fortran-lang-stdlib-0ede301/0000775000175000017500000000000015135654166016166 5ustar alastairalastairfortran-lang-stdlib-0ede301/API-doc-FORD-file.md0000664000175000017500000001063715135654166021340 0ustar alastairalastair--- project: Fortran-lang/stdlib summary: A community driven standard library for (modern) Fortran src_dir: src include: src include exclude_dir: src/tests output_dir: API-doc page_dir: doc media_dir: doc/media exclude: src/stdlib_linalg_lapack.fypp src/stdlib_linalg_lapack_aux.fypp src/stdlib_linalg_lapack_c.fypp src/stdlib_linalg_lapack_d.fypp src/stdlib_linalg_lapack_q.fypp src/stdlib_linalg_lapack_s.fypp src/stdlib_linalg_lapack_w.fypp src/stdlib_linalg_lapack_z.fypp fpp_extensions: fypp preprocess: true macro: MAXRANK=3 PROJECT_VERSION_MAJOR=0 PROJECT_VERSION_MINOR=0 PROJECT_VERSION_PATCH=0 preprocessor: fypp display: public protected source: true proc_internals: true md_extensions: markdown.extensions.toc graph: true graph_maxnodes: 250 graph_maxdepth: 5 coloured_edges: true sort: permission-alpha extra_mods: iso_fortran_env:https://gcc.gnu.org/onlinedocs/gfortran/ISO_005fFORTRAN_005fENV.html iso_c_binding:https://gcc.gnu.org/onlinedocs/gfortran/ISO_005fC_005fBINDING.html#ISO_005fC_005fBINDING print_creation_date: true creation_date: %Y-%m-%d %H:%M %z project_github: https://github.com/fortran-lang/stdlib project_download: https://github.com/fortran-lang/stdlib/archive/HEAD.zip project_website: https://stdlib.fortran-lang.org favicon: doc/media/favicon.ico license: by-sa author: fortran-lang/stdlib contributors author_pic: https://fortran-lang.org/en/_static/fortran-logo-256x256.png email: fortran-lang@groups.io github: https://github.com/fortran-lang twitter: https://twitter.com/fortranlang website: https://fortran-lang.org dbg: true --- [TOC] @warning This API documentation for the Fortran-lang/stdlib is a work in progress @note Use the navigation bar at the top of the screen to browse modules, procedures, source files, etc. The listings near the bottom of the page are incomplete. Fortran stdlib API Documentation ================================ This is the main API documentation landing page generated by [FORD]. The documentation for comment markup in source code, running [FORD] and the [FORD project file] are all maintained on the [FORD wiki]. [FORD]: https://github.com/Fortran-FOSS-Programmers/ford#readme [FORD wiki]: https://github.com/Fortran-FOSS-Programmers/ford/wiki [FORD project file]: https://github.com/fortran-lang/stdlib/blob/HEAD/API-doc-FORD-file.md Goals and Motivation ==================== The Fortran Standard, as published by the ISO (https://wg5-fortran.org/), does not have a Standard Library. The goal of this project is to provide a community driven and agreed upon *de facto* "standard" library for Fortran, called a Fortran Standard Library (`stdlib`). We have a rigorous process how `stdlib` is developed as documented in our [Workflow](page/contributing/Workflow.html). `stdlib` is both a specification and a reference implementation. We are cooperating with the Fortran Standards Committee (e.g., the effort [started](https://github.com/j3-fortran/fortran_proposals/issues/104) at the J3 committee repository) and the plan is to continue working with the Committee in the future (such as in the step 5. in the [Workflow](page/contributing/Workflow.html) document), so that if the Committee wants to standardize some feature already available in `stdlib`, it would base it on `stdlib`'s implementation. Scope ===== The goal of the Fortran Standard Library is to achieve the following general scope: * Utilities (containers, strings, files, OS/environment integration, unit testing & assertions, logging, ...) * Algorithms (searching and sorting, merging, ...) * Mathematics (linear algebra, sparse matrices, special functions, fast Fourier transform, random numbers, statistics, ordinary differential equations, numerical integration, optimization, ...) Code of Conduct =============== In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. Please read first [this Code of Conduct](./page/contributing/CodeOfConduct.html) License ======= The `stdlib` source code and related files and documentation are distributed under the [MIT license](page/License.html). fortran-lang-stdlib-0ede301/fpm.toml0000664000175000017500000000057315135654166017652 0ustar alastairalastairname = "stdlib" version = "VERSION" license = "MIT" author = "stdlib contributors" maintainer = "@fortran-lang/stdlib" copyright = "2019-2024 stdlib contributors" [install] library = true [dev-dependencies] test-drive.git = "https://github.com/fortran-lang/test-drive" test-drive.tag = "v0.4.0" [preprocess] [preprocess.cpp] suffixes = [".F90", ".f90"] macros = ["MAXRANK=7"] fortran-lang-stdlib-0ede301/STYLE_GUIDE.md0000664000175000017500000001252415135654166020331 0ustar alastairalastair# Fortran stdlib Style Guide Adopting a consistent style can improve code legibility through the choice of good naming conventions. In addition, style checks will be run during CI to flag any severe non-conformance. This allows code review discussions to focus on semantics and substance rather than pedantry. Consistent whitespace usage, and not polluting line endings with trailing white space makes `git diff`s considerably more legible. This style guide is a living document and proposed changes may be adopted after discussing them and coming to a consensus. ## Use (modern) standard Fortran * Do not use obsolescent or deleted language features E.g., `common`, `pause`, `entry`, arithmetic `if` and computed `goto` * Do not use vendor extensions in the form of non-standard syntax and vendor supplied intrinsic procedures E.g., `real*8` or `etime()` ## File naming conventions * Source files should contain at most one `program`, `module`, or `submodule` * The filename should match the program or module name and have the file extension `.f90` or `.F90` if preprocessing is required * All included files must use the `.inc` extension. These files should be located in the `include/` directory. * If the interface and implementation is split using submodules the implementation submodule file should have the same name as the interface (parent) module but end in `_implementation` E.g., `string_class.f90` and `string_class_implementation.f90` * Tests should be added in the `test` subdirectory and have the same name as the module they are testing with the `test_` prefix added E.g., `string_class.f90` and `test/test_string_class.f90` ## Indentation & whitespace By setting and following a convention for indentation and whitespace, code reviews and git-diffs can focus on the semantics of the proposed changes rather than style and formatting. * The body of every Fortran construct should be indented by __four (4) spaces__ * Line length *should be limited to 80 characters* and __must not exceed 132__ * Please do not use Tab characters for indentation * Please remove trailing white space before committing code ## Variable and procedure naming * Variable and procedure names, as well as Fortran keywords, should be written in lowercase * Variable and procedure names should be made up of one or more full words separated by an underscore, for example `has_failed` is preferred over `hasfailed` * Where conventional and appropriate shortening of a word is used then the underscore may be omitted, for example `linspace` is preferred over `lin_space` ## Attributes * Always specify `intent` for dummy arguments. * Don't use `dimension` attribute to declare arrays because it is more verbose. Use this: ``` real, allocatable :: a(:), b(:,:) ``` instead of: ``` real, dimension(:), allocatable :: a ``` ``` real, dimension(:,:), allocatable :: b ``` When defining many arrays of the same dimension, `dimension` can be used as an exception if it makes the code less verbose. * If the `optional` attribute is used to declare a dummy argument, it should follow the `intent` attribute. * For module procedures, it is recommended to declare attributes before the module keyword for better retro compatibility (Projects using CMake versions lower than CMake 3.25.0 are concerned see [Spurious modules](https://gitlab.kitware.com/cmake/cmake/-/issues/18427#note_983426)). Prefer the following pattern: ``` module ``` instead of: ``` module ``` ## End block closing statements Fortran allows certain block constructs or scopes to include the name of the program unit in the end statement. The convention adopted herein is to include procedure names, `module` names and `program` names in the `end` statement, unless the closing statement can reasonably be expected to be on the same screen or page, within about 25 lines. ## Document public API code with FORD Documentation strings should be provided for all public and protected entities and their arguments or parameters. This is currently accomplished using the [FORD tool](https://github.com/Fortran-FOSS-Programmers/ford). For help writing FORD style documentation please see the [FORD wiki](https://github.com/Fortran-FOSS-Programmers/ford/wiki). The following two sections are most relevant for contributing new code: * [Writing Documentation](https://github.com/Fortran-FOSS-Programmers/ford/wiki/Writing-Documentation) * [Documentation Meta Data](https://github.com/Fortran-FOSS-Programmers/ford/wiki/Documentation-Meta-Data) * [Limitations](https://github.com/Fortran-FOSS-Programmers/ford/wiki/Limitations) To write the "spec" (specification) for a new proposal, please place it in the [FORD "pages"](https://github.com/Fortran-FOSS-Programmers/ford/wiki/Writing-Pages) directory at [`doc/specs/`](https://github.com/fortran-lang/stdlib/tree/HEAD/doc/specs). To get help please see the ["Writing Pages"](https://github.com/Fortran-FOSS-Programmers/ford/wiki/Writing-Pages) and ["Writing Documentation"](https://github.com/Fortran-FOSS-Programmers/ford/wiki/Writing-Documentation) pages on the [FORD wiki](https://github.com/Fortran-FOSS-Programmers/ford/wiki). fortran-lang-stdlib-0ede301/WORKFLOW.md0000664000175000017500000002005115135654166017760 0ustar alastairalastair# Workflow for the Fortran stdlib contributors This document describes our current workflow. We welcome everyone and anyone to participate and propose additions to stdlib. It is okay if you do not have experience for specification or implementation, but have an idea for stdlib. If the idea is popular among the community, more experienced contributors will help it through all 5 steps. 1. **Idea**: You have an idea or a proposal. Open an [issue](https://github.com/fortran-lang/stdlib/issues) to discuss it. This is on the level of "is there interest in having image reader/writer functions in stdlib?" The goal of this step is to find out if the community is interested in having this functionality as part of stdlib. 2. **API**: When there seems to be significant interest in the proposal (vast majority of participants think it is a good idea), move on to discuss the specific API. It's OK to propose the API off the bat if you already have an idea for it. This step is exploratory and its goal is to find out what the API should *look* and *feel* like. 3. **Specification**: Discuss the API and iterate. When there is vast majority approval for the API, move on to implement it and submit a PR. Small PRs are always better than large. It is OK to implement only a few functions of a new module, and continue work on the others in a later PR. All new functionality goes into an "experimental" namespace (`version: experimental`). As part of the PR, when submitting a new public facing API, please provide the initial draft of the specification document as well as the initial reference implementation of this specification. The [specification is a document](https://stdlib.fortran-lang.org/page/specs/index.html) that describes the API and the functionality, so that anyone can use it to create an implementation from scratch without looking at `stdlib`. The `stdlib` library then provides the reference implementation. 4. **Implementation** in experimental: When opening a PR, request reviews from one or more people that are most relevant to it. These are likely to be people involved in prior steps of the workflow. Other contributors (not explicitly invited) are encouraged to provide reviews and suggestions as well. Iterate until all (or most) participants are on the same page. A merge is permitted if there are unit tests for a majority of the possible calling scenarios (with or without optional arguments, with arguments that trigger an error) and if there is vast majority approval of the PR. 5. **Release**: Moving from experimental to release. The experimental "namespace" contains new functionality together with its specification. In order to move from experimental to release, the specification document must be approved by the wide community and the standards committee (informally). If that happens, it has now been blessed for broad use and we can move the code into the main section of `stdlib`, and the particular specification document becomes part of the Fortran Standard Library. Note: the general term "vast majority" above means at least 80%, but ultimately it is left to our best judgement to ensure that the community agrees that each PR and proposal was approved by "vast majority". You are welcome to propose changes to this workflow by opening an [issue](https://github.com/fortran-lang/stdlib/issues). ## Build systems This project supports two build systems, [fpm](https://github.com/fortran-lang/fpm) and CMake. ### CMake build files The build files for CMake allow both in-tree, *i.e.* build artifacts share the same tree as the source files, and out-of-tree builds, *i.e.* build artifacts exist in a separate directory tree. Both build types are explicitly supported and tested, the latter strategy is recommended for local development. Sources for the main library target are added in ``src/CMakeLists.txt`` relative to the library target, *i.e.* no absolute paths are required. To add tests, the macro ``ADDTEST`` should be used instead of the CMake function ``add_test``, the macro hides creation of the executable target, linking against the main library target and registering the test. The tests themselves are defined as standalone executables in the subdirectories in ``test``, a new subdirectory with tests has to be registered in ``test/CMakeLists.txt``. The source tree should be considered read-only. References to ``PROJECT_SOURCE_DIR`` and ``CMAKE_CURRENT_SOURCE_DIR`` should only be used for accessing source files, never to write build outputs, use ``PROJECT_BINARY_DIR`` and ``CMAKE_CURRENT_BINARY_DIR`` to write build artifacts instead. To fully support in-tree builds, build artifacts must never have the same name as source files to avoid accidentally overwriting them, *e.g.* when preprocessing or configuring a file. The ``CMAKE_INSTALL_PREFIX`` should only be written to on install, never in the build process. To install generated files, create a build output in the build tree and install it with the ``install`` function. This project follows the GNU install conventions, this means that the variables ``CMAKE_INSTALL_BINDIR``, ``CMAKE_INSTALL_LIBDIR``, and ``CMAKE_INSTALL_INCLUDEDIR`` must be used instead of ``bin``, ``lib``, and ``include``, respectively. Library targets should be exported on install to allow correct inclusion of the project in other CMake projects. Prefer dashes as in ``project-config`` or ``project-targets`` over camel-case as in ``projectConfig`` or ``projectTarget`` for file names as the former allows easier construction from the ``PROJECT_NAME`` variable by concatenation. The project is usable as CMake subproject. Explicit references to ``CMAKE_SOURCE_DIR`` and ``CMAKE_BINARY_DIR`` must be avoided to not break subproject builds. An example project is available [here](https://github.com/fortran-lang/stdlib-cmake-example) to test the CMake subproject integration. ## GitHub collaboration Contributing can be daunting, we know! Even more for a big project with many contributors, and if you are not expert on the whole github workflow then even more, we have been there at some point. In order to help lowering the barrier for collaborating on ongoing efforts (e.g. an open PR), we have crafted a simple script that might come in handy. To explain the process we'll use Alice (the person you want to help) and Bob (you): ```text ┌────────────────────────────┐ │ fortran-lang/stdlib │ └────────────▲───────────────┘ │ │ [Pull Request] │ ┌───────┴────────┐ │ alice/stdlib │ ←─────┐ └──────▲─────────┘ │ │ │ [PR Branch] ←───┘ ┌──────┴──────┐ feature-branch │ bob/stdlib │ (hosted here) │ (fork) │ └─────────────┘ ▲ │ [Push access to Alice's repo] ``` After having forked from `fortran-lang/stdlib` and cloned your `stdlib` fork on your local machine; on an unix compatible terminal with access to the `git` CLI, being at the root folder: ```sh ./.github/collab.sh ``` You will be asked to enter the username and branch of the other person: ```bash Enter the GitHub username of the fork owner (e.g., alice): alice Enter the PR branch name (e.g., feature-branch): feature-branch ``` This will fetch Alice's repository and switch your view to Alice's feature-branch. Now you can review, build, run, play around, propose your nice improvements. Once you finish helping out, you can always `git checkout ` and/or delet Alice's branch from your local view `git branch -d feature-branch`. Remember, announce your willingness to help 😉 fortran-lang-stdlib-0ede301/README.md0000664000175000017500000005136615135654166017460 0ustar alastairalastair# Fortran Standard Library [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.18346789.svg)](https://doi.org/10.5281/zenodo.18346789) [![Actions Status](https://github.com/fortran-lang/stdlib/workflows/CI/badge.svg)](https://github.com/fortran-lang/stdlib/actions) [![Actions Status](https://github.com/fortran-lang/stdlib/workflows/CI_windows/badge.svg)](https://github.com/fortran-lang/stdlib/actions) * [Goals and Motivation](#goals-and-motivation) * [Scope](#scope) * [Getting started](#getting-started) - [Get the code](#get-the-code) - [Requirements](#requirements) - [Supported compilers](#supported-compilers) - [Build with CMake](#build-with-cmake) - [Build with fortran-lang/fpm](#build-with-fortran-langfpm) * [Using stdlib in your project](#using-stdlib-in-your-project) * [Documentation](#documentation) * [Contributing](#contributing) * [Links](#links) ## Goals and Motivation The Fortran Standard, as published by the ISO (https://wg5-fortran.org/), does not have a Standard Library. The goal of this project is to provide a community driven and agreed upon *de facto* "standard" library for Fortran, called a Fortran Standard Library (`stdlib`). We have a rigorous process how `stdlib` is developed as documented in our [Workflow](WORKFLOW.md). `stdlib` is both a specification and a reference implementation. We are cooperating with the Fortran Standards Committee (e.g., the effort [started](https://github.com/j3-fortran/fortran_proposals/issues/104) at the J3 committee repository) and the plan is to continue working with the Committee in the future (such as in the step 5. in the [Workflow](WORKFLOW.md) document), so that if the Committee wants to standardize some feature already available in `stdlib`, it would base it on `stdlib`'s implementation. ## Scope The goal of the Fortran Standard Library is to achieve the following general scope: * Utilities (containers, strings, files, OS/environment integration, unit testing & assertions, logging, ...) * Algorithms (searching and sorting, merging, ...) * Mathematics (linear algebra, sparse matrices, special functions, fast Fourier transform, random numbers, statistics, ordinary differential equations, numerical integration, optimization, ...) ## Getting started ### Get the code ```sh git clone https://github.com/fortran-lang/stdlib cd stdlib ``` ### Requirements To build the Fortran standard library you need - a Fortran 2008 compliant compiler, or better, a Fortran 2018 compliant compiler (GCC Fortran and Intel Fortran compilers are known to work for stdlib) - CMake version 3.14 or newer (alternatively Make can be used) - a build backend for CMake, like Make or Ninja (the latter is recommended on Windows) - the [fypp](https://github.com/aradi/fypp) preprocessor (used as meta-programming tool) If your system package manager does not provide the required build tools, all build dependencies can be installed with the Python command line installer ``pip``: ```sh pip install --user fypp cmake ninja ``` Alternatively, you can install the build tools from the conda-forge channel with the conda package manager: ```sh conda config --add channels conda-forge conda create -n stdlib-tools fypp cmake ninja conda activate stdlib-tools ``` You can install conda using the [miniforge installer](https://github.com/conda-forge/miniforge/releases). Also, you can install a Fortran compiler from conda-forge by installing the ``fortran-compiler`` package, which installs GFortran. ### Supported Compilers The following combinations are tested on the default branch of stdlib: Name | Version | Platform | Architecture --- | --- | --- | --- GCC Fortran | 10, 11, 12, 13, 14 | Ubuntu 24.04.3 LTS | x86_64 GCC Fortran | 11, 12, 13, 14, 15 | macOS 14.8.2 (23J126) | Arm64 GCC Fortran (MSYS) | 13 | Windows Server 2022 (10.0.20348 Build 1547) | x86_64 GCC Fortran (MinGW) | 13 | Windows Server 2022 (10.0.20348 Build 1547) | x86_64 Intel oneAPI LLVM | 2024.1 | Ubuntu 24.04.3 LTS | x86_64 Intel oneAPI classic | 2021.10 | Ubuntu 22.04.5 LTS | x86_64 The following combinations are known to work, but they are not tested in the CI: Name | Version | Platform | Architecture --- | --- | --- | --- GCC Fortran (MinGW) | 9.3.0, 10.2.0, 11.2.0 | Windows 10 | x86_64 We try to test as many available compilers and platforms as possible. A list of tested compilers which are currently not working and the respective issue are listed below. Name | Version | Platform | Architecture | Status --- | --- | --- | --- | --- GCC Fortran | <9 | any | any | [#296](https://github.com/fortran-lang/stdlib/issues/296), [#430](https://github.com/fortran-lang/stdlib/pull/430) NVIDIA HPC SDK | 20.7, 20.9, 20.11 | Manjaro Linux 20 | x86_64 | [#107](https://github.com/fortran-lang/stdlib/issues/107) NAG | 7.0 | RHEL | x86_64 | [#108](https://github.com/fortran-lang/stdlib/issues/108) Intel Parallel Studio XE | 16, 17, 18 | OpenSUSE | x86_64 | failed to compile Please share your experience with successful and failing builds for compiler/platform/architecture combinations not covered above. ### Build with CMake Configure the build with ```sh cmake -B build ``` You can pass additional options to CMake to customize the build. Important options are - `-G Ninja` to use the Ninja backend instead of the default Make backend. Other build backends are available with a similar syntax. - `-DCMAKE_INSTALL_PREFIX` is used to provide the install location for the library. If not provided the defaults will depend on your operating system, [see here](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html). - `-DCMAKE_MAXIMUM_RANK` the maximum array rank procedures should be generated for. The default value is chosen as 4. The maximum is 15 for Fortran 2003 compliant compilers, otherwise 7 for compilers not supporting Fortran 2003 completely yet. The minimum required rank to compile this project is 4. Compiling with maximum rank 15 can be resource intensive and requires at least 16 GB of memory to allow parallel compilation or 4 GB memory for sequential compilation. - `-DBUILD_SHARED_LIBS` set to `on` in case you want link your application dynamically against the standard library (default: `off`). - `-DBUILD_TESTING` set to `off` in case you want to disable the stdlib tests (default: `on`). - `-DCMAKE_VERBOSE_MAKEFILE` is by default set to `Off`, but if set to `On` will show commands used to compile the code. - `-DCMAKE_BUILD_TYPE` is by default set to `RelWithDebInfo`, which uses compiler flags suitable for code development (but with only `-O2` optimization). Beware the compiler flags set this way will override any compiler flags specified via `FFLAGS`. To prevent this, use `-DCMAKE_BUILD_TYPE=NoConfig` in conjunction with `FFLAGS`. - `-DFIND_BLAS` set to `off` in case you want to disable finding the external BLAS/LAPACK dependency (default: `on`). For example, to configure a build using the Ninja backend while specifying compiler optimization via `FFLAGS`, generating procedures up to rank 7, installing to your home directory, using the `NoConfig` compiler flags, and printing the compiler commands, use ```sh export FFLAGS="-O3" cmake -B build -G Ninja -DCMAKE_MAXIMUM_RANK:String=7 -DCMAKE_INSTALL_PREFIX=$HOME/.local -DCMAKE_VERBOSE_MAKEFILE=On -DCMAKE_BUILD_TYPE=NoConfig ``` To build the standard library run ```sh cmake --build build ``` To test your build, run the test suite and all example programs after the build has finished with ```sh cmake --build build --target test ``` To test only the test suite, run ```sh ctest --test-dir build/test ``` Please report failing tests on our [issue tracker](https://github.com/fortran-lang/stdlib/issues/new/choose) including details of the compiler used, the operating system and platform architecture. To install the project to the declared prefix run ```sh cmake --install build ``` Now you have a working version of stdlib you can use for your project. If at some point you wish to recompile `stdlib` with different options, you might want to delete the `build` folder. This will ensure that cached variables from earlier builds do not affect the new build. ### Build with [fortran-lang/fpm](https://github.com/fortran-lang/fpm) Fortran Package Manager (fpm) is a package manager and build system for Fortran. You can build `stdlib` using provided `fpm.toml`: **Option 1**: From root folder As `fpm` does not currently support `fypp` natively, `stdlib` now proposes a python script to preprocess and build it. This script enables modification of the different `fypp` macros available in `stdlib`. The preprocessed files will be dumped at `/temp/*.f90` or `*.F90`. Make sure to install the dependencies from the `requirement.txt` ```sh pip install --upgrade -r config/requirements.txt ``` To build, you can use the following command line: ```sh python config/fypp_deployment.py fpm build --profile release ``` or the short-cut ```sh python config/fypp_deployment.py --build ``` To modify the `maxrank` macro for instance: ```sh python config/fypp_deployment.py --maxrank 7 --build ``` To see all the options: ```sh python config/fypp_deployment.py --help ``` **Note**: If you use a compiler different than GNU compilers, the script will try to catch it from the environment variables `FPM_FC`, `FPM_CC`, `FPM_CXX`. **Option 2**: From the `stdlib-fpm` branch which has already been preprocessed with default macros: ```sh git checkout stdlib-fpm fpm build --profile release ``` #### Installing with fpm Either option you chose for building the `stdlib`, you can install it with: ```sh fpm install --profile release ``` The command above will install the following files: - `libstdlib.a` into `~/.local/lib/` (Unix) or `C:\Users\\AppData\Roaming\local\lib\` (Windows) - all the `.[s]mod` files produced by the compiler into `~/.local/include/` (Unix) or `C:\Users\\AppData\Roaming\local\include\` (Windows) You can change the installation path by setting the prefix option to `fpm`: ```sh fpm install --profile release --prefix /my/custom/installation/path/ ``` You can use the `stdlib` by adding the `-lstdlib` flag to your compiler. If your prefix is a non standard path, add also: - `-L/my/custom/installation/path/lib` - `-I/my/custom/installation/path/include` #### Running the examples You can run the examples with `fpm` as: ```sh fpm run --example prog ``` with `prog` being the name of the example program (e.g., `example_sort`). ### Preprocessing macros and flags `stdlib` uses two preprocessing steps: - *fypp* for meta-programming (templating and feature selection) - *C* preprocessing (activated through compiler flags like `-cpp`(GNU) or `-fpp`(Intel) or use of uppercase file suffix .F90) for conditional compilation *fypp* preprocessing macros and flags are supported through `CMake` or the `python` script `config/fypp_deployment.py`. *C* preprocessing macros and flags are supported through `CMake` and `fpm`. The table below lists all *fypp* preprocessing macros and flags currently used by `stdlib`: | Macro/flag Name | Comments | | --- | --- | | `MAXRANK` | Maximum array rank generated by templates. Set via CMake `-DCMAKE_MAXIMUM_RANK=` (passed to fypp as `-DMAXRANK=`), or via fypp deployment script `--maxrank `. | | `VERSION90` | Defines the default maximum rank generated when `MAXRANK` is not defined. If defined, the maximum rank generated is 7; otherwise it is 15. Can be passed to fypp as `-DVERSION90` (CMake sets this automatically in some configurations). | | `WITH_CBOOL` | Enables `c_bool` logical support if available. CMake auto-detects this and passes it to fypp; can be overridden at configure time with `-DWITH_CBOOL=ON/OFF`. | | `WITH_QP` | Enables quadruple precision code generation (`real(qp)`, `complex(qp)`). CMake auto-detects this and passes it to fypp; can be overridden at configure time with `-DWITH_QP=ON/OFF`; fypp deployment script: `--with_qp`. | | `WITH_XDP` | Enables extended double precision code generation (`real(xdp)`, `complex(xdp)`). CMake auto-detects this and passes it to fypp; can be overridden at configure time with `-DWITH_XDP=ON/OFF`; fypp deployment script: `--with_xdp`. | | `WITH_ILP64` | Enables generation of 64-bit integer (ILP64) size interfaces for BLAS and LAPACK (in addition to the default 32-bit interface). Set via CMake `-DWITH_ILP64=True` or via fypp deployment script `--with_ilp64`. | | `PROJECT_VERSION_MAJOR` | Part of the version string passed into fypp templates. Set automatically by CMake from the file `VERSION`. Can be overridden by passing `-DPROJECT_VERSION_MAJOR=`, or via fypp deployment script `--vmajor `. | | `PROJECT_VERSION_MINOR` | See `PROJECT_VERSION_MAJOR`. | | `PROJECT_VERSION_PATCH` | See `PROJECT_VERSION_MAJOR`. | The table below lists all *C preprocessing* macros and flags currently used by `stdlib`: | Macro/flag Name | Comments | | --- | --- | | `STDLIB_ANSI` | Enables compilation of the `stdlib_ansi` module when set to 1 (default). Set via CMake with `-DSTDLIB_ANSI=On/Off`. | | `STDLIB_BITSETS` | Enables compilation of the `stdlib_bitsets` module when set to 1 (default). Set via CMake with `-DSTDLIB_BITSETS=On/Off`. | | `STDLIB_EXTERNAL_BLAS` | Links against an external BLAS (32-bit integer interface). Set automatically by CMake when external BLAS/LAPACK are found, or manually via `add_compile_definitions(STDLIB_EXTERNAL_BLAS)`. In fpm: `preprocess.cpp.macros=["STDLIB_EXTERNAL_BLAS"]`. | | `STDLIB_EXTERNAL_LAPACK` | Links against an external LAPACK (32-bit integer interface). Usually paired with `STDLIB_EXTERNAL_BLAS`. | | `STDLIB_EXTERNAL_BLAS_I64` | Links against an external BLAS with ILP64 (64-bit integer) interfaces. Usually paired with `STDLIB_EXTERNAL_LAPACK_I64`. | | `STDLIB_EXTERNAL_LAPACK_I64` | Links against an external LAPACK with ILP64 (64-bit integer) interfaces. | | `STDLIB_HASHMAPS` | Enables compilation of the `stdlib_hashmaps` module when set to 1 (default). Set via CMake with `-DSTDLIB_HASHMAPS=On/Off`. | | `STDLIB_IO` | Enables compilation of the `stdlib_io` module when set to 1 (default). Set via CMake with `-DSTDLIB_IO=On/Off`. | | `STDLIB_LINALG_ITERATIVE` | Enables compilation of the `stdlib_linalg_iterative_solvers` module when set to 1 (default). Set via CMake with `-DSTDLIB_LINALG_ITERATIVE=On/Off`. | | `STDLIB_LOGGER` | Enables compilation of the `stdlib_logger` module when set to 1 (default). Set via CMake with `-DSTDLIB_LOGGER=On/Off`. | | `STDLIB_QUADRATURE` | Enables compilation of the `stdlib_quadrature` module when set to 1 (default). Set via CMake with `-DSTDLIB_QUADRATURE=On/Off`. | | `STDLIB_SPECIALMATRICES` | Enables compilation of the `stdlib_specialmatrices` module when set to 1 (default). Set via CMake with `-DSTDLIB_SPECIALMATRICES=On/Off`. | | `STDLIB_STATS` | Enables compilation of the `stdlib_stats` module when set to 1 (default). Set via CMake with `-DSTDLIB_STATS=On/Off`. | | `STDLIB_STRINGLIST` | Enables compilation of the `stdlib_stringlist` module when set to 1 (default). Set via CMake with `-DSTDLIB_STRINGLIST=On/Off`. | | `STDLIB_SYSTEM` | Enables compilation of the `stdlib_system` module when set to 1 (default). Set via CMake with `-DSTDLIB_SYSTEM=On/Off`. | ## Using stdlib in your project ### Using stdlib with CMake The stdlib project exports CMake package files and pkg-config files to make stdlib usable for other projects. The package files are located in the library directory in the installation prefix. For CMake builds of stdlib you can find a local installation with ```cmake find_package(fortran_stdlib REQUIRED) ... target_link_libraries( ${PROJECT_NAME} PRIVATE fortran_stdlib::fortran_stdlib ) ``` To make the installed stdlib project discoverable add the stdlib directory to the ``CMAKE_PREFIX_PATH``. The usual install location of the package files is ``$PREFIX/lib/cmake/fortran_stdlib``. ### Using stdlib with fpm To use `stdlib` within your `fpm` project, add the following lines to your `fpm.toml` file: ```toml [dependencies] stdlib = { git="https://github.com/fortran-lang/stdlib", branch="stdlib-fpm" } ``` > **Warning** > > Fpm 0.9.0 and later implements stdlib as a *metapackage*. > To include the standard library metapackage, change the dependency to: > `stdlib = "*"`. > > [see also](https://fpm.fortran-lang.org/spec/metapackages.html) ### Using stdlib with a regular Makefile After the library has been built, it can be included in a regular Makefile. The recommended way to do this is using the [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) tool, for which an example is shown below. ```make # Necessary if the installation directory is not in PKG_CONFIG_PATH install_dir := path/to/install_dir export PKG_CONFIG_PATH := $(install_dir)/lib/pkgconfig:$(PKG_CONFIG_PATH) # On some OS the pkgconfig file could be installed in lib64 instead of lib # export PKG_CONFIG_PATH := $(install_dir)/lib64/pkgconfig:$(PKG_CONFIG_PATH) STDLIB_CFLAGS := `pkg-config --cflags fortran_stdlib` STDLIB_LIBS := `pkg-config --libs fortran_stdlib` # Example definition of Fortran compiler and flags FC := gfortran FFLAGS := -O2 -Wall -g # Definition of targets etc. ... # Example rule to compile object files from .f90 files %.o: %.f90 $(FC) -c -o $@ $< $(FFLAGS) $(STDLIB_CFLAGS) # Example rule to link an executable from object files %: %.o $(FC) -o $@ $^ $(FFLAGS) $(STDLIB_LIBS) ``` The same can also be achieved without pkg-config. If the library has been installed in a directory inside the compiler's search path, only a flag `-lfortran_stdlib` is required. If the installation directory is not in the compiler's search path, one can add for example ```make install_dir := path/to/install_dir libdir := $(install_dir)/lib moduledir := $(install_dir)/include/fortran_stdlib/ ``` The linker should then look for libraries in `libdir` (using e.g.`-L$(libdir)`) and the compiler should look for module files in `moduledir` (using e.g. `-I$(moduledir)`). Alternatively, the library can also be included from a build directory without installation with ```make build_dir := path/to/build_dir libdir := $(build_dir)/src moduledir := $(build_dir)/src/mod_files ``` ## Documentation Documentation is a work in progress (see issue [#4](https://github.com/fortran-lang/stdlib/issues/4)) but already available at [stdlib.fortran-lang.org](https://stdlib.fortran-lang.org). This includes API documentation automatically generated from static analysis and markup comments in the source files using the [FORD](https://github.com/Fortran-FOSS-programmers/ford/wiki) tool, as well as a specification document or ["spec"](https://stdlib.fortran-lang.org/page/specs/index.html) for each proposed feature. Some discussions and prototypes of proposed APIs along with a list of popular open source Fortran projects are available on the [wiki](https://github.com/fortran-lang/stdlib/wiki). ## BLAS and LAPACK `stdlib` ships full versions of BLAS and LAPACK, for all `real` and `complex` kinds, through generalized interface modules `stdlib_linalg_blas` and `stdlib_linalg_lapack`. The 32- and 64-bit implementations may be replaced by external optimized libraries if available, which may allow for faster code. When linking against external BLAS/LAPACK libraries, the user should define macros `STDLIB_EXTERNAL_BLAS` and `STDLIB_EXTERNAL_LAPACK`, to ensure that the external library version is used instead of the internal implementation. - In case of a CMake build, the necessary configuration can be added by ensuring both macros are defined: ``` add_compile_definitions(STDLIB_EXTERNAL_BLAS STDLIB_EXTERNAL_LAPACK) ``` - In case of an `fpm` build, the stdlib dependency should be set as follows: ```toml [dependencies] stdlib = { git="https://github.com/fortran-lang/stdlib", branch="stdlib-fpm", preprocess.cpp.macros=["STDLIB_EXTERNAL_BLAS", "STDLIB_EXTERNAL_LAPACK"] } ``` Support for 64-bit integer size interfaces of all BLAS and LAPACK procedures may also be enabled by setting the CMake flag `-DWITH_ILP64=True`. The 64-bit integer version is always built in addition to the 32-bit integer version, that is always available. Additional macros `STDLIB_EXTERNAL_BLAS_I64` and `STDLIB_EXTERNAL_LAPACK_I64` may be defined to link against an external 64-bit integer library, such as Intel MKL. - In case of an `fpm` build, 64-bit integer linear algebra support is given via branch `stdlib-fpm-ilp64`: ```toml [dependencies] stdlib = { git="https://github.com/fortran-lang/stdlib", branch="stdlib-fpm-ilp64", preprocess.cpp.macros=["STDLIB_EXTERNAL_BLAS_I64", "STDLIB_EXTERNAL_LAPACK"] } ``` ## Contributing * [Guidelines](CONTRIBUTING.md) * [Issues](https://github.com/fortran-lang/stdlib/issues) * [Workflow](WORKFLOW.md) * [Style guide](STYLE_GUIDE.md) * [Code of conduct](CODE_OF_CONDUCT.md) * [License](LICENSE) ## Links * [Proposals for the Fortran Standard Committee](https://github.com/j3-fortran/fortran_proposals/) * [US Fortran Standards Committee](https://j3-fortran.org/) * [International Fortran Standard Committee](https://wg5-fortran.org/) fortran-lang-stdlib-0ede301/include/0000775000175000017500000000000015135654166017611 5ustar alastairalastairfortran-lang-stdlib-0ede301/include/macros.inc0000664000175000017500000000213115135654166021565 0ustar alastairalastair!Default: compile the ansi module #if !defined STDLIB_ANSI #define STDLIB_ANSI 1 #endif !Default: compile the bitsets module #if !defined STDLIB_BITSETS #define STDLIB_BITSETS 1 #endif !Default: compile the hashmaps module #if !defined STDLIB_HASHMAPS #define STDLIB_HASHMAPS 1 #endif !Default: compile the io module #if !defined STDLIB_IO #define STDLIB_IO 1 #endif !Default: compile the linalg_iterative module #if !defined STDLIB_LINALG_ITERATIVE #define STDLIB_LINALG_ITERATIVE 1 #endif !Default: compile the logger module #if !defined STDLIB_LOGGER #define STDLIB_LOGGER 1 #endif !Default: compile the quadrature module #if !defined STDLIB_QUADRATURE #define STDLIB_QUADRATURE 1 #endif !Default: compile the specialmatrices module #if !defined STDLIB_SPECIALMATRICES #define STDLIB_SPECIALMATRICES 1 #endif !Default: compile the stringlist module #if !defined STDLIB_STRINGLIST #define STDLIB_STRINGLIST 1 #endif !Default: compile the system module #if !defined STDLIB_SYSTEM #define STDLIB_SYSTEM 1 #endif !Default: compile the stats module #if !defined STDLIB_STATS #define STDLIB_STATS 1 #endif fortran-lang-stdlib-0ede301/include/common.fypp0000664000175000017500000003356115135654166022011 0ustar alastairalastair#:mute #! Project version number #:set PROJECT_VERSION = "{}.{}.{}".format(PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR, PROJECT_VERSION_PATCH) #! Support for C_BOOL logical #:if not defined("WITH_CBOOL") #:set WITH_CBOOL = False #:endif #! Support for quadruple precision floating point numbers #:if not defined("WITH_QP") #:set WITH_QP = False #:endif #! Support for extended double precision floating point numbers #:if not defined("WITH_XDP") #:set WITH_XDP = False #:endif #! Support for linear algebra with 64-bit integer sizes #:if not defined("WITH_ILP64") #:set WITH_ILP64 = False #:endif #! Real kinds to be considered during templating #:set REAL_KINDS = ["sp", "dp"] #:if WITH_XDP #:set REAL_KINDS = REAL_KINDS + ["xdp"] #:endif #:if WITH_QP #:set REAL_KINDS = REAL_KINDS + ["qp"] #:endif #! BLAS/LAPACK initials for each real kind #:set REAL_INIT = ["s", "d"] #:if WITH_XDP #:set REAL_INIT = REAL_INIT + ["x"] #:endif #:if WITH_QP #:set REAL_INIT = REAL_INIT + ["q"] #:endif #! Real types to be considered during templating #:set REAL_TYPES = ["real({})".format(k) for k in REAL_KINDS] #:set REAL_SUFFIX = REAL_KINDS #! Real CPPS to be considered during templating #:set REAL_CPPS = ["" for k in REAL_KINDS] #! Collected (kind, type) tuples for real types #:set REAL_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_INIT, REAL_CPPS)) #! Complex kinds to be considered during templating #:set CMPLX_KINDS = ["sp", "dp"] #:if WITH_XDP #:set CMPLX_KINDS = CMPLX_KINDS + ["xdp"] #:endif #:if WITH_QP #:set CMPLX_KINDS = CMPLX_KINDS + ["qp"] #:endif #! BLAS/LAPACK initials for each complex kind #:set CMPLX_INIT = ["c", "z"] #:if WITH_XDP #:set CMPLX_INIT = CMPLX_INIT + ["y"] #:endif #:if WITH_QP #:set CMPLX_INIT = CMPLX_INIT + ["w"] #:endif #! BLAS/LAPACK complex->real kind initial conversion #! Converts a BLAS/LAPACK complex kind initial to a real kind initial #! #! Args: #! ci (character): Complex kind initial in ["c","z","y","w"] #! #! Returns: #! Real kind initial in ["s","d","x","q"] or an empty string on invalid input #! #:def c2ri(cmplx) $:"s" if cmplx=="c" else "d" if cmplx=="z" else "x" if cmplx=="y" else "q" if cmplx=="w" else "ERROR" #:enddef #! BLAS/LAPACK/Linear Algebra Integer Kinds #:set LINALG_INT_KINDS = ["ilp"] #:set LINALG_INT_SUFFIX = [""] #:if WITH_ILP64 #:set LINALG_INT_KINDS = LINALG_INT_KINDS+["ilp64"] #:set LINALG_INT_SUFFIX = LINALG_INT_SUFFIX+["_I64"] #:endif #:set LINALG_INT_TYPES = ["integer({})".format(k) for k in LINALG_INT_KINDS] #:set LINALG_INT_KINDS_TYPES = list(zip(LINALG_INT_KINDS, LINALG_INT_TYPES, LINALG_INT_SUFFIX)) #! Complex types to be considered during templating #:set CMPLX_TYPES = ["complex({})".format(k) for k in CMPLX_KINDS] #:set CMPLX_SUFFIX = ["c{}".format(k) for k in CMPLX_KINDS] #! Collected (kind, type, initial) tuples for complex types #:set CMPLX_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_INIT)) #! Integer kinds to be considered during templating #:set INT_KINDS = ["int8", "int16", "int32", "int64"] #! Integer types to be considered during templating #:set INT_TYPES = ["integer({})".format(k) for k in INT_KINDS] #! Integer abbreviations to be considered during templating #:set INT_INIT = ["" for k in INT_KINDS] #! Integer CPPs to be considered during templating #:set INT_CPPS = ["" for k in INT_KINDS] #! Collected (kind, type) tuples for integer types #:set INT_KINDS_TYPES = list(zip(INT_KINDS, INT_TYPES, INT_INIT, INT_CPPS)) #! Logical kinds to be considered during templating #:set LOG_KINDS = ["lk"] #:if WITH_CBOOL #:set LOG_KINDS = LOG_KINDS + ["c_bool"] #:endif #! Logical types to be considered during templating #:set LOG_TYPES = ["logical({})".format(k) for k in LOG_KINDS] #! Collected (kind, type) tuples for logical types #:set LOG_KINDS_TYPES = list(zip(LOG_KINDS, LOG_TYPES)) #! Derived type string_type #:set STRING_KINDS = ["string_type"] #! String types to be considered during templating #:set STRING_TYPES = ["type({})".format(k) for k in STRING_KINDS] #! String abbreviations to be considered during templating #:set STRING_INIT = ["" for k in STRING_KINDS] #! String CPPs to be considered during templating #:set STRING_CPPS = ["" for k in STRING_KINDS] #! Collected (kind, type) tuples for string derived types #:set STRING_KINDS_TYPES = list(zip(STRING_KINDS, STRING_TYPES)) #! Derived type bitsets #:set BITSETS_KINDS = ["bitset_64", "bitset_large"] #! Bitset types to be considered during templating #:set BITSETS_TYPES = ["type({})".format(k) for k in BITSETS_KINDS] #! Bitset abbreviations directive to be considered during templating #:set BITSETS_INIT = ["" for k in BITSETS_KINDS] #! Bitset CPP directive to be considered during templating #:set BITSETS_CPPS = ["STDLIB_BITSETS" for k in BITSETS_KINDS] #! Collected (kind, type) tuples for bitset types #:set BITSETS_KINDS_TYPES = list(zip(BITSETS_KINDS, BITSETS_TYPES, BITSETS_INIT, BITSETS_CPPS)) #! Sparse types to be considered during templating #:set SPARSE_KINDS = ["COO", "CSR", "CSC", "ELL"] #! Whether Fortran 90 compatible code should be generated #:set VERSION90 = defined('VERSION90') #! Ranks to be generated when templates are created #:if not defined('MAXRANK') #:if VERSION90 #:set MAXRANK = 7 #:else #:set MAXRANK = 15 #:endif #:endif #! Generates an array rank suffix. #! #! Args: #! rank (int): Rank of the variable #! #! Returns: #! Array rank suffix string (e.g. (:,:) if rank = 2) #! #:def ranksuffix(rank) #{if rank > 0}#(${":" + ",:" * (rank - 1)}$)#{endif}# #:enddef #! Generates an empty array rank suffix. #! #! Args: #! rank (int): Rank of the variable #! #! Returns: #! Empty array rank suffix string (e.g. (0,0) if rank = 2) #! #:def emptyranksuffix(rank) #{if rank > 0}#(${"0" + ",0" * (rank - 1)}$)#{endif}# #:enddef #! Generates an array rank suffix with a fixed integer size for all dimensions. #! #! Args: #! rank (int): Rank of the variable #! size (int): Size along each dimension #! #! Returns: #! Array rank suffix string #! E.g., #! fixedranksuffix(3,4) #! -> (4,4,4) #! #:def fixedranksuffix(rank,size) #{if rank > 0}#(${str(size) + (","+str(size)) * (rank - 1)}$)#{endif}# #:enddef #! Joins stripped lines with given character string #! #! Args: #! txt (str): Text to process #! joinstr (str): String to use as connector #! prefix (str): String to add as prefix before the joined text #! suffix (str): String to add as suffix after the joined text #! #! Returns: #! Lines stripped and joined with the given string. #! #:def join_lines(txt, joinstr, prefix="", suffix="") ${prefix + joinstr.join([line.strip() for line in txt.split("\n")]) + suffix}$ #:enddef #! Brace enclosed, comma separated Fortran expressions for a reduced shape. #! #! Rank of the original variable will be reduced by one. The routine generates #! for each dimension a Fortan expression using merge(), which calculates the #! size of the array for that dimension. #! #! Args: #! varname (str): Name of the variable to be used as origin #! origrank (int): Rank of the original variable #! idim (int): Index of the reduced dimension #! #! Returns: #! Shape expression enclosed in braces, so that it can be used as suffix to #! define array shapes in declarations. #! #:def reduced_shape(varname, origrank, idim) #:assert origrank > 0 #:if origrank > 1 #:call join_lines(joinstr=", ", prefix="(", suffix=")") #:for i in range(1, origrank) merge(size(${varname}$, ${i}$), size(${varname}$, ${i + 1}$), mask=${i}$<${idim}$) #:endfor #:endcall #:endif #:enddef #! Generates a routine name from a generic name, rank, type and kind #! #! Args: #! gname (str): Generic name #! rank (integer): Rank if exist #! type (str): Type of the input #! kind (str): kind of inputs variable #! suffix (str): other identifier (could be used for output type/kind) #! #! Returns: #! A string with a new name #! #:def rname(gname, rank, type, kind, suffix='') $:"{0}_{1}_{2}{3}_{2}{3}".format(gname, rank, type[0], kind) if suffix == '' else "{0}_{1}_{2}{3}_{4}".format(gname, rank, type[0], kind, suffix) #:enddef #! Generates an array rank suffix for subarrays reducing the dimension #! #! Args: #! rank (int): Rank of the original variable #! selectors (array): Dimension and name of the variable(s) #! #! Returns: #! Array rank suffix string enclosed in braces #! #! E.g., #! select_subarray(5 , [(4, 'i'), (5, 'j')]) #! -> (:, :, :, i, j) #! #:def select_subarray(rank, selectors) #:assert rank > 0 #:set seldict = dict(selectors) #:call join_lines(joinstr=", ", prefix="(", suffix=")") #:for i in range(1, rank + 1) $:seldict.get(i, ":") #:endfor #:endcall #:enddef #! #! Generates an array rank suffix for subarrays along a dimension #! #! Args: #! varname (str): Name of the variable to be used as origin #! rank (int): Rank of the original variable #! dim (int): Dimension of the variable #! #! Returns: #! Array rank suffix string enclosed in braces #! #! E.g., #! select_subvector('j', 5, 2) #! -> (j1, :, j3, j4, j5) #! #! Used, e.g., in #! stdlib_stats_median.fypp #! #:def select_subvector(varname, rank, idim) #:assert rank > 0 #:call join_lines(joinstr=", ", prefix="(", suffix=")") #:for i in range(1, idim) ${varname}$${i}$ #:endfor : #:for i in range(idim + 1, rank + 1) ${varname}$${i}$ #:endfor #:endcall #:enddef #! #! Generates an array rank suffix for arrays #! #! Args: #! varname (str): Name of the variable to be used as origin #! rank (int): Rank of the original array variable #! idim (int): Dimension of the variable dropped #! #! Returns: #! Array rank suffix string enclosed in braces #! #! E.g., #! reduce_subvector('j', 5, 2) #! -> (j1, j3, j4, j5) #! #! Used, e.g., in #! stdlib_stats_median.fypp #! #:def reduce_subvector(varname, rank, idim) #:assert rank > 0 #:if rank > 1 #:call join_lines(joinstr=", ", prefix="(", suffix=")") #:for i in range(1, idim) ${varname}$${i}$ #:endfor #:for i in range(idim + 1, rank + 1) ${varname}$${i}$ #:endfor #:endcall #:endif #:enddef #! #! Generates a list of loop variables #! #! Args: #! varname(str): Name of the variable to be used as prefix #! n (int): Number of loop variables to be created #! offset (int): Optional index offset #! #! Returns: #! Variable definition string #! #! E.g., #! loop_variables('j', 5) #! -> "j1, j2, j3, j4, j5 #! #:def loop_variables(varname, n, offset=0) #:assert n > 0 #:call join_lines(joinstr=", ") #:for i in range(1, n + 1) ${varname}$${i+offset}$ #:endfor #:endcall #:enddef #! #! Generates a list of loop variables from an array #! #! Args: #! varname(str): Name of the array variable to be used as prefix #! n (int): Number of loop variables to be created #! offset (int): Optional index offset #! #! Returns: #! Variable definition string #! #! E.g., #! loop_array_variables('j', 5) #! -> "j(1), j(2), j(3), j(4), j(5) #! #! loop_array_variables('j', 5, 2) #! -> "j(3), j(4), j(5), j(6), j(7) #! #:def loop_array_variables(varname, n, offset=0) #:assert n > 0 #:call join_lines(joinstr=", ") #:for i in range(1, n + 1) ${varname}$(${i+offset}$) #:endfor #:endcall #:enddef #! Generates an array shape specifier from an N-D array size #! #! Args: #! name (str): Name of the original variable #! rank (int): Rank of the original variable #! offset(int): optional offset of the dimension loop (default = 0) #! #! Returns: #! Array rank suffix string enclosed in braces #! #! E.g., #! shape_from_array_size('mat', 5)}$ #! -> (size(mat,1),size(mat,2),size(mat,3),size(mat,4),size(mat,5)) #! shape_from_array_size('mat', 5, 2)}$ #! -> (size(mat,3),size(mat,4),size(mat,5),size(mat,6),size(mat,7)) #! #:def shape_from_array_size(name, rank, offset=0) #:assert rank > 0 #:call join_lines(joinstr=", ", prefix="(", suffix=")") #:for i in range(1, rank + 1) size(${name}$,${i+offset}$) #:endfor #:endcall #:enddef #! Generates an array shape specifier from an N-D array of sizes #! #! Args: #! name (str): Name of the original variable #! rank (int): Rank of the original variable #! offset(int): optional offset of the dimension loop (default = 0) #! #! Returns: #! Array rank suffix string enclosed in braces #! #! E.g., #! shape_from_array_data('mat', 5)}$ #! -> (1:mat(1),1:mat(2),1:mat(3),1:mat(4),1:mat(5)) #! shape_from_array_data('mat', 5, 2)}$ #! -> (1:mat(3),1:mat(4),1:mat(5),1:mat(6),1:mat(7)) #! #:def shape_from_array_data(name, rank, offset=0) #:assert rank > 0 #:call join_lines(joinstr=", ", prefix="(", suffix=")") #:for i in range(1, rank + 1) 1:${name}$(${i+offset}$) #:endfor #:endcall #:enddef #! #! Start a sequence of loop with indexed variables over an N-D array #! #! Args: #! varname (str): Name of the variable to be used as prefix #! matname (str): Name of the variable to be used as array #! n (int): Number of nested loops to be created (1=innermost; n=outermost) #! dim_offset (int): Optional dimension offset (1st loop is over dimension 1+dim_offset) #! intent (str): Optional indentation. Default: 8 spaces #! #! #:def loop_variables_start(varname, matname, n, dim_offset=0, indent=" "*8) #:assert n > 0 #:for i in range(1, n + 1) ${indent}$do ${varname}$${n+1+dim_offset-i}$ = lbound(${matname}$, ${n+1+dim_offset-i}$), ubound(${matname}$, ${n+1+dim_offset-i}$) #:endfor #:enddef #:def loop_variables_end(n, indent=" "*8) #:assert n > 0 #:call join_lines(joinstr="; ",prefix=indent) #:for i in range(1, n + 1) enddo #:endfor #:endcall #:enddef #! #! Encapsulate code into CPP pre-processing directives #ifdef and #endif #! #! Args: #! code (str): Code to be encapsulated #! cpp_var (str): CPP variable #! #:def generate_cpp(code, cpp_var) #:if cpp_var != "" #if ${cpp_var}$ #:endif $:code #:if cpp_var != "" #endif #:endif #:enddef generate_cpp #:endmute fortran-lang-stdlib-0ede301/CONTRIBUTING.md0000664000175000017500000001030715135654166020420 0ustar alastairalastair# Contributing to the Fortran standard library Thank you for considering contributing to the Fortran standard library (*stdlib*). Please review and follow these guidelines to make the contribution process simple and effective for all involved. It will help communicate that you respect the time of the community developers. In return, the community will help to address your problem, evaluate changes, and guide you through your pull requests. By contributing to *stdlib*, you certify that you own or are allowed to share the content of your contribution under the [stdlib license](https://github.com/fortran-lang/stdlib/blob/HEAD/LICENSE). * [Style](#style) * [Reporting a bug](#reporting-a-bug) * [Suggesting a feature](#suggesting-a-feature) * [Workflow](#workflow) * [General guidelines](#general-guidelines) * [For new contributors](#for-new-contributors) ## Style Please follow the [Fortran stdlib style guide](https://github.com/fortran-lang/stdlib/blob/HEAD/STYLE_GUIDE.md) for any Fortran code that you contribute. This allows the community to focus on substance rather than style. The style guide is a living document. You are welcome to propose changes to the style guide by [opening an issue](https://github.com/fortran-lang/stdlib/issues/new/choose) or [starting a discussion](https://github.com/fortran-lang/stdlib/discussions/new). ## Reporting a bug A bug is a *demonstrable problem* caused by the code in this repository. Good bug reports are extremely valuable to the community—thank you! Before opening a bug report: 1. Check if the issue has already been reported ([issues](https://github.com/fortran-lang/stdlib/issues)). 2. Check if it is still an issue or it has been fixed? Try to reproduce it with the latest version from the default branch. 3. Isolate the problem and create a minimal test case. A good bug report should include all information needed to reproduce the bug. Please be as detailed as possible: 1. Which version of *stdlib* are you using? Which compiler version are you using? Which platform and architecture are you on? Please be specific. 2. What are the steps to reproduce the issue? 3. What is the expected outcome? 4. What happens instead? This information will help the community to diagnose the issue quickly and with minimal back-and-forth. ## Suggesting a feature Before suggesting a new feature, take a moment to find out if it fits the scope of the project, or if it has already been discussed. It is up to you to provide a strong argument to convince the community of the benefits of this feature. Please provide as many details and context as possible. If applicable, include a mocked-up snippet of what the output or behavior would look like with this feature implemented. “Crazy,” out-of-the-box ideas are especially welcome. It is quite possible we have not considered such solutions yet. ## Workflow The general workflow is documented in [this document](https://github.com/fortran-lang/stdlib/blob/HEAD/WORKFLOW.md) The workflow guide is a living document. You are welcome to propose changes to the workflow by [opening an issue](https://github.com/fortran-lang/stdlib/issues/new/choose) or [starting a discussion](https://github.com/fortran-lang/stdlib/discussions/new). ## General guidelines * A PR should implement *only one* feature or bug fix. * Do not commit changes to files that are irrelevant to your feature or bug fix. * Smaller PRs are better than large PRs, and will lead to a shorter review and merge cycle. * Add tests for your feature or bug fix to be sure that it stays functional and useful. * Include new features and changes in the [CHANGELOG](https://github.com/fortran-lang/stdlib/blob/master/CHANGELOG.md) * Be open to constructive criticism and requests for improving your code. * Again, please follow the [Fortran stdlib style guide](https://github.com/fortran-lang/stdlib/blob/HEAD/STYLE_GUIDE.md). ## For new contributors If you have never created a pull request before, welcome :tada:. You can learn how from [this great tutorial](https://app.egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github). Don’t know where to start? You can start by looking through the list of [open issues](https://github.com/fortran-lang/stdlib/issues). fortran-lang-stdlib-0ede301/test/0000775000175000017500000000000015135654166017145 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/stringlist/0000775000175000017500000000000015135654166021347 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/stringlist/test_append_prepend.f900000664000175000017500000002467715135654166025732 0ustar alastairalastair! SPDX-Identifier: MIT module test_append_prepend use stdlib_error, only: check use stdlib_string_type, only: string_type, operator(//), operator(==) use stdlib_stringlist_type, only: stringlist_type, fidx, bidx, list_head, & & list_tail, operator(//), operator(==), operator(/=) use stdlib_strings, only: to_string implicit none contains subroutine test_append_prepend_string type(stringlist_type) :: work_list type(stringlist_type) :: reference_list integer :: i integer, parameter :: first = -100 integer, parameter :: last = 100 character(len=:), allocatable :: string type(string_type) :: all_strings(first:last) do concurrent (i=first:last) all_strings(i) = string_type( to_string(i) ) end do do i = first, last string = to_string(i) work_list = work_list // string call check( work_list%get( fidx( i - first + 1 ) ) == string_type( string ), & & "test_append_prepend_string: get fidx( i - first + 1 ) " // string ) end do call compare_list( work_list, first, last + 1, 1 ) call check( work_list == all_strings, & & "test_append_prepend_string: work_list ==& & [ ( string_type( to_string(i) ), i = first, last ) ]" ) call check( all_strings == work_list, & & "test_append_prepend_string: [ ( string_type( to_string(i) ),& & i = first, last ) ] == work_list" ) do i = last, first, -1 call check( work_list /= reference_list, "test_append_prepend_string:& & work_list /= reference_list" ) call check( reference_list /= work_list, "test_append_prepend_string:& & reference_list /= work_list" ) string = to_string(i) reference_list = string_type( string ) // reference_list call check( reference_list%get( bidx( last - i + 1 ) ) == string, & & "test_append_prepend_string: get bidx( last - i + 1 ) " // string ) end do call compare_list( reference_list, first, last + 1, 2 ) call check( reference_list == all_strings, "test_append_prepend_string:& & reference_list == [ ( string_type( to_string(i) ), i = first, last ) ]" ) call check( all_strings == reference_list, & & "test_append_prepend_string: [ ( string_type( to_string(i) ), i = first, last ) ] == reference_list" ) call check( work_list == reference_list, "test_append_prepend_string:& & work_list == reference_list" ) call check( reference_list == work_list, "test_append_prepend_string:& & reference_list == work_list" ) end subroutine test_append_prepend_string subroutine test_append_prepend_array type(stringlist_type) :: work_list type(stringlist_type) :: reference_list integer :: i, j integer, parameter :: first = -100 integer, parameter :: last = 100 integer, parameter :: stride = 10 type(string_type) :: all_strings(first:last) do concurrent (j=first:last) all_strings(j) = string_type( to_string(j) ) end do do i = first, last - 1, stride work_list = work_list // all_strings(i:i+stride-1) call check( work_list == all_strings(first:i+stride-1), & & "test_append_prepend_array: work_list ==& & [ ( string_type( to_string(j) ), j = first, i + stride - 1) ]" ) end do work_list = work_list // to_string(last) call compare_list( work_list, first, last + 1, 3 ) call check( work_list == all_strings, & & "test_append_prepend_array: work_list ==& & [ ( string_type( to_string(i) ), i = first, last) ]" ) call check( all_strings == work_list, & & "test_append_prepend_array: [ ( string_type( to_string(i) ), i = first, last) ]& & == work_list" ) do i = last, first + 1, -1 * stride call check( work_list /= reference_list, "test_append_prepend_array:& & work_list /= reference_list" ) call check( reference_list /= work_list, "test_append_prepend_array:& & reference_list /= work_list" ) reference_list = all_strings(i-stride+1:i) // reference_list call check( reference_list == all_strings(i-stride+1:last), & & "test_append_prepend_array: reference_list ==& & [ ( string_type( to_string(j) ), j = i - stride + 1, last ) ]" ) end do reference_list = to_string(first) // reference_list call compare_list( reference_list, first, last + 1, 4 ) call check( all_strings == reference_list, & & "test_append_prepend_array:& & [ ( string_type( to_string(i) ), i = first, last) ] == reference_list" ) call check( all_strings == reference_list, & & "test_append_prepend_array: [ ( string_type( to_string(i) ), i = first, last) ]& & == reference_list" ) call check( work_list == reference_list, "test_append_prepend_array:& & work_list == reference_list" ) call check( reference_list == work_list, "test_append_prepend_array:& & reference_list == work_list" ) end subroutine test_append_prepend_array subroutine test_append_prepend_list type(stringlist_type) :: work_list, reference_list type(stringlist_type) :: temp_list integer :: i, j integer, parameter :: first = -100 integer, parameter :: last = 100 integer, parameter :: stride = 10 type(string_type) :: all_strings(first:last) do concurrent (j=first:last) all_strings(j) = string_type( to_string(j) ) end do do i = first, last - 1, stride call temp_list%clear() do j = i, i + stride - 1 call temp_list%insert_at( list_tail, string_type( to_string(j) ) ) end do work_list = work_list // temp_list call check( work_list == all_strings(first:i+stride-1), & & "test_append_prepend_list: work_list ==& & [ ( to_string(j), j = first, i + stride - 1) ]" ) end do work_list = work_list // to_string(last) call compare_list( work_list, first, last + 1, 5 ) call check( work_list == all_strings, "test_append_prepend_list:& & work_list == [ ( string_type( to_string(i) ), i = first, last) ]" ) call check( all_strings == work_list, & & "test_append_prepend_list: [ ( string_type( to_string(i) ), i = first, last) ]& & == work_list" ) do i = last, first + 1, -1 * stride call check( work_list /= reference_list, "test_append_prepend_list:& & work_list /= reference_list" ) call check( reference_list /= work_list, "test_append_prepend_list:& & reference_list /= work_list" ) call temp_list%clear() do j = i - stride + 1, i call temp_list%insert_at( list_tail, to_string(j) ) end do reference_list = temp_list // reference_list call check( reference_list == & & all_strings(i-stride+1:last), & & "test_append_prepend_list: reference_list ==& & [ ( string_type( to_string(j) ), j = i - stride + 1, last ) ]" ) end do reference_list = to_string(first) // reference_list call compare_list( reference_list, first, last + 1, 6 ) call check( all_strings == reference_list, & & "test_append_prepend_list:& & [ ( string_type( to_string(i) ), i = first, last) ] == reference_list" ) call check( all_strings == reference_list, & & "test_append_prepend_list: [ ( string_type( to_string(i) ), i = first, last) ]& & == reference_list" ) call check( work_list == reference_list, "test_append_prepend_list:& & work_list == reference_list" ) call check( reference_list == work_list, "test_append_prepend_list:& & reference_list == work_list" ) end subroutine test_append_prepend_list ! compares input stringlist 'list' with an array of consecutive integers ! array is 'first' inclusive and 'last' exclusive subroutine compare_list(list, first, last, call_number) type(stringlist_type), intent(in) :: list integer, intent(in) :: first, last, call_number integer :: i, j call check( abs( last - first ) == list%len(), "compare_list: length mis-match& & call_number " // to_string( call_number ) ) j = merge(-1, 1, last < first) do i = 1, list%len() call check( list%get( fidx(i) ) == to_string( first + ( ( i - 1 ) * j ) ), & & "compare_list: call_number " // to_string( call_number ) & & // " fidx( " // to_string( i ) // " )") call check( list%get( bidx(i) ) == to_string( last - ( i * j ) ), & & "compare_list: call_number " // to_string( call_number ) & & // " bidx( " // to_string( i ) // " )") end do end subroutine compare_list end module test_append_prepend program tester use test_append_prepend implicit none call test_append_prepend_string call test_append_prepend_array call test_append_prepend_list end program tester fortran-lang-stdlib-0ede301/test/stringlist/CMakeLists.txt0000664000175000017500000000005315135654166024105 0ustar alastairalastairADDTEST(insert_at) ADDTEST(append_prepend) fortran-lang-stdlib-0ede301/test/stringlist/test_insert_at.f900000664000175000017500000004227615135654166024731 0ustar alastairalastair! SPDX-Identifier: MIT module test_insert_at use stdlib_error, only: check use stdlib_string_type, only: string_type, operator(//), operator(==) use stdlib_stringlist_type, only: stringlist_type, fidx, bidx, list_head, list_tail, operator(==) use stdlib_strings, only: to_string implicit none contains subroutine test_insert_at_string_1 type(stringlist_type) :: work_list integer :: i, current_length character(len=:), allocatable :: string integer, parameter :: first = -100 integer, parameter :: last = 1 work_list = stringlist_type() call check( work_list%len() == 0, "test_insert_at_string_1: constructor" ) write (*,*) "test_insert_at_string_1: Starting test case 1!" current_length = 0 do i = first, last string = to_string( i ) call work_list%insert_at( fidx(i), string ) current_length = current_length + 1 call check( work_list%get( fidx(1) ) == string, "test_insert_at_string_1:& & get fidx(1) " // string ) call check( work_list%get( list_head ) == string, "test_insert_at_string_1:& & get list_head " // string ) call check( work_list%get( bidx(current_length) ) == string, "test_insert_at_string_1: get& & bidx(current_length) " // string ) call check( work_list%get( list_tail ) == to_string(first), "test_insert_at_string_1: get& & list_tail " // string ) call check( work_list%len() == current_length, "test_insert_at_string_1: length check "& & // to_string( current_length ) ) end do ! compare work_list with [1, 0, -1, ..., ..., -99, -100] call compare_list( work_list, last, first - 1, 1) call work_list%clear() call work_list%clear() current_length = 0 write (*,*) "test_insert_at_string_1: Starting test case 2!" do i = first, last string = to_string( i ) call work_list%insert_at( bidx(i), string ) current_length = current_length + 1 call check( work_list%get( bidx(1) ) == string, "test_insert_at_string_1:& & get bidx(1) " // string ) call check( work_list%get( list_tail ) == string, "test_insert_at_string_1:& & get list_tail " // string ) call check( work_list%get( fidx(current_length) ) == string, "test_insert_at_string_1: get& & fidx(current_length) " // string ) call check( work_list%get( list_head ) == to_string(first), "test_insert_at_string_1: get& & list_head " // string ) call check( work_list%len() == current_length, "test_insert_at_string_1: length check "& & // to_string( current_length ) ) end do ! compare work_list with [-100, -99, ..., ..., 0, 1] call compare_list( work_list, first, last + 1, 2) end subroutine test_insert_at_string_1 subroutine test_insert_at_string_2 type(stringlist_type) :: work_list integer :: i, current_length character(len=:), allocatable :: string integer, parameter :: first = 2 integer, parameter :: last = 200 write (*,*) "test_insert_at_string_2: Starting test case 1!" current_length = 0 do i = first, last, 2 string = to_string( i ) call work_list%insert_at( fidx(i), string ) current_length = current_length + 1 call check( work_list%get( fidx(current_length) ) == string, "test_insert_at_string_2:& & get fidx(current_length) " // string ) call check( work_list%get( fidx(1) ) == to_string(first), "test_insert_at_string_2:& & get fidx(1) " // string ) call check( work_list%get( list_head ) == to_string(first), "test_insert_at_string_2:& & get list_head " // string ) call check( work_list%get( bidx(1) ) == string, "test_insert_at_string_2:& & get bidx(1) " // string ) call check( work_list%get( bidx(current_length) ) == to_string(first), "test_insert_at_string_2: get& & bidx(current_length) " // string ) call check( work_list%get( list_tail ) == string, "test_insert_at_string_2: get& & list_tail " // string ) call check( work_list%len() == current_length, "test_insert_at_string_2: length check "& & // to_string( current_length ) ) end do write (*,*) "test_insert_at_string_2: Starting test case 2!" do i = first - 1, last - 1, 2 string = to_string( i ) call work_list%insert_at( fidx(i), string ) current_length = current_length + 1 call check( work_list%get( fidx(i) ) == string, "test_insert_at_string_2:& & get fidx(current_length) " // string ) call check( work_list%get( fidx(1) ) == to_string(first - 1), "test_insert_at_string_2:& & get fidx(1) " // string ) call check( work_list%get( list_head ) == to_string(first - 1), "test_insert_at_string_2:& & get list_head " // string ) call check( work_list%get( bidx(1) ) == to_string(last), "test_insert_at_string_2:& & get bidx(1) " // string ) call check( work_list%get( bidx(current_length) ) == to_string(first - 1), "test_insert_at_string_2: get& & bidx(current_length) " // string ) call check( work_list%get( list_tail ) == to_string(last), "test_insert_at_string_2: get& & list_tail " // string ) call check( work_list%len() == current_length, "test_insert_at_string_2: length check "& & // to_string( current_length ) ) end do ! compare work_list with [1, 2, ..., ..., 199, 200] call compare_list( work_list, first - 1, last + 1, 3 ) end subroutine test_insert_at_string_2 subroutine test_insert_at_string_3 type(stringlist_type) :: work_list integer :: i, current_length character(len=:), allocatable :: string integer, parameter :: first = 2 integer, parameter :: last = 200 write (*,*) "test_insert_at_string_3: Starting test case 1!" current_length = 0 do i = first, last, 2 string = to_string( i ) call work_list%insert_at( bidx(i), string ) current_length = current_length + 1 call check( work_list%get( bidx(current_length) ) == string, "test_insert_at_string_3:& & get bidx(current_length) " // string ) call check( work_list%get( bidx(1) ) == to_string(first), "test_insert_at_string_3:& & get bidx(1) " // string ) call check( work_list%get( list_tail ) == to_string(first), "test_insert_at_string_3:& & get list_tail " // string ) call check( work_list%get( fidx(1) ) == string, "test_insert_at_string_3:& & get fidx(1) " // string ) call check( work_list%get( fidx(current_length) ) == to_string(first), "test_insert_at_string_3: get& & fidx(current_length) " // string ) call check( work_list%get( list_head ) == string, "test_insert_at_string_3: get& & list_head " // string ) call check( work_list%len() == current_length, "test_insert_at_string_3: length check "& & // to_string( current_length ) ) end do write (*,*) "test_insert_at_string_3: Starting test case 2!" do i = first - 1, last - 1, 2 string = to_string( i ) call work_list%insert_at( bidx(i), string ) current_length = current_length + 1 call check( work_list%get( bidx(i) ) == string, "test_insert_at_string_3:& & get bidx(current_length) " // string ) call check( work_list%get( bidx(1) ) == to_string(first - 1), "test_insert_at_string_3:& & get bidx(1) " // string ) call check( work_list%get( list_tail ) == to_string(first - 1), "test_insert_at_string_3:& & get list_tail " // string ) call check( work_list%get( fidx(1) ) == to_string(last), "test_insert_at_string_3:& & get fidx(1) " // string ) call check( work_list%get( fidx(current_length) ) == to_string(first - 1), "test_insert_at_string_3: get& & fidx(current_length) " // string ) call check( work_list%get( list_head ) == to_string(last), "test_insert_at_string_3: get& & list_head " // string ) call check( work_list%len() == current_length, "test_insert_at_string_3: length check "& & // to_string( current_length ) ) end do ! compare work_list with [200, 199, ..., ..., 2, 1] call compare_list( work_list, last, first - 2, 4 ) end subroutine test_insert_at_string_3 subroutine test_insert_at_array type(stringlist_type) :: work_list type(stringlist_type) :: reference_list integer :: i, j integer, parameter :: first = -100 integer, parameter :: last = 100 integer, parameter :: stride = 4 type(string_type) :: all_strings(first:last) write (*,*) "test_insert_at_array: Starting work_list!" do concurrent (j=first:last) all_strings(j) = string_type( to_string(j) ) end do call work_list%insert_at( list_head, all_strings(first:first+stride-1) ) call compare_list( work_list, first, first + stride, 5 ) call work_list%insert_at( list_tail, all_strings(last-stride:last-1) ) do i = first + stride, last - stride - 1, stride call work_list%insert_at( fidx( i - first + 1 ), all_strings(i:i+stride-1) ) end do call work_list%insert_at( list_tail, all_strings(last:last) ) call compare_list( work_list, first, last + 1, 6 ) write (*,*) "test_insert_at_array: Starting reference_list!" call reference_list%insert_at( list_tail, all_strings (last-stride+1:last) ) call compare_list( reference_list, last - stride + 1, last + 1, 7 ) call reference_list%insert_at( list_head, all_strings(first+1:first+stride) ) do i = last - stride, first + stride + 1, -1 * stride call reference_list%insert_at( bidx( last - i + 1 ), all_strings(i-stride+1:i) ) end do call reference_list%insert_at( list_head, all_strings(first:first) ) call compare_list( reference_list, first, last + 1, 8 ) end subroutine test_insert_at_array subroutine test_insert_at_list type(stringlist_type) :: work_list, reference_list type(stringlist_type) :: temp_list integer :: i, j integer, parameter :: first = -100 integer, parameter :: last = 100 integer, parameter :: stride = 4 type(string_type) :: all_strings(first:last) write (*,*) "test_insert_at_list: Starting work_list!" do concurrent (j=first:last) all_strings(j) = string_type( to_string(j) ) end do call temp_list%clear() do j = first, first + stride - 1 call temp_list%insert_at( list_tail, all_strings(j) ) end do call work_list%insert_at(list_head, temp_list) call compare_list( work_list, first, first + stride, 9) call temp_list%clear() do j = last - 1, last - stride, -1 call temp_list%insert_at( list_head, all_strings(j) ) end do call work_list%insert_at(list_tail, temp_list) do i = first + stride, last - stride - 1, stride call temp_list%clear() do j = i, i + stride - 1 call temp_list%insert_at( list_tail, to_string(j) ) end do call work_list%insert_at( fidx( i - first + 1 ), temp_list ) end do call temp_list%clear() call temp_list%insert_at( list_head, all_strings(last) ) call work_list%insert_at( list_tail, temp_list ) call compare_list( work_list, first, last + 1, 10 ) write (*,*) "test_insert_at_list: Starting reference_list!" call temp_list%clear() do j = last - stride + 1, last call temp_list%insert_at( list_tail, to_string(j) ) end do call reference_list%insert_at( list_tail, temp_list ) call compare_list( reference_list, last - stride + 1, last + 1, 11 ) call temp_list%clear() do j = first + 1, first + stride call temp_list%insert_at( list_tail, string_type( to_string(j) ) ) end do call reference_list%insert_at( list_head, temp_list ) do i = last - stride, first + stride + 1, -1 * stride call temp_list%clear() do j = i - stride + 1, i call temp_list%insert_at( list_tail, to_string(j) ) end do call reference_list%insert_at( bidx( last - i + 1 ), temp_list ) end do call temp_list%clear() call temp_list%insert_at( list_tail, to_string(first) ) call reference_list%insert_at( list_head, temp_list ) call compare_list( reference_list, first, last + 1, 12 ) end subroutine test_insert_at_list subroutine test_constructor type(stringlist_type) :: work_list character(len=4), allocatable :: carray(:) type(string_type), allocatable :: sarray(:) write (*,*) "test_constructor: Starting test case 1!" work_list = stringlist_type() allocate( carray(0) ) allocate( sarray(0) ) call check( work_list == carray, "test_constructor:& & test_case 1 work_list == carray" ) call check( work_list == sarray, "test_constructor:& & test_case 1 work_list == sarray" ) write (*,*) "test_constructor: Starting test case 2!" carray = [ '#1', '#2', '#3', '#4' ] sarray = [ string_type('#1'), string_type('#2'), string_type('#3'), string_type('#4') ] work_list = stringlist_type( carray ) call check( work_list == carray, "test_constructor:& & test_case 2 work_list == carray" ) call check( work_list == sarray, "test_constructor:& & test_case 2 work_list == sarray" ) write (*,*) "test_constructor: Starting test case 3!" work_list = stringlist_type( sarray ) call check( work_list == carray, "test_constructor:& & test_case 3 work_list == carray" ) call check( work_list == sarray, "test_constructor:& & test_case 3 work_list == sarray" ) end subroutine test_constructor ! compares input stringlist 'list' with an array of consecutive integers ! array is 'first' inclusive and 'last' exclusive subroutine compare_list(list, first, last, call_number) type(stringlist_type), intent(in) :: list integer, intent(in) :: first, last, call_number integer :: i, j call check( abs( last - first ) == list%len(), "compare_list: length mis-match& & call_number " // to_string( call_number ) ) j = merge(-1, 1, last < first) do i = 1, list%len() call check( list%get( fidx(i) ) == to_string( first + ( ( i - 1 ) * j ) ), & & "compare_list: call_number " // to_string( call_number ) & & // " fidx( " // to_string( i ) // " )") call check( list%get( bidx(i) ) == to_string( last - ( i * j ) ), & & "compare_list: call_number " // to_string( call_number ) & & // " bidx( " // to_string( i ) // " )") end do end subroutine compare_list end module test_insert_at program tester use test_insert_at implicit none call test_insert_at_string_1 call test_insert_at_string_2 call test_insert_at_string_3 call test_insert_at_array call test_insert_at_list call test_constructor end program tester fortran-lang-stdlib-0ede301/test/logger/0000775000175000017500000000000015135654166020424 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/logger/CMakeLists.txt0000664000175000017500000000002715135654166023163 0ustar alastairalastairADDTEST(stdlib_logger) fortran-lang-stdlib-0ede301/test/logger/test_stdlib_logger.f900000664000175000017500000007154115135654166024633 0ustar alastairalastairprogram test_stdlib_logger !! A test code for most of stdlib_logger.f90. use, intrinsic :: & iso_fortran_env, only : & error_unit, & input_unit, & output_unit use stdlib_logger, global => global_logger implicit none integer, allocatable :: log_units(:) integer :: level, max_width, stat integer :: unit1, unit2, unit3, unit4, unit5, unit6 logical :: add_blank_line, exist, indent, time_stamp if ( global % log_units_assigned() == 0 ) then write(*,*) 'Start off with 0 LOG_UNITS as expected.' else error stop 'Unexpected start off with non_zero LOG_UNITS.' end if call test_logging_configuration() call test_adding_log_files() print * print *, 'running test of log_error' call global % log_error( 'This message should be output to five ' // & 'files and not to OUTPUT_UNIT, limited to 72 columns width, ' // & 'preceded by no blank line, then by a time stamp, then by ' // & 'MODULE % PROCEDURE, be prefixed by ERROR and be indented on ' // & 'subsequent lines by 4 columns, and finish with STAT and.' // & 'ERRMSG lines.', & module = 'N/A', & procedure = 'TEST_STDLIB_LOGGER', & stat = 0, & errmsg = 'This is a long ERRMSG intended to test formatting ' // & 'of the ERRMSG when it is more than 72 columns wide.' ) call test_removing_log_units() print * print *, 'running log_text_error' call global % log_text_error( 'This text should be written to UNIT1' // & ' and UNIT3 and not to OUTPUT_UNIT.', & column = 25, & summary = 'There is no real error here.', & filename = 'dummy.txt', & line_number = 0, & caret = '1', & stat = stat ) ! call global % assert( 1 < 0, '1 < 0 ; Test of ASSERT', module='N/A', & ! procedure = 'TEST_SDLIB_LOGGER' ) call test_adding_log_units() print * print *, 'running log_text_error' call global % log_text_error( 'This text should be written to ' // & 'UNIT1, UNIT2, and OUTPUT_UNIT.', & column = 25, & summary = 'There is no real error here.', & filename = 'dummy.txt', & line_number = 0, & caret = '^', & stat = stat ) call test_level() contains subroutine test_logging_configuration() print *, 'running test_logging_configuration' call global % configuration( add_blank_line=add_blank_line, & indent=indent, max_width=max_width, time_stamp=time_stamp, & log_units=log_units ) if ( .not. add_blank_line ) then write(*,*) 'ADD_BLANK_LINE starts off as .FALSE. as expected.' else error stop 'ADD_BLANK_LINE starts off as .TRUE. contrary to ' // & 'expectations.' end if if ( indent ) then write(*,*) 'INDENT starts off as .TRUE. as expected.' else error stop 'INDENT starts off as .FALSE. contrary to expectations.' end if if ( max_width == 0 ) then write(*,*) 'MAX_WIDTH starts off as 0 as expected.' else error stop 'MAX_WIDTH starts off as not equal to 0 contrary ' // & 'to expectations.' end if if ( time_stamp ) then write(*,*) 'TIME_STAMP starts off as .TRUE. as expected.' else error stop 'TIME_STAMP starts off as .FALSE. contrary to ' // & 'expectations.' end if if ( size(log_units) == 0 ) then write(*,*) 'SIZE(LOG_UNITS) starts off as 0 as expected.' else error stop 'SIZE(LOG_UNITS) starts off as non-zero contrary ' // & 'to expectations.' end if !testing all calls independently call global % configuration( add_blank_line=add_blank_line ) if ( .not. add_blank_line ) then write(*,*) 'ADD_BLANK_LINE starts off as .FALSE. as expected.' else error stop 'ADD_BLANK_LINE starts off as .TRUE. contrary to ' // & 'expectations.' end if call global % configuration( indent=indent ) if ( indent ) then write(*,*) 'INDENT starts off as .TRUE. as expected.' else error stop 'INDENT starts off as .FALSE. contrary to expectations.' end if call global % configuration( max_width=max_width ) if ( max_width == 0 ) then write(*,*) 'MAX_WIDTH starts off as 0 as expected.' else error stop 'MAX_WIDTH starts off as not equal to 0 contrary ' // & 'to expectations.' end if call global % configuration( time_stamp=time_stamp ) if ( time_stamp ) then write(*,*) 'TIME_STAMP starts off as .TRUE. as expected.' else error stop 'TIME_STAMP starts off as .FALSE. contrary to ' // & 'expectations.' end if call global % configuration( log_units=log_units ) if ( size(log_units) == 0 ) then write(*,*) 'SIZE(LOG_UNITS) starts off as 0 as expected.' else error stop 'SIZE(LOG_UNITS) starts off as non-zero contrary ' // & 'to expectations.' end if call global % log_information( 'This message should be output ' // & 'to OUTPUT_UNIT, unlimited in width, not preceded by ' // & 'a blank line, then by a time stamp, then by MODULE % ' // & 'PROCEDURE, be prefixed by INFO and be indented on ' // & 'subsequent lines by 4 columns.', & module = 'N/A', & procedure = 'TEST_STDLIB_LOGGER' ) call global % log_information( 'This message should be output ' // & 'to OUTPUT_UNIT, unlimited in width, not preceded by ' // & 'a blank line, then by a time stamp, then by MODULE % ' // & 'PROCEDURE, be prefixed by INFO. ' // new_line('a') // & 'This is a new line of the same log message.', & module = 'N/A', & procedure = 'TEST_STDLIB_LOGGER' ) call global % log_debug( 'This message should be output ' // & 'to OUTPUT_UNIT, unlimited in width, not preceded by ' // & 'a blank line, then by a time stamp, then by MODULE % ' // & 'PROCEDURE, be prefixed by DEBUG and be indented on ' // & 'subsequent lines by 4 columns.', & module = 'N/A', & procedure = 'TEST_STDLIB_LOGGER' ) call global % log_debug( 'This message should be output ' // & 'to OUTPUT_UNIT, unlimited in width, not preceded by ' // & 'a blank line, then by a time stamp, then by MODULE % ' // & 'PROCEDURE, be prefixed by DEBUG. ' // new_line('a') // & 'This is a new line of the same log message.', & module = 'N/A', & procedure = 'TEST_STDLIB_LOGGER' ) call global % configure( add_blank_line=.true., indent=.false., & max_width=72, time_stamp=.false. ) call global % configuration( add_blank_line=add_blank_line, & indent=indent, max_width=max_width, time_stamp=time_stamp, & log_units=log_units ) if ( add_blank_line ) then write(*,*) 'ADD_BLANK_LINE is now .TRUE. as expected.' else error stop 'ADD_BLANKLINE is now .FALSE. contrary to expectations.' end if if ( .not. indent ) then write(*,*) 'INDENT is now .FALSE. as expected.' else error stop 'INDENT is now .TRUE. contrary to expectations.' end if if ( max_width == 72 ) then write(*,*) 'MAX_WIDTH is now 72 as expected.' else error stop 'MAX_WIDTH is not equal to 72 contrary to expectations.' end if if ( .not. time_stamp ) then write(*,*) 'TIME_STAMP is now .FALSE. as expected.' else error stop 'TIME_STAMP starts off as .FALSE. contrary to ' // & 'expectations.' end if if ( size(log_units) == 0 ) then write(*,*) 'SIZE(LOG_UNITS) is still 0 as expected.' else error stop 'SIZE(LOG_UNITS) is now non-zero contrary to ' // & 'expectations.' end if call global % log_message( 'This message should still be output ' // & 'to OUTPUT_UNIT, limited to 72 columns width, preceded by ' // & 'a blank line, then by no time stamp, then by MODULE % ' // & 'PROCEDURE, have no prefix, and be unindented on subsequent ' // & 'lines.', & module = 'N/A', & procedure = 'TEST_STDLIB_LOGGER' ) call global % log_message( 'The last word of the first line ' // & new_line('a')//'should be "line". "Line"' // new_line('a') // & 'is also the last word for the second line. The following ' // & 'lines should be limited to 72 columns width.' , & module = 'N/A', & procedure = 'TEST_STDLIB_LOGGER' ) call global % configure( add_blank_line=.false., indent=.true., & max_width=72, time_stamp=.true. ) call global % log_warning( 'This message should still be ' // & 'output to OUTPUT_UNIT, limited to 72 columns width, ' // & 'preceded by no blank line, then by a time stamp, then ' // & 'by MODULE % PROCEDURE, have a prefix of WARN, and be ' // & 'indented by 4 columns on subsequent lines.', & module = 'N/A', & procedure = 'TEST_STDLIB_LOGGER' ) call global % log_message( 'The last word of the first line ' // & new_line('a')//'should be "the". "Line"' // new_line('a') // & 'should be the last word for the second line. The following ' // & 'lines should be limited to 72 columns width. From the second ' //& 'line, all lines should be indented by 4 columns.' ,& module = 'N/A', & procedure = 'TEST_STDLIB_LOGGER' ) end subroutine test_logging_configuration subroutine test_adding_log_files() print * print *, 'running test_adding_log_files' call global % add_log_file( 'first_log_file.txt', unit1, stat=stat ) if ( stat == success ) then write(*,*) 'Able to open "first_log_file.txt" as expected' else error stop 'Unable to open "first_log_file.txt" contrary to ' // & 'expectations.' end if if ( global % log_units_assigned() == 1 ) then write(*,*) 'Incremented to 1 LOG_UNITS as expected.' else error stop 'Unexpected increment to other than 1 LOG_UNITS.' end if call global % add_log_file( 'second_log_file.txt', unit2, & action='readwrite', stat=stat ) if ( stat == success ) then write(*,*) 'Able to open "second_log_file.txt" as expected' else error stop 'Unable to open "second_log_file.txt" contrary to ' // & 'expectations.' end if if ( global % log_units_assigned() == 2 ) then write(*,*) 'Incremented to 2 LOG_UNITS as expected.' else error stop 'Unexpected increment to other than 2 LOG_UNITS.' end if call global %add_log_file( 'third_log_file.txt', unit3, & position='asis', stat=stat ) if ( stat == success ) then write(*,*) 'Able to open "third_log_file.txt" as expected' else error stop 'Unable to open "third_log_file.txt" as contrary ' // & 'to expectations.' end if if ( global % log_units_assigned() == 3 ) then write(*,*) 'Incremented to 3 LOG_UNITS as expected.' else error stop 'Unexpected increment to other than 3 LOG_UNITS.' end if call global % add_log_file( 'fourth_log_file.txt', unit4, & status='new', stat=stat ) if ( stat /= success ) then inquire( file='fourth_log_file.txt', exist=exist ) write(*,*) 'Unable to OPEN "fourth_log_file.txt" as "NEW" ' // & 'as it already exists, which is an expected result.' call global % add_log_file( 'fourth_log_file.txt', unit4, & status='old', position='rewind', stat=stat ) if ( stat /= success ) then error stop 'Unable to open "fourth_log_file.txt" as "OLD".' end if end if if ( global % log_units_assigned() == 4 ) then write(*,*) 'Incremented to 4 LOG_UNITS as expected.' else error stop 'Unexpected increment to other than 4 LOG_UNITS.' end if call global % add_log_file( 'fifth_log_file.txt', unit5, & action='READ', stat=stat ) if ( stat /= success ) then if ( stat == read_only_error ) then write(*,*) 'Unable to OPEN "fifth_log_file.txt" as ' // & '"READ", as it makes it read only, which is an ' // & 'expected result.' call global % add_log_file( 'fifth_log_file.txt', unit5, & action='write', stat=stat ) if ( stat /= success ) then error stop 'Unable to open "fifth_log_file.txt" as "WRITE".' end if end if end if if ( global % log_units_assigned() == 5 ) then write(*,*) 'Incremented to 5 LOG_UNITS as expected.' else error stop 'Unexpected increment to other than 5 LOG_UNITS.' end if end subroutine test_adding_log_files subroutine test_removing_log_units() logical :: opened integer :: istat print * print *, 'running test_removing_log_units' call global % remove_log_unit( unit5 ) if ( global % log_units_assigned() == 4 ) then write(*,*) 'Decremented to 4 LOG_UNITS as expected.' else error stop 'Unexpected change to other than 4 LOG_UNITS.' end if call global % remove_log_unit( unit5 ) ! Should do nothing as already removed if ( global % log_units_assigned() == 4 ) then write(*,*) 'Remained at 4 LOG_UNITS as expected.' else error stop 'Unexpected change to other than 4 LOG_UNITS.' end if inquire( unit4, opened=opened ) if ( opened ) then write(*,*) 'UNIT4 is OPENED as expected.' else error stop 'UNIT4 is not OPENED contrary to expectations.' end if call global % remove_log_unit( unit4, close_unit=.true., stat=stat ) if ( stat /= success ) then error stop 'Unable to close UNIT4 in REMOVE_LOG_UNIT.' end if if ( global % log_units_assigned() == 3 ) then write(*,*) 'Decremented to 3 LOG_UNITS as expected.' else error stop 'Unexpected change to other than 3 LOG_UNITS.' end if inquire( unit4, opened=opened, iostat=istat ) if(istat /= 0) opened = .false. if ( opened ) then error stop 'UNIT4 is opened contrary to expectations.' else write(*,*) 'UNIT4 is not opened as expected.' end if call global % configuration( log_units=log_units ) if ( unit1 == log_units(1) .and. unit2 == log_units(2) .and. & unit3 == log_units(3) ) then write(*,*) 'Units have retained their expected ordering' else error stop 'Units have not retained their expected ordering' end if call global % remove_log_unit( unit4, close_unit=.true., stat=stat ) if ( stat /= success ) then error stop 'Attempted to close UNIT4 in REMOVE_LOG_UNIT and failed.' end if if ( global % log_units_assigned() == 3 ) then write(*,*) 'Remained at 3 LOG_UNITS as expected.' else error stop 'Unexpected change to other than 3 LOG_UNITS.' end if call global % configuration( log_units=log_units ) if ( unit1 == log_units(1) .and. unit2 == log_units(2) .and. & unit3 == log_units(3) ) then write(*,*) 'Units have retained their expected ordering' else error stop 'Units have not retained their expected ordering' end if call global % remove_log_unit( unit2 ) if ( global % log_units_assigned() == 2 ) then write(*,*) 'Decremented to 2 LOG_UNITS as expected.' else error stop 'Unexpected change to other than 2 LOG_UNITS.' end if call global % configuration( log_units=log_units ) if ( unit1 == log_units(1) .and. unit3 == log_units(2) ) then write(*,*) 'Units have their expected placement' else error stop 'Units do not have their expected placement' end if end subroutine test_removing_log_units subroutine test_adding_log_units() print * print *, 'running test_adding_log_units' call global % add_log_unit( unit2, stat ) if ( stat == success ) then if ( global % log_units_assigned() == 3 ) then write(*,*) 'Successfully added unit2 as expected' else error stop 'Adding unit2 failed to increase log_units to 3.' end if else error stop 'Unexpected problem adding unit2.' end if call global % add_log_unit( output_unit, stat ) if ( stat == success ) then if ( global % log_units_assigned() == 4 ) then write(*,*) 'Successfully added output_unit as expected' else error stop 'Adding output_unit failed to increase ' // & 'log_units to 4.' end if else error stop 'Unexpected problem adding output_unit.' end if call global % add_log_unit( error_unit, stat ) if ( stat == success ) then if ( global % log_units_assigned() == 5 ) then write(*,*) 'Successfully added error_unit as expected' else error stop 'Adding error_unit failed to increase ' // & 'log_units to 5.' end if else error stop 'Unexpected problem adding error_unit.' end if call global % add_log_unit( input_unit, stat ) if ( stat /= success ) then if ( global % log_units_assigned() == 5 ) then write(*,*) 'Failed at adding input_unit as expected' else error stop 'Unsuccessfully adding input_unit failed to ' // & 'keep log_units to 5.' end if else error stop 'Unexpected success adding input_unit.' end if open( newunit=unit6, file='sixth_log_file.txt', form='formatted', & action='read', status='replace', position='rewind' ) call global % add_log_unit( unit6, stat ) if ( stat == read_only_error ) then write(*,*) 'Adding unit6 failed with a READ_ONLY_ERROR as expected' else error stop 'Adding unit6 did not fail with a READ_ONLY_ERROR.' end if close(unit6) call global % add_log_unit( unit6, stat ) if ( stat == unopened_in_error ) then write(*,*) 'Adding unit6 failed with a UNOPENED_IN_ERROR as ' // & 'expected' else error stop 'Adding unit6 did not fail with a UNOPENED_IN_ERROR.' end if open( newunit=unit6, file='sixth_log_file.txt', form='unformatted', & action='write', status='replace', position='rewind' ) call global % add_log_unit( unit6, stat ) if ( stat == unformatted_in_error ) then write(*,*) 'Adding unit6 failed with a UNFORMATTED_IN_ERROR ' // & 'as expected' else write(*, *) 'STAT = ', stat error stop 'Adding unit6 did not fail with a UNFORMATTED_IN_ERROR.' end if close(unit6) open( newunit=unit6, file='sixth_log_file.txt', form='formatted', & action='write', status='replace', access='direct', recl=100 ) call global % add_log_unit( unit6, stat ) if ( stat == non_sequential_error ) then write(*,*) 'Adding unit6 failed with a ' // & 'NON_SEQUENTIAL_ERROR as expected' else error stop 'Adding unit6 did not fail with a ' // & 'NON_SEQUENTIAL_ERROR.' end if close(unit6) open( newunit=unit6, file='sixth_log_file.txt', form='formatted', & action='write', status='replace', position='rewind', & access='sequential' ) call global % add_log_unit( unit6, stat ) if ( stat == success ) then if ( global % log_units_assigned() == 6 ) then write(*,*) 'Successfully added unit6 as expected' else error stop 'Adding unit6 failed to increase log_units to 6.' end if else error stop 'Unexpected problem adding unit6.' end if call global % remove_log_unit( unit6, stat=stat ) if ( stat /= success ) then error stop 'Unexpected problem removing unit6' else if ( global % log_units_assigned() /= 5 ) then error stop 'Removing unit6 did not decrement log_units to 5.' else write(*,*) 'Successfully removed unit6 as expected.' end if end if call global % remove_log_unit( error_unit, stat=stat ) if ( stat /= success ) then error stop 'Unexpected problem removing error_unit' else if ( global % log_units_assigned() /= 4 ) then error stop 'Removing error_unit did not decrement ' // & 'log_units to 4.' else write(*,*) 'Successfully removed error_unit as expected.' end if end if call global % remove_log_unit( unit3, stat=stat ) if ( stat /= success ) then error stop 'Unexpected problem removing unit3' else if ( global % log_units_assigned() /= 3 ) then error stop 'Removing unit3 did not decrement ' // & 'log_units to 3.' else write(*,*) 'Successfully removed unit3 as expected.' end if end if return end subroutine test_adding_log_units subroutine test_level() print *, 'running test_level' call global % configure( level = all_level ) call global % configuration( level = level ) if ( level == all_level ) then write(*,*) 'LEVEL is all_level as expected.' else error stop 'LEVEL starts off as not equal to all_level ' //& 'contrary to expectations.' end if call global % log_message('This message should be always printed, & & irrespective of the severity level') call global % log_debug( 'This message should be printed') call global % log_information( 'This message should be printed') call global % log_warning( 'This message should be printed') call global % log_error( 'This message should be printed') call global % log_io_error( 'This message should be printed') call global % configure( level = debug_level ) call global % configuration( level = level ) if ( level == debug_level ) then write(*,*) 'LEVEL is debug_level as expected.' else error stop 'LEVEL starts off as not equal to debug_level ' //& 'contrary to expectations.' end if call global % log_message('This message should be always printed, & & irrespective of the severity level') call global % log_debug( 'This message should be printed') call global % log_information( 'This message should be printed') call global % log_warning( 'This message should be printed') call global % log_error( 'This message should be printed') call global % log_io_error( 'This message should be printed') call global % configure( level = information_level ) call global % configuration( level = level ) if ( level == information_level ) then write(*,*) 'LEVEL is information_level as expected.' else error stop 'LEVEL starts off as not equal to information_level ' //& 'contrary to expectations.' end if call global % log_message('This message should be always printed, & & irrespective of the severity level') call global % log_debug( 'This message should NOT be printed') call global % log_information( 'This message should be printed') call global % log_warning( 'This message should be printed') call global % log_error( 'This message should be printed') call global % log_io_error( 'This message should be printed') call global % configure( level = warning_level ) call global % configuration( level = level ) if ( level == warning_level ) then write(*,*) 'LEVEL is warning_level as expected.' else error stop 'LEVEL starts off as not equal to warning_level ' //& 'contrary to expectations.' end if call global % log_message('This message should be always printed, & & irrespective of the severity level') call global % log_debug( 'This message should NOT be printed') call global % log_information( 'This message should NOT be printed') call global % log_warning( 'This message should be printed') call global % log_error( 'This message should be printed') call global % log_io_error( 'This message should be printed') call global % configure( level = error_level ) call global % configuration( level = level ) if ( level == error_level ) then write(*,*) 'LEVEL is error_level as expected.' else error stop 'LEVEL starts off as not equal to error_level ' //& 'contrary to expectations.' end if call global % log_message('This message should be always printed, & & irrespective of the severity level') call global % log_debug( 'This message should NOT be printed') call global % log_information( 'This message should NOT be printed') call global % log_warning( 'This message should NOT be printed') call global % log_error( 'This message should be printed') call global % log_io_error( 'This message should be printed') call global % configure( level = none_level ) call global % configuration( level = level ) if ( level == none_level ) then write(*,*) 'LEVEL is none_level as expected.' else error stop 'LEVEL starts off as not equal to none_level ' //& 'contrary to expectations.' end if call global % log_message('This message should be always printed, & & irrespective of the severity level') call global % log_debug( 'This message should NOT be printed') call global % log_information( 'This message should NOT be printed') call global % log_warning( 'This message should NOT be printed') call global % log_error( 'This message should NOT be printed') call global % log_io_error( 'This message should NOT be printed') print *, 'end of test_level' end subroutine test_level end program test_stdlib_logger fortran-lang-stdlib-0ede301/test/linalg/0000775000175000017500000000000015135654166020413 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/linalg/test_linalg_inverse.fypp0000664000175000017500000002542415135654166025362 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test inverse matrix operator module test_linalg_inverse use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg_constants use stdlib_linalg, only: inv,invert,operator(.inv.),eye use stdlib_linalg_state, only: linalg_state_type,LINALG_ERROR implicit none (type,external) private public :: test_inverse_matrix contains !> Matrix inversion tests subroutine test_inverse_matrix(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in RC_KINDS_TYPES call add_test(tests,new_unittest("${ri}$_eye_inverse",test_${ri}$_eye_inverse)) call add_test(tests,new_unittest("${ri}$_singular_inverse",test_${ri}$_singular_inverse)) call add_test(tests,new_unittest("${ri}$_random_spd_inverse",test_${ri}$_random_spd_inverse)) #:endfor end subroutine test_inverse_matrix #:for rk,rt,ri in REAL_KINDS_TYPES !> Invert real identity matrix subroutine test_${ri}$_eye_inverse(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp), parameter :: n = 25_ilp ${rt}$ :: a(n,n),inva(n,n) a = eye(n) !> Inverse function inva = inv(a,err=state) call check(error,state%ok(),'inverse_${ri}$_eye (function): '//state%print()) if (allocated(error)) return call check(error,all(abs(a-inva) Inverse subroutine: split call invert(a,inva,err=state) call check(error,state%ok(),'inverse_${ri}$_eye (subroutine): '//state%print()) if (allocated(error)) return call check(error,all(abs(a-inva) Inverse subroutine in-place call invert(a,err=state) call check(error,state%ok(),'inverse_${ri}$_eye (in-place): '//state%print()) if (allocated(error)) return call check(error,all(abs(a-inva) Invert singular matrix subroutine test_${ri}$_singular_inverse(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: err integer(ilp), parameter :: n = 25_ilp ${rt}$ :: a(n,n) a = eye(n) !> Make rank-deficient a(12,12) = 0 !> Inverse function call invert(a,err=err) call check(error,err%state==LINALG_ERROR,'singular ${rt}$ inverse returned '//err%print()) if (allocated(error)) return end subroutine test_${ri}$_singular_inverse !> Create a random symmetric positive definite matrix function random_spd_matrix_${ri}$(n) result(A) integer(ilp), intent(in) :: n ${rt}$ :: A(n,n) ${rt}$, parameter :: half = 0.5_${rk}$ !> Initialize with randoms call random_number(A) !> Make symmetric A = half*(A+transpose(A)) !> Add diagonally dominant part A = A + n*eye(n) end function random_spd_matrix_${ri}$ !> Test random symmetric positive-definite matrix subroutine test_${ri}$_random_spd_inverse(error) type(error_type), allocatable, intent(out) :: error !> Solution tolerance ${rt}$, parameter :: tol = sqrt(epsilon(0.0_${rk}$)) !> Local variables integer(ilp), parameter :: n = 5_ilp type(linalg_state_type) :: state ${rt}$ :: A(n,n),Am1(n,n) !> Generate random SPD matrix A = random_spd_matrix_${ri}$(n) !> Invert matrix call invert(A,Am1,err=state) !> Check result call check(error,state%ok(),'random SPD matrix (${rk}$): '//state%print()) if (allocated(error)) return call check(error,all(abs(matmul(Am1,A)-eye(n)) Invert complex identity matrix #:for ck,ct,ci in CMPLX_KINDS_TYPES subroutine test_${ci}$_eye_inverse(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp) :: i,j,failed integer(ilp), parameter :: n = 25_ilp ${ct}$ :: a(n,n),copya(n,n),inva(n,n) do concurrent (i=1:n,j=1:n) a(i,j) = merge((1.0_${ck}$,1.0_${ck}$),(0.0_${ck}$,0.0_${ck}$),i==j) end do copya = a !> The inverse of a complex diagonal matrix has conjg(z_ii)/abs(z_ii)^2 on the diagonal inva = inv(a,err=state) call check(error,state%ok(),'inverse_${ci}$_eye (function): '//state%print()) if (allocated(error)) return failed = 0 do i=1,n do j=1,n if (.not.is_diagonal_inverse(a(i,j),inva(i,j),i,j)) failed = failed+1 end do end do call check(error,failed==0,'inverse_${ci}$_eye (function): data converged') if (allocated(error)) return !> Inverse subroutine call invert(copya,err=state) call check(error,state%ok(),'inverse_${ci}$_eye (subroutine): '//state%print()) if (allocated(error)) return failed = 0 do i=1,n do j=1,n if (.not.is_diagonal_inverse(a(i,j),copya(i,j),i,j)) failed = failed+1 end do end do call check(error,failed==0,'inverse_${ci}$_eye (subroutine): data converged') if (allocated(error)) return contains elemental logical function is_diagonal_inverse(aij,invaij,i,j) ${ct}$, intent(in) :: aij,invaij integer(ilp), intent(in) :: i,j if (i/=j) then is_diagonal_inverse = max(abs(aij),abs(invaij)) Create a random symmetric positive definite matrix function random_spd_matrix_${ci}$(n) result(A) integer(ilp), intent(in) :: n ${ct}$ :: A(n,n) ${ct}$, parameter :: half = (0.5_${ck}$,0.0_${ck}$) real(${ck}$) :: reA(n,n),imA(n,n) integer(ilp) :: i !> Initialize with randoms call random_number(reA) call random_number(imA) A = cmplx(reA,imA,kind=${ck}$) !> Make symmetric A = half*(A+transpose(A)) !> Add diagonally dominant part forall(i=1:n) A(i,i) = A(i,i) + n*(1.0_${ck}$,0.0_${ck}$) end function random_spd_matrix_${ci}$ !> Test random symmetric positive-definite matrix subroutine test_${ci}$_random_spd_inverse(error) type(error_type), allocatable, intent(out) :: error !> Local variables integer(ilp) :: failed,i,j integer(ilp), parameter :: n = 5_ilp type(linalg_state_type) :: state ${ct}$ :: A(n,n),Am1(n,n),AA(n,n) !> Generate random SPD matrix A = random_spd_matrix_${ci}$(n) !> Invert matrix call invert(A,Am1,err=state) !> Check result call check(error,state%ok(),'random complex SPD matrix (${ck}$): '//state%print()) if (allocated(error)) return failed = 0 AA = matmul(A,Am1) do i=1,n do j=1,n if (.not.is_complex_inverse(AA(i,j),i,j)) failed = failed+1 end do end do call check(error,failed==0,'inverse_${ci}$_eye (subroutine): data converged') if (allocated(error)) return contains elemental logical function is_complex_inverse(aij,i,j) ${ct}$, intent(in) :: aij integer(ilp), intent(in) :: i,j real(${ck}$), parameter :: tol = sqrt(epsilon(0.0_${ck}$)) if (i/=j) then is_complex_inverse = abs(aij) Invert singular matrix subroutine test_${ci}$_singular_inverse(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: err integer(ilp), parameter :: n = 25_ilp ${ct}$ :: a(n,n) a = (0.0_${ck}$,0.0_${ck}$) !> Inverse function call invert(a,err=err) call check(error,err%state==LINALG_ERROR,'singular ${ct}$ inverse returned '//err%print()) if (allocated(error)) return end subroutine test_${ci}$_singular_inverse #:endfor ! gcc-15 bugfix utility subroutine add_test(tests,new_test) type(unittest_type), allocatable, intent(inout) :: tests(:) type(unittest_type), intent(in) :: new_test integer :: n type(unittest_type), allocatable :: new_tests(:) if (allocated(tests)) then n = size(tests) else n = 0 end if allocate(new_tests(n+1)) if (n>0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_inverse program test_inv use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_inverse, only : test_inverse_matrix implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_inverse", test_inverse_matrix) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_inv fortran-lang-stdlib-0ede301/test/linalg/test_linalg_expm.fypp0000664000175000017500000001170415135654166024654 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test the matrix exponential. module test_linalg_expm use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_constants use stdlib_linalg_constants use stdlib_linalg, only: expm, eye, norm, matrix_exp use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR implicit none (type,external) public :: test_expm_computation contains ! gcc-15 bugfix utility subroutine add_test(tests,new_test) type(unittest_type), allocatable, intent(inout) :: tests(:) type(unittest_type), intent(in) :: new_test integer :: n type(unittest_type), allocatable :: new_tests(:) if (allocated(tests)) then n = size(tests) else n = 0 end if allocate(new_tests(n+1)) if (n>0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test !> Exponent of matrix tests subroutine test_expm_computation(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) call add_test(tests,new_unittest("expm",test_expm)) call add_test(tests,new_unittest("error_handling_expm",test_error_handling_expm)) end subroutine test_expm_computation !> Matrix exponential with analytic expression. subroutine test_expm(error) type(error_type), allocatable, intent(out) :: error ! Problem dimension. integer(ilp), parameter :: n = 5, m = 6 ! Test matrix. integer(ilp) :: i, j #:for rk,rt,ri in RC_KINDS_TYPES block ${rt}$ :: A(n, n), E(n, n), Eref(n, n) real(${rk}$) :: err ! Initialize matrix. A = zero_${rk}$ do i = 1, n-1 A(i, i+1) = m*one_${rk}$ enddo ! Reference with analytical exponential Eref = eye(n, mold=one_${rk}$) do i = 1, n-1 do j = 1, n-i Eref(i, i+j) = Eref(i, i+j-1)*m/j enddo enddo ! Compute matrix exponential. E = expm(A) ! Check result. err = norm(Eref - E, "inf") print *, err , (n**2)*epsilon(1.0_${rk}$) call check(error, err < (n**2)*epsilon(1.0_${rk}$), "Analytical matrix exponential.") if (allocated(error)) return end block #:endfor end subroutine test_expm !> Test error handler. subroutine test_error_handling_expm(error) type(error_type), allocatable, intent(out) :: error ! Problem dimension. integer(ilp), parameter :: n = 5, m = 6 ! Test matrix. type(linalg_state_type) :: err integer(ilp) :: i #:for rk,rt,ri in RC_KINDS_TYPES block ${rt}$ :: A(n, n), E(n, n) ! Initialize matrix. A = zero_${rk}$ do i = 1, n-1 A(i, i+1) = m*one_${rk}$ enddo ! Compute matrix exponential. call matrix_exp(A, E, order=-1, err=err) ! Check result. call check(error, err%error(), "Negative Pade order") if (allocated(error)) return call matrix_exp(A, order=-1, err=err) ! Check result. call check(error, err%error(), "Negative Pade order") if (allocated(error)) return ! Compute matrix exponential. call matrix_exp(A, E(:n, :n-1), err=err) ! Check result. call check(error, err%error(), "Invalid matrix size") if (allocated(error)) return ! Compute matrix exponential. call matrix_exp(A(:n, :n-1), err=err) ! Check result. call check(error, err%error(), "Invalid matrix size") if (allocated(error)) return end block #:endfor end subroutine test_error_handling_expm end module test_linalg_expm program test_expm use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_expm, only : test_expm_computation implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_expm", test_expm_computation) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_expm fortran-lang-stdlib-0ede301/test/linalg/test_linalg_solve_iterative.fypp0000664000175000017500000002143315135654166027107 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set MATRIX_TYPES = ["dense", "CSR"] ! Test linear system iterative solvers module test_linalg_solve_iterative use stdlib_kinds use stdlib_sparse use stdlib_linalg_iterative_solvers use testdrive, only: error_type, check, new_unittest, unittest_type implicit none private public :: test_linear_systems contains subroutine test_linear_systems(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) tests = [ new_unittest("stdlib_solve_cg",test_stdlib_solve_cg), & new_unittest("stdlib_solve_pcg",test_stdlib_solve_pcg), & new_unittest("stdlib_solve_bicgstab",test_stdlib_solve_bicgstab), & new_unittest("stdlib_solve_bicgstab_nonsymmetric",test_stdlib_solve_bicgstab_nonsymmetric) ] end subroutine test_linear_systems subroutine test_stdlib_solve_cg(error) type(error_type), allocatable, intent(out) :: error #:for k, t, s in R_KINDS_TYPES block ${t}$, parameter :: tol = 1000*epsilon(0.0_${k}$) ${t}$ :: A(2,2) = reshape([${t}$ :: 4, 1, & 1, 3], [2,2]) ${t}$ :: x(2), load(2), xref(2) xref = [0.0909, 0.6364] x = real( [2,1] , kind = ${k}$ ) ! initial guess load = real( [1,2] , kind = ${k}$ ) ! load vector call stdlib_solve_cg(A, load, x) call check(error, norm2(x-xref)<1.e-4_${k}$, 'error in conjugate gradient solver') if (allocated(error)) return end block #:endfor end subroutine test_stdlib_solve_cg subroutine test_stdlib_solve_pcg(error) type(error_type), allocatable, intent(out) :: error #:for k, t, s in R_KINDS_TYPES block ${t}$, parameter :: tol = 1000*epsilon(0.0_${k}$) ${t}$ :: A(5,5) = reshape([${t}$ :: 1, -1, 0, 0, 0,& -1, 2, -1, 0, 0,& 0, -1, 2, -1, 0,& 0, 0, -1, 2, -1,& 0, 0, 0, -1, 1] , [5,5]) ${t}$ :: x(5), load(5), xref(5) logical(int8) :: dirichlet(5) xref = [0.0_${k}$,2.5_${k}$,5.0_${k}$,2.5_${k}$,0.0_${k}$] x = 0.0_${k}$ load = real( [0,0,5,0,0] , kind = ${k}$ ) ! load vector dirichlet = .false._int8 dirichlet([1,5]) = .true._int8 call stdlib_solve_pcg(A, load, x, di=dirichlet, rtol=1.e-6_${k}$) call check(error, norm2(x-xref)<1.e-6_${k}$*norm2(xref), 'error in preconditionned conjugate gradient solver') if (allocated(error)) return end block #:endfor end subroutine test_stdlib_solve_pcg subroutine test_stdlib_solve_bicgstab(error) type(error_type), allocatable, intent(out) :: error #:for k, t, s in R_KINDS_TYPES ! Test 1: Simple non-symmetric matrix (same as SciPy example) block ${t}$, parameter :: tol = 1000*epsilon(0.0_${k}$) ${t}$ :: A(4,4) = reshape([${t}$ :: 4, 2, 0, 1, & 3, 0, 0, 2, & 0, 1, 1, 1, & 0, 2, 1, 0], [4,4]) ${t}$ :: x(4), load(4), xref(4) ! Reference solution computed with high precision xref = [12.5_${k}$, -17._${k}$, 23.5_${k}$, -24.5_${k}$] x = 0.0_${k}$ ! initial guess load = [-1.0_${k}$, -0.5_${k}$, -1.0_${k}$, 2.0_${k}$] ! load vector call stdlib_solve_bicgstab(A, load, x, rtol=1.e-10_${k}$) call check(error, norm2(x-xref) 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_solve_iterative fortran-lang-stdlib-0ede301/test/linalg/test_linalg_eigenvalues.fypp0000664000175000017500000003271215135654166026214 0ustar alastairalastair#:include "common.fypp" ! Test eigenvalues and eigendecompositions module test_linalg_eigenvalues use stdlib_linalg_constants use stdlib_linalg_state use stdlib_linalg, only: eig, eigh, eigvals, eigvalsh, diag, eye use testdrive, only: error_type, check, new_unittest, unittest_type implicit none (type,external) private public :: test_eig_eigh contains !> SVD tests subroutine test_eig_eigh(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in REAL_KINDS_TYPES call add_test(tests,new_unittest("test_eig_real_${ri}$",test_eig_real_${ri}$)) call add_test(tests,new_unittest("test_eigvals_identity_${ri}$",test_eigvals_identity_${ri}$)) call add_test(tests,new_unittest("test_eigvals_diagonal_B_${ri}$",test_eigvals_diagonal_B_${ri}$)) call add_test(tests,new_unittest("test_eigvals_nondiagonal_B_${ri}$",test_eigvals_nondiagonal_B_${ri}$)) call add_test(tests,new_unittest("test_eigh_real_${ri}$",test_eigh_real_${ri}$)) #: endfor #:for ck,ct,ci in CMPLX_KINDS_TYPES call add_test(tests,new_unittest("test_eig_complex_${ci}$",test_eig_complex_${ci}$)) call add_test(tests,new_unittest("test_eig_generalized_complex_${ci}$",test_eigvals_generalized_complex_${ci}$)) call add_test(tests,new_unittest("test_eig_issue_927_${ci}$",test_issue_927_${ci}$)) #: endfor end subroutine test_eig_eigh !> Simple real matrix eigenvalues #:for rk,rt,ri in REAL_KINDS_TYPES subroutine test_eig_real_${ri}$(error) type(error_type), allocatable, intent(out) :: error !> Reference solution real(${rk}$), parameter :: zero = 0.0_${rk}$ real(${rk}$), parameter :: two = 2.0_${rk}$ real(${rk}$), parameter :: sqrt2o2 = sqrt(two)*0.5_${rk}$ real(${rk}$), parameter :: tol = sqrt(epsilon(zero)) !> Local variables type(linalg_state_type) :: state ${rt}$ :: A(3,3),B(2,2) complex(${rk}$) :: lambda(3),Bvec(2,2),Bres(2,2) !> Matrix with real eigenvalues A = reshape([1,0,0, & 0,2,0, & 0,0,3],[3,3]) call eig(A,lambda,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, all(aimag(lambda)==zero.and.real(lambda,kind=${rk}$)==[1,2,3]),'expected results') if (allocated(error)) return !> Matrix with complex eigenvalues B = transpose(reshape([1, -1, & 1, 1],[2,2])) !> Expected right eigenvectors Bres(1,1:2) = sqrt2o2 Bres(2,1) = cmplx(zero,-sqrt2o2,kind=${rk}$) Bres(2,2) = cmplx(zero,+sqrt2o2,kind=${rk}$) call eig(B,lambda,right=Bvec,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, all(abs(Bres-Bvec)<=tol),'expected results') if (allocated(error)) return end subroutine test_eig_real_${ri}$ ! Symmetric matrix eigenvalues subroutine test_eigh_real_${ri}$(error) type(error_type), allocatable, intent(out) :: error !> Reference solution real(${rk}$), parameter :: zero = 0.0_${rk}$ real(${rk}$), parameter :: tol = sqrt(epsilon(zero)) real(${rk}$), parameter :: A(4,4) = reshape([6,3,1,5, & 3,0,5,1, & 1,5,6,2, & 5,1,2,2],[4,4]) !> Local variables real(${rk}$) :: Amat(4,4),lambda(4),vect(4,4),Av(4,4),lv(4,4) type(linalg_state_type) :: state Amat = A call eigh(Amat,lambda,vect,err=state) Av = matmul(A,vect) lv = matmul(vect,diag(lambda)) call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, all(abs(Av-lv)<=tol*abs(Av)),'expected results') if (allocated(error)) return !> Test functional versions: no state interface lambda = eigvalsh(Amat) !> State interface lambda = eigvalsh(Amat,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return !> Functional version, lower A Amat = A lambda = eigvalsh(Amat,upper_a=.false.,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return end subroutine test_eigh_real_${ri}$ !> Test generalized eigenvalue problem with B = identity subroutine test_eigvals_identity_${ri}$(error) type(error_type), allocatable, intent(out) :: error !> Reference solution real(${rk}$), parameter :: zero = 0.0_${rk}$ real(${rk}$), parameter :: tol = sqrt(epsilon(zero)) !> Local variables type(linalg_state_type) :: state ${rt}$ :: A(3, 3), B(3, 3) complex(${rk}$) :: lambda(3) !> Matrix A A = reshape([3, 0, 0, & 0, 5, 0, & 0, 0, 7], [3, 3]) !> Identity matrix B B = reshape([1, 0, 0, & 0, 1, 0, & 0, 0, 1], [3, 3]) !> Generalized problem lambda = eigvals(A, B, err=state) call check(error, state%ok(), state%print()) if (allocated(error)) return call check(error, all(abs(real(lambda,${rk}$) - [3, 5, 7]) <= tol), & 'expected results for B=identity') if (allocated(error)) return end subroutine test_eigvals_identity_${ri}$ !> Test generalized eigenvalue problem with B = diagonal subroutine test_eigvals_diagonal_B_${ri}$(error) type(error_type), allocatable, intent(out) :: error !> Reference solution real(${rk}$), parameter :: zero = 0.0_${rk}$ real(${rk}$), parameter :: tol = sqrt(epsilon(zero)) !> Local variables type(linalg_state_type) :: state ${rt}$ :: A(3, 3), B(3, 3) complex(${rk}$) :: lambda(3) !> Matrix A A = reshape([3, 0, 0, & 0, 5, 0, & 0, 0, 7], [3, 3]) !> Diagonal matrix B B = reshape([2, 0, 0, & 0, 4, 0, & 0, 0, 8], [3, 3]) lambda = eigvals(A, B, err=state) call check(error, state%ok(), state%print()) if (allocated(error)) return call check(error, all(abs(real(lambda,${rk}$) - [1.5_${rk}$, 1.25_${rk}$, 0.875_${rk}$]) <= tol),& 'expected results for B=diagonal') if (allocated(error)) return end subroutine test_eigvals_diagonal_B_${ri}$ !> Test generalized eigenvalue problem with B = non-diagonal subroutine test_eigvals_nondiagonal_B_${ri}$(error) type(error_type), allocatable, intent(out) :: error !> Reference solution real(${rk}$), parameter :: zero = 0.0_${rk}$ real(${rk}$), parameter :: tol = 1.0e-3_${rk}$ !> Local variables type(linalg_state_type) :: state ${rt}$ :: A(3, 3), B(3, 3) complex(${rk}$) :: lambda(3) !> Matrix A A = reshape([3, 2, 0, & 2, 5, 1, & 0, 1, 7], [3, 3]) !> Non-diagonal matrix B B = reshape([2, 1, 0, & 1, 3, 0, & 0, 0, 4], [3, 3]) lambda = eigvals(A, B, err=state) call check(error, state%ok(), state%print()) if (allocated(error)) return call check(error, all(abs(lambda - [1.1734_${rk}$, 1.5766_${rk}$, 2.0000_${rk}$]) <= tol), 'expected results for B=nondiagonal') print *, 'lambda ',lambda print *, 'expected ',[1.0,2.5,3.75] if (allocated(error)) return end subroutine test_eigvals_nondiagonal_B_${ri}$ #:endfor !> Simple complex matrix eigenvalues #:for ck,ct,ci in CMPLX_KINDS_TYPES subroutine test_eig_complex_${ci}$(error) type(error_type), allocatable, intent(out) :: error !> Reference solution real(${ck}$), parameter :: zero = 0.0_${ck}$ real(${ck}$), parameter :: two = 2.0_${ck}$ real(${ck}$), parameter :: sqrt2o2 = sqrt(two)*0.5_${ck}$ real(${ck}$), parameter :: tol = sqrt(epsilon(zero)) ${ct}$, parameter :: cone = (1.0_${ck}$,0.0_${ck}$) ${ct}$, parameter :: cimg = (0.0_${ck}$,1.0_${ck}$) ${ct}$, parameter :: czero = (0.0_${ck}$,0.0_${ck}$) !> Local vaciables type(linalg_state_type) :: state ${ct}$ :: A(2,2),lambda(2),Avec(2,2),Ares(2,2),lres(2) !> Matcix with real eigenvalues A = transpose(reshape([ cone, cimg, & -cimg, cone], [2,2])) call eig(A,lambda,right=Avec,err=state) !> Expected eigenvalues and eigenvectors lres(1) = two lres(2) = zero !> Eigenvectors may vary: do not use for error Ares(1,1) = cmplx(zero,sqrt2o2,kind=${ck}$) Ares(1,2) = cmplx(sqrt2o2,zero,kind=${ck}$) Ares(2,1) = cmplx(sqrt2o2,zero,kind=${ck}$) Ares(2,2) = cmplx(zero,sqrt2o2,kind=${ck}$) call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, all(abs(lambda-lres)<=tol), 'results match expected') if (allocated(error)) return end subroutine test_eig_complex_${ci}$ !> Complex generalized eigenvalue problem with eigvals subroutine test_eigvals_generalized_complex_${ci}$(error) type(error_type), allocatable, intent(out) :: error !> Reference solution real(${ck}$), parameter :: zero = 0.0_${ck}$ real(${ck}$), parameter :: one = 1.0_${ck}$ real(${ck}$), parameter :: tol = sqrt(epsilon(zero)) ${ct}$, parameter :: cone = (one, zero) ${ct}$, parameter :: cimg = (zero, one) ${ct}$, parameter :: czero = (zero, zero) !> Local variables type(linalg_state_type) :: state ${ct}$ :: A(2,2), B(2,2), lambda(2), lres(2) !> Matrices A and B for the generalized problem A * x = lambda * B * x A = transpose(reshape([ cone, cimg, & -cimg, cone], [2,2])) B = transpose(reshape([ cone, czero, & czero, cone], [2,2])) lambda = eigvals(A, B, err=state) !> Expected eigenvalues lres(1) = czero lres(2) = 2*cone call check(error, state%ok(), state%print()) if (allocated(error)) return call check(error, all(abs(lambda - lres) <= tol) .or. & all(abs(lambda - lres([2,1])) <= tol), 'results match expected') if (allocated(error)) return end subroutine test_eigvals_generalized_complex_${ci}$ ! Generalized eigenvalues should not crash subroutine test_issue_927_${ci}$(error) type(error_type), allocatable, intent(out) :: error ${ct}$ :: A_Z(3,3),S_Z(3,3),vecs_r(3,3),eigs(3) real(${ck}$) :: A_D(3,3),S_D(3,3) type(linalg_state_type) :: state integer :: i ! Set matrix A_Z = reshape( [ [1, 6, 3], & [9, 2, 1], & [8, 3, 4] ], [3,3] ) S_Z = eye(3, mold=0.0_${ck}$) A_D = real(A_Z) S_D = real(S_Z) call eig(A_D,S_D,eigs,right=vecs_r,err=state) call check(error, state%ok(), 'test issue 927 (${ct}$): '//state%print()) if (allocated(error)) return call eig(A_Z,S_Z,eigs,right=vecs_r,err=state) !Fails call check(error, state%ok(), 'test issue 927 (${ct}$): '//state%print()) if (allocated(error)) return end subroutine test_issue_927_${ci}$ #:endfor ! gcc-15 bugfix utility subroutine add_test(tests,new_test) type(unittest_type), allocatable, intent(inout) :: tests(:) type(unittest_type), intent(in) :: new_test integer :: n type(unittest_type), allocatable :: new_tests(:) if (allocated(tests)) then n = size(tests) else n = 0 end if allocate(new_tests(n+1)) if (n>0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_eigenvalues program test_eigenvalues use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_eigenvalues, only : test_eig_eigh implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_eigenvalues", test_eig_eigh) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_eigenvalues fortran-lang-stdlib-0ede301/test/linalg/test_linalg_mnorm.fypp0000664000175000017500000001603415135654166025034 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES module test_linalg_mnorm use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg_constants use stdlib_linalg, only: mnorm, linalg_state_type use stdlib_linalg_state, only: linalg_state_type implicit none (type,external) contains !> Matrix norm tests subroutine test_matrix_norms(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in RC_KINDS_TYPES call add_test(tests,new_unittest("test_matrix_norms_${ri}$",test_matrix_norms_${ri}$)) #:for rank in range(3, MAXRANK) call add_test(tests,new_unittest("test_mnorm_${ri}$_${rank}$d",test_mnorm_${ri}$_${rank}$d)) #:endfor #:endfor end subroutine test_matrix_norms #:for rk,rt,ri in RC_KINDS_TYPES !> Test 1-norm, 2-norm (Euclidean), and infinity norm for ${rt}$ matrices subroutine test_matrix_norms_${ri}$(error) type(error_type), allocatable, intent(out) :: error integer(ilp) :: i integer(ilp), parameter :: mtx_dim = 5 real(${rk}$), parameter :: tol = 10*sqrt(epsilon(0.0_${rk}$)) ${rt}$, allocatable :: A(:,:) type(linalg_state_type) :: err allocate(A(mtx_dim,mtx_dim)) ! Initialize matrix with small values to avoid overflow A = reshape([(0.01_${rk}$*(i-mtx_dim/2_ilp), i=1_ilp,mtx_dim*mtx_dim)], [mtx_dim,mtx_dim]) ! 1-norm (Maximum absolute column sum) call check(error, abs(mnorm(A, '1', err) - maxval(sum(abs(A), dim=1),1)) < tol*mnorm(A, '1', err), & 'Matrix 1-norm does not match expected value') if (allocated(error)) return ! 2-norm (Frobenius norm) call check(error, abs(mnorm(A, err=err) - sqrt(sum(A**2))) < tol*mnorm(A, err=err), & 'Matrix Frobenius norm does not match expected value') if (allocated(error)) return ! Inf-norm (Maximum absolute row sum) call check(error, abs(mnorm(A, 'Inf', err) - maxval(sum(abs(A), dim=2),1)) < tol*mnorm(A, 'Inf', err), & 'Matrix Infinity norm does not match expected value') if (allocated(error)) return end subroutine test_matrix_norms_${ri}$ #:for rank in range(3, MAXRANK) !> Test N-D norms subroutine test_mnorm_${ri}$_${rank}$d(error) type(error_type), allocatable, intent(out) :: error integer(ilp) :: i,j,k,l,dim1,dim2,dim(2),dim_sizes(2),ptr(${rank}$) character(3), parameter :: orders(*) = ['1 ','2 ','fro','inf'] integer(ilp), parameter :: ndim = ${rank}$ integer(ilp), parameter :: n = 2_ilp**ndim integer(ilp), parameter :: dims(*) = [(dim1, dim1=1,ndim)] real(${rk}$), parameter :: tol = 10*sqrt(epsilon(0.0_${rk}$)) real(${rk}$) :: one_nrm real(${rk}$), allocatable :: bnrm${ranksuffix(rank-2)}$ ${rt}$, allocatable :: a(:), b${ranksuffix(rank)}$, one_mat(:,:) character(:), allocatable :: order character(64) :: msg allocate(a(n), b${fixedranksuffix(rank,2)}$) ! Init as a range,but with small elements such that all power norms will ! never overflow, even in single precision a = [(0.01_${rk}$*(j-n/2_ilp), j=1_ilp,n)] b = reshape(a, shape(b)) ! Test norm as collapsed around dimensions do k = 1, size(orders) order = trim(orders(k)) do dim1 = 1, ndim do dim2 = 1, ndim if (dim1==dim2) cycle dim = [dim1,dim2] dim_sizes = [size(b,dim1,kind=ilp),size(b,dim2,kind=ilp)] ! Get norms collapsed on these dims bnrm = mnorm(b,order,dim) ! Assert size write(msg,"('dim=[',i0,',',i0,'] order=',a,' ${rk}$ norm returned wrong shape')") dim, order call check(error,all(shape(bnrm)==pack(shape(b),dims/=dim1 .and. dims/=dim2) ), trim(msg)) if (allocated(error)) return ! Assert some matrix results: check that those on same index i.e. (l,l,l,:,l,l,:) etc. ! are equal to the corresponding 2d-array result do l = 1, minval(shape(b)) ptr = l allocate(one_mat(dim_sizes(1),dim_sizes(2))) do j = 1, dim_sizes(2) ptr(dim(2)) = j do i = 1, dim_sizes(1) ptr(dim(1)) = i one_mat(i,j) = b(${loop_array_variables('ptr',rank)}$) end do end do one_nrm = mnorm(one_mat,order) write(msg,"('dim=[',i0,',',i0,'] order=',a,' ${rk}$ ',i0,'-th norm is wrong')") dim, order, l call check(error, abs(one_nrm-bnrm(${fixedranksuffix(rank-2,'l')}$))0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_mnorm program test_mnorm use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_mnorm, only : test_matrix_norms implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("matrix_norms", test_matrix_norms) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_mnorm fortran-lang-stdlib-0ede301/test/linalg/test_blas_lapack.fypp0000664000175000017500000001451115135654166024610 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES module test_blas_lapack use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_kinds, only: sp, dp, xdp, qp, int8, int16, int32, int64 use stdlib_linalg, only: eye use stdlib_linalg_blas use stdlib_linalg_lapack implicit none contains !> Collect all exported unit tests subroutine collect_blas_lapack(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & #:for k1, t1 in REAL_KINDS_TYPES new_unittest("test_gemv${t1[0]}$${k1}$", test_gemv${t1[0]}$${k1}$), & new_unittest("test_getri${t1[0]}$${k1}$", test_getri${t1[0]}$${k1}$), & #:endfor new_unittest("test_idamax", test_idamax), & new_unittest("test_external_blas",external_blas_test), & new_unittest("test_external_lapack",external_lapack_test) & ] end subroutine collect_blas_lapack #:for k1, t1 in REAL_KINDS_TYPES subroutine test_gemv${t1[0]}$${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$ :: A(3,3),x(3),y(3),ylap(3),yintr(3),alpha,beta real(${k1}$), parameter :: tol = 1000 * epsilon(1.0_${k1}$) call random_number(alpha) call random_number(beta) call random_number(A) call random_number(x) call random_number(y) ylap = y call gemv('No transpose',size(A,1),size(A,2),alpha,A,size(A,1),x,1,beta,ylap,1) yintr = alpha*matmul(A,x)+beta*y call check(error, sum(abs(ylap - yintr)) < tol, & "blas vs. intrinsics axpy: sum() < tol failed") if (allocated(error)) return end subroutine test_gemv${t1[0]}$${k1}$ ! Find matrix inverse from LU decomposition subroutine test_getri${t1[0]}$${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(ilp), parameter :: n = 3 ${t1}$ :: A(n,n) ${t1}$,allocatable :: work(:) integer(ilp) :: ipiv(n),info,lwork,nb real(${k1}$), parameter :: tol = 1000 * epsilon(1.0_${k1}$) A = eye(n) ! Factorize matrix (overwrite result) call getrf(size(A,1),size(A,2),A,size(A,1),ipiv,info) call check(error, info==0, "lapack getrf returned info/=0") if (allocated(error)) return ! Get optimal worksize (returned in work(1)) (apply 2% safety parameter) nb = stdlib_ilaenv(1,'${t1[0]}$getri',' ',n,-1,-1,-1) lwork = nint(1.02*n*nb,kind=ilp) allocate (work(lwork)) ! Invert matrix call getri(n,a,n,ipiv,work,lwork,info) call check(error, info==0, "lapack getri returned info/=0") if (allocated(error)) return call check(error, sum(abs(A - eye(3))) < tol, & "lapack eye inversion: tolerance check failed") if (allocated(error)) return end subroutine test_getri${t1[0]}$${k1}$ #:endfor ! Return subroutine test_idamax(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(ilp), parameter :: n = 5 integer(ilp) :: imax real(dp) :: x(n) x = [1,2,3,4,5] imax = stdlib_idamax(n,x,1) call check(error, imax==5, "blas idamax returned wrong location") end subroutine test_idamax !> Test availability of the external BLAS interface subroutine external_blas_test(error) !> Error handling type(error_type), allocatable, intent(out) :: error #ifdef STDLIB_EXTERNAL_BLAS interface subroutine saxpy(n,sa,sx,incx,sy,incy) import sp,ilp implicit none(type,external) real(sp), intent(in) :: sa,sx(*) integer(ilp), intent(in) :: incx,incy,n real(sp), intent(inout) :: sy(*) end subroutine saxpy end interface integer(ilp), parameter :: n = 5, inc=1 real(sp) :: a,x(n),y(n) x = 1.0_sp y = 2.0_sp a = 3.0_sp call saxpy(n,a,x,inc,y,inc) call check(error, all(abs(y-5.0_sp) Test availability of the external BLAS interface subroutine external_lapack_test(error) !> Error handling type(error_type), allocatable, intent(out) :: error #ifdef STDLIB_EXTERNAL_LAPACK interface subroutine dgetrf( m, n, a, lda, ipiv, info ) import dp,ilp implicit none(type,external) integer(ilp), intent(out) :: info,ipiv(*) integer(ilp), intent(in) :: lda,m,n real(dp), intent(inout) :: a(lda,*) end subroutine dgetrf end interface integer(ilp), parameter :: n = 3 real(dp) :: A(n,n) integer(ilp) :: ipiv(n),info A = eye(n) info = 123 ! Factorize matrix call dgetrf(n,n,A,n,ipiv,info) call check(error, info==0, "dgetrf: check result") if (allocated(error)) return #else call skip_test(error, "Not using an external LAPACK") #endif end subroutine external_lapack_test end module test_blas_lapack program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_blas_lapack, only : collect_blas_lapack implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("blas_lapack", collect_blas_lapack) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/linalg/test_linalg_lstsq.fypp0000664000175000017500000001361015135654166025047 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test least squares solver module test_linalg_least_squares use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg_constants use stdlib_linalg, only: lstsq,solve_lstsq use stdlib_linalg_state, only: linalg_state_type implicit none (type,external) private public :: test_least_squares contains !> Solve sample least squares problems subroutine test_least_squares(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) call add_test(tests,new_unittest("issue_823",test_issue_823)) #:for rk,rt,ri in REAL_KINDS_TYPES call add_test(tests,new_unittest("least_squares_${ri}$",test_lstsq_one_${ri}$)) call add_test(tests,new_unittest("least_squares_randm_${ri}$",test_lstsq_random_${ri}$)) #:endfor end subroutine test_least_squares #:for rk,rt,ri in REAL_KINDS_TYPES !> Simple polynomial fit subroutine test_lstsq_one_${ri}$(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp) :: rank !> Example scattered data ${rt}$, parameter :: x(*) = real([1.0, 2.5, 3.5, 4.0, 5.0, 7.0, 8.5], ${rk}$) ${rt}$, parameter :: y(*) = real([0.3, 1.1, 1.5, 2.0, 3.2, 6.6, 8.6], ${rk}$) ${rt}$, parameter :: ab(*) = real([0.20925829, 0.12013861], ${rk}$) ${rt}$ :: M(size(x),2),p(2) ! Coefficient matrix for polynomial y = a + b*x**2 M(:,1) = x**0 M(:,2) = x**2 ! Find polynomial p = lstsq(M,y,rank=rank,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, all(abs(p-ab)<1.0e-4_${rk}$), 'data converged') if (allocated(error)) return call check(error, rank==2, 'matrix rank == 2') if (allocated(error)) return end subroutine test_lstsq_one_${ri}$ !> Fit from random array subroutine test_lstsq_random_${ri}$(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp), parameter :: n = 12, m = 3 real :: Arnd(n,m),xrnd(m) ${rt}$, allocatable :: x(:) ${rt}$ :: xsol(m),y(n),A(n,m) ! Random coefficient matrix and solution call random_number(Arnd) call random_number(xrnd) ! Compute rhs A = real(Arnd,${rk}$) xsol = real(xrnd,${rk}$) y = matmul(A,xsol) ! Find polynomial x = lstsq(A,y,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return ! Check size call check(error,size(x)==m) if (allocated(error)) return call check(error, all(abs(x-xsol)<1.0e-4_${rk}$), 'data converged') if (allocated(error)) return end subroutine test_lstsq_random_${ri}$ #:endfor ! Test issue #823 subroutine test_issue_823(error) type(error_type), allocatable, intent(out) :: error ! Dimension of the problem. integer(ilp), parameter :: n = 42 ! Data for the least-squares problem. complex(dp) :: A(n+1, n), b(n+1), x_true(n), x_lstsq(n) ! Internal variables. real(dp), allocatable :: tmp(:, :, :), tmp_vec(:, :) ! Error handler type(linalg_state_type) :: state ! Zero-out data. A = 0.0_dp b = 0.0_dp x_lstsq = 0.0_dp allocate(tmp(n+1, n, 2), tmp_vec(n, 2), source=0.0_dp) ! Generate a random complex least-squares problem of size (n+1, n). call random_number(tmp) call random_number(tmp_vec) A = cmplx(tmp(:, :, 1), tmp(:, :, 2), kind=dp) x_true = cmplx(tmp_vec(:, 1), tmp_vec(:, 2), kind=dp) b = matmul(A, x_true) ! Solve the lstsq problem. call solve_lstsq(A, b, x_lstsq, err=state) ! Check that no segfault occurred call check(error,state%ok(),'issue 823 returned '//state%print()) if (allocated(error)) return ! Check that least squares are verified call check(error,all(abs(x_true-x_lstsq)0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_least_squares program test_lstsq use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_least_squares, only : test_least_squares implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_least_squares", test_least_squares) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_lstsq fortran-lang-stdlib-0ede301/test/linalg/test_linalg_pseudoinverse.fypp0000664000175000017500000002264015135654166026577 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test Moore-Penrose pseudo matrix inverse module test_linalg_pseudoinverse use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg use stdlib_linalg_constants implicit none (type,external) private public :: test_pseudoinverse_matrix contains !> Matrix pseudo-inversion tests subroutine test_pseudoinverse_matrix(tests) !> Collertion of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in REAL_KINDS_TYPES call add_test(tests,new_unittest("${ri}$_eye_pseudoinverse",test_${ri}$_eye_pseudoinverse)) #:endfor #:for rk,rt,ri in RC_KINDS_TYPES call add_test(tests,new_unittest("${ri}$_square_pseudoinverse",test_${ri}$_square_pseudoinverse)) call add_test(tests,new_unittest("${ri}$_tall_pseudoinverse",test_${ri}$_tall_pseudoinverse)) call add_test(tests,new_unittest("${ri}$_wide_pseudoinverse",test_${ri}$_wide_pseudoinverse)) call add_test(tests,new_unittest("${ri}$_singular_pseudoinverse",test_${ri}$_singular_pseudoinverse)) #:endfor end subroutine test_pseudoinverse_matrix !> Invert identity matrix #:for rk,rt,ri in REAL_KINDS_TYPES subroutine test_${ri}$_eye_pseudoinverse(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp) :: i,j integer(ilp), parameter :: n = 15_ilp real(${rk}$), parameter :: tol = 1000*sqrt(epsilon(0.0_${rk}$)) ${rt}$ :: a(n,n),inva(n,n) do concurrent (i=1:n,j=1:n) a(i,j) = merge(1.0_${rk}$,0.0_${rk}$,i==j) end do !> Invert funrtion inva = pinv(a,err=state) call check(error,state%ok(),'${ri}$ pseudoinverse (eye, function): '//state%print()) if (allocated(error)) return call check(error,all(abs(a-inva) Inverse subroutine call pseudoinvert(a,inva,err=state) call check(error,state%ok(),'${ri}$ pseudoinverse (eye, subroutine): '//state%print()) if (allocated(error)) return call check(error,all(abs(a-inva) Operator inva = .pinv.a call check(error,all(abs(a-inva) Test edge case: square matrix subroutine test_${ri}$_square_pseudoinverse(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp) :: failed integer(ilp), parameter :: n = 10 real(${rk}$), parameter :: tol = 1000*sqrt(epsilon(0.0_${rk}$)) ${rt}$ :: a(n, n), inva(n, n) #:if rt.startswith('complex') real(${rk}$) :: rea(n, n, 2) call random_number(rea) a = cmplx(rea(:, :, 1), rea(:, :, 2), kind=${rk}$) #:else call random_number(a) #:endif inva = pinv(a, err=state) call check(error,state%ok(),'${ri}$ pseudoinverse (square): '//state%print()) if (allocated(error)) return failed = count(abs(a - matmul(a, matmul(inva, a))) > tol) call check(error,failed==0,'${ri}$ pseudoinverse (square, convergence): '//state%print()) if (allocated(error)) return failed = count(abs(inva - matmul(inva, matmul(a, inva))) > tol) call check(error,failed==0,'${ri}$ pseudoinverse (square, convergence): '//state%print()) if (allocated(error)) return end subroutine test_${ri}$_square_pseudoinverse !> Test edge case: tall matrix subroutine test_${ri}$_tall_pseudoinverse(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp) :: failed integer(ilp), parameter :: m = 20, n = 10 real(${rk}$), parameter :: tol = 1000*sqrt(epsilon(0.0_${rk}$)) ${rt}$ :: a(m, n), inva(n, m) #:if rt.startswith('complex') real(${rk}$) :: rea(m, n, 2) call random_number(rea) a = cmplx(rea(:, :, 1), rea(:, :, 2), kind=${rk}$) #:else call random_number(a) #:endif inva = pinv(a, err=state) call check(error,state%ok(),'${ri}$ pseudoinverse (tall): '//state%print()) if (allocated(error)) return failed = count(abs(a - matmul(a, matmul(inva, a))) > tol) call check(error,failed==0,'${ri}$ pseudoinverse (tall, convergence): '//state%print()) if (allocated(error)) return failed = count(abs(inva - matmul(inva, matmul(a, inva))) > tol) call check(error,failed==0,'${ri}$ pseudoinverse (tall, convergence): '//state%print()) if (allocated(error)) return end subroutine test_${ri}$_tall_pseudoinverse !> Test edge case: wide matrix subroutine test_${ri}$_wide_pseudoinverse(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp) :: failed integer(ilp), parameter :: m = 10, n = 20 real(${rk}$), parameter :: tol = 1000*sqrt(epsilon(0.0_${rk}$)) ${rt}$ :: a(m, n), inva(n, m) #:if rt.startswith('complex') real(${rk}$) :: rea(m, n, 2) call random_number(rea) a = cmplx(rea(:, :, 1), rea(:, :, 2), kind=${rk}$) #:else call random_number(a) #:endif inva = pinv(a, err=state) call check(error,state%ok(),'${ri}$ pseudoinverse (wide): '//state%print()) if (allocated(error)) return failed = count(abs(a - matmul(a, matmul(inva, a))) > tol) call check(error,failed==0,'${ri}$ pseudoinverse (wide, convergence): '//state%print()) if (allocated(error)) return failed = count(abs(inva - matmul(inva, matmul(a, inva))) > tol) call check(error,failed==0,'${ri}$ pseudoinverse (wide, convergence): '//state%print()) if (allocated(error)) return end subroutine test_${ri}$_wide_pseudoinverse !> Test edge case: singular matrix subroutine test_${ri}$_singular_pseudoinverse(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp) :: failed integer(ilp), parameter :: n = 10 real(${rk}$), parameter :: tol = 1000*sqrt(epsilon(0.0_${rk}$)) ${rt}$ :: a(n, n), inva(n, n) #:if rt.startswith('complex') real(${rk}$) :: rea(n, n, 2) call random_number(rea) a = cmplx(rea(:, :, 1), rea(:, :, 2), kind=${rk}$) #:else call random_number(a) #:endif ! Make the matrix singular a(:, 1) = a(:, 2) inva = pinv(a, err=state) call check(error,state%ok(),'${ri}$ pseudoinverse (singular): '//state%print()) if (allocated(error)) return failed = count(abs(a - matmul(a, matmul(inva, a))) > tol) call check(error,failed==0,'${ri}$ pseudoinverse (singular, convergence): '//state%print()) if (allocated(error)) return failed = count(abs(inva - matmul(inva, matmul(a, inva))) > tol) call check(error,failed==0,'${ri}$ pseudoinverse (singular, convergence): '//state%print()) if (allocated(error)) return end subroutine test_${ri}$_singular_pseudoinverse #:endfor ! gcc-15 bugfix utility subroutine add_test(tests,new_test) type(unittest_type), allocatable, intent(inout) :: tests(:) type(unittest_type), intent(in) :: new_test integer :: n type(unittest_type), allocatable :: new_tests(:) if (allocated(tests)) then n = size(tests) else n = 0 end if allocate(new_tests(n+1)) if (n>0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_pseudoinverse program test_inv use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_pseudoinverse, only : test_pseudoinverse_matrix implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_pseudoinverse", test_pseudoinverse_matrix) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_inv fortran-lang-stdlib-0ede301/test/linalg/CMakeLists.txt0000664000175000017500000000265215135654166023160 0ustar alastairalastairset( fppFiles "test_linalg.fypp" "test_linalg_eigenvalues.fypp" "test_linalg_solve.fypp" "test_linalg_inverse.fypp" "test_linalg_pseudoinverse.fypp" "test_linalg_lstsq.fypp" "test_linalg_constrained_lstsq.fypp" "test_linalg_norm.fypp" "test_linalg_mnorm.fypp" "test_linalg_determinant.fypp" "test_linalg_qr.fypp" "test_linalg_pivoting_qr.fypp" "test_linalg_schur.fypp" "test_linalg_solve_iterative.fypp" "test_linalg_svd.fypp" "test_linalg_matrix_property_checks.fypp" "test_linalg_sparse.fypp" "test_linalg_specialmatrices.fypp" "test_linalg_cholesky.fypp" "test_linalg_expm.fypp" ) # Preprocessed files to contain preprocessor directives -> .F90 set( cppFiles "test_blas_lapack.fypp" ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) fypp_f90pp("${fyppFlags}" "${cppFiles}" outPreprocFiles) ADDTEST(linalg) ADDTEST(linalg_cholesky) ADDTEST(linalg_determinant) ADDTEST(linalg_eigenvalues) ADDTEST(linalg_expm) ADDTEST(linalg_matrix_property_checks) ADDTEST(linalg_inverse) ADDTEST(linalg_pseudoinverse) ADDTEST(linalg_norm) ADDTEST(linalg_mnorm) ADDTEST(linalg_solve) ADDTEST(linalg_lstsq) ADDTEST(linalg_constrained_lstsq) ADDTEST(linalg_qr) ADDTEST(linalg_pivoting_qr) ADDTEST(linalg_schur) if (STDLIB_LINALG_ITERATIVE) ADDTEST(linalg_solve_iterative) endif() ADDTEST(linalg_svd) ADDTEST(linalg_sparse) if (STDLIB_SPECIALMATRICES) ADDTEST(linalg_specialmatrices) endif() ADDTESTPP(blas_lapack) fortran-lang-stdlib-0ede301/test/linalg/test_linalg_pivoting_qr.fypp0000664000175000017500000002743015135654166026247 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test QR factorization module test_linalg_pivoting_qr use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg_constants use stdlib_linalg_state, only: LINALG_VALUE_ERROR,linalg_state_type use stdlib_linalg, only: qr, qr_space, mnorm use ieee_arithmetic, only: ieee_value,ieee_quiet_nan implicit none (type,external) public :: test_pivoting_qr_factorization contains !> QR factorization tests subroutine test_pivoting_qr_factorization(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in RC_KINDS_TYPES call add_test(tests,new_unittest("pivoting_qr_random_tall_matrix_${ri}$",test_pivoting_qr_random_tall_matrix_${ri}$)) call add_test(tests,new_unittest("pivoting_qr_random_rank_deficient_${ri}$",test_pivoting_qr_random_rank_deficient_${ri}$)) call add_test(tests,new_unittest("pivoting_qr_random_wide_matrix_${ri}$",test_pivoting_qr_random_wide_matrix_${ri}$)) #:endfor end subroutine test_pivoting_qr_factorization !> QR factorization of a random matrix #:for rk,rt,ri in RC_KINDS_TYPES subroutine test_pivoting_qr_random_tall_matrix_${ri}$(error) use stdlib_linalg, only: hermitian type(error_type), allocatable, intent(out) :: error integer(ilp), parameter :: m = 15_ilp integer(ilp), parameter :: n = 4_ilp integer(ilp), parameter :: k = min(m,n) real(${rk}$), parameter :: tol = 100*sqrt(epsilon(0.0_${rk}$)) ${rt}$ :: a(m,n),aorig(m,n),q(m,m),r(m,n),qred(m,k),rred(k,n),qerr(m,6),rerr(6,n) real(${rk}$) :: rea(m,n),ima(m,n) integer(ilp) :: pivots(n), i, j integer(ilp) :: lwork ${rt}$, allocatable :: work(:) type(linalg_state_type) :: state call random_number(rea) #:if rt.startswith('complex') call random_number(ima) a = cmplx(rea,ima,kind=${rk}$) #:else a = rea #:endif aorig = a ! 1) QR factorization with full matrices. Input NaNs to be sure Q and R are OK on return q = ieee_value(0.0_${rk}$,ieee_quiet_nan) r = ieee_value(0.0_${rk}$,ieee_quiet_nan) call qr(a, q, r, pivots, err=state) ! Check return code call check(error,state%ok(),state%print()) if (allocated(error)) return ! Check solution call check(error, all(abs(a(:, pivots)-matmul(q,r))0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_pivoting_qr program test_pivoting_qr use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_pivoting_qr, only : test_pivoting_qr_factorization implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_pivoting_qr", test_pivoting_qr_factorization) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_pivoting_qr fortran-lang-stdlib-0ede301/test/linalg/test_linalg_schur.fypp0000664000175000017500000002110215135654166025020 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test Schur decomposition module test_linalg_schur use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg_constants use stdlib_linalg_state, only: LINALG_VALUE_ERROR,linalg_state_type use stdlib_linalg, only: schur,schur_space use ieee_arithmetic, only: ieee_value,ieee_quiet_nan implicit none (type,external) public :: test_schur_decomposition contains !> schur decomposition tests subroutine test_schur_decomposition(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in RC_KINDS_TYPES call add_test(tests,new_unittest("schur_api_${ri}$",test_schur_api_${ri}$)) call add_test(tests,new_unittest("schur_random_${ri}$",test_schur_random_${ri}$)) call add_test(tests,new_unittest("schur_symmetric_${ri}$",test_schur_symmetric_${ri}$)) #:endfor end subroutine test_schur_decomposition !> schur decomposition of a random matrix #:for rk,rt,ri in RC_KINDS_TYPES subroutine test_schur_api_${ri}$(error) type(error_type), allocatable, intent(out) :: error integer(ilp), parameter :: n = 15_ilp integer(ilp) :: lwork complex(${rk}$) :: eigs(n) ${rt}$, dimension(n,n) :: a,t,z ${rt}$, allocatable :: storage(:) #:if 'complex' in rt real(${rk}$) :: rea(n,n),ima(n,n) #:endif type(linalg_state_type) :: state #:if 'complex' in rt call random_number(rea) call random_number(ima) a = cmplx(rea,ima,kind=${rk}$) #:else call random_number(a) #:endif ! Test simple API call schur(a,t,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return ! Test output transformation matrix call schur(a,t,z,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return ! Test output eigenvalues call schur(a,t,eigvals=eigs,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return ! Test storage query call schur_space(a,lwork,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return ! Test with user-defined storage allocate(storage(lwork)) call schur(a,t,eigvals=eigs,storage=storage,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return end subroutine test_schur_api_${ri}$ subroutine test_schur_random_${ri}$(error) type(error_type), allocatable, intent(out) :: error integer(ilp), parameter :: n = 3_ilp real(${rk}$), parameter :: rtol = 1.0e-4_${rk}$ real(${rk}$), parameter :: eps = sqrt(epsilon(0.0_${rk}$)) integer(ilp) :: lwork ${rt}$, allocatable :: storage(:) ${rt}$, dimension(n,n) :: a,t,z,aorig #:if 'complex' in rt real(${rk}$), dimension(n,n) :: a_re,a_im #:endif type(linalg_state_type) :: state #:if 'complex' in rt call random_number(a_re) call random_number(a_im) a = cmplx(a_re,a_im,kind=${rk}$) #:else call random_number(a) #:endif aorig = a ! 1) Run schur (standard) call schur(a,t,z,err=state) ! Check return code call check(error,state%ok(),state%print()) if (allocated(error)) return ! Check solution call check(error, all(schur_error(a,z,t)<=max(rtol*abs(a),eps)), & 'converged solution (${rt}$)') if (allocated(error)) return ! 2) Run schur (overwrite A) call schur(a,t,z,overwrite_a=.true.,err=state) ! Check return code call check(error,state%ok(),state%print()) if (allocated(error)) return ! Check solution call check(error, all(schur_error(aorig,z,t)<=max(rtol*abs(aorig),eps)), & 'converged solution (${rt}$ - overwrite A)') if (allocated(error)) return ! 3) Use working storage a = aorig call schur_space(a,lwork,err=state) ! Check return code call check(error,state%ok(),state%print()) if (allocated(error)) return allocate(storage(lwork)) call schur(a,t,z,storage=storage,err=state) ! Check return code call check(error,state%ok(),state%print()) if (allocated(error)) return ! Check solution call check(error, all(schur_error(a,z,t)<=max(rtol*abs(a),eps)), & 'converged solution (${rt}$ - external storage)') if (allocated(error)) return contains pure function schur_error(a,z,t) result(err) ${rt}$, intent(in), dimension(:,:) :: a,z,t real(${rk}$), dimension(size(a,1),size(a,2)) :: err #:if rt.startswith('real') err = abs(matmul(matmul(z,t),transpose(z)) - a) #:else err = abs(matmul(matmul(z,t),conjg(transpose(z))) - a) #:endif end function schur_error end subroutine test_schur_random_${ri}$ !> Test symmetric matrix (real eigenvalues) subroutine test_schur_symmetric_${ri}$(error) type(error_type), allocatable, intent(out) :: error integer(ilp), parameter :: n = 3_ilp real(${rk}$), parameter :: rtol = 1.0e-4_${rk}$ real(${rk}$), parameter :: eps = sqrt(epsilon(0.0_${rk}$)) real(${rk}$) :: reigs(n) ${rt}$, dimension(n,n) :: a, t, z type(linalg_state_type) :: state ! Define a symmetric 3x3 matrix with real eigenvalues a = reshape([ 3, 1, 0, & 1, 3, 1, & 0, 1, 3], shape=[n, n]) ! Return real eigenvalues (Should trigger an error if they have an imaginary part) call schur(a, t, z, eigvals=reigs, err=state) ! Check return code call check(error, state%ok(), state%print()) if (allocated(error)) return ! Check solution call check(error, all(schur_error(a, z, t) <= max(rtol * abs(a), eps)), & 'converged solution (real symmetric, real eigs)') if (allocated(error)) return contains pure function schur_error(a,z,t) result(err) ${rt}$, intent(in), dimension(:,:) :: a,z,t real(${rk}$), dimension(size(a,1),size(a,2)) :: err #:if rt.startswith('real') err = abs(matmul(matmul(z,t),transpose(z)) - a) #:else err = abs(matmul(matmul(z,t),conjg(transpose(z))) - a) #:endif end function schur_error end subroutine test_schur_symmetric_${ri}$ #:endfor ! gcc-15 bugfix utility subroutine add_test(tests,new_test) type(unittest_type), allocatable, intent(inout) :: tests(:) type(unittest_type), intent(in) :: new_test integer :: n type(unittest_type), allocatable :: new_tests(:) if (allocated(tests)) then n = size(tests) else n = 0 end if allocate(new_tests(n+1)) if (n>0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_schur program test_schur use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_schur, only : test_schur_decomposition implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_schur", test_schur_decomposition) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_schur fortran-lang-stdlib-0ede301/test/linalg/test_linalg_specialmatrices.fypp0000664000175000017500000001417215135654166027055 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set KINDS_TYPES = R_KINDS_TYPES module test_specialmatrices use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_kinds use stdlib_linalg, only: hermitian use stdlib_linalg_state, only: linalg_state_type use stdlib_math, only: all_close use stdlib_specialmatrices implicit none contains !> Collect all exported unit tests subroutine collect_suite(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest('tridiagonal', test_tridiagonal), & new_unittest('tridiagonal error handling', test_tridiagonal_error_handling) & ] end subroutine subroutine test_tridiagonal(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for k1, t1, s1 in (KINDS_TYPES) block integer, parameter :: wp = ${k1}$ integer, parameter :: n = 5 type(tridiagonal_${s1}$_type) :: A ${t1}$, allocatable :: Amat(:,:), dl(:), dv(:), du(:) ${t1}$, allocatable :: x(:) ${t1}$, allocatable :: y1(:), y2(:) ${t1}$ :: alpha, beta integer :: i, j ${t1}$, parameter :: coeffs(3) = [-1.0_wp, 0.0_wp, 1.0_wp] ! Initialize matrix. allocate(dl(n-1), dv(n), du(n-1)) call random_number(dl) ; call random_number(dv) ; call random_number(du) A = tridiagonal(dl, dv, du) ; Amat = dense(A) ! Random vectors. allocate(x(n), source = 0.0_wp) ; call random_number(x) allocate(y1(n), source = 0.0_wp) ; allocate(y2(n), source=0.0_wp) ! Test y = A @ x y1 = matmul(Amat, x) ; call spmv(A, x, y2) call check(error, all_close(y1, y2), .true.) if (allocated(error)) return ! Test y = A.T @ x y1 = 0.0_wp ; y2 = 0.0_wp y1 = matmul(transpose(Amat), x) ; call spmv(A, x, y2, op="T") call check(error, all_close(y1, y2), .true.) if (allocated(error)) return #:if t1.startswith('complex') ! Test y = A.H @ x y1 = 0.0_wp ; y2 = 0.0_wp y1 = matmul(hermitian(Amat), x) ; call spmv(A, x, y2, op="H") call check(error, all_close(y1, y2), .true.) if (allocated(error)) return #:endif ! Test y = alpha * A @ x + beta * y for alpha,beta in {-1,0,1} do i = 1, 3 do j = 1,3 alpha = coeffs(i) beta = coeffs(j) y1 = 0.0_wp call random_number(y2) y1 = alpha * matmul(Amat, x) + beta * y2 call spmv(A, x, y2, alpha=alpha, beta=beta) call check(error, all_close(y1, y2), .true.) if (allocated(error)) return end do end do ! Test y = A @ x for random values of alpha and beta y1 = 0.0_wp call random_number(alpha) call random_number(beta) call random_number(y2) y1 = alpha * matmul(Amat, x) + beta * y2 call spmv(A, x, y2, alpha=alpha, beta=beta) call check(error, all_close(y1, y2), .true.) if (allocated(error)) return ! Test y = A.T @ x for random values of alpha and beta y1 = 0.0_wp call random_number(alpha) call random_number(beta) call random_number(y2) y1 = alpha * matmul(transpose(Amat), x) + beta * y2 call spmv(A, x, y2, alpha=alpha, beta=beta, op="T") call check(error, all_close(y1, y2), .true.) if (allocated(error)) return #:if t1.startswith('complex') ! Test y = A.H @ x for random values of alpha and beta y1 = 0.0_wp call random_number(alpha) call random_number(beta) call random_number(y2) y1 = alpha * matmul(transpose(conjg((Amat))), x) + beta * y2 call spmv(A, x, y2, alpha=alpha, beta=beta, op="H") call check(error, all_close(y1, y2), .true.) if (allocated(error)) return #:endif end block #:endfor end subroutine subroutine test_tridiagonal_error_handling(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for k1, t1, s1 in (KINDS_TYPES) block integer, parameter :: wp = ${k1}$ integer, parameter :: n = 5 type(tridiagonal_${s1}$_type) :: A ${t1}$, allocatable :: dl(:), dv(:), du(:) type(linalg_state_type) :: state integer :: i !> Test constructor from arrays. dl = [(1.0_wp, i = 1, n-2)] ; du = dl dv = [(2.0_wp, i = 1, n)] A = tridiagonal(dl, dv, du, state) call check(error, state%ok(), .false.) if (allocated(error)) return !> Test contructor from constants. A = tridiagonal(dl(1), dv(1), du(1), -n, state) call check(error, state%ok(), .false.) if (allocated(error)) return end block #:endfor end subroutine end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_specialmatrices, only : collect_suite implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("sparse", collect_suite) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/linalg/test_linalg_matrix_property_checks.fypp0000664000175000017500000006112215135654166030472 0ustar alastairalastair#:include "common.fypp" #:set RCI_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES + INT_KINDS_TYPES module test_linalg_matrix_property_checks use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_kinds, only: sp, dp, xdp, qp, int8, int16, int32, int64 use stdlib_linalg, only: is_square ,is_diagonal, is_symmetric, & is_skew_symmetric, is_hermitian, is_triangular, is_hessenberg implicit none real(sp), parameter :: sptol = 1000 * epsilon(1._sp) real(dp), parameter :: dptol = 1000 * epsilon(1._dp) #:if WITH_QP real(qp), parameter :: qptol = 1000 * epsilon(1._qp) #:endif #! create new list that contains test subroutine suffix (rsp, cdp, int64, etc.) #! alongside kind and type #:set RCI_KINDS_TYPES_SUFFIXES = [] #:for k1, t1 in RCI_KINDS_TYPES #:if t1[0] == 'i' #:set SUFFIX_START = '' #:else #:set SUFFIX_START = t1[0] #:endif $:RCI_KINDS_TYPES_SUFFIXES.append((k1,t1,SUFFIX_START+k1)) #:endfor contains !> Collect all exported unit tests subroutine collect_linalg_matrix_property_checks(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) #:set IMPLEMENTED_TESTS = ['is_square','is_diagonal','is_symmetric','is_skew_symmetric', & 'is_hermitian', 'is_triangular', 'is_hessenberg'] #:set NUM_TESTS = int(len(IMPLEMENTED_TESTS)*len(RCI_KINDS_TYPES_SUFFIXES)) #! set testsuite dynamically testsuite = [ & #:set TESTS_WRITTEN = 0 #:for cur_test in IMPLEMENTED_TESTS #:for k1, t1, s1 in RCI_KINDS_TYPES_SUFFIXES #! note that one has to use set directives to increment variable #:set TESTS_WRITTEN = TESTS_WRITTEN + 1 #! last test in list should not have comma #:if TESTS_WRITTEN < NUM_TESTS new_unittest("${cur_test}$_${s1}$", test_${cur_test}$_${s1}$), & #:else new_unittest("${cur_test}$_${s1}$", test_${cur_test}$_${s1}$) & #:endif #:endfor #:endfor ] end subroutine collect_linalg_matrix_property_checks !is_square #:for k1, t1, s1 in RCI_KINDS_TYPES_SUFFIXES subroutine test_is_square_${s1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #! variable sizes independent of type/kind ${t1}$ :: A_true(2,2), A_false(2,3) #! populate variables dependent on type/kind #:if s1[0] == 'r' A_true = reshape([1.,2.,3.,4.],[2,2]) A_false = reshape([1.,2.,3.,4.,5.,6.],[2,3]) #:elif s1[0] == 'c' A_true = reshape([cmplx(1.,0.),cmplx(2.,1.),cmplx(3.,0.),cmplx(4.,1.)],[2,2]) A_false = reshape([cmplx(1.,0.),cmplx(2.,1.),cmplx(3.,0.), & cmplx(4.,1.),cmplx(5.,0.),cmplx(6.,1.)],[2,3]) #:elif s1[0] == 'i' A_true = reshape([1,2,3,4],[2,2]) A_false = reshape([1,2,3,4,5,6],[2,3]) #:endif #! error check calls are type/kind independent call check(error, is_square(A_true), & "is_square(A_true) failed.") if (allocated(error)) return call check(error, (.not. is_square(A_false)), & "(.not. is_square(A_false)) failed.") if (allocated(error)) return end subroutine test_is_square_${s1}$ #:endfor !is_diagonal #:for k1, t1, s1 in RCI_KINDS_TYPES_SUFFIXES subroutine test_is_diagonal_${s1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #! variable sizes independent of type/kind ${t1}$ :: A_true_s(2,2), A_false_s(2,2) !square matrices ${t1}$ :: A_true_sf(2,3), A_false_sf(2,3) !short and fat matrices ${t1}$ :: A_true_ts(3,2), A_false_ts(3,2) !tall and skinny matrices #! populate variables dependent on type/kind #:if s1[0] == 'r' A_true_s = reshape([1.,0.,0.,4.],[2,2]) A_false_s = reshape([1.,0.,3.,4.],[2,2]) A_true_sf = reshape([1.,0.,0.,4.,0.,0.],[2,3]) A_false_sf = reshape([1.,0.,3.,4.,0.,0.],[2,3]) A_true_ts = reshape([1.,0.,0.,0.,5.,0.],[3,2]) A_false_ts = reshape([1.,0.,0.,0.,5.,6.],[3,2]) #:elif s1[0] == 'c' A_true_s = reshape([cmplx(1.,1.),cmplx(0.,0.), & cmplx(0.,0.),cmplx(4.,1.)],[2,2]) A_false_s = reshape([cmplx(1.,1.),cmplx(0.,0.), & cmplx(3.,1.),cmplx(4.,1.)],[2,2]) A_true_sf = reshape([cmplx(1.,1.),cmplx(0.,0.), & cmplx(0.,0.),cmplx(4.,1.), & cmplx(0.,0.),cmplx(0.,0.)],[2,3]) A_false_sf = reshape([cmplx(1.,1.),cmplx(0.,0.), & cmplx(3.,1.),cmplx(4.,1.), & cmplx(0.,0.),cmplx(0.,0.)],[2,3]) A_true_ts = reshape([cmplx(1.,1.),cmplx(0.,0.),cmplx(0.,0.), & cmplx(0.,0.),cmplx(5.,1.),cmplx(0.,0.)],[3,2]) A_false_ts = reshape([cmplx(1.,1.),cmplx(0.,0.),cmplx(0.,0.), & cmplx(0.,0.),cmplx(5.,1.),cmplx(6.,1.)],[3,2]) #:elif s1[0] == 'i' A_true_s = reshape([1,0,0,4],[2,2]) A_false_s = reshape([1,0,3,4],[2,2]) A_true_sf = reshape([1,0,0,4,0,0],[2,3]) A_false_sf = reshape([1,0,3,4,0,0],[2,3]) A_true_ts = reshape([1,0,0,0,5,0],[3,2]) A_false_ts = reshape([1,0,0,0,5,6],[3,2]) #:endif #! error check calls are type/kind independent call check(error, is_diagonal(A_true_s), & "is_diagonal(A_true_s) failed.") if (allocated(error)) return call check(error, (.not. is_diagonal(A_false_s)), & "(.not. is_diagonal(A_false_s)) failed.") if (allocated(error)) return call check(error, is_diagonal(A_true_sf), & "is_diagonal(A_true_sf) failed.") if (allocated(error)) return call check(error, (.not. is_diagonal(A_false_sf)), & "(.not. is_diagonal(A_false_sf)) failed.") if (allocated(error)) return call check(error, is_diagonal(A_true_ts), & "is_diagonal(A_true_ts) failed.") if (allocated(error)) return call check(error, (.not. is_diagonal(A_false_ts)), & "(.not. is_diagonal(A_false_ts)) failed.") if (allocated(error)) return end subroutine test_is_diagonal_${s1}$ #:endfor !is_symmetric #:for k1, t1, s1 in RCI_KINDS_TYPES_SUFFIXES subroutine test_is_symmetric_${s1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #! variable sizes independent of type/kind ${t1}$ :: A_true(2,2), A_false_1(2,2), A_false_2(3,2) #! populate variables dependent on type/kind #:if s1[0] == 'r' A_true = reshape([1.,2.,2.,4.],[2,2]) A_false_1 = reshape([1.,2.,3.,4.],[2,2]) A_false_2 = reshape([1.,2.,3.,2.,5.,6.],[3,2]) !nonsquare matrix #:elif s1[0] == 'c' A_true = reshape([cmplx(1.,1.),cmplx(2.,1.), & cmplx(2.,1.),cmplx(4.,1.)],[2,2]) A_false_1 = reshape([cmplx(1.,1.),cmplx(2.,1.), & cmplx(3.,1.),cmplx(4.,1.)],[2,2]) A_false_2 = reshape([cmplx(1.,1.),cmplx(2.,1.),cmplx(3.,1.), & cmplx(2.,1.),cmplx(5.,1.),cmplx(6.,2.)],[3,2]) !nonsquare matrix #:elif s1[0] == 'i' A_true = reshape([1,2,2,4],[2,2]) A_false_1 = reshape([1,2,3,4],[2,2]) A_false_2 = reshape([1,2,3,2,5,6],[3,2]) !nonsquare matrix #:endif #! error check calls are type/kind independent call check(error, is_symmetric(A_true), & "is_symmetric(A_true) failed.") if (allocated(error)) return call check(error, (.not. is_symmetric(A_false_1)), & "(.not. is_symmetric(A_false_1)) failed.") if (allocated(error)) return call check(error, (.not. is_symmetric(A_false_2)), & "(.not. is_symmetric(A_false_2)) failed.") if (allocated(error)) return end subroutine test_is_symmetric_${s1}$ #:endfor !is_skew_symmetric #:for k1, t1, s1 in RCI_KINDS_TYPES_SUFFIXES subroutine test_is_skew_symmetric_${s1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #! variable sizes independent of type/kind ${t1}$ :: A_true(2,2), A_false_1(2,2), A_false_2(3,2) #! populate variables dependent on type/kind #:if s1[0] == 'r' A_true = reshape([0.,2.,-2.,0.],[2,2]) A_false_1 = reshape([0.,2.,-3.,0.],[2,2]) A_false_2 = reshape([0.,2.,3.,-2.,0.,6.],[3,2]) !nonsquare matrix #:elif s1[0] == 'c' A_true = reshape([cmplx(0.,0.),cmplx(2.,1.), & -cmplx(2.,1.),cmplx(0.,0.)],[2,2]) A_false_1 = reshape([cmplx(0.,0.),cmplx(2.,1.), & -cmplx(3.,1.),cmplx(0.,0.)],[2,2]) A_false_2 = reshape([cmplx(0.,0.),cmplx(2.,1.),cmplx(3.,0.), & -cmplx(2.,1.),cmplx(0.,0.),cmplx(6.,0.)],[3,2]) !nonsquare matrix #:elif s1[0] == 'i' A_true = reshape([0,2,-2,0],[2,2]) A_false_1 = reshape([0,2,-3,0],[2,2]) A_false_2 = reshape([0,2,3,-2,0,6],[3,2]) !nonsquare matrix #:endif #! error check calls are type/kind independent call check(error, is_skew_symmetric(A_true), & "is_skew_symmetric(A_true) failed.") if (allocated(error)) return call check(error, (.not. is_skew_symmetric(A_false_1)), & "(.not. is_skew_symmetric(A_false_1)) failed.") if (allocated(error)) return call check(error, (.not. is_skew_symmetric(A_false_2)), & "(.not. is_skew_symmetric(A_false_2)) failed.") if (allocated(error)) return end subroutine test_is_skew_symmetric_${s1}$ #:endfor !is_hermitian #:for k1, t1, s1 in RCI_KINDS_TYPES_SUFFIXES subroutine test_is_hermitian_${s1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #! variable sizes independent of type/kind ${t1}$ :: A_true(2,2), A_false_1(2,2), A_false_2(3,2) #! populate variables dependent on type/kind #:if s1[0] == 'r' A_true = reshape([1.,2.,2.,4.],[2,2]) A_false_1 = reshape([1.,2.,3.,4.],[2,2]) A_false_2 = reshape([1.,2.,3.,2.,5.,6.],[3,2]) !nonsquare matrix #:elif s1[0] == 'c' A_true = reshape([cmplx(1.,0.),cmplx(2.,-1.), & cmplx(2.,1.),cmplx(4.,0.)],[2,2]) A_false_1 = reshape([cmplx(1.,0.),cmplx(2.,-1.), & cmplx(3.,1.),cmplx(4.,0.)],[2,2]) A_false_2 = reshape([cmplx(1.,0.),cmplx(2.,-1.),cmplx(3.,-1.), & cmplx(2.,1.),cmplx(5.,0.),cmplx(6.,-1.)],[3,2]) !nonsquare matrix #:elif s1[0] == 'i' A_true = reshape([1,2,2,4],[2,2]) A_false_1 = reshape([1,2,3,4],[2,2]) A_false_2 = reshape([1,2,3,2,5,6],[3,2]) !nonsquare matrix #:endif #! error check calls are type/kind independent call check(error, is_hermitian(A_true), & "is_hermitian(A_true) failed.") if (allocated(error)) return call check(error, (.not. is_hermitian(A_false_1)), & "(.not. is_hermitian(A_false_1)) failed.") if (allocated(error)) return call check(error, (.not. is_hermitian(A_false_2)), & "(.not. is_hermitian(A_false_2)) failed.") if (allocated(error)) return end subroutine test_is_hermitian_${s1}$ #:endfor !is_triangular #:for k1, t1, s1 in RCI_KINDS_TYPES_SUFFIXES subroutine test_is_triangular_${s1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #! variable sizes independent of type/kind ${t1}$ :: A_true_s_u(2,2), A_false_s_u(2,2) !square matrices (upper triangular) ${t1}$ :: A_true_sf_u(2,3), A_false_sf_u(2,3) !short and fat matrices ${t1}$ :: A_true_ts_u(3,2), A_false_ts_u(3,2) !tall and skinny matrices ${t1}$ :: A_true_s_l(2,2), A_false_s_l(2,2) !square matrices (lower triangular) ${t1}$ :: A_true_sf_l(2,3), A_false_sf_l(2,3) !short and fat matrices ${t1}$ :: A_true_ts_l(3,2), A_false_ts_l(3,2) !tall and skinny matrices #! populate variables dependent on type/kind #:if s1[0] == 'r' !upper triangular A_true_s_u = reshape([1.,0.,3.,4.],[2,2]) A_false_s_u = reshape([1.,2.,0.,4.],[2,2]) A_true_sf_u = reshape([1.,0.,3.,4.,0.,6.],[2,3]) A_false_sf_u = reshape([1.,2.,3.,4.,0.,6.],[2,3]) A_true_ts_u = reshape([1.,0.,0.,4.,5.,0.],[3,2]) A_false_ts_u = reshape([1.,0.,0.,4.,5.,6.],[3,2]) !lower triangular A_true_s_l = reshape([1.,2.,0.,4.],[2,2]) A_false_s_l = reshape([1.,0.,3.,4.],[2,2]) A_true_sf_l = reshape([1.,2.,0.,4.,0.,0.],[2,3]) A_false_sf_l = reshape([1.,2.,3.,4.,0.,0.],[2,3]) A_true_ts_l = reshape([1.,2.,3.,0.,5.,6.],[3,2]) A_false_ts_l = reshape([1.,2.,3.,4.,5.,6.],[3,2]) #:elif s1[0] == 'c' !upper triangular A_true_s_u = reshape([cmplx(1.,1.),cmplx(0.,0.), & cmplx(3.,1.),cmplx(4.,0.)],[2,2]) A_false_s_u = reshape([cmplx(1.,1.),cmplx(2.,0.), & cmplx(0.,0.),cmplx(4.,0.)],[2,2]) A_true_sf_u = reshape([cmplx(1.,1.),cmplx(0.,0.), & cmplx(3.,1.),cmplx(4.,0.), & cmplx(0.,0.),cmplx(6.,0.)],[2,3]) A_false_sf_u = reshape([cmplx(1.,1.),cmplx(2.,0.), & cmplx(3.,1.),cmplx(4.,0.), & cmplx(0.,0.),cmplx(6.,0.)],[2,3]) A_true_ts_u = reshape([cmplx(1.,1.),cmplx(0.,0.),cmplx(0.,0.), & cmplx(4.,0.),cmplx(5.,1.),cmplx(0.,0.)],[3,2]) A_false_ts_u = reshape([cmplx(1.,1.),cmplx(0.,0.),cmplx(0.,0.), & cmplx(4.,0.),cmplx(5.,1.),cmplx(6.,0.)],[3,2]) !lower triangular A_true_s_l = reshape([cmplx(1.,1.),cmplx(2.,0.), & cmplx(0.,0.),cmplx(4.,0.)],[2,2]) A_false_s_l = reshape([cmplx(1.,1.),cmplx(0.,0.), & cmplx(3.,1.),cmplx(4.,0.)],[2,2]) A_true_sf_l = reshape([cmplx(1.,1.),cmplx(2.,0.), & cmplx(0.,0.),cmplx(4.,0.), & cmplx(0.,0.),cmplx(0.,0.)],[2,3]) A_false_sf_l = reshape([cmplx(1.,1.),cmplx(2.,0.), & cmplx(3.,1.),cmplx(4.,0.), & cmplx(0.,0.),cmplx(0.,0.)],[2,3]) A_true_ts_l = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(3.,1.), & cmplx(0.,0.),cmplx(5.,1.),cmplx(6.,0.)],[3,2]) A_false_ts_l = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(3.,1.), & cmplx(4.,0.),cmplx(5.,1.),cmplx(6.,0.)],[3,2]) #:elif s1[0] == 'i' !upper triangular A_true_s_u = reshape([1,0,3,4],[2,2]) A_false_s_u = reshape([1,2,0,4],[2,2]) A_true_sf_u = reshape([1,0,3,4,0,6],[2,3]) A_false_sf_u = reshape([1,2,3,4,0,6],[2,3]) A_true_ts_u = reshape([1,0,0,4,5,0],[3,2]) A_false_ts_u = reshape([1,0,0,4,5,6],[3,2]) !lower triangular A_true_s_l = reshape([1,2,0,4],[2,2]) A_false_s_l = reshape([1,0,3,4],[2,2]) A_true_sf_l = reshape([1,2,0,4,0,0],[2,3]) A_false_sf_l = reshape([1,2,3,4,0,0],[2,3]) A_true_ts_l = reshape([1,2,3,0,5,6],[3,2]) A_false_ts_l = reshape([1,2,3,4,5,6],[3,2]) #:endif #! error check calls are type/kind independent !upper triangular checks call check(error, is_triangular(A_true_s_u,'u'), & "is_triangular(A_true_s_u,'u') failed.") if (allocated(error)) return call check(error, (.not. is_triangular(A_false_s_u,'u')), & "(.not. is_triangular(A_false_s_u,'u')) failed.") if (allocated(error)) return call check(error, is_triangular(A_true_sf_u,'u'), & "is_triangular(A_true_sf_u,'u') failed.") if (allocated(error)) return call check(error, (.not. is_triangular(A_false_sf_u,'u')), & "(.not. is_triangular(A_false_sf_u,'u')) failed.") if (allocated(error)) return call check(error, is_triangular(A_true_ts_u,'u'), & "is_triangular(A_true_ts_u,'u') failed.") if (allocated(error)) return call check(error, (.not. is_triangular(A_false_ts_u,'u')), & "(.not. is_triangular(A_false_ts_u,'u')) failed.") if (allocated(error)) return !lower triangular checks call check(error, is_triangular(A_true_s_l,'l'), & "is_triangular(A_true_s_l,'l') failed.") if (allocated(error)) return call check(error, (.not. is_triangular(A_false_s_l,'l')), & "(.not. is_triangular(A_false_s_l,'l')) failed.") if (allocated(error)) return call check(error, is_triangular(A_true_sf_l,'l'), & "is_triangular(A_true_sf_l,'l') failed.") if (allocated(error)) return call check(error, (.not. is_triangular(A_false_sf_l,'l')), & "(.not. is_triangular(A_false_sf_l,'l')) failed.") if (allocated(error)) return call check(error, is_triangular(A_true_ts_l,'l'), & "is_triangular(A_true_ts_l,'l') failed.") if (allocated(error)) return call check(error, (.not. is_triangular(A_false_ts_l,'l')), & "(.not. is_triangular(A_false_ts_l,'l')) failed.") if (allocated(error)) return end subroutine test_is_triangular_${s1}$ #:endfor !is_hessenberg #:for k1, t1, s1 in RCI_KINDS_TYPES_SUFFIXES subroutine test_is_hessenberg_${s1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #! variable sizes independent of type/kind ${t1}$ :: A_true_s_u(3,3), A_false_s_u(3,3) !square matrices (upper hessenberg) ${t1}$ :: A_true_sf_u(3,4), A_false_sf_u(3,4) !short and fat matrices ${t1}$ :: A_true_ts_u(4,3), A_false_ts_u(4,3) !tall and skinny matrices ${t1}$ :: A_true_s_l(3,3), A_false_s_l(3,3) !square matrices (lower hessenberg) ${t1}$ :: A_true_sf_l(3,4), A_false_sf_l(3,4) !short and fat matrices ${t1}$ :: A_true_ts_l(4,3), A_false_ts_l(4,3) !tall and skinny matrices #! populate variables dependent on type/kind #:if s1[0] == 'r' !upper hessenberg A_true_s_u = reshape([1.,2.,0.,4.,5.,6.,7.,8.,9.],[3,3]) A_false_s_u = reshape([1.,2.,3.,4.,5.,6.,7.,8.,9.],[3,3]) A_true_sf_u = reshape([1.,2.,0.,4.,5.,6.,7.,8.,9.,10.,11.,12.],[3,4]) A_false_sf_u = reshape([1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.],[3,4]) A_true_ts_u = reshape([1.,2.,0.,0.,5.,6.,7.,0.,9.,10.,11.,12.],[4,3]) A_false_ts_u = reshape([1.,2.,3.,0.,5.,6.,7.,0.,9.,10.,11.,12.],[4,3]) !lower hessenberg A_true_s_l = reshape([1.,2.,3.,4.,5.,6.,0.,8.,9.],[3,3]) A_false_s_l = reshape([1.,2.,3.,4.,5.,6.,7.,8.,9.],[3,3]) A_true_sf_l = reshape([1.,2.,3.,4.,5.,6.,0.,8.,9.,0.,0.,12.],[3,4]) A_false_sf_l = reshape([1.,2.,3.,4.,5.,6.,0.,8.,9.,0.,11.,12.],[3,4]) A_true_ts_l = reshape([1.,2.,3.,4.,5.,6.,7.,8.,0.,10.,11.,12.],[4,3]) A_false_ts_l = reshape([1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.],[4,3]) #:elif s1[0] == 'c' !upper hessenberg A_true_s_u = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(0.,0.), & cmplx(4.,0.),cmplx(5.,1.),cmplx(6.,0.), & cmplx(7.,1.),cmplx(8.,0.),cmplx(9.,1.)],[3,3]) A_false_s_u = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(3.,1.), & cmplx(4.,0.),cmplx(5.,1.),cmplx(6.,0.), & cmplx(7.,1.),cmplx(8.,0.),cmplx(9.,1.)],[3,3]) A_true_sf_u = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(0.,0.), & cmplx(4.,0.),cmplx(5.,1.),cmplx(6.,0.), & cmplx(7.,1.),cmplx(8.,0.),cmplx(9.,1.), & cmplx(10.,0.),cmplx(11.,1.),cmplx(12.,0.)],[3,4]) A_false_sf_u = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(3.,1.), & cmplx(4.,0.),cmplx(5.,1.),cmplx(6.,0.), & cmplx(7.,1.),cmplx(8.,0.),cmplx(9.,1.), & cmplx(10.,0.),cmplx(11.,1.),cmplx(12.,0.)],[3,4]) A_true_ts_u = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(0.,0.),cmplx(0.,0.), & cmplx(5.,1.),cmplx(6.,0.),cmplx(7.,1.),cmplx(0.,0.), & cmplx(9.,1.),cmplx(10.,0.),cmplx(11.,1.),cmplx(12.,0.)],[4,3]) A_false_ts_u = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(3.,1.),cmplx(0.,0.), & cmplx(5.,1.),cmplx(6.,0.),cmplx(7.,1.),cmplx(0.,0.), & cmplx(9.,1.),cmplx(10.,0.),cmplx(11.,1.),cmplx(12.,0.)],[4,3]) !lower hessenberg A_true_s_l = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(3.,1.), & cmplx(4.,0.),cmplx(5.,1.),cmplx(6.,0.), & cmplx(0.,0.),cmplx(8.,0.),cmplx(9.,1.)],[3,3]) A_false_s_l = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(3.,1.), & cmplx(4.,0.),cmplx(5.,1.),cmplx(6.,0.), & cmplx(7.,1.),cmplx(8.,0.),cmplx(9.,1.)],[3,3]) A_true_sf_l = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(3.,1.), & cmplx(4.,0.),cmplx(5.,1.),cmplx(6.,0.), & cmplx(0.,0.),cmplx(8.,0.),cmplx(9.,1.), & cmplx(0.,0.),cmplx(0.,0.),cmplx(12.,0.)],[3,4]) A_false_sf_l = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(3.,1.), & cmplx(4.,0.),cmplx(5.,1.),cmplx(6.,0.), & cmplx(0.,0.),cmplx(8.,0.),cmplx(9.,1.), & cmplx(0.,0.),cmplx(11.,1.),cmplx(12.,0.)],[3,4]) A_true_ts_l = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(3.,1.),cmplx(4.,0.), & cmplx(5.,1.),cmplx(6.,0.),cmplx(7.,1.),cmplx(8.,0.), & cmplx(0.,0.),cmplx(10.,0.),cmplx(11.,1.),cmplx(12.,0.)],[4,3]) A_false_ts_l = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(3.,1.),cmplx(4.,0.), & cmplx(5.,1.),cmplx(6.,0.),cmplx(7.,1.),cmplx(8.,0.), & cmplx(9.,1.),cmplx(10.,0.),cmplx(11.,1.),cmplx(12.,0.)],[4,3]) #:elif s1[0] == 'i' !upper hessenberg A_true_s_u = reshape([1,2,0,4,5,6,7,8,9],[3,3]) A_false_s_u = reshape([1,2,3,4,5,6,7,8,9],[3,3]) A_true_sf_u = reshape([1,2,0,4,5,6,7,8,9,10,11,12],[3,4]) A_false_sf_u = reshape([1,2,3,4,5,6,7,8,9,10,11,12],[3,4]) A_true_ts_u = reshape([1,2,0,0,5,6,7,0,9,10,11,12],[4,3]) A_false_ts_u = reshape([1,2,3,0,5,6,7,0,9,10,11,12],[4,3]) !lower hessenberg A_true_s_l = reshape([1,2,3,4,5,6,0,8,9],[3,3]) A_false_s_l = reshape([1,2,3,4,5,6,7,8,9],[3,3]) A_true_sf_l = reshape([1,2,3,4,5,6,0,8,9,0,0,12],[3,4]) A_false_sf_l = reshape([1,2,3,4,5,6,0,8,9,0,11,12],[3,4]) A_true_ts_l = reshape([1,2,3,4,5,6,7,8,0,10,11,12],[4,3]) A_false_ts_l = reshape([1,2,3,4,5,6,7,8,9,10,11,12],[4,3]) #:endif #! error check calls are type/kind independent !upper hessenberg checks call check(error, is_hessenberg(A_true_s_u,'u'), & "is_hessenberg(A_true_s_u,'u') failed.") call check(error, (.not. is_hessenberg(A_false_s_u,'u')), & "(.not. is_hessenberg(A_false_s_u,'u')) failed.") call check(error, is_hessenberg(A_true_sf_u,'u'), & "is_hessenberg(A_true_sf_u,'u') failed.") call check(error, (.not. is_hessenberg(A_false_sf_u,'u')), & "(.not. is_hessenberg(A_false_sf_u,'u')) failed.") call check(error, is_hessenberg(A_true_ts_u,'u'), & "is_hessenberg(A_true_ts_u,'u') failed.") call check(error, (.not. is_hessenberg(A_false_ts_u,'u')), & "(.not. is_hessenberg(A_false_ts_u,'u')) failed.") !lower hessenberg checks call check(error, is_hessenberg(A_true_s_l,'l'), & "is_hessenberg(A_true_s_l,'l') failed.") call check(error, (.not. is_hessenberg(A_false_s_l,'l')), & "(.not. is_hessenberg(A_false_s_l,'l')) failed.") call check(error, is_hessenberg(A_true_sf_l,'l'), & "is_hessenberg(A_true_sf_l,'l') failed.") call check(error, (.not. is_hessenberg(A_false_sf_l,'l')), & "(.not. is_hessenberg(A_false_sf_l,'l')) failed.") call check(error, is_hessenberg(A_true_ts_l,'l'), & "is_hessenberg(A_true_ts_l,'l') failed.") call check(error, (.not. is_hessenberg(A_false_ts_l,'l')), & "(.not. is_hessenberg(A_false_ts_l,'l')) failed.") end subroutine test_is_hessenberg_${s1}$ #:endfor end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_matrix_property_checks, only : collect_linalg_matrix_property_checks implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_matrix_property_checks", collect_linalg_matrix_property_checks) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/linalg/test_linalg_sparse.fypp0000664000175000017500000003355715135654166025212 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set KINDS_TYPES = R_KINDS_TYPES module test_sparse_spmv use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_kinds, only: sp, dp, xdp, qp, int8, int16, int32, int64 use stdlib_sparse implicit none contains !> Collect all exported unit tests subroutine collect_suite(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest('coo', test_coo), & new_unittest('coo2ordered', test_coo2ordered), & new_unittest('csr', test_csr), & new_unittest('csc', test_csc), & new_unittest('ell', test_ell), & new_unittest('sellc', test_sellc), & new_unittest('symmetries', test_symmetries), & new_unittest('diagonal', test_diagonal), & new_unittest('add_get_values', test_add_get_values) & ] end subroutine subroutine test_coo(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for k1, t1, s1 in (KINDS_TYPES) block integer, parameter :: wp = ${k1}$ type(COO_${s1}$_type) :: COO ${t1}$, allocatable :: dense(:,:) ${t1}$, allocatable :: vec_x(:) ${t1}$, allocatable :: vec_y1(:), vec_y2(:) allocate( dense(4,5) , source = & reshape(real([9,4, 0,4, & 0,7, 8,0, & 0,0,-1,5, & 0,0, 8,6, & -3,0, 0,0],kind=wp),[4,5]) ) call dense2coo( dense , COO ) allocate( vec_x(5) , source = 1._wp ) allocate( vec_y1(4) , source = 0._wp ) allocate( vec_y2(4) , source = 0._wp ) vec_y1 = matmul( dense, vec_x ) call check(error, all(vec_y1 == real([6,11,15,15],kind=wp)) ) if (allocated(error)) return call spmv( COO, vec_x, vec_y2 ) call check(error, all(vec_y1 == vec_y2) ) if (allocated(error)) return ! Test in-place transpose vec_y1 = 1._wp call spmv( COO, vec_y1, vec_x, op=sparse_op_transpose ) call check(error, all(vec_x == real([17,15,4,14,-3],kind=wp)) ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_coo2ordered(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(COO_sp_type) :: COO integer :: row(12), col(12) real :: data(12) row = [1,1,1,2,2,3,2,2,2,3,3,4] col = [2,3,4,3,4,4,3,4,5,4,5,5] data = 1.0 call from_ijv(COO,row,col,data) call coo2ordered(COO,sort_data=.true.) call check(error, COO%nnz < 12 .and. COO%nnz == 9 ) if (allocated(error)) return call check(error, all(COO%data==[1,1,1,2,2,1,2,1,1]) ) if (allocated(error)) return call check(error, all(COO%index(1,:)==[1,1,1,2,2,2,3,3,4]) ) if (allocated(error)) return call check(error, all(COO%index(2,:)==[2,3,4,3,4,5,4,5,5]) ) if (allocated(error)) return end subroutine subroutine test_csr(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for k1, t1, s1 in (KINDS_TYPES) block integer, parameter :: wp = ${k1}$ type(CSR_${s1}$_type) :: CSR ${t1}$, allocatable :: vec_x(:) ${t1}$, allocatable :: vec_y(:) call CSR%malloc(4,5,10) CSR%data(:) = real([9,-3,4,7,8,-1,8,4,5,6],kind=wp) CSR%col(:) = [1,5,1,2,2,3,4,1,3,4] CSR%rowptr(:) = [1,3,5,8,11] allocate( vec_x(5) , source = 1._wp ) allocate( vec_y(4) , source = 0._wp ) call spmv( CSR, vec_x, vec_y ) call check(error, all(vec_y == real([6,11,15,15],kind=wp)) ) if (allocated(error)) return ! Test in-place transpose vec_y = 1._wp call spmv( CSR, vec_y, vec_x, op=sparse_op_transpose ) call check(error, all(vec_x == real([17,15,4,14,-3],kind=wp)) ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_csc(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for k1, t1, s1 in (KINDS_TYPES) block integer, parameter :: wp = ${k1}$ type(CSC_${s1}$_type) :: CSC ${t1}$, allocatable :: vec_x(:) ${t1}$, allocatable :: vec_y(:) call CSC%malloc(4,5,10) CSC%data(:) = real([9,4,4,7,8,-1,5,8,6,-3],kind=wp) CSC%row(:) = [1,2,4,2,3,3,4,3,4,1] CSC%colptr(:) = [1,4,6,8,10,11] allocate( vec_x(5) , source = 1._wp ) allocate( vec_y(4) , source = 0._wp ) call spmv( CSC, vec_x, vec_y ) call check(error, all(vec_y == real([6,11,15,15],kind=wp)) ) if (allocated(error)) return ! Test in-place transpose vec_y = 1._wp call spmv( CSC, vec_y, vec_x, op=sparse_op_transpose ) call check(error, all(vec_x == real([17,15,4,14,-3],kind=wp)) ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_ell(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for k1, t1, s1 in (KINDS_TYPES) block integer, parameter :: wp = ${k1}$ type(ELL_${s1}$_type) :: ELL ${t1}$, allocatable :: vec_x(:) ${t1}$, allocatable :: vec_y(:) call ELL%malloc(4,5,3) ELL%data(1,1:3) = real([9,-3,0],kind=wp) ELL%data(2,1:3) = real([4,7,0],kind=wp) ELL%data(3,1:3) = real([8,-1,8],kind=wp) ELL%data(4,1:3) = real([4,5,6],kind=wp) ELL%index(1,1:3) = [1,5,0] ELL%index(2,1:3) = [1,2,0] ELL%index(3,1:3) = [2,3,4] ELL%index(4,1:3) = [1,3,4] allocate( vec_x(5) , source = 1._wp ) allocate( vec_y(4) , source = 0._wp ) call spmv( ELL, vec_x, vec_y ) call check(error, all(vec_y == real([6,11,15,15],kind=wp)) ) if (allocated(error)) return ! Test in-place transpose vec_y = 1._wp call spmv( ELL, vec_y, vec_x, op=sparse_op_transpose ) call check(error, all(vec_x == real([17,15,4,14,-3],kind=wp)) ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_sellc(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for k1, t1, s1 in (KINDS_TYPES) block integer, parameter :: wp = ${k1}$ type(SELLC_${s1}$_type) :: SELLC type(CSR_${s1}$_type) :: CSR ${t1}$, allocatable :: vec_x(:) ${t1}$, allocatable :: vec_y(:), vec_y2(:) integer :: i call CSR%malloc(6,6,17) ! 1 2 3 4 5 6 CSR%col = [ 1, 3, 4, & 2, 3, 5, 6, & 1, 2, 3, & 5, 6, & 4, 5, & 2, 5, 6] CSR%rowptr = [1,4,8,11,13,15,18] CSR%data = [(real(i,kind=wp),i=1,CSR%nnz)] call csr2sellc(CSR,SELLC,4) allocate( vec_x(6) , source = 1._wp ) allocate( vec_y(6) , source = 0._wp ) call spmv( SELLC, vec_x, vec_y ) call check(error, all(vec_y == real([6,22,27,23,27,48],kind=wp)) ) if (allocated(error)) return ! Test in-place transpose vec_x = real( [1,2,3,4,5,6] , kind=wp ) call spmv( CSR, vec_x, vec_y , op = sparse_op_transpose ) allocate( vec_y2(6) , source = 0._wp ) call spmv( SELLC, vec_x, vec_y2 , op = sparse_op_transpose ) call check(error, all(vec_y == vec_y2)) if (allocated(error)) return end block #:endfor end subroutine subroutine test_symmetries(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for k1, t1, s1 in (KINDS_TYPES) block integer, parameter :: wp = ${k1}$ type(COO_${s1}$_type) :: COO type(CSR_${s1}$_type) :: CSR type(ELL_${s1}$_type) :: ELL ${t1}$, allocatable :: dense(:,:) ${t1}$, allocatable :: vec_x(:) ${t1}$, allocatable :: vec_y1(:), vec_y2(:), vec_y3(:), vec_y4(:) allocate( vec_x(4) , source = 1._wp ) allocate( vec_y1(4) , source = 0._wp ) allocate( vec_y2(4) , source = 0._wp ) allocate( vec_y3(4) , source = 0._wp ) allocate( vec_y4(4) , source = 0._wp ) allocate( dense(4,4) , source = & reshape(real([1,0,0,0, & 2,1,0,0, & 0,2,1,0,& 0,0,2,1],kind=wp),[4,4]) ) call dense2coo( dense , COO ) COO%storage = sparse_upper call coo2csr(COO, CSR) call csr2ell(CSR, ELL) dense(2,1) = 2._wp; dense(3,2) = 2._wp; dense(4,3) = 2._wp vec_y1 = matmul( dense, vec_x ) call check(error, all(vec_y1 == [3,5,5,3]) ) if (allocated(error)) return call spmv( COO , vec_x, vec_y2 ) call check(error, all(vec_y1 == vec_y2) ) if (allocated(error)) return call spmv( CSR , vec_x, vec_y3 ) call check(error, all(vec_y1 == vec_y3) ) if (allocated(error)) return call spmv( ELL , vec_x, vec_y4 ) call check(error, all(vec_y1 == vec_y4) ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_diagonal(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for k1, t1, s1 in (KINDS_TYPES) block integer, parameter :: wp = ${k1}$ ${t1}$, allocatable :: dense(:,:) type(COO_${s1}$_type) :: COO type(CSR_${s1}$_type) :: CSR type(CSC_${s1}$_type) :: CSC ${t1}$, allocatable :: diagonal(:) allocate( dense(4,4) , source = & reshape(real([1,0,0,5, & 0,2,0,0, & 0,6,3,0,& 0,0,7,4],kind=wp),[4,4]) ) call diag(dense,diagonal) call check(error, all(diagonal == [1,2,3,4]) ) if (allocated(error)) return diagonal = 0.0 call dense2coo( dense , COO ) call diag( COO , diagonal ) call check(error, all(diagonal == [1,2,3,4]) ) if (allocated(error)) return diagonal = 0.0 call coo2csr( COO, CSR ) call diag( CSR , diagonal ) call check(error, all(diagonal == [1,2,3,4]) ) if (allocated(error)) return diagonal = 0.0 call coo2csc( COO, CSC ) call diag( CSC , diagonal ) call check(error, all(diagonal == [1,2,3,4]) ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_add_get_values(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for k1, t1, s1 in (KINDS_TYPES) block integer, parameter :: wp = ${k1}$ real(wp) :: dense(5,5), mat(2,2) type(COO_${s1}$_type) :: COO type(CSR_${s1}$_type) :: CSR ${t1}$:: err integer :: i, j, locdof(2) mat(:,1) = [1,2]; mat(:,2) = [2,1] dense = 0._wp do i = 0, 3 dense(1+i:2+i,1+i:2+i) = dense(1+i:2+i,1+i:2+i) + mat end do call dense2coo(dense,COO) call coo2csr(COO,CSR) CSR%data = 0._wp do i = 0, 3 locdof(1:2) = [1+i,2+i] call CSR%add(locdof,locdof,mat) end do call check(error, all(CSR%data == COO%data) ) if (allocated(error)) return err = 0._wp do i = 1, 5 do j = 1, 5 err = err + abs(dense(i,j) - CSR%at(i,j)) end do end do err = err / 5*5 call check(error, err <= epsilon(0._wp) ) if (allocated(error)) return end block #:endfor end subroutine end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_sparse_spmv, only : collect_suite implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("sparse", collect_suite) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/linalg/test_linalg_svd.fypp0000664000175000017500000002701415135654166024500 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test singular value decomposition module test_linalg_svd use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg_constants use stdlib_linalg, only: diag,svd,svdvals use stdlib_linalg_state, only: linalg_state_type implicit none (type,external) public :: test_svd contains !> Solve several SVD problems subroutine test_svd(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in REAL_KINDS_TYPES call add_test(tests,new_unittest("test_svd_${ri}$",test_svd_${ri}$)) #:endfor #:for ck,ct,ci in CMPLX_KINDS_TYPES call add_test(tests,new_unittest("test_complex_svd_${ci}$",test_complex_svd_${ci}$)) #:endfor #:for rk,rt,ri in RC_KINDS_TYPES call add_test(tests,new_unittest("test_svd_row_${ri}$",test_svd_row_${ri}$)) #:endfor end subroutine test_svd !> Real matrix svd #:for rk,rt,ri in REAL_KINDS_TYPES subroutine test_svd_${ri}$(error) type(error_type), allocatable, intent(out) :: error !> Reference solution ${rt}$, parameter :: tol = sqrt(epsilon(0.0_${rk}$)) ${rt}$, parameter :: third = 1.0_${rk}$/3.0_${rk}$ ${rt}$, parameter :: twothd = 2*third ${rt}$, parameter :: rsqrt2 = 1.0_${rk}$/sqrt(2.0_${rk}$) ${rt}$, parameter :: rsqrt18 = 1.0_${rk}$/sqrt(18.0_${rk}$) ${rt}$, parameter :: A_mat(2,3) = reshape([${rt}$ :: 3,2, 2,3, 2,-2],[2,3]) ${rt}$, parameter :: s_sol(2) = [${rt}$ :: 5, 3] ${rt}$, parameter :: u_sol(2,2) = reshape(rsqrt2*[1,1,1,-1],[2,2]) ${rt}$, parameter :: vt_sol(3,3) = reshape([rsqrt2,rsqrt18,twothd, & rsqrt2,-rsqrt18,-twothd,& 0.0_${rk}$,4*rsqrt18,-third],[3,3]) !> Local variables character(:), allocatable :: test type(linalg_state_type) :: state ${rt}$ :: A(2,3),s(2),u(2,2),vt(3,3) !> Initialize matrix A = A_mat !> Simple subroutine version call svd(A,s,err=state) test = 'subroutine version' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return !> Function interface s = svdvals(A,err=state) test = 'function interface' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return !> [S, U]. Singular vectors could be all flipped call svd(A,s,u,err=state) test = 'subroutine with singular vectors' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return call check(error, all(abs(abs(u)-abs(u_sol))<=tol), test//': U') if (allocated(error)) return !> [S, U]. Overwrite A matrix call svd(A,s,u,overwrite_a=.true.,err=state) test = 'subroutine, overwrite_a' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return call check(error, all(abs(abs(u)-abs(u_sol))<=tol), test//': U') if (allocated(error)) return !> [S, U, V^T] A = A_mat call svd(A,s,u,vt,overwrite_a=.true.,err=state) test = '[S, U, V^T]' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return call check(error, all(abs(abs(u)-abs(u_sol))<=tol), test//': U') if (allocated(error)) return call check(error, all(abs(abs(vt)-abs(vt_sol))<=tol), test//': V^T') if (allocated(error)) return !> [S, V^T]. Do not overwrite A matrix A = A_mat call svd(A,s,vt=vt,err=state) test = '[S, V^T], overwrite_a=.false.' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return call check(error, all(abs(abs(vt)-abs(vt_sol))<=tol), test//': V^T') if (allocated(error)) return !> [S, V^T]. Overwrite A matrix call svd(A,s,vt=vt,overwrite_a=.true.,err=state) test = '[S, V^T], overwrite_a=.true.' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return call check(error, all(abs(abs(vt)-abs(vt_sol))<=tol), test//': V^T') if (allocated(error)) return !> [U, S, V^T]. A = A_mat call svd(A,s,u,vt,err=state) test = '[U, S, V^T]' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(abs(u)-abs(u_sol))<=tol), test//': U') if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return call check(error, all(abs(abs(vt)-abs(vt_sol))<=tol), test//': V^T') if (allocated(error)) return !> [U, S, V^T]. Partial storage -> compare until k=2 columns of U rows of V^T A = A_mat u = 0 vt = 0 call svd(A,s,u,vt,full_matrices=.false.,err=state) test = '[U, S, V^T], partial storage' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(abs(u(:,:2))-abs(u_sol(:,:2)))<=tol), test//': U(:,:2)') if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return call check(error, all(abs(abs(vt(:2,:))-abs(vt_sol(:2,:)))<=tol), test//': V^T(:2,:)') if (allocated(error)) return end subroutine test_svd_${ri}$ #:endfor !> Test complex svd #:for ck,ct,ci in CMPLX_KINDS_TYPES subroutine test_complex_svd_${ci}$(error) type(error_type), allocatable, intent(out) :: error !> Reference solution real(${ck}$), parameter :: tol = sqrt(epsilon(0.0_${ck}$)) real(${ck}$), parameter :: one = 1.0_${ck}$ real(${ck}$), parameter :: zero = 0.0_${ck}$ real(${ck}$), parameter :: sqrt2 = sqrt(2.0_${ck}$) real(${ck}$), parameter :: rsqrt2 = one/sqrt2 ${ct}$, parameter :: csqrt2 = (rsqrt2,zero) ${ct}$, parameter :: isqrt2 = (zero,rsqrt2) ${ct}$, parameter :: cone = (1.0_${ck}$,0.0_${ck}$) ${ct}$, parameter :: cimg = (0.0_${ck}$,1.0_${ck}$) ${ct}$, parameter :: czero = (0.0_${ck}$,0.0_${ck}$) real(${ck}$), parameter :: s_sol(2) = [sqrt2,sqrt2] ${ct}$, parameter :: A_mat(2,2) = reshape([cone,cimg,cimg,cone],[2,2]) ${ct}$, parameter :: u_sol(2,2) = reshape([csqrt2,isqrt2,isqrt2,csqrt2],[2,2]) ${ct}$, parameter :: vt_sol(2,2) = reshape([cone,czero,czero,cone],[2,2]) !> Local variables character(:), allocatable :: test type(linalg_state_type) :: state ${ct}$ :: A(2,2),u(2,2),vt(2,2) real(${ck}$) :: s(2) !> Initialize matrix A = A_mat !> Simple subroutine version call svd(A,s,err=state) test = '[S], complex subroutine' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return !> Function interface s = svdvals(A,err=state) test = 'svdvals, complex function' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return !> [S, U, V^T] A = A_mat call svd(A,s,u,vt,overwrite_a=.true.,err=state) test = '[S, U, V^T], complex' call check(error,state%ok(),test//': '//state%print()) if (allocated(error)) return call check(error, all(abs(s-s_sol)<=tol), test//': S') if (allocated(error)) return call check(error, all(abs(matmul(u,matmul(diag(s),vt))-A_mat)<=tol), test//': U*S*V^T') if (allocated(error)) return end subroutine test_complex_svd_${ci}$ #:endfor #:for rk,rt,ri in RC_KINDS_TYPES ! Issue #835: bounds checking triggers an error with 1-sized A matrix subroutine test_svd_row_${ri}$(error) type(error_type), allocatable, intent(out) :: error !> Reference solution type(linalg_state_type) :: state integer(ilp), parameter :: m = 1, n = 1 real(${rk}$), parameter :: tol = sqrt(epsilon(0.0_${rk}$)) real(${rk}$) :: Arand(m, n), S(n) ${rt}$ :: A(m, n), U(m, m), Vt(n, n) ! Random matrix. call random_number(Arand) A = Arand call svd(A, S, U, Vt, err=state) call check(error,state%ok(),'1-row SVD: '//state%print()) if (allocated(error)) return call check(error, abs(S(1)-A(1,1))0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_svd program test_lstsq use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_svd, only : test_svd implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_svd", test_svd) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_lstsq fortran-lang-stdlib-0ede301/test/linalg/test_linalg_solve.fypp0000664000175000017500000001573415135654166025042 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test linear system solver module test_linalg_solve use stdlib_linalg_constants use stdlib_linalg_state use stdlib_linalg, only: solve use testdrive, only: error_type, check, new_unittest, unittest_type implicit none (type,external) private public :: test_linear_systems contains !> Solve real and complex linear systems subroutine test_linear_systems(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in REAL_KINDS_TYPES call add_test(tests,new_unittest("solve_${ri}$",test_${ri}$_solve)) call add_test(tests,new_unittest("solve_${ri}$_multiple",test_${ri}$_solve_multiple)) #:endfor #:for ck,ct,ci in CMPLX_KINDS_TYPES call add_test(tests,new_unittest("solve_complex_${ci}$",test_${ci}$_solve)) call add_test(tests,new_unittest("solve_2x2_complex_${ci}$",test_2x2_${ci}$_solve)) #:endfor end subroutine test_linear_systems #:for rk,rt,ri in REAL_KINDS_TYPES !> Simple linear system subroutine test_${ri}$_solve(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state ${rt}$ :: A(3,3) = transpose(reshape([${rt}$ :: 1, 3, 3, & 1, 3, 4, & 1, 4, 3], [3,3])) ${rt}$ :: b (3) = [${rt}$ :: 1, 4, -1] ${rt}$ :: res(3) = [${rt}$ :: -2, -2, 3] ${rt}$ :: x(3) x = solve(a,b,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, all(abs(x-res) Simple linear system with multiple right hand sides subroutine test_${ri}$_solve_multiple(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state ${rt}$ :: A(3,3) = transpose(reshape([${rt}$ :: 1,-1, 2, & 0, 1, 1, & 1,-1, 3], [3,3])) ${rt}$ :: b(3,3) = transpose(reshape([${rt}$ :: 0, 1, 2, & 1,-2,-1, & 2, 3,-1], [3,3])) ${rt}$ :: res(3,3) = transpose(reshape([${rt}$ ::-5,-7,10, & -1,-4, 2, & 2, 2,-3], [3,3])) ${rt}$ :: x(3,3) x = solve(a,b,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, all(abs(x-res) Complex linear system !> Militaru, Popa, "On the numerical solving of complex linear systems", !> Int J Pure Appl Math 76(1), 113-122, 2012. subroutine test_${ri}$_solve(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state ${rt}$ :: A(5,5), b(5), res(5), x(5) ! Fill in linear system A = (0.0_${rk}$,0.0_${rk}$) A(1:2,1) = [(19.73_${rk}$,0.0_${rk}$),(0.0_${rk}$,-0.51_${rk}$)] A(1:3,2) = [(12.11_${rk}$,-1.0_${rk}$),(32.3_${rk}$,7.0_${rk}$),(0.0_${rk}$,-0.51_${rk}$)] A(1:4,3) = [(0.0_${rk}$,5.0_${rk}$),(23.07_${rk}$,0.0_${rk}$),(70.0_${rk}$,7.3_${rk}$),(1.0_${rk}$,1.1_${rk}$)] A(2:5,4) = [(0.0_${rk}$,1.0_${rk}$),(3.95_${rk}$,0.0_${rk}$),(50.17_${rk}$,0.0_${rk}$),(0.0_${rk}$,-9.351_${rk}$)] A(3:5,5) = [(19.0_${rk}$,31.83_${rk}$),(45.51_${rk}$,0.0_${rk}$),(55.0_${rk}$,0.0_${rk}$)] b = [(77.38_${rk}$,8.82_${rk}$),(157.48_${rk}$,19.8_${rk}$),(1175.62_${rk}$,20.69_${rk}$),(912.12_${rk}$,-801.75_${rk}$),(550.0_${rk}$,-1060.4_${rk}$)] ! Exact result res = [(3.3_${rk}$,-1.0_${rk}$),(1.0_${rk}$,0.17_${rk}$),(5.5_${rk}$,0.0_${rk}$),(9.0_${rk}$,0.0_${rk}$),(10.0_${rk}$,-17.75_${rk}$)] x = solve(a,b,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, all(abs(x-res) 2x2 Complex linear system subroutine test_2x2_${ri}$_solve(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state ${rt}$, parameter :: i = (0.0_${rk}$,1.0_${rk}$) ${rt}$ :: A(2,2), b(2), res(2), x(2) ! Fill in linear system A(1,:) = [ 1+2*i, 2-i] A(2,:) = [ 2+i , i] b = [1,-1] ! Exact result res = [(-0.28_${rk}$,-0.04_${rk}$),(0.36_${rk}$,0.48_${rk}$)] x = solve(a,b,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, all(abs(x-res)0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_solve program test_solve use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_solve, only : test_linear_systems implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_solve", test_linear_systems) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_solve fortran-lang-stdlib-0ede301/test/linalg/test_linalg_cholesky.fypp0000664000175000017500000000732415135654166025527 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test Cholesky factorization module test_linalg_cholesky use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg_constants use stdlib_linalg, only: cholesky,chol use stdlib_linalg_state, only: linalg_state_type implicit none (type,external) private public :: test_cholesky_factorization contains !> Cholesky factorization tests subroutine test_cholesky_factorization(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in RC_KINDS_TYPES call add_test(tests,new_unittest("least_cholesky_${ri}$",test_cholesky_${ri}$)) #:endfor end subroutine test_cholesky_factorization !> Cholesky factorization of a random matrix #:for rk,rt,ri in RC_KINDS_TYPES subroutine test_cholesky_${ri}$(error) type(error_type), allocatable, intent(out) :: error integer(ilp), parameter :: n = 3_ilp real(${rk}$), parameter :: tol = 100*sqrt(epsilon(0.0_${rk}$)) ${rt}$ :: a(n,n), l(n,n) type(linalg_state_type) :: state ! Set real matrix a(1,:) = [6, 15, 55] a(2,:) = [15, 55, 225] a(3,:) = [55, 225, 979] ! Set result (lower factor) l(1,:) = [ 2.4495_${rk}$, 0.0000_${rk}$, 0.0000_${rk}$] l(2,:) = [ 6.1237_${rk}$, 4.1833_${rk}$, 0.0000_${rk}$] l(3,:) = [22.4537_${rk}$, 20.9165_${rk}$, 6.1101_${rk}$] ! 1) Cholesky factorization with full matrices call cholesky(a, l, other_zeroed=.true., err=state) call check(error,state%ok(),'cholesky (subr) :: '//state%print()) if (allocated(error)) return call check(error, all(abs(a-matmul(l,transpose(l)))0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_cholesky program test_cholesky use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_cholesky, only : test_cholesky_factorization implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_cholesky", test_cholesky_factorization) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_cholesky fortran-lang-stdlib-0ede301/test/linalg/test_linalg_determinant.fypp0000664000175000017500000001401015135654166026206 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test matrix determinant module test_linalg_determinant use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg_constants use stdlib_linalg, only: eye, det, linalg_state_type implicit none (type,external) private public :: test_matrix_determinant contains !> Matrix inversion tests subroutine test_matrix_determinant(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt in RC_KINDS_TYPES #:if rk!="xdp" call add_test(tests,new_unittest("$eye_det_${rt[0]}$${rk}$",test_${rt[0]}$${rk}$_eye_determinant)) call add_test(tests,new_unittest("$eye_det_multiple_${rt[0]}$${rk}$",test_${rt[0]}$${rk}$_eye_multiple)) #:endif #:endfor #:for ck,ct in CMPLX_KINDS_TYPES #:if ck!="xdp" call add_test(tests,new_unittest("$complex_det_${rt[0]}$${rk}$",test_${ct[0]}$${ck}$_complex_determinant)) #:endif #: endfor end subroutine test_matrix_determinant #:for rk,rt in RC_KINDS_TYPES #:if rk!="xdp" !> Determinant of identity matrix subroutine test_${rt[0]}$${rk}$_eye_determinant(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp), parameter :: n = 128_ilp ${rt}$ :: a(n,n),deta ${rt}$, allocatable :: aalloc(:,:) a = eye(n) !> Determinant function deta = det(a,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, abs(deta-1.0_${rk}$) Test with allocatable matrix aalloc = eye(n) deta = det(aalloc,overwrite_a=.false.,err=state) call check(error,state%ok(),state%print()//' (allocatable a)') if (allocated(error)) return call check(error,allocated(aalloc),'a is still allocated') if (allocated(error)) return call check(error, abs(deta-1.0_${rk}$) Determinant of identity matrix multiplier subroutine test_${rt[0]}$${rk}$_eye_multiple(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp), parameter :: n = 4_ilp real(${rk}$), parameter :: coef = 0.01_${rk}$ integer(ilp) :: i ${rt}$ :: a(n,n),deta !> Multiply eye by a very small number a = eye(n) do concurrent (i=1:n) a(i,i) = coef end do !> Determinant: small, but a is not singular, because it is a multiple of the identity. deta = det(a,err=state) call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, abs(deta-coef**n) Determinant of complex identity matrix #:for ck,ct in CMPLX_KINDS_TYPES #:if ck!="xdp" subroutine test_${ct[0]}$${ck}$_complex_determinant(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp) :: i,n integer(ilp), parameter :: nmax = 10_ilp ${ct}$, parameter :: res(nmax) = [${ct}$::(1,1),(0,2),(-2,2),(-4,0),(-4,-4), & (0,-8),(8,-8),(16,0),(16,16),(0,32)] ${ct}$, allocatable :: a(:,:) ${ct}$ :: deta(nmax) !> Test determinant for all sizes, 1:nmax matrix_size: do n=1,nmax ! Put 1+i on each diagonal element a = eye(n) do concurrent (i=1:n) a(i,i) = (1.0_${ck}$,1.0_${ck}$) end do ! Expected result deta(n) = det(a,err=state) deallocate(a) if (state%error()) exit matrix_size end do matrix_size call check(error,state%ok(),state%print()) if (allocated(error)) return call check(error, all(abs(res-deta)<=epsilon(0.0_${ck}$)), & 'det((1+i)*eye(n)) does not match result') end subroutine test_${ct[0]}$${ck}$_complex_determinant #:endif #:endfor ! gcc-15 bugfix utility subroutine add_test(tests,new_test) type(unittest_type), allocatable, intent(inout) :: tests(:) type(unittest_type), intent(in) :: new_test integer :: n type(unittest_type), allocatable :: new_tests(:) if (allocated(tests)) then n = size(tests) else n = 0 end if allocate(new_tests(n+1)) if (n>0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_determinant program test_det use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_determinant, only : test_matrix_determinant implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_determinant", test_matrix_determinant) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/linalg/test_linalg_norm.fypp0000664000175000017500000002775515135654166024673 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES #! Generate an array rank suffix with the same fixed size for all dimensions. #! #! Args: #! rank (int): Rank of the variable #! size (int): Size along each dimension #! #! Returns: #! Array rank suffix string (e.g. (4,4,4) if rank = 3 and size = 4) #! #:def fixedranksuffix(rank,size) #{if rank > 0}#(${str(size) + (","+str(size)) * (rank - 1)}$)#{endif}# #:enddef ! Test vector norms module test_linalg_norm use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg_constants use stdlib_linalg, only: norm, linalg_state_type use stdlib_linalg_state, only: linalg_state_type implicit none (type,external) contains !> Vector norm tests subroutine test_vector_norms(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in RC_KINDS_TYPES call add_test(tests,new_unittest("strided_1d_norm_${ri}$",test_strided_1d_${ri}$)) #:for rank in range(1, MAXRANK) call add_test(tests,new_unittest("norm_${ri}$_${rank}$d",test_norm_${ri}$_${rank}$d)) #:endfor #:for rank in range(2, MAXRANK) #:if rt.startswith('real') call add_test(tests,new_unittest("norm2_${ri}$_${rank}$d",test_norm2_${ri}$_${rank}$d)) #:endif call add_test(tests,new_unittest("maxabs_${ri}$_${rank}$d",test_maxabs_${ri}$_${rank}$d)) call add_test(tests,new_unittest("norm_dimmed_${ri}$_${rank}$d",test_norm_dimmed_${ri}$_${rank}$d)) #:endfor #:endfor end subroutine test_vector_norms #:for rk,rt,ri in RC_KINDS_TYPES !> Test strided norm subroutine test_strided_1d_${ri}$(error) type(error_type), allocatable, intent(out) :: error integer(ilp), parameter :: m = 8_ilp integer(ilp), parameter :: n = m**2 real(${rk}$), parameter :: tol = 10*sqrt(epsilon(0.0_${rk}$)) ${rt}$, target :: a(n) ${rt}$, allocatable :: slice(:) ${rt}$, pointer :: twod(:,:) real(${rk}$) :: rea(n),ima(n) call random_number(rea) #:if rt.startswith('real') a = rea #:else call random_number(ima) a = cmplx(rea,ima,kind=${rk}$) #:endif ! Test sliced array results slice = a(4:7:59) call check(error,abs(norm(a(4:7:59),2)-norm(slice,2)) a call check(error,abs(norm(twod,2)-norm(a,2)) Test several norms with different dimensions subroutine test_norm_${ri}$_${rank}$d(error) type(error_type), allocatable, intent(out) :: error integer(ilp) :: j,order integer(ilp), parameter :: n = 2_ilp**${rank}$ real(${rk}$), parameter :: tol = 10*sqrt(epsilon(0.0_${rk}$)) ${rt}$, allocatable :: a(:), b${ranksuffix(rank)}$ character(64) :: msg allocate(a(n), b${fixedranksuffix(rank,2)}$) ! Init as a range,but with small elements such that all power norms will ! never overflow, even in single precision a = [(0.01_${rk}$*(j-n/2_ilp), j=1_ilp,n)] b = reshape(a, shape(b)) ! Test some norms do order = 1, 10 write(msg,"('reshaped order-',i0,' p-norm is the same')") order call check(error,abs(norm(a,order)-norm(b,order)) Test Euclidean norm; compare with Fortran intrinsic norm2 for reals #:if rt.startswith('real') subroutine test_norm2_${ri}$_${rank}$d(error) type(error_type), allocatable, intent(out) :: error integer(ilp) :: j,dim integer(ilp), parameter :: ndim = ${rank}$ integer(ilp), parameter :: n = 2_ilp**ndim real(${rk}$), parameter :: tol = 10*sqrt(epsilon(0.0_${rk}$)) ${rt}$, allocatable :: a(:), b${ranksuffix(rank)}$ intrinsic :: norm2 character(64) :: msg allocate(a(n), b${fixedranksuffix(rank,2)}$) ! Init as a range,but with small elements such that all power norms will ! never overflow, even in single precision a = [(0.01_${rk}$*(j-n/2_ilp), j=1_ilp,n)] b = reshape(a, shape(b)) ! Test some norms call check(error,abs(norm(a,2) - norm2(a)) Test Infinity norm; compare with Fortran intrinsic max(abs(a)) subroutine test_maxabs_${ri}$_${rank}$d(error) type(error_type), allocatable, intent(out) :: error integer(ilp) :: j,dim integer(ilp), parameter :: ndim = ${rank}$ integer(ilp), parameter :: n = 2_ilp**ndim real(${rk}$), parameter :: tol = 10*sqrt(epsilon(0.0_${rk}$)) ${rt}$, allocatable :: a(:), b${ranksuffix(rank)}$ intrinsic :: maxval, abs character(128) :: msg allocate(a(n), b${fixedranksuffix(rank,2)}$) ! Init as a range,but with small elements such that all power norms will ! never overflow, even in single precision a = [(0.01_${rk}$*(j-n/2_ilp), j=1_ilp,n)] b = reshape(a, shape(b)) ! Test some norms call check(error,abs(norm(a,'inf') - maxval(abs(a)))0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_norm program test_norm use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_norm, only : test_vector_norms implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_norm", test_vector_norms) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_norm fortran-lang-stdlib-0ede301/test/linalg/test_linalg_constrained_lstsq.fypp0000664000175000017500000001254715135654166027450 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test least squares solver module test_linalg_constrained_least_squares use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg_constants use stdlib_linalg, only: constrained_lstsq, solve_constrained_lstsq, constrained_lstsq_space use stdlib_linalg_state, only: linalg_state_type implicit none (type,external) private public :: test_constrained_least_squares contains !> Solve sample least squares problems subroutine test_constrained_least_squares(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in REAL_KINDS_TYPES call add_test(tests,new_unittest("constrained_least_squares_randm_${ri}$",test_constrained_lstsq_random_${ri}$)) #:endfor end subroutine test_constrained_least_squares #:for rk,rt,ri in REAL_KINDS_TYPES !> Fit from random array subroutine test_constrained_lstsq_random_${ri}$(error) type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state integer(ilp), parameter :: m=5, n=4, p=3 !> Least-squares cost. ${rt}$ :: A(m, n), b(m) !> Equality constraints. ${rt}$ :: C(p, n), d(p) !> Solution. ${rt}$ :: x(n), x_true(n) !> Workspace. integer(ilp) :: lwork ${rt}$, allocatable :: work(:) !> Least-squares cost. A(1, :) = [1.0_${rk}$, 1.0_${rk}$, 1.0_${rk}$, 1.0_${rk}$] A(2, :) = [1.0_${rk}$, 3.0_${rk}$, 1.0_${rk}$, 1.0_${rk}$] A(3, :) = [1.0_${rk}$, -1.0_${rk}$, 3.0_${rk}$, 1.0_${rk}$] A(4, :) = [1.0_${rk}$, 1.0_${rk}$, 1.0_${rk}$, 3.0_${rk}$] A(5, :) = [1.0_${rk}$, 1.0_${rk}$, 1.0_${rk}$, -1.0_${rk}$] b = [2.0_${rk}$, 1.0_${rk}$, 6.0_${rk}$, 3.0_${rk}$, 1.0_${rk}$] !> Equality constraints. C(1, :) = [1.0_${rk}$, 1.0_${rk}$, 1.0_${rk}$, -1.0_${rk}$] C(2, :) = [1.0_${rk}$, -1.0_${rk}$, 1.0_${rk}$, 1.0_${rk}$] C(3, :) = [1.0_${rk}$, 1.0_${rk}$, -1.0_${rk}$, 1.0_${rk}$] d = [1.0_${rk}$, 3.0_${rk}$, -1.0_${rk}$] !----- Function interface ----- x = constrained_lstsq(A, b, C, d, err=state) x_true = [0.5_${rk}$, -0.5_${rk}$, 1.5_${rk}$, 0.5_${rk}$] call check(error, state%ok(), state%print()) if (allocated(error)) return call check(error, all(abs(x-x_true) < 1.0e-4_${rk}$), 'Solver converged') if (allocated(error)) return !----- Subroutine interface ----- call solve_constrained_lstsq(A, b, C, d, x, err=state) call check(error, state%ok(), state%print()) if (allocated(error)) return call check(error, all(abs(x-x_true) < 1.0e-4_${rk}$), 'Solver converged') if (allocated(error)) return !----- Pre-allocated storage ----- call constrained_lstsq_space(A, C, lwork, err=state) call check(error, state%ok(), state%print()) if (allocated(error)) return allocate(work(lwork)) call solve_constrained_lstsq(A, b, C, d, x, storage=work, err=state) call check(error, state%ok(), state%print()) if (allocated(error)) return call check(error, all(abs(x-x_true) < 1.0e-4_${rk}$), 'Solver converged') if (allocated(error)) return !----- Overwrite matrices (performance) ----- call solve_constrained_lstsq(A, b, C, d, x, storage=work, overwrite_matrices=.true., err=state) call check(error, state%ok(), state%print()) if (allocated(error)) return call check(error, all(abs(x-x_true) < 1.0e-4_${rk}$), 'Solver converged') if (allocated(error)) return end subroutine test_constrained_lstsq_random_${ri}$ #:endfor ! gcc-15 bugfix utility subroutine add_test(tests,new_test) type(unittest_type), allocatable, intent(inout) :: tests(:) type(unittest_type), intent(in) :: new_test integer :: n type(unittest_type), allocatable :: new_tests(:) if (allocated(tests)) then n = size(tests) else n = 0 end if allocate(new_tests(n+1)) if (n>0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_constrained_least_squares program test_constrained_lstsq use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_constrained_least_squares, only : test_constrained_least_squares implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_constrained_least_squares", test_constrained_least_squares) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_constrained_lstsq fortran-lang-stdlib-0ede301/test/linalg/test_linalg_qr.fypp0000664000175000017500000001233015135654166024321 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Test QR factorization module test_linalg_qr use testdrive, only: error_type, check, new_unittest, unittest_type use stdlib_linalg_constants use stdlib_linalg_state, only: LINALG_VALUE_ERROR,linalg_state_type use stdlib_linalg, only: qr,qr_space use ieee_arithmetic, only: ieee_value,ieee_quiet_nan implicit none (type,external) public :: test_qr_factorization contains !> QR factorization tests subroutine test_qr_factorization(tests) !> Collection of tests type(unittest_type), allocatable, intent(out) :: tests(:) allocate(tests(0)) #:for rk,rt,ri in RC_KINDS_TYPES call add_test(tests,new_unittest("qr_random_${ri}$",test_qr_random_${ri}$)) #:endfor end subroutine test_qr_factorization !> QR factorization of a random matrix #:for rk,rt,ri in RC_KINDS_TYPES subroutine test_qr_random_${ri}$(error) type(error_type), allocatable, intent(out) :: error integer(ilp), parameter :: m = 15_ilp integer(ilp), parameter :: n = 4_ilp integer(ilp), parameter :: k = min(m,n) real(${rk}$), parameter :: tol = 100*sqrt(epsilon(0.0_${rk}$)) ${rt}$ :: a(m,n),aorig(m,n),q(m,m),r(m,n),qred(m,k),rred(k,n),qerr(m,6),rerr(6,n) real(${rk}$) :: rea(m,n),ima(m,n) integer(ilp) :: lwork ${rt}$, allocatable :: work(:) type(linalg_state_type) :: state call random_number(rea) #:if rt.startswith('complex') call random_number(ima) a = cmplx(rea,ima,kind=${rk}$) #:else a = rea #:endif aorig = a ! 1) QR factorization with full matrices. Input NaNs to be sure Q and R are OK on return q = ieee_value(0.0_${rk}$,ieee_quiet_nan) r = ieee_value(0.0_${rk}$,ieee_quiet_nan) call qr(a,q,r,err=state) ! Check return code call check(error,state%ok(),state%print()) if (allocated(error)) return ! Check solution call check(error, all(abs(a-matmul(q,r))0) new_tests(1:n) = tests(1:n) new_tests(1+n) = new_test call move_alloc(from=new_tests,to=tests) end subroutine add_test end module test_linalg_qr program test_qr use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg_qr, only : test_qr_factorization implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg_qr", test_qr_factorization) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program test_qr fortran-lang-stdlib-0ede301/test/linalg/test_linalg.fypp0000664000175000017500000010773515135654166023635 0ustar alastairalastair#:include "common.fypp" #:set RCI_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES + INT_KINDS_TYPES module test_linalg use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_kinds, only: sp, dp, xdp, qp, int8, int16, int32, int64 use stdlib_linalg, only: diag, eye, trace, outer_product, cross_product, kronecker_product, hermitian use stdlib_linalg_state, only: linalg_state_type, LINALG_SUCCESS, linalg_error_handling implicit none real(sp), parameter :: sptol = 1000 * epsilon(1._sp) real(dp), parameter :: dptol = 1000 * epsilon(1._dp) #:if WITH_QP real(qp), parameter :: qptol = 1000 * epsilon(1._qp) #:endif contains !> Collect all exported unit tests subroutine collect_linalg(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("eye", test_eye), & new_unittest("diag_rsp", test_diag_rsp), & new_unittest("diag_rsp_k", test_diag_rsp_k), & new_unittest("diag_rdp", test_diag_rdp), & new_unittest("diag_rqp", test_diag_rqp), & new_unittest("diag_csp", test_diag_csp), & new_unittest("diag_cdp", test_diag_cdp), & new_unittest("diag_cqp", test_diag_cqp), & new_unittest("diag_int8", test_diag_int8), & new_unittest("diag_int16", test_diag_int16), & new_unittest("diag_int32", test_diag_int32), & new_unittest("diag_int64", test_diag_int64), & new_unittest("trace_rsp", test_trace_rsp), & new_unittest("trace_rsp_nonsquare", test_trace_rsp_nonsquare), & new_unittest("trace_rdp", test_trace_rdp), & new_unittest("trace_rdp_nonsquare", test_trace_rdp_nonsquare), & new_unittest("trace_rqp", test_trace_rqp), & new_unittest("trace_csp", test_trace_csp), & new_unittest("trace_cdp", test_trace_cdp), & new_unittest("trace_cqp", test_trace_cqp), & new_unittest("trace_int8", test_trace_int8), & new_unittest("trace_int16", test_trace_int16), & new_unittest("trace_int32", test_trace_int32), & new_unittest("trace_int64", test_trace_int64), & #:for k1, t1 in RCI_KINDS_TYPES new_unittest("kronecker_product_${t1[0]}$${k1}$", test_kronecker_product_${t1[0]}$${k1}$), & #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES new_unittest("hermitian_${t1[0]}$${k1}$", test_hermitian_${t1[0]}$${k1}$), & #:endfor new_unittest("outer_product_rsp", test_outer_product_rsp), & new_unittest("outer_product_rdp", test_outer_product_rdp), & new_unittest("outer_product_rqp", test_outer_product_rqp), & new_unittest("outer_product_csp", test_outer_product_csp), & new_unittest("outer_product_cdp", test_outer_product_cdp), & new_unittest("outer_product_cqp", test_outer_product_cqp), & new_unittest("outer_product_int8", test_outer_product_int8), & new_unittest("outer_product_int16", test_outer_product_int16), & new_unittest("outer_product_int32", test_outer_product_int32), & new_unittest("outer_product_int64", test_outer_product_int64), & new_unittest("cross_product_rsp", test_cross_product_rsp), & new_unittest("cross_product_rdp", test_cross_product_rdp), & new_unittest("cross_product_rqp", test_cross_product_rqp), & new_unittest("cross_product_csp", test_cross_product_csp), & new_unittest("cross_product_cdp", test_cross_product_cdp), & new_unittest("cross_product_cqp", test_cross_product_cqp), & new_unittest("cross_product_int8", test_cross_product_int8), & new_unittest("cross_product_int16", test_cross_product_int16), & new_unittest("cross_product_int32", test_cross_product_int32), & new_unittest("cross_product_int64", test_cross_product_int64), & new_unittest("state_handling", test_state_handling) & ] end subroutine collect_linalg subroutine test_eye(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(sp), allocatable :: rye(:,:) complex(sp) :: cye(7,7) integer :: i call check(error, all(eye(3,3) == diag([(1,i=1,3)])), & "all(eye(3,3) == diag([(1,i=1,3)])) failed.") if (allocated(error)) return rye = eye(3,4) call check(error, sum(abs(rye(:,1:3) - diag([(1.0_sp,i=1,3)]))) < sptol, & "sum(abs(rye(:,1:3) - diag([(1.0_sp,i=1,3)]))) < sptol failed") if (allocated(error)) return call check(error, all(eye(5) == diag([(1,i=1,5)])), & "all(eye(5) == diag([(1,i=1,5)] failed.") if (allocated(error)) return rye = eye(6) call check(error, sum(rye - diag([(1.0_sp,i=1,6)])) < sptol, & "sum(rye - diag([(1.0_sp,i=1,6)])) < sptol failed.") if (allocated(error)) return cye = eye(7) call check(error, abs(trace(cye) - cmplx(7.0_sp,0.0_sp,kind=sp)) < sptol, & "abs(trace(cye) - cmplx(7.0_sp,0.0_sp,kind=sp)) < sptol failed.") end subroutine test_eye subroutine test_diag_rsp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 real(sp) :: v(n), a(n,n), b(n,n) integer :: i,j v = [(i,i=1,n)] a = diag(v) b = reshape([((merge(i,0,i==j), i=1,n), j=1,n)], [n,n]) call check(error, all(a == b), & "all(a == b) failed.") if (allocated(error)) return call check(error, all(diag(3*a) == 3*v), & "all(diag(3*a) == 3*v) failed.") end subroutine test_diag_rsp subroutine test_diag_rsp_k(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 4 real(sp) :: a(n,n), b(n,n) integer :: i,j a = diag([(1._sp,i=1,n-1)],-1) b = reshape([((merge(1,0,i==j+1), i=1,n), j=1,n)], [n,n]) call check(error, all(a == b), & "all(a == b) failed.") if (allocated(error)) return call check(error, sum(diag(a,-1)) - (n-1) < sptol, & "sum(diag(a,-1)) - (n-1) < sptol failed.") if (allocated(error)) return call check(error, all(a == transpose(diag([(1._sp,i=1,n-1)],1))), & "all(a == transpose(diag([(1._sp,i=1,n-1)],1))) failed") if (allocated(error)) return call random_number(a) do i = 1, n call check(error, size(diag(a,i)) == n-i, & "size(diag(a,i)) == n-i failed.") if (allocated(error)) return end do call check(error, size(diag(a,n+1)) == 0, & "size(diag(a,n+1)) == 0 failed.") end subroutine test_diag_rsp_k subroutine test_diag_rdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 real(dp) :: v(n), a(n,n), b(n,n) integer :: i,j v = [(i,i=1,n)] a = diag(v) b = reshape([((merge(i,0,i==j), i=1,n), j=1,n)], [n,n]) call check(error, all(a == b), & "all(a == b) failed.") if (allocated(error)) return call check(error, all(diag(3*a) == 3*v), & "all(diag(3*a) == 3*v) failed.") end subroutine test_diag_rdp subroutine test_diag_rqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP integer, parameter :: n = 3 real(qp) :: v(n), a(n,n), b(n,n) integer :: i,j v = [(i,i=1,n)] a = diag(v) b = reshape([((merge(i,0,i==j), i=1,n), j=1,n)], [n,n]) call check(error, all(a == b), & "all(a == b) failed.") if (allocated(error)) return call check(error, all(diag(3*a) == 3*v), & "all(diag(3*a) == 3*v) failed.") #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_diag_rqp subroutine test_diag_csp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 complex(sp) :: a(n,n), b(n,n) complex(sp), parameter :: i_ = cmplx(0,1,kind=sp) integer :: i,j a = diag([(i,i=1,n)]) + diag([(i_,i=1,n)]) b = reshape([((merge(i + 1*i_,0*i_,i==j), i=1,n), j=1,n)], [n,n]) call check(error, all(a == b), & "all(a == b) failed.") if (allocated(error)) return call check(error, all(abs(real(diag(a)) - [(i,i=1,n)]) < sptol), & "all(abs(real(diag(a)) - [(i,i=1,n)]) < sptol)") if (allocated(error)) return call check(error, all(abs(aimag(diag(a)) - [(1,i=1,n)]) < sptol), & "all(abs(aimag(diag(a)) - [(1,i=1,n)]) < sptol)") end subroutine test_diag_csp subroutine test_diag_cdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 complex(dp) :: a(n,n) complex(dp), parameter :: i_ = cmplx(0,1,kind=dp) a = diag([i_],-2) + diag([i_],2) call check(error, a(3,1) == i_ .and. a(1,3) == i_, & "a(3,1) == i_ .and. a(1,3) == i_ failed.") end subroutine test_diag_cdp subroutine test_diag_cqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP integer, parameter :: n = 3 complex(qp) :: a(n,n) complex(qp), parameter :: i_ = cmplx(0,1,kind=qp) a = diag([i_,i_],-1) + diag([i_,i_],1) call check(error, all(diag(a,-1) == i_) .and. all(diag(a,1) == i_), & "all(diag(a,-1) == i_) .and. all(diag(a,1) == i_) failed.") #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_diag_cqp subroutine test_diag_int8(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 integer(int8), allocatable :: a(:,:) integer :: i logical, allocatable :: mask(:,:) a = reshape([(i,i=1,n**2)],[n,n]) mask = merge(.true.,.false.,eye(n) == 1) call check(error, all(diag(a) == pack(a,mask)), & "all(diag(a) == pack(a,mask)) failed.") if (allocated(error)) return call check(error, all(diag(diag(a)) == merge(a,0_int8,mask)), & "all(diag(diag(a)) == merge(a,0_int8,mask)) failed.") end subroutine test_diag_int8 subroutine test_diag_int16(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 4 integer(int16), allocatable :: a(:,:) integer :: i logical, allocatable :: mask(:,:) a = reshape([(i,i=1,n**2)],[n,n]) mask = merge(.true.,.false.,eye(n) == 1) call check(error, all(diag(a) == pack(a,mask)), & "all(diag(a) == pack(a,mask))") if (allocated(error)) return call check(error, all(diag(diag(a)) == merge(a,0_int16,mask)), & "all(diag(diag(a)) == merge(a,0_int16,mask)) failed.") end subroutine test_diag_int16 subroutine test_diag_int32(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 integer(int32) :: a(n,n) logical :: mask(n,n) integer :: i, j mask = reshape([((merge(.true.,.false.,i==j+1), i=1,n), j=1,n)], [n,n]) a = 0 a = unpack([1_int32,1_int32],mask,a) call check(error, all(diag([1,1],-1) == a), & "all(diag([1,1],-1) == a) failed.") if (allocated(error)) return call check(error, all(diag([1,1],1) == transpose(a)), & "all(diag([1,1],1) == transpose(a)) failed.") end subroutine test_diag_int32 subroutine test_diag_int64(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 4 integer(int64) :: a(n,n), c(0:2*n-1) logical :: mask(n,n) integer :: i, j mask = reshape([((merge(.true.,.false.,i+1==j), i=1,n), j=1,n)], [n,n]) a = 0 a = unpack([1_int64,1_int64,1_int64],mask,a) call check(error, all(diag([1,1,1],1) == a), & "all(diag([1,1,1],1) == a) failed.") if (allocated(error)) return call check(error, all(diag([1,1,1],-1) == transpose(a)), & "all(diag([1,1,1],-1) == transpose(a)) failed.") if (allocated(error)) return ! Fill array c with Catalan numbers do i = 0, 2*n-1 c(i) = catalan_number(i) end do ! Symmetric Hankel matrix filled with Catalan numbers (det(H) = 1) do i = 1, n do j = 1, n a(i,j) = c(i-1 + (j-1)) end do end do call check(error, all(diag(a,-2) == diag(a,2)), & "all(diag(a,-2) == diag(a,2))") end subroutine test_diag_int64 subroutine test_trace_rsp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 5 real(sp) :: a(n,n) integer :: i a = reshape([(i,i=1,n**2)],[n,n]) call check(error, abs(trace(a) - sum(diag(a))) < sptol, & "abs(trace(a) - sum(diag(a))) < sptol failed.") end subroutine test_trace_rsp subroutine test_trace_rsp_nonsquare(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 4 real(sp) :: a(n,n+1), ans integer :: i ! 1 5 9 13 17 ! 2 6 10 14 18 ! 3 7 11 15 19 ! 4 8 12 16 20 a = reshape([(i,i=1,n*(n+1))],[n,n+1]) ans = sum([1._sp,6._sp,11._sp,16._sp]) call check(error, abs(trace(a) - ans) < sptol, & "abs(trace(a) - ans) < sptol failed.") end subroutine test_trace_rsp_nonsquare subroutine test_trace_rdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 4 real(dp) :: a(n,n) integer :: i a = reshape([(i,i=1,n**2)],[n,n]) call check(error, abs(trace(a) - sum(diag(a))) < dptol, & "abs(trace(a) - sum(diag(a))) < dptol failed.") end subroutine test_trace_rdp subroutine test_trace_rdp_nonsquare(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 4 real(dp) :: a(n,n-1), ans integer :: i ! 1 25 81 ! 4 36 100 ! 9 49 121 ! 16 64 144 a = reshape([(i**2,i=1,n*(n-1))],[n,n-1]) ans = sum([1._dp,36._dp,121._dp]) call check(error, abs(trace(a) - ans) < dptol, & "abs(trace(a) - ans) < dptol failed.") end subroutine test_trace_rdp_nonsquare subroutine test_trace_rqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP integer, parameter :: n = 3 real(qp) :: a(n,n) integer :: i a = reshape([(i,i=1,n**2)],[n,n]) call check(error, abs(trace(a) - sum(diag(a))) < qptol, & "abs(trace(a) - sum(diag(a))) < qptol failed.") #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_trace_rqp subroutine test_trace_csp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 5 real(sp) :: re(n,n), im(n,n) complex(sp) :: a(n,n), b(n,n) complex(sp), parameter :: i_ = cmplx(0,1,kind=sp) call random_number(re) call random_number(im) a = re + im*i_ call random_number(re) call random_number(im) b = re + im*i_ ! tr(A + B) = tr(A) + tr(B) call check(error, abs(trace(a+b) - (trace(a) + trace(b))) < sptol, & "abs(trace(a+b) - (trace(a) + trace(b))) < sptol failed.") end subroutine test_trace_csp subroutine test_trace_cdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 complex(dp) :: a(n,n), ans complex(dp), parameter :: i_ = cmplx(0,1,kind=dp) integer :: j a = reshape([(j + (n**2 - (j-1))*i_,j=1,n**2)],[n,n]) ans = cmplx(15,15,kind=dp) !(1 + 5 + 9) + (9 + 5 + 1)i call check(error, abs(trace(a) - ans) < dptol, & "abs(trace(a) - ans) < dptol failed.") end subroutine test_trace_cdp subroutine test_trace_cqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP integer, parameter :: n = 3 complex(qp) :: a(n,n) complex(qp), parameter :: i_ = cmplx(0,1,kind=qp) a = 3*eye(n) + 4*eye(n)*i_ ! pythagorean triple call check(error, abs(trace(a)) - 3*5.0_qp < qptol, & "abs(trace(a)) - 3*5.0_qp < qptol failed.") #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_trace_cqp subroutine test_trace_int8(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 integer(int8) :: a(n,n) integer :: i a = reshape([(i**2,i=1,n**2)],[n,n]) call check(error, trace(a) == (1 + 25 + 81), & "trace(a) == (1 + 25 + 81) failed.") end subroutine test_trace_int8 subroutine test_trace_int16(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 integer(int16) :: a(n,n) integer :: i a = reshape([(i**3,i=1,n**2)],[n,n]) call check(error, trace(a) == (1 + 125 + 729), & "trace(a) == (1 + 125 + 729) failed.") end subroutine test_trace_int16 subroutine test_trace_int32(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 integer(int32) :: a(n,n) integer :: i a = reshape([(i**4,i=1,n**2)],[n,n]) call check(error, trace(a) == (1 + 625 + 6561), & "trace(a) == (1 + 625 + 6561) failed.") end subroutine test_trace_int32 subroutine test_trace_int64(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 5 integer, parameter :: nd = 2*n-1 ! number of diagonals integer :: i, j integer(int64) :: c(0:nd), H(n,n) ! Fill array with Catalan numbers do i = 0, nd c(i) = catalan_number(i) end do ! Symmetric Hankel matrix filled with Catalan numbers (det(H) = 1) do i = 1, n do j = 1, n H(i,j) = c(i-1 + (j-1)) end do end do call check(error, trace(h) == sum(c(0:nd:2)), & "trace(h) == sum(c(0:nd:2)) failed.") end subroutine test_trace_int64 #:for k1, t1 in RCI_KINDS_TYPES subroutine test_kronecker_product_${t1[0]}$${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: m1 = 1, n1 = 2, m2 = 2, n2 = 3 ${t1}$, dimension(m1*m2,n1*n2), parameter :: expected & = transpose(reshape([1,2,3, 2,4,6, 2,4,6, 4,8,12], [m2*n2, m1*n1])) ${t1}$, parameter :: tol = 1.e-6 ${t1}$ :: A(m1,n1), B(m2,n2) ${t1}$ :: C(m1*m2,n1*n2), diff(m1*m2,n1*n2) integer :: i,j do j = 1, n1 do i = 1, m1 A(i,j) = i*j ! A = [1, 2] end do end do do j = 1, n2 do i = 1, m2 B(i,j) = i*j ! B = [[1, 2, 3], [2, 4, 6]] end do end do C = kronecker_product(A,B) diff = C - expected call check(error, all(abs(diff) .le. abs(tol)), "all(abs(diff) .le. abs(tol)) failed") ! Expected: C = [1*B, 2*B] = [[1,2,3, 2,4,6], [2,4,6, 4, 8, 12]] end subroutine test_kronecker_product_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES subroutine test_hermitian_${t1[0]}$${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: m = 2, n = 3 ${t1}$, dimension(m,n) :: A ${t1}$, dimension(n,m) :: AT, expected, diff real(${k1}$), parameter :: tol = 1.e-6_${k1}$ integer :: i,j do concurrent (i=1:m,j=1:n) A (i,j) = cmplx(i,-j,kind=${k1}$) expected(j,i) = cmplx(i,+j,kind=${k1}$) end do AT = hermitian(A) diff = AT - expected call check(error, all(abs(diff) < abs(tol)), "hermitian: all(abs(diff) < abs(tol)) failed") end subroutine test_hermitian_${t1[0]}$${k1}$ #:endfor subroutine test_outer_product_rsp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 2 real(sp) :: u(n), v(n), expected(n,n), diff(n,n) u = [1.,2.] v = [1.,3.] expected = reshape([1.,2.,3.,6.],[n,n]) diff = expected - outer_product(u,v) call check(error, all(abs(diff) < sptol), & "all(abs(diff) < sptol) failed.") end subroutine test_outer_product_rsp subroutine test_outer_product_rdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 2 real(dp) :: u(n), v(n), expected(n,n), diff(n,n) u = [1.,2.] v = [1.,3.] expected = reshape([1.,2.,3.,6.],[n,n]) diff = expected - outer_product(u,v) call check(error, all(abs(diff) < dptol), & "all(abs(diff) < dptol) failed.") end subroutine test_outer_product_rdp subroutine test_outer_product_rqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP integer, parameter :: n = 2 real(qp) :: u(n), v(n), expected(n,n), diff(n,n) u = [1.,2.] v = [1.,3.] expected = reshape([1.,2.,3.,6.],[n,n]) diff = expected - outer_product(u,v) call check(error, all(abs(diff) < qptol), & "all(abs(diff) < qptol) failed.") #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_outer_product_rqp subroutine test_outer_product_csp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 2 complex(sp) :: u(n), v(n), expected(n,n), diff(n,n) u = [cmplx(1.,1.),cmplx(2.,0.)] v = [cmplx(1.,0.),cmplx(3.,1.)] expected = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(2.,4.),cmplx(6.,2.)],[n,n]) diff = expected - outer_product(u,v) call check(error, all(abs(diff) < sptol), & "all(abs(diff) < sptol) failed.") end subroutine test_outer_product_csp subroutine test_outer_product_cdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 2 complex(dp) :: u(n), v(n), expected(n,n), diff(n,n) u = [cmplx(1.,1.),cmplx(2.,0.)] v = [cmplx(1.,0.),cmplx(3.,1.)] expected = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(2.,4.),cmplx(6.,2.)],[n,n]) diff = expected - outer_product(u,v) call check(error, all(abs(diff) < dptol), & "all(abs(diff) < dptol) failed.") end subroutine test_outer_product_cdp subroutine test_outer_product_cqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP integer, parameter :: n = 2 complex(qp) :: u(n), v(n), expected(n,n), diff(n,n) u = [cmplx(1.,1.),cmplx(2.,0.)] v = [cmplx(1.,0.),cmplx(3.,1.)] expected = reshape([cmplx(1.,1.),cmplx(2.,0.),cmplx(2.,4.),cmplx(6.,2.)],[n,n]) diff = expected - outer_product(u,v) call check(error, all(abs(diff) < qptol), & "all(abs(diff) < qptol) failed.") #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_outer_product_cqp subroutine test_outer_product_int8(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 2 integer(int8) :: u(n), v(n), expected(n,n), diff(n,n) u = [1,2] v = [1,3] expected = reshape([1,2,3,6],[n,n]) diff = expected - outer_product(u,v) call check(error, all(abs(diff) == 0), & "all(abs(diff) == 0) failed.") end subroutine test_outer_product_int8 subroutine test_outer_product_int16(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 2 integer(int16) :: u(n), v(n), expected(n,n), diff(n,n) u = [1,2] v = [1,3] expected = reshape([1,2,3,6],[n,n]) diff = expected - outer_product(u,v) call check(error, all(abs(diff) == 0), & "all(abs(diff) == 0) failed.") end subroutine test_outer_product_int16 subroutine test_outer_product_int32(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 2 integer(int32) :: u(n), v(n), expected(n,n), diff(n,n) u = [1,2] v = [1,3] expected = reshape([1,2,3,6],[n,n]) diff = expected - outer_product(u,v) call check(error, all(abs(diff) == 0), & "all(abs(diff) == 0) failed.") end subroutine test_outer_product_int32 subroutine test_outer_product_int64(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 2 integer(int64) :: u(n), v(n), expected(n,n), diff(n,n) u = [1,2] v = [1,3] expected = reshape([1,2,3,6],[n,n]) diff = expected - outer_product(u,v) call check(error, all(abs(diff) == 0), & "all(abs(diff) == 0) failed.") end subroutine test_outer_product_int64 subroutine test_cross_product_int8(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 integer(int8) :: u(n), v(n), expected(n), diff(n) u = [1,0,0] v = [0,1,0] expected = [0,0,1] diff = expected - cross_product(u,v) call check(error, all(abs(diff) == 0), & "cross_product(u,v) == expected failed.") end subroutine test_cross_product_int8 subroutine test_cross_product_int16(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 integer(int16) :: u(n), v(n), expected(n), diff(n) u = [1,0,0] v = [0,1,0] expected = [0,0,1] diff = expected - cross_product(u,v) call check(error, all(abs(diff) == 0), & "cross_product(u,v) == expected failed.") end subroutine test_cross_product_int16 subroutine test_cross_product_int32(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 integer(int32) :: u(n), v(n), expected(n), diff(n) write(*,*) "test_cross_product_int32" u = [1,0,0] v = [0,1,0] expected = [0,0,1] diff = expected - cross_product(u,v) call check(error, all(abs(diff) == 0), & "cross_product(u,v) == expected failed.") end subroutine test_cross_product_int32 subroutine test_cross_product_int64(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 integer(int64) :: u(n), v(n), expected(n), diff(n) write(*,*) "test_cross_product_int64" u = [1,0,0] v = [0,1,0] expected = [0,0,1] diff = expected - cross_product(u,v) call check(error, all(abs(diff) == 0), & "cross_product(u,v) == expected failed.") end subroutine test_cross_product_int64 subroutine test_cross_product_rsp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 real(sp) :: u(n), v(n), expected(n), diff(n) write(*,*) "test_cross_product_rsp" u = [1.1_sp,2.5_sp,2.4_sp] v = [0.5_sp,1.5_sp,2.5_sp] expected = [2.65_sp,-1.55_sp,0.4_sp] diff = expected - cross_product(u,v) call check(error, all(abs(diff) < sptol), & "all(abs(cross_product(u,v)-expected)) < sptol failed.") end subroutine test_cross_product_rsp subroutine test_cross_product_rdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 real(dp) :: u(n), v(n), expected(n), diff(n) write(*,*) "test_cross_product_rdp" u = [1.1_dp,2.5_dp,2.4_dp] v = [0.5_dp,1.5_dp,2.5_dp] expected = [2.65_dp,-1.55_dp,0.4_dp] diff = expected - cross_product(u,v) call check(error, all(abs(diff) < dptol), & "all(abs(cross_product(u,v)-expected)) < dptol failed.") end subroutine test_cross_product_rdp subroutine test_cross_product_rqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP integer, parameter :: n = 3 real(qp) :: u(n), v(n), expected(n), diff(n) write(*,*) "test_cross_product_rqp" u = [1.1_qp,2.5_qp,2.4_qp] v = [0.5_qp,1.5_qp,2.5_qp] expected = [2.65_qp,-1.55_qp,0.4_qp] diff = expected - cross_product(u,v) call check(error, all(abs(diff) < qptol), & "all(abs(cross_product(u,v)-expected)) < qptol failed.") #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_cross_product_rqp subroutine test_cross_product_csp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 complex(sp) :: u(n), v(n), expected(n), diff(n) write(*,*) "test_cross_product_csp" u = [cmplx(0,1,sp),cmplx(1,0,sp),cmplx(0,0,sp)] v = [cmplx(1,1,sp),cmplx(0,0,sp),cmplx(1,0,sp)] expected = [cmplx(1,0,sp),cmplx(0,-1,sp),cmplx(-1,-1,sp)] diff = expected - cross_product(u,v) call check(error, all(abs(diff) < sptol), & "all(abs(cross_product(u,v)-expected)) < sptol failed.") end subroutine test_cross_product_csp subroutine test_cross_product_cdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 3 complex(dp) :: u(n), v(n), expected(n), diff(n) write(*,*) "test_cross_product_cdp" u = [cmplx(0,1,dp),cmplx(1,0,dp),cmplx(0,0,dp)] v = [cmplx(1,1,dp),cmplx(0,0,dp),cmplx(1,0,dp)] expected = [cmplx(1,0,dp),cmplx(0,-1,dp),cmplx(-1,-1,dp)] diff = expected - cross_product(u,v) call check(error, all(abs(diff) < dptol), & "all(abs(cross_product(u,v)-expected)) < dptol failed.") end subroutine test_cross_product_cdp subroutine test_cross_product_cqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP integer, parameter :: n = 3 complex(qp) :: u(n), v(n), expected(n), diff(n) write(*,*) "test_cross_product_cqp" u = [cmplx(0,1,qp),cmplx(1,0,qp),cmplx(0,0,qp)] v = [cmplx(1,1,qp),cmplx(0,0,qp),cmplx(1,0,qp)] expected = [cmplx(1,0,qp),cmplx(0,-1,qp),cmplx(-1,-1,qp)] diff = expected - cross_product(u,v) call check(error, all(abs(diff) < qptol), & "all(abs(cross_product(u,v)-expected)) < qptol failed.") #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_cross_product_cqp subroutine test_state_handling(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(linalg_state_type) :: state,state_out state = linalg_state_type(LINALG_SUCCESS,' 32-bit real: ',1.0_sp) call check(error, & state%message==' 32-bit real: 1.00000000E+00', & "malformed state message with 32-bit reals.") if (allocated(error)) return state = linalg_state_type(LINALG_SUCCESS,' 64-bit real: ',1.0_dp) call check(error, & state%message==' 64-bit real: 1.0000000000000000E+000', & "malformed state message with 64-bit reals.") if (allocated(error)) return #:if WITH_QP state = linalg_state_type(LINALG_SUCCESS,' 128-bit real: ',1.0_qp) call check(error, & state%message==' 128-bit real: 1.00000000000000000000000000000000000E+0000', & "malformed state message with 128-bit reals.") if (allocated(error)) return #:endif state = linalg_state_type(LINALG_SUCCESS,' 32-bit complex: ',(1.0_sp,1.0_sp)) call check(error, & state%message==' 32-bit complex: (1.00000000E+00,1.00000000E+00)', & "malformed state message with 32-bit complex: "//trim(state%message)) if (allocated(error)) return state = linalg_state_type(LINALG_SUCCESS,' 64-bit complex: ',(1.0_dp,1.0_dp)) call check(error, & state%message==' 64-bit complex: (1.0000000000000000E+000,1.0000000000000000E+000)', & "malformed state message with 64-bit complex.") if (allocated(error)) return #:if WITH_QP state = linalg_state_type(LINALG_SUCCESS,'128-bit complex: ',(1.0_qp,1.0_qp)) call check(error, state%message== & '128-bit complex: (1.00000000000000000000000000000000000E+0000,1.00000000000000000000000000000000000E+0000)', & "malformed state message with 128-bit complex.") #:endif state = linalg_state_type(LINALG_SUCCESS,' 32-bit array: ',[(1.0_sp,0.0_sp),(0.0_sp,1.0_sp)]) call check(error, state%message== & ' 32-bit array: [(1.00000000E+00,0.00000000E+00) (0.00000000E+00,1.00000000E+00)]', & "malformed state message with 32-bit real array.") if (allocated(error)) return !> State flag with location state = linalg_state_type('test_formats',LINALG_SUCCESS,' 32-bit real: ',1.0_sp) call check(error, & state%print()=='[test_formats] returned Success!', & "malformed state message with 32-bit real and location.") if (allocated(error)) return !> Test error handling procedure call linalg_error_handling(state,state_out) call check(error, state%print()==state_out%print(), & "malformed state message on return from error handling procedure.") end subroutine test_state_handling pure recursive function catalan_number(n) result(value) integer, intent(in) :: n integer :: value integer :: i if (n <= 1) then value = 1 else value = 0 do i = 0, n-1 value = value + catalan_number(i)*catalan_number(n-i-1) end do end if end function end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linalg, only : collect_linalg implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linalg", collect_linalg) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/terminal/0000775000175000017500000000000015135654166020760 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/terminal/CMakeLists.txt0000664000175000017500000000002015135654166023510 0ustar alastairalastairADDTEST(colors) fortran-lang-stdlib-0ede301/test/terminal/test_colors.f900000664000175000017500000000472115135654166023644 0ustar alastairalastair! SPDX-Identifier: MIT module test_colors use stdlib_ansi, only : fg_color_red, bg_color_yellow, style_bold, to_string use testdrive, only : new_unittest, unittest_type, error_type, check implicit none contains !> Collect all exported unit tests subroutine collect_colors(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("fg_color", test_fg_color), & new_unittest("bg_color", test_bg_color), & new_unittest("style", test_style) & ] end subroutine collect_colors subroutine test_fg_color(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=:), allocatable :: str str = to_string(fg_color_red) call check(error, iachar(str(1:1)), 27) if (allocated(error)) return call check(error, str(2:), "[0;31m") end subroutine test_fg_color subroutine test_bg_color(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=:), allocatable :: str str = to_string(bg_color_yellow) call check(error, iachar(str(1:1)), 27) if (allocated(error)) return call check(error, str(2:), "[0;43m") end subroutine test_bg_color subroutine test_style(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=:), allocatable :: str str = to_string(style_bold) call check(error, iachar(str(1:1)), 27) if (allocated(error)) return call check(error, str(2:), "[0;1m") end subroutine test_style end module test_colors program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_colors, only : collect_colors implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("colors", collect_colors) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/array/0000775000175000017500000000000015135654166020263 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/array/test_logicalloc.f900000664000175000017500000002201115135654166023746 0ustar alastairalastair! SPDX-Identifier: MIT module test_logicalloc use stdlib_array, only : trueloc, falseloc use stdlib_kinds, only : dp, i8 => int64 use stdlib_strings, only : to_string use testdrive, only : new_unittest, unittest_type, error_type, check implicit none private public :: collect_logicalloc contains !> Collect all exported unit tests subroutine collect_logicalloc(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("trueloc-empty", test_trueloc_empty), & new_unittest("trueloc-all", test_trueloc_all), & new_unittest("trueloc-where", test_trueloc_where), & new_unittest("trueloc-merge", test_trueloc_merge), & new_unittest("trueloc-pack", test_trueloc_pack), & new_unittest("falseloc-empty", test_falseloc_empty), & new_unittest("falseloc-all", test_falseloc_all), & new_unittest("falseloc-where", test_falseloc_where), & new_unittest("falseloc-merge", test_falseloc_merge), & new_unittest("falseloc-pack", test_falseloc_pack) & ] end subroutine collect_logicalloc subroutine test_trueloc_empty(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: ndim real, allocatable :: avec(:), bvec(:) do ndim = 100, 12000, 100 allocate(avec(ndim)) call random_number(avec) bvec = avec bvec(trueloc(bvec < 0)) = 0.0 call check(error, all(bvec == avec)) deallocate(avec, bvec) if (allocated(error)) exit end do end subroutine test_trueloc_empty subroutine test_trueloc_all(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: ndim real, allocatable :: avec(:) do ndim = 100, 12000, 100 allocate(avec(-ndim/2:ndim)) call random_number(avec) avec(trueloc(avec > 0, lbound(avec, 1))) = 0.0 call check(error, all(avec == 0.0)) deallocate(avec) if (allocated(error)) exit end do end subroutine test_trueloc_all subroutine test_trueloc_where(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: ndim real, allocatable :: avec(:), bvec(:), cvec(:) real(dp) :: tl, tw tl = 0.0_dp tw = 0.0_dp do ndim = 100, 12000, 100 allocate(avec(ndim)) call random_number(avec) avec(:) = avec - 0.5 bvec = avec tl = tl - timing() bvec(trueloc(bvec > 0)) = 0.0 tl = tl + timing() cvec = avec tw = tw - timing() where(cvec > 0) cvec = 0.0 tw = tw + timing() call check(error, all(bvec == cvec)) deallocate(avec, bvec, cvec) if (allocated(error)) exit end do call report("trueloc", tl, "where", tw) end subroutine test_trueloc_where subroutine test_trueloc_merge(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: ndim real, allocatable :: avec(:), bvec(:), cvec(:) real(dp) :: tl, tm tl = 0.0_dp tm = 0.0_dp do ndim = 100, 12000, 100 allocate(avec(ndim)) call random_number(avec) avec(:) = avec - 0.5 bvec = avec tl = tl - timing() bvec(trueloc(bvec > 0)) = 0.0 tl = tl + timing() cvec = avec tm = tm - timing() cvec(:) = merge(0.0, cvec, cvec > 0) tm = tm + timing() call check(error, all(bvec == cvec)) deallocate(avec, bvec, cvec) if (allocated(error)) exit end do call report("trueloc", tl, "merge", tm) end subroutine test_trueloc_merge subroutine test_trueloc_pack(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: ndim real, allocatable :: avec(:), bvec(:), cvec(:) real(dp) :: tl, tp tl = 0.0_dp tp = 0.0_dp do ndim = 100, 12000, 100 allocate(avec(ndim)) call random_number(avec) avec(:) = avec - 0.5 bvec = avec tl = tl - timing() bvec(trueloc(bvec > 0)) = 0.0 tl = tl + timing() cvec = avec tp = tp - timing() block integer :: i cvec(pack([(i, i=1, size(cvec))], cvec > 0)) = 0.0 end block tp = tp + timing() call check(error, all(bvec == cvec)) deallocate(avec, bvec, cvec) if (allocated(error)) exit end do call report("trueloc", tl, "pack", tp) end subroutine test_trueloc_pack subroutine test_falseloc_empty(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: ndim real, allocatable :: avec(:), bvec(:) do ndim = 100, 12000, 100 allocate(avec(ndim)) call random_number(avec) bvec = avec bvec(falseloc(bvec > 0)) = 0.0 call check(error, all(bvec == avec)) deallocate(avec, bvec) if (allocated(error)) exit end do end subroutine test_falseloc_empty subroutine test_falseloc_all(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: ndim real, allocatable :: avec(:) do ndim = 100, 12000, 100 allocate(avec(-ndim/2:ndim)) call random_number(avec) avec(falseloc(avec < 0, lbound(avec, 1))) = 0.0 call check(error, all(avec == 0.0)) deallocate(avec) if (allocated(error)) exit end do end subroutine test_falseloc_all subroutine test_falseloc_where(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: ndim real, allocatable :: avec(:), bvec(:), cvec(:) real(dp) :: tl, tw tl = 0.0_dp tw = 0.0_dp do ndim = 100, 12000, 100 allocate(avec(ndim)) call random_number(avec) avec(:) = avec - 0.5 bvec = avec tl = tl - timing() bvec(falseloc(bvec > 0)) = 0.0 tl = tl + timing() cvec = avec tw = tw - timing() where(.not.(cvec > 0)) cvec = 0.0 tw = tw + timing() call check(error, all(bvec == cvec)) deallocate(avec, bvec, cvec) if (allocated(error)) exit end do call report("falseloc", tl, "where", tw) end subroutine test_falseloc_where subroutine test_falseloc_merge(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: ndim real, allocatable :: avec(:), bvec(:), cvec(:) real(dp) :: tl, tm tl = 0.0_dp tm = 0.0_dp do ndim = 100, 12000, 100 allocate(avec(ndim)) call random_number(avec) avec(:) = avec - 0.5 bvec = avec tl = tl - timing() bvec(falseloc(bvec > 0)) = 0.0 tl = tl + timing() cvec = avec tm = tm - timing() cvec(:) = merge(cvec, 0.0, cvec > 0) tm = tm + timing() call check(error, all(bvec == cvec)) deallocate(avec, bvec, cvec) if (allocated(error)) exit end do call report("falseloc", tl, "merge", tm) end subroutine test_falseloc_merge subroutine test_falseloc_pack(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: ndim real, allocatable :: avec(:), bvec(:), cvec(:) real(dp) :: tl, tp tl = 0.0_dp tp = 0.0_dp do ndim = 100, 12000, 100 allocate(avec(ndim)) call random_number(avec) avec(:) = avec - 0.5 bvec = avec tl = tl - timing() bvec(falseloc(bvec > 0)) = 0.0 tl = tl + timing() cvec = avec tp = tp - timing() block integer :: i cvec(pack([(i, i=1, size(cvec))], cvec < 0)) = 0.0 end block tp = tp + timing() call check(error, all(bvec == cvec)) deallocate(avec, bvec, cvec) if (allocated(error)) exit end do call report("falseloc", tl, "pack", tp) end subroutine test_falseloc_pack subroutine report(l1, t1, l2, t2) character(len=*), intent(in) :: l1, l2 real(dp), intent(in) :: t1, t2 character(len=*), parameter :: fmt = "f6.4" !$omp critical print '(2x, "[Timing]", *(1x, g0))', & l1//":", to_string(t1, fmt)//"s", & l2//":", to_string(t2, fmt)//"s", & "ratio:", to_string(t1/t2, "f4.1") !$omp end critical end subroutine report function timing() result(time) real(dp) :: time integer(i8) :: time_count, time_rate, time_max call system_clock(time_count, time_rate, time_max) time = real(time_count, dp)/real(time_rate, dp) end function timing end module test_logicalloc program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_logicalloc, only : collect_logicalloc implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("logicalloc", collect_logicalloc) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/array/CMakeLists.txt0000664000175000017500000000002415135654166023017 0ustar alastairalastairADDTEST(logicalloc) fortran-lang-stdlib-0ede301/test/specialfunctions/0000775000175000017500000000000015135654166022516 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/specialfunctions/CMakeLists.txt0000664000175000017500000000045615135654166025263 0ustar alastairalastair### Pre-process: .fpp -> .f90 via Fypp # Create a list of the files to be preprocessed set(fppFiles test_specialfunctions_activations.fypp test_specialfunctions_gamma.fypp ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) ADDTEST(specialfunctions_gamma) ADDTEST(specialfunctions_activations)fortran-lang-stdlib-0ede301/test/specialfunctions/test_specialfunctions_activations.fypp0000664000175000017500000003675415135654166032451 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = [KT for KT in REAL_KINDS_TYPES if KT[0] in ["sp","dp"]] module test_specialfunctions_activation use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_kinds use stdlib_specialfunctions use stdlib_math, only: linspace implicit none private public :: collect_specialfunctions_activation ! use a low accuracy tolerance for the tests as activations should be fast ! and not necessarily accurate #:for k, t in R_KINDS_TYPES ${t}$, parameter :: tol_${k}$ = 1e-4_${k}$ #:endfor contains subroutine collect_specialfunctions_activation(testsuite) type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("gaussian", test_gaussian), & new_unittest("elu", test_elu), & new_unittest("relu", test_relu), & new_unittest("leaky_relu", test_leaky_relu), & new_unittest("gelu" , test_gelu), & new_unittest("selu" , test_selu), & new_unittest("sigmoid", test_sigmoid), & new_unittest("silu" , test_silu), & new_unittest("softmax", test_softmax), & new_unittest("logsoftmax", test_logsoftmax) & ] end subroutine collect_specialfunctions_activation subroutine test_gaussian(error) type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 10 #:for k, t in R_KINDS_TYPES block ${t}$ :: x(n), y(n), y_ref(n) x = linspace(-2._${k}$, 2._${k}$, n) y_ref = exp(-x**2) y = gaussian( x ) call check(error, norm2(y-y_ref) < n*tol_sp ) if (allocated(error)) return ! Derivative y_ref = -2._${k}$ * x * exp(-x**2) y = gaussian_grad( x ) call check(error, norm2(y-y_ref) < n*tol_sp ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_elu(error) type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 10 #:for k, t in R_KINDS_TYPES block ${t}$ :: x(n), y(n), y_ref(n), a x = linspace(-2._${k}$ , 2._${k}$, n) a = 1.0_${k}$ where(x >= 0._${k}$) y_ref = x elsewhere y_ref = a * (exp(x) - 1._${k}$) end where y = elu( x , a ) call check(error, norm2(y-y_ref) < n*tol_sp ) if (allocated(error)) return ! Derivative where(x >= 0._${k}$) y_ref = 1.0_${k}$ elsewhere y_ref = a * exp(x) end where y = elu_grad( x , a ) call check(error, norm2(y-y_ref) < n*tol_sp ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_relu(error) type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 10 #:for k, t in R_KINDS_TYPES block ${t}$ :: x(n), y(n), y_ref(n) x = linspace(-2._${k}$ , 2._${k}$, n) y_ref = max(0._${k}$, x) y = relu( x ) call check(error, norm2(y-y_ref) < n*tol_sp ) if (allocated(error)) return ! Derivative where(x > 0._${k}$) y_ref = 1.0_${k}$ elsewhere y_ref = 0.0_${k}$ end where y = relu_grad( x ) call check(error, norm2(y-y_ref) < n*tol_sp ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_selu(error) type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 10 #:for k, t in R_KINDS_TYPES block ${t}$, parameter :: scale = 1.0507009873554804934193349852946_${k}$ ${t}$, parameter :: alpha = 1.6732632423543772848170429916717_${k}$ ${t}$ :: x(n), y(n), y_ref(n) x = linspace(-2._${k}$, 2._${k}$, n) where(x >= 0._${k}$) y_ref = scale * x elsewhere y_ref = scale * (alpha * exp(x) - alpha) end where y = selu( x ) call check(error, norm2(y-y_ref) < n*tol_${k}$ ) if (allocated(error)) return ! Derivative where(x >= 0._${k}$) y_ref = scale elsewhere y_ref = scale * alpha * exp(x) end where y = selu_grad( x ) call check(error, norm2(y-y_ref) < n*tol_${k}$ ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_gelu(error) type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 10 #:for k, t in R_KINDS_TYPES block ${t}$ :: x(n), y(n), y_ref(n) y_ref = [-0.0455002784729 , -0.093188509345055, -0.148066952824593,& -0.168328359723091, -0.0915712043643 , 0.130650997161865,& 0.498338282108307, 0.963044226169586, 1.462367057800293,& 1.9544997215271 ] x = linspace(-2._${k}$, 2._${k}$, n) y = gelu( x ) call check(error, norm2(y-y_ref) < n*tol_${k}$ ) if (allocated(error)) return y = gelu_approx( x ) call check(error, norm2(y-y_ref) < n*tol_${k}$ ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_leaky_relu(error) type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 10 #:for k, t in R_KINDS_TYPES block ${t}$ :: x(n), y(n), y_ref(n), a call random_number(x) a = 0.1_${k}$ where(x>=0._${k}$) y_ref = x elsewhere y_ref = a * x end where y = leaky_relu( x , a ) call check(error, norm2(y-y_ref) < n*tol_${k}$ ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_sigmoid(error) type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 10 #:for k, t in R_KINDS_TYPES block ${t}$ :: x(n), y(n), y_ref(n) y_ref = [0.119202919304371, 0.174285307526588, 0.247663781046867,& 0.339243650436401, 0.444671928882599, 0.555328071117401,& 0.660756349563599, 0.752336204051971, 0.825714707374573,& 0.880797028541565] x = linspace(-2._${k}$, 2._${k}$, n) y = sigmoid( x ) call check(error, norm2(y-y_ref) < n*tol_${k}$ ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_silu(error) type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 10 #:for k, t in R_KINDS_TYPES block ${t}$ :: x(n), y(n), y_ref(n), a x = linspace(-2._${k}$, 2._${k}$, n) y_ref = x / (1._${k}$ + exp(-x)) y = silu( x ) call check(error, norm2(y-y_ref) < n*tol_${k}$ ) if (allocated(error)) return ! Derivative y_ref = (1._${k}$ + exp(x))**2 y_ref = exp(x) * ( x + y_ref ) / y_ref y = silu_grad( x ) call check(error, norm2(y-y_ref) < n*tol_${k}$ ) if (allocated(error)) return end block #:endfor end subroutine subroutine test_softmax(error) type(error_type), allocatable, intent(out) :: error #:for k, t in R_KINDS_TYPES block ${t}$ :: x(3,3,3), y(3,3,3), y_ref(3,3,3) x = reshape( [ 0.82192878, 0.76998032, 0.98611263,& 0.8621334 , 0.65358045, 0.26387113,& 0.12743663, 0.35237132, 0.23801647,& 0.69773567, 0.40568874, 0.44789482,& 0.42930753, 0.49579193, 0.53139985,& 0.03035799, 0.65293157, 0.47613957,& 0.21088634, 0.9356926 , 0.0991312 ,& 0.46070181, 0.02943479, 0.17557538,& 0.10541313, 0.33946349, 0.34804323 ] ,[3,3,3] ) !> softmax on dim = 1 y = softmax(x,dim=1) y_ref = reshape( [ 0.319712639, 0.303528070, 0.376759291,& 0.423455358, 0.343743294, 0.232801422,& 0.296809316, 0.371676773, 0.331513911,& 0.395936400, 0.295658976, 0.308404684,& 0.314838648, 0.336482018, 0.348679334,& 0.225966826, 0.421138495, 0.352894694,& 0.252614945, 0.521480858, 0.225904226,& 0.416388273, 0.270521373, 0.313090324,& 0.282621205, 0.357150704, 0.360228121 ] ,[3,3,3] ) call check(error, norm2(y-y_ref) < tol_${k}$ ) if (allocated(error)) return !> softmax on dim = 2 y = softmax(x,dim=2) y_ref = reshape( [ 0.393646270, 0.392350882, 0.510482967,& 0.409795105, 0.349239051, 0.247922391,& 0.196558580, 0.258410037, 0.241594598,& 0.439052343, 0.296315849, 0.320951223,& 0.335690796, 0.324254662, 0.348903090,& 0.225256786, 0.379429489, 0.330145657,& 0.314101219, 0.511530280, 0.297435701,& 0.403239518, 0.206675291, 0.321064562,& 0.282659233, 0.281794399, 0.381499708 ] ,[3,3,3] ) call check(error, norm2(y-y_ref) < tol_${k}$ ) if (allocated(error)) return !> softmax on dim = 3 y = softmax(x,dim=3) y_ref = reshape( [ 0.412202179, 0.347835541, 0.501081109,& 0.431399941, 0.418453932, 0.310344934,& 0.346536130, 0.299599379, 0.295405835,& 0.364060789, 0.241637364, 0.292525023,& 0.279837668, 0.357372403, 0.405537367,& 0.314476222, 0.404643506, 0.374830246,& 0.223737061, 0.410527140, 0.206393898,& 0.288762331, 0.224173695, 0.284117699,& 0.338987619, 0.295757085, 0.329763889 ] ,[3,3,3] ) call check(error, norm2(y-y_ref) < tol_${k}$ ) if (allocated(error)) return end block #:endfor end subroutine test_softmax subroutine test_logsoftmax(error) type(error_type), allocatable, intent(out) :: error #:for k, t in R_KINDS_TYPES block ${t}$ :: x(3,3,3), y(3,3,3), y_ref(3,3,3) x = reshape( [ 0.755308866500854,-0.789980888366699, 0.88806813955307 ,& -1.210636496543884, 0.746919095516205, 0.177668794989586,& 0.540819883346558, 0.291532933712006,-0.324642956256866,& 1.94184136390686 , 0.951070547103882,-2.303410291671753,& 0.59752631187439 , 1.189722180366516, 1.401878595352173,& -0.262732744216919, 0.421907186508179,-0.200457707047462,& -0.702468574047089, 0.153426378965378, 0.330110251903534,& -1.16956090927124 ,-0.845042765140533,-1.364316940307617,& -1.679381608963013,-1.497506022453308,-1.194215059280396 ] ,[3,3,3] ) !> logsoftmax on dim = 1 y = logsoftmax(x,dim=1) y_ref = reshape( [ -0.856636286,-2.40192604,-0.723877013,& -2.49238253,-0.534826934,-1.10407722 ,& -0.788554132,-1.03784108,-1.65401697 ,& -0.326149583,-1.31692040,-4.57140112 ,& -1.61804128,-1.02584541,-0.813688993 ,& -1.39805317,-0.713413179,-1.33577800 ,& -1.81836534,-0.962470412,-0.785786569,& -1.16514850,-0.840630412,-1.35990453 ,& -1.34127355,-1.15939808,-0.856107056 ],[3,3,3] ) !> logsoftmax on dim = 2 y = logsoftmax(x,dim=2) y_ref = reshape( [ -0.666278005,-2.15167999, -0.581566215,& -2.63222337 ,-0.614779949,-1.29196548 ,& -0.880766988,-1.07016611,-1.79427731 ,& -0.315551817,-1.05034387,-3.90906072 ,& -1.65986681 ,-0.811692238,-0.203771874,& -2.52012587 ,-1.57950723 ,-1.80610812 ,& -0.694792688,-0.444887042,-0.337523341,& -1.16188502 ,-1.44335616 ,-2.03195047 ,& -1.67170572 ,-2.09581947 ,-1.86184871 ],[3,3,3] ) call check(error, norm2(y-y_ref) < tol_${k}$ ) if (allocated(error)) return !> logsoftmax on dim = 3 y = logsoftmax(x,dim=3) y_ref = reshape( [ -1.50595474 , -2.22700500 ,-0.478398114,& -2.09693313 , -1.01544499 ,-1.52940571 ,& -0.442325860, -0.835677147,-0.936625183,& -0.319422185, -0.485953659,-3.66987658 ,& -0.288770229, -0.572641909,-0.305195898,& -1.24587846 , -0.705302894,-0.812439919,& -2.96373224 , -1.28359783 ,-1.03635597 ,& -2.05585742 , -2.60740685 ,-3.07139134 ,& -2.66252732 , -2.62471604 ,-1.80619729 ],[3,3,3] ) call check(error, norm2(y-y_ref) < tol_${k}$ ) if (allocated(error)) return end block #:endfor end subroutine test_logsoftmax end module test_specialfunctions_activation program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_specialfunctions_activation, only : collect_specialfunctions_activation implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [new_testsuite("activation functions", & collect_specialfunctions_activation)] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program testerfortran-lang-stdlib-0ede301/test/specialfunctions/test_specialfunctions_gamma.fypp0000664000175000017500000005653715135654166031210 0ustar alastairalastair#:include "common.fypp" #:set CI_KINDS_TYPES = INT_KINDS_TYPES + CMPLX_KINDS_TYPES #:set IDX_CMPLX_KINDS_TYPES = [(i, CMPLX_KINDS[i], CMPLX_TYPES[i], CMPLX_INIT[i]) for i in range(len(CMPLX_KINDS))] #:set IDX_REAL_KINDS_TYPES = [(i, REAL_KINDS[i], REAL_TYPES[i], REAL_INIT[i]) for i in range(len(REAL_KINDS))] module test_specialfunctions_gamma use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_kinds, only: sp, dp, xdp, qp, int8, int16, int32, int64 use stdlib_error, only: state_type, STDLIB_VALUE_ERROR use stdlib_specialfunctions_gamma, only: gamma, log_gamma, log_factorial, & lower_incomplete_gamma, & upper_incomplete_gamma, & log_lower_incomplete_gamma, & log_upper_incomplete_gamma, & regularized_gamma_p, & regularized_gamma_q implicit none private public :: collect_specialfunctions_gamma #:for k1, t1 in REAL_KINDS_TYPES ${t1}$, parameter :: tol_${k1}$ = sqrt(epsilon(1.0_${k1}$)) #:endfor contains subroutine collect_specialfunctions_gamma(testsuite) type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("log_factorial_iint8", test_logfact_iint8) & #:for k1, t1 in INT_KINDS_TYPES , new_unittest("log_factorial_${t1[0]}$${k1}$", & test_logfact_${t1[0]}$${k1}$) & #:endfor #:for k1, t1 in CI_KINDS_TYPES[:-1] , new_unittest("gamma_${t1[0]}$${k1}$", & test_gamma_${t1[0]}$${k1}$) & , new_unittest("log_gamma_${t1[0]}$${k1}$", & test_loggamma_${t1[0]}$${k1}$) & #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] , new_unittest("lower_incomplete_gamma_${t1[0]}$${k1}$${k2}$", & test_lincgamma_${t1[0]}$${k1}$${k2}$) & , new_unittest("log_lower_incomplete_gamma_${t1[0]}$${k1}$${k2}$", & test_log_lincgamma_${t1[0]}$${k1}$${k2}$) & , new_unittest("upper_incomplete_gamma_${t1[0]}$${k1}$${k2}$", & test_uincgamma_${t1[0]}$${k1}$${k2}$) & , new_unittest("log_upper_incomplete_gamma_${t1[0]}$${k1}$${k2}$", & test_log_uincgamma_${t1[0]}$${k1}$${k2}$) & , new_unittest("regularized_gamma_p_${t1[0]}$${k1}$${k2}$", & test_gamma_p_${t1[0]}$${k1}$${k2}$) & , new_unittest("regularized_gamma_q_${t1[0]}$${k1}$${k2}$", & test_gamma_q_${t1[0]}$${k1}$${k2}$) & #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] , new_unittest("lower_incomplete_gamma_${t1[0]}$${k1}$", & test_lincgamma_${t1[0]}$${k1}$) & , new_unittest("log_lower_incomplete_gamma_${t1[0]}$${k1}$", & test_log_lincgamma_${t1[0]}$${k1}$) & , new_unittest("upper_incomplete_gamma_${t1[0]}$${k1}$", & test_uincgamma_${t1[0]}$${k1}$) & , new_unittest("log_upper_incomplete_gamma_${t1[0]}$${k1}$", & test_log_uincgamma_${t1[0]}$${k1}$) & , new_unittest("regularized_gamma_p_${t1[0]}$${k1}$", & test_gamma_p_${t1[0]}$${k1}$) & , new_unittest("regularized_gamma_q_${t1[0]}$${k1}$", & test_gamma_q_${t1[0]}$${k1}$) & #:endfor ] end subroutine collect_specialfunctions_gamma #:for k1, t1 in INT_KINDS_TYPES #:set k2, t2 = REAL_KINDS[-2], REAL_TYPES[-2] subroutine test_logfact_${t1[0]}$${k1}$(error) type(error_type), allocatable, intent(out) :: error integer :: i integer, parameter :: xtest(*) = [0,1,2,4,5,7,12,20,100,500,7000,90000] ${t2}$, parameter :: res(*) = [0.0_${k2}$, & 0.0_${k2}$, & 0.69314718055994_${k2}$, & 3.17805383034794_${k2}$, & 4.78749174278204_${k2}$, & 8.52516136106541_${k2}$, & 1.998721449566e1_${k2}$, & 4.233561646075e1_${k2}$, & 3.637393755555e2_${k2}$, & 2.611330458460e3_${k2}$, & 5.498100377941e4_${k2}$, & 9.366874681600e5_${k2}$] ${t1}$, parameter :: x(*) = pack(xtest, xtest 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/specialfunctions/Makefile.manual0000664000175000017500000000030615135654166025431 0ustar alastairalastairSRCFYPP = \ test_specialfunctions_gamma.fypp SRCGEN = $(SRCFYPP:.fypp=.f90) $(SRCGEN): %.f90: %.fypp ../../common.fypp fypp -I../.. $(FYPPFLAGS) $< $@ include ../Makefile.manual.test.mk fortran-lang-stdlib-0ede301/test/io/0000775000175000017500000000000015135654166017554 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/io/test_loadtxt_qp.fypp0000664000175000017500000000720515135654166023676 0ustar alastairalastair#:include "common.fypp" module test_loadtxt_qp use stdlib_kinds, only: qp use stdlib_io, only: loadtxt, savetxt use testdrive, only: new_unittest, unittest_type, error_type, check, skip_test implicit none private public :: collect_loadtxt_qp contains !> Collect all exported unit tests subroutine collect_loadtxt_qp(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("loadtxt_qp", test_loadtxt_qp_), & new_unittest("loadtxt_qp_huge", test_loadtxt_qp_huge), & new_unittest("loadtxt_qp_tiny", test_loadtxt_qp_tiny) & ] end subroutine collect_loadtxt_qp subroutine test_loadtxt_qp_(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP real(qp), allocatable :: input(:,:), expected(:,:) integer :: n allocate(input(10,10)) allocate(expected(10,10)) do n = 1, 100 call random_number(input) input = input - 0.5 call savetxt('test_qp.txt', input) call loadtxt('test_qp.txt', expected) call check(error, all(input == expected)) if (allocated(error)) return end do #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_loadtxt_qp_ subroutine test_loadtxt_qp_huge(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP real(qp), allocatable :: input(:,:), expected(:,:) integer :: n allocate(input(10,10)) allocate(expected(10,10)) do n = 1, 10 call random_number(input) input = (input - 0.5) * huge(input) call savetxt('test_qp_huge.txt', input) call loadtxt('test_qp_huge.txt', expected) call check(error, all(input == expected)) if (allocated(error)) return end do #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_loadtxt_qp_huge subroutine test_loadtxt_qp_tiny(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP real(qp), allocatable :: input(:,:), expected(:,:) integer :: n allocate(input(10,10)) allocate(expected(10,10)) do n = 1, 10 call random_number(input) input = (input - 0.5) * tiny(input) call savetxt('test_qp_tiny.txt', input) call loadtxt('test_qp_tiny.txt', expected) call check(error, all(input == expected)) if (allocated(error)) return end do #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_loadtxt_qp_tiny end module test_loadtxt_qp program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_loadtxt_qp, only : collect_loadtxt_qp implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("loadtxt_qp", collect_loadtxt_qp) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/io/test_npy.f900000664000175000017500000005765015135654166021756 0ustar alastairalastairmodule test_npy use stdlib_kinds, only : int8, int16, int32, int64, sp, dp use stdlib_io_npy, only : save_npy, load_npy use testdrive, only : new_unittest, unittest_type, error_type, check implicit none private public :: collect_npy contains !> Collect all exported unit tests subroutine collect_npy(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("read-rdp-r2", test_read_rdp_rank2), & new_unittest("read-rdp-r3", test_read_rdp_rank3), & new_unittest("read-rsp-r1", test_read_rsp_rank1), & new_unittest("read-rsp-r2", test_read_rsp_rank2), & new_unittest("write-rdp-r2", test_write_rdp_rank2), & new_unittest("write-rsp-r2", test_write_rsp_rank2), & new_unittest("write-i2-r4", test_write_int16_rank4), & new_unittest("invalid-magic-number", test_invalid_magic_number, should_fail=.true.), & new_unittest("invalid-magic-string", test_invalid_magic_string, should_fail=.true.), & new_unittest("invalid-major-version", test_invalid_major_version, should_fail=.true.), & new_unittest("invalid-minor-version", test_invalid_minor_version, should_fail=.true.), & new_unittest("invalid-header-len", test_invalid_header_len, should_fail=.true.), & new_unittest("invalid-nul-byte", test_invalid_nul_byte, should_fail=.true.), & new_unittest("invalid-key", test_invalid_key, should_fail=.true.), & new_unittest("invalid-comma", test_invalid_comma, should_fail=.true.), & new_unittest("invalid-string", test_invalid_string, should_fail=.true.), & new_unittest("duplicate-descr", test_duplicate_descr, should_fail=.true.), & new_unittest("missing-descr", test_missing_descr, should_fail=.true.), & new_unittest("missing-fortran_order", test_missing_fortran_order, should_fail=.true.), & new_unittest("missing-shape", test_missing_shape, should_fail=.true.), & new_unittest("iomsg-deallocated", test_iomsg_deallocated) & ] end subroutine collect_npy subroutine test_read_rdp_rank2(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr':' Error handling type(error_type), allocatable, intent(out) :: error integer :: stat character(len=*), parameter :: filename = ".test-rdp-r2-rt.npy" real(dp), allocatable :: input(:, :), output(:, :) allocate(input(10, 4)) call random_number(input) call save_npy(filename, input, stat) call check(error, stat, "Writing of npy file failed") if (allocated(error)) return call load_npy(filename, output, stat) call delete_file(filename) call check(error, stat, "Reading of npy file failed") if (allocated(error)) return call check(error, size(output), size(input)) if (allocated(error)) return call check(error, any(abs(output - input) <= epsilon(1.0_dp)), & "Precision loss when rereading array") end subroutine test_write_rdp_rank2 subroutine test_write_rsp_rank2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: stat character(len=*), parameter :: filename = ".test-rsp-r2-rt.npy" real(sp), allocatable :: input(:, :), output(:, :) allocate(input(12, 5)) call random_number(input) call save_npy(filename, input, stat) call check(error, stat, "Writing of npy file failed") if (allocated(error)) return call load_npy(filename, output, stat) call delete_file(filename) call check(error, stat, "Reading of npy file failed") if (allocated(error)) return call check(error, size(output), size(input)) if (allocated(error)) return call check(error, any(abs(output - input) <= epsilon(1.0_dp)), & "Precision loss when rereading array") end subroutine test_write_rsp_rank2 subroutine test_write_int16_rank4(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: stat, i character(len=*), parameter :: filename = ".test-i2-r4-rt.npy" integer(int16), allocatable :: input(:, :, :, :), output(:, :, :, :) input = reshape([(i*(i+1)/2, i = 1, 40)], [2, 5, 2, 2]) call save_npy(filename, input, stat) call check(error, stat, "Writing of npy file failed") if (allocated(error)) return call load_npy(filename, output, stat) call delete_file(filename) call check(error, stat, "Reading of npy file failed") if (allocated(error)) return call check(error, size(output), size(input)) if (allocated(error)) return call check(error, all(abs(output - input) == 0), & "Precision loss when rereading array") end subroutine test_write_int16_rank4 subroutine test_invalid_magic_number(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'fortran_order': True, 'shape': (10, 4, ), 'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'fortran_order': True,, 'shape': (10, 4, ), 'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'fortran_order': True, 'shape': (10, 4, ), 'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'fortran_order': True, 'shape': (10, 4, ), } " // & char(10) character(len=*), parameter :: header = & char(int(z"93")) // "NUMPY" // char(1) // char(0) // & char(len(dict)) // char(0) // dict integer :: io, stat character(len=:), allocatable :: msg character(len=*), parameter :: filename = ".test-missing-descr.npy" real(dp), allocatable :: array(:, :) open(newunit=io, file=filename, form="unformatted", access="stream") write(io) header write(io) spread(0.0_dp, 1, 40) close(io) call load_npy(filename, array, stat, msg) call delete_file(filename) call check(error, stat, msg) end subroutine test_missing_descr subroutine test_missing_fortran_order(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'descr': ' Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: dict = & "{'fortran_order': True, 'descr': ' Error handling type(error_type), allocatable, intent(out) :: error integer :: stat character(len=:), allocatable :: msg character(len=*), parameter :: filename = ".test-iomsg-deallocated.npy" real(sp), allocatable :: input(:, :) msg = "This message should be deallocated." allocate(input(12, 5)) call random_number(input) call save_npy(filename, input, stat, msg) call delete_file(filename) call check(error,.not. allocated(msg), "Message wrongly allocated.") end subroutine subroutine delete_file(filename) character(len=*), intent(in) :: filename integer :: io open(newunit=io, file=filename) close(io, status="delete") end subroutine delete_file end module test_npy program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_npy, only : collect_npy implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("npy", collect_npy) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/io/test_open.f900000664000175000017500000001111315135654166022071 0ustar alastairalastairmodule test_open use stdlib_io, only: open use testdrive, only: new_unittest, unittest_type, error_type, check implicit none private public :: collect_open contains !> Collect all exported unit tests subroutine collect_open(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("io_read_write_text", test_io_read_write_text), & new_unittest("io_read_write_stream", test_io_read_write_stream), & new_unittest("io_open_error_flag", test_io_open_error_flag) & ] end subroutine collect_open function get_outpath() result(outpath) integer :: ierr character(256) :: argv character(:), allocatable :: outpath call get_command_argument(1, argv, status=ierr) if (ierr == 0) then outpath = trim(argv) else outpath = '.' end if end function get_outpath subroutine test_io_read_write_text(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(:), allocatable :: filename integer :: u, a(3) ! Text file filename = get_outpath() // "/io_open.dat" ! Test mode "w" u = open(filename, "w") write(u, *) 1, 2, 3 close(u) ! Test mode "r" u = open(filename, "r") read(u, *) a call check(error, all(a == [1, 2, 3])) close(u) if (allocated(error)) return ! Test mode "a" u = open(filename, "a") write(u, *) 4, 5, 6 close(u) u = open(filename, "r") read(u, *) a call check(error, all(a == [1, 2, 3])) read(u, *) a call check(error, all(a == [4, 5, 6])) close(u) if (allocated(error)) return end subroutine test_io_read_write_text subroutine test_io_read_write_stream(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(:), allocatable :: filename integer :: u, a(3) ! Stream file filename = get_outpath() // "/io_open.stream" ! Test mode "w" u = open(filename, "wb") write(u) 1, 2, 3 close(u) ! Test mode "r" u = open(filename, "rb") read(u) a call check(error, all(a == [1, 2, 3])) close(u) if (allocated(error)) return ! Test mode "a" u = open(filename, "ab") write(u) 4, 5, 6 close(u) u = open(filename, "rb") read(u) a call check(error, all(a == [1, 2, 3])) read(u) a if (allocated(error)) return call check(error, all(a == [4, 5, 6])) close(u) if (allocated(error)) return end subroutine test_io_read_write_stream subroutine test_io_open_error_flag(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(:), allocatable :: filename integer :: ierr, u filename = get_outpath() // "/io_open.stream" ! Write to file first to ensure that it exists u = open(filename, "wb") write(u) 1, 2, 3 close(u) u = open(filename, "rb", ierr) call check(error, ierr == 0) if (ierr == 0) close(u) if (allocated(error)) return u = open(filename, "ab", ierr) call check(error, ierr == 0) if (ierr == 0) close(u) if (allocated(error)) return filename = get_outpath() // "/does_not_exist.error" u = open(filename, "a", ierr) call check(error, ierr /= 0) if (allocated(error)) return u = open(filename, "r", ierr) call check(error, ierr /= 0) if (allocated(error)) return end subroutine test_io_open_error_flag end module test_open program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_open, only : collect_open implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("open", collect_open) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/io/test_savetxt_qp.fypp0000664000175000017500000000724715135654166023723 0ustar alastairalastair#:include "common.fypp" module test_savetxt_qp use stdlib_kinds, only: qp use stdlib_io, only: loadtxt, savetxt use testdrive, only: new_unittest, unittest_type, error_type, check, skip_test implicit none private public :: collect_savetxt_qp contains !> Collect all exported unit tests subroutine collect_savetxt_qp(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("rqp", test_rqp), & new_unittest("cqp", test_cqp) & ] end subroutine collect_savetxt_qp function get_outpath() result(outpath) integer :: ierr character(256) :: argv character(:), allocatable :: outpath call get_command_argument(1, argv, status=ierr) if (ierr == 0) then outpath = trim(argv) else outpath = '.' end if end function get_outpath subroutine test_rqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP real(qp) :: d(3, 2), e(2, 3) real(qp), allocatable :: d2(:, :) character(:), allocatable :: outpath outpath = get_outpath() // "/tmp_test_rqp.dat" d = reshape([1, 2, 3, 4, 5, 6], [3, 2]) call savetxt(outpath, d) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [3, 2])) if (allocated(error)) return call check(error, all(d == d2)) if (allocated(error)) return e = reshape([1, 2, 3, 4, 5, 6], [2, 3]) call savetxt(outpath, e) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [2, 3])) if (allocated(error)) return call check(error, all(e == d2)) if (allocated(error)) return #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_rqp subroutine test_cqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP complex(qp) :: d(3, 2), e(2, 3) complex(qp), allocatable :: d2(:, :) character(:), allocatable :: outpath outpath = get_outpath() // "/tmp_test_cqp.dat" d = reshape([1, 2, 3, 4, 5, 6], [3, 2]) call savetxt(outpath, d) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [3, 2])) if (allocated(error)) return call check(error, all(d == d2)) if (allocated(error)) return e = reshape([1, 2, 3, 4, 5, 6], [2, 3]) call savetxt(outpath, e) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [2, 3])) if (allocated(error)) return call check(error, all(e == d2)) if (allocated(error)) return #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_cqp end module test_savetxt_qp program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_savetxt_qp, only : collect_savetxt_qp implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("savetxt_qp", collect_savetxt_qp) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/io/test_savetxt.f900000664000175000017500000001443415135654166022637 0ustar alastairalastairmodule test_savetxt use stdlib_kinds, only: int32, sp, dp use stdlib_io, only: loadtxt, savetxt use testdrive, only: new_unittest, unittest_type, error_type, check implicit none private public :: collect_savetxt contains !> Collect all exported unit tests subroutine collect_savetxt(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("iint32", test_iint32), & new_unittest("rsp", test_rsp), & new_unittest("rdp", test_rdp), & new_unittest("csp", test_csp), & new_unittest("cdp", test_cdp) & ] end subroutine collect_savetxt function get_outpath() result(outpath) integer :: ierr character(256) :: argv character(:), allocatable :: outpath call get_command_argument(1, argv, status=ierr) if (ierr == 0) then outpath = trim(argv) else outpath = '.' end if end function get_outpath subroutine test_iint32(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(int32) :: d(3, 2), e(2, 3) integer(int32), allocatable :: d2(:, :) character(:), allocatable :: outpath outpath = get_outpath() // "/tmp_test_iint32.dat" d = reshape([1, 2, 3, 4, 5, 6], [3, 2]) call savetxt(outpath, d) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [3, 2])) if (allocated(error)) return call check(error, all(d == d2)) if (allocated(error)) return e = reshape([1, 2, 3, 4, 5, 6], [2, 3]) call savetxt(outpath, e) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [2, 3])) if (allocated(error)) return call check(error, all(e == d2)) if (allocated(error)) return end subroutine subroutine test_rsp(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(sp) :: d(3, 2), e(2, 3) real(sp), allocatable :: d2(:, :) character(:), allocatable :: outpath outpath = get_outpath() // "/tmp_test_rsp.dat" d = reshape([1, 2, 3, 4, 5, 6], [3, 2]) call savetxt(outpath, d) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [3, 2])) if (allocated(error)) return call check(error, all(d == d2)) if (allocated(error)) return e = reshape([1, 2, 3, 4, 5, 6], [2, 3]) call savetxt(outpath, e) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [2, 3])) if (allocated(error)) return call check(error, all(e == d2)) if (allocated(error)) return end subroutine test_rsp subroutine test_rdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(dp) :: d(3, 2), e(2, 3) real(dp), allocatable :: d2(:, :) character(:), allocatable :: outpath outpath = get_outpath() // "/tmp_test_rdp.dat" d = reshape([1, 2, 3, 4, 5, 6], [3, 2]) call savetxt(outpath, d) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [3, 2])) if (allocated(error)) return call check(error, all(d == d2)) if (allocated(error)) return e = reshape([1, 2, 3, 4, 5, 6], [2, 3]) call savetxt(outpath, e) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [2, 3])) if (allocated(error)) return call check(error, all(e == d2)) if (allocated(error)) return end subroutine test_rdp subroutine test_csp(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(sp) :: d(3, 2), e(2, 3) complex(sp), allocatable :: d2(:, :) character(:), allocatable :: outpath outpath = get_outpath() // "/tmp_test_csp.dat" d = cmplx(1, 1,kind=sp)* reshape([1, 2, 3, 4, 5, 6], [3, 2]) call savetxt(outpath, d) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [3, 2])) if (allocated(error)) return call check(error, all(d == d2)) if (allocated(error)) return e = cmplx(1, 1,kind=sp)* reshape([1, 2, 3, 4, 5, 6], [2, 3]) call savetxt(outpath, e) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [2, 3])) if (allocated(error)) return call check(error, all(e == d2)) if (allocated(error)) return end subroutine test_csp subroutine test_cdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(dp) :: d(3, 2), e(2, 3) complex(dp), allocatable :: d2(:, :) character(:), allocatable :: outpath outpath = get_outpath() // "/tmp_test_cdp.dat" d = cmplx(1._dp, 1._dp,kind=dp)* reshape([1, 2, 3, 4, 5, 6], [3, 2]) call savetxt(outpath, d) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [3, 2])) if (allocated(error)) return call check(error, all(d == d2)) if (allocated(error)) return e = cmplx(1, 1,kind=dp)* reshape([1, 2, 3, 4, 5, 6], [2, 3]) call savetxt(outpath, e) call loadtxt(outpath, d2) call check(error, all(shape(d2) == [2, 3])) if (allocated(error)) return call check(error, all(e == d2)) if (allocated(error)) return end subroutine test_cdp end module test_savetxt program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_savetxt, only : collect_savetxt implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("savetxt", collect_savetxt) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/io/CMakeLists.txt0000664000175000017500000000062015135654166022312 0ustar alastairalastairset( fppFiles "test_loadtxt_qp.fypp" "test_savetxt_qp.fypp" ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) ADDTEST(loadtxt) ADDTEST(savetxt) ADDTEST(loadtxt_qp) ADDTEST(savetxt_qp) set_tests_properties(loadtxt_qp PROPERTIES LABELS quadruple_precision) set_tests_properties(savetxt_qp PROPERTIES LABELS quadruple_precision) ADDTEST(get_line) ADDTEST(npy) ADDTEST(open) ADDTEST(parse_mode) fortran-lang-stdlib-0ede301/test/io/test_parse_mode.f900000664000175000017500000001242115135654166023251 0ustar alastairalastairmodule test_parse_mode use stdlib_ascii, only: reverse use stdlib_io, only: parse_mode use testdrive, only: new_unittest, unittest_type, error_type, check implicit none private public :: collect_parse_mode character(3), parameter :: parse_modes_input(*) = [ & " ", & "r ", "w ", "a ", "x ", & "rt ", "wt ", "at ", "xt ", & "rb ", "wb ", "ab ", "xb ", & "r+ ", "w+ ", "a+ ", "x+ ", & "r+t", "w+t", "a+t", "x+t", & "r+b", "w+b", "a+b", "x+b" & ] character(3), parameter :: parse_modes_expected(*) = [ & "r t", & "r t", "w t", "a t", "x t", & "r t", "w t", "a t", "x t", & "r b", "w b", "a b", "x b", & "r+t", "w+t", "a+t", "x+t", & "r+t", "w+t", "a+t", "x+t", & "r+b", "w+b", "a+b", "x+b" & ] contains !> Collect all exported unit tests subroutine collect_parse_mode(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("parse_mode_expected_order", test_parse_mode_expected_order), & new_unittest("parse_mode_reverse_order", test_parse_mode_reverse_order), & new_unittest("parse_mode_random_order", test_parse_mode_random_order) & !FIXME Is it possible to run tests with error stop? !new_unittest("parse_mode_always_fail", test_parse_mode_always_fail) & ] end subroutine collect_parse_mode subroutine test_parse_mode_expected_order(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: n do n = 1, size(parse_modes_input) call check(error, parse_mode(trim(parse_modes_input(n))) == & parse_modes_expected(n)) if (allocated(error)) return end do end subroutine test_parse_mode_expected_order subroutine test_parse_mode_reverse_order(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: n do n = 1, size(parse_modes_input) call check(error, & parse_mode(trim(reverse(parse_modes_input(n)))) == & parse_modes_expected(n)) if (allocated(error)) return end do end subroutine test_parse_mode_reverse_order subroutine test_parse_mode_random_order(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, parse_mode("t r") == "r t") if (allocated(error)) return call check(error, parse_mode(" tw ") == "w t") if (allocated(error)) return call check(error, parse_mode("ta ") == "a t") if (allocated(error)) return call check(error, parse_mode(" t x ") == "x t") if (allocated(error)) return call check(error, parse_mode("+ r ") == "r+t") if (allocated(error)) return call check(error, parse_mode("w +") == "w+t") if (allocated(error)) return call check(error, parse_mode(" a+") == "a+t") if (allocated(error)) return call check(error, parse_mode(" x+ t ") == "x+t") if (allocated(error)) return call check(error, parse_mode("tr+ ") == "r+t") if (allocated(error)) return call check(error, parse_mode("wt + ") == "w+t") if (allocated(error)) return call check(error, parse_mode("a + t") == "a+t") if (allocated(error)) return call check(error, parse_mode(" xt + ") == "x+t") if (allocated(error)) return call check(error, parse_mode(" + t") == "r+t") if (allocated(error)) return call check(error, parse_mode(" +w b") == "w+b") if (allocated(error)) return call check(error, parse_mode("a + b") == "a+b") if (allocated(error)) return call check(error, parse_mode(" b + x ") == "x+b") if (allocated(error)) return end subroutine test_parse_mode_random_order subroutine test_parse_mode_always_fail(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, parse_mode("r+w") /= "r t") if (allocated(error)) return call check(error, parse_mode("tt") /= "r t") if (allocated(error)) return call check(error, parse_mode("bt") /= "r t") if (allocated(error)) return end subroutine test_parse_mode_always_fail end module test_parse_mode program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_parse_mode, only : collect_parse_mode implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("parse_mode", collect_parse_mode) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/io/test_get_line.f900000664000175000017500000001717315135654166022732 0ustar alastairalastairmodule test_get_line use stdlib_io, only : get_line, get_file use stdlib_error, only: state_type use stdlib_string_type, only : string_type, len, len_trim use testdrive, only : new_unittest, unittest_type, error_type, check implicit none private public :: collect_get_line contains !> Collect all exported unit tests subroutine collect_get_line(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("read-char", test_read_char), & new_unittest("read-string", test_read_string), & new_unittest("pad-no", test_pad_no), & new_unittest("iostat-end", test_iostat_end), & new_unittest("closed-unit", test_closed_unit, should_fail=.true.), & new_unittest("no-unit", test_no_unit, should_fail=.true.), & new_unittest("get_file-no", test_get_file_missing), & new_unittest("get_file-empty", test_get_file_empty), & new_unittest("get_file-non-empty", test_get_file_non_empty) & ] end subroutine collect_get_line subroutine test_read_char(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: io, i, stat character(len=:), allocatable :: line open(newunit=io, status="scratch") write(io, "(a)") repeat("abc", 10), repeat("def", 100), repeat("ghi", 1000) rewind(io) do i = 1, 3 call get_line(io, line, stat) call check(error, stat) if (allocated(error)) exit call check(error, len(line), 3*10**i) if (allocated(error)) exit end do close(io) end subroutine test_read_char subroutine test_read_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: io, i, stat type(string_type) :: line open(newunit=io, status="scratch") write(io, "(a)") repeat("abc", 10), repeat("def", 100), repeat("ghi", 1000) rewind(io) do i = 1, 3 call get_line(io, line, stat) call check(error, stat) if (allocated(error)) exit call check(error, len(line), 3*10**i) if (allocated(error)) exit end do close(io) end subroutine test_read_string subroutine test_pad_no(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: io, i, stat character(len=:), allocatable :: line open(newunit=io, status="scratch", pad="no") write(io, "(a)") repeat("abc", 10), repeat("def", 100), repeat("ghi", 1000) rewind(io) do i = 1, 3 call get_line(io, line, stat) call check(error, stat) if (allocated(error)) exit call check(error, len(line), 3*10**i) if (allocated(error)) exit end do close(io) end subroutine test_pad_no subroutine test_iostat_end(error) use, intrinsic :: iso_fortran_env, only : iostat_end !> Error handling type(error_type), allocatable, intent(out) :: error integer :: io, i, stat character(len=:), allocatable :: line open(newunit=io, status="scratch") write(io, "(a)") repeat("abc", 10), repeat("def", 100), repeat("ghi", 1000) rewind(io) do i = 1, 3 call get_line(io, line, stat) call check(error, stat) if (allocated(error)) exit call check(error, len(line), 3*10**i) if (allocated(error)) exit end do if (.not.allocated(error)) then call get_line(io, line, stat) call check(error, stat, iostat_end) end if close(io) end subroutine test_iostat_end subroutine test_closed_unit(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: io, stat character(len=:), allocatable :: line, msg open(newunit=io, status="scratch") close(io) call get_line(io, line, stat, msg) call check(error, stat, msg) end subroutine test_closed_unit subroutine test_no_unit(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: io, stat character(len=:), allocatable :: line, msg io = -1 call get_line(io, line, stat, msg) call check(error, stat, msg) end subroutine test_no_unit subroutine test_get_file_missing(error) !> Test for a missing file. type(error_type), allocatable, intent(out) :: error type(string_type) :: filecontents type(state_type) :: err call get_file("nonexistent_file.txt", fileContents, err) ! Check that an error was returned call check(error, err%error(), "Error not returned on a missing file") if (allocated(error)) return end subroutine test_get_file_missing subroutine test_get_file_empty(error) !> Test for an empty file. type(error_type), allocatable, intent(out) :: error integer :: ios character(len=:), allocatable :: filename type(string_type) :: filecontents type(state_type) :: err ! Get a temporary file name filename = "test_get_file_empty.txt" ! Create an empty file open(newunit=ios, file=filename, action="write", form="formatted", access="sequential") close(ios) ! Read and delete it call get_file(filename, filecontents, err, delete=.true.) call check(error, err%ok(), "Should not return error reading an empty file") if (allocated(error)) return call check(error, len_trim(filecontents) == 0, "String from empty file should be empty") if (allocated(error)) return end subroutine test_get_file_empty subroutine test_get_file_non_empty(error) !> Test for a non-empty file. type(error_type), allocatable, intent(out) :: error integer :: ios character(len=:), allocatable :: filename type(string_type) :: filecontents type(state_type) :: err ! Get a temporary file name filename = "test_get_file_size5.txt" ! Create a fixed-size file open(newunit=ios, file=filename, action="write", form="unformatted", access="stream") write(ios) "12345" close(ios) ! Read and delete it call get_file(filename, filecontents, err, delete=.true.) call check(error, err%ok(), "Should not return error reading a non-empty file") if (allocated(error)) return call check(error, len_trim(filecontents) == 5, "Wrong string size returned") if (allocated(error)) return end subroutine test_get_file_non_empty end module test_get_line program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_get_line, only : collect_get_line implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("get_line", collect_get_line) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/io/test_loadtxt.f900000664000175000017500000003310215135654166022611 0ustar alastairalastairmodule test_loadtxt use stdlib_kinds, only: int32, sp, dp use stdlib_io, only: loadtxt, savetxt use testdrive, only: new_unittest, unittest_type, error_type, check implicit none private public :: collect_loadtxt contains !> Collect all exported unit tests subroutine collect_loadtxt(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("loadtxt_int32", test_loadtxt_int32), & new_unittest("loadtxt_sp", test_loadtxt_sp), & new_unittest("loadtxt_sp_huge", test_loadtxt_sp_huge), & new_unittest("loadtxt_sp_tiny", test_loadtxt_sp_tiny), & new_unittest("loadtxt_dp", test_loadtxt_dp), & new_unittest("loadtxt_dp_max_skip", test_loadtxt_dp_max_skip), & new_unittest("loadtxt_dp_huge", test_loadtxt_dp_huge), & new_unittest("loadtxt_dp_tiny", test_loadtxt_dp_tiny), & new_unittest("loadtxt_complex", test_loadtxt_complex) & ] end subroutine collect_loadtxt subroutine test_loadtxt_int32(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(int32), allocatable :: input(:,:), expected(:,:) real(sp), allocatable :: harvest(:,:) integer :: n allocate(harvest(10,10)) allocate(input(10,10)) allocate(expected(10,10)) do n = 1, 10 call random_number(harvest) input = int(harvest * 100) call savetxt('test_int32.txt', input) call loadtxt('test_int32.txt', expected) call check(error, all(input == expected),'Default list directed read failed') if (allocated(error)) return call loadtxt('test_int32.txt', expected, fmt='*') call check(error, all(input == expected),'User specified list directed read faile') if (allocated(error)) return call savetxt('test_int32.txt', input, delimiter=',') call loadtxt('test_int32.txt', expected, delimiter=',') call check(error, all(input == expected),'User specified delimiter `,` read failed') if (allocated(error)) return call savetxt('test_int32.txt', input, delimiter='-') call loadtxt('test_int32.txt', expected, delimiter='-') call check(error, all(input == expected),'User specified delimiter `-` read failed') if (allocated(error)) return end do end subroutine test_loadtxt_int32 subroutine test_loadtxt_sp(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(sp), allocatable :: input(:,:), expected(:,:) character(len=*), parameter :: FMT_REAL_SP = '(es15.8e2)' integer :: n allocate(input(10,10)) allocate(expected(10,10)) do n = 1, 10 call random_number(input) input = input - 0.5 call savetxt('test_sp.txt', input) call loadtxt('test_sp.txt', expected) call check(error, all(input == expected),'Default format read failed') if (allocated(error)) return call loadtxt('test_sp.txt', expected, fmt='*') call check(error, all(input == expected),'List directed read failed') if (allocated(error)) return call loadtxt('test_sp.txt', expected, fmt="(*"//FMT_REAL_sp(1:len(FMT_REAL_sp)-1)//",1x))") call check(error, all(input == expected),'User specified format failed') if (allocated(error)) return call savetxt('test_sp.txt', input, delimiter=',') call loadtxt('test_sp.txt', expected, delimiter=',') call check(error, all(input == expected),'User specified delimiter `,` read failed') if (allocated(error)) return call savetxt('test_sp.txt', input, delimiter=';') call loadtxt('test_sp.txt', expected, delimiter=';') call check(error, all(input == expected),'User specified delimiter `;` read failed') if (allocated(error)) return end do end subroutine test_loadtxt_sp subroutine test_loadtxt_sp_huge(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(sp), allocatable :: input(:,:), expected(:,:) integer :: n character(len=*), parameter :: FMT_REAL_SP = '(es15.8e2)' allocate(input(10,10)) allocate(expected(10,10)) do n = 1, 10 call random_number(input) input = (input - 0.5) * huge(input) call savetxt('test_sp_huge.txt', input) call loadtxt('test_sp_huge.txt', expected) call check(error, all(input == expected),'Default format read failed') if (allocated(error)) return call loadtxt('test_sp_huge.txt', expected, fmt='*') call check(error, all(input == expected),'List directed read failed') if (allocated(error)) return call loadtxt('test_sp_huge.txt', expected, fmt="(*"//FMT_REAL_sp(1:len(FMT_REAL_sp)-1)//",1x))") call check(error, all(input == expected),'User specified format failed') if (allocated(error)) return end do end subroutine test_loadtxt_sp_huge subroutine test_loadtxt_sp_tiny(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(sp), allocatable :: input(:,:), expected(:,:) integer :: n character(len=*), parameter :: FMT_REAL_SP = '(es15.8e2)' allocate(input(10,10)) allocate(expected(10,10)) do n = 1, 10 call random_number(input) input = (input - 0.5) * tiny(input) call savetxt('test_sp_tiny.txt', input) call loadtxt('test_sp_tiny.txt', expected) call check(error, all(input == expected),'Default format read failed') if (allocated(error)) return call loadtxt('test_sp_tiny.txt', expected, fmt='*') call check(error, all(input == expected),'List directed read failed') if (allocated(error)) return call loadtxt('test_sp_tiny.txt', expected, fmt="(*"//FMT_REAL_sp(1:len(FMT_REAL_sp)-1)//",1x))") call check(error, all(input == expected),'User specified format failed') if (allocated(error)) return end do end subroutine test_loadtxt_sp_tiny subroutine test_loadtxt_dp(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(dp), allocatable :: input(:,:), expected(:,:) integer :: n character(len=*), parameter :: FMT_REAL_DP = '(es24.16e3)' allocate(input(10,10)) allocate(expected(10,10)) do n = 1, 10 call random_number(input) input = input - 0.5 call savetxt('test_dp.txt', input) call loadtxt('test_dp.txt', expected) call check(error, all(input == expected),'Default format read failed') if (allocated(error)) return call loadtxt('test_dp.txt', expected, fmt='*') call check(error, all(input == expected),'List directed read failed') if (allocated(error)) return call loadtxt('test_dp.txt', expected, fmt="(*"//FMT_REAL_dp(1:len(FMT_REAL_dp)-1)//",1x))") call check(error, all(input == expected),'User specified format failed') if (allocated(error)) return call savetxt('test_dp.txt', input, delimiter=',') call loadtxt('test_dp.txt', expected, delimiter=',') call check(error, all(input == expected),'User specified delimiter read failed') if (allocated(error)) return end do end subroutine test_loadtxt_dp subroutine test_loadtxt_dp_max_skip(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(dp), allocatable :: input(:,:), expected(:,:) integer :: n, m character(len=*), parameter :: FMT_REAL_DP = '(es24.16e3)' allocate(input(10,10)) do m = 0, 5 do n = 1, 11 call random_number(input) input = input - 0.5 call savetxt('test_dp_max_skip.txt', input) call loadtxt('test_dp_max_skip.txt', expected, skiprows=m, max_rows=n) call check(error, all(input(m+1:min(n+m,10),:) == expected),'Default format read failed') if (allocated(error)) return call loadtxt('test_dp_max_skip.txt', expected, skiprows=m, max_rows=n, fmt='*') call check(error, all(input(m+1:min(n+m,10),:) == expected),'List directed read failed') if (allocated(error)) return call loadtxt('test_dp_max_skip.txt', expected, fmt="(*"//FMT_REAL_dp(1:len(FMT_REAL_dp)-1)//",1x))") call check(error, all(input == expected),'User specified format failed') deallocate(expected) if (allocated(error)) return end do end do end subroutine test_loadtxt_dp_max_skip subroutine test_loadtxt_dp_huge(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(dp), allocatable :: input(:,:), expected(:,:) integer :: n character(len=*), parameter :: FMT_REAL_DP = '(es24.16e3)' allocate(input(10,10)) allocate(expected(10,10)) do n = 1, 10 call random_number(input) input = (input - 0.5) * huge(input) call savetxt('test_dp_huge.txt', input) call loadtxt('test_dp_huge.txt', expected) call check(error, all(input == expected),'Default format read failed') if (allocated(error)) return call loadtxt('test_dp_huge.txt', expected, fmt='*') call check(error, all(input == expected),'List directed read failed') if (allocated(error)) return call loadtxt('test_dp_huge.txt', expected, fmt="(*"//FMT_REAL_dp(1:len(FMT_REAL_dp)-1)//",1x))") call check(error, all(input == expected),'User specified format failed') if (allocated(error)) return end do end subroutine test_loadtxt_dp_huge subroutine test_loadtxt_dp_tiny(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(dp), allocatable :: input(:,:), expected(:,:) integer :: n character(len=*), parameter :: FMT_REAL_DP = '(es24.16e3)' allocate(input(10,10)) allocate(expected(10,10)) do n = 1, 10 call random_number(input) input = (input - 0.5) * tiny(input) call savetxt('test_dp_tiny.txt', input) call loadtxt('test_dp_tiny.txt', expected) call check(error, all(input == expected),'Default format read failed') if (allocated(error)) return call loadtxt('test_dp_tiny.txt', expected, fmt='*') call check(error, all(input == expected),'List directed read failed') if (allocated(error)) return call loadtxt('test_dp_tiny.txt', expected, fmt="(*"//FMT_REAL_dp(1:len(FMT_REAL_dp)-1)//",1x))") call check(error, all(input == expected),'User specified format failed') if (allocated(error)) return end do end subroutine test_loadtxt_dp_tiny subroutine test_loadtxt_complex(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(dp), allocatable :: input(:,:), expected(:,:) real(dp), allocatable :: re(:,:), im(:,:) integer :: n character(len=*), parameter :: FMT_COMPLEX_DP = '(es24.16e3,1x,es24.16e3)' allocate(re(10,10)) allocate(im(10,10)) allocate(input(10,10)) allocate(expected(10,10)) do n = 1, 10 call random_number(re) call random_number(im) input = cmplx(re, im) call savetxt('test_complex.txt', input) call loadtxt('test_complex.txt', expected) call check(error, all(input == expected)) call loadtxt('test_complex.txt', expected, fmt="(*"//FMT_COMPLEX_dp(1:len(FMT_COMPLEX_dp)-1)//",1x))") call check(error, all(input == expected)) if (allocated(error)) return call savetxt('test_complex.txt', input, delimiter=',') call loadtxt('test_complex.txt', expected, delimiter=',') call check(error, all(input == expected)) if (allocated(error)) return call savetxt('test_complex.txt', input, delimiter=';') call loadtxt('test_complex.txt', expected, delimiter=';') call check(error, all(input == expected)) if (allocated(error)) return end do end subroutine test_loadtxt_complex end module test_loadtxt program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_loadtxt, only : collect_loadtxt implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("loadtxt", collect_loadtxt) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/selection/0000775000175000017500000000000015135654166021132 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/selection/test_selection.fypp0000664000175000017500000005115215135654166025062 0ustar alastairalastair#:include "common.fypp" ! Specify kinds/types for the input array in select and arg_select #:set ARRAY_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES ! The index arrays are of all INT_KINDS_TYPES module test_selection use stdlib_kinds use stdlib_selection, only: select, arg_select use testdrive, only: new_unittest, unittest_type, error_type, check implicit none private public :: collect_selection contains !> Collect all exported unit tests subroutine collect_selection(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("test_select_1_iint8_int8", test_select_1_iint8_int8) & #:for arraykind, arraytype in ARRAY_KINDS_TYPES #:for intkind, inttype in INT_KINDS_TYPES #:set name = rname("test_select", 1, arraytype, arraykind, intkind) , new_unittest("${name}$", ${name}$) & #:endfor #:endfor #:for arraykind, arraytype in ARRAY_KINDS_TYPES #:for intkind, inttype in INT_KINDS_TYPES #:set name = rname("test_arg_select", 1, arraytype, arraykind, intkind) , new_unittest("${name}$", ${name}$) & #:endfor #:endfor ] end subroutine collect_selection #:for arraykind, arraytype in ARRAY_KINDS_TYPES #:for intkind, inttype in INT_KINDS_TYPES #:set name = rname("test_select", 1, arraytype, arraykind, intkind) subroutine ${name}$(error) type(error_type), allocatable, intent(out) :: error integer, parameter :: ip = ${intkind}$ ${inttype}$, parameter :: N = 10, Nm = 8 ${inttype}$, parameter :: near_huge = HUGE(N) - 1_ip ! Segfaults without the -1_ip ${inttype}$, parameter :: Nreps = 2 ! Number of repetitions of random sampling ${inttype}$, parameter :: Nr = 25_ip ! Size of random array, must be < HUGE(N) ${arraytype}$ :: x(N), x_copy(N), mat(Nm), mat_copy(Nm), len1(1), len2(2), & kth_smallest, random_vals(Nr), one = 1 ${inttype}$ :: i, p, up_rank, down_rank, mid_rank real(dp) :: random_doubles(Nr) ! Deliberately double precision for all cases logical :: test1, test2, test3 ${arraytype}$, allocatable :: long_array(:) ! x contains the numbers 1**2, 2**2, .... 10**2, with mixed-up order x = (/( i**2, i=1, size(x, kind=ip) )/) x(5:2:-1) = x(2:5) x(10:8:-1) = x(8:10) ! Check that the ith-ranked entry of x really is i**2 do i = 1, size(x, kind=ip) x_copy = x call select(x_copy, i, kth_smallest) call check( error, (kth_smallest == i**2), " ${name}$: kth smallest entry should be i**2") if(allocated(error)) return end do ! Check that it works when we specify "left" and know that the array ! is partially sorted due to previous calls to quickselect x_copy = x do i = 1, size(x, kind=ip), 1 call select(x_copy, i, kth_smallest, left=i) call check( error, (kth_smallest == i**2), " ${name}$: kth smallest entry with left specified") if(allocated(error)) return end do ! Check that it works when we specify "right" and know that the array ! is partially sorted due to previous calls to quickselect x_copy = x do i = size(x, kind=ip), 1, -1 call select(x_copy, i, kth_smallest, right=i) call check( error, (kth_smallest == i**2), " ${name}$: kth smallest entry with right specified") if(allocated(error)) return end do ! The test below can catch overflow in naive calculation of the middle index, like discussed here: ! https://ai.googleblog.com/2006/06/extra-extra-read-all-about-it-nearly.html ! But don't do it if near_huge is large, to avoid allocating a big array and slowing the tests if(near_huge < 200) then allocate(long_array(near_huge)) long_array = 0 * one long_array(1:3) = one call select(long_array, near_huge - 2_ip, kth_smallest) call check( error, (kth_smallest == one), " ${name}$: designed to catch overflow in middle index") if(allocated(error)) return deallocate(long_array) end if ! Simple tests mat = one * [3, 2, 7, 4, 5, 1, 4, -1] mat_copy = mat call select(mat_copy, 1_ip, kth_smallest) call check(error, kth_smallest == -1, " ${name}$: mat test 1") if(allocated(error)) return mat_copy = mat call select(mat_copy, 2_ip, kth_smallest) call check(error, kth_smallest == 1, " ${name}$: mat test 2") if(allocated(error)) return mat_copy = mat call select(mat_copy, size(mat, kind=ip)+1_ip-4_ip, kth_smallest) call check(error, kth_smallest == 4, " ${name}$: mat test 3") if(allocated(error)) return mat_copy = mat call select(mat_copy, 5_ip, kth_smallest) call check(error, kth_smallest == 4, " ${name}$: mat test 4") if(allocated(error)) return mat_copy = mat call select(mat_copy, 6_ip, kth_smallest) call check(error, kth_smallest == 4, " ${name}$: mat test 5") if(allocated(error)) return mat_copy = mat call select(mat_copy, 7_ip, kth_smallest) call check(error, kth_smallest == 5, " ${name}$: mat test 6") if(allocated(error)) return ! Check it works for size(a) == 1 len1(1) = -1 * one call select(len1, 1_ip, kth_smallest) call check(error, kth_smallest == -1, " ${name}$: array with size 1") if(allocated(error)) return ! Check it works for size(a) == 2 len2 = [-3, -5]*one call select(len2, 2_ip, kth_smallest) call check(error, kth_smallest == -3, " ${name}$: array with size 2, test 1") if(allocated(error)) return len2 = [-3, -5]*one call select(len2, 1_ip, kth_smallest) call check(error, kth_smallest == -5, " ${name}$: array with size 2, test 2") if(allocated(error)) return len2 = [-1, -1]*one call select(len2, 1_ip, kth_smallest) call check(error, kth_smallest == -1, " ${name}$: array with size 2, test 3") if(allocated(error)) return len2 = [-1, -1]*one call select(len2, 2_ip, kth_smallest) call check(error, kth_smallest == -1, " ${name}$: array with size 2, test 4") if(allocated(error)) return ! ! Test using random data ! ! Search for the p-th smallest rank, for all these p ! (avoid end-points to enable constrained search tests) do p = 3, Nr-2 ! Repeat for different random samples to try to expose any errors do i = 1, Nreps ! Make random numbers of the correct type call random_number(random_doubles) random_vals = random_doubles * Nr call select(random_vals, p, kth_smallest) test1 = kth_smallest == random_vals(p) test2 = all(random_vals(1:(p-1)) <= random_vals(p)) test3 = all(random_vals(p) <= & random_vals((p+1):size(random_vals, kind=ip))) call check(error, (test1 .and. test2 .and. test3), "${name}$: random data regular select") if(allocated(error)) return ! Constrained search above 'p', providing 'left' up_rank = p + (Nr-p)/2_ip ! Deliberate integer division call select(random_vals, up_rank, kth_smallest, left=p) test1 = kth_smallest == random_vals(up_rank) test2 = all(random_vals(1:(up_rank-1)) <= random_vals(up_rank)) test3 = all(random_vals(up_rank) <= & random_vals((up_rank+1):size(random_vals, kind=ip))) call check(error, (test1 .and. test2 .and. test3), "${name}$: random data left-constrained select") if(allocated(error)) return ! Constrained search below p, providing 'right' down_rank = p - (p/2_ip) call select(random_vals, down_rank, kth_smallest, right=p) test1 = kth_smallest == random_vals(down_rank) test2 = all(random_vals(1:(down_rank-1)) <= & random_vals(down_rank)) test3 = all(random_vals(down_rank) <= & random_vals((down_rank+1):size(random_vals, kind=ip))) call check(error, (test1 .and. test2 .and. test3), "${name}$: random data right-constrained select") if(allocated(error)) return ! Constrained search between up-ind and down-ind, proving left ! and right. Make 'mid_rank' either above or below p mid_rank = p - p/3_ip*mod(i,2_ip) + (Nr-p)/3_ip*(1_ip-mod(i,2_ip)) call select(random_vals, mid_rank, kth_smallest, & left=down_rank, right=up_rank) test1 = kth_smallest == random_vals(mid_rank) test2 = all(random_vals(1:(mid_rank-1)) <= & random_vals(mid_rank)) test3 = all(random_vals(mid_rank) <= & random_vals((mid_rank+1):size(random_vals, kind=ip))) call check(error, (test1 .and. test2 .and. test3), "${name}$: random data left-right-constrained select") if(allocated(error)) return end do end do end subroutine #:endfor #:endfor #:for arraykind, arraytype in ARRAY_KINDS_TYPES #:for intkind, inttype in INT_KINDS_TYPES #:set name = rname("test_arg_select", 1, arraytype, arraykind, intkind) subroutine ${name}$(error) type(error_type), allocatable, intent(out) :: error integer, parameter :: ip = ${intkind}$ ${inttype}$, parameter :: N = 10, Nm = 8 ${inttype}$, parameter :: near_huge = HUGE(N) - 1_ip ! Segfaults without the -1_ip ${inttype}$, parameter :: Nreps = 2 ! Number of repetitions of random sampling ${inttype}$, parameter :: Nr = 25_ip ! Size of random array, must be < HUGE(N) ${arraytype}$ :: x(N), mat(Nm), len1(1), len2(2), random_vals(Nr), one=1 integer(ip) :: indx(N), indx_copy(N), indx_mat(Nm), indx_mat_copy(Nm), & indx_len1(1), indx_len2(2), indx_r(Nr) real(dp) :: random_doubles(Nr) ! Deliberately double precision for all cases integer(ip) :: i, j, p, up_rank, down_rank, mid_rank, kth_smallest logical :: test1, test2, test3 ${arraytype}$, allocatable :: long_array(:) ${inttype}$, allocatable :: long_array_index(:) ! Make x contain 1**2, 2**2, .... 10**2, but mix up the order x = (/( i**2, i=1, size(x, kind=ip) )/) x(5:2:-1) = x(2:5) x(10:8:-1) = x(8:10) indx = (/(i, i = 1, size(x, kind=ip))/) ! Check that the ith ranked entry of x equals i**2 do i = 1, size(x, kind=ip) indx_copy = indx call arg_select(x, indx, i, kth_smallest) call check(error, x(kth_smallest) == i**2, " ${name}$: kth smallest entry should be i**2") if(allocated(error)) return end do ! Check that it works when we specify "left" and know that the index ! array is partially sorted due to previous calls to arg_select indx_copy = indx do i = 1, size(x, kind=ip), 1 call arg_select(x, indx_copy, i, kth_smallest, left=i) call check(error, (x(kth_smallest) == i**2), " ${name}$: kth smallest entry with left specified") if(allocated(error)) return end do ! Check that it works when we specify "right" and know that the index ! array is partially sorted due to previous calls to arg_select indx_copy = indx do i = size(x, kind=ip), 1, -1 call arg_select(x, indx_copy, i, kth_smallest, right=i) call check(error, (x(kth_smallest) == i**2), " ${name}$: kth smallest entry with right specified") if(allocated(error)) return end do ! The test below would catch overflow in naive calculation of the middle index, like discussed here: ! https://ai.googleblog.com/2006/06/extra-extra-read-all-about-it-nearly.html ! But don't do it if near_huge is large, to avoid allocating a big array and slowing the tests if(near_huge < 200) then allocate(long_array(near_huge)) allocate(long_array_index(near_huge)) long_array = 0 * one long_array(1:3) = one long_array_index = (/( i, i = 1_ip, size(long_array, kind=ip) )/) call arg_select(long_array, long_array_index, near_huge - 2_ip, kth_smallest) call check( error, (kth_smallest < 4), " ${name}$: designed to catch overflow in middle index") if(allocated(error)) return deallocate(long_array, long_array_index) end if ! Simple tests mat = one * [3, 2, 7, 4, 5, 1, 4, -1] indx_mat = (/( i, i = 1, size(mat, kind=ip) )/) indx_mat_copy = indx_mat call arg_select(mat, indx_mat_copy, 1_ip, kth_smallest) call check(error, mat(kth_smallest) == -1, " ${name}$: mat test 1") if(allocated(error)) return indx_mat_copy = indx_mat call arg_select(mat, indx_mat_copy, 2_ip, kth_smallest) call check(error, mat(kth_smallest) == 1, " ${name}$: mat test 2") if(allocated(error)) return indx_mat_copy = indx_mat call arg_select(mat, indx_mat_copy, size(mat, kind=ip)+1_ip-4_ip, & kth_smallest) call check(error, mat(kth_smallest) == 4, " ${name}$: mat test 3") if(allocated(error)) return indx_mat_copy = indx_mat call arg_select(mat, indx_mat_copy, 5_ip, kth_smallest) call check(error, mat(kth_smallest) == 4, " ${name}$: mat test 4") if(allocated(error)) return indx_mat_copy = indx_mat call arg_select(mat, indx_mat_copy, 6_ip, kth_smallest) call check(error, mat(kth_smallest) == 4, " ${name}$: mat test 5") if(allocated(error)) return indx_mat_copy = indx_mat call arg_select(mat, indx_mat_copy, 7_ip, kth_smallest) call check(error, mat(kth_smallest) == 5, " ${name}$: mat test 6") if(allocated(error)) return ! Check it works for size(a) == 1 len1(1) = -1 * one indx_len1(1) = 1 call arg_select(len1, indx_len1, 1_ip, kth_smallest) call check(error, len1(kth_smallest) == -1, " ${name}$: array with size 1") if(allocated(error)) return ! Check it works for size(a) == 2 len2 = [-3, -5] * one indx_len2 = [1_ip, 2_ip] call arg_select(len2, indx_len2, 2_ip, kth_smallest) call check(error, len2(kth_smallest) == -3, " ${name}$: array with size 2, test 1") if(allocated(error)) return len2 = [-3, -5] * one indx_len2 = [1_ip, 2_ip] call arg_select(len2, indx_len2, 1_ip, kth_smallest) call check(error, len2(kth_smallest) == -5, " ${name}$: array with size 2, test 2") if(allocated(error)) return len2 = [-1, -1] * one indx_len2 = [1_ip, 2_ip] call arg_select(len2, indx_len2, 1_ip, kth_smallest) call check(error, len2(kth_smallest) == -1, " ${name}$: array with size 2, test 3") if(allocated(error)) return len2 = [-1, -1] * one indx_len2 = [1_ip, 2_ip] call arg_select(len2, indx_len2, 2_ip, kth_smallest) call check(error, len2(kth_smallest) == -1, " ${name}$: array with size 2, test 4") if(allocated(error)) return ! ! Test using random data ! ! Search for the p-th smallest, for all these p (avoid end-points to ! enable additional tests using "left", "right" arguments) do p = 3, Nr-2 ! Repeat for many random samples to try to expose any errors do i = 1, Nreps ! Make random numbers of the correct type call random_number(random_doubles) random_vals = random_doubles * Nr indx_r = (/( j, j = 1, size(random_vals, kind=ip) )/) ! Standard arg_select call arg_select(random_vals, indx_r, p, kth_smallest) test1 = random_vals(kth_smallest) == random_vals(indx_r(p)) test2 = all(random_vals(indx_r(1:(p-1))) <= & random_vals(indx_r(p))) test3 = all(random_vals(indx_r(p)) <= & random_vals(indx_r((p+1):size(random_vals, kind=ip)))) call check(error, (test1 .and. test2 .and. test3), "${name}$: random data regular arg_select") if(allocated(error)) return ! Constrained search for a rank above 'p', providing 'left' up_rank = p + (Nr-p)/2_ip ! Deliberate integer division call arg_select(random_vals, indx_r, up_rank, & kth_smallest, left=p) test1 = random_vals(kth_smallest) == & random_vals(indx_r(up_rank)) test2 = all(random_vals(indx_r(1:(up_rank-1))) <= & random_vals(indx_r(up_rank))) test3 = all(random_vals(indx_r(up_rank)) <= & random_vals(indx_r((up_rank+1):size(random_vals, kind=ip)))) call check(error, (test1 .and. test2 .and. test3), "${name}$: random data left-constrained arg_select") if(allocated(error)) return ! Constrained search for a rank below p, providing 'right' down_rank = p - (p/2_ip) call arg_select(random_vals, indx_r, down_rank, & kth_smallest, right=p) test1 = random_vals(kth_smallest) == & random_vals(indx_r(down_rank)) test2 = all(random_vals(indx_r(1:(down_rank-1))) <= & random_vals(indx_r(down_rank))) test3 = all(random_vals(indx_r(down_rank)) <= & random_vals(indx_r((down_rank+1):size(random_vals, kind=ip)))) call check(error, (test1 .and. test2 .and. test3), "${name}$: random data right-constrained arg_select") if(allocated(error)) return ! Constrained search for a rank between up-ind and down-ind, ! proving left and right. 'mid_rank' is either above or below p mid_rank = p - p/3_ip*mod(i,2_ip) + (Nr-p)/3_ip*(1_ip-mod(i,2_ip)) call arg_select(random_vals, indx_r, mid_rank, & kth_smallest, left=down_rank, right=up_rank) test1 = random_vals(kth_smallest) == & random_vals(indx_r(mid_rank)) test2 = all(random_vals(indx_r(1:(mid_rank-1))) <= & random_vals(indx_r(mid_rank))) test3 = all(random_vals(indx_r(mid_rank)) <= & random_vals(indx_r((mid_rank+1):size(random_vals, kind=ip)))) call check(error, (test1 .and. test2 .and. test3), "${name}$: random data left-right-constrained arg_select") if(allocated(error)) return end do end do end subroutine #:endfor #:endfor end module program tester use, intrinsic :: iso_fortran_env, only: compiler_version, error_unit use testdrive, only: new_testsuite, run_testsuite, testsuite_type use test_selection, only: collect_selection implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("selection", collect_selection) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/selection/CMakeLists.txt0000664000175000017500000000030715135654166023672 0ustar alastairalastair### Pre-process: .fpp -> .f90 via Fypp # Create a list of the files to be preprocessed set( fppFiles test_selection.fypp ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) ADDTEST(selection) fortran-lang-stdlib-0ede301/test/hash_functions/0000775000175000017500000000000015135654166022160 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/hash_functions/test_hash_functions.f900000664000175000017500000002166415135654166026563 0ustar alastairalastairmodule test_hash_functions use testdrive, only : new_unittest, unittest_type, error_type, check, & skip_test use stdlib_kinds, only: int8, int32, int64, dp use stdlib_hash_32bit, only: little_endian & , nmhash32 & , nmhash32x & , water_hash use stdlib_hash_64bit, only: pengy_hash, spooky_hash implicit none private public :: collect_hash_functions public :: generate_key_array integer, parameter :: size_key_array = 2048 integer(int32), parameter :: nm_seed = int( z'deadbeef', int32 ) integer(int64), parameter :: water_seed = int( z'deadbeef1eadbeef', int64 ) integer(int32), parameter :: pengy_seed = int( z'deadbeef', int32 ) integer(int64), parameter :: spooky_seed(2) = [ water_seed, water_seed ] interface read_array module procedure read_array_int8 module procedure read_array_int32 module procedure read_array_int64 module procedure read_2darray_int64 end interface contains !> Collect all exported unit tests subroutine collect_hash_functions(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("little_endian", test_little_endian) & , new_unittest("nmhash32", test_nmhash32) & , new_unittest("nmhash32x", test_nmhash32x) & , new_unittest("water_hash", test_water_hash) & , new_unittest("pengy_hash", test_pengy_hash) & , new_unittest("spooky_hash", test_spooky_hash) & ] end subroutine collect_hash_functions subroutine test_little_endian(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! Test for endianness call check(error, little_endian, "The processor is not Little-Endian") if (allocated(error)) return end subroutine test_little_endian subroutine test_nmhash32(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: index integer(int8) :: key_array(size_key_array) integer(int32) :: c_hash(0:size_key_array) call read_array("key_array.bin", key_array ) ! Read hash array generated from key array by the C version of nmhash32 call read_array("c_nmhash32_array.bin", c_hash) do index=0, size_key_array call check(error, c_hash(index) == nmhash32(key_array(1:index), nm_seed) & , "NMHASH32 failed") if (allocated(error)) return end do end subroutine test_nmhash32 subroutine test_nmhash32x(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: index integer(int8) :: key_array(size_key_array) integer(int32) :: c_hash(0:size_key_array) call read_array("key_array.bin", key_array ) ! Read hash array generated from key array by the C version of nmhash32x call read_array("c_nmhash32x_array.bin", c_hash) do index=0, size_key_array call check(error, c_hash(index) == nmhash32x(key_array(1:index), nm_seed) & , "NMHASH32X failed") if (allocated(error)) return end do end subroutine test_nmhash32x subroutine test_water_hash(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: index integer(int8) :: key_array(size_key_array) integer(int32) :: c_hash(0:size_key_array) call read_array("key_array.bin", key_array ) ! Read hash array generated from key array by the C version of water_hash call read_array("c_water_hash_array.bin", c_hash) do index=0, size_key_array call check(error, c_hash(index) == water_hash(key_array(1:index), water_seed) & , "WATER_HASH failed") if (allocated(error)) return end do end subroutine test_water_hash subroutine test_pengy_hash(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: index integer(int8) :: key_array(size_key_array) integer(int64) :: c_hash(0:size_key_array) call read_array("key_array.bin", key_array ) ! Read hash array generated from key array by the C version of pengy_hash call read_array("c_pengy_hash_array.bin", c_hash) do index=0, size_key_array call check(error, c_hash(index) == pengy_hash(key_array(1:index), pengy_seed) & , "PENGY_HASH failed") if (allocated(error)) return end do end subroutine test_pengy_hash subroutine test_spooky_hash(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: index integer(int8) :: key_array(size_key_array) integer(int64) :: c_hash(0:1, 0:size_key_array) call read_array("key_array.bin", key_array ) ! Read hash array generated from key array by the C version of spooky_hash call read_array("c_spooky_hash_array.bin", c_hash) do index=0, size_key_array call check(error, all(c_hash(:, index) == spooky_hash(key_array(1:index), spooky_seed)) & , "SPOOKY_HASH failed") if (allocated(error)) return end do end subroutine test_spooky_hash subroutine generate_key_array() integer :: i, lun integer(int8) :: key_array(size_key_array) integer(int32) :: dummy(size_key_array/4) real(dp) :: rand(size_key_array/4) ! Create key array call random_number( rand ) do i=1, size_key_array/4 dummy(i) = floor( rand(i) * 2_int64**32 - 2_int64**31, kind=int32 ) end do key_array = transfer( dummy, 0_int8, size_key_array ) open(newunit=lun, file="key_array.bin", form="unformatted", & access="stream", status="replace", action="write") write(lun) key_array close(lun) end subroutine generate_key_array subroutine read_array_int8(filename, res) character(*), intent(in) :: filename integer(int8), intent(out) :: res(:) integer :: lun open(newunit=lun, file=filename, form="unformatted", & access="stream", status="old", action="read", err = 9908) read(lun) res close(lun) return 9908 res = 0 end subroutine read_array_int8 subroutine read_array_int32(filename, res) character(*), intent(in) :: filename integer(int32), intent(out) :: res(:) integer :: lun open(newunit=lun, file=filename, form="unformatted", & access="stream", status="old", action="read", err = 9908) read(lun) res close(lun) return 9908 res = 0 end subroutine read_array_int32 subroutine read_array_int64(filename, res) character(*), intent(in) :: filename integer(int64), intent(out) :: res(:) integer :: lun open(newunit=lun, file=filename, form="unformatted", & access="stream", status="old", action="read", err = 9908) read(lun) res close(lun) return 9908 res = 0 end subroutine read_array_int64 subroutine read_2darray_int64(filename, res) character(*), intent(in) :: filename integer(int64), intent(out) :: res(:,:) integer :: lun open(newunit=lun, file=filename, form="unformatted", & access="stream", status="old", action="read", err = 9908) read(lun) res close(lun) return 9908 res = 0 end subroutine read_2darray_int64 end module module modchash use, intrinsic :: ISO_C_Binding implicit none private public :: generate_all_c_hash interface function generate_all_c_hash() result(error) bind(C,name = "generate_all_c_hash") import C_int integer(C_int) :: error end function end interface end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use, intrinsic :: ISO_C_Binding, only : C_int use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_hash_functions, only : collect_hash_functions, generate_key_array use modchash, only: generate_all_c_hash implicit none integer(C_int) :: error integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' call generate_key_array() error = generate_all_c_hash() stat = 0 testsuites = [ & new_testsuite("hash_functions", collect_hash_functions) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/hash_functions/pengyhash.c0000664000175000017500000000151015135654166024307 0ustar alastairalastair/* pengyhash v0.2 */ #include "pengyhash.h" uint64_t pengyhash(const void *p, size_t size, uint32_t seed) { uint64_t b[4] = { 0 }; uint64_t s[4] = { 0, 0, 0, size }; int i; for(; size >= 32; size -= 32, p = (const char*)p + 32) { memcpy(b, p, 32); s[1] = (s[0] += s[1] + b[3]) + (s[1] << 14 | s[1] >> 50); s[3] = (s[2] += s[3] + b[2]) + (s[3] << 23 | s[3] >> 41); s[3] = (s[0] += s[3] + b[1]) ^ (s[3] << 16 | s[3] >> 48); s[1] = (s[2] += s[1] + b[0]) ^ (s[1] << 40 | s[1] >> 24); } memcpy(b, p, size); for(i = 0; i < 6; i++) { s[1] = (s[0] += s[1] + b[3]) + (s[1] << 14 | s[1] >> 50) + seed; s[3] = (s[2] += s[3] + b[2]) + (s[3] << 23 | s[3] >> 41); s[3] = (s[0] += s[3] + b[1]) ^ (s[3] << 16 | s[3] >> 48); s[1] = (s[2] += s[1] + b[0]) ^ (s[1] << 40 | s[1] >> 24); } return s[0] + s[1] + s[2] + s[3]; } fortran-lang-stdlib-0ede301/test/hash_functions/nmhash.c0000664000175000017500000000042115135654166023577 0ustar alastairalastair#include "nmhash.h" int32_t nmhash32_test ( const void * key, size_t len, uint32_t seed ) { return NMHASH32 (key, (const size_t) len, seed); } int32_t nmhash32x_test ( const void * key, size_t len, uint32_t seed ) { return NMHASH32X (key, (const size_t) len, seed); } fortran-lang-stdlib-0ede301/test/hash_functions/README.md0000664000175000017500000000125515135654166023442 0ustar alastairalastairThe hash_functions directory contains code to validate the Fortran hash functions against the original C/C++ codes. It consists of one executable `test_hash_functions` that: * creates a file containing 2048 random 8 bit integers using the subroutine `generate_key_array`. * reads the file generated by the subroutine `generate_key_array` and uses its contents to generate 2049 hashes for each C/C++ hash algorithm and outputs files containing the hashes. * reads the file generated by the subroutine `generate_key_array` and uses its contents to generate 2049 hashes for each Fortran hash algorithm and compares the result with the corresponding outputs of C/C++ hash algorithms. fortran-lang-stdlib-0ede301/test/hash_functions/CMakeLists.txt0000775000175000017500000000234615135654166024730 0ustar alastairalastair#ADDTEST(hash_functions) enable_language(CXX) enable_language(C) ADDTEST(hash_functions) target_sources( test_hash_functions PRIVATE nmhash.c pengyhash.c SpookyV2.cpp SpookyV2Test.cpp waterhash.c generate_hash_arrays.cpp ) if(CMAKE_Fortran_COMPILER_ID MATCHES "^Intel") # Set the C++ standard to prevent icpc breakage set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set_target_properties(test_hash_functions PROPERTIES LINKER_LANGUAGE Fortran) if(WIN32) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL$<$:Debug>") target_compile_options( test_hash_functions PRIVATE $<$:/libs:dll> ) if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR "RelWithDebInfo") target_link_options(test_hash_functions PRIVATE /Qoption,link,/NODEFAULTLIB:libcmt /Qoption,link,/NODEFAULTLIB:msvcrt.lib /Qoption,link,/NODEFAULTLIB:libifcoremt.lib ) endif() endif() endif() if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 10.0) target_compile_options( test_hash_functions PRIVATE $<$:-fno-range-check> ) endif() fortran-lang-stdlib-0ede301/test/hash_functions/SpookyV2.h0000664000175000017500000002716515135654166024040 0ustar alastairalastair// // SpookyHash: a 128-bit noncryptographic hash function // By Bob Jenkins, public domain // Oct 31 2010: alpha, framework + SpookyHash::Mix appears right // Oct 31 2011: alpha again, Mix only good to 2^^69 but rest appears right // Dec 31 2011: beta, improved Mix, tested it for 2-bit deltas // Feb 2 2012: production, same bits as beta // Feb 5 2012: adjusted definitions of uint* to be more portable // Mar 30 2012: 3 bytes/cycle, not 4. Alpha was 4 but wasn't thorough enough. // August 5 2012: SpookyV2 (different results) // // Up to 3 bytes/cycle for long messages. Reasonably fast for short messages. // All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit. // // This was developed for and tested on 64-bit x86-compatible processors. // It assumes the processor is little-endian. There is a macro // controlling whether unaligned reads are allowed (by default they are). // This should be an equally good hash on big-endian machines, but it will // compute different results on them than on little-endian machines. // // Google's CityHash has similar specs to SpookyHash, and CityHash is faster // on new Intel boxes. MD4 and MD5 also have similar specs, but they are orders // of magnitude slower. CRCs are two or more times slower, but unlike // SpookyHash, they have nice math for combining the CRCs of pieces to form // the CRCs of wholes. There are also cryptographic hashes, but those are even // slower than MD5. // #include #ifdef _MSC_VER # define INLINE __forceinline typedef unsigned __int64 uint64; typedef unsigned __int32 uint32; typedef unsigned __int16 uint16; typedef unsigned __int8 uint8; #else # include # define INLINE inline typedef uint64_t uint64; typedef uint32_t uint32; typedef uint16_t uint16; typedef uint8_t uint8; #endif class SpookyHash { public: // // SpookyHash: hash a single message in one call, produce 128-bit output // static void Hash128( const void *message, // message to hash size_t length, // length of message in bytes uint64 *hash1, // in/out: in seed 1, out hash value 1 uint64 *hash2); // in/out: in seed 2, out hash value 2 // // Hash64: hash a single message in one call, return 64-bit output // static uint64 Hash64( const void *message, // message to hash size_t length, // length of message in bytes uint64 seed) // seed { uint64 hash1 = seed; Hash128(message, length, &hash1, &seed); return hash1; } // // Hash32: hash a single message in one call, produce 32-bit output // static uint32 Hash32( const void *message, // message to hash size_t length, // length of message in bytes uint32 seed) // seed { uint64 hash1 = seed, hash2 = seed; Hash128(message, length, &hash1, &hash2); return (uint32)hash1; } // // Init: initialize the context of a SpookyHash // void Init( uint64 seed1, // any 64-bit value will do, including 0 uint64 seed2); // different seeds produce independent hashes // // Update: add a piece of a message to a SpookyHash state // void Update( const void *message, // message fragment size_t length); // length of message fragment in bytes // // Final: compute the hash for the current SpookyHash state // // This does not modify the state; you can keep updating it afterward // // The result is the same as if SpookyHash() had been called with // all the pieces concatenated into one message. // void Final( uint64 *hash1, // out only: first 64 bits of hash value. uint64 *hash2); // out only: second 64 bits of hash value. // // left rotate a 64-bit value by k bytes // static INLINE uint64 Rot64(uint64 x, int k) { return (x << k) | (x >> (64 - k)); } // // This is used if the input is 96 bytes long or longer. // // The internal state is fully overwritten every 96 bytes. // Every input bit appears to cause at least 128 bits of entropy // before 96 other bytes are combined, when run forward or backward // For every input bit, // Two inputs differing in just that input bit // Where "differ" means xor or subtraction // And the base value is random // When run forward or backwards one Mix // I tried 3 pairs of each; they all differed by at least 212 bits. // static INLINE void Mix( const uint64 *data, uint64 &s0, uint64 &s1, uint64 &s2, uint64 &s3, uint64 &s4, uint64 &s5, uint64 &s6, uint64 &s7, uint64 &s8, uint64 &s9, uint64 &s10,uint64 &s11) { s0 += data[0]; s2 ^= s10; s11 ^= s0; s0 = Rot64(s0,11); s11 += s1; s1 += data[1]; s3 ^= s11; s0 ^= s1; s1 = Rot64(s1,32); s0 += s2; s2 += data[2]; s4 ^= s0; s1 ^= s2; s2 = Rot64(s2,43); s1 += s3; s3 += data[3]; s5 ^= s1; s2 ^= s3; s3 = Rot64(s3,31); s2 += s4; s4 += data[4]; s6 ^= s2; s3 ^= s4; s4 = Rot64(s4,17); s3 += s5; s5 += data[5]; s7 ^= s3; s4 ^= s5; s5 = Rot64(s5,28); s4 += s6; s6 += data[6]; s8 ^= s4; s5 ^= s6; s6 = Rot64(s6,39); s5 += s7; s7 += data[7]; s9 ^= s5; s6 ^= s7; s7 = Rot64(s7,57); s6 += s8; s8 += data[8]; s10 ^= s6; s7 ^= s8; s8 = Rot64(s8,55); s7 += s9; s9 += data[9]; s11 ^= s7; s8 ^= s9; s9 = Rot64(s9,54); s8 += s10; s10 += data[10]; s0 ^= s8; s9 ^= s10; s10 = Rot64(s10,22); s9 += s11; s11 += data[11]; s1 ^= s9; s10 ^= s11; s11 = Rot64(s11,46); s10 += s0; } // // Mix all 12 inputs together so that h0, h1 are a hash of them all. // // For two inputs differing in just the input bits // Where "differ" means xor or subtraction // And the base value is random, or a counting value starting at that bit // The final result will have each bit of h0, h1 flip // For every input bit, // with probability 50 +- .3% // For every pair of input bits, // with probability 50 +- 3% // // This does not rely on the last Mix() call having already mixed some. // Two iterations was almost good enough for a 64-bit result, but a // 128-bit result is reported, so End() does three iterations. // static INLINE void EndPartial( uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3, uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7, uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11) { h11+= h1; h2 ^= h11; h1 = Rot64(h1,44); h0 += h2; h3 ^= h0; h2 = Rot64(h2,15); h1 += h3; h4 ^= h1; h3 = Rot64(h3,34); h2 += h4; h5 ^= h2; h4 = Rot64(h4,21); h3 += h5; h6 ^= h3; h5 = Rot64(h5,38); h4 += h6; h7 ^= h4; h6 = Rot64(h6,33); h5 += h7; h8 ^= h5; h7 = Rot64(h7,10); h6 += h8; h9 ^= h6; h8 = Rot64(h8,13); h7 += h9; h10^= h7; h9 = Rot64(h9,38); h8 += h10; h11^= h8; h10= Rot64(h10,53); h9 += h11; h0 ^= h9; h11= Rot64(h11,42); h10+= h0; h1 ^= h10; h0 = Rot64(h0,54); } static INLINE void End( const uint64 *data, uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3, uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7, uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11) { h0 += data[0]; h1 += data[1]; h2 += data[2]; h3 += data[3]; h4 += data[4]; h5 += data[5]; h6 += data[6]; h7 += data[7]; h8 += data[8]; h9 += data[9]; h10 += data[10]; h11 += data[11]; EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); } // // The goal is for each bit of the input to expand into 128 bits of // apparent entropy before it is fully overwritten. // n trials both set and cleared at least m bits of h0 h1 h2 h3 // n: 2 m: 29 // n: 3 m: 46 // n: 4 m: 57 // n: 5 m: 107 // n: 6 m: 146 // n: 7 m: 152 // when run forwards or backwards // for all 1-bit and 2-bit diffs // with diffs defined by either xor or subtraction // with a base of all zeros plus a counter, or plus another bit, or random // static INLINE void ShortMix(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3) { h2 = Rot64(h2,50); h2 += h3; h0 ^= h2; h3 = Rot64(h3,52); h3 += h0; h1 ^= h3; h0 = Rot64(h0,30); h0 += h1; h2 ^= h0; h1 = Rot64(h1,41); h1 += h2; h3 ^= h1; h2 = Rot64(h2,54); h2 += h3; h0 ^= h2; h3 = Rot64(h3,48); h3 += h0; h1 ^= h3; h0 = Rot64(h0,38); h0 += h1; h2 ^= h0; h1 = Rot64(h1,37); h1 += h2; h3 ^= h1; h2 = Rot64(h2,62); h2 += h3; h0 ^= h2; h3 = Rot64(h3,34); h3 += h0; h1 ^= h3; h0 = Rot64(h0,5); h0 += h1; h2 ^= h0; h1 = Rot64(h1,36); h1 += h2; h3 ^= h1; } // // Mix all 4 inputs together so that h0, h1 are a hash of them all. // // For two inputs differing in just the input bits // Where "differ" means xor or subtraction // And the base value is random, or a counting value starting at that bit // The final result will have each bit of h0, h1 flip // For every input bit, // with probability 50 +- .3% (it is probably better than that) // For every pair of input bits, // with probability 50 +- .75% (the worst case is approximately that) // static INLINE void ShortEnd(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3) { h3 ^= h2; h2 = Rot64(h2,15); h3 += h2; h0 ^= h3; h3 = Rot64(h3,52); h0 += h3; h1 ^= h0; h0 = Rot64(h0,26); h1 += h0; h2 ^= h1; h1 = Rot64(h1,51); h2 += h1; h3 ^= h2; h2 = Rot64(h2,28); h3 += h2; h0 ^= h3; h3 = Rot64(h3,9); h0 += h3; h1 ^= h0; h0 = Rot64(h0,47); h1 += h0; h2 ^= h1; h1 = Rot64(h1,54); h2 += h1; h3 ^= h2; h2 = Rot64(h2,32); h3 += h2; h0 ^= h3; h3 = Rot64(h3,25); h0 += h3; h1 ^= h0; h0 = Rot64(h0,63); h1 += h0; } private: // // Short is used for messages under 192 bytes in length // Short has a low startup cost, the normal mode is good for long // keys, the cost crossover is at about 192 bytes. The two modes were // held to the same quality bar. // static void Short( const void *message, // message (array of bytes, not necessarily aligned) size_t length, // length of message (in bytes) uint64 *hash1, // in/out: in the seed, out the hash value uint64 *hash2); // in/out: in the seed, out the hash value // number of uint64's in internal state static const size_t sc_numVars = 12; // size of the internal state static const size_t sc_blockSize = sc_numVars*8; // size of buffer of unhashed data, in bytes static const size_t sc_bufSize = 2*sc_blockSize; // // sc_const: a constant which: // * is not zero // * is odd // * is a not-very-regular mix of 1's and 0's // * does not need any other special mathematical properties // static const uint64 sc_const = 0xdeadbeefdeadbeefLL; uint64 m_data[2*sc_numVars]; // unhashed data, for partial messages uint64 m_state[sc_numVars]; // internal state of the hash size_t m_length; // total length of the input so far uint8 m_remainder; // length of unhashed data stashed in m_data }; fortran-lang-stdlib-0ede301/test/hash_functions/SpookyV2Test.cpp0000664000175000017500000000250715135654166025224 0ustar alastairalastair#include "SpookyV2.h" #ifdef __cplusplus extern "C" { #endif void SpookyHash32_with_state_test(const void *key, size_t len, const void *state, void *out) { uint64 *state64= (uint64 *)state; uint64 s0 = state64[0]; uint64 s1 = state64[1]; SpookyHash::Hash128(key, len, &s0, &s1); ((uint32 *)out)[0]= (uint32)s0; } void SpookyHash64_with_state_test(const void *key, size_t len, const void *state, void *out) { uint64 *state64= (uint64 *)state; uint64 *out64= (uint64 *)out; out64[0] = state64[0]; uint64 s1 = state64[1]; SpookyHash::Hash128(key, len, out64, &s1); } void SpookyHash128_with_state_test(const void *key, size_t len, const void *state, void *out) { uint64 *state64= (uint64 *)state; uint64 *out64= (uint64 *)out; out64[0] = state64[0]; out64[1] = state64[1]; SpookyHash::Hash128(key, len, out64, out64+1); } void SpookyHash_seed_state_test(int in_bits, const void *seed, void *state) { uint64 *state64= (uint64 *)state; if (in_bits == 32) { state64[0]= state64[1]= ((uint32*)seed)[0]; } else { uint64 *seed64= (uint64 *)seed; if (in_bits == 64) { state64[0]= state64[1]= seed64[0]; } else if (in_bits == 128) { state64[0]= seed64[0]; state64[1]= seed64[1]; } } } #ifdef __cplusplus } #endif fortran-lang-stdlib-0ede301/test/hash_functions/waterhash.h0000664000175000017500000000644015135654166024323 0ustar alastairalastair/* Waterhash takes (optimally) 32-bit inputs and produces a 32-bit hash as its result. It is an edited version of wyhash that uses at most 64-bit math instead of 128-bit. It is meant to use very similar code to Wheathash, which produces a 64-bit hash. Original Author: Wang Yi Waterhash Variant Author: Tommy Ettinger */ #ifndef waterhash_version_3 #define waterhash_version_3 #include #include #include const uint64_t _waterp0 = 0xa0761d65ull, _waterp1 = 0xe7037ed1ull, _waterp2 = 0x8ebc6af1ull; const uint64_t _waterp3 = 0x589965cdull, _waterp4 = 0x1d8e4e27ull, _waterp5 = 0xeb44accbull; static inline uint64_t _watermum(const uint64_t A, const uint64_t B) { uint64_t r = A * B; return r - (r >> 32); } static inline uint64_t _waterr08(const uint8_t *p){ uint8_t v; memcpy(&v, p, 1); return v; } static inline uint64_t _waterr16(const uint8_t *p){ uint16_t v; memcpy(&v, p, 2); return v; } static inline uint64_t _waterr32(const uint8_t *p){ uint32_t v; memcpy(&v, p, 4); return v; } static inline uint32_t waterhash(const void* key, uint32_t len, uint64_t seed){ const uint8_t *p = (const uint8_t*)key; uint32_t i; for (i = 0; i + 16 <= len; i += 16, p += 16) { seed = _watermum( _watermum(_waterr32(p) ^ _waterp1, _waterr32(p + 4) ^ _waterp2) + seed, _watermum(_waterr32(p + 8) ^ _waterp3, _waterr32(p + 12) ^ _waterp4)); } seed += _waterp5; switch (len & 15) { case 1: seed = _watermum(_waterp2 ^ seed, _waterr08(p) ^ _waterp1); break; case 2: seed = _watermum(_waterp3 ^ seed, _waterr16(p) ^ _waterp4); break; case 3: seed = _watermum(_waterr16(p) ^ seed, _waterr08(p + 2) ^ _waterp2); break; case 4: seed = _watermum(_waterr16(p) ^ seed, _waterr16(p + 2) ^ _waterp3); break; case 5: seed = _watermum(_waterr32(p) ^ seed, _waterr08(p + 4) ^ _waterp1); break; case 6: seed = _watermum(_waterr32(p) ^ seed, _waterr16(p + 4) ^ _waterp1); break; case 7: seed = _watermum(_waterr32(p) ^ seed, (_waterr16(p + 4) << 8 | _waterr08(p + 6)) ^ _waterp1); break; case 8: seed = _watermum(_waterr32(p) ^ seed, _waterr32(p + 4) ^ _waterp0); break; case 9: seed = _watermum(_waterr32(p) ^ seed, _waterr32(p + 4) ^ _waterp2) ^ _watermum(seed ^ _waterp4, _waterr08(p + 8) ^ _waterp3); break; case 10: seed = _watermum(_waterr32(p) ^ seed, _waterr32(p + 4) ^ _waterp2) ^ _watermum(seed, _waterr16(p + 8) ^ _waterp3); break; case 11: seed = _watermum(_waterr32(p) ^ seed, _waterr32(p + 4) ^ _waterp2) ^ _watermum(seed, ((_waterr16(p + 8) << 8) | _waterr08(p + 10)) ^ _waterp3); break; case 12: seed = _watermum(_waterr32(p) ^ seed, _waterr32(p + 4) ^ _waterp2) ^ _watermum(seed ^ _waterr32(p + 8), _waterp4); break; case 13: seed = _watermum(_waterr32(p) ^ seed, _waterr32(p + 4) ^ _waterp2) ^ _watermum(seed ^ _waterr32(p + 8), (_waterr08(p + 12)) ^ _waterp4); break; case 14: seed = _watermum(_waterr32(p) ^ seed, _waterr32(p + 4) ^ _waterp2) ^ _watermum(seed ^ _waterr32(p + 8), (_waterr16(p + 12)) ^ _waterp4); break; case 15: seed = _watermum(_waterr32(p) ^ seed, _waterr32(p + 4) ^ _waterp2) ^ _watermum(seed ^ _waterr32(p + 8), (_waterr16(p + 12) << 8 | _waterr08(p + 14)) ^ _waterp4); break; } seed = (seed ^ seed << 16) * (len ^ _waterp0); return (uint32_t)(seed - (seed >> 32)); } #endif fortran-lang-stdlib-0ede301/test/hash_functions/waterhash.c0000664000175000017500000000021315135654166024306 0ustar alastairalastair#include "waterhash.h" int32_t waterhash_test ( const void * key, uint32_t len, uint64_t seed ) { return waterhash (key, len, seed); } fortran-lang-stdlib-0ede301/test/hash_functions/nmhash.h0000664000175000017500000006320315135654166023613 0ustar alastairalastair/* * verification: * NMHASH32: * rurban/smhasher: 0x12A30553 * demerphq/smhasher: 0x3D8F6C47 * NMHASH32X: * rurban/smhasher: 0xA8580227 * demerphq/smhasher: 0x40B451B3 */ #ifdef __cplusplus extern "C" { #endif #ifndef _nmhash_h_ #define _nmhash_h_ #define NMH_VERSION 2 #ifdef _MSC_VER # pragma warning(push, 3) #endif #if defined(__cplusplus) && __cplusplus < 201103L # define __STDC_CONSTANT_MACROS 1 #endif #include #include #if defined(__GNUC__) # if defined(__AVX2__) # include # elif defined(__SSE2__) # include # endif #elif defined(_MSC_VER) # include #endif #ifdef _MSC_VER # pragma warning(pop) #endif #if (defined(__GNUC__) && (__GNUC__ >= 3)) \ || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \ || defined(__clang__) # define NMH_likely(x) __builtin_expect(x, 1) #else # define NMH_likely(x) (x) #endif #if defined(__has_builtin) # if __has_builtin(__builtin_rotateleft32) \ && !(defined(__INTEL_COMPILER) && defined(__APPLE__)) # define NMH_rotl32 __builtin_rotateleft32 /* clang */ # endif #endif #if !defined(NMH_rotl32) # if defined(_MSC_VER) /* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */ # define NMH_rotl32(x,r) _rotl(x,r) # else # define NMH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) # endif #endif #if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */ # define NMH_RESTRICT /* disable */ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */ # define NMH_RESTRICT restrict #elif defined(__cplusplus) && (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)) # define NMH_RESTRICT __restrict__ #elif defined(__cplusplus) && defined(_MSC_VER) # define NMH_RESTRICT __restrict #else # define NMH_RESTRICT /* disable */ #endif /* endian macros */ #ifndef NMHASH_LITTLE_ENDIAN # if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || defined(__x86_64__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || defined(__SDCC) # define NMHASH_LITTLE_ENDIAN 1 # elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) # define NMHASH_LITTLE_ENDIAN 0 # else # warning could not determine endianness! Falling back to little endian. # define NMHASH_LITTLE_ENDIAN 1 # endif #endif /* vector macros */ #define NMH_SCALAR 0 #define NMH_SSE2 1 #define NMH_AVX2 2 #define NMH_AVX512 3 #ifndef NMH_VECTOR /* can be defined on command line */ # if defined(__AVX512BW__) # define NMH_VECTOR NMH_AVX512 /* _mm512_mullo_epi16 requires AVX512BW */ # elif defined(__AVX2__) # define NMH_VECTOR NMH_AVX2 /* add '-mno-avx256-split-unaligned-load' and '-mn-oavx256-split-unaligned-store' for gcc */ # elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) # define NMH_VECTOR NMH_SSE2 # else # define NMH_VECTOR NMH_SCALAR # endif #endif /* align macros */ #if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11+ */ # include # define NMH_ALIGN(n) alignas(n) #elif defined(__GNUC__) # define NMH_ALIGN(n) __attribute__ ((aligned(n))) #elif defined(_MSC_VER) # define NMH_ALIGN(n) __declspec(align(n)) #else # define NMH_ALIGN(n) /* disabled */ #endif #if NMH_VECTOR > 0 # define NMH_ACC_ALIGN 64 #elif defined(__BIGGEST_ALIGNMENT__) # define NMH_ACC_ALIGN __BIGGEST_ALIGNMENT__ #elif defined(__SDCC) # define NMH_ACC_ALIGN 1 #else # define NMH_ACC_ALIGN 16 #endif /* constants */ /* primes from xxh */ #define NMH_PRIME32_1 UINT32_C(0x9E3779B1) #define NMH_PRIME32_2 UINT32_C(0x85EBCA77) #define NMH_PRIME32_3 UINT32_C(0xC2B2AE3D) #define NMH_PRIME32_4 UINT32_C(0x27D4EB2F) /*! Pseudorandom secret taken directly from FARSH. */ NMH_ALIGN(NMH_ACC_ALIGN) static const uint32_t NMH_ACC_INIT[32] = { UINT32_C(0xB8FE6C39), UINT32_C(0x23A44BBE), UINT32_C(0x7C01812C), UINT32_C(0xF721AD1C), UINT32_C(0xDED46DE9), UINT32_C(0x839097DB), UINT32_C(0x7240A4A4), UINT32_C(0xB7B3671F), UINT32_C(0xCB79E64E), UINT32_C(0xCCC0E578), UINT32_C(0x825AD07D), UINT32_C(0xCCFF7221), UINT32_C(0xB8084674), UINT32_C(0xF743248E), UINT32_C(0xE03590E6), UINT32_C(0x813A264C), UINT32_C(0x3C2852BB), UINT32_C(0x91C300CB), UINT32_C(0x88D0658B), UINT32_C(0x1B532EA3), UINT32_C(0x71644897), UINT32_C(0xA20DF94E), UINT32_C(0x3819EF46), UINT32_C(0xA9DEACD8), UINT32_C(0xA8FA763F), UINT32_C(0xE39C343F), UINT32_C(0xF9DCBBC7), UINT32_C(0xC70B4F1D), UINT32_C(0x8A51E04B), UINT32_C(0xCDB45931), UINT32_C(0xC89F7EC9), UINT32_C(0xD9787364), }; #if defined(_MSC_VER) && _MSC_VER >= 1914 # pragma warning(push) # pragma warning(disable: 5045) #endif #ifdef __SDCC # define const # pragma save # pragma disable_warning 110 # pragma disable_warning 126 #endif /* read functions */ static inline uint32_t NMH_readLE32(const void *const p) { uint32_t v; memcpy(&v, p, 4); # if (NMHASH_LITTLE_ENDIAN) return v; # elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) return __builtin_bswap32(v); # elif defined(_MSC_VER) return _byteswap_ulong(v); # else return ((v >> 24) & 0xff) | ((v >> 8) & 0xff00) | ((v << 8) & 0xff0000) | ((v << 24) & 0xff000000); # endif } static inline uint16_t NMH_readLE16(const void *const p) { uint16_t v; memcpy(&v, p, 2); # if (NMHASH_LITTLE_ENDIAN) return v; # else return (uint16_t)((v << 8) | (v >> 8)); # endif } static inline uint32_t NMHASH32_0to8(uint32_t const x, uint32_t const seed2) { /* base mixer: [-6 -12 776bf593 -19 11 3fb39c65 -15 -9 e9139917 -11 16] = 0.027071104091278835 */ const uint32_t m1 = UINT32_C(0x776BF593); const uint32_t m2 = UINT32_C(0x3FB39C65); const uint32_t m3 = UINT32_C(0xE9139917); # if NMH_VECTOR == NMH_SCALAR { union { uint32_t u32; uint16_t u16[2]; } vx; vx.u32 = x; vx.u32 ^= (vx.u32 >> 12) ^ (vx.u32 >> 6); vx.u16[0] *= (uint16_t)m1; vx.u16[1] *= (uint16_t)(m1 >> 16); vx.u32 ^= (vx.u32 << 11) ^ ( vx.u32 >> 19); vx.u16[0] *= (uint16_t)m2; vx.u16[1] *= (uint16_t)(m2 >> 16); vx.u32 ^= seed2; vx.u32 ^= (vx.u32 >> 15) ^ ( vx.u32 >> 9); vx.u16[0] *= (uint16_t)m3; vx.u16[1] *= (uint16_t)(m3 >> 16); vx.u32 ^= (vx.u32 << 16) ^ ( vx.u32 >> 11); return vx.u32; } # else /* at least NMH_SSE2 */ { __m128i hv = _mm_setr_epi32((int)x, 0, 0, 0); const __m128i sv = _mm_setr_epi32((int)seed2, 0, 0, 0); const uint32_t *const result = (const uint32_t*)&hv; hv = _mm_xor_si128(_mm_xor_si128(hv, _mm_srli_epi32(hv, 12)), _mm_srli_epi32(hv, 6)); hv = _mm_mullo_epi16(hv, _mm_setr_epi32((int)m1, 0, 0, 0)); hv = _mm_xor_si128(_mm_xor_si128(hv, _mm_slli_epi32(hv, 11)), _mm_srli_epi32(hv, 19)); hv = _mm_mullo_epi16(hv, _mm_setr_epi32((int)m2, 0, 0, 0)); hv = _mm_xor_si128(hv, sv); hv = _mm_xor_si128(_mm_xor_si128(hv, _mm_srli_epi32(hv, 15)), _mm_srli_epi32(hv, 9)); hv = _mm_mullo_epi16(hv, _mm_setr_epi32((int)m3, 0, 0, 0)); hv = _mm_xor_si128(_mm_xor_si128(hv, _mm_slli_epi32(hv, 16)), _mm_srli_epi32(hv, 11)); return *result; } # endif } #define __NMH_M1 UINT32_C(0xF0D9649B) #define __NMH_M2 UINT32_C(0x29A7935D) #define __NMH_M3 UINT32_C(0x55D35831) NMH_ALIGN(NMH_ACC_ALIGN) static const uint32_t __NMH_M1_V[32] = { __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, __NMH_M1, }; NMH_ALIGN(NMH_ACC_ALIGN) static const uint32_t __NMH_M2_V[32] = { __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, __NMH_M2, }; NMH_ALIGN(NMH_ACC_ALIGN) static const uint32_t __NMH_M3_V[32] = { __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, __NMH_M3, }; static inline uint32_t NMHASH32_9to255(const uint8_t* const NMH_RESTRICT p, size_t const len, uint32_t const seed, int const type) { /* base mixer: [f0d9649b 5 -13 29a7935d -9 11 55d35831 -20 -10 ] = 0.93495901789135362 */ uint32_t result = 0; # if NMH_VECTOR == NMH_SCALAR { union { uint32_t u32; uint16_t u16[2]; } x[4], y[4]; uint32_t const sl = seed + (uint32_t)len; size_t j; x[0].u32 = NMH_PRIME32_1; x[1].u32 = NMH_PRIME32_2; x[2].u32 = NMH_PRIME32_3; x[3].u32 = NMH_PRIME32_4; for (j = 0; j < 4; ++j) y[j].u32 = sl; if (type) { /* 33 to 255 bytes */ size_t const r = (len - 1) / 32; size_t i; for (i = 0; i < r; ++i) { for (j = 0; j < 4; ++j) x[j].u32 ^= NMH_readLE32(p + i * 32 + j * 4); for (j = 0; j < 4; ++j) y[j].u32 ^= NMH_readLE32(p + i * 32 + j * 4 + 16); for (j = 0; j < 4; ++j) x[j].u32 += y[j].u32; for (j = 0; j < 4; ++j) { x[j].u16[0] *= (uint16_t)(__NMH_M1 & 0xFFFF); x[j].u16[1] *= (uint16_t)(__NMH_M1 >> 16); } for (j = 0; j < 4; ++j) x[j].u32 ^= (x[j].u32 << 5) ^ (x[j].u32 >> 13); for (j = 0; j < 4; ++j) { x[j].u16[0] *= (uint16_t)(__NMH_M2 & 0xFFFF); x[j].u16[1] *= (uint16_t)(__NMH_M2 >> 16); } for (j = 0; j < 4; ++j) x[j].u32 ^= y[j].u32; for (j = 0; j < 4; ++j) x[j].u32 ^= (x[j].u32 << 11) ^ (x[j].u32 >> 9); for (j = 0; j < 4; ++j) { x[j].u16[0] *= (uint16_t)(__NMH_M3 & 0xFFFF); x[j].u16[1] *= (uint16_t)(__NMH_M3 >> 16); } for (j = 0; j < 4; ++j) x[j].u32 ^= (x[j].u32 >> 10) ^ (x[j].u32 >> 20); } for (j = 0; j < 4; ++j) x[j].u32 ^= NMH_readLE32(p + len - 32 + j * 4); for (j = 0; j < 4; ++j) y[j].u32 ^= NMH_readLE32(p + len - 16 + j * 4); } else { /* 9 to 32 bytes */ x[0].u32 ^= NMH_readLE32(p); x[1].u32 ^= NMH_readLE32(p + ((len>>4)<<3)); x[2].u32 ^= NMH_readLE32(p + len - 8); x[3].u32 ^= NMH_readLE32(p + len - 8 - ((len>>4)<<3)); y[0].u32 ^= NMH_readLE32(p + 4); y[1].u32 ^= NMH_readLE32(p + ((len>>4)<<3) + 4); y[2].u32 ^= NMH_readLE32(p + len - 8 + 4); y[3].u32 ^= NMH_readLE32(p + len - 8 - ((len>>4)<<3) + 4); } for (j = 0; j < 4; ++j) x[j].u32 += y[j].u32; for (j = 0; j < 4; ++j) y[j].u32 ^= (y[j].u32 << 17) ^ (y[j].u32 >> 6); for (j = 0; j < 4; ++j) { x[j].u16[0] *= (uint16_t)(__NMH_M1 & 0xFFFF); x[j].u16[1] *= (uint16_t)(__NMH_M1 >> 16); } for (j = 0; j < 4; ++j) x[j].u32 ^= (x[j].u32 << 5) ^ (x[j].u32 >> 13); for (j = 0; j < 4; ++j) { x[j].u16[0] *= (uint16_t)(__NMH_M2 & 0xFFFF); x[j].u16[1] *= (uint16_t)(__NMH_M2 >> 16); } for (j = 0; j < 4; ++j) x[j].u32 ^= y[j].u32; for (j = 0; j < 4; ++j) x[j].u32 ^= (x[j].u32 << 11) ^ (x[j].u32 >> 9); for (j = 0; j < 4; ++j) { x[j].u16[0] *= (uint16_t)(__NMH_M3 & 0xFFFF); x[j].u16[1] *= (uint16_t)(__NMH_M3 >> 16); } for (j = 0; j < 4; ++j) x[j].u32 ^= (x[j].u32 >> 10) ^ (x[j].u32 >> 20); x[0].u32 ^= NMH_PRIME32_1; x[1].u32 ^= NMH_PRIME32_2; x[2].u32 ^= NMH_PRIME32_3; x[3].u32 ^= NMH_PRIME32_4; for (j = 1; j < 4; ++j) x[0].u32 += x[j].u32; x[0].u32 ^= sl + (sl >> 5); x[0].u16[0] *= (uint16_t)(__NMH_M3 & 0xFFFF); x[0].u16[1] *= (uint16_t)(__NMH_M3 >> 16); x[0].u32 ^= (x[0].u32 >> 10) ^ (x[0].u32 >> 20); result = x[0].u32; } # else /* at least NMH_SSE2 */ { __m128i const h0 = _mm_setr_epi32((int)NMH_PRIME32_1, (int)NMH_PRIME32_2, (int)NMH_PRIME32_3, (int)NMH_PRIME32_4); __m128i const sl = _mm_set1_epi32((int)seed + (int)len); __m128i const m1 = _mm_set1_epi32((int)__NMH_M1); __m128i const m2 = _mm_set1_epi32((int)__NMH_M2); __m128i const m3 = _mm_set1_epi32((int)__NMH_M3); __m128i x = h0; __m128i y = sl; const uint32_t *const px = (const uint32_t*)&x; if (type) { /* 32 to 127 bytes */ size_t const r = (len - 1) / 32; size_t i; for (i = 0; i < r; ++i) { x = _mm_xor_si128(x, _mm_loadu_si128((const __m128i *)(p + i * 32))); y = _mm_xor_si128(y, _mm_loadu_si128((const __m128i *)(p + i * 32 + 16))); x = _mm_add_epi32(x, y); x = _mm_mullo_epi16(x, m1); x = _mm_xor_si128(_mm_xor_si128(x, _mm_slli_epi32(x, 5)), _mm_srli_epi32(x, 13)); x = _mm_mullo_epi16(x, m2); x = _mm_xor_si128(x, y); x = _mm_xor_si128(_mm_xor_si128(x, _mm_slli_epi32(x, 11)), _mm_srli_epi32(x, 9)); x = _mm_mullo_epi16(x, m3); x = _mm_xor_si128(_mm_xor_si128(x, _mm_srli_epi32(x, 10)), _mm_srli_epi32(x, 20)); } x = _mm_xor_si128(x, _mm_loadu_si128((const __m128i *)(p + len - 32))); y = _mm_xor_si128(y, _mm_loadu_si128((const __m128i *)(p + len - 16))); } else { /* 9 to 32 bytes */ x = _mm_xor_si128(x, _mm_setr_epi32((int)NMH_readLE32(p), (int)NMH_readLE32(p + ((len>>4)<<3)), (int)NMH_readLE32(p + len - 8), (int)NMH_readLE32(p + len - 8 - ((len>>4)<<3)))); y = _mm_xor_si128(y, _mm_setr_epi32((int)NMH_readLE32(p + 4), (int)NMH_readLE32(p + ((len>>4)<<3) + 4), (int)NMH_readLE32(p + len - 8 + 4), (int)NMH_readLE32(p + len - 8 - ((len>>4)<<3) + 4))); } x = _mm_add_epi32(x, y); y = _mm_xor_si128(_mm_xor_si128(y, _mm_slli_epi32(y, 17)), _mm_srli_epi32(y, 6)); x = _mm_mullo_epi16(x, m1); x = _mm_xor_si128(_mm_xor_si128(x, _mm_slli_epi32(x, 5)), _mm_srli_epi32(x, 13)); x = _mm_mullo_epi16(x, m2); x = _mm_xor_si128(x, y); x = _mm_xor_si128(_mm_xor_si128(x, _mm_slli_epi32(x, 11)), _mm_srli_epi32(x, 9)); x = _mm_mullo_epi16(x, m3); x = _mm_xor_si128(_mm_xor_si128(x, _mm_srli_epi32(x, 10)), _mm_srli_epi32(x, 20)); x = _mm_xor_si128(x, h0); x = _mm_add_epi32(x, _mm_srli_si128(x, 4)); x = _mm_add_epi32(x, _mm_srli_si128(x, 8)); x = _mm_xor_si128(x, _mm_add_epi32(sl, _mm_srli_epi32(sl, 5))); x = _mm_mullo_epi16(x, m3); x = _mm_xor_si128(_mm_xor_si128(x, _mm_srli_epi32(x, 10)), _mm_srli_epi32(x, 20)); result = *px; } # endif return *&result; } #define NMHASH32_9to32(p, len, seed) NMHASH32_9to255(p, len, seed, 0) #define NMHASH32_33to255(p, len, seed) NMHASH32_9to255(p, len, seed, 1) #undef __NMH_M1 #undef __NMH_M2 #undef __NMH_M3 #if NMH_VECTOR == NMH_SCALAR #define NMHASH32_long_round NMHASH32_long_round_scalar static inline void NMHASH32_long_round_scalar(uint32_t *const NMH_RESTRICT accX, uint32_t *const NMH_RESTRICT accY, const uint8_t* const NMH_RESTRICT p) { /* breadth first calculation will hint some compiler to auto vectorize the code * on gcc, the performance becomes 10x than the depth first, and about 80% of the manually vectorized code */ const size_t nbGroups = sizeof(NMH_ACC_INIT) / sizeof(*NMH_ACC_INIT); size_t i; for (i = 0; i < nbGroups; ++i) { accX[i] ^= NMH_readLE32(p + i * 4); } for (i = 0; i < nbGroups; ++i) { accY[i] ^= NMH_readLE32(p + i * 4 + sizeof(NMH_ACC_INIT)); } for (i = 0; i < nbGroups; ++i) { accX[i] += accY[i]; } for (i = 0; i < nbGroups; ++i) { accY[i] ^= accX[i] >> 1; } for (i = 0; i < nbGroups * 2; ++i) { ((uint16_t*)accX)[i] *= ((uint16_t*)__NMH_M1_V)[i]; } for (i = 0; i < nbGroups; ++i) { accX[i] ^= accX[i] << 5 ^ accX[i] >> 13; } for (i = 0; i < nbGroups * 2; ++i) { ((uint16_t*)accX)[i] *= ((uint16_t*)__NMH_M2_V)[i]; } for (i = 0; i < nbGroups; ++i) { accX[i] ^= accY[i]; } for (i = 0; i < nbGroups; ++i) { accX[i] ^= accX[i] << 11 ^ accX[i] >> 9; } for (i = 0; i < nbGroups * 2; ++i) { ((uint16_t*)accX)[i] *= ((uint16_t*)__NMH_M3_V)[i]; } for (i = 0; i < nbGroups; ++i) { accX[i] ^= accX[i] >> 10 ^ accX[i] >> 20; } } #endif #if NMH_VECTOR == NMH_SSE2 # define _NMH_MM_(F) _mm_ ## F # define _NMH_MMW_(F) _mm_ ## F ## 128 # define _NMH_MM_T __m128i #elif NMH_VECTOR == NMH_AVX2 # define _NMH_MM_(F) _mm256_ ## F # define _NMH_MMW_(F) _mm256_ ## F ## 256 # define _NMH_MM_T __m256i #elif NMH_VECTOR == NMH_AVX512 # define _NMH_MM_(F) _mm512_ ## F # define _NMH_MMW_(F) _mm512_ ## F ## 512 # define _NMH_MM_T __m512i #endif #if NMH_VECTOR == NMH_SSE2 || NMH_VECTOR == NMH_AVX2 || NMH_VECTOR == NMH_AVX512 # define NMHASH32_long_round NMHASH32_long_round_sse # define NMH_VECTOR_NB_GROUP (sizeof(NMH_ACC_INIT) / sizeof(*NMH_ACC_INIT) / (sizeof(_NMH_MM_T) / sizeof(*NMH_ACC_INIT))) static inline void NMHASH32_long_round_sse(uint32_t *const NMH_RESTRICT accX, uint32_t *const NMH_RESTRICT accY, const uint8_t* const NMH_RESTRICT p) { const _NMH_MM_T *const NMH_RESTRICT m1 = (const _NMH_MM_T * NMH_RESTRICT)__NMH_M1_V; const _NMH_MM_T *const NMH_RESTRICT m2 = (const _NMH_MM_T * NMH_RESTRICT)__NMH_M2_V; const _NMH_MM_T *const NMH_RESTRICT m3 = (const _NMH_MM_T * NMH_RESTRICT)__NMH_M3_V; _NMH_MM_T *const xaccX = ( _NMH_MM_T * )accX; _NMH_MM_T *const xaccY = ( _NMH_MM_T * )accY; _NMH_MM_T *const xp = ( _NMH_MM_T * )p; size_t i; for (i = 0; i < NMH_VECTOR_NB_GROUP; ++i) { xaccX[i] = _NMH_MMW_(xor_si)(xaccX[i], _NMH_MMW_(loadu_si)(xp + i)); } for (i = 0; i < NMH_VECTOR_NB_GROUP; ++i) { xaccY[i] = _NMH_MMW_(xor_si)(xaccY[i], _NMH_MMW_(loadu_si)(xp + i + NMH_VECTOR_NB_GROUP)); } for (i = 0; i < NMH_VECTOR_NB_GROUP; ++i) { xaccX[i] = _NMH_MM_(add_epi32)(xaccX[i], xaccY[i]); } for (i = 0; i < NMH_VECTOR_NB_GROUP; ++i) { xaccY[i] = _NMH_MMW_(xor_si)(xaccY[i], _NMH_MM_(srli_epi32)(xaccX[i], 1)); } for (i = 0; i < NMH_VECTOR_NB_GROUP; ++i) { xaccX[i] = _NMH_MM_(mullo_epi16)(xaccX[i], *m1); } for (i = 0; i < NMH_VECTOR_NB_GROUP; ++i) { xaccX[i] = _NMH_MMW_(xor_si)(_NMH_MMW_(xor_si)(xaccX[i], _NMH_MM_(slli_epi32)(xaccX[i], 5)), _NMH_MM_(srli_epi32)(xaccX[i], 13)); } for (i = 0; i < NMH_VECTOR_NB_GROUP; ++i) { xaccX[i] = _NMH_MM_(mullo_epi16)(xaccX[i], *m2); } for (i = 0; i < NMH_VECTOR_NB_GROUP; ++i) { xaccX[i] = _NMH_MMW_(xor_si)(xaccX[i], xaccY[i]); } for (i = 0; i < NMH_VECTOR_NB_GROUP; ++i) { xaccX[i] = _NMH_MMW_(xor_si)(_NMH_MMW_(xor_si)(xaccX[i], _NMH_MM_(slli_epi32)(xaccX[i], 11)), _NMH_MM_(srli_epi32)(xaccX[i], 9)); } for (i = 0; i < NMH_VECTOR_NB_GROUP; ++i) { xaccX[i] = _NMH_MM_(mullo_epi16)(xaccX[i], *m3); } for (i = 0; i < NMH_VECTOR_NB_GROUP; ++i) { xaccX[i] = _NMH_MMW_(xor_si)(_NMH_MMW_(xor_si)(xaccX[i], _NMH_MM_(srli_epi32)(xaccX[i], 10)), _NMH_MM_(srli_epi32)(xaccX[i], 20)); } } # undef _NMH_MM_ # undef _NMH_MMW_ # undef _NMH_MM_T # undef NMH_VECTOR_NB_GROUP #endif static uint32_t NMHASH32_long(const uint8_t* const NMH_RESTRICT p, size_t const len, uint32_t const seed) { NMH_ALIGN(NMH_ACC_ALIGN) uint32_t accX[sizeof(NMH_ACC_INIT)/sizeof(*NMH_ACC_INIT)]; NMH_ALIGN(NMH_ACC_ALIGN) uint32_t accY[sizeof(accX)/sizeof(*accX)]; size_t const nbRounds = (len - 1) / (sizeof(accX) + sizeof(accY)); size_t i; uint32_t sum = 0; /* init */ for (i = 0; i < sizeof(accX)/sizeof(*accX); ++i) accX[i] = NMH_ACC_INIT[i]; for (i = 0; i < sizeof(accY)/sizeof(*accY); ++i) accY[i] = seed; for (i = 0; i < nbRounds; ++i) { NMHASH32_long_round(accX, accY, p + i * (sizeof(accX) + sizeof(accY))); } NMHASH32_long_round(accX, accY, p + len - (sizeof(accX) + sizeof(accY))); /* merge acc */ for (i = 0; i < sizeof(accX)/sizeof(*accX); ++i) accX[i] ^= NMH_ACC_INIT[i]; for (i = 0; i < sizeof(accX)/sizeof(*accX); ++i) sum += accX[i]; # if SIZE_MAX > UINT32_C(-1) sum += (uint32_t)(len >> 32); # endif return sum ^ (uint32_t)len; } static inline uint32_t NMHASH32_avalanche32(uint32_t const x) { /* [-21 -8 cce5196d 12 -7 464be229 -21 -8] = 3.2267098842182733 */ const uint32_t m1 = UINT32_C(0xCCE5196D); const uint32_t m2 = UINT32_C(0x464BE229); union { uint32_t u32; uint16_t u16[2]; } vx; vx.u32 = x; vx.u32 ^= (vx.u32 >> 8) ^ (vx.u32 >> 21); vx.u16[0] = (uint16_t)(vx.u16[0] * (uint16_t)m1); vx.u16[1] = (uint16_t)(vx.u16[1] * (uint16_t)(m1 >> 16)); vx.u32 ^= (vx.u32 << 12) ^ (vx.u32 >> 7); vx.u16[0] = (uint16_t)(vx.u16[0] * (uint16_t)m2); vx.u16[1] = (uint16_t)(vx.u16[1] * (uint16_t)(m2 >> 16)); return vx.u32 ^ (vx.u32 >> 8) ^ (vx.u32 >> 21); } static inline uint32_t NMHASH32(const void* const NMH_RESTRICT input, size_t const len, uint32_t seed) { const uint8_t *const p = (const uint8_t *)input; if (NMH_likely(len <= 32)) { if(NMH_likely(len > 8)) { return NMHASH32_9to32(p, len, seed); } if(NMH_likely(len > 4)) { uint32_t x = NMH_readLE32(p); uint32_t y = NMH_readLE32(p + len - 4) ^ (NMH_PRIME32_4 + 2 + seed); x += y; x ^= x << (len + 7); return NMHASH32_0to8(x, NMH_rotl32(y, 5)); } else { union { uint32_t u32; uint16_t u16[2]; uint8_t u8[4]; } data; switch (len) { case 0: seed += NMH_PRIME32_2; data.u32 = 0; break; case 1: seed += NMH_PRIME32_2 + (UINT32_C(1) << 24) + (1 << 1); data.u32 = p[0]; break; case 2: seed += NMH_PRIME32_2 + (UINT32_C(2) << 24) + (2 << 1); data.u32 = NMH_readLE16(p); break; case 3: seed += NMH_PRIME32_2 + (UINT32_C(3) << 24) + (3 << 1); data.u16[1] = p[2]; data.u16[0] = NMH_readLE16(p); break; case 4: seed += NMH_PRIME32_3; data.u32 = NMH_readLE32(p); break; default: return 0; } return NMHASH32_0to8(data.u32 + seed, NMH_rotl32(seed, 5)); } } if (NMH_likely(len < 256)) { return NMHASH32_33to255(p, len, seed); } return NMHASH32_avalanche32(NMHASH32_long(p, len, seed)); } static inline uint32_t NMHASH32X_0to4(uint32_t x, uint32_t const seed) { /* [bdab1ea9 18 a7896a1b 12 83796a2d 16] = 0.092922873297662509 */ x ^= seed; x *= UINT32_C(0xBDAB1EA9); x += NMH_rotl32(seed, 31); x ^= x >> 18; x *= UINT32_C(0xA7896A1B); x ^= x >> 12; x *= UINT32_C(0x83796A2D); x ^= x >> 16; return x; } static inline uint32_t NMHASH32X_5to8(const uint8_t* const NMH_RESTRICT p, size_t const len, uint32_t const seed) { /* - 5 to 9 bytes * - mixer: [11049a7d 23 bcccdc7b 12 065e9dad 12] = 0.16577596555667246 */ uint32_t x = NMH_readLE32(p) ^ NMH_PRIME32_3; uint32_t const y = NMH_readLE32(p + len - 4) ^ seed; x += y; x ^= x >> len; x *= UINT32_C(0x11049A7D); x ^= x >> 23; x *= UINT32_C(0xBCCCDC7B); x ^= NMH_rotl32(y, 3); x ^= x >> 12; x *= UINT32_C(0x065E9DAD); x ^= x >> 12; return x; } static inline uint32_t NMHASH32X_9to255(const uint8_t* const NMH_RESTRICT p, size_t const len, uint32_t const seed) { /* - at least 9 bytes * - base mixer: [11049a7d 23 bcccdc7b 12 065e9dad 12] = 0.16577596555667246 * - tail mixer: [16 a52fb2cd 15 551e4d49 16] = 0.17162579707098322 */ uint32_t x = NMH_PRIME32_3; uint32_t y = seed; uint32_t a = NMH_PRIME32_4; uint32_t b = seed; size_t i, r = (len - 1) / 16; for (i = 0; i < r; ++i) { x ^= NMH_readLE32(p + i * 16 + 0); y ^= NMH_readLE32(p + i * 16 + 4); x ^= y; x *= UINT32_C(0x11049A7D); x ^= x >> 23; x *= UINT32_C(0xBCCCDC7B); y = NMH_rotl32(y, 4); x ^= y; x ^= x >> 12; x *= UINT32_C(0x065E9DAD); x ^= x >> 12; a ^= NMH_readLE32(p + i * 16 + 8); b ^= NMH_readLE32(p + i * 16 + 12); a ^= b; a *= UINT32_C(0x11049A7D); a ^= a >> 23; a *= UINT32_C(0xBCCCDC7B); b = NMH_rotl32(b, 3); a ^= b; a ^= a >> 12; a *= UINT32_C(0x065E9DAD); a ^= a >> 12; } if (NMH_likely(((uint8_t)len-1) & 8)) { if (NMH_likely(((uint8_t)len-1) & 4)) { a ^= NMH_readLE32(p + r * 16 + 0); b ^= NMH_readLE32(p + r * 16 + 4); a ^= b; a *= UINT32_C(0x11049A7D); a ^= a >> 23; a *= UINT32_C(0xBCCCDC7B); a ^= NMH_rotl32(b, 4); a ^= a >> 12; a *= UINT32_C(0x065E9DAD); } else { a ^= NMH_readLE32(p + r * 16) + b; a ^= a >> 16; a *= UINT32_C(0xA52FB2CD); a ^= a >> 15; a *= UINT32_C(0x551E4D49); } x ^= NMH_readLE32(p + len - 8); y ^= NMH_readLE32(p + len - 4); x ^= y; x *= UINT32_C(0x11049A7D); x ^= x >> 23; x *= UINT32_C(0xBCCCDC7B); x ^= NMH_rotl32(y, 3); x ^= x >> 12; x *= UINT32_C(0x065E9DAD); } else { if (NMH_likely(((uint8_t)len-1) & 4)) { a ^= NMH_readLE32(p + r * 16) + b; a ^= a >> 16; a *= UINT32_C(0xA52FB2CD); a ^= a >> 15; a *= UINT32_C(0x551E4D49); } x ^= NMH_readLE32(p + len - 4) + y; x ^= x >> 16; x *= UINT32_C(0xA52FB2CD); x ^= x >> 15; x *= UINT32_C(0x551E4D49); } x ^= (uint32_t)len; x ^= NMH_rotl32(a, 27); /* rotate one lane to pass Diff test */ x ^= x >> 14; x *= UINT32_C(0x141CC535); return x; } static inline uint32_t NMHASH32X_avalanche32(uint32_t x) { /* mixer with 2 mul from skeeto/hash-prospector: * [15 d168aaad 15 af723597 15] = 0.15983776156606694 */ x ^= x >> 15; x *= UINT32_C(0xD168AAAD); x ^= x >> 15; x *= UINT32_C(0xAF723597); x ^= x >> 15; return x; } /* use 32*32->32 multiplication for short hash */ static inline uint32_t NMHASH32X(const void* const NMH_RESTRICT input, size_t const len, uint32_t seed) { const uint8_t *const p = (const uint8_t *)input; if (NMH_likely(len <= 8)) { if (NMH_likely(len > 4)) { return NMHASH32X_5to8(p, len, seed); } else { /* 0-4 bytes */ union { uint32_t u32; uint16_t u16[2]; uint8_t u8[4]; } data; switch (len) { case 0: seed += NMH_PRIME32_2; data.u32 = 0; break; case 1: seed += NMH_PRIME32_2 + (UINT32_C(1) << 24) + (1 << 1); data.u32 = p[0]; break; case 2: seed += NMH_PRIME32_2 + (UINT32_C(2) << 24) + (2 << 1); data.u32 = NMH_readLE16(p); break; case 3: seed += NMH_PRIME32_2 + (UINT32_C(3) << 24) + (3 << 1); data.u16[1] = p[2]; data.u16[0] = NMH_readLE16(p); break; case 4: seed += NMH_PRIME32_1; data.u32 = NMH_readLE32(p); break; default: return 0; } return NMHASH32X_0to4(data.u32, seed); } } if (NMH_likely(len < 256)) { return NMHASH32X_9to255(p, len, seed); } return NMHASH32X_avalanche32(NMHASH32_long(p, len, seed)); } #if defined(_MSC_VER) && _MSC_VER >= 1914 # pragma warning(pop) #endif #ifdef __SDCC # pragma restore # undef const #endif #endif /* _nmhash_h_ */ #ifdef __cplusplus } #endif fortran-lang-stdlib-0ede301/test/hash_functions/SpookyV2.cpp0000664000175000017500000002052115135654166024360 0ustar alastairalastair// Spooky Hash // A 128-bit noncryptographic hash, for checksums and table lookup // By Bob Jenkins. Public domain. // Oct 31 2010: published framework, disclaimer ShortHash isn't right // Nov 7 2010: disabled ShortHash // Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again // April 10 2012: buffer overflow on platforms without unaligned reads // July 12 2012: was passing out variables in final to in/out in short // July 30 2012: I reintroduced the buffer overflow // August 5 2012: SpookyV2: d = should be d += in short hash, and remove extra mix from long hash #include #include "SpookyV2.h" #define ALLOW_UNALIGNED_READS 1 // // short hash ... it could be used on any message, // but it's used by Spooky just for short messages. // void SpookyHash::Short( const void *message, size_t length, uint64 *hash1, uint64 *hash2) { uint64 buf[2*sc_numVars]; union { const uint8 *p8; uint32 *p32; uint64 *p64; size_t i; } u; u.p8 = (const uint8 *)message; if (!ALLOW_UNALIGNED_READS && (u.i & 0x7)) { memcpy(buf, message, length); u.p64 = buf; } size_t remainder = length%32; uint64 a=*hash1; uint64 b=*hash2; uint64 c=sc_const; uint64 d=sc_const; if (length > 15) { const uint64 *end = u.p64 + (length/32)*4; // handle all complete sets of 32 bytes for (; u.p64 < end; u.p64 += 4) { c += u.p64[0]; d += u.p64[1]; ShortMix(a,b,c,d); a += u.p64[2]; b += u.p64[3]; } //Handle the case of 16+ remaining bytes. if (remainder >= 16) { c += u.p64[0]; d += u.p64[1]; ShortMix(a,b,c,d); u.p64 += 2; remainder -= 16; } } // Handle the last 0..15 bytes, and its length d += ((uint64)length) << 56; switch (remainder) { case 15: d += ((uint64)u.p8[14]) << 48; case 14: d += ((uint64)u.p8[13]) << 40; case 13: d += ((uint64)u.p8[12]) << 32; case 12: d += u.p32[2]; c += u.p64[0]; break; case 11: d += ((uint64)u.p8[10]) << 16; case 10: d += ((uint64)u.p8[9]) << 8; case 9: d += (uint64)u.p8[8]; case 8: c += u.p64[0]; break; case 7: c += ((uint64)u.p8[6]) << 48; case 6: c += ((uint64)u.p8[5]) << 40; case 5: c += ((uint64)u.p8[4]) << 32; case 4: c += u.p32[0]; break; case 3: c += ((uint64)u.p8[2]) << 16; case 2: c += ((uint64)u.p8[1]) << 8; case 1: c += (uint64)u.p8[0]; break; case 0: c += sc_const; d += sc_const; } ShortEnd(a,b,c,d); *hash1 = a; *hash2 = b; } // do the whole hash in one call void SpookyHash::Hash128( const void *message, size_t length, uint64 *hash1, uint64 *hash2) { if (length < sc_bufSize) { Short(message, length, hash1, hash2); return; } uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11; uint64 buf[sc_numVars]; uint64 *end; union { const uint8 *p8; uint64 *p64; size_t i; } u; size_t remainder; h0=h3=h6=h9 = *hash1; h1=h4=h7=h10 = *hash2; h2=h5=h8=h11 = sc_const; u.p8 = (const uint8 *)message; end = u.p64 + (length/sc_blockSize)*sc_numVars; // handle all whole sc_blockSize blocks of bytes if (ALLOW_UNALIGNED_READS || ((u.i & 0x7) == 0)) { while (u.p64 < end) { Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); u.p64 += sc_numVars; } } else { while (u.p64 < end) { memcpy(buf, u.p64, sc_blockSize); Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); u.p64 += sc_numVars; } } // handle the last partial block of sc_blockSize bytes remainder = (length - ((const uint8 *)end-(const uint8 *)message)); memcpy(buf, end, remainder); memset(((uint8 *)buf)+remainder, 0, sc_blockSize-remainder); ((uint8 *)buf)[sc_blockSize-1] = remainder; // do some final mixing End(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); *hash1 = h0; *hash2 = h1; } // init spooky state void SpookyHash::Init(uint64 seed1, uint64 seed2) { m_length = 0; m_remainder = 0; m_state[0] = seed1; m_state[1] = seed2; } // add a message fragment to the state void SpookyHash::Update(const void *message, size_t length) { uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11; size_t newLength = length + m_remainder; uint8 remainder; union { const uint8 *p8; uint64 *p64; size_t i; } u; const uint64 *end; // Is this message fragment too short? If it is, stuff it away. if (newLength < sc_bufSize) { memcpy(&((uint8 *)m_data)[m_remainder], message, length); m_length = length + m_length; m_remainder = (uint8)newLength; return; } // init the variables if (m_length < sc_bufSize) { h0=h3=h6=h9 = m_state[0]; h1=h4=h7=h10 = m_state[1]; h2=h5=h8=h11 = sc_const; } else { h0 = m_state[0]; h1 = m_state[1]; h2 = m_state[2]; h3 = m_state[3]; h4 = m_state[4]; h5 = m_state[5]; h6 = m_state[6]; h7 = m_state[7]; h8 = m_state[8]; h9 = m_state[9]; h10 = m_state[10]; h11 = m_state[11]; } m_length = length + m_length; // if we've got anything stuffed away, use it now if (m_remainder) { uint8 prefix = sc_bufSize-m_remainder; memcpy(&(((uint8 *)m_data)[m_remainder]), message, prefix); u.p64 = m_data; Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); Mix(&u.p64[sc_numVars], h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); u.p8 = ((const uint8 *)message) + prefix; length -= prefix; } else { u.p8 = (const uint8 *)message; } // handle all whole blocks of sc_blockSize bytes end = u.p64 + (length/sc_blockSize)*sc_numVars; remainder = (uint8)(length-((const uint8 *)end-u.p8)); if (ALLOW_UNALIGNED_READS || (u.i & 0x7) == 0) { while (u.p64 < end) { Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); u.p64 += sc_numVars; } } else { while (u.p64 < end) { memcpy(m_data, u.p8, sc_blockSize); Mix(m_data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); u.p64 += sc_numVars; } } // stuff away the last few bytes m_remainder = remainder; memcpy(m_data, end, remainder); // stuff away the variables m_state[0] = h0; m_state[1] = h1; m_state[2] = h2; m_state[3] = h3; m_state[4] = h4; m_state[5] = h5; m_state[6] = h6; m_state[7] = h7; m_state[8] = h8; m_state[9] = h9; m_state[10] = h10; m_state[11] = h11; } // report the hash for the concatenation of all message fragments so far void SpookyHash::Final(uint64 *hash1, uint64 *hash2) { // init the variables if (m_length < sc_bufSize) { *hash1 = m_state[0]; *hash2 = m_state[1]; Short( m_data, m_length, hash1, hash2); return; } const uint64 *data = (const uint64 *)m_data; uint8 remainder = m_remainder; uint64 h0 = m_state[0]; uint64 h1 = m_state[1]; uint64 h2 = m_state[2]; uint64 h3 = m_state[3]; uint64 h4 = m_state[4]; uint64 h5 = m_state[5]; uint64 h6 = m_state[6]; uint64 h7 = m_state[7]; uint64 h8 = m_state[8]; uint64 h9 = m_state[9]; uint64 h10 = m_state[10]; uint64 h11 = m_state[11]; if (remainder >= sc_blockSize) { // m_data can contain two blocks; handle any whole first block Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); data += sc_numVars; remainder -= sc_blockSize; } // mix in the last partial block, and the length mod sc_blockSize memset(&((uint8 *)data)[remainder], 0, (sc_blockSize-remainder)); ((uint8 *)data)[sc_blockSize-1] = remainder; // do some final mixing End(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); *hash1 = h0; *hash2 = h1; } fortran-lang-stdlib-0ede301/test/hash_functions/pengyhash.h0000664000175000017500000000023315135654166024315 0ustar alastairalastair#ifndef _PENGYHASH_H #define _PENGYHASH_H #include #include uint64_t pengyhash(const void *p, size_t size, uint32_t seed); #endif fortran-lang-stdlib-0ede301/test/hash_functions/generate_hash_arrays.cpp0000664000175000017500000001136515135654166027050 0ustar alastairalastair#include #include extern "C" { #include "nmhash.h" #include "pengyhash.h" #include "waterhash.h" int generate_all_c_hash(); } #include "SpookyV2.h" void SpookyHash32_with_state_test(const void *key, size_t len, const void *state, void *out) { uint64_t *state64= (uint64_t *)state; uint64_t s0 = state64[0]; uint64_t s1 = state64[1]; SpookyHash::Hash128(key, len, &s0, &s1); ((uint32_t *)out)[0]= (uint32_t)s0; } void SpookyHash64_with_state_test(const void *key, size_t len, const void *state, void *out) { uint64_t *state64= (uint64_t *)state; uint64_t *out64= (uint64_t *)out; out64[0] = state64[0]; uint64_t s1 = state64[1]; SpookyHash::Hash128(key, len, out64, &s1); } void SpookyHash128_with_state_test(const void *key, size_t len, const void *state, void *out) { uint64_t *state64= (uint64_t *)state; uint64_t *out64= (uint64_t *)out; out64[0] = state64[0]; out64[1] = state64[1]; SpookyHash::Hash128(key, len, out64, out64+1); } void SpookyHash_seed_state_test(int in_bits, const void *seed, void *state) { uint64_t *state64= (uint64_t *)state; if (in_bits == 32) { state64[0]= state64[1]= ((uint32_t*)seed)[0]; } else { uint64_t *seed64= (uint64_t *)seed; if (in_bits == 64) { state64[0]= state64[1]= seed64[0]; } else if (in_bits == 128) { state64[0]= seed64[0]; state64[1]= seed64[1]; } } } using namespace std; static const int SIZE = 2048; char * key_array = new char[SIZE]; static const uint32_t NM_SEED = 0xdeadbeef; static const uint64_t WATER_SEED = 0xdeadbeef1eadbeef; static const uint32_t PENGY_SEED = 0xdeadbeef; static const uint64_t SPOOKY_SEED[2] = { WATER_SEED, WATER_SEED }; int read_keys(){ string inFileName = "key_array.bin"; std::ifstream fin( inFileName, ios::in | ios::binary ); if (!fin){ cout << "Cannot open key_array.bin!" << endl; return 1; } fin.read(key_array, SIZE); fin.close(); return 0; } int write_nmhash32(){ size_t i; uint32_t hash; string outFileName = "c_nmhash32_array.bin"; std::ofstream fout( outFileName, ios::out | ios::binary ); if (!fout){ cout << "Cannot open c_nmhash32_array.bin!" << endl; return 1; } for( i=0; i<=SIZE; i+=1 ){ hash = NMHASH32((void *) key_array, i, NM_SEED); fout.write((char *) &hash, 4); } fout.close(); return 0; } int write_nmhash32x(){ size_t i; uint32_t hash; string outFileName = "c_nmhash32x_array.bin"; std::ofstream fout( outFileName, ios::out | ios::binary ); if (!fout){ cout << "Cannot open c_nmhash32x_array.bin!" << endl; return 1; } for( i=0; i<=SIZE; i+=1 ){ hash = NMHASH32X((void *) key_array, i, NM_SEED); fout.write((char *) &hash, 4); } fout.close(); return 0; } int write_water(){ uint32_t i; uint32_t hash; string outFileName = "c_water_hash_array.bin"; std::ofstream fout( outFileName, ios::out | ios::binary ); if (!fout){ cout << "Cannot open c_water_hash_array.bin!" << endl; return 1; } for( i=0; i<=SIZE; i+=1 ){ hash = waterhash((void *) key_array, i, WATER_SEED); fout.write((char *) &hash, 4); } fout.close(); return 0; } int write_pengy(){ size_t i; uint64_t hash; string outFileName = "c_pengy_hash_array.bin"; std::ofstream fout( outFileName, ios::out | ios::binary ); if (!fout){ cout << "Cannot open c_pengy_hash_array.bin!" << endl; return 1; } for( i=0; i<=SIZE; i+=1 ){ hash = pengyhash((void *) key_array, i, PENGY_SEED); fout.write((char *) &hash, 8); } fout.close(); return 0; } int write_spooky(){ size_t i; uint64_t hash[2]; string outFileName = "c_spooky_hash_array.bin"; std::ofstream fout( outFileName, ios::out | ios::binary ); if (!fout){ cout << "Cannot open c_spooky_hash_array.bin!" << endl; return 1; } for( i=0; i<=SIZE; i+=1 ){ SpookyHash128_with_state_test((void *) key_array, i, (void *) SPOOKY_SEED, (void *) hash); fout.write((char *) hash, 16); } fout.close(); return 0; } int generate_all_c_hash(){ if (read_keys()==1){return 1;}; if (write_nmhash32()==1){return 1;}; if (write_nmhash32x()==1){return 1;}; if (write_water()==1){return 1;}; if (write_pengy()==1){return 1;}; if (write_spooky()==1){return 1;}; return 0; } /* int main(){ if (read_keys()==1){return 1;}; if (write_nmhash32()==1){return 1;}; if (write_nmhash32x()==1){return 1;}; if (write_water()==1){return 1;}; if (write_pengy()==1){return 1;}; if (write_spooky()==1){return 1;}; return 0; } */ fortran-lang-stdlib-0ede301/test/string/0000775000175000017500000000000015135654166020453 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/string/test_string_to_number.fypp0000664000175000017500000001200415135654166025767 0ustar alastairalastair#: include "common.fypp" module test_string_to_number use stdlib_kinds, only: sp, dp, xdp, qp use stdlib_str2num, only: to_num use testdrive, only : new_unittest, unittest_type, error_type, check implicit none contains !> Collect all exported unit tests subroutine collect_string_to_number(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("to_sp", test_to_sp), & new_unittest("to_dp", test_to_dp) & #:if WITH_QP , new_unittest("to_qp", test_to_qp) & #:endif #:if WITH_XDP , new_unittest("to_xdp", test_to_xdp) & #:endif ] end subroutine collect_string_to_number #:for k1, t1 in REAL_KINDS_TYPES subroutine test_to_${k1}$(error) type(error_type), allocatable, intent(out) :: error integer, parameter :: wp = ${k1}$ call check(error, ucheck("1.234")) if (allocated(error)) return call check(error, ucheck("1.E1")) if (allocated(error)) return call check(error, ucheck("1e0")) if (allocated(error)) return call check(error, ucheck("0.1234E0")) if (allocated(error)) return call check(error, ucheck("12.34E0")) if (allocated(error)) return call check(error, ucheck("0.34E2")) if (allocated(error)) return call check(error, ucheck(".34e0")) if (allocated(error)) return call check(error, ucheck("34.E1")) if (allocated(error)) return call check(error, ucheck("-34.5E1")) if (allocated(error)) return call check(error, ucheck("0.0021E10")) if (allocated(error)) return call check(error, ucheck("12.21e-1")) if (allocated(error)) return call check(error, ucheck("12.21e+001 ")) if (allocated(error)) return call check(error, ucheck("-1")) if (allocated(error)) return call check(error, ucheck(" -0.23317260678539647E-01 ")) if (allocated(error)) return call check(error, ucheck(" 2.5647869e-003 "//char(13)//char(10))) if (allocated(error)) return call check(error, ucheck("1.-3")) if (allocated(error)) return call check(error, ucheck("Inf")) if (allocated(error)) return call check(error, ucheck("-Inf")) if (allocated(error)) return call check(error, ucheck("NaN")) if (allocated(error)) return call check(error, ucheck("0.123456789123456789123456789123456789")) if (allocated(error)) return call check(error, ucheck("1234567890123456789012345678901234567890-9") ) if (allocated(error)) return call check(error, ucheck("123456.78901234567890123456789012345678901234567890+2") ) if (allocated(error)) return call check(error, ucheck("0.140129846432481707092372958328991613128026194187651577"//& & "175706828388979108268586060148663818836212158203125E-44")) if (allocated(error)) return contains logical function ucheck(s) character(*), intent(in) :: s real(wp) :: formatted_read_out real(wp) :: to_num_out real(wp) :: abs_err real(wp) :: rel_err ucheck = .true. read(s,*) formatted_read_out to_num_out = to_num(s, to_num_out) abs_err = to_num_out - formatted_read_out rel_err = abs_err / formatted_read_out #:if k1 == "sp" if(abs(rel_err) > 0.0_wp) then #:elif k1 == "dp" if(abs(rel_err) > epsilon(0.0_wp)) then #:elif k1 == "xdp" if(abs(rel_err) > 200*epsilon(0.0_wp)) then #:elif k1 == "qp" if(abs(rel_err) > 200*epsilon(0.0_wp)) then #:endif write(*,"('formatted read : ', g0)") formatted_read_out write(*,"('to_num : ', g0)") to_num_out write(*,"('difference abs : ', g0)") abs_err write(*,"('difference rel : ', g0, '%')") rel_err * 100 ucheck = .false. end if end function end subroutine #:endfor end module test_string_to_number program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_string_to_number, only : collect_string_to_number implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("string_to_number", collect_string_to_number) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/string/test_string_derivedtype_io.f900000664000175000017500000000730015135654166026433 0ustar alastairalastair! SPDX-Identifer: MIT module test_string_derivedtype_io use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_string_type, only : string_type, assignment(=), len, & write(formatted), read(formatted), write(unformatted), read(unformatted), & operator(==) implicit none contains !> Collect all exported unit tests subroutine collect_string_derivedtype_io(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("listdirected_io", test_listdirected_io), & new_unittest("formatted_io", test_formatted_io), & new_unittest("unformatted_io", test_unformatted_io) & ] end subroutine collect_string_derivedtype_io subroutine test_listdirected_io(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string integer :: io, stat string = "Important saved value" open(newunit=io, form="formatted", status="scratch") write(io, *) string write(io, *) ! Pad with a newline or we might run into EOF while reading string = "" rewind(io) read(io, *, iostat=stat) string close(io) call check(error, stat == 0) if (allocated(error)) return call check(error, len(string) == 21) if (allocated(error)) return call check(error, string == "Important saved value") end subroutine test_listdirected_io subroutine test_formatted_io(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string integer :: io, stat string = "Important saved value" open(newunit=io, form="formatted", status="scratch") write(io, '(dt)') string write(io, '(a)') ! Pad with a newline or we might run into EOF while reading string = "" rewind(io) read(io, *, iostat=stat) string close(io) call check(error, stat == 0) if (allocated(error)) return call check(error, len(string) == 21) if (allocated(error)) return call check(error, string == "Important saved value") end subroutine test_formatted_io subroutine test_unformatted_io(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string integer :: io string = "Important saved value" open(newunit=io, form="unformatted", status="scratch") write(io) string string = "" rewind(io) read(io) string close(io) call check(error, len(string) == 21) if (allocated(error)) return call check(error, string == "Important saved value") end subroutine test_unformatted_io end module test_string_derivedtype_io program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_string_derivedtype_io, only : collect_string_derivedtype_io implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("string-derivedtype-io", collect_string_derivedtype_io) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/string/test_string_assignment.fypp0000664000175000017500000000750615135654166026160 0ustar alastairalastair#:include "common.fypp" ! SPDX-Identifier: MIT module test_string_assignment use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_kinds, only : int8, int16, int32, int64, lk, c_bool use stdlib_string_type, only : string_type, assignment(=), operator(==), len implicit none contains !> Collect all exported unit tests subroutine collect_string_assignment(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("assignment", test_assignment), & new_unittest("constructor", test_constructor) & ] end subroutine collect_string_assignment subroutine test_assignment(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string call check(error, len(string) == 0) if (allocated(error)) return string = "Sequence" call check(error, len(string) == 8) end subroutine test_assignment subroutine test_constructor(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=128) :: flc write(flc, '(g0)') -1026191 call check(error, string_type(-1026191) == trim(flc)) if (allocated(error)) return write(flc, '(g0)') 124787 call check(error, string_type(124787) == trim(flc)) if (allocated(error)) return write(flc, '(g0)') -2_int8 call check(error, string_type(-2_int8) == trim(flc)) if (allocated(error)) return write(flc, '(g0)') 5_int8 call check(error, string_type(5_int8) == trim(flc)) if (allocated(error)) return write(flc, '(g0)') -72_int16 call check(error, string_type(-72_int16) == trim(flc)) if (allocated(error)) return write(flc, '(g0)') -8924889_int32 call check(error, string_type(-8924889_int32) == trim(flc)) if (allocated(error)) return write(flc, '(g0)') 2378405_int32 call check(error, string_type(2378405_int32) == trim(flc)) if (allocated(error)) return write(flc, '(g0)') 921092378411_int64 call check(error, string_type(921092378411_int64) == trim(flc)) if (allocated(error)) return write(flc, '(g0)') -1272835761_int64 call check(error, string_type(-1272835761_int64) == trim(flc)) if (allocated(error)) return write(flc, '(g0)') .true. call check(error, string_type(.true.) == trim(flc)) if (allocated(error)) return write(flc, '(g0)') .false. call check(error, string_type(.false.) == trim(flc)) if (allocated(error)) return #:if WITH_CBOOL write(flc, '(g0)') .false._c_bool call check(error, string_type(.false._c_bool) == trim(flc)) if (allocated(error)) return #:endif write(flc, '(g0)') .true._lk call check(error, string_type(.true._lk) == trim(flc)) end subroutine test_constructor end module test_string_assignment program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_string_assignment, only : collect_string_assignment implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("string-assignment", collect_string_assignment) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/string/test_string_functions.f900000664000175000017500000010273415135654166025437 0ustar alastairalastair! SPDX-Identifier: MIT module test_string_functions use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_string_type, only : string_type, assignment(=), operator(==), & to_lower, to_upper, to_title, to_sentence, reverse use stdlib_strings, only: slice, find, replace_all, padl, padr, count, zfill use stdlib_optval, only: optval use stdlib_strings, only : to_string implicit none contains !> Collect all exported unit tests subroutine collect_string_functions(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("to_lower_string", test_to_lower_string), & new_unittest("to_upper_string", test_to_upper_string), & new_unittest("to_title_string", test_to_title_string), & new_unittest("to_sentence_string", test_to_sentence_string), & new_unittest("reverse_string", test_reverse_string), & new_unittest("slice_string", test_slice_string), & new_unittest("slice_gen", test_slice_gen), & new_unittest("find", test_find), & new_unittest("replace_all", test_replace_all), & new_unittest("padl", test_padl), & new_unittest("padr", test_padr), & new_unittest("count", test_count), & new_unittest("zfill", test_zfill) & ] end subroutine collect_string_functions subroutine test_to_lower_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string, compare_string test_string = "To_LoWEr !$%-az09AZ" compare_string = "to_lower !$%-az09az" call check(error, to_lower(test_string) == compare_string) end subroutine test_to_lower_string subroutine test_to_upper_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string, compare_string test_string = "To_UpPeR !$%-az09AZ" compare_string = "TO_UPPER !$%-AZ09AZ" call check(error, to_upper(test_string) == compare_string) end subroutine test_to_upper_string subroutine test_to_title_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string, compare_string test_string = "tO_%t!TL3 7h1S p#ra$e" compare_string = "To_%T!Tl3 7h1s P#Ra$E" call check(error, to_title(test_string) == compare_string) end subroutine test_to_title_string subroutine test_to_sentence_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string, compare_string test_string = "_#To seNtEncE !$%-az09AZ" compare_string = "_#To sentence !$%-az09az" call check(error, to_sentence(test_string) == compare_string) end subroutine test_to_sentence_string subroutine test_reverse_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string, compare_string test_string = "_To ReVerSe !$%-az09AZ " compare_string = " ZA90za-%$! eSreVeR oT_" call check(error, reverse(test_string) == compare_string) end subroutine test_reverse_string subroutine test_slice_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string test_string = "abcdefghijklmnopqrstuvwxyz" ! Only one argument is given ! Valid call check(error, slice(test_string, first=10) == "jklmnopqrstuvwxyz", & "slice, Valid arguments: first=10") ! last=+inf if (allocated(error)) return call check(error, slice(test_string, last=10) == "abcdefghij", & "slice, Valid arguments: last=10") ! first=-inf if (allocated(error)) return call check(error, slice(test_string, stride=3) == "adgjmpsvy", & "slice, Valid arguments: stride=3") ! first=-inf, last=+inf if (allocated(error)) return call check(error, slice(test_string, stride=-3) == "zwtqnkheb", & "slice, Valid arguments: stride=-3") ! first=+inf, last=-inf if (allocated(error)) return ! Invalid call check(error, slice(test_string, first=27) == "", & "slice, Invalid arguments: first=27") ! last=+inf if (allocated(error)) return call check(error, slice(test_string, first=-10) == "abcdefghijklmnopqrstuvwxyz", & "slice, Invalid arguments: first=-10") ! last=+inf if (allocated(error)) return call check(error, slice(test_string, last=-2) == "", & "slice, Invalid arguments: last=-2") ! first=-inf if (allocated(error)) return call check(error, slice(test_string, last=30) == "abcdefghijklmnopqrstuvwxyz", & "slice, Invalid arguments: last=30") ! first=-inf if (allocated(error)) return call check(error, slice(test_string, stride=0) == "abcdefghijklmnopqrstuvwxyz", & "slice, Invalid arguments: stride=0") ! stride=1 if (allocated(error)) return ! Only two arguments are given ! Valid call check(error, slice(test_string, first=10, last=20) == "jklmnopqrst", & "slice, Valid arguments: first=10, last=20") if (allocated(error)) return call check(error, slice(test_string, first=7, last=2) == "gfedcb", & "slice, Valid arguments: first=7, last=2") ! stride=-1 if (allocated(error)) return call check(error, slice(test_string, first=10, stride=-2) == "jhfdb", & "slice, Valid arguments: first=10, stride=-2") ! last=-inf if (allocated(error)) return call check(error, slice(test_string, last=21, stride=-2) == "zxv", & "slice, Valid arguments: last=21, stride=-2") ! first=+inf if (allocated(error)) return ! Atleast one argument is invalid call check(error, slice(test_string, first=30, last=-3) == "zyxwvutsrqponmlkjihgfedcba", & "slice, Invalid arguments: first=30, last=-3") if (allocated(error)) return call check(error, slice(test_string, first=1, last=-20) == "a", & "slice, Invalid arguments: first=1, last=-20") if (allocated(error)) return call check(error, slice(test_string, first=7, last=-10) == "gfedcba", & "slice, Invalid arguments: first=7, last=-10") if (allocated(error)) return call check(error, slice(test_string, first=500, last=22) == "zyxwv", & "slice, Invalid arguments: first=500, last=22") if (allocated(error)) return call check(error, slice(test_string, first=50, last=27) == "", & "slice, Invalid arguments: first=50, last=27") if (allocated(error)) return call check(error, slice(test_string, first=-20, last=0) == "", & "slice, Invalid arguments: first=-20, last=0") if (allocated(error)) return call check(error, slice(test_string, last=-3, stride=-2) == "zxvtrpnljhfdb", & "slice, Invalid arguments: last=-3, stride=-2") ! first=+inf if (allocated(error)) return call check(error, slice(test_string, last=10, stride=0) == "abcdefghij", & "slice, Invalid arguments: last=10, stride=0") ! stride=1 if (allocated(error)) return call check(error, slice(test_string, first=-2, stride=-2) == "", & "slice, Invalid arguments: first=-2, stride=-2") ! last=-inf if (allocated(error)) return call check(error, slice(test_string, first=27, stride=2) == "", & "slice, Invalid arguments: first=27, stride=2") ! last=+inf if (allocated(error)) return call check(error, slice(test_string, last=27, stride=-1) == "", & "slice, Invalid arguments: last=27, stride=-1") ! first=+inf if (allocated(error)) return ! All three arguments are given ! Valid call check(error, slice(test_string, first=2, last=16, stride=3) == "behkn", & "slice, Valid arguments: first=2, last=16, stride=3") if (allocated(error)) return call check(error, slice(test_string, first=16, last=2, stride=-3) == "pmjgd", & "slice, Valid arguments: first=16, last=2, stride=-3") if (allocated(error)) return call check(error, slice(test_string, first=7, last=7, stride=-4) == "g", & "slice, Valid arguments: first=7, last=7, stride=-4") if (allocated(error)) return call check(error, slice(test_string, first=7, last=7, stride=3) == "g", & "slice, Valid arguments: first=7, last=7, stride=3") if (allocated(error)) return call check(error, slice(test_string, first=2, last=6, stride=-1) == "", & "slice, Valid arguments: first=2, last=6, stride=-1") if (allocated(error)) return call check(error, slice(test_string, first=20, last=10, stride=2) == "", & "slice, Valid arguments: first=20, last=10, stride=2") if (allocated(error)) return ! Atleast one argument is invalid call check(error, slice(test_string, first=20, last=30, stride=2) == "tvxz", & "slice, Invalid arguments: first=20, last=30, stride=2") if (allocated(error)) return call check(error, slice(test_string, first=-20, last=30, stride=2) == "acegikmoqsuwy", & "slice, Invalid arguments: first=-20, last=30, stride=2") if (allocated(error)) return call check(error, slice(test_string, first=26, last=30, stride=1) == "z", & "slice, Invalid arguments: first=26, last=30, stride=1") if (allocated(error)) return call check(error, slice(test_string, first=1, last=-20, stride=-1) == "a", & "slice, Invalid arguments: first=1, last=-20, stride=-1") if (allocated(error)) return call check(error, slice(test_string, first=26, last=20, stride=1) == "", & "slice, Invalid arguments: first=26, last=20, stride=1") if (allocated(error)) return call check(error, slice(test_string, first=1, last=20, stride=-1) == "", & "slice, Invalid arguments: first=1, last=20, stride=-1") if (allocated(error)) return test_string = "" ! Empty string input call check(error, slice(test_string, first=-2, last=6) == "", & "slice, Empty string: first=-2, last=6") if (allocated(error)) return call check(error, slice(test_string, first=6, last=-2) == "", & "slice, Empty string: first=6, last=-2") if (allocated(error)) return call check(error, slice(test_string, first=-10) == "", & "slice, Empty string: first=-10") ! last=+inf if (allocated(error)) return call check(error, slice(test_string, last=10) == "", & "slice, Empty string: last=10") ! first=-inf if (allocated(error)) return call check(error, slice(test_string) == "", & "slice, Empty string: no arguments provided") end subroutine test_slice_string subroutine test_find(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string_1, test_string_2, test_pattern_1, test_pattern_2 test_string_1 = "qwqwqwqwqwqwqw" test_string_2 = "abccbabccbabc" test_pattern_1 = "qwq" test_pattern_2 = "abccbabc" call check(error, all(find([test_string_1, test_string_2], test_pattern_1, 4) == [7, 0]), & & 'find: [test_string_1, test_string_2], test_pattern_1, 4') if (allocated(error)) return call check(error, all(find(test_string_1, [test_pattern_1, test_pattern_2], 3, .false.) == [9, 0]), & & 'find: test_string_1, [test_pattern_1, test_pattern_2], 3, .false.') if (allocated(error)) return call check(error, find(test_string_1, test_pattern_1, 7) == 0, & & 'find: test_string_1, test_pattern_1, 7') if (allocated(error)) return call check(error, all(find([test_string_1, test_string_2, test_string_2], [test_pattern_1, & & test_pattern_2, test_pattern_2], [7, 2, 2], [.true., .false., .true.]) == [0, 0, 6]), & & 'find: [test_string_1, test_string_2, test_string_2], [test_pattern_1, & & test_pattern_2, test_pattern_2], [7, 2, 2], [.true., .false., .true.]') if (allocated(error)) return call check(error, find("qwqwqwqwqwqwqw", test_pattern_1) == 1, & & 'find: "qwqwqwqwqwqwqw", test_pattern_1') if (allocated(error)) return call check(error, all(find(test_string_1, ["qwq", "wqw"], 2) == [3, 4]), & & 'find: test_string_1, ["qwq", "wqw"], 2') if (allocated(error)) return call check(error, find("qwqwqwqwqwqwqw", "qwq", 2, .false.) == 5, & & 'find: "qwqwqwqwqwqwqw", "qwq", 2, .false.') if (allocated(error)) return call check(error, find("", "") == 0, & & 'find: "", ""') if (allocated(error)) return call check(error, find("", test_pattern_1) == 0, & & 'find: "", test_pattern_1') if (allocated(error)) return call check(error, find(test_string_1, "") == 0, & & 'find: test_string_1, ""') end subroutine test_find subroutine test_slice_gen(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), parameter :: test = & & "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" integer :: i, j, k integer, parameter :: offset = 3 do i = 1 - offset, len(test) + offset call check_slicer(error, test, first=i) if (allocated(error)) return end do do i = 1 - offset, len(test) + offset call check_slicer(error, test, last=i) if (allocated(error)) return end do do i = -len(test) - offset, len(test) + offset call check_slicer(error, test, stride=i) if (allocated(error)) return end do do i = 1 - offset, len(test) + offset do j = 1 - offset, len(test) + offset call check_slicer(error, test, first=i, last=j) if (allocated(error)) return end do end do do i = 1 - offset, len(test) + offset do j = -len(test) - offset, len(test) + offset call check_slicer(error, test, first=i, stride=j) if (allocated(error)) return end do end do do i = 1 - offset, len(test) + offset do j = -len(test) - offset, len(test) + offset call check_slicer(error, test, last=i, stride=j) if (allocated(error)) return end do end do do i = 1 - offset, len(test) + offset do j = 1 - offset, len(test) + offset do k = -len(test) - offset, len(test) + offset call check_slicer(error, test, first=i, last=j, stride=k) if (allocated(error)) return end do end do end do end subroutine test_slice_gen subroutine check_slicer(error, string, first, last, stride) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: string integer, intent(in), optional :: first integer, intent(in), optional :: last integer, intent(in), optional :: stride character(len=:), allocatable :: actual, expected, message logical :: stat actual = slice(string, first, last, stride) expected = reference_slice(string, first, last, stride) stat = actual == expected if (.not.stat) then message = "For input '"//string//"'"//new_line('a') if (present(first)) then message = message // "first: "//to_string(first)//new_line('a') end if if (present(last)) then message = message // "last: "//to_string(last)//new_line('a') end if if (present(stride)) then message = message // "stride: "//to_string(stride)//new_line('a') end if message = message // "Expected: '"//expected//"' but got '"//actual//"'" end if call check(error, stat, message) end subroutine check_slicer pure function reference_slice(string, first, last, stride) result(sliced_string) character(len=*), intent(in) :: string integer, intent(in), optional :: first integer, intent(in), optional :: last integer, intent(in), optional :: stride character(len=:), allocatable :: sliced_string character(len=1), allocatable :: carray(:) integer :: first_, last_, stride_ stride_ = 1 if (present(stride)) then stride_ = merge(stride_, stride, stride == 0) else if (present(first) .and. present(last)) then if (last < first) stride_ = -1 end if end if if (stride_ < 0) then last_ = min(max(optval(last, 1), 1), len(string)+1) first_ = min(max(optval(first, len(string)), 0), len(string)) else first_ = min(max(optval(first, 1), 1), len(string)+1) last_ = min(max(optval(last, len(string)), 0), len(string)) end if carray = string_to_carray(string) carray = carray(first_:last_:stride_) sliced_string = carray_to_string(carray) end function reference_slice pure function string_to_carray(string) result(carray) character(len=*), intent(in) :: string character(len=1) :: carray(len(string)) carray = transfer(string, carray) end function string_to_carray pure function carray_to_string(carray) result(string) character(len=1), intent(in) :: carray(:) character(len=size(carray)) :: string string = transfer(carray, string) end function carray_to_string subroutine test_replace_all(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string_1, test_pattern_1, test_replacement_1 type(string_type) :: test_string_2, test_pattern_2, test_replacement_2 test_string_1 = "mutate DNA sequence: GTTATCGTATGCCGTAATTAT" test_pattern_1 = "TAT" test_replacement_1 = "ATA" test_string_2 = "mutate DNA sequence: AGAGAGCCTAGAGAGAG" test_pattern_2 = "AGA" test_replacement_2 = "aga" ! all 3 as string_type call check(error, replace_all(test_string_1, test_pattern_1, test_replacement_1) == & & "mutate DNA sequence: GTATACGATAGCCGTAATATA", & & "replace_all: all 3 string_type, test case 1") if (allocated(error)) return call check(error, replace_all(test_string_2, test_pattern_2, test_replacement_2) == & & "mutate DNA sequence: agaGAGCCTagaGagaG", & & "replace_all: all 3 string_type, test case 2") if (allocated(error)) return call check(error, replace_all(test_string_2, test_pattern_2, test_replacement_1) == & & "mutate DNA sequence: ATAGAGCCTATAGATAG", & & "replace_all: all 3 string_type, test case 3") if (allocated(error)) return ! 2 as string_type and 1 as character scalar call check(error, replace_all(test_string_1, "tat", test_replacement_1) == & & "muATAe DNA sequence: GTTATCGTATGCCGTAATTAT", & & "replace_all: 2 string_type & 1 character scalar, test case 1") if (allocated(error)) return call check(error, replace_all(test_string_2, test_pattern_2, "GC") == & & "mutate DNA sequence: GCGAGCCTGCGGCG", & & "replace_all: 2 string_type & 1 character scalar, test case 2") if (allocated(error)) return call check(error, replace_all("mutate DNA sequence: AGAGAGCCTAGAGAGAG", test_pattern_2, & & test_replacement_2) == "mutate DNA sequence: agaGAGCCTagaGagaG", & & "replace_all: 2 string_type & 1 character scalar, test case 3") if (allocated(error)) return ! 1 as string_type and 2 as character scalar call check(error, replace_all(test_string_1, "TAT", "ATA") == & & "mutate DNA sequence: GTATACGATAGCCGTAATATA", & & "replace_all: 1 string_type & 2 character scalar, test case 1") if (allocated(error)) return call check(error, replace_all("mutate DNA sequence: AGAGAGCCTAGAGAGAG", test_pattern_2, "GC") == & & "mutate DNA sequence: GCGAGCCTGCGGCG", & & "replace_all: 1 string_type & 2 character scalar, test case 2") if (allocated(error)) return call check(error, replace_all("mutate DNA sequence: GTTATCGTATGCCGTAATTAT", "TA", & & test_replacement_2) == "mutate DNA sequence: GTagaTCGagaTGCCGagaATagaT", & & "replace_all: 1 string_type & 2 character scalar, test case 3") if (allocated(error)) return call check(error, replace_all("mutate DNA sequence: GTTATCGTATGCCGTAATTAT", & & test_pattern_1, "") == "mutate DNA sequence: GTCGGCCGTAAT", & & "replace_all: 1 string_type & 2 character scalar, test case 4") if (allocated(error)) return call check(error, replace_all(test_string_1, "", "anything here") == test_string_1, & & "replace_all: 1 string_type & 2 character scalar, test case 5") if (allocated(error)) return call check(error, replace_all("", test_pattern_2, "anything here") == "", & & "replace_all: 1 string_type & 2 character scalar, test case 6") if (allocated(error)) return ! all 3 as character scalar call check(error, replace_all("mutate DNA sequence: GTTATCGTATGCCGTAATTAT", & & "GT", "gct") == "mutate DNA sequence: gctTATCgctATGCCgctAATTAT", & & "replace_all: all 3 character scalar, test case 1") if (allocated(error)) return call check(error, replace_all("", "anything here", "anything here") == "", & & "replace_all: all 3 character scalar, test case 2") end subroutine test_replace_all subroutine test_padl(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string character(len=:), allocatable :: test_char test_string = "left pad this string" test_char = " left pad this string " ! output_length > len(string) call check(error, padl(test_string, 25, "#") == "#####left pad this string", & & 'padl: output_length > len(string), test_case 1') if (allocated(error)) return call check(error, padl(test_string, 22, "$") == "$$left pad this string", & & 'padl: output_length > len(string), test_case 2') if (allocated(error)) return call check(error, padl(test_string, 23) == " left pad this string", & & 'padl: output_length > len(string), test_case 3') if (allocated(error)) return call check(error, padl(test_char, 26) == " left pad this string ", & & 'padl: output_length > len(string), test_case 4') if (allocated(error)) return call check(error, padl(test_char, 26, "&") == "&& left pad this string ", & & 'padl: output_length > len(string), test_case 5') if (allocated(error)) return call check(error, padl("", 10, "!") == "!!!!!!!!!!", & & 'padl: output_length > len(string), test_case 6') if (allocated(error)) return ! output_length <= len(string) call check(error, padl(test_string, 18, "#") == "left pad this string", & & 'padl: output_length <= len(string), test_case 1') if (allocated(error)) return call check(error, padl(test_string, -4, "@") == "left pad this string", & & 'padl: output_length <= len(string), test_case 2') if (allocated(error)) return call check(error, padl(test_char, 20, "0") == " left pad this string ", & & 'padl: output_length <= len(string), test_case 3') if (allocated(error)) return call check(error, padl(test_char, 17) == " left pad this string ", & & 'padl: output_length <= len(string), test_case 4') if (allocated(error)) return call check(error, padl("", 0, "!") == "", & & 'padl: output_length <= len(string), test_case 5') if (allocated(error)) return call check(error, padl("", -12, "!") == "", & & 'padl: output_length <= len(string), test_case 6') end subroutine test_padl subroutine test_padr(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string character(len=:), allocatable :: test_char test_string = "right pad this string" test_char = " right pad this string " ! output_length > len(string) call check(error, padr(test_string, 25, "#") == "right pad this string####", & & 'padr: output_length > len(string), test_case 1') if (allocated(error)) return call check(error, padr(test_string, 22, "$") == "right pad this string$", & & 'padr: output_length > len(string), test_case 2') if (allocated(error)) return call check(error, padr(test_string, 24) == "right pad this string ", & & 'padr: output_length > len(string), test_case 3') if (allocated(error)) return call check(error, padr(test_char, 27) == " right pad this string ", & & 'padr: output_length > len(string), test_case 4') if (allocated(error)) return call check(error, padr(test_char, 27, "&") == " right pad this string &&", & & 'padr: output_length > len(string), test_case 5') if (allocated(error)) return call check(error, padr("", 10, "!") == "!!!!!!!!!!", & & 'padr: output_length > len(string), test_case 6') if (allocated(error)) return ! output_length <= len(string) call check(error, padr(test_string, 18, "#") == "right pad this string", & & 'padr: output_length <= len(string), test_case 1') if (allocated(error)) return call check(error, padr(test_string, -4, "@") == "right pad this string", & & 'padr: output_length <= len(string), test_case 2') if (allocated(error)) return call check(error, padr(test_char, 20, "0") == " right pad this string ", & & 'padr: output_length <= len(string), test_case 3') if (allocated(error)) return call check(error, padr(test_char, 17) == " right pad this string ", & & 'padr: output_length <= len(string), test_case 4') if (allocated(error)) return call check(error, padr("", 0, "!") == "", & & 'padr: output_length <= len(string), test_case 5') if (allocated(error)) return call check(error, padr("", -12, "!") == "", & & 'padr: output_length <= len(string), test_case 6') end subroutine test_padr subroutine test_count(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string_1, test_string_2, test_pattern_1, test_pattern_2 test_string_1 = "DNA sequence: AGAGAGAGTCCTGTCGAGA" test_string_2 = "DNA sequence: GTCCTGTCCTGTCAGA" test_pattern_1 = "AGA" test_pattern_2 = "GTCCTGTC" ! all 2 as string_type call check(error, all(count([test_string_1, test_string_2], test_pattern_1) == [4, 1]), & & 'count: all 2 as string_type, test case 1') if (allocated(error)) return call check(error, all(count(test_string_1, [test_pattern_1, test_pattern_2], .false.) == [3, 1]), & & 'count: all 2 as string_type, test case 2') if (allocated(error)) return call check(error, count(test_string_2, test_pattern_1, .false.) == 1, & & 'count: all 2 as string_type, test case 3') if (allocated(error)) return call check(error, all(count([test_string_2, test_string_2, test_string_1], & & [test_pattern_2, test_pattern_2, test_pattern_1], [.true., .false., .false.]) == & & [2, 1, 3]), 'count: all 2 as string_type, test case 4') if (allocated(error)) return call check(error, all(count([[test_string_1, test_string_2], [test_string_1, test_string_2]], & & [[test_pattern_1, test_pattern_2], [test_pattern_2, test_pattern_1]], .true.) == & & [[4, 2], [1, 1]]), 'count: all 2 as string_type, test case 5') if (allocated(error)) return ! 1 string_type and 1 character scalar call check(error, all(count(test_string_1, ["AGA", "GTC"], [.true., .false.]) == [4, 2]), & & 'count: 1 string_type and 1 character scalar, test case 1') if (allocated(error)) return call check(error, all(count([test_string_1, test_string_2], ["CTC", "GTC"], [.true., .false.]) == & & [0, 3]), 'count: 1 string_type and 1 character scalar, test case 2') if (allocated(error)) return call check(error, all(count(["AGAGAGAGTCCTGTCGAGA", "AGAGAGAGTCCTGTCGAGA"], & & test_pattern_1, [.false., .true.]) == [3, 4]), & & 'count: 1 string_type and 1 character scalar, test case 3') if (allocated(error)) return call check(error, count(test_string_1, "GAG") == 4, & & 'count: 1 string_type and 1 character scalar, test case 4') if (allocated(error)) return call check(error, count("DNA sequence: GTCCTGTCCTGTCAGA", test_pattern_2, .false.) == 1, & & 'count: 1 string_type and 1 character scalar, test case 5') if (allocated(error)) return ! all 2 character scalar call check(error, all(count("", ["mango", "trees"], .true.) == [0, 0]), & & 'count: all 2 character scalar, test case 1') if (allocated(error)) return call check(error, count("", "", .true.) == 0, 'count: all 2 character scalar, test case 2') if (allocated(error)) return call check(error, all(count(["mango", "trees"], "", .true.) == [0, 0]), & & 'count: all 2 character scalar, test case 3') end subroutine test_count subroutine test_zfill(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: test_string character(len=:), allocatable :: test_char test_string = "left pad this string" test_char = " left pad this string " ! output_length > len(string) call check(error, zfill(test_string, 25) == "00000left pad this string", & & 'zfill: output_length > len(string), test_case 1') if (allocated(error)) return call check(error, zfill(test_string, 22) == "00left pad this string", & & 'zfill: output_length > len(string), test_case 2') if (allocated(error)) return call check(error, zfill(test_string, 23) == "000left pad this string", & & 'zfill: output_length > len(string), test_case 3') if (allocated(error)) return call check(error, zfill(test_char, 26) == "00 left pad this string ", & & 'zfill: output_length > len(string), test_case 4') if (allocated(error)) return call check(error, zfill("", 10) == "0000000000", & & 'zfill: output_length > len(string), test_case 5') if (allocated(error)) return ! output_length <= len(string) call check(error, zfill(test_string, 18) == "left pad this string", & & 'zfill: output_length <= len(string), test_case 1') if (allocated(error)) return call check(error, zfill(test_string, -4) == "left pad this string", & & 'zfill: output_length <= len(string), test_case 2') if (allocated(error)) return call check(error, zfill(test_char, 20) == " left pad this string ", & & 'zfill: output_length <= len(string), test_case 3') if (allocated(error)) return call check(error, zfill(test_char, 17) == " left pad this string ", & & 'zfill: output_length <= len(string), test_case 4') if (allocated(error)) return call check(error, zfill("", 0) == "", & & 'zfill: output_length <= len(string), test_case 5') if (allocated(error)) return call check(error, zfill("", -12) == "", & & 'zfill: output_length <= len(string), test_case 6') end subroutine test_zfill end module test_string_functions program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_string_functions, only : collect_string_functions implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("string-functions", collect_string_functions) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/string/CMakeLists.txt0000664000175000017500000000070615135654166023216 0ustar alastairalastair#### Pre-process: .fpp -> .f90 via Fypp # Create a list of the files to be preprocessed set(fppFiles test_string_assignment.fypp test_string_to_number.fypp ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) ADDTEST(string_assignment) ADDTEST(string_operator) ADDTEST(string_intrinsic) ADDTEST(string_match) ADDTEST(string_derivedtype_io) ADDTEST(string_functions) ADDTEST(string_strip_chomp) ADDTEST(string_to_number) ADDTEST(string_to_string) fortran-lang-stdlib-0ede301/test/string/test_string_strip_chomp.f900000664000175000017500000002264615135654166025761 0ustar alastairalastair! SPDX-Identifier: MIT module test_strip_chomp use stdlib_ascii, only : TAB, VT, NUL, LF, CR, FF use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_strings, only : strip, chomp use stdlib_string_type, only : string_type, operator(==), operator(//) implicit none contains !> Collect all exported unit tests subroutine collect_strip_chomp(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("strip_char", test_strip_char), & new_unittest("strip_string", test_strip_string), & new_unittest("chomp_char", test_chomp_char), & new_unittest("chomp_string", test_chomp_string), & new_unittest("chomp_set_char", test_chomp_set_char), & new_unittest("chomp_set_string", test_chomp_set_string), & new_unittest("chomp_substring_char", test_chomp_substring_char), & new_unittest("chomp_substring_string", test_chomp_substring_string) & ] end subroutine collect_strip_chomp subroutine test_strip_char(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, strip(" hello ") == "hello") if (allocated(error)) return call check(error, strip(TAB//"goodbye"//CR//LF) == "goodbye") if (allocated(error)) return call check(error, strip(NUL//TAB//LF//VT//FF//CR) == NUL) if (allocated(error)) return call check(error, strip(" "//TAB//LF//VT//FF//CR) == "") if (allocated(error)) return call check(error, strip(" ! ")//"!" == "!!") if (allocated(error)) return call check(error, strip("Hello") == "Hello") end subroutine test_strip_char subroutine test_strip_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, strip(string_type(" hello ")) == "hello") if (allocated(error)) return call check(error, strip(string_type(TAB//"goodbye"//CR//LF)) == "goodbye") if (allocated(error)) return call check(error, strip(string_type(NUL//TAB//LF//VT//FF//CR)) == NUL) if (allocated(error)) return call check(error, strip(string_type(" "//TAB//LF//VT//FF//CR)) == "") if (allocated(error)) return call check(error, strip(string_type(" ! "))//"!" == "!!") if (allocated(error)) return call check(error, strip(string_type("Hello")) == "Hello") end subroutine test_strip_string subroutine test_chomp_char(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, chomp("hello") == "hello") if (allocated(error)) return call check(error, chomp("hello"//LF) == "hello", "1") if (allocated(error)) return call check(error, chomp("hello"//CR//LF) == "hello", "2") if (allocated(error)) return call check(error, chomp("hello"//LF//CR) == "hello", "3") if (allocated(error)) return call check(error, chomp("hello"//CR) == "hello", "4") if (allocated(error)) return call check(error, chomp("hello "//LF//" there") == "hello "//LF//" there") if (allocated(error)) return call check(error, chomp("hello"//CR//LF//CR//LF) == "hello") if (allocated(error)) return call check(error, chomp("hello"//CR//LF//CR//CR//LF) == "hello") if (allocated(error)) return call check(error, chomp(NUL//TAB//LF//VT//FF//CR) == NUL) if (allocated(error)) return call check(error, chomp(" "//TAB//LF//VT//FF//CR) == "") if (allocated(error)) return call check(error, chomp(" ! ")//"!" == " !!") end subroutine test_chomp_char subroutine test_chomp_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, chomp(string_type("hello")) == "hello") if (allocated(error)) return call check(error, chomp(string_type("hello"//LF)) == "hello") if (allocated(error)) return call check(error, chomp(string_type("hello"//CR//LF)) == "hello") if (allocated(error)) return call check(error, chomp(string_type("hello"//LF//CR)) == "hello") if (allocated(error)) return call check(error, chomp(string_type("hello"//CR)) == "hello") if (allocated(error)) return call check(error, chomp(string_type("hello "//LF//" there")) == "hello "//LF//" there") if (allocated(error)) return call check(error, chomp(string_type("hello"//CR//LF//CR//LF)) == "hello") if (allocated(error)) return call check(error, chomp(string_type("hello"//CR//LF//CR//CR//LF)) == "hello") if (allocated(error)) return call check(error, chomp(string_type(NUL//TAB//LF//VT//FF//CR)) == NUL) if (allocated(error)) return call check(error, chomp(string_type(" "//TAB//LF//VT//FF//CR)) == "") if (allocated(error)) return call check(error, chomp(string_type(" ! "))//"!" == " !!") end subroutine test_chomp_string subroutine test_chomp_set_char(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, chomp("hello", ["l", "o"]) == "he") if (allocated(error)) return call check(error, chomp("hello", set=["l", "o"]) == "he") end subroutine test_chomp_set_char subroutine test_chomp_set_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, chomp(string_type("hello"), ["l", "o"]) == "he") if (allocated(error)) return call check(error, chomp(string_type("hello"), set=["l", "o"]) == "he") if (allocated(error)) return call check(error, chomp("hellooooo", ["o", "o"]) == "hell") if (allocated(error)) return call check(error, chomp("hellooooo", set=["o", "o"]) == "hell") end subroutine test_chomp_set_string subroutine test_chomp_substring_char(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, chomp("hello", "") == "hello") if (allocated(error)) return call check(error, chomp("hello", substring="") == "hello") if (allocated(error)) return call check(error, chomp("hello", "lo") == "hel") if (allocated(error)) return call check(error, chomp("hello", substring="lo") == "hel") if (allocated(error)) return call check(error, chomp("hellooooo", "oo") == "hello") if (allocated(error)) return call check(error, chomp("hellooooo", substring="oo") == "hello") if (allocated(error)) return call check(error, chomp("helhel", substring="hel") == "") end subroutine test_chomp_substring_char subroutine test_chomp_substring_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, chomp(string_type("hello"), "") == "hello") if (allocated(error)) return call check(error, chomp(string_type("hello"), substring="") == "hello") if (allocated(error)) return call check(error, chomp(string_type("hello"), "lo") == "hel") if (allocated(error)) return call check(error, chomp(string_type("hello"), substring="lo") == "hel") if (allocated(error)) return call check(error, chomp("hello", string_type("lo")) == "hel") if (allocated(error)) return call check(error, chomp("hello", substring=string_type("lo")) == "hel") if (allocated(error)) return call check(error, chomp(string_type("hello"), string_type("lo")) == "hel") if (allocated(error)) return call check(error, chomp(string_type("hello"), substring=string_type("lo")) == "hel") if (allocated(error)) return call check(error, chomp(string_type("hellooooo"), "oo") == "hello") if (allocated(error)) return call check(error, chomp(string_type("hellooooo"), substring="oo") == "hello") if (allocated(error)) return call check(error, chomp("hellooooo", string_type("oo")) == "hello") if (allocated(error)) return call check(error, chomp("hellooooo", substring=string_type("oo")) == "hello") if (allocated(error)) return call check(error, chomp(string_type("hellooooo"), string_type("oo")) == "hello") if (allocated(error)) return call check(error, chomp(string_type("hellooooo"), substring=string_type("oo")) == "hello") end subroutine test_chomp_substring_string end module test_strip_chomp program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_strip_chomp, only : collect_strip_chomp implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("strip-chomp", collect_strip_chomp) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/string/test_string_operator.f900000664000175000017500000001210515135654166025252 0ustar alastairalastair! SPDX-Identifer: MIT module test_string_operator use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_string_type, only : string_type, assignment(=), len, & operator(>), operator(<), operator(>=), operator(<=), & operator(/=), operator(==), operator(//) implicit none contains !> Collect all exported unit tests subroutine collect_string_operator(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("gt", test_gt), & new_unittest("lt", test_lt), & new_unittest("ge", test_ge), & new_unittest("le", test_le), & new_unittest("eq", test_eq), & new_unittest("ne", test_ne), & new_unittest("concat", test_concat) & ] end subroutine collect_string_operator subroutine test_gt(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string logical :: res string = "bcd" res = string > "abc" call check(error, res .eqv. .true.) if (allocated(error)) return res = string > "bcd" call check(error, res .eqv. .false.) if (allocated(error)) return res = string > "cde" call check(error, res .eqv. .false.) end subroutine test_gt subroutine test_lt(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string logical :: res string = "bcd" res = string < "abc" call check(error, res .eqv. .false.) if (allocated(error)) return res = string < "bcd" call check(error, res .eqv. .false.) if (allocated(error)) return res = string < "cde" call check(error, res .eqv. .true.) end subroutine test_lt subroutine test_ge(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string logical :: res string = "bcd" res = string >= "abc" call check(error, res .eqv. .true.) if (allocated(error)) return res = string >= "bcd" call check(error, res .eqv. .true.) if (allocated(error)) return res = string >= "cde" call check(error, res .eqv. .false.) end subroutine test_ge subroutine test_le(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string logical :: res string = "bcd" res = string <= "abc" call check(error, res .eqv. .false.) if (allocated(error)) return res = string <= "bcd" call check(error, res .eqv. .true.) if (allocated(error)) return res = string <= "cde" call check(error, res .eqv. .true.) end subroutine test_le subroutine test_eq(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string logical :: res string = "bcd" res = string == "abc" call check(error, res .eqv. .false.) if (allocated(error)) return res = string == "bcd" call check(error, res .eqv. .true.) if (allocated(error)) return res = string == "cde" call check(error, res .eqv. .false.) end subroutine test_eq subroutine test_ne(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string logical :: res string = "bcd" res = string /= "abc" call check(error, res .eqv. .true.) if (allocated(error)) return res = string /= "bcd" call check(error, res .eqv. .false.) if (allocated(error)) return res = string /= "cde" call check(error, res .eqv. .true.) end subroutine test_ne subroutine test_concat(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string string = "Hello, " string = string // "World!" call check(error, len(string) == 13) end subroutine test_concat end module test_string_operator program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_string_operator, only : collect_string_operator implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("string-operator", collect_string_operator) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/string/test_string_match.f900000664000175000017500000001315415135654166024520 0ustar alastairalastair! SPDX-Identifier: MIT module test_string_match use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_ascii, only : reverse use stdlib_strings, only : starts_with, ends_with, join use stdlib_string_type, only : string_type implicit none contains !> Collect all exported unit tests subroutine collect_string_match(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("starts_with", test_starts_with), & new_unittest("ends_with", test_ends_with), & new_unittest("join", test_join) & ] end subroutine collect_string_match subroutine check_starts_with(error, string, substring) type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: string character(len=*), intent(in) :: substring logical :: match character(len=:), allocatable :: message match = index(string, substring) == 1 if (match) then message = "Failed to recognize that '"//string//"' starts with '"//substring//"'" else message = "Incorrectly found that '"//string//"' starts with '"//substring//"'" end if call check(error, starts_with(string, substring) .eqv. match, message) if (allocated(error)) return call check(error, starts_with(string_type(string), substring) .eqv. match, message) if (allocated(error)) return call check(error, starts_with(string, string_type(substring)) .eqv. match, message) if (allocated(error)) return call check(error, starts_with(string_type(string), string_type(substring)) .eqv. match, message) end subroutine check_starts_with subroutine test_starts_with(error) type(error_type), allocatable, intent(out) :: error call check_starts_with(error, "pattern", "pat") if (allocated(error)) return call check_starts_with(error, "pat", "pattern") if (allocated(error)) return call check_starts_with(error, "pattern", "ern") if (allocated(error)) return call check_starts_with(error, "ern", "pattern") end subroutine test_starts_with subroutine check_ends_with(error, string, substring) type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: string character(len=*), intent(in) :: substring logical :: match character(len=:), allocatable :: message match = index(reverse(string), reverse(substring)) == 1 if (match) then message = "Failed to recognize that '"//string//"' ends with '"//substring//"'" else message = "Incorrectly found that '"//string//"' ends with '"//substring//"'" end if call check(error, ends_with(string, substring) .eqv. match, message) if (allocated(error)) return call check(error, ends_with(string_type(string), substring) .eqv. match, message) if (allocated(error)) return call check(error, ends_with(string, string_type(substring)) .eqv. match, message) if (allocated(error)) return call check(error, ends_with(string_type(string), string_type(substring)) .eqv. match, message) end subroutine check_ends_with subroutine test_join(error) type(error_type), allocatable, intent(out) :: error character(len=5) :: test_strings(3) test_strings = [character(5) :: "one", "two", "three"] call check_join(error, test_strings, " ", "one two three") if (allocated(error)) return call check_join(error, test_strings, ",", "one,two,three") if (allocated(error)) return call check_join(error, test_strings, "-", "one-two-three") end subroutine test_join subroutine check_join(error, strings, separator, expected) type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: strings(:) character(len=*), intent(in) :: separator character(len=*), intent(in) :: expected character(len=:), allocatable :: joined character(len=:), allocatable :: message joined = join(strings, separator) message = "'join' error: Expected '" // expected // "' but got '" // joined // "'" call check(error, joined == expected, message) end subroutine check_join subroutine test_ends_with(error) type(error_type), allocatable, intent(out) :: error call check_ends_with(error, "pattern", "pat") if (allocated(error)) return call check_ends_with(error, "pat", "pattern") if (allocated(error)) return call check_ends_with(error, "pattern", "ern") if (allocated(error)) return call check_ends_with(error, "ern", "pattern") end subroutine test_ends_with end module test_string_match program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_string_match, only : collect_string_match implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("string-match", collect_string_match) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/string/test_string_intrinsic.f900000664000175000017500000007054715135654166025437 0ustar alastairalastair! SPDX-Identifer: MIT module test_string_intrinsic use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_string_type implicit none abstract interface !> Actual tester working on a string type and a fixed length character !> representing the same character sequence subroutine check1_interface(error, str1, chr1) import :: string_type, error_type type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1 character(len=*), intent(in) :: chr1 end subroutine check1_interface !> Actual tester working on two pairs of string type and fixed length !> character representing the same character sequences subroutine check2_interface(error, str1, chr1, str2, chr2) import :: string_type, error_type type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1, str2 character(len=*), intent(in) :: chr1, chr2 end subroutine check2_interface end interface contains !> Collect all exported unit tests subroutine collect_string_intrinsic(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("lgt", test_lgt), & new_unittest("llt", test_llt), & new_unittest("lge", test_lge), & new_unittest("lle", test_lle), & new_unittest("trim", test_trim), & new_unittest("len", test_len), & new_unittest("len_trim", test_len_trim), & new_unittest("adjustl", test_adjustl), & new_unittest("adjustr", test_adjustr), & new_unittest("scan", test_scan), & new_unittest("verify", test_verify), & new_unittest("repeat", test_repeat), & new_unittest("index", test_index), & new_unittest("char", test_char), & new_unittest("ichar", test_ichar), & new_unittest("iachar", test_iachar), & new_unittest("move", test_move) & ] end subroutine collect_string_intrinsic !> Generate then checker both for the string type created from the character !> sequence by the contructor and the assignment operation subroutine check1(error, chr1, checker) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: chr1 procedure(check1_interface) :: checker call constructor_check1(error, chr1, checker) if (allocated(error)) return call assignment_check1(error, chr1, checker) end subroutine check1 !> Run the actual checker with a string type generated by the custom constructor subroutine constructor_check1(error, chr1, checker) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: chr1 procedure(check1_interface) :: checker call checker(error, string_type(chr1), chr1) end subroutine constructor_check1 !> Run the actual checker with a string type generated by assignment subroutine assignment_check1(error, chr1, checker) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: chr1 type(string_type) :: str1 procedure(check1_interface) :: checker str1 = chr1 call checker(error, str1, chr1) end subroutine assignment_check1 !> Generate then checker both for the string type created from the character !> sequence by the contructor and the assignment operation as well as the !> mixed assigment and constructor setup subroutine check2(error, chr1, chr2, checker) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: chr1, chr2 procedure(check2_interface) :: checker call constructor_check2(error, chr1, chr2, checker) if (allocated(error)) return call assignment_check2(error, chr1, chr2, checker) if (allocated(error)) return call mixed_check2(error, chr1, chr2, checker) end subroutine check2 !> Run the actual checker with both string types generated by the custom constructor subroutine constructor_check2(error, chr1, chr2, checker) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: chr1, chr2 procedure(check2_interface) :: checker call checker(error, string_type(chr1), chr1, string_type(chr2), chr2) end subroutine constructor_check2 !> Run the actual checker with one string type generated by the custom constructor !> and the other by assignment subroutine mixed_check2(error, chr1, chr2, checker) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: chr1, chr2 type(string_type) :: str1, str2 procedure(check2_interface) :: checker str1 = chr1 str2 = chr2 call checker(error, str1, chr1, string_type(chr2), chr2) if (allocated(error)) return call checker(error, string_type(chr1), chr1, str2, chr2) end subroutine mixed_check2 !> Run the actual checker with both string types generated by assignment subroutine assignment_check2(error, chr1, chr2, checker) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: chr1, chr2 type(string_type) :: str1, str2 procedure(check2_interface) :: checker str1 = chr1 str2 = chr2 call checker(error, str1, chr1, str2, chr2) end subroutine assignment_check2 !> Generator for checking the lexical comparison subroutine gen_lgt(error, str1, chr1, str2, chr2) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1, str2 character(len=*), intent(in) :: chr1, chr2 call check(error, lgt(str1, str2) .eqv. lgt(chr1, chr2)) if (allocated(error)) return call check(error, lgt(str1, chr2) .eqv. lgt(chr1, chr2)) if (allocated(error)) return call check(error, lgt(chr1, str2) .eqv. lgt(chr1, chr2)) end subroutine gen_lgt subroutine test_lgt(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string logical :: res string = "bcd" res = lgt(string, "abc") call check(error, res .eqv. .true.) if (allocated(error)) return res = lgt(string, "bcd") call check(error, res .eqv. .false.) if (allocated(error)) return res = lgt(string, "cde") call check(error, res .eqv. .false.) if (allocated(error)) return call check2(error, "bcd", "abc", gen_lgt) if (allocated(error)) return call check2(error, "bcd", "bcd", gen_lgt) if (allocated(error)) return call check2(error, "bcd", "cde", gen_lgt) end subroutine test_lgt !> Generator for checking the lexical comparison subroutine gen_llt(error, str1, chr1, str2, chr2) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1, str2 character(len=*), intent(in) :: chr1, chr2 call check(error, llt(str1, str2) .eqv. llt(chr1, chr2)) if (allocated(error)) return call check(error, llt(str1, chr2) .eqv. llt(chr1, chr2)) if (allocated(error)) return call check(error, llt(chr1, str2) .eqv. llt(chr1, chr2)) end subroutine gen_llt subroutine test_llt(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string logical :: res string = "bcd" res = llt(string, "abc") call check(error, res .eqv. .false.) if (allocated(error)) return res = llt(string, "bcd") call check(error, res .eqv. .false.) if (allocated(error)) return res = llt(string, "cde") call check(error, res .eqv. .true.) if (allocated(error)) return call check2(error, "bcd", "abc", gen_llt) if (allocated(error)) return call check2(error, "bcd", "bcd", gen_llt) if (allocated(error)) return call check2(error, "bcd", "cde", gen_llt) end subroutine test_llt !> Generator for checking the lexical comparison subroutine gen_lge(error, str1, chr1, str2, chr2) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1, str2 character(len=*), intent(in) :: chr1, chr2 call check(error, lge(str1, str2) .eqv. lge(chr1, chr2)) if (allocated(error)) return call check(error, lge(str1, chr2) .eqv. lge(chr1, chr2)) if (allocated(error)) return call check(error, lge(chr1, str2) .eqv. lge(chr1, chr2)) end subroutine gen_lge subroutine test_lge(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string logical :: res string = "bcd" res = lge(string, "abc") call check(error, res .eqv. .true.) if (allocated(error)) return res = lge(string, "bcd") call check(error, res .eqv. .true.) if (allocated(error)) return res = lge(string, "cde") call check(error, res .eqv. .false.) if (allocated(error)) return call check2(error, "bcd", "abc", gen_lge) if (allocated(error)) return call check2(error, "bcd", "bcd", gen_lge) if (allocated(error)) return call check2(error, "bcd", "cde", gen_lge) end subroutine test_lge !> Generator for checking the lexical comparison subroutine gen_lle(error, str1, chr1, str2, chr2) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1, str2 character(len=*), intent(in) :: chr1, chr2 call check(error, lle(str1, str2) .eqv. lle(chr1, chr2)) if (allocated(error)) return call check(error, lle(str1, chr2) .eqv. lle(chr1, chr2)) if (allocated(error)) return call check(error, lle(chr1, str2) .eqv. lle(chr1, chr2)) end subroutine gen_lle subroutine test_lle(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string logical :: res string = "bcd" res = lle(string, "abc") call check(error, res .eqv. .false.) if (allocated(error)) return res = lle(string, "bcd") call check(error, res .eqv. .true.) if (allocated(error)) return res = lle(string, "cde") call check(error, res .eqv. .true.) if (allocated(error)) return call check2(error, "bcd", "abc", gen_lle) if (allocated(error)) return call check2(error, "bcd", "bcd", gen_lle) if (allocated(error)) return call check2(error, "bcd", "cde", gen_lle) end subroutine test_lle !> Generator for checking the trimming of whitespace subroutine gen_trim(error, str1, chr1) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1 character(len=*), intent(in) :: chr1 call check(error, len(trim(str1)) == len(trim(chr1))) end subroutine gen_trim subroutine test_trim(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string, trimmed_str string = "Whitespace " trimmed_str = trim(string) call check(error, len(trimmed_str) == 10) if (allocated(error)) return call check1(error, " Whitespace ", gen_trim) if (allocated(error)) return call check1(error, " W h i t e s p a ce ", gen_trim) if (allocated(error)) return call check1(error, "SPACE SPACE", gen_trim) if (allocated(error)) return call check1(error, " ", gen_trim) end subroutine test_trim !> Generator for checking the length of the character sequence subroutine gen_len(error, str1, chr1) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1 character(len=*), intent(in) :: chr1 call check(error, len(str1) == len(chr1)) end subroutine gen_len subroutine test_len(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string integer :: length string = "Some longer sentence for this example." length = len(string) call check(error, length == 38) if (allocated(error)) return string = "Whitespace " length = len(string) call check(error, length == 38) if (allocated(error)) return call check1(error, "Example string", gen_len) if (allocated(error)) return call check1(error, "S P A C E D S T R I N G", gen_len) if (allocated(error)) return call check1(error, "With trailing whitespace ", gen_len) if (allocated(error)) return call check1(error, " centered ", gen_len) end subroutine test_len !> Generator for checking the length of the character sequence without whitespace subroutine gen_len_trim(error, str1, chr1) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1 character(len=*), intent(in) :: chr1 call check(error, len_trim(str1) == len_trim(chr1)) end subroutine gen_len_trim subroutine test_len_trim(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string integer :: length string = "Some longer sentence for this example." length = len_trim(string) call check(error, length == 38) if (allocated(error)) return string = "Whitespace " length = len_trim(string) call check(error, length == 10) if (allocated(error)) return call check1(error, "Example string", gen_len_trim) if (allocated(error)) return call check1(error, "S P A C E D S T R I N G", gen_len_trim) if (allocated(error)) return call check1(error, "With trailing whitespace ", gen_len_trim) if (allocated(error)) return call check1(error, " centered ", gen_len_trim) end subroutine test_len_trim !> Generator for checking the left adjustment of the character sequence subroutine gen_adjustl(error, str1, chr1) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1 character(len=*), intent(in) :: chr1 call check(error, adjustl(str1) == adjustl(chr1)) end subroutine gen_adjustl subroutine test_adjustl(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string string = " Whitespace" string = adjustl(string) call check(error, char(string) == "Whitespace ") if (allocated(error)) return call check1(error, " B L A N K S ", gen_adjustl) end subroutine test_adjustl !> Generator for checking the right adjustment of the character sequence subroutine gen_adjustr(error, str1, chr1) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1 character(len=*), intent(in) :: chr1 call check(error, adjustr(str1) == adjustr(chr1)) end subroutine gen_adjustr subroutine test_adjustr(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string string = "Whitespace " string = adjustr(string) call check(error, char(string) == " Whitespace") if (allocated(error)) return call check1(error, " B L A N K S ", gen_adjustr) end subroutine test_adjustr !> Generator for checking the presence of a character set in a character sequence subroutine gen_scan(error, str1, chr1, str2, chr2) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1, str2 character(len=*), intent(in) :: chr1, chr2 call check(error, scan(str1, str2) == scan(chr1, chr2)) if (allocated(error)) return call check(error, scan(str1, chr2) == scan(chr1, chr2)) if (allocated(error)) return call check(error, scan(chr1, str2) == scan(chr1, chr2)) if (allocated(error)) return call check(error, scan(str1, str2, back=.true.) == scan(chr1, chr2, back=.true.)) if (allocated(error)) return call check(error, scan(str1, chr2, back=.true.) == scan(chr1, chr2, back=.true.)) if (allocated(error)) return call check(error, scan(chr1, str2, back=.true.) == scan(chr1, chr2, back=.true.)) end subroutine gen_scan subroutine test_scan(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string integer :: pos string = "fortran" pos = scan(string, "ao") call check(error, pos == 2) if (allocated(error)) return pos = scan(string, "ao", .true.) call check(error, pos == 6) if (allocated(error)) return pos = scan(string, "c++") call check(error, pos == 0) if (allocated(error)) return call check2(error, "fortran", "ao", gen_scan) if (allocated(error)) return call check2(error, "c++", "fortran", gen_scan) end subroutine test_scan !> Generator for checking the absence of a character set in a character sequence subroutine gen_verify(error, str1, chr1, str2, chr2) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1, str2 character(len=*), intent(in) :: chr1, chr2 call check(error, verify(str1, str2) == verify(chr1, chr2)) if (allocated(error)) return call check(error, verify(str1, chr2) == verify(chr1, chr2)) if (allocated(error)) return call check(error, verify(chr1, str2) == verify(chr1, chr2)) if (allocated(error)) return call check(error, verify(str1, str2, back=.true.) == verify(chr1, chr2, back=.true.)) if (allocated(error)) return call check(error, verify(str1, chr2, back=.true.) == verify(chr1, chr2, back=.true.)) if (allocated(error)) return call check(error, verify(chr1, str2, back=.true.) == verify(chr1, chr2, back=.true.)) end subroutine gen_verify subroutine test_verify(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string integer :: pos string = "fortran" pos = verify(string, "ao") call check(error, pos == 1) if (allocated(error)) return pos = verify(string, "fo") call check(error, pos == 3) if (allocated(error)) return pos = verify(string, "c++") call check(error, pos == 1) if (allocated(error)) return pos = verify(string, "c++", back=.true.) call check(error, pos == 7) if (allocated(error)) return pos = verify(string, string) call check(error, pos == 0) if (allocated(error)) return call check2(error, "fortran", "ao", gen_verify) if (allocated(error)) return call check2(error, "c++", "fortran", gen_verify) end subroutine test_verify !> Generator for the repeatition of a character sequence subroutine gen_repeat(error, str1, chr1) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1 character(len=*), intent(in) :: chr1 integer :: i do i = 12, 3, -2 call check(error, repeat(str1, i) == repeat(chr1, i)) if (allocated(error)) return end do end subroutine gen_repeat subroutine test_repeat(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string string = "What? " string = repeat(string, 3) call check(error, string == "What? What? What? ") if (allocated(error)) return call check1(error, "!!1!", gen_repeat) if (allocated(error)) return call check1(error, "This sentence is repeated multiple times. ", gen_repeat) end subroutine test_repeat !> Generator for checking the substring search in a character string subroutine gen_index(error, str1, chr1, str2, chr2) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type), intent(in) :: str1, str2 character(len=*), intent(in) :: chr1, chr2 call check(error, index(str1, str2) == index(chr1, chr2)) if (allocated(error)) return call check(error, index(str1, chr2) == index(chr1, chr2)) if (allocated(error)) return call check(error, index(chr1, str2) == index(chr1, chr2)) if (allocated(error)) return call check(error, index(str1, str2, back=.true.) == index(chr1, chr2, back=.true.)) if (allocated(error)) return call check(error, index(str1, chr2, back=.true.) == index(chr1, chr2, back=.true.)) if (allocated(error)) return call check(error, index(chr1, str2, back=.true.) == index(chr1, chr2, back=.true.)) end subroutine gen_index subroutine test_index(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string integer :: pos string = "Search this string for this expression" pos = index(string, "this") call check(error, pos == 8) if (allocated(error)) return pos = index(string, "this", back=.true.) call check(error, pos == 24) if (allocated(error)) return pos = index(string, "This") call check(error, pos == 0) if (allocated(error)) return call check2(error, "Search this string for this expression", "this", gen_index) if (allocated(error)) return call check2(error, "Search this string for this expression", "This", gen_index) end subroutine test_index subroutine test_char(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string character(len=:), allocatable :: dlc character(len=1), allocatable :: chars(:) string = "Character sequence" dlc = char(string) call check(error, dlc == "Character sequence") if (allocated(error)) return dlc = char(string, 3) call check(error, dlc == "a") if (allocated(error)) return chars = char(string, [3, 5, 8, 12, 14, 15, 18]) call check(error, all(chars == ["a", "a", "e", "e", "u", "e", "e"])) if (allocated(error)) return string = "Fortran" dlc = char(string, 1, 4) call check(error, dlc == "Fort") end subroutine test_char subroutine test_ichar(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string integer :: code string = "Fortran" code = ichar(string) call check(error, code == ichar("F")) end subroutine test_ichar subroutine test_iachar(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: string integer :: code string = "Fortran" code = iachar(string) call check(error, code == iachar("F")) end subroutine test_iachar subroutine test_move(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(string_type) :: from_string, to_string type(string_type) :: from_string_not type(string_type) :: from_strings(2), to_strings(2) character(len=:), allocatable :: from_char, to_char from_string = "Move This String" from_strings = "Move This String" from_char = "Move This Char" call check(error, from_string == "Move This String" .and. to_string == "" .and. & & from_char == "Move This Char" .and. .not. allocated(to_char), & & "move: test_case 1") if (allocated(error)) return ! string_type (allocated) --> string_type (not allocated) call move(from_string, to_string) call check(error, from_string == "" .and. to_string == "Move This String", "move: test_case 2") if (allocated(error)) return ! character (allocated) --> string_type (not allocated) call move(from_char, from_string) call check(error, .not. allocated(from_char) .and. from_string == "Move This Char", & & "move: test_case 3") if (allocated(error)) return ! string_type (allocated) --> character (not allocated) call move(to_string, to_char) call check(error, to_string == "" .and. to_char == "Move This String", "move: test_case 4") if (allocated(error)) return ! character (allocated) --> string_type (allocated) call move(to_char, from_string) call check(error, .not. allocated(to_char) .and. from_string == "Move This String", & & "move: test_case 5") if (allocated(error)) return from_char = "new char" ! character (allocated) --> string_type (allocated) call move(from_char, from_string) call check(error, .not. allocated(from_char) .and. from_string == "new char", "move: test_case 6") if (allocated(error)) return ! character (not allocated) --> string_type (allocated) call move(from_char, from_string) call check(error, from_string == "", "move: test_case 7") if (allocated(error)) return from_string = "moving to self" ! string_type (allocated) --> string_type (allocated) call move(from_string, from_string) call check(error, from_string == "moving to self", "move: test_case 8") if (allocated(error)) return ! elemental: string_type (allocated) --> string_type (not allocated) call move(from_strings, to_strings) call check(error, all(from_strings(:) == "") .and. all(to_strings(:) == "Move This String"), "move: test_case 9") ! string_type (not allocated) --> string_type (not allocated) call move(from_string_not, to_string) call check(error, from_string_not == "" .and. to_string == "", "move: test_case 10") if (allocated(error)) return ! string_type (not allocated) --> string_type (not allocated) to_string = "to be deallocated" call move(from_string_not, to_string) call check(error, from_string_not == "" .and. to_string == "", "move: test_case 11") if (allocated(error)) return end subroutine test_move end module test_string_intrinsic program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_string_intrinsic, only : collect_string_intrinsic implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("string-intrinsic", collect_string_intrinsic) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/string/test_string_to_string.f900000664000175000017500000002373715135654166025444 0ustar alastairalastair! SPDX-Identifier: MIT module test_string_to_string use stdlib_strings, only: to_string, to_c_char, starts_with use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_optval, only: optval implicit none contains !> Collect all exported unit tests subroutine collect_string_to_string(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("to_string-complex", test_to_string_complex), & new_unittest("to_string-integer", test_to_string_integer), & new_unittest("to_string-logical", test_to_string_logical), & new_unittest("to_string-real", test_to_string_real), & new_unittest("to_string-limit-i1", test_string_i1), & new_unittest("to_string-limit-i2", test_string_i2), & new_unittest("to_string-limit-i4", test_string_i4), & new_unittest("to_string-limit-i8", test_string_i8), & new_unittest("to_c_char", test_to_c_char) & ] end subroutine collect_string_to_string subroutine check_formatter(error, actual, expected, description, partial) type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: actual, expected, description logical, intent(in), optional :: partial logical :: stat character(len=:), allocatable :: msg if (optval(partial, .false.)) then stat = starts_with(actual, expected) else stat = actual == expected end if if (.not. stat) then msg = description // new_line("a") // & & "Expected: '" // expected // "' but got '" // actual // "'" else print '(" - ", a, /, " Result: ''", a, "''")', description, actual end if call check(error, stat, msg) end subroutine check_formatter subroutine test_to_string_complex(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check_formatter(error, to_string((1, 1)), "(1.0", & & "Default formatter for complex number", partial=.true.) if (allocated(error)) return call check_formatter(error, to_string((1, 1), '(F6.2)'), "( 1.00, 1.00)", & & "Formatter for complex number") if (allocated(error)) return call check_formatter(error, to_string((-1, -1), 'F6.2'), "( -1.00, -1.00)", & & "Formatter for negative complex number") if (allocated(error)) return call check_formatter(error, to_string((1, 1), 'SP,F6.2'), "( +1.00, +1.00)", & & "Formatter with sign control descriptor for complex number") if (allocated(error)) return call check_formatter(error, to_string((1, 1), 'F6.2') // to_string((2, 2), '(F7.3)'), & & "( 1.00, 1.00)( 2.000, 2.000)", & & "Multiple formatters for complex numbers") end subroutine test_to_string_complex subroutine test_to_string_integer(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check_formatter(error, to_string(100), "100", & & "Default formatter for integer number") if (allocated(error)) return call check_formatter(error, to_string(100, 'I6'), " 100", & & "Formatter for integer number") if (allocated(error)) return call check_formatter(error, to_string(100, 'I0.6'), "000100", & & "Formatter with zero padding for integer number") if (allocated(error)) return call check_formatter(error, to_string(100, 'I6') // to_string(1000, '(I7)'), & & " 100 1000", "Multiple formatters for integers") if (allocated(error)) return call check_formatter(error, to_string(34, 'B8'), " 100010", & & "Binary formatter for integer number") if (allocated(error)) return call check_formatter(error, to_string(34, 'O0.3'), "042", & & "Octal formatter with zero padding for integer number") if (allocated(error)) return call check_formatter(error, to_string(34, 'Z3'), " 22", & & "Hexadecimal formatter for integer number") end subroutine test_to_string_integer subroutine test_to_string_real(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check_formatter(error, to_string(100.), "100.0", & & "Default formatter for real number", partial=.true.) if (allocated(error)) return call check_formatter(error, to_string(100., 'F6.2'), "100.00", & & "Formatter for real number") if (allocated(error)) return call check_formatter(error, to_string(289., 'E7.2'), ".29E+03", & & "Exponential formatter with rounding for real number") if (allocated(error)) return call check_formatter(error, to_string(128., 'ES8.2'), "1.28E+02", & & "Exponential formatter for real number") if (allocated(error)) return ! Wrong demonstration call check_formatter(error, to_string(-100., 'F6.2'), "*", & & "Too narrow formatter for signed real number", partial=.true.) if (allocated(error)) return call check_formatter(error, to_string(1000., 'F6.3'), "*", & & "Too narrow formatter for real number", partial=.true.) if (allocated(error)) return call check_formatter(error, to_string(1000., '7.3'), "[*]", & & "Invalid formatter for real number", partial=.true.) if (allocated(error)) return end subroutine test_to_string_real subroutine test_to_string_logical(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check_formatter(error, to_string(.true.), "T", & & "Default formatter for logcal value") if (allocated(error)) return call check_formatter(error, to_string(.true., 'L2'), " T", & & "Formatter for logical value") if (allocated(error)) return call check_formatter(error, to_string(.false., 'L2') // to_string(.true., '(L5)'), & & " F T", "Multiple formatters for logical values") if (allocated(error)) return ! Wrong demonstration call check_formatter(error, to_string(.false., '1x'), "[*]", & & "Invalid formatter for logical value", partial=.true.) end subroutine test_to_string_logical subroutine test_to_c_char(error) use stdlib_kinds, only : c_char use stdlib_string_type, only: string_type, len, char use iso_c_binding, only: c_size_t !> Error handling type(error_type), allocatable, intent(out) :: error !> Interface to C standard library interface integer(c_size_t) function c_strlen(cstr) bind(C, name="strlen") result(len) import :: c_char, c_size_t character(kind=c_char), intent(in) :: cstr(*) end function c_strlen end interface type(string_type) :: shello character(kind=c_char), allocatable :: cstr(:) character(*), parameter :: hello = "Hello, World!" integer :: i ! Convert character array cstr = to_c_char(hello) call check(error, len(hello)==c_strlen(cstr), 'to_c_char_from_char: invalid C length') if (allocated(error)) return do i=1,len(hello) call check(error, hello(i:i)==cstr(i), 'to_c_char_from_char: character mismatch') if (allocated(error)) return end do ! Convert string type shello = string_type(hello) cstr = to_c_char(shello) call check(error, len(shello)==c_strlen(cstr), 'to_c_char_from_string: invalid C length') if (allocated(error)) return do i=1,len(shello) call check(error, char(shello,pos=i)==cstr(i), 'to_c_char_from_string: character mismatch') if (allocated(error)) return end do end subroutine test_to_c_char subroutine test_string_i1(error) use stdlib_kinds, only : i1 => int8 !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, to_string(-huge(1_i1) - 1_i1), "-128") end subroutine test_string_i1 subroutine test_string_i2(error) use stdlib_kinds, only : i2 => int16 !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, to_string(-huge(1_i2) - 1_i2), "-32768") end subroutine test_string_i2 subroutine test_string_i4(error) use stdlib_kinds, only : i4 => int32 !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, to_string(-huge(1_i4) - 1_i4), "-2147483648") end subroutine test_string_i4 subroutine test_string_i8(error) use stdlib_kinds, only : i8 => int64 !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, to_string(-huge(1_i8) - 1_i8), "-9223372036854775808") end subroutine test_string_i8 end module test_string_to_string program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_string_to_string, only : collect_string_to_string implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("string-to_string", collect_string_to_string) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/math/0000775000175000017500000000000015135654166020076 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/math/test_logspace.f900000664000175000017500000002160515135654166023256 0ustar alastairalastairmodule test_logspace use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_kinds, only: sp, dp, int8, int16, int32, int64 use stdlib_math, only: logspace, DEFAULT_LOGSPACE_BASE, DEFAULT_LOGSPACE_LENGTH implicit none ! Testing logspace ! ! logspace should return a rank 1 array of values equally logarithmically spaced ! from the base**start to base**end, using 10 as the base. If no length ! is specified, return a rank 1 array with 50 elements. ! ! Also test to verify that the proportion between adjacent elements is constant within ! a certain tolerance real(sp), parameter :: TOLERANCE_SP = 1000 * epsilon(1.0_sp) real(dp), parameter :: TOLERANCE_DP = 1000 * epsilon(1.0_dp) ! Percentage of the range for which the actual gap must not exceed contains !> Collect all exported unit tests subroutine collect_logspace(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("logspace_sp", test_logspace_sp), & new_unittest("logspace_dp", test_logspace_dp), & new_unittest("logspace_default", test_logspace_default), & new_unittest("logspace_base_2", test_logspace_base_2), & new_unittest("logspace_base_2_cmplx_start", test_logspace_base_2_cmplx_start), & new_unittest("logspace_base_i_int_start", test_logspace_base_i_int_start) & ] end subroutine collect_logspace subroutine test_logspace_sp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 20 real(sp), parameter :: start = 0.0_sp real(sp), parameter :: end = 2.0_sp real(sp) :: expected_proportion integer :: i real(sp), allocatable :: x(:) x = logspace(start, end, n) expected_proportion = 10 ** ( ( end - start ) / ( n - 1 ) ) call check(error, size(x), n, "Array not allocated to appropriate size") if (allocated(error)) return call check(error, x(1), DEFAULT_LOGSPACE_BASE ** start, "Initial value of array is not equal to 10^start") if (allocated(error)) return call check(error, x(n), DEFAULT_LOGSPACE_BASE ** end, "Final value of array is not equal to 10^end") if (allocated(error)) return do i = 1, n-1 call check(error, x(i + 1) / x(i), expected_proportion, & & thr=abs(expected_proportion) * TOLERANCE_SP) if (allocated(error)) return end do end subroutine subroutine test_logspace_dp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 10 real(dp), parameter :: start = 1.0_dp real(dp), parameter :: end = 0.0_dp real(dp) :: expected_proportion integer :: i real(dp), allocatable :: x(:) x = logspace(start, end, n) expected_proportion = 10 ** ( ( end - start ) / ( n - 1 ) ) call check(error, size(x), n, "Array not allocated to appropriate size") if (allocated(error)) return call check(error, x(1), DEFAULT_LOGSPACE_BASE ** start, "Initial value of array is not equal to 10^start") if (allocated(error)) return call check(error, x(n), DEFAULT_LOGSPACE_BASE ** end, "Final value of array is not equal to 10^end") if (allocated(error)) return do i = 1, n-1 call check(error, x(i + 1) / x(i), expected_proportion, & & thr=abs(expected_proportion) * TOLERANCE_DP) if (allocated(error)) return end do end subroutine subroutine test_logspace_default(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(dp), parameter :: start = 0.0_dp real(dp), parameter :: end = 1.0_dp integer, parameter :: n = DEFAULT_LOGSPACE_LENGTH real(dp) :: expected_proportion integer :: i real(dp), allocatable :: x(:) x = logspace(start, end) expected_proportion = 10 ** ( ( end - start ) / ( n - 1 ) ) call check(error, size(x), n, "Array not allocated to appropriate size") if (allocated(error)) return call check(error, x(1), DEFAULT_LOGSPACE_BASE ** start, "Initial value of array is not equal to 10^start") if (allocated(error)) return call check(error, x(n), DEFAULT_LOGSPACE_BASE ** end, "Final value of array is not equal to 10^end") if (allocated(error)) return do i = 1, n-1 call check(error, x(i + 1) / x(i), expected_proportion, & & thr=abs(expected_proportion) * TOLERANCE_DP) if (allocated(error)) return end do end subroutine subroutine test_logspace_base_2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 10 real(dp), parameter :: start = 1.0_dp real(dp), parameter :: end = 10.0_dp integer, parameter :: base = 2 integer :: i real(dp) :: expected_proportion real(dp), allocatable :: x(:) x = logspace(start, end, n, base) expected_proportion = 2 ** ( ( end - start ) / ( n - 1 ) ) call check(error, size(x), n, "Array not allocated to appropriate size") if (allocated(error)) return call check(error, x(1), base ** start, "Initial value of array is not equal to 2^start") if (allocated(error)) return call check(error, x(n), base ** end, "Final value of array is not equal to 2^end") if (allocated(error)) return do i = 1, n-1 call check(error, x(i + 1) / x(i), expected_proportion, & & thr=abs(expected_proportion) * TOLERANCE_DP) if (allocated(error)) return end do end subroutine subroutine test_logspace_base_2_cmplx_start(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 10 complex(dp), parameter :: start = (1, 0) complex(dp), parameter :: end = (0, 1) integer, parameter :: base = 2 complex(dp) :: expected_proportion integer :: i complex(dp), allocatable :: x(:) x = logspace(start, end, n, base) expected_proportion = 2 ** ( ( end - start ) / ( n - 1 ) ) call check(error, size(x), n, "Array not allocated to appropriate size") if (allocated(error)) return call check(error, x(1), base ** start, "Initial value of array is not equal to 2^start") if (allocated(error)) return call check(error, x(n), base ** end, "Final value of array is not equal to 2^end") if (allocated(error)) return do i = 1, n-1 call check(error, x(i + 1) / x(i), expected_proportion, & & thr=abs(expected_proportion) * TOLERANCE_DP) if (allocated(error)) return end do end subroutine subroutine test_logspace_base_i_int_start(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 5 integer, parameter :: start = 1 integer, parameter :: end = 5 complex(dp), parameter :: base = (0, 1) ! i complex(dp) :: expected_proportion integer :: i complex(dp), allocatable :: x(:) x = logspace(start, end, n, base) expected_proportion = base ** ( ( end - start ) / ( n - 1 ) ) call check(error, size(x), n, "Array not allocated to appropriate size") if (allocated(error)) return call check(error, x(1), base ** start, "Initial value of array is not equal to 2^start") if (allocated(error)) return call check(error, x(n), base ** end, "Final value of array is not equal to 2^end") if (allocated(error)) return do i = 1, n-1 call check(error, x(i + 1) / x(i), expected_proportion, & & thr=abs(expected_proportion) * TOLERANCE_DP) if (allocated(error)) return end do end subroutine end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_logspace, only : collect_logspace implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("logspace", collect_logspace) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/math/test_linspace.f900000664000175000017500000003462715135654166023267 0ustar alastairalastairmodule test_linspace use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_kinds, only: sp, dp, int8, int16 use stdlib_math, only: linspace, DEFAULT_LINSPACE_LENGTH implicit none private public :: collect_linspace real(sp), parameter :: TOLERANCE_SP = 1000 * epsilon(1.0_sp) real(dp), parameter :: TOLERANCE_DP = 1000 * epsilon(1.0_dp) ! Percentage of the range for which the actual gap must not exceed ! Testing linspace. ! ! For single and double precision, check if the beginning and end values are properly recorded ! and make sure that the size of the result array is as expected. ! ! This testing suite makes use of the a repeated section of code that will check to make ! sure that every element is linearly spaced (i.e., call check(|array(i+1) - array(i)| < |expected_value| * TOLERANCE)). ! I would convert this repeated code into a subroutine but that would require the implementation of a ! generic procedure given that each linear space will have a different expected_value type and kind. contains !> Collect all exported unit tests subroutine collect_linspace(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("linspace_sp", test_linspace_sp), & new_unittest("linspace_dp", test_linspace_dp), & new_unittest("linspace_neg_index", test_linspace_neg_index), & new_unittest("linspace_cmplx", test_linspace_cmplx), & new_unittest("linspace_cmplx_2", test_linspace_cmplx_2), & new_unittest("linspace_cmplx_3", test_linspace_cmplx_3), & new_unittest("linspace_cmplx_sp", test_linspace_cmplx_sp), & new_unittest("linspace_cmplx_sp_2", test_linspace_cmplx_sp_2), & new_unittest("linspace_int16", test_linspace_int16), & new_unittest("linspace_int8", test_linspace_int8) & ] end subroutine collect_linspace subroutine test_linspace_sp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 20 real(sp), parameter :: start = 1.0_sp real(sp), parameter :: end = 10.0_sp real(sp) :: expected_interval real(sp) :: true_difference integer :: i real(sp), allocatable :: x(:) x = linspace(start, end, n) expected_interval =( end - start ) / real(( n - 1 ), sp) call check(error, x(1), start, "Initial value of array is not equal to the passed start parameter") if (allocated(error)) return call check(error, x(n), end, "Final array value is not equal to end parameter") if (allocated(error)) return call check(error, size(x), n, "Array not allocated to appropriate size") if (allocated(error)) return print *, "Made it through first round of tests" ! Due to roundoff error, it is possible that the jump from x(n-1) to x(n) is slightly different than the expected interval do i = 1, n-1 true_difference = x(i + 1) - x(i) call check(error, abs(true_difference - expected_interval) < abs(expected_interval) * TOLERANCE_SP) if (allocated(error)) return end do end subroutine subroutine test_linspace_dp(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(dp), parameter :: start = 1.0_dp real(dp), parameter :: end = 10.0_dp integer, parameter :: n = DEFAULT_LINSPACE_LENGTH real(dp) :: expected_interval real(dp) :: true_difference real(dp), allocatable :: x(:) integer :: i x = linspace(start, end) expected_interval =( end - start ) / ( n - 1 ) call check(error, size(x), n, "Array not allocated to default size") if (allocated(error)) return call check(error, x(1), start, "Initial value of array is not equal to the passed start parameter") if (allocated(error)) return call check(error, x(n), end, "Final array value is not equal to end parameter") if (allocated(error)) return ! Due to roundoff error, it is possible that the jump from x(n-1) to x(n) is slightly different than the expected interval do i = 1, n-1 true_difference = x(i + 1) - x(i) call check(error, true_difference, expected_interval, & & thr=abs(expected_interval) * TOLERANCE_DP) if (allocated(error)) return end do end subroutine subroutine test_linspace_neg_index(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(dp), parameter :: start = 1.0_dp real(dp), parameter :: end = 10.0_dp real(dp), allocatable :: x(:) x = linspace(start, end, -15) call check(error, size(x), 0, "Allocated array is not empty") end subroutine subroutine test_linspace_cmplx(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(dp), parameter :: start = (0.0_dp, 10.0_dp) complex(dp), parameter :: end = (1.0_dp, 0.0_dp) complex(dp) :: expected_interval integer, parameter :: n = 10 complex(dp), allocatable :: z(:) integer :: i z = linspace(start, end, n) expected_interval =( end - start ) / ( n - 1 ) call check(error, size(z), n, "Array not allocated to correct size") if (allocated(error)) return call check(error, z(1), start, "Initial value of array is not equal to the passed start parameter") if (allocated(error)) return call check(error, z(n), end, "Final array value is not equal to end parameter") if (allocated(error)) return ! Due to roundoff error, it is possible that the jump from x(n-1) to x(n) is slightly different than the expected interval do i = 1, n-1 call check(error, z(i + 1) - z(i), expected_interval, & & thr=abs(expected_interval) * TOLERANCE_DP) if (allocated(error)) return end do end subroutine subroutine test_linspace_cmplx_2(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(dp), parameter :: start = (10.0_dp, 10.0_dp) complex(dp), parameter :: end = (1.0_dp, 1.0_dp) complex(dp) :: expected_interval integer, parameter :: n = 5 complex(dp), allocatable :: z(:) integer :: i z = linspace(start, end, n) expected_interval =( end - start ) / ( n - 1 ) call check(error, size(z), n, "Array not allocated to correct size") if (allocated(error)) return call check(error, z(1), start, "Initial value of array is not equal to the passed start parameter") if (allocated(error)) return call check(error, z(n), end, "Final array value is not equal to end parameter") if (allocated(error)) return ! Due to roundoff error, it is possible that the jump from x(n-1) to x(n) is slightly different than the expected interval do i = 1, n-1 call check(error, z(i + 1) - z(i), expected_interval, & & thr=abs(expected_interval) * TOLERANCE_DP) if (allocated(error)) return end do end subroutine subroutine test_linspace_cmplx_3(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(dp), parameter :: start = (-5.0_dp, 100.0_dp) complex(dp), parameter :: end = (20.0_dp, 13.0_dp) complex(dp) :: expected_interval integer, parameter :: n = 20 complex(dp), allocatable :: z(:) integer :: i z = linspace(start, end, n) expected_interval = ( end - start ) / ( n - 1 ) call check(error, size(z), n, "Array not allocated to correct size") if (allocated(error)) return call check(error, z(1), start, "Initial value of array is not equal to the passed start parameter") if (allocated(error)) return call check(error, z(n), end, "Final array value is not equal to end parameter") if (allocated(error)) return ! Due to roundoff error, it is possible that the jump from x(n-1) to x(n) is slightly different than the expected interval do i = 1, n-1 call check(error, z(i + 1) - z(i), expected_interval, & & thr=abs(expected_interval) * TOLERANCE_DP) if (allocated(error)) return end do end subroutine subroutine test_linspace_cmplx_sp(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(sp), parameter :: start = (0.5_sp, 5.0_sp) complex(sp), parameter :: end = (1.0_sp, -30.0_sp) complex(sp) :: expected_interval integer, parameter :: n = 10 complex(sp), allocatable :: z(:) integer :: i z = linspace(start, end, n) expected_interval =( end - start ) / ( n - 1 ) call check(error, size(z), n, "Array not allocated to correct size") if (allocated(error)) return call check(error, z(1), start, "Initial value of array is not equal to the passed start parameter") if (allocated(error)) return call check(error, z(n), end, "Final array value is not equal to end parameter") if (allocated(error)) return ! Due to roundoff error, it is possible that the jump from x(n-1) to x(n) is slightly different than the expected interval do i = 1, n-1 call check(error, z(i + 1) - z(i), expected_interval, & & thr=abs(expected_interval) * TOLERANCE_SP) if (allocated(error)) return end do end subroutine subroutine test_linspace_cmplx_sp_2(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(sp), parameter :: start = (50.0_sp, 500.0_sp) complex(sp), parameter :: end = (-100.0_sp, 2000.0_sp) complex(sp) :: expected_interval complex(sp) :: true_interval real(sp) :: offset integer, parameter :: n = DEFAULT_LINSPACE_LENGTH complex(sp), allocatable :: z(:) integer :: i z = linspace(start, end) expected_interval =( end - start ) / ( n - 1 ) call check(error, size(z), n, "Array not allocated to default size") if (allocated(error)) return call check(error, z(1), start, "Initial value of array is not equal to the passed start parameter") if (allocated(error)) return call check(error, z(n), end, "Final array value is not equal to end parameter") if (allocated(error)) return ! Due to roundoff error, it is possible that the jump from x(n-1) to x(n) is slightly different than the expected interval do i = 1, n-1 true_interval = (z(i + 1) - z(i)) offset = abs(true_interval - expected_interval) call check(error, z(i + 1) - z(i), expected_interval, & & thr=abs(expected_interval) * TOLERANCE_SP) if (allocated(error)) return ! print *, i end do end subroutine subroutine test_linspace_int16(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(int16), parameter :: start = 5 integer(int16), parameter :: end = 10 real(dp) :: expected_interval integer, parameter :: n = 6 integer(int16), allocatable :: z(:) integer :: i z = linspace(start, end, n) expected_interval =( end - start ) / ( n - 1 ) call check(error, size(z), n, "Array not allocated to correct size") if (allocated(error)) return call check(error, z(1), start, "Initial value of array is not equal to the passed start parameter") if (allocated(error)) return call check(error, z(n), end, "Final array value is not equal to end parameter") if (allocated(error)) return ! Due to roundoff error, it is possible that the jump from x(n-1) to x(n) is slightly different than the expected interval do i = 1, n-1 call check(error, real(z(i + 1) - z(i), dp), expected_interval, & & thr=abs(expected_interval) * TOLERANCE_DP) if (allocated(error)) return end do end subroutine subroutine test_linspace_int8(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(int8), parameter :: start = 20 integer(int8), parameter :: end = 50 real(dp) :: expected_interval integer, parameter :: n = 10 real(dp), allocatable :: z(:) integer(int8) :: z_int(n) integer :: i z = linspace(start, end, n) z_int = linspace(start, end, n) expected_interval =real( end - start, dp ) / ( n - 1 ) call check(error, size(z), n, "Array not allocated to correct size") if (allocated(error)) return call check(error, z(1), real(start, dp), "Initial value of array is not equal to the passed start parameter") if (allocated(error)) return call check(error, z(n), real(end, dp), "Final array value is not equal to end parameter") if (allocated(error)) return ! Due to roundoff error, it is possible that the jump from x(n-1) to x(n) is slightly different than the expected interval do i = 1, n-1 call check(error, z(i + 1) - z(i), expected_interval, & & thr=abs(expected_interval) * TOLERANCE_DP) if (allocated(error)) return end do end subroutine end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_linspace, only : collect_linspace implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("linspace", collect_linspace) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/math/CMakeLists.txt0000664000175000017500000000040615135654166022636 0ustar alastairalastairset( fppFiles "test_meshgrid.fypp" ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) set( cppFiles "test_stdlib_math.fypp" ) fypp_f90pp("${fyppFlags}" "${cppFiles}" outFiles) ADDTESTPP(stdlib_math) ADDTEST(linspace) ADDTEST(logspace) ADDTEST(meshgrid) fortran-lang-stdlib-0ede301/test/math/test_stdlib_math.fypp0000664000175000017500000010066615135654166024340 0ustar alastairalastair! SPDX-Identifier: MIT #:include "common.fypp" module test_stdlib_math use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_math, only: clip, swap, arg, argd, argpi, arange, is_close, all_close, diff, & arange, deg2rad, rad2deg use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp implicit none public :: collect_stdlib_math #:for k1 in REAL_KINDS real(kind=${k1}$), parameter :: PI_${k1}$ = acos(-1.0_${k1}$) #:endfor contains !> Collect all exported unit tests subroutine collect_stdlib_math(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("clip-int8", test_clip_int8), & new_unittest("clip-int8-bounds", test_clip_int8_bounds), & new_unittest("clip-int16", test_clip_int16), & new_unittest("clip-int16-bounds", test_clip_int16_bounds), & new_unittest("clip-int32", test_clip_int32), & new_unittest("clip-int32-bounds", test_clip_int32_bounds), & new_unittest("clip-int64", test_clip_int64), & new_unittest("clip-int64-bounds", test_clip_int64_bounds), & new_unittest("clip-real-single", test_clip_rsp), & new_unittest("clip-real-single-bounds", test_clip_rsp_bounds), & new_unittest("clip-real-double", test_clip_rdp), & new_unittest("clip-real-double-bounds", test_clip_rdp_bounds), & new_unittest("clip-real-quad", test_clip_rqp), & new_unittest("clip-real-quad-bounds", test_clip_rqp_bounds) & !> Tests swap #:for k1, t1 in INT_KINDS_TYPES + REAL_KINDS_TYPES , new_unittest("swap_${k1}$", test_swap_${k1}$) & #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES , new_unittest("swap_c${k1}$", test_swap_c${k1}$) & #:endfor , new_unittest("swap_str", test_swap_str) & , new_unittest("swap_stt", test_swap_stt) & !> Tests for arg/argd/argpi #:for k1 in CMPLX_KINDS , new_unittest("arg-cmplx-${k1}$", test_arg_${k1}$) & , new_unittest("argd-cmplx-${k1}$", test_argd_${k1}$) & , new_unittest("argpi-cmplx-${k1}$", test_argpi_${k1}$) & #:endfor !> Tests for deg2rad/rad2deg #:for k1 in REAL_KINDS , new_unittest("deg2rad-real-${k1}$", test_deg2rad_${k1}$) & , new_unittest("rad2deg-real-${k1}$", test_rad2deg_${k1}$) & #:endfor !> Tests for `is_close` and `all_close` #:for k1 in REAL_KINDS , new_unittest("is_close-real-${k1}$", test_is_close_real_${k1}$) & , new_unittest("is_close-cmplx-${k1}$", test_is_close_cmplx_${k1}$) & , new_unittest("all_close-real-${k1}$", test_all_close_real_${k1}$) & , new_unittest("all_close-cmplx-${k1}$", test_all_close_cmplx_${k1}$) & #:endfor !> Tests for `diff` #:for k1 in REAL_KINDS , new_unittest("diff-real-${k1}$", test_diff_real_${k1}$) & #:endfor #:for k1 in INT_KINDS , new_unittest("diff-int-${k1}$", test_diff_int_${k1}$) & #:endfor !> Tests for `arange` #:for k1 in REAL_KINDS , new_unittest("arange-real-${k1}$", test_arange_real_${k1}$) & #:endfor #:for k1 in INT_KINDS , new_unittest("arange-int-${k1}$", test_arange_int_${k1}$) & #:endfor ] end subroutine collect_stdlib_math subroutine test_clip_int8(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! clip function ! testing format: check(clip(x, xmin, xmax) == correct answer) ! valid case: xmin is not greater than xmax ! invalid case: xmin is greater than xmax ! type: integer(int8), kind: int8 ! valid test case call check(error, clip(2_int8, -2_int8, 5_int8), 2_int8) if (allocated(error)) return call check(error, clip(127_int8, -127_int8, 0_int8), 0_int8) if (allocated(error)) return end subroutine test_clip_int8 subroutine test_clip_int8_bounds(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! invalid test case call check(error, clip(2_int8, 5_int8, -2_int8), 5_int8) if (allocated(error)) return call check(error, clip(127_int8, 0_int8, -127_int8), 0_int8) if (allocated(error)) return end subroutine test_clip_int8_bounds subroutine test_clip_int16(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! type: integer(int16), kind: int16 ! valid test case call check(error, clip(2_int16, -2_int16, 5_int16), 2_int16) if (allocated(error)) return call check(error, clip(32767_int16, -32767_int16, 0_int16), 0_int16) if (allocated(error)) return end subroutine test_clip_int16 subroutine test_clip_int16_bounds(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! invalid test case call check(error, clip(2_int16, 5_int16, -2_int16), 5_int16) if (allocated(error)) return call check(error, clip(32767_int16, 0_int16, -32767_int16), 0_int16) if (allocated(error)) return end subroutine test_clip_int16_bounds subroutine test_clip_int32(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! type: integer(int32), kind: int32 ! valid test case call check(error, clip(2_int32, -2_int32, 5_int32), 2_int32) if (allocated(error)) return call check(error, clip(-2147483647_int32, 0_int32, 2147483647_int32), 0_int32) if (allocated(error)) return end subroutine test_clip_int32 subroutine test_clip_int32_bounds(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! invalid test case call check(error, clip(2_int32, 5_int32, -2_int32), 5_int32) if (allocated(error)) return call check(error, clip(-2147483647_int32, 2147483647_int32, 0_int32), 2147483647_int32) if (allocated(error)) return end subroutine test_clip_int32_bounds subroutine test_clip_int64(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! type: integer(int64), kind: int64 ! valid test case call check(error, clip(2_int64, -2_int64, 5_int64), 2_int64) if (allocated(error)) return call check(error, clip(-922337203_int64, -10_int64, 25_int64), -10_int64) if (allocated(error)) return end subroutine test_clip_int64 subroutine test_clip_int64_bounds(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! invalid test case call check(error, clip(2_int64, 5_int64, -2_int64), 5_int64) if (allocated(error)) return call check(error, clip(-922337203_int64, 25_int64, -10_int64), 25_int64) if (allocated(error)) return end subroutine test_clip_int64_bounds subroutine test_clip_rsp(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! type: real(sp), kind: sp ! valid test case call check(error, clip(3.025_sp, -5.77_sp, 3.025_sp), 3.025_sp) if (allocated(error)) return call check(error, clip(0.0_sp, -1578.025_sp, -59.68_sp), -59.68_sp) if (allocated(error)) return end subroutine test_clip_rsp subroutine test_clip_rsp_bounds(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! invalid test case call check(error, clip(3.025_sp, 3.025_sp, -5.77_sp), 3.025_sp) if (allocated(error)) return call check(error, clip(0.0_sp, -59.68_sp, -1578.025_sp), -59.68_sp) if (allocated(error)) return end subroutine test_clip_rsp_bounds subroutine test_clip_rdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! type: real(dp), kind: dp ! valid test case call check(error, clip(3.025_dp, -5.77_dp, 3.025_dp), 3.025_dp) if (allocated(error)) return call check(error, clip(-7.0_dp, 0.059668_dp, 1.00268_dp), 0.059668_dp) if (allocated(error)) return end subroutine test_clip_rdp subroutine test_clip_rdp_bounds(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! invalid test case call check(error, clip(3.025_dp, 3.025_dp, -5.77_dp), 3.025_dp) if (allocated(error)) return call check(error, clip(-7.0_dp, 1.00268_dp, 0.059668_dp), 1.00268_dp) if (allocated(error)) return end subroutine test_clip_rdp_bounds subroutine test_clip_rqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP ! type: real(qp), kind: qp ! valid test case call check(error, clip(3.025_qp, -5.77_qp, 3.025_qp), 3.025_qp) if (allocated(error)) return call check(error, clip(-55891546.2_qp, -8958133457.23_qp, -689712245.23_qp), -689712245.23_qp) if (allocated(error)) return #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_clip_rqp subroutine test_clip_rqp_bounds(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP ! invalid test case call check(error, clip(3.025_qp, 3.025_qp, -5.77_qp), 3.025_qp) if (allocated(error)) return call check(error, clip(-55891546.2_qp, -689712245.23_qp, -8958133457.23_qp), -689712245.23_qp) if (allocated(error)) return #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_clip_rqp_bounds #:for k1, t1 in INT_KINDS_TYPES + REAL_KINDS_TYPES subroutine test_swap_${k1}$(error) type(error_type), allocatable, intent(out) :: error ${t1}$ :: x(3), y(3) x = [${t1}$ :: 1, 2, 3] y = [${t1}$ :: 4, 5, 6] call swap(x,y) call check(error, all( x == [${t1}$ :: 4, 5, 6] ) ) if (allocated(error)) return call check(error, all( y == [${t1}$ :: 1, 2, 3] ) ) if (allocated(error)) return ! check self swap call swap(x,x) call check(error, all( x == [${t1}$ :: 4, 5, 6] ) ) if (allocated(error)) return end subroutine test_swap_${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES subroutine test_swap_c${k1}$(error) type(error_type), allocatable, intent(out) :: error ${t1}$ :: x(3), y(3) x = cmplx( [1, 2, 3] , [4, 5, 6] ) y = cmplx( [4, 5, 6] , [1, 2, 3] ) call swap(x,y) call check(error, all( x == cmplx( [4, 5, 6] , [1, 2, 3] ) ) ) if (allocated(error)) return call check(error, all( y == cmplx( [1, 2, 3] , [4, 5, 6] ) ) ) if (allocated(error)) return ! check self swap call swap(x,x) call check(error, all( x == cmplx( [4, 5, 6] , [1, 2, 3] ) ) ) if (allocated(error)) return end subroutine test_swap_c${k1}$ #:endfor subroutine test_swap_str(error) type(error_type), allocatable, intent(out) :: error block character(5) :: x(2), y(2) x = ['abcde','fghij'] y = ['fghij','abcde'] call swap(x,y) call check(error, all( x == ['fghij','abcde'] ) ) if (allocated(error)) return call check(error, all( y == ['abcde','fghij'] ) ) if (allocated(error)) return ! check self swap call swap(x,x) call check(error, all( x == ['fghij','abcde'] ) ) if (allocated(error)) return end block block character(4) :: x character(6) :: y x = 'abcd' y = 'efghij' call swap(x,y) call check(error, x == 'efgh' ) if (allocated(error)) return call check(error, y(1:6) == 'abcd ' ) if (allocated(error)) return x = 'abcd' y = 'efghij' call swap(x,y(1:4)) call check(error, x == 'efgh' ) if (allocated(error)) return call check(error, y == 'abcdij' ) if (allocated(error)) return end block end subroutine test_swap_str subroutine test_swap_stt(error) use stdlib_string_type type(error_type), allocatable, intent(out) :: error type(string_type) :: x(2), y(2) x = ['abcde','fghij'] y = ['fghij','abcde'] call swap(x,y) call check(error, all( x == ['fghij','abcde'] ) ) if (allocated(error)) return call check(error, all( y == ['abcde','fghij'] ) ) if (allocated(error)) return ! check self swap call swap(x,x) call check(error, all( x == ['fghij','abcde'] ) ) if (allocated(error)) return end subroutine test_swap_stt #if STDLIB_BITSETS subroutine test_swap_bitset_64(error) use stdlib_bitsets type(error_type), allocatable, intent(out) :: error type(bitset_64) :: x, y, u, v x = [.true.,.false.,.true.,.false.] u = x y = [.false.,.true.,.false.,.true.] v = y call swap(x,y) call check(error, x == v ) if (allocated(error)) return call check(error, y == u ) if (allocated(error)) return ! check self swap call swap(x,x) call check(error, x == v ) if (allocated(error)) return end subroutine test_swap_bitset_64 subroutine test_swap_bitset_large(error) use stdlib_bitsets type(error_type), allocatable, intent(out) :: error type(bitset_large) :: x, y, u, v x = [.true.,.false.,.true.,.false.] u = x y = [.false.,.true.,.false.,.true.] v = y call swap(x,y) call check(error, x == v ) if (allocated(error)) return call check(error, y == u ) if (allocated(error)) return ! check self swap call swap(x,x) call check(error, x == v ) if (allocated(error)) return end subroutine test_swap_bitset_large #endif #:for k1 in CMPLX_KINDS subroutine test_arg_${k1}$(error) type(error_type), allocatable, intent(out) :: error real(${k1}$), parameter :: tol = sqrt(epsilon(1.0_${k1}$)) real(${k1}$), allocatable :: theta(:) #! For scalar call check(error, abs(arg(2*exp((0.0_${k1}$, 0.5_${k1}$))) - 0.5_${k1}$) < tol, & "test_nonzero_scalar") if (allocated(error)) return call check(error, abs(arg((0.0_${k1}$, 0.0_${k1}$)) - 0.0_${k1}$) < tol, & "test_zero_scalar") if (allocated(error)) return #! and for array (180.0° see scalar version) theta = arange(-179.0_${k1}$, 179.0_${k1}$, 3.58_${k1}$) call check(error, all(abs(arg(exp(cmplx(0.0_${k1}$, theta/180*PI_${k1}$, ${k1}$))) - theta/180*PI_${k1}$) < tol), & "test_array") end subroutine test_arg_${k1}$ subroutine test_argd_${k1}$(error) type(error_type), allocatable, intent(out) :: error real(${k1}$), parameter :: tol = sqrt(epsilon(1.0_${k1}$)) real(${k1}$), allocatable :: theta(:) #! For scalar call check(error, abs(argd((-1.0_${k1}$, 0.0_${k1}$)) - 180.0_${k1}$) < tol, & "test_nonzero_scalar") if (allocated(error)) return call check(error, abs(argd((0.0_${k1}$, 0.0_${k1}$)) - 0.0_${k1}$) < tol, & "test_zero_scalar") if (allocated(error)) return #! and for array (180.0° see scalar version) theta = arange(-179.0_${k1}$, 179.0_${k1}$, 3.58_${k1}$) call check(error, all(abs(argd(exp(cmplx(0.0_${k1}$, theta/180*PI_${k1}$, ${k1}$))) - theta) < tol), & "test_array") end subroutine test_argd_${k1}$ subroutine test_argpi_${k1}$(error) type(error_type), allocatable, intent(out) :: error real(${k1}$), parameter :: tol = sqrt(epsilon(1.0_${k1}$)) real(${k1}$), allocatable :: theta(:) #! For scalar call check(error, abs(argpi((-1.0_${k1}$, 0.0_${k1}$)) - 1.0_${k1}$) < tol, & "test_nonzero_scalar") if (allocated(error)) return call check(error, abs(argpi((0.0_${k1}$, 0.0_${k1}$)) - 0.0_${k1}$) < tol, & "test_zero_scalar") if (allocated(error)) return #! and for array (180.0° see scalar version) theta = arange(-179.0_${k1}$, 179.0_${k1}$, 3.58_${k1}$) call check(error, all(abs(argpi(exp(cmplx(0.0_${k1}$, theta/180*PI_${k1}$, ${k1}$))) - theta/180) < tol), & "test_array") end subroutine test_argpi_${k1}$ #:endfor #:for k1 in REAL_KINDS subroutine test_deg2rad_${k1}$(error) type(error_type), allocatable, intent(out) :: error real(${k1}$), parameter :: tol = sqrt(epsilon(1.0_${k1}$)) call check(error, PI_${k1}$, deg2rad(180.0_${k1}$), thr=tol) if (allocated(error)) return end subroutine test_deg2rad_${k1}$ subroutine test_rad2deg_${k1}$(error) type(error_type), allocatable, intent(out) :: error real(${k1}$), parameter :: tol = sqrt(epsilon(1.0_${k1}$)) call check(error, 180.0_${k1}$, rad2deg(PI_${k1}$), thr=tol) if (allocated(error)) return end subroutine test_rad2deg_${k1}$ #:endfor #:for k1 in REAL_KINDS subroutine test_is_close_real_${k1}$(error) type(error_type), allocatable, intent(out) :: error real(${k1}$) :: x, NAN x = -3; NAN = sqrt(x) call check(error, is_close(2.5_${k1}$, 2.5_${k1}$), .true.) if (allocated(error)) return call check(error, is_close(0.0_${k1}$, -0.0_${k1}$), .true.) if (allocated(error)) return call check(error, is_close(2.5_${k1}$, 1.2_${k1}$), .false.) if (allocated(error)) return call check(error, is_close(NAN, NAN), .false.) if (allocated(error)) return call check(error, is_close(NAN, 0.0_${k1}$), .false.) if (allocated(error)) return call check(error, is_close(NAN, NAN, equal_nan=.true.), .true.) end subroutine test_is_close_real_${k1}$ subroutine test_is_close_cmplx_${k1}$(error) type(error_type), allocatable, intent(out) :: error real(${k1}$) :: x, NAN x = -3; NAN = sqrt(x) call check(error, is_close((2.5_${k1}$, 1.5_${k1}$), (2.5_${k1}$, 1.5_${k1}$)), .true.) if (allocated(error)) return call check(error, is_close((2.5_${k1}$, 1.2_${k1}$), (2.5_${k1}$, 1.5_${k1}$)), .false.) if (allocated(error)) return call check(error, is_close(cmplx(NAN, NAN, ${k1}$), cmplx(NAN, NAN, ${k1}$)), .false.) if (allocated(error)) return call check(error, is_close(cmplx(NAN, NAN, ${k1}$), cmplx(NAN, 0.0_${k1}$, ${k1}$)), .false.) if (allocated(error)) return call check(error, is_close(cmplx(NAN, NAN, ${k1}$), cmplx(NAN, NAN, ${k1}$), equal_nan=.true.), .true.) if (allocated(error)) return call check(error, is_close(cmplx(NAN, 1.2_${k1}$, ${k1}$), cmplx(NAN, 1.2_${k1}$, ${k1}$), equal_nan=.true.), .true.) end subroutine test_is_close_cmplx_${k1}$ subroutine test_all_close_real_${k1}$(error) type(error_type), allocatable, intent(out) :: error real(${k1}$) :: x(2, 2), eps, NAN x = 1; eps = -3; NAN = sqrt(eps) eps = sqrt(epsilon(1.0_${k1}$)) call check(error, all_close(x, x), .true.) if (allocated(error)) return call check(error, all_close(x + x*eps + 1.0e-6, x), .false.) if (allocated(error)) return call check(error, all_close(x + NAN, x), .false.) if (allocated(error)) return call check(error, all_close(x + NAN, x, equal_nan=.true.), .false.) if (allocated(error)) return call check(error, all_close(x + NAN, x + NAN), .false.) if (allocated(error)) return call check(error, all_close(x + NAN, x + NAN, equal_nan=.true.), .true.) end subroutine test_all_close_real_${k1}$ subroutine test_all_close_cmplx_${k1}$(error) type(error_type), allocatable, intent(out) :: error real(${k1}$) :: eps, NAN complex(${k1}$) :: x(2, 2) x = (1, 1); eps = -3; NAN = sqrt(eps) eps = sqrt(epsilon(1.0_${k1}$)) call check(error, all_close(x, x), .true.) if (allocated(error)) return call check(error, all_close(x + x*eps + 1.0e-6, x), .false.) if (allocated(error)) return call check(error, all_close(x + cmplx(NAN, NAN, ${k1}$), x), .false.) if (allocated(error)) return call check(error, all_close(x + cmplx(NAN, NAN, ${k1}$), x, equal_nan=.true.), .false.) if (allocated(error)) return call check(error, all_close(x + cmplx(NAN, NAN, ${k1}$), x + cmplx(NAN, NAN, ${k1}$), equal_nan=.true.), .true.) if (allocated(error)) return call check(error, all_close(x + cmplx(NAN, NAN, ${k1}$), x + cmplx(NAN, NAN, ${k1}$)), .false.) end subroutine test_all_close_cmplx_${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES subroutine test_diff_real_${k1}$(error) type(error_type), allocatable, intent(out) :: error ${t1}$ :: x(6) = [${t1}$ :: 0, 5, 15, 30, 50, 75] ${t1}$ :: A(1, 3) = reshape([${t1}$ :: 1, 3, 5], [1, 3]) ${t1}$ :: B(2) = [${t1}$ :: 1, 2] !> rank-1 diff call check(error, all_close(diff(x), [${t1}$ :: 5, 10, 15, 20, 25]), & "diff() in test_diff_real_${k1}$ failed") if (allocated(error)) return call check(error, all_close(diff(x, n=0), x), & "diff(, n=0) in test_diff_real_${k1}$ failed") if (allocated(error)) return call check(error, all_close(diff(x, n=2), [${t1}$ :: 5, 5, 5, 5]), & "diff(, n=2) in test_diff_real_${k1}$ failed") if (allocated(error)) return call check(error, all_close(diff(x, prepend=[${t1}$ :: 1]), [${t1}$ :: -1, 5, 10, 15, 20, 25]), & "diff(, prepend=[${t1}$ :: 1]) in test_diff_real_${k1}$ failed") if (allocated(error)) return call check(error, all_close(diff(x, append=[${t1}$ :: 1]), [${t1}$ :: 5, 10, 15, 20, 25, -74]), & "diff(, append=[${t1}$ :: 1]) in test_diff_real_${k1}$ failed") if (allocated(error)) return !> rank-2 diff call check(error, all_close(diff(reshape(A, [3,1]), n=1, dim=1), reshape([${t1}$ :: 2, 2], [2, 1])), & "diff(, n=1, dim=1) in test_diff_real_${k1}$ failed") if (allocated(error)) return call check(error, all_close(diff(A, n=1, dim=2), reshape([${t1}$ :: 2, 2], [1, 2])), & "diff(, n=1, dim=2) in test_diff_real_${k1}$ failed") if (allocated(error)) return call check(error, all_close(diff(A, n=1, dim=2, prepend=reshape([${t1}$ :: 1], [1, 1]), & append=reshape([${t1}$ :: 2], [1, 1])), reshape([${t1}$ :: 0, 2, 2, -3], [1, 4])), & "diff(, n=1, dim=2, prepend=reshape([${t1}$ :: 1], [1, 1]), & &append=reshape([${t1}$ :: 2], [1, 1])) in test_diff_real_${k1}$ failed") if (allocated(error)) return !> size(B, dim) <= n call check(error, size(diff(B, 2)), 0, "size(diff(B, 2)) in test_diff_real_${k1}$ failed") if (allocated(error)) return call check(error, size(diff(B, 3)), 0, "size(diff(B, 3)) in test_diff_real_${k1}$ failed") end subroutine test_diff_real_${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES subroutine test_diff_int_${k1}$(error) type(error_type), allocatable, intent(out) :: error ${t1}$ :: x(6) = [${t1}$ :: 0, 5, 15, 30, 50, 75] ${t1}$ :: A(1, 3) = reshape([${t1}$ :: 1, 3, 5], [1, 3]) ${t1}$ :: B(2) = [${t1}$ :: 1, 2] !> rank-1 diff call check(error, all(diff(x) == [${t1}$ :: 5, 10, 15, 20, 25]), & "diff() in test_diff_int_${k1}$ failed") if (allocated(error)) return call check(error, all(diff(x, n=0) == x), & "diff(, n=0) in test_diff_int_${k1}$ failed") if (allocated(error)) return call check(error, all(diff(x, n=2) == [${t1}$ :: 5, 5, 5, 5]), & "diff(, n=2) in test_diff_int_${k1}$ failed") if (allocated(error)) return call check(error, all(diff(x, prepend=[${t1}$ :: 1]) == [${t1}$ :: -1, 5, 10, 15, 20, 25]), & "diff(, prepend=[${t1}$ :: 1]) in test_diff_int_${k1}$ failed") if (allocated(error)) return call check(error, all(diff(x, append=[${t1}$ :: 1]) == [${t1}$ :: 5, 10, 15, 20, 25, -74]), & "diff(, append=[${t1}$ :: 1]) in test_diff_int_${k1}$ failed") if (allocated(error)) return !> rank-2 diff call check(error, all(diff(reshape(A, [3,1]), n=1, dim=1) == reshape([${t1}$ :: 2, 2], [2, 1])), & "diff(, n=1, dim=1) in test_diff_int_${k1}$ failed") if (allocated(error)) return call check(error, all(diff(A, n=1, dim=2) == reshape([${t1}$ :: 2, 2], [1, 2])), & "diff(, n=1, dim=2) in test_diff_int_${k1}$ failed") if (allocated(error)) return call check(error, all(diff(A, n=1, dim=2, prepend=reshape([${t1}$ :: 1], [1, 1]), & append=reshape([${t1}$ :: 2], [1, 1])) == reshape([${t1}$ :: 0, 2, 2, -3], [1, 4])), & "diff(, n=1, dim=2, prepend=reshape([${t1}$ :: 1], [1, 1]), & &append=reshape([${t1}$ :: 2], [1, 1])) in test_diff_int_${k1}$ failed") if (allocated(error)) return !> size(B, dim) <= n call check(error, size(diff(B, 2)), 0, "size(diff(B, 2)) in test_diff_int_${k1}$ failed") if (allocated(error)) return call check(error, size(diff(B, 3)), 0, "size(diff(B, 3)) in test_diff_int_${k1}$ failed") end subroutine test_diff_int_${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES subroutine test_arange_real_${k1}$(error) type(error_type), allocatable, intent(out) :: error ! Normal call check(error, all_close(arange(3.0_${k1}$), [1.0_${k1}$, 2.0_${k1}$, 3.0_${k1}$]), & "all(arange(3.0_${k1}$), [1.0_${k1}$,2.0_${k1}$,3.0_${k1}$]) failed.") if (allocated(error)) return call check(error, all_close(arange(-1.0_${k1}$), [1.0_${k1}$, 0.0_${k1}$, -1.0_${k1}$]), & "all_close(arange(-1.0_${k1}$), [1.0_${k1}$,0.0_${k1}$,-1.0_${k1}$]) failed.") if (allocated(error)) return call check(error, all_close(arange(0.0_${k1}$, 2.0_${k1}$), [0.0_${k1}$, 1.0_${k1}$, 2.0_${k1}$]), & "all_close(arange(0.0_${k1}$,2.0_${k1}$), [0.0_${k1}$,1.0_${k1}$,2.0_${k1}$]) failed.") if (allocated(error)) return call check(error, all_close(arange(1.0_${k1}$, -1.0_${k1}$), [1.0_${k1}$, 0.0_${k1}$, -1.0_${k1}$]), & "all_close(arange(1.0_${k1}$,-1.0_${k1}$), [1.0_${k1}$,0.0_${k1}$,-1.0_${k1}$]) failed.") if (allocated(error)) return call check(error, all_close(arange(1.0_${k1}$, 1.0_${k1}$), [1.0_${k1}$]), & "all_close(arange(1.0_${k1}$,1.0_${k1}$), [1.0_${k1}$]) failed.") if (allocated(error)) return call check(error, all_close(arange(0.0_${k1}$, 2.0_${k1}$, 2.0_${k1}$), [0.0_${k1}$, 2.0_${k1}$]), & "all_close(arange(0.0_${k1}$,2.0_${k1}$,2.0_${k1}$), [0.0_${k1}$,2.0_${k1}$]) failed.") if (allocated(error)) return call check(error, all_close(arange(1.0_${k1}$, -1.0_${k1}$, 2.0_${k1}$), [1.0_${k1}$, -1.0_${k1}$]), & "all_close(arange(1.0_${k1}$,-1.0_${k1}$,2.0_${k1}$), [1.0_${k1}$,-1.0_${k1}$]) failed.") if (allocated(error)) return ! Not recommended call check(error, all_close(arange(0.0_${k1}$, 2.0_${k1}$, -2.0_${k1}$), [0.0_${k1}$, 2.0_${k1}$]), & "all_close(arange(0.0_${k1}$,2.0_${k1}$,-2.0_${k1}$), [0.0_${k1}$,2.0_${k1}$]) failed.") if (allocated(error)) return call check(error, all_close(arange(1.0_${k1}$, -1.0_${k1}$, -2.0_${k1}$), [1.0_${k1}$, -1.0_${k1}$]), & "all_close(arange(1.0_${k1}$,-1.0_${k1}$,-2.0_${k1}$), [1.0_${k1}$,-1.0_${k1}$]) failed.") if (allocated(error)) return call check(error, all_close(arange(0.0_${k1}$, 2.0_${k1}$, 0.0_${k1}$), [0.0_${k1}$,1.0_${k1}$,2.0_${k1}$]), & "all_close(arange(0.0_${k1}$, 2.0_${k1}$, 0.0_${k1}$), [0.0_${k1}$,1.0_${k1}$,2.0_${k1}$]) failed.") end subroutine test_arange_real_${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES subroutine test_arange_int_${k1}$(error) type(error_type), allocatable, intent(out) :: error ! Normal call check(error, all(arange(3_${k1}$) == [1_${k1}$, 2_${k1}$, 3_${k1}$]), & "all(arange(3_${k1}$) == [1_${k1}$,2_${k1}$,3_${k1}$]) failed.") if (allocated(error)) return call check(error, all(arange(-1_${k1}$) == [1_${k1}$, 0_${k1}$, -1_${k1}$]), & "all(arange(-1_${k1}$) == [1_${k1}$,0_${k1}$,-1_${k1}$]) failed.") if (allocated(error)) return call check(error, all(arange(0_${k1}$, 2_${k1}$) == [0_${k1}$, 1_${k1}$, 2_${k1}$]), & "all(arange(0_${k1}$,2_${k1}$) == [0_${k1}$,1_${k1}$,2_${k1}$]) failed.") if (allocated(error)) return call check(error, all(arange(1_${k1}$, -1_${k1}$) == [1_${k1}$, 0_${k1}$, -1_${k1}$]), & "all(arange(1_${k1}$,-1_${k1}$) == [1_${k1}$,0_${k1}$,-1_${k1}$]) failed.") if (allocated(error)) return call check(error, all(arange(1_${k1}$, 1_${k1}$) == [1_${k1}$]), & "all(arange(1_${k1}$,1_${k1}$) == [1_${k1}$]) failed.") if (allocated(error)) return call check(error, all(arange(0_${k1}$, 2_${k1}$, 2_${k1}$) == [0_${k1}$, 2_${k1}$]), & "all(arange(0_${k1}$,2_${k1}$,2_${k1}$) == [0_${k1}$,2_${k1}$]) failed.") if (allocated(error)) return call check(error, all(arange(1_${k1}$, -1_${k1}$, 2_${k1}$) == [1_${k1}$, -1_${k1}$]), & "all(arange(1_${k1}$,-1_${k1}$,2_${k1}$) == [1_${k1}$,-1_${k1}$]) failed.") if (allocated(error)) return ! Not recommended call check(error, all(arange(0_${k1}$, 2_${k1}$, -2_${k1}$) == [0_${k1}$, 2_${k1}$]), & "all(arange(0_${k1}$,2_${k1}$,2_${k1}$) == [0_${k1}$,2_${k1}$]) failed.") if (allocated(error)) return call check(error, all(arange(1_${k1}$, -1_${k1}$, -2_${k1}$) == [1_${k1}$, -1_${k1}$]), & "all(arange(1_${k1}$,-1_${k1}$,2_${k1}$) == [1_${k1}$,-1_${k1}$]) failed.") if (allocated(error)) return call check(error, all(arange(0_${k1}$, 2_${k1}$, 0_${k1}$) == [0_${k1}$, 1_${k1}$, 2_${k1}$]), & "all(arange(0_${k1}$,2_${k1}$,0_${k1}$) == [0_${k1}$,1_${k1}$,2_${k1}$]) failed.") end subroutine test_arange_int_${k1}$ #:endfor end module test_stdlib_math program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_stdlib_math, only : collect_stdlib_math implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("stdlib-math", collect_stdlib_math) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/math/test_meshgrid.fypp0000664000175000017500000001016615135654166023643 0ustar alastairalastair! SPDX-Identifier: MIT #:include "common.fypp" #:set IR_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES #:set RANKS = range(1, MAXRANK + 1) #:set INDEXINGS = ["default", "xy", "ij"] #:def OPTIONAL_PART_IN_SIGNATURE(indexing) #:if indexing in ("xy", "ij") ${f', stdlib_meshgrid_{indexing}'}$ #:endif #:enddef module test_meshgrid use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_math, only: meshgrid, stdlib_meshgrid_ij, stdlib_meshgrid_xy use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp implicit none public :: collect_meshgrid contains !> Collect all exported unit tests subroutine collect_meshgrid(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & #:for k1, t1 in IR_KINDS_TYPES #:for rank in RANKS #:for INDEXING in INDEXINGS #: set RName = rname(f"meshgrid_{INDEXING}", rank, t1, k1) new_unittest("${RName}$", test_${RName}$), & #:endfor #:endfor #:endfor new_unittest("dummy", test_dummy) & ] end subroutine collect_meshgrid #:for k1, t1 in IR_KINDS_TYPES #:for rank in RANKS #:for INDEXING in INDEXINGS #:if rank == 1 #:set INDICES = [1] #:else #:if INDEXING in ("default", "xy") #:set INDICES = [2, 1] + [j for j in range(3, rank + 1)] #:elif INDEXING == "ij" #:set INDICES = [1, 2] + [j for j in range(3, rank + 1)] #:endif #:endif #:set RName = rname(f"meshgrid_{INDEXING}", rank, t1, k1) #:set GRIDSHAPE = "".join("length," for j in range(rank)).removesuffix(",") subroutine test_${RName}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: length = 3 ${t1}$ :: ${"".join(f"x{j}(length)," for j in range(1, rank + 1)).removesuffix(",")}$ ${t1}$ :: ${"".join(f"xm{j}({GRIDSHAPE})," for j in range(1, rank + 1)).removesuffix(",")}$ ${t1}$ :: ${"".join(f"xm{j}_exact({GRIDSHAPE})," for j in range(1, rank + 1)).removesuffix(",")}$ integer :: i integer :: ${"".join(f"i{j}," for j in range(1, rank + 1)).removesuffix(",")}$ ${t1}$, parameter :: ZERO = 0 ! valid test case #:for index in range(1, rank + 1) x${index}$ = [(i, i = length * ${index - 1}$ + 1, length * ${index}$)] #:endfor #:for j in range(1, rank + 1) xm${j}$_exact = reshape( & [${"".join("(" for dummy in range(rank)) + f"x{j}(i{j})" + "".join(f", i{index} = 1, size(x{index}))" for index in INDICES)}$], & shape=[${GRIDSHAPE}$] & ) #:endfor call meshgrid( & ${"".join(f"x{j}," for j in range(1, rank + 1))}$ & ${"".join(f"xm{j}," for j in range(1, rank + 1)).removesuffix(",")}$ & ${OPTIONAL_PART_IN_SIGNATURE(INDEXING)}$ ) #:for j in range(1, rank + 1) call check(error, maxval(abs(xm${j}$ - xm${j}$_exact)), ZERO) if (allocated(error)) return #:endfor end subroutine test_${RName}$ #:endfor #:endfor #:endfor subroutine test_dummy(error) !> Error handling type(error_type), allocatable, intent(out) :: error end subroutine end module test_meshgrid program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_meshgrid, only : collect_meshgrid implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("meshgrid", collect_meshgrid) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/CMakeLists.txt0000664000175000017500000000346415135654166021714 0ustar alastairalastairif (NOT TARGET "test-drive::test-drive") find_package("test-drive" REQUIRED) endif() if(WIN32) if(CMAKE_Fortran_COMPILER_ID MATCHES "^Intel") add_link_options(/Qoption,link,/STACK:8388608) elseif(CMAKE_Fortran_COMPILER_ID STREQUAL GNU) add_link_options(-Wl,--stack,8388608) endif() endif() macro(ADDTEST name) add_executable(test_${name} test_${name}.f90) target_link_libraries(test_${name} "${PROJECT_NAME}" "test-drive::test-drive") add_test(NAME ${name} COMMAND $ ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endmacro(ADDTEST) macro(ADDTESTPP name) add_executable(test_${name} test_${name}.F90) target_link_libraries(test_${name} "${PROJECT_NAME}" "test-drive::test-drive") add_test(NAME ${name} COMMAND $ ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endmacro(ADDTESTPP) add_subdirectory(array) add_subdirectory(ascii) if (STDLIB_BITSETS) add_subdirectory(bitsets) endif() add_subdirectory(constants) add_subdirectory(hash_functions) add_subdirectory(hash_functions_perf) if (STDLIB_HASHMAPS) add_subdirectory(hashmaps) endif() add_subdirectory(intrinsics) if (STDLIB_IO) add_subdirectory(io) endif() add_subdirectory(linalg) if (STDLIB_LOGGER) add_subdirectory(logger) endif() add_subdirectory(optval) add_subdirectory(selection) add_subdirectory(sorting) add_subdirectory(specialfunctions) if (STDLIB_STATS) add_subdirectory(stats) endif() add_subdirectory(string) if (STDLIB_SYSTEM) add_subdirectory(system) endif() if (STDLIB_QUADRATURE) add_subdirectory(quadrature) endif() add_subdirectory(math) if (STDLIB_STRINGLIST) add_subdirectory(stringlist) endif() if (STDLIB_ANSI) add_subdirectory(terminal) endif() fortran-lang-stdlib-0ede301/test/constants/0000775000175000017500000000000015135654166021161 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/constants/test_constants.f900000664000175000017500000002441215135654166024557 0ustar alastairalastairmodule test_constants !! Test constant values only for double precision. use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_kinds, only : dp, int32 use stdlib_codata, only: YEAR, & ALPHA_PARTICLE_ELECTRON_MASS_RATIO, & ALPHA_PARTICLE_MASS, & ATOMIC_MASS_CONSTANT, & AVOGADRO_CONSTANT, & BOLTZMANN_CONSTANT, & ELECTRON_VOLT, & ELEMENTARY_CHARGE, & FARADAY_CONSTANT, & MOLAR_MASS_CONSTANT,& MOLAR_VOLUME_OF_IDEAL_GAS_273_15_K_101_325_KPA, & PLANCK_CONSTANT,& SPEED_OF_LIGHT_IN_VACUUM,& STANDARD_ACCELERATION_OF_GRAVITY implicit none private public :: collect_constants contains !> Collect all exported unit tests subroutine collect_constants(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [new_unittest("YEAR", test_year), & new_unittest("ALPHA_PARTICLE_ELECTRON_MASS_RATIO", test_ALPHA_PARTICLE_ELECTRON_MASS_RATIO),& new_unittest("ALPHA_PARTICLE_MASS", test_ALPHA_PARTICLE_MASS),& new_unittest("ATOMIC_MASS_CONSTANT", test_ATOMIC_MASS_CONSTANT),& new_unittest("AVOGADRO_CONSTANT", test_AVOGADRO_CONSTANT),& new_unittest("BOLTZMANN_CONSTANT", test_BOLTZMANN_CONSTANT),& new_unittest("ELECTRON_VOLT", test_ELECTRON_VOLT),& new_unittest("ELEMENTARY_CHARGE", test_ELEMENTARY_CHARGE),& new_unittest("FARADAY_CONSTANT", test_FARADAY_CONSTANT),& new_unittest("MOLAR_MASS_CONSTANT", test_MOLAR_MASS_CONSTANT),& new_unittest("MOLAR_VOLUME_OF_IDEAL_GAS__273_15K__101_325_KPA", test_MOLAR_VOLUME_NTP),& new_unittest("PLANCK_CONSTANT", test_PLANCK_CONSTANT),& new_unittest("SPEED_OF_LIGHT_IN_VACUUM", test_SPEED_OF_LIGHT),& new_unittest("STANDARD_ACCELERATION_OF_GRAVITY", test_STANDARD_ACCELERATION_OF_GRAVITY),& new_unittest("U_ALPHA_PARTICLE_ELECTRON_MASS_RATIO", test_U_ALPHA_PARTICLE_ELECTRON_MASS_RATIO),& new_unittest("U_ALPHA_PARTICLE_MASS", test_U_ALPHA_PARTICLE_MASS),& new_unittest("U_ATOMIC_MASS_CONSTANT", test_U_ATOMIC_MASS_CONSTANT),& new_unittest("U_AVOGADRO_CONSTANT", test_U_AVOGADRO_CONSTANT),& new_unittest("U_BOLTZMANN_CONSTANT", test_U_BOLTZMANN_CONSTANT),& new_unittest("U_ELECTRON_VOLT", test_U_ELECTRON_VOLT),& new_unittest("U_ELEMENTARY_CHARGE", test_U_ELEMENTARY_CHARGE),& new_unittest("U_FARADAY_CONSTANT", test_U_FARADAY_CONSTANT),& new_unittest("U_MOLAR_MASS_CONSTANT", test_U_MOLAR_MASS_CONSTANT),& new_unittest("U_MOLAR_VOLUME_OF_IDEAL_GAS__273_15K__101_325_KPA", test_U_MOLAR_VOLUME_NTP),& new_unittest("U_PLANCK_CONSTANT", test_U_PLANCK_CONSTANT),& new_unittest("U_SPEED_OF_LIGHT_IN_VACUUM", test_U_SPEED_OF_LIGHT),& new_unittest("U_STANDARD_ACCELERATION_OF_GRAVITY", test_U_STANDARD_ACCELERATION_OF_GRAVITY)] end subroutine subroutine test_year(error) type(error_type), allocatable, intent(out) :: error call check(error, YEAR, 2022) if (allocated(error)) return end subroutine subroutine test_ALPHA_PARTICLE_ELECTRON_MASS_RATIO(error) type(error_type), allocatable, intent(out) :: error call check(error, ALPHA_PARTICLE_ELECTRON_MASS_RATIO%to_real(1.0_dp), 7294.29954171_dp) if (allocated(error)) return end subroutine subroutine test_ALPHA_PARTICLE_MASS(error) type(error_type), allocatable, intent(out) :: error call check(error, ALPHA_PARTICLE_MASS%to_real(1.0_dp), 6.6446573450d-27) if (allocated(error)) return end subroutine subroutine test_ATOMIC_MASS_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, ATOMIC_MASS_CONSTANT%to_real(1.0_dp), 1.66053906892d-27) if (allocated(error)) return end subroutine subroutine test_AVOGADRO_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, AVOGADRO_CONSTANT%to_real(1.0_dp), 6.02214076d23) if (allocated(error)) return end subroutine subroutine test_BOLTZMANN_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, BOLTZMANN_CONSTANT%to_real(1.0_dp), 1.380649d-23) if (allocated(error)) return end subroutine subroutine test_ELECTRON_VOLT(error) type(error_type), allocatable, intent(out) :: error call check(error, ELECTRON_VOLT%to_real(1.0_dp), 1.602176634d-19) if (allocated(error)) return end subroutine subroutine test_ELEMENTARY_CHARGE(error) type(error_type), allocatable, intent(out) :: error call check(error, ELEMENTARY_CHARGE%to_real(1.0_dp), 1.602176634d-19) if (allocated(error)) return end subroutine subroutine test_FARADAY_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, FARADAY_CONSTANT%to_real(1.0_dp), 96485.33212d0) if (allocated(error)) return end subroutine subroutine test_MOLAR_MASS_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, MOLAR_MASS_CONSTANT%to_real(1.0_dp), 1.00000000105d-3) if (allocated(error)) return end subroutine subroutine test_MOLAR_VOLUME_NTP(error) type(error_type), allocatable, intent(out) :: error call check(error, MOLAR_VOLUME_OF_IDEAL_GAS_273_15_K_101_325_KPA%to_real(1.0_dp), 22.41396954d-3) if (allocated(error)) return end subroutine subroutine test_PLANCK_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, PLANCK_CONSTANT%to_real(1.0_dp), 6.62607015d-34) if (allocated(error)) return end subroutine subroutine test_SPEED_OF_LIGHT(error) type(error_type), allocatable, intent(out) :: error call check(error, SPEED_OF_LIGHT_IN_VACUUM%to_real(1.0_dp), 299792458.0d0) if (allocated(error)) return end subroutine subroutine test_STANDARD_ACCELERATION_OF_GRAVITY(error) type(error_type), allocatable, intent(out) :: error call check(error, STANDARD_ACCELERATION_OF_GRAVITY%to_real(1.0_dp), 9.80665d0) if (allocated(error)) return end subroutine subroutine test_U_ALPHA_PARTICLE_ELECTRON_MASS_RATIO(error) type(error_type), allocatable, intent(out) :: error call check(error, ALPHA_PARTICLE_ELECTRON_MASS_RATIO%to_real(1.0_dp, uncertainty=.true.), 0.00000017d0) if (allocated(error)) return end subroutine subroutine test_U_ALPHA_PARTICLE_MASS(error) type(error_type), allocatable, intent(out) :: error call check(error, ALPHA_PARTICLE_MASS%to_real(1.0_dp, uncertainty=.true.), 0.0000000021d-27) if (allocated(error)) return end subroutine subroutine test_U_ATOMIC_MASS_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, ATOMIC_MASS_CONSTANT%to_real(1.0_dp, uncertainty=.true.), 0.00000000052d-27) if (allocated(error)) return end subroutine subroutine test_U_AVOGADRO_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, AVOGADRO_CONSTANT%to_real(1.0_dp, uncertainty=.true.), 0.0_dp) if (allocated(error)) return end subroutine subroutine test_U_BOLTZMANN_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, BOLTZMANN_CONSTANT%to_real(1.0_dp, uncertainty=.true.), 0.0_dp) if (allocated(error)) return end subroutine subroutine test_U_ELECTRON_VOLT(error) type(error_type), allocatable, intent(out) :: error call check(error, ELECTRON_VOLT%to_real(1.0_dp, uncertainty=.true.), 0.0_dp) if (allocated(error)) return end subroutine subroutine test_U_ELEMENTARY_CHARGE(error) type(error_type), allocatable, intent(out) :: error call check(error, ELEMENTARY_CHARGE%to_real(1.0_dp, uncertainty=.true.), 0.0_dp) if (allocated(error)) return end subroutine subroutine test_U_FARADAY_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, FARADAY_CONSTANT%to_real(1.0_dp, uncertainty=.true.), 0.0_dp) if (allocated(error)) return end subroutine subroutine test_U_MOLAR_MASS_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, MOLAR_MASS_CONSTANT%to_real(1.0_dp, uncertainty=.true.), 0.00000000031d-3) if (allocated(error)) return end subroutine subroutine test_U_MOLAR_VOLUME_NTP(error) type(error_type), allocatable, intent(out) :: error call check(error, MOLAR_VOLUME_OF_IDEAL_GAS_273_15_K_101_325_KPA%to_real(1.0_dp, uncertainty=.true.), 0.0_dp) if (allocated(error)) return end subroutine subroutine test_U_PLANCK_CONSTANT(error) type(error_type), allocatable, intent(out) :: error call check(error, PLANCK_CONSTANT%to_real(1.0_dp, uncertainty=.true.), 0.0_dp) if (allocated(error)) return end subroutine subroutine test_U_SPEED_OF_LIGHT(error) type(error_type), allocatable, intent(out) :: error call check(error, SPEED_OF_LIGHT_IN_VACUUM%to_real(1.0_dp, uncertainty=.true.), 0.0_dp) if (allocated(error)) return end subroutine subroutine test_U_STANDARD_ACCELERATION_OF_GRAVITY(error) type(error_type), allocatable, intent(out) :: error call check(error, STANDARD_ACCELERATION_OF_GRAVITY%to_real(1.0_dp, uncertainty=.true.), 0.0_dp) if (allocated(error)) return end subroutine end module test_constants program tester use iso_fortran_env use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_constants, only : collect_constants implicit none type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' integer :: stat, is stat = 0 testsuites = [new_testsuite("constants", collect_constants)] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/constants/CMakeLists.txt0000664000175000017500000000002315135654166023714 0ustar alastairalastairADDTEST(constants) fortran-lang-stdlib-0ede301/test/ascii/0000775000175000017500000000000015135654166020235 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/ascii/CMakeLists.txt0000664000175000017500000000001715135654166022773 0ustar alastairalastairADDTEST(ascii) fortran-lang-stdlib-0ede301/test/ascii/test_ascii.f900000664000175000017500000010203015135654166022700 0ustar alastairalastairmodule test_ascii use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_ascii, only: lowercase, uppercase, digits, & octal_digits, fullhex_digits, hex_digits, lowerhex_digits, & whitespace, letters, is_alphanum, is_alpha, is_lower, is_upper, & is_digit, is_octal_digit, is_hex_digit, is_white, is_blank, & is_control, is_punctuation, is_graphical, is_printable, is_ascii, & to_lower, to_upper, to_title, to_sentence, reverse, LF, TAB, NUL, DEL use stdlib_kinds, only : int8, int16, int32, int64, lk implicit none private public :: collect_ascii contains !> Collect all exported unit tests subroutine collect_ascii(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("is_alphanum_short", test_is_alphanum_short), & new_unittest("is_alphanum_long", test_is_alphanum_long), & new_unittest("is_alpha_short", test_is_alpha_short), & new_unittest("is_alpha_long", test_is_alpha_long), & new_unittest("is_lower_short", test_is_lower_short), & new_unittest("is_lower_long", test_is_lower_long), & new_unittest("is_upper_short", test_is_upper_short), & new_unittest("is_upper_long", test_is_upper_long), & new_unittest("is_digit_short", test_is_digit_short), & new_unittest("is_digit_long", test_is_digit_long), & new_unittest("is_octal_digit_short", test_is_octal_digit_short), & new_unittest("is_octal_digit_long", test_is_octal_digit_long), & new_unittest("is_hex_digit_short", test_is_hex_digit_short), & new_unittest("is_hex_digit_long", test_is_hex_digit_long), & new_unittest("is_white_short", test_is_white_short), & new_unittest("is_white_long", test_is_white_long), & new_unittest("is_blank_short", test_is_blank_short), & new_unittest("is_blank_long", test_is_blank_long), & new_unittest("is_control_short", test_is_control_short), & new_unittest("is_control_long", test_is_control_long), & new_unittest("is_punctuation_short", test_is_punctuation_short), & new_unittest("is_punctuation_long", test_is_punctuation_long), & new_unittest("is_graphical_short", test_is_graphical_short), & new_unittest("is_graphical_long", test_is_graphical_long), & new_unittest("is_printable_short", test_is_printable_short), & new_unittest("is_printable_long", test_is_printable_long), & new_unittest("is_ascii_short", test_is_ascii_short), & new_unittest("is_ascii_long", test_is_ascii_long), & new_unittest("to_lower_short", test_to_lower_short), & new_unittest("to_lower_long", test_to_lower_long), & new_unittest("to_upper_short", test_to_upper_short), & new_unittest("to_upper_long", test_to_upper_long), & new_unittest("ascii_table", test_ascii_table), & new_unittest("to_upper_string", test_to_upper_string), & new_unittest("to_lower_string", test_to_lower_string), & new_unittest("to_title_string", test_to_title_string), & new_unittest("to_sentence_string", test_to_sentence_string), & new_unittest("reverse_string", test_reverse_string) & ] end subroutine collect_ascii subroutine test_is_alphanum_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_alphanum('A')) if (allocated(error)) return call check(error, is_alphanum('1')) if (allocated(error)) return call check(error, .not. is_alphanum('#')) if (allocated(error)) return ! N.B.: does not return true for non-ASCII Unicode alphanumerics call check(error, .not. is_alphanum('á')) if (allocated(error)) return end subroutine subroutine test_is_alphanum_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=:), allocatable :: clist clist = digits//octal_digits//fullhex_digits//letters//lowercase//uppercase do i = 1, len(clist) call check(error, is_alphanum(clist(i:i))) if (allocated(error)) return end do clist = whitespace do i = 1, len(clist) call check(error, .not. is_alphanum(clist(i:i))) if (allocated(error)) return end do end subroutine subroutine test_is_alpha_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_alpha('A')) if (allocated(error)) return call check(error, .not. is_alpha('1')) if (allocated(error)) return call check(error, .not. is_alpha('#')) if (allocated(error)) return ! N.B.: does not return true for non-ASCII Unicode alphabetic characters call check(error, .not. is_alpha('á')) if (allocated(error)) return end subroutine subroutine test_is_alpha_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=:), allocatable :: clist clist = letters//lowercase//uppercase do i = 1, len(clist) call check(error, is_alpha(clist(i:i))) if (allocated(error)) return end do clist = digits//octal_digits//whitespace do i = 1, len(clist) call check(error, .not. is_alpha(clist(i:i))) if (allocated(error)) return end do end subroutine subroutine test_is_lower_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_lower('a')) if (allocated(error)) return call check(error, .not. is_lower('A')) if (allocated(error)) return call check(error, .not. is_lower('#')) if (allocated(error)) return ! N.B.: does not return true for non-ASCII Unicode lowercase letters call check(error, .not. is_lower('á')) if (allocated(error)) return call check(error, .not. is_lower('Á')) if (allocated(error)) return end subroutine subroutine test_is_lower_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=:), allocatable :: clist do i = 1, len(lowercase) call check(error, is_lower(lowercase(i:i))) if (allocated(error)) return end do clist = digits//uppercase//whitespace do i = 1, len(clist) call check(error, .not. is_lower(clist(i:i))) if (allocated(error)) return end do end subroutine subroutine test_is_upper_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_upper('A')) if (allocated(error)) return call check(error, .not. is_upper('a')) if (allocated(error)) return call check(error, .not. is_upper('#')) if (allocated(error)) return ! N.B.: does not return true for non-ASCII Unicode uppercase letters call check(error, .not. is_upper('á')) if (allocated(error)) return call check(error, .not. is_upper('Á')) if (allocated(error)) return end subroutine subroutine test_is_upper_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=:), allocatable :: clist do i = 1, len(uppercase) call check(error, is_upper(uppercase(i:i))) if (allocated(error)) return end do clist = digits//lowercase//whitespace do i = 1, len(clist) call check(error, .not. is_upper(clist(i:i))) if (allocated(error)) return end do end subroutine subroutine test_is_digit_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_digit('3')) if (allocated(error)) return call check(error, is_digit('8')) if (allocated(error)) return call check(error, .not. is_digit('B')) if (allocated(error)) return call check(error, .not. is_digit('#')) if (allocated(error)) return ! N.B.: does not return true for non-ASCII Unicode numbers call check(error, .not. is_digit('0')) ! full-width digit zero (U+FF10) if (allocated(error)) return call check(error, .not. is_digit('4')) ! full-width digit four (U+FF14)) if (allocated(error)) return end subroutine subroutine test_is_digit_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=:), allocatable :: clist do i = 1, len(digits) call check(error, is_digit(digits(i:i))) if (allocated(error)) return end do clist = letters//whitespace do i = 1, len(clist) call check(error, .not. is_digit(clist(i:i))) if (allocated(error)) return end do end subroutine subroutine test_is_octal_digit_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_octal_digit('0')) if (allocated(error)) return call check(error, is_octal_digit('7')) if (allocated(error)) return call check(error, .not. is_octal_digit('8')) if (allocated(error)) return call check(error, .not. is_octal_digit('A')) if (allocated(error)) return call check(error, .not. is_octal_digit('#')) if (allocated(error)) return end subroutine subroutine test_is_octal_digit_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=:), allocatable :: clist do i = 1, len(octal_digits) call check(error, is_octal_digit(octal_digits(i:i))) if (allocated(error)) return end do clist = letters//'89'//whitespace do i = 1, len(clist) call check(error, .not. is_octal_digit(clist(i:i))) if (allocated(error)) return end do end subroutine subroutine test_is_hex_digit_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_hex_digit('0')) if (allocated(error)) return call check(error, is_hex_digit('A')) if (allocated(error)) return call check(error, is_hex_digit('f')) !! lowercase hex digits are accepted if (allocated(error)) return call check(error, .not. is_hex_digit('g')) if (allocated(error)) return call check(error, .not. is_hex_digit('G')) if (allocated(error)) return call check(error, .not. is_hex_digit('#')) if (allocated(error)) return end subroutine subroutine test_is_hex_digit_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=:), allocatable :: clist do i = 1, len(fullhex_digits) call check(error, is_hex_digit(fullhex_digits(i:i))) if (allocated(error)) return end do clist = lowercase(7:)//uppercase(7:)//whitespace do i = 1, len(clist) call check(error, .not. is_hex_digit(clist(i:i))) if (allocated(error)) return end do end subroutine subroutine test_is_white_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_white(' ')) if (allocated(error)) return call check(error, is_white(TAB)) if (allocated(error)) return call check(error, is_white(LF)) if (allocated(error)) return call check(error, .not. is_white('1')) if (allocated(error)) return call check(error, .not. is_white('a')) if (allocated(error)) return call check(error, .not. is_white('#')) if (allocated(error)) return end subroutine subroutine test_is_white_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=:), allocatable :: clist do i = 1, len(whitespace) call check(error, is_white(whitespace(i:i))) if (allocated(error)) return end do clist = digits//letters do i = 1, len(clist) call check(error, .not. is_white(clist(i:i))) if (allocated(error)) return end do end subroutine subroutine test_is_blank_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_blank(' ')) if (allocated(error)) return call check(error, is_blank(TAB)) if (allocated(error)) return call check(error, .not. is_blank('1')) if (allocated(error)) return call check(error, .not. is_blank('a')) if (allocated(error)) return call check(error, .not. is_blank('#')) if (allocated(error)) return end subroutine subroutine test_is_blank_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=:), allocatable :: clist do i = 1, len(whitespace) if (whitespace(i:i) == ' ' .or. whitespace(i:i) == TAB) then call check(error, is_blank(whitespace(i:i))) else call check(error, .not. is_blank(whitespace(i:i))) end if if (allocated(error)) return end do clist = digits//letters do i = 1, len(clist) call check(error, .not. is_blank(clist(i:i))) if (allocated(error)) return end do end subroutine subroutine test_is_control_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error ! print *, is_control('\0') ! print *, is_control('\022') call check(error, is_control(new_line('a'))) ! newline is both whitespace and control if (allocated(error)) return call check(error, .not. is_control(' ')) if (allocated(error)) return call check(error, .not. is_control('1')) if (allocated(error)) return call check(error, .not. is_control('a')) if (allocated(error)) return call check(error, .not. is_control('#')) if (allocated(error)) return ! N.B.: non-ASCII Unicode control characters are not recognized: ! print *, .not. is_control('\u0080') ! print *, .not. is_control('\u2028') ! print *, .not. is_control('\u2029') end subroutine subroutine test_is_control_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=:), allocatable :: clist do i = 0, 31 call check(error, is_control(achar(i))) if (allocated(error)) return end do call check(error, is_control(DEL)) if (allocated(error)) return clist = digits//letters//' ' do i = 1, len(clist) call check(error, .not. is_control(clist(i:i))) if (allocated(error)) return end do end subroutine subroutine test_is_punctuation_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_punctuation('.')) if (allocated(error)) return call check(error, is_punctuation(',')) if (allocated(error)) return call check(error, is_punctuation(':')) if (allocated(error)) return call check(error, is_punctuation('!')) if (allocated(error)) return call check(error, is_punctuation('#')) if (allocated(error)) return call check(error, is_punctuation('~')) if (allocated(error)) return call check(error, is_punctuation('+')) if (allocated(error)) return call check(error, is_punctuation('_')) if (allocated(error)) return call check(error, .not. is_punctuation('1')) if (allocated(error)) return call check(error, .not. is_punctuation('a')) if (allocated(error)) return call check(error, .not. is_punctuation(' ')) if (allocated(error)) return call check(error, .not. is_punctuation(LF)) ! new line character if (allocated(error)) return call check(error, .not. is_punctuation(NUL)) if (allocated(error)) return ! N.B.: Non-ASCII Unicode punctuation characters are not recognized. ! print *, is_punctuation('\u2012') ! (U+2012 = en-dash) end subroutine subroutine test_is_punctuation_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=1) :: c do i = 0, 127 c = achar(i) if (is_control(c) .or. is_alphanum(c) .or. c == ' ') then call check(error, .not. is_punctuation(c)) else call check(error, is_punctuation(c)) end if if (allocated(error)) return end do end subroutine subroutine test_is_graphical_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_graphical('1')) if (allocated(error)) return call check(error, is_graphical('a')) if (allocated(error)) return call check(error, is_graphical('#')) if (allocated(error)) return call check(error, .not. is_graphical(' ')) ! whitespace is not graphical if (allocated(error)) return call check(error, .not. is_graphical(LF)) if (allocated(error)) return call check(error, .not. is_graphical(NUL)) if (allocated(error)) return ! N.B.: Unicode graphical characters are not regarded as such. call check(error, .not. is_graphical('ä')) if (allocated(error)) return end subroutine subroutine test_is_graphical_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=1) :: c do i = 0, 127 c = achar(i) if (is_control(c) .or. c == ' ') then call check(error, .not. is_graphical(c)) else call check(error, is_graphical(c)) end if if (allocated(error)) return end do end subroutine subroutine test_is_printable_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_printable(' ')) ! whitespace is printable if (allocated(error)) return call check(error, is_printable('1')) if (allocated(error)) return call check(error, is_printable('a')) if (allocated(error)) return call check(error, is_printable('#')) if (allocated(error)) return call check(error, .not. is_printable(NUL)) ! control characters are not printable if (allocated(error)) return ! N.B.: Printable non-ASCII Unicode characters are not recognized. call check(error, .not. is_printable('ä')) if (allocated(error)) return end subroutine subroutine test_is_printable_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=1) :: c do i = 0, 127 c = achar(i) if (is_control(c)) then call check(error, .not. is_printable(c)) else call check(error, is_printable(c)) end if if (allocated(error)) return end do end subroutine subroutine test_is_ascii_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, is_ascii('a')) if (allocated(error)) return call check(error, .not. is_ascii('ä')) if (allocated(error)) return end subroutine subroutine test_is_ascii_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i do i = 0, 127 call check(error, is_ascii(achar(i))) if (allocated(error)) return end do call check(error, .not. is_ascii(achar(128))) ! raises compiler warning if (allocated(error)) return end subroutine subroutine test_to_lower_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, to_lower('a'), 'a') if (allocated(error)) return call check(error, to_lower('A'), 'a') if (allocated(error)) return call check(error, to_lower('#'), '#') if (allocated(error)) return end subroutine subroutine test_to_lower_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=1) :: c do i = 1, len(uppercase) call check(error, to_lower(uppercase(i:i)), lowercase(i:i)) if (allocated(error)) return end do do i = 0, 127 c = achar(i) if (c < 'A' .or. c > 'Z') then call check(error, to_lower(c), c) else call check(error, to_lower(c) /= c) end if if (allocated(error)) return end do end subroutine subroutine test_to_upper_short(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, to_upper('a'), 'A') if (allocated(error)) return call check(error, to_upper('A'), 'A') if (allocated(error)) return call check(error, to_upper('#'), '#') if (allocated(error)) return end subroutine subroutine test_to_upper_long(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i character(len=1) :: c do i = 1, len(lowercase) call check(error, to_upper(lowercase(i:i)), uppercase(i:i)) if (allocated(error)) return end do do i = 0, 127 c = achar(i) if (c < 'a' .or. c > 'z') then call check(error, to_upper(c), c) else call check(error, to_upper(c) /= c) end if if (allocated(error)) return end do end subroutine ! ! This test reproduces the true/false table found at ! https://en.cppreference.com/w/cpp/string/byte ! subroutine ascii_table(table) logical, intent(out) :: table(15,12) integer :: i, j ! loop through functions do i = 1, 12 table(1,i) = all([(validate(j,i), j=0,8)]) table(2,i) = validate(9,i) table(3,i) = all([(validate(j,i), j=10,13)]) table(4,i) = all([(validate(j,i), j=14,31)]) table(5,i) = validate(32,i) table(6,i) = all([(validate(j,i), j=33,47)]) table(7,i) = all([(validate(j,i), j=48,57)]) table(8,i) = all([(validate(j,i), j=58,64)]) table(9,i) = all([(validate(j,i), j=65,70)]) table(10,i) = all([(validate(j,i), j=71,90)]) table(11,i) = all([(validate(j,i), j=91,96)]) table(12,i) = all([(validate(j,i), j=97,102)]) table(13,i) = all([(validate(j,i), j=103,122)]) table(14,i) = all([(validate(j,i), j=123,126)]) table(15,i) = validate(127,i) end do ! output table for verification write(*,'(5X,12(I4))') (i,i=1,12) do j = 1, 15 write(*,'(I3,2X,12(L4),2X,I3)') j, (table(j,i),i=1,12), count(table(j,:)) end do write(*,'(5X,12(I4))') (count(table(:,i)),i=1,12) contains elemental logical function validate(ascii_code, func) integer, intent(in) :: ascii_code, func character(len=1) :: c c = achar(ascii_code) select case (func) case (1); validate = is_control(c) case (2); validate = is_printable(c) case (3); validate = is_white(c) case (4); validate = is_blank(c) case (5); validate = is_graphical(c) case (6); validate = is_punctuation(c) case (7); validate = is_alphanum(c) case (8); validate = is_alpha(c) case (9); validate = is_upper(c) case (10); validate = is_lower(c) case (11); validate = is_digit(c) case (12); validate = is_hex_digit(c) case default; validate = .false. end select end function validate end subroutine ascii_table subroutine test_ascii_table(error) type(error_type), allocatable, intent(out) :: error logical :: arr(15, 12) logical, parameter :: ascii_class_table(15,12) = transpose(reshape([ & ! iscntrl isprint isspace isblank isgraph ispunct isalnum isalpha isupper islower isdigit isxdigit .true., .false., .false., .false., .false., .false., .false., .false., .false., .false., .false., .false., & ! 0–8 .true., .false., .true., .true., .false., .false., .false., .false., .false., .false., .false., .false., & ! 9 .true., .false., .true., .false., .false., .false., .false., .false., .false., .false., .false., .false., & ! 10–13 .true., .false., .false., .false., .false., .false., .false., .false., .false., .false., .false., .false., & ! 14–31 .false., .true., .true., .true., .false., .false., .false., .false., .false., .false., .false., .false., & ! 32 (space) .false., .true., .false., .false., .true., .true., .false., .false., .false., .false., .false., .false., & ! 33–47 .false., .true., .false., .false., .true., .false., .true., .false., .false., .false., .true., .true., & ! 48–57 .false., .true., .false., .false., .true., .true., .false., .false., .false., .false., .false., .false., & ! 58–64 .false., .true., .false., .false., .true., .false., .true., .true., .true., .false., .false., .true., & ! 65–70 .false., .true., .false., .false., .true., .false., .true., .true., .true., .false., .false., .false., & ! 71–90 .false., .true., .false., .false., .true., .true., .false., .false., .false., .false., .false., .false., & ! 91–96 .false., .true., .false., .false., .true., .false., .true., .true., .false., .true., .false., .true., & ! 97–102 .false., .true., .false., .false., .true., .false., .true., .true., .false., .true., .false., .false., & ! 103–122 .false., .true., .false., .false., .true., .true., .false., .false., .false., .false., .false., .false., & ! 123–126 .true., .false., .false., .false., .false., .false., .false., .false., .false., .false., .false., .false. & ! 127 ], shape=[12,15])) call ascii_table(arr) call check(error, all(arr .eqv. ascii_class_table), "ascii table was not accurately generated") end subroutine test_ascii_table subroutine test_to_lower_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=:), allocatable :: dlc character(len=32), parameter :: input = "UPPERCASE" dlc = to_lower("UPPERCASE") call check(error, dlc, "uppercase") if (allocated(error)) return dlc = to_lower(input) call check(error, len(dlc), 32) if (allocated(error)) return call check(error, len_trim(dlc), 9) if (allocated(error)) return call check(error, trim(dlc), "uppercase") if (allocated(error)) return dlc = to_lower("0123456789ABCDE") call check(error, dlc, "0123456789abcde") if (allocated(error)) return end subroutine test_to_lower_string subroutine test_to_upper_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=:), allocatable :: dlc character(len=32), parameter :: input = "lowercase" dlc = to_upper("lowercase") call check(error, dlc, "LOWERCASE") if (allocated(error)) return dlc = to_upper(input) call check(error, len(dlc), 32) if (allocated(error)) return call check(error, len_trim(dlc), 9) if (allocated(error)) return call check(error, trim(dlc), "LOWERCASE") if (allocated(error)) return dlc = to_upper("0123456789abcde") call check(error, dlc, "0123456789ABCDE") if (allocated(error)) return end subroutine test_to_upper_string subroutine test_to_title_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=:), allocatable :: dlc character(len=32), parameter :: input = "tHis Is tO bE tiTlEd" dlc = to_title("tHis Is tO bE tiTlEd") call check(error, dlc, "This Is To Be Titled") if (allocated(error)) return dlc = to_title(input) call check(error, len(dlc), 32) if (allocated(error)) return call check(error, len_trim(dlc), 20) if (allocated(error)) return call check(error, trim(dlc), "This Is To Be Titled") if (allocated(error)) return dlc = to_title(" s P a C e D !") call check(error, dlc, " S P A C E D !") if (allocated(error)) return dlc = to_title("1st, 2nD, 3RD") call check(error, dlc, "1st, 2nd, 3rd") if (allocated(error)) return dlc = to_title("""quOTed""") call check(error, dlc, """Quoted""") if (allocated(error)) return end subroutine test_to_title_string subroutine test_to_sentence_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=:), allocatable :: dlc character(len=32), parameter :: input = "tHis iS A seNteNcE." dlc = to_sentence("tHis iS A seNteNcE.") call check(error, dlc, "This is a sentence.") if (allocated(error)) return dlc = to_sentence(input) call check(error, len(dlc), 32) if (allocated(error)) return call check(error, len_trim(dlc), 19) if (allocated(error)) return call check(error, trim(dlc), "This is a sentence.") if (allocated(error)) return dlc = to_sentence(" s P a C e D !") call check(error, dlc, " S p a c e d !") if (allocated(error)) return dlc = to_sentence("1st, 2nd, 3rd") call check(error, dlc, "1st, 2nd, 3rd") if (allocated(error)) return dlc = to_sentence("""quOTed""") call check(error, dlc, """Quoted""") if (allocated(error)) return end subroutine test_to_sentence_string subroutine test_reverse_string(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=:), allocatable :: dlc character(len=32), parameter :: input = "reversed" dlc = reverse("reversed") call check(error, dlc, "desrever") if (allocated(error)) return dlc = reverse(input) call check(error, len(dlc), 32) if (allocated(error)) return call check(error, len_trim(dlc), 32) if (allocated(error)) return call check(error, trim(dlc), " desrever") if (allocated(error)) return call check(error, trim(adjustl(dlc)), "desrever") if (allocated(error)) return end subroutine test_reverse_string end module test_ascii program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_ascii, only : collect_ascii implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("ascii", collect_ascii) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/hashmaps/0000775000175000017500000000000015135654166020751 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/hashmaps/CMakeLists.txt0000775000175000017500000000034515135654166023516 0ustar alastairalastair### Pre-process: .fpp -> .f90 via Fypp # Create a list of the files to be preprocessed set(fppFiles test_maps.fypp ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) ADDTEST(chaining_maps) ADDTEST(open_maps) ADDTEST(maps) fortran-lang-stdlib-0ede301/test/hashmaps/test_open_maps.f900000775000175000017500000003422715135654166024324 0ustar alastairalastairprogram test_open_maps !! Test various aspects of the runtime system. !! Running this program may require increasing the stack size to above 48 MBytes !! or decreasing rand_power to 20 or less use stdlib_kinds, only: & dp, & int8, & int32 use stdlib_hashmaps, only : open_hashmap_type, int_depth, int_index use stdlib_hashmap_wrappers implicit none type dummy_type integer(int8), allocatable :: value(:) end type dummy_type integer(int32), parameter :: huge32 = huge(0_int32) real(dp), parameter :: hugep1 = real(huge32, dp) + 1.0_dp integer, parameter :: rand_power = 18 integer, parameter :: rand_size = 2**rand_power integer, parameter :: test_size = rand_size*4 integer, parameter :: test_16 = 2**4 integer, parameter :: test_256 = 2**8 integer :: index integer :: lun type(open_hashmap_type) :: map real(dp) :: rand2(2) integer(int32) :: rand_object(rand_size) integer(int8) :: test_8_bits(test_size) open( newunit=lun, file="test_open_maps.txt", access="sequential", & action="write", form="formatted", position="rewind" ) write(lun, '("| ", a17, " | ", a12, " | ", a15, " | ", a10, " |")') & 'Algorithm', 'Process', 'Data Set', 'Time (s)' do index=1, rand_size call random_number(rand2) if (rand2(1) < 0.5_dp) then rand_object(index) = ceiling(-rand2(2)*hugep1, int32) - 1 else rand_object(index) = floor(rand2(2)*hugep1, int32) end if end do test_8_bits(:) = transfer( rand_object, 0_int8, test_size ) ! Test implicit initalization by skipping init call for first test. call input_random_data( map, test_16, 'FNV-1', "16 byte words" ) call test_inquire_data( map, test_16, 'FNV-1', "16 byte words" ) call test_get_data( map, test_16, 'FNV-1', '16 byte words' ) call test_get_all_keys( map, test_16, 'FNV-1', '16 byte words' ) call report_rehash_times( map, fnv_1_hasher, 'FNV-1', '16 byte words' ) call report_hash_statistics( map, 'FNV-1', '16 byte words' ) call report_removal_times( map, test_16, 'FNV-1', '16 byte words' ) call map % init() ! Test default options call input_random_data( map, test_256, 'FNV-1', "256 byte words" ) call test_inquire_data( map, test_256, 'FNV-1', "256 byte words" ) call test_get_data( map, test_256, 'FNV-1', '256 byte words' ) call test_get_all_keys( map, test_256, 'FNV-1', '256 byte words' ) call report_rehash_times( map, fnv_1_hasher, 'FNV-1', '256 byte words' ) call report_hash_statistics( map, 'FNV-1', '256 byte words' ) call report_removal_times( map, test_256, 'FNV-1', '256 byte words' ) call map % init( fnv_1a_hasher, slots_bits=10 ) call input_random_data( map, test_16, 'FNV-1A', "16 byte words" ) call test_inquire_data( map, test_16, 'FNV-1A', "16 byte words" ) call test_get_data( map, test_16, 'FNV-1A', '16 byte words' ) call test_get_all_keys( map, test_16, 'FNV-1A', '16 byte words' ) call report_rehash_times( map, fnv_1a_hasher, 'FNV-1', '16 byte words' ) call report_hash_statistics( map, 'FNV-1A', '16 byte words' ) call report_removal_times( map, test_16, 'FNV-1a', '16 byte words' ) call map % init( fnv_1a_hasher, slots_bits=10 ) call input_random_data( map, test_256, 'FNV-1A', "256 byte words" ) call test_inquire_data( map, test_256, 'FNV-1A', "256 byte words" ) call test_get_data( map, test_256, 'FNV-1A', '256 byte words' ) call test_get_all_keys( map, test_256, 'FNV-1A', '256 byte words' ) call report_rehash_times( map, fnv_1_hasher, 'FNV-1A', '256 byte words' ) call report_hash_statistics( map, 'FNV-1A', '256 byte words' ) call report_removal_times( map, test_256, 'FNV-1A', '256 byte words' ) call map % init( seeded_nmhash32_hasher, slots_bits=10 ) call input_random_data( map, test_16, 'Seeded_Nmhash32', "16 byte words" ) call test_inquire_data( map, test_16, 'Seeded_Nmhash32', "16 byte words" ) call test_get_data( map, test_16, 'Seeded_Nmhash32', '16 byte words' ) call test_get_all_keys( map, test_16, 'Seeded_Nmhash32', '16 byte words' ) call report_rehash_times( map, seeded_nmhash32_hasher, 'Seeded_Nmhash32', & '16 byte words' ) call report_hash_statistics( map, 'Seeded_Nmhash32', '16 byte words' ) call report_removal_times( map, test_16, 'Seeded_Nmhash32', & '16 byte words' ) call map % init( seeded_nmhash32_hasher, slots_bits=10 ) call input_random_data( map, test_256, 'Seeded_Nmhash32', "256 byte words" ) call test_inquire_data( map, test_256, 'Seeded_Nmhash32', "256 byte words" ) call test_get_data( map, test_256, 'Seeded_Nmhash32', '256 byte words' ) call test_get_all_keys( map, test_256, 'Seeded_Nmhash32', '256 byte words' ) call report_rehash_times( map, seeded_nmhash32_hasher, 'Seeded_Nmhash32', & '256 byte words' ) call report_hash_statistics( map, 'Seeded_Nmhash32', '256 byte words' ) call report_removal_times( map, test_256, 'Seeded_Nmhash32', & '256 byte words' ) call map % init( seeded_nmhash32x_hasher, slots_bits=10 ) call input_random_data( map, test_16, 'Seeded_Nmhash32x', "16 byte words" ) call test_inquire_data( map, test_16, 'Seeded_Nmhash32x', "16 byte words" ) call test_get_data( map, test_16, 'Seeded_Nmhash32x', '16 byte words' ) call test_get_all_keys( map, test_16, 'Seeded_Nmhash32x', '16 byte words' ) call report_rehash_times( map, seeded_nmhash32x_hasher, & 'Seeded_Nmhash32x', '16 byte words' ) call report_hash_statistics( map, 'Seeded_Nmhash32x', '16 byte words' ) call report_removal_times( map, test_16, 'Seeded_Nmhash32x', & '16 byte words' ) call map % init( seeded_nmhash32x_hasher, slots_bits=10 ) call input_random_data( map, test_256, 'Seeded_Nmhash32x', & "256 byte words" ) call test_inquire_data( map, test_256, 'Seeded_Nmhash32x', & "256 byte words" ) call test_get_data( map, test_256, 'Seeded_Nmhash32x', '256 byte words' ) call test_get_all_keys( map, test_256, 'Seeded_Nmhash32x', '256 byte words' ) call report_rehash_times( map, seeded_nmhash32x_hasher, & 'Seeded_Nmhash32x', '256 byte words' ) call report_hash_statistics( map, 'Seeded_Nmhash32x', '256 byte words' ) call report_removal_times( map, test_256, 'Seeded_Nmhash32x', & '256 byte words' ) call map % init( seeded_water_hasher, slots_bits=10 ) call input_random_data( map, test_16, 'Seeded_Water', "16 byte words" ) call test_inquire_data( map, test_16, 'Seeded_Water', "16 byte words" ) call test_get_data( map, test_16, 'Seeded_Water', '16 byte words' ) call test_get_all_keys( map, test_16, 'Seeded_Water', '16 byte words' ) call report_rehash_times( map, seeded_water_hasher, & 'Seeded_Water', '16 byte words' ) call report_hash_statistics( map, 'Seeded_Water', '16 byte words' ) call report_removal_times( map, test_16, 'Seeded_Water', & '16 byte words' ) call map % init( seeded_water_hasher, slots_bits=10 ) call input_random_data( map, test_256, 'Seeded_Water', & "256 byte words" ) call test_inquire_data( map, test_256, 'Seeded_Water', & "256 byte words" ) call test_get_data( map, test_256, 'Seeded_Water', '256 byte words' ) call test_get_all_keys( map, test_256, 'Seeded_Water', '256 byte words' ) call report_rehash_times( map, seeded_water_hasher, & 'Seeded_Water', '256 byte words' ) call report_hash_statistics( map, 'Seeded_Water', '256 byte words' ) call report_removal_times( map, test_256, 'Seeded_Water', & '256 byte words' ) contains subroutine input_random_data( map, test_block, hash_name, size_name ) type(open_hashmap_type), intent(inout) :: map integer(int_index), intent(in) :: test_block character(*), intent(in) :: hash_name character(*), intent(in) :: size_name type(dummy_type) :: dummy_val integer :: index2 type(key_type) :: key real :: t1, t2, tdiff logical :: conflict call cpu_time(t1) do index2=1, size(test_8_bits), test_block call set( key, test_8_bits( index2:index2+test_block-1 ) ) dummy_val % value = test_8_bits( index2:index2+test_block-1 ) call map % map_entry( key, dummy_val, conflict ) if (conflict) & error stop "Unable to map entry because of a key conflict." end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Enter data', size_name, tdiff end subroutine input_random_data subroutine test_inquire_data( map, test_block, hash_name, size_name ) type(open_hashmap_type), intent(inout) :: map integer(int_index), intent(in) :: test_block character(*), intent(in) :: hash_name, size_name integer :: index2 logical :: present type(key_type) :: key real :: t1, t2, tdiff call cpu_time(t1) do index2=1, size(test_8_bits), test_block call set( key, test_8_bits( index2:index2+test_block-1 ) ) call map % key_test( key, present ) if (.not. present) & error stop "KEY not found in map KEY_TEST." end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Inquire data', size_name, tdiff end subroutine test_inquire_data subroutine test_get_data( map, test_block, hash_name, size_name ) type(open_hashmap_type), intent(inout) :: map integer(int_index), intent(in) :: test_block character(*), intent(in) :: hash_name, size_name integer :: index2 type(key_type) :: key class(*), allocatable :: data logical :: exists real :: t1, t2, tdiff call cpu_time(t1) do index2=1, size(test_8_bits), test_block call set( key, test_8_bits( index2:index2+test_block-1 ) ) call map % get_other_data( key, data, exists ) if (.not. exists) & error stop "Unable to get data because key not found in map." end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Get data', size_name, tdiff end subroutine test_get_data subroutine test_get_all_keys( map, test_block, hash_name, size_name ) type(open_hashmap_type), intent(inout) :: map integer(int_index), intent(in) :: test_block character(*), intent(in) :: hash_name, size_name integer :: index2, key_idx type(key_type) :: key type(key_type), allocatable :: all_keys(:) real :: t1, t2, tdiff call cpu_time(t1) call map % get_all_keys(all_keys) call cpu_time(t2) tdiff = t2-t1 if (size( all_keys ) /= size( test_8_bits )/test_block) & error stop "Number of keys is different from that of keys in a map." do index2=1, size(test_8_bits), test_block call set( key, test_8_bits( index2:index2+test_block-1 ) ) key_idx = ( index2/test_block ) + 1 if (.not. ( all_keys(key_idx) == key )) & error stop "Invalid value of a key." end do write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Get all keys', size_name, tdiff end subroutine test_get_all_keys subroutine report_rehash_times( map, hasher, hash_name, size_name ) type(open_hashmap_type), intent(inout) :: map procedure(hasher_fun) :: hasher character(*), intent(in) :: hash_name, size_name real :: t1, t2, tdiff call cpu_time(t1) call map % rehash( hasher ) call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Rehash data', size_name, tdiff end subroutine report_rehash_times subroutine report_removal_times( map, test_block, hash_name, size_name ) type(open_hashmap_type), intent(inout) :: map integer(int_index), intent(in) :: test_block character(*), intent(in) :: hash_name, size_name real :: t1, t2, tdiff type(key_type) :: key integer(int_index) :: index2 logical :: existed call cpu_time(t1) do index2=1, size(test_8_bits), test_block call set( key, test_8_bits( index2:index2+test_block-1 ) ) call map % remove(key, existed) if ( .not. existed ) & error stop "Key not found in entry removal." end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Remove data', size_name, tdiff flush(lun) end subroutine report_removal_times subroutine report_hash_statistics( map, hash_name, size_name ) type(open_hashmap_type), intent(inout) :: map character(*), intent(in) :: hash_name, size_name integer(int_depth) :: depth write(lun, *) write(lun, '("Statistics for open hash table with ",' // & 'A, " hasher on ", A, ".")' ) hash_name, size_name write(lun, '("Slots = ", I0)' ) map % num_slots() write(lun, '("Calls = ", I0)' ) map % calls() write(lun, '("Entries = ", I0)' ) map % entries() write(lun, '("Total probes = ", I0)' ) map % map_probes() write(lun, '("Loading = ", ES10.3)' ) map % loading() depth = map % total_depth() write(lun, '("Total depth = ", I0)' ) depth write(lun, '("Relative depth = ", ES10.3)') & real( depth ) / real( map % entries() ) end subroutine report_hash_statistics end program test_open_maps fortran-lang-stdlib-0ede301/test/hashmaps/test_chaining_maps.f900000775000175000017500000003426215135654166025142 0ustar alastairalastairprogram test_chaining_maps !! Test various aspects of the runtime system. !! Running this program may require increasing the stack size to above 48 MBytes !! or decreasing rand_power to 20 or less use stdlib_kinds, only: & dp, & int8, & int32 use stdlib_hashmaps, only : chaining_hashmap_type, int_depth, int_index use stdlib_hashmap_wrappers implicit none type dummy_type integer(int8), allocatable :: value(:) end type dummy_type integer(int32), parameter :: huge32 = huge(0_int32) real(dp), parameter :: hugep1 = real(huge32, dp) + 1.0_dp integer, parameter :: rand_power = 18 integer, parameter :: rand_size = 2**rand_power integer, parameter :: test_size = rand_size*4 integer, parameter :: test_16 = 2**4 integer, parameter :: test_256 = 2**8 integer :: index integer :: lun type(chaining_hashmap_type) :: map real(dp) :: rand2(2) integer(int32) :: rand_object(rand_size) integer(int8) :: test_8_bits(test_size) open( newunit=lun, file="test_chaining_maps.txt", access="sequential", & action="write", form="formatted", position="rewind" ) write(lun, '("| ", a17, " | ", a12, " | ", a15, " | ", a10, " |")') & 'Algorithm', 'Process', 'Data Set', 'Time (s)' do index=1, rand_size call random_number(rand2) if (rand2(1) < 0.5_dp) then rand_object(index) = ceiling(-rand2(2)*hugep1, int32) - 1 else rand_object(index) = floor(rand2(2)*hugep1, int32) end if end do test_8_bits(:) = transfer( rand_object, 0_int8, test_size ) ! Test implicit initalization by skipping init call for first test. call input_random_data( map, test_16, 'FNV-1', "16 byte words" ) call test_inquire_data( map, test_16, 'FNV-1', "16 byte words" ) call test_get_all_keys( map, test_16, 'FNV-1', '16 byte words' ) call test_get_data( map, test_16, 'FNV-1', '16 byte words' ) call report_rehash_times( map, fnv_1_hasher, 'FNV-1', '16 byte words' ) call report_hash_statistics( map, 'FNV-1', '16 byte words' ) call report_removal_times( map, test_16, 'FNV-1', '16 byte words' ) call map % init() ! Test default options call input_random_data( map, test_256, 'FNV-1', "256 byte words" ) call test_inquire_data( map, test_256, 'FNV-1', "256 byte words" ) call test_get_data( map, test_256, 'FNV-1', '256 byte words' ) call test_get_all_keys( map, test_256, 'FNV-1', '256 byte words' ) call report_rehash_times( map, fnv_1_hasher, 'FNV-1', '256 byte words' ) call report_hash_statistics( map, 'FNV-1', '256 byte words' ) call report_removal_times( map, test_256, 'FNV-1', '256 byte words' ) call map % init( fnv_1a_hasher, slots_bits=10 ) call input_random_data( map, test_16, 'FNV-1A', "16 byte words" ) call test_inquire_data( map, test_16, 'FNV-1A', "16 byte words" ) call test_get_data( map, test_16, 'FNV-1A', '16 byte words' ) call test_get_all_keys( map, test_16, 'FNV-1A', '16 byte words' ) call report_rehash_times( map, fnv_1a_hasher, 'FNV-1', '16 byte words' ) call report_hash_statistics( map, 'FNV-1A', '16 byte words' ) call report_removal_times( map, test_16, 'FNV-1a', '16 byte words' ) call map % init( fnv_1a_hasher, slots_bits=10 ) call input_random_data( map, test_256, 'FNV-1A', "256 byte words" ) call test_inquire_data( map, test_256, 'FNV-1A', "256 byte words" ) call test_get_data( map, test_256, 'FNV-1A', '256 byte words' ) call test_get_all_keys( map, test_256, 'FNV-1A', '256 byte words' ) call report_rehash_times( map, fnv_1_hasher, 'FNV-1A', '256 byte words' ) call report_hash_statistics( map, 'FNV-1A', '256 byte words' ) call report_removal_times( map, test_256, 'FNV-1A', '256 byte words' ) call map % init( seeded_nmhash32_hasher, slots_bits=10 ) call input_random_data( map, test_16, 'Seeded_Nmhash32', "16 byte words" ) call test_inquire_data( map, test_16, 'Seeded_Nmhash32', "16 byte words" ) call test_get_data( map, test_16, 'Seeded_Nmhash32', '16 byte words' ) call test_get_all_keys( map, test_16, 'Seeded_Nmhash32', '16 byte words' ) call report_rehash_times( map, seeded_nmhash32_hasher, 'Seeded_Nmhash32', & '16 byte words' ) call report_hash_statistics( map, 'Seeded_Nmhash32', '16 byte words' ) call report_removal_times( map, test_16, 'Seeded_Nmhash32', & '16 byte words' ) call map % init( seeded_nmhash32_hasher, slots_bits=10 ) call input_random_data( map, test_256, 'Seeded_Nmhash32', "256 byte words" ) call test_inquire_data( map, test_256, 'Seeded_Nmhash32', "256 byte words" ) call test_get_data( map, test_256, 'Seeded_Nmhash32', '256 byte words' ) call test_get_all_keys( map, test_256, 'Seeded_Nmhash32', '256 byte words' ) call report_rehash_times( map, seeded_nmhash32_hasher, 'Seeded_Nmhash32', & '256 byte words' ) call report_hash_statistics( map, 'Seeded_Nmhash32', '256 byte words' ) call report_removal_times( map, test_256, 'Seeded_Nmhash32', & '256 byte words' ) call map % init( seeded_nmhash32x_hasher, slots_bits=10 ) call input_random_data( map, test_16, 'Seeded_Nmhash32x', "16 byte words" ) call test_inquire_data( map, test_16, 'Seeded_Nmhash32x', "16 byte words" ) call test_get_data( map, test_16, 'Seeded_Nmhash32x', '16 byte words' ) call test_get_all_keys( map, test_16, 'Seeded_Nmhash32x', '16 byte words' ) call report_rehash_times( map, seeded_nmhash32x_hasher, & 'Seeded_Nmhash32x', '16 byte words' ) call report_hash_statistics( map, 'Seeded_Nmhash32x', '16 byte words' ) call report_removal_times( map, test_16, 'Seeded_Nmhash32x', & '16 byte words' ) call map % init( seeded_nmhash32x_hasher, slots_bits=10 ) call input_random_data( map, test_256, 'Seeded_Nmhash32x', & "256 byte words" ) call test_inquire_data( map, test_256, 'Seeded_Nmhash32x', & "256 byte words" ) call test_get_data( map, test_256, 'Seeded_Nmhash32x', '256 byte words' ) call test_get_all_keys( map, test_256, 'Seeded_Nmhash32x', '256 byte words' ) call report_rehash_times( map, seeded_nmhash32x_hasher, & 'Seeded_Nmhash32x', '256 byte words' ) call report_hash_statistics( map, 'Seeded_Nmhash32x', '256 byte words' ) call report_removal_times( map, test_256, 'Seeded_Nmhash32x', & '256 byte words' ) call map % init( seeded_water_hasher, slots_bits=10 ) call input_random_data( map, test_16, 'Seeded_Water', "16 byte words" ) call test_inquire_data( map, test_16, 'Seeded_Water', "16 byte words" ) call test_get_data( map, test_16, 'Seeded_Water', '16 byte words' ) call test_get_all_keys( map, test_16, 'Seeded_Water', '16 byte words' ) call report_rehash_times( map, seeded_water_hasher, & 'Seeded_Water', '16 byte words' ) call report_hash_statistics( map, 'Seeded_Water', '16 byte words' ) call report_removal_times( map, test_16, 'Seeded_Water', & '16 byte words' ) call map % init( seeded_water_hasher, slots_bits=10 ) call input_random_data( map, test_256, 'Seeded_Water', & "256 byte words" ) call test_inquire_data( map, test_256, 'Seeded_Water', & "256 byte words" ) call test_get_data( map, test_256, 'Seeded_Water', '256 byte words' ) call test_get_all_keys( map, test_256, 'Seeded_Water', '256 byte words' ) call report_rehash_times( map, seeded_water_hasher, & 'Seeded_Water', '256 byte words' ) call report_hash_statistics( map, 'Seeded_Water', '256 byte words' ) call report_removal_times( map, test_256, 'Seeded_Water', & '256 byte words' ) contains subroutine input_random_data( map, test_block, hash_name, size_name ) type(chaining_hashmap_type), intent(inout) :: map integer(int_index), intent(in) :: test_block character(*), intent(in) :: hash_name character(*), intent(in) :: size_name type(dummy_type) :: dummy_val integer :: index2 type(key_type) :: key real :: t1, t2, tdiff logical :: conflict call cpu_time(t1) do index2=1, size(test_8_bits), test_block call set( key, test_8_bits( index2:index2+test_block-1 ) ) dummy_val % value = test_8_bits( index2:index2+test_block-1 ) call map % map_entry( key, dummy_val, conflict ) if (conflict) & error stop "Unable to map entry because of a key conflict." end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Enter data', size_name, tdiff end subroutine input_random_data subroutine test_inquire_data( map, test_block, hash_name, size_name ) type(chaining_hashmap_type), intent(inout) :: map integer(int_index), intent(in) :: test_block character(*), intent(in) :: hash_name, size_name integer :: index2 logical :: present type(key_type) :: key real :: t1, t2, tdiff call cpu_time(t1) do index2=1, size(test_8_bits), test_block call set( key, test_8_bits( index2:index2+test_block-1 ) ) call map % key_test( key, present ) if (.not. present) & error stop "KEY not found in map KEY_TEST." end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Inquire data', size_name, tdiff end subroutine test_inquire_data subroutine test_get_data( map, test_block, hash_name, size_name ) type(chaining_hashmap_type), intent(inout) :: map integer(int_index), intent(in) :: test_block character(*), intent(in) :: hash_name, size_name integer :: index2 type(key_type) :: key class(*), allocatable :: data logical :: exists real :: t1, t2, tdiff call cpu_time(t1) do index2=1, size(test_8_bits), test_block call set( key, test_8_bits( index2:index2+test_block-1 ) ) call map % get_other_data( key, data, exists ) if (.not. exists) & error stop "Unable to get data because key not found in map." end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Get data', size_name, tdiff end subroutine test_get_data subroutine test_get_all_keys( map, test_block, hash_name, size_name ) type(chaining_hashmap_type), intent(inout) :: map integer(int_index), intent(in) :: test_block character(*), intent(in) :: hash_name, size_name integer :: index2, key_idx type(key_type) :: key type(key_type), allocatable :: all_keys(:) real :: t1, t2, tdiff call cpu_time(t1) call map % get_all_keys(all_keys) call cpu_time(t2) tdiff = t2-t1 if (size( all_keys ) /= size( test_8_bits )/test_block) & error stop "Number of keys is different from that of keys in a map." do index2=1, size(test_8_bits), test_block call set( key, test_8_bits( index2:index2+test_block-1 ) ) key_idx = ( index2/test_block ) + 1 if (.not. ( all_keys(key_idx) == key )) & error stop "Invalid value of a key." end do write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Get all keys', size_name, tdiff end subroutine test_get_all_keys subroutine report_rehash_times( map, hasher, hash_name, size_name ) type(chaining_hashmap_type), intent(inout) :: map procedure(hasher_fun) :: hasher character(*), intent(in) :: hash_name, size_name real :: t1, t2, tdiff call cpu_time(t1) call map % rehash( hasher ) call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Rehash data', size_name, tdiff end subroutine report_rehash_times subroutine report_removal_times( map, test_block, hash_name, size_name ) type(chaining_hashmap_type), intent(inout) :: map integer(int_index), intent(in) :: test_block character(*), intent(in) :: hash_name, size_name real :: t1, t2, tdiff type(key_type) :: key integer(int_index) :: index2 logical :: existed call cpu_time(t1) do index2=1, size(test_8_bits), test_block call set( key, test_8_bits( index2:index2+test_block-1 ) ) call map % remove(key, existed) if ( .not. existed ) & error stop "Key not found in entry removal." end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a18, " | ", a12, " | ", a15, " | ", f10.5, " |")') & trim(hash_name), 'Remove data', size_name, tdiff flush(lun) end subroutine report_removal_times subroutine report_hash_statistics( map, hash_name, size_name ) type(chaining_hashmap_type), intent(inout) :: map character(*), intent(in) :: hash_name, size_name integer(int_depth) :: depth write(lun, *) write(lun, '("Statistics for chaining hash table with ",' // & 'A, " hasher on ", A, ".")' ) hash_name, size_name write(lun, '("Slots = ", I0)' ) map % num_slots() write(lun, '("Calls = ", I0)' ) map % calls() write(lun, '("Entries = ", I0)' ) map % entries() write(lun, '("Total probes = ", I0)' ) map % map_probes() write(lun, '("Loading = ", ES10.3)' ) map % loading() depth = map % total_depth() write(lun, '("Total depth = ", I0)' ) depth write(lun, '("Relative depth = ", ES10.3)') & real( depth ) / real( map % entries() ) end subroutine report_hash_statistics end program test_chaining_maps fortran-lang-stdlib-0ede301/test/hashmaps/Makefile.manual0000775000175000017500000000015115135654166023665 0ustar alastairalastairPROGS_SRC = test_chaining_maps.f90 \ test_open_maps.f90 include ../Makefile.manual.test.mk fortran-lang-stdlib-0ede301/test/hashmaps/test_maps.fypp0000664000175000017500000006251515135654166023661 0ustar alastairalastair#: include "common.fypp" #:set HASH_NAME = ["fnv_1_hasher", "fnv_1a_hasher", "seeded_nmhash32_hasher", "seeded_nmhash32x_hasher", "seeded_water_hasher"] #:set SIZE_NAME = ["16", "256"] module test_stdlib_chaining_maps !! Test various aspects of the runtime system. !! Running this program may require increasing the stack size to above 48 MBytes !! or decreasing rand_power to 20 or less use testdrive, only : new_unittest, unittest_type, error_type, check use :: stdlib_kinds, only : dp, int8, int32 use stdlib_hashmaps, only : chaining_hashmap_type, int_depth, int_index use stdlib_hashmap_wrappers implicit none private type dummy_type integer(int8), allocatable :: value(:) end type dummy_type integer(int32), parameter :: huge32 = huge(0_int32) real(dp), parameter :: hugep1 = real(huge32, dp) + 1.0_dp integer, parameter :: rand_power = 18 integer, parameter :: rand_size = 2**rand_power integer, parameter :: test_size = rand_size*4 integer, parameter :: test_16 = 2**4 integer, parameter :: test_256 = 2**8 ! key_type = 5 to support int8 and int32 key types tested. Can be ! increased to generate additional unique int8 vectors additional key types. integer, parameter :: key_types = 5 character(len=16) :: char_size public :: collect_stdlib_chaining_maps contains !> Collect all exported unit tests subroutine collect_stdlib_chaining_maps(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("chaining-maps-fnv_1_hasher-16-byte-words", test_fnv_1_hasher_16_byte_words) & #:for hash_ in HASH_NAME #:for size_ in SIZE_NAME , new_unittest("chaining-maps-${hash_}$-${size_}$-byte-words", test_${hash_}$_${size_}$_byte_words) & #:endfor #:endfor , new_unittest("chaining-maps-removal-spec", test_removal_spec) & ] end subroutine collect_stdlib_chaining_maps #:for hash_ in HASH_NAME #:for size_ in SIZE_NAME subroutine test_${hash_}$_${size_}$_byte_words(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(chaining_hashmap_type) :: map integer(int8) :: test_8_bits(test_size,key_types) call generate_vector(test_8_bits) call map % init( ${hash_}$, slots_bits=10 ) call test_input_random_data(error, map, test_8_bits, test_${size_}$) if (allocated(error)) return call test_inquire_data(error, map, test_8_bits, test_${size_}$) if (allocated(error)) return call test_get_data(error, map, test_8_bits, test_${size_}$) if (allocated(error)) return call test_removal(error, map, test_8_bits, test_${size_}$) if (allocated(error)) return end subroutine #:endfor #:endfor subroutine generate_vector(test_8_bits) integer(int8), intent(out) :: test_8_bits(test_size, key_types) integer :: index, key_type real(dp) :: rand2(2) integer(int32) :: rand_object(rand_size) ! Generate a unique int8 vector for each key type tested to avoid ! dupilcate keys and mapping conflicts. do key_type = 1, key_types do index=1, rand_size call random_number(rand2) if (rand2(1) < 0.5_dp) then rand_object(index) = ceiling(-rand2(2)*hugep1, int32) - 1 else rand_object(index) = floor(rand2(2)*hugep1, int32) end if end do test_8_bits(:,key_type) = transfer( rand_object, 0_int8, test_size ) end do end subroutine subroutine test_input_random_data(error, map, test_8_bits, test_block) type(error_type), allocatable, intent(out) :: error type(chaining_hashmap_type), intent(inout) :: map integer(int8), intent(in) :: test_8_bits(test_size, key_types) integer(int_index), intent(in) :: test_block type(dummy_type) :: dummy_val integer :: index2 type(key_type) :: key logical :: conflict do index2=1, test_size, test_block ! Test base int8 key interface call set( key, test_8_bits( index2:index2+test_block-1, 1 ) ) call map % map_entry( key, dummy_val, conflict ) call check(error, .not.conflict, "Unable to map int8 entry because of a key conflict.") ! Test int32 key interface ! Use transfer to create int32 vector from generated int8 vector. call set( key, transfer( test_8_bits( index2:index2+test_block-1, 2 ), [0_int32] ) ) call map % map_entry( key, dummy_val, conflict ) call check(error, .not.conflict, "Unable to map chaining int32 entry because of a key conflict.") ! Test int8 key generic interface call map % map_entry( test_8_bits( index2:index2+test_block-1, 3 ), dummy_val, conflict ) call check(error, .not.conflict, "Unable to map chaining int8 generic interface") ! Test int32 key generic interface call map % map_entry( transfer( test_8_bits( index2:index2+test_block-1, 4 ), [0_int32] ), dummy_val, conflict ) call check(error, .not.conflict, "Unable to map chaining int32 generic interface") ! Test char key generic interface call map % map_entry( transfer( test_8_bits( index2:index2+test_block-1, 5 ), char_size ), dummy_val, conflict ) call check(error, .not.conflict, "Unable to map chaining character generic interface") if (allocated(error)) return end do end subroutine subroutine test_inquire_data(error, map, test_8_bits, test_block) type(error_type), allocatable, intent(out) :: error type(chaining_hashmap_type), intent(inout) :: map integer(int8), intent(in) :: test_8_bits(test_size, key_types) integer(int_index), intent(in) :: test_block integer :: index2 logical :: present type(key_type) :: key do index2=1, test_size, test_block call set( key, test_8_bits( index2:index2+test_block-1, 1 ) ) call map % key_test( key, present ) call check(error, present, "Int8 KEY not found in map KEY_TEST.") call set( key, transfer( test_8_bits( index2:index2+test_block-1, 2 ), [0_int32] ) ) call map % key_test( key, present ) call check(error, present, "Int32 KEY not found in map KEY_TEST.") call map % key_test( test_8_bits( index2:index2+test_block-1, 3 ), present ) call check(error, present, "Int8 KEY generic interface not found in map KEY_TEST.") call map % key_test( transfer( test_8_bits( index2:index2+test_block-1, 4 ), [0_int32] ), present ) call check(error, present, "Int32 KEY generic interface not found in map KEY_TEST.") call map % key_test( transfer( test_8_bits( index2:index2+test_block-1, 5 ), char_size ), present ) call check(error, present, "Char KEY generic interface not found in map KEY_TEST.") if (allocated(error)) return end do end subroutine subroutine test_get_data(error, map, test_8_bits, test_block) type(error_type), allocatable, intent(out) :: error type(chaining_hashmap_type), intent(inout) :: map integer(int8), intent(in) :: test_8_bits(test_size, key_types) integer(int_index), intent(in) :: test_block integer :: index2 type(key_type) :: key class(*), allocatable :: data logical :: exists do index2=1, test_size, test_block call set( key, test_8_bits( index2:index2+test_block-1, 1 ) ) call map % get_other_data( key, data, exists ) call check(error, exists, "Unable to get data because int8 key not found in map.") call set( key, transfer( test_8_bits( index2:index2+test_block-1, 2 ), [0_int32] ) ) call map % get_other_data( key, data, exists ) call check(error, exists, "Unable to get data because int32 key not found in map.") call map % get_other_data( test_8_bits( index2:index2+test_block-1, 3 ), data, exists ) call check(error, exists, "Unable to get data because int8 generic interface key not found in map.") call map % get_other_data( transfer( test_8_bits( index2:index2+test_block-1, 4 ), [0_int32] ) , data, exists ) call check(error, exists, "Unable to get data because int32 generic interface key not found in map.") call map % get_other_data( transfer( test_8_bits( index2:index2+test_block-1, 5 ), char_size ) , data, exists ) call check(error, exists, "Unable to get data because character generic interface key not found in map.") end do end subroutine subroutine test_removal(error, map, test_8_bits, test_block) type(error_type), allocatable, intent(out) :: error type(chaining_hashmap_type), intent(inout) :: map integer(int8), intent(in) :: test_8_bits(test_size, key_types) integer(int_index), intent(in) :: test_block type(key_type) :: key integer(int_index) :: index2 logical :: existed do index2=1, test_size, test_block call set( key, test_8_bits( index2:index2+test_block-1, 1 ) ) call map % remove(key, existed) call check(error, existed, "Int8 Key not found in entry removal.") call set( key, transfer( test_8_bits( index2:index2+test_block-1, 2 ), [0_int32] ) ) call map % remove(key, existed) call check(error, existed, "Int32 Key not found in entry removal.") call map % remove(test_8_bits( index2:index2+test_block-1, 3 ), existed) call check(error, existed, "Int8 Key generic interface not found in entry removal.") call map % remove(transfer( test_8_bits( index2:index2+test_block-1, 4 ), [0_int32] ), existed) call check(error, existed, "Int32 Key generic interface not found in entry removal.") call map % remove(transfer( test_8_bits( index2:index2+test_block-1, 5 ), char_size ), existed) call check(error, existed, "Character Key generic interface not found in entry removal.") end do end subroutine subroutine test_removal_spec(error) !! Test following code provided by @jannisteunissen !! https://github.com/fortran-lang/stdlib/issues/785 type(error_type), allocatable, intent(out) :: error type(chaining_hashmap_type) :: map type(key_type) :: key integer, parameter :: n_max = 500 integer :: n integer, allocatable :: key_counts(:) integer, allocatable :: seed(:) integer(int8) :: int32_int8(4) integer(int32) :: keys(n_max) real(dp) :: r_uniform(n_max) logical :: existed, present call random_seed(size = n) allocate(seed(n), source = 123456) call random_seed(put = seed) call random_number(r_uniform) keys = nint(r_uniform * n_max * 0.25_dp) call map%init(fnv_1_hasher, slots_bits=10) do n = 1, n_max call set(key, transfer(keys(n), int32_int8)) call map%key_test(key, present) if (present) then call map%remove(key, existed) call check(error, existed, "chaining-removal-spec: Key not found in entry removal.") return else call map%map_entry(key) end if end do ! Count number of keys that occur an odd number of times allocate(key_counts(minval(keys):maxval(keys)), source = 0) do n = 1, n_max key_counts(keys(n)) = key_counts(keys(n)) + 1 end do n = sum(iand(key_counts, 1)) call check(error, map%entries(), n, & "chaining-removal-spec: Number of expected keys and entries are different.") return end subroutine end module module test_stdlib_open_maps !! Test various aspects of the runtime system. !! Running this program may require increasing the stack size to above 48 MBytes !! or decreasing rand_power to 20 or less use testdrive, only : new_unittest, unittest_type, error_type, check use :: stdlib_kinds, only : dp, int8, int32 use stdlib_hashmaps, only : open_hashmap_type, int_depth, int_index use stdlib_hashmap_wrappers implicit none private type dummy_type integer(int8), allocatable :: value(:) end type dummy_type integer(int32), parameter :: huge32 = huge(0_int32) real(dp), parameter :: hugep1 = real(huge32, dp) + 1.0_dp integer, parameter :: rand_power = 18 integer, parameter :: rand_size = 2**rand_power integer, parameter :: test_size = rand_size*4 integer, parameter :: test_16 = 2**4 integer, parameter :: test_256 = 2**8 ! key_type = 5 to support int8 and int32 key types tested. Can be ! increased to generate additional unique int8 vectors additional key types. integer, parameter :: key_types = 5 character(len=16) :: char_size public :: collect_stdlib_open_maps contains !> Collect all exported unit tests subroutine collect_stdlib_open_maps(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("open-maps-fnv_1_hasher-16-byte-words", test_fnv_1_hasher_16_byte_words) & #:for hash_ in HASH_NAME #:for size_ in SIZE_NAME , new_unittest("open-maps-${hash_}$-${size_}$-byte-words", test_${hash_}$_${size_}$_byte_words) & #:endfor #:endfor , new_unittest("open-maps-removal-spec", test_removal_spec) & ] end subroutine collect_stdlib_open_maps #:for hash_ in HASH_NAME #:for size_ in SIZE_NAME subroutine test_${hash_}$_${size_}$_byte_words(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(open_hashmap_type) :: map integer(int8) :: test_8_bits(test_size,key_types) call generate_vector(test_8_bits) call map % init( ${hash_}$, slots_bits=10 ) call test_input_random_data(error, map, test_8_bits, test_${size_}$) if (allocated(error)) return call test_inquire_data(error, map, test_8_bits, test_${size_}$) if (allocated(error)) return call test_get_data(error, map, test_8_bits, test_${size_}$) if (allocated(error)) return call test_removal(error, map, test_8_bits, test_${size_}$) if (allocated(error)) return end subroutine #:endfor #:endfor subroutine generate_vector(test_8_bits) integer(int8), intent(out) :: test_8_bits(test_size, key_types) integer :: index, key_type real(dp) :: rand2(2) integer(int32) :: rand_object(rand_size) ! Generate a unique int8 vector for each key type tested to avoid ! dupilcate keys and mapping conflicts. do key_type = 1, key_types do index=1, rand_size call random_number(rand2) if (rand2(1) < 0.5_dp) then rand_object(index) = ceiling(-rand2(2)*hugep1, int32) - 1 else rand_object(index) = floor(rand2(2)*hugep1, int32) end if end do test_8_bits(:,key_type) = transfer( rand_object, 0_int8, test_size ) enddo end subroutine subroutine test_input_random_data(error, map, test_8_bits, test_block) type(error_type), allocatable, intent(out) :: error type(open_hashmap_type), intent(inout) :: map integer(int8), intent(in) :: test_8_bits(test_size, key_types) integer(int_index), intent(in) :: test_block type(dummy_type) :: dummy_val integer :: index2 type(key_type) :: key logical :: conflict do index2=1, test_size, test_block ! Test base int8 key interface call set( key, test_8_bits( index2:index2+test_block-1, 1 ) ) call map % map_entry( key, dummy_val, conflict ) call check(error, .not.conflict, "Unable to map int8 entry because of a key conflict.") ! Test int32 key interface ! Use transfer to create int32 vector from generated int8 vector. call set( key, transfer( test_8_bits( index2:index2+test_block-1, 2 ), [0_int32] ) ) call map % map_entry( key, dummy_val, conflict ) call check(error, .not.conflict, "Unable to map int32 entry because of a key conflict.") ! Test int8 generic key interface call map % map_entry( test_8_bits( index2:index2+test_block-1, 3 ), dummy_val, conflict ) call check(error, .not.conflict, "Unable to map int8 generic key interface entry because of a key conflict.") ! Test int32 key generic interface call map % map_entry( transfer( test_8_bits( index2:index2+test_block-1, 4 ), [0_int32] ), dummy_val, conflict ) call check(error, .not.conflict, "Unable to map open int32 generic key interface entry because of a key conflict.") ! Test character key generic interface call map % map_entry( transfer( test_8_bits( index2:index2+test_block-1, 5 ), char_size ), dummy_val, conflict ) call check(error, .not.conflict, "Unable to map open character generic key interface entry because of a key conflict.") if (allocated(error)) return end do end subroutine subroutine test_inquire_data(error, map, test_8_bits, test_block) type(error_type), allocatable, intent(out) :: error type(open_hashmap_type), intent(inout) :: map integer(int8), intent(in) :: test_8_bits(test_size, key_types) integer(int_index), intent(in) :: test_block integer :: index2 logical :: present type(key_type) :: key do index2=1, test_size, test_block call set( key, test_8_bits( index2:index2+test_block-1, 1 ) ) call map % key_test( key, present ) call check(error, present, "Int8 KEY not found in map KEY_TEST.") call set( key, transfer( test_8_bits( index2:index2+test_block-1, 2 ), [0_int32] ) ) call map % key_test( key, present ) call check(error, present, "Int32 KEY not found in map KEY_TEST.") call map % key_test( test_8_bits( index2:index2+test_block-1, 3 ), present ) call check(error, present, "Int8 KEY generic interface not found in map KEY_TEST.") call map % key_test( transfer( test_8_bits( index2:index2+test_block-1, 4 ), [0_int32] ), present ) call check(error, present, "Int32 KEY generic interface not found in map KEY_TEST.") call map % key_test( transfer( test_8_bits( index2:index2+test_block-1, 5 ), char_size ), present ) call check(error, present, "Character KEY generic interface not found in map KEY_TEST.") if (allocated(error)) return end do end subroutine subroutine test_get_data(error, map, test_8_bits, test_block) type(error_type), allocatable, intent(out) :: error type(open_hashmap_type), intent(inout) :: map integer(int8), intent(in) :: test_8_bits(test_size, key_types) integer(int_index), intent(in) :: test_block integer :: index2 type(key_type) :: key class(*), allocatable :: data logical :: exists do index2=1, test_size, test_block call set( key, test_8_bits( index2:index2+test_block-1, 1 ) ) call map % get_other_data( key, data, exists ) call check(error, exists, "Unable to get data because int8 key not found in map.") call set( key, transfer( test_8_bits( index2:index2+test_block-1, 2 ), [0_int32] ) ) call map % get_other_data( key, data, exists ) call check(error, exists, "Unable to get data because int32 key not found in map.") call map % get_other_data( test_8_bits( index2:index2+test_block-1, 3 ), data, exists ) call check(error, exists, "Unable to get data because int8 generic interface key not found in map.") call map % get_other_data( transfer( test_8_bits( index2:index2+test_block-1, 4 ), [0_int32] ), data, exists ) call check(error, exists, "Unable to get data because int32 generic interface key not found in map.") call map % get_other_data( transfer( test_8_bits( index2:index2+test_block-1, 5 ), char_size ), data, exists ) call check(error, exists, "Unable to get data because character generic interface key not found in map.") end do end subroutine subroutine test_removal(error, map, test_8_bits, test_block) type(error_type), allocatable, intent(out) :: error type(open_hashmap_type), intent(inout) :: map integer(int8), intent(in) :: test_8_bits(test_size, key_types) integer(int_index), intent(in) :: test_block type(key_type) :: key integer(int_index) :: index2 logical :: existed do index2=1, test_size, test_block call set( key, test_8_bits( index2:index2+test_block-1, 1 ) ) call map % remove(key, existed) call check(error, existed, "Int8 Key not found in entry removal.") call set( key, transfer( test_8_bits( index2:index2+test_block-1, 2 ), [0_int32] ) ) call map % remove(key, existed) call check(error, existed, "Int32 Key not found in entry removal.") call map % remove( test_8_bits( index2:index2+test_block-1, 3 ), existed) call check(error, existed, "Int8 Key generic interface not found in entry removal.") call map % remove(transfer( test_8_bits( index2:index2+test_block-1, 4 ), [0_int32] ), existed) call check(error, existed, "Int32 Key generic interface not found in entry removal.") call map % remove(transfer( test_8_bits( index2:index2+test_block-1, 5 ), char_size ), existed) call check(error, existed, "Character Key generic interface not found in entry removal.") end do end subroutine subroutine test_removal_spec(error) !! Test following code provided by @jannisteunissen !! https://github.com/fortran-lang/stdlib/issues/785 type(error_type), allocatable, intent(out) :: error type(open_hashmap_type) :: map type(key_type) :: key integer, parameter :: n_max = 500 integer :: n integer, allocatable :: key_counts(:) integer, allocatable :: seed(:) integer(int8) :: int32_int8(4) integer(int32) :: keys(n_max) real(dp) :: r_uniform(n_max) logical :: existed, present call random_seed(size = n) allocate(seed(n), source = 123456) call random_seed(put = seed) call random_number(r_uniform) keys = nint(r_uniform * n_max * 0.25_dp) call map%init(fnv_1_hasher, slots_bits=10) do n = 1, n_max call set(key, transfer(keys(n), int32_int8)) call map%key_test(key, present) if (present) then call map%remove(key, existed) call check(error, existed, "open-removal-spec: Key not found in entry removal.") return else call map%map_entry(key) end if end do ! Count number of keys that occur an odd number of times allocate(key_counts(minval(keys):maxval(keys)), source = 0) do n = 1, n_max key_counts(keys(n)) = key_counts(keys(n)) + 1 end do n = sum(iand(key_counts, 1)) call check(error, map%entries(), n, & "open-removal-spec: Number of expected keys and entries are different.") return end subroutine end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_stdlib_open_maps, only : collect_stdlib_open_maps use test_stdlib_chaining_maps, only : collect_stdlib_chaining_maps implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("stdlib-open-maps", collect_stdlib_open_maps) & , new_testsuite("stdlib-chaining-maps", collect_stdlib_chaining_maps) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/sorting/0000775000175000017500000000000015135654166020632 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/sorting/CMakeLists.txt0000664000175000017500000000015615135654166023374 0ustar alastairalastairset( fppFiles "test_sorting.fypp" ) fypp_f90pp("${fyppFlags}" "${fppFiles}" outFiles) ADDTESTPP(sorting) fortran-lang-stdlib-0ede301/test/sorting/test_sorting.fypp0000664000175000017500000023374415135654166024273 0ustar alastairalastair#include "macros.inc" #:include "common.fypp" #:set INT_TYPES_ALT_NAME = list(zip(INT_TYPES, INT_TYPES, INT_KINDS)) #:set REAL_TYPES_ALT_NAME = list(zip(REAL_TYPES, REAL_TYPES, REAL_KINDS)) #:set INT_INDEX_TYPES_ALT_NAME = list(zip(["int_index", "int_index_low"], ["integer(int_index)", "integer(int_index_low)"], ["default", "low"])) module test_sorting use, intrinsic :: iso_fortran_env, only: compiler_version, error_unit use stdlib_kinds, only: int8, int16, int32, int64, dp, sp, xdp, qp use stdlib_sorting, only: sort, sort_index, sort_adjoint, ord_sort, radix_sort, int_index, int_index_low use stdlib_string_type, only: string_type, assignment(=), operator(>), & operator(<), write(formatted) #if STDLIB_BITSETS use stdlib_bitsets, only: bitset_64, bitset_large, & assignment(=), operator(>), operator(<) #endif use testdrive, only: new_unittest, unittest_type, error_type, check implicit none integer(int32), parameter :: test_power = 16 integer(int32), parameter :: char_set_size = 16 integer(int32), parameter :: test_size = 2_int32**test_power integer(int32), parameter :: char_size = char_set_size**4 integer(int32), parameter :: string_size = char_set_size**3 #if STDLIB_BITSETS integer(int32), parameter :: bitset_size = char_set_size**3 #endif integer(int32), parameter :: block_size = test_size/6 integer, parameter :: repeat = 1 integer(int32) :: & blocks(0:test_size-1), & decrease(0:test_size-1), & identical(0:test_size-1), & increase(0:test_size-1), & rand0(0:test_size-1), & rand1(0:test_size-1), & rand2(0:test_size-1), & rand3(0:test_size-1), & rand10(0:test_size-1) real(sp) :: rand_r32(0:test_size-1) character(len=4) :: & char_decrease(0:char_size-1), & char_increase(0:char_size-1), & char_rand(0:char_size-1) type(string_type) :: & string_decrease(0:string_size-1), & string_increase(0:string_size-1), & string_rand(0:string_size-1) #if STDLIB_BITSETS type(bitset_large) :: & bitsetl_decrease(0:bitset_size-1), & bitsetl_increase(0:bitset_size-1), & bitsetl_rand(0:bitset_size-1) type(bitset_64) :: & bitset64_decrease(0:bitset_size-1), & bitset64_increase(0:bitset_size-1), & bitset64_rand(0:bitset_size-1) #endif integer(int32) :: dummy(0:test_size-1) real(sp) :: real_dummy(0:test_size-1) character(len=4) :: char_dummy(0:char_size-1) type(string_type) :: string_dummy(0:string_size-1) #if STDLIB_BITSETS type(bitset_large) :: bitsetl_dummy(0:bitset_size-1) type(bitset_64) :: bitset64_dummy(0:bitset_size-1) #endif integer(int_index) :: index_default(0:max(test_size, char_size, string_size)-1) integer(int_index_low) :: index_low(0:max(test_size, char_size, string_size)-1) integer(int32) :: work(0:test_size/2-1) character(len=4) :: char_work(0:char_size/2-1) type(string_type) :: string_work(0:string_size/2-1) #if STDLIB_BITSETS type(bitset_large) :: bitsetl_work(0:bitset_size/2-1) type(bitset_64) :: bitset64_work(0:bitset_size/2-1) #endif integer(int_index) :: iwork_default(0:max(test_size, char_size, & string_size)/2-1) integer(int_index_low) :: iwork_low(0:max(test_size, char_size, & string_size)/2-1) integer :: count, i, index1, index2, j, k, l, temp real(sp) :: arand, brand character(*), parameter :: filename = 'test_sorting.txt' integer :: lun character(len=4) :: char_temp type(string_type) :: string_temp #if STDLIB_BITSETS type(bitset_large) :: bitsetl_temp type(bitset_64) :: bitset64_temp #endif logical :: ltest, ldummy character(32) :: bin32 character(64) :: bin64 contains !> Collect all exported unit tests subroutine collect_sorting(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest('char_ord_sorts', test_char_ord_sorts), & new_unittest('string_ord_sorts', test_string_ord_sorts), & #if STDLIB_BITSETS new_unittest('bitset_large_ord_sorts', test_bitsetl_ord_sorts), & new_unittest('bitset_64_ord_sorts', test_bitset64_ord_sorts), & #endif new_unittest('int_radix_sorts', test_int_radix_sorts), & new_unittest('real_radix_sorts', test_real_radix_sorts), & new_unittest('int_sorts', test_int_sorts), & new_unittest('char_sorts', test_char_sorts), & new_unittest('string_sorts', test_string_sorts), & #if STDLIB_BITSETS new_unittest('bitset_large_sorts', test_bitsetl_sorts), & new_unittest('bitset_64_sorts', test_bitset64_sorts), & #endif #:for ki, ti, namei in INT_INDEX_TYPES_ALT_NAME new_unittest('int_sort_indexes_${namei}$', test_int_sort_indexes_${namei}$), & new_unittest('char_sort_indexes_${namei}$', test_char_sort_indexes_${namei}$), & new_unittest('string_sort_indexes_${namei}$', test_string_sort_indexes_${namei}$), & #if STDLIB_BITSETS new_unittest('bitset_large_sort_indexes_${namei}$', test_bitsetl_sort_indexes_${namei}$), & new_unittest('bitset_64_sort_indexes_${namei}$', test_bitset64_sort_indexes_${namei}$), & #endif #:endfor #:for ki, ti, namei in INT_TYPES_ALT_NAME new_unittest('int_sort_adjointes_${namei}$', test_int_sort_adjointes_${namei}$), & new_unittest('char_sort_adjointes_${namei}$', test_char_sort_adjointes_${namei}$), & new_unittest('string_sort_adjointes_${namei}$', test_string_sort_adjointes_${namei}$), & #if STDLIB_BITSETS new_unittest('bitset_large_sort_adjointes_${namei}$', test_bitsetl_sort_adjointes_${namei}$), & new_unittest('bitset_64_sort_adjointes_${namei}$', test_bitset64_sort_adjointes_${namei}$), & #endif #:endfor #:for ki, ti, namei in REAL_TYPES_ALT_NAME new_unittest('real_sort_adjointes_${namei}$', test_real_sort_adjointes_${namei}$), & #:endfor new_unittest('int_ord_sorts', test_int_ord_sorts) & ] end subroutine collect_sorting subroutine initialize_tests() ! Create the test arrays identical(:) = 10 do i=0, test_size-1 increase(i) = i decrease(i) = test_size - 1 - i call random_number( arand ) rand0(i) = int( floor( 4 * arand * test_size ), kind=int32 ) rand1(i) = int( floor( arand * test_size / 4 ), kind=int32 ) end do blocks(:) = increase(:) blocks(0:block_size-1) = increase(4*block_size:5*block_size-1) blocks(block_size:2*block_size-1) = increase(0:block_size-1) blocks(2*block_size:3*block_size-1) = increase(2*block_size:3*block_size-1) blocks(3*block_size:4*block_size-1) = increase(block_size:2*block_size-1) blocks(4*block_size:5*block_size-1) = increase(3*block_size:4*block_size-1) rand2(:) = increase(:) do i=0, test_size-1 call random_number( arand ) index1 = int( floor( arand * test_size ), kind=int32 ) temp = rand2(i) rand2(i) = rand2(index1) rand2(index1) = temp end do rand3(:) = increase(:) do i=0, 2 call random_number( arand ) call random_number( brand ) index1 = int( floor( arand * test_size ), kind=int32 ) index2 = int( floor( brand * test_size ), kind=int32 ) temp = rand3(index1) rand3(index1) = rand3(index2) rand3(index2) = temp end do rand10(:) = increase(:) do i=test_size-10, test_size-1 call random_number( arand ) rand10(i) = int( floor( arand * test_size ), kind=int32 ) end do call random_number(rand_r32) rand_r32 = rand_r32 - 0.5 ! to test both positive and negative numbers count = 0 do i=0, char_set_size-1 do j=0, char_set_size-1 do k=0, char_set_size-1 do l=0, char_set_size-1 char_increase(count) = achar(97+i) // achar(97+j) // & achar(97+k) // achar(97+l) count = count + 1 end do end do end do end do do i=0, char_size-1 char_decrease(char_size-1-i) = char_increase(i) end do char_rand(:) = char_increase(:) do i=0, char_size-1 call random_number( arand ) index1 = int( floor( arand * char_size ), kind=int32 ) char_temp = char_rand(i) char_rand(i) = char_rand(index1) char_rand(index1) = char_temp end do count = 0 do i=0, char_set_size-1 do j=0, char_set_size-1 do k=0, char_set_size-1 string_increase(count) = achar(97+i) // achar(97+j) // & achar(97+k) count = count + 1 end do end do end do do i=0, string_size-1 string_decrease(string_size - 1 - i) = string_increase(i) end do string_rand(:) = string_increase(:) do i=0, string_size-1 call random_number( arand ) index1 = int( floor( arand * string_size ), kind=int32 ) string_temp = string_rand(i) string_rand(i) = string_rand(index1) string_rand(index1) = string_temp end do #if STDLIB_BITSETS do i = 0, bitset_size-1 write(bin32,'(b32.32)') i call bitsetl_increase(i)%from_string(bin32) end do do i=0, bitset_size-1 bitsetl_decrease(bitset_size-1-i) = bitsetl_increase(i) end do bitsetl_rand(:) = bitsetl_increase(:) do i=0, bitset_size-1 call random_number( arand ) index1 = int( floor( arand * bitset_size ), kind=int32 ) bitsetl_temp = bitsetl_rand(i) bitsetl_rand(i) = bitsetl_rand(index1) bitsetl_rand(index1) = bitsetl_temp end do do i = 0, bitset_size-1 write(bin64,'(b64.64)') i call bitset64_increase(i)%from_string(bin64) end do do i=0, bitset_size-1 bitset64_decrease(bitset_size-1-i) = bitset64_increase(i) end do bitset64_rand(:) = bitset64_increase(:) do i=0, bitset_size-1 call random_number( arand ) index1 = int( floor( arand * bitset_size ), kind=int32 ) bitset64_temp = bitset64_rand(i) bitset64_rand(i) = bitset64_rand(index1) bitset64_rand(index1) = bitset64_temp end do #endif ! Create and intialize file to report the results of the sortings open( newunit=lun, file=filename, access='sequential', action='write', & form='formatted', status='replace' ) write( lun, '(a)' ) trim(compiler_version()) write( lun, * ) write( lun, '("| Type | Elements | Array Name | Method ' // & ' | Time (s) |")' ) write( lun, '("|--------------|----------|-----------------|-----------' // & '--|-----------|")' ) end subroutine initialize_tests subroutine test_int_ord_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(int64) :: i integer, allocatable :: d1(:) logical :: ltest call test_int_ord_sort( blocks, "Blocks", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_ord_sort( decrease, "Decreasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_ord_sort( identical, "Identical", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_ord_sort( increase, "Increasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_ord_sort( rand1, "Random dense", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_ord_sort( rand2, "Random order", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_ord_sort( rand0, "Random sparse", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_ord_sort( rand3, "Random 3", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_ord_sort( rand10, "Random 10", ltest ) call check(error, ltest) if (allocated(error)) return !triggered an issue in insertion_sort d1 = [10, 2, -3, -4, 6, -6, 7, -8, 9, 0, 1, 20] call ord_sort( d1 ) call verify_sort( d1, ltest, i ) call check(error, ltest) end subroutine test_int_ord_sorts subroutine test_int_ord_sort( a, a_name, ltest ) integer(int32), intent(in) :: a(:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat dummy = a call system_clock( t0, rate ) call ord_sort( dummy, work ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_sort( dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "ORD_SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a12, 2i7)') 'dummy(i-1:i) = ', dummy(i-1:i) end if write( lun, '("| Integer |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & test_size, a_name, "Ord_Sort", tdiff/rate !reverse dummy = a call ord_sort( dummy, work, reverse = .true.) call verify_reverse_sort( dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse + work ORD_SORT did not sort " // a_name // & "." write(*,*) 'i = ', i write(*,'(a12, 2i7)') 'dummy(i-1:i) = ', dummy(i-1:i) end if dummy = a call ord_sort( dummy, reverse = .true.) call verify_reverse_sort( dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse ORD_SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a12, 2i7)') 'dummy(i-1:i) = ', dummy(i-1:i) end if end subroutine test_int_ord_sort subroutine test_char_ord_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_char_ord_sort( char_decrease, "Char. Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_char_ord_sort( char_increase, "Char. Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_char_ord_sort( char_rand, "Char. Random", ltest ) call check(error, ltest) end subroutine test_char_ord_sorts subroutine test_char_ord_sort( a, a_name, ltest ) character(len=4), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat char_dummy = a call system_clock( t0, rate ) call ord_sort( char_dummy, char_work ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_char_sort( char_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "ORD_SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a, 2(1x,a4))') 'char_dummy(i-1:i) = ', char_dummy(i-1:i) end if write( lun, '("| Character |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & char_size, a_name, "Ord_Sort", tdiff/rate !reverse char_dummy = a call ord_sort( char_dummy, char_work, reverse = .true. ) call verify_char_reverse_sort( char_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse + work ORD_SORT did not sort " // a_name // & "." write(*,*) 'i = ', i write(*,'(a, 2(1x,a4))') 'char_dummy(i-1:i) = ', char_dummy(i-1:i) end if char_dummy = a call ord_sort( char_dummy, reverse = .true. ) call verify_char_reverse_sort( char_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse + work ORD_SORT did not sort " // a_name // & "." write(*,*) 'i = ', i write(*,'(a, 2(1x,a4))') 'char_dummy(i-1:i) = ', char_dummy(i-1:i) end if end subroutine test_char_ord_sort subroutine test_string_ord_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical:: ltest call test_string_ord_sort( string_decrease, "String Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_string_ord_sort( string_increase, "String Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_string_ord_sort( string_rand, "String Random" , ltest) call check(error, ltest) end subroutine test_string_ord_sorts subroutine test_string_ord_sort( a, a_name, ltest ) type(string_type), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat string_dummy = a call system_clock( t0, rate ) call ord_sort( string_dummy, string_work ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_string_sort( string_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "ORD_SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a, 2(1x,a))') 'string_dummy(i-1:i) = ', & string_dummy(i-1:i) end if write( lun, '("| String_type |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & string_size, a_name, "Ord_Sort", tdiff/rate !reverse string_dummy = a call ord_sort( string_dummy, string_work, reverse = .true. ) call verify_string_reverse_sort( string_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse + work ORD_SORT did not sort " // a_name // & "." write(*,*) 'i = ', i write(*,'(a, 2(1x,a))') 'string_dummy(i-1:i) = ', & string_dummy(i-1:i) end if string_dummy = a call ord_sort( string_dummy, reverse = .true. ) call verify_string_reverse_sort( string_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse ORD_SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a, 2(1x,a))') 'string_dummy(i-1:i) = ', & string_dummy(i-1:i) end if end subroutine test_string_ord_sort #if STDLIB_BITSETS subroutine test_bitsetl_ord_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical:: ltest call test_bitsetl_ord_sort( bitsetl_decrease, "Bitset Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitsetl_ord_sort( bitsetl_increase, "Bitset Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitsetl_ord_sort( bitsetl_rand, "Bitset Random" , ltest) call check(error, ltest) end subroutine test_bitsetl_ord_sorts subroutine test_bitsetl_ord_sort( a, a_name, ltest ) type(bitset_large), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid character(:), allocatable :: bin_im1, bin_i ltest = .true. tdiff = 0 do i = 1, repeat bitsetl_dummy = a call system_clock( t0, rate ) call ord_sort( bitsetl_dummy, bitsetl_work ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_bitsetl_sort( bitsetl_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "ORD_SORT did not sort " // a_name // "." write(*,*) 'i = ', i call bitsetl_dummy(i-1)%to_string(bin_im1) call bitsetl_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitsetl_dummy(i-1:i) = ', & bin_im1, bin_i end if write( lun, '("| Bitset_large |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & bitset_size, a_name, "Ord_Sort", tdiff/rate !reverse bitsetl_dummy = a call ord_sort( bitsetl_dummy, bitsetl_work, reverse = .true. ) call verify_bitsetl_reverse_sort( bitsetl_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse + work ORD_SORT did not sort " // a_name // & "." write(*,*) 'i = ', i call bitsetl_dummy(i-1)%to_string(bin_im1) call bitsetl_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitsetl_dummy(i-1:i) = ', & bin_im1, bin_i end if bitsetl_dummy = a call ord_sort( bitsetl_dummy, reverse = .true. ) call verify_bitsetl_reverse_sort( bitsetl_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse ORD_SORT did not sort " // a_name // "." write(*,*) 'i = ', i call bitsetl_dummy(i-1)%to_string(bin_im1) call bitsetl_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitsetl_dummy(i-1:i) = ', & bin_im1, bin_i end if end subroutine test_bitsetl_ord_sort subroutine test_bitset64_ord_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical:: ltest call test_bitset64_ord_sort( bitset64_decrease, "Bitset Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitset64_ord_sort( bitset64_increase, "Bitset Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitset64_ord_sort( bitset64_rand, "Bitset Random" , ltest) call check(error, ltest) end subroutine test_bitset64_ord_sorts subroutine test_bitset64_ord_sort( a, a_name, ltest ) type(bitset_64), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid character(:), allocatable :: bin_im1, bin_i ltest = .true. tdiff = 0 do i = 1, repeat bitset64_dummy = a call system_clock( t0, rate ) call ord_sort( bitset64_dummy, bitset64_work ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_bitset64_sort( bitset64_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "ORD_SORT did not sort " // a_name // "." write(*,*) 'i = ', i call bitset64_dummy(i-1)%to_string(bin_im1) call bitset64_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitset64_dummy(i-1:i) = ', & bin_im1, bin_i end if write( lun, '("| Bitset_64 |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & bitset_size, a_name, "Ord_Sort", tdiff/rate !reverse bitset64_dummy = a call ord_sort( bitset64_dummy, bitset64_work, reverse = .true. ) call verify_bitset64_reverse_sort( bitset64_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse + work ORD_SORT did not sort " // a_name // & "." write(*,*) 'i = ', i call bitset64_dummy(i-1)%to_string(bin_im1) call bitset64_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitset64_dummy(i-1:i) = ', & bin_im1, bin_i end if bitset64_dummy = a call ord_sort( bitset64_dummy, reverse = .true. ) call verify_bitset64_reverse_sort( bitset64_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse ORD_SORT did not sort " // a_name // "." write(*,*) 'i = ', i call bitset64_dummy(i-1)%to_string(bin_im1) call bitset64_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitset64_dummy(i-1:i) = ', & bin_im1, bin_i end if end subroutine test_bitset64_ord_sort #endif subroutine test_int_radix_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(int64) :: i integer, allocatable :: d1(:) logical :: ltest call test_int_radix_sort( blocks, "Blocks", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_radix_sort( decrease, "Decreasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_radix_sort( identical, "Identical", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_radix_sort( increase, "Increasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_radix_sort( rand1, "Random dense", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_radix_sort( rand2, "Random order", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_radix_sort( rand0, "Random sparse", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_radix_sort( rand3, "Random 3", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_radix_sort( rand10, "Random 10", ltest ) call check(error, ltest) if (allocated(error)) return !triggered an issue in insertion d1 = [10, 2, -3, -4, 6, -6, 7, -8, 9, 0, 1, 20] call sort( d1 ) call verify_sort( d1, ltest, i ) call check(error, ltest) end subroutine test_int_radix_sorts subroutine test_int_radix_sort( a, a_name, ltest ) integer(int32), intent(in) :: a(:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat dummy = a call system_clock( t0, rate ) call radix_sort( dummy ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_sort( dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "RADIX_SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a12, 2i7)') 'dummy(i-1:i) = ', dummy(i-1:i) end if write( lun, '("| Integer |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & test_size, a_name, "Radix_Sort", tdiff/rate ! reverse dummy = a call radix_sort( dummy, reverse = .true.) call verify_reverse_sort(dummy, valid, i) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse RADIX_SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a12, 2i7)') 'dummy(i-1:i) = ', dummy(i-1:i) end if end subroutine test_int_radix_sort subroutine test_real_radix_sort( a, a_name, ltest ) real(sp), intent(in) :: a(:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat real_dummy = a call system_clock( t0, rate ) call radix_sort( real_dummy ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_real_sort( real_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "RADIX_SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a12, 2f12.5)') 'real_dummy(i-1:i) = ', real_dummy(i-1:i) end if write( lun, '("| Real |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & test_size, a_name, "Radix_Sort", tdiff/rate ! reverse real_dummy = a call radix_sort( real_dummy, reverse = .true.) call verify_real_reverse_sort(real_dummy, valid, i) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse RADIX_SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a12, 2f12.5)') 'real_dummy(i-1:i) = ', real_dummy(i-1:i) end if end subroutine test_real_radix_sort subroutine test_real_radix_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_real_radix_sort( rand_r32, "rand-real32", ltest ) call check(error, ltest) if (allocated(error)) return end subroutine test_real_radix_sorts subroutine test_int_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(int64) :: i integer, allocatable :: d1(:) logical :: ltest call test_int_sort( blocks, "Blocks", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort( decrease, "Decreasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort( identical, "Identical", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort( increase, "Increasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort( rand1, "Random dense", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort( rand2, "Random order", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort( rand0, "Random sparse", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort( rand3, "Random 3", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort( rand10, "Random 10", ltest ) call check(error, ltest) if (allocated(error)) return !triggered an issue in insertion d1 = [10, 2, -3, -4, 6, -6, 7, -8, 9, 0, 1, 20] call sort( d1 ) call verify_sort( d1, ltest, i ) call check(error, ltest) end subroutine test_int_sorts subroutine test_int_sort( a, a_name, ltest ) integer(int32), intent(in) :: a(:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat dummy = a call system_clock( t0, rate ) call sort( dummy ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_sort( dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a12, 2i7)') 'dummy(i-1:i) = ', dummy(i-1:i) end if write( lun, '("| Integer |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & test_size, a_name, "Sort", tdiff/rate ! reverse dummy = a call sort( dummy, .true.) call verify_reverse_sort(dummy, valid, i) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a12, 2i7)') 'dummy(i-1:i) = ', dummy(i-1:i) end if end subroutine test_int_sort subroutine test_char_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_char_sort( char_decrease, "Char. Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_char_sort( char_increase, "Char. Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_char_sort( char_rand, "Char. Random", ltest ) call check(error, ltest) end subroutine test_char_sorts subroutine test_char_sort( a, a_name, ltest ) character(len=4), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat char_dummy = a call system_clock( t0, rate ) call sort( char_dummy ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_char_sort( char_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a17, 2(1x,a4))') 'char_dummy(i-1:i) = ', char_dummy(i-1:i) end if write( lun, '("| Character |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & char_size, a_name, "Sort", tdiff/rate !reverse char_dummy = a call sort( char_dummy, .true.) call verify_char_reverse_sort( char_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a17, 2(1x,a4))') 'char_dummy(i-1:i) = ', char_dummy(i-1:i) end if end subroutine test_char_sort subroutine test_string_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_string_sort( string_decrease, "String Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_string_sort( string_increase, "String Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_string_sort( string_rand, "String Random", ltest ) call check(error, ltest) end subroutine test_string_sorts subroutine test_string_sort( a, a_name, ltest ) type(string_type), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat string_dummy = a call system_clock( t0, rate ) call sort( string_dummy ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_string_sort( string_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a17, 2(1x,a4))') 'string_dummy(i-1:i) = ', & string_dummy(i-1:i) end if write( lun, '("| String_type |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & string_size, a_name, "Sort", tdiff/rate ! reverse string_dummy = a call sort( string_dummy, .true.) call verify_string_reverse_sort(string_dummy, valid, i) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse SORT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a17, 2(1x,a4))') 'string_dummy(i-1:i) = ', & string_dummy(i-1:i) end if end subroutine test_string_sort #if STDLIB_BITSETS subroutine test_bitsetl_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_bitsetl_sort( bitsetl_decrease, "Bitset Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitsetl_sort( bitsetl_increase, "Bitset Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitsetl_sort( bitsetl_rand, "Bitset Random", ltest ) call check(error, ltest) end subroutine test_bitsetl_sorts subroutine test_bitsetl_sort( a, a_name, ltest ) type(bitset_large), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid character(:), allocatable :: bin_im1, bin_i ltest = .true. tdiff = 0 do i = 1, repeat bitsetl_dummy = a call system_clock( t0, rate ) call sort( bitsetl_dummy ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_bitsetl_sort( bitsetl_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT did not sort " // a_name // "." write(*,*) 'i = ', i call bitsetl_dummy(i-1)%to_string(bin_im1) call bitsetl_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitsetl_dummy(i-1:i) = ', & bin_im1, bin_i end if write( lun, '("| Bitset_large |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & bitset_size, a_name, "Sort", tdiff/rate ! reverse bitsetl_dummy = a call sort( bitsetl_dummy, .true.) call verify_bitsetl_reverse_sort(bitsetl_dummy, valid, i) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse SORT did not sort " // a_name // "." write(*,*) 'i = ', i call bitsetl_dummy(i-1)%to_string(bin_im1) call bitsetl_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitsetl_dummy(i-1:i) = ', & bin_im1, bin_i end if end subroutine test_bitsetl_sort subroutine test_bitset64_sorts(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_bitset64_sort( bitset64_decrease, "Bitset Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitset64_sort( bitset64_increase, "Bitset Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitset64_sort( bitset64_rand, "Bitset Random", ltest ) call check(error, ltest) end subroutine test_bitset64_sorts subroutine test_bitset64_sort( a, a_name, ltest ) type(bitset_64), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid character(:), allocatable :: bin_im1, bin_i ltest = .true. tdiff = 0 do i = 1, repeat bitset64_dummy = a call system_clock( t0, rate ) call sort( bitset64_dummy ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_bitset64_sort( bitset64_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT did not sort " // a_name // "." write(*,*) 'i = ', i call bitset64_dummy(i-1)%to_string(bin_im1) call bitset64_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitset64_dummy(i-1:i) = ', & bin_im1, bin_i end if write( lun, '("| Bitset_64 |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & bitset_size, a_name, "Sort", tdiff/rate ! reverse bitset64_dummy = a call sort( bitset64_dummy, .true.) call verify_bitset64_reverse_sort(bitset64_dummy, valid, i) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "reverse SORT did not sort " // a_name // "." write(*,*) 'i = ', i call bitset64_dummy(i-1)%to_string(bin_im1) call bitset64_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitsetl_dummy(i-1:i) = ', & bin_im1, bin_i end if end subroutine test_bitset64_sort #endif #:for ki, ti, namei in INT_INDEX_TYPES_ALT_NAME subroutine test_int_sort_indexes_${namei}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(int64) :: i integer(int32), allocatable :: d1(:) ${ti}$, allocatable :: index(:) logical :: ltest call test_int_sort_index_${namei}$( blocks, "Blocks", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_index_${namei}$( decrease, "Decreasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_index_${namei}$( identical, "Identical", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_index_${namei}$( increase, "Increasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_index_${namei}$( rand1, "Random dense", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_index_${namei}$( rand2, "Random order", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_index_${namei}$( rand0, "Random sparse", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_index_${namei}$( rand3, "Random 3", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_index_${namei}$( rand10, "Random 10", ltest ) call check(error, ltest) if (allocated(error)) return d1 = [10, 2, -3, -4, 6, -6, 7, -8, 9, 0, 1, 20] allocate( index(size(d1)) ) call sort_index( d1, index ) call verify_sort( d1, ltest, i ) call check(error, ltest) end subroutine test_int_sort_indexes_${namei}$ subroutine test_int_sort_index_${namei}$( a, a_name, ltest ) integer(int32), intent(inout) :: a(:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat dummy = a call system_clock( t0, rate ) call sort_index( dummy, index_${namei}$, work, iwork_${namei}$ ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat dummy = a(index_${namei}$(0:size(a)-1)) call verify_sort( dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_INDEX did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a18, 2i7)') 'a(index_${namei}$(i-1:i)) = ', a(index_${namei}$(i-1:i)) end if write( lun, '("| Integer |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & test_size, a_name, "Sort_Index", tdiff/rate dummy = a call sort_index( dummy, index_${namei}$, work, iwork_${namei}$, reverse=.true. ) dummy = a(index_${namei}$(size(a)-1)) call verify_reverse_sort( dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_INDEX did not reverse sort " // & a_name // "." write(*,*) 'i = ', i write(*,'(a18, 2i7)') 'a(index_${namei}$(i-1:i)) = ', a(index_${namei}$(i-1:i)) end if end subroutine test_int_sort_index_${namei}$ subroutine test_char_sort_indexes_${namei}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_char_sort_index_${namei}$( char_decrease, "Char. Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_char_sort_index_${namei}$( char_increase, "Char. Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_char_sort_index_${namei}$( char_rand, "Char. Random", ltest ) call check(error, ltest) end subroutine test_char_sort_indexes_${namei}$ subroutine test_char_sort_index_${namei}$( a, a_name, ltest ) character(len=4), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat char_dummy = a call system_clock( t0, rate ) call sort_index( char_dummy, index_${namei}$, char_work, iwork_${namei}$ ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_char_sort( char_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_INDEX did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a17, 2(1x,a4))') 'char_dummy(i-1:i) = ', char_dummy(i-1:i) end if write( lun, '("| Character |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & char_size, a_name, "Sort_Index", tdiff/rate end subroutine test_char_sort_index_${namei}$ subroutine test_string_sort_indexes_${namei}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_string_sort_index_${namei}$( string_decrease, "String Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_string_sort_index_${namei}$( string_increase, "String Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_string_sort_index_${namei}$( string_rand, "String Random", ltest ) call check(error, ltest) end subroutine test_string_sort_indexes_${namei}$ subroutine test_string_sort_index_${namei}$( a, a_name, ltest ) type(string_type), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat string_dummy = a call system_clock( t0, rate ) call sort_index( string_dummy, index_${namei}$, string_work, iwork_${namei}$ ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_string_sort( string_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_INDEX did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a17, 2(1x,a4))') 'string_dummy(i-1:i) = ', & string_dummy(i-1:i) end if write( lun, '("| String_type |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & string_size, a_name, "Sort_Index", tdiff/rate end subroutine test_string_sort_index_${namei}$ #if STDLIB_BITSETS subroutine test_bitsetl_sort_indexes_${namei}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_bitsetl_sort_index_${namei}$( bitsetl_decrease, "Bitset Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitsetl_sort_index_${namei}$( bitsetl_increase, "Bitset Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitsetl_sort_index_${namei}$( bitsetl_rand, "Bitset Random", ltest ) call check(error, ltest) end subroutine test_bitsetl_sort_indexes_${namei}$ subroutine test_bitsetl_sort_index_${namei}$( a, a_name, ltest ) type(bitset_large), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid character(:), allocatable :: bin_im1, bin_i ltest = .true. tdiff = 0 do i = 1, repeat bitsetl_dummy = a call system_clock( t0, rate ) call sort_index( bitsetl_dummy, index_${namei}$, bitsetl_work, iwork_${namei}$ ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_bitsetl_sort( bitsetl_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_INDEX did not sort " // a_name // "." write(*,*) 'i = ', i call bitsetl_dummy(i-1)%to_string(bin_im1) call bitsetl_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitsetl_dummy(i-1:i) = ', & bin_im1, bin_i end if write( lun, '("| Bitset_large |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & bitset_size, a_name, "Sort_Index", tdiff/rate end subroutine test_bitsetl_sort_index_${namei}$ subroutine test_bitset64_sort_indexes_${namei}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_bitset64_sort_index_${namei}$( bitset64_decrease, "Bitset Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitset64_sort_index_${namei}$( bitset64_increase, "Bitset Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitset64_sort_index_${namei}$( bitset64_rand, "Bitset Random", ltest ) call check(error, ltest) end subroutine test_bitset64_sort_indexes_${namei}$ subroutine test_bitset64_sort_index_${namei}$( a, a_name, ltest ) type(bitset_64), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i logical :: valid character(:), allocatable :: bin_im1, bin_i ltest = .true. tdiff = 0 do i = 1, repeat bitset64_dummy = a call system_clock( t0, rate ) call sort_index( bitset64_dummy, index_${namei}$, bitset64_work, iwork_${namei}$ ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_bitset64_sort( bitset64_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_INDEX did not sort " // a_name // "." write(*,*) 'i = ', i call bitset64_dummy(i-1)%to_string(bin_im1) call bitset64_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitset64_dummy(i-1:i) = ', & bin_im1, bin_i end if write( lun, '("| Bitset_64 |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & bitset_size, a_name, "Sort_Index", tdiff/rate end subroutine test_bitset64_sort_index_${namei}$ #endif #:endfor #:for ki, ti, namei in INT_TYPES_ALT_NAME subroutine test_int_sort_adjointes_${namei}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(int64) :: i integer(int32), allocatable :: d1(:) ${ti}$, allocatable :: adjoint(:) logical :: ltest call test_int_sort_adjoint_${namei}$( blocks, "Blocks", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_adjoint_${namei}$( decrease, "Decreasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_adjoint_${namei}$( identical, "Identical", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_adjoint_${namei}$( increase, "Increasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_adjoint_${namei}$( rand1, "Random dense", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_adjoint_${namei}$( rand2, "Random order", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_adjoint_${namei}$( rand0, "Random sparse", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_adjoint_${namei}$( rand3, "Random 3", ltest ) call check(error, ltest) if (allocated(error)) return call test_int_sort_adjoint_${namei}$( rand10, "Random 10", ltest ) call check(error, ltest) if (allocated(error)) return d1 = [10, 2, -3, -4, 6, -6, 7, -8, 9, 0, 1, 20] allocate( adjoint(size(d1))) adjoint = int([(i, i=1, size(d1))], kind=${namei}$) call sort_adjoint( d1, adjoint ) call verify_sort( d1, ltest, i ) call check(error, ltest) end subroutine test_int_sort_adjointes_${namei}$ subroutine test_int_sort_adjoint_${namei}$( a, a_name, ltest ) integer(int32), intent(inout) :: a(:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate ${ti}$ :: adjoint(size(a)) ${ti}$ :: iwork(size(a)) integer(int64) :: i, j logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat dummy = a adjoint = int([(j, j=1_int64, size(a, kind=int64))], kind=${namei}$) call system_clock( t0, rate ) call sort_adjoint( dummy, adjoint, work, iwork ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_sort( dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_ADJOINT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a18, 2i7)') 'a(i-1:i) = ', a(i-1:i) end if write( lun, '("| Integer |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & test_size, a_name, "Sort_adjoint", tdiff/rate !reverse dummy = a adjoint = int([(j, j=1_int64, size(a, kind=int64))], kind=${namei}$) call sort_adjoint( dummy, adjoint, work, iwork, reverse=.true. ) call verify_reverse_sort( dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_ADJOINT did not reverse sort " // & a_name // "." write(*,*) 'i = ', i write(*,'(a18, 2i7)') 'a(i-1:i) = ', a(i-1:i) end if end subroutine test_int_sort_adjoint_${namei}$ subroutine test_char_sort_adjointes_${namei}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_char_sort_adjoint_${namei}$( char_decrease, "Char. Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_char_sort_adjoint_${namei}$( char_increase, "Char. Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_char_sort_adjoint_${namei}$( char_rand, "Char. Random", ltest ) call check(error, ltest) end subroutine test_char_sort_adjointes_${namei}$ subroutine test_char_sort_adjoint_${namei}$( a, a_name, ltest ) character(len=4), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest ${ti}$ :: adjoint(size(a)) ${ti}$ :: iwork(size(a)) integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i, j logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat char_dummy = a adjoint = int([(j, j=1_int64, size(a, kind=int64))], kind=${namei}$) call system_clock( t0, rate ) call sort_adjoint( char_dummy, adjoint, char_work, iwork ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_char_sort( char_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_ADJ did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a17, 2(1x,a4))') 'char_dummy(i-1:i) = ', char_dummy(i-1:i) end if write( lun, '("| Character |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & char_size, a_name, "Sort_adjoint", tdiff/rate end subroutine test_char_sort_adjoint_${namei}$ subroutine test_string_sort_adjointes_${namei}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_string_sort_adjoint_${namei}$( string_decrease, "String Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_string_sort_adjoint_${namei}$( string_increase, "String Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_string_sort_adjoint_${namei}$( string_rand, "String Random", ltest ) call check(error, ltest) end subroutine test_string_sort_adjointes_${namei}$ subroutine test_string_sort_adjoint_${namei}$( a, a_name, ltest ) type(string_type), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest ${ti}$ :: adjoint(size(a)) ${ti}$ :: iwork(size(a)) integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i, j logical :: valid ltest = .true. tdiff = 0 do i = 1, repeat string_dummy = a adjoint = int([(j, j=1_int64, size(a, kind=int64))], kind=${namei}$) call system_clock( t0, rate ) call sort_adjoint( string_dummy, adjoint, string_work, iwork ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_string_sort( string_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_ADJOINT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a17, 2(1x,a4))') 'string_dummy(i-1:i) = ', & string_dummy(i-1:i) end if write( lun, '("| String_type |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & string_size, a_name, "Sort_adjoint", tdiff/rate end subroutine test_string_sort_adjoint_${namei}$ #if STDLIB_BITSETS subroutine test_bitsetl_sort_adjointes_${namei}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_bitsetl_sort_adjoint_${namei}$( bitsetl_decrease, "Bitset Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitsetl_sort_adjoint_${namei}$( bitsetl_increase, "Bitset Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitsetl_sort_adjoint_${namei}$( bitsetl_rand, "Bitset Random", ltest ) call check(error, ltest) end subroutine test_bitsetl_sort_adjointes_${namei}$ subroutine test_bitsetl_sort_adjoint_${namei}$( a, a_name, ltest ) type(bitset_large), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest ${ti}$ :: adjoint(size(a)) ${ti}$ :: iwork(size(a)) integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i, j logical :: valid character(:), allocatable :: bin_im1, bin_i ltest = .true. tdiff = 0 do i = 1, repeat bitsetl_dummy = a adjoint = int([(j, j=1_int64, size(a, kind=int64))], kind=${namei}$) call system_clock( t0, rate ) call sort_adjoint( bitsetl_dummy, adjoint, bitsetl_work, iwork ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_bitsetl_sort( bitsetl_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_ADJOINT did not sort " // a_name // "." write(*,*) 'i = ', i call bitsetl_dummy(i-1)%to_string(bin_im1) call bitsetl_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitsetl_dummy(i-1:i) = ', & bin_im1, bin_i end if write( lun, '("| Bitset_large |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & bitset_size, a_name, "Sort_adjoint", tdiff/rate end subroutine test_bitsetl_sort_adjoint_${namei}$ subroutine test_bitset64_sort_adjointes_${namei}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_bitset64_sort_adjoint_${namei}$( bitset64_decrease, "Bitset Decrease", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitset64_sort_adjoint_${namei}$( bitset64_increase, "Bitset Increase", ltest ) call check(error, ltest) if (allocated(error)) return call test_bitset64_sort_adjoint_${namei}$( bitset64_rand, "Bitset Random", ltest ) call check(error, ltest) end subroutine test_bitset64_sort_adjointes_${namei}$ subroutine test_bitset64_sort_adjoint_${namei}$( a, a_name, ltest ) type(bitset_64), intent(in) :: a(0:) character(*), intent(in) :: a_name logical, intent(out) :: ltest ${ti}$ :: adjoint(size(a)) ${ti}$ :: iwork(size(a)) integer(int64) :: t0, t1, tdiff real(dp) :: rate integer(int64) :: i, j logical :: valid character(:), allocatable :: bin_im1, bin_i ltest = .true. tdiff = 0 do i = 1, repeat bitset64_dummy = a adjoint = int([(j, j=1_int64, size(a, kind=int64))], kind=${namei}$) call system_clock( t0, rate ) call sort_adjoint( bitset64_dummy, adjoint, bitset64_work, iwork ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_bitset64_sort( bitset64_dummy, valid, i ) ltest = (ltest .and. valid) if ( .not. valid ) then write( *, * ) "SORT_ADJOINT did not sort " // a_name // "." write(*,*) 'i = ', i call bitset64_dummy(i-1)%to_string(bin_im1) call bitset64_dummy(i)%to_string(bin_i) write(*,'(a, 2(a:,1x))') 'bitset64_dummy(i-1:i) = ', & bin_im1, bin_i end if write( lun, '("| Bitset_64 |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & bitset_size, a_name, "Sort_adjoint", tdiff/rate end subroutine test_bitset64_sort_adjoint_${namei}$ #endif #:endfor #:for ki, ti, namei in REAL_TYPES_ALT_NAME subroutine test_real_sort_adjointes_${namei}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical :: ltest call test_real_sort_adjoint_${namei}$( blocks, "Blocks", ltest ) call check(error, ltest) if (allocated(error)) return call test_real_sort_adjoint_${namei}$( decrease, "Decreasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_real_sort_adjoint_${namei}$( identical, "Identical", ltest ) call check(error, ltest) if (allocated(error)) return call test_real_sort_adjoint_${namei}$( increase, "Increasing", ltest ) call check(error, ltest) if (allocated(error)) return call test_real_sort_adjoint_${namei}$( rand1, "Random dense", ltest ) call check(error, ltest) if (allocated(error)) return call test_real_sort_adjoint_${namei}$( rand2, "Random order", ltest ) call check(error, ltest) if (allocated(error)) return call test_real_sort_adjoint_${namei}$( rand0, "Random sparse", ltest ) call check(error, ltest) if (allocated(error)) return call test_real_sort_adjoint_${namei}$( rand3, "Random 3", ltest ) call check(error, ltest) if (allocated(error)) return call test_real_sort_adjoint_${namei}$( rand10, "Random 10", ltest ) call check(error, ltest) if (allocated(error)) return end subroutine test_real_sort_adjointes_${namei}$ subroutine test_real_sort_adjoint_${namei}$( a, a_name, ltest ) integer(int32), intent(inout) :: a(:) character(*), intent(in) :: a_name logical, intent(out) :: ltest integer(int64) :: t0, t1, tdiff real(dp) :: rate ${ti}$ :: adjoint(size(a)) ${ti}$ :: iwork(size(a)) integer(int64) :: i, j integer(int64) :: i_adj logical :: valid logical :: valid_adj ltest = .true. tdiff = 0 do i = 1, repeat dummy = a adjoint = real(dummy, kind=${namei}$) call system_clock( t0, rate ) call sort_adjoint( dummy, adjoint, work, iwork ) call system_clock( t1, rate ) tdiff = tdiff + t1 - t0 end do tdiff = tdiff/repeat call verify_sort( dummy, valid, i ) call verify_adjoint(int(adjoint, kind=int32), dummy, valid_adj, i_adj ) ltest = (ltest .and. valid .and. valid_adj) if ( .not. valid ) then write( *, * ) "SORT_ADJOINT did not sort " // a_name // "." write(*,*) 'i = ', i write(*,'(a18, 2i7)') 'a(i-1:i) = ', a(i-1:i) end if if ( .not. valid_adj ) then write( *, * ) "SORT_ADJOINT did not sort " // a_name // "." write(*,*) 'i_adj = ', i_adj write(*,'(a18, 2i7)') 'a(i_adj-1:i_adj) = ', a(i_adj-1:i_adj) end if write( lun, '("| Integer |", 1x, i7, 2x, "|", 1x, a15, " |", ' // & 'a12, " |", F10.6, " |" )' ) & test_size, a_name, "Sort_adjoint", tdiff/rate !reverse dummy = a adjoint = real(dummy, kind=${namei}$) call sort_adjoint( dummy, adjoint, work, iwork, reverse=.true. ) call verify_reverse_sort( dummy, valid, i ) call verify_adjoint(int(adjoint, kind=int32), dummy, valid_adj, i_adj ) ltest = (ltest .and. valid .and. valid_adj) if ( .not. valid ) then write( *, * ) "SORT_ADJOINT did not reverse sort " // & a_name // "." write(*,*) 'i = ', i write(*,'(a18, 2i7)') 'a(i-1:i) = ', a(i-1:i) end if if ( .not. valid_adj ) then write( *, * ) "SORT_ADJOINT did not reverse sort " // & a_name // "." write(*,*) 'i_adj = ', i_adj write(*,'(a18, 2i7)') 'a(i_adj-1:i_adj) = ', a(i_adj-1:i_adj) end if end subroutine test_real_sort_adjoint_${namei}$ #:endfor subroutine verify_sort( a, valid, i ) integer(int32), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) > a(i) ) return end do valid = .true. end subroutine verify_sort subroutine verify_adjoint( a, true, valid, i ) integer(int32), intent(in) :: a(:) integer(int32), intent(in) :: true(:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n if ( a(i) /= true(i) ) return end do valid = .true. end subroutine verify_adjoint subroutine verify_real_sort( a, valid, i ) real(sp), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) > a(i) ) return end do valid = .true. end subroutine verify_real_sort subroutine verify_string_sort( a, valid, i ) type(string_type), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) > a(i) ) return end do valid = .true. end subroutine verify_string_sort #if STDLIB_BITSETS subroutine verify_bitsetl_sort( a, valid, i ) type(bitset_large), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) > a(i) ) return end do valid = .true. end subroutine verify_bitsetl_sort subroutine verify_bitset64_sort( a, valid, i ) type(bitset_64), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) > a(i) ) return end do valid = .true. end subroutine verify_bitset64_sort #endif subroutine verify_char_sort( a, valid, i ) character(len=4), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) > a(i) ) return end do valid = .true. end subroutine verify_char_sort subroutine verify_char_reverse_sort( a, valid, i ) character(len=4), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) < a(i) ) return end do valid = .true. end subroutine verify_char_reverse_sort subroutine verify_reverse_sort( a, valid, i ) integer(int32), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) < a(i) ) return end do valid = .true. end subroutine verify_reverse_sort subroutine verify_real_reverse_sort( a, valid, i ) real(sp), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) < a(i) ) return end do valid = .true. end subroutine verify_real_reverse_sort subroutine verify_string_reverse_sort( a, valid, i ) type(string_type), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) < a(i) ) return end do valid = .true. end subroutine verify_string_reverse_sort #if STDLIB_BITSETS subroutine verify_bitsetl_reverse_sort( a, valid, i ) type(bitset_large), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) < a(i) ) return end do valid = .true. end subroutine verify_bitsetl_reverse_sort subroutine verify_bitset64_reverse_sort( a, valid, i ) type(bitset_64), intent(in) :: a(0:) logical, intent(out) :: valid integer(int64), intent(out) :: i integer(int64) :: n n = size( a, kind=int64 ) valid = .false. do i=1, n-1 if ( a(i-1) < a(i) ) return end do valid = .true. end subroutine verify_bitset64_reverse_sort #endif end module test_sorting program tester use, intrinsic :: iso_fortran_env, only: compiler_version, error_unit use testdrive, only: new_testsuite, run_testsuite, testsuite_type use test_sorting, only: initialize_tests, collect_sorting implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' call initialize_tests() stat = 0 testsuites = [ & new_testsuite("sorting", collect_sorting) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/hash_functions_perf/0000775000175000017500000000000015135654166023174 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/hash_functions_perf/CMakeLists.txt0000775000175000017500000000045315135654166025741 0ustar alastairalastairADDTEST(32_bit_hash_performance) ADDTEST(64_bit_hash_performance) if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 10.0) target_compile_options( test_64_bit_hash_performance PRIVATE $<$:-fno-range-check> ) endif() fortran-lang-stdlib-0ede301/test/hash_functions_perf/test_64_bit_hash_performance.f900000775000175000017500000001244315135654166031235 0ustar alastairalastairprogram test_64_bit_hash_performance !! Program to compare the relative performance of different 64 bit hash !! functions use stdlib_kinds, only: & dp, & int8, & int32, & int64 use stdlib_hash_64bit implicit none integer, parameter :: & block_size(8) = [ 1, 2, 4, 8, 16, 64, 256, 1024 ] integer(int32), parameter :: huge32 = huge(0_int32) real(dp), parameter :: hugep1 = real(huge32, dp) + 1.0_dp integer, parameter :: rand_power = 16 integer, parameter :: rand_size = 2**rand_power integer, parameter :: test_size = rand_size * 4 integer, parameter :: repeat = 4 integer :: index, k integer :: lun real(dp) :: rand(2) integer(int32) :: rand_object(rand_size) integer(int8) :: test_object(test_size) open( newunit=lun, file="64_bit_hash_performance_log.txt", & access="sequential", action="write", form="formatted", & position="rewind" ) do index=1, rand_size call random_number(rand) if (rand(1) < 0.5_dp) then rand_object(index) = ceiling(-rand(2)*hugep1, int32) - 1 else rand_object(index) = floor(rand(2)*hugep1, int32) end if end do test_object(:) = transfer( rand_object, 0_int8, test_size ) write(lun, '("| Algorithm | Key Size | Key # | Time (s) |")') write(lun, '("| | Bytes | | |")') write(lun, '("|------------|-----------|------------|----------|")') call test_fnv_1() call test_fnv_1a() call test_pengy() call test_spooky() contains subroutine test_fnv_1() integer :: index2 integer(int64) :: hash real :: t1, t2, tdiff integer(int64) :: summary(repeat) do k=1, size(block_size) call cpu_time(t1) do index=1, repeat do index2=1, test_size, block_size(k) hash = fnv_1_hash( test_object( index2: & index2+block_size(k)-1 ) ) if (index2 == index) summary(index) = hash end do end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a10, 2x, "|", i8, 3x, "|", 1x, i10, 1x, ' // & '"|", f9.5, 1x, "|")') 'FNV-1', & block_size(k), repeat*(test_size/block_size(k)), tdiff end do end subroutine test_fnv_1 subroutine test_fnv_1a() integer :: index2 integer(int64) :: hash real :: t1, t2, tdiff integer(int64) :: summary(repeat) do k=1, size(block_size) call cpu_time(t1) do index=1, repeat do index2=1, test_size, block_size(k) hash = fnv_1a_hash( test_object( index2: & index2+block_size(k)-1 ) ) if (index2 == index) summary(index) = hash end do end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a10, 2x, "|", i8, 3x, "|", 1x, i10, 1x, ' // & '"|", f9.5, 1x, "|")') 'FNV-1a', & block_size(k), repeat*(test_size/block_size(k)), tdiff end do end subroutine test_fnv_1a subroutine test_spooky() integer :: index2 integer(int64) :: hash(2) integer(int64) :: seed(2) = [ 0_int64, 0_int64 ] real :: t1, t2, tdiff integer(int64) :: summary(repeat) call new_spooky_hash_seed( seed ) do k=1, size(block_size) call cpu_time(t1) do index=1, repeat do index2=1, test_size, block_size(k) hash = spooky_hash( test_object( index2: & index2+block_size(k)-1 ), & seed ) if (index2 == index) summary(index) = hash(1) end do end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a10, 2x, "|", i8, 3x, "|", 1x, i10, 1x, ' // & '"|", f9.5, 1x, "|")') 'Spooky', & block_size(k), repeat*(test_size/block_size(k)), tdiff end do end subroutine test_spooky subroutine test_pengy() integer :: index2 integer(int64) :: hash integer(int32) :: seed = int( z'DEADBEEF', int32 ) real :: t1, t2, tdiff integer(int64) :: summary(repeat) call new_pengy_hash_seed( seed ) do k=1, size(block_size) call cpu_time(t1) do index=1, repeat do index2=1, test_size, block_size(k) hash = pengy_hash( test_object( index2: & index2+block_size(k)-1 ), & seed ) if (index2 == index) summary(index) = hash end do end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a10, 2x, "|", i8, 3x, "|", 1x, i10, 1x, ' // & '"|", f9.5, 1x, "|")') 'Pengy', & block_size(k), repeat*(test_size/block_size(k)), tdiff end do end subroutine test_pengy end program test_64_bit_hash_performance fortran-lang-stdlib-0ede301/test/hash_functions_perf/test_32_bit_hash_performance.f900000775000175000017500000001450215135654166031226 0ustar alastairalastairprogram test_32_bit_hash_performance !! Program to compare the relative performance of different 32 bit hash !! functions use stdlib_kinds, only: & dp, & int8, & int32, & int64 use stdlib_hash_32bit implicit none integer, parameter :: & block_size(8) = [ 1, 2, 4, 8, 16, 64, 256, 1024 ] integer(int32), parameter :: huge32 = huge(0_int32) real(dp), parameter :: hugep1 = real(huge32, dp) + 1.0_dp integer, parameter :: rand_power = 16 integer, parameter :: rand_size = 2**rand_power integer, parameter :: test_size = rand_size * 4 integer, parameter :: repeat = 4 integer :: index, k integer :: lun real(dp) :: rand(2) integer(int32) :: rand_object(rand_size) integer(int8) :: test_object(test_size) open( newunit=lun, file="32_bit_hash_performance_log.txt", & access="sequential", action="write", form="formatted", & position="rewind" ) do index=1, rand_size call random_number(rand) if (rand(1) < 0.5_dp) then rand_object(index) = ceiling(-rand(2)*hugep1, int32) - 1 else rand_object(index) = floor(rand(2)*hugep1, int32) end if end do test_object(:) = transfer( rand_object, 0_int8, test_size ) write(lun, '("| Algorithm | Key Size | Key # | Time (s) |")') write(lun, '("| | Bytes | | |")') write(lun, '("|------------|-----------|------------|----------|")') call test_fnv_1() call test_fnv_1a() call test_nmhash32() call test_nmhash32x() call test_water() contains subroutine test_fnv_1() integer :: index2 integer(int_hash) :: hash real :: t1, t2, tdiff integer(int_hash) :: summary(repeat) do k=1, size(block_size) call cpu_time(t1) do index=1, repeat do index2=1, test_size, block_size(k) hash = fnv_1_hash( test_object( index2: & index2+block_size(k)-1 ) ) if (index2 == index) summary(index) = hash end do end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a10, 2x, "|", i8, 3x, "|", 1x, i10, 1x, ' // & '"|", f9.5, 1x, "|")') 'FNV-1', & block_size(k), repeat*(test_size/block_size(k)), tdiff end do end subroutine test_fnv_1 subroutine test_fnv_1a() integer :: index2 integer(int_hash) :: hash real :: t1, t2, tdiff integer(int_hash) :: summary(repeat) do k=1, size(block_size) call cpu_time(t1) do index=1, repeat do index2=1, test_size, block_size(k) hash = fnv_1a_hash( test_object( index2: & index2+block_size(k)-1 ) ) if (index2 == index) summary(index) = hash end do end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a10, 2x, "|", i8, 3x, "|", 1x, i10, 1x, ' // & '"|", f9.5, 1x, "|")') 'FNV-1a', & block_size(k), repeat*(test_size/block_size(k)), tdiff end do end subroutine test_fnv_1a subroutine test_nmhash32() integer :: index2 integer(int_hash) :: hash integer(int32) :: seed = 0_int32 real :: t1, t2, tdiff integer(int_hash) :: summary(repeat) call new_nmhash32_seed( seed ) do k=1, size(block_size) call cpu_time(t1) do index=1, repeat do index2=1, test_size, block_size(k) hash = nmhash32( test_object( index2: & index2+block_size(k)-1 ),& seed ) if (index2 == index) summary(index) = hash end do end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a10, 2x, "|", i8, 3x, "|", 1x, i10, 1x, ' // & '"|", f9.5, 1x, "|")') 'nmhash32', & block_size(k), repeat*(test_size/block_size(k)), tdiff end do end subroutine test_nmhash32 subroutine test_nmhash32x() integer :: index2 integer(int_hash) :: hash integer(int32) :: seed = 0_int32 real :: t1, t2, tdiff integer(int_hash) :: summary(repeat) call new_nmhash32x_seed( seed ) do k=1, size(block_size) call cpu_time(t1) do index=1, repeat do index2=1, test_size, block_size(k) hash = nmhash32x( test_object( index2: & index2+block_size(k)-1 ),& seed ) if (index2 == index) summary(index) = hash end do end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a10, 2x, "|", i8, 3x, "|", 1x, i10, 1x, ' // & '"|", f9.5, 1x, "|")') 'nmhash32x', & block_size(k), repeat*(test_size/block_size(k)), tdiff end do end subroutine test_nmhash32x subroutine test_water() integer :: index2 integer(int_hash) :: hash integer(int64) :: seed = 0_int64 real :: t1, t2, tdiff integer(int_hash) :: summary(repeat) call new_water_hash_seed( seed ) do k=1, size(block_size) call cpu_time(t1) do index=1, repeat do index2=1, test_size, block_size(k) hash = water_hash( test_object( index2: & index2+block_size(k)-1 ),& seed ) if (index2 == index) summary(index) = hash end do end do call cpu_time(t2) tdiff = t2-t1 write(lun, '("|", a10, 2x, "|", i8, 3x, "|", 1x, i10, 1x, ' // & '"|", f9.5, 1x, "|")') 'water', & block_size(k), repeat*(test_size/block_size(k)), tdiff end do end subroutine test_water end program test_32_bit_hash_performance fortran-lang-stdlib-0ede301/test/stats/0000775000175000017500000000000015135654166020303 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/stats/test_rawmoment.f900000664000175000017500000010411215135654166023672 0ustar alastairalastairmodule test_rawmoment use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_kinds, only: sp, dp, int32 use stdlib_stats, only: mean, moment use,intrinsic :: ieee_arithmetic, only : ieee_is_nan implicit none real(sp), parameter :: sptol = 1000 * epsilon(1._sp) real(dp), parameter :: dptol = 1000 * epsilon(1._dp) real(dp), parameter :: d1(5) = [1.0_dp, 2.0_dp, 3.0_dp, 4.0_dp, 5.0_dp] real(dp), parameter :: d(4, 3) = reshape([1._dp, 3._dp, 5._dp, 7._dp,& 2._dp, 4._dp, 6._dp, 8._dp,& 9._dp, 10._dp, 11._dp, 12._dp], [4, 3]) complex(sp), parameter :: cs1(5) = [ cmplx(0.57706_sp, 0.00000_sp),& cmplx(0.00000_sp, 1.44065_sp),& cmplx(1.26401_sp, 0.00000_sp),& cmplx(0.00000_sp, 0.88833_sp),& cmplx(1.14352_sp, 0.00000_sp)] complex(sp), parameter :: cs(5,3) = reshape([cs1, cs1*3.0_sp, cs1*1.5_sp], shape(cs)) contains !> Collect all exported unit tests subroutine collect_rawmoment(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("sp", test_sp), & new_unittest("int32", test_int32), & new_unittest("csp", test_csp) & ] end subroutine collect_rawmoment subroutine test_sp(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(sp), parameter :: x1(5) = d1 real(sp), parameter :: x2(4, 3) = d integer :: order real(sp), allocatable :: x3(:, :, :) real(sp), allocatable :: zero2_1(:), zero2_2(:) real(sp), allocatable :: zero3_1(:,:), zero3_2(:,:), zero3_3(:,:) allocate(zero2_1(size(x2, 2)), zero2_2(size(x2, 1))) zero2_1 = 0 zero2_2 = 0 order = 1 !1dim print*,' test_sp_1dim', order call check(error, abs(moment(x1, order, center = 0.) - mean(x1)) < sptol) call check(error, abs(moment(x1, order, 1, center = 0.) - mean(x1)) < sptol) print*,' test_sp_1dim_mask', order call check(error, ieee_is_nan(moment(x1, order, center = 0., mask = .false.))) call check(error, ieee_is_nan(moment(x1, order, dim = 1, center = 0., mask = .false.))) print*,' test_sp_1dim_mask_array', order call check(error, abs(moment(x1, order, center = 0., mask = (x1 < 5)) -& mean(x1, mask = (x1 < 5)) ) < sptol) call check(error, abs(moment(x1, order, dim = 1, center = 0., mask = (x1 < 5)) -& mean(x1, dim = 1, mask = (x1 < 5))) < sptol) !2dim print*,' test_sp_2dim', order call check(error, abs(moment(x2, order, center = 0.) - mean(x2)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = 0.) -& mean(x2, dim = 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = 0.) -& mean(x2, dim = 2)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1) -& mean(x2, dim = 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = zero2_2) -& mean(x2, dim = 2)) < sptol)) print*,' test_sp_2dim_mask', order call check(error, ieee_is_nan(moment(x2, order, center = 0., mask = .false.))) call check(error, any(ieee_is_nan(moment(x2, order, dim = 1, center = zero2_1,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x2, order, dim = 2, center = zero2_2,& mask = .false.)))) print*,' test_sp_2dim_mask_array', order call check(error, abs(moment(x2, order, center = 0., mask = (x2 < 11)) -& mean(x2, x2 < 11)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = 0.,& mask = (x2 < 11)) -& mean(x2, 1, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = 0.,& mask = (x2 < 11)) -& mean(x2, 2, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1,& mask = (x2 < 11)) -& mean(x2, 1, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = zero2_2,& mask = (x2 < 11)) -& mean(x2, 2, x2 < 11)) < sptol)) !3dim allocate(x3(size(x2,1),size(x2,2),3)) x3(:,:,1)=x2; x3(:,:,2)=x2*2; x3(:,:,3)=x2*4; allocate(zero3_1(size(x3, 2), size(x3, 3))& ,zero3_2(size(x3, 1), size(x3, 3))& ,zero3_3(size(x3, 1), size(x3, 2))) zero3_1 = 0 zero3_2 = 0 zero3_3 = 0 print*,' test_sp_3dim', order call check(error, abs(moment(x3, order, center = 0.) - mean(x3)) < sptol) call check(error, all( abs( moment(x3, order, dim = 1, center = 0._sp) -& mean(x3, 1)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 2, center = 0._sp) -& mean(x3, 2)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 3, center = 0._sp) -& mean(x3, 3)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 1, center = zero3_1) -& mean(x3, 1)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 2, center = zero3_2) -& mean(x3, 2)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 3, center = zero3_3) -& mean(x3, 3)) < sptol)) print*,' test_sp_3dim_mask', order call check(error, ieee_is_nan(moment(x3, order, center = 0., mask = .false.))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 1, center = zero3_1,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 2, center = zero3_2,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 3, center = zero3_3,& mask = .false.)))) print*,' test_sp_3dim_mask_array', order call check(error, abs(moment(x3, order, center = 0., mask = (x3 < 11)) -& mean(x3, x3 < 11)) < sptol) call check(error, all( abs( moment(x3, order, dim = 1, center = 0.,& mask = (x3 < 45)) -& mean(x3, 1, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 2, center = 0.,& mask = (x3 < 45)) -& mean(x3, 2, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 3, center = 0.,& mask = (x3 < 45)) -& mean(x3, 3, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 1, center = zero3_1,& mask = (x3 < 45)) -& mean(x3, 1, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 2, center = zero3_2,& mask = (x3 < 45)) -& mean(x3, 2, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 3, center = zero3_3,& mask = (x3 < 45)) -& mean(x3, 3, x3 < 45)) < sptol )) order = 2 !1dim print*,' test_sp_1dim', order call check(error, abs(moment(x1, order, center = 0.) - mean(x1**2)) < sptol) call check(error, abs(moment(x1, order, 1, center = 0.) - mean(x1**2, 1)) < sptol) print*,' test_sp_1dim_mask', order call check(error, ieee_is_nan(moment(x1, order, center = 0., mask = .false.))) call check(error, ieee_is_nan(moment(x1, order, dim = 1, center = 0., mask = .false.))) print*,' test_sp_1dim_mask_array', order call check(error, abs(moment(x1, order, center = 0., mask = (x1 < 5)) -& mean(x1**2, x1 < 5)) < sptol) call check(error, abs(moment(x1, order, dim = 1, center = 0., mask = (x1 < 5)) -& mean(x1**2, 1, x1 < 5)) < sptol) !2dim print*,' test_sp_2dim', order call check(error, abs(moment(x2, order, center = 0.) - mean(x2**2)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = 0.) -& mean(x2**2, 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = 0.) - & mean(x2**2, 2)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1) -& mean(x2**2, 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = zero2_2) - & mean(x2**2, 2)) < sptol)) print*,' test_sp_2dim_mask', order call check(error, ieee_is_nan(moment(x2, order, center = 0., mask = .false.))) call check(error, any(ieee_is_nan(moment(x2, order, dim = 1, center = zero2_1, & mask = .false.)))) call check(error, any(ieee_is_nan(moment(x2, order, dim = 2, center = zero2_2, & mask = .false.)))) print*,' test_sp_2dim_mask_array', order call check(error, abs(moment(x2, order, center = 0., mask = (x2 < 11)) -& mean(x2**2, x2 < 11)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = 0.,& mask = (x2 < 11)) -& mean(x2**2, 1, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = 0.,& mask = (x2 < 11)) -& mean(x2**2, 2, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1,& mask = (x2 < 11)) -& mean(x2**2, 1, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = zero2_2,& mask = (x2 < 11)) -& mean(x2**2, 2, x2 < 11)) < sptol)) !3dim print*,' test_sp_3dim', order call check(error, abs(moment(x3, order, center = 0.) - mean(x3**2)) < sptol) call check(error, all( abs( moment(x3, order, dim = 1, center = 0.) -& mean(x3**2, 1)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 2, center = 0.) -& mean(x3**2, 2)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 3, center = 0.) -& mean(x3**2, 3)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 1, center = zero3_1) -& mean(x3**2, 1)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 2, center = zero3_2) -& mean(x3**2, 2)) < 1.5_sp*sptol)) call check(error, all( abs( moment(x3, order, dim = 3, center = zero3_3) -& mean(x3**2, 3)) < sptol)) print*,' test_sp_3dim_mask', order call check(error, ieee_is_nan(moment(x3, order, center = 0., mask = .false.))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 1, center = zero3_1,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 2, center = zero3_2,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 3, center = zero3_3,& mask = .false.)))) print*,' test_sp_3dim_mask_array', order call check(error, abs(moment(x3, order, center = 0., mask = (x3 < 11)) -& mean(x3**2, x3 < 11)) < sptol) call check(error, all( abs( moment(x3, order, dim = 1, center = 0.,& mask = (x3 < 45)) -& mean(x3**2, 1, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 2, center = 0.,& mask = (x3 < 45)) -& mean(x3**2, 2, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 3, center = 0.,& mask = (x3 < 45)) -& mean(x3**2, 3, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 1, center = zero3_1,& mask = (x3 < 45)) -& mean(x3**2, 1, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 2, center = zero3_2,& mask = (x3 < 45)) -& mean(x3**2, 2, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 3, center = zero3_3,& mask = (x3 < 45)) -& mean(x3**2, 3, x3 < 45)) < sptol )) end subroutine subroutine test_int32(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(int32), parameter :: x1(5) = d1 integer(int32), parameter :: x2(4, 3) = d integer :: order integer(int32), allocatable :: x3(:, :, :) real(dp), allocatable :: zero2_1(:), zero2_2(:) real(dp), allocatable :: zero3_1(:,:), zero3_2(:,:), zero3_3(:,:) allocate(zero2_1(size(x2, 2)), zero2_2(size(x2, 1))) zero2_1 = 0 zero2_2 = 0 order = 1 !1dim print*,' test_sp_1dim', order call check(error, abs(moment(x1, order, center = 0._dp) - mean(x1)) < sptol) call check(error, abs(moment(x1, order, 1, center = 0._dp) - mean(x1)) < sptol) print*,' test_sp_1dim_mask', order call check(error, ieee_is_nan(moment(x1, order, center = 0._dp, mask = .false.))) call check(error, ieee_is_nan(moment(x1, order, dim = 1, center = 0._dp,& mask = .false.))) print*,' test_sp_1dim_mask_array', order call check(error, abs(moment(x1, order, center = 0._dp, mask = (x1 < 5)) -& mean(x1, mask = (x1 < 5)) ) < sptol) call check(error, abs(moment(x1, order, dim = 1, center = 0._dp, mask = (x1 < 5)) -& mean(x1, dim = 1, mask = (x1 < 5))) < sptol) !2dim print*,' test_sp_2dim', order call check(error, abs(moment(x2, order, center = 0._dp) - mean(x2)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = 0._dp) -& mean(x2, dim = 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = 0._dp) -& mean(x2, dim = 2)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1) -& mean(x2, dim = 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = zero2_2) -& mean(x2, dim = 2)) < sptol)) print*,' test_sp_2dim_mask', order call check(error, ieee_is_nan(moment(x2, order, center = 0._dp, mask = .false.))) call check(error, any(ieee_is_nan(moment(x2, order, dim = 1, center = zero2_1,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x2, order, dim = 2, center = zero2_2,& mask = .false.)))) print*,' test_sp_2dim_mask_array', order call check(error, abs(moment(x2, order, center = 0._dp, mask = (x2 < 11)) -& mean(x2, x2 < 11)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = 0._dp,& mask = (x2 < 11)) -& mean(x2, 1, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = 0._dp,& mask = (x2 < 11)) -& mean(x2, 2, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1,& mask = (x2 < 11)) -& mean(x2, 1, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = zero2_2,& mask = (x2 < 11)) -& mean(x2, 2, x2 < 11)) < sptol)) !3dim allocate(x3(size(x2,1),size(x2,2),3)) x3(:,:,1)=x2; x3(:,:,2)=x2*2; x3(:,:,3)=x2*4; allocate(zero3_1(size(x3, 2), size(x3, 3))& ,zero3_2(size(x3, 1), size(x3, 3))& ,zero3_3(size(x3, 1), size(x3, 2))) zero3_1 = 0 zero3_2 = 0 zero3_3 = 0 print*,' test_sp_3dim', order call check(error, abs(moment(x3, order, center = 0._dp) - mean(x3)) < sptol) call check(error, all( abs( moment(x3, order, dim = 1, center = 0._dp) -& mean(x3, 1)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 2, center = 0._dp) -& mean(x3, 2)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 3, center = 0._dp) -& mean(x3, 3)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 1, center = zero3_1) -& mean(x3, 1)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 2, center = zero3_2) -& mean(x3, 2)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 3, center = zero3_3) -& mean(x3, 3)) < sptol)) print*,' test_sp_3dim_mask', order call check(error, ieee_is_nan(moment(x3, order, center = 0._dp, mask = .false.))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 1, center = zero3_1,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 2, center = zero3_2,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 3, center = zero3_3,& mask = .false.)))) print*,' test_sp_3dim_mask_array', order call check(error, abs(moment(x3, order, center = 0._dp, mask = (x3 < 11)) -& mean(x3, x3 < 11)) < sptol) call check(error, all( abs( moment(x3, order, dim = 1, center = 0._dp,& mask = (x3 < 45)) -& mean(x3, 1, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 2, center = 0._dp,& mask = (x3 < 45)) -& mean(x3, 2, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 3, center = 0._dp,& mask = (x3 < 45)) -& mean(x3, 3, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 1, center = zero3_1,& mask = (x3 < 45)) -& mean(x3, 1, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 2, center = zero3_2,& mask = (x3 < 45)) -& mean(x3, 2, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 3, center = zero3_3,& mask = (x3 < 45)) -& mean(x3, 3, x3 < 45)) < sptol )) order = 2 !1dim print*,' test_sp_1dim', order call check(error, abs(moment(x1, order, center = 0._dp) - mean(x1**2)) < sptol) call check(error, abs(moment(x1, order, 1, center = 0._dp) - mean(x1**2, 1)) < sptol) print*,' test_sp_1dim_mask', order call check(error, ieee_is_nan(moment(x1, order, center = 0._dp, mask = .false.))) call check(error, ieee_is_nan(moment(x1, order, dim = 1, center = 0._dp,& mask = .false.))) print*,' test_sp_1dim_mask_array', order call check(error, abs(moment(x1, order, center = 0._dp, mask = (x1 < 5)) -& mean(x1**2, x1 < 5)) < sptol) call check(error, abs(moment(x1, order, dim = 1, center = 0._dp, mask = (x1 < 5)) -& mean(x1**2, 1, x1 < 5)) < sptol) !2dim print*,' test_sp_2dim', order call check(error, abs(moment(x2, order, center = 0._dp) - mean(x2**2)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = 0._dp) -& mean(x2**2, 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = 0._dp) -& mean(x2**2, 2)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1) -& mean(x2**2, 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = zero2_2) -& mean(x2**2, 2)) < sptol)) print*,' test_sp_2dim_mask', order call check(error, ieee_is_nan(moment(x2, order, center = 0._dp, mask = .false.))) call check(error, any(ieee_is_nan(moment(x2, order, dim = 1, center = 0._dp,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x2, order, dim = 2, center = 0._dp,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x2, order, dim = 1, center = zero2_1,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x2, order, dim = 2, center = zero2_2,& mask = .false.)))) print*,' test_sp_2dim_mask_array', order call check(error, abs(moment(x2, order, center = 0._dp, mask = (x2 < 11)) -& mean(x2**2, x2 < 11)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = 0._dp,& mask = (x2 < 11)) -& mean(x2**2, 1, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = 0._dp,& mask = (x2 < 11)) -& mean(x2**2, 2, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1,& mask = (x2 < 11)) -& mean(x2**2, 1, x2 < 11)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = zero2_2,& mask = (x2 < 11)) -& mean(x2**2, 2, x2 < 11)) < sptol)) !3dim print*,' test_sp_3dim', order call check(error, abs(moment(x3, order, center = 0._dp) - mean(x3**2)) < sptol) call check(error, all( abs( moment(x3, order, dim = 1, center = 0._dp) -& mean(x3**2, 1)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 2, center = 0._dp) -& mean(x3**2, 2)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 3, center = 0._dp) -& mean(x3**2, 3)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 1, center = zero3_1) -& mean(x3**2, 1)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 2, center = zero3_2) -& mean(x3**2, 2)) < sptol)) call check(error, all( abs( moment(x3, order, dim = 3, center = zero3_3) -& mean(x3**2, 3)) < sptol)) print*,' test_sp_3dim_mask', order call check(error, ieee_is_nan(moment(x3, order, center = 0._dp, mask = .false.))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 1, center = 0._dp,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 2, center = 0._dp,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 3, center = 0._dp,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 1, center = zero3_1,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 2, center = zero3_2,& mask = .false.)))) call check(error, any(ieee_is_nan(moment(x3, order, dim = 3, center = zero3_3,& mask = .false.)))) print*,' test_sp_3dim_mask_array', order call check(error, abs(moment(x3, order, center = 0._dp, mask = (x3 < 11)) -& mean(x3**2, x3 < 11)) < sptol) call check(error, all( abs( moment(x3, order, dim = 1, center = 0._dp,& mask = (x3 < 45)) -& mean(x3**2, 1, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 2, center = 0._dp,& mask = (x3 < 45)) -& mean(x3**2, 2, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 3, center = 0._dp,& mask = (x3 < 45)) -& mean(x3**2, 3, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 1, center = zero3_1,& mask = (x3 < 45)) -& mean(x3**2, 1, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 2, center = zero3_2,& mask = (x3 < 45)) -& mean(x3**2, 2, x3 < 45)) < sptol )) call check(error, all( abs( moment(x3, order, dim = 3, center = zero3_3,& mask = (x3 < 45)) -& mean(x3**2, 3, x3 < 45)) < sptol )) end subroutine subroutine test_csp(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(sp), parameter :: x1(5) = cs1 complex(sp), parameter :: x2(5, 3) = cs integer :: order complex(sp), allocatable :: zero2_1(:), zero2_2(:) allocate(zero2_1(size(x2, 2)), zero2_2(size(x2, 1))) zero2_1 = (0., 0.) zero2_2 = (0., 0.) order = 1 !1dim print*,' test_sp_1dim', order call check(error, abs(moment(x1, order, center = (0., 0.)) - mean(x1)) < sptol) call check(error, abs(moment(x1, order, 1, center = (0., 0.)) - mean(x1, 1)) < sptol) print*,' test_sp_1dim_mask', order call check(error, ieee_is_nan(abs(moment(x1, order, center = (0., 0.),& mask = .false.)))) call check(error, ieee_is_nan(abs(moment(x1, order, dim = 1, center = (0., 0.),& mask = .false.)))) print*,' test_sp_1dim_mask_array', order call check(error, abs(moment(x1, order, center = (0., 0.), mask = (aimag(x1) == 0)) -& mean(x1, aimag(x1) == 0)) < sptol) call check(error, abs(moment(x1, order, dim = 1, center = (0., 0.),& mask = (aimag(x1) == 0)) -& mean(x1, 1, aimag(x1) == 0)) < sptol) !2dim print*,' test_sp_2dim', order call check(error, abs(moment(x2, order, center = (0., 0.)) - mean(x2)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = (0., 0.)) -& mean(x2, 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = (0., 0.)) -& mean(x2, 2)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1) -& mean(x2, 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = zero2_2) -& mean(x2, 2)) < sptol)) print*,' test_sp_2dim_mask', order call check(error, ieee_is_nan(abs(moment(x2, order, center = (0., 0.),& mask = .false.)))) call check(error, any(ieee_is_nan(abs(moment(x2, order, dim = 1, center = (0., 0.),& mask = .false.))))) call check(error, any(ieee_is_nan(abs(moment(x2, order, dim = 2, center = (0., 0.),& mask = .false.))))) call check(error, any(ieee_is_nan(abs(moment(x2, order, dim = 1, center = zero2_1,& mask = .false.))))) call check(error, any(ieee_is_nan(abs(moment(x2, order, dim = 2, center = zero2_2,& mask = .false.))))) print*,' test_sp_2dim_mask_array', order call check(error, abs(moment(x2, order, center = (0., 0.), mask = (aimag(x2) == 0)) -& mean(x2, aimag(x2) == 0)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = (0., 0.),& mask = (aimag(x2) == 0)) -& mean(x2, 1, aimag(x2) == 0)) < sptol)) call check(error, any(ieee_is_nan( abs( moment(x2, order,& dim = 2, center = (0., 0.), mask = (aimag(x2) == 0)) -& mean(x2, 2, aimag(x2) == 0))))) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1,& mask = (aimag(x2) == 0)) -& mean(x2, 1, aimag(x2) == 0)) < sptol)) call check(error, any(ieee_is_nan( abs( moment(x2, order,& dim = 2, center = zero2_2, mask = (aimag(x2) == 0)) -& mean(x2, 2, aimag(x2) == 0))))) order = 2 !1dim print*,' test_sp_1dim', order call check(error, abs(moment(x1, order, center = (0., 0.)) - mean(x1**2)) < sptol) call check(error, abs(moment(x1, order, 1, center = (0., 0.)) -& mean(x1**2, 1)) < sptol) print*,' test_sp_1dim_mask', order call check(error, ieee_is_nan(abs(moment(x1, order, center = (0., 0.),& mask = .false.)))) call check(error, ieee_is_nan(abs(moment(x1, order, dim = 1, center = (0., 0.),& mask = .false.)))) print*,' test_sp_1dim_mask_array', order call check(error, abs(moment(x1, order, center = (0., 0.), mask = (aimag(x1) == 0)) -& mean(x1**2, aimag(x1) == 0)) < sptol) call check(error, abs(moment(x1, order, dim = 1, center = (0., 0.),& mask = (aimag(x1) == 0)) -& mean(x1**2, 1, aimag(x1) == 0)) < sptol) !2dim print*,' test_sp_2dim', order call check(error, abs(moment(x2, order, center = (0., 0.)) - mean(x2**2)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = (0., 0.)) -& mean(x2**2, 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = (0., 0.)) -& mean(x2**2, 2)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1) -& mean(x2**2, 1)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 2, center = zero2_2) -& mean(x2**2, 2)) < sptol)) print*,' test_sp_2dim_mask', order call check(error, ieee_is_nan(abs(moment(x2, order, center = (0., 0.),& mask = .false.)))) call check(error, any(ieee_is_nan(abs(moment(x2, order, dim = 1, center = (0., 0.),& mask = .false.))))) call check(error, any(ieee_is_nan(abs(moment(x2, order, dim = 2, center = (0., 0.),& mask = .false.))))) call check(error, any(ieee_is_nan(abs(moment(x2, order, dim = 1, center = zero2_1,& mask = .false.))))) call check(error, any(ieee_is_nan(abs(moment(x2, order, dim = 2, center = zero2_2,& mask = .false.))))) print*,' test_sp_2dim_mask_array', order call check(error, abs(moment(x2, order, center = (0., 0.), mask = (aimag(x2) == 0)) -& mean(x2**2, aimag(x2) == 0)) < sptol) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1,& mask = (aimag(x2)==0)) -& mean(x2**2, 1, aimag(x2)==0)) < sptol)) call check(error, all( abs( moment(x2, order, dim = 1, center = zero2_1,& mask = (aimag(x2)==0)) -& mean(x2**2, 1, aimag(x2)==0)) < sptol)) end subroutine end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_rawmoment, only : collect_rawmoment implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("rawmoment", collect_rawmoment) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/stats/test_median.fypp0000664000175000017500000005006115135654166023501 0ustar alastairalastair#:include "common.fypp" #:set IR_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES #:set NRANK = 3 module test_stats_median use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_stats, only: median use stdlib_kinds, only : int8, int16, int32, int64, sp, dp, xdp, qp use, intrinsic :: ieee_arithmetic, only : ieee_is_nan implicit none private public :: collect_stats_median real(sp), parameter :: sptol = 1000 * epsilon(1._sp) real(dp), parameter :: dptol = 2000 * epsilon(1._dp) #:if WITH_XDP real(xdp), parameter :: xdptol = 2000 * epsilon(1._xdp) #:endif #:if WITH_QP real(qp), parameter :: qptol = 2000 * epsilon(1._qp) #:endif #:for k1,t1 in IR_KINDS_TYPES ${t1}$ , parameter :: d1_${k1}$(12) = [${t1}$ :: 10, 2, -3, -4, 6, -6, 7, -8, 9, 0, 1, 20] ${t1}$ :: d2_${k1}$(3, 4) = reshape(d1_${k1}$, [3, 4]) ${t1}$ :: d3_${k1}$(2, 3, 2) = reshape(d1_${k1}$, [2, 3, 2]) ${t1}$ , parameter :: d1odd_${k1}$(13) = [${t1}$ :: d1_${k1}$, 20] ${t1}$ :: d2odd_${k1}$(3, 5) = reshape(d1odd_${k1}$, [3, 5], [${t1}$ :: 0]) ${t1}$ :: d3odd_${k1}$(1, 3, 5) = reshape(d1odd_${k1}$, [1, 3, 5], [${t1}$ :: 0]) #:endfor contains !> Collect all exported unit tests subroutine collect_stats_median(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("test_stats_median_size_int8", test_stats_median_size_int8) & #:for k1,t1 in IR_KINDS_TYPES , new_unittest("test_stats_median_size_${k1}$", test_stats_median_size_${k1}$) & , new_unittest("test_stats_median_odd_size_${k1}$", test_stats_median_odd_size_${k1}$) & , new_unittest("test_stats_median_all_${k1}$", test_stats_median_all_${k1}$) & , new_unittest("test_stats_median_all_odd_${k1}$", test_stats_median_all_odd_${k1}$) & , new_unittest("test_stats_median_all_optmask_${k1}$", test_stats_median_all_optmask_${k1}$) & , new_unittest("test_stats_median_${k1}$", test_stats_median_${k1}$) & , new_unittest("test_stats_median_odd_${k1}$", test_stats_median_odd_${k1}$) & , new_unittest("test_stats_median_optmask_${k1}$", test_stats_median_optmask_${k1}$) & , new_unittest("test_stats_median_mask_all_${k1}$", test_stats_median_mask_all_${k1}$) & , new_unittest("test_stats_median_mask_${k1}$", test_stats_median_mask_${k1}$) & #:endfor ] end subroutine collect_stats_median #:for k1,t1 in INT_KINDS_TYPES subroutine test_stats_median_size_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) !check just to be sure that the setup of d0 is correct call check(error, size(d0), 0, 'size(d0): should be of size 0') #:for rank in range(1, NRANK + 1) call check(error, mod(size(d${rank}$_${k1}$), 2), 0& , 'mod(size(d${rank}$_${k1}$), 2): should be an even number'& ) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_median_odd_size_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for rank in range(1, NRANK + 1) call check(error, mod(size(d${rank}$odd_${k1}$), 2), 1& , 'mod(size(d${rank}$)_${k1}$, 2): should be an odd number'& ) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_median_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) call check(error, ieee_is_nan(median(d0)), 'median(d0): should be NaN' ) if (allocated(error)) return #:for rank in range(1, NRANK + 1) call check(error, median(d${rank}$_${k1}$), 1.5_dp& , 'median(d${rank}$_${k1}$): uncorrect answer'& , thr = dptol) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_median_all_odd_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, median(d1odd_${k1}$), 2._dp& , 'median(d1odd_${k1}$): uncorrect answer'& , thr = dptol) if (allocated(error)) return call check(error, median(d2odd_${k1}$), 1._dp& , 'median(d2odd_${k1}$): uncorrect answer'& , thr = dptol) end subroutine subroutine test_stats_median_all_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0_${k1}$(:) allocate(d0_${k1}$(0)) #:for rank in range(0, NRANK + 1) call check(error, ieee_is_nan(median(d${rank}$_${k1}$, .false.))& , 'median(d${rank}$_${k1}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor end subroutine subroutine test_stats_median_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) call check(error, ieee_is_nan(median(d0, 1)), 'median(d0, 1): should return NaN' ) call check(error& , abs(median(d1_${k1}$, 1) - 1.5_dp) < dptol& , 'median(d1_${k1}$, 1): uncorrect answer'& ) if (allocated(error)) return call check(error& , sum(abs(median(d2_${k1}$, 1) - [2._dp, -4._dp, 7._dp, 1._dp])) < dptol& , 'median(d2_${k1}$, 1): uncorrect answer') if (allocated(error)) return call check(error& , sum(abs(median(d2_${k1}$, 2) - [3.5_dp, 1.5_dp, 3._dp])) < dptol& ,'median(d2_${k1}$, 2): uncorrect answer') if (allocated(error)) return end subroutine subroutine test_stats_median_odd_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error& , abs(median(d1odd_${k1}$, 1) - 2._dp) < dptol& , 'median(d1odd_${k1}$, 1): wrong answer') if (allocated(error)) return call check(error& , sum(abs(median(d2odd_${k1}$, 1) - [2._dp, -4._dp, 7._dp, 1._dp, 0._dp])) < dptol& , 'median(d2odd_${k1}$, 1): wrong answer') if (allocated(error)) return call check(error& , sum(abs(median(d2odd_${k1}$, 2) - [7._dp, 1._dp, 0._dp])) < dptol& , 'median(d2odd_${k1}$, 2): wrong answer') if (allocated(error)) return end subroutine subroutine test_stats_median_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) call check(error, ieee_is_nan(median(d0, 1, .false.))& , 'median(d0, 1, .false.): uncorrect answer'& ) if (allocated(error)) return call check(error, ieee_is_nan(median(d1_${k1}$, 1, .false.))& , 'median(d1_${k1}$, 1, .false.): uncorrect answer'& ) if (allocated(error)) return #:for rank in range(2, NRANK+1) #:for dim in range(1, rank+1) call check(error, any(ieee_is_nan(median(d${rank}$_${k1}$, ${dim}$, .false.)))& , 'median(d${rank}$_${k1}$, ${dim}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor #:endfor end subroutine subroutine test_stats_median_mask_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) call check(error, ieee_is_nan(median(d0, d0 > 0))& , 'median(d0, d0 > 0): should be NaN' ) if (allocated(error)) return #:for rank in range(1, NRANK+1) call check(error& , ieee_is_nan(median(d${rank}$_${k1}$, d${rank}$_${k1}$ > huge(d${rank}$_${k1}$)))& , 'median(d${rank}$_${k1}$, d${rank}$_${k1}$ > huge(d${rank}$_${k1}$))' ) if (allocated(error)) return #:endfor #:for rank in range(1, NRANK+1) call check(error& , (median(d${rank}$_${k1}$, d${rank}$_${k1}$ > 0) - 7._dp) < dptol& , 'median(d${rank}$_${k1}$, d${rank}$_${k1}$> 0)' ) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_median_mask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) call check(error& , ieee_is_nan(median(d0, 1, d0 > 0))& , 'median(d0, 1, d0 > 0): uncorrect answer' ) if (allocated(error)) return call check(error& , ieee_is_nan(median(d1_${k1}$, 1, d1_${k1}$ > huge(d1_${k1}$)))& , 'median(d1_${k1}$, 1_${k1}$, d1_${k1}$ > huge(d1_${k1}$)): answer should be IEEE NaN' ) if (allocated(error)) return #:for rank in range(2, NRANK+1) call check(error& , any(ieee_is_nan(median(d${rank}$_${k1}$, 1, d${rank}$_${k1}$ > huge(d${rank}$_${k1}$))))& , 'median(d${rank}$_${k1}$, 1_${k1}$, d${rank}$_${k1}$ > huge(d${rank}$_${k1}$)): answer should be IEEE NaN' ) if (allocated(error)) return #:endfor call check(error& , (median(d1_${k1}$, 1, d1_${k1}$ > 0) - 7._dp) < dptol& , 'median(d1_${k1}$, 1, d1_${k1}$ >0): uncorrect answer') if (allocated(error)) return call check(error& , sum(abs( (median(d2_${k1}$, 1, d2_${k1}$ > 0) - [ 6._dp, 6._dp, 8._dp, 10.5_dp] ) )) & < dptol& , 'median(d2_${k1}$, 1, d2_${k1}$ > 0): uncorrect answer') if (allocated(error)) return call check(error& , sum(abs((median(d2_${k1}$, 2, d2_${k1}$ > 0) - [ 8.5_dp, 2._dp, 14.5_dp] )))& < dptol& , 'median(d2_${k1}$, 2, d2_${k1}$ > 0)') if (allocated(error)) return call check(error& , any(ieee_is_nan(median(d3_${k1}$, 1, d3_${k1}$ > 0)))& , 'median(d3_${k1}$, 1, d3_${k1}$ > 0): should contain at least 1 IEEE NaN') end subroutine #:endfor #:for k1,t1 in REAL_KINDS_TYPES subroutine test_stats_median_size_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) !check just to be sure that the setup of d0 is correct call check(error, size(d0), 0, 'size(d0): should be of size 0') #:for rank in range(1, NRANK + 1) call check(error, mod(size(d${rank}$_${k1}$), 2), 0& , 'mod(size(d${rank}$_${k1}$), 2): should be an even number'& ) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_median_odd_size_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for rank in range(1, NRANK + 1) call check(error, mod(size(d${rank}$odd_${k1}$), 2), 1& , 'mod(size(d${rank}$_${k1}$), 2): should be an odd number'& ) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_median_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) call check(error, ieee_is_nan(median(d0)), 'median(d0): should be NaN' ) if (allocated(error)) return #:for rank in range(1, NRANK + 1) call check(error, median(d${rank}$_${k1}$), 1.5_${k1}$& , 'median(d${rank}$_${k1}$): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_median_all_odd_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, median(d1odd_${k1}$), 2._${k1}$& , 'median(d1odd_${k1}$): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return call check(error, median(d2odd_${k1}$), 1._${k1}$& , 'median(d2odd_${k1}$): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return call check(error, median(d2odd_${k1}$), 1._${k1}$& , 'median(d2odd_${k1}$): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return end subroutine subroutine test_stats_median_all_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0_${k1}$(:) allocate(d0_${k1}$(0)) #:for rank in range(0, NRANK + 1) call check(error, ieee_is_nan(median(d${rank}$_${k1}$, .false.))& , 'median(d${rank}$_${k1}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor end subroutine subroutine test_stats_median_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) call check(error, ieee_is_nan(median(d0, 1)), 'median(d0, 1): should return NaN' ) call check(error& , abs(median(d1_${k1}$, 1) - 1.5_${k1}$) < ${k1}$tol& , 'median(d1_${k1}$, 1): uncorrect answer'& ) if (allocated(error)) return call check(error& , sum(abs(median(d2_${k1}$, 1) - [2._${k1}$, -4._${k1}$, 7._${k1}$, 1._${k1}$])) < ${k1}$tol& , 'median(d2_${k1}$, 1): uncorrect answer') if (allocated(error)) return call check(error& , sum(abs(median(d2_${k1}$, 2) - [3.5_${k1}$, 1.5_${k1}$, 3._${k1}$])) < ${k1}$tol& ,'median(d2_${k1}$, 2): uncorrect answer') if (allocated(error)) return end subroutine subroutine test_stats_median_odd_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error& , abs(median(d1odd_${k1}$, 1) - 2._${k1}$) < ${k1}$tol& , 'median(d1odd_${k1}$, 1): wrong answer') if (allocated(error)) return call check(error& , sum(abs(median(d2odd_${k1}$, 1) - [2._${k1}$, -4._${k1}$, 7._${k1}$, 1._${k1}$, 0._${k1}$])) < ${k1}$tol& , 'median(d2odd_${k1}$, 1): wrong answer') if (allocated(error)) return call check(error& , sum(abs(median(d2odd_${k1}$, 2) - [7._${k1}$, 1._${k1}$, 0._${k1}$])) < ${k1}$tol& , 'median(d2odd_${k1}$, 2): wrong answer') if (allocated(error)) return end subroutine subroutine test_stats_median_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) call check(error, ieee_is_nan(median(d0, 1, .false.))& , 'median(d0, 1, .false.): uncorrect answer'& ) if (allocated(error)) return call check(error, ieee_is_nan(median(d1_${k1}$, 1, .false.))& , 'median(d1_${k1}$, 1, .false.): uncorrect answer'& ) if (allocated(error)) return #:for rank in range(2, NRANK+1) #:for dim in range(1, rank+1) call check(error, any(ieee_is_nan(median(d${rank}$_${k1}$, ${dim}$, .false.)))& , 'median(d${rank}$_${k1}$, ${dim}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor #:endfor end subroutine subroutine test_stats_median_mask_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) call check(error, ieee_is_nan(median(d0, d0 > 0))& , 'median(d0, d0 > 0): should be NaN' ) if (allocated(error)) return #:for rank in range(1, NRANK+1) call check(error& , ieee_is_nan(median(d${rank}$_${k1}$, d${rank}$_${k1}$ > huge(d${rank}$_${k1}$)))& , 'median(d${rank}$_${k1}$, d${rank}$_${k1}$ > huge(d${rank}$_${k1}$))' ) if (allocated(error)) return #:endfor #:for rank in range(1, NRANK+1) call check(error& , (median(d${rank}$_${k1}$, d${rank}$_${k1}$ > 0) - 7._${k1}$) < ${k1}$tol& , 'median(d${rank}$_${k1}$, d${rank}$_${k1}$ > 0)' ) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_median_mask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, allocatable :: d0(:) allocate(d0(0)) call check(error& , ieee_is_nan(median(d0, 1, d0 > 0))& , 'median(d0, 1, d0 > 0): uncorrect answer' ) if (allocated(error)) return call check(error& , ieee_is_nan(median(d1_${k1}$, 1, d1_${k1}$ > huge(d1_${k1}$)))& , 'median(d1_${k1}$, 1, d1_${k1}$ > huge(d1_${k1}$)): answer should be IEEE NaN' ) if (allocated(error)) return #:for rank in range(2, NRANK+1) call check(error& , any(ieee_is_nan(median(d${rank}$_${k1}$, 1, d${rank}$_${k1}$ > huge(d${rank}$_${k1}$))))& , 'median(d${rank}$_${k1}$, 1, d${rank}$_${k1}$ > huge(d${rank}$_${k1}$)): answer should be IEEE NaN' ) if (allocated(error)) return #:endfor call check(error& , (median(d1_${k1}$, 1, d1_${k1}$ > 0) - 7._${k1}$) < ${k1}$tol& , 'median(d1_${k1}$, 1, d1_${k1}$ >0): uncorrect answer') if (allocated(error)) return call check(error& , sum(abs( (median(d2_${k1}$, 1, d2_${k1}$ > 0) - [ 6._${k1}$, 6._${k1}$, 8._${k1}$, 10.5_${k1}$] ) )) & < ${k1}$tol& , 'median(d2_${k1}$, 1, d2_${k1}$ > 0): uncorrect answer') if (allocated(error)) return call check(error& , sum(abs((median(d2_${k1}$, 2, d2_${k1}$ > 0) - [ 8.5_${k1}$, 2._${k1}$, 14.5_${k1}$] )))& < ${k1}$tol& , 'median(d2_${k1}$, 2, d2_${k1}$ > 0)') if (allocated(error)) return call check(error& , any(ieee_is_nan(median(d3_${k1}$, 1, d3_${k1}$ > 0)))& , 'median(d3_${k1}$, 1, d3_${k1}$ > 0): should contain at least 1 IEEE NaN') end subroutine #:endfor end module test_stats_median program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_stats_median, only : collect_stats_median implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("stats_median", collect_stats_median) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/stats/test_cov.f900000664000175000017500000005705515135654166022465 0ustar alastairalastairprogram test_cov use stdlib_error, only: check use stdlib_kinds, only: sp, dp, int32, int64 use stdlib_stats, only: cov, var use,intrinsic :: ieee_arithmetic, only : ieee_is_nan implicit none real(sp), parameter :: sptol = 1000 * epsilon(1._sp) real(dp), parameter :: dptol = 1000 * epsilon(1._dp) real(dp) :: d1(5) = [1.0_dp, 2.0_dp, 3.0_dp, 4.0_dp, 5.0_dp] real(dp) :: d(4, 3) = reshape([1._dp, 3._dp, 5._dp, 7._dp,& 2._dp, 4._dp, 6._dp, 8._dp,& 9._dp, 10._dp, 11._dp, 12._dp], [4, 3]) complex(dp) :: cd1(5) = [ cmplx(0.57706_dp, 0.00000_dp,kind=dp),& cmplx(0.00000_dp, 1.44065_dp,kind=dp),& cmplx(1.26401_dp, 0.00000_dp,kind=dp),& cmplx(0.00000_dp, 0.88833_dp,kind=dp),& cmplx(1.14352_dp, 0.00000_dp,kind=dp)] complex(dp) :: ds(2,3) = reshape([ cmplx(1._dp, 0._dp,kind=dp),& cmplx(0._dp, 2._dp,kind=dp),& cmplx(3._dp, 0._dp,kind=dp),& cmplx(0._dp, 4._dp,kind=dp),& cmplx(5._dp, 0._dp,kind=dp),& cmplx(0._dp, 6._dp,kind=dp)], [2, 3]) call test_sp(real(d1, sp), real(d, sp)) call test_dp(d1,d) call test_int32(int(d1, int32) ,int(d, int32)) call test_int64(int(d1, int64) ,int(d, int64)) call test_csp(cmplx(cd1, kind = sp), cmplx(ds, kind = sp)) call test_cdp(cd1, ds) contains subroutine test_sp(x, x2) real(sp), intent(in) :: x(:) real(sp), intent(in) :: x2(:, :) call check( abs(cov(x, 1) - 2.5_sp) < sptol& , 'sp check 1') call check( ieee_is_nan(cov(x, 1, .false.))& , 'sp check 2') call check( ieee_is_nan((cov(x, 1, x == 1.)))& , 'sp check 3') call check( abs(cov(x, 1, x < 5) - 5._sp/3) < sptol& , 'sp check 4') call check( abs(cov(x, 1, x < 5, corrected = .false.) -& 5._sp/4) < sptol& , 'sp check 5') call check( any(ieee_is_nan(cov(x2, 1, mask = .false.)))& , 'sp check 6') call check( any(ieee_is_nan(cov(x2, 2, mask = .false.)))& , 'sp check 7') call check( all( abs( cov(x2, 1) - reshape([& 60._sp/9, 60._sp/9, 30._sp/9& ,60._sp/9, 60._sp/9, 30._sp/9& ,30._sp/9, 30._sp/9, 15._sp/9]& ,[ size(x2, 2), size(x2, 2)])& ) < sptol)& , 'sp check 8') call check( all( abs( cov(x2, 2) - reshape([& 19._sp, 16.5_sp, 14._sp, 11.5_sp, 16.5_sp, 129._sp/9& ,109.5_sp/9, 10._sp, 14._sp, 109.5_sp/9, 93._sp/9& , 8.5_sp, 11.5_sp, 10._sp, 8.5_sp, 7._sp]& ,[ size(x2, 1), size(x2, 1)])& ) < sptol)& , 'sp check 9') call check( all( abs( cov(x2, 1, corrected=.false.) - reshape([& 60._sp/9, 60._sp/9, 30._sp/9& ,60._sp/9, 60._sp/9, 30._sp/9& ,30._sp/9, 30._sp/9, 15._sp/9]& *(size(x2, 1)-1._sp)/size(x2, 1)& ,[ size(x2, 2), size(x2, 2)])& ) < sptol)& , 'sp check 10') call check( all( abs( cov(x2, 2, corrected=.false.) - reshape([& 19._sp, 16.5_sp, 14._sp, 11.5_sp, 16.5_sp, 129._sp/9& ,109.5_sp/9, 10._sp, 14._sp, 109.5_sp/9, 93._sp/9& , 8.5_sp, 11.5_sp, 10._sp, 8.5_sp, 7._sp]& *(size(x2, 2)-1._sp)/size(x2, 2)& ,[ size(x2, 1), size(x2, 1)])& ) < sptol)& , 'sp check 11') call check( any(ieee_is_nan(cov(x2, 1, mask = x2 < 10)))& , 'sp check 12') call check( all( abs( cov(x2, 1, mask = x2 < 11) - reshape([& 60._sp/9, 60._sp/9, 1._sp, 60._sp/9, 60._sp/9, 1._sp& , 1._sp, 1._sp, 0.5_sp]& ,[ size(x2, 2), size(x2, 2)])& ) < sptol)& , 'sp check 13') call check( all( abs( cov(x2, 2, mask = x2 < 11) - reshape([& 19._sp, 16.5_sp, 0.5_sp, 0.5_sp, 16.5_sp& ,129._sp/9, 0.5_sp, 0.5_sp, 0.5_sp, 0.5_sp& ,0.5_sp, 0.5_sp, 0.5_sp, 0.5_sp, 0.5_sp, 0.5_sp]& ,[ size(x2, 1), size(x2, 1)])& ) < sptol)& , 'sp check 14') call check( all( abs( cov(x2, 1, mask = x2 < 11, corrected = .false.) -& reshape([& 5._sp, 5._sp, 0.5_sp, 5._sp, 5._sp, 0.5_sp, 0.5_sp,& 0.5_sp, 0.25_sp]& ,[ size(x2, 2), size(x2, 2)])& ) < sptol)& , 'sp check 15') call check( all( abs( cov(x2, 2, mask = x2 < 11, corrected = .false.) -& reshape([& 114._sp/9, 11._sp, 0.25_sp, 0.25_sp, 11._sp, 86._sp/9,& 0.25_sp, 0.25_sp, 0.25_sp, 0.25_sp, 0.25_sp, 0.25_sp,& 0.25_sp, 0.25_sp, 0.25_sp, 0.25_sp]& ,[ size(x2, 1), size(x2, 1)])& ) < sptol)& , 'sp check 16') call check( all( abs( cov(x2, 1, mask = x2 < 1000) - cov(x2, 1))& < sptol)& , 'sp check 17') call check( all( abs( cov(x2, 2, mask = x2 < 1000) - cov(x2, 2))& < sptol)& , 'sp check 18') end subroutine test_sp subroutine test_dp(x, x2) real(dp), intent(in) :: x(:) real(dp), intent(in) :: x2(:, :) call check( abs(cov(x, 1) - 2.5_dp) < dptol& , 'dp check 1') call check( ieee_is_nan(cov(x, 1, .false.))& , 'dp check 2') call check( ieee_is_nan((cov(x, 1, x == 1.)))& , 'dp check 3') call check( abs(cov(x, 1, x < 5) - 5._dp/3) < dptol& , 'dp check 4') call check( abs(cov(x, 1, x < 5, corrected = .false.) -& 5._dp/4) < dptol& , 'dp check 5') call check( any(ieee_is_nan(cov(x2, 1, mask = .false.)))& , 'dp check 6') call check( any(ieee_is_nan(cov(x2, 2, mask = .false.)))& , 'dp check 7') call check( all( abs( cov(x2, 1) - reshape([& 60._dp/9, 60._dp/9, 30._dp/9& ,60._dp/9, 60._dp/9, 30._dp/9& ,30._dp/9, 30._dp/9, 15._dp/9]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'dp check 8') call check( all( abs( cov(x2, 2) - reshape([& 19._dp, 16.5_dp, 14._dp, 11.5_dp, 16.5_dp, 129._dp/9& ,109.5_dp/9, 10._dp, 14._dp, 109.5_dp/9, 93._dp/9& , 8.5_dp, 11.5_dp, 10._dp, 8.5_dp, 7._dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'dp check 9') call check( all( abs( cov(x2, 1, corrected=.false.) - reshape([& 60._dp/9, 60._dp/9, 30._dp/9& ,60._dp/9, 60._dp/9, 30._dp/9& ,30._dp/9, 30._dp/9, 15._dp/9]& *(size(x2, 1)-1._dp)/size(x2, 1)& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'dp check 10') call check( all( abs( cov(x2, 2, corrected=.false.) - reshape([& 19._dp, 16.5_dp, 14._dp, 11.5_dp, 16.5_dp, 129._dp/9& ,109.5_dp/9, 10._dp, 14._dp, 109.5_dp/9, 93._dp/9& , 8.5_dp, 11.5_dp, 10._dp, 8.5_dp, 7._dp]& *(size(x2, 2)-1._dp)/size(x2, 2)& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'dp check 11') call check( any(ieee_is_nan(cov(x2, 1, mask = x2 < 10)))& , 'dp check 12') call check( all( abs( cov(x2, 1, mask = x2 < 11) - reshape([& 60._dp/9, 60._dp/9, 1._dp, 60._dp/9, 60._dp/9, 1._dp& , 1._dp, 1._dp, 0.5_dp]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'dp check 13') call check( all( abs( cov(x2, 2, mask = x2 < 11) - reshape([& 19._dp, 16.5_dp, 0.5_dp, 0.5_dp, 16.5_dp& ,129._dp/9, 0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp& ,0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'dp check 14') call check( all( abs( cov(x2, 1, mask = x2 < 11, corrected = .false.) -& reshape([& 5._dp, 5._dp, 0.5_dp, 5._dp, 5._dp, 0.5_dp, 0.5_dp,& 0.5_dp, 0.25_dp]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'dp check 15') call check( all( abs( cov(x2, 2, mask = x2 < 11, corrected = .false.) -& reshape([& 114._dp/9, 11._dp, 0.25_dp, 0.25_dp, 11._dp, 86._dp/9,& 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp,& 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'dp check 16') call check( all( abs( cov(x2, 1, mask = x2 < 1000) - cov(x2, 1))& < dptol)& , 'dp check 17') call check( all( abs( cov(x2, 2, mask = x2 < 1000) - cov(x2, 2))& < dptol)& , 'dp check 18') end subroutine test_dp subroutine test_int32(x, x2) integer(int32), intent(in) :: x(:) integer(int32), intent(in) :: x2(:, :) call check( abs(cov(x, 1) - 2.5_dp) < dptol& , 'int32 check 1') call check( ieee_is_nan(cov(x, 1, .false.))& , 'int32 check 2') call check( ieee_is_nan((cov(x, 1, x == 1.)))& , 'int32 check 3') call check( abs(cov(x, 1, x < 5) - 5._dp/3) < dptol& , 'int32 check 4') call check( abs(cov(x, 1, x < 5, corrected = .false.) -& 5._dp/4) < dptol& , 'int32 check 5') call check( any(ieee_is_nan(cov(x2, 1, mask = .false.)))& , 'int32 check 6') call check( any(ieee_is_nan(cov(x2, 2, mask = .false.)))& , 'int32 check 7') call check( all( abs( cov(x2, 1) - reshape([& 60._dp/9, 60._dp/9, 30._dp/9& ,60._dp/9, 60._dp/9, 30._dp/9& ,30._dp/9, 30._dp/9, 15._dp/9]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int32 check 8') call check( all( abs( cov(x2, 2) - reshape([& 19._dp, 16.5_dp, 14._dp, 11.5_dp, 16.5_dp, 129._dp/9& ,109.5_dp/9, 10._dp, 14._dp, 109.5_dp/9, 93._dp/9& , 8.5_dp, 11.5_dp, 10._dp, 8.5_dp, 7._dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int32 check 9') call check( all( abs( cov(x2, 1, corrected=.false.) - reshape([& 60._dp/9, 60._dp/9, 30._dp/9& ,60._dp/9, 60._dp/9, 30._dp/9& ,30._dp/9, 30._dp/9, 15._dp/9]& *(size(x2, 1)-1._dp)/size(x2, 1)& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int32 check 10') call check( all( abs( cov(x2, 2, corrected=.false.) - reshape([& 19._dp, 16.5_dp, 14._dp, 11.5_dp, 16.5_dp, 129._dp/9& ,109.5_dp/9, 10._dp, 14._dp, 109.5_dp/9, 93._dp/9& , 8.5_dp, 11.5_dp, 10._dp, 8.5_dp, 7._dp]& *(size(x2, 2)-1._dp)/size(x2, 2)& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int32 check 11') call check( any(ieee_is_nan(cov(x2, 1, mask = x2 < 10)))& , 'int32 check 12') call check( all( abs( cov(x2, 1, mask = x2 < 11) - reshape([& 60._dp/9, 60._dp/9, 1._dp, 60._dp/9, 60._dp/9, 1._dp& , 1._dp, 1._dp, 0.5_dp]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int32 check 13') call check( all( abs( cov(x2, 2, mask = x2 < 11) - reshape([& 19._dp, 16.5_dp, 0.5_dp, 0.5_dp, 16.5_dp& ,129._dp/9, 0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp& ,0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int32 check 14') call check( all( abs( cov(x2, 1, mask = x2 < 11, corrected = .false.) -& reshape([& 5._dp, 5._dp, 0.5_dp, 5._dp, 5._dp, 0.5_dp, 0.5_dp,& 0.5_dp, 0.25_dp]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int32 check 15') call check( all( abs( cov(x2, 2, mask = x2 < 11, corrected = .false.) -& reshape([& 114._dp/9, 11._dp, 0.25_dp, 0.25_dp, 11._dp, 86._dp/9,& 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp,& 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int32 check 16') call check( all( abs( cov(x2, 1, mask = x2 < 1000) - cov(x2, 1))& < dptol)& , 'int32 check 17') call check( all( abs( cov(x2, 2, mask = x2 < 1000) - cov(x2, 2))& < dptol)& , 'int32 check 18') end subroutine test_int32 subroutine test_int64(x, x2) integer(int64), intent(in) :: x(:) integer(int64), intent(in) :: x2(:, :) call check( abs(cov(x, 1) - 2.5_dp) < dptol& , 'int64 check 1') call check( ieee_is_nan(cov(x, 1, .false.))& , 'int64 check 2') call check( ieee_is_nan((cov(x, 1, x == 1)))& , 'int64 check 3') call check( abs(cov(x, 1, x < 5) - 5._dp/3) < dptol& , 'int64 check 4') call check( abs(cov(x, 1, x < 5, corrected = .false.) -& 5._dp/4) < dptol& , 'int64 check 5') call check( any(ieee_is_nan(cov(x2, 1, mask = .false.)))& , 'int64 check 6') call check( any(ieee_is_nan(cov(x2, 2, mask = .false.)))& , 'int64 check 7') call check( all( abs( cov(x2, 1) - reshape([& 60._dp/9, 60._dp/9, 30._dp/9& ,60._dp/9, 60._dp/9, 30._dp/9& ,30._dp/9, 30._dp/9, 15._dp/9]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int64 check 8') call check( all( abs( cov(x2, 2) - reshape([& 19._dp, 16.5_dp, 14._dp, 11.5_dp, 16.5_dp, 129._dp/9& ,109.5_dp/9, 10._dp, 14._dp, 109.5_dp/9, 93._dp/9& , 8.5_dp, 11.5_dp, 10._dp, 8.5_dp, 7._dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int64 check 9') call check( all( abs( cov(x2, 1, corrected=.false.) - reshape([& 60._dp/9, 60._dp/9, 30._dp/9& ,60._dp/9, 60._dp/9, 30._dp/9& ,30._dp/9, 30._dp/9, 15._dp/9]& *(size(x2, 1)-1._dp)/size(x2, 1)& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int64 check 10') call check( all( abs( cov(x2, 2, corrected=.false.) - reshape([& 19._dp, 16.5_dp, 14._dp, 11.5_dp, 16.5_dp, 129._dp/9& ,109.5_dp/9, 10._dp, 14._dp, 109.5_dp/9, 93._dp/9& , 8.5_dp, 11.5_dp, 10._dp, 8.5_dp, 7._dp]& *(size(x2, 2)-1._dp)/size(x2, 2)& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int64 check 11') call check( any(ieee_is_nan(cov(x2, 1, mask = x2 < 10)))& , 'int64 check 12') call check( all( abs( cov(x2, 1, mask = x2 < 11) - reshape([& 60._dp/9, 60._dp/9, 1._dp, 60._dp/9, 60._dp/9, 1._dp& , 1._dp, 1._dp, 0.5_dp]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int64 check 13') call check( all( abs( cov(x2, 2, mask = x2 < 11) - reshape([& 19._dp, 16.5_dp, 0.5_dp, 0.5_dp, 16.5_dp& ,129._dp/9, 0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp& ,0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp, 0.5_dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int64 check 14') call check( all( abs( cov(x2, 1, mask = x2 < 11, corrected = .false.) -& reshape([& 5._dp, 5._dp, 0.5_dp, 5._dp, 5._dp, 0.5_dp, 0.5_dp,& 0.5_dp, 0.25_dp]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int64 check 15') call check( all( abs( cov(x2, 2, mask = x2 < 11, corrected = .false.) -& reshape([& 114._dp/9, 11._dp, 0.25_dp, 0.25_dp, 11._dp, 86._dp/9,& 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp,& 0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int64 check 16') call check( all( abs( cov(x2, 1, mask = x2 < 1000) - cov(x2, 1))& < dptol)& , 'int64 check 17') call check( all( abs( cov(x2, 2, mask = x2 < 1000) - cov(x2, 2))& < dptol)& , 'int64 check 18') end subroutine test_int64 subroutine test_csp(x, x2) complex(sp), intent(in) :: x(:) complex(sp), intent(in) :: x2(:, :) ! complex(sp), allocatable :: cd(:,:) call check( abs(cov(x, dim=1) -& (var(real(x),1) + var(aimag(x), 1)) ) < sptol& , 'csp check 1') call check( abs(cov(x, 1, aimag(x) == 0) -& var(real(x), 1, aimag(x) == 0)) < sptol& , 'csp check 2') call check( abs(cov(x, dim=1, corrected=.false.) -& (var(real(x), dim=1, corrected=.false.) +& var(aimag(x), dim=1, corrected=.false.))) <& sptol& , 'csp check 3') call check( ieee_is_nan(real(cov(x, 1, .false., corrected=.false.)))& , 'csp check 4') call check( abs(cov(x, 1, aimag(x) == 0, corrected=.false.) -& var(real(x), 1, aimag(x) == 0,& corrected=.false.)) < sptol& , 'csp check 5') call check( all( abs( cov(x2, 1) - reshape([& (2.5_sp,0._sp), (5.5_sp,-1._sp), (8.5_sp,-2._sp)& , (5.5_sp,1._sp), (12.5_sp,0._sp), (19.5_sp,-1._sp)& , (8.5_sp,2._sp), (19.5_sp,1._sp), (30.5_sp,0._sp)]& ,[ size(x2, 2), size(x2, 2)])& ) < sptol)& , 'csp check 6') call check( all( abs( cov(x2, 2) - reshape([& (4._sp,0._sp), (0._sp,4._sp),& (0._sp,-4._sp), (4._sp,0._sp)]& ,[ size(x2, 1), size(x2, 1)])& ) < sptol)& , 'csp check 7') call check( all( abs( cov(x2, 1, corrected=.false.) - reshape([& (2.5_sp,0._sp), (5.5_sp,-1._sp), (8.5_sp,-2._sp)& , (5.5_sp,1._sp), (12.5_sp,0._sp), (19.5_sp,-1._sp)& , (8.5_sp,2._sp), (19.5_sp,1._sp), (30.5_sp,0._sp)]& *(size(x2, 1)-1._sp)/size(x2, 1)& ,[ size(x2, 2), size(x2, 2)])& ) < sptol)& , 'csp check 8') call check( all( abs( cov(x2, 2, corrected=.false.) - reshape([& (4._sp,0._sp), (0._sp,4._sp),& (0._sp,-4._sp), (4._sp,0._sp)]& *(size(x2, 2)-1._sp)/size(x2, 2)& ,[ size(x2, 1), size(x2, 1)])& ) < sptol)& , 'csp check 9') ! Issue with gfortran 7 and 8: do not extract cd(1:2, 1:2) correctly ! allocate(cd, source = cov(x2, 1, mask = aimag(x2) < 6)) ! call check( all( abs( cd(1:2, 1:2) - reshape([& ! (2.5_sp,0._sp), (5.5_sp,-1._sp)& ! ,(5.5_sp,1._sp), (12.5_sp,0._sp)]& ! ,[2, 2])& ! ) < sptol)& ! , 'csp check 10') ! call check( ieee_is_nan(real(cd(3,3)))& ! , 'csp check 10 bis') call check( all( abs( cov(x2, 1, mask = aimag(x2) < 8) - cov(x2, 1))& < sptol)& , 'csp check 11') call check( all( abs( cov(x2, 2, mask = aimag(x2) < 8) - cov(x2, 2))& < sptol)& , 'csp check 12') call check( all( abs( cov(x2, 2, mask = aimag(x2) < 6) - reshape([& (4._sp,0._sp), (0._sp,2._sp)& ,(0._sp,-2._sp), (2._sp,0._sp)]& ,[ size(x2, 1), size(x2, 1)])& ) < sptol)& , 'csp check 13') call check( all( abs( cov(x2, 2, mask = aimag(x2) < 6, corrected = .false.) -& reshape([& (2.6666666666666666_sp,0._sp), (0._sp,1._sp)& ,(0._sp,-1._sp), (1._sp,0._sp)]& ,[ size(x2, 1), size(x2, 1)])& ) < sp)& , 'csp check 14') end subroutine test_csp subroutine test_cdp(x, x2) complex(dp), intent(in) :: x(:) complex(dp), intent(in) :: x2(:, :) ! complex(dp), allocatable :: cd(:,:) call check( abs(cov(x, dim=1) -& (var(real(x),1) + var(aimag(x), 1)) ) < dptol& , 'cdp check 1') call check( abs(cov(x, 1, aimag(x) == 0) -& var(real(x), 1, aimag(x) == 0)) < dptol& , 'cdp check 2') call check( abs(cov(x, dim=1, corrected=.false.) -& (var(real(x), dim=1, corrected=.false.) +& var(aimag(x), dim=1, corrected=.false.))) <& dptol& , 'cdp check 3') call check( ieee_is_nan(real(cov(x, 1, .false., corrected=.false.)))& , 'cdp check 4') call check( abs(cov(x, 1, aimag(x) == 0, corrected=.false.) -& var(real(x), 1, aimag(x) == 0,& corrected=.false.)) < dptol& , 'cdp check 5') call check( all( abs( cov(x2, 1) - reshape([& (2.5_dp,0._dp), (5.5_dp,-1._dp), (8.5_dp,-2._dp)& , (5.5_dp,1._dp), (12.5_dp,0._dp), (19.5_dp,-1._dp)& , (8.5_dp,2._dp), (19.5_dp,1._dp), (30.5_dp,0._dp)]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'cdp check 6') call check( all( abs( cov(x2, 2) - reshape([& (4._dp,0._dp), (0._dp,4._dp),& (0._dp,-4._dp), (4._dp,0._dp)]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'cdp check 7') call check( all( abs( cov(x2, 1, corrected=.false.) - reshape([& (2.5_dp,0._dp), (5.5_dp,-1._dp), (8.5_dp,-2._dp)& , (5.5_dp,1._dp), (12.5_dp,0._dp), (19.5_dp,-1._dp)& , (8.5_dp,2._dp), (19.5_dp,1._dp), (30.5_dp,0._dp)]& *(size(x2, 1)-1._dp)/size(x2, 1)& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'cdp check 8') call check( all( abs( cov(x2, 2, corrected=.false.) - reshape([& (4._dp,0._dp), (0._dp,4._dp),& (0._dp,-4._dp), (4._dp,0._dp)]& *(size(x2, 2)-1._dp)/size(x2, 2)& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'cdp check 9') ! Issue with gfortran 7 and 8: do not extract cd(1:2, 1:2) correctly ! allocate(cd, source = cov(x2, 1, mask = aimag(x2) < 6)) ! ! call check( all( abs( cd(1:2, 1:2) - reshape([& ! (2.5_dp,0._dp), (5.5_dp,-1._dp)& ! ,(5.5_dp,1._dp), (12.5_dp,0._dp)]& ! ,[2, 2])& ! ) < dptol)& ! , 'cdp check 10') ! call check( ieee_is_nan(real(cd(3,3)))& ! , 'cdp check 10 bis') call check( all( abs( cov(x2, 1, mask = aimag(x2) < 8) - cov(x2, 1))& < dptol)& , 'cdp check 11') call check( all( abs( cov(x2, 2, mask = aimag(x2) < 8) - cov(x2, 2))& < dptol)& , 'cdp check 12') call check( all( abs( cov(x2, 2, mask = aimag(x2) < 6) - reshape([& (4._dp,0._dp), (0._dp,2._dp)& ,(0._dp,-2._dp), (2._dp,0._dp)]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'cdp check 13') call check( all( abs( cov(x2, 2, mask = aimag(x2) < 6, corrected = .false.) -& reshape([& (2.6666666666666666_dp,0._dp), (0._dp,1._dp)& ,(0._dp,-1._dp), (1._dp,0._dp)]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'cdp check 14') end subroutine test_cdp end program test_cov fortran-lang-stdlib-0ede301/test/stats/test_varn.f900000664000175000017500000005620215135654166022635 0ustar alastairalastairmodule test_varn use, intrinsic :: ieee_arithmetic, only: ieee_is_nan use stdlib_kinds, only: sp, dp, int32 use stdlib_stats, only: var use testdrive, only: new_unittest, unittest_type, error_type, check implicit none private public :: collect_varn, initialize_test_data real(sp), parameter :: sptol = 1000 * epsilon(1._sp) real(dp), parameter :: dptol = 1000 * epsilon(1._dp) integer(int32) :: i321(5) = [1, 2, 3, 4, 5] integer(int32), allocatable :: i32(:,:), i323(:,:,:) real(sp) :: s1(5) = [1._sp, 2._sp, 3._sp, 4._sp, 5._sp] real(dp) :: d1(5) = [1._dp, 2._dp, 3._dp, 4._dp, 5._dp] real(sp), allocatable :: s(:,:), s3(:,:,:) real(dp), allocatable :: d3(:,:,:) real(dp) :: d(4,3) = reshape([1._dp, 3._dp, 5._dp, 7._dp, & 2._dp, 4._dp, 6._dp, 8._dp, & 9._dp, 10._dp, 11._dp, 12._dp], [4, 3]) complex(dp) :: cd1(5) = [(0.57706_dp, 0.00000_dp), & (0.00000_dp, 1.44065_dp), & (1.26401_dp, 0.00000_dp), & (0.00000_dp, 0.88833_dp), & (1.14352_dp, 0.00000_dp)] complex(dp) :: cd(5,3) contains subroutine initialize_test_data() s = d i32 = d allocate(s3(size(s, 1),size(s, 2),3)) s3(:,:,1) = s s3(:,:,2) = s * 2 s3(:,:,3) = s * 4 allocate(d3(size(d, 1),size(d, 2),3)) d3(:,:,1) = d d3(:,:,2) = d * 2 d3(:,:,3) = d * 4 allocate(i323(size(i32, 1),size(i32, 2),3)) i323(:,:,1) = i32 i323(:,:,2) = i32 * 2 i323(:,:,3) = i32 * 4 cd(:,1) = cd1 cd(:,2) = cd1 * 3_sp cd(:,3) = cd1 * 1.5_sp end subroutine initialize_test_data !> Collect all exported unit tests subroutine collect_varn(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest('varn_sp_1dim', test_sp_1dim), & new_unittest('varn_sp_1dim_mask', test_sp_1dim_mask), & new_unittest('varn_sp_1dim_mask_array', test_sp_1dim_mask_array), & new_unittest('varn_sp_2dim', test_sp_2dim), & new_unittest('varn_sp_2dim_mask', test_sp_2dim_mask), & new_unittest('varn_sp_2dim_mask_array', test_sp_2dim_mask_array), & new_unittest('varn_sp_3dim', test_sp_3dim), & new_unittest('varn_sp_3dim_mask', test_sp_3dim_mask), & new_unittest('varn_sp_3dim_mask_array', test_sp_3dim_mask_array), & new_unittest('varn_dp_1dim', test_dp_1dim), & new_unittest('varn_dp_1dim_mask', test_dp_1dim_mask), & new_unittest('varn_dp_1dim_mask_array', test_dp_1dim_mask_array), & new_unittest('varn_dp_2dim', test_dp_2dim), & new_unittest('varn_dp_2dim_mask', test_dp_2dim_mask), & new_unittest('varn_dp_2dim_mask_array', test_dp_2dim_mask_array), & new_unittest('varn_dp_3dim', test_dp_3dim), & new_unittest('varn_dp_3dim_mask', test_dp_3dim_mask), & new_unittest('varn_dp_3dim_mask_array', test_dp_3dim_mask_array), & new_unittest('varn_int32_1dim', test_int32_1dim), & new_unittest('varn_int32_1dim_mask', test_int32_1dim_mask), & new_unittest('varn_int32_1dim_mask_array', test_int32_1dim_mask_array), & new_unittest('varn_int32_2dim', test_int32_2dim), & new_unittest('varn_int32_2dim_mask', test_int32_2dim_mask), & new_unittest('varn_int32_2dim_mask_array', test_int32_2dim_mask_array), & new_unittest('varn_int32_3dim', test_int32_3dim), & new_unittest('varn_int32_3dim_mask', test_int32_3dim_mask), & new_unittest('varn_int32_3dim_mask_array', test_int32_3dim_mask_array), & new_unittest('varn_cdp_1dim', test_cdp_1dim), & new_unittest('varn_cdp_1dim_mask', test_cdp_1dim_mask), & new_unittest('varn_cdp_1dim_mask_array', test_cdp_1dim_mask_array), & new_unittest('varn_cdp_2dim', test_cdp_2dim), & new_unittest('varn_cdp_2dim_mask', test_cdp_2dim_mask), & new_unittest('varn_cdp_2dim_mask_array', test_cdp_2dim_mask_array) & ] end subroutine test_sp_1dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s1, corrected=.false.) - 2.5*(4./5.)) < sptol) call check(error, abs(var(s1, dim=1, corrected=.false.) - 2.5*(4./5.)) < sptol) end subroutine test_sp_1dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(s1, .false., corrected=.false.))) call check(error, ieee_is_nan(var(s1, 1, .false., corrected=.false.))) end subroutine test_sp_1dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s1, s1 < 5, corrected=.false.) - 5./4.) < sptol) call check(error, ieee_is_nan((var(s1, s1 < 0., corrected=.false.)))) call check(error, abs(var(s1, s1 == 1., corrected=.false.)) < sptol) call check(error, abs(var(s1, 1, s1 < 5, corrected=.false.) - 5./4.) < sptol) end subroutine test_sp_2dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s, corrected=.false.) - 13.*11./12.) < sptol) call check(error, all(abs(var(s, 1, corrected=.false.) & - [20., 20., 5.]/4.) < sptol)) call check(error, all(abs(var(s, 2, corrected=.false.) & - [19., 43./3., 31./ 3., 7.0]*2./3.) < sptol)) end subroutine test_sp_2dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(s, .false., corrected=.false.))) call check(error, any(ieee_is_nan(var(s, 1, .false., corrected=.false.)))) call check(error, any(ieee_is_nan(var(s, 2, .false., corrected=.false.)))) end subroutine test_sp_2dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s, s < 11, corrected=.false.) - 2.75*3.) < sptol) call check(error, all(abs(var(s, 1, s < 11, corrected=.false.) & - [5., 5., 0.25]) < sptol)) call check(error, all(abs(var(s, 2, s < 11, corrected=.false.) & - [19.0*2./3., 43./9.*2., 0.25 , 0.25]) < sptol)) end subroutine test_sp_3dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s3, corrected=.false.) - 153.4*35./36.) < sptol) call check(error, all(abs(var(s3, 1, corrected=.false.) -& reshape([20. / 3., 20. / 3., 5. / 3.,& 4* 20. / 3., 4* 20. / 3., 4* 5. / 3.,& 16* 20. / 3., 16* 20. / 3., 16* 5. / 3.],& [size(s3, 2), size(s3, 3)])*3./4.)& < sptol)) call check(error, all(abs(var(s3, 2, corrected=.false.) -& reshape([19.0, 43. / 3., 31. / 3. , 7.0,& 4* 19.0, 4* 43. / 3., 4* 31. / 3. , 4* 7.0,& 16* 19.0, 16* 43. / 3., 16* 31. / 3. , 16* 7.0],& [size(s3, 1), size(s3, 3)])*2./3.)& < sptol)) call check(error, all(abs(var(s3, 3, corrected=.false.) -& reshape([ 7./3., 21., 175./3.,& 343./3., 28./3., 112./3.,& 84., 448./3., 189.,& 700./3., 847./3., 336.], [size(s3,1), size(s3,2)] )*2./3.)& < sptol)) end subroutine test_sp_3dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(s3, .false., corrected=.false.))) call check(error, any(ieee_is_nan(var(s3, 1, .false., corrected=.false.)))) call check(error, any(ieee_is_nan(var(s3, 2, .false., corrected=.false.)))) call check(error, any(ieee_is_nan(var(s3, 3, .false., corrected=.false.)))) end subroutine test_sp_3dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s3, s3 < 11, corrected=.false.) - 7.73702383_sp) < sptol) call check(error, all( abs( var(s3, 1, s3 < 45, corrected=.false.) -& reshape([5., 5., 1.25, 20., 20., 5., 80., 80., 32./3.],& [size(s3, 2), size(s3, 3)])) < sptol )) call check(error, all( abs( var(s3, 2, s3 < 45, corrected=.false.) -& reshape([ 38./3., 86./9., 6.88888931, 14./3., 152./3.,& 38.2222214, 27.5555573, 18.6666660, 202.666672,& 152.888885, 110.222229, 4.& ],& [size(s3, 1), size(s3, 3)])) < sptol )) call check(error, all( abs( var(s3, 3, s3 < 45, corrected=.false.) -& reshape([1.555555, 14., 38.888888, 76.222222, 6.2222222,& 24.888888, 56., 99.5555, 126., 155.555555, 188.22222, 36.& ], [size(s3,1), size(s3,2)] ))& < sptol )) end subroutine test_dp_1dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d1, corrected=.false.) - 2.5_dp*(4._dp/5.)) < dptol) call check(error, abs(var(d1, dim=1, corrected=.false.) - 2.5_dp*(4._dp/5.)) < dptol) end subroutine test_dp_1dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(d1, .false., corrected=.false.))) call check(error, ieee_is_nan(var(d1, 1, .false., corrected=.false.))) end subroutine test_dp_1dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d1, d1 < 5, corrected=.false.) - 5._dp/4.) < dptol) call check(error, ieee_is_nan((var(d1, d1 < 0, corrected=.false.)))) call check(error, abs(var(d1, d1 == 1, corrected=.false.)) < dptol) call check(error, abs(var(d1, 1, d1 < 5, corrected=.false.) - 5._dp/4.) < dptol) end subroutine test_dp_2dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d, corrected=.false.) - 13._dp*11./12.) < dptol) call check(error, all( abs( var(d, 1, corrected=.false.) - [20., 20., 5.]/4._dp) < dptol)) call check(error, all( abs( var(d, 2, corrected=.false.) -& [38._dp, 86._dp / 3._dp, 62._dp / 3._dp , 14._dp]/3._dp) < dptol)) end subroutine test_dp_2dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(d, .false., corrected=.false.))) call check(error, any(ieee_is_nan(var(d, 1, .false., corrected=.false.)))) call check(error, any(ieee_is_nan(var(d, 2, .false., corrected=.false.)))) end subroutine test_dp_2dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d, d < 11, corrected=.false.) - 2.75_dp*3._dp) < dptol) call check(error, all( abs( var(d, 1, d < 11, corrected=.false.) -& [5._dp, 5._dp, 0.25_dp]) < dptol)) call check(error, all( abs( var(d, 2, d < 11, corrected=.false.) -& [38._dp/3., 86._dp/9., 0.25_dp , 0.25_dp]) < dptol)) end subroutine test_dp_3dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d3, corrected=.false.) - 153.4_dp*35._dp/36._dp) < dptol) call check(error, all( abs( var(d3, 1, corrected=.false.) -& reshape([20._dp , 20._dp , 5._dp ,& 4* 20._dp , 4* 20._dp , 4* 5._dp ,& 16* 20._dp , 16* 20._dp , 16* 5._dp ],& [size(d3,2), size(d3,3)])/4._dp)& < dptol)) call check(error, all( abs( var(d3, 2, corrected=.false.) -& reshape([38._dp, 86. / 3._dp, 62. / 3._dp , 14._dp,& 8* 19._dp, 8* 43. / 3._dp, 8* 31. / 3._dp, 8* 7._dp,& 32* 19._dp, 32* 43. / 3._dp, 32* 31. / 3._dp, 32* 7._dp],& [size(d3,1), size(d3,3)] )/3._dp)& < dptol)) call check(error, all(abs( var(d3, 3, corrected=.false.) -& reshape([7._dp/3., 21._dp, 175._dp/3.,& 343._dp/3., 28._dp/3., 112._dp/3.,& 84._dp, 448._dp/3., 189._dp,& 700._dp/3., 847._dp/3., 336._dp],& [size(d3, 1), size(d3, 2)] )*2._dp/3._dp)& < dptol)) end subroutine test_dp_3dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(d3, .false., corrected=.false.))) call check(error, any(ieee_is_nan(var(d3, 1, .false., corrected=.false.)))) call check(error, any(ieee_is_nan(var(d3, 2, .false., corrected=.false.)))) call check(error, any(ieee_is_nan(var(d3, 3, .false., corrected=.false.)))) end subroutine test_dp_3dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d3, d3 < 11, corrected=.false.) -& 7.7370242214532876_dp) < dptol) call check(error, all(abs(var(d3, 1, d3 < 45, corrected=.false.) -& reshape([5._dp, 5._dp, 1.25_dp, 20._dp, 20._dp, 5._dp,& 80._dp, 80._dp, 32._dp/3.],& [size(d3, 2), size(d3, 3)])) < dptol)) call check(error, all(abs( var(d3, 2, d3 < 45, corrected=.false.) -& reshape([38._dp/3., 86._dp/9., 62._dp/9., 14._dp/3., 152._dp/3.,& 344._dp/9., 248._dp/9., 168._dp/9., 1824._dp/9.,& 1376._dp/9., 992._dp/9., 4._dp& ],& [size(d3, 1), size(d3, 3)])) < dptol)) call check(error, all(abs(var(d3, 3, d3 < 45, corrected=.false.) -& reshape([14._dp/9., 14._dp, 350._dp/9., 686._dp/9., 56._dp/9.,& 224._dp/9., 56._dp, 896._dp/9., 126._dp, 1400._dp/9.,& 1694._dp/9., 36._dp& ], [size(d3, 1), size(d3, 2)]))& < dptol )) end subroutine test_int32_1dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i321, corrected=.false.) - 2.5_dp*(4._dp/5.)) < dptol) call check(error, abs(var(i321, dim=1, corrected=.false.) - 2.5_dp*(4._dp/5.)) < dptol) end subroutine test_int32_1dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(i321, .false., corrected=.false.))) call check(error, ieee_is_nan(var(i321, 1, .false., corrected=.false.))) end subroutine test_int32_1dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i321, i321 < 5, corrected=.false.) - 5._dp/4.) < dptol) call check(error, ieee_is_nan((var(i321, i321 < 0, corrected=.false.)))) call check(error, abs(var(i321, i321 == 1, corrected=.false.)) < dptol) call check(error, abs(var(i321, 1, i321 < 5, corrected=.false.) - 5._dp/4.) < dptol) end subroutine test_int32_2dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i32, corrected=.false.) - 13._dp*11./12.) < dptol) call check(error, all(abs(var(i32, 1, corrected=.false.) -& [20., 20., 5.]/4._dp) < dptol)) call check(error, all(abs(var(i32, 2, corrected=.false.) -& [38._dp, 86._dp / 3._dp, 62._dp / 3._dp , 14._dp]/3._dp) < dptol)) end subroutine test_int32_2dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(i32, .false., corrected=.false.))) call check(error, any(ieee_is_nan(var(i32, 1, .false., corrected=.false.)))) call check(error, any(ieee_is_nan(var(i32, 2, .false., corrected=.false.)))) end subroutine test_int32_2dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i32, i32 < 11, corrected=.false.) - 2.75_dp*3._dp) < dptol) call check(error, all(abs(var(i32, 1, i32 < 11, corrected=.false.) -& [5._dp, 5._dp, 0.25_dp]) < dptol)) call check(error, all(abs(var(i32, 2, i32 < 11, corrected=.false.) -& [38._dp/3., 86._dp/9., 0.25_dp , 0.25_dp]) < dptol)) end subroutine test_int32_3dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i323, corrected=.false.) - 153.4_dp*35._dp/36._dp) < dptol) call check(error, all(abs(var(i323, 1, corrected=.false.) -& reshape([20._dp , 20._dp , 5._dp ,& 4* 20._dp , 4* 20._dp , 4* 5._dp ,& 16* 20._dp , 16* 20._dp , 16* 5._dp ],& [size(i323,2), size(i323,3)])/4._dp)& < dptol)) call check(error, all(abs(var(i323, 2, corrected=.false.) -& reshape([38._dp, 86. / 3._dp, 62. / 3._dp , 14._dp,& 8* 19._dp, 8* 43. / 3._dp, 8* 31. / 3._dp, 8* 7._dp,& 32* 19._dp, 32* 43. / 3._dp, 32* 31. / 3._dp, 32* 7._dp],& [size(i323,1), size(i323,3)] )/3._dp)& < dptol)) call check(error, all(abs(var(i323, 3, corrected=.false.) -& reshape([ 7._dp/3., 21._dp, 175._dp/3.,& 343._dp/3., 28._dp/3., 112._dp/3.,& 84._dp, 448._dp/3., 189._dp,& 700._dp/3., 847._dp/3., 336._dp],& [size(i323,1), size(i323,2)] )*2._dp/3._dp)& < dptol)) end subroutine test_int32_3dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(i323, .false., corrected=.false.))) call check(error, any(ieee_is_nan(var(i323, 1, .false., corrected=.false.)))) call check(error, any(ieee_is_nan(var(i323, 2, .false., corrected=.false.)))) call check(error, any(ieee_is_nan(var(i323, 3, .false., corrected=.false.)))) end subroutine test_int32_3dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i323, i323 < 11, corrected=.false.) -& 7.7370242214532876_dp) < dptol) call check(error, all(abs(var(i323, 1, i323 < 45, corrected=.false.) -& reshape([5._dp, 5._dp, 1.25_dp, 20._dp, 20._dp, 5._dp,& 80._dp, 80._dp, 32._dp/3.],& [size(i323, 2), size(i323, 3)])) < dptol )) call check(error, all(abs(var(i323, 2, i323 < 45, corrected=.false.) -& reshape([ 38._dp/3., 86._dp/9., 62._dp/9., 14._dp/3., 152._dp/3.,& 344._dp/9., 248._dp/9., 168._dp/9., 1824._dp/9.,& 1376._dp/9., 992._dp/9., 4._dp& ],& [size(i323, 1), size(i323, 3)])) < dptol )) call check(error, all(abs(var(i323, 3, i323 < 45, corrected=.false.) -& reshape([14._dp/9., 14._dp, 350._dp/9., 686._dp/9., 56._dp/9.,& 224._dp/9., 56._dp, 896._dp/9., 126._dp, 1400._dp/9.,& 1694._dp/9., 36._dp& ], [size(i323,1), size(i323,2)] ))& < dptol )) end subroutine test_cdp_1dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cd1, corrected=.false.) -& (var(real(cd1), corrected=.false.) +& var(aimag(cd1), corrected=.false.))) < dptol) call check(error, abs(var(cd1, dim=1, corrected=.false.) -& (var(real(cd1), dim=1, corrected=.false.) +& var(aimag(cd1), dim=1, corrected=.false.))) < dptol) end subroutine test_cdp_1dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(cd1, .false., corrected=.false.))) call check(error, ieee_is_nan(var(cd1, 1, .false., corrected=.false.))) end subroutine test_cdp_1dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cd1, cd1%im == 0, corrected=.false.) & - var(cd1%re, cd1%im == 0, corrected=.false.)) < dptol) call check(error, abs(var(cd1, 1, cd1%im == 0, corrected=.false.) & - var(cd1%re, 1, cd1%im == 0, corrected=.false.)) < dptol) call check(error, ieee_is_nan((var(cd1, all([cd1%re, cd1%im] == 0), & corrected=.false.)))) call check(error, abs(var(cd1, (cd1%re > 1.2 .and. cd1%im == 0), & corrected=.false.)) < dptol) end subroutine test_cdp_2dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cd, corrected=.false.) & - (var(cd%re, corrected=.false.) & + var(cd%im, corrected=.false.))) < dptol) call check(error, all(abs(var(cd, 1, corrected=.false.) & - (var(cd%re, 1, corrected=.false.) & + var(cd%im, 1, corrected=.false.))) < dptol)) call check(error, all(abs(var(cd, 2, corrected=.false.) & - (var(cd%re, 2, corrected=.false.) & + var(cd%im, 2, corrected=.false.))) < dptol)) end subroutine test_cdp_2dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(cd, .false., corrected=.false.))) call check(error, any(ieee_is_nan(var(cd, 1, .false., corrected=.false.)))) call check(error, any(ieee_is_nan(var(cd, 2, .false., corrected=.false.)))) end subroutine test_cdp_2dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cd, cd%im == 0, corrected=.false.) & - var(cd%re, cd%im == 0, corrected=.false.)) < dptol) call check(error, all(abs(var(cd, 1, cd%im == 0, corrected=.false.) & - var(cd%re, 1, cd%im == 0, corrected=.false.)) < dptol)) call check(error, any(ieee_is_nan(var(cd, 2, cd%im == 0, corrected=.false.)))) end end module test_varn program tester use, intrinsic :: iso_fortran_env, only: error_unit use testdrive, only: run_testsuite, new_testsuite, testsuite_type use test_varn, only: collect_varn, initialize_test_data implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite('varn', collect_varn) & ] call initialize_test_data() do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/stats/test_random.f900000664000175000017500000001044515135654166023146 0ustar alastairalastairmodule test_stats_random use stdlib_kinds, only: int8, int16, int32, int64 use stdlib_random, only : random_seed, dist_rand use testdrive, only: new_unittest, unittest_type, error_type, check implicit none private public :: collect_stats_random contains !> Collect all exported unit tests subroutine collect_stats_random(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("random_seed", test_random_seed), & new_unittest("random_rand_iint8", test_random_rand_iint8), & new_unittest("random_rand_iint16", test_random_rand_iint8), & new_unittest("random_rand_iint32", test_random_rand_iint8), & new_unittest("random_rand_iint64", test_random_rand_iint8) & ] end subroutine collect_stats_random subroutine test_random_seed(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: put, get, res(5) integer :: ans(5) = [-1859553078, -1933696596, -642834430, & 1711399314, 1548311463] integer :: i put = 135792468 do i = 1, 5 call random_seed(put, get) res(i) = get put = get end do call check(error, all(res == ans)) end subroutine test_random_seed subroutine test_random_rand_iint8(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: put, get, i integer(int8) :: res(5), ans(5) = [118, -15, -72, 101, 70] put = 12345678 call random_seed(put, get) do i = 1, 5 res(i) = dist_rand(1_int8) end do call check(error, all(res == ans)) end subroutine test_random_rand_iint8 subroutine test_random_rand_iint16(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: put, get, i integer(int16) :: res(5), ans(5) = [30286, -3799, -18204, 25947, 18148] put = 12345678 call random_seed(put, get) do i = 1, 5 res(i) = dist_rand(1_int16) end do call check(error, all(res == ans)) end subroutine test_random_rand_iint16 subroutine test_random_rand_iint32(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: put, get, i integer(int32) :: res(5), ans(5)=[1984865646, -248954393, -1192993267, & 1700514835, 1189401802] put = 12345678 call random_seed(put, get) do i = 1, 5 res(i) = dist_rand(1_int32) end do call check(error, all(res == ans)) end subroutine test_random_rand_iint32 subroutine test_random_rand_iint64(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: put, get, i integer(int64) :: res(5), ans(5)=[8524933037632333570_int64, & -1069250973542918798_int64, & -5123867065024149335_int64, & 7303655603304982073_int64, & 5108441843522503546_int64] put = 12345678 call random_seed(put, get) do i = 1, 5 res(i) = dist_rand(1_int64) end do call check(error, all(res == ans)) end subroutine test_random_rand_iint64 end module test_stats_random program tester use iso_fortran_env, only: error_unit use testdrive, only: new_testsuite, run_testsuite, testsuite_type use test_stats_random, only: collect_stats_random implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("stats_random", collect_stats_random) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/stats/test_mean.fypp0000664000175000017500000003717415135654166023176 0ustar alastairalastair#:include "common.fypp" #:set IR_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES #:set NRANK = 4 module test_stats_mean use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_stats, only: mean use stdlib_kinds, only : int8, int16, int32, int64, sp, dp, xdp, qp use, intrinsic :: ieee_arithmetic, only : ieee_is_nan implicit none private public :: collect_stats_mean real(sp), parameter :: sptol = 1000 * epsilon(1._sp) real(dp), parameter :: dptol = 2000 * epsilon(1._dp) #:if WITH_XDP real(xdp), parameter :: xdptol = 2000 * epsilon(1._xdp) #:endif #:if WITH_QP real(qp), parameter :: qptol = 2000 * epsilon(1._qp) #:endif #:for k1,t1 in IR_KINDS_TYPES ${t1}$ , parameter :: d1_${k1}$(18) = [-10, 2, 3, 4, -6, 6, -7, 8, 9, 4, 1, -20, 9, 10, 14, 15, 40, 30] ${t1}$ :: d2_${k1}$(3, 6) = reshape(d1_${k1}$, [3, 6]) ${t1}$ :: d3_${k1}$(3, 2, 3) = reshape(d1_${k1}$, [3, 2, 3]) ${t1}$ :: d4_${k1}$(3, 2, 3, 2) = reshape(d1_${k1}$, [3, 2, 3, 2], [${t1}$ :: 3]) #:endfor #:for k1,t1 in CMPLX_KINDS_TYPES ${t1}$ , parameter :: d1_c${k1}$(18) = d1_${k1}$ ${t1}$ :: d2_c${k1}$(3, 6) = reshape(d1_c${k1}$, [3, 6]) ${t1}$ :: d3_c${k1}$(3, 2, 3) = reshape(d1_c${k1}$, [3, 2, 3]) ${t1}$ :: d4_c${k1}$(3, 2, 3, 2) = reshape(d1_c${k1}$, [3, 2, 3, 2], [${t1}$ :: (3, -2)] ) #:endfor contains !> Collect all exported unit tests subroutine collect_stats_mean(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("test_stats_mean_all_int8", test_stats_mean_all_int8) & #:for k1,t1 in IR_KINDS_TYPES ,new_unittest("test_stats_mean_all_${k1}$", test_stats_mean_all_${k1}$) & , new_unittest("test_stats_mean_all_optmask_${k1}$", test_stats_mean_all_optmask_${k1}$) & , new_unittest("test_stats_mean_${k1}$", test_stats_mean_${k1}$) & , new_unittest("test_stats_mean_optmask_${k1}$", test_stats_mean_optmask_${k1}$) & , new_unittest("test_stats_mean_mask_all_${k1}$", test_stats_mean_mask_all_${k1}$) & , new_unittest("test_stats_mean_mask_${k1}$", test_stats_mean_mask_${k1}$) & #:endfor #:for k1,t1 in CMPLX_KINDS_TYPES ,new_unittest("test_stats_mean_all_c${k1}$", test_stats_mean_all_c${k1}$) & , new_unittest("test_stats_mean_all_optmask_c${k1}$", test_stats_mean_all_optmask_c${k1}$) & , new_unittest("test_stats_mean_c${k1}$", test_stats_mean_c${k1}$) & , new_unittest("test_stats_mean_optmask_c${k1}$", test_stats_mean_optmask_c${k1}$) & , new_unittest("test_stats_mean_mask_all_c${k1}$", test_stats_mean_mask_all_c${k1}$) & , new_unittest("test_stats_mean_mask_c${k1}$", test_stats_mean_mask_c${k1}$) & #:endfor ] end subroutine collect_stats_mean #:for k1,t1 in INT_KINDS_TYPES subroutine test_stats_mean_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for rank in range(1, NRANK + 1) call check(error, mean(d${rank}$_${k1}$), sum(real(d${rank}$_${k1}$, dp))/real(size(d${rank}$_${k1}$), dp)& , 'mean(d${rank}$_${k1}$): uncorrect answer'& , thr = dptol) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_mean_all_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for rank in range(1, NRANK + 1) call check(error, ieee_is_nan(mean(d${rank}$_${k1}$, .false.))& , 'mean(d${rank}$_${k1}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor end subroutine subroutine test_stats_mean_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error& , abs(mean(d1_${k1}$, 1) -& sum(real(d1_${k1}$, dp), 1)/real(size(d1_${k1}$, 1), dp)) < dptol& , 'mean(d1_${k1}$, 1): uncorrect answer'& ) if (allocated(error)) return #:for rank in range(2, NRANK+1) #:for dim in range(1, rank+1) call check(error& , sum(abs(mean(d${rank}$_${k1}$, ${dim}$) -& sum(real(d${rank}$_${k1}$, dp), ${dim}$)/real(size(d${rank}$_${k1}$, ${dim}$), dp))) < dptol& , 'mean(d${rank}$_${k1}$, ${dim}$): uncorrect answer'& ) if (allocated(error)) return #:endfor #:endfor end subroutine subroutine test_stats_mean_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(mean(d1_${k1}$, 1, .false.))& , 'mean(d1_${k1}$, 1, .false.): uncorrect answer'& ) if (allocated(error)) return #:for rank in range(2, NRANK+1) #:for dim in range(1, rank+1) call check(error, any(ieee_is_nan(mean(d${rank}$_${k1}$, ${dim}$, .false.)))& , 'mean(d${rank}$_${k1}$, ${dim}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor #:endfor end subroutine subroutine test_stats_mean_mask_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for rank in range(1, NRANK+1) call check(error, mean(d${rank}$_${k1}$, d${rank}$_${k1}$ > 0)& , sum(real(d${rank}$_${k1}$, dp), d${rank}$_${k1}$ > 0)/real(count(d${rank}$_${k1}$ > 0), dp)& , 'mean(d${rank}$_${k1}$, d${rank}$_${k1}$ > 0): uncorrect answer'& , thr = dptol) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_mean_mask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error& , abs(mean(d1_${k1}$, 1, d1_${k1}$ > 0) -& sum(real(d1_${k1}$, dp), 1, d1_${k1}$ > 0)/real(count(d1_${k1}$ > 0, 1), dp)) < dptol& , 'mean(d1_${k1}$, 1, d1_${k1}$ > 0): uncorrect answer'& ) if (allocated(error)) return #:for rank in range(2, NRANK+1) #:for dim in range(1, rank+1) call check(error& , sum(abs(mean(d${rank}$_${k1}$, ${dim}$, d${rank}$_${k1}$ > 0) -& sum(real(d${rank}$_${k1}$, dp), ${dim}$, d${rank}$_${k1}$ > 0)/real(count(d${rank}$_${k1}$ > 0, ${dim}$), dp))) < dptol& , 'mean(d${rank}$_${k1}$, ${dim}$, d${rank}$_${k1}$ > 0): uncorrect answer'& ) if (allocated(error)) return #:endfor #:endfor end subroutine #:endfor #:for k1,t1 in REAL_KINDS_TYPES subroutine test_stats_mean_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for rank in range(1, NRANK+1) call check(error, mean(d${rank}$_${k1}$), sum(d${rank}$_${k1}$)/real(size(d${rank}$_${k1}$), ${k1}$)& , 'mean(d${rank}$_${k1}$): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_mean_all_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for rank in range(1, NRANK+1) call check(error, ieee_is_nan(mean(d${rank}$_${k1}$, .false.))& , 'mean(d${rank}$_${k1}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor end subroutine subroutine test_stats_mean_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error& , abs(mean(d1_${k1}$, 1) - sum(d1_${k1}$, 1)/real(size(d1_${k1}$, 1), ${k1}$)) <${k1}$tol& , 'mean(d1_${k1}$, 1): uncorrect answer'& ) if (allocated(error)) return #:for rank in range(2, NRANK+1) #:for dim in range(1, rank+1) call check(error& , sum(abs(mean(d${rank}$_${k1}$, ${dim}$) -& sum(d${rank}$_${k1}$, ${dim}$)/real(size(d${rank}$_${k1}$, ${dim}$), ${k1}$))) < ${k1}$tol& , 'mean(d${rank}$_${k1}$, ${dim}$): uncorrect answer'& ) if (allocated(error)) return #:endfor #:endfor end subroutine subroutine test_stats_mean_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(mean(d1_${k1}$, 1, .false.))& , 'mean(d1_${k1}$, 1, .false.): uncorrect answer'& ) if (allocated(error)) return #:for rank in range(2, NRANK+1) #:for dim in range(1, rank+1) call check(error, any(ieee_is_nan(mean(d${rank}$_${k1}$, ${dim}$, .false.)))& , 'mean(d${rank}$_${k1}$, ${dim}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor #:endfor end subroutine subroutine test_stats_mean_mask_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for rank in range(1, NRANK+1) call check(error, mean(d${rank}$_${k1}$, d${rank}$_${k1}$ > 0)& , sum(d${rank}$_${k1}$, d${rank}$_${k1}$ > 0)/real(count(d${rank}$_${k1}$ > 0), ${k1}$)& , 'mean(d${rank}$_${k1}$, d${rank}$_${k1}$ > 0): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_mean_mask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error& , abs(mean(d1_${k1}$, 1, d1_${k1}$ > 0) -& sum(d1_${k1}$, 1, d1_${k1}$ > 0)/real(count(d1_${k1}$ > 0, 1), ${k1}$)) < ${k1}$tol& , 'mean(d1_${k1}$, 1, d1_${k1}$ > 0): uncorrect answer'& ) if (allocated(error)) return #:for rank in range(2, NRANK+1) #:for dim in range(1, rank+1) call check(error& , sum(abs(mean(d${rank}$_${k1}$, ${dim}$, d${rank}$_${k1}$ > 0) -& sum(d${rank}$_${k1}$, ${dim}$, d${rank}$_${k1}$ > 0)/real(count(d${rank}$_${k1}$ > 0, ${dim}$), ${k1}$))) < ${k1}$tol& , 'mean(d${rank}$_${k1}$, ${dim}$, d${rank}$_${k1}$ > 0): uncorrect answer'& ) if (allocated(error)) return #:endfor #:endfor end subroutine #:endfor #:for k1,t1 in CMPLX_KINDS_TYPES subroutine test_stats_mean_all_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for rank in range(1, NRANK+1) call check(error, mean(d${rank}$_c${k1}$), sum(d${rank}$_c${k1}$)/real(size(d${rank}$_c${k1}$), ${k1}$)& , 'mean(d${rank}$_c${k1}$): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_mean_all_optmask_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for rank in range(1, NRANK+1) call check(error, ieee_is_nan(real(mean(d${rank}$_c${k1}$, .false.)))& , 'mean(d${rank}$_c${k1}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor end subroutine subroutine test_stats_mean_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error& , abs(mean(d1_c${k1}$, 1) - sum(d1_c${k1}$, 1)/real(size(d1_c${k1}$, 1), ${k1}$)) <${k1}$tol& , 'mean(d1_c${k1}$, 1): uncorrect answer'& ) if (allocated(error)) return #:for rank in range(2, NRANK+1) #:for dim in range(1, rank+1) call check(error& , sum(abs(mean(d${rank}$_c${k1}$, ${dim}$) -& sum(d${rank}$_c${k1}$, ${dim}$)/real(size(d${rank}$_c${k1}$, ${dim}$), ${k1}$))) < ${k1}$tol& , 'mean(d${rank}$_c${k1}$, ${dim}$): uncorrect answer'& ) if (allocated(error)) return #:endfor #:endfor end subroutine subroutine test_stats_mean_optmask_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(real(mean(d1_c${k1}$, 1, .false.)))& , 'mean(d1_c${k1}$, 1, .false.): uncorrect answer'& ) if (allocated(error)) return #:for rank in range(2, NRANK+1) #:for dim in range(1, rank+1) call check(error, any(ieee_is_nan(real(mean(d${rank}$_c${k1}$, ${dim}$, .false.))))& , 'mean(d${rank}$_c${k1}$, ${dim}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor #:endfor end subroutine subroutine test_stats_mean_mask_all_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:for rank in range(1, NRANK+1) call check(error, mean(d${rank}$_c${k1}$, d${rank}$_c${k1}$%re > 0)& , sum(d${rank}$_c${k1}$, d${rank}$_c${k1}$%re > 0)/real(count(d${rank}$_c${k1}$%re > 0), ${k1}$)& , 'mean(d${rank}$_c${k1}$, d${rank}$_c${k1}$%re > 0): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return #:endfor end subroutine subroutine test_stats_mean_mask_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error& , abs(mean(d1_c${k1}$, 1, d1_c${k1}$%re > 0) -& sum(d1_c${k1}$, 1, d1_c${k1}$%re > 0)/real(count(d1_c${k1}$%re > 0, 1), ${k1}$)) < ${k1}$tol& , 'mean(d1_c${k1}$, 1, d1_c${k1}$%re > 0): uncorrect answer'& ) if (allocated(error)) return #:for rank in range(2, NRANK+1) #:for dim in range(1, rank+1) call check(error& , sum(abs(mean(d${rank}$_c${k1}$, ${dim}$, d${rank}$_c${k1}$%re > 0) -& sum(d${rank}$_c${k1}$, ${dim}$, d${rank}$_c${k1}$%re > 0)/real(count(d${rank}$_c${k1}$%re > 0, ${dim}$), ${k1}$))) < ${k1}$tol& , 'mean(d${rank}$_c${k1}$, ${dim}$, d${rank}$_c${k1}$%re > 0): uncorrect answer'& ) if (allocated(error)) return #:endfor #:endfor end subroutine #:endfor end module test_stats_mean program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_stats_mean, only : collect_stats_mean implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("stats_mean", collect_stats_mean) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/stats/CMakeLists.txt0000664000175000017500000000130515135654166023042 0ustar alastairalastair#### Pre-process: .fpp -> .f90 via Fypp # Create a list of the files to be preprocessed set(fppFiles test_mean.fypp test_mean_f03.fypp test_median.fypp test_distribution_uniform.fypp test_distribution_normal.fypp test_distribution_exponential.fypp ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) ADDTEST(corr) ADDTEST(cov) ADDTEST(mean) ADDTEST(median) ADDTEST(moment) ADDTEST(rawmoment) ADDTEST(var) ADDTEST(varn) ADDTEST(random) ADDTEST(distribution_uniform) ADDTEST(distribution_normal) ADDTEST(distribution_exponential) if(DEFINED CMAKE_MAXIMUM_RANK) if(${CMAKE_MAXIMUM_RANK} GREATER 7) ADDTEST(mean_f03) endif() elseif(f03rank) ADDTEST(mean_f03) endif() fortran-lang-stdlib-0ede301/test/stats/test_corr.f900000664000175000017500000003740415135654166022637 0ustar alastairalastairprogram test_corr use stdlib_error, only: check use stdlib_kinds, only: sp, dp, int32, int64 use stdlib_stats, only: corr use,intrinsic :: ieee_arithmetic, only : ieee_is_nan implicit none real(sp), parameter :: sptol = 1000 * epsilon(1._sp) real(dp), parameter :: dptol = 1000 * epsilon(1._dp) real(dp) :: d1(5) = [1.0_dp, 2.0_dp, 3.0_dp, 4.0_dp, 5.0_dp] real(dp) :: d(4, 3) = reshape([1._dp, 3._dp, 5._dp, 22._dp,& 3._dp, 4._dp, 6._dp, 20._dp,& 15._dp, 14._dp, 13._dp, 12._dp], [4, 3]) complex(dp) :: cd1(5) = [ cmplx(0.57706_dp, 0.00000_dp, kind = dp),& cmplx(0.00000_dp, 1.44065_dp, kind = dp),& cmplx(1.26401_dp, 0.00000_dp, kind = dp),& cmplx(0.00000_dp, 0.88833_dp, kind = dp),& cmplx(1.14352_dp, 0.00000_dp, kind = dp)] complex(dp) :: ds(2,3) = reshape([ cmplx(1._dp, 0._dp, kind = dp),& cmplx(0._dp, 2._dp, kind = dp),& cmplx(3._dp, 0._dp, kind = dp),& cmplx(0._dp, 4._dp, kind = dp),& cmplx(5._dp, 0._dp, kind = dp),& cmplx(0._dp, 6._dp, kind = dp)], [2, 3]) call test_sp(real(d1, sp), real(d, sp)) call test_dp(d1,d) call test_int32(int(d1, int32) ,int(d, int32)) call test_int64(int(d1, int64) ,int(d, int64)) call test_csp(cmplx(cd1, kind = sp), cmplx(ds, kind = sp)) call test_cdp(cd1, ds) contains subroutine test_sp(x, x2) real(sp), intent(in) :: x(:) real(sp), intent(in) :: x2(:, :) call check( abs(corr(x, 1) - 1._sp) < sptol& , 'sp check 1') call check( ieee_is_nan(corr(x, 1, .false.))& , 'sp check 2') call check( ieee_is_nan(corr(x, 1, x == 1.)), 'sp check 3') call check( abs(corr(x, 1, x < 5) - 1._sp) < sptol, 'sp check 4') call check( ieee_is_nan(corr(x, 1, x < -999)), 'sp check 5') call check( any(ieee_is_nan(corr(x2, 1, mask = .false.)))& , 'sp check 6') call check( any(ieee_is_nan(corr(x2, 2, mask = .false.)))& , 'sp check 7') call check( all( abs( corr(x2, 1) - reshape([& 1._sp, 0.9994439103600_sp, -0.870544389237152_sp, 0.99944391036_sp,& 1._sp, -0.86261576629742_sp, -0.87054438923715_sp, -0.862615766297428_sp,& 1._sp ]& ,[ size(x2, 2), size(x2, 2)])& ) < sptol)& , 'sp check 8') call check( all( abs( corr(x2, 2) - reshape([& 1._sp, 0.998742137866914_sp, 0.999846989517886_sp, -0.998337488459582_sp,& 0.998742137866914_sp, 1._sp, 0.999466429486246_sp, -0.99419162560192020_sp,& 0.999846989517886_sp, 0.999466429486246_sp, 1._sp, -0.99717646495273815_sp,& -0.998337488459582_sp, -0.994191625601920_sp, -0.997176464952738_sp, 1._sp]& ,[ size(x2, 1), size(x2, 1)])& ) < sptol)& , 'sp check 9') call check( any(ieee_is_nan(corr(x2, 1, mask = x2 < 10)))& , 'sp check 10') call check( all( abs( corr(x2, 1, mask = x2 < 22) - reshape([& 1._sp, 0.981980506061965_sp, -1._sp& ,0.981980506061965_sp, 1._sp, -0.862615766297428_sp& ,-1._sp, -0.862615766297428_sp, 1._sp]& ,[ size(x2, 2), size(x2, 2)])& ) < sptol)& , 'sp check 11') call check( all( abs( corr(x2, 2, mask = x2 < 22) - reshape([& 1._sp, 0.998742137866914_sp, 0.999846989517886_sp, -1._sp& ,0.998742137866914_sp, 1._sp, 0.999466429486246_sp, -1._sp& ,0.999846989517886_sp, 0.999466429486246_sp, 1._sp, -1._sp& ,-1._sp, -1._sp, -1._sp, 1._sp]& ,[ size(x2, 1), size(x2, 1)])& ) < sptol)& , 'sp check 12') call check( all(abs(corr(x2, 1, mask = x2 < 1000) - corr(x2, 1))& < sptol)& , 'sp check 13') call check( all(abs(corr(x2, 2, mask = x2 < 1000) - corr(x2, 2))& < sptol)& , 'sp check 14') end subroutine test_sp subroutine test_dp(x, x2) real(dp), intent(in) :: x(:) real(dp), intent(in) :: x2(:, :) call check( abs(corr(x, 1) - 1._dp) < dptol& , 'dp check 1') call check( ieee_is_nan(corr(x, 1, .false.))& , 'dp check 2') call check( ieee_is_nan(corr(x, 1, x == 1.)), 'dp check 3') call check( abs(corr(x, 1, x < 5) - 1._dp) < dptol, 'dp check 4') call check( ieee_is_nan(corr(x, 1, x < -999)), 'dp check 5') call check( any(ieee_is_nan(corr(x2, 1, mask = .false.)))& , 'dp check 6') call check( any(ieee_is_nan(corr(x2, 2, mask = .false.)))& , 'dp check 7') call check( all( abs( corr(x2, 1) - reshape([& 1._dp, 0.9994439103600_dp, -0.870544389237152_dp, 0.99944391036_dp,& 1._dp, -0.86261576629742_dp, -0.87054438923715_dp, -0.862615766297428_dp,& 1._dp ]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'dp check 8') call check( all( abs( corr(x2, 2) - reshape([& 1._dp, 0.998742137866914_dp, 0.999846989517886_dp, -0.998337488459582_dp,& 0.998742137866914_dp, 1._dp, 0.999466429486246_dp, -0.99419162560192020_dp,& 0.999846989517886_dp, 0.999466429486246_dp, 1._dp, -0.99717646495273815_dp,& -0.998337488459582_dp, -0.994191625601920_dp, -0.997176464952738_dp, 1._dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'dp check 9') call check( any(ieee_is_nan(corr(x2, 1, mask = x2 < 10)))& , 'dp check 10') call check( all( abs( corr(x2, 1, mask = x2 < 22) - reshape([& 1._dp, 0.981980506061965_dp, -1._dp& ,0.981980506061965_dp, 1._dp, -0.862615766297428_dp& ,-1._dp, -0.862615766297428_dp, 1._dp]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'dp check 11') call check( all( abs( corr(x2, 2, mask = x2 < 22) - reshape([& 1._dp, 0.998742137866914_dp, 0.999846989517886_dp, -1._dp& ,0.998742137866914_dp, 1._dp, 0.999466429486246_dp, -1._dp& ,0.999846989517886_dp, 0.999466429486246_dp, 1._dp, -1._dp& ,-1._dp, -1._dp, -1._dp, 1._dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'dp check 12') call check( all(abs(corr(x2, 1, mask = x2 < 1000) - corr(x2, 1))& < dptol)& , 'dp check 13') call check( all(abs(corr(x2, 2, mask = x2 < 1000) - corr(x2, 2))& < dptol)& , 'dp check 14') end subroutine test_dp subroutine test_int32(x, x2) integer(int32), intent(in) :: x(:) integer(int32), intent(in) :: x2(:, :) call check( abs(corr(x, 1) - 1._dp) < dptol& , 'int32 check 1') call check( ieee_is_nan(corr(x, 1, .false.))& , 'int32 check 2') call check( ieee_is_nan(corr(x, 1, x == 1.)), 'int32 check 3') call check( abs(corr(x, 1, x < 5) - 1._dp) < dptol, 'int32 check 4') call check( ieee_is_nan(corr(x, 1, x < -999)), 'int32 check 5') call check( any(ieee_is_nan(corr(x2, 1, mask = .false.)))& , 'int32 check 6') call check( any(ieee_is_nan(corr(x2, 2, mask = .false.)))& , 'int32 check 7') call check( all( abs( corr(x2, 1) - reshape([& 1._dp, 0.9994439103600_dp, -0.870544389237152_dp, 0.99944391036_dp,& 1._dp, -0.86261576629742_dp, -0.87054438923715_dp, -0.862615766297428_dp,& 1._dp ]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int32 check 8') call check( all( abs( corr(x2, 2) - reshape([& 1._dp, 0.998742137866914_dp, 0.999846989517886_dp, -0.998337488459582_dp,& 0.998742137866914_dp, 1._dp, 0.999466429486246_dp, -0.99419162560192020_dp,& 0.999846989517886_dp, 0.999466429486246_dp, 1._dp, -0.99717646495273815_dp,& -0.998337488459582_dp, -0.994191625601920_dp, -0.997176464952738_dp, 1._dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int32 check 9') call check( any(ieee_is_nan(corr(x2, 1, mask = x2 < 10)))& , 'int32 check 10') call check( all( abs( corr(x2, 1, mask = x2 < 22) - reshape([& 1._dp, 0.981980506061965_dp, -1._dp& ,0.981980506061965_dp, 1._dp, -0.862615766297428_dp& ,-1._dp, -0.862615766297428_dp, 1._dp]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int32 check 11') call check( all( abs( corr(x2, 2, mask = x2 < 22) - reshape([& 1._dp, 0.998742137866914_dp, 0.999846989517886_dp, -1._dp& ,0.998742137866914_dp, 1._dp, 0.999466429486246_dp, -1._dp& ,0.999846989517886_dp, 0.999466429486246_dp, 1._dp, -1._dp& ,-1._dp, -1._dp, -1._dp, 1._dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int32 check 12') call check( all(abs(corr(x2, 1, mask = x2 < 1000) - corr(x2, 1))& < dptol)& , 'int32 check 13') call check( all(abs(corr(x2, 2, mask = x2 < 1000) - corr(x2, 2))& < dptol)& , 'int32 check 14') end subroutine test_int32 subroutine test_int64(x, x2) integer(int64), intent(in) :: x(:) integer(int64), intent(in) :: x2(:, :) call check( abs(corr(x, 1) - 1._dp) < dptol& , 'int64 check 1') call check( ieee_is_nan(corr(x, 1, .false.))& , 'int64 check 2') call check( ieee_is_nan(corr(x, 1, x == 1)), 'int64 check 3') call check( abs(corr(x, 1, x < 5) - 1._dp) < dptol, 'int64 check 4') call check( ieee_is_nan(corr(x, 1, x < -999)), 'int64 check 5') call check( any(ieee_is_nan(corr(x2, 1, mask = .false.)))& , 'int64 check 6') call check( any(ieee_is_nan(corr(x2, 2, mask = .false.)))& , 'int64 check 7') call check( all( abs( corr(x2, 1) - reshape([& 1._dp, 0.9994439103600_dp, -0.870544389237152_dp, 0.99944391036_dp,& 1._dp, -0.86261576629742_dp, -0.87054438923715_dp, -0.862615766297428_dp,& 1._dp ]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int64 check 8') call check( all( abs( corr(x2, 2) - reshape([& 1._dp, 0.998742137866914_dp, 0.999846989517886_dp, -0.998337488459582_dp,& 0.998742137866914_dp, 1._dp, 0.999466429486246_dp, -0.99419162560192020_dp,& 0.999846989517886_dp, 0.999466429486246_dp, 1._dp, -0.99717646495273815_dp,& -0.998337488459582_dp, -0.994191625601920_dp, -0.997176464952738_dp, 1._dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int64 check 9') call check( any(ieee_is_nan(corr(x2, 1, mask = x2 < 10)))& , 'int64 check 10') call check( all( abs( corr(x2, 1, mask = x2 < 22) - reshape([& 1._dp, 0.981980506061965_dp, -1._dp& ,0.981980506061965_dp, 1._dp, -0.862615766297428_dp& ,-1._dp, -0.862615766297428_dp, 1._dp]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'int64 check 11') call check( all( abs( corr(x2, 2, mask = x2 < 22) - reshape([& 1._dp, 0.998742137866914_dp, 0.999846989517886_dp, -1._dp& ,0.998742137866914_dp, 1._dp, 0.999466429486246_dp, -1._dp& ,0.999846989517886_dp, 0.999466429486246_dp, 1._dp, -1._dp& ,-1._dp, -1._dp, -1._dp, 1._dp]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'int64 check 12') call check( all(abs(corr(x2, 1, mask = x2 < 1000) - corr(x2, 1))& < dptol)& , 'int64 check 13') call check( all(abs(corr(x2, 2, mask = x2 < 1000) - corr(x2, 2))& < dptol)& , 'int64 check 14') end subroutine test_int64 subroutine test_csp(x, x2) complex(sp), intent(in) :: x(:) complex(sp), intent(in) :: x2(:, :) call check( abs(corr(x, dim=1) - 1._sp) < sptol& , 'csp check 1') call check( abs(corr(x, 1, aimag(x) == 0) - 1._sp ) < sptol& , 'csp check 2') call check( ieee_is_nan(corr(x, 1, aimag(x) == -99 )) & , 'csp check 3') call check( ieee_is_nan(real(corr(x, 1, .false.)))& , 'csp check 4') call check( all( abs( corr(x2, 1) - reshape([& (1._sp,0._sp), (0.983869910099907_sp,-0.178885438199983_sp),& (0.973417168333576_sp,-0.229039333725547_sp),& (0.983869910099907_sp,0.178885438199983_sp), (1._sp,0._sp),& (0.998687663476588_sp,-0.051214751973158_sp),& (0.973417168333575_sp,0.229039333725547_sp),& (0.998687663476588_sp,0.0512147519731583_sp), (1._sp,0._sp) ]& ,[ size(x2, 2), size(x2, 2)])& ) < sptol)& , 'csp check 6') call check( all( abs( corr(x2, 2) - reshape([& (1._sp,0._sp), (0._sp,1._sp),& (0._sp,-1._sp), (1._sp,0._sp)]& ,[ size(x2, 1), size(x2, 1)])& ) < sptol)& , 'csp check 7') call check( all( abs( corr(x2, 2, mask = aimag(x2) < 6) - reshape([& (1._sp,0._sp), (0._sp,1._sp)& ,(0._sp,-1._sp), (1._sp,0._sp)]& ,[ size(x2, 1), size(x2, 1)])& ) < sptol)& , 'csp check 8') call check( all(abs(corr(x2, 1, mask = aimag(x2) < 1000) - corr(x2, 1))& < sptol)& , 'csp check 9') call check( all(abs(corr(x2, 2, mask = aimag(x2) < 1000) - corr(x2, 2))& < sptol)& , 'csp check 10') end subroutine test_csp subroutine test_cdp(x, x2) complex(dp), intent(in) :: x(:) complex(dp), intent(in) :: x2(:, :) call check( abs(corr(x, dim=1) - 1._dp) < dptol& , 'cdp check 1') call check( abs(corr(x, 1, aimag(x) == 0) - 1._dp ) < dptol& , 'cdp check 2') call check( ieee_is_nan(corr(x, 1, aimag(x) == -99 )) & , 'cdp check 3') call check( ieee_is_nan(real(corr(x, 1, .false.)))& , 'cdp check 4') call check( all( abs( corr(x2, 1) - reshape([& (1._dp,0._dp), (0.983869910099907_dp,-0.178885438199983_dp),& (0.973417168333576_dp,-0.229039333725547_dp),& (0.983869910099907_dp,0.178885438199983_dp), (1._dp,0._dp),& (0.998687663476588_dp,-0.051214751973158_dp),& (0.973417168333575_dp,0.229039333725547_dp),& (0.998687663476588_dp,0.0512147519731583_dp), (1._dp,0._dp) ]& ,[ size(x2, 2), size(x2, 2)])& ) < dptol)& , 'cdp check 6') call check( all( abs( corr(x2, 2) - reshape([& (1._dp,0._dp), (0._dp,1._dp),& (0._dp,-1._dp), (1._dp,0._dp)]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'cdp check 7') call check( all( abs( corr(x2, 2, mask = aimag(x2) < 6) - reshape([& (1._dp,0._dp), (0._dp,1._dp)& ,(0._dp,-1._dp), (1._dp,0._dp)]& ,[ size(x2, 1), size(x2, 1)])& ) < dptol)& , 'cdp check 8') call check( all(abs(corr(x2, 1, mask = aimag(x2) < 1000) - corr(x2, 1))& < sptol)& , 'csp check 9') call check( all(abs(corr(x2, 2, mask = aimag(x2) < 1000) - corr(x2, 2))& < sptol)& , 'csp check 10') end subroutine test_cdp end program test_corr fortran-lang-stdlib-0ede301/test/stats/test_distribution_exponential.fypp0000664000175000017500000003604715135654166027401 0ustar alastairalastair #:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES program test_distribution_expon use stdlib_kinds, only : sp, dp, xdp, qp use stdlib_error, only : check use stdlib_random, only : random_seed use stdlib_stats_distribution_exponential, only : expon_rvs => rvs_exp, & expon_pdf => pdf_exp, expon_cdf => cdf_exp implicit none #:for k1, t1 in REAL_KINDS_TYPES ${t1}$, parameter :: ${k1}$tol = 1000 * epsilon(1.0_${k1}$) #:endfor logical :: warn = .true. integer :: put, get put = 12345678 call random_seed(put, get) call test_exponential_random_generator #:for k1, t1 in RC_KINDS_TYPES call test_expon_rvs_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES call test_expon_pdf_${t1[0]}$${k1}$ #:endfor call test_expon_pdf_rsp #:for k1, t1 in RC_KINDS_TYPES call test_expon_cdf_${t1[0]}$${k1}$ #:endfor contains subroutine test_exponential_random_generator integer, parameter :: num = 10000000, array_size = 1000 integer :: i, j, freq(0:array_size) real(dp) :: chisq, expct print *, "" print *, "Test exponential random generator with chi-squared" ! using interface for lambda freq = 0 do i = 1, num j = 1000 * (1 - exp(- expon_rvs(1.0))) freq(j) = freq(j) + 1 end do chisq = 0.0_dp expct = num / array_size do i = 0, array_size - 1 chisq = chisq + (freq(i) - expct) ** 2 / expct end do write(*,*) "The critical values for chi-squared with 1000 d. of f. is" & //" 1143.92" write(*,*) "Chi-squared for exponential random generator is : ", chisq call check((chisq < 1143.9), & msg="exponential randomness failed chi-squared test", warn=warn) ! using interface for loc and scale freq = 0 do i = 1, num j = 1000 * (1 - exp(- expon_rvs(0.0, 1.0))) freq(j) = freq(j) + 1 end do chisq = 0.0_dp expct = num / array_size do i = 0, array_size - 1 chisq = chisq + (freq(i) - expct) ** 2 / expct end do write(*,*) "The critical values for chi-squared with 1000 d. of f. is" & //" 1143.92" write(*,*) "Chi-squared for exponential random generator is : ", chisq call check((chisq < 1143.9), & msg="exponential randomness failed chi-squared test", warn=warn) end subroutine test_exponential_random_generator #:for k1, t1 in RC_KINDS_TYPES subroutine test_expon_rvs_${t1[0]}$${k1}$ ${t1}$ :: res(10), lambda, loc, scale integer, parameter :: k = 5 integer :: i integer :: seed, get #:if t1[0] == "r" #! for real type ${t1}$, parameter :: ans(10) = & [0.609680481289574416337018192280083895_${k1}$, & 0.137541023585612635452927558314210417_${k1}$, & 0.134921508232253721063879462841820585_${k1}$, & 1.33766060689229752493171569464417802_${k1}$, & 0.111148487576340881943792737729381770_${k1}$, & 0.533951653963536868966836361020492979_${k1}$, & 1.96897428558727671799033487332053483_${k1}$, & 0.371111977992924465160247867364281152_${k1}$, & 0.811918715695663687862785688290993341_${k1}$, & 0.404637854946697868759504975362991277_${k1}$] #:else #! for complex type ${t1}$, parameter :: ans(10) = & [(1.30645817419194517786503898345732266_${k1}$, & 0.158701181060322271676454874977935106_${k1}$), & (0.289117517640543687994027420375329869_${k1}$, & 1.54345454641418945184428733997405138_${k1}$), & (0.238175330520730461308127295134389521_${k1}$, & 0.616098062265619464192503493485184250_${k1}$), & (4.21923061197273582426500329997257485_${k1}$, & 0.428206128453374382877209077728016710_${k1}$), & (1.73982581934785075970596933205212874_${k1}$, & 0.466889832630805233184044202341912994_${k1}$), & (2.22649889847873832288931745486999202_${k1}$, & 0.879109337848515628785697537331053851_${k1}$), & (8.76802198822945553859296653951917464_${k1}$, & 0.200128045239398311139211728004738688_${k1}$), & (0.694821947760945587572020290930855262_${k1}$, & 0.101964167346166995492113143812345625_${k1}$), & (0.141476585024528208770330398432893829_${k1}$, & 3.989655879458742013468417133900891716E-0002_${k1}$), & (2.10676792861163792685325850990401309_${k1}$, & 0.249356813451327473065187125310051027_${k1}$)] #:endif print *, "Test exponential_distribution_rvs_${t1[0]}$${k1}$" seed = 593742186 ! set args #:if t1[0] == "r" #! for real type lambda = 1.5_${k1}$ loc = 0._${k1}$ scale = 1.0_${k1}$/lambda #:else #! for complex type lambda = (0.7_${k1}$, 1.3_${k1}$) loc = (0._${k1}$, 0._${k1}$) scale = cmplx(1.0_${k1}$/lambda%re, 1.0_${k1}$/lambda%im, kind=${k1}$) #:endif ! tests using interface for lambda call random_seed(seed, get) do i = 1, k res(i) = expon_rvs(lambda) ! 1 dummy end do res(6:10) = expon_rvs(lambda, k) ! 2 dummies call check(all(abs(res - ans) < ${k1}$tol), & msg="exponential_distribution_rvs_${t1[0]}$${k1}$ failed", warn=warn) ! tests using interface for loc and scale call random_seed(seed, get) do i = 1, k res(i) = expon_rvs(loc, scale) end do res(6:10) = expon_rvs(loc, scale, k) call check(all(abs(res - ans) < ${k1}$tol), & msg="exponential_distribution_rvs_${t1[0]}$${k1}$ failed", warn=warn) end subroutine test_expon_rvs_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES subroutine test_expon_pdf_${t1[0]}$${k1}$ ${t1}$ :: x1, x2(3,4), lambda, loc, scale integer :: seed, get real(${k1}$) :: res(3,5) #:if t1[0] == "r" #! for real type real(${k1}$), parameter :: ans(15) = & [0.362692289054629718342313806171796533_${k1}$, & 0.362692289054629718342313806171796533_${k1}$, & 0.362692289054629718342313806171796533_${k1}$, & 1.44877092399186122284289290051705535_${k1}$, & 1.08871761038277651996081144393335589_${k1}$, & 0.203258408490339213767867275283195750_${k1}$, & 0.730004225568590859263284124264208147_${k1}$, & 0.237394827760488451509080387833146683_${k1}$, & 0.301732182586179598102005265289645959_${k1}$, & 1.35079274124711914255014934401469271_${k1}$, & 0.416578245043239337295928202660090263_${k1}$, & 1.44039177901335374382803898226703593_${k1}$, & 0.196044829271295768265275728683411055_${k1}$, & 0.271373826917613661285112379170965958_${k1}$, & 1.00108987409617105109732206933052664_${k1}$] #:else #! for complex type real(${k1}$), parameter :: ans(15) = & [0.112097715784191810518066563334849515_${k1}$, & 0.112097715784191810518066563334849515_${k1}$, & 0.112097715784191810518066563334849515_${k1}$, & 4.72087485401191174735651518020251204E-0002_${k1}$, & 3.69705018439006691768174449531170720E-0002_${k1}$, & 8.69498969681198520061798177185735738E-0002_${k1}$, & 0.128007654288233028296342302153338001_${k1}$, & 1.13496395875758374774198906169957218E-0002_${k1}$, & 0.294260498264128747413785056084385424_${k1}$, & 4.66169813179250908948018478030960097E-0002_${k1}$, & 2.84438693906889813143446828488861951E-0002_${k1}$, & 0.161859307815385236742977105439660254_${k1}$, & 4.22904796362406579112752522035325397E-0002_${k1}$, & 0.176117981883470250164040199296778089_${k1}$, & 0.107352342201327219885025541854724060_${k1}$] #:endif print *, "Test exponential_distribution_pdf_${t1[0]}$${k1}$" seed = 123987654 ! set args #:if t1[0] == "r" #! for real type lambda = 1.5_${k1}$ loc = 0._${k1}$ scale = 1.0_${k1}$/lambda #:else #! for complex type lambda = (0.3_${k1}$, 1.6_${k1}$) loc = (0._${k1}$, 0._${k1}$) scale = cmplx(1.0_${k1}$/lambda%re, 1.0_${k1}$/lambda%im, kind=${k1}$) #:endif ! tests using interface for lambda call random_seed(seed, get) x1 = expon_rvs(lambda) x2 = reshape(expon_rvs(lambda, 12), [3,4]) res(:,1) = expon_pdf(x1, lambda) res(:, 2:5) = expon_pdf(x2, lambda) call check(all(abs(res - reshape(ans, [3,5])) < ${k1}$tol), & msg="exponential_distribution_pdf_${t1[0]}$${k1}$ failed", warn=warn) ! tests using interface for loc and scale call random_seed(seed, get) x1 = expon_rvs(loc, scale) x2 = reshape(expon_rvs(loc, scale, 12), [3,4]) res(:,1) = expon_pdf(x1, loc, scale) res(:, 2:5) = expon_pdf(x2, loc, scale) call check(all(abs(res - reshape(ans, [3,5])) < ${k1}$tol), & msg="exponential_distribution_pdf_${t1[0]}$${k1}$ failed", warn=warn) end subroutine test_expon_pdf_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES subroutine test_expon_cdf_${t1[0]}$${k1}$ ${t1}$ :: x1, x2(3,4), lambda, loc, scale integer :: seed, get real(${k1}$) :: res(3,5) #:if t1[0] == "r" #! for real type real(${k1}$), parameter :: ans(15) = & [0.109257742653704886153815776449785051_${k1}$, & 0.109257742653704886153815776449785051_${k1}$, & 0.109257742653704886153815776449785051_${k1}$, & 0.717506371795765265795319089684216215_${k1}$, & 6.82471795435370961628021592837348251E-0002_${k1}$, & 0.158022297254037860379992220663140220_${k1}$, & 0.914579543576380160727189390750289231_${k1}$, & 0.735445094339121647068624074363021598_${k1}$, & 8.69845458684957375690771394578441361E-0002_${k1}$, & 0.491195342629961409581199224477971938_${k1}$, & 0.574283568793105916250099261345264380_${k1}$, & 0.312823040527767907760475800138803955_${k1}$, & 0.640029783598040153827956625977856239_${k1}$, & 2.16202116731629451897815202649346917E-0002_${k1}$, & 7.74788145547936974757767867581111655E-0002_${k1}$] #:else real(${k1}$), parameter :: ans(15) = & [7.83931265220552191922145459533155073E-0002_${k1}$, & 7.83931265220552191922145459533155073E-0002_${k1}$, & 7.83931265220552191922145459533155073E-0002_${k1}$, & 1.07845760925785109085652212151328215E-0002_${k1}$, & 0.672623038706161724678635394849362256_${k1}$, & 4.27264038113873579678831482902258168E-0002_${k1}$, & 0.179649132114996961326498233168917293_${k1}$, & 1.38375793985183014482681114776428612E-0002_${k1}$, & 3.49246365297941076158369468479748612E-0002_${k1}$, & 0.116869945417176368845403154176734792_${k1}$, & 0.468462732010133566674397830557697485_${k1}$, & 0.413506985517976634907329948218002431_${k1}$, & 0.665679674838121942273909342901808398_${k1}$, & 0.223748595107983772617787558595393205_${k1}$, & 0.337722969540396286456937689606849800_${k1}$] #:endif print *, "Test exponential_distribution_cdf_${t1[0]}$${k1}$" seed = 621957438 ! set args #:if t1[0] == "r" #! for real type lambda = 2.0_${k1}$ loc = 0._${k1}$ scale = 1.0_${k1}$/lambda #:else lambda = (1.3_${k1}$, 2.1_${k1}$) loc = (0._${k1}$, 0._${k1}$) scale = cmplx(1.0_${k1}$/lambda%re, 1.0_${k1}$/lambda%im, kind=${k1}$) #:endif ! tests using interface for lambda call random_seed(seed, get) x1 = expon_rvs(lambda) x2 = reshape(expon_rvs(lambda, 12), [3,4]) res(:,1) = expon_cdf(x1, lambda) res(:, 2:5) = expon_cdf(x2, lambda) call check(all(abs(res - reshape(ans,[3,5])) < ${k1}$tol), & msg="exponential_distribution_cdf_${t1[0]}$${k1}$ failed", warn=warn) ! tests using interface for loc and scale call random_seed(seed, get) x1 = expon_rvs(loc, scale) x2 = reshape(expon_rvs(loc, scale, 12), [3,4]) res(:,1) = expon_cdf(x1, loc, scale) res(:, 2:5) = expon_cdf(x2, loc, scale) call check(all(abs(res - reshape(ans,[3,5])) < ${k1}$tol), & msg="exponential_distribution_cdf_${t1[0]}$${k1}$ failed", warn=warn) end subroutine test_expon_cdf_${t1[0]}$${k1}$ #:endfor end program test_distribution_expon fortran-lang-stdlib-0ede301/test/stats/test_var.f900000664000175000017500000007462615135654166022471 0ustar alastairalastairmodule test_var use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_kinds, only: sp, dp, int32, int64 use stdlib_stats, only: var use,intrinsic :: ieee_arithmetic, only : ieee_is_nan implicit none real(sp), parameter :: sptol = 1000 * epsilon(1._sp) real(dp), parameter :: dptol = 1000 * epsilon(1._dp) integer(int32), parameter :: i321(5) = [1, 2, 3, 4, 5] integer(int64), parameter :: i641(5) = [1, 2, 3, 4, 5] real(sp), parameter :: s1(5) = [1.0_sp, 2.0_sp, 3.0_sp, 4.0_sp, 5.0_sp] real(dp), parameter :: d1(5) = [1.0_dp, 2.0_dp, 3.0_dp, 4.0_dp, 5.0_dp] real(dp), parameter :: d(4, 3) = reshape([1._dp, 3._dp, 5._dp, 7._dp,& 2._dp, 4._dp, 6._dp, 8._dp,& 9._dp, 10._dp, 11._dp, 12._dp], [4, 3]) real(dp), parameter :: d3(4, 3, 3) = reshape([d, d*2, d*4], shape(d3)) real(sp), parameter :: s(4, 3) = d real(sp), parameter :: s3(4, 3, 3) = reshape([s, s*2, s*4], shape(s3)) integer(int32), parameter :: i32(4, 3) = d integer(int32), parameter :: i323(4, 3, 3) = d3 integer(int64), parameter :: i64(4, 3) = d integer(int64), parameter :: i643(4, 3, 3) = d3 complex(sp), parameter :: cs1(5) = [ cmplx(0.57706_sp, 0.00000_sp, sp),& cmplx(0.00000_sp, 1.44065_sp, sp),& cmplx(1.26401_sp, 0.00000_sp, sp),& cmplx(0.00000_sp, 0.88833_sp, sp),& cmplx(1.14352_sp, 0.00000_sp, sp)] complex(dp), parameter :: cd1(5) = [ cmplx(0.57706_dp, 0.00000_dp,kind=dp),& cmplx(0.00000_dp, 1.44065_dp,kind=dp),& cmplx(1.26401_dp, 0.00000_dp,kind=dp),& cmplx(0.00000_dp, 0.88833_dp,kind=dp),& cmplx(1.14352_dp, 0.00000_dp,kind=dp)] complex(sp), parameter :: cs(5,3) = reshape([cs1, cs1*3.0_sp, cs1*1.5_sp], shape(cs)) complex(dp), parameter :: cd(5,3) = reshape([cd1, cd1*3.0_dp, cd1*1.5_dp], shape(cd)) contains !> Collect all exported unit tests subroutine collect_var(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("sp_1dim", test_sp_1dim), & new_unittest("sp_1dim_mask", test_sp_1dim_mask), & new_unittest("sp_2dim", test_sp_2dim), & new_unittest("sp_2dim_mask", test_sp_2dim_mask), & new_unittest("sp_2dim_mask_array", test_sp_2dim_mask_array), & new_unittest("sp_3dim", test_sp_3dim), & new_unittest("sp_3dim_mask", test_sp_3dim_mask), & new_unittest("sp_3dim_mask_array", test_sp_3dim_mask_array), & new_unittest("dp_1dim", test_dp_1dim), & new_unittest("dp_1dim_mask", test_dp_1dim_mask), & new_unittest("dp_1dim_mask_array", test_dp_1dim_mask_array), & new_unittest("dp_2dim", test_dp_2dim), & new_unittest("dp_2dim_mask", test_dp_2dim_mask), & new_unittest("dp_2dim_mask_array", test_dp_2dim_mask_array), & new_unittest("dp_3dim", test_dp_3dim), & new_unittest("dp_3dim_mask", test_dp_3dim_mask), & new_unittest("dp_3dim_mask_array", test_dp_3dim_mask_array), & new_unittest("int32_1dim", test_int32_1dim), & new_unittest("int32_1dim_mask", test_int32_1dim_mask), & new_unittest("int32_1dim_mask_array", test_int32_1dim_mask_array), & new_unittest("int32_2dim", test_int32_2dim), & new_unittest("int32_2dim_mask", test_int32_2dim_mask), & new_unittest("int32_2dim_mask_array", test_int32_2dim_mask_array), & new_unittest("int32_3dim", test_int32_3dim), & new_unittest("int32_3dim_mask", test_int32_3dim_mask), & new_unittest("int32_3dim_mask_array", test_int32_3dim_mask_array), & new_unittest("int64_1dim", test_int64_1dim), & new_unittest("int64_1dim_mask", test_int64_1dim_mask), & new_unittest("int641_1dim_mask_array", test_int641_1dim_mask_array), & new_unittest("int64_2dim", test_int64_2dim), & new_unittest("int64_2dim_mask", test_int64_2dim_mask), & new_unittest("int64_2dim_mask_array", test_int64_2dim_mask_array), & new_unittest("int64_3dim", test_int64_3dim), & new_unittest("int64_3dim_mask", test_int64_3dim_mask), & new_unittest("int64_3dim_mask_array", test_int64_3dim_mask_array), & new_unittest("csp_1dim", test_csp_1dim), & new_unittest("csp_1dim_mask", test_csp_1dim_mask), & new_unittest("csp_1dim_mask_array", test_csp_1dim_mask_array), & new_unittest("csp_2dim", test_csp_2dim), & new_unittest("csp_2dim_mask", test_csp_2dim_mask), & new_unittest("csp_2dim_mask_array", test_csp_2dim_mask_array), & new_unittest("cdp_1dim", test_cdp_1dim), & new_unittest("cdp_1dim_mask", test_cdp_1dim_mask), & new_unittest("cdp_1dim_mask_array", test_cdp_1dim_mask_array), & new_unittest("cdp_2dim", test_cdp_2dim), & new_unittest("cdp_2dim_mask", test_cdp_2dim_mask), & new_unittest("cdp_2dim_mask_array", test_cdp_2dim_mask_array) & ] end subroutine collect_var subroutine test_sp_1dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s1) - 2.5) < sptol) call check(error, abs(var(s1, dim=1) - 2.5) < sptol) end subroutine test_sp_1dim subroutine test_sp_1dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(s1, .false.))) call check(error, ieee_is_nan(var(s1, 1, .false.))) end subroutine test_sp_1dim_mask subroutine test_sp_1dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s1, s1 < 5) - 5./3.) < sptol) call check(error, ieee_is_nan((var(s1, s1 < 0.)))) call check(error, ieee_is_nan((var(s1, s1 == 1.)))) call check(error, abs(var(s1, 1, s1 < 5) - 5./3.) < sptol) end subroutine test_sp_1dim_mask_array subroutine test_sp_2dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s) - 13) < sptol) call check(error, all( abs( var(s, 1) - [20. / 3., 20. / 3., 5. / 3.]) < sptol)) call check(error, all( abs( var(s, 2) - [19.0, 43. / 3., 31. / 3. , 7.0]) < sptol)) end subroutine test_sp_2dim subroutine test_sp_2dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(s, .false.))) call check(error, any(ieee_is_nan(var(s, 1, .false.)))) call check(error, any(ieee_is_nan(var(s, 2, .false.)))) end subroutine test_sp_2dim_mask subroutine test_sp_2dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s, s < 11) - 27.5 / 3.) < sptol) call check(error, all( abs( var(s, 1, s < 11) - [20. / 3., 20. / 3., 0.5]) < sptol)) call check(error, all( abs( var(s, 2, s < 11) - [19.0, 43. / 3., 0.5 , 0.5]) < sptol)) end subroutine test_sp_2dim_mask_array subroutine test_sp_3dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s3) - 153.4) < sptol) call check(error, all( abs( var(s3, 1) -& reshape([20. / 3., 20. / 3., 5. / 3.,& 4* 20. / 3., 4* 20. / 3., 4* 5. / 3.,& 16* 20. / 3., 16* 20. / 3., 16* 5. / 3.],& [size(s3,2), size(s3,3)]))& < sptol)) call check(error, all( abs( var(s3, 2) -& reshape([19.0, 43. / 3., 31. / 3. , 7.0,& 4* 19.0, 4* 43. / 3., 4* 31. / 3. , 4* 7.0,& 16* 19.0, 16* 43. / 3., 16* 31. / 3. , 16* 7.0],& [size(s3,1), size(s3,3)] ))& < sptol)) call check(error, all(abs( var(s3, 3) -& reshape([ 7./3., 21., 175./3.,& 343./3., 28./3., 112./3.,& 84., 448./3., 189.,& 700./3., 847./3., 336.], [size(s3,1), size(s3,2)] ))& < sptol)) end subroutine test_sp_3dim subroutine test_sp_3dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(s3, .false.))) call check(error, any(ieee_is_nan(var(s3, 1, .false.)))) call check(error, any(ieee_is_nan(var(s3, 2, .false.)))) call check(error, any(ieee_is_nan(var(s3, 3, .false.)))) end subroutine test_sp_3dim_mask subroutine test_sp_3dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(s3, s3 < 11) - 8.2205877_sp) < sptol) call check(error, all( abs( var(s3, 1, s3 < 45) -& reshape([20./3., 20./3., 5./3., 80./3., 80./3., 20./3.,& 320./3., 320./3., 16.],& [size(s3, 2), size(s3, 3)])) < sptol )) call check(error, any( ieee_is_nan( var(s3, 2, s3 < 25)))) call check(error, all( abs( var(s3, 3, s3 < 25) -& reshape([ 7./3., 21., 175./3.,& 24.5, 28./3., 112./3.,& 84., 32., 40.5,& 50., 60.5, 72.], [size(s3,1), size(s3,2)] ))& < sptol )) end subroutine test_sp_3dim_mask_array subroutine test_dp_1dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d1) - 2.5) < dptol) call check(error, abs(var(d1, 1) - 2.5) < dptol) end subroutine test_dp_1dim subroutine test_dp_1dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(d1, .false.))) call check(error, ieee_is_nan(var(d1, 1, .false.))) end subroutine test_dp_1dim_mask subroutine test_dp_1dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d1, d1 < 5) - 5._dp/3._dp) < dptol) call check(error, ieee_is_nan((var(d1, d1 < 0.)))) call check(error, ieee_is_nan((var(d1, d1 == 1.)))) call check(error, abs(var(d1, 1, d1 < 5) - 5._dp/3._dp) < dptol) end subroutine test_dp_1dim_mask_array subroutine test_dp_2dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d) - 13) < dptol) call check(error, all( abs( var(d,1) -& [20._dp/3._dp, 20._dp/3._dp, 5._dp/3._dp]) < dptol)) call check(error, all( abs( var(d,2) -& [19.0_dp, 43._dp/3._dp, 31._dp/3._dp, 7.0_dp]) < dptol)) end subroutine test_dp_2dim subroutine test_dp_2dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(d, .false.))) call check(error, any(ieee_is_nan(var(d, 1, .false.)))) call check(error, any(ieee_is_nan(var(d, 2, .false.)))) end subroutine test_dp_2dim_mask subroutine test_dp_2dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d, d < 11) - 27.5_dp / 3._dp) < dptol) call check(error, all( abs( var(d, 1, d < 11) -& [20._dp / 3._dp, 20._dp / 3._dp, 0.5_dp]) < dptol)) call check(error, all( abs( var(d, 2, d < 11) -& [19.0_dp, 43._dp / 3._dp, 0.5_dp, 0.5_dp]) < dptol)) end subroutine test_dp_2dim_mask_array subroutine test_dp_3dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d3) - 153.4_dp) < dptol) call check(error, all( abs( var(d3, 1) -& reshape([20._dp / 3._dp, 20._dp / 3._dp, 5._dp / 3._dp,& 4* 20._dp / 3._dp, 4* 20._dp / 3._dp, 4* 5._dp / 3._dp,& 16* 20._dp / 3._dp, 16* 20._dp / 3._dp, 16* 5._dp / 3._dp],& [size(d3,2), size(d3,3)]))& < dptol)) call check(error, all( abs( var(d3, 2) -& reshape([19.0_dp, 43._dp / 3._dp, 31._dp / 3._dp , 7.0_dp,& 4* 19.0_dp, 4* 43._dp / 3._dp, 4* 31._dp / 3._dp , 4* 7.0_dp,& 16* 19.0_dp, 16* 43._dp / 3._dp, 16* 31._dp / 3._dp ,& 16* 7.0_dp],& [size(d3,1), size(d3,3)] ))& < dptol)) call check(error, all(abs( var(d3, 3) -& reshape([ 7._dp/3._dp, 21._dp, 175._dp/3._dp,& 343._dp/3._dp, 28._dp/3._dp, 112._dp/3._dp,& 84._dp, 448._dp/3._dp, 189._dp,& 700._dp/3._dp, 847._dp/3._dp, 336._dp],& [size(d3,1), size(d3,2)] ))& < dptol)) end subroutine test_dp_3dim subroutine test_dp_3dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(d3, .false.))) call check(error, any(ieee_is_nan(var(d3, 1, .false.)))) call check(error, any(ieee_is_nan(var(d3, 2, .false.)))) call check(error, any(ieee_is_nan(var(d3, 3, .false.)))) end subroutine test_dp_3dim_mask subroutine test_dp_3dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(d3, d3 < 25) - 46.041379310344823_dp) < dptol) call check(error, all( abs( var(d3, 1, d3 < 45) -& reshape([20._dp/3._dp, 20._dp/3._dp, 5._dp/3._dp,& 80._dp/3._dp, 80._dp/3._dp, 20._dp/3._dp,& 320._dp/3._dp, 320._dp/3._dp, 16._dp],& [size(d3, 2), size(d3, 3)]))& < dptol )) call check(error, any( ieee_is_nan( var(d3, 2, d3 < 25)))) call check(error, all( abs( var(d3, 3, d3 < 25) -& reshape([ 7._dp/3._dp, 21._dp, 175._dp/3._dp,& 24.5_dp, 28._dp/3._dp, 112._dp/3._dp,& 84._dp, 32._dp, 40.5_dp,& 50._dp, 60.5_dp, 72._dp],& [size(d3,1), size(d3,2)] ))& < dptol )) end subroutine test_dp_3dim_mask_array subroutine test_int32_1dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i321) - 2.5) < dptol) call check(error, abs(var(i321, 1) - 2.5) < dptol) end subroutine test_int32_1dim subroutine test_int32_1dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(i321, .false.))) call check(error, ieee_is_nan(var(i321, 1, .false.))) end subroutine test_int32_1dim_mask subroutine test_int32_1dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i321, i321 < 5) - 5._dp/3._dp) < dptol) call check(error, ieee_is_nan((var(i321, i321 < 0)))) call check(error, ieee_is_nan((var(i321, i321 == 1)))) call check(error, abs(var(i321, 1, i321 < 5) - 5._dp/3._dp) < dptol) end subroutine test_int32_1dim_mask_array subroutine test_int32_2dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i32) - 13) < dptol) call check(error, all( abs( var(i32,1) -& [20._dp/3._dp, 20._dp/3._dp, 5._dp/3._dp]) < dptol)) call check(error, all( abs( var(i32,2) -& [19.0_dp, 43._dp/3._dp, 31._dp/3._dp, 7.0_dp]) < dptol)) end subroutine test_int32_2dim subroutine test_int32_2dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(i32, .false.))) call check(error, any(ieee_is_nan(var(i32, 1, .false.)))) call check(error, any(ieee_is_nan(var(i32, 2, .false.)))) end subroutine test_int32_2dim_mask subroutine test_int32_2dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i32, i32 < 11) - 27.5_dp / 3._dp) < dptol) call check(error, all( abs( var(i32, 1, i32 < 11) -& [20._dp / 3._dp, 20._dp / 3._dp, 0.5_dp]) < dptol)) call check(error, all( abs( var(i32, 2, i32 < 11) -& [19.0_dp, 43._dp / 3._dp, 0.5_dp, 0.5_dp]) < dptol)) end subroutine test_int32_2dim_mask_array subroutine test_int32_3dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i323) - 153.4_dp) < dptol) call check(error, all( abs( var(i323, 1) -& reshape([20._dp / 3._dp, 20._dp / 3._dp, 5._dp / 3._dp,& 4* 20._dp / 3._dp, 4* 20._dp / 3._dp, 4* 5._dp / 3._dp,& 16* 20._dp / 3._dp, 16* 20._dp / 3._dp, 16* 5._dp / 3._dp],& [size(i323,2), size(i323,3)]))& < dptol)) call check(error, all( abs( var(i323, 2) -& reshape([19.0_dp, 43._dp / 3._dp, 31._dp / 3._dp , 7.0_dp,& 4* 19.0_dp, 4* 43._dp / 3._dp, 4* 31._dp / 3._dp , 4* 7.0_dp,& 16* 19.0_dp, 16* 43._dp / 3._dp, 16* 31._dp / 3._dp ,& 16* 7.0_dp],& [size(i323,1), size(i323,3)] ))& < dptol)) call check(error, all(abs( var(i323, 3) -& reshape([ 7._dp/3._dp, 21._dp, 175._dp/3._dp,& 343._dp/3._dp, 28._dp/3._dp, 112._dp/3._dp,& 84._dp, 448._dp/3._dp, 189._dp,& 700._dp/3._dp, 847._dp/3._dp, 336._dp],& [size(i323,1), size(i323,2)] ))& < dptol)) end subroutine test_int32_3dim subroutine test_int32_3dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(i323, .false.))) call check(error, any(ieee_is_nan(var(i323, 1, .false.)))) call check(error, any(ieee_is_nan(var(i323, 2, .false.)))) call check(error, any(ieee_is_nan(var(i323, 3, .false.)))) end subroutine test_int32_3dim_mask subroutine test_int32_3dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i323, i323 < 25) - 46.041379310344823_dp) < dptol) call check(error, all( abs( var(i323, 1, i323 < 45) -& reshape([20._dp/3._dp, 20._dp/3._dp, 5._dp/3._dp,& 80._dp/3._dp, 80._dp/3._dp, 20._dp/3._dp,& 320._dp/3._dp, 320._dp/3._dp, 16._dp],& [size(i323, 2), size(i323, 3)]))& < dptol )) call check(error, any( ieee_is_nan( var(i323, 2, i323 < 25)))) call check(error, all( abs( var(i323, 3, i323 < 25) -& reshape([ 7._dp/3._dp, 21._dp, 175._dp/3._dp,& 24.5_dp, 28._dp/3._dp, 112._dp/3._dp,& 84._dp, 32._dp, 40.5_dp,& 50._dp, 60.5_dp, 72._dp],& [size(i323,1), size(i323,2)] ))& < dptol )) end subroutine test_int32_3dim_mask_array subroutine test_int64_1dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i641) - 2.5) < dptol) call check(error, abs(var(i641, 1) - 2.5) < dptol) end subroutine test_int64_1dim subroutine test_int64_1dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(i641, .false.))) call check(error, ieee_is_nan(var(i641, 1, .false.))) end subroutine test_int64_1dim_mask subroutine test_int641_1dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i641, i641 < 5) - 5._dp/3._dp) < dptol) call check(error, ieee_is_nan((var(i641, i641 < 0)))) call check(error, ieee_is_nan((var(i641, i641 == 1)))) call check(error, abs(var(i641, 1, i641 < 5) - 5._dp/3._dp) < dptol) end subroutine test_int641_1dim_mask_array subroutine test_int64_2dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i64) - 13) < dptol) call check(error, all( abs( var(i64,1) -& [20._dp/3._dp, 20._dp/3._dp, 5._dp/3._dp]) < dptol)) call check(error, all( abs( var(i64,2) -& [19.0_dp, 43._dp/3._dp, 31._dp/3._dp, 7.0_dp]) < dptol)) end subroutine test_int64_2dim subroutine test_int64_2dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(i64, .false.))) call check(error, any(ieee_is_nan(var(i64, 1, .false.)))) call check(error, any(ieee_is_nan(var(i64, 2, .false.)))) end subroutine test_int64_2dim_mask subroutine test_int64_2dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i64, i64 < 11) - 27.5_dp / 3._dp) < dptol) call check(error, all( abs( var(i64, 1, i64 < 11) -& [20._dp / 3._dp, 20._dp / 3._dp, 0.5_dp]) < dptol)) call check(error, all( abs( var(i64, 2, i64 < 11) -& [19.0_dp, 43._dp / 3._dp, 0.5_dp, 0.5_dp]) < dptol)) end subroutine test_int64_2dim_mask_array subroutine test_int64_3dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i643) - 153.4_dp) < dptol) call check(error, all( abs( var(i643, 1) -& reshape([20._dp / 3._dp, 20._dp / 3._dp, 5._dp / 3._dp,& 4* 20._dp / 3._dp, 4* 20._dp / 3._dp, 4* 5._dp / 3._dp,& 16* 20._dp / 3._dp, 16* 20._dp / 3._dp, 16* 5._dp / 3._dp],& [size(i643,2), size(i643,3)]))& < dptol)) call check(error, all( abs( var(i643, 2) -& reshape([19.0_dp, 43._dp / 3._dp, 31._dp / 3._dp , 7.0_dp,& 4* 19.0_dp, 4* 43._dp / 3._dp, 4* 31._dp / 3._dp , 4* 7.0_dp,& 16* 19.0_dp, 16* 43._dp / 3._dp, 16* 31._dp / 3._dp ,& 16* 7.0_dp],& [size(i643,1), size(i643,3)] ))& < dptol)) call check(error, all(abs( var(i643, 3) -& reshape([ 7._dp/3._dp, 21._dp, 175._dp/3._dp,& 343._dp/3._dp, 28._dp/3._dp, 112._dp/3._dp,& 84._dp, 448._dp/3._dp, 189._dp,& 700._dp/3._dp, 847._dp/3._dp, 336._dp],& [size(i643,1), size(i643,2)] ))& < dptol)) end subroutine test_int64_3dim subroutine test_int64_3dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(i643, .false.))) call check(error, any(ieee_is_nan(var(i643, 1, .false.)))) call check(error, any(ieee_is_nan(var(i643, 2, .false.)))) call check(error, any(ieee_is_nan(var(i643, 3, .false.)))) end subroutine test_int64_3dim_mask subroutine test_int64_3dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(i643, i643 < 25) - 46.041379310344823_dp) < dptol) call check(error, all( abs( var(i643, 1, i643 < 45) -& reshape([20._dp/3._dp, 20._dp/3._dp, 5._dp/3._dp,& 80._dp/3._dp, 80._dp/3._dp, 20._dp/3._dp,& 320._dp/3._dp, 320._dp/3._dp, 16._dp],& [size(i643, 2), size(i643, 3)]))& < dptol )) call check(error, any( ieee_is_nan( var(i643, 2, i643 < 25)))) call check(error, all( abs( var(i643, 3, i643 < 25) -& reshape([ 7._dp/3._dp, 21._dp, 175._dp/3._dp,& 24.5_dp, 28._dp/3._dp, 112._dp/3._dp,& 84._dp, 32._dp, 40.5_dp,& 50._dp, 60.5_dp, 72._dp],& [size(i643,1), size(i643,2)] ))& < dptol )) end subroutine test_int64_3dim_mask_array subroutine test_csp_1dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cs1) - (var(real(cs1)) + var(aimag(cs1)))) < sptol) call check(error, abs(var(cs1, dim=1) - (var(real(cs1),1) + var(aimag(cs1), 1)) ) < sptol) end subroutine test_csp_1dim subroutine test_csp_1dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(cs1, .false.))) call check(error, ieee_is_nan(var(cs1, 1, .false.))) end subroutine test_csp_1dim_mask subroutine test_csp_1dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cs1, aimag(cs1) == 0) - var(real(cs1), aimag(cs1) == 0)) < sptol) call check(error, abs(var(cs1, 1, aimag(cs1) == 0) - var(real(cs1), 1, aimag(cs1) == 0)) < sptol) end subroutine test_csp_1dim_mask_array subroutine test_csp_2dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cs) - (var(real(cs)) + var(aimag(cs)))) < sptol) call check(error, all( abs( var(cs, 1) - (var(real(cs), 1) + var(aimag(cs), 1))) < sptol)) call check(error, all( abs( var(cs, 2) - (var(real(cs), 2) + var(aimag(cs), 2))) < sptol)) end subroutine test_csp_2dim subroutine test_csp_2dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(cs, .false.))) call check(error, any(ieee_is_nan(var(cs, 1, .false.)))) call check(error, any(ieee_is_nan(var(cs, 2, .false.)))) end subroutine test_csp_2dim_mask subroutine test_csp_2dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cs, aimag(cs) == 0) - var(real(cs), aimag(cs) == 0)) < sptol) call check(error, all( abs( var(cs, 1, aimag(cs) == 0) - var(real(cs), 1, aimag(cs) == 0)) < sptol)) call check(error, any( ieee_is_nan( var(cs, 2, aimag(cs) == 0)))) end subroutine test_csp_2dim_mask_array subroutine test_cdp_1dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cd1) - (var(real(cd1)) + var(aimag(cd1)))) < dptol) call check(error, abs(var(cd1, dim=1) - (var(real(cd1),1) + var(aimag(cd1), 1)) ) < dptol) end subroutine test_cdp_1dim subroutine test_cdp_1dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(cd1, .false.))) call check(error, ieee_is_nan(var(cd1, 1, .false.))) end subroutine test_cdp_1dim_mask subroutine test_cdp_1dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cd1, aimag(cd1) == 0) - var(real(cd1), aimag(cd1) == 0)) < dptol) call check(error, abs(var(cd1, 1, aimag(cd1) == 0) - var(real(cd1), 1, aimag(cd1) == 0)) < dptol) end subroutine test_cdp_1dim_mask_array subroutine test_cdp_2dim(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cd) - (var(real(cd)) + var(aimag(cd)))) < dptol) call check(error, all( abs( var(cd, 1) - (var(real(cd), 1) + var(aimag(cd), 1))) < dptol)) call check(error, all( abs( var(cd, 2) - (var(real(cd), 2) + var(aimag(cd), 2))) < dptol)) end subroutine test_cdp_2dim subroutine test_cdp_2dim_mask(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, ieee_is_nan(var(cd, .false.))) call check(error, any(ieee_is_nan(var(cd, 1, .false.)))) call check(error, any(ieee_is_nan(var(cd, 2, .false.)))) end subroutine test_cdp_2dim_mask subroutine test_cdp_2dim_mask_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, abs(var(cd, aimag(cd) == 0) - var(real(cd), aimag(cd) == 0)) < dptol) call check(error, all( abs( var(cd, 1, aimag(cd) == 0) - var(real(cd), 1, aimag(cd) == 0)) < dptol)) call check(error, any( ieee_is_nan( var(cd, 2, aimag(cd) == 0)))) end subroutine test_cdp_2dim_mask_array end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_var, only : collect_var implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("var", collect_var) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/stats/test_moment.f900000664000175000017500000015210115135654166023161 0ustar alastairalastairmodule test_moment use,intrinsic :: ieee_arithmetic, only : ieee_is_nan use stdlib_kinds, only: sp, dp, int32, int64 use stdlib_stats, only: moment use testdrive, only: new_unittest, unittest_type, error_type, check implicit none private public :: collect_moment, initialize_test_data real(sp), parameter :: sptol = 1000 * epsilon(1._sp) real(dp), parameter :: dptol = 1000 * epsilon(1._dp) real(dp), parameter :: d1(5) = [1._dp, 2._dp, 3._dp, 4._dp, 5._dp] real(dp), parameter :: d(4,3) = reshape( & [1._dp, 3._dp, 5._dp, 7._dp, & 2._dp, 4._dp, 6._dp, 8._dp, & 9._dp, 10._dp, 11._dp, 12._dp], [4, 3]) complex(dp) :: c1(5) = [(0.57706_dp, 0.00000_dp), & (0.00000_dp, 1.44065_dp), & (1.26401_dp, 0.00000_dp), & (0.00000_dp, 0.88833_dp), & (1.14352_dp, 0.00000_dp)] complex(dp) :: c2(5,3) real(sp) :: x1(5) = real(d1, sp) real(sp) :: x2(4,3) = real(d, sp) real(sp), allocatable :: x3(:,:,:) real(dp) :: dx1(5) = d1 real(dp) :: dx2(4,3) = d real(dp), allocatable :: dx3(:,:,:) integer(int32) :: i1(5) = d1 integer(int32) :: i2(4,3) = d integer(int32), allocatable :: i3(:,:,:) integer(int64) :: di1(5) = d1 integer(int64) :: di2(4,3) = d integer(int64), allocatable :: di3(:,:,:) contains subroutine initialize_test_data() allocate(x3(size(x2, 1),size(x2, 2),3)) x3(:,:,1) = x2 x3(:,:,2) = x2 * 2 x3(:,:,3) = x2 * 4 allocate(dx3(size(dx2, 1),size(dx2, 2),3)) dx3(:,:,1) = dx2 dx3(:,:,2) = dx2 * 2 dx3(:,:,3) = dx2 * 4 i3 = x3 di3 = dx3 c2(:,1) = c1 c2(:,2) = c1 * 3 c2(:,3) = c1 * 1.5 end subroutine initialize_test_data !> Collect all exported unit tests subroutine collect_moment(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest('moment_sp_dim1_order1', test_sp_dim1_order1), & new_unittest('moment_sp_dim1_mask_order1', test_sp_dim1_mask_order1), & new_unittest('moment_sp_dim1_mask_array_order1', test_sp_dim1_mask_array_order1), & new_unittest('moment_sp_dim2_order1', test_sp_dim2_order1), & new_unittest('moment_sp_dim2_mask_order1', test_sp_dim2_mask_order1), & new_unittest('moment_sp_dim2_mask_array_order1', test_sp_dim2_mask_array_order1), & new_unittest('moment_sp_dim3_order1', test_sp_dim3_order1), & new_unittest('moment_sp_dim3_mask_order1', test_sp_dim3_mask_order1), & new_unittest('moment_sp_dim3_mask_array_order1', test_sp_dim3_mask_array_order1), & new_unittest('moment_sp_dim1_order2', test_sp_dim1_order2), & new_unittest('moment_sp_dim1_mask_order2', test_sp_dim1_mask_order2), & new_unittest('moment_sp_dim1_mask_array_order2', test_sp_dim1_mask_array_order2), & new_unittest('moment_sp_dim2_order2', test_sp_dim2_order2), & new_unittest('moment_sp_dim2_mask_order2', test_sp_dim2_mask_order2), & new_unittest('moment_sp_dim2_mask_array_order2', test_sp_dim2_mask_array_order2), & new_unittest('moment_sp_dim3_order2', test_sp_dim3_order2), & new_unittest('moment_sp_dim3_mask_order2', test_sp_dim3_mask_order2), & new_unittest('moment_sp_dim3_mask_array_order2', test_sp_dim3_mask_array_order2), & new_unittest('moment_dp_dim1_order1', test_dp_dim1_order1), & new_unittest('moment_dp_dim1_mask_order1', test_dp_dim1_mask_order1), & new_unittest('moment_dp_dim1_mask_array_order1', test_dp_dim1_mask_array_order1), & new_unittest('moment_dp_dim2_order1', test_dp_dim2_order1), & new_unittest('moment_dp_dim2_mask_order1', test_dp_dim2_mask_order1), & new_unittest('moment_dp_dim2_mask_array_order1', test_dp_dim2_mask_array_order1), & new_unittest('moment_dp_dim3_order1', test_dp_dim3_order1), & new_unittest('moment_dp_dim3_mask_order1', test_dp_dim3_mask_order1), & new_unittest('moment_dp_dim3_mask_array_order1', test_dp_dim3_mask_array_order1), & new_unittest('moment_dp_dim1_order2', test_dp_dim1_order2), & new_unittest('moment_dp_dim1_mask_order2', test_dp_dim1_mask_order2), & new_unittest('moment_dp_dim1_mask_array_order2', test_dp_dim1_mask_array_order2), & new_unittest('moment_dp_dim2_order2', test_dp_dim2_order2), & new_unittest('moment_dp_dim2_mask_order2', test_dp_dim2_mask_order2), & new_unittest('moment_dp_dim2_mask_array_order2', test_dp_dim2_mask_array_order2), & new_unittest('moment_dp_dim3_order2', test_dp_dim3_order2), & new_unittest('moment_dp_dim3_mask_order2', test_dp_dim3_mask_order2), & new_unittest('moment_dp_dim3_mask_array_order2', test_dp_dim3_mask_array_order2), & new_unittest('moment_int32_dim1_order1', test_int32_dim1_order1), & new_unittest('moment_int32_dim1_mask_order1', test_int32_dim1_mask_order1), & new_unittest('moment_int32_dim1_mask_array_order1', test_int32_dim1_mask_array_order1), & new_unittest('moment_int32_dim2_order1', test_int32_dim2_order1), & new_unittest('moment_int32_dim2_mask_order1', test_int32_dim2_mask_order1), & new_unittest('moment_int32_dim2_mask_array_order1', test_int32_dim2_mask_array_order1), & new_unittest('moment_int32_dim3_order1', test_int32_dim3_order1), & new_unittest('moment_int32_dim3_mask_order1', test_int32_dim3_mask_order1), & new_unittest('moment_int32_dim3_mask_array_order1', test_int32_dim3_mask_array_order1), & new_unittest('moment_int32_dim1_order2', test_int32_dim1_order2), & new_unittest('moment_int32_dim1_mask_order2', test_int32_dim1_mask_order2), & new_unittest('moment_int32_dim1_mask_array_order2', test_int32_dim1_mask_array_order2), & new_unittest('moment_int32_dim2_order2', test_int32_dim2_order2), & new_unittest('moment_int32_dim2_mask_order2', test_int32_dim2_mask_order2), & new_unittest('moment_int32_dim2_mask_array_order2', test_int32_dim2_mask_array_order2), & new_unittest('moment_int32_dim3_order2', test_int32_dim3_order2), & new_unittest('moment_int32_dim3_mask_order2', test_int32_dim3_mask_order2), & new_unittest('moment_int32_dim3_mask_array_order2', test_int32_dim3_mask_array_order2), & new_unittest('moment_int64_dim1_order1', test_int64_dim1_order1), & new_unittest('moment_int64_dim1_mask_order1', test_int64_dim1_mask_order1), & new_unittest('moment_int64_dim1_mask_array_order1', test_int64_dim1_mask_array_order1), & new_unittest('moment_int64_dim2_order1', test_int64_dim2_order1), & new_unittest('moment_int64_dim2_mask_order1', test_int64_dim2_mask_order1), & new_unittest('moment_int64_dim2_mask_array_order1', test_int64_dim2_mask_array_order1), & new_unittest('moment_int64_dim3_order1', test_int64_dim3_order1), & new_unittest('moment_int64_dim3_mask_order1', test_int64_dim3_mask_order1), & new_unittest('moment_int64_dim3_mask_array_order1', test_int64_dim3_mask_array_order1), & new_unittest('moment_int64_dim1_order2', test_int64_dim1_order2), & new_unittest('moment_int64_dim1_mask_order2', test_int64_dim1_mask_order2), & new_unittest('moment_int64_dim1_mask_array_order2', test_int64_dim1_mask_array_order2), & new_unittest('moment_int64_dim2_order2', test_int64_dim2_order2), & new_unittest('moment_int64_dim2_mask_order2', test_int64_dim2_mask_order2), & new_unittest('moment_int64_dim2_mask_array_order2', test_int64_dim2_mask_array_order2), & new_unittest('moment_int64_dim3_order2', test_int64_dim3_order2), & new_unittest('moment_int64_dim3_mask_order2', test_int64_dim3_mask_order2), & new_unittest('moment_int64_dim3_mask_array_order2', test_int64_dim3_mask_array_order2), & new_unittest('moment_csp_dim1_order1', test_csp_dim1_order1), & new_unittest('moment_csp_dim1_mask_order1', test_csp_dim1_mask_order1), & new_unittest('moment_csp_dim1_mask_array_order1', test_csp_dim1_mask_array_order1), & new_unittest('moment_csp_dim2_order1', test_csp_dim2_order1), & new_unittest('moment_csp_dim2_mask_order1', test_csp_dim2_mask_order1), & new_unittest('moment_csp_dim2_mask_array_order1', test_csp_dim2_mask_array_order1), & new_unittest('moment_csp_dim1_order2', test_csp_dim1_order2), & new_unittest('moment_csp_dim1_mask_order2', test_csp_dim1_mask_order2), & new_unittest('moment_csp_dim1_mask_array_order2', test_csp_dim1_mask_array_order2), & new_unittest('moment_csp_dim2_order2', test_csp_dim2_order2), & new_unittest('moment_csp_dim2_mask_order2', test_csp_dim2_mask_order2), & new_unittest('moment_csp_dim2_mask_array_order2', test_csp_dim2_mask_array_order2) & ] end subroutine collect_moment subroutine test_sp_dim1_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(x1, order)) < sptol) call check(error, abs(moment(x1, order, dim=1)) < sptol) end subroutine subroutine test_sp_dim1_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(x1, order, mask=.false.))) call check(error, ieee_is_nan(moment(x1, order, 1, mask=.false.))) end subroutine subroutine test_sp_dim1_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(x1, order, mask=(x1 < 5))) < sptol) call check(error, abs(moment(x1, order, 1, mask=(x1 < 5))) < sptol) end subroutine subroutine test_sp_dim2_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(x2, order)) < sptol) call check(error, all(abs(moment(x2, order, 1)) < sptol)) call check(error, all(abs(moment(x2, order, 2)) < sptol)) end subroutine subroutine test_sp_dim2_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(x2, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(x2, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(x2, order, 2, mask=.false.)))) end subroutine subroutine test_sp_dim2_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(x2, order, mask=(x2 < 11))) < sptol) call check(error, all(abs(moment(x2, order, 1, mask=(x2 < 11))) < sptol)) call check(error, all(abs(moment(x2, order, 2, mask=(x2 < 11))) < sptol)) end subroutine subroutine test_sp_dim3_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(x3, order)) < sptol) call check(error, all(abs(moment(x3, order, 1)) < sptol)) call check(error, all(abs(moment(x3, order, 2)) < sptol)) call check(error, all(abs(moment(x3, order, 3)) < sptol)) end subroutine subroutine test_sp_dim3_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(x3, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(x3, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(x3, order, 2, mask=.false.)))) call check(error, any(ieee_is_nan(moment(x3, order, 3, mask=.false.)))) end subroutine subroutine test_sp_dim3_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(x3, order, mask=(x3 < 11)) ) < sptol) call check(error, all(abs(moment(x3, order, 1, mask=(x3 < 45))) < sptol )) call check(error, all(abs(moment(x3, order, 2, mask=(x3 < 45))) < sptol )) call check(error, all(abs(moment(x3, order, 3, mask=(x3 < 45))) < sptol )) end subroutine subroutine test_sp_dim1_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(x1, order) - 2._sp) < sptol) call check(error, abs(moment(x1, order, dim=1) - 2._sp) < sptol) end subroutine subroutine test_sp_dim1_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(x1, order, mask=.false.))) call check(error, ieee_is_nan(moment(x1, order, 1, mask=.false.))) end subroutine subroutine test_sp_dim1_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(x1, order, mask=(x1 < 5)) - 1.25_sp) < sptol) call check(error, abs(moment(x1, order, 1, mask=(x1 < 5)) - 1.25_sp) < sptol) end subroutine subroutine test_sp_dim2_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(x2, order) - 107.25_sp/9.) < sptol) call check(error, all(abs(moment(x2, order, 1) - [5._sp, 5._sp, 1.25_sp]) < sptol)) call check(error, all(abs(moment(x2, order, 2) -& [19.0, 43. / 3., 31. / 3. , 7.0]*2./3.) < sptol)) end subroutine subroutine test_sp_dim2_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(x2, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(x2, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(x2, order, 2, mask=.false.)))) end subroutine subroutine test_sp_dim2_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(x2, order, mask=(x2 < 11))- 2.75_sp*3.) < sptol) call check(error, all(abs(moment(x2, order, 1, mask=(x2 < 11)) -& [5._sp, 5._sp, 0.25_sp]) < sptol)) call check(error, all(abs(moment(x2, order, 2, mask=(x2 < 11)) -& [19._sp*2./3., 43._sp/9.*2., 0.25_sp , 0.25_sp]) < sptol)) end subroutine subroutine test_sp_dim3_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(x3, order) - 153.4_sp*35./36.) < sptol) call check(error, all(abs(moment(x3, order, 1) -& reshape([20._sp / 3., 20._sp / 3., 5._sp / 3.,& 4* 20._sp / 3., 4* 20._sp / 3., 4* 5._sp / 3.,& 16* 20._sp / 3., 16* 20._sp / 3., 16* 5._sp / 3.],& [size(x3,2), size(x3,3)])*3._sp/4.)& < sptol)) call check(error, all(abs(moment(x3, order, 2) -& reshape([19._sp, 43._sp / 3., 31._sp / 3. , 7.0_sp,& 4* 19.0_sp, 4* 43._sp / 3., 4* 31._sp / 3. , 4* 7.0_sp,& 16* 19.0_sp, 16* 43._sp / 3., 16* 31._sp / 3. , 16* 7.0_sp],& [size(x3,1), size(x3,3)] )*2._sp/3.)& < sptol)) call check(error, all(abs(moment(x3, order, 3) -& reshape([ 7._sp/3., 21._sp, 175._sp/3.,& 343._sp/3., 28._sp/3., 112._sp/3.,& 84._sp, 448._sp/3., 189._sp,& 700._sp/3., 847._sp/3., 336._sp],& [size(x3,1), size(x3,2)] )*2./3.)& < sptol)) end subroutine subroutine test_sp_dim3_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(x3, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(x3, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(x3, order, 2, mask=.false.)))) call check(error, any(ieee_is_nan(moment(x3, order, 3, mask=.false.)))) end subroutine subroutine test_sp_dim3_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(x3, order, mask=(x3 < 11)) -& 7.7370242214532876_dp ) < sptol) call check(error, all(abs(moment(x3, order, 1, mask=(x3 < 45)) -& reshape([5._sp, 5._sp, 1.25_sp, 20._sp, 20._sp, 5._sp,& 80._sp, 80._sp, 32._sp/3.],& [size(x3, 2), size(x3, 3)])) < sptol )) call check(error, all(abs(moment(x3, order, 2, mask=(x3 < 45)) -& reshape([ 38._sp/3., 86._sp/9., 62._sp/9., 14._sp/3., 152._sp/3.,& 344._sp/9., 248._sp/9., 168._sp/9., 1824._sp/9.,& 1376._sp/9., 992._sp/9., 4._sp& ],& [size(x3, 1), size(x3, 3)])) < sptol )) call check(error, all(abs(moment(x3, order, 3, mask=(x3 < 45)) -& reshape([14._sp/9., 14._sp, 350._sp/9., 686._sp/9., 56._sp/9.,& 224._sp/9., 56._sp, 896._sp/9., 126._sp, 1400._sp/9.,& 1694._sp/9., 36._sp& ], [size(x3,1), size(x3,2)] ))& < sptol )) end subroutine subroutine test_dp_dim1_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(dx1, order)) < dptol) call check(error, abs(moment(dx1, order, dim=1)) < dptol) end subroutine subroutine test_dp_dim1_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(dx1, order, mask=.false.))) call check(error, ieee_is_nan(moment(dx1, order, 1, mask=.false.))) end subroutine subroutine test_dp_dim1_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(dx1, order, mask=(dx1 < 5))) < dptol) call check(error, abs(moment(dx1, order, 1, mask=(dx1 < 5))) < dptol) end subroutine subroutine test_dp_dim2_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(dx2, order)) < dptol) call check(error, all(abs(moment(dx2, order, 1)) < dptol)) call check(error, all(abs(moment(dx2, order, 2)) < dptol)) end subroutine subroutine test_dp_dim2_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(dx2, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(dx2, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(dx2, order, 2, mask=.false.)))) end subroutine subroutine test_dp_dim2_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(dx2, order, mask=(dx2 < 11))) < dptol) call check(error, all(abs(moment(dx2, order, 1, mask=(dx2 < 11))) < dptol)) call check(error, all(abs(moment(dx2, order, 2, mask=(dx2 < 11))) < dptol)) end subroutine subroutine test_dp_dim3_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(dx3, order)) < dptol) call check(error, all(abs(moment(dx3, order, 1)) < dptol)) call check(error, all(abs(moment(dx3, order, 2)) < dptol)) call check(error, all(abs(moment(dx3, order, 3)) < dptol)) end subroutine subroutine test_dp_dim3_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(dx3, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(dx3, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(dx3, order, 2, mask=.false.)))) call check(error, any(ieee_is_nan(moment(dx3, order, 3, mask=.false.)))) end subroutine subroutine test_dp_dim3_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(dx3, order, mask=(dx3 < 11)) ) < dptol) call check(error, all(abs(moment(dx3, order, 1, mask=(dx3 < 45))) < dptol )) call check(error, all(abs(moment(dx3, order, 2, mask=(dx3 < 45))) < dptol )) call check(error, all(abs(moment(dx3, order, 3, mask=(dx3 < 45))) < dptol )) end subroutine subroutine test_dp_dim1_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(dx1, order) - 2._dp) < dptol) call check(error, abs(moment(dx1, order, dim=1) - 2._dp) < dptol) end subroutine subroutine test_dp_dim1_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(dx1, order, mask=.false.))) call check(error, ieee_is_nan(moment(dx1, order, 1, mask=.false.))) end subroutine subroutine test_dp_dim1_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(dx1, order, mask=(dx1 < 5)) - 1.25_dp) < dptol) call check(error, abs(moment(dx1, order, 1, mask=(dx1 < 5)) - 1.25_dp) < dptol) end subroutine subroutine test_dp_dim2_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(dx2, order) - 107.25_dp/9.) < dptol) call check(error, all(abs(moment(dx2, order, 1) - [5._dp, 5._dp, 1.25_dp]) < dptol)) call check(error, all(abs(moment(dx2, order, 2) -& [19._dp, 43._dp / 3., 31._dp / 3. , 7._dp]*2._dp/3.) < dptol)) end subroutine subroutine test_dp_dim2_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(dx2, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(dx2, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(dx2, order, 2, mask=.false.)))) end subroutine subroutine test_dp_dim2_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(dx2, order, mask=(dx2 < 11))- 2.75_dp*3.) < dptol) call check(error, all(abs(moment(dx2, order, 1, mask=(dx2 < 11)) -& [5._dp, 5._dp, 0.25_dp]) < dptol)) call check(error, all(abs(moment(dx2, order, 2, mask=(dx2 < 11)) -& [19._dp*2./3., 43._dp/9.*2., 0.25_dp , 0.25_dp]) < dptol)) end subroutine subroutine test_dp_dim3_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(dx3, order) - 153.4_dp*35./36.) < dptol) call check(error, all(abs(moment(dx3, order, 1) -& reshape([20._dp / 3., 20._dp / 3., 5._dp / 3.,& 4* 20._dp / 3., 4* 20._dp / 3., 4* 5._dp / 3.,& 16* 20._dp / 3., 16* 20._dp / 3., 16* 5._dp / 3.],& [size(dx3,2), size(dx3,3)])*3._dp/4.)& < dptol)) call check(error, all(abs(moment(dx3, order, 2) -& reshape([19._dp, 43._dp / 3., 31._dp / 3. , 7.0_dp,& 4* 19.0_dp, 4* 43._dp / 3., 4* 31._dp / 3. , 4* 7.0_dp,& 16* 19.0_dp, 16* 43._dp / 3., 16* 31._dp / 3. , 16* 7.0_dp],& [size(dx3,1), size(dx3,3)] )*2._dp/3.)& < dptol)) call check(error, all(abs(moment(dx3, order, 3) -& reshape([ 7._dp/3., 21._dp, 175._dp/3.,& 343._dp/3., 28._dp/3., 112._dp/3.,& 84._dp, 448._dp/3., 189._dp,& 700._dp/3., 847._dp/3., 336._dp],& [size(dx3,1), size(dx3,2)] )*2./3.)& < dptol)) end subroutine subroutine test_dp_dim3_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(dx3, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(dx3, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(dx3, order, 2, mask=.false.)))) call check(error, any(ieee_is_nan(moment(dx3, order, 3, mask=.false.)))) end subroutine subroutine test_dp_dim3_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(dx3, order, mask=(dx3 < 11)) -& 7.7370242214532876_dp ) < dptol) call check(error, all(abs(moment(dx3, order, 1, mask=(dx3 < 45)) -& reshape([5._dp, 5._dp, 1.25_dp, 20._dp, 20._dp, 5._dp,& 80._dp, 80._dp, 32._dp/3.],& [size(dx3, 2), size(dx3, 3)])) < dptol )) call check(error, all(abs(moment(dx3, order, 2, mask=(dx3 < 45)) -& reshape([ 38._dp/3., 86._dp/9., 62._dp/9., 14._dp/3., 152._dp/3.,& 344._dp/9., 248._dp/9., 168._dp/9., 1824._dp/9.,& 1376._dp/9., 992._dp/9., 4._dp& ],& [size(dx3, 1), size(dx3, 3)])) < dptol )) call check(error, all(abs(moment(dx3, order, 3, mask=(dx3 < 45)) -& reshape([14._dp/9., 14._dp, 350._dp/9., 686._dp/9., 56._dp/9.,& 224._dp/9., 56._dp, 896._dp/9., 126._dp, 1400._dp/9.,& 1694._dp/9., 36._dp& ], [size(dx3,1), size(dx3,2)] ))& < dptol )) end subroutine subroutine test_int32_dim1_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(i1, order)) < dptol) call check(error, abs(moment(i1, order, dim=1)) < dptol) end subroutine subroutine test_int32_dim1_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(i1, order, mask=.false.))) call check(error, ieee_is_nan(moment(i1, order, 1, mask=.false.))) end subroutine subroutine test_int32_dim1_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(i1, order, mask=(i1 < 5))) < dptol) call check(error, abs(moment(i1, order, 1, mask=(i1 < 5))) < dptol) end subroutine subroutine test_int32_dim2_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(i2, order)) < dptol) call check(error, all(abs(moment(i2, order, 1)) < dptol)) call check(error, all(abs(moment(i2, order, 2)) < dptol)) end subroutine subroutine test_int32_dim2_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(i2, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(i2, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(i2, order, 2, mask=.false.)))) end subroutine subroutine test_int32_dim2_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(i2, order, mask=(i2 < 11))) < dptol) call check(error, all(abs(moment(i2, order, 1, mask=(i2 < 11))) < dptol)) call check(error, all(abs(moment(i2, order, 2, mask=(i2 < 11))) < dptol)) end subroutine subroutine test_int32_dim3_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(i3, order)) < dptol) call check(error, all(abs(moment(i3, order, 1)) < dptol)) call check(error, all(abs(moment(i3, order, 2)) < dptol)) call check(error, all(abs(moment(i3, order, 3)) < dptol)) end subroutine subroutine test_int32_dim3_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(i3, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(i3, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(i3, order, 2, mask=.false.)))) call check(error, any(ieee_is_nan(moment(i3, order, 3, mask=.false.)))) end subroutine subroutine test_int32_dim3_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(i3, order, mask=(i3 < 11)) ) < dptol) call check(error, all(abs(moment(i3, order, 1, mask=(i3 < 45))) < dptol )) call check(error, all(abs(moment(i3, order, 2, mask=(i3 < 45))) < dptol )) call check(error, all(abs(moment(i3, order, 3, mask=(i3 < 45))) < dptol )) end subroutine subroutine test_int32_dim1_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(i1, order) - 2._dp) < dptol) call check(error, abs(moment(i1, order, dim=1) - 2._dp) < dptol) end subroutine subroutine test_int32_dim1_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(i1, order, mask=.false.))) call check(error, ieee_is_nan(moment(i1, order, 1, mask=.false.))) end subroutine subroutine test_int32_dim1_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(i1, order, mask=(i1 < 5)) - 1.25_dp) < dptol) call check(error, abs(moment(i1, order, 1, mask=(i1 < 5)) - 1.25_dp) < dptol) end subroutine subroutine test_int32_dim2_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(i2, order) - 107.25_dp/9.) < dptol) call check(error, all(abs(moment(i2, order, 1) - [5._dp, 5._dp, 1.25_dp]) < dptol)) call check(error, all(abs(moment(i2, order, 2) -& [19._dp, 43._dp / 3., 31._dp / 3. , 7._dp]*2._dp/3.) < dptol)) end subroutine subroutine test_int32_dim2_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(i2, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(i2, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(i2, order, 2, mask=.false.)))) end subroutine subroutine test_int32_dim2_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(i2, order, mask=(i2 < 11))- 2.75_dp*3.) < dptol) call check(error, all(abs(moment(i2, order, 1, mask=(i2 < 11)) -& [5._dp, 5._dp, 0.25_dp]) < dptol)) call check(error, all(abs(moment(i2, order, 2, mask=(i2 < 11)) -& [19._dp*2./3., 43._dp/9.*2., 0.25_dp , 0.25_dp]) < dptol)) end subroutine subroutine test_int32_dim3_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(i3, order) - 153.4_dp*35./36.) < dptol) call check(error, all(abs(moment(i3, order, 1) -& reshape([20._dp / 3., 20._dp / 3., 5._dp / 3.,& 4* 20._dp / 3., 4* 20._dp / 3., 4* 5._dp / 3.,& 16* 20._dp / 3., 16* 20._dp / 3., 16* 5._dp / 3.],& [size(i3,2), size(i3,3)])*3._dp/4.)& < dptol)) call check(error, all(abs(moment(i3, order, 2) -& reshape([19._dp, 43._dp / 3., 31._dp / 3. , 7.0_dp,& 4* 19.0_dp, 4* 43._dp / 3., 4* 31._dp / 3. , 4* 7.0_dp,& 16* 19.0_dp, 16* 43._dp / 3., 16* 31._dp / 3. , 16* 7.0_dp],& [size(i3,1), size(i3,3)] )*2._dp/3.)& < dptol)) call check(error, all(abs(moment(i3, order, 3) -& reshape([ 7._dp/3., 21._dp, 175._dp/3.,& 343._dp/3., 28._dp/3., 112._dp/3.,& 84._dp, 448._dp/3., 189._dp,& 700._dp/3., 847._dp/3., 336._dp],& [size(i3,1), size(i3,2)] )*2./3.)& < dptol)) end subroutine subroutine test_int32_dim3_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(i3, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(i3, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(i3, order, 2, mask=.false.)))) call check(error, any(ieee_is_nan(moment(i3, order, 3, mask=.false.)))) end subroutine subroutine test_int32_dim3_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(i3, order, mask=(i3 < 11)) -& 7.7370242214532876_dp ) < dptol) call check(error, all(abs(moment(i3, order, 1, mask=(i3 < 45)) -& reshape([5._dp, 5._dp, 1.25_dp, 20._dp, 20._dp, 5._dp,& 80._dp, 80._dp, 32._dp/3.],& [size(i3, 2), size(i3, 3)])) < dptol )) call check(error, all(abs(moment(i3, order, 2, mask=(i3 < 45)) -& reshape([ 38._dp/3., 86._dp/9., 62._dp/9., 14._dp/3., 152._dp/3.,& 344._dp/9., 248._dp/9., 168._dp/9., 1824._dp/9.,& 1376._dp/9., 992._dp/9., 4._dp& ],& [size(i3, 1), size(i3, 3)])) < dptol )) call check(error, all(abs(moment(i3, order, 3, mask=(i3 < 45)) -& reshape([14._dp/9., 14._dp, 350._dp/9., 686._dp/9., 56._dp/9.,& 224._dp/9., 56._dp, 896._dp/9., 126._dp, 1400._dp/9.,& 1694._dp/9., 36._dp& ], [size(i3,1), size(i3,2)] ))& < dptol )) end subroutine subroutine test_int64_dim1_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(di1, order)) < dptol) call check(error, abs(moment(di1, order, dim=1)) < dptol) end subroutine subroutine test_int64_dim1_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(di1, order, mask=.false.))) call check(error, ieee_is_nan(moment(di1, order, 1, mask=.false.))) end subroutine subroutine test_int64_dim1_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(di1, order, mask=(di1 < 5))) < dptol) call check(error, abs(moment(di1, order, 1, mask=(di1 < 5))) < dptol) end subroutine subroutine test_int64_dim2_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(di2, order)) < dptol) call check(error, all(abs(moment(di2, order, 1)) < dptol)) call check(error, all(abs(moment(di2, order, 2)) < dptol)) end subroutine subroutine test_int64_dim2_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(di2, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(di2, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(di2, order, 2, mask=.false.)))) end subroutine subroutine test_int64_dim2_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(di2, order, mask=(di2 < 11))) < dptol) call check(error, all(abs(moment(di2, order, 1, mask=(di2 < 11))) < dptol)) call check(error, all(abs(moment(di2, order, 2, mask=(di2 < 11))) < dptol)) end subroutine subroutine test_int64_dim3_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(di3, order)) < dptol) call check(error, all(abs(moment(di3, order, 1)) < dptol)) call check(error, all(abs(moment(di3, order, 2)) < dptol)) call check(error, all(abs(moment(di3, order, 3)) < dptol)) end subroutine subroutine test_int64_dim3_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(moment(di3, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(di3, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(di3, order, 2, mask=.false.)))) call check(error, any(ieee_is_nan(moment(di3, order, 3, mask=.false.)))) end subroutine subroutine test_int64_dim3_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(di3, order, mask=(di3 < 11)) ) < dptol) call check(error, all(abs(moment(di3, order, 1, mask=(di3 < 45))) < dptol )) call check(error, all(abs(moment(di3, order, 2, mask=(di3 < 45))) < dptol )) call check(error, all(abs(moment(di3, order, 3, mask=(di3 < 45))) < dptol )) end subroutine subroutine test_int64_dim1_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(di1, order) - 2._dp) < dptol) call check(error, abs(moment(di1, order, dim=1) - 2._dp) < dptol) end subroutine subroutine test_int64_dim1_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(di1, order, mask=.false.))) call check(error, ieee_is_nan(moment(di1, order, 1, mask=.false.))) end subroutine subroutine test_int64_dim1_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(di1, order, mask=(di1 < 5)) - 1.25_dp) < dptol) call check(error, abs(moment(di1, order, 1, mask=(di1 < 5)) - 1.25_dp) < dptol) end subroutine subroutine test_int64_dim2_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(di2, order) - 107.25_dp/9.) < dptol) call check(error, all(abs(moment(di2, order, 1) - [5._dp, 5._dp, 1.25_dp]) < dptol)) call check(error, all(abs(moment(di2, order, 2) -& [19._dp, 43._dp / 3., 31._dp / 3. , 7._dp]*2._dp/3.) < dptol)) end subroutine subroutine test_int64_dim2_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(i2, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(di2, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(di2, order, 2, mask=.false.)))) end subroutine subroutine test_int64_dim2_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(di2, order, mask=(di2 < 11))- 2.75_dp*3.) < dptol) call check(error, all(abs(moment(di2, order, 1, mask=(di2 < 11)) -& [5._dp, 5._dp, 0.25_dp]) < dptol)) call check(error, all(abs(moment(di2, order, 2, mask=(di2 < 11)) -& [19._dp*2./3., 43._dp/9.*2., 0.25_dp , 0.25_dp]) < dptol)) end subroutine subroutine test_int64_dim3_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(di3, order) - 153.4_dp*35./36.) < dptol) call check(error, all(abs(moment(di3, order, 1) -& reshape([20._dp / 3., 20._dp / 3., 5._dp / 3.,& 4* 20._dp / 3., 4* 20._dp / 3., 4* 5._dp / 3.,& 16* 20._dp / 3., 16* 20._dp / 3., 16* 5._dp / 3.],& [size(di3,2), size(di3,3)])*3._dp/4.)& < dptol)) call check(error, all(abs(moment(di3, order, 2) -& reshape([19._dp, 43._dp / 3., 31._dp / 3. , 7.0_dp,& 4* 19.0_dp, 4* 43._dp / 3., 4* 31._dp / 3. , 4* 7.0_dp,& 16* 19.0_dp, 16* 43._dp / 3., 16* 31._dp / 3. , 16* 7.0_dp],& [size(di3,1), size(di3,3)] )*2._dp/3.)& < dptol)) call check(error, all(abs(moment(di3, order, 3) -& reshape([ 7._dp/3., 21._dp, 175._dp/3.,& 343._dp/3., 28._dp/3., 112._dp/3.,& 84._dp, 448._dp/3., 189._dp,& 700._dp/3., 847._dp/3., 336._dp],& [size(di3,1), size(di3,2)] )*2./3.)& < dptol)) end subroutine subroutine test_int64_dim3_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(moment(di3, order, mask=.false.))) call check(error, any(ieee_is_nan(moment(di3, order, 1, mask=.false.)))) call check(error, any(ieee_is_nan(moment(di3, order, 2, mask=.false.)))) call check(error, any(ieee_is_nan(moment(di3, order, 3, mask=.false.)))) end subroutine subroutine test_int64_dim3_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(di3, order, mask=(di3 < 11)) -& 7.7370242214532876_dp ) < dptol) call check(error, all(abs(moment(di3, order, 1, mask=(di3 < 45)) -& reshape([5._dp, 5._dp, 1.25_dp, 20._dp, 20._dp, 5._dp,& 80._dp, 80._dp, 32._dp/3.],& [size(di3, 2), size(di3, 3)])) < dptol )) call check(error, all(abs(moment(di3, order, 2, mask=(di3 < 45)) -& reshape([ 38._dp/3., 86._dp/9., 62._dp/9., 14._dp/3., 152._dp/3.,& 344._dp/9., 248._dp/9., 168._dp/9., 1824._dp/9.,& 1376._dp/9., 992._dp/9., 4._dp& ],& [size(i3, 1), size(i3, 3)])) < dptol )) call check(error, all(abs(moment(di3, order, 3, mask=(di3 < 45)) -& reshape([14._dp/9., 14._dp, 350._dp/9., 686._dp/9., 56._dp/9.,& 224._dp/9., 56._dp, 896._dp/9., 126._dp, 1400._dp/9.,& 1694._dp/9., 36._dp& ], [size(di3,1), size(di3,2)] ))& < dptol )) end subroutine subroutine test_csp_dim1_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(c1, order)) < sptol) call check(error, abs(moment(c1, order, dim=1)) < sptol) end subroutine subroutine test_csp_dim1_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(abs(moment(c1, order, mask=.false.)))) call check(error, ieee_is_nan(abs(moment(c1, order, 1, mask=.false.)))) end subroutine subroutine test_csp_dim1_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(c1, order, mask=(aimag(c1) == 0))) < sptol) call check(error, abs(moment(c1, order, 1, mask=(aimag(c1) == 0))) < sptol) end subroutine subroutine test_csp_dim2_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(c2, order)) < sptol) call check(error, all(abs(moment(c2, order, 1)) < sptol)) call check(error, all(abs(moment(c2, order, 2)) < sptol)) end subroutine subroutine test_csp_dim2_mask_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, ieee_is_nan(abs(moment(c2, order, mask=.false.)))) call check(error, any(ieee_is_nan(abs(moment(c2, order, 1, mask=.false.))))) call check(error, any(ieee_is_nan(abs(moment(c2, order, 2, mask=.false.))))) end subroutine subroutine test_csp_dim2_mask_array_order1(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 1 call check(error, abs(moment(c2, order, mask=(aimag(c2) == 0))) < sptol) call check(error, all(abs(moment(c2, order, 1, mask=(aimag(c2) == 0))) < sptol)) call check(error, any(ieee_is_nan( abs(moment(c2, order, 2,& mask=(aimag(c2) == 0)))))) end subroutine subroutine test_csp_dim1_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(c1, order) - (-6.459422410E-02,-0.556084037)) < sptol) call check(error, abs(moment(c1, order, dim=1) -& (-6.459422410E-02,-0.556084037)) < sptol) end subroutine subroutine test_csp_dim1_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(abs(moment(c1, order, mask=.false.)))) call check(error, ieee_is_nan(abs(moment(c1, order, 1, mask=.false.)))) end subroutine subroutine test_csp_dim1_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(c1, order, mask=(aimag(c1) == 0)) -& (8.969944715E-02,0.00000000)) < sptol) call check(error, abs(moment(c1, order, 1, mask=(aimag(c1) == 0)) -& (8.969944715E-02,0.00000000)) < sptol) end subroutine subroutine test_csp_dim2_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(c2, order) - (-0.163121477,-1.86906016)) < sptol) call check(error, all(abs(moment(c2, order, 1) -& [(-6.459422410E-02,-0.556084037),& (-0.581347823,-5.00475645),& (-0.145336956,-1.25118911)]& ) < sptol)) call check(error, all(abs(moment(c2, order, 2) -& [(0.240498722,0.00000000),& (-1.49895227,0.00000000),& (1.15390968,0.00000000),& (-0.569927275,0.00000000),& (0.944405317,0.00000000)]& ) < sptol)) end subroutine subroutine test_csp_dim2_mask_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, ieee_is_nan(abs(moment(c2, order, mask=.false.)))) call check(error, any(ieee_is_nan(abs(moment(c2, order, 1, mask=.false.))))) call check(error, any(ieee_is_nan(abs(moment(c2, order, 2, mask=.false.))))) end subroutine subroutine test_csp_dim2_mask_array_order2(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: order = 2 call check(error, abs(moment(c2, order, mask=(aimag(c2) == 0))-& (1.08109438,0.00000000)) < sptol) call check(error, all(abs(moment(c2, order, 1, mask=(aimag(c2)==0)) -& [(8.969944715E-02,0.00000000),& (0.807295084,0.00000000),& (0.201823771,0.00000000)]& ) < sptol)) end subroutine end module test_moment program tester use, intrinsic :: iso_fortran_env, only: error_unit use testdrive, only: run_testsuite, new_testsuite, testsuite_type use test_moment, only: collect_moment, initialize_test_data implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("moment", collect_moment) & ] call initialize_test_data() do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/stats/test_distribution_normal.fypp0000664000175000017500000003427015135654166026337 0ustar alastairalastair #:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES program test_distribution_normal use stdlib_kinds, only : sp, dp, xdp, qp use stdlib_error, only : check use stdlib_random, only : random_seed use stdlib_stats_distribution_uniform, only : uni => rvs_uniform use stdlib_stats_distribution_normal, only : nor_rvs => rvs_normal, & nor_pdf => pdf_normal, nor_cdf => cdf_normal implicit none #:for k1, t1 in REAL_KINDS_TYPES ${t1}$, parameter :: ${k1}$tol = 1000 * epsilon(1.0_${k1}$) #:endfor logical :: warn = .true. integer :: put, get put = 12345678 call random_seed(put, get) call test_normal_random_generator #:for k1, t1 in RC_KINDS_TYPES call test_nor_rvs_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES call test_nor_rvs_default_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES call test_nor_pdf_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES call test_nor_cdf_${t1[0]}$${k1}$ #:endfor contains subroutine test_normal_random_generator integer, parameter :: num = 10000000, array_size = 1000 integer :: i, j, freq(0:array_size) real(dp) :: chisq, expct print *, "" print *, "Test normal random generator with chi-squared" freq = 0 do i = 1, num j = array_size * (1 + erf(nor_rvs(0.0, 1.0) / sqrt(2.0))) / 2.0 freq(j) = freq(j) + 1 end do chisq = 0.0_dp expct = num / array_size do i = 0, array_size - 1 chisq = chisq + (freq(i) - expct) ** 2 / expct end do write(*,*) "The critical values for chi-squared with 1000 d. of f. is" & //" 1143.92" write(*,*) "Chi-squared for normal random generator is : ", chisq call check((chisq < 1143.9), & msg = "normal randomness failed chi-squared test", warn = warn) end subroutine test_normal_random_generator #:for k1, t1 in RC_KINDS_TYPES subroutine test_nor_rvs_${t1[0]}$${k1}$ ${t1}$ :: res(10), loc, scale integer, parameter :: k = 5 integer :: i integer :: seed, get #:if t1[0] == "r" #! for real type ${t1}$, parameter :: ans(10) = & [2.66708039318040679432897377409972250_${k1}$, & 2.36030794936128329730706809641560540_${k1}$, & 1.27712218793084242296487218482070602_${k1}$, & -2.39132544130814794769435138732660562_${k1}$, & 1.72566595106028652928387145948363468_${k1}$, & -1.50621775537767632613395107910037041_${k1}$, & 2.13518835158352082714827702147886157_${k1}$, & -0.636788253742142318358787633769679815_${k1}$, & 2.48600787778845799813609573902795091_${k1}$, & -3.03711473837981227319460231228731573_${k1}$] #:else #! for complex type ${t1}$, parameter :: ans(10) = & [(2.12531029488530509574673033057479188_${k1}$, & 1.46507698734032082432676702410390135_${k1}$), & (1.08284164094813181722365413861552952_${k1}$, & 0.277168639672963013076412153168348595_${k1}$), & (1.41924946329521489696290359461272601_${k1}$, & 0.498445561155580918466512230224907398_${k1}$), & (1.72639126368764062036120776610914618_${k1}$, & 0.715802936564464420410303091557580046_${k1}$), & (1.98950590834134349860207180427096318_${k1}$, & 0.115721315405046931701349421928171068_${k1}$), & (-1.16929014824793620075382705181255005_${k1}$, & 0.250744737486995217246033007540972903_${k1}$), & (1.57160542831869509683428987045772374_${k1}$, & 0.638282596371312238581197107123443857_${k1}$), & (-1.36106107654239116833139178197598085_${k1}$, & 0.166259201494369124318950525776017457_${k1}$), & (1.13403096805387920698038328737311531_${k1}$, & 1.04232618148691447146347854868508875_${k1}$), & (-1.68220535920475811053620418533682823_${k1}$, & 1.63361446685040256898702182297711261_${k1}$)] #:endif print *, "Test normal_distribution_rvs_${t1[0]}$${k1}$" seed = 25836914 call random_seed(seed, get) #:if t1[0] == "r" #! for real type loc = 0.5_${k1}$; scale = 2.0_${k1}$ #:else #! for complex type loc = (0.5_${k1}$, 1.0_${k1}$); scale = (1.5_${k1}$, 0.5_${k1}$) #:endif do i = 1, k res(i) = nor_rvs(loc, scale) ! 2 dummies end do res(6:10) = nor_rvs(loc, scale, k) ! 3 dummies call check(all(abs(res - ans) < ${k1}$tol), & msg="normal_distribution_rvs_${t1[0]}$${k1}$ failed", warn=warn) end subroutine test_nor_rvs_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES subroutine test_nor_rvs_default_${t1[0]}$${k1}$ ${t1}$ :: a1(10), a2(10), mold integer :: i integer :: seed, get print *, "Test normal_distribution_rvs_default_${t1[0]}$${k1}$" seed = 25836914 call random_seed(seed, get) ! explicit form with loc=0, scale=1 #:if t1[0] == "r" a1 = nor_rvs(0.0_${k1}$, 1.0_${k1}$, 10) #:else a1 = nor_rvs((0.0_${k1}$, 0.0_${k1}$), (1.0_${k1}$, 1.0_${k1}$), 10) #:endif ! reset seed to reproduce same random sequence seed = 25836914 call random_seed(seed, get) ! default mold form: mold used only to disambiguate kind ! For real(dp), mold is optional; for other types (including complex), it's required #:if t1[0] == "r" and k1 == "dp" a2 = nor_rvs(10) ! mold optional for rdp only, defaults to real(dp) #:else #! mold required for all other types including complex and non-dp kinds #:if t1[0] == "r" mold = 0.0_${k1}$ #:else mold = (0.0_${k1}$, 0.0_${k1}$) #:endif a2 = nor_rvs(10, mold) #:endif call check(all(a1 == a2), msg="normal_distribution_rvs_default_${t1[0]}$${k1}$ failed", warn=warn) end subroutine test_nor_rvs_default_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES subroutine test_nor_pdf_${t1[0]}$${k1}$ ${t1}$ :: x1, x2(3,4), loc, scale integer, parameter :: k = 5 integer :: seed, get real(${k1}$) :: res(3,5) #:if t1[0] == "r" #! for real type real(${k1}$), parameter :: ans(15) = & [0.215050766989949083210785218076278553_${k1}$, & 0.215050766989949083210785218076278553_${k1}$, & 0.215050766989949083210785218076278553_${k1}$, & 0.200537626692880596839299818454439236_${k1}$, & 5.66161527403268434368575024104022496E-0002_${k1}$, & 0.238986957612021514867582359518579138_${k1}$, & 0.265935969411942911029638292783132425_${k1}$, & 0.262147558654079961109031890374902943_${k1}$, & 0.249866408914952245533320687656894701_${k1}$, & 3.98721117498705317877792757313696510E-0002_${k1}$, & 0.265902369803533466897906694845094995_${k1}$, & 0.161311603170650092038944290133124635_${k1}$, & 0.249177740354276111998717092437037695_${k1}$, & 0.237427217242213206474603807278971527_${k1}$, & 0.155696086384122017518186260628090478_${k1}$] #:else #! for complex type real(${k1}$), parameter :: ans(15) = & [0.129377311291944176372137325120411497_${k1}$, & 0.129377311291944176372137325120411497_${k1}$, & 0.129377311291944176372137325120411497_${k1}$, & 4.05915662853246811934977653001971736E-0002_${k1}$, & 0.209143395418940756076861773161637924_${k1}$, & 2.98881041363874672676853084975547667E-0002_${k1}$, & 0.128679412679649127469385460133445161_${k1}$, & 0.177484732473055532384223611956177231_${k1}$, & 3.82205306942578982084957100753849738E-0002_${k1}$, & 7.09915714309796034515515428785324918E-0002_${k1}$, & 4.56126582912124629544443072483362352E-0002_${k1}$, & 6.57454133967021123696499056531595921E-0002_${k1}$, & 0.165161039915667041643464172210282279_${k1}$, & 3.86104822953520989775015755966798359E-0002_${k1}$, & 0.196922947431391188040943672442575686_${k1}$] #:endif print *, "Test normal_distribution_pdf_${t1[0]}$${k1}$" seed = 741852963 call random_seed(seed, get) #:if t1[0] == "r" #! for real type loc = -0.5_${k1}$; scale = 1.5_${k1}$ #:else #! for complex type loc = (-0.5_${k1}$, 0.5_${k1}$); scale = (0.5_${k1}$, 1.5_${k1}$) #:endif x1 = nor_rvs(loc, scale) x2 = reshape(nor_rvs(loc, scale, 12), [3,4]) res(:,1) = nor_pdf(x1, loc, scale) res(:, 2:5) = nor_pdf(x2, loc, scale) call check(all(abs(res - reshape(ans, [3,5])) < ${k1}$tol), & msg="normal_distribution_pdf_${t1[0]}$${k1}$ failed", warn=warn) end subroutine test_nor_pdf_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES subroutine test_nor_cdf_${t1[0]}$${k1}$ ${t1}$ :: x1, x2(3,4), loc, scale integer :: seed, get real(${k1}$) :: res(3,5) #:if t1[0] == "r" #!for real type real(${k1}$), parameter :: ans(15) = & [7.50826305038441048487991102776953948E-0002_${k1}$, & 7.50826305038441048487991102776953948E-0002_${k1}$, & 7.50826305038441048487991102776953948E-0002_${k1}$, & 0.143119834108717983250834016885129863_${k1}$, & 0.241425421525703182028420560765471735_${k1}$, & 0.284345878626039240974266199229875972_${k1}$, & 0.233239836366015928845367994433532757_${k1}$, & 0.341059506137219171082517155967522896_${k1}$, & 0.353156850199835111081038166086606192_${k1}$, & 6.81066766396638231790017005897813244E-0002_${k1}$, & 4.38792331441682923984716366123285346E-0002_${k1}$, & 0.763679637882860826030745070304416929_${k1}$, & 0.363722187587355040667876190724308059_${k1}$, & 0.868187114884980488672309198087692444_${k1}$, & 0.626506799809652872401992867475200722_${k1}$] #:else #! for complex type real(${k1}$), parameter :: ans(15) = & [1.07458136221563368133842063954746170E-0002_${k1}$, & 1.07458136221563368133842063954746170E-0002_${k1}$, & 1.07458136221563368133842063954746170E-0002_${k1}$, & 6.86483236063879585051085536740820057E-0002_${k1}$, & 7.95486634025192048896990048539218724E-0002_${k1}$, & 2.40523393996423661445007940057223384E-0002_${k1}$, & 3.35096768781160662250307446207445131E-0002_${k1}$, & 0.315778916661119434962814841317323376_${k1}$, & 0.446311293878359175362094845206410428_${k1}$, & 0.102010220821382542292905161748120877_${k1}$, & 7.66919007012121545175655727052974512E-0002_${k1}$, & 0.564690968410069125818268877247699603_${k1}$, & 0.708769523556518785240723539383512333_${k1}$, & 6.40553790808161720088070925562830659E-0002_${k1}$, & 5.39999153072107729358158443133850711E-0002_${k1}$] #:endif print *, "Test normal_distribution_cdf_${t1[0]}$${k1}$" seed = 369147582 call random_seed(seed, get) #:if t1[0] == "r" #! for real type loc = -1.0_${k1}$; scale = 2.0_${k1}$ #:else #! for complex type loc = (-1.0_${k1}$, 1.0_${k1}$); scale = (1.7_${k1}$, 2.4_${k1}$) #:endif x1 = nor_rvs(loc, scale) x2 = reshape(nor_rvs(loc, scale, 12), [3,4]) res(:,1) = nor_cdf(x1, loc, scale) res(:, 2:5) = nor_cdf(x2, loc, scale) call check(all(abs(res - reshape(ans,[3,5])) < ${k1}$tol), & msg="normal_distribution_cdf_${t1[0]}$${k1}$ failed", warn=warn) end subroutine test_nor_cdf_${t1[0]}$${k1}$ #:endfor end program test_distribution_normal fortran-lang-stdlib-0ede301/test/stats/test_distribution_uniform.fypp0000664000175000017500000004122015135654166026517 0ustar alastairalastair#:include "common.fypp" #:set ALL_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES + CMPLX_KINDS_TYPES program test_distribution_uniform use stdlib_error, only : check use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp use stdlib_random, only : random_seed, dist_rand use stdlib_stats_distribution_uniform, uni_rvs => rvs_uniform, & uni_pdf => pdf_uniform, & uni_cdf => cdf_uniform implicit none logical :: warn = .true. #:for k1, t1 in REAL_KINDS_TYPES ${t1}$, parameter :: ${k1}$tol = 1000 * epsilon(1.0_${k1}$) #:endfor integer :: put put = 135792468 call test_shuffle call test_uni_rvs_0 #:for k1, t1 in ALL_KINDS_TYPES call test_uni_rvs_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in ALL_KINDS_TYPES call test_uni_pdf_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in ALL_KINDS_TYPES call test_uni_cdf_${t1[0]}$${k1}$ #:endfor contains subroutine test_shuffle integer :: n(10) integer, parameter :: na(10) = [10, 6, 9, 2, 8, 1, 3, 5, 7, 4] real :: x(10) real, parameter :: xa(10) = [5.0, 10.0, 9.0, 4.0, 3.0, 8.0, 2.0, 1.0, & 7.0, 6.0] complex :: z(10) complex, parameter :: za(10) = [(8.0, 8.0), (7.0, 7.0), (4.0, 4.0), & (1.0, 1.0), (5.0, 5.0), (9.0, 9.0), & (6.0, 6.0), (3.0, 3.0), (2.0, 2.0), & (10.0, 10.0)] integer :: i, put, get do i = 1, 10 n(i) = i x(i) = real(i) z(i) = cmplx(real(i),real(i)) end do put = 32165498 call random_seed(put, get) n(:) = shuffle(n) x(:) = shuffle(x) z(:) = shuffle(z) call check(all(n == na), & msg = "Integer shuffle failed test", warn=warn) call check(all(x == xa), & msg = "Real shuffle failed test", warn=warn) call check(all(z == za), & msg = "Complex shuffle failed test", warn=warn) end subroutine test_shuffle subroutine test_uni_rvs_0 integer, parameter :: num = 10000000 integer, parameter :: array_size = 1000 integer :: i, j, freq(0 : array_size - 1) real(dp) :: chisq, expct print *,"" print *, "Test uniform random generator with chi-squared" freq = 0 do i = 1, num j = array_size * uni_rvs( ) freq(j) = freq(j) + 1 end do chisq = 0.0_dp expct = num / array_size do i = 0, array_size - 1 chisq = chisq + (freq(i) - expct) ** 2 / expct end do write(*,*) "The critical value for chi-squared with 1000 d. of f. is" & //" 1143.92" write(*,*) "Chi-squared for uniform random generator is : ", chisq call check((chisq < 1143.9) , & msg = "uniform randomness failed chi-squared test", warn=warn) end subroutine test_uni_rvs_0 #:for k1, t1 in ALL_KINDS_TYPES subroutine test_uni_rvs_${t1[0]}$${k1}$ ${t1}$ :: res(15), scale, loc integer :: i, seed, get, k #:if k1 == "int8" ${t1}$, parameter :: ans(15) = [47, 99, 43, 37, 48, 30, 27, 100, 30, & 33, 21, 103, 55, 54, 110] #:elif k1 == "int16" ${t1}$, parameter :: ans(15) = [25, 4, 81, 98, 49, 34, 32, 62, 115, & 112, 26, 20, 37, 100, 82] #:elif k1 == "int32" ${t1}$, parameter :: ans(15) = [19, 52, 56, 20, 59, 44, 34, 102, 19, & 39, 60, 50, 97, 56, 67] #:elif k1 == "int64" ${t1}$, parameter :: ans(15) = [76, 45, 43, 75, 76, 15, 25, 24, 114, & 113, 94, 29, 109, 93, 89] #:elif t1[0] == "r" #! for real type ${t1}$, parameter :: ans(15) = & [0.914826628538749186958511927514337003_${k1}$, & 0.367330098664966409049981166390352882_${k1}$, & 1.77591243057709280428468900936422870_${k1}$, & 0.885921308987590139238932351872790605_${k1}$, & 0.950735656542987861428173346212133765_${k1}$, & -0.659562573857055134407545438079978339_${k1}$, & -0.116661718506947176265953203255776316_${k1}$, & 0.837391893893859151631886561517603695_${k1}$, & -0.703954396598600540269075054311542772_${k1}$, & 0.382592729851141566399519433616660535_${k1}$, & -0.132472493978185168472805344208609313_${k1}$, & -0.878723366294216184924081858298450243_${k1}$, & -0.901660046141515819639877804547722917_${k1}$, & -0.164090614147737401395943379611708224_${k1}$, & -0.333886718190384290672056977200554684_${k1}$] #:else #! for complex type ${t1}$, parameter :: ans(15) = & [(0.457413314269374593479255963757168502_${k1}$, & 0.183665049332483204524990583195176441_${k1}$), & (0.887956215288546402142344504682114348_${k1}$, & 0.442960654493795069619466175936395302_${k1}$), & (0.475367828271493930714086673106066883_${k1}$, & 0.170218713071472432796227280960010830_${k1}$), & (0.441669140746526411867023398372111842_${k1}$, & 0.918695946946929575815943280758801848_${k1}$), & (0.148022801700699729865462472844228614_${k1}$, & 0.691296364925570783199759716808330268_${k1}$), & (-6.623624698909258423640267210430465639E-0002_${k1}$, & 0.560638316852891907537959070850774879_${k1}$), & (-0.450830023070757909819938902273861459_${k1}$, & 0.917954692926131299302028310194145888_${k1}$), & (-0.166943359095192145336028488600277342_${k1}$, & 1.05997401970850635422038976685144007_${k1}$), & (-0.429652190199228276035192664039641386_${k1}$, & 0.523558274341032421628217008446881664_${k1}$), & (0.427181091476823815433760955784237012_${k1}$, & 1.34628934976074521312483511792379431_${k1}$), & (-0.343281426018765739582860874179459643_${k1}$, & 1.15357331316264255516301773241139017_${k1}$), & (-0.127590074749816595467422075671493076_${k1}$, & 1.06891199479835175001340985545539297_${k1}$), & (0.262287586904722758163188700564205647_${k1}$, & 1.29508919831907332032017166056903079_${k1}$), & (-0.192677407376582732201342196276527829_${k1}$, & 1.32794925614337933073016984053538181_${k1}$), & (-0.264742129752461530234342035328154452_${k1}$, & 1.01282963412172621886497836385387927_${k1}$)] #:endif print *, "Test rvs_uniform_${t1[0]}$${k1}$" seed = 258147369; k = 5 call random_seed(seed, get) #:if t1[0] == "i" #! for integer type loc = 15_${k1}$; scale = 100_${k1}$ #:elif t1[0] == "r" #! for real type loc = -1.0_${k1}$; scale = 2.0_${k1}$ #:else #! for complex type loc = (-0.5_${k1}$,0.5_${k1}$); scale = (1.0_${k1}$, 1.0_${k1}$) #:endif do i = 1, 5 res(i) = uni_rvs(scale) ! 1 dummy end do do i = 6,10 res(i) = uni_rvs(loc, scale) ! 2 dummies end do res(11:15) = uni_rvs(loc, scale, k) ! 3 dummies #:if t1[0] == "i" #! for integer type call check(all(res == ans), & msg="rvs_uniform_${t1[0]}$${k1}$ failed", warn=warn) #:else #! for real and complex types call check(all(abs(res - ans) < ${k1}$tol), & msg="rvs_uniform_${t1[0]}$${k1}$ failed", warn=warn) #:endif end subroutine test_uni_rvs_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in ALL_KINDS_TYPES subroutine test_uni_pdf_${t1[0]}$${k1}$ ${t1}$ :: x1, x2(3,4), loc, scale integer :: seed, get, i #:if t1[0] == "i" #! for integer type real :: res(3, 5) real, parameter :: ans(15) = [(1.96078438E-02, i=1,15)] #:elif t1[0] == "r" #! for real type ${t1}$ :: res(3, 5) ${t1}$, parameter :: ans(15) = [(0.5_${k1}$, i=1,15)] #:else #! for complex type real(${k1}$) :: res(3, 5) real(${k1}$), parameter :: ans(15) = [(1.0_${k1}$, i=1,15)] #:endif print *, "Test pdf_uniform_${t1[0]}$${k1}$" seed = 147258639 call random_seed(seed, get) #:if t1[0] == "i" #! for integer type loc = 0_${k1}$; scale = 50_${k1}$ #:elif t1[0] == "r" #! for real type loc = 0.0_${k1}$; scale = 2.0_${k1}$ #:else #! for complex type loc = (-0.5_${k1}$, 0.5_${k1}$); scale = (1.0_${k1}$, 1.0_${k1}$) #:endif x1 = uni_rvs(loc, scale) x2 = reshape(uni_rvs(loc, scale, 12), [3,4]) res(:,1) = uni_pdf(x1, loc, scale) res(:, 2:5) = uni_pdf(x2, loc, scale) #:if t1[0] == "i" #! for integer type call check(all(abs(res - reshape(ans,[3,5])) < sptol), & msg = "pdf_uniform_${t1[0]}$${k1}$ failed", warn=warn) #:else #! for real and complex types call check(all(abs(res - reshape(ans,[3,5])) < ${k1}$tol), & msg = "pdf_uniform_${t1[0]}$${k1}$ failed", warn=warn) #:endif end subroutine test_uni_pdf_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in ALL_KINDS_TYPES subroutine test_uni_cdf_${t1[0]}$${k1}$ ${t1}$ :: x1, x2(3,4), loc, scale integer :: seed, get #:if k1 == "int8" real :: res(3,5) real, parameter :: ans(15) = [0.435643554, 0.435643554, 0.435643554, & 0.702970326, 0.653465331, 0.485148519, & 0.386138618, 0.386138618, 0.336633652, & 0.277227730, 0.237623766, 0.524752498, & 0.732673287, 0.534653485, 0.415841579] #:elif k1 == "int16" real :: res(3,5) real, parameter :: ans(15) = [0.178217828, 0.178217828, 0.178217828, & 0.465346545, 0.673267305, 0.247524753, & 0.158415839, 0.792079210, 0.742574275, & 0.574257433, 0.881188095, 0.663366318, & 0.524752498, 0.623762369, 0.178217828] #:elif k1 == "int32" real :: res(3,5) real, parameter :: ans(15) = [0.732673287, 0.732673287, 0.732673287, & 0.722772300, 0.792079210, 5.94059415E-02,& 0.841584146, 0.405940592, 0.960396051, & 0.534653485, 0.782178223, 0.861386120, & 0.564356446, 0.613861382, 0.306930691] #:elif k1 == "int64" real :: res(3,5) real, parameter :: ans(15) = [0.455445558, 0.455445558, 0.455445558, & 0.277227730, 0.455445558, 0.930693090, & 0.851485133, 0.623762369, 5.94059415E-02,& 0.693069279, 0.544554472, 0.207920790, & 0.306930691, 0.356435657, 0.128712878] #:elif t1[0] == "r" #! for real type ${t1}$ :: res(3,5) ${t1}$, parameter :: ans(15) = & [0.170192944297557408050991512027394492_${k1}$, & 0.170192944297557408050991512027394492_${k1}$, & 0.170192944297557408050991512027394492_${k1}$, & 0.276106146274646191418611351764411665_${k1}$, & 0.754930097473875072466853453079238534_${k1}$, & 0.406620682573118008562573777453508228_${k1}$, & 0.187742819191801080247472555129206739_${k1}$, & 0.651605526090507591874256831943057477_${k1}$, & 0.934733949732104885121941606485052034_${k1}$, & 0.151271491851613287815681019310432021_${k1}$, & 0.987674522797719611766353864368284121_${k1}$, & 0.130533899463404684526679488953959662_${k1}$, & 0.106271905921876880229959283497009892_${k1}$, & 9.27578652240113182836367400341259781E-0002_${k1}$, & 0.203399426853420439709196898547816090_${k1}$] #:else #! for complex type real(${k1}$) :: res(3,5) real(${k1}$), parameter :: ans(15) = & [4.69913179731340971083526490627998168E-0002_${k1}$, & 4.69913179731340971083526490627998168E-0002_${k1}$, & 4.69913179731340971083526490627998168E-0002_${k1}$, & 0.306970191529817593217448363707416739_${k1}$, & 0.122334258469188588238756489506609443_${k1}$, & 0.141398599060326408705075175176932616_${k1}$, & 0.128925006861443729884744412460848140_${k1}$, & 9.85755512660026594506599410104817938E-0003_${k1}$, & 8.16527497645585445208592050401597260E-0002_${k1}$, & 0.163921605454974749736935624944263178_${k1}$, & 7.81712317416218284294000447064256003E-0002_${k1}$, & 0.446415807686727375005224206895756087_${k1}$, & 5.31753272901435018841591264266743165E-0004_${k1}$, & 0.101455865191097416942685556683943046_${k1}$, & 0.155276470981788516449112374966730510_${k1}$] #:endif print *, "Test cdf_uniform_${t1[0]}$${k1}$" seed = 369147258 call random_seed(seed, get) #:if t1[0] == "i" #! for integer type loc = 14_${k1}$; scale = 100_${k1}$ #:elif t1[0] == "r" #! for real type loc = 0.0_${k1}$; scale = 2.0_${k1}$ #:else #! for complex type loc = (-0.5_${k1}$, -0.5_${k1}$); scale = (1.0_${k1}$, 1.0_${k1}$) #:endif x1 = uni_rvs(loc, scale) x2 = reshape(uni_rvs(loc, scale, 12), [3,4]) res(:,1) = uni_cdf(x1, loc, scale) res(:, 2:5) = uni_cdf(x2, loc, scale) #:if t1[0] == "i" #! for integer type call check(all(abs(res - reshape(ans,[3,5])) < sptol), & msg = "cdf_uniform_${t1[0]}$${k1}$ failed", warn=warn) #:else #! for real and complex types call check(all(abs(res - reshape(ans,[3,5])) < ${k1}$tol), & msg = "cdf_uniform_${t1[0]}$${k1}$ failed", warn=warn) #:endif end subroutine test_uni_cdf_${t1[0]}$${k1}$ #:endfor end program test_distribution_uniform fortran-lang-stdlib-0ede301/test/stats/test_mean_f03.fypp0000664000175000017500000003356215135654166023643 0ustar alastairalastair#:include "common.fypp" #:set IR_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES #:set NRANK = 4 module test_stats_meanf03 use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_stats, only: mean use stdlib_kinds, only : int8, int16, int32, int64, sp, dp, xdp, qp use, intrinsic :: ieee_arithmetic, only : ieee_is_nan implicit none private public :: collect_stats_meanf03 real(sp), parameter :: sptol = 1000 * epsilon(1._sp) real(dp), parameter :: dptol = 2000 * epsilon(1._dp) #:if WITH_XDP real(xdp), parameter :: xdptol = 2000 * epsilon(1._xdp) #:endif #:if WITH_QP real(qp), parameter :: qptol = 2000 * epsilon(1._qp) #:endif #:for k1,t1 in IR_KINDS_TYPES ${t1}$ , parameter :: d1_${k1}$(18) = [-10, 2, 3, 4, -6, 6, -7, 8, 9, 4, 1, -20, 9, 10, 14, 15, 40, 30] ${t1}$ :: d8_${k1}$(2, 3, 4, 2, 3, 4, 2, 3) = reshape(d1_${k1}$, [2, 3, 4, 2, 3, 4, 2, 3], [${t1}$:: 3]) #:endfor #:for k1,t1 in CMPLX_KINDS_TYPES ${t1}$ , parameter :: d1_c${k1}$(18) = d1_${k1}$ ${t1}$ :: d8_c${k1}$(2, 3, 4, 2, 3, 4, 2, 3) = reshape(d1_c${k1}$, [2, 3, 4, 2, 3, 4, 2, 3], [${t1}$:: 3]) #:endfor contains !> Collect all exported unit tests subroutine collect_stats_meanf03(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("test_stats_meanf03_all_int8", test_stats_meanf03_all_int8) & #:for k1,t1 in IR_KINDS_TYPES ,new_unittest("test_stats_meanf03_all_${k1}$", test_stats_meanf03_all_${k1}$) & , new_unittest("test_stats_meanf03_all_optmask_${k1}$", test_stats_meanf03_all_optmask_${k1}$) & , new_unittest("test_stats_meanf03_${k1}$", test_stats_meanf03_${k1}$) & , new_unittest("test_stats_meanf03_optmask_${k1}$", test_stats_meanf03_optmask_${k1}$) & , new_unittest("test_stats_meanf03_mask_all_${k1}$", test_stats_meanf03_mask_all_${k1}$) & , new_unittest("test_stats_meanf03_mask_${k1}$", test_stats_meanf03_mask_${k1}$) & #:endfor #:for k1,t1 in CMPLX_KINDS_TYPES ,new_unittest("test_stats_meanf03_all_c${k1}$", test_stats_meanf03_all_c${k1}$) & , new_unittest("test_stats_meanf03_all_optmask_c${k1}$", test_stats_meanf03_all_optmask_c${k1}$) & , new_unittest("test_stats_meanf03_c${k1}$", test_stats_meanf03_c${k1}$) & , new_unittest("test_stats_meanf03_optmask_c${k1}$", test_stats_meanf03_optmask_c${k1}$) & , new_unittest("test_stats_meanf03_mask_all_c${k1}$", test_stats_meanf03_mask_all_c${k1}$) & , new_unittest("test_stats_meanf03_mask_c${k1}$", test_stats_meanf03_mask_c${k1}$) & #:endfor ] end subroutine collect_stats_meanf03 #:for k1,t1 in INT_KINDS_TYPES subroutine test_stats_meanf03_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 call check(error, mean(d8_${k1}$), sum(real(d8_${k1}$, dp))/real(size(d8_${k1}$), dp)& , 'mean(d8_${k1}$): uncorrect answer'& , thr = dptol) if (allocated(error)) return #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_all_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 call check(error, ieee_is_nan(mean(d8_${k1}$, .false.))& , 'mean(d8_${k1}$, .false.): uncorrect answer') if (allocated(error)) return #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 #:for dim in range(1, 9) call check(error& , sum(abs(mean(d8_${k1}$, ${dim}$) -& sum(real(d8_${k1}$, dp), ${dim}$)/real(size(d8_${k1}$, ${dim}$), dp))) < dptol& , 'mean(d8_${k1}$, ${dim}$): uncorrect answer'& ) if (allocated(error)) return #:endfor #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 call check(error, ieee_is_nan(mean(d1_${k1}$, 1, .false.))& , 'mean(d1_${k1}$, 1, .false.): uncorrect answer'& ) if (allocated(error)) return #:for dim in range(1, 9) call check(error, any(ieee_is_nan(mean(d8_${k1}$, ${dim}$, .false.)))& , 'mean(d8_${k1}$, ${dim}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_mask_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 call check(error, mean(d8_${k1}$, d8_${k1}$ > 0)& , sum(real(d8_${k1}$, dp), d8_${k1}$ > 0)/real(count(d8_${k1}$ > 0), dp)& , 'mean(d8_${k1}$, d8_${k1}$ > 0): uncorrect answer'& , thr = dptol) if (allocated(error)) return #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_mask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 #:for dim in range(1, 9) call check(error& , sum(abs(mean(d8_${k1}$, ${dim}$, d8_${k1}$ > 0) -& sum(real(d8_${k1}$, dp), ${dim}$, d8_${k1}$ > 0)/real(count(d8_${k1}$ > 0, ${dim}$), dp))) < dptol& , 'mean(d8_${k1}$, ${dim}$, d8_${k1}$ > 0): uncorrect answer'& ) if (allocated(error)) return #:endfor #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine #:endfor #:for k1,t1 in REAL_KINDS_TYPES subroutine test_stats_meanf03_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 call check(error, mean(d8_${k1}$), sum(d8_${k1}$)/real(size(d8_${k1}$), ${k1}$)& , 'mean(d8_${k1}$): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_all_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 call check(error, ieee_is_nan(mean(d8_${k1}$, .false.))& , 'mean(d8_${k1}$, .false.): uncorrect answer') if (allocated(error)) return #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 #:for dim in range(1, 9) call check(error& , sum(abs(mean(d8_${k1}$, ${dim}$) -& sum(d8_${k1}$, ${dim}$)/real(size(d8_${k1}$, ${dim}$), ${k1}$))) < ${k1}$tol& , 'mean(d8_${k1}$, ${dim}$): uncorrect answer'& ) if (allocated(error)) return #:endfor #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_optmask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 #:for dim in range(1, 9) call check(error, any(ieee_is_nan(mean(d8_${k1}$, ${dim}$, .false.)))& , 'mean(d8_${k1}$, ${dim}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_mask_all_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 call check(error, mean(d8_${k1}$, d8_${k1}$ > 0)& , sum(d8_${k1}$, d8_${k1}$ > 0)/real(count(d8_${k1}$ > 0), ${k1}$)& , 'mean(d8_${k1}$, d8_${k1}$ > 0): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_mask_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 #:for dim in range(1, 9) call check(error& , sum(abs(mean(d8_${k1}$, ${dim}$, d8_${k1}$ > 0) -& sum(d8_${k1}$, ${dim}$, d8_${k1}$ > 0)/real(count(d8_${k1}$ > 0, ${dim}$), ${k1}$))) < ${k1}$tol& , 'mean(d8_${k1}$, ${dim}$, d8_${k1}$ > 0): uncorrect answer'& ) if (allocated(error)) return #:endfor #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine #:endfor #:for k1,t1 in CMPLX_KINDS_TYPES subroutine test_stats_meanf03_all_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 call check(error, mean(d8_c${k1}$), sum(d8_c${k1}$)/real(size(d8_c${k1}$), ${k1}$)& , 'mean(d8_c${k1}$): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_all_optmask_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 call check(error, ieee_is_nan(real(mean(d8_c${k1}$, .false.)))& , 'mean(d8_c${k1}$, .false.): uncorrect answer') if (allocated(error)) return #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 #:for dim in range(1, 9) call check(error& , sum(abs(mean(d8_c${k1}$, ${dim}$) -& sum(d8_c${k1}$, ${dim}$)/real(size(d8_c${k1}$, ${dim}$), ${k1}$))) < ${k1}$tol& , 'mean(d8_c${k1}$, ${dim}$): uncorrect answer'& ) if (allocated(error)) return #:endfor #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_optmask_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 #:for dim in range(1, 9) call check(error, any(ieee_is_nan(real(mean(d8_c${k1}$, ${dim}$, .false.))))& , 'mean(d8_c${k1}$, ${dim}$, .false.): uncorrect answer') if (allocated(error)) return #:endfor #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_mask_all_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 call check(error, mean(d8_c${k1}$, d8_c${k1}$%re > 0)& , sum(d8_c${k1}$, d8_c${k1}$%re > 0)/real(count(d8_c${k1}$%re > 0), ${k1}$)& , 'mean(d8_c${k1}$, d8_c${k1}$%re > 0): uncorrect answer'& , thr = ${k1}$tol) if (allocated(error)) return #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine subroutine test_stats_meanf03_mask_c${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if MAXRANK > 7 #:for dim in range(1, 9) call check(error& , sum(abs(mean(d8_c${k1}$, ${dim}$, d8_c${k1}$%re > 0) -& sum(d8_c${k1}$, ${dim}$, d8_c${k1}$%re > 0)/real(count(d8_c${k1}$%re > 0, ${dim}$), ${k1}$))) < ${k1}$tol& , 'mean(d8_c${k1}$, ${dim}$, d8_c${k1}$%re > 0): uncorrect answer'& ) if (allocated(error)) return #:endfor #:else call skip_test(error, "Rank > 7 is not supported") #:endif end subroutine #:endfor end module test_stats_meanf03 program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_stats_meanf03, only : collect_stats_meanf03 implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("stats_meanf03", collect_stats_meanf03) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/quadrature/0000775000175000017500000000000015135654166021322 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/quadrature/test_gauss.f900000664000175000017500000006063615135654166024036 0ustar alastairalastairmodule test_gauss use stdlib_kinds, only: dp use testdrive, only : new_unittest, unittest_type, error_type, check use stdlib_quadrature , only: gauss_legendre, gauss_legendre_lobatto implicit none contains !> Collect all exported unit tests subroutine collect_gauss(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("gauss-analytic", test_gauss_analytic), & new_unittest("gauss-5", test_gauss_5), & new_unittest("gauss-32", test_gauss_32), & new_unittest("gauss-64", test_gauss_64), & new_unittest("gauss-lobatto-analytic", test_gauss_lobatto_analytic), & new_unittest("gauss-lobatto-5", test_gauss_lobatto_5), & new_unittest("gauss-lobatto-32", test_gauss_lobatto_32), & new_unittest("gauss-lobatto-64", test_gauss_lobatto_64), & new_unittest("gauss-github-issue-619", test_fix_github_issue619) & ] end subroutine subroutine test_gauss_analytic(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i real(dp) :: analytic, numeric ! test an analytic derivative versus an actual integration ! x**2 from -1 to 1 analytic = 2.0_dp/3.0_dp do i=2,6 block real(dp), dimension(i) :: x,w call gauss_legendre(x,w) numeric = sum(x**2 * w) !print *, i, numeric call check(error, abs(numeric-analytic) < 2*epsilon(analytic)) if (allocated(error)) return end block end do end subroutine subroutine test_fix_github_issue619(error) !> See github issue https://github.com/fortran-lang/stdlib/issues/619 type(error_type), allocatable, intent(out) :: error integer :: i ! test the values of nodes and weights i = 5 block real(dp), dimension(i) :: x1,w1,x2,w2 call gauss_legendre(x1,w1) call gauss_legendre(x2,w2,interval=[-1._dp, 1._dp]) call check(error, all(abs(x1-x2) < 2*epsilon(x1(1)))) if (allocated(error)) return call check(error, all(abs(w1-w2) < 2*epsilon(w1(1)))) end block end subroutine subroutine test_gauss_5(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i ! test the values of nodes and weights i = 5 block real(dp), dimension(i) :: x,w,xref,wref call gauss_legendre(x,w) xref(1)=-0.90617984593866399_dp xref(2)=-0.53846931010568309_dp xref(3)=0.0_dp xref(4)=0.53846931010568309_dp xref(5)=0.90617984593866399_dp wref(1)=0.23692688505618909_dp wref(2)=0.47862867049936647_dp wref(3)=0.56888888888888889_dp wref(4)=0.47862867049936647_dp wref(5)=0.23692688505618909_dp call check(error, all(abs(x-xref) < 2*epsilon(x(1)))) if (allocated(error)) return call check(error, all(abs(w-wref) < 2*epsilon(w(1)))) end block end subroutine subroutine test_gauss_32(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i i = 32 block real(dp), dimension(i) :: x,w,xref,wref call gauss_legendre(x,w) xref(1)=-0.99726386184948156_dp xref(2)=-0.98561151154526834_dp xref(3)=-0.96476225558750643_dp xref(4)=-0.93490607593773969_dp xref(5)=-0.89632115576605212_dp xref(6)=-0.84936761373256997_dp xref(7)=-0.79448379596794241_dp xref(8)=-0.73218211874028968_dp xref(9)=-0.66304426693021520_dp xref(10)=-0.58771575724076233_dp xref(11)=-0.50689990893222939_dp xref(12)=-0.42135127613063535_dp xref(13)=-0.33186860228212765_dp xref(14)=-0.23928736225213707_dp xref(15)=-0.14447196158279649_dp xref(16)=-0.048307665687738316_dp xref(17)=0.048307665687738316_dp xref(18)=0.14447196158279649_dp xref(19)=0.23928736225213707_dp xref(20)=0.33186860228212765_dp xref(21)=0.42135127613063535_dp xref(22)=0.50689990893222939_dp xref(23)=0.58771575724076233_dp xref(24)=0.66304426693021520_dp xref(25)=0.73218211874028968_dp xref(26)=0.79448379596794241_dp xref(27)=0.84936761373256997_dp xref(28)=0.89632115576605212_dp xref(29)=0.93490607593773969_dp xref(30)=0.96476225558750643_dp xref(31)=0.98561151154526834_dp xref(32)=0.99726386184948156_dp wref(1)=0.0070186100094700966_dp wref(2)=0.016274394730905671_dp wref(3)=0.025392065309262059_dp wref(4)=0.034273862913021433_dp wref(5)=0.042835898022226681_dp wref(6)=0.050998059262376176_dp wref(7)=0.058684093478535547_dp wref(8)=0.065822222776361847_dp wref(9)=0.072345794108848506_dp wref(10)=0.078193895787070306_dp wref(11)=0.083311924226946755_dp wref(12)=0.087652093004403811_dp wref(13)=0.091173878695763885_dp wref(14)=0.093844399080804566_dp wref(15)=0.095638720079274859_dp wref(16)=0.096540088514727801_dp wref(17)=0.096540088514727801_dp wref(18)=0.095638720079274859_dp wref(19)=0.093844399080804566_dp wref(20)=0.091173878695763885_dp wref(21)=0.087652093004403811_dp wref(22)=0.083311924226946755_dp wref(23)=0.078193895787070306_dp wref(24)=0.072345794108848506_dp wref(25)=0.065822222776361847_dp wref(26)=0.058684093478535547_dp wref(27)=0.050998059262376176_dp wref(28)=0.042835898022226681_dp wref(29)=0.034273862913021433_dp wref(30)=0.025392065309262059_dp wref(31)=0.016274394730905671_dp wref(32)=0.0070186100094700966_dp call check(error, all(abs(x-xref) < 2*epsilon(x(1)))) if (allocated(error)) return call check(error, all(abs(w-wref) < 2*epsilon(w(1)))) end block end subroutine subroutine test_gauss_64(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i i = 64 block real(dp), dimension(i) :: x,w,xref,wref call gauss_legendre(x,w) xref(1)=-0.99930504173577214_dp xref(2)=-0.99634011677195528_dp xref(3)=-0.99101337147674432_dp xref(4)=-0.98333625388462596_dp xref(5)=-0.97332682778991096_dp xref(6)=-0.96100879965205372_dp xref(7)=-0.94641137485840282_dp xref(8)=-0.92956917213193958_dp xref(9)=-0.91052213707850281_dp xref(10)=-0.88931544599511411_dp xref(11)=-0.86599939815409282_dp xref(12)=-0.84062929625258036_dp xref(13)=-0.81326531512279756_dp xref(14)=-0.78397235894334141_dp xref(15)=-0.75281990726053190_dp xref(16)=-0.71988185017161083_dp xref(17)=-0.68523631305423324_dp xref(18)=-0.64896547125465734_dp xref(19)=-0.61115535517239325_dp xref(20)=-0.57189564620263403_dp xref(21)=-0.53127946401989455_dp xref(22)=-0.48940314570705296_dp xref(23)=-0.44636601725346409_dp xref(24)=-0.40227015796399160_dp xref(25)=-0.35722015833766812_dp xref(26)=-0.31132287199021096_dp xref(27)=-0.26468716220876742_dp xref(28)=-0.21742364374000708_dp xref(29)=-0.16964442042399282_dp xref(30)=-0.12146281929612055_dp xref(31)=-0.072993121787799039_dp xref(32)=-0.024350292663424433_dp xref(33)=0.024350292663424433_dp xref(34)=0.072993121787799039_dp xref(35)=0.12146281929612055_dp xref(36)=0.16964442042399282_dp xref(37)=0.21742364374000708_dp xref(38)=0.26468716220876742_dp xref(39)=0.31132287199021096_dp xref(40)=0.35722015833766812_dp xref(41)=0.40227015796399160_dp xref(42)=0.44636601725346409_dp xref(43)=0.48940314570705296_dp xref(44)=0.53127946401989455_dp xref(45)=0.57189564620263403_dp xref(46)=0.61115535517239325_dp xref(47)=0.64896547125465734_dp xref(48)=0.68523631305423324_dp xref(49)=0.71988185017161083_dp xref(50)=0.75281990726053190_dp xref(51)=0.78397235894334141_dp xref(52)=0.81326531512279756_dp xref(53)=0.84062929625258036_dp xref(54)=0.86599939815409282_dp xref(55)=0.88931544599511411_dp xref(56)=0.91052213707850281_dp xref(57)=0.92956917213193958_dp xref(58)=0.94641137485840282_dp xref(59)=0.96100879965205372_dp xref(60)=0.97332682778991096_dp xref(61)=0.98333625388462596_dp xref(62)=0.99101337147674432_dp xref(63)=0.99634011677195528_dp xref(64)=0.99930504173577214_dp wref(1)=0.0017832807216964329_dp wref(2)=0.0041470332605624676_dp wref(3)=0.0065044579689783629_dp wref(4)=0.0088467598263639477_dp wref(5)=0.011168139460131129_dp wref(6)=0.013463047896718643_dp wref(7)=0.015726030476024719_dp wref(8)=0.017951715775697343_dp wref(9)=0.020134823153530209_dp wref(10)=0.022270173808383254_dp wref(11)=0.024352702568710873_dp wref(12)=0.026377469715054659_dp wref(13)=0.028339672614259483_dp wref(14)=0.030234657072402479_dp wref(15)=0.032057928354851554_dp wref(16)=0.033805161837141609_dp wref(17)=0.035472213256882384_dp wref(18)=0.037055128540240046_dp wref(19)=0.038550153178615629_dp wref(20)=0.039953741132720341_dp wref(21)=0.041262563242623529_dp wref(22)=0.042473515123653589_dp wref(23)=0.043583724529323453_dp wref(24)=0.044590558163756563_dp wref(25)=0.045491627927418144_dp wref(26)=0.046284796581314417_dp wref(27)=0.046968182816210017_dp wref(28)=0.047540165714830309_dp wref(29)=0.047999388596458308_dp wref(30)=0.048344762234802957_dp wref(31)=0.048575467441503427_dp wref(32)=0.048690957009139720_dp wref(33)=0.048690957009139720_dp wref(34)=0.048575467441503427_dp wref(35)=0.048344762234802957_dp wref(36)=0.047999388596458308_dp wref(37)=0.047540165714830309_dp wref(38)=0.046968182816210017_dp wref(39)=0.046284796581314417_dp wref(40)=0.045491627927418144_dp wref(41)=0.044590558163756563_dp wref(42)=0.043583724529323453_dp wref(43)=0.042473515123653589_dp wref(44)=0.041262563242623529_dp wref(45)=0.039953741132720341_dp wref(46)=0.038550153178615629_dp wref(47)=0.037055128540240046_dp wref(48)=0.035472213256882384_dp wref(49)=0.033805161837141609_dp wref(50)=0.032057928354851554_dp wref(51)=0.030234657072402479_dp wref(52)=0.028339672614259483_dp wref(53)=0.026377469715054659_dp wref(54)=0.024352702568710873_dp wref(55)=0.022270173808383254_dp wref(56)=0.020134823153530209_dp wref(57)=0.017951715775697343_dp wref(58)=0.015726030476024719_dp wref(59)=0.013463047896718643_dp wref(60)=0.011168139460131129_dp wref(61)=0.0088467598263639477_dp wref(62)=0.0065044579689783629_dp wref(63)=0.0041470332605624676_dp wref(64)=0.0017832807216964329_dp call check(error, all(abs(x-xref) < 2*epsilon(x(1)))) if (allocated(error)) return call check(error, all(abs(w-wref) < 2*epsilon(w(1)))) end block end subroutine subroutine test_gauss_lobatto_analytic(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i real(dp) :: analytic, numeric ! test an analytic derivative versus an actual integration ! x**2 from -1 to 1 analytic = 2.0_dp/3.0_dp do i=4,6 ! lobatto quadrature is less accurate for low i, so omit checking at i=2,3 block real(dp), dimension(i) :: x,w call gauss_legendre_lobatto(x,w) numeric = sum(x**2 * w) !print *, i, numeric call check(error, abs(numeric-analytic) < 2*epsilon(analytic)) if (allocated(error)) return end block end do end subroutine subroutine test_gauss_lobatto_5(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i ! test the values of nodes and weights i = 5 block real(dp), dimension(i) :: x,w,xref,wref call gauss_legendre_lobatto(x,w) xref(1)=-1.0000000000000000_dp xref(2)=-0.65465367070797714_dp xref(3)=0.0_dp xref(4)=0.65465367070797714_dp xref(5)=1.0000000000000000_dp wref(1)=0.10000000000000000_dp wref(2)=0.54444444444444444_dp wref(3)=0.71111111111111111_dp wref(4)=0.54444444444444444_dp wref(5)=0.10000000000000000_dp call check(error, all(abs(x-xref) < 2*epsilon(x(1)))) if (allocated(error)) return call check(error, all(abs(w-wref) < 2*epsilon(w(1)))) end block end subroutine subroutine test_gauss_lobatto_32(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i i = 32 block real(dp), dimension(i) :: x,w,xref,wref call gauss_legendre_lobatto(x,w) xref(1)=-1.0000000000000000_dp xref(2)=-0.99260893397276136_dp xref(3)=-0.97529469048270923_dp xref(4)=-0.94828483841723238_dp xref(5)=-0.91184993906373190_dp xref(6)=-0.86635247601267552_dp xref(7)=-0.81224473177744234_dp xref(8)=-0.75006449393667480_dp xref(9)=-0.68042975561555082_dp xref(10)=-0.60403258714842113_dp xref(11)=-0.52163226288156529_dp xref(12)=-0.43404771720184694_dp xref(13)=-0.34214940653888149_dp xref(14)=-0.24685065885020530_dp xref(15)=-0.14909859681364749_dp xref(16)=-0.049864725046593252_dp xref(17)=0.049864725046593252_dp xref(18)=0.14909859681364749_dp xref(19)=0.24685065885020530_dp xref(20)=0.34214940653888149_dp xref(21)=0.43404771720184694_dp xref(22)=0.52163226288156529_dp xref(23)=0.60403258714842113_dp xref(24)=0.68042975561555082_dp xref(25)=0.75006449393667480_dp xref(26)=0.81224473177744234_dp xref(27)=0.86635247601267552_dp xref(28)=0.91184993906373190_dp xref(29)=0.94828483841723238_dp xref(30)=0.97529469048270923_dp xref(31)=0.99260893397276136_dp xref(32)=1.0000000000000000_dp wref(1)=0.0020161290322580645_dp wref(2)=0.012398106501373844_dp wref(3)=0.022199552889291965_dp wref(4)=0.031775135410915466_dp wref(5)=0.041034201586062723_dp wref(6)=0.049885271336221207_dp wref(7)=0.058240497248055870_dp wref(8)=0.066016877257154544_dp wref(9)=0.073137139602679033_dp wref(10)=0.079530525692106252_dp wref(11)=0.085133497949668231_dp wref(12)=0.089890372957357833_dp wref(13)=0.093753875546813814_dp wref(14)=0.096685608948002601_dp wref(15)=0.098656436540761777_dp wref(16)=0.099646771501276778_dp wref(17)=0.099646771501276778_dp wref(18)=0.098656436540761777_dp wref(19)=0.096685608948002601_dp wref(20)=0.093753875546813814_dp wref(21)=0.089890372957357833_dp wref(22)=0.085133497949668231_dp wref(23)=0.079530525692106252_dp wref(24)=0.073137139602679033_dp wref(25)=0.066016877257154544_dp wref(26)=0.058240497248055870_dp wref(27)=0.049885271336221207_dp wref(28)=0.041034201586062723_dp wref(29)=0.031775135410915466_dp wref(30)=0.022199552889291965_dp wref(31)=0.012398106501373844_dp wref(32)=0.0020161290322580645_dp call check(error, all(abs(x-xref) < 2*epsilon(x(1)))) if (allocated(error)) return call check(error, all(abs(w-wref) < 2*epsilon(w(1)))) end block end subroutine subroutine test_gauss_lobatto_64(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: i i = 64 block real(dp), dimension(i) :: x,w,xref,wref call gauss_legendre_lobatto(x,w) xref(1)=-1.0000000000000000_dp xref(2)=-0.99817987150216322_dp xref(3)=-0.99390272670305729_dp xref(4)=-0.98719267660274024_dp xref(5)=-0.97806666283139607_dp xref(6)=-0.96654711036909923_dp xref(7)=-0.95266223578866292_dp xref(8)=-0.93644602747563416_dp xref(9)=-0.91793817351028163_dp xref(10)=-0.89718396784585004_dp xref(11)=-0.87423420065762749_dp xref(12)=-0.84914503454299099_dp xref(13)=-0.82197786730751705_dp xref(14)=-0.79279918182620814_dp xref(15)=-0.76168038340811997_dp xref(16)=-0.72869762508883694_dp xref(17)=-0.69393162129070484_dp xref(18)=-0.65746745031297650_dp xref(19)=-0.61939434613843155_dp xref(20)=-0.57980548006771842_dp xref(21)=-0.53879773271680044_dp xref(22)=-0.49647145693605775_dp xref(23)=-0.45293023223158118_dp xref(24)=-0.40828061128985404_dp xref(25)=-0.36263185922626182_dp xref(26)=-0.31609568619562581_dp xref(27)=-0.26878597401917000_dp xref(28)=-0.22081849749695350_dp xref(29)=-0.17231064108779297_dp xref(30)=-0.12338111165002799_dp xref(31)=-0.074149647946115919_dp xref(32)=-0.024736727621958728_dp xref(33)=0.024736727621958728_dp xref(34)=0.074149647946115919_dp xref(35)=0.12338111165002799_dp xref(36)=0.17231064108779297_dp xref(37)=0.22081849749695350_dp xref(38)=0.26878597401917000_dp xref(39)=0.31609568619562581_dp xref(40)=0.36263185922626182_dp xref(41)=0.40828061128985404_dp xref(42)=0.45293023223158118_dp xref(43)=0.49647145693605775_dp xref(44)=0.53879773271680044_dp xref(45)=0.57980548006771842_dp xref(46)=0.61939434613843155_dp xref(47)=0.65746745031297650_dp xref(48)=0.69393162129070484_dp xref(49)=0.72869762508883694_dp xref(50)=0.76168038340811997_dp xref(51)=0.79279918182620814_dp xref(52)=0.82197786730751705_dp xref(53)=0.84914503454299099_dp xref(54)=0.87423420065762749_dp xref(55)=0.89718396784585004_dp xref(56)=0.91793817351028163_dp xref(57)=0.93644602747563416_dp xref(58)=0.95266223578866292_dp xref(59)=0.96654711036909923_dp xref(60)=0.97806666283139607_dp xref(61)=0.98719267660274024_dp xref(62)=0.99390272670305729_dp xref(63)=0.99817987150216322_dp xref(64)=1.0000000000000000_dp wref(1)=0.00049603174603174603_dp wref(2)=0.0030560082449124904_dp wref(3)=0.0054960162038171569_dp wref(4)=0.0079212897900466340_dp wref(5)=0.010327002366815328_dp wref(6)=0.012707399197454735_dp wref(7)=0.015056683987961443_dp wref(8)=0.017369116384542182_dp wref(9)=0.019639040723241718_dp wref(10)=0.021860903511518060_dp wref(11)=0.024029268144023827_dp wref(12)=0.026138828614338438_dp wref(13)=0.028184422665848517_dp wref(14)=0.030161044499089451_dp wref(15)=0.032063857057727025_dp wref(16)=0.033888203884125398_dp wref(17)=0.035629620524489486_dp wref(18)=0.037283845459801173_dp wref(19)=0.038846830537807737_dp wref(20)=0.040314750881560237_dp wref(21)=0.041684014250801952_dp wref(22)=0.042951269833601819_dp wref(23)=0.044113416446892471_dp wref(24)=0.045167610125947702_dp wref(25)=0.046111271084289059_dp wref(26)=0.046942090027028316_dp wref(27)=0.047658033802220637_dp wref(28)=0.048257350376414549_dp wref(29)=0.048738573122233185_dp wref(30)=0.049100524407501308_dp wref(31)=0.049342318477139574_dp wref(32)=0.049463363620776646_dp wref(33)=0.049463363620776646_dp wref(34)=0.049342318477139574_dp wref(35)=0.049100524407501308_dp wref(36)=0.048738573122233185_dp wref(37)=0.048257350376414549_dp wref(38)=0.047658033802220637_dp wref(39)=0.046942090027028316_dp wref(40)=0.046111271084289059_dp wref(41)=0.045167610125947702_dp wref(42)=0.044113416446892471_dp wref(43)=0.042951269833601819_dp wref(44)=0.041684014250801952_dp wref(45)=0.040314750881560237_dp wref(46)=0.038846830537807737_dp wref(47)=0.037283845459801173_dp wref(48)=0.035629620524489486_dp wref(49)=0.033888203884125398_dp wref(50)=0.032063857057727025_dp wref(51)=0.030161044499089451_dp wref(52)=0.028184422665848517_dp wref(53)=0.026138828614338438_dp wref(54)=0.024029268144023827_dp wref(55)=0.021860903511518060_dp wref(56)=0.019639040723241718_dp wref(57)=0.017369116384542182_dp wref(58)=0.015056683987961443_dp wref(59)=0.012707399197454735_dp wref(60)=0.010327002366815328_dp wref(61)=0.0079212897900466340_dp wref(62)=0.0054960162038171569_dp wref(63)=0.0030560082449124904_dp wref(64)=0.00049603174603174603_dp call check(error, all(abs(x-xref) < 2*epsilon(x(1)))) if (allocated(error)) return call check(error, all(abs(w-wref) < 2*epsilon(w(1)))) end block end subroutine end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_gauss, only : collect_gauss implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("gauss", collect_gauss) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/quadrature/test_trapz.fypp0000664000175000017500000002044715135654166024430 0ustar alastairalastair#:include "common.fypp" module test_trapz use stdlib_kinds, only: sp, dp, xdp, qp use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_quadrature, only: trapz, trapz_weights implicit none contains !> Collect all exported unit tests subroutine collect_trapz(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("trapz_sp", test_trapz_sp), & new_unittest("trapz_dp", test_trapz_dp), & new_unittest("trapz_qp", test_trapz_qp), & new_unittest("trapz_weights_sp", test_trapz_weights_sp), & new_unittest("trapz_weights_dp", test_trapz_weights_dp), & new_unittest("trapz_weights_qp", test_trapz_weights_qp), & new_unittest("trapz_zero_sp", test_trapz_zero_sp), & new_unittest("trapz_zero_dp", test_trapz_zero_dp), & new_unittest("trapz_zero_qp", test_trapz_zero_qp) & ] end subroutine collect_trapz subroutine test_trapz_sp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 17 real(sp), dimension(n) :: y real(sp), dimension(n) :: x real(sp) :: val real(sp) :: ans integer :: i y = [(real(i-1, sp), i = 1, n)] val = trapz(y, 1.0_sp) ans = 128.0_sp call check(error, abs(val - ans) < epsilon(ans)) val = trapz(y, 0.5_sp) ans = 64.0_sp call check(error, abs(val - ans) < epsilon(ans)) x = [((i-1)*4.0_sp/real(n-1, sp), i = 1, n)] val = trapz(y, x) ans = 32.0_sp call check(error, abs(val - ans) < epsilon(ans)) x = y**2 val = trapz(y, x) ans = 2728.0_sp call check(error, abs(val - ans) < epsilon(ans)) end subroutine test_trapz_sp subroutine test_trapz_dp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 17 real(dp), dimension(n) :: y real(dp), dimension(n) :: x real(dp) :: val real(dp) :: ans integer :: i y = [(real(i-1, dp), i = 1, n)] val = trapz(y, 1.0_dp) ans = 128.0_dp call check(error, abs(val - ans) < epsilon(ans)) val = trapz(y, 0.5_dp) ans = 64.0_dp call check(error, abs(val - ans) < epsilon(ans)) x = [((i-1)*4.0_dp/real(n-1, dp), i = 1, n)] val = trapz(y, x) ans = 32.0_dp call check(error, abs(val - ans) < epsilon(ans)) x = y**2 val = trapz(y, x) ans = 2728.0_dp call check(error, abs(val - ans) < epsilon(ans)) end subroutine test_trapz_dp subroutine test_trapz_qp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP integer, parameter :: n = 17 real(qp), dimension(n) :: y real(qp), dimension(n) :: x real(qp) :: val real(qp) :: ans integer :: i y = [(real(i-1, qp), i = 1, n)] val = trapz(y, 1.0_qp) ans = 128.0_qp call check(error, abs(val - ans) < epsilon(ans)) val = trapz(y, 0.5_qp) ans = 64.0_qp call check(error, abs(val - ans) < epsilon(ans)) x = [((i-1)*4.0_qp/real(n-1, qp), i = 1, n)] val = trapz(y, x) ans = 32.0_qp call check(error, abs(val - ans) < epsilon(ans)) x = y**2 val = trapz(y, x) ans = 2728.0_qp call check(error, abs(val - ans) < epsilon(ans)) #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_trapz_qp subroutine test_trapz_weights_sp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 17 real(sp), dimension(n) :: y real(sp), dimension(n) :: x real(sp), dimension(n) :: w integer :: i real(sp) :: val real(sp) :: ans y = [(real(i-1, sp), i = 1, n)] x = y w = trapz_weights(x) val = dot_product(w, y) ans = trapz(y, x) call check(error, abs(val - ans) < epsilon(ans)) x = y**2 w = trapz_weights(x) val = dot_product(w, y) ans = trapz(y, x) call check(error, abs(val - ans) < epsilon(ans)) end subroutine test_trapz_weights_sp subroutine test_trapz_weights_dp(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 17 real(dp), dimension(n) :: y real(dp), dimension(n) :: x real(dp), dimension(n) :: w integer :: i real(dp) :: val real(dp) :: ans y = [(real(i-1, dp), i = 1, n)] x = y w = trapz_weights(x) val = dot_product(w, y) ans = trapz(y, x) call check(error, abs(val - ans) < epsilon(ans)) x = y**2 w = trapz_weights(x) val = dot_product(w, y) ans = trapz(y, x) call check(error, abs(val - ans) < epsilon(ans)) end subroutine test_trapz_weights_dp subroutine test_trapz_weights_qp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP integer, parameter :: n = 17 real(qp), dimension(n) :: y real(qp), dimension(n) :: x real(qp), dimension(n) :: w integer :: i real(qp) :: val real(qp) :: ans y = [(real(i-1, qp), i = 1, n)] x = y w = trapz_weights(x) val = dot_product(w, y) ans = trapz(y, x) call check(error, abs(val - ans) < epsilon(ans)) x = y**2 w = trapz_weights(x) val = dot_product(w, y) ans = trapz(y, x) call check(error, abs(val - ans) < epsilon(ans)) #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_trapz_weights_qp subroutine test_trapz_zero_sp(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(sp), dimension(0) :: a call check(error, abs(trapz(a, 1.0_sp)) < epsilon(0.0_sp)) call check(error, abs(trapz([1.0_sp], 1.0_sp)) < epsilon(0.0_sp)) call check(error, abs(trapz(a, a)) < epsilon(0.0_sp)) call check(error, abs(trapz([1.0_sp], [1.0_sp])) < epsilon(0.0_sp)) end subroutine test_trapz_zero_sp subroutine test_trapz_zero_dp(error) !> Error handling type(error_type), allocatable, intent(out) :: error real(dp), dimension(0) :: a call check(error, abs(trapz(a, 1.0_dp)) < epsilon(0.0_dp)) call check(error, abs(trapz([1.0_dp], 1.0_dp)) < epsilon(0.0_dp)) call check(error, abs(trapz(a, a)) < epsilon(0.0_dp)) call check(error, abs(trapz([1.0_dp], [1.0_dp])) < epsilon(0.0_dp)) end subroutine test_trapz_zero_dp subroutine test_trapz_zero_qp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP real(qp), dimension(0) :: a call check(error, abs(trapz(a, 1.0_qp)) < epsilon(0.0_qp)) call check(error, abs(trapz([1.0_qp], 1.0_qp)) < epsilon(0.0_qp)) call check(error, abs(trapz(a, a)) < epsilon(0.0_qp)) call check(error, abs(trapz([1.0_qp], [1.0_qp])) < epsilon(0.0_qp)) #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_trapz_zero_qp end module test_trapz program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_trapz, only : collect_trapz implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("trapz", collect_trapz) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/quadrature/CMakeLists.txt0000664000175000017500000000023015135654166024055 0ustar alastairalastairset( fppFiles "test_simps.fypp" "test_trapz.fypp" ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) ADDTEST(trapz) ADDTEST(simps) ADDTEST(gauss) fortran-lang-stdlib-0ede301/test/quadrature/test_simps.fypp0000664000175000017500000001570115135654166024420 0ustar alastairalastair#:include "common.fypp" module test_simps use stdlib_kinds, only: sp, dp, xdp, qp use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_quadrature, only: simps, simps_weights implicit none #:for k1, t1 in REAL_KINDS_TYPES ${t1}$, parameter :: tol_${k1}$ = 1000 * epsilon(1.0_${k1}$) #:endfor contains !> Collect all exported unit tests subroutine collect_simps(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & #:for k1, t1 in REAL_KINDS_TYPES[0:1] # set the first test independently to initialize the table new_unittest("simps_${k1}$", test_simps_sp) & #:endfor #:for k1, t1 in REAL_KINDS_TYPES[1:] , new_unittest("simps_${k1}$", test_simps_${k1}$) & #:endfor #:for k1, t1 in REAL_KINDS_TYPES , new_unittest("simps_weights_${k1}$", test_simps_weights_${k1}$) & #:endfor #:for k1, t1 in REAL_KINDS_TYPES , new_unittest("simps_zero_${k1}$", test_simps_zero_${k1}$) & #:endfor #:for k1, t1 in REAL_KINDS_TYPES , new_unittest("simps_even_${k1}$", test_simps_even_${k1}$) & #:endfor #:for k1, t1 in REAL_KINDS_TYPES , new_unittest("simps_weights_even_${k1}$", test_simps_weights_even_${k1}$) & #:endfor #:for k1, t1 in REAL_KINDS_TYPES , new_unittest("simps_six_${k1}$", test_simps_six_${k1}$) & #:endfor ] end subroutine collect_simps #:for k1, t1 in REAL_KINDS_TYPES subroutine test_simps_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 13 ${t1}$ :: y(n) ${t1}$ :: x(n) ${t1}$ :: val ${t1}$ :: ans integer :: i y = [(real(i-1, sp)**2, i = 1, n)] val = simps(y, 1.0_${k1}$) ans = 576.0_${k1}$ call check(error, val, ans, thr=tol_${k1}$) if (allocated(error)) return val = simps(y, 0.5_${k1}$) ans = 288.0_${k1}$ call check(error, val, ans, thr=tol_${k1}$) if (allocated(error)) return x = [(0.25_${k1}$*(i-1), i = 1, n)] val = simps(y, x) ans = 144.0_${k1}$ call check(error, val, ans, thr=tol_${k1}$) end subroutine test_simps_${k1}$ subroutine test_simps_weights_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 17 ${t1}$ :: y(n) ${t1}$ :: x(n) ${t1}$ :: w(n) integer :: i ${t1}$ :: val ${t1}$ :: ans y = [(real(i-1, sp), i = 1, n)] x = y w = simps_weights(x) val = sum(w*y) ans = simps(y, x) call check(error, val, ans, thr=tol_${k1}$) end subroutine test_simps_weights_${k1}$ subroutine test_simps_zero_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error ${t1}$, dimension(0) :: a call check(error, abs(simps(a, 1.0_${k1}$)) < epsilon(0.0_${k1}$)) if (allocated(error)) return call check(error, abs(simps([1.0_${k1}$], 1.0_${k1}$)) < epsilon(0.0_${k1}$)) if (allocated(error)) return call check(error, abs(simps(a, a)) < epsilon(0.0_${k1}$)) if (allocated(error)) return call check(error, abs(simps([1.0_${k1}$], [1.0_${k1}$])) < epsilon(0.0_${k1}$)) end subroutine test_simps_zero_${k1}$ subroutine test_simps_even_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 11 ${t1}$ :: y(n) ${t1}$ :: x(n) ${t1}$ :: val ${t1}$ :: ans integer :: i integer :: even y = [(3.0_${k1}$*real(i-1, sp)**2, i = 1, n)] do even = -1, 1 val = simps(y, 1.0_${k1}$) ans = 1000.0_${k1}$ call check(error, val, ans, thr=tol_${k1}$) if (allocated(error)) return val = simps(y, 0.5_${k1}$) ans = 500.0_${k1}$ call check(error, val, ans, thr=tol_${k1}$) if (allocated(error)) return x = [(0.25_${k1}$*(i-1), i = 1, n)] val = simps(y, x) ans = 250.0_${k1}$ call check(error, val, ans, thr=tol_${k1}$) if (allocated(error)) return end do end subroutine test_simps_even_${k1}$ subroutine test_simps_weights_even_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 16 ${t1}$ :: y(n) ${t1}$ :: x(n) ${t1}$ :: w(n) integer :: i ${t1}$ :: val ${t1}$ :: ans integer :: even y = [(real(i-1, sp), i = 1, n)] x = y do even = -1, 1 w = simps_weights(x) val = sum(w*y) ans = simps(y, x) call check(error, val, ans, thr=tol_${k1}$) if (allocated(error)) return end do end subroutine test_simps_weights_even_${k1}$ subroutine test_simps_six_${k1}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer, parameter :: n = 6 ${t1}$ :: y(n) ${t1}$ :: x(n) ${t1}$ :: val ${t1}$ :: ans integer :: i integer :: even y = [(3.0_${k1}$*real(i-1, sp)**2, i = 1, n)] do even = -1, 1 val = simps(y, 1.0_${k1}$) ans = 125.0_${k1}$ call check(error, val, ans, thr=tol_${k1}$) if (allocated(error)) return val = simps(y, 0.5_${k1}$) ans = 62.5_${k1}$ call check(error, val, ans, thr=tol_${k1}$) if (allocated(error)) return x = [(0.25_${k1}$*(i-1), i = 1, n)] val = simps(y, x) ans = 31.25_${k1}$ call check(error, val, ans, thr=tol_${k1}$) if (allocated(error)) return end do end subroutine test_simps_six_${k1}$ #:endfor end module program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_simps, only : collect_simps implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("simps", collect_simps) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/optval/0000775000175000017500000000000015135654166020452 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/optval/CMakeLists.txt0000664000175000017500000000051115135654166023207 0ustar alastairalastairset( fppFiles "test_optval.fypp" ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) ADDTEST(optval) # prevent false positive (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95446) if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU) set_source_files_properties("test_optval.f90" PROPERTIES COMPILE_FLAGS "-Wno-error=pedantic") endif() fortran-lang-stdlib-0ede301/test/optval/test_optval.fypp0000664000175000017500000003655415135654166023733 0ustar alastairalastair#:include "common.fypp" module test_optval use, intrinsic :: iso_fortran_env, only: & sp => real32, dp => real64, qp => real128, & int8, int16, int32, int64 use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_optval, only: optval implicit none contains !> Collect all exported unit tests subroutine collect_optval(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("rsp", test_optval_rsp), & new_unittest("rdp", test_optval_rdp), & new_unittest("rqp", test_optval_rqp), & new_unittest("csp", test_optval_csp), & new_unittest("cdp", test_optval_cdp), & new_unittest("cqp", test_optval_cqp), & new_unittest("iint8", test_optval_iint8), & new_unittest("iint16", test_optval_iint16), & new_unittest("iint32", test_optval_iint32), & new_unittest("iint64", test_optval_iint64), & new_unittest("logical", test_optval_logical), & new_unittest("character", test_optval_character), & new_unittest("rsp_arr", test_optval_rsp_arr), & new_unittest("rdp_arr", test_optval_rdp_arr), & new_unittest("rqp_arr", test_optval_rqp_arr), & new_unittest("csp_arr", test_optval_csp_arr), & new_unittest("cdp_arr", test_optval_cdp_arr), & new_unittest("cqp_arr", test_optval_cqp_arr), & new_unittest("iint8_arr", test_optval_iint8_arr), & new_unittest("iint16_arr", test_optval_iint16_arr), & new_unittest("iint32_arr", test_optval_iint32_arr), & new_unittest("iint64_arr", test_optval_iint64_arr) & ] end subroutine collect_optval subroutine test_optval_rsp(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, foo_sp(1.0_sp) == 1.0_sp) if (allocated(error)) return call check(error, foo_sp() == 2.0_sp) end subroutine test_optval_rsp function foo_sp(x) result(z) real(sp), intent(in), optional :: x real(sp) :: z z = optval(x, 2.0_sp) endfunction foo_sp subroutine test_optval_rdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, foo_dp(1.0_dp) == 1.0_dp) if (allocated(error)) return call check(error, foo_dp() == 2.0_dp) end subroutine test_optval_rdp function foo_dp(x) result(z) real(dp), intent(in), optional :: x real(dp) :: z z = optval(x, 2.0_dp) endfunction foo_dp subroutine test_optval_rqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP call check(error, foo_qp(1.0_qp) == 1.0_qp) if (allocated(error)) return call check(error, foo_qp() == 2.0_qp) #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_optval_rqp #:if WITH_QP function foo_qp(x) result(z) real(qp), intent(in), optional :: x real(qp) :: z z = optval(x, 2.0_qp) endfunction foo_qp #:endif subroutine test_optval_csp(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(sp) :: z1 z1 = cmplx(1.0_sp, 2.0_sp, kind=sp) call check(error, foo_csp(z1) == z1) if (allocated(error)) return call check(error, foo_csp() == z1) end subroutine test_optval_csp function foo_csp(x) result(z) complex(sp), intent(in), optional :: x complex(sp) :: z z = optval(x, cmplx(1.0_sp, 2.0_sp, kind=sp)) endfunction foo_csp subroutine test_optval_cdp(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(dp) :: z1 z1 = cmplx(1.0_dp, 2.0_dp,kind=dp) call check(error, foo_cdp(z1) == z1) if (allocated(error)) return call check(error, foo_cdp() == z1) end subroutine test_optval_cdp function foo_cdp(x) result(z) complex(dp), intent(in), optional :: x complex(dp) :: z z = optval(x, cmplx(1.0_dp, 2.0_dp, kind=dp)) endfunction foo_cdp subroutine test_optval_cqp(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP complex(qp) :: z1 z1 = cmplx(1.0_qp, 2.0_qp, kind=qp) call check(error, foo_cqp(z1) == z1) if (allocated(error)) return call check(error, foo_cqp() == z1) #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_optval_cqp #:if WITH_QP function foo_cqp(x) result(z) complex(qp), intent(in), optional :: x complex(qp) :: z z = optval(x, cmplx(1.0_qp, 2.0_qp, kind=qp)) endfunction foo_cqp #:endif subroutine test_optval_iint8(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, foo_int8(1_int8) == 1_int8) if (allocated(error)) return call check(error, foo_int8() == 2_int8) end subroutine test_optval_iint8 function foo_int8(x) result(z) integer(int8), intent(in), optional :: x integer(int8) :: z z = optval(x, 2_int8) endfunction foo_int8 subroutine test_optval_iint16(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, foo_int16(1_int16) == 1_int16) if (allocated(error)) return call check(error, foo_int16() == 2_int16) end subroutine test_optval_iint16 function foo_int16(x) result(z) integer(int16), intent(in), optional :: x integer(int16) :: z z = optval(x, 2_int16) endfunction foo_int16 subroutine test_optval_iint32(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, foo_int32(1_int32) == 1_int32) if (allocated(error)) return call check(error, foo_int32() == 2_int32) end subroutine test_optval_iint32 function foo_int32(x) result(z) integer(int32), intent(in), optional :: x integer(int32) :: z z = optval(x, 2_int32) endfunction foo_int32 subroutine test_optval_iint64(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, foo_int64(1_int64) == 1_int64) if (allocated(error)) return call check(error, foo_int64() == 2_int64) end subroutine test_optval_iint64 function foo_int64(x) result(z) integer(int64), intent(in), optional :: x integer(int64) :: z z = optval(x, 2_int64) endfunction foo_int64 subroutine test_optval_logical(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, foo_logical(.true.)) if (allocated(error)) return call check(error, .not.foo_logical()) end subroutine test_optval_logical function foo_logical(x) result(z) logical, intent(in), optional :: x logical :: z z = optval(x, .false.) endfunction foo_logical subroutine test_optval_character(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, foo_character("x") == "x") if (allocated(error)) return call check(error, foo_character() == "y") end subroutine test_optval_character function foo_character(x) result(z) character(len=*), intent(in), optional :: x character(len=:), allocatable :: z z = optval(x, "y") endfunction foo_character subroutine test_optval_rsp_arr(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, all(foo_sp_arr([1.0_sp, -1.0_sp]) == [1.0_sp, -1.0_sp])) if (allocated(error)) return call check(error, all(foo_sp_arr() == [2.0_sp, -2.0_sp])) end subroutine test_optval_rsp_arr function foo_sp_arr(x) result(z) real(sp), dimension(2), intent(in), optional :: x real(sp), dimension(2) :: z z = optval(x, [2.0_sp, -2.0_sp]) end function foo_sp_arr subroutine test_optval_rdp_arr(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, all(foo_dp_arr([1.0_dp, -1.0_dp]) == [1.0_dp, -1.0_dp])) if (allocated(error)) return call check(error, all(foo_dp_arr() == [2.0_dp, -2.0_dp])) end subroutine test_optval_rdp_arr function foo_dp_arr(x) result(z) real(dp), dimension(2), intent(in), optional :: x real(dp), dimension(2) :: z z = optval(x, [2.0_dp, -2.0_dp]) end function foo_dp_arr subroutine test_optval_rqp_arr(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP call check(error, all(foo_qp_arr([1.0_qp, -1.0_qp]) == [1.0_qp, -1.0_qp])) if (allocated(error)) return call check(error, all(foo_qp_arr() == [2.0_qp, -2.0_qp])) #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_optval_rqp_arr #:if WITH_QP function foo_qp_arr(x) result(z) real(qp), dimension(2), intent(in), optional :: x real(qp), dimension(2) :: z z = optval(x, [2.0_qp, -2.0_qp]) end function foo_qp_arr #:endif subroutine test_optval_csp_arr(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(sp), dimension(2) :: z1, z2 z1 = cmplx(1.0_sp, 2.0_sp, kind=sp)*[1.0_sp, -1.0_sp] z2 = cmplx(2.0_sp, 2.0_sp, kind=sp)*[1.0_sp, -1.0_sp] call check(error, all(foo_csp_arr(z1) == z1)) if (allocated(error)) return call check(error, all(foo_csp_arr() == z2)) end subroutine test_optval_csp_arr function foo_csp_arr(x) result(z) complex(sp), dimension(2), intent(in), optional :: x complex(sp), dimension(2) :: z z = optval(x, cmplx(2.0_sp, 2.0_sp, kind=sp)*[1.0_sp, -1.0_sp]) end function foo_csp_arr subroutine test_optval_cdp_arr(error) !> Error handling type(error_type), allocatable, intent(out) :: error complex(dp), dimension(2) :: z1, z2 z1 = cmplx(1.0_dp, 2.0_dp, kind=dp)*[1.0_dp, -1.0_dp] z2 = cmplx(2.0_dp, 2.0_dp, kind=dp)*[1.0_dp, -1.0_dp] call check(error, all(foo_cdp_arr(z1) == z1)) if (allocated(error)) return call check(error, all(foo_cdp_arr() == z2)) end subroutine test_optval_cdp_arr function foo_cdp_arr(x) result(z) complex(dp), dimension(2), intent(in), optional :: x complex(dp), dimension(2) :: z z = optval(x, cmplx(2.0_dp, 2.0_dp, kind=dp)*[1.0_dp, -1.0_dp]) end function foo_cdp_arr subroutine test_optval_cqp_arr(error) !> Error handling type(error_type), allocatable, intent(out) :: error #:if WITH_QP complex(qp), dimension(2) :: z1, z2 z1 = cmplx(1.0_qp, 2.0_qp, kind=qp)*[1.0_qp, -1.0_qp] z2 = cmplx(2.0_qp, 2.0_qp, kind=qp)*[1.0_qp, -1.0_qp] call check(error, all(foo_cqp_arr(z1) == z1)) if (allocated(error)) return call check(error, all(foo_cqp_arr() == z2)) #:else call skip_test(error, "Quadruple precision is not enabled") #:endif end subroutine test_optval_cqp_arr #:if WITH_QP function foo_cqp_arr(x) result(z) complex(qp), dimension(2), intent(in), optional :: x complex(qp), dimension(2) :: z z = optval(x, cmplx(2.0_qp, 2.0_qp, kind=qp)*[1.0_qp, -1.0_qp]) end function foo_cqp_arr #:endif subroutine test_optval_iint8_arr(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, all(foo_int8_arr([1_int8, -1_int8]) == [1_int8, -1_int8])) if (allocated(error)) return call check(error, all(foo_int8_arr() == [2_int8, -2_int8])) end subroutine test_optval_iint8_arr function foo_int8_arr(x) result(z) integer(int8), dimension(2), intent(in), optional :: x integer(int8), dimension(2) :: z z = optval(x, [2_int8, -2_int8]) end function foo_int8_arr subroutine test_optval_iint16_arr(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, all(foo_int16_arr([1_int16, -1_int16]) == [1_int16, -1_int16])) if (allocated(error)) return call check(error, all(foo_int16_arr() == [2_int16, -2_int16])) end subroutine test_optval_iint16_arr function foo_int16_arr(x) result(z) integer(int16), dimension(2), intent(in), optional :: x integer(int16), dimension(2) :: z z = optval(x, [2_int16, -2_int16]) end function foo_int16_arr subroutine test_optval_iint32_arr(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, all(foo_int32_arr([1_int32, -1_int32]) == [1_int32, -1_int32])) if (allocated(error)) return call check(error, all(foo_int32_arr() == [2_int32, -2_int32])) end subroutine test_optval_iint32_arr function foo_int32_arr(x) result(z) integer(int32), dimension(2), intent(in), optional :: x integer(int32), dimension(2) :: z z = optval(x, [2_int32, -2_int32]) end function foo_int32_arr subroutine test_optval_iint64_arr(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, all(foo_int64_arr([1_int64, -1_int64]) == [1_int64, -1_int64])) if (allocated(error)) return call check(error, all(foo_int64_arr() == [2_int64, -2_int64])) end subroutine test_optval_iint64_arr function foo_int64_arr(x) result(z) integer(int64), dimension(2), intent(in), optional :: x integer(int64), dimension(2) :: z z = optval(x, [2_int64, -2_int64]) end function foo_int64_arr subroutine test_optval_logical_arr(error) !> Error handling type(error_type), allocatable, intent(out) :: error call check(error, all(foo_logical_arr())) if (allocated(error)) return call check(error, all(.not.foo_logical_arr())) end subroutine test_optval_logical_arr function foo_logical_arr(x) result(z) logical, dimension(2), intent(in), optional :: x logical, dimension(2) :: z z = optval(x, [.false., .false.]) end function foo_logical_arr end module test_optval program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_optval, only : collect_optval implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("optval", collect_optval) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/system/0000775000175000017500000000000015135654166020471 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/system/test_path.f900000664000175000017500000001310315135654166023002 0ustar alastairalastairmodule test_path use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_system, only: join_path, operator(/), split_path, OS_TYPE, OS_WINDOWS implicit none contains !> Collect all exported unit tests subroutine collect_suite(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest('test_join_path', test_join_path), & new_unittest('test_join_path_operator', test_join_path_op), & new_unittest('test_split_path', test_split_path) & ] end subroutine collect_suite subroutine checkpath(error, funcname, expected, got) type(error_type), allocatable, intent(out) :: error character(len=*), intent(in) :: funcname character(len=*), intent(in) :: expected character(len=:), allocatable :: got character(len=:), allocatable :: message message = "'"//funcname//"'"//" error: Expected '"// expected // "' but got '" // got // "'" call check(error, expected == got, message) end subroutine checkpath subroutine test_join_path(error) type(error_type), allocatable, intent(out) :: error character(len=:), allocatable :: path character(len=20) :: paths(5) if (OS_TYPE() == OS_WINDOWS) then path = join_path('C:\Users', 'Alice') call checkpath(error, 'join_path', 'C:\Users\Alice', path) if (allocated(error)) return paths = [character(20) :: 'C:','Users','Bob','Pictures','2025'] path = join_path(paths) call checkpath(error, 'join_path', 'C:\Users\Bob\Pictures\2025', path) if (allocated(error)) return path = join_path('"C:\Users\John Doe"', 'Pictures\2025') ! path with spaces call checkpath(error, 'join_path', '"C:\Users\John Doe"\Pictures\2025', path) if (allocated(error)) return else path = join_path('/home', 'Alice') call checkpath(error, 'join_path', '/home/Alice', path) if (allocated(error)) return paths = [character(20) :: '','home','Bob','Pictures','2025'] path = join_path(paths) call checkpath(error, 'join_path', '/home/Bob/Pictures/2025', path) if (allocated(error)) return end if end subroutine test_join_path !> Test the operator subroutine test_join_path_op(error) type(error_type), allocatable, intent(out) :: error character(len=:), allocatable :: path if (OS_TYPE() == OS_WINDOWS) then path = 'C:'/'Users'/'Alice'/'Desktop' call checkpath(error, 'join_path operator', 'C:\Users\Alice\Desktop', path) if (allocated(error)) return else path = ''/'home'/'Alice'/'.config' call checkpath(error, 'join_path operator', '/home/Alice/.config', path) if (allocated(error)) return end if end subroutine test_join_path_op subroutine test_split_path(error) type(error_type), allocatable, intent(out) :: error character(len=:), allocatable :: head, tail call split_path('', head, tail) call checkpath(error, 'split_path-head', '.', head) if (allocated(error)) return call checkpath(error, 'split_path-tail', '', tail) if (allocated(error)) return if (OS_TYPE() == OS_WINDOWS) then call split_path('\\\\', head, tail) call checkpath(error, 'split_path-head', '\', head) if (allocated(error)) return call checkpath(error, 'split_path-tail', '', tail) if (allocated(error)) return call split_path('C:\', head, tail) call checkpath(error, 'split_path-head', 'C:\', head) if (allocated(error)) return call checkpath(error, 'split_path-tail', '', tail) if (allocated(error)) return call split_path('C:\Users\Alice\\\\\', head, tail) call checkpath(error, 'split_path-head', 'C:\Users', head) if (allocated(error)) return call checkpath(error, 'split_path-tail', 'Alice', tail) if (allocated(error)) return else call split_path('/////', head, tail) call checkpath(error, 'split_path-head', '/', head) if (allocated(error)) return call checkpath(error, 'split_path-tail', '', tail) if (allocated(error)) return call split_path('/home/Alice/foo/bar.f90///', head, tail) call checkpath(error, 'split_path-head', '/home/Alice/foo', head) if (allocated(error)) return call checkpath(error, 'split_path-tail', 'bar.f90', tail) if (allocated(error)) return end if end subroutine test_split_path end module test_path program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_path, only : collect_suite implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("path", collect_suite) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/system/CMakeLists.txt0000664000175000017500000000012115135654166023223 0ustar alastairalastairADDTEST(filesystem) ADDTEST(os) ADDTEST(sleep) ADDTEST(subprocess) ADDTEST(path) fortran-lang-stdlib-0ede301/test/system/test_os.f900000664000175000017500000000605015135654166022472 0ustar alastairalastairmodule test_os use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_system, only: get_runtime_os, OS_WINDOWS, OS_UNKNOWN, OS_TYPE, is_windows, null_device implicit none contains !> Collect all exported unit tests subroutine collect_suite(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest('test_get_runtime_os', test_get_runtime_os), & new_unittest('test_is_windows', test_is_windows), & new_unittest('test_null_device', test_null_device) & ] end subroutine collect_suite subroutine test_get_runtime_os(error) type(error_type), allocatable, intent(out) :: error integer :: os !> Get current OS os = get_runtime_os() call check(error, os /= OS_UNKNOWN, "running on an unknown/unsupported OS") end subroutine test_get_runtime_os !> If running on Windows (_WIN32 macro is defined), test that the appropriate OS flag is returned subroutine test_is_windows(error) type(error_type), allocatable, intent(out) :: error integer :: os_cached, os_runtime call check(error, OS_TYPE()==OS_WINDOWS .eqv. is_windows(), & "Cached OS type does not match _WIN32 macro presence") end subroutine test_is_windows !> Test that the null_device is valid by writing something to it subroutine test_null_device(error) type(error_type), allocatable, intent(out) :: error integer :: unit, ios character(len=512) :: iomsg ! Try opening the null device for writing open(newunit=unit, file=null_device(), status='old', action='write', iostat=ios, iomsg=iomsg) call check(error, ios==0, 'Cannot open null_device unit: '//trim(iomsg)) if (allocated(error)) return write(unit, *, iostat=ios, iomsg=iomsg) 'Hello, World!' call check(error, ios==0, 'Cannot write to null_device unit: '//trim(iomsg)) if (allocated(error)) return close(unit, iostat=ios, iomsg=iomsg) call check(error, ios==0, 'Cannot close null_device unit: '//trim(iomsg)) if (allocated(error)) return end subroutine test_null_device end module test_os program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_os, only : collect_suite implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("os", collect_suite) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/system/test_sleep.f900000664000175000017500000000331415135654166023161 0ustar alastairalastairmodule test_sleep use, intrinsic :: iso_fortran_env, only : int64, real64 use stdlib_system, only : sleep use testdrive, only: new_unittest, unittest_type, error_type, check implicit none private public :: collect_sleep integer, parameter :: millisec = 100 contains !> Collect all exported unit tests subroutine collect_sleep(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest('sleep', test_sleep_) & ] end subroutine collect_sleep subroutine test_sleep_(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(int64) :: tic, toc, trate real(real64) :: t_ms call system_clock(count_rate=trate) call system_clock(count=tic) call sleep(millisec) call system_clock(count=toc) t_ms = (toc - tic) * 1000._real64 / trate call check(error, t_ms, real(millisec, real64), thr=1.5_real64, rel=.true.) end subroutine test_sleep_ end module test_sleep program tester use, intrinsic :: iso_fortran_env, only: error_unit use testdrive, only: run_testsuite, new_testsuite, testsuite_type use test_sleep, only: collect_sleep implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite('sleep', collect_sleep) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program tester fortran-lang-stdlib-0ede301/test/system/test_filesystem.f900000664000175000017500000005530515135654166024244 0ustar alastairalastairmodule test_filesystem use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_system, only: is_directory, delete_file, FS_ERROR, FS_ERROR_CODE, & make_directory, remove_directory, make_directory_all, is_windows, OS_TYPE, & OS_WINDOWS, get_cwd, set_cwd, operator(/), exists, fs_type_unknown, & fs_type_regular_file, fs_type_directory, fs_type_symlink, is_file use stdlib_error, only: state_type, STDLIB_FS_ERROR use stdlib_strings, only: to_string implicit none contains !> Collect all exported unit tests subroutine collect_suite(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("fs_error", test_fs_error), & new_unittest("fs_exists_not_exists", test_exists_not_exists), & new_unittest("fs_exists_reg_file", test_exists_reg_file), & new_unittest("fs_exists_dir", test_exists_dir), & new_unittest("fs_exists_symlink", test_exists_symlink), & new_unittest("fs_is_file", test_is_file), & new_unittest("fs_is_directory_dir", test_is_directory_dir), & new_unittest("fs_is_directory_file", test_is_directory_file), & new_unittest("fs_delete_non_existent", test_delete_file_non_existent), & new_unittest("fs_delete_existing_file", test_delete_file_existing), & new_unittest("fs_delete_file_being_dir", test_delete_directory), & new_unittest("fs_make_dir", test_make_directory), & new_unittest("fs_make_dir_existing_dir", test_make_directory_existing), & new_unittest("fs_make_dir_all", test_make_directory_all), & new_unittest("fs_remove_dir", test_remove_directory), & new_unittest("fs_remove_dir_non_existent", test_remove_directory_nonexistent), & new_unittest("fs_cwd", test_cwd) & ] end subroutine collect_suite subroutine test_fs_error(error) type(error_type), allocatable, intent(out) :: error type(state_type) :: s1, s2 character(:), allocatable :: msg msg = "code - 10, Cannot create File temp.txt - File already exists" s1 = FS_ERROR_CODE(10, "Cannot create File temp.txt -", "File already exists") call check(error, s1%state == STDLIB_FS_ERROR .and. s1%message == msg, & "FS_ERROR_CODE: Could not construct the state with code correctly") if (allocated(error)) return msg = "Cannot create File temp.txt - File already exists" s2 = FS_ERROR("Cannot create File temp.txt -", "File already exists") call check(error, s2%state == STDLIB_FS_ERROR .and. s2%message == msg, & "FS_ERROR: Could not construct state without code correctly") if (allocated(error)) return end subroutine test_fs_error subroutine test_exists_not_exists(error) type(error_type), allocatable, intent(out) :: error type(state_type) :: err character(*), parameter :: path = "rand_name" integer :: t t = exists(path, err) call check(error, err%error(), "False positive for a non-existent path!") end subroutine test_exists_not_exists subroutine test_exists_reg_file(error) type(error_type), allocatable, intent(out) :: error type(state_type) :: err character(len=256) :: filename integer :: ios, iunit, t character(len=512) :: msg filename = "test_file.txt" ! Create a file open(newunit=iunit, file=filename, status="replace", iostat=ios, iomsg=msg) call check(error, ios == 0, "Cannot init test_exists_reg_file: " // trim(msg)) if (allocated(error)) return t = exists(filename, err) call check(error, err%ok(), "exists failed for reg file: " // err%print()) if (allocated(error)) then ! Clean up: remove the file close(iunit,status='delete',iostat=ios,iomsg=msg) call check(error, ios == 0, error%message// " and cannot delete test file: " // trim(msg)) return end if call check(error, t == fs_type_regular_file, "exists incorrectly identifies type of & reg files!: type=" // to_string(t)) if (allocated(error)) then ! Clean up: remove the file close(iunit,status='delete',iostat=ios,iomsg=msg) call check(error, ios == 0, error%message// " and cannot delete test file: " // trim(msg)) return end if ! Clean up: remove the file close(iunit,status='delete',iostat=ios,iomsg=msg) call check(error, ios == 0, "Cannot delete test file: " // trim(msg)) if (allocated(error)) return end subroutine test_exists_reg_file subroutine test_is_file(error) type(error_type), allocatable, intent(out) :: error character(len=256) :: filename integer :: ios, iunit character(len=512) :: msg logical :: is_reg_file filename = "test_file.txt" ! Create a file open(newunit=iunit, file=filename, status="replace", iostat=ios, iomsg=msg) call check(error, ios == 0, "Cannot init test_is_file: " // trim(msg)) if (allocated(error)) return is_reg_file = is_file(filename) call check(error, is_reg_file, "is_file could not identify a file") if (allocated(error)) then ! Clean up: remove the file close(iunit,status='delete',iostat=ios,iomsg=msg) call check(error, ios == 0, error%message// " and cannot delete test file: " // trim(msg)) return end if ! Clean up: remove the file close(iunit,status='delete',iostat=ios,iomsg=msg) call check(error, ios == 0, "Cannot delete test file: " // trim(msg)) if (allocated(error)) return end subroutine test_is_file subroutine test_exists_dir(error) type(error_type), allocatable, intent(out) :: error type(state_type) :: err character(len=256) :: dirname integer :: ios, iocmd, t character(len=512) :: msg dirname = "temp_dir" ! Create a directory call execute_command_line("mkdir " // dirname, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios == 0 .and. iocmd == 0, "Cannot int test_exists_dir: " // trim(msg)) if (allocated(error)) return t = exists(dirname, err) call check(error, err%ok(), "exists failed for directory: " // err%print()) if (allocated(error)) then ! Clean up: remove the directory call execute_command_line("rmdir " // dirname, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios == 0 .and. iocmd == 0, error%message // " and & & cannot cleanup test_exists_dir: " // trim(msg)) return end if call check(error, t == fs_type_directory, "exists incorrectly identifies type of & directories!: type=" // to_string(t)) if (allocated(error)) then ! Clean up: remove the directory call execute_command_line("rmdir " // dirname, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios == 0 .and. iocmd == 0, error%message // " and & & cannot cleanup test_exists_dir: " // trim(msg)) return end if ! Clean up: remove the directory call execute_command_line("rmdir " // dirname, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios == 0 .and. iocmd == 0, "Cannot cleanup test_exists_dir: " // trim(msg)) end subroutine test_exists_dir subroutine test_exists_symlink(error) type(error_type), allocatable, intent(out) :: error type(state_type) :: err character(len=128) :: target_name, link_name integer :: ios, iunit, iocmd, t character(len=512) :: msg, cmd target_name = "test_file.txt" link_name = "symlink.txt" ! Create a file open(newunit=iunit, file=target_name, status="replace", iostat=ios, iomsg=msg) call check(error, ios == 0, "Cannot init test_exists_symlink: " // trim(msg)) if (allocated(error)) return if (is_windows()) then cmd = 'mklink '//link_name//' '//target_name call execute_command_line(cmd, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) else cmd = 'ln -s '//target_name//' '//link_name call execute_command_line(cmd, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) end if call check(error, ios == 0 .and. iocmd == 0, "Cannot create symlink!: " // trim(msg)) if (allocated(error)) then ! Clean up: remove the target close(iunit,status='delete',iostat=ios,iomsg=msg) call check(error, ios == 0, error%message // " and cannot delete target: " // trim(msg)) return end if t = exists(link_name, err) call check(error, err%ok(), "exists failed for symlink: " // err%print()) if (allocated(error)) then ! Clean up: remove the link call execute_command_line("rm " // link_name, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios == 0 .and. iocmd == 0, error%message // " and & & cannot delete link: " // trim(msg)) ! Clean up: remove the target close(iunit,status='delete',iostat=ios,iomsg=msg) call check(error, ios == 0, error%message // " and cannot delete target: " // trim(msg)) return end if call check(error, t == fs_type_symlink, "exists incorrectly identifies type of & symlinks!: type=" // to_string(t)) if (allocated(error)) then ! Clean up: remove the link call execute_command_line("rm " // link_name, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios == 0 .and. iocmd == 0, error%message // " and & & cannot delete link: " // trim(msg)) ! Clean up: remove the target close(iunit,status='delete',iostat=ios,iomsg=msg) call check(error, ios == 0, error%message // " and cannot delete target: " // trim(msg)) return end if ! Clean up: remove the link call execute_command_line("rm " // link_name, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios == 0 .and. iocmd == 0, "Cannot delete link: " // trim(msg)) if (allocated(error)) then ! Clean up: remove the target close(iunit,status='delete',iostat=ios,iomsg=msg) call check(error, ios == 0, error%message // " and cannot delete target: " // trim(msg)) end if ! Clean up: remove the target close(iunit,status='delete',iostat=ios,iomsg=msg) call check(error, ios == 0, "Cannot delete target: " // trim(msg)) end subroutine test_exists_symlink ! Test `is_directory` for a directory subroutine test_is_directory_dir(error) type(error_type), allocatable, intent(out) :: error character(len=256) :: dirname integer :: ios, iocmd character(len=512) :: msg dirname = "this_test_dir_tmp" ! Create a directory call execute_command_line("mkdir " // dirname, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios == 0 .and. iocmd == 0, "Cannot create test directory: " // trim(msg)) if (allocated(error)) return ! Verify `is_directory` identifies it as a directory call check(error, is_directory(dirname), "is_directory did not recognize a valid directory") if (allocated(error)) return ! Clean up: remove the directory call execute_command_line("rmdir " // dirname, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios == 0 .and. iocmd == 0, "Cannot remove test directory: " // trim(msg)) end subroutine test_is_directory_dir ! Test `is_directory` for a regular file subroutine test_is_directory_file(error) type(error_type), allocatable, intent(out) :: error character(len=256) :: filename logical :: result integer :: ios, iunit character(len=512) :: msg filename = "test_file.txt" ! Create a file open(newunit=iunit, file=filename, status="replace", iostat=ios, iomsg=msg) call check(error, ios == 0, "Cannot create test file: " // trim(msg)) if (allocated(error)) return ! Verify `is_directory` identifies it as not a directory result = is_directory(filename) call check(error, .not. result, "is_directory falsely recognized a regular file as a directory") if (allocated(error)) return ! Clean up: remove the file close(iunit,status='delete',iostat=ios,iomsg=msg) call check(error, ios == 0, "Cannot delete test file: " // trim(msg)) if (allocated(error)) return end subroutine test_is_directory_file subroutine test_delete_file_non_existent(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(state_type) :: state ! Attempt to delete a file that doesn't exist call delete_file('non_existent_file.txt', state) call check(error, state%ok(), 'Error should not be triggered for non-existent file') if (allocated(error)) return end subroutine test_delete_file_non_existent subroutine test_delete_file_existing(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=256) :: filename type(state_type) :: state integer :: ios,iunit logical :: is_present character(len=512) :: msg filename = 'existing_file.txt' ! Create a file to be deleted open(newunit=iunit, file=filename, status='replace', iostat=ios, iomsg=msg) call check(error, ios==0, 'Failed to create test file') if (allocated(error)) return close(iunit) ! Attempt to delete the existing file call delete_file(filename, state) ! Check deletion successful call check(error, state%ok(), 'delete_file returned '//state%print()) if (allocated(error)) return ! Check if the file was successfully deleted (should no longer exist) inquire(file=filename, exist=is_present) call check(error, .not.is_present, 'File still present after delete') if (allocated(error)) return end subroutine test_delete_file_existing subroutine test_delete_directory(error) !> Error handling type(error_type), allocatable, intent(out) :: error character(len=256) :: filename type(state_type) :: state integer :: ios,iocmd character(len=512) :: msg filename = 'test_directory' ! The directory is not nested: it should be cross-platform to just call `mkdir` call execute_command_line('mkdir ' // filename, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios==0 .and. iocmd==0, 'Cannot init delete_directory test: '//trim(msg)) if (allocated(error)) return ! Attempt to delete a directory (which should fail) call delete_file(filename, state) ! Check that an error was raised since the target is a directory call check(error, state%error(), 'Error was not triggered trying to delete directory') if (allocated(error)) return ! Clean up: remove the empty directory call execute_command_line('rmdir ' // filename, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios==0 .and. iocmd==0, 'Cannot cleanup delete_directory test: '//trim(msg)) if (allocated(error)) return end subroutine test_delete_directory subroutine test_make_directory(error) type(error_type), allocatable, intent(out) :: error type(state_type) :: err character(len=256) :: dir_name integer :: ios,iocmd character(len=512) :: msg dir_name = "test_directory" call make_directory(dir_name, err=err) call check(error, err%ok(), 'Could not make directory: '//err%print()) if (allocated(error)) return ! clean up: remove the empty directory call execute_command_line('rmdir ' // dir_name, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios==0 .and. iocmd==0, 'Cannot cleanup make_directory test: '//trim(msg)) end subroutine test_make_directory subroutine test_make_directory_existing(error) type(error_type), allocatable, intent(out) :: error type(state_type) :: err character(len=256) :: dir_name integer :: ios,iocmd character(len=512) :: msg dir_name = "test_directory" call execute_command_line('mkdir ' // dir_name, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios==0 .and. iocmd==0, 'Cannot init make_directory_existing test: '//trim(msg)) if (allocated(error)) return call make_directory(dir_name, err=err) call check(error, err%error(), 'Made an already existing directory somehow') ! clean up: remove the empty directory call execute_command_line('rmdir ' // dir_name, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) if (allocated(error)) then ! if previous error is allocated as well call check(error, ios==0 .and. iocmd==0, error%message // ' and cannot cleanup make_directory test: '//trim(msg)) return end if call check(error, ios==0 .and. iocmd==0, 'Cannot cleanup make_directory test: '//trim(msg)) end subroutine test_make_directory_existing subroutine test_make_directory_all(error) type(error_type), allocatable, intent(out) :: error type(state_type) :: err character(len=256) :: dir_name integer :: ios,iocmd character(len=512) :: msg if (OS_TYPE() == OS_WINDOWS) then dir_name = "d1\d2\d3\d4\" else dir_name = "d1/d2/d3/d4/" end if call make_directory_all(dir_name, err=err) call check(error, err%ok(), 'Could not make all directories: '//err%print()) if (allocated(error)) return ! clean up: remove the empty directory if (is_windows()) then call execute_command_line('rmdir /s /q d1', exitstat=ios, cmdstat=iocmd, cmdmsg=msg) else call execute_command_line('rm -rf d1', exitstat=ios, cmdstat=iocmd, cmdmsg=msg) end if call check(error, ios==0 .and. iocmd==0, 'Cannot cleanup make_directory_all test: '//trim(msg)) end subroutine test_make_directory_all subroutine test_remove_directory(error) type(error_type), allocatable, intent(out) :: error type(state_type) :: err character(len=256) :: dir_name integer :: ios,iocmd character(len=512) :: msg dir_name = "test_directory" call execute_command_line('mkdir ' // dir_name, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios==0 .and. iocmd==0, 'Cannot init remove_directory test: '//trim(msg)) if (allocated(error)) return call remove_directory(dir_name, err) call check(error, err%ok(), 'Could not remove directory: '//err%print()) if (allocated(error)) then ! clean up: remove the empty directory call execute_command_line('rmdir ' // dir_name, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios==0 .and. iocmd==0, error%message // ' and cannot cleanup make_directory test: '//trim(msg)) end if end subroutine test_remove_directory subroutine test_remove_directory_nonexistent(error) type(error_type), allocatable, intent(out) :: error type(state_type) :: err call remove_directory("random_name", err) call check(error, err%error(), 'Somehow removed a non-existent directory') if (allocated(error)) return end subroutine test_remove_directory_nonexistent subroutine test_cwd(error) type(error_type), allocatable, intent(out) :: error type(state_type) :: err character(len=256) :: dir_name integer :: ios,iocmd character(len=512) :: msg character(:), allocatable :: pwd1, pwd2, abs_dir_name ! get the initial cwd call get_cwd(pwd1, err) call check(error, err%ok(), 'Could not get current working directory: '//err%print()) if (allocated(error)) return ! create a temporary directory for use by `set_cwd` dir_name = "test_directory" call execute_command_line('mkdir ' // dir_name, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios==0 .and. iocmd==0, 'Cannot init cwd test: '//trim(msg)) if (allocated(error)) return abs_dir_name = pwd1 / dir_name call set_cwd(abs_dir_name, err) call check(error, err%ok(), 'Could not set current working directory: '//err%print()) if (allocated(error)) return ! get the new cwd -> should be same as (pwd1 / dir_name) call get_cwd(pwd2, err) call check(error, err%ok(), 'Could not get current working directory: '//err%print()) if (allocated(error)) return call check(error, pwd2 == abs_dir_name, 'Working directory is wrong, & & expected: '//abs_dir_name//" got: "//pwd2) if (allocated(error)) return ! cleanup: set the cwd back to the initial value call set_cwd(pwd1, err) call check(error, err%ok(), 'Could not clean up cwd test, could not set the cwd back: '//err%print()) if (allocated(error)) then ! our cwd now is `./test_directory` ! there is no way of removing the empty test directory return end if ! cleanup: remove the empty directory call execute_command_line('rmdir ' // dir_name, exitstat=ios, cmdstat=iocmd, cmdmsg=msg) call check(error, ios==0 .and. iocmd==0, 'Cannot cleanup cwd test, cannot remove empty dir: '//trim(msg)) if (allocated(error)) return end subroutine test_cwd end module test_filesystem program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_filesystem, only : collect_suite implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("filesystem", collect_suite) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/system/test_subprocess.f900000664000175000017500000001523515135654166024246 0ustar alastairalastairmodule test_subprocess use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_system, only: process_type, run, runasync, is_running, wait, update, elapsed, is_windows, kill implicit none contains !> Collect all exported unit tests subroutine collect_suite(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest('test_run_synchronous', test_run_synchronous), & new_unittest('test_run_asynchronous', test_run_asynchronous), & new_unittest('test_process_kill', test_process_kill), & new_unittest('test_process_state', test_process_state), & new_unittest('test_input_redirection', test_input_redirection) & ] end subroutine collect_suite !> Test running a synchronous process subroutine test_run_synchronous(error) type(error_type), allocatable, intent(out) :: error type(process_type) :: process character(len=*), parameter :: command = "echo Hello" process = run(command, want_stdout=.true.) call check(error, process%completed) if (allocated(error)) return call check(error, trim(process%stdout) == "Hello", "stdout=<"//trim(process%stdout)//">, expected ") end subroutine test_run_synchronous !> Test running an asynchronous process subroutine test_run_asynchronous(error) type(error_type), allocatable, intent(out) :: error type(process_type) :: process logical :: running ! The closest possible to a cross-platform command that waits if (is_windows()) then process = runasync("ping -n 2 127.0.0.1") else process = runasync("ping -c 2 127.0.0.1") endif ! Should not be immediately completed call check(error, .not. process%completed, "ping process should not complete immediately") if (allocated(error)) return running = is_running(process) call check(error, running, "ping process should still be running immediately after started") if (allocated(error)) return call wait(process) call check(error, process%completed, "process should be complete after `call wait`") if (allocated(error)) return call check(error, elapsed(process)>1.0e-4, "There should be a non-zero elapsed time") end subroutine test_run_asynchronous !> Test killing an asynchronous process subroutine test_process_kill(error) type(error_type), allocatable, intent(out) :: error type(process_type) :: process logical :: running, success ! Start a long-running process asynchronously if (is_windows()) then process = runasync("ping -n 10 127.0.0.1") else process = runasync("ping -c 10 127.0.0.1") endif ! Ensure the process starts running call check(error, .not. process%completed, "Process should not be completed immediately after starting") if (allocated(error)) return running = is_running(process) call check(error, running, "Process should be running immediately after starting") if (allocated(error)) return ! Kill the process call kill(process, success) call check(error, success, "Failed to kill the process") if (allocated(error)) return ! Verify the process is no longer running call check(error, .not. is_running(process), "Process should not be running after being killed") if (allocated(error)) return ! Ensure process state updates correctly after killing call check(error, process%completed, "Process should be marked as completed after being killed") end subroutine test_process_kill !> Test updating and checking process state subroutine test_process_state(error) type(error_type), allocatable, intent(out) :: error type(process_type) :: process character(len=*), parameter :: command = "echo Testing" process = run(command, want_stdout=.true., want_stderr=.true.) call update(process) call check(error, process%completed) if (allocated(error)) return call check(error, process%exit_code == 0, "Check zero exit code") if (allocated(error)) return call check(error, len_trim(process%stderr) == 0, "Check no stderr output") if (allocated(error)) return call check(error, trim(process%stdout) == "Testing", "stdout=<"//trim(process%stdout)//">, expected ") if (allocated(error)) return end subroutine test_process_state !> Test input redirection subroutine test_input_redirection(error) type(error_type), allocatable, intent(out) :: error type(process_type) :: process character(len=*), parameter :: input_string = "Hello Stdin" if (is_windows()) then ! findstr "^" echoes input lines. ! Note: We need complex quoting because of how arguments are parsed. ! Actually, sticking to something simpler if possible. ! "more" implies paging which might hang. "sort" is usually safe. process = run("sort", stdin=input_string, want_stdout=.true.) else process = run("cat", stdin=input_string, want_stdout=.true.) endif call check(error, process%completed, "Process did not complete") if (allocated(error)) return call check(error, process%exit_code == 0, "Process failed with non-zero exit code") if (allocated(error)) return ! Check if output matches input (sort of "Hello Stdin" is "Hello Stdin") call check(error, index(process%stdout, input_string) > 0, & "Output <"//trim(process%stdout)//"> should contain <"//input_string//">") end subroutine test_input_redirection end module test_subprocess program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_subprocess, only : collect_suite implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("subprocess", collect_suite) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/intrinsics/0000775000175000017500000000000015135654166021332 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/intrinsics/test_intrinsics.fypp0000664000175000017500000003014415135654166025460 0ustar alastairalastair#:include "common.fypp" #:set I_KINDS_TYPES = list(zip(INT_KINDS, INT_TYPES, INT_KINDS)) #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) module test_intrinsics use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_kinds, only: sp, dp, xdp, qp, int8, int16, int32, int64 use stdlib_intrinsics use stdlib_linalg_state, only: linalg_state_type, LINALG_VALUE_ERROR, operator(==) use stdlib_math, only: swap implicit none contains !> Collect all exported unit tests subroutine collect_suite(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest('sum', test_sum), & new_unittest('dot_product', test_dot_product), & new_unittest('matmul', test_matmul) & ] end subroutine subroutine test_sum(error) !> Error handling type(error_type), allocatable, intent(out) :: error !> Internal parameters and variables integer, parameter :: n = 1e3, ncalc = 3 real(sp) :: u integer :: iter, i, j !==================================================================================== #:for k, t, s in I_KINDS_TYPES #:if not k in ["int8","int16"] # skip int8 and int16 block ${t}$, allocatable :: x(:) ${t}$, parameter :: total_sum = 0_${k}$ ${t}$ :: xsum(ncalc), err(ncalc) logical, allocatable :: mask(:), nmask(:) allocate(x(n+1)) do i = 1, n+1 x(i) = i - n/2 - 1 end do allocate(mask(n+1),source=.false.); mask(1:n+1:2) = .true. allocate(nmask(n+1)); nmask = .not.mask ! scramble array do i = 1, n+1 call random_number(u) j = 1 + floor(n*u) call swap( x(i), x(j) ) call swap( mask(i), mask(j) ) call swap( nmask(i), nmask(j) ) end do xsum(1) = sum(x) ! compiler intrinsic xsum(2) = stdlib_sum(x) ! chunked summation err(1:2) = abs(total_sum-xsum(1:2)) call check(error, all(err(1:2)==0_${k}$) , "real sum is not accurate" ) if (allocated(error)) return xsum(1) = sum(x,mask)+sum(x,nmask) ! compiler intrinsic xsum(2) = stdlib_sum(x,mask)+stdlib_sum(x,nmask) ! chunked summation err(1:2) = abs(total_sum-xsum(1:2)) call check(error, all(err(1:2)==0_${k}$) , "masked real sum is not accurate" ) if (allocated(error)) return end block #:endif #:endfor #:for k, t, s in R_KINDS_TYPES block ${t}$, allocatable :: x(:) ${t}$, parameter :: total_sum = 4*atan(1._${k}$), tolerance = epsilon(1._${k}$)*100 ${t}$ :: xsum(ncalc), err(ncalc) logical, allocatable :: mask(:), nmask(:) allocate(x(n)) do i = 1, n x(i) = 8*atan(1._${k}$)*(real(i,kind=${k}$)-0.5_${k}$)/real(n,kind=${k}$)**2 end do allocate(mask(n),source=.false.); mask(1:n:2) = .true. allocate(nmask(n)); nmask = .not.mask ! scramble array do i = 1, n call random_number(u) j = 1 + floor(n*u) call swap( x(i), x(j) ) call swap( mask(i), mask(j) ) call swap( nmask(i), nmask(j) ) end do xsum(1) = sum(x) ! compiler intrinsic xsum(2) = stdlib_sum_kahan(x) ! chunked Kahan summation xsum(3) = stdlib_sum(x) ! chunked summation err(1:ncalc) = abs(1._${k}$-xsum(1:ncalc)/total_sum) call check(error, all(err(:) sum all elements call check(error, abs( sum(x) - stdlib_sum(x) ) sum over specific rank dim do i = 1, rank(x) call check(error, norm2( sum(x,dim=i) - stdlib_sum(x,dim=i) ) Error handling type(error_type), allocatable, intent(out) :: error !> Internal parameters and variables integer, parameter :: n = 1e3, ncalc = 3 real(sp) :: u integer :: iter, i, j !==================================================================================== #:for k, t, s in R_KINDS_TYPES block ${t}$, allocatable :: x(:) ${t}$, parameter :: total_sum = 4*atan(1._${k}$), tolerance = epsilon(1._${k}$)*100 ${t}$ :: xsum(ncalc), err(ncalc) allocate(x(n)) do i = 1, n x(i) = 2*sqrt( 2*atan(1._${k}$)*(real(i,kind=${k}$)-0.5_${k}$) )/n end do ! scramble array do i = 1, n call random_number(u) j = 1 + floor(n*u) call swap( x(i), x(j) ) end do xsum(1) = dot_product(x,x) ! compiler intrinsic xsum(2) = stdlib_dot_product_kahan(x,x) ! chunked Kahan summation xsum(3) = stdlib_dot_product(x,x) ! chunked summation err(1:ncalc) = abs(1._${k}$-xsum(1:ncalc)/total_sum) call check(error, all(err(:) 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/intrinsics/CMakeLists.txt0000664000175000017500000000016015135654166024067 0ustar alastairalastairset( fppFiles "test_intrinsics.fypp" ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) ADDTEST(intrinsics) fortran-lang-stdlib-0ede301/test/bitsets/0000775000175000017500000000000015135654166020622 5ustar alastairalastairfortran-lang-stdlib-0ede301/test/bitsets/test_stdlib_bitset_large.f900000664000175000017500000013455715135654166026225 0ustar alastairalastairmodule test_stdlib_bitset_large use testdrive, only : new_unittest, unittest_type, error_type, check use :: stdlib_kinds, only : int8, int16, int32, int64 use stdlib_bitsets, only: bitset_large, bits_kind& , bits & , success & , and, and_not, or, xor& , extract& , assignment(=)& , operator(<), operator(<=)& , operator(>), operator(>=)& , operator(/=), operator(==) implicit none character(*), parameter :: & bitstring_0 = '000000000000000000000000000000000', & bitstring_33 = '100000000000000000000000000000000', & bitstring_all = '111111111111111111111111111111111' contains !> Collect all exported unit tests subroutine collect_stdlib_bitset_large(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("string-operations", test_string_operations), & new_unittest("io", test_io), & new_unittest("initialization", test_initialization), & new_unittest("bitset-assignment-array", test_assignment_array), & new_unittest("bitset-inquiry", test_bitset_inquiry), & new_unittest("bit-operations", test_bit_operations), & new_unittest("bitset-comparisons", test_bitset_comparisons), & new_unittest("bitset-operations", test_bitset_operations) & ] end subroutine collect_stdlib_bitset_large subroutine test_string_operations(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: status character(:), allocatable :: string0 type(bitset_large) :: set0, set1, set3, set4 type(bitset_large) :: set10, set11, set13, set14 call set0 % from_string( bitstring_0 ) call check(error, bits(set0), 33, & 'from_string failed to interpret bitstring_0 size properly.') if (allocated(error)) return call check(error, set0 % none(), & 'failed to interpret bitstring_0 value properly.') if (allocated(error)) return call check(error, .not. set0 % any(), & 'failed to interpret bitstring_0 value properly.') if (allocated(error)) return call set10 % from_string( bitstring_0 // bitstring_0 ) call check(error, bits(set10), 66, & 'from_string failed to interpret bitstring_0 // bitstring_0 size properly.') if (allocated(error)) return call check(error, set10 % none(), & 'failed to interpret bitstring_0 // bitstring_0 value properly.') if (allocated(error)) return call check(error, .not. set10 % any(), & 'failed to interpret bitstring_0 // bitstring_0 value properly.') if (allocated(error)) return call set1 % from_string( bitstring_all ) call check(error, bits(set1), 33, & 'from_string failed to interpret bitstring_all size properly.') if (allocated(error)) return call check(error, .not. set1 % none(), & 'failed to interpret bitstring_all value properly.') if (allocated(error)) return call check(error, set1 % any(), & 'failed to interpret bitstring_all value properly.') if (allocated(error)) return call check(error, set1 % all(), & 'failed to interpret bitstring_all value properly.') if (allocated(error)) return call set11 % from_string( bitstring_all // bitstring_all ) call check(error, bits(set11), 66, & 'from_string failed to interpret bitstring_all // bitstring_all size properly.') if (allocated(error)) return call check(error, .not. set11 % none(), & 'failed to interpret bitstring_all // bitstring_all value properly.') if (allocated(error)) return call check(error, set11 % any(), & 'failed to interpret bitstring_all // bitstring_all value properly.') if (allocated(error)) return call check(error, set11 % all(), & 'failed to interpret bitstring_all // bitstring_all value properly.') if (allocated(error)) return call set3 % read_bitset( bitstring_0, status ) call check(error, status /= success, & 'read_bitset_string did not fail with bitstring_0 as expected.') if (allocated(error)) return call set13 % read_bitset( bitstring_0 // bitstring_0, status ) call check(error, status /= success, & 'read_bitset_string did not fail with bitstring_0 // bitstring_0 as expected.') if (allocated(error)) return call set3 % read_bitset( 's33b' // bitstring_0, status ) call check(error, bits(set3), 33, & 'read_bitset_string failed to interpret "s33b" // bitstring_0 size properly.') if (allocated(error)) return call check(error, set3 % none(), & 'failed to interpret "s33b" // bitstring_0 value properly.') if (allocated(error)) return call set13 % read_bitset( 's66b' // bitstring_0 // bitstring_0, & status ) call check(error, bits(set13), 66, 'read_bitset_string failed to ' // & 'interpret "s66b" // bitstring_0 // bitstring_0 size properly.') if (allocated(error)) return call check(error, set13 % none(), & 'failed to interpret "s66b" // bitstring_0 // bitstring_0 value properly.') if (allocated(error)) return call set4 % read_bitset( 's33b' // bitstring_all ) call check(error, bits(set4), 33, & 'read_bitset_string failed to interpret "s33b" // bitstring_all size properly.') if (allocated(error)) return call check(error, .not. set4 % none(), & 'read_bitset_string failed to interpret "s33b" // bitstring_all value properly.') if (allocated(error)) return call check(error, set4 % any(), & 'read_bitset_string failed to // interpret "s33b" bitstring_all value properly.') if (allocated(error)) return call check(error, set4 % all(), & 'read_bitset_string failed to // interpret "s33b" bitstring_all value properly.') if (allocated(error)) return call set14 % read_bitset( 's66b' // bitstring_all // bitstring_all ) call check(error, bits(set14), 66, & 'read_bitset_string failed to ' // & 'interpret "s66b" // bitstring_all // bitstring_all size properly.') if (allocated(error)) return call check(error, .not. set14 % none(), 'read_bitset_string failed to ' // & 'interpret "s66b" // bitstring_all // bitstring_all value properly.') if (allocated(error)) return call check(error, set14 % any(), 'read_bitset_string failed to // ' // & 'interpret "s66b" bitstring_all // bitstring_all value properly.') if (allocated(error)) return call check(error, set14 % all(), 'read_bitset_string failed to // ' // & 'interpret "s66b" bitstring_all // bitstring_all value properly.') if (allocated(error)) return call set0 % to_string( string0 ) call check(error, bitstring_0, string0, & 'to_string failed to convert set0 value properly.') if (allocated(error)) return call set10 % to_string( string0 ) call check(error, bitstring_0 // bitstring_0, string0, & 'to_string failed to convert set10 value properly.') if (allocated(error)) return call set1 % to_string( string0 ) call check(error, bitstring_all, string0, & 'to_string failed to convert set1 value properly.') if (allocated(error)) return call set11 % to_string( string0 ) call check(error, bitstring_all // bitstring_all, string0, & 'to_string failed to convert set11 value properly.') if (allocated(error)) return call set0 % write_bitset( string0 ) call check(error, ('S33B' // bitstring_0), string0, & 'write_bitset_string failed to convert set2 value properly.') if (allocated(error)) return call set10 % write_bitset( string0 ) call check(error, ('S66B' // bitstring_0 // bitstring_0), string0, & 'write_bitset_string failed to convert set10 value properly.') if (allocated(error)) return call set1 % write_bitset( string0 ) call check(error, ('S33B' // bitstring_all), string0, & 'write_bitset_string failed to convert set1 value properly.') if (allocated(error)) return call set11 % write_bitset( string0 ) call check(error, ('S66B' // bitstring_all // bitstring_all), string0, & 'write_bitset_string failed to convert set11 value properly.') if (allocated(error)) return end subroutine test_string_operations subroutine test_io(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: unit type(bitset_large) :: set0, set1, set2, set3, set4, set5 type(bitset_large) :: set10, set11, set12, set13, set14, set15 call set0 % from_string( bitstring_0 ) call set1 % from_string( bitstring_all ) call set2 % from_string( bitstring_33 ) open( newunit=unit, status='scratch', form='formatted', & action='readwrite' ) call set2 % write_bitset(unit) call set1 % write_bitset(unit) call set0 % write_bitset(unit) rewind( unit ) call set3 % read_bitset(unit) call set5 % read_bitset(unit) call set4 % read_bitset(unit) call check(error, set4 == set0 .and. set5 == set1 .and. set3 == set2, & 'transfer to and from units using bitset literals failed.') if (.not.allocated(error)) then rewind( unit ) call set10 % from_string( bitstring_0 // bitstring_0 ) call set11 % from_string( bitstring_all // bitstring_all ) call set12 % from_string( bitstring_33 // bitstring_33 ) call set12 % write_bitset(unit) call set11 % write_bitset(unit) call set10 % write_bitset(unit) rewind( unit ) call set13 % read_bitset(unit) call set15 % read_bitset(unit) call set14 % read_bitset(unit) call check(error, set14 == set10 .and. set15 == set11 .and. set3 == set12, & 'transfer to and from units using bitset literals for bits > 64 failed.') end if if (.not.allocated(error)) then rewind( unit ) call set2 % write_bitset(unit, advance='no') call set1 % write_bitset(unit, advance='no') call set0 % write_bitset(unit) rewind( unit ) call set3 % read_bitset(unit, advance='no') call set4 % read_bitset(unit, advance='no') call set5 % read_bitset(unit) call check(error, set5 == set0 .and. set4 == set1 .and. set3 == set2, & 'transfer to and from units using bitset literals with advance == "no" failed.') end if if (.not.allocated(error)) then rewind( unit ) call set12 % write_bitset(unit, advance='no') call set11 % write_bitset(unit, advance='no') call set10 % write_bitset(unit) rewind( unit ) call set13 % read_bitset(unit, advance='no') call set14 % read_bitset(unit, advance='no') call set15 % read_bitset(unit) call check(error, set15 == set10 .and. set14 == set11 .and. set13 == set12, & 'transfer to and from units using bitset literals for bitss > 64 with advance == "no" failed.') end if close(unit) if (allocated(error)) return open( newunit=unit, form='unformatted', status='scratch', & action='readwrite' ) call set2 % output(unit) call set1 % output(unit) call set0 % output(unit) rewind( unit ) call set5 % input(unit) call set4 % input(unit) call set3 % input(unit) call check(error, set3 == set0 .and. set4 == set1 .and. set5 == set2, & 'transfer to and from units using output and input failed.') close( unit ) if (allocated(error)) return open( newunit=unit, form='unformatted', access='stream', & status='scratch', action='readwrite' ) call set2 % output(unit) call set1 % output(unit) call set0 % output(unit) rewind( unit ) call set5 % input(unit) call set4 % input(unit) call set3 % input(unit) call check(error, set3 == set0 .and. set4 == set1 .and. set5 == set2, & 'transfer to and from units using stream output and input failed.') close( unit ) if (allocated(error)) return open( newunit=unit, form='unformatted', status='scratch', & action='readwrite' ) call set12 % output(unit) call set11 % output(unit) call set10 % output(unit) rewind( unit ) call set15 % input(unit) call set14 % input(unit) call set13 % input(unit) call check(error, set13 == set10 .and. set14 == set11 .and. set15 == set12, & 'transfer to and from units using output and input failed for bits . 64.') close(unit) if (allocated(error)) return open( newunit=unit, form='unformatted', access='stream', & status='scratch', action='readwrite' ) call set12 % output(unit) call set11 % output(unit) call set10 % output(unit) rewind( unit ) call set15 % input(unit) call set14 % input(unit) call set13 % input(unit) call check(error, set13 == set10 .and. set14 == set11 .and. set15 == set12, & 'transfer to and from units using stream output and input failed for bits . 64.') close(unit) if (allocated(error)) return end subroutine test_io subroutine test_initialization(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical(int8) :: log1(64) = .true. logical(int16) :: log2(31) = .false. logical(int32) :: log3(15) = .true. logical(int64) :: log4(33) = .false. logical(int8) :: log11(66) = .true. logical(int16) :: log12(99) = .false. logical(int32) :: log13(132) = .true. logical(int64) :: log14(165) = .false. logical(int8), allocatable :: log5(:) logical(int16), allocatable :: log6(:) logical(int32), allocatable :: log7(:) logical(int64), allocatable :: log8(:) type(bitset_large) :: set4, set5 !The following triggers an issue in gfortran 11 and 12 block type(bitset_large) :: set6 call check(error, set6 % bits(), 0, & 'set6 % bits() returned non-zero value '//& 'even though set6 was not initialized.') if (allocated(error)) return end block set5 = log1 call check(error, set5 % bits(), 64, & ' initialization with logical(int8) failed to set' // & ' the right size.') if (allocated(error)) return call check(error, set5 % all(), & ' initialization with' // & ' logical(int8) failed to set the right values.') if (allocated(error)) return set5 = log11 call check(error, set5 % bits(), 66, & ' initialization with logical(int8) failed to set' // & ' the right size > 64 bits.') if (allocated(error)) return call check(error, set5 % all(), & ' initialization with' // & ' logical(int8) failed to set the right values.') if (allocated(error)) return set5 = log2 call check(error, set5 % bits(), 31, & ' initialization with logical(int16) failed to set' // & ' the right size.') if (allocated(error)) return call check(error, set5 % none(), & ' initialization with logical(int16) failed to set' // & ' the right values.') if (allocated(error)) return set5 = log12 call check(error, set5 % bits(), 99, & ' initialization with logical(int16) failed to set' // & ' the right size > 64 bits .') if (allocated(error)) return call check(error, set5 % none(), & ' initialization with logical(int16) failed to set' // & ' the right values > 64 bits .') if (allocated(error)) return set5 = log3 call check(error, set5 % bits(), 15, & ' initialization with logical(int32) failed to set' // & ' the right size.') if (allocated(error)) return call check(error, set5 % all(), & ' initialization with logical(int32) failed to set' // & ' the right values.') if (allocated(error)) return set5 = log13 call check(error, set5 % bits(), 132, & ' initialization with logical(int32) failed to set' // & ' the right size > 64 bits .') if (allocated(error)) return call check(error, set5 % all(), & ' initialization with logical(int32) failed to set' // & ' the right values > 64 bits .') if (allocated(error)) return set5 = log4 call check(error, set5 % bits(), 33, & ' initialization with logical(int64) failed to set' // & ' the right size.') if (allocated(error)) return call check(error, set5 % none(), & ' initialization with logical(int64) failed to set' // & ' the right values.') if (allocated(error)) return set5 = log14 call check(error, set5 % bits(), 165, & ' initialization with logical(int64) failed to set' // & ' the right size > 64 bits .') if (allocated(error)) return call check(error, set5 % none(), & ' initialization with logical(int64) failed to set' // & ' the right values > 64 bits .') if (allocated(error)) return set5 = log1 call extract( set4, set5, 1_bits_kind, 33_bits_kind ) call check(error, set4 % bits(), 33, & ' initialization with extract failed to set' // & ' the right size.') if (allocated(error)) return call check(error, set4 % all(), & ' initialization with extract failed to set' // & ' the right values.') if (allocated(error)) return set5 = log11 call extract( set4, set5, 1_bits_kind, 65_bits_kind ) call check(error, set4 % bits(), 65, & ' initialization with extract failed to set' // & ' the right size > 64 bits.') if (allocated(error)) return call check(error, set4 % all(), & ' initialization with extract failed to set' // & ' the right values > 64 bits.') if (allocated(error)) return set5 = log1 set4 = set5 call check(error, set4 % bits(), 64, & ' initialization with simple assignment failed to set' // & ' the right size.') if (allocated(error)) return call check(error, set4 % all(), & ' initialization with simple assignment failed to set' // & ' the right values.') if (allocated(error)) return set5 = log11 set4 = set5 call check(error, set4 % bits(), 66, & ' initialization with simple assignment failed to set' // & ' the right size > 64 bits.') if (allocated(error)) return call check(error, set4 % all(), & ' initialization with simple assignment failed to set' // & ' the right values > 64 bits.') if (allocated(error)) return set5 = log1 log5 = set5 call check(error, size(log5), 64, & ' initialization of logical(int8) with assignment failed' // & ' to set the right size.') if (allocated(error)) return call check(error, all(log5) .eqv. .true., & ! FIXME ' initialization of logical(int8) with assignment failed' // & ' to set the right values.') if (allocated(error)) return set5 = log11 log5 = set5 call check(error, size(log5), 66, & ' initialization of logical(int8) with assignment failed' // & ' to set the right size > 64 bits.') if (allocated(error)) return call check(error, all(log5) .eqv. .true., & ! FIXME ' initialization of logical(int8) with assignment failed' // & ' to set the right values > 64 bits.') if (allocated(error)) return set5 = log1 log6 = set5 call check(error, size(log6), 64, & ' initialization of logical(int16) with assignment failed' // & ' to set the right size.') if (allocated(error)) return call check(error, all(log6) .eqv. .true., & ! FIXME ' initialization of logical(int16) with assignment failed' // & ' to set the right values.') if (allocated(error)) return set5 = log11 log6 = set5 call check(error, size(log6), 66, & ' initialization of logical(int16) with assignment failed' // & ' to set the right size > 64 bits.') if (allocated(error)) return call check(error, all(log6) .eqv. .true., & ! FIXME ' initialization of logical(int16) with assignment failed' // & ' to set the right values > 64 bits.') if (allocated(error)) return set5 = log1 log7 = set5 call check(error, size(log7), 64, & ' initialization of logical(int32) with assignment failed' // & ' to set the right size.') if (allocated(error)) return call check(error, all(log7), & ' initialization of logical(int32) with assignment failed' // & ' to set the right values.') if (allocated(error)) return set5 = log11 log7 = set5 call check(error, size(log7), 66, & ' initialization of logical(int32) with assignment failed' // & ' to set the right size > 64 bits.') if (allocated(error)) return call check(error, all(log7), & ' initialization of logical(int32) with assignment failed' // & ' to set the right values > 64 bits.') if (allocated(error)) return set5 = log1 log8 = set5 call check(error, size(log8), 64, & ' initialization of logical(int64) with assignment failed' // & ' to set the right size.') if (allocated(error)) return call check(error, merge(.true., .false., all(log8)), & ! FIXME ' initialization of logical(int64) with assignment failed' // & ' to set the right values.') if (allocated(error)) return set5 = log11 log8 = set5 call check(error, size(log8), 66, & ' initialization of logical(int64) with assignment failed' // & ' to set the right size > 64 bits.') if (allocated(error)) return call check(error, merge(.true., .false., all(log8)), & ! FIXME ' initialization of logical(int64) with assignment failed' // & ' to set the right values > 64 bits.') if (allocated(error)) return end subroutine test_initialization subroutine test_assignment_array(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical(int8) :: log1(64) = .true. integer :: i type(bitset_large) :: set1(0:4) do i = 0, size(set1) - 1 set1(i) = log1 enddo do i = 0, size(set1) - 1 call check(error, set1(i) % bits(), 64, & ' initialization with logical(int8) failed to set' // & ' the right size in a bitset array.') if (allocated(error)) return enddo !Test added following issue https://github.com/fortran-lang/stdlib/issues/726 set1(0) = set1(0) call check(error, set1(0) % bits(), 64, & ' initialization from bitset_large failed to set' // & ' the right size in a bitset array.') if (allocated(error)) return end subroutine test_assignment_array subroutine test_bitset_inquiry(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(bits_kind) :: i type(bitset_large) :: set0, set1 type(bitset_large) :: set10, set11 call set0 % from_string( bitstring_0 ) call set1 % from_string( bitstring_all ) call check(error, set0 % none(), & ' set0 did not have none set which was unexpected') if (allocated(error)) return call check(error, .not. set0 % any(), & ' set0 had some bits set which was unexpected.') if (allocated(error)) return call set0 % not() call check(error, set0 % all(), & ' set0 did not have all bits set which was unexpected') if (allocated(error)) return call check(error, set0 % any(), & ' set0 had no bits set which was unexpected.') if (allocated(error)) return call check(error, set1 % any(), & ' set1 had none bits set which was unexpected') if (allocated(error)) return call check(error, set1 % all(), & ' set1 did not have all bits set which was unexpected.') if (allocated(error)) return call set0 % not() do i=0, set0 % bits() - 1 call check(error, .not. set0 % test(i), & 'against expectations set0 has at least 1 bit set.') if (allocated(error)) return end do do i=0, set1 % bits() - 1 call check(error, set1 % test(i), & 'against expectations set0 has at least 1 bit unset.') if (allocated(error)) return end do do i=0, set0 % bits() - 1 call check(error, set0 % value(i), 0, & 'against expectations set0 has at least 1 bit set.') if (allocated(error)) return end do do i=0, set1 % bits() - 1 call check(error, set1 % value(i), 1, & 'against expectations set0 has at least 1 bit unset.') if (allocated(error)) return end do call check(error, set0 % bits() == 33, & 'set0 unexpectedly does not have 33 bits.') if (allocated(error)) return ! > 64 bit inquiries call set10 % from_string( bitstring_0 // bitstring_0 // bitstring_0 ) call check(error, set10 % none(), & ' set10 did not have none set which was unexpected') if (allocated(error)) return call check(error, .not. set10 % any(), & ' set10 had some bits set which was unexpected.') if (allocated(error)) return call set10 % not() call check(error, set10 % all(), & ' set10 did not have all bits set which was unexpected') if (allocated(error)) return call check(error, set10 % any(), & ' set10 had no bits set which was unexpected.') if (allocated(error)) return call set11 % from_string( bitstring_all // bitstring_all // & bitstring_all ) call check(error, set11 % any(), & ' set11 had none bits set which was unexpected') if (allocated(error)) return call check(error, set11 % all(), & ' set11 did not have all bits set which was unexpected.') if (allocated(error)) return call set10 % not() do i=0, set10 % bits() - 1 call check(error, .not. set10 % test(i), & 'against expectations set10 has at least 1 bit set.') if (allocated(error)) return end do do i=0, set11 % bits() - 1 call check(error, set11 % test(i), & 'against expectations set11 has at least 1 bit unset.') if (allocated(error)) return end do do i=0, set10 % bits() - 1 call check(error, set10 % value(i), 0, & 'against expectations set10 has at least 1 bit set.') if (allocated(error)) return end do do i=0, set11 % bits() - 1 call check(error, set11 % value(i), 1, & 'against expectations set11 has at least 1 bit unset.') if (allocated(error)) return end do call check(error, set0 % bits() == 33, & 'set0 unexpectedly does not have 33 bits.') if (allocated(error)) return call check(error, set10 % bits() == 99, & 'set10 unexpectedly does not have 99 bits.') if (allocated(error)) return end subroutine test_bitset_inquiry subroutine test_bit_operations(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_large) :: set1, set11 call set1 % from_string( bitstring_all ) call check(error, set1 % all(), & 'set1 is not all set.') if (allocated(error)) return call set1 % clear(0_bits_kind) call check(error, .not. set1 % test(0_bits_kind), & 'did not clear the first bit in set1.') if (allocated(error)) return call check(error, set1 % test(1_bits_kind), & 'cleared more than one bit in set1.') if (allocated(error)) return call set1 % clear(1_bits_kind, 32_bits_kind) call check(error, set1 % none(), & 'did not clear remaining bits in set1.') if (allocated(error)) return call set1 % flip(0_bits_kind) call check(error, set1 % test(0_bits_kind), & 'did not flip the first bit in set1.') if (allocated(error)) return call check(error, .not. set1 % test(1_bits_kind), & 'flipped more than one bit in set1.') if (allocated(error)) return call set1 % flip(1_bits_kind, 32_bits_kind) call check(error, set1 % all(), & 'did not flip remaining bits in set1.') if (allocated(error)) return call set1 % not() call check(error, set1 % none(), & 'did not unset bits in set1.') if (allocated(error)) return call set1 % set(0_bits_kind) call check(error, set1 % test(0_bits_kind), & 'did not set the first bit in set1.') if (allocated(error)) return call check(error, .not. set1 % test(1_bits_kind), & 'set more than one bit in set1.') if (allocated(error)) return call set1 % set(1_bits_kind, 32_bits_kind) call check(error, set1 % all(), & 'did not set the remaining bits in set1.') if (allocated(error)) return call set11 % init( 166_bits_kind ) call set11 % not() call check(error, set11 % all(), & 'set11 is not all set.') if (allocated(error)) return call set11 % clear(0_bits_kind) call check(error, .not. set11 % test(0_bits_kind), & 'did not clear the first bit in set11.') if (allocated(error)) return call check(error, set11 % test(1_bits_kind), & 'cleared more than one bit in set11.') if (allocated(error)) return call set11 % clear(165_bits_kind) call check(error, .not. set11 % test(165_bits_kind), & 'did not clear the last bit in set11.') if (allocated(error)) return call check(error, set11 % test(164_bits_kind), & 'cleared more than one bit in set11.') if (allocated(error)) return call set11 % clear(1_bits_kind, 164_bits_kind) call check(error, set11 % none(), & 'did not clear remaining bits in set11.') if (allocated(error)) return call set11 % flip(0_bits_kind) call check(error, set11 % test(0_bits_kind), & 'did not flip the first bit in set11.') if (allocated(error)) return call check(error, .not. set11 % test(1_bits_kind), & 'flipped more than one bit in set11.') if (allocated(error)) return call set11 % flip(165_bits_kind) call check(error, set11 % test(165_bits_kind), & 'did not flip the last bit in set11.') if (allocated(error)) return call check(error, .not. set11 % test(164_bits_kind), & 'flipped more than one bit in set11.') if (allocated(error)) return call set11 % flip(1_bits_kind, 164_bits_kind) call check(error, set11 % all(), & 'did not flip remaining bits in set11.') if (allocated(error)) return call set11 % not() call check(error, set11 % none(), & 'did not unset bits in set11.') if (allocated(error)) return call set11 % set(0_bits_kind) call check(error, set11 % test(0_bits_kind), & 'did not set the first bit in set11.') if (allocated(error)) return call check(error, .not. set11 % test(1_bits_kind), & 'set more than one bit in set11.') if (allocated(error)) return call set11 % set(165_bits_kind) call check(error, set11 % test(165_bits_kind), & 'did not set the last bit in set11.') if (allocated(error)) return call check(error, .not. set11 % test(164_bits_kind), & 'set more than one bit in set11.') if (allocated(error)) return call set11 % set(1_bits_kind, 164_bits_kind) call check(error, set11 % all(), & 'did not set the remaining bits in set11.') if (allocated(error)) return end subroutine test_bit_operations subroutine test_bitset_comparisons(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_large) :: set0, set1, set2 type(bitset_large) :: set10, set11, set12, set13, set14 call set0 % from_string( bitstring_0 ) call set1 % from_string( bitstring_all ) call set2 % from_string( bitstring_33 ) call check(error, set0 == set0 .and. set1 == set1 .and. set2 == set2 .and. & .not. set0 == set1 .and. .not. set0 == set2 .and. .not. & set1 == set2, 'failed 64 bit equality tests.') if (allocated(error)) return call check(error, set0 /= set1 .and. set1 /= set2 .and. set0 /= set2 .and. & .not. set0 /= set0 .and. .not. set1 /= set1 .and. .not. & set2 /= set2, 'failed 64 bit inequality tests.') if (allocated(error)) return call check(error, set1 > set0 .and. set2 > set0 .and. set1 > set2 .and. & .not. set0 > set1 .and. .not. set1 > set1 .and. .not. & set2 > set1, 'failed 64 bit greater than tests.') if (allocated(error)) return call check(error, set1 >= set0 .and. set1 >= set2 .and. set2 >= set2 .and. & .not. set0 >= set1 .and. .not. set0 >= set1 .and. .not. & set2 >= set1, 'failed 64 bit greater than or equal tests.') if (allocated(error)) return call check(error, set0 < set1 .and. set0 < set1 .and. set2 < set1 .and. & .not. set1 < set0 .and. .not. set0 < set0 .and. .not. & set1 < set2, 'failed 64 bit less than tests.') if (allocated(error)) return call check(error, set0 <= set1 .and. set2 <= set1 .and. set2 <= set2 .and. & .not. set1 <= set0 .and. .not. set2 <= set0 .and. .not. & set1 <= set2, 'failed 64 bit less than or equal tests.') if (allocated(error)) return call set10 % init(166_bits_kind) call set11 % init(166_bits_kind) call set11 % not() call set12 % init(166_bits_kind) call set12 % set(165_bits_kind) call set13 % init(166_bits_kind) call set13 % set(65_bits_kind) call set14 % init(166_bits_kind) call set14 % set(0_bits_kind) call check(error, set10 == set10 .and. set11 == set11 .and. set12 == set12 .and. & set13 == set13 .and. set14 == set14 .and. & .not. set13 == set14 .and. .not. set12 == set13 .and. & .not. set10 == set11 .and. .not. set10 == set12 .and. .not. & set11 == set12, 'failed > 64 bit equality tests.') if (allocated(error)) return call check(error, set10 /= set11 .and. set11 /= set12 .and. set10 /= set12 .and. & set13 /= set12 .and. set14 /= set13 .and. set14 /= set12 .and. & .not. set13 /= set13 .and. .not. set12 /= set12 .and. & .not. set10 /= set10 .and. .not. set11 /= set11 .and. .not. & set12 /= set12, 'failed > 64 bit inequality tests.') if (allocated(error)) return call check(error, set11 > set10 .and. set12 > set10 .and. set11 > set12 .and. & set13 > set14 .and. set12 > set13 .and. set12 > set14 .and. & .not. set14 > set12 .and. .not. set12 > set11 .and. & .not. set10 > set11 .and. .not. set11 > set11 .and. .not. & set12 > set11, 'failed > 64 bit greater than tests.') if (allocated(error)) return call check(error, set11 >= set10 .and. set11 >= set12 .and. set12 >= set12 .and. & set13 >= set14 .and. set12 >= set13 .and. set12 >= set14 .and. & .not. set14 >= set12 .and. .not. set12 >= set11 .and. & .not. set10 >= set11 .and. .not. set10 >= set11 .and. .not. & set12 >= set11, 'failed 64 bit greater than or equal tests.') if (allocated(error)) return call check(error, set10 < set11 .and. set10 < set11 .and. set12 < set11 .and. & set14 < set13 .and. set13 < set12 .and. set14 < set12 .and. & .not. set12 < set14 .and. .not. set11 < set12 .and. & .not. set11 < set10 .and. .not. set10 < set10 .and. .not. & set11 < set12, 'failed > 64 bit less than tests.') if (allocated(error)) return call check(error, set10 <= set11 .and. set12 <= set11 .and. set12 <= set12 .and. & set14 <= set13 .and. set13 <= set12 .and. set14 <= set12 .and. & .not. set12 <= set14 .and. .not. set11 <= set12 .and. & .not. set11 <= set10 .and. .not. set12 <= set10 .and. .not. & set11 <= set12, 'failed > 64 bit less than or equal tests.') if (allocated(error)) return end subroutine test_bitset_comparisons subroutine test_bitset_operations(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_large) :: set0, set3, set4 call set0 % from_string( bitstring_all ) call set4 % from_string( bitstring_all ) call and( set0, set4 ) ! all all call check(error, set0 % all(), 'first test of < 64 bit AND failed.') if (allocated(error)) return call set4 % from_string( bitstring_0 ) call and( set0, set4 ) ! all none call check(error, set0 % none(), 'second test of < 64 bit AND failed.') if (allocated(error)) return call set3 % from_string( bitstring_all ) call set4 % from_string( bitstring_0 ) call and( set4, set3 ) ! none all call check(error, set4 % none(), 'third test of < 64 bit AND failed.') if (allocated(error)) return call set3 % from_string( bitstring_0 ) call and( set4, set3 ) ! none none call check(error, set4 % none(), 'fourth test of < 64 bit AND failed.') if (allocated(error)) return call set3 % from_string( bitstring_all ) call set4 % from_string( bitstring_all ) call and_not( set4, set3 ) ! all all call check(error, set4 % none(), 'first test of < 64 bit AND_NOT failed.') if (allocated(error)) return call set4 % from_string( bitstring_0 ) call and_not( set4, set3 ) ! none all call check(error, set4 % none(), 'second test of < 64 bit AND_NOT failed.') if (allocated(error)) return call set3 % from_string( bitstring_all ) call set4 % from_string( bitstring_0 ) call and_not( set3, set4 ) ! all none call check(error, set3 % all(), 'third test of < 64 bit AND_NOT failed.') if (allocated(error)) return call set3 % from_string( bitstring_0 ) call set4 % from_string( bitstring_0 ) call and_not( set3, set4 ) ! none none call check(error, set3 % none(), 'fourth test of < 64 bit AND_NOT failed.') if (allocated(error)) return call set3 % from_string( bitstring_all ) call set4 % from_string( bitstring_all ) call or( set3, set4 ) ! all all call check(error, set3 % all(), 'first test of < 64 bit OR failed.') if (allocated(error)) return call set3 % from_string( bitstring_0 ) call or( set4, set3 ) ! all none call check(error, set4 % all(), 'second test of < 64 bit OR failed.') if (allocated(error)) return call or( set3, set4 ) ! none all call check(error, set3 % all(), 'third test of < 64 bit OR failed.') if (allocated(error)) return call set3 % from_string( bitstring_0 ) call set4 % from_string( bitstring_0 ) call or( set4, set3 ) !none none call check(error, set4 % none(), 'fourth test of < 64 bit OR failed.') if (allocated(error)) return call set3 % from_string( bitstring_0 ) call set4 % from_string( bitstring_0 ) call xor( set3, set4 ) ! none none call check(error, set3 % none(), 'first test of < 64 bit XOR failed.') if (allocated(error)) return call set4 % from_string( bitstring_all ) call xor( set3, set4 ) ! none all call check(error, set3 % all(), 'second test of < 64 bit XOR failed.') if (allocated(error)) return call set4 % from_string( bitstring_0 ) call xor( set3, set4 ) ! all none call check(error, set3 % all(), 'third test of < 64 bit XOR failed.') if (allocated(error)) return call set4 % from_string( bitstring_all ) call xor( set3, set4 ) ! all all call check(error, set3 % none(), 'fourth test of < 64 bit XOR failed.') if (allocated(error)) return call set0 % init(166_bits_kind) call set0 % not() call set4 % init(166_bits_kind) call set4 % not() call and( set0, set4 ) ! all all call check(error, set0 % all(), 'first test of > 64 bit AND failed.') if (allocated(error)) return call set4 % init(166_bits_kind) call and( set0, set4 ) ! all none call check(error, set0 % none(), 'second test of > 64 bit AND failed.') if (allocated(error)) return call set3 % init(166_bits_kind) call set3 % not() call and( set4, set3 ) ! none all call check(error, set4 % none(), 'third test of > 64 bit AND failed.') if (allocated(error)) return call set3 % init(166_bits_kind) call and( set4, set3 ) ! none none call check(error, set4 % none(), 'fourth test of > 64 bit AND failed.') if (allocated(error)) return call set3 % not() call set4 % not() call and_not( set4, set3 ) ! all all call check(error, set4 % none(), 'first test of > 64 bit AND_NOT failed.') if (allocated(error)) return call and_not( set4, set3 ) ! none all call check(error, set4 % none(), 'second test of > 64 bit AND_NOT failed.') if (allocated(error)) return call and_not( set3, set4 ) ! all none call check(error, set3 % all(), 'third test of > 64 bit AND_NOT failed.') if (allocated(error)) return call set3 % not() call and_not( set3, set4 ) ! none none call check(error, set3 % none(), 'fourth test of > 64 bit AND_NOT failed.') if (allocated(error)) return call set3 % init(166_bits_kind) call set3 % not() call set4 % init(166_bits_kind) call set4 % not() call or( set3, set4 ) ! all all call check(error, set3 % all(), 'first test of > 64 bit OR failed.') if (allocated(error)) return call set3 % init(166_bits_kind) call or( set4, set3 ) ! all none call check(error, set4 % all(), 'second test of > 64 bit OR failed.') if (allocated(error)) return call or( set3, set4 ) ! none all call check(error, set3 % all(), 'third test of > 64 bit OR failed.') if (allocated(error)) return call set3 % init(166_bits_kind) call set4 % init(166_bits_kind) call or( set4, set3 ) !none none call check(error, set4 % none(), 'fourth test of > 64 bit OR failed.') if (allocated(error)) return call xor( set3, set4 ) ! none none call check(error, set3 % none(), 'first test of > 64 bit XOR failed.') if (allocated(error)) return call set4 % not() call xor( set3, set4 ) ! none all call check(error, set3 % all(), 'second test of > 64 bit XOR failed.') if (allocated(error)) return call set4 % not() call xor( set3, set4 ) ! all none call check(error, set3 % all(), 'third test of > 64 bit XOR failed.') if (allocated(error)) return call set4 % not() call xor( set3, set4 ) ! all all call check(error, set3 % none(), 'fourth test of > 64 bit XOR failed.') if (allocated(error)) return end subroutine test_bitset_operations end module test_stdlib_bitset_large program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_stdlib_bitset_large, only : collect_stdlib_bitset_large implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("stdlib-bitset-large", collect_stdlib_bitset_large) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/test/bitsets/CMakeLists.txt0000664000175000017500000000007015135654166023357 0ustar alastairalastairADDTEST(stdlib_bitset_64) ADDTEST(stdlib_bitset_large) fortran-lang-stdlib-0ede301/test/bitsets/test_stdlib_bitset_64.f900000664000175000017500000005430715135654166025356 0ustar alastairalastairmodule test_stdlib_bitset_64 use testdrive, only : new_unittest, unittest_type, error_type, check use :: stdlib_kinds, only : int8, int16, int32, int64 use stdlib_bitsets implicit none private public :: collect_stdlib_bitset_64 character(*), parameter :: & bitstring_0 = '000000000000000000000000000000000', & bitstring_33 = '100000000000000000000000000000000', & bitstring_all = '111111111111111111111111111111111' contains !> Collect all exported unit tests subroutine collect_stdlib_bitset_64(testsuite) !> Collection of tests type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & new_unittest("string-operations-0", test_string_operations_0), & new_unittest("string-operations-1", test_string_operations_1), & new_unittest("string-operations-3", test_string_operations_3), & new_unittest("string-operations-4", test_string_operations_4), & new_unittest("io", test_io), & new_unittest("initialization", test_initialization), & new_unittest("bitset-inquiry", test_bitset_inquiry), & new_unittest("bit-operations", test_bit_operations), & new_unittest("bitset-comparisons", test_bitset_comparisons), & new_unittest("bitset-operations-and", test_bitset_operations_and), & new_unittest("bitset-operations-nand", test_bitset_operations_nand), & new_unittest("bitset-operations-or", test_bitset_operations_or), & new_unittest("bitset-operations-xor", test_bitset_operations_xor) & ] end subroutine collect_stdlib_bitset_64 subroutine test_string_operations_0(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_64) :: set character(:), allocatable :: string0 call set%from_string(bitstring_0) call check(error, bits(set), 33) if (allocated(error)) return call check(error, set%none()) if (allocated(error)) return call check(error, .not.set%any()) if (allocated(error)) return call set%to_string(string0) call check(error, string0, bitstring_0) if (allocated(error)) return call set%write_bitset(string0) call check(error, string0, ('S33B' // bitstring_0)) if (allocated(error)) return end subroutine test_string_operations_0 subroutine test_string_operations_1(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_64) :: set character(:), allocatable :: string0 call set%from_string(bitstring_all) call check(error, bits(set), 33) if (allocated(error)) return call check(error, .not.set%none() ) if (allocated(error)) return call check(error, set%any() ) if (allocated(error)) return call check(error, set%all() ) if (allocated(error)) return call set%to_string(string0) call check(error, string0, bitstring_all) if (allocated(error)) return call set%write_bitset(string0) call check(error, string0, ('S33B' // bitstring_all)) if (allocated(error)) return end subroutine test_string_operations_1 subroutine test_string_operations_3(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_64) :: set integer :: status call set%read_bitset(bitstring_0, status) call check(error, status /= success) if (allocated(error)) return call set%read_bitset('s33b' // bitstring_0, status) call check(error, bits(set), 33) if (allocated(error)) return call check(error, set%none()) if (allocated(error)) return end subroutine test_string_operations_3 subroutine test_string_operations_4(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_64) :: set call set%read_bitset('s33b' // bitstring_all ) call check(error, bits(set), 33) if (allocated(error)) return call check(error, .not.set%none()) if (allocated(error)) return call check(error, set%any()) if (allocated(error)) return call check(error, set%all()) if (allocated(error)) return end subroutine test_string_operations_4 subroutine test_io(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer :: unit type(bitset_64) :: set0, set1, set2, set3, set4, set5 call set0%from_string(bitstring_0) call set1%from_string(bitstring_all) call set2%from_string(bitstring_33) open( newunit=unit, status='scratch', form='formatted', & action='readwrite' ) call set2%write_bitset(unit) call set1%write_bitset(unit) call set0%write_bitset(unit) rewind( unit ) call set3%read_bitset(unit) call set5%read_bitset(unit) call set4%read_bitset(unit) call check(error, set4 == set0 .and. set5 == set1 .and. set3 == set2, & 'transfer to and from units using bitset literals failed.') if (.not.allocated(error)) then rewind( unit ) call set2%write_bitset(unit, advance='no') call set1%write_bitset(unit, advance='no') call set0%write_bitset(unit) rewind( unit ) call set3%read_bitset(unit, advance='no') call set4%read_bitset(unit, advance='no') call set5%read_bitset(unit) call check(error, set5 == set0 .and. set4 == set1 .and. set3 == set2, & 'transfer to and from units using bitset literals with advance="no" failed.') end if close(unit) if (allocated(error)) return open( newunit=unit, form='unformatted', status='scratch', & action='readwrite' ) call set2%output(unit) call set1%output(unit) call set0%output(unit) rewind( unit ) call set5%input(unit) call set4%input(unit) call set3%input(unit) close( unit ) call check(error, set3 == set0 .and. set4 == set1 .and. set5 == set2, & 'transfer to and from units using output and input failed.') if (allocated(error)) return open( newunit=unit, form='unformatted', access='stream', & status='scratch', action='readwrite' ) call set2%output(unit) call set1%output(unit) call set0%output(unit) rewind( unit ) call set5%input(unit) call set4%input(unit) call set3%input(unit) close( unit ) call check(error, set3 == set0 .and. set4 == set1 .and. set5 == set2, & 'transfer to and from units using stream output and input failed.') if (allocated(error)) return end subroutine test_io subroutine test_initialization(error) !> Error handling type(error_type), allocatable, intent(out) :: error logical(int8) :: log1(64) = .true. logical(int16) :: log2(31) = .false. logical(int32) :: log3(15) = .true. logical(int64) :: log4(33) = .false. logical(int8), allocatable :: log5(:) logical(int16), allocatable :: log6(:) logical(int32), allocatable :: log7(:) logical(int64), allocatable :: log8(:) type(bitset_64) :: set4, set5 !The following block triggers an issue in gfortran 11 and 12 block type(bitset_64) :: set6 call check(error, set6 % bits(), 0, & 'set6 % bits() returned non-zero value '//& 'even though set6 was not initialized.') if (allocated(error)) return end block set5 = log1 call check(error, set5%bits(), 64, & 'initialization with logical(int8) failed to set the right size.') if (allocated(error)) return call check(error, set5%all(), & 'initialization with logical(int8) failed to set the right values.') if (allocated(error)) return set5 = log2 call check(error, set5%bits(), 31, & 'initialization with logical(int16) failed to set the right size.') if (allocated(error)) return call check(error, set5%none(), & 'initialization with logical(int16) failed to set the right values.') if (allocated(error)) return set5 = log3 call check(error, set5%bits(), 15, & 'initialization with logical(int32) failed to set the right size.') if (allocated(error)) return call check(error, set5%all(), & 'initialization with logical(int32) failed to set the right values.') if (allocated(error)) return set5 = log4 call check(error, set5%bits(), 33, & 'initialization with logical(int64) failed to set the right size.') if (allocated(error)) return call check(error, set5%none(), & 'initialization with logical(int64) failed to set the right values.') if (allocated(error)) return set5 = log1 call extract( set4, set5, 1_bits_kind, 33_bits_kind ) call check(error, set4%bits(), 33, & 'initialization with extract failed to set the right size.') if (allocated(error)) return call check(error, set4%all(), & 'initialization with extract failed to set the right values.') if (allocated(error)) return set4 = set5 call check(error, set4%bits(), 64, & 'initialization with simple assignment failed to set the right size.') if (allocated(error)) return call check(error, set4%all(), & 'initialization with simple assignment failed to set the right values.') if (allocated(error)) return log5 = set5 call check(error, size(log5), 64, & 'initialization of logical(int8) with assignment failed to set the right size.') if (allocated(error)) return call check(error, all(log5) .eqv. .true., & ! FIXME 'initialization of logical(int8) with assignment failed to set the right values.') if (allocated(error)) return log6 = set5 call check(error, size(log6), 64, & 'initialization of logical(int16) with assignment failed to set the right size.') if (allocated(error)) return call check(error, all(log6) .eqv. .true., & ! FIXME 'initialization of logical(int16) with assignment failed to set the right values.') if (allocated(error)) return log7 = set5 call check(error, size(log7), 64, & 'initialization of logical(int32) with assignment failed to set the right size.') if (allocated(error)) return call check(error, all(log7), & 'initialization of logical(int32) with assignment failed to set the right values.') if (allocated(error)) return log8 = set5 call check(error, size(log8), 64, & 'initialization of logical(int64) with assignment failed to set the right size.') if (allocated(error)) return call check(error, merge(.true., .false., all(log8)), & ! FIXME 'initialization of logical(int64) with assignment failed to set the right values.') if (allocated(error)) return end subroutine test_initialization subroutine test_bitset_inquiry(error) !> Error handling type(error_type), allocatable, intent(out) :: error integer(bits_kind) :: i type(bitset_64) :: set0, set1 call set0%from_string(bitstring_0) call set1%from_string(bitstring_all) call check(error, set0%none(), 'set0 did not have none set which ' // & 'was unexpected') if (allocated(error)) return call check(error, .not. set0%any(), 'set0 had some bits set which ' // & 'was unexpected.') if (allocated(error)) return call set0%not() call check(error, set0%all(), 'set0 did not have all bits set ' // & 'which was unexpected') if (allocated(error)) return call check(error, set0%any(), 'set0 had no bits set which ' // & 'was unexpected.') if (allocated(error)) return call check(error, set1%any(), 'set1 had no bits set ' // & 'which was unexpected') if (allocated(error)) return call check(error, set1%all(), 'set1 did not have all bits set ' // & 'which was unexpected.') if (allocated(error)) return call set0%not() do i=0, set0%bits() - 1 call check(error, .not. set0%test(i), & 'against expectations set0 has at least 1 bit set.') end do do i=0, set1%bits() - 1 call check(error, set1%test(i), & 'against expectations set1 has at least 1 bit unset.') end do do i=0, set0%bits() - 1 call check(error, .not.( set0%value(i) /= 0), & 'against expectations set0 has at least 1 bit set.') end do do i=0, set1%bits() - 1 call check(error, .not.( set1%value(i) /= 1), & 'against expectations set1 has at least 1 bit unset.') end do call check(error, set0%bits() == 33, 'et0 unexpectedly does not have 33 bits.') if (allocated(error)) return end subroutine test_bitset_inquiry subroutine test_bit_operations(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_64) :: set1 call set1%from_string(bitstring_all) call check(error, set1%all(), 'set1 is not all set.') if (allocated(error)) return call set1%clear(0_bits_kind) call check(error, .not. set1%test(0_bits_kind), 'did not clear the first bit in set1.') if (allocated(error)) return call check(error, set1%test(1_bits_kind), 'cleared more than one bit in set1.') if (allocated(error)) return call set1%clear(1_bits_kind, 32_bits_kind) call check(error, set1%none(), 'did not clear remaining bits in set1.') if (allocated(error)) return call set1%flip(0_bits_kind) call check(error, set1%test(0_bits_kind), 'did not flip the first bit in set1.') if (allocated(error)) return call check(error, .not. set1%test(1_bits_kind), 'flipped more than one bit in set1.') if (allocated(error)) return call set1%flip(1_bits_kind, 32_bits_kind) call check(error, set1%all(), 'did not flip remaining bits in set1.') if (allocated(error)) return call set1%not() call check(error, set1%none(), 'did not unset bits in set1.') if (allocated(error)) return call set1%set(0_bits_kind) call check(error, set1%test(0_bits_kind), 'did not set the first bit in set1.') if (allocated(error)) return call check(error, .not. set1%test(1_bits_kind), 'set more than one bit in set1.') if (allocated(error)) return call set1%set(1_bits_kind, 32_bits_kind) call check(error, set1%all(), 'did not set the remaining bits in set1.') if (allocated(error)) return end subroutine test_bit_operations subroutine test_bitset_comparisons(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_64) :: set0, set1, set2 call set0%from_string(bitstring_0) call set1%from_string(bitstring_all) call set2%from_string(bitstring_33) call check(error, set0 == set0 .and. set1 == set1 .and. set2 == set2 .and. & .not. set0 == set1 .and. .not. set0 == set2 .and. .not. & set1 == set2, 'failed 64 bit equality tests.') if (allocated(error)) return call check(error, set0 /= set1 .and. set1 /= set2 .and. set0 /= set2 .and. & .not. set0 /= set0 .and. .not. set1 /= set1 .and. .not. & set2 /= set2, 'failed 64 bit inequality tests.') if (allocated(error)) return call check(error, set1 > set0 .and. set2 > set0 .and. set1 > set2 .and. & .not. set0 > set1 .and. .not. set1 > set1 .and. .not. & set2 > set1, 'failed 64 bit greater than tests.') if (allocated(error)) return call check(error, set1 >= set0 .and. set1 >= set2 .and. set2 >= set2 .and. & .not. set0 >= set1 .and. .not. set0 >= set1 .and. .not. & set2 >= set1, 'failed 64 bit greater than or equal tests.') if (allocated(error)) return call check(error, set0 < set1 .and. set0 < set1 .and. set2 < set1 .and. & .not. set1 < set0 .and. .not. set0 < set0 .and. .not. & set1 < set2, 'failed 64 bit less than tests.') if (allocated(error)) return call check(error, set0 <= set1 .and. set2 <= set1 .and. set2 <= set2 .and. & .not. set1 <= set0 .and. .not. set2 <= set0 .and. .not. & set1 <= set2, 'failed 64 bit less than or equal tests.') if (allocated(error)) return end subroutine test_bitset_comparisons subroutine test_bitset_operations_and(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_64) :: set3, set4, set0 call set0%from_string( bitstring_all ) call set4%from_string( bitstring_all ) call and( set0, set4 ) ! all all call check(error, set0%all(), 'first test of AND failed.') if (allocated(error)) return call set4%from_string( bitstring_0 ) call set3%from_string( bitstring_all ) call and( set3, set4 ) ! all none call check(error, set3%none(), 'second test of AND failed.') if (allocated(error)) return call set3%from_string( bitstring_all ) call set4%from_string( bitstring_0 ) call and( set4, set3 ) ! none all call check(error, set4%none(), 'third test of AND failed.') if (allocated(error)) return call set3%from_string( bitstring_0 ) call and( set4, set3 ) ! none none call check(error, set4%none(), 'fourth test of AND failed.') if (allocated(error)) return end subroutine test_bitset_operations_and subroutine test_bitset_operations_nand(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_64) :: set3, set4 call set3%from_string( bitstring_all ) call set4%from_string( bitstring_all ) call and_not( set4, set3 ) ! all all call check(error, set4%none(), 'first test of AND_NOT failed.') if (allocated(error)) return call set4%from_string( bitstring_0 ) call and_not( set4, set3 ) ! none all call check(error, set4%none(), 'second test of AND_NOT failed.') if (allocated(error)) return call set3%from_string( bitstring_all ) call set4%from_string( bitstring_0 ) call and_not( set3, set4 ) ! all none call check(error, set3%all(), 'third test of AND_NOT failed.') if (allocated(error)) return call set3%from_string( bitstring_0 ) call set4%from_string( bitstring_0 ) call and_not( set3, set4 ) ! none none call check(error, set3%none(), 'fourth test of AND_NOT failed.') if (allocated(error)) return end subroutine test_bitset_operations_nand subroutine test_bitset_operations_or(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_64) :: set3, set4 call set3%from_string( bitstring_all ) call set4%from_string( bitstring_all ) call or( set3, set4 ) ! all all call check(error, set3%all(), 'first test of OR failed.') if (allocated(error)) return call set3%from_string( bitstring_0 ) call or( set4, set3 ) ! all none call check(error, set4%all(), 'second test of OR failed.') if (allocated(error)) return call or( set3, set4 ) ! none all call check(error, set3%all(), 'third test of OR failed.') if (allocated(error)) return call set3%from_string( bitstring_0 ) call set4%from_string( bitstring_0 ) call or( set4, set3 ) !none none call check(error, set4%none(), 'fourth test of OR failed.') if (allocated(error)) return end subroutine test_bitset_operations_or subroutine test_bitset_operations_xor(error) !> Error handling type(error_type), allocatable, intent(out) :: error type(bitset_64) :: set3, set4 call set3%from_string( bitstring_0 ) call set4%from_string( bitstring_0 ) call xor( set3, set4 ) ! none none call check(error, set3%none(), 'first test of XOR failed.') if (allocated(error)) return call set4%from_string( bitstring_all ) call xor( set3, set4 ) ! none all call check(error, set3%all(), 'second test of XOR failed.') if (allocated(error)) return call set4%from_string( bitstring_0 ) call xor( set3, set4 ) ! all none call check(error, set3%all(), 'third test of XOR failed.') if (allocated(error)) return call set4%from_string( bitstring_all ) call xor( set3, set4 ) ! all all call check(error, set3%none(), 'fourth test of XOR failed.') if (allocated(error)) return end subroutine test_bitset_operations_xor end module test_stdlib_bitset_64 program tester use, intrinsic :: iso_fortran_env, only : error_unit use testdrive, only : run_testsuite, new_testsuite, testsuite_type use test_stdlib_bitset_64, only : collect_stdlib_bitset_64 implicit none integer :: stat, is type(testsuite_type), allocatable :: testsuites(:) character(len=*), parameter :: fmt = '("#", *(1x, a))' stat = 0 testsuites = [ & new_testsuite("stdlib-bitset-64", collect_stdlib_bitset_64) & ] do is = 1, size(testsuites) write(error_unit, fmt) "Testing:", testsuites(is)%name call run_testsuite(testsuites(is)%collect, error_unit, stat) end do if (stat > 0) then write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" error stop end if end program fortran-lang-stdlib-0ede301/src/0000775000175000017500000000000015135654166016755 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/linalg_core/0000775000175000017500000000000015135654166021233 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/linalg_core/stdlib_linalg_state.fypp0000664000175000017500000001311715135654166026145 0ustar alastairalastair#:include "common.fypp" #:set KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES + CMPLX_KINDS_TYPES module stdlib_linalg_state !! Version: experimental !! !! Provides a state/error handling derived type for advanced error handling of !! BLAS/LAPACK based linear algebra procedures. All procedures are pure. !! ([Specification](../page/specs/stdlib_linalg.html)) use stdlib_linalg_constants,only: ilp use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp, lk use stdlib_error, only: state_type, operator(==), operator(/=), operator(<), operator(>), & operator(<=), operator(>=), STDLIB_SUCCESS, STDLIB_VALUE_ERROR, STDLIB_LINALG_ERROR, STDLIB_INTERNAL_ERROR use stdlib_io_aux, only: FMT_REAL_SP, FMT_REAL_DP, FMT_REAL_QP, FMT_COMPLEX_SP, FMT_COMPLEX_DP, & FMT_COMPLEX_QP, FMT_REAL_XDP, FMT_COMPLEX_XDP implicit none private !> Version: experimental !> !> A fixed-storage state variable for error handling of linear algebra routines public :: linalg_state_type !> Version: experimental !> !> Error state handling: if the user requested the error state variable on !> output, just return it to the user. Otherwise, halt the program on error. public :: linalg_error_handling !> Version: experimental !> !> Interfaces for comparison operators of error states with integer flags public :: operator(==),operator(/=) public :: operator(<),operator(<=) public :: operator(>),operator(>=) !> State return types for linear algebra integer(ilp),parameter,public :: LINALG_SUCCESS = STDLIB_SUCCESS integer(ilp),parameter,public :: LINALG_VALUE_ERROR = STDLIB_VALUE_ERROR integer(ilp),parameter,public :: LINALG_ERROR = STDLIB_LINALG_ERROR integer(ilp),parameter,public :: LINALG_INTERNAL_ERROR = STDLIB_INTERNAL_ERROR !> `linalg_state_type` defines a state return type for a !> linear algebra routine. State contains a status flag, a comment, and a !> procedure specifier that can be used to mark where the error happened type, extends(state_type) :: linalg_state_type contains !> Print error message procedure :: print_msg => state_message end type linalg_state_type interface linalg_state_type module procedure new_state module procedure new_state_nowhere end interface linalg_state_type contains !> Interface to print linalg state flags pure function linalg_message(flag) result(msg) integer(ilp),intent(in) :: flag character(len=:),allocatable :: msg select case (flag) case (LINALG_SUCCESS); msg = 'Success!' case (LINALG_VALUE_ERROR); msg = 'Value Error' case (LINALG_ERROR); msg = 'Algebra Error' case (LINALG_INTERNAL_ERROR); msg = 'Internal Error' case default; msg = 'ERROR/INVALID FLAG' end select end function linalg_message !> Flow control: on output flag present, return it; otherwise, halt on error pure subroutine linalg_error_handling(ierr,ierr_out) type(linalg_state_type),intent(in) :: ierr type(linalg_state_type),optional,intent(out) :: ierr_out character(len=:),allocatable :: err_msg if (present(ierr_out)) then ! Return error flag ierr_out = ierr elseif (ierr%error()) then err_msg = ierr%print() error stop err_msg end if end subroutine linalg_error_handling !> Formatted message pure function state_message(this) result(msg) class(linalg_state_type),intent(in) :: this character(len=:),allocatable :: msg if (this%state == LINALG_SUCCESS) then msg = 'Success!' else msg = linalg_message(this%state)//': '//trim(this%message) end if end function state_message !> Error creation message, with location location pure type(linalg_state_type) function new_state(where_at,flag,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) !> Location character(len=*),intent(in) :: where_at !> Input error flag integer,intent(in) :: flag !> Optional rank-agnostic arguments class(*),optional,intent(in),dimension(..) :: a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20 ! Init object call new_state%parse(where_at,flag,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) end function new_state !> Error creation message, from N input variables (numeric or strings) pure type(linalg_state_type) function new_state_nowhere(flag,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) & result(new_state) !> Input error flag integer,intent(in) :: flag !> Optional rank-agnostic arguments class(*),optional,intent(in),dimension(..) :: a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20 ! Init object call new_state%parse(flag,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) end function new_state_nowhere end module stdlib_linalg_state fortran-lang-stdlib-0ede301/src/linalg_core/stdlib_linalg_constants.fypp0000664000175000017500000000275715135654166027051 0ustar alastairalastair#:include "common.fypp" module stdlib_linalg_constants use stdlib_kinds, only: sp, dp, xdp, qp, int32, int64, lk use, intrinsic :: ieee_arithmetic, only: ieee_is_nan !$ use omp_lib implicit none public ! Checks whether BLAS is provided by an external library #ifdef STDLIB_EXTERNAL_BLAS logical(lk), parameter :: external_blas_ilp32 = .true._lk #else logical(lk), parameter :: external_blas_ilp32 = .false._lk #endif #ifdef STDLIB_EXTERNAL_BLAS_I64 logical(lk), parameter :: external_blas_ilp64 = .true._lk #else logical(lk), parameter :: external_blas_ilp64 = .false._lk #endif #ifdef STDLIB_EXTERNAL_LAPACK logical(lk), parameter :: external_lapack_ilp32 = .true._lk #else logical(lk), parameter :: external_lapack_ilp32 = .false._lk #endif #ifdef STDLIB_EXTERNAL_LAPACK_I64 logical(lk), parameter :: external_lapack_ilp64 = .true._lk #else logical(lk), parameter :: external_lapack_ilp64 = .false._lk #endif ! Generic checks for external libraries logical(lk), parameter :: external_blas = external_blas_ilp32 .or. external_blas_ilp64 logical(lk), parameter :: external_lapack = external_lapack_ilp32 .or. external_lapack_ilp64 ! Support both 32-bit (ilp) and 64-bit (ilp64) integer kinds integer, parameter :: ilp = int32 integer, parameter :: ilp64 = #{if WITH_ILP64}# int64 #{else}# -1 #{endif}# private :: int32, int64 end module stdlib_linalg_constants fortran-lang-stdlib-0ede301/src/linalg_core/CMakeLists.txt0000664000175000017500000000054215135654166023774 0ustar alastairalastairset(linalg_core_fppFiles stdlib_linalg_state.fypp ) set(linalg_core_cppFiles stdlib_linalg_constants.fypp ) set(linalg_core_f90Files ) configure_stdlib_target(${PROJECT_NAME}_linalg_core linalg_core_f90Files linalg_core_fppFiles linalg_core_cppFiles) target_link_libraries(${PROJECT_NAME}_linalg_core PUBLIC ${PROJECT_NAME}_core) fortran-lang-stdlib-0ede301/src/stdlib_version.fypp0000664000175000017500000000354115135654166022706 0ustar alastairalastair! SPDX-Identifier: MIT #:include "common.fypp" !> Version information on stdlib module stdlib_version implicit none private public :: get_stdlib_version public :: stdlib_version_string, stdlib_version_compact !> String representation of the standard library version character(len=*), parameter :: stdlib_version_string = "${PROJECT_VERSION}$" !> Major version number of the above standard library version integer, parameter :: stdlib_major = ${PROJECT_VERSION_MAJOR}$ !> Minor version number of the above standard library version integer, parameter :: stdlib_minor = ${PROJECT_VERSION_MINOR}$ !> Patch version number of the above standard library version integer, parameter :: stdlib_patch = ${PROJECT_VERSION_PATCH}$ !> Compact numeric representation of the standard library version integer, parameter :: stdlib_version_compact = & & stdlib_major*10000 + stdlib_minor*100 + stdlib_patch contains !> Getter function to retrieve standard library version pure subroutine get_stdlib_version(major, minor, patch, string) !> Major version number of the standard library version integer, intent(out), optional :: major !> Minor version number of the standard library version integer, intent(out), optional :: minor !> Patch version number of the standard library version integer, intent(out), optional :: patch !> String representation of the standard library version character(len=:), allocatable, intent(out), optional :: string if (present(major)) then major = stdlib_major end if if (present(minor)) then minor = stdlib_minor end if if (present(patch)) then patch = stdlib_patch end if if (present(string)) then string = stdlib_version_string end if end subroutine get_stdlib_version end module stdlib_version fortran-lang-stdlib-0ede301/src/lapack_extended/0000775000175000017500000000000015135654166022070 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/lapack_extended/stdlib_lapack_extended.fypp0000664000175000017500000000673115135654166027453 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set KINDS_TYPES = R_KINDS_TYPES+C_KINDS_TYPES submodule(stdlib_lapack_extended_base) stdlib_lapack_extended implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES #:for k1,t1,s1 in KINDS_TYPES pure module subroutine stdlib${ii}$_glagtm_${s1}$(trans, n, nrhs, alpha, dl, d, du, x, ldx, beta, b, ldb) character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ${t1}$, intent(in) :: alpha, beta ${t1}$, intent(inout) :: b(ldb,*) ${t1}$, intent(in) :: d(*), dl(*), du(*), x(ldx,*) ! Internal variables. integer(${ik}$) :: i, j ${t1}$ :: temp if(n == 0) then return endif if(beta == 0.0_${k1}$) then b(1:n, 1:nrhs) = 0.0_${k1}$ else b(1:n, 1:nrhs) = beta * b(1:n, 1:nrhs) end if if(trans == 'N') then do j = 1, nrhs if(n == 1_${ik}$) then temp = d(1_${ik}$) * x(1_${ik}$, j) b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp else temp = d(1_${ik}$) * x(1_${ik}$, j) + du(1_${ik}$) * x(2_${ik}$, j) b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp do i = 2, n - 1 temp = dl(i - 1) * x(i - 1, j) + d(i) * x(i, j) + du(i) * x(i + 1, j) b(i, j) = b(i, j) + alpha * temp end do temp = dl(n - 1) * x(n - 1, j) + d(n) * x(n, j) b(n, j) = b(n, j) + alpha * temp end if end do #:if t1.startswith('complex') else if(trans == 'C') then do j = 1, nrhs if(n == 1_${ik}$) then temp = conjg(d(1_${ik}$)) * x(1_${ik}$, j) b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp else temp = conjg(d(1_${ik}$)) * x(1_${ik}$, j) + conjg(dl(1_${ik}$)) * x(2_${ik}$, j) b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp do i = 2, n - 1 temp = conjg(du(i - 1)) * x(i - 1, j) + conjg(d(i)) * x(i, j) + conjg(dl(i)) * x(i + 1, j) b(i, j) = b(i, j) + alpha * temp end do temp = conjg(du(n - 1)) * x(n - 1, j) + conjg(d(n)) * x(n, j) b(n, j) = b(n, j) + alpha * temp end if end do #:endif else do j = 1, nrhs if(n == 1_${ik}$) then temp = d(1_${ik}$) * x(1_${ik}$, j) b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp else temp = d(1_${ik}$) * x(1_${ik}$, j) + dl(1_${ik}$) * x(2_${ik}$, j) b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp do i = 2, n - 1 temp = du(i - 1) * x(i - 1, j) + d(i) * x(i, j) + dl(i) * x(i + 1, j) b(i, j) = b(i, j) + alpha * temp end do temp = du(n - 1) * x(n - 1, j) + d(n) * x(n, j) b(n, j) = b(n, j) + alpha * temp end if end do end if end subroutine stdlib${ii}$_glagtm_${s1}$ #:endfor #:endfor end submodulefortran-lang-stdlib-0ede301/src/lapack_extended/CMakeLists.txt0000664000175000017500000000054215135654166024631 0ustar alastairalastairset(lapack_extended_fppFiles stdlib_lapack_extended_base.fypp stdlib_lapack_extended.fypp ) set(lapack_extended_cppFiles ) configure_stdlib_target(${PROJECT_NAME}_lapack_extended "" lapack_extended_fppFiles lapack_extended_cppFiles) target_link_libraries(${PROJECT_NAME}_lapack_extended PUBLIC ${PROJECT_NAME}_core ${PROJECT_NAME}_linalg_core) fortran-lang-stdlib-0ede301/src/lapack_extended/stdlib_lapack_extended_base.fypp0000664000175000017500000000155415135654166030443 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set KINDS_TYPES = R_KINDS_TYPES+C_KINDS_TYPES module stdlib_lapack_extended_base use stdlib_linalg_constants implicit none interface glagtm #:for ik,it,ii in LINALG_INT_KINDS_TYPES #:for k1,t1,s1 in KINDS_TYPES pure module subroutine stdlib${ii}$_glagtm_${s1}$(trans, n, nrhs, alpha, dl, d, du, x, ldx, beta, b, ldb) character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ${t1}$, intent(in) :: alpha, beta ${t1}$, intent(inout) :: b(ldb,*) ${t1}$, intent(in) :: d(*), dl(*), du(*), x(ldx,*) end subroutine stdlib${ii}$_glagtm_${s1}$ #:endfor #:endfor end interface end modulefortran-lang-stdlib-0ede301/src/stringlist/0000775000175000017500000000000015135654166021157 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/stringlist/stdlib_stringlist_type.f900000664000175000017500000006643015135654166026314 0ustar alastairalastair! stdlib_stringlist_type.f90 -- ! Module for storing and manipulating list of strings ! The strings may have arbitrary lengths, not necessarily the same ! ! insert AT: Inserts an element BEFORE the element present currently at the asked index ! for forward indexes ! Inserts an element AFTER the element present currently at the asked index ! for backward indexes ! In other words, after insertion the element will be present at the asked index ! for both forward and backward indexes ! insert BEFORE: Inserts an element BEFORE the element present currently at the asked index ! insert AFTER: Inserts an element AFTER the element present currently at the asked index ! ! Note the distinction between AT and BEFORE in the module. Care has been taken to keep it consistent ! throughout the PR ! module stdlib_stringlist_type use stdlib_string_type, only: string_type, operator(/=) use stdlib_math, only: clip implicit none private public :: stringlist_type, operator(//), operator(==), operator(/=) public :: list_head, list_tail, fidx, bidx, stringlist_index_type type stringlist_index_type private logical :: forward integer :: offset end type stringlist_index_type type(stringlist_index_type), parameter :: list_head = stringlist_index_type( .true. , 1 ) ! fidx(1) type(stringlist_index_type), parameter :: list_tail = stringlist_index_type( .false., 1 ) ! bidx(1) !> Version: experimental !> !> Returns an instance of type 'stringlist_index_type' representing forward index !> [Specifications](../page/specs/stdlib_stringlist_type.html#fidx) interface fidx module procedure forward_index end interface !> Version: experimental !> !> Returns an instance of type 'stringlist_index_type' representing backward index !> [Specifications](../page/specs/stdlib_stringlist_type.html#bidx) interface bidx module procedure backward_index end interface type stringlist_type private type(string_type), dimension(:), allocatable :: stringarray contains private procedure, public :: clear => clear_list procedure, public :: len => length_list procedure :: to_future_at_idxn => convert_to_future_at_idxn procedure :: to_current_idxn => convert_to_current_idxn procedure :: insert_at_char_idx => insert_at_char_idx_wrap procedure :: insert_at_string_idx => insert_at_string_idx_wrap procedure :: insert_at_stringlist_idx => insert_at_stringlist_idx_wrap procedure :: insert_at_chararray_idx => insert_at_chararray_idx_wrap procedure :: insert_at_stringarray_idx => insert_at_stringarray_idx_wrap generic, public :: insert_at => insert_at_char_idx, & insert_at_string_idx, & insert_at_stringlist_idx, & insert_at_chararray_idx, & insert_at_stringarray_idx procedure :: insert_before_string_int => insert_before_string_int_impl procedure :: insert_before_stringlist_int => insert_before_stringlist_int_impl procedure :: insert_before_chararray_int => insert_before_chararray_int_impl procedure :: insert_before_stringarray_int => insert_before_stringarray_int_impl generic :: insert_before => insert_before_string_int, & insert_before_stringlist_int, & insert_before_chararray_int, & insert_before_stringarray_int procedure :: get_string_idx => get_string_idx_wrap generic, public :: get => get_string_idx end type stringlist_type !> Version: experimental !> !> Constructor for stringlist !> Returns an instance of type stringlist_type !> [Specifications](../page/specs/stdlib_stringlist_type.html#stringlist_type) interface stringlist_type module procedure new_stringlist module procedure new_stringlist_carray module procedure new_stringlist_sarray end interface !> Version: experimental !> !> Concatenates stringlist with the input entity !> Returns a new stringlist !> [Specifications](../page/specs/stdlib_stringlist_type.html#append-operator) interface operator(//) module procedure append_char module procedure append_string module procedure prepend_char module procedure prepend_string module procedure append_stringlist module procedure append_carray module procedure append_sarray module procedure prepend_carray module procedure prepend_sarray end interface !> Version: experimental !> !> Compares stringlist for equality with the input entity !> Returns a logical !> [Specifications](../page/specs/stdlib_stringlist_type.html#equality-operator) interface operator(==) module procedure eq_stringlist module procedure eq_stringlist_carray module procedure eq_stringlist_sarray module procedure eq_carray_stringlist module procedure eq_sarray_stringlist end interface !> Version: experimental !> !> Compares stringlist for inequality with the input entity !> Returns a logical !> [Specifications](../page/specs/stdlib_stringlist_type.html#inequality-operator) interface operator(/=) module procedure ineq_stringlist module procedure ineq_stringlist_carray module procedure ineq_stringlist_sarray module procedure ineq_carray_stringlist module procedure ineq_sarray_stringlist end interface contains ! constructor for stringlist_type: !> Constructor with no argument !> Returns a new instance of type stringlist pure function new_stringlist() type(stringlist_type) :: new_stringlist end function new_stringlist !> Constructor to convert chararray to stringlist !> Returns a new instance of type stringlist pure function new_stringlist_carray( array ) character(len=*), dimension(:), intent(in) :: array type(stringlist_type) :: new_stringlist_carray type(string_type), dimension( size(array) ) :: sarray integer :: i do i = 1, size(array) sarray(i) = string_type( array(i) ) end do new_stringlist_carray = stringlist_type( sarray ) end function new_stringlist_carray !> Constructor to convert stringarray to stringlist !> Returns a new instance of type stringlist pure function new_stringlist_sarray( array ) type(string_type), dimension(:), intent(in) :: array type(stringlist_type) :: new_stringlist_sarray new_stringlist_sarray = stringlist_type() new_stringlist_sarray%stringarray = array end function new_stringlist_sarray ! constructor for stringlist_index_type: !> Returns an instance of type 'stringlist_index_type' representing forward index 'idx' pure function forward_index( idx ) integer, intent(in) :: idx type(stringlist_index_type) :: forward_index forward_index = stringlist_index_type( .true., idx ) end function forward_index !> Returns an instance of type 'stringlist_index_type' representing backward index 'idx' pure function backward_index( idx ) integer, intent(in) :: idx type(stringlist_index_type) :: backward_index backward_index = stringlist_index_type( .false., idx ) end function backward_index ! concatenation operator: !> Appends character scalar 'rhs' to the stringlist 'list' !> Returns a new stringlist function append_char( lhs, rhs ) type(stringlist_type), intent(in) :: lhs character(len=*), intent(in) :: rhs type(stringlist_type) :: append_char append_char = lhs // string_type( rhs ) end function append_char !> Appends string 'rhs' to the stringlist 'list' !> Returns a new stringlist function append_string( lhs, rhs ) type(stringlist_type), intent(in) :: lhs type(string_type), intent(in) :: rhs type(stringlist_type) :: append_string append_string = lhs ! Intent: creating a full, deep copy call append_string%insert_at( list_tail, rhs ) end function append_string !> Prepends character scalar 'lhs' to the stringlist 'rhs' !> Returns a new stringlist function prepend_char( lhs, rhs ) character(len=*), intent(in) :: lhs type(stringlist_type), intent(in) :: rhs type(stringlist_type) :: prepend_char prepend_char = string_type( lhs ) // rhs end function prepend_char !> Prepends string 'lhs' to the stringlist 'rhs' !> Returns a new stringlist function prepend_string( lhs, rhs ) type(string_type), intent(in) :: lhs type(stringlist_type), intent(in) :: rhs type(stringlist_type) :: prepend_string prepend_string = rhs ! Intent: creating a full, deep copy call prepend_string%insert_at( list_head, lhs ) end function prepend_string !> Appends stringlist 'rhs' to the stringlist 'lhs' !> Returns a new stringlist function append_stringlist( lhs, rhs ) type(stringlist_type), intent(in) :: lhs type(stringlist_type), intent(in) :: rhs type(stringlist_type) :: append_stringlist append_stringlist = lhs ! Intent: creating a full, deep copy call append_stringlist%insert_at( list_tail, rhs ) end function append_stringlist !> Appends chararray 'rhs' to the stringlist 'lhs' !> Returns a new stringlist function append_carray( lhs, rhs ) type(stringlist_type), intent(in) :: lhs character(len=*), dimension(:), intent(in) :: rhs type(stringlist_type) :: append_carray append_carray = lhs ! Intent: creating a full, deep copy call append_carray%insert_at( list_tail, rhs ) end function append_carray !> Appends stringarray 'rhs' to the stringlist 'lhs' !> Returns a new stringlist function append_sarray( lhs, rhs ) type(stringlist_type), intent(in) :: lhs type(string_type), dimension(:), intent(in) :: rhs type(stringlist_type) :: append_sarray append_sarray = lhs ! Intent: creating a full, deep copy call append_sarray%insert_at( list_tail, rhs ) end function append_sarray !> Prepends chararray 'lhs' to the stringlist 'rhs' !> Returns a new stringlist function prepend_carray( lhs, rhs ) character(len=*), dimension(:), intent(in) :: lhs type(stringlist_type), intent(in) :: rhs type(stringlist_type) :: prepend_carray prepend_carray = rhs ! Intent: creating a full, deep copy call prepend_carray%insert_at( list_head, lhs ) end function prepend_carray !> Prepends stringarray 'lhs' to the stringlist 'rhs' !> Returns a new stringlist function prepend_sarray( lhs, rhs ) type(string_type), dimension(:), intent(in) :: lhs type(stringlist_type), intent(in) :: rhs type(stringlist_type) :: prepend_sarray prepend_sarray = rhs ! Intent: creating a full, deep copy call prepend_sarray%insert_at( list_head, lhs ) end function prepend_sarray ! equality operator: !> Compares stringlist 'lhs' for equality with stringlist 'rhs' !> Returns a logical pure logical function eq_stringlist( lhs, rhs ) type(stringlist_type), intent(in) :: lhs type(stringlist_type), intent(in) :: rhs integer :: i eq_stringlist = .false. if ( lhs%len() == rhs%len() ) then eq_stringlist = .true. do i = 1, lhs%len() if ( lhs%stringarray(i) /= rhs%stringarray(i) ) then eq_stringlist = .false. exit end if end do end if end function eq_stringlist !> Compares stringlist 'lhs' for equality with chararray 'rhs' !> Returns a logical pure logical function eq_stringlist_carray( lhs, rhs ) type(stringlist_type), intent(in) :: lhs character(len=*), dimension(:), intent(in) :: rhs integer :: i eq_stringlist_carray = .false. if ( lhs%len() == size( rhs ) ) then eq_stringlist_carray = .true. do i = 1, lhs%len() if ( lhs%stringarray(i) /= rhs(i) ) then eq_stringlist_carray = .false. exit end if end do end if end function eq_stringlist_carray !> Compares stringlist 'lhs' for equality with stringarray 'rhs' !> Returns a logical pure logical function eq_stringlist_sarray( lhs, rhs ) type(stringlist_type), intent(in) :: lhs type(string_type), dimension(:), intent(in) :: rhs integer :: i eq_stringlist_sarray = .false. if ( lhs%len() == size( rhs ) ) then eq_stringlist_sarray = .true. do i = 1, lhs%len() if ( lhs%stringarray(i) /= rhs(i) ) then eq_stringlist_sarray = .false. exit end if end do end if end function eq_stringlist_sarray !> Compares chararray 'lhs' for equality with stringlist 'rhs' !> Returns a logical pure logical function eq_carray_stringlist( lhs, rhs ) character(len=*), dimension(:), intent(in) :: lhs type(stringlist_type), intent(in) :: rhs eq_carray_stringlist = ( rhs == lhs ) end function eq_carray_stringlist !> Compares stringarray 'lhs' for equality with stringlist 'rhs' !> Returns a logical pure logical function eq_sarray_stringlist( lhs, rhs ) type(string_type), dimension(:), intent(in) :: lhs type(stringlist_type), intent(in) :: rhs eq_sarray_stringlist = ( rhs == lhs ) end function eq_sarray_stringlist ! inequality operator: !> Compares stringlist 'lhs' for inequality with stringlist 'rhs' !> Returns a logical pure logical function ineq_stringlist( lhs, rhs ) type(stringlist_type), intent(in) :: lhs type(stringlist_type), intent(in) :: rhs ineq_stringlist = .not.( lhs == rhs ) end function ineq_stringlist !> Compares stringlist 'lhs' for inequality with chararray 'rhs' !> Returns a logical pure logical function ineq_stringlist_carray( lhs, rhs ) type(stringlist_type), intent(in) :: lhs character(len=*), dimension(:), intent(in) :: rhs ineq_stringlist_carray = .not.( lhs == rhs ) end function ineq_stringlist_carray !> Compares stringlist 'lhs' for inequality with stringarray 'rhs' !> Returns a logical pure logical function ineq_stringlist_sarray( lhs, rhs ) type(stringlist_type), intent(in) :: lhs type(string_type), dimension(:), intent(in) :: rhs ineq_stringlist_sarray = .not.( lhs == rhs ) end function ineq_stringlist_sarray !> Compares chararray 'lhs' for inequality with stringlist 'rhs' !> Returns a logical pure logical function ineq_carray_stringlist( lhs, rhs ) character(len=*), dimension(:), intent(in) :: lhs type(stringlist_type), intent(in) :: rhs ineq_carray_stringlist = .not.( lhs == rhs) end function ineq_carray_stringlist !> Compares stringarray 'lhs' for inequality with stringlist 'rhs' !> Returns a logical pure logical function ineq_sarray_stringlist( lhs, rhs ) type(string_type), dimension(:), intent(in) :: lhs type(stringlist_type), intent(in) :: rhs ineq_sarray_stringlist = .not.( lhs == rhs ) end function ineq_sarray_stringlist ! clear: !> Version: experimental !> !> Resets stringlist 'list' to an empy stringlist of len 0 !> Modifies the input stringlist 'list' subroutine clear_list( list ) class(stringlist_type), intent(inout) :: list if ( allocated( list%stringarray ) ) then deallocate( list%stringarray ) end if end subroutine clear_list ! len: !> Version: experimental !> !> Returns the len (length) of the list !> Returns an integer pure integer function length_list( list ) class(stringlist_type), intent(in) :: list length_list = 0 if ( allocated( list%stringarray ) ) then length_list = size( list%stringarray ) end if end function length_list ! to_future_at_idxn: !> Version: experimental !> !> Converts a forward index OR a backward index to an integer index at !> which the new element will be present post insertion (i.e. in future) !> Returns an integer pure integer function convert_to_future_at_idxn( list, idx ) !> Not a part of public API class(stringlist_type), intent(in) :: list type(stringlist_index_type), intent(in) :: idx ! Formula: merge( fidx( x ) - ( list_head - 1 ), len - bidx( x ) + ( list_tail - 1 ) + 2, ... ) convert_to_future_at_idxn = merge( idx%offset, list%len() - idx%offset + 2 , idx%forward ) end function convert_to_future_at_idxn ! to_current_idxn: !> Version: experimental !> !> Converts a forward index OR backward index to its equivalent integer index idxn !> Returns an integer pure integer function convert_to_current_idxn( list, idx ) !> Not a part of public API class(stringlist_type), intent(in) :: list type(stringlist_index_type), intent(in) :: idx ! Formula: merge( fidx( x ) - ( list_head - 1 ), len + 1 - bidx( x ) + ( list_tail - 1 ), ... ) convert_to_current_idxn = merge( idx%offset, list%len() - idx%offset + 1, idx%forward ) end function convert_to_current_idxn ! insert_at: !> Version: experimental !> !> Inserts character scalar 'string' AT stringlist_index 'idx' in stringlist 'list' !> Modifies the input stringlist 'list' subroutine insert_at_char_idx_wrap( list, idx, string ) class(stringlist_type), intent(inout) :: list type(stringlist_index_type), intent(in) :: idx character(len=*), intent(in) :: string call list%insert_at( idx, string_type( string ) ) end subroutine insert_at_char_idx_wrap !> Version: experimental !> !> Inserts string 'string' AT stringlist_index 'idx' in stringlist 'list' !> Modifies the input stringlist 'list' subroutine insert_at_string_idx_wrap( list, idx, string ) class(stringlist_type), intent(inout) :: list type(stringlist_index_type), intent(in) :: idx type(string_type), intent(in) :: string call list%insert_before( list%to_future_at_idxn( idx ), string ) end subroutine insert_at_string_idx_wrap !> Version: experimental !> !> Inserts stringlist 'slist' AT stringlist_index 'idx' in stringlist 'list' !> Modifies the input stringlist 'list' subroutine insert_at_stringlist_idx_wrap( list, idx, slist ) class(stringlist_type), intent(inout) :: list type(stringlist_index_type), intent(in) :: idx type(stringlist_type), intent(in) :: slist call list%insert_before( list%to_future_at_idxn( idx ), slist ) end subroutine insert_at_stringlist_idx_wrap !> Version: experimental !> !> Inserts chararray 'carray' AT stringlist_index 'idx' in stringlist 'list' !> Modifies the input stringlist 'list' subroutine insert_at_chararray_idx_wrap( list, idx, carray ) class(stringlist_type), intent(inout) :: list type(stringlist_index_type), intent(in) :: idx character(len=*), dimension(:), intent(in) :: carray call list%insert_before( list%to_future_at_idxn( idx ), carray ) end subroutine insert_at_chararray_idx_wrap !> Version: experimental !> !> Inserts stringarray 'sarray' AT stringlist_index 'idx' in stringlist 'list' !> Modifies the input stringlist 'list' subroutine insert_at_stringarray_idx_wrap( list, idx, sarray ) class(stringlist_type), intent(inout) :: list type(stringlist_index_type), intent(in) :: idx type(string_type), dimension(:), intent(in) :: sarray call list%insert_before( list%to_future_at_idxn( idx ), sarray ) end subroutine insert_at_stringarray_idx_wrap !> Version: experimental !> !> Inserts 'positions' number of empty positions BEFORE integer index 'idxn' !> Modifies the input stringlist 'list' subroutine insert_before_empty_positions( list, idxn, positions ) !> Not a part of public API class(stringlist_type), intent(inout) :: list integer, intent(inout) :: idxn integer, intent(in) :: positions integer :: i, inew integer :: new_len, old_len type(string_type), dimension(:), allocatable :: new_stringarray if (positions > 0) then idxn = clip( idxn, 1, list%len() + 1 ) old_len = list%len() new_len = old_len + positions allocate( new_stringarray(new_len) ) do i = 1, idxn - 1 ! TODO: can be improved by move new_stringarray(i) = list%stringarray(i) end do do i = idxn, old_len inew = i + positions ! TODO: can be improved by move new_stringarray(inew) = list%stringarray(i) end do call move_alloc( new_stringarray, list%stringarray ) end if end subroutine insert_before_empty_positions !> Version: experimental !> !> Inserts string 'string' BEFORE integer index 'idxn' in the underlying stringarray !> Modifies the input stringlist 'list' subroutine insert_before_string_int_impl( list, idxn, string ) !> Not a part of public API class(stringlist_type), intent(inout) :: list integer, intent(in) :: idxn type(string_type), intent(in) :: string integer :: work_idxn work_idxn = idxn call insert_before_empty_positions( list, work_idxn, 1 ) list%stringarray(work_idxn) = string end subroutine insert_before_string_int_impl !> Version: experimental !> !> Inserts stringlist 'slist' BEFORE integer index 'idxn' in the underlying stringarray !> Modifies the input stringlist 'list' subroutine insert_before_stringlist_int_impl( list, idxn, slist ) !> Not a part of public API class(stringlist_type), intent(inout) :: list integer, intent(in) :: idxn type(stringlist_type), intent(in) :: slist integer :: i integer :: work_idxn, idxnew integer :: pre_length, post_length work_idxn = idxn pre_length = slist%len() call insert_before_empty_positions( list, work_idxn, pre_length ) post_length = slist%len() do i = 1, min( work_idxn - 1, pre_length ) idxnew = work_idxn + i - 1 list%stringarray(idxnew) = slist%stringarray(i) end do do i = work_idxn + post_length - pre_length, post_length idxnew = work_idxn + i - post_length + pre_length - 1 list%stringarray(idxnew) = slist%stringarray(i) end do end subroutine insert_before_stringlist_int_impl !> Version: experimental !> !> Inserts chararray 'carray' BEFORE integer index 'idxn' in the underlying stringarray !> Modifies the input stringlist 'list' subroutine insert_before_chararray_int_impl( list, idxn, carray ) !> Not a part of public API class(stringlist_type), intent(inout) :: list integer, intent(in) :: idxn character(len=*), dimension(:), intent(in) :: carray integer :: i integer :: work_idxn, idxnew work_idxn = idxn call insert_before_empty_positions( list, work_idxn, size( carray ) ) do i = 1, size( carray ) idxnew = work_idxn + i - 1 list%stringarray(idxnew) = string_type( carray(i) ) end do end subroutine insert_before_chararray_int_impl !> Version: experimental !> !> Inserts stringarray 'sarray' BEFORE integer index 'idxn' in the underlying stringarray !> Modifies the input stringlist 'list' subroutine insert_before_stringarray_int_impl( list, idxn, sarray ) !> Not a part of public API class(stringlist_type), intent(inout) :: list integer, intent(in) :: idxn type(string_type), dimension(:), intent(in) :: sarray integer :: i integer :: work_idxn, idxnew work_idxn = idxn call insert_before_empty_positions( list, work_idxn, size( sarray ) ) do i = 1, size( sarray ) idxnew = work_idxn + i - 1 list%stringarray(idxnew) = sarray(i) end do end subroutine insert_before_stringarray_int_impl ! get: !> Version: experimental !> !> Returns the string present at stringlist_index 'idx' in stringlist 'list' !> Returns string_type instance pure function get_string_idx_wrap( list, idx ) class(stringlist_type), intent(in) :: list type(stringlist_index_type), intent(in) :: idx type(string_type) :: get_string_idx_wrap integer :: idxn idxn = list%to_current_idxn( idx ) ! if the index is out of bounds, return a string_type equivalent to empty string if ( 1 <= idxn .and. idxn <= list%len() ) then get_string_idx_wrap = list%stringarray(idxn) end if end function get_string_idx_wrap end module stdlib_stringlist_type fortran-lang-stdlib-0ede301/src/stringlist/CMakeLists.txt0000664000175000017500000000052315135654166023717 0ustar alastairalastairset(stringlist_fppFiles ) set(stringlist_cppFiles ) set(stringlist_f90Files stdlib_stringlist_type.f90 ) configure_stdlib_target(${PROJECT_NAME}_stringlist stringlist_f90Files stringlist_fppFiles stringlist_cppFiles) target_link_libraries(${PROJECT_NAME}_stringlist PUBLIC ${PROJECT_NAME}_math ${PROJECT_NAME}_strings) fortran-lang-stdlib-0ede301/src/logger/0000775000175000017500000000000015135654166020234 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/logger/CMakeLists.txt0000664000175000017500000000042215135654166022772 0ustar alastairalastairset(logger_fppFiles ) set(logger_cppFiles ) set(logger_f90Files stdlib_logger.f90 ) configure_stdlib_target(${PROJECT_NAME}_logger logger_f90Files logger_fppFiles logger_cppFiles) target_link_libraries(${PROJECT_NAME}_logger PUBLIC ${PROJECT_NAME}_core) fortran-lang-stdlib-0ede301/src/logger/stdlib_logger.f900000664000175000017500000016507115135654166023406 0ustar alastairalastairmodule stdlib_logger !!### Module stdlib_logger !! !! This module defines a derived type, procedures, a variable, and !! constants to be used for logging information and reporting errors !! in Fortran applications. !!([Specification](../page/specs/stdlib_logger.html)) !! The derived type, `logger_type`, is to be used to define variables to !! serve as both local and global loggers. A logger directs its messages !! to selected I/O units so the user has a record (a log) of major events. !! For each entity of `logger_type` the reports go to a list of I/O units !! represented by the private internal array, `log_units`. If `log_units` is !! empty then output by default goes to `output_unit`. Otherwise reports !! go to `output_unit` only if it has been explicitly added to `log_units`. !! Each entity of type `logger_type` also maintains an internal state !! controlling the formatting of output. !! !! The procedures are as follows. The logical function !! `log_units_assigned` returns the number of I/O units in `log_units`. The !! subroutines `add_log_file` and `add_log_unit` include the specified file !! in `log_units`. `remove_log_units` removes the specified logical unit from !! the `log_units` array and optionally closes the file. `configure` !! configures the details of the logging process. `configuration` !! reports the details of that configuration. The subroutines !! `log_error`, `log_information`, `log_io_error`, `log_message`, !! `log_text_error`, and `log_warning` send messages to the log units. !! !! The variable `global_logger` of type `logger_type` can be used !! as a default global logger anywhere in the source code. !! !! The constants are used to report errors by some of the subroutines !! in their optional `stat` arguments. The constants are as follows. !! `success` indicates that no error has occurred. `close_failure` !! indicates that a `close` statement for an I/O unit failed. !! `index_invalid_error` indicates that `column` was invalid for !! the given `line`. `open_failure` indicates that an `open` statement !! failed. `read_only_error` indicates that an output unit did not have a !! `"write"` or `"readwrite"` action. `non_sequential_error` indicates !! that the unit did not have `sequential` access. `unformatted_in_error` !! indicates that the unit did not have a `form` of `"formatted"`. !! `unopened_in_error` indicates that the unit was not opened. `write_failure` !! indicates that at least one of the writes to `log_units` failed. use, intrinsic :: & iso_fortran_env, only : & error_unit, & input_unit, & output_unit use stdlib_ascii, only : to_lower use stdlib_optval, only : optval implicit none private public :: global_logger, logger_type !! public constants used as error flags integer, parameter, public :: & success = 0, & close_failure = 1, & index_invalid_error = 2, & non_sequential_error = 3, & open_failure = 4, & read_only_error = 5, & unformatted_in_error = 6, & unopened_in_error = 7, & write_failure = 8 integer, parameter, public :: & debug_level = 10, & information_level = 20, & warning_level = 30, & error_level = 40, & io_error_level = 40, & text_error_level = 50, & all_level = -10 + min( & debug_level, & information_level, & warning_level, & error_level, & io_error_level, & text_error_level), & none_level = 10 + max( & debug_level, & information_level, & warning_level, & error_level, & io_error_level, & text_error_level) character(*), parameter :: module_name = 'stdlib_logger' type :: logger_type !! version: experimental !! Public derived type ([Specification](../page/specs/stdlib_logger.html#the-derived-type-logger_type)) private logical :: add_blank_line = .false. logical :: indent_lines = .true. integer :: level = information_level integer, allocatable :: log_units(:) integer :: max_width = 0 logical :: time_stamp = .true. integer :: units = 0 contains private procedure, public, pass(self) :: add_log_file procedure, public, pass(self) :: add_log_unit procedure, public, pass(self) :: configuration procedure, public, pass(self) :: configure procedure, public, pass(self) :: log_debug procedure, public, pass(self) :: log_error procedure, public, pass(self) :: log_information procedure, public, pass(self) :: log_io_error procedure, public, pass(self) :: log_message procedure, public, pass(self) :: log_text_error procedure, public, pass(self) :: log_units_assigned procedure, public, pass(self) :: log_warning procedure, public, pass(self) :: remove_log_unit final :: final_logger end type logger_type !! Variable of type `logger_type` to be used as a global logger type(logger_type) :: global_logger character(*), parameter :: & invalid_column = 'column is not a valid index to line.' contains subroutine add_log_file( self, filename, unit, action, position, status, & stat ) !! version: experimental !! Opens a formatted sequential access output file, `filename` using !! `newunit` and adds the resulting unit number to `self`'s `log_units` !! array. `action`, if present, is the `action` specifier of the `open` !! statement, and has the default value of `"write"`. `position`, if present, !! is the `position` specifier, and has the default value of `"REWIND"`. !! `status`, if present, is the `status` specifier of the `open` statement, !! and has the default value of `"REPLACE"`. `stat`, if present, has the value !! `success` if `filename` could be opened, `read_only_error` if `action` is !! `"read"`, and `open_failure` otherwise. !!([Specification](../page/specs/stdlib_logger.html#add_log_file-open-a-file-and-add-its-unit-to-self-log_units)) class(logger_type), intent(inout) :: self !! The logger variable to which the file is to be added character(*), intent(in) :: filename !! The name of the file to be added to the logger integer, intent(out), optional :: unit !! The resulting I/O unit number character(*), intent(in), optional :: action !! The `action` specifier for the `open`` statement character(*), intent(in), optional :: position !! The `position` specifier for the `open` statement character(*), intent(in), optional :: status !! The `status` specifier for the `open` statement integer, intent(out), optional :: stat !! The error status on exit with the possible values !! * `success` - no errors found !! * `read_only_error` - file unopened as `action1 was `"read"` for an output !! file !! * `open_failure` - the `open` statement failed !!##### Example !! !! program main !! use stdlib_logger !! ... !! integer :: unit, stat !! ... !! call global_logger % add_log_file( 'error_log.txt', unit, & !! position='asis', stat=stat ) !! if ( stat /= success ) then !! error stop 'Unable to open "error_log.txt".' !! end if !! ... !! end program main character(16) :: aaction, aposition, astatus integer :: aunit character(128) :: iomsg integer :: iostat character(*), parameter :: procedure_name = 'add_log_file' integer, allocatable :: dummy(:) integer :: lun integer :: i aaction = optval(action, 'write') aposition = optval(position, 'rewind') astatus = optval(status, 'replace') if ( len_trim(aaction) == 4 ) then do i=1, 4 aaction(i:i) = to_lower(aaction(i:i)) end do if ( aaction == 'read' ) then if ( present( stat ) ) then stat = read_only_error return else error stop 'In ' // module_name // ' % ' // & procedure_name // ' action is "read" which ' // & 'does not allow writes to the file.' end if end if end if open( newunit=aunit, file=filename, form='formatted', action=aaction, & position=aposition, status=astatus, iostat=iostat, iomsg=iomsg, & err=999 ) if ( allocated( self % log_units ) ) then if ( size(self % log_units) == self % units ) then allocate( dummy(2*self % units) ) do lun=1, self % units dummy(lun) = self % log_units(lun) end do dummy(self % units+1:) = 0 call move_alloc( dummy, self % log_units ) end if else allocate( self % log_units(16) ) end if self % log_units(self % units + 1 ) = aunit self % units = self % units + 1 if ( present(unit) ) unit = aunit if ( present(stat) ) stat = success return 999 if (present(stat) ) then stat = open_failure return else call self % log_io_error( 'Unable to open ' // trim(filename), & module = module_name, & procedure = procedure_name, & iostat = iostat, & iomsg = iomsg ) error stop module_name // ' % ' // procedure_name // & ': Unable to open file' end if end subroutine add_log_file subroutine add_log_unit( self, unit, stat ) !! version: experimental !! Adds `unit` to the log file units in `log_units`. `unit` must be an `open` !! file, of `form` `"formatted"`, with `"sequential"` `access`, and an `action` !! of `"write"` or `"readwrite"`, otherwise either `stat`, if present, has a !! value other than `success` and `unit` is not entered into `log_units`, !! or, if `stat` is not presecn, processing stops. !!([Specification](../page/specs/stdlib_logger.html#add_log_unit-add-a-unit-to-the-array-self-log_units)) class(logger_type), intent(inout) :: self !! The logger variable to which the I/O unit is to be added integer, intent(in) :: unit !! The input logical unit number integer, intent(out), optional :: stat !! An error code with the possible values !! * `success` - no problems were found !! * `non_sequential_error` - `unit` did not have sequential access !! * `read_only_error` - `unit` was not writeable !! * `unformatted_in_error` - `unit` was an `'unformatted'` file !! * `unopened_in_error` - `unit` was not opened !!##### Example !! !! program main !! use stdlib_logger !! ... !! character(256) :: iomsg !! integer :: iostat, unit, stat !! ... !! open( newunit=unit, 'error_log.txt', form='formatted', & !! status='replace', position='rewind', err=999, & !! action='read', iostat=iostat, iomsg=iomsg ) !! ... !! call global_logger % add_log_unit( unit, stat ) !! select case ( stat ) !! ... !! case ( read_only_error ) !! error stop 'Unable to write to "error_log.txt".' !! ... !! end select !! ... !! 999 error stop 'Unable to open "error_log.txt". !! ... !! end program main integer, allocatable :: dummy(:) character(*), parameter :: procedure_name = 'set_log_unit' integer :: lun character(12) :: specifier logical :: question integer :: istat call validate_unit() if ( present(stat) ) then if ( stat /= success ) return end if do lun = 1, self % units ! Check that unit is not already registered if (self % log_units(lun) == unit ) return end do if ( allocated( self % log_units ) ) then if ( size(self % log_units) == self % units ) then allocate( dummy(2*self % units) ) do lun=1, self % units dummy(lun) = self % log_units(lun) end do call move_alloc( dummy, self % log_units ) end if else allocate( self % log_units(16) ) end if self % log_units(self % units + 1 ) = unit self % units = self % units + 1 contains subroutine validate_unit() ! Check that unit is not input_unit if ( unit == input_unit ) then if ( present(stat) ) then stat = read_only_error return else error stop 'unit in ' // module_name // ' % ' // & procedure_name // ' must not be input_unit.' end if end if ! Check that unit is opened inquire( unit, opened=question, iostat=istat ) if(istat /= 0) question = .false. if ( .not. question ) then if ( present(stat) ) then stat = unopened_in_error return else error stop 'unit in ' // module_name // ' % ' // & procedure_name // ' is not open.' end if end if ! Check that unit is writeable inquire( unit, write=specifier ) if ( specifier(1:1) /= 'Y' .and. specifier(1:1) /= 'y' ) then if ( present(stat) ) then stat = read_only_error return else error stop 'unit in ' // module_name // ' % ' // & procedure_name // ' is not writeable.' end if end if inquire( unit, sequential=specifier ) if ( specifier(1:1) /= 'Y' .and. specifier(1:1) /= 'y' ) then if ( present(stat) ) then stat = non_sequential_error return else error stop 'unit in ' // module_name // ' % ' // & procedure_name // ' is not "sequential".' end if end if inquire( unit, formatted=specifier ) if ( specifier(1:1) /= 'Y' .and. specifier(1:1) /= 'y' ) then if ( present(stat) ) then stat = unformatted_in_error return else error stop 'unit in ' // module_name // ' % ' // & procedure_name // ' is not "formatted".' end if end if if ( present(stat) ) stat = success end subroutine validate_unit end subroutine add_log_unit pure subroutine configuration( self, add_blank_line, indent, level, & max_width, time_stamp, log_units ) !! version: experimental !! Reports the logging configuration of `self`. The following attributes are !! reported: !! 1. `add_blank_line` is a logical flag with `.true.` implying that output !! starts with a blank line, and `.false.` implying no blank line. !! 2. `indent` is a logical flag with `.true.` implying that subsequent columns !! will be indented 4 spaces and `.false.` implying no indentation. !! 3. `level` is the lowest level for printing a message !! 4. `max_width` is the maximum number of columns of output text with !! `max_width` == 0 => no bounds on output width. !! 5. `time_stamp` is a logical flag with `.true.` implying that the output !! will have a time stamp, and `.false.` implying that there will be no !! time stamp. !! 6. `log_units` is an array of the I/O unit numbers to which log output !! will be written. !!([Specification](../page/specs/stdlib_logger.html#configuration-report-a-loggers-configuration)) class(logger_type), intent(in) :: self !! The logger variable whose configuration is being reported logical, intent(out), optional :: add_blank_line !! A logical flag to add a preceding blank line logical, intent(out), optional :: indent !! A logical flag to indent subsequent lines integer, intent(out), optional :: level !! The minimum level for printing a message integer, intent(out), optional :: max_width !! The maximum number of columns for most outputs logical, intent(out), optional :: time_stamp !! A logical flag to add a time stamp integer, intent(out), allocatable, optional :: log_units(:) !! The I/O units used in output !!##### Example !! !! module example_mod !! use stdlib_logger !! ... !! contains !! ... !! subroutine example_sub(unit, ...) !! integer, intent(in) :: unit !! ... !! integer, allocatable :: log_units(:) !! ... !! call global_logger % configuration( log_units=log_units ) !! if ( size(log_units) == 0 ) then !! call add_logger_unit( unit ) !! end if !! .. !! end subroutine example_sub !! ... !! end module example_mod if ( present(add_blank_line) ) add_blank_line = self % add_blank_line if ( present(indent) ) indent = self % indent_lines if ( present(level) ) level = self % level if ( present(max_width) ) max_width = self % max_width if ( present(time_stamp) ) time_stamp = self % time_stamp if ( present(log_units) ) then if ( self % units .gt. 0 ) then log_units = self % log_units(1:self % units) else allocate(log_units(0)) end if end if end subroutine configuration pure subroutine configure( self, add_blank_line, indent, level, max_width, & time_stamp ) !! version: experimental !! Configures the logging process for SELF. The following attributes are !! configured: !! 1. `add_blank_line` is a logical flag with `.true.` implying that output !! starts with a blank line, and `.false.` implying no blank line. !! `add_blank_line` has a startup value of `.false.`. !! 2. `indent` is a logical flag with `.true.` implying that subsequent lines !! will be indented 4 spaces and `.false.` implying no indentation. `indent` !! has a startup value of `.true.`. !! 3. `level` is the lowest level for printing a message !! 4. `max_width` is the maximum number of columns of output text with !! `max_width == 0` => no bounds on output width. `max_width` has a startup !! value of 0. !! 5. `time_stamp` is a logical flag with `.true.` implying that the output !! will have a time stamp, and `.false.` implying that there will be no !! time stamp. `time_stamp` has a startup value of `.true.`. !!([Specification](../page/specs/stdlib_logger.html#configure-configure-the-logging-process)) !!##### Example !! !! program main !! use stdlib_logger !! ... !! call global_logger % configure( indent=.false., max_width=72 ) !! ... class(logger_type), intent(inout) :: self logical, intent(in), optional :: add_blank_line logical, intent(in), optional :: indent integer, intent(in), optional :: level integer, intent(in), optional :: max_width logical, intent(in), optional :: time_stamp if ( present(add_blank_line) ) self % add_blank_line = add_blank_line if ( present(level) ) self % level = level if ( present(indent) ) self % indent_lines = indent if ( present(max_width) ) then if ( max_width <= 4 ) then self % max_width = 0 else self % max_width = max_width end if end if if ( present(time_stamp) ) self % time_stamp = time_stamp end subroutine configure subroutine final_logger( self ) !! version: experimental !! Finalizes the `logger_type` entity `self` by flushing the units type(logger_type), intent(in) :: self integer :: iostat character(256) :: message integer :: unit do unit=1, self % units flush( self % log_units(unit), iomsg=message, iostat=iostat ) if ( iostat /= 0 ) then write(error_unit, '(a, i0)' ) 'In the logger_type ' // & 'finalizer an error occurred in flushing unit = ', & self % log_units(unit) write(error_unit, '(a, i0)') 'With iostat = ', iostat write(error_unit, '(a)') 'With iomsg = ' // trim(message) end if end do end subroutine final_logger subroutine format_output_string( self, string, col_indent, len_buffer, buffer ) !! version: experimental !! Writes the STRING to UNIT ensuring that the number of characters !! does not exceed MAX_WIDTH and that the lines after the first !! one are indented four characters. class(logger_type), intent(in) :: self character(*), intent(in) :: string character(*), intent(in) :: col_indent integer, intent(out) :: len_buffer character(len=:), allocatable, intent(out) :: buffer integer :: count, indent_len, index_, length, remain integer, parameter :: new_len = len(new_line('a')) length = len_trim(string) allocate( character(2*length) :: buffer ) len_buffer = 0 indent_len = len(col_indent) call format_first_line() if ( self % indent_lines ) then do while( remain > 0 ) call indent_format_subsequent_line() end do else do while( remain > 0 ) call format_subsequent_line() end do end if contains subroutine format_first_line() if ( self % max_width == 0 .or. & ( length <= self % max_width .and. & index( string(1:length), new_line('a')) == 0 ) ) then buffer(1:length) = string(1:length) len_buffer = length remain = 0 return else index_ = index( string(1:min(length, self % max_width)), & new_line('a') ) if ( index_ == 0 ) then do index_=self % max_width, 1, -1 if ( string(index_:index_) == ' ' ) exit end do end if if ( index_ == 0 ) then buffer(1:self % max_width) = & string(1:self % max_width) len_buffer = self % max_width count = self % max_width remain = length - count return else buffer(1:index_-1) = string(1:index_-1) len_buffer = index_-1 count = index_ remain = length - count return end if end if end subroutine format_first_line subroutine format_subsequent_line() integer :: new_len_buffer character(:), allocatable :: dummy if ( remain <= self % max_width ) then new_len_buffer = len_buffer + length - count + new_len if ( new_len_buffer > len( buffer ) ) then allocate( character( 2*len( buffer ) ) :: dummy ) dummy = buffer call move_alloc( dummy, buffer ) end if buffer( len_buffer+1:new_len_buffer ) = & new_line('a') // string(count+1:length) len_buffer = new_len_buffer count = length remain = 0 return else index_ = count + index(string(count+1:count+self % max_width),& new_line('a')) if(index_ == count) then do index_=count+self % max_width, count+1, -1 if ( string(index_:index_) == ' ' ) exit end do end if if ( index_ == count ) then new_len_buffer = len_buffer + self % max_width + & new_len if ( new_len_buffer > len( buffer ) ) then allocate( character( 2*len( buffer ) ) :: dummy ) dummy = buffer call move_alloc( dummy, buffer ) end if buffer( len_buffer+1:new_len_buffer ) = & new_line('a') // string(count+1:count+self % max_width) len_buffer = new_len_buffer count = count + self % max_width remain = length - count return else new_len_buffer = len_buffer + index_ - 1 & - count + new_len if ( new_len_buffer > len( buffer ) ) then allocate( character( 2*len( buffer ) ) :: dummy ) dummy = buffer call move_alloc( dummy, buffer ) end if buffer( len_buffer+1:new_len_buffer ) = & new_line('a') // string(count+1:index_-1) len_buffer = new_len_buffer count = index_ remain = length - count return end if end if end subroutine format_subsequent_line subroutine indent_format_subsequent_line() integer :: new_len_buffer character(:), allocatable :: dummy if ( index( string(count+1:length), new_line('a')) == 0 .and. & remain <= self % max_width - indent_len ) then new_len_buffer = len_buffer + length & - count + new_len + indent_len if ( new_len_buffer > len( buffer ) ) then allocate( character( 2*len( buffer ) ) :: dummy ) dummy = buffer call move_alloc( dummy, buffer ) end if buffer( len_buffer+1:new_len_buffer ) = & new_line('a') // col_indent // string(count+1:length) len_buffer = new_len_buffer count = length remain = 0 return else index_ = count + index( string(count+1: & min ( length, count+self % max_width - indent_len) ), & new_line('a')) if(index_ == count) then do index_=count+self % max_width-indent_len, count+1, -1 if ( string(index_:index_) == ' ' ) exit end do end if if ( index_ == count ) then new_len_buffer = len_buffer + self % max_width & + new_len if ( new_len_buffer > len( buffer ) ) then allocate( character( 2*len( buffer ) ) :: dummy ) dummy = buffer call move_alloc( dummy, buffer ) end if buffer( len_buffer+1: new_len_buffer ) = & new_line('a') // col_indent // & string(count+1:count+self % max_width-indent_len) len_buffer = new_len_buffer count = count + self % max_width - indent_len remain = length - count return else new_len_buffer = len_buffer + index_ - count - 1 & + new_len + indent_len if ( new_len_buffer > len( buffer ) ) then allocate( character( 2*len( buffer ) ) :: dummy ) dummy = buffer call move_alloc( dummy, buffer ) end if buffer( len_buffer+1: new_len_buffer ) = & new_line('a') // col_indent // string(count+1:index_-1) len_buffer = new_len_buffer count = index_ remain = length - count return end if end if end subroutine indent_format_subsequent_line end subroutine format_output_string subroutine handle_write_failure( unit, procedure_name, iostat, iomsg ) !! version: experimental !! Handles a failure to write to `unit` in `procedure_name` with `iostat` and !! `iomsg` by writing a description of the failure to `output_unit` and !! stopping. integer, intent(in) :: unit character(*), intent(in) :: procedure_name integer, intent(in) :: iostat character(*), intent(in) :: iomsg character(256) :: name logical :: named character(10) :: action write( output_unit, '(a)' ) 'write failure in ' // module_name // & ' % ' // trim(procedure_name) // '.' if ( unit == -999 ) then write( output_unit, '(a, i0)' ) 'unit = internal file' else write( output_unit, '(a, i0)' ) 'unit = ', unit inquire( unit, named=named ) if ( named ) then inquire( unit, name=name ) write( output_unit, '(a, a)' ) 'name = ', trim(name) else write( output_unit, '(a)' ) 'unit is unnamed' end if inquire( unit, action=action ) write( output_unit, '(a, a)' ) 'action = ', trim(action) end if write( output_unit, '(a, i0)' ) 'iostat = ', iostat write( output_unit, '(a, a )' ) 'iomsg = ', trim(iomsg) error stop 'write failure in ' // module_name // '.' end subroutine handle_write_failure subroutine log_debug( self, message, module, procedure ) !! version: experimental !! Writes the string `message` to `self % log_units` with optional additional !! text. !!([Specification](../page/specs/stdlib_logger.html#log_debug-writes-the-string-message-to-self-log_units)) !! !!##### Behavior !! !! If time stamps are active, a time stamp is written, followed by !! `module` and `procedure` if present, and then `message` is !! written with the prefix 'DEBUG: '. !! !!##### Example !! !! module example_mod !! use stdlib_logger !! ... !! real, allocatable :: a(:) !! ... !! type(logger_type) :: alogger !! ... !! contains !! ... !! subroutine example_sub( selection ) !! integer, intent(out) :: selection !! integer :: stat !! write(*,'(a)') "Enter an integer to select a widget" !! read(*,'(i0)') selection !! write( message, `(a, i0)' ) & !! "The user selected ", selection !! call alogger % log_debug( message, & !! module = 'EXAMPLE_MOD', & !! procedure = 'EXAMPLE_SUB' ) !! ... !! end subroutine example_sub !! ... !! end module example_mod !! class(logger_type), intent(in) :: self !! The logger used to send the message character(len=*), intent(in) :: message !! A string to be written to log_unit character(len=*), intent(in), optional :: module !! The name of the module containing the current invocation of `log_information` character(len=*), intent(in), optional :: procedure !! The name of the procedure containing the current invocation of !! `log_information` if ( self % level > debug_level ) return call self % log_message( message, & module = module, & procedure = procedure, & prefix = 'DEBUG' ) end subroutine log_debug subroutine log_error( self, message, module, procedure, stat, errmsg ) !! version: experimental !! Writes the string `message` to `self % log_units` with optional additional !! text. !! ([Specification](../specs/stdlib_logger.html#log_error-writes-the-string-message-to-self-log_units)) !!##### Behavior !! !! If time stamps are active, a time stamp is written, followed by !! `module` and `procedure` if present, then `message` is !! written with the prefix 'ERROR: ', and then if `stat` or `errmsg` !! are present they are written. !! !!##### Example !! !! module example_mod !! use stdlib_logger !! ... !! real, allocatable :: a(:) !! ... !! type(logger_type) :: alogger !! ... !! contains !! ... !! subroutine example_sub( size ) !! integer, intent(in) :: size !! character(128) :: errmsg, message !! integer :: stat !! allocate( a(size), stat=stat, errmsg=errmsg ) !! if ( stat /= 0 ) then !! write( message, `(a, i0)' ) & !! "Allocation of A failed with SIZE = ", size !! alogger % call log_error( message, & !! module = 'EXAMPLE_MOD', & !! procedure = 'EXAMPLE_SUB', & !! stat = stat, & !! errmsg = errmsg ) !! end if !! end subroutine example_sub !! ... !! end module example_mod !! class(logger_type), intent(in) :: self !! The logger to be used in logging the message character(len=*), intent(in) :: message !! A string to be written to log_unit character(len=*), intent(in), optional :: module !! The name of the module containing the current invocation of `log_error` character(len=*), intent(in), optional :: procedure !! The name of the procedure containing the current invocation of `log_error` integer, intent(in), optional :: stat !! The value of the `stat` specifier returned by a Fortran statement character(len=*), intent(in), optional :: errmsg !! The value of the `errmsg` specifier returned by a Fortran statement integer :: iostat character(28) :: dummy character(256) :: iomsg character(*), parameter :: procedure_name = 'log_error' character(:), allocatable :: suffix if ( self % level > error_level ) return if ( present(stat) ) then write( dummy, '(a, i0)', err=999, iostat=iostat, iomsg=iomsg ) & new_line('a') // "With stat = ", stat else dummy = ' ' end if if ( present(errmsg) ) then if ( len_trim(errmsg) > 0 ) then suffix = trim(dummy) // & new_line('a') // 'With errmsg = "' // trim(errmsg) // '"' else suffix = dummy end if else suffix = dummy end if call self % log_message( trim(message) // suffix, & module = module, & procedure = procedure, & prefix = 'ERROR') return 999 call handle_write_failure( -999, procedure_name, iostat, iomsg ) end subroutine log_error subroutine log_information( self, message, module, procedure ) !! version: experimental !! Writes the string `message` to `self % log_units` with optional additional !! text. !!([Specification](../page/specs/stdlib_logger.html#log_information-writes-the-string-message-to-self-log_units)) !! !!##### Behavior !! !! If time stamps are active, a time stamp is written, followed by !! `module` and `procedure` if present, and then `message` is !! written with the prefix 'INFO: '. !! !!##### Example !! !! module example_mod !! use stdlib_logger !! ... !! real, allocatable :: a(:) !! ... !! type(logger_type) :: alogger !! ... !! contains !! ... !! subroutine example_sub( selection ) !! integer, intent(out) :: selection !! integer :: stat !! write(*,'(a)') "Enter an integer to select a widget" !! read(*,'(i0)') selection !! write( message, `(a, i0)' ) & !! "The user selected ", selection !! call alogger % log_information( message, & !! module = 'EXAMPLE_MOD', & !! procedure = 'EXAMPLE_SUB' ) !! ... !! end subroutine example_sub !! ... !! end module example_mod !! class(logger_type), intent(in) :: self !! The logger used to send the message character(len=*), intent(in) :: message !! A string to be written to log_unit character(len=*), intent(in), optional :: module !! The name of the module containing the current invocation of `log_information` character(len=*), intent(in), optional :: procedure !! The name of the procedure containing the current invocation of !! `log_information` if ( self % level > information_level ) return call self % log_message( message, & module = module, & procedure = procedure, & prefix = 'INFO' ) end subroutine log_information subroutine log_io_error( self, message, module, procedure, iostat, & iomsg ) !! version: experimental !! Writes the string `message` to the `self % log_units` with optional !! additional text. !!([Specification](../page/specs/stdlib_logger.html#log_io_error-write-the-string-message-to-self-log_units)) !! !!##### Behavior !! !! If time stamps are active, a time stamp is written, followed by !! `module` and `procedure` if present, then `message` is !! written with a prefix 'I/O ERROR: ', and then if `iostat` or `iomsg` !! are present they are also written. !! !!##### Example !! !! program example !! use stdlib_logger !! ... !! character(*), parameter :: filename = 'dummy.txt' !! integer :: iostat, lun !! character(128) :: iomsg !! character(*), parameter :: message = 'Failure in opening "dummy.txt".' !! !! open( newunit=lun, file = filename, form='formatted', & !! status='old', iostat=iostat, iomsg=iomsg ) !! if ( iostat /= 0 ) then !! call global_logger % log_io_error( message, procedure = 'EXAMPLE', & !! iostat=iostat, iomsg = iomsg ) !! error stop 'Error on opening ' // filename !! end if !! ... !! end program example class(logger_type), intent(in) :: self !! The logger variable to receivee the message character(len=*), intent(in) :: message !! A string to be written to LOG_UNIT character(len=*), intent(in), optional :: module !! The name of the module containing the current invocation of REPORT_ERROR character(len=*), intent(in), optional :: procedure !! The name of the procedure containing the current invocation of REPORT_ERROR integer, intent(in), optional :: iostat !! The value of the IOSTAT specifier returned by a Fortran I/O statement character(len=*), intent(in), optional :: iomsg !! The value of the IOMSG specifier returned by a Fortran I/O statement character(28) :: dummy character(256) :: iomsg2 integer :: iostat2 character(*), parameter :: procedure_name = 'log_io_error' character(:), allocatable :: suffix if ( self % level > io_error_level ) return if ( present(iostat) ) then write( dummy, '(a, i0)', err=999, iostat=iostat2, iomsg=iomsg2 ) & new_line('a') // "With iostat = ", iostat else dummy = ' ' end if if ( present(iomsg) ) then if ( len_trim(iomsg) > 0 ) then suffix = trim(dummy) // & new_line('a') // 'With iomsg = "' // trim(iomsg) // '"' else suffix = trim(dummy) end if else suffix = trim(dummy) end if call self % log_message( trim(message) // suffix, & module = module, & procedure = procedure, & prefix = 'I/O ERROR' ) return 999 call handle_write_failure( -999, procedure_name, iostat2, iomsg2 ) end subroutine log_io_error subroutine log_message( self, message, module, procedure, prefix ) !! version: experimental !! Writes the string `message` to the `self % log_units` with optional !! additional text. !!([Specification](../page/specs/stdlib_logger.html#log_message-write-the-string-message-to-self-log_units)) !! !!##### Behavior !! !! If time stamps are active, a time stamp is written, followed by `module` !! and `procedure` if present, followed by `prefix // ': '` if present, !! and then `message`. !! !!##### Example !! !! module example_mod !! use stdlib_logger !! ... !! real, allocatable :: a(:) !! ... !! contains !! ... !! subroutine example_sub( selection ) !! integer, intent(out) :: selection !! integer :: stat !! write(*,'(a)') "Enter an integer to select a widget" !! read(*,'(i0)') selection !! write( message, `(a, i0)' ) & !! "The user selected ", selection !! call global_logger % log_message( message, & !! module = 'example_mod', & !! procedure = 'example_sub', & !! prefix = 'info' ) !! end subroutine example_sub !! ... !! end module example_mod !! class(logger_type), intent(in) :: self !! The logger variable to receive the message character(len=*), intent(in) :: message !! A string to be written to log_unit character(len=*), intent(in), optional :: module !! The name of the module containing the current invocation of `log_message` character(len=*), intent(in), optional :: procedure !! The name of the procedure containing the current invocation of `log_message` character(len=*), intent(in), optional :: prefix !! To be prepended to message as `prefix // ': ' // message`. integer :: unit integer :: iostat integer :: len_buffer character(*), parameter :: procedure_name = 'log_message' character(256) :: iomsg character(:), allocatable :: d_and_t, m_and_p, pref character(:), allocatable :: buffer pref = optval(prefix, '') if ( len(pref) > 0 ) pref = pref // ': ' if ( self % time_stamp ) then d_and_t = time_stamp() // ': ' else d_and_t = '' end if if ( present(module) ) then if ( present(procedure) ) then m_and_p = trim(module) // ' % ' // trim(procedure) // ': ' else m_and_p = trim(module) // ': ' end if else if ( present(procedure) ) then m_and_p = trim(procedure) // ': ' else m_and_p = '' end if call format_output_string( self, & d_and_t // m_and_p // pref // & trim( message ), & ' ', & len_buffer, & buffer) if ( self % units == 0 ) then if ( self % add_blank_line ) then write( output_unit, '(a)', err=999, iostat=iostat, & iomsg=iomsg) & new_line('a') // buffer(1:len_buffer) else write( output_unit, '(a)', err=999, iostat=iostat, & iomsg=iomsg ) & buffer(1:len_buffer) end if else if ( self % add_blank_line ) then do unit=1, self % units write( self % log_units(unit), '(a)', err=999, iostat=iostat, & iomsg=iomsg ) new_line('a') // & buffer(1:len_buffer) end do else do unit=1, self % units write( self % log_units(unit), '(a)', err=999, iostat=iostat, & iomsg=iomsg ) & buffer(1:len_buffer) end do end if end if return 999 call handle_write_failure( unit, procedure_name, iostat, iomsg ) end subroutine log_message subroutine log_text_error( self, line, column, summary, filename, & line_number, caret, stat ) !! version: experimental !! Sends a message to `self % log_units` describing an error found !! in a line of text. !!([Specification](../page/specs/stdlib_logger.html#log_text_error-send-a-message-to-self-log_units-describing-an-error)) !!##### Behavior !! !! If time stamps are active first a time stamp is written. Then if !! `filename` or `line_number` or `column` are present they are written. !! Then `line` is written. Then the symbol `caret` is written below `line` !! at the column indicated by `column`. Then `summary` is written. ! !!##### Example !! !! program example !! ... !! character(*), parameter :: filename = 'dummy.txt' !! integer :: col_num, line_num, lun !! character(128) :: line !! character(*), parameter :: message = 'Bad text found.' !! !! open( newunit=lun, file = filename, statu='old', form='formatted' ) !! line_num = 0 !! do !! read( lun, fmt='(a)', end=900 ) line !! line_num = line_num + 1 !! call check_line( line, status, col_num ) !! if ( status /= 0 ) !! call global_logger % log_text_error( line, col_num, message, & !! filename, line_num ) !! error stop 'Error in reading ' // filename !! end if !! ... !! end do !!900 continue !! ... !! end program example !! class(logger_type), intent(in) :: self !! The logger variable to receive the message character(*), intent(in) :: line !! The line of text in which the error was found. integer, intent(in) :: column !! The one's based column in LINE at which the error starts. character(*), intent(in) :: summary !! A brief description of the error. character(*), intent(in), optional :: filename !! The name of the file, if any, in which the error was found. integer, intent(in), optional :: line_number !! The one's based line number in the file where `line` was found. character(1), intent(in), optional :: caret !! The symbol used to mark the column wher the error was first detected integer, intent(out), optional :: stat !! Integer flag that an error has occurred. Has the value `success` if no !! error hass occurred, `index_invalid_error` if `column` is less than zero or !! greater than `len(line)`, and `write_failure` if any of the `write` !! statements has failed. character(1) :: acaret character(128) :: iomsg integer :: iostat integer :: lun character(*), parameter :: procedure_name = 'LOG_TEXT_ERROR' character(len=:), allocatable :: buffer if ( self % level > text_error_level ) return acaret = optval(caret, '^') if ( column < 0 .or. column > len( line ) + 1 ) then if ( present(stat) ) then stat = index_invalid_error return else call self % log_error( invalid_column, & module = module_name, & procedure = procedure_name ) error stop module_name // ' % ' // procedure_name // ': ' // & invalid_column end if end if call write_log_text_error_buffer( ) if ( self % units == 0 ) then write( output_unit, '(a)' ) buffer else do lun=1, self % units write( self % log_units(lun), '(a)' ) buffer end do end if contains subroutine write_log_text_error_buffer( ) integer :: i character(:), allocatable :: location, marker if ( present(filename) ) then if ( present(line_number) ) then allocate( character(len_trim(filename)+15) :: location ) write( location, fmt='(a, ":", i0, ":", i0)', err=999, & iomsg=iomsg, iostat=iostat ) & trim(filename) , line_number, column else allocate( character(len_trim(filename)+45) :: location ) write( location, fmt='(a, i0)', err=999, iomsg=iomsg, & iostat=iostat ) & "Error found in file: '" // trim(filename) // & "', at column: ", column end if else if ( present(line_number) ) then allocate( character(54) :: location ) write( location, fmt='(a, i0, a, i0)', err=999, & iomsg=iomsg, iostat=iostat ) & 'Error found at line number: ', line_number, & ', and column: ', column else allocate( character(36) :: location ) write( location, & fmt='("Error found in line at column:", i0)' ) & column end if end if allocate( character(column) :: marker ) do i=1, column-1 marker(i:i) = ' ' end do marker(column:column) = acaret if ( self % add_blank_line ) then if ( self % time_stamp ) then buffer = new_line('a') // time_stamp() // & new_line('a') // trim(location) // & new_line('a') // new_line('a') // trim(line) // & new_line('a') // marker // & new_line('a') // 'Error: ' // trim(summary) else buffer = new_line('a') // trim(location) // & new_line('a') // new_line('a') // trim(line) // & new_line('a') // marker // & new_line('a') // 'Error: ' // trim(summary) end if else if ( self % time_stamp ) then buffer = time_stamp() // & new_line('a') // trim(location) // & new_line('a') // new_line('a') // trim(line) // & new_line('a') // marker // & new_line('a') // 'Error: ' // trim(summary) else buffer = trim(location) // & new_line('a') // new_line('a') // trim(line) // & new_line('a') // marker // & new_line('a') // 'Error: ' // trim(summary) end if end if if ( present(stat) ) stat = success return 999 if ( present( stat ) ) then stat = write_failure return else call handle_write_failure( -999, procedure_name, iostat, & iomsg ) end if end subroutine write_log_text_error_buffer end subroutine log_text_error elemental function log_units_assigned(self) !! version: experimental !! Returns the number of units assigned to `self % log_units` !!([Specification](../page/specs/stdlib_logger.html#log_units_assigned-returns-the-number-of-active-io-units)) class(logger_type), intent(in) :: self !! The logger subject to the inquiry integer :: log_units_assigned !!##### Example !! !! module example_mod !! use stdlib_logger !! ... !! type(logger_type) :: alogger !! ... !! contains !! ... !! subroutine example_sub(unit, ...) !! integer, intent(in) :: unit !! ... !! integer, allocatable :: log_units(:) !! ... !! if ( alogger % log_units_assigned() == 0 ) then !! call alogger % add_log_unit( unit ) !! end if !! ... !! end subroutine example_sub !! ... !! end module example_mod log_units_assigned = self % units end function log_units_assigned subroutine log_warning( self, message, module, procedure ) !! version: experimental !! Writes the string `message` to `self % log_units` with optional additional !! text. !!([Specification](../page/specs/stdlib_logger.html#log_warning-write-the-string-message-to-log_units)) !!##### Behavior !! !! If time stamps are active, a time stamp is written, followed by !! `module` and `procedure` if present, then `message` is !! written with the prefix 'WARN: '. !! !!##### Example !! !! module example_mod !! use stdlib_logger !! ... !! real, allocatable :: a(:) !! ... !! type(logger_type) :: alogger !! ... !! contains !! ... !! subroutine example_sub( size, stat ) !! integer, intent(in) :: size !! integer, intent(out) :: stat !! allocate( a(size) ) !! if ( stat /= 0 ) then !! write( message, `(a, i0)' ) & !! "Allocation of A failed with SIZE = ", size !! call alogger % log_warning( message, & !! module = 'EXAMPLE_MOD', & !! procedure = 'EXAMPLE_SUB' ) !! end if !! end subroutine example_sub !! ... !! end module example_mod !! class(logger_type), intent(in) :: self !! The logger to which the message is written character(len=*), intent(in) :: message !! A string to be written to LOG_UNIT character(len=*), intent(in), optional :: module !! The name of the module containing the current invocation of `log_warning` character(len=*), intent(in), optional :: procedure !! The name of the procedure containing the current invocation of `log_warning` if ( self % level > warning_level ) return call self % log_message( message, & module = module, & procedure = procedure, & prefix = 'WARN' ) end subroutine log_warning subroutine remove_log_unit( self, unit, close_unit, stat ) !! version: experimental !! Remove the I/O unit from the self % log_units list. If `close_unit` is !! present and `.true.` then the corresponding file is closed. If `unit` is !! not in `log_units` then nothing is done. If `stat` is present it, by !! default, has the value `success`. If closing the `unit` fails, then if !! `stat` is present it has the value `close_failure`, otherwise processing !! stops with an informative message. !!([Specification](../page/specs/stdlib_logger.html#remove_log_unit-remove-unit-from-self-log_units)) class(logger_type), intent(inout) :: self !! The logger variable whose unit is to be removed integer, intent(in) :: unit !! The I/O unit to be removed from self logical, intent(in), optional :: close_unit !! A logical flag to close the unit while removing it from the SELF list integer, intent(out), optional :: stat !! An error status with the values !! * success - no problems found !! * close_failure - the close statement for unit failed !! !!##### Example !! !! module example_mod !! use stdlib_logger !! ... !! type(logger_type) :: alogger !! contains !! ... !! subroutine example_sub(unit, ...) !! integer, intent(in) :: unit !! ... !! call alogger % remove_log_unit( unit ) !! ... !! end subroutine example_sub !! ... !! end module example_mod character(128) :: errmsg integer :: lun, lun_old character(*), parameter :: procedure_name = 'REMOVE_LOG_UNIT' if ( present(stat) ) stat = success do lun=1, self % units if ( unit == self % log_units(lun) ) exit end do if ( lun == self % units + 1 ) return if ( present(close_unit) ) then if ( close_unit ) close( unit, err=999, iomsg=errmsg ) end if do lun_old=lun+1, self % units self % log_units(lun_old-1) = self % log_units(lun_old) end do self % units = self % units - 1 return 999 if ( present(stat) ) then stat = close_failure return else write(*, '(a, i0)') 'In ' // module_name // ' % ' // & procedure_name // ' close_unit failed for unit = ', unit write(*, '(a)' ) 'With iomsg = ' // trim(errmsg) error stop 'close_unit failed in ' // module_name // ' % ' // & procedure_name // '.' end if end subroutine remove_log_unit function time_stamp() !! Creates a time stamp in the format 'yyyy-mm-dd hh:mm:ss.sss' character(23) :: time_stamp character(8) :: date character(10) :: time call date_and_time( date, time ) time_stamp(1:4) = date(1:4) time_stamp(5:5) = '-' time_stamp(6:7) = date(5:6) time_stamp(8:8) = '-' time_stamp(9:10) = date(7:8) time_stamp(11:11) = ' ' time_stamp(12:13) = time(1:2) time_stamp(14:14) = ':' time_stamp(15:16) = time(3:4) time_stamp(17:17) = ':' time_stamp(18:23) = time(5:10) end function time_stamp end module stdlib_logger fortran-lang-stdlib-0ede301/src/linalg/0000775000175000017500000000000015135654166020223 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_outer_product.fypp0000664000175000017500000000102515135654166026706 0ustar alastairalastair#:include "common.fypp" #:set RCI_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES + INT_KINDS_TYPES submodule (stdlib_linalg) stdlib_linalg_outer_product implicit none contains #:for k1, t1 in RCI_KINDS_TYPES pure module function outer_product_${t1[0]}$${k1}$(u, v) result(res) ${t1}$, intent(in) :: u(:), v(:) ${t1}$ :: res(size(u),size(v)) integer :: col do col = 1, size(v) res(:,col) = v(col) * u end do end function outer_product_${t1[0]}$${k1}$ #:endfor end submodule fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_norms.fypp0000664000175000017500000005671515135654166025166 0ustar alastairalastair#:include "common.fypp" #:set ALL_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES #! Allow for integer or character norm input: i.e., norm(a,2) or norm(a, '2') #:set INPUT_TYPE = ["character(len=*)","integer(ilp)"] #:set INPUT_SHORT = ["char","int"] #:set INPUT_OPTIONS = list(zip(INPUT_TYPE,INPUT_SHORT)) ! Vector norms submodule(stdlib_linalg) stdlib_linalg_norms use stdlib_linalg_constants use stdlib_linalg_blas use stdlib_linalg_lapack use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR use iso_c_binding, only: c_intptr_t,c_char,c_loc implicit none character(*), parameter :: this = 'norm' !> List of internal norm flags integer(ilp), parameter :: NORM_ONE = 1_ilp integer(ilp), parameter :: NORM_TWO = 2_ilp integer(ilp), parameter :: NORM_POW_FIRST = 3_ilp integer(ilp), parameter :: NORM_INF = +huge(0_ilp) ! infinity norm integer(ilp), parameter :: NORM_POW_LAST = NORM_INF - 1_ilp integer(ilp), parameter :: NORM_MINUSINF = -huge(0_ilp) !> Wrappers to LAPACK *LANGE matrix norm flags character, parameter :: MAT_NORM_MAT = 'M' ! maxval(sum(abs(a))) ! over whole matrix: unused character, parameter :: MAT_NORM_ONE = '1' ! maxval(sum(abs(a),1)) ! over columns character, parameter :: MAT_NORM_INF = 'I' ! maxval(sum(abs(a),2)) ! over rows character, parameter :: MAT_NORM_FRO = 'E' ! sqrt(sum(a**2)) ! "Euclidean" or "Frobenius" !> Other wrappers to matrix norms character, parameter :: MAT_NORM_SVD = '2' ! maxval(svdvals(a)) ! Maximum singular value interface parse_norm_type module procedure parse_norm_type_integer module procedure parse_norm_type_character end interface parse_norm_type interface mat_task_request module procedure mat_task_request_integer module procedure mat_task_request_character end interface mat_task_request interface stride_1d #:for rk,rt,ri in ALL_KINDS_TYPES module procedure stride_1d_${ri}$ #:endfor end interface stride_1d contains !> Parse norm type from an integer user input pure subroutine parse_norm_type_integer(order,norm_type,err) !> User input value integer(ilp), intent(in) :: order !> Return value: norm type integer(ilp), intent(out) :: norm_type !> State return flag type(linalg_state_type), intent(out) :: err select case (order) case (1_ilp) norm_type = NORM_ONE case (2_ilp) norm_type = NORM_TWO case (3_ilp:NORM_POW_LAST) norm_type = order case (NORM_INF:) norm_type = NORM_INF case (:NORM_MINUSINF) norm_type = NORM_MINUSINF case default norm_type = NORM_ONE err = linalg_state_type(this,LINALG_ERROR,'Input norm type ',order,' is not recognized.') end select end subroutine parse_norm_type_integer pure subroutine parse_norm_type_character(order,norm_type,err) !> User input value character(len=*), intent(in) :: order !> Return value: norm type integer(ilp), intent(out) :: norm_type !> State return flag type(linalg_state_type), intent(out) :: err integer(ilp) :: int_order,read_err select case (order) case ('inf','Inf','INF') norm_type = NORM_INF case ('-inf','-Inf','-INF') norm_type = NORM_MINUSINF case ('Euclidean','euclidean','EUCLIDEAN') norm_type = NORM_TWO case default ! Check if this input can be read as an integer read(order,*,iostat=read_err) int_order if (read_err/=0) then ! Cannot read as an integer norm_type = NORM_ONE err = linalg_state_type(this,LINALG_ERROR,'Input norm type ',order,' is not recognized.') else call parse_norm_type_integer(int_order,norm_type,err) endif end select end subroutine parse_norm_type_character !> From a user norm request, generate a *LANGE task command pure subroutine mat_task_request_integer(order,mat_task,err) !> Parsed matrix norm type integer(ilp), optional, intent(in) :: order !> LANGE task character, intent(out) :: mat_task !> Error flag type(linalg_state_type), intent(inout) :: err if (present(order)) then select case (order) case (NORM_INF) mat_task = MAT_NORM_INF case (NORM_TWO) mat_task = MAT_NORM_SVD case (NORM_ONE) mat_task = MAT_NORM_ONE case default err = linalg_state_type(this,LINALG_VALUE_ERROR,'Integer order ',order,' is not a valid matrix norm input.') end select else ! No user input: Frobenius norm mat_task = MAT_NORM_FRO endif end subroutine mat_task_request_integer pure subroutine mat_task_request_character(order,mat_task,err) !> User input value character(len=*), intent(in) :: order !> Return value: norm type character, intent(out) :: mat_task !> State return flag type(linalg_state_type), intent(out) :: err integer(ilp) :: int_order,read_err select case (order) case ('inf','Inf','INF') mat_task = MAT_NORM_INF case ('Euclidean','euclidean','EUCLIDEAN','Frobenius','frobenius','FROBENIUS','Fro','fro','frob') mat_task = MAT_NORM_FRO case default ! Check if this input can be read as an integer read(order,*,iostat=read_err) int_order if (read_err/=0 .or. all(int_order/=[1,2])) then ! Cannot read as an integer err = linalg_state_type(this,LINALG_ERROR,'Matrix norm input',order,' is not recognized.') endif select case (int_order) case (1); mat_task = MAT_NORM_ONE case (2); mat_task = MAT_NORM_SVD case default; mat_task = MAT_NORM_ONE end select end select end subroutine mat_task_request_character #:for rk,rt,ri in ALL_KINDS_TYPES ! Compute stride of a 1d array pure integer(ilp) function stride_1d_${ri}$(a) result(stride) !> Input 1-d array ${rt}$, intent(in), target :: a(:) integer(c_intptr_t) :: a1,a2 if (size(a,kind=ilp)<=1_ilp) then stride = 1_ilp else a1 = transfer(c_loc(a(1)),a1) a2 = transfer(c_loc(a(2)),a2) stride = bit_size(0_c_char)*int(a2-a1, ilp)/storage_size(a, kind=ilp) endif end function stride_1d_${ri}$ ! Private internal 1D implementation. This has to be used only internally, ! when all inputs are already checked for correctness. pure subroutine internal_norm_1D_${ri}$(sze, a, nrm, norm_request) !> Input matrix length integer(ilp), intent(in) :: sze !> Input contiguous 1-d matrix a(*) ${rt}$, intent(in) :: a(sze) !> Norm of the matrix. real(${rk}$), intent(out) :: nrm !> Internal matrix request integer(ilp), intent(in) :: norm_request integer(ilp) :: i real(${rk}$) :: rorder ! Initialize norm to zero nrm = 0.0_${rk}$ select case(norm_request) case(NORM_ONE) nrm = asum(sze,a,incx=1_ilp) case(NORM_TWO) nrm = nrm2(sze,a,incx=1_ilp) case(NORM_INF) #:if rt.startswith('complex') ! The default BLAS stdlib_i${ri}$amax uses |Re(.)|+|Im(.)|. Do not use it. i = stdlib_i${ri}$max1(sze,a,incx=1_ilp) #:else i = stdlib_i${ri}$amax(sze,a,incx=1_ilp) #:endif nrm = abs(a(i)) case(NORM_MINUSINF) nrm = minval( abs(a) ) case (NORM_POW_FIRST:NORM_POW_LAST) rorder = 1.0_${rk}$ / norm_request nrm = sum( abs(a) ** norm_request ) ** rorder end select end subroutine internal_norm_1D_${ri}$ #:for it,ii in INPUT_OPTIONS !============================================== ! Norms : any rank to scalar !============================================== #:for rank in range(1, MAXRANK + 1) ! Pure function interface, with order specification. On error, the code will stop pure module function stdlib_linalg_norm_${rank}$D_order_${ii}$_${ri}$(a, order) result(nrm) !> Input ${rank}$-d matrix a${ranksuffix(rank)}$ ${rt}$, intent(in) :: a${ranksuffix(rank)}$ !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> Norm of the matrix. real(${rk}$) :: nrm call norm_${rank}$D_${ii}$_${ri}$(a, nrm=nrm, order=order) end function stdlib_linalg_norm_${rank}$D_order_${ii}$_${ri}$ ! Function interface with output error module function stdlib_linalg_norm_${rank}$D_order_err_${ii}$_${ri}$(a, order, err) result(nrm) !> Input ${rank}$-d matrix a${ranksuffix(rank)}$ ${rt}$, intent(in) :: a${ranksuffix(rank)}$ !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> Output state return flag. type(linalg_state_type), intent(out) :: err !> Norm of the matrix. real(${rk}$) :: nrm call norm_${rank}$D_${ii}$_${ri}$(a, nrm=nrm, order=order, err=err) end function stdlib_linalg_norm_${rank}$D_order_err_${ii}$_${ri}$ ! Internal implementation: ${rank}$-d pure module subroutine norm_${rank}$D_${ii}$_${ri}$(a, nrm, order, err) !> Input ${rank}$-d matrix a${ranksuffix(rank)}$ ${rt}$, intent(in), target :: a${ranksuffix(rank)}$ !> Norm of the matrix. real(${rk}$), intent(out) :: nrm !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out), optional :: err type(linalg_state_type) :: err_ integer(ilp) :: sze,norm_request sze = size(a,kind=ilp) ! Initialize norm to zero nrm = 0.0_${rk}$ ! Check matrix size if (sze<=0) then err_ = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix shape: a=',shape(a,kind=ilp)) call linalg_error_handling(err_,err) return end if ! Check norm request call parse_norm_type(order,norm_request,err_) if (err_%error()) then call linalg_error_handling(err_,err) return endif ! Get norm call internal_norm_1D_${ri}$(sze, a, nrm, norm_request) call linalg_error_handling(err_,err) end subroutine norm_${rank}$D_${ii}$_${ri}$ #:endfor !==================================================================== ! Norms : any rank to rank-1, with DIM specifier and ${ii}$ input !==================================================================== #:for rank in range(2, MAXRANK + 1) ! Pure function interface with DIM specifier. On error, the code will stop pure module function stdlib_linalg_norm_${rank}$D_to_${rank-1}$D_${ii}$_${ri}$(a, order, dim) result(nrm) !> Input matrix a[..] ${rt}$, intent(in), target :: a${ranksuffix(rank)}$ !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> Dimension to collapse by computing the norm w.r.t other dimensions integer(ilp), intent(in) :: dim !> Norm of the matrix. real(${rk}$) :: nrm${reduced_shape('a', rank, 'dim')}$ call norm_${rank}$D_to_${rank-1}$D_${ii}$_${ri}$(a, nrm, order, dim) end function stdlib_linalg_norm_${rank}$D_to_${rank-1}$D_${ii}$_${ri}$ ! Function interface with DIM specifier and output error state. module function stdlib_linalg_norm_${rank}$D_to_${rank-1}$D_err_${ii}$_${ri}$(a, order, dim, err) result(nrm) !> Input matrix a[..] ${rt}$, intent(in), target :: a${ranksuffix(rank)}$ !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> Dimension to collapse by computing the norm w.r.t other dimensions integer(ilp), intent(in) :: dim !> Output state return flag. type(linalg_state_type), intent(out) :: err !> Norm of the matrix. real(${rk}$) :: nrm${reduced_shape('a', rank, 'dim')}$ call norm_${rank}$D_to_${rank-1}$D_${ii}$_${ri}$(a, nrm, order, dim, err) end function stdlib_linalg_norm_${rank}$D_to_${rank-1}$D_err_${ii}$_${ri}$ ! Internal implementation pure module subroutine norm_${rank}$D_to_${rank-1}$D_${ii}$_${ri}$(a, nrm, order, dim, err) !> Input matrix a[..] ${rt}$, intent(in) :: a${ranksuffix(rank)}$ !> Dimension to collapse by computing the norm w.r.t other dimensions ! (dim must be defined before it is used for `nrm`) integer(ilp), intent(in) :: dim !> Norm of the matrix. real(${rk}$), intent(out) :: nrm${reduced_shape('a', rank, 'dim')}$ !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out), optional :: err type(linalg_state_type) :: err_ integer(ilp) :: sze,lda,norm_request,${loop_variables('j',rank-1,1)}$ logical :: contiguous_data integer(ilp), dimension(${rank}$) :: spe,spack,perm,iperm integer(ilp), dimension(${rank}$), parameter :: dim_range = [(lda,lda=1_ilp,${rank}$_ilp)] ${rt}$, allocatable :: apack${ranksuffix(rank)}$ ! Input matrix properties sze = size (a,kind=ilp) spe = shape(a,kind=ilp) ! Initialize norm to zero nrm = 0.0_${rk}$ if (sze<=0) then err_ = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix shape: a=',shape(a,kind=ilp)) call linalg_error_handling(err_,err) return end if ! Check dimension choice if (dim<1 .or. dim>${rank}$) then err_ = linalg_state_type(this,LINALG_VALUE_ERROR,'dimension ',dim, & 'is out of rank for shape(a)=',shape(a,kind=ilp)) call linalg_error_handling(err_,err) return end if ! Check norm request call parse_norm_type(order,norm_request,err_) if (err_%error()) then call linalg_error_handling(err_,err) return endif ! The norm's leading dimension lda = spe(dim) ! Check if input column data is contiguous contiguous_data = dim==1 ! Get packed data with the norm dimension as the first dimension if (.not.contiguous_data) then ! Permute array to map dim to 1 perm = [dim,pack(dim_range,dim_range/=dim)] iperm(perm) = dim_range spack = spe(perm) apack = reshape(a, shape=spack, order=iperm) ${loop_variables_start('j', 'apack', rank-1, 1," "*12)}$ call internal_norm_1D_${ri}$(lda, apack(:, ${loop_variables('j',rank-1,1)}$), & nrm(${loop_variables('j',rank-1,1)}$), norm_request) ${loop_variables_end(rank-1," "*12)}$ else ${loop_variables_start('j', 'a', rank-1, 1," "*12)}$ call internal_norm_1D_${ri}$(lda, a(:, ${loop_variables('j',rank-1,1)}$), & nrm(${loop_variables('j',rank-1,1)}$), norm_request) ${loop_variables_end(rank-1," "*12)}$ endif end subroutine norm_${rank}$D_to_${rank-1}$D_${ii}$_${ri}$ #:endfor !==================================================================== ! Matrix norms !==================================================================== ! Internal implementation module function matrix_norm_${ii}$_${ri}$(a, order, err) result(nrm) !> Input matrix a(m,n) ${rt}$, intent(in), target :: a(:,:) !> Norm of the matrix. real(${rk}$) :: nrm !> Order of the matrix norm being computed. ${it}$, #{if 'integer' in it}#optional, #{endif}#intent(in) :: order !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out), optional :: err type(linalg_state_type) :: err_ integer(ilp) :: m,n character :: mat_task real(${rk}$), target :: work1(1) real(${rk}$), pointer :: work(:) m = size(a,dim=1,kind=ilp) n = size(a,dim=2,kind=ilp) ! Initialize norm to zero nrm = 0.0_${rk}$ if (m<=0 .or. n<=0) then err_ = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix shape: a=',[m,n]) call linalg_error_handling(err_,err) return end if ! Check norm request: user + *LANGE support call mat_task_request(order,mat_task,err_) if (err_%error()) then call linalg_error_handling(err_,err) return endif if (mat_task==MAT_NORM_INF) then allocate(work(m)) else work => work1 end if if (mat_task==MAT_NORM_SVD) then nrm = maxval(svdvals(a,err_),1) call linalg_error_handling(err_,err) else ! LAPACK interface nrm = lange(mat_task,m,n,a,m,work) end if if (mat_task==MAT_NORM_INF) deallocate(work) end function matrix_norm_${ii}$_${ri}$ #:for rank in range(3, MAXRANK + 1) ! Pure function interface with DIM specifier. On error, the code will stop module function matrix_norm_${rank}$D_to_${rank-2}$D_${ii}$_${ri}$(a, order, dim, err) result(nrm) !> Input matrix a(m,n) ${rt}$, intent(in), contiguous, target :: a${ranksuffix(rank)}$ !> Norm of the matrix. real(${rk}$), allocatable :: nrm${ranksuffix(rank-2)}$ !> Order of the matrix norm being computed. ${it}$, #{if 'integer' in it}#optional, #{endif}#intent(in) :: order !> [optional] dimensions of the sub-matrices the norms should be evaluated at (default = [1,2]) integer(ilp), optional, intent(in) :: dim(2) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out), optional :: err type(linalg_state_type) :: err_ integer(ilp) :: m,n,lda,dims(2),svd_errors integer(ilp), dimension(${rank}$) :: s,spack,perm,iperm integer(ilp), dimension(${rank}$), parameter :: dim_range = [(m,m=1_ilp,${rank}$_ilp)] integer(ilp) :: ${loop_variables('j',rank-2,2)}$ logical :: contiguous_data character :: mat_task real(${rk}$), target :: work1(1) real(${rk}$), pointer :: work(:) ${rt}$, pointer :: apack${ranksuffix(rank)}$ ! Get dimensions if (present(dim)) then dims = dim else dims = [1,2] endif nullify(apack) svd_errors = 0 if (dims(1)==dims(2) .or. .not.all(dims>0 .and. dims<=${rank}$)) then err_ = linalg_state_type(this,LINALG_VALUE_ERROR,'Rank-',${rank}$,' matrix norm has invalid dim=',dims) allocate(nrm${emptyranksuffix(rank-2)}$) call linalg_error_handling(err_,err) return endif ! Check norm request: user + *LANGE support call mat_task_request(order,mat_task,err_) if (err_%error()) then allocate(nrm${emptyranksuffix(rank-2)}$) call linalg_error_handling(err_,err) return endif ! Input matrix properties s = shape(a,kind=ilp) ! Check if input column data is contiguous contiguous_data = all(dims==[1,2]) ! Matrix norm size m = s(dims(1)) n = s(dims(2)) if (m<=0 .or. n<=0) then err_ = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix shape: a=',[m,n]) allocate(nrm${emptyranksuffix(rank-2)}$) call linalg_error_handling(err_,err) return end if ! Get packed data with norm dimensions as 1:2 if (contiguous_data) then ! Reshape without moving data spack = s apack => a else ! Dimension permutations to map dims(1),dims(2) => 1:2 perm = [dims,pack(dim_range, dim_range/=dims(1) .and. dim_range/=dims(2))] iperm(perm) = dim_range spack = s(perm) allocate(apack,source=reshape(a, shape=spack, order=iperm)) endif if (mat_task==MAT_NORM_INF) then allocate(work(m)) elseif (mat_task==MAT_NORM_SVD) then allocate(work(min(m,n))) else work => work1 endif ! Allocate norm allocate(nrm${shape_from_array_size('apack',rank-2, 2)}$) lda = size(apack,dim=1,kind=ilp) ! LAPACK interface ${loop_variables_start('j', 'apack', rank-2, 2)}$ if (mat_task==MAT_NORM_SVD) then work(:) = svdvals(apack(:,:,${loop_variables('j',rank-2,2)}$),err_) nrm(${loop_variables('j',rank-2,2)}$) = maxval(work,1) if (err_%error()) svd_errors = svd_errors+1 else nrm(${loop_variables('j',rank-2,2)}$) = & lange(mat_task,m,n,apack(:,:,${loop_variables('j',rank-2,2)}$),lda,work) end if ${loop_variables_end(rank-2)}$ if (any(mat_task==[MAT_NORM_INF,MAT_NORM_SVD])) deallocate(work) if (.not.contiguous_data) deallocate(apack) if (svd_errors>0) then err_ = linalg_state_type(this,LINALG_VALUE_ERROR,svd_errors,'failed SVDs') call linalg_error_handling(err_,err) endif end function matrix_norm_${rank}$D_to_${rank-2}$D_${ii}$_${ri}$ #:endfor #:endfor #:endfor end submodule stdlib_linalg_norms fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_least_squares.fypp0000664000175000017500000005534615135654166026702 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES #:set RHS_SUFFIX = ["one","many"] #:set RHS_SYMBOL = [ranksuffix(r) for r in [1,2]] #:set RHS_EMPTY = [emptyranksuffix(r) for r in [1,2]] #:set ALL_RHS = list(zip(RHS_SYMBOL,RHS_SUFFIX,RHS_EMPTY)) submodule (stdlib_linalg) stdlib_linalg_least_squares !! Least-squares solution to Ax=b use stdlib_linalg_constants use stdlib_linalg_lapack, only: gelsd, gglse, stdlib_ilaenv use stdlib_linalg_lapack_aux, only: handle_gelsd_info, handle_gglse_info use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR implicit none character(*), parameter :: this = 'lstsq' contains #:for rk,rt,ri in RC_KINDS_TYPES ! Workspace needed by gelsd elemental subroutine ${ri}$gelsd_space(m,n,nrhs,lrwork,liwork,lcwork) integer(ilp), intent(in) :: m,n,nrhs integer(ilp), intent(out) :: lrwork,liwork,lcwork integer(ilp) :: smlsiz,mnmin,nlvl mnmin = min(m,n) ! Maximum size of the subproblems at the bottom of the computation (~25) smlsiz = stdlib_ilaenv(9,'${ri}$gelsd',' ',0,0,0,0) ! The exact minimum amount of workspace needed depends on M, N and NRHS. nlvl = max(0, ilog2(mnmin/(smlsiz+1))+1) ! Real space #:if rt.startswith('complex') lrwork = 10*mnmin+2*mnmin*smlsiz+8*mnmin*nlvl+3*smlsiz*nrhs+max((smlsiz+1)**2,n*(1+nrhs)+2*nrhs) #:else lrwork = 12*mnmin+2*mnmin*smlsiz+8*mnmin*nlvl+mnmin*nrhs+(smlsiz+1)**2 #:endif lrwork = max(1,lrwork) ! Complex space lcwork = 2*mnmin + nrhs*mnmin ! Integer space liwork = max(1, 3*mnmin*nlvl+11*mnmin) ! For good performance, the workspace should generally be larger. ! Allocate 25% more space than strictly needed. lrwork = ceiling(1.25*lrwork,kind=ilp) lcwork = ceiling(1.25*lcwork,kind=ilp) liwork = ceiling(1.25*liwork,kind=ilp) end subroutine ${ri}$gelsd_space #:endfor #:for nd,ndsuf,nde in ALL_RHS #:for rk,rt,ri in RC_KINDS_TYPES ! Compute the integer, real, [complex] working space requested by the least squares procedure pure module subroutine stdlib_linalg_${ri}$_lstsq_space_${ndsuf}$(a,b,lrwork,liwork#{if rt.startswith('c')}#,lcwork#{endif}#) !> Input matrix a[m,n] ${rt}$, intent(in), target :: a(:,:) !> Right hand side vector or array, b[m] or b[m,nrhs] ${rt}$, intent(in) :: b${nd}$ !> Size of the working space arrays integer(ilp), intent(out) :: lrwork,liwork integer(ilp) #{if rt.startswith('c')}#, intent(out)#{endif}# :: lcwork integer(ilp) :: m,n,nrhs m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) nrhs = size(b,kind=ilp)/size(b,1,kind=ilp) call ${ri}$gelsd_space(m,n,nrhs,lrwork,liwork,lcwork) end subroutine stdlib_linalg_${ri}$_lstsq_space_${ndsuf}$ ! Compute the least-squares solution to a real system of linear equations Ax = b module function stdlib_linalg_${ri}$_lstsq_${ndsuf}$(a,b,cond,overwrite_a,rank,err) result(x) !!### Summary !! Compute least-squares solution to a real system of linear equations \( Ax = b \) !! !!### Description !! !! This function computes the least-squares solution of a linear matrix problem. !! !! param: a Input matrix of size [m,n]. !! param: b Right-hand-side vector of size [m] or matrix of size [m,nrhs]. !! param: cond [optional] Real input threshold indicating that singular values `s_i <= cond*maxval(s)` !! do not contribute to the matrix rank. !! param: overwrite_a [optional] Flag indicating if the input matrix can be overwritten. !! param: rank [optional] integer flag returning matrix rank. !! param: err [optional] State return flag. !! return: x Solution vector of size [n] or solution matrix of size [n,nrhs]. !! !> Input matrix a[m,n] ${rt}$, intent(inout), target :: a(:,:) !> Right hand side vector or array, b[m] or b[m,nrhs] ${rt}$, intent(in) :: b${nd}$ !> [optional] cutoff for rank evaluation: singular values s(i)<=cond*maxval(s) are considered 0. real(${rk}$), optional, intent(in) :: cond !> [optional] Can A,b data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] Return rank of A integer(ilp), optional, intent(out) :: rank !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Result array/matrix x[n] or x[n,nrhs] ${rt}$, allocatable, target :: x${nd}$ integer(ilp) :: n,nrhs,ldb n = size(a,2,kind=ilp) ldb = size(b,1,kind=ilp) nrhs = size(b,kind=ilp)/ldb ! Initialize solution with the shape of the rhs #:if ndsuf=="one" allocate(x(n)) #:else allocate(x(n,nrhs)) #:endif call stdlib_linalg_${ri}$_solve_lstsq_${ndsuf}$(a,b,x,& cond=cond,overwrite_a=overwrite_a,rank=rank,err=err) end function stdlib_linalg_${ri}$_lstsq_${ndsuf}$ ! Compute the least-squares solution to a real system of linear equations Ax = b module subroutine stdlib_linalg_${ri}$_solve_lstsq_${ndsuf}$(a,b,x,real_storage,int_storage, & #{if rt.startswith('c')}#cmpl_storage,#{endif}# cond,singvals,overwrite_a,rank,err) !!### Summary !! Compute least-squares solution to a real system of linear equations \( Ax = b \) !! !!### Description !! !! This function computes the least-squares solution of a linear matrix problem. !! !! param: a Input matrix of size [m,n]. !! param: b Right-hand-side vector of size [n] or matrix of size [n,nrhs]. !! param: x Solution vector of size at [>=n] or solution matrix of size [>=n,nrhs]. !! param: real_storage [optional] Real working space !! param: int_storage [optional] Integer working space #:if rt.startswith('c') !! param: cmpl_storage [optional] Complex working space #:endif !! param: cond [optional] Real input threshold indicating that singular values `s_i <= cond*maxval(s)` !! do not contribute to the matrix rank. !! param: singvals [optional] Real array of size [min(m,n)] returning a list of singular values. !! param: overwrite_a [optional] Flag indicating if the input matrix can be overwritten. !! param: rank [optional] integer flag returning matrix rank. !! param: err [optional] State return flag. !! !> Input matrix a[n,n] ${rt}$, intent(inout), target :: a(:,:) !> Right hand side vector or array, b[n] or b[n,nrhs] ${rt}$, intent(in) :: b${nd}$ !> Result array/matrix x[n] or x[n,nrhs] ${rt}$, intent(inout), contiguous, target :: x${nd}$ !> [optional] real working storage space real(${rk}$), optional, intent(inout), target :: real_storage(:) !> [optional] integer working storage space integer(ilp), optional, intent(inout), target :: int_storage(:) #:if rt.startswith('c') !> [optional] complex working storage space ${rt}$, optional, intent(inout), target :: cmpl_storage(:) #:endif !> [optional] cutoff for rank evaluation: singular values s(i)<=cond*maxval(s) are considered 0. real(${rk}$), optional, intent(in) :: cond !> [optional] list of singular values [min(m,n)], in descending magnitude order, returned by the SVD real(${rk}$), optional, intent(out), target :: singvals(:) !> [optional] Can A,b data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] Return rank of A integer(ilp), optional, intent(out) :: rank !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !! Local variables type(linalg_state_type) :: err0 integer(ilp) :: m,n,lda,ldb,nrhs,ldx,nrhsx,info,mnmin,mnmax,arank,lrwork,liwork,lcwork integer(ilp) :: nrs,nis,nsvd #:if rt.startswith('complex') integer(ilp) :: ncs #:endif integer(ilp), pointer :: iwork(:) logical(lk) :: copy_a,large_enough_x real(${rk}$) :: acond,rcond real(${rk}$), pointer :: rwork(:),singular(:) ${rt}$, pointer :: xmat(:,:),amat(:,:) #:if rt.startswith('complex') ${rt}$, pointer :: cwork(:) #:endif ! Problem sizes m = size(a,1,kind=ilp) lda = size(a,1,kind=ilp) n = size(a,2,kind=ilp) ldb = size(b,1,kind=ilp) nrhs = size(b ,kind=ilp)/ldb ldx = size(x,1,kind=ilp) nrhsx = size(x ,kind=ilp)/ldx mnmin = min(m,n) mnmax = max(m,n) if (lda<1 .or. n<1 .or. ldb<1 .or. ldb/=m .or. ldx cmpl_storage else allocate(cwork(lcwork)) endif ncs = size(cwork,kind=ilp) #:endif if (nrs=',lrwork, & ', int=',nis,' should be >=',liwork, & #{if rt.startswith('complex')}#', cmplx=',ncs,' should be >=',lcwork, &#{endif}# ', singv=',nsvd,' should be >=',mnmin) else ! Solve system using singular value decomposition call gelsd(m,n,nrhs,amat,lda,xmat,ldb,singular,rcond,arank, & #:if rt.startswith('complex') cwork,ncs,rwork,iwork,info) #:else rwork,nrs,iwork,info) #:endif ! The condition number of A in the 2-norm = S(1)/S(min(m,n)). acond = singular(1)/singular(mnmin) ! Process output call handle_gelsd_info(this,info,lda,n,ldb,nrhs,err0) endif ! Process output and return if (.not.large_enough_x) then #:if ndsuf=="one" x(1:n) = xmat(1:n,1) #:else x(1:n,1:nrhs) = xmat(1:n,1:nrhs) #:endif deallocate(xmat) endif if (copy_a) deallocate(amat) if (present(rank)) rank = arank if (.not.present(real_storage)) deallocate(rwork) if (.not.present(int_storage)) deallocate(iwork) #:if rt.startswith('complex') if (.not.present(cmpl_storage)) deallocate(cwork) #:endif if (.not.present(singvals)) deallocate(singular) call linalg_error_handling(err0,err) end subroutine stdlib_linalg_${ri}$_solve_lstsq_${ndsuf}$ #:endfor #:endfor ! Simple integer log2 implementation elemental integer(ilp) function ilog2(x) integer(ilp), intent(in) :: x integer(ilp) :: remndr if (x>0) then remndr = x ilog2 = -1_ilp do while (remndr>0) ilog2 = ilog2 + 1_ilp remndr = shiftr(remndr,1) end do else ilog2 = -huge(0_ilp) endif end function ilog2 !------------------------------------------------------------- !----- Equality-constrained Least-Squares solver ----- !------------------------------------------------------------- pure subroutine check_problem_size(ma, na, mb, mc, nc, md, mx, err) integer(ilp), intent(in) :: ma, na, mb, mc, nc, md, mx type(linalg_state_type), intent(out) :: err ! Check sizes. if (ma < 1 .or. na < 1) then err = linalg_state_type(this, LINALG_VALUE_ERROR, 'Invalid matrix size a(m, n) =', [ma, na]) return else if (mc < 1 .or. nc < 1) then err = linalg_state_type(this, LINALG_VALUE_ERROR, 'Invalid matrix size c(p, n) =', [mc, nc]) else if (na /= nc) then err = linalg_state_type(this, LINALG_VALUE_ERROR, 'Matrix A and matrix C have inconsistent number of columns.') else if (mb /= ma) then err = linalg_state_type(this, LINALG_VALUE_ERROR, 'Size(b) inconsistent with number of rows in a, size(b) =', mb) else if (md /= mc) then err = linalg_state_type(this, LINALG_VALUE_ERROR, 'Size(d) inconsistent with number of rows in c, size(d) =', md) else if (na /= mx) then err = linalg_state_type(this, LINALG_VALUE_ERROR, 'Size(x) inconsistent with number of columns of a, size(x) =', mx) endif end subroutine check_problem_size #:for rk, rt, ri in RC_KINDS_TYPES ! Compute the size of the workspace requested by the constrained least-squares procedure. module subroutine stdlib_linalg_${ri}$_constrained_lstsq_space(A, C, lwork, err) !> Least-squares cost. ${rt}$, intent(in) :: A(:, :) !> Equality constraints. ${rt}$, intent(in) :: C(:, :) !> Size of the workspace array. integer(ilp), intent(out) :: lwork !> [optional] State return flag. type(linalg_state_type), optional, intent(out) :: err !> Local variables. integer(ilp) :: m, n, p, info ${rt}$ :: a_dummy(1, 1), b_dummy(1) ${rt}$ :: c_dummy(1, 1), d_dummy(1) ${rt}$ :: work(1), x(1) type(linalg_state_type) :: err0 !> Problem dimensions. m = size(A, 1) ; n = size(A, 2) ; p = size(C, 1) lwork = -1_ilp !> Workspace query. call gglse(m, n, p, a_dummy, m, c_dummy, p, b_dummy, d_dummy, x, work, lwork, info) call handle_gglse_info(this, info, m, n, p, err0) !> Optimal workspace size. lwork = ceiling(real(work(1), kind=${rk}$), kind=ilp) call linalg_error_handling(err0, err) end subroutine stdlib_linalg_${ri}$_constrained_lstsq_space ! Constrained least-squares solver. module subroutine stdlib_linalg_${ri}$_solve_constrained_lstsq(A, b, C, d, x, storage, overwrite_matrices, err) !! ### Summary !! Compute the solution of the equality constrained least-squares problem !! !! minimize || Ax - b ||² !! subject to Cx = d !! !! ### Description !! !! This function computes the solution of an equality constrained linear least-squares !! problem. !! !! param: a Input matrix of size [m, n] (with m > n). !! param: b Right-hand side vector of size [m] in the least-squares cost. !! param: c Input matrix of size [p, n] (with p < n) defining the equality constraints. !! param: d Right-hand side vector of size [p] in the equality constraints. !! param: x Vector of size [n] solution to the problem. !! param: storage [optional] Working array. !! param: overwrite_matrices [optional] Boolean flag indicating whether the matrices !! and vectors can be overwritten. !! param: err [optional] State return flag. !! !> Least-squares cost. ${rt}$, intent(inout), target :: A(:, :), b(:) !> Equality constraints. ${rt}$, intent(inout), target :: C(:, :), d(:) !> Solution vector. ${rt}$, intent(out) :: x(:) !> [optional] Storage. ${rt}$, optional, intent(out), target :: storage(:) !> [optional] Can A, b, C, and d be overwritten? logical(lk), optional, intent(in) :: overwrite_matrices !> [optional] State return flag. type(linalg_state_type), optional, intent(out) :: err ! Local variables. type(linalg_state_type) :: err0 integer(ilp) :: ma, na, mb integer(ilp) :: mc, nc, md integer(ilp) :: mx logical(lk) :: overwrite_matrices_ ${rt}$, pointer :: amat(:, :), bvec(:) ${rt}$, pointer :: cmat(:, :), dvec(:) ! LAPACK related. integer(ilp) :: lwork, info ${rt}$, pointer :: work(:) !> Check dimensions. ma = size(A, 1, kind=ilp) ; na = size(A, 2, kind=ilp) mc = size(C, 1, kind=ilp) ; nc = size(C, 2, kind=ilp) mb = size(b, kind=ilp) ; md = size(d, kind=ilp) ; mx = size(x, kind=ilp) call check_problem_size(ma, na, mb, mc, nc, md, mx, err0) if (err0%error()) then call linalg_error_handling(err0, err) return endif !> Check if matrices can be overwritten. overwrite_matrices_ = optval(overwrite_matrices, .false._lk) !> Allocate matrices. if (overwrite_matrices_) then amat => a bvec => b cmat => c dvec => d else allocate(amat(ma, na), source=a) allocate(bvec(mb), source=b) allocate(cmat(mc, nc), source=c) allocate(dvec(md), source=d) endif !> Retrieve workspace size. call stdlib_linalg_${ri}$_constrained_lstsq_space(A, C, lwork, err0) if (err0%ok()) then !> Workspace. if (present(storage)) then work => storage else allocate(work(lwork)) endif if (size(work, kind=ilp) < lwork) then err0 = linalg_state_type(this, LINALG_ERROR, 'Insufficient workspace. Should be at least ', lwork) call linalg_error_handling(err0, err) return endif !> Compute constrained lstsq solution. call gglse(ma, na, mc, amat, ma, cmat, mc, bvec, dvec, x, work, lwork, info) call handle_gglse_info(this, info, ma, na, mc, err0) !> Deallocate. if (.not. present(storage)) deallocate(work) endif if (.not. overwrite_matrices_) then deallocate(amat, bvec, cmat, dvec) endif call linalg_error_handling(err0, err) end subroutine stdlib_linalg_${ri}$_solve_constrained_lstsq module function stdlib_linalg_${ri}$_constrained_lstsq(A, b, C, d, overwrite_matrices, err) result(x) !! ### Summary !! Compute the solution of the equality constrained least-squares problem !! !! minimize || Ax - b ||² !! subject to Cx = d !! !! ### Description !! !! This function computes the solution of an equality constrained linear least-squares !! problem. !! !! param: a Input matrix of size [m, n] (with m > n). !! param: b Right-hand side vector of size [m] in the least-squares cost. !! param: c Input matrix of size [p, n] (with p < n) defining the equality constraints. !! param: d Right-hand side vector of size [p] in the equality constraints. !! param: x Vector of size [n] solution to the problem. !! param: overwrite_matrices [optional] Boolean flag indicating whether the matrices !! and vectors can be overwritten. !! param: err [optional] State return flag. !! !> Least-squares cost. ${rt}$, intent(inout), target :: A(:, :), b(:) !> Equality constraints. ${rt}$, intent(inout), target :: C(:, :), d(:) !> [optional] Can A, b, C, d be overwritten? logical(lk), optional, intent(in) :: overwrite_matrices !> [optional] State return flag. type(linalg_state_type), optional, intent(out) :: err !> Solution of the constrained least-squares problem. ${rt}$, allocatable, target :: x(:) ! Local variables. integer(ilp) :: n n = size(A, 2, kind=ilp) allocate(x(n)) call stdlib_linalg_${ri}$_solve_constrained_lstsq(A, b, C, d, x, overwrite_matrices=overwrite_matrices, err=err) end function stdlib_linalg_${ri}$_constrained_lstsq #:endfor end submodule stdlib_linalg_least_squares fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_schur.fypp0000664000175000017500000003007015135654166025136 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_linalg) stdlib_linalg_schur use stdlib_linalg_constants use stdlib_linalg_lapack, only: gees use stdlib_linalg_lapack_aux, only: handle_gees_info use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR implicit none character(*), parameter :: this = 'schur' !> List of internal GEES tasks: !> No task request character, parameter :: GEES_NOT = 'N' !> Request Schur vectors to be computed character, parameter :: GEES_WITH_VECTORS = 'V' !> Request Schur vectors to be sorted character, parameter :: GEES_SORTED_VECTORS = 'S' contains !> Wrapper function for Schur vectors request elemental character function gees_vectors(wanted) !> Are Schur vectors wanted? logical(lk), intent(in) :: wanted gees_vectors = merge(GEES_WITH_VECTORS,GEES_NOT,wanted) end function gees_vectors !> Wrapper function for Schur vectors request elemental character function gees_sort_eigs(sorted) !> Should the eigenvalues be sorted? logical(lk), intent(in) :: sorted gees_sort_eigs = merge(GEES_SORTED_VECTORS,GEES_NOT,sorted) end function gees_sort_eigs #:for rk, rt, ri in RC_KINDS_TYPES !> Workspace query module subroutine get_schur_${ri}$_workspace(a,lwork,err) !> Input matrix a[m,m] ${rt}$, intent(in), target :: a(:,:) !> Minimum workspace size for the decomposition operation integer(ilp), intent(out) :: lwork !> State return flag. Returns an error if the query failed type(linalg_state_type), optional, intent(out) :: err integer(ilp) :: m,n,sdim,info character :: jobvs,sort logical(lk) :: bwork_dummy(1) ${rt}$, pointer :: amat(:,:) real(${rk}$) :: rwork_dummy(1) ${rt}$ :: wr_dummy(1),wi_dummy(1),vs_dummy(1,1),work_dummy(1) type(linalg_state_type) :: err0 !> Initialize problem lwork = -1_ilp m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) !> Create a dummy intent(inout) argument amat => a !> Select dummy task jobvs = gees_vectors(.true.) sort = gees_sort_eigs(.false.) sdim = 0_ilp !> Get Schur workspace call gees(jobvs,sort,do_not_select,n,amat,m,sdim,wr_dummy,#{if rt.startswith('r')}#wi_dummy, #{endif}#& vs_dummy,m,work_dummy,lwork,#{if rt.startswith('c')}#rwork_dummy,#{endif}#bwork_dummy,info) if (info==0) lwork = nint(real(work_dummy(1),kind=${rk}$),kind=ilp) call handle_gees_info(this,info,m,n,m,err0) call linalg_error_handling(err0,err) contains ! Interface to dummy select routine pure logical(lk) function do_not_select(alpha#{if rt.startswith('r')}#r,alphai#{endif}#) ${rt}$, intent(in) :: alpha#{if rt.startswith('r')}#r,alphai#{endif}# do_not_select = .false. end function do_not_select end subroutine get_schur_${ri}$_workspace ! Schur decomposition subroutine module subroutine stdlib_linalg_${ri}$_schur(a,t,z,eigvals,overwrite_a,storage,err) !> Input matrix a[m,m] ${rt}$, intent(inout), target :: a(:,:) !> Schur form of A: upper-triangular or quasi-upper-triangular matrix T ${rt}$, intent(out), contiguous, target :: t(:,:) !> Unitary/orthonormal transformation matrix Z ${rt}$, optional, intent(out), contiguous, target :: z(:,:) !> [optional] Output eigenvalues that appear on the diagonal of T complex(${rk}$), optional, intent(out), contiguous, target :: eigvals(:) !> [optional] Provide pre-allocated workspace, size to be checked with schur_space ${rt}$, optional, intent(inout), target :: storage(:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] State return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err ! Local variables integer(ilp) :: m,n,mt,nt,ldvs,nvs,lde,lwork,sdim,info logical(lk) :: overwrite_a_ logical(lk), target :: bwork_dummy(1),local_eigs logical(lk), pointer :: bwork(:) real(${rk}$), allocatable :: rwork(:) ${rt}$, target :: vs_dummy(1,1) ${rt}$, pointer :: vs(:,:),work(:),eigs(:)#{if rt.startswith('r')}#,eigi(:)#{endif}# character :: jobvs,sort type(linalg_state_type) :: err0 ! Problem size m = size(a, 1, kind=ilp) n = size(a, 2, kind=ilp) mt = size(t, 1, kind=ilp) nt = size(t, 2, kind=ilp) ! Validate dimensions if (m/=n .or. m<=0 .or. n<=0) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, 'Matrix A must be square: size(a)=',[m,n]) call linalg_error_handling(err0, err) return end if if (mt/=nt .or. mt/=n .or. nt/=n) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, 'Matrix T must be square: size(T)=',[mt,nt], & 'should be',[m,n]) call linalg_error_handling(err0, err) return end if !> Copy data into the output array t = a ! Can A be overwritten? By default, do not overwrite overwrite_a_ = .false._lk if (present(overwrite_a)) overwrite_a_ = overwrite_a .and. n>=2 !> Schur vectors jobvs = gees_vectors(present(z)) if (present(z)) then vs => z ldvs = size(vs, 1, kind=ilp) nvs = size(vs, 2, kind=ilp) if (ldvs eigvals local_eigs = .false. #:else local_eigs = .true. #:endif else local_eigs = .true. lde = n end if if (local_eigs) then ! Use A storage if possible if (overwrite_a_) then eigs => a(:,1) #:if rt.startswith('r') eigi => a(:,2) #:endif else allocate(eigs(n)#{if rt.startswith('r')}#,eigi(n)#{endif}#) end if endif #:if rt.startswith('c') allocate(rwork(n)) #:endif if (lde=',n) else ! Compute Schur decomposition call gees(jobvs,sort,eig_select,nt,t,mt,sdim,eigs,#{if rt.startswith('r')}#eigi,#{endif}# & vs,ldvs,work,lwork,#{if rt.startswith('c')}#rwork,#{endif}#bwork,info) call handle_gees_info(this,info,m,n,m,err0) end if eigenvalue_output: if (local_eigs) then #:if rt.startswith('r') ! Build complex eigenvalues if (present(eigvals)) eigvals = cmplx(eigs,eigi,kind=${rk}$) #:endif if (.not.overwrite_a_) deallocate(eigs#{if rt.startswith('r')}#,eigi#{endif}#) endif eigenvalue_output if (.not.present(storage)) deallocate(work) if (sort/=GEES_NOT) deallocate(bwork) call linalg_error_handling(err0,err) contains ! Dummy select routine: currently, no sorting options are offered pure logical(lk) function eig_select(alpha#{if rt.startswith('r')}#r,alphai#{endif}#) #:if rt.startswith('r') ${rt}$, intent(in) :: alphar,alphai complex(${rk}$) :: alpha alpha = cmplx(alphar,alphai,kind=${rk}$) #:else ${rt}$, intent(in) :: alpha #:endif eig_select = .false. end function eig_select end subroutine stdlib_linalg_${ri}$_schur ! Schur decomposition subroutine: real eigenvalue interface module subroutine stdlib_linalg_real_eig_${ri}$_schur(a,t,z,eigvals,overwrite_a,storage,err) !> Input matrix a[m,m] ${rt}$, intent(inout), target :: a(:,:) !> Schur form of A: upper-triangular or quasi-upper-triangular matrix T ${rt}$, intent(out), contiguous, target :: t(:,:) !> Unitary/orthonormal transformation matrix Z ${rt}$, optional, intent(out), contiguous, target :: z(:,:) !> Output eigenvalues that appear on the diagonal of T real(${rk}$), intent(out), contiguous, target :: eigvals(:) !> [optional] Provide pre-allocated workspace, size to be checked with schur_space ${rt}$, optional, intent(inout), target :: storage(:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] State return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err type(linalg_state_type) :: err0 integer(ilp) :: n complex(${rk}$), allocatable :: ceigvals(:) real(${rk}$), parameter :: rtol = epsilon(0.0_${rk}$) real(${rk}$), parameter :: atol = tiny(0.0_${rk}$) n = size(eigvals,dim=1,kind=ilp) allocate(ceigvals(n)) !> Compute Schur decomposition with complex eigenvalues call stdlib_linalg_${ri}$_schur(a,t,z,ceigvals,overwrite_a,storage,err0) ! Check that no eigenvalues have meaningful imaginary part if (err0%ok() .and. any(aimag(ceigvals)>atol+rtol*abs(abs(ceigvals)))) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR, & 'complex eigenvalues detected: max(imag(lambda))=',maxval(aimag(ceigvals))) endif ! Return real components only eigvals(:n) = real(ceigvals,kind=${rk}$) call linalg_error_handling(err0,err) end subroutine stdlib_linalg_real_eig_${ri}$_schur #:endfor end submodule stdlib_linalg_schur fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_determinant.fypp0000664000175000017500000001677515135654166026344 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_linalg) stdlib_linalg_determinant !! Determinant of a rectangular matrix use stdlib_linalg_constants use stdlib_linalg_lapack, only: getrf use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR implicit none ! Function interface character(*), parameter :: this = 'determinant' contains ! BLAS/LAPACK backends do not currently support xdp #:for rk,rt in RC_KINDS_TYPES #:if rk!="xdp" pure module function stdlib_linalg_pure_${rt[0]}$${rk}$determinant(a) result(det) !!### Summary !! Compute determinant of a real square matrix (pure interface). !! !!### Description !! !! This function computes the determinant of a real square matrix. !! !! param: a Input matrix of size [m,n]. !! return: det Matrix determinant. !! !!### Example !! !!```fortran !! !! ${rt}$ :: matrix(3,3) !! ${rt}$ :: determinant !! matrix = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) !! determinant = det(matrix) !! !!``` !> Input matrix a[m,n] ${rt}$, intent(in) :: a(:,:) !> Matrix determinant ${rt}$ :: det !! Local variables type(linalg_state_type) :: err0 integer(ilp) :: m,n,info,perm,k integer(ilp), allocatable :: ipiv(:) ${rt}$, allocatable :: amat(:,:) ! Matrix determinant size m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) if (m/=n .or. .not.min(m,n)>=0) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid or non-square matrix: a=[',m,',',n,']') det = 0.0_${rk}$ ! Process output and return call linalg_error_handling(err0) return end if select case (m) case (0) ! Empty array has determinant 1 because math det = 1.0_${rk}$ case (1) ! Scalar input det = a(1,1) case default ! Find determinant from LU decomposition ! Initialize a matrix temporary allocate(amat(m,n),source=a) ! Pivot indices allocate(ipiv(n)) ! Compute determinant from LU factorization, then calculate the ! product of all diagonal entries of the U factor. call getrf(m,n,amat,m,ipiv,info) select case (info) case (0) ! Success: compute determinant ! Start with real 1.0 det = 1.0_${rk}$ perm = 0 do k=1,n if (ipiv(k)/=k) perm = perm+1 det = det*amat(k,k) end do if (mod(perm,2)/=0) det = -det case (:-1) err0 = linalg_state_type(this,LINALG_ERROR,'invalid matrix size a=[',m,',',n,']') case (1:) err0 = linalg_state_type(this,LINALG_ERROR,'singular matrix') case default err0 = linalg_state_type(this,LINALG_INTERNAL_ERROR,'catastrophic error') end select deallocate(amat) end select ! Process output and return call linalg_error_handling(err0) end function stdlib_linalg_pure_${rt[0]}$${rk}$determinant module function stdlib_linalg_${rt[0]}$${rk}$determinant(a,overwrite_a,err) result(det) !!### Summary !! Compute determinant of a square matrix (with error control). !! !!### Description !! !! This function computes the determinant of a square matrix with error control. !! !! param: a Input matrix of size [m,n]. !! param: overwrite_a [optional] Flag indicating if the input matrix can be overwritten. !! param: err State return flag. !! return: det Matrix determinant. !! !!### Example !! !!```fortran !! !! ${rt}$ :: matrix(3,3) !! ${rt}$ :: determinant !! matrix = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) !! determinant = det(matrix, err=err) !! !!``` ! !> Input matrix a[m,n] ${rt}$, intent(inout), target :: a(:,:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> State return flag. type(linalg_state_type), intent(out) :: err !> Matrix determinant ${rt}$ :: det !! Local variables type(linalg_state_type) :: err0 integer(ilp) :: m,n,info,perm,k integer(ilp), allocatable :: ipiv(:) logical(lk) :: copy_a ${rt}$, pointer :: amat(:,:) ! Matrix determinant size m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) if (m/=n .or. .not.min(m,n)>=0) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid or non-square matrix: a=[',m,',',n,']') det = 0.0_${rk}$ ! Process output and return call linalg_error_handling(err0,err) return end if ! Can A be overwritten? By default, do not overwrite if (present(overwrite_a)) then copy_a = .not.overwrite_a else copy_a = .true._lk endif select case (m) case (0) ! Empty array has determinant 1 because math det = 1.0_${rk}$ case (1) ! Scalar input det = a(1,1) case default ! Find determinant from LU decomposition ! Initialize a matrix temporary if (copy_a) then allocate(amat, source=a) else amat => a endif ! Pivot indices allocate(ipiv(n)) ! Compute determinant from LU factorization, then calculate the ! product of all diagonal entries of the U factor. call getrf(m,n,amat,m,ipiv,info) select case (info) case (0) ! Success: compute determinant ! Start with real 1.0 det = 1.0_${rk}$ perm = 0 do k=1,n if (ipiv(k)/=k) perm = perm+1 det = det*amat(k,k) end do if (mod(perm,2)/=0) det = -det case (:-1) err0 = linalg_state_type(this,LINALG_ERROR,'invalid matrix size a=[',m,',',n,']') case (1:) err0 = linalg_state_type(this,LINALG_ERROR,'singular matrix') case default err0 = linalg_state_type(this,LINALG_INTERNAL_ERROR,'catastrophic error') end select if (copy_a) deallocate(amat) end select ! Process output and return call linalg_error_handling(err0,err) end function stdlib_linalg_${rt[0]}$${rk}$determinant #:endif #:endfor end submodule stdlib_linalg_determinant fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_qr.fypp0000664000175000017500000004044515135654166024443 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_linalg) stdlib_linalg_qr use stdlib_linalg_constants use stdlib_linalg_lapack, only: geqrf, geqp3, orgqr, ungqr use stdlib_linalg_lapack_aux, only: handle_geqrf_info, handle_orgqr_info, handle_geqp3_info use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR implicit none character(*), parameter :: this = 'qr' contains ! Check problem size and evaluate whether full/reduced problem is requested pure subroutine check_problem_size(m,n,q1,q2,r1,r2,err,reduced) integer(ilp), intent(in) :: m,n,q1,q2,r1,r2 type(linalg_state_type), intent(out) :: err logical, intent(out) :: reduced integer(ilp) :: k k = min(m,n) reduced = .false. ! Check sizes if (m<1 .or. n<1) then err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size: a(m,n)=',[m,n]) else ! Check if we should operate on reduced full QR ! - Reduced: shape(Q)==[m,k], shape(R)==[k,n] ! - Full : shape(Q)==[m,m], shape(R)==[m,n] if (all([q1,q2]==[m,k] .and. [r1,r2]==[k,n])) then reduced = .true. elseif (all([q1,q2]==[m,m] .and. [r1,r2]==[m,n])) then reduced = .false. else err = linalg_state_type(this,LINALG_VALUE_ERROR,'with a=',[m,n],'q=',[q1,q2],'r=',[r1,r2], & 'problem is neither full (q=',[m,m],'r=',[m,n],') nor reduced (q=',[m,m],'r=',[m,n],')') endif end if end subroutine check_problem_size #:for rk,rt,ri in RC_KINDS_TYPES ! Get workspace size for QR operations pure module subroutine get_qr_${ri}$_workspace(a,lwork,err) !> Input matrix a[m,n] ${rt}$, intent(in), target :: a(:,:) !> Minimum workspace size for both operations integer(ilp), intent(out) :: lwork !> State return flag. Returns an error if the query failed type(linalg_state_type), optional, intent(out) :: err integer(ilp) :: m,n,k,info,lwork_qr,lwork_ord ${rt}$ :: work_dummy(1),tau_dummy(1),a_dummy(1,1) type(linalg_state_type) :: err0 lwork = -1_ilp !> Problem sizes m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) ! QR space lwork_qr = -1_ilp call geqrf(m,n,a_dummy,m,tau_dummy,work_dummy,lwork_qr,info) call handle_geqrf_info(this,info,m,n,lwork_qr,err0) if (err0%error()) then call linalg_error_handling(err0,err) return endif lwork_qr = ceiling(real(work_dummy(1),kind=${rk}$),kind=ilp) ! Ordering space (for full factorization) lwork_ord = -1_ilp call #{if rt.startswith('complex')}# ungqr #{else}# orgqr #{endif}# & (m,m,k,a_dummy,m,tau_dummy,work_dummy,lwork_ord,info) call handle_orgqr_info(this,info,m,n,k,lwork_ord,err0) if (err0%error()) then call linalg_error_handling(err0,err) return endif lwork_ord = ceiling(real(work_dummy(1),kind=${rk}$),kind=ilp) ! Pick the largest size, so two operations can be performed with the same allocation lwork = max(lwork_qr, lwork_ord) end subroutine get_qr_${ri}$_workspace ! Compute the solution to a real system of linear equations A * X = B pure module subroutine stdlib_linalg_${ri}$_qr(a,q,r,overwrite_a,storage,err) !> Input matrix a[m,n] ${rt}$, intent(inout), target :: a(:,:) !> Orthogonal matrix Q ([m,m], or [m,k] if reduced) ${rt}$, intent(out), contiguous, target :: q(:,:) !> Upper triangular matrix R ([m,n], or [k,n] if reduced) ${rt}$, intent(out), contiguous, target :: r(:,:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] Provide pre-allocated workspace, size to be checked with qr_space ${rt}$, intent(out), optional, target :: storage(:) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Local variables type(linalg_state_type) :: err0 integer(ilp) :: i,j,m,n,k,q1,q2,r1,r2,lda,lwork,info logical(lk) :: overwrite_a_,use_q_matrix,reduced ${rt}$ :: r11 ${rt}$, parameter :: zero = 0.0_${rk}$ ${rt}$, pointer :: amat(:,:),tau(:),work(:) !> Problem sizes m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) q1 = size(q,1,kind=ilp) q2 = size(q,2,kind=ilp) r1 = size(r,1,kind=ilp) r2 = size(r,2,kind=ilp) ! Check if we should operate on reduced full QR call check_problem_size(m,n,q1,q2,r1,r2,err0,reduced) if (err0%error()) then call linalg_error_handling(err0,err) return end if ! Check if Q can be used as temporary storage for A, ! to be destroyed by *GEQRF use_q_matrix = q1>=m .and. q2>=n ! Can A be overwritten? By default, do not overwrite overwrite_a_ = .false._lk if (present(overwrite_a) .and. .not.use_q_matrix) overwrite_a_ = overwrite_a ! Initialize a matrix temporary, or reuse available ! storage if possible if (use_q_matrix) then amat => q q(:m,:n) = a elseif (overwrite_a_) then amat => a else allocate(amat(m,n),source=a) endif lda = size(amat,1,kind=ilp) ! To store the elementary reflectors, we need a [1:k] column. if (.not.use_q_matrix) then ! Q is not being used as the storage matrix tau(1:k) => q(1:k,1) else ! R has unused contiguous storage in the 1st column, except for the ! diagonal element. So, use the full column and store it in a dummy variable tau(1:k) => r(1:k,1) endif ! Retrieve workspace size call get_qr_${ri}$_workspace(a,lwork,err0) if (err0%ok()) then if (present(storage)) then work => storage else allocate(work(lwork)) endif if (.not.size(work,kind=ilp)>=lwork) then err0 = linalg_state_type(this,LINALG_ERROR,'insufficient workspace: should be at least ',lwork) call linalg_error_handling(err0,err) return endif ! Compute factorization. call geqrf(m,n,amat,m,tau,work,lwork,info) call handle_geqrf_info(this,info,m,n,lwork,err0) if (err0%ok()) then ! Get R matrix out before overwritten. ! Do not copy the first column at this stage: it may be being used by `tau` r11 = amat(1,1) forall(i=1:min(r1,m),j=2:n) r(i,j) = merge(amat(i,j),zero,i<=j) ! Convert K elementary reflectors tau(1:k) -> orthogonal matrix Q call #{if rt.startswith('complex')}# ungqr #{else}# orgqr #{endif}# & (q1,q2,k,amat,lda,tau,work,lwork,info) call handle_orgqr_info(this,info,m,n,k,lwork,err0) ! Copy result back to Q if (.not.use_q_matrix) q = amat(:q1,:q2) ! Copy first column of R r(1,1) = r11 r(2:r1,1) = zero ! Ensure last m-n rows of R are zeros, ! if full matrices were provided if (.not.reduced) r(k+1:m,1:n) = zero endif if (.not.present(storage)) deallocate(work) endif if (.not.(use_q_matrix.or.overwrite_a_)) deallocate(amat) ! Process output and return call linalg_error_handling(err0,err) end subroutine stdlib_linalg_${ri}$_qr #:endfor !--------------------------------------------------------- !----- QR decomposition with column pivoting ----- !--------------------------------------------------------- #:for rk, rt, ri in RC_KINDS_TYPES ! Get workspace size for QR operations pure module subroutine get_pivoting_qr_${ri}$_workspace(a,lwork,pivoting,err) !> Input matrix a[m,n] ${rt}$, intent(in), target :: a(:,:) !> Minimum workspace size for both operations integer(ilp), intent(out) :: lwork !> Pivoting flag. logical(lk), intent(in) :: pivoting !> State return flag. Returns an error if the query failed type(linalg_state_type), optional, intent(out) :: err integer(ilp) :: m,n,k,info,lwork_qr,lwork_ord ${rt}$ :: work_dummy(1),tau_dummy(1),a_dummy(1,1) integer(ilp) :: jpvt_dummy(1) real(${rk}$) :: rwork_dummy(1) type(linalg_state_type) :: err0 if (pivoting) then lwork = -1_ilp !> Problem sizes m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) ! QR space lwork_qr = -1_ilp #:if rt.startswith('complex') call geqp3(m, n, a_dummy, m, jpvt_dummy, tau_dummy, work_dummy, lwork_qr, rwork_dummy, info) #:else call geqp3(m, n, a_dummy, m, jpvt_dummy, tau_dummy, work_dummy, lwork_qr, info) #:endif call handle_geqp3_info(this, info, m, n, lwork_qr, err0) if (err0%error()) then call linalg_error_handling(err0,err) return endif lwork_qr = ceiling(real(work_dummy(1),kind=${rk}$),kind=ilp) ! Ordering space (for full factorization) lwork_ord = -1_ilp call #{if rt.startswith('complex')}# ungqr #{else}# orgqr #{endif}# & (m,k,k,a_dummy,m,tau_dummy,work_dummy,lwork_ord,info) call handle_orgqr_info(this,info,m,n,k,lwork_ord,err0) if (err0%error()) then call linalg_error_handling(err0,err) return endif lwork_ord = ceiling(real(work_dummy(1),kind=${rk}$),kind=ilp) ! Pick the largest size, so two operations can be performed with the same allocation lwork = max(lwork_qr, lwork_ord) else call qr_space(a, lwork, err) endif end subroutine get_pivoting_qr_${ri}$_workspace pure module subroutine stdlib_linalg_${ri}$_pivoting_qr(a, q, r, pivots, overwrite_a, storage, err) !> Input matrix a[m, n] ${rt}$, intent(inout), target :: a(:, :) !> Orthogonal matrix Q ([m, m] or [m, k] if reduced) ${rt}$, intent(out), contiguous, target :: q(:, :) !> Upper triangular matrix R ([m, n] or [k, n] if reduced) ${rt}$, intent(out), contiguous, target :: r(:, :) !> Pivots. integer(ilp), intent(out) :: pivots(:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] Provide pre-allocated workspace, size to be checked with qr_space. ${rt}$, intent(out), optional, target :: storage(:) !> [optional] state return flag. On error if not requested, the code will stop. type(linalg_state_type), optional, intent(out) :: err !> Local variables. type(linalg_state_type) :: err0 integer(ilp) :: i, j, m, n, k, q1, q2, r1, r2, lda, lwork, info logical(lk) :: overwrite_a_, use_q_matrix, reduced ${rt}$ :: r11 ${rt}$, parameter :: zero = 0.0_${rk}$ ${rt}$, pointer :: amat(:, :), tau(:), work(:) #:if rt.startswith('complex') real(${rk}$) :: rwork(2*size(a, 2, kind=ilp)) #:endif !> Problem sizes. m = size(a, 1, kind=ilp) n = size(a, 2, kind=ilp) k = min(m, n) q1 = size(q, 1, kind=ilp) q2 = size(q, 2, kind=ilp) r1 = size(r, 1, kind=ilp) r2 = size(r, 2, kind=ilp) pivots = 0_ilp !> Full or thin QR factorization ? call check_problem_size(m, n, q1, q2, r1, r2, err0, reduced) if (err0%error()) then call linalg_error_handling(err0, err) return endif !> Can Q be used as temporary storage for A, ! to be destroyed by *GEQP3. use_q_matrix = q1 >= m .and. q2 >= n !> Can A be overwritten ? (By default, no). overwrite_a_ = .false._lk if (present(overwrite_a) .and. .not. use_q_matrix) overwrite_a_ = overwrite_a !> Initialize a temporary matrix or reuse available storage if possible. if (use_q_matrix) then amat(1:q1, 1:q2) => q q(1:m, 1:n) = a else if (overwrite_a_) then amat => a else allocate(amat(m, n), source=a) endif lda = size(amat, 1, kind=ilp) !> Store the elementary reflectors. if (.not. use_q_matrix) then ! Q is not being used as the storage matrix. tau(1:k) => q(1:k, 1) else ! R has unused contiguous storage in the 1st column, except for the ! r11 element. Use the full column and store it in a dummy variable. tau(1:k) => r(1:k, 1) endif ! Retrieve workspace size. call get_pivoting_qr_${ri}$_workspace(a, lwork, .true., err0) if (err0%ok()) then if (present(storage)) then work => storage else allocate(work(lwork)) endif if (.not. size(work, kind=ilp) >= lwork) then err0 = linalg_state_type(this, LINALG_ERROR, "insufficient workspace: should be at least ", lwork) call linalg_error_handling(err0, err) return endif ! Compute factorization. #:if rt.startswith('complex') call geqp3(m, n, amat, m, pivots, tau, work, lwork, rwork, info) #:else call geqp3(m, n, amat, m, pivots, tau, work, lwork, info) #:endif call handle_geqp3_info(this, info, m, n, lwork, err0) if (err0%ok()) then ! Get R matrix out before overwritten. ! Do not copy the first column at this stage: it may be used by `tau` r11 = amat(1, 1) do j = 2, r2 do i = 1, min(r1, m) r(i, j) = merge(amat(i, j), zero, i <= j) enddo enddo ! Convert K elementary reflectors tau(1:k) -> orthogonal matrix Q call #{if rt.startswith('complex')}#ungqr#{else}#orgqr#{endif}#(q1, q2, k, amat, lda, tau, work, lwork, info) call handle_orgqr_info(this, info, m, n, k, lwork, err0) ! Copy result back to Q if (.not.use_q_matrix) q = amat(1:q1, 1:q2) ! Copy first column of R r(1,1) = r11 r(2:r1,1) = zero ! Ensure last m-n rows of R are zeros, ! if full matrices were provided if (.not.reduced) r(k+1:m,1:n) = zero endif if (.not. present(storage)) deallocate(work) endif if (.not.(use_q_matrix.or.overwrite_a_)) deallocate(amat) ! Process output and return call linalg_error_handling(err0,err) end subroutine stdlib_linalg_${ri}$_pivoting_qr #:endfor end submodule stdlib_linalg_qr fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg.fypp0000664000175000017500000027322215135654166023742 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES #:set RCI_KINDS_TYPES = RC_KINDS_TYPES + INT_KINDS_TYPES #:set RHS_SUFFIX = ["one","many"] #:set RHS_SYMBOL = [ranksuffix(r) for r in [1,2]] #:set RHS_EMPTY = [emptyranksuffix(r) for r in [1,2]] #:set ALL_RHS = list(zip(RHS_SYMBOL,RHS_SUFFIX,RHS_EMPTY)) #:set EIG_PROBLEM = ["standard", "generalized"] #:set EIG_FUNCTION = ["geev","ggev"] #:set EIG_PROBLEM_LIST = list(zip(EIG_PROBLEM, EIG_FUNCTION)) module stdlib_linalg !!Provides a support for various linear algebra procedures !! ([Specification](../page/specs/stdlib_linalg.html)) use stdlib_kinds, only: xdp, int8, int16, int32, int64 use stdlib_linalg_constants, only: sp, dp, qp, lk, ilp use stdlib_error, only: error_stop use stdlib_optval, only: optval use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling implicit none private public :: chol public :: cholesky public :: det public :: operator(.det.) public :: diag public :: eig public :: eigh public :: eigvals public :: eigvalsh public :: expm, matrix_exp public :: eye public :: inv public :: invert public :: operator(.inv.) public :: pinv public :: pseudoinvert public :: operator(.pinv.) public :: lstsq public :: lstsq_space public :: constrained_lstsq public :: constrained_lstsq_space public :: norm public :: mnorm public :: get_norm public :: solve public :: solve_lu public :: solve_lstsq public :: solve_constrained_lstsq public :: trace public :: svd public :: svdvals public :: outer_product public :: kronecker_product public :: cross_product public :: qr public :: qr_space public :: schur public :: schur_space public :: is_square public :: is_diagonal public :: is_symmetric public :: is_skew_symmetric public :: hermitian public :: is_hermitian public :: is_triangular public :: is_hessenberg ! Export linalg error handling public :: linalg_state_type, linalg_error_handling interface chol !! version: experimental !! !! Computes the Cholesky factorization \( A = L \cdot L^T \), or \( A = U^T \cdot U \). !! ([Specification](../page/specs/stdlib_linalg.html#chol-compute-the-cholesky-factorization-of-a-rank-2-square-array-matrix)) !! !!### Summary !! Pure function interface for computing the Cholesky triangular factors. !! !!### Description !! !! This interface provides methods for computing the lower- or upper- triangular matrix from the !! Cholesky factorization of a `real` symmetric or `complex` Hermitian matrix. !! Supported data types include `real` and `complex`. !! !!@note The solution is based on LAPACK's `*POTRF` methods. !! #:for rk,rt,ri in RC_KINDS_TYPES pure module function stdlib_linalg_${ri}$_cholesky_fun(a,lower,other_zeroed) result(c) !> Input matrix a[m,n] ${rt}$, intent(in) :: a(:,:) !> [optional] is the lower or upper triangular factor required? Default = lower logical(lk), optional, intent(in) :: lower !> [optional] should the unused half of the return matrix be zeroed out? Default: yes logical(lk), optional, intent(in) :: other_zeroed !> Output matrix with Cholesky factors c[n,n] ${rt}$ :: c(size(a,1),size(a,2)) end function stdlib_linalg_${ri}$_cholesky_fun #:endfor end interface chol interface cholesky !! version: experimental !! !! Computes the Cholesky factorization \( A = L \cdot L^T \), or \( A = U^T \cdot U \). !! ([Specification](../page/specs/stdlib_linalg.html#cholesky-compute-the-cholesky-factorization-of-a-rank-2-square-array-matrix)) !! !!### Summary !! Pure subroutine interface for computing the Cholesky triangular factors. !! !!### Description !! !! This interface provides methods for computing the lower- or upper- triangular matrix from the !! Cholesky factorization of a `real` symmetric or `complex` Hermitian matrix. !! Supported data types include `real` and `complex`. !! The factorization is computed in-place if only one matrix argument is present; or returned into !! a second matrix argument, if present. The `lower` `logical` flag allows to select between upper or !! lower factorization; the `other_zeroed` optional `logical` flag allows to choose whether the unused !! part of the triangular matrix should be filled with zeroes. !! !!@note The solution is based on LAPACK's `*POTRF` methods. !! #:for rk,rt,ri in RC_KINDS_TYPES pure module subroutine stdlib_linalg_${ri}$_cholesky_inplace(a,lower,other_zeroed,err) !> Input matrix a[m,n] ${rt}$, intent(inout), target :: a(:,:) !> [optional] is the lower or upper triangular factor required? Default = lower logical(lk), optional, intent(in) :: lower !> [optional] should the unused half of the return matrix be zeroed out? Default: yes logical(lk), optional, intent(in) :: other_zeroed !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_${ri}$_cholesky_inplace pure module subroutine stdlib_linalg_${ri}$_cholesky(a,c,lower,other_zeroed,err) !> Input matrix a[n,n] ${rt}$, intent(in) :: a(:,:) !> Output matrix with Cholesky factors c[n,n] ${rt}$, intent(out) :: c(:,:) !> [optional] is the lower or upper triangular factor required? Default = lower logical(lk), optional, intent(in) :: lower !> [optional] should the unused half of the return matrix be zeroed out? Default: yes logical(lk), optional, intent(in) :: other_zeroed !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_${ri}$_cholesky #:endfor end interface cholesky interface diag !! version: experimental !! !! Creates a diagonal array or extract the diagonal elements of an array !! ([Specification](../page/specs/stdlib_linalg.html# !! diag-create-a-diagonal-array-or-extract-the-diagonal-elements-of-an-array)) ! ! Vector to matrix ! #:for k1, t1 in RCI_KINDS_TYPES pure module function diag_${t1[0]}$${k1}$(v) result(res) ${t1}$, intent(in) :: v(:) ${t1}$ :: res(size(v),size(v)) end function diag_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RCI_KINDS_TYPES pure module function diag_${t1[0]}$${k1}$_k(v,k) result(res) ${t1}$, intent(in) :: v(:) integer, intent(in) :: k ${t1}$ :: res(size(v)+abs(k),size(v)+abs(k)) end function diag_${t1[0]}$${k1}$_k #:endfor ! ! Matrix to vector ! #:for k1, t1 in RCI_KINDS_TYPES pure module function diag_${t1[0]}$${k1}$_mat(A) result(res) ${t1}$, intent(in) :: A(:,:) ${t1}$ :: res(minval(shape(A))) end function diag_${t1[0]}$${k1}$_mat #:endfor #:for k1, t1 in RCI_KINDS_TYPES pure module function diag_${t1[0]}$${k1}$_mat_k(A,k) result(res) ${t1}$, intent(in) :: A(:,:) integer, intent(in) :: k ${t1}$ :: res(minval(shape(A))-abs(k)) end function diag_${t1[0]}$${k1}$_mat_k #:endfor end interface ! Matrix trace interface trace !! version: experimental !! !! Computes the trace of a matrix !! ([Specification](../page/specs/stdlib_linalg.html# !! trace-trace-of-a-matrix)) #:for k1, t1 in RCI_KINDS_TYPES module procedure trace_${t1[0]}$${k1}$ #:endfor end interface ! Identity matrix interface eye !! version: experimental !! !! Constructs the identity matrix !! ([Specification](../page/specs/stdlib_linalg.html#eye-construct-the-identity-matrix)) #:for k1, t1 in RCI_KINDS_TYPES module procedure eye_${t1[0]}$${k1}$ #:endfor end interface eye ! Outer product (of two vectors) interface outer_product !! version: experimental !! !! Computes the outer product of two vectors, returning a rank-2 array !! ([Specification](../page/specs/stdlib_linalg.html# !! outer_product-computes-the-outer-product-of-two-vectors)) #:for k1, t1 in RCI_KINDS_TYPES pure module function outer_product_${t1[0]}$${k1}$(u, v) result(res) ${t1}$, intent(in) :: u(:), v(:) ${t1}$ :: res(size(u),size(v)) end function outer_product_${t1[0]}$${k1}$ #:endfor end interface outer_product interface kronecker_product !! version: experimental !! !! Computes the Kronecker product of two arrays of size M1xN1, and of M2xN2, returning an (M1*M2)x(N1*N2) array !! ([Specification](../page/specs/stdlib_linalg.html# !! kronecker_product-computes-the-kronecker-product-of-two-matrices)) #:for k1, t1 in RCI_KINDS_TYPES pure module function kronecker_product_${t1[0]}$${k1}$(A, B) result(C) ${t1}$, intent(in) :: A(:,:), B(:,:) ${t1}$ :: C(size(A,dim=1)*size(B,dim=1),size(A,dim=2)*size(B,dim=2)) end function kronecker_product_${t1[0]}$${k1}$ #:endfor end interface kronecker_product ! Cross product (of two vectors) interface cross_product !! version: experimental !! !! Computes the cross product of two vectors, returning a rank-1 and size-3 array !! ([Specification](../page/specs/stdlib_linalg.html#cross_product-computes-the-cross-product-of-two-3-d-vectors)) #:for k1, t1 in RCI_KINDS_TYPES pure module function cross_product_${t1[0]}$${k1}$(a, b) result(res) ${t1}$, intent(in) :: a(3), b(3) ${t1}$ :: res(3) end function cross_product_${t1[0]}$${k1}$ #:endfor end interface cross_product ! Check for squareness interface is_square !! version: experimental !! !! Checks if a matrix (rank-2 array) is square !! ([Specification](../page/specs/stdlib_linalg.html# !! is_square-checks-if-a-matrix-is-square)) #:for k1, t1 in RCI_KINDS_TYPES module procedure is_square_${t1[0]}$${k1}$ #:endfor end interface is_square ! Check for diagonality interface is_diagonal !! version: experimental !! !! Checks if a matrix (rank-2 array) is diagonal !! ([Specification](../page/specs/stdlib_linalg.html# !! is_diagonal-checks-if-a-matrix-is-diagonal)) #:for k1, t1 in RCI_KINDS_TYPES module procedure is_diagonal_${t1[0]}$${k1}$ #:endfor end interface is_diagonal ! Check for symmetry interface is_symmetric !! version: experimental !! !! Checks if a matrix (rank-2 array) is symmetric !! ([Specification](../page/specs/stdlib_linalg.html# !! is_symmetric-checks-if-a-matrix-is-symmetric)) #:for k1, t1 in RCI_KINDS_TYPES module procedure is_symmetric_${t1[0]}$${k1}$ #:endfor end interface is_symmetric ! Check for skew-symmetry interface is_skew_symmetric !! version: experimental !! !! Checks if a matrix (rank-2 array) is skew-symmetric !! ([Specification](../page/specs/stdlib_linalg.html# !! is_skew_symmetric-checks-if-a-matrix-is-skew-symmetric)) #:for k1, t1 in RCI_KINDS_TYPES module procedure is_skew_symmetric_${t1[0]}$${k1}$ #:endfor end interface is_skew_symmetric ! Check for Hermiticity interface is_hermitian !! version: experimental !! !! Checks if a matrix (rank-2 array) is Hermitian !! ([Specification](../page/specs/stdlib_linalg.html# !! is_hermitian-checks-if-a-matrix-is-hermitian)) #:for k1, t1 in RCI_KINDS_TYPES module procedure is_hermitian_${t1[0]}$${k1}$ #:endfor end interface is_hermitian interface hermitian !! version: experimental !! !! Computes the Hermitian version of a rank-2 matrix. !! For complex matrices, this returns `conjg(transpose(a))`. !! For real or integer matrices, this returns `transpose(a)`. !! !! Usage: !! ``` !! A = reshape([(1, 2), (3, 4), (5, 6), (7, 8)], [2, 2]) !! AH = hermitian(A) !! ``` !! !! [Specification](../page/specs/stdlib_linalg.html#hermitian-compute-the-hermitian-version-of-a-rank-2-matrix) !! #:for k1, t1 in RCI_KINDS_TYPES pure module function hermitian_${t1[0]}$${k1}$(a) result(ah) ${t1}$, intent(in) :: a(:,:) ${t1}$ :: ah(size(a, 2), size(a, 1)) end function hermitian_${t1[0]}$${k1}$ #:endfor end interface hermitian ! Check for triangularity interface is_triangular !! version: experimental !! !! Checks if a matrix (rank-2 array) is triangular !! ([Specification](../page/specs/stdlib_linalg.html# !! is_triangular-checks-if-a-matrix-is-triangular)) #:for k1, t1 in RCI_KINDS_TYPES module procedure is_triangular_${t1[0]}$${k1}$ #:endfor end interface is_triangular ! Check for matrix being Hessenberg interface is_hessenberg !! version: experimental !! !! Checks if a matrix (rank-2 array) is Hessenberg !! ([Specification](../page/specs/stdlib_linalg.html# !! is_hessenberg-checks-if-a-matrix-is-hessenberg)) #:for k1, t1 in RCI_KINDS_TYPES module procedure is_Hessenberg_${t1[0]}$${k1}$ #:endfor end interface is_hessenberg ! Solve linear system system Ax=b. interface solve !! version: experimental !! !! Solves the linear system \( A \cdot x = b \) for the unknown vector \( x \) from a square matrix \( A \). !! ([Specification](../page/specs/stdlib_linalg.html#solve-solves-a-linear-matrix-equation-or-a-linear-system-of-equations)) !! !!### Summary !! Interface for solving a linear system arising from a general matrix. !! !!### Description !! !! This interface provides methods for computing the solution of a linear matrix system. !! Supported data types include `real` and `complex`. No assumption is made on the matrix !! structure. !! The function can solve simultaneously either one (from a 1-d right-hand-side vector `b(:)`) !! or several (from a 2-d right-hand-side vector `b(:,:)`) systems. !! !!@note The solution is based on LAPACK's generic LU decomposition based solvers `*GESV`. !! #:for nd,ndsuf,nde in ALL_RHS #:for rk,rt,ri in RC_KINDS_TYPES module function stdlib_linalg_${ri}$_solve_${ndsuf}$(a,b,overwrite_a,err) result(x) !> Input matrix a[n,n] ${rt}$, intent(inout), target :: a(:,:) !> Right hand side vector or array, b[n] or b[n,nrhs] ${rt}$, intent(in) :: b${nd}$ !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out) :: err !> Result array/matrix x[n] or x[n,nrhs] ${rt}$, allocatable, target :: x${nd}$ end function stdlib_linalg_${ri}$_solve_${ndsuf}$ pure module function stdlib_linalg_${ri}$_pure_solve_${ndsuf}$(a,b) result(x) !> Input matrix a[n,n] ${rt}$, intent(in) :: a(:,:) !> Right hand side vector or array, b[n] or b[n,nrhs] ${rt}$, intent(in) :: b${nd}$ !> Result array/matrix x[n] or x[n,nrhs] ${rt}$, allocatable, target :: x${nd}$ end function stdlib_linalg_${ri}$_pure_solve_${ndsuf}$ #:endfor #:endfor end interface solve ! Solve linear system Ax = b using LU decomposition (subroutine interface). interface solve_lu !! version: experimental !! !! Solves the linear system \( A \cdot x = b \) for the unknown vector \( x \) from a square matrix \( A \). !! ([Specification](../page/specs/stdlib_linalg.html#solve-lu-solves-a-linear-matrix-equation-or-a-linear-system-of-equations-subroutine-interface)) !! !!### Summary !! Subroutine interface for solving a linear system using LU decomposition. !! !!### Description !! !! This interface provides methods for computing the solution of a linear matrix system using !! a subroutine. Supported data types include `real` and `complex`. No assumption is made on the matrix !! structure. Preallocated space for the solution vector `x` is user-provided, and it may be provided !! for the array of pivot indices, `pivot`. If all pre-allocated work spaces are provided, no internal !! memory allocations take place when using this interface. !! The function can solve simultaneously either one (from a 1-d right-hand-side vector `b(:)`) !! or several (from a 2-d right-hand-side vector `b(:,:)`) systems. !! !!@note The solution is based on LAPACK's generic LU decomposition based solvers `*GESV`. !! #:for nd,ndsuf,nde in ALL_RHS #:for rk,rt,ri in RC_KINDS_TYPES pure module subroutine stdlib_linalg_${ri}$_solve_lu_${ndsuf}$(a,b,x,pivot,overwrite_a,err) !> Input matrix a[n,n] ${rt}$, intent(inout), target :: a(:,:) !> Right hand side vector or array, b[n] or b[n,nrhs] ${rt}$, intent(in) :: b${nd}$ !> Result array/matrix x[n] or x[n,nrhs] ${rt}$, intent(inout), contiguous, target :: x${nd}$ !> [optional] Storage array for the diagonal pivot indices integer(ilp), optional, intent(inout), target :: pivot(:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_${ri}$_solve_lu_${ndsuf}$ #:endfor #:endfor end interface solve_lu ! Least squares solution to system Ax=b, i.e. such that the 2-norm abs(b-Ax) is minimized. interface lstsq !! version: experimental !! !! Computes the squares solution to system \( A \cdot x = b \). !! ([Specification](../page/specs/stdlib_linalg.html#lstsq-computes-the-least-squares-solution-to-a-linear-matrix-equation)) !! !!### Summary !! Interface for computing least squares, i.e. the 2-norm \( || (b-A \cdot x ||_2 \) minimizing solution. !! !!### Description !! !! This interface provides methods for computing the least squares of a linear matrix system. !! Supported data types include `real` and `complex`. !! !!@note The solution is based on LAPACK's singular value decomposition `*GELSD` methods. !! #:for nd,ndsuf,nde in ALL_RHS #:for rk,rt,ri in RC_KINDS_TYPES module function stdlib_linalg_${ri}$_lstsq_${ndsuf}$(a,b,cond,overwrite_a,rank,err) result(x) !> Input matrix a[n,n] ${rt}$, intent(inout), target :: a(:,:) !> Right hand side vector or array, b[n] or b[n,nrhs] ${rt}$, intent(in) :: b${nd}$ !> [optional] cutoff for rank evaluation: singular values s(i)<=cond*maxval(s) are considered 0. real(${rk}$), optional, intent(in) :: cond !> [optional] Can A,b data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] Return rank of A integer(ilp), optional, intent(out) :: rank !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Result array/matrix x[n] or x[n,nrhs] ${rt}$, allocatable, target :: x${nd}$ end function stdlib_linalg_${ri}$_lstsq_${ndsuf}$ #:endfor #:endfor end interface lstsq ! Least squares solution to system Ax=b, i.e. such that the 2-norm abs(b-Ax) is minimized. interface solve_lstsq !! version: experimental !! !! Computes the squares solution to system \( A \cdot x = b \). !! ([Specification](../page/specs/stdlib_linalg.html#solve-lstsq-compute-the-least-squares-solution-to-a-linear-matrix-equation-subroutine-interface)) !! !!### Summary !! Subroutine interface for computing least squares, i.e. the 2-norm \( || (b-A \cdot x ||_2 \) minimizing solution. !! !!### Description !! !! This interface provides methods for computing the least squares of a linear matrix system using !! a subroutine. Supported data types include `real` and `complex`. If pre-allocated work spaces !! are provided, no internal memory allocations take place when using this interface. !! !!@note The solution is based on LAPACK's singular value decomposition `*GELSD` methods. !! #:for nd,ndsuf,nde in ALL_RHS #:for rk,rt,ri in RC_KINDS_TYPES module subroutine stdlib_linalg_${ri}$_solve_lstsq_${ndsuf}$(a,b,x,real_storage,int_storage,& #{if rt.startswith('c')}#cmpl_storage,#{endif}#cond,singvals,overwrite_a,rank,err) !> Input matrix a[n,n] ${rt}$, intent(inout), target :: a(:,:) !> Right hand side vector or array, b[n] or b[n,nrhs] ${rt}$, intent(in) :: b${nd}$ !> Result array/matrix x[n] or x[n,nrhs] ${rt}$, intent(inout), contiguous, target :: x${nd}$ !> [optional] real working storage space real(${rk}$), optional, intent(inout), target :: real_storage(:) !> [optional] integer working storage space integer(ilp), optional, intent(inout), target :: int_storage(:) #:if rt.startswith('complex') !> [optional] complex working storage space ${rt}$, optional, intent(inout), target :: cmpl_storage(:) #:endif !> [optional] cutoff for rank evaluation: singular values s(i)<=cond*maxval(s) are considered 0. real(${rk}$), optional, intent(in) :: cond !> [optional] list of singular values [min(m,n)], in descending magnitude order, returned by the SVD real(${rk}$), optional, intent(out), target :: singvals(:) !> [optional] Can A,b data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] Return rank of A integer(ilp), optional, intent(out) :: rank !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_${ri}$_solve_lstsq_${ndsuf}$ #:endfor #:endfor end interface solve_lstsq ! Return the working array space required by the least squares solver interface lstsq_space !! version: experimental !! !! Computes the integer, real [, complex] working space required by the least-squares solver !! ([Specification](../page/specs/stdlib_linalg.html#lstsq-space-compute-internal-working-space-requirements-for-the-least-squares-solver)) !! !!### Description !! !! This interface provides sizes of integer, real [, complex] working spaces required by the !! least-squares solver. These sizes can be used to pre-allocated working arrays in case several !! repeated least-squares solutions to a same system are sought. If pre-allocated working arrays !! are provided, no internal allocations will take place. !! #:for nd,ndsuf,nde in ALL_RHS #:for rk,rt,ri in RC_KINDS_TYPES pure module subroutine stdlib_linalg_${ri}$_lstsq_space_${ndsuf}$(a,b,lrwork,liwork#{if rt.startswith('c')}#,lcwork#{endif}#) !> Input matrix a[m,n] ${rt}$, intent(in), target :: a(:,:) !> Right hand side vector or array, b[n] or b[n,nrhs] ${rt}$, intent(in) :: b${nd}$ !> Size of the working space arrays integer(ilp), intent(out) :: lrwork,liwork#{if rt.startswith('c')}#,lcwork#{endif}# end subroutine stdlib_linalg_${ri}$_lstsq_space_${ndsuf}$ #:endfor #:endfor end interface lstsq_space ! Equality-constrained least-squares, i.e. minimize the sum of squares ! cost || Ax - b ||^2 subject to the equality constraint Cx = d. interface constrained_lstsq !! version: experimental !! !! Computes the solution of the equality constrained least-squares problem !! !! minimize || Ax - b ||² !! subject to Cx = d !! !! where A is of size `m x n` and C of size `p x n`. !! ([Specification](../page/specs/stdlib_linalg.html#constrained-lstsq)) !! !! ### Description !! !! This interface provides methods for computing the solution of an equality-constrained !! least-squares problem using a function. Supported data types include `real` and !! `complex`. !! !! @note The solution is based on LAPACK's `*GGLSE` methods. #:for rk, rt, ri in RC_KINDS_TYPES module function stdlib_linalg_${ri}$_constrained_lstsq(A, b, C, d, overwrite_matrices, err) result(x) !> Least-squares cost ${rt}$, intent(inout), target :: A(:, :), b(:) !> Equality constraints. ${rt}$, intent(inout), target :: C(:, :), d(:) !> [optional] Can A and C be overwritten? logical(lk), optional, intent(in) :: overwrite_matrices !> [optional] State return flag. type(linalg_state_type), optional, intent(out) :: err !> Solution of the constrained least-squares problem. ${rt}$, allocatable, target :: x(:) end function stdlib_linalg_${ri}$_constrained_lstsq #:endfor end interface ! Equality-constrained least-squares, i.e. minimize the sum of squares ! cost || Ax - b ||^2 subject to the equality constraint Cx = d. interface solve_constrained_lstsq !! version: experimental !! !! Computes the solution of the equality constrained least-squares problem !! !! minimize || Ax - b ||² !! subject to Cx = d !! !! where A is of size `m x n` and C of size `p x n`. !! ([Specification](../page/specs/stdlib_linalg.html#solve-constrained-lstsq)) !! !! ### Description !! !! This interface provides methods for computing the solution of an equality-constrained !! least-squares problem using a subroutine. Supported data types include `real` and !! `complex`. If a pre-allocated workspace is provided, no internal memory allocation takes !! place. !! !! @note The solution is based on LAPACK's `*GGLSE` methods. #:for rk, rt, ri in RC_KINDS_TYPES module subroutine stdlib_linalg_${ri}$_solve_constrained_lstsq(A, b, C, d, x, storage, overwrite_matrices, err) !> Least-squares cost. ${rt}$, intent(inout), target :: A(:, :), b(:) !> Equality constraints. ${rt}$, intent(inout), target :: C(:, :), d(:) !> Solution vector. ${rt}$, intent(out) :: x(:) !> [optional] Storage. ${rt}$, optional, intent(out), target :: storage(:) !> [optional] Can A and C be overwritten? logical(lk), optional, intent(in) :: overwrite_matrices !> [optional] State return flag. On error if not requested, the code stops. type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_${ri}$_solve_constrained_lstsq #:endfor end interface interface constrained_lstsq_space !! version: experimental !! !! Computes the size of the workspace required by the constrained least-squares solver. !! ([Specification](../page/specs/stdlib_linalg.html#constrained-lstsq-space)) !! !! ### Description !! !! This interface provides the size of the workspace array required by the constrained !! least-squares solver. It can be used to pre-allocate the working array in !! case several repeated solutions to a same system are sought. If pre-allocated, !! working arrays are provided, no internal allocation will take place. !! #:for rk, rt, ri in RC_KINDS_TYPES module subroutine stdlib_linalg_${ri}$_constrained_lstsq_space(A, C, lwork, err) !> Least-squares cost. ${rt}$, intent(in) :: A(:, :) !> Equality constraints. ${rt}$, intent(in) :: C(:, :) integer(ilp), intent(out) :: lwork type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_${ri}$_constrained_lstsq_space #:endfor end interface ! QR factorization of rank-2 array A interface qr !! version: experimental !! !! Computes the QR factorization of matrix \( A = Q R \). !! ([Specification](../page/specs/stdlib_linalg.html#qr-compute-the-qr-factorization-of-a-matrix)) !! !!### Summary !! Compute the QR factorization of a `real` or `complex` matrix: \( A = Q R \), where \( Q \) is orthonormal !! and \( R \) is upper-triangular. Matrix \( A \) has size `[m,n]`, with \( m\ge n \). !! !!### Description !! !! This interface provides methods for computing the QR factorization of a matrix. !! Supported data types include `real` and `complex`. If a pre-allocated work space !! is provided, no internal memory allocations take place when using this interface. !! !! Given `k = min(m,n)`, one can write \( A = \( Q_1 Q_2 \) \cdot \( \frac{R_1}{0}\) \). !! The user may want the full problem (provide `shape(Q)==[m,m]`, `shape(R)==[m,n]`) or the reduced !! problem only: \( A = Q_1 R_1 \) (provide `shape(Q)==[m,k]`, `shape(R)==[k,n]`). !! !!@note The solution is based on LAPACK's QR factorization (`*GEQRF`) and ordered matrix output (`*ORGQR`, `*UNGQR`). !! #:for rk,rt,ri in RC_KINDS_TYPES pure module subroutine stdlib_linalg_${ri}$_qr(a,q,r,overwrite_a,storage,err) !> Input matrix a[m,n] ${rt}$, intent(inout), target :: a(:,:) !> Orthogonal matrix Q ([m,m], or [m,k] if reduced) ${rt}$, intent(out), contiguous, target :: q(:,:) !> Upper triangular matrix R ([m,n], or [k,n] if reduced) ${rt}$, intent(out), contiguous, target :: r(:,:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] Provide pre-allocated workspace, size to be checked with qr_space ${rt}$, intent(out), optional, target :: storage(:) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_${ri}$_qr pure module subroutine stdlib_linalg_${ri}$_pivoting_qr(a, q, r, pivots, overwrite_a, storage, err) !> Input matrix a[m, n] ${rt}$, intent(inout), target :: a(:, :) !> Orthogonal matrix Q ([m, m] or [m, k] if reduced) ${rt}$, intent(out), contiguous, target :: q(:, :) !> Upper triangular matrix R ([m, n] or [k, n] if reduced) ${rt}$, intent(out), contiguous, target :: r(:, :) !> Pivots. integer(ilp), intent(out) :: pivots(:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] Provide pre-allocated workspace, size to be checked with qr_space. ${rt}$, intent(out), optional, target :: storage(:) !> [optional] state return flag. On error if not requested, the code will stop. type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_${ri}$_pivoting_qr #:endfor end interface qr ! Return the working array space required by the QR factorization solver interface qr_space !! version: experimental !! !! Computes the working array space required by the QR factorization solver !! ([Specification](../page/specs/stdlib_linalg.html#qr-space-compute-internal-working-space-requirements-for-the-qr-factorization)) !! !!### Description !! !! This interface returns the size of the `real` or `complex` working storage required by the !! QR factorization solver. The working size only depends on the kind (`real` or `complex`) and size of !! the matrix being factorized. Storage size can be used to pre-allocate a working array in case several !! repeated QR factorizations to a same-size matrix are sought. If pre-allocated working arrays !! are provided, no internal allocations will take place during the factorization. !! #:for rk,rt,ri in RC_KINDS_TYPES pure module subroutine get_qr_${ri}$_workspace(a,lwork,err) !> Input matrix a[m,n] ${rt}$, intent(in), target :: a(:,:) !> Minimum workspace size for both operations integer(ilp), intent(out) :: lwork !> State return flag. Returns an error if the query failed type(linalg_state_type), optional, intent(out) :: err end subroutine get_qr_${ri}$_workspace pure module subroutine get_pivoting_qr_${ri}$_workspace(a, lwork, pivoting, err) !> Input matrix a[m, n] ${rt}$, intent(in), target :: a(:, :) !> Minimum workspace size for both operations. integer(ilp), intent(out) :: lwork !> Pivoting flag. logical(lk), intent(in) :: pivoting !> State return flag. Returns an error if the query failed. type(linalg_state_type), optional, intent(out) :: err end subroutine get_pivoting_qr_${ri}$_workspace #:endfor end interface qr_space ! Schur decomposition of rank-2 array A interface schur !! version: experimental !! !! Computes the Schur decomposition of matrix \( A = Z T Z^H \). !! ([Specification](../page/specs/stdlib_linalg.html#schur-compute-the-schur-decomposition-of-a-matrix)) !! !!### Summary !! Compute the Schur decomposition of a `real` or `complex` matrix: \( A = Z T Z^H \), where \( Z \) is !! orthonormal/unitary and \( T \) is upper-triangular or quasi-upper-triangular. Matrix \( A \) has size `[m,m]`. !! !!### Description !! !! This interface provides methods for computing the Schur decomposition of a matrix. !! Supported data types include `real` and `complex`. If a pre-allocated workspace is provided, no internal !! memory allocations take place when using this interface. !! !! The output matrix \( T \) is upper-triangular for `complex` input matrices and quasi-upper-triangular !! for `real` input matrices (with possible \( 2 \times 2 \) blocks on the diagonal). !! !!@note The solution is based on LAPACK's Schur decomposition routines (`*GEES`). !! #:for rk,rt,ri in RC_KINDS_TYPES module subroutine stdlib_linalg_${ri}$_schur(a, t, z, eigvals, overwrite_a, storage, err) !> Input matrix a[m,m] ${rt}$, intent(inout), target :: a(:,:) !> Schur form of A: upper-triangular or quasi-upper-triangular matrix T ${rt}$, intent(out), contiguous, target :: t(:,:) !> Unitary/orthonormal transformation matrix Z ${rt}$, optional, intent(out), contiguous, target :: z(:,:) !> [optional] Output eigenvalues that appear on the diagonal of T complex(${rk}$), optional, intent(out), contiguous, target :: eigvals(:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] Provide pre-allocated workspace, size to be checked with schur_space ${rt}$, optional, intent(inout), target :: storage(:) !> [optional] State return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_${ri}$_schur ! Schur decomposition subroutine: real eigenvalue interface module subroutine stdlib_linalg_real_eig_${ri}$_schur(a,t,z,eigvals,overwrite_a,storage,err) !> Input matrix a[m,m] ${rt}$, intent(inout), target :: a(:,:) !> Schur form of A: upper-triangular or quasi-upper-triangular matrix T ${rt}$, intent(out), contiguous, target :: t(:,:) !> Unitary/orthonormal transformation matrix Z ${rt}$, optional, intent(out), contiguous, target :: z(:,:) !> Output real eigenvalues that appear on the diagonal of T real(${rk}$), intent(out), contiguous, target :: eigvals(:) !> [optional] Provide pre-allocated workspace, size to be checked with schur_space ${rt}$, optional, intent(inout), target :: storage(:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] State return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_real_eig_${ri}$_schur #:endfor end interface schur ! Return the working array space required by the Schur decomposition solver interface schur_space !! version: experimental !! !! Computes the working array space required by the Schur decomposition solver !! ([Specification](../page/specs/stdlib_linalg.html#schur-space-compute-internal-working-space-requirements-for-the-schur-decomposition)) !! !!### Description !! !! This interface returns the size of the `real` or `complex` working storage required by the !! Schur decomposition solver. The working size only depends on the kind (`real` or `complex`) and size of !! the matrix being decomposed. Storage size can be used to pre-allocate a working array in case several !! repeated Schur decompositions of same-size matrices are sought. If pre-allocated working arrays !! are provided, no internal allocations will take place during the decomposition. !! #:for rk,rt,ri in RC_KINDS_TYPES module subroutine get_schur_${ri}$_workspace(a,lwork,err) !> Input matrix a[m,m] ${rt}$, intent(in), target :: a(:,:) !> Minimum workspace size for the decomposition operation integer(ilp), intent(out) :: lwork !> State return flag. Returns an error if the query failed type(linalg_state_type), optional, intent(out) :: err end subroutine get_schur_${ri}$_workspace #:endfor end interface schur_space interface det !! version: experimental !! !! Computes the determinant of a square matrix !! ([Specification](../page/specs/stdlib_linalg.html#det-computes-the-determinant-of-a-square-matrix)) !! !!### Summary !! Interface for computing matrix determinant. !! !!### Description !! !! This interface provides methods for computing the determinant of a matrix. !! Supported data types include `real` and `complex`. !! !!@note The provided functions are intended for square matrices only. !!@note BLAS/LAPACK backends do not currently support extended precision (``xdp``). !! !!### Example !! !!```fortran !! !! real(sp) :: a(3,3), d !! type(linalg_state_type) :: state !! a = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) !! !! ! ... !! d = det(a,err=state) !! if (state%ok()) then !! print *, 'Success! det=',d !! else !! print *, state%print() !! endif !! ! ... !!``` !! #:for rk,rt in RC_KINDS_TYPES #:if rk!="xdp" module procedure stdlib_linalg_${rt[0]}$${rk}$determinant module procedure stdlib_linalg_pure_${rt[0]}$${rk}$determinant #:endif #:endfor end interface det interface operator(.det.) !! version: experimental !! !! Determinant operator of a square matrix !! ([Specification](../page/specs/stdlib_linalg.html#det-determinant-operator-of-a-square-matrix)) !! !!### Summary !! Pure operator interface for computing matrix determinant. !! !!### Description !! !! This pure operator interface provides a convenient way to compute the determinant of a matrix. !! Supported data types include real and complex. !! !!@note The provided functions are intended for square matrices. !!@note BLAS/LAPACK backends do not currently support extended precision (``xdp``). !! !!### Example !! !!```fortran !! !! ! ... !! real(sp) :: matrix(3,3), d !! matrix = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) !! d = .det.matrix !! ! ... !! !!``` ! #:for rk,rt in RC_KINDS_TYPES #:if rk!="xdp" module procedure stdlib_linalg_pure_${rt[0]}$${rk}$determinant #:endif #:endfor end interface operator(.det.) interface #:for rk,rt in RC_KINDS_TYPES #:if rk!="xdp" module function stdlib_linalg_${rt[0]}$${rk}$determinant(a,overwrite_a,err) result(det) !> Input matrix a[m,n] ${rt}$, intent(inout), target :: a(:,:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> State return flag. type(linalg_state_type), intent(out) :: err !> Matrix determinant ${rt}$ :: det end function stdlib_linalg_${rt[0]}$${rk}$determinant pure module function stdlib_linalg_pure_${rt[0]}$${rk}$determinant(a) result(det) !> Input matrix a[m,n] ${rt}$, intent(in) :: a(:,:) !> Matrix determinant ${rt}$ :: det end function stdlib_linalg_pure_${rt[0]}$${rk}$determinant #:endif #:endfor end interface ! Matrix Inverse: Function interface interface inv !! version: experimental !! !! Inverse of a square matrix !! ([Specification](../page/specs/stdlib_linalg.html#inv-inverse-of-a-square-matrix)) !! !!### Summary !! This interface provides methods for computing the inverse of a square `real` or `complex` matrix. !! The inverse \( A^{-1} \) is defined such that \( A \cdot A^{-1} = A^{-1} \cdot A = I_n \). !! !!### Description !! !! This function interface provides methods that return the inverse of a square matrix. !! Supported data types include `real` and `complex`. !! The inverse matrix \( A^{-1} \) is returned as a function result. !! Exceptions are raised in case of singular matrix or invalid size, and trigger an `error stop` if !! the state flag `err` is not provided. !! !!@note The provided functions are intended for square matrices. !! #:for rk,rt,ri in RC_KINDS_TYPES module function stdlib_linalg_inverse_${ri}$(a,err) result(inva) !> Input matrix a[n,n] ${rt}$, intent(in) :: a(:,:) !> Output matrix inverse ${rt}$, allocatable :: inva(:,:) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end function stdlib_linalg_inverse_${ri}$ #:endfor end interface inv ! Matrix Inverse: Subroutine interface - in-place inversion interface invert !! version: experimental !! !! Inversion of a square matrix !! ([Specification](../page/specs/stdlib_linalg.html#invert-inversion-of-a-square-matrix)) !! !!### Summary !! This interface provides methods for inverting a square `real` or `complex` matrix in-place. !! The inverse \( A^{-1} \) is defined such that \( A \cdot A^{-1} = A^{-1} \cdot A = I_n \). !! !!### Description !! !! This subroutine interface provides a way to compute the inverse of a matrix. !! Supported data types include `real` and `complex`. !! The user may provide a unique matrix argument `a`. In this case, `a` is replaced by the inverse matrix. !! on output. Otherwise, one may provide two separate arguments: an input matrix `a` and an output matrix !! `inva`. In this case, `a` will not be modified, and the inverse is returned in `inva`. !! Pre-allocated storage may be provided for the array of pivot indices, `pivot`. If all pre-allocated !! work spaces are provided, no internal memory allocations take place when using this interface. !! !!@note The provided subroutines are intended for square matrices. !! #:for rk,rt,ri in RC_KINDS_TYPES module subroutine stdlib_linalg_invert_inplace_${ri}$(a,pivot,err) !> Input matrix a[n,n] ${rt}$, intent(inout) :: a(:,:) !> [optional] Storage array for the diagonal pivot indices integer(ilp), optional, intent(inout), target :: pivot(:) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_invert_inplace_${ri}$ ! Compute the square matrix inverse of a module subroutine stdlib_linalg_invert_split_${ri}$(a,inva,pivot,err) !> Input matrix a[n,n]. ${rt}$, intent(in) :: a(:,:) !> Inverse matrix a[n,n]. ${rt}$, intent(out) :: inva(:,:) !> [optional] Storage array for the diagonal pivot indices integer(ilp), optional, intent(inout), target :: pivot(:) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_invert_split_${ri}$ #:endfor end interface invert ! Matrix Inverse: Operator interface interface operator(.inv.) !! version: experimental !! !! Inverse operator of a square matrix !! ([Specification](../page/specs/stdlib_linalg.html#inv-inverse-operator-of-a-square-matrix)) !! !!### Summary !! Operator interface for computing the inverse of a square `real` or `complex` matrix. !! !!### Description !! !! This operator interface provides a convenient way to compute the inverse of a matrix. !! Supported data types include `real` and `complex`. On input errors or singular matrix, !! NaNs will be returned. !! !!@note The provided functions are intended for square matrices. !! #:for rk,rt,ri in RC_KINDS_TYPES module function stdlib_linalg_inverse_${ri}$_operator(a) result(inva) !> Input matrix a[n,n] ${rt}$, intent(in) :: a(:,:) !> Result matrix ${rt}$, allocatable :: inva(:,:) end function stdlib_linalg_inverse_${ri}$_operator #:endfor end interface operator(.inv.) ! Moore-Penrose Pseudo-Inverse: Function interface interface pinv !! version: experimental !! !! Pseudo-inverse of a matrix !! ([Specification](../page/specs/stdlib_linalg.html#pinv-moore-penrose-pseudo-inverse-of-a-matrix)) !! !!### Summary !! This interface provides methods for computing the Moore-Penrose pseudo-inverse of a matrix. !! The pseudo-inverse \( A^{+} \) is a generalization of the matrix inverse, computed for square, singular, !! or rectangular matrices. It is defined such that it satisfies the conditions: !! - \( A \cdot A^{+} \cdot A = A \) !! - \( A^{+} \cdot A \cdot A^{+} = A^{+} \) !! - \( (A \cdot A^{+})^T = A \cdot A^{+} \) !! - \( (A^{+} \cdot A)^T = A^{+} \cdot A \) !! !!### Description !! !! This function interface provides methods that return the Moore-Penrose pseudo-inverse of a matrix. !! Supported data types include `real` and `complex`. !! The pseudo-inverse \( A^{+} \) is returned as a function result. The computation is based on the !! singular value decomposition (SVD). An optional relative tolerance `rtol` is provided to control the !! inclusion of singular values during inversion. Singular values below \( \text{rtol} \cdot \sigma_{\max} \) !! are treated as zero, where \( \sigma_{\max} \) is the largest singular value. If `rtol` is not provided, !! a default threshold is applied. !! !! Exceptions are raised in case of computational errors or invalid input, and trigger an `error stop` !! if the state flag `err` is not provided. !! !!@note The provided functions are intended for both rectangular and square matrices. !! #:for rk,rt,ri in RC_KINDS_TYPES module function stdlib_linalg_pseudoinverse_${ri}$(a,rtol,err) result(pinva) !> Input matrix a[m,n] ${rt}$, intent(in), target :: a(:,:) !> [optional] Relative tolerance for singular value cutoff real(${rk}$), optional, intent(in) :: rtol !> [optional] State return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Output matrix pseudo-inverse [n,m] ${rt}$ :: pinva(size(a,2,kind=ilp),size(a,1,kind=ilp)) end function stdlib_linalg_pseudoinverse_${ri}$ #:endfor end interface pinv ! Moore-Penrose Pseudo-Inverse: Subroutine interface interface pseudoinvert !! version: experimental !! !! Computation of the Moore-Penrose pseudo-inverse !! ([Specification](../page/specs/stdlib_linalg.html#pseudoinvert-moore-penrose-pseudo-inverse-of-a-matrix)) !! !!### Summary !! This interface provides methods for computing the Moore-Penrose pseudo-inverse of a rectangular !! or square `real` or `complex` matrix. !! The pseudo-inverse \( A^{+} \) generalizes the matrix inverse and satisfies the properties: !! - \( A \cdot A^{+} \cdot A = A \) !! - \( A^{+} \cdot A \cdot A^{+} = A^{+} \) !! - \( (A \cdot A^{+})^T = A \cdot A^{+} \) !! - \( (A^{+} \cdot A)^T = A^{+} \cdot A \) !! !!### Description !! !! This subroutine interface provides a way to compute the Moore-Penrose pseudo-inverse of a matrix. !! Supported data types include `real` and `complex`. !! Users must provide two matrices: the input matrix `a` [m,n] and the output pseudo-inverse `pinva` [n,m]. !! The input matrix `a` is used to compute the pseudo-inverse and is not modified. The computed !! pseudo-inverse is stored in `pinva`. The computation is based on the singular value decomposition (SVD). !! !! An optional relative tolerance `rtol` is used to control the inclusion of singular values in the !! computation. Singular values below \( \text{rtol} \cdot \sigma_{\max} \) are treated as zero, !! where \( \sigma_{\max} \) is the largest singular value. If `rtol` is not provided, a default !! threshold is applied. !! !! Exceptions are raised in case of computational errors or invalid input, and trigger an `error stop` !! if the state flag `err` is not provided. !! !!@note The provided subroutines are intended for both rectangular and square matrices. !! #:for rk,rt,ri in RC_KINDS_TYPES module subroutine stdlib_linalg_pseudoinvert_${ri}$(a,pinva,rtol,err) !> Input matrix a[m,n] ${rt}$, intent(inout) :: a(:,:) !> Output pseudo-inverse matrix [n,m] ${rt}$, intent(out) :: pinva(:,:) !> [optional] Relative tolerance for singular value cutoff real(${rk}$), optional, intent(in) :: rtol !> [optional] State return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_pseudoinvert_${ri}$ #:endfor end interface pseudoinvert ! Moore-Penrose Pseudo-Inverse: Operator interface interface operator(.pinv.) !! version: experimental !! !! Pseudo-inverse operator of a matrix !! ([Specification](../page/specs/stdlib_linalg.html#pinv-moore-penrose-pseudo-inverse-operator)) !! !!### Summary !! Operator interface for computing the Moore-Penrose pseudo-inverse of a `real` or `complex` matrix. !! !!### Description !! !! This operator interface provides a convenient way to compute the Moore-Penrose pseudo-inverse !! of a matrix. Supported data types include `real` and `complex`. The pseudo-inverse \( A^{+} \) !! is computed using singular value decomposition (SVD), with singular values below an internal !! threshold treated as zero. !! !! For computational errors or invalid input, the function may return a matrix filled with NaNs. !! !!@note The provided functions are intended for both rectangular and square matrices. !! #:for rk,rt,ri in RC_KINDS_TYPES module function stdlib_linalg_pinv_${ri}$_operator(a) result(pinva) !> Input matrix a[m,n] ${rt}$, intent(in), target :: a(:,:) !> Result pseudo-inverse matrix ${rt}$ :: pinva(size(a,2,kind=ilp),size(a,1,kind=ilp)) end function stdlib_linalg_pinv_${ri}$_operator #:endfor end interface operator(.pinv.) ! Eigendecomposition of a square matrix: eigenvalues, and optionally eigenvectors interface eig !! version: experimental !! !! Solves the eigendecomposition \( A \cdot \bar{v} - \lambda \cdot \bar{v} \) for square matrix \( A \). !! ([Specification](../page/specs/stdlib_linalg.html#eig-eigenvalues-and-eigenvectors-of-a-square-matrix)) !! !!### Summary !! Subroutine interface for computing eigenvalues and eigenvectors of a square matrix. !! !!### Description !! !! This interface provides methods for computing the eigenvalues, and optionally eigenvectors, !! of a general square matrix. Supported data types include `real` and `complex`, and no assumption is !! made on the matrix structure. The user may request either left, right, or both !! eigenvectors to be returned. They are returned as columns of a square matrix with the same size as `A`. !! Preallocated space for both eigenvalues `lambda` and the eigenvector matrices must be user-provided. !! !!@note The solution is based on LAPACK's general eigenproblem solvers `*GEEV`. !!@note BLAS/LAPACK backends do not currently support extended precision (``xdp``). !! #:for rk,rt,ri in RC_KINDS_TYPES #:for ep,ei in EIG_PROBLEM_LIST module subroutine stdlib_linalg_eig_${ep}$_${ri}$(a#{if ei=='ggev'}#,b#{endif}#,lambda,right,left, & overwrite_a#{if ei=='ggev'}#,overwrite_b#{endif}#,err) !! Eigendecomposition of matrix A returning an array `lambda` of eigenvalues, !! and optionally right or left eigenvectors. !> Input matrix A[m,n] ${rt}$, intent(inout), target :: a(:,:) #:if ei=='ggev' !> Generalized problem matrix B[n,n] ${rt}$, intent(inout), target :: b(:,:) #:endif !> Array of eigenvalues complex(${rk}$), intent(out) :: lambda(:) !> The columns of RIGHT contain the right eigenvectors of A complex(${rk}$), optional, intent(out), target :: right(:,:) !> The columns of LEFT contain the left eigenvectors of A complex(${rk}$), optional, intent(out), target :: left(:,:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a #:if ei=='ggev' !> [optional] Can B data be overwritten and destroyed? (default: no) logical(lk), optional, intent(in) :: overwrite_b #:endif !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_eig_${ep}$_${ri}$ module subroutine stdlib_linalg_real_eig_${ep}$_${ri}$(a#{if ei=='ggev'}#,b#{endif}#,lambda,right,left, & overwrite_a#{if ei=='ggev'}#,overwrite_b#{endif}#,err) !! Eigendecomposition of matrix A returning an array `lambda` of real eigenvalues, !! and optionally right or left eigenvectors. Returns an error if the eigenvalues had !! non-trivial imaginary parts. !> Input matrix A[m,n] ${rt}$, intent(inout), target :: a(:,:) #:if ei=='ggev' !> Generalized problem matrix B[n,n] ${rt}$, intent(inout), target :: b(:,:) #:endif !> Array of real eigenvalues real(${rk}$), intent(out) :: lambda(:) !> The columns of RIGHT contain the right eigenvectors of A complex(${rk}$), optional, intent(out), target :: right(:,:) !> The columns of LEFT contain the left eigenvectors of A complex(${rk}$), optional, intent(out), target :: left(:,:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a #:if ei=='ggev' !> [optional] Can B data be overwritten and destroyed? (default: no) logical(lk), optional, intent(in) :: overwrite_b #:endif !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_real_eig_${ep}$_${ri}$ #:endfor #:endfor end interface eig ! Eigenvalues of a square matrix interface eigvals !! version: experimental !! !! Returns the eigenvalues \( lambda \), \( A \cdot \bar{v} - \lambda \cdot \bar{v} \), for square matrix \( A \). !! ([Specification](../page/specs/stdlib_linalg.html#eigvals-eigenvalues-of-a-square-matrix)) !! !!### Summary !! Function interface for computing the eigenvalues of a square matrix. !! !!### Description !! !! This interface provides functions for returning the eigenvalues of a general square matrix. !! Supported data types include `real` and `complex`, and no assumption is made on the matrix structure. !! An `error stop` is thrown in case of failure; otherwise, error information can be returned !! as an optional `type(linalg_state_type)` output flag. !! !!@note The solution is based on LAPACK's general eigenproblem solvers `*GEEV`. !!@note BLAS/LAPACK backends do not currently support extended precision (``xdp``). !! #:for rk,rt,ri in RC_KINDS_TYPES #:for ep,ei in EIG_PROBLEM_LIST module function stdlib_linalg_eigvals_${ep}$_${ri}$(a#{if ei=='ggev'}#,b#{endif}#,err) result(lambda) !! Return an array of eigenvalues of matrix A. !> Input matrix A[m,n] ${rt}$, intent(in), dimension(:,:), target :: a #:if ei=='ggev' !> Generalized problem matrix B[n,n] ${rt}$, intent(inout), dimension(:,:), target :: b #:endif !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out) :: err !> Array of singular values complex(${rk}$), allocatable :: lambda(:) end function stdlib_linalg_eigvals_${ep}$_${ri}$ module function stdlib_linalg_eigvals_noerr_${ep}$_${ri}$(a#{if ei=='ggev'}#,b#{endif}#) result(lambda) !! Return an array of eigenvalues of matrix A. !> Input matrix A[m,n] ${rt}$, intent(in), dimension(:,:), target :: a #:if ei=='ggev' !> Generalized problem matrix B[n,n] ${rt}$, intent(inout), dimension(:,:), target :: b #:endif !> Array of singular values complex(${rk}$), allocatable :: lambda(:) end function stdlib_linalg_eigvals_noerr_${ep}$_${ri}$ #:endfor #:endfor end interface eigvals ! Eigendecomposition of a real symmetric or complex hermitian matrix interface eigh !! version: experimental !! !! Solves the eigendecomposition \( A \cdot \bar{v} - \lambda \cdot \bar{v} \) for a real symmetric !! \( A = A^T \) or complex Hermitian \( A = A^H \) square matrix. !! ([Specification](../page/specs/stdlib_linalg.html#eigh-eigenvalues-and-eigenvectors-of-a-real-symmetric-or-complex-hermitian-square-matrix)) !! !!### Summary !! Subroutine interface for computing eigenvalues and eigenvectors of a real symmetric or complex Hermitian square matrix. !! !!### Description !! !! This interface provides methods for computing the eigenvalues, and optionally eigenvectors, !! of a real symmetric or complex Hermitian square matrix. Supported data types include `real` and `complex`. !! The matrix must be symmetric (if `real`) or Hermitian (if `complex`). Only the lower or upper !! half of the matrix is accessed, and the user can select which using the optional `upper_a` !! flag (default: use lower half). The vectors are orthogonal, and may be returned as columns of an optional !! matrix `vectors` with the same kind and size as `A`. !! Preallocated space for both eigenvalues `lambda` and the eigenvector matrix must be user-provided. !! !!@note The solution is based on LAPACK's eigenproblem solvers `*SYEV`/`*HEEV`. !!@note BLAS/LAPACK backends do not currently support extended precision (``xdp``). !! #:for rk,rt,ri in RC_KINDS_TYPES module subroutine stdlib_linalg_eigh_${ri}$(a,lambda,vectors,upper_a,overwrite_a,err) !! Eigendecomposition of a real symmetric or complex Hermitian matrix A returning an array `lambda` !! of eigenvalues, and optionally right or left eigenvectors. !> Input matrix A[m,n] ${rt}$, intent(inout), target :: a(:,:) !> Array of eigenvalues real(${rk}$), intent(out) :: lambda(:) !> The columns of vectors contain the orthonormal eigenvectors of A ${rt}$, optional, intent(out), target :: vectors(:,:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] Should the upper/lower half of A be used? Default: lower logical(lk), optional, intent(in) :: upper_a !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_eigh_${ri}$ #:endfor end interface eigh ! Eigenvalues of a real symmetric or complex hermitian matrix interface eigvalsh !! version: experimental !! !! Returns the eigenvalues \( lambda \), \( A \cdot \bar{v} - \lambda \cdot \bar{v} \), for a real !! symmetric \( A = A^T \) or complex Hermitian \( A = A^H \) square matrix. !! ([Specification](../page/specs/stdlib_linalg.html#eigvalsh-eigenvalues-of-a-real-symmetric-or-complex-hermitian-square-matrix)) !! !!### Summary !! Function interface for computing the eigenvalues of a real symmetric or complex hermitian square matrix. !! !!### Description !! !! This interface provides functions for returning the eigenvalues of a real symmetric or complex Hermitian !! square matrix. Supported data types include `real` and `complex`. The matrix must be symmetric !! (if `real`) or Hermitian (if `complex`). Only the lower or upper half of the matrix is accessed, !! and the user can select which using the optional `upper_a` flag (default: use lower half). !! An `error stop` is thrown in case of failure; otherwise, error information can be returned !! as an optional `type(linalg_state_type)` output flag. !! !!@note The solution is based on LAPACK's eigenproblem solvers `*SYEV`/`*HEEV`. !!@note BLAS/LAPACK backends do not currently support extended precision (``xdp``). !! #:for rk,rt,ri in RC_KINDS_TYPES module function stdlib_linalg_eigvalsh_${ri}$(a,upper_a,err) result(lambda) !! Return an array of eigenvalues of real symmetric / complex hermitian A !> Input matrix A[m,n] ${rt}$, intent(in), target :: a(:,:) !> [optional] Should the upper/lower half of A be used? Default: lower logical(lk), optional, intent(in) :: upper_a !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out) :: err !> Array of singular values real(${rk}$), allocatable :: lambda(:) end function stdlib_linalg_eigvalsh_${ri}$ module function stdlib_linalg_eigvalsh_noerr_${ri}$(a,upper_a) result(lambda) !! Return an array of eigenvalues of real symmetric / complex hermitian A !> Input matrix A[m,n] ${rt}$, intent(in), target :: a(:,:) !> [optional] Should the upper/lower half of A be used? Default: lower logical(lk), optional, intent(in) :: upper_a !> Array of singular values real(${rk}$), allocatable :: lambda(:) end function stdlib_linalg_eigvalsh_noerr_${ri}$ #:endfor end interface eigvalsh ! Singular value decomposition interface svd !! version: experimental !! !! Computes the singular value decomposition of a `real` or `complex` 2d matrix. !! ([Specification](../page/specs/stdlib_linalg.html#svd-compute-the-singular-value-decomposition-of-a-rank-2-array-matrix)) !! !!### Summary !! Interface for computing the singular value decomposition of a `real` or `complex` 2d matrix. !! !!### Description !! !! This interface provides methods for computing the singular value decomposition of a matrix. !! Supported data types include `real` and `complex`. The subroutine returns a `real` array of !! singular values, and optionally, left- and right- singular vector matrices, `U` and `V`. !! For a matrix `A` with size [m,n], full matrix storage for `U` and `V` should be [m,m] and [n,n]. !! It is possible to use partial storage [m,k] and [k,n], `k=min(m,n)`, choosing `full_matrices=.false.`. !! !!@note The solution is based on LAPACK's singular value decomposition `*GESDD` methods. !! !!### Example !! !!```fortran !! real(sp) :: a(2,3), s(2), u(2,2), vt(3,3) !! a = reshape([3,2, 2,3, 2,-2],[2,3]) !! !! call svd(A,s,u,v) !! print *, 'singular values = ',s !!``` !! #:for rk,rt,ri in RC_KINDS_TYPES module subroutine stdlib_linalg_svd_${ri}$(a,s,u,vt,overwrite_a,full_matrices,err) !!### Summary !! Compute singular value decomposition of a matrix \( A = U \cdot S \cdot \V^T \) !! !!### Description !! !! This function computes the singular value decomposition of a `real` or `complex` matrix \( A \), !! and returns the array of singular values, and optionally the left matrix \( U \) containing the !! left unitary singular vectors, and the right matrix \( V^T \), containing the right unitary !! singular vectors. !! !! param: a Input matrix of size [m,n]. !! param: s Output `real` array of size [min(m,n)] returning a list of singular values. !! param: u [optional] Output left singular matrix of size [m,m] or [m,min(m,n)] (.not.full_matrices). Contains singular vectors as columns. !! param: vt [optional] Output right singular matrix of size [n,n] or [min(m,n),n] (.not.full_matrices). Contains singular vectors as rows. !! param: overwrite_a [optional] Flag indicating if the input matrix can be overwritten. !! param: full_matrices [optional] If `.true.` (default), matrices \( U \) and \( V^T \) have size [m,m], [n,n]. Otherwise, they are [m,k], [k,n] with `k=min(m,n)`. !! param: err [optional] State return flag. !! !> Input matrix A[m,n] ${rt}$, intent(inout), target :: a(:,:) !> Array of singular values real(${rk}$), intent(out) :: s(:) !> The columns of U contain the left singular vectors ${rt}$, optional, intent(out), target :: u(:,:) !> The rows of V^T contain the right singular vectors ${rt}$, optional, intent(out), target :: vt(:,:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] full matrices have shape(u)==[m,m], shape(vh)==[n,n] (default); otherwise !> they are shape(u)==[m,k] and shape(vh)==[k,n] with k=min(m,n) logical(lk), optional, intent(in) :: full_matrices !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_svd_${ri}$ #:endfor end interface svd ! Singular values interface svdvals !! version: experimental !! !! Computes the singular values of a `real` or `complex` 2d matrix. !! ([Specification](../page/specs/stdlib_linalg.html#svdvals-compute-the-singular-values-of-a-rank-2-array-matrix)) !! !!### Summary !! !! Function interface for computing the array of singular values from the singular value decomposition !! of a `real` or `complex` 2d matrix. !! !!### Description !! !! This interface provides methods for computing the singular values a 2d matrix. !! Supported data types include `real` and `complex`. The function returns a `real` array of !! singular values, with size [min(m,n)]. !! !!@note The solution is based on LAPACK's singular value decomposition `*GESDD` methods. !! !!### Example !! !!```fortran !! real(sp) :: a(2,3), s(2) !! a = reshape([3,2, 2,3, 2,-2],[2,3]) !! !! s = svdvals(A) !! print *, 'singular values = ',s !!``` !! #:for rk,rt,ri in RC_KINDS_TYPES module function stdlib_linalg_svdvals_${ri}$(a,err) result(s) !!### Summary !! Compute singular values \(S \) from the singular-value decomposition of a matrix \( A = U \cdot S \cdot \V^T \). !! !!### Description !! !! This function returns the array of singular values from the singular value decomposition of a `real` !! or `complex` matrix \( A = U \cdot S \cdot V^T \). !! !! param: a Input matrix of size [m,n]. !! param: err [optional] State return flag. !! !!### Return value !! !! param: s `real` array of size [min(m,n)] returning a list of singular values. !! !> Input matrix A[m,n] ${rt}$, intent(in), target :: a(:,:) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Array of singular values real(${rk}$), allocatable :: s(:) end function stdlib_linalg_svdvals_${ri}$ #:endfor end interface svdvals #! Allow for integer or character norm input: i.e., norm(a,2) or norm(a, '2') #:set NORM_INPUT_TYPE = ["character(len=*)","integer(ilp)"] #:set NORM_INPUT_SHORT = ["char","int"] #:set NORM_INPUT_OPTIONS = list(zip(NORM_INPUT_TYPE,NORM_INPUT_SHORT)) ! Vector norms: function interface interface norm !! version: experimental !! !! Computes the vector norm of a generic-rank array \( A \). !! ([Specification](../page/specs/stdlib_linalg.html#norm-computes-the-vector-norm-of-a-generic-rank-array)) !! !!### Summary !! Return one of several scalar norm metrics of a `real` or `complex` input array \( A \), !! that can have any rank. For generic rank-n arrays, the scalar norm over the whole !! array is returned by default. If `n>=2` and the optional input dimension `dim` is specified, !! a rank `n-1` array is returned with dimension `dim` collapsed, containing all 1D array norms !! evaluated along dimension `dim` only. !! !! !!### Description !! !! This interface provides methods for computing the vector norm(s) of an array. !! Supported data types include `real` and `complex`. !! Input arrays may have generic rank from 1 to ${MAXRANK}$. !! !! Norm type input is mandatory, and it is provided via the `order` argument. !! This can be provided as either an `integer` value or a `character` string. !! Allowed metrics are: !! - 1-norm \( \sum_i{ \left|a_i\right| } \): `order` = 1 or '1' !! - Euclidean norm \( \sqrt{\sum_i{ a_i^2 }} \): `order` = 2 or '2' !! - p-norm \( \left( \sum_i{ \left|a_i\right|^p }\right) ^{1/p} \): `integer` `order`, order>=3 !! - Infinity norm \( \max_i{ \left|a_i\right| } \): order = huge(0) or 'inf' !! - Minus-infinity norm \( \min_i{ \left|a_i\right| } \): order = -huge(0) or '-inf' !! !!### Example !! !!```fortran !! !! real(sp) :: a(3,3), na, rown(3) !! a = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) !! !! ! L2 norm: whole matrix !! na = norm(a, 2) !! !! ! Infinity norm of each row !! rown = norm(a, 'inf', dim=2) !! !!``` !! #:for rk,rt,ri in RC_KINDS_TYPES #:for it,ii in NORM_INPUT_OPTIONS !> Scalar norms: ${rt}$ #:for rank in range(1, MAXRANK + 1) pure module function stdlib_linalg_norm_${rank}$D_order_${ii}$_${ri}$(a, order) result(nrm) !> Input ${rank}$-d matrix a${ranksuffix(rank)}$ ${rt}$, intent(in) :: a${ranksuffix(rank)}$ !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> Norm of the matrix. real(${rk}$) :: nrm end function stdlib_linalg_norm_${rank}$D_order_${ii}$_${ri}$ module function stdlib_linalg_norm_${rank}$D_order_err_${ii}$_${ri}$(a, order, err) result(nrm) !> Input ${rank}$-d matrix a${ranksuffix(rank)}$ ${rt}$, intent(in) :: a${ranksuffix(rank)}$ !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> Output state return flag. type(linalg_state_type), intent(out) :: err !> Norm of the matrix. real(${rk}$) :: nrm end function stdlib_linalg_norm_${rank}$D_order_err_${ii}$_${ri}$ #:endfor !> Array norms: ${rt}$ #:for rank in range(2, MAXRANK + 1) pure module function stdlib_linalg_norm_${rank}$D_to_${rank-1}$D_${ii}$_${ri}$(a, order, dim) result(nrm) !> Input matrix a[..] ${rt}$, intent(in), target :: a${ranksuffix(rank)}$ !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> Dimension the norm is computed along integer(ilp), intent(in) :: dim !> Norm of the matrix. (Same shape as `a`, with `dim` dropped). real(${rk}$) :: nrm${reduced_shape('a', rank, 'dim')}$ end function stdlib_linalg_norm_${rank}$D_to_${rank-1}$D_${ii}$_${ri}$ module function stdlib_linalg_norm_${rank}$D_to_${rank-1}$D_err_${ii}$_${ri}$(a, order, dim, err) result(nrm) !> Input matrix a[..] ${rt}$, intent(in), target :: a${ranksuffix(rank)}$ !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> Dimension the norm is computed along integer(ilp), intent(in) :: dim !> Output state return flag. type(linalg_state_type), intent(out) :: err !> Norm of the matrix. (Same shape as `a`, with `dim` dropped). real(${rk}$) :: nrm${reduced_shape('a', rank, 'dim')}$ end function stdlib_linalg_norm_${rank}$D_to_${rank-1}$D_err_${ii}$_${ri}$ #:endfor #:endfor #:endfor end interface norm !> Vector norm: subroutine interface interface get_norm !! version: experimental !! !! Computes the vector norm of a generic-rank array \( A \). !! ([Specification](../page/specs/stdlib_linalg.html#get-norm-computes-the-vector-norm-of-a-generic-rank-array)) !! !!### Summary !! Subroutine interface that returns one of several scalar norm metrics of a `real` or `complex` !! input array \( A \), that can have any rank. For generic rank-n arrays, the scalar norm over !! the whole array is returned by default. If `n>=2` and the optional input dimension `dim` is !! specified, a rank `n-1` array is returned with dimension `dim` collapsed, containing all 1D !! array norms evaluated along dimension `dim` only. !! !! !!### Description !! !! This `pure subroutine `interface provides methods for computing the vector norm(s) of an array. !! Supported data types include `real` and `complex`. !! Input arrays may have generic rank from 1 to ${MAXRANK}$. !! !! Norm type input is mandatory, and it is provided via the `order` argument. !! This can be provided as either an `integer` value or a `character` string. !! Allowed metrics are: !! - 1-norm \( \sum_i{ \left|a_i\right| } \): `order` = 1 or '1' !! - Euclidean norm \( \sqrt{\sum_i{ a_i^2 }} \): `order` = 2 or '2' !! - p-norm \( \left( \sum_i{ \left|a_i\right|^p }\right) ^{1/p} \): `integer` `order`, order>=3 !! - Infinity norm \( \max_i{ \left|a_i\right| } \): order = huge(0) or 'inf' !! - Minus-infinity norm \( \min_i{ \left|a_i\right| } \): order = -huge(0) or '-inf' !! !!### Example !! !!```fortran !! !! real(sp) :: a(3,3), na, rown(3) !! type(linalg_state_type) :: err !! a = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) !! !! ! L2 norm: whole matrix !! call get_norm(a, na, 2) !! !! ! Infinity norms of each row, with error control !! call get_norm(a, rown, 'inf', dim=2, err=err) !! !!``` !! #:for rk,rt,ri in RC_KINDS_TYPES #:for it,ii in NORM_INPUT_OPTIONS !> Scalar norms: ${rt}$ #:for rank in range(1, MAXRANK + 1) pure module subroutine norm_${rank}$D_${ii}$_${ri}$(a, nrm, order, err) !> Input ${rank}$-d matrix a${ranksuffix(rank)}$ ${rt}$, intent(in), target :: a${ranksuffix(rank)}$ !> Norm of the matrix. real(${rk}$), intent(out) :: nrm !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out), optional :: err end subroutine norm_${rank}$D_${ii}$_${ri}$ #:endfor !> Array norms: ${rt}$ #:for rank in range(2, MAXRANK + 1) pure module subroutine norm_${rank}$D_to_${rank-1}$D_${ii}$_${ri}$(a, nrm, order, dim, err) !> Input matrix a[..] ${rt}$, intent(in) :: a${ranksuffix(rank)}$ !> Dimension the norm is computed along integer(ilp), intent(in) :: dim !> Norm of the matrix. (Same shape as `a`, with `dim` dropped). real(${rk}$), intent(out) :: nrm${reduced_shape('a', rank, 'dim')}$ !> Order of the matrix norm being computed. ${it}$, intent(in) :: order !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out), optional :: err end subroutine norm_${rank}$D_to_${rank-1}$D_${ii}$_${ri}$ #:endfor #:endfor #:endfor end interface get_norm !> Matrix norms: function interface interface mnorm !! version: experimental !! !! Computes the matrix norm of a generic-rank array \( A \). !! ([Specification](../page/specs/stdlib_linalg.html#mnorm-computes-the-matrix-norm-of-a-generic-rank-array)) !! !!### Summary !! Return one of several matrix norm metrics of a `real` or `complex` input array \( A \), !! that can have rank 2 or higher. For rank-2 arrays, the matrix norm is returned. !! If rank>2 and the optional input dimensions `dim` are specified, !! a rank `n-2` array is returned with dimensions `dim(1),dim(2)` collapsed, containing all !! matrix norms evaluated over the specified dimensions only. `dim==[1,2]` are assumed as default !! dimensions if not specified. !! !!### Description !! !! This interface provides methods for computing the matrix norm(s) of an array. !! Supported data types include `real` and `complex`. !! Input arrays must have rank >= 2. !! !! Norm type input is optional, and it is provided via the `order` argument. !! This can be provided as either an `integer` value or a `character` string. !! Allowed metrics are: !! - 1-norm: `order` = 1 or '1' !! - 2-norm: `order` = 2 or '2' !! - Euclidean/Frobenius: `order` = 'Euclidean','Frobenius', or argument not specified !! - Infinity norm: `order` = huge(0) or 'Inf' !! !! If an invalid norm type is provided, the routine returns an error state. !! !!### Example !! !!```fortran !! real(sp) :: a(3,3), na !! real(sp) :: b(3,3,4), nb(4) ! Array of 4 3x3 matrices !! a = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) !! !! ! Euclidean/Frobenius norm of single matrix !! na = mnorm(a) !! na = mnorm(a, 'Euclidean') !! !! ! 1-norm of each 3x3 matrix in b !! nb = mnorm(b, 1, dim=[1,2]) !! !! ! Infinity-norm !! na = mnorm(b, 'inf', dim=[3,2]) !!``` !! #:for rk,rt,ri in RC_KINDS_TYPES #:for it,ii in NORM_INPUT_OPTIONS !> Matrix norms: ${rt}$ rank-2 arrays module function matrix_norm_${ii}$_${ri}$(a, order, err) result(nrm) !> Input matrix a(m,n) ${rt}$, intent(in), target :: a(:,:) !> Norm of the matrix. real(${rk}$) :: nrm !> Order of the matrix norm being computed. ${it}$, #{if 'integer' in it}#optional, #{endif}#intent(in) :: order !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out), optional :: err end function matrix_norm_${ii}$_${ri}$ !> Matrix norms: ${rt}$ higher rank arrays #:for rank in range(3, MAXRANK + 1) module function matrix_norm_${rank}$D_to_${rank-2}$D_${ii}$_${ri}$(a, order, dim, err) result(nrm) !> Input matrix a(m,n) ${rt}$, intent(in), contiguous, target :: a${ranksuffix(rank)}$ !> Norm of the matrix. real(${rk}$), allocatable :: nrm${ranksuffix(rank-2)}$ !> Order of the matrix norm being computed. ${it}$, #{if 'integer' in it}#optional, #{endif}#intent(in) :: order !> [optional] dimensions of the sub-matrices the norms should be evaluated at (default = [1,2]) integer(ilp), optional, intent(in) :: dim(2) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out), optional :: err end function matrix_norm_${rank}$D_to_${rank-2}$D_${ii}$_${ri}$ #:endfor #:endfor #:endfor end interface mnorm !> Matrix exponential: function interface interface expm !! version : experimental !! !! Computes the exponential of a matrix using a rational Pade approximation. !! ([Specification](../page/specs/stdlib_linalg.html#expm)) !! !! ### Description !! !! This interface provides methods for computing the exponential of a matrix !! represented as a standard Fortran rank-2 array. Supported data types include !! `real` and `complex`. !! !! By default, the order of the Pade approximation is set to 10. It can be changed !! via the `order` argument that must be non-negative. !! !! If the input matrix is non-square or the order of the Pade approximation is !! negative, the function returns an error state. !! !! ### Example !! !! ```fortran !! real(dp) :: A(3, 3), E(3, 3) !! !! A = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) !! !! ! Default Pade approximation of the matrix exponential. !! E = expm(A) !! !! ! Pade approximation with specified order. !! E = expm(A, order=12) !! ``` !! #:for rk,rt,ri in RC_KINDS_TYPES module function stdlib_linalg_${ri}$_expm_fun(A, order) result(E) !> Input matrix a(:, :). ${rt}$, intent(in) :: A(:, :) !> [optional] Order of the Pade approximation (default `order=10`) integer(ilp), optional, intent(in) :: order !> Exponential of the input matrix E = exp(A). ${rt}$, allocatable :: E(:, :) end function stdlib_linalg_${ri}$_expm_fun #:endfor end interface expm !> Matrix exponential: subroutine interface interface matrix_exp !! version : experimental !! !! Computes the exponential of a matrix using a rational Pade approximation. !! ([Specification](../page/specs/stdlib_linalg.html#matrix_exp)) !! !! ### Description !! !! This interface provides methods for computing the exponential of a matrix !! represented as a standard Fortran rank-2 array. Supported data types include !! `real` and `complex`. !! !! By default, the order of the Pade approximation is set to 10. It can be changed !! via the `order` argument that must be non-negative. !! !! If the input matrix is non-square or the order of the Pade approximation is !! negative, the function returns an error state. !! !! ### Example !! !! ```fortran !! real(dp) :: A(3, 3), E(3, 3) !! !! A = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) !! !! ! Default Pade approximation of the matrix exponential. !! call matrix_exp(A, E) ! Out-of-place !! ! call matrix_exp(A) for in-place computation. !! !! ! Pade approximation with specified order. !! call matrix_exp(A, E, order=12) !! ``` !! #:for rk,rt,ri in RC_KINDS_TYPES module subroutine stdlib_linalg_${ri}$_expm_inplace(A, order, err) !> Input matrix A(n, n) / Output matrix E = exp(A) ${rt}$, intent(inout) :: A(:, :) !> [optional] Order of the Pade approximation (default `order=10`) integer(ilp), optional, intent(in) :: order !> [optional] Error handling. type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_${ri}$_expm_inplace module subroutine stdlib_linalg_${ri}$_expm(A, E, order, err) !> Input matrix A(n, n) ${rt}$, intent(in) :: A(:, :) !> Output matrix exponential E = exp(A) ${rt}$, intent(out) :: E(:, :) !> [optional] Order of the Pade approximation (default `order=10`) integer(ilp), optional, intent(in) :: order !> [optional] Error handling. type(linalg_state_type), optional, intent(out) :: err end subroutine stdlib_linalg_${ri}$_expm #:endfor end interface matrix_exp contains !> Version: experimental !> !> Constructs the identity matrix. !> ([Specification](../page/specs/stdlib_linalg.html#eye-construct-the-identity-matrix)) #:for k1, t1 in RCI_KINDS_TYPES pure function eye_${t1[0]}$${k1}$(dim1, dim2, mold) result(result) integer, intent(in) :: dim1 integer, intent(in), optional :: dim2 ${t1}$, intent(in) #{if t1 == 'real(dp)'}#, optional #{endif}#:: mold ${t1}$, allocatable :: result(:, :) integer :: dim2_ integer :: i dim2_ = optval(dim2, dim1) allocate(result(dim1, dim2_)) result = 0 do i = 1, min(dim1, dim2_) result(i, i) = 1 end do end function eye_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RCI_KINDS_TYPES function trace_${t1[0]}$${k1}$(A) result(res) ${t1}$, intent(in) :: A(:,:) ${t1}$ :: res integer :: i res = 0 do i = 1, minval(shape(A)) res = res + A(i,i) end do end function trace_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RCI_KINDS_TYPES pure function is_square_${t1[0]}$${k1}$(A) result(res) ${t1}$, intent(in) :: A(:,:) logical :: res res = (size(A,1) == size(A,2)) end function is_square_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RCI_KINDS_TYPES pure function is_diagonal_${t1[0]}$${k1}$(A) result(res) ${t1}$, intent(in) :: A(:,:) logical :: res ${t1}$, parameter :: zero = 0 !zero of relevant type integer :: m, n, o, i, j m = size(A,1) n = size(A,2) do j = 1, n !loop over all columns o = min(j-1,m) !index of row above diagonal (or last row) do i = 1, o !loop over rows above diagonal if (A(i,j) /= zero) then res = .false. return end if end do do i = o+2, m !loop over rows below diagonal if (A(i,j) /= zero) then res = .false. return end if end do end do res = .true. !otherwise A is diagonal end function is_diagonal_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RCI_KINDS_TYPES pure function is_symmetric_${t1[0]}$${k1}$(A) result(res) ${t1}$, intent(in) :: A(:,:) logical :: res integer :: n, i, j if (.not. is_square(A)) then res = .false. return !nonsquare matrices cannot be symmetric end if n = size(A,1) !symmetric dimension of A do j = 1, n !loop over all columns do i = 1, j-1 !loop over all rows above diagonal if (A(i,j) /= A(j,i)) then res = .false. return end if end do end do res = .true. !otherwise A is symmetric end function is_symmetric_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RCI_KINDS_TYPES pure function is_skew_symmetric_${t1[0]}$${k1}$(A) result(res) ${t1}$, intent(in) :: A(:,:) logical :: res integer :: n, i, j if (.not. is_square(A)) then res = .false. return !nonsquare matrices cannot be skew-symmetric end if n = size(A,1) !symmetric dimension of A do j = 1, n !loop over all columns do i = 1, j !loop over all rows above diagonal (and diagonal) if (A(i,j) /= -A(j,i)) then res = .false. return end if end do end do res = .true. !otherwise A is skew-symmetric end function is_skew_symmetric_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in (REAL_KINDS_TYPES + INT_KINDS_TYPES) pure function is_hermitian_${t1[0]}$${k1}$(A) result(res) ${t1}$, intent(in) :: A(:,:) logical :: res res = is_symmetric(A) !symmetry and Hermiticity are equivalent for real matrices end function is_hermitian_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES pure function is_hermitian_${t1[0]}$${k1}$(A) result(res) ${t1}$, intent(in) :: A(:,:) logical :: res integer :: n, i, j if (.not. is_square(A)) then res = .false. return !nonsquare matrices cannot be Hermitian end if n = size(A,1) !symmetric dimension of A do j = 1, n !loop over all columns do i = 1, j !loop over all rows above diagonal (and diagonal) if (A(i,j) /= conjg(A(j,i))) then res = .false. return end if end do end do res = .true. !otherwise A is Hermitian end function is_hermitian_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RCI_KINDS_TYPES pure module function hermitian_${t1[0]}$${k1}$(a) result(ah) ${t1}$, intent(in) :: a(:,:) ${t1}$ :: ah(size(a, 2), size(a, 1)) #:if t1.startswith('complex') ah = conjg(transpose(a)) #:else ah = transpose(a) #:endif end function hermitian_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RCI_KINDS_TYPES function is_triangular_${t1[0]}$${k1}$(A,uplo) result(res) ${t1}$, intent(in) :: A(:,:) character, intent(in) :: uplo logical :: res ${t1}$, parameter :: zero = 0 !zero of relevant type integer :: m, n, o, i, j m = size(A,1) n = size(A,2) if ((uplo == 'u') .or. (uplo == 'U')) then !check for upper triangularity do j = 1, n !loop over all columns o = min(j-1,m) !index of row above diagonal (or last row) do i = o+2, m !loop over rows below diagonal if (A(i,j) /= zero) then res = .false. return end if end do end do else if ((uplo == 'l') .or. (uplo == 'L')) then !check for lower triangularity do j=1,n !loop over all columns o = min(j-1,m) !index of row above diagonal (or last row) do i=1,o !loop over rows above diagonal if (A(i,j) /= zero) then res = .false. return end if end do end do else call error_stop("ERROR (is_triangular): second argument must be one of {'u','U','l','L'}") end if res = .true. !otherwise A is triangular of the requested type end function is_triangular_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RCI_KINDS_TYPES function is_hessenberg_${t1[0]}$${k1}$(A,uplo) result(res) ${t1}$, intent(in) :: A(:,:) character, intent(in) :: uplo logical :: res ${t1}$, parameter :: zero = 0 !zero of relevant type integer :: m, n, o, i, j m = size(A,1) n = size(A,2) if ((uplo == 'u') .or. (uplo == 'U')) then !check for upper Hessenberg do j = 1, n !loop over all columns o = min(j-2,m) !index of row two above diagonal (or last row) do i = o+4, m !loop over rows two or more below main diagonal if (A(i,j) /= zero) then res = .false. return end if end do end do else if ((uplo == 'l') .or. (uplo == 'L')) then !check for lower Hessenberg do j = 1, n !loop over all columns o = min(j-2,m) !index of row two above diagonal (or last row) do i = 1, o !loop over rows one or more above main diagonal if (A(i,j) /= zero) then res = .false. return end if end do end do else call error_stop("ERROR (is_hessenberg): second argument must be one of {'u','U','l','L'}") end if res = .true. !otherwise A is Hessenberg of the requested type end function is_hessenberg_${t1[0]}$${k1}$ #:endfor end module stdlib_linalg fortran-lang-stdlib-0ede301/src/linalg/CMakeLists.txt0000664000175000017500000000166415135654166022772 0ustar alastairalastairset(linalg_fppFiles stdlib_linalg_cholesky.fypp stdlib_linalg_cross_product.fypp stdlib_linalg_determinant.fypp stdlib_linalg_diag.fypp stdlib_linalg_eigenvalues.fypp stdlib_linalg.fypp stdlib_linalg_inverse.fypp stdlib_linalg_kronecker.fypp stdlib_linalg_least_squares.fypp stdlib_linalg_matrix_functions.fypp stdlib_linalg_norms.fypp stdlib_linalg_outer_product.fypp stdlib_linalg_pinv.fypp stdlib_linalg_qr.fypp stdlib_linalg_schur.fypp stdlib_linalg_solve.fypp stdlib_linalg_svd.fypp ) set(linalg_cppFiles ) set(linalg_f90Files ) configure_stdlib_target(${PROJECT_NAME}_linalg linalg_f90Files linalg_fppFiles linalg_cppFiles) target_link_libraries(${PROJECT_NAME}_linalg PUBLIC ${PROJECT_NAME}_core ${PROJECT_NAME}_linalg_core ${PROJECT_NAME}_constants ${PROJECT_NAME}_lapack ${PROJECT_NAME}_lapack_extended ${PROJECT_NAME}_sorting ${PROJECT_NAME}_intrinsics) fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_kronecker.fypp0000664000175000017500000000173715135654166026005 0ustar alastairalastair#:include "common.fypp" #:set RCI_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES + INT_KINDS_TYPES submodule (stdlib_linalg) stdlib_linalg_kronecker implicit none contains #:for k1, t1 in RCI_KINDS_TYPES pure module function kronecker_product_${t1[0]}$${k1}$(A, B) result(C) ${t1}$, intent(in) :: A(:,:), B(:,:) ${t1}$ :: C(size(A,dim=1)*size(B,dim=1),size(A,dim=2)*size(B,dim=2)) integer :: m1, n1, maxM1, maxN1, maxM2, maxN2 maxM1 = size(A, dim=1) maxN1 = size(A, dim=2) maxM2 = size(B, dim=1) maxN2 = size(B, dim=2) do n1 = 1, maxN1 do m1 = 1, maxM1 ! We use the Wikipedia convention for ordering of the matrix elements ! https://en.wikipedia.org/wiki/Kronecker_product C((m1-1)*maxM2+1:m1*maxM2, (n1-1)*maxN2+1:n1*maxN2) = A(m1, n1) * B(:,:) end do end do end function kronecker_product_${t1[0]}$${k1}$ #:endfor end submodule stdlib_linalg_kronecker fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_eigenvalues.fypp0000664000175000017500000006252015135654166026326 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES #:set EIG_PROBLEM = ["standard", "generalized"] #:set EIG_FUNCTION = ["geev","ggev"] #:set EIG_PROBLEM_LIST = list(zip(EIG_PROBLEM, EIG_FUNCTION)) submodule (stdlib_linalg) stdlib_linalg_eigenvalues !! Compute eigenvalues and eigenvectors use stdlib_linalg_constants use stdlib_linalg_lapack, only: geev, ggev, heev, syev use stdlib_linalg_lapack_aux, only: handle_geev_info, handle_ggev_info, handle_heev_info use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR, LINALG_SUCCESS use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_positive_inf, ieee_quiet_nan implicit none character(*), parameter :: this = 'eigenvalues' !> Utility function: Scale generalized eigenvalue interface scale_general_eig #:for rk,rt,ri in RC_KINDS_TYPES module procedure scale_general_eig_${ri}$ #:endfor end interface scale_general_eig contains !> Request for eigenvector calculation elemental character function eigenvectors_task(required) logical(lk), intent(in) :: required eigenvectors_task = merge('V','N',required) end function eigenvectors_task !> Request for symmetry side (default: lower) elemental character function symmetric_triangle_task(upper) logical(lk), optional, intent(in) :: upper symmetric_triangle_task = 'L' if (present(upper)) symmetric_triangle_task = merge('U','L',upper) end function symmetric_triangle_task #:for rk,rt,ri in RC_KINDS_TYPES #:for ep,ei in EIG_PROBLEM_LIST module function stdlib_linalg_eigvals_${ep}$_${ri}$(a#{if ei=='ggev'}#,b#{endif}#,err) result(lambda) !! Return an array of eigenvalues of matrix A. !> Input matrix A[m,n] ${rt}$, intent(in), target :: a(:,:) #:if ei=='ggev' !> Generalized problem matrix B[n,n] ${rt}$, intent(inout), target :: b(:,:) #:endif !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out) :: err !> Array of eigenvalues complex(${rk}$), allocatable :: lambda(:) !> Create ${rt}$, pointer :: amat(:,:)#{if ei=='ggev'}#, bmat(:,:) #{endif}# integer(ilp) :: m,n,k !> Create an internal pointer so the intent of A won't affect the next call amat => a #{if ei=='ggev'}#bmat => b#{endif}# m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) !> Allocate return storage allocate(lambda(k)) !> Compute eigenvalues only call stdlib_linalg_eig_${ep}$_${ri}$(amat#{if ei=='ggev'}#,bmat#{endif}#,lambda,err=err) end function stdlib_linalg_eigvals_${ep}$_${ri}$ module function stdlib_linalg_eigvals_noerr_${ep}$_${ri}$(a#{if ei=='ggev'}#,b#{endif}#) result(lambda) !! Return an array of eigenvalues of matrix A. !> Input matrix A[m,n] ${rt}$, intent(in), target :: a(:,:) #:if ei=='ggev' !> Generalized problem matrix B[n,n] ${rt}$, intent(inout), target :: b(:,:) #:endif !> Array of eigenvalues complex(${rk}$), allocatable :: lambda(:) !> Create ${rt}$, pointer :: amat(:,:)#{if ei=='ggev'}#, bmat(:,:) #{endif}# integer(ilp) :: m,n,k !> Create an internal pointer so the intent of A won't affect the next call amat => a #{if ei=='ggev'}#bmat => b#{endif}# m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) !> Allocate return storage allocate(lambda(k)) !> Compute eigenvalues only call stdlib_linalg_eig_${ep}$_${ri}$(amat#{if ei=='ggev'}#,bmat#{endif}#,lambda,overwrite_a=.false.) end function stdlib_linalg_eigvals_noerr_${ep}$_${ri}$ module subroutine stdlib_linalg_eig_${ep}$_${ri}$(a#{if ei=='ggev'}#,b#{endif}#,lambda,right,left,& overwrite_a#{if ei=='ggev'}#,overwrite_b#{endif}#,err) !! Eigendecomposition of matrix A returning an array `lambda` of eigenvalues, !! and optionally right or left eigenvectors. !> Input matrix A[m,n] ${rt}$, intent(inout), target :: a(:,:) #:if ei=='ggev' !> Generalized problem matrix B[n,n] ${rt}$, intent(inout), target :: b(:,:) #:endif !> Array of eigenvalues complex(${rk}$), intent(out) :: lambda(:) !> [optional] RIGHT eigenvectors of A (as columns) complex(${rk}$), optional, intent(out), target :: right(:,:) !> [optional] LEFT eigenvectors of A (as columns) complex(${rk}$), optional, intent(out), target :: left(:,:) !> [optional] Can A data be overwritten and destroyed? (default: no) logical(lk), optional, intent(in) :: overwrite_a #:if ei=='ggev' !> [optional] Can B data be overwritten and destroyed? (default: no) logical(lk), optional, intent(in) :: overwrite_b #:endif !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Local variables type(linalg_state_type) :: err0 integer(ilp) :: m,n,lda,ldu,ldv,info,k,lwork,neig#{if ei=='ggev'}#,ldb,nb#{endif}# logical(lk) :: copy_a#{if ei=='ggev'}#,copy_b#{endif}# character :: task_u,task_v ${rt}$, target :: work_dummy(1),u_dummy(1,1),v_dummy(1,1) ${rt}$, allocatable :: work(:) ${rt}$, pointer :: amat(:,:),umat(:,:),vmat(:,:)#{if ei=='ggev'}#,bmat(:,:)#{endif}# #:if rt.startswith('complex') real(${rk}$), allocatable :: rwork(:) #:else ${rt}$, pointer :: lreal(:),limag(:) #:endif #:if ei=='ggev' ${rt}$, allocatable :: beta(:) #:endif !> Matrix size m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) neig = size(lambda,kind=ilp) lda = m if (k<=0 .or. m/=n) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR,& 'invalid or matrix size a=',[m,n],', must be nonempty square.') call linalg_error_handling(err0,err) return elseif (neig b endif allocate(beta(n)) #:endif ! Decide if U, V eigenvectors task_u = eigenvectors_task(present(left)) task_v = eigenvectors_task(present(right)) if (present(right)) then #:if rt.startswith('complex') ! For a complex matrix, GEEV returns complex arrays. ! Point directly to output. vmat => right #:else ! For a real matrix, GEEV returns real arrays. ! Allocate temporary reals, will be converted to complex vectors at the end. allocate(vmat(n,n)) #:endif if (size(vmat,2,kind=ilp) left #:else ! For a real matrix, GEEV returns real arrays. ! Allocate temporary reals, will be converted to complex vectors at the end. allocate(umat(n,n)) #:endif if (size(umat,2,kind=ilp) Prepare working storage lwork = nint(real(work_dummy(1),kind=${rk}$), kind=ilp) allocate(work(lwork)) !> Compute eigensystem call ${ei}$(task_u,task_v,n,amat,lda,& #:if ep=='generalized' bmat,ldb, & #:endif #{if rt.startswith('complex')}#lambda,#{else}#lreal,limag,#{endif}# & #:if ep=='generalized' beta, & #:endif umat,ldu,vmat,ldv,& work,lwork,#{if rt.startswith('complex')}#rwork,#{endif}#info) call handle_${ei}$_info(this,err0,info,shape(amat)#{if ei=='ggev'}#,shape(bmat)#{endif}#) endif ! Finalize storage and process output flag #:if not rt.startswith('complex') lambda(:n) = cmplx(lreal(:n),limag(:n),kind=${rk}$) #:endif #:if ep=='generalized' ! Scale generalized eigenvalues lambda(:n) = scale_general_eig(lambda(:n),beta) #:endif #:if not rt.startswith('complex') ! If the j-th and (j+1)-st eigenvalues form a complex conjugate pair, ! ${ei}$ returns reals as: ! u(j) = VL(:,j) + i*VL(:,j+1) and ! u(j+1) = VL(:,j) - i*VL(:,j+1). ! Convert these to complex numbers here. if (present(right)) call assign_real_eigenvectors_${rk}$(n,lambda,vmat,right) if (present(left)) call assign_real_eigenvectors_${rk}$(n,lambda,umat,left) #:endif endif get_${ei}$ if (copy_a) deallocate(amat) #:if ep=='generalized' if (copy_b) deallocate(bmat) #:endif #:if not rt.startswith('complex') if (present(right)) deallocate(vmat) if (present(left)) deallocate(umat) #:endif call linalg_error_handling(err0,err) end subroutine stdlib_linalg_eig_${ep}$_${ri}$ #:endfor module function stdlib_linalg_eigvalsh_${ri}$(a,upper_a,err) result(lambda) !! Return an array of eigenvalues of real symmetric / complex hermitian A !> Input matrix A[m,n] ${rt}$, intent(in), target :: a(:,:) !> [optional] Should the upper/lower half of A be used? Default: lower logical(lk), optional, intent(in) :: upper_a !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out) :: err !> Array of eigenvalues real(${rk}$), allocatable :: lambda(:) ${rt}$, pointer :: amat(:,:) integer(ilp) :: m,n,k !> Create an internal pointer so the intent of A won't affect the next call amat => a m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) !> Allocate return storage allocate(lambda(k)) !> Compute eigenvalues only call stdlib_linalg_eigh_${ri}$(amat,lambda,upper_a=upper_a,err=err) end function stdlib_linalg_eigvalsh_${ri}$ module function stdlib_linalg_eigvalsh_noerr_${ri}$(a,upper_a) result(lambda) !! Return an array of eigenvalues of real symmetric / complex hermitian A !> Input matrix A[m,n] ${rt}$, intent(in), target :: a(:,:) !> [optional] Should the upper/lower half of A be used? Default: use lower logical(lk), optional, intent(in) :: upper_a !> Array of eigenvalues real(${rk}$), allocatable :: lambda(:) ${rt}$, pointer :: amat(:,:) integer(ilp) :: m,n,k !> Create an internal pointer so the intent of A won't affect the next call amat => a m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) !> Allocate return storage allocate(lambda(k)) !> Compute eigenvalues only call stdlib_linalg_eigh_${ri}$(amat,lambda,upper_a=upper_a,overwrite_a=.false.) end function stdlib_linalg_eigvalsh_noerr_${ri}$ module subroutine stdlib_linalg_eigh_${ri}$(a,lambda,vectors,upper_a,overwrite_a,err) !! Eigendecomposition of a real symmetric or complex Hermitian matrix A returning an array `lambda` !! of eigenvalues, and optionally right or left eigenvectors. !> Input matrix A[m,n] ${rt}$, intent(inout), target :: a(:,:) !> Array of eigenvalues real(${rk}$), intent(out) :: lambda(:) !> The columns of vectors contain the orthonormal eigenvectors of A ${rt}$, optional, intent(out), target :: vectors(:,:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] Should the upper/lower half of A be used? Default: use lower logical(lk), optional, intent(in) :: upper_a !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Local variables type(linalg_state_type) :: err0 integer(ilp) :: m,n,lda,info,k,lwork,neig logical(lk) :: copy_a character :: triangle,task ${rt}$, target :: work_dummy(1) ${rt}$, allocatable :: work(:) #:if rt.startswith('complex') real(${rk}$), allocatable :: rwork(:) #:endif ${rt}$, pointer :: amat(:,:) !> Matrix size m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) neig = size(lambda,kind=ilp) if (k<=0 .or. m/=n) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid or matrix size a=',[m,n], & ', must be non-empty square.') call linalg_error_handling(err0,err) return elseif (neig= n=',n) call linalg_error_handling(err0,err) return endif ! Check if input A can be overwritten copy_a = .true._lk if (present(vectors)) then ! No need to copy A anyways copy_a = .false. elseif (present(overwrite_a)) then copy_a = .not.overwrite_a endif ! Should we use the upper or lower half of the matrix? triangle = symmetric_triangle_task(upper_a) ! Request for eigenvectors task = eigenvectors_task(present(vectors)) if (present(vectors)) then ! Check size if (any(shape(vectors,kind=ilp) Prepare working storage lwork = nint(real(work_dummy(1),kind=${rk}$), kind=ilp) allocate(work(lwork)) !> Compute eigensystem #:if rt.startswith('complex') call heev(task,triangle,n,amat,lda,lambda,work,lwork,rwork,info) #:else call syev(task,triangle,n,amat,lda,lambda,work,lwork,info) #:endif call handle_heev_info(this,err0,info,m,n) endif ! Finalize storage and process output flag if (copy_a) deallocate(amat) call linalg_error_handling(err0,err) end subroutine stdlib_linalg_eigh_${ri}$ #:endfor #:for rk,rt,ri in REAL_KINDS_TYPES pure subroutine assign_real_eigenvectors_${rk}$(n,lambda,lmat,out_mat) !! GEEV for real matrices returns complex eigenvalues in real arrays, where two consecutive !! reals at [j,j+1] locations represent the real and imaginary parts of two complex conjugate !! eigenvalues. Convert them to complex here, following the GEEV logic. !> Problem size integer(ilp), intent(in) :: n !> Array of eigenvalues complex(${rk}$), intent(in) :: lambda(:) !> Real matrix as returned by geev ${rt}$, intent(in) :: lmat(:,:) !> Complex matrix as returned by eig complex(${rk}$), intent(out) :: out_mat(:,:) integer(ilp) :: i,j ! Copy matrix do concurrent(i=1:n,j=1:n) out_mat(i,j) = lmat(i,j) end do ! If the j-th and (j+1)-st eigenvalues form a complex conjugate pair, ! geev returns them as reals as: ! u(j) = VL(:,j) + i*VL(:,j+1) and ! u(j+1) = VL(:,j) - i*VL(:,j+1). ! Convert these to complex numbers here. do j=1,n-1 if (lambda(j)==conjg(lambda(j+1))) then out_mat(:, j) = cmplx(lmat(:,j), lmat(:,j+1),kind=${rk}$) out_mat(:,j+1) = cmplx(lmat(:,j),-lmat(:,j+1),kind=${rk}$) endif end do end subroutine assign_real_eigenvectors_${rk}$ #:for ep,ei in EIG_PROBLEM_LIST module subroutine stdlib_linalg_real_eig_${ep}$_${ri}$(a#{if ei=='ggev'}#,b#{endif}#,lambda,right,left, & overwrite_a#{if ei=='ggev'}#,overwrite_b#{endif}#,err) !! Eigendecomposition of matrix A returning an array `lambda` of real eigenvalues, !! and optionally right or left eigenvectors. Returns an error if the eigenvalues had !! non-trivial imaginary parts. !> Input matrix A[m,n] ${rt}$, intent(inout), target :: a(:,:) #:if ei=='ggev' !> Generalized problem matrix B[n,n] ${rt}$, intent(inout), target :: b(:,:) #:endif !> Array of real eigenvalues real(${rk}$), intent(out) :: lambda(:) !> The columns of RIGHT contain the right eigenvectors of A complex(${rk}$), optional, intent(out), target :: right(:,:) !> The columns of LEFT contain the left eigenvectors of A complex(${rk}$), optional, intent(out), target :: left(:,:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a #:if ei=='ggev' !> [optional] Can B data be overwritten and destroyed? (default: no) logical(lk), optional, intent(in) :: overwrite_b #:endif !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err type(linalg_state_type) :: err0 integer(ilp) :: n complex(${rk}$), allocatable :: clambda(:) real(${rk}$), parameter :: rtol = epsilon(0.0_${rk}$) real(${rk}$), parameter :: atol = tiny(0.0_${rk}$) n = size(lambda,dim=1,kind=ilp) allocate(clambda(n)) call stdlib_linalg_eig_${ep}$_${ri}$(a#{if ei=='ggev'}#,b#{endif}#,clambda,right,left, & overwrite_a#{if ei=='ggev'}#,overwrite_b#{endif}#,err0) ! Check that no eigenvalues have meaningful imaginary part if (err0%ok() .and. any(aimag(clambda)>atol+rtol*abs(abs(clambda)))) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR, & 'complex eigenvalues detected: max(imag(lambda))=',maxval(aimag(clambda))) endif ! Return real components only lambda(:n) = real(clambda,kind=${rk}$) call linalg_error_handling(err0,err) end subroutine stdlib_linalg_real_eig_${ep}$_${ri}$ #:endfor #:endfor #:for rk,rt,ri in RC_KINDS_TYPES !> Utility function: Scale generalized eigenvalue elemental complex(${rk}$) function scale_general_eig_${ri}$(alpha,beta) result(lambda) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar lambda or a ratio !! alpha/beta = lambda, such that A - lambda*B is singular. It is usually represented as the !! pair (alpha,beta), there is a reasonable interpretation for beta=0, and even for both !! being zero. complex(${rk}$), intent(in) :: alpha ${rt}$, intent(in) :: beta real (${rk}$), parameter :: rzero = 0.0_${rk}$ complex(${rk}$), parameter :: czero = (0.0_${rk}$,0.0_${rk}$) if (beta==#{if rt.startswith('real')}#r#{else}#c#{endif}#zero) then if (alpha/=czero) then lambda = cmplx(ieee_value(1.0_${rk}$, ieee_positive_inf), & ieee_value(1.0_${rk}$, ieee_positive_inf), kind=${rk}$) else lambda = ieee_value(1.0_${rk}$, ieee_quiet_nan) end if else lambda = alpha/beta end if end function scale_general_eig_${ri}$ #:endfor end submodule stdlib_linalg_eigenvalues fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_cross_product.fypp0000664000175000017500000000107015135654166026701 0ustar alastairalastair#:include "common.fypp" #:set RCI_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES + INT_KINDS_TYPES submodule (stdlib_linalg) stdlib_linalg_cross_product implicit none contains #:for k1, t1 in RCI_KINDS_TYPES pure module function cross_product_${t1[0]}$${k1}$(a, b) result(res) ${t1}$, intent(in) :: a(3), b(3) ${t1}$ :: res(3) res(1) = a(2) * b(3) - a(3) * b(2) res(2) = a(3) * b(1) - a(1) * b(3) res(3) = a(1) * b(2) - a(2) * b(1) end function cross_product_${t1[0]}$${k1}$ #:endfor end submodule fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_cholesky.fypp0000664000175000017500000001344315135654166025640 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES ! Cholesky factorization of a matrix, based on LAPACK *POTRF functions submodule (stdlib_linalg) stdlib_linalg_cholesky use stdlib_linalg_constants use stdlib_linalg_lapack, only: potrf use stdlib_linalg_lapack_aux, only: handle_potrf_info use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR implicit none character(*), parameter :: this = 'cholesky' contains #:for rk,rt,ri in RC_KINDS_TYPES ! Compute the Cholesky factorization of a symmetric / Hermitian matrix, A = L*L^T = U^T*U. ! The factorization is returned in-place, overwriting matrix A pure module subroutine stdlib_linalg_${ri}$_cholesky_inplace(a,lower,other_zeroed,err) !> Input matrix a[m,n] ${rt}$, intent(inout), target :: a(:,:) !> [optional] is the lower or upper triangular factor required? Default = lower logical(lk), optional, intent(in) :: lower !> [optional] should the unused half of the return matrix be zeroed out? Default: yes logical(lk), optional, intent(in) :: other_zeroed !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Local variables type(linalg_state_type) :: err0 integer(ilp) :: lda,n,info,j logical(lk) :: lower_,other_zeroed_ character :: triangle ${rt}$, parameter :: zero = 0.0_${rk}$ !> Check if the lower or upper factor is required. !> Default: use lower factor lower_ = .true. if (present(lower)) lower_ = lower triangle = merge('L','U',lower_) !> Check if the unused half of the return matrix should be zeroed out (default). !> Otherwise it is unused and will contain garbage. other_zeroed_ = .true. if (present(other_zeroed)) other_zeroed_ = other_zeroed !> Problem size lda = size(a,1,kind=ilp) n = size(a,2,kind=ilp) ! Check sizes if (n<1 .or. lda<1 .or. lda Input matrix a[n,n]. On return, A is destroyed and replaced by the inverse ${rt}$, intent(inout) :: a(:,:) !> [optional] Storage array for the diagonal pivot indices integer(ilp), optional, intent(inout), target :: pivot(:) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Local variables type(linalg_state_type) :: err0 integer(ilp) :: lda,n,info,nb,lwork,npiv integer(ilp), pointer :: ipiv(:) ${rt}$, allocatable :: work(:) !> Problem sizes lda = size(a,1,kind=ilp) n = size(a,2,kind=ilp) ! Has a pre-allocated pivots storage array been provided? if (present(pivot)) then ipiv => pivot else allocate(ipiv(n)) endif npiv = size(ipiv,kind=ilp) if (lda<1 .or. n<1 .or. lda/=n .or. npiv Input matrix a[n,n]. ${rt}$, intent(in) :: a(:,:) !> Inverse matrix a[n,n]. ${rt}$, intent(out) :: inva(:,:) !> [optional] Storage array for the diagonal pivot indices integer(ilp), optional, intent(inout), target :: pivot(:) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err type(linalg_state_type) :: err0 integer(ilp) :: sa(2),sinva(2) sa = shape(a,kind=ilp) sinva = shape(inva,kind=ilp) if (any(sa/=sinva)) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size: a=',sa,' inva=',sinva) else !> Copy data in inva = a !> Compute matrix inverse call stdlib_linalg_invert_inplace_${ri}$(inva,pivot=pivot,err=err0) end if ! Process output and return call linalg_error_handling(err0,err) end subroutine stdlib_linalg_invert_split_${ri}$ ! Invert matrix in place module function stdlib_linalg_inverse_${ri}$(a,err) result(inva) !> Input matrix a[n,n] ${rt}$, intent(in) :: a(:,:) !> Output matrix inverse ${rt}$, allocatable :: inva(:,:) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Allocate with copy allocate(inva,source=a) !> Compute matrix inverse call stdlib_linalg_invert_inplace_${ri}$(inva,err=err) end function stdlib_linalg_inverse_${ri}$ ! Inverse matrix operator module function stdlib_linalg_inverse_${ri}$_operator(a) result(inva) !> Input matrix a[n,n] ${rt}$, intent(in) :: a(:,:) !> Result matrix ${rt}$, allocatable :: inva(:,:) type(linalg_state_type) :: err ! Provide an error handler to return NaNs on issues inva = stdlib_linalg_inverse_${ri}$(a,err=err) ! Return NaN on issues if (err%error()) then if (allocated(inva)) deallocate(inva) allocate(inva(size(a,1,kind=ilp),size(a,2,kind=ilp))) #:if rt.startswith('real') inva = ieee_value(1.0_${rk}$,ieee_quiet_nan) #:else inva = cmplx(ieee_value(1.0_${rk}$,ieee_quiet_nan), & ieee_value(1.0_${rk}$,ieee_quiet_nan), kind=${rk}$) #:endif endif end function stdlib_linalg_inverse_${ri}$_operator #:endfor end submodule stdlib_linalg_inverse fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_solve.fypp0000664000175000017500000001306515135654166025147 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES #:set RHS_SUFFIX = ["one","many"] #:set RHS_SYMBOL = [ranksuffix(r) for r in [1,2]] #:set RHS_EMPTY = [emptyranksuffix(r) for r in [1,2]] #:set ALL_RHS = list(zip(RHS_SYMBOL,RHS_SUFFIX,RHS_EMPTY)) submodule (stdlib_linalg) stdlib_linalg_solve !! Solve linear system Ax=b use stdlib_linalg_constants use stdlib_linalg_lapack, only: gesv use stdlib_linalg_lapack_aux, only: handle_gesv_info use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR implicit none character(*), parameter :: this = 'solve' contains #:for nd,ndsuf,nde in ALL_RHS #:for rk,rt,ri in RC_KINDS_TYPES ! Compute the solution to a real system of linear equations A * X = B module function stdlib_linalg_${ri}$_solve_${ndsuf}$(a,b,overwrite_a,err) result(x) !> Input matrix a[n,n] ${rt}$, intent(inout), target :: a(:,:) !> Right hand side vector or array, b[n] or b[n,nrhs] ${rt}$, intent(in) :: b${nd}$ !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), intent(out) :: err !> Result array/matrix x[n] or x[n,nrhs] ${rt}$, allocatable, target :: x${nd}$ ! Initialize solution shape from the rhs array allocate(x,mold=b) call stdlib_linalg_${ri}$_solve_lu_${ndsuf}$(a,b,x,overwrite_a=overwrite_a,err=err) end function stdlib_linalg_${ri}$_solve_${ndsuf}$ !> Compute the solution to a real system of linear equations A * X = B (pure interface) pure module function stdlib_linalg_${ri}$_pure_solve_${ndsuf}$(a,b) result(x) !> Input matrix a[n,n] ${rt}$, intent(in) :: a(:,:) !> Right hand side vector or array, b[n] or b[n,nrhs] ${rt}$, intent(in) :: b${nd}$ !> Result array/matrix x[n] or x[n,nrhs] ${rt}$, allocatable, target :: x${nd}$ ! Local variables ${rt}$, allocatable :: amat(:,:) ! Copy `a` so it can be intent(in) allocate(amat,source=a) ! Initialize solution shape from the rhs array allocate(x,mold=b) call stdlib_linalg_${ri}$_solve_lu_${ndsuf}$(amat,b,x,overwrite_a=.true.) end function stdlib_linalg_${ri}$_pure_solve_${ndsuf}$ !> Compute the solution to a real system of linear equations A * X = B (pure interface) pure module subroutine stdlib_linalg_${ri}$_solve_lu_${ndsuf}$(a,b,x,pivot,overwrite_a,err) !> Input matrix a[n,n] ${rt}$, intent(inout), target :: a(:,:) !> Right hand side vector or array, b[n] or b[n,nrhs] ${rt}$, intent(in) :: b${nd}$ !> Result array/matrix x[n] or x[n,nrhs] ${rt}$, intent(inout), contiguous, target :: x${nd}$ !> [optional] Storage array for the diagonal pivot indices integer(ilp), optional, intent(inout), target :: pivot(:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err ! Local variables type(linalg_state_type) :: err0 integer(ilp) :: lda,n,ldb,ldx,nrhsx,nrhs,info,npiv integer(ilp), pointer :: ipiv(:) logical(lk) :: copy_a ${rt}$, pointer :: xmat(:,:),amat(:,:) ! Problem sizes lda = size(a,1,kind=ilp) n = size(a,2,kind=ilp) ldb = size(b,1,kind=ilp) nrhs = size(b ,kind=ilp)/ldb ldx = size(x,1,kind=ilp) nrhsx = size(x ,kind=ilp)/ldx ! Has a pre-allocated pivots storage array been provided? if (present(pivot)) then ipiv => pivot else allocate(ipiv(n)) endif npiv = size(ipiv,kind=ilp) ! Can A be overwritten? By default, do not overwrite if (present(overwrite_a)) then copy_a = .not.overwrite_a else copy_a = .true._lk endif if (any([lda,n,ldb]<1) .or. any([lda,ldb,ldx]/=n) .or. nrhsx/=nrhs .or. npiv/=n) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid sizes: a=',[lda,n], & 'b=',[ldb,nrhs],' x=',[ldx,nrhsx], & 'pivot=',n) call linalg_error_handling(err0,err) return end if ! Initialize a matrix temporary if (copy_a) then allocate(amat(lda,n),source=a) else amat => a endif ! Initialize solution with the rhs x = b xmat(1:n,1:nrhs) => x ! Solve system call gesv(n,nrhs,amat,lda,ipiv,xmat,ldb,info) ! Process output call handle_gesv_info(this,info,lda,n,nrhs,err0) if (copy_a) deallocate(amat) if (.not.present(pivot)) deallocate(ipiv) ! Process output and return call linalg_error_handling(err0,err) end subroutine stdlib_linalg_${ri}$_solve_lu_${ndsuf}$ #:endfor #:endfor end submodule stdlib_linalg_solve fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_svd.fypp0000664000175000017500000002437115135654166024615 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule(stdlib_linalg) stdlib_linalg_svd !! Singular-Value Decomposition use stdlib_linalg_constants use stdlib_linalg_lapack, only: gesdd use stdlib_linalg_lapack_aux, only: handle_gesdd_info use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR, LINALG_SUCCESS implicit none character(*), parameter :: this = 'svd' !> List of internal GESDD tasks: !> Return full matrices U, V^T to separate storage character, parameter :: GESDD_FULL_MATRICES = 'A' !> Return shrunk matrices U, V^T to k = min(m,n) character, parameter :: GESDD_SHRINK_MATRICES = 'S' !> Overwrite A storage with U (if M>=N) or VT (if M Do not return either U or VT (singular values array only) character, parameter :: GESDD_SINGVAL_ONLY = 'N' contains #:for rk,rt,ri in RC_KINDS_TYPES !> Singular values of matrix A module function stdlib_linalg_svdvals_${ri}$(a,err) result(s) !!### Summary !! Compute singular values \(S \) from the singular-value decomposition of a matrix \( A = U \cdot S \cdot \V^T \). !! !!### Description !! !! This function returns the array of singular values from the singular value decomposition of a `real` !! or `complex` matrix \( A = U \cdot S \cdot V^T \). !! !! param: a Input matrix of size [m,n]. !! param: err [optional] State return flag. !! !!### Return value !! !! param: s `real` array of size [min(m,n)] returning a list of singular values. !! !> Input matrix A[m,n] ${rt}$, intent(in), target :: a(:,:) !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Array of singular values real(${rk}$), allocatable :: s(:) !> Create ${rt}$, pointer :: amat(:,:) integer(ilp) :: m,n,k !> Create an internal pointer so the intent of A won't affect the next call amat => a m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) !> Allocate return storage allocate(s(k)) !> Compute singular values call stdlib_linalg_svd_${ri}$(amat,s,overwrite_a=.false.,err=err) end function stdlib_linalg_svdvals_${ri}$ !> SVD of matrix A = U S V^T, returning S and optionally U and V^T module subroutine stdlib_linalg_svd_${ri}$(a,s,u,vt,overwrite_a,full_matrices,err) !!### Summary !! Compute singular value decomposition of a matrix \( A = U \cdot S \cdot \V^T \) !! !!### Description !! !! This function computes the singular value decomposition of a `real` or `complex` matrix \( A \), !! and returns the array of singular values, and optionally the left matrix \( U \) containing the !! left unitary singular vectors, and the right matrix \( V^T \), containing the right unitary !! singular vectors. !! !! param: a Input matrix of size [m,n]. !! param: s Output `real` array of size [min(m,n)] returning a list of singular values. !! param: u [optional] Output left singular matrix of size [m,m] or [m,min(m,n)] (.not.full_matrices). Contains singular vectors as columns. !! param: vt [optional] Output right singular matrix of size [n,n] or [min(m,n),n] (.not.full_matrices). Contains singular vectors as rows. !! param: overwrite_a [optional] Flag indicating if the input matrix can be overwritten. !! param: full_matrices [optional] If `.true.` (default), matrices \( U \) and \( V^T \) have size [m,m], [n,n]. Otherwise, they are [m,k], [k,n] with `k=min(m,n)`. !! param: err [optional] State return flag. !! !> Input matrix A[m,n] ${rt}$, intent(inout), target :: a(:,:) !> Array of singular values real(${rk}$), intent(out) :: s(:) !> The columns of U contain the left singular vectors ${rt}$, optional, intent(out), target :: u(:,:) !> The rows of V^T contain the right singular vectors ${rt}$, optional, intent(out), target :: vt(:,:) !> [optional] Can A data be overwritten and destroyed? logical(lk), optional, intent(in) :: overwrite_a !> [optional] full matrices have shape(u)==[m,m], shape(vh)==[n,n] (default); otherwise !> they are shape(u)==[m,k] and shape(vh)==[k,n] with k=min(m,n) logical(lk), optional, intent(in) :: full_matrices !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Local variables type(linalg_state_type) :: err0 integer(ilp) :: m,n,lda,ldu,ldvt,info,k,lwork,liwork,lrwork integer(ilp), allocatable :: iwork(:) logical(lk) :: overwrite_a_,full_storage,compute_uv,temp_u,temp_vt,can_overwrite_amat character :: task ${rt}$, target :: work_dummy(1),u_dummy(1,1),vt_dummy(1,1) ${rt}$, allocatable :: work(:) #:if rt.startswith('complex') real(${rk}$), allocatable :: rwork(:) #:endif ${rt}$, pointer :: amat(:,:),umat(:,:),vtmat(:,:) !> Matrix determinant size m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) lda = m if (.not.k>0) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid or matrix size: a=',[m,n]) call linalg_error_handling(err0,err) return elseif (.not.size(s,kind=ilp)>=k) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'singular value array has insufficient size:',& ' s=',shape(s,kind=ilp),', k=',k) call linalg_error_handling(err0,err) return endif ! Integer storage liwork = 8*k allocate(iwork(liwork)) ! Can A be overwritten? By default, do not overwrite overwrite_a_ = .false. if (present(overwrite_a)) overwrite_a_ = overwrite_a ! Initialize a matrix temporary? if (overwrite_a_) then amat => a else allocate(amat(m,n),source=a) endif ! Check if we can overwrite amat with data that will be lost can_overwrite_amat = (.not.overwrite_a_) .and. merge(.not.present(u),.not.present(vt),m>=n) ! Full-size matrices if (present(full_matrices)) then full_storage = full_matrices else full_storage = .true. endif ! Decide if U, VT matrices should be computed compute_uv = present(u) .or. present(vt) ! U, VT storage if (present(u)) then ! User input umat => u temp_u = .false. elseif ((m>=n .and. .not.overwrite_a_) .or. .not.compute_uv) then ! U not wanted, and A can be overwritten: do not allocate umat => u_dummy temp_u = .false. elseif (.not.full_storage) then ! Allocate with minimum size allocate(umat(m,k)) temp_u = .true. else ! Allocate with regular size allocate(umat(m,m)) temp_u = .true. end if if (present(vt)) then ! User input vtmat => vt temp_vt = .false. elseif ((m vt_dummy temp_vt = .false. elseif (.not.full_storage) then ! Allocate with minimum size allocate(vtmat(k,n)) temp_vt = .true. else ! Allocate with regular size allocate(vtmat(n,n)) temp_vt = .true. end if ldu = size(umat ,1,kind=ilp) ldvt = size(vtmat,1,kind=ilp) ! Decide SVD task if (.not.compute_uv) then task = GESDD_SINGVAL_ONLY elseif (can_overwrite_amat) then ! A is a copy: we can overwrite its storage task = GESDD_OVERWRITE_A elseif (.not.full_storage) then task = GESDD_SHRINK_MATRICES else task = GESDD_FULL_MATRICES end if ! Compute workspace #:if rt.startswith('complex') if (task==GESDD_SINGVAL_ONLY) then lrwork = max(1,7*k) else lrwork = max(1,5*k*(k+1),2*k*(k+max(m,n))+k) endif allocate(rwork(lrwork)) #:else lrwork = -1_ilp ! not needed #:endif ! First call: request working storage space lwork = -1_ilp call gesdd(task,m,n,amat,lda,s,umat,ldu,vtmat,ldvt,& work_dummy,lwork,#{if rt.startswith('complex')}#rwork,#{endif}#iwork,info) call handle_gesdd_info(this,err0,info,m,n) ! Compute SVD if (info==0) then !> Prepare working storage ! Check if the returned working storage space is smaller than the largest value ! allowed by lwork lwork = merge(nint(real(work_dummy(1),kind=${rk}$), kind=ilp) & , huge(lwork) & , real(work_dummy(1),kind=${rk}$) < real(huge(lwork),kind=${rk}$) ) allocate(work(lwork)) !> Compute SVD call gesdd(task,m,n,amat,lda,s,umat,ldu,vtmat,ldvt,& work,lwork,#{if rt.startswith('complex')}#rwork,#{endif}#iwork,info) call handle_gesdd_info(this,err0,info,m,n) endif ! Finalize storage and process output flag if (.not.overwrite_a_) deallocate(amat) if (temp_u) deallocate(umat) if (temp_vt) deallocate(vtmat) call linalg_error_handling(err0,err) end subroutine stdlib_linalg_svd_${ri}$ #:endfor end submodule stdlib_linalg_svd fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_matrix_functions.fypp0000664000175000017500000001323415135654166027411 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX, REAL_INIT)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX, CMPLX_INIT)) #:set RC_KINDS_TYPES = R_KINDS_TYPES + C_KINDS_TYPES submodule (stdlib_linalg) stdlib_linalg_matrix_functions use stdlib_constants use stdlib_linalg_constants use stdlib_linalg_blas, only: gemm use stdlib_linalg_lapack, only: gesv, lacpy use stdlib_linalg_lapack_aux, only: handle_gesv_info use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR implicit none(type, external) character(len=*), parameter :: this = "matrix_exponential" contains #:for k,t,s, i in RC_KINDS_TYPES module function stdlib_linalg_${i}$_expm_fun(A, order) result(E) !> Input matrix A(n, n). ${t}$, intent(in) :: A(:, :) !> [optional] Order of the Pade approximation. integer(ilp), optional, intent(in) :: order !> Exponential of the input matrix E = exp(A). ${t}$, allocatable :: E(:, :) E = A call stdlib_linalg_${i}$_expm_inplace(E, order) end function stdlib_linalg_${i}$_expm_fun module subroutine stdlib_linalg_${i}$_expm(A, E, order, err) !> Input matrix A(n, n). ${t}$, intent(in) :: A(:, :) !> Exponential of the input matrix E = exp(A). ${t}$, intent(out) :: E(:, :) !> [optional] Order of the Pade approximation. integer(ilp), optional, intent(in) :: order !> [optional] State return flag. type(linalg_state_type), optional, intent(out) :: err type(linalg_state_type) :: err0 integer(ilp) :: lda, n, lde, ne ! Check E sizes lda = size(A, 1, kind=ilp) ; n = size(A, 2, kind=ilp) lde = size(E, 1, kind=ilp) ; ne = size(E, 2, kind=ilp) if (lda<1 .or. n<1 .or. lda/=n .or. lde/=n .or. ne/=n) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR, & 'invalid matrix sizes: A must be square (lda=', lda, ', n=', n, ')', & ' E must be square (lde=', lde, ', ne=', ne, ')') else call lacpy("n", n, n, A, n, E, n) ! E = A call stdlib_linalg_${i}$_expm_inplace(E, order, err0) endif ! Process output and return call linalg_error_handling(err0,err) return end subroutine stdlib_linalg_${i}$_expm module subroutine stdlib_linalg_${i}$_expm_inplace(A, order, err) !> Input matrix A(n, n) / Output matrix exponential. ${t}$, intent(inout) :: A(:, :) !> [optional] Order of the Pade approximation. integer(ilp), optional, intent(in) :: order !> [optional] State return flag. type(linalg_state_type), optional, intent(out) :: err ! Internal variables. ${t}$ :: A2(size(A, 1), size(A, 2)), Q(size(A, 1), size(A, 2)) ${t}$ :: X(size(A, 1), size(A, 2)), X_tmp(size(A, 1), size(A, 2)) real(${k}$) :: a_norm, c integer(ilp) :: m, n, ee, k, s, order_, i, j logical(lk) :: p type(linalg_state_type) :: err0 ! Deal with optional args. order_ = 10 ; if (present(order)) order_ = order ! Problem's dimension. m = size(A, dim=1, kind=ilp) ; n = size(A, dim=2, kind=ilp) if (m /= n) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'Invalid matrix size A=',[m, n]) else if (order_ < 0) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, 'Order of Pade approximation & needs to be positive, order=', order_) else ! Compute the L-infinity norm. a_norm = mnorm(A, "inf") ! Determine scaling factor for the matrix. ee = int(log(a_norm) / log2_${k}$, kind=ilp) + 1 s = max(0, ee+1) ! Scale the input matrix & initialize polynomial. A2 = A/2.0_${k}$**s call lacpy("n", n, n, A2, n, X, n) ! X = A2 ! First step of the Pade approximation. c = 0.5_${k}$ do concurrent(i=1:n, j=1:n) A(i, j) = merge(1.0_${k}$ + c*A2(i, j), c*A2(i, j), i == j) Q(i, j) = merge(1.0_${k}$ - c*A2(i, j), -c*A2(i, j), i == j) enddo ! Iteratively compute the Pade approximation. p = .true. do k = 2, order_ c = c * (order_ - k + 1) / (k * (2*order_ - k + 1)) call lacpy("n", n, n, X, n, X_tmp, n) ! X_tmp = X call gemm("N", "N", n, n, n, one_${s}$, A2, n, X_tmp, n, zero_${s}$, X, n) do concurrent(i=1:n, j=1:n) A(i, j) = A(i, j) + c*X(i, j) ! E = E + c*X Q(i, j) = merge(Q(i, j) + c*X(i, j), Q(i, j) - c*X(i, j), p) enddo p = .not. p enddo block integer(ilp) :: ipiv(n), info call gesv(n, n, Q, n, ipiv, A, n, info) ! E = inv(Q) @ E call handle_gesv_info(this, info, n, n, n, err0) end block ! Matrix squaring. do k = 1, s call lacpy("n", n, n, A, n, X, n) ! X = A call gemm("N", "N", n, n, n, one_${s}$, X, n, X, n, zero_${s}$, A, n) enddo endif call linalg_error_handling(err0, err) return end subroutine stdlib_linalg_${i}$_expm_inplace #:endfor end submodule stdlib_linalg_matrix_functions fortran-lang-stdlib-0ede301/src/linalg/stdlib_linalg_pinv.fypp0000664000175000017500000001204315135654166024766 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule(stdlib_linalg) stdlib_linalg_pseudoinverse !! Compute the (Moore-Penrose) pseudo-inverse of a matrix. use stdlib_linalg_constants use stdlib_linalg_blas use stdlib_linalg_lapack use stdlib_linalg_state use ieee_arithmetic, only: ieee_value, ieee_quiet_nan implicit none character(*), parameter :: this = 'pseudo-inverse' contains #:for rk,rt,ri in RC_KINDS_TYPES ! Compute the in-place pseudo-inverse of matrix a module subroutine stdlib_linalg_pseudoinvert_${ri}$(a,pinva,rtol,err) !> Input matrix a[m,n] ${rt}$, intent(inout) :: a(:,:) !> Output pseudo-inverse matrix ${rt}$, intent(out) :: pinva(:,:) !> [optional] Relative tolerance for singular value cutoff real(${rk}$), optional, intent(in) :: rtol !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err ! Local variables real(${rk}$) :: tolerance,cutoff real(${rk}$), allocatable :: s(:) ${rt}$, allocatable :: u(:,:),vt(:,:) type(linalg_state_type) :: err0 integer(ilp) :: m,n,k,i,j ${rt}$, parameter :: alpha = 1.0_${rk}$, beta = 0.0_${rk}$ character, parameter :: H = #{if rt.startswith('complex')}# 'C' #{else}# 'T' #{endif}# ! Problem size m = size(a,1,kind=ilp) n = size(a,2,kind=ilp) k = min(m,n) if (m<1 .or. n<1) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size: a=',[m,n]) call linalg_error_handling(err0,err) return end if if (any(shape(pinva,kind=ilp)/=[n,m])) then err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid pinv size:',shape(pinva),'should be',[n,m]) call linalg_error_handling(err0,err) return end if ! Singular value threshold tolerance = max(m,n)*epsilon(0.0_${rk}$) ! User threshold: fallback to default if <=0 if (present(rtol)) then if (rtol>0.0_${rk}$) tolerance = rtol end if allocate(s(k),u(m,k),vt(k,n)) call svd(a,s,u,vt,overwrite_a=.false.,full_matrices=.false.,err=err0) if (err0%error()) then err0 = linalg_state_type(this,LINALG_ERROR,'svd failure -',err0%message) call linalg_error_handling(err0,err) return endif !> Discard singular values cutoff = tolerance*maxval(s) s = merge(1.0_${rk}$/s,0.0_${rk}$,s>cutoff) ! Get pseudo-inverse: A_pinv = V * (diag(1/s) * U^H) = V * (U * diag(1/s))^H ! 1) compute (U * diag(1/s)) in-place do concurrent (i=1:m,j=1:k) u(i,j) = s(j)*u(i,j) end do ! 2) commutate matmul: A_pinv = V * (U * diag(1/s))^H = ((U * diag(1/s)) * V^H)^H. ! This avoids one matrix transpose call gemm(H, H, n, m, k, alpha, vt, k, u, m, beta, pinva, size(pinva,1,kind=ilp)) end subroutine stdlib_linalg_pseudoinvert_${ri}$ ! Function interface module function stdlib_linalg_pseudoinverse_${ri}$(a,rtol,err) result(pinva) !> Input matrix a[m,n] ${rt}$, intent(in), target :: a(:,:) !> [optional] Relative tolerance for singular value cutoff real(${rk}$), optional, intent(in) :: rtol !> [optional] state return flag. On error if not requested, the code will stop type(linalg_state_type), optional, intent(out) :: err !> Matrix pseudo-inverse ${rt}$ :: pinva(size(a,2,kind=ilp),size(a,1,kind=ilp)) ! Use pointer to circumvent svd intent(inout) restriction ${rt}$, pointer :: ap(:,:) ap => a call stdlib_linalg_pseudoinvert_${ri}$(ap,pinva,rtol,err) end function stdlib_linalg_pseudoinverse_${ri}$ ! Inverse matrix operator module function stdlib_linalg_pinv_${ri}$_operator(a) result(pinva) !> Input matrix a[m,n] ${rt}$, intent(in), target :: a(:,:) !> Result pseudo-inverse matrix ${rt}$ :: pinva(size(a,2,kind=ilp),size(a,1,kind=ilp)) type(linalg_state_type) :: err ! Use pointer to circumvent svd intent(inout) restriction ${rt}$, pointer :: ap(:,:) ap => a call stdlib_linalg_pseudoinvert_${ri}$(ap,pinva,err=err) if (err%error()) then #:if rt.startswith('real') pinva = ieee_value(1.0_${rk}$,ieee_quiet_nan) #:else pinva = cmplx(ieee_value(1.0_${rk}$,ieee_quiet_nan), & ieee_value(1.0_${rk}$,ieee_quiet_nan), kind=${rk}$) #:endif endif end function stdlib_linalg_pinv_${ri}$_operator #:endfor end submodule stdlib_linalg_pseudoinverse fortran-lang-stdlib-0ede301/src/array/0000775000175000017500000000000015135654166020073 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/array/CMakeLists.txt0000664000175000017500000000027715135654166022641 0ustar alastairalastairset(array_fppFiles ) set(array_cppFiles ) set(array_f90Files stdlib_array.f90 ) configure_stdlib_target(${PROJECT_NAME}_array array_f90Files array_fppFiles array_cppFiles) fortran-lang-stdlib-0ede301/src/array/stdlib_array.f900000664000175000017500000000357115135654166023100 0ustar alastairalastair! SPDX-Identifier: MIT !> Module for index manipulation and general array handling !> !> The specification of this module is available [here](../page/specs/stdlib_array.html). module stdlib_array implicit none private public :: trueloc, falseloc contains !> Version: experimental !> !> Return the positions of the true elements in array. !> [Specification](../page/specs/stdlib_array.html#trueloc) pure function trueloc(array, lbound) result(loc) !> Mask of logicals logical, intent(in) :: array(:) !> Lower bound of array to index integer, intent(in), optional :: lbound !> Locations of true elements integer :: loc(count(array)) call logicalloc(loc, array, .true., lbound) end function trueloc !> Version: experimental !> !> Return the positions of the false elements in array. !> [Specification](../page/specs/stdlib_array.html#falseloc) pure function falseloc(array, lbound) result(loc) !> Mask of logicals logical, intent(in) :: array(:) !> Lower bound of array to index integer, intent(in), optional :: lbound !> Locations of false elements integer :: loc(count(.not.array)) call logicalloc(loc, array, .false., lbound) end function falseloc !> Return the positions of the truthy elements in array pure subroutine logicalloc(loc, array, truth, lbound) !> Locations of truthy elements integer, intent(out) :: loc(:) !> Mask of logicals logical, intent(in) :: array(:) !> Truthy value logical, intent(in) :: truth !> Lower bound of array to index integer, intent(in), optional :: lbound integer :: i, pos, offset offset = 0 if (present(lbound)) offset = lbound - 1 i = 0 do pos = 1, size(array) if (array(pos).eqv.truth) then i = i + 1 loc(i) = pos + offset end if end do end subroutine logicalloc end module stdlib_array fortran-lang-stdlib-0ede301/src/specialfunctions/0000775000175000017500000000000015135654166022326 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/specialfunctions/stdlib_specialfunctions.fypp0000664000175000017500000003404715135654166030150 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(2, MAXRANK + 1) module stdlib_specialfunctions use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp implicit none private interface legendre !! version: experimental !! !! Legendre polynomial pure elemental module function legendre_fp64(n,x) result(leg) integer, intent(in) :: n real(dp), intent(in) :: x real(dp) :: leg end function end interface public :: legendre interface dlegendre !! version: experimental !! !! First derivative Legendre polynomial pure elemental module function dlegendre_fp64(n,x) result(dleg) integer, intent(in) :: n real(dp), intent(in) :: x real(dp) :: dleg end function end interface public :: dlegendre interface gaussian !! Version: experimental !! !! gaussian function !> ([Specification](../page/specs/stdlib_specialfunctions.html#gaussian)) #:for rk, rt in REAL_KINDS_TYPES elemental module function gaussian_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: gaussian interface gaussian_grad !! Version: experimental !! !! gradient of the gaussian function !> ([Specification](../page/specs/stdlib_specialfunctions.html#gaussian_grad)) #:for rk, rt in REAL_KINDS_TYPES elemental module function gaussian_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: gaussian_grad interface elu !! Version: experimental !! !! exponential linear unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#elu)) #:for rk, rt in REAL_KINDS_TYPES elemental module function elu_${rk}$( x , a ) result( y ) ${rt}$, intent(in) :: x ${rt}$, intent(in) :: a ${rt}$ :: y end function #:endfor end interface public :: elu interface elu_grad !! Version: experimental !! !! gradient of the exponential linear unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#elu_grad)) #:for rk, rt in REAL_KINDS_TYPES elemental module function elu_grad_${rk}$( x , a ) result( y ) ${rt}$, intent(in) :: x ${rt}$, intent(in) :: a ${rt}$ :: y end function #:endfor end interface public :: elu_grad interface relu !! Version: experimental !! !! Rectified linear unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#relu)) #:for rk, rt in REAL_KINDS_TYPES elemental module function relu_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: relu interface relu_grad !! Version: experimental !! !! Gradient rectified linear unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#relu_grad)) #:for rk, rt in REAL_KINDS_TYPES elemental module function relu_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: relu_grad interface leaky_relu !! Version: experimental !! !! leaky Rectified linear unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#leaky_relu)) #:for rk, rt in REAL_KINDS_TYPES elemental module function leaky_relu_${rk}$( x , a ) result( y ) ${rt}$, intent(in) :: x ${rt}$, intent(in) :: a ${rt}$ :: y end function #:endfor end interface public :: leaky_relu interface leaky_relu_grad !! Version: experimental !! !! Gradient of the leaky Rectified linear unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#leaky_relu_grad)) #:for rk, rt in REAL_KINDS_TYPES elemental module function leaky_relu_grad_${rk}$( x , a ) result( y ) ${rt}$, intent(in) :: x ${rt}$, intent(in) :: a ${rt}$ :: y end function #:endfor end interface public :: leaky_relu_grad interface gelu !! Version: experimental !! !! Gaussian error linear unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#gelu)) #:for rk, rt in REAL_KINDS_TYPES elemental module function gelu_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: gelu interface gelu_grad !! Version: experimental !! !! Gradient of the gaussian error linear unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#gelu_grad)) #:for rk, rt in REAL_KINDS_TYPES elemental module function gelu_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: gelu_grad interface gelu_approx !! Version: experimental !! !! Approximated gaussian error linear unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#gelu_approx)) #:for rk, rt in REAL_KINDS_TYPES elemental module function gelu_approx_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: gelu_approx interface gelu_approx_grad !! Version: experimental !! !! Gradient of the approximated gaussian error linear unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#gelu_approx_grad)) #:for rk, rt in REAL_KINDS_TYPES elemental module function gelu_approx_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: gelu_approx_grad interface selu !! Version: experimental !! !! Scaled Exponential Linear Unit !> ([Specification](../page/specs/stdlib_specialfunctions.html#selu)) #:for rk, rt in REAL_KINDS_TYPES elemental module function selu_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: selu interface selu_grad !! Version: experimental !! !! Scaled Exponential Linear Unit !> ([Specification](../page/specs/stdlib_specialfunctions.html#selu_grad)) #:for rk, rt in REAL_KINDS_TYPES elemental module function selu_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: selu_grad interface sigmoid !! Version: experimental !! !! Sigmoid function !> ([Specification](../page/specs/stdlib_specialfunctions.html#sigmoid)) #:for rk, rt in REAL_KINDS_TYPES elemental module function sigmoid_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: sigmoid interface sigmoid_grad !! Version: experimental !! !! Gradient of the sigmoid function !> ([Specification](../page/specs/stdlib_specialfunctions.html#sigmoid_grad)) #:for rk, rt in REAL_KINDS_TYPES elemental module function sigmoid_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: sigmoid_grad interface silu !! Version: experimental !! !! Sigmoid Linear Unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#silu)) #:for rk, rt in REAL_KINDS_TYPES elemental module function silu_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: silu interface silu_grad !! Version: experimental !! !! Gradient of the Sigmoid Linear Unit function !> ([Specification](../page/specs/stdlib_specialfunctions.html#silu_grad)) #:for rk, rt in REAL_KINDS_TYPES elemental module function silu_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: silu_grad interface step !! Version: experimental !! !! Step function !> ([Specification](../page/specs/stdlib_specialfunctions.html#step)) #:for rk, rt in REAL_KINDS_TYPES elemental module function step_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: step interface step_grad !! Version: experimental !! !! Gradient of the step function !> ([Specification](../page/specs/stdlib_specialfunctions.html#step_grad)) #:for rk, rt in REAL_KINDS_TYPES elemental module function step_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: step_grad interface softmax !! Version: experimental !! !! softmax function. Available for ranks 1 to 4 !> ([Specification](../page/specs/stdlib_specialfunctions.html#softmax)) #:for rk, rt in REAL_KINDS_TYPES pure module function softmax_r1_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x(:) ${rt}$ :: y(size(x)) end function #:for rank in RANKS pure module function softmax_r${rank}$_${rk}$( x , dim ) result( y ) ${rt}$, intent(in) :: x${ranksuffix(rank)}$ ${rt}$ :: y${shape_from_array_size('x', rank)}$ integer, intent(in), optional :: dim end function #:endfor #:endfor end interface public :: softmax interface softmax_grad !! Version: experimental !! !! Gradient of the softmax function. Available for ranks 1 to 4 !> ([Specification](../page/specs/stdlib_specialfunctions.html#softmax_grad)) #:for rk, rt in REAL_KINDS_TYPES pure module function softmax_grad_r1_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x(:) ${rt}$ :: y(size(x)) end function #:for rank in RANKS pure module function softmax_grad_r${rank}$_${rk}$( x , dim ) result( y ) ${rt}$, intent(in) :: x${ranksuffix(rank)}$ ${rt}$ :: y${shape_from_array_size('x', rank)}$ integer, intent(in), optional :: dim end function #:endfor #:endfor end interface public :: softmax_grad interface logsoftmax !! Version: experimental !! !! softmax function. Available for ranks 1 to 4 !> ([Specification](../page/specs/stdlib_specialfunctions.html#logsoftmax)) #:for rk, rt in REAL_KINDS_TYPES pure module function logsoftmax_r1_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x(:) ${rt}$ :: y(size(x)) end function #:for rank in RANKS pure module function logsoftmax_r${rank}$_${rk}$( x , dim ) result( y ) ${rt}$, intent(in) :: x${ranksuffix(rank)}$ ${rt}$ :: y${shape_from_array_size('x', rank)}$ integer, intent(in), optional :: dim end function #:endfor #:endfor end interface public :: logsoftmax interface softplus !! Version: experimental !! !! softplus function !> ([Specification](../page/specs/stdlib_specialfunctions.html#softplus)) #:for rk, rt in REAL_KINDS_TYPES elemental module function softplus_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: softplus interface softplus_grad !! Version: experimental !! !! Gradient of the softplus function !> ([Specification](../page/specs/stdlib_specialfunctions.html#softplus_grad)) #:for rk, rt in REAL_KINDS_TYPES elemental module function softplus_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: softplus_grad interface fast_tanh !! Version: experimental !! !! Fast approximation of the tanh function #:for rk, rt in REAL_KINDS_TYPES elemental module function fast_tanh_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: fast_tanh interface fast_tanh_grad !! Version: experimental !! !! gradient of the hyperbolic tangent function #:for rk, rt in REAL_KINDS_TYPES elemental module function fast_tanh_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: fast_tanh_grad interface fast_erf !! Version: experimental !! !! Fast approximation of the erf function #:for rk, rt in REAL_KINDS_TYPES elemental module function fast_erf_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y end function #:endfor end interface public :: fast_erf end module stdlib_specialfunctionsfortran-lang-stdlib-0ede301/src/specialfunctions/stdlib_specialfunctions_activations.fypp0000664000175000017500000002510115135654166032543 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(2, MAXRANK + 1) submodule(stdlib_specialfunctions) stdlib_specialfunctions_activations use stdlib_intrinsics, only: sum => stdlib_sum implicit none #:for rk, rt in REAL_KINDS_TYPES ${rt}$, parameter :: isqrt2_${rk}$ = 1._${rk}$ / sqrt(2._${rk}$) #:endfor contains !================================================== ! Gaussian !================================================== #:for rk, rt in REAL_KINDS_TYPES elemental module function gaussian_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = exp(-x**2) end function elemental module function gaussian_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = -2._${rk}$ * x * exp(-x**2) end function #:endfor !================================================== ! Exponential Linear Unit !================================================== #:for rk, rt in REAL_KINDS_TYPES elemental module function elu_${rk}$( x , a ) result ( y ) ${rt}$, intent(in) :: x ${rt}$, intent(in) :: a ${rt}$ :: y y = merge( x , a * (exp(x) - 1._${rk}$), x >= 0._${rk}$) end function elemental module function elu_grad_${rk}$( x , a ) result ( y ) ${rt}$, intent(in) :: x ${rt}$, intent(in) :: a ${rt}$ :: y y = merge( 1._${rk}$ , a * exp(x), x >= 0._${rk}$) end function #:endfor !================================================== ! Rectified Linear Unit !================================================== #:for rk, rt in REAL_KINDS_TYPES elemental module function relu_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = max(0._${rk}$, x) end function elemental module function relu_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = merge( 1._${rk}$ , 0._${rk}$, x > 0._${rk}$) end function #:endfor !================================================== ! leaky Rectified Linear Unit !================================================== #:for rk, rt in REAL_KINDS_TYPES elemental module function leaky_relu_${rk}$( x , a ) result( y ) ${rt}$, intent(in) :: x ${rt}$, intent(in) :: a ${rt}$ :: y y = merge( x, a * x , x >= 0._${rk}$) end function elemental module function leaky_relu_grad_${rk}$( x , a ) result( y ) ${rt}$, intent(in) :: x ${rt}$, intent(in) :: a ${rt}$ :: y y = merge( 1._${rk}$ , a , x >= 0._${rk}$) end function #:endfor !================================================== ! GELU: Gaussian Error Linear Units function !================================================== #:for rk, rt in REAL_KINDS_TYPES elemental module function gelu_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = 0.5_${rk}$ * x * (1._${rk}$ + erf(x * isqrt2_${rk}$)) end function elemental module function gelu_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = 0.5_${rk}$ * (1._${rk}$ + erf(x * isqrt2_${rk}$) ) y = y + x * isqrt2_${rk}$ * exp( - 0.5_${rk}$ * x**2 ) end function #:endfor #:for rk, rt in REAL_KINDS_TYPES elemental module function gelu_approx_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = 0.5_${rk}$ * x * (1._${rk}$ + fast_erf(x * isqrt2_${rk}$)) end function elemental module function gelu_approx_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = 0.5_${rk}$ * (1._${rk}$ + fast_erf(x * isqrt2_${rk}$) ) y = y + x * isqrt2_${rk}$ * exp( - 0.5_${rk}$ * x**2 ) end function #:endfor !================================================== ! Scaled Exponential Linear Unit (SELU) !================================================== #:for rk, rt in REAL_KINDS_TYPES elemental module function selu_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y ${rt}$, parameter :: scale = 1.0507009873554804934193349852946_${rk}$ ${rt}$, parameter :: alpha = 1.6732632423543772848170429916717_${rk}$ y = merge( x , alpha * exp(x) - alpha, x > 0._${rk}$) y = scale * y end function elemental module function selu_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y ${rt}$, parameter :: scale = 1.0507009873554804934193349852946_${rk}$ ${rt}$, parameter :: alpha = 1.6732632423543772848170429916717_${rk}$ y = merge( scale , scale * alpha * exp(x), x > 0._${rk}$) end function #:endfor !================================================== ! Sigmoid !================================================== #:for rk, rt in REAL_KINDS_TYPES elemental module function sigmoid_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = 1._${rk}$ / (1._${rk}$ + exp(-x)) end function elemental module function sigmoid_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = exp(x) / (1._${rk}$ + exp(x))**2 end function #:endfor !================================================== ! SiLU: Sigmoid Linear Unit !================================================== #:for rk, rt in REAL_KINDS_TYPES elemental module function silu_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = x / (1._${rk}$ + exp(-x)) end function elemental module function silu_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = (1._${rk}$ + exp(x))**2 y = exp(x) * ( x + y ) / y end function #:endfor !================================================== ! Step !================================================== #:for rk, rt in REAL_KINDS_TYPES elemental module function step_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = merge( 1._${rk}$ , 0._${rk}$, x > 0._${rk}$) end function elemental module function step_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = 0._${rk}$ end function #:endfor !================================================== ! softmax !================================================== #:for rk, rt in REAL_KINDS_TYPES pure module function softmax_r1_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x(:) ${rt}$ :: y(size(x)) y = exp(x - maxval(x)) y = y / sum(y) end function #:for rank in RANKS pure module function softmax_r${rank}$_${rk}$( x , dim ) result( y ) ${rt}$, intent(in) :: x${ranksuffix(rank)}$ ${rt}$ :: y${shape_from_array_size('x', rank)}$ integer, intent(in), optional :: dim integer :: dim_, j dim_ = 1; if(present(dim)) dim_ = dim if(dim_<${rank}$)then do j = 1, size(x,dim=${rank}$) #:if rank == 2 y${select_subarray(rank, [(rank, 'j')])}$ = softmax( x${select_subarray(rank, [(rank, 'j')])}$ ) #:else y${select_subarray(rank, [(rank, 'j')])}$ = softmax( x${select_subarray(rank, [(rank, 'j')])}$, dim=dim_ ) #:endif end do else do j = 1, size(x,dim=1) #:if rank == 2 y${select_subarray(rank, [(1, 'j')])}$ = softmax( x${select_subarray(rank, [(1, 'j')])}$ ) #:else y${select_subarray(rank, [(1, 'j')])}$ = softmax( x${select_subarray(rank, [(1, 'j')])}$, dim=${rank-1}$ ) #:endif end do end if end function #:endfor pure module function softmax_grad_r1_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x(:) ${rt}$ :: y(size(x)) y = softmax(x) y = y * (1._${rk}$ - y) end function #:for rank in RANKS pure module function softmax_grad_r${rank}$_${rk}$( x , dim ) result( y ) ${rt}$, intent(in) :: x${ranksuffix(rank)}$ ${rt}$ :: y${shape_from_array_size('x', rank)}$ integer, intent(in), optional :: dim integer :: dim_ dim_ = 1; if(present(dim)) dim_ = dim y = softmax(x,dim_) y = y * (1._${rk}$ - y) end function #:endfor #:endfor !================================================== ! logsoftmax !================================================== #:for rk, rt in REAL_KINDS_TYPES pure module function logsoftmax_r1_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x(:) ${rt}$ :: y(size(x)) y = x - maxval(x) y = y - log( sum(exp(y)) ) end function #:for rank in RANKS pure module function logsoftmax_r${rank}$_${rk}$( x , dim ) result( y ) ${rt}$, intent(in) :: x${ranksuffix(rank)}$ ${rt}$ :: y${shape_from_array_size('x', rank)}$ integer, intent(in), optional :: dim integer :: dim_, j dim_ = 1; if(present(dim)) dim_ = dim if(dim_<${rank}$)then do j = 1, size(x,dim=${rank}$) #:if rank == 2 y${select_subarray(rank, [(rank, 'j')])}$ = logsoftmax( x${select_subarray(rank, [(rank, 'j')])}$ ) #:else y${select_subarray(rank, [(rank, 'j')])}$ = logsoftmax( x${select_subarray(rank, [(rank, 'j')])}$, dim=dim_ ) #:endif end do else do j = 1, size(x,dim=1) #:if rank == 2 y${select_subarray(rank, [(1, 'j')])}$ = logsoftmax( x${select_subarray(rank, [(1, 'j')])}$ ) #:else y${select_subarray(rank, [(1, 'j')])}$ = logsoftmax( x${select_subarray(rank, [(1, 'j')])}$, dim=${rank-1}$ ) #:endif end do end if end function #:endfor #:endfor !================================================== ! softplus !================================================== #:for rk, rt in REAL_KINDS_TYPES elemental module function softplus_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = log(exp(x) + 1._${rk}$) end function elemental module function softplus_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = exp(x) / (exp(x) + 1._${rk}$) end function #:endfor !================================================== ! Fast intrinsics for accelerated activations !================================================== ! Source: https://fortran-lang.discourse.group/t/fastgpt-faster-than-pytorch-in-300-lines-of-fortran/5385/31 #:for rk, rt in REAL_KINDS_TYPES elemental module function fast_tanh_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y ${rt}$ :: x2, a, b x2 = x*x a = x * (135135.0_${rk}$ + x2 * (17325.0_${rk}$ + x2 * (378.0_${rk}$ + x2))) b = 135135.0_${rk}$ + x2 * (62370.0_${rk}$ + x2 * (3150.0_${rk}$ + x2 * 28.0_${rk}$)) y = merge( a / b , sign(1._${rk}$,x) , x2 <= 25._${rk}$ ) end function elemental module function fast_tanh_grad_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y y = 1._${rk}$ - fast_tanh(x)**2 end function elemental module function fast_erf_${rk}$( x ) result( y ) ${rt}$, intent(in) :: x ${rt}$ :: y ${rt}$ :: abs_x abs_x = abs(x) y = 1._${rk}$ - 1._${rk}$ / (1._${rk}$+ 0.278393_${rk}$*abs_x + 0.230389_${rk}$*abs_x**2 + 0.000972_${rk}$*abs_x**3 + 0.078108_${rk}$*abs_x**4)**4 y = y * sign(1.0_${rk}$,x) end function #:endfor end submodulefortran-lang-stdlib-0ede301/src/specialfunctions/stdlib_specialfunctions_gamma.fypp0000664000175000017500000010512315135654166031304 0ustar alastairalastair#:include "common.fypp" #:set CI_KINDS_TYPES = INT_KINDS_TYPES + CMPLX_KINDS_TYPES #:set IDX_CMPLX_KINDS_TYPES = [(i, CMPLX_KINDS[i], CMPLX_TYPES[i], CMPLX_INIT[i]) for i in range(len(CMPLX_KINDS))] #:set IDX_REAL_KINDS_TYPES = [(i, REAL_KINDS[i], REAL_TYPES[i], REAL_INIT[i]) for i in range(len(REAL_KINDS))] module stdlib_specialfunctions_gamma use ieee_arithmetic, only: ieee_value, ieee_quiet_nan use stdlib_kinds, only : sp, dp, xdp, qp, int8, int16, int32, int64 use stdlib_error, only : error_stop implicit none private integer(int8), parameter :: max_fact_int8 = 6_int8 integer(int16), parameter :: max_fact_int16 = 8_int16 integer(int32), parameter :: max_fact_int32 = 13_int32 integer(int64), parameter :: max_fact_int64 = 21_int64 #:for k1, t1 in REAL_KINDS_TYPES ${t1}$, parameter :: tol_${k1}$ = epsilon(1.0_${k1}$) #:endfor public :: gamma, log_gamma, log_factorial public :: lower_incomplete_gamma, log_lower_incomplete_gamma public :: upper_incomplete_gamma, log_upper_incomplete_gamma public :: regularized_gamma_p, regularized_gamma_q interface gamma !! Gamma function for integer and complex numbers !! #:for k1, t1 in CI_KINDS_TYPES[:-1] module procedure gamma_${t1[0]}$${k1}$ #:endfor end interface gamma interface log_gamma !! Logarithm of gamma function !! #:for k1, t1 in CI_KINDS_TYPES[:-1] module procedure l_gamma_${t1[0]}$${k1}$ #:endfor end interface log_gamma interface log_factorial !! Logarithm of factorial n!, integer variable !! #:for k1, t1 in INT_KINDS_TYPES module procedure l_factorial_${t1[0]}$${k1}$ #:endfor end interface log_factorial interface lower_incomplete_gamma !! Lower incomplete gamma function !! #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] module procedure ingamma_low_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] module procedure ingamma_low_${t1[0]}$${k1}$ #:endfor end interface lower_incomplete_gamma interface log_lower_incomplete_gamma !! Logarithm of lower incomplete gamma function !! #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] module procedure l_ingamma_low_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] module procedure l_ingamma_low_${t1[0]}$${k1}$ #:endfor end interface log_lower_incomplete_gamma interface upper_incomplete_gamma !! Upper incomplete gamma function !! #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] module procedure ingamma_up_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] module procedure ingamma_up_${t1[0]}$${k1}$ #:endfor end interface upper_incomplete_gamma interface log_upper_incomplete_gamma !! Logarithm of upper incomplete gamma function !! #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] module procedure l_ingamma_up_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] module procedure l_ingamma_up_${t1[0]}$${k1}$ #:endfor end interface log_upper_incomplete_gamma interface regularized_gamma_p !! Regularized (normalized) lower incomplete gamma function, P !! #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] module procedure regamma_p_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] module procedure regamma_p_${t1[0]}$${k1}$ #:endfor end interface regularized_gamma_p interface regularized_gamma_q !! Regularized (normalized) upper incomplete gamma function, Q !! #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] module procedure regamma_q_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] module procedure regamma_q_${t1[0]}$${k1}$ #:endfor end interface regularized_gamma_q interface gpx ! Incomplete gamma G function. ! Internal use only ! #:for k1, t1 in REAL_KINDS_TYPES[:-1] module procedure gpx_${t1[0]}$${k1}$ !for real p and x #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] module procedure gpx_${t1[0]}$${k1}$${k2}$ !for integer p and real x #:endfor #:endfor end interface gpx interface l_gamma ! Logarithm of gamma with integer argument for designated output kind. ! Internal use only ! #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] module procedure l_gamma_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor end interface l_gamma contains #:for k1, t1 in INT_KINDS_TYPES impure elemental function gamma_${t1[0]}$${k1}$(z) result(res) ${t1}$, intent(in) :: z ${t1}$ :: res, i ${t1}$, parameter :: zero = 0_${k1}$, one = 1_${k1}$ if(z <= zero) call error_stop("Error(gamma): Gamma function argument" & //" must be positive integer.") if(z > max_fact_${k1}$) call error_stop("Error(gamma): Gamma function" & //" integer argument is greater than the upper limit from which an"& //" integer overflow will be generated. Suggest switch to high " & //" precision or convert to real data type") res = one do i = one, z - one res = res * i end do end function gamma_${t1[0]}$${k1}$ #:endfor #! Because the KIND lists are sorted by increasing accuracy, #! gamma will use the next available more accurate KIND for the #! internal more accurate solver. #:for i, k1, t1, i1 in IDX_CMPLX_KINDS_TYPES[:-1] #:set k2 = CMPLX_KINDS[i + 1] if k1 == "sp" else CMPLX_KINDS[-1] #:set t2 = "real({})".format(k2) impure elemental function gamma_${t1[0]}$${k1}$(z) result(res) ${t1}$, intent(in) :: z ${t1}$ :: res integer :: i real(${k1}$), parameter :: zero_k1 = 0.0_${k1}$ ${t2}$, parameter :: half = 0.5_${k2}$, & one = 1.0_${k2}$, pi = acos(- one), sqpi = sqrt(pi) complex(${k2}$) :: y, x, sum #:if k1 == "sp" #! for single precision input, using double precision for calculation integer, parameter :: n = 10 ${t2}$, parameter :: r = 10.900511_${k2}$ ${t2}$, parameter :: d(0 : n) = [2.48574089138753566e-5_${k2}$, & 1.05142378581721974_${k2}$, & -3.45687097222016235_${k2}$, & 4.51227709466894824_${k2}$, & -2.98285225323576656_${k2}$, & 1.05639711577126713_${k2}$, & -1.95428773191645870e-1_${k2}$, & 1.70970543404441224e-2_${k2}$, & -5.71926117404305781e-4_${k2}$, & 4.63399473359905637e-6_${k2}$, & -2.71994908488607704e-9_${k2}$] ! parameters from above referenced source. #:else #! for double or extended precision input, using quadruple precision for calculation integer, parameter :: n = 24 ${t2}$, parameter :: r = 25.617904_${k2}$ ${t2}$, parameter :: d(0 : n)= & [1.0087261714899910504854136977047144166e-11_${k2}$, & 1.6339627701280724777912729825256860624_${k2}$, & -1.4205787702221583745972794018472259342e+1_${k2}$, & 5.6689501646428786119793943350900908698e+1_${k2}$, & -1.3766376824252176069406853670529834070e+2_${k2}$, & 2.2739972766608392140035874845640820558e+2_${k2}$, & -2.7058382145757164380300118233258834430e+2_${k2}$, & 2.39614374587263042692333711131832094166e+2_${k2}$, & -1.6090450559507517723393498276315290189e+2_${k2}$, & 8.27378183187161305711485619113605553100e+1_${k2}$, & -3.2678977082742592701862249152153110206e+1_${k2}$, & 9.89018079175824824537131521501652931756_${k2}$, & -2.2762136356329318377213053650799013041_${k2}$, & 3.93265017303573867227590563182750070164e-1_${k2}$, & -5.0051054352146209116457193223422284239e-2_${k2}$, & 4.57142601898244576789629257292603538238e-3_${k2}$, & -2.8922592124650765614787233510990416584e-4_${k2}$, & 1.20833375377219592849746118012697473202e-5_${k2}$, & -3.1220812187551248389268359432609135033e-7_${k2}$, & 4.55117045361638520378367871355819524460e-9_${k2}$, & -3.2757632817493581828033170342853173968e-11_${k2}$, & 9.49784279240135747819870224486376897253e-14_${k2}$, & -7.9480594917454410117072562195702526836e-17_${k2}$, & 1.04692819439870077791406760109955648941e-20_${k2}$, & -5.8990280044857540075384586350723191533e-26_${k2}$] ! parameters from above referenced source. #:endif if(abs(z % im) < tol_${k1}$) then res = cmplx(gamma(z % re), kind = ${k1}$) return end if if(z % re < zero_k1) then x = cmplx(abs(z % re), - z % im, kind = ${k1}$) y = x - one else y = z - one end if sum = cmplx(d(0), kind = ${k2}$) do i = 1, n sum = sum + d(i) / (y + i) end do y = exp((y + half) * log(y + half + r) - y) * sum y = y * 2 / sqpi !Re(z) > 0 return if(z % re < zero_k1 ) then y = - pi / (sin(pi * x) * x * y) !Re(z) < 0 return end if res = y end function gamma_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES impure elemental function l_gamma_${t1[0]}$${k1}$(z) result(res) ! ! Logarithm of gamma function for integer input ! ${t1}$, intent(in) :: z real(dp) :: res ${t1}$ :: i ${t1}$, parameter :: zero = 0_${k1}$, one = 1_${k1}$, two = 2_${k1}$ if(z <= zero) call error_stop("Error(log_gamma): Gamma function" & //" argument must be positive integer.") select case(z) case (one) res = 0.0 case (two :) res = 0.0 do i = one, z - one res = res + log(real(i,dp)) end do end select end function l_gamma_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] impure elemental function l_gamma_${t1[0]}$${k1}$${k2}$(z, x) result(res) ! ! Logarithm of gamma function for integer input with defined precision output ! ${t1}$, intent(in) :: z ${t2}$, intent(in) :: x ${t2}$ :: res ${t1}$ :: i ${t1}$, parameter :: zero = 0_${k1}$, one = 1_${k1}$, two = 2_${k1}$ ${t2}$, parameter :: zero_k2 = 0.0_${k2}$ if(z <= zero) call error_stop("Error(log_gamma): Gamma function" & //" argument must be positive integer.") select case(z) case (one) res = zero_k2 case (two :) res = zero_k2 do i = one, z - one res = res + log(real(i, ${k2}$)) end do end select end function l_gamma_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #! Because the KIND lists are sorted by increasing accuracy, #! gamma will use the next available more accurate KIND for the #! internal more accurate solver. #:for i, k1, t1, i1 in IDX_CMPLX_KINDS_TYPES[:-1] #:set k2 = CMPLX_KINDS[i + 1] if k1 == "sp" else CMPLX_KINDS[-1] #:set t2 = "real({})".format(k2) impure elemental function l_gamma_${t1[0]}$${k1}$(z) result (res) ! ! log_gamma function for any complex number, excluding negative whole number ! "Computation of special functions", Shanjie Zhang & Jianmin Jin, 1996, p.48 ! "Computing the principal branch of log-gamma", D.E.G. Hare, ! J. of Algorithms, 25(2), 1997 p. 221–236 ! ! Fortran 90 program by Jim-215-Fisher ! ${t1}$, intent(in) :: z ${t1}$ :: res, z1, z2 real(${k1}$) :: d integer :: m, i complex(${k2}$) :: zr, zr2, sum, s real(${k1}$), parameter :: z_limit = 10.0_${k1}$, zero_k1 = 0.0_${k1}$ integer, parameter :: n = 20 ${t2}$, parameter :: zero = 0.0_${k2}$, one = 1.0_${k2}$, & pi = acos(-one), ln2pi = log(2 * pi) ${t2}$, parameter :: a(n) = [ & .8333333333333333333333333333333333333333E-1_${k2}$,& -.2777777777777777777777777777777777777778E-2_${k2}$,& .7936507936507936507936507936507936507937E-3_${k2}$,& -.5952380952380952380952380952380952380952E-3_${k2}$,& .8417508417508417508417508417508417508418E-3_${k2}$,& -.1917526917526917526917526917526917526918E-2_${k2}$,& .6410256410256410256410256410256410256410E-2_${k2}$,& -.2955065359477124183006535947712418300654E-1_${k2}$,& .1796443723688305731649384900158893966944E+0_${k2}$,& -.1392432216905901116427432216905901116427E+1_${k2}$,& .1340286404416839199447895100069013112491E+2_${k2}$,& -.1568482846260020173063651324520889738281E+3_${k2}$,& .2193103333333333333333333333333333333333E+4_${k2}$,& -.3610877125372498935717326521924223073648E+5_${k2}$,& .6914722688513130671083952507756734675533E+6_${k2}$,& -.1523822153940741619228336495888678051866E+8_${k2}$,& .3829007513914141414141414141414141414141E+9_${k2}$,& -.1088226603578439108901514916552510537473E+11_${k2}$,& .3473202837650022522522522522522522522523E+12_${k2}$,& -.1236960214226927445425171034927132488108E+14_${k2}$] ! parameters from above reference z2 = z if(z % re < zero_k1) then z2 = cmplx(abs(z % re), - z % im, kind = ${k1}$) + 1 end if d = hypot(z2 % re, z2 % im) z1 = z2 m = 0 if(d <= z_limit) then !for small |z| m = ceiling(z_limit - d) z1 = z2 + m end if zr = one / z1 zr2 = zr * zr sum = (((a(20) * zr2 + a(19)) * zr2 + a(18)) * zr2 + a(17)) * zr2 sum = (((sum + a(16)) * zr2 + a(15)) * zr2 + a(14)) * zr2 sum = (((sum + a(13)) * zr2 + a(12)) * zr2 + a(11)) * zr2 sum = (((sum + a(10)) * zr2 + a(9)) * zr2 + a(8)) * zr2 sum = (((sum + a(7)) * zr2 + a(6)) * zr2 + a(5)) * zr2 sum = (((sum + a(4)) * zr2 + a(3)) * zr2 + a(2)) * zr2 sum = (sum + a(1)) * zr + ln2pi / 2 - z1 + (z1 - 0.5_${k2}$) * log(z1) if(m /= 0) then s = cmplx(zero, zero, kind = ${k2}$) do i = 1, m s = s + log(cmplx(z1, kind = ${k2}$) - i) end do sum = sum - s end if if(z % re < zero_k1) then sum = log(pi) - log(sin(pi * z)) - sum m = ceiling((2 * z % re - 3) / 4) sum % im = sum % im + 2 * pi * m * sign(1.0_${k1}$, z % im) end if res = cmplx(sum, kind = ${k1}$) end function l_gamma_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:set k2, t2 = REAL_KINDS[-2], REAL_TYPES[-2] impure elemental function l_factorial_${t1[0]}$${k1}$(n) result(res) ! ! Log(n!) ! ${t1}$, intent(in) :: n ${t2}$ :: res ${t1}$, parameter :: zero = 0_${k1}$, one = 1_${k1}$, two = 2_${k1}$ ${t2}$, parameter :: zero_${k2}$ = 0.0_${k2}$, one_${k2}$ = 1.0_${k2}$ if(n < zero) call error_stop("Error(l_factorial): Logarithm of" & //" factorial function argument must be non-negative") select case(n) case (zero) res = zero_${k2}$ case (one) res = zero_${k2}$ case (two : ) res = l_gamma(n + 1, one_${k2}$) end select end function l_factorial_${t1[0]}$${k1}$ #:endfor #! Because the KIND lists are sorted by increasing accuracy, #! gamma will use the next available more accurate KIND for the #! internal more accurate solver. #:for i, k1, t1, i1 in IDX_REAL_KINDS_TYPES[:-1] #:set k2 = REAL_KINDS[i + 1] if k1 == "sp" else REAL_KINDS[-1] #:set t2 = REAL_TYPES[i + 1] impure elemental function gpx_${t1[0]}$${k1}$(p, x) result(res) ! ! Approximation of incomplete gamma G function with real argument p. ! ! Based on Rémy Abergel and Lionel Moisan "Algorithm 1006, Fast and ! Accurate Evaluation of a Generalized Incomplete Gamma Function", ACM ! Transactions on Mathematical Software, March 2020. ! ! Fortran 90 program by Jim-215-Fisher ! ${t1}$, intent(in) :: p, x integer :: n ${t2}$ :: res, p_lim, a, b, g, c, d, y ${t2}$, parameter :: zero = 0.0_${k2}$, one = 1.0_${k2}$ ${t2}$, parameter :: dm = tiny(1.0_${k2}$) * 10 ** 6 ${t1}$, parameter :: zero_k1 = 0.0_${k1}$ if(p <= zero_k1) call error_stop("Error(gpx): Incomplete gamma" & //" function must have a positive parameter p") if(x < -9.0_${k1}$) then p_lim = 5.0_${k1}$ * (sqrt(abs(x)) - 1.0_${k1}$) elseif(x >= -9.0_${k1}$ .and. x <= zero_k1) then p_lim = zero_k1 else p_lim = x endif if(x < zero_k1 .and. p < p_lim .and. abs(anint(p) - p) > tol_${k1}$) & call error_stop("Error(gpx): Incomplete gamma function with " & //"negative x must come with a whole number p not too small") if(x < zero_k1) call error_stop("Error(gpx): Incomplete gamma" & // " function with negative x must have an integer parameter p") if(p >= p_lim) then !use modified Lentz method of continued fraction !for eq. (15) in the above reference. a = one b = p g = a / b c = a / dm d = one / b n = 2 do if(mod(n, 2) == 0) then a = (one - p - n / 2) * x else a = (n / 2) * x end if b = p - one + n d = d * a + b if(d == zero) d = dm c = b + a / c if(c == zero) c = dm d = one / d y = c * d g = g * y n = n + 1 if(abs(y - one) < tol_${k2}$) exit end do else if(x >= zero_k1) then !use modified Lentz method of continued !fraction for eq. (16) in the reference. a = one b = x + one - p g = a / b c = a / dm d = one / b n = 2 do a = (n - 1) * (1 + p - n) b = b + 2 d = d * a + b if(d == zero) d = dm c = b + a / c if(c == zero) c = dm d = one / d y = c * d g = g * y n = n + 1 if(abs(y - one) < tol_${k2}$) exit end do else g = ieee_value(1._${k1}$, ieee_quiet_nan) end if res = g end function gpx_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] impure elemental function gpx_${t1[0]}$${k1}$${k2}$(p, x) result(res) ! ! Approximation of incomplete gamma G function with integer argument p. ! ! Based on Rémy Abergel and Lionel Moisan "Algorithm 1006, Fast and ! Accurate Evaluation of a Generalized Incomplete Gamma Function", ACM ! Transactions on Mathematical Software, March 2020. ! ${t1}$, intent(in) :: p ${t2}$, intent(in) :: x ${t2}$ :: res, p_lim, a, b, g, c, d, y integer :: n ${t2}$, parameter :: zero = 0.0_${k2}$, one = 1.0_${k2}$ ${t2}$, parameter :: dm = tiny(1.0_${k2}$) * 10 ** 6 ${t1}$, parameter :: zero_k1 = 0_${k1}$, two = 2_${k1}$ if(p <= zero_k1) call error_stop("Error(gpx): Incomplete gamma " & //"function must have a positive parameter p") if(x < -9.0_${k2}$) then p_lim = 5.0_${k2}$ * (sqrt(abs(x)) - 1.0_${k2}$) else if(x >= -9.0_${k2}$ .and. x <= zero) then p_lim = zero else p_lim = x end if if(real(p, ${k2}$) >= p_lim) then a = one b = p g = a / b c = a / dm d = one / b n = 2 do if(mod(n, 2) == 0) then a = (one - p - n / 2) * x else a = (n / 2) * x end if b = p - 1 + n d = d * a + b if(d == zero) d = dm c = b + a / c if(c == zero) c = dm d = one / d y = c * d g = g * y n = n + 1 if(abs(y - one) < tol_${k2}$) exit end do else if(x >= zero) then a = one b = x + 1 - p g = a / b c = a / dm d = one / b n = 2 do a = -(n - 1) * (n - 1 - p) b = b + 2 d = d * a + b if(d == zero) d = dm c = b + a / c if(c == zero) c = dm d = one / d y = c * d g = g * y n = n + 1 if(abs(y - one) < tol_${k2}$) exit end do else a = -x c = one / a d = p - 1 b = c * (a - d) n = 1 do c = d * (d - one) / (a * a) d = d - 2 y = c * ( a - d) b = b + y n = n + 1 if(int(n, ${k1}$) > (p - two) / two .or. y < b * tol_${k2}$) exit end do if(y >= b * tol_${k2}$ .and. mod(p, two) /= zero_k1) & b = b + d * c / a g = ((-1) ** p * exp(-a + l_gamma(p, one) - (p - 1) * log(a)) & + b ) / a end if res = g end function gpx_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] impure elemental function ingamma_low_${t1[0]}$${k1}$(p, x) result(res) ! ! Approximation of lower incomplete gamma function with real p. ! ${t1}$, intent(in) :: p, x ${t1}$ :: res, s1, y ${t1}$, parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ if(x == zero) then res = zero else if(x > p) then s1 = log_gamma(p) y = one - exp(-x + p * log(x) - s1) * gpx(p, x) res = exp(s1 + log(y)) else if(x <= p .and. x > zero) then s1 = -x + p * log(x) res = gpx(p, x) * exp(s1) else call error_stop("Error(Logarithm of upper incomplete gamma " & //"function): negative x must be with integer p") end if end function ingamma_low_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] impure elemental function ingamma_low_${t1[0]}$${k1}$${k2}$(p, x) & result(res) ! ! Approximation of lower incomplete gamma function with integer p. ! ${t1}$, intent(in) :: p ${t2}$, intent(in) :: x ${t2}$ :: res, s1, y ${t2}$, parameter :: zero = 0.0_${k2}$, one = 1.0_${k2}$ if(x == zero) then res = zero else if(x > real(p, ${k2}$)) then s1 = l_gamma(p, one) y = one - exp(-x + p * log(x) - s1) * gpx(p, x) res = exp(s1 + log(y)) else if(x <= real(p, ${k2}$) .and. x > zero) then s1 = -x + p * log(x) res = gpx(p, x) * exp(s1) else s1 = -x + p * log(abs(x)) res = gpx(p, x) * exp(s1) res = (-1) ** p * res end if end function ingamma_low_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] impure elemental function l_ingamma_low_${t1[0]}$${k1}$(p, x) result(res) ${t1}$, intent(in) :: p, x ${t1}$ :: res, s1, y ${t1}$, parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ if(x == zero) then res = zero else if(x > p) then s1 = log_gamma(p) y = one - exp(-x + p * log(x) - s1) * gpx(p, x) res = s1 + log(y) else if(x <= p .and. x > zero) then s1 = -x + p * log(abs(x)) res = log(abs(gpx(p, x))) + s1 else call error_stop("Error(Logarithm of upper incomplete gamma " & //"function): negative x must be with integer p") end if end function l_ingamma_low_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] impure elemental function l_ingamma_low_${t1[0]}$${k1}$${k2}$(p, x) & result(res) ${t1}$, intent(in) :: p ${t2}$, intent(in) :: x ${t2}$ :: res, s1, y ${t2}$, parameter :: zero = 0.0_${k2}$, one = 1.0_${k2}$ if(x == zero) then res = zero else if(x > real(p, ${k2}$)) then s1 = l_gamma(p, one) y = one - exp(-x + p * log(x) - s1) * gpx(p, x) res = s1 + log(y) else if(x <= real(p, ${k2}$)) then s1 = -x + p * log(abs(x)) res = log(abs(gpx(p, x))) + s1 end if end function l_ingamma_low_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] impure elemental function ingamma_up_${t1[0]}$${k1}$(p, x) result(res) ! ! Approximation of upper incomplete gamma function with real p. ! ${t1}$, intent(in) :: p, x ${t1}$ :: res, s1, y ${t1}$, parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ if(x == zero) then res = gamma(p) else if(x > p) then s1 = -x + p * log(x) res = gpx(p, x) * exp(s1) else if(x <= p .and. x > zero) then y = log_gamma(p) s1 = -x + p * log(x) - y res = (one - gpx(p, x) * exp(s1)) * exp(y) else call error_stop("Error(Logarithm of upper incomplete gamma " & //"function): negative x must be with integer p") end if end function ingamma_up_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] impure elemental function ingamma_up_${t1[0]}$${k1}$${k2}$(p, x) & result(res) ! ! Approximation of upper incomplete gamma function with integer p. ! ${t1}$, intent(in) :: p ${t2}$, intent(in) :: x ${t2}$ :: res, s1, y ${t2}$, parameter :: zero = 0.0_${k2}$, one = 1.0_${k2}$ if(x == zero) then res = gamma(real(p, ${k2}$)) else if(x > real(p, ${k2}$)) then s1 = -x + p * log(x) res = gpx(p, x) * exp(s1) else if(x <= real(p, ${k2}$) .and. x > zero) then y = l_gamma(p, one) s1 = -x + p * log(x) - y res = gpx(p, x) * exp(s1) res = (one - res) * exp(y) else y = l_gamma(p, one) s1 = -x + p * log(abs(x)) - y res = gpx(p, x) * exp(s1) res = (one - (-1) ** p * res) * exp(y) end if end function ingamma_up_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] impure elemental function l_ingamma_up_${t1[0]}$${k1}$(p, x) result(res) ${t1}$, intent(in) :: p, x ${t1}$ :: res, s1, y ${t1}$, parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ if(x == zero) then res = log_gamma(p) else if(x > p) then s1 = -x + p * log(x) res = log(gpx(p, x)) + s1 else if(x <= p .and. x > zero) then y= log_gamma(p) s1 = -x + p * log(x) - y res = gpx(p, x) * exp(s1) res = log(one - res) + y else call error_stop("Error(Logarithm of upper incomplete gamma " & //"function): negative x must be with integer p") end if end function l_ingamma_up_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] impure elemental function l_ingamma_up_${t1[0]}$${k1}$${k2}$(p, x) & result(res) ${t1}$, intent(in) :: p ${t2}$, intent(in) :: x ${t2}$ :: res, s1, y ${t2}$, parameter :: zero = 0.0_${k2}$, one = 1.0_${k2}$ if(x == zero) then res = l_gamma(p, one) else if(x > real(p, ${k2}$)) then s1 = -x + p * log(x) res = log(gpx(p, x)) + s1 else if(x <= real(p, ${k2}$) .and. x > zero) then y = l_gamma(p, one) s1 = -x + p * log(x) - y res = gpx(p, x) * exp(s1) res = log(one - res) + y else y = l_gamma(p, one) s1 = -x + p * log(abs(x)) + log(gpx(p, x)) res = (-1) ** p * exp(s1) res = log(abs(exp(y) - res)) end if end function l_ingamma_up_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] impure elemental function regamma_p_${t1[0]}$${k1}$(p, x) result(res) ! ! Approximation of regularized incomplete gamma function P(p,x) for real p ! ${t1}$, intent(in) :: p, x ${t1}$ :: res, s1 ${t1}$, parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ if(x < zero) call error_stop("Error(regamma_p): Regularized gamma_p" & //" function is not defined at x < 0") if(x == zero) then res = zero else if(x > p) then s1 = -x + p * log(x) - log_gamma(p) res = one - exp(s1 + log(gpx(p,x))) else if(x <= p) then s1 = -x + p * log(abs(x)) - log_gamma(p) res = exp(log(gpx(p, x)) + s1) end if end function regamma_p_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] impure elemental function regamma_p_${t1[0]}$${k1}$${k2}$(p, x) result(res) ! ! Approximation of regularized incomplete gamma function P(p,x) for integer p ! ${t1}$, intent(in) :: p ${t2}$, intent(in) :: x ${t2}$ :: res, s1 ${t2}$, parameter :: zero = 0.0_${k2}$, one = 1.0_${k2}$ if(x < zero) call error_stop("Error(regamma_p): Regularized gamma_p" & //" function is not defined at x < 0") if(x == zero) then res = zero else if(x > real(p, ${k2}$)) then s1 = -x + p * log(x) - l_gamma(p, one) res = one - exp(s1 + log(gpx(p,x))) else if(x <= real(p, ${k2}$)) then s1 = -x + p * log(abs(x)) - l_gamma(p, one) res = exp(log(gpx(p, x)) + s1) end if end function regamma_p_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor #:for k1, t1 in REAL_KINDS_TYPES[:-1] impure elemental function regamma_q_${t1[0]}$${k1}$(p, x) result(res) ! ! Approximation of regularized incomplete gamma function Q(p,x) for real p ! ${t1}$, intent(in) :: p, x ${t1}$ :: res, s1 ${t1}$, parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ if(x < zero) call error_stop("Error(regamma_p): Regularized gamma_q" & //" function is not defined at x < 0") if(x == zero) then res = one else if(x > p) then s1 = -x + p * log(x) - log_gamma(p) res = exp(s1 + log(gpx(p,x))) else if(x <= p) then s1 = -x + p * log(abs(x)) - log_gamma(p) res = one - exp(log(gpx(p, x)) + s1) end if end function regamma_q_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for k2, t2 in REAL_KINDS_TYPES[:-1] impure elemental function regamma_q_${t1[0]}$${k1}$${k2}$(p, x) result(res) ! ! Approximation of regularized incomplet gamma function Q(p,x) for integer p ! ${t1}$, intent(in) :: p ${t2}$, intent(in) :: x ${t2}$ :: res, s1 ${t2}$, parameter :: zero = 0.0_${k2}$, one = 1.0_${k2}$ if(x < zero) call error_stop("Error(regamma_q): Regularized gamma_q" & //" function is not defined at x < 0") if(x == zero) then res = one else if(x > real(p, ${k2}$)) then s1 = -x + p * log(x) - l_gamma(p, one) res = exp(log(gpx(p,x)) + s1) elseif(x <= real(p, ${k2}$)) then s1 = -x + p * log(abs(x)) - l_gamma(p, one) res = one - exp(s1 + log(gpx(p,x))) end if end function regamma_q_${t1[0]}$${k1}$${k2}$ #:endfor #:endfor end module stdlib_specialfunctions_gamma fortran-lang-stdlib-0ede301/src/specialfunctions/stdlib_specialfunctions_legendre.f900000664000175000017500000000403415135654166031426 0ustar alastairalastairsubmodule (stdlib_specialfunctions) stdlib_specialfunctions_legendre implicit none contains ! derivatives of legegendre polynomials ! unspecified behaviour if n is negative pure elemental module function dlegendre_fp64(n,x) result(dleg) integer, intent(in) :: n real(dp), intent(in) :: x real(dp) :: dleg select case(n) case(0) dleg = 0 case(1) dleg = 1 case default block real(dp) :: leg_down1, leg_down2, leg real(dp) :: dleg_down1, dleg_down2 integer :: i leg_down1 = x dleg_down1 = 1 leg_down2 = 1 dleg_down2 = 0 do i = 2, n leg = (2*i-1)*x*leg_down1/i - (i-1)*leg_down2/i dleg = dleg_down2 + (2*i-1)*leg_down1 leg_down2 = leg_down1 leg_down1 = leg dleg_down2 = dleg_down1 dleg_down1 = dleg end do end block end select end function ! legegendre polynomials ! unspecified behaviour if n is negative pure elemental module function legendre_fp64(n,x) result(leg) integer, intent(in) :: n real(dp), intent(in) :: x real(dp) :: leg select case(n) case(0) leg = 1 case(1) leg = x case default block real(dp) :: leg_down1, leg_down2 integer :: i leg_down1 = x leg_down2 = 1 do i = 2, n leg = (2*i-1)*x*leg_down1/i - (i-1)*leg_down2/i leg_down2 = leg_down1 leg_down1 = leg end do end block end select end function end submodule fortran-lang-stdlib-0ede301/src/specialfunctions/CMakeLists.txt0000664000175000017500000000066315135654166025073 0ustar alastairalastairset(specialfunctions_f90Files stdlib_specialfunctions_legendre.f90 ) set(specialfunctions_fppFiles stdlib_specialfunctions_activations.fypp stdlib_specialfunctions.fypp stdlib_specialfunctions_gamma.fypp ) configure_stdlib_target(${PROJECT_NAME}_specialfunctions specialfunctions_f90Files specialfunctions_fppFiles "") target_link_libraries(${PROJECT_NAME}_specialfunctions PUBLIC ${PROJECT_NAME}_intrinsics) fortran-lang-stdlib-0ede301/src/io/0000775000175000017500000000000015135654166017364 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/io/stdlib_io_npy_load.fypp0000664000175000017500000004506715135654166024135 0ustar alastairalastair! SPDX-Identifier: MIT #:include "common.fypp" #:set RANKS = range(1, MAXRANK + 1) #:set KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES + CMPLX_KINDS_TYPES !> Implementation of loading npy files into multidimensional arrays submodule (stdlib_io_npy) stdlib_io_npy_load use stdlib_error, only : error_stop use stdlib_strings, only : to_string, starts_with implicit none contains #:for k1, t1 in KINDS_TYPES #:for rank in RANKS !> Load a ${rank}$-dimensional array from a npy file module subroutine load_npy_${t1[0]}$${k1}$_${rank}$(filename, array, iostat, iomsg) !> Name of the npy file to load from character(len=*), intent(in) :: filename !> Array to be loaded from the npy file ${t1}$, allocatable, intent(out) :: array${ranksuffix(rank)}$ !> Error status of loading, zero on success integer, intent(out), optional :: iostat !> Associated error message in case of non-zero status code character(len=:), allocatable, intent(out), optional :: iomsg character(len=*), parameter :: vtype = type_${t1[0]}$${k1}$ integer, parameter :: rank = ${rank}$ integer :: io, stat character(len=:), allocatable :: msg open(newunit=io, file=filename, form="unformatted", access="stream", iostat=stat) catch: block character(len=:), allocatable :: this_type integer, allocatable :: vshape(:) call get_descriptor(io, filename, this_type, vshape, stat, msg) if (stat /= 0) exit catch if (this_type /= vtype) then stat = 1 msg = "File '"//filename//"' contains data of type '"//this_type//"', "//& & "but expected '"//vtype//"'" exit catch end if if (size(vshape) /= rank) then stat = 1 msg = "File '"//filename//"' contains data of rank "//& & to_string(size(vshape))//", but expected "//& & to_string(rank) exit catch end if call allocator(array, vshape, stat) if (stat /= 0) then msg = "Failed to allocate array of type '"//vtype//"' "//& & "with total size of "//to_string(product(vshape)) exit catch end if read(io, iostat=stat) array end block catch close(io) if (present(iostat)) then iostat = stat else if (stat /= 0) then if (allocated(msg)) then call error_stop("Failed to read array from file '"//filename//"'"//nl//& & msg) else call error_stop("Failed to read array from file '"//filename//"'") end if end if if (present(iomsg).and.allocated(msg)) call move_alloc(msg, iomsg) contains !> Wrapped intrinsic allocate to create an allocation from a shape array subroutine allocator(array, vshape, stat) !> Instance of the array to be allocated ${t1}$, allocatable, intent(out) :: array${ranksuffix(rank)}$ !> Dimensions to allocate for integer, intent(in) :: vshape(:) !> Status of allocate integer, intent(out) :: stat allocate(array( & #:for i in range(rank-1) & vshape(${i+1}$), & #:endfor & vshape(${rank}$)), & & stat=stat) end subroutine allocator end subroutine load_npy_${t1[0]}$${k1}$_${rank}$ #:endfor #:endfor !> Read the npy header from a binary file and retrieve the descriptor string. subroutine get_descriptor(io, filename, vtype, vshape, stat, msg) !> Unformatted, stream accessed unit integer, intent(in) :: io !> Filename for error reporting character(len=*), intent(in) :: filename !> Type of data saved in npy file character(len=:), allocatable, intent(out) :: vtype !> Shape descriptor of the integer, allocatable, intent(out) :: vshape(:) !> Status of operation integer, intent(out) :: stat !> Associated error message in case of non-zero status character(len=:), allocatable, intent(out) :: msg integer :: major, header_len, i character(len=:), allocatable :: dict character(len=8) :: header character :: buf(4) logical :: fortran_order ! stat should be zero if no error occurred stat = 0 read(io, iostat=stat) header if (stat /= 0) return call parse_header(header, major, stat, msg) if (stat /= 0) return read(io, iostat=stat) buf(1:merge(4, 2, major > 1)) if (stat /= 0) return if (major > 1) then header_len = ichar(buf(1)) & & + ichar(buf(2)) * 256**1 & & + ichar(buf(3)) * 256**2 & & + ichar(buf(4)) * 256**3 else header_len = ichar(buf(1)) & & + ichar(buf(2)) * 256**1 end if allocate(character(header_len) :: dict, stat=stat) if (stat /= 0) return read(io, iostat=stat) dict if (stat /= 0) return if (dict(header_len:header_len) /= nl) then stat = 1 msg = "Descriptor length does not match" return end if if (scan(dict, achar(0)) > 0) then stat = 1 msg = "Nul byte not allowed in descriptor string" return end if call parse_descriptor(trim(dict(:len(dict)-1)), filename, & & vtype, fortran_order, vshape, stat, msg) if (stat /= 0) return if (.not.fortran_order) then vshape = [(vshape(i), i = size(vshape), 1, -1)] end if end subroutine get_descriptor !> Parse the first eight bytes of the npy header to verify the data subroutine parse_header(header, major, stat, msg) !> Header of the binary file character(len=*), intent(in) :: header !> Major version of the npy format integer, intent(out) :: major !> Status of operation integer, intent(out) :: stat !> Associated error message in case of non-zero status character(len=:), allocatable, intent(out) :: msg integer :: minor ! stat should be zero if no error occurred stat = 0 if (header(1:1) /= magic_number) then stat = 1 msg = "Expected z'93' but got z'"//to_string(ichar(header(1:1)))//"' "//& & "as first byte" return end if if (header(2:6) /= magic_string) then stat = 1 msg = "Expected identifier '"//magic_string//"'" return end if major = ichar(header(7:7)) if (.not.any(major == [1, 2, 3])) then stat = 1 msg = "Unsupported format major version number '"//to_string(major)//"'" return end if minor = ichar(header(8:8)) if (minor /= 0) then stat = 1 msg = "Unsupported format version "// & & "'"//to_string(major)//"."//to_string(minor)//"'" return end if end subroutine parse_header !> Parse the descriptor in the npy header. This routine implements a minimal !> non-recursive parser for serialized Python dictionaries. subroutine parse_descriptor(input, filename, vtype, fortran_order, vshape, stat, msg) !> Input string to parse as descriptor character(len=*), intent(in) :: input !> Filename for error reporting character(len=*), intent(in) :: filename !> Type of the data stored, retrieved from field `descr` character(len=:), allocatable, intent(out) :: vtype !> Whether the data is in left layout, retrieved from field `fortran_order` logical, intent(out) :: fortran_order !> Shape of the stored data, retrieved from field `shape` integer, allocatable, intent(out) :: vshape(:) !> Status of operation integer, intent(out) :: stat !> Associated error message in case of non-zero status character(len=:), allocatable, intent(out) :: msg enum, bind(c) enumerator :: invalid, string, lbrace, rbrace, comma, colon, & lparen, rparen, bool, literal, space end enum type :: token_type integer :: first, last, kind end type token_type integer :: pos character(len=:), allocatable :: key type(token_type) :: token, last logical :: has_descr, has_shape, has_fortran_order has_descr = .false. has_shape = .false. has_fortran_order = .false. pos = 0 call next_token(input, pos, token, [lbrace], stat, msg) if (stat /= 0) return last = token_type(pos, pos, comma) do while (pos < len(input)) call get_token(input, pos, token) select case(token%kind) case(space) continue case(comma) if (token%kind == last%kind) then stat = 1 msg = make_message(filename, input, token%first, token%last, & & "Comma cannot appear at this point") return end if last = token case(rbrace) exit case(string) if (token%kind == last%kind) then stat = 1 msg = make_message(filename, input, token%first, token%last, & & "String cannot appear at this point") return end if last = token key = input(token%first+1:token%last-1) call next_token(input, pos, token, [colon], stat, msg) if (stat /= 0) return if (key == "descr" .and. has_descr & & .or. key == "fortran_order" .and. has_fortran_order & & .or. key == "shape" .and. has_shape) then stat = 1 msg = make_message(filename, input, last%first, last%last, & & "Duplicate entry for '"//key//"' found") return end if select case(key) case("descr") call next_token(input, pos, token, [string], stat, msg) if (stat /= 0) return vtype = input(token%first+1:token%last-1) has_descr = .true. case("fortran_order") call next_token(input, pos, token, [bool], stat, msg) if (stat /= 0) return fortran_order = input(token%first:token%last) == "True" has_fortran_order = .true. case("shape") call parse_tuple(input, pos, vshape, stat, msg) has_shape = .true. case default stat = 1 msg = make_message(filename, input, last%first, last%last, & & "Invalid entry '"//key//"' in dictionary encountered") return end select case default stat = 1 msg = make_message(filename, input, token%first, token%last, & & "Invalid token encountered") return end select end do if (.not.has_descr) then stat = 1 msg = make_message(filename, input, 1, pos, & & "Dictionary does not contain required entry 'descr'") end if if (.not.has_shape) then stat = 1 msg = make_message(filename, input, 1, pos, & & "Dictionary does not contain required entry 'shape'") end if if (.not.has_fortran_order) then stat = 1 msg = make_message(filename, input, 1, pos, & & "Dictionary does not contain required entry 'fortran_order'") end if contains function make_message(filename, input, first, last, message) result(str) !> Filename for context character(len=*), intent(in) :: filename !> Input string to parse character(len=*), intent(in) :: input !> Offset in the input integer, intent(in) :: first, last !> Error message character(len=*), intent(in) :: message !> Final output message character(len=:), allocatable :: str character(len=*), parameter :: nl = new_line('a') str = message // nl // & & " --> " // filename // ":1:" // to_string(first) // "-" // to_string(last) // nl // & & " |" // nl // & & "1 | " // input // nl // & & " |" // repeat(" ", first) // repeat("^", last - first + 1) // nl // & & " |" end function make_message !> Parse a tuple of integers into an array of integers subroutine parse_tuple(input, pos, tuple, stat, msg) !> Input string to parse character(len=*), intent(in) :: input !> Offset in the input, will be advanced after reading integer, intent(inout) :: pos !> Array representing tuple of integers integer, allocatable, intent(out) :: tuple(:) !> Status of operation integer, intent(out) :: stat !> Associated error message in case of non-zero status character(len=:), allocatable, intent(out) :: msg type(token_type) :: token integer :: last, itmp allocate(tuple(0), stat=stat) if (stat /= 0) return call next_token(input, pos, token, [lparen], stat, msg) if (stat /= 0) return last = comma do while (pos < len(input)) call get_token(input, pos, token) select case(token%kind) case(space) continue case(literal) if (token%kind == last) then stat = 1 msg = make_message(filename, input, token%first, token%last, & & "Invalid token encountered") return end if last = token%kind read(input(token%first:token%last), *, iostat=stat) itmp if (stat /= 0) then return end if tuple = [tuple, itmp] case(comma) if (token%kind == last) then stat = 1 msg = make_message(filename, input, token%first, token%last, & & "Invalid token encountered") return end if last = token%kind case(rparen) exit case default stat = 1 msg = make_message(filename, input, token%first, token%last, & & "Invalid token encountered") return end select end do end subroutine parse_tuple !> Get the next allowed token subroutine next_token(input, pos, token, allowed_token, stat, msg) !> Input string to parse character(len=*), intent(in) :: input !> Current offset in the input string integer, intent(inout) :: pos !> Last token parsed type(token_type), intent(out) :: token !> Tokens allowed in the current context integer, intent(in) :: allowed_token(:) !> Status of operation integer, intent(out) :: stat !> Associated error message in case of non-zero status character(len=:), allocatable, intent(out) :: msg stat = pos do while (pos < len(input)) call get_token(input, pos, token) if (token%kind == space) then continue else if (any(token%kind == allowed_token)) then stat = 0 exit else stat = 1 msg = make_message(filename, input, token%first, token%last, & & "Invalid token encountered") exit end if end do end subroutine next_token !> Tokenize input string subroutine get_token(input, pos, token) !> Input strin to tokenize character(len=*), intent(in) :: input !> Offset in input string, will be advanced integer, intent(inout) :: pos !> Returned token from the next position type(token_type), intent(out) :: token character :: quote pos = pos + 1 select case(input(pos:pos)) case("""", "'") quote = input(pos:pos) token%first = pos pos = pos + 1 do while (pos <= len(input)) if (input(pos:pos) == quote) then token%last = pos exit else pos = pos + 1 end if end do token%kind = string case("0", "1", "2", "3", "4", "5", "6", "7", "8", "9") token%first = pos do while (pos <= len(input)) if (.not.any(input(pos:pos) == ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"])) then pos = pos - 1 token%last = pos exit else pos = pos + 1 end if end do token%kind = literal case("T") if (starts_with(input(pos:), "True")) then token = token_type(pos, pos+3, bool) pos = pos + 3 else token = token_type(pos, pos, invalid) end if case("F") if (starts_with(input(pos:), "False")) then token = token_type(pos, pos+4, bool) pos = pos + 4 else token = token_type(pos, pos, invalid) end if case("{") token = token_type(pos, pos, lbrace) case("}") token = token_type(pos, pos, rbrace) case(",") token = token_type(pos, pos, comma) case(":") token = token_type(pos, pos, colon) case("(") token = token_type(pos, pos, lparen) case(")") token = token_type(pos, pos, rparen) case(" ", nl) token = token_type(pos, pos, space) case default token = token_type(pos, pos, invalid) end select end subroutine get_token end subroutine parse_descriptor end submodule stdlib_io_npy_load fortran-lang-stdlib-0ede301/src/io/stdlib_io_npy.fypp0000664000175000017500000001172615135654166023131 0ustar alastairalastair! SPDX-Identifer: MIT #:include "common.fypp" #:set RANKS = range(1, MAXRANK + 1) #:set KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES + CMPLX_KINDS_TYPES !> Description of the npy format taken from !> https://numpy.org/doc/stable/reference/generated/numpy.lib.format.html !> !>## Format Version 1.0 !> !> The first 6 bytes are a magic string: exactly \x93NUMPY. !> !> The next 1 byte is an unsigned byte: !> the major version number of the file format, e.g. \x01. !> !> The next 1 byte is an unsigned byte: !> the minor version number of the file format, e.g. \x00. !> Note: the version of the file format is not tied to the version of the numpy package. !> !> The next 2 bytes form a little-endian unsigned short int: !> the length of the header data HEADER_LEN. !> !> The next HEADER_LEN bytes form the header data describing the array’s format. !> It is an ASCII string which contains a Python literal expression of a dictionary. !> It is terminated by a newline (\n) and padded with spaces (\x20) to make the total !> of len(magic string) + 2 + len(length) + HEADER_LEN be evenly divisible by 64 for !> alignment purposes. !> !> The dictionary contains three keys: !> !> - “descr”: dtype.descr !> An object that can be passed as an argument to the numpy.dtype constructor !> to create the array’s dtype. !> !> - “fortran_order”: bool !> Whether the array data is Fortran-contiguous or not. Since Fortran-contiguous !> arrays are a common form of non-C-contiguity, we allow them to be written directly !> to disk for efficiency. !> !> - “shape”: tuple of int !> The shape of the array. !> !> For repeatability and readability, the dictionary keys are sorted in alphabetic order. !> This is for convenience only. A writer SHOULD implement this if possible. A reader MUST !> NOT depend on this. !> !> Following the header comes the array data. If the dtype contains Python objects !> (i.e. dtype.hasobject is True), then the data is a Python pickle of the array. !> Otherwise the data is the contiguous (either C- or Fortran-, depending on fortran_order) !> bytes of the array. Consumers can figure out the number of bytes by multiplying the !> number of elements given by the shape (noting that shape=() means there is 1 element) !> by dtype.itemsize. !> !>## Format Version 2.0 !> !> The version 1.0 format only allowed the array header to have a total size of 65535 bytes. !> This can be exceeded by structured arrays with a large number of columns. !> The version 2.0 format extends the header size to 4 GiB. numpy.save will automatically !> save in 2.0 format if the data requires it, else it will always use the more compatible !> 1.0 format. !> !> The description of the fourth element of the header therefore has become: !> “The next 4 bytes form a little-endian unsigned int: the length of the header data !> HEADER_LEN.” !> !>## Format Version 3.0 !> !> This version replaces the ASCII string (which in practice was latin1) with a !> utf8-encoded string, so supports structured types with any unicode field names. module stdlib_io_npy use stdlib_kinds, only : int8, int16, int32, int64, sp, dp, xdp, qp implicit none private public :: save_npy, load_npy !> Version: experimental !> !> Save multidimensional array in npy format !> ([Specification](../page/specs/stdlib_io.html#save_npy)) interface save_npy #:for k1, t1 in KINDS_TYPES #:for rank in RANKS module subroutine save_npy_${t1[0]}$${k1}$_${rank}$(filename, array, iostat, iomsg) character(len=*), intent(in) :: filename ${t1}$, intent(in) :: array${ranksuffix(rank)}$ integer, intent(out), optional :: iostat character(len=:), allocatable, intent(out), optional :: iomsg end subroutine save_npy_${t1[0]}$${k1}$_${rank}$ #:endfor #:endfor end interface save_npy !> Version: experimental !> !> Load multidimensional array in npy format !> ([Specification](../page/specs/stdlib_io.html#load_npy)) interface load_npy #:for k1, t1 in KINDS_TYPES #:for rank in RANKS module subroutine load_npy_${t1[0]}$${k1}$_${rank}$(filename, array, iostat, iomsg) character(len=*), intent(in) :: filename ${t1}$, allocatable, intent(out) :: array${ranksuffix(rank)}$ integer, intent(out), optional :: iostat character(len=:), allocatable, intent(out), optional :: iomsg end subroutine load_npy_${t1[0]}$${k1}$_${rank}$ #:endfor #:endfor end interface load_npy character(len=*), parameter :: nl = achar(10) character(len=*), parameter :: & type_iint8 = " Default delimiter for loadtxt, savetxt and number_of_columns character(len=1), parameter :: delimiter_default = " " public :: FMT_INT, FMT_REAL_SP, FMT_REAL_DP, FMT_REAL_XDP, FMT_REAL_QP public :: FMT_COMPLEX_SP, FMT_COMPLEX_DP, FMT_COMPLEX_XDP, FMT_COMPLEX_QP !> Version: experimental !> !> Read a whole line from a formatted unit into a string variable interface get_line module procedure :: get_line_char module procedure :: get_line_string module procedure :: get_line_input_char module procedure :: get_line_input_string end interface get_line interface loadtxt !! version: experimental !! !! Loads a 2D array from a text file !! ([Specification](../page/specs/stdlib_io.html#description)) #:for k1, t1 in KINDS_TYPES module procedure loadtxt_${t1[0]}$${k1}$ #:endfor end interface loadtxt interface savetxt !! version: experimental !! !! Saves a 2D array into a text file !! ([Specification](../page/specs/stdlib_io.html#description_2)) #:for k1, t1 in KINDS_TYPES module procedure savetxt_${t1[0]}$${k1}$ #:endfor end interface contains #:for k1, t1 in KINDS_TYPES subroutine loadtxt_${t1[0]}$${k1}$(filename, d, skiprows, max_rows, fmt, delimiter) !! version: experimental !! !! Loads a 2D array from a text file. !! !! Arguments !! --------- !! !! Filename to load the array from character(len=*), intent(in) :: filename !! The array 'd' will be automatically allocated with the correct dimensions ${t1}$, allocatable, intent(out) :: d(:,:) !! Skip the first `skiprows` lines. If skipping more rows than present, a 0-sized array will be returned. The default is 0. integer, intent(in), optional :: skiprows !! Read `max_rows` lines of content after `skiprows` lines. !! A negative value results in reading all lines. !! A value of zero results in no lines to be read. !! The default value is -1. integer, intent(in), optional :: max_rows character(len=*), intent(in), optional :: fmt character(len=1), intent(in), optional :: delimiter character(len=:), allocatable :: fmt_ character(len=1) :: delimiter_ !! !! Example !! ------- !! !!```fortran !! ${t1}$, allocatable :: data(:, :) !! call loadtxt("log.txt", data) ! 'data' will be automatically allocated !!``` !! !! Where 'log.txt' contains for example:: !! !! 1 2 3 !! 2 4 6 !! 8 9 10 !! 11 12 13 !! ... !! integer :: s integer :: nrow, ncol, i, j, ios, skiprows_, max_rows_, istart, iend character(len=:), allocatable :: line, iomsg_ character(len=1024) :: iomsg, msgout skiprows_ = max(optval(skiprows, 0), 0) max_rows_ = optval(max_rows, -1) delimiter_ = optval(delimiter, delimiter_default) s = open(filename) ! determine number or rows nrow = number_of_rows(s) skiprows_ = min(skiprows_, nrow) if ( max_rows_ < 0 .or. max_rows_ > (nrow - skiprows_) ) max_rows_ = nrow - skiprows_ ! determine number of columns ncol = 0 if ( skiprows_ < nrow ) ncol = number_of_columns(s, skiprows=skiprows_, delimiter=delimiter_) #:if 'complex' in t1 ncol = ncol / 2 #:endif allocate(d(max_rows_, ncol)) if (max_rows_ == 0 .or. ncol == 0) return do i = 1, skiprows_ read(s, *, iostat=ios, iomsg=iomsg) if (ios/=0) then write(msgout,1) trim(iomsg),i,trim(filename) 1 format('loadtxt: error <',a,'> skipping line ',i0,' of ',a,'.') call error_stop(msg=trim(msgout)) end if end do ! Default to format used for savetxt if fmt not specified. #:if 'real' in t1 fmt_ = optval(fmt, "(*"//FMT_REAL_${k1}$(1:len(FMT_REAL_${k1}$)-1)//",:,1x))") #:elif 'complex' in t1 fmt_ = optval(fmt, "(*"//FMT_COMPLEX_${k1}$(1:len(FMT_COMPLEX_${k1}$)-1)//",:,1x))") #:else fmt_ = optval(fmt, "*") #:endif if ( fmt_ == '*' ) then ! Use list directed read if user has specified fmt='*' if (is_blank(delimiter_) .or. delimiter_ == ",") then do i = 1, max_rows_ read (s,*,iostat=ios,iomsg=iomsg) d(i, :) if (ios/=0) then write(msgout,2) trim(iomsg),size(d,2),i,trim(filename) call error_stop(msg=trim(msgout)) end if enddo ! Otherwise read each value separately else do i = 1, max_rows_ call get_line(s, line, ios, iomsg_) if (ios/=0) then write(msgout,2) trim(iomsg_),size(d,2),i,trim(filename) call error_stop(msg=trim(msgout)) end if istart = 0 do j = 1, ncol - 1 iend = index(line(istart+1:), delimiter_) read (line(istart+1:istart+iend-1),*,iostat=ios,iomsg=iomsg) d(i, j) if (ios/=0) then write(msgout,2) trim(iomsg),size(d,2),i,trim(filename) call error_stop(msg=trim(msgout)) end if istart = istart + iend end do read (line(istart+1:),*,iostat=ios,iomsg=iomsg) d(i, ncol) if (ios/=0) then write(msgout,2) trim(iomsg),size(d,2),i,trim(filename) call error_stop(msg=trim(msgout)) end if enddo end if else ! Otherwise pass default or user specified fmt string. do i = 1, max_rows_ read (s,fmt_,iostat=ios,iomsg=iomsg) d(i, :) if (ios/=0) then write(msgout,2) trim(iomsg),size(d,2),i,trim(filename) call error_stop(msg=trim(msgout)) end if enddo endif close(s) 2 format('loadtxt: error <',a,'> reading ',i0,' values from line ',i0,' of ',a,'.') end subroutine loadtxt_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in KINDS_TYPES subroutine savetxt_${t1[0]}$${k1}$(filename, d, delimiter) !! version: experimental !! !! Saves a 2D array into a text file. !! !! Arguments !! --------- !! character(len=*), intent(in) :: filename ! File to save the array to ${t1}$, intent(in) :: d(:,:) ! The 2D array to save character(len=1), intent(in), optional :: delimiter ! Column delimiter. Default is a space. !! !! Example !! ------- !! !!```fortran !! ${t1}$ :: data(3, 2) !! call savetxt("log.txt", data) !!``` !! integer :: s, i, ios character(len=1) :: delimiter_ character(len=3) :: delim_str character(len=:), allocatable :: fmt_ character(len=1024) :: iomsg, msgout delimiter_ = optval(delimiter, delimiter_default) delim_str = "'"//delimiter_//"'" #:if 'real' in t1 fmt_ = "(*"//FMT_REAL_${k1}$(1:len(FMT_REAL_${k1}$)-1)//",:,"//delim_str//"))" #:elif 'complex' in t1 fmt_ = "(*"//FMT_COMPLEX_${k1}$(1:11)//delim_str//FMT_COMPLEX_${k1}$(14:23)//",:,"//delim_str//"))" #:elif 'integer' in t1 fmt_ = "(*"//FMT_INT(1:len(FMT_INT)-1)//",:,"//delim_str//"))" #:endif s = open(filename, "w") do i = 1, size(d, 1) #:if 'real' in t1 or 'complex' in t1 or 'integer' in t1 write(s, fmt_, & #:else write(s, *, & #:endif iostat=ios,iomsg=iomsg) d(i, :) if (ios/=0) then write(msgout,1) trim(iomsg),size(d,2),i,trim(filename) call error_stop(msg=trim(msgout)) end if end do close(s) 1 format('savetxt: error <',a,'> writing ',i0,' values to line ',i0,' of ',a,'.') end subroutine savetxt_${t1[0]}$${k1}$ #:endfor integer function number_of_columns(s, skiprows, delimiter) !! version: experimental !! !! determine number of columns integer,intent(in) :: s integer, intent(in), optional :: skiprows character(len=1), intent(in), optional :: delimiter integer :: ios, skiprows_, i character :: c character(len=:), allocatable :: line character(len=1) :: delimiter_ logical :: last_delim skiprows_ = optval(skiprows, 0) delimiter_ = optval(delimiter, delimiter_default) rewind(s) do i = 1, skiprows_ read(s, *) end do number_of_columns = 0 ! Read first non-skipped line as a whole call get_line(s, line, ios) if (ios/=0 .or. .not.allocated(line)) return last_delim = .true. if (delimiter_ == delimiter_default) then do i = 1,len(line) c = line(i:i) if (last_delim .and. .not. is_blank(c)) number_of_columns = number_of_columns + 1 last_delim = is_blank(c) end do else do i = 1,len(line) if (line(i:i) == delimiter_) number_of_columns = number_of_columns + 1 end do if (number_of_columns == 0) then if (len_trim(line) /= 0) number_of_columns = 1 else number_of_columns = number_of_columns + 1 end if end if rewind(s) end function number_of_columns integer function number_of_rows(s) result(nrows) !! version: experimental !! !! Determine the number or rows in a file integer, intent(in)::s integer :: ios rewind(s) nrows = 0 do read(s, *, iostat=ios) if (ios /= 0) exit nrows = nrows + 1 end do rewind(s) end function number_of_rows integer function open(filename, mode, iostat) result(u) !! version: experimental !! !! Opens a file !! ([Specification](../page/specs/stdlib_io.html#description_1)) !! !!##### Behavior !! !! !! To open a file to read: !! !!```fortran !! u = open("somefile.txt") ! The default `mode` is "rt" !! u = open("somefile.txt", "r") !!``` !! !! To open a file to write: !! !!```fortran !! u = open("somefile.txt", "w") !!``` !! !! To append to the end of the file if it exists: !! !!```fortran !! u = open("somefile.txt", "a") !!``` character(*), intent(in) :: filename character(*), intent(in), optional :: mode integer, intent(out), optional :: iostat character(3) :: mode_ character(:),allocatable :: action_, position_, status_, access_, form_ mode_ = parse_mode(optval(mode, "")) select case (mode_(1:2)) case('r') action_='read' position_='asis' status_='old' case('w') action_='write' position_='asis' status_='replace' case('a') action_='write' position_='append' status_='old' case('x') action_='write' position_='asis' status_='new' case('r+') action_='readwrite' position_='asis' status_='old' case('w+') action_='readwrite' position_='asis' status_='replace' case('a+') action_='readwrite' position_='append' status_='old' case('x+') action_='readwrite' position_='asis' status_='new' case default call error_stop("Unsupported mode: "//mode_(1:2)) end select select case (mode_(3:3)) case('t') form_='formatted' access_='sequential' case('b') form_='unformatted' access_ = 'stream' case default call error_stop("Unsupported mode: "//mode_(3:3)) end select if (present(iostat)) then open(newunit=u, file=filename, & action = action_, position = position_, status = status_, & access = access_, form = form_, & iostat = iostat) else open(newunit=u, file=filename, & action = action_, position = position_, status = status_, & access = access_, form = form_) end if end function open character(3) function parse_mode(mode) result(mode_) character(*), intent(in) :: mode integer :: i character(:),allocatable :: a logical :: lfirst(3) mode_ = 'r t' if (len_trim(mode) == 0) return a=trim(adjustl(mode)) lfirst = .true. do i=1,len(a) if (lfirst(1) & .and. (a(i:i) == 'r' .or. a(i:i) == 'w' .or. a(i:i) == 'a' .or. a(i:i) == 'x') & ) then mode_(1:1) = a(i:i) lfirst(1)=.false. else if (lfirst(2) .and. a(i:i) == '+') then mode_(2:2) = a(i:i) lfirst(2)=.false. else if (lfirst(3) .and. (a(i:i) == 't' .or. a(i:i) == 'b')) then mode_(3:3) = a(i:i) lfirst(3)=.false. else if (a(i:i) == ' ') then cycle else if(any(.not.lfirst)) then call error_stop("Wrong mode: "//trim(a)) else call error_stop("Wrong character: "//a(i:i)) endif end do end function parse_mode !> Version: experimental !> !> Read a whole line from a formatted unit into a deferred length character variable subroutine get_line_char(unit, line, iostat, iomsg) !> Formatted IO unit integer, intent(in) :: unit !> Line to read character(len=:), allocatable, intent(out) :: line !> Status of operation integer, intent(out), optional :: iostat !> Error message character(len=:), allocatable, optional :: iomsg integer, parameter :: bufsize = 4096 character(len=bufsize) :: buffer, msg integer :: chunk, stat logical :: opened if (unit /= -1) then inquire(unit=unit, opened=opened) else opened = .false. end if if (opened) then open(unit=unit, pad="yes", iostat=stat, iomsg=msg) else stat = 1 msg = "Unit is not connected" end if line = "" do while (stat == 0) read(unit, '(a)', advance='no', iostat=stat, iomsg=msg, size=chunk) buffer if (stat > 0) exit line = line // buffer(:chunk) end do if (is_iostat_eor(stat)) stat = 0 if (stat /= 0 .and. present(iomsg)) iomsg = trim(msg) if (present(iostat)) then iostat = stat else if (stat /= 0) then call error_stop(trim(msg)) end if end subroutine get_line_char !> Version: experimental !> !> Read a whole line from a formatted unit into a string variable subroutine get_line_string(unit, line, iostat, iomsg) !> Formatted IO unit integer, intent(in) :: unit !> Line to read type(string_type), intent(out) :: line !> Status of operation integer, intent(out), optional :: iostat !> Error message character(len=:), allocatable, optional :: iomsg character(len=:), allocatable :: buffer call get_line(unit, buffer, iostat, iomsg) line = string_type(buffer) end subroutine get_line_string !> Version: experimental !> !> Read a whole line from the standard input into a deferred length character variable subroutine get_line_input_char(line, iostat, iomsg) !> Line to read character(len=:), allocatable, intent(out) :: line !> Status of operation integer, intent(out), optional :: iostat !> Error message character(len=:), allocatable, optional :: iomsg call get_line(input_unit, line, iostat, iomsg) end subroutine get_line_input_char !> Version: experimental !> !> Read a whole line from the standard input into a string variable subroutine get_line_input_string(line, iostat, iomsg) !> Line to read type(string_type), intent(out) :: line !> Status of operation integer, intent(out), optional :: iostat !> Error message character(len=:), allocatable, optional :: iomsg call get_line(input_unit, line, iostat, iomsg) end subroutine get_line_input_string !> Version: experimental !> !> Reads a whole ASCII file and loads its contents into a string variable. !> The function handles error states and optionally deletes the file after reading. subroutine get_file_string(filename,file,err,delete) !> Input file name character(*), intent(in) :: filename !> Output string variable type(string_type), intent(out) :: file !> [optional] State return flag. On error, if not requested, the code will stop. type(state_type), optional, intent(out) :: err !> [optional] Delete file after reading? Default: do not delete logical, optional, intent(in) :: delete ! Local variables character(len=:), allocatable :: filestring ! Process output call get_file_char(filename,filestring,err,delete) call move(from=fileString,to=file) end subroutine get_file_string !> Version: experimental !> !> Reads a whole ASCII file and loads its contents into an allocatable `character` variable. !> The function handles error states and optionally deletes the file after reading. subroutine get_file_char(filename,file,err,delete) !> Input file name character(*), intent(in) :: filename !> Output string variable character(len=:), allocatable, intent(out) :: file !> [optional] State return flag. On error, if not requested, the code will stop. type(state_type), optional, intent(out) :: err !> [optional] Delete file after reading? Default: do not delete logical, optional, intent(in) :: delete ! Local variables type(state_type) :: err0 character(len=512) :: iomsg integer :: lun,iostat integer(int64) :: errpos,file_size logical :: is_present,want_deleted !> Check if the file should be deleted after reading if (present(delete)) then want_deleted = delete else want_deleted = .false. end if !> Check file existing inquire(file=filename, exist=is_present) if (.not.is_present) then allocate(character(len=0) :: file) err0 = state_type('get_file',STDLIB_IO_ERROR,'File not present:',filename) call err0%handle(err) return end if !> Retrieve file size inquire(file=filename,size=file_size) invalid_size: if (file_size<0) then allocate(character(len=0) :: file) err0 = state_type('get_file',STDLIB_IO_ERROR,filename,'has invalid size=',file_size) call err0%handle(err) return endif invalid_size ! Read file open(newunit=lun,file=filename, & form='unformatted',action='read',access='stream',status='old', & iostat=iostat,iomsg=iomsg) if (iostat/=0) then allocate(character(len=0) :: file) err0 = state_type('get_file',STDLIB_IO_ERROR,'Cannot open',filename,'for read:',iomsg) call err0%handle(err) return end if allocate(character(len=file_size) :: file) read_data: if (file_size>0) then read(lun, pos=1, iostat=iostat, iomsg=iomsg) file ! Read error if (iostat/=0) then inquire(unit=lun,pos=errpos) err0 = state_type('get_file',STDLIB_IO_ERROR,iomsg,'(',filename,'at byte',errpos,')') call err0%handle(err) return endif end if read_data if (want_deleted) then close(lun,iostat=iostat,status='delete') if (iostat/=0) err0 = state_type('get_file',STDLIB_IO_ERROR,'Cannot delete',filename,'after reading') else close(lun,iostat=iostat) if (iostat/=0) err0 = state_type('get_file',STDLIB_IO_ERROR,'Cannot close',filename,'after reading') endif ! Process output call err0%handle(err) end subroutine get_file_char end module stdlib_io fortran-lang-stdlib-0ede301/src/io/stdlib_io_npy_save.fypp0000664000175000017500000001104315135654166024137 0ustar alastairalastair! SPDX-Identifer: MIT #:include "common.fypp" #:set RANKS = range(1, MAXRANK + 1) #:set KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES + CMPLX_KINDS_TYPES !> Implementation of saving multidimensional arrays to npy files submodule (stdlib_io_npy) stdlib_io_npy_save use stdlib_error, only : error_stop use stdlib_strings, only : to_string implicit none contains !> Generate magic header string for npy format pure function magic_header(major, minor) result(str) !> Major version of npy format integer, intent(in) :: major !> Minor version of npy format integer, intent(in) :: minor !> Magic string for npy format character(len=8) :: str str = magic_number // magic_string // achar(major) // achar(minor) end function magic_header !> Generate header for npy format pure function npy_header(vtype, vshape) result(str) !> Type of variable character(len=*), intent(in) :: vtype !> Shape of variable integer, intent(in) :: vshape(:) !> Header string for npy format character(len=:), allocatable :: str integer, parameter :: len_v10 = 8 + 2, len_v20 = 8 + 4, block_size = 64 str = & "{'descr': '"//vtype//& "', 'fortran_order': True, 'shape': "//& shape_str(vshape)//", }" if (len(str) + len_v10 >= 65535) then str = str // & & repeat(" ", block_size - mod(len(str) + len_v20 + 1, block_size)) // nl str = magic_header(2, 0) // to_bytes_i4(int(len(str))) // str else str = str // & & repeat(" ", block_size - mod(len(str) + len_v10 + 1, block_size)) // nl str = magic_header(1, 0) // to_bytes_i2(int(len(str))) // str end if end function npy_header !> Write integer as byte string in little endian encoding pure function to_bytes_i4(val) result(str) !> Integer value to convert to bytes integer, intent(in) :: val !> String of bytes character(len=4) :: str str = achar(mod(val, 256**1)) // & & achar(mod(val, 256**2) / 256**1) // & & achar(mod(val, 256**3) / 256**2) // & & achar(val / 256**3) end function to_bytes_i4 !> Write integer as byte string in little endian encoding, 2-byte truncated version pure function to_bytes_i2(val) result(str) !> Integer value to convert to bytes integer, intent(in) :: val !> String of bytes character(len=2) :: str str = achar(mod(val, 2**8)) // & & achar(mod(val, 2**16) / 2**8) end function to_bytes_i2 !> Print array shape as tuple of int pure function shape_str(vshape) result(str) !> Shape of variable integer, intent(in) :: vshape(:) !> Shape string for npy format character(len=:), allocatable :: str integer :: i str = "(" do i = 1, size(vshape) str = str//to_string(vshape(i))//", " enddo str = str//")" end function shape_str #:for k1, t1 in KINDS_TYPES #:for rank in RANKS !> Save ${rank}$-dimensional array in npy format module subroutine save_npy_${t1[0]}$${k1}$_${rank}$(filename, array, iostat, iomsg) !> Name of the npy file to load from character(len=*), intent(in) :: filename !> Array to be loaded from the npy file ${t1}$, intent(in) :: array${ranksuffix(rank)}$ !> Error status of loading, zero on success integer, intent(out), optional :: iostat !> Associated error message in case of non-zero status code character(len=:), allocatable, intent(out), optional :: iomsg character(len=*), parameter :: vtype = type_${t1[0]}$${k1}$ integer :: io, stat open(newunit=io, file=filename, form="unformatted", access="stream", iostat=stat) if (stat == 0) then write(io, iostat=stat) npy_header(vtype, shape(array)) end if if (stat == 0) then write(io, iostat=stat) array end if close(io, iostat=stat) if (present(iostat)) then iostat = stat else if (stat /= 0) then call error_stop("Failed to write array to file '"//filename//"'") end if if (present(iomsg)) then if (stat /= 0) then iomsg = "Failed to write array to file '"//filename//"'" end if end if end subroutine save_npy_${t1[0]}$${k1}$_${rank}$ #:endfor #:endfor end submodule stdlib_io_npy_save fortran-lang-stdlib-0ede301/src/selection/0000775000175000017500000000000015135654166020742 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/selection/CMakeLists.txt0000664000175000017500000000045615135654166023507 0ustar alastairalastairset(selection_fppFiles stdlib_selection.fypp ) set(selection_cppFiles ) set(selection_f90Files ) configure_stdlib_target(${PROJECT_NAME}_selection selection_f90Files selection_fppFiles selection_cppFiles) target_link_libraries(${PROJECT_NAME}_selection PUBLIC ${PROJECT_NAME}_core) fortran-lang-stdlib-0ede301/src/selection/stdlib_selection.fypp0000664000175000017500000002602215135654166025172 0ustar alastairalastair#:include "common.fypp" ! Specify kinds/types for the input array in select and arg_select #:set ARRAY_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES ! The index arrays are of all INT_KINDS_TYPES module stdlib_selection !! Quickly find the k-th smallest value of an array, or the index of the k-th smallest value. !! ([Specification](../page/specs/stdlib_selection.html)) ! ! This code was modified from the "Coretran" implementation "quickSelect" by ! Leon Foks, https://github.com/leonfoks/coretran/tree/HEAD/src/sorting ! ! Leon Foks gave permission to release this code under stdlib's MIT license. ! (https://github.com/fortran-lang/stdlib/pull/500#commitcomment-57418593) ! use stdlib_kinds implicit none private public :: select, arg_select interface select !! version: experimental !! ([Specification](..//page/specs/stdlib_selection.html#select-find-the-k-th-smallest-value-in-an-input-array)) #:for arraykind, arraytype in ARRAY_KINDS_TYPES #:for intkind, inttype in INT_KINDS_TYPES #:set name = rname("select", 1, arraytype, arraykind, intkind) module procedure ${name}$ #:endfor #:endfor end interface interface arg_select !! version: experimental !! ([Specification](..//page/specs/stdlib_selection.html#arg_select-find-the-index-of-the-k-th-smallest-value-in-an-input-array)) #:for arraykind, arraytype in ARRAY_KINDS_TYPES #:for intkind, inttype in INT_KINDS_TYPES #:set name = rname("arg_select", 1, arraytype, arraykind, intkind) module procedure ${name}$ #:endfor #:endfor end interface contains #:for arraykind, arraytype in ARRAY_KINDS_TYPES #:for intkind, inttype in INT_KINDS_TYPES #:set name = rname("select", 1, arraytype, arraykind, intkind) subroutine ${name}$(a, k, kth_smallest, left, right) !! select - select the k-th smallest entry in a(:). !! !! Partly derived from the "Coretran" implementation of !! quickSelect by Leon Foks, https://github.com/leonfoks/coretran !! ${arraytype}$, intent(inout) :: a(:) !! Array in which we seek the k-th smallest entry. !! On output it will be partially sorted such that !! `all(a(1:(k-1)) <= a(k)) .and. all(a(k) <= a((k+1):size(a)))` !! is true. ${inttype}$, intent(in) :: k !! We want the k-th smallest entry. E.G. `k=1` leads to !! `kth_smallest=min(a)`, and `k=size(a)` leads to !! `kth_smallest=max(a)` ${arraytype}$, intent(out) :: kth_smallest !! On output contains the k-th smallest value of `a(:)` ${inttype}$, intent(in), optional :: left, right !! If we know that: !! the k-th smallest entry of `a` is in `a(left:right)` !! and also that: !! `maxval(a(1:(left-1))) <= minval(a(left:right))` !! and: !! `maxval(a(left:right))) <= minval(a((right+1):size(a)))` !! then one or both bounds can be specified to narrow the search. !! The constraints are available if we have previously called the !! subroutine with different `k` (because of how `a(:)` becomes !! partially sorted, see documentation for `a(:)`). ${inttype}$ :: l, r, mid, iPivot integer, parameter :: ip = ${intkind}$ l = 1_ip if(present(left)) l = left r = size(a, kind=ip) if(present(right)) r = right if(l > r .or. l < 1_ip .or. r > size(a, kind=ip) & .or. k < l .or. k > r & !i.e. if k is not in the interval [l; r] ) then error stop "select must have 1 <= left <= k <= right <= size(a)"; end if searchk: do mid = l + ((r-l)/2_ip) ! Avoid (l+r)/2 which can cause overflow call medianOf3(a, l, mid, r) call swap(a(l), a(mid)) call partition(a, l, r, iPivot) if (iPivot < k) then l = iPivot + 1_ip elseif (iPivot > k) then r = iPivot - 1_ip elseif (iPivot == k) then kth_smallest = a(k) return end if end do searchk contains pure subroutine swap(a, b) ${arraytype}$, intent(inout) :: a, b ${arraytype}$ :: tmp tmp = a; a = b; b = tmp end subroutine pure subroutine medianOf3(a, left, mid, right) ${arraytype}$, intent(inout) :: a(:) ${inttype}$, intent(in) :: left, mid, right if(a(right) < a(left)) call swap(a(right), a(left)) if(a(mid) < a(left)) call swap(a(mid) , a(left)) if(a(right) < a(mid) ) call swap(a(mid) , a(right)) end subroutine pure subroutine partition(array,left,right,iPivot) ${arraytype}$, intent(inout) :: array(:) ${inttype}$, intent(in) :: left, right ${inttype}$, intent(out) :: iPivot ${inttype}$ :: lo,hi ${arraytype}$ :: pivot pivot = array(left) lo = left hi=right do while (lo <= hi) do while (array(hi) > pivot) hi=hi-1_ip end do inner_lohi: do while (lo <= hi ) if(array(lo) > pivot) exit inner_lohi lo=lo+1_ip end do inner_lohi if (lo <= hi) then call swap(array(lo),array(hi)) lo=lo+1_ip hi=hi-1_ip end if end do call swap(array(left),array(hi)) iPivot=hi end subroutine end subroutine #:endfor #:endfor #:for arraykind, arraytype in ARRAY_KINDS_TYPES #:for intkind, inttype in INT_KINDS_TYPES #:set name = rname("arg_select", 1, arraytype, arraykind, intkind) subroutine ${name}$(a, indx, k, kth_smallest, left, right) !! arg_select - find the index of the k-th smallest entry in `a(:)` !! !! Partly derived from the "Coretran" implementation of !! quickSelect by Leon Foks, https://github.com/leonfoks/coretran !! ${arraytype}$, intent(in) :: a(:) !! Array in which we seek the k-th smallest entry. ${inttype}$, intent(inout) :: indx(:) !! Array of indices into `a(:)`. Must contain each integer !! from `1:size(a)` exactly once. On output it will be partially !! sorted such that !! `all( a(indx(1:(k-1)))) <= a(indx(k)) ) .AND. !! all( a(indx(k)) <= a(indx( (k+1):size(a) )) )`. ${inttype}$, intent(in) :: k !! We want index of the k-th smallest entry. E.G. `k=1` leads to !! `a(kth_smallest) = min(a)`, and `k=size(a)` leads to !! `a(kth_smallest) = max(a)` ${inttype}$, intent(out) :: kth_smallest !! On output contains the index with the k-th smallest value of `a(:)` ${inttype}$, intent(in), optional :: left, right !! If we know that: !! the k-th smallest entry of `a` is in `a(indx(left:right))` !! and also that: !! `maxval(a(indx(1:(left-1)))) <= minval(a(indx(left:right)))` !! and: !! `maxval(a(indx(left:right))) <= minval(a(indx((right+1):size(a))))` !! then one or both bounds can be specified to reduce the search !! time. These constraints are available if we have previously !! called the subroutine with a different `k` (due to the way that !! `indx(:)` becomes partially sorted, see documentation for `indx(:)`). ${inttype}$ :: l, r, mid, iPivot integer, parameter :: ip = ${intkind}$ l = 1_ip if(present(left)) l = left r = size(a, kind=ip) if(present(right)) r = right if(size(a) /= size(indx)) then error stop "arg_select must have size(a) == size(indx)" end if if(l > r .or. l < 1_ip .or. r > size(a, kind=ip) & .or. k < l .or. k > r & !i.e. if k is not in the interval [l; r] ) then error stop "arg_select must have 1 <= left <= k <= right <= size(a)"; end if searchk: do mid = l + ((r-l)/2_ip) ! Avoid (l+r)/2 which can cause overflow call arg_medianOf3(a, indx, l, mid, r) call swap(indx(l), indx(mid)) call arg_partition(a, indx, l, r, iPivot) if (iPivot < k) then l = iPivot + 1_ip elseif (iPivot > k) then r = iPivot - 1_ip elseif (iPivot == k) then kth_smallest = indx(k) return end if end do searchk contains pure subroutine swap(a, b) ${inttype}$, intent(inout) :: a, b ${inttype}$ :: tmp tmp = a; a = b; b = tmp end subroutine pure subroutine arg_medianOf3(a, indx, left, mid, right) ${arraytype}$, intent(in) :: a(:) ${inttype}$, intent(inout) :: indx(:) ${inttype}$, intent(in) :: left, mid, right if(a(indx(right)) < a(indx(left))) call swap(indx(right), indx(left)) if(a(indx(mid)) < a(indx(left))) call swap(indx(mid) , indx(left)) if(a(indx(right)) < a(indx(mid)) ) call swap(indx(mid) , indx(right)) end subroutine pure subroutine arg_partition(array, indx, left,right,iPivot) ${arraytype}$, intent(in) :: array(:) ${inttype}$, intent(inout) :: indx(:) ${inttype}$, intent(in) :: left, right ${inttype}$, intent(out) :: iPivot ${inttype}$ :: lo,hi ${arraytype}$ :: pivot pivot = array(indx(left)) lo = left hi = right do while (lo <= hi) do while (array(indx(hi)) > pivot) hi=hi-1_ip end do inner_lohi: do while (lo <= hi ) if(array(indx(lo)) > pivot) exit inner_lohi lo=lo+1_ip end do inner_lohi if (lo <= hi) then call swap(indx(lo),indx(hi)) lo=lo+1_ip hi=hi-1_ip end if end do call swap(indx(left),indx(hi)) iPivot=hi end subroutine end subroutine #:endfor #:endfor end module fortran-lang-stdlib-0ede301/src/specialmatrices/0000775000175000017500000000000015135654166022125 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/specialmatrices/CMakeLists.txt0000664000175000017500000000077715135654166024700 0ustar alastairalastairset(specialmatrices_fppFiles stdlib_specialmatrices.fypp stdlib_specialmatrices_tridiagonal.fypp ) set(specialmatrices_cppFiles ) set(specialmatrices_f90Files ) configure_stdlib_target(${PROJECT_NAME}_specialmatrices specialmatrices_f90Files specialmatrices_fppFiles specialmatrices_cppFiles) target_link_libraries(${PROJECT_NAME}_specialmatrices PUBLIC ${PROJECT_NAME}_constants ${PROJECT_NAME}_linalg_core ${PROJECT_NAME}_linalg ${PROJECT_NAME}_lapack ${PROJECT_NAME}_lapack_extended) fortran-lang-stdlib-0ede301/src/specialmatrices/stdlib_specialmatrices.fypp0000664000175000017500000002466715135654166027555 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(1, 2+1) #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set KINDS_TYPES = R_KINDS_TYPES+C_KINDS_TYPES module stdlib_specialmatrices !! Provides derived-types and associated specialized linear algebra drivers !! for highly-structured matrices commonly encountered in the discretization !! of partial differential equations, as well as control and signal processing !! applications. ([Specifications](../page/specs/stdlib_specialmatrices.html)) use stdlib_linalg_constants use stdlib_constants use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR use stdlib_lapack_extended_base implicit none private public :: tridiagonal public :: spmv public :: dense, transpose, hermitian public :: operator(*), operator(+), operator(-) !-------------------------------------- !----- ------ !----- TYPE DEFINITIONS ------ !----- ------ !-------------------------------------- !--> Tridiagonal matrices #:for k1, t1, s1 in (KINDS_TYPES) type, public :: tridiagonal_${s1}$_type !! Base type to define a `tridiagonal` matrix. private ${t1}$, allocatable :: dl(:), dv(:), du(:) integer(ilp) :: n end type #:endfor !-------------------------------- !----- ----- !----- CONSTRUCTORS ----- !----- ----- !-------------------------------- interface tridiagonal !! ([Specifications](../page/specs/stdlib_specialmatrices.html#Tridiagonal)) This !! interface provides different methods to construct a `tridiagonal` matrix. Only !! the non-zero elements of \( A \) are stored, i.e. !! !! \[ !! A !! = !! \begin{bmatrix} !! a_1 & b_1 \\ !! c_1 & a_2 & b_2 \\ !! & \ddots & \ddots & \ddots \\ !! & & c_{n-2} & a_{n-1} & b_{n-1} \\ !! & & & c_{n-1} & a_n !! \end{bmatrix}. !! \] !! !! #### Syntax !! !! - Construct a real `tridiagonal` matrix from rank-1 arrays: !! !! ```fortran !! integer, parameter :: n !! real(dp), allocatable :: dl(:), dv(:), du(:) !! type(tridiagonal_rdp_type) :: A !! integer :: i !! !! dl = [(i, i=1, n-1)]; dv = [(2*i, i=1, n)]; du = [(3*i, i=1, n)] !! A = Tridiagonal(dl, dv, du) !! ``` !! !! - Construct a real `tridiagonal` matrix with constant diagonals: !! !! ```fortran !! integer, parameter :: n !! real(dp), parameter :: a = 1.0_dp, b = 1.0_dp, c = 2.0_dp !! type(tridiagonal_rdp_type) :: A !! !! A = Tridiagonal(a, b, c, n) !! ``` #:for k1, t1, s1 in (KINDS_TYPES) pure module function initialize_tridiagonal_pure_${s1}$(dl, dv, du) result(A) !! Construct a `tridiagonal` matrix from the rank-1 arrays !! `dl`, `dv` and `du`. ${t1}$, intent(in) :: dl(:), dv(:), du(:) !! Tridiagonal matrix elements. type(tridiagonal_${s1}$_type) :: A !! Corresponding Tridiagonal matrix. end function pure module function initialize_constant_tridiagonal_pure_${s1}$(dl, dv, du, n) result(A) !! Construct a `tridiagonal` matrix with constant elements. ${t1}$, intent(in) :: dl, dv, du !! Tridiagonal matrix elements. integer(ilp), intent(in) :: n !! Matrix dimension. type(tridiagonal_${s1}$_type) :: A !! Corresponding Tridiagonal matrix. end function module function initialize_tridiagonal_impure_${s1}$(dl, dv, du, err) result(A) !! Construct a `tridiagonal` matrix from the rank-1 arrays !! `dl`, `dv` and `du`. ${t1}$, intent(in) :: dl(:), dv(:), du(:) !! Tridiagonal matrix elements. type(linalg_state_type), intent(out) :: err !! Error handling. type(tridiagonal_${s1}$_type) :: A !! Corresponding Tridiagonal matrix. end function module function initialize_constant_tridiagonal_impure_${s1}$(dl, dv, du, n, err) result(A) !! Construct a `tridiagonal` matrix with constant elements. ${t1}$, intent(in) :: dl, dv, du !! Tridiagonal matrix elements. integer(ilp), intent(in) :: n !! Matrix dimension. type(linalg_state_type), intent(out) :: err !! Error handling. type(tridiagonal_${s1}$_type) :: A !! Corresponding Tridiagonal matrix. end function #:endfor end interface !---------------------------------- !----- ----- !----- LINEAR ALGEBRA ----- !----- ----- !---------------------------------- interface spmv !! ([Specifications](../page/specs/stdlib_specialmatrices.html#spmv)) This !! interface provides methods to compute the matrix-vector product !! !! $$ y = \alpha \mathrm{op}(A) x + \beta y$$ !! !! for the different matrix types defined by `stdlib_specialmatrices`. #:for k1, t1, s1 in (KINDS_TYPES) #:for rank in RANKS module subroutine spmv_tridiag_${rank}$d_${s1}$(A, x, y, alpha, beta, op) type(tridiagonal_${s1}$_type), intent(in) :: A ${t1}$, intent(in), contiguous, target :: x${ranksuffix(rank)}$ ${t1}$, intent(inout), contiguous, target :: y${ranksuffix(rank)}$ ${t1}$, intent(in), optional :: alpha ${t1}$, intent(in), optional :: beta character(1), intent(in), optional :: op end subroutine #:endfor #:endfor end interface !------------------------------------- !----- ----- !----- UTILITY FUNCTIONS ----- !----- ----- !------------------------------------- interface dense !! This interface provides methods to convert a matrix of one of the !! types defined by `stdlib_specialmatrices` to a standard rank-2 array. !! ([Specifications](../page/specs/stdlib_specialmatrices.html#dense)) #:for k1, t1, s1 in (KINDS_TYPES) pure module function tridiagonal_to_dense_${s1}$(A) result(B) !! Convert a `tridiagonal` matrix to its dense representation. type(tridiagonal_${s1}$_type), intent(in) :: A !! Input Tridiagonal matrix. ${t1}$, allocatable :: B(:, :) !! Corresponding dense matrix. end function #:endfor end interface interface transpose !! This interface provides methods to compute the transpose operation for !! the different matrix types defined by `stdlib_specialmatrices`. !! [Specifications](../page/specs/stdlib_specialmatrices.html#transpose) #:for k1, t1, s1 in (KINDS_TYPES) pure module function transpose_tridiagonal_${s1}$(A) result(B) type(tridiagonal_${s1}$_type), intent(in) :: A !! Input matrix. type(tridiagonal_${s1}$_type) :: B end function #:endfor end interface interface hermitian !! This interface provides methods to compute the hermitian operation for !! the different matrix types defined by `stdlib_specialmatrices`. For !! real-valued matrices, this is equivalent to the standard `transpose`. !! [Specifications](../page/specs/stdlib_specialmatrices.html#hermitian) #:for k1, t1, s1 in (KINDS_TYPES) pure module function hermitian_tridiagonal_${s1}$(A) result(B) type(tridiagonal_${s1}$_type), intent(in) :: A !! Input matrix. type(tridiagonal_${s1}$_type) :: B end function #:endfor end interface !---------------------------------------- !----- ----- !----- ARITHMETIC OPERATORS ----- !----- ----- !---------------------------------------- interface operator(*) !! Overload the `*` for scalar-matrix multiplications for the different matrix !! types provided by `stdlib_specialmatrices`. !! [Specifications](../page/specs/stdlib_specialmatrices.html#operators) #:for k1, t1, s1 in (KINDS_TYPES) pure module function scalar_multiplication_tridiagonal_${s1}$(alpha, A) result(B) ${t1}$, intent(in) :: alpha type(tridiagonal_${s1}$_type), intent(in) :: A type(tridiagonal_${s1}$_type) :: B end function pure module function scalar_multiplication_bis_tridiagonal_${s1}$(A, alpha) result(B) type(tridiagonal_${s1}$_type), intent(in) :: A ${t1}$, intent(in) :: alpha type(tridiagonal_${s1}$_type) :: B end function #:endfor end interface interface operator(+) !! Overload the `+` operator for matrix-matrix addition. The two matrices need to !! be of the same type and kind. !! [Specifications](../page/specs/stdlib_specialmatrices.html#operators) #:for k1, t1, s1 in (KINDS_TYPES) pure module function matrix_add_tridiagonal_${s1}$(A, B) result(C) type(tridiagonal_${s1}$_type), intent(in) :: A type(tridiagonal_${s1}$_type), intent(in) :: B type(tridiagonal_${s1}$_type) :: C end function #:endfor end interface interface operator(-) !! Overload the `-` operator for matrix-matrix subtraction. The two matrices need to !! be of the same type and kind. !! [Specifications](../page/specs/stdlib_specialmatrices.html#operators) #:for k1, t1, s1 in (KINDS_TYPES) pure module function matrix_sub_tridiagonal_${s1}$(A, B) result(C) type(tridiagonal_${s1}$_type), intent(in) :: A type(tridiagonal_${s1}$_type), intent(in) :: B type(tridiagonal_${s1}$_type) :: C end function #:endfor end interface end module stdlib_specialmatrices fortran-lang-stdlib-0ede301/src/specialmatrices/stdlib_specialmatrices_tridiagonal.fypp0000664000175000017500000002624315135654166032122 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(1, 2+1) #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set KINDS_TYPES = R_KINDS_TYPES+C_KINDS_TYPES submodule (stdlib_specialmatrices) tridiagonal_matrices use stdlib_linalg_lapack, only: lagtm character(len=*), parameter :: this = "tridiagonal matrices" contains !-------------------------------- !----- ----- !----- CONSTRUCTORS ----- !----- ----- !-------------------------------- #:for k1, t1, s1 in (KINDS_TYPES) pure module function initialize_tridiagonal_pure_${s1}$(dl, dv, du) result(A) !! Construct a `tridiagonal` matrix from the rank-1 arrays !! `dl`, `dv` and `du`. ${t1}$, intent(in) :: dl(:), dv(:), du(:) !! tridiagonal matrix elements. type(tridiagonal_${s1}$_type) :: A !! Corresponding tridiagonal matrix. ! Internal variables. integer(ilp) :: n type(linalg_state_type) :: err0 ! Sanity check. n = size(dv, kind=ilp) if (n <= 0) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, "Matrix size needs to be positive, n = ", n, ".") call linalg_error_handling(err0) endif if (size(dl, kind=ilp) /= n-1) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, "Vector dl does not have the correct length.") call linalg_error_handling(err0) endif if (size(du, kind=ilp) /= n-1) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, "Vector du does not have the correct length.") call linalg_error_handling(err0) endif ! Description of the matrix. A%n = n ! Matrix elements. A%dl = dl ; A%dv = dv ; A%du = du end function pure module function initialize_constant_tridiagonal_pure_${s1}$(dl, dv, du, n) result(A) !! Construct a `tridiagonal` matrix with constant elements. ${t1}$, intent(in) :: dl, dv, du !! tridiagonal matrix elements. integer(ilp), intent(in) :: n !! Matrix dimension. type(tridiagonal_${s1}$_type) :: A !! Corresponding tridiagonal matrix. ! Internal variables. integer(ilp) :: i type(linalg_state_type) :: err0 ! Description of the matrix. A%n = n if (n <= 0) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, "Matrix size needs to be positive, n = ", n, ".") call linalg_error_handling(err0) endif ! Matrix elements. allocate( A%dl(n-1), source = dl ) allocate( A%dv(n), source= dv ) allocate( A%du(n-1), source = du ) end function module function initialize_tridiagonal_impure_${s1}$(dl, dv, du, err) result(A) !! Construct a `tridiagonal` matrix from the rank-1 arrays !! `dl`, `dv` and `du`. ${t1}$, intent(in) :: dl(:), dv(:), du(:) !! tridiagonal matrix elements. type(linalg_state_type), intent(out) :: err !! Error handling. type(tridiagonal_${s1}$_type) :: A !! Corresponding tridiagonal matrix. ! Internal variables. integer(ilp) :: n type(linalg_state_type) :: err0 ! Sanity check. n = size(dv, kind=ilp) if (n <= 0) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, "Matrix size needs to be positive, n = ", n, ".") call linalg_error_handling(err0, err) endif if (size(dl, kind=ilp) /= n-1) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, "Vector dl does not have the correct length.") call linalg_error_handling(err0, err) endif if (size(du, kind=ilp) /= n-1) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, "Vector du does not have the correct length.") call linalg_error_handling(err0, err) endif if(err0%ok()) then ! Description of the matrix. A%n = n ! Matrix elements. A%dl = dl ; A%dv = dv ; A%du = du endif end function module function initialize_constant_tridiagonal_impure_${s1}$(dl, dv, du, n, err) result(A) !! Construct a `tridiagonal` matrix with constant elements. ${t1}$, intent(in) :: dl, dv, du !! tridiagonal matrix elements. integer(ilp), intent(in) :: n !! Matrix dimension. type(linalg_state_type), intent(out) :: err !! Error handling type(tridiagonal_${s1}$_type) :: A !! Corresponding tridiagonal matrix. ! Internal variables. integer(ilp) :: i type(linalg_state_type) :: err0 if (n <= 0) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, "Matrix size needs to be positive, n = ", n, ".") call linalg_error_handling(err0, err) endif if(err0%ok()) then ! Description of the matrix. A%n = n ! Matrix elements. allocate( A%dl(n-1), source = dl ) allocate( A%dv(n), source= dv ) allocate( A%du(n-1), source = du ) endif end function #:endfor !----------------------------------------- !----- ----- !----- MATRIX-VECTOR PRODUCT ----- !----- ----- !----------------------------------------- !! spmv_tridiag #:for k1, t1, s1 in (KINDS_TYPES) #:for rank in RANKS module subroutine spmv_tridiag_${rank}$d_${s1}$(A, x, y, alpha, beta, op) type(tridiagonal_${s1}$_type), intent(in) :: A ${t1}$, intent(in), contiguous, target :: x${ranksuffix(rank)}$ ${t1}$, intent(inout), contiguous, target :: y${ranksuffix(rank)}$ ${t1}$, intent(in), optional :: alpha ${t1}$, intent(in), optional :: beta character(1), intent(in), optional :: op ! Internal variables. ${t1}$ :: alpha_, beta_ integer(ilp) :: n, nrhs, ldx, ldy character(1) :: op_ #:if t1.startswith('real') logical :: is_alpha_special, is_beta_special #:endif #:if rank == 1 ${t1}$, pointer :: xmat(:, :), ymat(:, :) #:endif ! Deal with optional arguments. alpha_ = 1.0_${k1}$ ; if (present(alpha)) alpha_ = alpha beta_ = 0.0_${k1}$ ; if (present(beta)) beta_ = beta op_ = "N" ; if (present(op)) op_ = op #:if t1.startswith('real') is_alpha_special = (alpha_ == 1.0_${k1}$ .or. alpha_ == 0.0_${k1}$ .or. alpha_ == -1.0_${k1}$) is_beta_special = (beta_ == 1.0_${k1}$ .or. beta_ == 0.0_${k1}$ .or. beta_ == -1.0_${k1}$) #:endif ! Prepare Lapack arguments. n = A%n ; ldx = n ; ldy = n ; nrhs = #{if rank==1}# 1 #{else}# size(x, dim=2, kind=ilp) #{endif}# #:if rank == 1 ! Pointer trick. xmat(1:n, 1:nrhs) => x ; ymat(1:n, 1:nrhs) => y #:if t1.startswith('complex') call glagtm(op_, n, nrhs, alpha_, A%dl, A%dv, A%du, xmat, ldx, beta_, ymat, ldy) #:else if(is_alpha_special .and. is_beta_special) then call lagtm(op_, n, nrhs, alpha_, A%dl, A%dv, A%du, xmat, ldx, beta_, ymat, ldy) else call glagtm(op_, n, nrhs, alpha_, A%dl, A%dv, A%du, xmat, ldx, beta_, ymat, ldy) end if #:endif #:else #:if t1.startswith('complex') call glagtm(op_, n, nrhs, alpha_, A%dl, A%dv, A%du, x, ldx, beta_, y, ldy) #:else if(is_alpha_special .and. is_beta_special) then call lagtm(op_, n, nrhs, alpha_, A%dl, A%dv, A%du, x, ldx, beta_, y, ldy) else call glagtm(op_, n, nrhs, alpha_, A%dl, A%dv, A%du, x, ldx, beta_, y, ldy) end if #:endif #:endif end subroutine #:endfor #:endfor !------------------------------------- !----- ----- !----- UTILITY FUNCTIONS ----- !----- ----- !------------------------------------- #:for k1, t1, s1 in (KINDS_TYPES) pure module function tridiagonal_to_dense_${s1}$(A) result(B) !! Convert a `tridiagonal` matrix to its dense representation. type(tridiagonal_${s1}$_type), intent(in) :: A !! Input tridiagonal matrix. ${t1}$, allocatable :: B(:, :) !! Corresponding dense matrix. ! Internal variables. integer(ilp) :: i associate (n => A%n) #:if t1.startswith('complex') allocate(B(n, n), source=zero_c${k1}$) #:else allocate(B(n, n), source=zero_${k1}$) #:endif B(1, 1) = A%dv(1) ; B(1, 2) = A%du(1) do concurrent (i=2:n-1) B(i, i-1) = A%dl(i-1) B(i, i) = A%dv(i) B(i, i+1) = A%du(i) enddo B(n, n-1) = A%dl(n-1) ; B(n, n) = A%dv(n) end associate end function #:endfor #:for k1, t1, s1 in (KINDS_TYPES) pure module function transpose_tridiagonal_${s1}$(A) result(B) type(tridiagonal_${s1}$_type), intent(in) :: A !! Input matrix. type(tridiagonal_${s1}$_type) :: B B = tridiagonal(A%du, A%dv, A%dl) end function #:endfor #:for k1, t1, s1 in (KINDS_TYPES) pure module function hermitian_tridiagonal_${s1}$(A) result(B) type(tridiagonal_${s1}$_type), intent(in) :: A !! Input matrix. type(tridiagonal_${s1}$_type) :: B #:if t1.startswith("complex") B = tridiagonal(conjg(A%du), conjg(A%dv), conjg(A%dl)) #:else B = tridiagonal(A%du, A%dv, A%dl) #:endif end function #:endfor #:for k1, t1, s1 in (KINDS_TYPES) pure module function scalar_multiplication_tridiagonal_${s1}$(alpha, A) result(B) ${t1}$, intent(in) :: alpha type(tridiagonal_${s1}$_type), intent(in) :: A type(tridiagonal_${s1}$_type) :: B B = tridiagonal(A%dl, A%dv, A%du) B%dl = alpha*B%dl; B%dv = alpha*B%dv; B%du = alpha*B%du end function pure module function scalar_multiplication_bis_tridiagonal_${s1}$(A, alpha) result(B) type(tridiagonal_${s1}$_type), intent(in) :: A ${t1}$, intent(in) :: alpha type(tridiagonal_${s1}$_type) :: B B = tridiagonal(A%dl, A%dv, A%du) B%dl = alpha*B%dl; B%dv = alpha*B%dv; B%du = alpha*B%du end function #:endfor #:for k1, t1, s1 in (KINDS_TYPES) pure module function matrix_add_tridiagonal_${s1}$(A, B) result(C) type(tridiagonal_${s1}$_type), intent(in) :: A type(tridiagonal_${s1}$_type), intent(in) :: B type(tridiagonal_${s1}$_type) :: C C = tridiagonal(A%dl, A%dv, A%du) C%dl = C%dl + B%dl; C%dv = C%dv + B%dv; C%du = C%du + B%du end function pure module function matrix_sub_tridiagonal_${s1}$(A, B) result(C) type(tridiagonal_${s1}$_type), intent(in) :: A type(tridiagonal_${s1}$_type), intent(in) :: B type(tridiagonal_${s1}$_type) :: C C = tridiagonal(A%dl, A%dv, A%du) C%dl = C%dl - B%dl; C%dv = C%dv - B%dv; C%du = C%du - B%du end function #:endfor end submodule fortran-lang-stdlib-0ede301/src/math/0000775000175000017500000000000015135654166017706 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/math/stdlib_math_logspace.fypp0000664000175000017500000000631215135654166024757 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_math) stdlib_math_logspace implicit none contains #!========================================================= #!= logspace(start, end) = #!========================================================= #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("logspace", 1, t1, k1, "default") module procedure ${RName}$ res = logspace(start, end, DEFAULT_LOGSPACE_LENGTH, real(DEFAULT_LOGSPACE_BASE, ${k1}$)) end procedure #:endfor #! Integer support #:set RName = rname("logspace", 1, "integer(int32)", "int32", "default") module procedure ${RName}$ res = logspace(start, end, DEFAULT_LOGSPACE_LENGTH, DEFAULT_LOGSPACE_BASE) end procedure #!========================================================= #!= logspace(start, end, n) = #!========================================================= #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("logspace", 1, t1, k1, "n") module procedure ${RName}$ res = logspace(start, end, n, real(DEFAULT_LOGSPACE_BASE, ${k1}$)) end procedure #:endfor #! Integer support #:set RName = rname("logspace", 1, "integer(int32)", "int32", "n") module procedure ${RName}$ res = logspace(start, end, n, DEFAULT_LOGSPACE_BASE) end procedure #!========================================================= #!= logspace(start, end, n, base) = #!========================================================= #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("logspace", 1, t1, k1, "n_rbase") module procedure ${RName}$ ${t1}$ :: exponents(max(n, 0)) exponents = linspace(start, end, n) res = base ** exponents end procedure #:set RName = rname("logspace", 1, t1, k1, "n_cbase") module procedure ${RName}$ ${t1}$ :: exponents(max(n, 0)) exponents = linspace(start, end, n) res = base ** exponents end procedure #:set RName = rname("logspace", 1, t1, k1, "n_ibase") module procedure ${RName}$ ${t1}$ :: exponents(max(n, 0)) exponents = linspace(start, end, n) res = base ** exponents end procedure #:endfor #! Integer support: ! Generate logarithmically spaced sequence from ${k1}$ base to the powers ! of ${k1}$ start and end. [base^start, ... , base^end] ! RName = ${RName}$ #:for k1 in REAL_KINDS #:set RName = rname("logspace", 1, "integer(int32)", "int32", "n_r" + str(k1) + "base") module procedure ${RName}$ integer :: exponents(max(n, 0)) exponents = linspace(start, end, n) res = base ** exponents end procedure #:set RName = rname("logspace", 1, "integer(int32)", "int32", "n_c" + str(k1) + "base") module procedure ${RName}$ integer :: exponents(max(n, 0)) exponents = linspace(start, end, n) res = base ** exponents end procedure #:endfor #:set RName = rname("logspace", 1, "integer(int32)", "int32", "n_ibase") module procedure ${RName}$ integer :: exponents(max(n, 0)) exponents = linspace(start, end, n) res = base ** exponents end procedure end submodule fortran-lang-stdlib-0ede301/src/math/stdlib_math_all_close.fypp0000664000175000017500000000134215135654166025115 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(1, MAXRANK + 1) #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_math) stdlib_math_all_close implicit none contains #:for k1, t1 in RC_KINDS_TYPES #:for r1 in RANKS logical pure module function all_close_${r1}$_${t1[0]}$${k1}$(a, b, rel_tol, abs_tol, equal_nan) result(close) ${t1}$, intent(in) :: a${ranksuffix(r1)}$, b${ranksuffix(r1)}$ real(${k1}$), intent(in), optional :: rel_tol, abs_tol logical, intent(in), optional :: equal_nan close = all(is_close(a, b, rel_tol, abs_tol, equal_nan)) end function all_close_${r1}$_${t1[0]}$${k1}$ #:endfor #:endfor end submodule stdlib_math_all_closefortran-lang-stdlib-0ede301/src/math/stdlib_math_arange.fypp0000664000175000017500000000331615135654166024420 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_math) stdlib_math_arange contains #:for k1, t1 in REAL_KINDS_TYPES !> `arange` creates a vector of the `${t1}$` type !> with evenly spaced values within a given interval. pure module function arange_${t1[0]}$_${k1}$(start, end, step) result(result) ${t1}$, intent(in) :: start ${t1}$, intent(in), optional :: end, step ${t1}$, allocatable :: result(:) ${t1}$ :: start_, end_, step_ integer :: i start_ = merge(start, 1.0_${k1}$, present(end)) end_ = optval(end, start) step_ = optval(step, 1.0_${k1}$) step_ = sign(merge(step_, 1.0_${k1}$, step_ /= 0.0_${k1}$), end_ - start_) allocate(result(floor((end_ - start_)/step_) + 1)) result = [(start_ + (i - 1)*step_, i=1, size(result), 1)] end function arange_${t1[0]}$_${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES !> `arange` creates a vector of the `${t1}$` type !> with evenly spaced values within a given interval. pure module function arange_${t1[0]}$_${k1}$(start, end, step) result(result) ${t1}$, intent(in) :: start ${t1}$, intent(in), optional :: end, step ${t1}$, allocatable :: result(:) ${t1}$ :: start_, end_, step_ ${t1}$ :: i start_ = merge(start, 1_${k1}$, present(end)) end_ = optval(end, start) step_ = optval(step, 1_${k1}$) step_ = sign(merge(step_, 1_${k1}$, step_ /= 0_${k1}$), end_ - start_) allocate(result((end_ - start_)/step_ + 1_${k1}$)) result = [(i, i=start_, end_, step_)] end function arange_${t1[0]}$_${k1}$ #:endfor end submodule stdlib_math_arange fortran-lang-stdlib-0ede301/src/math/stdlib_math_linspace.fypp0000664000175000017500000000463715135654166024770 0ustar alastairalastair#:include "common.fypp" submodule (stdlib_math) stdlib_math_linspace implicit none contains #:for k1, t1 in REAL_KINDS_TYPES #:set RName = rname("linspace_default", 1, t1, k1) pure module function ${RName}$(start, end) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end ${t1}$ :: res(DEFAULT_LINSPACE_LENGTH) res = linspace(start, end, DEFAULT_LINSPACE_LENGTH) end function ${RName}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES #:set RName = rname("linspace_n", 1, t1, k1) pure module function ${RName}$(start, end, n) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end integer, intent(in) :: n ${t1}$ :: res(max(n, 0)) integer :: i ! Looping index ${t1}$ :: interval ! Difference between adjacent elements if(n <= 0) return ! If passed length is less than or equal to 0, return an empty (allocated with length 0) array if(n == 1) then res(1) = end return end if interval = (end - start) / real((n - 1), ${k1}$) res(1) = start res(n) = end do i = 2, n - 1 res(i) = real((i-1), ${k1}$) * interval + start end do end function ${RName}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES #:set RName = rname("linspace_default", 1, t1, k1) module procedure ${RName}$ res = linspace(start, end, DEFAULT_LINSPACE_LENGTH) end procedure ${RName}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES #:set RName = rname("linspace_n", 1, t1, k1) module procedure ${RName}$ real(${k1}$) :: x(max(n, 0)) ! array of the real part of complex number real(${k1}$) :: y(max(n, 0)) ! array of the imaginary part of the complex number x = linspace(start%re, end%re, n) y = linspace(start%im, end%im, n) res = cmplx(x, y, kind=${k1}$) end procedure ${RName}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:set RName = rname("linspace_default", 1, t1, k1) module procedure ${RName}$ res = linspace(real(start, kind=dp), real(end, kind=dp), DEFAULT_LINSPACE_LENGTH) end procedure ${RName}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:set RName = rname("linspace_n", 1, t1, k1) module procedure ${RName}$ res = linspace(real(start, kind=dp), real(end, kind=dp), n) end procedure ${RName}$ #:endfor end submodule fortran-lang-stdlib-0ede301/src/math/CMakeLists.txt0000664000175000017500000000105315135654166022445 0ustar alastairalastairset(math_fppFiles stdlib_math_all_close.fypp stdlib_math_arange.fypp stdlib_math_diff.fypp stdlib_math_is_close.fypp stdlib_math_linspace.fypp stdlib_math_logspace.fypp stdlib_math_meshgrid.fypp ) set(math_cppFiles stdlib_math.fypp ) configure_stdlib_target(${PROJECT_NAME}_math "" math_fppFiles math_cppFiles) if(STDLIB_BITSETS) target_link_libraries(${PROJECT_NAME}_math PUBLIC ${PROJECT_NAME}_bitsets) endif() target_link_libraries(${PROJECT_NAME}_math PUBLIC ${PROJECT_NAME}_core ${PROJECT_NAME}_strings) fortran-lang-stdlib-0ede301/src/math/stdlib_math_is_close.fypp0000664000175000017500000000320415135654166024757 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_math) stdlib_math_is_close use, intrinsic :: ieee_arithmetic, only: ieee_is_nan implicit none #:for k1 in REAL_KINDS real(${k1}$), parameter :: sqrt_eps_${k1}$ = sqrt(epsilon(1.0_${k1}$)) #:endfor contains #! Determines whether the values of `a` and `b` are close. #:for k1, t1 in REAL_KINDS_TYPES elemental module logical function is_close_${t1[0]}$${k1}$(a, b, rel_tol, abs_tol, equal_nan) result(close) ${t1}$, intent(in) :: a, b real(${k1}$), intent(in), optional :: rel_tol, abs_tol logical, intent(in), optional :: equal_nan logical :: equal_nan_ equal_nan_ = optval(equal_nan, .false.) if (ieee_is_nan(a) .or. ieee_is_nan(b)) then close = equal_nan_ .and. ieee_is_nan(a) .and. ieee_is_nan(b) else close = abs(a - b) <= max( abs(optval(rel_tol, sqrt_eps_${k1}$)*max(abs(a), abs(b))), & abs(optval(abs_tol, 0.0_${k1}$)) ) end if end function is_close_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES elemental module logical function is_close_${t1[0]}$${k1}$(a, b, rel_tol, abs_tol, equal_nan) result(close) ${t1}$, intent(in) :: a, b real(${k1}$), intent(in), optional :: rel_tol, abs_tol logical, intent(in), optional :: equal_nan close = is_close_r${k1}$(a%re, b%re, rel_tol, abs_tol, equal_nan) .and. & is_close_r${k1}$(a%im, b%im, rel_tol, abs_tol, equal_nan) end function is_close_${t1[0]}$${k1}$ #:endfor end submodule stdlib_math_is_close fortran-lang-stdlib-0ede301/src/math/stdlib_math_meshgrid.fypp0000664000175000017500000000242115135654166024761 0ustar alastairalastair#:include "common.fypp" #:set IR_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES #:set RANKS = range(1, MAXRANK + 1) #:def meshgrid_loop(indices) #:for j in reversed(indices) do i${j}$ = 1, size(x${j}$) #:endfor #:for j in indices xm${j}$(${",".join(f"i{j}" for j in indices)}$) = & x${j}$(i${j}$) #:endfor #:for j in indices end do #:endfor #:enddef submodule(stdlib_math) stdlib_math_meshgrid use stdlib_error, only: error_stop contains #:for k1, t1 in IR_KINDS_TYPES #:for rank in RANKS #:if rank == 1 #:set XY_INDICES = [1] #:set IJ_INDICES = [1] #:else #:set XY_INDICES = [2, 1] + [j for j in range(3, rank + 1)] #:set IJ_INDICES = [1, 2] + [j for j in range(3, rank + 1)] #:endif #: set RName = rname("meshgrid", rank, t1, k1) module procedure ${RName}$ integer :: ${",".join(f"i{j}" for j in range(1, rank + 1))}$ select case (optval(indexing, stdlib_meshgrid_xy)) case (stdlib_meshgrid_xy) $:meshgrid_loop(XY_INDICES) case (stdlib_meshgrid_ij) $:meshgrid_loop(IJ_INDICES) case default call error_stop("ERROR (meshgrid): unexpected indexing.") end select end procedure #:endfor #:endfor end submodule fortran-lang-stdlib-0ede301/src/math/stdlib_math.fypp0000664000175000017500000005110315135654166023100 0ustar alastairalastair#include "macros.inc" #:include "common.fypp" #:set IR_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES module stdlib_math use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp use stdlib_optval, only: optval #if STDLIB_BITSETS use stdlib_bitsets, only: bitset_64, bitset_large #endif implicit none private public :: clip, swap, gcd, linspace, logspace public :: EULERS_NUMBER_SP, EULERS_NUMBER_DP #:if WITH_QP public :: EULERS_NUMBER_QP #:endif public :: DEFAULT_LINSPACE_LENGTH, DEFAULT_LOGSPACE_BASE, DEFAULT_LOGSPACE_LENGTH public :: stdlib_meshgrid_ij, stdlib_meshgrid_xy public :: arange, arg, argd, argpi, deg2rad, rad2deg, is_close, all_close, diff, meshgrid integer, parameter :: DEFAULT_LINSPACE_LENGTH = 100 integer, parameter :: DEFAULT_LOGSPACE_LENGTH = 50 integer, parameter :: DEFAULT_LOGSPACE_BASE = 10 ! Useful constants for lnspace real(sp), parameter :: EULERS_NUMBER_SP = exp(1.0_sp) real(dp), parameter :: EULERS_NUMBER_DP = exp(1.0_dp) #:if WITH_QP real(qp), parameter :: EULERS_NUMBER_QP = exp(1.0_qp) #:endif !> Useful constants `PI` for `argd/argpi` #:for k1 in REAL_KINDS real(kind=${k1}$), parameter :: PI_${k1}$ = acos(-1.0_${k1}$) #:endfor !> Values for optional argument `indexing` of `meshgrid` integer, parameter :: stdlib_meshgrid_xy = 0, stdlib_meshgrid_ij = 1 interface clip #:for k1, t1 in IR_KINDS_TYPES module procedure clip_${k1}$ #:endfor end interface clip !> Swap the values of the lhs and rhs arguments !> ([Specification](../page/specs/stdlib_math.html#swap_subroutine)) !> !> Version: experimental interface swap #:for k1, t1, a1, cpp1 in INT_KINDS_TYPES + REAL_KINDS_TYPES + BITSETS_KINDS_TYPES #:block generate_cpp(cpp_var=cpp1) module procedure :: swap_${k1}$ #:endblock #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES module procedure :: swap_c${k1}$ #:endfor module procedure :: swap_bool module procedure :: swap_str module procedure :: swap_stt end interface !> Returns the greatest common divisor of two integers !> ([Specification](../page/specs/stdlib_math.html#gcd)) !> !> Version: experimental interface gcd #:for k1, t1 in INT_KINDS_TYPES module procedure gcd_${k1}$ #:endfor end interface gcd interface linspace !! Version: Experimental !! !! Create rank 1 array of linearly spaced elements !! If the number of elements is not specified, create an array with size 100. If n is a negative value, !! return an array with size 0. If n = 1, return an array whose only element is end !!([Specification](../page/specs/stdlib_math.html#linspace-create-a-linearly-spaced-rank-one-array)) #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("linspace_default", 1, t1, k1) pure module function ${RName}$(start, end) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end ${t1}$ :: res(DEFAULT_LINSPACE_LENGTH) end function ${RName}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("linspace_n", 1, t1, k1) pure module function ${RName}$(start, end, n) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end integer, intent(in) :: n ${t1}$ :: res(max(n, 0)) end function ${RName}$ #:endfor ! Add support for integer linspace !! !! When dealing with integers as the `start` and `end` parameters, the return type is always a `real(dp)`. #:for k1, t1 in INT_KINDS_TYPES #:set RName = rname("linspace_default", 1, t1, k1) #! The interface for INT_KINDS_TYPES cannot be combined with RC_KINDS_TYPES #! because the output for integer types is always a real with dp. pure module function ${RName}$(start, end) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end real(dp) :: res(DEFAULT_LINSPACE_LENGTH) end function ${RName}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:set RName = rname("linspace_n", 1, t1, k1) pure module function ${RName}$(start, end, n) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end integer, intent(in) :: n real(dp) :: res(max(n, 0)) end function ${RName}$ #:endfor end interface interface logspace !! Version: Experimental !! !! Create rank 1 array of logarithmically spaced elements from base**start to base**end. !! If the number of elements is not specified, create an array with size 50. If n is a negative value, !! return an array with size 0. If n = 1, return an array whose only element is base**end. If no base !! is specified, logspace will default to using a base of 10 !! !!([Specification](../page/specs/stdlib_math.html#logspace-create-a-logarithmically-spaced-rank-one-array)) #!========================================================= #!= logspace(start, end) = #!========================================================= #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("logspace", 1, t1, k1, "default") pure module function ${RName}$(start, end) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end ${t1}$ :: res(DEFAULT_LOGSPACE_LENGTH) end function ${RName}$ #:endfor #! Integer support #:set RName = rname("logspace", 1, "integer(int32)", "int32", "default") pure module function ${RName}$(start, end) result(res) integer, intent(in) :: start integer, intent(in) :: end real(dp) :: res(DEFAULT_LOGSPACE_LENGTH) end function ${RName}$ #!========================================================= #!= logspace(start, end, n) = #!========================================================= #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("logspace", 1, t1, k1, "n") pure module function ${RName}$(start, end, n) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end integer, intent(in) :: n ${t1}$ :: res(max(n, 0)) end function ${RName}$ #:endfor #! Integer support #:set RName = rname("logspace", 1, "integer(int32)", "int32", "n") pure module function ${RName}$(start, end, n) result(res) integer, intent(in) :: start integer, intent(in) :: end integer, intent(in) :: n real(dp) :: res(n) end function ${RName}$ #!========================================================= #!= logspace(start, end, n, base) = #!========================================================= #! Need another function where base is not optional, #! otherwise the compiler can not differentiate between #! generic calls to logspace_n where a base is not present #! ======================================================== #:for k1, t1 in REAL_KINDS_TYPES ! Generate logarithmically spaced sequence from ${k1}$ base to the powers ! of ${k1}$ start and end. [base^start, ... , base^end] ! Different combinations of parameter types will lead to different result types. ! Those combinations are indicated in the body of each function. #:set RName = rname("logspace", 1, t1, k1, "n_rbase") pure module function ${RName}$(start, end, n, base) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end integer, intent(in) :: n ${t1}$, intent(in) :: base ! real(${k1}$) endpoints + real(${k1}$) base = real(${k1}$) result ${t1}$ :: res(max(n, 0)) end function ${RName}$ #:set RName = rname("logspace", 1, t1, k1, "n_cbase") pure module function ${RName}$(start, end, n, base) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end integer, intent(in) :: n complex(${k1}$), intent(in) :: base ! real(${k1}$) endpoints + complex(${k1}$) base = complex(${k1}$) result ${t1}$ :: res(max(n, 0)) end function ${RName}$ #:set RName = rname("logspace", 1, t1, k1, "n_ibase") pure module function ${RName}$(start, end, n, base) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end integer, intent(in) :: n integer, intent(in) :: base ! real(${k1}$) endpoints + integer base = real(${k1}$) result ${t1}$ :: res(max(n, 0)) end function ${RName}$ #:endfor #! ======================================================== #! ======================================================== #:for k1, t1 in CMPLX_KINDS_TYPES ! Generate logarithmically spaced sequence from ${k1}$ base to the powers ! of ${k1}$ start and end. [base^start, ... , base^end] ! Different combinations of parameter types will lead to different result types. ! Those combinations are indicated in the body of each function. #:set RName = rname("logspace", 1, t1, k1, "n_rbase") pure module function ${RName}$(start, end, n, base) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end integer, intent(in) :: n real(${k1}$), intent(in) :: base ! complex(${k1}$) endpoints + real(${k1}$) base = complex(${k1}$) result ${t1}$ :: res(max(n, 0)) end function ${RName}$ #:set RName = rname("logspace", 1, t1, k1, "n_cbase") pure module function ${RName}$(start, end, n, base) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end integer, intent(in) :: n complex(${k1}$), intent(in) :: base ! complex(${k1}$) endpoints + complex(${k1}$) base = complex(${k1}$) result ${t1}$ :: res(max(n, 0)) end function ${RName}$ #:set RName = rname("logspace", 1, t1, k1, "n_ibase") pure module function ${RName}$(start, end, n, base) result(res) ${t1}$, intent(in) :: start ${t1}$, intent(in) :: end integer, intent(in) :: n integer, intent(in) :: base ! complex(${k1}$) endpoints + integer base = complex(${k1}$) result ${t1}$ :: res(max(n, 0)) end function ${RName}$ #:endfor #! ======================================================== #! ======================================================== #! Provide support for Integer start/endpoints ! Generate logarithmically spaced sequence from ${k1}$ base to the powers ! of ${k1}$ start and end. [base^start, ... , base^end] ! Different combinations of parameter types will lead to different result types. ! Those combinations are indicated in the body of each function. #:for k1 in REAL_KINDS #:set RName = rname("logspace", 1, "integer(int32)", "int32", "n_r" + str(k1) + "base") pure module function ${RName}$(start, end, n, base) result(res) integer, intent(in) :: start integer, intent(in) :: end integer, intent(in) :: n real(${k1}$), intent(in) :: base ! integer endpoints + real(${k1}$) base = real(${k1}$) result real(${k1}$) :: res(max(n, 0)) end function ${RName}$ #:set RName = rname("logspace", 1, "integer(int32)", "int32", "n_c" + str(k1) + "base") pure module function ${RName}$(start, end, n, base) result(res) integer, intent(in) :: start integer, intent(in) :: end integer, intent(in) :: n complex(${k1}$), intent(in) :: base ! integer endpoints + complex(${k1}$) base = complex(${k1}$) result complex(${k1}$) :: res(max(n, 0)) end function ${RName}$ #:endfor #:set RName = rname("logspace", 1, "integer(int32)", "int32", "n_ibase") pure module function ${RName}$(start, end, n, base) result(res) integer, intent(in) :: start integer, intent(in) :: end integer, intent(in) :: n integer, intent(in) :: base ! integer endpoints + integer base = integer result integer :: res(max(n, 0)) end function ${RName}$ end interface !> Version: experimental !> !> `arange` creates a one-dimensional `array` of the `integer/real` type !> with fixed-spaced values of given spacing, within a given interval. !> ([Specification](../page/specs/stdlib_math.html#arange-function)) interface arange #:set RI_KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES #:for k1, t1 in RI_KINDS_TYPES pure module function arange_${t1[0]}$_${k1}$(start, end, step) result(result) ${t1}$, intent(in) :: start ${t1}$, intent(in), optional :: end, step ${t1}$, allocatable :: result(:) end function arange_${t1[0]}$_${k1}$ #:endfor end interface arange !> Version: experimental !> !> `arg` computes the phase angle in the interval (-π,π]. !> ([Specification](../page/specs/stdlib_math.html#arg-function)) interface arg #:for k1 in CMPLX_KINDS procedure :: arg_${k1}$ #:endfor end interface arg !> Version: experimental !> !> `argd` computes the phase angle of degree version in the interval (-180.0,180.0]. !> ([Specification](../page/specs/stdlib_math.html#argd-function)) interface argd #:for k1 in CMPLX_KINDS procedure :: argd_${k1}$ #:endfor end interface argd !> Version: experimental !> !> `argpi` computes the phase angle of circular version in the interval (-1.0,1.0]. !> ([Specification](../page/specs/stdlib_math.html#argpi-function)) interface argpi #:for k1 in CMPLX_KINDS procedure :: argpi_${k1}$ #:endfor end interface argpi !> Version: experimental !> !> `deg2rad` converts phase angles from degrees to radians. !> ([Specification](../page/specs/stdlib_math.html#deg2rad-function)) interface deg2rad #:for k1 in REAL_KINDS procedure :: deg2rad_${k1}$ #:endfor end interface deg2rad !> Version: experimental !> !> `rad2deg` converts phase angles from radians to degrees. !> ([Specification](../page/specs/stdlib_math.html#rad2deg-function)) interface rad2deg #:for k1 in REAL_KINDS procedure :: rad2deg_${k1}$ #:endfor end interface rad2deg !> Returns a boolean scalar/array where two scalar/arrays are element-wise equal within a tolerance. !> ([Specification](../page/specs/stdlib_math.html#is_close-function)) interface is_close #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES #:for k1, t1 in RC_KINDS_TYPES elemental module logical function is_close_${t1[0]}$${k1}$(a, b, rel_tol, abs_tol, equal_nan) result(close) ${t1}$, intent(in) :: a, b real(${k1}$), intent(in), optional :: rel_tol, abs_tol logical, intent(in), optional :: equal_nan end function is_close_${t1[0]}$${k1}$ #:endfor end interface is_close !> Version: experimental !> !> Returns a boolean scalar where two arrays are element-wise equal within a tolerance. !> ([Specification](../page/specs/stdlib_math.html#all_close-function)) interface all_close #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES #:set RANKS = range(1, MAXRANK + 1) #:for k1, t1 in RC_KINDS_TYPES #:for r1 in RANKS logical pure module function all_close_${r1}$_${t1[0]}$${k1}$(a, b, rel_tol, abs_tol, equal_nan) result(close) ${t1}$, intent(in) :: a${ranksuffix(r1)}$, b${ranksuffix(r1)}$ real(${k1}$), intent(in), optional :: rel_tol, abs_tol logical, intent(in), optional :: equal_nan end function all_close_${r1}$_${t1[0]}$${k1}$ #:endfor #:endfor end interface all_close !> Version: experimental !> !> Computes differences between adjacent elements of an array. !> ([Specification](../page/specs/stdlib_math.html#diff-function)) interface diff #:set RI_KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES #:for k1, t1 in RI_KINDS_TYPES pure module function diff_1_${k1}$(x, n, prepend, append) result(y) ${t1}$, intent(in) :: x(:) integer, intent(in), optional :: n ${t1}$, intent(in), optional :: prepend(:), append(:) ${t1}$, allocatable :: y(:) end function diff_1_${k1}$ pure module function diff_2_${k1}$(X, n, dim, prepend, append) result(y) ${t1}$, intent(in) :: x(:, :) integer, intent(in), optional :: n, dim ${t1}$, intent(in), optional :: prepend(:, :), append(:, :) ${t1}$, allocatable :: y(:, :) end function diff_2_${k1}$ #:endfor end interface diff !> Version: experimental !> !> Computes a list of coordinate matrices from coordinate vectors. !> ([Specification](../page/specs/stdlib_math.html#meshgrid)) interface meshgrid #:set RANKS = range(1, MAXRANK + 1) #:for k1, t1 in IR_KINDS_TYPES #:for rank in RANKS #:set RName = rname("meshgrid", rank, t1, k1) module subroutine ${RName}$(& ${"".join(f"x{i}, " for i in range(1, rank + 1))}$ & ${"".join(f"xm{i}, " for i in range(1, rank + 1))}$ & indexing & ) #:for i in range(1, rank + 1) ${t1}$, intent(in) :: x${i}$(:) ${t1}$, intent(out) :: xm${i}$ ${ranksuffix(rank)}$ #:endfor integer, intent(in), optional :: indexing end subroutine ${RName}$ #:endfor #:endfor end interface meshgrid contains #:for k1, t1 in IR_KINDS_TYPES elemental function clip_${k1}$(x, xmin, xmax) result(res) ${t1}$, intent(in) :: x ${t1}$, intent(in) :: xmin ${t1}$, intent(in) :: xmax ${t1}$ :: res res = max(min(x, xmax), xmin) end function clip_${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES elemental function arg_${k1}$(z) result(result) ${t1}$, intent(in) :: z real(${k1}$) :: result result = merge(0.0_${k1}$, atan2(z%im, z%re), z == (0.0_${k1}$, 0.0_${k1}$)) end function arg_${k1}$ elemental function argd_${k1}$(z) result(result) ${t1}$, intent(in) :: z real(${k1}$) :: result result = merge(0.0_${k1}$, atan2(z%im, z%re)*180.0_${k1}$/PI_${k1}$, & z == (0.0_${k1}$, 0.0_${k1}$)) end function argd_${k1}$ elemental function argpi_${k1}$(z) result(result) ${t1}$, intent(in) :: z real(${k1}$) :: result result = merge(0.0_${k1}$, atan2(z%im, z%re)/PI_${k1}$, & z == (0.0_${k1}$, 0.0_${k1}$)) end function argpi_${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES elemental function deg2rad_${k1}$(theta) result(result) ${t1}$, intent(in) :: theta ${t1}$ :: result result = theta * PI_${k1}$ / 180.0_${k1}$ end function deg2rad_${k1}$ elemental function rad2deg_${k1}$(theta) result(result) ${t1}$, intent(in) :: theta ${t1}$ :: result result = theta * 180.0_${k1}$ / PI_${k1}$ end function rad2deg_${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES !> Returns the greatest common divisor of two integers of kind ${k1}$ !> using the Euclidean algorithm. elemental function gcd_${k1}$(a, b) result(res) ${t1}$, intent(in) :: a ${t1}$, intent(in) :: b ${t1}$ :: res ${t1}$ :: rem, tmp rem = min(abs(a), abs(b)) res = max(abs(a), abs(b)) do while (rem /= 0_${k1}$) tmp = rem rem = mod(res, rem) res = tmp end do end function gcd_${k1}$ #:endfor #:for k1, t1, a1, cpp1 in INT_KINDS_TYPES + REAL_KINDS_TYPES + BITSETS_KINDS_TYPES #:block generate_cpp(cpp_var=cpp1) elemental subroutine swap_${k1}$(lhs, rhs) ${t1}$, intent(inout) :: lhs, rhs ${t1}$ :: temp temp = lhs; lhs = rhs; rhs = temp end subroutine #:endblock #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES elemental subroutine swap_c${k1}$(lhs, rhs) ${t1}$, intent(inout) :: lhs, rhs ${t1}$ :: temp temp = lhs; lhs = rhs; rhs = temp end subroutine #:endfor elemental subroutine swap_bool(lhs, rhs) logical, intent(inout) :: lhs, rhs logical :: temp temp = lhs; lhs = rhs; rhs = temp end subroutine elemental subroutine swap_str(lhs,rhs) character(*), intent(inout) :: lhs, rhs character(len=max(len(lhs), len(rhs))) :: temp temp = lhs ; lhs = rhs ; rhs = temp end subroutine elemental subroutine swap_stt(lhs,rhs) use stdlib_string_type, only: string_type type(string_type), intent(inout) :: lhs, rhs type(string_type) :: temp temp = lhs ; lhs = rhs ; rhs = temp end subroutine end module stdlib_math fortran-lang-stdlib-0ede301/src/math/stdlib_math_diff.fypp0000664000175000017500000001053415135654166024073 0ustar alastairalastair!> Inspired by original code (MIT license) written in 2016 by Keurfon Luu (keurfonluu@outlook.com) !> https://github.com/keurfonluu/Forlab #:include "common.fypp" #:set RI_KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES submodule (stdlib_math) stdlib_math_diff implicit none contains !> `diff` computes differences of adjacent elements of an array. #:for k1, t1 in RI_KINDS_TYPES pure module function diff_1_${k1}$(x, n, prepend, append) result(y) ${t1}$, intent(in) :: x(:) integer, intent(in), optional :: n ${t1}$, intent(in), optional :: prepend(:), append(:) ${t1}$, allocatable :: y(:) integer :: size_prepend, size_append, size_x, size_work integer :: n_, i n_ = optval(n, 1) if (n_ <= 0) then y = x return end if size_prepend = 0 size_append = 0 if (present(prepend)) size_prepend = size(prepend) if (present(append)) size_append = size(append) size_x = size(x) size_work = size_x + size_prepend + size_append if (size_work <= n_) then allocate(y(0)) return end if !> Use a quick exit for the common case, to avoid memory allocation. if (size_prepend == 0 .and. size_append == 0 .and. n_ == 1) then y = x(2:) - x(1:size_x-1) return end if block ${t1}$ :: work(size_work) if (size_prepend > 0) work(:size_prepend) = prepend work(size_prepend+1:size_prepend+size_x) = x if (size_append > 0) work(size_prepend+size_x+1:) = append do i = 1, n_ work(1:size_work-i) = work(2:size_work-i+1) - work(1:size_work-i) end do y = work(1:size_work-n_) end block end function diff_1_${k1}$ pure module function diff_2_${k1}$(x, n, dim, prepend, append) result(y) ${t1}$, intent(in) :: x(:, :) integer, intent(in), optional :: n, dim ${t1}$, intent(in), optional :: prepend(:, :), append(:, :) ${t1}$, allocatable :: y(:, :) integer :: size_prepend, size_append, size_x, size_work integer :: n_, dim_, i n_ = optval(n, 1) if (n_ <= 0) then y = x return end if size_prepend = 0 size_append = 0 if (present(dim)) then if (dim == 1 .or. dim == 2) then dim_ = dim else dim_ = 1 end if else dim_ = 1 end if if (present(prepend)) size_prepend = size(prepend, dim_) if (present(append)) size_append = size(append, dim_) size_x = size(x, dim_) size_work = size_x + size_prepend + size_append if (size_work <= n_) then allocate(y(0, 0)) return end if !> Use a quick exit for the common case, to avoid memory allocation. if (size_prepend == 0 .and. size_append == 0 .and. n_ == 1) then if (dim_ == 1) then y = x(2:, :) - x(1:size_x-1, :) elseif (dim_ == 2) then y = x(:, 2:) - x(:, 1:size_x-1) end if return end if if (dim_ == 1) then block ${t1}$ :: work(size_work, size(x, 2)) if (size_prepend > 0) work(1:size_prepend, :) = prepend work(size_prepend+1:size_x+size_prepend, :) = x if (size_append > 0) work(size_x+size_prepend+1:, :) = append do i = 1, n_ work(1:size_work-i, :) = work(2:size_work-i+1, :) - work(1:size_work-i, :) end do y = work(1:size_work-n_, :) end block elseif (dim_ == 2) then block ${t1}$ :: work(size(x, 1), size_work) if (size_prepend > 0) work(:, 1:size_prepend) = prepend work(:, size_prepend+1:size_x+size_prepend) = x if (size_append > 0) work(:, size_x+size_prepend+1:) = append do i = 1, n_ work(:, 1:size_work-i) = work(:, 2:size_work-i+1) - work(:, 1:size_work-i) end do y = work(:, 1:size_work-n_) end block end if end function diff_2_${k1}$ #:endfor end submodule stdlib_math_difffortran-lang-stdlib-0ede301/src/CMakeLists.txt0000664000175000017500000000274315135654166021523 0ustar alastairalastairmacro(ADD_SUBDIR name) string(TOUPPER "${name}" uname) if (STDLIB_${uname}) add_subdirectory(${name}) list(APPEND OPTIONAL_LIB ${PROJECT_NAME}_${name}) endif() endmacro() set(OPTIONAL_LIB) ADD_SUBDIR(ansi) add_subdirectory(array) ADD_SUBDIR(bitsets) add_subdirectory(blas) add_subdirectory(constants) add_subdirectory(core) add_subdirectory(hash) ADD_SUBDIR(hashmaps) add_subdirectory(intrinsics) ADD_SUBDIR(io) add_subdirectory(lapack) add_subdirectory(lapack_extended) add_subdirectory(linalg_core) ADD_SUBDIR(linalg_iterative) add_subdirectory(linalg) ADD_SUBDIR(logger) add_subdirectory(math) ADD_SUBDIR(quadrature) add_subdirectory(selection) add_subdirectory(sorting) add_subdirectory(specialfunctions) ADD_SUBDIR(specialmatrices) ADD_SUBDIR(stringlist) add_subdirectory(strings) ADD_SUBDIR(system) ADD_SUBDIR(stats) add_subdirectory(sparse) set(fppFiles stdlib_version.fypp ) set(cppFiles ) set(f90Files ) configure_stdlib_target(${PROJECT_NAME} f90Files fppFiles cppFiles) target_link_libraries(${PROJECT_NAME} PUBLIC ${PROJECT_NAME}_array ${PROJECT_NAME}_constants ${PROJECT_NAME}_core ${PROJECT_NAME}_hash ${PROJECT_NAME}_intrinsics ${PROJECT_NAME}_linalg_core ${PROJECT_NAME}_linalg ${PROJECT_NAME}_math ${PROJECT_NAME}_selection ${PROJECT_NAME}_specialfunctions ${PROJECT_NAME}_sorting ${PROJECT_NAME}_strings ${PROJECT_NAME}_blas ${PROJECT_NAME}_lapack ${PROJECT_NAME}_lapack_extended ${PROJECT_NAME}_sparse ${OPTIONAL_LIB} ) fortran-lang-stdlib-0ede301/src/constants/0000775000175000017500000000000015135654166020771 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/constants/stdlib_constants.fypp0000664000175000017500000001144115135654166025247 0ustar alastairalastair#:include "common.fypp" #:set KINDS = REAL_KINDS #:set I_KINDS_TYPES = list(zip(INT_KINDS, INT_TYPES, INT_KINDS)) #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) module stdlib_constants !! Constants !! ([Specification](../page/specs/stdlib_constants.html)) use stdlib_kinds use stdlib_codata, only: SPEED_OF_LIGHT_IN_VACUUM, & VACUUM_ELECTRIC_PERMITTIVITY, & VACUUM_MAG_PERMEABILITY, & PLANCK_CONSTANT, & NEWTONIAN_CONSTANT_OF_GRAVITATION, & STANDARD_ACCELERATION_OF_GRAVITY, & ELEMENTARY_CHARGE, & MOLAR_GAS_CONSTANT, & FINE_STRUCTURE_CONSTANT, & AVOGADRO_CONSTANT, & BOLTZMANN_CONSTANT, & STEFAN_BOLTZMANN_CONSTANT, & WIEN_WAVELENGTH_DISPLACEMENT_LAW_CONSTANT, & RYDBERG_CONSTANT, & ELECTRON_MASS, & PROTON_MASS, & NEUTRON_MASS, & ATOMIC_MASS_CONSTANT private ! mathematical constants #:for k in KINDS real(${k}$), parameter, public :: PI_${k}$ = acos(-1.0_${k}$) !! PI #:endfor ! Physical constants real(dp), parameter, public :: c = SPEED_OF_LIGHT_IN_VACUUM%value !! Speed of light in vacuum real(dp), parameter, public :: speed_of_light = SPEED_OF_LIGHT_IN_VACUUM%value !! Speed of light in vacuum real(dp), parameter, public :: mu_0 = VACUUM_MAG_PERMEABILITY%value !! vacuum mag. permeability real(dp), parameter, public :: epsilon_0 = VACUUM_ELECTRIC_PERMITTIVITY%value !! vacuum mag. permeability real(dp), parameter, public :: h = PLANCK_CONSTANT%value !! Planck constant real(dp), parameter, public :: Planck = PLANCK_CONSTANT%value !! Planck constant real(dp), parameter, public :: hbar = PLANCK_CONSTANT%value / (2.0_dp * PI_dp) !! Reduced Planck constant real(dp), parameter, public :: G = NEWTONIAN_CONSTANT_OF_GRAVITATION%value !! Newtonian constant of gravitation real(dp), parameter, public :: gravitation_constant = NEWTONIAN_CONSTANT_OF_GRAVITATION%value !! Newtonian constant of gravitation real(dp), parameter, public :: g2 = STANDARD_ACCELERATION_OF_GRAVITY%value !! Standard acceleration of gravity real(dp), parameter, public :: e = ELEMENTARY_CHARGE%value !! Elementary charge real(dp), parameter, public :: R = MOLAR_GAS_CONSTANT%value !! Molar gas constant real(dp), parameter, public :: gas_constant = MOLAR_GAS_CONSTANT%value !! Molar gas constant real(dp), parameter, public :: alpha = FINE_STRUCTURE_CONSTANT%value !! Fine structure constant real(dp), parameter, public :: fine_structure = FINE_STRUCTURE_CONSTANT%value !! Fine structure constant real(dp), parameter, public :: N_A = AVOGADRO_CONSTANT%value !! Avogadro constant real(dp), parameter, public :: Avogadro = AVOGADRO_CONSTANT%value !! Avogadro constant real(dp), parameter, public :: k = BOLTZMANN_CONSTANT%value !! Boltzmann constant real(dp), parameter, public :: Boltzmann = BOLTZMANN_CONSTANT%value !! Boltzmann constant real(dp), parameter, public :: sigma = STEFAN_BOLTZMANN_CONSTANT%value !! Stefan-Boltzmann constant real(dp), parameter, public :: Stefan_Boltzmann = STEFAN_BOLTZMANN_CONSTANT%value !! Stefan-Boltzmann constant real(dp), parameter, public :: Wien = WIEN_WAVELENGTH_DISPLACEMENT_LAW_CONSTANT%value !! Wien wavelength displacement law constant real(dp), parameter, public :: Rydberg = RYDBERG_CONSTANT%value !! Rydberg constant real(dp), parameter, public :: m_e = ELECTRON_MASS%value !! Electron mass real(dp), parameter, public :: m_p = PROTON_MASS%value !! Proton mass real(dp), parameter, public :: m_n = NEUTRON_MASS%value !! Neutron mass real(dp), parameter, public :: m_u = ATOMIC_MASS_CONSTANT%value !! Atomic mass constant real(dp), parameter, public :: u = ATOMIC_MASS_CONSTANT%value !! Atomic mass constant ! Additional constants if needed #:for k, t, s in I_KINDS_TYPES ${t}$, parameter, public :: zero_${s}$ = 0_${k}$ ${t}$, parameter, public :: one_${s}$ = 1_${k}$ #:endfor #:for k, t, s in R_KINDS_TYPES ${t}$, parameter, public :: zero_${s}$ = 0._${k}$ ${t}$, parameter, public :: one_${s}$ = 1._${k}$ ${t}$, parameter, public :: log2_${s}$ = log(2.0_${k}$) #:endfor #:for k, t, s in C_KINDS_TYPES ${t}$, parameter, public :: zero_${s}$ = (0._${k}$,0._${k}$) ${t}$, parameter, public :: one_${s}$ = (1._${k}$,0._${k}$) #:endfor end module stdlib_constants fortran-lang-stdlib-0ede301/src/constants/stdlib_codata_type.fypp0000664000175000017500000000427015135654166025531 0ustar alastairalastair#:include "common.fypp" #:set KINDS = REAL_KINDS module stdlib_codata_type !! Codata constant type !! ([Specification](../page/specs/stdlib_constants.html)) use stdlib_kinds, only: #{for k in KINDS[:-1]}#${k}$, #{endfor}#${KINDS[-1]}$ use stdlib_io_aux, only: FMT_REAL_DP use stdlib_optval, only: optval private type, public :: codata_constant_type !! version: experimental !! !! Derived type for representing a Codata constant. !! ([Specification](../page/specs/stdlib_constants.html)) character(len=64) :: name real(dp) :: value real(dp) :: uncertainty character(len=32) :: unit contains procedure :: print #:for k in KINDS procedure :: to_real_${k}$ #:endfor generic :: to_real => #{for k in KINDS[:-1]}#to_real_${k}$, #{endfor}#to_real_${KINDS[-1]}$ end type interface to_real !! Get the constant value or uncertainty. #:for k in KINDS module procedure to_real_${k}$ #:endfor end interface public :: to_real contains subroutine print(self) !! Print out the constant's name, value, uncertainty and unit. class(codata_constant_type), intent(in) :: self print "(A64, SP, "//FMT_REAL_DP//", A5, "//FMT_REAL_DP//", 1X, A32)", self%name, self%value, "+/-", self%uncertainty, self%unit end subroutine #:for k in KINDS elemental pure real(${k}$) function to_real_${k}$(self, mold, uncertainty) result(r) !! version: experimental !! !! Get the constant value or uncertainty for the kind ${k}$ !! ([Specification](../page/specs/stdlib_constants.html)) class(codata_constant_type), intent(in) :: self !! Codata constant real(${k}$), intent(in) :: mold !! dummy argument to disambiguate at compile time the generic interface logical, intent(in), optional :: uncertainty !! Set to true if the uncertainty is required. Default to .false.. !! logical :: u u = optval(uncertainty, .false.) if(u .eqv. .false.)then r = real(self%value, kind(mold)) else r = real(self%uncertainty, kind(mold)) end if end function #:endfor end module stdlib_codata_type fortran-lang-stdlib-0ede301/src/constants/stdlib_codata.f900000664000175000017500000022451215135654166024113 0ustar alastairalastairmodule stdlib_codata !! Codata Constants - Autogenerated use stdlib_kinds, only: dp, int32 use stdlib_codata_type private integer(int32), parameter, public :: YEAR = 2022 !! Year of release. type(codata_constant_type), parameter, public :: ALPHA_PARTICLE_ELECTRON_MASS_RATIO = & codata_constant_type("alpha particle-electron mass ratio", & 7294.29954171_dp, 0.00000017_dp, & "") !! alpha particle-electron mass ratio type(codata_constant_type), parameter, public :: ALPHA_PARTICLE_MASS = & codata_constant_type("alpha particle mass", & 6.6446573450e-27_dp, 0.0000000021e-27_dp, & "kg") !! alpha particle mass type(codata_constant_type), parameter, public :: ALPHA_PARTICLE_MASS_ENERGY_EQUIVALENT = & codata_constant_type("alpha particle mass energy equivalent", & 5.9719201997e-10_dp, 0.0000000019e-10_dp, & "J") !! alpha particle mass energy equivalent type(codata_constant_type), parameter, public :: ALPHA_PARTICLE_MASS_ENERGY_EQUIVALENT_IN_MEV = & codata_constant_type("alpha particle mass energy equivalent in MeV", & 3727.3794118_dp, 0.0000012_dp, & "MeV") !! alpha particle mass energy equivalent in MeV type(codata_constant_type), parameter, public :: ALPHA_PARTICLE_MASS_IN_U = & codata_constant_type("alpha particle mass in u", & 4.001506179129_dp, 0.000000000062_dp, & "u") !! alpha particle mass in u type(codata_constant_type), parameter, public :: ALPHA_PARTICLE_MOLAR_MASS = & codata_constant_type("alpha particle molar mass", & 4.0015061833e-3_dp, 0.0000000012e-3_dp, & "kg mol^-1") !! alpha particle molar mass type(codata_constant_type), parameter, public :: ALPHA_PARTICLE_PROTON_MASS_RATIO = & codata_constant_type("alpha particle-proton mass ratio", & 3.972599690252_dp, 0.000000000070_dp, & "") !! alpha particle-proton mass ratio type(codata_constant_type), parameter, public :: ALPHA_PARTICLE_RELATIVE_ATOMIC_MASS = & codata_constant_type("alpha particle relative atomic mass", & 4.001506179129_dp, 0.000000000062_dp, & "") !! alpha particle relative atomic mass type(codata_constant_type), parameter, public :: ALPHA_PARTICLE_RMS_CHARGE_RADIUS = & codata_constant_type("alpha particle rms charge radius", & 1.6785e-15_dp, 0.0021e-15_dp, & "m") !! alpha particle rms charge radius type(codata_constant_type), parameter, public :: ANGSTROM_STAR = & codata_constant_type("Angstrom star", & 1.00001495e-10_dp, 0.00000090e-10_dp, & "m") !! Angstrom star type(codata_constant_type), parameter, public :: ATOMIC_MASS_CONSTANT = & codata_constant_type("atomic mass constant", & 1.66053906892e-27_dp, 0.00000000052e-27_dp, & "kg") !! atomic mass constant type(codata_constant_type), parameter, public :: ATOMIC_MASS_CONSTANT_ENERGY_EQUIVALENT = & codata_constant_type("atomic mass constant energy equivalent", & 1.49241808768e-10_dp, 0.00000000046e-10_dp, & "J") !! atomic mass constant energy equivalent type(codata_constant_type), parameter, public :: ATOMIC_MASS_CONSTANT_ENERGY_EQUIVALENT_IN_MEV = & codata_constant_type("atomic mass constant energy equivalent in MeV", & 931.49410372_dp, 0.00000029_dp, & "MeV") !! atomic mass constant energy equivalent in MeV type(codata_constant_type), parameter, public :: ATOMIC_MASS_UNIT_ELECTRON_VOLT_RELATIONSHIP = & codata_constant_type("atomic mass unit-electron volt relationship", & 9.3149410372e8_dp, 0.0000000029e8_dp, & "eV") !! atomic mass unit-electron volt relationship type(codata_constant_type), parameter, public :: ATOMIC_MASS_UNIT_HARTREE_RELATIONSHIP = & codata_constant_type("atomic mass unit-hartree relationship", & 3.4231776922e7_dp, 0.0000000011e7_dp, & "E_h") !! atomic mass unit-hartree relationship type(codata_constant_type), parameter, public :: ATOMIC_MASS_UNIT_HERTZ_RELATIONSHIP = & codata_constant_type("atomic mass unit-hertz relationship", & 2.25234272185e23_dp, 0.00000000070e23_dp, & "Hz") !! atomic mass unit-hertz relationship type(codata_constant_type), parameter, public :: ATOMIC_MASS_UNIT_INVERSE_METER_RELATIONSHIP = & codata_constant_type("atomic mass unit-inverse meter relationship", & 7.5130066209e14_dp, 0.0000000023e14_dp, & "m^-1") !! atomic mass unit-inverse meter relationship type(codata_constant_type), parameter, public :: ATOMIC_MASS_UNIT_JOULE_RELATIONSHIP = & codata_constant_type("atomic mass unit-joule relationship", & 1.49241808768e-10_dp, 0.00000000046e-10_dp, & "J") !! atomic mass unit-joule relationship type(codata_constant_type), parameter, public :: ATOMIC_MASS_UNIT_KELVIN_RELATIONSHIP = & codata_constant_type("atomic mass unit-kelvin relationship", & 1.08095402067e13_dp, 0.00000000034e13_dp, & "K") !! atomic mass unit-kelvin relationship type(codata_constant_type), parameter, public :: ATOMIC_MASS_UNIT_KILOGRAM_RELATIONSHIP = & codata_constant_type("atomic mass unit-kilogram relationship", & 1.66053906892e-27_dp, 0.00000000052e-27_dp, & "kg") !! atomic mass unit-kilogram relationship type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_1ST_HYPERPOLARIZABILITY = & codata_constant_type("atomic unit of 1st hyperpolarizability", & 3.2063612996e-53_dp, 0.0000000015e-53_dp, & "C^3 m^3 J^-2") !! atomic unit of 1st hyperpolarizability type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_2ND_HYPERPOLARIZABILITY = & codata_constant_type("atomic unit of 2nd hyperpolarizability", & 6.2353799735e-65_dp, 0.0000000039e-65_dp, & "C^4 m^4 J^-3") !! atomic unit of 2nd hyperpolarizability type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_ACTION = & codata_constant_type("atomic unit of action", & 1.054571817e-34_dp, 0.0_dp, & "J s") !! atomic unit of action type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_CHARGE = & codata_constant_type("atomic unit of charge", & 1.602176634e-19_dp, 0.0_dp, & "C") !! atomic unit of charge type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_CHARGE_DENSITY = & codata_constant_type("atomic unit of charge density", & 1.08120238677e12_dp, 0.00000000051e12_dp, & "C m^-3") !! atomic unit of charge density type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_CURRENT = & codata_constant_type("atomic unit of current", & 6.6236182375082e-3_dp, 0.0000000000072e-3_dp, & "A") !! atomic unit of current type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_ELECTRIC_DIPOLE_MOM = & codata_constant_type("atomic unit of electric dipole mom.", & 8.4783536198e-30_dp, 0.0000000013e-30_dp, & "C m") !! atomic unit of electric dipole mom. type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_ELECTRIC_FIELD = & codata_constant_type("atomic unit of electric field", & 5.14220675112e11_dp, 0.00000000080e11_dp, & "V m^-1") !! atomic unit of electric field type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_ELECTRIC_FIELD_GRADIENT = & codata_constant_type("atomic unit of electric field gradient", & 9.7173624424e21_dp, 0.0000000030e21_dp, & "V m^-2") !! atomic unit of electric field gradient type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_ELECTRIC_POLARIZABILITY = & codata_constant_type("atomic unit of electric polarizability", & 1.64877727212e-41_dp, 0.00000000051e-41_dp, & "C^2 m^2 J^-1") !! atomic unit of electric polarizability type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_ELECTRIC_POTENTIAL = & codata_constant_type("atomic unit of electric potential", & 27.211386245981_dp, 0.000000000030_dp, & "V") !! atomic unit of electric potential type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_ELECTRIC_QUADRUPOLE_MOM = & codata_constant_type("atomic unit of electric quadrupole mom.", & 4.4865515185e-40_dp, 0.0000000014e-40_dp, & "C m^2") !! atomic unit of electric quadrupole mom. type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_ENERGY = & codata_constant_type("atomic unit of energy", & 4.3597447222060e-18_dp, 0.0000000000048e-18_dp, & "J") !! atomic unit of energy type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_FORCE = & codata_constant_type("atomic unit of force", & 8.2387235038e-8_dp, 0.0000000013e-8_dp, & "N") !! atomic unit of force type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_LENGTH = & codata_constant_type("atomic unit of length", & 5.29177210544e-11_dp, 0.00000000082e-11_dp, & "m") !! atomic unit of length type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_MAG_DIPOLE_MOM = & codata_constant_type("atomic unit of mag. dipole mom.", & 1.85480201315e-23_dp, 0.00000000058e-23_dp, & "J T^-1") !! atomic unit of mag. dipole mom. type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_MAG_FLUX_DENSITY = & codata_constant_type("atomic unit of mag. flux density", & 2.35051757077e5_dp, 0.00000000073e5_dp, & "T") !! atomic unit of mag. flux density type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_MAGNETIZABILITY = & codata_constant_type("atomic unit of magnetizability", & 7.8910365794e-29_dp, 0.0000000049e-29_dp, & "J T^-2") !! atomic unit of magnetizability type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_MASS = & codata_constant_type("atomic unit of mass", & 9.1093837139e-31_dp, 0.0000000028e-31_dp, & "kg") !! atomic unit of mass type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_MOMENTUM = & codata_constant_type("atomic unit of momentum", & 1.99285191545e-24_dp, 0.00000000031e-24_dp, & "kg m s^-1") !! atomic unit of momentum type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_PERMITTIVITY = & codata_constant_type("atomic unit of permittivity", & 1.11265005620e-10_dp, 0.00000000017e-10_dp, & "F m^-1") !! atomic unit of permittivity type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_TIME = & codata_constant_type("atomic unit of time", & 2.4188843265864e-17_dp, 0.0000000000026e-17_dp, & "s") !! atomic unit of time type(codata_constant_type), parameter, public :: ATOMIC_UNIT_OF_VELOCITY = & codata_constant_type("atomic unit of velocity", & 2.18769126216e6_dp, 0.00000000034e6_dp, & "m s^-1") !! atomic unit of velocity type(codata_constant_type), parameter, public :: AVOGADRO_CONSTANT = & codata_constant_type("Avogadro constant", & 6.02214076e23_dp, 0.0_dp, & "mol^-1") !! Avogadro constant type(codata_constant_type), parameter, public :: BOHR_MAGNETON = & codata_constant_type("Bohr magneton", & 9.2740100657e-24_dp, 0.0000000029e-24_dp, & "J T^-1") !! Bohr magneton type(codata_constant_type), parameter, public :: BOHR_MAGNETON_IN_EV_T = & codata_constant_type("Bohr magneton in eV/T", & 5.7883817982e-5_dp, 0.0000000018e-5_dp, & "eV T^-1") !! Bohr magneton in eV/T type(codata_constant_type), parameter, public :: BOHR_MAGNETON_IN_HZ_T = & codata_constant_type("Bohr magneton in Hz/T", & 1.39962449171e10_dp, 0.00000000044e10_dp, & "Hz T^-1") !! Bohr magneton in Hz/T type(codata_constant_type), parameter, public :: BOHR_MAGNETON_IN_INVERSE_METER_PER_TESLA = & codata_constant_type("Bohr magneton in inverse meter per tesla", & 46.686447719_dp, 0.000000015_dp, & "m^-1 T^-1") !! Bohr magneton in inverse meter per tesla type(codata_constant_type), parameter, public :: BOHR_MAGNETON_IN_K_T = & codata_constant_type("Bohr magneton in K/T", & 0.67171381472_dp, 0.00000000021_dp, & "K T^-1") !! Bohr magneton in K/T type(codata_constant_type), parameter, public :: BOHR_RADIUS = & codata_constant_type("Bohr radius", & 5.29177210544e-11_dp, 0.00000000082e-11_dp, & "m") !! Bohr radius type(codata_constant_type), parameter, public :: BOLTZMANN_CONSTANT = & codata_constant_type("Boltzmann constant", & 1.380649e-23_dp, 0.0_dp, & "J K^-1") !! Boltzmann constant type(codata_constant_type), parameter, public :: BOLTZMANN_CONSTANT_IN_EV_K = & codata_constant_type("Boltzmann constant in eV/K", & 8.617333262e-5_dp, 0.0_dp, & "eV K^-1") !! Boltzmann constant in eV/K type(codata_constant_type), parameter, public :: BOLTZMANN_CONSTANT_IN_HZ_K = & codata_constant_type("Boltzmann constant in Hz/K", & 2.083661912e10_dp, 0.0_dp, & "Hz K^-1") !! Boltzmann constant in Hz/K type(codata_constant_type), parameter, public :: BOLTZMANN_CONSTANT_IN_INVERSE_METER_PER_KELVIN = & codata_constant_type("Boltzmann constant in inverse meter per kelvin", & 69.50348004_dp, 0.0_dp, & "m^-1 K^-1") !! Boltzmann constant in inverse meter per kelvin type(codata_constant_type), parameter, public :: CHARACTERISTIC_IMPEDANCE_OF_VACUUM = & codata_constant_type("characteristic impedance of vacuum", & 376.730313412_dp, 0.000000059_dp, & "ohm") !! characteristic impedance of vacuum type(codata_constant_type), parameter, public :: CLASSICAL_ELECTRON_RADIUS = & codata_constant_type("classical electron radius", & 2.8179403205e-15_dp, 0.0000000013e-15_dp, & "m") !! classical electron radius type(codata_constant_type), parameter, public :: COMPTON_WAVELENGTH = & codata_constant_type("Compton wavelength", & 2.42631023538e-12_dp, 0.00000000076e-12_dp, & "m") !! Compton wavelength type(codata_constant_type), parameter, public :: CONDUCTANCE_QUANTUM = & codata_constant_type("conductance quantum", & 7.748091729e-5_dp, 0.0_dp, & "S") !! conductance quantum type(codata_constant_type), parameter, public :: CONVENTIONAL_VALUE_OF_AMPERE_90 = & codata_constant_type("conventional value of ampere-90", & 1.00000008887_dp, 0.0_dp, & "A") !! conventional value of ampere-90 type(codata_constant_type), parameter, public :: CONVENTIONAL_VALUE_OF_COULOMB_90 = & codata_constant_type("conventional value of coulomb-90", & 1.00000008887_dp, 0.0_dp, & "C") !! conventional value of coulomb-90 type(codata_constant_type), parameter, public :: CONVENTIONAL_VALUE_OF_FARAD_90 = & codata_constant_type("conventional value of farad-90", & 0.99999998220_dp, 0.0_dp, & "F") !! conventional value of farad-90 type(codata_constant_type), parameter, public :: CONVENTIONAL_VALUE_OF_HENRY_90 = & codata_constant_type("conventional value of henry-90", & 1.00000001779_dp, 0.0_dp, & "H") !! conventional value of henry-90 type(codata_constant_type), parameter, public :: CONVENTIONAL_VALUE_OF_JOSEPHSON_CONSTANT = & codata_constant_type("conventional value of Josephson constant", & 483597.9e9_dp, 0.0_dp, & "Hz V^-1") !! conventional value of Josephson constant type(codata_constant_type), parameter, public :: CONVENTIONAL_VALUE_OF_OHM_90 = & codata_constant_type("conventional value of ohm-90", & 1.00000001779_dp, 0.0_dp, & "ohm") !! conventional value of ohm-90 type(codata_constant_type), parameter, public :: CONVENTIONAL_VALUE_OF_VOLT_90 = & codata_constant_type("conventional value of volt-90", & 1.00000010666_dp, 0.0_dp, & "V") !! conventional value of volt-90 type(codata_constant_type), parameter, public :: CONVENTIONAL_VALUE_OF_VON_KLITZING_CONSTANT = & codata_constant_type("conventional value of von Klitzing constant", & 25812.807_dp, 0.0_dp, & "ohm") !! conventional value of von Klitzing constant type(codata_constant_type), parameter, public :: CONVENTIONAL_VALUE_OF_WATT_90 = & codata_constant_type("conventional value of watt-90", & 1.00000019553_dp, 0.0_dp, & "W") !! conventional value of watt-90 type(codata_constant_type), parameter, public :: COPPER_X_UNIT = & codata_constant_type("Copper x unit", & 1.00207697e-13_dp, 0.00000028e-13_dp, & "m") !! Copper x unit type(codata_constant_type), parameter, public :: DEUTERON_ELECTRON_MAG_MOM_RATIO = & codata_constant_type("deuteron-electron mag. mom. ratio", & -4.664345550e-4_dp, 0.000000012e-4_dp, & "") !! deuteron-electron mag. mom. ratio type(codata_constant_type), parameter, public :: DEUTERON_ELECTRON_MASS_RATIO = & codata_constant_type("deuteron-electron mass ratio", & 3670.482967655_dp, 0.000000063_dp, & "") !! deuteron-electron mass ratio type(codata_constant_type), parameter, public :: DEUTERON_G_FACTOR = & codata_constant_type("deuteron g factor", & 0.8574382335_dp, 0.0000000022_dp, & "") !! deuteron g factor type(codata_constant_type), parameter, public :: DEUTERON_MAG_MOM = & codata_constant_type("deuteron mag. mom.", & 4.330735087e-27_dp, 0.000000011e-27_dp, & "J T^-1") !! deuteron mag. mom. type(codata_constant_type), parameter, public :: DEUTERON_MAG_MOM_TO_BOHR_MAGNETON_RATIO = & codata_constant_type("deuteron mag. mom. to Bohr magneton ratio", & 4.669754568e-4_dp, 0.000000012e-4_dp, & "") !! deuteron mag. mom. to Bohr magneton ratio type(codata_constant_type), parameter, public :: DEUTERON_MAG_MOM_TO_NUCLEAR_MAGNETON_RATIO = & codata_constant_type("deuteron mag. mom. to nuclear magneton ratio", & 0.8574382335_dp, 0.0000000022_dp, & "") !! deuteron mag. mom. to nuclear magneton ratio type(codata_constant_type), parameter, public :: DEUTERON_MASS = & codata_constant_type("deuteron mass", & 3.3435837768e-27_dp, 0.0000000010e-27_dp, & "kg") !! deuteron mass type(codata_constant_type), parameter, public :: DEUTERON_MASS_ENERGY_EQUIVALENT = & codata_constant_type("deuteron mass energy equivalent", & 3.00506323491e-10_dp, 0.00000000094e-10_dp, & "J") !! deuteron mass energy equivalent type(codata_constant_type), parameter, public :: DEUTERON_MASS_ENERGY_EQUIVALENT_IN_MEV = & codata_constant_type("deuteron mass energy equivalent in MeV", & 1875.61294500_dp, 0.00000058_dp, & "MeV") !! deuteron mass energy equivalent in MeV type(codata_constant_type), parameter, public :: DEUTERON_MASS_IN_U = & codata_constant_type("deuteron mass in u", & 2.013553212544_dp, 0.000000000015_dp, & "u") !! deuteron mass in u type(codata_constant_type), parameter, public :: DEUTERON_MOLAR_MASS = & codata_constant_type("deuteron molar mass", & 2.01355321466e-3_dp, 0.00000000063e-3_dp, & "kg mol^-1") !! deuteron molar mass type(codata_constant_type), parameter, public :: DEUTERON_NEUTRON_MAG_MOM_RATIO = & codata_constant_type("deuteron-neutron mag. mom. ratio", & -0.44820652_dp, 0.00000011_dp, & "") !! deuteron-neutron mag. mom. ratio type(codata_constant_type), parameter, public :: DEUTERON_PROTON_MAG_MOM_RATIO = & codata_constant_type("deuteron-proton mag. mom. ratio", & 0.30701220930_dp, 0.00000000079_dp, & "") !! deuteron-proton mag. mom. ratio type(codata_constant_type), parameter, public :: DEUTERON_PROTON_MASS_RATIO = & codata_constant_type("deuteron-proton mass ratio", & 1.9990075012699_dp, 0.0000000000084_dp, & "") !! deuteron-proton mass ratio type(codata_constant_type), parameter, public :: DEUTERON_RELATIVE_ATOMIC_MASS = & codata_constant_type("deuteron relative atomic mass", & 2.013553212544_dp, 0.000000000015_dp, & "") !! deuteron relative atomic mass type(codata_constant_type), parameter, public :: DEUTERON_RMS_CHARGE_RADIUS = & codata_constant_type("deuteron rms charge radius", & 2.12778e-15_dp, 0.00027e-15_dp, & "m") !! deuteron rms charge radius type(codata_constant_type), parameter, public :: ELECTRON_CHARGE_TO_MASS_QUOTIENT = & codata_constant_type("electron charge to mass quotient", & -1.75882000838e11_dp, 0.00000000055e11_dp, & "C kg^-1") !! electron charge to mass quotient type(codata_constant_type), parameter, public :: ELECTRON_DEUTERON_MAG_MOM_RATIO = & codata_constant_type("electron-deuteron mag. mom. ratio", & -2143.9234921_dp, 0.0000056_dp, & "") !! electron-deuteron mag. mom. ratio type(codata_constant_type), parameter, public :: ELECTRON_DEUTERON_MASS_RATIO = & codata_constant_type("electron-deuteron mass ratio", & 2.724437107629e-4_dp, 0.000000000047e-4_dp, & "") !! electron-deuteron mass ratio type(codata_constant_type), parameter, public :: ELECTRON_G_FACTOR = & codata_constant_type("electron g factor", & -2.00231930436092_dp, 0.00000000000036_dp, & "") !! electron g factor type(codata_constant_type), parameter, public :: ELECTRON_GYROMAG_RATIO = & codata_constant_type("electron gyromag. ratio", & 1.76085962784e11_dp, 0.00000000055e11_dp, & "s^-1 T^-1") !! electron gyromag. ratio type(codata_constant_type), parameter, public :: ELECTRON_GYROMAG_RATIO_IN_MHZ_T = & codata_constant_type("electron gyromag. ratio in MHz/T", & 28024.9513861_dp, 0.0000087_dp, & "MHz T^-1") !! electron gyromag. ratio in MHz/T type(codata_constant_type), parameter, public :: ELECTRON_HELION_MASS_RATIO = & codata_constant_type("electron-helion mass ratio", & 1.819543074649e-4_dp, 0.000000000053e-4_dp, & "") !! electron-helion mass ratio type(codata_constant_type), parameter, public :: ELECTRON_MAG_MOM = & codata_constant_type("electron mag. mom.", & -9.2847646917e-24_dp, 0.0000000029e-24_dp, & "J T^-1") !! electron mag. mom. type(codata_constant_type), parameter, public :: ELECTRON_MAG_MOM_ANOMALY = & codata_constant_type("electron mag. mom. anomaly", & 1.15965218046e-3_dp, 0.00000000018e-3_dp, & "") !! electron mag. mom. anomaly type(codata_constant_type), parameter, public :: ELECTRON_MAG_MOM_TO_BOHR_MAGNETON_RATIO = & codata_constant_type("electron mag. mom. to Bohr magneton ratio", & -1.00115965218046_dp, 0.00000000000018_dp, & "") !! electron mag. mom. to Bohr magneton ratio type(codata_constant_type), parameter, public :: ELECTRON_MAG_MOM_TO_NUCLEAR_MAGNETON_RATIO = & codata_constant_type("electron mag. mom. to nuclear magneton ratio", & -1838.281971877_dp, 0.000000032_dp, & "") !! electron mag. mom. to nuclear magneton ratio type(codata_constant_type), parameter, public :: ELECTRON_MASS = & codata_constant_type("electron mass", & 9.1093837139e-31_dp, 0.0000000028e-31_dp, & "kg") !! electron mass type(codata_constant_type), parameter, public :: ELECTRON_MASS_ENERGY_EQUIVALENT = & codata_constant_type("electron mass energy equivalent", & 8.1871057880e-14_dp, 0.0000000026e-14_dp, & "J") !! electron mass energy equivalent type(codata_constant_type), parameter, public :: ELECTRON_MASS_ENERGY_EQUIVALENT_IN_MEV = & codata_constant_type("electron mass energy equivalent in MeV", & 0.51099895069_dp, 0.00000000016_dp, & "MeV") !! electron mass energy equivalent in MeV type(codata_constant_type), parameter, public :: ELECTRON_MASS_IN_U = & codata_constant_type("electron mass in u", & 5.485799090441e-4_dp, 0.000000000097e-4_dp, & "u") !! electron mass in u type(codata_constant_type), parameter, public :: ELECTRON_MOLAR_MASS = & codata_constant_type("electron molar mass", & 5.4857990962e-7_dp, 0.0000000017e-7_dp, & "kg mol^-1") !! electron molar mass type(codata_constant_type), parameter, public :: ELECTRON_MUON_MAG_MOM_RATIO = & codata_constant_type("electron-muon mag. mom. ratio", & 206.7669881_dp, 0.0000046_dp, & "") !! electron-muon mag. mom. ratio type(codata_constant_type), parameter, public :: ELECTRON_MUON_MASS_RATIO = & codata_constant_type("electron-muon mass ratio", & 4.83633170e-3_dp, 0.00000011e-3_dp, & "") !! electron-muon mass ratio type(codata_constant_type), parameter, public :: ELECTRON_NEUTRON_MAG_MOM_RATIO = & codata_constant_type("electron-neutron mag. mom. ratio", & 960.92048_dp, 0.00023_dp, & "") !! electron-neutron mag. mom. ratio type(codata_constant_type), parameter, public :: ELECTRON_NEUTRON_MASS_RATIO = & codata_constant_type("electron-neutron mass ratio", & 5.4386734416e-4_dp, 0.0000000022e-4_dp, & "") !! electron-neutron mass ratio type(codata_constant_type), parameter, public :: ELECTRON_PROTON_MAG_MOM_RATIO = & codata_constant_type("electron-proton mag. mom. ratio", & -658.21068789_dp, 0.00000019_dp, & "") !! electron-proton mag. mom. ratio type(codata_constant_type), parameter, public :: ELECTRON_PROTON_MASS_RATIO = & codata_constant_type("electron-proton mass ratio", & 5.446170214889e-4_dp, 0.000000000094e-4_dp, & "") !! electron-proton mass ratio type(codata_constant_type), parameter, public :: ELECTRON_RELATIVE_ATOMIC_MASS = & codata_constant_type("electron relative atomic mass", & 5.485799090441e-4_dp, 0.000000000097e-4_dp, & "") !! electron relative atomic mass type(codata_constant_type), parameter, public :: ELECTRON_TAU_MASS_RATIO = & codata_constant_type("electron-tau mass ratio", & 2.87585e-4_dp, 0.00019e-4_dp, & "") !! electron-tau mass ratio type(codata_constant_type), parameter, public :: ELECTRON_TO_ALPHA_PARTICLE_MASS_RATIO = & codata_constant_type("electron to alpha particle mass ratio", & 1.370933554733e-4_dp, 0.000000000032e-4_dp, & "") !! electron to alpha particle mass ratio type(codata_constant_type), parameter, public :: ELECTRON_TO_SHIELDED_HELION_MAG_MOM_RATIO = & codata_constant_type("electron to shielded helion mag. mom. ratio", & 864.05823986_dp, 0.00000070_dp, & "") !! electron to shielded helion mag. mom. ratio type(codata_constant_type), parameter, public :: ELECTRON_TO_SHIELDED_PROTON_MAG_MOM_RATIO = & codata_constant_type("electron to shielded proton mag. mom. ratio", & -658.2275856_dp, 0.0000027_dp, & "") !! electron to shielded proton mag. mom. ratio type(codata_constant_type), parameter, public :: ELECTRON_TRITON_MASS_RATIO = & codata_constant_type("electron-triton mass ratio", & 1.819200062327e-4_dp, 0.000000000068e-4_dp, & "") !! electron-triton mass ratio type(codata_constant_type), parameter, public :: ELECTRON_VOLT = & codata_constant_type("electron volt", & 1.602176634e-19_dp, 0.0_dp, & "J") !! electron volt type(codata_constant_type), parameter, public :: ELECTRON_VOLT_ATOMIC_MASS_UNIT_RELATIONSHIP = & codata_constant_type("electron volt-atomic mass unit relationship", & 1.07354410083e-9_dp, 0.00000000033e-9_dp, & "u") !! electron volt-atomic mass unit relationship type(codata_constant_type), parameter, public :: ELECTRON_VOLT_HARTREE_RELATIONSHIP = & codata_constant_type("electron volt-hartree relationship", & 3.6749322175665e-2_dp, 0.0000000000040e-2_dp, & "E_h") !! electron volt-hartree relationship type(codata_constant_type), parameter, public :: ELECTRON_VOLT_HERTZ_RELATIONSHIP = & codata_constant_type("electron volt-hertz relationship", & 2.417989242e14_dp, 0.0_dp, & "Hz") !! electron volt-hertz relationship type(codata_constant_type), parameter, public :: ELECTRON_VOLT_INVERSE_METER_RELATIONSHIP = & codata_constant_type("electron volt-inverse meter relationship", & 8.065543937e5_dp, 0.0_dp, & "m^-1") !! electron volt-inverse meter relationship type(codata_constant_type), parameter, public :: ELECTRON_VOLT_JOULE_RELATIONSHIP = & codata_constant_type("electron volt-joule relationship", & 1.602176634e-19_dp, 0.0_dp, & "J") !! electron volt-joule relationship type(codata_constant_type), parameter, public :: ELECTRON_VOLT_KELVIN_RELATIONSHIP = & codata_constant_type("electron volt-kelvin relationship", & 1.160451812e4_dp, 0.0_dp, & "K") !! electron volt-kelvin relationship type(codata_constant_type), parameter, public :: ELECTRON_VOLT_KILOGRAM_RELATIONSHIP = & codata_constant_type("electron volt-kilogram relationship", & 1.782661921e-36_dp, 0.0_dp, & "kg") !! electron volt-kilogram relationship type(codata_constant_type), parameter, public :: ELEMENTARY_CHARGE = & codata_constant_type("elementary charge", & 1.602176634e-19_dp, 0.0_dp, & "C") !! elementary charge type(codata_constant_type), parameter, public :: ELEMENTARY_CHARGE_OVER_H_BAR = & codata_constant_type("elementary charge over h-bar", & 1.519267447e15_dp, 0.0_dp, & "A J^-1") !! elementary charge over h-bar type(codata_constant_type), parameter, public :: FARADAY_CONSTANT = & codata_constant_type("Faraday constant", & 96485.33212_dp, 0.0_dp, & "C mol^-1") !! Faraday constant type(codata_constant_type), parameter, public :: FERMI_COUPLING_CONSTANT = & codata_constant_type("Fermi coupling constant", & 1.1663787e-5_dp, 0.0000006e-5_dp, & "GeV^-2") !! Fermi coupling constant type(codata_constant_type), parameter, public :: FINE_STRUCTURE_CONSTANT = & codata_constant_type("fine-structure constant", & 7.2973525643e-3_dp, 0.0000000011e-3_dp, & "") !! fine-structure constant type(codata_constant_type), parameter, public :: FIRST_RADIATION_CONSTANT = & codata_constant_type("first radiation constant", & 3.741771852e-16_dp, 0.0_dp, & "W m^2") !! first radiation constant type(codata_constant_type), parameter, public :: FIRST_RADIATION_CONSTANT_FOR_SPECTRAL_RADIANCE = & codata_constant_type("first radiation constant for spectral radiance", & 1.191042972e-16_dp, 0.0_dp, & "W m^2 sr^-1") !! first radiation constant for spectral radiance type(codata_constant_type), parameter, public :: HARTREE_ATOMIC_MASS_UNIT_RELATIONSHIP = & codata_constant_type("hartree-atomic mass unit relationship", & 2.92126231797e-8_dp, 0.00000000091e-8_dp, & "u") !! hartree-atomic mass unit relationship type(codata_constant_type), parameter, public :: HARTREE_ELECTRON_VOLT_RELATIONSHIP = & codata_constant_type("hartree-electron volt relationship", & 27.211386245981_dp, 0.000000000030_dp, & "eV") !! hartree-electron volt relationship type(codata_constant_type), parameter, public :: HARTREE_ENERGY = & codata_constant_type("Hartree energy", & 4.3597447222060e-18_dp, 0.0000000000048e-18_dp, & "J") !! Hartree energy type(codata_constant_type), parameter, public :: HARTREE_ENERGY_IN_EV = & codata_constant_type("Hartree energy in eV", & 27.211386245981_dp, 0.000000000030_dp, & "eV") !! Hartree energy in eV type(codata_constant_type), parameter, public :: HARTREE_HERTZ_RELATIONSHIP = & codata_constant_type("hartree-hertz relationship", & 6.5796839204999e15_dp, 0.0000000000072e15_dp, & "Hz") !! hartree-hertz relationship type(codata_constant_type), parameter, public :: HARTREE_INVERSE_METER_RELATIONSHIP = & codata_constant_type("hartree-inverse meter relationship", & 2.1947463136314e7_dp, 0.0000000000024e7_dp, & "m^-1") !! hartree-inverse meter relationship type(codata_constant_type), parameter, public :: HARTREE_JOULE_RELATIONSHIP = & codata_constant_type("hartree-joule relationship", & 4.3597447222060e-18_dp, 0.0000000000048e-18_dp, & "J") !! hartree-joule relationship type(codata_constant_type), parameter, public :: HARTREE_KELVIN_RELATIONSHIP = & codata_constant_type("hartree-kelvin relationship", & 3.1577502480398e5_dp, 0.0000000000034e5_dp, & "K") !! hartree-kelvin relationship type(codata_constant_type), parameter, public :: HARTREE_KILOGRAM_RELATIONSHIP = & codata_constant_type("hartree-kilogram relationship", & 4.8508702095419e-35_dp, 0.0000000000053e-35_dp, & "kg") !! hartree-kilogram relationship type(codata_constant_type), parameter, public :: HELION_ELECTRON_MASS_RATIO = & codata_constant_type("helion-electron mass ratio", & 5495.88527984_dp, 0.00000016_dp, & "") !! helion-electron mass ratio type(codata_constant_type), parameter, public :: HELION_G_FACTOR = & codata_constant_type("helion g factor", & -4.2552506995_dp, 0.0000000034_dp, & "") !! helion g factor type(codata_constant_type), parameter, public :: HELION_MAG_MOM = & codata_constant_type("helion mag. mom.", & -1.07461755198e-26_dp, 0.00000000093e-26_dp, & "J T^-1") !! helion mag. mom. type(codata_constant_type), parameter, public :: HELION_MAG_MOM_TO_BOHR_MAGNETON_RATIO = & codata_constant_type("helion mag. mom. to Bohr magneton ratio", & -1.15874098083e-3_dp, 0.00000000094e-3_dp, & "") !! helion mag. mom. to Bohr magneton ratio type(codata_constant_type), parameter, public :: HELION_MAG_MOM_TO_NUCLEAR_MAGNETON_RATIO = & codata_constant_type("helion mag. mom. to nuclear magneton ratio", & -2.1276253498_dp, 0.0000000017_dp, & "") !! helion mag. mom. to nuclear magneton ratio type(codata_constant_type), parameter, public :: HELION_MASS = & codata_constant_type("helion mass", & 5.0064127862e-27_dp, 0.0000000016e-27_dp, & "kg") !! helion mass type(codata_constant_type), parameter, public :: HELION_MASS_ENERGY_EQUIVALENT = & codata_constant_type("helion mass energy equivalent", & 4.4995394185e-10_dp, 0.0000000014e-10_dp, & "J") !! helion mass energy equivalent type(codata_constant_type), parameter, public :: HELION_MASS_ENERGY_EQUIVALENT_IN_MEV = & codata_constant_type("helion mass energy equivalent in MeV", & 2808.39161112_dp, 0.00000088_dp, & "MeV") !! helion mass energy equivalent in MeV type(codata_constant_type), parameter, public :: HELION_MASS_IN_U = & codata_constant_type("helion mass in u", & 3.014932246932_dp, 0.000000000074_dp, & "u") !! helion mass in u type(codata_constant_type), parameter, public :: HELION_MOLAR_MASS = & codata_constant_type("helion molar mass", & 3.01493225010e-3_dp, 0.00000000094e-3_dp, & "kg mol^-1") !! helion molar mass type(codata_constant_type), parameter, public :: HELION_PROTON_MASS_RATIO = & codata_constant_type("helion-proton mass ratio", & 2.993152671552_dp, 0.000000000070_dp, & "") !! helion-proton mass ratio type(codata_constant_type), parameter, public :: HELION_RELATIVE_ATOMIC_MASS = & codata_constant_type("helion relative atomic mass", & 3.014932246932_dp, 0.000000000074_dp, & "") !! helion relative atomic mass type(codata_constant_type), parameter, public :: HELION_SHIELDING_SHIFT = & codata_constant_type("helion shielding shift", & 5.9967029e-5_dp, 0.0000023e-5_dp, & "") !! helion shielding shift type(codata_constant_type), parameter, public :: HERTZ_ATOMIC_MASS_UNIT_RELATIONSHIP = & codata_constant_type("hertz-atomic mass unit relationship", & 4.4398216590e-24_dp, 0.0000000014e-24_dp, & "u") !! hertz-atomic mass unit relationship type(codata_constant_type), parameter, public :: HERTZ_ELECTRON_VOLT_RELATIONSHIP = & codata_constant_type("hertz-electron volt relationship", & 4.135667696e-15_dp, 0.0_dp, & "eV") !! hertz-electron volt relationship type(codata_constant_type), parameter, public :: HERTZ_HARTREE_RELATIONSHIP = & codata_constant_type("hertz-hartree relationship", & 1.5198298460574e-16_dp, 0.0000000000017e-16_dp, & "E_h") !! hertz-hartree relationship type(codata_constant_type), parameter, public :: HERTZ_INVERSE_METER_RELATIONSHIP = & codata_constant_type("hertz-inverse meter relationship", & 3.335640951e-9_dp, 0.0_dp, & "m^-1") !! hertz-inverse meter relationship type(codata_constant_type), parameter, public :: HERTZ_JOULE_RELATIONSHIP = & codata_constant_type("hertz-joule relationship", & 6.62607015e-34_dp, 0.0_dp, & "J") !! hertz-joule relationship type(codata_constant_type), parameter, public :: HERTZ_KELVIN_RELATIONSHIP = & codata_constant_type("hertz-kelvin relationship", & 4.799243073e-11_dp, 0.0_dp, & "K") !! hertz-kelvin relationship type(codata_constant_type), parameter, public :: HERTZ_KILOGRAM_RELATIONSHIP = & codata_constant_type("hertz-kilogram relationship", & 7.372497323e-51_dp, 0.0_dp, & "kg") !! hertz-kilogram relationship type(codata_constant_type), parameter, public :: HYPERFINE_TRANSITION_FREQUENCY_OF_CS_133 = & codata_constant_type("hyperfine transition frequency of Cs-133", & 9192631770_dp, 0.0_dp, & "Hz") !! hyperfine transition frequency of Cs-133 type(codata_constant_type), parameter, public :: INVERSE_FINE_STRUCTURE_CONSTANT = & codata_constant_type("inverse fine-structure constant", & 137.035999177_dp, 0.000000021_dp, & "") !! inverse fine-structure constant type(codata_constant_type), parameter, public :: INVERSE_METER_ATOMIC_MASS_UNIT_RELATIONSHIP = & codata_constant_type("inverse meter-atomic mass unit relationship", & 1.33102504824e-15_dp, 0.00000000041e-15_dp, & "u") !! inverse meter-atomic mass unit relationship type(codata_constant_type), parameter, public :: INVERSE_METER_ELECTRON_VOLT_RELATIONSHIP = & codata_constant_type("inverse meter-electron volt relationship", & 1.239841984e-6_dp, 0.0_dp, & "eV") !! inverse meter-electron volt relationship type(codata_constant_type), parameter, public :: INVERSE_METER_HARTREE_RELATIONSHIP = & codata_constant_type("inverse meter-hartree relationship", & 4.5563352529132e-8_dp, 0.0000000000050e-8_dp, & "E_h") !! inverse meter-hartree relationship type(codata_constant_type), parameter, public :: INVERSE_METER_HERTZ_RELATIONSHIP = & codata_constant_type("inverse meter-hertz relationship", & 299792458_dp, 0.0_dp, & "Hz") !! inverse meter-hertz relationship type(codata_constant_type), parameter, public :: INVERSE_METER_JOULE_RELATIONSHIP = & codata_constant_type("inverse meter-joule relationship", & 1.986445857e-25_dp, 0.0_dp, & "J") !! inverse meter-joule relationship type(codata_constant_type), parameter, public :: INVERSE_METER_KELVIN_RELATIONSHIP = & codata_constant_type("inverse meter-kelvin relationship", & 1.438776877e-2_dp, 0.0_dp, & "K") !! inverse meter-kelvin relationship type(codata_constant_type), parameter, public :: INVERSE_METER_KILOGRAM_RELATIONSHIP = & codata_constant_type("inverse meter-kilogram relationship", & 2.210219094e-42_dp, 0.0_dp, & "kg") !! inverse meter-kilogram relationship type(codata_constant_type), parameter, public :: INVERSE_OF_CONDUCTANCE_QUANTUM = & codata_constant_type("inverse of conductance quantum", & 12906.40372_dp, 0.0_dp, & "ohm") !! inverse of conductance quantum type(codata_constant_type), parameter, public :: JOSEPHSON_CONSTANT = & codata_constant_type("Josephson constant", & 483597.8484e9_dp, 0.0_dp, & "Hz V^-1") !! Josephson constant type(codata_constant_type), parameter, public :: JOULE_ATOMIC_MASS_UNIT_RELATIONSHIP = & codata_constant_type("joule-atomic mass unit relationship", & 6.7005352471e9_dp, 0.0000000021e9_dp, & "u") !! joule-atomic mass unit relationship type(codata_constant_type), parameter, public :: JOULE_ELECTRON_VOLT_RELATIONSHIP = & codata_constant_type("joule-electron volt relationship", & 6.241509074e18_dp, 0.0_dp, & "eV") !! joule-electron volt relationship type(codata_constant_type), parameter, public :: JOULE_HARTREE_RELATIONSHIP = & codata_constant_type("joule-hartree relationship", & 2.2937122783969e17_dp, 0.0000000000025e17_dp, & "E_h") !! joule-hartree relationship type(codata_constant_type), parameter, public :: JOULE_HERTZ_RELATIONSHIP = & codata_constant_type("joule-hertz relationship", & 1.509190179e33_dp, 0.0_dp, & "Hz") !! joule-hertz relationship type(codata_constant_type), parameter, public :: JOULE_INVERSE_METER_RELATIONSHIP = & codata_constant_type("joule-inverse meter relationship", & 5.034116567e24_dp, 0.0_dp, & "m^-1") !! joule-inverse meter relationship type(codata_constant_type), parameter, public :: JOULE_KELVIN_RELATIONSHIP = & codata_constant_type("joule-kelvin relationship", & 7.242970516e22_dp, 0.0_dp, & "K") !! joule-kelvin relationship type(codata_constant_type), parameter, public :: JOULE_KILOGRAM_RELATIONSHIP = & codata_constant_type("joule-kilogram relationship", & 1.112650056e-17_dp, 0.0_dp, & "kg") !! joule-kilogram relationship type(codata_constant_type), parameter, public :: KELVIN_ATOMIC_MASS_UNIT_RELATIONSHIP = & codata_constant_type("kelvin-atomic mass unit relationship", & 9.2510872884e-14_dp, 0.0000000029e-14_dp, & "u") !! kelvin-atomic mass unit relationship type(codata_constant_type), parameter, public :: KELVIN_ELECTRON_VOLT_RELATIONSHIP = & codata_constant_type("kelvin-electron volt relationship", & 8.617333262e-5_dp, 0.0_dp, & "eV") !! kelvin-electron volt relationship type(codata_constant_type), parameter, public :: KELVIN_HARTREE_RELATIONSHIP = & codata_constant_type("kelvin-hartree relationship", & 3.1668115634564e-6_dp, 0.0000000000035e-6_dp, & "E_h") !! kelvin-hartree relationship type(codata_constant_type), parameter, public :: KELVIN_HERTZ_RELATIONSHIP = & codata_constant_type("kelvin-hertz relationship", & 2.083661912e10_dp, 0.0_dp, & "Hz") !! kelvin-hertz relationship type(codata_constant_type), parameter, public :: KELVIN_INVERSE_METER_RELATIONSHIP = & codata_constant_type("kelvin-inverse meter relationship", & 69.50348004_dp, 0.0_dp, & "m^-1") !! kelvin-inverse meter relationship type(codata_constant_type), parameter, public :: KELVIN_JOULE_RELATIONSHIP = & codata_constant_type("kelvin-joule relationship", & 1.380649e-23_dp, 0.0_dp, & "J") !! kelvin-joule relationship type(codata_constant_type), parameter, public :: KELVIN_KILOGRAM_RELATIONSHIP = & codata_constant_type("kelvin-kilogram relationship", & 1.536179187e-40_dp, 0.0_dp, & "kg") !! kelvin-kilogram relationship type(codata_constant_type), parameter, public :: KILOGRAM_ATOMIC_MASS_UNIT_RELATIONSHIP = & codata_constant_type("kilogram-atomic mass unit relationship", & 6.0221407537e26_dp, 0.0000000019e26_dp, & "u") !! kilogram-atomic mass unit relationship type(codata_constant_type), parameter, public :: KILOGRAM_ELECTRON_VOLT_RELATIONSHIP = & codata_constant_type("kilogram-electron volt relationship", & 5.609588603e35_dp, 0.0_dp, & "eV") !! kilogram-electron volt relationship type(codata_constant_type), parameter, public :: KILOGRAM_HARTREE_RELATIONSHIP = & codata_constant_type("kilogram-hartree relationship", & 2.0614857887415e34_dp, 0.0000000000022e34_dp, & "E_h") !! kilogram-hartree relationship type(codata_constant_type), parameter, public :: KILOGRAM_HERTZ_RELATIONSHIP = & codata_constant_type("kilogram-hertz relationship", & 1.356392489e50_dp, 0.0_dp, & "Hz") !! kilogram-hertz relationship type(codata_constant_type), parameter, public :: KILOGRAM_INVERSE_METER_RELATIONSHIP = & codata_constant_type("kilogram-inverse meter relationship", & 4.524438335e41_dp, 0.0_dp, & "m^-1") !! kilogram-inverse meter relationship type(codata_constant_type), parameter, public :: KILOGRAM_JOULE_RELATIONSHIP = & codata_constant_type("kilogram-joule relationship", & 8.987551787e16_dp, 0.0_dp, & "J") !! kilogram-joule relationship type(codata_constant_type), parameter, public :: KILOGRAM_KELVIN_RELATIONSHIP = & codata_constant_type("kilogram-kelvin relationship", & 6.509657260e39_dp, 0.0_dp, & "K") !! kilogram-kelvin relationship type(codata_constant_type), parameter, public :: LATTICE_PARAMETER_OF_SILICON = & codata_constant_type("lattice parameter of silicon", & 5.431020511e-10_dp, 0.000000089e-10_dp, & "m") !! lattice parameter of silicon type(codata_constant_type), parameter, public :: LATTICE_SPACING_OF_IDEAL_SI_220 = & codata_constant_type("lattice spacing of ideal Si (220)", & 1.920155716e-10_dp, 0.000000032e-10_dp, & "m") !! lattice spacing of ideal Si (220) type(codata_constant_type), parameter, public :: LOSCHMIDT_CONSTANT_273_15_K_100_KPA = & codata_constant_type("Loschmidt constant (273.15 K, 100 kPa)", & 2.651645804e25_dp, 0.0_dp, & "m^-3") !! Loschmidt constant (273.15 K, 100 kPa) type(codata_constant_type), parameter, public :: LOSCHMIDT_CONSTANT_273_15_K_101_325_KPA = & codata_constant_type("Loschmidt constant (273.15 K, 101.325 kPa)", & 2.686780111e25_dp, 0.0_dp, & "m^-3") !! Loschmidt constant (273.15 K, 101.325 kPa) type(codata_constant_type), parameter, public :: LUMINOUS_EFFICACY = & codata_constant_type("luminous efficacy", & 683_dp, 0.0_dp, & "lm W^-1") !! luminous efficacy type(codata_constant_type), parameter, public :: MAG_FLUX_QUANTUM = & codata_constant_type("mag. flux quantum", & 2.067833848e-15_dp, 0.0_dp, & "Wb") !! mag. flux quantum type(codata_constant_type), parameter, public :: MOLAR_GAS_CONSTANT = & codata_constant_type("molar gas constant", & 8.314462618_dp, 0.0_dp, & "J mol^-1 K^-1") !! molar gas constant type(codata_constant_type), parameter, public :: MOLAR_MASS_CONSTANT = & codata_constant_type("molar mass constant", & 1.00000000105e-3_dp, 0.00000000031e-3_dp, & "kg mol^-1") !! molar mass constant type(codata_constant_type), parameter, public :: MOLAR_MASS_OF_CARBON_12 = & codata_constant_type("molar mass of carbon-12", & 12.0000000126e-3_dp, 0.0000000037e-3_dp, & "kg mol^-1") !! molar mass of carbon-12 type(codata_constant_type), parameter, public :: MOLAR_PLANCK_CONSTANT = & codata_constant_type("molar Planck constant", & 3.990312712e-10_dp, 0.0_dp, & "J Hz^-1 mol^-1") !! molar Planck constant type(codata_constant_type), parameter, public :: MOLAR_VOLUME_OF_IDEAL_GAS_273_15_K_100_KPA = & codata_constant_type("molar volume of ideal gas (273.15 K, 100 kPa)", & 22.71095464e-3_dp, 0.0_dp, & "m^3 mol^-1") !! molar volume of ideal gas (273.15 K, 100 kPa) type(codata_constant_type), parameter, public :: MOLAR_VOLUME_OF_IDEAL_GAS_273_15_K_101_325_KPA = & codata_constant_type("molar volume of ideal gas (273.15 K, 101.325 kPa)", & 22.41396954e-3_dp, 0.0_dp, & "m^3 mol^-1") !! molar volume of ideal gas (273.15 K, 101.325 kPa) type(codata_constant_type), parameter, public :: MOLAR_VOLUME_OF_SILICON = & codata_constant_type("molar volume of silicon", & 1.205883199e-5_dp, 0.000000060e-5_dp, & "m^3 mol^-1") !! molar volume of silicon type(codata_constant_type), parameter, public :: MOLYBDENUM_X_UNIT = & codata_constant_type("Molybdenum x unit", & 1.00209952e-13_dp, 0.00000053e-13_dp, & "m") !! Molybdenum x unit type(codata_constant_type), parameter, public :: MUON_COMPTON_WAVELENGTH = & codata_constant_type("muon Compton wavelength", & 1.173444110e-14_dp, 0.000000026e-14_dp, & "m") !! muon Compton wavelength type(codata_constant_type), parameter, public :: MUON_ELECTRON_MASS_RATIO = & codata_constant_type("muon-electron mass ratio", & 206.7682827_dp, 0.0000046_dp, & "") !! muon-electron mass ratio type(codata_constant_type), parameter, public :: MUON_G_FACTOR = & codata_constant_type("muon g factor", & -2.00233184123_dp, 0.00000000082_dp, & "") !! muon g factor type(codata_constant_type), parameter, public :: MUON_MAG_MOM = & codata_constant_type("muon mag. mom.", & -4.49044830e-26_dp, 0.00000010e-26_dp, & "J T^-1") !! muon mag. mom. type(codata_constant_type), parameter, public :: MUON_MAG_MOM_ANOMALY = & codata_constant_type("muon mag. mom. anomaly", & 1.16592062e-3_dp, 0.00000041e-3_dp, & "") !! muon mag. mom. anomaly type(codata_constant_type), parameter, public :: MUON_MAG_MOM_TO_BOHR_MAGNETON_RATIO = & codata_constant_type("muon mag. mom. to Bohr magneton ratio", & -4.84197048e-3_dp, 0.00000011e-3_dp, & "") !! muon mag. mom. to Bohr magneton ratio type(codata_constant_type), parameter, public :: MUON_MAG_MOM_TO_NUCLEAR_MAGNETON_RATIO = & codata_constant_type("muon mag. mom. to nuclear magneton ratio", & -8.89059704_dp, 0.00000020_dp, & "") !! muon mag. mom. to nuclear magneton ratio type(codata_constant_type), parameter, public :: MUON_MASS = & codata_constant_type("muon mass", & 1.883531627e-28_dp, 0.000000042e-28_dp, & "kg") !! muon mass type(codata_constant_type), parameter, public :: MUON_MASS_ENERGY_EQUIVALENT = & codata_constant_type("muon mass energy equivalent", & 1.692833804e-11_dp, 0.000000038e-11_dp, & "J") !! muon mass energy equivalent type(codata_constant_type), parameter, public :: MUON_MASS_ENERGY_EQUIVALENT_IN_MEV = & codata_constant_type("muon mass energy equivalent in MeV", & 105.6583755_dp, 0.0000023_dp, & "MeV") !! muon mass energy equivalent in MeV type(codata_constant_type), parameter, public :: MUON_MASS_IN_U = & codata_constant_type("muon mass in u", & 0.1134289257_dp, 0.0000000025_dp, & "u") !! muon mass in u type(codata_constant_type), parameter, public :: MUON_MOLAR_MASS = & codata_constant_type("muon molar mass", & 1.134289258e-4_dp, 0.000000025e-4_dp, & "kg mol^-1") !! muon molar mass type(codata_constant_type), parameter, public :: MUON_NEUTRON_MASS_RATIO = & codata_constant_type("muon-neutron mass ratio", & 0.1124545168_dp, 0.0000000025_dp, & "") !! muon-neutron mass ratio type(codata_constant_type), parameter, public :: MUON_PROTON_MAG_MOM_RATIO = & codata_constant_type("muon-proton mag. mom. ratio", & -3.183345146_dp, 0.000000071_dp, & "") !! muon-proton mag. mom. ratio type(codata_constant_type), parameter, public :: MUON_PROTON_MASS_RATIO = & codata_constant_type("muon-proton mass ratio", & 0.1126095262_dp, 0.0000000025_dp, & "") !! muon-proton mass ratio type(codata_constant_type), parameter, public :: MUON_TAU_MASS_RATIO = & codata_constant_type("muon-tau mass ratio", & 5.94635e-2_dp, 0.00040e-2_dp, & "") !! muon-tau mass ratio type(codata_constant_type), parameter, public :: NATURAL_UNIT_OF_ACTION = & codata_constant_type("natural unit of action", & 1.054571817e-34_dp, 0.0_dp, & "J s") !! natural unit of action type(codata_constant_type), parameter, public :: NATURAL_UNIT_OF_ACTION_IN_EV_S = & codata_constant_type("natural unit of action in eV s", & 6.582119569e-16_dp, 0.0_dp, & "eV s") !! natural unit of action in eV s type(codata_constant_type), parameter, public :: NATURAL_UNIT_OF_ENERGY = & codata_constant_type("natural unit of energy", & 8.1871057880e-14_dp, 0.0000000026e-14_dp, & "J") !! natural unit of energy type(codata_constant_type), parameter, public :: NATURAL_UNIT_OF_ENERGY_IN_MEV = & codata_constant_type("natural unit of energy in MeV", & 0.51099895069_dp, 0.00000000016_dp, & "MeV") !! natural unit of energy in MeV type(codata_constant_type), parameter, public :: NATURAL_UNIT_OF_LENGTH = & codata_constant_type("natural unit of length", & 3.8615926744e-13_dp, 0.0000000012e-13_dp, & "m") !! natural unit of length type(codata_constant_type), parameter, public :: NATURAL_UNIT_OF_MASS = & codata_constant_type("natural unit of mass", & 9.1093837139e-31_dp, 0.0000000028e-31_dp, & "kg") !! natural unit of mass type(codata_constant_type), parameter, public :: NATURAL_UNIT_OF_MOMENTUM = & codata_constant_type("natural unit of momentum", & 2.73092453446e-22_dp, 0.00000000085e-22_dp, & "kg m s^-1") !! natural unit of momentum type(codata_constant_type), parameter, public :: NATURAL_UNIT_OF_MOMENTUM_IN_MEV_C = & codata_constant_type("natural unit of momentum in MeV/c", & 0.51099895069_dp, 0.00000000016_dp, & "MeV/c") !! natural unit of momentum in MeV/c type(codata_constant_type), parameter, public :: NATURAL_UNIT_OF_TIME = & codata_constant_type("natural unit of time", & 1.28808866644e-21_dp, 0.00000000040e-21_dp, & "s") !! natural unit of time type(codata_constant_type), parameter, public :: NATURAL_UNIT_OF_VELOCITY = & codata_constant_type("natural unit of velocity", & 299792458_dp, 0.0_dp, & "m s^-1") !! natural unit of velocity type(codata_constant_type), parameter, public :: NEUTRON_COMPTON_WAVELENGTH = & codata_constant_type("neutron Compton wavelength", & 1.31959090382e-15_dp, 0.00000000067e-15_dp, & "m") !! neutron Compton wavelength type(codata_constant_type), parameter, public :: NEUTRON_ELECTRON_MAG_MOM_RATIO = & codata_constant_type("neutron-electron mag. mom. ratio", & 1.04066884e-3_dp, 0.00000024e-3_dp, & "") !! neutron-electron mag. mom. ratio type(codata_constant_type), parameter, public :: NEUTRON_ELECTRON_MASS_RATIO = & codata_constant_type("neutron-electron mass ratio", & 1838.68366200_dp, 0.00000074_dp, & "") !! neutron-electron mass ratio type(codata_constant_type), parameter, public :: NEUTRON_G_FACTOR = & codata_constant_type("neutron g factor", & -3.82608552_dp, 0.00000090_dp, & "") !! neutron g factor type(codata_constant_type), parameter, public :: NEUTRON_GYROMAG_RATIO = & codata_constant_type("neutron gyromag. ratio", & 1.83247174e8_dp, 0.00000043e8_dp, & "s^-1 T^-1") !! neutron gyromag. ratio type(codata_constant_type), parameter, public :: NEUTRON_GYROMAG_RATIO_IN_MHZ_T = & codata_constant_type("neutron gyromag. ratio in MHz/T", & 29.1646935_dp, 0.0000069_dp, & "MHz T^-1") !! neutron gyromag. ratio in MHz/T type(codata_constant_type), parameter, public :: NEUTRON_MAG_MOM = & codata_constant_type("neutron mag. mom.", & -9.6623653e-27_dp, 0.0000023e-27_dp, & "J T^-1") !! neutron mag. mom. type(codata_constant_type), parameter, public :: NEUTRON_MAG_MOM_TO_BOHR_MAGNETON_RATIO = & codata_constant_type("neutron mag. mom. to Bohr magneton ratio", & -1.04187565e-3_dp, 0.00000025e-3_dp, & "") !! neutron mag. mom. to Bohr magneton ratio type(codata_constant_type), parameter, public :: NEUTRON_MAG_MOM_TO_NUCLEAR_MAGNETON_RATIO = & codata_constant_type("neutron mag. mom. to nuclear magneton ratio", & -1.91304276_dp, 0.00000045_dp, & "") !! neutron mag. mom. to nuclear magneton ratio type(codata_constant_type), parameter, public :: NEUTRON_MASS = & codata_constant_type("neutron mass", & 1.67492750056e-27_dp, 0.00000000085e-27_dp, & "kg") !! neutron mass type(codata_constant_type), parameter, public :: NEUTRON_MASS_ENERGY_EQUIVALENT = & codata_constant_type("neutron mass energy equivalent", & 1.50534976514e-10_dp, 0.00000000076e-10_dp, & "J") !! neutron mass energy equivalent type(codata_constant_type), parameter, public :: NEUTRON_MASS_ENERGY_EQUIVALENT_IN_MEV = & codata_constant_type("neutron mass energy equivalent in MeV", & 939.56542194_dp, 0.00000048_dp, & "MeV") !! neutron mass energy equivalent in MeV type(codata_constant_type), parameter, public :: NEUTRON_MASS_IN_U = & codata_constant_type("neutron mass in u", & 1.00866491606_dp, 0.00000000040_dp, & "u") !! neutron mass in u type(codata_constant_type), parameter, public :: NEUTRON_MOLAR_MASS = & codata_constant_type("neutron molar mass", & 1.00866491712e-3_dp, 0.00000000051e-3_dp, & "kg mol^-1") !! neutron molar mass type(codata_constant_type), parameter, public :: NEUTRON_MUON_MASS_RATIO = & codata_constant_type("neutron-muon mass ratio", & 8.89248408_dp, 0.00000020_dp, & "") !! neutron-muon mass ratio type(codata_constant_type), parameter, public :: NEUTRON_PROTON_MAG_MOM_RATIO = & codata_constant_type("neutron-proton mag. mom. ratio", & -0.68497935_dp, 0.00000016_dp, & "") !! neutron-proton mag. mom. ratio type(codata_constant_type), parameter, public :: NEUTRON_PROTON_MASS_DIFFERENCE = & codata_constant_type("neutron-proton mass difference", & 2.30557461e-30_dp, 0.00000067e-30_dp, & "kg") !! neutron-proton mass difference type(codata_constant_type), parameter, public :: NEUTRON_PROTON_MASS_DIFFERENCE_ENERGY_EQUIVALENT = & codata_constant_type("neutron-proton mass difference energy equivalent", & 2.07214712e-13_dp, 0.00000060e-13_dp, & "J") !! neutron-proton mass difference energy equivalent type(codata_constant_type), parameter, public :: NEUTRON_PROTON_MASS_DIFFERENCE_ENERGY_EQUIVALENT_IN_MEV = & codata_constant_type("neutron-proton mass difference energy equivalent in MeV", & 1.29333251_dp, 0.00000038_dp, & "MeV") !! neutron-proton mass difference energy equivalent in MeV type(codata_constant_type), parameter, public :: NEUTRON_PROTON_MASS_DIFFERENCE_IN_U = & codata_constant_type("neutron-proton mass difference in u", & 1.38844948e-3_dp, 0.00000040e-3_dp, & "u") !! neutron-proton mass difference in u type(codata_constant_type), parameter, public :: NEUTRON_PROTON_MASS_RATIO = & codata_constant_type("neutron-proton mass ratio", & 1.00137841946_dp, 0.00000000040_dp, & "") !! neutron-proton mass ratio type(codata_constant_type), parameter, public :: NEUTRON_RELATIVE_ATOMIC_MASS = & codata_constant_type("neutron relative atomic mass", & 1.00866491606_dp, 0.00000000040_dp, & "") !! neutron relative atomic mass type(codata_constant_type), parameter, public :: NEUTRON_TAU_MASS_RATIO = & codata_constant_type("neutron-tau mass ratio", & 0.528779_dp, 0.000036_dp, & "") !! neutron-tau mass ratio type(codata_constant_type), parameter, public :: NEUTRON_TO_SHIELDED_PROTON_MAG_MOM_RATIO = & codata_constant_type("neutron to shielded proton mag. mom. ratio", & -0.68499694_dp, 0.00000016_dp, & "") !! neutron to shielded proton mag. mom. ratio type(codata_constant_type), parameter, public :: NEWTONIAN_CONSTANT_OF_GRAVITATION = & codata_constant_type("Newtonian constant of gravitation", & 6.67430e-11_dp, 0.00015e-11_dp, & "m^3 kg^-1 s^-2") !! Newtonian constant of gravitation type(codata_constant_type), parameter, public :: NEWTONIAN_CONSTANT_OF_GRAVITATION_OVER_H_BAR_C = & codata_constant_type("Newtonian constant of gravitation over h-bar c", & 6.70883e-39_dp, 0.00015e-39_dp, & "(GeV/c^2)^-2") !! Newtonian constant of gravitation over h-bar c type(codata_constant_type), parameter, public :: NUCLEAR_MAGNETON = & codata_constant_type("nuclear magneton", & 5.0507837393e-27_dp, 0.0000000016e-27_dp, & "J T^-1") !! nuclear magneton type(codata_constant_type), parameter, public :: NUCLEAR_MAGNETON_IN_EV_T = & codata_constant_type("nuclear magneton in eV/T", & 3.15245125417e-8_dp, 0.00000000098e-8_dp, & "eV T^-1") !! nuclear magneton in eV/T type(codata_constant_type), parameter, public :: NUCLEAR_MAGNETON_IN_INVERSE_METER_PER_TESLA = & codata_constant_type("nuclear magneton in inverse meter per tesla", & 2.54262341009e-2_dp, 0.00000000079e-2_dp, & "m^-1 T^-1") !! nuclear magneton in inverse meter per tesla type(codata_constant_type), parameter, public :: NUCLEAR_MAGNETON_IN_K_T = & codata_constant_type("nuclear magneton in K/T", & 3.6582677706e-4_dp, 0.0000000011e-4_dp, & "K T^-1") !! nuclear magneton in K/T type(codata_constant_type), parameter, public :: NUCLEAR_MAGNETON_IN_MHZ_T = & codata_constant_type("nuclear magneton in MHz/T", & 7.6225932188_dp, 0.0000000024_dp, & "MHz T^-1") !! nuclear magneton in MHz/T type(codata_constant_type), parameter, public :: PLANCK_CONSTANT = & codata_constant_type("Planck constant", & 6.62607015e-34_dp, 0.0_dp, & "J Hz^-1") !! Planck constant type(codata_constant_type), parameter, public :: PLANCK_CONSTANT_IN_EV_HZ = & codata_constant_type("Planck constant in eV/Hz", & 4.135667696e-15_dp, 0.0_dp, & "eV Hz^-1") !! Planck constant in eV/Hz type(codata_constant_type), parameter, public :: PLANCK_LENGTH = & codata_constant_type("Planck length", & 1.616255e-35_dp, 0.000018e-35_dp, & "m") !! Planck length type(codata_constant_type), parameter, public :: PLANCK_MASS = & codata_constant_type("Planck mass", & 2.176434e-8_dp, 0.000024e-8_dp, & "kg") !! Planck mass type(codata_constant_type), parameter, public :: PLANCK_MASS_ENERGY_EQUIVALENT_IN_GEV = & codata_constant_type("Planck mass energy equivalent in GeV", & 1.220890e19_dp, 0.000014e19_dp, & "GeV") !! Planck mass energy equivalent in GeV type(codata_constant_type), parameter, public :: PLANCK_TEMPERATURE = & codata_constant_type("Planck temperature", & 1.416784e32_dp, 0.000016e32_dp, & "K") !! Planck temperature type(codata_constant_type), parameter, public :: PLANCK_TIME = & codata_constant_type("Planck time", & 5.391247e-44_dp, 0.000060e-44_dp, & "s") !! Planck time type(codata_constant_type), parameter, public :: PROTON_CHARGE_TO_MASS_QUOTIENT = & codata_constant_type("proton charge to mass quotient", & 9.5788331430e7_dp, 0.0000000030e7_dp, & "C kg^-1") !! proton charge to mass quotient type(codata_constant_type), parameter, public :: PROTON_COMPTON_WAVELENGTH = & codata_constant_type("proton Compton wavelength", & 1.32140985360e-15_dp, 0.00000000041e-15_dp, & "m") !! proton Compton wavelength type(codata_constant_type), parameter, public :: PROTON_ELECTRON_MASS_RATIO = & codata_constant_type("proton-electron mass ratio", & 1836.152673426_dp, 0.000000032_dp, & "") !! proton-electron mass ratio type(codata_constant_type), parameter, public :: PROTON_G_FACTOR = & codata_constant_type("proton g factor", & 5.5856946893_dp, 0.0000000016_dp, & "") !! proton g factor type(codata_constant_type), parameter, public :: PROTON_GYROMAG_RATIO = & codata_constant_type("proton gyromag. ratio", & 2.6752218708e8_dp, 0.0000000011e8_dp, & "s^-1 T^-1") !! proton gyromag. ratio type(codata_constant_type), parameter, public :: PROTON_GYROMAG_RATIO_IN_MHZ_T = & codata_constant_type("proton gyromag. ratio in MHz/T", & 42.577478461_dp, 0.000000018_dp, & "MHz T^-1") !! proton gyromag. ratio in MHz/T type(codata_constant_type), parameter, public :: PROTON_MAG_MOM = & codata_constant_type("proton mag. mom.", & 1.41060679545e-26_dp, 0.00000000060e-26_dp, & "J T^-1") !! proton mag. mom. type(codata_constant_type), parameter, public :: PROTON_MAG_MOM_TO_BOHR_MAGNETON_RATIO = & codata_constant_type("proton mag. mom. to Bohr magneton ratio", & 1.52103220230e-3_dp, 0.00000000045e-3_dp, & "") !! proton mag. mom. to Bohr magneton ratio type(codata_constant_type), parameter, public :: PROTON_MAG_MOM_TO_NUCLEAR_MAGNETON_RATIO = & codata_constant_type("proton mag. mom. to nuclear magneton ratio", & 2.79284734463_dp, 0.00000000082_dp, & "") !! proton mag. mom. to nuclear magneton ratio type(codata_constant_type), parameter, public :: PROTON_MAG_SHIELDING_CORRECTION = & codata_constant_type("proton mag. shielding correction", & 2.56715e-5_dp, 0.00041e-5_dp, & "") !! proton mag. shielding correction type(codata_constant_type), parameter, public :: PROTON_MASS = & codata_constant_type("proton mass", & 1.67262192595e-27_dp, 0.00000000052e-27_dp, & "kg") !! proton mass type(codata_constant_type), parameter, public :: PROTON_MASS_ENERGY_EQUIVALENT = & codata_constant_type("proton mass energy equivalent", & 1.50327761802e-10_dp, 0.00000000047e-10_dp, & "J") !! proton mass energy equivalent type(codata_constant_type), parameter, public :: PROTON_MASS_ENERGY_EQUIVALENT_IN_MEV = & codata_constant_type("proton mass energy equivalent in MeV", & 938.27208943_dp, 0.00000029_dp, & "MeV") !! proton mass energy equivalent in MeV type(codata_constant_type), parameter, public :: PROTON_MASS_IN_U = & codata_constant_type("proton mass in u", & 1.0072764665789_dp, 0.0000000000083_dp, & "u") !! proton mass in u type(codata_constant_type), parameter, public :: PROTON_MOLAR_MASS = & codata_constant_type("proton molar mass", & 1.00727646764e-3_dp, 0.00000000031e-3_dp, & "kg mol^-1") !! proton molar mass type(codata_constant_type), parameter, public :: PROTON_MUON_MASS_RATIO = & codata_constant_type("proton-muon mass ratio", & 8.88024338_dp, 0.00000020_dp, & "") !! proton-muon mass ratio type(codata_constant_type), parameter, public :: PROTON_NEUTRON_MAG_MOM_RATIO = & codata_constant_type("proton-neutron mag. mom. ratio", & -1.45989802_dp, 0.00000034_dp, & "") !! proton-neutron mag. mom. ratio type(codata_constant_type), parameter, public :: PROTON_NEUTRON_MASS_RATIO = & codata_constant_type("proton-neutron mass ratio", & 0.99862347797_dp, 0.00000000040_dp, & "") !! proton-neutron mass ratio type(codata_constant_type), parameter, public :: PROTON_RELATIVE_ATOMIC_MASS = & codata_constant_type("proton relative atomic mass", & 1.0072764665789_dp, 0.0000000000083_dp, & "") !! proton relative atomic mass type(codata_constant_type), parameter, public :: PROTON_RMS_CHARGE_RADIUS = & codata_constant_type("proton rms charge radius", & 8.4075e-16_dp, 0.0064e-16_dp, & "m") !! proton rms charge radius type(codata_constant_type), parameter, public :: PROTON_TAU_MASS_RATIO = & codata_constant_type("proton-tau mass ratio", & 0.528051_dp, 0.000036_dp, & "") !! proton-tau mass ratio type(codata_constant_type), parameter, public :: QUANTUM_OF_CIRCULATION = & codata_constant_type("quantum of circulation", & 3.6369475467e-4_dp, 0.0000000011e-4_dp, & "m^2 s^-1") !! quantum of circulation type(codata_constant_type), parameter, public :: QUANTUM_OF_CIRCULATION_TIMES_2 = & codata_constant_type("quantum of circulation times 2", & 7.2738950934e-4_dp, 0.0000000023e-4_dp, & "m^2 s^-1") !! quantum of circulation times 2 type(codata_constant_type), parameter, public :: REDUCED_COMPTON_WAVELENGTH = & codata_constant_type("reduced Compton wavelength", & 3.8615926744e-13_dp, 0.0000000012e-13_dp, & "m") !! reduced Compton wavelength type(codata_constant_type), parameter, public :: REDUCED_MUON_COMPTON_WAVELENGTH = & codata_constant_type("reduced muon Compton wavelength", & 1.867594306e-15_dp, 0.000000042e-15_dp, & "m") !! reduced muon Compton wavelength type(codata_constant_type), parameter, public :: REDUCED_NEUTRON_COMPTON_WAVELENGTH = & codata_constant_type("reduced neutron Compton wavelength", & 2.1001941520e-16_dp, 0.0000000011e-16_dp, & "m") !! reduced neutron Compton wavelength type(codata_constant_type), parameter, public :: REDUCED_PLANCK_CONSTANT = & codata_constant_type("reduced Planck constant", & 1.054571817e-34_dp, 0.0_dp, & "J s") !! reduced Planck constant type(codata_constant_type), parameter, public :: REDUCED_PLANCK_CONSTANT_IN_EV_S = & codata_constant_type("reduced Planck constant in eV s", & 6.582119569e-16_dp, 0.0_dp, & "eV s") !! reduced Planck constant in eV s type(codata_constant_type), parameter, public :: REDUCED_PLANCK_CONSTANT_TIMES_C_IN_MEV_FM = & codata_constant_type("reduced Planck constant times c in MeV fm", & 197.3269804_dp, 0.0_dp, & "MeV fm") !! reduced Planck constant times c in MeV fm type(codata_constant_type), parameter, public :: REDUCED_PROTON_COMPTON_WAVELENGTH = & codata_constant_type("reduced proton Compton wavelength", & 2.10308910051e-16_dp, 0.00000000066e-16_dp, & "m") !! reduced proton Compton wavelength type(codata_constant_type), parameter, public :: REDUCED_TAU_COMPTON_WAVELENGTH = & codata_constant_type("reduced tau Compton wavelength", & 1.110538e-16_dp, 0.000075e-16_dp, & "m") !! reduced tau Compton wavelength type(codata_constant_type), parameter, public :: RYDBERG_CONSTANT = & codata_constant_type("Rydberg constant", & 10973731.568157_dp, 0.000012_dp, & "m^-1") !! Rydberg constant type(codata_constant_type), parameter, public :: RYDBERG_CONSTANT_TIMES_C_IN_HZ = & codata_constant_type("Rydberg constant times c in Hz", & 3.2898419602500e15_dp, 0.0000000000036e15_dp, & "Hz") !! Rydberg constant times c in Hz type(codata_constant_type), parameter, public :: RYDBERG_CONSTANT_TIMES_HC_IN_EV = & codata_constant_type("Rydberg constant times hc in eV", & 13.605693122990_dp, 0.000000000015_dp, & "eV") !! Rydberg constant times hc in eV type(codata_constant_type), parameter, public :: RYDBERG_CONSTANT_TIMES_HC_IN_J = & codata_constant_type("Rydberg constant times hc in J", & 2.1798723611030e-18_dp, 0.0000000000024e-18_dp, & "J") !! Rydberg constant times hc in J type(codata_constant_type), parameter, public :: SACKUR_TETRODE_CONSTANT_1_K_100_KPA = & codata_constant_type("Sackur-Tetrode constant (1 K, 100 kPa)", & -1.15170753496_dp, 0.00000000047_dp, & "") !! Sackur-Tetrode constant (1 K, 100 kPa) type(codata_constant_type), parameter, public :: SACKUR_TETRODE_CONSTANT_1_K_101_325_KPA = & codata_constant_type("Sackur-Tetrode constant (1 K, 101.325 kPa)", & -1.16487052149_dp, 0.00000000047_dp, & "") !! Sackur-Tetrode constant (1 K, 101.325 kPa) type(codata_constant_type), parameter, public :: SECOND_RADIATION_CONSTANT = & codata_constant_type("second radiation constant", & 1.438776877e-2_dp, 0.0_dp, & "m K") !! second radiation constant type(codata_constant_type), parameter, public :: SHIELDED_HELION_GYROMAG_RATIO = & codata_constant_type("shielded helion gyromag. ratio", & 2.0378946078e8_dp, 0.0000000018e8_dp, & "s^-1 T^-1") !! shielded helion gyromag. ratio type(codata_constant_type), parameter, public :: SHIELDED_HELION_GYROMAG_RATIO_IN_MHZ_T = & codata_constant_type("shielded helion gyromag. ratio in MHz/T", & 32.434100033_dp, 0.000000028_dp, & "MHz T^-1") !! shielded helion gyromag. ratio in MHz/T type(codata_constant_type), parameter, public :: SHIELDED_HELION_MAG_MOM = & codata_constant_type("shielded helion mag. mom.", & -1.07455311035e-26_dp, 0.00000000093e-26_dp, & "J T^-1") !! shielded helion mag. mom. type(codata_constant_type), parameter, public :: SHIELDED_HELION_MAG_MOM_TO_BOHR_MAGNETON_RATIO = & codata_constant_type("shielded helion mag. mom. to Bohr magneton ratio", & -1.15867149457e-3_dp, 0.00000000094e-3_dp, & "") !! shielded helion mag. mom. to Bohr magneton ratio type(codata_constant_type), parameter, public :: SHIELDED_HELION_MAG_MOM_TO_NUCLEAR_MAGNETON_RATIO = & codata_constant_type("shielded helion mag. mom. to nuclear magneton ratio", & -2.1274977624_dp, 0.0000000017_dp, & "") !! shielded helion mag. mom. to nuclear magneton ratio type(codata_constant_type), parameter, public :: SHIELDED_HELION_TO_PROTON_MAG_MOM_RATIO = & codata_constant_type("shielded helion to proton mag. mom. ratio", & -0.76176657721_dp, 0.00000000066_dp, & "") !! shielded helion to proton mag. mom. ratio type(codata_constant_type), parameter, public :: SHIELDED_HELION_TO_SHIELDED_PROTON_MAG_MOM_RATIO = & codata_constant_type("shielded helion to shielded proton mag. mom. ratio", & -0.7617861334_dp, 0.0000000031_dp, & "") !! shielded helion to shielded proton mag. mom. ratio type(codata_constant_type), parameter, public :: SHIELDED_PROTON_GYROMAG_RATIO = & codata_constant_type("shielded proton gyromag. ratio", & 2.675153194e8_dp, 0.000000011e8_dp, & "s^-1 T^-1") !! shielded proton gyromag. ratio type(codata_constant_type), parameter, public :: SHIELDED_PROTON_GYROMAG_RATIO_IN_MHZ_T = & codata_constant_type("shielded proton gyromag. ratio in MHz/T", & 42.57638543_dp, 0.00000017_dp, & "MHz T^-1") !! shielded proton gyromag. ratio in MHz/T type(codata_constant_type), parameter, public :: SHIELDED_PROTON_MAG_MOM = & codata_constant_type("shielded proton mag. mom.", & 1.4105705830e-26_dp, 0.0000000058e-26_dp, & "J T^-1") !! shielded proton mag. mom. type(codata_constant_type), parameter, public :: SHIELDED_PROTON_MAG_MOM_TO_BOHR_MAGNETON_RATIO = & codata_constant_type("shielded proton mag. mom. to Bohr magneton ratio", & 1.5209931551e-3_dp, 0.0000000062e-3_dp, & "") !! shielded proton mag. mom. to Bohr magneton ratio type(codata_constant_type), parameter, public :: SHIELDED_PROTON_MAG_MOM_TO_NUCLEAR_MAGNETON_RATIO = & codata_constant_type("shielded proton mag. mom. to nuclear magneton ratio", & 2.792775648_dp, 0.000000011_dp, & "") !! shielded proton mag. mom. to nuclear magneton ratio type(codata_constant_type), parameter, public :: SHIELDING_DIFFERENCE_OF_D_AND_P_IN_HD = & codata_constant_type("shielding difference of d and p in HD", & 1.98770e-8_dp, 0.00010e-8_dp, & "") !! shielding difference of d and p in HD type(codata_constant_type), parameter, public :: SHIELDING_DIFFERENCE_OF_T_AND_P_IN_HT = & codata_constant_type("shielding difference of t and p in HT", & 2.39450e-8_dp, 0.00020e-8_dp, & "") !! shielding difference of t and p in HT type(codata_constant_type), parameter, public :: SPEED_OF_LIGHT_IN_VACUUM = & codata_constant_type("speed of light in vacuum", & 299792458_dp, 0.0_dp, & "m s^-1") !! speed of light in vacuum type(codata_constant_type), parameter, public :: STANDARD_ACCELERATION_OF_GRAVITY = & codata_constant_type("standard acceleration of gravity", & 9.80665_dp, 0.0_dp, & "m s^-2") !! standard acceleration of gravity type(codata_constant_type), parameter, public :: STANDARD_ATMOSPHERE = & codata_constant_type("standard atmosphere", & 101325_dp, 0.0_dp, & "Pa") !! standard atmosphere type(codata_constant_type), parameter, public :: STANDARD_STATE_PRESSURE = & codata_constant_type("standard-state pressure", & 100000_dp, 0.0_dp, & "Pa") !! standard-state pressure type(codata_constant_type), parameter, public :: STEFAN_BOLTZMANN_CONSTANT = & codata_constant_type("Stefan-Boltzmann constant", & 5.670374419e-8_dp, 0.0_dp, & "W m^-2 K^-4") !! Stefan-Boltzmann constant type(codata_constant_type), parameter, public :: TAU_COMPTON_WAVELENGTH = & codata_constant_type("tau Compton wavelength", & 6.97771e-16_dp, 0.00047e-16_dp, & "m") !! tau Compton wavelength type(codata_constant_type), parameter, public :: TAU_ELECTRON_MASS_RATIO = & codata_constant_type("tau-electron mass ratio", & 3477.23_dp, 0.23_dp, & "") !! tau-electron mass ratio type(codata_constant_type), parameter, public :: TAU_ENERGY_EQUIVALENT = & codata_constant_type("tau energy equivalent", & 1776.86_dp, 0.12_dp, & "MeV") !! tau energy equivalent type(codata_constant_type), parameter, public :: TAU_MASS = & codata_constant_type("tau mass", & 3.16754e-27_dp, 0.00021e-27_dp, & "kg") !! tau mass type(codata_constant_type), parameter, public :: TAU_MASS_ENERGY_EQUIVALENT = & codata_constant_type("tau mass energy equivalent", & 2.84684e-10_dp, 0.00019e-10_dp, & "J") !! tau mass energy equivalent type(codata_constant_type), parameter, public :: TAU_MASS_IN_U = & codata_constant_type("tau mass in u", & 1.90754_dp, 0.00013_dp, & "u") !! tau mass in u type(codata_constant_type), parameter, public :: TAU_MOLAR_MASS = & codata_constant_type("tau molar mass", & 1.90754e-3_dp, 0.00013e-3_dp, & "kg mol^-1") !! tau molar mass type(codata_constant_type), parameter, public :: TAU_MUON_MASS_RATIO = & codata_constant_type("tau-muon mass ratio", & 16.8170_dp, 0.0011_dp, & "") !! tau-muon mass ratio type(codata_constant_type), parameter, public :: TAU_NEUTRON_MASS_RATIO = & codata_constant_type("tau-neutron mass ratio", & 1.89115_dp, 0.00013_dp, & "") !! tau-neutron mass ratio type(codata_constant_type), parameter, public :: TAU_PROTON_MASS_RATIO = & codata_constant_type("tau-proton mass ratio", & 1.89376_dp, 0.00013_dp, & "") !! tau-proton mass ratio type(codata_constant_type), parameter, public :: THOMSON_CROSS_SECTION = & codata_constant_type("Thomson cross section", & 6.6524587051e-29_dp, 0.0000000062e-29_dp, & "m^2") !! Thomson cross section type(codata_constant_type), parameter, public :: TRITON_ELECTRON_MASS_RATIO = & codata_constant_type("triton-electron mass ratio", & 5496.92153551_dp, 0.00000021_dp, & "") !! triton-electron mass ratio type(codata_constant_type), parameter, public :: TRITON_G_FACTOR = & codata_constant_type("triton g factor", & 5.957924930_dp, 0.000000012_dp, & "") !! triton g factor type(codata_constant_type), parameter, public :: TRITON_MAG_MOM = & codata_constant_type("triton mag. mom.", & 1.5046095178e-26_dp, 0.0000000030e-26_dp, & "J T^-1") !! triton mag. mom. type(codata_constant_type), parameter, public :: TRITON_MAG_MOM_TO_BOHR_MAGNETON_RATIO = & codata_constant_type("triton mag. mom. to Bohr magneton ratio", & 1.6223936648e-3_dp, 0.0000000032e-3_dp, & "") !! triton mag. mom. to Bohr magneton ratio type(codata_constant_type), parameter, public :: TRITON_MAG_MOM_TO_NUCLEAR_MAGNETON_RATIO = & codata_constant_type("triton mag. mom. to nuclear magneton ratio", & 2.9789624650_dp, 0.0000000059_dp, & "") !! triton mag. mom. to nuclear magneton ratio type(codata_constant_type), parameter, public :: TRITON_MASS = & codata_constant_type("triton mass", & 5.0073567512e-27_dp, 0.0000000016e-27_dp, & "kg") !! triton mass type(codata_constant_type), parameter, public :: TRITON_MASS_ENERGY_EQUIVALENT = & codata_constant_type("triton mass energy equivalent", & 4.5003878119e-10_dp, 0.0000000014e-10_dp, & "J") !! triton mass energy equivalent type(codata_constant_type), parameter, public :: TRITON_MASS_ENERGY_EQUIVALENT_IN_MEV = & codata_constant_type("triton mass energy equivalent in MeV", & 2808.92113668_dp, 0.00000088_dp, & "MeV") !! triton mass energy equivalent in MeV type(codata_constant_type), parameter, public :: TRITON_MASS_IN_U = & codata_constant_type("triton mass in u", & 3.01550071597_dp, 0.00000000010_dp, & "u") !! triton mass in u type(codata_constant_type), parameter, public :: TRITON_MOLAR_MASS = & codata_constant_type("triton molar mass", & 3.01550071913e-3_dp, 0.00000000094e-3_dp, & "kg mol^-1") !! triton molar mass type(codata_constant_type), parameter, public :: TRITON_PROTON_MASS_RATIO = & codata_constant_type("triton-proton mass ratio", & 2.99371703403_dp, 0.00000000010_dp, & "") !! triton-proton mass ratio type(codata_constant_type), parameter, public :: TRITON_RELATIVE_ATOMIC_MASS = & codata_constant_type("triton relative atomic mass", & 3.01550071597_dp, 0.00000000010_dp, & "") !! triton relative atomic mass type(codata_constant_type), parameter, public :: TRITON_TO_PROTON_MAG_MOM_RATIO = & codata_constant_type("triton to proton mag. mom. ratio", & 1.0666399189_dp, 0.0000000021_dp, & "") !! triton to proton mag. mom. ratio type(codata_constant_type), parameter, public :: UNIFIED_ATOMIC_MASS_UNIT = & codata_constant_type("unified atomic mass unit", & 1.66053906892e-27_dp, 0.00000000052e-27_dp, & "kg") !! unified atomic mass unit type(codata_constant_type), parameter, public :: VACUUM_ELECTRIC_PERMITTIVITY = & codata_constant_type("vacuum electric permittivity", & 8.8541878188e-12_dp, 0.0000000014e-12_dp, & "F m^-1") !! vacuum electric permittivity type(codata_constant_type), parameter, public :: VACUUM_MAG_PERMEABILITY = & codata_constant_type("vacuum mag. permeability", & 1.25663706127e-6_dp, 0.00000000020e-6_dp, & "N A^-2") !! vacuum mag. permeability type(codata_constant_type), parameter, public :: VON_KLITZING_CONSTANT = & codata_constant_type("von Klitzing constant", & 25812.80745_dp, 0.0_dp, & "ohm") !! von Klitzing constant type(codata_constant_type), parameter, public :: WEAK_MIXING_ANGLE = & codata_constant_type("weak mixing angle", & 0.22305_dp, 0.00023_dp, & "") !! weak mixing angle type(codata_constant_type), parameter, public :: WIEN_FREQUENCY_DISPLACEMENT_LAW_CONSTANT = & codata_constant_type("Wien frequency displacement law constant", & 5.878925757e10_dp, 0.0_dp, & "Hz K^-1") !! Wien frequency displacement law constant type(codata_constant_type), parameter, public :: WIEN_WAVELENGTH_DISPLACEMENT_LAW_CONSTANT = & codata_constant_type("Wien wavelength displacement law constant", & 2.897771955e-3_dp, 0.0_dp, & "m K") !! Wien wavelength displacement law constant type(codata_constant_type), parameter, public :: W_TO_Z_MASS_RATIO = & codata_constant_type("W to Z mass ratio", & 0.88145_dp, 0.00013_dp, & "") !! W to Z mass ratio end module stdlib_codatafortran-lang-stdlib-0ede301/src/constants/CMakeLists.txt0000664000175000017500000000046215135654166023533 0ustar alastairalastairset(constants_fppFiles stdlib_codata_type.fypp stdlib_constants.fypp ) set(constants_f90Files stdlib_codata.f90 ) configure_stdlib_target(${PROJECT_NAME}_constants constants_f90Files constants_fppFiles "") target_link_libraries(${PROJECT_NAME}_constants PUBLIC ${PROJECT_NAME}_core) fortran-lang-stdlib-0ede301/src/blas/0000775000175000017500000000000015135654166017676 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/blas/stdlib_blas_level2_gen.fypp0000664000175000017500000032607215135654166025174 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_blas) stdlib_blas_level2_gen implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgemv(trans,m,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_sp !! SGEMV performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n character, intent(in) :: trans ! Array Arguments real(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(sp) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky, lenx, leny ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (lda0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,leny y(i) = zero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,leny y(iy) = zero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) do i = 1,m y(i) = y(i) + temp*a(i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky do i = 1,m y(iy) = y(iy) + temp*a(i,j) iy = iy + incy end do jx = jx + incx end do end if else ! form y := alpha*a**t*x + y. jy = ky if (incx==1) then do j = 1,n temp = zero do i = 1,m temp = temp + a(i,j)*x(i) end do y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = zero ix = kx do i = 1,m temp = temp + a(i,j)*x(ix) ix = ix + incx end do y(jy) = y(jy) + alpha*temp jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_sgemv pure module subroutine stdlib${ii}$_dgemv(trans,m,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_dp !! DGEMV performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n character, intent(in) :: trans ! Array Arguments real(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(dp) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky, lenx, leny ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (lda0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,leny y(i) = zero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,leny y(iy) = zero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) do i = 1,m y(i) = y(i) + temp*a(i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky do i = 1,m y(iy) = y(iy) + temp*a(i,j) iy = iy + incy end do jx = jx + incx end do end if else ! form y := alpha*a**t*x + y. jy = ky if (incx==1) then do j = 1,n temp = zero do i = 1,m temp = temp + a(i,j)*x(i) end do y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = zero ix = kx do i = 1,m temp = temp + a(i,j)*x(ix) ix = ix + incx end do y(jy) = y(jy) + alpha*temp jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_dgemv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gemv(trans,m,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_${rk}$ !! DGEMV: performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n character, intent(in) :: trans ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), x(*) real(${rk}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky, lenx, leny ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (lda0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,leny y(i) = zero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,leny y(iy) = zero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) do i = 1,m y(i) = y(i) + temp*a(i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky do i = 1,m y(iy) = y(iy) + temp*a(i,j) iy = iy + incy end do jx = jx + incx end do end if else ! form y := alpha*a**t*x + y. jy = ky if (incx==1) then do j = 1,n temp = zero do i = 1,m temp = temp + a(i,j)*x(i) end do y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = zero ix = kx do i = 1,m temp = temp + a(i,j)*x(ix) ix = ix + incx end do y(jy) = y(jy) + alpha*temp jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_${ri}$gemv #:endif #:endfor pure module subroutine stdlib${ii}$_cgemv(trans,m,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_sp !! CGEMV performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, or !! y := alpha*A**H*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n character, intent(in) :: trans ! Array Arguments complex(sp), intent(in) :: a(lda,*), x(*) complex(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky, lenx, leny logical(lk) :: noconj ! Intrinsic Functions intrinsic :: conjg,max ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (lda0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,leny y(i) = czero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,leny y(iy) = czero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) do i = 1,m y(i) = y(i) + temp*a(i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky do i = 1,m y(iy) = y(iy) + temp*a(i,j) iy = iy + incy end do jx = jx + incx end do end if else ! form y := alpha*a**t*x + y or y := alpha*a**h*x + y. jy = ky if (incx==1) then do j = 1,n temp = czero if (noconj) then do i = 1,m temp = temp + a(i,j)*x(i) end do else do i = 1,m temp = temp + conjg(a(i,j))*x(i) end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = czero ix = kx if (noconj) then do i = 1,m temp = temp + a(i,j)*x(ix) ix = ix + incx end do else do i = 1,m temp = temp + conjg(a(i,j))*x(ix) ix = ix + incx end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_cgemv pure module subroutine stdlib${ii}$_zgemv(trans,m,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_dp !! ZGEMV performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, or !! y := alpha*A**H*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n character, intent(in) :: trans ! Array Arguments complex(dp), intent(in) :: a(lda,*), x(*) complex(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky, lenx, leny logical(lk) :: noconj ! Intrinsic Functions intrinsic :: conjg,max ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (lda0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,leny y(i) = czero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,leny y(iy) = czero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) do i = 1,m y(i) = y(i) + temp*a(i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky do i = 1,m y(iy) = y(iy) + temp*a(i,j) iy = iy + incy end do jx = jx + incx end do end if else ! form y := alpha*a**t*x + y or y := alpha*a**h*x + y. jy = ky if (incx==1) then do j = 1,n temp = czero if (noconj) then do i = 1,m temp = temp + a(i,j)*x(i) end do else do i = 1,m temp = temp + conjg(a(i,j))*x(i) end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = czero ix = kx if (noconj) then do i = 1,m temp = temp + a(i,j)*x(ix) ix = ix + incx end do else do i = 1,m temp = temp + conjg(a(i,j))*x(ix) ix = ix + incx end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_zgemv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gemv(trans,m,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_${ck}$ !! ZGEMV: performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, or !! y := alpha*A**H*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n character, intent(in) :: trans ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), x(*) complex(${ck}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky, lenx, leny logical(lk) :: noconj ! Intrinsic Functions intrinsic :: conjg,max ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (lda0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,leny y(i) = czero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,leny y(iy) = czero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) do i = 1,m y(i) = y(i) + temp*a(i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky do i = 1,m y(iy) = y(iy) + temp*a(i,j) iy = iy + incy end do jx = jx + incx end do end if else ! form y := alpha*a**t*x + y or y := alpha*a**h*x + y. jy = ky if (incx==1) then do j = 1,n temp = czero if (noconj) then do i = 1,m temp = temp + a(i,j)*x(i) end do else do i = 1,m temp = temp + conjg(a(i,j))*x(i) end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = czero ix = kx if (noconj) then do i = 1,m temp = temp + a(i,j)*x(ix) ix = ix + incx end do else do i = 1,m temp = temp + conjg(a(i,j))*x(ix) ix = ix + incx end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_${ci}$gemv #:endif #:endfor pure module subroutine stdlib${ii}$_sger(m,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_sp !! SGER performs the rank 1 operation !! A := alpha*x*y**T + A, !! where alpha is a scalar, x is an m element vector, y is an n element !! vector and A is an m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(sp) :: temp integer(${ik}$) :: i, info, ix, j, jy, kx ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (m<0) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then jy = 1 else jy = 1 - (n-1)*incy end if if (incx==1) then do j = 1,n if (y(jy)/=zero) then temp = alpha*y(jy) do i = 1,m a(i,j) = a(i,j) + x(i)*temp end do end if jy = jy + incy end do else if (incx>0) then kx = 1 else kx = 1 - (m-1)*incx end if do j = 1,n if (y(jy)/=zero) then temp = alpha*y(jy) ix = kx do i = 1,m a(i,j) = a(i,j) + x(ix)*temp ix = ix + incx end do end if jy = jy + incy end do end if return end subroutine stdlib${ii}$_sger pure module subroutine stdlib${ii}$_dger(m,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_dp !! DGER performs the rank 1 operation !! A := alpha*x*y**T + A, !! where alpha is a scalar, x is an m element vector, y is an n element !! vector and A is an m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(dp) :: temp integer(${ik}$) :: i, info, ix, j, jy, kx ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (m<0) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then jy = 1 else jy = 1 - (n-1)*incy end if if (incx==1) then do j = 1,n if (y(jy)/=zero) then temp = alpha*y(jy) do i = 1,m a(i,j) = a(i,j) + x(i)*temp end do end if jy = jy + incy end do else if (incx>0) then kx = 1 else kx = 1 - (m-1)*incx end if do j = 1,n if (y(jy)/=zero) then temp = alpha*y(jy) ix = kx do i = 1,m a(i,j) = a(i,j) + x(ix)*temp ix = ix + incx end do end if jy = jy + incy end do end if return end subroutine stdlib${ii}$_dger #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ger(m,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_${rk}$ !! DGER: performs the rank 1 operation !! A := alpha*x*y**T + A, !! where alpha is a scalar, x is an m element vector, y is an n element !! vector and A is an m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${rk}$), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp integer(${ik}$) :: i, info, ix, j, jy, kx ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (m<0) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then jy = 1 else jy = 1 - (n-1)*incy end if if (incx==1) then do j = 1,n if (y(jy)/=zero) then temp = alpha*y(jy) do i = 1,m a(i,j) = a(i,j) + x(i)*temp end do end if jy = jy + incy end do else if (incx>0) then kx = 1 else kx = 1 - (m-1)*incx end if do j = 1,n if (y(jy)/=zero) then temp = alpha*y(jy) ix = kx do i = 1,m a(i,j) = a(i,j) + x(ix)*temp ix = ix + incx end do end if jy = jy + incy end do end if return end subroutine stdlib${ii}$_${ri}$ger #:endif #:endfor pure module subroutine stdlib${ii}$_cgerc(m,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_sp !! CGERC performs the rank 1 operation !! A := alpha*x*y**H + A, !! where alpha is a scalar, x is an m element vector, y is an n element !! vector and A is an m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(sp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp integer(${ik}$) :: i, info, ix, j, jy, kx ! Intrinsic Functions intrinsic :: conjg,max ! test the input parameters. info = 0 if (m<0) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then jy = 1 else jy = 1 - (n-1)*incy end if if (incx==1) then do j = 1,n if (y(jy)/=czero) then temp = alpha*conjg(y(jy)) do i = 1,m a(i,j) = a(i,j) + x(i)*temp end do end if jy = jy + incy end do else if (incx>0) then kx = 1 else kx = 1 - (m-1)*incx end if do j = 1,n if (y(jy)/=czero) then temp = alpha*conjg(y(jy)) ix = kx do i = 1,m a(i,j) = a(i,j) + x(ix)*temp ix = ix + incx end do end if jy = jy + incy end do end if return end subroutine stdlib${ii}$_cgerc pure module subroutine stdlib${ii}$_zgerc(m,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_dp !! ZGERC performs the rank 1 operation !! A := alpha*x*y**H + A, !! where alpha is a scalar, x is an m element vector, y is an n element !! vector and A is an m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(dp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp integer(${ik}$) :: i, info, ix, j, jy, kx ! Intrinsic Functions intrinsic :: conjg,max ! test the input parameters. info = 0 if (m<0) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then jy = 1 else jy = 1 - (n-1)*incy end if if (incx==1) then do j = 1,n if (y(jy)/=czero) then temp = alpha*conjg(y(jy)) do i = 1,m a(i,j) = a(i,j) + x(i)*temp end do end if jy = jy + incy end do else if (incx>0) then kx = 1 else kx = 1 - (m-1)*incx end if do j = 1,n if (y(jy)/=czero) then temp = alpha*conjg(y(jy)) ix = kx do i = 1,m a(i,j) = a(i,j) + x(ix)*temp ix = ix + incx end do end if jy = jy + incy end do end if return end subroutine stdlib${ii}$_zgerc #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gerc(m,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_${ck}$ !! ZGERC: performs the rank 1 operation !! A := alpha*x*y**H + A, !! where alpha is a scalar, x is an m element vector, y is an n element !! vector and A is an m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(${ck}$), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp integer(${ik}$) :: i, info, ix, j, jy, kx ! Intrinsic Functions intrinsic :: conjg,max ! test the input parameters. info = 0 if (m<0) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then jy = 1 else jy = 1 - (n-1)*incy end if if (incx==1) then do j = 1,n if (y(jy)/=czero) then temp = alpha*conjg(y(jy)) do i = 1,m a(i,j) = a(i,j) + x(i)*temp end do end if jy = jy + incy end do else if (incx>0) then kx = 1 else kx = 1 - (m-1)*incx end if do j = 1,n if (y(jy)/=czero) then temp = alpha*conjg(y(jy)) ix = kx do i = 1,m a(i,j) = a(i,j) + x(ix)*temp ix = ix + incx end do end if jy = jy + incy end do end if return end subroutine stdlib${ii}$_${ci}$gerc #:endif #:endfor pure module subroutine stdlib${ii}$_cgeru(m,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_sp !! CGERU performs the rank 1 operation !! A := alpha*x*y**T + A, !! where alpha is a scalar, x is an m element vector, y is an n element !! vector and A is an m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(sp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp integer(${ik}$) :: i, info, ix, j, jy, kx ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (m<0) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then jy = 1 else jy = 1 - (n-1)*incy end if if (incx==1) then do j = 1,n if (y(jy)/=czero) then temp = alpha*y(jy) do i = 1,m a(i,j) = a(i,j) + x(i)*temp end do end if jy = jy + incy end do else if (incx>0) then kx = 1 else kx = 1 - (m-1)*incx end if do j = 1,n if (y(jy)/=czero) then temp = alpha*y(jy) ix = kx do i = 1,m a(i,j) = a(i,j) + x(ix)*temp ix = ix + incx end do end if jy = jy + incy end do end if return end subroutine stdlib${ii}$_cgeru pure module subroutine stdlib${ii}$_zgeru(m,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_dp !! ZGERU performs the rank 1 operation !! A := alpha*x*y**T + A, !! where alpha is a scalar, x is an m element vector, y is an n element !! vector and A is an m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(dp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp integer(${ik}$) :: i, info, ix, j, jy, kx ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (m<0) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then jy = 1 else jy = 1 - (n-1)*incy end if if (incx==1) then do j = 1,n if (y(jy)/=czero) then temp = alpha*y(jy) do i = 1,m a(i,j) = a(i,j) + x(i)*temp end do end if jy = jy + incy end do else if (incx>0) then kx = 1 else kx = 1 - (m-1)*incx end if do j = 1,n if (y(jy)/=czero) then temp = alpha*y(jy) ix = kx do i = 1,m a(i,j) = a(i,j) + x(ix)*temp ix = ix + incx end do end if jy = jy + incy end do end if return end subroutine stdlib${ii}$_zgeru #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$geru(m,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_${ck}$ !! ZGERU: performs the rank 1 operation !! A := alpha*x*y**T + A, !! where alpha is a scalar, x is an m element vector, y is an n element !! vector and A is an m by n matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(${ck}$), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp integer(${ik}$) :: i, info, ix, j, jy, kx ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (m<0) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then jy = 1 else jy = 1 - (n-1)*incy end if if (incx==1) then do j = 1,n if (y(jy)/=czero) then temp = alpha*y(jy) do i = 1,m a(i,j) = a(i,j) + x(i)*temp end do end if jy = jy + incy end do else if (incx>0) then kx = 1 else kx = 1 - (m-1)*incx end if do j = 1,n if (y(jy)/=czero) then temp = alpha*y(jy) ix = kx do i = 1,m a(i,j) = a(i,j) + x(ix)*temp ix = ix + incx end do end if jy = jy + incy end do end if return end subroutine stdlib${ii}$_${ci}$geru #:endif #:endfor pure module subroutine stdlib${ii}$_cher(uplo,n,alpha,x,incx,a,lda) use stdlib_blas_constants_sp !! CHER performs the hermitian rank 1 operation !! A := alpha*x*x**H + A, !! where alpha is a real scalar, x is an n element vector and A is an !! n by n hermitian matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, lda, n character, intent(in) :: uplo ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: x(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, kx ! Intrinsic Functions intrinsic :: conjg,max,real ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the triangular part ! of a. if (stdlib_lsame(uplo,'U')) then ! form a when a is stored in the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) do i = 1,j - 1 a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do a(j,j) = real(a(j,j),KIND=sp) +real(x(j)*temp1+y(j)*temp2,KIND=sp) else a(j,j) = real(a(j,j),KIND=sp) end if end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) ix = kx iy = ky do i = 1,j - 1 a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do a(j,j) = real(a(j,j),KIND=sp) +real(x(jx)*temp1+y(jy)*temp2,KIND=sp) else a(j,j) = real(a(j,j),KIND=sp) end if jx = jx + incx jy = jy + incy end do end if else ! form a when a is stored in the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) a(j,j) = real(a(j,j),KIND=sp) +real(x(j)*temp1+y(j)*temp2,KIND=sp) do i = j + 1,n a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do else a(j,j) = real(a(j,j),KIND=sp) end if end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) a(j,j) = real(a(j,j),KIND=sp) +real(x(jx)*temp1+y(jy)*temp2,KIND=sp) ix = jx iy = jy do i = j + 1,n ix = ix + incx iy = iy + incy a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 end do else a(j,j) = real(a(j,j),KIND=sp) end if jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_cher2 pure module subroutine stdlib${ii}$_zher2(uplo,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_dp !! ZHER2 performs the hermitian rank 2 operation !! A := alpha*x*y**H + conjg( alpha )*y*x**H + A, !! where alpha is a scalar, x and y are n element vectors and A is an n !! by n hermitian matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(dp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, n character, intent(in) :: uplo ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky ! Intrinsic Functions intrinsic :: real,conjg,max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the triangular part ! of a. if (stdlib_lsame(uplo,'U')) then ! form a when a is stored in the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) do i = 1,j - 1 a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do a(j,j) = real(a(j,j),KIND=dp) +real(x(j)*temp1+y(j)*temp2,KIND=dp) else a(j,j) = real(a(j,j),KIND=dp) end if end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) ix = kx iy = ky do i = 1,j - 1 a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do a(j,j) = real(a(j,j),KIND=dp) +real(x(jx)*temp1+y(jy)*temp2,KIND=dp) else a(j,j) = real(a(j,j),KIND=dp) end if jx = jx + incx jy = jy + incy end do end if else ! form a when a is stored in the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) a(j,j) = real(a(j,j),KIND=dp) +real(x(j)*temp1+y(j)*temp2,KIND=dp) do i = j + 1,n a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do else a(j,j) = real(a(j,j),KIND=dp) end if end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) a(j,j) = real(a(j,j),KIND=dp) +real(x(jx)*temp1+y(jy)*temp2,KIND=dp) ix = jx iy = jy do i = j + 1,n ix = ix + incx iy = iy + incy a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 end do else a(j,j) = real(a(j,j),KIND=dp) end if jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_zher2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$her2(uplo,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_${ck}$ !! ZHER2: performs the hermitian rank 2 operation !! A := alpha*x*y**H + conjg( alpha )*y*x**H + A, !! where alpha is a scalar, x and y are n element vectors and A is an n !! by n hermitian matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(${ck}$), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, n character, intent(in) :: uplo ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky ! Intrinsic Functions intrinsic :: real,conjg,max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the triangular part ! of a. if (stdlib_lsame(uplo,'U')) then ! form a when a is stored in the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) do i = 1,j - 1 a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do a(j,j) = real(a(j,j),KIND=${ck}$) +real(x(j)*temp1+y(j)*temp2,KIND=${ck}$) else a(j,j) = real(a(j,j),KIND=${ck}$) end if end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) ix = kx iy = ky do i = 1,j - 1 a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do a(j,j) = real(a(j,j),KIND=${ck}$) +real(x(jx)*temp1+y(jy)*temp2,KIND=${ck}$) else a(j,j) = real(a(j,j),KIND=${ck}$) end if jx = jx + incx jy = jy + incy end do end if else ! form a when a is stored in the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) a(j,j) = real(a(j,j),KIND=${ck}$) +real(x(j)*temp1+y(j)*temp2,KIND=${ck}$) do i = j + 1,n a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do else a(j,j) = real(a(j,j),KIND=${ck}$) end if end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) a(j,j) = real(a(j,j),KIND=${ck}$) +real(x(jx)*temp1+y(jy)*temp2,KIND=${ck}$) ix = jx iy = jy do i = j + 1,n ix = ix + incx iy = iy + incy a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 end do else a(j,j) = real(a(j,j),KIND=${ck}$) end if jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_${ci}$her2 #:endif #:endfor pure module subroutine stdlib${ii}$_chemv(uplo,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_sp !! CHEMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n hermitian matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n character, intent(in) :: uplo ! Array Arguments complex(sp), intent(in) :: a(lda,*), x(*) complex(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky ! Intrinsic Functions intrinsic :: conjg,max,real ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the triangular part ! of a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,n y(i) = czero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,n y(iy) = czero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return if (stdlib_lsame(uplo,'U')) then ! form y when a is stored in upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero do i = 1,j - 1 y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(i) end do y(j) = y(j) + temp1*real(a(j,j),KIND=sp) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero ix = kx iy = ky do i = 1,j - 1 y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*real(a(j,j),KIND=sp) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if else ! form y when a is stored in lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero y(j) = y(j) + temp1*real(a(j,j),KIND=sp) do i = j + 1,n y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero y(jy) = y(jy) + temp1*real(a(j,j),KIND=sp) ix = jx iy = jy do i = j + 1,n ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_chemv pure module subroutine stdlib${ii}$_zhemv(uplo,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_dp !! ZHEMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n hermitian matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n character, intent(in) :: uplo ! Array Arguments complex(dp), intent(in) :: a(lda,*), x(*) complex(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky ! Intrinsic Functions intrinsic :: real,conjg,max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the triangular part ! of a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,n y(i) = czero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,n y(iy) = czero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return if (stdlib_lsame(uplo,'U')) then ! form y when a is stored in upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero do i = 1,j - 1 y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(i) end do y(j) = y(j) + temp1*real(a(j,j),KIND=dp) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero ix = kx iy = ky do i = 1,j - 1 y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*real(a(j,j),KIND=dp) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if else ! form y when a is stored in lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero y(j) = y(j) + temp1*real(a(j,j),KIND=dp) do i = j + 1,n y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero y(jy) = y(jy) + temp1*real(a(j,j),KIND=dp) ix = jx iy = jy do i = j + 1,n ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_zhemv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hemv(uplo,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_${ck}$ !! ZHEMV: performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n hermitian matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n character, intent(in) :: uplo ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), x(*) complex(${ck}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky ! Intrinsic Functions intrinsic :: real,conjg,max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the triangular part ! of a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,n y(i) = czero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,n y(iy) = czero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return if (stdlib_lsame(uplo,'U')) then ! form y when a is stored in upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero do i = 1,j - 1 y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(i) end do y(j) = y(j) + temp1*real(a(j,j),KIND=${ck}$) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero ix = kx iy = ky do i = 1,j - 1 y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*real(a(j,j),KIND=${ck}$) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if else ! form y when a is stored in lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero y(j) = y(j) + temp1*real(a(j,j),KIND=${ck}$) do i = j + 1,n y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero y(jy) = y(jy) + temp1*real(a(j,j),KIND=${ck}$) ix = jx iy = jy do i = j + 1,n ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + conjg(a(i,j))*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_${ci}$hemv #:endif #:endfor #:endfor end submodule stdlib_blas_level2_gen fortran-lang-stdlib-0ede301/src/blas/stdlib_blas_level2_ban.fypp0000664000175000017500000015613615135654166025165 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_blas) stdlib_blas_level2_ban implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgbmv(trans,m,n,kl,ku,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_sp !! SGBMV performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n band matrix, with kl sub-diagonals and ku super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, kl, ku, lda, m, n character, intent(in) :: trans ! Array Arguments real(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(sp) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kup1, kx, ky, lenx, leny ! Intrinsic Functions intrinsic :: max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (kl<0) then info = 4 else if (ku<0) then info = 5 else if (lda< (kl+ku+1)) then info = 8 else if (incx==0) then info = 10 else if (incy==0) then info = 13 end if if (info/=0) then call stdlib${ii}$_xerbla('SGBMV ',info) return end if ! quick return if possible. if ((m==0) .or. (n==0) .or.((alpha==zero).and. (beta==one))) return ! set lenx and leny, the lengths of the vectors x and y, and set ! up the start points in x and y. if (stdlib_lsame(trans,'N')) then lenx = n leny = m else lenx = m leny = n end if if (incx>0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through the band part of a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,leny y(i) = zero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,leny y(iy) = zero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return kup1 = ku + 1 if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(i) = y(i) + temp*a(k+i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(iy) = y(iy) + temp*a(k+i,j) iy = iy + incy end do jx = jx + incx if (j>ku) ky = ky + incy end do end if else ! form y := alpha*a**t*x + y. jy = ky if (incx==1) then do j = 1,n temp = zero k = kup1 - j do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(i) end do y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = zero ix = kx k = kup1 - j do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(ix) ix = ix + incx end do y(jy) = y(jy) + alpha*temp jy = jy + incy if (j>ku) kx = kx + incx end do end if end if return end subroutine stdlib${ii}$_sgbmv pure module subroutine stdlib${ii}$_dgbmv(trans,m,n,kl,ku,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_dp !! DGBMV performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n band matrix, with kl sub-diagonals and ku super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, kl, ku, lda, m, n character, intent(in) :: trans ! Array Arguments real(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(dp) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kup1, kx, ky, lenx, leny ! Intrinsic Functions intrinsic :: max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (kl<0) then info = 4 else if (ku<0) then info = 5 else if (lda< (kl+ku+1)) then info = 8 else if (incx==0) then info = 10 else if (incy==0) then info = 13 end if if (info/=0) then call stdlib${ii}$_xerbla('DGBMV ',info) return end if ! quick return if possible. if ((m==0) .or. (n==0) .or.((alpha==zero).and. (beta==one))) return ! set lenx and leny, the lengths of the vectors x and y, and set ! up the start points in x and y. if (stdlib_lsame(trans,'N')) then lenx = n leny = m else lenx = m leny = n end if if (incx>0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through the band part of a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,leny y(i) = zero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,leny y(iy) = zero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return kup1 = ku + 1 if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(i) = y(i) + temp*a(k+i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(iy) = y(iy) + temp*a(k+i,j) iy = iy + incy end do jx = jx + incx if (j>ku) ky = ky + incy end do end if else ! form y := alpha*a**t*x + y. jy = ky if (incx==1) then do j = 1,n temp = zero k = kup1 - j do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(i) end do y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = zero ix = kx k = kup1 - j do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(ix) ix = ix + incx end do y(jy) = y(jy) + alpha*temp jy = jy + incy if (j>ku) kx = kx + incx end do end if end if return end subroutine stdlib${ii}$_dgbmv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gbmv(trans,m,n,kl,ku,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_${rk}$ !! DGBMV: performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n band matrix, with kl sub-diagonals and ku super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, kl, ku, lda, m, n character, intent(in) :: trans ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), x(*) real(${rk}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kup1, kx, ky, lenx, leny ! Intrinsic Functions intrinsic :: max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (kl<0) then info = 4 else if (ku<0) then info = 5 else if (lda< (kl+ku+1)) then info = 8 else if (incx==0) then info = 10 else if (incy==0) then info = 13 end if if (info/=0) then call stdlib${ii}$_xerbla('DGBMV ',info) return end if ! quick return if possible. if ((m==0) .or. (n==0) .or.((alpha==zero).and. (beta==one))) return ! set lenx and leny, the lengths of the vectors x and y, and set ! up the start points in x and y. if (stdlib_lsame(trans,'N')) then lenx = n leny = m else lenx = m leny = n end if if (incx>0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through the band part of a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,leny y(i) = zero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,leny y(iy) = zero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return kup1 = ku + 1 if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(i) = y(i) + temp*a(k+i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(iy) = y(iy) + temp*a(k+i,j) iy = iy + incy end do jx = jx + incx if (j>ku) ky = ky + incy end do end if else ! form y := alpha*a**t*x + y. jy = ky if (incx==1) then do j = 1,n temp = zero k = kup1 - j do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(i) end do y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = zero ix = kx k = kup1 - j do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(ix) ix = ix + incx end do y(jy) = y(jy) + alpha*temp jy = jy + incy if (j>ku) kx = kx + incx end do end if end if return end subroutine stdlib${ii}$_${ri}$gbmv #:endif #:endfor pure module subroutine stdlib${ii}$_cgbmv(trans,m,n,kl,ku,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_sp !! CGBMV performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, or !! y := alpha*A**H*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n band matrix, with kl sub-diagonals and ku super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, kl, ku, lda, m, n character, intent(in) :: trans ! Array Arguments complex(sp), intent(in) :: a(lda,*), x(*) complex(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kup1, kx, ky, lenx, leny logical(lk) :: noconj ! Intrinsic Functions intrinsic :: conjg,max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (kl<0) then info = 4 else if (ku<0) then info = 5 else if (lda< (kl+ku+1)) then info = 8 else if (incx==0) then info = 10 else if (incy==0) then info = 13 end if if (info/=0) then call stdlib${ii}$_xerbla('CGBMV ',info) return end if ! quick return if possible. if ((m==0) .or. (n==0) .or.((alpha==czero).and. (beta==cone))) return noconj = stdlib_lsame(trans,'T') ! set lenx and leny, the lengths of the vectors x and y, and set ! up the start points in x and y. if (stdlib_lsame(trans,'N')) then lenx = n leny = m else lenx = m leny = n end if if (incx>0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the band part of a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,leny y(i) = czero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,leny y(iy) = czero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return kup1 = ku + 1 if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(i) = y(i) + temp*a(k+i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(iy) = y(iy) + temp*a(k+i,j) iy = iy + incy end do jx = jx + incx if (j>ku) ky = ky + incy end do end if else ! form y := alpha*a**t*x + y or y := alpha*a**h*x + y. jy = ky if (incx==1) then do j = 1,n temp = czero k = kup1 - j if (noconj) then do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(i) end do else do i = max(1,j-ku),min(m,j+kl) temp = temp + conjg(a(k+i,j))*x(i) end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = czero ix = kx k = kup1 - j if (noconj) then do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(ix) ix = ix + incx end do else do i = max(1,j-ku),min(m,j+kl) temp = temp + conjg(a(k+i,j))*x(ix) ix = ix + incx end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy if (j>ku) kx = kx + incx end do end if end if return end subroutine stdlib${ii}$_cgbmv pure module subroutine stdlib${ii}$_zgbmv(trans,m,n,kl,ku,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_dp !! ZGBMV performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, or !! y := alpha*A**H*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n band matrix, with kl sub-diagonals and ku super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, kl, ku, lda, m, n character, intent(in) :: trans ! Array Arguments complex(dp), intent(in) :: a(lda,*), x(*) complex(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kup1, kx, ky, lenx, leny logical(lk) :: noconj ! Intrinsic Functions intrinsic :: conjg,max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (kl<0) then info = 4 else if (ku<0) then info = 5 else if (lda< (kl+ku+1)) then info = 8 else if (incx==0) then info = 10 else if (incy==0) then info = 13 end if if (info/=0) then call stdlib${ii}$_xerbla('ZGBMV ',info) return end if ! quick return if possible. if ((m==0) .or. (n==0) .or.((alpha==czero).and. (beta==cone))) return noconj = stdlib_lsame(trans,'T') ! set lenx and leny, the lengths of the vectors x and y, and set ! up the start points in x and y. if (stdlib_lsame(trans,'N')) then lenx = n leny = m else lenx = m leny = n end if if (incx>0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the band part of a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,leny y(i) = czero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,leny y(iy) = czero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return kup1 = ku + 1 if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(i) = y(i) + temp*a(k+i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(iy) = y(iy) + temp*a(k+i,j) iy = iy + incy end do jx = jx + incx if (j>ku) ky = ky + incy end do end if else ! form y := alpha*a**t*x + y or y := alpha*a**h*x + y. jy = ky if (incx==1) then do j = 1,n temp = czero k = kup1 - j if (noconj) then do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(i) end do else do i = max(1,j-ku),min(m,j+kl) temp = temp + conjg(a(k+i,j))*x(i) end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = czero ix = kx k = kup1 - j if (noconj) then do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(ix) ix = ix + incx end do else do i = max(1,j-ku),min(m,j+kl) temp = temp + conjg(a(k+i,j))*x(ix) ix = ix + incx end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy if (j>ku) kx = kx + incx end do end if end if return end subroutine stdlib${ii}$_zgbmv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gbmv(trans,m,n,kl,ku,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_${ck}$ !! ZGBMV: performs one of the matrix-vector operations !! y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, or !! y := alpha*A**H*x + beta*y, !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n band matrix, with kl sub-diagonals and ku super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, kl, ku, lda, m, n character, intent(in) :: trans ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), x(*) complex(${ck}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kup1, kx, ky, lenx, leny logical(lk) :: noconj ! Intrinsic Functions intrinsic :: conjg,max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 1 else if (m<0) then info = 2 else if (n<0) then info = 3 else if (kl<0) then info = 4 else if (ku<0) then info = 5 else if (lda< (kl+ku+1)) then info = 8 else if (incx==0) then info = 10 else if (incy==0) then info = 13 end if if (info/=0) then call stdlib${ii}$_xerbla('ZGBMV ',info) return end if ! quick return if possible. if ((m==0) .or. (n==0) .or.((alpha==czero).and. (beta==cone))) return noconj = stdlib_lsame(trans,'T') ! set lenx and leny, the lengths of the vectors x and y, and set ! up the start points in x and y. if (stdlib_lsame(trans,'N')) then lenx = n leny = m else lenx = m leny = n end if if (incx>0) then kx = 1 else kx = 1 - (lenx-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (leny-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the band part of a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,leny y(i) = czero end do else do i = 1,leny y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,leny y(iy) = czero iy = iy + incy end do else do i = 1,leny y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return kup1 = ku + 1 if (stdlib_lsame(trans,'N')) then ! form y := alpha*a*x + y. jx = kx if (incy==1) then do j = 1,n temp = alpha*x(jx) k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(i) = y(i) + temp*a(k+i,j) end do jx = jx + incx end do else do j = 1,n temp = alpha*x(jx) iy = ky k = kup1 - j do i = max(1,j-ku),min(m,j+kl) y(iy) = y(iy) + temp*a(k+i,j) iy = iy + incy end do jx = jx + incx if (j>ku) ky = ky + incy end do end if else ! form y := alpha*a**t*x + y or y := alpha*a**h*x + y. jy = ky if (incx==1) then do j = 1,n temp = czero k = kup1 - j if (noconj) then do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(i) end do else do i = max(1,j-ku),min(m,j+kl) temp = temp + conjg(a(k+i,j))*x(i) end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy end do else do j = 1,n temp = czero ix = kx k = kup1 - j if (noconj) then do i = max(1,j-ku),min(m,j+kl) temp = temp + a(k+i,j)*x(ix) ix = ix + incx end do else do i = max(1,j-ku),min(m,j+kl) temp = temp + conjg(a(k+i,j))*x(ix) ix = ix + incx end do end if y(jy) = y(jy) + alpha*temp jy = jy + incy if (j>ku) kx = kx + incx end do end if end if return end subroutine stdlib${ii}$_${ci}$gbmv #:endif #:endfor pure module subroutine stdlib${ii}$_chbmv(uplo,n,k,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_sp !! CHBMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n hermitian band matrix, with k super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, k, lda, n character, intent(in) :: uplo ! Array Arguments complex(sp), intent(in) :: a(lda,*), x(*) complex(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kplus1, kx, ky, l ! Intrinsic Functions intrinsic :: conjg,max,min,real ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (k<0) then info = 3 else if (lda< (k+1)) then info = 6 else if (incx==0) then info = 8 else if (incy==0) then info = 11 end if if (info/=0) then call stdlib${ii}$_xerbla('CHBMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==czero).and. (beta==cone))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array a ! are accessed sequentially with cone pass through a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,n y(i) = czero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,n y(iy) = czero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return if (stdlib_lsame(uplo,'U')) then ! form y when upper triangle of a is stored. kplus1 = k + 1 if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero l = kplus1 - j do i = max(1,j-k),j - 1 y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(i) end do y(j) = y(j) + temp1*real(a(kplus1,j),KIND=sp) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero ix = kx iy = ky l = kplus1 - j do i = max(1,j-k),j - 1 y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*real(a(kplus1,j),KIND=sp) + alpha*temp2 jx = jx + incx jy = jy + incy if (j>k) then kx = kx + incx ky = ky + incy end if end do end if else ! form y when lower triangle of a is stored. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero y(j) = y(j) + temp1*real(a(1,j),KIND=sp) l = 1 - j do i = j + 1,min(n,j+k) y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero y(jy) = y(jy) + temp1*real(a(1,j),KIND=sp) l = 1 - j ix = jx iy = jy do i = j + 1,min(n,j+k) ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_chbmv pure module subroutine stdlib${ii}$_zhbmv(uplo,n,k,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_dp !! ZHBMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n hermitian band matrix, with k super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, k, lda, n character, intent(in) :: uplo ! Array Arguments complex(dp), intent(in) :: a(lda,*), x(*) complex(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kplus1, kx, ky, l ! Intrinsic Functions intrinsic :: real,conjg,max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (k<0) then info = 3 else if (lda< (k+1)) then info = 6 else if (incx==0) then info = 8 else if (incy==0) then info = 11 end if if (info/=0) then call stdlib${ii}$_xerbla('ZHBMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==czero).and. (beta==cone))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array a ! are accessed sequentially with cone pass through a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,n y(i) = czero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,n y(iy) = czero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return if (stdlib_lsame(uplo,'U')) then ! form y when upper triangle of a is stored. kplus1 = k + 1 if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero l = kplus1 - j do i = max(1,j-k),j - 1 y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(i) end do y(j) = y(j) + temp1*real(a(kplus1,j),KIND=dp) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero ix = kx iy = ky l = kplus1 - j do i = max(1,j-k),j - 1 y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*real(a(kplus1,j),KIND=dp) + alpha*temp2 jx = jx + incx jy = jy + incy if (j>k) then kx = kx + incx ky = ky + incy end if end do end if else ! form y when lower triangle of a is stored. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero y(j) = y(j) + temp1*real(a(1,j),KIND=dp) l = 1 - j do i = j + 1,min(n,j+k) y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero y(jy) = y(jy) + temp1*real(a(1,j),KIND=dp) l = 1 - j ix = jx iy = jy do i = j + 1,min(n,j+k) ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_zhbmv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hbmv(uplo,n,k,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_${ck}$ !! ZHBMV: performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n hermitian band matrix, with k super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, k, lda, n character, intent(in) :: uplo ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), x(*) complex(${ck}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kplus1, kx, ky, l ! Intrinsic Functions intrinsic :: real,conjg,max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (k<0) then info = 3 else if (lda< (k+1)) then info = 6 else if (incx==0) then info = 8 else if (incy==0) then info = 11 end if if (info/=0) then call stdlib${ii}$_xerbla('ZHBMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==czero).and. (beta==cone))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array a ! are accessed sequentially with cone pass through a. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,n y(i) = czero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,n y(iy) = czero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return if (stdlib_lsame(uplo,'U')) then ! form y when upper triangle of a is stored. kplus1 = k + 1 if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero l = kplus1 - j do i = max(1,j-k),j - 1 y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(i) end do y(j) = y(j) + temp1*real(a(kplus1,j),KIND=${ck}$) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero ix = kx iy = ky l = kplus1 - j do i = max(1,j-k),j - 1 y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*real(a(kplus1,j),KIND=${ck}$) + alpha*temp2 jx = jx + incx jy = jy + incy if (j>k) then kx = kx + incx ky = ky + incy end if end do end if else ! form y when lower triangle of a is stored. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero y(j) = y(j) + temp1*real(a(1,j),KIND=${ck}$) l = 1 - j do i = j + 1,min(n,j+k) y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero y(jy) = y(jy) + temp1*real(a(1,j),KIND=${ck}$) l = 1 - j ix = jx iy = jy do i = j + 1,min(n,j+k) ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + conjg(a(l+i,j))*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_${ci}$hbmv #:endif #:endfor #:endfor end submodule stdlib_blas_level2_ban fortran-lang-stdlib-0ede301/src/blas/stdlib_linalg_blas_aux.fypp0000664000175000017500000002410515135654166025265 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES module stdlib_linalg_blas_aux use stdlib_linalg_constants implicit none private public :: sp,dp,qp,lk,ilp public :: stdlib_cabs1 public :: stdlib_lsame #:for ik,it,ii in LINALG_INT_KINDS_TYPES #:for rk,rt,ri in RC_KINDS_TYPES public :: stdlib${ii}$_i${ri}$amax #:endfor public :: stdlib${ii}$_xerbla public :: stdlib${ii}$_xerbla_array #:endfor interface stdlib_cabs1 #:for rk,rt,ri in REAL_KINDS_TYPES module procedure stdlib_${ri}$cabs1 #:endfor end interface stdlib_cabs1 contains #:for ck,ct,ci in REAL_KINDS_TYPES pure elemental real(${ck}$) function stdlib_${ci}$cabs1(z) !! DCABS1 computes |Re(.)| + |Im(.)| of a double complex number ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(${ck}$), intent(in) :: z ! ===================================================================== ! Intrinsic Functions intrinsic :: abs,real,aimag stdlib_${ci}$cabs1 = abs(real(z,KIND=${ck}$)) + abs(aimag(z)) return end function stdlib_${ci}$cabs1 #:endfor pure elemental logical(lk) function stdlib_lsame(ca,cb) !! LSAME returns .TRUE. if CA is the same letter as CB regardless of !! case. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character, intent(in) :: ca, cb ! ===================================================================== ! Intrinsic Functions intrinsic :: ichar ! Local Scalars integer(ilp) :: inta, intb, zcode ! test if the characters are equal stdlib_lsame = ca == cb if (stdlib_lsame) return ! now test for equivalence if both characters are alphabetic. zcode = ichar('Z',kind=ilp) ! use 'z' rather than 'a' so that ascii can be detected on prime ! machines, on which ichar returns a value with bit 8 set. ! ichar('a') on prime machines returns 193 which is the same as ! ichar('a') on an ebcdic machine. inta = ichar(ca,kind=ilp) intb = ichar(cb,kind=ilp) if (zcode==90 .or. zcode==122) then ! ascii is assumed - zcode is the ascii code of either lower or ! upper case 'z'. if (inta>=97 .and. inta<=122) inta = inta - 32 if (intb>=97 .and. intb<=122) intb = intb - 32 else if (zcode==233 .or. zcode==169) then ! ebcdic is assumed - zcode is the ebcdic code of either lower or ! upper case 'z'. if (inta>=129 .and. inta<=137 .or.inta>=145 .and. inta<=153 .or.inta>=162 .and. & inta<=169) inta = inta + 64 if (intb>=129 .and. intb<=137 .or.intb>=145 .and. intb<=153 .or.intb>=162 .and. & intb<=169) intb = intb + 64 else if (zcode==218 .or. zcode==250) then ! ascii is assumed, on prime machines - zcode is the ascii code ! plus 128 of either lower or upper case 'z'. if (inta>=225 .and. inta<=250) inta = inta - 32 if (intb>=225 .and. intb<=250) intb = intb - 32 end if stdlib_lsame = inta == intb ! return end function stdlib_lsame #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure subroutine stdlib${ii}$_xerbla( srname, info ) !! XERBLA is an error handler for the LAPACK routines. !! It is called by an LAPACK routine if an input parameter has an !! invalid value. A message is printed and execution stops. !! Installers may consider modifying the STOP statement in order to !! call system-specific exception-handling facilities. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character(len=*), intent(in) :: srname integer(${ik}$), intent(in) :: info ! ===================================================================== ! Intrinsic Functions intrinsic :: len_trim ! Executable Statements 9999 format( ' ** ON ENTRY TO ', a, ' PARAMETER NUMBER ', i2, ' HAD ','AN ILLEGAL VALUE' ) end subroutine stdlib${ii}$_xerbla pure subroutine stdlib${ii}$_xerbla_array(srname_array, srname_len, info) !! XERBLA_ARRAY assists other languages in calling XERBLA, the LAPACK !! and BLAS error handler. Rather than taking a Fortran string argument !! as the function's name, XERBLA_ARRAY takes an array of single !! characters along with the array's length. XERBLA_ARRAY then copies !! up to 32 characters of that array into a Fortran string and passes !! that to XERBLA. If called with a non-positive SRNAME_LEN, !! XERBLA_ARRAY will call XERBLA with a string of all blank characters. !! Say some macro or other device makes XERBLA_ARRAY available to C99 !! by a name lapack_xerbla and with a common Fortran calling convention. !! Then a C99 program could invoke XERBLA via: !! { !! int flen = strlen(__func__); !! lapack_xerbla(__func__, !! } !! Providing XERBLA_ARRAY is not necessary for intercepting LAPACK !! errors. XERBLA_ARRAY calls XERBLA. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: srname_len, info ! Array Arguments character(1), intent(in) :: srname_array(srname_len) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i ! Local Arrays character*32 srname ! Intrinsic Functions intrinsic :: min,len ! Executable Statements srname = '' do i = 1, min( srname_len, len( srname ) ) srname( i:i ) = srname_array( i ) end do call stdlib${ii}$_xerbla( srname, info ) return end subroutine stdlib${ii}$_xerbla_array #:for rk,rt,ri in REAL_KINDS_TYPES pure integer(${ik}$) function stdlib${ii}$_i${ri}$amax(n,dx,incx) result(iamax) !! IDAMAX: finds the index of the first element having maximum absolute value. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments real(${rk}$), intent(in) :: dx(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: dmax integer(${ik}$) :: i, ix ! Intrinsic Functions intrinsic :: abs iamax = 0 if (n<1 .or. incx<=0) return iamax = 1 if (n==1) return if (incx==1) then ! code for increment equal to 1 dmax = abs(dx(1)) do i = 2,n if (abs(dx(i))>dmax) then iamax = i dmax = abs(dx(i)) end if end do else ! code for increment not equal to 1 ix = 1 dmax = abs(dx(1)) ix = ix + incx do i = 2,n if (abs(dx(ix))>dmax) then iamax = i dmax = abs(dx(ix)) end if ix = ix + incx end do end if return end function stdlib${ii}$_i${ri}$amax #:endfor #:for ck,ct,ci in CMPLX_KINDS_TYPES pure integer(${ik}$) function stdlib${ii}$_i${ci}$amax(n,zx,incx) result(iamax) !! IZAMAX: finds the index of the first element having maximum |Re(.)| + |Im(.)| ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments complex(${ck}$), intent(in) :: zx(*) ! ===================================================================== ! Local Scalars real(${ck}$) :: dmax integer(${ik}$) :: i, ix iamax = 0 if (n<1 .or. incx<=0) return iamax = 1 if (n==1) return if (incx==1) then ! code for increment equal to 1 dmax = stdlib_cabs1(zx(1)) do i = 2,n if (stdlib_cabs1(zx(i))>dmax) then iamax = i dmax = stdlib_cabs1(zx(i)) end if end do else ! code for increment not equal to 1 ix = 1 dmax = stdlib_cabs1(zx(1)) ix = ix + incx do i = 2,n if (stdlib_cabs1(zx(ix))>dmax) then iamax = i dmax = stdlib_cabs1(zx(ix)) end if ix = ix + incx end do end if return end function stdlib${ii}$_i${ci}$amax #:endfor #:endfor end module stdlib_linalg_blas_aux fortran-lang-stdlib-0ede301/src/blas/stdlib_blas_constants.fypp0000664000175000017500000000413015135654166025152 0ustar alastairalastair#:include "common.fypp" #:for ck,ct,ci in REAL_KINDS_TYPES module stdlib_blas_constants_${ck}$ use stdlib_linalg_constants implicit none real(${ck}$), parameter :: negone = -1.00_${ck}$ real(${ck}$), parameter :: zero = 0.00_${ck}$ real(${ck}$), parameter :: half = 0.50_${ck}$ real(${ck}$), parameter :: one = 1.00_${ck}$ real(${ck}$), parameter :: two = 2.00_${ck}$ real(${ck}$), parameter :: three = 3.00_${ck}$ real(${ck}$), parameter :: four = 4.00_${ck}$ real(${ck}$), parameter :: eight = 8.00_${ck}$ real(${ck}$), parameter :: ten = 10.00_${ck}$ complex(${ck}$), parameter :: czero = ( 0.0_${ck}$,0.0_${ck}$) complex(${ck}$), parameter :: chalf = ( 0.5_${ck}$,0.0_${ck}$) complex(${ck}$), parameter :: cone = ( 1.0_${ck}$,0.0_${ck}$) complex(${ck}$), parameter :: cnegone = (-1.0_${ck}$,0.0_${ck}$) ! scaling constants integer, parameter :: maxexp = maxexponent(zero) integer, parameter :: minexp = minexponent(zero) real(${ck}$), parameter :: rradix = real(radix(zero),${ck}$) real(${ck}$), parameter :: ulp = epsilon(zero) real(${ck}$), parameter :: eps = ulp*half real(${ck}$), parameter :: safmin = rradix**max(minexp-1,1-maxexp) real(${ck}$), parameter :: safmax = one/safmin real(${ck}$), parameter :: smlnum = safmin/ulp real(${ck}$), parameter :: bignum = safmax*ulp real(${ck}$), parameter :: rtmin = sqrt(smlnum) real(${ck}$), parameter :: rtmax = sqrt(bignum) ! Blue's scaling constants ! ssml>=1/s and sbig==1/S with s,S as defined in https://doi.org/10.1145/355769.355771 real(${ck}$), parameter :: tsml = rradix**ceiling((minexp-1)*half) real(${ck}$), parameter :: tbig = rradix**floor((maxexp-digits(zero)+1)*half) real(${ck}$), parameter :: ssml = rradix**(-floor((minexp-digits(zero))*half)) real(${ck}$), parameter :: sbig = rradix**(-ceiling((maxexp+digits(zero)-1)*half)) end module #:endfor fortran-lang-stdlib-0ede301/src/blas/CMakeLists.txt0000664000175000017500000000130215135654166022432 0ustar alastairalastairset(blas_fppFiles stdlib_blas_constants.fypp stdlib_blas.fypp stdlib_blas_level1.fypp stdlib_blas_level2_ban.fypp stdlib_blas_level2_gen.fypp stdlib_blas_level2_pac.fypp stdlib_blas_level2_sym.fypp stdlib_blas_level2_tri.fypp stdlib_blas_level3_gen.fypp stdlib_blas_level3_sym.fypp stdlib_blas_level3_tri.fypp stdlib_linalg_blas_aux.fypp ) set(blas_cppFiles stdlib_linalg_blas.fypp ) configure_stdlib_target(${PROJECT_NAME}_blas "" blas_fppFiles blas_cppFiles) if(BLAS_FOUND) target_link_libraries(${PROJECT_NAME}_blas PUBLIC "BLAS::BLAS") endif() target_link_libraries(${PROJECT_NAME}_blas PUBLIC ${PROJECT_NAME}_core ${PROJECT_NAME}_linalg_core) fortran-lang-stdlib-0ede301/src/blas/stdlib_blas_level2_sym.fypp0000664000175000017500000012630115135654166025224 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_blas) stdlib_blas_level2_sym implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_ssymv(uplo,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_sp !! SSYMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n character, intent(in) :: uplo ! Array Arguments real(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(sp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through the triangular part ! of a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,n y(i) = zero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,n y(iy) = zero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return if (stdlib_lsame(uplo,'U')) then ! form y when a is stored in upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero do i = 1,j - 1 y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(i) end do y(j) = y(j) + temp1*a(j,j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero ix = kx iy = ky do i = 1,j - 1 y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*a(j,j) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if else ! form y when a is stored in lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero y(j) = y(j) + temp1*a(j,j) do i = j + 1,n y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero y(jy) = y(jy) + temp1*a(j,j) ix = jx iy = jy do i = j + 1,n ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_ssymv pure module subroutine stdlib${ii}$_dsymv(uplo,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_dp !! DSYMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n character, intent(in) :: uplo ! Array Arguments real(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(dp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through the triangular part ! of a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,n y(i) = zero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,n y(iy) = zero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return if (stdlib_lsame(uplo,'U')) then ! form y when a is stored in upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero do i = 1,j - 1 y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(i) end do y(j) = y(j) + temp1*a(j,j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero ix = kx iy = ky do i = 1,j - 1 y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*a(j,j) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if else ! form y when a is stored in lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero y(j) = y(j) + temp1*a(j,j) do i = j + 1,n y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero y(jy) = y(jy) + temp1*a(j,j) ix = jx iy = jy do i = j + 1,n ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_dsymv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$symv(uplo,n,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_${rk}$ !! DSYMV: performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n character, intent(in) :: uplo ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), x(*) real(${rk}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through the triangular part ! of a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,n y(i) = zero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,n y(iy) = zero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return if (stdlib_lsame(uplo,'U')) then ! form y when a is stored in upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero do i = 1,j - 1 y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(i) end do y(j) = y(j) + temp1*a(j,j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero ix = kx iy = ky do i = 1,j - 1 y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*a(j,j) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if else ! form y when a is stored in lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero y(j) = y(j) + temp1*a(j,j) do i = j + 1,n y(i) = y(i) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero y(jy) = y(jy) + temp1*a(j,j) ix = jx iy = jy do i = j + 1,n ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(i,j) temp2 = temp2 + a(i,j)*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_${ri}$symv #:endif #:endfor pure module subroutine stdlib${ii}$_ssyr(uplo,n,alpha,x,incx,a,lda) use stdlib_blas_constants_sp !! SSYR performs the symmetric rank 1 operation !! A := alpha*x*x**T + A, !! where alpha is a real scalar, x is an n element vector and A is an !! n by n symmetric matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, lda, n character, intent(in) :: uplo ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: x(*) ! ===================================================================== ! Local Scalars real(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, kx ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through the triangular part ! of a. if (stdlib_lsame(uplo,'U')) then ! form a when a is stored in the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) do i = 1,j a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do end if end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = kx iy = ky do i = 1,j a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy end do end if else ! form a when a is stored in the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) do i = j,n a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do end if end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = jx iy = jy do i = j,n a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_ssyr2 pure module subroutine stdlib${ii}$_dsyr2(uplo,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_dp !! DSYR2 performs the symmetric rank 2 operation !! A := alpha*x*y**T + alpha*y*x**T + A, !! where alpha is a scalar, x and y are n element vectors and A is an n !! by n symmetric matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, n character, intent(in) :: uplo ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(dp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through the triangular part ! of a. if (stdlib_lsame(uplo,'U')) then ! form a when a is stored in the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) do i = 1,j a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do end if end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = kx iy = ky do i = 1,j a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy end do end if else ! form a when a is stored in the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) do i = j,n a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do end if end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = jx iy = jy do i = j,n a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_dsyr2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$syr2(uplo,n,alpha,x,incx,y,incy,a,lda) use stdlib_blas_constants_${rk}$ !! DSYR2: performs the symmetric rank 2 operation !! A := alpha*x*y**T + alpha*y*x**T + A, !! where alpha is a scalar, x and y are n element vectors and A is an n !! by n symmetric matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${rk}$), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, lda, n character, intent(in) :: uplo ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 else if (lda0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through the triangular part ! of a. if (stdlib_lsame(uplo,'U')) then ! form a when a is stored in the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) do i = 1,j a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do end if end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = kx iy = ky do i = 1,j a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy end do end if else ! form a when a is stored in the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) do i = j,n a(i,j) = a(i,j) + x(i)*temp1 + y(i)*temp2 end do end if end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = jx iy = jy do i = j,n a(i,j) = a(i,j) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_${ri}$syr2 #:endif #:endfor #:endfor end submodule stdlib_blas_level2_sym fortran-lang-stdlib-0ede301/src/blas/stdlib_blas_level2_pac.fypp0000664000175000017500000034466415135654166025175 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_blas) stdlib_blas_level2_pac implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sspmv(uplo,n,alpha,ap,x,incx,beta,y,incy) use stdlib_blas_constants_sp !! SSPMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments real(sp), intent(in) :: ap(*), x(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(sp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 6 else if (incy==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('SSPMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==zero).and. (beta==one))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with one pass through ap. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,n y(i) = zero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,n y(iy) = zero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return kk = 1 if (stdlib_lsame(uplo,'U')) then ! form y when ap contains the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero k = kk do i = 1,j - 1 y(i) = y(i) + temp1*ap(k) temp2 = temp2 + ap(k)*x(i) k = k + 1 end do y(j) = y(j) + temp1*ap(kk+j-1) + alpha*temp2 kk = kk + j end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero ix = kx iy = ky do k = kk,kk + j - 2 y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + ap(k)*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*ap(kk+j-1) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form y when ap contains the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero y(j) = y(j) + temp1*ap(kk) k = kk + 1 do i = j + 1,n y(i) = y(i) + temp1*ap(k) temp2 = temp2 + ap(k)*x(i) k = k + 1 end do y(j) = y(j) + alpha*temp2 kk = kk + (n-j+1) end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero y(jy) = y(jy) + temp1*ap(kk) ix = jx iy = jy do k = kk + 1,kk + n - j ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + ap(k)*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + (n-j+1) end do end if end if return end subroutine stdlib${ii}$_sspmv pure module subroutine stdlib${ii}$_dspmv(uplo,n,alpha,ap,x,incx,beta,y,incy) use stdlib_blas_constants_dp !! DSPMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments real(dp), intent(in) :: ap(*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(dp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 6 else if (incy==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('DSPMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==zero).and. (beta==one))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with one pass through ap. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,n y(i) = zero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,n y(iy) = zero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return kk = 1 if (stdlib_lsame(uplo,'U')) then ! form y when ap contains the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero k = kk do i = 1,j - 1 y(i) = y(i) + temp1*ap(k) temp2 = temp2 + ap(k)*x(i) k = k + 1 end do y(j) = y(j) + temp1*ap(kk+j-1) + alpha*temp2 kk = kk + j end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero ix = kx iy = ky do k = kk,kk + j - 2 y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + ap(k)*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*ap(kk+j-1) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form y when ap contains the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero y(j) = y(j) + temp1*ap(kk) k = kk + 1 do i = j + 1,n y(i) = y(i) + temp1*ap(k) temp2 = temp2 + ap(k)*x(i) k = k + 1 end do y(j) = y(j) + alpha*temp2 kk = kk + (n-j+1) end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero y(jy) = y(jy) + temp1*ap(kk) ix = jx iy = jy do k = kk + 1,kk + n - j ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + ap(k)*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + (n-j+1) end do end if end if return end subroutine stdlib${ii}$_dspmv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$spmv(uplo,n,alpha,ap,x,incx,beta,y,incy) use stdlib_blas_constants_${rk}$ !! DSPMV: performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments real(${rk}$), intent(in) :: ap(*), x(*) real(${rk}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 6 else if (incy==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('DSPMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==zero).and. (beta==one))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with one pass through ap. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,n y(i) = zero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,n y(iy) = zero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return kk = 1 if (stdlib_lsame(uplo,'U')) then ! form y when ap contains the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero k = kk do i = 1,j - 1 y(i) = y(i) + temp1*ap(k) temp2 = temp2 + ap(k)*x(i) k = k + 1 end do y(j) = y(j) + temp1*ap(kk+j-1) + alpha*temp2 kk = kk + j end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero ix = kx iy = ky do k = kk,kk + j - 2 y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + ap(k)*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*ap(kk+j-1) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form y when ap contains the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero y(j) = y(j) + temp1*ap(kk) k = kk + 1 do i = j + 1,n y(i) = y(i) + temp1*ap(k) temp2 = temp2 + ap(k)*x(i) k = k + 1 end do y(j) = y(j) + alpha*temp2 kk = kk + (n-j+1) end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero y(jy) = y(jy) + temp1*ap(kk) ix = jx iy = jy do k = kk + 1,kk + n - j ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + ap(k)*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + (n-j+1) end do end if end if return end subroutine stdlib${ii}$_${ri}$spmv #:endif #:endfor pure module subroutine stdlib${ii}$_ssbmv(uplo,n,k,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_sp !! SSBMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric band matrix, with k super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, k, lda, n character, intent(in) :: uplo ! Array Arguments real(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(sp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kplus1, kx, ky, l ! Intrinsic Functions intrinsic :: max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (k<0) then info = 3 else if (lda< (k+1)) then info = 6 else if (incx==0) then info = 8 else if (incy==0) then info = 11 end if if (info/=0) then call stdlib${ii}$_xerbla('SSBMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==zero).and. (beta==one))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array a ! are accessed sequentially with one pass through a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,n y(i) = zero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,n y(iy) = zero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return if (stdlib_lsame(uplo,'U')) then ! form y when upper triangle of a is stored. kplus1 = k + 1 if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero l = kplus1 - j do i = max(1,j-k),j - 1 y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(i) end do y(j) = y(j) + temp1*a(kplus1,j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero ix = kx iy = ky l = kplus1 - j do i = max(1,j-k),j - 1 y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*a(kplus1,j) + alpha*temp2 jx = jx + incx jy = jy + incy if (j>k) then kx = kx + incx ky = ky + incy end if end do end if else ! form y when lower triangle of a is stored. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero y(j) = y(j) + temp1*a(1,j) l = 1 - j do i = j + 1,min(n,j+k) y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero y(jy) = y(jy) + temp1*a(1,j) l = 1 - j ix = jx iy = jy do i = j + 1,min(n,j+k) ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_ssbmv pure module subroutine stdlib${ii}$_dsbmv(uplo,n,k,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_dp !! DSBMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric band matrix, with k super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, k, lda, n character, intent(in) :: uplo ! Array Arguments real(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(dp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kplus1, kx, ky, l ! Intrinsic Functions intrinsic :: max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (k<0) then info = 3 else if (lda< (k+1)) then info = 6 else if (incx==0) then info = 8 else if (incy==0) then info = 11 end if if (info/=0) then call stdlib${ii}$_xerbla('DSBMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==zero).and. (beta==one))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array a ! are accessed sequentially with one pass through a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,n y(i) = zero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,n y(iy) = zero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return if (stdlib_lsame(uplo,'U')) then ! form y when upper triangle of a is stored. kplus1 = k + 1 if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero l = kplus1 - j do i = max(1,j-k),j - 1 y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(i) end do y(j) = y(j) + temp1*a(kplus1,j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero ix = kx iy = ky l = kplus1 - j do i = max(1,j-k),j - 1 y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*a(kplus1,j) + alpha*temp2 jx = jx + incx jy = jy + incy if (j>k) then kx = kx + incx ky = ky + incy end if end do end if else ! form y when lower triangle of a is stored. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero y(j) = y(j) + temp1*a(1,j) l = 1 - j do i = j + 1,min(n,j+k) y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero y(jy) = y(jy) + temp1*a(1,j) l = 1 - j ix = jx iy = jy do i = j + 1,min(n,j+k) ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_dsbmv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sbmv(uplo,n,k,alpha,a,lda,x,incx,beta,y,incy) use stdlib_blas_constants_${rk}$ !! DSBMV: performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric band matrix, with k super-diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, k, lda, n character, intent(in) :: uplo ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), x(*) real(${rk}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kplus1, kx, ky, l ! Intrinsic Functions intrinsic :: max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (k<0) then info = 3 else if (lda< (k+1)) then info = 6 else if (incx==0) then info = 8 else if (incy==0) then info = 11 end if if (info/=0) then call stdlib${ii}$_xerbla('DSBMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==zero).and. (beta==one))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array a ! are accessed sequentially with one pass through a. ! first form y := beta*y. if (beta/=one) then if (incy==1) then if (beta==zero) then do i = 1,n y(i) = zero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==zero) then do i = 1,n y(iy) = zero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==zero) return if (stdlib_lsame(uplo,'U')) then ! form y when upper triangle of a is stored. kplus1 = k + 1 if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero l = kplus1 - j do i = max(1,j-k),j - 1 y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(i) end do y(j) = y(j) + temp1*a(kplus1,j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero ix = kx iy = ky l = kplus1 - j do i = max(1,j-k),j - 1 y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*a(kplus1,j) + alpha*temp2 jx = jx + incx jy = jy + incy if (j>k) then kx = kx + incx ky = ky + incy end if end do end if else ! form y when lower triangle of a is stored. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = zero y(j) = y(j) + temp1*a(1,j) l = 1 - j do i = j + 1,min(n,j+k) y(i) = y(i) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(i) end do y(j) = y(j) + alpha*temp2 end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = zero y(jy) = y(jy) + temp1*a(1,j) l = 1 - j ix = jx iy = jy do i = j + 1,min(n,j+k) ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*a(l+i,j) temp2 = temp2 + a(l+i,j)*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_${ri}$sbmv #:endif #:endfor pure module subroutine stdlib${ii}$_sspr(uplo,n,alpha,x,incx,ap) use stdlib_blas_constants_sp !! SSPR performs the symmetric rank 1 operation !! A := alpha*x*x**T + A, !! where alpha is a real scalar, x is an n element vector and A is an !! n by n symmetric matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, n character, intent(in) :: uplo ! Array Arguments real(sp), intent(inout) :: ap(*) real(sp), intent(in) :: x(*) ! ===================================================================== ! Local Scalars real(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 end if if (info/=0) then call stdlib${ii}$_xerbla('SSPR ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==zero)) return ! set the start point in x if the increment is not unity. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with one pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=zero) then temp = alpha*x(j) k = kk do i = 1,j ap(k) = ap(k) + x(i)*temp k = k + 1 end do end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=zero) then temp = alpha*x(jx) ix = kx do k = kk,kk + j - 1 ap(k) = ap(k) + x(ix)*temp ix = ix + incx end do end if jx = jx + incx kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=zero) then temp = alpha*x(j) k = kk do i = j,n ap(k) = ap(k) + x(i)*temp k = k + 1 end do end if kk = kk + n - j + 1 end do else jx = kx do j = 1,n if (x(jx)/=zero) then temp = alpha*x(jx) ix = jx do k = kk,kk + n - j ap(k) = ap(k) + x(ix)*temp ix = ix + incx end do end if jx = jx + incx kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_sspr pure module subroutine stdlib${ii}$_dspr(uplo,n,alpha,x,incx,ap) use stdlib_blas_constants_dp !! DSPR performs the symmetric rank 1 operation !! A := alpha*x*x**T + A, !! where alpha is a real scalar, x is an n element vector and A is an !! n by n symmetric matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, n character, intent(in) :: uplo ! Array Arguments real(dp), intent(inout) :: ap(*) real(dp), intent(in) :: x(*) ! ===================================================================== ! Local Scalars real(dp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 end if if (info/=0) then call stdlib${ii}$_xerbla('DSPR ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==zero)) return ! set the start point in x if the increment is not unity. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with one pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=zero) then temp = alpha*x(j) k = kk do i = 1,j ap(k) = ap(k) + x(i)*temp k = k + 1 end do end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=zero) then temp = alpha*x(jx) ix = kx do k = kk,kk + j - 1 ap(k) = ap(k) + x(ix)*temp ix = ix + incx end do end if jx = jx + incx kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=zero) then temp = alpha*x(j) k = kk do i = j,n ap(k) = ap(k) + x(i)*temp k = k + 1 end do end if kk = kk + n - j + 1 end do else jx = kx do j = 1,n if (x(jx)/=zero) then temp = alpha*x(jx) ix = jx do k = kk,kk + n - j ap(k) = ap(k) + x(ix)*temp ix = ix + incx end do end if jx = jx + incx kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_dspr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$spr(uplo,n,alpha,x,incx,ap) use stdlib_blas_constants_${rk}$ !! DSPR: performs the symmetric rank 1 operation !! A := alpha*x*x**T + A, !! where alpha is a real scalar, x is an n element vector and A is an !! n by n symmetric matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${rk}$), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, n character, intent(in) :: uplo ! Array Arguments real(${rk}$), intent(inout) :: ap(*) real(${rk}$), intent(in) :: x(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 end if if (info/=0) then call stdlib${ii}$_xerbla('DSPR ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==zero)) return ! set the start point in x if the increment is not unity. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with one pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=zero) then temp = alpha*x(j) k = kk do i = 1,j ap(k) = ap(k) + x(i)*temp k = k + 1 end do end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=zero) then temp = alpha*x(jx) ix = kx do k = kk,kk + j - 1 ap(k) = ap(k) + x(ix)*temp ix = ix + incx end do end if jx = jx + incx kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=zero) then temp = alpha*x(j) k = kk do i = j,n ap(k) = ap(k) + x(i)*temp k = k + 1 end do end if kk = kk + n - j + 1 end do else jx = kx do j = 1,n if (x(jx)/=zero) then temp = alpha*x(jx) ix = jx do k = kk,kk + n - j ap(k) = ap(k) + x(ix)*temp ix = ix + incx end do end if jx = jx + incx kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_${ri}$spr #:endif #:endfor pure module subroutine stdlib${ii}$_sspr2(uplo,n,alpha,x,incx,y,incy,ap) use stdlib_blas_constants_sp !! SSPR2 performs the symmetric rank 2 operation !! A := alpha*x*y**T + alpha*y*x**T + A, !! where alpha is a scalar, x and y are n element vectors and A is an !! n by n symmetric matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments real(sp), intent(inout) :: ap(*) real(sp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(sp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('SSPR2 ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==zero)) return ! set up the start points in x and y if the increments are not both ! unity. if ((incx/=1) .or. (incy/=1)) then if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with one pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) k = kk do i = 1,j ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do end if kk = kk + j end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = kx iy = ky do k = kk,kk + j - 1 ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) k = kk do i = j,n ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do end if kk = kk + n - j + 1 end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = jx iy = jy do k = kk,kk + n - j ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_sspr2 pure module subroutine stdlib${ii}$_dspr2(uplo,n,alpha,x,incx,y,incy,ap) use stdlib_blas_constants_dp !! DSPR2 performs the symmetric rank 2 operation !! A := alpha*x*y**T + alpha*y*x**T + A, !! where alpha is a scalar, x and y are n element vectors and A is an !! n by n symmetric matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments real(dp), intent(inout) :: ap(*) real(dp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(dp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('DSPR2 ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==zero)) return ! set up the start points in x and y if the increments are not both ! unity. if ((incx/=1) .or. (incy/=1)) then if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with one pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) k = kk do i = 1,j ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do end if kk = kk + j end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = kx iy = ky do k = kk,kk + j - 1 ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) k = kk do i = j,n ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do end if kk = kk + n - j + 1 end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = jx iy = jy do k = kk,kk + n - j ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_dspr2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$spr2(uplo,n,alpha,x,incx,y,incy,ap) use stdlib_blas_constants_${rk}$ !! DSPR2: performs the symmetric rank 2 operation !! A := alpha*x*y**T + alpha*y*x**T + A, !! where alpha is a scalar, x and y are n element vectors and A is an !! n by n symmetric matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${rk}$), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments real(${rk}$), intent(inout) :: ap(*) real(${rk}$), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('DSPR2 ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==zero)) return ! set up the start points in x and y if the increments are not both ! unity. if ((incx/=1) .or. (incy/=1)) then if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with one pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) k = kk do i = 1,j ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do end if kk = kk + j end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = kx iy = ky do k = kk,kk + j - 1 ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=zero) .or. (y(j)/=zero)) then temp1 = alpha*y(j) temp2 = alpha*x(j) k = kk do i = j,n ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do end if kk = kk + n - j + 1 end do else do j = 1,n if ((x(jx)/=zero) .or. (y(jy)/=zero)) then temp1 = alpha*y(jy) temp2 = alpha*x(jx) ix = jx iy = jy do k = kk,kk + n - j ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do end if jx = jx + incx jy = jy + incy kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_${ri}$spr2 #:endif #:endfor pure module subroutine stdlib${ii}$_chpmv(uplo,n,alpha,ap,x,incx,beta,y,incy) use stdlib_blas_constants_sp !! CHPMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n hermitian matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments complex(sp), intent(in) :: ap(*), x(*) complex(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! Intrinsic Functions intrinsic :: conjg,real ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 6 else if (incy==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('CHPMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==czero).and. (beta==cone))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,n y(i) = czero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,n y(iy) = czero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return kk = 1 if (stdlib_lsame(uplo,'U')) then ! form y when ap contains the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero k = kk do i = 1,j - 1 y(i) = y(i) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(i) k = k + 1 end do y(j) = y(j) + temp1*real(ap(kk+j-1),KIND=sp) + alpha*temp2 kk = kk + j end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero ix = kx iy = ky do k = kk,kk + j - 2 y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*real(ap(kk+j-1),KIND=sp) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form y when ap contains the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero y(j) = y(j) + temp1*real(ap(kk),KIND=sp) k = kk + 1 do i = j + 1,n y(i) = y(i) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(i) k = k + 1 end do y(j) = y(j) + alpha*temp2 kk = kk + (n-j+1) end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero y(jy) = y(jy) + temp1*real(ap(kk),KIND=sp) ix = jx iy = jy do k = kk + 1,kk + n - j ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + (n-j+1) end do end if end if return end subroutine stdlib${ii}$_chpmv pure module subroutine stdlib${ii}$_zhpmv(uplo,n,alpha,ap,x,incx,beta,y,incy) use stdlib_blas_constants_dp !! ZHPMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n hermitian matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments complex(dp), intent(in) :: ap(*), x(*) complex(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! Intrinsic Functions intrinsic :: real,conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 6 else if (incy==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('ZHPMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==czero).and. (beta==cone))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,n y(i) = czero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,n y(iy) = czero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return kk = 1 if (stdlib_lsame(uplo,'U')) then ! form y when ap contains the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero k = kk do i = 1,j - 1 y(i) = y(i) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(i) k = k + 1 end do y(j) = y(j) + temp1*real(ap(kk+j-1),KIND=dp) + alpha*temp2 kk = kk + j end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero ix = kx iy = ky do k = kk,kk + j - 2 y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*real(ap(kk+j-1),KIND=dp) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form y when ap contains the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero y(j) = y(j) + temp1*real(ap(kk),KIND=dp) k = kk + 1 do i = j + 1,n y(i) = y(i) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(i) k = k + 1 end do y(j) = y(j) + alpha*temp2 kk = kk + (n-j+1) end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero y(jy) = y(jy) + temp1*real(ap(kk),KIND=dp) ix = jx iy = jy do k = kk + 1,kk + n - j ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + (n-j+1) end do end if end if return end subroutine stdlib${ii}$_zhpmv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hpmv(uplo,n,alpha,ap,x,incx,beta,y,incy) use stdlib_blas_constants_${ck}$ !! ZHPMV: performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n hermitian matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments complex(${ck}$), intent(in) :: ap(*), x(*) complex(${ck}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! Intrinsic Functions intrinsic :: real,conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 6 else if (incy==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('ZHPMV ',info) return end if ! quick return if possible. if ((n==0) .or. ((alpha==czero).and. (beta==cone))) return ! set up the start points in x and y. if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. ! first form y := beta*y. if (beta/=cone) then if (incy==1) then if (beta==czero) then do i = 1,n y(i) = czero end do else do i = 1,n y(i) = beta*y(i) end do end if else iy = ky if (beta==czero) then do i = 1,n y(iy) = czero iy = iy + incy end do else do i = 1,n y(iy) = beta*y(iy) iy = iy + incy end do end if end if end if if (alpha==czero) return kk = 1 if (stdlib_lsame(uplo,'U')) then ! form y when ap contains the upper triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero k = kk do i = 1,j - 1 y(i) = y(i) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(i) k = k + 1 end do y(j) = y(j) + temp1*real(ap(kk+j-1),KIND=${ck}$) + alpha*temp2 kk = kk + j end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero ix = kx iy = ky do k = kk,kk + j - 2 y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(ix) ix = ix + incx iy = iy + incy end do y(jy) = y(jy) + temp1*real(ap(kk+j-1),KIND=${ck}$) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form y when ap contains the lower triangle. if ((incx==1) .and. (incy==1)) then do j = 1,n temp1 = alpha*x(j) temp2 = czero y(j) = y(j) + temp1*real(ap(kk),KIND=${ck}$) k = kk + 1 do i = j + 1,n y(i) = y(i) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(i) k = k + 1 end do y(j) = y(j) + alpha*temp2 kk = kk + (n-j+1) end do else jx = kx jy = ky do j = 1,n temp1 = alpha*x(jx) temp2 = czero y(jy) = y(jy) + temp1*real(ap(kk),KIND=${ck}$) ix = jx iy = jy do k = kk + 1,kk + n - j ix = ix + incx iy = iy + incy y(iy) = y(iy) + temp1*ap(k) temp2 = temp2 + conjg(ap(k))*x(ix) end do y(jy) = y(jy) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + (n-j+1) end do end if end if return end subroutine stdlib${ii}$_${ci}$hpmv #:endif #:endfor pure module subroutine stdlib${ii}$_chpr(uplo,n,alpha,x,incx,ap) use stdlib_blas_constants_sp !! CHPR performs the hermitian rank 1 operation !! A := alpha*x*x**H + A, !! where alpha is a real scalar, x is an n element vector and A is an !! n by n hermitian matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, n character, intent(in) :: uplo ! Array Arguments complex(sp), intent(inout) :: ap(*) complex(sp), intent(in) :: x(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx ! Intrinsic Functions intrinsic :: conjg,real ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 end if if (info/=0) then call stdlib${ii}$_xerbla('CHPR ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==real(czero,KIND=sp))) return ! set the start point in x if the increment is not unity. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = alpha*conjg(x(j)) k = kk do i = 1,j - 1 ap(k) = ap(k) + x(i)*temp k = k + 1 end do ap(kk+j-1) = real(ap(kk+j-1),KIND=sp) + real(x(j)*temp,KIND=sp) else ap(kk+j-1) = real(ap(kk+j-1),KIND=sp) end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = alpha*conjg(x(jx)) ix = kx do k = kk,kk + j - 2 ap(k) = ap(k) + x(ix)*temp ix = ix + incx end do ap(kk+j-1) = real(ap(kk+j-1),KIND=sp) + real(x(jx)*temp,KIND=sp) else ap(kk+j-1) = real(ap(kk+j-1),KIND=sp) end if jx = jx + incx kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = alpha*conjg(x(j)) ap(kk) = real(ap(kk),KIND=sp) + real(temp*x(j),KIND=sp) k = kk + 1 do i = j + 1,n ap(k) = ap(k) + x(i)*temp k = k + 1 end do else ap(kk) = real(ap(kk),KIND=sp) end if kk = kk + n - j + 1 end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = alpha*conjg(x(jx)) ap(kk) = real(ap(kk),KIND=sp) + real(temp*x(jx),KIND=sp) ix = jx do k = kk + 1,kk + n - j ix = ix + incx ap(k) = ap(k) + x(ix)*temp end do else ap(kk) = real(ap(kk),KIND=sp) end if jx = jx + incx kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_chpr pure module subroutine stdlib${ii}$_zhpr(uplo,n,alpha,x,incx,ap) use stdlib_blas_constants_dp !! ZHPR performs the hermitian rank 1 operation !! A := alpha*x*x**H + A, !! where alpha is a real scalar, x is an n element vector and A is an !! n by n hermitian matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, n character, intent(in) :: uplo ! Array Arguments complex(dp), intent(inout) :: ap(*) complex(dp), intent(in) :: x(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx ! Intrinsic Functions intrinsic :: real,conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 end if if (info/=0) then call stdlib${ii}$_xerbla('ZHPR ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==real(czero,KIND=dp))) return ! set the start point in x if the increment is not unity. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = alpha*conjg(x(j)) k = kk do i = 1,j - 1 ap(k) = ap(k) + x(i)*temp k = k + 1 end do ap(kk+j-1) = real(ap(kk+j-1),KIND=dp) + real(x(j)*temp,KIND=dp) else ap(kk+j-1) = real(ap(kk+j-1),KIND=dp) end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = alpha*conjg(x(jx)) ix = kx do k = kk,kk + j - 2 ap(k) = ap(k) + x(ix)*temp ix = ix + incx end do ap(kk+j-1) = real(ap(kk+j-1),KIND=dp) + real(x(jx)*temp,KIND=dp) else ap(kk+j-1) = real(ap(kk+j-1),KIND=dp) end if jx = jx + incx kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = alpha*conjg(x(j)) ap(kk) = real(ap(kk),KIND=dp) + real(temp*x(j),KIND=dp) k = kk + 1 do i = j + 1,n ap(k) = ap(k) + x(i)*temp k = k + 1 end do else ap(kk) = real(ap(kk),KIND=dp) end if kk = kk + n - j + 1 end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = alpha*conjg(x(jx)) ap(kk) = real(ap(kk),KIND=dp) + real(temp*x(jx),KIND=dp) ix = jx do k = kk + 1,kk + n - j ix = ix + incx ap(k) = ap(k) + x(ix)*temp end do else ap(kk) = real(ap(kk),KIND=dp) end if jx = jx + incx kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_zhpr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hpr(uplo,n,alpha,x,incx,ap) use stdlib_blas_constants_${ck}$ !! ZHPR: performs the hermitian rank 1 operation !! A := alpha*x*x**H + A, !! where alpha is a real scalar, x is an n element vector and A is an !! n by n hermitian matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${ck}$), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, n character, intent(in) :: uplo ! Array Arguments complex(${ck}$), intent(inout) :: ap(*) complex(${ck}$), intent(in) :: x(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx ! Intrinsic Functions intrinsic :: real,conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 end if if (info/=0) then call stdlib${ii}$_xerbla('ZHPR ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==real(czero,KIND=${ck}$))) return ! set the start point in x if the increment is not unity. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = alpha*conjg(x(j)) k = kk do i = 1,j - 1 ap(k) = ap(k) + x(i)*temp k = k + 1 end do ap(kk+j-1) = real(ap(kk+j-1),KIND=${ck}$) + real(x(j)*temp,KIND=${ck}$) else ap(kk+j-1) = real(ap(kk+j-1),KIND=${ck}$) end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = alpha*conjg(x(jx)) ix = kx do k = kk,kk + j - 2 ap(k) = ap(k) + x(ix)*temp ix = ix + incx end do ap(kk+j-1) = real(ap(kk+j-1),KIND=${ck}$) + real(x(jx)*temp,KIND=${ck}$) else ap(kk+j-1) = real(ap(kk+j-1),KIND=${ck}$) end if jx = jx + incx kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = alpha*conjg(x(j)) ap(kk) = real(ap(kk),KIND=${ck}$) + real(temp*x(j),KIND=${ck}$) k = kk + 1 do i = j + 1,n ap(k) = ap(k) + x(i)*temp k = k + 1 end do else ap(kk) = real(ap(kk),KIND=${ck}$) end if kk = kk + n - j + 1 end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = alpha*conjg(x(jx)) ap(kk) = real(ap(kk),KIND=${ck}$) + real(temp*x(jx),KIND=${ck}$) ix = jx do k = kk + 1,kk + n - j ix = ix + incx ap(k) = ap(k) + x(ix)*temp end do else ap(kk) = real(ap(kk),KIND=${ck}$) end if jx = jx + incx kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_${ci}$hpr #:endif #:endfor pure module subroutine stdlib${ii}$_chpr2(uplo,n,alpha,x,incx,y,incy,ap) use stdlib_blas_constants_sp !! CHPR2 performs the hermitian rank 2 operation !! A := alpha*x*y**H + conjg( alpha )*y*x**H + A, !! where alpha is a scalar, x and y are n element vectors and A is an !! n by n hermitian matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(sp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments complex(sp), intent(inout) :: ap(*) complex(sp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! Intrinsic Functions intrinsic :: conjg,real ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('CHPR2 ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==czero)) return ! set up the start points in x and y if the increments are not both ! unity. if ((incx/=1) .or. (incy/=1)) then if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) k = kk do i = 1,j - 1 ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do ap(kk+j-1) = real(ap(kk+j-1),KIND=sp) +real(x(j)*temp1+y(j)*temp2,& KIND=sp) else ap(kk+j-1) = real(ap(kk+j-1),KIND=sp) end if kk = kk + j end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) ix = kx iy = ky do k = kk,kk + j - 2 ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do ap(kk+j-1) = real(ap(kk+j-1),KIND=sp) +real(x(jx)*temp1+y(jy)*temp2,& KIND=sp) else ap(kk+j-1) = real(ap(kk+j-1),KIND=sp) end if jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) ap(kk) = real(ap(kk),KIND=sp) +real(x(j)*temp1+y(j)*temp2,KIND=sp) k = kk + 1 do i = j + 1,n ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do else ap(kk) = real(ap(kk),KIND=sp) end if kk = kk + n - j + 1 end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) ap(kk) = real(ap(kk),KIND=sp) +real(x(jx)*temp1+y(jy)*temp2,KIND=sp) ix = jx iy = jy do k = kk + 1,kk + n - j ix = ix + incx iy = iy + incy ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 end do else ap(kk) = real(ap(kk),KIND=sp) end if jx = jx + incx jy = jy + incy kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_chpr2 pure module subroutine stdlib${ii}$_zhpr2(uplo,n,alpha,x,incx,y,incy,ap) use stdlib_blas_constants_dp !! ZHPR2 performs the hermitian rank 2 operation !! A := alpha*x*y**H + conjg( alpha )*y*x**H + A, !! where alpha is a scalar, x and y are n element vectors and A is an !! n by n hermitian matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(dp), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments complex(dp), intent(inout) :: ap(*) complex(dp), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! Intrinsic Functions intrinsic :: real,conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('ZHPR2 ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==czero)) return ! set up the start points in x and y if the increments are not both ! unity. if ((incx/=1) .or. (incy/=1)) then if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) k = kk do i = 1,j - 1 ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do ap(kk+j-1) = real(ap(kk+j-1),KIND=dp) +real(x(j)*temp1+y(j)*temp2,& KIND=dp) else ap(kk+j-1) = real(ap(kk+j-1),KIND=dp) end if kk = kk + j end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) ix = kx iy = ky do k = kk,kk + j - 2 ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do ap(kk+j-1) = real(ap(kk+j-1),KIND=dp) +real(x(jx)*temp1+y(jy)*temp2,& KIND=dp) else ap(kk+j-1) = real(ap(kk+j-1),KIND=dp) end if jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) ap(kk) = real(ap(kk),KIND=dp) +real(x(j)*temp1+y(j)*temp2,KIND=dp) k = kk + 1 do i = j + 1,n ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do else ap(kk) = real(ap(kk),KIND=dp) end if kk = kk + n - j + 1 end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) ap(kk) = real(ap(kk),KIND=dp) +real(x(jx)*temp1+y(jy)*temp2,KIND=dp) ix = jx iy = jy do k = kk + 1,kk + n - j ix = ix + incx iy = iy + incy ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 end do else ap(kk) = real(ap(kk),KIND=dp) end if jx = jx + incx jy = jy + incy kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_zhpr2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hpr2(uplo,n,alpha,x,incx,y,incy,ap) use stdlib_blas_constants_${ck}$ !! ZHPR2: performs the hermitian rank 2 operation !! A := alpha*x*y**H + conjg( alpha )*y*x**H + A, !! where alpha is a scalar, x and y are n element vectors and A is an !! n by n hermitian matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments complex(${ck}$), intent(in) :: alpha integer(${ik}$), intent(in) :: incx, incy, n character, intent(in) :: uplo ! Array Arguments complex(${ck}$), intent(inout) :: ap(*) complex(${ck}$), intent(in) :: x(*), y(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp1, temp2 integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky ! Intrinsic Functions intrinsic :: real,conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (n<0) then info = 2 else if (incx==0) then info = 5 else if (incy==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('ZHPR2 ',info) return end if ! quick return if possible. if ((n==0) .or. (alpha==czero)) return ! set up the start points in x and y if the increments are not both ! unity. if ((incx/=1) .or. (incy/=1)) then if (incx>0) then kx = 1 else kx = 1 - (n-1)*incx end if if (incy>0) then ky = 1 else ky = 1 - (n-1)*incy end if jx = kx jy = ky end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. kk = 1 if (stdlib_lsame(uplo,'U')) then ! form a when upper triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) k = kk do i = 1,j - 1 ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do ap(kk+j-1) = real(ap(kk+j-1),KIND=${ck}$) +real(x(j)*temp1+y(j)*temp2,& KIND=${ck}$) else ap(kk+j-1) = real(ap(kk+j-1),KIND=${ck}$) end if kk = kk + j end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) ix = kx iy = ky do k = kk,kk + j - 2 ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 ix = ix + incx iy = iy + incy end do ap(kk+j-1) = real(ap(kk+j-1),KIND=${ck}$) +real(x(jx)*temp1+y(jy)*temp2,& KIND=${ck}$) else ap(kk+j-1) = real(ap(kk+j-1),KIND=${ck}$) end if jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if ((incx==1) .and. (incy==1)) then do j = 1,n if ((x(j)/=czero) .or. (y(j)/=czero)) then temp1 = alpha*conjg(y(j)) temp2 = conjg(alpha*x(j)) ap(kk) = real(ap(kk),KIND=${ck}$) +real(x(j)*temp1+y(j)*temp2,KIND=${ck}$) k = kk + 1 do i = j + 1,n ap(k) = ap(k) + x(i)*temp1 + y(i)*temp2 k = k + 1 end do else ap(kk) = real(ap(kk),KIND=${ck}$) end if kk = kk + n - j + 1 end do else do j = 1,n if ((x(jx)/=czero) .or. (y(jy)/=czero)) then temp1 = alpha*conjg(y(jy)) temp2 = conjg(alpha*x(jx)) ap(kk) = real(ap(kk),KIND=${ck}$) +real(x(jx)*temp1+y(jy)*temp2,KIND=${ck}$) ix = jx iy = jy do k = kk + 1,kk + n - j ix = ix + incx iy = iy + incy ap(k) = ap(k) + x(ix)*temp1 + y(iy)*temp2 end do else ap(kk) = real(ap(kk),KIND=${ck}$) end if jx = jx + incx jy = jy + incy kk = kk + n - j + 1 end do end if end if return end subroutine stdlib${ii}$_${ci}$hpr2 #:endif #:endfor #:endfor end submodule stdlib_blas_level2_pac fortran-lang-stdlib-0ede301/src/blas/stdlib_blas_level2_tri.fypp0000664000175000017500000110506315135654166025215 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_blas) stdlib_blas_level2_tri implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_strmv(uplo,trans,diag,n,a,lda,x,incx) use stdlib_blas_constants_sp !! STRMV performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular matrix. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, kx logical(lk) :: nounit ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (ldak) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 if (x(j)/=zero) then temp = x(j) l = 1 - j do i = min(n,j+k),j + 1,-1 x(i) = x(i) + temp*a(l+i,j) end do if (nounit) x(j) = x(j)*a(1,j) end if end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=zero) then temp = x(jx) ix = kx l = 1 - j do i = min(n,j+k),j + 1,-1 x(ix) = x(ix) + temp*a(l+i,j) ix = ix - incx end do if (nounit) x(jx) = x(jx)*a(1,j) end if jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if else ! form x := a**t*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = n,1,-1 temp = x(j) l = kplus1 - j if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(i) end do x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) kx = kx - incx ix = kx l = kplus1 - j if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(ix) ix = ix - incx end do x(jx) = temp jx = jx - incx end do end if else if (incx==1) then do j = 1,n temp = x(j) l = 1 - j if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(i) end do x(j) = temp end do else jx = kx do j = 1,n temp = x(jx) kx = kx + incx ix = kx l = 1 - j if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(ix) ix = ix + incx end do x(jx) = temp jx = jx + incx end do end if end if end if return end subroutine stdlib${ii}$_stbmv pure module subroutine stdlib${ii}$_dtbmv(uplo,trans,diag,n,k,a,lda,x,incx) use stdlib_blas_constants_dp !! DTBMV performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular band matrix, with ( k + 1 ) diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(dp) :: temp integer(${ik}$) :: i, info, ix, j, jx, kplus1, kx, l logical(lk) :: nounit ! Intrinsic Functions intrinsic :: max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (k<0) then info = 5 else if (lda< (k+1)) then info = 7 else if (incx==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('DTBMV ',info) return end if ! quick return if possible. if (n==0) return nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through a. if (stdlib_lsame(trans,'N')) then ! form x := a*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = 1,n if (x(j)/=zero) then temp = x(j) l = kplus1 - j do i = max(1,j-k),j - 1 x(i) = x(i) + temp*a(l+i,j) end do if (nounit) x(j) = x(j)*a(kplus1,j) end if end do else jx = kx do j = 1,n if (x(jx)/=zero) then temp = x(jx) ix = kx l = kplus1 - j do i = max(1,j-k),j - 1 x(ix) = x(ix) + temp*a(l+i,j) ix = ix + incx end do if (nounit) x(jx) = x(jx)*a(kplus1,j) end if jx = jx + incx if (j>k) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 if (x(j)/=zero) then temp = x(j) l = 1 - j do i = min(n,j+k),j + 1,-1 x(i) = x(i) + temp*a(l+i,j) end do if (nounit) x(j) = x(j)*a(1,j) end if end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=zero) then temp = x(jx) ix = kx l = 1 - j do i = min(n,j+k),j + 1,-1 x(ix) = x(ix) + temp*a(l+i,j) ix = ix - incx end do if (nounit) x(jx) = x(jx)*a(1,j) end if jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if else ! form x := a**t*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = n,1,-1 temp = x(j) l = kplus1 - j if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(i) end do x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) kx = kx - incx ix = kx l = kplus1 - j if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(ix) ix = ix - incx end do x(jx) = temp jx = jx - incx end do end if else if (incx==1) then do j = 1,n temp = x(j) l = 1 - j if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(i) end do x(j) = temp end do else jx = kx do j = 1,n temp = x(jx) kx = kx + incx ix = kx l = 1 - j if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(ix) ix = ix + incx end do x(jx) = temp jx = jx + incx end do end if end if end if return end subroutine stdlib${ii}$_dtbmv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tbmv(uplo,trans,diag,n,k,a,lda,x,incx) use stdlib_blas_constants_${rk}$ !! DTBMV: performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular band matrix, with ( k + 1 ) diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp integer(${ik}$) :: i, info, ix, j, jx, kplus1, kx, l logical(lk) :: nounit ! Intrinsic Functions intrinsic :: max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (k<0) then info = 5 else if (lda< (k+1)) then info = 7 else if (incx==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('DTBMV ',info) return end if ! quick return if possible. if (n==0) return nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of a are ! accessed sequentially with one pass through a. if (stdlib_lsame(trans,'N')) then ! form x := a*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = 1,n if (x(j)/=zero) then temp = x(j) l = kplus1 - j do i = max(1,j-k),j - 1 x(i) = x(i) + temp*a(l+i,j) end do if (nounit) x(j) = x(j)*a(kplus1,j) end if end do else jx = kx do j = 1,n if (x(jx)/=zero) then temp = x(jx) ix = kx l = kplus1 - j do i = max(1,j-k),j - 1 x(ix) = x(ix) + temp*a(l+i,j) ix = ix + incx end do if (nounit) x(jx) = x(jx)*a(kplus1,j) end if jx = jx + incx if (j>k) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 if (x(j)/=zero) then temp = x(j) l = 1 - j do i = min(n,j+k),j + 1,-1 x(i) = x(i) + temp*a(l+i,j) end do if (nounit) x(j) = x(j)*a(1,j) end if end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=zero) then temp = x(jx) ix = kx l = 1 - j do i = min(n,j+k),j + 1,-1 x(ix) = x(ix) + temp*a(l+i,j) ix = ix - incx end do if (nounit) x(jx) = x(jx)*a(1,j) end if jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if else ! form x := a**t*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = n,1,-1 temp = x(j) l = kplus1 - j if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(i) end do x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) kx = kx - incx ix = kx l = kplus1 - j if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(ix) ix = ix - incx end do x(jx) = temp jx = jx - incx end do end if else if (incx==1) then do j = 1,n temp = x(j) l = 1 - j if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(i) end do x(j) = temp end do else jx = kx do j = 1,n temp = x(jx) kx = kx + incx ix = kx l = 1 - j if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(ix) ix = ix + incx end do x(jx) = temp jx = jx + incx end do end if end if end if return end subroutine stdlib${ii}$_${ri}$tbmv #:endif #:endfor pure module subroutine stdlib${ii}$_ctbmv(uplo,trans,diag,n,k,a,lda,x,incx) use stdlib_blas_constants_sp !! CTBMV performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, or x := A**H*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular band matrix, with ( k + 1 ) diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, kplus1, kx, l logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg,max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (k<0) then info = 5 else if (lda< (k+1)) then info = 7 else if (incx==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('CTBMV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through a. if (stdlib_lsame(trans,'N')) then ! form x := a*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = x(j) l = kplus1 - j do i = max(1,j-k),j - 1 x(i) = x(i) + temp*a(l+i,j) end do if (nounit) x(j) = x(j)*a(kplus1,j) end if end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = x(jx) ix = kx l = kplus1 - j do i = max(1,j-k),j - 1 x(ix) = x(ix) + temp*a(l+i,j) ix = ix + incx end do if (nounit) x(jx) = x(jx)*a(kplus1,j) end if jx = jx + incx if (j>k) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then temp = x(j) l = 1 - j do i = min(n,j+k),j + 1,-1 x(i) = x(i) + temp*a(l+i,j) end do if (nounit) x(j) = x(j)*a(1,j) end if end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=czero) then temp = x(jx) ix = kx l = 1 - j do i = min(n,j+k),j + 1,-1 x(ix) = x(ix) + temp*a(l+i,j) ix = ix - incx end do if (nounit) x(jx) = x(jx)*a(1,j) end if jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if else ! form x := a**t*x or x := a**h*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = n,1,-1 temp = x(j) l = kplus1 - j if (noconj) then if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(i) end do else if (nounit) temp = temp*conjg(a(kplus1,j)) do i = j - 1,max(1,j-k),-1 temp = temp + conjg(a(l+i,j))*x(i) end do end if x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) kx = kx - incx ix = kx l = kplus1 - j if (noconj) then if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(ix) ix = ix - incx end do else if (nounit) temp = temp*conjg(a(kplus1,j)) do i = j - 1,max(1,j-k),-1 temp = temp + conjg(a(l+i,j))*x(ix) ix = ix - incx end do end if x(jx) = temp jx = jx - incx end do end if else if (incx==1) then do j = 1,n temp = x(j) l = 1 - j if (noconj) then if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(i) end do else if (nounit) temp = temp*conjg(a(1,j)) do i = j + 1,min(n,j+k) temp = temp + conjg(a(l+i,j))*x(i) end do end if x(j) = temp end do else jx = kx do j = 1,n temp = x(jx) kx = kx + incx ix = kx l = 1 - j if (noconj) then if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(ix) ix = ix + incx end do else if (nounit) temp = temp*conjg(a(1,j)) do i = j + 1,min(n,j+k) temp = temp + conjg(a(l+i,j))*x(ix) ix = ix + incx end do end if x(jx) = temp jx = jx + incx end do end if end if end if return end subroutine stdlib${ii}$_ctbmv pure module subroutine stdlib${ii}$_ztbmv(uplo,trans,diag,n,k,a,lda,x,incx) use stdlib_blas_constants_dp !! ZTBMV performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, or x := A**H*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular band matrix, with ( k + 1 ) diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp integer(${ik}$) :: i, info, ix, j, jx, kplus1, kx, l logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg,max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (k<0) then info = 5 else if (lda< (k+1)) then info = 7 else if (incx==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('ZTBMV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through a. if (stdlib_lsame(trans,'N')) then ! form x := a*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = x(j) l = kplus1 - j do i = max(1,j-k),j - 1 x(i) = x(i) + temp*a(l+i,j) end do if (nounit) x(j) = x(j)*a(kplus1,j) end if end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = x(jx) ix = kx l = kplus1 - j do i = max(1,j-k),j - 1 x(ix) = x(ix) + temp*a(l+i,j) ix = ix + incx end do if (nounit) x(jx) = x(jx)*a(kplus1,j) end if jx = jx + incx if (j>k) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then temp = x(j) l = 1 - j do i = min(n,j+k),j + 1,-1 x(i) = x(i) + temp*a(l+i,j) end do if (nounit) x(j) = x(j)*a(1,j) end if end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=czero) then temp = x(jx) ix = kx l = 1 - j do i = min(n,j+k),j + 1,-1 x(ix) = x(ix) + temp*a(l+i,j) ix = ix - incx end do if (nounit) x(jx) = x(jx)*a(1,j) end if jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if else ! form x := a**t*x or x := a**h*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = n,1,-1 temp = x(j) l = kplus1 - j if (noconj) then if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(i) end do else if (nounit) temp = temp*conjg(a(kplus1,j)) do i = j - 1,max(1,j-k),-1 temp = temp + conjg(a(l+i,j))*x(i) end do end if x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) kx = kx - incx ix = kx l = kplus1 - j if (noconj) then if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(ix) ix = ix - incx end do else if (nounit) temp = temp*conjg(a(kplus1,j)) do i = j - 1,max(1,j-k),-1 temp = temp + conjg(a(l+i,j))*x(ix) ix = ix - incx end do end if x(jx) = temp jx = jx - incx end do end if else if (incx==1) then do j = 1,n temp = x(j) l = 1 - j if (noconj) then if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(i) end do else if (nounit) temp = temp*conjg(a(1,j)) do i = j + 1,min(n,j+k) temp = temp + conjg(a(l+i,j))*x(i) end do end if x(j) = temp end do else jx = kx do j = 1,n temp = x(jx) kx = kx + incx ix = kx l = 1 - j if (noconj) then if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(ix) ix = ix + incx end do else if (nounit) temp = temp*conjg(a(1,j)) do i = j + 1,min(n,j+k) temp = temp + conjg(a(l+i,j))*x(ix) ix = ix + incx end do end if x(jx) = temp jx = jx + incx end do end if end if end if return end subroutine stdlib${ii}$_ztbmv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tbmv(uplo,trans,diag,n,k,a,lda,x,incx) use stdlib_blas_constants_${ck}$ !! ZTBMV: performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, or x := A**H*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular band matrix, with ( k + 1 ) diagonals. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp integer(${ik}$) :: i, info, ix, j, jx, kplus1, kx, l logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg,max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (k<0) then info = 5 else if (lda< (k+1)) then info = 7 else if (incx==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('ZTBMV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through a. if (stdlib_lsame(trans,'N')) then ! form x := a*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = x(j) l = kplus1 - j do i = max(1,j-k),j - 1 x(i) = x(i) + temp*a(l+i,j) end do if (nounit) x(j) = x(j)*a(kplus1,j) end if end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = x(jx) ix = kx l = kplus1 - j do i = max(1,j-k),j - 1 x(ix) = x(ix) + temp*a(l+i,j) ix = ix + incx end do if (nounit) x(jx) = x(jx)*a(kplus1,j) end if jx = jx + incx if (j>k) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then temp = x(j) l = 1 - j do i = min(n,j+k),j + 1,-1 x(i) = x(i) + temp*a(l+i,j) end do if (nounit) x(j) = x(j)*a(1,j) end if end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=czero) then temp = x(jx) ix = kx l = 1 - j do i = min(n,j+k),j + 1,-1 x(ix) = x(ix) + temp*a(l+i,j) ix = ix - incx end do if (nounit) x(jx) = x(jx)*a(1,j) end if jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if else ! form x := a**t*x or x := a**h*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = n,1,-1 temp = x(j) l = kplus1 - j if (noconj) then if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(i) end do else if (nounit) temp = temp*conjg(a(kplus1,j)) do i = j - 1,max(1,j-k),-1 temp = temp + conjg(a(l+i,j))*x(i) end do end if x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) kx = kx - incx ix = kx l = kplus1 - j if (noconj) then if (nounit) temp = temp*a(kplus1,j) do i = j - 1,max(1,j-k),-1 temp = temp + a(l+i,j)*x(ix) ix = ix - incx end do else if (nounit) temp = temp*conjg(a(kplus1,j)) do i = j - 1,max(1,j-k),-1 temp = temp + conjg(a(l+i,j))*x(ix) ix = ix - incx end do end if x(jx) = temp jx = jx - incx end do end if else if (incx==1) then do j = 1,n temp = x(j) l = 1 - j if (noconj) then if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(i) end do else if (nounit) temp = temp*conjg(a(1,j)) do i = j + 1,min(n,j+k) temp = temp + conjg(a(l+i,j))*x(i) end do end if x(j) = temp end do else jx = kx do j = 1,n temp = x(jx) kx = kx + incx ix = kx l = 1 - j if (noconj) then if (nounit) temp = temp*a(1,j) do i = j + 1,min(n,j+k) temp = temp + a(l+i,j)*x(ix) ix = ix + incx end do else if (nounit) temp = temp*conjg(a(1,j)) do i = j + 1,min(n,j+k) temp = temp + conjg(a(l+i,j))*x(ix) ix = ix + incx end do end if x(jx) = temp jx = jx + incx end do end if end if end if return end subroutine stdlib${ii}$_${ci}$tbmv #:endif #:endfor pure module subroutine stdlib${ii}$_stpmv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_sp !! STPMV performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(sp), intent(in) :: ap(*) real(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: nounit ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('STPMV ',info) return end if ! quick return if possible. if (n==0) return nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with one pass through ap. if (stdlib_lsame(trans,'N')) then ! form x:= a*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n if (x(j)/=zero) then temp = x(j) k = kk do i = 1,j - 1 x(i) = x(i) + temp*ap(k) k = k + 1 end do if (nounit) x(j) = x(j)*ap(kk+j-1) end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=zero) then temp = x(jx) ix = kx do k = kk,kk + j - 2 x(ix) = x(ix) + temp*ap(k) ix = ix + incx end do if (nounit) x(jx) = x(jx)*ap(kk+j-1) end if jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=zero) then temp = x(j) k = kk do i = n,j + 1,-1 x(i) = x(i) + temp*ap(k) k = k - 1 end do if (nounit) x(j) = x(j)*ap(kk-n+j) end if kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=zero) then temp = x(jx) ix = kx do k = kk,kk - (n- (j+1)),-1 x(ix) = x(ix) + temp*ap(k) ix = ix - incx end do if (nounit) x(jx) = x(jx)*ap(kk-n+j) end if jx = jx - incx kk = kk - (n-j+1) end do end if end if else ! form x := a**t*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) if (nounit) temp = temp*ap(kk) k = kk - 1 do i = j - 1,1,-1 temp = temp + ap(k)*x(i) k = k - 1 end do x(j) = temp kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 temp = x(jx) ix = jx if (nounit) temp = temp*ap(kk) do k = kk - 1,kk - j + 1,-1 ix = ix - incx temp = temp + ap(k)*x(ix) end do x(jx) = temp jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n temp = x(j) if (nounit) temp = temp*ap(kk) k = kk + 1 do i = j + 1,n temp = temp + ap(k)*x(i) k = k + 1 end do x(j) = temp kk = kk + (n-j+1) end do else jx = kx do j = 1,n temp = x(jx) ix = jx if (nounit) temp = temp*ap(kk) do k = kk + 1,kk + n - j ix = ix + incx temp = temp + ap(k)*x(ix) end do x(jx) = temp jx = jx + incx kk = kk + (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_stpmv pure module subroutine stdlib${ii}$_dtpmv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_dp !! DTPMV performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(dp), intent(in) :: ap(*) real(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(dp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: nounit ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('DTPMV ',info) return end if ! quick return if possible. if (n==0) return nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with one pass through ap. if (stdlib_lsame(trans,'N')) then ! form x:= a*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n if (x(j)/=zero) then temp = x(j) k = kk do i = 1,j - 1 x(i) = x(i) + temp*ap(k) k = k + 1 end do if (nounit) x(j) = x(j)*ap(kk+j-1) end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=zero) then temp = x(jx) ix = kx do k = kk,kk + j - 2 x(ix) = x(ix) + temp*ap(k) ix = ix + incx end do if (nounit) x(jx) = x(jx)*ap(kk+j-1) end if jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=zero) then temp = x(j) k = kk do i = n,j + 1,-1 x(i) = x(i) + temp*ap(k) k = k - 1 end do if (nounit) x(j) = x(j)*ap(kk-n+j) end if kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=zero) then temp = x(jx) ix = kx do k = kk,kk - (n- (j+1)),-1 x(ix) = x(ix) + temp*ap(k) ix = ix - incx end do if (nounit) x(jx) = x(jx)*ap(kk-n+j) end if jx = jx - incx kk = kk - (n-j+1) end do end if end if else ! form x := a**t*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) if (nounit) temp = temp*ap(kk) k = kk - 1 do i = j - 1,1,-1 temp = temp + ap(k)*x(i) k = k - 1 end do x(j) = temp kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 temp = x(jx) ix = jx if (nounit) temp = temp*ap(kk) do k = kk - 1,kk - j + 1,-1 ix = ix - incx temp = temp + ap(k)*x(ix) end do x(jx) = temp jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n temp = x(j) if (nounit) temp = temp*ap(kk) k = kk + 1 do i = j + 1,n temp = temp + ap(k)*x(i) k = k + 1 end do x(j) = temp kk = kk + (n-j+1) end do else jx = kx do j = 1,n temp = x(jx) ix = jx if (nounit) temp = temp*ap(kk) do k = kk + 1,kk + n - j ix = ix + incx temp = temp + ap(k)*x(ix) end do x(jx) = temp jx = jx + incx kk = kk + (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_dtpmv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tpmv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_${rk}$ !! DTPMV: performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(${rk}$), intent(in) :: ap(*) real(${rk}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: nounit ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('DTPMV ',info) return end if ! quick return if possible. if (n==0) return nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with one pass through ap. if (stdlib_lsame(trans,'N')) then ! form x:= a*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n if (x(j)/=zero) then temp = x(j) k = kk do i = 1,j - 1 x(i) = x(i) + temp*ap(k) k = k + 1 end do if (nounit) x(j) = x(j)*ap(kk+j-1) end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=zero) then temp = x(jx) ix = kx do k = kk,kk + j - 2 x(ix) = x(ix) + temp*ap(k) ix = ix + incx end do if (nounit) x(jx) = x(jx)*ap(kk+j-1) end if jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=zero) then temp = x(j) k = kk do i = n,j + 1,-1 x(i) = x(i) + temp*ap(k) k = k - 1 end do if (nounit) x(j) = x(j)*ap(kk-n+j) end if kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=zero) then temp = x(jx) ix = kx do k = kk,kk - (n- (j+1)),-1 x(ix) = x(ix) + temp*ap(k) ix = ix - incx end do if (nounit) x(jx) = x(jx)*ap(kk-n+j) end if jx = jx - incx kk = kk - (n-j+1) end do end if end if else ! form x := a**t*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) if (nounit) temp = temp*ap(kk) k = kk - 1 do i = j - 1,1,-1 temp = temp + ap(k)*x(i) k = k - 1 end do x(j) = temp kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 temp = x(jx) ix = jx if (nounit) temp = temp*ap(kk) do k = kk - 1,kk - j + 1,-1 ix = ix - incx temp = temp + ap(k)*x(ix) end do x(jx) = temp jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n temp = x(j) if (nounit) temp = temp*ap(kk) k = kk + 1 do i = j + 1,n temp = temp + ap(k)*x(i) k = k + 1 end do x(j) = temp kk = kk + (n-j+1) end do else jx = kx do j = 1,n temp = x(jx) ix = jx if (nounit) temp = temp*ap(kk) do k = kk + 1,kk + n - j ix = ix + incx temp = temp + ap(k)*x(ix) end do x(jx) = temp jx = jx + incx kk = kk + (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_${ri}$tpmv #:endif #:endfor pure module subroutine stdlib${ii}$_ctpmv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_sp !! CTPMV performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, or x := A**H*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(sp), intent(in) :: ap(*) complex(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('CTPMV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with cone pass through ap. if (stdlib_lsame(trans,'N')) then ! form x:= a*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = x(j) k = kk do i = 1,j - 1 x(i) = x(i) + temp*ap(k) k = k + 1 end do if (nounit) x(j) = x(j)*ap(kk+j-1) end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = x(jx) ix = kx do k = kk,kk + j - 2 x(ix) = x(ix) + temp*ap(k) ix = ix + incx end do if (nounit) x(jx) = x(jx)*ap(kk+j-1) end if jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then temp = x(j) k = kk do i = n,j + 1,-1 x(i) = x(i) + temp*ap(k) k = k - 1 end do if (nounit) x(j) = x(j)*ap(kk-n+j) end if kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=czero) then temp = x(jx) ix = kx do k = kk,kk - (n- (j+1)),-1 x(ix) = x(ix) + temp*ap(k) ix = ix - incx end do if (nounit) x(jx) = x(jx)*ap(kk-n+j) end if jx = jx - incx kk = kk - (n-j+1) end do end if end if else ! form x := a**t*x or x := a**h*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) k = kk - 1 if (noconj) then if (nounit) temp = temp*ap(kk) do i = j - 1,1,-1 temp = temp + ap(k)*x(i) k = k - 1 end do else if (nounit) temp = temp*conjg(ap(kk)) do i = j - 1,1,-1 temp = temp + conjg(ap(k))*x(i) k = k - 1 end do end if x(j) = temp kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 temp = x(jx) ix = jx if (noconj) then if (nounit) temp = temp*ap(kk) do k = kk - 1,kk - j + 1,-1 ix = ix - incx temp = temp + ap(k)*x(ix) end do else if (nounit) temp = temp*conjg(ap(kk)) do k = kk - 1,kk - j + 1,-1 ix = ix - incx temp = temp + conjg(ap(k))*x(ix) end do end if x(jx) = temp jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n temp = x(j) k = kk + 1 if (noconj) then if (nounit) temp = temp*ap(kk) do i = j + 1,n temp = temp + ap(k)*x(i) k = k + 1 end do else if (nounit) temp = temp*conjg(ap(kk)) do i = j + 1,n temp = temp + conjg(ap(k))*x(i) k = k + 1 end do end if x(j) = temp kk = kk + (n-j+1) end do else jx = kx do j = 1,n temp = x(jx) ix = jx if (noconj) then if (nounit) temp = temp*ap(kk) do k = kk + 1,kk + n - j ix = ix + incx temp = temp + ap(k)*x(ix) end do else if (nounit) temp = temp*conjg(ap(kk)) do k = kk + 1,kk + n - j ix = ix + incx temp = temp + conjg(ap(k))*x(ix) end do end if x(jx) = temp jx = jx + incx kk = kk + (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_ctpmv pure module subroutine stdlib${ii}$_ztpmv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_dp !! ZTPMV performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, or x := A**H*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(dp), intent(in) :: ap(*) complex(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('ZTPMV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with cone pass through ap. if (stdlib_lsame(trans,'N')) then ! form x:= a*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = x(j) k = kk do i = 1,j - 1 x(i) = x(i) + temp*ap(k) k = k + 1 end do if (nounit) x(j) = x(j)*ap(kk+j-1) end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = x(jx) ix = kx do k = kk,kk + j - 2 x(ix) = x(ix) + temp*ap(k) ix = ix + incx end do if (nounit) x(jx) = x(jx)*ap(kk+j-1) end if jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then temp = x(j) k = kk do i = n,j + 1,-1 x(i) = x(i) + temp*ap(k) k = k - 1 end do if (nounit) x(j) = x(j)*ap(kk-n+j) end if kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=czero) then temp = x(jx) ix = kx do k = kk,kk - (n- (j+1)),-1 x(ix) = x(ix) + temp*ap(k) ix = ix - incx end do if (nounit) x(jx) = x(jx)*ap(kk-n+j) end if jx = jx - incx kk = kk - (n-j+1) end do end if end if else ! form x := a**t*x or x := a**h*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) k = kk - 1 if (noconj) then if (nounit) temp = temp*ap(kk) do i = j - 1,1,-1 temp = temp + ap(k)*x(i) k = k - 1 end do else if (nounit) temp = temp*conjg(ap(kk)) do i = j - 1,1,-1 temp = temp + conjg(ap(k))*x(i) k = k - 1 end do end if x(j) = temp kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 temp = x(jx) ix = jx if (noconj) then if (nounit) temp = temp*ap(kk) do k = kk - 1,kk - j + 1,-1 ix = ix - incx temp = temp + ap(k)*x(ix) end do else if (nounit) temp = temp*conjg(ap(kk)) do k = kk - 1,kk - j + 1,-1 ix = ix - incx temp = temp + conjg(ap(k))*x(ix) end do end if x(jx) = temp jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n temp = x(j) k = kk + 1 if (noconj) then if (nounit) temp = temp*ap(kk) do i = j + 1,n temp = temp + ap(k)*x(i) k = k + 1 end do else if (nounit) temp = temp*conjg(ap(kk)) do i = j + 1,n temp = temp + conjg(ap(k))*x(i) k = k + 1 end do end if x(j) = temp kk = kk + (n-j+1) end do else jx = kx do j = 1,n temp = x(jx) ix = jx if (noconj) then if (nounit) temp = temp*ap(kk) do k = kk + 1,kk + n - j ix = ix + incx temp = temp + ap(k)*x(ix) end do else if (nounit) temp = temp*conjg(ap(kk)) do k = kk + 1,kk + n - j ix = ix + incx temp = temp + conjg(ap(k))*x(ix) end do end if x(jx) = temp jx = jx + incx kk = kk + (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_ztpmv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tpmv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_${ck}$ !! ZTPMV: performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, or x := A**H*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular matrix, supplied in packed form. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(${ck}$), intent(in) :: ap(*) complex(${ck}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('ZTPMV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with cone pass through ap. if (stdlib_lsame(trans,'N')) then ! form x:= a*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n if (x(j)/=czero) then temp = x(j) k = kk do i = 1,j - 1 x(i) = x(i) + temp*ap(k) k = k + 1 end do if (nounit) x(j) = x(j)*ap(kk+j-1) end if kk = kk + j end do else jx = kx do j = 1,n if (x(jx)/=czero) then temp = x(jx) ix = kx do k = kk,kk + j - 2 x(ix) = x(ix) + temp*ap(k) ix = ix + incx end do if (nounit) x(jx) = x(jx)*ap(kk+j-1) end if jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then temp = x(j) k = kk do i = n,j + 1,-1 x(i) = x(i) + temp*ap(k) k = k - 1 end do if (nounit) x(j) = x(j)*ap(kk-n+j) end if kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 if (x(jx)/=czero) then temp = x(jx) ix = kx do k = kk,kk - (n- (j+1)),-1 x(ix) = x(ix) + temp*ap(k) ix = ix - incx end do if (nounit) x(jx) = x(jx)*ap(kk-n+j) end if jx = jx - incx kk = kk - (n-j+1) end do end if end if else ! form x := a**t*x or x := a**h*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) k = kk - 1 if (noconj) then if (nounit) temp = temp*ap(kk) do i = j - 1,1,-1 temp = temp + ap(k)*x(i) k = k - 1 end do else if (nounit) temp = temp*conjg(ap(kk)) do i = j - 1,1,-1 temp = temp + conjg(ap(k))*x(i) k = k - 1 end do end if x(j) = temp kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 temp = x(jx) ix = jx if (noconj) then if (nounit) temp = temp*ap(kk) do k = kk - 1,kk - j + 1,-1 ix = ix - incx temp = temp + ap(k)*x(ix) end do else if (nounit) temp = temp*conjg(ap(kk)) do k = kk - 1,kk - j + 1,-1 ix = ix - incx temp = temp + conjg(ap(k))*x(ix) end do end if x(jx) = temp jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n temp = x(j) k = kk + 1 if (noconj) then if (nounit) temp = temp*ap(kk) do i = j + 1,n temp = temp + ap(k)*x(i) k = k + 1 end do else if (nounit) temp = temp*conjg(ap(kk)) do i = j + 1,n temp = temp + conjg(ap(k))*x(i) k = k + 1 end do end if x(j) = temp kk = kk + (n-j+1) end do else jx = kx do j = 1,n temp = x(jx) ix = jx if (noconj) then if (nounit) temp = temp*ap(kk) do k = kk + 1,kk + n - j ix = ix + incx temp = temp + ap(k)*x(ix) end do else if (nounit) temp = temp*conjg(ap(kk)) do k = kk + 1,kk + n - j ix = ix + incx temp = temp + conjg(ap(k))*x(ix) end do end if x(jx) = temp jx = jx + incx kk = kk + (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_${ci}$tpmv #:endif #:endfor pure module subroutine stdlib${ii}$_strsv(uplo,trans,diag,n,a,lda,x,incx) use stdlib_blas_constants_sp !! STRSV solves one of the systems of equations !! A*x = b, or A**T*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular matrix. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, kx logical(lk) :: nounit ! Intrinsic Functions intrinsic :: max ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (ldak) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 temp = x(j) l = 1 - j do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(i) end do if (nounit) temp = temp/a(1,j) x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx l = 1 - j do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(ix) ix = ix - incx end do if (nounit) temp = temp/a(1,j) x(jx) = temp jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if end if return end subroutine stdlib${ii}$_stbsv pure module subroutine stdlib${ii}$_dtbsv(uplo,trans,diag,n,k,a,lda,x,incx) use stdlib_blas_constants_dp !! DTBSV solves one of the systems of equations !! A*x = b, or A**T*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular band matrix, with ( k + 1 ) !! diagonals. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(dp) :: temp integer(${ik}$) :: i, info, ix, j, jx, kplus1, kx, l logical(lk) :: nounit ! Intrinsic Functions intrinsic :: max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (k<0) then info = 5 else if (lda< (k+1)) then info = 7 else if (incx==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('DTBSV ',info) return end if ! quick return if possible. if (n==0) return nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of a are ! accessed by sequentially with one pass through a. if (stdlib_lsame(trans,'N')) then ! form x := inv( a )*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = n,1,-1 if (x(j)/=zero) then l = kplus1 - j if (nounit) x(j) = x(j)/a(kplus1,j) temp = x(j) do i = j - 1,max(1,j-k),-1 x(i) = x(i) - temp*a(l+i,j) end do end if end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 kx = kx - incx if (x(jx)/=zero) then ix = kx l = kplus1 - j if (nounit) x(jx) = x(jx)/a(kplus1,j) temp = x(jx) do i = j - 1,max(1,j-k),-1 x(ix) = x(ix) - temp*a(l+i,j) ix = ix - incx end do end if jx = jx - incx end do end if else if (incx==1) then do j = 1,n if (x(j)/=zero) then l = 1 - j if (nounit) x(j) = x(j)/a(1,j) temp = x(j) do i = j + 1,min(n,j+k) x(i) = x(i) - temp*a(l+i,j) end do end if end do else jx = kx do j = 1,n kx = kx + incx if (x(jx)/=zero) then ix = kx l = 1 - j if (nounit) x(jx) = x(jx)/a(1,j) temp = x(jx) do i = j + 1,min(n,j+k) x(ix) = x(ix) - temp*a(l+i,j) ix = ix + incx end do end if jx = jx + incx end do end if end if else ! form x := inv( a**t)*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = 1,n temp = x(j) l = kplus1 - j do i = max(1,j-k),j - 1 temp = temp - a(l+i,j)*x(i) end do if (nounit) temp = temp/a(kplus1,j) x(j) = temp end do else jx = kx do j = 1,n temp = x(jx) ix = kx l = kplus1 - j do i = max(1,j-k),j - 1 temp = temp - a(l+i,j)*x(ix) ix = ix + incx end do if (nounit) temp = temp/a(kplus1,j) x(jx) = temp jx = jx + incx if (j>k) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 temp = x(j) l = 1 - j do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(i) end do if (nounit) temp = temp/a(1,j) x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx l = 1 - j do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(ix) ix = ix - incx end do if (nounit) temp = temp/a(1,j) x(jx) = temp jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if end if return end subroutine stdlib${ii}$_dtbsv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tbsv(uplo,trans,diag,n,k,a,lda,x,incx) use stdlib_blas_constants_${rk}$ !! DTBSV: solves one of the systems of equations !! A*x = b, or A**T*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular band matrix, with ( k + 1 ) !! diagonals. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp integer(${ik}$) :: i, info, ix, j, jx, kplus1, kx, l logical(lk) :: nounit ! Intrinsic Functions intrinsic :: max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (k<0) then info = 5 else if (lda< (k+1)) then info = 7 else if (incx==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('DTBSV ',info) return end if ! quick return if possible. if (n==0) return nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of a are ! accessed by sequentially with one pass through a. if (stdlib_lsame(trans,'N')) then ! form x := inv( a )*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = n,1,-1 if (x(j)/=zero) then l = kplus1 - j if (nounit) x(j) = x(j)/a(kplus1,j) temp = x(j) do i = j - 1,max(1,j-k),-1 x(i) = x(i) - temp*a(l+i,j) end do end if end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 kx = kx - incx if (x(jx)/=zero) then ix = kx l = kplus1 - j if (nounit) x(jx) = x(jx)/a(kplus1,j) temp = x(jx) do i = j - 1,max(1,j-k),-1 x(ix) = x(ix) - temp*a(l+i,j) ix = ix - incx end do end if jx = jx - incx end do end if else if (incx==1) then do j = 1,n if (x(j)/=zero) then l = 1 - j if (nounit) x(j) = x(j)/a(1,j) temp = x(j) do i = j + 1,min(n,j+k) x(i) = x(i) - temp*a(l+i,j) end do end if end do else jx = kx do j = 1,n kx = kx + incx if (x(jx)/=zero) then ix = kx l = 1 - j if (nounit) x(jx) = x(jx)/a(1,j) temp = x(jx) do i = j + 1,min(n,j+k) x(ix) = x(ix) - temp*a(l+i,j) ix = ix + incx end do end if jx = jx + incx end do end if end if else ! form x := inv( a**t)*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = 1,n temp = x(j) l = kplus1 - j do i = max(1,j-k),j - 1 temp = temp - a(l+i,j)*x(i) end do if (nounit) temp = temp/a(kplus1,j) x(j) = temp end do else jx = kx do j = 1,n temp = x(jx) ix = kx l = kplus1 - j do i = max(1,j-k),j - 1 temp = temp - a(l+i,j)*x(ix) ix = ix + incx end do if (nounit) temp = temp/a(kplus1,j) x(jx) = temp jx = jx + incx if (j>k) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 temp = x(j) l = 1 - j do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(i) end do if (nounit) temp = temp/a(1,j) x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx l = 1 - j do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(ix) ix = ix - incx end do if (nounit) temp = temp/a(1,j) x(jx) = temp jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if end if return end subroutine stdlib${ii}$_${ri}$tbsv #:endif #:endfor pure module subroutine stdlib${ii}$_ctbsv(uplo,trans,diag,n,k,a,lda,x,incx) use stdlib_blas_constants_sp !! CTBSV solves one of the systems of equations !! A*x = b, or A**T*x = b, or A**H*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular band matrix, with ( k + 1 ) !! diagonals. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, kplus1, kx, l logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg,max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (k<0) then info = 5 else if (lda< (k+1)) then info = 7 else if (incx==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('CTBSV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of a are ! accessed by sequentially with cone pass through a. if (stdlib_lsame(trans,'N')) then ! form x := inv( a )*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then l = kplus1 - j if (nounit) x(j) = x(j)/a(kplus1,j) temp = x(j) do i = j - 1,max(1,j-k),-1 x(i) = x(i) - temp*a(l+i,j) end do end if end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 kx = kx - incx if (x(jx)/=czero) then ix = kx l = kplus1 - j if (nounit) x(jx) = x(jx)/a(kplus1,j) temp = x(jx) do i = j - 1,max(1,j-k),-1 x(ix) = x(ix) - temp*a(l+i,j) ix = ix - incx end do end if jx = jx - incx end do end if else if (incx==1) then do j = 1,n if (x(j)/=czero) then l = 1 - j if (nounit) x(j) = x(j)/a(1,j) temp = x(j) do i = j + 1,min(n,j+k) x(i) = x(i) - temp*a(l+i,j) end do end if end do else jx = kx do j = 1,n kx = kx + incx if (x(jx)/=czero) then ix = kx l = 1 - j if (nounit) x(jx) = x(jx)/a(1,j) temp = x(jx) do i = j + 1,min(n,j+k) x(ix) = x(ix) - temp*a(l+i,j) ix = ix + incx end do end if jx = jx + incx end do end if end if else ! form x := inv( a**t )*x or x := inv( a**h )*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = 1,n temp = x(j) l = kplus1 - j if (noconj) then do i = max(1,j-k),j - 1 temp = temp - a(l+i,j)*x(i) end do if (nounit) temp = temp/a(kplus1,j) else do i = max(1,j-k),j - 1 temp = temp - conjg(a(l+i,j))*x(i) end do if (nounit) temp = temp/conjg(a(kplus1,j)) end if x(j) = temp end do else jx = kx do j = 1,n temp = x(jx) ix = kx l = kplus1 - j if (noconj) then do i = max(1,j-k),j - 1 temp = temp - a(l+i,j)*x(ix) ix = ix + incx end do if (nounit) temp = temp/a(kplus1,j) else do i = max(1,j-k),j - 1 temp = temp - conjg(a(l+i,j))*x(ix) ix = ix + incx end do if (nounit) temp = temp/conjg(a(kplus1,j)) end if x(jx) = temp jx = jx + incx if (j>k) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 temp = x(j) l = 1 - j if (noconj) then do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(i) end do if (nounit) temp = temp/a(1,j) else do i = min(n,j+k),j + 1,-1 temp = temp - conjg(a(l+i,j))*x(i) end do if (nounit) temp = temp/conjg(a(1,j)) end if x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx l = 1 - j if (noconj) then do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(ix) ix = ix - incx end do if (nounit) temp = temp/a(1,j) else do i = min(n,j+k),j + 1,-1 temp = temp - conjg(a(l+i,j))*x(ix) ix = ix - incx end do if (nounit) temp = temp/conjg(a(1,j)) end if x(jx) = temp jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if end if return end subroutine stdlib${ii}$_ctbsv pure module subroutine stdlib${ii}$_ztbsv(uplo,trans,diag,n,k,a,lda,x,incx) use stdlib_blas_constants_dp !! ZTBSV solves one of the systems of equations !! A*x = b, or A**T*x = b, or A**H*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular band matrix, with ( k + 1 ) !! diagonals. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp integer(${ik}$) :: i, info, ix, j, jx, kplus1, kx, l logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg,max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (k<0) then info = 5 else if (lda< (k+1)) then info = 7 else if (incx==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('ZTBSV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of a are ! accessed by sequentially with cone pass through a. if (stdlib_lsame(trans,'N')) then ! form x := inv( a )*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then l = kplus1 - j if (nounit) x(j) = x(j)/a(kplus1,j) temp = x(j) do i = j - 1,max(1,j-k),-1 x(i) = x(i) - temp*a(l+i,j) end do end if end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 kx = kx - incx if (x(jx)/=czero) then ix = kx l = kplus1 - j if (nounit) x(jx) = x(jx)/a(kplus1,j) temp = x(jx) do i = j - 1,max(1,j-k),-1 x(ix) = x(ix) - temp*a(l+i,j) ix = ix - incx end do end if jx = jx - incx end do end if else if (incx==1) then do j = 1,n if (x(j)/=czero) then l = 1 - j if (nounit) x(j) = x(j)/a(1,j) temp = x(j) do i = j + 1,min(n,j+k) x(i) = x(i) - temp*a(l+i,j) end do end if end do else jx = kx do j = 1,n kx = kx + incx if (x(jx)/=czero) then ix = kx l = 1 - j if (nounit) x(jx) = x(jx)/a(1,j) temp = x(jx) do i = j + 1,min(n,j+k) x(ix) = x(ix) - temp*a(l+i,j) ix = ix + incx end do end if jx = jx + incx end do end if end if else ! form x := inv( a**t )*x or x := inv( a**h )*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = 1,n temp = x(j) l = kplus1 - j if (noconj) then do i = max(1,j-k),j - 1 temp = temp - a(l+i,j)*x(i) end do if (nounit) temp = temp/a(kplus1,j) else do i = max(1,j-k),j - 1 temp = temp - conjg(a(l+i,j))*x(i) end do if (nounit) temp = temp/conjg(a(kplus1,j)) end if x(j) = temp end do else jx = kx do j = 1,n temp = x(jx) ix = kx l = kplus1 - j if (noconj) then do i = max(1,j-k),j - 1 temp = temp - a(l+i,j)*x(ix) ix = ix + incx end do if (nounit) temp = temp/a(kplus1,j) else do i = max(1,j-k),j - 1 temp = temp - conjg(a(l+i,j))*x(ix) ix = ix + incx end do if (nounit) temp = temp/conjg(a(kplus1,j)) end if x(jx) = temp jx = jx + incx if (j>k) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 temp = x(j) l = 1 - j if (noconj) then do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(i) end do if (nounit) temp = temp/a(1,j) else do i = min(n,j+k),j + 1,-1 temp = temp - conjg(a(l+i,j))*x(i) end do if (nounit) temp = temp/conjg(a(1,j)) end if x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx l = 1 - j if (noconj) then do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(ix) ix = ix - incx end do if (nounit) temp = temp/a(1,j) else do i = min(n,j+k),j + 1,-1 temp = temp - conjg(a(l+i,j))*x(ix) ix = ix - incx end do if (nounit) temp = temp/conjg(a(1,j)) end if x(jx) = temp jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if end if return end subroutine stdlib${ii}$_ztbsv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tbsv(uplo,trans,diag,n,k,a,lda,x,incx) use stdlib_blas_constants_${ck}$ !! ZTBSV: solves one of the systems of equations !! A*x = b, or A**T*x = b, or A**H*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular band matrix, with ( k + 1 ) !! diagonals. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k, lda, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp integer(${ik}$) :: i, info, ix, j, jx, kplus1, kx, l logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg,max,min ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (k<0) then info = 5 else if (lda< (k+1)) then info = 7 else if (incx==0) then info = 9 end if if (info/=0) then call stdlib${ii}$_xerbla('ZTBSV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of a are ! accessed by sequentially with cone pass through a. if (stdlib_lsame(trans,'N')) then ! form x := inv( a )*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then l = kplus1 - j if (nounit) x(j) = x(j)/a(kplus1,j) temp = x(j) do i = j - 1,max(1,j-k),-1 x(i) = x(i) - temp*a(l+i,j) end do end if end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 kx = kx - incx if (x(jx)/=czero) then ix = kx l = kplus1 - j if (nounit) x(jx) = x(jx)/a(kplus1,j) temp = x(jx) do i = j - 1,max(1,j-k),-1 x(ix) = x(ix) - temp*a(l+i,j) ix = ix - incx end do end if jx = jx - incx end do end if else if (incx==1) then do j = 1,n if (x(j)/=czero) then l = 1 - j if (nounit) x(j) = x(j)/a(1,j) temp = x(j) do i = j + 1,min(n,j+k) x(i) = x(i) - temp*a(l+i,j) end do end if end do else jx = kx do j = 1,n kx = kx + incx if (x(jx)/=czero) then ix = kx l = 1 - j if (nounit) x(jx) = x(jx)/a(1,j) temp = x(jx) do i = j + 1,min(n,j+k) x(ix) = x(ix) - temp*a(l+i,j) ix = ix + incx end do end if jx = jx + incx end do end if end if else ! form x := inv( a**t )*x or x := inv( a**h )*x. if (stdlib_lsame(uplo,'U')) then kplus1 = k + 1 if (incx==1) then do j = 1,n temp = x(j) l = kplus1 - j if (noconj) then do i = max(1,j-k),j - 1 temp = temp - a(l+i,j)*x(i) end do if (nounit) temp = temp/a(kplus1,j) else do i = max(1,j-k),j - 1 temp = temp - conjg(a(l+i,j))*x(i) end do if (nounit) temp = temp/conjg(a(kplus1,j)) end if x(j) = temp end do else jx = kx do j = 1,n temp = x(jx) ix = kx l = kplus1 - j if (noconj) then do i = max(1,j-k),j - 1 temp = temp - a(l+i,j)*x(ix) ix = ix + incx end do if (nounit) temp = temp/a(kplus1,j) else do i = max(1,j-k),j - 1 temp = temp - conjg(a(l+i,j))*x(ix) ix = ix + incx end do if (nounit) temp = temp/conjg(a(kplus1,j)) end if x(jx) = temp jx = jx + incx if (j>k) kx = kx + incx end do end if else if (incx==1) then do j = n,1,-1 temp = x(j) l = 1 - j if (noconj) then do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(i) end do if (nounit) temp = temp/a(1,j) else do i = min(n,j+k),j + 1,-1 temp = temp - conjg(a(l+i,j))*x(i) end do if (nounit) temp = temp/conjg(a(1,j)) end if x(j) = temp end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx l = 1 - j if (noconj) then do i = min(n,j+k),j + 1,-1 temp = temp - a(l+i,j)*x(ix) ix = ix - incx end do if (nounit) temp = temp/a(1,j) else do i = min(n,j+k),j + 1,-1 temp = temp - conjg(a(l+i,j))*x(ix) ix = ix - incx end do if (nounit) temp = temp/conjg(a(1,j)) end if x(jx) = temp jx = jx - incx if ((n-j)>=k) kx = kx - incx end do end if end if end if return end subroutine stdlib${ii}$_${ci}$tbsv #:endif #:endfor pure module subroutine stdlib${ii}$_stpsv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_sp !! STPSV solves one of the systems of equations !! A*x = b, or A**T*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular matrix, supplied in packed form. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(sp), intent(in) :: ap(*) real(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: nounit ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('STPSV ',info) return end if ! quick return if possible. if (n==0) return nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with one pass through ap. if (stdlib_lsame(trans,'N')) then ! form x := inv( a )*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=zero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk - 1 do i = j - 1,1,-1 x(i) = x(i) - temp*ap(k) k = k - 1 end do end if kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 if (x(jx)/=zero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk - 1,kk - j + 1,-1 ix = ix - incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n if (x(j)/=zero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk + 1 do i = j + 1,n x(i) = x(i) - temp*ap(k) k = k + 1 end do end if kk = kk + (n-j+1) end do else jx = kx do j = 1,n if (x(jx)/=zero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk + 1,kk + n - j ix = ix + incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx + incx kk = kk + (n-j+1) end do end if end if else ! form x := inv( a**t )*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n temp = x(j) k = kk do i = 1,j - 1 temp = temp - ap(k)*x(i) k = k + 1 end do if (nounit) temp = temp/ap(kk+j-1) x(j) = temp kk = kk + j end do else jx = kx do j = 1,n temp = x(jx) ix = kx do k = kk,kk + j - 2 temp = temp - ap(k)*x(ix) ix = ix + incx end do if (nounit) temp = temp/ap(kk+j-1) x(jx) = temp jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) k = kk do i = n,j + 1,-1 temp = temp - ap(k)*x(i) k = k - 1 end do if (nounit) temp = temp/ap(kk-n+j) x(j) = temp kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx do k = kk,kk - (n- (j+1)),-1 temp = temp - ap(k)*x(ix) ix = ix - incx end do if (nounit) temp = temp/ap(kk-n+j) x(jx) = temp jx = jx - incx kk = kk - (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_stpsv pure module subroutine stdlib${ii}$_dtpsv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_dp !! DTPSV solves one of the systems of equations !! A*x = b, or A**T*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular matrix, supplied in packed form. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(dp), intent(in) :: ap(*) real(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(dp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: nounit ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('DTPSV ',info) return end if ! quick return if possible. if (n==0) return nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with one pass through ap. if (stdlib_lsame(trans,'N')) then ! form x := inv( a )*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=zero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk - 1 do i = j - 1,1,-1 x(i) = x(i) - temp*ap(k) k = k - 1 end do end if kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 if (x(jx)/=zero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk - 1,kk - j + 1,-1 ix = ix - incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n if (x(j)/=zero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk + 1 do i = j + 1,n x(i) = x(i) - temp*ap(k) k = k + 1 end do end if kk = kk + (n-j+1) end do else jx = kx do j = 1,n if (x(jx)/=zero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk + 1,kk + n - j ix = ix + incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx + incx kk = kk + (n-j+1) end do end if end if else ! form x := inv( a**t )*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n temp = x(j) k = kk do i = 1,j - 1 temp = temp - ap(k)*x(i) k = k + 1 end do if (nounit) temp = temp/ap(kk+j-1) x(j) = temp kk = kk + j end do else jx = kx do j = 1,n temp = x(jx) ix = kx do k = kk,kk + j - 2 temp = temp - ap(k)*x(ix) ix = ix + incx end do if (nounit) temp = temp/ap(kk+j-1) x(jx) = temp jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) k = kk do i = n,j + 1,-1 temp = temp - ap(k)*x(i) k = k - 1 end do if (nounit) temp = temp/ap(kk-n+j) x(j) = temp kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx do k = kk,kk - (n- (j+1)),-1 temp = temp - ap(k)*x(ix) ix = ix - incx end do if (nounit) temp = temp/ap(kk-n+j) x(jx) = temp jx = jx - incx kk = kk - (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_dtpsv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tpsv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_${rk}$ !! DTPSV: solves one of the systems of equations !! A*x = b, or A**T*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular matrix, supplied in packed form. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments real(${rk}$), intent(in) :: ap(*) real(${rk}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: nounit ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('DTPSV ',info) return end if ! quick return if possible. if (n==0) return nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with one pass through ap. if (stdlib_lsame(trans,'N')) then ! form x := inv( a )*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=zero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk - 1 do i = j - 1,1,-1 x(i) = x(i) - temp*ap(k) k = k - 1 end do end if kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 if (x(jx)/=zero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk - 1,kk - j + 1,-1 ix = ix - incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n if (x(j)/=zero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk + 1 do i = j + 1,n x(i) = x(i) - temp*ap(k) k = k + 1 end do end if kk = kk + (n-j+1) end do else jx = kx do j = 1,n if (x(jx)/=zero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk + 1,kk + n - j ix = ix + incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx + incx kk = kk + (n-j+1) end do end if end if else ! form x := inv( a**t )*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n temp = x(j) k = kk do i = 1,j - 1 temp = temp - ap(k)*x(i) k = k + 1 end do if (nounit) temp = temp/ap(kk+j-1) x(j) = temp kk = kk + j end do else jx = kx do j = 1,n temp = x(jx) ix = kx do k = kk,kk + j - 2 temp = temp - ap(k)*x(ix) ix = ix + incx end do if (nounit) temp = temp/ap(kk+j-1) x(jx) = temp jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) k = kk do i = n,j + 1,-1 temp = temp - ap(k)*x(i) k = k - 1 end do if (nounit) temp = temp/ap(kk-n+j) x(j) = temp kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx do k = kk,kk - (n- (j+1)),-1 temp = temp - ap(k)*x(ix) ix = ix - incx end do if (nounit) temp = temp/ap(kk-n+j) x(jx) = temp jx = jx - incx kk = kk - (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_${ri}$tpsv #:endif #:endfor pure module subroutine stdlib${ii}$_ctpsv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_sp !! CTPSV solves one of the systems of equations !! A*x = b, or A**T*x = b, or A**H*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular matrix, supplied in packed form. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(sp), intent(in) :: ap(*) complex(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(sp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('CTPSV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with cone pass through ap. if (stdlib_lsame(trans,'N')) then ! form x := inv( a )*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk - 1 do i = j - 1,1,-1 x(i) = x(i) - temp*ap(k) k = k - 1 end do end if kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 if (x(jx)/=czero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk - 1,kk - j + 1,-1 ix = ix - incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n if (x(j)/=czero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk + 1 do i = j + 1,n x(i) = x(i) - temp*ap(k) k = k + 1 end do end if kk = kk + (n-j+1) end do else jx = kx do j = 1,n if (x(jx)/=czero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk + 1,kk + n - j ix = ix + incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx + incx kk = kk + (n-j+1) end do end if end if else ! form x := inv( a**t )*x or x := inv( a**h )*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n temp = x(j) k = kk if (noconj) then do i = 1,j - 1 temp = temp - ap(k)*x(i) k = k + 1 end do if (nounit) temp = temp/ap(kk+j-1) else do i = 1,j - 1 temp = temp - conjg(ap(k))*x(i) k = k + 1 end do if (nounit) temp = temp/conjg(ap(kk+j-1)) end if x(j) = temp kk = kk + j end do else jx = kx do j = 1,n temp = x(jx) ix = kx if (noconj) then do k = kk,kk + j - 2 temp = temp - ap(k)*x(ix) ix = ix + incx end do if (nounit) temp = temp/ap(kk+j-1) else do k = kk,kk + j - 2 temp = temp - conjg(ap(k))*x(ix) ix = ix + incx end do if (nounit) temp = temp/conjg(ap(kk+j-1)) end if x(jx) = temp jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) k = kk if (noconj) then do i = n,j + 1,-1 temp = temp - ap(k)*x(i) k = k - 1 end do if (nounit) temp = temp/ap(kk-n+j) else do i = n,j + 1,-1 temp = temp - conjg(ap(k))*x(i) k = k - 1 end do if (nounit) temp = temp/conjg(ap(kk-n+j)) end if x(j) = temp kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx if (noconj) then do k = kk,kk - (n- (j+1)),-1 temp = temp - ap(k)*x(ix) ix = ix - incx end do if (nounit) temp = temp/ap(kk-n+j) else do k = kk,kk - (n- (j+1)),-1 temp = temp - conjg(ap(k))*x(ix) ix = ix - incx end do if (nounit) temp = temp/conjg(ap(kk-n+j)) end if x(jx) = temp jx = jx - incx kk = kk - (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_ctpsv pure module subroutine stdlib${ii}$_ztpsv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_dp !! ZTPSV solves one of the systems of equations !! A*x = b, or A**T*x = b, or A**H*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular matrix, supplied in packed form. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(dp), intent(in) :: ap(*) complex(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(dp) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('ZTPSV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with cone pass through ap. if (stdlib_lsame(trans,'N')) then ! form x := inv( a )*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk - 1 do i = j - 1,1,-1 x(i) = x(i) - temp*ap(k) k = k - 1 end do end if kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 if (x(jx)/=czero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk - 1,kk - j + 1,-1 ix = ix - incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n if (x(j)/=czero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk + 1 do i = j + 1,n x(i) = x(i) - temp*ap(k) k = k + 1 end do end if kk = kk + (n-j+1) end do else jx = kx do j = 1,n if (x(jx)/=czero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk + 1,kk + n - j ix = ix + incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx + incx kk = kk + (n-j+1) end do end if end if else ! form x := inv( a**t )*x or x := inv( a**h )*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n temp = x(j) k = kk if (noconj) then do i = 1,j - 1 temp = temp - ap(k)*x(i) k = k + 1 end do if (nounit) temp = temp/ap(kk+j-1) else do i = 1,j - 1 temp = temp - conjg(ap(k))*x(i) k = k + 1 end do if (nounit) temp = temp/conjg(ap(kk+j-1)) end if x(j) = temp kk = kk + j end do else jx = kx do j = 1,n temp = x(jx) ix = kx if (noconj) then do k = kk,kk + j - 2 temp = temp - ap(k)*x(ix) ix = ix + incx end do if (nounit) temp = temp/ap(kk+j-1) else do k = kk,kk + j - 2 temp = temp - conjg(ap(k))*x(ix) ix = ix + incx end do if (nounit) temp = temp/conjg(ap(kk+j-1)) end if x(jx) = temp jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) k = kk if (noconj) then do i = n,j + 1,-1 temp = temp - ap(k)*x(i) k = k - 1 end do if (nounit) temp = temp/ap(kk-n+j) else do i = n,j + 1,-1 temp = temp - conjg(ap(k))*x(i) k = k - 1 end do if (nounit) temp = temp/conjg(ap(kk-n+j)) end if x(j) = temp kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx if (noconj) then do k = kk,kk - (n- (j+1)),-1 temp = temp - ap(k)*x(ix) ix = ix - incx end do if (nounit) temp = temp/ap(kk-n+j) else do k = kk,kk - (n- (j+1)),-1 temp = temp - conjg(ap(k))*x(ix) ix = ix - incx end do if (nounit) temp = temp/conjg(ap(kk-n+j)) end if x(jx) = temp jx = jx - incx kk = kk - (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_ztpsv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tpsv(uplo,trans,diag,n,ap,x,incx) use stdlib_blas_constants_${ck}$ !! ZTPSV: solves one of the systems of equations !! A*x = b, or A**T*x = b, or A**H*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular matrix, supplied in packed form. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. ! -- reference blas level2 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n character, intent(in) :: diag, trans, uplo ! Array Arguments complex(${ck}$), intent(in) :: ap(*) complex(${ck}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: temp integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx logical(lk) :: noconj, nounit ! Intrinsic Functions intrinsic :: conjg ! test the input parameters. info = 0 if (.not.stdlib_lsame(uplo,'U') .and. .not.stdlib_lsame(uplo,'L')) then info = 1 else if (.not.stdlib_lsame(trans,'N') .and. .not.stdlib_lsame(trans,'T') & .and..not.stdlib_lsame(trans,'C')) then info = 2 else if (.not.stdlib_lsame(diag,'U') .and. .not.stdlib_lsame(diag,'N')) then info = 3 else if (n<0) then info = 4 else if (incx==0) then info = 7 end if if (info/=0) then call stdlib${ii}$_xerbla('ZTPSV ',info) return end if ! quick return if possible. if (n==0) return noconj = stdlib_lsame(trans,'T') nounit = stdlib_lsame(diag,'N') ! set up the start point in x if the increment is not unity. this ! will be ( n - 1 )*incx too small for descending loops. if (incx<=0) then kx = 1 - (n-1)*incx else if (incx/=1) then kx = 1 end if ! start the operations. in this version the elements of ap are ! accessed sequentially with cone pass through ap. if (stdlib_lsame(trans,'N')) then ! form x := inv( a )*x. if (stdlib_lsame(uplo,'U')) then kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 if (x(j)/=czero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk - 1 do i = j - 1,1,-1 x(i) = x(i) - temp*ap(k) k = k - 1 end do end if kk = kk - j end do else jx = kx + (n-1)*incx do j = n,1,-1 if (x(jx)/=czero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk - 1,kk - j + 1,-1 ix = ix - incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx - incx kk = kk - j end do end if else kk = 1 if (incx==1) then do j = 1,n if (x(j)/=czero) then if (nounit) x(j) = x(j)/ap(kk) temp = x(j) k = kk + 1 do i = j + 1,n x(i) = x(i) - temp*ap(k) k = k + 1 end do end if kk = kk + (n-j+1) end do else jx = kx do j = 1,n if (x(jx)/=czero) then if (nounit) x(jx) = x(jx)/ap(kk) temp = x(jx) ix = jx do k = kk + 1,kk + n - j ix = ix + incx x(ix) = x(ix) - temp*ap(k) end do end if jx = jx + incx kk = kk + (n-j+1) end do end if end if else ! form x := inv( a**t )*x or x := inv( a**h )*x. if (stdlib_lsame(uplo,'U')) then kk = 1 if (incx==1) then do j = 1,n temp = x(j) k = kk if (noconj) then do i = 1,j - 1 temp = temp - ap(k)*x(i) k = k + 1 end do if (nounit) temp = temp/ap(kk+j-1) else do i = 1,j - 1 temp = temp - conjg(ap(k))*x(i) k = k + 1 end do if (nounit) temp = temp/conjg(ap(kk+j-1)) end if x(j) = temp kk = kk + j end do else jx = kx do j = 1,n temp = x(jx) ix = kx if (noconj) then do k = kk,kk + j - 2 temp = temp - ap(k)*x(ix) ix = ix + incx end do if (nounit) temp = temp/ap(kk+j-1) else do k = kk,kk + j - 2 temp = temp - conjg(ap(k))*x(ix) ix = ix + incx end do if (nounit) temp = temp/conjg(ap(kk+j-1)) end if x(jx) = temp jx = jx + incx kk = kk + j end do end if else kk = (n* (n+1))/2 if (incx==1) then do j = n,1,-1 temp = x(j) k = kk if (noconj) then do i = n,j + 1,-1 temp = temp - ap(k)*x(i) k = k - 1 end do if (nounit) temp = temp/ap(kk-n+j) else do i = n,j + 1,-1 temp = temp - conjg(ap(k))*x(i) k = k - 1 end do if (nounit) temp = temp/conjg(ap(kk-n+j)) end if x(j) = temp kk = kk - (n-j+1) end do else kx = kx + (n-1)*incx jx = kx do j = n,1,-1 temp = x(jx) ix = kx if (noconj) then do k = kk,kk - (n- (j+1)),-1 temp = temp - ap(k)*x(ix) ix = ix - incx end do if (nounit) temp = temp/ap(kk-n+j) else do k = kk,kk - (n- (j+1)),-1 temp = temp - conjg(ap(k))*x(ix) ix = ix - incx end do if (nounit) temp = temp/conjg(ap(kk-n+j)) end if x(jx) = temp jx = jx - incx kk = kk - (n-j+1) end do end if end if end if return end subroutine stdlib${ii}$_${ci}$tpsv #:endif #:endfor #:endfor end submodule stdlib_blas_level2_tri fortran-lang-stdlib-0ede301/src/blas/stdlib_blas_level3_tri.fypp0000664000175000017500000035226015135654166025220 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_blas) stdlib_blas_level3_tri implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_strmm(side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb) use stdlib_blas_constants_sp !! STRMM performs one of the matrix-matrix operations !! B := alpha*op( A )*B, or B := alpha*B*op( A ), !! where alpha is a scalar, B is an m by n matrix, A is a unit, or !! non-unit, upper or lower triangular matrix and op( A ) is one of !! op( A ) = A or op( A ) = A**T. ! -- reference blas level3 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha integer(${ik}$), intent(in) :: lda, ldb, m, n character, intent(in) :: diag, side, transa, uplo ! Array Arguments real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Intrinsic Functions intrinsic :: max ! Local Scalars real(sp) :: temp integer(${ik}$) :: i, info, j, k, nrowa logical(lk) :: lside, nounit, upper ! test the input parameters. lside = stdlib_lsame(side,'L') if (lside) then nrowa = m else nrowa = n end if nounit = stdlib_lsame(diag,'N') upper = stdlib_lsame(uplo,'U') info = 0 if ((.not.lside) .and. (.not.stdlib_lsame(side,'R'))) then info = 1 else if ((.not.upper) .and. (.not.stdlib_lsame(uplo,'L'))) then info = 2 else if ((.not.stdlib_lsame(transa,'N')) .and.(.not.stdlib_lsame(transa,'T')) .and.(& .not.stdlib_lsame(transa,'C'))) then info = 3 else if ((.not.stdlib_lsame(diag,'U')) .and. (.not.stdlib_lsame(diag,'N'))) & then info = 4 else if (m<0) then info = 5 else if (n<0) then info = 6 else if (lda= 0, else LX = 1+(1-N)*INCX, and LY is !! defined in a similar way using INCY. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments real(sp), intent(in) :: sx(*), sy(*) ! authors: ! ======== ! lawson, c. l., (jpl), hanson, r. j., (snla), ! kincaid, d. r., (u. of texas), krogh, f. t., (jpl) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, kx, ky, ns ! Intrinsic Functions intrinsic :: real stdlib${ii}$_dsdot = zero if (n<=0) return if (incx==incy .and. incx>0) then ! code for equal, positive, non-unit increments. ns = n*incx do i = 1,ns,incx stdlib${ii}$_dsdot = stdlib${ii}$_dsdot + real(sx(i),KIND=dp)*real(sy(i),KIND=dp) end do else ! code for unequal or nonpositive increments. kx = 1 ky = 1 if (incx<0) kx = 1 + (1-n)*incx if (incy<0) ky = 1 + (1-n)*incy do i = 1,n stdlib${ii}$_dsdot = stdlib${ii}$_dsdot + real(sx(kx),KIND=dp)*real(sy(ky),KIND=dp) kx = kx + incx ky = ky + incy end do end if return end function stdlib${ii}$_dsdot #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$sdot(n,sx,incx,sy,incy) use stdlib_blas_constants_${rk}$ !! Compute the inner product of two vectors with extended !! precision accumulation and result. !! Returns D.P. dot product accumulated in D.P., for S.P. SX and SY !! DSDOT: = sum for I = 0 to N-1 of SX(LX+I*INCX) * SY(LY+I*INCY), !! where LX = 1 if INCX >= 0, else LX = 1+(1-N)*INCX, and LY is !! defined in a similar way using INCY. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments real(dp), intent(in) :: sx(*), sy(*) ! authors: ! ======== ! lawson, c. l., (jpl), hanson, r. j., (snla), ! kincaid, d. r., (u. of texas), krogh, f. t., (jpl) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, kx, ky, ns ! Intrinsic Functions intrinsic :: real stdlib${ii}$_${ri}$sdot = zero if (n<=0) return if (incx==incy .and. incx>0) then ! code for equal, positive, non-unit increments. ns = n*incx do i = 1,ns,incx stdlib${ii}$_${ri}$sdot = stdlib${ii}$_${ri}$sdot + real(sx(i),KIND=${rk}$)*real(sy(i),KIND=${rk}$) end do else ! code for unequal or nonpositive increments. kx = 1 ky = 1 if (incx<0) kx = 1 + (1-n)*incx if (incy<0) ky = 1 + (1-n)*incy do i = 1,n stdlib${ii}$_${ri}$sdot = stdlib${ii}$_${ri}$sdot + real(sx(kx),KIND=${rk}$)*real(sy(ky),KIND=${rk}$) kx = kx + incx ky = ky + incy end do end if return end function stdlib${ii}$_${ri}$sdot #:endif #:endfor pure complex(sp) module function stdlib${ii}$_cdotc(n,cx,incx,cy,incy) use stdlib_blas_constants_sp !! CDOTC forms the dot product of two complex vectors !! CDOTC = X^H * Y ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments complex(sp), intent(in) :: cx(*), cy(*) ! ===================================================================== ! Local Scalars complex(sp) :: ctemp integer(${ik}$) :: i, ix, iy ! Intrinsic Functions intrinsic :: conjg ctemp = (0.0_sp,0.0_sp) stdlib${ii}$_cdotc = (0.0_sp,0.0_sp) if (n<=0) return if (incx==1 .and. incy==1) then ! code for both increments equal to 1 do i = 1,n ctemp = ctemp + conjg(cx(i))*cy(i) end do else ! code for unequal increments or equal increments ! not equal to 1 ix = 1 iy = 1 if (incx<0) ix = (-n+1)*incx + 1 if (incy<0) iy = (-n+1)*incy + 1 do i = 1,n ctemp = ctemp + conjg(cx(ix))*cy(iy) ix = ix + incx iy = iy + incy end do end if stdlib${ii}$_cdotc = ctemp return end function stdlib${ii}$_cdotc pure complex(dp) module function stdlib${ii}$_zdotc(n,zx,incx,zy,incy) use stdlib_blas_constants_dp !! ZDOTC forms the dot product of two complex vectors !! ZDOTC = X^H * Y ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments complex(dp), intent(in) :: zx(*), zy(*) ! ===================================================================== ! Local Scalars complex(dp) :: ztemp integer(${ik}$) :: i, ix, iy ! Intrinsic Functions intrinsic :: conjg ztemp = (0.0_dp,0.0_dp) stdlib${ii}$_zdotc = (0.0_dp,0.0_dp) if (n<=0) return if (incx==1 .and. incy==1) then ! code for both increments equal to 1 do i = 1,n ztemp = ztemp + conjg(zx(i))*zy(i) end do else ! code for unequal increments or equal increments ! not equal to 1 ix = 1 iy = 1 if (incx<0) ix = (-n+1)*incx + 1 if (incy<0) iy = (-n+1)*incy + 1 do i = 1,n ztemp = ztemp + conjg(zx(ix))*zy(iy) ix = ix + incx iy = iy + incy end do end if stdlib${ii}$_zdotc = ztemp return end function stdlib${ii}$_zdotc #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure complex(${ck}$) module function stdlib${ii}$_${ci}$dotc(n,zx,incx,zy,incy) use stdlib_blas_constants_${ck}$ !! ZDOTC: forms the dot product of two complex vectors !! ZDOTC = X^H * Y ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments complex(${ck}$), intent(in) :: zx(*), zy(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: ztemp integer(${ik}$) :: i, ix, iy ! Intrinsic Functions intrinsic :: conjg ztemp = (0.0_${ck}$,0.0_${ck}$) stdlib${ii}$_${ci}$dotc = (0.0_${ck}$,0.0_${ck}$) if (n<=0) return if (incx==1 .and. incy==1) then ! code for both increments equal to 1 do i = 1,n ztemp = ztemp + conjg(zx(i))*zy(i) end do else ! code for unequal increments or equal increments ! not equal to 1 ix = 1 iy = 1 if (incx<0) ix = (-n+1)*incx + 1 if (incy<0) iy = (-n+1)*incy + 1 do i = 1,n ztemp = ztemp + conjg(zx(ix))*zy(iy) ix = ix + incx iy = iy + incy end do end if stdlib${ii}$_${ci}$dotc = ztemp return end function stdlib${ii}$_${ci}$dotc #:endif #:endfor pure complex(sp) module function stdlib${ii}$_cdotu(n,cx,incx,cy,incy) use stdlib_blas_constants_sp !! CDOTU forms the dot product of two complex vectors !! CDOTU = X^T * Y ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments complex(sp), intent(in) :: cx(*), cy(*) ! ===================================================================== ! Local Scalars complex(sp) :: ctemp integer(${ik}$) :: i, ix, iy ctemp = (0.0_sp,0.0_sp) stdlib${ii}$_cdotu = (0.0_sp,0.0_sp) if (n<=0) return if (incx==1 .and. incy==1) then ! code for both increments equal to 1 do i = 1,n ctemp = ctemp + cx(i)*cy(i) end do else ! code for unequal increments or equal increments ! not equal to 1 ix = 1 iy = 1 if (incx<0) ix = (-n+1)*incx + 1 if (incy<0) iy = (-n+1)*incy + 1 do i = 1,n ctemp = ctemp + cx(ix)*cy(iy) ix = ix + incx iy = iy + incy end do end if stdlib${ii}$_cdotu = ctemp return end function stdlib${ii}$_cdotu pure complex(dp) module function stdlib${ii}$_zdotu(n,zx,incx,zy,incy) use stdlib_blas_constants_dp !! ZDOTU forms the dot product of two complex vectors !! ZDOTU = X^T * Y ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments complex(dp), intent(in) :: zx(*), zy(*) ! ===================================================================== ! Local Scalars complex(dp) :: ztemp integer(${ik}$) :: i, ix, iy ztemp = (0.0_dp,0.0_dp) stdlib${ii}$_zdotu = (0.0_dp,0.0_dp) if (n<=0) return if (incx==1 .and. incy==1) then ! code for both increments equal to 1 do i = 1,n ztemp = ztemp + zx(i)*zy(i) end do else ! code for unequal increments or equal increments ! not equal to 1 ix = 1 iy = 1 if (incx<0) ix = (-n+1)*incx + 1 if (incy<0) iy = (-n+1)*incy + 1 do i = 1,n ztemp = ztemp + zx(ix)*zy(iy) ix = ix + incx iy = iy + incy end do end if stdlib${ii}$_zdotu = ztemp return end function stdlib${ii}$_zdotu #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure complex(${ck}$) module function stdlib${ii}$_${ci}$dotu(n,zx,incx,zy,incy) use stdlib_blas_constants_${ck}$ !! ZDOTU: forms the dot product of two complex vectors !! ZDOTU = X^T * Y ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments complex(${ck}$), intent(in) :: zx(*), zy(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: ztemp integer(${ik}$) :: i, ix, iy ztemp = (0.0_${ck}$,0.0_${ck}$) stdlib${ii}$_${ci}$dotu = (0.0_${ck}$,0.0_${ck}$) if (n<=0) return if (incx==1 .and. incy==1) then ! code for both increments equal to 1 do i = 1,n ztemp = ztemp + zx(i)*zy(i) end do else ! code for unequal increments or equal increments ! not equal to 1 ix = 1 iy = 1 if (incx<0) ix = (-n+1)*incx + 1 if (incy<0) iy = (-n+1)*incy + 1 do i = 1,n ztemp = ztemp + zx(ix)*zy(iy) ix = ix + incx iy = iy + incy end do end if stdlib${ii}$_${ci}$dotu = ztemp return end function stdlib${ii}$_${ci}$dotu #:endif #:endfor pure real(sp) module function stdlib${ii}$_snrm2( n, x, incx ) use stdlib_blas_constants_sp !! SNRM2 returns the euclidean norm of a vector via the function !! name, so that !! SNRM2 := sqrt( x'*x ). ! -- reference blas level1 routine (version 3.9.1_sp) -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! march 2021 ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments real(sp), intent(in) :: x(*) ! ===================================================================== ! Constants real(sp), parameter :: maxn = huge(0.0_sp) ! .. blue's scaling constants .. ! Local Scalars integer(${ik}$) :: i, ix logical(lk) :: notbig real(sp) :: abig, amed, asml, ax, scl, sumsq, ymax, ymin ! quick return if possible stdlib${ii}$_snrm2 = zero if( n <= 0 ) return scl = one sumsq = zero ! compute the sum of squares in 3 accumulators: ! abig -- sums of squares scaled down to avoid overflow ! asml -- sums of squares scaled up to avoid underflow ! amed -- sums of squares that do not require scaling ! the thresholds and multipliers are ! tbig -- values bigger than this are scaled down by sbig ! tsml -- values smaller than this are scaled up by ssml notbig = .true. asml = zero amed = zero abig = zero ix = 1 if( incx < 0 ) ix = 1 - (n-1)*incx do i = 1, n ax = abs(x(ix)) if (ax > tbig) then abig = abig + (ax*sbig)**2 notbig = .false. else if (ax < tsml) then if (notbig) asml = asml + (ax*ssml)**2 else amed = amed + ax**2 end if ix = ix + incx end do ! combine abig and amed or amed and asml if more than one ! accumulator was used. if (abig > zero) then ! combine abig and amed if abig > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then abig = abig + (amed*sbig)*sbig end if scl = one / sbig sumsq = abig else if (asml > zero) then ! combine amed and asml if asml > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then amed = sqrt(amed) asml = sqrt(asml) / ssml if (asml > amed) then ymin = amed ymax = asml else ymin = asml ymax = amed end if scl = one sumsq = ymax**2*( one + (ymin/ymax)**2 ) else scl = one / ssml sumsq = asml end if else ! otherwise all values are mid-range scl = one sumsq = amed end if stdlib${ii}$_snrm2 = scl*sqrt( sumsq ) return end function stdlib${ii}$_snrm2 pure real(dp) module function stdlib${ii}$_dnrm2( n, x, incx ) use stdlib_blas_constants_dp !! DNRM2 returns the euclidean norm of a vector via the function !! name, so that !! DNRM2 := sqrt( x'*x ) ! -- reference blas level1 routine (version 3.9.1_dp) -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! march 2021 ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments real(dp), intent(in) :: x(*) ! ===================================================================== ! Constants real(dp), parameter :: maxn = huge(0.0_dp) ! .. blue's scaling constants .. ! Local Scalars integer(${ik}$) :: i, ix logical(lk) :: notbig real(dp) :: abig, amed, asml, ax, scl, sumsq, ymax, ymin ! quick return if possible stdlib${ii}$_dnrm2 = zero if( n <= 0 ) return scl = one sumsq = zero ! compute the sum of squares in 3 accumulators: ! abig -- sums of squares scaled down to avoid overflow ! asml -- sums of squares scaled up to avoid underflow ! amed -- sums of squares that do not require scaling ! the thresholds and multipliers are ! tbig -- values bigger than this are scaled down by sbig ! tsml -- values smaller than this are scaled up by ssml notbig = .true. asml = zero amed = zero abig = zero ix = 1 if( incx < 0 ) ix = 1 - (n-1)*incx do i = 1, n ax = abs(x(ix)) if (ax > tbig) then abig = abig + (ax*sbig)**2 notbig = .false. else if (ax < tsml) then if (notbig) asml = asml + (ax*ssml)**2 else amed = amed + ax**2 end if ix = ix + incx end do ! combine abig and amed or amed and asml if more than one ! accumulator was used. if (abig > zero) then ! combine abig and amed if abig > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then abig = abig + (amed*sbig)*sbig end if scl = one / sbig sumsq = abig else if (asml > zero) then ! combine amed and asml if asml > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then amed = sqrt(amed) asml = sqrt(asml) / ssml if (asml > amed) then ymin = amed ymax = asml else ymin = asml ymax = amed end if scl = one sumsq = ymax**2*( one + (ymin/ymax)**2 ) else scl = one / ssml sumsq = asml end if else ! otherwise all values are mid-range scl = one sumsq = amed end if stdlib${ii}$_dnrm2 = scl*sqrt( sumsq ) return end function stdlib${ii}$_dnrm2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$nrm2( n, x, incx ) use stdlib_blas_constants_${rk}$ !! DNRM2: returns the euclidean norm of a vector via the function !! name, so that !! DNRM2 := sqrt( x'*x ) ! -- reference blas level1 routine (version 3.9.1_${rk}$) -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! march 2021 ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments real(${rk}$), intent(in) :: x(*) ! ===================================================================== ! Constants real(${rk}$), parameter :: maxn = huge(0.0_${rk}$) ! .. blue's scaling constants .. ! Local Scalars integer(${ik}$) :: i, ix logical(lk) :: notbig real(${rk}$) :: abig, amed, asml, ax, scl, sumsq, ymax, ymin ! quick return if possible stdlib${ii}$_${ri}$nrm2 = zero if( n <= 0 ) return scl = one sumsq = zero ! compute the sum of squares in 3 accumulators: ! abig -- sums of squares scaled down to avoid overflow ! asml -- sums of squares scaled up to avoid underflow ! amed -- sums of squares that do not require scaling ! the thresholds and multipliers are ! tbig -- values bigger than this are scaled down by sbig ! tsml -- values smaller than this are scaled up by ssml notbig = .true. asml = zero amed = zero abig = zero ix = 1 if( incx < 0 ) ix = 1 - (n-1)*incx do i = 1, n ax = abs(x(ix)) if (ax > tbig) then abig = abig + (ax*sbig)**2 notbig = .false. else if (ax < tsml) then if (notbig) asml = asml + (ax*ssml)**2 else amed = amed + ax**2 end if ix = ix + incx end do ! combine abig and amed or amed and asml if more than one ! accumulator was used. if (abig > zero) then ! combine abig and amed if abig > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then abig = abig + (amed*sbig)*sbig end if scl = one / sbig sumsq = abig else if (asml > zero) then ! combine amed and asml if asml > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then amed = sqrt(amed) asml = sqrt(asml) / ssml if (asml > amed) then ymin = amed ymax = asml else ymin = asml ymax = amed end if scl = one sumsq = ymax**2*( one + (ymin/ymax)**2 ) else scl = one / ssml sumsq = asml end if else ! otherwise all values are mid-range scl = one sumsq = amed end if stdlib${ii}$_${ri}$nrm2 = scl*sqrt( sumsq ) return end function stdlib${ii}$_${ri}$nrm2 #:endif #:endfor pure real(sp) module function stdlib${ii}$_scnrm2( n, x, incx ) use stdlib_blas_constants_sp !! SCNRM2 returns the euclidean norm of a vector via the function !! name, so that !! SCNRM2 := sqrt( x**H*x ) ! -- reference blas level1 routine (version 3.9.1_sp) -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! march 2021 ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments complex(sp), intent(in) :: x(*) ! ===================================================================== ! Constants real(sp), parameter :: maxn = huge(0.0_sp) ! .. blue's scaling constants .. ! Local Scalars integer(${ik}$) :: i, ix logical(lk) :: notbig real(sp) :: abig, amed, asml, ax, scl, sumsq, ymax, ymin ! quick return if possible stdlib${ii}$_scnrm2 = zero if( n <= 0 ) return scl = one sumsq = zero ! compute the sum of squares in 3 accumulators: ! abig -- sums of squares scaled down to avoid overflow ! asml -- sums of squares scaled up to avoid underflow ! amed -- sums of squares that do not require scaling ! the thresholds and multipliers are ! tbig -- values bigger than this are scaled down by sbig ! tsml -- values smaller than this are scaled up by ssml notbig = .true. asml = zero amed = zero abig = zero ix = 1 if( incx < 0 ) ix = 1 - (n-1)*incx do i = 1, n ax = abs(real(x(ix),KIND=sp)) if (ax > tbig) then abig = abig + (ax*sbig)**2 notbig = .false. else if (ax < tsml) then if (notbig) asml = asml + (ax*ssml)**2 else amed = amed + ax**2 end if ax = abs(aimag(x(ix))) if (ax > tbig) then abig = abig + (ax*sbig)**2 notbig = .false. else if (ax < tsml) then if (notbig) asml = asml + (ax*ssml)**2 else amed = amed + ax**2 end if ix = ix + incx end do ! combine abig and amed or amed and asml if more than one ! accumulator was used. if (abig > zero) then ! combine abig and amed if abig > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then abig = abig + (amed*sbig)*sbig end if scl = one / sbig sumsq = abig else if (asml > zero) then ! combine amed and asml if asml > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then amed = sqrt(amed) asml = sqrt(asml) / ssml if (asml > amed) then ymin = amed ymax = asml else ymin = asml ymax = amed end if scl = one sumsq = ymax**2*( one + (ymin/ymax)**2 ) else scl = one / ssml sumsq = asml end if else ! otherwise all values are mid-range scl = one sumsq = amed end if stdlib${ii}$_scnrm2 = scl*sqrt( sumsq ) return end function stdlib${ii}$_scnrm2 pure real(dp) module function stdlib${ii}$_dznrm2( n, x, incx ) use stdlib_blas_constants_dp !! DZNRM2 returns the euclidean norm of a vector via the function !! name, so that !! DZNRM2 := sqrt( x**H*x ) ! -- reference blas level1 routine (version 3.9.1_dp) -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! march 2021 ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments complex(dp), intent(in) :: x(*) ! ===================================================================== ! Constants real(dp), parameter :: maxn = huge(0.0_dp) ! .. blue's scaling constants .. ! Local Scalars integer(${ik}$) :: i, ix logical(lk) :: notbig real(dp) :: abig, amed, asml, ax, scl, sumsq, ymax, ymin ! quick return if possible stdlib${ii}$_dznrm2 = zero if( n <= 0 ) return scl = one sumsq = zero ! compute the sum of squares in 3 accumulators: ! abig -- sums of squares scaled down to avoid overflow ! asml -- sums of squares scaled up to avoid underflow ! amed -- sums of squares that do not require scaling ! the thresholds and multipliers are ! tbig -- values bigger than this are scaled down by sbig ! tsml -- values smaller than this are scaled up by ssml notbig = .true. asml = zero amed = zero abig = zero ix = 1 if( incx < 0 ) ix = 1 - (n-1)*incx do i = 1, n ax = abs(real(x(ix),KIND=dp)) if (ax > tbig) then abig = abig + (ax*sbig)**2 notbig = .false. else if (ax < tsml) then if (notbig) asml = asml + (ax*ssml)**2 else amed = amed + ax**2 end if ax = abs(aimag(x(ix))) if (ax > tbig) then abig = abig + (ax*sbig)**2 notbig = .false. else if (ax < tsml) then if (notbig) asml = asml + (ax*ssml)**2 else amed = amed + ax**2 end if ix = ix + incx end do ! combine abig and amed or amed and asml if more than one ! accumulator was used. if (abig > zero) then ! combine abig and amed if abig > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then abig = abig + (amed*sbig)*sbig end if scl = one / sbig sumsq = abig else if (asml > zero) then ! combine amed and asml if asml > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then amed = sqrt(amed) asml = sqrt(asml) / ssml if (asml > amed) then ymin = amed ymax = asml else ymin = asml ymax = amed end if scl = one sumsq = ymax**2*( one + (ymin/ymax)**2 ) else scl = one / ssml sumsq = asml end if else ! otherwise all values are mid-range scl = one sumsq = amed end if stdlib${ii}$_dznrm2 = scl*sqrt( sumsq ) return end function stdlib${ii}$_dznrm2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$znrm2( n, x, incx ) use stdlib_blas_constants_${rk}$ !! DZNRM2: returns the euclidean norm of a vector via the function !! name, so that !! DZNRM2 := sqrt( x**H*x ) ! -- reference blas level1 routine (version 3.9.1_${rk}$) -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! march 2021 ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments complex(${rk}$), intent(in) :: x(*) ! ===================================================================== ! Constants real(${rk}$), parameter :: maxn = huge(0.0_${rk}$) ! .. blue's scaling constants .. ! Local Scalars integer(${ik}$) :: i, ix logical(lk) :: notbig real(${rk}$) :: abig, amed, asml, ax, scl, sumsq, ymax, ymin ! quick return if possible stdlib${ii}$_${ri}$znrm2 = zero if( n <= 0 ) return scl = one sumsq = zero ! compute the sum of squares in 3 accumulators: ! abig -- sums of squares scaled down to avoid overflow ! asml -- sums of squares scaled up to avoid underflow ! amed -- sums of squares that do not require scaling ! the thresholds and multipliers are ! tbig -- values bigger than this are scaled down by sbig ! tsml -- values smaller than this are scaled up by ssml notbig = .true. asml = zero amed = zero abig = zero ix = 1 if( incx < 0 ) ix = 1 - (n-1)*incx do i = 1, n ax = abs(real(x(ix),KIND=${rk}$)) if (ax > tbig) then abig = abig + (ax*sbig)**2 notbig = .false. else if (ax < tsml) then if (notbig) asml = asml + (ax*ssml)**2 else amed = amed + ax**2 end if ax = abs(aimag(x(ix))) if (ax > tbig) then abig = abig + (ax*sbig)**2 notbig = .false. else if (ax < tsml) then if (notbig) asml = asml + (ax*ssml)**2 else amed = amed + ax**2 end if ix = ix + incx end do ! combine abig and amed or amed and asml if more than one ! accumulator was used. if (abig > zero) then ! combine abig and amed if abig > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then abig = abig + (amed*sbig)*sbig end if scl = one / sbig sumsq = abig else if (asml > zero) then ! combine amed and asml if asml > 0. if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then amed = sqrt(amed) asml = sqrt(asml) / ssml if (asml > amed) then ymin = amed ymax = asml else ymin = asml ymax = amed end if scl = one sumsq = ymax**2*( one + (ymin/ymax)**2 ) else scl = one / ssml sumsq = asml end if else ! otherwise all values are mid-range scl = one sumsq = amed end if stdlib${ii}$_${ri}$znrm2 = scl*sqrt( sumsq ) return end function stdlib${ii}$_${ri}$znrm2 #:endif #:endfor pure module subroutine stdlib${ii}$_srot(n,sx,incx,sy,incy,c,s) use stdlib_blas_constants_sp !! applies a plane rotation. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: c, s integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments real(sp), intent(inout) :: sx(*), sy(*) ! ===================================================================== ! Local Scalars real(sp) :: stemp integer(${ik}$) :: i, ix, iy if (n<=0) return if (incx==1 .and. incy==1) then ! code for both increments equal to 1 do i = 1,n stemp = c*sx(i) + s*sy(i) sy(i) = c*sy(i) - s*sx(i) sx(i) = stemp end do else ! code for unequal increments or equal increments not equal ! to 1 ix = 1 iy = 1 if (incx<0) ix = (-n+1)*incx + 1 if (incy<0) iy = (-n+1)*incy + 1 do i = 1,n stemp = c*sx(ix) + s*sy(iy) sy(iy) = c*sy(iy) - s*sx(ix) sx(ix) = stemp ix = ix + incx iy = iy + incy end do end if return end subroutine stdlib${ii}$_srot pure module subroutine stdlib${ii}$_drot(n,dx,incx,dy,incy,c,s) use stdlib_blas_constants_dp !! DROT applies a plane rotation. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(in) :: c, s integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments real(dp), intent(inout) :: dx(*), dy(*) ! ===================================================================== ! Local Scalars real(dp) :: dtemp integer(${ik}$) :: i, ix, iy if (n<=0) return if (incx==1 .and. incy==1) then ! code for both increments equal to 1 do i = 1,n dtemp = c*dx(i) + s*dy(i) dy(i) = c*dy(i) - s*dx(i) dx(i) = dtemp end do else ! code for unequal increments or equal increments not equal ! to 1 ix = 1 iy = 1 if (incx<0) ix = (-n+1)*incx + 1 if (incy<0) iy = (-n+1)*incy + 1 do i = 1,n dtemp = c*dx(ix) + s*dy(iy) dy(iy) = c*dy(iy) - s*dx(ix) dx(ix) = dtemp ix = ix + incx iy = iy + incy end do end if return end subroutine stdlib${ii}$_drot #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$rot(n,dx,incx,dy,incy,c,s) use stdlib_blas_constants_${rk}$ !! DROT: applies a plane rotation. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${rk}$), intent(in) :: c, s integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments real(${rk}$), intent(inout) :: dx(*), dy(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: dtemp integer(${ik}$) :: i, ix, iy if (n<=0) return if (incx==1 .and. incy==1) then ! code for both increments equal to 1 do i = 1,n dtemp = c*dx(i) + s*dy(i) dy(i) = c*dy(i) - s*dx(i) dx(i) = dtemp end do else ! code for unequal increments or equal increments not equal ! to 1 ix = 1 iy = 1 if (incx<0) ix = (-n+1)*incx + 1 if (incy<0) iy = (-n+1)*incy + 1 do i = 1,n dtemp = c*dx(ix) + s*dy(iy) dy(iy) = c*dy(iy) - s*dx(ix) dx(ix) = dtemp ix = ix + incx iy = iy + incy end do end if return end subroutine stdlib${ii}$_${ri}$rot #:endif #:endfor pure module subroutine stdlib${ii}$_zdrot( n, zx, incx, zy, incy, c, s ) use stdlib_blas_constants_dp !! Applies a plane rotation, where the cos and sin (c and s) are real !! and the vectors cx and cy are complex. !! jack dongarra, linpack, 3/11/78. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n real(dp), intent(in) :: c, s ! Array Arguments complex(dp), intent(inout) :: zx(*), zy(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ix, iy complex(dp) :: ctemp ! Executable Statements if( n<=0 )return if( incx==1 .and. incy==1 ) then ! code for both increments equal to 1 do i = 1, n ctemp = c*zx( i ) + s*zy( i ) zy( i ) = c*zy( i ) - s*zx( i ) zx( i ) = ctemp end do else ! code for unequal increments or equal increments not equal ! to 1 ix = 1 iy = 1 if( incx<0 )ix = ( -n+1 )*incx + 1 if( incy<0 )iy = ( -n+1 )*incy + 1 do i = 1, n ctemp = c*zx( ix ) + s*zy( iy ) zy( iy ) = c*zy( iy ) - s*zx( ix ) zx( ix ) = ctemp ix = ix + incx iy = iy + incy end do end if return end subroutine stdlib${ii}$_zdrot #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$drot( n, zx, incx, zy, incy, c, s ) use stdlib_blas_constants_${ck}$ !! Applies a plane rotation, where the cos and sin (c and s) are real !! and the vectors cx and cy are complex. !! jack dongarra, linpack, 3/11/78. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n real(${ck}$), intent(in) :: c, s ! Array Arguments complex(${ck}$), intent(inout) :: zx(*), zy(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ix, iy complex(${ck}$) :: ctemp ! Executable Statements if( n<=0 )return if( incx==1 .and. incy==1 ) then ! code for both increments equal to 1 do i = 1, n ctemp = c*zx( i ) + s*zy( i ) zy( i ) = c*zy( i ) - s*zx( i ) zx( i ) = ctemp end do else ! code for unequal increments or equal increments not equal ! to 1 ix = 1 iy = 1 if( incx<0 )ix = ( -n+1 )*incx + 1 if( incy<0 )iy = ( -n+1 )*incy + 1 do i = 1, n ctemp = c*zx( ix ) + s*zy( iy ) zy( iy ) = c*zy( iy ) - s*zx( ix ) zx( ix ) = ctemp ix = ix + incx iy = iy + incy end do end if return end subroutine stdlib${ii}$_${ci}$drot #:endif #:endfor pure module subroutine stdlib${ii}$_srotg( a, b, c, s ) use stdlib_blas_constants_sp !! The computation uses the formulas !! sigma = sgn(a) if |a| > |b| !! = sgn(b) if |b| >= |a| !! r = sigma*sqrt( a**2 + b**2 ) !! c = 1; s = 0 if r = 0 !! c = a/r; s = b/r if r != 0 !! The subroutine also computes !! z = s if |a| > |b|, !! = 1/c if |b| >= |a| and c != 0 !! = 1 if c = 0 !! This allows c and s to be reconstructed from z as follows: !! If z = 1, set c = 0, s = 1. !! If |z| < 1, set c = sqrt(1 - z**2) and s = z. !! If |z| > 1, set c = 1/z and s = sqrt( 1 - c**2). ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Constants ! Scaling Constants ! Scalar Arguments real(sp), intent(inout) :: a, b real(sp), intent(out) :: c, s ! ===================================================================== ! Local Scalars real(sp) :: anorm, bnorm, scl, sigma, r, z anorm = abs(a) bnorm = abs(b) if( bnorm == zero ) then c = one s = zero b = zero else if( anorm == zero ) then c = zero s = one a = b b = one else scl = min( safmax, max( safmin, anorm, bnorm ) ) if( anorm > bnorm ) then sigma = sign(one,a) else sigma = sign(one,b) end if r = sigma*( scl*sqrt((a/scl)**2 + (b/scl)**2) ) c = a/r s = b/r if( anorm > bnorm ) then z = s else if( c /= zero ) then z = one/c else z = one end if a = r b = z end if return end subroutine stdlib${ii}$_srotg pure module subroutine stdlib${ii}$_drotg( a, b, c, s ) use stdlib_blas_constants_dp !! The computation uses the formulas !! sigma = sgn(a) if |a| > |b| !! = sgn(b) if |b| >= |a| !! r = sigma*sqrt( a**2 + b**2 ) !! c = 1; s = 0 if r = 0 !! c = a/r; s = b/r if r != 0 !! The subroutine also computes !! z = s if |a| > |b|, !! = 1/c if |b| >= |a| and c != 0 !! = 1 if c = 0 !! This allows c and s to be reconstructed from z as follows: !! If z = 1, set c = 0, s = 1. !! If |z| < 1, set c = sqrt(1 - z**2) and s = z. !! If |z| > 1, set c = 1/z and s = sqrt( 1 - c**2). ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scaling Constants ! Scalar Arguments real(dp), intent(inout) :: a, b real(dp), intent(out) :: c, s ! ===================================================================== ! Local Scalars real(dp) :: anorm, bnorm, scl, sigma, r, z anorm = abs(a) bnorm = abs(b) if( bnorm == zero ) then c = one s = zero b = zero else if( anorm == zero ) then c = zero s = one a = b b = one else scl = min( safmax, max( safmin, anorm, bnorm ) ) if( anorm > bnorm ) then sigma = sign(one,a) else sigma = sign(one,b) end if r = sigma*( scl*sqrt((a/scl)**2 + (b/scl)**2) ) c = a/r s = b/r if( anorm > bnorm ) then z = s else if( c /= zero ) then z = one/c else z = one end if a = r b = z end if return end subroutine stdlib${ii}$_drotg #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$rotg( a, b, c, s ) use stdlib_blas_constants_${rk}$ !! The computation uses the formulas !! sigma = sgn(a) if |a| > |b| !! = sgn(b) if |b| >= |a| !! r = sigma*sqrt( a**2 + b**2 ) !! c = 1; s = 0 if r = 0 !! c = a/r; s = b/r if r != 0 !! The subroutine also computes !! z = s if |a| > |b|, !! = 1/c if |b| >= |a| and c != 0 !! = 1 if c = 0 !! This allows c and s to be reconstructed from z as follows: !! If z = 1, set c = 0, s = 1. !! If |z| < 1, set c = sqrt(1 - z**2) and s = z. !! If |z| > 1, set c = 1/z and s = sqrt( 1 - c**2). ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scaling Constants ! Scalar Arguments real(${rk}$), intent(inout) :: a, b real(${rk}$), intent(out) :: c, s ! ===================================================================== ! Local Scalars real(${rk}$) :: anorm, bnorm, scl, sigma, r, z anorm = abs(a) bnorm = abs(b) if( bnorm == zero ) then c = one s = zero b = zero else if( anorm == zero ) then c = zero s = one a = b b = one else scl = min( safmax, max( safmin, anorm, bnorm ) ) if( anorm > bnorm ) then sigma = sign(one,a) else sigma = sign(one,b) end if r = sigma*( scl*sqrt((a/scl)**2 + (b/scl)**2) ) c = a/r s = b/r if( anorm > bnorm ) then z = s else if( c /= zero ) then z = one/c else z = one end if a = r b = z end if return end subroutine stdlib${ii}$_${ri}$rotg #:endif #:endfor pure module subroutine stdlib${ii}$_crotg( a, b, c, s ) use stdlib_blas_constants_sp !! The computation uses the formulas !! |x| = sqrt( Re(x)**2 + Im(x)**2 ) !! sgn(x) = x / |x| if x /= 0 !! = 1 if x = 0 !! c = |a| / sqrt(|a|**2 + |b|**2) !! s = sgn(a) * conjg(b) / sqrt(|a|**2 + |b|**2) !! When a and b are real and r /= 0, the formulas simplify to !! r = sgn(a)*sqrt(|a|**2 + |b|**2) !! c = a / r !! s = b / r !! the same as in SROTG when |a| > |b|. When |b| >= |a|, the !! sign of c and s will be different from those computed by SROTG !! if the signs of a and b are not the same. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scaling Constants ! Scalar Arguments real(sp), intent(out) :: c complex(sp), intent(inout) :: a complex(sp), intent(in) :: b complex(sp), intent(out) :: s ! ===================================================================== ! Local Scalars real(sp) :: d, f1, f2, g1, g2, h2, p, u, uu, v, vv, w complex(sp) :: f, fs, g, gs, r, t ! Intrinsic Functions intrinsic :: abs,aimag,conjg,max,min,real,sqrt ! Statement Functions real(sp) :: abssq ! Statement Function Definitions abssq( t ) = real( t,KIND=sp)**2 + aimag( t )**2 ! Executable Statements f = a g = b if( g == czero ) then c = one s = czero r = f else if( f == czero ) then c = zero g1 = max( abs(real(g,KIND=sp)), abs(aimag(g)) ) if( g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm g2 = abssq( g ) d = sqrt( g2 ) s = conjg( g ) / d r = d else ! use scaled algorithm u = min( safmax, max( safmin, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) d = sqrt( g2 ) s = conjg( gs ) / d r = d*u end if else f1 = max( abs(real(f,KIND=sp)), abs(aimag(f)) ) g1 = max( abs(real(g,KIND=sp)), abs(aimag(g)) ) if( f1 > rtmin .and. f1 < rtmax .and. g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm f2 = abssq( f ) g2 = abssq( g ) h2 = f2 + g2 if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1 / d c = f2*p s = conjg( g )*( f*p ) r = f*( h2*p ) else ! use scaled algorithm u = min( safmax, max( safmin, f1, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) if( f1*uu < rtmin ) then ! f is not well-scaled when scaled by g1. ! use a different scaling for f. v = min( safmax, max( safmin, f1 ) ) vv = one / v w = v * uu fs = f*vv f2 = abssq( fs ) h2 = f2*w**2 + g2 else ! otherwise use the same scaling for f and g. w = one fs = f*uu f2 = abssq( fs ) h2 = f2 + g2 end if if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1 / d c = ( f2*p )*w s = conjg( gs )*( fs*p ) r = ( fs*( h2*p ) )*u end if end if a = r return end subroutine stdlib${ii}$_crotg pure module subroutine stdlib${ii}$_zrotg( a, b, c, s ) use stdlib_blas_constants_dp !! The computation uses the formulas !! |x| = sqrt( Re(x)**2 + Im(x)**2 ) !! sgn(x) = x / |x| if x /= 0 !! = 1 if x = 0 !! c = |a| / sqrt(|a|**2 + |b|**2) !! s = sgn(a) * conjg(b) / sqrt(|a|**2 + |b|**2) !! When a and b are real and r /= 0, the formulas simplify to !! r = sgn(a)*sqrt(|a|**2 + |b|**2) !! c = a / r !! s = b / r !! the same as in DROTG when |a| > |b|. When |b| >= |a|, the !! sign of c and s will be different from those computed by DROTG !! if the signs of a and b are not the same. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scaling Constants ! Scalar Arguments real(dp), intent(out) :: c complex(dp), intent(inout) :: a complex(dp), intent(in) :: b complex(dp), intent(out) :: s ! ===================================================================== ! Local Scalars real(dp) :: d, f1, f2, g1, g2, h2, p, u, uu, v, vv, w complex(dp) :: f, fs, g, gs, r, t ! Intrinsic Functions intrinsic :: abs,aimag,conjg,max,min,real,sqrt ! Statement Functions real(dp) :: abssq ! Statement Function Definitions abssq( t ) = real( t,KIND=dp)**2 + aimag( t )**2 ! Executable Statements f = a g = b if( g == czero ) then c = one s = czero r = f else if( f == czero ) then c = zero g1 = max( abs(real(g,KIND=dp)), abs(aimag(g)) ) if( g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm g2 = abssq( g ) d = sqrt( g2 ) s = conjg( g ) / d r = d else ! use scaled algorithm u = min( safmax, max( safmin, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) d = sqrt( g2 ) s = conjg( gs ) / d r = d*u end if else f1 = max( abs(real(f,KIND=dp)), abs(aimag(f)) ) g1 = max( abs(real(g,KIND=dp)), abs(aimag(g)) ) if( f1 > rtmin .and. f1 < rtmax .and. g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm f2 = abssq( f ) g2 = abssq( g ) h2 = f2 + g2 if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1 / d c = f2*p s = conjg( g )*( f*p ) r = f*( h2*p ) else ! use scaled algorithm u = min( safmax, max( safmin, f1, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) if( f1*uu < rtmin ) then ! f is not well-scaled when scaled by g1. ! use a different scaling for f. v = min( safmax, max( safmin, f1 ) ) vv = one / v w = v * uu fs = f*vv f2 = abssq( fs ) h2 = f2*w**2 + g2 else ! otherwise use the same scaling for f and g. w = one fs = f*uu f2 = abssq( fs ) h2 = f2 + g2 end if if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1 / d c = ( f2*p )*w s = conjg( gs )*( fs*p ) r = ( fs*( h2*p ) )*u end if end if a = r return end subroutine stdlib${ii}$_zrotg #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$rotg( a, b, c, s ) use stdlib_blas_constants_${ck}$ !! The computation uses the formulas !! |x| = sqrt( Re(x)**2 + Im(x)**2 ) !! sgn(x) = x / |x| if x /= 0 !! = 1 if x = 0 !! c = |a| / sqrt(|a|**2 + |b|**2) !! s = sgn(a) * conjg(b) / sqrt(|a|**2 + |b|**2) !! When a and b are real and r /= 0, the formulas simplify to !! r = sgn(a)*sqrt(|a|**2 + |b|**2) !! c = a / r !! s = b / r !! the same as in DROTG when |a| > |b|. When |b| >= |a|, the !! sign of c and s will be different from those computed by DROTG !! if the signs of a and b are not the same. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scaling Constants ! Scalar Arguments real(${ck}$), intent(out) :: c complex(${ck}$), intent(inout) :: a complex(${ck}$), intent(in) :: b complex(${ck}$), intent(out) :: s ! ===================================================================== ! Local Scalars real(${ck}$) :: d, f1, f2, g1, g2, h2, p, u, uu, v, vv, w complex(${ck}$) :: f, fs, g, gs, r, t ! Intrinsic Functions intrinsic :: abs,aimag,conjg,max,min,real,sqrt ! Statement Functions real(${ck}$) :: abssq ! Statement Function Definitions abssq( t ) = real( t,KIND=${ck}$)**2 + aimag( t )**2 ! Executable Statements f = a g = b if( g == czero ) then c = one s = czero r = f else if( f == czero ) then c = zero g1 = max( abs(real(g,KIND=${ck}$)), abs(aimag(g)) ) if( g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm g2 = abssq( g ) d = sqrt( g2 ) s = conjg( g ) / d r = d else ! use scaled algorithm u = min( safmax, max( safmin, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) d = sqrt( g2 ) s = conjg( gs ) / d r = d*u end if else f1 = max( abs(real(f,KIND=${ck}$)), abs(aimag(f)) ) g1 = max( abs(real(g,KIND=${ck}$)), abs(aimag(g)) ) if( f1 > rtmin .and. f1 < rtmax .and. g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm f2 = abssq( f ) g2 = abssq( g ) h2 = f2 + g2 if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1 / d c = f2*p s = conjg( g )*( f*p ) r = f*( h2*p ) else ! use scaled algorithm u = min( safmax, max( safmin, f1, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) if( f1*uu < rtmin ) then ! f is not well-scaled when scaled by g1. ! use a different scaling for f. v = min( safmax, max( safmin, f1 ) ) vv = one / v w = v * uu fs = f*vv f2 = abssq( fs ) h2 = f2*w**2 + g2 else ! otherwise use the same scaling for f and g. w = one fs = f*uu f2 = abssq( fs ) h2 = f2 + g2 end if if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1 / d c = ( f2*p )*w s = conjg( gs )*( fs*p ) r = ( fs*( h2*p ) )*u end if end if a = r return end subroutine stdlib${ii}$_${ci}$rotg #:endif #:endfor pure module subroutine stdlib${ii}$_srotm(n,sx,incx,sy,incy,sparam) use stdlib_blas_constants_sp !! SROTM applies the modified Givens transformation, \(H\), to the 2-by-N matrix !! $$ \left[ \begin{array}{c}SX^T\\SY^T\\ \end{array} \right], $$ !! where \(^T\) indicates transpose. The elements of \(SX\) are in !! SX(LX+I*INCX), I = 0:N-1, where LX = 1 if INCX >= 0, else LX = (-INCX)*N, !! and similarly for SY using LY and INCY. !! With SPARAM(1)=SFLAG, \(H\) has one of the following forms: !! $$ H=\underbrace{\begin{bmatrix}SH_{11} & SH_{12}\\SH_{21} & SH_{22}\end{bmatrix}}_{SFLAG=-1}, !! \underbrace{\begin{bmatrix}1 & SH_{12}\\SH_{21} & 1\end{bmatrix}}_{SFLAG=0}, !! \underbrace{\begin{bmatrix}SH_{11} & 1\\-1 & SH_{22}\end{bmatrix}}_{SFLAG=1}, !! \underbrace{\begin{bmatrix}1 & 0\\0 & 1\end{bmatrix}}_{SFLAG=-2}. $$ !! See SROTMG for a description of data storage in SPARAM. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments real(sp), intent(in) :: sparam(5) real(sp), intent(inout) :: sx(*), sy(*) ! ===================================================================== ! Local Scalars real(sp) :: sflag, sh11, sh12, sh21, sh22, w, z integer(${ik}$) :: i, kx, ky, nsteps ! Data Statements sflag = sparam(1) if (n<=0 .or. (sflag+two==zero)) return if (incx==incy.and.incx>0) then nsteps = n*incx if (sflag= 0, else LX = (-INCX)*N, !! and similarly for DY using LY and INCY. !! With DPARAM(1)=DFLAG, \(H\) has one of the following forms: !! $$ H=\underbrace{\begin{bmatrix}DH_{11} & DH_{12}\\DH_{21} & DH_{22}\end{bmatrix}}_{DFLAG=-1}, !! \underbrace{\begin{bmatrix}1 & DH_{12}\\DH_{21} & 1\end{bmatrix}}_{DFLAG=0}, !! \underbrace{\begin{bmatrix}DH_{11} & 1\\-1 & DH_{22}\end{bmatrix}}_{DFLAG=1}, !! \underbrace{\begin{bmatrix}1 & 0\\0 & 1\end{bmatrix}}_{DFLAG=-2}. $$ !! See DROTMG for a description of data storage in DPARAM. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments real(dp), intent(in) :: dparam(5) real(dp), intent(inout) :: dx(*), dy(*) ! ===================================================================== ! Local Scalars real(dp) :: dflag, dh11, dh12, dh21, dh22, w, z integer(${ik}$) :: i, kx, ky, nsteps ! Data Statements dflag = dparam(1) if (n<=0 .or. (dflag+two==zero)) return if (incx==incy.and.incx>0) then nsteps = n*incx if (dflag= 0, else LX = (-INCX)*N, !! and similarly for DY using LY and INCY. !! With DPARAM(1)=DFLAG, \(H\) has one of the following forms: !! $$ H=\underbrace{\begin{bmatrix}DH_{11} & DH_{12}\\DH_{21} & DH_{22}\end{bmatrix}}_{DFLAG=-1}, !! \underbrace{\begin{bmatrix}1 & DH_{12}\\DH_{21} & 1\end{bmatrix}}_{DFLAG=0}, !! \underbrace{\begin{bmatrix}DH_{11} & 1\\-1 & DH_{22}\end{bmatrix}}_{DFLAG=1}, !! \underbrace{\begin{bmatrix}1 & 0\\0 & 1\end{bmatrix}}_{DFLAG=-2}. $$ !! See QROTMG for a description of data storage in DPARAM. ! -- reference blas level1 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n ! Array Arguments real(${rk}$), intent(in) :: dparam(5) real(${rk}$), intent(inout) :: dx(*), dy(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: dflag, dh11, dh12, dh21, dh22, w, z integer(${ik}$) :: i, kx, ky, nsteps ! Data Statements dflag = dparam(1) if (n<=0 .or. (dflag+two==zero)) return if (incx==incy.and.incx>0) then nsteps = n*incx if (dflagabs(sq2)) then sh21 = -sy1/sx1 sh12 = sp2/sp1 su = one - sh12*sh21 if (su>zero) then sflag = zero sd1 = sd1/su sd2 = sd2/su sx1 = sx1*su else ! this code path if here for safety. we do not expect this ! condition to ever hold except in edge cases with rounding ! errors. see doi: 10.1145/355841.355847 sflag = -one sh11 = zero sh12 = zero sh21 = zero sh22 = zero sd1 = zero sd2 = zero sx1 = zero end if else if (sq2=gamsq)) if (sflag==zero) then sh11 = one sh22 = one sflag = -one else sh21 = -one sh12 = one sflag = -one end if if (sd1<=rgamsq) then sd1 = sd1*gam**2 sx1 = sx1/gam sh11 = sh11/gam sh12 = sh12/gam else sd1 = sd1/gam**2 sx1 = sx1*gam sh11 = sh11*gam sh12 = sh12*gam end if enddo end if if (sd2/=zero) then do while ( (abs(sd2)<=rgamsq) .or. (abs(sd2)>=gamsq) ) if (sflag==zero) then sh11 = one sh22 = one sflag = -one else sh21 = -one sh12 = one sflag = -one end if if (abs(sd2)<=rgamsq) then sd2 = sd2*gam**2 sh21 = sh21/gam sh22 = sh22/gam else sd2 = sd2/gam**2 sh21 = sh21*gam sh22 = sh22*gam end if end do end if end if if (sflagabs(dq2)) then dh21 = -dy1/dx1 dh12 = dp2/dp1 du = one - dh12*dh21 if (du>zero) then dflag = zero dd1 = dd1/du dd2 = dd2/du dx1 = dx1*du else ! this code path if here for safety. we do not expect this ! condition to ever hold except in edge cases with rounding ! errors. see doi: 10.1145/355841.355847 dflag = -one dh11 = zero dh12 = zero dh21 = zero dh22 = zero dd1 = zero dd2 = zero dx1 = zero end if else if (dq2=gamsq)) if (dflag==zero) then dh11 = one dh22 = one dflag = -one else dh21 = -one dh12 = one dflag = -one end if if (dd1<=rgamsq) then dd1 = dd1*gam**2 dx1 = dx1/gam dh11 = dh11/gam dh12 = dh12/gam else dd1 = dd1/gam**2 dx1 = dx1*gam dh11 = dh11*gam dh12 = dh12*gam end if enddo end if if (dd2/=zero) then do while ( (abs(dd2)<=rgamsq) .or. (abs(dd2)>=gamsq) ) if (dflag==zero) then dh11 = one dh22 = one dflag = -one else dh21 = -one dh12 = one dflag = -one end if if (abs(dd2)<=rgamsq) then dd2 = dd2*gam**2 dh21 = dh21/gam dh22 = dh22/gam else dd2 = dd2/gam**2 dh21 = dh21*gam dh22 = dh22*gam end if end do end if end if if (dflagabs(dq2)) then dh21 = -dy1/dx1 dh12 = dp2/dp1 du = one - dh12*dh21 if (du>zero) then dflag = zero dd1 = dd1/du dd2 = dd2/du dx1 = dx1*du else ! this code path if here for safety. we do not expect this ! condition to ever hold except in edge cases with rounding ! errors. see doi: 10.1145/355841.355847 dflag = -one dh11 = zero dh12 = zero dh21 = zero dh22 = zero dd1 = zero dd2 = zero dx1 = zero end if else if (dq2=gamsq)) if (dflag==zero) then dh11 = one dh22 = one dflag = -one else dh21 = -one dh12 = one dflag = -one end if if (dd1<=rgamsq) then dd1 = dd1*gam**2 dx1 = dx1/gam dh11 = dh11/gam dh12 = dh12/gam else dd1 = dd1/gam**2 dx1 = dx1*gam dh11 = dh11*gam dh12 = dh12*gam end if enddo end if if (dd2/=zero) then do while ( (abs(dd2)<=rgamsq) .or. (abs(dd2)>=gamsq) ) if (dflag==zero) then dh11 = one dh22 = one dflag = -one else dh21 = -one dh12 = one dflag = -one end if if (abs(dd2)<=rgamsq) then dd2 = dd2*gam**2 dh21 = dh21/gam dh22 = dh22/gam else dd2 = dd2/gam**2 dh21 = dh21*gam dh22 = dh22*gam end if end do end if end if if (dflag |b|. When |b| >= |a|, the !! sign of c and s will be different from those computed by SROTG !! if the signs of a and b are not the same. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine crotg( a, b, c, s ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(out) :: c complex(sp), intent(inout) :: a complex(sp), intent(in) :: b complex(sp), intent(out) :: s end subroutine crotg #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_crotg #:endif #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine drotg( a, b, c, s ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(inout) :: a,b real(dp), intent(out) :: c,s end subroutine drotg #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_drotg #:endif #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine srotg( a, b, c, s ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(inout) :: a,b real(sp), intent(out) :: c,s end subroutine srotg #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_srotg #:endif #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine zrotg( a, b, c, s ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(out) :: c complex(dp), intent(inout) :: a complex(dp), intent(in) :: b complex(dp), intent(out) :: s end subroutine zrotg #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_zrotg #:endif #endif #:endfor #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib_${ri}$rotg #:endif #:endfor end interface rotg interface rotm !! ROTM applies the modified Givens transformation, \(H\), to the 2-by-N matrix !! $$ \left[ \begin{array}{c}DX^T\\DY^T\\ \end{array} \right], $$ !! where \(^T\) indicates transpose. The elements of \(DX\) are in !! DX(LX+I*INCX), I = 0:N-1, where LX = 1 if INCX >= 0, else LX = (-INCX)*N, !! and similarly for DY using LY and INCY. !! With DPARAM(1)=DFLAG, \(H\) has one of the following forms: !! $$ H=\underbrace{\begin{bmatrix}DH_{11} & DH_{12}\\DH_{21} & DH_{22}\end{bmatrix}}_{DFLAG=-1}, !! \underbrace{\begin{bmatrix}1 & DH_{12}\\DH_{21} & 1\end{bmatrix}}_{DFLAG=0}, !! \underbrace{\begin{bmatrix}DH_{11} & 1\\-1 & DH_{22}\end{bmatrix}}_{DFLAG=1}, !! \underbrace{\begin{bmatrix}1 & 0\\0 & 1\end{bmatrix}}_{DFLAG=-2}. $$ !! See ROTMG for a description of data storage in DPARAM. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine drotm(n,dx,incx,dy,incy,dparam) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(dp), intent(in) :: dparam(5) real(dp), intent(inout) :: dx(*),dy(*) end subroutine drotm #else module procedure stdlib${ii}$_drotm #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine srotm(n,sx,incx,sy,incy,sparam) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(sp), intent(in) :: sparam(5) real(sp), intent(inout) :: sx(*),sy(*) end subroutine srotm #else module procedure stdlib${ii}$_srotm #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$rotm #:endif #:endfor #:endfor end interface rotm interface rotmg !! ROTMG Constructs the modified Givens transformation matrix \(H\) which zeros the !! second component of the 2-vector !! $$ \left[ {\sqrt{DD_1}\cdot DX_1,\sqrt{DD_2}\cdot DY_2} \right]^T. $$ !! With DPARAM(1)=DFLAG, \(H\) has one of the following forms: !! $$ H=\underbrace{\begin{bmatrix}DH_{11} & DH_{12}\\DH_{21} & DH_{22}\end{bmatrix}}_{DFLAG=-1}, !! \underbrace{\begin{bmatrix}1 & DH_{12}\\DH_{21} & 1\end{bmatrix}}_{DFLAG=0}, !! \underbrace{\begin{bmatrix}DH_{11} & 1\\-1 & DH_{22}\end{bmatrix}}_{DFLAG=1}, !! \underbrace{\begin{bmatrix}1 & 0\\0 & 1\end{bmatrix}}_{DFLAG=-2}. $$ !! Locations 2-4 of DPARAM contain DH11, DH21, DH12 and DH22 respectively. !! (Values of 1.0, -1.0, or 0.0 implied by the value of DPARAM(1) are not stored in DPARAM.) !! The values of parameters GAMSQ and RGAMSQ may be inexact. This is OK as they are only !! used for testing the size of DD1 and DD2. All actual scaling of data is done using GAM. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine drotmg(dd1,dd2,dx1,dy1,dparam) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(inout) :: dd1,dd2,dx1 real(dp), intent(in) :: dy1 real(dp), intent(out) :: dparam(5) end subroutine drotmg #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_drotmg #:endif #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine srotmg(sd1,sd2,sx1,sy1,sparam) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(inout) :: sd1,sd2,sx1 real(sp), intent(in) :: sy1 real(sp), intent(out) :: sparam(5) end subroutine srotmg #:if not 'ilp64' in ik #else module procedure stdlib_srotmg #:endif #endif #:endfor #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib_${ri}$rotmg #:endif #:endfor end interface rotmg interface sbmv !! SBMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric band matrix, with k super-diagonals. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dsbmv(uplo,n,k,alpha,a,lda,x,incx,beta,y,incy) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta,a(lda,*),x(*) integer(${ik}$), intent(in) :: incx,incy,k,lda,n character, intent(in) :: uplo real(dp), intent(inout) :: y(*) end subroutine dsbmv #else module procedure stdlib${ii}$_dsbmv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ssbmv(uplo,n,k,alpha,a,lda,x,incx,beta,y,incy) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta,a(lda,*),x(*) integer(${ik}$), intent(in) :: incx,incy,k,lda,n character, intent(in) :: uplo real(sp), intent(inout) :: y(*) end subroutine ssbmv #else module procedure stdlib${ii}$_ssbmv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sbmv #:endif #:endfor #:endfor end interface sbmv interface scal !! SCAL scales a vector by a constant. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine cscal(n,ca,cx,incx) import sp,dp,qp,${ik}$,lk implicit none complex(sp), intent(in) :: ca integer(${ik}$), intent(in) :: incx,n complex(sp), intent(inout) :: cx(*) end subroutine cscal #else module procedure stdlib${ii}$_cscal #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dscal(n,da,dx,incx) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: da integer(${ik}$), intent(in) :: incx,n real(dp), intent(inout) :: dx(*) end subroutine dscal #else module procedure stdlib${ii}$_dscal #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine sscal(n,sa,sx,incx) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: sa integer(${ik}$), intent(in) :: incx,n real(sp), intent(inout) :: sx(*) end subroutine sscal #else module procedure stdlib${ii}$_sscal #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine zscal(n,za,zx,incx) import sp,dp,qp,${ik}$,lk implicit none complex(dp), intent(in) :: za integer(${ik}$), intent(in) :: incx,n complex(dp), intent(inout) :: zx(*) end subroutine zscal #else module procedure stdlib${ii}$_zscal #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$scal #:endif #:endfor #:endfor end interface scal interface sdot !! Compute the inner product of two vectors with extended !! precision accumulation and result. !! Returns D.P. dot product accumulated in D.P., for S.P. SX and SY !! SDOT = sum for I = 0 to N-1 of SX(LX+I*INCX) * SY(LY+I*INCY), !! where LX = 1 if INCX >= 0, else LX = 1+(1-N)*INCX, and LY is !! defined in a similar way using INCY. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #:if WITH_QP !! Provide a unique interface to accumulate double precision reals !! into the highest available precision. module procedure stdlib${ii}$_qsdot #:elif WITH_XDP !! Provide a unique interface to accumulate double precision reals !! into the highest available precision. module procedure stdlib${ii}$_xsdot #:endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure real(dp) function dsdot(n,sx,incx,sy,incy) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(sp), intent(in) :: sx(*),sy(*) end function dsdot #else module procedure stdlib${ii}$_dsdot #endif #:endfor end interface sdot interface spmv !! SPMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix, supplied in packed form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dspmv(uplo,n,alpha,ap,x,incx,beta,y,incy) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta,ap(*),x(*) integer(${ik}$), intent(in) :: incx,incy,n character, intent(in) :: uplo real(dp), intent(inout) :: y(*) end subroutine dspmv #else module procedure stdlib${ii}$_dspmv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine sspmv(uplo,n,alpha,ap,x,incx,beta,y,incy) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta,ap(*),x(*) integer(${ik}$), intent(in) :: incx,incy,n character, intent(in) :: uplo real(sp), intent(inout) :: y(*) end subroutine sspmv #else module procedure stdlib${ii}$_sspmv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spmv #:endif #:endfor #:endfor end interface spmv interface spr !! SPR performs the symmetric rank 1 operation !! A := alpha*x*x**T + A, !! where alpha is a real scalar, x is an n element vector and A is an !! n by n symmetric matrix, supplied in packed form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dspr(uplo,n,alpha,x,incx,ap) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,x(*) integer(${ik}$), intent(in) :: incx,n character, intent(in) :: uplo real(dp), intent(inout) :: ap(*) end subroutine dspr #else module procedure stdlib${ii}$_dspr #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine sspr(uplo,n,alpha,x,incx,ap) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,x(*) integer(${ik}$), intent(in) :: incx,n character, intent(in) :: uplo real(sp), intent(inout) :: ap(*) end subroutine sspr #else module procedure stdlib${ii}$_sspr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spr #:endif #:endfor #:endfor end interface spr interface spr2 !! SPR2 performs the symmetric rank 2 operation !! A := alpha*x*y**T + alpha*y*x**T + A, !! where alpha is a scalar, x and y are n element vectors and A is an !! n by n symmetric matrix, supplied in packed form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dspr2(uplo,n,alpha,x,incx,y,incy,ap) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,x(*),y(*) integer(${ik}$), intent(in) :: incx,incy,n character, intent(in) :: uplo real(dp), intent(inout) :: ap(*) end subroutine dspr2 #else module procedure stdlib${ii}$_dspr2 #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine sspr2(uplo,n,alpha,x,incx,y,incy,ap) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,x(*),y(*) integer(${ik}$), intent(in) :: incx,incy,n character, intent(in) :: uplo real(sp), intent(inout) :: ap(*) end subroutine sspr2 #else module procedure stdlib${ii}$_sspr2 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spr2 #:endif #:endfor #:endfor end interface spr2 interface srot !! SROT applies a plane rotation, where the cos and sin (c and s) are real !! and the vectors cx and cy are complex. !! jack dongarra, linpack, 3/11/78. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine csrot( n, cx, incx, cy, incy, c, s ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(sp), intent(in) :: c,s complex(sp), intent(inout) :: cx(*),cy(*) end subroutine csrot #else module procedure stdlib${ii}$_csrot #endif #:endfor end interface srot interface sscal !! SSCAL scales a complex vector by a real constant. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine csscal(n,sa,cx,incx) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: sa integer(${ik}$), intent(in) :: incx,n complex(sp), intent(inout) :: cx(*) end subroutine csscal #else module procedure stdlib${ii}$_csscal #endif #:endfor end interface sscal interface swap !! SWAP interchanges two vectors. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine cswap(n,cx,incx,cy,incy) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n complex(sp), intent(inout) :: cx(*),cy(*) end subroutine cswap #else module procedure stdlib${ii}$_cswap #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dswap(n,dx,incx,dy,incy) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(dp), intent(inout) :: dx(*),dy(*) end subroutine dswap #else module procedure stdlib${ii}$_dswap #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine sswap(n,sx,incx,sy,incy) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(sp), intent(inout) :: sx(*),sy(*) end subroutine sswap #else module procedure stdlib${ii}$_sswap #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine zswap(n,zx,incx,zy,incy) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n complex(dp), intent(inout) :: zx(*),zy(*) end subroutine zswap #else module procedure stdlib${ii}$_zswap #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$swap #:endif #:endfor #:endfor end interface swap interface symm !! SYMM performs one of the matrix-matrix operations !! C := alpha*A*B + beta*C, !! or !! C := alpha*B*A + beta*C, !! where alpha and beta are scalars, A is a symmetric matrix and B and !! C are m by n matrices. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine csymm(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none complex(sp), intent(in) :: alpha,beta,a(lda,*),b(ldb,*) integer(${ik}$), intent(in) :: lda,ldb,ldc,m,n character, intent(in) :: side,uplo complex(sp), intent(inout) :: c(ldc,*) end subroutine csymm #else module procedure stdlib${ii}$_csymm #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dsymm(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta,a(lda,*),b(ldb,*) integer(${ik}$), intent(in) :: lda,ldb,ldc,m,n character, intent(in) :: side,uplo real(dp), intent(inout) :: c(ldc,*) end subroutine dsymm #else module procedure stdlib${ii}$_dsymm #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ssymm(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta,a(lda,*),b(ldb,*) integer(${ik}$), intent(in) :: lda,ldb,ldc,m,n character, intent(in) :: side,uplo real(sp), intent(inout) :: c(ldc,*) end subroutine ssymm #else module procedure stdlib${ii}$_ssymm #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine zsymm(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none complex(dp), intent(in) :: alpha,beta,a(lda,*),b(ldb,*) integer(${ik}$), intent(in) :: lda,ldb,ldc,m,n character, intent(in) :: side,uplo complex(dp), intent(inout) :: c(ldc,*) end subroutine zsymm #else module procedure stdlib${ii}$_zsymm #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$symm #:endif #:endfor #:endfor end interface symm interface symv !! SYMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dsymv(uplo,n,alpha,a,lda,x,incx,beta,y,incy) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta,a(lda,*),x(*) integer(${ik}$), intent(in) :: incx,incy,lda,n character, intent(in) :: uplo real(dp), intent(inout) :: y(*) end subroutine dsymv #else module procedure stdlib${ii}$_dsymv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ssymv(uplo,n,alpha,a,lda,x,incx,beta,y,incy) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta,a(lda,*),x(*) integer(${ik}$), intent(in) :: incx,incy,lda,n character, intent(in) :: uplo real(sp), intent(inout) :: y(*) end subroutine ssymv #else module procedure stdlib${ii}$_ssymv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$symv #:endif #:endfor #:endfor end interface symv interface syr !! SYR performs the symmetric rank 1 operation !! A := alpha*x*x**T + A, !! where alpha is a real scalar, x is an n element vector and A is an !! n by n symmetric matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dsyr(uplo,n,alpha,x,incx,a,lda) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,x(*) integer(${ik}$), intent(in) :: incx,lda,n character, intent(in) :: uplo real(dp), intent(inout) :: a(lda,*) end subroutine dsyr #else module procedure stdlib${ii}$_dsyr #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ssyr(uplo,n,alpha,x,incx,a,lda) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,x(*) integer(${ik}$), intent(in) :: incx,lda,n character, intent(in) :: uplo real(sp), intent(inout) :: a(lda,*) end subroutine ssyr #else module procedure stdlib${ii}$_ssyr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syr #:endif #:endfor #:endfor end interface syr interface syr2 !! SYR2 performs the symmetric rank 2 operation !! A := alpha*x*y**T + alpha*y*x**T + A, !! where alpha is a scalar, x and y are n element vectors and A is an n !! by n symmetric matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dsyr2(uplo,n,alpha,x,incx,y,incy,a,lda) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,x(*),y(*) integer(${ik}$), intent(in) :: incx,incy,lda,n character, intent(in) :: uplo real(dp), intent(inout) :: a(lda,*) end subroutine dsyr2 #else module procedure stdlib${ii}$_dsyr2 #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ssyr2(uplo,n,alpha,x,incx,y,incy,a,lda) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,x(*),y(*) integer(${ik}$), intent(in) :: incx,incy,lda,n character, intent(in) :: uplo real(sp), intent(inout) :: a(lda,*) end subroutine ssyr2 #else module procedure stdlib${ii}$_ssyr2 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syr2 #:endif #:endfor #:endfor end interface syr2 interface syr2k !! SYR2K performs one of the symmetric rank 2k operations !! C := alpha*A*B**T + alpha*B*A**T + beta*C, !! or !! C := alpha*A**T*B + alpha*B**T*A + beta*C, !! where alpha and beta are scalars, C is an n by n symmetric matrix !! and A and B are n by k matrices in the first case and k by n !! matrices in the second case. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine csyr2k(uplo,trans,n,k,alpha,a,lda,b,ldb,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none complex(sp), intent(in) :: alpha,beta,a(lda,*),b(ldb,*) integer(${ik}$), intent(in) :: k,lda,ldb,ldc,n character, intent(in) :: trans,uplo complex(sp), intent(inout) :: c(ldc,*) end subroutine csyr2k #else module procedure stdlib${ii}$_csyr2k #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dsyr2k(uplo,trans,n,k,alpha,a,lda,b,ldb,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta,a(lda,*),b(ldb,*) integer(${ik}$), intent(in) :: k,lda,ldb,ldc,n character, intent(in) :: trans,uplo real(dp), intent(inout) :: c(ldc,*) end subroutine dsyr2k #else module procedure stdlib${ii}$_dsyr2k #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ssyr2k(uplo,trans,n,k,alpha,a,lda,b,ldb,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta,a(lda,*),b(ldb,*) integer(${ik}$), intent(in) :: k,lda,ldb,ldc,n character, intent(in) :: trans,uplo real(sp), intent(inout) :: c(ldc,*) end subroutine ssyr2k #else module procedure stdlib${ii}$_ssyr2k #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine zsyr2k(uplo,trans,n,k,alpha,a,lda,b,ldb,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none complex(dp), intent(in) :: alpha,beta,a(lda,*),b(ldb,*) integer(${ik}$), intent(in) :: k,lda,ldb,ldc,n character, intent(in) :: trans,uplo complex(dp), intent(inout) :: c(ldc,*) end subroutine zsyr2k #else module procedure stdlib${ii}$_zsyr2k #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syr2k #:endif #:endfor #:endfor end interface syr2k interface syrk !! SYRK performs one of the symmetric rank k operations !! C := alpha*A*A**T + beta*C, !! or !! C := alpha*A**T*A + beta*C, !! where alpha and beta are scalars, C is an n by n symmetric matrix !! and A is an n by k matrix in the first case and a k by n matrix !! in the second case. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine csyrk(uplo,trans,n,k,alpha,a,lda,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none complex(sp), intent(in) :: alpha,beta,a(lda,*) integer(${ik}$), intent(in) :: k,lda,ldc,n character, intent(in) :: trans,uplo complex(sp), intent(inout) :: c(ldc,*) end subroutine csyrk #else module procedure stdlib${ii}$_csyrk #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dsyrk(uplo,trans,n,k,alpha,a,lda,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta,a(lda,*) integer(${ik}$), intent(in) :: k,lda,ldc,n character, intent(in) :: trans,uplo real(dp), intent(inout) :: c(ldc,*) end subroutine dsyrk #else module procedure stdlib${ii}$_dsyrk #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ssyrk(uplo,trans,n,k,alpha,a,lda,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta,a(lda,*) integer(${ik}$), intent(in) :: k,lda,ldc,n character, intent(in) :: trans,uplo real(sp), intent(inout) :: c(ldc,*) end subroutine ssyrk #else module procedure stdlib${ii}$_ssyrk #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine zsyrk(uplo,trans,n,k,alpha,a,lda,beta,c,ldc) import sp,dp,qp,${ik}$,lk implicit none complex(dp), intent(in) :: alpha,beta,a(lda,*) integer(${ik}$), intent(in) :: k,lda,ldc,n character, intent(in) :: trans,uplo complex(dp), intent(inout) :: c(ldc,*) end subroutine zsyrk #else module procedure stdlib${ii}$_zsyrk #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syrk #:endif #:endfor #:endfor end interface syrk interface tbmv !! TBMV performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, or x := A**H*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular band matrix, with ( k + 1 ) diagonals. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ctbmv(uplo,trans,diag,n,k,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k,lda,n character, intent(in) :: diag,trans,uplo complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: x(*) end subroutine ctbmv #else module procedure stdlib${ii}$_ctbmv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dtbmv(uplo,trans,diag,n,k,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k,lda,n character, intent(in) :: diag,trans,uplo real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: x(*) end subroutine dtbmv #else module procedure stdlib${ii}$_dtbmv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine stbmv(uplo,trans,diag,n,k,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k,lda,n character, intent(in) :: diag,trans,uplo real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: x(*) end subroutine stbmv #else module procedure stdlib${ii}$_stbmv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ztbmv(uplo,trans,diag,n,k,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k,lda,n character, intent(in) :: diag,trans,uplo complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: x(*) end subroutine ztbmv #else module procedure stdlib${ii}$_ztbmv #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tbmv #:endif #:endfor #:endfor end interface tbmv interface tbsv !! TBSV solves one of the systems of equations !! A*x = b, or A**T*x = b, or A**H*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular band matrix, with ( k + 1 ) !! diagonals. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ctbsv(uplo,trans,diag,n,k,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k,lda,n character, intent(in) :: diag,trans,uplo complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: x(*) end subroutine ctbsv #else module procedure stdlib${ii}$_ctbsv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dtbsv(uplo,trans,diag,n,k,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k,lda,n character, intent(in) :: diag,trans,uplo real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: x(*) end subroutine dtbsv #else module procedure stdlib${ii}$_dtbsv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine stbsv(uplo,trans,diag,n,k,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k,lda,n character, intent(in) :: diag,trans,uplo real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: x(*) end subroutine stbsv #else module procedure stdlib${ii}$_stbsv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ztbsv(uplo,trans,diag,n,k,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k,lda,n character, intent(in) :: diag,trans,uplo complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: x(*) end subroutine ztbsv #else module procedure stdlib${ii}$_ztbsv #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tbsv #:endif #:endfor #:endfor end interface tbsv interface tpmv !! TPMV performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, or x := A**H*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular matrix, supplied in packed form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ctpmv(uplo,trans,diag,n,ap,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n character, intent(in) :: diag,trans,uplo complex(sp), intent(in) :: ap(*) complex(sp), intent(inout) :: x(*) end subroutine ctpmv #else module procedure stdlib${ii}$_ctpmv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dtpmv(uplo,trans,diag,n,ap,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n character, intent(in) :: diag,trans,uplo real(dp), intent(in) :: ap(*) real(dp), intent(inout) :: x(*) end subroutine dtpmv #else module procedure stdlib${ii}$_dtpmv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine stpmv(uplo,trans,diag,n,ap,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n character, intent(in) :: diag,trans,uplo real(sp), intent(in) :: ap(*) real(sp), intent(inout) :: x(*) end subroutine stpmv #else module procedure stdlib${ii}$_stpmv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ztpmv(uplo,trans,diag,n,ap,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n character, intent(in) :: diag,trans,uplo complex(dp), intent(in) :: ap(*) complex(dp), intent(inout) :: x(*) end subroutine ztpmv #else module procedure stdlib${ii}$_ztpmv #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpmv #:endif #:endfor #:endfor end interface tpmv interface tpsv !! TPSV solves one of the systems of equations !! A*x = b, or A**T*x = b, or A**H*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular matrix, supplied in packed form. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ctpsv(uplo,trans,diag,n,ap,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n character, intent(in) :: diag,trans,uplo complex(sp), intent(in) :: ap(*) complex(sp), intent(inout) :: x(*) end subroutine ctpsv #else module procedure stdlib${ii}$_ctpsv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dtpsv(uplo,trans,diag,n,ap,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n character, intent(in) :: diag,trans,uplo real(dp), intent(in) :: ap(*) real(dp), intent(inout) :: x(*) end subroutine dtpsv #else module procedure stdlib${ii}$_dtpsv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine stpsv(uplo,trans,diag,n,ap,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n character, intent(in) :: diag,trans,uplo real(sp), intent(in) :: ap(*) real(sp), intent(inout) :: x(*) end subroutine stpsv #else module procedure stdlib${ii}$_stpsv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ztpsv(uplo,trans,diag,n,ap,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n character, intent(in) :: diag,trans,uplo complex(dp), intent(in) :: ap(*) complex(dp), intent(inout) :: x(*) end subroutine ztpsv #else module procedure stdlib${ii}$_ztpsv #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpsv #:endif #:endfor #:endfor end interface tpsv interface trmm !! TRMM performs one of the matrix-matrix operations !! B := alpha*op( A )*B, or B := alpha*B*op( A ) !! where alpha is a scalar, B is an m by n matrix, A is a unit, or !! non-unit, upper or lower triangular matrix and op( A ) is one of !! op( A ) = A or op( A ) = A**T or op( A ) = A**H. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ctrmm(side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb) import sp,dp,qp,${ik}$,lk implicit none complex(sp), intent(in) :: alpha,a(lda,*) integer(${ik}$), intent(in) :: lda,ldb,m,n character, intent(in) :: diag,side,transa,uplo complex(sp), intent(inout) :: b(ldb,*) end subroutine ctrmm #else module procedure stdlib${ii}$_ctrmm #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dtrmm(side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,a(lda,*) integer(${ik}$), intent(in) :: lda,ldb,m,n character, intent(in) :: diag,side,transa,uplo real(dp), intent(inout) :: b(ldb,*) end subroutine dtrmm #else module procedure stdlib${ii}$_dtrmm #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine strmm(side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,a(lda,*) integer(${ik}$), intent(in) :: lda,ldb,m,n character, intent(in) :: diag,side,transa,uplo real(sp), intent(inout) :: b(ldb,*) end subroutine strmm #else module procedure stdlib${ii}$_strmm #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ztrmm(side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb) import sp,dp,qp,${ik}$,lk implicit none complex(dp), intent(in) :: alpha,a(lda,*) integer(${ik}$), intent(in) :: lda,ldb,m,n character, intent(in) :: diag,side,transa,uplo complex(dp), intent(inout) :: b(ldb,*) end subroutine ztrmm #else module procedure stdlib${ii}$_ztrmm #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trmm #:endif #:endfor #:endfor end interface trmm interface trmv !! TRMV performs one of the matrix-vector operations !! x := A*x, or x := A**T*x, or x := A**H*x, !! where x is an n element vector and A is an n by n unit, or non-unit, !! upper or lower triangular matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ctrmv(uplo,trans,diag,n,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,lda,n character, intent(in) :: diag,trans,uplo complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: x(*) end subroutine ctrmv #else module procedure stdlib${ii}$_ctrmv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dtrmv(uplo,trans,diag,n,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,lda,n character, intent(in) :: diag,trans,uplo real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: x(*) end subroutine dtrmv #else module procedure stdlib${ii}$_dtrmv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine strmv(uplo,trans,diag,n,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,lda,n character, intent(in) :: diag,trans,uplo real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: x(*) end subroutine strmv #else module procedure stdlib${ii}$_strmv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ztrmv(uplo,trans,diag,n,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,lda,n character, intent(in) :: diag,trans,uplo complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: x(*) end subroutine ztrmv #else module procedure stdlib${ii}$_ztrmv #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trmv #:endif #:endfor #:endfor end interface trmv interface trsm !! TRSM solves one of the matrix equations !! op( A )*X = alpha*B, or X*op( A ) = alpha*B, !! where alpha is a scalar, X and B are m by n matrices, A is a unit, or !! non-unit, upper or lower triangular matrix and op( A ) is one of !! op( A ) = A or op( A ) = A**T or op( A ) = A**H. !! The matrix X is overwritten on B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ctrsm(side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb) import sp,dp,qp,${ik}$,lk implicit none complex(sp), intent(in) :: alpha,a(lda,*) integer(${ik}$), intent(in) :: lda,ldb,m,n character, intent(in) :: diag,side,transa,uplo complex(sp), intent(inout) :: b(ldb,*) end subroutine ctrsm #else module procedure stdlib${ii}$_ctrsm #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dtrsm(side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,a(lda,*) integer(${ik}$), intent(in) :: lda,ldb,m,n character, intent(in) :: diag,side,transa,uplo real(dp), intent(inout) :: b(ldb,*) end subroutine dtrsm #else module procedure stdlib${ii}$_dtrsm #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine strsm(side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,a(lda,*) integer(${ik}$), intent(in) :: lda,ldb,m,n character, intent(in) :: diag,side,transa,uplo real(sp), intent(inout) :: b(ldb,*) end subroutine strsm #else module procedure stdlib${ii}$_strsm #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ztrsm(side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb) import sp,dp,qp,${ik}$,lk implicit none complex(dp), intent(in) :: alpha,a(lda,*) integer(${ik}$), intent(in) :: lda,ldb,m,n character, intent(in) :: diag,side,transa,uplo complex(dp), intent(inout) :: b(ldb,*) end subroutine ztrsm #else module procedure stdlib${ii}$_ztrsm #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trsm #:endif #:endfor #:endfor end interface trsm interface trsv !! TRSV solves one of the systems of equations !! A*x = b, or A**T*x = b, or A**H*x = b, !! where b and x are n element vectors and A is an n by n unit, or !! non-unit, upper or lower triangular matrix. !! No test for singularity or near-singularity is included in this !! routine. Such tests must be performed before calling this routine. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ctrsv(uplo,trans,diag,n,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,lda,n character, intent(in) :: diag,trans,uplo complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: x(*) end subroutine ctrsv #else module procedure stdlib${ii}$_ctrsv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine dtrsv(uplo,trans,diag,n,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,lda,n character, intent(in) :: diag,trans,uplo real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: x(*) end subroutine dtrsv #else module procedure stdlib${ii}$_dtrsv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine strsv(uplo,trans,diag,n,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,lda,n character, intent(in) :: diag,trans,uplo real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: x(*) end subroutine strsv #else module procedure stdlib${ii}$_strsv #endif #ifdef STDLIB_EXTERNAL_BLAS${ii}$ pure subroutine ztrsv(uplo,trans,diag,n,a,lda,x,incx) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,lda,n character, intent(in) :: diag,trans,uplo complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: x(*) end subroutine ztrsv #else module procedure stdlib${ii}$_ztrsv #endif #:for rk,rt,ri in RC_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trsv #:endif #:endfor #:endfor end interface trsv end module stdlib_linalg_blas fortran-lang-stdlib-0ede301/src/blas/stdlib_blas_level3_sym.fypp0000664000175000017500000034005215135654166025226 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_blas) stdlib_blas_level3_sym implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_ssyrk(uplo,trans,n,k,alpha,a,lda,beta,c,ldc) use stdlib_blas_constants_sp !! SSYRK performs one of the symmetric rank k operations !! C := alpha*A*A**T + beta*C, !! or !! C := alpha*A**T*A + beta*C, !! where alpha and beta are scalars, C is an n by n symmetric matrix !! and A is an n by k matrix in the first case and a k by n matrix !! in the second case. ! -- reference blas level3 routine -- ! -- reference blas is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: k, lda, ldc, n character, intent(in) :: trans, uplo ! Array Arguments real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: c(ldc,*) ! ===================================================================== ! Intrinsic Functions intrinsic :: max ! Local Scalars real(sp) :: temp integer(${ik}$) :: i, info, j, l, nrowa logical(lk) :: upper ! test the input parameters. if (stdlib_lsame(trans,'N')) then nrowa = n else nrowa = k end if upper = stdlib_lsame(uplo,'U') info = 0 if ((.not.upper) .and. (.not.stdlib_lsame(uplo,'L'))) then info = 1 else if ((.not.stdlib_lsame(trans,'N')) .and.(.not.stdlib_lsame(trans,'T')) .and.(& .not.stdlib_lsame(trans,'C'))) then info = 2 else if (n<0) then info = 3 else if (k<0) then info = 4 else if (lda Version: experimental !> !> Format strings with edit descriptors for each type and kind !> ([Specification](../page/specs/stdlib_io.html)) character(*), parameter :: & !> Format string for integers FMT_INT = '(i0)', & !> Format string for single precision real numbers FMT_REAL_SP = '(es15.8e2)', & !> Format string for souble precision real numbers FMT_REAL_DP = '(es24.16e3)', & !> Format string for extended double precision real numbers FMT_REAL_XDP = '(es26.18e3)', & !> Format string for quadruple precision real numbers FMT_REAL_QP = '(es44.35e4)', & !> Format string for single precision complex numbers FMT_COMPLEX_SP = '(es15.08e2,1x,es15.08e2)', & !> Format string for double precision complex numbers FMT_COMPLEX_DP = '(es24.16e3,1x,es24.16e3)', & !> Format string for extended double precision complex numbers FMT_COMPLEX_XDP = '(es26.18e3,1x,es26.18e3)', & !> Format string for quadruple precision complex numbers FMT_COMPLEX_QP = '(es44.35e4,1x,es44.35e4)' end module stdlib_io_aux fortran-lang-stdlib-0ede301/src/core/stdlib_error.fypp0000664000175000017500000005464415135654166023314 0ustar alastairalastair#:include "common.fypp" #:set KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES + CMPLX_KINDS_TYPES module stdlib_error !! Provides support for catching and handling errors !! ([Specification](../page/specs/stdlib_error.html)) use, intrinsic :: iso_fortran_env, only: stderr => error_unit, ilp => int32 use stdlib_optval, only: optval use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp, lk implicit none private interface ! f{08,18}estop.f90 module subroutine error_stop(msg, code) !! version: experimental !! !! Provides a call to `error stop` and allows the user to specify a code and message !! ([Specification](..//page/specs/stdlib_error.html#description_1)) character(*), intent(in) :: msg integer, intent(in), optional :: code end subroutine error_stop end interface public :: check, error_stop !> Version: experimental !> !> A fixed-storage state variable for error handling of linear algebra routines public :: state_type !> Version: experimental !> !> Interfaces for comparison operators of error states with integer flags public :: operator(==),operator(/=) public :: operator(<),operator(<=) public :: operator(>),operator(>=) !> Base state return types for integer(ilp),parameter,public :: STDLIB_SUCCESS = 0_ilp integer(ilp),parameter,public :: STDLIB_VALUE_ERROR = -1_ilp integer(ilp),parameter,public :: STDLIB_LINALG_ERROR = -2_ilp integer(ilp),parameter,public :: STDLIB_INTERNAL_ERROR = -3_ilp integer(ilp),parameter,public :: STDLIB_IO_ERROR = -4_ilp integer(ilp),parameter,public :: STDLIB_FS_ERROR = -5_ilp !> Use fixed-size character storage for performance integer(ilp),parameter :: MSG_LENGTH = 512_ilp integer(ilp),parameter :: NAME_LENGTH = 32_ilp !> `state_type` defines a general state return type for a !> stdlib routine. State contains a status flag, a comment, and a !> procedure specifier that can be used to mark where the error happened type :: state_type !> The current exit state integer(ilp) :: state = STDLIB_SUCCESS !> Message associated to the current state character(len=MSG_LENGTH) :: message = repeat(' ',MSG_LENGTH) !> Location of the state change character(len=NAME_LENGTH) :: where_at = repeat(' ',NAME_LENGTH) contains !> Cleanup procedure :: destroy => state_destroy !> Parse error constructor procedure, private :: state_parse_at_location procedure, private :: state_parse_arguments generic :: parse => state_parse_at_location, & state_parse_arguments !> Print error message procedure :: print => state_print procedure :: print_msg => state_message !> State properties procedure :: ok => state_is_ok procedure :: error => state_is_error !> Handle optional error message procedure :: handle => error_handling end type state_type !> Comparison operators interface operator(==) module procedure state_eq_flag module procedure flag_eq_state end interface interface operator(/=) module procedure state_neq_flag module procedure flag_neq_state end interface interface operator(<) module procedure state_lt_flag module procedure flag_lt_state end interface interface operator(<=) module procedure state_le_flag module procedure flag_le_state end interface interface operator(>) module procedure state_gt_flag module procedure flag_gt_state end interface interface operator(>=) module procedure state_ge_flag module procedure flag_ge_state end interface !> Assignment operator interface assignment(=) module procedure state_assign_state end interface assignment(=) interface state_type module procedure new_state module procedure new_state_nowhere end interface state_type !> Format strings with edit descriptors for each type and kind !> cannot be retrieved from stdlib_io due to circular dependencies character(*), parameter :: & FMT_INT = '(i0)', & FMT_REAL_SP = '(es15.8e2)', & FMT_REAL_DP = '(es24.16e3)', & FMT_REAL_XDP = '(es26.18e3)', & FMT_REAL_QP = '(es44.35e4)', & FMT_COMPLEX_SP = '(es15.8e2,1x,es15.8e2)', & FMT_COMPLEX_DP = '(es24.16e3,1x,es24.16e3)', & FMT_COMPLEX_XDP = '(es26.18e3,1x,es26.18e3)', & FMT_COMPLEX_QP = '(es44.35e4,1x,es44.35e4)' contains subroutine check(condition, msg, code, warn) !! version: experimental !! !! Checks the value of a logical condition !! ([Specification](../page/specs/stdlib_error.html#description)) !! !!##### Behavior !! !! If `condition == .false.` and: !! !! * No other arguments are provided, it stops the program with the default !! message and exit code `1`; !! * `msg` is provided, it prints the value of `msg`; !! * `code` is provided, it stops the program with the given exit code; !! * `warn` is provided and `.true.`, it doesn't stop the program and prints !! the message. !! !!##### Examples !! !!* If `a /= 5`, stops the program with exit code `1` !! and prints `Check failed.` !!``` fortran !! call check(a == 5) !!``` !! !!* As above, but prints `a == 5 failed`. !!``` fortran !! call check(a == 5, msg='a == 5 failed.') !!``` !! !!* As above, but doesn't stop the program. !!``` fortran !! call check(a == 5, msg='a == 5 failed.', warn=.true.) !!``` !! !!* As example #2, but stops the program with exit code `77` !!``` fortran !! call check(a == 5, msg='a == 5 failed.', code=77) !!``` ! ! Arguments ! --------- logical, intent(in) :: condition character(*), intent(in), optional :: msg integer, intent(in), optional :: code logical, intent(in), optional :: warn character(*), parameter :: msg_default = 'Check failed.' if (.not. condition) then if (optval(warn, .false.)) then write(stderr,*) optval(msg, msg_default) else call error_stop(optval(msg, msg_default), optval(code, 1)) end if end if end subroutine check !> Cleanup the object elemental subroutine state_destroy(this) class(state_type),intent(inout) :: this this%state = STDLIB_SUCCESS this%message = repeat(' ',len(this%message)) this%where_at = repeat(' ',len(this%where_at)) end subroutine state_destroy !> Interface to print stdlib error messages pure function state_flag_message(flag) result(msg) integer(ilp),intent(in) :: flag character(len=:),allocatable :: msg select case (flag) case (STDLIB_SUCCESS); msg = 'Success!' case (STDLIB_VALUE_ERROR); msg = 'Value Error' case (STDLIB_LINALG_ERROR); msg = 'Linear Algebra Error' case (STDLIB_IO_ERROR); msg = 'I/O Error' case (STDLIB_FS_ERROR); msg = 'Filesystem Error' case (STDLIB_INTERNAL_ERROR); msg = 'Internal Error' case default; msg = 'INVALID/UNKNOWN STATE FLAG' end select end function state_flag_message !> Return a formatted message pure function state_message(this) result(msg) class(state_type),intent(in) :: this character(len=:),allocatable :: msg if (this%state == STDLIB_SUCCESS) then msg = 'Success!' else msg = state_flag_message(this%state)//': '//trim(this%message) end if end function state_message !> Flow control: on output flag present, return it; otherwise, halt on error pure subroutine error_handling(ierr,ierr_out) class(state_type), intent(in) :: ierr class(state_type), optional, intent(inout) :: ierr_out character(len=:),allocatable :: err_msg if (present(ierr_out)) then ! Return error flag ierr_out = ierr elseif (ierr%error()) then err_msg = ierr%print() error stop err_msg end if end subroutine error_handling !> Produce a nice error string pure function state_print(this) result(msg) class(state_type),intent(in) :: this character(len=:),allocatable :: msg if (len_trim(this%where_at) > 0) then msg = '['//trim(this%where_at)//'] returned '//this%print_msg() elseif (this%error()) then msg = 'Error encountered: '//this%print_msg() else msg = this%print_msg() end if end function state_print !> Check if the current state is successful elemental logical(lk) function state_is_ok(this) class(state_type),intent(in) :: this state_is_ok = this%state == STDLIB_SUCCESS end function state_is_ok !> Check if the current state is an error state elemental logical(lk) function state_is_error(this) class(state_type),intent(in) :: this state_is_error = this%state /= STDLIB_SUCCESS end function state_is_error !> Compare an error state with an integer flag elemental logical(lk) function state_eq_flag(err,flag) class(state_type),intent(in) :: err integer,intent(in) :: flag state_eq_flag = err%state == flag end function state_eq_flag !> Compare an integer flag with the error state elemental logical(lk) function flag_eq_state(flag,err) integer,intent(in) :: flag class(state_type),intent(in) :: err flag_eq_state = err%state == flag end function flag_eq_state !> Compare the error state with an integer flag elemental logical(lk) function state_neq_flag(err,flag) class(state_type),intent(in) :: err integer,intent(in) :: flag state_neq_flag = .not. state_eq_flag(err,flag) end function state_neq_flag !> Compare an integer flag with the error state elemental logical(lk) function flag_neq_state(flag,err) integer,intent(in) :: flag class(state_type),intent(in) :: err flag_neq_state = .not. state_eq_flag(err,flag) end function flag_neq_state !> Compare the error state with an integer flag elemental logical(lk) function state_lt_flag(err,flag) class(state_type),intent(in) :: err integer,intent(in) :: flag state_lt_flag = err%state < flag end function state_lt_flag !> Compare the error state with an integer flag elemental logical(lk) function state_le_flag(err,flag) class(state_type),intent(in) :: err integer,intent(in) :: flag state_le_flag = err%state <= flag end function state_le_flag !> Compare an integer flag with the error state elemental logical(lk) function flag_lt_state(flag,err) integer,intent(in) :: flag class(state_type),intent(in) :: err flag_lt_state = err%state < flag end function flag_lt_state !> Compare an integer flag with the error state elemental logical(lk) function flag_le_state(flag,err) integer,intent(in) :: flag class(state_type),intent(in) :: err flag_le_state = err%state <= flag end function flag_le_state !> Compare the error state with an integer flag elemental logical(lk) function state_gt_flag(err,flag) class(state_type),intent(in) :: err integer,intent(in) :: flag state_gt_flag = err%state > flag end function state_gt_flag !> Compare the error state with an integer flag elemental logical(lk) function state_ge_flag(err,flag) class(state_type),intent(in) :: err integer,intent(in) :: flag state_ge_flag = err%state >= flag end function state_ge_flag !> Compare an integer flag with the error state elemental logical(lk) function flag_gt_state(flag,err) integer,intent(in) :: flag class(state_type),intent(in) :: err flag_gt_state = err%state > flag end function flag_gt_state !> Compare an integer flag with the error state elemental logical(lk) function flag_ge_state(flag,err) integer,intent(in) :: flag class(state_type),intent(in) :: err flag_ge_state = err%state >= flag end function flag_ge_state !> Assign a state type to another elemental subroutine state_assign_state(to, from) class(state_type), intent(inout) :: to class(state_type), intent(in) :: from to%state = from%state to%message = from%message to%where_at = from%where_at end subroutine state_assign_state !> Append a generic value to the error flag (rank-agnostic) pure subroutine appendr(msg,a,prefix) class(*),optional,intent(in) :: a(..) character(len=*),intent(inout) :: msg character,optional,intent(in) :: prefix if (present(a)) then select rank (v=>a) rank (0) call append (msg,v,prefix) rank (1) call appendv(msg,v) rank default msg = trim(msg)//' ' end select endif end subroutine appendr ! Append a generic value to the error flag pure subroutine append(msg,a,prefix) class(*),intent(in) :: a character(len=*),intent(inout) :: msg character,optional,intent(in) :: prefix character(len=MSG_LENGTH) :: buffer,buffer2 character(len=2) :: sep integer :: ls ! Do not add separator if this is the first instance sep = ' ' ls = merge(1,0,len_trim(msg) > 0) if (present(prefix)) then ls = ls + 1 sep(ls:ls) = prefix end if select type (aa => a) !> String type type is (character(len=*)) msg = trim(msg)//sep(:ls)//aa !> Numeric types #:for k1, t1 in KINDS_TYPES type is (${t1}$) #:if 'complex' in t1 write (buffer, FMT_REAL_${k1}$) aa%re write (buffer2,FMT_REAL_${k1}$) aa%im msg = trim(msg)//sep(:ls)//'('//trim(adjustl(buffer))//','//trim(adjustl(buffer2))//')' #:else #:if 'real' in t1 write (buffer,FMT_REAL_${k1}$) aa #:else write (buffer,FMT_INT) aa #:endif msg = trim(msg)//sep(:ls)//trim(adjustl(buffer)) #:endif #:endfor class default msg = trim(msg)//' ' end select end subroutine append !> Append a generic vector to the error flag pure subroutine appendv(msg,a) class(*),intent(in) :: a(:) character(len=*),intent(inout) :: msg integer :: j,ls character(len=MSG_LENGTH) :: buffer,buffer2,buffer_format character(len=2) :: sep if (size(a) <= 0) return ! Default: separate elements with one space sep = ' ' ls = 1 ! Open bracket msg = trim(msg)//' [' ! Do not call append(msg(aa(j))), it will crash gfortran select type (aa => a) !> Strings (cannot use string_type due to `sequence`) type is (character(len=*)) msg = trim(msg)//adjustl(aa(1)) do j = 2,size(a) msg = trim(msg)//sep(:ls)//adjustl(aa(j)) end do !> Numeric types #:for k1, t1 in KINDS_TYPES type is (${t1}$) #:if 'complex' in t1 write (buffer,FMT_REAL_${k1}$) aa(1)%re write (buffer2,FMT_REAL_${k1}$) aa(1)%im msg = trim(msg)//'('//trim(adjustl(buffer))//','//trim(adjustl(buffer2))//')' do j = 2,size(a) write (buffer,FMT_REAL_${k1}$) aa(j)%re write (buffer2,FMT_REAL_${k1}$) aa(j)%im msg = trim(msg)//sep(:ls)//'('//trim(adjustl(buffer))//','//trim(adjustl(buffer2))//')' end do #:else #:if 'real' in t1 buffer_format = FMT_REAL_${k1}$ #:else buffer_format = FMT_INT #:endif write (buffer,buffer_format) aa(1) msg = trim(msg)//adjustl(buffer) do j = 2,size(a) write (buffer,buffer_format) aa(j) msg = trim(msg)//sep(:ls)//adjustl(buffer) end do msg = trim(msg)//sep(:ls)//trim(adjustl(buffer)) #:endif #:endfor class default msg = trim(msg)//' ' end select ! Close bracket msg = trim(msg)//']' end subroutine appendv !> Error creation message, with location location pure type(state_type) function new_state(where_at,flag,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) !> Location character(len=*),intent(in) :: where_at !> Input error flag integer,intent(in) :: flag !> Optional rank-agnostic arguments class(*),optional,intent(in),dimension(..) :: a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20 ! Init object call new_state%parse(where_at,flag,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) end function new_state !> Error creation message, from N input variables (numeric or strings) pure type(state_type) function new_state_nowhere(flag,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) & result(new_state) !> Input error flag integer,intent(in) :: flag !> Optional rank-agnostic arguments class(*),optional,intent(in),dimension(..) :: a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20 ! Init object call new_state%parse(flag,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) end function new_state_nowhere !> Parse a generic list of arguments provided to the error constructor pure subroutine state_parse_at_location(new_state,where_at,flag,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) !> The current state variable class(state_type), intent(inout) :: new_state !> Error Location character(len=*),intent(in) :: where_at !> Input error flag integer,intent(in) :: flag !> Optional rank-agnostic arguments class(*),optional,intent(in),dimension(..) :: a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20 ! Init object call new_state%destroy() !> Set error flag new_state%state = flag !> Set chain new_state%message = "" call appendr(new_state%message,a1) call appendr(new_state%message,a2) call appendr(new_state%message,a3) call appendr(new_state%message,a4) call appendr(new_state%message,a5) call appendr(new_state%message,a6) call appendr(new_state%message,a7) call appendr(new_state%message,a8) call appendr(new_state%message,a9) call appendr(new_state%message,a10) call appendr(new_state%message,a11) call appendr(new_state%message,a12) call appendr(new_state%message,a13) call appendr(new_state%message,a14) call appendr(new_state%message,a15) call appendr(new_state%message,a16) call appendr(new_state%message,a17) call appendr(new_state%message,a18) call appendr(new_state%message,a19) call appendr(new_state%message,a20) !> Add location if (len_trim(where_at) > 0) new_state%where_at = adjustl(where_at) end subroutine state_parse_at_location !> Parse a generic list of arguments provided to the error constructor pure subroutine state_parse_arguments(new_state,flag,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) !> The current state variable class(state_type), intent(inout) :: new_state !> Input error flag integer,intent(in) :: flag !> Optional rank-agnostic arguments class(*),optional,intent(in),dimension(..) :: a1,a2,a3,a4,a5,a6,a7,a8,a9,a10, & a11,a12,a13,a14,a15,a16,a17,a18,a19,a20 ! Init object call new_state%destroy() !> Set error flag new_state%state = flag !> Set chain new_state%message = "" call appendr(new_state%message,a1) call appendr(new_state%message,a2) call appendr(new_state%message,a3) call appendr(new_state%message,a4) call appendr(new_state%message,a5) call appendr(new_state%message,a6) call appendr(new_state%message,a7) call appendr(new_state%message,a8) call appendr(new_state%message,a9) call appendr(new_state%message,a10) call appendr(new_state%message,a11) call appendr(new_state%message,a12) call appendr(new_state%message,a13) call appendr(new_state%message,a14) call appendr(new_state%message,a15) call appendr(new_state%message,a16) call appendr(new_state%message,a17) call appendr(new_state%message,a18) call appendr(new_state%message,a19) call appendr(new_state%message,a20) end subroutine state_parse_arguments end module stdlib_error fortran-lang-stdlib-0ede301/src/core/f18estop.f900000664000175000017500000000117215135654166021677 0ustar alastairalastairsubmodule (stdlib_error) f18estop implicit none contains module procedure error_stop ! Aborts the program with nonzero exit code ! ! The "stop " statement generally has return code 0. ! To allow non-zero return code termination with character message, ! error_stop() uses the statement "error stop", which by default ! has exit code 1 and prints the message to stderr. ! An optional integer return code "code" may be specified. ! ! Example ! ------- ! ! call error_stop("Invalid argument") if(present(code)) then write(stderr,*) msg error stop code else error stop msg endif end procedure end submodule f18estop fortran-lang-stdlib-0ede301/src/core/stdlib_optval.fypp0000664000175000017500000000341415135654166023455 0ustar alastairalastair#:include "common.fypp" #:set KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES + CMPLX_KINDS_TYPES + & & [('l1','logical')] module stdlib_optval !! !! Provides a generic function `optval`, which can be used to !! conveniently implement fallback values for optional arguments !! to subprograms !! ([Specification](../page/specs/stdlib_optval.html)) !! !! If `x` is an `optional` parameter of a !! subprogram, then the expression `optval(x, default)` inside that !! subprogram evaluates to `x` if it is present, otherwise `default`. !! !! It is an error to call `optval` with a single actual argument. !! use stdlib_kinds, only: sp, dp, xdp, qp, int8, int16, int32, int64 implicit none private public :: optval interface optval !! version: experimental !! !! Fallback value for optional arguments !! ([Specification](../page/specs/stdlib_optval.html#description)) #:for k1, t1 in KINDS_TYPES module procedure optval_${t1[0]}$${k1}$ #:endfor module procedure optval_character ! TODO: differentiate ascii & ucs char kinds end interface optval contains #:for k1, t1 in KINDS_TYPES pure elemental function optval_${t1[0]}$${k1}$(x, default) result(y) ${t1}$, intent(in), optional :: x ${t1}$, intent(in) :: default ${t1}$ :: y if (present(x)) then y = x else y = default end if end function optval_${t1[0]}$${k1}$ #:endfor ! Cannot be made elemental pure function optval_character(x, default) result(y) character(len=*), intent(in), optional :: x character(len=*), intent(in) :: default character(len=:), allocatable :: y if (present(x)) then y = x else y = default end if end function optval_character end module stdlib_optval fortran-lang-stdlib-0ede301/src/core/CMakeLists.txt0000664000175000017500000000051615135654166022447 0ustar alastairalastairset(core_fppFiles stdlib_ascii.fypp stdlib_error.fypp stdlib_kinds.fypp stdlib_optval.fypp ) set(core_cppFiles ) set(core_f90Files $,f18estop.f90,f08estop.f90> stdlib_io_aux.f90 ) configure_stdlib_target(${PROJECT_NAME}_core core_f90Files core_fppFiles core_cppFiles) fortran-lang-stdlib-0ede301/src/core/f08estop.f900000664000175000017500000000160415135654166021676 0ustar alastairalastairsubmodule (stdlib_error) f08estop implicit none contains module procedure error_stop ! Aborts the program with nonzero exit code ! this is a fallback for Fortran 2008 error stop (e.g. Intel 19.1/2020 compiler) ! ! The "stop " statement generally has return code 0. ! To allow non-zero return code termination with character message, ! error_stop() uses the statement "error stop", which by default ! has exit code 1 and prints the message to stderr. ! An optional integer return code "code" may be specified. ! ! Example ! ------- ! ! call error_stop("Invalid argument") write(stderr,*) msg if(present(code)) then select case (code) case (1) error stop 1 case (2) error stop 2 case (77) error stop 77 case default write(stderr,*) 'ERROR: code ',code,' was specified.' error stop end select else error stop endif end procedure end submodule f08estop fortran-lang-stdlib-0ede301/src/core/stdlib_ascii.fypp0000664000175000017500000003476515135654166023255 0ustar alastairalastair#:include "common.fypp" !> The `stdlib_ascii` module provides procedures for handling and manipulating !> intrinsic character variables and constants. !> !> The specification of this module is available [here](../page/specs/stdlib_ascii.html). module stdlib_ascii use stdlib_kinds, only : int8, int16, int32, int64, lk, c_bool implicit none private ! Character validation functions public :: is_alpha, is_alphanum public :: is_digit, is_hex_digit, is_octal_digit public :: is_control, is_white, is_blank public :: is_ascii, is_punctuation public :: is_graphical, is_printable public :: is_lower, is_upper ! Character conversion functions public :: to_lower, to_upper, to_title, to_sentence, reverse ! All control characters in the ASCII table (see www.asciitable.com). character(len=1), public, parameter :: NUL = achar(int(z'00')) !! Null character(len=1), public, parameter :: SOH = achar(int(z'01')) !! Start of heading character(len=1), public, parameter :: STX = achar(int(z'02')) !! Start of text character(len=1), public, parameter :: ETX = achar(int(z'03')) !! End of text character(len=1), public, parameter :: EOT = achar(int(z'04')) !! End of transmission character(len=1), public, parameter :: ENQ = achar(int(z'05')) !! Enquiry character(len=1), public, parameter :: ACK = achar(int(z'06')) !! Acknowledge character(len=1), public, parameter :: BEL = achar(int(z'07')) !! Bell character(len=1), public, parameter :: BS = achar(int(z'08')) !! Backspace character(len=1), public, parameter :: TAB = achar(int(z'09')) !! Horizontal tab character(len=1), public, parameter :: LF = achar(int(z'0A')) !! NL line feed, new line character(len=1), public, parameter :: VT = achar(int(z'0B')) !! Vertical tab character(len=1), public, parameter :: FF = achar(int(z'0C')) !! NP form feed, new page character(len=1), public, parameter :: CR = achar(int(z'0D')) !! Carriage return character(len=1), public, parameter :: SO = achar(int(z'0E')) !! Shift out character(len=1), public, parameter :: SI = achar(int(z'0F')) !! Shift in character(len=1), public, parameter :: DLE = achar(int(z'10')) !! Data link escape character(len=1), public, parameter :: DC1 = achar(int(z'11')) !! Device control 1 character(len=1), public, parameter :: DC2 = achar(int(z'12')) !! Device control 2 character(len=1), public, parameter :: DC3 = achar(int(z'13')) !! Device control 3 character(len=1), public, parameter :: DC4 = achar(int(z'14')) !! Device control 4 character(len=1), public, parameter :: NAK = achar(int(z'15')) !! Negative acknowledge character(len=1), public, parameter :: SYN = achar(int(z'16')) !! Synchronous idle character(len=1), public, parameter :: ETB = achar(int(z'17')) !! End of transmission block character(len=1), public, parameter :: CAN = achar(int(z'18')) !! Cancel character(len=1), public, parameter :: EM = achar(int(z'19')) !! End of medium character(len=1), public, parameter :: SUB = achar(int(z'1A')) !! Substitute character(len=1), public, parameter :: ESC = achar(int(z'1B')) !! Escape character(len=1), public, parameter :: FS = achar(int(z'1C')) !! File separator character(len=1), public, parameter :: GS = achar(int(z'1D')) !! Group separator character(len=1), public, parameter :: RS = achar(int(z'1E')) !! Record separator character(len=1), public, parameter :: US = achar(int(z'1F')) !! Unit separator character(len=1), public, parameter :: DEL = achar(int(z'7F')) !! Delete ! Constant character sequences character(len=*), public, parameter :: fullhex_digits = "0123456789ABCDEFabcdef" !! 0 .. 9A .. Fa .. f character(len=*), public, parameter :: hex_digits = fullhex_digits(1:16) !! 0 .. 9A .. F character(len=*), public, parameter :: lowerhex_digits = "0123456789abcdef" !! 0 .. 9a .. f character(len=*), public, parameter :: digits = hex_digits(1:10) !! 0 .. 9 character(len=*), public, parameter :: octal_digits = digits(1:8) !! 0 .. 7 character(len=*), public, parameter :: letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" !! A .. Za .. z character(len=*), public, parameter :: uppercase = letters(1:26) !! A .. Z character(len=*), public, parameter :: lowercase = letters(27:) !! a .. z character(len=*), public, parameter :: whitespace = " "//TAB//VT//CR//LF//FF !! ASCII _whitespace !> Returns a new character sequence which is the lower case !> version of the input character sequence !> This method is elemental and returns a character sequence interface to_lower module procedure :: to_lower end interface to_lower !> Returns a new character sequence which is the upper case !> version of the input character sequence !> This method is elemental and returns a character sequence interface to_upper module procedure :: to_upper end interface to_upper !> Returns a new character sequence which is the title case !> version of the input character sequence !> This method is elemental and returns a character sequence interface to_title module procedure :: to_title end interface to_title !> Returns a new character sequence which is the sentence case !> version of the input character sequence !> This method is elemental and returns a character sequence interface to_sentence module procedure :: to_sentence end interface to_sentence !> Returns a new character sequence which is reverse of !> the input charater sequence !> This method is elemental and returns a character sequence interface reverse module procedure :: reverse end interface reverse contains !> Checks whether `c` is an ASCII letter (A .. Z, a .. z). elemental logical function is_alpha(c) character(len=1), intent(in) :: c !! The character to test. is_alpha = (c >= 'A' .and. c <= 'Z') .or. (c >= 'a' .and. c <= 'z') end function !> Checks whether `c` is a letter or a number (0 .. 9, a .. z, A .. Z). elemental logical function is_alphanum(c) character(len=1), intent(in) :: c !! The character to test. is_alphanum = (c >= '0' .and. c <= '9') .or. (c >= 'a' .and. c <= 'z') & .or. (c >= 'A' .and. c <= 'Z') end function !> Checks whether or not `c` is in the ASCII character set - !> i.e. in the range 0 .. 0x7F. elemental logical function is_ascii(c) character(len=1), intent(in) :: c !! The character to test. is_ascii = iachar(c) <= int(z'7F') end function !> Checks whether `c` is a control character. elemental logical function is_control(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) is_control = ic < int(z'20') .or. ic == int(z'7F') end function !> Checks whether `c` is a digit (0 .. 9). elemental logical function is_digit(c) character(len=1), intent(in) :: c !! The character to test. is_digit = ('0' <= c) .and. (c <= '9') end function !> Checks whether `c` is a digit in base 8 (0 .. 7). elemental logical function is_octal_digit(c) character(len=1), intent(in) :: c !! The character to test. is_octal_digit = (c >= '0') .and. (c <= '7'); end function !> Checks whether `c` is a digit in base 16 (0 .. 9, A .. F, a .. f). elemental logical function is_hex_digit(c) character(len=1), intent(in) :: c !! The character to test. is_hex_digit = (c >= '0' .and. c <= '9') .or. (c >= 'a' .and. c <= 'f') & .or. (c >= 'A' .and. c <= 'F') end function !> Checks whether or not `c` is a punctuation character. That includes !> all ASCII characters which are not control characters, letters, !> digits, or whitespace. elemental logical function is_punctuation(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) ! '~' '!' is_punctuation = (ic <= int(z'7E')) .and. (ic >= int(z'21')) .and. & (.not. is_alphanum(c)) end function !> Checks whether or not `c` is a printable character other than the !> space character. elemental logical function is_graphical(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) !The character is graphical if it's between '!' and '~' in the ASCII table, !that is: printable but not a space is_graphical = (int(z'21') <= ic) .and. (ic <= int(z'7E')) end function !> Checks whether or not `c` is a printable character - including the !> space character. elemental logical function is_printable(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) !The character is printable if it's between ' ' and '~' in the ASCII table is_printable = ic >= iachar(' ') .and. ic <= int(z'7E') end function !> Checks whether `c` is a lowercase ASCII letter (a .. z). elemental logical function is_lower(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) is_lower = ic >= iachar('a') .and. ic <= iachar('z') end function !> Checks whether `c` is an uppercase ASCII letter (A .. Z). elemental logical function is_upper(c) character(len=1), intent(in) :: c !! The character to test. is_upper = (c >= 'A') .and. (c <= 'Z') end function !> Checks whether or not `c` is a whitespace character. That includes the !> space, tab, vertical tab, form feed, carriage return, and linefeed !> characters. elemental logical function is_white(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) ! TAB, LF, VT, FF, CR is_white = (c == ' ') .or. (ic >= int(z'09') .and. ic <= int(z'0D')); end function !> Checks whether or not `c` is a blank character. That includes the !> only the space and tab characters elemental logical function is_blank(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) ! TAB is_blank = (c == ' ') .or. (ic == int(z'09')); end function !> Returns the corresponding lowercase letter, if `c` is an uppercase !> ASCII character, otherwise `c` itself. elemental function char_to_lower(c) result(t) character(len=1), intent(in) :: c !! A character. character(len=1) :: t integer, parameter :: wp= iachar('a')-iachar('A'), BA=iachar('A'), BZ=iachar('Z') integer :: k !Check whether the integer equivalent is between BA=65 and BZ=90 k = ichar(c) if (k>=BA.and.k<=BZ) k = k + wp t = char(k) end function char_to_lower !> Returns the corresponding uppercase letter, if `c` is a lowercase !> ASCII character, otherwise `c` itself. elemental function char_to_upper(c) result(t) character(len=1), intent(in) :: c !! A character. character(len=1) :: t integer, parameter :: wp= iachar('a')-iachar('A'), la=iachar('a'), lz=iachar('z') integer :: k !Check whether the integer equivalent is between la=97 and lz=122 k = ichar(c) if (k>=la.and.k<=lz) k = k - wp t = char(k) end function char_to_upper !> Convert character variable to lower case !> ([Specification](../page/specs/stdlib_ascii.html#to_lower)) !> !> Version: experimental elemental function to_lower(string) result(lower_string) character(len=*), intent(in) :: string character(len=len(string)) :: lower_string integer :: i do i = 1, len(string) lower_string(i:i) = char_to_lower(string(i:i)) end do end function to_lower !> Convert character variable to upper case !> ([Specification](../page/specs/stdlib_ascii.html#to_upper)) !> !> Version: experimental elemental function to_upper(string) result(upper_string) character(len=*), intent(in) :: string character(len=len(string)) :: upper_string integer :: i do i = 1, len(string) upper_string(i:i) = char_to_upper(string(i:i)) end do end function to_upper !> Converts character sequence to title case !> ([Specification](../page/specs/stdlib_ascii.html#to_title)) !> !> Version: experimental elemental function to_title(string) result(title_string) character(len=*), intent(in) :: string character(len=len(string)) :: title_string integer :: i logical :: capitalize_switch capitalize_switch = .true. do i = 1, len(string) if (is_alphanum(string(i:i))) then if (capitalize_switch) then title_string(i:i) = char_to_upper(string(i:i)) capitalize_switch = .false. else title_string(i:i) = char_to_lower(string(i:i)) end if else title_string(i:i) = string(i:i) capitalize_switch = .true. end if end do end function to_title !> Converts character sequence to sentence case !> ([Specification](../page/specs/stdlib_ascii.html#to_sentence)) !> !> Version: experimental elemental function to_sentence(string) result(sentence_string) character(len=*), intent(in) :: string character(len=len(string)) :: sentence_string integer :: i, n n = len(string) do i = 1, len(string) if (is_alphanum(string(i:i))) then sentence_string(i:i) = char_to_upper(string(i:i)) n = i exit else sentence_string(i:i) = string(i:i) end if end do do i = n + 1, len(string) sentence_string(i:i) = char_to_lower(string(i:i)) end do end function to_sentence !> Reverse the character order in the input character variable !> ([Specification](../page/specs/stdlib_ascii.html#reverse)) !> !> Version: experimental elemental function reverse(string) result(reverse_string) character(len=*), intent(in) :: string character(len=len(string)) :: reverse_string integer :: i, n n = len(string) do i = 1, n reverse_string(n-i+1:n-i+1) = string(i:i) end do end function reverse end module stdlib_ascii fortran-lang-stdlib-0ede301/src/core/stdlib_kinds.fypp0000664000175000017500000000157715135654166023270 0ustar alastairalastair#:include "common.fypp" !> Version: experimental !> !> The specification of this module is available [here](../page/specs/stdlib_kinds.html). module stdlib_kinds use iso_fortran_env, only: int8, int16, int32, int64 use iso_c_binding, only: c_bool, c_char implicit none private public :: sp, dp, xdp, qp, int8, int16, int32, int64, lk, c_bool, c_char !> Single precision real numbers integer, parameter :: sp = selected_real_kind(6) !> Double precision real numbers integer, parameter :: dp = selected_real_kind(15) !> Extended double precision real numbers integer, parameter :: xdp = #{if WITH_XDP}#selected_real_kind(18)#{else}#-1#{endif}# !> Quadruple precision real numbers integer, parameter :: qp = #{if WITH_QP}#selected_real_kind(33)#{else}#-1#{endif}# !> Default logical kind parameter integer, parameter :: lk = kind(.true.) end module stdlib_kinds fortran-lang-stdlib-0ede301/src/hashmaps/0000775000175000017500000000000015135654166020561 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/hashmaps/stdlib_hashmap_open.f900000664000175000017500000010241015135654166025102 0ustar alastairalastair!! The module, STDLIB_HASHMAP_OPEN implements a simple open addressing hash !! map using linear addressing. The implementation is loosely based on a !! C implementation by David Chase, http://chasewoerner.org/src/hasht/, for !! which he has given permission to use in the Fortran Standard Library. ! Note an error in the code caused attempts to deallocate already deallocated ! entries. This did not cause stat to be non-zero, but did cause system errors, ! on my Mac. I therefore decided to remove all deallocation error reporting. submodule(stdlib_hashmaps) stdlib_hashmap_open use, intrinsic :: iso_fortran_env, only: & character_storage_size, & error_unit use stdlib_hashmap_wrappers implicit none ! Error messages character(len=*), parameter :: & alloc_inv_fault = "OPEN_HASHMAP_TYPE % INVERSE allocation fault.", & alloc_key_fault = "KEY allocation fault.", & alloc_slots_fault = "OPEN_HASHMAP_TYPE % SLOTS allocation fault.", & conflicting_key = "KEY already exists in MAP.", & expand_slots_fail = "OPEN_HASHMAP_TYPE % SLOTS allocation > " // & "MAX_BITS.", & init_slots_pow_fail = "SLOTS_BITS is not between DEFAULT_BITS " // & "and MAX_BITS.", & invalid_inmap = "INMAP was not a valid INVERSE index.", & map_consist_fault = "The hash map found an inconsistency." character(*), parameter :: submodule_name = 'STDLIB_HASHMAP_OPEN' interface expand_slots !! Version: Experimental !! !! Interface to internal procedure that expands an open map's slots. module procedure expand_open_slots end interface expand_slots interface extend_map_entry_pool !! Version: Experimental !! !! Interface to internal procedure that expands an open map entry pool. module procedure extend_open_map_entry_pool end interface extend_map_entry_pool interface free_map !! Version: Experimental !! !! Interface to procedure that finalizes an open hash map. module procedure free_open_map end interface free_map interface free_map_entry_pool !! Version: Experimental !! !! Interface to internal procedure that finalizes an open hash map !! entry pool. module procedure free_map_entry_pool end interface free_map_entry_pool interface get_other_data !! Version: Experimental !! !! Interface to procedure that gets an entry's other data. module procedure get_other_open_data end interface get_other_data interface init !! Version: Experimental !! !! Interface to initialization procedure for an open hash map. module procedure init_open_map end interface init interface rehash !! Version: Experimental !! !! Interface to a procedure that changes the hash function that !! is used to map the keys into an open hash map. module procedure rehash_open_map end interface rehash interface remove !! Version: Experimental !! !! Interface to a procedure that removees an entry from an open hash map. module procedure remove_open_entry end interface remove interface set_other_data !! Version: Experimental !! !! Interface to a procedure that changes the other data associated with a key module procedure set_other_open_data end interface set_other_data contains subroutine expand_open_slots( map ) !! Version: Experimental !! !! Internal routine to make a duplicate map with more hash slots. !! Doubles the size of the map % slots array !! Arguments: !! map - the hash table whose hash slots are to be expanded ! type(open_hashmap_type), intent(inout) :: map integer(int_hash) :: base_slot integer(int_index), allocatable :: dummy_slots(:) integer(int_index) :: inv_index, & new_size, & offset, & old_size, & test_slot integer(int32) :: bits, & stat character(256) :: errmsg character(*), parameter :: procedure = 'EXPAND_SLOTS' if ( map % nbits == max_bits ) then error stop submodule_name // ' % ' // procedure // ': ' // & expand_slots_fail end if old_size = size(map % slots, kind=int_index) new_size = 2*old_size bits = map % nbits + 1 allocate( dummy_slots(0:new_size-1), stat=stat, errmsg=errmsg ) if (stat /= 0) then error stop submodule_name // ' % ' // procedure // ': ' // & alloc_slots_fault end if map % nbits = bits dummy_slots(:) = 0 map % index_mask = new_size-1 map % total_probes = map % total_probes + map % probe_count map % probe_count = 0 REMAP_SLOTS: do inv_index=1_int_index, & map % num_entries + map % num_free associate( inverse => map % inverse(inv_index) ) if ( associated(inverse % target) ) then base_slot = fibonacci_hash( inverse % target % hash_val, & map % nbits ) offset = 0 FIND_EMPTY_SLOT: do test_slot = iand( int( base_slot + offset, int_hash), & map % index_mask ) if ( dummy_slots(test_slot) == 0 ) then dummy_slots(test_slot) = inv_index exit FIND_EMPTY_SLOT end if offset = offset + 1 end do FIND_EMPTY_SLOT end if end associate end do REMAP_SLOTS call move_alloc( dummy_slots, map % slots ) end subroutine expand_open_slots subroutine extend_open_map_entry_pool(pool) ! gent_pool_new !! Version: Experimental !! !! Add more map_entrys to the pool head !! Arguments: !! pool - an open map entry pool type(open_map_entry_pool), intent(inout), pointer :: pool type(open_map_entry_pool), pointer :: map_entry_pool_head allocate(map_entry_pool_head) allocate(map_entry_pool_head % more_map_entries(0:pool_size-1)) map_entry_pool_head % lastpool => pool pool => map_entry_pool_head pool % next = 0 end subroutine extend_open_map_entry_pool recursive subroutine free_map_entry_pool(pool) ! gent_pool_free !! Version: Experimental !! Note the freeing of allocated memory may be unnecessary !! !! Recursively descends map entry pool list freeing each element !! Arguments: !! pool The map entry pool whose elements are to be freed ! type(open_map_entry_pool), intent(inout), pointer :: pool type(open_map_entry_pool), pointer :: lastpool if ( associated(pool) ) then lastpool => pool % lastpool pool % lastpool => null() deallocate( pool ) ! Trace component pointers/lists call free_map_entry_pool( lastpool ) end if end subroutine free_map_entry_pool module subroutine free_open_map( map ) !! Version: Experimental !! !! Frees internal memory of an open map !! Arguments: !! map - the open hash map whose memory is to be freed ! type(open_hashmap_type), intent(inout) :: map type(open_map_entry_list), pointer :: free_list integer(int_index) :: i if ( allocated( map % slots ) ) then deallocate( map % slots ) end if if ( allocated( map % inverse ) ) then remove_links: do i=1, size( map % inverse, kind=int_index ) map % inverse(i) % target => null() end do remove_links deallocate( map % inverse ) end if free_free_list: do while( map % num_free > 0 ) free_list => map % free_list map % free_list => map % free_list % next free_list % next => null() free_list % target => null() map % num_free = map % num_free - 1 end do free_free_list map % num_free = 0 if ( associated( map % cache ) ) call free_map_entry_pool(map % cache) map % num_entries = 0 end subroutine free_open_map module subroutine get_all_open_keys(map, all_keys) !! Version: Experimental !! !! Returns all the keys contained in a hash map !! Arguments: !! map - an open hash map !! all_keys - all the keys contained in a hash map ! class(open_hashmap_type), intent(in) :: map type(key_type), allocatable, intent(out) :: all_keys(:) integer(int32) :: num_keys integer(int_index) :: i, key_idx num_keys = map % entries() allocate( all_keys(num_keys) ) if ( num_keys == 0 ) return if ( allocated( map % inverse) ) then key_idx = 1_int_index do i=1_int_index, size( map % inverse, kind=int_index ) if ( associated( map % inverse(i) % target ) ) then all_keys(key_idx) = map % inverse(i) % target % key key_idx = key_idx + 1_int_index end if end do end if end subroutine get_all_open_keys module subroutine get_other_open_data( map, key, other, exists ) !! Version: Experimental !! !! Returns the other data associated with the inverse table index !! Arguments: !! map - an open hash table !! key - the key associated with a map entry !! other - the other data associated with the key !! exists - a logical flag indicating whether an entry with that key exists ! class(open_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), allocatable, intent(out) :: other logical, intent(out), optional :: exists integer(int_index) :: inmap character(*), parameter :: procedure = 'GET_OTHER_DATA' call in_open_map(map, inmap, key) if ( inmap <= 0 .or. & inmap > map % num_entries + map % num_free ) then if ( present(exists) ) then exists = .false. return else error stop submodule_name // ' % ' // procedure // ': ' // & invalid_inmap end if else if ( associated( map % inverse(inmap) % target ) ) then if ( present(exists) ) exists = .true. other = map % inverse(inmap) % target % other else if ( present(exists) ) then exists = .false. return else error stop submodule_name // ' % ' // procedure // ': ' // & map_consist_fault end if end if end subroutine get_other_open_data subroutine in_open_map(map, inmap, key) ! Chase's inmap !! Version: Experimental !! !! Returns the index into the INVERSE array associated with the KEY !! Arguments: !! map - the hash map of interest !! inmap - the returned index into the INVERSE array of entry pointers !! key - the key identifying the entry of interest ! class(open_hashmap_type), intent(inout) :: map integer(int_index), intent(out) :: inmap type(key_type), intent(in) :: key character(*), parameter :: procedure = 'IN_MAP' integer(int_hash) :: & base_slot, & hash_val, & test_slot integer(int_index) :: & offset hash_val = map % hasher( key ) if ( map % probe_count > inmap_probe_factor * map % call_count .or. & map % num_entries >= load_factor * & size( map % slots, kind=int_index ) ) then if ( map % nbits < max_bits ) & call expand_slots(map) end if map % call_count = map % call_count + 1 base_slot = fibonacci_hash( hash_val, map % nbits ) offset = 0_int_index PROBE_SLOTS: do test_slot = iand( base_slot + offset, map % index_mask ) map % probe_count = map % probe_count + 1 inmap = map % slots( test_slot ) if ( inmap == 0 ) then return else if ( inmap < 0 .or. & inmap > map % num_entries + map % num_free ) then error stop submodule_name // ' % ' // procedure // ': ' // & map_consist_fault else if ( .not. associated( map % inverse(inmap) % target ) ) then error stop submodule_name // ' % ' // procedure // ': ' // & map_consist_fault else associate( inverse => map % inverse(inmap) ) if ( hash_val == inverse % target % hash_val ) then if ( key == inverse % target % key ) then return end if end if end associate end if offset = offset + 1_int_index end do PROBE_SLOTS end subroutine in_open_map module subroutine init_open_map( map, & hasher, & slots_bits, & status ) !! Version: Experimental !! !! Routine to allocate an empty map with HASHER as the hash function, !! 2**SLOTS_BITS initial SIZE(map % slots), and SIZE(map % slots) limited to a !! maximum of 2**MAX_BITS. All fields are initialized. !! Arguments: !! map - the open hash maap to be initialized !! hasher - the hash function to be used to map keys to slots !! slots_bits - the number of bits used to map to the slots !! status - an integer error status flag with the allowed values: !! success - no problems were found !! alloc_fault - map % slots or map % inverse could not be allocated !! array_size_error - slots_bits is less than default_bitd or !! greater than max_bits class(open_hashmap_type), intent(out) :: map procedure(hasher_fun), optional :: hasher integer, intent(in), optional :: slots_bits integer(int32), intent(out), optional :: status character(256) :: errmsg integer(int_index) :: i character(*), parameter :: procedure = 'INIT' integer(int_index) :: slots integer(int32) :: stat type(open_map_entry_pool), pointer :: map_entry_pool_head map % call_count = 0 map % probe_count = 0 map % total_probes = 0 ! Check if user has specified a hasher other than the default hasher. if (present(hasher)) map % hasher => hasher if ( present(slots_bits) ) then if ( slots_bits < default_bits .OR. & slots_bits > max_bits ) then if ( present(status) ) then status = array_size_error return else error stop submodule_name // ' % ' // procedure // ': ' // & init_slots_pow_fail end if end if map % nbits = slots_bits else map % nbits = min( default_bits, max_bits ) end if slots = 2_int32**map % nbits map % index_mask = slots - 1 allocate( map % slots(0:slots-1), stat=stat, errmsg=errmsg ) if ( stat /= 0 ) then if ( present(status) ) then status = alloc_fault return else write(error_unit, '(a)') 'Allocation ERRMSG: ' // trim(errmsg) error stop submodule_name // ' % ' // procedure // ': ' // & alloc_slots_fault end if end if do i=0, size( map % slots, kind=int_index ) - 1 map % slots(i) = 0 ! May be redundant end do !! 5*s from Chase's g_new_map allocate( map % inverse(1:ceiling(load_factor*slots, & kind=int_index)), & stat=stat, & errmsg=errmsg ) if ( stat /= 0 ) then if ( present( status ) ) then status = alloc_fault return else write(error_unit, '(a)') 'Allocation ERRMSG: ' // trim(errmsg) error stop submodule_name // ' % ' // procedure // ': ' // & alloc_inv_fault end if end if do i=1, size(map % inverse, kind=int_index) map % inverse(i) % target => null() end do do while(associated(map % cache)) map_entry_pool_head => map % cache map % cache => map_entry_pool_head % lastpool map_entry_pool_head % lastpool => null() deallocate( map_entry_pool_head % more_map_entries ) deallocate( map_entry_pool_head ) end do call extend_map_entry_pool(map % cache) map % initialized = .true. if (present(status) ) status = success end subroutine init_open_map pure module function open_loading( map ) !! Version: Experimental !! !! Returns the number of entries relative to slots in a hash map !! Arguments: !! map - an open hash map class(open_hashmap_type), intent(in) :: map real :: open_loading open_loading = real( map % num_entries ) / & size( map % slots, kind=int_index ) end function open_loading module subroutine map_open_entry(map, key, other, conflict) !! Version: Experimental !! !! Inserts an entry into the hash table !! Arguments: !! map the hash table of interest !! key - the key identifying the entry !! other - other data associated with the key !! conflict - logical flag indicating whether the entry key conflicts !! with an existing key ! class(open_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), intent(in), optional :: other logical, intent(out), optional :: conflict type(open_map_entry_type), pointer :: new_ent integer(int_hash) :: base_slot integer(int_hash) :: hash_val integer(int_index) :: inmap, offset, test_slot character(*), parameter :: procedure = 'MAP_ENTRY' ! Check that map is initialized. if (.not. map % initialized) call init_open_map( map ) hash_val = map % hasher( key ) if ( map % probe_count > map_probe_factor * map % call_count .or. & map % num_entries >= load_factor * size( map % slots, & kind=int_index) ) then call expand_slots(map) end if map % call_count = map % call_count + 1 base_slot = fibonacci_hash( hash_val, map % nbits ) offset = 0 PROBE_SUCCESSIVE_SLOTS: do map % probe_count = map % probe_count + 1 test_slot = iand( base_slot + offset, map % index_mask ) inmap = map % slots(test_slot) if ( inmap == 0 ) then call allocate_open_map_entry(map, new_ent) new_ent % hash_val = hash_val call copy_key( key, new_ent % key ) if ( present( other ) ) new_ent % other = other inmap = new_ent % inmap map % inverse( inmap ) % target => new_ent map % slots( test_slot ) = inmap if ( present(conflict) ) conflict = .false. return else if ( inmap < 0 .or. & inmap > map % num_entries + map % num_free ) then error stop submodule_name // ' % ' // procedure // ': ' // & invalid_inmap else if (.not. associated( map % inverse(inmap) % target ) ) then error stop submodule_name // ' % ' // procedure // ': ' // & invalid_inmap else associate( target => map % inverse(inmap) % target ) if ( hash_val == target % hash_val ) then if ( key == target % key ) then ! entry already exists if ( present(conflict) ) then conflict = .true. else error stop submodule_name // ' % ' // procedure & // ': ' // conflicting_key end if return end if end if end associate end if offset = offset + 1 end do PROBE_SUCCESSIVE_SLOTS contains subroutine allocate_open_map_entry(map, bucket) ! allocates a hash bucket type(open_hashmap_type), intent(inout) :: map type(open_map_entry_type), pointer, intent(out) :: bucket type(open_map_entry_list), pointer :: free_list type(open_map_entry_pool), pointer :: pool character(*), parameter :: procedure_name = "ALLOCATE_MAP_ENTRY" pool => map % cache map % num_entries = map % num_entries + 1 if ( associated(map % free_list) ) then ! Get hash bucket from free_list free_list => map % free_list bucket => free_list % target map % free_list => free_list % next free_list % target => null() free_list % next => null() if (bucket % inmap <= 0) & error stop submodule_name // " % " // procedure_name // & ": Failed consistency check: BUCKET % INMAP <= 0" map % num_free = map % num_free - 1 else ! Get hash bucket from pool if ( pool % next == pool_size ) then ! Expand pool call extend_map_entry_pool(map % cache) pool => map % cache end if bucket => pool % more_map_entries(pool % next) pool % next = pool % next + 1 ! 0s based -> post-increment if ( map % num_entries > & size( map % inverse, kind=int_index ) ) then call expand_inverse( map ) end if if ( map % num_entries <= 0 ) & error stop submodule_name // " % " // procedure_name // & ": Failed consistency check: MAP % NUM_ENTRIES <= 0." bucket % inmap = map % num_entries end if end subroutine allocate_open_map_entry subroutine expand_inverse(map) !! Increase size of map % inverse type(open_hashmap_type), intent(inout) :: map type(open_map_entry_ptr), allocatable :: dummy_inverse(:) integer(int32) :: stat character(256) :: errmsg allocate( dummy_inverse(1:2*size(map % inverse, kind=int_index)), & stat=stat, errmsg=errmsg ) if ( stat /= 0 ) then write(error_unit, '(a)') 'Allocation ERRMSG: ' // trim(errmsg) error stop submodule_name // ' % ' // procedure // ': ' // & alloc_inv_fault end if dummy_inverse(1:size(map % inverse, kind=int_index)) = & map % inverse(:) call move_alloc( dummy_inverse, map % inverse ) end subroutine expand_inverse end subroutine map_open_entry module subroutine rehash_open_map( map, hasher ) !! Version: Experimental !! !! Changes the hashing method of the table entries to that of HASHER. !! Arguments: !! map the table to be rehashed !! hasher the hasher function to be used for the table ! class(open_hashmap_type), intent(inout) :: map procedure(hasher_fun) :: hasher integer(int_hash) :: base_slot integer(int_hash) :: hash_val integer(int_index) :: i, test_slot, offset map % hasher => hasher map % slots = 0 do i=1, map % num_entries + map % num_free if ( .not. associated( map % inverse(i) % target ) ) cycle hash_val = map % hasher( map % inverse(i) % target % key ) map % inverse(i) % target % hash_val = hash_val base_slot = fibonaccI_hash( hash_val, map % nbits ) offset = 0 FIND_EMPTY_SLOT: do test_slot = iand( int( base_slot + offset, int_hash ), & map % index_mask ) if ( map % slots(test_slot) == 0 ) then map % slots(test_slot) = i exit FIND_EMPTY_SLOT end if offset = offset + 1 end do FIND_EMPTY_SLOT end do end subroutine rehash_open_map module subroutine remove_open_entry(map, key, existed) !! Remove the entry, if any, that has the key !! Arguments: !! map - the table from which the entry is to be removed !! key - the key to an entry !! existed - a logical flag indicating whether an entry with the key !! was present in the original map ! class(open_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key logical, intent(out), optional :: existed type(open_map_entry_list), pointer :: aentry type(open_map_entry_type), pointer :: bucket integer(int_index) :: base_slot integer(int_index) :: current_index integer(int_index) :: current_slot integer(int_index) :: empty_slot integer(int_index) :: inmap logical :: overlap integer(int_index) :: slot_index overlap = .false. call in_open_map( map, inmap, key ) if ( inmap < 1 .or. inmap > size( map % inverse ) ) then if ( present( existed ) ) existed = .false. return end if bucket => map % inverse(inmap) % target if ( associated(bucket) ) then base_slot = fibonacci_hash( bucket % hash_val, map % nbits ) if ( present(existed) ) existed = .true. else if ( present( existed ) ) existed = .false. return end if ! Find slot associated with inmap and nullify the pointer current_slot = base_slot search_for_inmap: do slot_index = map % slots(current_slot) if ( slot_index == inmap ) then allocate(aentry) aentry % target => map % inverse(inmap) % target aentry % next => map % free_list map % free_list => aentry map % num_free = map % num_free + 1 map % slots( current_slot ) = 0 map % inverse(inmap) % target => null() map % num_entries = map % num_entries - 1 empty_slot = current_slot current_slot = iand( map % index_mask, current_slot + 1 ) if ( map % slots(current_slot) == 0 ) return if ( current_slot == 0 ) overlap = .true. exit search_for_inmap else if ( map % slots(current_slot) == 0 ) return current_slot = iand( map % index_mask, current_slot + 1 ) if ( current_slot == 0 ) overlap = .true. cycle search_for_inmap end if end do search_for_inmap ! Have found slot and stored it in free_list, now may need to iteratively ! swap to fill holes. First search backwards to find start of run. find_run_start: do base_slot = iand( map % index_mask, base_slot - 1 ) if ( base_slot == map % index_mask ) then if ( map % slots(base_slot) == 0 ) then base_slot = 0 exit find_run_start else overlap = .true. cycle find_run_start end if else if ( map % slots(base_slot) == 0 ) then base_slot = iand( map % index_mask, base_slot + 1 ) exit find_run_start else cycle find_run_start end if end do find_run_start ! Search forward for entry to fill empty slot fill_empty_slots: do bucket => map % inverse(map % slots(current_slot) ) % target current_index = fibonacci_hash( bucket % hash_val, & map % nbits ) if ( overlap .and. empty_slot < base_slot ) then if ( ( current_index >= base_slot .and. & current_index <= map % index_mask ) .or. & ( current_index >= 0 .and. & current_index <= empty_slot ) ) then map % slots( empty_slot ) = map % slots( current_slot ) map % slots( current_slot ) = 0 empty_slot = current_slot end if current_slot = iand( map % index_mask, current_slot + 1 ) else if ( current_index >= base_slot .and. & current_index <= empty_slot ) then map % slots( empty_slot ) = map % slots( current_slot ) map % slots( current_slot ) = 0 empty_slot = current_slot end if current_slot = iand( map % index_mask, current_slot + 1 ) if ( current_slot == 0 ) overlap = .true. end if if ( map % slots( current_slot ) == 0 ) exit fill_empty_slots end do fill_empty_slots end subroutine remove_open_entry module subroutine set_other_open_data( map, key, other, exists ) !! Version: Experimental !! !! Change the other data associated with the key !! Arguments: !! map - the map with the entry of interest !! key - the key to the entry inthe map !! other - the new data to be associated with the key !! exists - a logical flag indicating whether the key is already entered !! in the map ! class(open_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), intent(in) :: other logical, intent(out),optional :: exists integer(int_index) :: inmap character(*), parameter :: procedure = 'SET_OTHER_DATA' call in_open_map( map, inmap, key ) if ( inmap <= 0 .or. inmap > size( map % inverse, kind=int_index ) ) & then if ( present(exists) ) then exists = .false. return else error stop submodule_name // ' % ' // procedure // ': ' // & invalid_inmap end if else if ( associated( map % inverse(inmap) % target ) ) then map % inverse(inmap) % target % other = other if ( present(exists) ) exists = .true. return else error stop submodule_name // ' % ' // procedure // ': ' // & invalid_inmap end if end subroutine set_other_open_data module function total_open_depth( map ) result(total_depth) !! Version: Experimental !! !! Returns the total number of ones based offsets of slot entries from !! their slot index for a hash map !! Arguments: !! map - an open hash map class(open_hashmap_type), intent(in) :: map integer(int64) :: total_depth integer(int_index) :: inv_index, slot, slots integer(int_hash) :: index total_depth = 0_int64 slots = size( map % slots, kind=int_index ) do slot=0, slots-1 if ( map % slots( slot ) == 0 ) cycle inv_index = map % slots( slot ) if ( inv_index <= 0 ) cycle associate( inverse => map % inverse( inv_index )) index = fibonacci_hash( inverse % target % hash_val, & map % nbits ) end associate total_depth = total_depth + & iand( slot - index, map % index_mask ) + 1_int64 end do end function total_open_depth module subroutine open_key_test(map, key, present) !! Version: Experimental !! !! Returns a logical flag indicating whether KEY exists in the hash map !! Arguments: !! map - the hash map of interest !! key - the key of interest ! class(open_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key logical, intent(out) :: present integer(int_index) :: inmap call in_open_map( map, inmap, key ) if ( inmap <= 0 .or. inmap > size( map % inverse, kind=int_index ) ) & then present = .false. else present = associated( map % inverse(inmap) % target ) end if end subroutine open_key_test end submodule stdlib_hashmap_open fortran-lang-stdlib-0ede301/src/hashmaps/stdlib_hashmaps.f900000664000175000017500000013100515135654166024246 0ustar alastairalastair!! The module, STDLIB_HASH_MAPS, implements two hash maps: !! CHAINING_HASH_MAP_TYPE, a separate chaining hash map; and OPEN_HASH_MAP_TYPE, !! an open addressing hash map using linear addressing. The two hash maps are !! implementations of the abstract type, HASH_MAP_TYPE. module stdlib_hashmaps use, intrinsic :: iso_fortran_env, only: & character_storage_size, & error_unit use stdlib_kinds, only: & dp, & int8, & int16, & int32, & int64 use stdlib_hashmap_wrappers, only: & copy_key, & fibonacci_hash, & default_hasher => fnv_1_hasher, & hasher_fun, & operator(==), & set, & key_type, & int_hash implicit none private !! Public data_types public :: & chaining_hashmap_type, & open_hashmap_type !! Values that parameterize David Chase's empirical SLOT expansion code integer, parameter :: & inmap_probe_factor = 10, & map_probe_factor = 5 !! Values that parameterize the SLOTS table size integer, parameter, public :: & default_bits = 6, & max_bits = 30 !! KIND values used to parameterixe the hash map and its procedures integer, parameter, public :: & int_calls = int64, & int_depth = int64, & int_index = int32, & int_probes = int64 !! Error codes returned by the hash map procedures integer, parameter, public :: & success = 0, & alloc_fault = 1, & array_size_error = 2 ! The number of bits used by various types integer, parameter :: & ! Should be 8 int8_bits = bit_size(0_int8), & char_bits = character_storage_size !! The hash map load factor real, parameter, public :: & load_factor = 0.5625 !! The size of the pools of allocated map entries integer(int32), parameter :: pool_size = 64 character(*), parameter, private :: module_name = 'STDLIB_HASHMAPS' type, abstract :: hashmap_type !! Version: Experimental !! !! Type implementing an abstract hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#the-hashmap_type-abstract-type)) private integer(int_calls) :: call_count = 0 !! Number of calls integer(int_calls) :: probe_count = 0 !! Number of probes since last expansion integer(int_calls) :: total_probes = 0 !! Cumulative number of probes integer(int_index) :: num_entries = 0 !! Number of entries integer(int_index) :: num_free = 0 !! Number of elements in the free_list integer(int32) :: nbits = default_bits !! Number of bits used to address the slots procedure(hasher_fun), pointer, nopass :: hasher => default_hasher !! Hash function logical :: initialized = .false. contains procedure, non_overridable, pass(map) :: calls procedure, non_overridable, pass(map) :: entries procedure, non_overridable, pass(map) :: map_probes procedure, non_overridable, pass(map) :: num_slots procedure, non_overridable, pass(map) :: slots_bits procedure(get_all_keys), deferred, pass(map) :: get_all_keys procedure(init_map), deferred, pass(map) :: init procedure(loading), deferred, pass(map) :: loading procedure(rehash_map), deferred, pass(map) :: rehash procedure(total_depth), deferred, pass(map) :: total_depth !! Key_test procedures. procedure(key_key_test), deferred, pass(map) :: key_key_test procedure, non_overridable, pass(map) :: int8_key_test procedure, non_overridable, pass(map) :: int32_key_test procedure, non_overridable, pass(map) :: char_key_test generic, public :: key_test => key_key_test, int8_key_test, int32_key_test, char_key_test ! Map_entry procedures procedure(key_map_entry), deferred, pass(map) :: key_map_entry procedure, non_overridable, pass(map) :: int8_map_entry procedure, non_overridable, pass(map) :: int32_map_entry procedure, non_overridable, pass(map) :: char_map_entry generic, public :: map_entry => key_map_entry, int8_map_entry, int32_map_entry, char_map_entry ! Get_other_data procedures procedure(key_get_other_data), deferred, pass(map) :: key_get_other_data procedure, non_overridable, pass(map) :: int8_get_other_data procedure, non_overridable, pass(map) :: int32_get_other_data procedure, non_overridable, pass(map) :: char_get_other_data generic, public :: get_other_data => key_get_other_data, int8_get_other_data, int32_get_other_data, char_get_other_data ! Key_remove_entry procedures procedure(key_remove_entry), deferred, pass(map) :: key_remove_entry procedure, non_overridable, pass(map) :: int8_remove_entry procedure, non_overridable, pass(map) :: int32_remove_entry procedure, non_overridable, pass(map) :: char_remove_entry generic, public :: remove => key_remove_entry, int8_remove_entry, int32_remove_entry, char_remove_entry ! Set_other_data procedures procedure(key_set_other_data), deferred, pass(map) :: key_set_other_data procedure, non_overridable, pass(map) :: int8_set_other_data procedure, non_overridable, pass(map) :: int32_set_other_data procedure, non_overridable, pass(map) :: char_set_other_data generic, public :: set_other_data => key_set_other_data, int8_set_other_data, int32_set_other_data, char_set_other_data end type hashmap_type abstract interface subroutine get_all_keys(map, all_keys) !! Version: Experimental !! !! Returns the all keys contained in a hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#get_all_keys-returns-all-the-keys-contained-in-a-map)) !! !! Arguments: !! map - a hash map !! all_keys - all the keys contained in a hash map ! import hashmap_type, key_type class(hashmap_type), intent(in) :: map type(key_type), allocatable, intent(out) :: all_keys(:) end subroutine get_all_keys subroutine key_get_other_data( map, key, other, exists ) !! Version: Experimental !! !! Returns the other data associated with the inverse table index !! Arguments: !! map - a hash map !! key - the key associated with a map entry !! other - the other data associated with the key !! exists - a logical flag indicating whether an entry with that key exists ! import hashmap_type, key_type class(hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), allocatable, intent(out) :: other logical, intent(out), optional :: exists end subroutine key_get_other_data subroutine init_map( map, & hasher, & slots_bits, & status ) !! Version: Experimental !! !! Routine to allocate an empty map with HASHER as the hash function, !! 2**SLOTS_BITS initial SIZE(map % slots), SIZE(map % slots) limited to a !! maximum of 2**MAX_BITS, and with up to LOAD_FACTOR * SIZE(map % slots), !! map % inverse elements. All fields are initialized. !! Arguments: !! map - the hash maap to be initialized !! hasher - the hash function to be used to map keys to slots !! slots_bits - the number of bits initially used to map to the slots !! status - an integer error status flag with the allowed values: !! success - no problems were found !! alloc_fault - map % slots or map % inverse could not be allocated !! array_size_error - slots_bits or max_bits is less than !! default_bits or greater than strict_max_bits !! real_value_error - load_factor is less than 0.375 or greater than !! 0.875 ! import hashmap_type, hasher_fun, int32 class(hashmap_type), intent(out) :: map procedure(hasher_fun), optional :: hasher integer, intent(in), optional :: slots_bits integer(int32), intent(out), optional :: status end subroutine init_map subroutine key_key_test(map, key, present) !! Version: Experimental !! !! Returns a logical flag indicating whether KEY exists in the hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#key_test-indicates-whether-key-is-present)) !! !! Arguments: !! map - the hash map of interest !! key - the key of interest !! present - a flag indicating whether key is present in the map ! import hashmap_type, key_type class(hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key logical, intent(out) :: present end subroutine key_key_test pure function loading( map ) !! Version: Experimental !! !! Returns the number of entries relative to slots in a hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#loading-returns-the-ratio-of-entries-to-slots)) !! !! Arguments: !! map - a hash map import hashmap_type class(hashmap_type), intent(in) :: map real :: loading end function loading subroutine key_map_entry(map, key, other, conflict) !! Version: Experimental !! !! Inserts an entry into the hash table !! ([Specifications](../page/specs/stdlib_hashmaps.html#map_entry-inserts-an-entry-into-the-hash-map)) !! import hashmap_type, key_type class(hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), intent(in), optional :: other logical, intent(out), optional :: conflict end subroutine key_map_entry subroutine rehash_map( map, hasher ) !! Version: Experimental !! !! Changes the hashing method of the table entries to that of HASHER. !! Arguments: !! map the table to be rehashed !! hasher the hasher function to be used for the table ! import hashmap_type, hasher_fun class(hashmap_type), intent(inout) :: map procedure(hasher_fun) :: hasher end subroutine rehash_map subroutine key_remove_entry(map, key, existed) ! Chase's delent !! Version: Experimental !! !! Remove the entry, if any, that has the key !! Arguments: !! map - the table from which the entry is to be removed !! key - the key to an entry !! existed - a logical flag indicating whether an entry with the key !! was present in the original map ! import hashmap_type, key_type class(hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key logical, intent(out), optional :: existed end subroutine key_remove_entry subroutine key_set_other_data( map, key, other, exists ) !! Version: Experimental !! !! Change the other data associated with the key !! Arguments: !! map - the map with the entry of interest !! key - the key to the entry inthe map !! other - the new data to be associated with the key !! exists - a logical flag indicating whether the key is already entered !! in the map !! ! import hashmap_type, key_type class(hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), intent(in) :: other logical, intent(out), optional :: exists end subroutine key_set_other_data function total_depth( map ) !! Version: Experimental !! !! Returns the total number of ones based offsets of slot entriesyy from !! their slot index for a hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#total_depth-returns-the-total-depth-of-the-hash-map-entries)) !! Arguments: !! map - a hash map import hashmap_type, int64 class(hashmap_type), intent(in) :: map integer(int64) :: total_depth end function total_depth end interface !! API for the chaining_hashmap_type type :: chaining_map_entry_type ! Hash entry !! Version: Experimental !! !! Chaining hash map entry type !! ([Specifications](../page/specs/stdlib_hashmaps.html#the-chaining_map_entry_type-derived-type)) private integer(int_hash) :: hash_val !! Full hash value type(key_type) :: key !! The entry's key class(*), allocatable :: other !! Other entry data integer(int_index) :: inmap !! Index into inverse table type(chaining_map_entry_type), pointer :: next => null() !! Next bucket end type chaining_map_entry_type type chaining_map_entry_ptr !! Version: Experimental !! !! Wrapper for a pointer to a chaining map entry type object !! ([Specifications](../page/specs/stdlib_hashmaps.html#the-chaining_map_entry_type_ptr-derived-type)) type(chaining_map_entry_type), pointer :: target => null() end type chaining_map_entry_ptr type :: chaining_map_entry_pool !! Version: Experimental !! !! Type implementing a pool of allocated `chaining_map_entry_type` !! ([Specifications](../page/specs/stdlib_hashmaps.html#the-chaining_map_entry_pool-derived-type)) private ! Index of next bucket integer(int_index) :: next = 0 type(chaining_map_entry_type), allocatable :: more_map_entries(:) type(chaining_map_entry_pool), pointer :: lastpool => null() end type chaining_map_entry_pool type, extends(hashmap_type) :: chaining_hashmap_type !! Version: Experimental !! !! Type implementing the `chaining_hashmap_type` types !! ([Specifications](../page/specs/stdlib_hashmaps.html#the-chaining_hashmap_type-derived-type)) private type(chaining_map_entry_pool), pointer :: cache => null() !! Pool of allocated chaining_map_entry_type objects type(chaining_map_entry_type), pointer :: free_list => null() !! free list of map entries type(chaining_map_entry_ptr), allocatable :: inverse(:) !! Array of bucket lists (inverses) Note max_elts=size(inverse) type(chaining_map_entry_ptr), allocatable :: slots(:) !! Array of bucket lists Note # slots=size(slots) contains procedure :: get_all_keys => get_all_chaining_keys procedure :: key_get_other_data => get_other_chaining_data procedure :: init => init_chaining_map procedure :: loading => chaining_loading procedure :: key_map_entry => map_chain_entry procedure :: rehash => rehash_chaining_map procedure :: key_remove_entry => remove_chaining_entry procedure :: key_set_other_data => set_other_chaining_data procedure :: total_depth => total_chaining_depth procedure :: key_key_test => chaining_key_test final :: free_chaining_map end type chaining_hashmap_type interface module subroutine free_chaining_map( map ) !! Version: Experimental !! !! Frees internal memory of an chaining map !! Arguments: !! map - the chaining hash map whose memory is to be freed ! type(chaining_hashmap_type), intent(inout) :: map end subroutine free_chaining_map module subroutine get_all_chaining_keys(map, all_keys) !! Version: Experimental !! !! Returns all the keys contained in a hashmap !! Arguments: !! map - an chaining hash map !! all_keys - all the keys contained in a hash map ! class(chaining_hashmap_type), intent(in) :: map type(key_type), allocatable, intent(out) :: all_keys(:) end subroutine get_all_chaining_keys module subroutine get_other_chaining_data( map, key, other, exists ) !! Version: Experimental !! !! Returns the other data associated with the inverse table index !! Arguments: !! map - a chaining hash table !! key - the key associated with a map entry !! other - the other data associated with the key !! exists - a logical flag indicating whether an entry with that key exists ! class(chaining_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), allocatable, intent(out) :: other logical, intent(out), optional :: exists end subroutine get_other_chaining_data module subroutine init_chaining_map( map, & hasher, & slots_bits, & status ) !! Version: Experimental !! !! Routine to allocate an empty map with HASHER as the hash function, !! 2**SLOTS_BITS initial SIZE(map % slots), and SIZE(map % slots) limited !! to a maximum of 2**MAX_BITS. All fields are initialized. !! Arguments: !! map - the chaining hash map to be initialized !! hasher - the hash function to be used to map keys to slots !! slots_bits - the bits of two used to initialize the number of slots !! status - an integer error status flag with the allowed values: !! success - no problems were found !! alloc_fault - map % slots or map % inverse could not be allocated !! array_size_error - slots_bits is less than default_bits or !! greater than max_bits ! class(chaining_hashmap_type), intent(out) :: map procedure(hasher_fun), optional :: hasher integer, intent(in), optional :: slots_bits integer(int32), intent(out), optional :: status end subroutine init_chaining_map module subroutine chaining_key_test(map, key, present) !! Version: Experimental !! !! Returns a logical flag indicating whether KEY is present in the hash map !! Arguments: !! map - the hash map of interest !! key - the key of interest !! present - a logical flag indicating whether key is present in map ! class(chaining_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key logical, intent(out) :: present end subroutine chaining_key_test pure module function chaining_loading( map ) !! Version: Experimental !! !! Returns the number of entries relative to slots in a hash map !! Arguments: !! map - a chaining hash map class(chaining_hashmap_type), intent(in) :: map real :: chaining_loading end function chaining_loading module subroutine map_chain_entry(map, key, other, conflict) ! ! Inserts an entry innto the hash map ! Arguments: !! map - the hash table of interest !! key - the key identifying the entry !! other - other data associated with the key !! conflict - logical flag indicating whether the entry key conflicts !! with an existing key ! class(chaining_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), intent(in), optional :: other logical, intent(out), optional :: conflict end subroutine map_chain_entry module subroutine rehash_chaining_map( map, hasher ) !! Version: Experimental !! !! Changes the hashing method of the table entries to that of HASHER. !! Arguments: !! map the table to be rehashed !! hasher the hasher function to be used for the table ! class(chaining_hashmap_type), intent(inout) :: map procedure(hasher_fun) :: hasher end subroutine rehash_chaining_map module subroutine remove_chaining_entry(map, key, existed) !! Version: Experimental !! !! Remove the entry, if any, that has the key !! Arguments: !! map - the table from which the entry is to be removed !! key - the key to an entry !! existed - a logical flag indicating whether an entry with the key !! was present in the original map ! class(chaining_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key logical, intent(out), optional :: existed end subroutine remove_chaining_entry module subroutine set_other_chaining_data( map, key, other, exists ) !! Version: Experimental !! !! Change the other data associated with the key !! Arguments: !! map - the map with the entry of interest !! key - the key to the entry inthe map !! other - the new data to be associated with the key !! exists - a logical flag indicating whether the key is already entered !! in the map ! class(chaining_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), intent(in) :: other logical, intent(out), optional :: exists end subroutine set_other_chaining_data module function total_chaining_depth( map ) result(total_depth) !! Version: Experimental !! !! Returns the total number of ones based offsets of slot entries from !! their slot index for a hash map !! Arguments: !! map - an chaining hash map class(chaining_hashmap_type), intent(in) :: map integer(int_depth) :: total_depth end function total_chaining_depth end interface !! API for the open_hashmap_type type :: open_map_entry_type !! Version: Experimental !! !! Open hash map entry type !! ([Specifications](../page/specs/stdlib_hashmaps.html#the-open_map_entry_type-derived-type)) private integer(int_hash) :: hash_val !! Full hash value type(key_type) :: key !! Hash entry key class(*), allocatable :: other !! Other entry data integer(int_index) :: inmap !! Index into inverse table end type open_map_entry_type type :: open_map_entry_list !! Version: Experimental !! !! Open hash map entry type private type(open_map_entry_type), pointer :: target => null() type(open_map_entry_list), pointer :: next => null() end type open_map_entry_list type open_map_entry_ptr !! Version: Experimental !! !! Wrapper for a pointer to an open hash map entry type object !! ([Specifications](../page/specs/stdlib_hashmaps.html#the-open_map_entry_ptr-derived-type)) type(open_map_entry_type), pointer :: target => null() end type open_map_entry_ptr type :: open_map_entry_pool !! Version: Experimental !! !! Type implementing a pool of allocated `open_map_entry_type` private integer(int_index) :: next = 0 !! Index of next bucket type(open_map_entry_type), allocatable :: more_map_entries(:) type(open_map_entry_pool), pointer :: lastpool => null() end type open_map_entry_pool type, extends(hashmap_type) :: open_hashmap_type !! Version: Experimental !! !! Type implementing an "open" hash map private integer(int_index) :: index_mask = 2_int_index**default_bits-1 !! Mask used in linear addressing type(open_map_entry_pool), pointer :: cache => null() !! Pool of allocated open_map_entry_type objects type(open_map_entry_list), pointer :: free_list => null() !! free list of map entries type(open_map_entry_ptr), allocatable :: inverse(:) !! Array of bucket lists (inverses) Note max_elts=size(inverse) integer(int_index), allocatable :: slots(:) !! Array of indices to the inverse Note # slots=size(slots) contains procedure :: get_all_keys => get_all_open_keys procedure :: key_get_other_data => get_other_open_data procedure :: init => init_open_map procedure :: loading => open_loading procedure :: key_map_entry => map_open_entry procedure :: rehash => rehash_open_map procedure :: key_remove_entry => remove_open_entry procedure :: key_set_other_data => set_other_open_data procedure :: total_depth => total_open_depth procedure :: key_key_test => open_key_test final :: free_open_map end type open_hashmap_type interface module subroutine free_open_map( map ) !! Version: Experimental !! !! Frees internal memory of an open map !! Arguments: !! map - the open hash map whose memory is to be freed ! type(open_hashmap_type), intent(inout) :: map end subroutine free_open_map module subroutine get_all_open_keys(map, all_keys) !! Version: Experimental !! !! Returns all the keys contained in a hashmap !! Arguments: !! map - an open hash map !! all_keys - all the keys contained in a hash map ! class(open_hashmap_type), intent(in) :: map type(key_type), allocatable, intent(out) :: all_keys(:) end subroutine get_all_open_keys module subroutine get_other_open_data( map, key, other, exists ) !! Version: Experimental !! !! Returns the other data associated with the inverse table index !! Arguments: !! map - an open hash table !! key - the key associated with a map entry !! other - the other data associated with the key !! exists - a logical flag indicating whether an entry with that key exists ! class(open_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), allocatable, intent(out) :: other logical, intent(out), optional :: exists end subroutine get_other_open_data module subroutine init_open_map( map, & hasher, & slots_bits, & status ) !! Version: Experimental !! !! Routine to allocate an empty map with HASHER as the hash function, !! 2**SLOTS_BITS initial SIZE(map % slots), and SIZE(map % slots) limited to a !! maximum of 2**MAX_BITS. All fields are initialized. !! Arguments: !! map - the open hash maap to be initialized !! hasher - the hash function to be used to map keys to slots !! slots_bits - the number of bits used to map to the slots !! status - an integer error status flag with the allowed values: !! success - no problems were found !! alloc_fault - map % slots or map % inverse could not be allocated !! array_size_error - slots_bits is less than default_bitd or !! greater than max_bits class(open_hashmap_type), intent(out) :: map procedure(hasher_fun), optional :: hasher integer, intent(in), optional :: slots_bits integer(int32), intent(out), optional :: status end subroutine init_open_map module subroutine open_key_test(map, key, present) !! Version: Experimental !! !! Returns a logical flag indicating whether KEY exists in the hash map !! Arguments: !! map - the hash map of interest !! key - the key of interest !! present - a logical flag indicating whether KEY exists in the hash map ! class(open_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key logical, intent(out) :: present end subroutine open_key_test pure module function open_loading( map ) !! Version: Experimental !! !! Returns the number of entries relative to slots in a hash map !! Arguments: !! map - an open hash map class(open_hashmap_type), intent(in) :: map real :: open_loading end function open_loading module subroutine map_open_entry(map, key, other, conflict) !! Version: Experimental !! !! Inserts an entry into the hash table !! Arguments: !! map - the hash table of interest !! key - the key identifying the entry !! other - other data associated with the key !! conflict - logical flag indicating whether the entry key conflicts !! with an existing key ! class(open_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), intent(in), optional :: other logical, intent(out), optional :: conflict end subroutine map_open_entry module subroutine rehash_open_map( map, hasher ) !! Version: Experimental !! !! Changes the hashing method of the table entries to that of HASHER. !! Arguments: !! map the table to be rehashed !! hasher the hasher function to be used for the table ! class(open_hashmap_type), intent(inout) :: map procedure(hasher_fun) :: hasher end subroutine rehash_open_map module subroutine remove_open_entry(map, key, existed) !! Remove the entry, if any, that has the key !! Arguments: !! map - the table from which the entry is to be removed !! key - the key to an entry !! existed - a logical flag indicating whether an entry with the key !! was present in the original map ! class(open_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key logical, intent(out), optional :: existed end subroutine remove_open_entry module subroutine set_other_open_data( map, key, other, exists ) !! Version: Experimental !! !! Change the other data associated with the key !! Arguments: !! map - the map with the entry of interest !! key - the key to the entry inthe map !! other - the new data to be associated with the key !! exists - a logical flag indicating whether the key is already entered !! in the map ! class(open_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), intent(in) :: other logical, intent(out), optional :: exists end subroutine set_other_open_data module function total_open_depth( map ) result(total_depth) !! Version: Experimental !! !! Returns the total number of ones based offsets of slot entries from !! their slot index for a hash map !! Arguments: !! map - an open hash map class(open_hashmap_type), intent(in) :: map integer(int64) :: total_depth end function total_open_depth end interface contains subroutine int8_get_other_data( map, value, other, exists ) !! Version: Experimental !! !! Int8 key generic interface for get_other_data function class(hashmap_type), intent(inout) :: map integer(int8), intent(in) :: value(:) class(*), allocatable, intent(out) :: other logical, intent(out), optional :: exists type(key_type) :: key call set( key, value ) call map % key_get_other_data( key, other, exists ) end subroutine int8_get_other_data subroutine int32_get_other_data( map, value, other, exists ) !! Version: Experimental !! !! Int32 key generic interface for get_other_data function class(hashmap_type), intent(inout) :: map integer(int32), intent(in) :: value(:) class(*), allocatable, intent(out) :: other logical, intent(out), optional :: exists type(key_type) :: key call set( key, value ) call map % key_get_other_data( key, other, exists ) end subroutine int32_get_other_data subroutine char_get_other_data( map, value, other, exists ) !! Version: Experimental !! !! Character key generic interface for get_other_data function class(hashmap_type), intent(inout) :: map character(*), intent(in) :: value class(*), allocatable, intent(out) :: other logical, intent(out), optional :: exists type(key_type) :: key call set( key, value ) call map % key_get_other_data( key, other, exists ) end subroutine char_get_other_data subroutine int8_remove_entry(map, value, existed) ! Chase's delent !! Version: Experimental !! !! Remove the entry, if any, that has the key !! Arguments: !! map - the table from which the entry is to be removed !! value - the int8 array key to an entry !! existed - a logical flag indicating whether an entry with the key !! was present in the original map ! class(hashmap_type), intent(inout) :: map integer(int8), intent(in) :: value(:) logical, intent(out), optional :: existed type(key_type) :: key call set( key, value ) call map % key_remove_entry( key, existed ) end subroutine int8_remove_entry subroutine int32_remove_entry(map, value, existed) ! Chase's delent !! Version: Experimental !! !! Remove the entry, if any, that has the key !! Arguments: !! map - the table from which the entry is to be removed !! key - the key to an entry !! existed - a logical flag indicating whether an entry with the key !! was present in the original map ! class(hashmap_type), intent(inout) :: map integer(int32), intent(in) :: value(:) logical, intent(out), optional :: existed type(key_type) :: key call set( key, value ) call map % key_remove_entry( key, existed ) end subroutine int32_remove_entry subroutine char_remove_entry(map, value, existed) ! Chase's delent !! Version: Experimental !! !! Remove the entry, if any, that has the key !! Arguments: !! map - the table from which the entry is to be removed !! key - the key to an entry !! existed - a logical flag indicating whether an entry with the key !! was present in the original map ! class(hashmap_type), intent(inout) :: map character(*), intent(in) :: value logical, intent(out), optional :: existed type(key_type) :: key call set( key, value ) call map % key_remove_entry( key, existed ) end subroutine char_remove_entry subroutine int8_map_entry(map, value, other, conflict) !! Version: Experimental !! Int8 generic interface for map entry !! ([Specifications](../page/specs/stdlib_hashmaps.html#map_entry-inserts-an-entry-into-the-hash-map)) !! class(hashmap_type), intent(inout) :: map integer(int8), intent(in) :: value(:) class(*), intent(in), optional :: other logical, intent(out), optional :: conflict type(key_type) :: key call set( key, value ) call map % key_map_entry( key, other, conflict ) end subroutine int8_map_entry subroutine int32_map_entry(map, value, other, conflict) !! Version: Experimental !! !! Inserts an entry into the hash table !! ([Specifications](../page/specs/stdlib_hashmaps.html#map_entry-inserts-an-entry-into-the-hash-map)) !! class(hashmap_type), intent(inout) :: map integer(int32), intent(in) :: value(:) class(*), intent(in), optional :: other logical, intent(out), optional :: conflict type(key_type) :: key call set( key, value ) call map % key_map_entry( key, other, conflict ) end subroutine int32_map_entry subroutine char_map_entry(map, value, other, conflict) !! Version: Experimental !! !! Inserts an entry into the hash table !! ([Specifications](../page/specs/stdlib_hashmaps.html#map_entry-inserts-an-entry-into-the-hash-map)) !! class(hashmap_type), intent(inout) :: map character(len=*), intent(in) :: value class(*), intent(in), optional :: other logical, intent(out), optional :: conflict type(key_type) :: key call set( key, value ) call map % key_map_entry( key, other, conflict ) end subroutine char_map_entry subroutine int8_key_test(map, value, present) !! Version: Experimental !! !! Returns a logical flag indicating whether KEY exists in the hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#key_test-indicates-whether-key-is-present)) !! !! Arguments: !! map - the hash map of interest !! value - int8 array that is the key to lookup. !! present - a flag indicating whether key is present in the map ! class(hashmap_type), intent(inout) :: map integer(int8), intent(in) :: value(:) logical, intent(out) :: present type(key_type) :: key ! Generate key from int8 array. call set( key, value ) ! Call key test procedure. call map % key_key_test( key, present ) end subroutine int8_key_test subroutine int32_key_test(map, value, present) !! Version: Experimental !! !! Returns a logical flag indicating whether KEY exists in the hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#key_test-indicates-whether-key-is-present)) !! !! Arguments: !! map - the hash map of interest !! value - int32 array that is the key to lookup. !! present - a flag indicating whether key is present in the map ! class(hashmap_type), intent(inout) :: map integer(int32), intent(in) :: value(:) logical, intent(out) :: present type(key_type) :: key call set( key, value ) call map % key_key_test( key, present ) end subroutine int32_key_test subroutine char_key_test(map, value, present) !! Version: Experimental !! !! Returns a logical flag indicating whether KEY exists in the hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#key_test-indicates-whether-key-is-present)) !! !! Arguments: !! map - the hash map of interest !! value - char array that is the key to lookup. !! present - a flag indicating whether key is present in the map ! class(hashmap_type), intent(inout) :: map character(*), intent(in) :: value logical, intent(out) :: present type(key_type) :: key call set( key, value ) call map % key_key_test( key, present ) end subroutine char_key_test subroutine int8_set_other_data( map, value, other, exists ) !! Version: Experimental !! !! Change the other data associated with the key !! Arguments: !! map - the map with the entry of interest !! value - the int8 array key to the entry inthe map !! other - the new data to be associated with the key !! exists - a logical flag indicating whether the key is already entered !! in the map !! ! class(hashmap_type), intent(inout) :: map integer(int8), intent(in) :: value(:) class(*), intent(in) :: other logical, intent(out), optional :: exists type(key_type) :: key call set( key, value ) call map % key_set_other_data( key, other, exists ) end subroutine int8_set_other_data subroutine int32_set_other_data( map, value, other, exists ) !! Version: Experimental !! !! Change the other data associated with the key !! Arguments: !! map - the map with the entry of interest !! value - the int32 array key to the entry inthe map !! other - the new data to be associated with the key !! exists - a logical flag indicating whether the key is already entered !! in the map !! ! class(hashmap_type), intent(inout) :: map integer(int32), intent(in) :: value(:) class(*), intent(in) :: other logical, intent(out), optional :: exists type(key_type) :: key call set( key, value ) call map % key_set_other_data( key, other, exists ) end subroutine int32_set_other_data subroutine char_set_other_data( map, value, other, exists ) !! Version: Experimental !! !! Change the other data associated with the key !! Arguments: !! map - the map with the entry of interest !! value - the char value key to the entry inthe map !! other - the new data to be associated with the key !! exists - a logical flag indicating whether the key is already entered !! in the map !! ! class(hashmap_type), intent(inout) :: map character(*), intent(in) :: value class(*), intent(in) :: other logical, intent(out), optional :: exists type(key_type) :: key call set( key, value ) call map % key_set_other_data( key, other, exists ) end subroutine char_set_other_data pure function calls( map ) !! Version: Experimental !! !! Returns the number of subroutine calls on an open hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#calls-returns-the-number-of-calls-on-the-hash-map)) !! !! Arguments: !! map - an open hash map class(hashmap_type), intent(in) :: map integer(int_calls) :: calls calls = map % call_count end function calls pure function entries( map ) !! Version: Experimental !! !! Returns the number of entries in a hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#entries-returns-the-number-of-entries-in-the-hash-map)) !! !! Arguments: !! map - an open hash map class(hashmap_type), intent(in) :: map integer(int_index) :: entries entries = map % num_entries end function entries pure function map_probes( map ) !! Version: Experimental !! !! Returns the total number of table probes on a hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#map_probes-returns-the-number-of-hash-map-probes)) !! !! Arguments: !! map - an open hash map class(hashmap_type), intent(in) :: map integer(int_calls) :: map_probes map_probes = map % total_probes + map % probe_count end function map_probes pure function num_slots( map ) !! Version: Experimental !! !! Returns the number of allocated slots in a hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#num_slots-returns-the-number-of-hash-map-slots)) !! !! Arguments: !! map - an open hash map class(hashmap_type), intent(in) :: map integer(int_index) :: num_slots num_slots = 2**map % nbits end function num_slots pure function slots_bits( map ) !! Version: Experimental !! !! Returns the number of bits used to specify the number of allocated !! slots in a hash map !! ([Specifications](../page/specs/stdlib_hashmaps.html#slots_bits-returns-the-number-of-bits-used-to-address-the-hash-map-slots)) !! !! Arguments: !! map - an open hash map class(hashmap_type), intent(in) :: map integer :: slots_bits slots_bits = map % nbits end function slots_bits end module stdlib_hashmaps fortran-lang-stdlib-0ede301/src/hashmaps/stdlib_hashmap_chaining.f900000664000175000017500000007724515135654166025742 0ustar alastairalastair!! The module STDLIB_HASHMAP_CHAINING implements a simple separate !! chaining hash map. The implementation is loosely based on a C !! implementation by David Chase, http://chasewoerner.org/src/hasht/, for !! which he has given permission to use in the Fortran Standard Library. ! Note an error in the code caused attempts to deallocate already deallocated ! entries. This did not cause stat to be non-zero, but did cause system errors, ! on my Mac. I therefore decided to remove all deallocation error reporting. submodule(stdlib_hashmaps) stdlib_hashmap_chaining !! Version: Experimental !! !! Implements a simple separate chaining hash map. implicit none ! Error messages character(len=*), parameter :: & alloc_inv_fault = "CHAINING_HASHMAP_TYPE % INVERSE allocation " // & "fault.", & alloc_slots_fault = "CHAINING_HASHMAP_TYPE % SLOTS allocation " // & "fault.", & conflicting_key = "KEY already exists in MAP.", & expand_slots_fail = "CHAINING_HASHMAP_TYPE % SLOTS allocation > " // & "max bits.", & init_slots_pow_fail = "SLOT_BITS is not between DEFAULT_BITS " // & "and MAX_BITS.", & invalid_inmap = "INMAP was not a valid INVERSE index.", & map_consist_fault = "The hash map found a inconsistency." character(len=*), parameter :: submodule_name = "STDLIB_HASHMAP_CHAINING" interface expand_slots !! Version: Experimental !! !! Interface to internal procedure that expands the number of map slots. module procedure expand_chaining_slots end interface expand_slots interface extend_map_entry_pool !! Version: Experimental !! !! Interface to internal procedure that expands a chaining map entry pool. module procedure extend_chaining_map_entry_pool end interface extend_map_entry_pool interface free_map !! Version: Experimental !! !! Interface to procedure that finalizes a chaining hash map. module procedure free_chaining_map end interface free_map interface free_map_entry_pool !! Version: Experimental !! !! Interface to internal procedure that finalizes a chaining hash map !! entry pool. module procedure free_map_entry_pool end interface free_map_entry_pool interface get_other_data !! Version: Experimental !! !! Interface to procedure that gets an entry's other data. module procedure get_other_chaining_data end interface get_other_data interface init !! Version: Experimental !! !! Interface to initialization procedure for a chaining hash map. module procedure init_chaining_map end interface init interface rehash !! Version: Experimental !! !! Interface to a procedure that changes the hash function that !! is used to map the keys into a chaining hash map. module procedure rehash_chaining_map end interface rehash interface remove !! Version: Experimental !! !! Interface to a procedure that removes the entry associated with a key module procedure remove_chaining_entry ! Chase's delent end interface remove interface set_other_data !! Version: Experimental !! !! Interface to a procedure that changes the other data associated with a key module procedure set_other_chaining_data end interface set_other_data contains ! Internal routine to make a duplicate map with more hash slots. ! Note David Chase had pointer returning functions, but the logic did not ! depend on the result value subroutine expand_chaining_slots( map ) !! Version: Experimental !! !! Internal routine to make a duplicate map with more hash slots. !! Doubles the size of the map % slots array !! Arguments: !! map - the hash map whose hash slots are to be expanded ! type(chaining_hashmap_type), intent(inout) :: map type(chaining_map_entry_type), pointer :: current_entry type(chaining_map_entry_ptr), allocatable :: dummy_slots(:) integer(int_index) :: min_size, new_size integer(int_index) :: old_size, & slot_index integer(int32) :: bits, & stat character(256) :: errmsg character(*), parameter :: procedure = 'EXPAND_SLOTS' if ( map % nbits == max_bits ) then error stop submodule_name // ' % ' // procedure // ': ' // & expand_slots_fail end if old_size = size(map % slots, kind=int_index) determine_new_size: if ( map % num_entries <= old_size ) then ! Expand by factor of two to improve efficiency new_size = 2*old_size bits = map % nbits + 1 else ! Expand so the number of slots is no more than 2**max_bits but otherwise ! at least the number of entries min_size = map % num_entries new_size = old_size bits = map % nbits do bits = bits + 1 new_size = new_size * 2 if ( bits >= max_bits .OR. new_size >= min_size ) exit end do end if determine_new_size allocate( dummy_slots(0:new_size-1), stat=stat, errmsg=errmsg ) if (stat /= 0) then write(error_unit, '(a)') 'Allocation ERRMSG: ' // trim(errmsg) error stop submodule_name // ' % ' // procedure // ': ' // & alloc_slots_fault end if map % nbits = bits do slot_index=0, new_size-1 dummy_slots(slot_index) % target => null() ! May be redundant end do map % total_probes = map % total_probes + map % probe_count map % probe_count = 0 ! This maps old slots entries to new slots, but we could also map inverse ! entries to new_slots do slot_index=0, old_size-1 do while( associated(map % slots(slot_index) % target) ) current_entry => map % slots(slot_index) % target map % slots(slot_index) % target => current_entry % next call remap( dummy_slots, current_entry, map % nbits ) end do end do call move_alloc( dummy_slots, map % slots ) contains subroutine remap(slots, gentry, bits) type(chaining_map_entry_ptr), intent(inout) :: slots(0:) type(chaining_map_entry_type), intent(inout), target :: gentry integer(int_hash), intent(in) :: bits integer(int_index) :: hash_index type(chaining_map_entry_type), pointer :: where_loc hash_index = fibonacci_hash( gentry % hash_val, bits ) where_loc => slots(hash_index) % target gentry % next => null() ! May be redundant if ( associated( where_loc ) ) then do while ( associated(where_loc % next) ) where_loc => where_loc % next end do where_loc % next => gentry else slots(hash_index) % target => gentry end if end subroutine remap end subroutine expand_chaining_slots subroutine extend_chaining_map_entry_pool(map) ! gent_pool_new !! Version: Experimental !! !! Add more map_entrys to the pool head !! Arguments: !! pool - a chaining map entry pool type(chaining_hashmap_type), intent(inout) :: map type(chaining_map_entry_pool), pointer :: pool allocate(pool) allocate(pool % more_map_entries(0:pool_size-1)) pool % next = 0 ! may be redundant pool % lastpool => map % cache map % cache => pool end subroutine extend_chaining_map_entry_pool ! Internal final routine to free a map and its memory module subroutine free_chaining_map( map ) !! Version: Experimental !! !! Frees internal memory of an chaining map !! Arguments: !! map - the chaining hash map whose memory is to be freed ! type(chaining_hashmap_type), intent(inout) :: map integer(int_index) :: i type(chaining_map_entry_type), pointer :: next if ( allocated( map % slots ) ) then remove_slot_links: do i=0, size( map % slots ) - 1 if ( associated( map % slots(i) % target ) ) then map % slots(i) % target => null() end if end do remove_slot_links deallocate( map % slots ) end if if ( allocated( map % inverse) ) then remove_links: do i=1, size( map % inverse, kind=int_index ) if ( associated( map % inverse(i) % target ) ) then map % inverse(i) % target % next => null() end if map % inverse(i) % target => null() end do remove_links deallocate( map % inverse ) end if free_free_list: do if ( associated( map % free_list) ) then next => map % free_list % next map % free_list => next cycle free_free_list else map % num_free = 0 exit free_free_list end if end do free_free_list if ( associated( map % cache ) ) call free_map_entry_pool(map % cache) map % num_entries = 0 end subroutine free_chaining_map recursive subroutine free_map_entry_pool(pool) ! gent_pool_free !! Version: Experimental !! !! Recursively descends map entry pool list freeing each element !! Arguments: !! pool The map entry pool whose elements are to be freed ! type(chaining_map_entry_pool), intent(inout), pointer :: pool if ( .not. associated(pool) ) return call free_map_entry_pool(pool % lastpool) deallocate( pool ) end subroutine free_map_entry_pool module subroutine get_all_chaining_keys(map, all_keys) !! Version: Experimental !! !! Returns all the keys contained in a hash map !! Arguments: !! map - a chaining hash map !! all_keys - all the keys contained in a hash map ! class(chaining_hashmap_type), intent(in) :: map type(key_type), allocatable, intent(out) :: all_keys(:) integer(int32) :: num_keys integer(int_index) :: i, key_idx num_keys = map % entries() allocate( all_keys(num_keys) ) if ( num_keys == 0 ) return if( allocated( map % inverse ) ) then key_idx = 1_int_index do i=1_int_index, size( map % inverse, kind=int_index ) if ( associated( map % inverse(i) % target ) ) then all_keys(key_idx) = map % inverse(i) % target % key key_idx = key_idx + 1_int_index end if end do end if end subroutine get_all_chaining_keys module subroutine get_other_chaining_data( map, key, other, exists ) !! Version: Experimental !! !! Returns the other data associated with the inverse table index !! Arguments: !! map - a chaining hash map !! key - the key associated with a map entry !! other - the other data associated with the key !! exists - a logical flag indicating whether an entry with that key exists ! class(chaining_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), allocatable, intent(out) :: other logical, intent(out), optional :: exists integer(int_index) :: inmap character(*), parameter :: procedure = 'GET_OTHER_DATA' call in_chain_map(map, inmap, key) if ( inmap <= 0 .or. & inmap > size(map % inverse, kind=int_index ) ) then if ( present(exists) ) then exists = .false. return else error stop submodule_name // ' % ' // procedure // ': ' // & invalid_inmap end if else if ( associated( map % inverse(inmap) % target ) ) then if (present(exists) ) exists = .true. other = map % inverse(inmap) % target % other else if ( present(exists) ) then exists = .false. return else error stop submodule_name // ' % ' // procedure // ': ' // & map_consist_fault end if end if end subroutine get_other_chaining_data subroutine in_chain_map(map, inmap, key) !! Version: Experimental !! !! Returns the index into the INVERSE array associated with the KEY !! Arguments: !! map - the hash map of interest !! inmap - the returned index into the INVERSE array of entry pointers. !! A value of zero indicates that an entry with that key was not !! found. !! key - the key identifying the entry of interest ! class(chaining_hashmap_type), intent(inout) :: map integer(int_index), intent(out) :: inmap type(key_type), intent(in) :: key integer(int_hash) :: hash_val, hash_index type(chaining_map_entry_type), pointer :: gentry, pentry, sentry if ( map % probe_count > inmap_probe_factor * map % call_count ) then if ( map % nbits < max_bits .AND. & map % num_entries > size( map % slots, kind=int_index ) ) then call expand_slots(map) end if end if map % call_count = map % call_count + 1 hash_val = map % hasher( key ) hash_index = fibonacci_hash( hash_val, map % nbits ) pentry => map % slots(hash_index) % target sentry => pentry climb_chain: do gentry => pentry map % probe_count = map % probe_count + 1 if (.not. associated( gentry ) ) then inmap = 0 return else if ( hash_val == gentry % hash_val ) then if ( key == gentry % key ) then ! The swap to front seems to confuse gfortran's pointers ! if ( .not. associated( pentry, sentry ) ) then ! ! swap to front ! pentry => gentry % next ! gentry % next => sentry ! sentry => gentry ! end if inmap = gentry % inmap return end if end if pentry => gentry % next end do climb_chain end subroutine in_chain_map module subroutine init_chaining_map( map, & hasher, & slots_bits, & status ) !! Version: Experimental !! !! Routine to allocate an empty map with HASHER as the hash function, !! 2**SLOTS_BITS initial SIZE(map % slots), and SIZE(map % slots) limited !! to a maximum of 2**MAX_BITS. All fields are initialized. !! Arguments: !! map - the chaining hash map to be initialized !! hasher - the hash function to be used to map keys to slots !! slots_bits - the bits of two used to initialize the number of slots !! status - an integer error status flag with the allowed values: !! success - no problems were found !! alloc_fault - map % slots or map % inverse could not be allocated !! array_size_error - slots_bits is less than default_bits or !! greater than max_bits ! class(chaining_hashmap_type), intent(out) :: map procedure(hasher_fun), optional :: hasher integer, intent(in), optional :: slots_bits integer(int32), intent(out), optional :: status character(256) :: errmsg integer(int_index) :: index character(*), parameter :: procedure = 'INIT' integer(int_index) :: slots integer(int32) :: stat map % call_count = 0 map % probe_count = 0 map % total_probes = 0 ! Check if user has specified a hasher other than the default hasher. if (present(hasher)) map % hasher => hasher call free_chaining_map( map ) if ( present(slots_bits) ) then if ( slots_bits < 6 .OR. slots_bits > max_bits ) then if ( present(status) ) then status = array_size_error return else error stop submodule_name // ' % ' // procedure // ': ' // & init_slots_pow_fail end if end if map % nbits = slots_bits else map % nbits = min( default_bits, max_bits ) end if slots = 2_int_index**map % nbits allocate( map % slots(0:slots-1), stat=stat, errmsg=errmsg ) if ( stat /= 0 ) then if ( present(status) ) then status = alloc_fault return else write(error_unit, '(a)') 'Allocation ERRMSG: ' // trim(errmsg) error stop submodule_name // ' % ' // procedure // ': ' // & alloc_slots_fault end if end if do index = 0, size( map % slots, kind=int_index )-1 map % slots(index) % target => null() ! May be redundant end do ! 5*s from Chase's g_new_map allocate( map % inverse(1:slots), stat=stat, errmsg=errmsg ) if ( stat /= 0 ) then if ( present( status ) ) then status = alloc_fault return else write(error_unit, '(a)') 'Allocation ERRMSG: ' // trim(errmsg) error stop submodule_name // ' % ' // procedure // ': ' // & alloc_inv_fault end if end if do index=1, size(map % inverse, kind=int_index) map % inverse(index) % target => null() end do call extend_map_entry_pool(map) map % initialized = .true. if (present(status) ) status = success end subroutine init_chaining_map pure module function chaining_loading( map ) !! Version: Experimental !! !! Returns the number of entries relative to slots in a hash map !! Arguments: !! map - a chaining hash map class(chaining_hashmap_type), intent(in) :: map real :: chaining_loading chaining_loading = real( map % num_entries ) / & real( size( map % slots, kind=int_index ) ) end function chaining_loading module subroutine map_chain_entry(map, key, other, conflict) !! Version: Experimental !! !! Inserts an entry into the hash table !! Arguments: !! map - the hash table of interest !! key - the key identifying the entry !! other - other data associated with the key !! conflict - logical flag indicating whether the entry key conflicts !! with an existing key ! class(chaining_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), intent(in), optional :: other logical, intent(out), optional :: conflict integer(int_hash) :: hash_index integer(int_hash) :: hash_val integer(int_index) :: inmap type(chaining_map_entry_type), pointer :: new_ent type(chaining_map_entry_type), pointer :: gentry, pentry, sentry character(*), parameter :: procedure = 'MAP_ENTRY' ! Check that map is initialized. if (.not. map % initialized) call init_chaining_map( map ) hash_val = map % hasher( key ) if ( map % probe_count > map_probe_factor * map % call_count ) then call expand_slots(map) end if map % call_count = map % call_count + 1 hash_index = fibonacci_hash( hash_val, map % nbits ) pentry => map % slots(hash_index) % target sentry => pentry do gentry => pentry map % probe_count = map % probe_count + 1 if ( .not. associated( gentry ) ) then call allocate_chaining_map_entry( map, new_ent ) new_ent % hash_val = hash_val ! Adding to tail of chain doesn't work on gfortran ! new_ent % next => sentry ! sentry => new_ent ! Adding to head of chain works on gfortran new_ent % next => map % slots(hash_index) % target map % slots(hash_index) % target => new_ent call copy_key( key, new_ent % key ) if ( present(other) ) new_ent % other = other if ( new_ent % inmap == 0 ) then map % num_entries = map % num_entries + 1 inmap = map % num_entries else inmap = new_ent % inmap end if if ( inmap == size( map % inverse, kind=int_index ) ) then call expand_inverse( map ) end if new_ent % inmap = inmap map % inverse(inmap) % target => new_ent if ( present(conflict) ) conflict = .false. return else if ( hash_val == gentry % hash_val ) then if ( key == gentry % key ) then inmap = gentry % inmap if ( .not. associated( pentry, sentry ) ) then ! Swap to front pentry => gentry % next gentry % next => sentry sentry => gentry end if if ( present(conflict) ) then conflict = .true. else error stop submodule_name // ' % ' // procedure & // ': ' // conflicting_key end if return end if end if pentry => gentry % next end do contains subroutine allocate_chaining_map_entry(map, bucket) ! Chases gent_malloc ! allocates a hash bucket type(chaining_hashmap_type), intent(inout) :: map type(chaining_map_entry_type), pointer, intent(out) :: bucket type(chaining_map_entry_pool), pointer :: pool pool => map % cache map % num_entries = map % num_entries + 1 if ( associated(map % free_list) ) then ! Get hash bucket from free_list bucket => map % free_list map % free_list => bucket % next map % num_free = map % num_free - 1 else ! Get hash bucket from pool if ( pool % next == pool_size ) then ! Expand pool call extend_map_entry_pool(map) pool => map % cache end if bucket => pool % more_map_entries(pool % next) pool % next = pool % next + 1 ! 0s based if ( map % num_entries > & size( map % inverse, kind=int_index ) ) & then call expand_inverse( map ) end if bucket % inmap = map % num_entries end if end subroutine allocate_chaining_map_entry subroutine expand_inverse(map) ! Increase size of map % inverse type(chaining_hashmap_type), intent(inout) :: map type(chaining_map_entry_ptr), allocatable :: dummy_inverse(:) integer(int32) :: stat character(256) :: errmsg character(*), parameter :: procedure = 'MAP_ENTRY' allocate( dummy_inverse( 1:2*size(map % inverse, & kind=int_index) ), & stat=stat, & errmsg=errmsg ) if ( stat /= 0 ) then write(error_unit, '(a)') 'Allocation ERRMSG: ' // trim(errmsg) error stop submodule_name // ' % ' // procedure // ': ' // & alloc_inv_fault end if dummy_inverse(1:size(map % inverse, kind=int_index)) = & map % inverse(:) call move_alloc( dummy_inverse, map % inverse ) end subroutine expand_inverse end subroutine map_chain_entry module subroutine rehash_chaining_map( map, hasher ) !! Version: Experimental !! !! Changes the hashing method of the table entries to that of HASHER. !! Arguments: !! map the table to be rehashed !! hasher the hasher function to be used for the table ! class(chaining_hashmap_type), intent(inout) :: map procedure(hasher_fun) :: hasher integer(int_hash) :: hash_val integer(int_index) :: i integer(int_index) :: index map % hasher => hasher do i=0, size( map % slots, kind=int_index ) - 1 map % slots(i) % target => null() end do do i=1, map % num_entries + map % num_free if ( .not. associated( map % inverse(i) % target ) ) cycle hash_val = map % hasher ( map % inverse(i) % target % key ) map % inverse(i) % target % hash_val = hash_val index = fibonacci_hash( hash_val, map % nbits ) map % inverse(i) % target % inmap = i if ( associated( map % slots(index) % target ) ) then map % inverse(i) % target % next => map % slots(index) % target map % slots(index) % target => map % inverse(i) % target else map % slots(index) % target => map % inverse(i) % target map % slots(index) % target % next => null() end if end do end subroutine rehash_chaining_map module subroutine remove_chaining_entry(map, key, existed) !! Remove the entry, if any, that has the key !! Arguments: !! map - the table from which the entry is to be removed !! key - the key to an entry !! existed - a logical flag indicating whether an entry with the key !! was present in the original map ! class(chaining_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key logical, intent(out), optional :: existed type(chaining_map_entry_type), pointer :: bucket, aentry, bentry, centry integer(int_hash) :: hash_val integer(int_index) :: inmap, k, level call in_chain_map( map, inmap, key ) if ( inmap < 1 .or. inmap > size( map % inverse ) ) then if ( present( existed ) ) existed = .false. return end if bucket => map % inverse(inmap) % target if ( .not. associated(bucket) ) then if ( present( existed ) ) existed = .false. return end if if ( present(existed) ) existed = .true. hash_val = bucket % hash_val k = fibonacci_hash( hash_val, map % nbits ) allocate(aentry) aentry => map % slots(k) % target if ( associated(aentry) ) then if ( aentry % inmap == inmap ) then bentry => aentry % next map % slots(k) % target => bentry aentry % next => map % free_list map % free_list => aentry map % inverse(inmap) % target => null() map % num_free = map % num_free + 1 map % num_entries = map % num_entries - 1 return end if else return end if level = 1 centry => map % slots(k) % target aentry => aentry % next FIND_SLOTS_ENTRY:do if ( .not. associated(aentry) ) return if ( aentry % inmap == inmap ) exit centry => aentry aentry => aentry % next level = level + 1 end do FIND_SLOTS_ENTRY bentry => aentry % next aentry % next => map % free_list map % free_list => aentry centry % next => bentry map % inverse(inmap) % target => null() map % num_free = map % num_free + 1 map % num_entries = map % num_entries - 1 end subroutine remove_chaining_entry module subroutine set_other_chaining_data( map, key, other, exists ) !! Version: Experimental !! !! Change the other data associated with the key !! Arguments: !! map - the map with the entry of interest !! key - the key to the entry inthe map !! other - the new data to be associated with the key !! exists - a logical flag indicating whether the key is already entered !! in the map ! class(chaining_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key class(*), intent(in) :: other logical, intent(out), optional :: exists integer(int_index) :: inmap character(*), parameter :: procedure = 'SET_OTHER_DATA' call in_chain_map( map, inmap, key ) if ( inmap <= 0 .or. inmap > size( map % inverse, kind=int_index ) ) & then if ( present(exists) ) then exists = .false. return else error stop submodule_name // ' % ' // procedure // ': ' // & invalid_inmap end if else if ( associated( map % inverse(inmap) % target ) ) then map % inverse(inmap) % target % other = other if ( present(exists) ) exists = .true. return else error stop submodule_name // ' % ' // procedure // ': ' // & invalid_inmap end if end subroutine set_other_chaining_data module function total_chaining_depth( map ) result(total_depth) !! Version: Experimental !! !! Returns the total number of ones based offsets of slot entries from !! their slot index for a hash map !! Arguments: !! map - an chaining hash map class(chaining_hashmap_type), intent(in) :: map integer(int_depth) :: total_depth type(chaining_map_entry_type), pointer :: current_key integer(int_index) :: slot, slots integer(int_depth) :: index total_depth = 0_int_depth slots = size( map % slots, kind=int_index ) do slot=0, slots-1 current_key => map % slots(slot) % target index = 0_int_depth do while( associated(current_key) ) index = index + 1_int_depth total_depth = total_depth + index current_key => current_key % next end do end do end function total_chaining_depth module subroutine chaining_key_test(map, key, present) !! Version: Experimental !! !! Returns a logical flag indicating whether KEY is present in the hash map !! Arguments: !! map - the hash map of interest !! key - the key of interest !! present - a logical flag indicating whether key is present in map ! class(chaining_hashmap_type), intent(inout) :: map type(key_type), intent(in) :: key logical, intent(out) :: present integer(int_index) :: inmap call in_chain_map( map, inmap, key ) if ( inmap <= 0 .or. inmap > size( map % inverse, kind=int_index ) ) & then present = .false. else present = associated( map % inverse(inmap) % target ) end if end subroutine chaining_key_test end submodule stdlib_hashmap_chaining fortran-lang-stdlib-0ede301/src/hashmaps/CMakeLists.txt0000664000175000017500000000045015135654166023320 0ustar alastairalastairset(hashmaps_f90Files stdlib_hashmap_chaining.f90 stdlib_hashmap_open.f90 stdlib_hashmaps.f90 stdlib_hashmap_wrappers.f90 ) configure_stdlib_target(${PROJECT_NAME}_hashmaps hashmaps_f90Files "" "") target_link_libraries(${PROJECT_NAME}_hashmaps PUBLIC ${PROJECT_NAME}_hash) fortran-lang-stdlib-0ede301/src/hashmaps/stdlib_hashmap_wrappers.f900000664000175000017500000002466315135654166026021 0ustar alastairalastair!! The module STDLIB_HASHMAP_WRAPPERS provides wrappers for various !! entities used by the hash map procedures. These include wrappers for the !! `key` and `other` data, and hashing procedures to operate on entities of !! the `key_type`. module stdlib_hashmap_wrappers use, intrinsic :: iso_fortran_env, only : & character_storage_size use stdlib_hash_32bit use stdlib_kinds, only : & int8, & int16, & int32, & int64, & dp implicit none private !! Public procedures public :: & copy_key, & fibonacci_hash, & fnv_1_hasher, & fnv_1a_hasher, & free_key, & get, & hasher_fun, & operator(==), & seeded_nmhash32_hasher, & seeded_nmhash32x_hasher, & seeded_water_hasher, & set !! Public types public :: & key_type !! Public integers public :: & int_hash integer, parameter :: & ! Should be 8 bits_int8 = bit_size(0_int8) integer, parameter :: & bits_char = character_storage_size, & bytes_char = bits_char/bits_int8 character(*), parameter :: module_name = "STDLIB_HASHMAP_WRAPPERS" type :: key_type !! Version: Experimental !! !! A wrapper type for the key's true type ! private integer(int8), allocatable :: value(:) end type key_type abstract interface !! Version: Experimental !! !! Abstract interface to a 64 bit hash function operating on a KEY_TYPE pure function hasher_fun( key ) result(hash_value) import key_type, int_hash type(key_type), intent(in) :: key integer(int_hash) :: hash_value end function hasher_fun end interface interface get module procedure get_char_key, & get_int8_key, & get_int32_key end interface get interface operator(==) module procedure equal_keys end interface operator(==) interface set module procedure set_char_key, & set_int8_key, & set_int32_key end interface set contains pure subroutine copy_key( old_key, new_key ) !! Version: Experimental !! !! Copies the contents of the key, old_key, to the key, new_key !! ([Specifications](../page/specs/stdlib_hashmaps.html#copy_key-returns-a-copy-of-the-key)) !! !! Arguments: !! old_key - the input key !! new_key - the output copy of old_key type(key_type), intent(in) :: old_key type(key_type), intent(out) :: new_key new_key % value = old_key % value end subroutine copy_key function equal_keys( key1, key2 ) result(test) ! Chase's tester !! Version: Experimental !! !! Compares two keys for equality !! ([Specifications](../page/specs/stdlib_hashmaps.html#operator(==)-compares-two-keys-for-equality)) !! !! Arguments: !! key1 - the first key !! key2 - the second key logical :: test type(key_type), intent(in) :: key1 type(key_type), intent(in) :: key2 if ( size(key1 % value, kind=int64) /= & size(key2 % value, kind=int64) ) then test = .false. return end if if ( all( key1 % value == key2 % value ) ) then test = .true. else test = .false. end if end function equal_keys subroutine free_key( key ) !! Version: Experimental !! !! Frees the memory in a key !! ([Specifications](../page/specs/stdlib_hashmaps.html#free_key-frees-the-memory-associated-with-a-key)) !! !! Arguments: !! key - the key type(key_type), intent(inout) :: key if ( allocated( key % value ) ) deallocate( key % value ) end subroutine free_key subroutine get_char_key( key, value ) !! Version: Experimental !! !! Gets the contents of the key as a CHARACTER string !! Arguments: !! key - the input key !! value - the contents of key mapped to a CHARACTER string type(key_type), intent(in) :: key character(:), allocatable, intent(out) :: value character(*), parameter :: procedure = "GET" integer(int64) :: key_as_char integer(int64) :: key_size key_size = size( key % value, kind=int64 ) select case( bytes_char ) case(1) key_as_char = key_size case(2) if ( iand( key_size, 1_int64 ) > 0 ) then error stop module_name // " % " // procedure // & ": Internal Error at stdlib_hashmaps: " // & "System uses 2 bytes per character, so " // & "key_size can't be an odd number." end if key_as_char = ishft( key_size, -1 ) case(4) if ( iand( key_size, 3_int64) > 0 ) then error stop module_name // " % " // procedure // & ": Internal Error at stdlib_hashmaps: " // & "System uses 4 bytes per character, and " // & "key_size is not a multiple of four." end if key_as_char = ishft( key_size, -2 ) case default error stop module_name // " % " // procedure // & ": Internal Error: " // & "System doesn't use a power of two for its " // & "character size as expected by stdlib_hashmaps." end select allocate( character( len=key_as_char ) :: value ) value(1:key_as_char) = transfer( key % value, value ) end subroutine get_char_key subroutine get_int8_key( key, value ) !! Version: Experimental !! !! Gets the contents of the key as an INTEGER(INT8) vector !! Arguments: !! key - the input key !! value - the contents of key mapped to an INTEGER(INT8) vector type(key_type), intent(in) :: key integer(int8), allocatable, intent(out) :: value(:) value = key % value end subroutine get_int8_key pure subroutine get_int32_key( key, value ) !! Version: Experimental !! !! Gets the contents of the key as an INTEGER(INT32) vector !! Arguments: !! key - the input key !! value - the contents of key mapped to an INTEGER(INT32) vector type(key_type), intent(in) :: key integer(int32), allocatable, intent(out) :: value(:) value = transfer( key % value, value ) end subroutine get_int32_key subroutine set_char_key( key, value ) !! Version: Experimental !! !! Sets the contents of the key from a CHARACTER string !! Arguments: !! key - the output key !! value - the input CHARACTER string type(key_type), intent(out) :: key character(*), intent(in) :: value key % value = transfer( value, key % value, & bytes_char * len( value ) ) end subroutine set_char_key subroutine set_int8_key( key, value ) !! Version: Experimental !! !! Sets the contents of the key from an INTEGER(INT8) vector !! Arguments: !! key - the output key !! value - the input INTEGER(INT8) vector type(key_type), intent(out) :: key integer(int8), intent(in) :: value(:) key % value = value end subroutine set_int8_key pure subroutine set_int32_key( key, value ) !! Version: Experimental !! !! Sets the contents of the key from an INTEGER(INT32) vector !! Arguments: !! key - the output key !! value - the input INTEGER(INT32) vector type(key_type), intent(out) :: key integer(int32), intent(in) :: value(:) key % value = transfer(value, key % value) end subroutine set_int32_key pure function fnv_1_hasher( key ) !! Version: Experimental !! !! Hashes a key with the FNV_1 algorithm !! Arguments: !! key - the key to be hashed type(key_type), intent(in) :: key integer(int_hash) :: fnv_1_hasher fnv_1_hasher = fnv_1_hash( key % value ) end function fnv_1_hasher pure function fnv_1a_hasher( key ) !! Version: Experimental !! !! Hashes a key with the FNV_1a algorithm !! ([Specifications](../page/specs/stdlib_hashmaps.html#fnv_1a_hasher-calculates-a-hash-code-from-a-key)) !! !! Arguments: !! key - the key to be hashed type(key_type), intent(in) :: key integer(int_hash) :: fnv_1a_hasher fnv_1a_hasher = fnv_1a_hash( key % value ) end function fnv_1a_hasher pure function seeded_nmhash32_hasher( key ) !! Version: Experimental !! !! Hashes a key with the NMHASH32 hash algorithm !! ([Specifications](../page/specs/stdlib_hashmaps.html#seeded_nmhash32_hasher-calculates-a-hash-code-from-a-key)) !! !! Arguments: !! key - the key to be hashed !! seed - the seed (unused) for the hashing algorithm type(key_type), intent(in) :: key integer(int_hash) :: seeded_nmhash32_hasher seeded_nmhash32_hasher = nmhash32( key % value, & int( z'DEADBEEF', int32 ) ) end function seeded_nmhash32_hasher pure function seeded_nmhash32x_hasher( key ) !! Version: Experimental !! !! Hashes a key with the NMHASH32X hash algorithm !! ([Specifications](../page/specs/stdlib_hashmaps.html#seeded_nmhash32x_hasher-calculates-a-hash-code-from-a-key)) !! Arguments: !! key - the key to be hashed !! seed - the seed (unused) for the hashing algorithm type(key_type), intent(in) :: key integer(int_hash) :: seeded_nmhash32x_hasher seeded_nmhash32x_hasher = nmhash32x( key % value, & int( z'DEADBEEF', int32 ) ) end function seeded_nmhash32x_hasher pure function seeded_water_hasher( key ) !! Version: Experimental !! !! Hashes a key with the waterhash algorithm !! ([Specifications](../page/specs/stdlib_hashmaps.html#seeded_water_hasher-calculates-a-hash-code-from-a-key)) !! !! Arguments: !! key - the key to be hashed type(key_type), intent(in) :: key integer(int_hash) :: seeded_water_hasher seeded_water_hasher = water_hash( key % value, & int( z'DEADBEEF1EADBEEF', int64 ) ) end function seeded_water_hasher end module stdlib_hashmap_wrappers fortran-lang-stdlib-0ede301/src/linalg_iterative/0000775000175000017500000000000015135654166022277 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/linalg_iterative/stdlib_linalg_iterative_solvers.fypp0000664000175000017500000002552715135654166031652 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set MATRIX_TYPES = ["dense", "CSR"] #:set RANKS = range(1, 2+1) !! The `stdlib_linalg_iterative_solvers` module provides interfaces for iterative solvers. !! module stdlib_linalg_iterative_solvers use stdlib_kinds use stdlib_sparse implicit none private !! workspace sizes: defined by the number of vectors used by the iterative solver. enum, bind(c) enumerator :: stdlib_size_wksp_cg = 3 enumerator :: stdlib_size_wksp_pcg = 4 enumerator :: stdlib_size_wksp_bicgstab = 8 end enum public :: stdlib_size_wksp_cg, stdlib_size_wksp_pcg, stdlib_size_wksp_bicgstab enum, bind(c) enumerator :: pc_none = 0 enumerator :: pc_jacobi end enum public :: pc_none, pc_jacobi !! version: experimental !! !! [Specifications](../page/specs/stdlib_linalg_iterative_solvers.html#stdlib_linop) !! !! linop type holding the linear operator and its associated methods. !! The `linop` type is used to define the linear operator for the iterative solvers. #:for k, t, s in R_KINDS_TYPES type, public :: stdlib_linop_${s}$_type procedure(vector_sub_${s}$), nopass, pointer :: matvec => null() procedure(reduction_sub_${s}$), nopass, pointer :: inner_product => default_dot_${s}$ end type #:endfor !! version: experimental !! !! [Specifications](../page/specs/stdlib_linalg_iterative_solvers.html#stdlib_solver_workspace) !! !! solver_workspace type holding temporal array data for the iterative solvers. #:for k, t, s in R_KINDS_TYPES type, public :: stdlib_solver_workspace_${s}$_type ${t}$, allocatable :: tmp(:,:) procedure(logger_sub_${s}$), pointer, nopass :: callback => null() end type #:endfor abstract interface #:for k, t, s in R_KINDS_TYPES subroutine vector_sub_${s}$(x,y,alpha,beta,op) import :: ${k}$ ${t}$, intent(in) :: x(:) ${t}$, intent(inout) :: y(:) ${t}$, intent(in) :: alpha ${t}$, intent(in) :: beta character(1), intent(in) :: op end subroutine ${t}$ function reduction_sub_${s}$(x,y) result(r) import :: ${k}$ ${t}$, intent(in) :: x(:) ${t}$, intent(in) :: y(:) end function subroutine logger_sub_${s}$(x,norm_sq,iter) import :: ${k}$ ${t}$, intent(in) :: x(:) ${t}$, intent(in) :: norm_sq integer, intent(in) :: iter end subroutine #:endfor end interface !! version: experimental !! !! stdlib_solve_cg_kernel interface for the conjugate gradient method. !! [Specifications](../page/specs/stdlib_linalg_iterative_solvers.html#stdlib_solve_cg_kernel) interface stdlib_solve_cg_kernel #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_cg_kernel_${s}$(A,b,x,rtol,atol,maxiter,workspace) class(stdlib_linop_${s}$_type), intent(in) :: A !! linear operator ${t}$, intent(in) :: b(:) !! right-hand side vector ${t}$, intent(inout) :: x(:) !! solution vector and initial guess ${t}$, intent(in) :: rtol !! relative tolerance for convergence ${t}$, intent(in) :: atol !! absolut tolerance for convergence integer, intent(in) :: maxiter !! maximum number of iterations type(stdlib_solver_workspace_${s}$_type), intent(inout) :: workspace !! workspace for the solver end subroutine #:endfor end interface public :: stdlib_solve_cg_kernel !! version: experimental !! !! [Specifications](../page/specs/stdlib_linalg_iterative_solvers.html#stdlib_solve_cg) interface stdlib_solve_cg #:for matrix in MATRIX_TYPES #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_cg_${matrix}$_${s}$(A,b,x,di,rtol,atol,maxiter,restart,workspace) !! linear operator matrix #:if matrix == "dense" ${t}$, intent(in) :: A(:,:) #:else type(${matrix}$_${s}$_type), intent(in) :: A #:endif ${t}$, intent(in) :: b(:) !! right-hand side vector ${t}$, intent(inout) :: x(:) !! solution vector and initial guess ${t}$, intent(in), optional :: rtol !! relative tolerance for convergence ${t}$, intent(in), optional :: atol !! absolute tolerance for convergence logical(int8), intent(in), optional, target :: di(:) !! dirichlet conditions mask integer, intent(in), optional :: maxiter !! maximum number of iterations logical, intent(in), optional :: restart !! restart flag type(stdlib_solver_workspace_${s}$_type), optional, intent(inout), target :: workspace !! workspace for the solver end subroutine #:endfor #:endfor end interface public :: stdlib_solve_cg !! version: experimental !! !! stdlib_solve_pcg_kernel interface for the preconditionned conjugate gradient method. !! [Specifications](../page/specs/stdlib_linalg_iterative_solvers.html#stdlib_solve_pcg_kernel) interface stdlib_solve_pcg_kernel #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_pcg_kernel_${s}$(A,M,b,x,rtol,atol,maxiter,workspace) class(stdlib_linop_${s}$_type), intent(in) :: A !! linear operator class(stdlib_linop_${s}$_type), intent(in) :: M !! preconditioner linear operator ${t}$, intent(in) :: b(:) !! right-hand side vector ${t}$, intent(inout) :: x(:) !! solution vector and initial guess ${t}$, intent(in) :: rtol !! relative tolerance for convergence ${t}$, intent(in) :: atol !! absolute tolerance for convergence integer, intent(in) :: maxiter !! maximum number of iterations type(stdlib_solver_workspace_${s}$_type), intent(inout) :: workspace !! workspace for the solver end subroutine #:endfor end interface public :: stdlib_solve_pcg_kernel !! version: experimental !! !! stdlib_solve_bicgstab_kernel interface for the biconjugate gradient stabilized method. !! [Specifications](../page/specs/stdlib_linalg_iterative_solvers.html#stdlib_solve_bicgstab_kernel) interface stdlib_solve_bicgstab_kernel #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_bicgstab_kernel_${s}$(A,M,b,x,rtol,atol,maxiter,workspace) class(stdlib_linop_${s}$_type), intent(in) :: A !! linear operator class(stdlib_linop_${s}$_type), intent(in) :: M !! preconditioner linear operator ${t}$, intent(in) :: b(:) !! right-hand side vector ${t}$, intent(inout) :: x(:) !! solution vector and initial guess ${t}$, intent(in) :: rtol !! relative tolerance for convergence ${t}$, intent(in) :: atol !! absolute tolerance for convergence integer, intent(in) :: maxiter !! maximum number of iterations type(stdlib_solver_workspace_${s}$_type), intent(inout) :: workspace !! workspace for the solver end subroutine #:endfor end interface public :: stdlib_solve_bicgstab_kernel !! version: experimental !! !! [Specifications](../page/specs/stdlib_linalg_iterative_solvers.html#stdlib_solve_pcg) interface stdlib_solve_pcg #:for matrix in MATRIX_TYPES #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_pcg_${matrix}$_${s}$(A,b,x,di,rtol,atol,maxiter,restart,precond,M,workspace) !! linear operator matrix #:if matrix == "dense" ${t}$, intent(in) :: A(:,:) #:else type(${matrix}$_${s}$_type), intent(in) :: A #:endif ${t}$, intent(in) :: b(:) !! right-hand side vector ${t}$, intent(inout) :: x(:) !! solution vector and initial guess ${t}$, intent(in), optional :: rtol !! relative tolerance for convergence ${t}$, intent(in), optional :: atol !! absolute tolerance for convergence logical(int8), intent(in), optional, target :: di(:) !! dirichlet conditions mask integer, intent(in), optional :: maxiter !! maximum number of iterations logical, intent(in), optional :: restart !! restart flag integer, intent(in), optional :: precond !! preconditioner method enumerator class(stdlib_linop_${s}$_type), optional , intent(in), target :: M !! preconditioner linear operator type(stdlib_solver_workspace_${s}$_type), optional, intent(inout), target :: workspace !! workspace for the solver end subroutine #:endfor #:endfor end interface public :: stdlib_solve_pcg !! version: experimental !! !! [Specifications](../page/specs/stdlib_linalg_iterative_solvers.html#stdlib_solve_bicgstab) interface stdlib_solve_bicgstab #:for matrix in MATRIX_TYPES #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_bicgstab_${matrix}$_${s}$(A,b,x,di,rtol,atol,maxiter,restart,precond,M,workspace) !! linear operator matrix #:if matrix == "dense" ${t}$, intent(in) :: A(:,:) #:else type(${matrix}$_${s}$_type), intent(in) :: A #:endif ${t}$, intent(in) :: b(:) !! right-hand side vector ${t}$, intent(inout) :: x(:) !! solution vector and initial guess ${t}$, intent(in), optional :: rtol !! relative tolerance for convergence ${t}$, intent(in), optional :: atol !! absolute tolerance for convergence logical(int8), intent(in), optional, target :: di(:) !! dirichlet conditions mask integer, intent(in), optional :: maxiter !! maximum number of iterations logical, intent(in), optional :: restart !! restart flag integer, intent(in), optional :: precond !! preconditioner method enumerator class(stdlib_linop_${s}$_type), optional , intent(in), target :: M !! preconditioner linear operator type(stdlib_solver_workspace_${s}$_type), optional, intent(inout), target :: workspace !! workspace for the solver end subroutine #:endfor #:endfor end interface public :: stdlib_solve_bicgstab contains !------------------------------------------------------------------ ! defaults !------------------------------------------------------------------ #:for k, t, s in R_KINDS_TYPES ${t}$ function default_dot_${s}$(x,y) result(r) use stdlib_intrinsics, only: stdlib_dot_product ${t}$, intent(in) :: x(:) ${t}$, intent(in) :: y(:) r = stdlib_dot_product(x,y) end function #:endfor end module stdlib_linalg_iterative_solvers fortran-lang-stdlib-0ede301/src/linalg_iterative/stdlib_linalg_iterative_solvers_pcg.fypp0000664000175000017500000001711415135654166032474 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set MATRIX_TYPES = ["dense", "CSR"] #:set RANKS = range(1, 2+1) submodule(stdlib_linalg_iterative_solvers) stdlib_linalg_iterative_pcg use stdlib_kinds use stdlib_sparse use stdlib_constants use stdlib_optval, only: optval implicit none contains #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_pcg_kernel_${s}$(A,M,b,x,rtol,atol,maxiter,workspace) class(stdlib_linop_${s}$_type), intent(in) :: A class(stdlib_linop_${s}$_type), intent(in) :: M ${t}$, intent(in) :: b(:), rtol, atol ${t}$, intent(inout) :: x(:) integer, intent(in) :: maxiter type(stdlib_solver_workspace_${s}$_type), intent(inout) :: workspace !------------------------- integer :: iter ${t}$ :: norm_sq, norm_sq0, norm_sq_old ${t}$ :: zr1, zr2, zv2, alpha, beta, tolsq !------------------------- iter = 0 associate( R => workspace%tmp(:,1), & S => workspace%tmp(:,2), & P => workspace%tmp(:,3), & Q => workspace%tmp(:,4)) norm_sq = A%inner_product( b, b ) norm_sq0 = norm_sq if(associated(workspace%callback)) call workspace%callback(x, norm_sq, iter) if ( norm_sq0 > zero_${s}$ ) then R = B call A%matvec(X, R, alpha= -one_${s}$, beta=one_${s}$, op='N') ! R = B - A*X call M%matvec(R,P, alpha= one_${s}$, beta=zero_${s}$, op='N') ! P = M^{-1}*R tolsq = max(rtol*rtol * norm_sq0, atol*atol) zr1 = zero_${s}$ zr2 = one_${s}$ do while ( (iter < maxiter) .AND. (norm_sq >= tolsq) ) call M%matvec(R,S, alpha= one_${s}$, beta=zero_${s}$, op='N') ! S = M^{-1}*R zr2 = A%inner_product( R, S ) if (iter>0) then beta = zr2 / zr1 P = S + beta * P end if call A%matvec(P, Q, alpha= one_${s}$, beta=zero_${s}$, op='N') ! Q = A*P zv2 = A%inner_product( P, Q ) alpha = zr2 / zv2 X = X + alpha * P R = R - alpha * Q norm_sq = A%inner_product( R, R ) norm_sq_old = norm_sq zr1 = zr2 iter = iter + 1 if(associated(workspace%callback)) call workspace%callback(x, norm_sq, iter) end do end if end associate end subroutine #:endfor #:for matrix in MATRIX_TYPES #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_pcg_${matrix}$_${s}$(A,b,x,di,rtol,atol,maxiter,restart,precond,M,workspace) #:if matrix == "dense" use stdlib_linalg, only: diag ${t}$, intent(in) :: A(:,:) #:else type(${matrix}$_${s}$_type), intent(in) :: A #:endif ${t}$, intent(in) :: b(:) ${t}$, intent(inout) :: x(:) ${t}$, intent(in), optional :: rtol, atol logical(int8), intent(in), optional, target :: di(:) integer, intent(in), optional :: maxiter logical, intent(in), optional :: restart integer, intent(in), optional :: precond class(stdlib_linop_${s}$_type), optional , intent(in), target :: M type(stdlib_solver_workspace_${s}$_type), optional, intent(inout), target :: workspace !------------------------- type(stdlib_linop_${s}$_type) :: op type(stdlib_linop_${s}$_type), pointer :: M_ => null() type(stdlib_solver_workspace_${s}$_type), pointer :: workspace_ integer :: n, maxiter_ ${t}$ :: rtol_, atol_ logical :: restart_ logical(int8), pointer :: di_(:) !------------------------- ! working data for preconditioner integer :: precond_ ${t}$, allocatable :: diagonal(:) !------------------------- n = size(b) maxiter_ = optval(x=maxiter, default=n) restart_ = optval(x=restart, default=.true.) rtol_ = optval(x=rtol, default=1.e-5_${s}$) atol_ = optval(x=atol, default=epsilon(one_${s}$)) precond_ = optval(x=precond, default=pc_none) !------------------------- ! internal memory setup ! preconditioner if(present(M)) then M_ => M else allocate( M_ ) allocate(diagonal(n),source=zero_${s}$) select case(precond_) case(pc_jacobi) #:if matrix == "dense" diagonal = diag(A) #:else call diag(A,diagonal) #:endif M_%matvec => precond_jacobi case default M_%matvec => precond_none end select where(abs(diagonal)>epsilon(zero_${s}$)) diagonal = one_${s}$/diagonal end if ! matvec for the operator op%matvec => matvec ! direchlet boundary conditions mask if(present(di))then di_ => di else allocate(di_(n),source=.false._int8) end if ! workspace for the solver if(present(workspace)) then workspace_ => workspace else allocate( workspace_ ) end if if(.not.allocated(workspace_%tmp)) allocate( workspace_%tmp(n,stdlib_size_wksp_pcg) , source = zero_${s}$ ) !------------------------- ! main call to the solver if(restart_) x = zero_${s}$ x = merge( b, x, di_ ) ! copy dirichlet load conditions encoded in B and indicated by di call stdlib_solve_pcg_kernel(op,M_,b,x,rtol_,atol_,maxiter_,workspace_) !------------------------- ! internal memory cleanup if(.not.present(di)) deallocate(di_) di_ => null() if(.not.present(workspace)) then deallocate( workspace_%tmp ) deallocate( workspace_ ) end if M_ => null() workspace_ => null() contains subroutine matvec(x,y,alpha,beta,op) #:if matrix == "dense" use stdlib_linalg_blas, only: gemv #:endif ${t}$, intent(in) :: x(:) ${t}$, intent(inout) :: y(:) ${t}$, intent(in) :: alpha ${t}$, intent(in) :: beta character(1), intent(in) :: op #:if matrix == "dense" call gemv(op,m=size(A,1),n=size(A,2),alpha=alpha,a=A,lda=size(A,1),x=x,incx=1,beta=beta,y=y,incy=1) #:else call spmv( A , x, y , alpha, beta , op) #:endif y = merge( zero_${s}$, y, di_ ) end subroutine subroutine precond_none(x,y,alpha,beta,op) ${t}$, intent(in) :: x(:) ${t}$, intent(inout) :: y(:) ${t}$, intent(in) :: alpha ${t}$, intent(in) :: beta character(1), intent(in) :: op y = merge( zero_${s}$, x, di_ ) end subroutine subroutine precond_jacobi(x,y,alpha,beta,op) ${t}$, intent(in) :: x(:) ${t}$, intent(inout) :: y(:) ${t}$, intent(in) :: alpha ${t}$, intent(in) :: beta character(1), intent(in) :: op y = merge( zero_${s}$, diagonal * x, di_ ) ! inverted diagonal end subroutine end subroutine #:endfor #:endfor end submodule stdlib_linalg_iterative_pcgfortran-lang-stdlib-0ede301/src/linalg_iterative/CMakeLists.txt0000664000175000017500000000103115135654166025032 0ustar alastairalastairset(linalg_iterative_fppFiles stdlib_linalg_iterative_solvers_bicgstab.fypp stdlib_linalg_iterative_solvers_cg.fypp stdlib_linalg_iterative_solvers.fypp stdlib_linalg_iterative_solvers_pcg.fypp ) set(linalg_iterative_cppFiles ) set(linalg_iterative_f90Files ) configure_stdlib_target(${PROJECT_NAME}_linalg_iterative linalg_iterative_f90Files linalg_iterative_fppFiles linalg_iterative_cppFiles) target_link_libraries(${PROJECT_NAME}_linalg_iterative PUBLIC ${PROJECT_NAME}_linalg ${PROJECT_NAME}_sparse) fortran-lang-stdlib-0ede301/src/linalg_iterative/stdlib_linalg_iterative_solvers_bicgstab.fypp0000664000175000017500000002233215135654166033477 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set MATRIX_TYPES = ["dense", "CSR"] #:set RANKS = range(1, 2+1) submodule(stdlib_linalg_iterative_solvers) stdlib_linalg_iterative_bicgstab use stdlib_kinds use stdlib_sparse use stdlib_constants use stdlib_optval, only: optval implicit none contains #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_bicgstab_kernel_${s}$(A,M,b,x,rtol,atol,maxiter,workspace) class(stdlib_linop_${s}$_type), intent(in) :: A class(stdlib_linop_${s}$_type), intent(in) :: M ${t}$, intent(in) :: b(:), rtol, atol ${t}$, intent(inout) :: x(:) integer, intent(in) :: maxiter type(stdlib_solver_workspace_${s}$_type), intent(inout) :: workspace !------------------------- integer :: iter ${t}$ :: norm_sq, norm_sq0, tolsq ${t}$ :: rho, rho_prev, alpha, beta, omega, rv ${t}$, parameter :: rhotol = epsilon(one_${s}$)**2 ${t}$, parameter :: omegatol = epsilon(one_${s}$)**2 !------------------------- iter = 0 associate( R => workspace%tmp(:,1), & Rt => workspace%tmp(:,2), & P => workspace%tmp(:,3), & Pt => workspace%tmp(:,4), & V => workspace%tmp(:,5), & S => workspace%tmp(:,6), & St => workspace%tmp(:,7), & T => workspace%tmp(:,8)) norm_sq = A%inner_product( b, b ) norm_sq0 = norm_sq if(associated(workspace%callback)) call workspace%callback(x, norm_sq, iter) if ( norm_sq0 > zero_${s}$ ) then ! Compute initial residual: r = b - A*x R = B call A%matvec(X, R, alpha= -one_${s}$, beta=one_${s}$, op='N') ! R = B - A*X ! Choose arbitrary Rt (often Rt = r0) Rt = R tolsq = max(rtol*rtol * norm_sq0, atol*atol) rho_prev = one_${s}$ alpha = one_${s}$ omega = one_${s}$ do while ( (iter < maxiter) .AND. (norm_sq >= tolsq) ) rho = A%inner_product( Rt, R ) ! Check for rho breakdown if (abs(rho) < rhotol) exit if (iter > 0) then ! Check for omega breakdown if (abs(omega) < omegatol) exit beta = (rho / rho_prev) * (alpha / omega) P = R + beta * (P - omega * V) else P = R end if ! Preconditioned BiCGSTAB step call M%matvec(P, Pt, alpha=one_${s}$, beta=zero_${s}$, op='N') ! Pt = M^{-1}*P call A%matvec(Pt, V, alpha=one_${s}$, beta=zero_${s}$, op='N') ! V = A*Pt rv = A%inner_product( Rt, V ) if (abs(rv) < epsilon(one_${s}$)) exit ! rv breakdown alpha = rho / rv ! Update residual: s = r - alpha*v S = R - alpha * V ! Check if s is small enough norm_sq = A%inner_product( S, S ) if (norm_sq < tolsq) then X = X + alpha * Pt exit end if ! Preconditioned update for t = A * M^{-1} * s call M%matvec(S, St, alpha=one_${s}$, beta=zero_${s}$, op='N') ! St = M^{-1}*S call A%matvec(St, T, alpha=one_${s}$, beta=zero_${s}$, op='N') ! T = A*St ! Compute omega omega = A%inner_product( T, S ) / A%inner_product( T, T ) ! Update solution and residual X = X + alpha * Pt + omega * St R = S - omega * T norm_sq = A%inner_product( R, R ) rho_prev = rho iter = iter + 1 if(associated(workspace%callback)) call workspace%callback(x, norm_sq, iter) end do end if end associate end subroutine #:endfor #:for matrix in MATRIX_TYPES #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_bicgstab_${matrix}$_${s}$(A,b,x,di,rtol,atol,maxiter,restart,precond,M,workspace) #:if matrix == "dense" use stdlib_linalg, only: diag ${t}$, intent(in) :: A(:,:) #:else type(${matrix}$_${s}$_type), intent(in) :: A #:endif ${t}$, intent(in) :: b(:) ${t}$, intent(inout) :: x(:) ${t}$, intent(in), optional :: rtol, atol logical(int8), intent(in), optional, target :: di(:) integer, intent(in), optional :: maxiter logical, intent(in), optional :: restart integer, intent(in), optional :: precond class(stdlib_linop_${s}$_type), optional , intent(in), target :: M type(stdlib_solver_workspace_${s}$_type), optional, intent(inout), target :: workspace !------------------------- type(stdlib_linop_${s}$_type) :: op type(stdlib_linop_${s}$_type), pointer :: M_ => null() type(stdlib_solver_workspace_${s}$_type), pointer :: workspace_ integer :: n, maxiter_ ${t}$ :: rtol_, atol_ logical :: restart_ logical(int8), pointer :: di_(:) !------------------------- ! working data for preconditioner integer :: precond_ ${t}$, allocatable :: diagonal(:) !------------------------- n = size(b) maxiter_ = optval(x=maxiter, default=n) restart_ = optval(x=restart, default=.true.) rtol_ = optval(x=rtol, default=1.e-5_${s}$) atol_ = optval(x=atol, default=epsilon(one_${s}$)) precond_ = optval(x=precond, default=pc_none) !------------------------- ! internal memory setup ! preconditioner if(present(M)) then M_ => M else allocate( M_ ) allocate(diagonal(n),source=zero_${s}$) select case(precond_) case(pc_jacobi) #:if matrix == "dense" diagonal = diag(A) #:else call diag(A,diagonal) #:endif M_%matvec => precond_jacobi case default M_%matvec => precond_none end select where(abs(diagonal)>epsilon(zero_${s}$)) diagonal = one_${s}$/diagonal end if ! matvec for the operator op%matvec => matvec ! direchlet boundary conditions mask if(present(di))then di_ => di else allocate(di_(n),source=.false._int8) end if ! workspace for the solver if(present(workspace)) then workspace_ => workspace else allocate( workspace_ ) end if if(.not.allocated(workspace_%tmp)) allocate( workspace_%tmp(n,stdlib_size_wksp_bicgstab) , source = zero_${s}$ ) !------------------------- ! main call to the solver if(restart_) x = zero_${s}$ x = merge( b, x, di_ ) ! copy dirichlet load conditions encoded in B and indicated by di call stdlib_solve_bicgstab_kernel(op,M_,b,x,rtol_,atol_,maxiter_,workspace_) !------------------------- ! internal memory cleanup if(.not.present(di)) deallocate(di_) di_ => null() if(.not.present(workspace)) then deallocate( workspace_%tmp ) deallocate( workspace_ ) end if M_ => null() workspace_ => null() contains subroutine matvec(x,y,alpha,beta,op) #:if matrix == "dense" use stdlib_linalg_blas, only: gemv #:endif ${t}$, intent(in) :: x(:) ${t}$, intent(inout) :: y(:) ${t}$, intent(in) :: alpha ${t}$, intent(in) :: beta character(1), intent(in) :: op #:if matrix == "dense" call gemv(op,m=size(A,1),n=size(A,2),alpha=alpha,a=A,lda=size(A,1),x=x,incx=1,beta=beta,y=y,incy=1) #:else call spmv( A , x, y , alpha, beta , op) #:endif y = merge( zero_${s}$, y, di_ ) end subroutine subroutine precond_none(x,y,alpha,beta,op) ${t}$, intent(in) :: x(:) ${t}$, intent(inout) :: y(:) ${t}$, intent(in) :: alpha ${t}$, intent(in) :: beta character(1), intent(in) :: op y = merge( zero_${s}$, x, di_ ) end subroutine subroutine precond_jacobi(x,y,alpha,beta,op) ${t}$, intent(in) :: x(:) ${t}$, intent(inout) :: y(:) ${t}$, intent(in) :: alpha ${t}$, intent(in) :: beta character(1), intent(in) :: op y = merge( zero_${s}$, diagonal * x, di_ ) ! inverted diagonal end subroutine end subroutine #:endfor #:endfor end submodule stdlib_linalg_iterative_bicgstab fortran-lang-stdlib-0ede301/src/linalg_iterative/stdlib_linalg_iterative_solvers_cg.fypp0000664000175000017500000001254115135654166032313 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set MATRIX_TYPES = ["dense", "CSR"] #:set RANKS = range(1, 2+1) submodule(stdlib_linalg_iterative_solvers) stdlib_linalg_iterative_cg use stdlib_kinds use stdlib_sparse use stdlib_constants use stdlib_optval, only: optval implicit none contains #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_cg_kernel_${s}$(A,b,x,rtol,atol,maxiter,workspace) class(stdlib_linop_${s}$_type), intent(in) :: A ${t}$, intent(in) :: b(:), rtol, atol ${t}$, intent(inout) :: x(:) integer, intent(in) :: maxiter type(stdlib_solver_workspace_${s}$_type), intent(inout) :: workspace !------------------------- integer :: iter ${t}$ :: norm_sq, norm_sq_old, norm_sq0 ${t}$ :: alpha, beta, tolsq !------------------------- iter = 0 associate( P => workspace%tmp(:,1), & R => workspace%tmp(:,2), & Ap => workspace%tmp(:,3)) norm_sq0 = A%inner_product(B, B) if(associated(workspace%callback)) call workspace%callback(x, norm_sq0, iter) R = B call A%matvec(X, R, alpha= -one_${s}$, beta=one_${s}$, op='N') ! R = B - A*X norm_sq = A%inner_product(R, R) P = R tolsq = max(rtol*rtol * norm_sq0, atol*atol) beta = zero_${s}$ if(associated(workspace%callback)) call workspace%callback(x, norm_sq, iter) do while( norm_sq >= tolsq .and. iter < maxiter) call A%matvec(P,Ap, alpha= one_${s}$, beta=zero_${s}$, op='N') ! Ap = A*P alpha = norm_sq / A%inner_product(P, Ap) X = X + alpha * P R = R - alpha * Ap norm_sq_old = norm_sq norm_sq = A%inner_product(R, R) beta = norm_sq / norm_sq_old P = R + beta * P iter = iter + 1 if(associated(workspace%callback)) call workspace%callback(x, norm_sq, iter) end do end associate end subroutine #:endfor #:for matrix in MATRIX_TYPES #:for k, t, s in R_KINDS_TYPES module subroutine stdlib_solve_cg_${matrix}$_${s}$(A,b,x,di,rtol,atol,maxiter,restart,workspace) #:if matrix == "dense" ${t}$, intent(in) :: A(:,:) #:else type(${matrix}$_${s}$_type), intent(in) :: A #:endif ${t}$, intent(in) :: b(:) ${t}$, intent(inout) :: x(:) ${t}$, intent(in), optional :: rtol, atol logical(int8), intent(in), optional, target :: di(:) integer, intent(in), optional :: maxiter logical, intent(in), optional :: restart type(stdlib_solver_workspace_${s}$_type), optional, intent(inout), target :: workspace !------------------------- type(stdlib_linop_${s}$_type) :: op type(stdlib_solver_workspace_${s}$_type), pointer :: workspace_ integer :: n, maxiter_ ${t}$ :: rtol_, atol_ logical :: restart_ logical(int8), pointer :: di_(:) !------------------------- n = size(b) maxiter_ = optval(x=maxiter, default=n) restart_ = optval(x=restart, default=.true.) rtol_ = optval(x=rtol, default=1.e-5_${s}$) atol_ = optval(x=atol, default=epsilon(one_${s}$)) !------------------------- ! internal memory setup op%matvec => matvec ! op%inner_product => default_dot if(present(di))then di_ => di else allocate(di_(n),source=.false._int8) end if if(present(workspace)) then workspace_ => workspace else allocate( workspace_ ) end if if(.not.allocated(workspace_%tmp)) allocate( workspace_%tmp(n,stdlib_size_wksp_cg), source = zero_${s}$ ) !------------------------- ! main call to the solver if(restart_) x = zero_${s}$ x = merge( b, x, di_ ) ! copy dirichlet load conditions encoded in B and indicated by di call stdlib_solve_cg_kernel(op,b,x,rtol_,atol_,maxiter_,workspace_) !------------------------- ! internal memory cleanup if(.not.present(di)) deallocate(di_) di_ => null() if(.not.present(workspace)) then deallocate( workspace_%tmp ) deallocate( workspace_ ) end if workspace_ => null() contains subroutine matvec(x,y,alpha,beta,op) #:if matrix == "dense" use stdlib_linalg_blas, only: gemv #:endif ${t}$, intent(in) :: x(:) ${t}$, intent(inout) :: y(:) ${t}$, intent(in) :: alpha ${t}$, intent(in) :: beta character(1), intent(in) :: op #:if matrix == "dense" call gemv(op,m=size(A,1),n=size(A,2),alpha=alpha,a=A,lda=size(A,1),x=x,incx=1,beta=beta,y=y,incy=1) #:else call spmv( A , x, y , alpha, beta , op) #:endif y = merge( zero_${s}$, y, di_ ) end subroutine end subroutine #:endfor #:endfor end submodule stdlib_linalg_iterative_cgfortran-lang-stdlib-0ede301/src/sorting/0000775000175000017500000000000015135654166020442 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/sorting/stdlib_sorting_sort_adjoint.fypp0000664000175000017500000005121315135654166027151 0ustar alastairalastair#include "macros.inc" #:include "common.fypp" #:set INT_TYPES_ALT_NAME = list(zip(INT_TYPES, INT_TYPES, INT_TYPES, INT_KINDS, INT_CPPS)) #:set REAL_TYPES_ALT_NAME = list(zip(REAL_TYPES, REAL_TYPES, REAL_TYPES, REAL_KINDS, REAL_CPPS)) #:set STRING_TYPES_ALT_NAME = list(zip(STRING_TYPES, STRING_TYPES, STRING_TYPES, STRING_KINDS, STRING_CPPS)) #:set CHAR_TYPES_ALT_NAME = list(zip(["character(len=*)"], ["character(len=:)"], ["character(len=len(array))"], ["char"], [""])) #:set BITSETS_TYPES_ALT_NAME = list(zip(BITSETS_TYPES, BITSETS_TYPES, BITSETS_TYPES, BITSETS_KINDS, BITSETS_CPPS)) #! For better code reuse in fypp, make lists that contain the input types, #! with each having output types and a separate name prefix for subroutines #! This approach allows us to have the same code for all input types. #:set IRSCB_TYPES_ALT_NAME = INT_TYPES_ALT_NAME + REAL_TYPES_ALT_NAME + STRING_TYPES_ALT_NAME + CHAR_TYPES_ALT_NAME & & + BITSETS_TYPES_ALT_NAME #:set IR_INDEX_TYPES_ALT_NAME = INT_TYPES_ALT_NAME + REAL_TYPES_ALT_NAME !! Licensing: !! !! This file is subjec† both to the Fortran Standard Library license, and !! to additional licensing requirements as it contains translations of !! other software. !! !! The Fortran Standard Library, including this file, is distributed under !! the MIT license that should be included with the library's distribution. !! !! Copyright (c) 2021 Fortran stdlib developers !! !! Permission is hereby granted, free of charge, to any person obtaining a !! copy of this software and associated documentation files (the !! "Software"), to deal in the Software without restriction, including !! without limitation the rights to use, copy, modify, merge, publish, !! distribute, sublicense, and/or sellcopies of the Software, and to permit !! persons to whom the Software is furnished to do so, subject to the !! following conditions: !! !! The above copyright notice and this permission notice shall be included !! in all copies or substantial portions of the Software. !! !! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS !! OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF !! MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. !! IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY !! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, !! TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE !! SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. !! !! The generic subroutine, `SORT_ADJ`, is substantially a translation to !! Fortran 2008 of the `"Rust" sort` sorting routines in !! [`slice.rs`](https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs) !! The `rust sort` implementation is distributed with the header: !! !! Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT !! file at the top-level directory of this distribution and at !! http://rust-lang.org/COPYRIGHT. !! !! Licensed under the Apache License, Version 2.0 or the MIT license !! , at your !! option. This file may not be copied, modified, or distributed !! except according to those terms. !! !! so the license for the original`slice.rs` code is compatible with the use !! of modified versions of the code in the Fortran Standard Library under !! the MIT license. submodule(stdlib_sorting) stdlib_sorting_sort_adjoint implicit none contains #:for ki, ti, tii, namei, cppi in IR_INDEX_TYPES_ALT_NAME #:for t1, t2, t3, name1, cpp1 in IRSCB_TYPES_ALT_NAME #:block generate_cpp(cpp_var=cpp1) module subroutine ${name1}$_${namei}$_sort_adjoint( array, adjoint_array, work, iwork, reverse ) ! A modification of `${name1}$_ord_sort` to return an array of indices that ! would perform a stable sort of the `ARRAY` as input, and also sort `ARRAY` ! as desired. The indices by default ! correspond to a non-decreasing sort, but if the optional argument ! `REVERSE` is present with a value of `.TRUE.` the indices correspond to ! a non-increasing sort. The logic of the determination of indexing largely ! follows the `"Rust" sort` found in `slice.rs`: ! https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs#L2159 ! The Rust version in turn is a simplification of the Timsort algorithm ! described in ! https://svn.python.org/projects/python/trunk/Objects/listsort.txt, as ! it drops both the use of 'galloping' to identify bounds of regions to be ! sorted and the estimation of the optimal `run size`. However it remains ! a hybrid sorting algorithm combining an iterative Merge sort controlled ! by a stack of `RUNS` identified by regions of uniformly decreasing or ! non-decreasing sequences that may be expanded to a minimum run size and ! initially processed by an insertion sort. ! ! Note the Fortran implementation simplifies the logic as it only has to ! deal with Fortran arrays of intrinsic types and not the full generality ! of Rust's arrays and lists for arbitrary types. It also adds the ! estimation of the optimal `run size` as suggested in Tim Peters' ! original `listsort.txt`, and the optional `work` and `iwork` arrays to be ! used as scratch memory. ${t1}$, intent(inout) :: array(0:) ${ti}$, intent(inout) :: adjoint_array(0:) ${t3}$, intent(out), optional :: work(0:) ${ti}$, intent(out), optional :: iwork(0:) logical, intent(in), optional :: reverse ${t2}$, allocatable :: buf(:) ${ti}$, allocatable :: ibuf(:) integer(int_index) :: array_size integer(int_index) :: stat array_size = size(array, kind=int_index) if ( optval(reverse, .false.) ) then call reverse_segment( array, adjoint_array ) end if ! If necessary allocate buffers to serve as scratch memory. if ( present(work) ) then if ( size(work, kind=int_index) < array_size/2 ) then error stop "work array is too small." end if if ( present(iwork) ) then if ( size(iwork, kind=int_index) < array_size/2 ) then error stop "iwork array is too small." endif call merge_sort( array, adjoint_array, work, iwork ) else allocate( ibuf(0:array_size/2-1), stat=stat ) if ( stat /= 0 ) error stop "Allocation of adjoint_array buffer failed." call merge_sort( array, adjoint_array, work, ibuf ) end if else ! Allocate a buffer to use as scratch memory. #:if t1[0:4] == "char" allocate( ${t3}$ :: buf(0:array_size/2-1), & stat=stat ) #:else allocate( buf(0:array_size/2-1), stat=stat ) #:endif if ( stat /= 0 ) error stop "Allocation of array buffer failed." if ( present(iwork) ) then if ( size(iwork, kind=int_index) < array_size/2 ) then error stop "iwork array is too small." endif call merge_sort( array, adjoint_array, buf, iwork ) else allocate( ibuf(0:array_size/2-1), stat=stat ) if ( stat /= 0 ) error stop "Allocation of adjoint_array buffer failed." call merge_sort( array, adjoint_array, buf, ibuf ) end if end if if ( optval(reverse, .false.) ) then call reverse_segment( array, adjoint_array ) end if contains pure function calc_min_run( n ) result(min_run) !! Returns the minimum length of a run from 32-63 so that N/MIN_RUN is !! less than or equal to a power of two. See !! https://svn.python.org/projects/python/trunk/Objects/listsort.txt integer(int_index) :: min_run integer(int_index), intent(in) :: n integer(int_index) :: num, r num = n r = 0_int_index do while( num >= 64 ) r = ior( r, iand(num, 1_int_index) ) num = ishft(num, -1_int_index) end do min_run = num + r end function calc_min_run pure subroutine insertion_sort( array, adjoint_array ) ! Sorts `ARRAY` using an insertion sort, while maintaining consistency in ! location of the indices in `INDEX` to the elements of `ARRAY`. ${t1}$, intent(inout) :: array(0:) ${ti}$, intent(inout) :: adjoint_array(0:) integer(int_index) :: i, j ${ti}$ :: key_adjoint_array ${t3}$ :: key do j=1, size(array, kind=int_index)-1 key = array(j) key_adjoint_array = adjoint_array(j) i = j - 1 do while( i >= 0 ) if ( array(i) <= key ) exit array(i+1) = array(i) adjoint_array(i+1) = adjoint_array(i) i = i - 1 end do array(i+1) = key adjoint_array(i+1) = key_adjoint_array end do end subroutine insertion_sort pure function collapse( runs ) result ( r ) ! Examine the stack of runs waiting to be merged, identifying adjacent runs ! to be merged until the stack invariants are restablished: ! ! 1. len(-3) > len(-2) + len(-1) ! 2. len(-2) > len(-1) integer(int_index) :: r type(run_type), intent(in), target :: runs(0:) integer(int_index) :: n logical :: test n = size(runs, kind=int_index) test = .false. if (n >= 2) then if ( runs( n-1 ) % base == 0 .or. & runs( n-2 ) % len <= runs(n-1) % len ) then test = .true. else if ( n >= 3 ) then ! X exists if ( runs(n-3) % len <= & runs(n-2) % len + runs(n-1) % len ) then test = .true. ! |X| <= |Y| + |Z| => will need to merge due to rho1 or rho2 else if( n >= 4 ) then if ( runs(n-4) % len <= & runs(n-3) % len + runs(n-2) % len ) then test = .true. ! |W| <= |X| + |Y| => will need to merge due to rho1 or rho3 end if end if end if end if if ( test ) then ! By default merge Y & Z, rho2 or rho3 if ( n >= 3 ) then if ( runs(n-3) % len < runs(n-1) % len ) then r = n - 3 ! |X| < |Z| => merge X & Y, rho1 return end if end if r = n - 2 ! |Y| <= |Z| => merge Y & Z, rho4 return else r = -1 end if end function collapse pure subroutine insert_head( array, adjoint_array ) ! Inserts `array(0)` into the pre-sorted sequence `array(1:)` so that the ! whole `array(0:)` becomes sorted, copying the first element into ! a temporary variable, iterating until the right place for it is found. ! copying every traversed element into the slot preceding it, and finally, ! copying data from the temporary variable into the resulting hole. ! Consistency of the indices in `adjoint_array` with the elements of `array` ! are maintained. ${t1}$, intent(inout) :: array(0:) ${ti}$, intent(inout) :: adjoint_array(0:) ${t3}$ :: tmp integer(int_index) :: i ${ti}$ :: tmp_adjoint_array tmp = array(0) tmp_adjoint_array = adjoint_array(0) find_hole: do i=1, size(array, kind=int_index)-1 if ( array(i) >= tmp ) exit find_hole array(i-1) = array(i) adjoint_array(i-1) = adjoint_array(i) end do find_hole array(i-1) = tmp adjoint_array(i-1) = tmp_adjoint_array end subroutine insert_head subroutine merge_sort( array, adjoint_array, buf, ibuf ) ! The Rust merge sort borrows some (but not all) of the ideas from TimSort, ! which is described in detail at ! (http://svn.python.org/projects/python/trunk/Objects/listsort.txt). ! ! The algorithm identifies strictly descending and non-descending ! subsequences, which are called natural runs. Where these runs are less ! than a minimum run size they are padded by adding additional samples ! using an insertion sort. The merge process is driven by a stack of ! pending unmerged runs. Each newly found run is pushed onto the stack, ! and then pairs of adjacentd runs are merged until these two invariants ! are satisfied: ! ! 1. for every `i` in `1..size(runs)-1`: `runs(i - 1)%len > runs(i)%len` ! 2. for every `i` in `2..size(runs)-1`: `runs(i - 2)%len > ! runs(i - 1)%len + runs(i)%len` ! ! The invariants ensure that the total running time is `O(n log n)` ! worst-case. Consistency of the indices in `adjoint_array` with the elements of ! `array` are maintained. ${t1}$, intent(inout) :: array(0:) ${ti}$, intent(inout) :: adjoint_array(0:) ${t3}$, intent(inout) :: buf(0:) ${ti}$, intent(inout) :: ibuf(0:) integer(int_index) :: array_size, finish, min_run, r, r_count, & start type(run_type) :: runs(0:max_merge_stack-1), left, right array_size = size(array, kind=int_index) ! Very short runs are extended using insertion sort to span at least this ! many elements. Slices of up to this length are sorted using insertion sort. min_run = calc_min_run( array_size ) if ( array_size <= min_run ) then if ( array_size >= 2 ) call insertion_sort( array, adjoint_array ) return end if ! Following Rust sort, natural runs in `array` are identified by traversing ! it backwards. By traversing it backward, merges more often go in the ! opposite direction (forwards). According to developers of Rust sort, ! merging forwards is slightly faster than merging backwards. Therefore ! identifying runs by traversing backwards should improve performance. r_count = 0 finish = array_size - 1 do while ( finish >= 0 ) ! Find the next natural run, and reverse it if it's strictly descending. start = finish if ( start > 0 ) then start = start - 1 if ( array(start+1) < array(start) ) then Descending: do while ( start > 0 ) if ( array(start) >= array(start-1) ) & exit Descending start = start - 1 end do Descending call reverse_segment( array(start:finish), & adjoint_array(start:finish) ) else Ascending: do while( start > 0 ) if ( array(start) < array(start-1) ) exit Ascending start = start - 1 end do Ascending end if end if ! If the run is too short insert some more elements using an insertion sort. Insert: do while ( start > 0 ) if ( finish - start >= min_run - 1 ) exit Insert start = start - 1 call insert_head( array(start:finish), adjoint_array(start:finish) ) end do Insert if ( start == 0 .and. finish == array_size - 1 ) return runs(r_count) = run_type( base = start, & len = finish - start + 1 ) finish = start-1 r_count = r_count + 1 ! Determine whether pairs of adjacent runs need to be merged to satisfy ! the invariants, and, if so, merge them. Merge_loop: do r = collapse( runs(0:r_count - 1) ) if ( r < 0 .or. r_count <= 1 ) exit Merge_loop left = runs( r + 1 ) right = runs( r ) call merge( array( left % base: & right % base + right % len - 1 ), & left % len, buf, & adjoint_array( left % base: & right % base + right % len - 1 ), ibuf ) runs(r) = run_type( base = left % base, & len = left % len + right % len ) if ( r == r_count - 3 ) runs(r+1) = runs(r+2) r_count = r_count - 1 end do Merge_loop end do if ( r_count /= 1 ) & error stop "MERGE_SORT completed without RUN COUNT == 1." end subroutine merge_sort pure subroutine merge( array, mid, buf, adjoint_array, ibuf ) ! Merges the two non-decreasing runs `ARRAY(0:MID-1)` and `ARRAY(MID:)` ! using `BUF` as temporary storage, and stores the merged runs into ! `ARRAY(0:)`. `MID` must be > 0, and < `SIZE(ARRAY)-1`. Buffer `BUF` ! must be long enough to hold the shorter of the two runs. ${t1}$, intent(inout) :: array(0:) integer(int_index), intent(in) :: mid ${t3}$, intent(inout) :: buf(0:) ${ti}$, intent(inout) :: adjoint_array(0:) ${ti}$, intent(inout) :: ibuf(0:) integer(int_index) :: array_len, i, j, k array_len = size(array, kind=int_index) ! Merge first copies the shorter run into `buf`. Then, depending on which ! run was shorter, it traces the copied run and the longer run forwards ! (or backwards), comparing their next unprocessed elements and then ! copying the lesser (or greater) one into `array`. if ( mid <= array_len - mid ) then ! The left run is shorter. buf(0:mid-1) = array(0:mid-1) ibuf(0:mid-1) = adjoint_array(0:mid-1) i = 0 j = mid merge_lower: do k = 0, array_len-1 if ( buf(i) <= array(j) ) then array(k) = buf(i) adjoint_array(k) = ibuf(i) i = i + 1 if ( i >= mid ) exit merge_lower else array(k) = array(j) adjoint_array(k) = adjoint_array(j) j = j + 1 if ( j >= array_len ) then array(k+1:) = buf(i:mid-1) adjoint_array(k+1:) = ibuf(i:mid-1) exit merge_lower end if end if end do merge_lower else ! The right run is shorter buf(0:array_len-mid-1) = array(mid:array_len-1) ibuf(0:array_len-mid-1) = adjoint_array(mid:array_len-1) i = mid - 1 j = array_len - mid -1 merge_upper: do k = array_len-1, 0, -1 if ( buf(j) >= array(i) ) then array(k) = buf(j) adjoint_array(k) = ibuf(j) j = j - 1 if ( j < 0 ) exit merge_upper else array(k) = array(i) adjoint_array(k) = adjoint_array(i) i = i - 1 if ( i < 0 ) then array(0:k-1) = buf(0:j) adjoint_array(0:k-1) = ibuf(0:j) exit merge_upper end if end if end do merge_upper end if end subroutine merge pure subroutine reverse_segment( array, adjoint_array ) ! Reverse a segment of an array in place ${t1}$, intent(inout) :: array(0:) ${ti}$, intent(inout) :: adjoint_array(0:) ${ti}$ :: itemp integer(int_index) :: lo, hi ${t3}$ :: temp lo = 0 hi = size( array, kind=int_index ) - 1 do while( lo < hi ) temp = array(lo) array(lo) = array(hi) array(hi) = temp itemp = adjoint_array(lo) adjoint_array(lo) = adjoint_array(hi) adjoint_array(hi) = itemp lo = lo + 1 hi = hi - 1 end do end subroutine reverse_segment end subroutine ${name1}$_${namei}$_sort_adjoint #:endblock #:endfor #:endfor end submodule stdlib_sorting_sort_adjoint fortran-lang-stdlib-0ede301/src/sorting/stdlib_sorting_radix_sort.f900000664000175000017500000004262415135654166026256 0ustar alastairalastairsubmodule(stdlib_sorting) stdlib_sorting_radix_sort implicit none integer, parameter :: radix_bits = 8 integer, parameter :: radix_mask = 255 integer(kind=int16), parameter :: radix_bits_i16 = 8_int16 integer(kind=int16), parameter :: radix_mask_i16 = 255_int16 integer(kind=int32), parameter :: radix_bits_i32 = 8_int32 integer(kind=int32), parameter :: radix_mask_i32 = 255_int32 integer(kind=int64), parameter :: radix_bits_i64 = 8_int64 integer(kind=int64), parameter :: radix_mask_i64 = 255_int64 contains ! For int8, radix sort becomes counting sort, so buffer is not needed pure subroutine radix_sort_u8_helper(N, arr) integer(kind=int_index), intent(in) :: N integer(kind=int8), dimension(N), intent(inout) :: arr integer(kind=int_index) :: i integer :: bin_idx integer(kind=int_index), dimension(-128:127) :: counts counts(:) = 0 do i = 1, N bin_idx = arr(i) counts(bin_idx) = counts(bin_idx) + 1 end do i = 1 do bin_idx = -128, 127 do while (counts(bin_idx) > 0) arr(i) = int(bin_idx, kind=int8) i = i + 1 counts(bin_idx) = counts(bin_idx) - 1 end do end do end subroutine pure subroutine radix_sort_u16_helper(N, arr, buf) integer(kind=int_index), intent(in) :: N integer(kind=int16), dimension(N), intent(inout) :: arr integer(kind=int16), dimension(N), intent(inout) :: buf integer(kind=int_index) :: i integer :: b, b0, b1 integer(kind=int_index), dimension(0:radix_mask) :: c0, c1 c0(:) = 0 c1(:) = 0 do i = 1, N b0 = iand(arr(i), radix_mask_i16) b1 = ishft(arr(i), -radix_bits_i16) c0(b0) = c0(b0) + 1 c1(b1) = c1(b1) + 1 end do do b = 1, radix_mask c0(b) = c0(b) + c0(b - 1) c1(b) = c1(b) + c1(b - 1) end do do i = N, 1, -1 b0 = iand(arr(i), radix_mask_i16) buf(c0(b0)) = arr(i) c0(b0) = c0(b0) - 1 end do do i = N, 1, -1 b1 = ishft(buf(i), -radix_bits_i16) arr(c1(b1)) = buf(i) c1(b1) = c1(b1) - 1 end do end subroutine pure subroutine radix_sort_u32_helper(N, arr, buf) integer(kind=int_index), intent(in) :: N integer(kind=int32), dimension(N), intent(inout) :: arr integer(kind=int32), dimension(N), intent(inout) :: buf integer(kind=int_index) :: i integer :: b, b0, b1, b2, b3 integer(kind=int_index), dimension(0:radix_mask) :: c0, c1, c2, c3 c0(:) = 0 c1(:) = 0 c2(:) = 0 c3(:) = 0 do i = 1, N b0 = iand(arr(i), radix_mask_i32) b1 = iand(ishft(arr(i), -radix_bits_i32), radix_mask_i32) b2 = iand(ishft(arr(i), -2*radix_bits_i32), radix_mask_i32) b3 = ishft(arr(i), -3*radix_bits_i32) c0(b0) = c0(b0) + 1 c1(b1) = c1(b1) + 1 c2(b2) = c2(b2) + 1 c3(b3) = c3(b3) + 1 end do do b = 1, radix_mask c0(b) = c0(b) + c0(b - 1) c1(b) = c1(b) + c1(b - 1) c2(b) = c2(b) + c2(b - 1) c3(b) = c3(b) + c3(b - 1) end do do i = N, 1, -1 b0 = iand(arr(i), radix_mask_i32) buf(c0(b0)) = arr(i) c0(b0) = c0(b0) - 1 end do do i = N, 1, -1 b1 = iand(ishft(buf(i), -radix_bits_i32), radix_mask_i32) arr(c1(b1)) = buf(i) c1(b1) = c1(b1) - 1 end do do i = N, 1, -1 b2 = iand(ishft(arr(i), -2*radix_bits_i32), radix_mask_i32) buf(c2(b2)) = arr(i) c2(b2) = c2(b2) - 1 end do do i = N, 1, -1 b3 = ishft(buf(i), -3*radix_bits_i32) arr(c3(b3)) = buf(i) c3(b3) = c3(b3) - 1 end do end subroutine radix_sort_u32_helper pure subroutine radix_sort_u64_helper(N, arr, buffer) integer(kind=int_index), intent(in) :: N integer(kind=int64), dimension(N), intent(inout) :: arr integer(kind=int64), dimension(N), intent(inout) :: buffer integer(kind=int_index) :: i integer(kind=int64) :: b, b0, b1, b2, b3, b4, b5, b6, b7 integer(kind=int_index), dimension(0:radix_mask) :: c0, c1, c2, c3, c4, c5, c6, c7 c0(:) = 0 c1(:) = 0 c2(:) = 0 c3(:) = 0 c4(:) = 0 c5(:) = 0 c6(:) = 0 c7(:) = 0 do i = 1, N b0 = iand(arr(i), radix_mask_i64) b1 = iand(ishft(arr(i), -radix_bits_i64), radix_mask_i64) b2 = iand(ishft(arr(i), -2*radix_bits_i64), radix_mask_i64) b3 = iand(ishft(arr(i), -3*radix_bits_i64), radix_mask_i64) b4 = iand(ishft(arr(i), -4*radix_bits_i64), radix_mask_i64) b5 = iand(ishft(arr(i), -5*radix_bits_i64), radix_mask_i64) b6 = iand(ishft(arr(i), -6*radix_bits_i64), radix_mask_i64) b7 = ishft(arr(i), -7*radix_bits_i64) c0(b0) = c0(b0) + 1 c1(b1) = c1(b1) + 1 c2(b2) = c2(b2) + 1 c3(b3) = c3(b3) + 1 c4(b4) = c4(b4) + 1 c5(b5) = c5(b5) + 1 c6(b6) = c6(b6) + 1 c7(b7) = c7(b7) + 1 end do do b = 1, radix_mask c0(b) = c0(b) + c0(b - 1) c1(b) = c1(b) + c1(b - 1) c2(b) = c2(b) + c2(b - 1) c3(b) = c3(b) + c3(b - 1) c4(b) = c4(b) + c4(b - 1) c5(b) = c5(b) + c5(b - 1) c6(b) = c6(b) + c6(b - 1) c7(b) = c7(b) + c7(b - 1) end do do i = N, 1, -1 b0 = iand(arr(i), radix_mask_i64) buffer(c0(b0)) = arr(i) c0(b0) = c0(b0) - 1 end do do i = N, 1, -1 b1 = iand(ishft(buffer(i), -radix_bits_i64), radix_mask_i64) arr(c1(b1)) = buffer(i) c1(b1) = c1(b1) - 1 end do do i = N, 1, -1 b2 = iand(ishft(arr(i), -2*radix_bits_i64), radix_mask_i64) buffer(c2(b2)) = arr(i) c2(b2) = c2(b2) - 1 end do do i = N, 1, -1 b3 = iand(ishft(buffer(i), -3*radix_bits_i64), radix_mask_i64) arr(c3(b3)) = buffer(i) c3(b3) = c3(b3) - 1 end do do i = N, 1, -1 b4 = iand(ishft(arr(i), -4*radix_bits_i64), radix_mask_i64) buffer(c4(b4)) = arr(i) c4(b4) = c4(b4) - 1 end do do i = N, 1, -1 b5 = iand(ishft(buffer(i), -5*radix_bits_i64), radix_mask_i64) arr(c5(b5)) = buffer(i) c5(b5) = c5(b5) - 1 end do do i = N, 1, -1 b6 = iand(ishft(arr(i), -6*radix_bits_i64), radix_mask_i64) buffer(c6(b6)) = arr(i) c6(b6) = c6(b6) - 1 end do do i = N, 1, -1 b7 = ishft(buffer(i), -7*radix_bits_i64) arr(c7(b7)) = buffer(i) c7(b7) = c7(b7) - 1 end do end subroutine radix_sort_u64_helper pure module subroutine int8_radix_sort(array, reverse) integer(kind=int8), dimension(:), intent(inout) :: array logical, intent(in), optional :: reverse integer(kind=int8) :: item integer(kind=int_index) :: i, N N = size(array, kind=int_index) call radix_sort_u8_helper(N, array) if (optval(reverse, .false.)) then do i = 1, N/2 item = array(i) array(i) = array(N - i + 1) array(N - i + 1) = item end do end if end subroutine int8_radix_sort pure module subroutine int16_radix_sort(array, work, reverse) integer(kind=int16), dimension(:), intent(inout) :: array integer(kind=int16), dimension(:), intent(inout), target, optional :: work logical, intent(in), optional :: reverse integer(kind=int_index) :: i, N, start, middle, end integer(kind=int16), dimension(:), pointer :: buffer integer(kind=int16) :: item logical :: use_internal_buffer N = size(array, kind=int_index) if (present(work)) then if (size(work, kind=int_index) < N) then error stop "int16_radix_sort: work array is too small." end if use_internal_buffer = .false. buffer => work else use_internal_buffer = .true. allocate (buffer(N)) end if call radix_sort_u16_helper(N, array, buffer) ! After calling `radix_sort_u_helper. The array is sorted as unsigned integers. ! In the view of signed array, the negative numbers are sorted but in the tail of the array. ! Use binary search to find the boundary, and move them to correct position. if (array(1) >= 0 .and. array(N) < 0) then start = 1 end = N middle = (1 + N)/2 do while (.true.) if (array(middle) >= 0) then start = middle + 1 else end = middle end if middle = (start + end)/2 if (start == end) exit end do buffer(1:(N - middle + 1)) = array(middle:N) buffer(N - middle + 2:N) = array(1:middle - 1) array(:) = buffer(:) end if if (optval(reverse, .false.)) then do i = 1, N/2 item = array(i) array(i) = array(N - i + 1) array(N - i + 1) = item end do end if if (use_internal_buffer) then deallocate (buffer) end if end subroutine int16_radix_sort pure module subroutine int32_radix_sort(array, work, reverse) integer(kind=int32), dimension(:), intent(inout) :: array integer(kind=int32), dimension(:), intent(inout), target, optional :: work logical, intent(in), optional :: reverse integer(kind=int_index) :: i, N, start, middle, end integer(kind=int32), dimension(:), pointer :: buffer integer(kind=int32) :: item logical :: use_internal_buffer N = size(array, kind=int_index) if (present(work)) then if (size(work, kind=int_index) < N) then error stop "int32_radix_sort: work array is too small." end if use_internal_buffer = .false. buffer => work else use_internal_buffer = .true. allocate (buffer(N)) end if call radix_sort_u32_helper(N, array, buffer) if (array(1) >= 0 .and. array(N) < 0) then start = 1 end = N middle = (1 + N)/2 do while (.true.) if (array(middle) >= 0) then start = middle + 1 else end = middle end if middle = (start + end)/2 if (start == end) exit end do buffer(1:(N - middle + 1)) = array(middle:N) buffer(N - middle + 2:N) = array(1:middle - 1) array(:) = buffer(:) end if if (optval(reverse, .false.)) then do i = 1, N/2 item = array(i) array(i) = array(N - i + 1) array(N - i + 1) = item end do end if if (use_internal_buffer) then deallocate (buffer) end if end subroutine int32_radix_sort module subroutine sp_radix_sort(array, work, reverse) use iso_c_binding real(kind=sp), dimension(:), intent(inout), target :: array real(kind=sp), dimension(:), intent(inout), target, optional :: work logical, intent(in), optional :: reverse integer(kind=int_index) :: i, N, pos, rev_pos integer(kind=int32), dimension(:), pointer :: arri32 integer(kind=int32), dimension(:), pointer :: buffer real(kind=sp) :: item logical :: use_internal_buffer N = size(array, kind=int_index) if (present(work)) then if (size(work, kind=int_index) < N) then error stop "sp_radix_sort: work array is too small." end if use_internal_buffer = .false. call c_f_pointer(c_loc(work), buffer, [N]) else use_internal_buffer = .true. allocate (buffer(N)) end if call c_f_pointer(c_loc(array), arri32, [N]) call radix_sort_u32_helper(N, arri32, buffer) ! After calling `radix_sort_u_helper. The array is sorted as unsigned integers. ! The positive real number is sorted, guaranteed by IEEE-754 standard. ! But the negative real number is sorted in a reversed order, and also in the tail of array. ! Remark that -0.0 is the minimum nagative integer, so using radix sort, -0.0 is naturally lesser than 0.0. ! In IEEE-754 standard, the bit representation of `Inf` is greater than all positive real numbers, ! and the `-Inf` is lesser than all negative real numbers. So the order of `Inf, -Inf` is ok. ! The bit representation of `NaN` may be positive or negative integers in different machine, ! thus if the array contains `NaN`, the result is undefined. if (arri32(1) >= 0 .and. arri32(N) < 0) then pos = 1 rev_pos = N do while (arri32(rev_pos) < 0) buffer(pos) = arri32(rev_pos) pos = pos + 1 rev_pos = rev_pos - 1 end do buffer(pos:N) = arri32(1:rev_pos) arri32(:) = buffer(:) end if if (optval(reverse, .false.)) then do i = 1, N/2 item = array(i) array(i) = array(N - i + 1) array(N - i + 1) = item end do end if if (use_internal_buffer) then deallocate (buffer) end if end subroutine sp_radix_sort pure module subroutine int64_radix_sort(array, work, reverse) integer(kind=int64), dimension(:), intent(inout) :: array integer(kind=int64), dimension(:), intent(inout), target, optional :: work logical, intent(in), optional :: reverse integer(kind=int_index) :: i, N, start, middle, end integer(kind=int64), dimension(:), pointer :: buffer integer(kind=int64) :: item logical :: use_internal_buffer N = size(array, kind=int_index) if (present(work)) then if (size(work, kind=int_index) < N) then error stop "int64_radix_sort: work array is too small." end if use_internal_buffer = .false. buffer => work else use_internal_buffer = .true. allocate (buffer(N)) end if call radix_sort_u64_helper(N, array, buffer) if (array(1) >= 0 .and. array(N) < 0) then start = 1 end = N middle = (1 + N)/2 do while (.true.) if (array(middle) >= 0) then start = middle + 1 else end = middle end if middle = (start + end)/2 if (start == end) exit end do buffer(1:(N - middle + 1)) = array(middle:N) buffer(N - middle + 2:N) = array(1:middle - 1) array(:) = buffer(:) end if if (optval(reverse, .false.)) then do i = 1, N/2 item = array(i) array(i) = array(N - i + 1) array(N - i + 1) = item end do end if if (use_internal_buffer) then deallocate (buffer) end if end subroutine int64_radix_sort module subroutine dp_radix_sort(array, work, reverse) use iso_c_binding real(kind=dp), dimension(:), intent(inout), target :: array real(kind=dp), dimension(:), intent(inout), target, optional :: work logical, intent(in), optional :: reverse integer(kind=int_index) :: i, N, pos, rev_pos integer(kind=int64), dimension(:), pointer :: arri64 integer(kind=int64), dimension(:), pointer :: buffer real(kind=dp) :: item logical :: use_internal_buffer N = size(array, kind=int_index) if (present(work)) then if (size(work, kind=int_index) < N) then error stop "sp_radix_sort: work array is too small." end if use_internal_buffer = .false. call c_f_pointer(c_loc(work), buffer, [N]) else use_internal_buffer = .true. allocate (buffer(N)) end if call c_f_pointer(c_loc(array), arri64, [N]) call radix_sort_u64_helper(N, arri64, buffer) if (arri64(1) >= 0 .and. arri64(N) < 0) then pos = 1 rev_pos = N do while (arri64(rev_pos) < 0) buffer(pos) = arri64(rev_pos) pos = pos + 1 rev_pos = rev_pos - 1 end do buffer(pos:N) = arri64(1:rev_pos) arri64(:) = buffer(:) end if if (optval(reverse, .false.)) then do i = 1, N/2 item = array(i) array(i) = array(N - i + 1) array(N - i + 1) = item end do end if if (use_internal_buffer) then deallocate (buffer) end if end subroutine dp_radix_sort end submodule stdlib_sorting_radix_sort fortran-lang-stdlib-0ede301/src/sorting/stdlib_sorting_ord_sort.fypp0000664000175000017500000004324615135654166026314 0ustar alastairalastair#include "macros.inc" #:include "common.fypp" #:set INT_TYPES_ALT_NAME = list(zip(INT_TYPES, INT_TYPES, INT_TYPES, INT_KINDS, INT_CPPS)) #:set REAL_TYPES_ALT_NAME = list(zip(REAL_TYPES, REAL_TYPES, REAL_TYPES, REAL_KINDS, REAL_CPPS)) #:set STRING_TYPES_ALT_NAME = list(zip(STRING_TYPES, STRING_TYPES, STRING_TYPES, STRING_KINDS, STRING_CPPS)) #:set CHAR_TYPES_ALT_NAME = list(zip(["character(len=*)"], ["character(len=:)"], ["character(len=len(array))"], ["char"], [""])) #:set BITSETS_TYPES_ALT_NAME = list(zip(BITSETS_TYPES, BITSETS_TYPES, BITSETS_TYPES, BITSETS_KINDS, BITSETS_CPPS)) #! For better code reuse in fypp, make lists that contain the input types, #! with each having output types and a separate name prefix for subroutines #! This approach allows us to have the same code for all input types. #:set IRSCB_TYPES_ALT_NAME = INT_TYPES_ALT_NAME + REAL_TYPES_ALT_NAME + STRING_TYPES_ALT_NAME + CHAR_TYPES_ALT_NAME & & + BITSETS_TYPES_ALT_NAME #:set SIGN_NAME = ["increase", "decrease"] #:set SIGN_TYPE = [">", "<"] #:set SIGN_OPP_TYPE = ["<", ">"] #:set SIGN_NAME_TYPE = list(zip(SIGN_NAME, SIGN_TYPE, SIGN_OPP_TYPE)) !! Licensing: !! !! This file is subjec† both to the Fortran Standard Library license, and !! to additional licensing requirements as it contains translations of !! other software. !! !! The Fortran Standard Library, including this file, is distributed under !! the MIT license that should be included with the library's distribution. !! !! Copyright (c) 2021 Fortran stdlib developers !! !! Permission is hereby granted, free of charge, to any person obtaining a !! copy of this software and associated documentation files (the !! "Software"), to deal in the Software without restriction, including !! without limitation the rights to use, copy, modify, merge, publish, !! distribute, sublicense, and/or sellcopies of the Software, and to permit !! persons to whom the Software is furnished to do so, subject to the !! following conditions: !! !! The above copyright notice and this permission notice shall be included !! in all copies or substantial portions of the Software. !! !! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS !! OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF !! MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. !! IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY !! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, !! TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE !! SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. !! !! The generic subroutine, `ORD_SORT`, is substantially a translation to !! Fortran 2008 of the `"Rust" sort` sorting routines in !! [`slice.rs`](https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs) !! The `rust sort` implementation is distributed with the header: !! !! Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT !! file at the top-level directory of this distribution and at !! http://rust-lang.org/COPYRIGHT. !! !! Licensed under the Apache License, Version 2.0 or the MIT license !! , at your !! option. This file may not be copied, modified, or distributed !! except according to those terms. !! !! so the license for the original`slice.rs` code is compatible with the use !! of modified versions of the code in the Fortran Standard Library under !! the MIT license. submodule(stdlib_sorting) stdlib_sorting_ord_sort implicit none contains #:for t1, t2, t3, name1, cpp1 in IRSCB_TYPES_ALT_NAME #:block generate_cpp(cpp_var=cpp1) module subroutine ${name1}$_ord_sort( array, work, reverse ) ${t1}$, intent(inout) :: array(0:) ${t3}$, intent(out), optional :: work(0:) logical, intent(in), optional :: reverse if (optval(reverse, .false.)) then call ${name1}$_decrease_ord_sort(array, work) else call ${name1}$_increase_ord_sort(array, work) endif end subroutine ${name1}$_ord_sort #:endblock #:endfor #:for sname, signt, signoppt in SIGN_NAME_TYPE #:for t1, t2, t3, name1, cpp1 in IRSCB_TYPES_ALT_NAME #:block generate_cpp(cpp_var=cpp1) subroutine ${name1}$_${sname}$_ord_sort( array, work ) ! A translation to Fortran 2008, of the `"Rust" sort` algorithm found in ! `slice.rs` ! https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs#L2159 ! The Rust version in turn is a simplification of the Timsort algorithm ! described in ! https://svn.python.org/projects/python/trunk/Objects/listsort.txt, as ! it drops both the use of 'galloping' to identify bounds of regions to be ! sorted and the estimation of the optimal `run size`. However it remains ! a hybrid sorting algorithm combining an iterative Merge sort controlled ! by a stack of `RUNS` identified by regions of uniformly decreasing or ! non-decreasing sequences that may be expanded to a minimum run size and ! initially processed by an insertion sort. ! ! Note the Fortran implementation simplifies the logic as it only has to ! deal with Fortran arrays of intrinsic types and not the full generality ! of Rust's arrays and lists for arbitrary types. It also adds the ! estimation of the optimal `run size` as suggested in Tim Peters' ! original `listsort.txt`, and an optional `work` array to be used as ! scratch memory. ${t1}$, intent(inout) :: array(0:) ${t3}$, intent(out), optional :: work(0:) ${t2}$, allocatable :: buf(:) integer(int_index) :: array_size integer :: stat array_size = size( array, kind=int_index ) ! If necessary allocate buffers to serve as scratch memory. if ( present(work) ) then if ( size(work, kind=int_index) < array_size/2 ) then error stop "${name1}$_${sname}$_ord_sort: work array is too small." end if ! Use the work array as scratch memory call merge_sort( array, work ) else ! Allocate a buffer to use as scratch memory. #:if t1[0:4] == "char" allocate( ${t3}$ :: buf(0:array_size/2-1), & stat=stat ) #:else allocate( buf(0:array_size/2-1), stat=stat ) #:endif if ( stat /= 0 ) error stop "${name1}$_${sname}$_ord_sort: Allocation of buffer failed." call merge_sort( array, buf ) end if contains pure function calc_min_run( n ) result(min_run) !! Returns the minimum length of a run from 32-63 so that N/MIN_RUN is !! less than or equal to a power of two. See !! https://svn.python.org/projects/python/trunk/Objects/listsort.txt integer(int_index) :: min_run integer(int_index), intent(in) :: n integer(int_index) :: num, r num = n r = 0_int_index do while( num >= 64 ) r = ior( r, iand(num, 1_int_index) ) num = ishft(num, -1_int_index) end do min_run = num + r end function calc_min_run pure subroutine insertion_sort( array ) ! Sorts `ARRAY` using an insertion sort. ${t1}$, intent(inout) :: array(0:) integer(int_index) :: i, j ${t3}$ :: key do j=1, size(array, kind=int_index)-1 key = array(j) i = j - 1 do while( i >= 0 ) if ( array(i) ${signoppt}$= key ) exit array(i+1) = array(i) i = i - 1 end do array(i+1) = key end do end subroutine insertion_sort pure function collapse( runs ) result ( r ) ! Examine the stack of runs waiting to be merged, identifying adjacent runs ! to be merged until the stack invariants are restablished: ! ! 1. len(-3) > len(-2) + len(-1) ! 2. len(-2) > len(-1) integer(int_index) :: r type(run_type), intent(in), target :: runs(0:) integer(int_index) :: n logical :: test n = size(runs, kind=int_index) test = .false. if (n >= 2) then if ( runs( n-1 ) % base == 0 .or. & runs( n-2 ) % len <= runs(n-1) % len ) then test = .true. else if ( n >= 3 ) then ! X exists if ( runs(n-3) % len <= & runs(n-2) % len + runs(n-1) % len ) then test = .true. ! |X| <= |Y| + |Z| => will need to merge due to rho1 or rho2 else if( n >= 4 ) then if ( runs(n-4) % len <= & runs(n-3) % len + runs(n-2) % len ) then test = .true. ! |W| <= |X| + |Y| => will need to merge due to rho1 or rho3 end if end if end if end if if ( test ) then ! By default merge Y & Z, rho2 or rho3 if ( n >= 3 ) then if ( runs(n-3) % len < runs(n-1) % len ) then r = n - 3 ! |X| < |Z| => merge X & Y, rho1 return end if end if r = n - 2 ! |Y| <= |Z| => merge Y & Z, rho4 return else r = -1 end if end function collapse pure subroutine insert_head( array ) ! Inserts `array(0)` into the pre-sorted sequence `array(1:)` so that the ! whole `array(0:)` becomes sorted, copying the first element into ! a temporary variable, iterating until the right place for it is found. ! copying every traversed element into the slot preceding it, and finally, ! copying data from the temporary variable into the resulting hole. ${t1}$, intent(inout) :: array(0:) ${t3}$ :: tmp integer(int_index) :: i tmp = array(0) find_hole: do i=1, size(array, kind=int_index)-1 if ( array(i) ${signt}$= tmp ) exit find_hole array(i-1) = array(i) end do find_hole array(i-1) = tmp end subroutine insert_head subroutine merge_sort( array, buf ) ! The Rust merge sort borrows some (but not all) of the ideas from TimSort, ! which is described in detail at ! (http://svn.python.org/projects/python/trunk/Objects/listsort.txt). ! ! The algorithm identifies strictly descending and non-descending ! subsequences, which are called natural runs. Where these runs are less ! than a minimum run size they are padded by adding additional samples ! using an insertion sort. The merge process is driven by a stack of ! pending unmerged runs. Each newly found run is pushed onto the stack, ! and then pairs of adjacentd runs are merged until these two invariants ! are satisfied: ! ! 1. for every `i` in `1..size(runs)-1`: `runs(i - 1)%len > runs(i)%len` ! 2. for every `i` in `2..size(runs)-1`: `runs(i - 2)%len > ! runs(i - 1)%len + runs(i)%len` ! ! The invariants ensure that the total running time is `O(n log n)` ! worst-case. ${t1}$, intent(inout) :: array(0:) ${t3}$, intent(inout) :: buf(0:) integer(int_index) :: array_size, finish, min_run, r, r_count, & start type(run_type) :: runs(0:max_merge_stack-1), left, right array_size = size(array, kind=int_index) ! Very short runs are extended using insertion sort to span at least ! min_run elements. Slices of up to this length are sorted using insertion ! sort. min_run = calc_min_run( array_size ) if ( array_size <= min_run ) then if ( array_size >= 2 ) call insertion_sort( array ) return end if ! Following Rust sort, natural runs in `array` are identified by traversing ! it backwards. By traversing it backward, merges more often go in the ! opposite direction (forwards). According to developers of Rust sort, ! merging forwards is slightly faster than merging backwards. Therefore ! identifying runs by traversing backwards should improve performance. r_count = 0 finish = array_size - 1 do while ( finish >= 0 ) ! Find the next natural run, and reverse it if it's strictly descending. start = finish if ( start > 0 ) then start = start - 1 if ( array(start+1) ${signoppt}$ array(start) ) then Descending: do while ( start > 0 ) if ( array(start) ${signt}$= array(start-1) ) & exit Descending start = start - 1 end do Descending call reverse_segment( array(start:finish) ) else Ascending: do while( start > 0 ) if ( array(start) ${signoppt}$ array(start-1) ) exit Ascending start = start - 1 end do Ascending end if end if ! If the run is too short insert some more elements using an insertion sort. Insert: do while ( start > 0 ) if ( finish - start >= min_run - 1 ) exit Insert start = start - 1 call insert_head( array(start:finish) ) end do Insert if ( start == 0 .and. finish == array_size - 1 ) return runs(r_count) = run_type( base = start, & len = finish - start + 1 ) finish = start-1 r_count = r_count + 1 ! Determine whether pairs of adjacent runs need to be merged to satisfy ! the invariants, and, if so, merge them. Merge_loop: do r = collapse( runs(0:r_count - 1) ) if ( r < 0 .or. r_count <= 1 ) exit Merge_loop left = runs( r + 1 ) right = runs( r ) call merge( array( left % base: & right % base + right % len - 1 ), & left % len, buf ) runs(r) = run_type( base = left % base, & len = left % len + right % len ) if ( r == r_count - 3 ) runs(r+1) = runs(r+2) r_count = r_count - 1 end do Merge_loop end do if ( r_count /= 1 ) & error stop "MERGE_SORT completed without RUN COUNT == 1." end subroutine merge_sort pure subroutine merge( array, mid, buf ) ! Merges the two non-decreasing runs `ARRAY(0:MID-1)` and `ARRAY(MID:)` ! using `BUF` as temporary storage, and stores the merged runs into ! `ARRAY(0:)`. `MID` must be > 0, and < `SIZE(ARRAY)-1`. Buffer `BUF` ! must be long enough to hold the shorter of the two runs. ${t1}$, intent(inout) :: array(0:) integer(int_index), intent(in) :: mid ${t3}$, intent(inout) :: buf(0:) integer(int_index) :: array_len, i, j, k array_len = size(array, kind=int_index) ! Merge first copies the shorter run into `buf`. Then, depending on which ! run was shorter, it traces the copied run and the longer run forwards ! (or backwards), comparing their next unprocessed elements and then ! copying the lesser (or greater) one into `array`. if ( mid <= array_len - mid ) then ! The left run is shorter. buf(0:mid-1) = array(0:mid-1) i = 0 j = mid merge_lower: do k = 0, array_len-1 if ( buf(i) ${signoppt}$= array(j) ) then array(k) = buf(i) i = i + 1 if ( i >= mid ) exit merge_lower else array(k) = array(j) j = j + 1 if ( j >= array_len ) then array(k+1:) = buf(i:mid-1) exit merge_lower end if end if end do merge_lower else ! The right run is shorter ! check that it is stable buf(0:array_len-mid-1) = array(mid:array_len-1) i = mid - 1 j = array_len - mid -1 merge_upper: do k = array_len-1, 0, -1 if ( buf(j) ${signt}$= array(i) ) then array(k) = buf(j) j = j - 1 if ( j < 0 ) exit merge_upper else array(k) = array(i) i = i - 1 if ( i < 0 ) then array(0:k-1) = buf(0:j) exit merge_upper end if end if end do merge_upper end if end subroutine merge pure subroutine reverse_segment( array ) ! Reverse a segment of an array in place ${t1}$, intent(inout) :: array(0:) integer(int_index) :: lo, hi ${t3}$ :: temp lo = 0 hi = size( array, kind=int_index ) - 1 do while( lo < hi ) temp = array(lo) array(lo) = array(hi) array(hi) = temp lo = lo + 1 hi = hi - 1 end do end subroutine reverse_segment end subroutine ${name1}$_${sname}$_ord_sort #:endblock #:endfor #:endfor end submodule stdlib_sorting_ord_sort fortran-lang-stdlib-0ede301/src/sorting/stdlib_sorting.fypp0000664000175000017500000007416415135654166024404 0ustar alastairalastair#include "macros.inc" #:include "common.fypp" #:set INT_TYPES_ALT_NAME = list(zip(INT_TYPES, INT_TYPES, INT_KINDS, INT_CPPS)) #:set REAL_TYPES_ALT_NAME = list(zip(REAL_TYPES, REAL_TYPES, REAL_KINDS, REAL_CPPS)) #:set STRING_TYPES_ALT_NAME = list(zip(STRING_TYPES, STRING_TYPES, STRING_KINDS, STRING_CPPS)) #:set CHAR_TYPES_ALT_NAME = list(zip(["character(len=*)"], ["character(len=len(array))"], ["char"], [""])) #:set BITSETS_TYPES_ALT_NAME = list(zip(BITSETS_TYPES, BITSETS_TYPES, BITSETS_KINDS, BITSETS_CPPS)) #:set INT_INDEX_TYPES_ALT_NAME = list(zip(["int_index", "int_index_low"], ["integer(int_index)", "integer(int_index_low)"], ["default", "low"])) #! For better code reuse in fypp, make lists that contain the input types, #! with each having output types and a separate name prefix for subroutines #! This approach allows us to have the same code for all input types. #:set IRSCB_TYPES_ALT_NAME = INT_TYPES_ALT_NAME + REAL_TYPES_ALT_NAME + STRING_TYPES_ALT_NAME + CHAR_TYPES_ALT_NAME & & + BITSETS_TYPES_ALT_NAME #:set IR_INDEX_TYPES_ALT_NAME = INT_TYPES_ALT_NAME + REAL_TYPES_ALT_NAME !! Licensing: !! !! This file is subject both to the Fortran Standard Library license, and !! to additional licensing requirements as it contains translations of !! other software. !! !! The Fortran Standard Library, including this file, is distributed under !! the MIT license that should be included with the library's distribution. !! !! Copyright (c) 2021 Fortran stdlib developers !! !! Permission is hereby granted, free of charge, to any person obtaining a !! copy of this software and associated documentation files (the !! "Software"), to deal in the Software without restriction, including !! without limitation the rights to use, copy, modify, merge, publish, !! distribute, sublicense, and/or sellcopies of the Software, and to permit !! persons to whom the Software is furnished to do so, subject to the !! following conditions: !! !! The above copyright notice and this permission notice shall be included !! in all copies or substantial portions of the Software. !! !! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS !! OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF !! MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. !! IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY !! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, !! TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE !! SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. !! !! Two of the generic subroutines, `ORD_SORT` and `SORT_INDEX`, are !! substantially translations to Fortran 2008 of the `"Rust" sort` sorting !! routines in !! [`slice.rs`](https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs) !! The `rust sort` implementation is distributed with the header: !! !! Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT !! file at the top-level directory of this distribution and at !! http://rust-lang.org/COPYRIGHT. !! !! Licensed under the Apache License, Version 2.0 or the MIT license !! , at your !! option. This file may not be copied, modified, or distributed !! except according to those terms. !! !! so the license for the original`slice.rs` code is compatible with the use !! of modified versions of the code in the Fortran Standard Library under !! the MIT license. !! !! One of the generic subroutines, `SORT`, is substantially a !! translation to Fortran 2008, of the `introsort` of David Musser. !! David Musser has given permission to include a variant of `introsort` !! in the Fortran Standard Library under the MIT license provided !! we cite: !! !! Musser, D.R., “Introspective Sorting and Selection Algorithms,” !! Software—Practice and Experience, Vol. 27(8), 983–993 (August 1997). !! !! as the official source of the algorithm. module stdlib_sorting !! This module implements overloaded sorting subroutines named `ORD_SORT`, !! `SORT_INDEX`, and `SORT`, that each can be used to sort four kinds !! of `INTEGER` arrays, three kinds of `REAL` arrays, `character(len=*)` arrays, !! and arrays of `type(string_type)`. !! ([Specification](../page/specs/stdlib_sorting.html)) !! !! By default sorting is in order of !! increasing value, but there is an option to sort in decreasing order. !! All the subroutines have worst case run time performance of `O(N Ln(N))`, !! but on largely sorted data `ORD_SORT` and `SORT_INDEX` can have a run time !! performance of `O(N)`. !! !! `ORD_SORT` is a translation of the `"Rust" sort` sorting algorithm in !! `slice.rs`: !! https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs !! which in turn is inspired by the `timsort` algorithm of Tim Peters, !! http://svn.python.org/projects/python/trunk/Objects/listsort.txt. !! `ORD_SORT` is a hybrid stable comparison algorithm combining `merge sort`, !! and `insertion sort`. It is always at worst O(N Ln(N)) in sorting random !! data, having a performance about 25% slower than `SORT` on such !! data, but has much better performance than `SORT` on partially !! sorted data, having O(N) performance on uniformly non-increasing or !! non-decreasing data. !! !! `SORT_INDEX` is a modification of `ORD_SORT` so that in addition to !! sorting the input array, it returns the indices that map to a !! stable sort of the original array. These indices are !! intended to be used to sort data that is correlated with the input !! array, e.g., different arrays in a database, different columns of a !! rank 2 array, different elements of a derived type. It is less !! efficient than `ORD_SORT` at sorting a simple array. !! !! `SORT` uses the `INTROSORT` sorting algorithm of David Musser, !! http://www.cs.rpi.edu/~musser/gp/introsort.ps. `introsort` is a hybrid !! unstable comparison algorithm combining `quicksort`, `insertion sort`, and !! `heap sort`. While this algorithm is always O(N Ln(N)) it is relatively !! fast on randomly ordered data, but inconsistent in performance on partly !! sorted data, sometimes having `merge sort` performance, sometimes having !! better than `quicksort` performance. `UNORD_SOORT` is about 25% !! more efficient than `ORD_SORT` at sorting purely random data, but af an !! order of `Ln(N)` less efficient at sorting partially sorted data. use stdlib_kinds, only: & int8, & int16, & int32, & int64, & sp, & dp, & xdp, & qp use stdlib_optval, only: optval use stdlib_string_type, only: string_type, assignment(=), operator(>), & operator(>=), operator(<), operator(<=) #if STDLIB_BITSETS use stdlib_bitsets, only: bitset_64, bitset_large, & assignment(=), operator(>), operator(>=), operator(<), operator(<=) #endif implicit none private integer, parameter, public :: int_index = int64 !! Integer kind for indexing integer, parameter, public :: int_index_low = int32 !! Integer kind for indexing using less than `huge(1_int32)` values ! Constants for use by tim_sort integer, parameter :: & ! The maximum number of entries in a run stack, good for an array of ! 2**64 elements see ! https://svn.python.org/projects/python/trunk/Objects/listsort.txt max_merge_stack = int( ceiling( log( 2._dp**64 ) / & log(1.6180339887_dp) ) ) type run_type !! Version: experimental !! !! Used to pass state around in a stack among helper functions for the !! `ORD_SORT` and `SORT_INDEX` algorithms integer(int_index) :: base = 0 integer(int_index) :: len = 0 end type run_type public ord_sort !! Version: experimental !! !! The generic subroutine implementing the `ORD_SORT` algorithm to return !! an input array with its elements sorted in order of (non-)decreasing !! value. Its use has the syntax: !! !! call ord_sort( array[, work, reverse] ) !! !! with the arguments: !! !! * array: the rank 1 array to be sorted. It is an `intent(inout)` !! argument of any of the types `integer(int8)`, `integer(int16)`, !! `integer(int32)`, `integer(int64)`, `real(real32)`, `real(real64)`, !! `real(real128)`, `character(*)`, `type(string_type)`, !! `type(bitset_64)`, `type(bitset_large)`. If both the !! type of `array` is real and at least one of the elements is a !! `NaN`, then the ordering of the result is undefined. Otherwise it !! is defined to be the original elements in non-decreasing order. !! !! * work (optional): shall be a rank 1 array of the same type as !! `array`, and shall have at least `size(array)/2` elements. It is an !! `intent(out)` argument to be used as "scratch" memory !! for internal record keeping. If associated with an array in static !! storage, its use can significantly reduce the stack memory requirements !! for the code. Its value on return is undefined. !! !! * `reverse` (optional): shall be a scalar of type default logical. It !! is an `intent(in)` argument. If present with a value of `.true.` then !! `array` will be sorted in order of non-increasing values in stable !! order. Otherwise index will sort `array` in order of non-decreasing !! values in stable order. !! !!#### Example !! !!```fortran !! ... !! ! Read arrays from sorted files !! call read_sorted_file( 'dummy_file1', array1 ) !! call read_sorted_file( 'dummy_file2', array2 ) !! ! Concatenate the arrays !! allocate( array( size(array1) + size(array2) ) ) !! array( 1:size(array1) ) = array1(:) !! array( size(array1)+1:size(array1)+size(array2) ) = array2(:) !! ! Sort the resulting array !! call ord_sort( array, work ) !! ! Process the sorted array !! call array_search( array, values ) !! ... !!``` public sort !! Version: experimental !! !! The generic subroutine implementing the `SORT` algorithm to return !! an input array with its elements sorted in order of (non-)decreasing !! value. Its use has the syntax: !! !! call sort( array[, reverse] ) !! !! with the arguments: !! !! * array: the rank 1 array to be sorted. It is an `intent(inout)` !! argument of any of the types `integer(int8)`, `integer(int16)`, !! `integer(int32)`, `integer(int64)`, `real(real32)`, `real(real64)`, !! `real(real128)`, `character(*)`, `type(string_type)`, !! `type(bitset_64)`, `type(bitset_large)`. If both the type !! of `array` is real and at least one of the elements is a `NaN`, then !! the ordering of the result is undefined. Otherwise it is defined to be the !! original elements in non-decreasing order. !! * `reverse` (optional): shall be a scalar of type default logical. It !! is an `intent(in)` argument. If present with a value of `.true.` then !! `array` will be sorted in order of non-increasing values in unstable !! order. Otherwise index will sort `array` in order of non-decreasing !! values in unstable order. !! !!#### Example !! !!```fortran !! ... !! ! Read random data from a file !! call read_file( 'dummy_file', array ) !! ! Sort the random data !! call sort( array ) !! ! Process the sorted data !! call array_search( array, values ) !! ... !!``` public radix_sort !! Version: experimental !! !! The generic subroutine implementing the LSD radix sort algorithm to return !! an input array with its elements sorted in order of (non-)decreasing !! value. Its use has the syntax: !! !! call radix_sort( array[, work, reverse] ) !! !! with the arguments: !! !! * array: the rank 1 array to be sorted. It is an `intent(inout)` !! argument of any of the types `integer(int8)`, `integer(int16)`, !! `integer(int32)`, `integer(int64)`, `real(real32)`, `real(real64)`. !! If both the type of `array` is real and at least one of the !! elements is a `NaN`, then the ordering of the result is undefined. !! Otherwise it is defined to be the original elements in !! non-decreasing order. Especially, -0.0 is lesser than 0.0. !! !! * work (optional): shall be a rank 1 array of the same type as !! `array`, and shall have at least `size(array)` elements. It is an !! `intent(inout)` argument to be used as buffer. Its value on return is !! undefined. If it is not present, `radix_sort` will allocate a !! buffer for use, and deallocate it before return. If you do several !! similar `radix_sort`s, reusing the `work` array is a good parctice. !! This argument is not present for `int8_radix_sort` because it use !! counting sort, so no buffer is needed. !! !! * `reverse` (optional): shall be a scalar of type default logical. It !! is an `intent(in)` argument. If present with a value of `.true.` then !! `array` will be sorted in order of non-increasing values in stable !! order. Otherwise index will sort `array` in order of non-decreasing !! values in stable order. !! !!#### Example !! !!```fortran !! ... !! ! Read random data from a file !! call read_file( 'dummy_file', array ) !! ! Sort the random data !! call radix_sort( array ) !! ... !!``` public sort_adjoint !! Version: experimental !! !! The generic subroutine implementing the `SORT_ADJ` algorithm to !! return an adjoint array whose elements are sorted in the same order !! as the input array in the !! desired direction. It is primarily intended to be used to sort a !! rank 1 `integer` or `real` array based on the values of a component of the array. !! Its use has the syntax: !! !! call sort_adjoint( array, adjoint_array[, work, iwork, reverse ] ) !! !! with the arguments: !! !! * array: the rank 1 array to be sorted. It is an `intent(inout)` !! argument of any of the types `integer(int8)`, `integer(int16)`, !! `integer(int32)`, `integer(int64)`, `real(real32)`, `real(real64)`, !! `real(real128)`, `character(*)`, `type(string_type)`, !! `type(bitset_64)`, `type(bitset_large)`. If both the !! type of `array` is real and at least one of the elements is a `NaN`, !! then the ordering of the `array` and `adjoint_array` results is undefined. !! Otherwise it is defined to be as specified by reverse. !! !! * adjoint_array: a rank 1 `integer` or `real` array. It is an `intent(inout)` !! argument. Its size shall be the !! same as `array`. On return, its elements are sorted in the same order !! as the input `array` in the direction specified by `reverse`. !! !! * work (optional): shall be a rank 1 array of the same type as !! `array`, and shall have at least `size(array)/2` elements. It is an !! `intent(out)` argument to be used as "scratch" memory !! for internal record keeping. If associated with an array in static !! storage, its use can significantly reduce the stack memory requirements !! for the code. Its value on return is undefined. !! !! * iwork (optional): shall be a rank 1 integer array of the same type as `adjoint_array`, !! and shall have at least `size(array)/2` elements. It is an !! `intent(out)` argument to be used as "scratch" memory !! for internal record keeping. If associated with an array in static !! storage, its use can significantly reduce the stack memory requirements !! for the code. Its value on return is undefined. !! !! * `reverse` (optional): shall be a scalar of type default logical. It !! is an `intent(in)` argument. If present with a value of `.true.` then !! `array` will be sorted in order of non-increasing values in stable !! order. Otherwise `array` will be sorted in order of non-decreasing !! values in stable order. !! !!#### Examples !! !! Sorting a related rank one array: !! !!```Fortran !!program example_sort_adjoint !! use stdlib_sorting, only: sort_adjoint !! implicit none !! integer, allocatable :: array(:) !! real, allocatable :: adj(:) !! !! array = [5, 4, 3, 1, 10, 4, 9] !! allocate(adj, source=real(array)) !! !! call sort_adjoint(array, adj) !! !! print *, array !print [1, 3, 4, 4, 5, 9, 10] !! print *, adj !print [1., 3., 4., 4., 5., 9., 10.] !! !!end program example_sort_adjoint !!``` public sort_index !! Version: experimental !! !! The generic subroutine implementing the `SORT_INDEX` algorithm to !! return an index array whose elements would sort the input array in the !! desired direction. It is primarily intended to be used to sort a !! derived type array based on the values of a component of the array. !! Its use has the syntax: !! !! call sort_index( array, index[, work, iwork, reverse ] ) !! !! with the arguments: !! !! * array: the rank 1 array to be sorted. It is an `intent(inout)` !! argument of any of the types `integer(int8)`, `integer(int16)`, !! `integer(int32)`, `integer(int64)`, `real(real32)`, `real(real64)`, !! `real(real128)`, `character(*)`, `type(string_type)`, !! `type(bitset_64)`, `type(bitset_large)`. If both the !! type of `array` is real and at least one of the elements is a `NaN`, !! then the ordering of the `array` and `index` results is undefined. !! Otherwise it is defined to be as specified by reverse. !! !! * index: a rank 1 array of sorting indices. It is an `intent(out)` !! argument of the type `integer(int_index)`. Its size shall be the !! same as `array`. On return, if defined, its elements would !! sort the input `array` in the direction specified by `reverse`. !! !! * work (optional): shall be a rank 1 array of the same type as !! `array`, and shall have at least `size(array)/2` elements. It is an !! `intent(out)` argument to be used as "scratch" memory !! for internal record keeping. If associated with an array in static !! storage, its use can significantly reduce the stack memory requirements !! for the code. Its value on return is undefined. !! !! * iwork (optional): shall be a rank 1 integer array of kind `int_index`, !! and shall have at least `size(array)/2` elements. It is an !! `intent(out)` argument to be used as "scratch" memory !! for internal record keeping. If associated with an array in static !! storage, its use can significantly reduce the stack memory requirements !! for the code. Its value on return is undefined. !! !! * `reverse` (optional): shall be a scalar of type default logical. It !! is an `intent(in)` argument. If present with a value of `.true.` then !! `index` will sort `array` in order of non-increasing values in stable !! order. Otherwise index will sort `array` in order of non-decreasing !! values in stable order. !! !!#### Examples !! !! Sorting a related rank one array: !! !!```Fortran !! subroutine sort_related_data( a, b, work, index, iwork ) !! ! Sort `b` in terms or its related array `a` !! integer, intent(inout) :: a(:) !! integer(int32), intent(inout) :: b(:) ! The same size as a !! integer(int32), intent(out) :: work(:) !! integer(int_index), intent(out) :: index(:) !! integer(int_index), intent(out) :: iwork(:) !! ! Find the indices to sort a !! call sort_index(a, index(1:size(a)),& !! work(1:size(a)/2), iwork(1:size(a)/2)) !! ! Sort b based on the sorting of a !! b(:) = b( index(1:size(a)) ) !! end subroutine sort_related_data !!``` !! !! Sorting a rank 2 array based on the data in a column !! !!```Fortran !! subroutine sort_related_data( array, column, work, index, iwork ) !! ! Sort `a_data` in terms or its component `a` !! integer, intent(inout) :: a(:,:) !! integer(int32), intent(in) :: column !! integer(int32), intent(out) :: work(:) !! integer(int_index), intent(out) :: index(:) !! integer(int_index), intent(out) :: iwork(:) !! integer, allocatable :: dummy(:) !! integer :: i !! allocate(dummy(size(a, dim=1))) !! ! Extract a component of `a_data` !! dummy(:) = a(:, column) !! ! Find the indices to sort the column !! call sort_index(dummy, index(1:size(dummy)),& !! work(1:size(dummy)/2), iwork(1:size(dummy)/2)) !! ! Sort a based on the sorting of its column !! do i=1, size(a, dim=2) !! a(:, i) = a(index(1:size(a, dim=1)), i) !! end do !! end subroutine sort_related_data !!``` !! !! Sorting an array of a derived type based on the dsta in one component !!```fortran !! subroutine sort_a_data( a_data, a, work, index, iwork ) !! ! Sort `a_data` in terms or its component `a` !! type(a_type), intent(inout) :: a_data(:) !! integer(int32), intent(inout) :: a(:) !! integer(int32), intent(out) :: work(:) !! integer(int_index), intent(out) :: index(:) !! integer(int_index), intent(out) :: iwork(:) !! ! Extract a component of `a_data` !! a(1:size(a_data)) = a_data(:) % a !! ! Find the indices to sort the component !! call sort_index(a(1:size(a_data)), index(1:size(a_data)),& !! work(1:size(a_data)/2), iwork(1:size(a_data)/2)) !! ! Sort a_data based on the sorting of that component !! a_data(:) = a_data( index(1:size(a_data)) ) !! end subroutine sort_a_data !!``` interface ord_sort !! Version: experimental !! !! The generic subroutine interface implementing the `ORD_SORT` algorithm, !! a translation to Fortran 2008, of the `"Rust" sort` algorithm found in !! `slice.rs` !! https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs#L2159 !! `ORD_SORT` is a hybrid stable comparison algorithm combining `merge sort`, !! and `insertion sort`. !! ([Specification](../page/specs/stdlib_sorting.html#ord_sort-sorts-an-input-array)) !! !! It is always at worst O(N Ln(N)) in sorting random !! data, having a performance about 25% slower than `SORT` on such !! data, but has much better performance than `SORT` on partially !! sorted data, having O(N) performance on uniformly non-increasing or !! non-decreasing data. #:for t1, t2, name1, cpp1 in IRSCB_TYPES_ALT_NAME #:block generate_cpp(cpp_var=cpp1) module subroutine ${name1}$_ord_sort( array, work, reverse ) !! Version: experimental !! !! `${name1}$_ord_sort( array )` sorts the input `ARRAY` of type `${t1}$` !! using a hybrid sort based on the `"Rust" sort` algorithm found in `slice.rs` ${t1}$, intent(inout) :: array(0:) ${t2}$, intent(out), optional :: work(0:) logical, intent(in), optional :: reverse end subroutine ${name1}$_ord_sort #:endblock #:endfor end interface ord_sort interface radix_sort !! Version: experimental !! !! The generic subroutine interface implementing the LSD radix sort algorithm, !! see https://en.wikipedia.org/wiki/Radix_sort for more details. !! It is always O(N) in sorting random data, but need a O(N) buffer. !! ([Specification](../page/specs/stdlib_sorting.html#radix_sort-sorts-an-input-array)) !! pure module subroutine int8_radix_sort(array, reverse) integer(kind=int8), dimension(:), intent(inout) :: array logical, intent(in), optional :: reverse end subroutine int8_radix_sort pure module subroutine int16_radix_sort(array, work, reverse) integer(kind=int16), dimension(:), intent(inout) :: array integer(kind=int16), dimension(:), intent(inout), target, optional :: work logical, intent(in), optional :: reverse end subroutine int16_radix_sort pure module subroutine int32_radix_sort(array, work, reverse) integer(kind=int32), dimension(:), intent(inout) :: array integer(kind=int32), dimension(:), intent(inout), target, optional :: work logical, intent(in), optional :: reverse end subroutine int32_radix_sort pure module subroutine int64_radix_sort(array, work, reverse) integer(kind=int64), dimension(:), intent(inout) :: array integer(kind=int64), dimension(:), intent(inout), target, optional :: work logical, intent(in), optional :: reverse end subroutine int64_radix_sort module subroutine sp_radix_sort(array, work, reverse) real(kind=sp), dimension(:), intent(inout), target :: array real(kind=sp), dimension(:), intent(inout), target, optional :: work logical, intent(in), optional :: reverse end subroutine sp_radix_sort module subroutine dp_radix_sort(array, work, reverse) real(kind=dp), dimension(:), intent(inout), target :: array real(kind=dp), dimension(:), intent(inout), target, optional :: work logical, intent(in), optional :: reverse end subroutine dp_radix_sort end interface radix_sort interface sort !! Version: experimental !! !! The generic subroutine interface implementing the `SORT` algorithm, based !! on the `introsort` of David Musser. !! ([Specification](../page/specs/stdlib_sorting.html#sort-sorts-an-input-array)) #:for t1, t2, name1, cpp1 in IRSCB_TYPES_ALT_NAME #:block generate_cpp(cpp_var=cpp1) pure module subroutine ${name1}$_sort( array, reverse ) !! Version: experimental !! !! `${name1}$_sort( array[, reverse] )` sorts the input `ARRAY` of type `${t1}$` !! using a hybrid sort based on the `introsort` of David Musser. !! The algorithm is of order O(N Ln(N)) for all inputs. !! Because it relies on `quicksort`, the coefficient of the O(N Ln(N)) !! behavior is small for random data compared to other sorting algorithms. ${t1}$, intent(inout) :: array(0:) logical, intent(in), optional :: reverse end subroutine ${name1}$_sort #:endblock #:endfor end interface sort interface sort_adjoint !! Version: experimental !! !! The generic subroutine interface implementing the `SORT_ADJ` algorithm, !! based on the `"Rust" sort` algorithm found in `slice.rs` !! https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs#L2159 !! but modified to return an array of indices that would provide a stable !! sort of the rank one `ARRAY` input. !! ([Specification](../page/specs/stdlib_sorting.html#sort_adjoint-creates-an-array-of-sorting-indices-for-an-input-array-while-also-sorting-the-array)) !! !! The indices by default correspond to a !! non-decreasing sort, but if the optional argument `REVERSE` is present !! with a value of `.TRUE.` the indices correspond to a non-increasing sort. #:for ti, tii, namei in IR_INDEX_TYPES_ALT_NAME #:for t1, t2, name1, cpp1 in IRSCB_TYPES_ALT_NAME #:block generate_cpp(cpp_var=cpp1) module subroutine ${name1}$_${namei}$_sort_adjoint( array, adjoint_array, work, iwork, & reverse ) !! Version: experimental !! !! `${name1}$_${namei}$_sort_adjoint( array, adjoint_array[, work, iwork, reverse] )` sorts !! an input `ARRAY` of type `${t1}$` !! using a hybrid sort based on the `"Rust" sort` algorithm found in `slice.rs` !! and returns the sorted `ARRAY` and an array `INDEX` of indices in the !! order that would sort the input `ARRAY` in the desired direction. ${t1}$, intent(inout) :: array(0:) ${ti}$, intent(inout) :: adjoint_array(0:) ${t2}$, intent(out), optional :: work(0:) ${ti}$, intent(out), optional :: iwork(0:) logical, intent(in), optional :: reverse end subroutine ${name1}$_${namei}$_sort_adjoint #:endblock #:endfor #:endfor end interface sort_adjoint interface sort_index !! Version: experimental !! !! The generic subroutine interface implementing the `SORT_INDEX` algorithm, !! based on the `"Rust" sort` algorithm found in `slice.rs` !! https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs#L2159 !! but modified to return an array of indices that would provide a stable !! sort of the rank one `ARRAY` input. !! ([Specification](../page/specs/stdlib_sorting.html#sort_index-creates-an-array-of-sorting-indices-for-an-input-array-while-also-sorting-the-array)) !! !! The indices by default correspond to a !! non-decreasing sort, but if the optional argument `REVERSE` is present !! with a value of `.TRUE.` the indices correspond to a non-increasing sort. #:for ki, ti, namei in INT_INDEX_TYPES_ALT_NAME #:for t1, t2, name1, cpp1 in IRSCB_TYPES_ALT_NAME #:block generate_cpp(cpp_var=cpp1) !> Version: experimental !> !> `${name1}$_sort_index_${namei}$( array, index[, work, iwork, reverse] )` sorts !> an input `ARRAY` of type `${t1}$` !> using a hybrid sort based on the `"Rust" sort` algorithm found in `slice.rs` !> and returns the sorted `ARRAY` and an array `INDEX` of indices in the !> order that would sort the input `ARRAY` in the desired direction. module procedure ${name1}$_sort_index_${namei}$ #:endblock #:endfor #:endfor end interface sort_index contains #:for ki, ti, namei in INT_INDEX_TYPES_ALT_NAME #:for t1, t2, name1, cpp1 in IRSCB_TYPES_ALT_NAME #:block generate_cpp(cpp_var=cpp1) subroutine ${name1}$_sort_index_${namei}$( array, index, work, iwork, & reverse ) !! Version: experimental !! !! `${name1}$_sort_index_${namei}$( array, index[, work, iwork, reverse] )` sorts !! an input `ARRAY` of type `${t1}$` !! using a hybrid sort based on the `"Rust" sort` algorithm found in `slice.rs` !! and returns the sorted `ARRAY` and an array `INDEX` of indices in the !! order that would sort the input `ARRAY` in the desired direction. ${t1}$, intent(inout) :: array(0:) ${ti}$, intent(out) :: index(0:) ${t2}$, intent(out), optional :: work(0:) ${ti}$, intent(out), optional :: iwork(0:) logical, intent(in), optional :: reverse integer(int_index) :: array_size, i array_size = size(array, kind=int_index) if ( array_size > huge(index)) then error stop "Too many entries for the kind of index." end if if ( array_size > size(index, kind=int_index) ) then error stop "Too many entries for the size of index." end if do i = 0, array_size-1 index(i) = int(i+1, kind=${ki}$) end do call sort_adjoint(array, index, work, iwork, reverse) end subroutine ${name1}$_sort_index_${namei}$ #:endblock #:endfor #:endfor end module stdlib_sorting fortran-lang-stdlib-0ede301/src/sorting/CMakeLists.txt0000664000175000017500000000104515135654166023202 0ustar alastairalastairset(sorting_fppFiles ) set(sorting_cppFiles stdlib_sorting.fypp stdlib_sorting_ord_sort.fypp stdlib_sorting_sort_adjoint.fypp stdlib_sorting_sort.fypp ) set(sorting_f90Files stdlib_sorting_radix_sort.f90 ) configure_stdlib_target(${PROJECT_NAME}_sorting sorting_f90Files sorting_fppFiles sorting_cppFiles) if(STDLIB_BITSETS) target_link_libraries(${PROJECT_NAME}_sorting PUBLIC ${PROJECT_NAME}_bitsets) endif() target_link_libraries(${PROJECT_NAME}_sorting PUBLIC ${PROJECT_NAME}_core ${PROJECT_NAME}_strings) fortran-lang-stdlib-0ede301/src/sorting/stdlib_sorting_sort.fypp0000664000175000017500000002512615135654166025445 0ustar alastairalastair#include "macros.inc" #:include "common.fypp" #:set INT_TYPES_ALT_NAME = list(zip(INT_TYPES, INT_TYPES, INT_KINDS, INT_CPPS)) #:set REAL_TYPES_ALT_NAME = list(zip(REAL_TYPES, REAL_TYPES, REAL_KINDS, REAL_CPPS)) #:set STRING_TYPES_ALT_NAME = list(zip(STRING_TYPES, STRING_TYPES, STRING_KINDS, STRING_CPPS)) #:set CHAR_TYPES_ALT_NAME = list(zip(["character(len=*)"], ["character(len=len(array))"], ["char"], [""])) #:set BITSETS_TYPES_ALT_NAME = list(zip(BITSETS_TYPES, BITSETS_TYPES, BITSETS_KINDS, BITSETS_CPPS)) #! For better code reuse in fypp, make lists that contain the input types, #! with each having output types and a separate name prefix for subroutines #! This approach allows us to have the same code for all input types. #:set IRSCB_TYPES_ALT_NAME = INT_TYPES_ALT_NAME + REAL_TYPES_ALT_NAME + STRING_TYPES_ALT_NAME + CHAR_TYPES_ALT_NAME & & + BITSETS_TYPES_ALT_NAME #:set SIGN_NAME = ["increase", "decrease"] #:set SIGN_TYPE = [">", "<"] #:set SIGN_OPP_TYPE = ["<", ">"] #:set SIGN_NAME_TYPE = list(zip(SIGN_NAME, SIGN_TYPE, SIGN_OPP_TYPE)) !! Licensing: !! !! This file is subjec† both to the Fortran Standard Library license, and !! to additional licensing requirements as it contains translations of !! other software. !! !! The Fortran Standard Library, including this file, is distributed under !! the MIT license that should be included with the library's distribution. !! !! Copyright (c) 2021 Fortran stdlib developers !! !! Permission is hereby granted, free of charge, to any person obtaining a !! copy of this software and associated documentation files (the !! "Software"), to deal in the Software without restriction, including !! without limitation the rights to use, copy, modify, merge, publish, !! distribute, sublicense, and/or sellcopies of the Software, and to permit !! persons to whom the Software is furnished to do so, subject to the !! following conditions: !! !! The above copyright notice and this permission notice shall be included !! in all copies or substantial portions of the Software. !! !! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS !! OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF !! MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. !! IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY !! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, !! TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE !! SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. !! !! The generic subroutine, `SORT`, is substantially a !! translation to Fortran 2008, of the `introsort` of David Musser. !! David Musser has given permission to include a variant of `introsort` !! in the Fortran Standard Library under the MIT license provided !! we cite: !! !! Musser, D.R., “Introspective Sorting and Selection Algorithms,” !! Software—Practice and Experience, Vol. 27(8), 983–993 (August 1997). !! !! as the official source of the algorithm. submodule(stdlib_sorting) stdlib_sorting_sort !! This submodule implements the overloaded sorting subroutine `SORT` !! that can be used to sort four kinds of `INTEGER` arrays and three kinds !! of `REAL` arrays. Sorting is in order of increasing value, with the worst !! case run time performance of `O(N Ln(N))`. !! !! `SORT` uses the `INTROSORT` sorting algorithm of David Musser, !! http://www.cs.rpi.edu/~musser/gp/introsort.ps. `introsort` is a hybrid !! unstable comparison algorithm combining `quicksort`, `insertion sort`, and !! `heap sort`. While this algorithm is always O(N Ln(N)) it is relatively !! fast on randomly ordered data, but inconsistent in performance on partly !! sorted data, sometimes having `merge sort` performance, sometimes having !! better than `quicksort` performance. implicit none contains #:for t1, t2, name1, cpp1 in IRSCB_TYPES_ALT_NAME #:block generate_cpp(cpp_var=cpp1) pure module subroutine ${name1}$_sort( array, reverse ) ${t1}$, intent(inout) :: array(0:) logical, intent(in), optional :: reverse if(optval(reverse, .false.))then call ${name1}$_decrease_sort(array) else call ${name1}$_increase_sort(array) endif end subroutine ${name1}$_sort #:endblock #:endfor #:for sname, signt, signoppt in SIGN_NAME_TYPE #:for t1, t2, name1, cpp1 in IRSCB_TYPES_ALT_NAME #:block generate_cpp(cpp_var=cpp1) pure subroutine ${name1}$_${sname}$_sort( array ) ! `${name1}$_${sname}$_sort( array )` sorts the input `ARRAY` of type `${t1}$` ! using a hybrid sort based on the `introsort` of David Musser. As with ! `introsort`, `${name1}$_${sname}$_sort( array )` is an unstable hybrid comparison ! algorithm using `quicksort` for the main body of the sort tree, ! supplemented by `insertion sort` for the outer branches, but if ! `quicksort` is converging too slowly the algorithm resorts ! to `heapsort`. The algorithm is of order O(N Ln(N)) for all inputs. ! Because it relies on `quicksort`, the coefficient of the O(N Ln(N)) ! behavior is typically small compared to other sorting algorithms. ${t1}$, intent(inout) :: array(0:) integer(int32) :: depth_limit depth_limit = 2 * int( floor( log( real( size( array, kind=int_index), & kind=dp) ) / log(2.0_dp) ), & kind=int32 ) call introsort(array, depth_limit) contains pure recursive subroutine introsort( array, depth_limit ) ! It devolves to `insertionsort` if the remaining number of elements ! is fewer than or equal to `INSERT_SIZE`, `heapsort` if the completion ! of the `quicksort` is too slow as estimated from `DEPTH_LIMIT`, ! otherwise sorting is done by a `quicksort`. ${t1}$, intent(inout) :: array(0:) integer(int32), intent(in) :: depth_limit integer(int_index), parameter :: insert_size = 16_int_index integer(int_index) :: index if ( size(array, kind=int_index) <= insert_size ) then ! May be best at the end of SORT processing the whole array ! See Musser, D.R., “Introspective Sorting and Selection ! Algorithms,” Software—Practice and Experience, Vol. 27(8), ! 983–993 (August 1997). call insertion_sort( array ) else if ( depth_limit == 0 ) then call heap_sort( array ) else call partition( array, index ) call introsort( array(0:index-1), depth_limit-1 ) call introsort( array(index+1:), depth_limit-1 ) end if end subroutine introsort pure subroutine partition( array, index ) ! quicksort partition using median of three. ${t1}$, intent(inout) :: array(0:) integer(int_index), intent(out) :: index ${t2}$ :: u, v, w, x, y integer(int_index) :: i, j ! Determine median of three and exchange it with the end. u = array( 0 ) v = array( size(array, kind=int_index)/2-1 ) w = array( size(array, kind=int_index)-1 ) if ( (u ${signt}$ v) .neqv. (u ${signt}$ w) ) then x = u y = array(0) array(0) = array( size( array, kind=int_index ) - 1 ) array( size( array, kind=int_index ) - 1 ) = y else if ( (v ${signoppt}$ u) .neqv. (v ${signoppt}$ w) ) then x = v y = array(size( array, kind=int_index )/2-1) array( size( array, kind=int_index )/2-1 ) = & array( size( array, kind=int_index )-1 ) array( size( array, kind=int_index )-1 ) = y else x = w end if ! Partition the array. i = -1_int_index do j = 0_int_index, size(array, kind=int_index)-2 if ( array(j) ${signoppt}$= x ) then i = i + 1 y = array(i) array(i) = array(j) array(j) = y end if end do y = array(i+1) array(i+1) = array(size(array, kind=int_index)-1) array(size(array, kind=int_index)-1) = y index = i + 1 end subroutine partition pure subroutine insertion_sort( array ) ! Bog standard insertion sort. ${t1}$, intent(inout) :: array(0:) integer(int_index) :: i, j ${t2}$ :: key do j=1_int_index, size(array, kind=int_index)-1 key = array(j) i = j - 1 do while( i >= 0 ) if ( array(i) ${signoppt}$= key ) exit array(i+1) = array(i) i = i - 1 end do array(i+1) = key end do end subroutine insertion_sort pure subroutine heap_sort( array ) ! A bog standard heap sort ${t1}$, intent(inout) :: array(0:) integer(int_index) :: i, heap_size ${t2}$ :: y heap_size = size( array, kind=int_index ) ! Build the max heap do i = (heap_size-2)/2_int_index, 0_int_index, -1_int_index call max_heapify( array, i, heap_size ) end do do i = heap_size-1, 1_int_index, -1_int_index ! Swap the first element with the current final element y = array(0) array(0) = array(i) array(i) = y ! Sift down using max_heapify call max_heapify( array, 0_int_index, i ) end do end subroutine heap_sort pure recursive subroutine max_heapify( array, i, heap_size ) ! Transform the array into a max heap ${t1}$, intent(inout) :: array(0:) integer(int_index), intent(in) :: i, heap_size integer(int_index) :: l, r, largest ${t2}$ :: y largest = i l = 2_int_index * i + 1_int_index r = l + 1_int_index if ( l < heap_size ) then if ( array(l) ${signt}$ array(largest) ) largest = l end if if ( r < heap_size ) then if ( array(r) ${signt}$ array(largest) ) largest = r end if if ( largest /= i ) then y = array(i) array(i) = array(largest) array(largest) = y call max_heapify( array, largest, heap_size ) end if end subroutine max_heapify end subroutine ${name1}$_${sname}$_sort #:endblock #:endfor #:endfor end submodule stdlib_sorting_sort fortran-lang-stdlib-0ede301/src/stats/0000775000175000017500000000000015135654166020113 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/stats/stdlib_stats_distribution_exponential.fypp0000664000175000017500000003243615135654166030727 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES module stdlib_stats_distribution_exponential use ieee_arithmetic, only: ieee_value, ieee_quiet_nan use stdlib_kinds, only : sp, dp, xdp, qp, int32 use stdlib_random, only : dist_rand use stdlib_stats_distribution_uniform, only : uni=>rvs_uniform implicit none private integer :: ke(0:255) real(dp) :: we(0:255), fe(0:255) logical :: zig_exp_initialized = .false. public :: rvs_exp public :: pdf_exp public :: cdf_exp interface rvs_exp !! Version experimental !! !! Exponential Distribution Random Variates !! ([Specification](../page/specs/stdlib_stats_distribution_exponential.html# !! rvs_exp-exponential-distribution-random-variates)) !! module procedure rvs_exp_0_rsp !0 dummy variable ! new interfaces using loc and scale #:for k1, t1 in RC_KINDS_TYPES module procedure rvs_exp_${t1[0]}$${k1}$ !1 dummy variable #:endfor #:for k1, t1 in RC_KINDS_TYPES module procedure rvs_exp_array_${t1[0]}$${k1}$ !2 dummy variables #:endfor ! original interfaces using lambda #:for k1, t1 in RC_KINDS_TYPES module procedure rvs_exp_lambda_${t1[0]}$${k1}$ !1 dummy variable #:endfor #:for k1, t1 in RC_KINDS_TYPES module procedure rvs_exp_array_lambda_${t1[0]}$${k1}$ !2 dummy variables #:endfor end interface rvs_exp interface pdf_exp !! Version experimental !! !! Exponential Distribution Probability Density Function !! ([Specification](../page/specs/stdlib_stats_distribution_exponential.html# !! pdf_exp-exponential-distribution-probability-density-function)) !! ! new interfaces using loc and scale #:for k1, t1 in RC_KINDS_TYPES module procedure pdf_exp_${t1[0]}$${k1}$ #:endfor ! original interfaces using lambda #:for k1, t1 in RC_KINDS_TYPES module procedure pdf_exp_lambda_${t1[0]}$${k1}$ #:endfor end interface pdf_exp interface cdf_exp !! Version experimental !! !! Exponential Cumulative Distribution Function !! ([Specification](../page/specs/stdlib_stats_distribution_exponential.html# !! cdf_exp-exponential-distribution-cumulative-distribution-function)) !! ! new interfaces using loc and scale #:for k1, t1 in RC_KINDS_TYPES module procedure cdf_exp_${t1[0]}$${k1}$ #:endfor ! original interfaces using lambda #:for k1, t1 in RC_KINDS_TYPES module procedure cdf_exp_lambda_${t1[0]}$${k1}$ #:endfor end interface cdf_exp contains impure subroutine zigset ! Marsaglia & Tsang generator for random normals & random exponentials. ! Translated from C by Alan Miller (amiller@bigpond.net.au) ! ! Marsaglia, G. & Tsang, W.W. (2000) 'The ziggurat method for generating ! random variables', J. Statist. Software, v5(8). ! ! This is an electronic journal which can be downloaded from: ! http://www.jstatsoft.org/v05/i08 ! ! Latest version - 1 January 2001 ! real(dp), parameter :: M2 = 2147483648.0_dp, ve = 0.003949659822581572_dp real(dp), parameter :: ONE = 1.0_dp real(dp) :: de, te, q integer :: i de = 7.697117470131487_dp te = de ! tables for random exponentials q = ve * exp(de) ke(0) = int((de / q) * M2, kind = int32) ke(1) = 0 we(0) = q / M2 we(255) = de / M2 fe(0) = ONE fe(255) = exp(- de) do i = 254, 1, -1 de = -log(ve / de + exp(- de)) ke(i+1) = int(M2 * (de / te), kind = int32) te = de fe(i) = exp(- de) we(i) = de / M2 end do zig_exp_initialized = .true. end subroutine zigset #:for k1, t1 in REAL_KINDS_TYPES impure function rvs_exp_0_${t1[0]}$${k1}$( ) result(res) ! ! Standard exponential random variate (lambda=1; scale=1/lambda=1) ! ${t1}$ :: res, x ${t1}$, parameter :: r = 7.69711747013104972_${k1}$ integer :: jz, iz if(.not. zig_exp_initialized ) call zigset iz = 0 jz = dist_rand(1_int32) ! 32bit random integer iz = iand( jz, 255 ) ! random integer in [0, 255] if( abs( jz ) < ke(iz) ) then res = abs(jz) * we(iz) else L1: do if( iz == 0 ) then res = r - log( uni(1.0_${k1}$) ) exit L1 end if x = abs( jz ) * we(iz) if(fe(iz) + uni(1.0_${k1}$) * (fe(iz-1) - fe(iz)) < exp(-x)) then res = x exit L1 end if jz = dist_rand(1_int32) iz = iand( jz, 255 ) if( abs( jz ) < ke(iz) ) then res = abs( jz ) * we(iz) exit L1 end if end do L1 endif end function rvs_exp_0_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES impure elemental function rvs_exp_${t1[0]}$${k1}$(loc, scale) result(res) ! ! Exponential distributed random variate ! ${t1}$, intent(in) :: loc, scale ${t1}$ :: res if (scale <= 0._${k1}$) then res = ieee_value(1._${k1}$, ieee_quiet_nan) else res = rvs_exp_0_${t1[0]}$${k1}$( ) res = res * scale + loc end if end function rvs_exp_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES impure elemental function rvs_exp_${t1[0]}$${k1}$(loc, scale) result(res) ${t1}$, intent(in) :: loc, scale ${t1}$ :: res real(${k1}$) :: tr, ti tr = rvs_exp_r${k1}$(loc%re, scale%re) ti = rvs_exp_r${k1}$(loc%im, scale%im) res = cmplx(tr, ti, kind=${k1}$) end function rvs_exp_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES impure function rvs_exp_array_${t1[0]}$${k1}$(loc, scale, array_size) result(res) ${t1}$, intent(in) :: loc, scale integer, intent(in) :: array_size ${t1}$ :: res(array_size), x, re ${t1}$, parameter :: r = 7.69711747013104972_${k1}$ integer :: jz, iz, i if (scale <= 0._${k1}$) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if if(.not. zig_exp_initialized) call zigset do i = 1, array_size iz = 0 jz = dist_rand(1_int32) iz = iand( jz, 255 ) if( abs( jz ) < ke(iz) ) then re = abs(jz) * we(iz) else L1: do if( iz == 0 ) then re = r - log( uni(1.0_${k1}$) ) exit L1 end if x = abs( jz ) * we(iz) if(fe(iz) + uni(1.0_${k1}$)*(fe(iz-1)-fe(iz)) < exp(-x)) then re = x exit L1 end if jz = dist_rand(1_int32) iz = iand( jz, 255 ) if( abs( jz ) < ke(iz) ) then re = abs( jz ) * we(iz) exit L1 end if end do L1 endif res(i) = re * scale + loc end do end function rvs_exp_array_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES impure function rvs_exp_array_${t1[0]}$${k1}$(loc, scale, array_size) result(res) ${t1}$, intent(in) :: loc, scale integer, intent(in) :: array_size ${t1}$ :: res(array_size) integer :: i real(${k1}$) :: tr, ti do i = 1, array_size tr = rvs_exp_r${k1}$(loc%re, scale%re) ti = rvs_exp_r${k1}$(loc%im, scale%im) res(i) = cmplx(tr, ti, kind=${k1}$) end do end function rvs_exp_array_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES elemental function pdf_exp_${t1[0]}$${k1}$(x, loc, scale) result(res) ! ! Exponential Distribution Probability Density Function ! ${t1}$, intent(in) :: x, loc, scale real(${k1}$) :: res if (scale <= 0._${k1}$) then res = ieee_value(1._${k1}$, ieee_quiet_nan) else if (x < loc) then res = 0._${k1}$ else res = exp(- (x - loc) / scale) / scale end if end function pdf_exp_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES elemental function pdf_exp_${t1[0]}$${k1}$(x, loc, scale) result(res) ${t1}$, intent(in) :: x, loc, scale real(${k1}$) :: res res = pdf_exp_r${k1}$(x%re, loc%re, scale%re) res = res * pdf_exp_r${k1}$(x%im, loc%im, scale%im) end function pdf_exp_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES elemental function cdf_exp_${t1[0]}$${k1}$(x, loc, scale) result(res) ! ! Exponential Distribution Cumulative Distribution Function ! ${t1}$, intent(in) :: x, loc, scale real(${k1}$) :: res if (scale <= 0._${k1}$) then res = ieee_value(1._${k1}$, ieee_quiet_nan) else if (x < loc) then res = 0._${k1}$ else res = 1.0_${k1}$ - exp(- (x - loc) / scale) end if end function cdf_exp_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES elemental function cdf_exp_${t1[0]}$${k1}$(x, loc, scale) result(res) ${t1}$, intent(in) :: x, loc, scale real(${k1}$) :: res res = cdf_exp_r${k1}$(x%re, loc%re, scale%re) res = res * cdf_exp_r${k1}$(x%im, loc%im, scale%im) end function cdf_exp_${t1[0]}$${k1}$ #:endfor ! ! below: wrapper functions for interfaces using lambda (for backward compatibility) ! #:for k1, t1 in REAL_KINDS_TYPES impure elemental function rvs_exp_lambda_${t1[0]}$${k1}$(lambda) result(res) ! ! Exponential distributed random variate ! ${t1}$, intent(in) :: lambda ${t1}$ :: res res = rvs_exp_${t1[0]}$${k1}$(0._${k1}$, 1.0_${k1}$/lambda) end function rvs_exp_lambda_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES impure elemental function rvs_exp_lambda_${t1[0]}$${k1}$(lambda) result(res) ${t1}$, intent(in) :: lambda ${t1}$ :: res real(${k1}$) :: tr, ti tr = rvs_exp_r${k1}$(0._${k1}$, 1.0_${k1}$/lambda%re) ti = rvs_exp_r${k1}$(0._${k1}$, 1.0_${k1}$/lambda%im) res = cmplx(tr, ti, kind=${k1}$) end function rvs_exp_lambda_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES impure function rvs_exp_array_lambda_${t1[0]}$${k1}$(lambda, array_size) result(res) ${t1}$, intent(in) :: lambda integer, intent(in) :: array_size ${t1}$ :: res(array_size) res = rvs_exp_array_${t1[0]}$${k1}$(0._${k1}$, 1.0_${k1}$/lambda, array_size) end function rvs_exp_array_lambda_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES impure function rvs_exp_array_lambda_${t1[0]}$${k1}$(lambda, array_size) result(res) ${t1}$, intent(in) :: lambda integer, intent(in) :: array_size ${t1}$ :: res(array_size) integer :: i real(${k1}$) :: tr, ti do i = 1, array_size tr = rvs_exp_r${k1}$(0._${k1}$, 1.0_${k1}$/lambda%re) ti = rvs_exp_r${k1}$(0._${k1}$, 1.0_${k1}$/lambda%im) res(i) = cmplx(tr, ti, kind=${k1}$) end do end function rvs_exp_array_lambda_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES elemental function pdf_exp_lambda_${t1[0]}$${k1}$(x, lambda) result(res) ! ! Exponential Distribution Probability Density Function ! ${t1}$, intent(in) :: x, lambda real(${k1}$) :: res res = pdf_exp_${t1[0]}$${k1}$(x, 0._${k1}$, 1.0_${k1}$/lambda) end function pdf_exp_lambda_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES elemental function pdf_exp_lambda_${t1[0]}$${k1}$(x, lambda) result(res) ${t1}$, intent(in) :: x, lambda real(${k1}$) :: res res = pdf_exp_r${k1}$(x%re, 0._${k1}$, 1.0_${k1}$/lambda%re) res = res * pdf_exp_r${k1}$(x%im, 0._${k1}$, 1.0_${k1}$/lambda%im) end function pdf_exp_lambda_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES elemental function cdf_exp_lambda_${t1[0]}$${k1}$(x, lambda) result(res) ! ! Exponential Distribution Cumulative Distribution Function ! ${t1}$, intent(in) :: x, lambda real(${k1}$) :: res res = cdf_exp_${t1[0]}$${k1}$(x, 0._${k1}$, 1.0_${k1}$/lambda) end function cdf_exp_lambda_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES elemental function cdf_exp_lambda_${t1[0]}$${k1}$(x, lambda) result(res) ${t1}$, intent(in) :: x, lambda real(${k1}$) :: res res = cdf_exp_r${k1}$(x%re, 0._${k1}$, 1.0_${k1}$/lambda%re) res = res * cdf_exp_r${k1}$(x%im, 0._${k1}$, 1.0_${k1}$/lambda%im) end function cdf_exp_lambda_${t1[0]}$${k1}$ #:endfor end module stdlib_stats_distribution_exponential fortran-lang-stdlib-0ede301/src/stats/stdlib_stats_moment_all.fypp0000664000175000017500000000673215135654166025731 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(1, MAXRANK + 1) #:set REDRANKS = range(2, MAXRANK + 1) #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_stats) stdlib_stats_moment_all use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_quiet_nan use stdlib_error, only: error_stop use stdlib_optval, only: optval implicit none contains #:for k1, t1 in RC_KINDS_TYPES #:for rank in RANKS #:set RName = rname("moment_all",rank, t1, k1) module function ${RName}$(x, order, center, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: order ${t1}$, intent(in), optional :: center logical, intent(in), optional :: mask ${t1}$ :: res real(${k1}$) :: n ${t1}$ :: center_ if (.not.optval(mask, .true.)) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if n = real(size(x, kind = int64), ${k1}$) if (present(center)) then center_ = center else center_ = mean(x) end if res = sum((x - center_)**order) / n end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in RANKS #:set RName = rname("moment_all",rank, t1, k1, 'dp') module function ${RName}$(x, order, center, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: order real(dp), intent(in), optional :: center logical, intent(in), optional :: mask real(dp) :: res real(dp) :: n real(dp) :: center_ if (.not.optval(mask, .true.)) then res = ieee_value(1._dp, ieee_quiet_nan) return end if n = real(size(x, kind = int64), dp) if (present(center)) then center_ = center else center_ = mean(x) end if res = sum((real(x, dp) - center_)**order) / n end function ${RName}$ #:endfor #:endfor #:for k1, t1 in RC_KINDS_TYPES #:for rank in RANKS #:set RName = rname("moment_mask_all",rank, t1, k1) module function ${RName}$(x, order, center, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: order ${t1}$, intent(in), optional :: center logical, intent(in) :: mask${ranksuffix(rank)}$ ${t1}$ :: res real(${k1}$) :: n ${t1}$ :: center_ n = real(count(mask, kind = int64), ${k1}$) if (present(center)) then center_ = center else center_ = mean(x, mask) end if res = sum((x - center_)**order, mask) / n end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in RANKS #:set RName = rname("moment_mask_all",rank, t1, k1, 'dp') module function ${RName}$(x, order, center, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: order real(dp),intent(in), optional :: center logical, intent(in) :: mask${ranksuffix(rank)}$ real(dp) :: res real(dp) :: n real(dp) :: center_ n = real(count(mask, kind = int64), dp) if (present(center)) then center_ = center else center_ = mean(x, mask) end if res = sum((real(x, dp) - center_)**order, mask) / n end function ${RName}$ #:endfor #:endfor end submodule fortran-lang-stdlib-0ede301/src/stats/stdlib_stats_corr.fypp0000664000175000017500000002213315135654166024540 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_stats) stdlib_stats_corr use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_quiet_nan use stdlib_error, only: error_stop use stdlib_linalg, only: diag use stdlib_optval, only: optval implicit none contains #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("corr",1, t1, k1) module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in), optional :: mask real(${k1}$) :: res if (.not.optval(mask, .true.) .or. size(x) < 2) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if res = 1 end function ${RName}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:set RName = rname("corr",1, t1, k1, 'dp') module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in), optional :: mask real(dp) :: res if (.not.optval(mask, .true.) .or. size(x) < 2) then res = ieee_value(1._dp, ieee_quiet_nan) return end if res = 1 end function ${RName}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("corr_mask",1, t1, k1) module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in) :: mask(:) real(${k1}$) :: res if (count(mask) < 2) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if res = 1 end function ${RName}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:set RName = rname("corr_mask",1, t1, k1, 'dp') module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in) :: mask(:) real(dp) :: res if (count(mask) < 2) then res = ieee_value(1._dp, ieee_quiet_nan) return end if res = 1 end function ${RName}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("corr",2, t1, k1) module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x(:, :) integer, intent(in) :: dim logical, intent(in), optional :: mask ${t1}$ :: res(merge(size(x, 1), size(x, 2), mask = 1 rvs_uniform implicit none private real(dp), parameter :: HALF = 0.5_dp, ONE = 1.0_dp, TWO = 2.0_dp integer :: kn(0:127) real(dp) :: wn(0:127), fn(0:127) logical :: zig_norm_initialized = .false. public :: rvs_normal public :: pdf_normal public :: cdf_normal interface rvs_normal !! version: experimental !! !! Normal Distribution Random Variates !! ([Specification](../page/specs/stdlib_stats_distribution_normal.html# !! rvs_normal-normal-distribution-random-variates)) !! module procedure rvs_norm_0_rsp !0 dummy variable #:for k1, t1 in RC_KINDS_TYPES module procedure rvs_norm_${t1[0]}$${k1}$ !2 dummy variables #:endfor #:for k1, t1 in RC_KINDS_TYPES module procedure rvs_norm_array_${t1[0]}$${k1}$ !3 dummy variables module procedure rvs_norm_array_default_${t1[0]}$${k1}$ !array_size, mold (mold optional for real(dp) only) #:endfor end interface rvs_normal interface pdf_normal !! version: experimental !! !! Normal Distribution Probability Density Function !! ([Specification](../page/specs/stdlib_stats_distribution_normal.html# !! pdf_normal-normal-distribution-probability-density-function)) !! #:for k1, t1 in RC_KINDS_TYPES module procedure pdf_norm_${t1[0]}$${k1}$ #:endfor end interface pdf_normal interface cdf_normal !! version: experimental !! !! Normal Distribution Cumulative Distribution Function !! ([Specification](../page/specs/stdlib_stats_distribution_normal.html# !! cdf_normal-normal-distribution-cumulative-distribution-function)) !! #:for k1, t1 in RC_KINDS_TYPES module procedure cdf_norm_${t1[0]}$${k1}$ #:endfor end interface cdf_normal contains impure subroutine zigset ! Marsaglia & Tsang generator for random normals & random exponentials. ! Translated from C by Alan Miller (amiller@bigpond.net.au), released as public ! domain (https://jblevins.org/mirror/amiller/) ! ! Marsaglia, G. & Tsang, W.W. (2000) `The ziggurat method for generating ! random variables', J. Statist. Software, v5(8). ! ! This is an electronic journal which can be downloaded from: ! http://www.jstatsoft.org/v05/i08 ! ! Latest version - 1 January 2001 ! real(dp), parameter :: M1 = 2147483648.0_dp, vn = 0.00991256303526217_dp real(dp) :: dn, tn, q integer :: i dn = 3.442619855899_dp tn = dn !tables for random normals q = vn*exp(HALF*dn*dn) kn(0) = int((dn/q)*M1, kind=int32) kn(1) = 0 wn(0) = q/M1 wn(127) = dn/M1 fn(0) = ONE fn(127) = exp(-HALF*dn*dn) do i = 126, 1, -1 dn = sqrt(-TWO*log(vn/dn + exp(-HALF*dn*dn))) kn(i + 1) = int((dn/tn)*M1, kind=int32) tn = dn fn(i) = exp(-HALF*dn*dn) wn(i) = dn/M1 end do zig_norm_initialized = .true. end subroutine zigset #:for k1, t1 in REAL_KINDS_TYPES impure function rvs_norm_0_${t1[0]}$${k1}$ () result(res) ! ! Standard normal random variate (0,1) ! ${t1}$ :: res ${t1}$, parameter :: r = 3.442619855899_${k1}$, rr = 1.0_${k1}$/r ${t1}$ :: x, y integer :: hz, iz if (.not. zig_norm_initialized) call zigset iz = 0 hz = dist_rand(1_int32) !32bit random integer iz = iand(hz, 127) !random integer in [0, 127] if (abs(hz) < kn(iz)) then res = hz*wn(iz) else L1: do L2: if (iz == 0) then do x = -log(uni(1.0_${k1}$))*rr y = -log(uni(1.0_${k1}$)) if (y + y >= x*x) exit end do res = r + x if (hz <= 0) res = -res exit L1 end if L2 x = hz*wn(iz) if (fn(iz) + uni(1.0_${k1}$)*(fn(iz - 1) - fn(iz)) < & exp(-HALF*x*x)) then res = x exit L1 end if hz = dist_rand(1_int32) iz = iand(hz, 127) if (abs(hz) < kn(iz)) then res = hz*wn(iz) exit L1 end if end do L1 end if end function rvs_norm_0_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES impure elemental & function rvs_norm_${t1[0]}$${k1}$ (loc, scale) result(res) ! ! Normal random variate (loc, scale) ! ${t1}$, intent(in) :: loc, scale ${t1}$ :: res if (scale <= 0._${k1}$) then res = ieee_value(1._${k1}$, ieee_quiet_nan) else res = rvs_norm_0_${t1[0]}$${k1}$ () res = res*scale + loc end if end function rvs_norm_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES impure elemental function rvs_norm_${t1[0]}$${k1}$ (loc, scale) result(res) ! ! Normally distributed complex. The real part and imaginary part are & ! independent of each other. ! ${t1}$, intent(in) :: loc, scale ${t1}$ :: res real(${k1}$) :: tr, ti tr = rvs_norm_r${k1}$ (loc%re, scale%re) ti = rvs_norm_r${k1}$ (loc%im, scale%im) res = cmplx(tr, ti, kind=${k1}$) end function rvs_norm_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES impure function rvs_norm_array_${t1[0]}$${k1}$ (loc, scale, array_size) result(res) ${t1}$, intent(in) :: loc, scale integer, intent(in) :: array_size ${t1}$ :: res(array_size) ${t1}$, parameter :: r = 3.442619855899_${k1}$, rr = 1.0_${k1}$/r ${t1}$ :: x, y, re integer :: hz, iz, i if (.not. zig_norm_initialized) call zigset if (scale <= 0._${k1}$) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if do i = 1, array_size iz = 0 hz = dist_rand(1_int32) iz = iand(hz, 127) if (abs(hz) < kn(iz)) then re = hz*wn(iz) else L1: do L2: if (iz == 0) then do x = -log(uni(1.0_${k1}$))*rr y = -log(uni(1.0_${k1}$)) if (y + y >= x*x) exit end do re = r + x if (hz <= 0) re = -re exit L1 end if L2 x = hz*wn(iz) if (fn(iz) + uni(1.0_${k1}$)*(fn(iz - 1) - fn(iz)) < & exp(-HALF*x*x)) then re = x exit L1 end if hz = dist_rand(1_int32) iz = iand(hz, 127) if (abs(hz) < kn(iz)) then re = hz*wn(iz) exit L1 end if end do L1 end if res(i) = re*scale + loc end do end function rvs_norm_array_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES impure function rvs_norm_array_default_${t1[0]}$${k1}$ (array_size, mold) result(res) ! ! Standard normal array random variate with default loc=0, scale=1 ! The mold argument is used only to determine the type and is not referenced ! integer, intent(in) :: array_size ${t1}$, intent(in) #{if t1 == 'real(dp)'}#, optional #{endif}#:: mold ${t1}$ :: res(array_size) res = rvs_norm_array_${t1[0]}$${k1}$ (0.0_${k1}$, 1.0_${k1}$, array_size) end function rvs_norm_array_default_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES impure function rvs_norm_array_${t1[0]}$${k1}$ (loc, scale, array_size) result(res) ${t1}$, intent(in) :: loc, scale integer, intent(in) :: array_size integer :: i ${t1}$ :: res(array_size) real(${k1}$) :: tr, ti do i = 1, array_size tr = rvs_norm_r${k1}$ (loc%re, scale%re) ti = rvs_norm_r${k1}$ (loc%im, scale%im) res(i) = cmplx(tr, ti, kind=${k1}$) end do end function rvs_norm_array_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES impure function rvs_norm_array_default_${t1[0]}$${k1}$ (array_size, mold) result(res) ! ! Standard normal complex array random variate with default loc=0, scale=1 ! The mold argument is used only to determine the type and is not referenced ! integer, intent(in) :: array_size ${t1}$, intent(in) :: mold ${t1}$ :: res(array_size) ! Call the full procedure with default loc=(0,0), scale=(1,1) res = rvs_norm_array_${t1[0]}$${k1}$ (cmplx(0.0_${k1}$, 0.0_${k1}$, kind=${k1}$), & cmplx(1.0_${k1}$, 1.0_${k1}$, kind=${k1}$), & array_size) end function rvs_norm_array_default_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES elemental function pdf_norm_${t1[0]}$${k1}$ (x, loc, scale) result(res) ! ! Normal distribution probability density function ! ${t1}$, intent(in) :: x, loc, scale ${t1}$ :: res ${t1}$, parameter :: sqrt_2_pi = sqrt(2.0_${k1}$*acos(-1.0_${k1}$)) if (scale <= 0._${k1}$) then res = ieee_value(1._${k1}$, ieee_quiet_nan) else res = exp(-0.5_${k1}$*((x - loc)/scale)*(x - loc)/scale)/ & (sqrt_2_Pi*scale) end if end function pdf_norm_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES elemental function pdf_norm_${t1[0]}$${k1}$ (x, loc, scale) result(res) ${t1}$, intent(in) :: x, loc, scale real(${k1}$) :: res res = pdf_norm_r${k1}$ (x%re, loc%re, scale%re) res = res*pdf_norm_r${k1}$ (x%im, loc%im, scale%im) end function pdf_norm_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES elemental function cdf_norm_${t1[0]}$${k1}$ (x, loc, scale) result(res) ! ! Normal distribution cumulative distribution function ! ${t1}$, intent(in) :: x, loc, scale ${t1}$ :: res ${t1}$, parameter :: sqrt_2 = sqrt(2.0_${k1}$) if (scale <= 0._${k1}$) then res = ieee_value(1._${k1}$, ieee_quiet_nan) else res = erfc(-(x - loc)/(scale*sqrt_2))/2.0_${k1}$ end if end function cdf_norm_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES elemental function cdf_norm_${t1[0]}$${k1}$ (x, loc, scale) result(res) ${t1}$, intent(in) :: x, loc, scale real(${k1}$) :: res res = cdf_norm_r${k1}$ (x%re, loc%re, scale%re) res = res*cdf_norm_r${k1}$ (x%im, loc%im, scale%im) end function cdf_norm_${t1[0]}$${k1}$ #:endfor end module stdlib_stats_distribution_normal fortran-lang-stdlib-0ede301/src/stats/stdlib_stats_cov.fypp0000664000175000017500000002257015135654166024367 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_stats) stdlib_stats_cov use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_quiet_nan use stdlib_error, only: error_stop use stdlib_optval, only: optval implicit none contains #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("cov",1, t1, k1) module function ${RName}$(x, dim, mask, corrected) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in), optional :: mask logical, intent(in), optional :: corrected real(${k1}$) :: res if (.not.optval(mask, .true.)) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if res = var(x, dim, corrected = optval(corrected, .true.)) end function ${RName}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:set RName = rname("cov",1, t1, k1, 'dp') module function ${RName}$(x, dim, mask, corrected) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in), optional :: mask logical, intent(in), optional :: corrected real(dp) :: res if (.not.optval(mask, .true.)) then res = ieee_value(1._dp, ieee_quiet_nan) return end if res = var(x, dim, corrected = optval(corrected, .true.)) end function ${RName}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("cov_mask",1, t1, k1) module function ${RName}$(x, dim, mask, corrected) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in) :: mask(:) logical, intent(in), optional :: corrected real(${k1}$) :: res res = var(x, dim, mask, corrected = optval(corrected, .true.)) end function ${RName}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:set RName = rname("cov_mask",1, t1, k1, 'dp') module function ${RName}$(x, dim, mask, corrected) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in) :: mask(:) logical, intent(in), optional :: corrected real(dp) :: res res = var(x, dim, mask, corrected = optval(corrected, .true.)) end function ${RName}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("cov",2, t1, k1) module function ${RName}$(x, dim, mask, corrected) result(res) ${t1}$, intent(in) :: x(:, :) integer, intent(in) :: dim logical, intent(in), optional :: mask logical, intent(in), optional :: corrected ${t1}$ :: res(merge(size(x, 1), size(x, 2), mask = 1 0)) end do end do case(2) do i = 1, size(res, 2) do j = 1, size(res, 1) mask_ = mask(i, :) .and. mask(j, :) centeri_ = merge( x(i, :) - mean(x(i, :), mask = mask_),& #:if t1[0] == 'r' 0._${k1}$,& #:else cmplx(0,0,kind=${k1}$),& #:endif mask_) centerj_ = merge( x(j, :) - mean(x(j, :), mask = mask_),& #:if t1[0] == 'r' 0._${k1}$,& #:else cmplx(0,0,kind=${k1}$),& #:endif mask_) n = count(mask_) res(j, i) = dot_product( centeri_, centerj_)& / (n - merge(1, 0,& optval(corrected, .true.) .and. n > 0)) end do end do case default call error_stop("ERROR (cov): wrong dimension") end select end function ${RName}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:set RName = rname("cov_mask",2, t1, k1, 'dp') module function ${RName}$(x, dim, mask, corrected) result(res) ${t1}$, intent(in) :: x(:, :) integer, intent(in) :: dim logical, intent(in) :: mask(:,:) logical, intent(in), optional :: corrected real(dp) :: res(merge(size(x, 1), size(x, 2), mask = 1 0)) end do end do case(2) do i = 1, size(res, 2) do j = 1, size(res, 1) mask_ = mask(i, :) .and. mask(j, :) centeri_ = merge( x(i, :) - mean(x(i, :), mask = mask_),0._dp, mask_) centerj_ = merge( x(j, :) - mean(x(j, :), mask = mask_),0._dp, mask_) n = count(mask_) res(j, i) = dot_product( centeri_, centerj_)& / (n - merge(1, 0,& optval(corrected, .true.) .and. n > 0)) end do end do case default call error_stop("ERROR (cov): wrong dimension") end select end function ${RName}$ #:endfor end submodule fortran-lang-stdlib-0ede301/src/stats/stdlib_stats.fypp0000664000175000017500000005604415135654166023523 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(1, MAXRANK + 1) #:set REDRANKS = range(2, MAXRANK + 1) #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES #:set IR_KINDS_TYPES_OUTPUT = list(zip(INT_KINDS,INT_TYPES, ['dp']*len(INT_KINDS))) + list(zip(REAL_KINDS, REAL_TYPES, REAL_KINDS)) module stdlib_stats !! Provides support for various statistical methods. This includes currently !! descriptive statistics !! ([Specification](../page/specs/stdlib_stats.html)) use stdlib_kinds, only: sp, dp, xdp, qp, & int8, int16, int32, int64 implicit none private ! Public API public :: corr, cov, mean, median, moment, var interface corr !! version: experimental !! !! Pearson correlation of array elements !! ([Specification](../page/specs/stdlib_stats.html#corr-pearson-correlation-of-array-elements)) #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("corr",1, t1, k1) module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in), optional :: mask real(${k1}$) :: res end function ${RName}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:set RName = rname("corr",1, t1, k1, 'dp') module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in), optional :: mask real(dp) :: res end function ${RName}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("corr_mask",1, t1, k1) module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in) :: mask(:) real(${k1}$) :: res end function ${RName}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES #:set RName = rname("corr_mask",1, t1, k1, 'dp') module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x(:) integer, intent(in) :: dim logical, intent(in) :: mask(:) real(dp) :: res end function ${RName}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES #:set RName = rname("corr",2, t1, k1) module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x(:, :) integer, intent(in) :: dim logical, intent(in), optional :: mask ${t1}$ :: res(merge(size(x, 1), size(x, 2), mask = 1 1 #:for fj in range(1, rank+1) integer :: j${fj}$ #:endfor #:endif ${t1}$ :: val, val1 ${t1}$, allocatable :: x_tmp(:) if (.not.optval(mask, .true.) .or. size(x) == 0) then res = ieee_value(1._${o1}$, ieee_quiet_nan) return end if n = size(x, dim) c = floor( (n + 1) / 2._${o1}$ ) allocate(x_tmp(n)) select case(dim) #:for fi in range(1, rank+1) case(${fi}$) ! Loop over every dimension of the array except "dim" #:for fj in list(range(1, fi)) + list(range(fi+1, rank+1)) do j${fj}$ = 1, size(x, ${fj}$) #:endfor x_tmp(:) = x${select_subvector('j', rank, fi)}$ #:if t1[0] == 'r' if (any(ieee_is_nan(x_tmp))) then res${reduce_subvector('j', rank, fi)}$ = & ieee_value(1._${o1}$, ieee_quiet_nan) #:if fi == 1 return #:else cycle #:endif end if #:endif call select(x_tmp, c, val) if (mod(n, 2) == 0) then val1 = minval(x_tmp(c+1:n)) res${reduce_subvector('j', rank, fi)}$ = & #:if t1[0] == 'r' (val + val1) / 2._${o1}$ #:else (real(val, kind=${o1}$) + real(val1, kind=${o1}$)) / 2._${o1}$ #:endif else res${reduce_subvector('j', rank, fi)}$ = val end if #:for fj in range(1, rank) end do #:endfor #:endfor case default call error_stop("ERROR (median): wrong dimension") end select end function ${name}$ #:endfor #:endfor #:for k1, t1, o1 in IR_KINDS_TYPES_OUTPUT #:for rank in RANKS #:set name = rname('median_all_mask',rank, t1, k1, o1) module function ${name}$(x, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in) :: mask${ranksuffix(rank)}$ real(${o1}$) :: res integer(kind = int64) :: c, n ${t1}$ :: val, val1 ${t1}$, allocatable :: x_tmp(:) if (any(shape(x) .ne. shape(mask))) then call error_stop("ERROR (median): shapes of x and mask are different") end if #:if t1[0] == 'r' if (any(ieee_is_nan(x))) then res = ieee_value(1._${o1}$, ieee_quiet_nan) return end if #:endif x_tmp = pack(x, mask) n = size(x_tmp, kind=int64) if (n == 0) then res = ieee_value(1._${o1}$, ieee_quiet_nan) return end if c = floor( (n + 1) / 2._${o1}$, kind=int64) call select(x_tmp, c, val) if (mod(n, 2_int64) == 0) then val1 = minval(x_tmp(c+1:n)) #:if t1[0] == 'r' res = (val + val1) / 2._${o1}$ #:else res = (real(val, kind=${o1}$) + real(val1, kind=${o1}$)) / 2._${o1}$ #:endif else if (mod(n, 2_int64) == 1) then res = val end if end function ${name}$ #:endfor #:endfor #:for k1, t1, o1 in IR_KINDS_TYPES_OUTPUT #:for rank in RANKS #:set name = rname('median_mask',rank, t1, k1, o1) module function ${name}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: dim logical, intent(in) :: mask${ranksuffix(rank)}$ real(${o1}$) :: res${reduced_shape('x', rank, 'dim')}$ integer(kind = int64) :: c, n #:if rank > 1 #:for fj in range(1, rank+1) integer :: j${fj}$ #:endfor #:endif ${t1}$ :: val, val1 ${t1}$, allocatable :: x_tmp(:) if (any(shape(x) .ne. shape(mask))) then call error_stop("ERROR (median): shapes of x and mask are different") end if select case(dim) #:for fi in range(1, rank+1) case(${fi}$) ! Loop over every dimension of the array except "dim" #:for fj in list(range(1, fi)) + list(range(fi+1, rank+1)) do j${fj}$ = 1, size(x, ${fj}$) #:endfor x_tmp = pack(x${select_subvector('j', rank, fi)}$, & mask${select_subvector('j', rank, fi)}$) #:if t1[0] == 'r' if (any(ieee_is_nan(x_tmp))) then res${reduce_subvector('j', rank, fi)}$ = & ieee_value(1._${o1}$, ieee_quiet_nan) #:if rank == 1 return #:else cycle #:endif end if #:endif n = size(x_tmp, kind=int64) if (n == 0) then res${reduce_subvector('j', rank, fi)}$ = & ieee_value(1._${o1}$, ieee_quiet_nan) return end if c = floor( (n + 1) / 2._${o1}$, kind=int64 ) call select(x_tmp, c, val) if (mod(n, 2_int64) == 0) then val1 = minval(x_tmp(c+1:n)) res${reduce_subvector('j', rank, fi)}$ = & #:if t1[0] == 'r' (val + val1) / 2._${o1}$ #:else (real(val, kind=${o1}$) + real(val1, kind=${o1}$)) / 2._${o1}$ #:endif else if (mod(n, 2_int64) == 1) then res${reduce_subvector('j', rank, fi)}$ = val end if deallocate(x_tmp) #:for fj in range(1, rank) end do #:endfor #:endfor case default call error_stop("ERROR (median): wrong dimension") end select end function ${name}$ #:endfor #:endfor end submodule fortran-lang-stdlib-0ede301/src/stats/CMakeLists.txt0000664000175000017500000000142115135654166022651 0ustar alastairalastairset(stats_cppFiles ) set(stats_fppFiles stdlib_random.fypp stdlib_stats_corr.fypp stdlib_stats_cov.fypp stdlib_stats_distribution_exponential.fypp stdlib_stats_distribution_normal.fypp stdlib_stats_distribution_uniform.fypp stdlib_stats.fypp stdlib_stats_mean.fypp stdlib_stats_median.fypp stdlib_stats_moment_all.fypp stdlib_stats_moment.fypp stdlib_stats_moment_mask.fypp stdlib_stats_moment_scalar.fypp stdlib_stats_var.fypp ) set(stats_f90Files ) configure_stdlib_target(${PROJECT_NAME}_stats stats_f90Files stats_fppFiles stats_cppFiles) target_link_libraries(${PROJECT_NAME}_stats PUBLIC ${PROJECT_NAME}_core ${PROJECT_NAME}_linalg_core ${PROJECT_NAME}_linalg ${PROJECT_NAME}_selection ${PROJECT_NAME}_strings) fortran-lang-stdlib-0ede301/src/stats/stdlib_stats_var.fypp0000664000175000017500000002100615135654166024361 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(1, MAXRANK + 1) #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_stats) stdlib_stats_var use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_quiet_nan use stdlib_error, only: error_stop use stdlib_optval, only: optval implicit none contains #:for k1, t1 in RC_KINDS_TYPES #:for rank in RANKS #:set RName = rname("var_all",rank, t1, k1) module function ${RName}$(x, mask, corrected) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in), optional :: mask logical, intent(in), optional :: corrected real(${k1}$) :: res real(${k1}$) :: n ${t1}$ :: mean if (.not.optval(mask, .true.)) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if n = real(size(x, kind = int64), ${k1}$) mean = sum(x) / n #:if t1[0] == 'r' res = sum((x - mean)**2) / (n - merge(1, 0 , optval(corrected, .true.))) #:else res = sum(abs(x - mean)**2) / (n - merge(1, 0, optval(corrected, .true.))) #:endif end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in RANKS #:set RName = rname("var_all",rank, t1, k1, 'dp') module function ${RName}$(x, mask, corrected) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in), optional :: mask logical, intent(in), optional :: corrected real(dp) :: res real(dp) :: n, mean if (.not.optval(mask, .true.)) then res = ieee_value(1._dp, ieee_quiet_nan) return end if n = real(size(x, kind = int64), dp) mean = sum(real(x, dp)) / n res = sum((real(x, dp) - mean)**2) / (n - merge(1, 0, optval(corrected, .true.))) end function ${RName}$ #:endfor #:endfor #:for k1, t1 in RC_KINDS_TYPES #:for rank in RANKS #:set RName = rname("var",rank, t1, k1) module function ${RName}$(x, dim, mask, corrected) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: dim logical, intent(in), optional :: mask logical, intent(in), optional :: corrected real(${k1}$) :: res${reduced_shape('x', rank, 'dim')}$ integer :: i real(${k1}$) :: n ${t1}$ :: mean${reduced_shape('x', rank, 'dim')}$ if (.not.optval(mask, .true.)) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if res = 0._${k1}$ select case(dim) #:for fi in range(1, rank+1) case(${fi}$) n = size(x, dim) mean = sum(x, dim) / n do i = 1, size(x, dim) #:if t1[0] == 'r' res = res + (x${select_subarray(rank, [(fi, 'i')])}$ - mean)**2 #:else res = res + abs(x${select_subarray(rank, [(fi, 'i')])}$ - mean)**2 #:endif end do #:endfor case default call error_stop("ERROR (var): wrong dimension") end select res = res / (n - merge(1, 0, optval(corrected, .true.))) end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in RANKS #:set RName = rname("var",rank, t1, k1, 'dp') module function ${RName}$(x, dim, mask, corrected) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: dim logical, intent(in), optional :: mask logical, intent(in), optional :: corrected real(dp) :: res${reduced_shape('x', rank, 'dim')}$ integer :: i real(dp) :: n real(dp) :: mean${reduced_shape('x', rank, 'dim')}$ if (.not.optval(mask, .true.)) then res = ieee_value(1._dp, ieee_quiet_nan) return end if res = 0._dp select case(dim) #:for fi in range(1, rank+1) case(${fi}$) n = size(x, dim) mean = sum(real(x, dp), dim) / n do i = 1, size(x, dim) res = res + (real(x${select_subarray(rank, [(fi, 'i')])}$, dp) - mean)**2 end do #:endfor case default call error_stop("ERROR (var): wrong dimension") end select res = res / (n - merge(1, 0, optval(corrected, .true.))) end function ${RName}$ #:endfor #:endfor #:for k1, t1 in RC_KINDS_TYPES #:for rank in RANKS #:set RName = rname("var_mask_all",rank, t1, k1) module function ${RName}$(x, mask, corrected) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in) :: mask${ranksuffix(rank)}$ logical, intent(in), optional :: corrected real(${k1}$) :: res real(${k1}$) :: n ${t1}$ :: mean n = real(count(mask, kind = int64), ${k1}$) mean = sum(x, mask) / n #:if t1[0] == 'r' res = sum((x - mean)**2, mask) / (n -& #:else res = sum(abs(x - mean)**2, mask) / (n -& #:endif merge(1, 0, (optval(corrected, .true.) .and. n > 0))) end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in RANKS #:set RName = rname("var_mask_all",rank, t1, k1, 'dp') module function ${RName}$(x, mask, corrected) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in) :: mask${ranksuffix(rank)}$ logical, intent(in), optional :: corrected real(dp) :: res real(dp) :: n, mean n = real(count(mask, kind = int64), dp) mean = sum(real(x, dp), mask) / n res = sum((real(x, dp) - mean)**2, mask) / (n -& merge(1, 0, (optval(corrected, .true.) .and. n > 0))) end function ${RName}$ #:endfor #:endfor #:for k1, t1 in RC_KINDS_TYPES #:for rank in RANKS #:set RName = rname("var_mask",rank, t1, k1) module function ${RName}$(x, dim, mask, corrected) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: dim logical, intent(in) :: mask${ranksuffix(rank)}$ logical, intent(in), optional :: corrected real(${k1}$) :: res${reduced_shape('x', rank, 'dim')}$ integer :: i real(${k1}$) :: n${reduced_shape('x', rank, 'dim')}$ ${t1}$ :: mean${reduced_shape('x', rank, 'dim')}$ res = 0._${k1}$ select case(dim) #:for fi in range(1, rank+1) case(${fi}$) n = count(mask, dim) mean = sum(x, dim, mask) / n do i = 1, size(x, dim) #:if t1[0] == 'r' res = res + merge( (x${select_subarray(rank, [(fi, 'i')])}$ - mean)**2,& #:else res = res + merge( abs(x${select_subarray(rank, [(fi, 'i')])}$ - mean)**2,& #:endif 0._${k1}$,& mask${select_subarray(rank, [(fi, 'i')])}$) end do #:endfor case default call error_stop("ERROR (var): wrong dimension") end select res = res / (n - merge(1, 0, (optval(corrected, .true.) .and. n > 0))) end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in RANKS #:set RName = rname("var_mask",rank, t1, k1, 'dp') module function ${RName}$(x, dim, mask, corrected) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: dim logical, intent(in) :: mask${ranksuffix(rank)}$ logical, intent(in), optional :: corrected real(dp) :: res${reduced_shape('x', rank, 'dim')}$ integer :: i real(dp) :: n${reduced_shape('x', rank, 'dim')}$ real(dp) :: mean${reduced_shape('x', rank, 'dim')}$ res = 0._dp select case(dim) #:for fi in range(1, rank+1) case(${fi}$) n = count(mask, dim) mean = sum(real(x, dp), dim, mask) / n do i = 1, size(x, dim) res = res + merge((real(x${select_subarray(rank, [(fi, 'i')])}$, dp) - mean)**2,& 0._dp, mask${select_subarray(rank, [(fi, 'i')])}$) end do #:endfor case default call error_stop("ERROR (var): wrong dimension") end select res = res / (n - merge(1, 0, (optval(corrected, .true.) .and. n > 0))) end function ${RName}$ #:endfor #:endfor end submodule fortran-lang-stdlib-0ede301/src/stats/stdlib_stats_distribution_uniform.fypp0000664000175000017500000003677115135654166030066 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES #:set ALL_KINDS_TYPES = INT_KINDS_TYPES + RC_KINDS_TYPES module stdlib_stats_distribution_uniform use stdlib_kinds, only : sp, dp, xdp, qp, int8, int16, int32, int64 use stdlib_error, only : error_stop use stdlib_random, only : dist_rand implicit none private real(dp), parameter :: MESENNE_NUMBER = 1.0_dp / (2.0_dp ** 53 - 1.0_dp) integer(int64), parameter :: INT_ONE = 1_int64 public :: rvs_uniform public :: pdf_uniform public :: cdf_uniform public :: shuffle interface rvs_uniform !! version: experimental !! !! Get uniformly distributed random variate for integer, real and complex !! variables. !! ([Specification](../page/specs/stdlib_stats_distribution_uniform.html# !! rvs_uniform-uniform-distribution-random-variates)) module procedure rvs_unif_0_rsp ! 0 dummy variable #:for k1, t1 in ALL_KINDS_TYPES module procedure rvs_unif_1_${t1[0]}$${k1}$ ! 1 dummy variable #:endfor #:for k1, t1 in ALL_KINDS_TYPES module procedure rvs_unif_${t1[0]}$${k1}$ ! 2 dummy variables #:endfor #:for k1, t1 in ALL_KINDS_TYPES module procedure rvs_unif_array_${t1[0]}$${k1}$ ! 3 dummy variables #:endfor end interface rvs_uniform interface pdf_uniform !! version: experimental !! !! Get uniform distribution probability density (pdf) for integer, real and !! complex variables. !! ([Specification](../page/specs/stdlib_stats_distribution_uniform.html# !! pdf_uniform-uniform-probability-density-function)) #:for k1, t1 in ALL_KINDS_TYPES module procedure pdf_unif_${t1[0]}$${k1}$ #:endfor end interface pdf_uniform interface cdf_uniform !! version: experimental !! !! Get uniform distribution cumulative distribution function (cdf) for integer, !! real and complex variables. !! ([Specification](../page/specs/stdlib_stats_distribution_uniform.html# !! cdf_uniform-uniform-cumulative-distribution-function)) !! #:for k1, t1 in ALL_KINDS_TYPES module procedure cdf_unif_${t1[0]}$${k1}$ #:endfor end interface cdf_uniform interface shuffle !! version: experimental !! !! Fisher-Yates shuffle algorithm for a rank one array of integer, real and !! complex variables. !! ([Specification](../page/specs/stdlib_stats_distribution_uniform.html# !! shuffle-using-fisher-yates-algorithm-to-generate-a-random-permutation-of-a-list)) !! #:for k1, t1 in ALL_KINDS_TYPES module procedure shuffle_${t1[0]}$${k1}$ #:endfor end interface shuffle contains #:for k1, t1 in INT_KINDS_TYPES impure elemental function rvs_unif_1_${t1[0]}$${k1}$(scale) result(res) ! ! Uniformly distributed integer in [0, scale] ! Bitmask with rejection ! https://www.pcg-random.org/posts/bounded-rands.html ! ! Fortran 90 translated from c by Jim-215-fisher ! ${t1}$, intent(in) :: scale ${t1}$ :: res, u, mask integer :: zeros, bits_left, bits if(scale <= 0_${k1}$) call error_stop("Error(rvs_unif_1): Uniform" & //" distribution scale parameter must be positive") zeros = leadz(scale) bits = bit_size(scale) - zeros mask = shiftr(not(0_${k1}$), zeros) L1 : do u = dist_rand(scale) res = iand(u, mask) if(res <= scale) exit L1 bits_left = zeros L2 : do if(bits_left < bits) exit L2 u = shiftr(u, bits) res = iand(u, mask) if(res <= scale) exit L1 bits_left = bits_left - bits end do L2 end do L1 end function rvs_unif_1_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES impure elemental function rvs_unif_${t1[0]}$${k1}$(loc, scale) result(res) ! ! Uniformly distributed integer in [loc, loc + scale] ! ${t1}$, intent(in) :: loc, scale ${t1}$ :: res if(scale <= 0_${k1}$) call error_stop("Error(rvs_unif): Uniform" & //" distribution scale parameter must be positive") res = loc + rvs_unif_1_${t1[0]}$${k1}$(scale) end function rvs_unif_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES impure elemental function rvs_unif_0_${t1[0]}$${k1}$( ) result(res) ! ! Uniformly distributed float in [0,1] ! Based on the paper by Frederic Goualard, "Generating Random Floating- ! Point Numbers By Dividing Integers: a Case Study", Proceedings of ! ICCS 2020, June 2020, Amsterdam, Netherlands ! ${t1}$ :: res integer(int64) :: tmp tmp = shiftr(dist_rand(INT_ONE), 11) ! Get random from [0,2^53-1] res = real(tmp * MESENNE_NUMBER, kind = ${k1}$) ! convert to [0,1] end function rvs_unif_0_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES impure elemental function rvs_unif_1_${t1[0]}$${k1}$(scale) result(res) ! ! Uniformly distributed float in [0, scale] ! ${t1}$, intent(in) :: scale ${t1}$ :: res if(scale == 0._${k1}$) call error_stop("Error(rvs_unif_1): " & //"Uniform distribution scale parameter must be non-zero") res = scale * rvs_unif_0_${t1[0]}$${k1}$( ) end function rvs_unif_1_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES impure elemental function rvs_unif_${t1[0]}$${k1}$(loc, scale) result(res) ! ! Uniformly distributed float in [loc, loc + scale] ! ${t1}$, intent(in) :: loc, scale ${t1}$ :: res if(scale == 0._${k1}$) call error_stop("Error(rvs_unif): " & //"Uniform distribution scale parameter must be non-zero") res = loc + scale * rvs_unif_0_${t1[0]}$${k1}$( ) end function rvs_unif_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES impure elemental function rvs_unif_1_${t1[0]}$${k1}$(scale) result(res) ! ! Uniformly distributed complex in [(0,0i), (scale, i(scale))] ! The real part and imaginary part are independent of each other, so that ! the joint distribution is on an unit square [(0,0i), (scale,i(scale))] ! ${t1}$, intent(in) :: scale ${t1}$ :: res real(${k1}$) :: r1, tr, ti if(scale == (0.0_${k1}$, 0.0_${k1}$)) call error_stop("Error(rvs_uni_" & //"1): Uniform distribution scale parameter must be non-zero") r1 = rvs_unif_0_r${k1}$( ) if(scale % re == 0.0_${k1}$) then ti = scale % im * r1 tr = 0.0_${k1}$ else if(scale % im == 0.0_${k1}$) then tr = scale % re * r1 ti = 0.0_${k1}$ else tr = scale % re * r1 r1 = rvs_unif_0_r${k1}$( ) ti = scale % im * r1 end if res = cmplx(tr, ti, kind=${k1}$) end function rvs_unif_1_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES impure elemental function rvs_unif_${t1[0]}$${k1}$(loc, scale) result(res) ! ! Uniformly distributed complex in [(loc,iloc), (loc + scale, i(loc + ! scale))]. ! The real part and imaginary part are independent of each other, so that ! the joint distribution is on an unit square [(loc,iloc), (loc + scale, ! i(loc + scale))] ! ${t1}$, intent(in) :: loc, scale ${t1}$ :: res real(${k1}$) :: r1, tr, ti if(scale == (0.0_${k1}$, 0.0_${k1}$)) call error_stop("Error(rvs_uni_" & //"): Uniform distribution scale parameter must be non-zero") r1 = rvs_unif_0_r${k1}$( ) if(scale % re == 0.0_${k1}$) then tr = loc % re ti = loc % im + scale % im * r1 else if(scale % im == 0.0_${k1}$) then tr = loc % re + scale % re * r1 ti = loc % im else tr = loc % re + scale % re * r1 r1 = rvs_unif_0_r${k1}$( ) ti = loc % im + scale % im * r1 end if res = cmplx(tr, ti, kind=${k1}$) end function rvs_unif_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES function rvs_unif_array_${t1[0]}$${k1}$(loc, scale, array_size) result(res) integer, intent(in) :: array_size ${t1}$, intent(in) :: loc, scale ${t1}$ :: res(array_size) ${t1}$ :: u, mask, nn integer :: i, zeros, bits_left, bits if(scale == 0_${k1}$) call error_stop("Error(rvs_unif_array): " & //"Uniform distribution scale parameter must be non-zero") zeros = leadz(scale) bits = bit_size(scale) - zeros mask = shiftr(not(0_${k1}$), zeros) do i = 1, array_size L1 : do u = dist_rand(scale) nn = iand(u, mask) if(nn <= scale) exit L1 bits_left = zeros L2 : do if(bits_left < bits) exit L2 u = shiftr(u, bits) nn = iand(u, mask) if(nn <= scale) exit L1 bits_left = bits_left - bits end do L2 end do L1 res(i) = loc + nn end do end function rvs_unif_array_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES function rvs_unif_array_${t1[0]}$${k1}$(loc, scale, array_size) result(res) integer, intent(in) :: array_size ${t1}$, intent(in) :: loc, scale ${t1}$ :: res(array_size) ${t1}$ :: t integer(int64) :: tmp integer :: i if(scale == 0._${k1}$) call error_stop("Error(rvs_unif_array):" & //" Uniform distribution scale parameter must be non-zero") do i = 1, array_size tmp = shiftr(dist_rand(INT_ONE), 11) t = real(tmp * MESENNE_NUMBER, kind = ${k1}$) res(i) = loc + scale * t end do end function rvs_unif_array_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES function rvs_unif_array_${t1[0]}$${k1}$(loc, scale, array_size) result(res) integer, intent(in) :: array_size ${t1}$, intent(in) :: loc, scale ${t1}$ :: res(array_size) real(${k1}$) :: r1, tr, ti integer(int64) :: tmp integer :: i if(scale == (0.0_${k1}$, 0.0_${k1}$)) call error_stop("Error(rvs_unif" & //"_array): Uniform distribution scale parameter must be non-zero") do i = 1, array_size tmp = shiftr(dist_rand(INT_ONE), 11) r1 = real(tmp * MESENNE_NUMBER, kind = ${k1}$) if(scale % re == 0.0_${k1}$) then tr = loc % re ti = loc % im + scale % im * r1 else if(scale % im == 0.0_${k1}$) then tr = loc % re + scale % re * r1 ti = loc % im else tr = loc % re + scale % re * r1 tmp = shiftr(dist_rand(INT_ONE), 11) r1 = real(tmp * MESENNE_NUMBER, kind = ${k1}$) ti = loc % im + scale % im * r1 end if res(i) = cmplx(tr, ti, kind=${k1}$) end do end function rvs_unif_array_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES elemental function pdf_unif_${t1[0]}$${k1}$(x, loc, scale) result(res) ${t1}$, intent(in) :: x, loc, scale real :: res if(scale == 0_${k1}$) then res = 0.0 else if(x < loc .or. x > (loc + scale)) then res = 0.0 else res = 1. / (scale + 1_${k1}$) end if end function pdf_unif_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES elemental function pdf_unif_${t1[0]}$${k1}$(x, loc, scale) result(res) ${t1}$, intent(in) :: x, loc, scale ${t1}$ :: res ${t1}$, parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ if(scale == zero) then res = zero else if(x < loc .or. x > (loc + scale)) then res = zero else res = one / scale end if end function pdf_unif_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES elemental function pdf_unif_${t1[0]}$${k1}$(x, loc, scale) result(res) ${t1}$, intent(in) :: x, loc, scale real(${k1}$) :: res, tr, ti real(${k1}$), parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ tr = loc % re + scale % re; ti = loc % im + scale % im if(scale == (zero, zero)) then res = zero else if((x % re >= loc % re .and. x % re <= tr) .and. & (x % im >= loc % im .and. x % im <= ti)) then res = one / (scale % re * scale % im) else res = zero end if end function pdf_unif_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES elemental function cdf_unif_${t1[0]}$${k1}$(x, loc, scale) result(res) ${t1}$, intent(in) :: x, loc, scale real :: res if(scale == 0_${k1}$) then res = 0.0 else if(x < loc) then res = 0.0 else if(x >= loc .and. x <= (loc + scale)) then res = real((x - loc + 1_${k1}$)) / real((scale + 1_${k1}$)) else res = 1.0 end if end function cdf_unif_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES elemental function cdf_unif_${t1[0]}$${k1}$(x, loc, scale) result(res) ${t1}$, intent(in) :: x, loc, scale ${t1}$ :: res ${t1}$, parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ if(scale == zero) then res = zero else if(x < loc) then res = zero else if(x >= loc .and. x <= (loc + scale)) then res = (x - loc) / scale else res = one end if end function cdf_unif_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES elemental function cdf_unif_${t1[0]}$${k1}$(x, loc, scale) result(res) ${t1}$, intent(in) :: x, loc, scale real(${k1}$) :: res real(${k1}$), parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ logical :: r1, r2, i1, i2 if(scale == (zero, zero)) then res = zero return end if r1 = x % re < loc % re r2 = x % re > (loc % re + scale % re) i1 = x % im < loc % im i2 = x % im > (loc % im + scale % im) if(r1 .or. i1) then res = zero else if((.not. r1) .and. (.not. r2) .and. i2) then res = (x % re - loc % re) / scale % re else if((.not. i1) .and. (.not. i2) .and. r2) then res = (x % im - loc % im) / scale % im else if((.not. r1) .and. (.not. r2) .and. (.not. i1) .and. (.not. i2)) & then res = ((x % re - loc % re) / scale % re) * ((x % im - loc % im) / & scale % im) else if(r2 .and. i2)then res = one end if end function cdf_unif_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in ALL_KINDS_TYPES function shuffle_${t1[0]}$${k1}$( list ) result(res) ${t1}$, intent(in) :: list(:) ${t1}$ :: res(size(list)) ${t1}$ :: tmp integer :: n, i, j n = size(list) res = list do i = 1, n - 1 j = rvs_uniform(n - i) + i tmp = res(i) res(i) = res(j) res(j) = tmp end do end function shuffle_${t1[0]}$${k1}$ #:endfor end module stdlib_stats_distribution_uniform fortran-lang-stdlib-0ede301/src/stats/stdlib_stats_moment.fypp0000664000175000017500000000662615135654166025103 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(1, MAXRANK + 1) #:set REDRANKS = range(2, MAXRANK + 1) #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_stats) stdlib_stats_moment use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_quiet_nan use stdlib_error, only: error_stop use stdlib_optval, only: optval implicit none contains #:for k1, t1 in RC_KINDS_TYPES #:for rank in RANKS #:set RName = rname("moment",rank, t1, k1) module function ${RName}$(x, order, dim, center, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: order integer, intent(in) :: dim ${t1}$, intent(in), optional :: center${reduced_shape('x', rank, 'dim')}$ logical, intent(in), optional :: mask ${t1}$ :: res${reduced_shape('x', rank, 'dim')}$ integer :: i real(${k1}$) :: n ${t1}$, allocatable :: mean_${ranksuffix(rank-1)}$ if (.not.optval(mask, .true.)) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if n = real(size(x, dim), ${k1}$) res = 0 select case(dim) #:for fi in range(1, rank+1) case(${fi}$) if (present(center)) then do i = 1, size(x, ${fi}$) res = res + (x${select_subarray(rank, [(fi, 'i')])}$ - center)**order end do else allocate(mean_, source = mean(x, ${fi}$)) do i = 1, size(x, ${fi}$) res = res + (x${select_subarray(rank, [(fi, 'i')])}$ - mean_)**order end do deallocate(mean_) end if #:endfor case default call error_stop("ERROR (moment): wrong dimension") end select res = res / n end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in RANKS #:set RName = rname("moment",rank, t1, k1, 'dp') module function ${RName}$(x, order, dim, center, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: order integer, intent(in) :: dim real(dp),intent(in), optional :: center${reduced_shape('x', rank, 'dim')}$ logical, intent(in), optional :: mask real(dp) :: res${reduced_shape('x', rank, 'dim')}$ integer :: i real(dp) :: n real(dp), allocatable :: mean_${ranksuffix(rank-1)}$ if (.not.optval(mask, .true.)) then res = ieee_value(1._dp, ieee_quiet_nan) return end if n = real(size(x, dim), dp) res = 0 select case(dim) #:for fi in range(1, rank+1) case(${fi}$) if (present(center)) then do i = 1, size(x, ${fi}$) res = res + (real(x${select_subarray(rank, [(fi, 'i')])}$, dp) -& center)**order end do else allocate(mean_, source = mean(x, ${fi}$)) do i = 1, size(x, ${fi}$) res = res + (real(x${select_subarray(rank, [(fi, 'i')])}$, dp) - mean_)**order end do deallocate(mean_) end if #:endfor case default call error_stop("ERROR (moment): wrong dimension") end select res = res / n end function ${RName}$ #:endfor #:endfor end submodule fortran-lang-stdlib-0ede301/src/stats/stdlib_stats_moment_scalar.fypp0000664000175000017500000000677215135654166026432 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(1, MAXRANK + 1) #:set REDRANKS = range(2, MAXRANK + 1) #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_stats) stdlib_stats_moment_scalar use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_quiet_nan use stdlib_error, only: error_stop use stdlib_optval, only: optval implicit none contains #:for k1, t1 in RC_KINDS_TYPES #:for rank in REDRANKS #:set RName = rname("moment_scalar",rank, t1, k1) module function ${RName}$(x, order, dim, center, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: order integer, intent(in) :: dim ${t1}$, intent(in) :: center logical, intent(in), optional :: mask ${t1}$ :: res${reduced_shape('x', rank, 'dim')}$ if (.not.optval(mask, .true.)) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if if (dim >= 1 .and. dim <= ${rank}$) then res = sum((x - center)**order, dim) / size(x, dim) else call error_stop("ERROR (moment): wrong dimension") end if end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in REDRANKS #:set RName = rname("moment_scalar",rank, t1, k1, 'dp') module function ${RName}$(x, order, dim, center, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: order integer, intent(in) :: dim real(dp),intent(in) :: center logical, intent(in), optional :: mask real(dp) :: res${reduced_shape('x', rank, 'dim')}$ if (.not.optval(mask, .true.)) then res = ieee_value(1._dp, ieee_quiet_nan) return end if if (dim >= 1 .and. dim <= ${rank}$) then res = sum( (real(x, dp) - center)**order, dim) / size(x, dim) else call error_stop("ERROR (moment): wrong dimension") end if end function ${RName}$ #:endfor #:endfor #:for k1, t1 in RC_KINDS_TYPES #:for rank in REDRANKS #:set RName = rname("moment_mask_scalar",rank, t1, k1) module function ${RName}$(x, order, dim, center, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: order integer, intent(in) :: dim ${t1}$, intent(in) :: center logical, intent(in) :: mask${ranksuffix(rank)}$ ${t1}$ :: res${reduced_shape('x', rank, 'dim')}$ if (dim >= 1 .and. dim <= ${rank}$) then res = sum((x - center)**order, dim, mask) / count(mask, dim) else call error_stop("ERROR (moment): wrong dimension") end if end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in REDRANKS #:set RName = rname("moment_mask_scalar",rank, t1, k1, 'dp') module function ${RName}$(x, order, dim, center, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: order integer, intent(in) :: dim real(dp), intent(in) :: center logical, intent(in) :: mask${ranksuffix(rank)}$ real(dp) :: res${reduced_shape('x', rank, 'dim')}$ if (dim >= 1 .and. dim <= ${rank}$) then res = sum(( real(x, dp) - center)**order, dim, mask) / count(mask, dim) else call error_stop("ERROR (moment): wrong dimension") end if end function ${RName}$ #:endfor #:endfor end submodule fortran-lang-stdlib-0ede301/src/stats/stdlib_stats_mean.fypp0000664000175000017500000001162615135654166024520 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(1, MAXRANK + 1) #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES submodule (stdlib_stats) stdlib_stats_mean use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_quiet_nan use stdlib_error, only: error_stop use stdlib_optval, only: optval implicit none contains #:for k1, t1 in RC_KINDS_TYPES #:for rank in RANKS #:set RName = rname("mean_all",rank, t1, k1) module function ${RName}$ (x, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in), optional :: mask ${t1}$ :: res if (.not.optval(mask, .true.)) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if res = sum(x) / real(size(x, kind = int64), ${k1}$) end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in RANKS #:set RName = rname('mean_all', rank, t1, k1,'dp') module function ${RName}$(x, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in), optional :: mask real(dp) :: res if (.not.optval(mask, .true.)) then res = ieee_value(1._dp, ieee_quiet_nan) return end if res = sum(real(x, dp)) / real(size(x, kind = int64), dp) end function ${RName}$ #:endfor #:endfor #:for k1, t1 in RC_KINDS_TYPES #:for rank in RANKS #:set RName = rname("mean",rank, t1, k1) module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: dim logical, intent(in), optional :: mask ${t1}$ :: res${reduced_shape('x', rank, 'dim')}$ if (.not.optval(mask, .true.)) then res = ieee_value(1._${k1}$, ieee_quiet_nan) return end if if (dim >= 1 .and. dim <= ${rank}$) then res = sum(x, dim) / real(size(x, dim), ${k1}$) else call error_stop("ERROR (mean): wrong dimension") end if end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in RANKS #:set RName = rname("mean",rank, t1, k1,'dp') module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: dim logical, intent(in), optional :: mask real(dp) :: res${reduced_shape('x', rank, 'dim')}$ if (.not.optval(mask, .true.)) then res = ieee_value(1._dp, ieee_quiet_nan) return end if if (dim >= 1 .and. dim <= ${rank}$) then res = sum(real(x, dp), dim) / real(size(x, dim), dp) else call error_stop("ERROR (mean): wrong dimension") end if end function ${RName}$ #:endfor #:endfor #:for k1, t1 in RC_KINDS_TYPES #:for rank in RANKS #:set RName = rname('mean_mask_all',rank, t1, k1) module function ${RName}$(x, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in) :: mask${ranksuffix(rank)}$ ${t1}$ :: res res = sum(x, mask) / real(count(mask, kind = int64), ${k1}$) end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in RANKS #:set RName = rname('mean_mask_all',rank, t1, k1, 'dp') module function ${RName}$(x, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in) :: mask${ranksuffix(rank)}$ real(dp) :: res res = sum(real(x, dp), mask) / real(count(mask, kind = int64), dp) end function ${RName}$ #:endfor #:endfor #:for k1, t1 in RC_KINDS_TYPES #:for rank in RANKS #:set RName = rname('mean_mask',rank, t1, k1) module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: dim logical, intent(in) :: mask${ranksuffix(rank)}$ ${t1}$ :: res${reduced_shape('x', rank, 'dim')}$ if (dim >= 1 .and. dim <= ${rank}$) then res = sum(x, dim, mask) / real(count(mask, dim), ${k1}$) else call error_stop("ERROR (mean): wrong dimension") end if end function ${RName}$ #:endfor #:endfor #:for k1, t1 in INT_KINDS_TYPES #:for rank in RANKS #:set RName = rname('mean_mask',rank, t1, k1, 'dp') module function ${RName}$(x, dim, mask) result(res) ${t1}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in) :: dim logical, intent(in) :: mask${ranksuffix(rank)}$ real(dp) :: res${reduced_shape('x', rank, 'dim')}$ if (dim >= 1 .and. dim <= ${rank}$) then res = sum(real(x, dp), dim, mask) / real(count(mask, dim), dp) else call error_stop("ERROR (mean): wrong dimension") end if end function ${RName}$ #:endfor #:endfor end submodule fortran-lang-stdlib-0ede301/src/ansi/0000775000175000017500000000000015135654166017707 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/ansi/stdlib_ansi_operator.f900000664000175000017500000000513215135654166024436 0ustar alastairalastair! SPDX-Identifier: MIT !> Implementation of the conversion to enumerator and identifier types to strings submodule (stdlib_ansi) stdlib_ansi_operator use stdlib_string_type, only : operator(//) implicit none contains !> Add two escape sequences, attributes in the right value override the left value ones. pure module function add(lval, rval) result(code) !> First escape code type(ansi_code), intent(in) :: lval !> Second escape code type(ansi_code), intent(in) :: rval !> Combined escape code type(ansi_code) :: code code%style = merge(rval%style, lval%style, rval%style >= 0) code%fg = merge(rval%fg, lval%fg, rval%fg >= 0) code%bg = merge(rval%bg, lval%bg, rval%bg >= 0) end function add !> Concatenate an escape code with a string and turn it into an actual escape sequence pure module function concat_left(lval, code) result(str) !> String to add the escape code to character(len=*), intent(in) :: lval !> Escape sequence type(ansi_code), intent(in) :: code !> Concatenated string character(len=:), allocatable :: str str = lval // to_string(code) end function concat_left !> Concatenate an escape code with a string and turn it into an actual escape sequence pure module function concat_right(code, rval) result(str) !> String to add the escape code to character(len=*), intent(in) :: rval !> Escape sequence type(ansi_code), intent(in) :: code !> Concatenated string character(len=:), allocatable :: str str = to_string(code) // rval end function concat_right !> Concatenate an escape code with a string and turn it into an actual escape sequence pure module function concat_left_str(lval, code) result(str) !> String to add the escape code to type(string_type), intent(in) :: lval !> Escape sequence type(ansi_code), intent(in) :: code !> Concatenated string type(string_type) :: str str = lval // to_string(code) end function concat_left_str !> Concatenate an escape code with a string and turn it into an actual escape sequence pure module function concat_right_str(code, rval) result(str) !> String to add the escape code to type(string_type), intent(in) :: rval !> Escape sequence type(ansi_code), intent(in) :: code !> Concatenated string type(string_type) :: str str = to_string(code) // rval end function concat_right_str end submodule stdlib_ansi_operator fortran-lang-stdlib-0ede301/src/ansi/stdlib_ansi.f900000664000175000017500000001551715135654166022533 0ustar alastairalastair! SPDX-Identifier: MIT !> Terminal color and style escape sequences module stdlib_ansi use stdlib_kinds, only : i1 => int8 use stdlib_string_type, only : string_type implicit none private public :: ansi_code public :: style_reset, style_bold, style_dim, style_italic, style_underline, & & style_blink, style_blink_fast, style_reverse, style_hidden, style_strikethrough public :: fg_color_black, fg_color_red, fg_color_green, fg_color_yellow, fg_color_blue, & & fg_color_magenta, fg_color_cyan, fg_color_white, fg_color_default public :: bg_color_black, bg_color_red, bg_color_green, bg_color_yellow, bg_color_blue, & & bg_color_magenta, bg_color_cyan, bg_color_white, bg_color_default public :: to_string, operator(+), operator(//) !> Container for terminal escape code type :: ansi_code private !> Style descriptor integer(i1) :: style = -1_i1 !> Background color descriptor integer(i1) :: bg = -1_i1 !> Foreground color descriptor integer(i1) :: fg = -1_i1 end type ansi_code !> Identifier for reset style type(ansi_code), parameter :: style_reset = ansi_code(style=0) !> Identifier for bold style type(ansi_code), parameter :: style_bold = ansi_code(style=1) !> Identifier for dim style type(ansi_code), parameter :: style_dim = ansi_code(style=2) !> Identifier for italic style type(ansi_code), parameter :: style_italic = ansi_code(style=3) !> Identifier for underline style type(ansi_code), parameter :: style_underline = ansi_code(style=4) !> Identifier for blink style type(ansi_code), parameter :: style_blink = ansi_code(style=5) !> Identifier for (fast) blink style type(ansi_code), parameter :: style_blink_fast = ansi_code(style=6) !> Identifier for reverse style type(ansi_code), parameter :: style_reverse = ansi_code(style=7) !> Identifier for hidden style type(ansi_code), parameter :: style_hidden = ansi_code(style=8) !> Identifier for strikethrough style type(ansi_code), parameter :: style_strikethrough = ansi_code(style=9) !> Identifier for black foreground color type(ansi_code), parameter :: fg_color_black = ansi_code(fg=0) !> Identifier for red foreground color type(ansi_code), parameter :: fg_color_red = ansi_code(fg=1) !> Identifier for green foreground color type(ansi_code), parameter :: fg_color_green = ansi_code(fg=2) !> Identifier for yellow foreground color type(ansi_code), parameter :: fg_color_yellow = ansi_code(fg=3) !> Identifier for blue foreground color type(ansi_code), parameter :: fg_color_blue = ansi_code(fg=4) !> Identifier for magenta foreground color type(ansi_code), parameter :: fg_color_magenta = ansi_code(fg=5) !> Identifier for cyan foreground color type(ansi_code), parameter :: fg_color_cyan = ansi_code(fg=6) !> Identifier for white foreground color type(ansi_code), parameter :: fg_color_white = ansi_code(fg=7) !> Identifier for the default foreground color type(ansi_code), parameter :: fg_color_default = ansi_code(fg=9) !> Identifier for black background color type(ansi_code), parameter :: bg_color_black = ansi_code(bg=0) !> Identifier for red background color type(ansi_code), parameter :: bg_color_red = ansi_code(bg=1) !> Identifier for green background color type(ansi_code), parameter :: bg_color_green = ansi_code(bg=2) !> Identifier for yellow background color type(ansi_code), parameter :: bg_color_yellow = ansi_code(bg=3) !> Identifier for blue background color type(ansi_code), parameter :: bg_color_blue = ansi_code(bg=4) !> Identifier for magenta background color type(ansi_code), parameter :: bg_color_magenta = ansi_code(bg=5) !> Identifier for cyan background color type(ansi_code), parameter :: bg_color_cyan = ansi_code(bg=6) !> Identifier for white background color type(ansi_code), parameter :: bg_color_white = ansi_code(bg=7) !> Identifier for the default background color type(ansi_code), parameter :: bg_color_default = ansi_code(bg=9) interface to_string !> Transform a color code into an actual ANSI escape sequence pure module function to_string_ansi_code(code) result(str) !> Color code to be used type(ansi_code), intent(in) :: code !> ANSI escape sequence representing the color code character(len=:), allocatable :: str end function to_string_ansi_code end interface to_string interface operator(+) !> Add two escape sequences, attributes in the right value override the left value ones. pure module function add(lval, rval) result(code) !> First escape code type(ansi_code), intent(in) :: lval !> Second escape code type(ansi_code), intent(in) :: rval !> Combined escape code type(ansi_code) :: code end function add end interface operator(+) interface operator(//) !> Concatenate an escape code with a string and turn it into an actual escape sequence pure module function concat_left(lval, code) result(str) !> String to add the escape code to character(len=*), intent(in) :: lval !> Escape sequence type(ansi_code), intent(in) :: code !> Concatenated string character(len=:), allocatable :: str end function concat_left !> Concatenate an escape code with a string and turn it into an actual escape sequence pure module function concat_right(code, rval) result(str) !> String to add the escape code to character(len=*), intent(in) :: rval !> Escape sequence type(ansi_code), intent(in) :: code !> Concatenated string character(len=:), allocatable :: str end function concat_right !> Concatenate an escape code with a string and turn it into an actual escape sequence pure module function concat_left_str(lval, code) result(str) !> String to add the escape code to type(string_type), intent(in) :: lval !> Escape sequence type(ansi_code), intent(in) :: code !> Concatenated string type(string_type) :: str end function concat_left_str !> Concatenate an escape code with a string and turn it into an actual escape sequence pure module function concat_right_str(code, rval) result(str) !> String to add the escape code to type(string_type), intent(in) :: rval !> Escape sequence type(ansi_code), intent(in) :: code !> Concatenated string type(string_type) :: str end function concat_right_str end interface operator(//) end module stdlib_ansi fortran-lang-stdlib-0ede301/src/ansi/CMakeLists.txt0000664000175000017500000000045715135654166022455 0ustar alastairalastairset(ansi_f90Files stdlib_ansi.f90 stdlib_ansi_operator.f90 stdlib_ansi_to_string.f90 ) set(ansi_fppFiles ) configure_stdlib_target(${PROJECT_NAME}_ansi ansi_f90Files ansi_fppFiles "") target_link_libraries(${PROJECT_NAME}_ansi PUBLIC ${PROJECT_NAME}_core ${PROJECT_NAME}_strings) fortran-lang-stdlib-0ede301/src/ansi/stdlib_ansi_to_string.f900000664000175000017500000000266615135654166024624 0ustar alastairalastair! SPDX-Identifier: MIT !> Implementation of the conversion to enumerator and identifier types to strings submodule (stdlib_ansi) stdlib_ansi_to_string implicit none character, parameter :: esc = achar(27), chars(0:9) = & ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] contains !> Transform a color code into an actual ANSI escape sequence pure module function to_string_ansi_code(code) result(str) !> Color code to be used type(ansi_code), intent(in) :: code !> ANSI escape sequence representing the color code character(len=:), allocatable :: str if (anycolor(code)) then str = esc // "[0" ! Always reset the style if (code%style > 0 .and. code%style < 10) str = str // ";" // chars(code%style) if (code%fg >= 0 .and. code%fg < 10) str = str // ";3" // chars(code%fg) if (code%bg >= 0 .and. code%bg < 10) str = str // ";4" // chars(code%bg) str = str // "m" else str = "" end if end function to_string_ansi_code !> Check whether the code describes any color / style or is just a stub pure function anycolor(code) !> Escape sequence type(ansi_code), intent(in) :: code !> Any color / style is active logical :: anycolor anycolor = code%fg >= 0 .or. code%bg >= 0 .or. code%style >= 0 end function anycolor end submodule stdlib_ansi_to_string fortran-lang-stdlib-0ede301/src/quadrature/0000775000175000017500000000000015135654166021132 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/quadrature/stdlib_quadrature_gauss.f900000664000175000017500000000772315135654166026403 0ustar alastairalastairsubmodule (stdlib_quadrature) stdlib_quadrature_gauss use stdlib_specialfunctions, only: legendre, dlegendre implicit none real(dp), parameter :: pi = acos(-1._dp) real(dp), parameter :: tolerance = 4._dp * epsilon(1._dp) integer, parameter :: newton_iters = 100 contains pure module subroutine gauss_legendre_fp64 (x, w, interval) real(dp), intent(out) :: x(:), w(:) real(dp), intent(in), optional :: interval(2) associate (n => size(x)-1 ) select case (n) case (0) x = 0 w = 2 case (1) x(1) = -sqrt(1._dp/3._dp) x(2) = -x(1) w = 1 case default block integer :: i,j real(dp) :: leg, dleg, delta do i = 0, (n+1)/2 - 1 ! use Gauss-Chebyshev points as an initial guess x(i+1) = -cos((2*i+1)/(2._dp*n+2._dp) * pi) do j = 1, newton_iters leg = legendre(n+1,x(i+1)) dleg = dlegendre(n+1,x(i+1)) delta = -leg/dleg x(i+1) = x(i+1) + delta if ( abs(delta) <= tolerance * abs(x(i+1)) ) exit end do x(n-i+1) = -x(i+1) dleg = dlegendre(n+1,x(i+1)) w(i+1) = 2._dp/((1-x(i+1)**2)*dleg**2) w(n-i+1) = w(i+1) end do if (mod(n,2) == 0) then x(n/2+1) = 0 dleg = dlegendre(n+1, 0.0_dp) w(n/2+1) = 2._dp/(dleg**2) end if end block end select end associate if (present(interval)) then associate ( a => interval(1) , b => interval(2) ) x = 0.5_dp*(b-a)*x+0.5_dp*(b+a) w = 0.5_dp*(b-a)*w end associate end if end subroutine pure module subroutine gauss_legendre_lobatto_fp64 (x, w, interval) real(dp), intent(out) :: x(:), w(:) real(dp), intent(in), optional :: interval(2) associate (n => size(x)-1) select case (n) case (1) x(1) = -1 x(2) = 1 w = 1 case default block integer :: i,j real(dp) :: leg, dleg, delta x(1) = -1._dp x(n+1) = 1._dp w(1) = 2._dp/(n*(n+1._dp)) w(n+1) = 2._dp/(n*(n+1._dp)) do i = 1, (n+1)/2 - 1 ! initial guess from an approximate form given by SV Parter (1999) x(i+1) = -cos( (i+0.25_dp)*pi/n - 3/(8*n*pi*(i+0.25_dp))) do j = 1, newton_iters leg = legendre(n+1,x(i+1)) - legendre(n-1,x(i+1)) dleg = dlegendre(n+1,x(i+1)) - dlegendre(n-1,x(i+1)) delta = -leg/dleg x(i+1) = x(i+1) + delta if ( abs(delta) <= tolerance * abs(x(i+1)) ) exit end do x(n-i+1) = -x(i+1) leg = legendre(n, x(i+1)) w(i+1) = 2._dp/(n*(n+1._dp)*leg**2) w(n-i+1) = w(i+1) end do if (mod(n,2) == 0) then x(n/2+1) = 0 leg = legendre(n, 0.0_dp) w(n/2+1) = 2._dp/(n*(n+1._dp)*leg**2) end if end block end select end associate if (present(interval)) then associate ( a => interval(1) , b => interval(2) ) x = 0.5_dp*(b-a)*x+0.5_dp*(b+a) x(1) = interval(1) x(size(x)) = interval(2) w = 0.5_dp*(b-a)*w end associate end if end subroutine end submodule fortran-lang-stdlib-0ede301/src/quadrature/CMakeLists.txt0000664000175000017500000000067215135654166023677 0ustar alastairalastairset(quadrature_fppFiles stdlib_quadrature.fypp stdlib_quadrature_trapz.fypp stdlib_quadrature_simps.fypp ) set(quadrature_cppFiles ) set(quadrature_f90Files stdlib_quadrature_gauss.f90 ) configure_stdlib_target(${PROJECT_NAME}_quadrature quadrature_f90Files quadrature_fppFiles quadrature_cppFiles) target_link_libraries(${PROJECT_NAME}_quadrature PUBLIC ${PROJECT_NAME}_core ${PROJECT_NAME}_specialfunctions) fortran-lang-stdlib-0ede301/src/quadrature/stdlib_quadrature_trapz.fypp0000664000175000017500000000443415135654166026775 0ustar alastairalastair#:include "common.fypp" submodule (stdlib_quadrature) stdlib_quadrature_trapz use stdlib_error, only: check implicit none contains #:for KIND in REAL_KINDS pure module function trapz_dx_${KIND}$(y, dx) result(integral) real(${KIND}$), dimension(:), intent(in) :: y real(${KIND}$), intent(in) :: dx real(${KIND}$) :: integral integer :: n n = size(y) select case (n) case (0:1) integral = 0.0_${KIND}$ case (2) integral = 0.5_${KIND}$*dx*(y(1) + y(2)) case default integral = dx*(sum(y(2:n-1)) + 0.5_${KIND}$*(y(1) + y(n))) end select end function trapz_dx_${KIND}$ #:endfor #:for KIND in REAL_KINDS module function trapz_x_${KIND}$(y, x) result(integral) real(${KIND}$), dimension(:), intent(in) :: y real(${KIND}$), dimension(:), intent(in) :: x real(${KIND}$) :: integral integer :: i integer :: n n = size(y) call check(size(x) == n, "trapz: Arguments `x` and `y` must be the same size.") select case (n) case (0:1) integral = 0.0_${KIND}$ case (2) integral = 0.5_${KIND}$*(x(2) - x(1))*(y(1) + y(2)) case default integral = 0.0_${KIND}$ do i = 2, n integral = integral + (x(i) - x(i-1))*(y(i) + y(i-1)) end do integral = 0.5_${KIND}$*integral end select end function trapz_x_${KIND}$ #:endfor #:for KIND in REAL_KINDS pure module function trapz_weights_${KIND}$(x) result(w) real(${KIND}$), dimension(:), intent(in) :: x real(${KIND}$), dimension(size(x)) :: w integer :: i integer :: n n = size(x) select case (n) case (0) ! no action needed case (1) w(1) = 0.0_${KIND}$ case (2) w = 0.5_${KIND}$*(x(2) - x(1)) case default w(1) = 0.5_${KIND}$*(x(2) - x(1)) w(n) = 0.5_${KIND}$*(x(n) - x(n-1)) do i = 2, size(x)-1 w(i) = 0.5_${KIND}$*(x(i+1) - x(i-1)) end do end select end function trapz_weights_${KIND}$ #:endfor end submodule stdlib_quadrature_trapz fortran-lang-stdlib-0ede301/src/quadrature/stdlib_quadrature.fypp0000664000175000017500000001070515135654166025553 0ustar alastairalastair#:include "common.fypp" module stdlib_quadrature !! ([Specification](../page/specs/stdlib_quadrature.html#description)) use stdlib_kinds, only: sp, dp, xdp, qp implicit none private ! array integration public :: trapz public :: trapz_weights public :: simps public :: simps_weights public :: gauss_legendre public :: gauss_legendre_lobatto interface trapz !! version: experimental !! !! Integrates sampled values using trapezoidal rule !! ([Specification](../page/specs/stdlib_quadrature.html#description)) #:for k1, t1 in REAL_KINDS_TYPES pure module function trapz_dx_${k1}$(y, dx) result(integral) ${t1}$, dimension(:), intent(in) :: y ${t1}$, intent(in) :: dx ${t1}$ :: integral end function trapz_dx_${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES module function trapz_x_${k1}$(y, x) result(integral) ${t1}$, dimension(:), intent(in) :: y ${t1}$, dimension(:), intent(in) :: x ${t1}$ :: integral end function trapz_x_${k1}$ #:endfor end interface trapz interface trapz_weights !! version: experimental !! !! Integrates sampled values using trapezoidal rule weights for given abscissas !! ([Specification](../page/specs/stdlib_quadrature.html#description_1)) #:for k1, t1 in REAL_KINDS_TYPES pure module function trapz_weights_${k1}$(x) result(w) ${t1}$, dimension(:), intent(in) :: x ${t1}$, dimension(size(x)) :: w end function trapz_weights_${k1}$ #:endfor end interface trapz_weights interface simps !! version: experimental !! !! Integrates sampled values using Simpson's rule !! ([Specification](../page/specs/stdlib_quadrature.html#description_3)) ! "recursive" is an implementation detail #:for k1, t1 in REAL_KINDS_TYPES pure recursive module function simps_dx_${k1}$(y, dx, even) result(integral) ${t1}$, dimension(:), intent(in) :: y ${t1}$, intent(in) :: dx integer, intent(in), optional :: even ${t1}$ :: integral end function simps_dx_${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES recursive module function simps_x_${k1}$(y, x, even) result(integral) ${t1}$, dimension(:), intent(in) :: y ${t1}$, dimension(:), intent(in) :: x integer, intent(in), optional :: even ${t1}$ :: integral end function simps_x_${k1}$ #:endfor end interface simps interface simps_weights !! version: experimental !! !! Integrates sampled values using trapezoidal rule weights for given abscissas !! ([Specification](../page/specs/stdlib_quadrature.html#description_3)) #:for k1, t1 in REAL_KINDS_TYPES pure recursive module function simps_weights_${k1}$(x, even) result(w) ${t1}$, dimension(:), intent(in) :: x integer, intent(in), optional :: even ${t1}$, dimension(size(x)) :: w end function simps_weights_${k1}$ #:endfor end interface simps_weights interface gauss_legendre !! version: experimental !! !! Computes Gauss-Legendre quadrature nodes and weights. pure module subroutine gauss_legendre_fp64 (x, w, interval) real(dp), intent(out) :: x(:), w(:) real(dp), intent(in), optional :: interval(2) end subroutine end interface gauss_legendre interface gauss_legendre_lobatto !! version: experimental !! !! Computes Gauss-Legendre-Lobatto quadrature nodes and weights. pure module subroutine gauss_legendre_lobatto_fp64 (x, w, interval) real(dp), intent(out) :: x(:), w(:) real(dp), intent(in), optional :: interval(2) end subroutine end interface gauss_legendre_lobatto ! Interface for a simple f(x)-style integrand function. ! Could become fancier as we learn about the performance ! ramifications of different ways to do callbacks. abstract interface #:for k1, t1 in REAL_KINDS_TYPES pure function integrand_${k1}$(x) result(f) import :: ${k1}$ ${t1}$, intent(in) :: x ${t1}$ :: f end function integrand_${k1}$ #:endfor end interface end module stdlib_quadrature fortran-lang-stdlib-0ede301/src/quadrature/stdlib_quadrature_simps.fypp0000664000175000017500000002253315135654166026770 0ustar alastairalastair#:include "common.fypp" submodule (stdlib_quadrature) stdlib_quadrature_simps use stdlib_error, only: check implicit none ! internal use only interface simps38 #:for k1, t1 in REAL_KINDS_TYPES module procedure simps38_dx_${k1}$ module procedure simps38_x_${k1}$ #:endfor end interface simps38 ! internal use only interface simps38_weights #:for k1, t1 in REAL_KINDS_TYPES module procedure simps38_weights_${k1}$ #:endfor end interface simps38_weights contains #:for k1, t1 in REAL_KINDS_TYPES pure recursive module function simps_dx_${k1}$(y, dx, even) result(integral) ${t1}$, dimension(:), intent(in) :: y ${t1}$, intent(in) :: dx integer, intent(in), optional :: even ${t1}$ :: integral integer :: n n = size(y) select case (n) case (0:1) integral = 0.0_${k1}$ case (2) integral = 0.5_${k1}$*dx*(y(1) + y(2)) case (3) integral = dx/3.0_${k1}$*(y(1) + 4*y(2) + y(3)) case (4) integral = simps38(y, dx) ! case (5) not needed; handled by default case (6) ! needs special handling because of averaged 3/8's rule case if (present(even)) then if (even < 0) then ! 3/8 rule on left integral = simps38(y(1:4), dx) + simps(y(4:6), dx) return else if (even > 0) then ! 3/8 rule on right integral = simps(y(1:3), dx) + simps38(y(3:6), dx) return else ! fall through end if end if ! either `even` not present or is zero ! equivalent to averaging left and right integral = dx/48.0_${k1}$ * (17*(y(1) + y(6)) + 59*(y(2) + y(5)) + 44*(y(3) + y(4))) case default if (mod(n, 2) == 1) then integral = dx/3.0_${k1}$*(y(1) + 4*sum(y(2:n-1:2)) + 2*sum(y(3:n-2:2)) + y(n)) else if (present(even)) then if (even < 0) then ! 3/8th rule on left integral = simps38(y(1:4), dx) + simps(y(4:n), dx) return else if (even > 0) then ! 3/8 rule on right integral = simps(y(1:n-3), dx) + simps38(y(n-3:n), dx) return else ! fall through end if end if ! either `even` not present or is zero ! equivalent to averaging left and right integral = dx/48.0_${k1}$ * (17*(y(1) + y(n)) + 59*(y(2) + y(n-1)) & + 43*(y(3) + y(n-2)) + 49*(y(4) + y(n-3)) + 48*sum(y(5:n-4))) end if end select end function simps_dx_${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES recursive module function simps_x_${k1}$(y, x, even) result(integral) ${t1}$, dimension(:), intent(in) :: y ${t1}$, dimension(:), intent(in) :: x integer, intent(in), optional :: even ${t1}$ :: integral integer :: i integer :: n ${t1}$ :: h1, h2 ${t1}$ :: a, b, c n = size(y) call check(size(x) == n, "simps: Arguments `x` and `y` must be the same size.") select case (n) case (0:1) integral = 0.0_${k1}$ case (2) integral = 0.5_${k1}$*(x(2) - x(1))*(y(1) + y(2)) case (3) h1 = x(2) - x(1) h2 = x(3) - x(2) a = (2*h1**2 + h1*h2 - h2**2)/(6*h1) b = (h1+h2)**3/(6*h1*h2) c = (2*h2**2 + h1*h2 - h1**2)/(6*h2) integral = a*y(1) + b*y(2) + c*y(3) case (4) integral = simps38(y, x) ! case (6) unneeded; handled by default case default if (mod(n, 2) == 1) then integral = 0.0_${k1}$ do i = 1, n-2, 2 h1 = x(i+1) - x(i) h2 = x(i+2) - x(i+1) a = (2*h1**2 + h1*h2 - h2**2)/(6*h1) b = (h1+h2)**3/(6*h1*h2) c = (2*h2**2 + h1*h2 - h1**2)/(6*h2) integral = integral + a*y(i) + b*y(i+1) + c*y(i+2) end do else if (present(even)) then if (even < 0) then ! 3/8 rule on left integral = simps38(y(1:4), x(1:4)) + simps(y(4:n), x(4:n)) return else if (even > 0) then ! 3/8 rule on right integral = simps(y(1:n-3), x(1:n-3)) + simps38(y(n-3:n), x(n-3:n)) return else ! fall through end if end if ! either `even` not present or is zero integral = 0.5_${k1}$ * ( simps38(y(1:4), x(1:4)) + simps(y(4:n), x(4:n)) & + simps(y(1:n-3), x(1:n-3)) + simps38(y(n-3:n), x(n-3:n)) ) end if end select end function simps_x_${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES pure recursive module function simps_weights_${k1}$(x, even) result(w) ${t1}$, dimension(:), intent(in) :: x integer, intent(in), optional :: even ${t1}$, dimension(size(x)) :: w integer :: i, n ${t1}$ :: h1, h2 n = size(x) select case (n) case (0) ! no action needed case (1) w(1) = 0.0_${k1}$ case (2) w = 0.5_${k1}$*(x(2) - x(1)) case (3) h1 = x(2) - x(1) h2 = x(3) - x(2) w(1) = (2*h1**2 + h1*h2 - h2**2)/(6*h1) w(2) = (h1+h2)**3/(6*h1*h2) w(3) = (2*h2**2 + h1*h2 - h1**2)/(6*h2) case (4) w = simps38_weights(x) case default if (mod(n, 2) == 1) then w = 0.0_${k1}$ do i = 1, n-2, 2 h1 = x(i+1) - x(i) h2 = x(i+2) - x(i+1) w(i) = w(i) + (2*h1**2 + h1*h2 - h2**2)/(6*h1) w(i+1) = w(i+1) + (h1+h2)**3/(6*h1*h2) w(i+2) = w(i+2) + (2*h2**2 + h1*h2 - h1**2)/(6*h2) end do else if (present(even)) then if (even < 0) then ! 3/8 rule on left w = 0.0_${k1}$ w(1:4) = simps38_weights(x(1:4)) w(4:n) = w(4:n) + simps_weights(x(4:n)) ! position 4 needs both rules return else if (even > 0) then ! 3/8 rule on right w = 0.0_${k1}$ w(1:n-3) = simps_weights(x(1:n-3)) w(n-3:n) = w(n-3:n) + simps38_weights(x(n-3:n)) ! position n-3 needs both rules return else ! fall through end if end if ! either `even` not present or is zero w = 0.0_${k1}$ ! 3/8 rule on left w(1:4) = simps38_weights(x(1:4)) w(4:n) = w(4:n) + simps_weights(x(4:n)) ! 3/8 rule on right w(1:n-3) = w(1:n-3) + simps_weights(x(1:n-3)) w(n-3:n) = w(n-3:n) + simps38_weights(x(n-3:n)) ! average w = 0.5_${k1}$ * w end if end select end function simps_weights_${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES pure function simps38_dx_${k1}$(y, dx) result (integral) ${t1}$, dimension(4), intent(in) :: y ${t1}$, intent(in) :: dx ${t1}$ :: integral integral = 3.0_${k1}$*dx/8.0_${k1}$ * (y(1) + y(4) + 3*(y(2) + y(3))) end function simps38_dx_${k1}$ #:endfor #: for k1, t1 in REAL_KINDS_TYPES pure function simps38_x_${k1}$(y, x) result(integral) ${t1}$, dimension(4), intent(in) :: y ${t1}$, dimension(4), intent(in) :: x ${t1}$ :: integral ${t1}$ :: h1, h2, h3 ${t1}$ :: a, b, c, d h1 = x(2) - x(1) h2 = x(3) - x(2) h3 = x(4) - x(3) a = (h1+h2+h3)*(3*h1**2 + 2*h1*h2 - 2*h1*h3 - h2**2 + h3**2)/(12*h1*(h1+h2)) b = (h1+h2-h3)*(h1+h2+h3)**3/(12*h1*h2*(h2+h3)) c = (h2+h3-h1)*(h1+h2+h3)**3/(12*h2*h3*(h1+h2)) d = (h1+h2+h3)*(3*h3**2 + 2*h2*h3 - 2*h1*h3 - h2**2 + h1**2)/(12*h3*(h2+h3)) integral = a*y(1) + b*y(2) + c*y(3) + d*y(4) end function simps38_x_${k1}$ #:endfor #:for k1, t1 in REAL_KINDS_TYPES pure function simps38_weights_${k1}$(x) result(w) ${t1}$, intent(in) :: x(4) ${t1}$ :: w(size(x)) ${t1}$ :: h1, h2, h3 h1 = x(2) - x(1) h2 = x(3) - x(2) h3 = x(4) - x(3) w(1) = (h1+h2+h3)*(3*h1**2 + 2*h1*h2 - 2*h1*h3 - h2**2 + h3**2)/(12*h1*(h1+h2)) w(2) = (h1+h2-h3)*(h1+h2+h3)**3/(12*h1*h2*(h2+h3)) w(3) = (h2+h3-h1)*(h1+h2+h3)**3/(12*h2*h3*(h1+h2)) w(4) = (h1+h2+h3)*(3*h3**2 + 2*h2*h3 - 2*h1*h3 - h2**2 + h1**2)/(12*h3*(h2+h3)) end function simps38_weights_${k1}$ #:endfor end submodule stdlib_quadrature_simps fortran-lang-stdlib-0ede301/src/sparse/0000775000175000017500000000000015135654166020252 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/sparse/stdlib_sparse.f900000664000175000017500000000022315135654166023425 0ustar alastairalastair!! public API module stdlib_sparse use stdlib_sparse_kinds use stdlib_sparse_conversion use stdlib_sparse_spmv end module stdlib_sparsefortran-lang-stdlib-0ede301/src/sparse/stdlib_sparse_spmv.fypp0000664000175000017500000006056715135654166025073 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(1, 2+1) #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set KINDS_TYPES = R_KINDS_TYPES+C_KINDS_TYPES #! define ranks without parentheses #:def rksfx2(rank) #{if rank > 0}#${":," + ":," * (rank - 1)}$#{endif}# #:enddef !! The `stdlib_sparse_spmv` submodule provides matrix-vector product kernels. !! ! This code was modified from https://github.com/jalvesz/FSPARSE by its author: Alves Jose module stdlib_sparse_spmv use stdlib_sparse_constants use stdlib_sparse_kinds implicit none private !! Version experimental !! !! Apply the sparse matrix-vector product $$y = \alpha * op(M) * x + \beta * y $$ !! [Specifications](../page/specs/stdlib_sparse.html#spmv) interface spmv #:for k1, t1, s1 in (KINDS_TYPES) #:for rank in RANKS module procedure :: spmv_coo_${rank}$d_${s1}$ module procedure :: spmv_csr_${rank}$d_${s1}$ module procedure :: spmv_csc_${rank}$d_${s1}$ module procedure :: spmv_ell_${rank}$d_${s1}$ #:endfor module procedure :: spmv_sellc_${s1}$ #:endfor end interface public :: spmv contains !! spmv_coo #:for k1, t1, s1 in (KINDS_TYPES) #:for rank in RANKS subroutine spmv_coo_${rank}$d_${s1}$(matrix,vec_x,vec_y,alpha,beta,op) type(COO_${s1}$_type), intent(in) :: matrix ${t1}$, intent(in) :: vec_x${ranksuffix(rank)}$ ${t1}$, intent(inout) :: vec_y${ranksuffix(rank)}$ ${t1}$, intent(in), optional :: alpha ${t1}$, intent(in), optional :: beta character(1), intent(in), optional :: op ${t1}$ :: alpha_ character(1) :: op_ integer(ilp) :: k, ik, jk op_ = sparse_op_none; if(present(op)) op_ = op alpha_ = one_${k1}$ if(present(alpha)) alpha_ = alpha if(present(beta)) then vec_y = beta * vec_y else vec_y = zero_${s1}$ endif associate( data => matrix%data, index => matrix%index, storage => matrix%storage, nnz => matrix%nnz ) select case(op_) case(sparse_op_none) if(storage == sparse_full) then do concurrent (k = 1:nnz) ik = index(1,k) jk = index(2,k) vec_y(${rksfx2(rank-1)}$ik) = vec_y(${rksfx2(rank-1)}$ik) + alpha_*data(k) * vec_x(${rksfx2(rank-1)}$jk) end do else do concurrent (k = 1:nnz) ik = index(1,k) jk = index(2,k) vec_y(${rksfx2(rank-1)}$ik) = vec_y(${rksfx2(rank-1)}$ik) + alpha_*data(k) * vec_x(${rksfx2(rank-1)}$jk) if( ik==jk ) cycle vec_y(${rksfx2(rank-1)}$jk) = vec_y(${rksfx2(rank-1)}$jk) + alpha_*data(k) * vec_x(${rksfx2(rank-1)}$ik) end do end if case(sparse_op_transpose) if(storage == sparse_full) then do concurrent (k = 1:nnz) jk = index(1,k) ik = index(2,k) vec_y(${rksfx2(rank-1)}$ik) = vec_y(${rksfx2(rank-1)}$ik) + alpha_*data(k) * vec_x(${rksfx2(rank-1)}$jk) end do else do concurrent (k = 1:nnz) jk = index(1,k) ik = index(2,k) vec_y(${rksfx2(rank-1)}$ik) = vec_y(${rksfx2(rank-1)}$ik) + alpha_*data(k) * vec_x(${rksfx2(rank-1)}$jk) if( ik==jk ) cycle vec_y(${rksfx2(rank-1)}$jk) = vec_y(${rksfx2(rank-1)}$jk) + alpha_*data(k) * vec_x(${rksfx2(rank-1)}$ik) end do end if #:if t1.startswith('complex') case(sparse_op_hermitian) if(storage == sparse_full) then do concurrent (k = 1:nnz) jk = index(1,k) ik = index(2,k) vec_y(${rksfx2(rank-1)}$ik) = vec_y(${rksfx2(rank-1)}$ik) + alpha_*conjg(data(k)) * vec_x(${rksfx2(rank-1)}$jk) end do else do concurrent (k = 1:nnz) jk = index(1,k) ik = index(2,k) vec_y(${rksfx2(rank-1)}$ik) = vec_y(${rksfx2(rank-1)}$ik) + alpha_*conjg(data(k)) * vec_x(${rksfx2(rank-1)}$jk) if( ik==jk ) cycle vec_y(${rksfx2(rank-1)}$jk) = vec_y(${rksfx2(rank-1)}$jk) + alpha_*conjg(data(k)) * vec_x(${rksfx2(rank-1)}$ik) end do end if #:endif end select end associate end subroutine #:endfor #:endfor !! spmv_csr #:for k1, t1, s1 in (KINDS_TYPES) #:for rank in RANKS subroutine spmv_csr_${rank}$d_${s1}$(matrix,vec_x,vec_y,alpha,beta,op) type(CSR_${s1}$_type), intent(in) :: matrix ${t1}$, intent(in) :: vec_x${ranksuffix(rank)}$ ${t1}$, intent(inout) :: vec_y${ranksuffix(rank)}$ ${t1}$, intent(in), optional :: alpha ${t1}$, intent(in), optional :: beta character(1), intent(in), optional :: op ${t1}$ :: alpha_ character(1) :: op_ integer(ilp) :: i, j #:if rank == 1 ${t1}$ :: aux, aux2 #:else ${t1}$ :: aux(size(vec_x,dim=1)), aux2(size(vec_x,dim=1)) #:endif op_ = sparse_op_none; if(present(op)) op_ = op alpha_ = one_${k1}$ if(present(alpha)) alpha_ = alpha if(present(beta)) then vec_y = beta * vec_y else vec_y = zero_${s1}$ endif associate( data => matrix%data, col => matrix%col, rowptr => matrix%rowptr, & & nnz => matrix%nnz, nrows => matrix%nrows, ncols => matrix%ncols, storage => matrix%storage ) if( storage == sparse_full .and. op_==sparse_op_none ) then do i = 1, nrows aux = zero_${k1}$ do j = rowptr(i), rowptr(i+1)-1 aux = aux + data(j) * vec_x(${rksfx2(rank-1)}$col(j)) end do vec_y(${rksfx2(rank-1)}$i) = vec_y(${rksfx2(rank-1)}$i) + alpha_ * aux end do else if( storage == sparse_full .and. op_==sparse_op_transpose ) then do i = 1, nrows aux = alpha_ * vec_x(${rksfx2(rank-1)}$i) do j = rowptr(i), rowptr(i+1)-1 vec_y(${rksfx2(rank-1)}$col(j)) = vec_y(${rksfx2(rank-1)}$col(j)) + data(j) * aux end do end do else if( storage == sparse_lower .and. op_/=sparse_op_hermitian )then do i = 1 , nrows aux = zero_${s1}$ aux2 = alpha_ * vec_x(${rksfx2(rank-1)}$i) do j = rowptr(i), rowptr(i+1)-2 aux = aux + data(j) * vec_x(${rksfx2(rank-1)}$col(j)) vec_y(${rksfx2(rank-1)}$col(j)) = vec_y(${rksfx2(rank-1)}$col(j)) + data(j) * aux2 end do aux = alpha_ * aux + data(j) * aux2 vec_y(${rksfx2(rank-1)}$i) = vec_y(${rksfx2(rank-1)}$i) + aux end do else if( storage == sparse_upper .and. op_/=sparse_op_hermitian )then do i = 1 , nrows aux = vec_x(${rksfx2(rank-1)}$i) * data(rowptr(i)) aux2 = alpha_ * vec_x(${rksfx2(rank-1)}$i) do j = rowptr(i)+1, rowptr(i+1)-1 aux = aux + data(j) * vec_x(${rksfx2(rank-1)}$col(j)) vec_y(${rksfx2(rank-1)}$col(j)) = vec_y(${rksfx2(rank-1)}$col(j)) + data(j) * aux2 end do vec_y(${rksfx2(rank-1)}$i) = vec_y(${rksfx2(rank-1)}$i) + alpha_ * aux end do #:if t1.startswith('complex') else if( storage == sparse_full .and. op_==sparse_op_hermitian) then do i = 1, nrows aux = alpha_ * vec_x(${rksfx2(rank-1)}$i) do j = rowptr(i), rowptr(i+1)-1 vec_y(${rksfx2(rank-1)}$col(j)) = vec_y(${rksfx2(rank-1)}$col(j)) + conjg(data(j)) * aux end do end do else if( storage == sparse_lower .and. op_==sparse_op_hermitian )then do i = 1 , nrows aux = zero_${s1}$ aux2 = alpha_ * vec_x(${rksfx2(rank-1)}$i) do j = rowptr(i), rowptr(i+1)-2 aux = aux + conjg(data(j)) * vec_x(${rksfx2(rank-1)}$col(j)) vec_y(${rksfx2(rank-1)}$col(j)) = vec_y(${rksfx2(rank-1)}$col(j)) + conjg(data(j)) * aux2 end do aux = alpha_ * aux + conjg(data(j)) * aux2 vec_y(${rksfx2(rank-1)}$i) = vec_y(${rksfx2(rank-1)}$i) + aux end do else if( storage == sparse_upper .and. op_==sparse_op_hermitian )then do i = 1 , nrows aux = vec_x(${rksfx2(rank-1)}$i) * conjg(data(rowptr(i))) aux2 = alpha_ * vec_x(${rksfx2(rank-1)}$i) do j = rowptr(i)+1, rowptr(i+1)-1 aux = aux + conjg(data(j)) * vec_x(${rksfx2(rank-1)}$col(j)) vec_y(${rksfx2(rank-1)}$col(j)) = vec_y(${rksfx2(rank-1)}$col(j)) + conjg(data(j)) * aux2 end do vec_y(${rksfx2(rank-1)}$i) = vec_y(${rksfx2(rank-1)}$i) + alpha_ * aux end do #:endif end if end associate end subroutine #:endfor #:endfor !! spmv_csc #:for k1, t1, s1 in (KINDS_TYPES) #:for rank in RANKS subroutine spmv_csc_${rank}$d_${s1}$(matrix,vec_x,vec_y,alpha,beta,op) type(CSC_${s1}$_type), intent(in) :: matrix ${t1}$, intent(in) :: vec_x${ranksuffix(rank)}$ ${t1}$, intent(inout) :: vec_y${ranksuffix(rank)}$ ${t1}$, intent(in), optional :: alpha ${t1}$, intent(in), optional :: beta character(1), intent(in), optional :: op ${t1}$ :: alpha_ character(1) :: op_ integer(ilp) :: i, j #:if rank == 1 ${t1}$ :: aux #:else ${t1}$ :: aux(size(vec_x,dim=1)) #:endif op_ = sparse_op_none; if(present(op)) op_ = op alpha_ = one_${k1}$ if(present(alpha)) alpha_ = alpha if(present(beta)) then vec_y = beta * vec_y else vec_y = zero_${s1}$ endif associate( data => matrix%data, colptr => matrix%colptr, row => matrix%row, & & nnz => matrix%nnz, nrows => matrix%nrows, ncols => matrix%ncols, storage => matrix%storage ) if( storage == sparse_full .and. op_==sparse_op_none ) then do concurrent(j=1:ncols) aux = alpha_ * vec_x(${rksfx2(rank-1)}$j) do i = colptr(j), colptr(j+1)-1 vec_y(${rksfx2(rank-1)}$row(i)) = vec_y(${rksfx2(rank-1)}$row(i)) + data(i) * aux end do end do else if( storage == sparse_full .and. op_==sparse_op_transpose ) then do concurrent(j=1:ncols) aux = zero_${k1}$ do i = colptr(j), colptr(j+1)-1 aux = aux + data(i) * vec_x(${rksfx2(rank-1)}$row(i)) end do vec_y(${rksfx2(rank-1)}$j) = vec_y(${rksfx2(rank-1)}$j) + alpha_ * aux end do else if( storage == sparse_lower .and. op_/=sparse_op_hermitian )then do j = 1 , ncols aux = vec_x(${rksfx2(rank-1)}$j) * data(colptr(j)) do i = colptr(j)+1, colptr(j+1)-1 aux = aux + data(i) * vec_x(${rksfx2(rank-1)}$row(i)) vec_y(${rksfx2(rank-1)}$row(i)) = vec_y(${rksfx2(rank-1)}$row(i)) + alpha_ * data(i) * vec_x(${rksfx2(rank-1)}$j) end do vec_y(${rksfx2(rank-1)}$j) = vec_y(${rksfx2(rank-1)}$j) + alpha_ * aux end do else if( storage == sparse_upper .and. op_/=sparse_op_hermitian )then do j = 1 , ncols aux = zero_${s1}$ do i = colptr(j), colptr(i+1)-2 aux = aux + data(i) * vec_x(${rksfx2(rank-1)}$j) vec_y(${rksfx2(rank-1)}$i) = vec_y(${rksfx2(rank-1)}$i) + alpha_ * data(i) * vec_x(${rksfx2(rank-1)}$row(i)) end do aux = aux + data(colptr(j)) * vec_x(${rksfx2(rank-1)}$j) vec_y(${rksfx2(rank-1)}$j) = vec_y(${rksfx2(rank-1)}$j) + alpha_ * aux end do #:if t1.startswith('complex') else if( storage == sparse_full .and. op_==sparse_op_hermitian ) then do concurrent(j=1:ncols) aux = zero_${k1}$ do i = colptr(j), colptr(j+1)-1 aux = aux + conjg(data(i)) * vec_x(${rksfx2(rank-1)}$row(i)) end do vec_y(${rksfx2(rank-1)}$j) = vec_y(${rksfx2(rank-1)}$j) + alpha_ * aux end do else if( storage == sparse_lower .and. op_==sparse_op_hermitian )then do j = 1 , ncols aux = vec_x(${rksfx2(rank-1)}$j) * conjg(data(colptr(j))) do i = colptr(j)+1, colptr(j+1)-1 aux = aux + conjg(data(i)) * vec_x(${rksfx2(rank-1)}$row(i)) vec_y(${rksfx2(rank-1)}$row(i)) = vec_y(${rksfx2(rank-1)}$row(i)) + alpha_ * conjg(data(i)) * vec_x(${rksfx2(rank-1)}$j) end do vec_y(${rksfx2(rank-1)}$j) = vec_y(${rksfx2(rank-1)}$j) + alpha_ * aux end do else if( storage == sparse_upper .and. op_==sparse_op_hermitian )then do j = 1 , ncols aux = zero_${s1}$ do i = colptr(j), colptr(i+1)-2 aux = aux + conjg(data(i)) * vec_x(${rksfx2(rank-1)}$j) vec_y(${rksfx2(rank-1)}$i) = vec_y(${rksfx2(rank-1)}$i) + alpha_ * conjg(data(i)) * vec_x(${rksfx2(rank-1)}$row(i)) end do aux = aux + conjg(data(colptr(j))) * vec_x(${rksfx2(rank-1)}$j) vec_y(${rksfx2(rank-1)}$j) = vec_y(${rksfx2(rank-1)}$j) + alpha_ * aux end do #:endif end if end associate end subroutine #:endfor #:endfor !! spmv_ell #:for k1, t1, s1 in (KINDS_TYPES) #:for rank in RANKS subroutine spmv_ell_${rank}$d_${s1}$(matrix,vec_x,vec_y,alpha,beta,op) type(ELL_${s1}$_type), intent(in) :: matrix ${t1}$, intent(in) :: vec_x${ranksuffix(rank)}$ ${t1}$, intent(inout) :: vec_y${ranksuffix(rank)}$ ${t1}$, intent(in), optional :: alpha ${t1}$, intent(in), optional :: beta character(1), intent(in), optional :: op ${t1}$ :: alpha_ character(1) :: op_ integer(ilp) :: i, j, k op_ = sparse_op_none; if(present(op)) op_ = op alpha_ = one_${k1}$ if(present(alpha)) alpha_ = alpha if(present(beta)) then vec_y = beta * vec_y else vec_y = zero_${s1}$ endif associate( data => matrix%data, index => matrix%index, MNZ_P_ROW => matrix%K, & & nnz => matrix%nnz, nrows => matrix%nrows, ncols => matrix%ncols, storage => matrix%storage ) if( storage == sparse_full .and. op_==sparse_op_none ) then do concurrent (i = 1:nrows, k = 1:MNZ_P_ROW) j = index(i,k) if(j>0) vec_y(${rksfx2(rank-1)}$i) = vec_y(${rksfx2(rank-1)}$i) + alpha_*data(i,k) * vec_x(${rksfx2(rank-1)}$j) end do else if( storage == sparse_full .and. op_==sparse_op_transpose ) then do concurrent (i = 1:nrows, k = 1:MNZ_P_ROW) j = index(i,k) if(j>0) vec_y(${rksfx2(rank-1)}$j) = vec_y(${rksfx2(rank-1)}$j) + alpha_*data(i,k) * vec_x(${rksfx2(rank-1)}$i) end do else if( storage /= sparse_full .and. op_/=sparse_op_hermitian ) then do concurrent (i = 1:nrows, k = 1:MNZ_P_ROW) j = index(i,k) if(j>0) then vec_y(${rksfx2(rank-1)}$i) = vec_y(${rksfx2(rank-1)}$i) + alpha_*data(i,k) * vec_x(${rksfx2(rank-1)}$j) if(i==j) cycle vec_y(${rksfx2(rank-1)}$j) = vec_y(${rksfx2(rank-1)}$j) + alpha_*data(i,k) * vec_x(${rksfx2(rank-1)}$i) end if end do #:if t1.startswith('complex') else if( storage == sparse_full .and. op_==sparse_op_hermitian ) then do concurrent (i = 1:nrows, k = 1:MNZ_P_ROW) j = index(i,k) if(j>0) vec_y(${rksfx2(rank-1)}$j) = vec_y(${rksfx2(rank-1)}$j) + alpha_*conjg(data(i,k)) * vec_x(${rksfx2(rank-1)}$i) end do else if( storage /= sparse_full .and. op_==sparse_op_hermitian ) then do concurrent (i = 1:nrows, k = 1:MNZ_P_ROW) j = index(i,k) if(j>0) then vec_y(${rksfx2(rank-1)}$i) = vec_y(${rksfx2(rank-1)}$i) + alpha_*conjg(data(i,k)) * vec_x(${rksfx2(rank-1)}$j) if(i==j) cycle vec_y(${rksfx2(rank-1)}$j) = vec_y(${rksfx2(rank-1)}$j) + alpha_*conjg(data(i,k)) * vec_x(${rksfx2(rank-1)}$i) end if end do #:endif end if end associate end subroutine #:endfor #:endfor !! spmv_sellc #:set CHUNKS = [4,8,16] #:for k1, t1, s1 in (KINDS_TYPES) subroutine spmv_sellc_${s1}$(matrix,vec_x,vec_y,alpha,beta,op) !! This algorithm was gracefully provided by Ivan Privec and adapted by Jose Alves type(SELLC_${s1}$_type), intent(in) :: matrix ${t1}$, intent(in) :: vec_x(:) ${t1}$, intent(inout) :: vec_y(:) ${t1}$, intent(in), optional :: alpha ${t1}$, intent(in), optional :: beta character(1), intent(in), optional :: op ${t1}$ :: alpha_ character(1) :: op_ integer(ilp) :: i, nz, rowidx, num_chunks, rm op_ = sparse_op_none; if(present(op)) op_ = op alpha_ = one_${s1}$ if(present(alpha)) alpha_ = alpha if(present(beta)) then vec_y = beta * vec_y else vec_y = zero_${s1}$ endif associate( data => matrix%data, ia => matrix%rowptr , ja => matrix%col, cs => matrix%chunk_size, & & nnz => matrix%nnz, nrows => matrix%nrows, ncols => matrix%ncols, storage => matrix%storage ) if( .not.any( ${CHUNKS}$ == cs ) ) then print *, "error: sellc chunk size not supported." return end if num_chunks = nrows / cs rm = nrows - num_chunks * cs if( storage == sparse_full .and. op_==sparse_op_none ) then select case(cs) #:for chunk in CHUNKS case(${chunk}$) do i = 1, num_chunks nz = ia(i+1) - ia(i) rowidx = (i - 1)*${chunk}$ + 1 call chunk_kernel_${chunk}$(nz,data(:,ia(i)),ja(:,ia(i)),vec_x,vec_y(rowidx:)) end do #:endfor end select ! remainder if(rm>0)then i = num_chunks + 1 nz = ia(i+1) - ia(i) rowidx = (i - 1)*cs + 1 call chunk_kernel_rm(nz,cs,rm,data(:,ia(i)),ja(:,ia(i)),vec_x,vec_y(rowidx:)) end if else if( storage == sparse_full .and. op_==sparse_op_transpose ) then select case(cs) #:for chunk in CHUNKS case(${chunk}$) do i = 1, num_chunks nz = ia(i+1) - ia(i) rowidx = (i - 1)*${chunk}$ + 1 call chunk_kernel_trans_${chunk}$(nz,data(:,ia(i)),ja(:,ia(i)),vec_x(rowidx:),vec_y) end do #:endfor end select ! remainder if(rm>0)then i = num_chunks + 1 nz = ia(i+1) - ia(i) rowidx = (i - 1)*cs + 1 call chunk_kernel_rm_trans(nz,cs,rm,data(:,ia(i)),ja(:,ia(i)),vec_x(rowidx:),vec_y) end if #:if t1.startswith('complex') else if( storage == sparse_full .and. op_==sparse_op_hermitian ) then select case(cs) #:for chunk in CHUNKS case(${chunk}$) do i = 1, num_chunks nz = ia(i+1) - ia(i) rowidx = (i - 1)*${chunk}$ + 1 call chunk_kernel_herm_${chunk}$(nz,data(:,ia(i)),ja(:,ia(i)),vec_x(rowidx:),vec_y) end do #:endfor end select ! remainder if(rm>0)then i = num_chunks + 1 nz = ia(i+1) - ia(i) rowidx = (i - 1)*cs + 1 call chunk_kernel_rm_herm(nz,cs,rm,data(:,ia(i)),ja(:,ia(i)),vec_x(rowidx:),vec_y) end if #:endif else print *, "error: sellc format for spmv operation not yet supported." return end if end associate contains #:for chunk in CHUNKS pure subroutine chunk_kernel_${chunk}$(n,a,col,x,y) integer, value :: n ${t1}$, intent(in) :: a(${chunk}$,n), x(:) integer(ilp), intent(in) :: col(${chunk}$,n) ${t1}$, intent(inout) :: y(${chunk}$) integer :: j do j = 1, n y(:) = y(:) + alpha_ * a(:,j) * x(col(:,j)) end do end subroutine pure subroutine chunk_kernel_trans_${chunk}$(n,a,col,x,y) integer, value :: n ${t1}$, intent(in) :: a(${chunk}$,n), x(${chunk}$) integer(ilp), intent(in) :: col(${chunk}$,n) ${t1}$, intent(inout) :: y(:) integer :: j, k do j = 1, n do k = 1, ${chunk}$ y(col(k,j)) = y(col(k,j)) + alpha_ * a(k,j) * x(k) end do end do end subroutine #:if t1.startswith('complex') pure subroutine chunk_kernel_herm_${chunk}$(n,a,col,x,y) integer, value :: n ${t1}$, intent(in) :: a(${chunk}$,n), x(${chunk}$) integer(ilp), intent(in) :: col(${chunk}$,n) ${t1}$, intent(inout) :: y(:) integer :: j, k do j = 1, n do k = 1, ${chunk}$ y(col(k,j)) = y(col(k,j)) + alpha_ * conjg(a(k,j)) * x(k) end do end do end subroutine #:endif #:endfor pure subroutine chunk_kernel_rm(n,cs,r,a,col,x,y) integer, value :: n, cs, r ${t1}$, intent(in) :: a(cs,n), x(:) integer(ilp), intent(in) :: col(cs,n) ${t1}$, intent(inout) :: y(r) integer :: j do j = 1, n y(1:r) = y(1:r) + alpha_ * a(1:r,j) * x(col(1:r,j)) end do end subroutine pure subroutine chunk_kernel_rm_trans(n,cs,r,a,col,x,y) integer, value :: n, cs, r ${t1}$, intent(in) :: a(cs,n), x(r) integer(ilp), intent(in) :: col(cs,n) ${t1}$, intent(inout) :: y(:) integer :: j, k do j = 1, n do k = 1, r y(col(k,j)) = y(col(k,j)) + alpha_ * a(k,j) * x(k) end do end do end subroutine #:if t1.startswith('complex') pure subroutine chunk_kernel_rm_herm(n,cs,r,a,col,x,y) integer, value :: n, cs, r ${t1}$, intent(in) :: a(cs,n), x(r) integer(ilp), intent(in) :: col(cs,n) ${t1}$, intent(inout) :: y(:) integer :: j, k do j = 1, n do k = 1, r y(col(k,j)) = y(col(k,j)) + alpha_ * conjg(a(k,j)) * x(k) end do end do end subroutine #:endif end subroutine #:endfor end module fortran-lang-stdlib-0ede301/src/sparse/CMakeLists.txt0000664000175000017500000000065315135654166023016 0ustar alastairalastairset(sparse_fppFiles stdlib_sparse_constants.fypp stdlib_sparse_conversion.fypp stdlib_sparse_kinds.fypp stdlib_sparse_spmv.fypp ) set(sparse_cppFiles ) set(sparse_f90Files stdlib_sparse.f90 ) configure_stdlib_target(${PROJECT_NAME}_sparse sparse_f90Files sparse_fppFiles sparse_cppFiles) target_link_libraries(${PROJECT_NAME}_sparse PUBLIC ${PROJECT_NAME}_constants ${PROJECT_NAME}_sorting) fortran-lang-stdlib-0ede301/src/sparse/stdlib_sparse_conversion.fypp0000664000175000017500000007660015135654166026266 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set KINDS_TYPES = R_KINDS_TYPES+C_KINDS_TYPES !! The `stdlib_sparse_conversion` submodule provides sparse to sparse matrix conversion utilities. !! ! This code was modified from https://github.com/jalvesz/FSPARSE by its author: Alves Jose module stdlib_sparse_conversion use stdlib_sorting, only: sort use stdlib_sparse_constants use stdlib_sparse_kinds implicit none private !! Sort arrays of a COO matrix !! interface sort_coo module procedure :: sort_coo_unique #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: sort_coo_unique_${s1}$ #:endfor end interface !! version: experimental !! !! Conversion from dense to coo !! Enables extracting the non-zero elements of a dense 2D matrix and !! storing those values in a COO format. The coo matrix is (re)allocated on the fly. !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) interface dense2coo #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: dense2coo_${s1}$ #:endfor end interface public :: dense2coo !! version: experimental !! !! Conversion from coo to dense !! Enables creating a dense 2D matrix from the non-zero values stored in a COO format !! The dense matrix can be allocated on the fly if not pre-allocated by the user. !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) interface coo2dense #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: coo2dense_${s1}$ #:endfor end interface public :: coo2dense !! version: experimental !! !! Conversion from coo to csr !! Enables transferring data from a COO matrix to a CSR matrix !! under the hypothesis that the COO is already ordered. !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) interface coo2csr #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: coo2csr_${s1}$ #:endfor end interface public :: coo2csr !! version: experimental !! !! Conversion from coo to csc !! Enables transferring data from a COO matrix to a CSC matrix !! under the hypothesis that the COO is already ordered. !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) interface coo2csc #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: coo2csc_${s1}$ #:endfor end interface public :: coo2csc !! version: experimental !! !! Conversion from csr to dense !! Enables creating a dense 2D matrix from the non-zero values stored in a CSR format !! The dense matrix can be allocated on the fly if not pre-allocated by the user. !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) interface csr2dense #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: csr2dense_${s1}$ #:endfor end interface public :: csr2dense !! version: experimental !! !! Conversion from csr to coo !! Enables transferring data from a CSR matrix to a COO matrix !! under the hypothesis that the CSR is already ordered. !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) interface csr2coo #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: csr2coo_${s1}$ #:endfor end interface public :: csr2coo !! version: experimental !! !! Conversion from csr to ell !! Enables transferring data from a CSR matrix to a ELL matrix !! under the hypothesis that the CSR is already ordered. !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) interface csr2ell #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: csr2ell_${s1}$ #:endfor end interface public :: csr2ell !! version: experimental !! !! Conversion from csr to SELL-C !! Enables transferring data from a CSR matrix to a SELL-C matrix !! It takes an optional parameter to decide the chunck size 4, 8 or 16 !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) interface csr2sellc #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: csr2sellc_${s1}$ #:endfor end interface public :: csr2sellc !! version: experimental !! !! Conversion from csc to coo !! Enables transferring data from a CSC matrix to a COO matrix !! under the hypothesis that the CSC is already ordered. !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) interface csc2coo #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: csc2coo_${s1}$ #:endfor end interface public :: csc2coo !! version: experimental !! !! Extraction of diagonal values !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) interface diag #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: dense2diagonal_${s1}$ module procedure :: coo2diagonal_${s1}$ module procedure :: csr2diagonal_${s1}$ module procedure :: csc2diagonal_${s1}$ module procedure :: ell2diagonal_${s1}$ #:endfor end interface public :: diag !! version: experimental !! !! Enable creating a sparse matrix from ijv (row,col,data) triplet !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) interface from_ijv module procedure :: coo_from_ijv_type #:for k1, t1, s1 in (KINDS_TYPES) module procedure :: coo_from_ijv_${s1}$ module procedure :: csr_from_ijv_${s1}$ module procedure :: ell_from_ijv_${s1}$ module procedure :: sellc_from_ijv_${s1}$ #:endfor end interface public :: from_ijv public :: coo2ordered contains #:for k1, t1, s1 in (KINDS_TYPES) subroutine dense2coo_${s1}$(dense,COO) ${t1}$, intent(in) :: dense(:,:) type(COO_${s1}$_type), intent(out) :: COO integer(ilp) :: num_rows, num_cols, nnz integer(ilp) :: i, j, idx num_rows = size(dense,dim=1) num_cols = size(dense,dim=2) nnz = count( abs(dense) > tiny(1._${k1}$) ) call COO%malloc(num_rows,num_cols,nnz) idx = 1 do i = 1, num_rows do j = 1, num_cols if(abs(dense(i,j)) < tiny(1._${k1}$)) cycle COO%index(1,idx) = i COO%index(2,idx) = j COO%data(idx) = dense(i,j) idx = idx + 1 end do end do COO%is_sorted = .true. end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine coo2dense_${s1}$(COO,dense) type(COO_${s1}$_type), intent(in) :: COO ${t1}$, allocatable, intent(out) :: dense(:,:) integer(ilp) :: idx if(.not.allocated(dense)) allocate(dense(COO%nrows,COO%nrows),source=zero_${s1}$) do concurrent(idx = 1:COO%nnz) dense( COO%index(1,idx) , COO%index(2,idx) ) = COO%data(idx) end do end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine coo2csr_${s1}$(COO,CSR) type(COO_${s1}$_type), intent(in) :: COO type(CSR_${s1}$_type), intent(out) :: CSR integer(ilp) :: i CSR%nnz = COO%nnz; CSR%nrows = COO%nrows; CSR%ncols = COO%ncols CSR%storage = COO%storage if( allocated(CSR%col) ) then CSR%col(1:COO%nnz) = COO%index(2,1:COO%nnz) CSR%rowptr(1:CSR%nrows) = 0 CSR%data(1:CSR%nnz) = COO%data(1:COO%nnz) else allocate( CSR%col(CSR%nnz) , source = COO%index(2,1:COO%nnz) ) allocate( CSR%rowptr(CSR%nrows+1) , source = 0 ) allocate( CSR%data(CSR%nnz) , source = COO%data(1:COO%nnz) ) end if CSR%rowptr(1) = 1 do i = 1, COO%nnz CSR%rowptr( COO%index(1,i)+1 ) = CSR%rowptr( COO%index(1,i)+1 ) + 1 end do do i = 1, CSR%nrows CSR%rowptr( i+1 ) = CSR%rowptr( i+1 ) + CSR%rowptr( i ) end do end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine coo2csc_${s1}$(COO,CSC) type(COO_${s1}$_type), intent(in) :: COO type(CSC_${s1}$_type), intent(out) :: CSC ${t1}$, allocatable :: data(:) integer(ilp), allocatable :: temp(:,:) integer(ilp) :: i, nnz CSC%nnz = COO%nnz; CSC%nrows = COO%nrows; CSC%ncols = COO%ncols CSC%storage = COO%storage allocate(temp(2,COO%nnz)) temp(1,1:COO%nnz) = COO%index(2,1:COO%nnz) temp(2,1:COO%nnz) = COO%index(1,1:COO%nnz) allocate(data, source = COO%data ) nnz = COO%nnz call sort_coo_unique_${s1}$( temp, data, nnz, COO%nrows, COO%ncols ) if( allocated(CSC%row) ) then CSC%row(1:COO%nnz) = temp(2,1:COO%nnz) CSC%colptr(1:CSC%ncols) = 0 CSC%data(1:CSC%nnz) = data(1:COO%nnz) else allocate( CSC%row(CSC%nnz) , source = temp(2,1:COO%nnz) ) allocate( CSC%colptr(CSC%ncols+1) , source = 0 ) allocate( CSC%data(CSC%nnz) , source = data(1:COO%nnz) ) end if CSC%colptr(1) = 1 do i = 1, COO%nnz CSC%colptr( temp(1,i)+1 ) = CSC%colptr( temp(1,i)+1 ) + 1 end do do i = 1, CSC%ncols CSC%colptr( i+1 ) = CSC%colptr( i+1 ) + CSC%colptr( i ) end do end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine csr2dense_${s1}$(CSR,dense) type(CSR_${s1}$_type), intent(in) :: CSR ${t1}$, allocatable, intent(out) :: dense(:,:) integer(ilp) :: i, j if(.not.allocated(dense)) allocate(dense(CSR%nrows,CSR%nrows),source=zero_${s1}$) if( CSR%storage == sparse_full) then do i = 1, CSR%nrows do j = CSR%rowptr(i), CSR%rowptr(i+1)-1 dense(i,CSR%col(j)) = CSR%data(j) end do end do else do i = 1, CSR%nrows do j = CSR%rowptr(i), CSR%rowptr(i+1)-1 dense(i,CSR%col(j)) = CSR%data(j) if( i == CSR%col(j) ) cycle dense(CSR%col(j),i) = CSR%data(j) end do end do end if end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine csr2coo_${s1}$(CSR,COO) type(CSR_${s1}$_type), intent(in) :: CSR type(COO_${s1}$_type), intent(out) :: COO integer(ilp) :: i, j COO%nnz = CSR%nnz; COO%nrows = CSR%nrows; COO%ncols = CSR%ncols COO%storage = CSR%storage if( .not.allocated(COO%data) ) then allocate( COO%data(CSR%nnz) , source = CSR%data(1:CSR%nnz) ) else COO%data(1:CSR%nnz) = CSR%data(1:CSR%nnz) end if if( .not.allocated(COO%index) ) allocate( COO%index(2,CSR%nnz) ) do i = 1, CSR%nrows do j = CSR%rowptr(i), CSR%rowptr(i+1)-1 COO%index(1:2,j) = [i,CSR%col(j)] end do end do end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine csc2coo_${s1}$(CSC,COO) type(CSC_${s1}$_type), intent(in) :: CSC type(COO_${s1}$_type), intent(out) :: COO integer(ilp) :: i, j COO%nnz = CSC%nnz; COO%nrows = CSC%nrows; COO%ncols = CSC%ncols COO%storage = CSC%storage if( .not.allocated(COO%data) ) then allocate( COO%data(CSC%nnz) , source = CSC%data(1:CSC%nnz) ) else COO%data(1:CSC%nnz) = CSC%data(1:CSC%nnz) end if if( .not.allocated(COO%index) ) allocate( COO%index(2,CSC%nnz) ) do j = 1, CSC%ncols do i = CSC%colptr(j), CSC%colptr(j+1)-1 COO%index(1:2,i) = [CSC%row(i),j] end do end do call sort_coo_unique_${s1}$( COO%index, COO%data, COO%nnz, COO%nrows, COO%ncols ) end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine csr2ell_${s1}$(CSR,ELL,num_nz_rows) type(CSR_${s1}$_type), intent(in) :: CSR type(ELL_${s1}$_type), intent(out) :: ELL integer, intent(in), optional :: num_nz_rows !! number of non zeros per row integer(ilp) :: i, j, num_nz_rows_, adr1, adr2 !------------------------------------------- num_nz_rows_ = 0 if(present(num_nz_rows)) then num_nz_rows_ = num_nz_rows else do i = 1, CSR%nrows num_nz_rows_ = max(num_nz_rows_, CSR%rowptr( i+1 ) - CSR%rowptr( i ) ) end do end if call ELL%malloc(CSR%nrows,CSR%ncols,num_nz_rows_) ELL%storage = CSR%storage !------------------------------------------- do i = 1, CSR%nrows adr1 = CSR%rowptr(i) adr2 = min( adr1+num_nz_rows_ , CSR%rowptr(i+1)-1) do j = adr1, adr2 ELL%index(i,j-adr1+1) = CSR%col(j) ELL%data(i,j-adr1+1) = CSR%data(j) end do end do end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine csr2sellc_${s1}$(CSR,SELLC,chunk) !! csr2sellc: This function enables transfering data from a CSR matrix to a SELL-C matrix !! This algorithm was gracefully provided by Ivan Privec and adapted by Jose Alves type(CSR_${s1}$_type), intent(in) :: CSR type(SELLC_${s1}$_type), intent(out) :: SELLC integer, intent(in), optional :: chunk ${t1}$, parameter :: zero = zero_${s1}$ integer(ilp) :: i, j, num_chunks if(present(chunk)) SELLC%chunk_size = chunk SELLC%nrows = CSR%nrows; SELLC%ncols = CSR%ncols SELLC%storage = CSR%storage associate( nrows=>SELLC%nrows, ncols=>SELLC%ncols, nnz=>SELLC%nnz, & & chunk_size=>SELLC%chunk_size ) !------------------------------------------- ! csr rowptr to SELL-C chunked rowptr num_chunks = (nrows + chunk_size - 1)/chunk_size allocate( SELLC%rowptr(num_chunks+1) ) block integer :: cidx, rownnz, chunknnz SELLC%rowptr(1) = 1 cidx = 1 do i = 1, nrows, chunk_size chunknnz = 0 ! Iterate over rows in a given chunk do j = i, min(i+chunk_size-1,nrows) rownnz = CSR%rowptr(j+1) - CSR%rowptr(j) chunknnz = max(chunknnz,rownnz) end do SELLC%rowptr(cidx+1) = SELLC%rowptr(cidx) + chunknnz cidx = cidx + 1 end do nnz = SELLC%rowptr(num_chunks+1) - 1 end block !------------------------------------------- ! copy values and colum index allocate(SELLC%col(chunk_size,nnz), source = 1) allocate(SELLC%data(chunk_size,nnz), source = zero ) block integer :: lb, ri, iaa, iab, rownnz do i = 1, num_chunks lb = SELLC%rowptr(i) ! Loop over rows of a chunk do j = (i-1)*chunk_size + 1, min(i*chunk_size,nrows) ri = j - (i - 1)*chunk_size rownnz = CSR%rowptr(j+1) - CSR%rowptr(j) - 1 iaa = CSR%rowptr(j) iab = CSR%rowptr(j+1) - 1 SELLC%col(ri,lb:lb+rownnz) = CSR%col(iaa:iab) SELLC%data(ri,lb:lb+rownnz) = CSR%data(iaa:iab) end do end do end block end associate end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) recursive subroutine quicksort_i_${s1}$(a, b, first, last) integer(ilp), intent(inout) :: a(*) !! reference table to sort ${t1}$, intent(inout) :: b(*) !! secondary real data to sort w.r.t. a integer(ilp), intent(in) :: first, last integer(ilp) :: i, j, x, t ${t1}$ :: d x = a( (first+last) / 2 ) i = first j = last do do while (a(i) < x) i=i+1 end do do while (x < a(j)) j=j-1 end do if (i >= j) exit t = a(i); a(i) = a(j); a(j) = t d = b(i); b(i) = b(j); b(j) = d i=i+1 j=j-1 end do if (first < i-1) call quicksort_i_${s1}$(a, b, first, i-1) if (j+1 < last) call quicksort_i_${s1}$(a, b, j+1, last) end subroutine #:endfor subroutine sort_coo_unique( a, n, num_rows, num_cols ) !! Sort a 2d array in increasing order first by index 1 and then by index 2 integer(ilp), intent(inout) :: a(2,*) integer(ilp), intent(inout) :: n integer(ilp), intent(in) :: num_rows integer(ilp), intent(in) :: num_cols integer(ilp) :: stride, adr0, adr1, dd integer(ilp) :: n_i, pos, ed integer(ilp), allocatable :: count_i(:), count_i_aux(:), rows_(:), cols_(:) !--------------------------------------------------------- ! Sort a first time with respect to first index using count sort allocate( count_i( 0:num_rows ) , source = 0 ) do ed = 1, n count_i( a(1,ed) ) = count_i( a(1,ed) ) + 1 end do do n_i = 2, num_rows count_i(n_i) = count_i(n_i) + count_i(n_i-1) end do allocate( count_i_aux( 0:num_rows ) , source = count_i ) allocate( rows_(n), cols_(n) ) do ed = n, 1, -1 n_i = a(1,ed) pos = count_i(n_i) rows_(pos) = a(1,ed) cols_(pos) = a(2,ed) count_i(n_i) = count_i(n_i) - 1 end do !--------------------------------------------------------- ! Sort with respect to second column do n_i = 1, num_rows adr0 = count_i_aux(n_i-1)+1 adr1 = count_i_aux(n_i) dd = adr1-adr0+1 if(dd>0) call sort(cols_(adr0:adr1)) end do !--------------------------------------------------------- ! Remove duplicates do ed = 1,n a(1:2,ed) = [rows_(ed),cols_(ed)] end do stride = 0 do ed = 2, n if( a(1,ed) == a(1,ed-1) .and. a(2,ed) == a(2,ed-1) ) then stride = stride + 1 else a(1:2,ed-stride) = a(1:2,ed) end if end do n = n - stride end subroutine #:for k1, t1, s1 in (KINDS_TYPES) subroutine sort_coo_unique_${s1}$( a, data, n, num_rows, num_cols ) !! Sort a 2d array in increasing order first by index 1 and then by index 2 ${t1}$, intent(inout) :: data(*) integer(ilp), intent(inout) :: a(2,*) integer(ilp), intent(inout) :: n integer(ilp), intent(in) :: num_rows integer(ilp), intent(in) :: num_cols integer(ilp) :: stride, adr0, adr1, dd integer(ilp) :: n_i, pos, ed integer(ilp), allocatable :: count_i(:), count_i_aux(:), rows_(:), cols_(:) ${t1}$, allocatable :: temp(:) !--------------------------------------------------------- ! Sort a first time with respect to first index using Count sort allocate( count_i( 0:num_rows ) , source = 0 ) do ed = 1, n count_i( a(1,ed) ) = count_i( a(1,ed) ) + 1 end do do n_i = 2, num_rows count_i(n_i) = count_i(n_i) + count_i(n_i-1) end do allocate( count_i_aux( 0:num_rows ) , source = count_i ) allocate( rows_(n), cols_(n), temp(n) ) do ed = n, 1, -1 n_i = a(1,ed) pos = count_i(n_i) rows_(pos) = a(1,ed) cols_(pos) = a(2,ed) temp(pos) = data(ed) count_i(n_i) = count_i(n_i) - 1 end do !--------------------------------------------------------- ! Sort with respect to second colum using a quicksort do n_i = 1, num_rows adr0 = count_i_aux(n_i-1)+1 adr1 = count_i_aux(n_i) dd = adr1-adr0+1 if(dd>0) call quicksort_i_${s1}$(cols_(adr0),temp(adr0),1,dd) end do !--------------------------------------------------------- ! Remove duplicates do ed = 1,n a(1:2,ed) = [rows_(ed),cols_(ed)] end do data(1:n) = temp(1:n) stride = 0 do ed = 2, n if( a(1,ed) == a(1,ed-1) .and. a(2,ed) == a(2,ed-1) ) then data(ed-1-stride) = data(ed-1-stride) + data(ed) data(ed) = data(ed-1-stride) stride = stride + 1 else a(1:2,ed-stride) = a(1:2,ed) data(ed-stride) = data(ed) end if end do n = n - stride end subroutine #:endfor !! version: experimental !! !! Transform COO matrix to canonical form with ordered and unique entries !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion) subroutine coo2ordered(COO,sort_data) class(COO_type), intent(inout) :: COO logical, intent(in), optional :: sort_data integer(ilp), allocatable :: itemp(:,:) logical :: sort_data_ if(COO%is_sorted) return sort_data_ = .false. if(present(sort_data)) sort_data_ = sort_data select type (COO) type is( COO_type ) call sort_coo(COO%index, COO%nnz, COO%nrows, COO%ncols) #:for k1, t1, s1 in (KINDS_TYPES) type is( COO_${s1}$_type ) block ${t1}$, allocatable :: temp(:) if( sort_data_ ) then call sort_coo(COO%index, COO%data, COO%nnz, COO%nrows, COO%ncols) allocate( temp(COO%nnz) , source=COO%data(1:COO%nnz) ) else call sort_coo(COO%index, COO%nnz, COO%nrows, COO%ncols) allocate( temp(COO%nnz) ) end if call move_alloc( temp , COO%data ) end block #:endfor end select allocate( itemp(2,COO%nnz) , source=COO%index(1:2,1:COO%nnz) ) call move_alloc( itemp , COO%index ) COO%is_sorted = .true. end subroutine subroutine coo_from_ijv_type(COO,row,col,nrows,ncols) type(COO_type), intent(inout) :: COO integer(ilp), intent(in) :: row(:) integer(ilp), intent(in) :: col(:) integer(ilp), intent(in), optional :: nrows integer(ilp), intent(in), optional :: ncols integer(ilp) :: nrows_, ncols_, nnz, ed !--------------------------------------------------------- if(present(nrows)) then nrows_ = nrows else nrows_ = size(row) end if if(present(ncols)) then ncols_ = ncols else ncols_ = size(col) end if nnz = size(row) !--------------------------------------------------------- call COO%malloc(nrows_,ncols_,nnz) do ed = 1, nnz COO%index(1:2,ed) = [row(ed),col(ed)] end do call coo2ordered(COO,.true.) end subroutine #:for k1, t1, s1 in (KINDS_TYPES) subroutine coo_from_ijv_${s1}$(COO,row,col,data,nrows,ncols) type(COO_${s1}$_type), intent(inout) :: COO integer(ilp), intent(in) :: row(:) integer(ilp), intent(in) :: col(:) ${t1}$, intent(in), optional :: data(:) integer(ilp), intent(in), optional :: nrows integer(ilp), intent(in), optional :: ncols integer(ilp) :: nrows_, ncols_, nnz, ed !--------------------------------------------------------- if(present(nrows)) then nrows_ = nrows else nrows_ = maxval(row) end if if(present(ncols)) then ncols_ = ncols else ncols_ = maxval(col) end if nnz = size(row) !--------------------------------------------------------- call COO%malloc(nrows_,ncols_,nnz) do ed = 1, nnz COO%index(1:2,ed) = [row(ed),col(ed)] end do if(present(data)) COO%data = data call coo2ordered(COO,.true.) end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine csr_from_ijv_${s1}$(CSR,row,col,data,nrows,ncols) type(CSR_${s1}$_type), intent(inout) :: CSR integer(ilp), intent(in) :: row(:) integer(ilp), intent(in) :: col(:) ${t1}$, intent(in), optional :: data(:) integer(ilp), intent(in), optional :: nrows integer(ilp), intent(in), optional :: ncols integer(ilp) :: nrows_, ncols_ !--------------------------------------------------------- if(present(nrows)) then nrows_ = nrows else nrows_ = maxval(row) end if if(present(ncols)) then ncols_ = ncols else ncols_ = maxval(col) end if !--------------------------------------------------------- block type(COO_${s1}$_type) :: COO if(present(data)) then call from_ijv(COO,row,col,data=data,nrows=nrows_,ncols=ncols_) else call from_ijv(COO,row,col,nrows=nrows_,ncols=ncols_) end if call coo2csr(COO,CSR) end block end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine ell_from_ijv_${s1}$(ELL,row,col,data,nrows,ncols,num_nz_rows) type(ELL_${s1}$_type), intent(inout) :: ELL integer(ilp), intent(in) :: row(:) integer(ilp), intent(in) :: col(:) ${t1}$, intent(in), optional :: data(:) integer(ilp), intent(in), optional :: nrows integer(ilp), intent(in), optional :: ncols integer, intent(in), optional :: num_nz_rows integer(ilp) :: nrows_, ncols_ !--------------------------------------------------------- if(present(nrows)) then nrows_ = nrows else nrows_ = maxval(row) end if if(present(ncols)) then ncols_ = ncols else ncols_ = maxval(col) end if !--------------------------------------------------------- block type(COO_${s1}$_type) :: COO type(CSR_${s1}$_type) :: CSR if(present(data)) then call from_ijv(COO,row,col,data=data,nrows=nrows_,ncols=ncols_) else call from_ijv(COO,row,col,nrows=nrows_,ncols=ncols_) end if call coo2csr(COO,CSR) if(present(num_nz_rows)) then call csr2ell(CSR,ELL,num_nz_rows) else call csr2ell(CSR,ELL) end if end block end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine sellc_from_ijv_${s1}$(SELLC,row,col,data,nrows,ncols,chunk) type(SELLC_${s1}$_type), intent(inout) :: SELLC integer(ilp), intent(in) :: row(:) integer(ilp), intent(in) :: col(:) ${t1}$, intent(in), optional :: data(:) integer(ilp), intent(in), optional :: nrows integer(ilp), intent(in), optional :: ncols integer, intent(in), optional :: chunk integer(ilp) :: nrows_, ncols_ !--------------------------------------------------------- if(present(nrows)) then nrows_ = nrows else nrows_ = maxval(row) end if if(present(ncols)) then ncols_ = ncols else ncols_ = maxval(col) end if if(present(chunk)) SELLC%chunk_size = chunk !--------------------------------------------------------- block type(COO_${s1}$_type) :: COO type(CSR_${s1}$_type) :: CSR if(present(data)) then call from_ijv(COO,row,col,data=data,nrows=nrows_,ncols=ncols_) else call from_ijv(COO,row,col,nrows=nrows_,ncols=ncols_) end if call coo2csr(COO,CSR) call csr2sellc(CSR,SELLC) end block end subroutine #:endfor !! Diagonal extraction #:for k1, t1, s1 in (KINDS_TYPES) subroutine dense2diagonal_${s1}$(dense,diagonal) ${t1}$, intent(in) :: dense(:,:) ${t1}$, intent(inout), allocatable :: diagonal(:) integer :: num_rows integer :: i num_rows = size(dense,dim=1) if(.not.allocated(diagonal)) allocate(diagonal(num_rows)) do i = 1, num_rows diagonal(i) = dense(i,i) end do end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine coo2diagonal_${s1}$(COO,diagonal) type(COO_${s1}$_type), intent(in) :: COO ${t1}$, intent(inout), allocatable :: diagonal(:) integer :: idx if(.not.allocated(diagonal)) allocate(diagonal(COO%nrows)) do concurrent(idx = 1:COO%nnz) if(COO%index(1,idx)==COO%index(2,idx)) & & diagonal( COO%index(1,idx) ) = COO%data(idx) end do end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine csr2diagonal_${s1}$(CSR,diagonal) type(CSR_${s1}$_type), intent(in) :: CSR ${t1}$, intent(inout), allocatable :: diagonal(:) integer :: i, j if(.not.allocated(diagonal)) allocate(diagonal(CSR%nrows)) select case(CSR%storage) case(sparse_lower) do i = 1, CSR%nrows diagonal(i) = CSR%data( CSR%rowptr(i+1)-1 ) end do case(sparse_upper) do i = 1, CSR%nrows diagonal(i) = CSR%data( CSR%rowptr(i) ) end do case(sparse_full) do i = 1, CSR%nrows do j = CSR%rowptr(i), CSR%rowptr(i+1)-1 if( CSR%col(j) == i ) then diagonal(i) = CSR%data(j) exit end if end do end do end select end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine csc2diagonal_${s1}$(CSC,diagonal) type(CSC_${s1}$_type), intent(in) :: CSC ${t1}$, intent(inout), allocatable :: diagonal(:) integer :: i, j if(.not.allocated(diagonal)) allocate(diagonal(CSC%nrows)) select case(CSC%storage) case(sparse_lower) do i = 1, CSC%ncols diagonal(i) = CSC%data( CSC%colptr(i+1)-1 ) end do case(sparse_upper) do i = 1, CSC%ncols diagonal(i) = CSC%data( CSC%colptr(i) ) end do case(sparse_full) do i = 1, CSC%ncols do j = CSC%colptr(i), CSC%colptr(i+1)-1 if( CSC%row(j) == i ) then diagonal(i) = CSC%data(j) exit end if end do end do end select end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) subroutine ell2diagonal_${s1}$(ELL,diagonal) type(ELL_${s1}$_type), intent(in) :: ELL ${t1}$, intent(inout), allocatable :: diagonal(:) integer :: i, k if(.not.allocated(diagonal)) allocate(diagonal(ELL%nrows)) if( ELL%storage == sparse_full) then do i = 1, ELL%nrows do k = 1, ELL%K if(ELL%index(i,k)==i) diagonal(i) = ELL%data(i,k) end do end do end if end subroutine #:endfor end modulefortran-lang-stdlib-0ede301/src/sparse/stdlib_sparse_kinds.fypp0000664000175000017500000005206015135654166025203 0ustar alastairalastair#:include "common.fypp" #:set RANKS = range(1, 2+1) #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set KINDS_TYPES = R_KINDS_TYPES+C_KINDS_TYPES !! The `stdlib_sparse_kinds` module provides derived type definitions for different sparse matrices !! ! This code was modified from https://github.com/jalvesz/FSPARSE by its author: Alves Jose module stdlib_sparse_kinds use ieee_arithmetic use stdlib_sparse_constants implicit none private public :: sparse_full, sparse_lower, sparse_upper public :: sparse_op_none, sparse_op_transpose, sparse_op_hermitian !! version: experimental !! !! Base sparse type holding the meta data related to the storage capacity of a matrix. type, public, abstract :: sparse_type integer(ilp) :: nrows = 0 !! number of rows integer(ilp) :: ncols = 0 !! number of columns integer(ilp) :: nnz = 0 !! number of non-zero values integer :: storage = sparse_full !! assumed storage symmetry end type !! version: experimental !! !! COO: COOrdinates compresed format type, public, extends(sparse_type) :: COO_type logical :: is_sorted = .false. !! whether the matrix is sorted or not integer(ilp), allocatable :: index(:,:) !! Matrix coordinates index(2,nnz) contains procedure :: malloc => malloc_coo end type #:for k1, t1, s1 in (KINDS_TYPES) type, public, extends(COO_type) :: COO_${s1}$_type ${t1}$, allocatable :: data(:) contains procedure, non_overridable :: at => at_value_coo_${s1}$ procedure, non_overridable :: add_value => add_value_coo_${s1}$ procedure, non_overridable :: add_block => add_block_coo_${s1}$ generic :: add => add_value, add_block end type #:endfor !! version: experimental !! !! CSR: Compressed sparse row or Yale format type, public, extends(sparse_type) :: CSR_type integer(ilp), allocatable :: col(:) !! matrix column pointer integer(ilp), allocatable :: rowptr(:) !! matrix row pointer contains procedure :: malloc => malloc_csr end type #:for k1, t1, s1 in (KINDS_TYPES) type, public, extends(CSR_type) :: CSR_${s1}$_type ${t1}$, allocatable :: data(:) contains procedure, non_overridable :: at => at_value_csr_${s1}$ procedure, non_overridable :: add_value => add_value_csr_${s1}$ procedure, non_overridable :: add_block => add_block_csr_${s1}$ generic :: add => add_value, add_block end type #:endfor !! version: experimental !! !! CSC: Compressed sparse column type, public, extends(sparse_type) :: CSC_type integer(ilp), allocatable :: colptr(:) !! matrix column pointer integer(ilp), allocatable :: row(:) !! matrix row pointer contains procedure :: malloc => malloc_csc end type #:for k1, t1, s1 in (KINDS_TYPES) type, public, extends(CSC_type) :: CSC_${s1}$_type ${t1}$, allocatable :: data(:) contains procedure, non_overridable :: at => at_value_csc_${s1}$ procedure, non_overridable :: add_value => add_value_csc_${s1}$ procedure, non_overridable :: add_block => add_block_csc_${s1}$ generic :: add => add_value, add_block end type #:endfor !! version: experimental !! !! Compressed ELLPACK type, public, extends(sparse_type) :: ELL_type integer :: K = 0 !! maximum number of nonzeros per row integer(ilp), allocatable :: index(:,:) !! column indices contains procedure :: malloc => malloc_ell end type #:for k1, t1, s1 in (KINDS_TYPES) type, public, extends(ELL_type) :: ELL_${s1}$_type ${t1}$, allocatable :: data(:,:) contains procedure, non_overridable :: at => at_value_ell_${s1}$ procedure, non_overridable :: add_value => add_value_ell_${s1}$ procedure, non_overridable :: add_block => add_block_ell_${s1}$ generic :: add => add_value, add_block end type #:endfor !! version: experimental !! !! Compressed SELL-C !! Reference : https://library.eecs.utk.edu/storage/files/ut-eecs-14-727.pdf type, public, extends(sparse_type) :: SELLC_type integer :: chunk_size = 8 !! default chunk size integer(ilp), allocatable :: rowptr(:) !! row pointer integer(ilp), allocatable :: col(:,:) !! column indices end type #:for k1, t1, s1 in (KINDS_TYPES) type, public, extends(SELLC_type) :: SELLC_${s1}$_type ${t1}$, allocatable :: data(:,:) contains procedure, non_overridable :: at => at_value_sellc_${s1}$ procedure, non_overridable :: add_value => add_value_sellc_${s1}$ procedure, non_overridable :: add_block => add_block_sellc_${s1}$ generic :: add => add_value, add_block end type #:endfor contains !! (re)Allocate matrix memory for the COO type subroutine malloc_coo(self,num_rows,num_cols,nnz) class(COO_type) :: self integer(ilp), intent(in) :: num_rows !! number of rows integer(ilp), intent(in) :: num_cols !! number of columns integer(ilp), intent(in) :: nnz !! number of non zeros integer(ilp), allocatable :: temp_idx(:,:) !----------------------------------------------------- self%nrows = num_rows self%ncols = num_cols self%nnz = nnz if(.not.allocated(self%index)) then allocate(temp_idx(2,nnz) , source = 0 ) else allocate(temp_idx(2,nnz) , source = self%index ) end if call move_alloc(from=temp_idx,to=self%index) select type(self) #:for k1, t1, s1 in (KINDS_TYPES) type is(COO_${s1}$_type) block ${t1}$, allocatable :: temp_data_${s1}$(:) if(.not.allocated(self%data)) then allocate(temp_data_${s1}$(nnz) , source = zero_${s1}$ ) else allocate(temp_data_${s1}$(nnz) , source = self%data ) end if call move_alloc(from=temp_data_${s1}$,to=self%data) end block #:endfor end select end subroutine !! (re)Allocate matrix memory for the CSR type subroutine malloc_csr(self,num_rows,num_cols,nnz) class(CSR_type) :: self integer(ilp), intent(in) :: num_rows !! number of rows integer(ilp), intent(in) :: num_cols !! number of columns integer(ilp), intent(in) :: nnz !! number of non zeros integer(ilp), allocatable :: temp_idx(:) !----------------------------------------------------- self%nrows = num_rows self%ncols = num_cols self%nnz = nnz if(.not.allocated(self%col)) then allocate(temp_idx(nnz) , source = 0 ) else allocate(temp_idx(nnz) , source = self%col ) end if call move_alloc(from=temp_idx,to=self%col) if(.not.allocated(self%rowptr)) then allocate(temp_idx(num_rows+1) , source = 0 ) else allocate(temp_idx(num_rows+1) , source = self%rowptr ) end if call move_alloc(from=temp_idx,to=self%rowptr) select type(self) #:for k1, t1, s1 in (KINDS_TYPES) type is(CSR_${s1}$_type) block ${t1}$, allocatable :: temp_data_${s1}$(:) if(.not.allocated(self%data)) then allocate(temp_data_${s1}$(nnz) , source = zero_${s1}$ ) else allocate(temp_data_${s1}$(nnz) , source = self%data ) end if call move_alloc(from=temp_data_${s1}$,to=self%data) end block #:endfor end select end subroutine !! (re)Allocate matrix memory for the CSC type subroutine malloc_csc(self,num_rows,num_cols,nnz) class(CSC_type) :: self integer(ilp), intent(in) :: num_rows !! number of rows integer(ilp), intent(in) :: num_cols !! number of columns integer(ilp), intent(in) :: nnz !! number of non zeros integer(ilp), allocatable :: temp_idx(:) !----------------------------------------------------- self%nrows = num_rows self%ncols = num_cols self%nnz = nnz if(.not.allocated(self%row)) then allocate(temp_idx(nnz) , source = 0 ) else allocate(temp_idx(nnz) , source = self%row ) end if call move_alloc(from=temp_idx,to=self%row) if(.not.allocated(self%colptr)) then allocate(temp_idx(num_cols+1) , source = 0 ) else allocate(temp_idx(num_cols+1) , source = self%colptr ) end if call move_alloc(from=temp_idx,to=self%colptr) select type(self) #:for k1, t1, s1 in (KINDS_TYPES) type is(CSC_${s1}$_type) block ${t1}$, allocatable :: temp_data_${s1}$(:) if(.not.allocated(self%data)) then allocate(temp_data_${s1}$(nnz) , source = zero_${s1}$ ) else allocate(temp_data_${s1}$(nnz) , source = self%data ) end if call move_alloc(from=temp_data_${s1}$,to=self%data) end block #:endfor end select end subroutine !! (re)Allocate matrix memory for the ELLPACK type subroutine malloc_ell(self,num_rows,num_cols,num_nz_rows) class(ELL_type) :: self integer(ilp), intent(in) :: num_rows !! number of rows integer(ilp), intent(in) :: num_cols !! number of columns integer(ilp), intent(in) :: num_nz_rows !! number of non zeros per row integer(ilp), allocatable :: temp_idx(:,:) !----------------------------------------------------- self%nrows = num_rows self%ncols = num_cols self%K = num_nz_rows if(.not.allocated(self%index)) then allocate(temp_idx(num_rows,num_nz_rows) , source = 0 ) else allocate(temp_idx(num_rows,num_nz_rows) , source = self%index ) end if call move_alloc(from=temp_idx,to=self%index) select type(self) #:for k1, t1, s1 in (KINDS_TYPES) type is(ELL_${s1}$_type) block ${t1}$, allocatable :: temp_data_${s1}$(:,:) if(.not.allocated(self%data)) then allocate(temp_data_${s1}$(num_rows,num_nz_rows) , source = zero_${s1}$ ) else allocate(temp_data_${s1}$(num_rows,num_nz_rows) , source = self%data ) end if call move_alloc(from=temp_data_${s1}$,to=self%data) end block #:endfor end select end subroutine !================================================================== ! data accessors !================================================================== #:for k1, t1, s1 in (KINDS_TYPES) pure ${t1}$ function at_value_coo_${s1}$(self,ik,jk) result(val) class(COO_${s1}$_type), intent(in) :: self integer(ilp), intent(in) :: ik, jk integer(ilp) :: k, ik_, jk_ logical :: transpose ! naive implementation if( (ik<1 .or. ik>self%nrows) .or. (jk<1 .or. jk>self%ncols) ) then val = ieee_value( 0._${k1}$ , ieee_quiet_nan) return end if ik_ = ik; jk_ = jk transpose = (self%storage == sparse_lower .and. ik > jk) .or. (self%storage == sparse_upper .and. ik < jk) if(transpose) then ! allow extraction of symmetric elements ik_ = jk; jk_ = ik end if do k = 1, self%nnz if( ik_ == self%index(1,k) .and. jk_ == self%index(2,k) ) then val = self%data(k) return end if end do val = zero_${s1}$ end function subroutine add_value_coo_${s1}$(self,ik,jk,val) class(COO_${s1}$_type), intent(inout) :: self ${t1}$, intent(in) :: val integer(ilp), intent(in) :: ik, jk integer(ilp) :: k ! naive implementation do k = 1,self%nnz if( ik == self%index(1,k) .and. jk == self%index(2,k) ) then self%data(k) = self%data(k) + val return end if end do end subroutine subroutine add_block_coo_${s1}$(self,ik,jk,val) class(COO_${s1}$_type), intent(inout) :: self ${t1}$, intent(in) :: val(:,:) integer(ilp), intent(in) :: ik(:), jk(:) integer(ilp) :: k, i, j ! naive implementation do k = 1, self%nnz do i = 1, size(ik) if( ik(i) /= self%index(1,k) ) cycle do j = 1, size(jk) if( jk(j) /= self%index(2,k) ) cycle self%data(k) = self%data(k) + val(i,j) end do end do end do end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) pure ${t1}$ function at_value_csr_${s1}$(self,ik,jk) result(val) class(CSR_${s1}$_type), intent(in) :: self integer(ilp), intent(in) :: ik, jk integer(ilp) :: k, ik_, jk_ logical :: transpose ! naive implementation if( (ik<1 .or. ik>self%nrows) .or. (jk<1 .or. jk>self%ncols) ) then val = ieee_value( 0._${k1}$ , ieee_quiet_nan) return end if ik_ = ik; jk_ = jk transpose = (self%storage == sparse_lower .and. ik > jk) .or. (self%storage == sparse_upper .and. ik < jk) if(transpose) then ! allow extraction of symmetric elements ik_ = jk; jk_ = ik end if do k = self%rowptr(ik_), self%rowptr(ik_+1)-1 if( jk_ == self%col(k) ) then val = self%data(k) return end if end do val = zero_${s1}$ end function subroutine add_value_csr_${s1}$(self,ik,jk,val) class(CSR_${s1}$_type), intent(inout) :: self ${t1}$, intent(in) :: val integer(ilp), intent(in) :: ik, jk integer(ilp) :: k ! naive implementation do k = self%rowptr(ik), self%rowptr(ik+1)-1 if( jk == self%col(k) ) then self%data(k) = self%data(k) + val return end if end do end subroutine subroutine add_block_csr_${s1}$(self,ik,jk,val) class(CSR_${s1}$_type), intent(inout) :: self ${t1}$, intent(in) :: val(:,:) integer(ilp), intent(in) :: ik(:), jk(:) integer(ilp) :: k, i, j ! naive implementation do i = 1, size(ik) do k = self%rowptr(ik(i)), self%rowptr(ik(i)+1)-1 do j = 1, size(jk) if( jk(j) == self%col(k) ) then self%data(k) = self%data(k) + val(i,j) end if end do end do end do end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) pure ${t1}$ function at_value_csc_${s1}$(self,ik,jk) result(val) class(CSC_${s1}$_type), intent(in) :: self integer(ilp), intent(in) :: ik, jk integer(ilp) :: k, ik_, jk_ logical :: transpose ! naive implementation if( (ik<1 .or. ik>self%nrows) .or. (jk<1 .or. jk>self%ncols) ) then val = ieee_value( 0._${k1}$ , ieee_quiet_nan) return end if ik_ = ik; jk_ = jk transpose = (self%storage == sparse_lower .and. ik > jk) .or. (self%storage == sparse_upper .and. ik < jk) if(transpose) then ! allow extraction of symmetric elements ik_ = jk; jk_ = ik end if do k = self%colptr(jk_), self%colptr(jk_+1)-1 if( ik_ == self%row(k) ) then val = self%data(k) return end if end do val = zero_${s1}$ end function subroutine add_value_csc_${s1}$(self,ik,jk,val) class(CSC_${s1}$_type), intent(inout) :: self ${t1}$, intent(in) :: val integer(ilp), intent(in) :: ik, jk integer(ilp) :: k ! naive implementation do k = self%colptr(jk), self%colptr(jk+1)-1 if( ik == self%row(k) ) then self%data(k) = self%data(k) + val return end if end do end subroutine subroutine add_block_csc_${s1}$(self,ik,jk,val) class(CSC_${s1}$_type), intent(inout) :: self ${t1}$, intent(in) :: val(:,:) integer(ilp), intent(in) :: ik(:), jk(:) integer(ilp) :: k, i, j ! naive implementation do j = 1, size(jk) do k = self%colptr(jk(j)), self%colptr(jk(j)+1)-1 do i = 1, size(ik) if( ik(i) == self%row(k) ) then self%data(k) = self%data(k) + val(i,j) end if end do end do end do end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) pure ${t1}$ function at_value_ell_${s1}$(self,ik,jk) result(val) class(ELL_${s1}$_type), intent(in) :: self integer(ilp), intent(in) :: ik, jk integer(ilp) :: k, ik_, jk_ logical :: transpose ! naive implementation if( (ik<1 .or. ik>self%nrows) .or. (jk<1 .or. jk>self%ncols) ) then val = ieee_value( 0._${k1}$ , ieee_quiet_nan) return end if ik_ = ik; jk_ = jk transpose = (self%storage == sparse_lower .and. ik > jk) .or. (self%storage == sparse_upper .and. ik < jk) if(transpose) then ! allow extraction of symmetric elements ik_ = jk; jk_ = ik end if do k = 1 , self%K if( jk_ == self%index(ik_,k) ) then val = self%data(ik_,k) return end if end do val = zero_${s1}$ end function subroutine add_value_ell_${s1}$(self,ik,jk,val) class(ELL_${s1}$_type), intent(inout) :: self ${t1}$, intent(in) :: val integer(ilp), intent(in) :: ik, jk integer(ilp) :: k ! naive implementation do k = 1 , self%K if( jk == self%index(ik,k) ) then self%data(ik,k) = self%data(ik,k) + val return end if end do end subroutine subroutine add_block_ell_${s1}$(self,ik,jk,val) class(ELL_${s1}$_type), intent(inout) :: self ${t1}$, intent(in) :: val(:,:) integer(ilp), intent(in) :: ik(:), jk(:) integer(ilp) :: k, i, j ! naive implementation do k = 1 , self%K do j = 1, size(jk) do i = 1, size(ik) if( jk(j) == self%index(ik(i),k) ) then self%data(ik(i),k) = self%data(ik(i),k) + val(i,j) end if end do end do end do end subroutine #:endfor #:for k1, t1, s1 in (KINDS_TYPES) pure ${t1}$ function at_value_sellc_${s1}$(self,ik,jk) result(val) class(SELLC_${s1}$_type), intent(in) :: self integer(ilp), intent(in) :: ik, jk integer(ilp) :: k, ik_, jk_, idx logical :: transpose ! naive implementation if( (ik<1 .or. ik>self%nrows) .or. (jk<1 .or. jk>self%ncols) ) then val = ieee_value( 0._${k1}$ , ieee_quiet_nan) return end if ik_ = ik; jk_ = jk transpose = (self%storage == sparse_lower .and. ik > jk) .or. (self%storage == sparse_upper .and. ik < jk) if(transpose) then ! allow extraction of symmetric elements ik_ = jk; jk_ = ik end if idx = self%rowptr((ik_ - 1)/self%chunk_size + 1) do k = 1, self%chunk_size if ( jk_ == self%col(k,idx) )then val = self%data(k,idx) return endif end do val = zero_${s1}$ end function subroutine add_value_sellc_${s1}$(self,ik,jk,val) class(SELLC_${s1}$_type), intent(inout) :: self ${t1}$, intent(in) :: val integer(ilp), intent(in) :: ik, jk integer(ilp) :: k, idx ! naive implementation idx = self%rowptr((ik - 1)/self%chunk_size + 1) do k = 1, self%chunk_size if ( jk == self%col(k,idx) )then self%data(k,idx) = self%data(k,idx) + val return endif end do end subroutine subroutine add_block_sellc_${s1}$(self,ik,jk,val) class(SELLC_${s1}$_type), intent(inout) :: self ${t1}$, intent(in) :: val(:,:) integer(ilp), intent(in) :: ik(:), jk(:) integer(ilp) :: k, i, j, idx ! naive implementation do k = 1 , self%chunk_size do j = 1, size(jk) do i = 1, size(ik) idx = self%rowptr((ik(i) - 1)/self%chunk_size + 1) if( jk(j) == self%col(k,idx) ) then self%data(k,idx) = self%data(k,idx) + val(i,j) end if end do end do end do end subroutine #:endfor end module stdlib_sparse_kinds fortran-lang-stdlib-0ede301/src/sparse/stdlib_sparse_constants.fypp0000664000175000017500000000175515135654166026114 0ustar alastairalastair#:include "common.fypp" #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) module stdlib_sparse_constants use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp use stdlib_constants implicit none public enum, bind(C) enumerator :: sparse_full !! Full Sparse matrix (no symmetry considerations) enumerator :: sparse_lower !! Symmetric Sparse matrix with triangular inferior storage enumerator :: sparse_upper !! Symmetric Sparse matrix with triangular supperior storage end enum character(1), parameter :: sparse_op_none = 'N' !! no transpose character(1), parameter :: sparse_op_transpose = 'T' !! transpose character(1), parameter :: sparse_op_hermitian = 'H' !! conjugate or hermitian transpose ! Integer size support for ILP64 builds should be done here integer, parameter :: ilp = int32 end module stdlib_sparse_constants fortran-lang-stdlib-0ede301/src/system/0000775000175000017500000000000015135654166020301 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/system/stdlib_system_path.f900000664000175000017500000001165015135654166024525 0ustar alastairalastairsubmodule(stdlib_system) stdlib_system_path use stdlib_ascii, only: reverse use stdlib_strings, only: chomp, join use stdlib_string_type, only: string_type, char, move contains module function join2_char_char(p1, p2) result(path) character(:), allocatable :: path character(*), intent(in) :: p1, p2 path = trim(p1) // path_sep() // trim(p2) end function join2_char_char module function join2_char_string(p1, p2) result(path) character(:), allocatable :: path character(*), intent(in) :: p1 type(string_type), intent(in) :: p2 path = join_path(p1, char(p2)) end function join2_char_string module function join2_string_char(p1, p2) result(path) type(string_type) :: path type(string_type), intent(in) :: p1 character(*), intent(in) :: p2 character(:), allocatable :: join_char join_char = join_path(char(p1), p2) call move(join_char, path) end function join2_string_char module function join2_string_string(p1, p2) result(path) type(string_type) :: path type(string_type), intent(in) :: p1, p2 character(:), allocatable :: join_char join_char = join_path(char(p1), char(p2)) call move(join_char, path) end function join2_string_string module function joinarr_char(p) result(path) character(:), allocatable :: path character(*), intent(in) :: p(:) path = join(p, path_sep()) end function joinarr_char module function joinarr_string(p) result(path) type(string_type) :: path type(string_type), intent(in) :: p(:) path = join(p, path_sep()) end function joinarr_string module function join_op_char_char(p1, p2) result(path) character(:), allocatable :: path character(*), intent(in) :: p1, p2 path = join_path(p1, p2) end function join_op_char_char module function join_op_char_string(p1, p2) result(path) character(:), allocatable :: path character(*), intent(in) :: p1 type(string_type), intent(in) :: p2 path = join_path(p1, p2) end function join_op_char_string module function join_op_string_char(p1, p2) result(path) type(string_type) :: path type(string_type), intent(in) :: p1 character(*), intent(in) :: p2 path = join_path(p1, p2) end function join_op_string_char module function join_op_string_string(p1, p2) result(path) type(string_type) :: path type(string_type), intent(in) :: p1, p2 path = join_path(p1, p2) end function join_op_string_string module subroutine split_path_char(p, head, tail) character(*), intent(in) :: p character(:), allocatable, intent(out) :: head, tail character(:), allocatable :: temp integer :: i character(len=1) :: sep sep = path_sep() ! Empty string, return (.,'') if (trim(p) == '') then head = '.' tail = '' return end if ! Remove trailing path separators temp = trim(chomp(trim(p), sep)) if (temp == '') then head = sep tail = '' return end if i = find(reverse(temp), sep) ! if no `pathsep`, then it probably was a root dir like `C:\` if (i == 0) then head = temp // sep tail = '' return end if head = temp(:len(temp)-i) ! child of a root directory if (find(head, sep) == 0) then head = head // sep end if tail = temp(len(temp)-i+2:) end subroutine split_path_char module subroutine split_path_string(p, head, tail) type(string_type), intent(in) :: p type(string_type), intent(out) :: head, tail character(:), allocatable :: head_char, tail_char call split_path(char(p), head_char, tail_char) call move(head_char, head) call move(tail_char, tail) end subroutine split_path_string module function base_name_char(p) result(base) character(:), allocatable :: base, temp character(*), intent(in) :: p call split_path(p, temp, base) end function base_name_char module function base_name_string(p) result(base) type(string_type) :: base type(string_type), intent(in) :: p type(string_type) :: temp call split_path(p, temp, base) end function base_name_string module function dir_name_char(p) result(dir) character(:), allocatable :: dir, temp character(*), intent(in) :: p call split_path(p, dir, temp) end function dir_name_char module function dir_name_string(p) result(dir) type(string_type) :: dir type(string_type), intent(in) :: p type(string_type) :: temp call split_path(p, dir, temp) end function dir_name_string end submodule stdlib_system_path fortran-lang-stdlib-0ede301/src/system/stdlib_system_subprocess.F900000664000175000017500000007103715135654166025726 0ustar alastairalastairsubmodule (stdlib_system) stdlib_system_subprocess use iso_c_binding use iso_fortran_env, only: int64, real64 use stdlib_strings, only: join use stdlib_linalg_state, only: linalg_state_type, LINALG_ERROR, linalg_error_handling implicit none(type, external) ! Number of CPU ticks between status updates integer(TICKS), parameter :: CHECK_EVERY_TICKS = 100 ! Interface to C support functions from stdlib_system_subprocess.c interface ! C wrapper to query process status subroutine process_query_status(pid, wait, is_running, exit_code) & bind(C, name='process_query_status') import c_int, c_bool, process_ID implicit none ! Process ID integer(process_ID), value :: pid ! Whether to wait for process completion logical(c_bool), value :: wait ! Whether the process is still running logical(c_bool), intent(out) :: is_running ! Process exit code (or error code) integer(c_int), intent(out) :: exit_code end subroutine process_query_status subroutine process_create(cmd, stdin_stream, stdin_file, stdout_file, stderr_file, pid) & bind(C, name='process_create') import c_char, process_ID implicit none character(c_char), intent(in) :: cmd(*) character(c_char), intent(in), optional :: stdin_stream(*) character(c_char), intent(in), optional :: stdin_file(*) character(c_char), intent(in), optional :: stdout_file(*) character(c_char), intent(in), optional :: stderr_file(*) integer(process_ID), intent(out) :: pid end subroutine process_create logical(c_bool) function process_system_kill(pid) bind(C, name='process_kill') import c_bool, process_ID implicit none integer(process_ID), intent(in), value :: pid end function process_system_kill ! System implementation of a wait function subroutine process_wait(seconds) bind(C,name='process_wait') import c_float implicit none real(c_float), intent(in), value :: seconds end subroutine process_wait ! Utility: check if _WIN32 is defined in the C compiler logical(c_bool) function process_is_windows() bind(C,name='process_is_windows') import c_bool implicit none end function process_is_windows end interface ! C boolean constants logical(c_bool), parameter :: C_FALSE = .false._c_bool logical(c_bool), parameter :: C_TRUE = .true._c_bool contains ! Call system-dependent wait implementation module subroutine sleep(millisec) integer, intent(in) :: millisec real(c_float) :: seconds seconds = 0.001_c_float*max(0,millisec) call process_wait(seconds) end subroutine sleep module function run_async_cmd(cmd, stdin, want_stdout, want_stderr, callback, payload) result(process) !> The command line string to execute. character(*), intent(in) :: cmd !> Optional input sent to the process via standard input (stdin). character(*), optional, intent(in) :: stdin !> Whether to collect standard output. logical, optional, intent(in) :: want_stdout !> Whether to collect standard error output. logical, optional, intent(in) :: want_stderr !> Optional callback function to be called on process completion procedure(process_callback), optional :: callback !> Optional payload to pass to the callback on completion class(*), optional, intent(inout), target :: payload !> The output process handler. type(process_type) :: process process = process_open([cmd],.false.,stdin,want_stdout,want_stderr,callback,payload) end function run_async_cmd module function run_async_args(args, stdin, want_stdout, want_stderr, callback, payload) result(process) !> List of arguments for the process to execute. character(*), intent(in) :: args(:) !> Optional input sent to the process via standard input (stdin). character(*), optional, intent(in) :: stdin !> Whether to collect standard output. logical, optional, intent(in) :: want_stdout !> Whether to collect standard error output. logical, optional, intent(in) :: want_stderr !> Optional callback function to be called on process completion procedure(process_callback), optional :: callback !> Optional payload to pass to the callback on completion class(*), optional, intent(inout), target :: payload !> The output process handler. type(process_type) :: process process = process_open(args,.false.,stdin,want_stdout,want_stderr,callback,payload) end function run_async_args module function run_sync_cmd(cmd, stdin, want_stdout, want_stderr, callback, payload) result(process) !> The command line string to execute. character(*), intent(in) :: cmd !> Optional input sent to the process via standard input (stdin). character(*), optional, intent(in) :: stdin !> Whether to collect standard output. logical, optional, intent(in) :: want_stdout !> Whether to collect standard error output. logical, optional, intent(in) :: want_stderr !> Optional callback function to be called on process completion procedure(process_callback), optional :: callback !> Optional payload to pass to the callback on completion class(*), optional, intent(inout), target :: payload !> The output process handler. type(process_type) :: process process = process_open([cmd],.true.,stdin,want_stdout,want_stderr,callback,payload) end function run_sync_cmd module function run_sync_args(args, stdin, want_stdout, want_stderr, callback, payload) result(process) !> List of arguments for the process to execute. character(*), intent(in) :: args(:) !> Optional input sent to the process via standard input (stdin). character(*), optional, intent(in) :: stdin !> Whether to collect standard output. logical, optional, intent(in) :: want_stdout !> Whether to collect standard error output. logical, optional, intent(in) :: want_stderr !> Optional callback function to be called on process completion procedure(process_callback), optional :: callback !> Optional payload to pass to the callback on completion class(*), optional, intent(inout), target :: payload !> The output process handler. type(process_type) :: process process = process_open(args,.true.,stdin,want_stdout,want_stderr,callback,payload) end function run_sync_args !> Internal function: open a new process from a command line function process_open_cmd(cmd,wait,stdin,want_stdout,want_stderr,callback,payload) result(process) !> The command and arguments character(*), intent(in) :: cmd !> Optional character input to be sent to the process via pipe character(*), optional, intent(in) :: stdin !> Define if the process should be synchronous (wait=.true.), or asynchronous(wait=.false.) logical, intent(in) :: wait !> Require collecting output logical, optional, intent(in) :: want_stdout, want_stderr !> Optional callback function to be called on process completion procedure(process_callback), optional :: callback !> Optional payload to pass to the callback on completion class(*), optional, intent(inout), target :: payload !> The output process handler type(process_type) :: process process = process_open([cmd],wait,stdin,want_stdout,want_stderr,callback,payload) end function process_open_cmd !> Internal function: open a new process from arguments function process_open(args,wait,stdin,want_stdout,want_stderr,callback,payload) result(process) !> The command and arguments character(*), intent(in) :: args(:) !> Optional character input to be sent to the process via pipe character(*), optional, intent(in) :: stdin !> Define if the process should be synchronous (wait=.true.), or asynchronous(wait=.false.) logical, intent(in) :: wait !> Require collecting output logical, optional, intent(in) :: want_stdout, want_stderr !> Optional callback function to be called on process completion procedure(process_callback), optional :: callback !> Optional payload to pass to the callback on completion class(*), optional, intent(inout), target :: payload !> The output process handler type(process_type) :: process real(RTICKS) :: count_rate logical :: asynchronous, collect_stdout, collect_stderr, has_stdin integer :: command_state, exit_state integer(TICKS) :: count_max ! Process user requests asynchronous = .not.wait collect_stdout = .false. collect_stderr = .false. has_stdin = present(stdin) if (present(want_stdout)) collect_stdout = want_stdout if (present(want_stderr)) collect_stderr = want_stderr ! Attach stdout to a scratch file (must be named) if (has_stdin) process%stdin_file = scratch_name('inp') if (collect_stdout) process%stdout_file = scratch_name('out') if (collect_stderr) process%stderr_file = scratch_name('err') ! Attach callback function and payload if (present(callback)) then process%oncomplete => callback else nullify(process%oncomplete) end if if (present(payload)) then process%payload => payload else nullify(process%payload) end if ! Save the process's generation time call system_clock(process%start_time,count_rate,count_max) process%last_update = process%start_time if (asynchronous) then ! Create or fork a new process, store pid call launch_asynchronous(process, args, stdin) else ! No need to create an external process process%id = FORKED_PROCESS endif if (process%id == FORKED_PROCESS) then ! Launch to completion from the local process call launch_synchronous(process, args, stdin) call save_completed_state(process,delete_files=.not.asynchronous) ! If the process was forked ! Note: use `exit` rather than `stop` to prevent the mandatory stdout STOP message if (asynchronous) then if (command_state/=0) then ! Invalid command: didn't even start call exit(command_state) else ! Return exit state call exit(exit_state) end if endif endif ! Run a first update call update_process_state(process) end function process_open subroutine launch_asynchronous(process, args, stdin) class(process_type), intent(inout) :: process !> The command and arguments character(*), intent(in) :: args(:) !> Optional character input to be sent to the process via pipe character(*), optional, intent(in) :: stdin character(c_char), dimension(:), allocatable, target :: c_cmd,c_stdin,c_stdin_file,c_stdout_file,c_stderr_file ! Assemble C strings c_cmd = to_c_char(join(args)) if (present(stdin)) c_stdin = to_c_char(stdin) if (allocated(process%stdin_file)) c_stdin_file = to_c_char(process%stdin_file) if (allocated(process%stdout_file)) c_stdout_file = to_c_char(process%stdout_file) if (allocated(process%stderr_file)) c_stderr_file = to_c_char(process%stderr_file) ! On Windows, this 1) creates 2) launches an external process from C. ! On unix, this 1) forks an external process call process_create(c_cmd, c_stdin, c_stdin_file, c_stdout_file, c_stderr_file, process%id) end subroutine launch_asynchronous subroutine launch_synchronous(process, args, stdin) class(process_type), intent(inout) :: process !> The command and arguments character(*), intent(in) :: args(:) !> Optional character input to be sent to the process via pipe character(*), optional, intent(in) :: stdin character(:), allocatable :: cmd character(4096) :: iomsg integer :: iostat,estat,cstat,stdin_unit logical :: has_stdin has_stdin = present(stdin) ! Prepare stdin if (has_stdin) then open(newunit=stdin_unit,file=process%stdin_file, & access='stream',action='write',position='rewind', & iostat=iostat,iomsg=iomsg) if (iostat/=0) error stop 'cannot open temporary stdin' write(stdin_unit,iostat=iostat,iomsg=iomsg) stdin if (iostat/=0) error stop trim(iomsg) close(stdin_unit,iostat=iostat,iomsg=iomsg,status='keep') if (iostat/=0) error stop 'cannot close temporary stdin' end if ! Run command cmd = assemble_cmd(args,process%stdin_file,process%stdout_file,process%stderr_file) ! Execute command call execute_command_line(cmd,wait=.true.,exitstat=estat,cmdstat=cstat) ! Save state and output process%exit_code = merge(cstat,estat,cstat/=0) end subroutine launch_synchronous !> Return the current (or total) process lifetime, in seconds real(RTICKS) module function process_lifetime(process) result(delta_t) class(process_type), intent(in) :: process real(RTICKS) :: ticks_per_second integer(TICKS) :: current_time,count_max ! Get current time call system_clock(current_time,ticks_per_second,count_max) if (process%completed) then delta_t = real(process%last_update-process%start_time,RTICKS)/ticks_per_second else delta_t = real(current_time-process%start_time,RTICKS)/ticks_per_second end if end function process_lifetime !> Wait for a process to be completed module subroutine wait_for_completion(process, max_wait_time) class(process_type), intent(inout) :: process ! Optional max wait time in seconds real, optional, intent(in) :: max_wait_time integer :: sleep_interval real(RTICKS) :: wait_time, elapsed integer(TICKS) :: start_time, current_time, count_rate ! Sleep interval ms integer, parameter :: MIN_WAIT_MS = 1 integer, parameter :: MAX_WAIT_MS = 100 ! Starting sleep interval: 1ms sleep_interval = MIN_WAIT_MS ! Determine the wait time if (present(max_wait_time)) then wait_time = max(0.0_RTICKS, max_wait_time) else ! No limit if max_wait_time is not provided wait_time = huge(wait_time) end if ! Get the system clock rate and the start time call system_clock(start_time, count_rate) elapsed = 0.0_real64 ! Wait loop wait_loop: do while (process_is_running(process) .and. elapsed <= wait_time) ! Small sleep to avoid CPU hogging, with exponential backoff (1 ms) ! from 1ms up to 100ms call sleep(millisec=sleep_interval) sleep_interval = min(sleep_interval*2, MAX_WAIT_MS) call system_clock(current_time) elapsed = real(current_time - start_time, RTICKS) / count_rate end do wait_loop end subroutine wait_for_completion !> Update a process's state, and save it to the process variable module subroutine update_process_state(process) class(process_type), intent(inout) :: process real(RTICKS) :: count_rate integer(TICKS) :: count_max,current_time logical(c_bool) :: running integer(c_int) :: exit_code ! If the process has completed, should not be queried again if (process%completed) return ! Save the process's generation time call system_clock(current_time,count_rate,count_max) ! Only trigger an update after at least 100 count units if (abs(real(current_time-process%last_update,RTICKS)) Live check if a process is running logical module function process_is_running(process) result(is_running) class(process_type), intent(inout) :: process ! Each evaluation triggers a state update call update_process_state(process) is_running = .not.process%completed end function process_is_running !> Live check if a process has completed logical module function process_is_completed(process) result(is_completed) class(process_type), intent(inout) :: process ! Each evaluation triggers a state update call update_process_state(process) is_completed = process%completed end function process_is_completed function scratch_name(prefix) result(temp_filename) character(*), optional, intent(in) :: prefix character(:), allocatable :: temp_filename character(len=8) :: date character(len=10) :: time character(len=7) :: rand_str real :: rrand integer :: rand_val ! Get the current date and time call date_and_time(date=date, time=time) ! Generate a random number for additional uniqueness call random_number(rrand) rand_val = nint(rrand * 1e6) ! Scale random number write(rand_str,'(i7.7)') rand_val ! Construct the filename if (present(prefix)) then temp_filename = trim(prefix)// '_' // date // '_' // time(1:6) // '_' // rand_str // '.tmp' else temp_filename = 'tmp_' // date // '_' // time(1:6) // '_' // rand_str // '.tmp' endif end function scratch_name !> Assemble a single-line proces command line from a list of arguments. !> !> Version: Helper function. function assemble_cmd(args, stdin, stdout, stderr) result(cmd) !> Command to execute as a string character(len=*), intent(in) :: args(:) !> [optional] File name standard input (stdin) should be taken from character(len=*), optional, intent(in) :: stdin !> [optional] File name standard output (stdout) should be directed to character(len=*), optional, intent(in) :: stdout !> [optional] File name error output (stderr) should be directed to character(len=*), optional, intent(in) :: stderr character(:), allocatable :: cmd,stdout_file,input_file,stderr_file if (present(stdin)) then input_file = stdin else input_file = null_device() end if if (present(stdout)) then ! Redirect output to a file stdout_file = stdout else stdout_file = null_device() endif if (present(stderr)) then stderr_file = stderr else stderr_file = null_device() end if cmd = join(args)//" <"//input_file//" 1>"//stdout_file//" 2>"//stderr_file end function assemble_cmd !> Returns the file path of the null device for the current operating system. !> !> Version: Helper function. logical module function is_windows() is_windows = logical(process_is_windows()) end function is_windows !> Reads a whole ASCII file and loads its contents into an allocatable character string.. !> The function handles error states and optionally deletes the file after reading. !> Temporarily uses `linalg_state_type` in lieu of the generalized `state_type`. !> !> Version: to be replaced after `getfile` is standardized in `stdlib_io`. function getfile(fileName,err,delete) result(file) !> Input file name character(*), intent(in) :: fileName !> [optional] State return flag. On error, if not requested, the code will stop. type(linalg_state_type), optional, intent(out) :: err !> [optional] Delete file after reading? Default: do not delete logical, optional, intent(in) :: delete !> Return as an allocatable string character(:), allocatable :: file ! Local variables character(*), parameter :: CRLF = achar(13)//new_line('a') type(linalg_state_type) :: err0 character(len=:), allocatable :: fileString character(len=512) :: iomsg character :: last_char integer :: lun,iostat integer(int64) :: errpos,fileSize logical :: is_present,want_deleted ! Initializations file = "" !> Check if the file should be deleted after reading if (present(delete)) then want_deleted = delete else want_deleted = .false. end if !> Check file existing inquire(file=fileName, exist=is_present) if (.not.is_present) then err0 = linalg_state_type('getfile',LINALG_ERROR,'File not present:',fileName) call linalg_error_handling(err0,err) return end if !> Retrieve file size inquire(file=fileName,size=fileSize) invalid_size: if (fileSize<0) then err0 = linalg_state_type('getfile',LINALG_ERROR,fileName,'has invalid size=',fileSize) call linalg_error_handling(err0,err) return endif invalid_size ! Read file open(newunit=lun,file=fileName, & form='unformatted',action='read',access='stream',status='old', & iostat=iostat,iomsg=iomsg) if (iostat/=0) then err0 = linalg_state_type('getfile',LINALG_ERROR,'Cannot open',fileName,'for read:',iomsg) call linalg_error_handling(err0,err) return end if remove_trailing_newline: if (fileSize>0) then last_char = CRLF(1:1) fileSize = fileSize+1 do while (scan(last_char,CRLF)>0 .and. fileSize>1) fileSize = fileSize-1 read(lun, pos=fileSize, iostat=iostat, iomsg=iomsg) last_char ! Read error if (iostat/=0) then err0 = linalg_state_type('getfile',LINALG_ERROR,iomsg,'(',fileName,'at byte',fileSize,')') call linalg_error_handling(err0,err) return endif end do endif remove_trailing_newline allocate(character(len=fileSize) :: fileString) read_data: if (fileSize>0) then read(lun, pos=1, iostat=iostat, iomsg=iomsg) fileString ! Read error if (iostat/=0) then inquire(unit=lun,pos=errpos) err0 = linalg_state_type('getfile',LINALG_ERROR,iomsg,'(',fileName,'at byte',errpos,')') call linalg_error_handling(err0,err) return endif end if read_data if (want_deleted) then close(lun,iostat=iostat,status='delete') if (iostat/=0) err0 = linalg_state_type('getfile',LINALG_ERROR,'Cannot delete',fileName,'after reading') else close(lun,iostat=iostat) if (iostat/=0) err0 = linalg_state_type('getfile',LINALG_ERROR,'Cannot close',fileName,'after reading') endif ! Process output call move_alloc(from=fileString,to=file) call linalg_error_handling(err0,err) end function getfile !> Return process ID module function process_get_ID(process) result(ID) class(process_type), intent(in) :: process !> Return a process ID integer(process_ID) :: ID ID = process%id end function process_get_ID end submodule stdlib_system_subprocess fortran-lang-stdlib-0ede301/src/system/stdlib_system.F900000664000175000017500000013616715135654166023464 0ustar alastairalastairmodule stdlib_system use, intrinsic :: iso_c_binding, only : c_int, c_long, c_ptr, c_null_ptr, c_int64_t, c_size_t, & c_f_pointer use stdlib_kinds, only: int64, dp, c_bool, c_char use stdlib_strings, only: to_c_char, find, to_string use stdlib_string_type, only: string_type use stdlib_optval, only: optval use stdlib_error, only: state_type, STDLIB_SUCCESS, STDLIB_FS_ERROR implicit none private public :: sleep !! version: experimental !! !! Cached OS type retrieval with negligible runtime overhead. !! ([Specification](../page/specs/stdlib_system.html#os_type-cached-os-type-retrieval)) !! !! ### Summary !! Provides a cached value for the runtime OS type. !! !! ### Description !! !! This function caches the result of `get_runtime_os` after the first invocation. !! Subsequent calls return the cached value, ensuring minimal overhead. !! public :: OS_TYPE !! version: experimental !! !! Determine the current operating system (OS) type at runtime. !! ([Specification](../page/specs/stdlib_system.html#get_runtime_os-determine-the-os-type-at-runtime)) !! !! ### Summary !! This function inspects the runtime environment to identify the OS type. !! !! ### Description !! !! The function evaluates environment variables (`OSTYPE` or `OS`) and filesystem attributes !! to identify the OS. It distinguishes between several common operating systems: !! - Linux !! - macOS !! - Windows !! - Cygwin !! - Solaris !! - FreeBSD !! - OpenBSD !! !! Returns a constant representing the OS type or `OS_UNKNOWN` if the OS cannot be determined. !! public :: get_runtime_os !> Version: experimental !> !> Integer constants representing known operating system (OS) types !> ([Specification](../page/specs/stdlib_system.html)) integer, parameter, public :: & !> Represents an unknown operating system OS_UNKNOWN = 0, & !> Represents a Linux operating system OS_LINUX = 1, & !> Represents a macOS operating system OS_MACOS = 2, & !> Represents a Windows operating system OS_WINDOWS = 3, & !> Represents a Cygwin environment OS_CYGWIN = 4, & !> Represents a Solaris operating system OS_SOLARIS = 5, & !> Represents a FreeBSD operating system OS_FREEBSD = 6, & !> Represents an OpenBSD operating system OS_OPENBSD = 7 !! Helper function returning the name of an OS parameter public :: OS_NAME !> Public sub-processing interface public :: run public :: runasync public :: process_type public :: is_completed public :: is_running public :: update public :: wait public :: kill public :: elapsed public :: is_windows !! Public path related functions and interfaces public :: path_sep public :: join_path public :: operator(/) public :: split_path public :: base_name public :: dir_name !! version: experimental !! !! Tests if a given path matches an existing directory. !! ([Specification](../page/specs/stdlib_system.html#is_directory-test-if-a-path-is-a-directory)) !! !!### Summary !! Function to evaluate whether a specified path corresponds to an existing directory. !! !!### Description !! !! This function checks if a given file system path is a directory. !! It follows symbolic links to return the status of the `target`. !! !! It is cross-platform and utilizes native system calls. !! It supports common operating systems such as Linux, macOS, Windows, and various UNIX-like environments. !! On unsupported operating systems, the function will return `.false.`. !! public :: is_directory !! version: experimental !! !! Makes an empty directory. !! ([Specification](../page/specs/stdlib_system.html#make_directory)) !! !! ### Summary !! Creates an empty directory with default permissions. !! !! ### Description !! This function makes an empty directory according to the path provided. !! Relative paths are supported. On Windows, paths involving either `/` or `\` are accepted. !! An appropriate error message is returned whenever any error occurs. !! public :: make_directory !! version: experimental !! !! Makes an empty directory, also creating all the parent directories required. !! ([Specification](../page/specs/stdlib_system.html#make_directory)) !! !! ### Summary !! Creates an empty directory with all the parent directories required to do so. !! !! ### Description !! This function makes an empty directory according to the path provided. !! It also creates all the necessary parent directories in the path if they do not exist already. !! Relative paths are supported. !! An appropriate error message is returned whenever any error occurs. !! public :: make_directory_all !! version: experimental !! !! Removes an empty directory. !! ([Specification](../page/specs/stdlib_system.html#remove_directory)) !! !! ### Summary !! Removes an empty directory. !! !! ### Description !! This function Removes an empty directory according to the path provided. !! Relative paths are supported. On Windows paths involving either `/` or `\` are accepted. !! An appropriate error message is returned whenever any error occurs. !! public :: remove_directory !! version: experimental !! !! Gets the current working directory of the process !! ([Specification](../page/specs/stdlib_system.html#get_cwd)) !! !! ### Summary !! Gets the current working directory. !! !! ### Description !! This subroutine gets the current working directory the process is executing from. !! public :: get_cwd !! version: experimental !! !! Sets the current working directory of the process !! ([Specification](../page/specs/stdlib_system.html#set_cwd)) !! !! ### Summary !! Changes the current working directory to the one specified. !! !! ### Description !! This subroutine sets the current working directory the process is executing from. !! public :: set_cwd !! version: experimental !! !! Deletes a specified file from the filesystem. !! ([Specification](../page/specs/stdlib_system.html#delete_file-delete-a-file)) !! !!### Summary !! Subroutine to safely delete a file from the filesystem. It handles errors gracefully using the library's `state_type`. !! !!### Description !! !! This subroutine deletes a specified file. If the file is a directory or inaccessible, an error is raised. !! If the file does not exist, a warning is returned, but no error state. Errors are handled using the !! library's `state_type` mechanism. If the optional `err` argument is not provided, exceptions trigger !! an `error stop`. !! public :: delete_file !! version: experimental !! !! Returns the file path of the null device, which discards all data written to it. !! ([Specification](../page/specs/stdlib_system.html#null_device-return-the-null-device-file-path)) !! !! ### Summary !! Function that provides the file path of the null device appropriate for the current operating system. !! !! ### Description !! !! The null device is a special file that discards all data written to it and always reads as !! an empty file. This function returns the null device path, adapted for the operating system in use. !! !! On Windows, this is `NUL`. On UNIX-like systems, this is `/dev/null`. !! public :: null_device !! version: experimental !! !! A helper function for returning the `type(state_type)` with the flag `STDLIB_FS_ERROR` set. !! ([Specification](../page/specs/stdlib_system.html#FS_ERROR)) !! public :: FS_ERROR !! version: experimental !! !! A helper function for returning the `type(state_type)` with the flag `STDLIB_FS_ERROR` set. !! It also formats and prefixes the `code` passed to it as the first argument !! ([Specification](../page/specs/stdlib_system.html#FS_ERROR_CODE)) !! public :: FS_ERROR_CODE !> Version: experimental !> !> Integer constants representing the most common path types. !> ([Specification](../page/specs/stdlib_system.html)) integer, parameter, public :: & !> Represents an unknown path type fs_type_unknown = 0, & !> Represents a regular file fs_type_regular_file = 1, & !> Represents a directory fs_type_directory = 2, & !> Represents a symbolic link fs_type_symlink = 3 !! version: experimental !! !! Checks if a path exists in the filesystem. !! ([Specification](../page/specs/stdlib_system.html#exists)) !! !!### Summary !! Function to check whether the path exists in the fileystem at all. !! If the path does exist, returns the type of the path. !! !!### Description !! !! This function makes a system call (syscall) to retrieve metadata for the specified path and determines its type. !! It can distinguish between the following path types: !! !! - Regular File !! - Directory !! - Symbolic Link !! !! It does not follow symbolic links. !! !! It returns a constant representing the detected path type, or `type_unknown` if the type cannot be determined. !! Any encountered errors are handled using `state_type`. !! public :: exists !! version: experimental !! !! Tests if a given path is a symbolic link. !! ([Specification](../page/specs/stdlib_system.html#is_symlink)) !! !!### Summary !! Function to evaluate whether a specified path corresponds to a symbolic link. !! !!### Description !! !! This function checks if a given file system path is a symbolic link either to a !! file or a directory. It is cross-platform and utilizes native system calls. !! It supports common operating systems such as Linux, macOS, Windows, and various UNIX-like environments. !! public :: is_symlink !! version: experimental !! !! Tests if a given path is a regular file. !! ([Specification](../page/specs/stdlib_system.html#is_file)) !! !!### Summary !! Function to evaluate whether a specified path corresponds to a regular file. !! !!### Description !! !! This function checks if a given file system path is a regular file. !! It follows symbolic links to return the status of the `target`. !! It is cross-platform and utilizes native system calls. !! It supports common operating systems such as Linux, macOS, Windows, and various UNIX-like environments. !! public :: is_file ! CPU clock ticks storage integer, parameter, private :: TICKS = int64 integer, parameter, private :: RTICKS = dp ! Interoperable types to the C backend integer, parameter, public :: process_ID = c_int64_t ! Default flag for the runner process integer(process_ID), parameter, private :: FORKED_PROCESS = 0_process_ID !> Process type holding process information and the connected stdout, stderr, stdin units type :: process_type !> Process ID (if external); 0 if run by the program process integer(process_ID) :: id = FORKED_PROCESS !> Process is completed logical :: completed = .false. integer(TICKS) :: start_time = 0 !> Standard input character(:), allocatable :: stdin_file character(:), allocatable :: stdin !> Standard output character(:), allocatable :: stdout_file character(:), allocatable :: stdout !> Error output integer :: exit_code = 0 character(:), allocatable :: stderr_file character(:), allocatable :: stderr !> Callback function procedure(process_callback), nopass, pointer :: oncomplete => null() !> Optional payload for the callback function class(*), pointer :: payload => null() !> Store time at the last update integer(TICKS) :: last_update = 0 contains !! Check if process is still running procedure :: is_running => process_is_running !! Check if process is completed procedure :: is_completed => process_is_completed !! Return elapsed time since inception procedure :: elapsed => process_lifetime !! Update process state internals procedure :: update => update_process_state !! Kill a process procedure :: kill => process_kill !! Get process ID procedure :: pid => process_get_ID end type process_type interface runasync !! version: experimental !! !! Executes an external process asynchronously. !! ([Specification](../page/specs/stdlib_system.html#runasync-execute-an-external-process-asynchronously)) !! !! ### Summary !! Provides methods for executing external processes asynchronously, using either a single command string !! or an argument list, with options for output collection and standard input. !! !! ### Description !! !! This interface allows the user to spawn external processes asynchronously (non-blocking). !! Processes can be executed via a single command string or a list of arguments, with options to collect !! standard output and error streams, or to provide a standard input stream via a `character` string. !! Additionally, a callback function can be provided, which will be called upon process completion. !! A user-defined payload can be attached and passed to the callback for handling process-specific data. !! !! @note The implementation depends on system-level process management capabilities. !! module function run_async_cmd(cmd, stdin, want_stdout, want_stderr, callback, payload) result(process) !> The command line string to execute. character(*), intent(in) :: cmd !> Optional input sent to the process via standard input (stdin). character(*), optional, intent(in) :: stdin !> Whether to collect standard output. logical, optional, intent(in) :: want_stdout !> Whether to collect standard error output. logical, optional, intent(in) :: want_stderr !> Optional callback function to be called on process completion procedure(process_callback), optional :: callback !> Optional payload to pass to the callback on completion class(*), optional, intent(inout), target :: payload !> The output process handler. type(process_type) :: process end function run_async_cmd module function run_async_args(args, stdin, want_stdout, want_stderr, callback, payload) result(process) !> List of arguments for the process to execute. character(*), intent(in) :: args(:) !> Optional input sent to the process via standard input (stdin). character(*), optional, intent(in) :: stdin !> Whether to collect standard output. logical, optional, intent(in) :: want_stdout !> Whether to collect standard error output. logical, optional, intent(in) :: want_stderr !> Optional callback function to be called on process completion procedure(process_callback), optional :: callback !> Optional payload to pass to the callback on completion class(*), optional, intent(inout), target :: payload !> The output process handler. type(process_type) :: process end function run_async_args end interface runasync interface run !! version: experimental !! !! Executes an external process synchronously. !! ([Specification](../page/specs/stdlib_system.html#run-execute-an-external-process-synchronously)) !! !! ### Summary !! Provides methods for executing external processes synchronously, using either a single command string !! or an argument list, with options for output collection and standard input. !! !! ### Description !! !! This interface allows the user to spawn external processes synchronously (blocking), !! via either a single command string or a list of arguments. It also includes options to collect !! standard output and error streams, or to provide a standard input stream via a `character` string. !! Additionally, it supports an optional callback function that is invoked upon process completion, !! allowing users to process results dynamically. A user-defined payload can also be provided, !! which is passed to the callback function to facilitate contextual processing. !! !! @note The implementation depends on system-level process management capabilities. !! module function run_sync_cmd(cmd, stdin, want_stdout, want_stderr, callback, payload) result(process) !> The command line string to execute. character(*), intent(in) :: cmd !> Optional input sent to the process via standard input (stdin). character(*), optional, intent(in) :: stdin !> Whether to collect standard output. logical, optional, intent(in) :: want_stdout !> Whether to collect standard error output. logical, optional, intent(in) :: want_stderr !> Optional callback function to be called on process completion procedure(process_callback), optional :: callback !> Optional payload to pass to the callback on completion class(*), optional, intent(inout), target :: payload !> The output process handler. type(process_type) :: process end function run_sync_cmd module function run_sync_args(args, stdin, want_stdout, want_stderr, callback, payload) result(process) !> List of arguments for the process to execute. character(*), intent(in) :: args(:) !> Optional input sent to the process via standard input (stdin). character(*), optional, intent(in) :: stdin !> Whether to collect standard output. logical, optional, intent(in) :: want_stdout !> Whether to collect standard error output. logical, optional, intent(in) :: want_stderr !> Optional callback function to be called on process completion procedure(process_callback), optional :: callback !> Optional payload to pass to the callback on completion class(*), optional, intent(inout), target :: payload !> The output process handler. type(process_type) :: process end function run_sync_args end interface run interface is_running !! version: experimental !! !! Checks if an external process is still running. !! ([Specification](../page/specs/stdlib_system.html#is_running-check-if-a-process-is-still-running)) !! !! ### Summary !! Provides a method to determine if an external process is still actively running. !! !! ### Description !! !! This interface checks the status of an external process to determine whether it is still actively running. !! It is particularly useful for monitoring asynchronous processes created using the `run` interface. !! The internal state of the `process_type` object is updated after the call to reflect the current process status. !! !! @note The implementation relies on system-level process management capabilities. !! logical module function process_is_running(process) result(is_running) !> The process object to check. class(process_type), intent(inout) :: process !> Logical result: `.true.` if the process is still running, `.false.` otherwise. end function process_is_running end interface is_running interface is_completed !! version: experimental !! !! Checks if an external process has completed execution. !! ([Specification](../page/specs/stdlib_system.html#is_completed-check-if-a-process-has-completed-execution)) !! !! ### Summary !! Provides a method to determine if an external process has finished execution. !! !! ### Description !! !! This interface checks the status of an external process to determine whether it has finished execution. !! It is particularly useful for monitoring asynchronous processes created using the `run` interface. !! The internal state of the `process_type` object is updated after the call to reflect the current process status. !! !! @note The implementation relies on system-level process management capabilities. !! logical module function process_is_completed(process) result(is_completed) !> The process object to check. class(process_type), intent(inout) :: process !> Logical result: `.true.` if the process has completed, `.false.` otherwise. end function process_is_completed end interface is_completed interface elapsed !! version: experimental !! !! Returns the lifetime of a process, in seconds. !! ([Specification](../page/specs/stdlib_system.html#elapsed-return-process-lifetime-in-seconds)) !! !! ### Summary !! Provides the total elapsed time (in seconds) since the creation of the specified process. !! !! ### Description !! !! This interface returns the total elapsed time (in seconds) for a given process since it was started. !! If the process is still running, the value returned reflects the time from the creation of the process !! until the call to this function. Otherwise, the total process duration until completion is returned. !! module function process_lifetime(process) result(delta_t) !> The process object for which to calculate elapsed time. class(process_type), intent(in) :: process !> The elapsed time in seconds since the process started. real(RTICKS) :: delta_t end function process_lifetime end interface elapsed interface wait !! version: experimental !! !! Waits for a running process to complete. !! ([Specification](../page/specs/stdlib_system.html#wait-wait-until-a-running-process-is-completed)) !! !! ### Summary !! Provides a method to block the execution and wait until the specified process finishes. !! Supports an optional maximum wait time, after which the function returns regardless of process completion. !! !! ### Description !! !! This interface allows waiting for a process to complete. If the process is running asynchronously, this subroutine !! will block further execution until the process finishes. Optionally, a maximum wait time can be specified; if !! the process doesn't complete within this time, the subroutine returns without further waiting. !! !! @note The process state is accordingly updated on return from this call. !! module subroutine wait_for_completion(process, max_wait_time) !> The process object to monitor. class(process_type), intent(inout) :: process !> Optional maximum wait time in seconds. If not provided, waits indefinitely. real, optional, intent(in) :: max_wait_time end subroutine wait_for_completion end interface wait interface update !! version: experimental !! !! Updates the internal state of a process variable. !! ([Specification](../page/specs/stdlib_system.html#update-update-the-internal-state-of-a-process)) !! !! ### Summary !! Provides a method to query the system and update the internal state of the specified process variable. !! !! ### Description !! !! This subroutine queries the system to retrieve and update information about the state of the process. !! Once the process is completed, and if standard output or standard error were requested, their respective !! data is loaded into the `process%stdout` and `process%stderr` variables. This routine is useful for keeping !! track of the latest state and output of a process, particularly for asynchronous processes. !! !! @note This subroutine should be called periodically for asynchronous processes to check their completion !! and retrieve the output. !! module subroutine update_process_state(process) !> The process object whose state needs to be updated. class(process_type), intent(inout) :: process end subroutine update_process_state end interface update interface kill !! version: experimental !! !! Terminates a running process. !! ([Specification](../page/specs/stdlib_system.html#kill-terminate-a-running-process)) !! !! ### Summary !! Provides a method to kill or terminate a running process. !! Returns a boolean flag indicating whether the termination was successful. !! !! ### Description !! !! This interface allows for the termination of an external process that is still running. !! If the process is successfully killed, the `success` output flag is set to `.true.`, otherwise `.false.`. !! This function is useful for controlling and managing processes that are no longer needed or for forcefully !! stopping an unresponsive process. !! !! @note This operation may be system-dependent and could fail if the underlying user does not have !! the necessary rights to kill a process. !! module subroutine process_kill(process, success) !> The process object to be terminated. class(process_type), intent(inout) :: process !> Boolean flag indicating whether the termination was successful. logical, intent(out) :: success end subroutine process_kill end interface kill interface sleep !! version: experimental !! !! Pauses execution for a specified time in milliseconds. !! ([Specification](../page/specs/stdlib_system.html#sleep-pause-execution-for-a-specified-time=in-milliseconds)) !! !! ### Summary !! Pauses code execution for a specified number of milliseconds. This routine is a cross-platform !! wrapper around platform-specific sleep functions, providing consistent behavior on different operating systems. !! !! ### Description !! !! This interface allows the user to pause the execution of a program for a specified duration, expressed in !! milliseconds. It provides a cross-platform wrapper around native sleep functions, ensuring that the program !! will sleep for the requested amount of time on different systems (e.g., using `Sleep` on Windows or `nanosleep` !! on Unix-like systems). !! !! @note The precision of the sleep may vary depending on the system and platform. !! module subroutine sleep(millisec) !> The number of milliseconds to pause execution for. integer, intent(in) :: millisec end subroutine sleep end interface sleep abstract interface !! version: experimental !! !! Process callback interface !! !! ### Summary !! !! The `process_callback` interface defines a user-provided subroutine that will be called !! upon process completion. It provides access to process metadata, including the process ID, !! exit state, and optional input/output streams. If passed on creation, a generic payload can be !! accessed by the callback function. This variable must be a valid `target` in the calling scope. !! subroutine process_callback(pid,exit_state,stdin,stdout,stderr,payload) import process_ID implicit none !> Process ID integer(process_ID), intent(in) :: pid !> Process return state integer, intent(in) :: exit_state !> Process input/output: presence of these arguments depends on how process was created character(len=*), optional, intent(in) :: stdin,stdout,stderr !> Optional payload passed by the user on process creation class(*), optional, intent(inout) :: payload end subroutine process_callback end interface !! Static storage for the current OS logical :: have_os = .false. integer :: OS_CURRENT = OS_UNKNOWN interface !! version: experimental !! !! Returns a `logical` flag indicating if the system is Windows. !! ([Specification](../page/specs/stdlib_system.html#is_windows-check-if-the-system-is-running-on-windows)) !! !! ### Summary !! A fast, compile-time check to determine if the system is running Windows, based on the `_WIN32` macro. !! !! ### Description !! !! This interface provides a function to check if the current system is Windows. The check is performed by !! wrapping a C function that tests if the `_WIN32` macro is defined. This check is fast and occurs at !! compile-time, making it a more efficient alternative to platform-specific runtime checks. !! !! The `is_windows` function is particularly useful for conditional compilation or system-specific code paths !! that are dependent on whether the code is running on Windows. !! !! @note This function relies on the `_WIN32` macro, which is defined in C compilers when targeting Windows. !! logical module function is_windows() end function is_windows module function process_get_ID(process) result(ID) class(process_type), intent(in) :: process !> Return a process ID integer(process_ID) :: ID end function process_get_ID end interface interface join_path !! version: experimental !! !!### Summary !! join the paths provided according to the OS-specific path-separator !! ([Specification](../page/specs/stdlib_system.html#join_path)) !! module function join2_char_char(p1, p2) result(path) character(:), allocatable :: path character(*), intent(in) :: p1, p2 end function join2_char_char module function join2_char_string(p1, p2) result(path) character(:), allocatable :: path character(*), intent(in) :: p1 type(string_type), intent(in) :: p2 end function join2_char_string module function join2_string_char(p1, p2) result(path) type(string_type) :: path type(string_type), intent(in) :: p1 character(*), intent(in) :: p2 end function join2_string_char module function join2_string_string(p1, p2) result(path) type(string_type) :: path type(string_type), intent(in) :: p1, p2 end function join2_string_string module function joinarr_char(p) result(path) character(:), allocatable :: path character(*), intent(in) :: p(:) end function joinarr_char module function joinarr_string(p) result(path) type(string_type) :: path type(string_type), intent(in) :: p(:) end function joinarr_string end interface join_path interface operator(/) !! version: experimental !! !!### Summary !! A binary operator to join the paths provided according to the OS-specific path-separator !! ([Specification](../page/specs/stdlib_system.html#operator(/))) !! module function join_op_char_char(p1, p2) result(path) character(:), allocatable :: path character(*), intent(in) :: p1, p2 end function join_op_char_char module function join_op_char_string(p1, p2) result(path) character(:), allocatable :: path character(*), intent(in) :: p1 type(string_type), intent(in) :: p2 end function join_op_char_string module function join_op_string_char(p1, p2) result(path) type(string_type) :: path type(string_type), intent(in) :: p1 character(*), intent(in) :: p2 end function join_op_string_char module function join_op_string_string(p1, p2) result(path) type(string_type) :: path type(string_type), intent(in) :: p1, p2 end function join_op_string_string end interface operator(/) interface split_path !! version: experimental !! !!### Summary !! splits the path immediately following the final path-separator !! separating into typically a directory and a file name. !! ([Specification](../page/specs/stdlib_system.html#split_path)) !! !!### Description !! If the path is empty `head`='.' and tail='' !! If the path only consists of separators, `head` is set to the separator and tail is empty !! If the path is a root directory, `head` is set to that directory and tail is empty !! `head` ends with a path-separator iff the path appears to be a root directory or a child of the root directory module subroutine split_path_char(p, head, tail) character(*), intent(in) :: p character(:), allocatable, intent(out) :: head, tail end subroutine split_path_char module subroutine split_path_string(p, head, tail) type(string_type), intent(in) :: p type(string_type), intent(out) :: head, tail end subroutine split_path_string end interface split_path interface base_name !! version: experimental !! !!### Summary !! returns the base name (last component) of the provided path !! ([Specification](../page/specs/stdlib_system.html#base_name)) !! !!### Description !! The value returned is the `tail` of the interface `split_path` module function base_name_char(p) result(base) character(:), allocatable :: base character(*), intent(in) :: p end function base_name_char module function base_name_string(p) result(base) type(string_type) :: base type(string_type), intent(in) :: p end function base_name_string end interface base_name interface dir_name !! version: experimental !! !!### Summary !! returns everything but the last component of the provided path !! ([Specification](../page/specs/stdlib_system.html#dir_name)) !! !!### Description !! The value returned is the `head` of the interface `split_path` module function dir_name_char(p) result(dir) character(:), allocatable :: dir character(*), intent(in) :: p end function dir_name_char module function dir_name_string(p) result(dir) type(string_type) :: dir type(string_type), intent(in) :: p end function dir_name_string end interface dir_name contains integer function get_runtime_os() result(os) !! The function identifies the OS by inspecting environment variables and filesystem attributes. !! !! ### Returns: !! - **OS_UNKNOWN**: If the OS cannot be determined. !! - **OS_LINUX**, **OS_MACOS**, **OS_WINDOWS**, **OS_CYGWIN**, **OS_SOLARIS**, **OS_FREEBSD**, or **OS_OPENBSD**. !! !! Note: This function performs a detailed runtime inspection, so it has non-negligible overhead. ! Local variables character(len=255) :: val integer :: length, rc logical :: file_exists os = OS_UNKNOWN ! Check environment variable `OSTYPE`. call get_environment_variable('OSTYPE', val, length, rc) if (rc == 0 .and. length > 0) then ! Linux if (index(val, 'linux') > 0) then os = OS_LINUX return ! macOS elseif (index(val, 'darwin') > 0) then os = OS_MACOS return ! Windows, MSYS, MinGW, Git Bash elseif (index(val, 'win') > 0 .or. index(val, 'msys') > 0) then os = OS_WINDOWS return ! Cygwin elseif (index(val, 'cygwin') > 0) then os = OS_CYGWIN return ! Solaris, OpenIndiana, ... elseif (index(val, 'SunOS') > 0 .or. index(val, 'solaris') > 0) then os = OS_SOLARIS return ! FreeBSD elseif (index(val, 'FreeBSD') > 0 .or. index(val, 'freebsd') > 0) then os = OS_FREEBSD return ! OpenBSD elseif (index(val, 'OpenBSD') > 0 .or. index(val, 'openbsd') > 0) then os = OS_OPENBSD return end if end if ! Check environment variable `OS`. call get_environment_variable('OS', val, length, rc) if (rc == 0 .and. length > 0 .and. index(val, 'Windows_NT') > 0) then os = OS_WINDOWS return end if ! Linux inquire (file='/etc/os-release', exist=file_exists) if (file_exists) then os = OS_LINUX return end if ! macOS inquire (file='/usr/bin/sw_vers', exist=file_exists) if (file_exists) then os = OS_MACOS return end if ! FreeBSD inquire (file='/bin/freebsd-version', exist=file_exists) if (file_exists) then os = OS_FREEBSD return end if end function get_runtime_os !> Retrieves the cached OS type for minimal runtime overhead. integer function OS_TYPE() result(os) !! This function uses a static cache to avoid recalculating the OS type after the first call. !! It is recommended for performance-sensitive use cases where the OS type is checked multiple times. if (.not.have_os) then OS_CURRENT = get_runtime_os() have_os = .true. end if os = OS_CURRENT end function OS_TYPE !> Return string describing the OS type flag pure function OS_NAME(os) integer, intent(in) :: os character(len=:), allocatable :: OS_NAME select case (os) case (OS_LINUX); OS_NAME = "Linux" case (OS_MACOS); OS_NAME = "macOS" case (OS_WINDOWS); OS_NAME = "Windows" case (OS_CYGWIN); OS_NAME = "Cygwin" case (OS_SOLARIS); OS_NAME = "Solaris" case (OS_FREEBSD); OS_NAME = "FreeBSD" case (OS_OPENBSD); OS_NAME = "OpenBSD" case default ; OS_NAME = "Unknown" end select end function OS_NAME !! Tests if a given path matches an existing directory. !! Cross-platform implementation without using external C libraries. logical function is_directory(path) !> Input path to evaluate character(*), intent(in) :: path interface logical(c_bool) function stdlib_is_directory(path) bind(c, name="stdlib_is_directory") import c_bool, c_char character(kind=c_char), intent(in) :: path(*) end function stdlib_is_directory end interface is_directory = logical(stdlib_is_directory(to_c_char(trim(path)))) end function is_directory ! A Helper function to convert C character arrays to Fortran character strings function to_f_char(c_str_ptr, len) result(f_str) type(c_ptr), intent(in) :: c_str_ptr ! length of the string excluding the null character integer(kind=c_size_t), intent(in) :: len character(:), allocatable :: f_str integer :: i character(kind=c_char), pointer :: c_str(:) call c_f_pointer(c_str_ptr, c_str, [len]) allocate(character(len=len) :: f_str) do concurrent (i=1:len) f_str(i:i) = c_str(i) end do end function to_f_char ! A helper function to get the string describing an error from C functions. ! If `winapi` is false or not present, uses `strerror` provided by `` ! Otherwise, uses `strerror` on unix and `FormatMessageA` on windows. function c_get_strerror(winapi) result(str) character(len=:), allocatable :: str logical, optional, intent(in) :: winapi interface type(c_ptr) function strerror(len, winapi) bind(C, name='stdlib_strerror') import c_size_t, c_ptr, c_bool implicit none integer(c_size_t), intent(out) :: len logical, intent(in) :: winapi end function strerror end interface type(c_ptr) :: c_str_ptr integer(c_size_t) :: len, i character(kind=c_char), pointer :: c_str(:) logical :: winapi_ winapi_ = optval(winapi, .false.) c_str_ptr = strerror(len, winapi_) str = to_f_char(c_str_ptr, len) end function c_get_strerror !! makes an empty directory subroutine make_directory(path, err) character(len=*), intent(in) :: path type(state_type), optional, intent(out) :: err integer :: code type(state_type) :: err0 interface integer function stdlib_make_directory(cpath) bind(C, name='stdlib_make_directory') import c_char character(kind=c_char), intent(in) :: cpath(*) end function stdlib_make_directory end interface code = stdlib_make_directory(to_c_char(trim(path))) if (code /= 0) then err0 = FS_ERROR_CODE(code, c_get_strerror()) call err0%handle(err) end if end subroutine make_directory subroutine make_directory_all(path, err) character(len=*), intent(in) :: path type(state_type), optional, intent(out) :: err integer :: i, indx type(state_type) :: err0 character(len=1) :: sep logical :: is_dir, check_is_dir sep = path_sep() i = 1 indx = find(path, sep, i) check_is_dir = .true. do ! Base case to exit the loop if (indx == 0) then is_dir = is_directory(path) if (.not. is_dir) then call make_directory(path, err0) if (err0%error()) then call err0%handle(err) end if end if return end if if (check_is_dir) then is_dir = is_directory(path(1:indx)) end if if (.not. is_dir) then ! no need for further `is_dir` checks ! all paths going forward need to be created check_is_dir = .false. call make_directory(path(1:indx), err0) if (err0%error()) then call err0%handle(err) return end if end if i = i + 1 ! the next occurence of `sep` indx = find(path, sep, i) end do end subroutine make_directory_all !! removes an empty directory subroutine remove_directory(path, err) character(len=*), intent(in) :: path type(state_type), optional, intent(out) :: err integer :: code type(state_type) :: err0 interface integer function stdlib_remove_directory(cpath) bind(C, name='stdlib_remove_directory') import c_char character(kind=c_char), intent(in) :: cpath(*) end function stdlib_remove_directory end interface code = stdlib_remove_directory(to_c_char(trim(path))) if (code /= 0) then err0 = FS_ERROR_CODE(code, c_get_strerror()) call err0%handle(err) end if end subroutine remove_directory subroutine get_cwd(cwd, err) character(:), allocatable, intent(out) :: cwd type(state_type), optional, intent(out) :: err type(state_type) :: err0 interface type(c_ptr) function stdlib_get_cwd(len, stat) bind(C, name='stdlib_get_cwd') import c_ptr, c_size_t integer(c_size_t), intent(out) :: len integer :: stat end function stdlib_get_cwd end interface type(c_ptr) :: c_str_ptr integer(c_size_t) :: len integer :: stat c_str_ptr = stdlib_get_cwd(len, stat) if (stat /= 0) then err0 = FS_ERROR_CODE(stat, c_get_strerror()) call err0%handle(err) end if cwd = to_f_char(c_str_ptr, len) end subroutine get_cwd subroutine set_cwd(path, err) character(len=*), intent(in) :: path type(state_type), optional, intent(out) :: err type(state_type) :: err0 interface integer function stdlib_set_cwd(path) bind(C, name='stdlib_set_cwd') import c_char character(kind=c_char), intent(in) :: path(*) end function stdlib_set_cwd end interface integer :: code code = stdlib_set_cwd(to_c_char(trim(path))) if (code /= 0) then err0 = FS_ERROR_CODE(code, c_get_strerror()) call err0%handle(err) end if end subroutine set_cwd !> Returns the file path of the null device for the current operating system. !> !> Version: Helper function. function null_device() result(path) !> File path of the null device character(:), allocatable :: path interface ! No-overhead return path to the null device type(c_ptr) function process_null_device(len) bind(C,name='process_null_device') import c_ptr, c_size_t implicit none integer(c_size_t), intent(out) :: len end function process_null_device end interface integer(c_size_t) :: len type(c_ptr) :: c_path_ptr ! Call the C function to get the null device path and its length c_path_ptr = process_null_device(len) path = to_f_char(c_path_ptr, len) end function null_device !> Delete a file at the given path. subroutine delete_file(path, err) character(*), intent(in) :: path type(state_type), optional, intent(out) :: err !> Local variables integer :: file_unit, ios type(state_type) :: err0 character(len=512) :: msg logical :: file_exists ! Verify the file is not a directory. if (is_directory(path)) then ! If unable to open, assume it's a directory or inaccessible err0 = state_type(STDLIB_FS_ERROR,'Cannot delete',path,'- is a directory') call err0%handle(err) return end if ! Check if the path exists ! Because Intel compilers return .false. if path is a directory, this must be tested ! _after_ the directory test inquire(file=path, exist=file_exists) if (.not. file_exists) then ! File does not exist, return non-error status err0 = state_type(STDLIB_SUCCESS,path,' not deleted: file does not exist') call err0%handle(err) return endif ! Close and delete the file open(newunit=file_unit, file=path, status='old', iostat=ios, iomsg=msg) if (ios /= 0) then err0 = state_type(STDLIB_FS_ERROR,'Cannot delete',path,'-',msg) call err0%handle(err) return end if close(unit=file_unit, status='delete', iostat=ios, iomsg=msg) if (ios /= 0) then err0 = state_type(STDLIB_FS_ERROR,'Cannot delete',path,'-',msg) call err0%handle(err) return end if end subroutine delete_file pure function FS_ERROR_CODE(code,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,& a11,a12,a13,a14,a15,a16,a17,a18,a19) result(state) type(state_type) :: state !> Platform specific error code integer, intent(in) :: code !> Optional rank-agnostic arguments class(*), intent(in), optional, dimension(..) :: a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,& a11,a12,a13,a14,a15,a16,a17,a18,a19 character(32) :: code_msg write(code_msg, "('code - ', i0, ',')") code state = state_type(STDLIB_FS_ERROR, code_msg,a1,a2,a3,a4,a5,a6,a7,a8,& a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19) end function FS_ERROR_CODE pure function FS_ERROR(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,& a12,a13,a14,a15,a16,a17,a18,a19,a20) result(state) type(state_type) :: state !> Optional rank-agnostic arguments class(*), intent(in), optional, dimension(..) :: a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,& a11,a12,a13,a14,a15,a16,a17,a18,a19,a20 state = state_type(STDLIB_FS_ERROR, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,& a13,a14,a15,a16,a17,a18,a19,a20) end function FS_ERROR ! checks if a path exists and returns its type function exists(path, err) result(fs_type) character(*), intent(in) :: path type(state_type), optional, intent(out) :: err integer :: fs_type type(state_type) :: err0 interface integer function stdlib_exists(path, stat) bind(C, name='stdlib_exists') import c_char, c_int character(kind=c_char), intent(in) :: path(*) ! to return the error code if any integer(kind=c_int), intent(out) :: stat end function stdlib_exists end interface integer(kind=c_int) :: stat fs_type = stdlib_exists(to_c_char(trim(path)), stat) ! an error occurred if (stat /= 0) then err0 = FS_ERROR_CODE(stat, c_get_strerror()) call err0%handle(err) end if end function exists ! public convenience wrapper to check if path is a symbolic link logical function is_symlink(path) character(len=*), intent(in) :: path type(state_type) :: err is_symlink = exists(path, err) == fs_type_symlink end function is_symlink ! checks if path is a regular file. ! It follows symbolic links and returns the status of the `target`. logical function is_file(path) character(len=*), intent(in) :: path interface logical(c_bool) function stdlib_is_file(path) bind(C, name='stdlib_is_file') import c_char, c_bool character(kind=c_char) :: path(*) end function stdlib_is_file end interface is_file = logical(stdlib_is_file(to_c_char(trim(path)))) end function is_file character function path_sep() if (OS_TYPE() == OS_WINDOWS) then path_sep = '\' else path_sep = '/' end if end function path_sep end module stdlib_system fortran-lang-stdlib-0ede301/src/system/stdlib_system.c0000664000175000017500000001161115135654166023332 0ustar alastairalastair#include #include #include #include #include #include #include #include #ifdef _WIN32 #include #include #ifndef S_ISREG #if defined(S_IFMT) && defined(S_IFREG) #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #elif defined(_S_IFMT) && defined(_S_IFREG) #define S_ISREG(mode) (((mode) & _S_IFMT) == _S_IFREG) #endif #endif /* ifndef S_ISREG */ #else #include #endif /* ifdef _WIN32 */ // Wrapper to get the string describing a system syscall error. // Always Uses `strerr` on unix. // if `winapi` is `false`, uses the usual `strerr` on windows. // If `winapi` is `true`, uses `FormatMessageA`(from windows.h) on windows. char* stdlib_strerror(size_t* len, bool winapi){ if (winapi) { #ifdef _WIN32 LPSTR err = NULL; DWORD dw = GetLastError(); FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &err, 0, NULL); *len = strlen(err); return (char*) err; #endif /* ifdef _WIN32 */ } char* err = strerror(errno); *len = strlen(err); return err; } // Wrapper to the platform's `mkdir`(make directory) call. // Uses `mkdir` on unix, `_mkdir` on windows. // Returns 0 if successful, otherwise returns the `errno`. int stdlib_make_directory(const char* path){ int code; #ifdef _WIN32 code = _mkdir(path); #else // Default mode 0777 code = mkdir(path, 0777); #endif /* ifdef _WIN32 */ return (!code) ? 0 : errno; } // Wrapper to the platform's `rmdir`(remove directory) call. // Uses `rmdir` on unix, `_rmdir` on windows. // Returns 0 if successful, otherwise returns the `errno`. int stdlib_remove_directory(const char* path){ int code; #ifdef _WIN32 code = _rmdir(path); #else code = rmdir(path); #endif /* ifdef _WIN32 */ return (!code) ? 0 : errno; } // Wrapper to the platform's `getcwd`(get current working directory) call. // Uses `getcwd` on unix, `_getcwd` on windows. // Returns the cwd, sets the length of cwd and the `stat` of the operation. char* stdlib_get_cwd(size_t* len, int* stat){ *stat = 0; #ifdef _WIN32 char* buffer; buffer = _getcwd(NULL, 0); if (buffer == NULL) { *stat = errno; return NULL; } *len = strlen(buffer); return buffer; #else char buffer[PATH_MAX + 1]; if (!getcwd(buffer, sizeof(buffer))) { *stat = errno; } *len = strlen(buffer); char* res = malloc(*len + 1); // Allocate space for null terminator if (res == NULL) { *stat = ENOMEM; // Set error code for memory allocation failure return NULL; } strncpy(res, buffer, *len); res[*len] = '\0'; // Ensure null termination return res; #endif /* ifdef _WIN32 */ } // Wrapper to the platform's `chdir`(change directory) call. // Uses `chdir` on unix, `_chdir` on windows. // Returns 0 if successful, otherwise returns the `errno`. int stdlib_set_cwd(const char* path) { int code; #ifdef _WIN32 code = _chdir(path); #else code = chdir(path); #endif /* ifdef _WIN32 */ return (code == -1) ? errno : 0; } // Wrapper to the platform's `stat`(status of path) call. // Uses `lstat` on unix, `GetFileAttributesA` on windows. // Returns the `type` of the path, and sets the `stat`(if any errors). int stdlib_exists(const char* path, int* stat){ // All the valid types const int fs_type_unknown = 0; const int fs_type_regular_file = 1; const int fs_type_directory = 2; const int fs_type_symlink = 3; int type = fs_type_unknown; *stat = 0; #ifdef _WIN32 DWORD attrs = GetFileAttributesA(path); if (attrs == INVALID_FILE_ATTRIBUTES) { *stat = (int) GetLastError(); return fs_type_unknown; } // Let's assume it is a regular file type = fs_type_regular_file; if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) type = fs_type_symlink; if (attrs & FILE_ATTRIBUTE_DIRECTORY) type = fs_type_directory; #else struct stat buf = {0}; int status; status = lstat(path, &buf); if (status == -1) { // `lstat` failed *stat = errno; return fs_type_unknown; } switch (buf.st_mode & S_IFMT) { case S_IFREG: type = fs_type_regular_file; break; case S_IFDIR: type = fs_type_directory; break; case S_IFLNK: type = fs_type_symlink; break; default: type = fs_type_unknown; break; } #endif /* ifdef _WIN32 */ return type; } // `stat` and `_stat` follow symlinks automatically. // so no need for winapi functions. bool stdlib_is_file(const char* path) { #ifdef _WIN32 struct _stat buf = {0}; return _stat(path, &buf) == 0 && S_ISREG(buf.st_mode); #else struct stat buf = {0}; return stat(path, &buf) == 0 && S_ISREG(buf.st_mode); #endif /* ifdef _WIN32 */ } fortran-lang-stdlib-0ede301/src/system/CMakeLists.txt0000664000175000017500000000066515135654166023050 0ustar alastairalastairset(system_fppFiles ) set(system_cppFiles ) set(system_f90Files stdlib_system_subprocess.c stdlib_system_subprocess.F90 stdlib_system_path.f90 stdlib_system.c stdlib_system.F90 ) configure_stdlib_target(${PROJECT_NAME}_system system_f90Files system_fppFiles system_cppFiles) target_link_libraries(${PROJECT_NAME}_system PUBLIC ${PROJECT_NAME}_core ${PROJECT_NAME}_linalg_core ${PROJECT_NAME}_strings) fortran-lang-stdlib-0ede301/src/system/stdlib_system_subprocess.c0000664000175000017500000003074015135654166025606 0ustar alastairalastair#include #include #include #include #include #include #ifdef _WIN32 #include #else #define _POSIX_C_SOURCE 199309L #include #include #include #include #include #include #endif // _WIN32 // Typedefs typedef void* stdlib_handle; typedef int64_t stdlib_pid; ///////////////////////////////////////////////////////////////////////////////////// // Windows-specific code ///////////////////////////////////////////////////////////////////////////////////// #ifdef _WIN32 // On Windows systems: create a new process void process_create_windows(const char* cmd, const char* stdin_stream, const char* stdin_file, const char* stdout_file, const char* stderr_file, stdlib_pid* pid) { STARTUPINFO si; PROCESS_INFORMATION pi; HANDLE hStdout = NULL, hStderr = NULL, hStdin = NULL; SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; FILE* stdin_fp = NULL; char* full_cmd = NULL; // Initialize null handle (*pid) = 0; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(STARTUPINFO); // Write stdin_stream to stdin_file if provided if (stdin_stream && stdin_file) { stdin_fp = fopen(stdin_file, "w"); if (!stdin_fp) { fprintf(stderr, "Failed to open stdin file for writing\n"); return; } fputs(stdin_stream, stdin_fp); fclose(stdin_fp); } // Open stdin file if provided, otherwise use the null device if (stdin_file) { hStdin = CreateFile(stdin_file, GENERIC_READ, 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } else { hStdin = CreateFile("NUL", GENERIC_READ, 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } if (hStdin == INVALID_HANDLE_VALUE) { fprintf(stderr, "Failed to open input source (file or null)\n"); // No handles to close yet return; } si.hStdInput = hStdin; si.dwFlags |= STARTF_USESTDHANDLES; // Open stdout file if provided, otherwise use the null device if (stdout_file) { hStdout = CreateFile(stdout_file, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); } else { hStdout = CreateFile("NUL", GENERIC_WRITE, 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } if (hStdout == INVALID_HANDLE_VALUE) { fprintf(stderr, "Failed to open stdout sink\n"); CloseHandle(hStdin); return; } si.hStdOutput = hStdout; // Open stderr file if provided, otherwise use the null device if (stderr_file) { hStderr = CreateFile(stderr_file, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); } else { hStderr = CreateFile("NUL", GENERIC_WRITE, 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } if (hStderr == INVALID_HANDLE_VALUE) { fprintf(stderr, "Failed to open stderr sink\n"); CloseHandle(hStdin); CloseHandle(hStdout); return; } si.hStdError = hStderr; // Prepare the command line size_t cmd_len = strlen(cmd); size_t full_cmd_len = cmd_len + 1; full_cmd = (char*)malloc(full_cmd_len); if (!full_cmd) { fprintf(stderr, "Failed to allocate memory for full_cmd\n"); CloseHandle(hStdin); CloseHandle(hStdout); CloseHandle(hStderr); return; } // Use full_cmd as needed (e.g., pass to CreateProcess) snprintf(full_cmd, full_cmd_len, "%s", cmd); // Create the process BOOL success = CreateProcess( NULL, // Application name full_cmd, // Command line NULL, // Process security attributes NULL, // Thread security attributes TRUE, // Inherit handles 0, // Creation flags NULL, // Environment variables NULL, // Current directory &si, // STARTUPINFO &pi // PROCESS_INFORMATION ); // Free the allocated memory free(full_cmd); if (!success) { fprintf(stderr, "CreateProcess failed (%lu).\n", GetLastError()); CloseHandle(hStdin); CloseHandle(hStdout); CloseHandle(hStderr); return; } // Close unneeded handles (the child has its own duplicates now) CloseHandle(hStdin); CloseHandle(hStdout); CloseHandle(hStderr); // Return the process handle for status queries CloseHandle(pi.hThread); // Close the thread handle (*pid) = (stdlib_pid) pi.dwProcessId; } // Query process state on a Windows system void process_query_status_windows(stdlib_pid pid, bool wait, bool* is_running, int* exit_code) { int wait_code; HANDLE hProcess; DWORD dwExitCode,dwPid; dwPid = (DWORD) pid; // Open the process with the appropriate access rights hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, dwPid); // Error opening the process, likely pid does not exist if (hProcess == NULL) { *is_running = false; *exit_code = -1; return; } if (wait) { // Wait for the process to terminate wait_code = WaitForSingleObject(hProcess, INFINITE); } else { // Check if the process has terminated wait_code = WaitForSingleObject(hProcess, 0); } if (wait_code == WAIT_OBJECT_0) { // Process has exited, get the exit code *is_running = false; if (GetExitCodeProcess(hProcess, &dwExitCode)) { *exit_code = dwExitCode; } else { *exit_code = -1; // Error retrieving the exit code } } else if (wait_code == WAIT_TIMEOUT) { // Process is still running *is_running = true; *exit_code = 0; } else { // WAIT_FAILED // Error occurred *is_running = false; *exit_code = -1; // Error occurred in WaitForSingleObject } // Close the process handle CloseHandle(hProcess); } // Kill a process on Windows by sending a PROCESS_TERMINATE signal. // Return true if the operation succeeded, or false if it failed (process does not // exist anymore, or we may not have the rights to kill the process). bool process_kill_windows(stdlib_pid pid) { HANDLE hProcess; DWORD dwPid; dwPid = (DWORD) pid; // Open the process with terminate rights hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwPid); if (hProcess == NULL) { // Failed to open the process; return false return false; } // Attempt to terminate the process if (!TerminateProcess(hProcess, 1)) { // Failed to terminate the process CloseHandle(hProcess); return false; } // Successfully terminated the process CloseHandle(hProcess); return true; } // Check if input path is a directory bool stdlib_is_directory_windows(const char *path) { DWORD attrs = GetFileAttributesA(path); return (attrs != INVALID_FILE_ATTRIBUTES) // Path exists && (attrs & FILE_ATTRIBUTE_DIRECTORY); // Path is a directory } #else // _WIN32 ///////////////////////////////////////////////////////////////////////////////////// // Unix-specific code ///////////////////////////////////////////////////////////////////////////////////// void process_query_status_unix(stdlib_pid pid, bool wait, bool* is_running, int* exit_code) { int status; int wait_code; // Wait or return immediately if no status change int options = wait ? 0 : WNOHANG; // Call waitpid to check the process state wait_code = waitpid(pid, &status, options); if (wait_code > 0) { // Process state was updated if (WIFEXITED(status)) { *is_running = false; // Get exit code *exit_code = WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { *is_running = false; // Use negative value to indicate termination by signal *exit_code = -WTERMSIG(status); } else { // Process is still running: no valid exit code yet *is_running = true; *exit_code = 0; } } else if (wait_code == 0) { // No status change; process is still running *is_running = true; *exit_code = 0; } else { // Error occurred *is_running = false; *exit_code = -1; // Indicate an error } } // Kill a process by sending a SIGKILL signal. Return .true. if succeeded, or false if not. // Killing process may fail due to unexistent process, or not enough rights to kill. bool process_kill_unix(stdlib_pid pid) { // Send the SIGKILL signal to the process if (kill(pid, SIGKILL) == 0) { // Successfully sent the signal return true; } // If `kill` fails, check if the process no longer exists if (errno == ESRCH) { // Process does not exist return true; // Already "terminated" } // Other errors occurred return false; } // On UNIX systems: just fork a new process. The command line will be executed from Fortran. void process_create_posix(stdlib_pid* pid) { (*pid) = (stdlib_pid) fork(); } // On UNIX systems: check if input path is a directory bool stdlib_is_directory_posix(const char *path) { struct stat sb; return stat(path, &sb) == 0 && S_ISDIR(sb.st_mode); } #endif // _WIN32 ///////////////////////////////////////////////////////////////////////////////////// // Cross-platform interface ///////////////////////////////////////////////////////////////////////////////////// // Cross-platform interface: query directory state bool stdlib_is_directory(const char *path) { // Invalid input if (path == NULL || strlen(path) == 0) return false; #ifdef _WIN32 return stdlib_is_directory_windows(path); #else return stdlib_is_directory_posix(path); #endif // _WIN32 } // Create or fork process void process_create(const char* cmd, const char* stdin_stream, const char* stdin_file, const char* stdout_file, const char* stderr_file, stdlib_pid* pid) { #ifdef _WIN32 process_create_windows(cmd, stdin_stream, stdin_file, stdout_file, stderr_file, pid); #else process_create_posix(pid); #endif // _WIN32 } // Cross-platform interface: query process state void process_query_status(stdlib_pid pid, bool wait, bool* is_running, int* exit_code) { #ifdef _WIN32 process_query_status_windows(pid, wait, is_running, exit_code); #else process_query_status_unix (pid, wait, is_running, exit_code); #endif // _WIN32 } // Cross-platform interface: kill process by ID bool process_kill(stdlib_pid pid) { #ifdef _WIN32 return process_kill_windows(pid); #else return process_kill_unix(pid); #endif // _WIN32 } // Cross-platform interface: sleep(seconds) void process_wait(float seconds) { #ifdef _WIN32 DWORD dwMilliseconds = (DWORD) (seconds * 1000); Sleep(dwMilliseconds); #else int ierr; unsigned int ms = (unsigned int) (seconds * 1000); struct timespec ts_remaining = { ms / 1000, (ms % 1000) * 1000000L }; do { struct timespec ts_sleep = ts_remaining; ierr = nanosleep(&ts_sleep, &ts_remaining); } while ((EINTR == errno) && (-1 == ierr)); if (ierr != 0){ switch(errno){ case EINTR: fprintf(stderr, "nanosleep() interrupted\n"); break; case EINVAL: fprintf(stderr, "nanosleep() bad milliseconds value\n"); exit(EINVAL); case EFAULT: fprintf(stderr, "nanosleep() problem copying information to user space\n"); exit(EFAULT); case ENOSYS: fprintf(stderr, "nanosleep() not supported on this system\n"); exit(ENOSYS); default: fprintf(stderr, "nanosleep() error\n"); exit(1); } } #endif // _WIN32 } // Returns the cross-platform file path of the null device for the current operating system. const char* process_null_device(size_t* len) { #ifdef _WIN32 (*len) = strlen("NUL"); return "NUL"; #else (*len) = strlen("/dev/null"); return "/dev/null"; #endif } // Returns a boolean flag if macro _WIN32 is defined bool process_is_windows() { #ifdef _WIN32 return true; #else return false; #endif // _WIN32 } fortran-lang-stdlib-0ede301/src/lapack/0000775000175000017500000000000015135654166020210 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_solve_ldl_comp.fypp0000664000175000017500000302021715135654166026772 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_solve) stdlib_lapack_solve_ldl_comp implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_ssycon( uplo, n, a, lda, ipiv, anorm, rcond, work,iwork, info ) !! SSYCON estimates the reciprocal of the condition number (in the !! 1-norm) of a real symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by SSYTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(sp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_slacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_ssytrs( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_ssycon pure module subroutine stdlib${ii}$_dsycon( uplo, n, a, lda, ipiv, anorm, rcond, work,iwork, info ) !! DSYCON estimates the reciprocal of the condition number (in the !! 1-norm) of a real symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by DSYTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(dp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_dlacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_dsytrs( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_dsycon #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sycon( uplo, n, a, lda, ipiv, anorm, rcond, work,iwork, info ) !! DSYCON: estimates the reciprocal of the condition number (in the !! 1-norm) of a real symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by DSYTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(${rk}$), intent(in) :: anorm real(${rk}$), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(${rk}$) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_${ri}$lacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_${ri}$sytrs( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_${ri}$sycon #:endif #:endfor pure module subroutine stdlib${ii}$_csycon( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) !! CSYCON estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by CSYTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(sp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_csytrs( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_csycon pure module subroutine stdlib${ii}$_zsycon( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) !! ZSYCON estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by ZSYTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(dp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_zsytrs( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_zsycon #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$sycon( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) !! ZSYCON: estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by ZSYTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(in) :: anorm real(${ck}$), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(${ck}$) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_${ci}$sytrs( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_${ci}$sycon #:endif #:endfor pure module subroutine stdlib${ii}$_ssytrf( uplo, n, a, lda, ipiv, work, lwork, info ) !! SSYTRF computes the factorization of a real symmetric matrix A using !! the Bunch-Kaufman diagonal pivoting method. The form of the !! factorization is !! A = U**T*D*U or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_slasyf( uplo, k, nb, kb, a, lda, ipiv, work, ldwork,iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_ssytf2( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_slasyf; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_slasyf( uplo, n-k+1, nb, kb, a( k, k ), lda, ipiv( k ),work, ldwork, & iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_ssytf2( uplo, n-k+1, a( k, k ), lda, ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_ssytrf pure module subroutine stdlib${ii}$_dsytrf( uplo, n, a, lda, ipiv, work, lwork, info ) !! DSYTRF computes the factorization of a real symmetric matrix A using !! the Bunch-Kaufman diagonal pivoting method. The form of the !! factorization is !! A = U**T*D*U or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_dlasyf( uplo, k, nb, kb, a, lda, ipiv, work, ldwork,iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_dsytf2( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_dlasyf; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_dlasyf( uplo, n-k+1, nb, kb, a( k, k ), lda, ipiv( k ),work, ldwork, & iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_dsytf2( uplo, n-k+1, a( k, k ), lda, ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dsytrf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sytrf( uplo, n, a, lda, ipiv, work, lwork, info ) !! DSYTRF: computes the factorization of a real symmetric matrix A using !! the Bunch-Kaufman diagonal pivoting method. The form of the !! factorization is !! A = U**T*D*U or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_${ri}$lasyf( uplo, k, nb, kb, a, lda, ipiv, work, ldwork,iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_${ri}$sytf2( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_${ri}$lasyf; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_${ri}$lasyf( uplo, n-k+1, nb, kb, a( k, k ), lda, ipiv( k ),work, ldwork, & iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_${ri}$sytf2( uplo, n-k+1, a( k, k ), lda, ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$sytrf #:endif #:endfor pure module subroutine stdlib${ii}$_csytrf( uplo, n, a, lda, ipiv, work, lwork, info ) !! CSYTRF computes the factorization of a complex symmetric matrix A !! using the Bunch-Kaufman diagonal pivoting method. The form of the !! factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_clasyf( uplo, k, nb, kb, a, lda, ipiv, work, n, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_csytf2( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_clasyf; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_clasyf( uplo, n-k+1, nb, kb, a( k, k ), lda, ipiv( k ),work, n, & iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_csytf2( uplo, n-k+1, a( k, k ), lda, ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_csytrf pure module subroutine stdlib${ii}$_zsytrf( uplo, n, a, lda, ipiv, work, lwork, info ) !! ZSYTRF computes the factorization of a complex symmetric matrix A !! using the Bunch-Kaufman diagonal pivoting method. The form of the !! factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_zlasyf( uplo, k, nb, kb, a, lda, ipiv, work, n, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_zsytf2( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_zlasyf; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_zlasyf( uplo, n-k+1, nb, kb, a( k, k ), lda, ipiv( k ),work, n, & iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_zsytf2( uplo, n-k+1, a( k, k ), lda, ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zsytrf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$sytrf( uplo, n, a, lda, ipiv, work, lwork, info ) !! ZSYTRF: computes the factorization of a complex symmetric matrix A !! using the Bunch-Kaufman diagonal pivoting method. The form of the !! factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_${ci}$lasyf( uplo, k, nb, kb, a, lda, ipiv, work, n, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_${ci}$sytf2( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_${ci}$lasyf; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_${ci}$lasyf( uplo, n-k+1, nb, kb, a( k, k ), lda, ipiv( k ),work, n, & iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_${ci}$sytf2( uplo, n-k+1, a( k, k ), lda, ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$sytrf #:endif #:endfor pure module subroutine stdlib${ii}$_slasyf( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) !! SLASYF computes a partial factorization of a real symmetric matrix A !! using the Bunch-Kaufman diagonal pivoting method. The partial !! factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! SLASYF is an auxiliary routine called by SSYTRF. It uses blocked code !! (calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or !! A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars integer(${ik}$) :: imax, j, jb, jj, jmax, jp, k, kk, kkw, kp, kstep, kw real(sp) :: absakk, alpha, colmax, d11, d21, d22, r1, rowmax, t ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 ! kw is the column of w which corresponds to column k of a k = n 10 continue kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_isamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = abs( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column kw-1 of w and update it call stdlib${ii}$_scopy( imax, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_scopy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then jmax = stdlib${ii}$_isamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) rowmax = max( rowmax, abs( w( jmax, kw-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( w( imax, kw-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column kw-1 of w to column kw of w call stdlib${ii}$_scopy( k, w( 1_${ik}$, kw-1 ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k - kstep + 1_${ik}$ ! kkw is the column of w which corresponds to column kk of a kkw = nb + kk - n ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kkw of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k-1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_scopy( kk-1-kp, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) if( kp>1_${ik}$ )call stdlib${ii}$_scopy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k2_${ik}$ ) then ! compose the columns of the inverse of 2-by-2 pivot ! block d in the following way to reduce the number ! of flops when we myltiply panel ( w(kw-1) w(kw) ) by ! this inverse ! d**(-1) = ( d11 d21 )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-d21**2) * ( ( d22 ) (-d21 ) ) = ! ( (-d21 ) ( d11 ) ) ! = 1/d21 * 1/((d11/d21)*(d22/d21)-1) * ! * ( ( d22/d21 ) ( -1 ) ) = ! ( ( -1 ) ( d11/d21 ) ) ! = 1/d21 * 1/(d22*d11-1) * ( ( d11 ) ( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = 1/d21 * t * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) ! = d21 * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) d21 = w( k-1, kw ) d11 = w( k, kw ) / d21 d22 = w( k-1, kw-1 ) / d21 t = one / ( d11*d22-one ) d21 = t / d21 ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = d21*( d11*w( j, kw-1 )-w( j, kw ) ) a( j, k ) = d21*( d22*w( j, kw )-w( j, kw-1 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_sgemv( 'NO TRANSPOSE', jj-j+1, n-k, -one,a( j, k+1 ), lda, w( jj, & kw+1 ), ldw, one,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k, -one,a( 1_${ik}$, k+1 ), & lda, w( j, kw+1 ), ldw, one,a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows jj and jp at each ! step j ! (here, j is a diagonal index) jj = j jp = ipiv( j ) if( jp<0_${ik}$ ) then jp = -jp ! (here, j is a diagonal index) j = j + 1_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp/=jj .and. j<=n )call stdlib${ii}$_sswap( n-j+1, a( jp, j ), lda, a( jj, j ), & lda ) if( j=nb .and. nbn )go to 90 ! copy column k of a to column k of w and update it call stdlib${ii}$_scopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ), lda,w( k, 1_${ik}$ ), ldw, & one, w( k, k ), 1_${ik}$ ) kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column k+1 of w and update it call stdlib${ii}$_scopy( imax-k, a( imax, k ), lda, w( k, k+1 ), 1_${ik}$ ) call stdlib${ii}$_scopy( n-imax+1, a( imax, imax ), 1_${ik}$, w( imax, k+1 ),1_${ik}$ ) call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ),lda, w( imax, & 1_${ik}$ ), ldw, one, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_isamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = abs( w( jmax, k+1 ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( w( imax, k+1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column k+1 of w to column k of w call stdlib${ii}$_scopy( n-k+1, w( k, k+1 ), 1_${ik}$, w( k, k ), 1_${ik}$ ) else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k + kstep - 1_${ik}$ ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_scopy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) if( kp1_${ik}$ )call stdlib${ii}$_sswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_sswap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) call stdlib${ii}$_scopy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=1_${ik}$ )call stdlib${ii}$_sswap( j, a( jp, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) if( j>1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_slasyf pure module subroutine stdlib${ii}$_dlasyf( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) !! DLASYF computes a partial factorization of a real symmetric matrix A !! using the Bunch-Kaufman diagonal pivoting method. The partial !! factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! DLASYF is an auxiliary routine called by DSYTRF. It uses blocked code !! (calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or !! A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(dp), parameter :: sevten = 17.0e+0_dp ! Local Scalars integer(${ik}$) :: imax, j, jb, jj, jmax, jp, k, kk, kkw, kp, kstep, kw real(dp) :: absakk, alpha, colmax, d11, d21, d22, r1, rowmax, t ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 ! kw is the column of w which corresponds to column k of a k = n 10 continue kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_idamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = abs( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column kw-1 of w and update it call stdlib${ii}$_dcopy( imax, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_dcopy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then jmax = stdlib${ii}$_idamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) rowmax = max( rowmax, abs( w( jmax, kw-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( w( imax, kw-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column kw-1 of w to column kw of w call stdlib${ii}$_dcopy( k, w( 1_${ik}$, kw-1 ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k - kstep + 1_${ik}$ ! kkw is the column of w which corresponds to column kk of a kkw = nb + kk - n ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kkw of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k-1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_dcopy( kk-1-kp, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) if( kp>1_${ik}$ )call stdlib${ii}$_dcopy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k2_${ik}$ ) then ! compose the columns of the inverse of 2-by-2 pivot ! block d in the following way to reduce the number ! of flops when we myltiply panel ( w(kw-1) w(kw) ) by ! this inverse ! d**(-1) = ( d11 d21 )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-d21**2) * ( ( d22 ) (-d21 ) ) = ! ( (-d21 ) ( d11 ) ) ! = 1/d21 * 1/((d11/d21)*(d22/d21)-1) * ! * ( ( d22/d21 ) ( -1 ) ) = ! ( ( -1 ) ( d11/d21 ) ) ! = 1/d21 * 1/(d22*d11-1) * ( ( d11 ) ( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = 1/d21 * t * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) ! = d21 * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) d21 = w( k-1, kw ) d11 = w( k, kw ) / d21 d22 = w( k-1, kw-1 ) / d21 t = one / ( d11*d22-one ) d21 = t / d21 ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = d21*( d11*w( j, kw-1 )-w( j, kw ) ) a( j, k ) = d21*( d22*w( j, kw )-w( j, kw-1 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_dgemv( 'NO TRANSPOSE', jj-j+1, n-k, -one,a( j, k+1 ), lda, w( jj, & kw+1 ), ldw, one,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k, -one,a( 1_${ik}$, k+1 ), & lda, w( j, kw+1 ), ldw, one,a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows jj and jp at each ! step j ! (here, j is a diagonal index) jj = j jp = ipiv( j ) if( jp<0_${ik}$ ) then jp = -jp ! (here, j is a diagonal index) j = j + 1_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp/=jj .and. j<=n )call stdlib${ii}$_dswap( n-j+1, a( jp, j ), lda, a( jj, j ), & lda ) if( j=nb .and. nbn )go to 90 ! copy column k of a to column k of w and update it call stdlib${ii}$_dcopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ), lda,w( k, 1_${ik}$ ), ldw, & one, w( k, k ), 1_${ik}$ ) kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column k+1 of w and update it call stdlib${ii}$_dcopy( imax-k, a( imax, k ), lda, w( k, k+1 ), 1_${ik}$ ) call stdlib${ii}$_dcopy( n-imax+1, a( imax, imax ), 1_${ik}$, w( imax, k+1 ),1_${ik}$ ) call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ),lda, w( imax, & 1_${ik}$ ), ldw, one, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_idamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = abs( w( jmax, k+1 ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( w( imax, k+1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column k+1 of w to column k of w call stdlib${ii}$_dcopy( n-k+1, w( k, k+1 ), 1_${ik}$, w( k, k ), 1_${ik}$ ) else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k + kstep - 1_${ik}$ ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_dcopy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) if( kp1_${ik}$ )call stdlib${ii}$_dswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_dswap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) call stdlib${ii}$_dcopy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=1_${ik}$ )call stdlib${ii}$_dswap( j, a( jp, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) if( j>1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_dlasyf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasyf( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) !! DLASYF: computes a partial factorization of a real symmetric matrix A !! using the Bunch-Kaufman diagonal pivoting method. The partial !! factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! DLASYF is an auxiliary routine called by DSYTRF. It uses blocked code !! (calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or !! A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: sevten = 17.0e+0_${rk}$ ! Local Scalars integer(${ik}$) :: imax, j, jb, jj, jmax, jp, k, kk, kkw, kp, kstep, kw real(${rk}$) :: absakk, alpha, colmax, d11, d21, d22, r1, rowmax, t ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 ! kw is the column of w which corresponds to column k of a k = n 10 continue kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_i${ri}$amax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = abs( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column kw-1 of w and update it call stdlib${ii}$_${ri}$copy( imax, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then jmax = stdlib${ii}$_i${ri}$amax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) rowmax = max( rowmax, abs( w( jmax, kw-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( w( imax, kw-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column kw-1 of w to column kw of w call stdlib${ii}$_${ri}$copy( k, w( 1_${ik}$, kw-1 ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k - kstep + 1_${ik}$ ! kkw is the column of w which corresponds to column kk of a kkw = nb + kk - n ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kkw of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k-1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_${ri}$copy( kk-1-kp, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) if( kp>1_${ik}$ )call stdlib${ii}$_${ri}$copy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k2_${ik}$ ) then ! compose the columns of the inverse of 2-by-2 pivot ! block d in the following way to reduce the number ! of flops when we myltiply panel ( w(kw-1) w(kw) ) by ! this inverse ! d**(-1) = ( d11 d21 )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-d21**2) * ( ( d22 ) (-d21 ) ) = ! ( (-d21 ) ( d11 ) ) ! = 1/d21 * 1/((d11/d21)*(d22/d21)-1) * ! * ( ( d22/d21 ) ( -1 ) ) = ! ( ( -1 ) ( d11/d21 ) ) ! = 1/d21 * 1/(d22*d11-1) * ( ( d11 ) ( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = 1/d21 * t * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) ! = d21 * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) d21 = w( k-1, kw ) d11 = w( k, kw ) / d21 d22 = w( k-1, kw-1 ) / d21 t = one / ( d11*d22-one ) d21 = t / d21 ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = d21*( d11*w( j, kw-1 )-w( j, kw ) ) a( j, k ) = d21*( d22*w( j, kw )-w( j, kw-1 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', jj-j+1, n-k, -one,a( j, k+1 ), lda, w( jj, & kw+1 ), ldw, one,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k, -one,a( 1_${ik}$, k+1 ), & lda, w( j, kw+1 ), ldw, one,a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows jj and jp at each ! step j ! (here, j is a diagonal index) jj = j jp = ipiv( j ) if( jp<0_${ik}$ ) then jp = -jp ! (here, j is a diagonal index) j = j + 1_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp/=jj .and. j<=n )call stdlib${ii}$_${ri}$swap( n-j+1, a( jp, j ), lda, a( jj, j ), & lda ) if( j=nb .and. nbn )go to 90 ! copy column k of a to column k of w and update it call stdlib${ii}$_${ri}$copy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ), lda,w( k, 1_${ik}$ ), ldw, & one, w( k, k ), 1_${ik}$ ) kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column k+1 of w and update it call stdlib${ii}$_${ri}$copy( imax-k, a( imax, k ), lda, w( k, k+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n-imax+1, a( imax, imax ), 1_${ik}$, w( imax, k+1 ),1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ),lda, w( imax, & 1_${ik}$ ), ldw, one, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_i${ri}$amax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = abs( w( jmax, k+1 ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( w( imax, k+1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column k+1 of w to column k of w call stdlib${ii}$_${ri}$copy( n-k+1, w( k, k+1 ), 1_${ik}$, w( k, k ), 1_${ik}$ ) else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k + kstep - 1_${ik}$ ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_${ri}$copy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) if( kp1_${ik}$ )call stdlib${ii}$_${ri}$swap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_${ri}$swap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) call stdlib${ii}$_${ri}$copy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=1_${ik}$ )call stdlib${ii}$_${ri}$swap( j, a( jp, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) if( j>1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_${ri}$lasyf #:endif #:endfor pure module subroutine stdlib${ii}$_clasyf( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) !! CLASYF computes a partial factorization of a complex symmetric matrix !! A using the Bunch-Kaufman diagonal pivoting method. The partial !! factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**T denotes the transpose of U. !! CLASYF is an auxiliary routine called by CSYTRF. It uses blocked code !! (calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or !! A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars integer(${ik}$) :: imax, j, jb, jj, jmax, jp, k, kk, kkw, kp, kstep, kw real(sp) :: absakk, alpha, colmax, rowmax complex(sp) :: d11, d21, d22, r1, t, z ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=sp) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 ! kw is the column of w which corresponds to column k of a k = n 10 continue kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column kw-1 of w and update it call stdlib${ii}$_ccopy( imax, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_ccopy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then jmax = stdlib${ii}$_icamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( w( jmax, kw-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( w( imax, kw-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column kw-1 of w to column kw of w call stdlib${ii}$_ccopy( k, w( 1_${ik}$, kw-1 ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k - kstep + 1_${ik}$ ! kkw is the column of w which corresponds to column kk of a kkw = nb + kk - n ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kkw of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k-1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_ccopy( kk-1-kp, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) if( kp>1_${ik}$ )call stdlib${ii}$_ccopy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k2_${ik}$ ) then ! compose the columns of the inverse of 2-by-2 pivot ! block d in the following way to reduce the number ! of flops when we myltiply panel ( w(kw-1) w(kw) ) by ! this inverse ! d**(-1) = ( d11 d21 )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-d21**2) * ( ( d22 ) (-d21 ) ) = ! ( (-d21 ) ( d11 ) ) ! = 1/d21 * 1/((d11/d21)*(d22/d21)-1) * ! * ( ( d22/d21 ) ( -1 ) ) = ! ( ( -1 ) ( d11/d21 ) ) ! = 1/d21 * 1/(d22*d11-1) * ( ( d11 ) ( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = 1/d21 * t * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) ! = d21 * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) d21 = w( k-1, kw ) d11 = w( k, kw ) / d21 d22 = w( k-1, kw-1 ) / d21 t = cone / ( d11*d22-cone ) ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) d21 = t / d21 do j = 1, k - 2 a( j, k-1 ) = d21*( d11*w( j, kw-1 )-w( j, kw ) ) a( j, k ) = d21*( d22*w( j, kw )-w( j, kw-1 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_cgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( 1_${ik}$, k+1 ), & lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows jj and jp at each ! step j ! (here, j is a diagonal index) jj = j jp = ipiv( j ) if( jp<0_${ik}$ ) then jp = -jp ! (here, j is a diagonal index) j = j + 1_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp/=jj .and. j<=n )call stdlib${ii}$_cswap( n-j+1, a( jp, j ), lda, a( jj, j ), & lda ) if( j=nb .and. nbn )go to 90 ! copy column k of a to column k of w and update it call stdlib${ii}$_ccopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ), lda,w( k, 1_${ik}$ ), ldw,& cone, w( k, k ), 1_${ik}$ ) kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column k+1 of w and update it call stdlib${ii}$_ccopy( imax-k, a( imax, k ), lda, w( k, k+1 ), 1_${ik}$ ) call stdlib${ii}$_ccopy( n-imax+1, a( imax, imax ), 1_${ik}$, w( imax, k+1 ),1_${ik}$ ) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( imax, & 1_${ik}$ ), ldw, cone, w( k, k+1 ),1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_icamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( w( imax, k+1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column k+1 of w to column k of w call stdlib${ii}$_ccopy( n-k+1, w( k, k+1 ), 1_${ik}$, w( k, k ), 1_${ik}$ ) else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k + kstep - 1_${ik}$ ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_ccopy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) if( kp1_${ik}$ )call stdlib${ii}$_cswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_cswap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) call stdlib${ii}$_ccopy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=1_${ik}$ )call stdlib${ii}$_cswap( j, a( jp, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) if( j>1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_clasyf pure module subroutine stdlib${ii}$_zlasyf( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) !! ZLASYF computes a partial factorization of a complex symmetric matrix !! A using the Bunch-Kaufman diagonal pivoting method. The partial !! factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**T denotes the transpose of U. !! ZLASYF is an auxiliary routine called by ZSYTRF. It uses blocked code !! (calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or !! A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(dp), parameter :: sevten = 17.0e+0_dp ! Local Scalars integer(${ik}$) :: imax, j, jb, jj, jmax, jp, k, kk, kkw, kp, kstep, kw real(dp) :: absakk, alpha, colmax, rowmax complex(dp) :: d11, d21, d22, r1, t, z ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=dp) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 ! kw is the column of w which corresponds to column k of a k = n 10 continue kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column kw-1 of w and update it call stdlib${ii}$_zcopy( imax, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_zcopy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then jmax = stdlib${ii}$_izamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( w( jmax, kw-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( w( imax, kw-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column kw-1 of w to column kw of w call stdlib${ii}$_zcopy( k, w( 1_${ik}$, kw-1 ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k - kstep + 1_${ik}$ ! kkw is the column of w which corresponds to column kk of a kkw = nb + kk - n ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kkw of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k-1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_zcopy( kk-1-kp, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) if( kp>1_${ik}$ )call stdlib${ii}$_zcopy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k2_${ik}$ ) then ! compose the columns of the inverse of 2-by-2 pivot ! block d in the following way to reduce the number ! of flops when we myltiply panel ( w(kw-1) w(kw) ) by ! this inverse ! d**(-1) = ( d11 d21 )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-d21**2) * ( ( d22 ) (-d21 ) ) = ! ( (-d21 ) ( d11 ) ) ! = 1/d21 * 1/((d11/d21)*(d22/d21)-1) * ! * ( ( d22/d21 ) ( -1 ) ) = ! ( ( -1 ) ( d11/d21 ) ) ! = 1/d21 * 1/(d22*d11-1) * ( ( d11 ) ( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = 1/d21 * t * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) ! = d21 * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) d21 = w( k-1, kw ) d11 = w( k, kw ) / d21 d22 = w( k-1, kw-1 ) / d21 t = cone / ( d11*d22-cone ) d21 = t / d21 ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = d21*( d11*w( j, kw-1 )-w( j, kw ) ) a( j, k ) = d21*( d22*w( j, kw )-w( j, kw-1 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_zgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( 1_${ik}$, k+1 ), & lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows jj and jp at each ! step j ! (here, j is a diagonal index) jj = j jp = ipiv( j ) if( jp<0_${ik}$ ) then jp = -jp ! (here, j is a diagonal index) j = j + 1_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp/=jj .and. j<=n )call stdlib${ii}$_zswap( n-j+1, a( jp, j ), lda, a( jj, j ), & lda ) if( j=nb .and. nbn )go to 90 ! copy column k of a to column k of w and update it call stdlib${ii}$_zcopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ), lda,w( k, 1_${ik}$ ), ldw,& cone, w( k, k ), 1_${ik}$ ) kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column k+1 of w and update it call stdlib${ii}$_zcopy( imax-k, a( imax, k ), lda, w( k, k+1 ), 1_${ik}$ ) call stdlib${ii}$_zcopy( n-imax+1, a( imax, imax ), 1_${ik}$, w( imax, k+1 ),1_${ik}$ ) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( imax, & 1_${ik}$ ), ldw, cone, w( k, k+1 ),1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_izamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( w( imax, k+1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column k+1 of w to column k of w call stdlib${ii}$_zcopy( n-k+1, w( k, k+1 ), 1_${ik}$, w( k, k ), 1_${ik}$ ) else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k + kstep - 1_${ik}$ ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_zcopy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) if( kp1_${ik}$ )call stdlib${ii}$_zswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_zswap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) call stdlib${ii}$_zcopy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=1_${ik}$ )call stdlib${ii}$_zswap( j, a( jp, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) if( j>1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_zlasyf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lasyf( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) !! ZLASYF: computes a partial factorization of a complex symmetric matrix !! A using the Bunch-Kaufman diagonal pivoting method. The partial !! factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**T denotes the transpose of U. !! ZLASYF is an auxiliary routine called by ZSYTRF. It uses blocked code !! (calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or !! A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: sevten = 17.0e+0_${ck}$ ! Local Scalars integer(${ik}$) :: imax, j, jb, jj, jmax, jp, k, kk, kkw, kp, kstep, kw real(${ck}$) :: absakk, alpha, colmax, rowmax complex(${ck}$) :: d11, d21, d22, r1, t, z ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=${ck}$) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 ! kw is the column of w which corresponds to column k of a k = n 10 continue kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column kw-1 of w and update it call stdlib${ii}$_${ci}$copy( imax, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$copy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then jmax = stdlib${ii}$_i${ci}$amax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( w( jmax, kw-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( w( imax, kw-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column kw-1 of w to column kw of w call stdlib${ii}$_${ci}$copy( k, w( 1_${ik}$, kw-1 ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k - kstep + 1_${ik}$ ! kkw is the column of w which corresponds to column kk of a kkw = nb + kk - n ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kkw of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k-1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_${ci}$copy( kk-1-kp, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) if( kp>1_${ik}$ )call stdlib${ii}$_${ci}$copy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k2_${ik}$ ) then ! compose the columns of the inverse of 2-by-2 pivot ! block d in the following way to reduce the number ! of flops when we myltiply panel ( w(kw-1) w(kw) ) by ! this inverse ! d**(-1) = ( d11 d21 )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-d21**2) * ( ( d22 ) (-d21 ) ) = ! ( (-d21 ) ( d11 ) ) ! = 1/d21 * 1/((d11/d21)*(d22/d21)-1) * ! * ( ( d22/d21 ) ( -1 ) ) = ! ( ( -1 ) ( d11/d21 ) ) ! = 1/d21 * 1/(d22*d11-1) * ( ( d11 ) ( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = 1/d21 * t * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) ! = d21 * ( ( d11 ) ( -1 ) ) ! ( ( -1 ) ( d22 ) ) d21 = w( k-1, kw ) d11 = w( k, kw ) / d21 d22 = w( k-1, kw-1 ) / d21 t = cone / ( d11*d22-cone ) d21 = t / d21 ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = d21*( d11*w( j, kw-1 )-w( j, kw ) ) a( j, k ) = d21*( d22*w( j, kw )-w( j, kw-1 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( 1_${ik}$, k+1 ), & lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows jj and jp at each ! step j ! (here, j is a diagonal index) jj = j jp = ipiv( j ) if( jp<0_${ik}$ ) then jp = -jp ! (here, j is a diagonal index) j = j + 1_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp/=jj .and. j<=n )call stdlib${ii}$_${ci}$swap( n-j+1, a( jp, j ), lda, a( jj, j ), & lda ) if( j=nb .and. nbn )go to 90 ! copy column k of a to column k of w and update it call stdlib${ii}$_${ci}$copy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ), lda,w( k, 1_${ik}$ ), ldw,& cone, w( k, k ), 1_${ik}$ ) kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! copy column imax to column k+1 of w and update it call stdlib${ii}$_${ci}$copy( imax-k, a( imax, k ), lda, w( k, k+1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$copy( n-imax+1, a( imax, imax ), 1_${ik}$, w( imax, k+1 ),1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( imax, & 1_${ik}$ ), ldw, cone, w( k, k+1 ),1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_i${ci}$amax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( w( imax, k+1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column k+1 of w to column k of w call stdlib${ii}$_${ci}$copy( n-k+1, w( k, k+1 ), 1_${ik}$, w( k, k ), 1_${ik}$ ) else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k + kstep - 1_${ik}$ ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = a( kk, kk ) call stdlib${ii}$_${ci}$copy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) if( kp1_${ik}$ )call stdlib${ii}$_${ci}$swap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$swap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) call stdlib${ii}$_${ci}$copy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=1_${ik}$ )call stdlib${ii}$_${ci}$swap( j, a( jp, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) if( j>1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_${ci}$lasyf #:endif #:endfor pure module subroutine stdlib${ii}$_ssytf2( uplo, n, a, lda, ipiv, info ) !! SSYTF2 computes the factorization of a real symmetric matrix A using !! the Bunch-Kaufman diagonal pivoting method: !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, U**T is the transpose of U, and D is symmetric and !! block diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, imax, j, jmax, k, kk, kp, kstep real(sp) :: absakk, alpha, colmax, d11, d12, d21, d22, r1, rowmax, t, wk, wkm1, & wkp1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ ) then imax = stdlib${ii}$_isamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = abs( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) .or. stdlib${ii}$_sisnan(absakk) ) then ! column k is zero or underflow, or contains a nan: ! set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = imax + stdlib${ii}$_isamax( k-imax, a( imax, imax+1 ), lda ) rowmax = abs( a( imax, jmax ) ) if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_isamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) rowmax = max( rowmax, abs( a( jmax, imax ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_sswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_sswap( kk-kp-1, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = one / a( k, k ) call stdlib${ii}$_ssyr( uplo, k-1, -r1, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_sscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = one / ( d11*d22-one ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*a( j, k-1 )-a( j, k ) ) wk = d12*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - a( i, k )*wk -a( i, k-1 )*wkm1 end do a( j, k ) = wk a( j, k-1 ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_isamax( imax-k, a( imax, k ), lda ) rowmax = abs( a( imax, jmax ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_idamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = abs( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) .or. stdlib${ii}$_disnan(absakk) ) then ! column k is zero or underflow, or contains a nan: ! set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = imax + stdlib${ii}$_idamax( k-imax, a( imax, imax+1 ), lda ) rowmax = abs( a( imax, jmax ) ) if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_idamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) rowmax = max( rowmax, abs( a( jmax, imax ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_dswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_dswap( kk-kp-1, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = one / a( k, k ) call stdlib${ii}$_dsyr( uplo, k-1, -r1, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_dscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = one / ( d11*d22-one ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*a( j, k-1 )-a( j, k ) ) wk = d12*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - a( i, k )*wk -a( i, k-1 )*wkm1 end do a( j, k ) = wk a( j, k-1 ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_idamax( imax-k, a( imax, k ), lda ) rowmax = abs( a( imax, jmax ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_i${ri}$amax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = abs( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) .or. stdlib${ii}$_${ri}$isnan(absakk) ) then ! column k is zero or underflow, or contains a nan: ! set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = imax + stdlib${ii}$_i${ri}$amax( k-imax, a( imax, imax+1 ), lda ) rowmax = abs( a( imax, jmax ) ) if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_i${ri}$amax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) rowmax = max( rowmax, abs( a( jmax, imax ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_${ri}$swap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_${ri}$swap( kk-kp-1, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = one / a( k, k ) call stdlib${ii}$_${ri}$syr( uplo, k-1, -r1, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_${ri}$scal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = one / ( d11*d22-one ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*a( j, k-1 )-a( j, k ) ) wk = d12*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - a( i, k )*wk -a( i, k-1 )*wkm1 end do a( j, k ) = wk a( j, k-1 ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_i${ri}$amax( imax-k, a( imax, k ), lda ) rowmax = abs( a( imax, jmax ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( max( absakk, colmax )==zero .or. stdlib${ii}$_sisnan(absakk) ) then ! column k is zero or underflow, or contains a nan: ! set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = imax + stdlib${ii}$_icamax( k-imax, a( imax, imax+1 ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_icamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( a( jmax, imax ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_cswap( kk-kp-1, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = cone / a( k, k ) call stdlib${ii}$_csyr( uplo, k-1, -r1, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_cscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = cone / ( d11*d22-cone ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*a( j, k-1 )-a( j, k ) ) wk = d12*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - a( i, k )*wk -a( i, k-1 )*wkm1 end do a( j, k ) = wk a( j, k-1 ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_icamax( imax-k, a( imax, k ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( max( absakk, colmax )==zero .or. stdlib${ii}$_disnan(absakk) ) then ! column k is zero or underflow, or contains a nan: ! set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = imax + stdlib${ii}$_izamax( k-imax, a( imax, imax+1 ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_izamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( a( jmax, imax ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_zswap( kk-kp-1, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = cone / a( k, k ) call stdlib${ii}$_zsyr( uplo, k-1, -r1, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_zscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = cone / ( d11*d22-cone ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*a( j, k-1 )-a( j, k ) ) wk = d12*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - a( i, k )*wk -a( i, k-1 )*wkm1 end do a( j, k ) = wk a( j, k-1 ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_izamax( imax-k, a( imax, k ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( max( absakk, colmax )==zero .or. stdlib${ii}$_${c2ri(ci)}$isnan(absakk) ) then ! column k is zero or underflow, or contains a nan: ! set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = imax + stdlib${ii}$_i${ci}$amax( k-imax, a( imax, imax+1 ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_i${ci}$amax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( a( jmax, imax ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_${ci}$swap( kk-kp-1, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = cone / a( k, k ) call stdlib${ii}$_${ci}$syr( uplo, k-1, -r1, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_${ci}$scal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = cone / ( d11*d22-cone ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*a( j, k-1 )-a( j, k ) ) wk = d12*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - a( i, k )*wk -a( i, k-1 )*wkm1 end do a( j, k ) = wk a( j, k-1 ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_i${ci}$amax( imax-k, a( imax, k ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( a( imax, imax ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_sger( k-1, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_sscal( nrhs, one / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_sswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_sger( k-2, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_sger( k-2, nrhs, -one, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_sgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, a( 1_${ik}$, k ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_sgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, a( 1_${ik}$, k ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) call stdlib${ii}$_sgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb,a( 1_${ik}$, k+1 ), 1_${ik}$, one, b( & k+1, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_dger( k-1, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_dscal( nrhs, one / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_dswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_dger( k-2, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_dger( k-2, nrhs, -one, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_dgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, a( 1_${ik}$, k ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_dgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, a( 1_${ik}$, k ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) call stdlib${ii}$_dgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb,a( 1_${ik}$, k+1 ), 1_${ik}$, one, b( & k+1, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ri}$ger( k-1, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_${ri}$scal( nrhs, one / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_${ri}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_${ri}$ger( k-2, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ri}$ger( k-2, nrhs, -one, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, a( 1_${ik}$, k ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, a( 1_${ik}$, k ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb,a( 1_${ik}$, k+1 ), 1_${ik}$, one, b( & k+1, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_cgeru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_cscal( nrhs, cone / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_cswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_cgeru( k-2, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) call stdlib${ii}$_cgeru( k-2, nrhs, -cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_cgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, a( 1_${ik}$, k ),1_${ik}$, cone, b( & k, 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_cgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, a( 1_${ik}$, k ),1_${ik}$, cone, b( & k, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb,a( 1_${ik}$, k+1 ), 1_${ik}$, cone, b(& k+1, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_zgeru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_zscal( nrhs, cone / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_zswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_zgeru( k-2, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) call stdlib${ii}$_zgeru( k-2, nrhs, -cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_zgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, a( 1_${ik}$, k ),1_${ik}$, cone, b( & k, 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_zgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, a( 1_${ik}$, k ),1_${ik}$, cone, b( & k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb,a( 1_${ik}$, k+1 ), 1_${ik}$, cone, b(& k+1, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ci}$geru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_${ci}$scal( nrhs, cone / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_${ci}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_${ci}$geru( k-2, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) call stdlib${ii}$_${ci}$geru( k-2, nrhs, -cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ci}$gemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, a( 1_${ik}$, k ),1_${ik}$, cone, b( & k, 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_${ci}$gemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, a( 1_${ik}$, k ),1_${ik}$, cone, b( & k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb,a( 1_${ik}$, k+1 ), 1_${ik}$, cone, b(& k+1, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0 .and. a( info, info )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==zero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_scopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_ssymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_sdot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_scopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_ssymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_sdot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_sdot( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_scopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_ssymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_sdot( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) call stdlib${ii}$_sswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_sswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp if( kstep==2_${ik}$ ) then temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if end if k = k + kstep go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k0 .and. a( info, info )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==zero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_dcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dsymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_ddot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_dcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dsymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_ddot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_ddot( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_dcopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dsymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_ddot( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) call stdlib${ii}$_dswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_dswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp if( kstep==2_${ik}$ ) then temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if end if k = k + kstep go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k0 .and. a( info, info )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==zero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$symv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_${ri}$dot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$symv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_${ri}$dot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_${ri}$dot( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$symv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_${ri}$dot( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) call stdlib${ii}$_${ri}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_${ri}$swap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp if( kstep==2_${ik}$ ) then temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if end if k = k + kstep go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_csymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_cdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = a( k, k+1 ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-cone ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_csymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_cdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_cdotu( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_csymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_cdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_cswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp if( kstep==2_${ik}$ ) then temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if end if k = k + kstep go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zsymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_zdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = a( k, k+1 ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-cone ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zsymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_zdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_zdotu( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zsymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_zdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_zswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp if( kstep==2_${ik}$ ) then temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if end if k = k + kstep go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$symv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_${ci}$dotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = a( k, k+1 ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-cone ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$symv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_${ci}$dotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_${ci}$dotu( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$symv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_${ci}$dotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_${ci}$swap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp if( kstep==2_${ik}$ ) then temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if end if k = k + kstep go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( ksafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_ssytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) call stdlib${ii}$_saxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_slacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_slacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_ssytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_ssytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_ssyrfs pure module subroutine stdlib${ii}$_dsyrfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! DSYRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite, and !! provides error bounds and backward error estimates for the solution. berr, work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) real(dp), intent(out) :: berr(*), ferr(*), work(*) real(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_dsytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) call stdlib${ii}$_daxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_dlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_dlacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_dsytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_dsytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_dsyrfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$syrfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! DSYRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite, and !! provides error bounds and backward error estimates for the solution. berr, work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) real(${rk}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(${rk}$) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ri}$sytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) call stdlib${ii}$_${ri}$axpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ri}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ri}$lacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_${ri}$sytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_${ri}$sytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ri}$syrfs #:endif #:endfor pure module subroutine stdlib${ii}$_csyrfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! CSYRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite, and !! provides error bounds and backward error estimates for the solution. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_csytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) call stdlib${ii}$_caxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_csytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_csytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_csyrfs pure module subroutine stdlib${ii}$_zsyrfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! ZSYRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite, and !! provides error bounds and backward error estimates for the solution. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_zsytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) call stdlib${ii}$_zaxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_zsytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_zsytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_zsyrfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$syrfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! ZSYRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite, and !! provides error bounds and backward error estimates for the solution. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ci}$sytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) call stdlib${ii}$_${ci}$axpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_${ci}$sytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$sytrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ci}$syrfs #:endif #:endfor pure module subroutine stdlib${ii}$_ssyequb( uplo, n, a, lda, s, scond, amax, work, info ) !! SSYEQUB computes row and column scalings intended to equilibrate a !! symmetric matrix A (with respect to the Euclidean norm) and reduce !! its condition number. The scale factors S are computed by the BIN !! algorithm (see references) so that the scaled matrix B with elements !! B(i,j) = S(i)*A(i,j)*S(j) has a condition number within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(sp), intent(out) :: amax, scond character, intent(in) :: uplo ! Array Arguments real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: s(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: max_iter = 100_${ik}$ ! Local Scalars integer(${ik}$) :: i, j, iter real(sp) :: avg, std, tol, c0, c1, c2, t, u, si, d, base, smin, smax, smlnum, bignum, & scale, sumsq logical(lk) :: up ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not. ( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) ) then info = -1_${ik}$ else if ( n < 0_${ik}$ ) then info = -2_${ik}$ else if ( lda < max( 1_${ik}$, n ) ) then info = -4_${ik}$ end if if ( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSYEQUB', -info ) return end if up = stdlib_lsame( uplo, 'U' ) amax = zero ! quick return if possible. if ( n == 0_${ik}$ ) then scond = one return end if do i = 1, n s( i ) = zero end do amax = zero if ( up ) then do j = 1, n do i = 1, j-1 s( i ) = max( s( i ), abs( a( i, j ) ) ) s( j ) = max( s( j ), abs( a( i, j ) ) ) amax = max( amax, abs( a( i, j ) ) ) end do s( j ) = max( s( j ), abs( a( j, j ) ) ) amax = max( amax, abs( a( j, j ) ) ) end do else do j = 1, n s( j ) = max( s( j ), abs( a( j, j ) ) ) amax = max( amax, abs( a( j, j ) ) ) do i = j+1, n s( i ) = max( s( i ), abs( a( i, j ) ) ) s( j ) = max( s( j ), abs( a( i, j ) ) ) amax = max( amax, abs( a( i, j ) ) ) end do end do end if do j = 1, n s( j ) = one / s( j ) end do tol = one / sqrt( two * n ) do iter = 1, max_iter scale = zero sumsq = zero ! beta = |a|s do i = 1, n work( i ) = zero end do if ( up ) then do j = 1, n do i = 1, j-1 work( i ) = work( i ) + abs( a( i, j ) ) * s( j ) work( j ) = work( j ) + abs( a( i, j ) ) * s( i ) end do work( j ) = work( j ) + abs( a( j, j ) ) * s( j ) end do else do j = 1, n work( j ) = work( j ) + abs( a( j, j ) ) * s( j ) do i = j+1, n work( i ) = work( i ) + abs( a( i, j ) ) * s( j ) work( j ) = work( j ) + abs( a( i, j ) ) * s( i ) end do end do end if ! avg = s^t beta / n avg = zero do i = 1, n avg = avg + s( i )*work( i ) end do avg = avg / n std = zero do i = n+1, 2*n work( i ) = s( i-n ) * work( i-n ) - avg end do call stdlib${ii}$_slassq( n, work( n+1 ), 1_${ik}$, scale, sumsq ) std = scale * sqrt( sumsq / n ) if ( std < tol * avg ) goto 999 do i = 1, n t = abs( a( i, i ) ) si = s( i ) c2 = ( n-1 ) * t c1 = ( n-2 ) * ( work( i ) - t*si ) c0 = -(t*si)*si + 2_${ik}$*work( i )*si - n*avg d = c1*c1 - 4_${ik}$*c0*c2 if ( d <= 0_${ik}$ ) then info = -1_${ik}$ return end if si = -2_${ik}$*c0 / ( c1 + sqrt( d ) ) d = si - s( i ) u = zero if ( up ) then do j = 1, i t = abs( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = abs( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do else do j = 1, i t = abs( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = abs( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do end if avg = avg + ( u + work( i ) ) * d / n s( i ) = si end do end do 999 continue smlnum = stdlib${ii}$_slamch( 'SAFEMIN' ) bignum = one / smlnum smin = bignum smax = zero t = one / sqrt( avg ) base = stdlib${ii}$_slamch( 'B' ) u = one / log( base ) do i = 1, n s( i ) = base ** int( u * log( s( i ) * t ),KIND=${ik}$) smin = min( smin, s( i ) ) smax = max( smax, s( i ) ) end do scond = max( smin, smlnum ) / min( smax, bignum ) end subroutine stdlib${ii}$_ssyequb pure module subroutine stdlib${ii}$_dsyequb( uplo, n, a, lda, s, scond, amax, work, info ) !! DSYEQUB computes row and column scalings intended to equilibrate a !! symmetric matrix A (with respect to the Euclidean norm) and reduce !! its condition number. The scale factors S are computed by the BIN !! algorithm (see references) so that the scaled matrix B with elements !! B(i,j) = S(i)*A(i,j)*S(j) has a condition number within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(dp), intent(out) :: amax, scond character, intent(in) :: uplo ! Array Arguments real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: s(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: max_iter = 100_${ik}$ ! Local Scalars integer(${ik}$) :: i, j, iter real(dp) :: avg, std, tol, c0, c1, c2, t, u, si, d, base, smin, smax, smlnum, bignum, & scale, sumsq logical(lk) :: up ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not. ( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) ) then info = -1_${ik}$ else if ( n < 0_${ik}$ ) then info = -2_${ik}$ else if ( lda < max( 1_${ik}$, n ) ) then info = -4_${ik}$ end if if ( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSYEQUB', -info ) return end if up = stdlib_lsame( uplo, 'U' ) amax = zero ! quick return if possible. if ( n == 0_${ik}$ ) then scond = one return end if do i = 1, n s( i ) = zero end do amax = zero if ( up ) then do j = 1, n do i = 1, j-1 s( i ) = max( s( i ), abs( a( i, j ) ) ) s( j ) = max( s( j ), abs( a( i, j ) ) ) amax = max( amax, abs( a( i, j ) ) ) end do s( j ) = max( s( j ), abs( a( j, j ) ) ) amax = max( amax, abs( a( j, j ) ) ) end do else do j = 1, n s( j ) = max( s( j ), abs( a( j, j ) ) ) amax = max( amax, abs( a( j, j ) ) ) do i = j+1, n s( i ) = max( s( i ), abs( a( i, j ) ) ) s( j ) = max( s( j ), abs( a( i, j ) ) ) amax = max( amax, abs( a( i, j ) ) ) end do end do end if do j = 1, n s( j ) = one / s( j ) end do tol = one / sqrt( two * n ) do iter = 1, max_iter scale = zero sumsq = zero ! beta = |a|s do i = 1, n work( i ) = zero end do if ( up ) then do j = 1, n do i = 1, j-1 work( i ) = work( i ) + abs( a( i, j ) ) * s( j ) work( j ) = work( j ) + abs( a( i, j ) ) * s( i ) end do work( j ) = work( j ) + abs( a( j, j ) ) * s( j ) end do else do j = 1, n work( j ) = work( j ) + abs( a( j, j ) ) * s( j ) do i = j+1, n work( i ) = work( i ) + abs( a( i, j ) ) * s( j ) work( j ) = work( j ) + abs( a( i, j ) ) * s( i ) end do end do end if ! avg = s^t beta / n avg = zero do i = 1, n avg = avg + s( i )*work( i ) end do avg = avg / n std = zero do i = n+1, 2*n work( i ) = s( i-n ) * work( i-n ) - avg end do call stdlib${ii}$_dlassq( n, work( n+1 ), 1_${ik}$, scale, sumsq ) std = scale * sqrt( sumsq / n ) if ( std < tol * avg ) goto 999 do i = 1, n t = abs( a( i, i ) ) si = s( i ) c2 = ( n-1 ) * t c1 = ( n-2 ) * ( work( i ) - t*si ) c0 = -(t*si)*si + 2_${ik}$*work( i )*si - n*avg d = c1*c1 - 4_${ik}$*c0*c2 if ( d <= 0_${ik}$ ) then info = -1_${ik}$ return end if si = -2_${ik}$*c0 / ( c1 + sqrt( d ) ) d = si - s( i ) u = zero if ( up ) then do j = 1, i t = abs( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = abs( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do else do j = 1, i t = abs( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = abs( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do end if avg = avg + ( u + work( i ) ) * d / n s( i ) = si end do end do 999 continue smlnum = stdlib${ii}$_dlamch( 'SAFEMIN' ) bignum = one / smlnum smin = bignum smax = zero t = one / sqrt( avg ) base = stdlib${ii}$_dlamch( 'B' ) u = one / log( base ) do i = 1, n s( i ) = base ** int( u * log( s( i ) * t ),KIND=${ik}$) smin = min( smin, s( i ) ) smax = max( smax, s( i ) ) end do scond = max( smin, smlnum ) / min( smax, bignum ) end subroutine stdlib${ii}$_dsyequb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$syequb( uplo, n, a, lda, s, scond, amax, work, info ) !! DSYEQUB: computes row and column scalings intended to equilibrate a !! symmetric matrix A (with respect to the Euclidean norm) and reduce !! its condition number. The scale factors S are computed by the BIN !! algorithm (see references) so that the scaled matrix B with elements !! B(i,j) = S(i)*A(i,j)*S(j) has a condition number within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(${rk}$), intent(out) :: amax, scond character, intent(in) :: uplo ! Array Arguments real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: s(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: max_iter = 100_${ik}$ ! Local Scalars integer(${ik}$) :: i, j, iter real(${rk}$) :: avg, std, tol, c0, c1, c2, t, u, si, d, base, smin, smax, smlnum, bignum, & scale, sumsq logical(lk) :: up ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not. ( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) ) then info = -1_${ik}$ else if ( n < 0_${ik}$ ) then info = -2_${ik}$ else if ( lda < max( 1_${ik}$, n ) ) then info = -4_${ik}$ end if if ( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSYEQUB', -info ) return end if up = stdlib_lsame( uplo, 'U' ) amax = zero ! quick return if possible. if ( n == 0_${ik}$ ) then scond = one return end if do i = 1, n s( i ) = zero end do amax = zero if ( up ) then do j = 1, n do i = 1, j-1 s( i ) = max( s( i ), abs( a( i, j ) ) ) s( j ) = max( s( j ), abs( a( i, j ) ) ) amax = max( amax, abs( a( i, j ) ) ) end do s( j ) = max( s( j ), abs( a( j, j ) ) ) amax = max( amax, abs( a( j, j ) ) ) end do else do j = 1, n s( j ) = max( s( j ), abs( a( j, j ) ) ) amax = max( amax, abs( a( j, j ) ) ) do i = j+1, n s( i ) = max( s( i ), abs( a( i, j ) ) ) s( j ) = max( s( j ), abs( a( i, j ) ) ) amax = max( amax, abs( a( i, j ) ) ) end do end do end if do j = 1, n s( j ) = one / s( j ) end do tol = one / sqrt( two * n ) do iter = 1, max_iter scale = zero sumsq = zero ! beta = |a|s do i = 1, n work( i ) = zero end do if ( up ) then do j = 1, n do i = 1, j-1 work( i ) = work( i ) + abs( a( i, j ) ) * s( j ) work( j ) = work( j ) + abs( a( i, j ) ) * s( i ) end do work( j ) = work( j ) + abs( a( j, j ) ) * s( j ) end do else do j = 1, n work( j ) = work( j ) + abs( a( j, j ) ) * s( j ) do i = j+1, n work( i ) = work( i ) + abs( a( i, j ) ) * s( j ) work( j ) = work( j ) + abs( a( i, j ) ) * s( i ) end do end do end if ! avg = s^t beta / n avg = zero do i = 1, n avg = avg + s( i )*work( i ) end do avg = avg / n std = zero do i = n+1, 2*n work( i ) = s( i-n ) * work( i-n ) - avg end do call stdlib${ii}$_${ri}$lassq( n, work( n+1 ), 1_${ik}$, scale, sumsq ) std = scale * sqrt( sumsq / n ) if ( std < tol * avg ) goto 999 do i = 1, n t = abs( a( i, i ) ) si = s( i ) c2 = ( n-1 ) * t c1 = ( n-2 ) * ( work( i ) - t*si ) c0 = -(t*si)*si + 2_${ik}$*work( i )*si - n*avg d = c1*c1 - 4_${ik}$*c0*c2 if ( d <= 0_${ik}$ ) then info = -1_${ik}$ return end if si = -2_${ik}$*c0 / ( c1 + sqrt( d ) ) d = si - s( i ) u = zero if ( up ) then do j = 1, i t = abs( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = abs( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do else do j = 1, i t = abs( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = abs( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do end if avg = avg + ( u + work( i ) ) * d / n s( i ) = si end do end do 999 continue smlnum = stdlib${ii}$_${ri}$lamch( 'SAFEMIN' ) bignum = one / smlnum smin = bignum smax = zero t = one / sqrt( avg ) base = stdlib${ii}$_${ri}$lamch( 'B' ) u = one / log( base ) do i = 1, n s( i ) = base ** int( u * log( s( i ) * t ),KIND=${ik}$) smin = min( smin, s( i ) ) smax = max( smax, s( i ) ) end do scond = max( smin, smlnum ) / min( smax, bignum ) end subroutine stdlib${ii}$_${ri}$syequb #:endif #:endfor pure module subroutine stdlib${ii}$_csyequb( uplo, n, a, lda, s, scond, amax, work, info ) !! CSYEQUB computes row and column scalings intended to equilibrate a !! symmetric matrix A (with respect to the Euclidean norm) and reduce !! its condition number. The scale factors S are computed by the BIN !! algorithm (see references) so that the scaled matrix B with elements !! B(i,j) = S(i)*A(i,j)*S(j) has a condition number within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(sp), intent(out) :: amax, scond character, intent(in) :: uplo ! Array Arguments complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) real(sp), intent(out) :: s(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: max_iter = 100_${ik}$ ! Local Scalars integer(${ik}$) :: i, j, iter real(sp) :: avg, std, tol, c0, c1, c2, t, u, si, d, base, smin, smax, smlnum, bignum, & scale, sumsq logical(lk) :: up complex(sp) :: zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not. ( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) ) then info = -1_${ik}$ else if ( n < 0_${ik}$ ) then info = -2_${ik}$ else if ( lda < max( 1_${ik}$, n ) ) then info = -4_${ik}$ end if if ( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CSYEQUB', -info ) return end if up = stdlib_lsame( uplo, 'U' ) amax = zero ! quick return if possible. if ( n == 0_${ik}$ ) then scond = one return end if do i = 1, n s( i ) = zero end do amax = zero if ( up ) then do j = 1, n do i = 1, j-1 s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) end do else do j = 1, n s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) do i = j+1, n s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do end do end if do j = 1, n s( j ) = one / s( j ) end do tol = one / sqrt( two * n ) do iter = 1, max_iter scale = zero sumsq = zero ! beta = |a|s do i = 1, n work( i ) = zero end do if ( up ) then do j = 1, n do i = 1, j-1 work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) end do else do j = 1, n work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) do i = j+1, n work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do end do end if ! avg = s^t beta / n avg = zero do i = 1, n avg = avg + real( s( i )*work( i ),KIND=sp) end do avg = avg / n std = zero do i = n+1, 2*n work( i ) = s( i-n ) * work( i-n ) - avg end do call stdlib${ii}$_classq( n, work( n+1 ), 1_${ik}$, scale, sumsq ) std = scale * sqrt( sumsq / n ) if ( std < tol * avg ) goto 999 do i = 1, n t = cabs1( a( i, i ) ) si = s( i ) c2 = ( n-1 ) * t c1 = real( n-2,KIND=sp) * ( real( work( i ),KIND=sp) - t*si ) c0 = -(t*si)*si + 2_${ik}$ * real( work( i ),KIND=sp) * si - n*avg d = c1*c1 - 4_${ik}$*c0*c2 if ( d <= 0_${ik}$ ) then info = -1_${ik}$ return end if si = -2_${ik}$*c0 / ( c1 + sqrt( d ) ) d = si - s( i ) u = zero if ( up ) then do j = 1, i t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do else do j = 1, i t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do end if avg = avg + ( u + real( work( i ),KIND=sp) ) * d / n s( i ) = si end do end do 999 continue smlnum = stdlib${ii}$_slamch( 'SAFEMIN' ) bignum = one / smlnum smin = bignum smax = zero t = one / sqrt( avg ) base = stdlib${ii}$_slamch( 'B' ) u = one / log( base ) do i = 1, n s( i ) = base ** int( u * log( s( i ) * t ),KIND=${ik}$) smin = min( smin, s( i ) ) smax = max( smax, s( i ) ) end do scond = max( smin, smlnum ) / min( smax, bignum ) end subroutine stdlib${ii}$_csyequb pure module subroutine stdlib${ii}$_zsyequb( uplo, n, a, lda, s, scond, amax, work, info ) !! ZSYEQUB computes row and column scalings intended to equilibrate a !! symmetric matrix A (with respect to the Euclidean norm) and reduce !! its condition number. The scale factors S are computed by the BIN !! algorithm (see references) so that the scaled matrix B with elements !! B(i,j) = S(i)*A(i,j)*S(j) has a condition number within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(dp), intent(out) :: amax, scond character, intent(in) :: uplo ! Array Arguments complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) real(dp), intent(out) :: s(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: max_iter = 100_${ik}$ ! Local Scalars integer(${ik}$) :: i, j, iter real(dp) :: avg, std, tol, c0, c1, c2, t, u, si, d, base, smin, smax, smlnum, bignum, & scale, sumsq logical(lk) :: up complex(dp) :: zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not. ( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) ) then info = -1_${ik}$ else if ( n < 0_${ik}$ ) then info = -2_${ik}$ else if ( lda < max( 1_${ik}$, n ) ) then info = -4_${ik}$ end if if ( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZSYEQUB', -info ) return end if up = stdlib_lsame( uplo, 'U' ) amax = zero ! quick return if possible. if ( n == 0_${ik}$ ) then scond = one return end if do i = 1, n s( i ) = zero end do amax = zero if ( up ) then do j = 1, n do i = 1, j-1 s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) end do else do j = 1, n s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) do i = j+1, n s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do end do end if do j = 1, n s( j ) = one / s( j ) end do tol = one / sqrt( two * n ) do iter = 1, max_iter scale = zero sumsq = zero ! beta = |a|s do i = 1, n work( i ) = zero end do if ( up ) then do j = 1, n do i = 1, j-1 work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) end do else do j = 1, n work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) do i = j+1, n work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do end do end if ! avg = s^t beta / n avg = zero do i = 1, n avg = avg + s( i ) * real( work( i ),KIND=dp) end do avg = avg / n std = zero do i = n+1, 2*n work( i ) = s( i-n ) * work( i-n ) - avg end do call stdlib${ii}$_zlassq( n, work( n+1 ), 1_${ik}$, scale, sumsq ) std = scale * sqrt( sumsq / n ) if ( std < tol * avg ) goto 999 do i = 1, n t = cabs1( a( i, i ) ) si = s( i ) c2 = ( n-1 ) * t c1 = ( n-2 ) * ( real( work( i ),KIND=dp) - t*si ) c0 = -(t*si)*si + 2_${ik}$ * real( work( i ),KIND=dp) * si - n*avg d = c1*c1 - 4_${ik}$*c0*c2 if ( d <= 0_${ik}$ ) then info = -1_${ik}$ return end if si = -2_${ik}$*c0 / ( c1 + sqrt( d ) ) d = si - s( i ) u = zero if ( up ) then do j = 1, i t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do else do j = 1, i t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do end if avg = avg + ( u + real( work( i ),KIND=dp) ) * d / n s( i ) = si end do end do 999 continue smlnum = stdlib${ii}$_dlamch( 'SAFEMIN' ) bignum = one / smlnum smin = bignum smax = zero t = one / sqrt( avg ) base = stdlib${ii}$_dlamch( 'B' ) u = one / log( base ) do i = 1, n s( i ) = base ** int( u * log( s( i ) * t ),KIND=${ik}$) smin = min( smin, s( i ) ) smax = max( smax, s( i ) ) end do scond = max( smin, smlnum ) / min( smax, bignum ) end subroutine stdlib${ii}$_zsyequb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$syequb( uplo, n, a, lda, s, scond, amax, work, info ) !! ZSYEQUB: computes row and column scalings intended to equilibrate a !! symmetric matrix A (with respect to the Euclidean norm) and reduce !! its condition number. The scale factors S are computed by the BIN !! algorithm (see references) so that the scaled matrix B with elements !! B(i,j) = S(i)*A(i,j)*S(j) has a condition number within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(out) :: amax, scond character, intent(in) :: uplo ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) real(${ck}$), intent(out) :: s(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: max_iter = 100_${ik}$ ! Local Scalars integer(${ik}$) :: i, j, iter real(${ck}$) :: avg, std, tol, c0, c1, c2, t, u, si, d, base, smin, smax, smlnum, bignum, & scale, sumsq logical(lk) :: up complex(${ck}$) :: zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not. ( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) ) then info = -1_${ik}$ else if ( n < 0_${ik}$ ) then info = -2_${ik}$ else if ( lda < max( 1_${ik}$, n ) ) then info = -4_${ik}$ end if if ( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZSYEQUB', -info ) return end if up = stdlib_lsame( uplo, 'U' ) amax = zero ! quick return if possible. if ( n == 0_${ik}$ ) then scond = one return end if do i = 1, n s( i ) = zero end do amax = zero if ( up ) then do j = 1, n do i = 1, j-1 s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) end do else do j = 1, n s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) do i = j+1, n s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do end do end if do j = 1, n s( j ) = one / s( j ) end do tol = one / sqrt( two * n ) do iter = 1, max_iter scale = zero sumsq = zero ! beta = |a|s do i = 1, n work( i ) = zero end do if ( up ) then do j = 1, n do i = 1, j-1 work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) end do else do j = 1, n work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) do i = j+1, n work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do end do end if ! avg = s^t beta / n avg = zero do i = 1, n avg = avg + s( i ) * real( work( i ),KIND=${ck}$) end do avg = avg / n std = zero do i = n+1, 2*n work( i ) = s( i-n ) * work( i-n ) - avg end do call stdlib${ii}$_${ci}$lassq( n, work( n+1 ), 1_${ik}$, scale, sumsq ) std = scale * sqrt( sumsq / n ) if ( std < tol * avg ) goto 999 do i = 1, n t = cabs1( a( i, i ) ) si = s( i ) c2 = ( n-1 ) * t c1 = ( n-2 ) * ( real( work( i ),KIND=${ck}$) - t*si ) c0 = -(t*si)*si + 2_${ik}$ * real( work( i ),KIND=${ck}$) * si - n*avg d = c1*c1 - 4_${ik}$*c0*c2 if ( d <= 0_${ik}$ ) then info = -1_${ik}$ return end if si = -2_${ik}$*c0 / ( c1 + sqrt( d ) ) d = si - s( i ) u = zero if ( up ) then do j = 1, i t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do else do j = 1, i t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do end if avg = avg + ( u + real( work( i ),KIND=${ck}$) ) * d / n s( i ) = si end do end do 999 continue smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFEMIN' ) bignum = one / smlnum smin = bignum smax = zero t = one / sqrt( avg ) base = stdlib${ii}$_${c2ri(ci)}$lamch( 'B' ) u = one / log( base ) do i = 1, n s( i ) = base ** int( u * log( s( i ) * t ),KIND=${ik}$) smin = min( smin, s( i ) ) smax = max( smax, s( i ) ) end do scond = max( smin, smlnum ) / min( smax, bignum ) end subroutine stdlib${ii}$_${ci}$syequb #:endif #:endfor pure module subroutine stdlib${ii}$_ssyconv( uplo, way, n, a, lda, ipiv, e, info ) !! SSYCONV convert A given by TRF into L and D and vice-versa. !! Get Non-diag elements of D (returned in workspace) and !! apply or reverse permutation done in TRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, j real(sp) :: temp ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda 1 ) if( ipiv(i) < 0_${ik}$ ) then e(i)=a(i-1,i) e(i-1)=zero a(i-1,i)=zero i=i-1 else e(i)=zero endif i=i-1 end do ! convert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif i=i-1 endif i=i-1 end do else ! revert a (a is upper) ! revert permutations i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) i=i+1 if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif endif i=i+1 end do ! revert value i=n do while ( i > 1 ) if( ipiv(i) < 0_${ik}$ ) then a(i-1,i)=e(i) i=i-1 endif i=i-1 end do end if else ! a is lower if ( convert ) then ! convert a (a is lower) ! convert value i=1_${ik}$ e(n)=zero do while ( i <= n ) if( i 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i+1,j) a(i+1,j)=temp end do endif i=i+1 endif i=i+1 end do else ! revert a (a is lower) ! revert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i,j) a(i,j)=a(ip,j) a(ip,j)=temp end do endif else ip=-ipiv(i) i=i-1 if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i+1,j) a(i+1,j)=a(ip,j) a(ip,j)=temp end do endif endif i=i-1 end do ! revert value i=1_${ik}$ do while ( i <= n-1 ) if( ipiv(i) < 0_${ik}$ ) then a(i+1,i)=e(i) i=i+1 endif i=i+1 end do end if end if return end subroutine stdlib${ii}$_ssyconv pure module subroutine stdlib${ii}$_dsyconv( uplo, way, n, a, lda, ipiv, e, info ) !! DSYCONV convert A given by TRF into L and D and vice-versa. !! Get Non-diag elements of D (returned in workspace) and !! apply or reverse permutation done in TRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, j real(dp) :: temp ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda 1 ) if( ipiv(i) < 0_${ik}$ ) then e(i)=a(i-1,i) e(i-1)=zero a(i-1,i)=zero i=i-1 else e(i)=zero endif i=i-1 end do ! convert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif i=i-1 endif i=i-1 end do else ! revert a (a is upper) ! revert permutations i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) i=i+1 if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif endif i=i+1 end do ! revert value i=n do while ( i > 1 ) if( ipiv(i) < 0_${ik}$ ) then a(i-1,i)=e(i) i=i-1 endif i=i-1 end do end if else ! a is lower if ( convert ) then ! convert a (a is lower) ! convert value i=1_${ik}$ e(n)=zero do while ( i <= n ) if( i 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i+1,j) a(i+1,j)=temp end do endif i=i+1 endif i=i+1 end do else ! revert a (a is lower) ! revert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i,j) a(i,j)=a(ip,j) a(ip,j)=temp end do endif else ip=-ipiv(i) i=i-1 if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i+1,j) a(i+1,j)=a(ip,j) a(ip,j)=temp end do endif endif i=i-1 end do ! revert value i=1_${ik}$ do while ( i <= n-1 ) if( ipiv(i) < 0_${ik}$ ) then a(i+1,i)=e(i) i=i+1 endif i=i+1 end do end if end if return end subroutine stdlib${ii}$_dsyconv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$syconv( uplo, way, n, a, lda, ipiv, e, info ) !! DSYCONV: convert A given by TRF into L and D and vice-versa. !! Get Non-diag elements of D (returned in workspace) and !! apply or reverse permutation done in TRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, j real(${rk}$) :: temp ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda 1 ) if( ipiv(i) < 0_${ik}$ ) then e(i)=a(i-1,i) e(i-1)=zero a(i-1,i)=zero i=i-1 else e(i)=zero endif i=i-1 end do ! convert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif i=i-1 endif i=i-1 end do else ! revert a (a is upper) ! revert permutations i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) i=i+1 if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif endif i=i+1 end do ! revert value i=n do while ( i > 1 ) if( ipiv(i) < 0_${ik}$ ) then a(i-1,i)=e(i) i=i-1 endif i=i-1 end do end if else ! a is lower if ( convert ) then ! convert a (a is lower) ! convert value i=1_${ik}$ e(n)=zero do while ( i <= n ) if( i 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i+1,j) a(i+1,j)=temp end do endif i=i+1 endif i=i+1 end do else ! revert a (a is lower) ! revert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i,j) a(i,j)=a(ip,j) a(ip,j)=temp end do endif else ip=-ipiv(i) i=i-1 if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i+1,j) a(i+1,j)=a(ip,j) a(ip,j)=temp end do endif endif i=i-1 end do ! revert value i=1_${ik}$ do while ( i <= n-1 ) if( ipiv(i) < 0_${ik}$ ) then a(i+1,i)=e(i) i=i+1 endif i=i+1 end do end if end if return end subroutine stdlib${ii}$_${ri}$syconv #:endif #:endfor pure module subroutine stdlib${ii}$_csyconv( uplo, way, n, a, lda, ipiv, e, info ) !! CSYCONV convert A given by TRF into L and D and vice-versa. !! Get Non-diag elements of D (returned in workspace) and !! apply or reverse permutation done in TRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, j complex(sp) :: temp ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda 1 ) if( ipiv(i) < 0_${ik}$ ) then e(i)=a(i-1,i) e(i-1)=czero a(i-1,i)=czero i=i-1 else e(i)=czero endif i=i-1 end do ! convert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif i=i-1 endif i=i-1 end do else ! revert a (a is upper) ! revert permutations i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) i=i+1 if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif endif i=i+1 end do ! revert value i=n do while ( i > 1 ) if( ipiv(i) < 0_${ik}$ ) then a(i-1,i)=e(i) i=i-1 endif i=i-1 end do end if else ! a is lower if ( convert ) then ! convert a (a is lower) ! convert value i=1_${ik}$ e(n)=czero do while ( i <= n ) if( i 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i+1,j) a(i+1,j)=temp end do endif i=i+1 endif i=i+1 end do else ! revert a (a is lower) ! revert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i,j) a(i,j)=a(ip,j) a(ip,j)=temp end do endif else ip=-ipiv(i) i=i-1 if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i+1,j) a(i+1,j)=a(ip,j) a(ip,j)=temp end do endif endif i=i-1 end do ! revert value i=1_${ik}$ do while ( i <= n-1 ) if( ipiv(i) < 0_${ik}$ ) then a(i+1,i)=e(i) i=i+1 endif i=i+1 end do end if end if return end subroutine stdlib${ii}$_csyconv pure module subroutine stdlib${ii}$_zsyconv( uplo, way, n, a, lda, ipiv, e, info ) !! ZSYCONV converts A given by ZHETRF into L and D or vice-versa. !! Get nondiagonal elements of D (returned in workspace) and !! apply or reverse permutation done in TRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, j complex(dp) :: temp ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda 1 ) if( ipiv(i) < 0_${ik}$ ) then e(i)=a(i-1,i) e(i-1)=czero a(i-1,i)=czero i=i-1 else e(i)=czero endif i=i-1 end do ! convert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif i=i-1 endif i=i-1 end do else ! revert a (a is upper) ! revert permutations i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) i=i+1 if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif endif i=i+1 end do ! revert value i=n do while ( i > 1 ) if( ipiv(i) < 0_${ik}$ ) then a(i-1,i)=e(i) i=i-1 endif i=i-1 end do end if else ! a is lower if ( convert ) then ! convert a (a is lower) ! convert value i=1_${ik}$ e(n)=czero do while ( i <= n ) if( i 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i+1,j) a(i+1,j)=temp end do endif i=i+1 endif i=i+1 end do else ! revert a (a is lower) ! revert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i,j) a(i,j)=a(ip,j) a(ip,j)=temp end do endif else ip=-ipiv(i) i=i-1 if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i+1,j) a(i+1,j)=a(ip,j) a(ip,j)=temp end do endif endif i=i-1 end do ! revert value i=1_${ik}$ do while ( i <= n-1 ) if( ipiv(i) < 0_${ik}$ ) then a(i+1,i)=e(i) i=i+1 endif i=i+1 end do end if end if return end subroutine stdlib${ii}$_zsyconv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$syconv( uplo, way, n, a, lda, ipiv, e, info ) !! ZSYCONV: converts A given by ZHETRF into L and D or vice-versa. !! Get nondiagonal elements of D (returned in workspace) and !! apply or reverse permutation done in TRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, j complex(${ck}$) :: temp ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda 1 ) if( ipiv(i) < 0_${ik}$ ) then e(i)=a(i-1,i) e(i-1)=czero a(i-1,i)=czero i=i-1 else e(i)=czero endif i=i-1 end do ! convert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif i=i-1 endif i=i-1 end do else ! revert a (a is upper) ! revert permutations i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) i=i+1 if( i < n) then do j= i+1,n temp=a(ip,j) a(ip,j)=a(i-1,j) a(i-1,j)=temp end do endif endif i=i+1 end do ! revert value i=n do while ( i > 1 ) if( ipiv(i) < 0_${ik}$ ) then a(i-1,i)=e(i) i=i-1 endif i=i-1 end do end if else ! a is lower if ( convert ) then ! convert a (a is lower) ! convert value i=1_${ik}$ e(n)=czero do while ( i <= n ) if( i 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i,j) a(i,j)=temp end do endif else ip=-ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(ip,j) a(ip,j)=a(i+1,j) a(i+1,j)=temp end do endif i=i+1 endif i=i+1 end do else ! revert a (a is lower) ! revert permutations i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then ip=ipiv(i) if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i,j) a(i,j)=a(ip,j) a(ip,j)=temp end do endif else ip=-ipiv(i) i=i-1 if (i > 1_${ik}$) then do j= 1,i-1 temp=a(i+1,j) a(i+1,j)=a(ip,j) a(ip,j)=temp end do endif endif i=i-1 end do ! revert value i=1_${ik}$ do while ( i <= n-1 ) if( ipiv(i) < 0_${ik}$ ) then a(i+1,i)=e(i) i=i+1 endif i=i+1 end do end if end if return end subroutine stdlib${ii}$_${ci}$syconv #:endif #:endfor pure module subroutine stdlib${ii}$_ssytrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) !! SSYTRS2 solves a system of linear equations A*X = B with a real !! symmetric matrix A using the factorization A = U*D*U**T or !! A = L*D*L**T computed by SSYTRF and converted by SSYCONV. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, j, k, kp real(sp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp==-ipiv( k-1 ) )call stdlib${ii}$_sswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb & ) k=k-2 end if end do ! compute (u \p**t * b) -> b [ (u \p**t * b) ] call stdlib${ii}$_strsm('L','U','N','U',n,nrhs,one,a,lda,b,ldb) ! compute d \ b -> b [ d \ (u \p**t * b) ] i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_sscal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) elseif ( i > 1_${ik}$) then if ( ipiv(i-1) == ipiv(i) ) then akm1k = work(i) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ endif endif i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_strsm('L','U','T','U',n,nrhs,one,a,lda,b,ldb) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k < n .and. kp==-ipiv( k+1 ) )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp,& 1_${ik}$ ), ldb ) k=k+2 endif end do else ! solve a*x = b, where a = l*d*l**t. ! p**t * b k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k+1). kp = -ipiv( k+1 ) if( kp==-ipiv( k ) )call stdlib${ii}$_sswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+2 endif end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_strsm('L','L','N','U',n,nrhs,one,a,lda,b,ldb) ! compute d \ b -> b [ d \ (l \p**t * b) ] i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_sscal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) else akm1k = work(i) akm1 = a( i, i ) / akm1k ak = a( i+1, i+1 ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( i, j ) / akm1k bk = b( i+1, j ) / akm1k b( i, j ) = ( ak*bkm1-bk ) / denom b( i+1, j ) = ( akm1*bk-bkm1 ) / denom end do i = i + 1_${ik}$ endif i = i + 1_${ik}$ end do ! compute (l**t \ b) -> b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_strsm('L','L','T','U',n,nrhs,one,a,lda,b,ldb) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] k=n do while ( k >= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k>1_${ik}$ .and. kp==-ipiv( k-1 ) )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, & 1_${ik}$ ), ldb ) k=k-2 endif end do end if ! revert a call stdlib${ii}$_ssyconv( uplo, 'R', n, a, lda, ipiv, work, iinfo ) return end subroutine stdlib${ii}$_ssytrs2 pure module subroutine stdlib${ii}$_dsytrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) !! DSYTRS2 solves a system of linear equations A*X = B with a real !! symmetric matrix A using the factorization A = U*D*U**T or !! A = L*D*L**T computed by DSYTRF and converted by DSYCONV. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, j, k, kp real(dp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp==-ipiv( k-1 ) )call stdlib${ii}$_dswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb & ) k=k-2 end if end do ! compute (u \p**t * b) -> b [ (u \p**t * b) ] call stdlib${ii}$_dtrsm('L','U','N','U',n,nrhs,one,a,lda,b,ldb) ! compute d \ b -> b [ d \ (u \p**t * b) ] i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_dscal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) elseif ( i > 1_${ik}$) then if ( ipiv(i-1) == ipiv(i) ) then akm1k = work(i) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ endif endif i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_dtrsm('L','U','T','U',n,nrhs,one,a,lda,b,ldb) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k < n .and. kp==-ipiv( k+1 ) )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp,& 1_${ik}$ ), ldb ) k=k+2 endif end do else ! solve a*x = b, where a = l*d*l**t. ! p**t * b k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k+1). kp = -ipiv( k+1 ) if( kp==-ipiv( k ) )call stdlib${ii}$_dswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+2 endif end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_dtrsm('L','L','N','U',n,nrhs,one,a,lda,b,ldb) ! compute d \ b -> b [ d \ (l \p**t * b) ] i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_dscal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) else akm1k = work(i) akm1 = a( i, i ) / akm1k ak = a( i+1, i+1 ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( i, j ) / akm1k bk = b( i+1, j ) / akm1k b( i, j ) = ( ak*bkm1-bk ) / denom b( i+1, j ) = ( akm1*bk-bkm1 ) / denom end do i = i + 1_${ik}$ endif i = i + 1_${ik}$ end do ! compute (l**t \ b) -> b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_dtrsm('L','L','T','U',n,nrhs,one,a,lda,b,ldb) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] k=n do while ( k >= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k>1_${ik}$ .and. kp==-ipiv( k-1 ) )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, & 1_${ik}$ ), ldb ) k=k-2 endif end do end if ! revert a call stdlib${ii}$_dsyconv( uplo, 'R', n, a, lda, ipiv, work, iinfo ) return end subroutine stdlib${ii}$_dsytrs2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sytrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) !! DSYTRS2: solves a system of linear equations A*X = B with a real !! symmetric matrix A using the factorization A = U*D*U**T or !! A = L*D*L**T computed by DSYTRF and converted by DSYCONV. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, j, k, kp real(${rk}$) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp==-ipiv( k-1 ) )call stdlib${ii}$_${ri}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb & ) k=k-2 end if end do ! compute (u \p**t * b) -> b [ (u \p**t * b) ] call stdlib${ii}$_${ri}$trsm('L','U','N','U',n,nrhs,one,a,lda,b,ldb) ! compute d \ b -> b [ d \ (u \p**t * b) ] i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_${ri}$scal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) elseif ( i > 1_${ik}$) then if ( ipiv(i-1) == ipiv(i) ) then akm1k = work(i) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ endif endif i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_${ri}$trsm('L','U','T','U',n,nrhs,one,a,lda,b,ldb) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k < n .and. kp==-ipiv( k+1 ) )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp,& 1_${ik}$ ), ldb ) k=k+2 endif end do else ! solve a*x = b, where a = l*d*l**t. ! p**t * b k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k+1). kp = -ipiv( k+1 ) if( kp==-ipiv( k ) )call stdlib${ii}$_${ri}$swap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+2 endif end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_${ri}$trsm('L','L','N','U',n,nrhs,one,a,lda,b,ldb) ! compute d \ b -> b [ d \ (l \p**t * b) ] i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_${ri}$scal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) else akm1k = work(i) akm1 = a( i, i ) / akm1k ak = a( i+1, i+1 ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( i, j ) / akm1k bk = b( i+1, j ) / akm1k b( i, j ) = ( ak*bkm1-bk ) / denom b( i+1, j ) = ( akm1*bk-bkm1 ) / denom end do i = i + 1_${ik}$ endif i = i + 1_${ik}$ end do ! compute (l**t \ b) -> b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_${ri}$trsm('L','L','T','U',n,nrhs,one,a,lda,b,ldb) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] k=n do while ( k >= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k>1_${ik}$ .and. kp==-ipiv( k-1 ) )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, & 1_${ik}$ ), ldb ) k=k-2 endif end do end if ! revert a call stdlib${ii}$_${ri}$syconv( uplo, 'R', n, a, lda, ipiv, work, iinfo ) return end subroutine stdlib${ii}$_${ri}$sytrs2 #:endif #:endfor pure module subroutine stdlib${ii}$_csytrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) !! CSYTRS2 solves a system of linear equations A*X = B with a complex !! symmetric matrix A using the factorization A = U*D*U**T or !! A = L*D*L**T computed by CSYTRF and converted by CSYCONV. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, j, k, kp complex(sp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp==-ipiv( k-1 ) )call stdlib${ii}$_cswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb & ) k=k-2 end if end do ! compute (u \p**t * b) -> b [ (u \p**t * b) ] call stdlib${ii}$_ctrsm('L','U','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (u \p**t * b) ] i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_cscal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) elseif ( i > 1_${ik}$) then if ( ipiv(i-1) == ipiv(i) ) then akm1k = work(i) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ endif endif i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_ctrsm('L','U','T','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k < n .and. kp==-ipiv( k+1 ) )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp,& 1_${ik}$ ), ldb ) k=k+2 endif end do else ! solve a*x = b, where a = l*d*l**t. ! p**t * b k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k+1). kp = -ipiv( k+1 ) if( kp==-ipiv( k ) )call stdlib${ii}$_cswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+2 endif end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_ctrsm('L','L','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (l \p**t * b) ] i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_cscal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) else akm1k = work(i) akm1 = a( i, i ) / akm1k ak = a( i+1, i+1 ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i, j ) / akm1k bk = b( i+1, j ) / akm1k b( i, j ) = ( ak*bkm1-bk ) / denom b( i+1, j ) = ( akm1*bk-bkm1 ) / denom end do i = i + 1_${ik}$ endif i = i + 1_${ik}$ end do ! compute (l**t \ b) -> b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_ctrsm('L','L','T','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] k=n do while ( k >= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k>1_${ik}$ .and. kp==-ipiv( k-1 ) )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, & 1_${ik}$ ), ldb ) k=k-2 endif end do end if ! revert a call stdlib${ii}$_csyconv( uplo, 'R', n, a, lda, ipiv, work, iinfo ) return end subroutine stdlib${ii}$_csytrs2 pure module subroutine stdlib${ii}$_zsytrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) !! ZSYTRS2 solves a system of linear equations A*X = B with a complex !! symmetric matrix A using the factorization A = U*D*U**T or !! A = L*D*L**T computed by ZSYTRF and converted by ZSYCONV. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, j, k, kp complex(dp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp==-ipiv( k-1 ) )call stdlib${ii}$_zswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb & ) k=k-2 end if end do ! compute (u \p**t * b) -> b [ (u \p**t * b) ] call stdlib${ii}$_ztrsm('L','U','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (u \p**t * b) ] i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_zscal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) elseif ( i > 1_${ik}$) then if ( ipiv(i-1) == ipiv(i) ) then akm1k = work(i) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ endif endif i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_ztrsm('L','U','T','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k < n .and. kp==-ipiv( k+1 ) )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp,& 1_${ik}$ ), ldb ) k=k+2 endif end do else ! solve a*x = b, where a = l*d*l**t. ! p**t * b k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k+1). kp = -ipiv( k+1 ) if( kp==-ipiv( k ) )call stdlib${ii}$_zswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+2 endif end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_ztrsm('L','L','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (l \p**t * b) ] i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_zscal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) else akm1k = work(i) akm1 = a( i, i ) / akm1k ak = a( i+1, i+1 ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i, j ) / akm1k bk = b( i+1, j ) / akm1k b( i, j ) = ( ak*bkm1-bk ) / denom b( i+1, j ) = ( akm1*bk-bkm1 ) / denom end do i = i + 1_${ik}$ endif i = i + 1_${ik}$ end do ! compute (l**t \ b) -> b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_ztrsm('L','L','T','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] k=n do while ( k >= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k>1_${ik}$ .and. kp==-ipiv( k-1 ) )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, & 1_${ik}$ ), ldb ) k=k-2 endif end do end if ! revert a call stdlib${ii}$_zsyconv( uplo, 'R', n, a, lda, ipiv, work, iinfo ) return end subroutine stdlib${ii}$_zsytrs2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$sytrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) !! ZSYTRS2: solves a system of linear equations A*X = B with a complex !! symmetric matrix A using the factorization A = U*D*U**T or !! A = L*D*L**T computed by ZSYTRF and converted by ZSYCONV. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, j, k, kp complex(${ck}$) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp==-ipiv( k-1 ) )call stdlib${ii}$_${ci}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb & ) k=k-2 end if end do ! compute (u \p**t * b) -> b [ (u \p**t * b) ] call stdlib${ii}$_${ci}$trsm('L','U','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (u \p**t * b) ] i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_${ci}$scal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) elseif ( i > 1_${ik}$) then if ( ipiv(i-1) == ipiv(i) ) then akm1k = work(i) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ endif endif i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm('L','U','T','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k < n .and. kp==-ipiv( k+1 ) )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp,& 1_${ik}$ ), ldb ) k=k+2 endif end do else ! solve a*x = b, where a = l*d*l**t. ! p**t * b k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k+1). kp = -ipiv( k+1 ) if( kp==-ipiv( k ) )call stdlib${ii}$_${ci}$swap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+2 endif end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_${ci}$trsm('L','L','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (l \p**t * b) ] i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then call stdlib${ii}$_${ci}$scal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) else akm1k = work(i) akm1 = a( i, i ) / akm1k ak = a( i+1, i+1 ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i, j ) / akm1k bk = b( i+1, j ) / akm1k b( i, j ) = ( ak*bkm1-bk ) / denom b( i+1, j ) = ( akm1*bk-bkm1 ) / denom end do i = i + 1_${ik}$ endif i = i + 1_${ik}$ end do ! compute (l**t \ b) -> b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm('L','L','T','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] k=n do while ( k >= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k>1_${ik}$ .and. kp==-ipiv( k-1 ) )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, & 1_${ik}$ ), ldb ) k=k-2 endif end do end if ! revert a call stdlib${ii}$_${ci}$syconv( uplo, 'R', n, a, lda, ipiv, work, iinfo ) return end subroutine stdlib${ii}$_${ci}$sytrs2 #:endif #:endfor pure module subroutine stdlib${ii}$_ssytrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) !! SSYTRS_3 solves a system of linear equations A * X = B with a real !! symmetric matrix A using the factorization computed !! by SSYTRF_RK or SSYTRF_BK: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This algorithm is using Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(in) :: a(lda,*), e(*) real(sp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, j, k, kp real(sp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda b [ (u \p**t * b) ] call stdlib${ii}$_strsm( 'L', 'U', 'N', 'U', n, nrhs, one, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (u \p**t * b) ] i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_sscal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if ( i>1_${ik}$ ) then akm1k = e( i ) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_strsm( 'L', 'U', 'T', 'U', n, nrhs, one, a, lda, b, ldb ) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for upper case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do else ! begin lower ! solve a*x = b, where a = l*d*l**t. ! p**t * b ! interchange rows k and ipiv(k) of matrix b in the same order ! that the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_strsm( 'L', 'L', 'N', 'U', n, nrhs, one, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (l \p**t * b) ] i = 1_${ik}$ do while ( i<=n ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_sscal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if( i b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_strsm('L', 'L', 'T', 'U', n, nrhs, one, a, lda, b, ldb ) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = n, 1, -1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! end lower end if return end subroutine stdlib${ii}$_ssytrs_3 pure module subroutine stdlib${ii}$_dsytrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) !! DSYTRS_3 solves a system of linear equations A * X = B with a real !! symmetric matrix A using the factorization computed !! by DSYTRF_RK or DSYTRF_BK: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This algorithm is using Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(in) :: a(lda,*), e(*) real(dp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, j, k, kp real(dp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda b [ (u \p**t * b) ] call stdlib${ii}$_dtrsm( 'L', 'U', 'N', 'U', n, nrhs, one, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (u \p**t * b) ] i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_dscal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if ( i>1_${ik}$ ) then akm1k = e( i ) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_dtrsm( 'L', 'U', 'T', 'U', n, nrhs, one, a, lda, b, ldb ) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for upper case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do else ! begin lower ! solve a*x = b, where a = l*d*l**t. ! p**t * b ! interchange rows k and ipiv(k) of matrix b in the same order ! that the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_dtrsm( 'L', 'L', 'N', 'U', n, nrhs, one, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (l \p**t * b) ] i = 1_${ik}$ do while ( i<=n ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_dscal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if( i b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_dtrsm('L', 'L', 'T', 'U', n, nrhs, one, a, lda, b, ldb ) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = n, 1, -1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! end lower end if return end subroutine stdlib${ii}$_dsytrs_3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sytrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) !! DSYTRS_3: solves a system of linear equations A * X = B with a real !! symmetric matrix A using the factorization computed !! by DSYTRF_RK or DSYTRF_BK: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This algorithm is using Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(in) :: a(lda,*), e(*) real(${rk}$), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, j, k, kp real(${rk}$) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda b [ (u \p**t * b) ] call stdlib${ii}$_${ri}$trsm( 'L', 'U', 'N', 'U', n, nrhs, one, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (u \p**t * b) ] i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_${ri}$scal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if ( i>1_${ik}$ ) then akm1k = e( i ) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_${ri}$trsm( 'L', 'U', 'T', 'U', n, nrhs, one, a, lda, b, ldb ) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for upper case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do else ! begin lower ! solve a*x = b, where a = l*d*l**t. ! p**t * b ! interchange rows k and ipiv(k) of matrix b in the same order ! that the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_${ri}$trsm( 'L', 'L', 'N', 'U', n, nrhs, one, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (l \p**t * b) ] i = 1_${ik}$ do while ( i<=n ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_${ri}$scal( nrhs, one / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if( i b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_${ri}$trsm('L', 'L', 'T', 'U', n, nrhs, one, a, lda, b, ldb ) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = n, 1, -1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! end lower end if return end subroutine stdlib${ii}$_${ri}$sytrs_3 #:endif #:endfor pure module subroutine stdlib${ii}$_csytrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) !! CSYTRS_3 solves a system of linear equations A * X = B with a complex !! symmetric matrix A using the factorization computed !! by CSYTRF_RK or CSYTRF_BK: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This algorithm is using Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: a(lda,*), e(*) complex(sp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, j, k, kp complex(sp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda b [ (u \p**t * b) ] call stdlib${ii}$_ctrsm( 'L', 'U', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (u \p**t * b) ] i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_cscal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if ( i>1_${ik}$ ) then akm1k = e( i ) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_ctrsm( 'L', 'U', 'T', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for upper case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do else ! begin lower ! solve a*x = b, where a = l*d*l**t. ! p**t * b ! interchange rows k and ipiv(k) of matrix b in the same order ! that the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_ctrsm( 'L', 'L', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (l \p**t * b) ] i = 1_${ik}$ do while ( i<=n ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_cscal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if( i b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_ctrsm('L', 'L', 'T', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = n, 1, -1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! end lower end if return end subroutine stdlib${ii}$_csytrs_3 pure module subroutine stdlib${ii}$_zsytrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) !! ZSYTRS_3 solves a system of linear equations A * X = B with a complex !! symmetric matrix A using the factorization computed !! by ZSYTRF_RK or ZSYTRF_BK: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This algorithm is using Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*), e(*) complex(dp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, j, k, kp complex(dp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda b [ (u \p**t * b) ] call stdlib${ii}$_ztrsm( 'L', 'U', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (u \p**t * b) ] i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_zscal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if ( i>1_${ik}$ ) then akm1k = e( i ) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_ztrsm( 'L', 'U', 'T', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for upper case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do else ! begin lower ! solve a*x = b, where a = l*d*l**t. ! p**t * b ! interchange rows k and ipiv(k) of matrix b in the same order ! that the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_ztrsm( 'L', 'L', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (l \p**t * b) ] i = 1_${ik}$ do while ( i<=n ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_zscal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if( i b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_ztrsm('L', 'L', 'T', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = n, 1, -1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! end lower end if return end subroutine stdlib${ii}$_zsytrs_3 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$sytrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) !! ZSYTRS_3: solves a system of linear equations A * X = B with a complex !! symmetric matrix A using the factorization computed !! by ZSYTRF_RK or ZSYTRF_BK: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This algorithm is using Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*), e(*) complex(${ck}$), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, j, k, kp complex(${ck}$) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda b [ (u \p**t * b) ] call stdlib${ii}$_${ci}$trsm( 'L', 'U', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (u \p**t * b) ] i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_${ci}$scal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if ( i>1_${ik}$ ) then akm1k = e( i ) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / akm1k b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! compute (u**t \ b) -> b [ u**t \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm( 'L', 'U', 'T', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (u**t \ (d \ (u \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for upper case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do else ! begin lower ! solve a*x = b, where a = l*d*l**t. ! p**t * b ! interchange rows k and ipiv(k) of matrix b in the same order ! that the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_${ci}$trsm( 'L', 'L', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (l \p**t * b) ] i = 1_${ik}$ do while ( i<=n ) if( ipiv( i )>0_${ik}$ ) then call stdlib${ii}$_${ci}$scal( nrhs, cone / a( i, i ), b( i, 1_${ik}$ ), ldb ) else if( i b [ l**t \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm('L', 'L', 'T', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (l**t \ (d \ (l \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = n, 1, -1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! end lower end if return end subroutine stdlib${ii}$_${ci}$sytrs_3 #:endif #:endfor pure module subroutine stdlib${ii}$_ssyswapr( uplo, n, a, lda, i1, i2) !! SSYSWAPR applies an elementary permutation on the rows and the columns of !! a symmetric matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1, i2, lda, n ! Array Arguments real(sp), intent(inout) :: a(lda,n) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i real(sp) :: tmp ! Executable Statements upper = stdlib_lsame( uplo, 'U' ) if (upper) then ! upper ! first swap ! - swap column i1 and i2 from i1 to i1-1 call stdlib${ii}$_sswap( i1-1, a(1_${ik}$,i1), 1_${ik}$, a(1_${ik}$,i2), 1_${ik}$ ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap row i1 from i1+1 to i2-1 with col i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1,i1+i) a(i1,i1+i)=a(i1+i,i2) a(i1+i,i2)=tmp end do ! third swap ! - swap row i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i1,i) a(i1,i)=a(i2,i) a(i2,i)=tmp end do else ! lower ! first swap ! - swap row i1 and i2 from i1 to i1-1 call stdlib${ii}$_sswap( i1-1, a(i1,1_${ik}$), lda, a(i2,1_${ik}$), lda ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap col i1 from i1+1 to i2-1 with row i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1+i,i1) a(i1+i,i1)=a(i2,i1+i) a(i2,i1+i)=tmp end do ! third swap ! - swap col i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i,i1) a(i,i1)=a(i,i2) a(i,i2)=tmp end do endif end subroutine stdlib${ii}$_ssyswapr pure module subroutine stdlib${ii}$_dsyswapr( uplo, n, a, lda, i1, i2) !! DSYSWAPR applies an elementary permutation on the rows and the columns of !! a symmetric matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1, i2, lda, n ! Array Arguments real(dp), intent(inout) :: a(lda,n) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i real(dp) :: tmp ! Executable Statements upper = stdlib_lsame( uplo, 'U' ) if (upper) then ! upper ! first swap ! - swap column i1 and i2 from i1 to i1-1 call stdlib${ii}$_dswap( i1-1, a(1_${ik}$,i1), 1_${ik}$, a(1_${ik}$,i2), 1_${ik}$ ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap row i1 from i1+1 to i2-1 with col i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1,i1+i) a(i1,i1+i)=a(i1+i,i2) a(i1+i,i2)=tmp end do ! third swap ! - swap row i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i1,i) a(i1,i)=a(i2,i) a(i2,i)=tmp end do else ! lower ! first swap ! - swap row i1 and i2 from i1 to i1-1 call stdlib${ii}$_dswap( i1-1, a(i1,1_${ik}$), lda, a(i2,1_${ik}$), lda ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap col i1 from i1+1 to i2-1 with row i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1+i,i1) a(i1+i,i1)=a(i2,i1+i) a(i2,i1+i)=tmp end do ! third swap ! - swap col i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i,i1) a(i,i1)=a(i,i2) a(i,i2)=tmp end do endif end subroutine stdlib${ii}$_dsyswapr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$syswapr( uplo, n, a, lda, i1, i2) !! DSYSWAPR: applies an elementary permutation on the rows and the columns of !! a symmetric matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1, i2, lda, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,n) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i real(${rk}$) :: tmp ! Executable Statements upper = stdlib_lsame( uplo, 'U' ) if (upper) then ! upper ! first swap ! - swap column i1 and i2 from i1 to i1-1 call stdlib${ii}$_${ri}$swap( i1-1, a(1_${ik}$,i1), 1_${ik}$, a(1_${ik}$,i2), 1_${ik}$ ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap row i1 from i1+1 to i2-1 with col i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1,i1+i) a(i1,i1+i)=a(i1+i,i2) a(i1+i,i2)=tmp end do ! third swap ! - swap row i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i1,i) a(i1,i)=a(i2,i) a(i2,i)=tmp end do else ! lower ! first swap ! - swap row i1 and i2 from i1 to i1-1 call stdlib${ii}$_${ri}$swap( i1-1, a(i1,1_${ik}$), lda, a(i2,1_${ik}$), lda ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap col i1 from i1+1 to i2-1 with row i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1+i,i1) a(i1+i,i1)=a(i2,i1+i) a(i2,i1+i)=tmp end do ! third swap ! - swap col i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i,i1) a(i,i1)=a(i,i2) a(i,i2)=tmp end do endif end subroutine stdlib${ii}$_${ri}$syswapr #:endif #:endfor pure module subroutine stdlib${ii}$_csyswapr( uplo, n, a, lda, i1, i2) !! CSYSWAPR applies an elementary permutation on the rows and the columns of !! a symmetric matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1, i2, lda, n ! Array Arguments complex(sp), intent(inout) :: a(lda,n) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i complex(sp) :: tmp ! Executable Statements upper = stdlib_lsame( uplo, 'U' ) if (upper) then ! upper ! first swap ! - swap column i1 and i2 from i1 to i1-1 call stdlib${ii}$_cswap( i1-1, a(1_${ik}$,i1), 1_${ik}$, a(1_${ik}$,i2), 1_${ik}$ ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap row i1 from i1+1 to i2-1 with col i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1,i1+i) a(i1,i1+i)=a(i1+i,i2) a(i1+i,i2)=tmp end do ! third swap ! - swap row i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i1,i) a(i1,i)=a(i2,i) a(i2,i)=tmp end do else ! lower ! first swap ! - swap row i1 and i2 from i1 to i1-1 call stdlib${ii}$_cswap ( i1-1, a(i1,1_${ik}$), lda, a(i2,1_${ik}$), lda ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap col i1 from i1+1 to i2-1 with row i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1+i,i1) a(i1+i,i1)=a(i2,i1+i) a(i2,i1+i)=tmp end do ! third swap ! - swap col i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i,i1) a(i,i1)=a(i,i2) a(i,i2)=tmp end do endif end subroutine stdlib${ii}$_csyswapr pure module subroutine stdlib${ii}$_zsyswapr( uplo, n, a, lda, i1, i2) !! ZSYSWAPR applies an elementary permutation on the rows and the columns of !! a symmetric matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1, i2, lda, n ! Array Arguments complex(dp), intent(inout) :: a(lda,n) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i complex(dp) :: tmp ! Executable Statements upper = stdlib_lsame( uplo, 'U' ) if (upper) then ! upper ! first swap ! - swap column i1 and i2 from i1 to i1-1 call stdlib${ii}$_zswap( i1-1, a(1_${ik}$,i1), 1_${ik}$, a(1_${ik}$,i2), 1_${ik}$ ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap row i1 from i1+1 to i2-1 with col i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1,i1+i) a(i1,i1+i)=a(i1+i,i2) a(i1+i,i2)=tmp end do ! third swap ! - swap row i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i1,i) a(i1,i)=a(i2,i) a(i2,i)=tmp end do else ! lower ! first swap ! - swap row i1 and i2 from i1 to i1-1 call stdlib${ii}$_zswap( i1-1, a(i1,1_${ik}$), lda, a(i2,1_${ik}$), lda ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap col i1 from i1+1 to i2-1 with row i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1+i,i1) a(i1+i,i1)=a(i2,i1+i) a(i2,i1+i)=tmp end do ! third swap ! - swap col i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i,i1) a(i,i1)=a(i,i2) a(i,i2)=tmp end do endif end subroutine stdlib${ii}$_zsyswapr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$syswapr( uplo, n, a, lda, i1, i2) !! ZSYSWAPR: applies an elementary permutation on the rows and the columns of !! a symmetric matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1, i2, lda, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,n) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i complex(${ck}$) :: tmp ! Executable Statements upper = stdlib_lsame( uplo, 'U' ) if (upper) then ! upper ! first swap ! - swap column i1 and i2 from i1 to i1-1 call stdlib${ii}$_${ci}$swap( i1-1, a(1_${ik}$,i1), 1_${ik}$, a(1_${ik}$,i2), 1_${ik}$ ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap row i1 from i1+1 to i2-1 with col i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1,i1+i) a(i1,i1+i)=a(i1+i,i2) a(i1+i,i2)=tmp end do ! third swap ! - swap row i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i1,i) a(i1,i)=a(i2,i) a(i2,i)=tmp end do else ! lower ! first swap ! - swap row i1 and i2 from i1 to i1-1 call stdlib${ii}$_${ci}$swap( i1-1, a(i1,1_${ik}$), lda, a(i2,1_${ik}$), lda ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap col i1 from i1+1 to i2-1 with row i2 from i1+1 to i2-1 tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1+i,i1) a(i1+i,i1)=a(i2,i1+i) a(i2,i1+i)=tmp end do ! third swap ! - swap col i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i,i1) a(i,i1)=a(i,i2) a(i,i2)=tmp end do endif end subroutine stdlib${ii}$_${ci}$syswapr #:endif #:endfor real(sp) module function stdlib${ii}$_cla_herpvgrw( uplo, n, info, a, lda, af, ldaf, ipiv,work ) !! CLA_HERPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: a(lda,*), af(ldaf,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ncols, i, j, k, kp real(sp) :: amax, umax, rpvgrw, tmp logical(lk) :: upper complex(sp) :: zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag ( zdum ) ) ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) if ( info==0_${ik}$ ) then if (upper) then ncols = 1_${ik}$ else ncols = n end if else ncols = info end if rpvgrw = one do i = 1, 2*n work( i ) = zero end do ! find the max magnitude entry of each column of a. compute the max ! for all n columns so we can apply the pivot permutation while ! looping below. assume a full factorization is the common case. if ( upper ) then do j = 1, n do i = 1, j work( n+i ) = max( cabs1( a( i,j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i,j ) ), work( n+j ) ) end do end do else do j = 1, n do i = j, n work( n+i ) = max( cabs1( a( i, j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i, j ) ), work( n+j ) ) end do end do end if ! now find the max magnitude entry of each column of u or l. also ! permute the magnitudes of a above so they're in the same order as ! the factor. ! the iteration orders and permutations were copied from stdlib${ii}$_csytrs. ! calls to stdlib${ii}$_sswap would be severe overkill. if ( upper ) then k = n do while ( k < ncols .and. k>0 ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = 1, k work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k - 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k-1 ) work( n+k-1 ) = work( n+kp ) work( n+kp ) = tmp do i = 1, k-1 work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k-1 ) =max( cabs1( af( i, k-1 ) ), work( k-1 ) ) end do work( k ) = max( cabs1( af( k, k ) ), work( k ) ) k = k - 2_${ik}$ end if end do k = ncols do while ( k <= n ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k + 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k + 2_${ik}$ end if end do else k = 1_${ik}$ do while ( k <= ncols ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = k, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k + 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k+1 ) work( n+k+1 ) = work( n+kp ) work( n+kp ) = tmp do i = k+1, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k+1 ) =max( cabs1( af( i, k+1 ) ) , work( k+1 ) ) end do work(k) = max( cabs1( af( k, k ) ), work( k ) ) k = k + 2_${ik}$ end if end do k = ncols do while ( k >= 1 ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k - 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k - 2_${ik}$ endif end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( upper ) then do i = ncols, n umax = work( i ) amax = work( n+i ) if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( n+i ) if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_cla_herpvgrw = rpvgrw end function stdlib${ii}$_cla_herpvgrw real(dp) module function stdlib${ii}$_zla_herpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) !! ZLA_HERPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*), af(ldaf,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ncols, i, j, k, kp real(dp) :: amax, umax, rpvgrw, tmp logical(lk) :: upper complex(dp) :: zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag ( zdum ) ) ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) if ( info==0_${ik}$ ) then if (upper) then ncols = 1_${ik}$ else ncols = n end if else ncols = info end if rpvgrw = one do i = 1, 2*n work( i ) = zero end do ! find the max magnitude entry of each column of a. compute the max ! for all n columns so we can apply the pivot permutation while ! looping below. assume a full factorization is the common case. if ( upper ) then do j = 1, n do i = 1, j work( n+i ) = max( cabs1( a( i,j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i,j ) ), work( n+j ) ) end do end do else do j = 1, n do i = j, n work( n+i ) = max( cabs1( a( i, j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i, j ) ), work( n+j ) ) end do end do end if ! now find the max magnitude entry of each column of u or l. also ! permute the magnitudes of a above so they're in the same order as ! the factor. ! the iteration orders and permutations were copied from stdlib${ii}$_zsytrs. ! calls to stdlib${ii}$_sswap would be severe overkill. if ( upper ) then k = n do while ( k < ncols .and. k>0 ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = 1, k work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k - 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k-1 ) work( n+k-1 ) = work( n+kp ) work( n+kp ) = tmp do i = 1, k-1 work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k-1 ) =max( cabs1( af( i, k-1 ) ), work( k-1 ) ) end do work( k ) = max( cabs1( af( k, k ) ), work( k ) ) k = k - 2_${ik}$ end if end do k = ncols do while ( k <= n ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k + 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k + 2_${ik}$ end if end do else k = 1_${ik}$ do while ( k <= ncols ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = k, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k + 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k+1 ) work( n+k+1 ) = work( n+kp ) work( n+kp ) = tmp do i = k+1, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k+1 ) =max( cabs1( af( i, k+1 ) ) , work( k+1 ) ) end do work(k) = max( cabs1( af( k, k ) ), work( k ) ) k = k + 2_${ik}$ end if end do k = ncols do while ( k >= 1 ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k - 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k - 2_${ik}$ endif end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( upper ) then do i = ncols, n umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_zla_herpvgrw = rpvgrw end function stdlib${ii}$_zla_herpvgrw #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$la_herpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) !! ZLA_HERPVGRW: computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*) real(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ncols, i, j, k, kp real(${ck}$) :: amax, umax, rpvgrw, tmp logical(lk) :: upper complex(${ck}$) :: zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag ( zdum ) ) ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) if ( info==0_${ik}$ ) then if (upper) then ncols = 1_${ik}$ else ncols = n end if else ncols = info end if rpvgrw = one do i = 1, 2*n work( i ) = zero end do ! find the max magnitude entry of each column of a. compute the max ! for all n columns so we can apply the pivot permutation while ! looping below. assume a full factorization is the common case. if ( upper ) then do j = 1, n do i = 1, j work( n+i ) = max( cabs1( a( i,j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i,j ) ), work( n+j ) ) end do end do else do j = 1, n do i = j, n work( n+i ) = max( cabs1( a( i, j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i, j ) ), work( n+j ) ) end do end do end if ! now find the max magnitude entry of each column of u or l. also ! permute the magnitudes of a above so they're in the same order as ! the factor. ! the iteration orders and permutations were copied from stdlib${ii}$_${ci}$sytrs. ! calls to stdlib${ii}$_dswap would be severe overkill. if ( upper ) then k = n do while ( k < ncols .and. k>0 ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = 1, k work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k - 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k-1 ) work( n+k-1 ) = work( n+kp ) work( n+kp ) = tmp do i = 1, k-1 work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k-1 ) =max( cabs1( af( i, k-1 ) ), work( k-1 ) ) end do work( k ) = max( cabs1( af( k, k ) ), work( k ) ) k = k - 2_${ik}$ end if end do k = ncols do while ( k <= n ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k + 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k + 2_${ik}$ end if end do else k = 1_${ik}$ do while ( k <= ncols ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = k, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k + 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k+1 ) work( n+k+1 ) = work( n+kp ) work( n+kp ) = tmp do i = k+1, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k+1 ) =max( cabs1( af( i, k+1 ) ) , work( k+1 ) ) end do work(k) = max( cabs1( af( k, k ) ), work( k ) ) k = k + 2_${ik}$ end if end do k = ncols do while ( k >= 1 ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k - 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k - 2_${ik}$ endif end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( upper ) then do i = ncols, n umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_${ci}$la_herpvgrw = rpvgrw end function stdlib${ii}$_${ci}$la_herpvgrw #:endif #:endfor pure module subroutine stdlib${ii}$_sspcon( uplo, n, ap, ipiv, anorm, rcond, work, iwork,info ) !! SSPCON estimates the reciprocal of the condition number (in the !! 1-norm) of a real symmetric packed matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by SSPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: ap(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ip, kase real(sp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( anorm0 .and. ap( ip )==zero )return ip = ip - i end do else ! lower triangular storage: examine d from top to bottom. ip = 1_${ik}$ do i = 1, n if( ipiv( i )>0 .and. ap( ip )==zero )return ip = ip + n - i + 1_${ik}$ end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_slacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_ssptrs( uplo, n, 1_${ik}$, ap, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_sspcon pure module subroutine stdlib${ii}$_dspcon( uplo, n, ap, ipiv, anorm, rcond, work, iwork,info ) !! DSPCON estimates the reciprocal of the condition number (in the !! 1-norm) of a real symmetric packed matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by DSPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: ap(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ip, kase real(dp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( anorm0 .and. ap( ip )==zero )return ip = ip - i end do else ! lower triangular storage: examine d from top to bottom. ip = 1_${ik}$ do i = 1, n if( ipiv( i )>0 .and. ap( ip )==zero )return ip = ip + n - i + 1_${ik}$ end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_dlacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_dsptrs( uplo, n, 1_${ik}$, ap, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_dspcon #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$spcon( uplo, n, ap, ipiv, anorm, rcond, work, iwork,info ) !! DSPCON: estimates the reciprocal of the condition number (in the !! 1-norm) of a real symmetric packed matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by DSPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(${rk}$), intent(in) :: anorm real(${rk}$), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: ap(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ip, kase real(${rk}$) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( anorm0 .and. ap( ip )==zero )return ip = ip - i end do else ! lower triangular storage: examine d from top to bottom. ip = 1_${ik}$ do i = 1, n if( ipiv( i )>0 .and. ap( ip )==zero )return ip = ip + n - i + 1_${ik}$ end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_${ri}$lacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_${ri}$sptrs( uplo, n, 1_${ik}$, ap, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_${ri}$spcon #:endif #:endfor pure module subroutine stdlib${ii}$_cspcon( uplo, n, ap, ipiv, anorm, rcond, work, info ) !! CSPCON estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric packed matrix A using the !! factorization A = U*D*U**T or A = L*D*L**T computed by CSPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: ap(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ip, kase real(sp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( anorm0 .and. ap( ip )==zero )return ip = ip - i end do else ! lower triangular storage: examine d from top to bottom. ip = 1_${ik}$ do i = 1, n if( ipiv( i )>0 .and. ap( ip )==zero )return ip = ip + n - i + 1_${ik}$ end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_csptrs( uplo, n, 1_${ik}$, ap, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_cspcon pure module subroutine stdlib${ii}$_zspcon( uplo, n, ap, ipiv, anorm, rcond, work, info ) !! ZSPCON estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric packed matrix A using the !! factorization A = U*D*U**T or A = L*D*L**T computed by ZSPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: ap(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ip, kase real(dp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( anorm0 .and. ap( ip )==zero )return ip = ip - i end do else ! lower triangular storage: examine d from top to bottom. ip = 1_${ik}$ do i = 1, n if( ipiv( i )>0 .and. ap( ip )==zero )return ip = ip + n - i + 1_${ik}$ end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_zsptrs( uplo, n, 1_${ik}$, ap, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_zspcon #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$spcon( uplo, n, ap, ipiv, anorm, rcond, work, info ) !! ZSPCON: estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric packed matrix A using the !! factorization A = U*D*U**T or A = L*D*L**T computed by ZSPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(${ck}$), intent(in) :: anorm real(${ck}$), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: ap(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ip, kase real(${ck}$) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( anorm0 .and. ap( ip )==zero )return ip = ip - i end do else ! lower triangular storage: examine d from top to bottom. ip = 1_${ik}$ do i = 1, n if( ipiv( i )>0 .and. ap( ip )==zero )return ip = ip + n - i + 1_${ik}$ end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_${ci}$sptrs( uplo, n, 1_${ik}$, ap, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_${ci}$spcon #:endif #:endfor pure module subroutine stdlib${ii}$_ssptrf( uplo, n, ap, ipiv, info ) !! SSPTRF computes the factorization of a real symmetric matrix A stored !! in packed format using the Bunch-Kaufman diagonal pivoting method: !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: ap(*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, imax, j, jmax, k, kc, kk, knc, kp, kpc, kstep, kx, npp real(sp) :: absakk, alpha, colmax, d11, d12, d21, d22, r1, rowmax, t, wk, wkm1, & wkp1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSPTRF', -info ) return end if ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight if( upper ) then ! factorize a as u*d*u**t using the upper triangle of a ! k is the main loop index, decreasing from n to 1 in steps of ! 1 or 2 k = n kc = ( n-1 )*n / 2_${ik}$ + 1_${ik}$ 10 continue knc = kc ! if k < 1, exit from loop if( k<1 )go to 110 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( ap( kc+k-1 ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value if( k>1_${ik}$ ) then imax = stdlib${ii}$_isamax( k-1, ap( kc ), 1_${ik}$ ) colmax = abs( ap( kc+imax-1 ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else rowmax = zero jmax = imax kx = imax*( imax+1 ) / 2_${ik}$ + imax do j = imax + 1, k if( abs( ap( kx ) )>rowmax ) then rowmax = abs( ap( kx ) ) jmax = j end if kx = kx + j end do kpc = ( imax-1 )*imax / 2_${ik}$ + 1_${ik}$ if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_isamax( imax-1, ap( kpc ), 1_${ik}$ ) rowmax = max( rowmax, abs( ap( kpc+jmax-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( ap( kpc+imax-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kstep==2_${ik}$ )knc = knc - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_sswap( kp-1, ap( knc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, kk - 1 kx = kx + j - 1_${ik}$ t = ap( knc+j-1 ) ap( knc+j-1 ) = ap( kx ) ap( kx ) = t end do t = ap( knc+kk-1 ) ap( knc+kk-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = t if( kstep==2_${ik}$ ) then t = ap( kc+k-2 ) ap( kc+k-2 ) = ap( kc+kp-1 ) ap( kc+kp-1 ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = one / ap( kc+k-1 ) call stdlib${ii}$_sspr( uplo, k-1, -r1, ap( kc ), 1_${ik}$, ap ) ! store u(k) in column k call stdlib${ii}$_sscal( k-1, r1, ap( kc ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = ap( k-1+( k-1 )*k / 2_${ik}$ ) d22 = ap( k-1+( k-2 )*( k-1 ) / 2_${ik}$ ) / d12 d11 = ap( k+( k-1 )*k / 2_${ik}$ ) / d12 t = one / ( d11*d22-one ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ )-ap( j+( k-1 )*k / 2_${ik}$ ) ) wk = d12*( d22*ap( j+( k-1 )*k / 2_${ik}$ )-ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) ) do i = j, 1, -1 ap( i+( j-1 )*j / 2_${ik}$ ) = ap( i+( j-1 )*j / 2_${ik}$ ) -ap( i+( k-1 )*k / 2_${ik}$ )& *wk -ap( i+( k-2 )*( k-1 ) / 2_${ik}$ )*wkm1 end do ap( j+( k-1 )*k / 2_${ik}$ ) = wk ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep kc = knc - k go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ kc = 1_${ik}$ npp = n*( n+1 ) / 2_${ik}$ 60 continue knc = kc ! if k > n, exit from loop if( k>n )go to 110 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( ap( kc ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero kx = kc + imax - k do j = k, imax - 1 if( abs( ap( kx ) )>rowmax ) then rowmax = abs( ap( kx ) ) jmax = j end if kx = kx + n - j end do kpc = npp - ( n-imax+1 )*( n-imax+2 ) / 2_${ik}$ + 1_${ik}$ if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( ap( kpc ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kstep==2_${ik}$ )knc = knc + n - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_idamax( k-1, ap( kc ), 1_${ik}$ ) colmax = abs( ap( kc+imax-1 ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else rowmax = zero jmax = imax kx = imax*( imax+1 ) / 2_${ik}$ + imax do j = imax + 1, k if( abs( ap( kx ) )>rowmax ) then rowmax = abs( ap( kx ) ) jmax = j end if kx = kx + j end do kpc = ( imax-1 )*imax / 2_${ik}$ + 1_${ik}$ if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_idamax( imax-1, ap( kpc ), 1_${ik}$ ) rowmax = max( rowmax, abs( ap( kpc+jmax-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( ap( kpc+imax-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kstep==2_${ik}$ )knc = knc - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_dswap( kp-1, ap( knc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, kk - 1 kx = kx + j - 1_${ik}$ t = ap( knc+j-1 ) ap( knc+j-1 ) = ap( kx ) ap( kx ) = t end do t = ap( knc+kk-1 ) ap( knc+kk-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = t if( kstep==2_${ik}$ ) then t = ap( kc+k-2 ) ap( kc+k-2 ) = ap( kc+kp-1 ) ap( kc+kp-1 ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = one / ap( kc+k-1 ) call stdlib${ii}$_dspr( uplo, k-1, -r1, ap( kc ), 1_${ik}$, ap ) ! store u(k) in column k call stdlib${ii}$_dscal( k-1, r1, ap( kc ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = ap( k-1+( k-1 )*k / 2_${ik}$ ) d22 = ap( k-1+( k-2 )*( k-1 ) / 2_${ik}$ ) / d12 d11 = ap( k+( k-1 )*k / 2_${ik}$ ) / d12 t = one / ( d11*d22-one ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ )-ap( j+( k-1 )*k / 2_${ik}$ ) ) wk = d12*( d22*ap( j+( k-1 )*k / 2_${ik}$ )-ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) ) do i = j, 1, -1 ap( i+( j-1 )*j / 2_${ik}$ ) = ap( i+( j-1 )*j / 2_${ik}$ ) -ap( i+( k-1 )*k / 2_${ik}$ )& *wk -ap( i+( k-2 )*( k-1 ) / 2_${ik}$ )*wkm1 end do ap( j+( k-1 )*k / 2_${ik}$ ) = wk ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep kc = knc - k go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ kc = 1_${ik}$ npp = n*( n+1 ) / 2_${ik}$ 60 continue knc = kc ! if k > n, exit from loop if( k>n )go to 110 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( ap( kc ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero kx = kc + imax - k do j = k, imax - 1 if( abs( ap( kx ) )>rowmax ) then rowmax = abs( ap( kx ) ) jmax = j end if kx = kx + n - j end do kpc = npp - ( n-imax+1 )*( n-imax+2 ) / 2_${ik}$ + 1_${ik}$ if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( ap( kpc ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kstep==2_${ik}$ )knc = knc + n - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_i${ri}$amax( k-1, ap( kc ), 1_${ik}$ ) colmax = abs( ap( kc+imax-1 ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else rowmax = zero jmax = imax kx = imax*( imax+1 ) / 2_${ik}$ + imax do j = imax + 1, k if( abs( ap( kx ) )>rowmax ) then rowmax = abs( ap( kx ) ) jmax = j end if kx = kx + j end do kpc = ( imax-1 )*imax / 2_${ik}$ + 1_${ik}$ if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_i${ri}$amax( imax-1, ap( kpc ), 1_${ik}$ ) rowmax = max( rowmax, abs( ap( kpc+jmax-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( ap( kpc+imax-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kstep==2_${ik}$ )knc = knc - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_${ri}$swap( kp-1, ap( knc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, kk - 1 kx = kx + j - 1_${ik}$ t = ap( knc+j-1 ) ap( knc+j-1 ) = ap( kx ) ap( kx ) = t end do t = ap( knc+kk-1 ) ap( knc+kk-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = t if( kstep==2_${ik}$ ) then t = ap( kc+k-2 ) ap( kc+k-2 ) = ap( kc+kp-1 ) ap( kc+kp-1 ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = one / ap( kc+k-1 ) call stdlib${ii}$_${ri}$spr( uplo, k-1, -r1, ap( kc ), 1_${ik}$, ap ) ! store u(k) in column k call stdlib${ii}$_${ri}$scal( k-1, r1, ap( kc ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = ap( k-1+( k-1 )*k / 2_${ik}$ ) d22 = ap( k-1+( k-2 )*( k-1 ) / 2_${ik}$ ) / d12 d11 = ap( k+( k-1 )*k / 2_${ik}$ ) / d12 t = one / ( d11*d22-one ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ )-ap( j+( k-1 )*k / 2_${ik}$ ) ) wk = d12*( d22*ap( j+( k-1 )*k / 2_${ik}$ )-ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) ) do i = j, 1, -1 ap( i+( j-1 )*j / 2_${ik}$ ) = ap( i+( j-1 )*j / 2_${ik}$ ) -ap( i+( k-1 )*k / 2_${ik}$ )& *wk -ap( i+( k-2 )*( k-1 ) / 2_${ik}$ )*wkm1 end do ap( j+( k-1 )*k / 2_${ik}$ ) = wk ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep kc = knc - k go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ kc = 1_${ik}$ npp = n*( n+1 ) / 2_${ik}$ 60 continue knc = kc ! if k > n, exit from loop if( k>n )go to 110 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( ap( kc ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero kx = kc + imax - k do j = k, imax - 1 if( abs( ap( kx ) )>rowmax ) then rowmax = abs( ap( kx ) ) jmax = j end if kx = kx + n - j end do kpc = npp - ( n-imax+1 )*( n-imax+2 ) / 2_${ik}$ + 1_${ik}$ if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( ap( kpc ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kstep==2_${ik}$ )knc = knc + n - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, ap( kc ), 1_${ik}$ ) colmax = cabs1( ap( kc+imax-1 ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else rowmax = zero jmax = imax kx = imax*( imax+1 ) / 2_${ik}$ + imax do j = imax + 1, k if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + j end do kpc = ( imax-1 )*imax / 2_${ik}$ + 1_${ik}$ if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_icamax( imax-1, ap( kpc ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( ap( kpc+jmax-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( ap( kpc+imax-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kstep==2_${ik}$ )knc = knc - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_cswap( kp-1, ap( knc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, kk - 1 kx = kx + j - 1_${ik}$ t = ap( knc+j-1 ) ap( knc+j-1 ) = ap( kx ) ap( kx ) = t end do t = ap( knc+kk-1 ) ap( knc+kk-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = t if( kstep==2_${ik}$ ) then t = ap( kc+k-2 ) ap( kc+k-2 ) = ap( kc+kp-1 ) ap( kc+kp-1 ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = cone / ap( kc+k-1 ) call stdlib${ii}$_cspr( uplo, k-1, -r1, ap( kc ), 1_${ik}$, ap ) ! store u(k) in column k call stdlib${ii}$_cscal( k-1, r1, ap( kc ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = ap( k-1+( k-1 )*k / 2_${ik}$ ) d22 = ap( k-1+( k-2 )*( k-1 ) / 2_${ik}$ ) / d12 d11 = ap( k+( k-1 )*k / 2_${ik}$ ) / d12 t = cone / ( d11*d22-cone ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ )-ap( j+( k-1 )*k / 2_${ik}$ ) ) wk = d12*( d22*ap( j+( k-1 )*k / 2_${ik}$ )-ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) ) do i = j, 1, -1 ap( i+( j-1 )*j / 2_${ik}$ ) = ap( i+( j-1 )*j / 2_${ik}$ ) -ap( i+( k-1 )*k / 2_${ik}$ )& *wk -ap( i+( k-2 )*( k-1 ) / 2_${ik}$ )*wkm1 end do ap( j+( k-1 )*k / 2_${ik}$ ) = wk ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep kc = knc - k go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ kc = 1_${ik}$ npp = n*( n+1 ) / 2_${ik}$ 60 continue knc = kc ! if k > n, exit from loop if( k>n )go to 110 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( ap( kc ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero kx = kc + imax - k do j = k, imax - 1 if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + n - j end do kpc = npp - ( n-imax+1 )*( n-imax+2 ) / 2_${ik}$ + 1_${ik}$ if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( ap( kpc ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kstep==2_${ik}$ )knc = knc + n - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, ap( kc ), 1_${ik}$ ) colmax = cabs1( ap( kc+imax-1 ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else rowmax = zero jmax = imax kx = imax*( imax+1 ) / 2_${ik}$ + imax do j = imax + 1, k if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + j end do kpc = ( imax-1 )*imax / 2_${ik}$ + 1_${ik}$ if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_izamax( imax-1, ap( kpc ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( ap( kpc+jmax-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( ap( kpc+imax-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kstep==2_${ik}$ )knc = knc - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_zswap( kp-1, ap( knc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, kk - 1 kx = kx + j - 1_${ik}$ t = ap( knc+j-1 ) ap( knc+j-1 ) = ap( kx ) ap( kx ) = t end do t = ap( knc+kk-1 ) ap( knc+kk-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = t if( kstep==2_${ik}$ ) then t = ap( kc+k-2 ) ap( kc+k-2 ) = ap( kc+kp-1 ) ap( kc+kp-1 ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = cone / ap( kc+k-1 ) call stdlib${ii}$_zspr( uplo, k-1, -r1, ap( kc ), 1_${ik}$, ap ) ! store u(k) in column k call stdlib${ii}$_zscal( k-1, r1, ap( kc ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = ap( k-1+( k-1 )*k / 2_${ik}$ ) d22 = ap( k-1+( k-2 )*( k-1 ) / 2_${ik}$ ) / d12 d11 = ap( k+( k-1 )*k / 2_${ik}$ ) / d12 t = cone / ( d11*d22-cone ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ )-ap( j+( k-1 )*k / 2_${ik}$ ) ) wk = d12*( d22*ap( j+( k-1 )*k / 2_${ik}$ )-ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) ) do i = j, 1, -1 ap( i+( j-1 )*j / 2_${ik}$ ) = ap( i+( j-1 )*j / 2_${ik}$ ) -ap( i+( k-1 )*k / 2_${ik}$ )& *wk -ap( i+( k-2 )*( k-1 ) / 2_${ik}$ )*wkm1 end do ap( j+( k-1 )*k / 2_${ik}$ ) = wk ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep kc = knc - k go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ kc = 1_${ik}$ npp = n*( n+1 ) / 2_${ik}$ 60 continue knc = kc ! if k > n, exit from loop if( k>n )go to 110 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( ap( kc ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero kx = kc + imax - k do j = k, imax - 1 if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + n - j end do kpc = npp - ( n-imax+1 )*( n-imax+2 ) / 2_${ik}$ + 1_${ik}$ if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( ap( kpc ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kstep==2_${ik}$ )knc = knc + n - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, ap( kc ), 1_${ik}$ ) colmax = cabs1( ap( kc+imax-1 ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero: set info and continue if( info==0_${ik}$ )info = k kp = k else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else rowmax = zero jmax = imax kx = imax*( imax+1 ) / 2_${ik}$ + imax do j = imax + 1, k if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + j end do kpc = ( imax-1 )*imax / 2_${ik}$ + 1_${ik}$ if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_i${ci}$amax( imax-1, ap( kpc ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( ap( kpc+jmax-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( ap( kpc+imax-1 ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kstep==2_${ik}$ )knc = knc - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_${ci}$swap( kp-1, ap( knc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, kk - 1 kx = kx + j - 1_${ik}$ t = ap( knc+j-1 ) ap( knc+j-1 ) = ap( kx ) ap( kx ) = t end do t = ap( knc+kk-1 ) ap( knc+kk-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = t if( kstep==2_${ik}$ ) then t = ap( kc+k-2 ) ap( kc+k-2 ) = ap( kc+kp-1 ) ap( kc+kp-1 ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t = a - w(k)*1/d(k)*w(k)**t r1 = cone / ap( kc+k-1 ) call stdlib${ii}$_${ci}$spr( uplo, k-1, -r1, ap( kc ), 1_${ik}$, ap ) ! store u(k) in column k call stdlib${ii}$_${ci}$scal( k-1, r1, ap( kc ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**t if( k>2_${ik}$ ) then d12 = ap( k-1+( k-1 )*k / 2_${ik}$ ) d22 = ap( k-1+( k-2 )*( k-1 ) / 2_${ik}$ ) / d12 d11 = ap( k+( k-1 )*k / 2_${ik}$ ) / d12 t = cone / ( d11*d22-cone ) d12 = t / d12 do j = k - 2, 1, -1 wkm1 = d12*( d11*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ )-ap( j+( k-1 )*k / 2_${ik}$ ) ) wk = d12*( d22*ap( j+( k-1 )*k / 2_${ik}$ )-ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) ) do i = j, 1, -1 ap( i+( j-1 )*j / 2_${ik}$ ) = ap( i+( j-1 )*j / 2_${ik}$ ) -ap( i+( k-1 )*k / 2_${ik}$ )& *wk -ap( i+( k-2 )*( k-1 ) / 2_${ik}$ )*wkm1 end do ap( j+( k-1 )*k / 2_${ik}$ ) = wk ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) = wkm1 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep kc = knc - k go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ kc = 1_${ik}$ npp = n*( n+1 ) / 2_${ik}$ 60 continue knc = kc ! if k > n, exit from loop if( k>n )go to 110 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( ap( kc ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero kx = kc + imax - k do j = k, imax - 1 if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + n - j end do kpc = npp - ( n-imax+1 )*( n-imax+2 ) / 2_${ik}$ + 1_${ik}$ if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( cabs1( ap( kpc ) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kstep==2_${ik}$ )knc = knc + n - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_slarzt( 'BACKWARD', 'ROWWISE', n-m, ib, a( i, m1 ),lda, tau( i ), & work, ldwork ) ! apply h to a(1:i-1,i:n) from the right call stdlib${ii}$_slarzb( 'RIGHT', 'NO TRANSPOSE', 'BACKWARD','ROWWISE', i-1, n-i+1,& ib, n-m, a( i, m1 ),lda, work, ldwork, a( 1_${ik}$, i ), lda,work( ib+1 ), ldwork ) end if end do mu = i + nb - 1_${ik}$ else mu = m end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ )call stdlib${ii}$_slatrz( mu, n, n-m, a, lda, tau, work ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_stzrzf pure module subroutine stdlib${ii}$_dtzrzf( m, n, a, lda, tau, work, lwork, info ) !! DTZRZF reduces the M-by-N ( M<=N ) real upper trapezoidal matrix A !! to upper triangular form by means of orthogonal transformations. !! The upper trapezoidal matrix A is factored as !! A = ( R 0 ) * Z, !! where Z is an N-by-N orthogonal matrix and R is an M-by-M upper !! triangular matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iws, ki, kk, ldwork, lwkmin, lwkopt, m1, mu, nb, nbmin, & nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_dlarzt( 'BACKWARD', 'ROWWISE', n-m, ib, a( i, m1 ),lda, tau( i ), & work, ldwork ) ! apply h to a(1:i-1,i:n) from the right call stdlib${ii}$_dlarzb( 'RIGHT', 'NO TRANSPOSE', 'BACKWARD','ROWWISE', i-1, n-i+1,& ib, n-m, a( i, m1 ),lda, work, ldwork, a( 1_${ik}$, i ), lda,work( ib+1 ), ldwork ) end if end do mu = i + nb - 1_${ik}$ else mu = m end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ )call stdlib${ii}$_dlatrz( mu, n, n-m, a, lda, tau, work ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dtzrzf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tzrzf( m, n, a, lda, tau, work, lwork, info ) !! DTZRZF: reduces the M-by-N ( M<=N ) real upper trapezoidal matrix A !! to upper triangular form by means of orthogonal transformations. !! The upper trapezoidal matrix A is factored as !! A = ( R 0 ) * Z, !! where Z is an N-by-N orthogonal matrix and R is an M-by-M upper !! triangular matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iws, ki, kk, ldwork, lwkmin, lwkopt, m1, mu, nb, nbmin, & nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_${ri}$larzt( 'BACKWARD', 'ROWWISE', n-m, ib, a( i, m1 ),lda, tau( i ), & work, ldwork ) ! apply h to a(1:i-1,i:n) from the right call stdlib${ii}$_${ri}$larzb( 'RIGHT', 'NO TRANSPOSE', 'BACKWARD','ROWWISE', i-1, n-i+1,& ib, n-m, a( i, m1 ),lda, work, ldwork, a( 1_${ik}$, i ), lda,work( ib+1 ), ldwork ) end if end do mu = i + nb - 1_${ik}$ else mu = m end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ )call stdlib${ii}$_${ri}$latrz( mu, n, n-m, a, lda, tau, work ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$tzrzf #:endif #:endfor pure module subroutine stdlib${ii}$_ctzrzf( m, n, a, lda, tau, work, lwork, info ) !! CTZRZF reduces the M-by-N ( M<=N ) complex upper trapezoidal matrix A !! to upper triangular form by means of unitary transformations. !! The upper trapezoidal matrix A is factored as !! A = ( R 0 ) * Z, !! where Z is an N-by-N unitary matrix and R is an M-by-M upper !! triangular matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iws, ki, kk, ldwork, lwkmin, lwkopt, m1, mu, nb, nbmin, & nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_clarzt( 'BACKWARD', 'ROWWISE', n-m, ib, a( i, m1 ),lda, tau( i ), & work, ldwork ) ! apply h to a(1:i-1,i:n) from the right call stdlib${ii}$_clarzb( 'RIGHT', 'NO TRANSPOSE', 'BACKWARD','ROWWISE', i-1, n-i+1,& ib, n-m, a( i, m1 ),lda, work, ldwork, a( 1_${ik}$, i ), lda,work( ib+1 ), ldwork ) end if end do mu = i + nb - 1_${ik}$ else mu = m end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ )call stdlib${ii}$_clatrz( mu, n, n-m, a, lda, tau, work ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_ctzrzf pure module subroutine stdlib${ii}$_ztzrzf( m, n, a, lda, tau, work, lwork, info ) !! ZTZRZF reduces the M-by-N ( M<=N ) complex upper trapezoidal matrix A !! to upper triangular form by means of unitary transformations. !! The upper trapezoidal matrix A is factored as !! A = ( R 0 ) * Z, !! where Z is an N-by-N unitary matrix and R is an M-by-M upper !! triangular matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iws, ki, kk, ldwork, lwkmin, lwkopt, m1, mu, nb, nbmin, & nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_zlarzt( 'BACKWARD', 'ROWWISE', n-m, ib, a( i, m1 ),lda, tau( i ), & work, ldwork ) ! apply h to a(1:i-1,i:n) from the right call stdlib${ii}$_zlarzb( 'RIGHT', 'NO TRANSPOSE', 'BACKWARD','ROWWISE', i-1, n-i+1,& ib, n-m, a( i, m1 ),lda, work, ldwork, a( 1_${ik}$, i ), lda,work( ib+1 ), ldwork ) end if end do mu = i + nb - 1_${ik}$ else mu = m end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ )call stdlib${ii}$_zlatrz( mu, n, n-m, a, lda, tau, work ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_ztzrzf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tzrzf( m, n, a, lda, tau, work, lwork, info ) !! ZTZRZF: reduces the M-by-N ( M<=N ) complex upper trapezoidal matrix A !! to upper triangular form by means of unitary transformations. !! The upper trapezoidal matrix A is factored as !! A = ( R 0 ) * Z, !! where Z is an N-by-N unitary matrix and R is an M-by-M upper !! triangular matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iws, ki, kk, ldwork, lwkmin, lwkopt, m1, mu, nb, nbmin, & nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_${ci}$larzt( 'BACKWARD', 'ROWWISE', n-m, ib, a( i, m1 ),lda, tau( i ), & work, ldwork ) ! apply h to a(1:i-1,i:n) from the right call stdlib${ii}$_${ci}$larzb( 'RIGHT', 'NO TRANSPOSE', 'BACKWARD','ROWWISE', i-1, n-i+1,& ib, n-m, a( i, m1 ),lda, work, ldwork, a( 1_${ik}$, i ), lda,work( ib+1 ), ldwork ) end if end do mu = i + nb - 1_${ik}$ else mu = m end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ )call stdlib${ii}$_${ci}$latrz( mu, n, n-m, a, lda, tau, work ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$tzrzf #:endif #:endfor pure module subroutine stdlib${ii}$_cunmrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & !! CUNMRZ overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by CTZRZF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran character :: transt integer(${ik}$) :: i, i1, i2, i3, ib, ic, iinfo, iwt, ja, jc, ldwork, lwkopt, mi, nb, & nbmin, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_cunmr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. .not.notran ) .or.( .not.left .and. notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ ja = m - l + 1_${ik}$ else mi = m ic = 1_${ik}$ ja = n - l + 1_${ik}$ end if if( notran ) then transt = 'C' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_clarzt( 'BACKWARD', 'ROWWISE', l, ib, a( i, ja ), lda,tau( i ), work(& iwt ), ldt ) if( left ) then ! h or h**h is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**h is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**h call stdlib${ii}$_clarzb( side, transt, 'BACKWARD', 'ROWWISE', mi, ni,ib, l, a( i, ja )& , lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cunmrz pure module subroutine stdlib${ii}$_zunmrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & !! ZUNMRZ overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by ZTZRZF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran character :: transt integer(${ik}$) :: i, i1, i2, i3, ib, ic, iinfo, iwt, ja, jc, ldwork, lwkopt, mi, nb, & nbmin, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_zunmr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. .not.notran ) .or.( .not.left .and. notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ ja = m - l + 1_${ik}$ else mi = m ic = 1_${ik}$ ja = n - l + 1_${ik}$ end if if( notran ) then transt = 'C' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_zlarzt( 'BACKWARD', 'ROWWISE', l, ib, a( i, ja ), lda,tau( i ), work(& iwt ), ldt ) if( left ) then ! h or h**h is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**h is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**h call stdlib${ii}$_zlarzb( side, transt, 'BACKWARD', 'ROWWISE', mi, ni,ib, l, a( i, ja )& , lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zunmrz #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unmrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & !! ZUNMRZ: overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by ZTZRZF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran character :: transt integer(${ik}$) :: i, i1, i2, i3, ib, ic, iinfo, iwt, ja, jc, ldwork, lwkopt, mi, nb, & nbmin, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_${ci}$unmr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. .not.notran ) .or.( .not.left .and. notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ ja = m - l + 1_${ik}$ else mi = m ic = 1_${ik}$ ja = n - l + 1_${ik}$ end if if( notran ) then transt = 'C' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_${ci}$larzt( 'BACKWARD', 'ROWWISE', l, ib, a( i, ja ), lda,tau( i ), work(& iwt ), ldt ) if( left ) then ! h or h**h is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**h is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**h call stdlib${ii}$_${ci}$larzb( side, transt, 'BACKWARD', 'ROWWISE', mi, ni,ib, l, a( i, ja )& , lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$unmrz #:endif #:endfor pure module subroutine stdlib${ii}$_sormrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & !! SORMRZ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by STZRZF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran character :: transt integer(${ik}$) :: i, i1, i2, i3, ib, ic, iinfo, iwt, ja, jc, ldwork, lwkopt, mi, nb, & nbmin, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_sormr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. .not.notran ) .or.( .not.left .and. notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ ja = m - l + 1_${ik}$ else mi = m ic = 1_${ik}$ ja = n - l + 1_${ik}$ end if if( notran ) then transt = 'T' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_slarzt( 'BACKWARD', 'ROWWISE', l, ib, a( i, ja ), lda,tau( i ), work(& iwt ), ldt ) if( left ) then ! h or h**t is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**t is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**t call stdlib${ii}$_slarzb( side, transt, 'BACKWARD', 'ROWWISE', mi, ni,ib, l, a( i, ja )& , lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_sormrz pure module subroutine stdlib${ii}$_dormrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & !! DORMRZ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by DTZRZF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran character :: transt integer(${ik}$) :: i, i1, i2, i3, ib, ic, iinfo, iwt, ja, jc, ldwork, lwkopt, mi, nb, & nbmin, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_dormr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. .not.notran ) .or.( .not.left .and. notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ ja = m - l + 1_${ik}$ else mi = m ic = 1_${ik}$ ja = n - l + 1_${ik}$ end if if( notran ) then transt = 'T' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_dlarzt( 'BACKWARD', 'ROWWISE', l, ib, a( i, ja ), lda,tau( i ), work(& iwt ), ldt ) if( left ) then ! h or h**t is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**t is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**t call stdlib${ii}$_dlarzb( side, transt, 'BACKWARD', 'ROWWISE', mi, ni,ib, l, a( i, ja )& , lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dormrz #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ormrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & !! DORMRZ: overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by DTZRZF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran character :: transt integer(${ik}$) :: i, i1, i2, i3, ib, ic, iinfo, iwt, ja, jc, ldwork, lwkopt, mi, nb, & nbmin, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_${ri}$ormr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. .not.notran ) .or.( .not.left .and. notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ ja = m - l + 1_${ik}$ else mi = m ic = 1_${ik}$ ja = n - l + 1_${ik}$ end if if( notran ) then transt = 'T' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_${ri}$larzt( 'BACKWARD', 'ROWWISE', l, ib, a( i, ja ), lda,tau( i ), work(& iwt ), ldt ) if( left ) then ! h or h**t is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**t is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**t call stdlib${ii}$_${ri}$larzb( side, transt, 'BACKWARD', 'ROWWISE', mi, ni,ib, l, a( i, ja )& , lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$ormrz #:endif #:endfor pure module subroutine stdlib${ii}$_cunmr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, info ) !! CUNMR3 overwrites the general complex m by n matrix C with !! Q * C if SIDE = 'L' and TRANS = 'N', or !! Q**H* C if SIDE = 'L' and TRANS = 'C', or !! C * Q if SIDE = 'R' and TRANS = 'N', or !! C * Q**H if SIDE = 'R' and TRANS = 'C', !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by CTZRZF. Q is of order m if SIDE = 'L' and of order n !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, m, n ! Array Arguments complex(sp), intent(in) :: a(lda,*), tau(*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, notran integer(${ik}$) :: i, i1, i2, i3, ic, ja, jc, mi, ni, nq complex(sp) :: taui ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) ! nq is the order of q if( left ) then nq = m else nq = n end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. ( left .and. ( l>m ) ) .or.( .not.left .and. ( l>n ) ) ) then info = -6_${ik}$ else if( lda0_${ik}$ )call stdlib${ii}$_sgemm( 'TRANSPOSE', 'TRANSPOSE', n, k, l, one,c( m-l+1, 1_${ik}$ ), & ldc, v, ldv, one, work, ldwork ) ! w( 1:n, 1:k ) = w( 1:n, 1:k ) * t**t or w( 1:m, 1:k ) * t call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k, one, t,ldt, work, & ldwork ) ! c( 1:k, 1:n ) = c( 1:k, 1:n ) - w( 1:n, 1:k )**t do j = 1, n do i = 1, k c( i, j ) = c( i, j ) - work( j, i ) end do end do ! c( m-l+1:m, 1:n ) = c( m-l+1:m, 1:n ) - ... ! v( 1:k, 1:l )**t * w( 1:n, 1:k )**t if( l>0_${ik}$ )call stdlib${ii}$_sgemm( 'TRANSPOSE', 'TRANSPOSE', l, n, k, -one, v, ldv,work, & ldwork, one, c( m-l+1, 1_${ik}$ ), ldc ) else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t ! w( 1:m, 1:k ) = c( 1:m, 1:k ) do j = 1, k call stdlib${ii}$_scopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w( 1:m, 1:k ) = w( 1:m, 1:k ) + ... ! c( 1:m, n-l+1:n ) * v( 1:k, 1:l )**t if( l>0_${ik}$ )call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, l, one,c( 1_${ik}$, n-l+1 ),& ldc, v, ldv, one, work, ldwork ) ! w( 1:m, 1:k ) = w( 1:m, 1:k ) * t or w( 1:m, 1:k ) * t**t call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k, one, t,ldt, work, & ldwork ) ! c( 1:m, 1:k ) = c( 1:m, 1:k ) - w( 1:m, 1:k ) do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do ! c( 1:m, n-l+1:n ) = c( 1:m, n-l+1:n ) - ... ! w( 1:m, 1:k ) * v( 1:k, 1:l ) if( l>0_${ik}$ )call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, l, k, -one,work, & ldwork, v, ldv, one, c( 1_${ik}$, n-l+1 ), ldc ) end if return end subroutine stdlib${ii}$_slarzb pure module subroutine stdlib${ii}$_dlarzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & !! DLARZB applies a real block reflector H or its transpose H**T to !! a real distributed M-by-N C from the left or the right. !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. ldc, work, ldwork ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, ldc, ldt, ldv, ldwork, m, n ! Array Arguments real(dp), intent(inout) :: c(ldc,*), t(ldt,*), v(ldv,*) real(dp), intent(out) :: work(ldwork,*) ! ===================================================================== ! Local Scalars character :: transt integer(${ik}$) :: i, info, j ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return ! check for currently supported options info = 0_${ik}$ if( .not.stdlib_lsame( direct, 'B' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( storev, 'R' ) ) then info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLARZB', -info ) return end if if( stdlib_lsame( trans, 'N' ) ) then transt = 'T' else transt = 'N' end if if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c ! w( 1:n, 1:k ) = c( 1:k, 1:n )**t do j = 1, k call stdlib${ii}$_dcopy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w( 1:n, 1:k ) = w( 1:n, 1:k ) + ... ! c( m-l+1:m, 1:n )**t * v( 1:k, 1:l )**t if( l>0_${ik}$ )call stdlib${ii}$_dgemm( 'TRANSPOSE', 'TRANSPOSE', n, k, l, one,c( m-l+1, 1_${ik}$ ), & ldc, v, ldv, one, work, ldwork ) ! w( 1:n, 1:k ) = w( 1:n, 1:k ) * t**t or w( 1:m, 1:k ) * t call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k, one, t,ldt, work, & ldwork ) ! c( 1:k, 1:n ) = c( 1:k, 1:n ) - w( 1:n, 1:k )**t do j = 1, n do i = 1, k c( i, j ) = c( i, j ) - work( j, i ) end do end do ! c( m-l+1:m, 1:n ) = c( m-l+1:m, 1:n ) - ... ! v( 1:k, 1:l )**t * w( 1:n, 1:k )**t if( l>0_${ik}$ )call stdlib${ii}$_dgemm( 'TRANSPOSE', 'TRANSPOSE', l, n, k, -one, v, ldv,work, & ldwork, one, c( m-l+1, 1_${ik}$ ), ldc ) else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t ! w( 1:m, 1:k ) = c( 1:m, 1:k ) do j = 1, k call stdlib${ii}$_dcopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w( 1:m, 1:k ) = w( 1:m, 1:k ) + ... ! c( 1:m, n-l+1:n ) * v( 1:k, 1:l )**t if( l>0_${ik}$ )call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, l, one,c( 1_${ik}$, n-l+1 ),& ldc, v, ldv, one, work, ldwork ) ! w( 1:m, 1:k ) = w( 1:m, 1:k ) * t or w( 1:m, 1:k ) * t**t call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k, one, t,ldt, work, & ldwork ) ! c( 1:m, 1:k ) = c( 1:m, 1:k ) - w( 1:m, 1:k ) do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do ! c( 1:m, n-l+1:n ) = c( 1:m, n-l+1:n ) - ... ! w( 1:m, 1:k ) * v( 1:k, 1:l ) if( l>0_${ik}$ )call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, l, k, -one,work, & ldwork, v, ldv, one, c( 1_${ik}$, n-l+1 ), ldc ) end if return end subroutine stdlib${ii}$_dlarzb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & !! DLARZB: applies a real block reflector H or its transpose H**T to !! a real distributed M-by-N C from the left or the right. !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. ldc, work, ldwork ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, ldc, ldt, ldv, ldwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: c(ldc,*), t(ldt,*), v(ldv,*) real(${rk}$), intent(out) :: work(ldwork,*) ! ===================================================================== ! Local Scalars character :: transt integer(${ik}$) :: i, info, j ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return ! check for currently supported options info = 0_${ik}$ if( .not.stdlib_lsame( direct, 'B' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( storev, 'R' ) ) then info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLARZB', -info ) return end if if( stdlib_lsame( trans, 'N' ) ) then transt = 'T' else transt = 'N' end if if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c ! w( 1:n, 1:k ) = c( 1:k, 1:n )**t do j = 1, k call stdlib${ii}$_${ri}$copy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w( 1:n, 1:k ) = w( 1:n, 1:k ) + ... ! c( m-l+1:m, 1:n )**t * v( 1:k, 1:l )**t if( l>0_${ik}$ )call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'TRANSPOSE', n, k, l, one,c( m-l+1, 1_${ik}$ ), & ldc, v, ldv, one, work, ldwork ) ! w( 1:n, 1:k ) = w( 1:n, 1:k ) * t**t or w( 1:m, 1:k ) * t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k, one, t,ldt, work, & ldwork ) ! c( 1:k, 1:n ) = c( 1:k, 1:n ) - w( 1:n, 1:k )**t do j = 1, n do i = 1, k c( i, j ) = c( i, j ) - work( j, i ) end do end do ! c( m-l+1:m, 1:n ) = c( m-l+1:m, 1:n ) - ... ! v( 1:k, 1:l )**t * w( 1:n, 1:k )**t if( l>0_${ik}$ )call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'TRANSPOSE', l, n, k, -one, v, ldv,work, & ldwork, one, c( m-l+1, 1_${ik}$ ), ldc ) else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t ! w( 1:m, 1:k ) = c( 1:m, 1:k ) do j = 1, k call stdlib${ii}$_${ri}$copy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w( 1:m, 1:k ) = w( 1:m, 1:k ) + ... ! c( 1:m, n-l+1:n ) * v( 1:k, 1:l )**t if( l>0_${ik}$ )call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, l, one,c( 1_${ik}$, n-l+1 ),& ldc, v, ldv, one, work, ldwork ) ! w( 1:m, 1:k ) = w( 1:m, 1:k ) * t or w( 1:m, 1:k ) * t**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k, one, t,ldt, work, & ldwork ) ! c( 1:m, 1:k ) = c( 1:m, 1:k ) - w( 1:m, 1:k ) do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do ! c( 1:m, n-l+1:n ) = c( 1:m, n-l+1:n ) - ... ! w( 1:m, 1:k ) * v( 1:k, 1:l ) if( l>0_${ik}$ )call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, l, k, -one,work, & ldwork, v, ldv, one, c( 1_${ik}$, n-l+1 ), ldc ) end if return end subroutine stdlib${ii}$_${ri}$larzb #:endif #:endfor pure module subroutine stdlib${ii}$_clarzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & !! CLARZB applies a complex block reflector H or its transpose H**H !! to a complex distributed M-by-N C from the left or the right. !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. ldc, work, ldwork ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, ldc, ldt, ldv, ldwork, m, n ! Array Arguments complex(sp), intent(inout) :: c(ldc,*), t(ldt,*), v(ldv,*) complex(sp), intent(out) :: work(ldwork,*) ! ===================================================================== ! Local Scalars character :: transt integer(${ik}$) :: i, info, j ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return ! check for currently supported options info = 0_${ik}$ if( .not.stdlib_lsame( direct, 'B' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( storev, 'R' ) ) then info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CLARZB', -info ) return end if if( stdlib_lsame( trans, 'N' ) ) then transt = 'C' else transt = 'N' end if if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c ! w( 1:n, 1:k ) = c( 1:k, 1:n )**h do j = 1, k call stdlib${ii}$_ccopy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w( 1:n, 1:k ) = w( 1:n, 1:k ) + ... ! c( m-l+1:m, 1:n )**h * v( 1:k, 1:l )**t if( l>0_${ik}$ )call stdlib${ii}$_cgemm( 'TRANSPOSE', 'CONJUGATE TRANSPOSE', n, k, l,cone, c( m-& l+1, 1_${ik}$ ), ldc, v, ldv, cone, work,ldwork ) ! w( 1:n, 1:k ) = w( 1:n, 1:k ) * t**t or w( 1:m, 1:k ) * t call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k, cone, t,ldt, work, & ldwork ) ! c( 1:k, 1:n ) = c( 1:k, 1:n ) - w( 1:n, 1:k )**h do j = 1, n do i = 1, k c( i, j ) = c( i, j ) - work( j, i ) end do end do ! c( m-l+1:m, 1:n ) = c( m-l+1:m, 1:n ) - ... ! v( 1:k, 1:l )**h * w( 1:n, 1:k )**h if( l>0_${ik}$ )call stdlib${ii}$_cgemm( 'TRANSPOSE', 'TRANSPOSE', l, n, k, -cone, v, ldv,work, & ldwork, cone, c( m-l+1, 1_${ik}$ ), ldc ) else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h ! w( 1:m, 1:k ) = c( 1:m, 1:k ) do j = 1, k call stdlib${ii}$_ccopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w( 1:m, 1:k ) = w( 1:m, 1:k ) + ... ! c( 1:m, n-l+1:n ) * v( 1:k, 1:l )**h if( l>0_${ik}$ )call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, l, cone,c( 1_${ik}$, n-l+1 )& , ldc, v, ldv, cone, work, ldwork ) ! w( 1:m, 1:k ) = w( 1:m, 1:k ) * conjg( t ) or ! w( 1:m, 1:k ) * t**h do j = 1, k call stdlib${ii}$_clacgv( k-j+1, t( j, j ), 1_${ik}$ ) end do call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k, cone, t,ldt, work, & ldwork ) do j = 1, k call stdlib${ii}$_clacgv( k-j+1, t( j, j ), 1_${ik}$ ) end do ! c( 1:m, 1:k ) = c( 1:m, 1:k ) - w( 1:m, 1:k ) do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do ! c( 1:m, n-l+1:n ) = c( 1:m, n-l+1:n ) - ... ! w( 1:m, 1:k ) * conjg( v( 1:k, 1:l ) ) do j = 1, l call stdlib${ii}$_clacgv( k, v( 1_${ik}$, j ), 1_${ik}$ ) end do if( l>0_${ik}$ )call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, l, k, -cone,work, & ldwork, v, ldv, cone, c( 1_${ik}$, n-l+1 ), ldc ) do j = 1, l call stdlib${ii}$_clacgv( k, v( 1_${ik}$, j ), 1_${ik}$ ) end do end if return end subroutine stdlib${ii}$_clarzb pure module subroutine stdlib${ii}$_zlarzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & !! ZLARZB applies a complex block reflector H or its transpose H**H !! to a complex distributed M-by-N C from the left or the right. !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. ldc, work, ldwork ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, ldc, ldt, ldv, ldwork, m, n ! Array Arguments complex(dp), intent(inout) :: c(ldc,*), t(ldt,*), v(ldv,*) complex(dp), intent(out) :: work(ldwork,*) ! ===================================================================== ! Local Scalars character :: transt integer(${ik}$) :: i, info, j ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return ! check for currently supported options info = 0_${ik}$ if( .not.stdlib_lsame( direct, 'B' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( storev, 'R' ) ) then info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLARZB', -info ) return end if if( stdlib_lsame( trans, 'N' ) ) then transt = 'C' else transt = 'N' end if if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c ! w( 1:n, 1:k ) = c( 1:k, 1:n )**h do j = 1, k call stdlib${ii}$_zcopy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w( 1:n, 1:k ) = w( 1:n, 1:k ) + ... ! c( m-l+1:m, 1:n )**h * v( 1:k, 1:l )**t if( l>0_${ik}$ )call stdlib${ii}$_zgemm( 'TRANSPOSE', 'CONJUGATE TRANSPOSE', n, k, l,cone, c( m-& l+1, 1_${ik}$ ), ldc, v, ldv, cone, work,ldwork ) ! w( 1:n, 1:k ) = w( 1:n, 1:k ) * t**t or w( 1:m, 1:k ) * t call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k, cone, t,ldt, work, & ldwork ) ! c( 1:k, 1:n ) = c( 1:k, 1:n ) - w( 1:n, 1:k )**h do j = 1, n do i = 1, k c( i, j ) = c( i, j ) - work( j, i ) end do end do ! c( m-l+1:m, 1:n ) = c( m-l+1:m, 1:n ) - ... ! v( 1:k, 1:l )**h * w( 1:n, 1:k )**h if( l>0_${ik}$ )call stdlib${ii}$_zgemm( 'TRANSPOSE', 'TRANSPOSE', l, n, k, -cone, v, ldv,work, & ldwork, cone, c( m-l+1, 1_${ik}$ ), ldc ) else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h ! w( 1:m, 1:k ) = c( 1:m, 1:k ) do j = 1, k call stdlib${ii}$_zcopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w( 1:m, 1:k ) = w( 1:m, 1:k ) + ... ! c( 1:m, n-l+1:n ) * v( 1:k, 1:l )**h if( l>0_${ik}$ )call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, l, cone,c( 1_${ik}$, n-l+1 )& , ldc, v, ldv, cone, work, ldwork ) ! w( 1:m, 1:k ) = w( 1:m, 1:k ) * conjg( t ) or ! w( 1:m, 1:k ) * t**h do j = 1, k call stdlib${ii}$_zlacgv( k-j+1, t( j, j ), 1_${ik}$ ) end do call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k, cone, t,ldt, work, & ldwork ) do j = 1, k call stdlib${ii}$_zlacgv( k-j+1, t( j, j ), 1_${ik}$ ) end do ! c( 1:m, 1:k ) = c( 1:m, 1:k ) - w( 1:m, 1:k ) do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do ! c( 1:m, n-l+1:n ) = c( 1:m, n-l+1:n ) - ... ! w( 1:m, 1:k ) * conjg( v( 1:k, 1:l ) ) do j = 1, l call stdlib${ii}$_zlacgv( k, v( 1_${ik}$, j ), 1_${ik}$ ) end do if( l>0_${ik}$ )call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, l, k, -cone,work, & ldwork, v, ldv, cone, c( 1_${ik}$, n-l+1 ), ldc ) do j = 1, l call stdlib${ii}$_zlacgv( k, v( 1_${ik}$, j ), 1_${ik}$ ) end do end if return end subroutine stdlib${ii}$_zlarzb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & !! ZLARZB: applies a complex block reflector H or its transpose H**H !! to a complex distributed M-by-N C from the left or the right. !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. ldc, work, ldwork ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, ldc, ldt, ldv, ldwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: c(ldc,*), t(ldt,*), v(ldv,*) complex(${ck}$), intent(out) :: work(ldwork,*) ! ===================================================================== ! Local Scalars character :: transt integer(${ik}$) :: i, info, j ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return ! check for currently supported options info = 0_${ik}$ if( .not.stdlib_lsame( direct, 'B' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( storev, 'R' ) ) then info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLARZB', -info ) return end if if( stdlib_lsame( trans, 'N' ) ) then transt = 'C' else transt = 'N' end if if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c ! w( 1:n, 1:k ) = c( 1:k, 1:n )**h do j = 1, k call stdlib${ii}$_${ci}$copy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w( 1:n, 1:k ) = w( 1:n, 1:k ) + ... ! c( m-l+1:m, 1:n )**h * v( 1:k, 1:l )**t if( l>0_${ik}$ )call stdlib${ii}$_${ci}$gemm( 'TRANSPOSE', 'CONJUGATE TRANSPOSE', n, k, l,cone, c( m-& l+1, 1_${ik}$ ), ldc, v, ldv, cone, work,ldwork ) ! w( 1:n, 1:k ) = w( 1:n, 1:k ) * t**t or w( 1:m, 1:k ) * t call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k, cone, t,ldt, work, & ldwork ) ! c( 1:k, 1:n ) = c( 1:k, 1:n ) - w( 1:n, 1:k )**h do j = 1, n do i = 1, k c( i, j ) = c( i, j ) - work( j, i ) end do end do ! c( m-l+1:m, 1:n ) = c( m-l+1:m, 1:n ) - ... ! v( 1:k, 1:l )**h * w( 1:n, 1:k )**h if( l>0_${ik}$ )call stdlib${ii}$_${ci}$gemm( 'TRANSPOSE', 'TRANSPOSE', l, n, k, -cone, v, ldv,work, & ldwork, cone, c( m-l+1, 1_${ik}$ ), ldc ) else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h ! w( 1:m, 1:k ) = c( 1:m, 1:k ) do j = 1, k call stdlib${ii}$_${ci}$copy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w( 1:m, 1:k ) = w( 1:m, 1:k ) + ... ! c( 1:m, n-l+1:n ) * v( 1:k, 1:l )**h if( l>0_${ik}$ )call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, l, cone,c( 1_${ik}$, n-l+1 )& , ldc, v, ldv, cone, work, ldwork ) ! w( 1:m, 1:k ) = w( 1:m, 1:k ) * conjg( t ) or ! w( 1:m, 1:k ) * t**h do j = 1, k call stdlib${ii}$_${ci}$lacgv( k-j+1, t( j, j ), 1_${ik}$ ) end do call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k, cone, t,ldt, work, & ldwork ) do j = 1, k call stdlib${ii}$_${ci}$lacgv( k-j+1, t( j, j ), 1_${ik}$ ) end do ! c( 1:m, 1:k ) = c( 1:m, 1:k ) - w( 1:m, 1:k ) do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do ! c( 1:m, n-l+1:n ) = c( 1:m, n-l+1:n ) - ... ! w( 1:m, 1:k ) * conjg( v( 1:k, 1:l ) ) do j = 1, l call stdlib${ii}$_${ci}$lacgv( k, v( 1_${ik}$, j ), 1_${ik}$ ) end do if( l>0_${ik}$ )call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, l, k, -cone,work, & ldwork, v, ldv, cone, c( 1_${ik}$, n-l+1 ), ldc ) do j = 1, l call stdlib${ii}$_${ci}$lacgv( k, v( 1_${ik}$, j ), 1_${ik}$ ) end do end if return end subroutine stdlib${ii}$_${ci}$larzb #:endif #:endfor pure module subroutine stdlib${ii}$_slarzt( direct, storev, n, k, v, ldv, tau, t, ldt ) !! SLARZT forms the triangular factor T of a real block reflector !! H of order > n, which is defined as a product of k elementary !! reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**T !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**T * T * V !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments real(sp), intent(out) :: t(ldt,*) real(sp), intent(in) :: tau(*) real(sp), intent(inout) :: v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, j ! Executable Statements ! check for currently supported options info = 0_${ik}$ if( .not.stdlib_lsame( direct, 'B' ) ) then info = -1_${ik}$ else if( .not.stdlib_lsame( storev, 'R' ) ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SLARZT', -info ) return end if do i = k, 1, -1 if( tau( i )==zero ) then ! h(i) = i do j = i, k t( j, i ) = zero end do else ! general case if( i n, which is defined as a product of k elementary !! reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**T !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**T * T * V !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments real(dp), intent(out) :: t(ldt,*) real(dp), intent(in) :: tau(*) real(dp), intent(inout) :: v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, j ! Executable Statements ! check for currently supported options info = 0_${ik}$ if( .not.stdlib_lsame( direct, 'B' ) ) then info = -1_${ik}$ else if( .not.stdlib_lsame( storev, 'R' ) ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLARZT', -info ) return end if do i = k, 1, -1 if( tau( i )==zero ) then ! h(i) = i do j = i, k t( j, i ) = zero end do else ! general case if( i n, which is defined as a product of k elementary !! reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**T !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**T * T * V !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments real(${rk}$), intent(out) :: t(ldt,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(inout) :: v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, j ! Executable Statements ! check for currently supported options info = 0_${ik}$ if( .not.stdlib_lsame( direct, 'B' ) ) then info = -1_${ik}$ else if( .not.stdlib_lsame( storev, 'R' ) ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLARZT', -info ) return end if do i = k, 1, -1 if( tau( i )==zero ) then ! h(i) = i do j = i, k t( j, i ) = zero end do else ! general case if( i n, which is defined as a product of k elementary !! reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**H !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**H * T * V !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments complex(sp), intent(out) :: t(ldt,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(inout) :: v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, j ! Executable Statements ! check for currently supported options info = 0_${ik}$ if( .not.stdlib_lsame( direct, 'B' ) ) then info = -1_${ik}$ else if( .not.stdlib_lsame( storev, 'R' ) ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CLARZT', -info ) return end if do i = k, 1, -1 if( tau( i )==czero ) then ! h(i) = i do j = i, k t( j, i ) = czero end do else ! general case if( i n, which is defined as a product of k elementary !! reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**H !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**H * T * V !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments complex(dp), intent(out) :: t(ldt,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(inout) :: v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, j ! Executable Statements ! check for currently supported options info = 0_${ik}$ if( .not.stdlib_lsame( direct, 'B' ) ) then info = -1_${ik}$ else if( .not.stdlib_lsame( storev, 'R' ) ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLARZT', -info ) return end if do i = k, 1, -1 if( tau( i )==czero ) then ! h(i) = i do j = i, k t( j, i ) = czero end do else ! general case if( i n, which is defined as a product of k elementary !! reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**H !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**H * T * V !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments complex(${ck}$), intent(out) :: t(ldt,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(inout) :: v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, j ! Executable Statements ! check for currently supported options info = 0_${ik}$ if( .not.stdlib_lsame( direct, 'B' ) ) then info = -1_${ik}$ else if( .not.stdlib_lsame( storev, 'R' ) ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLARZT', -info ) return end if do i = k, 1, -1 if( tau( i )==czero ) then ! h(i) = i do j = i, k t( j, i ) = czero end do else ! general case if( i= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgebrd( m, n, a, lda, d, e, tauq, taup, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(sp), intent(out) :: d(*),e(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: taup(*),tauq(*),work(*) end subroutine cgebrd #else module procedure stdlib${ii}$_cgebrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgebrd( m, n, a, lda, d, e, tauq, taup, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*),e(*),taup(*),tauq(*),work(*) end subroutine dgebrd #else module procedure stdlib${ii}$_dgebrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgebrd( m, n, a, lda, d, e, tauq, taup, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*),e(*),taup(*),tauq(*),work(*) end subroutine sgebrd #else module procedure stdlib${ii}$_sgebrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgebrd( m, n, a, lda, d, e, tauq, taup, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(dp), intent(out) :: d(*),e(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: taup(*),tauq(*),work(*) end subroutine zgebrd #else module procedure stdlib${ii}$_zgebrd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gebrd #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gebrd #:endif #:endfor #:endfor end interface gebrd interface gecon !! GECON estimates the reciprocal of the condition number of a general !! complex matrix A, in either the 1-norm or the infinity-norm, using !! the LU factorization computed by CGETRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as !! RCOND = 1 / ( norm(A) * norm(inv(A)) ). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgecon( norm, n, a, lda, anorm, rcond, work, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond,rwork(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine cgecon #else module procedure stdlib${ii}$_cgecon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgecon( norm, n, a, lda, anorm, rcond, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond,work(*) real(dp), intent(inout) :: a(lda,*) end subroutine dgecon #else module procedure stdlib${ii}$_dgecon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgecon( norm, n, a, lda, anorm, rcond, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond,work(*) real(sp), intent(inout) :: a(lda,*) end subroutine sgecon #else module procedure stdlib${ii}$_sgecon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgecon( norm, n, a, lda, anorm, rcond, work, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond,rwork(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zgecon #else module procedure stdlib${ii}$_zgecon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gecon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gecon #:endif #:endfor #:endfor end interface gecon interface geequ !! GEEQU computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have absolute value 1. !! R(i) and C(j) are restricted to be between SMLNUM = smallest safe !! number and BIGNUM = largest safe number. Use of these scaling !! factors is not guaranteed to reduce the condition number of A but !! works well in practice. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgeequ( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(out) :: amax,colcnd,rowcnd,c(*),r(*) complex(sp), intent(in) :: a(lda,*) end subroutine cgeequ #else module procedure stdlib${ii}$_cgeequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgeequ( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(out) :: amax,colcnd,rowcnd,c(*),r(*) real(dp), intent(in) :: a(lda,*) end subroutine dgeequ #else module procedure stdlib${ii}$_dgeequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgeequ( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(out) :: amax,colcnd,rowcnd,c(*),r(*) real(sp), intent(in) :: a(lda,*) end subroutine sgeequ #else module procedure stdlib${ii}$_sgeequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgeequ( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(out) :: amax,colcnd,rowcnd,c(*),r(*) complex(dp), intent(in) :: a(lda,*) end subroutine zgeequ #else module procedure stdlib${ii}$_zgeequ #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geequ #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geequ #:endif #:endfor #:endfor end interface geequ interface geequb !! GEEQUB computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most !! the radix. !! R(i) and C(j) are restricted to be a power of the radix between !! SMLNUM = smallest safe number and BIGNUM = largest safe number. Use !! of these scaling factors is not guaranteed to reduce the condition !! number of A but works well in practice. !! This routine differs from CGEEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled entries' magnitudes are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgeequb( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(out) :: amax,colcnd,rowcnd,c(*),r(*) complex(sp), intent(in) :: a(lda,*) end subroutine cgeequb #else module procedure stdlib${ii}$_cgeequb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgeequb( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(out) :: amax,colcnd,rowcnd,c(*),r(*) real(dp), intent(in) :: a(lda,*) end subroutine dgeequb #else module procedure stdlib${ii}$_dgeequb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgeequb( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(out) :: amax,colcnd,rowcnd,c(*),r(*) real(sp), intent(in) :: a(lda,*) end subroutine sgeequb #else module procedure stdlib${ii}$_sgeequb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgeequb( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(out) :: amax,colcnd,rowcnd,c(*),r(*) complex(dp), intent(in) :: a(lda,*) end subroutine zgeequb #else module procedure stdlib${ii}$_zgeequb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geequb #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geequb #:endif #:endfor #:endfor end interface geequb interface gees !! GEES computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A complex matrix is in Schur form if it is upper triangular. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgees( jobvs, sort, select, n, a, lda, sdim, w, vs,ldvs, work, lwork, & rwork, bwork, info ) import sp,dp,qp,${ik}$,lk,stdlib_select_c implicit none character, intent(in) :: jobvs,sort integer(${ik}$), intent(out) :: info,sdim integer(${ik}$), intent(in) :: lda,ldvs,lwork,n logical(lk), intent(out) :: bwork(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: vs(ldvs,*),w(*),work(*) procedure(stdlib_select_c) :: select end subroutine cgees #else module procedure stdlib${ii}$_cgees #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgees( jobvs, sort, select, n, a, lda, sdim, wr, wi,vs, ldvs, work, & lwork, bwork, info ) import sp,dp,qp,${ik}$,lk,stdlib_select_d implicit none character, intent(in) :: jobvs,sort integer(${ik}$), intent(out) :: info,sdim integer(${ik}$), intent(in) :: lda,ldvs,lwork,n logical(lk), intent(out) :: bwork(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: vs(ldvs,*),wi(*),work(*),wr(*) procedure(stdlib_select_d) :: select end subroutine dgees #else module procedure stdlib${ii}$_dgees #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgees( jobvs, sort, select, n, a, lda, sdim, wr, wi,vs, ldvs, work, & lwork, bwork, info ) import sp,dp,qp,${ik}$,lk,stdlib_select_s implicit none character, intent(in) :: jobvs,sort integer(${ik}$), intent(out) :: info,sdim integer(${ik}$), intent(in) :: lda,ldvs,lwork,n logical(lk), intent(out) :: bwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: vs(ldvs,*),wi(*),work(*),wr(*) procedure(stdlib_select_s) :: select end subroutine sgees #else module procedure stdlib${ii}$_sgees #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgees( jobvs, sort, select, n, a, lda, sdim, w, vs,ldvs, work, lwork, & rwork, bwork, info ) import sp,dp,qp,${ik}$,lk,stdlib_select_z implicit none character, intent(in) :: jobvs,sort integer(${ik}$), intent(out) :: info,sdim integer(${ik}$), intent(in) :: lda,ldvs,lwork,n logical(lk), intent(out) :: bwork(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: vs(ldvs,*),w(*),work(*) procedure(stdlib_select_z) :: select end subroutine zgees #else module procedure stdlib${ii}$_zgees #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gees #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gees #:endif #:endfor #:endfor end interface gees interface geev !! GEEV computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgeev( jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr,work, lwork, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobvl,jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldvl,ldvr,lwork,n real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: vl(ldvl,*),vr(ldvr,*),w(*),work(*) end subroutine cgeev #else module procedure stdlib${ii}$_cgeev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgeev( jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr,ldvr, work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobvl,jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldvl,ldvr,lwork,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: vl(ldvl,*),vr(ldvr,*),wi(*),work(*),wr(*) end subroutine dgeev #else module procedure stdlib${ii}$_dgeev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgeev( jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr,ldvr, work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobvl,jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldvl,ldvr,lwork,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: vl(ldvl,*),vr(ldvr,*),wi(*),work(*),wr(*) end subroutine sgeev #else module procedure stdlib${ii}$_sgeev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgeev( jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr,work, lwork, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobvl,jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldvl,ldvr,lwork,n real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: vl(ldvl,*),vr(ldvr,*),w(*),work(*) end subroutine zgeev #else module procedure stdlib${ii}$_zgeev #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geev #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geev #:endif #:endfor #:endfor end interface geev interface gehrd !! GEHRD reduces a complex general matrix A to upper Hessenberg form H by !! an unitary similarity transformation: Q**H * A * Q = H . #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,lda,lwork,n integer(${ik}$), intent(out) :: info complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*),work(*) end subroutine cgehrd #else module procedure stdlib${ii}$_cgehrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,lda,lwork,n integer(${ik}$), intent(out) :: info real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*),work(*) end subroutine dgehrd #else module procedure stdlib${ii}$_dgehrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,lda,lwork,n integer(${ik}$), intent(out) :: info real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*),work(*) end subroutine sgehrd #else module procedure stdlib${ii}$_sgehrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,lda,lwork,n integer(${ik}$), intent(out) :: info complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*),work(*) end subroutine zgehrd #else module procedure stdlib${ii}$_zgehrd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gehrd #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gehrd #:endif #:endfor #:endfor end interface gehrd interface gejsv !! GEJSV computes the singular value decomposition (SVD) of a complex M-by-N !! matrix [A], where M >= N. The SVD of [A] is written as !! [A] = [U] * [SIGMA] * [V]^*, !! where [SIGMA] is an N-by-N (M-by-N) matrix which is zero except for its N !! diagonal elements, [U] is an M-by-N (or M-by-M) unitary matrix, and !! [V] is an N-by-N unitary matrix. The diagonal elements of [SIGMA] are !! the singular values of [A]. The columns of [U] and [V] are the left and !! the right singular vectors of [A], respectively. The matrices [U] and [V] !! are computed and stored in the arrays U and V, respectively. The diagonal !! of [SIGMA] is computed and stored in the array SVA. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgejsv( joba, jobu, jobv, jobr, jobt, jobp,m, n, a, lda, sva, u, & ldu, v, ldv,cwork, lwork, rwork, lrwork, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldu,ldv,lwork,lrwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: u(ldu,*),v(ldv,*),cwork(lwork) real(sp), intent(out) :: sva(n),rwork(lrwork) character, intent(in) :: joba,jobp,jobr,jobt,jobu,jobv end subroutine cgejsv #else module procedure stdlib${ii}$_cgejsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgejsv( joba, jobu, jobv, jobr, jobt, jobp,m, n, a, lda, sva, u, & ldu, v, ldv,work, lwork, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldu,ldv,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: sva(n),u(ldu,*),v(ldv,*),work(lwork) character, intent(in) :: joba,jobp,jobr,jobt,jobu,jobv end subroutine dgejsv #else module procedure stdlib${ii}$_dgejsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgejsv( joba, jobu, jobv, jobr, jobt, jobp,m, n, a, lda, sva, u, & ldu, v, ldv,work, lwork, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldu,ldv,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: sva(n),u(ldu,*),v(ldv,*),work(lwork) character, intent(in) :: joba,jobp,jobr,jobt,jobu,jobv end subroutine sgejsv #else module procedure stdlib${ii}$_sgejsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgejsv( joba, jobu, jobv, jobr, jobt, jobp,m, n, a, lda, sva, u, & ldu, v, ldv,cwork, lwork, rwork, lrwork, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldu,ldv,lwork,lrwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: u(ldu,*),v(ldv,*),cwork(lwork) real(dp), intent(out) :: sva(n),rwork(lrwork) character, intent(in) :: joba,jobp,jobr,jobt,jobu,jobv end subroutine zgejsv #else module procedure stdlib${ii}$_zgejsv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gejsv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gejsv #:endif #:endfor #:endfor end interface gejsv interface gelq !! GELQ computes an LQ factorization of a complex M-by-N matrix A: !! A = ( L 0 ) * Q !! where: !! Q is a N-by-N orthogonal matrix; !! L is a lower-triangular M-by-M matrix; !! 0 is a M-by-(N-M) zero matrix, if M < N. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgelq( m, n, a, lda, t, tsize, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,tsize,lwork complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(*),work(*) end subroutine cgelq #else module procedure stdlib${ii}$_cgelq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgelq( m, n, a, lda, t, tsize, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,tsize,lwork real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(*),work(*) end subroutine dgelq #else module procedure stdlib${ii}$_dgelq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgelq( m, n, a, lda, t, tsize, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,tsize,lwork real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(*),work(*) end subroutine sgelq #else module procedure stdlib${ii}$_sgelq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgelq( m, n, a, lda, t, tsize, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,tsize,lwork complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(*),work(*) end subroutine zgelq #else module procedure stdlib${ii}$_zgelq #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelq #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelq #:endif #:endfor #:endfor end interface gelq interface gelqf !! GELQF computes an LQ factorization of a complex M-by-N matrix A: !! A = ( L 0 ) * Q !! where: !! Q is a N-by-N orthogonal matrix; !! L is a lower-triangular M-by-M matrix; !! 0 is a M-by-(N-M) zero matrix, if M < N. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgelqf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*),work(*) end subroutine cgelqf #else module procedure stdlib${ii}$_cgelqf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgelqf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*),work(*) end subroutine dgelqf #else module procedure stdlib${ii}$_dgelqf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgelqf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*),work(*) end subroutine sgelqf #else module procedure stdlib${ii}$_sgelqf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgelqf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*),work(*) end subroutine zgelqf #else module procedure stdlib${ii}$_zgelqf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelqf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelqf #:endif #:endfor #:endfor end interface gelqf interface gelqt !! GELQT computes a blocked LQ factorization of a complex M-by-N matrix A !! using the compact WY representation of Q. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgelqt( m, n, mb, a, lda, t, ldt, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,mb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*),work(*) end subroutine cgelqt #else module procedure stdlib${ii}$_cgelqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgelqt( m, n, mb, a, lda, t, ldt, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,mb real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*),work(*) end subroutine dgelqt #else module procedure stdlib${ii}$_dgelqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgelqt( m, n, mb, a, lda, t, ldt, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,mb real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*),work(*) end subroutine sgelqt #else module procedure stdlib${ii}$_sgelqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgelqt( m, n, mb, a, lda, t, ldt, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,mb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*),work(*) end subroutine zgelqt #else module procedure stdlib${ii}$_zgelqt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelqt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelqt #:endif #:endfor #:endfor end interface gelqt interface gelqt3 !! GELQT3 recursively computes a LQ factorization of a complex M-by-N !! matrix A, using the compact WY representation of Q. !! Based on the algorithm of Elmroth and Gustavson, !! IBM J. Res. Develop. Vol 44 No. 4 July 2000. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine cgelqt3( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,ldt complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*) end subroutine cgelqt3 #else module procedure stdlib${ii}$_cgelqt3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine dgelqt3( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,ldt real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*) end subroutine dgelqt3 #else module procedure stdlib${ii}$_dgelqt3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine sgelqt3( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,ldt real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*) end subroutine sgelqt3 #else module procedure stdlib${ii}$_sgelqt3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine zgelqt3( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,ldt complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*) end subroutine zgelqt3 #else module procedure stdlib${ii}$_zgelqt3 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelqt3 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelqt3 #:endif #:endfor #:endfor end interface gelqt3 interface gels !! GELS solves overdetermined or underdetermined complex linear systems !! involving an M-by-N matrix A, or its conjugate-transpose, using a QR !! or LQ factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'C' and m >= n: find the minimum norm solution of !! an underdetermined system A**H * X = B. !! 4. If TRANS = 'C' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**H * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgels( trans, m, n, nrhs, a, lda, b, ldb, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine cgels #else module procedure stdlib${ii}$_cgels #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgels( trans, m, n, nrhs, a, lda, b, ldb, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: work(*) end subroutine dgels #else module procedure stdlib${ii}$_dgels #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgels( trans, m, n, nrhs, a, lda, b, ldb, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: work(*) end subroutine sgels #else module procedure stdlib${ii}$_sgels #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgels( trans, m, n, nrhs, a, lda, b, ldb, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zgels #else module procedure stdlib${ii}$_zgels #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gels #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gels #:endif #:endfor #:endfor end interface gels interface gelsd !! GELSD computes the minimum-norm solution to a real linear least !! squares problem: !! minimize 2-norm(| b - A*x |) !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. !! The problem is solved in three steps: !! (1) Reduce the coefficient matrix A to bidiagonal form with !! Householder transformations, reducing the original problem !! into a "bidiagonal least squares problem" (BLS) !! (2) Solve the BLS using a divide and conquer approach. !! (3) Apply back all the Householder transformations to solve !! the original least squares problem. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgelsd( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, rwork, & iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank,iwork(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(sp), intent(in) :: rcond real(sp), intent(out) :: rwork(*),s(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine cgelsd #else module procedure stdlib${ii}$_cgelsd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgelsd( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, iwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank,iwork(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(dp), intent(in) :: rcond real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: s(*),work(*) end subroutine dgelsd #else module procedure stdlib${ii}$_dgelsd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgelsd( m, n, nrhs, a, lda, b, ldb, s, rcond,rank, work, lwork, iwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank,iwork(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(sp), intent(in) :: rcond real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: s(*),work(*) end subroutine sgelsd #else module procedure stdlib${ii}$_sgelsd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgelsd( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, rwork, & iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank,iwork(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(dp), intent(in) :: rcond real(dp), intent(out) :: rwork(*),s(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zgelsd #else module procedure stdlib${ii}$_zgelsd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelsd #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelsd #:endif #:endfor #:endfor end interface gelsd interface gelss !! GELSS computes the minimum norm solution to a complex linear !! least squares problem: !! Minimize 2-norm(| b - A*x |). !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix !! X. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgelss( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, rwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(sp), intent(in) :: rcond real(sp), intent(out) :: rwork(*),s(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine cgelss #else module procedure stdlib${ii}$_cgelss #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgelss( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(dp), intent(in) :: rcond real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: s(*),work(*) end subroutine dgelss #else module procedure stdlib${ii}$_dgelss #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgelss( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(sp), intent(in) :: rcond real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: s(*),work(*) end subroutine sgelss #else module procedure stdlib${ii}$_sgelss #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgelss( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, rwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(dp), intent(in) :: rcond real(dp), intent(out) :: rwork(*),s(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zgelss #else module procedure stdlib${ii}$_zgelss #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelss #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelss #:endif #:endfor #:endfor end interface gelss interface gelsy !! GELSY computes the minimum-norm solution to a complex linear least !! squares problem: !! minimize || A * X - B || !! using a complete orthogonal factorization of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. !! The routine first computes a QR factorization with column pivoting: !! A * P = Q * [ R11 R12 ] !! [ 0 R22 ] !! with R11 defined as the largest leading submatrix whose estimated !! condition number is less than 1/RCOND. The order of R11, RANK, !! is the effective rank of A. !! Then, R22 is considered to be negligible, and R12 is annihilated !! by unitary transformations from the right, arriving at the !! complete orthogonal factorization: !! A * P = Q * [ T11 0 ] * Z !! [ 0 0 ] !! The minimum-norm solution is then !! X = P * Z**H [ inv(T11)*Q1**H*B ] !! [ 0 ] !! where Q1 consists of the first RANK columns of Q. !! This routine is basically identical to the original xGELSX except !! three differences: !! o The permutation of matrix B (the right hand side) is faster and !! more simple. !! o The call to the subroutine xGEQPF has been substituted by the !! the call to the subroutine xGEQP3. This subroutine is a Blas-3 !! version of the QR factorization with column pivoting. !! o Matrix B (the right hand side) is updated with Blas-3. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgelsy( m, n, nrhs, a, lda, b, ldb, jpvt, rcond, rank,work, lwork, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(sp), intent(in) :: rcond integer(${ik}$), intent(inout) :: jpvt(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine cgelsy #else module procedure stdlib${ii}$_cgelsy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgelsy( m, n, nrhs, a, lda, b, ldb, jpvt, rcond, rank,work, lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(dp), intent(in) :: rcond integer(${ik}$), intent(inout) :: jpvt(*) real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: work(*) end subroutine dgelsy #else module procedure stdlib${ii}$_dgelsy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgelsy( m, n, nrhs, a, lda, b, ldb, jpvt, rcond, rank,work, lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(sp), intent(in) :: rcond integer(${ik}$), intent(inout) :: jpvt(*) real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: work(*) end subroutine sgelsy #else module procedure stdlib${ii}$_sgelsy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgelsy( m, n, nrhs, a, lda, b, ldb, jpvt, rcond, rank,work, lwork, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,rank integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(dp), intent(in) :: rcond integer(${ik}$), intent(inout) :: jpvt(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zgelsy #else module procedure stdlib${ii}$_zgelsy #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelsy #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gelsy #:endif #:endfor #:endfor end interface gelsy interface gemlq !! GEMLQ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product !! of blocked elementary reflectors computed by short wide !! LQ factorization (CGELQ) #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,tsize,lwork,ldc complex(sp), intent(in) :: a(lda,*),t(*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine cgemlq #else module procedure stdlib${ii}$_cgemlq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,tsize,lwork,ldc real(dp), intent(in) :: a(lda,*),t(*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine dgemlq #else module procedure stdlib${ii}$_dgemlq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,tsize,lwork,ldc real(sp), intent(in) :: a(lda,*),t(*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine sgemlq #else module procedure stdlib${ii}$_sgemlq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,tsize,lwork,ldc complex(dp), intent(in) :: a(lda,*),t(*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine zgemlq #else module procedure stdlib${ii}$_zgemlq #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gemlq #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gemlq #:endif #:endfor #:endfor end interface gemlq interface gemlqt !! GEMLQT overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q C C Q !! TRANS = 'C': Q**H C C Q**H !! where Q is a complex unitary matrix defined as the product of K !! elementary reflectors: !! Q = H(1) H(2) . . . H(K) = I - V T V**H !! generated using the compact WY representation as returned by CGELQT. !! Q is of order M if SIDE = 'L' and of order N if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgemlqt( side, trans, m, n, k, mb, v, ldv, t, ldt,c, ldc, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,ldc,m,n,mb,ldt complex(sp), intent(in) :: v(ldv,*),t(ldt,*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine cgemlqt #else module procedure stdlib${ii}$_cgemlqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgemlqt( side, trans, m, n, k, mb, v, ldv, t, ldt,c, ldc, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,ldc,m,n,mb,ldt real(dp), intent(in) :: v(ldv,*),t(ldt,*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine dgemlqt #else module procedure stdlib${ii}$_dgemlqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgemlqt( side, trans, m, n, k, mb, v, ldv, t, ldt,c, ldc, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,ldc,m,n,mb,ldt real(sp), intent(in) :: v(ldv,*),t(ldt,*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine sgemlqt #else module procedure stdlib${ii}$_sgemlqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgemlqt( side, trans, m, n, k, mb, v, ldv, t, ldt,c, ldc, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,ldc,m,n,mb,ldt complex(dp), intent(in) :: v(ldv,*),t(ldt,*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine zgemlqt #else module procedure stdlib${ii}$_zgemlqt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gemlqt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gemlqt #:endif #:endfor #:endfor end interface gemlqt interface gemqr !! GEMQR overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product !! of blocked elementary reflectors computed by tall skinny !! QR factorization (CGEQR) #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgemqr( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,tsize,lwork,ldc complex(sp), intent(in) :: a(lda,*),t(*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine cgemqr #else module procedure stdlib${ii}$_cgemqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgemqr( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,tsize,lwork,ldc real(dp), intent(in) :: a(lda,*),t(*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine dgemqr #else module procedure stdlib${ii}$_dgemqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgemqr( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,tsize,lwork,ldc real(sp), intent(in) :: a(lda,*),t(*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine sgemqr #else module procedure stdlib${ii}$_sgemqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgemqr( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,tsize,lwork,ldc complex(dp), intent(in) :: a(lda,*),t(*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine zgemqr #else module procedure stdlib${ii}$_zgemqr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gemqr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gemqr #:endif #:endfor #:endfor end interface gemqr interface gemqrt !! GEMQRT overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q C C Q !! TRANS = 'C': Q**H C C Q**H !! where Q is a complex orthogonal matrix defined as the product of K !! elementary reflectors: !! Q = H(1) H(2) . . . H(K) = I - V T V**H !! generated using the compact WY representation as returned by CGEQRT. !! Q is of order M if SIDE = 'L' and of order N if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgemqrt( side, trans, m, n, k, nb, v, ldv, t, ldt,c, ldc, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,ldc,m,n,nb,ldt complex(sp), intent(in) :: v(ldv,*),t(ldt,*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine cgemqrt #else module procedure stdlib${ii}$_cgemqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgemqrt( side, trans, m, n, k, nb, v, ldv, t, ldt,c, ldc, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,ldc,m,n,nb,ldt real(dp), intent(in) :: v(ldv,*),t(ldt,*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine dgemqrt #else module procedure stdlib${ii}$_dgemqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgemqrt( side, trans, m, n, k, nb, v, ldv, t, ldt,c, ldc, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,ldc,m,n,nb,ldt real(sp), intent(in) :: v(ldv,*),t(ldt,*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine sgemqrt #else module procedure stdlib${ii}$_sgemqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgemqrt( side, trans, m, n, k, nb, v, ldv, t, ldt,c, ldc, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,ldc,m,n,nb,ldt complex(dp), intent(in) :: v(ldv,*),t(ldt,*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine zgemqrt #else module procedure stdlib${ii}$_zgemqrt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gemqrt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gemqrt #:endif #:endfor #:endfor end interface gemqrt interface geqlf !! GEQLF computes a QL factorization of a complex M-by-N matrix A: !! A = Q * L. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgeqlf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*),work(*) end subroutine cgeqlf #else module procedure stdlib${ii}$_cgeqlf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgeqlf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*),work(*) end subroutine dgeqlf #else module procedure stdlib${ii}$_dgeqlf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgeqlf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*),work(*) end subroutine sgeqlf #else module procedure stdlib${ii}$_sgeqlf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgeqlf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*),work(*) end subroutine zgeqlf #else module procedure stdlib${ii}$_zgeqlf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqlf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqlf #:endif #:endfor #:endfor end interface geqlf interface geqr !! GEQR computes a QR factorization of a complex M-by-N matrix A: !! A = Q * ( R ), !! ( 0 ) !! where: !! Q is a M-by-M orthogonal matrix; !! R is an upper-triangular N-by-N matrix; !! 0 is a (M-N)-by-N zero matrix, if M > N. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgeqr( m, n, a, lda, t, tsize, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,tsize,lwork complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(*),work(*) end subroutine cgeqr #else module procedure stdlib${ii}$_cgeqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgeqr( m, n, a, lda, t, tsize, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,tsize,lwork real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(*),work(*) end subroutine dgeqr #else module procedure stdlib${ii}$_dgeqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgeqr( m, n, a, lda, t, tsize, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,tsize,lwork real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(*),work(*) end subroutine sgeqr #else module procedure stdlib${ii}$_sgeqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgeqr( m, n, a, lda, t, tsize, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,tsize,lwork complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(*),work(*) end subroutine zgeqr #else module procedure stdlib${ii}$_zgeqr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqr #:endif #:endfor #:endfor end interface geqr interface geqr2p !! GEQR2P computes a QR factorization of a complex m-by-n matrix A: !! A = Q * ( R ), !! ( 0 ) !! where: !! Q is a m-by-m orthogonal matrix; !! R is an upper-triangular n-by-n matrix with nonnegative diagonal !! entries; !! 0 is a (m-n)-by-n zero matrix, if m > n. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgeqr2p( m, n, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*),work(*) end subroutine cgeqr2p #else module procedure stdlib${ii}$_cgeqr2p #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgeqr2p( m, n, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*),work(*) end subroutine dgeqr2p #else module procedure stdlib${ii}$_dgeqr2p #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgeqr2p( m, n, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*),work(*) end subroutine sgeqr2p #else module procedure stdlib${ii}$_sgeqr2p #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgeqr2p( m, n, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*),work(*) end subroutine zgeqr2p #else module procedure stdlib${ii}$_zgeqr2p #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqr2p #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqr2p #:endif #:endfor #:endfor end interface geqr2p interface geqrf !! GEQRF computes a QR factorization of a complex M-by-N matrix A: !! A = Q * ( R ), !! ( 0 ) !! where: !! Q is a M-by-M orthogonal matrix; !! R is an upper-triangular N-by-N matrix; !! 0 is a (M-N)-by-N zero matrix, if M > N. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgeqrf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*),work(*) end subroutine cgeqrf #else module procedure stdlib${ii}$_cgeqrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgeqrf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*),work(*) end subroutine dgeqrf #else module procedure stdlib${ii}$_dgeqrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgeqrf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*),work(*) end subroutine sgeqrf #else module procedure stdlib${ii}$_sgeqrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgeqrf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*),work(*) end subroutine zgeqrf #else module procedure stdlib${ii}$_zgeqrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqrf #:endif #:endfor #:endfor end interface geqrf interface geqrfp !! CGEQR2P computes a QR factorization of a complex M-by-N matrix A: !! A = Q * ( R ), !! ( 0 ) !! where: !! Q is a M-by-M orthogonal matrix; !! R is an upper-triangular N-by-N matrix with nonnegative diagonal !! entries; !! 0 is a (M-N)-by-N zero matrix, if M > N. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgeqrfp( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*),work(*) end subroutine cgeqrfp #else module procedure stdlib${ii}$_cgeqrfp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgeqrfp( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*),work(*) end subroutine dgeqrfp #else module procedure stdlib${ii}$_dgeqrfp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgeqrfp( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*),work(*) end subroutine sgeqrfp #else module procedure stdlib${ii}$_sgeqrfp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgeqrfp( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*),work(*) end subroutine zgeqrfp #else module procedure stdlib${ii}$_zgeqrfp #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqrfp #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqrfp #:endif #:endfor #:endfor end interface geqrfp interface geqrt !! GEQRT computes a blocked QR factorization of a complex M-by-N matrix A !! using the compact WY representation of Q. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgeqrt( m, n, nb, a, lda, t, ldt, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*),work(*) end subroutine cgeqrt #else module procedure stdlib${ii}$_cgeqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgeqrt( m, n, nb, a, lda, t, ldt, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*),work(*) end subroutine dgeqrt #else module procedure stdlib${ii}$_dgeqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgeqrt( m, n, nb, a, lda, t, ldt, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*),work(*) end subroutine sgeqrt #else module procedure stdlib${ii}$_sgeqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgeqrt( m, n, nb, a, lda, t, ldt, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*),work(*) end subroutine zgeqrt #else module procedure stdlib${ii}$_zgeqrt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqrt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqrt #:endif #:endfor #:endfor end interface geqrt interface geqrt2 !! GEQRT2 computes a QR factorization of a complex M-by-N matrix A, !! using the compact WY representation of Q. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgeqrt2( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*) end subroutine cgeqrt2 #else module procedure stdlib${ii}$_cgeqrt2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgeqrt2( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*) end subroutine dgeqrt2 #else module procedure stdlib${ii}$_dgeqrt2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgeqrt2( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*) end subroutine sgeqrt2 #else module procedure stdlib${ii}$_sgeqrt2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgeqrt2( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*) end subroutine zgeqrt2 #else module procedure stdlib${ii}$_zgeqrt2 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqrt2 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqrt2 #:endif #:endfor #:endfor end interface geqrt2 interface geqrt3 !! GEQRT3 recursively computes a QR factorization of a complex M-by-N matrix A, !! using the compact WY representation of Q. !! Based on the algorithm of Elmroth and Gustavson, !! IBM J. Res. Develop. Vol 44 No. 4 July 2000. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine cgeqrt3( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,ldt complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*) end subroutine cgeqrt3 #else module procedure stdlib${ii}$_cgeqrt3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine dgeqrt3( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,ldt real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*) end subroutine dgeqrt3 #else module procedure stdlib${ii}$_dgeqrt3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine sgeqrt3( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,ldt real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*) end subroutine sgeqrt3 #else module procedure stdlib${ii}$_sgeqrt3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine zgeqrt3( m, n, a, lda, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,ldt complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*) end subroutine zgeqrt3 #else module procedure stdlib${ii}$_zgeqrt3 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqrt3 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$geqrt3 #:endif #:endfor #:endfor end interface geqrt3 interface geqp3 !! GEQP3 computes a QR factorization with column pivoting of a real or complex !! M-by-N matrix A: !! !! A * P = Q * R, !! !! where: !! Q is an M-by-min(M, N) orthogonal matrix !! R is an min(M, N)-by-N upper triangular matrix; #:for ik, it, ii in LINALG_INT_KINDS_TYPES #:for rk, rt, ri in RC_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ #:if rk in ["sp", "dp"] #:if rt.startswith("real") pure subroutine ${ri}$geqp3(m, n, a, lda, jpvt, tau, work, lwork, info) import sp, dp, qp, ${ik}$, lk implicit none integer(${ik}$), intent(in) :: m, n, lda, lwork integer(${ik}$), intent(out) :: info integer(${ik}$), intent(inout) :: jpvt(*) ${rt}$, intent(inout) :: a(lda, *) ${rt}$, intent(out) :: tau(*), work(*) end subroutine ${ri}$geqp3 #:else pure subroutine ${ri}$geqp3(m, n, a, lda, jpvt, tau, work, lwork, rwork, info) import sp, dp, qp, ${ik}$, lk implicit none integer(${ik}$), intent(in) :: m, n, lda, lwork integer(${ik}$), intent(out) :: info integer(${ik}$), intent(inout) :: jpvt(*) ${rt}$, intent(inout) :: a(lda, *) ${rt}$, intent(out) :: tau(*), work(*) real(${rk}$), intent(out) :: rwork(*) end subroutine ${ri}$geqp3 #:endif #:else module procedure stdlib${ii}$_${ri}$geqp3 #:endif #else module procedure stdlib${ii}$_${ri}$geqp3 #endif #:endfor #:endfor end interface geqp3 interface gerfs !! GERFS improves the computed solution to a system of linear !! equations and provides error bounds and backward error estimates for !! the solution. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, & ferr, berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs,ipiv(*) real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine cgerfs #else module procedure stdlib${ii}$_cgerfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, & ferr, berr, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs,ipiv(*) real(dp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) real(dp), intent(out) :: berr(*),ferr(*),work(*) real(dp), intent(inout) :: x(ldx,*) end subroutine dgerfs #else module procedure stdlib${ii}$_dgerfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, & ferr, berr, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs,ipiv(*) real(sp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) real(sp), intent(out) :: berr(*),ferr(*),work(*) real(sp), intent(inout) :: x(ldx,*) end subroutine sgerfs #else module procedure stdlib${ii}$_sgerfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, & ferr, berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs,ipiv(*) real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zgerfs #else module procedure stdlib${ii}$_zgerfs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gerfs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gerfs #:endif #:endfor #:endfor end interface gerfs interface gerqf !! GERQF computes an RQ factorization of a complex M-by-N matrix A: !! A = R * Q. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgerqf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*),work(*) end subroutine cgerqf #else module procedure stdlib${ii}$_cgerqf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgerqf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*),work(*) end subroutine dgerqf #else module procedure stdlib${ii}$_dgerqf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgerqf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*),work(*) end subroutine sgerqf #else module procedure stdlib${ii}$_sgerqf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgerqf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*),work(*) end subroutine zgerqf #else module procedure stdlib${ii}$_zgerqf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gerqf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gerqf #:endif #:endfor #:endfor end interface gerqf interface gesdd !! GESDD computes the singular value decomposition (SVD) of a complex !! M-by-N matrix A, optionally computing the left and/or right singular !! vectors, by using divide-and-conquer method. The SVD is written !! A = U * SIGMA * conjugate-transpose(V) !! where SIGMA is an M-by-N matrix which is zero except for its !! min(m,n) diagonal elements, U is an M-by-M unitary matrix, and !! V is an N-by-N unitary matrix. The diagonal elements of SIGMA !! are the singular values of A; they are real and non-negative, and !! are returned in descending order. The first min(m,n) columns of !! U and V are the left and right singular vectors of A. !! Note that the routine returns VT = V**H, not V. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgesdd( jobz, m, n, a, lda, s, u, ldu, vt, ldvt,work, lwork, rwork, & iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldu,ldvt,lwork,m,n real(sp), intent(out) :: rwork(*),s(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: u(ldu,*),vt(ldvt,*),work(*) end subroutine cgesdd #else module procedure stdlib${ii}$_cgesdd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgesdd( jobz, m, n, a, lda, s, u, ldu, vt, ldvt,work, lwork, iwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldu,ldvt,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: s(*),u(ldu,*),vt(ldvt,*),work(*) end subroutine dgesdd #else module procedure stdlib${ii}$_dgesdd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgesdd( jobz, m, n, a, lda, s, u, ldu, vt, ldvt,work, lwork, iwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldu,ldvt,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: s(*),u(ldu,*),vt(ldvt,*),work(*) end subroutine sgesdd #else module procedure stdlib${ii}$_sgesdd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgesdd( jobz, m, n, a, lda, s, u, ldu, vt, ldvt,work, lwork, rwork, & iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldu,ldvt,lwork,m,n real(dp), intent(out) :: rwork(*),s(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: u(ldu,*),vt(ldvt,*),work(*) end subroutine zgesdd #else module procedure stdlib${ii}$_zgesdd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gesdd #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gesdd #:endif #:endfor #:endfor end interface gesdd interface gesv !! GESV computes the solution to a complex system of linear equations !! A * X = B, !! where A is an N-by-N matrix and X and B are N-by-NRHS matrices. !! The LU decomposition with partial pivoting and row interchanges is !! used to factor A as !! A = P * L * U, !! where P is a permutation matrix, L is unit lower triangular, and U is !! upper triangular. The factored form of A is then used to solve the !! system of equations A * X = B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgesv( n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine cgesv #else module procedure stdlib${ii}$_cgesv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgesv( n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,n,nrhs real(dp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine dgesv #else module procedure stdlib${ii}$_dgesv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgesv( n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,n,nrhs real(sp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine sgesv #else module procedure stdlib${ii}$_sgesv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgesv( n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine zgesv #else module procedure stdlib${ii}$_zgesv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gesv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gesv #:endif #:endfor #:endfor end interface gesv interface gesvd !! GESVD computes the singular value decomposition (SVD) of a complex !! M-by-N matrix A, optionally computing the left and/or right singular !! vectors. The SVD is written !! A = U * SIGMA * conjugate-transpose(V) !! where SIGMA is an M-by-N matrix which is zero except for its !! min(m,n) diagonal elements, U is an M-by-M unitary matrix, and !! V is an N-by-N unitary matrix. The diagonal elements of SIGMA !! are the singular values of A; they are real and non-negative, and !! are returned in descending order. The first min(m,n) columns of !! U and V are the left and right singular vectors of A. !! Note that the routine returns V**H, not V. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgesvd( jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt,work, lwork, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu,jobvt integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldu,ldvt,lwork,m,n real(sp), intent(out) :: rwork(*),s(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: u(ldu,*),vt(ldvt,*),work(*) end subroutine cgesvd #else module procedure stdlib${ii}$_cgesvd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgesvd( jobu, jobvt, m, n, a, lda, s, u, ldu,vt, ldvt, work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu,jobvt integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldu,ldvt,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: s(*),u(ldu,*),vt(ldvt,*),work(*) end subroutine dgesvd #else module procedure stdlib${ii}$_dgesvd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgesvd( jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu,jobvt integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldu,ldvt,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: s(*),u(ldu,*),vt(ldvt,*),work(*) end subroutine sgesvd #else module procedure stdlib${ii}$_sgesvd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgesvd( jobu, jobvt, m, n, a, lda, s, u, ldu,vt, ldvt, work, lwork, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu,jobvt integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldu,ldvt,lwork,m,n real(dp), intent(out) :: rwork(*),s(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: u(ldu,*),vt(ldvt,*),work(*) end subroutine zgesvd #else module procedure stdlib${ii}$_zgesvd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gesvd #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gesvd #:endif #:endfor #:endfor end interface gesvd interface gesvdq !! GESVDQ computes the singular value decomposition (SVD) of a complex !! M-by-N matrix A, where M >= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N unitary matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgesvdq( joba, jobp, jobr, jobu, jobv, m, n, a, lda,s, u, ldu, v, ldv, & numrank, iwork, liwork,cwork, lcwork, rwork, lrwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: joba,jobp,jobr,jobu,jobv integer(${ik}$), intent(in) :: m,n,lda,ldu,ldv,liwork,lrwork integer(${ik}$), intent(out) :: numrank,info,iwork(*) integer(${ik}$), intent(inout) :: lcwork complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: u(ldu,*),v(ldv,*),cwork(*) real(sp), intent(out) :: s(*),rwork(*) end subroutine cgesvdq #else module procedure stdlib${ii}$_cgesvdq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgesvdq( joba, jobp, jobr, jobu, jobv, m, n, a, lda,s, u, ldu, v, ldv, & numrank, iwork, liwork,work, lwork, rwork, lrwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: joba,jobp,jobr,jobu,jobv integer(${ik}$), intent(in) :: m,n,lda,ldu,ldv,liwork,lrwork integer(${ik}$), intent(out) :: numrank,info,iwork(*) integer(${ik}$), intent(inout) :: lwork real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: u(ldu,*),v(ldv,*),work(*),s(*),rwork(*) end subroutine dgesvdq #else module procedure stdlib${ii}$_dgesvdq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgesvdq( joba, jobp, jobr, jobu, jobv, m, n, a, lda,s, u, ldu, v, ldv, & numrank, iwork, liwork,work, lwork, rwork, lrwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: joba,jobp,jobr,jobu,jobv integer(${ik}$), intent(in) :: m,n,lda,ldu,ldv,liwork,lrwork integer(${ik}$), intent(out) :: numrank,info,iwork(*) integer(${ik}$), intent(inout) :: lwork real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: u(ldu,*),v(ldv,*),work(*),s(*),rwork(*) end subroutine sgesvdq #else module procedure stdlib${ii}$_sgesvdq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgesvdq( joba, jobp, jobr, jobu, jobv, m, n, a, lda,s, u, ldu, v, ldv, & numrank, iwork, liwork,cwork, lcwork, rwork, lrwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: joba,jobp,jobr,jobu,jobv integer(${ik}$), intent(in) :: m,n,lda,ldu,ldv,liwork,lrwork integer(${ik}$), intent(out) :: numrank,info,iwork(*) integer(${ik}$), intent(inout) :: lcwork complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: u(ldu,*),v(ldv,*),cwork(*) real(dp), intent(out) :: s(*),rwork(*) end subroutine zgesvdq #else module procedure stdlib${ii}$_zgesvdq #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gesvdq #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gesvdq #:endif #:endfor #:endfor end interface gesvdq interface gesvj !! GESVJ computes the singular value decomposition (SVD) of a complex !! M-by-N matrix A, where M >= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N unitary matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgesvj( joba, jobu, jobv, m, n, a, lda, sva, mv, v,ldv, cwork, & lwork, rwork, lrwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,lrwork,m,mv,n character, intent(in) :: joba,jobu,jobv complex(sp), intent(inout) :: a(lda,*),v(ldv,*),cwork(lwork) real(sp), intent(inout) :: rwork(lrwork) real(sp), intent(out) :: sva(n) end subroutine cgesvj #else module procedure stdlib${ii}$_cgesvj #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgesvj( joba, jobu, jobv, m, n, a, lda, sva, mv, v,ldv, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,m,mv,n character, intent(in) :: joba,jobu,jobv real(dp), intent(inout) :: a(lda,*),v(ldv,*),work(lwork) real(dp), intent(out) :: sva(n) end subroutine dgesvj #else module procedure stdlib${ii}$_dgesvj #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgesvj( joba, jobu, jobv, m, n, a, lda, sva, mv, v,ldv, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,m,mv,n character, intent(in) :: joba,jobu,jobv real(sp), intent(inout) :: a(lda,*),v(ldv,*),work(lwork) real(sp), intent(out) :: sva(n) end subroutine sgesvj #else module procedure stdlib${ii}$_sgesvj #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgesvj( joba, jobu, jobv, m, n, a, lda, sva, mv, v,ldv, cwork, & lwork, rwork, lrwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,lrwork,m,mv,n character, intent(in) :: joba,jobu,jobv complex(dp), intent(inout) :: a(lda,*),v(ldv,*),cwork(lwork) real(dp), intent(inout) :: rwork(lrwork) real(dp), intent(out) :: sva(n) end subroutine zgesvj #else module procedure stdlib${ii}$_zgesvj #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gesvj #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gesvj #:endif #:endfor #:endfor end interface gesvj interface getrf !! GETRF computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 3 BLAS version of the algorithm. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgetrf( m, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,m,n complex(sp), intent(inout) :: a(lda,*) end subroutine cgetrf #else module procedure stdlib${ii}$_cgetrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgetrf( m, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(inout) :: a(lda,*) end subroutine dgetrf #else module procedure stdlib${ii}$_dgetrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgetrf( m, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(inout) :: a(lda,*) end subroutine sgetrf #else module procedure stdlib${ii}$_sgetrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgetrf( m, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,m,n complex(dp), intent(inout) :: a(lda,*) end subroutine zgetrf #else module procedure stdlib${ii}$_zgetrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getrf #:endif #:endfor #:endfor end interface getrf interface getrf2 !! GETRF2 computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the recursive version of the algorithm. It divides !! the matrix into four submatrices: !! [ A11 | A12 ] where A11 is n1 by n1 and A22 is n2 by n2 !! A = [ -----|----- ] with n1 = min(m,n)/2 !! [ A21 | A22 ] n2 = n-n1 !! [ A11 ] !! The subroutine calls itself to factor [ --- ], !! [ A12 ] !! [ A12 ] !! do the swaps on [ --- ], solve A12, update A22, !! [ A22 ] !! then calls itself to factor A22 and do the swaps on A21. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine cgetrf2( m, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,m,n complex(sp), intent(inout) :: a(lda,*) end subroutine cgetrf2 #else module procedure stdlib${ii}$_cgetrf2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine dgetrf2( m, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(inout) :: a(lda,*) end subroutine dgetrf2 #else module procedure stdlib${ii}$_dgetrf2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine sgetrf2( m, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(inout) :: a(lda,*) end subroutine sgetrf2 #else module procedure stdlib${ii}$_sgetrf2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine zgetrf2( m, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,m,n complex(dp), intent(inout) :: a(lda,*) end subroutine zgetrf2 #else module procedure stdlib${ii}$_zgetrf2 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getrf2 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getrf2 #:endif #:endfor #:endfor end interface getrf2 interface getri !! GETRI computes the inverse of a matrix using the LU factorization !! computed by CGETRF. !! This method inverts U and then computes inv(A) by solving the system !! inv(A)*L = inv(U) for inv(A). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgetri( n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n,ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine cgetri #else module procedure stdlib${ii}$_cgetri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgetri( n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n,ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*) end subroutine dgetri #else module procedure stdlib${ii}$_dgetri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgetri( n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n,ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*) end subroutine sgetri #else module procedure stdlib${ii}$_sgetri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgetri( n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n,ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zgetri #else module procedure stdlib${ii}$_zgetri #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getri #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getri #:endif #:endfor #:endfor end interface getri interface getrs !! GETRS solves a system of linear equations !! A * X = B, A**T * X = B, or A**H * X = B !! with a general N-by-N matrix A using the LU factorization computed !! by CGETRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgetrs( trans, n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: b(ldb,*) end subroutine cgetrs #else module procedure stdlib${ii}$_cgetrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgetrs( trans, n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: b(ldb,*) end subroutine dgetrs #else module procedure stdlib${ii}$_dgetrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgetrs( trans, n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: b(ldb,*) end subroutine sgetrs #else module procedure stdlib${ii}$_sgetrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgetrs( trans, n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zgetrs #else module procedure stdlib${ii}$_zgetrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getrs #:endif #:endfor #:endfor end interface getrs interface getsls !! GETSLS solves overdetermined or underdetermined complex linear systems !! involving an M-by-N matrix A, using a tall skinny QR or short wide LQ !! factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'C' and m >= n: find the minimum norm solution of !! an undetermined system A**T * X = B. !! 4. If TRANS = 'C' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**T * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgetsls( trans, m, n, nrhs, a, lda, b, ldb,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine cgetsls #else module procedure stdlib${ii}$_cgetsls #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgetsls( trans, m, n, nrhs, a, lda, b, ldb,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: work(*) end subroutine dgetsls #else module procedure stdlib${ii}$_dgetsls #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgetsls( trans, m, n, nrhs, a, lda, b, ldb,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: work(*) end subroutine sgetsls #else module procedure stdlib${ii}$_sgetsls #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgetsls( trans, m, n, nrhs, a, lda, b, ldb,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zgetsls #else module procedure stdlib${ii}$_zgetsls #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getsls #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getsls #:endif #:endfor #:endfor end interface getsls interface getsqrhrt !! GETSQRHRT computes a NB2-sized column blocked QR-factorization !! of a complex M-by-N matrix A with M >= N, !! A = Q * R. !! The routine uses internally a NB1-sized column blocked and MB1-sized !! row blocked TSQR-factorization and perfors the reconstruction !! of the Householder vectors from the TSQR output. The routine also !! converts the R_tsqr factor from the TSQR-factorization output into !! the R factor that corresponds to the Householder QR-factorization, !! A = Q_tsqr * R_tsqr = Q * R. !! The output Q and R factors are stored in the same format as in CGEQRT !! (Q is in blocked compact WY-representation). See the documentation !! of CGEQRT for more details on the format. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgetsqrhrt( m, n, mb1, nb1, nb2, a, lda, t, ldt, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,nb1,nb2,mb1 complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*),work(*) end subroutine cgetsqrhrt #else module procedure stdlib${ii}$_cgetsqrhrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgetsqrhrt( m, n, mb1, nb1, nb2, a, lda, t, ldt, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,nb1,nb2,mb1 real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*),work(*) end subroutine dgetsqrhrt #else module procedure stdlib${ii}$_dgetsqrhrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgetsqrhrt( m, n, mb1, nb1, nb2, a, lda, t, ldt, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,nb1,nb2,mb1 real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*),work(*) end subroutine sgetsqrhrt #else module procedure stdlib${ii}$_sgetsqrhrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgetsqrhrt( m, n, mb1, nb1, nb2, a, lda, t, ldt, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,nb1,nb2,mb1 complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*),work(*) end subroutine zgetsqrhrt #else module procedure stdlib${ii}$_zgetsqrhrt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getsqrhrt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$getsqrhrt #:endif #:endfor #:endfor end interface getsqrhrt interface ggbak !! GGBAK forms the right or left eigenvectors of a complex generalized !! eigenvalue problem A*x = lambda*B*x, by backward transformation on !! the computed eigenvectors of the balanced pair of matrices output by !! CGGBAL. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cggbak( job, side, n, ilo, ihi, lscale, rscale, m, v,ldv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: job,side integer(${ik}$), intent(in) :: ihi,ilo,ldv,m,n integer(${ik}$), intent(out) :: info real(sp), intent(in) :: lscale(*),rscale(*) complex(sp), intent(inout) :: v(ldv,*) end subroutine cggbak #else module procedure stdlib${ii}$_cggbak #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dggbak( job, side, n, ilo, ihi, lscale, rscale, m, v,ldv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: job,side integer(${ik}$), intent(in) :: ihi,ilo,ldv,m,n integer(${ik}$), intent(out) :: info real(dp), intent(in) :: lscale(*),rscale(*) real(dp), intent(inout) :: v(ldv,*) end subroutine dggbak #else module procedure stdlib${ii}$_dggbak #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sggbak( job, side, n, ilo, ihi, lscale, rscale, m, v,ldv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: job,side integer(${ik}$), intent(in) :: ihi,ilo,ldv,m,n integer(${ik}$), intent(out) :: info real(sp), intent(in) :: lscale(*),rscale(*) real(sp), intent(inout) :: v(ldv,*) end subroutine sggbak #else module procedure stdlib${ii}$_sggbak #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zggbak( job, side, n, ilo, ihi, lscale, rscale, m, v,ldv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: job,side integer(${ik}$), intent(in) :: ihi,ilo,ldv,m,n integer(${ik}$), intent(out) :: info real(dp), intent(in) :: lscale(*),rscale(*) complex(dp), intent(inout) :: v(ldv,*) end subroutine zggbak #else module procedure stdlib${ii}$_zggbak #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggbak #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggbak #:endif #:endfor #:endfor end interface ggbak interface ggbal !! GGBAL balances a pair of general complex matrices (A,B). This !! involves, first, permuting A and B by similarity transformations to !! isolate eigenvalues in the first 1 to ILO$-$1 and last IHI+1 to N !! elements on the diagonal; and second, applying a diagonal similarity !! transformation to rows and columns ILO to IHI to make the rows !! and columns as close in norm as possible. Both steps are optional. !! Balancing may reduce the 1-norm of the matrices, and improve the !! accuracy of the computed eigenvalues and/or eigenvectors in the !! generalized eigenvalue problem A*x = lambda*B*x. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cggbal( job, n, a, lda, b, ldb, ilo, ihi, lscale,rscale, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: job integer(${ik}$), intent(out) :: ihi,ilo,info integer(${ik}$), intent(in) :: lda,ldb,n real(sp), intent(out) :: lscale(*),rscale(*),work(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine cggbal #else module procedure stdlib${ii}$_cggbal #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dggbal( job, n, a, lda, b, ldb, ilo, ihi, lscale,rscale, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: job integer(${ik}$), intent(out) :: ihi,ilo,info integer(${ik}$), intent(in) :: lda,ldb,n real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: lscale(*),rscale(*),work(*) end subroutine dggbal #else module procedure stdlib${ii}$_dggbal #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sggbal( job, n, a, lda, b, ldb, ilo, ihi, lscale,rscale, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: job integer(${ik}$), intent(out) :: ihi,ilo,info integer(${ik}$), intent(in) :: lda,ldb,n real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: lscale(*),rscale(*),work(*) end subroutine sggbal #else module procedure stdlib${ii}$_sggbal #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zggbal( job, n, a, lda, b, ldb, ilo, ihi, lscale,rscale, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: job integer(${ik}$), intent(out) :: ihi,ilo,info integer(${ik}$), intent(in) :: lda,ldb,n real(dp), intent(out) :: lscale(*),rscale(*),work(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine zggbal #else module procedure stdlib${ii}$_zggbal #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggbal #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggbal #:endif #:endfor #:endfor end interface ggbal interface gges !! GGES computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, the generalized complex Schur !! form (S, T), and optionally left and/or right Schur vectors (VSL !! and VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H ) !! where (VSR)**H is the conjugate-transpose of VSR. !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! triangular matrix S and the upper triangular matrix T. The leading !! columns of VSL and VSR then form an unitary basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! CGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0, and even for both being zero. !! A pair of matrices (S,T) is in generalized complex Schur form if S !! and T are upper triangular and, in addition, the diagonal elements !! of T are non-negative real numbers. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alpha, & beta, vsl, ldvsl, vsr, ldvsr, work,lwork, rwork, bwork, info ) import sp,dp,qp,${ik}$,lk,stdlib_selctg_c implicit none character, intent(in) :: jobvsl,jobvsr,sort integer(${ik}$), intent(out) :: info,sdim integer(${ik}$), intent(in) :: lda,ldb,ldvsl,ldvsr,lwork,n logical(lk), intent(out) :: bwork(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: alpha(*),beta(*),vsl(ldvsl,*),vsr(ldvsr,*),work(*) procedure(stdlib_selctg_c) :: selctg end subroutine cgges #else module procedure stdlib${ii}$_cgges #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alphar, & alphai, beta, vsl, ldvsl, vsr,ldvsr, work, lwork, bwork, info ) import sp,dp,qp,${ik}$,lk,stdlib_selctg_d implicit none character, intent(in) :: jobvsl,jobvsr,sort integer(${ik}$), intent(out) :: info,sdim integer(${ik}$), intent(in) :: lda,ldb,ldvsl,ldvsr,lwork,n logical(lk), intent(out) :: bwork(*) real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: alphai(*),alphar(*),beta(*),vsl(ldvsl,*),vsr(ldvsr,*)& ,work(*) procedure(stdlib_selctg_d) :: selctg end subroutine dgges #else module procedure stdlib${ii}$_dgges #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alphar, & alphai, beta, vsl, ldvsl, vsr,ldvsr, work, lwork, bwork, info ) import sp,dp,qp,${ik}$,lk,stdlib_selctg_s implicit none character, intent(in) :: jobvsl,jobvsr,sort integer(${ik}$), intent(out) :: info,sdim integer(${ik}$), intent(in) :: lda,ldb,ldvsl,ldvsr,lwork,n logical(lk), intent(out) :: bwork(*) real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: alphai(*),alphar(*),beta(*),vsl(ldvsl,*),vsr(ldvsr,*)& ,work(*) procedure(stdlib_selctg_s) :: selctg end subroutine sgges #else module procedure stdlib${ii}$_sgges #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alpha, & beta, vsl, ldvsl, vsr, ldvsr, work,lwork, rwork, bwork, info ) import sp,dp,qp,${ik}$,lk,stdlib_selctg_z implicit none character, intent(in) :: jobvsl,jobvsr,sort integer(${ik}$), intent(out) :: info,sdim integer(${ik}$), intent(in) :: lda,ldb,ldvsl,ldvsr,lwork,n logical(lk), intent(out) :: bwork(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: alpha(*),beta(*),vsl(ldvsl,*),vsr(ldvsr,*),work(*) procedure(stdlib_selctg_z) :: selctg end subroutine zgges #else module procedure stdlib${ii}$_zgges #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gges #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gges #:endif #:endfor #:endfor end interface gges interface ggev !! GGEV computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, and optionally, the left and/or !! right generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right generalized eigenvector v(j) corresponding to the !! generalized eigenvalue lambda(j) of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left generalized eigenvector u(j) corresponding to the !! generalized eigenvalues lambda(j) of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B !! where u(j)**H is the conjugate-transpose of u(j). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cggev( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, & work, lwork, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobvl,jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldvl,ldvr,lwork,n real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: alpha(*),beta(*),vl(ldvl,*),vr(ldvr,*),work(*) end subroutine cggev #else module procedure stdlib${ii}$_cggev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dggev( jobvl, jobvr, n, a, lda, b, ldb, alphar, alphai,beta, vl, ldvl, & vr, ldvr, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobvl,jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldvl,ldvr,lwork,n real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: alphai(*),alphar(*),beta(*),vl(ldvl,*),vr(ldvr,*),& work(*) end subroutine dggev #else module procedure stdlib${ii}$_dggev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sggev( jobvl, jobvr, n, a, lda, b, ldb, alphar, alphai,beta, vl, ldvl, & vr, ldvr, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobvl,jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldvl,ldvr,lwork,n real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: alphai(*),alphar(*),beta(*),vl(ldvl,*),vr(ldvr,*),& work(*) end subroutine sggev #else module procedure stdlib${ii}$_sggev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zggev( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, & work, lwork, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobvl,jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldvl,ldvr,lwork,n real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: alpha(*),beta(*),vl(ldvl,*),vr(ldvr,*),work(*) end subroutine zggev #else module procedure stdlib${ii}$_zggev #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggev #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggev #:endif #:endfor #:endfor end interface ggev interface ggglm !! GGGLM solves a general Gauss-Markov linear model (GLM) problem: !! minimize || y ||_2 subject to d = A*x + B*y !! x !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a !! given N-vector. It is assumed that M <= N <= M+P, and !! rank(A) = M and rank( A B ) = N. !! Under these assumptions, the constrained equation is always !! consistent, and there is a unique solution x and a minimal 2-norm !! solution y, which is obtained using a generalized QR factorization !! of the matrices (A, B) given by !! A = Q*(R), B = Q*T*Z. !! (0) !! In particular, if matrix B is square nonsingular, then the problem !! GLM is equivalent to the following weighted linear least squares !! problem !! minimize || inv(B)*(d-A*x) ||_2 !! x !! where inv(B) denotes the inverse of B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p complex(sp), intent(inout) :: a(lda,*),b(ldb,*),d(*) complex(sp), intent(out) :: work(*),x(*),y(*) end subroutine cggglm #else module procedure stdlib${ii}$_cggglm #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p real(dp), intent(inout) :: a(lda,*),b(ldb,*),d(*) real(dp), intent(out) :: work(*),x(*),y(*) end subroutine dggglm #else module procedure stdlib${ii}$_dggglm #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p real(sp), intent(inout) :: a(lda,*),b(ldb,*),d(*) real(sp), intent(out) :: work(*),x(*),y(*) end subroutine sggglm #else module procedure stdlib${ii}$_sggglm #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p complex(dp), intent(inout) :: a(lda,*),b(ldb,*),d(*) complex(dp), intent(out) :: work(*),x(*),y(*) end subroutine zggglm #else module procedure stdlib${ii}$_zggglm #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggglm #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggglm #:endif #:endfor #:endfor end interface ggglm interface gghrd !! GGHRD reduces a pair of complex matrices (A,B) to generalized upper !! Hessenberg form using unitary transformations, where A is a !! general matrix and B is upper triangular. The form of the generalized !! eigenvalue problem is !! A*x = lambda*B*x, !! and B is typically made upper triangular by computing its QR !! factorization and moving the unitary matrix Q to the left side !! of the equation. !! This subroutine simultaneously reduces A to a Hessenberg matrix H: !! Q**H*A*Z = H !! and transforms B to another upper triangular matrix T: !! Q**H*B*Z = T !! in order to reduce the problem to its standard form !! H*y = lambda*T*y !! where y = Z**H*x. !! The unitary matrices Q and Z are determined as products of Givens !! rotations. They may either be formed explicitly, or they may be !! postmultiplied into input matrices Q1 and Z1, so that !! Q1 * A * Z1**H = (Q1*Q) * H * (Z1*Z)**H !! Q1 * B * Z1**H = (Q1*Q) * T * (Z1*Z)**H !! If Q1 is the unitary matrix from the QR factorization of B in the !! original equation A*x = lambda*B*x, then GGHRD reduces the original !! problem to generalized Hessenberg form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgghrd( compq, compz, n, ilo, ihi, a, lda, b, ldb, q,ldq, z, ldz, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,compz integer(${ik}$), intent(in) :: ihi,ilo,lda,ldb,ldq,ldz,n integer(${ik}$), intent(out) :: info complex(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) end subroutine cgghrd #else module procedure stdlib${ii}$_cgghrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgghrd( compq, compz, n, ilo, ihi, a, lda, b, ldb, q,ldq, z, ldz, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,compz integer(${ik}$), intent(in) :: ihi,ilo,lda,ldb,ldq,ldz,n integer(${ik}$), intent(out) :: info real(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) end subroutine dgghrd #else module procedure stdlib${ii}$_dgghrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgghrd( compq, compz, n, ilo, ihi, a, lda, b, ldb, q,ldq, z, ldz, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,compz integer(${ik}$), intent(in) :: ihi,ilo,lda,ldb,ldq,ldz,n integer(${ik}$), intent(out) :: info real(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) end subroutine sgghrd #else module procedure stdlib${ii}$_sgghrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgghrd( compq, compz, n, ilo, ihi, a, lda, b, ldb, q,ldq, z, ldz, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,compz integer(${ik}$), intent(in) :: ihi,ilo,lda,ldb,ldq,ldz,n integer(${ik}$), intent(out) :: info complex(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) end subroutine zgghrd #else module procedure stdlib${ii}$_zgghrd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gghrd #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gghrd #:endif #:endfor #:endfor end interface gghrd interface gglse !! GGLSE solves the linear equality-constrained least squares (LSE) !! problem: !! minimize || c - A*x ||_2 subject to B*x = d !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given !! M-vector, and d is a given P-vector. It is assumed that !! P <= N <= M+P, and !! rank(B) = P and rank( (A) ) = N. !! ( (B) ) !! These conditions ensure that the LSE problem has a unique solution, !! which is obtained using a generalized RQ factorization of the !! matrices (B, A) given by !! B = (0 R)*Q, A = Z*T*Q. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p complex(sp), intent(inout) :: a(lda,*),b(ldb,*),c(*),d(*) complex(sp), intent(out) :: work(*),x(*) end subroutine cgglse #else module procedure stdlib${ii}$_cgglse #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p real(dp), intent(inout) :: a(lda,*),b(ldb,*),c(*),d(*) real(dp), intent(out) :: work(*),x(*) end subroutine dgglse #else module procedure stdlib${ii}$_dgglse #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p real(sp), intent(inout) :: a(lda,*),b(ldb,*),c(*),d(*) real(sp), intent(out) :: work(*),x(*) end subroutine sgglse #else module procedure stdlib${ii}$_sgglse #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p complex(dp), intent(inout) :: a(lda,*),b(ldb,*),c(*),d(*) complex(dp), intent(out) :: work(*),x(*) end subroutine zgglse #else module procedure stdlib${ii}$_zgglse #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gglse #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gglse #:endif #:endfor #:endfor end interface gglse interface ggqrf !! GGQRF computes a generalized QR factorization of an N-by-M matrix A !! and an N-by-P matrix B: !! A = Q*R, B = Q*T*Z, !! where Q is an N-by-N unitary matrix, Z is a P-by-P unitary matrix, !! and R and T assume one of the forms: !! if N >= M, R = ( R11 ) M , or if N < M, R = ( R11 R12 ) N, !! ( 0 ) N-M N M-N !! M !! where R11 is upper triangular, and !! if N <= P, T = ( 0 T12 ) N, or if N > P, T = ( T11 ) N-P, !! P-N N ( T21 ) P !! P !! where T12 or T21 is upper triangular. !! In particular, if B is square and nonsingular, the GQR factorization !! of A and B implicitly gives the QR factorization of inv(B)*A: !! inv(B)*A = Z**H * (inv(T)*R) !! where inv(B) denotes the inverse of the matrix B, and Z' denotes the !! conjugate transpose of matrix Z. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cggqrf( n, m, p, a, lda, taua, b, ldb, taub, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: taua(*),taub(*),work(*) end subroutine cggqrf #else module procedure stdlib${ii}$_cggqrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dggqrf( n, m, p, a, lda, taua, b, ldb, taub, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: taua(*),taub(*),work(*) end subroutine dggqrf #else module procedure stdlib${ii}$_dggqrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sggqrf( n, m, p, a, lda, taua, b, ldb, taub, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: taua(*),taub(*),work(*) end subroutine sggqrf #else module procedure stdlib${ii}$_sggqrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zggqrf( n, m, p, a, lda, taua, b, ldb, taub, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: taua(*),taub(*),work(*) end subroutine zggqrf #else module procedure stdlib${ii}$_zggqrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggqrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggqrf #:endif #:endfor #:endfor end interface ggqrf interface ggrqf !! GGRQF computes a generalized RQ factorization of an M-by-N matrix A !! and a P-by-N matrix B: !! A = R*Q, B = Z*T*Q, !! where Q is an N-by-N unitary matrix, Z is a P-by-P unitary !! matrix, and R and T assume one of the forms: !! if M <= N, R = ( 0 R12 ) M, or if M > N, R = ( R11 ) M-N, !! N-M M ( R21 ) N !! N !! where R12 or R21 is upper triangular, and !! if P >= N, T = ( T11 ) N , or if P < N, T = ( T11 T12 ) P, !! ( 0 ) P-N P N-P !! N !! where T11 is upper triangular. !! In particular, if B is square and nonsingular, the GRQ factorization !! of A and B implicitly gives the RQ factorization of A*inv(B): !! A*inv(B) = (R*inv(T))*Z**H !! where inv(B) denotes the inverse of the matrix B, and Z**H denotes the !! conjugate transpose of the matrix Z. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cggrqf( m, p, n, a, lda, taua, b, ldb, taub, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: taua(*),taub(*),work(*) end subroutine cggrqf #else module procedure stdlib${ii}$_cggrqf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dggrqf( m, p, n, a, lda, taua, b, ldb, taub, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: taua(*),taub(*),work(*) end subroutine dggrqf #else module procedure stdlib${ii}$_dggrqf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sggrqf( m, p, n, a, lda, taua, b, ldb, taub, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: taua(*),taub(*),work(*) end subroutine sggrqf #else module procedure stdlib${ii}$_sggrqf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zggrqf( m, p, n, a, lda, taua, b, ldb, taub, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,lwork,m,n,p complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: taua(*),taub(*),work(*) end subroutine zggrqf #else module procedure stdlib${ii}$_zggrqf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggrqf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ggrqf #:endif #:endfor #:endfor end interface ggrqf interface gsvj0 !! GSVJ0 is called from CGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as CGESVJ does, but !! it does not check convergence (stopping criterion). Few tuning !! parameters (marked by [TP]) are available for the implementer. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgsvj0( jobv, m, n, a, lda, d, sva, mv, v, ldv, eps,sfmin, tol, & nsweep, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,m,mv,n,nsweep real(sp), intent(in) :: eps,sfmin,tol character, intent(in) :: jobv complex(sp), intent(inout) :: a(lda,*),d(n),v(ldv,*) complex(sp), intent(out) :: work(lwork) real(sp), intent(inout) :: sva(n) end subroutine cgsvj0 #else module procedure stdlib${ii}$_cgsvj0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgsvj0( jobv, m, n, a, lda, d, sva, mv, v, ldv, eps,sfmin, tol, & nsweep, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,m,mv,n,nsweep real(dp), intent(in) :: eps,sfmin,tol character, intent(in) :: jobv real(dp), intent(inout) :: a(lda,*),sva(n),d(n),v(ldv,*) real(dp), intent(out) :: work(lwork) end subroutine dgsvj0 #else module procedure stdlib${ii}$_dgsvj0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgsvj0( jobv, m, n, a, lda, d, sva, mv, v, ldv, eps,sfmin, tol, & nsweep, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,m,mv,n,nsweep real(sp), intent(in) :: eps,sfmin,tol character, intent(in) :: jobv real(sp), intent(inout) :: a(lda,*),sva(n),d(n),v(ldv,*) real(sp), intent(out) :: work(lwork) end subroutine sgsvj0 #else module procedure stdlib${ii}$_sgsvj0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgsvj0( jobv, m, n, a, lda, d, sva, mv, v, ldv, eps,sfmin, tol, & nsweep, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,m,mv,n,nsweep real(dp), intent(in) :: eps,sfmin,tol character, intent(in) :: jobv complex(dp), intent(inout) :: a(lda,*),d(n),v(ldv,*) complex(dp), intent(out) :: work(lwork) real(dp), intent(inout) :: sva(n) end subroutine zgsvj0 #else module procedure stdlib${ii}$_zgsvj0 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gsvj0 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gsvj0 #:endif #:endfor #:endfor end interface gsvj0 interface gsvj1 !! GSVJ1 is called from CGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as CGESVJ does, but !! it targets only particular pivots and it does not check convergence !! (stopping criterion). Few tuning parameters (marked by [TP]) are !! available for the implementer. !! Further Details !! ~~~~~~~~~~~~~~~ !! GSVJ1 applies few sweeps of Jacobi rotations in the column space of !! the input M-by-N matrix A. The pivot pairs are taken from the (1,2) !! off-diagonal block in the corresponding N-by-N Gram matrix A^T * A. The !! block-entries (tiles) of the (1,2) off-diagonal block are marked by the !! [x]'s in the following scheme: !! | * * * [x] [x] [x]| !! | * * * [x] [x] [x]| Row-cycling in the nblr-by-nblc [x] blocks. !! | * * * [x] [x] [x]| Row-cyclic pivoting inside each [x] block. !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! In terms of the columns of A, the first N1 columns are rotated 'against' !! the remaining N-N1 columns, trying to increase the angle between the !! corresponding subspaces. The off-diagonal block is N1-by(N-N1) and it is !! tiled using quadratic tiles of side KBL. Here, KBL is a tuning parameter. !! The number of sweeps is given in NSWEEP and the orthogonality threshold !! is given in TOL. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgsvj1( jobv, m, n, n1, a, lda, d, sva, mv, v, ldv,eps, sfmin, tol,& nsweep, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: eps,sfmin,tol integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,m,mv,n,n1,nsweep character, intent(in) :: jobv complex(sp), intent(inout) :: a(lda,*),d(n),v(ldv,*) complex(sp), intent(out) :: work(lwork) real(sp), intent(inout) :: sva(n) end subroutine cgsvj1 #else module procedure stdlib${ii}$_cgsvj1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgsvj1( jobv, m, n, n1, a, lda, d, sva, mv, v, ldv,eps, sfmin, tol,& nsweep, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: eps,sfmin,tol integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,m,mv,n,n1,nsweep character, intent(in) :: jobv real(dp), intent(inout) :: a(lda,*),d(n),sva(n),v(ldv,*) real(dp), intent(out) :: work(lwork) end subroutine dgsvj1 #else module procedure stdlib${ii}$_dgsvj1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgsvj1( jobv, m, n, n1, a, lda, d, sva, mv, v, ldv,eps, sfmin, tol,& nsweep, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: eps,sfmin,tol integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,m,mv,n,n1,nsweep character, intent(in) :: jobv real(sp), intent(inout) :: a(lda,*),d(n),sva(n),v(ldv,*) real(sp), intent(out) :: work(lwork) end subroutine sgsvj1 #else module procedure stdlib${ii}$_sgsvj1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgsvj1( jobv, m, n, n1, a, lda, d, sva, mv, v, ldv,eps, sfmin, tol,& nsweep, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: eps,sfmin,tol integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldv,lwork,m,mv,n,n1,nsweep character, intent(in) :: jobv complex(dp), intent(inout) :: a(lda,*),d(n),v(ldv,*) complex(dp), intent(out) :: work(lwork) real(dp), intent(inout) :: sva(n) end subroutine zgsvj1 #else module procedure stdlib${ii}$_zgsvj1 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gsvj1 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gsvj1 #:endif #:endfor #:endfor end interface gsvj1 interface gtcon !! GTCON estimates the reciprocal of the condition number of a complex !! tridiagonal matrix A using the LU factorization as computed by !! CGTTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgtcon( norm, n, dl, d, du, du2, ipiv, anorm, rcond,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond complex(sp), intent(in) :: d(*),dl(*),du(*),du2(*) complex(sp), intent(out) :: work(*) end subroutine cgtcon #else module procedure stdlib${ii}$_cgtcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgtcon( norm, n, dl, d, du, du2, ipiv, anorm, rcond,work, iwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: n,ipiv(*) real(dp), intent(in) :: anorm,d(*),dl(*),du(*),du2(*) real(dp), intent(out) :: rcond,work(*) end subroutine dgtcon #else module procedure stdlib${ii}$_dgtcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgtcon( norm, n, dl, d, du, du2, ipiv, anorm, rcond,work, iwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: n,ipiv(*) real(sp), intent(in) :: anorm,d(*),dl(*),du(*),du2(*) real(sp), intent(out) :: rcond,work(*) end subroutine sgtcon #else module procedure stdlib${ii}$_sgtcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgtcon( norm, n, dl, d, du, du2, ipiv, anorm, rcond,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond complex(dp), intent(in) :: d(*),dl(*),du(*),du2(*) complex(dp), intent(out) :: work(*) end subroutine zgtcon #else module procedure stdlib${ii}$_zgtcon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gtcon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gtcon #:endif #:endfor #:endfor end interface gtcon interface gtrfs !! GTRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is tridiagonal, and provides !! error bounds and backward error estimates for the solution. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2,ipiv, b, ldb, & x, ldx, ferr, berr, work, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs,ipiv(*) real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: b(ldb,*),d(*),df(*),dl(*),dlf(*),du(*),du2(*),duf(& *) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine cgtrfs #else module procedure stdlib${ii}$_cgtrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2,ipiv, b, ldb, & x, ldx, ferr, berr, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs,ipiv(*) real(dp), intent(in) :: b(ldb,*),d(*),df(*),dl(*),dlf(*),du(*),du2(*),duf(*) real(dp), intent(out) :: berr(*),ferr(*),work(*) real(dp), intent(inout) :: x(ldx,*) end subroutine dgtrfs #else module procedure stdlib${ii}$_dgtrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2,ipiv, b, ldb, & x, ldx, ferr, berr, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs,ipiv(*) real(sp), intent(in) :: b(ldb,*),d(*),df(*),dl(*),dlf(*),du(*),du2(*),duf(*) real(sp), intent(out) :: berr(*),ferr(*),work(*) real(sp), intent(inout) :: x(ldx,*) end subroutine sgtrfs #else module procedure stdlib${ii}$_sgtrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2,ipiv, b, ldb, & x, ldx, ferr, berr, work, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs,ipiv(*) real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: b(ldb,*),d(*),df(*),dl(*),dlf(*),du(*),du2(*),duf(& *) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zgtrfs #else module procedure stdlib${ii}$_zgtrfs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gtrfs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gtrfs #:endif #:endfor #:endfor end interface gtrfs interface gtsv !! GTSV solves the equation !! A*X = B, !! where A is an N-by-N tridiagonal matrix, by Gaussian elimination with !! partial pivoting. !! Note that the equation A**T *X = B may be solved by interchanging the !! order of the arguments DU and DL. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgtsv( n, nrhs, dl, d, du, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs complex(sp), intent(inout) :: b(ldb,*),d(*),dl(*),du(*) end subroutine cgtsv #else module procedure stdlib${ii}$_cgtsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgtsv( n, nrhs, dl, d, du, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(dp), intent(inout) :: b(ldb,*),d(*),dl(*),du(*) end subroutine dgtsv #else module procedure stdlib${ii}$_dgtsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgtsv( n, nrhs, dl, d, du, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(sp), intent(inout) :: b(ldb,*),d(*),dl(*),du(*) end subroutine sgtsv #else module procedure stdlib${ii}$_sgtsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgtsv( n, nrhs, dl, d, du, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs complex(dp), intent(inout) :: b(ldb,*),d(*),dl(*),du(*) end subroutine zgtsv #else module procedure stdlib${ii}$_zgtsv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gtsv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gtsv #:endif #:endfor #:endfor end interface gtsv interface gttrf !! GTTRF computes an LU factorization of a complex tridiagonal matrix A !! using elimination with partial pivoting and row interchanges. !! The factorization has the form !! A = L * U !! where L is a product of permutation and unit lower bidiagonal !! matrices and U is upper triangular with nonzeros in only the main !! diagonal and first two superdiagonals. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgttrf( n, dl, d, du, du2, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: n complex(sp), intent(inout) :: d(*),dl(*),du(*) complex(sp), intent(out) :: du2(*) end subroutine cgttrf #else module procedure stdlib${ii}$_cgttrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgttrf( n, dl, d, du, du2, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: d(*),dl(*),du(*) real(dp), intent(out) :: du2(*) end subroutine dgttrf #else module procedure stdlib${ii}$_dgttrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgttrf( n, dl, d, du, du2, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: d(*),dl(*),du(*) real(sp), intent(out) :: du2(*) end subroutine sgttrf #else module procedure stdlib${ii}$_sgttrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgttrf( n, dl, d, du, du2, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: n complex(dp), intent(inout) :: d(*),dl(*),du(*) complex(dp), intent(out) :: du2(*) end subroutine zgttrf #else module procedure stdlib${ii}$_zgttrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gttrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gttrf #:endif #:endfor #:endfor end interface gttrf interface gttrs !! GTTRS solves one of the systems of equations !! A * X = B, A**T * X = B, or A**H * X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by CGTTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cgttrs( trans, n, nrhs, dl, d, du, du2, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs,ipiv(*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(in) :: d(*),dl(*),du(*),du2(*) end subroutine cgttrs #else module procedure stdlib${ii}$_cgttrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dgttrs( trans, n, nrhs, dl, d, du, du2, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs,ipiv(*) real(dp), intent(inout) :: b(ldb,*) real(dp), intent(in) :: d(*),dl(*),du(*),du2(*) end subroutine dgttrs #else module procedure stdlib${ii}$_dgttrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sgttrs( trans, n, nrhs, dl, d, du, du2, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs,ipiv(*) real(sp), intent(inout) :: b(ldb,*) real(sp), intent(in) :: d(*),dl(*),du(*),du2(*) end subroutine sgttrs #else module procedure stdlib${ii}$_sgttrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zgttrs( trans, n, nrhs, dl, d, du, du2, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs,ipiv(*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(in) :: d(*),dl(*),du(*),du2(*) end subroutine zgttrs #else module procedure stdlib${ii}$_zgttrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gttrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$gttrs #:endif #:endfor #:endfor end interface gttrs interface hb2st_kernels !! HB2ST_KERNELS is an internal routine used by the CHETRD_HB2ST !! subroutine. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chb2st_kernels( uplo, wantz, ttype,st, ed, sweep, n, nb, ib,a, & lda, v, tau, ldvt, work) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo logical(lk), intent(in) :: wantz integer(${ik}$), intent(in) :: ttype,st,ed,sweep,n,nb,ib,lda,ldvt complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: v(*),tau(*),work(*) end subroutine chb2st_kernels #else module procedure stdlib${ii}$_chb2st_kernels #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhb2st_kernels( uplo, wantz, ttype,st, ed, sweep, n, nb, ib,a, & lda, v, tau, ldvt, work) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo logical(lk), intent(in) :: wantz integer(${ik}$), intent(in) :: ttype,st,ed,sweep,n,nb,ib,lda,ldvt complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: v(*),tau(*),work(*) end subroutine zhb2st_kernels #else module procedure stdlib${ii}$_zhb2st_kernels #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hb2st_kernels #:endif #:endfor #:endfor end interface hb2st_kernels interface hbev !! HBEV computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldz,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: ab(ldab,*) complex(sp), intent(out) :: work(*),z(ldz,*) end subroutine chbev #else module procedure stdlib${ii}$_chbev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldz,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: ab(ldab,*) complex(dp), intent(out) :: work(*),z(ldz,*) end subroutine zhbev #else module procedure stdlib${ii}$_zhbev #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hbev #:endif #:endfor #:endfor end interface hbev interface hbevd !! HBEVD computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. If eigenvectors are desired, it !! uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, rwork, & lrwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,ldz,liwork,lrwork,lwork,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: ab(ldab,*) complex(sp), intent(out) :: work(*),z(ldz,*) end subroutine chbevd #else module procedure stdlib${ii}$_chbevd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, rwork, & lrwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,ldz,liwork,lrwork,lwork,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: ab(ldab,*) complex(dp), intent(out) :: work(*),z(ldz,*) end subroutine zhbevd #else module procedure stdlib${ii}$_zhbevd #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hbevd #:endif #:endfor #:endfor end interface hbevd interface hbgst !! HBGST reduces a complex Hermitian-definite banded generalized !! eigenproblem A*x = lambda*B*x to standard form C*y = lambda*y, !! such that C has the same bandwidth as A. !! B must have been previously factorized as S**H*S by CPBSTF, using a !! split Cholesky factorization. A is overwritten by C = X**H*A*X, where !! X = S**(-1)*Q and Q is a unitary matrix chosen to preserve the !! bandwidth of A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chbgst( vect, uplo, n, ka, kb, ab, ldab, bb, ldbb, x,ldx, work, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldx,n real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: ab(ldab,*) complex(sp), intent(in) :: bb(ldbb,*) complex(sp), intent(out) :: work(*),x(ldx,*) end subroutine chbgst #else module procedure stdlib${ii}$_chbgst #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhbgst( vect, uplo, n, ka, kb, ab, ldab, bb, ldbb, x,ldx, work, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldx,n real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: ab(ldab,*) complex(dp), intent(in) :: bb(ldbb,*) complex(dp), intent(out) :: work(*),x(ldx,*) end subroutine zhbgst #else module procedure stdlib${ii}$_zhbgst #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hbgst #:endif #:endfor #:endfor end interface hbgst interface hbgv !! HBGV computes all the eigenvalues, and optionally, the eigenvectors !! of a complex generalized Hermitian-definite banded eigenproblem, of !! the form A*x=(lambda)*B*x. Here A and B are assumed to be Hermitian !! and banded, and B is also positive definite. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chbgv( jobz, uplo, n, ka, kb, ab, ldab, bb, ldbb, w, z,ldz, work, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldz,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: ab(ldab,*),bb(ldbb,*) complex(sp), intent(out) :: work(*),z(ldz,*) end subroutine chbgv #else module procedure stdlib${ii}$_chbgv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhbgv( jobz, uplo, n, ka, kb, ab, ldab, bb, ldbb, w, z,ldz, work, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldz,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: ab(ldab,*),bb(ldbb,*) complex(dp), intent(out) :: work(*),z(ldz,*) end subroutine zhbgv #else module procedure stdlib${ii}$_zhbgv #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hbgv #:endif #:endfor #:endfor end interface hbgv interface hbgvd !! HBGVD computes all the eigenvalues, and optionally, the eigenvectors !! of a complex generalized Hermitian-definite banded eigenproblem, of !! the form A*x=(lambda)*B*x. Here A and B are assumed to be Hermitian !! and banded, and B is also positive definite. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chbgvd( jobz, uplo, n, ka, kb, ab, ldab, bb, ldbb, w,z, ldz, work, & lwork, rwork, lrwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldz,liwork,lrwork,lwork,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: ab(ldab,*),bb(ldbb,*) complex(sp), intent(out) :: work(*),z(ldz,*) end subroutine chbgvd #else module procedure stdlib${ii}$_chbgvd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhbgvd( jobz, uplo, n, ka, kb, ab, ldab, bb, ldbb, w,z, ldz, work, & lwork, rwork, lrwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldz,liwork,lrwork,lwork,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: ab(ldab,*),bb(ldbb,*) complex(dp), intent(out) :: work(*),z(ldz,*) end subroutine zhbgvd #else module procedure stdlib${ii}$_zhbgvd #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hbgvd #:endif #:endfor #:endfor end interface hbgvd interface hbtrd !! HBTRD reduces a complex Hermitian band matrix A to real symmetric !! tridiagonal form T by a unitary similarity transformation: !! Q**H * A * Q = T. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chbtrd( vect, uplo, n, kd, ab, ldab, d, e, q, ldq,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldq,n real(sp), intent(out) :: d(*),e(*) complex(sp), intent(inout) :: ab(ldab,*),q(ldq,*) complex(sp), intent(out) :: work(*) end subroutine chbtrd #else module procedure stdlib${ii}$_chbtrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhbtrd( vect, uplo, n, kd, ab, ldab, d, e, q, ldq,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldq,n real(dp), intent(out) :: d(*),e(*) complex(dp), intent(inout) :: ab(ldab,*),q(ldq,*) complex(dp), intent(out) :: work(*) end subroutine zhbtrd #else module procedure stdlib${ii}$_zhbtrd #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hbtrd #:endif #:endfor #:endfor end interface hbtrd interface hecon !! HECON estimates the reciprocal of the condition number of a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHETRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine checon( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine checon #else module procedure stdlib${ii}$_checon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhecon( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zhecon #else module procedure stdlib${ii}$_zhecon #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hecon #:endif #:endfor #:endfor end interface hecon interface hecon_rook !! HECON_ROOK estimates the reciprocal of the condition number of a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHETRF_ROOK. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine checon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine checon_rook #else module procedure stdlib${ii}$_checon_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhecon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zhecon_rook #else module procedure stdlib${ii}$_zhecon_rook #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hecon_rook #:endif #:endfor #:endfor end interface hecon_rook interface heequb !! HEEQUB computes row and column scalings intended to equilibrate a !! Hermitian matrix A (with respect to the Euclidean norm) and reduce !! its condition number. The scale factors S are computed by the BIN !! algorithm (see references) so that the scaled matrix B with elements !! B(i,j) = S(i)*A(i,j)*S(j) has a condition number within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cheequb( uplo, n, a, lda, s, scond, amax, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: amax,scond,s(*) character, intent(in) :: uplo complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine cheequb #else module procedure stdlib${ii}$_cheequb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zheequb( uplo, n, a, lda, s, scond, amax, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: amax,scond,s(*) character, intent(in) :: uplo complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zheequb #else module procedure stdlib${ii}$_zheequb #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$heequb #:endif #:endfor #:endfor end interface heequb interface heev !! HEEV computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cheev( jobz, uplo, n, a, lda, w, work, lwork, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine cheev #else module procedure stdlib${ii}$_cheev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zheev( jobz, uplo, n, a, lda, w, work, lwork, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zheev #else module procedure stdlib${ii}$_zheev #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$heev #:endif #:endfor #:endfor end interface heev interface heevd !! HEEVD computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cheevd( jobz, uplo, n, a, lda, w, work, lwork, rwork,lrwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,liwork,lrwork,lwork,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine cheevd #else module procedure stdlib${ii}$_cheevd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zheevd( jobz, uplo, n, a, lda, w, work, lwork, rwork,lrwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,liwork,lrwork,lwork,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zheevd #else module procedure stdlib${ii}$_zheevd #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$heevd #:endif #:endfor #:endfor end interface heevd interface heevr !! HEEVR computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. !! HEEVR first reduces the matrix A to tridiagonal form T with a call !! to CHETRD. Then, whenever possible, HEEVR calls CSTEMR to compute !! the eigenspectrum using Relatively Robust Representations. CSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. !! For each unreduced block (submatrix) of T, !! (a) Compute T - sigma I = L D L^T, so that L and D !! define all the wanted eigenvalues to high relative accuracy. !! This means that small relative changes in the entries of D and L !! cause only small relative changes in the eigenvalues and !! eigenvectors. The standard (unfactored) representation of the !! tridiagonal matrix T does not have this property in general. !! (b) Compute the eigenvalues to suitable accuracy. !! If the eigenvectors are desired, the algorithm attains full !! accuracy of the computed eigenvalues only right before !! the corresponding vectors have to be computed, see steps c) and d). !! (c) For each cluster of close eigenvalues, select a new !! shift close to the cluster, find a new factorization, and refine !! the shifted eigenvalues to suitable accuracy. !! (d) For each eigenvalue with a large enough relative separation compute !! the corresponding eigenvector by forming a rank revealing twisted !! factorization. Go back to (c) for any clusters that remain. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see CSTEMR's documentation and: !! - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations !! to compute orthogonal eigenvectors of symmetric tridiagonal matrices," !! Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. !! - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and !! Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, !! 2004. Also LAPACK Working Note 154. !! - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", !! Computer Science Division Technical Report No. UCB/CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : HEEVR calls CSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! HEEVR calls SSTEBZ and CSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of CSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cheevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, & ldz, isuppz, work, lwork,rwork, lrwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range,uplo integer(${ik}$), intent(in) :: il,iu,lda,ldz,liwork,lrwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(sp), intent(in) :: abstol,vl,vu real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*),z(ldz,*) end subroutine cheevr #else module procedure stdlib${ii}$_cheevr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zheevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, & ldz, isuppz, work, lwork,rwork, lrwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range,uplo integer(${ik}$), intent(in) :: il,iu,lda,ldz,liwork,lrwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(dp), intent(in) :: abstol,vl,vu real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*),z(ldz,*) end subroutine zheevr #else module procedure stdlib${ii}$_zheevr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$heevr #:endif #:endfor #:endfor end interface heevr interface hegst !! HEGST reduces a complex Hermitian-definite generalized !! eigenproblem to standard form. !! If ITYPE = 1, the problem is A*x = lambda*B*x, !! and A is overwritten by inv(U**H)*A*inv(U) or inv(L)*A*inv(L**H) !! If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or !! B*A*x = lambda*x, and A is overwritten by U*A*U**H or L**H*A*L. !! B must have been previously factorized as U**H*U or L*L**H by CPOTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chegst( itype, uplo, n, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,lda,ldb,n complex(sp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine chegst #else module procedure stdlib${ii}$_chegst #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhegst( itype, uplo, n, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,lda,ldb,n complex(dp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine zhegst #else module procedure stdlib${ii}$_zhegst #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hegst #:endif #:endfor #:endfor end interface hegst interface hegv !! HEGV computes all the eigenvalues, and optionally, the eigenvectors !! of a complex generalized Hermitian-definite eigenproblem, of the form !! A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. !! Here A and B are assumed to be Hermitian and B is also !! positive definite. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chegv( itype, jobz, uplo, n, a, lda, b, ldb, w, work,lwork, rwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,lda,ldb,lwork,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine chegv #else module procedure stdlib${ii}$_chegv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhegv( itype, jobz, uplo, n, a, lda, b, ldb, w, work,lwork, rwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,lda,ldb,lwork,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zhegv #else module procedure stdlib${ii}$_zhegv #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hegv #:endif #:endfor #:endfor end interface hegv interface hegvd !! HEGVD computes all the eigenvalues, and optionally, the eigenvectors !! of a complex generalized Hermitian-definite eigenproblem, of the form !! A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. Here A and !! B are assumed to be Hermitian and B is also positive definite. !! If eigenvectors are desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chegvd( itype, jobz, uplo, n, a, lda, b, ldb, w, work,lwork, rwork, & lrwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: itype,lda,ldb,liwork,lrwork,lwork,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine chegvd #else module procedure stdlib${ii}$_chegvd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhegvd( itype, jobz, uplo, n, a, lda, b, ldb, w, work,lwork, rwork, & lrwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: itype,lda,ldb,liwork,lrwork,lwork,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zhegvd #else module procedure stdlib${ii}$_zhegvd #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hegvd #:endif #:endfor #:endfor end interface hegvd interface herfs !! HERFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian indefinite, and !! provides error bounds and backward error estimates for the solution. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cherfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr,& berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs,ipiv(*) real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine cherfs #else module procedure stdlib${ii}$_cherfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zherfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr,& berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs,ipiv(*) real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zherfs #else module procedure stdlib${ii}$_zherfs #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$herfs #:endif #:endfor #:endfor end interface herfs interface hesv !! HESV computes the solution to a complex system of linear equations !! A * X = B, !! where A is an N-by-N Hermitian matrix and X and B are N-by-NRHS !! matrices. !! The diagonal pivoting method is used to factor A as !! A = U * D * U**H, if UPLO = 'U', or !! A = L * D * L**H, if UPLO = 'L', !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. The factored form of A is then !! used to solve the system of equations A * X = B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chesv( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine chesv #else module procedure stdlib${ii}$_chesv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhesv( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zhesv #else module procedure stdlib${ii}$_zhesv #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hesv #:endif #:endfor #:endfor end interface hesv interface hesv_aa !! HESV_AA computes the solution to a complex system of linear equations !! A * X = B, !! where A is an N-by-N Hermitian matrix and X and B are N-by-NRHS !! matrices. !! Aasen's algorithm is used to factor A as !! A = U**H * T * U, if UPLO = 'U', or !! A = L * T * L**H, if UPLO = 'L', !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is Hermitian and tridiagonal. The factored form !! of A is then used to solve the system of equations A * X = B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chesv_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine chesv_aa #else module procedure stdlib${ii}$_chesv_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhesv_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zhesv_aa #else module procedure stdlib${ii}$_zhesv_aa #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hesv_aa #:endif #:endfor #:endfor end interface hesv_aa interface hesv_rk !! HESV_RK computes the solution to a complex system of linear !! equations A * X = B, where A is an N-by-N Hermitian matrix !! and X and B are N-by-NRHS matrices. !! The bounded Bunch-Kaufman (rook) diagonal pivoting method is used !! to factor A as !! A = P*U*D*(U**H)*(P**T), if UPLO = 'U', or !! A = P*L*D*(L**H)*(P**T), if UPLO = 'L', !! where U (or L) is unit upper (or lower) triangular matrix, !! U**H (or L**H) is the conjugate of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is Hermitian and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! CHETRF_RK is called to compute the factorization of a complex !! Hermitian matrix. The factored form of A is then used to solve !! the system of equations A * X = B by calling BLAS3 routine CHETRS_3. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chesv_rk( uplo, n, nrhs, a, lda, e, ipiv, b, ldb, work,lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: e(*),work(*) end subroutine chesv_rk #else module procedure stdlib${ii}$_chesv_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhesv_rk( uplo, n, nrhs, a, lda, e, ipiv, b, ldb, work,lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: e(*),work(*) end subroutine zhesv_rk #else module procedure stdlib${ii}$_zhesv_rk #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hesv_rk #:endif #:endfor #:endfor end interface hesv_rk interface hesv_rook !! HESV_ROOK computes the solution to a complex system of linear equations !! A * X = B, !! where A is an N-by-N Hermitian matrix and X and B are N-by-NRHS !! matrices. !! The bounded Bunch-Kaufman ("rook") diagonal pivoting method is used !! to factor A as !! A = U * D * U**T, if UPLO = 'U', or !! A = L * D * L**T, if UPLO = 'L', !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! CHETRF_ROOK is called to compute the factorization of a complex !! Hermition matrix A using the bounded Bunch-Kaufman ("rook") diagonal !! pivoting method. !! The factored form of A is then used to solve the system !! of equations A * X = B by calling CHETRS_ROOK (uses BLAS 2). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chesv_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine chesv_rook #else module procedure stdlib${ii}$_chesv_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhesv_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zhesv_rook #else module procedure stdlib${ii}$_zhesv_rook #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hesv_rook #:endif #:endfor #:endfor end interface hesv_rook interface heswapr !! HESWAPR applies an elementary permutation on the rows and the columns of !! a hermitian matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cheswapr( uplo, n, a, lda, i1, i2) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1,i2,lda,n complex(sp), intent(inout) :: a(lda,n) end subroutine cheswapr #else module procedure stdlib${ii}$_cheswapr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zheswapr( uplo, n, a, lda, i1, i2) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1,i2,lda,n complex(dp), intent(inout) :: a(lda,n) end subroutine zheswapr #else module procedure stdlib${ii}$_zheswapr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$heswapr #:endif #:endfor #:endfor end interface heswapr interface hetf2_rk !! HETF2_RK computes the factorization of a complex Hermitian matrix A !! using the bounded Bunch-Kaufman (rook) diagonal pivoting method: !! A = P*U*D*(U**H)*(P**T) or A = P*L*D*(L**H)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**H (or L**H) is the conjugate of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is Hermitian and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. !! For more information see Further Details section. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetf2_rk( uplo, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: e(*) end subroutine chetf2_rk #else module procedure stdlib${ii}$_chetf2_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetf2_rk( uplo, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: e(*) end subroutine zhetf2_rk #else module procedure stdlib${ii}$_zhetf2_rk #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetf2_rk #:endif #:endfor #:endfor end interface hetf2_rk interface hetf2_rook !! HETF2_ROOK computes the factorization of a complex Hermitian matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method: !! A = U*D*U**H or A = L*D*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, U**H is the conjugate transpose of U, and D is !! Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetf2_rook( uplo, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n complex(sp), intent(inout) :: a(lda,*) end subroutine chetf2_rook #else module procedure stdlib${ii}$_chetf2_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetf2_rook( uplo, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n complex(dp), intent(inout) :: a(lda,*) end subroutine zhetf2_rook #else module procedure stdlib${ii}$_zhetf2_rook #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetf2_rook #:endif #:endfor #:endfor end interface hetf2_rook interface hetrd !! HETRD reduces a complex Hermitian matrix A to real symmetric !! tridiagonal form T by a unitary similarity transformation: !! Q**H * A * Q = T. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetrd( uplo, n, a, lda, d, e, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n real(sp), intent(out) :: d(*),e(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*),work(*) end subroutine chetrd #else module procedure stdlib${ii}$_chetrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetrd( uplo, n, a, lda, d, e, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n real(dp), intent(out) :: d(*),e(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*),work(*) end subroutine zhetrd #else module procedure stdlib${ii}$_zhetrd #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrd #:endif #:endfor #:endfor end interface hetrd interface hetrd_hb2st !! HETRD_HB2ST reduces a complex Hermitian band matrix A to real symmetric !! tridiagonal form T by a unitary similarity transformation: !! Q**H * A * Q = T. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chetrd_hb2st( stage1, vect, uplo, n, kd, ab, ldab,d, e, hous, & lhous, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: stage1,uplo,vect integer(${ik}$), intent(in) :: n,kd,ldab,lhous,lwork integer(${ik}$), intent(out) :: info real(sp), intent(out) :: d(*),e(*) complex(sp), intent(inout) :: ab(ldab,*) complex(sp), intent(out) :: hous(*),work(*) end subroutine chetrd_hb2st #else module procedure stdlib${ii}$_chetrd_hb2st #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhetrd_hb2st( stage1, vect, uplo, n, kd, ab, ldab,d, e, hous, & lhous, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: stage1,uplo,vect integer(${ik}$), intent(in) :: n,kd,ldab,lhous,lwork integer(${ik}$), intent(out) :: info real(dp), intent(out) :: d(*),e(*) complex(dp), intent(inout) :: ab(ldab,*) complex(dp), intent(out) :: hous(*),work(*) end subroutine zhetrd_hb2st #else module procedure stdlib${ii}$_zhetrd_hb2st #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrd_hb2st #:endif #:endfor #:endfor end interface hetrd_hb2st interface hetrd_he2hb !! HETRD_HE2HB reduces a complex Hermitian matrix A to complex Hermitian !! band-diagonal form AB by a unitary similarity transformation: !! Q**H * A * Q = AB. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chetrd_he2hb( uplo, n, kd, a, lda, ab, ldab, tau,work, lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldab,lwork,n,kd complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: ab(ldab,*),tau(*),work(*) end subroutine chetrd_he2hb #else module procedure stdlib${ii}$_chetrd_he2hb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhetrd_he2hb( uplo, n, kd, a, lda, ab, ldab, tau,work, lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldab,lwork,n,kd complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: ab(ldab,*),tau(*),work(*) end subroutine zhetrd_he2hb #else module procedure stdlib${ii}$_zhetrd_he2hb #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrd_he2hb #:endif #:endfor #:endfor end interface hetrd_he2hb interface hetrf !! HETRF computes the factorization of a complex Hermitian matrix A !! using the Bunch-Kaufman diagonal pivoting method. The form of the !! factorization is !! A = U*D*U**H or A = L*D*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetrf( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine chetrf #else module procedure stdlib${ii}$_chetrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetrf( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zhetrf #else module procedure stdlib${ii}$_zhetrf #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrf #:endif #:endfor #:endfor end interface hetrf interface hetrf_aa !! HETRF_AA computes the factorization of a complex hermitian matrix A !! using the Aasen's algorithm. The form of the factorization is !! A = U**H*T*U or A = L*T*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is a hermitian tridiagonal matrix. !! This is the blocked version of the algorithm, calling Level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,lda,lwork integer(${ik}$), intent(out) :: info,ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine chetrf_aa #else module procedure stdlib${ii}$_chetrf_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,lda,lwork integer(${ik}$), intent(out) :: info,ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zhetrf_aa #else module procedure stdlib${ii}$_zhetrf_aa #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrf_aa #:endif #:endfor #:endfor end interface hetrf_aa interface hetrf_rk !! HETRF_RK computes the factorization of a complex Hermitian matrix A !! using the bounded Bunch-Kaufman (rook) diagonal pivoting method: !! A = P*U*D*(U**H)*(P**T) or A = P*L*D*(L**H)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**H (or L**H) is the conjugate of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is Hermitian and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. !! For more information see Further Details section. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: e(*),work(*) end subroutine chetrf_rk #else module procedure stdlib${ii}$_chetrf_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: e(*),work(*) end subroutine zhetrf_rk #else module procedure stdlib${ii}$_zhetrf_rk #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrf_rk #:endif #:endfor #:endfor end interface hetrf_rk interface hetrf_rook !! HETRF_ROOK computes the factorization of a complex Hermitian matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method. !! The form of the factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine chetrf_rook #else module procedure stdlib${ii}$_chetrf_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zhetrf_rook #else module procedure stdlib${ii}$_zhetrf_rook #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrf_rook #:endif #:endfor #:endfor end interface hetrf_rook interface hetri !! HETRI computes the inverse of a complex Hermitian indefinite matrix !! A using the factorization A = U*D*U**H or A = L*D*L**H computed by !! CHETRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetri( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine chetri #else module procedure stdlib${ii}$_chetri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetri( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zhetri #else module procedure stdlib${ii}$_zhetri #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetri #:endif #:endfor #:endfor end interface hetri interface hetri_rook !! HETRI_ROOK computes the inverse of a complex Hermitian indefinite matrix !! A using the factorization A = U*D*U**H or A = L*D*L**H computed by !! CHETRF_ROOK. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetri_rook( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine chetri_rook #else module procedure stdlib${ii}$_chetri_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetri_rook( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zhetri_rook #else module procedure stdlib${ii}$_zhetri_rook #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetri_rook #:endif #:endfor #:endfor end interface hetri_rook interface hetrs !! HETRS solves a system of linear equations A*X = B with a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHETRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetrs( uplo, n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: b(ldb,*) end subroutine chetrs #else module procedure stdlib${ii}$_chetrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetrs( uplo, n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zhetrs #else module procedure stdlib${ii}$_zhetrs #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrs #:endif #:endfor #:endfor end interface hetrs interface hetrs2 !! HETRS2 solves a system of linear equations A*X = B with a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHETRF and converted by CSYCONV. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine chetrs2 #else module procedure stdlib${ii}$_chetrs2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zhetrs2 #else module procedure stdlib${ii}$_zhetrs2 #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrs2 #:endif #:endfor #:endfor end interface hetrs2 interface hetrs_3 !! HETRS_3 solves a system of linear equations A * X = B with a complex !! Hermitian matrix A using the factorization computed !! by CHETRF_RK or CHETRF_BK: !! A = P*U*D*(U**H)*(P**T) or A = P*L*D*(L**H)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**H (or L**H) is the conjugate of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is Hermitian and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This algorithm is using Level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(sp), intent(in) :: a(lda,*),e(*) complex(sp), intent(inout) :: b(ldb,*) end subroutine chetrs_3 #else module procedure stdlib${ii}$_chetrs_3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(dp), intent(in) :: a(lda,*),e(*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zhetrs_3 #else module procedure stdlib${ii}$_zhetrs_3 #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrs_3 #:endif #:endfor #:endfor end interface hetrs_3 interface hetrs_aa !! HETRS_AA solves a system of linear equations A*X = B with a complex !! hermitian matrix A using the factorization A = U**H*T*U or !! A = L*T*L**H computed by CHETRF_AA. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,nrhs,lda,ldb,lwork,ipiv(*) integer(${ik}$), intent(out) :: info complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine chetrs_aa #else module procedure stdlib${ii}$_chetrs_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,nrhs,lda,ldb,lwork,ipiv(*) integer(${ik}$), intent(out) :: info complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zhetrs_aa #else module procedure stdlib${ii}$_zhetrs_aa #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrs_aa #:endif #:endfor #:endfor end interface hetrs_aa interface hetrs_rook !! HETRS_ROOK solves a system of linear equations A*X = B with a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHETRF_ROOK. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chetrs_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: b(ldb,*) end subroutine chetrs_rook #else module procedure stdlib${ii}$_chetrs_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhetrs_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zhetrs_rook #else module procedure stdlib${ii}$_zhetrs_rook #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hetrs_rook #:endif #:endfor #:endfor end interface hetrs_rook interface hfrk !! Level 3 BLAS like routine for C in RFP Format. !! HFRK performs one of the Hermitian rank--k operations !! C := alpha*A*A**H + beta*C, !! or !! C := alpha*A**H*A + beta*C, !! where alpha and beta are real scalars, C is an n--by--n Hermitian !! matrix and A is an n--by--k matrix in the first case and a k--by--n !! matrix in the second case. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chfrk( transr, uplo, trans, n, k, alpha, a, lda, beta,c ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta integer(${ik}$), intent(in) :: k,lda,n character, intent(in) :: trans,transr,uplo complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: c(*) end subroutine chfrk #else module procedure stdlib${ii}$_chfrk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhfrk( transr, uplo, trans, n, k, alpha, a, lda, beta,c ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta integer(${ik}$), intent(in) :: k,lda,n character, intent(in) :: trans,transr,uplo complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: c(*) end subroutine zhfrk #else module procedure stdlib${ii}$_zhfrk #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hfrk #:endif #:endfor #:endfor end interface hfrk interface hgeqz !! HGEQZ computes the eigenvalues of a complex matrix pair (H,T), !! where H is an upper Hessenberg matrix and T is upper triangular, !! using the single-shift QZ method. !! Matrix pairs of this type are produced by the reduction to !! generalized upper Hessenberg form of a complex matrix pair (A,B): !! A = Q1*H*Z1**H, B = Q1*T*Z1**H, !! as computed by CGGHRD. !! If JOB='S', then the Hessenberg-triangular pair (H,T) is !! also reduced to generalized Schur form, !! H = Q*S*Z**H, T = Q*P*Z**H, !! where Q and Z are unitary matrices and S and P are upper triangular. !! Optionally, the unitary matrix Q from the generalized Schur !! factorization may be postmultiplied into an input matrix Q1, and the !! unitary matrix Z may be postmultiplied into an input matrix Z1. !! If Q1 and Z1 are the unitary matrices from CGGHRD that reduced !! the matrix pair (A,B) to generalized Hessenberg form, then the output !! matrices Q1*Q and Z1*Z are the unitary factors from the generalized !! Schur factorization of (A,B): !! A = (Q1*Q)*S*(Z1*Z)**H, B = (Q1*Q)*P*(Z1*Z)**H. !! To avoid overflow, eigenvalues of the matrix pair (H,T) !! (equivalently, of (A,B)) are computed as a pair of complex values !! (alpha,beta). If beta is nonzero, lambda = alpha / beta is an !! eigenvalue of the generalized nonsymmetric eigenvalue problem (GNEP) !! A*x = lambda*B*x !! and if alpha is nonzero, mu = beta / alpha is an eigenvalue of the !! alternate form of the GNEP !! mu*A*y = B*y. !! The values of alpha and beta for the i-th eigenvalue can be read !! directly from the generalized Schur form: alpha = S(i,i), !! beta = P(i,i). !! Ref: C.B. Moler !! Eigenvalue Problems", SIAM J. Numer. Anal., 10(1973), !! pp. 241--256. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chgeqz( job, compq, compz, n, ilo, ihi, h, ldh, t, ldt,alpha, beta, q, & ldq, z, ldz, work, lwork,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,compz,job integer(${ik}$), intent(in) :: ihi,ilo,ldh,ldq,ldt,ldz,lwork,n integer(${ik}$), intent(out) :: info real(sp), intent(out) :: rwork(*) complex(sp), intent(out) :: alpha(*),beta(*),work(*) complex(sp), intent(inout) :: h(ldh,*),q(ldq,*),t(ldt,*),z(ldz,*) end subroutine chgeqz #else module procedure stdlib${ii}$_chgeqz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dhgeqz( job, compq, compz, n, ilo, ihi, h, ldh, t, ldt,alphar, alphai, & beta, q, ldq, z, ldz, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,compz,job integer(${ik}$), intent(in) :: ihi,ilo,ldh,ldq,ldt,ldz,lwork,n integer(${ik}$), intent(out) :: info real(dp), intent(out) :: alphai(*),alphar(*),beta(*),work(*) real(dp), intent(inout) :: h(ldh,*),q(ldq,*),t(ldt,*),z(ldz,*) end subroutine dhgeqz #else module procedure stdlib${ii}$_dhgeqz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine shgeqz( job, compq, compz, n, ilo, ihi, h, ldh, t, ldt,alphar, alphai, & beta, q, ldq, z, ldz, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,compz,job integer(${ik}$), intent(in) :: ihi,ilo,ldh,ldq,ldt,ldz,lwork,n integer(${ik}$), intent(out) :: info real(sp), intent(out) :: alphai(*),alphar(*),beta(*),work(*) real(sp), intent(inout) :: h(ldh,*),q(ldq,*),t(ldt,*),z(ldz,*) end subroutine shgeqz #else module procedure stdlib${ii}$_shgeqz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhgeqz( job, compq, compz, n, ilo, ihi, h, ldh, t, ldt,alpha, beta, q, & ldq, z, ldz, work, lwork,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,compz,job integer(${ik}$), intent(in) :: ihi,ilo,ldh,ldq,ldt,ldz,lwork,n integer(${ik}$), intent(out) :: info real(dp), intent(out) :: rwork(*) complex(dp), intent(out) :: alpha(*),beta(*),work(*) complex(dp), intent(inout) :: h(ldh,*),q(ldq,*),t(ldt,*),z(ldz,*) end subroutine zhgeqz #else module procedure stdlib${ii}$_zhgeqz #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hgeqz #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hgeqz #:endif #:endfor #:endfor end interface hgeqz interface hpcon !! HPCON estimates the reciprocal of the condition number of a complex !! Hermitian packed matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chpcon( uplo, n, ap, ipiv, anorm, rcond, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond complex(sp), intent(in) :: ap(*) complex(sp), intent(out) :: work(*) end subroutine chpcon #else module procedure stdlib${ii}$_chpcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhpcon( uplo, n, ap, ipiv, anorm, rcond, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond complex(dp), intent(in) :: ap(*) complex(dp), intent(out) :: work(*) end subroutine zhpcon #else module procedure stdlib${ii}$_zhpcon #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hpcon #:endif #:endfor #:endfor end interface hpcon interface hpev !! HPEV computes all the eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix in packed storage. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chpev( jobz, uplo, n, ap, w, z, ldz, work, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: ap(*) complex(sp), intent(out) :: work(*),z(ldz,*) end subroutine chpev #else module procedure stdlib${ii}$_chpev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhpev( jobz, uplo, n, ap, w, z, ldz, work, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: ap(*) complex(dp), intent(out) :: work(*),z(ldz,*) end subroutine zhpev #else module procedure stdlib${ii}$_zhpev #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hpev #:endif #:endfor #:endfor end interface hpev interface hpevd !! HPEVD computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chpevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,rwork, lrwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldz,liwork,lrwork,lwork,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: ap(*) complex(sp), intent(out) :: work(*),z(ldz,*) end subroutine chpevd #else module procedure stdlib${ii}$_chpevd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhpevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,rwork, lrwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldz,liwork,lrwork,lwork,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: ap(*) complex(dp), intent(out) :: work(*),z(ldz,*) end subroutine zhpevd #else module procedure stdlib${ii}$_zhpevd #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hpevd #:endif #:endfor #:endfor end interface hpevd interface hpgst !! HPGST reduces a complex Hermitian-definite generalized !! eigenproblem to standard form, using packed storage. !! If ITYPE = 1, the problem is A*x = lambda*B*x, !! and A is overwritten by inv(U**H)*A*inv(U) or inv(L)*A*inv(L**H) !! If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or !! B*A*x = lambda*x, and A is overwritten by U*A*U**H or L**H*A*L. !! B must have been previously factorized as U**H*U or L*L**H by CPPTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chpgst( itype, uplo, n, ap, bp, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,n complex(sp), intent(inout) :: ap(*) complex(sp), intent(in) :: bp(*) end subroutine chpgst #else module procedure stdlib${ii}$_chpgst #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhpgst( itype, uplo, n, ap, bp, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,n complex(dp), intent(inout) :: ap(*) complex(dp), intent(in) :: bp(*) end subroutine zhpgst #else module procedure stdlib${ii}$_zhpgst #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hpgst #:endif #:endfor #:endfor end interface hpgst interface hpgv !! HPGV computes all the eigenvalues and, optionally, the eigenvectors !! of a complex generalized Hermitian-definite eigenproblem, of the form !! A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. !! Here A and B are assumed to be Hermitian, stored in packed format, !! and B is also positive definite. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chpgv( itype, jobz, uplo, n, ap, bp, w, z, ldz, work,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,ldz,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: ap(*),bp(*) complex(sp), intent(out) :: work(*),z(ldz,*) end subroutine chpgv #else module procedure stdlib${ii}$_chpgv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhpgv( itype, jobz, uplo, n, ap, bp, w, z, ldz, work,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,ldz,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: ap(*),bp(*) complex(dp), intent(out) :: work(*),z(ldz,*) end subroutine zhpgv #else module procedure stdlib${ii}$_zhpgv #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hpgv #:endif #:endfor #:endfor end interface hpgv interface hpgvd !! HPGVD computes all the eigenvalues and, optionally, the eigenvectors !! of a complex generalized Hermitian-definite eigenproblem, of the form !! A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. Here A and !! B are assumed to be Hermitian, stored in packed format, and B is also !! positive definite. !! If eigenvectors are desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chpgvd( itype, jobz, uplo, n, ap, bp, w, z, ldz, work,lwork, rwork, & lrwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: itype,ldz,liwork,lrwork,lwork,n real(sp), intent(out) :: rwork(*),w(*) complex(sp), intent(inout) :: ap(*),bp(*) complex(sp), intent(out) :: work(*),z(ldz,*) end subroutine chpgvd #else module procedure stdlib${ii}$_chpgvd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhpgvd( itype, jobz, uplo, n, ap, bp, w, z, ldz, work,lwork, rwork, & lrwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: itype,ldz,liwork,lrwork,lwork,n real(dp), intent(out) :: rwork(*),w(*) complex(dp), intent(inout) :: ap(*),bp(*) complex(dp), intent(out) :: work(*),z(ldz,*) end subroutine zhpgvd #else module procedure stdlib${ii}$_zhpgvd #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hpgvd #:endif #:endfor #:endfor end interface hpgvd interface hprfs !! HPRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian indefinite !! and packed, and provides error bounds and backward error estimates !! for the solution. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, & work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs,ipiv(*) real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: afp(*),ap(*),b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine chprfs #else module procedure stdlib${ii}$_chprfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, & work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs,ipiv(*) real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: afp(*),ap(*),b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zhprfs #else module procedure stdlib${ii}$_zhprfs #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hprfs #:endif #:endfor #:endfor end interface hprfs interface hpsv !! HPSV computes the solution to a complex system of linear equations !! A * X = B, !! where A is an N-by-N Hermitian matrix stored in packed format and X !! and B are N-by-NRHS matrices. !! The diagonal pivoting method is used to factor A as !! A = U * D * U**H, if UPLO = 'U', or !! A = L * D * L**H, if UPLO = 'L', !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, D is Hermitian and block diagonal with 1-by-1 !! and 2-by-2 diagonal blocks. The factored form of A is then used to !! solve the system of equations A * X = B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chpsv( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: ldb,n,nrhs complex(sp), intent(inout) :: ap(*),b(ldb,*) end subroutine chpsv #else module procedure stdlib${ii}$_chpsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhpsv( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: ldb,n,nrhs complex(dp), intent(inout) :: ap(*),b(ldb,*) end subroutine zhpsv #else module procedure stdlib${ii}$_zhpsv #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hpsv #:endif #:endfor #:endfor end interface hpsv interface hptrd !! HPTRD reduces a complex Hermitian matrix A stored in packed form to !! real symmetric tridiagonal form T by a unitary similarity !! transformation: Q**H * A * Q = T. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chptrd( uplo, n, ap, d, e, tau, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(out) :: d(*),e(*) complex(sp), intent(inout) :: ap(*) complex(sp), intent(out) :: tau(*) end subroutine chptrd #else module procedure stdlib${ii}$_chptrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhptrd( uplo, n, ap, d, e, tau, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: d(*),e(*) complex(dp), intent(inout) :: ap(*) complex(dp), intent(out) :: tau(*) end subroutine zhptrd #else module procedure stdlib${ii}$_zhptrd #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hptrd #:endif #:endfor #:endfor end interface hptrd interface hptrf !! HPTRF computes the factorization of a complex Hermitian packed !! matrix A using the Bunch-Kaufman diagonal pivoting method: !! A = U*D*U**H or A = L*D*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chptrf( uplo, n, ap, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: n complex(sp), intent(inout) :: ap(*) end subroutine chptrf #else module procedure stdlib${ii}$_chptrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhptrf( uplo, n, ap, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: n complex(dp), intent(inout) :: ap(*) end subroutine zhptrf #else module procedure stdlib${ii}$_zhptrf #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hptrf #:endif #:endfor #:endfor end interface hptrf interface hptri !! HPTRI computes the inverse of a complex Hermitian indefinite matrix !! A in packed storage using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHPTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chptri( uplo, n, ap, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) complex(sp), intent(inout) :: ap(*) complex(sp), intent(out) :: work(*) end subroutine chptri #else module procedure stdlib${ii}$_chptri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhptri( uplo, n, ap, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) complex(dp), intent(inout) :: ap(*) complex(dp), intent(out) :: work(*) end subroutine zhptri #else module procedure stdlib${ii}$_zhptri #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hptri #:endif #:endfor #:endfor end interface hptri interface hptrs !! HPTRS solves a system of linear equations A*X = B with a complex !! Hermitian matrix A stored in packed format using the factorization !! A = U*D*U**H or A = L*D*L**H computed by CHPTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chptrs( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs,ipiv(*) complex(sp), intent(in) :: ap(*) complex(sp), intent(inout) :: b(ldb,*) end subroutine chptrs #else module procedure stdlib${ii}$_chptrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhptrs( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs,ipiv(*) complex(dp), intent(in) :: ap(*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zhptrs #else module procedure stdlib${ii}$_zhptrs #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hptrs #:endif #:endfor #:endfor end interface hptrs interface hsein !! HSEIN uses inverse iteration to find specified right and/or left !! eigenvectors of a complex upper Hessenberg matrix H. !! The right eigenvector x and the left eigenvector y of the matrix H !! corresponding to an eigenvalue w are defined by: !! H * x = w * x, y**h * H = w * y**h !! where y**h denotes the conjugate transpose of the vector y. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine chsein( side, eigsrc, initv, select, n, h, ldh, w, vl,ldvl, vr, ldvr, & mm, m, work, rwork, ifaill,ifailr, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: eigsrc,initv,side integer(${ik}$), intent(out) :: info,m,ifaill(*),ifailr(*) integer(${ik}$), intent(in) :: ldh,ldvl,ldvr,mm,n logical(lk), intent(in) :: select(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(in) :: h(ldh,*) complex(sp), intent(inout) :: vl(ldvl,*),vr(ldvr,*),w(*) complex(sp), intent(out) :: work(*) end subroutine chsein #else module procedure stdlib${ii}$_chsein #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dhsein( side, eigsrc, initv, select, n, h, ldh, wr, wi,vl, ldvl, vr, & ldvr, mm, m, work, ifaill,ifailr, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: eigsrc,initv,side integer(${ik}$), intent(out) :: info,m,ifaill(*),ifailr(*) integer(${ik}$), intent(in) :: ldh,ldvl,ldvr,mm,n logical(lk), intent(inout) :: select(*) real(dp), intent(in) :: h(ldh,*),wi(*) real(dp), intent(inout) :: vl(ldvl,*),vr(ldvr,*),wr(*) real(dp), intent(out) :: work(*) end subroutine dhsein #else module procedure stdlib${ii}$_dhsein #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine shsein( side, eigsrc, initv, select, n, h, ldh, wr, wi,vl, ldvl, vr, & ldvr, mm, m, work, ifaill,ifailr, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: eigsrc,initv,side integer(${ik}$), intent(out) :: info,m,ifaill(*),ifailr(*) integer(${ik}$), intent(in) :: ldh,ldvl,ldvr,mm,n logical(lk), intent(inout) :: select(*) real(sp), intent(in) :: h(ldh,*),wi(*) real(sp), intent(inout) :: vl(ldvl,*),vr(ldvr,*),wr(*) real(sp), intent(out) :: work(*) end subroutine shsein #else module procedure stdlib${ii}$_shsein #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zhsein( side, eigsrc, initv, select, n, h, ldh, w, vl,ldvl, vr, ldvr, & mm, m, work, rwork, ifaill,ifailr, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: eigsrc,initv,side integer(${ik}$), intent(out) :: info,m,ifaill(*),ifailr(*) integer(${ik}$), intent(in) :: ldh,ldvl,ldvr,mm,n logical(lk), intent(in) :: select(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(in) :: h(ldh,*) complex(dp), intent(inout) :: vl(ldvl,*),vr(ldvr,*),w(*) complex(dp), intent(out) :: work(*) end subroutine zhsein #else module procedure stdlib${ii}$_zhsein #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hsein #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hsein #:endif #:endfor #:endfor end interface hsein interface hseqr !! HSEQR computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*T*(QZ)**H. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine chseqr( job, compz, n, ilo, ihi, h, ldh, w, z, ldz,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info character, intent(in) :: compz,job complex(sp), intent(inout) :: h(ldh,*),z(ldz,*) complex(sp), intent(out) :: w(*),work(*) end subroutine chseqr #else module procedure stdlib${ii}$_chseqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dhseqr( job, compz, n, ilo, ihi, h, ldh, wr, wi, z,ldz, work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info character, intent(in) :: compz,job real(dp), intent(inout) :: h(ldh,*),z(ldz,*) real(dp), intent(out) :: wi(*),work(*),wr(*) end subroutine dhseqr #else module procedure stdlib${ii}$_dhseqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine shseqr( job, compz, n, ilo, ihi, h, ldh, wr, wi, z,ldz, work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info character, intent(in) :: compz,job real(sp), intent(inout) :: h(ldh,*),z(ldz,*) real(sp), intent(out) :: wi(*),work(*),wr(*) end subroutine shseqr #else module procedure stdlib${ii}$_shseqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zhseqr( job, compz, n, ilo, ihi, h, ldh, w, z, ldz,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info character, intent(in) :: compz,job complex(dp), intent(inout) :: h(ldh,*),z(ldz,*) complex(dp), intent(out) :: w(*),work(*) end subroutine zhseqr #else module procedure stdlib${ii}$_zhseqr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hseqr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$hseqr #:endif #:endfor #:endfor end interface hseqr interface isnan !! ISNAN returns .TRUE. if its argument is NaN, and .FALSE. !! otherwise. To be replaced by the Fortran 2003 intrinsic in the !! future. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure logical(lk) function disnan( din ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: din end function disnan #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_disnan #:endif #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure logical(lk) function sisnan( sin ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: sin end function sisnan #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_sisnan #:endif #endif #:endfor #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib_${ri}$isnan #:endif #:endfor end interface isnan interface la_gbamv !! LA_GBAMV performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta integer(${ik}$), intent(in) :: incx,incy,ldab,m,n,kl,ku,trans complex(sp), intent(in) :: ab(ldab,*),x(*) real(sp), intent(inout) :: y(*) end subroutine cla_gbamv #else module procedure stdlib${ii}$_cla_gbamv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta,ab(ldab,*),x(*) integer(${ik}$), intent(in) :: incx,incy,ldab,m,n,kl,ku,trans real(dp), intent(inout) :: y(*) end subroutine dla_gbamv #else module procedure stdlib${ii}$_dla_gbamv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta,ab(ldab,*),x(*) integer(${ik}$), intent(in) :: incx,incy,ldab,m,n,kl,ku,trans real(sp), intent(inout) :: y(*) end subroutine sla_gbamv #else module procedure stdlib${ii}$_sla_gbamv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta integer(${ik}$), intent(in) :: incx,incy,ldab,m,n,kl,ku,trans complex(dp), intent(in) :: ab(ldab,*),x(*) real(dp), intent(inout) :: y(*) end subroutine zla_gbamv #else module procedure stdlib${ii}$_zla_gbamv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_gbamv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_gbamv #:endif #:endfor #:endfor end interface la_gbamv interface la_gbrcond !! LA_GBRCOND Estimates the Skeel condition number of op(A) * op2(C) !! where op2 is determined by CMODE as follows !! CMODE = 1 op2(C) = C !! CMODE = 0 op2(C) = I !! CMODE = -1 op2(C) = inv(C) !! The Skeel condition number cond(A) = norminf( |inv(A)||A| ) !! is computed by computing scaling factors R such that !! diag(R)*A*op2(C) is row equilibrated and computing the standard !! infinity-norm condition number. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dla_gbrcond( trans, n, kl, ku, ab, ldab,afb, ldafb, ipiv, cmode, & c,info, work, iwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: n,ldab,ldafb,kl,ku,cmode,ipiv(*) integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(in) :: ab(ldab,*),afb(ldafb,*),c(*) real(dp), intent(out) :: work(*) end function dla_gbrcond #else module procedure stdlib${ii}$_dla_gbrcond #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function sla_gbrcond( trans, n, kl, ku, ab, ldab, afb, ldafb,ipiv, cmode, & c, info, work, iwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: n,ldab,ldafb,kl,ku,cmode,ipiv(*) integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(in) :: ab(ldab,*),afb(ldafb,*),c(*) real(sp), intent(out) :: work(*) end function sla_gbrcond #else module procedure stdlib${ii}$_sla_gbrcond #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_gbrcond #:endif #:endfor #:endfor end interface la_gbrcond interface la_gbrcond_c !! LA_GBRCOND_C Computes the infinity norm condition number of !! op(A) * inv(diag(C)) where C is a REAL vector. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function cla_gbrcond_c( trans, n, kl, ku, ab, ldab, afb,ldafb, ipiv, c, & capply, info, work,rwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n,kl,ku,ldab,ldafb,ipiv(*) integer(${ik}$), intent(out) :: info complex(sp), intent(in) :: ab(ldab,*),afb(ldafb,*) complex(sp), intent(out) :: work(*) real(sp), intent(in) :: c(*) real(sp), intent(out) :: rwork(*) end function cla_gbrcond_c #else module procedure stdlib${ii}$_cla_gbrcond_c #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zla_gbrcond_c( trans, n, kl, ku, ab,ldab, afb, ldafb, ipiv,c, & capply, info, work,rwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n,kl,ku,ldab,ldafb,ipiv(*) integer(${ik}$), intent(out) :: info complex(dp), intent(in) :: ab(ldab,*),afb(ldafb,*) complex(dp), intent(out) :: work(*) real(dp), intent(in) :: c(*) real(dp), intent(out) :: rwork(*) end function zla_gbrcond_c #else module procedure stdlib${ii}$_zla_gbrcond_c #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_gbrcond_c #:endif #:endfor #:endfor end interface la_gbrcond_c interface la_gbrpvgrw !! LA_GBRPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(sp) function cla_gbrpvgrw( n, kl, ku, ncols, ab, ldab, afb,ldafb ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,kl,ku,ncols,ldab,ldafb complex(sp), intent(in) :: ab(ldab,*),afb(ldafb,*) end function cla_gbrpvgrw #else module procedure stdlib${ii}$_cla_gbrpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(dp) function dla_gbrpvgrw( n, kl, ku, ncols, ab,ldab, afb, ldafb ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,kl,ku,ncols,ldab,ldafb real(dp), intent(in) :: ab(ldab,*),afb(ldafb,*) end function dla_gbrpvgrw #else module procedure stdlib${ii}$_dla_gbrpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(sp) function sla_gbrpvgrw( n, kl, ku, ncols, ab, ldab, afb,ldafb ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,kl,ku,ncols,ldab,ldafb real(sp), intent(in) :: ab(ldab,*),afb(ldafb,*) end function sla_gbrpvgrw #else module procedure stdlib${ii}$_sla_gbrpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(dp) function zla_gbrpvgrw( n, kl, ku, ncols, ab,ldab, afb, ldafb ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,kl,ku,ncols,ldab,ldafb complex(dp), intent(in) :: ab(ldab,*),afb(ldafb,*) end function zla_gbrpvgrw #else module procedure stdlib${ii}$_zla_gbrpvgrw #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_gbrpvgrw #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_gbrpvgrw #:endif #:endfor #:endfor end interface la_gbrpvgrw interface la_geamv !! LA_GEAMV performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cla_geamv( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta integer(${ik}$), intent(in) :: incx,incy,lda,m,n,trans complex(sp), intent(in) :: a(lda,*),x(*) real(sp), intent(inout) :: y(*) end subroutine cla_geamv #else module procedure stdlib${ii}$_cla_geamv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dla_geamv ( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta,a(lda,*),x(*) integer(${ik}$), intent(in) :: incx,incy,lda,m,n,trans real(dp), intent(inout) :: y(*) end subroutine dla_geamv #else module procedure stdlib${ii}$_dla_geamv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sla_geamv( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta,a(lda,*),x(*) integer(${ik}$), intent(in) :: incx,incy,lda,m,n,trans real(sp), intent(inout) :: y(*) end subroutine sla_geamv #else module procedure stdlib${ii}$_sla_geamv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zla_geamv( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta integer(${ik}$), intent(in) :: incx,incy,lda,m,n,trans complex(dp), intent(in) :: a(lda,*),x(*) real(dp), intent(inout) :: y(*) end subroutine zla_geamv #else module procedure stdlib${ii}$_zla_geamv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_geamv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_geamv #:endif #:endfor #:endfor end interface la_geamv interface la_gercond !! LA_GERCOND estimates the Skeel condition number of op(A) * op2(C) !! where op2 is determined by CMODE as follows !! CMODE = 1 op2(C) = C !! CMODE = 0 op2(C) = I !! CMODE = -1 op2(C) = inv(C) !! The Skeel condition number cond(A) = norminf( |inv(A)||A| ) !! is computed by computing scaling factors R such that !! diag(R)*A*op2(C) is row equilibrated and computing the standard !! infinity-norm condition number. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dla_gercond( trans, n, a, lda, af,ldaf, ipiv, cmode, c,info, & work, iwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: n,lda,ldaf,cmode,ipiv(*) integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(in) :: a(lda,*),af(ldaf,*),c(*) real(dp), intent(out) :: work(*) end function dla_gercond #else module procedure stdlib${ii}$_dla_gercond #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function sla_gercond( trans, n, a, lda, af, ldaf, ipiv,cmode, c, info, & work, iwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: n,lda,ldaf,cmode,ipiv(*) integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(in) :: a(lda,*),af(ldaf,*),c(*) real(sp), intent(out) :: work(*) end function sla_gercond #else module procedure stdlib${ii}$_sla_gercond #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_gercond #:endif #:endfor #:endfor end interface la_gercond interface la_gercond_c !! LA_GERCOND_C computes the infinity norm condition number of !! op(A) * inv(diag(C)) where C is a REAL vector. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function cla_gercond_c( trans, n, a, lda, af, ldaf, ipiv, c,capply, info, & work, rwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n,lda,ldaf,ipiv(*) integer(${ik}$), intent(out) :: info complex(sp), intent(in) :: a(lda,*),af(ldaf,*) complex(sp), intent(out) :: work(*) real(sp), intent(in) :: c(*) real(sp), intent(out) :: rwork(*) end function cla_gercond_c #else module procedure stdlib${ii}$_cla_gercond_c #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zla_gercond_c( trans, n, a, lda, af,ldaf, ipiv, c, capply,info, & work, rwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n,lda,ldaf,ipiv(*) integer(${ik}$), intent(out) :: info complex(dp), intent(in) :: a(lda,*),af(ldaf,*) complex(dp), intent(out) :: work(*) real(dp), intent(in) :: c(*) real(dp), intent(out) :: rwork(*) end function zla_gercond_c #else module procedure stdlib${ii}$_zla_gercond_c #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_gercond_c #:endif #:endfor #:endfor end interface la_gercond_c interface la_gerpvgrw !! LA_GERPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(sp) function cla_gerpvgrw( n, ncols, a, lda, af, ldaf ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,ncols,lda,ldaf complex(sp), intent(in) :: a(lda,*),af(ldaf,*) end function cla_gerpvgrw #else module procedure stdlib${ii}$_cla_gerpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(dp) function dla_gerpvgrw( n, ncols, a, lda, af,ldaf ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,ncols,lda,ldaf real(dp), intent(in) :: a(lda,*),af(ldaf,*) end function dla_gerpvgrw #else module procedure stdlib${ii}$_dla_gerpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(sp) function sla_gerpvgrw( n, ncols, a, lda, af, ldaf ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,ncols,lda,ldaf real(sp), intent(in) :: a(lda,*),af(ldaf,*) end function sla_gerpvgrw #else module procedure stdlib${ii}$_sla_gerpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(dp) function zla_gerpvgrw( n, ncols, a, lda, af,ldaf ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,ncols,lda,ldaf complex(dp), intent(in) :: a(lda,*),af(ldaf,*) end function zla_gerpvgrw #else module procedure stdlib${ii}$_zla_gerpvgrw #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_gerpvgrw #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_gerpvgrw #:endif #:endfor #:endfor end interface la_gerpvgrw interface la_heamv !! CLA_SYAMV performs the matrix-vector operation !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! n by n symmetric matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cla_heamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta integer(${ik}$), intent(in) :: incx,incy,lda,n,uplo complex(sp), intent(in) :: a(lda,*),x(*) real(sp), intent(inout) :: y(*) end subroutine cla_heamv #else module procedure stdlib${ii}$_cla_heamv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zla_heamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta integer(${ik}$), intent(in) :: incx,incy,lda,n,uplo complex(dp), intent(in) :: a(lda,*),x(*) real(dp), intent(inout) :: y(*) end subroutine zla_heamv #else module procedure stdlib${ii}$_zla_heamv #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_heamv #:endif #:endfor #:endfor end interface la_heamv interface la_hercond_c !! LA_HERCOND_C computes the infinity norm condition number of !! op(A) * inv(diag(C)) where C is a REAL vector. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function cla_hercond_c( uplo, n, a, lda, af, ldaf, ipiv, c,capply, info, & work, rwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n,lda,ldaf,ipiv(*) integer(${ik}$), intent(out) :: info complex(sp), intent(in) :: a(lda,*),af(ldaf,*) complex(sp), intent(out) :: work(*) real(sp), intent(in) :: c(*) real(sp), intent(out) :: rwork(*) end function cla_hercond_c #else module procedure stdlib${ii}$_cla_hercond_c #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zla_hercond_c( uplo, n, a, lda, af,ldaf, ipiv, c, capply,info, & work, rwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n,lda,ldaf,ipiv(*) integer(${ik}$), intent(out) :: info complex(dp), intent(in) :: a(lda,*),af(ldaf,*) complex(dp), intent(out) :: work(*) real(dp), intent(in) :: c(*) real(dp), intent(out) :: rwork(*) end function zla_hercond_c #else module procedure stdlib${ii}$_zla_hercond_c #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_hercond_c #:endif #:endfor #:endfor end interface la_hercond_c interface la_herpvgrw !! LA_HERPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function cla_herpvgrw( uplo, n, info, a, lda, af, ldaf, ipiv,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,info,lda,ldaf,ipiv(*) complex(sp), intent(in) :: a(lda,*),af(ldaf,*) real(sp), intent(out) :: work(*) end function cla_herpvgrw #else module procedure stdlib${ii}$_cla_herpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zla_herpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,info,lda,ldaf,ipiv(*) complex(dp), intent(in) :: a(lda,*),af(ldaf,*) real(dp), intent(out) :: work(*) end function zla_herpvgrw #else module procedure stdlib${ii}$_zla_herpvgrw #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_herpvgrw #:endif #:endfor #:endfor end interface la_herpvgrw interface la_lin_berr !! LA_LIN_BERR computes componentwise relative backward error from !! the formula !! max(i) ( abs(R(i)) / ( abs(op(A_s))*abs(Y) + abs(B_s) )(i) ) !! where abs(Z) is the componentwise absolute value of the matrix !! or vector Z. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cla_lin_berr( n, nz, nrhs, res, ayb, berr ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,nz,nrhs real(sp), intent(in) :: ayb(n,nrhs) real(sp), intent(out) :: berr(nrhs) complex(sp), intent(in) :: res(n,nrhs) end subroutine cla_lin_berr #else module procedure stdlib${ii}$_cla_lin_berr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dla_lin_berr ( n, nz, nrhs, res, ayb, berr ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,nz,nrhs real(dp), intent(in) :: ayb(n,nrhs),res(n,nrhs) real(dp), intent(out) :: berr(nrhs) end subroutine dla_lin_berr #else module procedure stdlib${ii}$_dla_lin_berr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sla_lin_berr( n, nz, nrhs, res, ayb, berr ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,nz,nrhs real(sp), intent(in) :: ayb(n,nrhs),res(n,nrhs) real(sp), intent(out) :: berr(nrhs) end subroutine sla_lin_berr #else module procedure stdlib${ii}$_sla_lin_berr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zla_lin_berr( n, nz, nrhs, res, ayb, berr ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,nz,nrhs real(dp), intent(in) :: ayb(n,nrhs) real(dp), intent(out) :: berr(nrhs) complex(dp), intent(in) :: res(n,nrhs) end subroutine zla_lin_berr #else module procedure stdlib${ii}$_zla_lin_berr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_lin_berr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_lin_berr #:endif #:endfor #:endfor end interface la_lin_berr interface la_porcond !! LA_PORCOND Estimates the Skeel condition number of op(A) * op2(C) !! where op2 is determined by CMODE as follows !! CMODE = 1 op2(C) = C !! CMODE = 0 op2(C) = I !! CMODE = -1 op2(C) = inv(C) !! The Skeel condition number cond(A) = norminf( |inv(A)||A| ) !! is computed by computing scaling factors R such that !! diag(R)*A*op2(C) is row equilibrated and computing the standard !! infinity-norm condition number. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dla_porcond( uplo, n, a, lda, af, ldaf,cmode, c, info, work,& iwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,lda,ldaf,cmode integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(in) :: a(lda,*),af(ldaf,*),c(*) real(dp), intent(out) :: work(*) end function dla_porcond #else module procedure stdlib${ii}$_dla_porcond #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function sla_porcond( uplo, n, a, lda, af, ldaf, cmode, c,info, work, & iwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,lda,ldaf,cmode integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(in) :: a(lda,*),af(ldaf,*),c(*) real(sp), intent(out) :: work(*) end function sla_porcond #else module procedure stdlib${ii}$_sla_porcond #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_porcond #:endif #:endfor #:endfor end interface la_porcond interface la_porcond_c !! LA_PORCOND_C Computes the infinity norm condition number of !! op(A) * inv(diag(C)) where C is a REAL vector #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function cla_porcond_c( uplo, n, a, lda, af, ldaf, c, capply,info, work, & rwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n,lda,ldaf integer(${ik}$), intent(out) :: info complex(sp), intent(in) :: a(lda,*),af(ldaf,*) complex(sp), intent(out) :: work(*) real(sp), intent(in) :: c(*) real(sp), intent(out) :: rwork(*) end function cla_porcond_c #else module procedure stdlib${ii}$_cla_porcond_c #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zla_porcond_c( uplo, n, a, lda, af,ldaf, c, capply, info,work, & rwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n,lda,ldaf integer(${ik}$), intent(out) :: info complex(dp), intent(in) :: a(lda,*),af(ldaf,*) complex(dp), intent(out) :: work(*) real(dp), intent(in) :: c(*) real(dp), intent(out) :: rwork(*) end function zla_porcond_c #else module procedure stdlib${ii}$_zla_porcond_c #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_porcond_c #:endif #:endfor #:endfor end interface la_porcond_c interface la_porpvgrw !! LA_PORPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function cla_porpvgrw( uplo, ncols, a, lda, af, ldaf, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: ncols,lda,ldaf complex(sp), intent(in) :: a(lda,*),af(ldaf,*) real(sp), intent(out) :: work(*) end function cla_porpvgrw #else module procedure stdlib${ii}$_cla_porpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dla_porpvgrw( uplo, ncols, a, lda, af,ldaf, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: ncols,lda,ldaf real(dp), intent(in) :: a(lda,*),af(ldaf,*) real(dp), intent(out) :: work(*) end function dla_porpvgrw #else module procedure stdlib${ii}$_dla_porpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function sla_porpvgrw( uplo, ncols, a, lda, af, ldaf, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: ncols,lda,ldaf real(sp), intent(in) :: a(lda,*),af(ldaf,*) real(sp), intent(out) :: work(*) end function sla_porpvgrw #else module procedure stdlib${ii}$_sla_porpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zla_porpvgrw( uplo, ncols, a, lda, af,ldaf, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: ncols,lda,ldaf complex(dp), intent(in) :: a(lda,*),af(ldaf,*) real(dp), intent(out) :: work(*) end function zla_porpvgrw #else module procedure stdlib${ii}$_zla_porpvgrw #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_porpvgrw #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_porpvgrw #:endif #:endfor #:endfor end interface la_porpvgrw interface la_syamv !! LA_SYAMV performs the matrix-vector operation !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! n by n symmetric matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cla_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta integer(${ik}$), intent(in) :: incx,incy,lda,n,uplo complex(sp), intent(in) :: a(lda,*),x(*) real(sp), intent(inout) :: y(*) end subroutine cla_syamv #else module procedure stdlib${ii}$_cla_syamv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dla_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta,a(lda,*),x(*) integer(${ik}$), intent(in) :: incx,incy,lda,n,uplo real(dp), intent(inout) :: y(*) end subroutine dla_syamv #else module procedure stdlib${ii}$_dla_syamv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sla_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta,a(lda,*),x(*) integer(${ik}$), intent(in) :: incx,incy,lda,n,uplo real(sp), intent(inout) :: y(*) end subroutine sla_syamv #else module procedure stdlib${ii}$_sla_syamv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zla_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta integer(${ik}$), intent(in) :: incx,incy,lda,n,uplo complex(dp), intent(in) :: a(lda,*),x(*) real(dp), intent(inout) :: y(*) end subroutine zla_syamv #else module procedure stdlib${ii}$_zla_syamv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_syamv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_syamv #:endif #:endfor #:endfor end interface la_syamv interface la_syrcond !! LA_SYRCOND estimates the Skeel condition number of op(A) * op2(C) !! where op2 is determined by CMODE as follows !! CMODE = 1 op2(C) = C !! CMODE = 0 op2(C) = I !! CMODE = -1 op2(C) = inv(C) !! The Skeel condition number cond(A) = norminf( |inv(A)||A| ) !! is computed by computing scaling factors R such that !! diag(R)*A*op2(C) is row equilibrated and computing the standard !! infinity-norm condition number. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dla_syrcond( uplo, n, a, lda, af, ldaf,ipiv, cmode, c, info, & work,iwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,lda,ldaf,cmode,ipiv(*) integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(in) :: a(lda,*),af(ldaf,*),c(*) real(dp), intent(out) :: work(*) end function dla_syrcond #else module procedure stdlib${ii}$_dla_syrcond #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function sla_syrcond( uplo, n, a, lda, af, ldaf, ipiv, cmode,c, info, & work, iwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,lda,ldaf,cmode,ipiv(*) integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(in) :: a(lda,*),af(ldaf,*),c(*) real(sp), intent(out) :: work(*) end function sla_syrcond #else module procedure stdlib${ii}$_sla_syrcond #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_syrcond #:endif #:endfor #:endfor end interface la_syrcond interface la_syrcond_c !! LA_SYRCOND_C Computes the infinity norm condition number of !! op(A) * inv(diag(C)) where C is a REAL vector. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function cla_syrcond_c( uplo, n, a, lda, af, ldaf, ipiv, c,capply, info, & work, rwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n,lda,ldaf,ipiv(*) integer(${ik}$), intent(out) :: info complex(sp), intent(in) :: a(lda,*),af(ldaf,*) complex(sp), intent(out) :: work(*) real(sp), intent(in) :: c(*) real(sp), intent(out) :: rwork(*) end function cla_syrcond_c #else module procedure stdlib${ii}$_cla_syrcond_c #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zla_syrcond_c( uplo, n, a, lda, af,ldaf, ipiv, c, capply,info, & work, rwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n,lda,ldaf,ipiv(*) integer(${ik}$), intent(out) :: info complex(dp), intent(in) :: a(lda,*),af(ldaf,*) complex(dp), intent(out) :: work(*) real(dp), intent(in) :: c(*) real(dp), intent(out) :: rwork(*) end function zla_syrcond_c #else module procedure stdlib${ii}$_zla_syrcond_c #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_syrcond_c #:endif #:endfor #:endfor end interface la_syrcond_c interface la_syrpvgrw !! LA_SYRPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function cla_syrpvgrw( uplo, n, info, a, lda, af, ldaf, ipiv,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,info,lda,ldaf,ipiv(*) complex(sp), intent(in) :: a(lda,*),af(ldaf,*) real(sp), intent(out) :: work(*) end function cla_syrpvgrw #else module procedure stdlib${ii}$_cla_syrpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dla_syrpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,info,lda,ldaf,ipiv(*) real(dp), intent(in) :: a(lda,*),af(ldaf,*) real(dp), intent(out) :: work(*) end function dla_syrpvgrw #else module procedure stdlib${ii}$_dla_syrpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function sla_syrpvgrw( uplo, n, info, a, lda, af, ldaf, ipiv,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,info,lda,ldaf,ipiv(*) real(sp), intent(in) :: a(lda,*),af(ldaf,*) real(sp), intent(out) :: work(*) end function sla_syrpvgrw #else module procedure stdlib${ii}$_sla_syrpvgrw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zla_syrpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,info,lda,ldaf,ipiv(*) complex(dp), intent(in) :: a(lda,*),af(ldaf,*) real(dp), intent(out) :: work(*) end function zla_syrpvgrw #else module procedure stdlib${ii}$_zla_syrpvgrw #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_syrpvgrw #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_syrpvgrw #:endif #:endfor #:endfor end interface la_syrpvgrw interface la_wwaddw !! LA_WWADDW adds a vector W into a doubled-single vector (X, Y). !! This works for all extant IBM's hex and binary floating point !! arithmetic, but not for decimal. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cla_wwaddw( n, x, y, w ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n complex(sp), intent(inout) :: x(*),y(*) complex(sp), intent(in) :: w(*) end subroutine cla_wwaddw #else module procedure stdlib${ii}$_cla_wwaddw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dla_wwaddw( n, x, y, w ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: x(*),y(*) real(dp), intent(in) :: w(*) end subroutine dla_wwaddw #else module procedure stdlib${ii}$_dla_wwaddw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sla_wwaddw( n, x, y, w ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: x(*),y(*) real(sp), intent(in) :: w(*) end subroutine sla_wwaddw #else module procedure stdlib${ii}$_sla_wwaddw #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zla_wwaddw( n, x, y, w ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n complex(dp), intent(inout) :: x(*),y(*) complex(dp), intent(in) :: w(*) end subroutine zla_wwaddw #else module procedure stdlib${ii}$_zla_wwaddw #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_wwaddw #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$la_wwaddw #:endif #:endfor #:endfor end interface la_wwaddw interface labad !! LABAD takes as input the values computed by DLAMCH for underflow and !! overflow, and returns the square root of each of these values if the !! log of LARGE is sufficiently large. This subroutine is intended to !! identify machines with a large exponent range, such as the Crays, and !! redefine the underflow and overflow limits to be the square roots of !! the values computed by DLAMCH. This subroutine is needed because !! DLAMCH does not compensate for poor arithmetic in the upper half of !! the exponent range, as is found on a Cray. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlabad( small, large ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(inout) :: large,small end subroutine dlabad #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_dlabad #:endif #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slabad( small, large ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(inout) :: large,small end subroutine slabad #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_slabad #:endif #endif #:endfor #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib_${ri}$labad #:endif #:endfor end interface labad interface labrd !! LABRD reduces the first NB rows and columns of a complex general !! m by n matrix A to upper or lower real bidiagonal form by a unitary !! transformation Q**H * A * P, and returns the matrices X and Y which !! are needed to apply the transformation to the unreduced part of A. !! If m >= n, A is reduced to upper bidiagonal form; if m < n, to lower !! bidiagonal form. !! This is an auxiliary routine called by CGEBRD #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clabrd( m, n, nb, a, lda, d, e, tauq, taup, x, ldx, y,ldy ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: lda,ldx,ldy,m,n,nb real(sp), intent(out) :: d(*),e(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: taup(*),tauq(*),x(ldx,*),y(ldy,*) end subroutine clabrd #else module procedure stdlib${ii}$_clabrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlabrd( m, n, nb, a, lda, d, e, tauq, taup, x, ldx, y,ldy ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: lda,ldx,ldy,m,n,nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*),e(*),taup(*),tauq(*),x(ldx,*),y(ldy,*) end subroutine dlabrd #else module procedure stdlib${ii}$_dlabrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slabrd( m, n, nb, a, lda, d, e, tauq, taup, x, ldx, y,ldy ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: lda,ldx,ldy,m,n,nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*),e(*),taup(*),tauq(*),x(ldx,*),y(ldy,*) end subroutine slabrd #else module procedure stdlib${ii}$_slabrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlabrd( m, n, nb, a, lda, d, e, tauq, taup, x, ldx, y,ldy ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: lda,ldx,ldy,m,n,nb real(dp), intent(out) :: d(*),e(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: taup(*),tauq(*),x(ldx,*),y(ldy,*) end subroutine zlabrd #else module procedure stdlib${ii}$_zlabrd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$labrd #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$labrd #:endif #:endfor #:endfor end interface labrd interface lacgv !! LACGV conjugates a complex vector of length N. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clacgv( n, x, incx ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n complex(sp), intent(inout) :: x(*) end subroutine clacgv #else module procedure stdlib${ii}$_clacgv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlacgv( n, x, incx ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n complex(dp), intent(inout) :: x(*) end subroutine zlacgv #else module procedure stdlib${ii}$_zlacgv #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lacgv #:endif #:endfor #:endfor end interface lacgv interface lacon !! LACON estimates the 1-norm of a square, complex matrix A. !! Reverse communication is used for evaluating matrix-vector products. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine clacon( n, v, x, est, kase ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: est complex(sp), intent(out) :: v(n) complex(sp), intent(inout) :: x(n) end subroutine clacon #else module procedure stdlib${ii}$_clacon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dlacon( n, v, x, isgn, est, kase ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: est,x(*) integer(${ik}$), intent(out) :: isgn(*) real(dp), intent(out) :: v(*) end subroutine dlacon #else module procedure stdlib${ii}$_dlacon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine slacon( n, v, x, isgn, est, kase ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: est,x(*) integer(${ik}$), intent(out) :: isgn(*) real(sp), intent(out) :: v(*) end subroutine slacon #else module procedure stdlib${ii}$_slacon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zlacon( n, v, x, est, kase ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: est complex(dp), intent(out) :: v(n) complex(dp), intent(inout) :: x(n) end subroutine zlacon #else module procedure stdlib${ii}$_zlacon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lacon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lacon #:endif #:endfor #:endfor end interface lacon interface lacpy !! LACPY copies all or part of a two-dimensional matrix A to another !! matrix B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clacpy( uplo, m, n, a, lda, b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,ldb,m,n complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: b(ldb,*) end subroutine clacpy #else module procedure stdlib${ii}$_clacpy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlacpy( uplo, m, n, a, lda, b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,ldb,m,n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: b(ldb,*) end subroutine dlacpy #else module procedure stdlib${ii}$_dlacpy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slacpy( uplo, m, n, a, lda, b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,ldb,m,n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: b(ldb,*) end subroutine slacpy #else module procedure stdlib${ii}$_slacpy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlacpy( uplo, m, n, a, lda, b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,ldb,m,n complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: b(ldb,*) end subroutine zlacpy #else module procedure stdlib${ii}$_zlacpy #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lacpy #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lacpy #:endif #:endfor #:endfor end interface lacpy interface lacrm !! LACRM performs a very simple matrix-matrix multiplication: !! C := A * B, !! where A is M by N and complex; B is N by N and real; !! C is M by N and complex. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clacrm( m, n, a, lda, b, ldb, c, ldc, rwork ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: lda,ldb,ldc,m,n real(sp), intent(in) :: b(ldb,*) real(sp), intent(out) :: rwork(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: c(ldc,*) end subroutine clacrm #else module procedure stdlib${ii}$_clacrm #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlacrm( m, n, a, lda, b, ldb, c, ldc, rwork ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: lda,ldb,ldc,m,n real(dp), intent(in) :: b(ldb,*) real(dp), intent(out) :: rwork(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: c(ldc,*) end subroutine zlacrm #else module procedure stdlib${ii}$_zlacrm #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lacrm #:endif #:endfor #:endfor end interface lacrm interface lacrt !! LACRT performs the operation !! ( c s )( x ) ==> ( x ) !! ( -s c )( y ) ( y ) !! where c and s are complex and the vectors x and y are complex. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clacrt( n, cx, incx, cy, incy, c, s ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n complex(sp), intent(in) :: c,s complex(sp), intent(inout) :: cx(*),cy(*) end subroutine clacrt #else module procedure stdlib${ii}$_clacrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlacrt( n, cx, incx, cy, incy, c, s ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n complex(dp), intent(in) :: c,s complex(dp), intent(inout) :: cx(*),cy(*) end subroutine zlacrt #else module procedure stdlib${ii}$_zlacrt #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lacrt #:endif #:endfor #:endfor end interface lacrt interface ladiv_f !! LADIV_F := X / Y, where X and Y are complex. The computation of X / Y !! will not overflow on an intermediary step unless the results !! overflows. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure complex(sp) function cladiv( x, y ) import sp,dp,qp,${ik}$,lk implicit none complex(sp), intent(in) :: x,y end function cladiv #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_cladiv #:endif #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure complex(dp) function zladiv( x, y ) import sp,dp,qp,${ik}$,lk implicit none complex(dp), intent(in) :: x,y end function zladiv #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_zladiv #:endif #endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib_${ri}$ladiv #:endif #:endfor end interface ladiv_f interface ladiv_s !! LADIV_S performs complex division in real arithmetic !! a + i*b !! p + i*q = --------- !! c + i*d !! The algorithm is due to Michael Baudin and Robert L. Smith !! and can be found in the paper !! "A Robust Complex Division in Scilab" #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dladiv( a, b, c, d, p, q ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: a,b,c,d real(dp), intent(out) :: p,q end subroutine dladiv #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_dladiv #:endif #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sladiv( a, b, c, d, p, q ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: a,b,c,d real(sp), intent(out) :: p,q end subroutine sladiv #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_sladiv #:endif #endif #:endfor #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib_${ri}$ladiv #:endif #:endfor end interface ladiv_s interface ladiv1 #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dladiv1( a, b, c, d, p, q ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(inout) :: a real(dp), intent(in) :: b,c,d real(dp), intent(out) :: p,q end subroutine dladiv1 #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_dladiv1 #:endif #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sladiv1( a, b, c, d, p, q ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(inout) :: a real(sp), intent(in) :: b,c,d real(sp), intent(out) :: p,q end subroutine sladiv1 #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_sladiv1 #:endif #endif #:endfor #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib_${ri}$ladiv1 #:endif #:endfor end interface ladiv1 interface ladiv2 #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(dp) function dladiv2( a, b, c, d, r, t ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: a,b,c,d,r,t end function dladiv2 #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_dladiv2 #:endif #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(sp) function sladiv2( a, b, c, d, r, t ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: a,b,c,d,r,t end function sladiv2 #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_sladiv2 #:endif #endif #:endfor #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib_${ri}$ladiv2 #:endif #:endfor end interface ladiv2 interface laebz !! LAEBZ contains the iteration loops which compute and use the !! function N(w), which is the count of eigenvalues of a symmetric !! tridiagonal matrix T less than or equal to its argument w. It !! performs a choice of two types of loops: !! IJOB=1, followed by !! IJOB=2: It takes as input a list of intervals and returns a list of !! sufficiently small intervals whose union contains the same !! eigenvalues as the union of the original intervals. !! The input intervals are (AB(j,1),AB(j,2)], j=1,...,MINP. !! The output interval (AB(j,1),AB(j,2)] will contain !! eigenvalues NAB(j,1)+1,...,NAB(j,2), where 1 <= j <= MOUT. !! IJOB=3: It performs a binary search in each input interval !! (AB(j,1),AB(j,2)] for a point w(j) such that !! N(w(j))=NVAL(j), and uses C(j) as the starting point of !! the search. If such a w(j) is found, then on output !! AB(j,1)=AB(j,2)=w. If no such w(j) is found, then on output !! (AB(j,1),AB(j,2)] will be a small interval containing the !! point where N(w) jumps through NVAL(j), unless that point !! lies outside the initial interval. !! Note that the intervals are in all cases half-open intervals, !! i.e., of the form (a,b] , which includes b but not a . !! To avoid underflow, the matrix should be scaled so that its largest !! element is no greater than overflow**(1/2) * underflow**(1/4) !! in absolute value. To assure the most accurate computation !! of small eigenvalues, the matrix should be scaled to be !! not much smaller than that, either. !! See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal !! Matrix", Report CS41, Computer Science Dept., Stanford !! University, July 21, 1966 !! Note: the arguments are, in general, *not* checked for unreasonable !! values. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaebz( ijob, nitmax, n, mmax, minp, nbmin, abstol,reltol, pivmin, & d, e, e2, nval, ab, c, mout,nab, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ijob,minp,mmax,n,nbmin,nitmax integer(${ik}$), intent(out) :: info,mout,iwork(*) real(dp), intent(in) :: abstol,pivmin,reltol,d(*),e(*),e2(*) integer(${ik}$), intent(inout) :: nab(mmax,*),nval(*) real(dp), intent(inout) :: ab(mmax,*),c(*) real(dp), intent(out) :: work(*) end subroutine dlaebz #else module procedure stdlib${ii}$_dlaebz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaebz( ijob, nitmax, n, mmax, minp, nbmin, abstol,reltol, pivmin, & d, e, e2, nval, ab, c, mout,nab, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ijob,minp,mmax,n,nbmin,nitmax integer(${ik}$), intent(out) :: info,mout,iwork(*) real(sp), intent(in) :: abstol,pivmin,reltol,d(*),e(*),e2(*) integer(${ik}$), intent(inout) :: nab(mmax,*),nval(*) real(sp), intent(inout) :: ab(mmax,*),c(*) real(sp), intent(out) :: work(*) end subroutine slaebz #else module procedure stdlib${ii}$_slaebz #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laebz #:endif #:endfor #:endfor end interface laebz interface laed0 !! Using the divide and conquer method, LAED0: computes all eigenvalues !! of a symmetric tridiagonal matrix which is one diagonal block of !! those from reducing a dense or band Hermitian matrix and !! corresponding eigenvectors of the dense or band matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claed0( qsiz, n, d, e, q, ldq, qstore, ldqs, rwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldq,ldqs,n,qsiz real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: q(ldq,*) complex(sp), intent(out) :: qstore(ldqs,*) end subroutine claed0 #else module procedure stdlib${ii}$_claed0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaed0( icompq, qsiz, n, d, e, q, ldq, qstore, ldqs,work, iwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: icompq,ldq,ldqs,n,qsiz integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(inout) :: d(*),e(*),q(ldq,*) real(dp), intent(out) :: qstore(ldqs,*),work(*) end subroutine dlaed0 #else module procedure stdlib${ii}$_dlaed0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaed0( icompq, qsiz, n, d, e, q, ldq, qstore, ldqs,work, iwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: icompq,ldq,ldqs,n,qsiz integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(inout) :: d(*),e(*),q(ldq,*) real(sp), intent(out) :: qstore(ldqs,*),work(*) end subroutine slaed0 #else module procedure stdlib${ii}$_slaed0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaed0( qsiz, n, d, e, q, ldq, qstore, ldqs, rwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldq,ldqs,n,qsiz real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: q(ldq,*) complex(dp), intent(out) :: qstore(ldqs,*) end subroutine zlaed0 #else module procedure stdlib${ii}$_zlaed0 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laed0 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laed0 #:endif #:endfor #:endfor end interface laed0 interface laed1 !! LAED1 computes the updated eigensystem of a diagonal !! matrix after modification by a rank-one symmetric matrix. This !! routine is used only for the eigenproblem which requires all !! eigenvalues and eigenvectors of a tridiagonal matrix. DLAED7 handles !! the case in which eigenvalues only or eigenvalues and eigenvectors !! of a full symmetric matrix (which was reduced to tridiagonal form) !! are desired. !! T = Q(in) ( D(in) + RHO * Z*Z**T ) Q**T(in) = Q(out) * D(out) * Q**T(out) !! where Z = Q**T*u, u is a vector of length N with ones in the !! CUTPNT and CUTPNT + 1 th elements and zeros elsewhere. !! The eigenvectors of the original matrix are stored in Q, and the !! eigenvalues are in D. The algorithm consists of three stages: !! The first stage consists of deflating the size of the problem !! when there are multiple eigenvalues or if there is a zero in !! the Z vector. For each such occurrence the dimension of the !! secular equation problem is reduced by one. This stage is !! performed by the routine DLAED2. !! The second stage consists of calculating the updated !! eigenvalues. This is done by finding the roots of the secular !! equation via the routine DLAED4 (as called by DLAED3). !! This routine also calculates the eigenvectors of the current !! problem. !! The final stage consists of computing the updated eigenvectors !! directly using the updated eigenvalues. The eigenvectors for !! the current problem are multiplied with the eigenvectors from !! the overall problem. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaed1( n, d, q, ldq, indxq, rho, cutpnt, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: cutpnt,ldq,n integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(inout) :: rho,d(*),q(ldq,*) integer(${ik}$), intent(inout) :: indxq(*) real(dp), intent(out) :: work(*) end subroutine dlaed1 #else module procedure stdlib${ii}$_dlaed1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaed1( n, d, q, ldq, indxq, rho, cutpnt, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: cutpnt,ldq,n integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(inout) :: rho,d(*),q(ldq,*) integer(${ik}$), intent(inout) :: indxq(*) real(sp), intent(out) :: work(*) end subroutine slaed1 #else module procedure stdlib${ii}$_slaed1 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laed1 #:endif #:endfor #:endfor end interface laed1 interface laed4 !! This subroutine computes the I-th updated eigenvalue of a symmetric !! rank-one modification to a diagonal matrix whose elements are !! given in the array d, and that !! D(i) < D(j) for i < j !! and that RHO > 0. This is arranged by the calling routine, and is !! no loss in generality. The rank-one modified system is thus !! diag( D ) + RHO * Z * Z_transpose. !! where we assume the Euclidean norm of Z is 1. !! The method consists of approximating the rational functions in the !! secular equation by simpler interpolating rational functions. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaed4( n, i, d, z, delta, rho, dlam, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i,n integer(${ik}$), intent(out) :: info real(dp), intent(out) :: dlam,delta(*) real(dp), intent(in) :: rho,d(*),z(*) end subroutine dlaed4 #else module procedure stdlib${ii}$_dlaed4 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaed4( n, i, d, z, delta, rho, dlam, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i,n integer(${ik}$), intent(out) :: info real(sp), intent(out) :: dlam,delta(*) real(sp), intent(in) :: rho,d(*),z(*) end subroutine slaed4 #else module procedure stdlib${ii}$_slaed4 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laed4 #:endif #:endfor #:endfor end interface laed4 interface laed5 !! This subroutine computes the I-th eigenvalue of a symmetric rank-one !! modification of a 2-by-2 diagonal matrix !! diag( D ) + RHO * Z * transpose(Z) . !! The diagonal elements in the array D are assumed to satisfy !! D(i) < D(j) for i < j . !! We also assume RHO > 0 and that the Euclidean norm of the vector !! Z is one. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaed5( i, d, z, delta, rho, dlam ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i real(dp), intent(out) :: dlam,delta(2) real(dp), intent(in) :: rho,d(2),z(2) end subroutine dlaed5 #else module procedure stdlib${ii}$_dlaed5 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaed5( i, d, z, delta, rho, dlam ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i real(sp), intent(out) :: dlam,delta(2) real(sp), intent(in) :: rho,d(2),z(2) end subroutine slaed5 #else module procedure stdlib${ii}$_slaed5 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laed5 #:endif #:endfor #:endfor end interface laed5 interface laed6 !! LAED6 computes the positive or negative root (closest to the origin) !! of !! z(1) z(2) z(3) !! f(x) = rho + --------- + ---------- + --------- !! d(1)-x d(2)-x d(3)-x !! It is assumed that !! if ORGATI = .true. the root is between d(2) and d(3); !! otherwise it is between d(1) and d(2) !! This routine will be called by DLAED4 when necessary. In most cases, !! the root sought is the smallest in magnitude, though it might not be !! in some extremely rare situations. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaed6( kniter, orgati, rho, d, z, finit, tau, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: orgati integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kniter real(dp), intent(in) :: finit,rho,d(3),z(3) real(dp), intent(out) :: tau end subroutine dlaed6 #else module procedure stdlib${ii}$_dlaed6 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaed6( kniter, orgati, rho, d, z, finit, tau, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: orgati integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kniter real(sp), intent(in) :: finit,rho,d(3),z(3) real(sp), intent(out) :: tau end subroutine slaed6 #else module procedure stdlib${ii}$_slaed6 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laed6 #:endif #:endfor #:endfor end interface laed6 interface laed7 !! LAED7 computes the updated eigensystem of a diagonal !! matrix after modification by a rank-one symmetric matrix. This !! routine is used only for the eigenproblem which requires all !! eigenvalues and optionally eigenvectors of a dense or banded !! Hermitian matrix that has been reduced to tridiagonal form. !! T = Q(in) ( D(in) + RHO * Z*Z**H ) Q**H(in) = Q(out) * D(out) * Q**H(out) !! where Z = Q**Hu, u is a vector of length N with ones in the !! CUTPNT and CUTPNT + 1 th elements and zeros elsewhere. !! The eigenvectors of the original matrix are stored in Q, and the !! eigenvalues are in D. The algorithm consists of three stages: !! The first stage consists of deflating the size of the problem !! when there are multiple eigenvalues or if there is a zero in !! the Z vector. For each such occurrence the dimension of the !! secular equation problem is reduced by one. This stage is !! performed by the routine SLAED2. !! The second stage consists of calculating the updated !! eigenvalues. This is done by finding the roots of the secular !! equation via the routine SLAED4 (as called by SLAED3). !! This routine also calculates the eigenvectors of the current !! problem. !! The final stage consists of computing the updated eigenvectors !! directly using the updated eigenvalues. The eigenvectors for !! the current problem are multiplied with the eigenvectors from !! the overall problem. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claed7( n, cutpnt, qsiz, tlvls, curlvl, curpbm, d, q,ldq, rho, & indxq, qstore, qptr, prmptr, perm,givptr, givcol, givnum, work, rwork, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: curlvl,curpbm,cutpnt,ldq,n,qsiz,tlvls integer(${ik}$), intent(out) :: info,indxq(*),iwork(*) real(sp), intent(inout) :: rho,d(*),givnum(2,*),qstore(*) integer(${ik}$), intent(inout) :: givcol(2,*),givptr(*),perm(*),prmptr(*),qptr(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: q(ldq,*) complex(sp), intent(out) :: work(*) end subroutine claed7 #else module procedure stdlib${ii}$_claed7 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaed7( icompq, n, qsiz, tlvls, curlvl, curpbm, d, q,ldq, indxq, & rho, cutpnt, qstore, qptr, prmptr,perm, givptr, givcol, givnum, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: curlvl,curpbm,cutpnt,icompq,ldq,n,qsiz,& tlvls integer(${ik}$), intent(out) :: info,indxq(*),iwork(*) real(dp), intent(inout) :: rho,d(*),givnum(2,*),q(ldq,*),qstore(*) integer(${ik}$), intent(inout) :: givcol(2,*),givptr(*),perm(*),prmptr(*),qptr(*) real(dp), intent(out) :: work(*) end subroutine dlaed7 #else module procedure stdlib${ii}$_dlaed7 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaed7( icompq, n, qsiz, tlvls, curlvl, curpbm, d, q,ldq, indxq, & rho, cutpnt, qstore, qptr, prmptr,perm, givptr, givcol, givnum, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: curlvl,curpbm,cutpnt,icompq,ldq,n,qsiz,& tlvls integer(${ik}$), intent(out) :: info,indxq(*),iwork(*) real(sp), intent(inout) :: rho,d(*),givnum(2,*),q(ldq,*),qstore(*) integer(${ik}$), intent(inout) :: givcol(2,*),givptr(*),perm(*),prmptr(*),qptr(*) real(sp), intent(out) :: work(*) end subroutine slaed7 #else module procedure stdlib${ii}$_slaed7 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaed7( n, cutpnt, qsiz, tlvls, curlvl, curpbm, d, q,ldq, rho, & indxq, qstore, qptr, prmptr, perm,givptr, givcol, givnum, work, rwork, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: curlvl,curpbm,cutpnt,ldq,n,qsiz,tlvls integer(${ik}$), intent(out) :: info,indxq(*),iwork(*) real(dp), intent(inout) :: rho,d(*),givnum(2,*),qstore(*) integer(${ik}$), intent(inout) :: givcol(2,*),givptr(*),perm(*),prmptr(*),qptr(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: q(ldq,*) complex(dp), intent(out) :: work(*) end subroutine zlaed7 #else module procedure stdlib${ii}$_zlaed7 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laed7 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laed7 #:endif #:endfor #:endfor end interface laed7 interface laed8 !! LAED8 merges the two sets of eigenvalues together into a single !! sorted set. Then it tries to deflate the size of the problem. !! There are two ways in which deflation can occur: when two or more !! eigenvalues are close together or if there is a tiny element in the !! Z vector. For each such occurrence the order of the related secular !! equation problem is reduced by one. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claed8( k, n, qsiz, q, ldq, d, rho, cutpnt, z, dlamda,q2, ldq2, w, & indxp, indx, indxq, perm, givptr,givcol, givnum, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: cutpnt,ldq,ldq2,n,qsiz integer(${ik}$), intent(out) :: givptr,info,k,givcol(2,*),indx(*),indxp(*),perm(& *) real(sp), intent(inout) :: rho,d(*),z(*) integer(${ik}$), intent(inout) :: indxq(*) real(sp), intent(out) :: dlamda(*),givnum(2,*),w(*) complex(sp), intent(inout) :: q(ldq,*) complex(sp), intent(out) :: q2(ldq2,*) end subroutine claed8 #else module procedure stdlib${ii}$_claed8 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaed8( icompq, k, n, qsiz, d, q, ldq, indxq, rho,cutpnt, z, & dlamda, q2, ldq2, w, perm, givptr,givcol, givnum, indxp, indx, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: cutpnt,icompq,ldq,ldq2,n,qsiz integer(${ik}$), intent(out) :: givptr,info,k,givcol(2,*),indx(*),indxp(*),perm(& *) real(dp), intent(inout) :: rho,d(*),q(ldq,*),z(*) integer(${ik}$), intent(inout) :: indxq(*) real(dp), intent(out) :: dlamda(*),givnum(2,*),q2(ldq2,*),w(*) end subroutine dlaed8 #else module procedure stdlib${ii}$_dlaed8 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaed8( icompq, k, n, qsiz, d, q, ldq, indxq, rho,cutpnt, z, & dlamda, q2, ldq2, w, perm, givptr,givcol, givnum, indxp, indx, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: cutpnt,icompq,ldq,ldq2,n,qsiz integer(${ik}$), intent(out) :: givptr,info,k,givcol(2,*),indx(*),indxp(*),perm(& *) real(sp), intent(inout) :: rho,d(*),q(ldq,*),z(*) integer(${ik}$), intent(inout) :: indxq(*) real(sp), intent(out) :: dlamda(*),givnum(2,*),q2(ldq2,*),w(*) end subroutine slaed8 #else module procedure stdlib${ii}$_slaed8 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaed8( k, n, qsiz, q, ldq, d, rho, cutpnt, z, dlamda,q2, ldq2, w, & indxp, indx, indxq, perm, givptr,givcol, givnum, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: cutpnt,ldq,ldq2,n,qsiz integer(${ik}$), intent(out) :: givptr,info,k,givcol(2,*),indx(*),indxp(*),perm(& *) real(dp), intent(inout) :: rho,d(*),z(*) integer(${ik}$), intent(inout) :: indxq(*) real(dp), intent(out) :: dlamda(*),givnum(2,*),w(*) complex(dp), intent(inout) :: q(ldq,*) complex(dp), intent(out) :: q2(ldq2,*) end subroutine zlaed8 #else module procedure stdlib${ii}$_zlaed8 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laed8 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laed8 #:endif #:endfor #:endfor end interface laed8 interface laed9 !! LAED9 finds the roots of the secular equation, as defined by the !! values in D, Z, and RHO, between KSTART and KSTOP. It makes the !! appropriate calls to DLAED4 and then stores the new matrix of !! eigenvectors for use in calculating the next level of Z vectors. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaed9( k, kstart, kstop, n, d, q, ldq, rho, dlamda, w,s, lds, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,kstart,kstop,ldq,lds,n real(dp), intent(in) :: rho real(dp), intent(out) :: d(*),q(ldq,*),s(lds,*) real(dp), intent(inout) :: dlamda(*),w(*) end subroutine dlaed9 #else module procedure stdlib${ii}$_dlaed9 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaed9( k, kstart, kstop, n, d, q, ldq, rho, dlamda, w,s, lds, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,kstart,kstop,ldq,lds,n real(sp), intent(in) :: rho real(sp), intent(out) :: d(*),q(ldq,*),s(lds,*) real(sp), intent(inout) :: dlamda(*),w(*) end subroutine slaed9 #else module procedure stdlib${ii}$_slaed9 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laed9 #:endif #:endfor #:endfor end interface laed9 interface laeda !! LAEDA computes the Z vector corresponding to the merge step in the !! CURLVLth step of the merge process with TLVLS steps for the CURPBMth !! problem. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaeda( n, tlvls, curlvl, curpbm, prmptr, perm, givptr,givcol, & givnum, q, qptr, z, ztemp, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: curlvl,curpbm,n,tlvls,givcol(2,*),givptr(*),perm(& *),prmptr(*),qptr(*) integer(${ik}$), intent(out) :: info real(dp), intent(in) :: givnum(2,*),q(*) real(dp), intent(out) :: z(*),ztemp(*) end subroutine dlaeda #else module procedure stdlib${ii}$_dlaeda #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaeda( n, tlvls, curlvl, curpbm, prmptr, perm, givptr,givcol, & givnum, q, qptr, z, ztemp, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: curlvl,curpbm,n,tlvls,givcol(2,*),givptr(*),perm(& *),prmptr(*),qptr(*) integer(${ik}$), intent(out) :: info real(sp), intent(in) :: givnum(2,*),q(*) real(sp), intent(out) :: z(*),ztemp(*) end subroutine slaeda #else module procedure stdlib${ii}$_slaeda #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laeda #:endif #:endfor #:endfor end interface laeda interface laein !! LAEIN uses inverse iteration to find a right or left eigenvector !! corresponding to the eigenvalue W of a complex upper Hessenberg !! matrix H. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claein( rightv, noinit, n, h, ldh, w, v, b, ldb, rwork,eps3, & smlnum, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: noinit,rightv integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldh,n real(sp), intent(in) :: eps3,smlnum complex(sp), intent(in) :: w,h(ldh,*) real(sp), intent(out) :: rwork(*) complex(sp), intent(out) :: b(ldb,*) complex(sp), intent(inout) :: v(*) end subroutine claein #else module procedure stdlib${ii}$_claein #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaein( rightv, noinit, n, h, ldh, wr, wi, vr, vi, b,ldb, work, & eps3, smlnum, bignum, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: noinit,rightv integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldh,n real(dp), intent(in) :: bignum,eps3,smlnum,wi,wr,h(ldh,*) real(dp), intent(out) :: b(ldb,*),work(*) real(dp), intent(inout) :: vi(*),vr(*) end subroutine dlaein #else module procedure stdlib${ii}$_dlaein #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaein( rightv, noinit, n, h, ldh, wr, wi, vr, vi, b,ldb, work, & eps3, smlnum, bignum, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: noinit,rightv integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldh,n real(sp), intent(in) :: bignum,eps3,smlnum,wi,wr,h(ldh,*) real(sp), intent(out) :: b(ldb,*),work(*) real(sp), intent(inout) :: vi(*),vr(*) end subroutine slaein #else module procedure stdlib${ii}$_slaein #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaein( rightv, noinit, n, h, ldh, w, v, b, ldb, rwork,eps3, & smlnum, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: noinit,rightv integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldh,n real(dp), intent(in) :: eps3,smlnum complex(dp), intent(in) :: w,h(ldh,*) real(dp), intent(out) :: rwork(*) complex(dp), intent(out) :: b(ldb,*) complex(dp), intent(inout) :: v(*) end subroutine zlaein #else module procedure stdlib${ii}$_zlaein #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laein #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laein #:endif #:endfor #:endfor end interface laein interface laesy !! LAESY computes the eigendecomposition of a 2-by-2 symmetric matrix !! ( ( A, B );( B, C ) ) !! provided the norm of the matrix of eigenvectors is larger than !! some threshold value. !! RT1 is the eigenvalue of larger absolute value, and RT2 of !! smaller absolute value. If the eigenvectors are computed, then !! on return ( CS1, SN1 ) is the unit eigenvector for RT1, hence !! [ CS1 SN1 ] . [ A B ] . [ CS1 -SN1 ] = [ RT1 0 ] !! [ -SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ] #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claesy( a, b, c, rt1, rt2, evscal, cs1, sn1 ) import sp,dp,qp,${ik}$,lk implicit none complex(sp), intent(in) :: a,b,c complex(sp), intent(out) :: cs1,evscal,rt1,rt2,sn1 end subroutine claesy #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_claesy #:endif #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaesy( a, b, c, rt1, rt2, evscal, cs1, sn1 ) import sp,dp,qp,${ik}$,lk implicit none complex(dp), intent(in) :: a,b,c complex(dp), intent(out) :: cs1,evscal,rt1,rt2,sn1 end subroutine zlaesy #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_zlaesy #:endif #endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib_${ri}$laesy #:endif #:endfor end interface laesy interface laexc !! LAEXC swaps adjacent diagonal blocks T11 and T22 of order 1 or 2 in !! an upper quasi-triangular matrix T by an orthogonal similarity !! transformation. !! T must be in Schur canonical form, that is, block upper triangular !! with 1-by-1 and 2-by-2 diagonal blocks; each 2-by-2 diagonal block !! has its diagonal elements equal and its off-diagonal elements of !! opposite sign. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dlaexc( wantq, n, t, ldt, q, ldq, j1, n1, n2, work,info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantq integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: j1,ldq,ldt,n,n1,n2 real(dp), intent(inout) :: q(ldq,*),t(ldt,*) real(dp), intent(out) :: work(*) end subroutine dlaexc #else module procedure stdlib${ii}$_dlaexc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine slaexc( wantq, n, t, ldt, q, ldq, j1, n1, n2, work,info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantq integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: j1,ldq,ldt,n,n1,n2 real(sp), intent(inout) :: q(ldq,*),t(ldt,*) real(sp), intent(out) :: work(*) end subroutine slaexc #else module procedure stdlib${ii}$_slaexc #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laexc #:endif #:endfor #:endfor end interface laexc interface lagtf !! LAGTF factorizes the matrix (T - lambda*I), where T is an n by n !! tridiagonal matrix and lambda is a scalar, as !! T - lambda*I = PLU, !! where P is a permutation matrix, L is a unit lower tridiagonal matrix !! with at most one non-zero sub-diagonal elements per column and U is !! an upper triangular matrix with at most two non-zero super-diagonal !! elements per column. !! The factorization is obtained by Gaussian elimination with partial !! pivoting and implicit row scaling. !! The parameter LAMBDA is included in the routine so that LAGTF may !! be used, in conjunction with DLAGTS, to obtain eigenvectors of T by !! inverse iteration. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlagtf( n, a, lambda, b, c, tol, d, in, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,in(*) integer(${ik}$), intent(in) :: n real(dp), intent(in) :: lambda,tol real(dp), intent(inout) :: a(*),b(*),c(*) real(dp), intent(out) :: d(*) end subroutine dlagtf #else module procedure stdlib${ii}$_dlagtf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slagtf( n, a, lambda, b, c, tol, d, in, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,in(*) integer(${ik}$), intent(in) :: n real(sp), intent(in) :: lambda,tol real(sp), intent(inout) :: a(*),b(*),c(*) real(sp), intent(out) :: d(*) end subroutine slagtf #else module procedure stdlib${ii}$_slagtf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lagtf #:endif #:endfor #:endfor end interface lagtf interface lagtm !! LAGTM performs a matrix-vector product of the form !! B := alpha * A * X + beta * B !! where A is a tridiagonal matrix of order N, B and X are N by NRHS !! matrices, and alpha and beta are real scalars, each of which may be !! 0., 1., or -1. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clagtm( trans, n, nrhs, alpha, dl, d, du, x, ldx, beta,b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(sp), intent(in) :: alpha,beta complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(in) :: d(*),dl(*),du(*),x(ldx,*) end subroutine clagtm #else module procedure stdlib${ii}$_clagtm #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlagtm( trans, n, nrhs, alpha, dl, d, du, x, ldx, beta,b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(dp), intent(in) :: alpha,beta,d(*),dl(*),du(*),x(ldx,*) real(dp), intent(inout) :: b(ldb,*) end subroutine dlagtm #else module procedure stdlib${ii}$_dlagtm #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slagtm( trans, n, nrhs, alpha, dl, d, du, x, ldx, beta,b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(sp), intent(in) :: alpha,beta,d(*),dl(*),du(*),x(ldx,*) real(sp), intent(inout) :: b(ldb,*) end subroutine slagtm #else module procedure stdlib${ii}$_slagtm #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlagtm( trans, n, nrhs, alpha, dl, d, du, x, ldx, beta,b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(dp), intent(in) :: alpha,beta complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(in) :: d(*),dl(*),du(*),x(ldx,*) end subroutine zlagtm #else module procedure stdlib${ii}$_zlagtm #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lagtm #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lagtm #:endif #:endfor #:endfor end interface lagtm interface lagts !! LAGTS may be used to solve one of the systems of equations !! (T - lambda*I)*x = y or (T - lambda*I)**T*x = y, !! where T is an n by n tridiagonal matrix, for x, following the !! factorization of (T - lambda*I) as !! (T - lambda*I) = P*L*U , !! by routine DLAGTF. The choice of equation to be solved is !! controlled by the argument JOB, and in each case there is an option !! to perturb zero or very small diagonal elements of U, this option !! being intended for use in applications such as inverse iteration. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlagts( job, n, a, b, c, d, in, y, tol, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: job,n,in(*) real(dp), intent(inout) :: tol,y(*) real(dp), intent(in) :: a(*),b(*),c(*),d(*) end subroutine dlagts #else module procedure stdlib${ii}$_dlagts #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slagts( job, n, a, b, c, d, in, y, tol, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: job,n,in(*) real(sp), intent(inout) :: tol,y(*) real(sp), intent(in) :: a(*),b(*),c(*),d(*) end subroutine slagts #else module procedure stdlib${ii}$_slagts #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lagts #:endif #:endfor #:endfor end interface lagts interface lahef !! LAHEF computes a partial factorization of a complex Hermitian !! matrix A using the Bunch-Kaufman diagonal pivoting method. The !! partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**H U22**H ) !! A = ( L11 0 ) ( D 0 ) ( L11**H L21**H ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**H denotes the conjugate transpose of U. !! LAHEF is an auxiliary routine called by CHETRF. It uses blocked code !! (calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or !! A22 (if UPLO = 'L'). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clahef( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: w(ldw,*) end subroutine clahef #else module procedure stdlib${ii}$_clahef #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlahef( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: w(ldw,*) end subroutine zlahef #else module procedure stdlib${ii}$_zlahef #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lahef #:endif #:endfor #:endfor end interface lahef interface lahef_aa !! LAHEF_AA factorizes a panel of a complex hermitian matrix A using !! the Aasen's algorithm. The panel consists of a set of NB rows of A !! when UPLO is U, or a set of NB columns when UPLO is L. !! In order to factorize the panel, the Aasen's algorithm requires the !! last row, or column, of the previous panel. The first row, or column, !! of A is set to be the first row, or column, of an identity matrix, !! which is used to factorize the first panel. !! The resulting J-th row of U, or J-th column of L, is stored in the !! (J-1)-th row, or column, of A (without the unit diagonals), while !! the diagonal and subdiagonal of A are overwritten by those of T. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clahef_aa( uplo, j1, m, nb, a, lda, ipiv,h, ldh, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: m,nb,j1,lda,ldh integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*),h(ldh,*) complex(sp), intent(out) :: work(*) end subroutine clahef_aa #else module procedure stdlib${ii}$_clahef_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlahef_aa( uplo, j1, m, nb, a, lda, ipiv,h, ldh, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: m,nb,j1,lda,ldh integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*),h(ldh,*) complex(dp), intent(out) :: work(*) end subroutine zlahef_aa #else module procedure stdlib${ii}$_zlahef_aa #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lahef_aa #:endif #:endfor #:endfor end interface lahef_aa interface lahef_rk !! LAHEF_RK computes a partial factorization of a complex Hermitian !! matrix A using the bounded Bunch-Kaufman (rook) diagonal !! pivoting method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**H U22**H ) !! A = ( L11 0 ) ( D 0 ) ( L11**H L21**H ) if UPLO = 'L', !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! LAHEF_RK is an auxiliary routine called by CHETRF_RK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clahef_rk( uplo, n, nb, kb, a, lda, e, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: w(ldw,*),e(*) end subroutine clahef_rk #else module procedure stdlib${ii}$_clahef_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlahef_rk( uplo, n, nb, kb, a, lda, e, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: w(ldw,*),e(*) end subroutine zlahef_rk #else module procedure stdlib${ii}$_zlahef_rk #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lahef_rk #:endif #:endfor #:endfor end interface lahef_rk interface lahef_rook !! LAHEF_ROOK computes a partial factorization of a complex Hermitian !! matrix A using the bounded Bunch-Kaufman ("rook") diagonal pivoting !! method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**H U22**H ) !! A = ( L11 0 ) ( D 0 ) ( L11**H L21**H ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**H denotes the conjugate transpose of U. !! LAHEF_ROOK is an auxiliary routine called by CHETRF_ROOK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clahef_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: w(ldw,*) end subroutine clahef_rook #else module procedure stdlib${ii}$_clahef_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlahef_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: w(ldw,*) end subroutine zlahef_rook #else module procedure stdlib${ii}$_zlahef_rook #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lahef_rook #:endif #:endfor #:endfor end interface lahef_rook interface lahqr !! LAHQR is an auxiliary routine called by CHSEQR to update the !! eigenvalues and Schur decomposition already computed by CHSEQR, by !! dealing with the Hessenberg submatrix in rows and columns ILO to !! IHI. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz complex(sp), intent(inout) :: h(ldh,*),z(ldz,*) complex(sp), intent(out) :: w(*) end subroutine clahqr #else module procedure stdlib${ii}$_clahqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, & ldz, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz real(dp), intent(inout) :: h(ldh,*),z(ldz,*) real(dp), intent(out) :: wi(*),wr(*) end subroutine dlahqr #else module procedure stdlib${ii}$_dlahqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, & ldz, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz real(sp), intent(inout) :: h(ldh,*),z(ldz,*) real(sp), intent(out) :: wi(*),wr(*) end subroutine slahqr #else module procedure stdlib${ii}$_slahqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz complex(dp), intent(inout) :: h(ldh,*),z(ldz,*) complex(dp), intent(out) :: w(*) end subroutine zlahqr #else module procedure stdlib${ii}$_zlahqr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lahqr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lahqr #:endif #:endfor #:endfor end interface lahqr interface laic1 !! LAIC1 applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then LAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**H gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**H and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ conjg(alpha) ] !! [ conjg(gamma) ] !! where alpha = x**H*w. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claic1( job, j, x, sest, w, gamma, sestpr, s, c ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: j,job real(sp), intent(in) :: sest real(sp), intent(out) :: sestpr complex(sp), intent(out) :: c,s complex(sp), intent(in) :: gamma,w(j),x(j) end subroutine claic1 #else module procedure stdlib${ii}$_claic1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaic1( job, j, x, sest, w, gamma, sestpr, s, c ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: j,job real(dp), intent(out) :: c,s,sestpr real(dp), intent(in) :: gamma,sest,w(j),x(j) end subroutine dlaic1 #else module procedure stdlib${ii}$_dlaic1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaic1( job, j, x, sest, w, gamma, sestpr, s, c ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: j,job real(sp), intent(out) :: c,s,sestpr real(sp), intent(in) :: gamma,sest,w(j),x(j) end subroutine slaic1 #else module procedure stdlib${ii}$_slaic1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaic1( job, j, x, sest, w, gamma, sestpr, s, c ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: j,job real(dp), intent(in) :: sest real(dp), intent(out) :: sestpr complex(dp), intent(out) :: c,s complex(dp), intent(in) :: gamma,w(j),x(j) end subroutine zlaic1 #else module procedure stdlib${ii}$_zlaic1 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laic1 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laic1 #:endif #:endfor #:endfor end interface laic1 interface laisnan !! This routine is not for general use. It exists solely to avoid !! over-optimization in DISNAN. !! LAISNAN checks for NaNs by comparing its two arguments for !! inequality. NaN is the only floating-point value where NaN != NaN !! returns .TRUE. To check for NaNs, pass the same variable as both !! arguments. !! A compiler must assume that the two arguments are !! not the same variable, and the test will not be optimized away. !! Interprocedural or whole-program optimization may delete this !! test. The ISNAN functions will be replaced by the correct !! Fortran 03 intrinsic once the intrinsic is widely available. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure logical(lk) function dlaisnan( din1, din2 ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: din1,din2 end function dlaisnan #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_dlaisnan #:endif #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure logical(lk) function slaisnan( sin1, sin2 ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: sin1,sin2 end function slaisnan #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_slaisnan #:endif #endif #:endfor #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib_${ri}$laisnan #:endif #:endfor end interface laisnan interface lals0 !! LALS0 applies back the multiplying factors of either the left or the !! right singular vector matrix of a diagonal matrix appended by a row !! to the right hand side matrix B in solving the least squares problem !! using the divide-and-conquer SVD approach. !! For the left singular vector matrix, three types of orthogonal !! matrices are involved: !! (1L) Givens rotations: the number of such rotations is GIVPTR; the !! pairs of columns/rows they were applied to are stored in GIVCOL; !! and the C- and S-values of these rotations are stored in GIVNUM. !! (2L) Permutation. The (NL+1)-st row of B is to be moved to the first !! row, and for J=2:N, PERM(J)-th row of B is to be moved to the !! J-th row. !! (3L) The left singular vector matrix of the remaining matrix. !! For the right singular vector matrix, four types of orthogonal !! matrices are involved: !! (1R) The right singular vector matrix of the remaining matrix. !! (2R) If SQRE = 1, one extra Givens rotation to generate the right !! null space. !! (3R) The inverse transformation of (2L). !! (4R) The inverse transformation of (1L). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clals0( icompq, nl, nr, sqre, nrhs, b, ldb, bx, ldbx,perm, givptr, & givcol, ldgcol, givnum, ldgnum,poles, difl, difr, z, k, c, s, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: givptr,icompq,k,ldb,ldbx,ldgcol,ldgnum,nl,nr,nrhs,& sqre,givcol(ldgcol,*),perm(*) integer(${ik}$), intent(out) :: info real(sp), intent(in) :: c,s,difl(*),difr(ldgnum,*),givnum(ldgnum,*),poles(& ldgnum,*),z(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(out) :: bx(ldbx,*) end subroutine clals0 #else module procedure stdlib${ii}$_clals0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlals0( icompq, nl, nr, sqre, nrhs, b, ldb, bx, ldbx,perm, givptr, & givcol, ldgcol, givnum, ldgnum,poles, difl, difr, z, k, c, s, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: givptr,icompq,k,ldb,ldbx,ldgcol,ldgnum,nl,nr,nrhs,& sqre,givcol(ldgcol,*),perm(*) integer(${ik}$), intent(out) :: info real(dp), intent(in) :: c,s,difl(*),difr(ldgnum,*),givnum(ldgnum,*),poles(& ldgnum,*),z(*) real(dp), intent(inout) :: b(ldb,*) real(dp), intent(out) :: bx(ldbx,*),work(*) end subroutine dlals0 #else module procedure stdlib${ii}$_dlals0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slals0( icompq, nl, nr, sqre, nrhs, b, ldb, bx, ldbx,perm, givptr, & givcol, ldgcol, givnum, ldgnum,poles, difl, difr, z, k, c, s, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: givptr,icompq,k,ldb,ldbx,ldgcol,ldgnum,nl,nr,nrhs,& sqre,givcol(ldgcol,*),perm(*) integer(${ik}$), intent(out) :: info real(sp), intent(in) :: c,s,difl(*),difr(ldgnum,*),givnum(ldgnum,*),poles(& ldgnum,*),z(*) real(sp), intent(inout) :: b(ldb,*) real(sp), intent(out) :: bx(ldbx,*),work(*) end subroutine slals0 #else module procedure stdlib${ii}$_slals0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlals0( icompq, nl, nr, sqre, nrhs, b, ldb, bx, ldbx,perm, givptr, & givcol, ldgcol, givnum, ldgnum,poles, difl, difr, z, k, c, s, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: givptr,icompq,k,ldb,ldbx,ldgcol,ldgnum,nl,nr,nrhs,& sqre,givcol(ldgcol,*),perm(*) integer(${ik}$), intent(out) :: info real(dp), intent(in) :: c,s,difl(*),difr(ldgnum,*),givnum(ldgnum,*),poles(& ldgnum,*),z(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(out) :: bx(ldbx,*) end subroutine zlals0 #else module procedure stdlib${ii}$_zlals0 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lals0 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lals0 #:endif #:endfor #:endfor end interface lals0 interface lalsa !! LALSA is an itermediate step in solving the least squares problem !! by computing the SVD of the coefficient matrix in compact form (The !! singular vectors are computed as products of simple orthorgonal !! matrices.). !! If ICOMPQ = 0, LALSA applies the inverse of the left singular vector !! matrix of an upper bidiagonal matrix to the right hand side; and if !! ICOMPQ = 1, LALSA applies the right singular vector matrix to the !! right hand side. The singular vector matrices were generated in !! compact form by LALSA. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clalsa( icompq, smlsiz, n, nrhs, b, ldb, bx, ldbx, u,ldu, vt, k, & difl, difr, z, poles, givptr,givcol, ldgcol, perm, givnum, c, s, rwork,iwork, info & ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: icompq,ldb,ldbx,ldgcol,ldu,n,nrhs,smlsiz,givcol(& ldgcol,*),givptr(*),k(*),perm(ldgcol,*) integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(in) :: c(*),difl(ldu,*),difr(ldu,*),givnum(ldu,*),poles(ldu,& *),s(*),u(ldu,*),vt(ldu,*),z(ldu,*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(out) :: bx(ldbx,*) end subroutine clalsa #else module procedure stdlib${ii}$_clalsa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlalsa( icompq, smlsiz, n, nrhs, b, ldb, bx, ldbx, u,ldu, vt, k, & difl, difr, z, poles, givptr,givcol, ldgcol, perm, givnum, c, s, work,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: icompq,ldb,ldbx,ldgcol,ldu,n,nrhs,smlsiz,givcol(& ldgcol,*),givptr(*),k(*),perm(ldgcol,*) integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(inout) :: b(ldb,*) real(dp), intent(out) :: bx(ldbx,*),work(*) real(dp), intent(in) :: c(*),difl(ldu,*),difr(ldu,*),givnum(ldu,*),poles(ldu,& *),s(*),u(ldu,*),vt(ldu,*),z(ldu,*) end subroutine dlalsa #else module procedure stdlib${ii}$_dlalsa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slalsa( icompq, smlsiz, n, nrhs, b, ldb, bx, ldbx, u,ldu, vt, k, & difl, difr, z, poles, givptr,givcol, ldgcol, perm, givnum, c, s, work,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: icompq,ldb,ldbx,ldgcol,ldu,n,nrhs,smlsiz,givcol(& ldgcol,*),givptr(*),k(*),perm(ldgcol,*) integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(inout) :: b(ldb,*) real(sp), intent(out) :: bx(ldbx,*),work(*) real(sp), intent(in) :: c(*),difl(ldu,*),difr(ldu,*),givnum(ldu,*),poles(ldu,& *),s(*),u(ldu,*),vt(ldu,*),z(ldu,*) end subroutine slalsa #else module procedure stdlib${ii}$_slalsa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlalsa( icompq, smlsiz, n, nrhs, b, ldb, bx, ldbx, u,ldu, vt, k, & difl, difr, z, poles, givptr,givcol, ldgcol, perm, givnum, c, s, rwork,iwork, info & ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: icompq,ldb,ldbx,ldgcol,ldu,n,nrhs,smlsiz,givcol(& ldgcol,*),givptr(*),k(*),perm(ldgcol,*) integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(in) :: c(*),difl(ldu,*),difr(ldu,*),givnum(ldu,*),poles(ldu,& *),s(*),u(ldu,*),vt(ldu,*),z(ldu,*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(out) :: bx(ldbx,*) end subroutine zlalsa #else module procedure stdlib${ii}$_zlalsa #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lalsa #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lalsa #:endif #:endfor #:endfor end interface lalsa interface lalsd !! LALSD uses the singular value decomposition of A to solve the least !! squares problem of finding X to minimize the Euclidean norm of each !! column of A*X-B, where A is N-by-N upper bidiagonal, and X and B !! are N-by-NRHS. The solution X overwrites B. !! The singular values of A smaller than RCOND times the largest !! singular value are treated as zero in solving the least squares !! problem; in this case a minimum norm solution is returned. !! The actual singular values are returned in D in ascending order. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clalsd( uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond,rank, work, & rwork, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,rank,iwork(*) integer(${ik}$), intent(in) :: ldb,n,nrhs,smlsiz real(sp), intent(in) :: rcond real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine clalsd #else module procedure stdlib${ii}$_clalsd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlalsd( uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond,rank, work, & iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,rank,iwork(*) integer(${ik}$), intent(in) :: ldb,n,nrhs,smlsiz real(dp), intent(in) :: rcond real(dp), intent(inout) :: b(ldb,*),d(*),e(*) real(dp), intent(out) :: work(*) end subroutine dlalsd #else module procedure stdlib${ii}$_dlalsd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slalsd( uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond,rank, work, & iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,rank,iwork(*) integer(${ik}$), intent(in) :: ldb,n,nrhs,smlsiz real(sp), intent(in) :: rcond real(sp), intent(inout) :: b(ldb,*),d(*),e(*) real(sp), intent(out) :: work(*) end subroutine slalsd #else module procedure stdlib${ii}$_slalsd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlalsd( uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond,rank, work, & rwork, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,rank,iwork(*) integer(${ik}$), intent(in) :: ldb,n,nrhs,smlsiz real(dp), intent(in) :: rcond real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zlalsd #else module procedure stdlib${ii}$_zlalsd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lalsd #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lalsd #:endif #:endfor #:endfor end interface lalsd interface lamrg !! LAMRG will create a permutation list which will merge the elements !! of A (which is composed of two independently sorted sets) into a !! single set which is sorted in ascending order. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlamrg( n1, n2, a, dtrd1, dtrd2, index ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: dtrd1,dtrd2,n1,n2 integer(${ik}$), intent(out) :: index(*) real(dp), intent(in) :: a(*) end subroutine dlamrg #else module procedure stdlib${ii}$_dlamrg #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slamrg( n1, n2, a, strd1, strd2, index ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n1,n2,strd1,strd2 integer(${ik}$), intent(out) :: index(*) real(sp), intent(in) :: a(*) end subroutine slamrg #else module procedure stdlib${ii}$_slamrg #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lamrg #:endif #:endfor #:endfor end interface lamrg interface lamswlq !! LAMSWLQ overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of blocked !! elementary reflectors computed by short wide LQ !! factorization (CLASWLQ) #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,mb,nb,ldt,lwork,ldc complex(sp), intent(in) :: a(lda,*),t(ldt,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: c(ldc,*) end subroutine clamswlq #else module procedure stdlib${ii}$_clamswlq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,mb,nb,ldt,lwork,ldc real(dp), intent(in) :: a(lda,*),t(ldt,*) real(dp), intent(out) :: work(*) real(dp), intent(inout) :: c(ldc,*) end subroutine dlamswlq #else module procedure stdlib${ii}$_dlamswlq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,mb,nb,ldt,lwork,ldc real(sp), intent(in) :: a(lda,*),t(ldt,*) real(sp), intent(out) :: work(*) real(sp), intent(inout) :: c(ldc,*) end subroutine slamswlq #else module procedure stdlib${ii}$_slamswlq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,mb,nb,ldt,lwork,ldc complex(dp), intent(in) :: a(lda,*),t(ldt,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: c(ldc,*) end subroutine zlamswlq #else module procedure stdlib${ii}$_zlamswlq #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lamswlq #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lamswlq #:endif #:endfor #:endfor end interface lamswlq interface lamtsqr !! LAMTSQR overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product !! of blocked elementary reflectors computed by tall skinny !! QR factorization (CLATSQR) #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clamtsqr( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,mb,nb,ldt,lwork,ldc complex(sp), intent(in) :: a(lda,*),t(ldt,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: c(ldc,*) end subroutine clamtsqr #else module procedure stdlib${ii}$_clamtsqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlamtsqr( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,mb,nb,ldt,lwork,ldc real(dp), intent(in) :: a(lda,*),t(ldt,*) real(dp), intent(out) :: work(*) real(dp), intent(inout) :: c(ldc,*) end subroutine dlamtsqr #else module procedure stdlib${ii}$_dlamtsqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slamtsqr( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,mb,nb,ldt,lwork,ldc real(sp), intent(in) :: a(lda,*),t(ldt,*) real(sp), intent(out) :: work(*) real(sp), intent(inout) :: c(ldc,*) end subroutine slamtsqr #else module procedure stdlib${ii}$_slamtsqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlamtsqr( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,k,mb,nb,ldt,lwork,ldc complex(dp), intent(in) :: a(lda,*),t(ldt,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: c(ldc,*) end subroutine zlamtsqr #else module procedure stdlib${ii}$_zlamtsqr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lamtsqr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lamtsqr #:endif #:endfor #:endfor end interface lamtsqr interface laneg !! LANEG computes the Sturm count, the number of negative pivots !! encountered while factoring tridiagonal T - sigma I = L D L^T. !! This implementation works directly on the factors without forming !! the tridiagonal matrix T. The Sturm count is also the number of !! eigenvalues of T less than sigma. !! This routine is called from DLARRB. !! The current routine does not use the PIVMIN parameter but rather !! requires IEEE-754 propagation of Infinities and NaNs. This !! routine also has no input range restrictions but does require !! default exception handling such that x/0 produces Inf when x is !! non-zero, and Inf/Inf produces NaN. For more information, see: !! Marques, Riedy, and Voemel, "Benefits of IEEE-754 Features in !! Modern Symmetric Tridiagonal Eigensolvers," SIAM Journal on !! Scientific Computing, v28, n5, 2006. DOI 10.1137/050641624 !! (Tech report version in LAWN 172 with the same title.) #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure integer(${ik}$) function dlaneg( n, d, lld, sigma, pivmin, r ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,r real(dp), intent(in) :: pivmin,sigma,d(*),lld(*) end function dlaneg #else module procedure stdlib${ii}$_dlaneg #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure integer(${ik}$) function slaneg( n, d, lld, sigma, pivmin, r ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n,r real(sp), intent(in) :: pivmin,sigma,d(*),lld(*) end function slaneg #else module procedure stdlib${ii}$_slaneg #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laneg #:endif #:endfor #:endfor end interface laneg interface langb !! LANGB returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n band matrix A, with kl sub-diagonals and ku super-diagonals. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clangb( norm, n, kl, ku, ab, ldab,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: kl,ku,ldab,n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ab(ldab,*) end function clangb #else module procedure stdlib${ii}$_clangb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dlangb( norm, n, kl, ku, ab, ldab,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: kl,ku,ldab,n real(dp), intent(in) :: ab(ldab,*) real(dp), intent(out) :: work(*) end function dlangb #else module procedure stdlib${ii}$_dlangb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function slangb( norm, n, kl, ku, ab, ldab,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: kl,ku,ldab,n real(sp), intent(in) :: ab(ldab,*) real(sp), intent(out) :: work(*) end function slangb #else module procedure stdlib${ii}$_slangb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlangb( norm, n, kl, ku, ab, ldab,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: kl,ku,ldab,n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ab(ldab,*) end function zlangb #else module procedure stdlib${ii}$_zlangb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$langb #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$langb #:endif #:endfor #:endfor end interface langb interface lange !! LANGE returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clange( norm, m, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) end function clange #else module procedure stdlib${ii}$_clange #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dlange( norm, m, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) end function dlange #else module procedure stdlib${ii}$_dlange #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function slange( norm, m, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) end function slange #else module procedure stdlib${ii}$_slange #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlange( norm, m, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) end function zlange #else module procedure stdlib${ii}$_zlange #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lange #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lange #:endif #:endfor #:endfor end interface lange interface langt !! LANGT returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex tridiagonal matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(sp) function clangt( norm, n, dl, d, du ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: n complex(sp), intent(in) :: d(*),dl(*),du(*) end function clangt #else module procedure stdlib${ii}$_clangt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(dp) function dlangt( norm, n, dl, d, du ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(dp), intent(in) :: d(*),dl(*),du(*) end function dlangt #else module procedure stdlib${ii}$_dlangt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(sp) function slangt( norm, n, dl, d, du ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(sp), intent(in) :: d(*),dl(*),du(*) end function slangt #else module procedure stdlib${ii}$_slangt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(dp) function zlangt( norm, n, dl, d, du ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: n complex(dp), intent(in) :: d(*),dl(*),du(*) end function zlangt #else module procedure stdlib${ii}$_zlangt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$langt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$langt #:endif #:endfor #:endfor end interface langt interface lanhb !! LANHB returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n hermitian band matrix A, with k super-diagonals. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clanhb( norm, uplo, n, k, ab, ldab,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: k,ldab,n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ab(ldab,*) end function clanhb #else module procedure stdlib${ii}$_clanhb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlanhb( norm, uplo, n, k, ab, ldab,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: k,ldab,n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ab(ldab,*) end function zlanhb #else module procedure stdlib${ii}$_zlanhb #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lanhb #:endif #:endfor #:endfor end interface lanhb interface lanhe !! LANHE returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex hermitian matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clanhe( norm, uplo, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) end function clanhe #else module procedure stdlib${ii}$_clanhe #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlanhe( norm, uplo, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) end function zlanhe #else module procedure stdlib${ii}$_zlanhe #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lanhe #:endif #:endfor #:endfor end interface lanhe interface lanhf !! LANHF returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex Hermitian matrix A in RFP format. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clanhf( norm, transr, uplo, n, a, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,transr,uplo integer(${ik}$), intent(in) :: n real(sp), intent(out) :: work(0:*) complex(sp), intent(in) :: a(0:*) end function clanhf #else module procedure stdlib${ii}$_clanhf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlanhf( norm, transr, uplo, n, a, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,transr,uplo integer(${ik}$), intent(in) :: n real(dp), intent(out) :: work(0:*) complex(dp), intent(in) :: a(0:*) end function zlanhf #else module procedure stdlib${ii}$_zlanhf #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lanhf #:endif #:endfor #:endfor end interface lanhf interface lanhp !! LANHP returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex hermitian matrix A, supplied in packed form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clanhp( norm, uplo, n, ap, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ap(*) end function clanhp #else module procedure stdlib${ii}$_clanhp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlanhp( norm, uplo, n, ap, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ap(*) end function zlanhp #else module procedure stdlib${ii}$_zlanhp #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lanhp #:endif #:endfor #:endfor end interface lanhp interface lanhs !! LANHS returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! Hessenberg matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clanhs( norm, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) end function clanhs #else module procedure stdlib${ii}$_clanhs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dlanhs( norm, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: lda,n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) end function dlanhs #else module procedure stdlib${ii}$_dlanhs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function slanhs( norm, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: lda,n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) end function slanhs #else module procedure stdlib${ii}$_slanhs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlanhs( norm, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) end function zlanhs #else module procedure stdlib${ii}$_zlanhs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lanhs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lanhs #:endif #:endfor #:endfor end interface lanhs interface lanht !! LANHT returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex Hermitian tridiagonal matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(sp) function clanht( norm, n, d, e ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(sp), intent(in) :: d(*) complex(sp), intent(in) :: e(*) end function clanht #else module procedure stdlib${ii}$_clanht #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(dp) function zlanht( norm, n, d, e ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(dp), intent(in) :: d(*) complex(dp), intent(in) :: e(*) end function zlanht #else module procedure stdlib${ii}$_zlanht #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lanht #:endif #:endfor #:endfor end interface lanht interface lansb !! LANSB returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n symmetric band matrix A, with k super-diagonals. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clansb( norm, uplo, n, k, ab, ldab,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: k,ldab,n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ab(ldab,*) end function clansb #else module procedure stdlib${ii}$_clansb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dlansb( norm, uplo, n, k, ab, ldab,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: k,ldab,n real(dp), intent(in) :: ab(ldab,*) real(dp), intent(out) :: work(*) end function dlansb #else module procedure stdlib${ii}$_dlansb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function slansb( norm, uplo, n, k, ab, ldab,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: k,ldab,n real(sp), intent(in) :: ab(ldab,*) real(sp), intent(out) :: work(*) end function slansb #else module procedure stdlib${ii}$_slansb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlansb( norm, uplo, n, k, ab, ldab,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: k,ldab,n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ab(ldab,*) end function zlansb #else module procedure stdlib${ii}$_zlansb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lansb #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lansb #:endif #:endfor #:endfor end interface lansb interface lansf !! LANSF returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real symmetric matrix A in RFP format. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dlansf( norm, transr, uplo, n, a, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,transr,uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: a(0:*) real(dp), intent(out) :: work(0:*) end function dlansf #else module procedure stdlib${ii}$_dlansf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function slansf( norm, transr, uplo, n, a, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,transr,uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: a(0:*) real(sp), intent(out) :: work(0:*) end function slansf #else module procedure stdlib${ii}$_slansf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lansf #:endif #:endfor #:endfor end interface lansf interface lansp !! LANSP returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex symmetric matrix A, supplied in packed form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clansp( norm, uplo, n, ap, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ap(*) end function clansp #else module procedure stdlib${ii}$_clansp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dlansp( norm, uplo, n, ap, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: ap(*) real(dp), intent(out) :: work(*) end function dlansp #else module procedure stdlib${ii}$_dlansp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function slansp( norm, uplo, n, ap, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: ap(*) real(sp), intent(out) :: work(*) end function slansp #else module procedure stdlib${ii}$_slansp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlansp( norm, uplo, n, ap, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ap(*) end function zlansp #else module procedure stdlib${ii}$_zlansp #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lansp #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lansp #:endif #:endfor #:endfor end interface lansp interface lanst !! LANST returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real symmetric tridiagonal matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(dp) function dlanst( norm, n, d, e ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(dp), intent(in) :: d(*),e(*) end function dlanst #else module procedure stdlib${ii}$_dlanst #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure real(sp) function slanst( norm, n, d, e ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(sp), intent(in) :: d(*),e(*) end function slanst #else module procedure stdlib${ii}$_slanst #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lanst #:endif #:endfor #:endfor end interface lanst interface lansy !! LANSY returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex symmetric matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clansy( norm, uplo, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) end function clansy #else module procedure stdlib${ii}$_clansy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dlansy( norm, uplo, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: lda,n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) end function dlansy #else module procedure stdlib${ii}$_dlansy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function slansy( norm, uplo, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: lda,n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) end function slansy #else module procedure stdlib${ii}$_slansy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlansy( norm, uplo, n, a, lda, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: norm,uplo integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) end function zlansy #else module procedure stdlib${ii}$_zlansy #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lansy #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lansy #:endif #:endfor #:endfor end interface lansy interface lantb !! LANTB returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n triangular band matrix A, with ( k + 1 ) diagonals. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clantb( norm, uplo, diag, n, k, ab,ldab, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: k,ldab,n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ab(ldab,*) end function clantb #else module procedure stdlib${ii}$_clantb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dlantb( norm, uplo, diag, n, k, ab,ldab, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: k,ldab,n real(dp), intent(in) :: ab(ldab,*) real(dp), intent(out) :: work(*) end function dlantb #else module procedure stdlib${ii}$_dlantb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function slantb( norm, uplo, diag, n, k, ab,ldab, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: k,ldab,n real(sp), intent(in) :: ab(ldab,*) real(sp), intent(out) :: work(*) end function slantb #else module procedure stdlib${ii}$_slantb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlantb( norm, uplo, diag, n, k, ab,ldab, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: k,ldab,n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ab(ldab,*) end function zlantb #else module procedure stdlib${ii}$_zlantb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lantb #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lantb #:endif #:endfor #:endfor end interface lantb interface lantp !! LANTP returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! triangular matrix A, supplied in packed form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clantp( norm, uplo, diag, n, ap, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ap(*) end function clantp #else module procedure stdlib${ii}$_clantp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dlantp( norm, uplo, diag, n, ap, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: ap(*) real(dp), intent(out) :: work(*) end function dlantp #else module procedure stdlib${ii}$_dlantp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function slantp( norm, uplo, diag, n, ap, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: ap(*) real(sp), intent(out) :: work(*) end function slantp #else module procedure stdlib${ii}$_slantp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlantp( norm, uplo, diag, n, ap, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ap(*) end function zlantp #else module procedure stdlib${ii}$_zlantp #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lantp #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lantp #:endif #:endfor #:endfor end interface lantp interface lantr !! LANTR returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! trapezoidal or triangular matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function clantr( norm, uplo, diag, m, n, a, lda,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) end function clantr #else module procedure stdlib${ii}$_clantr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function dlantr( norm, uplo, diag, m, n, a, lda,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) end function dlantr #else module procedure stdlib${ii}$_dlantr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(sp) function slantr( norm, uplo, diag, m, n, a, lda,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) end function slantr #else module procedure stdlib${ii}$_slantr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ real(dp) function zlantr( norm, uplo, diag, m, n, a, lda,work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) end function zlantr #else module procedure stdlib${ii}$_zlantr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lantr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lantr #:endif #:endfor #:endfor end interface lantr interface laorhr_col_getrfnp !! LAORHR_COL_GETRFNP computes the modified LU factorization without !! pivoting of a real general M-by-N matrix A. The factorization has !! the form: !! A - S = L * U, !! where: !! S is a m-by-n diagonal sign matrix with the diagonal D, so that !! D(i) = S(i,i), 1 <= i <= min(M,N). The diagonal D is constructed !! as D(i)=-SIGN(A(i,i)), where A(i,i) is the value after performing !! i-1 steps of Gaussian elimination. This means that the diagonal !! element at each step of "modified" Gaussian elimination is !! at least one in absolute value (so that division-by-zero not !! not possible during the division by the diagonal element); !! L is a M-by-N lower triangular matrix with unit diagonal elements !! (lower trapezoidal if M > N); !! and U is a M-by-N upper triangular matrix !! (upper trapezoidal if M < N). !! This routine is an auxiliary routine used in the Householder !! reconstruction routine DORHR_COL. In DORHR_COL, this routine is !! applied to an M-by-N matrix A with orthonormal columns, where each !! element is bounded by one in absolute value. With the choice of !! the matrix S above, one can show that the diagonal element at each !! step of Gaussian elimination is the largest (in absolute value) in !! the column on or below the diagonal, so that no pivoting is required !! for numerical stability [1]. !! For more details on the Householder reconstruction algorithm, !! including the modified LU factorization, see [1]. !! This is the blocked right-looking version of the algorithm, !! calling Level 3 BLAS to update the submatrix. To factorize a block, !! this routine calls the recursive routine LAORHR_COL_GETRFNP2. !! [1] "Reconstructing Householder vectors from tall-skinny QR", !! G. Ballard, J. Demmel, L. Grigori, M. Jacquelin, H.D. Nguyen, !! E. Solomonik, J. Parallel Distrib. Comput., !! vol. 85, pp. 3-31, 2015. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaorhr_col_getrfnp( m, n, a, lda, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*) end subroutine dlaorhr_col_getrfnp #else module procedure stdlib${ii}$_dlaorhr_col_getrfnp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaorhr_col_getrfnp( m, n, a, lda, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*) end subroutine slaorhr_col_getrfnp #else module procedure stdlib${ii}$_slaorhr_col_getrfnp #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laorhr_col_getrfnp #:endif #:endfor #:endfor end interface laorhr_col_getrfnp interface laorhr_col_getrfnp2 !! LAORHR_COL_GETRFNP2 computes the modified LU factorization without !! pivoting of a real general M-by-N matrix A. The factorization has !! the form: !! A - S = L * U, !! where: !! S is a m-by-n diagonal sign matrix with the diagonal D, so that !! D(i) = S(i,i), 1 <= i <= min(M,N). The diagonal D is constructed !! as D(i)=-SIGN(A(i,i)), where A(i,i) is the value after performing !! i-1 steps of Gaussian elimination. This means that the diagonal !! element at each step of "modified" Gaussian elimination is at !! least one in absolute value (so that division-by-zero not !! possible during the division by the diagonal element); !! L is a M-by-N lower triangular matrix with unit diagonal elements !! (lower trapezoidal if M > N); !! and U is a M-by-N upper triangular matrix !! (upper trapezoidal if M < N). !! This routine is an auxiliary routine used in the Householder !! reconstruction routine DORHR_COL. In DORHR_COL, this routine is !! applied to an M-by-N matrix A with orthonormal columns, where each !! element is bounded by one in absolute value. With the choice of !! the matrix S above, one can show that the diagonal element at each !! step of Gaussian elimination is the largest (in absolute value) in !! the column on or below the diagonal, so that no pivoting is required !! for numerical stability [1]. !! For more details on the Householder reconstruction algorithm, !! including the modified LU factorization, see [1]. !! This is the recursive version of the LU factorization algorithm. !! Denote A - S by B. The algorithm divides the matrix B into four !! submatrices: !! [ B11 | B12 ] where B11 is n1 by n1, !! B = [ -----|----- ] B21 is (m-n1) by n1, !! [ B21 | B22 ] B12 is n1 by n2, !! B22 is (m-n1) by n2, !! with n1 = min(m,n)/2, n2 = n-n1. !! The subroutine calls itself to factor B11, solves for B21, !! solves for B12, updates B22, then calls itself to factor B22. !! For more details on the recursive LU algorithm, see [2]. !! LAORHR_COL_GETRFNP2 is called to factorize a block by the blocked !! routine DLAORHR_COL_GETRFNP, which uses blocked code calling !! Level 3 BLAS to update the submatrix. However, LAORHR_COL_GETRFNP2 !! is self-sufficient and can be used without DLAORHR_COL_GETRFNP. !! [1] "Reconstructing Householder vectors from tall-skinny QR", !! G. Ballard, J. Demmel, L. Grigori, M. Jacquelin, H.D. Nguyen, !! E. Solomonik, J. Parallel Distrib. Comput., !! vol. 85, pp. 3-31, 2015. !! [2] "Recursion leads to automatic variable blocking for dense linear !! algebra algorithms", F. Gustavson, IBM J. of Res. and Dev., !! vol. 41, no. 6, pp. 737-755, 1997. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine dlaorhr_col_getrfnp2( m, n, a, lda, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*) end subroutine dlaorhr_col_getrfnp2 #else module procedure stdlib${ii}$_dlaorhr_col_getrfnp2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine slaorhr_col_getrfnp2( m, n, a, lda, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*) end subroutine slaorhr_col_getrfnp2 #else module procedure stdlib${ii}$_slaorhr_col_getrfnp2 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laorhr_col_getrfnp2 #:endif #:endfor #:endfor end interface laorhr_col_getrfnp2 interface lapll !! Given two column vectors X and Y, let !! A = ( X Y ). !! The subroutine first computes the QR factorization of A = Q*R, !! and then computes the SVD of the 2-by-2 upper triangular matrix R. !! The smaller singular value of R is returned in SSMIN, which is used !! as the measurement of the linear dependency of the vectors X and Y. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clapll( n, x, incx, y, incy, ssmin ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(sp), intent(out) :: ssmin complex(sp), intent(inout) :: x(*),y(*) end subroutine clapll #else module procedure stdlib${ii}$_clapll #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlapll( n, x, incx, y, incy, ssmin ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(dp), intent(out) :: ssmin real(dp), intent(inout) :: x(*),y(*) end subroutine dlapll #else module procedure stdlib${ii}$_dlapll #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slapll( n, x, incx, y, incy, ssmin ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(sp), intent(out) :: ssmin real(sp), intent(inout) :: x(*),y(*) end subroutine slapll #else module procedure stdlib${ii}$_slapll #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlapll( n, x, incx, y, incy, ssmin ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(dp), intent(out) :: ssmin complex(dp), intent(inout) :: x(*),y(*) end subroutine zlapll #else module procedure stdlib${ii}$_zlapll #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lapll #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lapll #:endif #:endfor #:endfor end interface lapll interface lapmr !! LAPMR rearranges the rows of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M. !! If FORWRD = .TRUE., forward permutation: !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M. !! If FORWRD = .FALSE., backward permutation: !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clapmr( forwrd, m, n, x, ldx, k ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx,m,n integer(${ik}$), intent(inout) :: k(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine clapmr #else module procedure stdlib${ii}$_clapmr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlapmr( forwrd, m, n, x, ldx, k ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx,m,n integer(${ik}$), intent(inout) :: k(*) real(dp), intent(inout) :: x(ldx,*) end subroutine dlapmr #else module procedure stdlib${ii}$_dlapmr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slapmr( forwrd, m, n, x, ldx, k ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx,m,n integer(${ik}$), intent(inout) :: k(*) real(sp), intent(inout) :: x(ldx,*) end subroutine slapmr #else module procedure stdlib${ii}$_slapmr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlapmr( forwrd, m, n, x, ldx, k ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx,m,n integer(${ik}$), intent(inout) :: k(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zlapmr #else module procedure stdlib${ii}$_zlapmr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lapmr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lapmr #:endif #:endfor #:endfor end interface lapmr interface lapmt !! LAPMT rearranges the columns of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N. !! If FORWRD = .TRUE., forward permutation: !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N. !! If FORWRD = .FALSE., backward permutation: !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clapmt( forwrd, m, n, x, ldx, k ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx,m,n integer(${ik}$), intent(inout) :: k(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine clapmt #else module procedure stdlib${ii}$_clapmt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlapmt( forwrd, m, n, x, ldx, k ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx,m,n integer(${ik}$), intent(inout) :: k(*) real(dp), intent(inout) :: x(ldx,*) end subroutine dlapmt #else module procedure stdlib${ii}$_dlapmt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slapmt( forwrd, m, n, x, ldx, k ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx,m,n integer(${ik}$), intent(inout) :: k(*) real(sp), intent(inout) :: x(ldx,*) end subroutine slapmt #else module procedure stdlib${ii}$_slapmt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlapmt( forwrd, m, n, x, ldx, k ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx,m,n integer(${ik}$), intent(inout) :: k(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zlapmt #else module procedure stdlib${ii}$_zlapmt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lapmt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lapmt #:endif #:endfor #:endfor end interface lapmt interface laqgb !! LAQGB equilibrates a general M by N band matrix A with KL !! subdiagonals and KU superdiagonals using the row and scaling factors !! in the vectors R and C. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqgb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed integer(${ik}$), intent(in) :: kl,ku,ldab,m,n real(sp), intent(in) :: amax,colcnd,rowcnd,c(*),r(*) complex(sp), intent(inout) :: ab(ldab,*) end subroutine claqgb #else module procedure stdlib${ii}$_claqgb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaqgb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed integer(${ik}$), intent(in) :: kl,ku,ldab,m,n real(dp), intent(in) :: amax,colcnd,rowcnd,c(*),r(*) real(dp), intent(inout) :: ab(ldab,*) end subroutine dlaqgb #else module procedure stdlib${ii}$_dlaqgb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaqgb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed integer(${ik}$), intent(in) :: kl,ku,ldab,m,n real(sp), intent(in) :: amax,colcnd,rowcnd,c(*),r(*) real(sp), intent(inout) :: ab(ldab,*) end subroutine slaqgb #else module procedure stdlib${ii}$_slaqgb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqgb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed integer(${ik}$), intent(in) :: kl,ku,ldab,m,n real(dp), intent(in) :: amax,colcnd,rowcnd,c(*),r(*) complex(dp), intent(inout) :: ab(ldab,*) end subroutine zlaqgb #else module procedure stdlib${ii}$_zlaqgb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqgb #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqgb #:endif #:endfor #:endfor end interface laqgb interface laqge !! LAQGE equilibrates a general M by N matrix A using the row and !! column scaling factors in the vectors R and C. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqge( m, n, a, lda, r, c, rowcnd, colcnd, amax,equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(in) :: amax,colcnd,rowcnd,c(*),r(*) complex(sp), intent(inout) :: a(lda,*) end subroutine claqge #else module procedure stdlib${ii}$_claqge #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaqge( m, n, a, lda, r, c, rowcnd, colcnd, amax,equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(in) :: amax,colcnd,rowcnd,c(*),r(*) real(dp), intent(inout) :: a(lda,*) end subroutine dlaqge #else module procedure stdlib${ii}$_dlaqge #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaqge( m, n, a, lda, r, c, rowcnd, colcnd, amax,equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(in) :: amax,colcnd,rowcnd,c(*),r(*) real(sp), intent(inout) :: a(lda,*) end subroutine slaqge #else module procedure stdlib${ii}$_slaqge #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqge( m, n, a, lda, r, c, rowcnd, colcnd, amax,equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(in) :: amax,colcnd,rowcnd,c(*),r(*) complex(dp), intent(inout) :: a(lda,*) end subroutine zlaqge #else module procedure stdlib${ii}$_zlaqge #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqge #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqge #:endif #:endfor #:endfor end interface laqge interface laqhb !! LAQHB equilibrates an Hermitian band matrix A using the scaling !! factors in the vector S. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqhb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(in) :: amax,scond real(sp), intent(out) :: s(*) complex(sp), intent(inout) :: ab(ldab,*) end subroutine claqhb #else module procedure stdlib${ii}$_claqhb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqhb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(in) :: amax,scond real(dp), intent(out) :: s(*) complex(dp), intent(inout) :: ab(ldab,*) end subroutine zlaqhb #else module procedure stdlib${ii}$_zlaqhb #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqhb #:endif #:endfor #:endfor end interface laqhb interface laqhe !! LAQHE equilibrates a Hermitian matrix A using the scaling factors !! in the vector S. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqhe( uplo, n, a, lda, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,n real(sp), intent(in) :: amax,scond,s(*) complex(sp), intent(inout) :: a(lda,*) end subroutine claqhe #else module procedure stdlib${ii}$_claqhe #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqhe( uplo, n, a, lda, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,n real(dp), intent(in) :: amax,scond,s(*) complex(dp), intent(inout) :: a(lda,*) end subroutine zlaqhe #else module procedure stdlib${ii}$_zlaqhe #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqhe #:endif #:endfor #:endfor end interface laqhe interface laqhp !! LAQHP equilibrates a Hermitian matrix A using the scaling factors !! in the vector S. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqhp( uplo, n, ap, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: amax,scond,s(*) complex(sp), intent(inout) :: ap(*) end subroutine claqhp #else module procedure stdlib${ii}$_claqhp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqhp( uplo, n, ap, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: amax,scond,s(*) complex(dp), intent(inout) :: ap(*) end subroutine zlaqhp #else module procedure stdlib${ii}$_zlaqhp #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqhp #:endif #:endfor #:endfor end interface laqhp interface laqps !! LAQPS computes a step of QR factorization with column pivoting !! of a complex M-by-N matrix A by using Blas-3. It tries to factorize !! NB columns from A starting from the row OFFSET+1, and updates all !! of the matrix with Blas-3 xGEMM. !! In some cases, due to catastrophic cancellations, it cannot !! factorize NB columns. Hence, the actual number of factorized !! columns is returned in KB. !! Block A(1:OFFSET,1:N) is accordingly pivoted, but not factorized. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqps( m, n, offset, nb, kb, a, lda, jpvt, tau, vn1,vn2, auxv, f, & ldf ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: kb integer(${ik}$), intent(in) :: lda,ldf,m,n,nb,offset integer(${ik}$), intent(inout) :: jpvt(*) real(sp), intent(inout) :: vn1(*),vn2(*) complex(sp), intent(inout) :: a(lda,*),auxv(*),f(ldf,*) complex(sp), intent(out) :: tau(*) end subroutine claqps #else module procedure stdlib${ii}$_claqps #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaqps( m, n, offset, nb, kb, a, lda, jpvt, tau, vn1,vn2, auxv, f, & ldf ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: kb integer(${ik}$), intent(in) :: lda,ldf,m,n,nb,offset integer(${ik}$), intent(inout) :: jpvt(*) real(dp), intent(inout) :: a(lda,*),auxv(*),f(ldf,*),vn1(*),vn2(*) real(dp), intent(out) :: tau(*) end subroutine dlaqps #else module procedure stdlib${ii}$_dlaqps #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaqps( m, n, offset, nb, kb, a, lda, jpvt, tau, vn1,vn2, auxv, f, & ldf ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: kb integer(${ik}$), intent(in) :: lda,ldf,m,n,nb,offset integer(${ik}$), intent(inout) :: jpvt(*) real(sp), intent(inout) :: a(lda,*),auxv(*),f(ldf,*),vn1(*),vn2(*) real(sp), intent(out) :: tau(*) end subroutine slaqps #else module procedure stdlib${ii}$_slaqps #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqps( m, n, offset, nb, kb, a, lda, jpvt, tau, vn1,vn2, auxv, f, & ldf ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: kb integer(${ik}$), intent(in) :: lda,ldf,m,n,nb,offset integer(${ik}$), intent(inout) :: jpvt(*) real(dp), intent(inout) :: vn1(*),vn2(*) complex(dp), intent(inout) :: a(lda,*),auxv(*),f(ldf,*) complex(dp), intent(out) :: tau(*) end subroutine zlaqps #else module procedure stdlib${ii}$_zlaqps #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqps #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqps #:endif #:endfor #:endfor end interface laqps interface laqr0 !! LAQR0 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*H*(QZ)**H. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqr0( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz complex(sp), intent(inout) :: h(ldh,*),z(ldz,*) complex(sp), intent(out) :: w(*),work(*) end subroutine claqr0 #else module procedure stdlib${ii}$_claqr0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dlaqr0( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz real(dp), intent(inout) :: h(ldh,*),z(ldz,*) real(dp), intent(out) :: wi(*),work(*),wr(*) end subroutine dlaqr0 #else module procedure stdlib${ii}$_dlaqr0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine slaqr0( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz real(sp), intent(inout) :: h(ldh,*),z(ldz,*) real(sp), intent(out) :: wi(*),work(*),wr(*) end subroutine slaqr0 #else module procedure stdlib${ii}$_slaqr0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqr0( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz complex(dp), intent(inout) :: h(ldh,*),z(ldz,*) complex(dp), intent(out) :: w(*),work(*) end subroutine zlaqr0 #else module procedure stdlib${ii}$_zlaqr0 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqr0 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqr0 #:endif #:endfor #:endfor end interface laqr0 interface laqr1 !! Given a 2-by-2 or 3-by-3 matrix H, LAQR1: sets v to a !! scalar multiple of the first column of the product !! (*) K = (H - s1*I)*(H - s2*I) !! scaling to avoid overflows and most underflows. !! This is useful for starting double implicit shift bulges !! in the QR algorithm. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqr1( n, h, ldh, s1, s2, v ) import sp,dp,qp,${ik}$,lk implicit none complex(sp), intent(in) :: s1,s2,h(ldh,*) integer(${ik}$), intent(in) :: ldh,n complex(sp), intent(out) :: v(*) end subroutine claqr1 #else module procedure stdlib${ii}$_claqr1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaqr1( n, h, ldh, sr1, si1, sr2, si2, v ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: si1,si2,sr1,sr2,h(ldh,*) integer(${ik}$), intent(in) :: ldh,n real(dp), intent(out) :: v(*) end subroutine dlaqr1 #else module procedure stdlib${ii}$_dlaqr1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaqr1( n, h, ldh, sr1, si1, sr2, si2, v ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: si1,si2,sr1,sr2,h(ldh,*) integer(${ik}$), intent(in) :: ldh,n real(sp), intent(out) :: v(*) end subroutine slaqr1 #else module procedure stdlib${ii}$_slaqr1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqr1( n, h, ldh, s1, s2, v ) import sp,dp,qp,${ik}$,lk implicit none complex(dp), intent(in) :: s1,s2,h(ldh,*) integer(${ik}$), intent(in) :: ldh,n complex(dp), intent(out) :: v(*) end subroutine zlaqr1 #else module procedure stdlib${ii}$_zlaqr1 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqr1 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqr1 #:endif #:endfor #:endfor end interface laqr1 interface laqr4 !! LAQR4 implements one level of recursion for CLAQR0. !! It is a complete implementation of the small bulge multi-shift !! QR algorithm. It may be called by CLAQR0 and, for large enough !! deflation window size, it may be called by CLAQR3. This !! subroutine is identical to CLAQR0 except that it calls CLAQR2 !! instead of CLAQR3. !! LAQR4 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*H*(QZ)**H. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqr4( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz complex(sp), intent(inout) :: h(ldh,*),z(ldz,*) complex(sp), intent(out) :: w(*),work(*) end subroutine claqr4 #else module procedure stdlib${ii}$_claqr4 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dlaqr4( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz real(dp), intent(inout) :: h(ldh,*),z(ldz,*) real(dp), intent(out) :: wi(*),work(*),wr(*) end subroutine dlaqr4 #else module procedure stdlib${ii}$_dlaqr4 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine slaqr4( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz real(sp), intent(inout) :: h(ldh,*),z(ldz,*) real(sp), intent(out) :: wi(*),work(*),wr(*) end subroutine slaqr4 #else module procedure stdlib${ii}$_slaqr4 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqr4( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, & work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ihiz,ilo,iloz,ldh,ldz,lwork,n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt,wantz complex(dp), intent(inout) :: h(ldh,*),z(ldz,*) complex(dp), intent(out) :: w(*),work(*) end subroutine zlaqr4 #else module procedure stdlib${ii}$_zlaqr4 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqr4 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqr4 #:endif #:endfor #:endfor end interface laqr4 interface laqr5 !! LAQR5 called by CLAQR0 performs a !! single small-bulge multi-shift QR sweep. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqr5( wantt, wantz, kacc22, n, ktop, kbot, nshfts, s,h, ldh, & iloz, ihiz, z, ldz, v, ldv, u, ldu, nv,wv, ldwv, nh, wh, ldwh ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihiz,iloz,kacc22,kbot,ktop,ldh,ldu,ldv,ldwh,ldwv,& ldz,n,nh,nshfts,nv logical(lk), intent(in) :: wantt,wantz complex(sp), intent(inout) :: h(ldh,*),s(*),z(ldz,*) complex(sp), intent(out) :: u(ldu,*),v(ldv,*),wh(ldwh,*),wv(ldwv,*) end subroutine claqr5 #else module procedure stdlib${ii}$_claqr5 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaqr5( wantt, wantz, kacc22, n, ktop, kbot, nshfts,sr, si, h, ldh,& iloz, ihiz, z, ldz, v, ldv, u,ldu, nv, wv, ldwv, nh, wh, ldwh ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihiz,iloz,kacc22,kbot,ktop,ldh,ldu,ldv,ldwh,ldwv,& ldz,n,nh,nshfts,nv logical(lk), intent(in) :: wantt,wantz real(dp), intent(inout) :: h(ldh,*),si(*),sr(*),z(ldz,*) real(dp), intent(out) :: u(ldu,*),v(ldv,*),wh(ldwh,*),wv(ldwv,*) end subroutine dlaqr5 #else module procedure stdlib${ii}$_dlaqr5 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaqr5( wantt, wantz, kacc22, n, ktop, kbot, nshfts,sr, si, h, ldh,& iloz, ihiz, z, ldz, v, ldv, u,ldu, nv, wv, ldwv, nh, wh, ldwh ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihiz,iloz,kacc22,kbot,ktop,ldh,ldu,ldv,ldwh,ldwv,& ldz,n,nh,nshfts,nv logical(lk), intent(in) :: wantt,wantz real(sp), intent(inout) :: h(ldh,*),si(*),sr(*),z(ldz,*) real(sp), intent(out) :: u(ldu,*),v(ldv,*),wh(ldwh,*),wv(ldwv,*) end subroutine slaqr5 #else module procedure stdlib${ii}$_slaqr5 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqr5( wantt, wantz, kacc22, n, ktop, kbot, nshfts, s,h, ldh, & iloz, ihiz, z, ldz, v, ldv, u, ldu, nv,wv, ldwv, nh, wh, ldwh ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihiz,iloz,kacc22,kbot,ktop,ldh,ldu,ldv,ldwh,ldwv,& ldz,n,nh,nshfts,nv logical(lk), intent(in) :: wantt,wantz complex(dp), intent(inout) :: h(ldh,*),s(*),z(ldz,*) complex(dp), intent(out) :: u(ldu,*),v(ldv,*),wh(ldwh,*),wv(ldwv,*) end subroutine zlaqr5 #else module procedure stdlib${ii}$_zlaqr5 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqr5 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqr5 #:endif #:endfor #:endfor end interface laqr5 interface laqsb !! LAQSB equilibrates a symmetric band matrix A using the scaling !! factors in the vector S. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(in) :: amax,scond,s(*) complex(sp), intent(inout) :: ab(ldab,*) end subroutine claqsb #else module procedure stdlib${ii}$_claqsb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(in) :: amax,scond,s(*) real(dp), intent(inout) :: ab(ldab,*) end subroutine dlaqsb #else module procedure stdlib${ii}$_dlaqsb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(in) :: amax,scond,s(*) real(sp), intent(inout) :: ab(ldab,*) end subroutine slaqsb #else module procedure stdlib${ii}$_slaqsb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(in) :: amax,scond,s(*) complex(dp), intent(inout) :: ab(ldab,*) end subroutine zlaqsb #else module procedure stdlib${ii}$_zlaqsb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqsb #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqsb #:endif #:endfor #:endfor end interface laqsb interface laqsp !! LAQSP equilibrates a symmetric matrix A using the scaling factors !! in the vector S. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqsp( uplo, n, ap, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: amax,scond,s(*) complex(sp), intent(inout) :: ap(*) end subroutine claqsp #else module procedure stdlib${ii}$_claqsp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaqsp( uplo, n, ap, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: amax,scond,s(*) real(dp), intent(inout) :: ap(*) end subroutine dlaqsp #else module procedure stdlib${ii}$_dlaqsp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaqsp( uplo, n, ap, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: amax,scond,s(*) real(sp), intent(inout) :: ap(*) end subroutine slaqsp #else module procedure stdlib${ii}$_slaqsp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqsp( uplo, n, ap, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: amax,scond,s(*) complex(dp), intent(inout) :: ap(*) end subroutine zlaqsp #else module procedure stdlib${ii}$_zlaqsp #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqsp #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqsp #:endif #:endfor #:endfor end interface laqsp interface laqsy !! LAQSY equilibrates a symmetric matrix A using the scaling factors !! in the vector S. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqsy( uplo, n, a, lda, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,n real(sp), intent(in) :: amax,scond,s(*) complex(sp), intent(inout) :: a(lda,*) end subroutine claqsy #else module procedure stdlib${ii}$_claqsy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaqsy( uplo, n, a, lda, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,n real(dp), intent(in) :: amax,scond,s(*) real(dp), intent(inout) :: a(lda,*) end subroutine dlaqsy #else module procedure stdlib${ii}$_dlaqsy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaqsy( uplo, n, a, lda, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,n real(sp), intent(in) :: amax,scond,s(*) real(sp), intent(inout) :: a(lda,*) end subroutine slaqsy #else module procedure stdlib${ii}$_slaqsy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqsy( uplo, n, a, lda, s, scond, amax, equed ) import sp,dp,qp,${ik}$,lk implicit none character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,n real(dp), intent(in) :: amax,scond,s(*) complex(dp), intent(inout) :: a(lda,*) end subroutine zlaqsy #else module procedure stdlib${ii}$_zlaqsy #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqsy #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqsy #:endif #:endfor #:endfor end interface laqsy interface laqtr !! LAQTR solves the real quasi-triangular system !! op(T)*p = scale*c, if LREAL = .TRUE. !! or the complex quasi-triangular systems !! op(T + iB)*(p+iq) = scale*(c+id), if LREAL = .FALSE. !! in real arithmetic, where T is upper quasi-triangular. !! If LREAL = .FALSE., then the first diagonal block of T must be !! 1 by 1, B is the specially structured matrix !! B = [ b(1) b(2) ... b(n) ] !! [ w ] !! [ w ] !! [ . ] !! [ w ] !! op(A) = A or A**T, A**T denotes the transpose of !! matrix A. !! On input, X = [ c ]. On output, X = [ p ]. !! [ d ] [ q ] !! This subroutine is designed for the condition number estimation !! in routine DTRSNA. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dlaqtr( ltran, lreal, n, t, ldt, b, w, scale, x, work,info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: lreal,ltran integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldt,n real(dp), intent(out) :: scale,work(*) real(dp), intent(in) :: w,b(*),t(ldt,*) real(dp), intent(inout) :: x(*) end subroutine dlaqtr #else module procedure stdlib${ii}$_dlaqtr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine slaqtr( ltran, lreal, n, t, ldt, b, w, scale, x, work,info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: lreal,ltran integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldt,n real(sp), intent(out) :: scale,work(*) real(sp), intent(in) :: w,b(*),t(ldt,*) real(sp), intent(inout) :: x(*) end subroutine slaqtr #else module procedure stdlib${ii}$_slaqtr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqtr #:endif #:endfor #:endfor end interface laqtr interface laqz0 !! LAQZ0 computes the eigenvalues of a matrix pair (H,T), !! where H is an upper Hessenberg matrix and T is upper triangular, !! using the double-shift QZ method. !! Matrix pairs of this type are produced by the reduction to !! generalized upper Hessenberg form of a matrix pair (A,B): !! A = Q1*H*Z1**H, B = Q1*T*Z1**H, !! as computed by CGGHRD. !! If JOB='S', then the Hessenberg-triangular pair (H,T) is !! also reduced to generalized Schur form, !! H = Q*S*Z**H, T = Q*P*Z**H, !! where Q and Z are unitary matrices, P and S are an upper triangular !! matrices. !! Optionally, the unitary matrix Q from the generalized Schur !! factorization may be postmultiplied into an input matrix Q1, and the !! unitary matrix Z may be postmultiplied into an input matrix Z1. !! If Q1 and Z1 are the unitary matrices from CGGHRD that reduced !! the matrix pair (A,B) to generalized upper Hessenberg form, then the !! output matrices Q1*Q and Z1*Z are the unitary factors from the !! generalized Schur factorization of (A,B): !! A = (Q1*Q)*S*(Z1*Z)**H, B = (Q1*Q)*P*(Z1*Z)**H. !! To avoid overflow, eigenvalues of the matrix pair (H,T) (equivalently, !! of (A,B)) are computed as a pair of values (alpha,beta), where alpha is !! complex and beta real. !! If beta is nonzero, lambda = alpha / beta is an eigenvalue of the !! generalized nonsymmetric eigenvalue problem (GNEP) !! A*x = lambda*B*x !! and if alpha is nonzero, mu = beta / alpha is an eigenvalue of the !! alternate form of the GNEP !! mu*A*y = B*y. !! Eigenvalues can be read directly from the generalized Schur !! form: !! alpha = S(i,i), beta = P(i,i). !! Ref: C.B. Moler !! Eigenvalue Problems", SIAM J. Numer. Anal., 10(1973), !! pp. 241--256. !! Ref: B. Kagstrom, D. Kressner, "Multishift Variants of the QZ !! Algorithm with Aggressive Early Deflation", SIAM J. Numer. !! Anal., 29(2006), pp. 199--227. !! Ref: T. Steel, D. Camps, K. Meerbergen, R. Vandebril "A multishift, !! multipole rational QZ method with agressive early deflation" #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ recursive subroutine claqz0( wants, wantq, wantz, n, ilo, ihi, a,lda, b, ldb, & alpha, beta, q, ldq, z,ldz, work, lwork, rwork, rec,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: wants,wantq,wantz integer(${ik}$), intent(in) :: n,ilo,ihi,lda,ldb,ldq,ldz,lwork,rec integer(${ik}$), intent(out) :: info complex(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) complex(sp), intent(inout) :: alpha(*),beta(*),work(*) real(sp), intent(out) :: rwork(*) end subroutine claqz0 #else module procedure stdlib${ii}$_claqz0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ recursive subroutine dlaqz0( wants, wantq, wantz, n, ilo, ihi, a,lda, b, ldb, & alphar, alphai, beta,q, ldq, z, ldz, work, lwork, rec,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: wants,wantq,wantz integer(${ik}$), intent(in) :: n,ilo,ihi,lda,ldb,ldq,ldz,lwork,rec integer(${ik}$), intent(out) :: info real(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) real(dp), intent(inout) :: alphar(*),alphai(*),beta(*),work(*) end subroutine dlaqz0 #else module procedure stdlib${ii}$_dlaqz0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ recursive subroutine slaqz0( wants, wantq, wantz, n, ilo, ihi, a,lda, b, ldb, & alphar, alphai, beta,q, ldq, z, ldz, work, lwork, rec,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: wants,wantq,wantz integer(${ik}$), intent(in) :: n,ilo,ihi,lda,ldb,ldq,ldz,lwork,rec integer(${ik}$), intent(out) :: info real(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) real(sp), intent(inout) :: alphar(*),alphai(*),beta(*),work(*) end subroutine slaqz0 #else module procedure stdlib${ii}$_slaqz0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ recursive subroutine zlaqz0( wants, wantq, wantz, n, ilo, ihi, a,lda, b, ldb, & alpha, beta, q, ldq, z,ldz, work, lwork, rwork, rec,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: wants,wantq,wantz integer(${ik}$), intent(in) :: n,ilo,ihi,lda,ldb,ldq,ldz,lwork,rec integer(${ik}$), intent(out) :: info complex(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) complex(dp), intent(inout) :: alpha(*),beta(*),work(*) real(dp), intent(out) :: rwork(*) end subroutine zlaqz0 #else module procedure stdlib${ii}$_zlaqz0 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqz0 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqz0 #:endif #:endfor #:endfor end interface laqz0 interface laqz1 !! LAQZ1 chases a 1x1 shift bulge in a matrix pencil down a single position #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claqz1( ilq, ilz, k, istartm, istopm, ihi, a, lda, b,ldb, nq, & qstart, q, ldq, nz, zstart, z, ldz ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: ilq,ilz integer(${ik}$), intent(in) :: k,lda,ldb,ldq,ldz,istartm,istopm,nq,nz,qstart,& zstart,ihi complex(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) end subroutine claqz1 #else module procedure stdlib${ii}$_claqz1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaqz1( a, lda, b, ldb, sr1, sr2, si, beta1, beta2,v ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: lda,ldb real(dp), intent(in) :: a(lda,*),b(ldb,*),sr1,sr2,si,beta1,beta2 real(dp), intent(out) :: v(*) end subroutine dlaqz1 #else module procedure stdlib${ii}$_dlaqz1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaqz1( a, lda, b, ldb, sr1, sr2, si, beta1, beta2,v ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: lda,ldb real(sp), intent(in) :: a(lda,*),b(ldb,*),sr1,sr2,si,beta1,beta2 real(sp), intent(out) :: v(*) end subroutine slaqz1 #else module procedure stdlib${ii}$_slaqz1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaqz1( ilq, ilz, k, istartm, istopm, ihi, a, lda, b,ldb, nq, & qstart, q, ldq, nz, zstart, z, ldz ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: ilq,ilz integer(${ik}$), intent(in) :: k,lda,ldb,ldq,ldz,istartm,istopm,nq,nz,qstart,& zstart,ihi complex(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) end subroutine zlaqz1 #else module procedure stdlib${ii}$_zlaqz1 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqz1 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqz1 #:endif #:endfor #:endfor end interface laqz1 interface laqz4 !! LAQZ4 Executes a single multishift QZ sweep #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaqz4( ilschur, ilq, ilz, n, ilo, ihi, nshifts,nblock_desired, sr,& si, ss, a, lda, b, ldb, q,ldq, z, ldz, qc, ldqc, zc, ldzc, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: ilschur,ilq,ilz integer(${ik}$), intent(in) :: n,ilo,ihi,lda,ldb,ldq,ldz,lwork,nshifts,& nblock_desired,ldqc,ldzc real(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*),qc(ldqc,*),zc(& ldzc,*) real(dp), intent(inout) :: work(*) real(dp), intent(inout) :: sr(*),si(*),ss(*) integer(${ik}$), intent(out) :: info end subroutine dlaqz4 #else module procedure stdlib${ii}$_dlaqz4 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaqz4( ilschur, ilq, ilz, n, ilo, ihi, nshifts,nblock_desired, sr,& si, ss, a, lda, b, ldb, q,ldq, z, ldz, qc, ldqc, zc, ldzc, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: ilschur,ilq,ilz integer(${ik}$), intent(in) :: n,ilo,ihi,lda,ldb,ldq,ldz,lwork,nshifts,& nblock_desired,ldqc,ldzc real(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*),qc(ldqc,*),zc(& ldzc,*) real(sp), intent(inout) :: work(*) real(sp), intent(inout) :: sr(*),si(*),ss(*) integer(${ik}$), intent(out) :: info end subroutine slaqz4 #else module procedure stdlib${ii}$_slaqz4 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laqz4 #:endif #:endfor #:endfor end interface laqz4 interface lar1v !! LAR1V computes the (scaled) r-th column of the inverse of !! the sumbmatrix in rows B1 through BN of the tridiagonal matrix !! L D L**T - sigma I. When sigma is close to an eigenvalue, the !! computed vector is an accurate eigenvector. Usually, r corresponds !! to the index where the eigenvector is largest in magnitude. !! The following steps accomplish this computation : !! (a) Stationary qd transform, L D L**T - sigma I = L(+) D(+) L(+)**T, !! (b) Progressive qd transform, L D L**T - sigma I = U(-) D(-) U(-)**T, !! (c) Computation of the diagonal elements of the inverse of !! L D L**T - sigma I by combining the above transforms, and choosing !! r as the index where the diagonal of the inverse is (one of the) !! largest in magnitude. !! (d) Computation of the (scaled) r-th column of the inverse using the !! twisted factorization obtained by combining the top part of the !! the stationary and the bottom part of the progressive transform. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clar1v( n, b1, bn, lambda, d, l, ld, lld,pivmin, gaptol, z, wantnc,& negcnt, ztz, mingma,r, isuppz, nrminv, resid, rqcorr, work ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantnc integer(${ik}$), intent(in) :: b1,bn,n integer(${ik}$), intent(out) :: negcnt,isuppz(*) integer(${ik}$), intent(inout) :: r real(sp), intent(in) :: gaptol,lambda,pivmin,d(*),l(*),ld(*),lld(*) real(sp), intent(out) :: mingma,nrminv,resid,rqcorr,ztz,work(*) complex(sp), intent(inout) :: z(*) end subroutine clar1v #else module procedure stdlib${ii}$_clar1v #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlar1v( n, b1, bn, lambda, d, l, ld, lld,pivmin, gaptol, z, wantnc,& negcnt, ztz, mingma,r, isuppz, nrminv, resid, rqcorr, work ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantnc integer(${ik}$), intent(in) :: b1,bn,n integer(${ik}$), intent(out) :: negcnt,isuppz(*) integer(${ik}$), intent(inout) :: r real(dp), intent(in) :: gaptol,lambda,pivmin,d(*),l(*),ld(*),lld(*) real(dp), intent(out) :: mingma,nrminv,resid,rqcorr,ztz,work(*) real(dp), intent(inout) :: z(*) end subroutine dlar1v #else module procedure stdlib${ii}$_dlar1v #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slar1v( n, b1, bn, lambda, d, l, ld, lld,pivmin, gaptol, z, wantnc,& negcnt, ztz, mingma,r, isuppz, nrminv, resid, rqcorr, work ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantnc integer(${ik}$), intent(in) :: b1,bn,n integer(${ik}$), intent(out) :: negcnt,isuppz(*) integer(${ik}$), intent(inout) :: r real(sp), intent(in) :: gaptol,lambda,pivmin,d(*),l(*),ld(*),lld(*) real(sp), intent(out) :: mingma,nrminv,resid,rqcorr,ztz,work(*) real(sp), intent(inout) :: z(*) end subroutine slar1v #else module procedure stdlib${ii}$_slar1v #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlar1v( n, b1, bn, lambda, d, l, ld, lld,pivmin, gaptol, z, wantnc,& negcnt, ztz, mingma,r, isuppz, nrminv, resid, rqcorr, work ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantnc integer(${ik}$), intent(in) :: b1,bn,n integer(${ik}$), intent(out) :: negcnt,isuppz(*) integer(${ik}$), intent(inout) :: r real(dp), intent(in) :: gaptol,lambda,pivmin,d(*),l(*),ld(*),lld(*) real(dp), intent(out) :: mingma,nrminv,resid,rqcorr,ztz,work(*) complex(dp), intent(inout) :: z(*) end subroutine zlar1v #else module procedure stdlib${ii}$_zlar1v #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lar1v #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lar1v #:endif #:endfor #:endfor end interface lar1v interface lar2v !! LAR2V applies a vector of complex plane rotations with real cosines !! from both sides to a sequence of 2-by-2 complex Hermitian matrices, !! defined by the elements of the vectors x, y and z. For i = 1,2,...,n !! ( x(i) z(i) ) := !! ( conjg(z(i)) y(i) ) !! ( c(i) conjg(s(i)) ) ( x(i) z(i) ) ( c(i) -conjg(s(i)) ) !! ( -s(i) c(i) ) ( conjg(z(i)) y(i) ) ( s(i) c(i) ) #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clar2v( n, x, y, z, incx, c, s, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,n real(sp), intent(in) :: c(*) complex(sp), intent(in) :: s(*) complex(sp), intent(inout) :: x(*),y(*),z(*) end subroutine clar2v #else module procedure stdlib${ii}$_clar2v #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlar2v( n, x, y, z, incx, c, s, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,n real(dp), intent(in) :: c(*),s(*) real(dp), intent(inout) :: x(*),y(*),z(*) end subroutine dlar2v #else module procedure stdlib${ii}$_dlar2v #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slar2v( n, x, y, z, incx, c, s, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,n real(sp), intent(in) :: c(*),s(*) real(sp), intent(inout) :: x(*),y(*),z(*) end subroutine slar2v #else module procedure stdlib${ii}$_slar2v #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlar2v( n, x, y, z, incx, c, s, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,n real(dp), intent(in) :: c(*) complex(dp), intent(in) :: s(*) complex(dp), intent(inout) :: x(*),y(*),z(*) end subroutine zlar2v #else module procedure stdlib${ii}$_zlar2v #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lar2v #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lar2v #:endif #:endfor #:endfor end interface lar2v interface larcm !! LARCM performs a very simple matrix-matrix multiplication: !! C := A * B, !! where A is M by M and real; B is M by N and complex; !! C is M by N and complex. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarcm( m, n, a, lda, b, ldb, c, ldc, rwork ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: lda,ldb,ldc,m,n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: rwork(*) complex(sp), intent(in) :: b(ldb,*) complex(sp), intent(out) :: c(ldc,*) end subroutine clarcm #else module procedure stdlib${ii}$_clarcm #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarcm( m, n, a, lda, b, ldb, c, ldc, rwork ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: lda,ldb,ldc,m,n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: rwork(*) complex(dp), intent(in) :: b(ldb,*) complex(dp), intent(out) :: c(ldc,*) end subroutine zlarcm #else module procedure stdlib${ii}$_zlarcm #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larcm #:endif #:endfor #:endfor end interface larcm interface larf !! LARF applies a complex elementary reflector H to a complex M-by-N !! matrix C, from either the left or the right. H is represented in the !! form !! H = I - tau * v * v**H !! where tau is a complex scalar and v is a complex vector. !! If tau = 0, then H is taken to be the unit matrix. !! To apply H**H (the conjugate transpose of H), supply conjg(tau) instead !! tau. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarf( side, m, n, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side integer(${ik}$), intent(in) :: incv,ldc,m,n complex(sp), intent(in) :: tau,v(*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine clarf #else module procedure stdlib${ii}$_clarf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarf( side, m, n, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side integer(${ik}$), intent(in) :: incv,ldc,m,n real(dp), intent(in) :: tau,v(*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine dlarf #else module procedure stdlib${ii}$_dlarf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarf( side, m, n, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side integer(${ik}$), intent(in) :: incv,ldc,m,n real(sp), intent(in) :: tau,v(*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine slarf #else module procedure stdlib${ii}$_slarf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarf( side, m, n, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side integer(${ik}$), intent(in) :: incv,ldc,m,n complex(dp), intent(in) :: tau,v(*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine zlarf #else module procedure stdlib${ii}$_zlarf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larf #:endif #:endfor #:endfor end interface larf interface larfb !! LARFB applies a complex block reflector H or its transpose H**H to a !! complex M-by-N matrix C, from either the left or the right. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, & ldc, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,ldc,ldt,ldv,ldwork,m,n complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(in) :: t(ldt,*),v(ldv,*) complex(sp), intent(out) :: work(ldwork,*) end subroutine clarfb #else module procedure stdlib${ii}$_clarfb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, & ldc, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,ldc,ldt,ldv,ldwork,m,n real(dp), intent(inout) :: c(ldc,*) real(dp), intent(in) :: t(ldt,*),v(ldv,*) real(dp), intent(out) :: work(ldwork,*) end subroutine dlarfb #else module procedure stdlib${ii}$_dlarfb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, & ldc, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,ldc,ldt,ldv,ldwork,m,n real(sp), intent(inout) :: c(ldc,*) real(sp), intent(in) :: t(ldt,*),v(ldv,*) real(sp), intent(out) :: work(ldwork,*) end subroutine slarfb #else module procedure stdlib${ii}$_slarfb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, & ldc, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,ldc,ldt,ldv,ldwork,m,n complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(in) :: t(ldt,*),v(ldv,*) complex(dp), intent(out) :: work(ldwork,*) end subroutine zlarfb #else module procedure stdlib${ii}$_zlarfb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larfb #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larfb #:endif #:endfor #:endfor end interface larfb interface larfb_gett !! LARFB_GETT applies a complex Householder block reflector H from the !! left to a complex (K+M)-by-N "triangular-pentagonal" matrix !! composed of two block matrices: an upper trapezoidal K-by-N matrix A !! stored in the array A, and a rectangular M-by-(N-K) matrix B, stored !! in the array B. The block reflector H is stored in a compact !! WY-representation, where the elementary reflectors are in the !! arrays A, B and T. See Further Details section. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarfb_gett( ident, m, n, k, t, ldt, a, lda, b, ldb,work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: ident integer(${ik}$), intent(in) :: k,lda,ldb,ldt,ldwork,m,n complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(in) :: t(ldt,*) complex(sp), intent(out) :: work(ldwork,*) end subroutine clarfb_gett #else module procedure stdlib${ii}$_clarfb_gett #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarfb_gett( ident, m, n, k, t, ldt, a, lda, b, ldb,work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: ident integer(${ik}$), intent(in) :: k,lda,ldb,ldt,ldwork,m,n real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(in) :: t(ldt,*) real(dp), intent(out) :: work(ldwork,*) end subroutine dlarfb_gett #else module procedure stdlib${ii}$_dlarfb_gett #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarfb_gett( ident, m, n, k, t, ldt, a, lda, b, ldb,work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: ident integer(${ik}$), intent(in) :: k,lda,ldb,ldt,ldwork,m,n real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(in) :: t(ldt,*) real(sp), intent(out) :: work(ldwork,*) end subroutine slarfb_gett #else module procedure stdlib${ii}$_slarfb_gett #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarfb_gett( ident, m, n, k, t, ldt, a, lda, b, ldb,work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: ident integer(${ik}$), intent(in) :: k,lda,ldb,ldt,ldwork,m,n complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(in) :: t(ldt,*) complex(dp), intent(out) :: work(ldwork,*) end subroutine zlarfb_gett #else module procedure stdlib${ii}$_zlarfb_gett #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larfb_gett #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larfb_gett #:endif #:endfor #:endfor end interface larfb_gett interface larfg !! LARFG generates a complex elementary reflector H of order n, such !! that !! H**H * ( alpha ) = ( beta ), H**H * H = I. !! ( x ) ( 0 ) !! where alpha and beta are scalars, with beta real, and x is an !! (n-1)-element complex vector. H is represented in the form !! H = I - tau * ( 1 ) * ( 1 v**H ) , !! ( v ) !! where tau is a complex scalar and v is a complex (n-1)-element !! vector. Note that H is not hermitian. !! If the elements of x are all zero and alpha is real, then tau = 0 !! and H is taken to be the unit matrix. !! Otherwise 1 <= real(tau) <= 2 and abs(tau-1) <= 1 . #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarfg( n, alpha, x, incx, tau ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n complex(sp), intent(inout) :: alpha,x(*) complex(sp), intent(out) :: tau end subroutine clarfg #else module procedure stdlib${ii}$_clarfg #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarfg( n, alpha, x, incx, tau ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n real(dp), intent(inout) :: alpha,x(*) real(dp), intent(out) :: tau end subroutine dlarfg #else module procedure stdlib${ii}$_dlarfg #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarfg( n, alpha, x, incx, tau ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n real(sp), intent(inout) :: alpha,x(*) real(sp), intent(out) :: tau end subroutine slarfg #else module procedure stdlib${ii}$_slarfg #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarfg( n, alpha, x, incx, tau ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n complex(dp), intent(inout) :: alpha,x(*) complex(dp), intent(out) :: tau end subroutine zlarfg #else module procedure stdlib${ii}$_zlarfg #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larfg #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larfg #:endif #:endfor #:endfor end interface larfg interface larfgp !! LARFGP generates a complex elementary reflector H of order n, such !! that !! H**H * ( alpha ) = ( beta ), H**H * H = I. !! ( x ) ( 0 ) !! where alpha and beta are scalars, beta is real and non-negative, and !! x is an (n-1)-element complex vector. H is represented in the form !! H = I - tau * ( 1 ) * ( 1 v**H ) , !! ( v ) !! where tau is a complex scalar and v is a complex (n-1)-element !! vector. Note that H is not hermitian. !! If the elements of x are all zero and alpha is real, then tau = 0 !! and H is taken to be the unit matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine clarfgp( n, alpha, x, incx, tau ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n complex(sp), intent(inout) :: alpha,x(*) complex(sp), intent(out) :: tau end subroutine clarfgp #else module procedure stdlib${ii}$_clarfgp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dlarfgp( n, alpha, x, incx, tau ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n real(dp), intent(inout) :: alpha,x(*) real(dp), intent(out) :: tau end subroutine dlarfgp #else module procedure stdlib${ii}$_dlarfgp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine slarfgp( n, alpha, x, incx, tau ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n real(sp), intent(inout) :: alpha,x(*) real(sp), intent(out) :: tau end subroutine slarfgp #else module procedure stdlib${ii}$_slarfgp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zlarfgp( n, alpha, x, incx, tau ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n complex(dp), intent(inout) :: alpha,x(*) complex(dp), intent(out) :: tau end subroutine zlarfgp #else module procedure stdlib${ii}$_zlarfgp #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larfgp #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larfgp #:endif #:endfor #:endfor end interface larfgp interface larft !! LARFT forms the triangular factor T of a complex block reflector H !! of order n, which is defined as a product of k elementary reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**H !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**H * T * V #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarft( direct, storev, n, k, v, ldv, tau, t, ldt ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,storev integer(${ik}$), intent(in) :: k,ldt,ldv,n complex(sp), intent(out) :: t(ldt,*) complex(sp), intent(in) :: tau(*),v(ldv,*) end subroutine clarft #else module procedure stdlib${ii}$_clarft #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarft( direct, storev, n, k, v, ldv, tau, t, ldt ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,storev integer(${ik}$), intent(in) :: k,ldt,ldv,n real(dp), intent(out) :: t(ldt,*) real(dp), intent(in) :: tau(*),v(ldv,*) end subroutine dlarft #else module procedure stdlib${ii}$_dlarft #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarft( direct, storev, n, k, v, ldv, tau, t, ldt ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,storev integer(${ik}$), intent(in) :: k,ldt,ldv,n real(sp), intent(out) :: t(ldt,*) real(sp), intent(in) :: tau(*),v(ldv,*) end subroutine slarft #else module procedure stdlib${ii}$_slarft #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarft( direct, storev, n, k, v, ldv, tau, t, ldt ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,storev integer(${ik}$), intent(in) :: k,ldt,ldv,n complex(dp), intent(out) :: t(ldt,*) complex(dp), intent(in) :: tau(*),v(ldv,*) end subroutine zlarft #else module procedure stdlib${ii}$_zlarft #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larft #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larft #:endif #:endfor #:endfor end interface larft interface larfy !! LARFY applies an elementary reflector, or Householder matrix, H, !! to an n x n Hermitian matrix C, from both the left and the right. !! H is represented in the form !! H = I - tau * v * v' !! where tau is a scalar and v is a vector. !! If tau is zero, then H is taken to be the unit matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarfy( uplo, n, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv,ldc,n complex(sp), intent(in) :: tau,v(*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine clarfy #else module procedure stdlib${ii}$_clarfy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarfy( uplo, n, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv,ldc,n real(dp), intent(in) :: tau,v(*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine dlarfy #else module procedure stdlib${ii}$_dlarfy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarfy( uplo, n, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv,ldc,n real(sp), intent(in) :: tau,v(*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine slarfy #else module procedure stdlib${ii}$_slarfy #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarfy( uplo, n, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv,ldc,n complex(dp), intent(in) :: tau,v(*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine zlarfy #else module procedure stdlib${ii}$_zlarfy #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larfy #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larfy #:endif #:endfor #:endfor end interface larfy interface largv !! LARGV generates a vector of complex plane rotations with real !! cosines, determined by elements of the complex vectors x and y. !! For i = 1,2,...,n !! ( c(i) s(i) ) ( x(i) ) = ( r(i) ) !! ( -conjg(s(i)) c(i) ) ( y(i) ) = ( 0 ) !! where c(i)**2 + ABS(s(i))**2 = 1 !! The following conventions are used (these are the same as in CLARTG, !! but differ from the BLAS1 routine CROTG): !! If y(i)=0, then c(i)=1 and s(i)=0. !! If x(i)=0, then c(i)=0 and s(i) is chosen so that r(i) is real. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clargv( n, x, incx, y, incy, c, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,incy,n real(sp), intent(out) :: c(*) complex(sp), intent(inout) :: x(*),y(*) end subroutine clargv #else module procedure stdlib${ii}$_clargv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlargv( n, x, incx, y, incy, c, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,incy,n real(dp), intent(out) :: c(*) real(dp), intent(inout) :: x(*),y(*) end subroutine dlargv #else module procedure stdlib${ii}$_dlargv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slargv( n, x, incx, y, incy, c, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,incy,n real(sp), intent(out) :: c(*) real(sp), intent(inout) :: x(*),y(*) end subroutine slargv #else module procedure stdlib${ii}$_slargv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlargv( n, x, incx, y, incy, c, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,incy,n real(dp), intent(out) :: c(*) complex(dp), intent(inout) :: x(*),y(*) end subroutine zlargv #else module procedure stdlib${ii}$_zlargv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$largv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$largv #:endif #:endfor #:endfor end interface largv interface larnv !! LARNV returns a vector of n random complex numbers from a uniform or !! normal distribution. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarnv( idist, iseed, n, x ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: idist,n integer(${ik}$), intent(inout) :: iseed(4) complex(sp), intent(out) :: x(*) end subroutine clarnv #else module procedure stdlib${ii}$_clarnv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarnv( idist, iseed, n, x ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: idist,n integer(${ik}$), intent(inout) :: iseed(4) real(dp), intent(out) :: x(*) end subroutine dlarnv #else module procedure stdlib${ii}$_dlarnv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarnv( idist, iseed, n, x ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: idist,n integer(${ik}$), intent(inout) :: iseed(4) real(sp), intent(out) :: x(*) end subroutine slarnv #else module procedure stdlib${ii}$_slarnv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarnv( idist, iseed, n, x ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: idist,n integer(${ik}$), intent(inout) :: iseed(4) complex(dp), intent(out) :: x(*) end subroutine zlarnv #else module procedure stdlib${ii}$_zlarnv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larnv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larnv #:endif #:endfor #:endfor end interface larnv interface larra !! Compute the splitting points with threshold SPLTOL. !! LARRA sets any "small" off-diagonal elements to zero. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarra( n, d, e, e2, spltol, tnrm,nsplit, isplit, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,nsplit,isplit(*) integer(${ik}$), intent(in) :: n real(dp), intent(in) :: spltol,tnrm,d(*) real(dp), intent(inout) :: e(*),e2(*) end subroutine dlarra #else module procedure stdlib${ii}$_dlarra #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarra( n, d, e, e2, spltol, tnrm,nsplit, isplit, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,nsplit,isplit(*) integer(${ik}$), intent(in) :: n real(sp), intent(in) :: spltol,tnrm,d(*) real(sp), intent(inout) :: e(*),e2(*) end subroutine slarra #else module procedure stdlib${ii}$_slarra #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larra #:endif #:endfor #:endfor end interface larra interface larrb !! Given the relatively robust representation(RRR) L D L^T, LARRB: !! does "limited" bisection to refine the eigenvalues of L D L^T, !! W( IFIRST-OFFSET ) through W( ILAST-OFFSET ), to more accuracy. Initial !! guesses for these eigenvalues are input in W, the corresponding estimate !! of the error in these guesses and their gaps are input in WERR !! and WGAP, respectively. During bisection, intervals !! [left, right] are maintained by storing their mid-points and !! semi-widths in the arrays W and WERR respectively. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarrb( n, d, lld, ifirst, ilast, rtol1,rtol2, offset, w, wgap, & werr, work, iwork,pivmin, spdiam, twist, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ifirst,ilast,n,offset,twist integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(in) :: pivmin,rtol1,rtol2,spdiam,d(*),lld(*) real(dp), intent(inout) :: w(*),werr(*),wgap(*) real(dp), intent(out) :: work(*) end subroutine dlarrb #else module procedure stdlib${ii}$_dlarrb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarrb( n, d, lld, ifirst, ilast, rtol1,rtol2, offset, w, wgap, & werr, work, iwork,pivmin, spdiam, twist, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ifirst,ilast,n,offset,twist integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(in) :: pivmin,rtol1,rtol2,spdiam,d(*),lld(*) real(sp), intent(inout) :: w(*),werr(*),wgap(*) real(sp), intent(out) :: work(*) end subroutine slarrb #else module procedure stdlib${ii}$_slarrb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larrb #:endif #:endfor #:endfor end interface larrb interface larrc !! Find the number of eigenvalues of the symmetric tridiagonal matrix T !! that are in the interval (VL,VU] if JOBT = 'T', and of L D L^T !! if JOBT = 'L'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarrc( jobt, n, vl, vu, d, e, pivmin,eigcnt, lcnt, rcnt, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobt integer(${ik}$), intent(out) :: eigcnt,info,lcnt,rcnt integer(${ik}$), intent(in) :: n real(dp), intent(in) :: pivmin,vl,vu,d(*),e(*) end subroutine dlarrc #else module procedure stdlib${ii}$_dlarrc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarrc( jobt, n, vl, vu, d, e, pivmin,eigcnt, lcnt, rcnt, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobt integer(${ik}$), intent(out) :: eigcnt,info,lcnt,rcnt integer(${ik}$), intent(in) :: n real(sp), intent(in) :: pivmin,vl,vu,d(*),e(*) end subroutine slarrc #else module procedure stdlib${ii}$_slarrc #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larrc #:endif #:endfor #:endfor end interface larrc interface larrd !! LARRD computes the eigenvalues of a symmetric tridiagonal !! matrix T to suitable accuracy. This is an auxiliary code to be !! called from DSTEMR. !! The user may ask for all eigenvalues, all eigenvalues !! in the half-open interval (VL, VU], or the IL-th through IU-th !! eigenvalues. !! To avoid overflow, the matrix must be scaled so that its !! largest element is no greater than overflow**(1/2) * underflow**(1/4) in absolute value, and for greatest !! accuracy, it should not be much smaller than that. !! See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal !! Matrix", Report CS41, Computer Science Dept., Stanford !! University, July 21, 1966. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarrd( range, order, n, vl, vu, il, iu, gers,reltol, d, e, e2, & pivmin, nsplit, isplit,m, w, werr, wl, wu, iblock, indexw,work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: order,range integer(${ik}$), intent(in) :: il,iu,n,nsplit,isplit(*) integer(${ik}$), intent(out) :: info,m,iblock(*),indexw(*),iwork(*) real(dp), intent(in) :: pivmin,reltol,vl,vu,d(*),e(*),e2(*),gers(*) real(dp), intent(out) :: wl,wu,w(*),werr(*),work(*) end subroutine dlarrd #else module procedure stdlib${ii}$_dlarrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarrd( range, order, n, vl, vu, il, iu, gers,reltol, d, e, e2, & pivmin, nsplit, isplit,m, w, werr, wl, wu, iblock, indexw,work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: order,range integer(${ik}$), intent(in) :: il,iu,n,nsplit,isplit(*) integer(${ik}$), intent(out) :: info,m,iblock(*),indexw(*),iwork(*) real(sp), intent(in) :: pivmin,reltol,vl,vu,d(*),e(*),e2(*),gers(*) real(sp), intent(out) :: wl,wu,w(*),werr(*),work(*) end subroutine slarrd #else module procedure stdlib${ii}$_slarrd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larrd #:endif #:endfor #:endfor end interface larrd interface larre !! To find the desired eigenvalues of a given real symmetric !! tridiagonal matrix T, LARRE: sets any "small" off-diagonal !! elements to zero, and for each unreduced block T_i, it finds !! (a) a suitable shift at one end of the block's spectrum, !! (b) the base representation, T_i - sigma_i I = L_i D_i L_i^T, and !! (c) eigenvalues of each L_i D_i L_i^T. !! The representations and eigenvalues found are then used by !! DSTEMR to compute the eigenvectors of T. !! The accuracy varies depending on whether bisection is used to !! find a few eigenvalues or the dqds algorithm (subroutine DLASQ2) to !! conpute all and then discard any unwanted one. !! As an added benefit, LARRE also outputs the n !! Gerschgorin intervals for the matrices L_i D_i L_i^T. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarre( range, n, vl, vu, il, iu, d, e, e2,rtol1, rtol2, spltol, & nsplit, isplit, m,w, werr, wgap, iblock, indexw, gers, pivmin,work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: range integer(${ik}$), intent(in) :: il,iu,n integer(${ik}$), intent(out) :: info,m,nsplit,iblock(*),isplit(*),iwork(*),& indexw(*) real(dp), intent(out) :: pivmin,gers(*),w(*),werr(*),wgap(*),work(*) real(dp), intent(in) :: rtol1,rtol2,spltol real(dp), intent(inout) :: vl,vu,d(*),e(*),e2(*) end subroutine dlarre #else module procedure stdlib${ii}$_dlarre #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarre( range, n, vl, vu, il, iu, d, e, e2,rtol1, rtol2, spltol, & nsplit, isplit, m,w, werr, wgap, iblock, indexw, gers, pivmin,work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: range integer(${ik}$), intent(in) :: il,iu,n integer(${ik}$), intent(out) :: info,m,nsplit,iblock(*),isplit(*),iwork(*),& indexw(*) real(sp), intent(out) :: pivmin,gers(*),w(*),werr(*),wgap(*),work(*) real(sp), intent(in) :: rtol1,rtol2,spltol real(sp), intent(inout) :: vl,vu,d(*),e(*),e2(*) end subroutine slarre #else module procedure stdlib${ii}$_slarre #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larre #:endif #:endfor #:endfor end interface larre interface larrf !! Given the initial representation L D L^T and its cluster of close !! eigenvalues (in a relative measure), W( CLSTRT ), W( CLSTRT+1 ), ... !! W( CLEND ), LARRF: finds a new relatively robust representation !! L D L^T - SIGMA I = L(+) D(+) L(+)^T such that at least one of the !! eigenvalues of L(+) D(+) L(+)^T is relatively isolated. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarrf( n, d, l, ld, clstrt, clend,w, wgap, werr,spdiam, clgapl, & clgapr, pivmin, sigma,dplus, lplus, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: clstrt,clend,n integer(${ik}$), intent(out) :: info real(dp), intent(in) :: clgapl,clgapr,pivmin,spdiam,d(*),l(*),ld(*),w(*),werr(& *) real(dp), intent(out) :: sigma,dplus(*),lplus(*),work(*) real(dp), intent(inout) :: wgap(*) end subroutine dlarrf #else module procedure stdlib${ii}$_dlarrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarrf( n, d, l, ld, clstrt, clend,w, wgap, werr,spdiam, clgapl, & clgapr, pivmin, sigma,dplus, lplus, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: clstrt,clend,n integer(${ik}$), intent(out) :: info real(sp), intent(in) :: clgapl,clgapr,pivmin,spdiam,d(*),l(*),ld(*),w(*),werr(& *) real(sp), intent(out) :: sigma,dplus(*),lplus(*),work(*) real(sp), intent(inout) :: wgap(*) end subroutine slarrf #else module procedure stdlib${ii}$_slarrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larrf #:endif #:endfor #:endfor end interface larrf interface larrj !! Given the initial eigenvalue approximations of T, LARRJ: !! does bisection to refine the eigenvalues of T, !! W( IFIRST-OFFSET ) through W( ILAST-OFFSET ), to more accuracy. Initial !! guesses for these eigenvalues are input in W, the corresponding estimate !! of the error in these guesses in WERR. During bisection, intervals !! [left, right] are maintained by storing their mid-points and !! semi-widths in the arrays W and WERR respectively. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarrj( n, d, e2, ifirst, ilast,rtol, offset, w, werr, work, iwork,& pivmin, spdiam, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ifirst,ilast,n,offset integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(in) :: pivmin,rtol,spdiam,d(*),e2(*) real(dp), intent(inout) :: w(*),werr(*) real(dp), intent(out) :: work(*) end subroutine dlarrj #else module procedure stdlib${ii}$_dlarrj #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarrj( n, d, e2, ifirst, ilast,rtol, offset, w, werr, work, iwork,& pivmin, spdiam, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ifirst,ilast,n,offset integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(in) :: pivmin,rtol,spdiam,d(*),e2(*) real(sp), intent(inout) :: w(*),werr(*) real(sp), intent(out) :: work(*) end subroutine slarrj #else module procedure stdlib${ii}$_slarrj #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larrj #:endif #:endfor #:endfor end interface larrj interface larrk !! LARRK computes one eigenvalue of a symmetric tridiagonal !! matrix T to suitable accuracy. This is an auxiliary code to be !! called from DSTEMR. !! To avoid overflow, the matrix must be scaled so that its !! largest element is no greater than overflow**(1/2) * underflow**(1/4) in absolute value, and for greatest !! accuracy, it should not be much smaller than that. !! See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal !! Matrix", Report CS41, Computer Science Dept., Stanford !! University, July 21, 1966. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarrk( n, iw, gl, gu,d, e2, pivmin, reltol, w, werr, info) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: iw,n real(dp), intent(in) :: pivmin,reltol,gl,gu,d(*),e2(*) real(dp), intent(out) :: w,werr end subroutine dlarrk #else module procedure stdlib${ii}$_dlarrk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarrk( n, iw, gl, gu,d, e2, pivmin, reltol, w, werr, info) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: iw,n real(sp), intent(in) :: pivmin,reltol,gl,gu,d(*),e2(*) real(sp), intent(out) :: w,werr end subroutine slarrk #else module procedure stdlib${ii}$_slarrk #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larrk #:endif #:endfor #:endfor end interface larrk interface larrr !! Perform tests to decide whether the symmetric tridiagonal matrix T !! warrants expensive computations which guarantee high relative accuracy !! in the eigenvalues. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarrr( n, d, e, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info real(dp), intent(in) :: d(*) real(dp), intent(inout) :: e(*) end subroutine dlarrr #else module procedure stdlib${ii}$_dlarrr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarrr( n, d, e, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info real(sp), intent(in) :: d(*) real(sp), intent(inout) :: e(*) end subroutine slarrr #else module procedure stdlib${ii}$_slarrr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larrr #:endif #:endfor #:endfor end interface larrr interface larrv !! LARRV computes the eigenvectors of the tridiagonal matrix !! T = L D L**T given L, D and APPROXIMATIONS to the eigenvalues of L D L**T. !! The input eigenvalues should have been computed by SLARRE. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarrv( n, vl, vu, d, l, pivmin,isplit, m, dol, dou, minrgp,rtol1, & rtol2, w, werr, wgap,iblock, indexw, gers, z, ldz, isuppz,work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: dol,dou,ldz,m,n,iblock(*),indexw(*),isplit(*) integer(${ik}$), intent(out) :: info,isuppz(*),iwork(*) real(sp), intent(in) :: minrgp,pivmin,vl,vu,gers(*) real(sp), intent(inout) :: rtol1,rtol2,d(*),l(*),w(*),werr(*),wgap(*) real(sp), intent(out) :: work(*) complex(sp), intent(out) :: z(ldz,*) end subroutine clarrv #else module procedure stdlib${ii}$_clarrv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarrv( n, vl, vu, d, l, pivmin,isplit, m, dol, dou, minrgp,rtol1, & rtol2, w, werr, wgap,iblock, indexw, gers, z, ldz, isuppz,work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: dol,dou,ldz,m,n,iblock(*),indexw(*),isplit(*) integer(${ik}$), intent(out) :: info,isuppz(*),iwork(*) real(dp), intent(in) :: minrgp,pivmin,vl,vu,gers(*) real(dp), intent(inout) :: rtol1,rtol2,d(*),l(*),w(*),werr(*),wgap(*) real(dp), intent(out) :: work(*),z(ldz,*) end subroutine dlarrv #else module procedure stdlib${ii}$_dlarrv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarrv( n, vl, vu, d, l, pivmin,isplit, m, dol, dou, minrgp,rtol1, & rtol2, w, werr, wgap,iblock, indexw, gers, z, ldz, isuppz,work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: dol,dou,ldz,m,n,iblock(*),indexw(*),isplit(*) integer(${ik}$), intent(out) :: info,isuppz(*),iwork(*) real(sp), intent(in) :: minrgp,pivmin,vl,vu,gers(*) real(sp), intent(inout) :: rtol1,rtol2,d(*),l(*),w(*),werr(*),wgap(*) real(sp), intent(out) :: work(*),z(ldz,*) end subroutine slarrv #else module procedure stdlib${ii}$_slarrv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarrv( n, vl, vu, d, l, pivmin,isplit, m, dol, dou, minrgp,rtol1, & rtol2, w, werr, wgap,iblock, indexw, gers, z, ldz, isuppz,work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: dol,dou,ldz,m,n,iblock(*),indexw(*),isplit(*) integer(${ik}$), intent(out) :: info,isuppz(*),iwork(*) real(dp), intent(in) :: minrgp,pivmin,vl,vu,gers(*) real(dp), intent(inout) :: rtol1,rtol2,d(*),l(*),w(*),werr(*),wgap(*) real(dp), intent(out) :: work(*) complex(dp), intent(out) :: z(ldz,*) end subroutine zlarrv #else module procedure stdlib${ii}$_zlarrv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larrv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larrv #:endif #:endfor #:endfor end interface larrv interface lartg !! LARTG generates a plane rotation so that !! [ C S ] . [ F ] = [ R ] !! [ -conjg(S) C ] [ G ] [ 0 ] !! where C is real and C**2 + |S|**2 = 1. !! The mathematical formulas used for C and S are !! sgn(x) = { x / |x|, x != 0 !! { 1, x = 0 !! R = sgn(F) * sqrt(|F|**2 + |G|**2) !! C = |F| / sqrt(|F|**2 + |G|**2) !! S = sgn(F) * conjg(G) / sqrt(|F|**2 + |G|**2) !! When F and G are real, the formulas simplify to C = F/R and !! S = G/R, and the returned values of C, S, and R should be !! identical to those returned by LARTG. !! The algorithm used to compute these quantities incorporates scaling !! to avoid overflow or underflow in computing the square root of the !! sum of squares. !! This is a faster version of the BLAS1 routine CROTG, except for !! the following differences: !! F and G are unchanged on return. !! If G=0, then C=1 and S=0. !! If F=0, then C=0 and S is chosen so that R is real. !! Below, wp=>sp stands for single precision from LA_CONSTANTS module. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #:for rk,rt,ri in RC_KINDS_TYPES #:if rk in ["sp","dp"] #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ${ri}$lartg( f, g, c, s, r ) import sp,dp,qp,${ik}$,lk implicit none real(${rk}$), intent(out) :: c ${rt}$, intent(in) :: f,g ${rt}$, intent(out) :: r,s end subroutine ${ri}$lartg #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_${ri}$lartg #:endif #endif #:elif not 'ilp64' in ik module procedure stdlib${ii}$_${ri}$lartg #:endif #:endfor #:endfor end interface lartg interface lartgp !! LARTGP generates a plane rotation so that !! [ CS SN ] . [ F ] = [ R ] where CS**2 + SN**2 = 1. !! [ -SN CS ] [ G ] [ 0 ] !! This is a slower, more accurate version of the Level 1 BLAS routine DROTG, !! with the following other differences: !! F and G are unchanged on return. !! If G=0, then CS=(+/-)1 and SN=0. !! If F=0 and (G .ne. 0), then CS=0 and SN=(+/-)1. !! The sign is chosen so that R >= 0. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #:for rk,rt,ri in REAL_KINDS_TYPES #:if rk in ["sp","dp"] #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ${ri}$lartgp( f, g, cs, sn, r ) import sp,dp,qp,${ik}$,lk implicit none ${rt}$, intent(out) :: cs,r,sn ${rt}$, intent(in) :: f,g end subroutine ${ri}$lartgp #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_${ri}$lartgp #:endif #endif #:elif not 'ilp64' in ik module procedure stdlib${ii}$_${ri}$lartgp #:endif #:endfor #:endfor end interface lartgp interface lartgs !! LARTGS generates a plane rotation designed to introduce a bulge in !! Golub-Reinsch-style implicit QR iteration for the bidiagonal SVD !! problem. X and Y are the top-row entries, and SIGMA is the shift. !! The computed CS and SN define a plane rotation satisfying !! [ CS SN ] . [ X^2 - SIGMA ] = [ R ], !! [ -SN CS ] [ X * Y ] [ 0 ] !! with R nonnegative. If X^2 - SIGMA and X * Y are 0, then the !! rotation is by PI/2. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #:for rk,rt,ri in REAL_KINDS_TYPES #:if rk in ["sp","dp"] #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ${ri}$lartgs( x, y, sigma, cs, sn ) import sp,dp,qp,${ik}$,lk implicit none ${rt}$, intent(out) :: cs,sn ${rt}$, intent(in) :: sigma,x,y end subroutine ${ri}$lartgs #:if not 'ilp64' in ik #else module procedure stdlib${ii}$_${ri}$lartgs #:endif #endif #:elif not 'ilp64' in ik module procedure stdlib${ii}$_${ri}$lartgs #:endif #:endfor #:endfor end interface lartgs interface lartv !! LARTV applies a vector of complex plane rotations with real cosines !! to elements of the complex vectors x and y. For i = 1,2,...,n !! ( x(i) ) := ( c(i) s(i) ) ( x(i) ) !! ( y(i) ) ( -conjg(s(i)) c(i) ) ( y(i) ) #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clartv( n, x, incx, y, incy, c, s, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,incy,n real(sp), intent(in) :: c(*) complex(sp), intent(in) :: s(*) complex(sp), intent(inout) :: x(*),y(*) end subroutine clartv #else module procedure stdlib${ii}$_clartv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlartv( n, x, incx, y, incy, c, s, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,incy,n real(dp), intent(in) :: c(*),s(*) real(dp), intent(inout) :: x(*),y(*) end subroutine dlartv #else module procedure stdlib${ii}$_dlartv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slartv( n, x, incx, y, incy, c, s, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,incy,n real(sp), intent(in) :: c(*),s(*) real(sp), intent(inout) :: x(*),y(*) end subroutine slartv #else module procedure stdlib${ii}$_slartv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlartv( n, x, incx, y, incy, c, s, incc ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incc,incx,incy,n real(dp), intent(in) :: c(*) complex(dp), intent(in) :: s(*) complex(dp), intent(inout) :: x(*),y(*) end subroutine zlartv #else module procedure stdlib${ii}$_zlartv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lartv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lartv #:endif #:endfor #:endfor end interface lartv interface laruv !! LARUV returns a vector of n random real numbers from a uniform (0,1) !! distribution (n <= 128). !! This is an auxiliary routine called by DLARNV and ZLARNV. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaruv( iseed, n, x ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n integer(${ik}$), intent(inout) :: iseed(4) real(dp), intent(out) :: x(n) end subroutine dlaruv #else module procedure stdlib${ii}$_dlaruv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaruv( iseed, n, x ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: n integer(${ik}$), intent(inout) :: iseed(4) real(sp), intent(out) :: x(n) end subroutine slaruv #else module procedure stdlib${ii}$_slaruv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laruv #:endif #:endfor #:endfor end interface laruv interface larz !! LARZ applies a complex elementary reflector H to a complex !! M-by-N matrix C, from either the left or the right. H is represented !! in the form !! H = I - tau * v * v**H !! where tau is a complex scalar and v is a complex vector. !! If tau = 0, then H is taken to be the unit matrix. !! To apply H**H (the conjugate transpose of H), supply conjg(tau) instead !! tau. !! H is a product of k elementary reflectors as returned by CTZRZF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarz( side, m, n, l, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side integer(${ik}$), intent(in) :: incv,l,ldc,m,n complex(sp), intent(in) :: tau,v(*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine clarz #else module procedure stdlib${ii}$_clarz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarz( side, m, n, l, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side integer(${ik}$), intent(in) :: incv,l,ldc,m,n real(dp), intent(in) :: tau,v(*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine dlarz #else module procedure stdlib${ii}$_dlarz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarz( side, m, n, l, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side integer(${ik}$), intent(in) :: incv,l,ldc,m,n real(sp), intent(in) :: tau,v(*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine slarz #else module procedure stdlib${ii}$_slarz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarz( side, m, n, l, v, incv, tau, c, ldc, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side integer(${ik}$), intent(in) :: incv,l,ldc,m,n complex(dp), intent(in) :: tau,v(*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine zlarz #else module procedure stdlib${ii}$_zlarz #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larz #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larz #:endif #:endfor #:endfor end interface larz interface larzb !! LARZB applies a complex block reflector H or its transpose H**H !! to a complex distributed M-by-N C from the left or the right. !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & ldc, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,l,ldc,ldt,ldv,ldwork,m,n complex(sp), intent(inout) :: c(ldc,*),t(ldt,*),v(ldv,*) complex(sp), intent(out) :: work(ldwork,*) end subroutine clarzb #else module procedure stdlib${ii}$_clarzb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & ldc, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,l,ldc,ldt,ldv,ldwork,m,n real(dp), intent(inout) :: c(ldc,*),t(ldt,*),v(ldv,*) real(dp), intent(out) :: work(ldwork,*) end subroutine dlarzb #else module procedure stdlib${ii}$_dlarzb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & ldc, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,l,ldc,ldt,ldv,ldwork,m,n real(sp), intent(inout) :: c(ldc,*),t(ldt,*),v(ldv,*) real(sp), intent(out) :: work(ldwork,*) end subroutine slarzb #else module procedure stdlib${ii}$_slarzb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & ldc, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,l,ldc,ldt,ldv,ldwork,m,n complex(dp), intent(inout) :: c(ldc,*),t(ldt,*),v(ldv,*) complex(dp), intent(out) :: work(ldwork,*) end subroutine zlarzb #else module procedure stdlib${ii}$_zlarzb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larzb #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larzb #:endif #:endfor #:endfor end interface larzb interface larzt !! LARZT forms the triangular factor T of a complex block reflector !! H of order > n, which is defined as a product of k elementary !! reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**H !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**H * T * V !! Currently, only STOREV = 'R' and DIRECT = 'B' are supported. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clarzt( direct, storev, n, k, v, ldv, tau, t, ldt ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,storev integer(${ik}$), intent(in) :: k,ldt,ldv,n complex(sp), intent(out) :: t(ldt,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(inout) :: v(ldv,*) end subroutine clarzt #else module procedure stdlib${ii}$_clarzt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlarzt( direct, storev, n, k, v, ldv, tau, t, ldt ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,storev integer(${ik}$), intent(in) :: k,ldt,ldv,n real(dp), intent(out) :: t(ldt,*) real(dp), intent(in) :: tau(*) real(dp), intent(inout) :: v(ldv,*) end subroutine dlarzt #else module procedure stdlib${ii}$_dlarzt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slarzt( direct, storev, n, k, v, ldv, tau, t, ldt ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,storev integer(${ik}$), intent(in) :: k,ldt,ldv,n real(sp), intent(out) :: t(ldt,*) real(sp), intent(in) :: tau(*) real(sp), intent(inout) :: v(ldv,*) end subroutine slarzt #else module procedure stdlib${ii}$_slarzt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlarzt( direct, storev, n, k, v, ldv, tau, t, ldt ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,storev integer(${ik}$), intent(in) :: k,ldt,ldv,n complex(dp), intent(out) :: t(ldt,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(inout) :: v(ldv,*) end subroutine zlarzt #else module procedure stdlib${ii}$_zlarzt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larzt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$larzt #:endif #:endfor #:endfor end interface larzt interface lascl !! LASCL multiplies the M by N complex matrix A by the real scalar !! CTO/CFROM. This is done without over/underflow as long as the final !! result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that !! A may be full, upper triangular, lower triangular, upper Hessenberg, !! or banded. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl,ku,lda,m,n real(sp), intent(in) :: cfrom,cto complex(sp), intent(inout) :: a(lda,*) end subroutine clascl #else module procedure stdlib${ii}$_clascl #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl,ku,lda,m,n real(dp), intent(in) :: cfrom,cto real(dp), intent(inout) :: a(lda,*) end subroutine dlascl #else module procedure stdlib${ii}$_dlascl #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl,ku,lda,m,n real(sp), intent(in) :: cfrom,cto real(sp), intent(inout) :: a(lda,*) end subroutine slascl #else module procedure stdlib${ii}$_slascl #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl,ku,lda,m,n real(dp), intent(in) :: cfrom,cto complex(dp), intent(inout) :: a(lda,*) end subroutine zlascl #else module procedure stdlib${ii}$_zlascl #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lascl #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lascl #:endif #:endfor #:endfor end interface lascl interface lasd0 !! Using a divide and conquer approach, LASD0: computes the singular !! value decomposition (SVD) of a real upper bidiagonal N-by-M !! matrix B with diagonal D and offdiagonal E, where M = N + SQRE. !! The algorithm computes orthogonal matrices U and VT such that !! B = U * S * VT. The singular values S are overwritten on D. !! A related subroutine, DLASDA, computes only the singular values, !! and optionally, the singular vectors in compact form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasd0( n, sqre, d, e, u, ldu, vt, ldvt, smlsiz, iwork,work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu,ldvt,n,smlsiz,sqre real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: u(ldu,*),vt(ldvt,*),work(*) end subroutine dlasd0 #else module procedure stdlib${ii}$_dlasd0 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasd0( n, sqre, d, e, u, ldu, vt, ldvt, smlsiz, iwork,work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu,ldvt,n,smlsiz,sqre real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: u(ldu,*),vt(ldvt,*),work(*) end subroutine slasd0 #else module procedure stdlib${ii}$_slasd0 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasd0 #:endif #:endfor #:endfor end interface lasd0 interface lasd1 !! LASD1 computes the SVD of an upper bidiagonal N-by-M matrix B, !! where N = NL + NR + 1 and M = N + SQRE. LASD1 is called from DLASD0. !! A related subroutine DLASD7 handles the case in which the singular !! values (and the singular vectors in factored form) are desired. !! LASD1 computes the SVD as follows: !! ( D1(in) 0 0 0 ) !! B = U(in) * ( Z1**T a Z2**T b ) * VT(in) !! ( 0 0 D2(in) 0 ) !! = U(out) * ( D(out) 0) * VT(out) !! where Z**T = (Z1**T a Z2**T b) = u**T VT**T, and u is a vector of dimension M !! with ALPHA and BETA in the NL+1 and NL+2 th entries and zeros !! elsewhere; and the entry b is empty if SQRE = 0. !! The left singular vectors of the original matrix are stored in U, and !! the transpose of the right singular vectors are stored in VT, and the !! singular values are in D. The algorithm consists of three stages: !! The first stage consists of deflating the size of the problem !! when there are multiple singular values or when there are zeros in !! the Z vector. For each such occurrence the dimension of the !! secular equation problem is reduced by one. This stage is !! performed by the routine DLASD2. !! The second stage consists of calculating the updated !! singular values. This is done by finding the square roots of the !! roots of the secular equation via the routine DLASD4 (as called !! by DLASD3). This routine also calculates the singular vectors of !! the current problem. !! The final stage consists of computing the updated singular vectors !! directly using the updated singular values. The singular vectors !! for the current problem are multiplied with the singular vectors !! from the overall problem. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasd1( nl, nr, sqre, d, alpha, beta, u, ldu, vt, ldvt,idxq, iwork,& work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu,ldvt,nl,nr,sqre real(dp), intent(inout) :: alpha,beta,d(*),u(ldu,*),vt(ldvt,*) integer(${ik}$), intent(inout) :: idxq(*) real(dp), intent(out) :: work(*) end subroutine dlasd1 #else module procedure stdlib${ii}$_dlasd1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasd1( nl, nr, sqre, d, alpha, beta, u, ldu, vt, ldvt,idxq, iwork,& work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu,ldvt,nl,nr,sqre real(sp), intent(inout) :: alpha,beta,d(*),u(ldu,*),vt(ldvt,*) integer(${ik}$), intent(inout) :: idxq(*) real(sp), intent(out) :: work(*) end subroutine slasd1 #else module procedure stdlib${ii}$_slasd1 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasd1 #:endif #:endfor #:endfor end interface lasd1 interface lasd4 !! This subroutine computes the square root of the I-th updated !! eigenvalue of a positive symmetric rank-one modification to !! a positive diagonal matrix whose entries are given as the squares !! of the corresponding entries in the array d, and that !! 0 <= D(i) < D(j) for i < j !! and that RHO > 0. This is arranged by the calling routine, and is !! no loss in generality. The rank-one modified system is thus !! diag( D ) * diag( D ) + RHO * Z * Z_transpose. !! where we assume the Euclidean norm of Z is 1. !! The method consists of approximating the rational functions in the !! secular equation by simpler interpolating rational functions. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasd4( n, i, d, z, delta, rho, sigma, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i,n integer(${ik}$), intent(out) :: info real(dp), intent(in) :: rho,d(*),z(*) real(dp), intent(out) :: sigma,delta(*),work(*) end subroutine dlasd4 #else module procedure stdlib${ii}$_dlasd4 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasd4( n, i, d, z, delta, rho, sigma, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i,n integer(${ik}$), intent(out) :: info real(sp), intent(in) :: rho,d(*),z(*) real(sp), intent(out) :: sigma,delta(*),work(*) end subroutine slasd4 #else module procedure stdlib${ii}$_slasd4 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasd4 #:endif #:endfor #:endfor end interface lasd4 interface lasd5 !! This subroutine computes the square root of the I-th eigenvalue !! of a positive symmetric rank-one modification of a 2-by-2 diagonal !! matrix !! diag( D ) * diag( D ) + RHO * Z * transpose(Z) . !! The diagonal entries in the array D are assumed to satisfy !! 0 <= D(i) < D(j) for i < j . !! We also assume RHO > 0 and that the Euclidean norm of the vector !! Z is one. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasd5( i, d, z, delta, rho, dsigma, work ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i real(dp), intent(out) :: dsigma,delta(2),work(2) real(dp), intent(in) :: rho,d(2),z(2) end subroutine dlasd5 #else module procedure stdlib${ii}$_dlasd5 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasd5( i, d, z, delta, rho, dsigma, work ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i real(sp), intent(out) :: dsigma,delta(2),work(2) real(sp), intent(in) :: rho,d(2),z(2) end subroutine slasd5 #else module procedure stdlib${ii}$_slasd5 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasd5 #:endif #:endfor #:endfor end interface lasd5 interface lasd6 !! LASD6 computes the SVD of an updated upper bidiagonal matrix B !! obtained by merging two smaller ones by appending a row. This !! routine is used only for the problem which requires all singular !! values and optionally singular vector matrices in factored form. !! B is an N-by-M matrix with N = NL + NR + 1 and M = N + SQRE. !! A related subroutine, DLASD1, handles the case in which all singular !! values and singular vectors of the bidiagonal matrix are desired. !! LASD6 computes the SVD as follows: !! ( D1(in) 0 0 0 ) !! B = U(in) * ( Z1**T a Z2**T b ) * VT(in) !! ( 0 0 D2(in) 0 ) !! = U(out) * ( D(out) 0) * VT(out) !! where Z**T = (Z1**T a Z2**T b) = u**T VT**T, and u is a vector of dimension M !! with ALPHA and BETA in the NL+1 and NL+2 th entries and zeros !! elsewhere; and the entry b is empty if SQRE = 0. !! The singular values of B can be computed using D1, D2, the first !! components of all the right singular vectors of the lower block, and !! the last components of all the right singular vectors of the upper !! block. These components are stored and updated in VF and VL, !! respectively, in LASD6. Hence U and VT are not explicitly !! referenced. !! The singular values are stored in D. The algorithm consists of two !! stages: !! The first stage consists of deflating the size of the problem !! when there are multiple singular values or if there is a zero !! in the Z vector. For each such occurrence the dimension of the !! secular equation problem is reduced by one. This stage is !! performed by the routine DLASD7. !! The second stage consists of calculating the updated !! singular values. This is done by finding the roots of the !! secular equation via the routine DLASD4 (as called by DLASD8). !! This routine also updates VF and VL and computes the distances !! between the updated singular values and the old singular !! values. !! LASD6 is called from DLASDA. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasd6( icompq, nl, nr, sqre, d, vf, vl, alpha, beta,idxq, perm, & givptr, givcol, ldgcol, givnum,ldgnum, poles, difl, difr, z, k, c, s, work,iwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: givptr,info,k,givcol(ldgcol,*),iwork(*),perm(*) integer(${ik}$), intent(in) :: icompq,ldgcol,ldgnum,nl,nr,sqre real(dp), intent(inout) :: alpha,beta,d(*),vf(*),vl(*) real(dp), intent(out) :: c,s,difl(*),difr(*),givnum(ldgnum,*),poles(ldgnum,*),& work(*),z(*) integer(${ik}$), intent(inout) :: idxq(*) end subroutine dlasd6 #else module procedure stdlib${ii}$_dlasd6 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasd6( icompq, nl, nr, sqre, d, vf, vl, alpha, beta,idxq, perm, & givptr, givcol, ldgcol, givnum,ldgnum, poles, difl, difr, z, k, c, s, work,iwork, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: givptr,info,k,givcol(ldgcol,*),iwork(*),perm(*) integer(${ik}$), intent(in) :: icompq,ldgcol,ldgnum,nl,nr,sqre real(sp), intent(inout) :: alpha,beta,d(*),vf(*),vl(*) real(sp), intent(out) :: c,s,difl(*),difr(*),givnum(ldgnum,*),poles(ldgnum,*),& work(*),z(*) integer(${ik}$), intent(inout) :: idxq(*) end subroutine slasd6 #else module procedure stdlib${ii}$_slasd6 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasd6 #:endif #:endfor #:endfor end interface lasd6 interface lasd7 !! LASD7 merges the two sets of singular values together into a single !! sorted set. Then it tries to deflate the size of the problem. There !! are two ways in which deflation can occur: when two or more singular !! values are close together or if there is a tiny entry in the Z !! vector. For each such occurrence the order of the related !! secular equation problem is reduced by one. !! LASD7 is called from DLASD6. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasd7( icompq, nl, nr, sqre, k, d, z, zw, vf, vfw, vl,vlw, alpha, & beta, dsigma, idx, idxp, idxq,perm, givptr, givcol, ldgcol, givnum, ldgnum,c, s, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: givptr,info,k,givcol(ldgcol,*),idx(*),idxp(*),& perm(*) integer(${ik}$), intent(in) :: icompq,ldgcol,ldgnum,nl,nr,sqre real(dp), intent(in) :: alpha,beta real(dp), intent(out) :: c,s,dsigma(*),givnum(ldgnum,*),vfw(*),vlw(*),z(*),zw(& *) integer(${ik}$), intent(inout) :: idxq(*) real(dp), intent(inout) :: d(*),vf(*),vl(*) end subroutine dlasd7 #else module procedure stdlib${ii}$_dlasd7 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasd7( icompq, nl, nr, sqre, k, d, z, zw, vf, vfw, vl,vlw, alpha, & beta, dsigma, idx, idxp, idxq,perm, givptr, givcol, ldgcol, givnum, ldgnum,c, s, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: givptr,info,k,givcol(ldgcol,*),idx(*),idxp(*),& perm(*) integer(${ik}$), intent(in) :: icompq,ldgcol,ldgnum,nl,nr,sqre real(sp), intent(in) :: alpha,beta real(sp), intent(out) :: c,s,dsigma(*),givnum(ldgnum,*),vfw(*),vlw(*),z(*),zw(& *) integer(${ik}$), intent(inout) :: idxq(*) real(sp), intent(inout) :: d(*),vf(*),vl(*) end subroutine slasd7 #else module procedure stdlib${ii}$_slasd7 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasd7 #:endif #:endfor #:endfor end interface lasd7 interface lasd8 !! LASD8 finds the square roots of the roots of the secular equation, !! as defined by the values in DSIGMA and Z. It makes the appropriate !! calls to DLASD4, and stores, for each element in D, the distance !! to its two nearest poles (elements in DSIGMA). It also updates !! the arrays VF and VL, the first and last components of all the !! right singular vectors of the original bidiagonal matrix. !! LASD8 is called from DLASD6. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasd8( icompq, k, d, z, vf, vl, difl, difr, lddifr,dsigma, work, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: icompq,k,lddifr integer(${ik}$), intent(out) :: info real(dp), intent(out) :: d(*),difl(*),difr(lddifr,*),work(*) real(dp), intent(inout) :: dsigma(*),vf(*),vl(*),z(*) end subroutine dlasd8 #else module procedure stdlib${ii}$_dlasd8 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasd8( icompq, k, d, z, vf, vl, difl, difr, lddifr,dsigma, work, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: icompq,k,lddifr integer(${ik}$), intent(out) :: info real(sp), intent(out) :: d(*),difl(*),difr(lddifr,*),work(*) real(sp), intent(inout) :: dsigma(*),vf(*),vl(*),z(*) end subroutine slasd8 #else module procedure stdlib${ii}$_slasd8 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasd8 #:endif #:endfor #:endfor end interface lasd8 interface lasda !! Using a divide and conquer approach, LASDA: computes the singular !! value decomposition (SVD) of a real upper bidiagonal N-by-M matrix !! B with diagonal D and offdiagonal E, where M = N + SQRE. The !! algorithm computes the singular values in the SVD B = U * S * VT. !! The orthogonal matrices U and VT are optionally computed in !! compact form. !! A related subroutine, DLASD0, computes the singular values and !! the singular vectors in explicit form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasda( icompq, smlsiz, n, sqre, d, e, u, ldu, vt, k,difl, difr, z,& poles, givptr, givcol, ldgcol,perm, givnum, c, s, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: icompq,ldgcol,ldu,n,smlsiz,sqre integer(${ik}$), intent(out) :: info,givcol(ldgcol,*),givptr(*),iwork(*),k(*),& perm(ldgcol,*) real(dp), intent(out) :: c(*),difl(ldu,*),difr(ldu,*),givnum(ldu,*),poles(ldu,& *),s(*),u(ldu,*),vt(ldu,*),work(*),z(ldu,*) real(dp), intent(inout) :: d(*),e(*) end subroutine dlasda #else module procedure stdlib${ii}$_dlasda #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasda( icompq, smlsiz, n, sqre, d, e, u, ldu, vt, k,difl, difr, z,& poles, givptr, givcol, ldgcol,perm, givnum, c, s, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: icompq,ldgcol,ldu,n,smlsiz,sqre integer(${ik}$), intent(out) :: info,givcol(ldgcol,*),givptr(*),iwork(*),k(*),& perm(ldgcol,*) real(sp), intent(out) :: c(*),difl(ldu,*),difr(ldu,*),givnum(ldu,*),poles(ldu,& *),s(*),u(ldu,*),vt(ldu,*),work(*),z(ldu,*) real(sp), intent(inout) :: d(*),e(*) end subroutine slasda #else module procedure stdlib${ii}$_slasda #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasda #:endif #:endfor #:endfor end interface lasda interface lasdq !! LASDQ computes the singular value decomposition (SVD) of a real !! (upper or lower) bidiagonal matrix with diagonal D and offdiagonal !! E, accumulating the transformations if desired. Letting B denote !! the input bidiagonal matrix, the algorithm computes orthogonal !! matrices Q and P such that B = Q * S * P**T (P**T denotes the transpose !! of P). The singular values S are overwritten on D. !! The input matrix U is changed to U * Q if desired. !! The input matrix VT is changed to P**T * VT if desired. !! The input matrix C is changed to Q**T * C if desired. !! See "Computing Small Singular Values of Bidiagonal Matrices With !! Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan, !! LAPACK Working Note #3, for a detailed description of the algorithm. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasdq( uplo, sqre, n, ncvt, nru, ncc, d, e, vt, ldvt,u, ldu, c, & ldc, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc,ldu,ldvt,n,ncc,ncvt,nru,sqre real(dp), intent(inout) :: c(ldc,*),d(*),e(*),u(ldu,*),vt(ldvt,*) real(dp), intent(out) :: work(*) end subroutine dlasdq #else module procedure stdlib${ii}$_dlasdq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasdq( uplo, sqre, n, ncvt, nru, ncc, d, e, vt, ldvt,u, ldu, c, & ldc, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc,ldu,ldvt,n,ncc,ncvt,nru,sqre real(sp), intent(inout) :: c(ldc,*),d(*),e(*),u(ldu,*),vt(ldvt,*) real(sp), intent(out) :: work(*) end subroutine slasdq #else module procedure stdlib${ii}$_slasdq #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasdq #:endif #:endfor #:endfor end interface lasdq interface laset !! LASET initializes a 2-D array A to BETA on the diagonal and !! ALPHA on the offdiagonals. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claset( uplo, m, n, alpha, beta, a, lda ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,m,n complex(sp), intent(in) :: alpha,beta complex(sp), intent(out) :: a(lda,*) end subroutine claset #else module procedure stdlib${ii}$_claset #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaset( uplo, m, n, alpha, beta, a, lda ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(in) :: alpha,beta real(dp), intent(out) :: a(lda,*) end subroutine dlaset #else module procedure stdlib${ii}$_dlaset #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaset( uplo, m, n, alpha, beta, a, lda ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(in) :: alpha,beta real(sp), intent(out) :: a(lda,*) end subroutine slaset #else module procedure stdlib${ii}$_slaset #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaset( uplo, m, n, alpha, beta, a, lda ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,m,n complex(dp), intent(in) :: alpha,beta complex(dp), intent(out) :: a(lda,*) end subroutine zlaset #else module procedure stdlib${ii}$_zlaset #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laset #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laset #:endif #:endfor #:endfor end interface laset interface lasq1 !! LASQ1 computes the singular values of a real N-by-N bidiagonal !! matrix with diagonal D and off-diagonal E. The singular values !! are computed to high relative accuracy, in the absence of !! denormalization, underflow and overflow. The algorithm was first !! presented in !! "Accurate singular values and differential qd algorithms" by K. V. !! Fernando and B. N. Parlett, Numer. Math., Vol-67, No. 2, pp. 191-230, !! 1994, !! and the present implementation is described in "An implementation of !! the dqds Algorithm (Positive Case)", LAPACK Working Note. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasq1( n, d, e, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: work(*) end subroutine dlasq1 #else module procedure stdlib${ii}$_dlasq1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasq1( n, d, e, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: work(*) end subroutine slasq1 #else module procedure stdlib${ii}$_slasq1 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasq1 #:endif #:endfor #:endfor end interface lasq1 interface lasq4 !! LASQ4 computes an approximation TAU to the smallest eigenvalue !! using values of d from the previous transform. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasq4( i0, n0, z, pp, n0in, dmin, dmin1, dmin2, dn,dn1, dn2, tau, & ttype, g ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i0,n0,n0in,pp integer(${ik}$), intent(out) :: ttype real(dp), intent(in) :: dmin,dmin1,dmin2,dn,dn1,dn2,z(*) real(dp), intent(inout) :: g real(dp), intent(out) :: tau end subroutine dlasq4 #else module procedure stdlib${ii}$_dlasq4 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasq4( i0, n0, z, pp, n0in, dmin, dmin1, dmin2, dn,dn1, dn2, tau, & ttype, g ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i0,n0,n0in,pp integer(${ik}$), intent(out) :: ttype real(sp), intent(in) :: dmin,dmin1,dmin2,dn,dn1,dn2,z(*) real(sp), intent(inout) :: g real(sp), intent(out) :: tau end subroutine slasq4 #else module procedure stdlib${ii}$_slasq4 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasq4 #:endif #:endfor #:endfor end interface lasq4 interface lasq5 !! LASQ5 computes one dqds transform in ping-pong form, one !! version for IEEE machines another for non IEEE machines. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasq5( i0, n0, z, pp, tau, sigma, dmin, dmin1, dmin2,dn, dnm1, & dnm2, ieee, eps ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: ieee integer(${ik}$), intent(in) :: i0,n0,pp real(dp), intent(out) :: dmin,dmin1,dmin2,dn,dnm1,dnm2 real(dp), intent(inout) :: tau,z(*) real(dp), intent(in) :: sigma,eps end subroutine dlasq5 #else module procedure stdlib${ii}$_dlasq5 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasq5( i0, n0, z, pp, tau, sigma, dmin, dmin1, dmin2,dn, dnm1, & dnm2, ieee, eps ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: ieee integer(${ik}$), intent(in) :: i0,n0,pp real(sp), intent(out) :: dmin,dmin1,dmin2,dn,dnm1,dnm2 real(sp), intent(inout) :: tau,z(*) real(sp), intent(in) :: sigma,eps end subroutine slasq5 #else module procedure stdlib${ii}$_slasq5 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasq5 #:endif #:endfor #:endfor end interface lasq5 interface lasq6 !! LASQ6 computes one dqd (shift equal to zero) transform in !! ping-pong form, with protection against underflow and overflow. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasq6( i0, n0, z, pp, dmin, dmin1, dmin2, dn,dnm1, dnm2 ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i0,n0,pp real(dp), intent(out) :: dmin,dmin1,dmin2,dn,dnm1,dnm2 real(dp), intent(inout) :: z(*) end subroutine dlasq6 #else module procedure stdlib${ii}$_dlasq6 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasq6( i0, n0, z, pp, dmin, dmin1, dmin2, dn,dnm1, dnm2 ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: i0,n0,pp real(sp), intent(out) :: dmin,dmin1,dmin2,dn,dnm1,dnm2 real(sp), intent(inout) :: z(*) end subroutine slasq6 #else module procedure stdlib${ii}$_slasq6 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasq6 #:endif #:endfor #:endfor end interface lasq6 interface lasr !! LASR applies a sequence of real plane rotations to a complex matrix !! A, from either the left or the right. !! When SIDE = 'L', the transformation takes the form !! A := P*A !! and when SIDE = 'R', the transformation takes the form !! A := A*P**T !! where P is an orthogonal matrix consisting of a sequence of z plane !! rotations, with z = M when SIDE = 'L' and z = N when SIDE = 'R', !! and P**T is the transpose of P. !! When DIRECT = 'F' (Forward sequence), then !! P = P(z-1) * ... * P(2) * P(1) !! and when DIRECT = 'B' (Backward sequence), then !! P = P(1) * P(2) * ... * P(z-1) !! where P(k) is a plane rotation matrix defined by the 2-by-2 rotation !! R(k) = ( c(k) s(k) ) !! = ( -s(k) c(k) ). !! When PIVOT = 'V' (Variable pivot), the rotation is performed !! for the plane (k,k+1), i.e., P(k) has the form !! P(k) = ( 1 ) !! ( ... ) !! ( 1 ) !! ( c(k) s(k) ) !! ( -s(k) c(k) ) !! ( 1 ) !! ( ... ) !! ( 1 ) !! where R(k) appears as a rank-2 modification to the identity matrix in !! rows and columns k and k+1. !! When PIVOT = 'T' (Top pivot), the rotation is performed for the !! plane (1,k+1), so P(k) has the form !! P(k) = ( c(k) s(k) ) !! ( 1 ) !! ( ... ) !! ( 1 ) !! ( -s(k) c(k) ) !! ( 1 ) !! ( ... ) !! ( 1 ) !! where R(k) appears in rows and columns 1 and k+1. !! Similarly, when PIVOT = 'B' (Bottom pivot), the rotation is !! performed for the plane (k,z), giving P(k) the form !! P(k) = ( 1 ) !! ( ... ) !! ( 1 ) !! ( c(k) s(k) ) !! ( 1 ) !! ( ... ) !! ( 1 ) !! ( -s(k) c(k) ) !! where R(k) appears in rows and columns k and z. The rotations are !! performed without ever forming P(k) explicitly. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clasr( side, pivot, direct, m, n, c, s, a, lda ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,pivot,side integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(in) :: c(*),s(*) complex(sp), intent(inout) :: a(lda,*) end subroutine clasr #else module procedure stdlib${ii}$_clasr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasr( side, pivot, direct, m, n, c, s, a, lda ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,pivot,side integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: c(*),s(*) end subroutine dlasr #else module procedure stdlib${ii}$_dlasr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasr( side, pivot, direct, m, n, c, s, a, lda ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,pivot,side integer(${ik}$), intent(in) :: lda,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: c(*),s(*) end subroutine slasr #else module procedure stdlib${ii}$_slasr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlasr( side, pivot, direct, m, n, c, s, a, lda ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,pivot,side integer(${ik}$), intent(in) :: lda,m,n real(dp), intent(in) :: c(*),s(*) complex(dp), intent(inout) :: a(lda,*) end subroutine zlasr #else module procedure stdlib${ii}$_zlasr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasr #:endif #:endfor #:endfor end interface lasr interface lasrt !! Sort the numbers in D in increasing order (if ID = 'I') or !! in decreasing order (if ID = 'D' ). !! Use Quick Sort, reverting to Insertion sort on arrays of !! size <= 20. Dimension of STACK limits N to about 2**32. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasrt( id, n, d, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: id integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: d(*) end subroutine dlasrt #else module procedure stdlib${ii}$_dlasrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasrt( id, n, d, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: id integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: d(*) end subroutine slasrt #else module procedure stdlib${ii}$_slasrt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasrt #:endif #:endfor #:endfor end interface lasrt interface lassq !! LASSQ returns the values scl and smsq such that !! ( scl**2 )*smsq = x( 1 )**2 +...+ x( n )**2 + ( scale**2 )*sumsq, !! where x( i ) = X( 1 + ( i - 1 )*INCX ). The value of sumsq is !! assumed to be non-negative. !! scale and sumsq must be supplied in SCALE and SUMSQ and !! scl and smsq are overwritten on SCALE and SUMSQ respectively. !! If scale * sqrt( sumsq ) > tbig then !! we require: scale >= sqrt( TINY*EPS ) / sbig on entry, !! and if 0 < scale * sqrt( sumsq ) < tsml then !! we require: scale <= sqrt( HUGE ) / ssml on entry, !! where !! tbig -- upper threshold for values whose square is representable; !! sbig -- scaling constant for big numbers; \see la_constants.f90 !! tsml -- lower threshold for values whose square is representable; !! ssml -- scaling constant for small numbers; \see la_constants.f90 !! and !! TINY*EPS -- tiniest representable number; !! HUGE -- biggest representable number. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine classq( n, x, incx, scl, sumsq ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n real(sp), intent(inout) :: scl,sumsq complex(sp), intent(in) :: x(*) end subroutine classq #else module procedure stdlib${ii}$_classq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlassq( n, x, incx, scl, sumsq ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n real(dp), intent(inout) :: scl,sumsq real(dp), intent(in) :: x(*) end subroutine dlassq #else module procedure stdlib${ii}$_dlassq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slassq( n, x, incx, scl, sumsq ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n real(sp), intent(inout) :: scl,sumsq real(sp), intent(in) :: x(*) end subroutine slassq #else module procedure stdlib${ii}$_slassq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlassq( n, x, incx, scl, sumsq ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n real(dp), intent(inout) :: scl,sumsq complex(dp), intent(in) :: x(*) end subroutine zlassq #else module procedure stdlib${ii}$_zlassq #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lassq #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lassq #:endif #:endfor #:endfor end interface lassq interface laswlq !! LASWLQ computes a blocked Tall-Skinny LQ factorization of !! a complex M-by-N matrix A for M <= N: !! A = ( L 0 ) * Q, !! where: !! Q is a n-by-N orthogonal matrix, stored on exit in an implicit !! form in the elements above the diagonal of the array A and in !! the elements of the array T; !! L is a lower-triangular M-by-M matrix stored on exit in !! the elements on and below the diagonal of the array A. !! 0 is a M-by-(N-M) zero matrix, if M < N, and is not stored. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,mb,nb,lwork,ldt complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*),t(ldt,*) end subroutine claswlq #else module procedure stdlib${ii}$_claswlq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,mb,nb,lwork,ldt real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*),t(ldt,*) end subroutine dlaswlq #else module procedure stdlib${ii}$_dlaswlq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,mb,nb,lwork,ldt real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*),t(ldt,*) end subroutine slaswlq #else module procedure stdlib${ii}$_slaswlq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,mb,nb,lwork,ldt complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*),t(ldt,*) end subroutine zlaswlq #else module procedure stdlib${ii}$_zlaswlq #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laswlq #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laswlq #:endif #:endfor #:endfor end interface laswlq interface laswp !! LASWP performs a series of row interchanges on the matrix A. !! One row interchange is initiated for each of rows K1 through K2 of A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claswp( n, a, lda, k1, k2, ipiv, incx ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k1,k2,lda,n,ipiv(*) complex(sp), intent(inout) :: a(lda,*) end subroutine claswp #else module procedure stdlib${ii}$_claswp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlaswp( n, a, lda, k1, k2, ipiv, incx ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k1,k2,lda,n,ipiv(*) real(dp), intent(inout) :: a(lda,*) end subroutine dlaswp #else module procedure stdlib${ii}$_dlaswp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slaswp( n, a, lda, k1, k2, ipiv, incx ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k1,k2,lda,n,ipiv(*) real(sp), intent(inout) :: a(lda,*) end subroutine slaswp #else module procedure stdlib${ii}$_slaswp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaswp( n, a, lda, k1, k2, ipiv, incx ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,k1,k2,lda,n,ipiv(*) complex(dp), intent(inout) :: a(lda,*) end subroutine zlaswp #else module procedure stdlib${ii}$_zlaswp #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laswp #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$laswp #:endif #:endfor #:endfor end interface laswp interface lasyf !! LASYF computes a partial factorization of a complex symmetric matrix !! A using the Bunch-Kaufman diagonal pivoting method. The partial !! factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**T denotes the transpose of U. !! LASYF is an auxiliary routine called by CSYTRF. It uses blocked code !! (calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or !! A22 (if UPLO = 'L'). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clasyf( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: w(ldw,*) end subroutine clasyf #else module procedure stdlib${ii}$_clasyf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasyf( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(ldw,*) end subroutine dlasyf #else module procedure stdlib${ii}$_dlasyf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasyf( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(ldw,*) end subroutine slasyf #else module procedure stdlib${ii}$_slasyf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlasyf( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: w(ldw,*) end subroutine zlasyf #else module procedure stdlib${ii}$_zlasyf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasyf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasyf #:endif #:endfor #:endfor end interface lasyf interface lasyf_aa !! DLATRF_AA factorizes a panel of a complex symmetric matrix A using !! the Aasen's algorithm. The panel consists of a set of NB rows of A !! when UPLO is U, or a set of NB columns when UPLO is L. !! In order to factorize the panel, the Aasen's algorithm requires the !! last row, or column, of the previous panel. The first row, or column, !! of A is set to be the first row, or column, of an identity matrix, !! which is used to factorize the first panel. !! The resulting J-th row of U, or J-th column of L, is stored in the !! (J-1)-th row, or column, of A (without the unit diagonals), while !! the diagonal and subdiagonal of A are overwritten by those of T. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clasyf_aa( uplo, j1, m, nb, a, lda, ipiv,h, ldh, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: m,nb,j1,lda,ldh integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*),h(ldh,*) complex(sp), intent(out) :: work(*) end subroutine clasyf_aa #else module procedure stdlib${ii}$_clasyf_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasyf_aa( uplo, j1, m, nb, a, lda, ipiv,h, ldh, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: m,nb,j1,lda,ldh integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: a(lda,*),h(ldh,*) real(dp), intent(out) :: work(*) end subroutine dlasyf_aa #else module procedure stdlib${ii}$_dlasyf_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasyf_aa( uplo, j1, m, nb, a, lda, ipiv,h, ldh, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: m,nb,j1,lda,ldh integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*),h(ldh,*) real(sp), intent(out) :: work(*) end subroutine slasyf_aa #else module procedure stdlib${ii}$_slasyf_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlasyf_aa( uplo, j1, m, nb, a, lda, ipiv,h, ldh, work ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: m,nb,j1,lda,ldh integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*),h(ldh,*) complex(dp), intent(out) :: work(*) end subroutine zlasyf_aa #else module procedure stdlib${ii}$_zlasyf_aa #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasyf_aa #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasyf_aa #:endif #:endfor #:endfor end interface lasyf_aa interface lasyf_rk !! LASYF_RK computes a partial factorization of a complex symmetric !! matrix A using the bounded Bunch-Kaufman (rook) diagonal !! pivoting method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L', !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! LASYF_RK is an auxiliary routine called by CSYTRF_RK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clasyf_rk( uplo, n, nb, kb, a, lda, e, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: e(*),w(ldw,*) end subroutine clasyf_rk #else module procedure stdlib${ii}$_clasyf_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasyf_rk( uplo, n, nb, kb, a, lda, e, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: e(*),w(ldw,*) end subroutine dlasyf_rk #else module procedure stdlib${ii}$_dlasyf_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasyf_rk( uplo, n, nb, kb, a, lda, e, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: e(*),w(ldw,*) end subroutine slasyf_rk #else module procedure stdlib${ii}$_slasyf_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlasyf_rk( uplo, n, nb, kb, a, lda, e, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: e(*),w(ldw,*) end subroutine zlasyf_rk #else module procedure stdlib${ii}$_zlasyf_rk #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasyf_rk #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasyf_rk #:endif #:endfor #:endfor end interface lasyf_rk interface lasyf_rook !! LASYF_ROOK computes a partial factorization of a complex symmetric !! matrix A using the bounded Bunch-Kaufman ("rook") diagonal !! pivoting method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! LASYF_ROOK is an auxiliary routine called by CSYTRF_ROOK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clasyf_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: w(ldw,*) end subroutine clasyf_rook #else module procedure stdlib${ii}$_clasyf_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlasyf_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(ldw,*) end subroutine dlasyf_rook #else module procedure stdlib${ii}$_dlasyf_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slasyf_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(ldw,*) end subroutine slasyf_rook #else module procedure stdlib${ii}$_slasyf_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlasyf_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,kb,ipiv(*) integer(${ik}$), intent(in) :: lda,ldw,n,nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: w(ldw,*) end subroutine zlasyf_rook #else module procedure stdlib${ii}$_zlasyf_rook #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasyf_rook #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lasyf_rook #:endif #:endfor #:endfor end interface lasyf_rook interface latbs !! LATBS solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow, where A is an upper or lower !! triangular band matrix. Here A**T denotes the transpose of A, x and b !! are n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine CTBSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clatbs( uplo, trans, diag, normin, n, kd, ab, ldab, x,scale, cnorm,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(out) :: scale real(sp), intent(inout) :: cnorm(*) complex(sp), intent(in) :: ab(ldab,*) complex(sp), intent(inout) :: x(*) end subroutine clatbs #else module procedure stdlib${ii}$_clatbs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlatbs( uplo, trans, diag, normin, n, kd, ab, ldab, x,scale, cnorm,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(out) :: scale real(dp), intent(in) :: ab(ldab,*) real(dp), intent(inout) :: cnorm(*),x(*) end subroutine dlatbs #else module procedure stdlib${ii}$_dlatbs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slatbs( uplo, trans, diag, normin, n, kd, ab, ldab, x,scale, cnorm,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(out) :: scale real(sp), intent(in) :: ab(ldab,*) real(sp), intent(inout) :: cnorm(*),x(*) end subroutine slatbs #else module procedure stdlib${ii}$_slatbs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlatbs( uplo, trans, diag, normin, n, kd, ab, ldab, x,scale, cnorm,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(out) :: scale real(dp), intent(inout) :: cnorm(*) complex(dp), intent(in) :: ab(ldab,*) complex(dp), intent(inout) :: x(*) end subroutine zlatbs #else module procedure stdlib${ii}$_zlatbs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latbs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latbs #:endif #:endfor #:endfor end interface latbs interface latdf !! LATDF computes the contribution to the reciprocal Dif-estimate !! by solving for x in Z * x = b, where b is chosen such that the norm !! of x is as large as possible. It is assumed that LU decomposition !! of Z has been computed by CGETC2. On entry RHS = f holds the !! contribution from earlier solved sub-systems, and on return RHS = x. !! The factorization of Z returned by CGETC2 has the form !! Z = P * L * U * Q, where P and Q are permutation matrices. L is lower !! triangular with unit diagonal elements and U is upper triangular. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clatdf( ijob, n, z, ldz, rhs, rdsum, rdscal, ipiv,jpiv ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ijob,ldz,n,ipiv(*),jpiv(*) real(sp), intent(inout) :: rdscal,rdsum complex(sp), intent(inout) :: rhs(*),z(ldz,*) end subroutine clatdf #else module procedure stdlib${ii}$_clatdf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlatdf( ijob, n, z, ldz, rhs, rdsum, rdscal, ipiv,jpiv ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ijob,ldz,n,ipiv(*),jpiv(*) real(dp), intent(inout) :: rdscal,rdsum,rhs(*),z(ldz,*) end subroutine dlatdf #else module procedure stdlib${ii}$_dlatdf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slatdf( ijob, n, z, ldz, rhs, rdsum, rdscal, ipiv,jpiv ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ijob,ldz,n,ipiv(*),jpiv(*) real(sp), intent(inout) :: rdscal,rdsum,rhs(*),z(ldz,*) end subroutine slatdf #else module procedure stdlib${ii}$_slatdf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlatdf( ijob, n, z, ldz, rhs, rdsum, rdscal, ipiv,jpiv ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ijob,ldz,n,ipiv(*),jpiv(*) real(dp), intent(inout) :: rdscal,rdsum complex(dp), intent(inout) :: rhs(*),z(ldz,*) end subroutine zlatdf #else module procedure stdlib${ii}$_zlatdf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latdf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latdf #:endif #:endfor #:endfor end interface latdf interface latps !! LATPS solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow, where A is an upper or lower !! triangular matrix stored in packed form. Here A**T denotes the !! transpose of A, A**H denotes the conjugate transpose of A, x and b !! are n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine CTPSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clatps( uplo, trans, diag, normin, n, ap, x, scale,cnorm, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(out) :: scale real(sp), intent(inout) :: cnorm(*) complex(sp), intent(in) :: ap(*) complex(sp), intent(inout) :: x(*) end subroutine clatps #else module procedure stdlib${ii}$_clatps #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlatps( uplo, trans, diag, normin, n, ap, x, scale,cnorm, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: scale real(dp), intent(in) :: ap(*) real(dp), intent(inout) :: cnorm(*),x(*) end subroutine dlatps #else module procedure stdlib${ii}$_dlatps #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slatps( uplo, trans, diag, normin, n, ap, x, scale,cnorm, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(out) :: scale real(sp), intent(in) :: ap(*) real(sp), intent(inout) :: cnorm(*),x(*) end subroutine slatps #else module procedure stdlib${ii}$_slatps #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlatps( uplo, trans, diag, normin, n, ap, x, scale,cnorm, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: scale real(dp), intent(inout) :: cnorm(*) complex(dp), intent(in) :: ap(*) complex(dp), intent(inout) :: x(*) end subroutine zlatps #else module procedure stdlib${ii}$_zlatps #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latps #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latps #:endif #:endfor #:endfor end interface latps interface latrd !! LATRD reduces NB rows and columns of a complex Hermitian matrix A to !! Hermitian tridiagonal form by a unitary similarity !! transformation Q**H * A * Q, and returns the matrices V and W which are !! needed to apply the transformation to the unreduced part of A. !! If UPLO = 'U', LATRD reduces the last NB rows and columns of a !! matrix, of which the upper triangle is supplied; !! if UPLO = 'L', LATRD reduces the first NB rows and columns of a !! matrix, of which the lower triangle is supplied. !! This is an auxiliary routine called by CHETRD. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clatrd( uplo, n, nb, a, lda, e, tau, w, ldw ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,ldw,n,nb real(sp), intent(out) :: e(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*),w(ldw,*) end subroutine clatrd #else module procedure stdlib${ii}$_clatrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlatrd( uplo, n, nb, a, lda, e, tau, w, ldw ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,ldw,n,nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: e(*),tau(*),w(ldw,*) end subroutine dlatrd #else module procedure stdlib${ii}$_dlatrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slatrd( uplo, n, nb, a, lda, e, tau, w, ldw ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,ldw,n,nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: e(*),tau(*),w(ldw,*) end subroutine slatrd #else module procedure stdlib${ii}$_slatrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlatrd( uplo, n, nb, a, lda, e, tau, w, ldw ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda,ldw,n,nb real(dp), intent(out) :: e(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*),w(ldw,*) end subroutine zlatrd #else module procedure stdlib${ii}$_zlatrd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latrd #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latrd #:endif #:endfor #:endfor end interface latrd interface latrs !! LATRS solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow. Here A is an upper or lower !! triangular matrix, A**T denotes the transpose of A, A**H denotes the !! conjugate transpose of A, x and b are n-element vectors, and s is a !! scaling factor, usually less than or equal to 1, chosen so that the !! components of x will be less than the overflow threshold. If the !! unscaled problem will not cause overflow, the Level 2 BLAS routine !! CTRSV is called. If the matrix A is singular (A(j,j) = 0 for some j), !! then s is set to 0 and a non-trivial solution to A*x = 0 is returned. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clatrs( uplo, trans, diag, normin, n, a, lda, x, scale,cnorm, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: scale real(sp), intent(inout) :: cnorm(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: x(*) end subroutine clatrs #else module procedure stdlib${ii}$_clatrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlatrs( uplo, trans, diag, normin, n, a, lda, x, scale,cnorm, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: scale real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: cnorm(*),x(*) end subroutine dlatrs #else module procedure stdlib${ii}$_dlatrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slatrs( uplo, trans, diag, normin, n, a, lda, x, scale,cnorm, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: scale real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: cnorm(*),x(*) end subroutine slatrs #else module procedure stdlib${ii}$_slatrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlatrs( uplo, trans, diag, normin, n, a, lda, x, scale,cnorm, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,normin,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: scale real(dp), intent(inout) :: cnorm(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: x(*) end subroutine zlatrs #else module procedure stdlib${ii}$_zlatrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latrs #:endif #:endfor #:endfor end interface latrs interface latrz !! LATRZ factors the M-by-(M+L) complex upper trapezoidal matrix !! [ A1 A2 ] = [ A(1:M,1:M) A(1:M,N-L+1:N) ] as ( R 0 ) * Z by means !! of unitary transformations, where Z is an (M+L)-by-(M+L) unitary !! matrix and, R and A1 are M-by-M upper triangular matrices. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clatrz( m, n, l, a, lda, tau, work ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: l,lda,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*),work(*) end subroutine clatrz #else module procedure stdlib${ii}$_clatrz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlatrz( m, n, l, a, lda, tau, work ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: l,lda,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*),work(*) end subroutine dlatrz #else module procedure stdlib${ii}$_dlatrz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slatrz( m, n, l, a, lda, tau, work ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: l,lda,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*),work(*) end subroutine slatrz #else module procedure stdlib${ii}$_slatrz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlatrz( m, n, l, a, lda, tau, work ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: l,lda,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*),work(*) end subroutine zlatrz #else module procedure stdlib${ii}$_zlatrz #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latrz #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latrz #:endif #:endfor #:endfor end interface latrz interface latsqr !! LATSQR computes a blocked Tall-Skinny QR factorization of !! a complex M-by-N matrix A for M >= N: !! A = Q * ( R ), !! ( 0 ) !! where: !! Q is a M-by-M orthogonal matrix, stored on exit in an implicit !! form in the elements below the diagonal of the array A and in !! the elements of the array T; !! R is an upper-triangular N-by-N matrix, stored on exit in !! the elements on and above the diagonal of the array A. !! 0 is a (M-N)-by-N zero matrix, and is not stored. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clatsqr( m, n, mb, nb, a, lda, t, ldt, work,lwork, info) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,mb,nb,ldt,lwork complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*),t(ldt,*) end subroutine clatsqr #else module procedure stdlib${ii}$_clatsqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlatsqr( m, n, mb, nb, a, lda, t, ldt, work,lwork, info) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,mb,nb,ldt,lwork real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*),t(ldt,*) end subroutine dlatsqr #else module procedure stdlib${ii}$_dlatsqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slatsqr( m, n, mb, nb, a, lda, t, ldt, work,lwork, info) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,mb,nb,ldt,lwork real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*),t(ldt,*) end subroutine slatsqr #else module procedure stdlib${ii}$_slatsqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlatsqr( m, n, mb, nb, a, lda, t, ldt, work,lwork, info) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n,mb,nb,ldt,lwork complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*),t(ldt,*) end subroutine zlatsqr #else module procedure stdlib${ii}$_zlatsqr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latsqr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$latsqr #:endif #:endfor #:endfor end interface latsqr interface launhr_col_getrfnp !! LAUNHR_COL_GETRFNP computes the modified LU factorization without !! pivoting of a complex general M-by-N matrix A. The factorization has !! the form: !! A - S = L * U, !! where: !! S is a m-by-n diagonal sign matrix with the diagonal D, so that !! D(i) = S(i,i), 1 <= i <= min(M,N). The diagonal D is constructed !! as D(i)=-SIGN(A(i,i)), where A(i,i) is the value after performing !! i-1 steps of Gaussian elimination. This means that the diagonal !! element at each step of "modified" Gaussian elimination is !! at least one in absolute value (so that division-by-zero not !! not possible during the division by the diagonal element); !! L is a M-by-N lower triangular matrix with unit diagonal elements !! (lower trapezoidal if M > N); !! and U is a M-by-N upper triangular matrix !! (upper trapezoidal if M < N). !! This routine is an auxiliary routine used in the Householder !! reconstruction routine CUNHR_COL. In CUNHR_COL, this routine is !! applied to an M-by-N matrix A with orthonormal columns, where each !! element is bounded by one in absolute value. With the choice of !! the matrix S above, one can show that the diagonal element at each !! step of Gaussian elimination is the largest (in absolute value) in !! the column on or below the diagonal, so that no pivoting is required !! for numerical stability [1]. !! For more details on the Householder reconstruction algorithm, !! including the modified LU factorization, see [1]. !! This is the blocked right-looking version of the algorithm, !! calling Level 3 BLAS to update the submatrix. To factorize a block, !! this routine calls the recursive routine LAUNHR_COL_GETRFNP2. !! [1] "Reconstructing Householder vectors from tall-skinny QR", !! G. Ballard, J. Demmel, L. Grigori, M. Jacquelin, H.D. Nguyen, !! E. Solomonik, J. Parallel Distrib. Comput., !! vol. 85, pp. 3-31, 2015. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine claunhr_col_getrfnp( m, n, a, lda, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: d(*) end subroutine claunhr_col_getrfnp #else module procedure stdlib${ii}$_claunhr_col_getrfnp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlaunhr_col_getrfnp( m, n, a, lda, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: d(*) end subroutine zlaunhr_col_getrfnp #else module procedure stdlib${ii}$_zlaunhr_col_getrfnp #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$launhr_col_getrfnp #:endif #:endfor #:endfor end interface launhr_col_getrfnp interface launhr_col_getrfnp2 !! LAUNHR_COL_GETRFNP2 computes the modified LU factorization without !! pivoting of a complex general M-by-N matrix A. The factorization has !! the form: !! A - S = L * U, !! where: !! S is a m-by-n diagonal sign matrix with the diagonal D, so that !! D(i) = S(i,i), 1 <= i <= min(M,N). The diagonal D is constructed !! as D(i)=-SIGN(A(i,i)), where A(i,i) is the value after performing !! i-1 steps of Gaussian elimination. This means that the diagonal !! element at each step of "modified" Gaussian elimination is at !! least one in absolute value (so that division-by-zero not !! possible during the division by the diagonal element); !! L is a M-by-N lower triangular matrix with unit diagonal elements !! (lower trapezoidal if M > N); !! and U is a M-by-N upper triangular matrix !! (upper trapezoidal if M < N). !! This routine is an auxiliary routine used in the Householder !! reconstruction routine CUNHR_COL. In CUNHR_COL, this routine is !! applied to an M-by-N matrix A with orthonormal columns, where each !! element is bounded by one in absolute value. With the choice of !! the matrix S above, one can show that the diagonal element at each !! step of Gaussian elimination is the largest (in absolute value) in !! the column on or below the diagonal, so that no pivoting is required !! for numerical stability [1]. !! For more details on the Householder reconstruction algorithm, !! including the modified LU factorization, see [1]. !! This is the recursive version of the LU factorization algorithm. !! Denote A - S by B. The algorithm divides the matrix B into four !! submatrices: !! [ B11 | B12 ] where B11 is n1 by n1, !! B = [ -----|----- ] B21 is (m-n1) by n1, !! [ B21 | B22 ] B12 is n1 by n2, !! B22 is (m-n1) by n2, !! with n1 = min(m,n)/2, n2 = n-n1. !! The subroutine calls itself to factor B11, solves for B21, !! solves for B12, updates B22, then calls itself to factor B22. !! For more details on the recursive LU algorithm, see [2]. !! LAUNHR_COL_GETRFNP2 is called to factorize a block by the blocked !! routine CLAUNHR_COL_GETRFNP, which uses blocked code calling !! Level 3 BLAS to update the submatrix. However, LAUNHR_COL_GETRFNP2 !! is self-sufficient and can be used without CLAUNHR_COL_GETRFNP. !! [1] "Reconstructing Householder vectors from tall-skinny QR", !! G. Ballard, J. Demmel, L. Grigori, M. Jacquelin, H.D. Nguyen, !! E. Solomonik, J. Parallel Distrib. Comput., !! vol. 85, pp. 3-31, 2015. !! [2] "Recursion leads to automatic variable blocking for dense linear !! algebra algorithms", F. Gustavson, IBM J. of Res. and Dev., !! vol. 41, no. 6, pp. 737-755, 1997. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine claunhr_col_getrfnp2( m, n, a, lda, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: d(*) end subroutine claunhr_col_getrfnp2 #else module procedure stdlib${ii}$_claunhr_col_getrfnp2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine zlaunhr_col_getrfnp2( m, n, a, lda, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: d(*) end subroutine zlaunhr_col_getrfnp2 #else module procedure stdlib${ii}$_zlaunhr_col_getrfnp2 #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$launhr_col_getrfnp2 #:endif #:endfor #:endfor end interface launhr_col_getrfnp2 interface lauum !! LAUUM computes the product U * U**H or L**H * L, where the triangular !! factor U or L is stored in the upper or lower triangular part of !! the array A. !! If UPLO = 'U' or 'u' then the upper triangle of the result is stored, !! overwriting the factor U in A. !! If UPLO = 'L' or 'l' then the lower triangle of the result is stored, !! overwriting the factor L in A. !! This is the blocked form of the algorithm, calling Level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine clauum( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n complex(sp), intent(inout) :: a(lda,*) end subroutine clauum #else module procedure stdlib${ii}$_clauum #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dlauum( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(inout) :: a(lda,*) end subroutine dlauum #else module procedure stdlib${ii}$_dlauum #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine slauum( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(inout) :: a(lda,*) end subroutine slauum #else module procedure stdlib${ii}$_slauum #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zlauum( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n complex(dp), intent(inout) :: a(lda,*) end subroutine zlauum #else module procedure stdlib${ii}$_zlauum #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lauum #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$lauum #:endif #:endfor #:endfor end interface lauum interface opgtr !! OPGTR generates a real orthogonal matrix Q which is defined as the !! product of n-1 elementary reflectors H(i) of order n, as returned by !! DSPTRD using packed storage: !! if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), !! if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dopgtr( uplo, n, ap, tau, q, ldq, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq,n real(dp), intent(in) :: ap(*),tau(*) real(dp), intent(out) :: q(ldq,*),work(*) end subroutine dopgtr #else module procedure stdlib${ii}$_dopgtr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sopgtr( uplo, n, ap, tau, q, ldq, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq,n real(sp), intent(in) :: ap(*),tau(*) real(sp), intent(out) :: q(ldq,*),work(*) end subroutine sopgtr #else module procedure stdlib${ii}$_sopgtr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$opgtr #:endif #:endfor #:endfor end interface opgtr interface opmtr !! OPMTR overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix of order nq, with nq = m if !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of !! nq-1 elementary reflectors, as returned by DSPTRD using packed !! storage: !! if UPLO = 'U', Q = H(nq-1) . . . H(2) H(1); !! if UPLO = 'L', Q = H(1) H(2) . . . H(nq-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dopmtr( side, uplo, trans, m, n, ap, tau, c, ldc, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc,m,n real(dp), intent(inout) :: ap(*),c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dopmtr #else module procedure stdlib${ii}$_dopmtr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sopmtr( side, uplo, trans, m, n, ap, tau, c, ldc, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc,m,n real(sp), intent(inout) :: ap(*),c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sopmtr #else module procedure stdlib${ii}$_sopmtr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$opmtr #:endif #:endfor #:endfor end interface opmtr interface orbdb !! ORBDB simultaneously bidiagonalizes the blocks of an M-by-M !! partitioned orthogonal matrix X: !! [ B11 | B12 0 0 ] !! [ X11 | X12 ] [ P1 | ] [ 0 | 0 -I 0 ] [ Q1 | ]**T !! X = [-----------] = [---------] [----------------] [---------] . !! [ X21 | X22 ] [ | P2 ] [ B21 | B22 0 0 ] [ | Q2 ] !! [ 0 | 0 0 I ] !! X11 is P-by-Q. Q must be no larger than P, M-P, or M-Q. (If this is !! not the case, then X must be transposed and/or permuted. This can be !! done in constant time using the TRANS and SIGNS options. See DORCSD !! for details.) !! The orthogonal matrices P1, P2, Q1, and Q2 are P-by-P, (M-P)-by- !! (M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. They are !! represented implicitly by Householder vectors. !! B11, B12, B21, and B22 are Q-by-Q bidiagonal matrices represented !! implicitly by angles THETA, PHI. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: signs,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldx11,ldx12,ldx21,ldx22,lwork,m,p,q real(dp), intent(out) :: phi(*),theta(*),taup1(*),taup2(*),tauq1(*),tauq2(*),& work(*) real(dp), intent(inout) :: x11(ldx11,*),x12(ldx12,*),x21(ldx21,*),x22(ldx22,*) end subroutine dorbdb #else module procedure stdlib${ii}$_dorbdb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: signs,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldx11,ldx12,ldx21,ldx22,lwork,m,p,q real(sp), intent(out) :: phi(*),theta(*),taup1(*),taup2(*),tauq1(*),tauq2(*),& work(*) real(sp), intent(inout) :: x11(ldx11,*),x12(ldx12,*),x21(ldx21,*),x22(ldx22,*) end subroutine sorbdb #else module procedure stdlib${ii}$_sorbdb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orbdb #:endif #:endfor #:endfor end interface orbdb interface orbdb1 !! ORBDB1 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. Q must be no larger than P, !! M-P, or M-Q. Routines DORBDB2, DORBDB3, and DORBDB4 handle cases in !! which Q is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are Q-by-Q bidiagonal matrices represented implicitly by !! angles THETA, PHI. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(dp), intent(out) :: phi(*),theta(*),taup1(*),taup2(*),tauq1(*),work(*) real(dp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine dorbdb1 #else module procedure stdlib${ii}$_dorbdb1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(sp), intent(out) :: phi(*),theta(*),taup1(*),taup2(*),tauq1(*),work(*) real(sp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine sorbdb1 #else module procedure stdlib${ii}$_sorbdb1 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orbdb1 #:endif #:endfor #:endfor end interface orbdb1 interface orbdb2 !! ORBDB2 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. P must be no larger than M-P, !! Q, or M-Q. Routines DORBDB1, DORBDB3, and DORBDB4 handle cases in !! which P is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are P-by-P bidiagonal matrices represented implicitly by !! angles THETA, PHI. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(dp), intent(out) :: phi(*),theta(*),taup1(*),taup2(*),tauq1(*),work(*) real(dp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine dorbdb2 #else module procedure stdlib${ii}$_dorbdb2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(sp), intent(out) :: phi(*),theta(*),taup1(*),taup2(*),tauq1(*),work(*) real(sp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine sorbdb2 #else module procedure stdlib${ii}$_sorbdb2 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orbdb2 #:endif #:endfor #:endfor end interface orbdb2 interface orbdb3 !! ORBDB3 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-P must be no larger than P, !! Q, or M-Q. Routines DORBDB1, DORBDB2, and DORBDB4 handle cases in !! which M-P is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-P)-by-(M-P) bidiagonal matrices represented !! implicitly by angles THETA, PHI. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(dp), intent(out) :: phi(*),theta(*),taup1(*),taup2(*),tauq1(*),work(*) real(dp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine dorbdb3 #else module procedure stdlib${ii}$_dorbdb3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(sp), intent(out) :: phi(*),theta(*),taup1(*),taup2(*),tauq1(*),work(*) real(sp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine sorbdb3 #else module procedure stdlib${ii}$_sorbdb3 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orbdb3 #:endif #:endfor #:endfor end interface orbdb3 interface orbdb4 !! ORBDB4 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-Q must be no larger than P, !! M-P, or Q. Routines DORBDB1, DORBDB2, and DORBDB3 handle cases in !! which M-Q is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-Q)-by-(M-Q) bidiagonal matrices represented !! implicitly by angles THETA, PHI. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, phantom, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(dp), intent(out) :: phi(*),theta(*),phantom(*),taup1(*),taup2(*),tauq1(*)& ,work(*) real(dp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine dorbdb4 #else module procedure stdlib${ii}$_dorbdb4 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, phantom, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(sp), intent(out) :: phi(*),theta(*),phantom(*),taup1(*),taup2(*),tauq1(*)& ,work(*) real(sp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine sorbdb4 #else module procedure stdlib${ii}$_sorbdb4 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orbdb4 #:endif #:endfor #:endfor end interface orbdb4 interface orbdb5 !! ORBDB5 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then some other vector from the orthogonal complement !! is returned. This vector is chosen in an arbitrary but deterministic !! way. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx1,incx2,ldq1,ldq2,lwork,m1,m2,n integer(${ik}$), intent(out) :: info real(dp), intent(in) :: q1(ldq1,*),q2(ldq2,*) real(dp), intent(out) :: work(*) real(dp), intent(inout) :: x1(*),x2(*) end subroutine dorbdb5 #else module procedure stdlib${ii}$_dorbdb5 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx1,incx2,ldq1,ldq2,lwork,m1,m2,n integer(${ik}$), intent(out) :: info real(sp), intent(in) :: q1(ldq1,*),q2(ldq2,*) real(sp), intent(out) :: work(*) real(sp), intent(inout) :: x1(*),x2(*) end subroutine sorbdb5 #else module procedure stdlib${ii}$_sorbdb5 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orbdb5 #:endif #:endfor #:endfor end interface orbdb5 interface orbdb6 !! ORBDB6 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then the zero vector is returned. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx1,incx2,ldq1,ldq2,lwork,m1,m2,n integer(${ik}$), intent(out) :: info real(dp), intent(in) :: q1(ldq1,*),q2(ldq2,*) real(dp), intent(out) :: work(*) real(dp), intent(inout) :: x1(*),x2(*) end subroutine dorbdb6 #else module procedure stdlib${ii}$_dorbdb6 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx1,incx2,ldq1,ldq2,lwork,m1,m2,n integer(${ik}$), intent(out) :: info real(sp), intent(in) :: q1(ldq1,*),q2(ldq2,*) real(sp), intent(out) :: work(*) real(sp), intent(inout) :: x1(*),x2(*) end subroutine sorbdb6 #else module procedure stdlib${ii}$_sorbdb6 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orbdb6 #:endif #:endfor #:endfor end interface orbdb6 interface orcsd !! ORCSD computes the CS decomposition of an M-by-M partitioned !! orthogonal matrix X: !! [ I 0 0 | 0 0 0 ] !! [ 0 C 0 | 0 -S 0 ] !! [ X11 | X12 ] [ U1 | ] [ 0 0 0 | 0 0 -I ] [ V1 | ]**T !! X = [-----------] = [---------] [---------------------] [---------] . !! [ X21 | X22 ] [ | U2 ] [ 0 0 0 | I 0 0 ] [ | V2 ] !! [ 0 S 0 | 0 C 0 ] !! [ 0 0 I | 0 0 0 ] !! X11 is P-by-Q. The orthogonal matrices U1, U2, V1, and V2 are P-by-P, !! (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are !! R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in !! which R = MIN(P,M-P,Q,M-Q). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ recursive subroutine dorcsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, & x11, ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, & ldv1t, v2t,ldv2t, work, lwork, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu1,jobu2,jobv1t,jobv2t,signs,trans integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu1,ldu2,ldv1t,ldv2t,ldx11,ldx12,ldx21,ldx22,& lwork,m,p,q real(dp), intent(out) :: theta(*),u1(ldu1,*),u2(ldu2,*),v1t(ldv1t,*),v2t(& ldv2t,*),work(*) real(dp), intent(inout) :: x11(ldx11,*),x12(ldx12,*),x21(ldx21,*),x22(ldx22,*) end subroutine dorcsd #else module procedure stdlib${ii}$_dorcsd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ recursive subroutine sorcsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, & x11, ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, & ldv1t, v2t,ldv2t, work, lwork, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu1,jobu2,jobv1t,jobv2t,signs,trans integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu1,ldu2,ldv1t,ldv2t,ldx11,ldx12,ldx21,ldx22,& lwork,m,p,q real(sp), intent(out) :: theta(*),u1(ldu1,*),u2(ldu2,*),v1t(ldv1t,*),v2t(& ldv2t,*),work(*) real(sp), intent(inout) :: x11(ldx11,*),x12(ldx12,*),x21(ldx21,*),x22(ldx22,*) end subroutine sorcsd #else module procedure stdlib${ii}$_sorcsd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orcsd #:endif #:endfor #:endfor end interface orcsd interface orcsd2by1 !! ORCSD2BY1 computes the CS decomposition of an M-by-Q matrix X with !! orthonormal columns that has been partitioned into a 2-by-1 block !! structure: !! [ I1 0 0 ] !! [ 0 C 0 ] !! [ X11 ] [ U1 | ] [ 0 0 0 ] !! X = [-----] = [---------] [----------] V1**T . !! [ X21 ] [ | U2 ] [ 0 0 0 ] !! [ 0 S 0 ] !! [ 0 0 I2] !! X11 is P-by-Q. The orthogonal matrices U1, U2, and V1 are P-by-P, !! (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R !! nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which !! R = MIN(P,M-P,Q,M-Q). I1 is a K1-by-K1 identity matrix and I2 is a !! K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dorcsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta,& u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu1,jobu2,jobv1t integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu1,ldu2,ldv1t,lwork,ldx11,ldx21,m,p,q real(dp), intent(out) :: theta(*),u1(ldu1,*),u2(ldu2,*),v1t(ldv1t,*),work(*) real(dp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine dorcsd2by1 #else module procedure stdlib${ii}$_dorcsd2by1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sorcsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta,& u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu1,jobu2,jobv1t integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu1,ldu2,ldv1t,lwork,ldx11,ldx21,m,p,q real(sp), intent(out) :: theta(*),u1(ldu1,*),u2(ldu2,*),v1t(ldv1t,*),work(*) real(sp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine sorcsd2by1 #else module procedure stdlib${ii}$_sorcsd2by1 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orcsd2by1 #:endif #:endfor #:endfor end interface orcsd2by1 interface org2l !! ORG2L generates an m by n real matrix Q with orthonormal columns, !! which is defined as the last n columns of a product of k elementary !! reflectors of order m !! Q = H(k) . . . H(2) H(1) !! as returned by DGEQLF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorg2l( m, n, k, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dorg2l #else module procedure stdlib${ii}$_dorg2l #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorg2l( m, n, k, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sorg2l #else module procedure stdlib${ii}$_sorg2l #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$org2l #:endif #:endfor #:endfor end interface org2l interface org2r !! ORG2R generates an m by n real matrix Q with orthonormal columns, !! which is defined as the first n columns of a product of k elementary !! reflectors of order m !! Q = H(1) H(2) . . . H(k) !! as returned by DGEQRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorg2r( m, n, k, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dorg2r #else module procedure stdlib${ii}$_dorg2r #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorg2r( m, n, k, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sorg2r #else module procedure stdlib${ii}$_sorg2r #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$org2r #:endif #:endfor #:endfor end interface org2r interface orgbr !! ORGBR generates one of the real orthogonal matrices Q or P**T !! determined by DGEBRD when reducing a real matrix A to bidiagonal !! form: A = Q * B * P**T. Q and P**T are defined as products of !! elementary reflectors H(i) or G(i) respectively. !! If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q !! is of order M: !! if m >= k, Q = H(1) H(2) . . . H(k) and ORGBR returns the first n !! columns of Q, where m >= n >= k; !! if m < k, Q = H(1) H(2) . . . H(m-1) and ORGBR returns Q as an !! M-by-M matrix. !! If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**T !! is of order N: !! if k < n, P**T = G(k) . . . G(2) G(1) and ORGBR returns the first m !! rows of P**T, where n >= m >= k; !! if k >= n, P**T = G(n-1) . . . G(2) G(1) and ORGBR returns P**T as !! an N-by-N matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorgbr( vect, m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dorgbr #else module procedure stdlib${ii}$_dorgbr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorgbr( vect, m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sorgbr #else module procedure stdlib${ii}$_sorgbr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orgbr #:endif #:endfor #:endfor end interface orgbr interface orghr !! ORGHR generates a real orthogonal matrix Q which is defined as the !! product of IHI-ILO elementary reflectors of order N, as returned by !! DGEHRD: !! Q = H(ilo) H(ilo+1) . . . H(ihi-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorghr( n, ilo, ihi, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,lda,lwork,n integer(${ik}$), intent(out) :: info real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dorghr #else module procedure stdlib${ii}$_dorghr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorghr( n, ilo, ihi, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,lda,lwork,n integer(${ik}$), intent(out) :: info real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sorghr #else module procedure stdlib${ii}$_sorghr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orghr #:endif #:endfor #:endfor end interface orghr interface orglq !! ORGLQ generates an M-by-N real matrix Q with orthonormal rows, !! which is defined as the first M rows of a product of K elementary !! reflectors of order N !! Q = H(k) . . . H(2) H(1) !! as returned by DGELQF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorglq( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dorglq #else module procedure stdlib${ii}$_dorglq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorglq( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sorglq #else module procedure stdlib${ii}$_sorglq #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orglq #:endif #:endfor #:endfor end interface orglq interface orgql !! ORGQL generates an M-by-N real matrix Q with orthonormal columns, !! which is defined as the last N columns of a product of K elementary !! reflectors of order M !! Q = H(k) . . . H(2) H(1) !! as returned by DGEQLF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorgql( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dorgql #else module procedure stdlib${ii}$_dorgql #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorgql( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sorgql #else module procedure stdlib${ii}$_sorgql #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orgql #:endif #:endfor #:endfor end interface orgql interface orgqr !! ORGQR generates an M-by-N real matrix Q with orthonormal columns, !! which is defined as the first N columns of a product of K elementary !! reflectors of order M !! Q = H(1) H(2) . . . H(k) !! as returned by DGEQRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorgqr( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dorgqr #else module procedure stdlib${ii}$_dorgqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorgqr( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sorgqr #else module procedure stdlib${ii}$_sorgqr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orgqr #:endif #:endfor #:endfor end interface orgqr interface orgrq !! ORGRQ generates an M-by-N real matrix Q with orthonormal rows, !! which is defined as the last M rows of a product of K elementary !! reflectors of order N !! Q = H(1) H(2) . . . H(k) !! as returned by DGERQF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorgrq( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dorgrq #else module procedure stdlib${ii}$_dorgrq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorgrq( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sorgrq #else module procedure stdlib${ii}$_sorgrq #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orgrq #:endif #:endfor #:endfor end interface orgrq interface orgtr !! ORGTR generates a real orthogonal matrix Q which is defined as the !! product of n-1 elementary reflectors of order N, as returned by !! DSYTRD: !! if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), !! if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorgtr( uplo, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dorgtr #else module procedure stdlib${ii}$_dorgtr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorgtr( uplo, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sorgtr #else module procedure stdlib${ii}$_sorgtr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orgtr #:endif #:endfor #:endfor end interface orgtr interface orgtsqr !! ORGTSQR generates an M-by-N real matrix Q_out with orthonormal columns, !! which are the first N columns of a product of real orthogonal !! matrices of order M which are returned by DLATSQR !! Q_out = first_N_columns_of( Q(1)_in * Q(2)_in * ... * Q(k)_in ). !! See the documentation for DLATSQR. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorgtsqr( m, n, mb, nb, a, lda, t, ldt, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,mb,nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: t(ldt,*) real(dp), intent(out) :: work(*) end subroutine dorgtsqr #else module procedure stdlib${ii}$_dorgtsqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorgtsqr( m, n, mb, nb, a, lda, t, ldt, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,mb,nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: t(ldt,*) real(sp), intent(out) :: work(*) end subroutine sorgtsqr #else module procedure stdlib${ii}$_sorgtsqr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orgtsqr #:endif #:endfor #:endfor end interface orgtsqr interface orgtsqr_row !! ORGTSQR_ROW generates an M-by-N real matrix Q_out with !! orthonormal columns from the output of DLATSQR. These N orthonormal !! columns are the first N columns of a product of complex unitary !! matrices Q(k)_in of order M, which are returned by DLATSQR in !! a special format. !! Q_out = first_N_columns_of( Q(1)_in * Q(2)_in * ... * Q(k)_in ). !! The input matrices Q(k)_in are stored in row and column blocks in A. !! See the documentation of DLATSQR for more details on the format of !! Q(k)_in, where each Q(k)_in is represented by block Householder !! transformations. This routine calls an auxiliary routine DLARFB_GETT, !! where the computation is performed on each individual block. The !! algorithm first sweeps NB-sized column blocks from the right to left !! starting in the bottom row block and continues to the top row block !! (hence _ROW in the routine name). This sweep is in reverse order of !! the order in which DLATSQR generates the output blocks. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorgtsqr_row( m, n, mb, nb, a, lda, t, ldt, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,mb,nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: t(ldt,*) real(dp), intent(out) :: work(*) end subroutine dorgtsqr_row #else module procedure stdlib${ii}$_dorgtsqr_row #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorgtsqr_row( m, n, mb, nb, a, lda, t, ldt, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,mb,nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: t(ldt,*) real(sp), intent(out) :: work(*) end subroutine sorgtsqr_row #else module procedure stdlib${ii}$_sorgtsqr_row #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orgtsqr_row #:endif #:endfor #:endfor end interface orgtsqr_row interface orhr_col !! ORHR_COL takes an M-by-N real matrix Q_in with orthonormal columns !! as input, stored in A, and performs Householder Reconstruction (HR), !! i.e. reconstructs Householder vectors V(i) implicitly representing !! another M-by-N matrix Q_out, with the property that Q_in = Q_out*S, !! where S is an N-by-N diagonal matrix with diagonal entries !! equal to +1 or -1. The Householder vectors (columns V(i) of V) are !! stored in A on output, and the diagonal entries of S are stored in D. !! Block reflectors are also returned in T !! (same output format as DGEQRT). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorhr_col( m, n, nb, a, lda, t, ldt, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*),t(ldt,*) end subroutine dorhr_col #else module procedure stdlib${ii}$_dorhr_col #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorhr_col( m, n, nb, a, lda, t, ldt, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*),t(ldt,*) end subroutine sorhr_col #else module procedure stdlib${ii}$_sorhr_col #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orhr_col #:endif #:endfor #:endfor end interface orhr_col interface orm2l !! ORM2L overwrites the general real m by n matrix C with !! Q * C if SIDE = 'L' and TRANS = 'N', or !! Q**T * C if SIDE = 'L' and TRANS = 'T', or !! C * Q if SIDE = 'R' and TRANS = 'N', or !! C * Q**T if SIDE = 'R' and TRANS = 'T', !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by DGEQLF. Q is of order m if SIDE = 'L' and of order n !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorm2l( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,m,n real(dp), intent(inout) :: a(lda,*),c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dorm2l #else module procedure stdlib${ii}$_dorm2l #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorm2l( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,m,n real(sp), intent(inout) :: a(lda,*),c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sorm2l #else module procedure stdlib${ii}$_sorm2l #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orm2l #:endif #:endfor #:endfor end interface orm2l interface orm2r !! ORM2R overwrites the general real m by n matrix C with !! Q * C if SIDE = 'L' and TRANS = 'N', or !! Q**T* C if SIDE = 'L' and TRANS = 'T', or !! C * Q if SIDE = 'R' and TRANS = 'N', or !! C * Q**T if SIDE = 'R' and TRANS = 'T', !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by DGEQRF. Q is of order m if SIDE = 'L' and of order n !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dorm2r( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,m,n real(dp), intent(inout) :: a(lda,*),c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dorm2r #else module procedure stdlib${ii}$_dorm2r #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sorm2r( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,m,n real(sp), intent(inout) :: a(lda,*),c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sorm2r #else module procedure stdlib${ii}$_sorm2r #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$orm2r #:endif #:endfor #:endfor end interface orm2r interface ormbr !! If VECT = 'Q', ORMBR: overwrites the general real M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! If VECT = 'P', ORMBR overwrites the general real M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': P * C C * P !! TRANS = 'T': P**T * C C * P**T !! Here Q and P**T are the orthogonal matrices determined by DGEBRD when !! reducing a real matrix A to bidiagonal form: A = Q * B * P**T. Q and !! P**T are defined as products of elementary reflectors H(i) and G(i) !! respectively. !! Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the !! order of the orthogonal matrix Q or P**T that is applied. !! If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: !! if nq >= k, Q = H(1) H(2) . . . H(k); !! if nq < k, Q = H(1) H(2) . . . H(nq-1). !! If VECT = 'P', A is assumed to have been a K-by-NQ matrix: !! if k < nq, P = G(1) G(2) . . . G(k); !! if k >= nq, P = G(1) G(2) . . . G(nq-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dormbr( vect, side, trans, m, n, k, a, lda, tau, c,ldc, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n real(dp), intent(inout) :: a(lda,*),c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dormbr #else module procedure stdlib${ii}$_dormbr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sormbr( vect, side, trans, m, n, k, a, lda, tau, c,ldc, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n real(sp), intent(inout) :: a(lda,*),c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sormbr #else module procedure stdlib${ii}$_sormbr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ormbr #:endif #:endfor #:endfor end interface ormbr interface ormhr !! ORMHR overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix of order nq, with nq = m if !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of !! IHI-ILO elementary reflectors, as returned by DGEHRD: !! Q = H(ilo) H(ilo+1) . . . H(ihi-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dormhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(in) :: ihi,ilo,lda,ldc,lwork,m,n integer(${ik}$), intent(out) :: info real(dp), intent(inout) :: a(lda,*),c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dormhr #else module procedure stdlib${ii}$_dormhr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sormhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(in) :: ihi,ilo,lda,ldc,lwork,m,n integer(${ik}$), intent(out) :: info real(sp), intent(inout) :: a(lda,*),c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sormhr #else module procedure stdlib${ii}$_sormhr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ormhr #:endif #:endfor #:endfor end interface ormhr interface ormlq !! ORMLQ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by DGELQF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dormlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n real(dp), intent(inout) :: a(lda,*),c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dormlq #else module procedure stdlib${ii}$_dormlq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sormlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n real(sp), intent(inout) :: a(lda,*),c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sormlq #else module procedure stdlib${ii}$_sormlq #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ormlq #:endif #:endfor #:endfor end interface ormlq interface ormql !! ORMQL overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by DGEQLF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dormql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n real(dp), intent(inout) :: a(lda,*),c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dormql #else module procedure stdlib${ii}$_dormql #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sormql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n real(sp), intent(inout) :: a(lda,*),c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sormql #else module procedure stdlib${ii}$_sormql #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ormql #:endif #:endfor #:endfor end interface ormql interface ormqr !! ORMQR overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by DGEQRF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dormqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n real(dp), intent(inout) :: a(lda,*),c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dormqr #else module procedure stdlib${ii}$_dormqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sormqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n real(sp), intent(inout) :: a(lda,*),c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sormqr #else module procedure stdlib${ii}$_sormqr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ormqr #:endif #:endfor #:endfor end interface ormqr interface ormrq !! ORMRQ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by DGERQF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dormrq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n real(dp), intent(inout) :: a(lda,*),c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dormrq #else module procedure stdlib${ii}$_dormrq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sormrq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n real(sp), intent(inout) :: a(lda,*),c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sormrq #else module procedure stdlib${ii}$_sormrq #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ormrq #:endif #:endfor #:endfor end interface ormrq interface ormrz !! ORMRZ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by DTZRZF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dormrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,l,lda,ldc,lwork,m,n real(dp), intent(inout) :: a(lda,*),c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dormrz #else module procedure stdlib${ii}$_dormrz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sormrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,l,lda,ldc,lwork,m,n real(sp), intent(inout) :: a(lda,*),c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sormrz #else module procedure stdlib${ii}$_sormrz #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ormrz #:endif #:endfor #:endfor end interface ormrz interface ormtr !! ORMTR overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix of order nq, with nq = m if !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of !! nq-1 elementary reflectors, as returned by DSYTRD: !! if UPLO = 'U', Q = H(nq-1) . . . H(2) H(1); !! if UPLO = 'L', Q = H(1) H(2) . . . H(nq-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dormtr( side, uplo, trans, m, n, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldc,lwork,m,n real(dp), intent(inout) :: a(lda,*),c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine dormtr #else module procedure stdlib${ii}$_dormtr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sormtr( side, uplo, trans, m, n, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldc,lwork,m,n real(sp), intent(inout) :: a(lda,*),c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine sormtr #else module procedure stdlib${ii}$_sormtr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ormtr #:endif #:endfor #:endfor end interface ormtr interface pbcon !! PBCON estimates the reciprocal of the condition number (in the !! 1-norm) of a complex Hermitian positive definite band matrix using !! the Cholesky factorization A = U**H*U or A = L*L**H computed by !! CPBTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpbcon( uplo, n, kd, ab, ldab, anorm, rcond, work,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond,rwork(*) complex(sp), intent(in) :: ab(ldab,*) complex(sp), intent(out) :: work(*) end subroutine cpbcon #else module procedure stdlib${ii}$_cpbcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpbcon( uplo, n, kd, ab, ldab, anorm, rcond, work,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(in) :: anorm,ab(ldab,*) real(dp), intent(out) :: rcond,work(*) end subroutine dpbcon #else module procedure stdlib${ii}$_dpbcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spbcon( uplo, n, kd, ab, ldab, anorm, rcond, work,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(in) :: anorm,ab(ldab,*) real(sp), intent(out) :: rcond,work(*) end subroutine spbcon #else module procedure stdlib${ii}$_spbcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpbcon( uplo, n, kd, ab, ldab, anorm, rcond, work,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond,rwork(*) complex(dp), intent(in) :: ab(ldab,*) complex(dp), intent(out) :: work(*) end subroutine zpbcon #else module procedure stdlib${ii}$_zpbcon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbcon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbcon #:endif #:endfor #:endfor end interface pbcon interface pbequ !! PBEQU computes row and column scalings intended to equilibrate a !! Hermitian positive definite band matrix A and reduce its condition !! number (with respect to the two-norm). S contains the scale factors, !! S(i) = 1/sqrt(A(i,i)), chosen so that the scaled matrix B with !! elements B(i,j) = S(i)*A(i,j)*S(j) has ones on the diagonal. This !! choice of S puts the condition number of B within a factor N of the !! smallest possible condition number over all possible diagonal !! scalings. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpbequ( uplo, n, kd, ab, ldab, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(out) :: amax,scond,s(*) complex(sp), intent(in) :: ab(ldab,*) end subroutine cpbequ #else module procedure stdlib${ii}$_cpbequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpbequ( uplo, n, kd, ab, ldab, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(out) :: amax,scond,s(*) real(dp), intent(in) :: ab(ldab,*) end subroutine dpbequ #else module procedure stdlib${ii}$_dpbequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spbequ( uplo, n, kd, ab, ldab, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(out) :: amax,scond,s(*) real(sp), intent(in) :: ab(ldab,*) end subroutine spbequ #else module procedure stdlib${ii}$_spbequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpbequ( uplo, n, kd, ab, ldab, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(out) :: amax,scond,s(*) complex(dp), intent(in) :: ab(ldab,*) end subroutine zpbequ #else module procedure stdlib${ii}$_zpbequ #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbequ #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbequ #:endif #:endfor #:endfor end interface pbequ interface pbrfs !! PBRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and banded, and provides error bounds and backward error estimates !! for the solution. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b,ldb, x, ldx, & ferr, berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldafb,ldb,ldx,n,nrhs real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: ab(ldab,*),afb(ldafb,*),b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine cpbrfs #else module procedure stdlib${ii}$_cpbrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b,ldb, x, ldx, & ferr, berr, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,ldafb,ldb,ldx,n,nrhs real(dp), intent(in) :: ab(ldab,*),afb(ldafb,*),b(ldb,*) real(dp), intent(out) :: berr(*),ferr(*),work(*) real(dp), intent(inout) :: x(ldx,*) end subroutine dpbrfs #else module procedure stdlib${ii}$_dpbrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b,ldb, x, ldx, & ferr, berr, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,ldafb,ldb,ldx,n,nrhs real(sp), intent(in) :: ab(ldab,*),afb(ldafb,*),b(ldb,*) real(sp), intent(out) :: berr(*),ferr(*),work(*) real(sp), intent(inout) :: x(ldx,*) end subroutine spbrfs #else module procedure stdlib${ii}$_spbrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b,ldb, x, ldx, & ferr, berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldafb,ldb,ldx,n,nrhs real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: ab(ldab,*),afb(ldafb,*),b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zpbrfs #else module procedure stdlib${ii}$_zpbrfs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbrfs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbrfs #:endif #:endfor #:endfor end interface pbrfs interface pbstf !! PBSTF computes a split Cholesky factorization of a complex !! Hermitian positive definite band matrix A. !! This routine is designed to be used in conjunction with CHBGST. !! The factorization has the form A = S**H*S where S is a band matrix !! of the same bandwidth as A and the following structure: !! S = ( U ) !! ( M L ) !! where U is upper triangular of order m = (n+kd)/2, and L is lower !! triangular of order n-m. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpbstf( uplo, n, kd, ab, ldab, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n complex(sp), intent(inout) :: ab(ldab,*) end subroutine cpbstf #else module procedure stdlib${ii}$_cpbstf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpbstf( uplo, n, kd, ab, ldab, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(inout) :: ab(ldab,*) end subroutine dpbstf #else module procedure stdlib${ii}$_dpbstf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spbstf( uplo, n, kd, ab, ldab, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(inout) :: ab(ldab,*) end subroutine spbstf #else module procedure stdlib${ii}$_spbstf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpbstf( uplo, n, kd, ab, ldab, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n complex(dp), intent(inout) :: ab(ldab,*) end subroutine zpbstf #else module procedure stdlib${ii}$_zpbstf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbstf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbstf #:endif #:endfor #:endfor end interface pbstf interface pbsv !! PBSV computes the solution to a complex system of linear equations !! A * X = B, !! where A is an N-by-N Hermitian positive definite band matrix and X !! and B are N-by-NRHS matrices. !! The Cholesky decomposition is used to factor A as !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular band matrix, and L is a lower !! triangular band matrix, with the same number of superdiagonals or !! subdiagonals as A. The factored form of A is then used to solve the !! system of equations A * X = B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpbsv( uplo, n, kd, nrhs, ab, ldab, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs complex(sp), intent(inout) :: ab(ldab,*),b(ldb,*) end subroutine cpbsv #else module procedure stdlib${ii}$_cpbsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpbsv( uplo, n, kd, nrhs, ab, ldab, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs real(dp), intent(inout) :: ab(ldab,*),b(ldb,*) end subroutine dpbsv #else module procedure stdlib${ii}$_dpbsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spbsv( uplo, n, kd, nrhs, ab, ldab, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs real(sp), intent(inout) :: ab(ldab,*),b(ldb,*) end subroutine spbsv #else module procedure stdlib${ii}$_spbsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpbsv( uplo, n, kd, nrhs, ab, ldab, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs complex(dp), intent(inout) :: ab(ldab,*),b(ldb,*) end subroutine zpbsv #else module procedure stdlib${ii}$_zpbsv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbsv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbsv #:endif #:endfor #:endfor end interface pbsv interface pbtrf !! PBTRF computes the Cholesky factorization of a complex Hermitian !! positive definite band matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpbtrf( uplo, n, kd, ab, ldab, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n complex(sp), intent(inout) :: ab(ldab,*) end subroutine cpbtrf #else module procedure stdlib${ii}$_cpbtrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpbtrf( uplo, n, kd, ab, ldab, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(inout) :: ab(ldab,*) end subroutine dpbtrf #else module procedure stdlib${ii}$_dpbtrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spbtrf( uplo, n, kd, ab, ldab, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(inout) :: ab(ldab,*) end subroutine spbtrf #else module procedure stdlib${ii}$_spbtrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpbtrf( uplo, n, kd, ab, ldab, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n complex(dp), intent(inout) :: ab(ldab,*) end subroutine zpbtrf #else module procedure stdlib${ii}$_zpbtrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbtrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbtrf #:endif #:endfor #:endfor end interface pbtrf interface pbtrs !! PBTRS solves a system of linear equations A*X = B with a Hermitian !! positive definite band matrix A using the Cholesky factorization !! A = U**H*U or A = L*L**H computed by CPBTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpbtrs( uplo, n, kd, nrhs, ab, ldab, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs complex(sp), intent(in) :: ab(ldab,*) complex(sp), intent(inout) :: b(ldb,*) end subroutine cpbtrs #else module procedure stdlib${ii}$_cpbtrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpbtrs( uplo, n, kd, nrhs, ab, ldab, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs real(dp), intent(in) :: ab(ldab,*) real(dp), intent(inout) :: b(ldb,*) end subroutine dpbtrs #else module procedure stdlib${ii}$_dpbtrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spbtrs( uplo, n, kd, nrhs, ab, ldab, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs real(sp), intent(in) :: ab(ldab,*) real(sp), intent(inout) :: b(ldb,*) end subroutine spbtrs #else module procedure stdlib${ii}$_spbtrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpbtrs( uplo, n, kd, nrhs, ab, ldab, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs complex(dp), intent(in) :: ab(ldab,*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zpbtrs #else module procedure stdlib${ii}$_zpbtrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbtrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pbtrs #:endif #:endfor #:endfor end interface pbtrs interface pftrf !! PFTRF computes the Cholesky factorization of a complex Hermitian !! positive definite matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpftrf( transr, uplo, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info complex(sp), intent(inout) :: a(0:*) end subroutine cpftrf #else module procedure stdlib${ii}$_cpftrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpftrf( transr, uplo, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info real(dp), intent(inout) :: a(0:*) end subroutine dpftrf #else module procedure stdlib${ii}$_dpftrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spftrf( transr, uplo, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info real(sp), intent(inout) :: a(0:*) end subroutine spftrf #else module procedure stdlib${ii}$_spftrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpftrf( transr, uplo, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info complex(dp), intent(inout) :: a(0:*) end subroutine zpftrf #else module procedure stdlib${ii}$_zpftrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pftrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pftrf #:endif #:endfor #:endfor end interface pftrf interface pftri !! PFTRI computes the inverse of a complex Hermitian positive definite !! matrix A using the Cholesky factorization A = U**H*U or A = L*L**H !! computed by CPFTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpftri( transr, uplo, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(sp), intent(inout) :: a(0:*) end subroutine cpftri #else module procedure stdlib${ii}$_cpftri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpftri( transr, uplo, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: a(0:*) end subroutine dpftri #else module procedure stdlib${ii}$_dpftri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spftri( transr, uplo, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: a(0:*) end subroutine spftri #else module procedure stdlib${ii}$_spftri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpftri( transr, uplo, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(dp), intent(inout) :: a(0:*) end subroutine zpftri #else module procedure stdlib${ii}$_zpftri #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pftri #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pftri #:endif #:endfor #:endfor end interface pftri interface pftrs !! PFTRS solves a system of linear equations A*X = B with a Hermitian !! positive definite matrix A using the Cholesky factorization !! A = U**H*U or A = L*L**H computed by CPFTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpftrs( transr, uplo, n, nrhs, a, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs complex(sp), intent(in) :: a(0:*) complex(sp), intent(inout) :: b(ldb,*) end subroutine cpftrs #else module procedure stdlib${ii}$_cpftrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpftrs( transr, uplo, n, nrhs, a, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(dp), intent(in) :: a(0:*) real(dp), intent(inout) :: b(ldb,*) end subroutine dpftrs #else module procedure stdlib${ii}$_dpftrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spftrs( transr, uplo, n, nrhs, a, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(sp), intent(in) :: a(0:*) real(sp), intent(inout) :: b(ldb,*) end subroutine spftrs #else module procedure stdlib${ii}$_spftrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpftrs( transr, uplo, n, nrhs, a, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs complex(dp), intent(in) :: a(0:*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zpftrs #else module procedure stdlib${ii}$_zpftrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pftrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pftrs #:endif #:endfor #:endfor end interface pftrs interface pocon !! POCON estimates the reciprocal of the condition number (in the !! 1-norm) of a complex Hermitian positive definite matrix using the !! Cholesky factorization A = U**H*U or A = L*L**H computed by CPOTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpocon( uplo, n, a, lda, anorm, rcond, work, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond,rwork(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine cpocon #else module procedure stdlib${ii}$_cpocon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpocon( uplo, n, a, lda, anorm, rcond, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond,work(*) real(dp), intent(inout) :: a(lda,*) end subroutine dpocon #else module procedure stdlib${ii}$_dpocon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spocon( uplo, n, a, lda, anorm, rcond, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond,work(*) real(sp), intent(inout) :: a(lda,*) end subroutine spocon #else module procedure stdlib${ii}$_spocon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpocon( uplo, n, a, lda, anorm, rcond, work, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond,rwork(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zpocon #else module procedure stdlib${ii}$_zpocon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pocon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pocon #:endif #:endfor #:endfor end interface pocon interface poequ !! POEQU computes row and column scalings intended to equilibrate a !! Hermitian positive definite matrix A and reduce its condition number !! (with respect to the two-norm). S contains the scale factors, !! S(i) = 1/sqrt(A(i,i)), chosen so that the scaled matrix B with !! elements B(i,j) = S(i)*A(i,j)*S(j) has ones on the diagonal. This !! choice of S puts the condition number of B within a factor N of the !! smallest possible condition number over all possible diagonal !! scalings. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpoequ( n, a, lda, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: amax,scond,s(*) complex(sp), intent(in) :: a(lda,*) end subroutine cpoequ #else module procedure stdlib${ii}$_cpoequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpoequ( n, a, lda, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: amax,scond,s(*) real(dp), intent(in) :: a(lda,*) end subroutine dpoequ #else module procedure stdlib${ii}$_dpoequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spoequ( n, a, lda, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: amax,scond,s(*) real(sp), intent(in) :: a(lda,*) end subroutine spoequ #else module procedure stdlib${ii}$_spoequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpoequ( n, a, lda, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: amax,scond,s(*) complex(dp), intent(in) :: a(lda,*) end subroutine zpoequ #else module procedure stdlib${ii}$_zpoequ #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$poequ #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$poequ #:endif #:endfor #:endfor end interface poequ interface poequb !! POEQUB computes row and column scalings intended to equilibrate a !! Hermitian positive definite matrix A and reduce its condition number !! (with respect to the two-norm). S contains the scale factors, !! S(i) = 1/sqrt(A(i,i)), chosen so that the scaled matrix B with !! elements B(i,j) = S(i)*A(i,j)*S(j) has ones on the diagonal. This !! choice of S puts the condition number of B within a factor N of the !! smallest possible condition number over all possible diagonal !! scalings. !! This routine differs from CPOEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled diagonal entries are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpoequb( n, a, lda, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: amax,scond,s(*) complex(sp), intent(in) :: a(lda,*) end subroutine cpoequb #else module procedure stdlib${ii}$_cpoequb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpoequb( n, a, lda, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: amax,scond,s(*) real(dp), intent(in) :: a(lda,*) end subroutine dpoequb #else module procedure stdlib${ii}$_dpoequb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spoequb( n, a, lda, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: amax,scond,s(*) real(sp), intent(in) :: a(lda,*) end subroutine spoequb #else module procedure stdlib${ii}$_spoequb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpoequb( n, a, lda, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: amax,scond,s(*) complex(dp), intent(in) :: a(lda,*) end subroutine zpoequb #else module procedure stdlib${ii}$_zpoequb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$poequb #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$poequb #:endif #:endfor #:endfor end interface poequb interface porfs !! PORFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite, !! and provides error bounds and backward error estimates for the !! solution. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x,ldx, ferr, berr,& work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine cporfs #else module procedure stdlib${ii}$_cporfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x,ldx, ferr, berr,& work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs real(dp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) real(dp), intent(out) :: berr(*),ferr(*),work(*) real(dp), intent(inout) :: x(ldx,*) end subroutine dporfs #else module procedure stdlib${ii}$_dporfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x,ldx, ferr, berr,& work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs real(sp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) real(sp), intent(out) :: berr(*),ferr(*),work(*) real(sp), intent(inout) :: x(ldx,*) end subroutine sporfs #else module procedure stdlib${ii}$_sporfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x,ldx, ferr, berr,& work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zporfs #else module procedure stdlib${ii}$_zporfs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$porfs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$porfs #:endif #:endfor #:endfor end interface porfs interface posv !! POSV computes the solution to a complex system of linear equations !! A * X = B, !! where A is an N-by-N Hermitian positive definite matrix and X and B !! are N-by-NRHS matrices. !! The Cholesky decomposition is used to factor A as !! A = U**H* U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is a lower triangular !! matrix. The factored form of A is then used to solve the system of !! equations A * X = B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cposv( uplo, n, nrhs, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine cposv #else module procedure stdlib${ii}$_cposv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dposv( uplo, n, nrhs, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs real(dp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine dposv #else module procedure stdlib${ii}$_dposv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sposv( uplo, n, nrhs, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs real(sp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine sposv #else module procedure stdlib${ii}$_sposv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zposv( uplo, n, nrhs, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) end subroutine zposv #else module procedure stdlib${ii}$_zposv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$posv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$posv #:endif #:endfor #:endfor end interface posv interface potrf !! POTRF computes the Cholesky factorization of a complex Hermitian !! positive definite matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpotrf( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n complex(sp), intent(inout) :: a(lda,*) end subroutine cpotrf #else module procedure stdlib${ii}$_cpotrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpotrf( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(inout) :: a(lda,*) end subroutine dpotrf #else module procedure stdlib${ii}$_dpotrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spotrf( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(inout) :: a(lda,*) end subroutine spotrf #else module procedure stdlib${ii}$_spotrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpotrf( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n complex(dp), intent(inout) :: a(lda,*) end subroutine zpotrf #else module procedure stdlib${ii}$_zpotrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$potrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$potrf #:endif #:endfor #:endfor end interface potrf interface potrf2 !! POTRF2 computes the Cholesky factorization of a Hermitian !! positive definite matrix A using the recursive algorithm. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the recursive version of the algorithm. It divides !! the matrix into four submatrices: !! [ A11 | A12 ] where A11 is n1 by n1 and A22 is n2 by n2 !! A = [ -----|----- ] with n1 = n/2 !! [ A21 | A22 ] n2 = n-n1 !! The subroutine calls itself to factor A11. Update and scale A21 !! or A12, update A22 then calls itself to factor A22. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine cpotrf2( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n complex(sp), intent(inout) :: a(lda,*) end subroutine cpotrf2 #else module procedure stdlib${ii}$_cpotrf2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine dpotrf2( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(inout) :: a(lda,*) end subroutine dpotrf2 #else module procedure stdlib${ii}$_dpotrf2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine spotrf2( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(inout) :: a(lda,*) end subroutine spotrf2 #else module procedure stdlib${ii}$_spotrf2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure recursive subroutine zpotrf2( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n complex(dp), intent(inout) :: a(lda,*) end subroutine zpotrf2 #else module procedure stdlib${ii}$_zpotrf2 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$potrf2 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$potrf2 #:endif #:endfor #:endfor end interface potrf2 interface potri !! POTRI computes the inverse of a complex Hermitian positive definite !! matrix A using the Cholesky factorization A = U**H*U or A = L*L**H !! computed by CPOTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpotri( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n complex(sp), intent(inout) :: a(lda,*) end subroutine cpotri #else module procedure stdlib${ii}$_cpotri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpotri( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(inout) :: a(lda,*) end subroutine dpotri #else module procedure stdlib${ii}$_dpotri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spotri( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(inout) :: a(lda,*) end subroutine spotri #else module procedure stdlib${ii}$_spotri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpotri( uplo, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n complex(dp), intent(inout) :: a(lda,*) end subroutine zpotri #else module procedure stdlib${ii}$_zpotri #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$potri #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$potri #:endif #:endfor #:endfor end interface potri interface potrs !! POTRS solves a system of linear equations A*X = B with a Hermitian !! positive definite matrix A using the Cholesky factorization !! A = U**H*U or A = L*L**H computed by CPOTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpotrs( uplo, n, nrhs, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: b(ldb,*) end subroutine cpotrs #else module procedure stdlib${ii}$_cpotrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpotrs( uplo, n, nrhs, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: b(ldb,*) end subroutine dpotrs #else module procedure stdlib${ii}$_dpotrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spotrs( uplo, n, nrhs, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: b(ldb,*) end subroutine spotrs #else module procedure stdlib${ii}$_spotrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpotrs( uplo, n, nrhs, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zpotrs #else module procedure stdlib${ii}$_zpotrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$potrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$potrs #:endif #:endfor #:endfor end interface potrs interface ppcon !! PPCON estimates the reciprocal of the condition number (in the !! 1-norm) of a complex Hermitian positive definite packed matrix using !! the Cholesky factorization A = U**H*U or A = L*L**H computed by !! CPPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cppcon( uplo, n, ap, anorm, rcond, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond,rwork(*) complex(sp), intent(in) :: ap(*) complex(sp), intent(out) :: work(*) end subroutine cppcon #else module procedure stdlib${ii}$_cppcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dppcon( uplo, n, ap, anorm, rcond, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: n real(dp), intent(in) :: anorm,ap(*) real(dp), intent(out) :: rcond,work(*) end subroutine dppcon #else module procedure stdlib${ii}$_dppcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sppcon( uplo, n, ap, anorm, rcond, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: n real(sp), intent(in) :: anorm,ap(*) real(sp), intent(out) :: rcond,work(*) end subroutine sppcon #else module procedure stdlib${ii}$_sppcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zppcon( uplo, n, ap, anorm, rcond, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond,rwork(*) complex(dp), intent(in) :: ap(*) complex(dp), intent(out) :: work(*) end subroutine zppcon #else module procedure stdlib${ii}$_zppcon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ppcon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ppcon #:endif #:endfor #:endfor end interface ppcon interface ppequ !! PPEQU computes row and column scalings intended to equilibrate a !! Hermitian positive definite matrix A in packed storage and reduce !! its condition number (with respect to the two-norm). S contains the !! scale factors, S(i)=1/sqrt(A(i,i)), chosen so that the scaled matrix !! B with elements B(i,j)=S(i)*A(i,j)*S(j) has ones on the diagonal. !! This choice of S puts the condition number of B within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cppequ( uplo, n, ap, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(out) :: amax,scond,s(*) complex(sp), intent(in) :: ap(*) end subroutine cppequ #else module procedure stdlib${ii}$_cppequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dppequ( uplo, n, ap, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: amax,scond,s(*) real(dp), intent(in) :: ap(*) end subroutine dppequ #else module procedure stdlib${ii}$_dppequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sppequ( uplo, n, ap, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(out) :: amax,scond,s(*) real(sp), intent(in) :: ap(*) end subroutine sppequ #else module procedure stdlib${ii}$_sppequ #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zppequ( uplo, n, ap, s, scond, amax, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: amax,scond,s(*) complex(dp), intent(in) :: ap(*) end subroutine zppequ #else module procedure stdlib${ii}$_zppequ #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ppequ #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ppequ #:endif #:endfor #:endfor end interface ppequ interface pprfs !! PPRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and packed, and provides error bounds and backward error estimates !! for the solution. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr,berr, work, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: afp(*),ap(*),b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine cpprfs #else module procedure stdlib${ii}$_cpprfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr,berr, work, & iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(dp), intent(in) :: afp(*),ap(*),b(ldb,*) real(dp), intent(out) :: berr(*),ferr(*),work(*) real(dp), intent(inout) :: x(ldx,*) end subroutine dpprfs #else module procedure stdlib${ii}$_dpprfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr,berr, work, & iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(sp), intent(in) :: afp(*),ap(*),b(ldb,*) real(sp), intent(out) :: berr(*),ferr(*),work(*) real(sp), intent(inout) :: x(ldx,*) end subroutine spprfs #else module procedure stdlib${ii}$_spprfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr,berr, work, & rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: afp(*),ap(*),b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zpprfs #else module procedure stdlib${ii}$_zpprfs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pprfs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pprfs #:endif #:endfor #:endfor end interface pprfs interface ppsv !! PPSV computes the solution to a complex system of linear equations !! A * X = B, !! where A is an N-by-N Hermitian positive definite matrix stored in !! packed format and X and B are N-by-NRHS matrices. !! The Cholesky decomposition is used to factor A as !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is a lower triangular !! matrix. The factored form of A is then used to solve the system of !! equations A * X = B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cppsv( uplo, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs complex(sp), intent(inout) :: ap(*),b(ldb,*) end subroutine cppsv #else module procedure stdlib${ii}$_cppsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dppsv( uplo, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(dp), intent(inout) :: ap(*),b(ldb,*) end subroutine dppsv #else module procedure stdlib${ii}$_dppsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sppsv( uplo, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(sp), intent(inout) :: ap(*),b(ldb,*) end subroutine sppsv #else module procedure stdlib${ii}$_sppsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zppsv( uplo, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs complex(dp), intent(inout) :: ap(*),b(ldb,*) end subroutine zppsv #else module procedure stdlib${ii}$_zppsv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ppsv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ppsv #:endif #:endfor #:endfor end interface ppsv interface pptrf !! PPTRF computes the Cholesky factorization of a complex Hermitian !! positive definite matrix A stored in packed format. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpptrf( uplo, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(sp), intent(inout) :: ap(*) end subroutine cpptrf #else module procedure stdlib${ii}$_cpptrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpptrf( uplo, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: ap(*) end subroutine dpptrf #else module procedure stdlib${ii}$_dpptrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spptrf( uplo, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: ap(*) end subroutine spptrf #else module procedure stdlib${ii}$_spptrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpptrf( uplo, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(dp), intent(inout) :: ap(*) end subroutine zpptrf #else module procedure stdlib${ii}$_zpptrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pptrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pptrf #:endif #:endfor #:endfor end interface pptrf interface pptri !! PPTRI computes the inverse of a complex Hermitian positive definite !! matrix A using the Cholesky factorization A = U**H*U or A = L*L**H !! computed by CPPTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpptri( uplo, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(sp), intent(inout) :: ap(*) end subroutine cpptri #else module procedure stdlib${ii}$_cpptri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpptri( uplo, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: ap(*) end subroutine dpptri #else module procedure stdlib${ii}$_dpptri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spptri( uplo, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: ap(*) end subroutine spptri #else module procedure stdlib${ii}$_spptri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpptri( uplo, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(dp), intent(inout) :: ap(*) end subroutine zpptri #else module procedure stdlib${ii}$_zpptri #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pptri #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pptri #:endif #:endfor #:endfor end interface pptri interface pptrs !! PPTRS solves a system of linear equations A*X = B with a Hermitian !! positive definite matrix A in packed storage using the Cholesky !! factorization A = U**H*U or A = L*L**H computed by CPPTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpptrs( uplo, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs complex(sp), intent(in) :: ap(*) complex(sp), intent(inout) :: b(ldb,*) end subroutine cpptrs #else module procedure stdlib${ii}$_cpptrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpptrs( uplo, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(dp), intent(in) :: ap(*) real(dp), intent(inout) :: b(ldb,*) end subroutine dpptrs #else module procedure stdlib${ii}$_dpptrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spptrs( uplo, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(sp), intent(in) :: ap(*) real(sp), intent(inout) :: b(ldb,*) end subroutine spptrs #else module procedure stdlib${ii}$_spptrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpptrs( uplo, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs complex(dp), intent(in) :: ap(*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zpptrs #else module procedure stdlib${ii}$_zpptrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pptrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pptrs #:endif #:endfor #:endfor end interface pptrs interface pstrf !! PSTRF computes the Cholesky factorization with complete !! pivoting of a complex Hermitian positive semidefinite matrix A. !! The factorization has the form !! P**T * A * P = U**H * U , if UPLO = 'U', !! P**T * A * P = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular, and !! P is stored as vector PIV. !! This algorithm does not attempt to check that A is positive !! semidefinite. This version of the algorithm calls level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpstrf( uplo, n, a, lda, piv, rank, tol, work, info ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: tol integer(${ik}$), intent(out) :: info,rank,piv(n) integer(${ik}$), intent(in) :: lda,n character, intent(in) :: uplo complex(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(2*n) end subroutine cpstrf #else module procedure stdlib${ii}$_cpstrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpstrf( uplo, n, a, lda, piv, rank, tol, work, info ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: tol integer(${ik}$), intent(out) :: info,rank,piv(n) integer(${ik}$), intent(in) :: lda,n character, intent(in) :: uplo real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(2*n) end subroutine dpstrf #else module procedure stdlib${ii}$_dpstrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spstrf( uplo, n, a, lda, piv, rank, tol, work, info ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: tol integer(${ik}$), intent(out) :: info,rank,piv(n) integer(${ik}$), intent(in) :: lda,n character, intent(in) :: uplo real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(2*n) end subroutine spstrf #else module procedure stdlib${ii}$_spstrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpstrf( uplo, n, a, lda, piv, rank, tol, work, info ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: tol integer(${ik}$), intent(out) :: info,rank,piv(n) integer(${ik}$), intent(in) :: lda,n character, intent(in) :: uplo complex(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(2*n) end subroutine zpstrf #else module procedure stdlib${ii}$_zpstrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pstrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pstrf #:endif #:endfor #:endfor end interface pstrf interface ptcon !! PTCON computes the reciprocal of the condition number (in the !! 1-norm) of a complex Hermitian positive definite tridiagonal matrix !! using the factorization A = L*D*L**H or A = U**H*D*U computed by !! CPTTRF. !! Norm(inv(A)) is computed by a direct method, and the reciprocal of !! the condition number is computed as !! RCOND = 1 / (ANORM * norm(inv(A))). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cptcon( n, d, e, anorm, rcond, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(in) :: anorm,d(*) real(sp), intent(out) :: rcond,rwork(*) complex(sp), intent(in) :: e(*) end subroutine cptcon #else module procedure stdlib${ii}$_cptcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dptcon( n, d, e, anorm, rcond, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(in) :: anorm,d(*),e(*) real(dp), intent(out) :: rcond,work(*) end subroutine dptcon #else module procedure stdlib${ii}$_dptcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sptcon( n, d, e, anorm, rcond, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(in) :: anorm,d(*),e(*) real(sp), intent(out) :: rcond,work(*) end subroutine sptcon #else module procedure stdlib${ii}$_sptcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zptcon( n, d, e, anorm, rcond, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(in) :: anorm,d(*) real(dp), intent(out) :: rcond,rwork(*) complex(dp), intent(in) :: e(*) end subroutine zptcon #else module procedure stdlib${ii}$_zptcon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ptcon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ptcon #:endif #:endfor #:endfor end interface ptcon interface pteqr !! PTEQR computes all eigenvalues and, optionally, eigenvectors of a !! symmetric positive definite tridiagonal matrix by first factoring the !! matrix using SPTTRF and then calling CBDSQR to compute the singular !! values of the bidiagonal factor. !! This routine computes the eigenvalues of the positive definite !! tridiagonal matrix to high relative accuracy. This means that if the !! eigenvalues range over many orders of magnitude in size, then the !! small eigenvalues and corresponding eigenvectors will be computed !! more accurately than, for example, with the standard QR method. !! The eigenvectors of a full or band positive definite Hermitian matrix !! can also be found if CHETRD, CHPTRD, or CHBTRD has been used to !! reduce this matrix to tridiagonal form. (The reduction to !! tridiagonal form, however, may preclude the possibility of obtaining !! high relative accuracy in the small eigenvalues of the original !! matrix, if these eigenvalues range over many orders of magnitude.) #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpteqr( compz, n, d, e, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: work(*) complex(sp), intent(inout) :: z(ldz,*) end subroutine cpteqr #else module procedure stdlib${ii}$_cpteqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpteqr( compz, n, d, e, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(dp), intent(inout) :: d(*),e(*),z(ldz,*) real(dp), intent(out) :: work(*) end subroutine dpteqr #else module procedure stdlib${ii}$_dpteqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spteqr( compz, n, d, e, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(sp), intent(inout) :: d(*),e(*),z(ldz,*) real(sp), intent(out) :: work(*) end subroutine spteqr #else module procedure stdlib${ii}$_spteqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpteqr( compz, n, d, e, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: work(*) complex(dp), intent(inout) :: z(ldz,*) end subroutine zpteqr #else module procedure stdlib${ii}$_zpteqr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pteqr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pteqr #:endif #:endfor #:endfor end interface pteqr interface ptrfs !! PTRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and tridiagonal, and provides error bounds and backward error !! estimates for the solution. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cptrfs( uplo, n, nrhs, d, e, df, ef, b, ldb, x, ldx,ferr, berr, & work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(sp), intent(out) :: berr(*),ferr(*),rwork(*) real(sp), intent(in) :: d(*),df(*) complex(sp), intent(in) :: b(ldb,*),e(*),ef(*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine cptrfs #else module procedure stdlib${ii}$_cptrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dptrfs( n, nrhs, d, e, df, ef, b, ldb, x, ldx, ferr,berr, work, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(dp), intent(in) :: b(ldb,*),d(*),df(*),e(*),ef(*) real(dp), intent(out) :: berr(*),ferr(*),work(*) real(dp), intent(inout) :: x(ldx,*) end subroutine dptrfs #else module procedure stdlib${ii}$_dptrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sptrfs( n, nrhs, d, e, df, ef, b, ldb, x, ldx, ferr,berr, work, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(sp), intent(in) :: b(ldb,*),d(*),df(*),e(*),ef(*) real(sp), intent(out) :: berr(*),ferr(*),work(*) real(sp), intent(inout) :: x(ldx,*) end subroutine sptrfs #else module procedure stdlib${ii}$_sptrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zptrfs( uplo, n, nrhs, d, e, df, ef, b, ldb, x, ldx,ferr, berr, & work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(dp), intent(out) :: berr(*),ferr(*),rwork(*) real(dp), intent(in) :: d(*),df(*) complex(dp), intent(in) :: b(ldb,*),e(*),ef(*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zptrfs #else module procedure stdlib${ii}$_zptrfs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ptrfs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ptrfs #:endif #:endfor #:endfor end interface ptrfs interface ptsv !! PTSV computes the solution to a complex system of linear equations !! A*X = B, where A is an N-by-N Hermitian positive definite tridiagonal !! matrix, and X and B are N-by-NRHS matrices. !! A is factored as A = L*D*L**H, and the factored form of A is then !! used to solve the system of equations. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cptsv( n, nrhs, d, e, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(sp), intent(inout) :: d(*) complex(sp), intent(inout) :: b(ldb,*),e(*) end subroutine cptsv #else module procedure stdlib${ii}$_cptsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dptsv( n, nrhs, d, e, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(dp), intent(inout) :: b(ldb,*),d(*),e(*) end subroutine dptsv #else module procedure stdlib${ii}$_dptsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sptsv( n, nrhs, d, e, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(sp), intent(inout) :: b(ldb,*),d(*),e(*) end subroutine sptsv #else module procedure stdlib${ii}$_sptsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zptsv( n, nrhs, d, e, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(dp), intent(inout) :: d(*) complex(dp), intent(inout) :: b(ldb,*),e(*) end subroutine zptsv #else module procedure stdlib${ii}$_zptsv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ptsv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ptsv #:endif #:endfor #:endfor end interface ptsv interface pttrf !! PTTRF computes the L*D*L**H factorization of a complex Hermitian !! positive definite tridiagonal matrix A. The factorization may also !! be regarded as having the form A = U**H *D*U. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpttrf( n, d, e, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: d(*) complex(sp), intent(inout) :: e(*) end subroutine cpttrf #else module procedure stdlib${ii}$_cpttrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpttrf( n, d, e, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: d(*),e(*) end subroutine dpttrf #else module procedure stdlib${ii}$_dpttrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spttrf( n, d, e, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: d(*),e(*) end subroutine spttrf #else module procedure stdlib${ii}$_spttrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpttrf( n, d, e, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: d(*) complex(dp), intent(inout) :: e(*) end subroutine zpttrf #else module procedure stdlib${ii}$_zpttrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pttrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pttrf #:endif #:endfor #:endfor end interface pttrf interface pttrs !! PTTRS solves a tridiagonal system of the form !! A * X = B !! using the factorization A = U**H*D*U or A = L*D*L**H computed by CPTTRF. !! D is a diagonal matrix specified in the vector D, U (or L) is a unit !! bidiagonal matrix whose superdiagonal (subdiagonal) is specified in !! the vector E, and X and B are N by NRHS matrices. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cpttrs( uplo, n, nrhs, d, e, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(sp), intent(in) :: d(*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(in) :: e(*) end subroutine cpttrs #else module procedure stdlib${ii}$_cpttrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dpttrs( n, nrhs, d, e, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(dp), intent(inout) :: b(ldb,*) real(dp), intent(in) :: d(*),e(*) end subroutine dpttrs #else module procedure stdlib${ii}$_dpttrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine spttrs( n, nrhs, d, e, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(sp), intent(inout) :: b(ldb,*) real(sp), intent(in) :: d(*),e(*) end subroutine spttrs #else module procedure stdlib${ii}$_spttrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zpttrs( uplo, n, nrhs, d, e, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(dp), intent(in) :: d(*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(in) :: e(*) end subroutine zpttrs #else module procedure stdlib${ii}$_zpttrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pttrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$pttrs #:endif #:endfor #:endfor end interface pttrs interface rot !! ROT applies a plane rotation, where the cos (C) is real and the !! sin (S) is complex, and the vectors CX and CY are complex. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine crot( n, cx, incx, cy, incy, c, s ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(sp), intent(in) :: c complex(sp), intent(in) :: s complex(sp), intent(inout) :: cx(*),cy(*) end subroutine crot #else module procedure stdlib${ii}$_crot #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zrot( n, cx, incx, cy, incy, c, s ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,incy,n real(dp), intent(in) :: c complex(dp), intent(in) :: s complex(dp), intent(inout) :: cx(*),cy(*) end subroutine zrot #else module procedure stdlib${ii}$_zrot #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$rot #:endif #:endfor #:endfor end interface rot interface rscl !! RSCL multiplies an n-element real vector x by the real scalar 1/a. !! This is done without overflow or underflow as long as !! the final result x/a does not overflow or underflow. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine drscl( n, sa, sx, incx ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n real(dp), intent(in) :: sa real(dp), intent(inout) :: sx(*) end subroutine drscl #else module procedure stdlib${ii}$_drscl #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine srscl( n, sa, sx, incx ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx,n real(sp), intent(in) :: sa real(sp), intent(inout) :: sx(*) end subroutine srscl #else module procedure stdlib${ii}$_srscl #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$rscl #:endif #:endfor #:endfor end interface rscl interface sb2st_kernels !! SB2ST_KERNELS is an internal routine used by the DSYTRD_SB2ST !! subroutine. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsb2st_kernels( uplo, wantz, ttype,st, ed, sweep, n, nb, ib,a, & lda, v, tau, ldvt, work) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo logical(lk), intent(in) :: wantz integer(${ik}$), intent(in) :: ttype,st,ed,sweep,n,nb,ib,lda,ldvt real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: v(*),tau(*),work(*) end subroutine dsb2st_kernels #else module procedure stdlib${ii}$_dsb2st_kernels #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssb2st_kernels( uplo, wantz, ttype,st, ed, sweep, n, nb, ib,a, & lda, v, tau, ldvt, work) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo logical(lk), intent(in) :: wantz integer(${ik}$), intent(in) :: ttype,st,ed,sweep,n,nb,ib,lda,ldvt real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: v(*),tau(*),work(*) end subroutine ssb2st_kernels #else module procedure stdlib${ii}$_ssb2st_kernels #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sb2st_kernels #:endif #:endfor #:endfor end interface sb2st_kernels interface sbev !! SBEV computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dsbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldz,n real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dsbev #else module procedure stdlib${ii}$_dsbev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ssbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldz,n real(sp), intent(inout) :: ab(ldab,*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine ssbev #else module procedure stdlib${ii}$_ssbev #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sbev #:endif #:endfor #:endfor end interface sbev interface sbevd !! SBEVD computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. If eigenvectors are desired, it uses !! a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dsbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,ldz,liwork,lwork,n real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dsbevd #else module procedure stdlib${ii}$_dsbevd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ssbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,ldz,liwork,lwork,n real(sp), intent(inout) :: ab(ldab,*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine ssbevd #else module procedure stdlib${ii}$_ssbevd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sbevd #:endif #:endfor #:endfor end interface sbevd interface sbgst !! SBGST reduces a real symmetric-definite banded generalized !! eigenproblem A*x = lambda*B*x to standard form C*y = lambda*y, !! such that C has the same bandwidth as A. !! B must have been previously factorized as S**T*S by DPBSTF, using a !! split Cholesky factorization. A is overwritten by C = X**T*A*X, where !! X = S**(-1)*Q and Q is an orthogonal matrix chosen to preserve the !! bandwidth of A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsbgst( vect, uplo, n, ka, kb, ab, ldab, bb, ldbb, x,ldx, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldx,n real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(in) :: bb(ldbb,*) real(dp), intent(out) :: work(*),x(ldx,*) end subroutine dsbgst #else module procedure stdlib${ii}$_dsbgst #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssbgst( vect, uplo, n, ka, kb, ab, ldab, bb, ldbb, x,ldx, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldx,n real(sp), intent(inout) :: ab(ldab,*) real(sp), intent(in) :: bb(ldbb,*) real(sp), intent(out) :: work(*),x(ldx,*) end subroutine ssbgst #else module procedure stdlib${ii}$_ssbgst #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sbgst #:endif #:endfor #:endfor end interface sbgst interface sbgv !! SBGV computes all the eigenvalues, and optionally, the eigenvectors !! of a real generalized symmetric-definite banded eigenproblem, of !! the form A*x=(lambda)*B*x. Here A and B are assumed to be symmetric !! and banded, and B is also positive definite. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsbgv( jobz, uplo, n, ka, kb, ab, ldab, bb, ldbb, w, z,ldz, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldz,n real(dp), intent(inout) :: ab(ldab,*),bb(ldbb,*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dsbgv #else module procedure stdlib${ii}$_dsbgv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssbgv( jobz, uplo, n, ka, kb, ab, ldab, bb, ldbb, w, z,ldz, work, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldz,n real(sp), intent(inout) :: ab(ldab,*),bb(ldbb,*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine ssbgv #else module procedure stdlib${ii}$_ssbgv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sbgv #:endif #:endfor #:endfor end interface sbgv interface sbgvd !! SBGVD computes all the eigenvalues, and optionally, the eigenvectors !! of a real generalized symmetric-definite banded eigenproblem, of the !! form A*x=(lambda)*B*x. Here A and B are assumed to be symmetric and !! banded, and B is also positive definite. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsbgvd( jobz, uplo, n, ka, kb, ab, ldab, bb, ldbb, w,z, ldz, work, & lwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldz,liwork,lwork,n real(dp), intent(inout) :: ab(ldab,*),bb(ldbb,*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dsbgvd #else module procedure stdlib${ii}$_dsbgvd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssbgvd( jobz, uplo, n, ka, kb, ab, ldab, bb, ldbb, w,z, ldz, work, & lwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ka,kb,ldab,ldbb,ldz,liwork,lwork,n real(sp), intent(inout) :: ab(ldab,*),bb(ldbb,*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine ssbgvd #else module procedure stdlib${ii}$_ssbgvd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sbgvd #:endif #:endfor #:endfor end interface sbgvd interface sbtrd !! SBTRD reduces a real symmetric band matrix A to symmetric !! tridiagonal form T by an orthogonal similarity transformation: !! Q**T * A * Q = T. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsbtrd( vect, uplo, n, kd, ab, ldab, d, e, q, ldq,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldq,n real(dp), intent(inout) :: ab(ldab,*),q(ldq,*) real(dp), intent(out) :: d(*),e(*),work(*) end subroutine dsbtrd #else module procedure stdlib${ii}$_dsbtrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssbtrd( vect, uplo, n, kd, ab, ldab, d, e, q, ldq,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldq,n real(sp), intent(inout) :: ab(ldab,*),q(ldq,*) real(sp), intent(out) :: d(*),e(*),work(*) end subroutine ssbtrd #else module procedure stdlib${ii}$_ssbtrd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sbtrd #:endif #:endfor #:endfor end interface sbtrd interface sfrk !! Level 3 BLAS like routine for C in RFP Format. !! SFRK performs one of the symmetric rank--k operations !! C := alpha*A*A**T + beta*C, !! or !! C := alpha*A**T*A + beta*C, !! where alpha and beta are real scalars, C is an n--by--n symmetric !! matrix and A is an n--by--k matrix in the first case and a k--by--n !! matrix in the second case. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsfrk( transr, uplo, trans, n, k, alpha, a, lda, beta,c ) import sp,dp,qp,${ik}$,lk implicit none real(dp), intent(in) :: alpha,beta,a(lda,*) integer(${ik}$), intent(in) :: k,lda,n character, intent(in) :: trans,transr,uplo real(dp), intent(inout) :: c(*) end subroutine dsfrk #else module procedure stdlib${ii}$_dsfrk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssfrk( transr, uplo, trans, n, k, alpha, a, lda, beta,c ) import sp,dp,qp,${ik}$,lk implicit none real(sp), intent(in) :: alpha,beta,a(lda,*) integer(${ik}$), intent(in) :: k,lda,n character, intent(in) :: trans,transr,uplo real(sp), intent(inout) :: c(*) end subroutine ssfrk #else module procedure stdlib${ii}$_ssfrk #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sfrk #:endif #:endfor #:endfor end interface sfrk interface spcon !! SPCON estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric packed matrix A using the !! factorization A = U*D*U**T or A = L*D*L**T computed by CSPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cspcon( uplo, n, ap, ipiv, anorm, rcond, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond complex(sp), intent(in) :: ap(*) complex(sp), intent(out) :: work(*) end subroutine cspcon #else module procedure stdlib${ii}$_cspcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dspcon( uplo, n, ap, ipiv, anorm, rcond, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: n,ipiv(*) real(dp), intent(in) :: anorm,ap(*) real(dp), intent(out) :: rcond,work(*) end subroutine dspcon #else module procedure stdlib${ii}$_dspcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sspcon( uplo, n, ap, ipiv, anorm, rcond, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: n,ipiv(*) real(sp), intent(in) :: anorm,ap(*) real(sp), intent(out) :: rcond,work(*) end subroutine sspcon #else module procedure stdlib${ii}$_sspcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zspcon( uplo, n, ap, ipiv, anorm, rcond, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond complex(dp), intent(in) :: ap(*) complex(dp), intent(out) :: work(*) end subroutine zspcon #else module procedure stdlib${ii}$_zspcon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spcon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spcon #:endif #:endfor #:endfor end interface spcon interface spev !! SPEV computes all the eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A in packed storage. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dspev( jobz, uplo, n, ap, w, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(dp), intent(inout) :: ap(*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dspev #else module procedure stdlib${ii}$_dspev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sspev( jobz, uplo, n, ap, w, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(sp), intent(inout) :: ap(*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine sspev #else module procedure stdlib${ii}$_sspev #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spev #:endif #:endfor #:endfor end interface spev interface spevd !! SPEVD computes all the eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dspevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldz,liwork,lwork,n real(dp), intent(inout) :: ap(*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dspevd #else module procedure stdlib${ii}$_dspevd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sspevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldz,liwork,lwork,n real(sp), intent(inout) :: ap(*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine sspevd #else module procedure stdlib${ii}$_sspevd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spevd #:endif #:endfor #:endfor end interface spevd interface spgst !! SPGST reduces a real symmetric-definite generalized eigenproblem !! to standard form, using packed storage. !! If ITYPE = 1, the problem is A*x = lambda*B*x, !! and A is overwritten by inv(U**T)*A*inv(U) or inv(L)*A*inv(L**T) !! If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or !! B*A*x = lambda*x, and A is overwritten by U*A*U**T or L**T*A*L. !! B must have been previously factorized as U**T*U or L*L**T by DPPTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dspgst( itype, uplo, n, ap, bp, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,n real(dp), intent(inout) :: ap(*) real(dp), intent(in) :: bp(*) end subroutine dspgst #else module procedure stdlib${ii}$_dspgst #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sspgst( itype, uplo, n, ap, bp, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,n real(sp), intent(inout) :: ap(*) real(sp), intent(in) :: bp(*) end subroutine sspgst #else module procedure stdlib${ii}$_sspgst #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spgst #:endif #:endfor #:endfor end interface spgst interface spgv !! SPGV computes all the eigenvalues and, optionally, the eigenvectors !! of a real generalized symmetric-definite eigenproblem, of the form !! A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. !! Here A and B are assumed to be symmetric, stored in packed format, !! and B is also positive definite. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dspgv( itype, jobz, uplo, n, ap, bp, w, z, ldz, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,ldz,n real(dp), intent(inout) :: ap(*),bp(*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dspgv #else module procedure stdlib${ii}$_dspgv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sspgv( itype, jobz, uplo, n, ap, bp, w, z, ldz, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,ldz,n real(sp), intent(inout) :: ap(*),bp(*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine sspgv #else module procedure stdlib${ii}$_sspgv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spgv #:endif #:endfor #:endfor end interface spgv interface spgvd !! SPGVD computes all the eigenvalues, and optionally, the eigenvectors !! of a real generalized symmetric-definite eigenproblem, of the form !! A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. Here A and !! B are assumed to be symmetric, stored in packed format, and B is also !! positive definite. !! If eigenvectors are desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dspgvd( itype, jobz, uplo, n, ap, bp, w, z, ldz, work,lwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: itype,ldz,liwork,lwork,n real(dp), intent(inout) :: ap(*),bp(*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dspgvd #else module procedure stdlib${ii}$_dspgvd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine sspgvd( itype, jobz, uplo, n, ap, bp, w, z, ldz, work,lwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: itype,ldz,liwork,lwork,n real(sp), intent(inout) :: ap(*),bp(*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine sspgvd #else module procedure stdlib${ii}$_sspgvd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spgvd #:endif #:endfor #:endfor end interface spgvd interface spmv !! SPMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix, supplied in packed form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cspmv( uplo, n, alpha, ap, x, incx, beta, y, incy ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx,incy,n complex(sp), intent(in) :: alpha,beta,ap(*),x(*) complex(sp), intent(inout) :: y(*) end subroutine cspmv #else module procedure stdlib${ii}$_cspmv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zspmv( uplo, n, alpha, ap, x, incx, beta, y, incy ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx,incy,n complex(dp), intent(in) :: alpha,beta,ap(*),x(*) complex(dp), intent(inout) :: y(*) end subroutine zspmv #else module procedure stdlib${ii}$_zspmv #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spmv #:endif #:endfor #:endfor end interface spmv interface spr !! SPR performs the symmetric rank 1 operation !! A := alpha*x*x**H + A, !! where alpha is a complex scalar, x is an n element vector and A is an !! n by n symmetric matrix, supplied in packed form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cspr( uplo, n, alpha, x, incx, ap ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx,n complex(sp), intent(in) :: alpha,x(*) complex(sp), intent(inout) :: ap(*) end subroutine cspr #else module procedure stdlib${ii}$_cspr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zspr( uplo, n, alpha, x, incx, ap ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx,n complex(dp), intent(in) :: alpha,x(*) complex(dp), intent(inout) :: ap(*) end subroutine zspr #else module procedure stdlib${ii}$_zspr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spr #:endif #:endfor #:endfor end interface spr interface sprfs !! SPRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite !! and packed, and provides error bounds and backward error estimates !! for the solution. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, & work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs,ipiv(*) real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: afp(*),ap(*),b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine csprfs #else module procedure stdlib${ii}$_csprfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, & work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs,ipiv(*) real(dp), intent(in) :: afp(*),ap(*),b(ldb,*) real(dp), intent(out) :: berr(*),ferr(*),work(*) real(dp), intent(inout) :: x(ldx,*) end subroutine dsprfs #else module procedure stdlib${ii}$_dsprfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, & work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs,ipiv(*) real(sp), intent(in) :: afp(*),ap(*),b(ldb,*) real(sp), intent(out) :: berr(*),ferr(*),work(*) real(sp), intent(inout) :: x(ldx,*) end subroutine ssprfs #else module procedure stdlib${ii}$_ssprfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, & work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs,ipiv(*) real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: afp(*),ap(*),b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zsprfs #else module procedure stdlib${ii}$_zsprfs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sprfs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sprfs #:endif #:endfor #:endfor end interface sprfs interface spsv !! SPSV computes the solution to a complex system of linear equations !! A * X = B, !! where A is an N-by-N symmetric matrix stored in packed format and X !! and B are N-by-NRHS matrices. !! The diagonal pivoting method is used to factor A as !! A = U * D * U**T, if UPLO = 'U', or !! A = L * D * L**T, if UPLO = 'L', !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, D is symmetric and block diagonal with 1-by-1 !! and 2-by-2 diagonal blocks. The factored form of A is then used to !! solve the system of equations A * X = B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cspsv( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: ldb,n,nrhs complex(sp), intent(inout) :: ap(*),b(ldb,*) end subroutine cspsv #else module procedure stdlib${ii}$_cspsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dspsv( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: ldb,n,nrhs real(dp), intent(inout) :: ap(*),b(ldb,*) end subroutine dspsv #else module procedure stdlib${ii}$_dspsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sspsv( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: ldb,n,nrhs real(sp), intent(inout) :: ap(*),b(ldb,*) end subroutine sspsv #else module procedure stdlib${ii}$_sspsv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zspsv( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: ldb,n,nrhs complex(dp), intent(inout) :: ap(*),b(ldb,*) end subroutine zspsv #else module procedure stdlib${ii}$_zspsv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spsv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$spsv #:endif #:endfor #:endfor end interface spsv interface sptrd !! SPTRD reduces a real symmetric matrix A stored in packed form to !! symmetric tridiagonal form T by an orthogonal similarity !! transformation: Q**T * A * Q = T. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsptrd( uplo, n, ap, d, e, tau, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: ap(*) real(dp), intent(out) :: d(*),e(*),tau(*) end subroutine dsptrd #else module procedure stdlib${ii}$_dsptrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssptrd( uplo, n, ap, d, e, tau, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: ap(*) real(sp), intent(out) :: d(*),e(*),tau(*) end subroutine ssptrd #else module procedure stdlib${ii}$_ssptrd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sptrd #:endif #:endfor #:endfor end interface sptrd interface sptrf !! SPTRF computes the factorization of a complex symmetric matrix A !! stored in packed format using the Bunch-Kaufman diagonal pivoting !! method: !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csptrf( uplo, n, ap, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: n complex(sp), intent(inout) :: ap(*) end subroutine csptrf #else module procedure stdlib${ii}$_csptrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsptrf( uplo, n, ap, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: ap(*) end subroutine dsptrf #else module procedure stdlib${ii}$_dsptrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssptrf( uplo, n, ap, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: ap(*) end subroutine ssptrf #else module procedure stdlib${ii}$_ssptrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsptrf( uplo, n, ap, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: n complex(dp), intent(inout) :: ap(*) end subroutine zsptrf #else module procedure stdlib${ii}$_zsptrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sptrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sptrf #:endif #:endfor #:endfor end interface sptrf interface sptri !! SPTRI computes the inverse of a complex symmetric indefinite matrix !! A in packed storage using the factorization A = U*D*U**T or !! A = L*D*L**T computed by CSPTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csptri( uplo, n, ap, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) complex(sp), intent(inout) :: ap(*) complex(sp), intent(out) :: work(*) end subroutine csptri #else module procedure stdlib${ii}$_csptri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsptri( uplo, n, ap, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) real(dp), intent(inout) :: ap(*) real(dp), intent(out) :: work(*) end subroutine dsptri #else module procedure stdlib${ii}$_dsptri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssptri( uplo, n, ap, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) real(sp), intent(inout) :: ap(*) real(sp), intent(out) :: work(*) end subroutine ssptri #else module procedure stdlib${ii}$_ssptri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsptri( uplo, n, ap, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,ipiv(*) complex(dp), intent(inout) :: ap(*) complex(dp), intent(out) :: work(*) end subroutine zsptri #else module procedure stdlib${ii}$_zsptri #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sptri #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sptri #:endif #:endfor #:endfor end interface sptri interface sptrs !! SPTRS solves a system of linear equations A*X = B with a complex !! symmetric matrix A stored in packed format using the factorization !! A = U*D*U**T or A = L*D*L**T computed by CSPTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csptrs( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs,ipiv(*) complex(sp), intent(in) :: ap(*) complex(sp), intent(inout) :: b(ldb,*) end subroutine csptrs #else module procedure stdlib${ii}$_csptrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsptrs( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs,ipiv(*) real(dp), intent(in) :: ap(*) real(dp), intent(inout) :: b(ldb,*) end subroutine dsptrs #else module procedure stdlib${ii}$_dsptrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssptrs( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs,ipiv(*) real(sp), intent(in) :: ap(*) real(sp), intent(inout) :: b(ldb,*) end subroutine ssptrs #else module procedure stdlib${ii}$_ssptrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsptrs( uplo, n, nrhs, ap, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs,ipiv(*) complex(dp), intent(in) :: ap(*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zsptrs #else module procedure stdlib${ii}$_zsptrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sptrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sptrs #:endif #:endfor #:endfor end interface sptrs interface stebz !! STEBZ computes the eigenvalues of a symmetric tridiagonal !! matrix T. The user may ask for all eigenvalues, all eigenvalues !! in the half-open interval (VL, VU], or the IL-th through IU-th !! eigenvalues. !! To avoid overflow, the matrix must be scaled so that its !! largest element is no greater than overflow**(1/2) * underflow**(1/4) in absolute value, and for greatest !! accuracy, it should not be much smaller than that. !! See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal !! Matrix", Report CS41, Computer Science Dept., Stanford !! University, July 21, 1966. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dstebz( range, order, n, vl, vu, il, iu, abstol, d, e,m, nsplit, w,& iblock, isplit, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: order,range integer(${ik}$), intent(in) :: il,iu,n integer(${ik}$), intent(out) :: info,m,nsplit,iblock(*),isplit(*),iwork(*) real(dp), intent(in) :: abstol,vl,vu,d(*),e(*) real(dp), intent(out) :: w(*),work(*) end subroutine dstebz #else module procedure stdlib${ii}$_dstebz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sstebz( range, order, n, vl, vu, il, iu, abstol, d, e,m, nsplit, w,& iblock, isplit, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: order,range integer(${ik}$), intent(in) :: il,iu,n integer(${ik}$), intent(out) :: info,m,nsplit,iblock(*),isplit(*),iwork(*) real(sp), intent(in) :: abstol,vl,vu,d(*),e(*) real(sp), intent(out) :: w(*),work(*) end subroutine sstebz #else module procedure stdlib${ii}$_sstebz #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stebz #:endif #:endfor #:endfor end interface stebz interface stedc !! STEDC computes all eigenvalues and, optionally, eigenvectors of a !! symmetric tridiagonal matrix using the divide and conquer method. !! The eigenvectors of a full or band complex Hermitian matrix can also !! be found if CHETRD or CHPTRD or CHBTRD has been used to reduce this !! matrix to tridiagonal form. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or Cray-2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. See SLAED3 for details. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cstedc( compz, n, d, e, z, ldz, work, lwork, rwork,lrwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldz,liwork,lrwork,lwork,n real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: z(ldz,*) end subroutine cstedc #else module procedure stdlib${ii}$_cstedc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dstedc( compz, n, d, e, z, ldz, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldz,liwork,lwork,n real(dp), intent(inout) :: d(*),e(*),z(ldz,*) real(dp), intent(out) :: work(*) end subroutine dstedc #else module procedure stdlib${ii}$_dstedc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sstedc( compz, n, d, e, z, ldz, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldz,liwork,lwork,n real(sp), intent(inout) :: d(*),e(*),z(ldz,*) real(sp), intent(out) :: work(*) end subroutine sstedc #else module procedure stdlib${ii}$_sstedc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zstedc( compz, n, d, e, z, ldz, work, lwork, rwork,lrwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldz,liwork,lrwork,lwork,n real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: z(ldz,*) end subroutine zstedc #else module procedure stdlib${ii}$_zstedc #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stedc #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stedc #:endif #:endfor #:endfor end interface stedc interface stegr !! STEGR computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric tridiagonal matrix T. Any such unreduced matrix has !! a well defined set of pairwise different real eigenvalues, the corresponding !! real eigenvectors are pairwise orthogonal. !! The spectrum may be computed either completely or partially by specifying !! either an interval (VL,VU] or a range of indices IL:IU for the desired !! eigenvalues. !! STEGR is a compatibility wrapper around the improved CSTEMR routine. !! See SSTEMR for further details. !! One important change is that the ABSTOL parameter no longer provides any !! benefit and hence is no longer used. !! Note : STEGR and CSTEMR work only on machines which follow !! IEEE-754 floating-point standard in their handling of infinities and !! NaNs. Normal execution may create these exceptiona values and hence !! may abort due to a floating point exception in environments which !! do not conform to the IEEE-754 standard. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cstegr( jobz, range, n, d, e, vl, vu, il, iu,abstol, m, w, z, ldz, & isuppz, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range integer(${ik}$), intent(in) :: il,iu,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(sp), intent(in) :: abstol,vl,vu real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: w(*),work(*) complex(sp), intent(out) :: z(ldz,*) end subroutine cstegr #else module procedure stdlib${ii}$_cstegr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dstegr( jobz, range, n, d, e, vl, vu, il, iu,abstol, m, w, z, ldz, & isuppz, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range integer(${ik}$), intent(in) :: il,iu,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(dp), intent(in) :: abstol,vl,vu real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dstegr #else module procedure stdlib${ii}$_dstegr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sstegr( jobz, range, n, d, e, vl, vu, il, iu,abstol, m, w, z, ldz, & isuppz, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range integer(${ik}$), intent(in) :: il,iu,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(sp), intent(in) :: abstol,vl,vu real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine sstegr #else module procedure stdlib${ii}$_sstegr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zstegr( jobz, range, n, d, e, vl, vu, il, iu,abstol, m, w, z, ldz, & isuppz, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range integer(${ik}$), intent(in) :: il,iu,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(dp), intent(in) :: abstol,vl,vu real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: w(*),work(*) complex(dp), intent(out) :: z(ldz,*) end subroutine zstegr #else module procedure stdlib${ii}$_zstegr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stegr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stegr #:endif #:endfor #:endfor end interface stegr interface stein !! STEIN computes the eigenvectors of a real symmetric tridiagonal !! matrix T corresponding to specified eigenvalues, using inverse !! iteration. !! The maximum number of iterations allowed for each eigenvector is !! specified by an internal parameter MAXITS (currently set to 5). !! Although the eigenvectors are real, they are stored in a complex !! array, which may be passed to CUNMTR or CUPMTR for back !! transformation to the eigenvectors of a complex Hermitian matrix !! which was reduced to tridiagonal form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cstein( n, d, e, m, w, iblock, isplit, z, ldz, work,iwork, ifail, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ifail(*),iwork(*) integer(${ik}$), intent(in) :: ldz,m,n,iblock(*),isplit(*) real(sp), intent(in) :: d(*),e(*),w(*) real(sp), intent(out) :: work(*) complex(sp), intent(out) :: z(ldz,*) end subroutine cstein #else module procedure stdlib${ii}$_cstein #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dstein( n, d, e, m, w, iblock, isplit, z, ldz, work,iwork, ifail, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ifail(*),iwork(*) integer(${ik}$), intent(in) :: ldz,m,n,iblock(*),isplit(*) real(dp), intent(in) :: d(*),e(*),w(*) real(dp), intent(out) :: work(*),z(ldz,*) end subroutine dstein #else module procedure stdlib${ii}$_dstein #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sstein( n, d, e, m, w, iblock, isplit, z, ldz, work,iwork, ifail, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ifail(*),iwork(*) integer(${ik}$), intent(in) :: ldz,m,n,iblock(*),isplit(*) real(sp), intent(in) :: d(*),e(*),w(*) real(sp), intent(out) :: work(*),z(ldz,*) end subroutine sstein #else module procedure stdlib${ii}$_sstein #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zstein( n, d, e, m, w, iblock, isplit, z, ldz, work,iwork, ifail, & info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info,ifail(*),iwork(*) integer(${ik}$), intent(in) :: ldz,m,n,iblock(*),isplit(*) real(dp), intent(in) :: d(*),e(*),w(*) real(dp), intent(out) :: work(*) complex(dp), intent(out) :: z(ldz,*) end subroutine zstein #else module procedure stdlib${ii}$_zstein #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stein #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stein #:endif #:endfor #:endfor end interface stein interface stemr !! STEMR computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric tridiagonal matrix T. Any such unreduced matrix has !! a well defined set of pairwise different real eigenvalues, the corresponding !! real eigenvectors are pairwise orthogonal. !! The spectrum may be computed either completely or partially by specifying !! either an interval (VL,VU] or a range of indices IL:IU for the desired !! eigenvalues. !! Depending on the number of desired eigenvalues, these are computed either !! by bisection or the dqds algorithm. Numerically orthogonal eigenvectors are !! computed by the use of various suitable L D L^T factorizations near clusters !! of close eigenvalues (referred to as RRRs, Relatively Robust !! Representations). An informal sketch of the algorithm follows. !! For each unreduced block (submatrix) of T, !! (a) Compute T - sigma I = L D L^T, so that L and D !! define all the wanted eigenvalues to high relative accuracy. !! This means that small relative changes in the entries of D and L !! cause only small relative changes in the eigenvalues and !! eigenvectors. The standard (unfactored) representation of the !! tridiagonal matrix T does not have this property in general. !! (b) Compute the eigenvalues to suitable accuracy. !! If the eigenvectors are desired, the algorithm attains full !! accuracy of the computed eigenvalues only right before !! the corresponding vectors have to be computed, see steps c) and d). !! (c) For each cluster of close eigenvalues, select a new !! shift close to the cluster, find a new factorization, and refine !! the shifted eigenvalues to suitable accuracy. !! (d) For each eigenvalue with a large enough relative separation compute !! the corresponding eigenvector by forming a rank revealing twisted !! factorization. Go back to (c) for any clusters that remain. !! For more details, see: !! - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations !! to compute orthogonal eigenvectors of symmetric tridiagonal matrices," !! Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. !! - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and !! Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, !! 2004. Also LAPACK Working Note 154. !! - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", !! Computer Science Division Technical Report No. UCB/CSD-97-971, !! UC Berkeley, May 1997. !! Further Details !! 1.STEMR works only on machines which follow IEEE-754 !! floating-point standard in their handling of infinities and NaNs. !! This permits the use of efficient inner loops avoiding a check for !! zero divisors. !! 2. LAPACK routines can be used to reduce a complex Hermitean matrix to !! real symmetric tridiagonal form. !! (Any complex Hermitean tridiagonal matrix has real values on its diagonal !! and potentially complex numbers on its off-diagonals. By applying a !! similarity transform with an appropriate diagonal matrix !! diag(1,e^{i \phy_1}, ... , e^{i \phy_{n-1}}), the complex Hermitean !! matrix can be transformed into a real symmetric matrix and complex !! arithmetic can be entirely avoided.) !! While the eigenvectors of the real symmetric tridiagonal matrix are real, !! the eigenvectors of original complex Hermitean matrix have complex entries !! in general. !! Since LAPACK drivers overwrite the matrix data with the eigenvectors, !! STEMR accepts complex workspace to facilitate interoperability !! with CUNMTR or CUPMTR. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cstemr( jobz, range, n, d, e, vl, vu, il, iu,m, w, z, ldz, nzc, & isuppz, tryrac, work, lwork,iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range logical(lk), intent(inout) :: tryrac integer(${ik}$), intent(in) :: il,iu,ldz,nzc,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(sp), intent(in) :: vl,vu real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: w(*),work(*) complex(sp), intent(out) :: z(ldz,*) end subroutine cstemr #else module procedure stdlib${ii}$_cstemr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dstemr( jobz, range, n, d, e, vl, vu, il, iu,m, w, z, ldz, nzc, & isuppz, tryrac, work, lwork,iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range logical(lk), intent(inout) :: tryrac integer(${ik}$), intent(in) :: il,iu,ldz,nzc,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(dp), intent(in) :: vl,vu real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dstemr #else module procedure stdlib${ii}$_dstemr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sstemr( jobz, range, n, d, e, vl, vu, il, iu,m, w, z, ldz, nzc, & isuppz, tryrac, work, lwork,iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range logical(lk), intent(inout) :: tryrac integer(${ik}$), intent(in) :: il,iu,ldz,nzc,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(sp), intent(in) :: vl,vu real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine sstemr #else module procedure stdlib${ii}$_sstemr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zstemr( jobz, range, n, d, e, vl, vu, il, iu,m, w, z, ldz, nzc, & isuppz, tryrac, work, lwork,iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range logical(lk), intent(inout) :: tryrac integer(${ik}$), intent(in) :: il,iu,ldz,nzc,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(dp), intent(in) :: vl,vu real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: w(*),work(*) complex(dp), intent(out) :: z(ldz,*) end subroutine zstemr #else module procedure stdlib${ii}$_zstemr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stemr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stemr #:endif #:endfor #:endfor end interface stemr interface steqr !! STEQR computes all eigenvalues and, optionally, eigenvectors of a !! symmetric tridiagonal matrix using the implicit QL or QR method. !! The eigenvectors of a full or band complex Hermitian matrix can also !! be found if CHETRD or CHPTRD or CHBTRD has been used to reduce this !! matrix to tridiagonal form. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csteqr( compz, n, d, e, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: work(*) complex(sp), intent(inout) :: z(ldz,*) end subroutine csteqr #else module procedure stdlib${ii}$_csteqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsteqr( compz, n, d, e, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(dp), intent(inout) :: d(*),e(*),z(ldz,*) real(dp), intent(out) :: work(*) end subroutine dsteqr #else module procedure stdlib${ii}$_dsteqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssteqr( compz, n, d, e, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(sp), intent(inout) :: d(*),e(*),z(ldz,*) real(sp), intent(out) :: work(*) end subroutine ssteqr #else module procedure stdlib${ii}$_ssteqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsteqr( compz, n, d, e, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: work(*) complex(dp), intent(inout) :: z(ldz,*) end subroutine zsteqr #else module procedure stdlib${ii}$_zsteqr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$steqr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$steqr #:endif #:endfor #:endfor end interface steqr interface sterf !! STERF computes all eigenvalues of a symmetric tridiagonal matrix !! using the Pal-Walker-Kahan variant of the QL or QR algorithm. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsterf( n, d, e, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: d(*),e(*) end subroutine dsterf #else module procedure stdlib${ii}$_dsterf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssterf( n, d, e, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: d(*),e(*) end subroutine ssterf #else module procedure stdlib${ii}$_ssterf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sterf #:endif #:endfor #:endfor end interface sterf interface stev !! STEV computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric tridiagonal matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dstev( jobz, n, d, e, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: work(*),z(ldz,*) end subroutine dstev #else module procedure stdlib${ii}$_dstev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sstev( jobz, n, d, e, z, ldz, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz,n real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: work(*),z(ldz,*) end subroutine sstev #else module procedure stdlib${ii}$_sstev #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stev #:endif #:endfor #:endfor end interface stev interface stevd !! STEVD computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric tridiagonal matrix. If eigenvectors are desired, it !! uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dstevd( jobz, n, d, e, z, ldz, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldz,liwork,lwork,n real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: work(*),z(ldz,*) end subroutine dstevd #else module procedure stdlib${ii}$_dstevd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sstevd( jobz, n, d, e, z, ldz, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldz,liwork,lwork,n real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: work(*),z(ldz,*) end subroutine sstevd #else module procedure stdlib${ii}$_sstevd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stevd #:endif #:endfor #:endfor end interface stevd interface stevr !! STEVR computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric tridiagonal matrix T. Eigenvalues and !! eigenvectors can be selected by specifying either a range of values !! or a range of indices for the desired eigenvalues. !! Whenever possible, STEVR calls DSTEMR to compute the !! eigenspectrum using Relatively Robust Representations. DSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. For the i-th !! unreduced block of T, !! (a) Compute T - sigma_i = L_i D_i L_i^T, such that L_i D_i L_i^T !! is a relatively robust representation, !! (b) Compute the eigenvalues, lambda_j, of L_i D_i L_i^T to high !! relative accuracy by the dqds algorithm, !! (c) If there is a cluster of close eigenvalues, "choose" sigma_i !! close to the cluster, and go to step (a), !! (d) Given the approximate eigenvalue lambda_j of L_i D_i L_i^T, !! compute the corresponding eigenvector by forming a !! rank-revealing twisted factorization. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", by Inderjit Dhillon, !! Computer Science Division Technical Report No. UCB//CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : STEVR calls DSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! STEVR calls DSTEBZ and DSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of DSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dstevr( jobz, range, n, d, e, vl, vu, il, iu, abstol,m, w, z, ldz, & isuppz, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range integer(${ik}$), intent(in) :: il,iu,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(dp), intent(in) :: abstol,vl,vu real(dp), intent(inout) :: d(*),e(*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dstevr #else module procedure stdlib${ii}$_dstevr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine sstevr( jobz, range, n, d, e, vl, vu, il, iu, abstol,m, w, z, ldz, & isuppz, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range integer(${ik}$), intent(in) :: il,iu,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(sp), intent(in) :: abstol,vl,vu real(sp), intent(inout) :: d(*),e(*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine sstevr #else module procedure stdlib${ii}$_sstevr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$stevr #:endif #:endfor #:endfor end interface stevr interface sycon !! SYCON estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by CSYTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csycon( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine csycon #else module procedure stdlib${ii}$_csycon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsycon( uplo, n, a, lda, ipiv, anorm, rcond, work,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(dp), intent(in) :: anorm,a(lda,*) real(dp), intent(out) :: rcond,work(*) end subroutine dsycon #else module procedure stdlib${ii}$_dsycon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssycon( uplo, n, a, lda, ipiv, anorm, rcond, work,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(sp), intent(in) :: anorm,a(lda,*) real(sp), intent(out) :: rcond,work(*) end subroutine ssycon #else module procedure stdlib${ii}$_ssycon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsycon( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zsycon #else module procedure stdlib${ii}$_zsycon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sycon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sycon #:endif #:endfor #:endfor end interface sycon interface sycon_rook !! SYCON_ROOK estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by CSYTRF_ROOK. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csycon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine csycon_rook #else module procedure stdlib${ii}$_csycon_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsycon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,iwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(dp), intent(in) :: anorm,a(lda,*) real(dp), intent(out) :: rcond,work(*) end subroutine dsycon_rook #else module procedure stdlib${ii}$_dsycon_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssycon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,iwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(sp), intent(in) :: anorm,a(lda,*) real(sp), intent(out) :: rcond,work(*) end subroutine ssycon_rook #else module procedure stdlib${ii}$_ssycon_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsycon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zsycon_rook #else module procedure stdlib${ii}$_zsycon_rook #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sycon_rook #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sycon_rook #:endif #:endfor #:endfor end interface sycon_rook interface syconv !! SYCONV convert A given by TRF into L and D and vice-versa. !! Get Non-diag elements of D (returned in workspace) and !! apply or reverse permutation done in TRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csyconv( uplo, way, n, a, lda, ipiv, e, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: e(*) end subroutine csyconv #else module procedure stdlib${ii}$_csyconv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsyconv( uplo, way, n, a, lda, ipiv, e, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: e(*) end subroutine dsyconv #else module procedure stdlib${ii}$_dsyconv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssyconv( uplo, way, n, a, lda, ipiv, e, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: e(*) end subroutine ssyconv #else module procedure stdlib${ii}$_ssyconv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsyconv( uplo, way, n, a, lda, ipiv, e, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: e(*) end subroutine zsyconv #else module procedure stdlib${ii}$_zsyconv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syconv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syconv #:endif #:endfor #:endfor end interface syconv interface syconvf !! If parameter WAY = 'C': !! SYCONVF converts the factorization output format used in !! CSYTRF provided on entry in parameter A into the factorization !! output format used in CSYTRF_RK (or CSYTRF_BK) that is stored !! on exit in parameters A and E. It also converts in place details of !! the intechanges stored in IPIV from the format used in CSYTRF into !! the format used in CSYTRF_RK (or CSYTRF_BK). !! If parameter WAY = 'R': !! SYCONVF performs the conversion in reverse direction, i.e. !! converts the factorization output format used in CSYTRF_RK !! (or CSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in CSYTRF that is stored !! on exit in parameter A. It also converts in place details of !! the intechanges stored in IPIV from the format used in CSYTRF_RK !! (or CSYTRF_BK) into the format used in CSYTRF. !! SYCONVF can also convert in Hermitian matrix case, i.e. between !! formats used in CHETRF and CHETRF_RK (or CHETRF_BK). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csyconvf( uplo, way, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n integer(${ik}$), intent(inout) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*),e(*) end subroutine csyconvf #else module procedure stdlib${ii}$_csyconvf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsyconvf( uplo, way, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n integer(${ik}$), intent(inout) :: ipiv(*) real(dp), intent(inout) :: a(lda,*),e(*) end subroutine dsyconvf #else module procedure stdlib${ii}$_dsyconvf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssyconvf( uplo, way, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n integer(${ik}$), intent(inout) :: ipiv(*) real(sp), intent(inout) :: a(lda,*),e(*) end subroutine ssyconvf #else module procedure stdlib${ii}$_ssyconvf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsyconvf( uplo, way, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n integer(${ik}$), intent(inout) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*),e(*) end subroutine zsyconvf #else module procedure stdlib${ii}$_zsyconvf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syconvf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syconvf #:endif #:endfor #:endfor end interface syconvf interface syconvf_rook !! If parameter WAY = 'C': !! SYCONVF_ROOK converts the factorization output format used in !! CSYTRF_ROOK provided on entry in parameter A into the factorization !! output format used in CSYTRF_RK (or CSYTRF_BK) that is stored !! on exit in parameters A and E. IPIV format for CSYTRF_ROOK and !! CSYTRF_RK (or CSYTRF_BK) is the same and is not converted. !! If parameter WAY = 'R': !! SYCONVF_ROOK performs the conversion in reverse direction, i.e. !! converts the factorization output format used in CSYTRF_RK !! (or CSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in CSYTRF_ROOK that is stored !! on exit in parameter A. IPIV format for CSYTRF_ROOK and !! CSYTRF_RK (or CSYTRF_BK) is the same and is not converted. !! SYCONVF_ROOK can also convert in Hermitian matrix case, i.e. between !! formats used in CHETRF_ROOK and CHETRF_RK (or CHETRF_BK). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csyconvf_rook( uplo, way, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(sp), intent(inout) :: a(lda,*),e(*) end subroutine csyconvf_rook #else module procedure stdlib${ii}$_csyconvf_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsyconvf_rook( uplo, way, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(dp), intent(inout) :: a(lda,*),e(*) end subroutine dsyconvf_rook #else module procedure stdlib${ii}$_dsyconvf_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssyconvf_rook( uplo, way, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(sp), intent(inout) :: a(lda,*),e(*) end subroutine ssyconvf_rook #else module procedure stdlib${ii}$_ssyconvf_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsyconvf_rook( uplo, way, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo,way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(dp), intent(inout) :: a(lda,*),e(*) end subroutine zsyconvf_rook #else module procedure stdlib${ii}$_zsyconvf_rook #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syconvf_rook #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syconvf_rook #:endif #:endfor #:endfor end interface syconvf_rook interface syequb !! SYEQUB computes row and column scalings intended to equilibrate a !! symmetric matrix A (with respect to the Euclidean norm) and reduce !! its condition number. The scale factors S are computed by the BIN !! algorithm (see references) so that the scaled matrix B with elements !! B(i,j) = S(i)*A(i,j)*S(j) has a condition number within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csyequb( uplo, n, a, lda, s, scond, amax, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: amax,scond,s(*) character, intent(in) :: uplo complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine csyequb #else module procedure stdlib${ii}$_csyequb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsyequb( uplo, n, a, lda, s, scond, amax, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: amax,scond,s(*),work(*) character, intent(in) :: uplo real(dp), intent(in) :: a(lda,*) end subroutine dsyequb #else module procedure stdlib${ii}$_dsyequb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssyequb( uplo, n, a, lda, s, scond, amax, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: amax,scond,s(*),work(*) character, intent(in) :: uplo real(sp), intent(in) :: a(lda,*) end subroutine ssyequb #else module procedure stdlib${ii}$_ssyequb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsyequb( uplo, n, a, lda, s, scond, amax, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: amax,scond,s(*) character, intent(in) :: uplo complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zsyequb #else module procedure stdlib${ii}$_zsyequb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syequb #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syequb #:endif #:endfor #:endfor end interface syequb interface syev !! SYEV computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dsyev( jobz, uplo, n, a, lda, w, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(*),work(*) end subroutine dsyev #else module procedure stdlib${ii}$_dsyev #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ssyev( jobz, uplo, n, a, lda, w, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(*),work(*) end subroutine ssyev #else module procedure stdlib${ii}$_ssyev #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syev #:endif #:endfor #:endfor end interface syev interface syevd !! SYEVD computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. !! Because of large use of BLAS of level 3, SYEVD needs N**2 more !! workspace than DSYEVX. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dsyevd( jobz, uplo, n, a, lda, w, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,liwork,lwork,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(*),work(*) end subroutine dsyevd #else module procedure stdlib${ii}$_dsyevd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ssyevd( jobz, uplo, n, a, lda, w, work, lwork, iwork,liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,liwork,lwork,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(*),work(*) end subroutine ssyevd #else module procedure stdlib${ii}$_ssyevd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syevd #:endif #:endfor #:endfor end interface syevd interface syevr !! SYEVR computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A. Eigenvalues and eigenvectors can be !! selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. !! SYEVR first reduces the matrix A to tridiagonal form T with a call !! to DSYTRD. Then, whenever possible, SYEVR calls DSTEMR to compute !! the eigenspectrum using Relatively Robust Representations. DSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. !! For each unreduced block (submatrix) of T, !! (a) Compute T - sigma I = L D L^T, so that L and D !! define all the wanted eigenvalues to high relative accuracy. !! This means that small relative changes in the entries of D and L !! cause only small relative changes in the eigenvalues and !! eigenvectors. The standard (unfactored) representation of the !! tridiagonal matrix T does not have this property in general. !! (b) Compute the eigenvalues to suitable accuracy. !! If the eigenvectors are desired, the algorithm attains full !! accuracy of the computed eigenvalues only right before !! the corresponding vectors have to be computed, see steps c) and d). !! (c) For each cluster of close eigenvalues, select a new !! shift close to the cluster, find a new factorization, and refine !! the shifted eigenvalues to suitable accuracy. !! (d) For each eigenvalue with a large enough relative separation compute !! the corresponding eigenvector by forming a rank revealing twisted !! factorization. Go back to (c) for any clusters that remain. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see DSTEMR's documentation and: !! - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations !! to compute orthogonal eigenvectors of symmetric tridiagonal matrices," !! Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. !! - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and !! Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, !! 2004. Also LAPACK Working Note 154. !! - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", !! Computer Science Division Technical Report No. UCB/CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : SYEVR calls DSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! SYEVR calls DSTEBZ and DSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of DSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dsyevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, & ldz, isuppz, work, lwork,iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range,uplo integer(${ik}$), intent(in) :: il,iu,lda,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(dp), intent(in) :: abstol,vl,vu real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine dsyevr #else module procedure stdlib${ii}$_dsyevr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ssyevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, & ldz, isuppz, work, lwork,iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,range,uplo integer(${ik}$), intent(in) :: il,iu,lda,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,isuppz(*),iwork(*) real(sp), intent(in) :: abstol,vl,vu real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(*),work(*),z(ldz,*) end subroutine ssyevr #else module procedure stdlib${ii}$_ssyevr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syevr #:endif #:endfor #:endfor end interface syevr interface sygst !! SYGST reduces a real symmetric-definite generalized eigenproblem !! to standard form. !! If ITYPE = 1, the problem is A*x = lambda*B*x, !! and A is overwritten by inv(U**T)*A*inv(U) or inv(L)*A*inv(L**T) !! If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or !! B*A*x = lambda*x, and A is overwritten by U*A*U**T or L**T*A*L. !! B must have been previously factorized as U**T*U or L*L**T by DPOTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsygst( itype, uplo, n, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,lda,ldb,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: b(ldb,*) end subroutine dsygst #else module procedure stdlib${ii}$_dsygst #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssygst( itype, uplo, n, a, lda, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,lda,ldb,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: b(ldb,*) end subroutine ssygst #else module procedure stdlib${ii}$_ssygst #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sygst #:endif #:endfor #:endfor end interface sygst interface sygv !! SYGV computes all the eigenvalues, and optionally, the eigenvectors !! of a real generalized symmetric-definite eigenproblem, of the form !! A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. !! Here A and B are assumed to be symmetric and B is also !! positive definite. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dsygv( itype, jobz, uplo, n, a, lda, b, ldb, w, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,lda,ldb,lwork,n real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: w(*),work(*) end subroutine dsygv #else module procedure stdlib${ii}$_dsygv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ssygv( itype, jobz, uplo, n, a, lda, b, ldb, w, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype,lda,ldb,lwork,n real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: w(*),work(*) end subroutine ssygv #else module procedure stdlib${ii}$_ssygv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sygv #:endif #:endfor #:endfor end interface sygv interface sygvd !! SYGVD computes all the eigenvalues, and optionally, the eigenvectors !! of a real generalized symmetric-definite eigenproblem, of the form !! A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. Here A and !! B are assumed to be symmetric and B is also positive definite. !! If eigenvectors are desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dsygvd( itype, jobz, uplo, n, a, lda, b, ldb, w, work,lwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: itype,lda,ldb,liwork,lwork,n real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: w(*),work(*) end subroutine dsygvd #else module procedure stdlib${ii}$_dsygvd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ssygvd( itype, jobz, uplo, n, a, lda, b, ldb, w, work,lwork, iwork, & liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobz,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: itype,lda,ldb,liwork,lwork,n real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: w(*),work(*) end subroutine ssygvd #else module procedure stdlib${ii}$_ssygvd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sygvd #:endif #:endfor #:endfor end interface sygvd interface symv !! SYMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csymv( uplo, n, alpha, a, lda, x, incx, beta, y, incy ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx,incy,lda,n complex(sp), intent(in) :: alpha,beta,a(lda,*),x(*) complex(sp), intent(inout) :: y(*) end subroutine csymv #else module procedure stdlib${ii}$_csymv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsymv( uplo, n, alpha, a, lda, x, incx, beta, y, incy ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx,incy,lda,n complex(dp), intent(in) :: alpha,beta,a(lda,*),x(*) complex(dp), intent(inout) :: y(*) end subroutine zsymv #else module procedure stdlib${ii}$_zsymv #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$symv #:endif #:endfor #:endfor end interface symv interface syr !! SYR performs the symmetric rank 1 operation !! A := alpha*x*x**H + A, !! where alpha is a complex scalar, x is an n element vector and A is an !! n by n symmetric matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csyr( uplo, n, alpha, x, incx, a, lda ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx,lda,n complex(sp), intent(in) :: alpha,x(*) complex(sp), intent(inout) :: a(lda,*) end subroutine csyr #else module procedure stdlib${ii}$_csyr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsyr( uplo, n, alpha, x, incx, a, lda ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx,lda,n complex(dp), intent(in) :: alpha,x(*) complex(dp), intent(inout) :: a(lda,*) end subroutine zsyr #else module procedure stdlib${ii}$_zsyr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syr #:endif #:endfor #:endfor end interface syr interface syrfs !! SYRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite, and !! provides error bounds and backward error estimates for the solution. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csyrfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr,& berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs,ipiv(*) real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) end subroutine csyrfs #else module procedure stdlib${ii}$_csyrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsyrfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr,& berr, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs,ipiv(*) real(dp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) real(dp), intent(out) :: berr(*),ferr(*),work(*) real(dp), intent(inout) :: x(ldx,*) end subroutine dsyrfs #else module procedure stdlib${ii}$_dsyrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssyrfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr,& berr, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs,ipiv(*) real(sp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) real(sp), intent(out) :: berr(*),ferr(*),work(*) real(sp), intent(inout) :: x(ldx,*) end subroutine ssyrfs #else module procedure stdlib${ii}$_ssyrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsyrfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr,& berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldaf,ldb,ldx,n,nrhs,ipiv(*) real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: a(lda,*),af(ldaf,*),b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) end subroutine zsyrfs #else module procedure stdlib${ii}$_zsyrfs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syrfs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syrfs #:endif #:endfor #:endfor end interface syrfs interface sysv !! SYSV computes the solution to a complex system of linear equations !! A * X = B, !! where A is an N-by-N symmetric matrix and X and B are N-by-NRHS !! matrices. !! The diagonal pivoting method is used to factor A as !! A = U * D * U**T, if UPLO = 'U', or !! A = L * D * L**T, if UPLO = 'L', !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. The factored form of A is then !! used to solve the system of equations A * X = B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csysv( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine csysv #else module procedure stdlib${ii}$_csysv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsysv( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: work(*) end subroutine dsysv #else module procedure stdlib${ii}$_dsysv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssysv( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: work(*) end subroutine ssysv #else module procedure stdlib${ii}$_ssysv #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsysv( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zsysv #else module procedure stdlib${ii}$_zsysv #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sysv #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sysv #:endif #:endfor #:endfor end interface sysv interface sysv_aa !! CSYSV computes the solution to a complex system of linear equations !! A * X = B, !! where A is an N-by-N symmetric matrix and X and B are N-by-NRHS !! matrices. !! Aasen's algorithm is used to factor A as !! A = U**T * T * U, if UPLO = 'U', or !! A = L * T * L**T, if UPLO = 'L', !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is symmetric tridiagonal. The factored !! form of A is then used to solve the system of equations A * X = B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csysv_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine csysv_aa #else module procedure stdlib${ii}$_csysv_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsysv_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: work(*) end subroutine dsysv_aa #else module procedure stdlib${ii}$_dsysv_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssysv_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: work(*) end subroutine ssysv_aa #else module procedure stdlib${ii}$_ssysv_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsysv_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zsysv_aa #else module procedure stdlib${ii}$_zsysv_aa #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sysv_aa #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sysv_aa #:endif #:endfor #:endfor end interface sysv_aa interface sysv_rk !! SYSV_RK computes the solution to a complex system of linear !! equations A * X = B, where A is an N-by-N symmetric matrix !! and X and B are N-by-NRHS matrices. !! The bounded Bunch-Kaufman (rook) diagonal pivoting method is used !! to factor A as !! A = P*U*D*(U**T)*(P**T), if UPLO = 'U', or !! A = P*L*D*(L**T)*(P**T), if UPLO = 'L', !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! CSYTRF_RK is called to compute the factorization of a complex !! symmetric matrix. The factored form of A is then used to solve !! the system of equations A * X = B by calling BLAS3 routine CSYTRS_3. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csysv_rk( uplo, n, nrhs, a, lda, e, ipiv, b, ldb, work,lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: e(*),work(*) end subroutine csysv_rk #else module procedure stdlib${ii}$_csysv_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsysv_rk( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,work, lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: e(*),work(*) end subroutine dsysv_rk #else module procedure stdlib${ii}$_dsysv_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssysv_rk( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,work, lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: e(*),work(*) end subroutine ssysv_rk #else module procedure stdlib${ii}$_ssysv_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsysv_rk( uplo, n, nrhs, a, lda, e, ipiv, b, ldb, work,lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: e(*),work(*) end subroutine zsysv_rk #else module procedure stdlib${ii}$_zsysv_rk #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sysv_rk #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sysv_rk #:endif #:endfor #:endfor end interface sysv_rk interface sysv_rook !! SYSV_ROOK computes the solution to a complex system of linear !! equations !! A * X = B, !! where A is an N-by-N symmetric matrix and X and B are N-by-NRHS !! matrices. !! The diagonal pivoting method is used to factor A as !! A = U * D * U**T, if UPLO = 'U', or !! A = L * D * L**T, if UPLO = 'L', !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! CSYTRF_ROOK is called to compute the factorization of a complex !! symmetric matrix A using the bounded Bunch-Kaufman ("rook") diagonal !! pivoting method. !! The factored form of A is then used to solve the system !! of equations A * X = B by calling CSYTRS_ROOK. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csysv_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine csysv_rook #else module procedure stdlib${ii}$_csysv_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsysv_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: work(*) end subroutine dsysv_rook #else module procedure stdlib${ii}$_dsysv_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssysv_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: work(*) end subroutine ssysv_rook #else module procedure stdlib${ii}$_ssysv_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsysv_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,ldb,lwork,n,nrhs complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zsysv_rook #else module procedure stdlib${ii}$_zsysv_rook #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sysv_rook #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sysv_rook #:endif #:endfor #:endfor end interface sysv_rook interface syswapr !! SYSWAPR applies an elementary permutation on the rows and the columns of !! a symmetric matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csyswapr( uplo, n, a, lda, i1, i2) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1,i2,lda,n complex(sp), intent(inout) :: a(lda,n) end subroutine csyswapr #else module procedure stdlib${ii}$_csyswapr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsyswapr( uplo, n, a, lda, i1, i2) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1,i2,lda,n real(dp), intent(inout) :: a(lda,n) end subroutine dsyswapr #else module procedure stdlib${ii}$_dsyswapr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssyswapr( uplo, n, a, lda, i1, i2) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1,i2,lda,n real(sp), intent(inout) :: a(lda,n) end subroutine ssyswapr #else module procedure stdlib${ii}$_ssyswapr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsyswapr( uplo, n, a, lda, i1, i2) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1,i2,lda,n complex(dp), intent(inout) :: a(lda,n) end subroutine zsyswapr #else module procedure stdlib${ii}$_zsyswapr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syswapr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$syswapr #:endif #:endfor #:endfor end interface syswapr interface sytf2_rk !! SYTF2_RK computes the factorization of a complex symmetric matrix A !! using the bounded Bunch-Kaufman (rook) diagonal pivoting method: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. !! For more information see Further Details section. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytf2_rk( uplo, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: e(*) end subroutine csytf2_rk #else module procedure stdlib${ii}$_csytf2_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytf2_rk( uplo, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: e(*) end subroutine dsytf2_rk #else module procedure stdlib${ii}$_dsytf2_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytf2_rk( uplo, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: e(*) end subroutine ssytf2_rk #else module procedure stdlib${ii}$_ssytf2_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytf2_rk( uplo, n, a, lda, e, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: e(*) end subroutine zsytf2_rk #else module procedure stdlib${ii}$_zsytf2_rk #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytf2_rk #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytf2_rk #:endif #:endfor #:endfor end interface sytf2_rk interface sytf2_rook !! SYTF2_ROOK computes the factorization of a complex symmetric matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method: !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, U**T is the transpose of U, and D is symmetric and !! block diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytf2_rook( uplo, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n complex(sp), intent(inout) :: a(lda,*) end subroutine csytf2_rook #else module procedure stdlib${ii}$_csytf2_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytf2_rook( uplo, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n real(dp), intent(inout) :: a(lda,*) end subroutine dsytf2_rook #else module procedure stdlib${ii}$_dsytf2_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytf2_rook( uplo, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n real(sp), intent(inout) :: a(lda,*) end subroutine ssytf2_rook #else module procedure stdlib${ii}$_ssytf2_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytf2_rook( uplo, n, a, lda, ipiv, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,n complex(dp), intent(inout) :: a(lda,*) end subroutine zsytf2_rook #else module procedure stdlib${ii}$_zsytf2_rook #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytf2_rook #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytf2_rook #:endif #:endfor #:endfor end interface sytf2_rook interface sytrd !! SYTRD reduces a real symmetric matrix A to real symmetric !! tridiagonal form T by an orthogonal similarity transformation: !! Q**T * A * Q = T. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytrd( uplo, n, a, lda, d, e, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*),e(*),tau(*),work(*) end subroutine dsytrd #else module procedure stdlib${ii}$_dsytrd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytrd( uplo, n, a, lda, d, e, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*),e(*),tau(*),work(*) end subroutine ssytrd #else module procedure stdlib${ii}$_ssytrd #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrd #:endif #:endfor #:endfor end interface sytrd interface sytrd_sb2st !! SYTRD_SB2ST reduces a real symmetric band matrix A to real symmetric !! tridiagonal form T by a orthogonal similarity transformation: !! Q**T * A * Q = T. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dsytrd_sb2st( stage1, vect, uplo, n, kd, ab, ldab,d, e, hous, & lhous, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: stage1,uplo,vect integer(${ik}$), intent(in) :: n,kd,ldab,lhous,lwork integer(${ik}$), intent(out) :: info real(dp), intent(out) :: d(*),e(*),hous(*),work(*) real(dp), intent(inout) :: ab(ldab,*) end subroutine dsytrd_sb2st #else module procedure stdlib${ii}$_dsytrd_sb2st #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ssytrd_sb2st( stage1, vect, uplo, n, kd, ab, ldab,d, e, hous, & lhous, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: stage1,uplo,vect integer(${ik}$), intent(in) :: n,kd,ldab,lhous,lwork integer(${ik}$), intent(out) :: info real(sp), intent(out) :: d(*),e(*),hous(*),work(*) real(sp), intent(inout) :: ab(ldab,*) end subroutine ssytrd_sb2st #else module procedure stdlib${ii}$_ssytrd_sb2st #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrd_sb2st #:endif #:endfor #:endfor end interface sytrd_sb2st interface sytrd_sy2sb !! SYTRD_SY2SB reduces a real symmetric matrix A to real symmetric !! band-diagonal form AB by a orthogonal similarity transformation: !! Q**T * A * Q = AB. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dsytrd_sy2sb( uplo, n, kd, a, lda, ab, ldab, tau,work, lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldab,lwork,n,kd real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: ab(ldab,*),tau(*),work(*) end subroutine dsytrd_sy2sb #else module procedure stdlib${ii}$_dsytrd_sy2sb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ssytrd_sy2sb( uplo, n, kd, a, lda, ab, ldab, tau,work, lwork, info & ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldab,lwork,n,kd real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: ab(ldab,*),tau(*),work(*) end subroutine ssytrd_sy2sb #else module procedure stdlib${ii}$_ssytrd_sy2sb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrd_sy2sb #:endif #:endfor #:endfor end interface sytrd_sy2sb interface sytrf !! SYTRF computes the factorization of a complex symmetric matrix A !! using the Bunch-Kaufman diagonal pivoting method. The form of the !! factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytrf( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine csytrf #else module procedure stdlib${ii}$_csytrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytrf( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*) end subroutine dsytrf #else module procedure stdlib${ii}$_dsytrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytrf( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*) end subroutine ssytrf #else module procedure stdlib${ii}$_ssytrf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytrf( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zsytrf #else module procedure stdlib${ii}$_zsytrf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrf #:endif #:endfor #:endfor end interface sytrf interface sytrf_aa !! SYTRF_AA computes the factorization of a complex symmetric matrix A !! using the Aasen's algorithm. The form of the factorization is !! A = U**T*T*U or A = L*T*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is a complex symmetric tridiagonal matrix. !! This is the blocked version of the algorithm, calling Level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,lda,lwork integer(${ik}$), intent(out) :: info,ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine csytrf_aa #else module procedure stdlib${ii}$_csytrf_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,lda,lwork integer(${ik}$), intent(out) :: info,ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*) end subroutine dsytrf_aa #else module procedure stdlib${ii}$_dsytrf_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,lda,lwork integer(${ik}$), intent(out) :: info,ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*) end subroutine ssytrf_aa #else module procedure stdlib${ii}$_ssytrf_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,lda,lwork integer(${ik}$), intent(out) :: info,ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zsytrf_aa #else module procedure stdlib${ii}$_zsytrf_aa #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrf_aa #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrf_aa #:endif #:endfor #:endfor end interface sytrf_aa interface sytrf_rk !! SYTRF_RK computes the factorization of a complex symmetric matrix A !! using the bounded Bunch-Kaufman (rook) diagonal pivoting method: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. !! For more information see Further Details section. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: e(*),work(*) end subroutine csytrf_rk #else module procedure stdlib${ii}$_csytrf_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: e(*),work(*) end subroutine dsytrf_rk #else module procedure stdlib${ii}$_dsytrf_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: e(*),work(*) end subroutine ssytrf_rk #else module procedure stdlib${ii}$_ssytrf_rk #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: e(*),work(*) end subroutine zsytrf_rk #else module procedure stdlib${ii}$_zsytrf_rk #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrf_rk #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrf_rk #:endif #:endfor #:endfor end interface sytrf_rk interface sytrf_rook !! SYTRF_ROOK computes the factorization of a complex symmetric matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method. !! The form of the factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine csytrf_rook #else module procedure stdlib${ii}$_csytrf_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*) end subroutine dsytrf_rook #else module procedure stdlib${ii}$_dsytrf_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*) end subroutine ssytrf_rook #else module procedure stdlib${ii}$_ssytrf_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info,ipiv(*) integer(${ik}$), intent(in) :: lda,lwork,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zsytrf_rook #else module procedure stdlib${ii}$_zsytrf_rook #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrf_rook #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrf_rook #:endif #:endfor #:endfor end interface sytrf_rook interface sytri !! SYTRI computes the inverse of a complex symmetric indefinite matrix !! A using the factorization A = U*D*U**T or A = L*D*L**T computed by !! CSYTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytri( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine csytri #else module procedure stdlib${ii}$_csytri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytri( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*) end subroutine dsytri #else module procedure stdlib${ii}$_dsytri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytri( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*) end subroutine ssytri #else module procedure stdlib${ii}$_ssytri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytri( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zsytri #else module procedure stdlib${ii}$_zsytri #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytri #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytri #:endif #:endfor #:endfor end interface sytri interface sytri_rook !! SYTRI_ROOK computes the inverse of a complex symmetric !! matrix A using the factorization A = U*D*U**T or A = L*D*L**T !! computed by CSYTRF_ROOK. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytri_rook( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine csytri_rook #else module procedure stdlib${ii}$_csytri_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytri_rook( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*) end subroutine dsytri_rook #else module procedure stdlib${ii}$_dsytri_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytri_rook( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*) end subroutine ssytri_rook #else module procedure stdlib${ii}$_ssytri_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytri_rook( uplo, n, a, lda, ipiv, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n,ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine zsytri_rook #else module procedure stdlib${ii}$_zsytri_rook #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytri_rook #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytri_rook #:endif #:endfor #:endfor end interface sytri_rook interface sytrs !! SYTRS solves a system of linear equations A*X = B with a complex !! symmetric matrix A using the factorization A = U*D*U**T or !! A = L*D*L**T computed by CSYTRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytrs( uplo, n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: b(ldb,*) end subroutine csytrs #else module procedure stdlib${ii}$_csytrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytrs( uplo, n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: b(ldb,*) end subroutine dsytrs #else module procedure stdlib${ii}$_dsytrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytrs( uplo, n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: b(ldb,*) end subroutine ssytrs #else module procedure stdlib${ii}$_ssytrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytrs( uplo, n, nrhs, a, lda, ipiv, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zsytrs #else module procedure stdlib${ii}$_zsytrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrs #:endif #:endfor #:endfor end interface sytrs interface sytrs2 !! SYTRS2 solves a system of linear equations A*X = B with a complex !! symmetric matrix A using the factorization A = U*D*U**T or !! A = L*D*L**T computed by CSYTRF and converted by CSYCONV. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine csytrs2 #else module procedure stdlib${ii}$_csytrs2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: work(*) end subroutine dsytrs2 #else module procedure stdlib${ii}$_dsytrs2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: work(*) end subroutine ssytrs2 #else module procedure stdlib${ii}$_ssytrs2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zsytrs2 #else module procedure stdlib${ii}$_zsytrs2 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrs2 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrs2 #:endif #:endfor #:endfor end interface sytrs2 interface sytrs_3 !! SYTRS_3 solves a system of linear equations A * X = B with a complex !! symmetric matrix A using the factorization computed !! by CSYTRF_RK or CSYTRF_BK: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This algorithm is using Level 3 BLAS. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(sp), intent(in) :: a(lda,*),e(*) complex(sp), intent(inout) :: b(ldb,*) end subroutine csytrs_3 #else module procedure stdlib${ii}$_csytrs_3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) real(dp), intent(in) :: a(lda,*),e(*) real(dp), intent(inout) :: b(ldb,*) end subroutine dsytrs_3 #else module procedure stdlib${ii}$_dsytrs_3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) real(sp), intent(in) :: a(lda,*),e(*) real(sp), intent(inout) :: b(ldb,*) end subroutine ssytrs_3 #else module procedure stdlib${ii}$_ssytrs_3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(dp), intent(in) :: a(lda,*),e(*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zsytrs_3 #else module procedure stdlib${ii}$_zsytrs_3 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrs_3 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrs_3 #:endif #:endfor #:endfor end interface sytrs_3 interface sytrs_aa !! SYTRS_AA solves a system of linear equations A*X = B with a complex !! symmetric matrix A using the factorization A = U**T*T*U or !! A = L*T*L**T computed by CSYTRF_AA. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,nrhs,lda,ldb,lwork,ipiv(*) integer(${ik}$), intent(out) :: info complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine csytrs_aa #else module procedure stdlib${ii}$_csytrs_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,nrhs,lda,ldb,lwork,ipiv(*) integer(${ik}$), intent(out) :: info real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: b(ldb,*) real(dp), intent(out) :: work(*) end subroutine dsytrs_aa #else module procedure stdlib${ii}$_dsytrs_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,nrhs,lda,ldb,lwork,ipiv(*) integer(${ik}$), intent(out) :: info real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: b(ldb,*) real(sp), intent(out) :: work(*) end subroutine ssytrs_aa #else module procedure stdlib${ii}$_ssytrs_aa #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(in) :: n,nrhs,lda,ldb,lwork,ipiv(*) integer(${ik}$), intent(out) :: info complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine zsytrs_aa #else module procedure stdlib${ii}$_zsytrs_aa #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrs_aa #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrs_aa #:endif #:endfor #:endfor end interface sytrs_aa interface sytrs_rook !! SYTRS_ROOK solves a system of linear equations A*X = B with !! a complex symmetric matrix A using the factorization A = U*D*U**T or !! A = L*D*L**T computed by CSYTRF_ROOK. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine csytrs_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: b(ldb,*) end subroutine csytrs_rook #else module procedure stdlib${ii}$_csytrs_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dsytrs_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: b(ldb,*) end subroutine dsytrs_rook #else module procedure stdlib${ii}$_dsytrs_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ssytrs_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: b(ldb,*) end subroutine ssytrs_rook #else module procedure stdlib${ii}$_ssytrs_rook #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zsytrs_rook( uplo, n, nrhs, a, lda, ipiv, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs,ipiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: b(ldb,*) end subroutine zsytrs_rook #else module procedure stdlib${ii}$_zsytrs_rook #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrs_rook #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$sytrs_rook #:endif #:endfor #:endfor end interface sytrs_rook interface tbcon !! TBCON estimates the reciprocal of the condition number of a !! triangular band matrix A, in either the 1-norm or the infinity-norm. !! The norm of A is computed and an estimate is obtained for !! norm(inv(A)), then the reciprocal of the condition number is !! computed as !! RCOND = 1 / ( norm(A) * norm(inv(A)) ). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ctbcon( norm, uplo, diag, n, kd, ab, ldab, rcond, work,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(out) :: rcond,rwork(*) complex(sp), intent(in) :: ab(ldab,*) complex(sp), intent(out) :: work(*) end subroutine ctbcon #else module procedure stdlib${ii}$_ctbcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dtbcon( norm, uplo, diag, n, kd, ab, ldab, rcond, work,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(out) :: rcond,work(*) real(dp), intent(in) :: ab(ldab,*) end subroutine dtbcon #else module procedure stdlib${ii}$_dtbcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine stbcon( norm, uplo, diag, n, kd, ab, ldab, rcond, work,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,n real(sp), intent(out) :: rcond,work(*) real(sp), intent(in) :: ab(ldab,*) end subroutine stbcon #else module procedure stdlib${ii}$_stbcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ztbcon( norm, uplo, diag, n, kd, ab, ldab, rcond, work,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,n real(dp), intent(out) :: rcond,rwork(*) complex(dp), intent(in) :: ab(ldab,*) complex(dp), intent(out) :: work(*) end subroutine ztbcon #else module procedure stdlib${ii}$_ztbcon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tbcon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tbcon #:endif #:endfor #:endfor end interface tbcon interface tbrfs !! TBRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular band !! coefficient matrix. !! The solution matrix X must be computed by CTBTRS or some other !! means before entering this routine. TBRFS does not do iterative !! refinement because doing so cannot improve the backward error. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctbrfs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, x, ldx, & ferr, berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,ldx,n,nrhs real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: ab(ldab,*),b(ldb,*),x(ldx,*) complex(sp), intent(out) :: work(*) end subroutine ctbrfs #else module procedure stdlib${ii}$_ctbrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtbrfs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, x, ldx, & ferr, berr, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,ldb,ldx,n,nrhs real(dp), intent(in) :: ab(ldab,*),b(ldb,*),x(ldx,*) real(dp), intent(out) :: berr(*),ferr(*),work(*) end subroutine dtbrfs #else module procedure stdlib${ii}$_dtbrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stbrfs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, x, ldx, & ferr, berr, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: kd,ldab,ldb,ldx,n,nrhs real(sp), intent(in) :: ab(ldab,*),b(ldb,*),x(ldx,*) real(sp), intent(out) :: berr(*),ferr(*),work(*) end subroutine stbrfs #else module procedure stdlib${ii}$_stbrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztbrfs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, x, ldx, & ferr, berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,ldx,n,nrhs real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: ab(ldab,*),b(ldb,*),x(ldx,*) complex(dp), intent(out) :: work(*) end subroutine ztbrfs #else module procedure stdlib${ii}$_ztbrfs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tbrfs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tbrfs #:endif #:endfor #:endfor end interface tbrfs interface tbtrs !! TBTRS solves a triangular system of the form !! A * X = B, A**T * X = B, or A**H * X = B, !! where A is a triangular band matrix of order N, and B is an !! N-by-NRHS matrix. A check is made to verify that A is nonsingular. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctbtrs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs complex(sp), intent(in) :: ab(ldab,*) complex(sp), intent(inout) :: b(ldb,*) end subroutine ctbtrs #else module procedure stdlib${ii}$_ctbtrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtbtrs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs real(dp), intent(in) :: ab(ldab,*) real(dp), intent(inout) :: b(ldb,*) end subroutine dtbtrs #else module procedure stdlib${ii}$_dtbtrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stbtrs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs real(sp), intent(in) :: ab(ldab,*) real(sp), intent(inout) :: b(ldb,*) end subroutine stbtrs #else module procedure stdlib${ii}$_stbtrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztbtrs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd,ldab,ldb,n,nrhs complex(dp), intent(in) :: ab(ldab,*) complex(dp), intent(inout) :: b(ldb,*) end subroutine ztbtrs #else module procedure stdlib${ii}$_ztbtrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tbtrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tbtrs #:endif #:endfor #:endfor end interface tbtrs interface tfsm !! Level 3 BLAS like routine for A in RFP Format. !! TFSM solves the matrix equation !! op( A )*X = alpha*B or X*op( A ) = alpha*B !! where alpha is a scalar, X and B are m by n matrices, A is a unit, or !! non-unit, upper or lower triangular matrix and op( A ) is one of !! op( A ) = A or op( A ) = A**H. !! A is in Rectangular Full Packed (RFP) Format. !! The matrix X is overwritten on B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctfsm( transr, side, uplo, trans, diag, m, n, alpha, a,b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,diag,side,trans,uplo integer(${ik}$), intent(in) :: ldb,m,n complex(sp), intent(in) :: alpha,a(0:*) complex(sp), intent(inout) :: b(0:ldb-1,0:*) end subroutine ctfsm #else module procedure stdlib${ii}$_ctfsm #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtfsm( transr, side, uplo, trans, diag, m, n, alpha, a,b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,diag,side,trans,uplo integer(${ik}$), intent(in) :: ldb,m,n real(dp), intent(in) :: alpha,a(0:*) real(dp), intent(inout) :: b(0:ldb-1,0:*) end subroutine dtfsm #else module procedure stdlib${ii}$_dtfsm #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stfsm( transr, side, uplo, trans, diag, m, n, alpha, a,b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,diag,side,trans,uplo integer(${ik}$), intent(in) :: ldb,m,n real(sp), intent(in) :: alpha,a(0:*) real(sp), intent(inout) :: b(0:ldb-1,0:*) end subroutine stfsm #else module procedure stdlib${ii}$_stfsm #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztfsm( transr, side, uplo, trans, diag, m, n, alpha, a,b, ldb ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,diag,side,trans,uplo integer(${ik}$), intent(in) :: ldb,m,n complex(dp), intent(in) :: alpha,a(0:*) complex(dp), intent(inout) :: b(0:ldb-1,0:*) end subroutine ztfsm #else module procedure stdlib${ii}$_ztfsm #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tfsm #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tfsm #:endif #:endfor #:endfor end interface tfsm interface tftri !! TFTRI computes the inverse of a triangular matrix A stored in RFP !! format. !! This is a Level 3 BLAS version of the algorithm. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctftri( transr, uplo, diag, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo,diag integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(sp), intent(inout) :: a(0:*) end subroutine ctftri #else module procedure stdlib${ii}$_ctftri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtftri( transr, uplo, diag, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo,diag integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: a(0:*) end subroutine dtftri #else module procedure stdlib${ii}$_dtftri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stftri( transr, uplo, diag, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo,diag integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: a(0:*) end subroutine stftri #else module procedure stdlib${ii}$_stftri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztftri( transr, uplo, diag, n, a, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo,diag integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(dp), intent(inout) :: a(0:*) end subroutine ztftri #else module procedure stdlib${ii}$_ztftri #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tftri #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tftri #:endif #:endfor #:endfor end interface tftri interface tfttp !! TFTTP copies a triangular matrix A from rectangular full packed !! format (TF) to standard packed format (TP). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctfttp( transr, uplo, n, arf, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(sp), intent(out) :: ap(0:*) complex(sp), intent(in) :: arf(0:*) end subroutine ctfttp #else module procedure stdlib${ii}$_ctfttp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtfttp( transr, uplo, n, arf, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: ap(0:*) real(dp), intent(in) :: arf(0:*) end subroutine dtfttp #else module procedure stdlib${ii}$_dtfttp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stfttp( transr, uplo, n, arf, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(out) :: ap(0:*) real(sp), intent(in) :: arf(0:*) end subroutine stfttp #else module procedure stdlib${ii}$_stfttp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztfttp( transr, uplo, n, arf, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(dp), intent(out) :: ap(0:*) complex(dp), intent(in) :: arf(0:*) end subroutine ztfttp #else module procedure stdlib${ii}$_ztfttp #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tfttp #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tfttp #:endif #:endfor #:endfor end interface tfttp interface tfttr !! TFTTR copies a triangular matrix A from rectangular full packed !! format (TF) to standard full format (TR). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctfttr( transr, uplo, n, arf, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda complex(sp), intent(out) :: a(0:lda-1,0:*) complex(sp), intent(in) :: arf(0:*) end subroutine ctfttr #else module procedure stdlib${ii}$_ctfttr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtfttr( transr, uplo, n, arf, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda real(dp), intent(out) :: a(0:lda-1,0:*) real(dp), intent(in) :: arf(0:*) end subroutine dtfttr #else module procedure stdlib${ii}$_dtfttr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stfttr( transr, uplo, n, arf, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda real(sp), intent(out) :: a(0:lda-1,0:*) real(sp), intent(in) :: arf(0:*) end subroutine stfttr #else module procedure stdlib${ii}$_stfttr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztfttr( transr, uplo, n, arf, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda complex(dp), intent(out) :: a(0:lda-1,0:*) complex(dp), intent(in) :: arf(0:*) end subroutine ztfttr #else module procedure stdlib${ii}$_ztfttr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tfttr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tfttr #:endif #:endfor #:endfor end interface tfttr interface tgevc !! TGEVC computes some or all of the right and/or left eigenvectors of !! a pair of complex matrices (S,P), where S and P are upper triangular. !! Matrix pairs of this type are produced by the generalized Schur !! factorization of a complex matrix pair (A,B): !! A = Q*S*Z**H, B = Q*P*Z**H !! as computed by CGGHRD + CHGEQZ. !! The right eigenvector x and the left eigenvector y of (S,P) !! corresponding to an eigenvalue w are defined by: !! S*x = w*P*x, (y**H)*S = w*(y**H)*P, !! where y**H denotes the conjugate tranpose of y. !! The eigenvalues are not input to this routine, but are computed !! directly from the diagonal elements of S and P. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of (S,P), or the products Z*X and/or Q*Y, !! where Z and Q are input matrices. !! If Q and Z are the unitary factors from the generalized Schur !! factorization of a matrix pair (A,B), then Z*X and Q*Y !! are the matrices of right and left eigenvectors of (A,B). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctgevc( side, howmny, select, n, s, lds, p, ldp, vl,ldvl, vr, ldvr,& mm, m, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldp,lds,ldvl,ldvr,mm,n logical(lk), intent(in) :: select(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(in) :: p(ldp,*),s(lds,*) complex(sp), intent(inout) :: vl(ldvl,*),vr(ldvr,*) complex(sp), intent(out) :: work(*) end subroutine ctgevc #else module procedure stdlib${ii}$_ctgevc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtgevc( side, howmny, select, n, s, lds, p, ldp, vl,ldvl, vr, ldvr,& mm, m, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldp,lds,ldvl,ldvr,mm,n logical(lk), intent(in) :: select(*) real(dp), intent(in) :: p(ldp,*),s(lds,*) real(dp), intent(inout) :: vl(ldvl,*),vr(ldvr,*) real(dp), intent(out) :: work(*) end subroutine dtgevc #else module procedure stdlib${ii}$_dtgevc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stgevc( side, howmny, select, n, s, lds, p, ldp, vl,ldvl, vr, ldvr,& mm, m, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldp,lds,ldvl,ldvr,mm,n logical(lk), intent(in) :: select(*) real(sp), intent(in) :: p(ldp,*),s(lds,*) real(sp), intent(inout) :: vl(ldvl,*),vr(ldvr,*) real(sp), intent(out) :: work(*) end subroutine stgevc #else module procedure stdlib${ii}$_stgevc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztgevc( side, howmny, select, n, s, lds, p, ldp, vl,ldvl, vr, ldvr,& mm, m, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldp,lds,ldvl,ldvr,mm,n logical(lk), intent(in) :: select(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(in) :: p(ldp,*),s(lds,*) complex(dp), intent(inout) :: vl(ldvl,*),vr(ldvr,*) complex(dp), intent(out) :: work(*) end subroutine ztgevc #else module procedure stdlib${ii}$_ztgevc #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgevc #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgevc #:endif #:endfor #:endfor end interface tgevc interface tgexc !! TGEXC reorders the generalized Schur decomposition of a complex !! matrix pair (A,B), using an unitary equivalence transformation !! (A, B) := Q * (A, B) * Z**H, so that the diagonal block of (A, B) with !! row index IFST is moved to row ILST. !! (A, B) must be in generalized Schur canonical form, that is, A and !! B are both upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**H = Q(out) * A(out) * Z(out)**H !! Q(in) * B(in) * Z(in)**H = Q(out) * B(out) * Z(out)**H #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctgexc( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, ifst, ilst,& info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantq,wantz integer(${ik}$), intent(in) :: ifst,lda,ldb,ldq,ldz,n integer(${ik}$), intent(inout) :: ilst integer(${ik}$), intent(out) :: info complex(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) end subroutine ctgexc #else module procedure stdlib${ii}$_ctgexc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtgexc( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, ifst, ilst,& work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantq,wantz integer(${ik}$), intent(inout) :: ifst,ilst integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldq,ldz,lwork,n real(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) real(dp), intent(out) :: work(*) end subroutine dtgexc #else module procedure stdlib${ii}$_dtgexc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stgexc( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, ifst, ilst,& work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantq,wantz integer(${ik}$), intent(inout) :: ifst,ilst integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldq,ldz,lwork,n real(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) real(sp), intent(out) :: work(*) end subroutine stgexc #else module procedure stdlib${ii}$_stgexc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztgexc( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, ifst, ilst,& info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantq,wantz integer(${ik}$), intent(in) :: ifst,lda,ldb,ldq,ldz,n integer(${ik}$), intent(inout) :: ilst integer(${ik}$), intent(out) :: info complex(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) end subroutine ztgexc #else module procedure stdlib${ii}$_ztgexc #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgexc #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgexc #:endif #:endfor #:endfor end interface tgexc interface tgsen !! TGSEN reorders the generalized Schur decomposition of a complex !! matrix pair (A, B) (in terms of an unitary equivalence trans- !! formation Q**H * (A, B) * Z), so that a selected cluster of eigenvalues !! appears in the leading diagonal blocks of the pair (A,B). The leading !! columns of Q and Z form unitary bases of the corresponding left and !! right eigenspaces (deflating subspaces). (A, B) must be in !! generalized Schur canonical form, that is, A and B are both upper !! triangular. !! TGSEN also computes the generalized eigenvalues !! w(j)= ALPHA(j) / BETA(j) !! of the reordered matrix pair (A, B). !! Optionally, the routine computes estimates of reciprocal condition !! numbers for eigenvalues and eigenspaces. These are Difu[(A11,B11), !! (A22,B22)] and Difl[(A11,B11), (A22,B22)], i.e. the separation(s) !! between the matrix pairs (A11, B11) and (A22,B22) that correspond to !! the selected cluster and the eigenvalues outside the cluster, resp., !! and norms of "projections" onto left and right eigenspaces w.r.t. !! the selected cluster in the (1,1)-block. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctgsen( ijob, wantq, wantz, select, n, a, lda, b, ldb,alpha, beta, & q, ldq, z, ldz, m, pl, pr, dif,work, lwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantq,wantz,select(*) integer(${ik}$), intent(in) :: ijob,lda,ldb,ldq,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,iwork(*) real(sp), intent(out) :: pl,pr,dif(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) complex(sp), intent(out) :: alpha(*),beta(*),work(*) end subroutine ctgsen #else module procedure stdlib${ii}$_ctgsen #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtgsen( ijob, wantq, wantz, select, n, a, lda, b, ldb,alphar, & alphai, beta, q, ldq, z, ldz, m, pl,pr, dif, work, lwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantq,wantz,select(*) integer(${ik}$), intent(in) :: ijob,lda,ldb,ldq,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,iwork(*) real(dp), intent(out) :: pl,pr,alphai(*),alphar(*),beta(*),dif(*),work(*) real(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) end subroutine dtgsen #else module procedure stdlib${ii}$_dtgsen #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stgsen( ijob, wantq, wantz, select, n, a, lda, b, ldb,alphar, & alphai, beta, q, ldq, z, ldz, m, pl,pr, dif, work, lwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantq,wantz,select(*) integer(${ik}$), intent(in) :: ijob,lda,ldb,ldq,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,iwork(*) real(sp), intent(out) :: pl,pr,alphai(*),alphar(*),beta(*),dif(*),work(*) real(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) end subroutine stgsen #else module procedure stdlib${ii}$_stgsen #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztgsen( ijob, wantq, wantz, select, n, a, lda, b, ldb,alpha, beta, & q, ldq, z, ldz, m, pl, pr, dif,work, lwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none logical(lk), intent(in) :: wantq,wantz,select(*) integer(${ik}$), intent(in) :: ijob,lda,ldb,ldq,ldz,liwork,lwork,n integer(${ik}$), intent(out) :: info,m,iwork(*) real(dp), intent(out) :: pl,pr,dif(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),z(ldz,*) complex(dp), intent(out) :: alpha(*),beta(*),work(*) end subroutine ztgsen #else module procedure stdlib${ii}$_ztgsen #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgsen #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgsen #:endif #:endfor #:endfor end interface tgsen interface tgsja !! TGSJA computes the generalized singular value decomposition (GSVD) !! of two complex upper triangular (or trapezoidal) matrices A and B. !! On entry, it is assumed that matrices A and B have the following !! forms, which may be obtained by the preprocessing subroutine CGGSVP !! from a general M-by-N matrix A and P-by-N matrix B: !! N-K-L K L !! A = K ( 0 A12 A13 ) if M-K-L >= 0; !! L ( 0 0 A23 ) !! M-K-L ( 0 0 0 ) !! N-K-L K L !! A = K ( 0 A12 A13 ) if M-K-L < 0; !! M-K ( 0 0 A23 ) !! N-K-L K L !! B = L ( 0 0 B13 ) !! P-L ( 0 0 0 ) !! where the K-by-K matrix A12 and L-by-L matrix B13 are nonsingular !! upper triangular; A23 is L-by-L upper triangular if M-K-L >= 0, !! otherwise A23 is (M-K)-by-L upper trapezoidal. !! On exit, !! U**H *A*Q = D1*( 0 R ), V**H *B*Q = D2*( 0 R ), !! where U, V and Q are unitary matrices. !! R is a nonsingular upper triangular matrix, and D1 !! and D2 are ``diagonal'' matrices, which are of the following !! structures: !! If M-K-L >= 0, !! K L !! D1 = K ( I 0 ) !! L ( 0 C ) !! M-K-L ( 0 0 ) !! K L !! D2 = L ( 0 S ) !! P-L ( 0 0 ) !! N-K-L K L !! ( 0 R ) = K ( 0 R11 R12 ) K !! L ( 0 0 R22 ) L !! where !! C = diag( ALPHA(K+1), ... , ALPHA(K+L) ), !! S = diag( BETA(K+1), ... , BETA(K+L) ), !! C**2 + S**2 = I. !! R is stored in A(1:K+L,N-K-L+1:N) on exit. !! If M-K-L < 0, !! K M-K K+L-M !! D1 = K ( I 0 0 ) !! M-K ( 0 C 0 ) !! K M-K K+L-M !! D2 = M-K ( 0 S 0 ) !! K+L-M ( 0 0 I ) !! P-L ( 0 0 0 ) !! N-K-L K M-K K+L-M !! ( 0 R ) = K ( 0 R11 R12 R13 ) !! M-K ( 0 0 R22 R23 ) !! K+L-M ( 0 0 0 R33 ) !! where !! C = diag( ALPHA(K+1), ... , ALPHA(M) ), !! S = diag( BETA(K+1), ... , BETA(M) ), !! C**2 + S**2 = I. !! R = ( R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) and R33 is stored !! ( 0 R22 R23 ) !! in B(M-K+1:L,N+M-K-L+1:N) on exit. !! The computation of the unitary transformation matrices U, V or Q !! is optional. These matrices may either be formed explicitly, or they !! may be postmultiplied into input matrices U1, V1, or Q1. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctgsja( jobu, jobv, jobq, m, p, n, k, l, a, lda, b,ldb, tola, tolb,& alpha, beta, u, ldu, v, ldv,q, ldq, work, ncycle, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobq,jobu,jobv integer(${ik}$), intent(out) :: info,ncycle integer(${ik}$), intent(in) :: k,l,lda,ldb,ldq,ldu,ldv,m,n,p real(sp), intent(in) :: tola,tolb real(sp), intent(out) :: alpha(*),beta(*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),u(ldu,*),v(ldv,*) complex(sp), intent(out) :: work(*) end subroutine ctgsja #else module procedure stdlib${ii}$_ctgsja #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtgsja( jobu, jobv, jobq, m, p, n, k, l, a, lda, b,ldb, tola, tolb,& alpha, beta, u, ldu, v, ldv,q, ldq, work, ncycle, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobq,jobu,jobv integer(${ik}$), intent(out) :: info,ncycle integer(${ik}$), intent(in) :: k,l,lda,ldb,ldq,ldu,ldv,m,n,p real(dp), intent(in) :: tola,tolb real(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),u(ldu,*),v(ldv,*) real(dp), intent(out) :: alpha(*),beta(*),work(*) end subroutine dtgsja #else module procedure stdlib${ii}$_dtgsja #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stgsja( jobu, jobv, jobq, m, p, n, k, l, a, lda, b,ldb, tola, tolb,& alpha, beta, u, ldu, v, ldv,q, ldq, work, ncycle, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobq,jobu,jobv integer(${ik}$), intent(out) :: info,ncycle integer(${ik}$), intent(in) :: k,l,lda,ldb,ldq,ldu,ldv,m,n,p real(sp), intent(in) :: tola,tolb real(sp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),u(ldu,*),v(ldv,*) real(sp), intent(out) :: alpha(*),beta(*),work(*) end subroutine stgsja #else module procedure stdlib${ii}$_stgsja #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztgsja( jobu, jobv, jobq, m, p, n, k, l, a, lda, b,ldb, tola, tolb,& alpha, beta, u, ldu, v, ldv,q, ldq, work, ncycle, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobq,jobu,jobv integer(${ik}$), intent(out) :: info,ncycle integer(${ik}$), intent(in) :: k,l,lda,ldb,ldq,ldu,ldv,m,n,p real(dp), intent(in) :: tola,tolb real(dp), intent(out) :: alpha(*),beta(*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*),q(ldq,*),u(ldu,*),v(ldv,*) complex(dp), intent(out) :: work(*) end subroutine ztgsja #else module procedure stdlib${ii}$_ztgsja #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgsja #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgsja #:endif #:endfor #:endfor end interface tgsja interface tgsna !! TGSNA estimates reciprocal condition numbers for specified !! eigenvalues and/or eigenvectors of a matrix pair (A, B). !! (A, B) must be in generalized Schur canonical form, that is, A and !! B are both upper triangular. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctgsna( job, howmny, select, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, & s, dif, mm, m, work, lwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,job integer(${ik}$), intent(out) :: info,m,iwork(*) integer(${ik}$), intent(in) :: lda,ldb,ldvl,ldvr,lwork,mm,n logical(lk), intent(in) :: select(*) real(sp), intent(out) :: dif(*),s(*) complex(sp), intent(in) :: a(lda,*),b(ldb,*),vl(ldvl,*),vr(ldvr,*) complex(sp), intent(out) :: work(*) end subroutine ctgsna #else module procedure stdlib${ii}$_ctgsna #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtgsna( job, howmny, select, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, & s, dif, mm, m, work, lwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,job integer(${ik}$), intent(out) :: info,m,iwork(*) integer(${ik}$), intent(in) :: lda,ldb,ldvl,ldvr,lwork,mm,n logical(lk), intent(in) :: select(*) real(dp), intent(in) :: a(lda,*),b(ldb,*),vl(ldvl,*),vr(ldvr,*) real(dp), intent(out) :: dif(*),s(*),work(*) end subroutine dtgsna #else module procedure stdlib${ii}$_dtgsna #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stgsna( job, howmny, select, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, & s, dif, mm, m, work, lwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,job integer(${ik}$), intent(out) :: info,m,iwork(*) integer(${ik}$), intent(in) :: lda,ldb,ldvl,ldvr,lwork,mm,n logical(lk), intent(in) :: select(*) real(sp), intent(in) :: a(lda,*),b(ldb,*),vl(ldvl,*),vr(ldvr,*) real(sp), intent(out) :: dif(*),s(*),work(*) end subroutine stgsna #else module procedure stdlib${ii}$_stgsna #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztgsna( job, howmny, select, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, & s, dif, mm, m, work, lwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,job integer(${ik}$), intent(out) :: info,m,iwork(*) integer(${ik}$), intent(in) :: lda,ldb,ldvl,ldvr,lwork,mm,n logical(lk), intent(in) :: select(*) real(dp), intent(out) :: dif(*),s(*) complex(dp), intent(in) :: a(lda,*),b(ldb,*),vl(ldvl,*),vr(ldvr,*) complex(dp), intent(out) :: work(*) end subroutine ztgsna #else module procedure stdlib${ii}$_ztgsna #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgsna #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgsna #:endif #:endfor #:endfor end interface tgsna interface tgsyl !! TGSYL solves the generalized Sylvester equation: !! A * R - L * B = scale * C (1) !! D * R - L * E = scale * F !! where R and L are unknown m-by-n matrices, (A, D), (B, E) and !! (C, F) are given matrix pairs of size m-by-m, n-by-n and m-by-n, !! respectively, with complex entries. A, B, D and E are upper !! triangular (i.e., (A,D) and (B,E) in generalized Schur form). !! The solution (R, L) overwrites (C, F). 0 <= SCALE <= 1 !! is an output scaling factor chosen to avoid overflow. !! In matrix notation (1) is equivalent to solve Zx = scale*b, where Z !! is defined as !! Z = [ kron(In, A) -kron(B**H, Im) ] (2) !! [ kron(In, D) -kron(E**H, Im) ], !! Here Ix is the identity matrix of size x and X**H is the conjugate !! transpose of X. Kron(X, Y) is the Kronecker product between the !! matrices X and Y. !! If TRANS = 'C', y in the conjugate transposed system Z**H *y = scale*b !! is solved for, which is equivalent to solve for R and L in !! A**H * R + D**H * L = scale * C (3) !! R * B**H + L * E**H = scale * -F !! This case (TRANS = 'C') is used to compute an one-norm-based estimate !! of Dif[(A,D), (B,E)], the separation between the matrix pairs (A,D) !! and (B,E), using CLACON. !! If IJOB >= 1, TGSYL computes a Frobenius norm-based estimate of !! Dif[(A,D),(B,E)]. That is, the reciprocal of a lower bound on the !! reciprocal of the smallest singular value of Z. !! This is a level-3 BLAS algorithm. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctgsyl( trans, ijob, m, n, a, lda, b, ldb, c, ldc, d,ldd, e, lde, & f, ldf, scale, dif, work, lwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob,lda,ldb,ldc,ldd,lde,ldf,lwork,m,n integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(out) :: dif,scale complex(sp), intent(in) :: a(lda,*),b(ldb,*),d(ldd,*),e(lde,*) complex(sp), intent(inout) :: c(ldc,*),f(ldf,*) complex(sp), intent(out) :: work(*) end subroutine ctgsyl #else module procedure stdlib${ii}$_ctgsyl #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtgsyl( trans, ijob, m, n, a, lda, b, ldb, c, ldc, d,ldd, e, lde, & f, ldf, scale, dif, work, lwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob,lda,ldb,ldc,ldd,lde,ldf,lwork,m,n integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(out) :: dif,scale,work(*) real(dp), intent(in) :: a(lda,*),b(ldb,*),d(ldd,*),e(lde,*) real(dp), intent(inout) :: c(ldc,*),f(ldf,*) end subroutine dtgsyl #else module procedure stdlib${ii}$_dtgsyl #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stgsyl( trans, ijob, m, n, a, lda, b, ldb, c, ldc, d,ldd, e, lde, & f, ldf, scale, dif, work, lwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob,lda,ldb,ldc,ldd,lde,ldf,lwork,m,n integer(${ik}$), intent(out) :: info,iwork(*) real(sp), intent(out) :: dif,scale,work(*) real(sp), intent(in) :: a(lda,*),b(ldb,*),d(ldd,*),e(lde,*) real(sp), intent(inout) :: c(ldc,*),f(ldf,*) end subroutine stgsyl #else module procedure stdlib${ii}$_stgsyl #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztgsyl( trans, ijob, m, n, a, lda, b, ldb, c, ldc, d,ldd, e, lde, & f, ldf, scale, dif, work, lwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob,lda,ldb,ldc,ldd,lde,ldf,lwork,m,n integer(${ik}$), intent(out) :: info,iwork(*) real(dp), intent(out) :: dif,scale complex(dp), intent(in) :: a(lda,*),b(ldb,*),d(ldd,*),e(lde,*) complex(dp), intent(inout) :: c(ldc,*),f(ldf,*) complex(dp), intent(out) :: work(*) end subroutine ztgsyl #else module procedure stdlib${ii}$_ztgsyl #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgsyl #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tgsyl #:endif #:endfor #:endfor end interface tgsyl interface tpcon !! TPCON estimates the reciprocal of the condition number of a packed !! triangular matrix A, in either the 1-norm or the infinity-norm. !! The norm of A is computed and an estimate is obtained for !! norm(inv(A)), then the reciprocal of the condition number is !! computed as !! RCOND = 1 / ( norm(A) * norm(inv(A)) ). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ctpcon( norm, uplo, diag, n, ap, rcond, work, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(out) :: rcond,rwork(*) complex(sp), intent(in) :: ap(*) complex(sp), intent(out) :: work(*) end subroutine ctpcon #else module procedure stdlib${ii}$_ctpcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dtpcon( norm, uplo, diag, n, ap, rcond, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: n real(dp), intent(out) :: rcond,work(*) real(dp), intent(in) :: ap(*) end subroutine dtpcon #else module procedure stdlib${ii}$_dtpcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine stpcon( norm, uplo, diag, n, ap, rcond, work, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: n real(sp), intent(out) :: rcond,work(*) real(sp), intent(in) :: ap(*) end subroutine stpcon #else module procedure stdlib${ii}$_stpcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ztpcon( norm, uplo, diag, n, ap, rcond, work, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: rcond,rwork(*) complex(dp), intent(in) :: ap(*) complex(dp), intent(out) :: work(*) end subroutine ztpcon #else module procedure stdlib${ii}$_ztpcon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpcon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpcon #:endif #:endfor #:endfor end interface tpcon interface tplqt !! TPLQT computes a blocked LQ factorization of a complex !! "triangular-pentagonal" matrix C, which is composed of a !! triangular block A and pentagonal block B, using the compact !! WY representation for Q. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l,mb complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: t(ldt,*),work(*) end subroutine ctplqt #else module procedure stdlib${ii}$_ctplqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l,mb real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: t(ldt,*),work(*) end subroutine dtplqt #else module procedure stdlib${ii}$_dtplqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l,mb real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: t(ldt,*),work(*) end subroutine stplqt #else module procedure stdlib${ii}$_stplqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l,mb complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: t(ldt,*),work(*) end subroutine ztplqt #else module procedure stdlib${ii}$_ztplqt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tplqt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tplqt #:endif #:endfor #:endfor end interface tplqt interface tplqt2 !! TPLQT2 computes a LQ a factorization of a complex "triangular-pentagonal" !! matrix C, which is composed of a triangular block A and pentagonal block B, !! using the compact WY representation for Q. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctplqt2( m, n, l, a, lda, b, ldb, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: t(ldt,*) end subroutine ctplqt2 #else module procedure stdlib${ii}$_ctplqt2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtplqt2( m, n, l, a, lda, b, ldb, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: t(ldt,*) end subroutine dtplqt2 #else module procedure stdlib${ii}$_dtplqt2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stplqt2( m, n, l, a, lda, b, ldb, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: t(ldt,*) end subroutine stplqt2 #else module procedure stdlib${ii}$_stplqt2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztplqt2( m, n, l, a, lda, b, ldb, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: t(ldt,*) end subroutine ztplqt2 #else module procedure stdlib${ii}$_ztplqt2 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tplqt2 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tplqt2 #:endif #:endfor #:endfor end interface tplqt2 interface tpmlqt !! TPMLQT applies a complex unitary matrix Q obtained from a !! "triangular-pentagonal" complex block reflector H to a general !! complex matrix C, which consists of two blocks A and B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, & ldb, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,lda,ldb,m,n,l,mb,ldt complex(sp), intent(in) :: v(ldv,*),t(ldt,*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine ctpmlqt #else module procedure stdlib${ii}$_ctpmlqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, & ldb, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,lda,ldb,m,n,l,mb,ldt real(dp), intent(in) :: v(ldv,*),t(ldt,*) real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: work(*) end subroutine dtpmlqt #else module procedure stdlib${ii}$_dtpmlqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, & ldb, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,lda,ldb,m,n,l,mb,ldt real(sp), intent(in) :: v(ldv,*),t(ldt,*) real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: work(*) end subroutine stpmlqt #else module procedure stdlib${ii}$_stpmlqt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, & ldb, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,lda,ldb,m,n,l,mb,ldt complex(dp), intent(in) :: v(ldv,*),t(ldt,*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine ztpmlqt #else module procedure stdlib${ii}$_ztpmlqt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpmlqt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpmlqt #:endif #:endfor #:endfor end interface tpmlqt interface tpmqrt !! TPMQRT applies a complex orthogonal matrix Q obtained from a !! "triangular-pentagonal" complex block reflector H to a general !! complex matrix C, which consists of two blocks A and B. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctpmqrt( side, trans, m, n, k, l, nb, v, ldv, t, ldt,a, lda, b, & ldb, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,lda,ldb,m,n,l,nb,ldt complex(sp), intent(in) :: v(ldv,*),t(ldt,*) complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine ctpmqrt #else module procedure stdlib${ii}$_ctpmqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtpmqrt( side, trans, m, n, k, l, nb, v, ldv, t, ldt,a, lda, b, & ldb, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,lda,ldb,m,n,l,nb,ldt real(dp), intent(in) :: v(ldv,*),t(ldt,*) real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: work(*) end subroutine dtpmqrt #else module procedure stdlib${ii}$_dtpmqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stpmqrt( side, trans, m, n, k, l, nb, v, ldv, t, ldt,a, lda, b, & ldb, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,lda,ldb,m,n,l,nb,ldt real(sp), intent(in) :: v(ldv,*),t(ldt,*) real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: work(*) end subroutine stpmqrt #else module procedure stdlib${ii}$_stpmqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztpmqrt( side, trans, m, n, k, l, nb, v, ldv, t, ldt,a, lda, b, & ldb, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,ldv,lda,ldb,m,n,l,nb,ldt complex(dp), intent(in) :: v(ldv,*),t(ldt,*) complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine ztpmqrt #else module procedure stdlib${ii}$_ztpmqrt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpmqrt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpmqrt #:endif #:endfor #:endfor end interface tpmqrt interface tpqrt !! TPQRT computes a blocked QR factorization of a complex !! "triangular-pentagonal" matrix C, which is composed of a !! triangular block A and pentagonal block B, using the compact !! WY representation for Q. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctpqrt( m, n, l, nb, a, lda, b, ldb, t, ldt, work,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l,nb complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: t(ldt,*),work(*) end subroutine ctpqrt #else module procedure stdlib${ii}$_ctpqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtpqrt( m, n, l, nb, a, lda, b, ldb, t, ldt, work,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l,nb real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: t(ldt,*),work(*) end subroutine dtpqrt #else module procedure stdlib${ii}$_dtpqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stpqrt( m, n, l, nb, a, lda, b, ldb, t, ldt, work,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l,nb real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: t(ldt,*),work(*) end subroutine stpqrt #else module procedure stdlib${ii}$_stpqrt #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztpqrt( m, n, l, nb, a, lda, b, ldb, t, ldt, work,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l,nb complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: t(ldt,*),work(*) end subroutine ztpqrt #else module procedure stdlib${ii}$_ztpqrt #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpqrt #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpqrt #:endif #:endfor #:endfor end interface tpqrt interface tpqrt2 !! TPQRT2 computes a QR factorization of a complex "triangular-pentagonal" !! matrix C, which is composed of a triangular block A and pentagonal block B, !! using the compact WY representation for Q. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctpqrt2( m, n, l, a, lda, b, ldb, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(out) :: t(ldt,*) end subroutine ctpqrt2 #else module procedure stdlib${ii}$_ctpqrt2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtpqrt2( m, n, l, a, lda, b, ldb, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(out) :: t(ldt,*) end subroutine dtpqrt2 #else module procedure stdlib${ii}$_dtpqrt2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stpqrt2( m, n, l, a, lda, b, ldb, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(out) :: t(ldt,*) end subroutine stpqrt2 #else module procedure stdlib${ii}$_stpqrt2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztpqrt2( m, n, l, a, lda, b, ldb, t, ldt, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldt,n,m,l complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(out) :: t(ldt,*) end subroutine ztpqrt2 #else module procedure stdlib${ii}$_ztpqrt2 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpqrt2 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpqrt2 #:endif #:endfor #:endfor end interface tpqrt2 interface tprfb !! TPRFB applies a complex "triangular-pentagonal" block reflector H or its !! conjugate transpose H**H to a complex matrix C, which is composed of two !! blocks A and B, either from the left or right. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctprfb( side, trans, direct, storev, m, n, k, l,v, ldv, t, ldt, a, & lda, b, ldb, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,l,lda,ldb,ldt,ldv,ldwork,m,n complex(sp), intent(inout) :: a(lda,*),b(ldb,*) complex(sp), intent(in) :: t(ldt,*),v(ldv,*) complex(sp), intent(out) :: work(ldwork,*) end subroutine ctprfb #else module procedure stdlib${ii}$_ctprfb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtprfb( side, trans, direct, storev, m, n, k, l,v, ldv, t, ldt, a, & lda, b, ldb, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,l,lda,ldb,ldt,ldv,ldwork,m,n real(dp), intent(inout) :: a(lda,*),b(ldb,*) real(dp), intent(in) :: t(ldt,*),v(ldv,*) real(dp), intent(out) :: work(ldwork,*) end subroutine dtprfb #else module procedure stdlib${ii}$_dtprfb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stprfb( side, trans, direct, storev, m, n, k, l,v, ldv, t, ldt, a, & lda, b, ldb, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,l,lda,ldb,ldt,ldv,ldwork,m,n real(sp), intent(inout) :: a(lda,*),b(ldb,*) real(sp), intent(in) :: t(ldt,*),v(ldv,*) real(sp), intent(out) :: work(ldwork,*) end subroutine stprfb #else module procedure stdlib${ii}$_stprfb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztprfb( side, trans, direct, storev, m, n, k, l,v, ldv, t, ldt, a, & lda, b, ldb, work, ldwork ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: direct,side,storev,trans integer(${ik}$), intent(in) :: k,l,lda,ldb,ldt,ldv,ldwork,m,n complex(dp), intent(inout) :: a(lda,*),b(ldb,*) complex(dp), intent(in) :: t(ldt,*),v(ldv,*) complex(dp), intent(out) :: work(ldwork,*) end subroutine ztprfb #else module procedure stdlib${ii}$_ztprfb #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tprfb #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tprfb #:endif #:endfor #:endfor end interface tprfb interface tprfs !! TPRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular packed !! coefficient matrix. !! The solution matrix X must be computed by CTPTRS or some other !! means before entering this routine. TPRFS does not do iterative !! refinement because doing so cannot improve the backward error. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctprfs( uplo, trans, diag, n, nrhs, ap, b, ldb, x, ldx,ferr, berr, & work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: ap(*),b(ldb,*),x(ldx,*) complex(sp), intent(out) :: work(*) end subroutine ctprfs #else module procedure stdlib${ii}$_ctprfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtprfs( uplo, trans, diag, n, nrhs, ap, b, ldb, x, ldx,ferr, berr, & work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(dp), intent(in) :: ap(*),b(ldb,*),x(ldx,*) real(dp), intent(out) :: berr(*),ferr(*),work(*) end subroutine dtprfs #else module procedure stdlib${ii}$_dtprfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stprfs( uplo, trans, diag, n, nrhs, ap, b, ldb, x, ldx,ferr, berr, & work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(sp), intent(in) :: ap(*),b(ldb,*),x(ldx,*) real(sp), intent(out) :: berr(*),ferr(*),work(*) end subroutine stprfs #else module procedure stdlib${ii}$_stprfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztprfs( uplo, trans, diag, n, nrhs, ap, b, ldb, x, ldx,ferr, berr, & work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,ldx,n,nrhs real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: ap(*),b(ldb,*),x(ldx,*) complex(dp), intent(out) :: work(*) end subroutine ztprfs #else module procedure stdlib${ii}$_ztprfs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tprfs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tprfs #:endif #:endfor #:endfor end interface tprfs interface tptri !! TPTRI computes the inverse of a complex upper or lower triangular !! matrix A stored in packed format. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctptri( uplo, diag, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(sp), intent(inout) :: ap(*) end subroutine ctptri #else module procedure stdlib${ii}$_ctptri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtptri( uplo, diag, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: ap(*) end subroutine dtptri #else module procedure stdlib${ii}$_dtptri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stptri( uplo, diag, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: ap(*) end subroutine stptri #else module procedure stdlib${ii}$_stptri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztptri( uplo, diag, n, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(dp), intent(inout) :: ap(*) end subroutine ztptri #else module procedure stdlib${ii}$_ztptri #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tptri #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tptri #:endif #:endfor #:endfor end interface tptri interface tptrs !! TPTRS solves a triangular system of the form !! A * X = B, A**T * X = B, or A**H * X = B, !! where A is a triangular matrix of order N stored in packed format, !! and B is an N-by-NRHS matrix. A check is made to verify that A is !! nonsingular. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctptrs( uplo, trans, diag, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs complex(sp), intent(in) :: ap(*) complex(sp), intent(inout) :: b(ldb,*) end subroutine ctptrs #else module procedure stdlib${ii}$_ctptrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtptrs( uplo, trans, diag, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(dp), intent(in) :: ap(*) real(dp), intent(inout) :: b(ldb,*) end subroutine dtptrs #else module procedure stdlib${ii}$_dtptrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stptrs( uplo, trans, diag, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs real(sp), intent(in) :: ap(*) real(sp), intent(inout) :: b(ldb,*) end subroutine stptrs #else module procedure stdlib${ii}$_stptrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztptrs( uplo, trans, diag, n, nrhs, ap, b, ldb, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb,n,nrhs complex(dp), intent(in) :: ap(*) complex(dp), intent(inout) :: b(ldb,*) end subroutine ztptrs #else module procedure stdlib${ii}$_ztptrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tptrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tptrs #:endif #:endfor #:endfor end interface tptrs interface tpttf !! TPTTF copies a triangular matrix A from standard packed format (TP) !! to rectangular full packed format (TF). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctpttf( transr, uplo, n, ap, arf, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(sp), intent(in) :: ap(0:*) complex(sp), intent(out) :: arf(0:*) end subroutine ctpttf #else module procedure stdlib${ii}$_ctpttf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtpttf( transr, uplo, n, ap, arf, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(in) :: ap(0:*) real(dp), intent(out) :: arf(0:*) end subroutine dtpttf #else module procedure stdlib${ii}$_dtpttf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stpttf( transr, uplo, n, ap, arf, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(in) :: ap(0:*) real(sp), intent(out) :: arf(0:*) end subroutine stpttf #else module procedure stdlib${ii}$_stpttf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztpttf( transr, uplo, n, ap, arf, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(dp), intent(in) :: ap(0:*) complex(dp), intent(out) :: arf(0:*) end subroutine ztpttf #else module procedure stdlib${ii}$_ztpttf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpttf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpttf #:endif #:endfor #:endfor end interface tpttf interface tpttr !! TPTTR copies a triangular matrix A from standard packed format (TP) !! to standard full format (TR). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctpttr( uplo, n, ap, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda complex(sp), intent(out) :: a(lda,*) complex(sp), intent(in) :: ap(*) end subroutine ctpttr #else module procedure stdlib${ii}$_ctpttr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtpttr( uplo, n, ap, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda real(dp), intent(out) :: a(lda,*) real(dp), intent(in) :: ap(*) end subroutine dtpttr #else module procedure stdlib${ii}$_dtpttr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stpttr( uplo, n, ap, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda real(sp), intent(out) :: a(lda,*) real(sp), intent(in) :: ap(*) end subroutine stpttr #else module procedure stdlib${ii}$_stpttr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztpttr( uplo, n, ap, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda complex(dp), intent(out) :: a(lda,*) complex(dp), intent(in) :: ap(*) end subroutine ztpttr #else module procedure stdlib${ii}$_ztpttr #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpttr #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tpttr #:endif #:endfor #:endfor end interface tpttr interface trcon !! TRCON estimates the reciprocal of the condition number of a !! triangular matrix A, in either the 1-norm or the infinity-norm. !! The norm of A is computed and an estimate is obtained for !! norm(inv(A)), then the reciprocal of the condition number is !! computed as !! RCOND = 1 / ( norm(A) * norm(inv(A)) ). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ctrcon( norm, uplo, diag, n, a, lda, rcond, work,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: rcond,rwork(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) end subroutine ctrcon #else module procedure stdlib${ii}$_ctrcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dtrcon( norm, uplo, diag, n, a, lda, rcond, work,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: rcond,work(*) real(dp), intent(in) :: a(lda,*) end subroutine dtrcon #else module procedure stdlib${ii}$_dtrcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine strcon( norm, uplo, diag, n, a, lda, rcond, work,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,n real(sp), intent(out) :: rcond,work(*) real(sp), intent(in) :: a(lda,*) end subroutine strcon #else module procedure stdlib${ii}$_strcon #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ztrcon( norm, uplo, diag, n, a, lda, rcond, work,rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,norm,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(out) :: rcond,rwork(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) end subroutine ztrcon #else module procedure stdlib${ii}$_ztrcon #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trcon #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trcon #:endif #:endfor #:endfor end interface trcon interface trevc !! TREVC computes some or all of the right and/or left eigenvectors of !! a complex upper triangular matrix T. !! Matrices of this type are produced by the Schur factorization of !! a complex general matrix: A = Q*T*Q**H, as computed by CHSEQR. !! The right eigenvector x and the left eigenvector y of T corresponding !! to an eigenvalue w are defined by: !! T*x = w*x, (y**H)*T = w*(y**H) !! where y**H denotes the conjugate transpose of the vector y. !! The eigenvalues are not input to this routine, but are read directly !! from the diagonal of T. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an !! input matrix. If Q is the unitary factor that reduces a matrix A to !! Schur form T, then Q*X and Q*Y are the matrices of right and left !! eigenvectors of A. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctrevc( side, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, mm, m, & work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,mm,n logical(lk), intent(in) :: select(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: t(ldt,*),vl(ldvl,*),vr(ldvr,*) complex(sp), intent(out) :: work(*) end subroutine ctrevc #else module procedure stdlib${ii}$_ctrevc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtrevc( side, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, mm, m, & work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,mm,n logical(lk), intent(inout) :: select(*) real(dp), intent(in) :: t(ldt,*) real(dp), intent(inout) :: vl(ldvl,*),vr(ldvr,*) real(dp), intent(out) :: work(*) end subroutine dtrevc #else module procedure stdlib${ii}$_dtrevc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine strevc( side, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, mm, m, & work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,mm,n logical(lk), intent(inout) :: select(*) real(sp), intent(in) :: t(ldt,*) real(sp), intent(inout) :: vl(ldvl,*),vr(ldvr,*) real(sp), intent(out) :: work(*) end subroutine strevc #else module procedure stdlib${ii}$_strevc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztrevc( side, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, mm, m, & work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,mm,n logical(lk), intent(in) :: select(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: t(ldt,*),vl(ldvl,*),vr(ldvr,*) complex(dp), intent(out) :: work(*) end subroutine ztrevc #else module procedure stdlib${ii}$_ztrevc #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trevc #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trevc #:endif #:endfor #:endfor end interface trevc interface trevc3 !! TREVC3 computes some or all of the right and/or left eigenvectors of !! a complex upper triangular matrix T. !! Matrices of this type are produced by the Schur factorization of !! a complex general matrix: A = Q*T*Q**H, as computed by CHSEQR. !! The right eigenvector x and the left eigenvector y of T corresponding !! to an eigenvalue w are defined by: !! T*x = w*x, (y**H)*T = w*(y**H) !! where y**H denotes the conjugate transpose of the vector y. !! The eigenvalues are not input to this routine, but are read directly !! from the diagonal of T. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an !! input matrix. If Q is the unitary factor that reduces a matrix A to !! Schur form T, then Q*X and Q*Y are the matrices of right and left !! eigenvectors of A. !! This uses a Level 3 BLAS version of the back transformation. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctrevc3( side, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, mm, m,& work, lwork, rwork, lrwork, info) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,lwork,lrwork,mm,n logical(lk), intent(in) :: select(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: t(ldt,*),vl(ldvl,*),vr(ldvr,*) complex(sp), intent(out) :: work(*) end subroutine ctrevc3 #else module procedure stdlib${ii}$_ctrevc3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtrevc3( side, howmny, select, n, t, ldt, vl, ldvl,vr, ldvr, mm, m,& work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,lwork,mm,n logical(lk), intent(inout) :: select(*) real(dp), intent(in) :: t(ldt,*) real(dp), intent(inout) :: vl(ldvl,*),vr(ldvr,*) real(dp), intent(out) :: work(*) end subroutine dtrevc3 #else module procedure stdlib${ii}$_dtrevc3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine strevc3( side, howmny, select, n, t, ldt, vl, ldvl,vr, ldvr, mm, m,& work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,lwork,mm,n logical(lk), intent(inout) :: select(*) real(sp), intent(in) :: t(ldt,*) real(sp), intent(inout) :: vl(ldvl,*),vr(ldvr,*) real(sp), intent(out) :: work(*) end subroutine strevc3 #else module procedure stdlib${ii}$_strevc3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztrevc3( side, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, mm, m,& work, lwork, rwork, lrwork, info) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,side integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,lwork,lrwork,mm,n logical(lk), intent(in) :: select(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: t(ldt,*),vl(ldvl,*),vr(ldvr,*) complex(dp), intent(out) :: work(*) end subroutine ztrevc3 #else module procedure stdlib${ii}$_ztrevc3 #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trevc3 #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trevc3 #:endif #:endfor #:endfor end interface trevc3 interface trexc !! TREXC reorders the Schur factorization of a complex matrix !! A = Q*T*Q**H, so that the diagonal element of T with row index IFST !! is moved to row ILST. !! The Schur form T is reordered by a unitary similarity transformation !! Z**H*T*Z, and optionally the matrix Q of Schur vectors is updated by !! postmultplying it with Z. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctrexc( compq, n, t, ldt, q, ldq, ifst, ilst, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq integer(${ik}$), intent(in) :: ifst,ilst,ldq,ldt,n integer(${ik}$), intent(out) :: info complex(sp), intent(inout) :: q(ldq,*),t(ldt,*) end subroutine ctrexc #else module procedure stdlib${ii}$_ctrexc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dtrexc( compq, n, t, ldt, q, ldq, ifst, ilst, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq integer(${ik}$), intent(inout) :: ifst,ilst integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq,ldt,n real(dp), intent(inout) :: q(ldq,*),t(ldt,*) real(dp), intent(out) :: work(*) end subroutine dtrexc #else module procedure stdlib${ii}$_dtrexc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine strexc( compq, n, t, ldt, q, ldq, ifst, ilst, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq integer(${ik}$), intent(inout) :: ifst,ilst integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq,ldt,n real(sp), intent(inout) :: q(ldq,*),t(ldt,*) real(sp), intent(out) :: work(*) end subroutine strexc #else module procedure stdlib${ii}$_strexc #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztrexc( compq, n, t, ldt, q, ldq, ifst, ilst, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq integer(${ik}$), intent(in) :: ifst,ilst,ldq,ldt,n integer(${ik}$), intent(out) :: info complex(dp), intent(inout) :: q(ldq,*),t(ldt,*) end subroutine ztrexc #else module procedure stdlib${ii}$_ztrexc #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trexc #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trexc #:endif #:endfor #:endfor end interface trexc interface trrfs !! TRRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular !! coefficient matrix. !! The solution matrix X must be computed by CTRTRS or some other !! means before entering this routine. TRRFS does not do iterative !! refinement because doing so cannot improve the backward error. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctrrfs( uplo, trans, diag, n, nrhs, a, lda, b, ldb, x,ldx, ferr, & berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldx,n,nrhs real(sp), intent(out) :: berr(*),ferr(*),rwork(*) complex(sp), intent(in) :: a(lda,*),b(ldb,*),x(ldx,*) complex(sp), intent(out) :: work(*) end subroutine ctrrfs #else module procedure stdlib${ii}$_ctrrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtrrfs( uplo, trans, diag, n, nrhs, a, lda, b, ldb, x,ldx, ferr, & berr, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldb,ldx,n,nrhs real(dp), intent(in) :: a(lda,*),b(ldb,*),x(ldx,*) real(dp), intent(out) :: berr(*),ferr(*),work(*) end subroutine dtrrfs #else module procedure stdlib${ii}$_dtrrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine strrfs( uplo, trans, diag, n, nrhs, a, lda, b, ldb, x,ldx, ferr, & berr, work, iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: lda,ldb,ldx,n,nrhs real(sp), intent(in) :: a(lda,*),b(ldb,*),x(ldx,*) real(sp), intent(out) :: berr(*),ferr(*),work(*) end subroutine strrfs #else module procedure stdlib${ii}$_strrfs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztrrfs( uplo, trans, diag, n, nrhs, a, lda, b, ldb, x,ldx, ferr, & berr, work, rwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,ldx,n,nrhs real(dp), intent(out) :: berr(*),ferr(*),rwork(*) complex(dp), intent(in) :: a(lda,*),b(ldb,*),x(ldx,*) complex(dp), intent(out) :: work(*) end subroutine ztrrfs #else module procedure stdlib${ii}$_ztrrfs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trrfs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trrfs #:endif #:endfor #:endfor end interface trrfs interface trsen !! TRSEN reorders the Schur factorization of a complex matrix !! A = Q*T*Q**H, so that a selected cluster of eigenvalues appears in !! the leading positions on the diagonal of the upper triangular matrix !! T, and the leading columns of Q form an orthonormal basis of the !! corresponding right invariant subspace. !! Optionally the routine computes the reciprocal condition numbers of !! the cluster of eigenvalues and/or the invariant subspace. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ctrsen( job, compq, select, n, t, ldt, q, ldq, w, m, s,sep, work, lwork,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,job integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldq,ldt,lwork,n real(sp), intent(out) :: s,sep logical(lk), intent(in) :: select(*) complex(sp), intent(inout) :: q(ldq,*),t(ldt,*) complex(sp), intent(out) :: w(*),work(*) end subroutine ctrsen #else module procedure stdlib${ii}$_ctrsen #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dtrsen( job, compq, select, n, t, ldt, q, ldq, wr, wi,m, s, sep, work, & lwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,job integer(${ik}$), intent(out) :: info,m,iwork(*) integer(${ik}$), intent(in) :: ldq,ldt,liwork,lwork,n real(dp), intent(out) :: s,sep,wi(*),work(*),wr(*) logical(lk), intent(in) :: select(*) real(dp), intent(inout) :: q(ldq,*),t(ldt,*) end subroutine dtrsen #else module procedure stdlib${ii}$_dtrsen #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine strsen( job, compq, select, n, t, ldt, q, ldq, wr, wi,m, s, sep, work, & lwork, iwork, liwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,job integer(${ik}$), intent(out) :: info,m,iwork(*) integer(${ik}$), intent(in) :: ldq,ldt,liwork,lwork,n real(sp), intent(out) :: s,sep,wi(*),work(*),wr(*) logical(lk), intent(in) :: select(*) real(sp), intent(inout) :: q(ldq,*),t(ldt,*) end subroutine strsen #else module procedure stdlib${ii}$_strsen #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ztrsen( job, compq, select, n, t, ldt, q, ldq, w, m, s,sep, work, lwork,& info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: compq,job integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldq,ldt,lwork,n real(dp), intent(out) :: s,sep logical(lk), intent(in) :: select(*) complex(dp), intent(inout) :: q(ldq,*),t(ldt,*) complex(dp), intent(out) :: w(*),work(*) end subroutine ztrsen #else module procedure stdlib${ii}$_ztrsen #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trsen #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trsen #:endif #:endfor #:endfor end interface trsen interface trsna !! TRSNA estimates reciprocal condition numbers for specified !! eigenvalues and/or right eigenvectors of a complex upper triangular !! matrix T (or of any matrix Q*T*Q**H with Q unitary). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctrsna( job, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, s, sep, & mm, m, work, ldwork, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,job integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,ldwork,mm,n logical(lk), intent(in) :: select(*) real(sp), intent(out) :: rwork(*),s(*),sep(*) complex(sp), intent(in) :: t(ldt,*),vl(ldvl,*),vr(ldvr,*) complex(sp), intent(out) :: work(ldwork,*) end subroutine ctrsna #else module procedure stdlib${ii}$_ctrsna #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dtrsna( job, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, s, sep, mm, & m, work, ldwork, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,job integer(${ik}$), intent(out) :: info,m,iwork(*) integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,ldwork,mm,n logical(lk), intent(in) :: select(*) real(dp), intent(out) :: s(*),sep(*),work(ldwork,*) real(dp), intent(in) :: t(ldt,*),vl(ldvl,*),vr(ldvr,*) end subroutine dtrsna #else module procedure stdlib${ii}$_dtrsna #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine strsna( job, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, s, sep, mm, & m, work, ldwork, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,job integer(${ik}$), intent(out) :: info,m,iwork(*) integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,ldwork,mm,n logical(lk), intent(in) :: select(*) real(sp), intent(out) :: s(*),sep(*),work(ldwork,*) real(sp), intent(in) :: t(ldt,*),vl(ldvl,*),vr(ldvr,*) end subroutine strsna #else module procedure stdlib${ii}$_strsna #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztrsna( job, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, s, sep, & mm, m, work, ldwork, rwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: howmny,job integer(${ik}$), intent(out) :: info,m integer(${ik}$), intent(in) :: ldt,ldvl,ldvr,ldwork,mm,n logical(lk), intent(in) :: select(*) real(dp), intent(out) :: rwork(*),s(*),sep(*) complex(dp), intent(in) :: t(ldt,*),vl(ldvl,*),vr(ldvr,*) complex(dp), intent(out) :: work(ldwork,*) end subroutine ztrsna #else module procedure stdlib${ii}$_ztrsna #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trsna #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trsna #:endif #:endfor #:endfor end interface trsna interface trsyl !! TRSYL solves the complex Sylvester matrix equation: !! op(A)*X + X*op(B) = scale*C or !! op(A)*X - X*op(B) = scale*C, !! where op(A) = A or A**H, and A and B are both upper triangular. A is !! M-by-M and B is N-by-N; the right hand side C and the solution X are !! M-by-N; and scale is an output scale factor, set <= 1 to avoid !! overflow in X. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ctrsyl( trana, tranb, isgn, m, n, a, lda, b, ldb, c,ldc, scale, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trana,tranb integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn,lda,ldb,ldc,m,n real(sp), intent(out) :: scale complex(sp), intent(in) :: a(lda,*),b(ldb,*) complex(sp), intent(inout) :: c(ldc,*) end subroutine ctrsyl #else module procedure stdlib${ii}$_ctrsyl #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine dtrsyl( trana, tranb, isgn, m, n, a, lda, b, ldb, c,ldc, scale, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trana,tranb integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn,lda,ldb,ldc,m,n real(dp), intent(out) :: scale real(dp), intent(in) :: a(lda,*),b(ldb,*) real(dp), intent(inout) :: c(ldc,*) end subroutine dtrsyl #else module procedure stdlib${ii}$_dtrsyl #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine strsyl( trana, tranb, isgn, m, n, a, lda, b, ldb, c,ldc, scale, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trana,tranb integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn,lda,ldb,ldc,m,n real(sp), intent(out) :: scale real(sp), intent(in) :: a(lda,*),b(ldb,*) real(sp), intent(inout) :: c(ldc,*) end subroutine strsyl #else module procedure stdlib${ii}$_strsyl #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine ztrsyl( trana, tranb, isgn, m, n, a, lda, b, ldb, c,ldc, scale, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: trana,tranb integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn,lda,ldb,ldc,m,n real(dp), intent(out) :: scale complex(dp), intent(in) :: a(lda,*),b(ldb,*) complex(dp), intent(inout) :: c(ldc,*) end subroutine ztrsyl #else module procedure stdlib${ii}$_ztrsyl #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trsyl #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trsyl #:endif #:endfor #:endfor end interface trsyl interface trtri !! TRTRI computes the inverse of a complex upper or lower triangular !! matrix A. !! This is the Level 3 BLAS version of the algorithm. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctrtri( uplo, diag, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n complex(sp), intent(inout) :: a(lda,*) end subroutine ctrtri #else module procedure stdlib${ii}$_ctrtri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtrtri( uplo, diag, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(dp), intent(inout) :: a(lda,*) end subroutine dtrtri #else module procedure stdlib${ii}$_dtrtri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine strtri( uplo, diag, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n real(sp), intent(inout) :: a(lda,*) end subroutine strtri #else module procedure stdlib${ii}$_strtri #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztrtri( uplo, diag, n, a, lda, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,n complex(dp), intent(inout) :: a(lda,*) end subroutine ztrtri #else module procedure stdlib${ii}$_ztrtri #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trtri #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trtri #:endif #:endfor #:endfor end interface trtri interface trtrs !! TRTRS solves a triangular system of the form !! A * X = B, A**T * X = B, or A**H * X = B, !! where A is a triangular matrix of order N, and B is an N-by-NRHS !! matrix. A check is made to verify that A is nonsingular. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctrtrs( uplo, trans, diag, n, nrhs, a, lda, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: b(ldb,*) end subroutine ctrtrs #else module procedure stdlib${ii}$_ctrtrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtrtrs( uplo, trans, diag, n, nrhs, a, lda, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: b(ldb,*) end subroutine dtrtrs #else module procedure stdlib${ii}$_dtrtrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine strtrs( uplo, trans, diag, n, nrhs, a, lda, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: b(ldb,*) end subroutine strtrs #else module procedure stdlib${ii}$_strtrs #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztrtrs( uplo, trans, diag, n, nrhs, a, lda, b, ldb,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: diag,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldb,n,nrhs complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: b(ldb,*) end subroutine ztrtrs #else module procedure stdlib${ii}$_ztrtrs #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trtrs #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trtrs #:endif #:endfor #:endfor end interface trtrs interface trttf !! TRTTF copies a triangular matrix A from standard full format (TR) !! to rectangular full packed format (TF) . #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctrttf( transr, uplo, n, a, lda, arf, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda complex(sp), intent(in) :: a(0:lda-1,0:*) complex(sp), intent(out) :: arf(0:*) end subroutine ctrttf #else module procedure stdlib${ii}$_ctrttf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtrttf( transr, uplo, n, a, lda, arf, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda real(dp), intent(in) :: a(0:lda-1,0:*) real(dp), intent(out) :: arf(0:*) end subroutine dtrttf #else module procedure stdlib${ii}$_dtrttf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine strttf( transr, uplo, n, a, lda, arf, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda real(sp), intent(in) :: a(0:lda-1,0:*) real(sp), intent(out) :: arf(0:*) end subroutine strttf #else module procedure stdlib${ii}$_strttf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztrttf( transr, uplo, n, a, lda, arf, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: transr,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda complex(dp), intent(in) :: a(0:lda-1,0:*) complex(dp), intent(out) :: arf(0:*) end subroutine ztrttf #else module procedure stdlib${ii}$_ztrttf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trttf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trttf #:endif #:endfor #:endfor end interface trttf interface trttp !! TRTTP copies a triangular matrix A from full format (TR) to standard !! packed format (TP). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctrttp( uplo, n, a, lda, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: ap(*) end subroutine ctrttp #else module procedure stdlib${ii}$_ctrttp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtrttp( uplo, n, a, lda, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: ap(*) end subroutine dtrttp #else module procedure stdlib${ii}$_dtrttp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine strttp( uplo, n, a, lda, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: ap(*) end subroutine strttp #else module procedure stdlib${ii}$_strttp #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztrttp( uplo, n, a, lda, ap, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n,lda complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: ap(*) end subroutine ztrttp #else module procedure stdlib${ii}$_ztrttp #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trttp #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$trttp #:endif #:endfor #:endfor end interface trttp interface tzrzf !! TZRZF reduces the M-by-N ( M<=N ) complex upper trapezoidal matrix A !! to upper triangular form by means of unitary transformations. !! The upper trapezoidal matrix A is factored as !! A = ( R 0 ) * Z, !! where Z is an N-by-N unitary matrix and R is an M-by-M upper !! triangular matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ctzrzf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*),work(*) end subroutine ctzrzf #else module procedure stdlib${ii}$_ctzrzf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine dtzrzf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*),work(*) end subroutine dtzrzf #else module procedure stdlib${ii}$_dtzrzf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine stzrzf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*),work(*) end subroutine stzrzf #else module procedure stdlib${ii}$_stzrzf #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine ztzrzf( m, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*),work(*) end subroutine ztzrzf #else module procedure stdlib${ii}$_ztzrzf #endif #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tzrzf #:endif #:endfor #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$tzrzf #:endif #:endfor #:endfor end interface tzrzf interface unbdb !! UNBDB simultaneously bidiagonalizes the blocks of an M-by-M !! partitioned unitary matrix X: !! [ B11 | B12 0 0 ] !! [ X11 | X12 ] [ P1 | ] [ 0 | 0 -I 0 ] [ Q1 | ]**H !! X = [-----------] = [---------] [----------------] [---------] . !! [ X21 | X22 ] [ | P2 ] [ B21 | B22 0 0 ] [ | Q2 ] !! [ 0 | 0 0 I ] !! X11 is P-by-Q. Q must be no larger than P, M-P, or M-Q. (If this is !! not the case, then X must be transposed and/or permuted. This can be !! done in constant time using the TRANS and SIGNS options. See CUNCSD !! for details.) !! The unitary matrices P1, P2, Q1, and Q2 are P-by-P, (M-P)-by- !! (M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. They are !! represented implicitly by Householder vectors. !! B11, B12, B21, and B22 are Q-by-Q bidiagonal matrices represented !! implicitly by angles THETA, PHI. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: signs,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldx11,ldx12,ldx21,ldx22,lwork,m,p,q real(sp), intent(out) :: phi(*),theta(*) complex(sp), intent(out) :: taup1(*),taup2(*),tauq1(*),tauq2(*),work(*) complex(sp), intent(inout) :: x11(ldx11,*),x12(ldx12,*),x21(ldx21,*),x22(& ldx22,*) end subroutine cunbdb #else module procedure stdlib${ii}$_cunbdb #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: signs,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldx11,ldx12,ldx21,ldx22,lwork,m,p,q real(dp), intent(out) :: phi(*),theta(*) complex(dp), intent(out) :: taup1(*),taup2(*),tauq1(*),tauq2(*),work(*) complex(dp), intent(inout) :: x11(ldx11,*),x12(ldx12,*),x21(ldx21,*),x22(& ldx22,*) end subroutine zunbdb #else module procedure stdlib${ii}$_zunbdb #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unbdb #:endif #:endfor #:endfor end interface unbdb interface unbdb1 !! UNBDB1 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. Q must be no larger than P, !! M-P, or M-Q. Routines CUNBDB2, CUNBDB3, and CUNBDB4 handle cases in !! which Q is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are Q-by-Q bidiagonal matrices represented implicitly by !! angles THETA, PHI. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(sp), intent(out) :: phi(*),theta(*) complex(sp), intent(out) :: taup1(*),taup2(*),tauq1(*),work(*) complex(sp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine cunbdb1 #else module procedure stdlib${ii}$_cunbdb1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(dp), intent(out) :: phi(*),theta(*) complex(dp), intent(out) :: taup1(*),taup2(*),tauq1(*),work(*) complex(dp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine zunbdb1 #else module procedure stdlib${ii}$_zunbdb1 #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unbdb1 #:endif #:endfor #:endfor end interface unbdb1 interface unbdb2 !! UNBDB2 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. P must be no larger than M-P, !! Q, or M-Q. Routines CUNBDB1, CUNBDB3, and CUNBDB4 handle cases in !! which P is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are P-by-P bidiagonal matrices represented implicitly by !! angles THETA, PHI. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(sp), intent(out) :: phi(*),theta(*) complex(sp), intent(out) :: taup1(*),taup2(*),tauq1(*),work(*) complex(sp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine cunbdb2 #else module procedure stdlib${ii}$_cunbdb2 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(dp), intent(out) :: phi(*),theta(*) complex(dp), intent(out) :: taup1(*),taup2(*),tauq1(*),work(*) complex(dp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine zunbdb2 #else module procedure stdlib${ii}$_zunbdb2 #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unbdb2 #:endif #:endfor #:endfor end interface unbdb2 interface unbdb3 !! UNBDB3 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-P must be no larger than P, !! Q, or M-Q. Routines CUNBDB1, CUNBDB2, and CUNBDB4 handle cases in !! which M-P is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-P)-by-(M-P) bidiagonal matrices represented !! implicitly by angles THETA, PHI. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(sp), intent(out) :: phi(*),theta(*) complex(sp), intent(out) :: taup1(*),taup2(*),tauq1(*),work(*) complex(sp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine cunbdb3 #else module procedure stdlib${ii}$_cunbdb3 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(dp), intent(out) :: phi(*),theta(*) complex(dp), intent(out) :: taup1(*),taup2(*),tauq1(*),work(*) complex(dp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine zunbdb3 #else module procedure stdlib${ii}$_zunbdb3 #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unbdb3 #:endif #:endfor #:endfor end interface unbdb3 interface unbdb4 !! UNBDB4 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-Q must be no larger than P, !! M-P, or Q. Routines CUNBDB1, CUNBDB2, and CUNBDB3 handle cases in !! which M-Q is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-Q)-by-(M-Q) bidiagonal matrices represented !! implicitly by angles THETA, PHI. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, phantom, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(sp), intent(out) :: phi(*),theta(*) complex(sp), intent(out) :: phantom(*),taup1(*),taup2(*),tauq1(*),work(*) complex(sp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine cunbdb4 #else module procedure stdlib${ii}$_cunbdb4 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, & tauq1, phantom, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork,m,p,q,ldx11,ldx21 real(dp), intent(out) :: phi(*),theta(*) complex(dp), intent(out) :: phantom(*),taup1(*),taup2(*),tauq1(*),work(*) complex(dp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine zunbdb4 #else module procedure stdlib${ii}$_zunbdb4 #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unbdb4 #:endif #:endfor #:endfor end interface unbdb4 interface unbdb5 !! UNBDB5 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then some other vector from the orthogonal complement !! is returned. This vector is chosen in an arbitrary but deterministic !! way. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx1,incx2,ldq1,ldq2,lwork,m1,m2,n integer(${ik}$), intent(out) :: info complex(sp), intent(in) :: q1(ldq1,*),q2(ldq2,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x1(*),x2(*) end subroutine cunbdb5 #else module procedure stdlib${ii}$_cunbdb5 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx1,incx2,ldq1,ldq2,lwork,m1,m2,n integer(${ik}$), intent(out) :: info complex(dp), intent(in) :: q1(ldq1,*),q2(ldq2,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x1(*),x2(*) end subroutine zunbdb5 #else module procedure stdlib${ii}$_zunbdb5 #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unbdb5 #:endif #:endfor #:endfor end interface unbdb5 interface unbdb6 !! UNBDB6 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then the zero vector is returned. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx1,incx2,ldq1,ldq2,lwork,m1,m2,n integer(${ik}$), intent(out) :: info complex(sp), intent(in) :: q1(ldq1,*),q2(ldq2,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x1(*),x2(*) end subroutine cunbdb6 #else module procedure stdlib${ii}$_cunbdb6 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: incx1,incx2,ldq1,ldq2,lwork,m1,m2,n integer(${ik}$), intent(out) :: info complex(dp), intent(in) :: q1(ldq1,*),q2(ldq2,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x1(*),x2(*) end subroutine zunbdb6 #else module procedure stdlib${ii}$_zunbdb6 #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unbdb6 #:endif #:endfor #:endfor end interface unbdb6 interface uncsd !! UNCSD computes the CS decomposition of an M-by-M partitioned !! unitary matrix X: !! [ I 0 0 | 0 0 0 ] !! [ 0 C 0 | 0 -S 0 ] !! [ X11 | X12 ] [ U1 | ] [ 0 0 0 | 0 0 -I ] [ V1 | ]**H !! X = [-----------] = [---------] [---------------------] [---------] . !! [ X21 | X22 ] [ | U2 ] [ 0 0 0 | I 0 0 ] [ | V2 ] !! [ 0 S 0 | 0 C 0 ] !! [ 0 0 I | 0 0 0 ] !! X11 is P-by-Q. The unitary matrices U1, U2, V1, and V2 are P-by-P, !! (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are !! R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in !! which R = MIN(P,M-P,Q,M-Q). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ recursive subroutine cuncsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, & x11, ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, & ldv1t, v2t,ldv2t, work, lwork, rwork, lrwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu1,jobu2,jobv1t,jobv2t,signs,trans integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu1,ldu2,ldv1t,ldv2t,ldx11,ldx12,ldx21,ldx22,& lrwork,lwork,m,p,q real(sp), intent(out) :: theta(*),rwork(*) complex(sp), intent(out) :: u1(ldu1,*),u2(ldu2,*),v1t(ldv1t,*),v2t(ldv2t,*),& work(*) complex(sp), intent(inout) :: x11(ldx11,*),x12(ldx12,*),x21(ldx21,*),x22(& ldx22,*) end subroutine cuncsd #else module procedure stdlib${ii}$_cuncsd #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ recursive subroutine zuncsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, & x11, ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, & ldv1t, v2t,ldv2t, work, lwork, rwork, lrwork,iwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu1,jobu2,jobv1t,jobv2t,signs,trans integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu1,ldu2,ldv1t,ldv2t,ldx11,ldx12,ldx21,ldx22,& lrwork,lwork,m,p,q real(dp), intent(out) :: theta(*),rwork(*) complex(dp), intent(out) :: u1(ldu1,*),u2(ldu2,*),v1t(ldv1t,*),v2t(ldv2t,*),& work(*) complex(dp), intent(inout) :: x11(ldx11,*),x12(ldx12,*),x21(ldx21,*),x22(& ldx22,*) end subroutine zuncsd #else module procedure stdlib${ii}$_zuncsd #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$uncsd #:endif #:endfor #:endfor end interface uncsd interface uncsd2by1 !! UNCSD2BY1 computes the CS decomposition of an M-by-Q matrix X with !! orthonormal columns that has been partitioned into a 2-by-1 block !! structure: !! [ I1 0 0 ] !! [ 0 C 0 ] !! [ X11 ] [ U1 | ] [ 0 0 0 ] !! X = [-----] = [---------] [----------] V1**T . !! [ X21 ] [ | U2 ] [ 0 0 0 ] !! [ 0 S 0 ] !! [ 0 0 I2] !! X11 is P-by-Q. The unitary matrices U1, U2, and V1 are P-by-P, !! (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R !! nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which !! R = MIN(P,M-P,Q,M-Q). I1 is a K1-by-K1 identity matrix and I2 is a !! K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine cuncsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta,& u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, rwork, lrwork, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu1,jobu2,jobv1t integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu1,ldu2,ldv1t,lwork,ldx11,ldx21,m,p,q,& lrwork real(sp), intent(out) :: rwork(*),theta(*) complex(sp), intent(out) :: u1(ldu1,*),u2(ldu2,*),v1t(ldv1t,*),work(*) complex(sp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine cuncsd2by1 #else module procedure stdlib${ii}$_cuncsd2by1 #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ subroutine zuncsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta,& u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, rwork, lrwork, iwork,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: jobu1,jobu2,jobv1t integer(${ik}$), intent(out) :: info,iwork(*) integer(${ik}$), intent(in) :: ldu1,ldu2,ldv1t,lwork,ldx11,ldx21,m,p,q,& lrwork real(dp), intent(out) :: rwork(*),theta(*) complex(dp), intent(out) :: u1(ldu1,*),u2(ldu2,*),v1t(ldv1t,*),work(*) complex(dp), intent(inout) :: x11(ldx11,*),x21(ldx21,*) end subroutine zuncsd2by1 #else module procedure stdlib${ii}$_zuncsd2by1 #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$uncsd2by1 #:endif #:endfor #:endfor end interface uncsd2by1 interface ung2l !! UNG2L generates an m by n complex matrix Q with orthonormal columns, !! which is defined as the last n columns of a product of k elementary !! reflectors of order m !! Q = H(k) . . . H(2) H(1) !! as returned by CGEQLF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cung2l( m, n, k, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cung2l #else module procedure stdlib${ii}$_cung2l #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zung2l( m, n, k, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zung2l #else module procedure stdlib${ii}$_zung2l #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ung2l #:endif #:endfor #:endfor end interface ung2l interface ung2r !! UNG2R generates an m by n complex matrix Q with orthonormal columns, !! which is defined as the first n columns of a product of k elementary !! reflectors of order m !! Q = H(1) H(2) . . . H(k) !! as returned by CGEQRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cung2r( m, n, k, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cung2r #else module procedure stdlib${ii}$_cung2r #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zung2r( m, n, k, a, lda, tau, work, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zung2r #else module procedure stdlib${ii}$_zung2r #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ung2r #:endif #:endfor #:endfor end interface ung2r interface ungbr !! UNGBR generates one of the complex unitary matrices Q or P**H !! determined by CGEBRD when reducing a complex matrix A to bidiagonal !! form: A = Q * B * P**H. Q and P**H are defined as products of !! elementary reflectors H(i) or G(i) respectively. !! If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q !! is of order M: !! if m >= k, Q = H(1) H(2) . . . H(k) and UNGBR returns the first n !! columns of Q, where m >= n >= k; !! if m < k, Q = H(1) H(2) . . . H(m-1) and UNGBR returns Q as an !! M-by-M matrix. !! If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**H !! is of order N: !! if k < n, P**H = G(k) . . . G(2) G(1) and UNGBR returns the first m !! rows of P**H, where n >= m >= k; !! if k >= n, P**H = G(n-1) . . . G(2) G(1) and UNGBR returns P**H as !! an N-by-N matrix. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cungbr( vect, m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cungbr #else module procedure stdlib${ii}$_cungbr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zungbr( vect, m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zungbr #else module procedure stdlib${ii}$_zungbr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ungbr #:endif #:endfor #:endfor end interface ungbr interface unghr !! UNGHR generates a complex unitary matrix Q which is defined as the !! product of IHI-ILO elementary reflectors of order N, as returned by !! CGEHRD: !! Q = H(ilo) H(ilo+1) . . . H(ihi-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunghr( n, ilo, ihi, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,lda,lwork,n integer(${ik}$), intent(out) :: info complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunghr #else module procedure stdlib${ii}$_cunghr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunghr( n, ilo, ihi, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(in) :: ihi,ilo,lda,lwork,n integer(${ik}$), intent(out) :: info complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunghr #else module procedure stdlib${ii}$_zunghr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unghr #:endif #:endfor #:endfor end interface unghr interface unglq !! UNGLQ generates an M-by-N complex matrix Q with orthonormal rows, !! which is defined as the first M rows of a product of K elementary !! reflectors of order N !! Q = H(k)**H . . . H(2)**H H(1)**H !! as returned by CGELQF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunglq( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunglq #else module procedure stdlib${ii}$_cunglq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunglq( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunglq #else module procedure stdlib${ii}$_zunglq #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unglq #:endif #:endfor #:endfor end interface unglq interface ungql !! UNGQL generates an M-by-N complex matrix Q with orthonormal columns, !! which is defined as the last N columns of a product of K elementary !! reflectors of order M !! Q = H(k) . . . H(2) H(1) !! as returned by CGEQLF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cungql( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cungql #else module procedure stdlib${ii}$_cungql #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zungql( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zungql #else module procedure stdlib${ii}$_zungql #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ungql #:endif #:endfor #:endfor end interface ungql interface ungqr !! UNGQR generates an M-by-N complex matrix Q with orthonormal columns, !! which is defined as the first N columns of a product of K elementary !! reflectors of order M !! Q = H(1) H(2) . . . H(k) !! as returned by CGEQRF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cungqr( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cungqr #else module procedure stdlib${ii}$_cungqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zungqr( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zungqr #else module procedure stdlib${ii}$_zungqr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ungqr #:endif #:endfor #:endfor end interface ungqr interface ungrq !! UNGRQ generates an M-by-N complex matrix Q with orthonormal rows, !! which is defined as the last M rows of a product of K elementary !! reflectors of order N !! Q = H(1)**H H(2)**H . . . H(k)**H !! as returned by CGERQF. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cungrq( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cungrq #else module procedure stdlib${ii}$_cungrq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zungrq( m, n, k, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,lwork,m,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zungrq #else module procedure stdlib${ii}$_zungrq #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ungrq #:endif #:endfor #:endfor end interface ungrq interface ungtr !! UNGTR generates a complex unitary matrix Q which is defined as the !! product of n-1 elementary reflectors of order N, as returned by !! CHETRD: !! if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), !! if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cungtr( uplo, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cungtr #else module procedure stdlib${ii}$_cungtr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zungtr( uplo, n, a, lda, tau, work, lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,lwork,n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zungtr #else module procedure stdlib${ii}$_zungtr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ungtr #:endif #:endfor #:endfor end interface ungtr interface ungtsqr !! UNGTSQR generates an M-by-N complex matrix Q_out with orthonormal !! columns, which are the first N columns of a product of comlpex unitary !! matrices of order M which are returned by CLATSQR !! Q_out = first_N_columns_of( Q(1)_in * Q(2)_in * ... * Q(k)_in ). !! See the documentation for CLATSQR. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cungtsqr( m, n, mb, nb, a, lda, t, ldt, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,mb,nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: t(ldt,*) complex(sp), intent(out) :: work(*) end subroutine cungtsqr #else module procedure stdlib${ii}$_cungtsqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zungtsqr( m, n, mb, nb, a, lda, t, ldt, work, lwork,info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,mb,nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: t(ldt,*) complex(dp), intent(out) :: work(*) end subroutine zungtsqr #else module procedure stdlib${ii}$_zungtsqr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ungtsqr #:endif #:endfor #:endfor end interface ungtsqr interface ungtsqr_row !! UNGTSQR_ROW generates an M-by-N complex matrix Q_out with !! orthonormal columns from the output of CLATSQR. These N orthonormal !! columns are the first N columns of a product of complex unitary !! matrices Q(k)_in of order M, which are returned by CLATSQR in !! a special format. !! Q_out = first_N_columns_of( Q(1)_in * Q(2)_in * ... * Q(k)_in ). !! The input matrices Q(k)_in are stored in row and column blocks in A. !! See the documentation of CLATSQR for more details on the format of !! Q(k)_in, where each Q(k)_in is represented by block Householder !! transformations. This routine calls an auxiliary routine CLARFB_GETT, !! where the computation is performed on each individual block. The !! algorithm first sweeps NB-sized column blocks from the right to left !! starting in the bottom row block and continues to the top row block !! (hence _ROW in the routine name). This sweep is in reverse order of !! the order in which CLATSQR generates the output blocks. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cungtsqr_row( m, n, mb, nb, a, lda, t, ldt, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,mb,nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: t(ldt,*) complex(sp), intent(out) :: work(*) end subroutine cungtsqr_row #else module procedure stdlib${ii}$_cungtsqr_row #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zungtsqr_row( m, n, mb, nb, a, lda, t, ldt, work,lwork, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,lwork,m,n,mb,nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: t(ldt,*) complex(dp), intent(out) :: work(*) end subroutine zungtsqr_row #else module procedure stdlib${ii}$_zungtsqr_row #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$ungtsqr_row #:endif #:endfor #:endfor end interface ungtsqr_row interface unhr_col !! UNHR_COL takes an M-by-N complex matrix Q_in with orthonormal columns !! as input, stored in A, and performs Householder Reconstruction (HR), !! i.e. reconstructs Householder vectors V(i) implicitly representing !! another M-by-N matrix Q_out, with the property that Q_in = Q_out*S, !! where S is an N-by-N diagonal matrix with diagonal entries !! equal to +1 or -1. The Householder vectors (columns V(i) of V) are !! stored in A on output, and the diagonal entries of S are stored in D. !! Block reflectors are also returned in T !! (same output format as CGEQRT). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunhr_col( m, n, nb, a, lda, t, ldt, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: d(*),t(ldt,*) end subroutine cunhr_col #else module procedure stdlib${ii}$_cunhr_col #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunhr_col( m, n, nb, a, lda, t, ldt, d, info ) import sp,dp,qp,${ik}$,lk implicit none integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldt,m,n,nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: d(*),t(ldt,*) end subroutine zunhr_col #else module procedure stdlib${ii}$_zunhr_col #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unhr_col #:endif #:endfor #:endfor end interface unhr_col interface unm2l !! UNM2L overwrites the general complex m-by-n matrix C with !! Q * C if SIDE = 'L' and TRANS = 'N', or !! Q**H* C if SIDE = 'L' and TRANS = 'C', or !! C * Q if SIDE = 'R' and TRANS = 'N', or !! C * Q**H if SIDE = 'R' and TRANS = 'C', !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by CGEQLF. Q is of order m if SIDE = 'L' and of order n !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunm2l( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,m,n complex(sp), intent(inout) :: a(lda,*),c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunm2l #else module procedure stdlib${ii}$_cunm2l #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunm2l( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,m,n complex(dp), intent(inout) :: a(lda,*),c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunm2l #else module procedure stdlib${ii}$_zunm2l #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unm2l #:endif #:endfor #:endfor end interface unm2l interface unm2r !! UNM2R overwrites the general complex m-by-n matrix C with !! Q * C if SIDE = 'L' and TRANS = 'N', or !! Q**H* C if SIDE = 'L' and TRANS = 'C', or !! C * Q if SIDE = 'R' and TRANS = 'N', or !! C * Q**H if SIDE = 'R' and TRANS = 'C', !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by CGEQRF. Q is of order m if SIDE = 'L' and of order n !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunm2r( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,m,n complex(sp), intent(inout) :: a(lda,*),c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunm2r #else module procedure stdlib${ii}$_cunm2r #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunm2r( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,m,n complex(dp), intent(inout) :: a(lda,*),c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunm2r #else module procedure stdlib${ii}$_zunm2r #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unm2r #:endif #:endfor #:endfor end interface unm2r interface unmbr !! If VECT = 'Q', UNMBR: overwrites the general complex M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! If VECT = 'P', UNMBR overwrites the general complex M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': P * C C * P !! TRANS = 'C': P**H * C C * P**H !! Here Q and P**H are the unitary matrices determined by CGEBRD when !! reducing a complex matrix A to bidiagonal form: A = Q * B * P**H. Q !! and P**H are defined as products of elementary reflectors H(i) and !! G(i) respectively. !! Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the !! order of the unitary matrix Q or P**H that is applied. !! If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: !! if nq >= k, Q = H(1) H(2) . . . H(k); !! if nq < k, Q = H(1) H(2) . . . H(nq-1). !! If VECT = 'P', A is assumed to have been a K-by-NQ matrix: !! if k < nq, P = G(1) G(2) . . . G(k); !! if k >= nq, P = G(1) G(2) . . . G(nq-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunmbr( vect, side, trans, m, n, k, a, lda, tau, c,ldc, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n complex(sp), intent(inout) :: a(lda,*),c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunmbr #else module procedure stdlib${ii}$_cunmbr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunmbr( vect, side, trans, m, n, k, a, lda, tau, c,ldc, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n complex(dp), intent(inout) :: a(lda,*),c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunmbr #else module procedure stdlib${ii}$_zunmbr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unmbr #:endif #:endfor #:endfor end interface unmbr interface unmhr !! UNMHR overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix of order nq, with nq = m if !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of !! IHI-ILO elementary reflectors, as returned by CGEHRD: !! Q = H(ilo) H(ilo+1) . . . H(ihi-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunmhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(in) :: ihi,ilo,lda,ldc,lwork,m,n integer(${ik}$), intent(out) :: info complex(sp), intent(inout) :: a(lda,*),c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunmhr #else module procedure stdlib${ii}$_cunmhr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunmhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, & lwork, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(in) :: ihi,ilo,lda,ldc,lwork,m,n integer(${ik}$), intent(out) :: info complex(dp), intent(inout) :: a(lda,*),c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunmhr #else module procedure stdlib${ii}$_zunmhr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unmhr #:endif #:endfor #:endfor end interface unmhr interface unmlq !! UNMLQ overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(k)**H . . . H(2)**H H(1)**H !! as returned by CGELQF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunmlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n complex(sp), intent(inout) :: a(lda,*),c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunmlq #else module procedure stdlib${ii}$_cunmlq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunmlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n complex(dp), intent(inout) :: a(lda,*),c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunmlq #else module procedure stdlib${ii}$_zunmlq #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unmlq #:endif #:endfor #:endfor end interface unmlq interface unmql !! UNMQL overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by CGEQLF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunmql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n complex(sp), intent(inout) :: a(lda,*),c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunmql #else module procedure stdlib${ii}$_cunmql #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunmql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n complex(dp), intent(inout) :: a(lda,*),c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunmql #else module procedure stdlib${ii}$_zunmql #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unmql #:endif #:endfor #:endfor end interface unmql interface unmqr !! UNMQR overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by CGEQRF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunmqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n complex(sp), intent(inout) :: a(lda,*),c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunmqr #else module procedure stdlib${ii}$_cunmqr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunmqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n complex(dp), intent(inout) :: a(lda,*),c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunmqr #else module procedure stdlib${ii}$_zunmqr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unmqr #:endif #:endfor #:endfor end interface unmqr interface unmrq !! UNMRQ overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(1)**H H(2)**H . . . H(k)**H !! as returned by CGERQF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunmrq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n complex(sp), intent(inout) :: a(lda,*),c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunmrq #else module procedure stdlib${ii}$_cunmrq #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunmrq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,lda,ldc,lwork,m,n complex(dp), intent(inout) :: a(lda,*),c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunmrq #else module procedure stdlib${ii}$_zunmrq #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unmrq #:endif #:endfor #:endfor end interface unmrq interface unmrz !! UNMRZ overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(1) H(2) . . . H(k) !! as returned by CTZRZF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunmrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,l,lda,ldc,lwork,m,n complex(sp), intent(inout) :: a(lda,*),c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunmrz #else module procedure stdlib${ii}$_cunmrz #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunmrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k,l,lda,ldc,lwork,m,n complex(dp), intent(inout) :: a(lda,*),c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunmrz #else module procedure stdlib${ii}$_zunmrz #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unmrz #:endif #:endfor #:endfor end interface unmrz interface unmtr !! UNMTR overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix of order nq, with nq = m if !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of !! nq-1 elementary reflectors, as returned by CHETRD: !! if UPLO = 'U', Q = H(nq-1) . . . H(2) H(1); !! if UPLO = 'L', Q = H(1) H(2) . . . H(nq-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cunmtr( side, uplo, trans, m, n, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldc,lwork,m,n complex(sp), intent(inout) :: a(lda,*),c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cunmtr #else module procedure stdlib${ii}$_cunmtr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zunmtr( side, uplo, trans, m, n, a, lda, tau, c, ldc,work, lwork, & info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda,ldc,lwork,m,n complex(dp), intent(inout) :: a(lda,*),c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zunmtr #else module procedure stdlib${ii}$_zunmtr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$unmtr #:endif #:endfor #:endfor end interface unmtr interface upgtr !! UPGTR generates a complex unitary matrix Q which is defined as the !! product of n-1 elementary reflectors H(i) of order n, as returned by !! CHPTRD using packed storage: !! if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), !! if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cupgtr( uplo, n, ap, tau, q, ldq, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq,n complex(sp), intent(in) :: ap(*),tau(*) complex(sp), intent(out) :: q(ldq,*),work(*) end subroutine cupgtr #else module procedure stdlib${ii}$_cupgtr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zupgtr( uplo, n, ap, tau, q, ldq, work, info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq,n complex(dp), intent(in) :: ap(*),tau(*) complex(dp), intent(out) :: q(ldq,*),work(*) end subroutine zupgtr #else module procedure stdlib${ii}$_zupgtr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$upgtr #:endif #:endfor #:endfor end interface upgtr interface upmtr !! UPMTR overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix of order nq, with nq = m if !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of !! nq-1 elementary reflectors, as returned by CHPTRD using packed !! storage: !! if UPLO = 'U', Q = H(nq-1) . . . H(2) H(1); !! if UPLO = 'L', Q = H(1) H(2) . . . H(nq-1). #:for ik,it,ii in LINALG_INT_KINDS_TYPES #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine cupmtr( side, uplo, trans, m, n, ap, tau, c, ldc, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc,m,n complex(sp), intent(inout) :: ap(*),c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine cupmtr #else module procedure stdlib${ii}$_cupmtr #endif #ifdef STDLIB_EXTERNAL_LAPACK${ii}$ pure subroutine zupmtr( side, uplo, trans, m, n, ap, tau, c, ldc, work,info ) import sp,dp,qp,${ik}$,lk implicit none character, intent(in) :: side,trans,uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc,m,n complex(dp), intent(inout) :: ap(*),c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine zupmtr #else module procedure stdlib${ii}$_zupmtr #endif #:for rk,rt,ri in CMPLX_KINDS_TYPES #:if not rk in ["sp","dp"] module procedure stdlib${ii}$_${ri}$upmtr #:endif #:endfor #:endfor end interface upmtr end module stdlib_linalg_lapack fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_base.fypp0000664000175000017500000037055515135654166024715 0ustar alastairalastair#:include "common.fypp" module stdlib_lapack_base use stdlib_linalg_constants use stdlib_linalg_lapack_aux use stdlib_linalg_blas implicit none interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(sp) module function stdlib${ii}$_slamch( cmach ) character, intent(in) :: cmach end function stdlib${ii}$_slamch pure real(dp) module function stdlib${ii}$_dlamch( cmach ) character, intent(in) :: cmach end function stdlib${ii}$_dlamch #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$lamch( cmach ) character, intent(in) :: cmach end function stdlib${ii}$_${ri}$lamch #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(sp) module function stdlib${ii}$_slamc3( a, b ) real(sp), intent(in) :: a, b end function stdlib${ii}$_slamc3 pure real(dp) module function stdlib${ii}$_dlamc3( a, b ) real(dp), intent(in) :: a, b end function stdlib${ii}$_dlamc3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$lamc3( a, b ) real(${rk}$), intent(in) :: a, b end function stdlib${ii}$_${ri}$lamc3 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slabad( small, large ) real(sp), intent(inout) :: large, small end subroutine stdlib${ii}$_slabad pure module subroutine stdlib${ii}$_dlabad( small, large ) real(dp), intent(inout) :: large, small end subroutine stdlib${ii}$_dlabad #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$labad( small, large ) real(${rk}$), intent(inout) :: large, small end subroutine stdlib${ii}$_${ri}$labad #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(sp) module function stdlib${ii}$_scsum1( n, cx, incx ) integer(${ik}$), intent(in) :: incx, n complex(sp), intent(in) :: cx(*) end function stdlib${ii}$_scsum1 #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(dp) module function stdlib${ii}$_dzsum1( n, cx, incx ) integer(${ik}$), intent(in) :: incx, n complex(dp), intent(in) :: cx(*) end function stdlib${ii}$_dzsum1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$zsum1( n, cx, incx ) integer(${ik}$), intent(in) :: incx, n complex(${rk}$), intent(in) :: cx(*) end function stdlib${ii}$_${ri}$zsum1 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slaqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(sp), intent(in) :: amax, scond real(sp), intent(inout) :: ab(ldab,*) real(sp), intent(in) :: s(*) end subroutine stdlib${ii}$_slaqsb pure module subroutine stdlib${ii}$_dlaqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(dp), intent(in) :: amax, scond real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(in) :: s(*) end subroutine stdlib${ii}$_dlaqsb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(${rk}$), intent(in) :: amax, scond real(${rk}$), intent(inout) :: ab(ldab,*) real(${rk}$), intent(in) :: s(*) end subroutine stdlib${ii}$_${ri}$laqsb #:endif #:endfor pure module subroutine stdlib${ii}$_claqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(sp), intent(in) :: amax, scond real(sp), intent(in) :: s(*) complex(sp), intent(inout) :: ab(ldab,*) end subroutine stdlib${ii}$_claqsb pure module subroutine stdlib${ii}$_zlaqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(dp), intent(in) :: amax, scond real(dp), intent(in) :: s(*) complex(dp), intent(inout) :: ab(ldab,*) end subroutine stdlib${ii}$_zlaqsb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(${ck}$), intent(in) :: amax, scond real(${ck}$), intent(in) :: s(*) complex(${ck}$), intent(inout) :: ab(ldab,*) end subroutine stdlib${ii}$_${ci}$laqsb #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sladiv1( a, b, c, d, p, q ) real(sp), intent(inout) :: a real(sp), intent(in) :: b, c, d real(sp), intent(out) :: p, q end subroutine stdlib${ii}$_sladiv1 pure module subroutine stdlib${ii}$_dladiv1( a, b, c, d, p, q ) real(dp), intent(inout) :: a real(dp), intent(in) :: b, c, d real(dp), intent(out) :: p, q end subroutine stdlib${ii}$_dladiv1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ladiv1( a, b, c, d, p, q ) real(${rk}$), intent(inout) :: a real(${rk}$), intent(in) :: b, c, d real(${rk}$), intent(out) :: p, q end subroutine stdlib${ii}$_${ri}$ladiv1 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(sp) module function stdlib${ii}$_sladiv2( a, b, c, d, r, t ) real(sp), intent(in) :: a, b, c, d, r, t end function stdlib${ii}$_sladiv2 pure real(dp) module function stdlib${ii}$_dladiv2( a, b, c, d, r, t ) real(dp), intent(in) :: a, b, c, d, r, t end function stdlib${ii}$_dladiv2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$ladiv2( a, b, c, d, r, t ) real(${rk}$), intent(in) :: a, b, c, d, r, t end function stdlib${ii}$_${ri}$ladiv2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_crot( n, cx, incx, cy, incy, c, s ) integer(${ik}$), intent(in) :: incx, incy, n real(sp), intent(in) :: c complex(sp), intent(in) :: s complex(sp), intent(inout) :: cx(*), cy(*) end subroutine stdlib${ii}$_crot pure module subroutine stdlib${ii}$_zrot( n, cx, incx, cy, incy, c, s ) integer(${ik}$), intent(in) :: incx, incy, n real(dp), intent(in) :: c complex(dp), intent(in) :: s complex(dp), intent(inout) :: cx(*), cy(*) end subroutine stdlib${ii}$_zrot #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$rot( n, cx, incx, cy, incy, c, s ) integer(${ik}$), intent(in) :: incx, incy, n real(${ck}$), intent(in) :: c complex(${ck}$), intent(in) :: s complex(${ck}$), intent(inout) :: cx(*), cy(*) end subroutine stdlib${ii}$_${ci}$rot #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slaset( uplo, m, n, alpha, beta, a, lda ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(in) :: alpha, beta real(sp), intent(out) :: a(lda,*) end subroutine stdlib${ii}$_slaset pure module subroutine stdlib${ii}$_dlaset( uplo, m, n, alpha, beta, a, lda ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(in) :: alpha, beta real(dp), intent(out) :: a(lda,*) end subroutine stdlib${ii}$_dlaset #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laset( uplo, m, n, alpha, beta, a, lda ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(in) :: alpha, beta real(${rk}$), intent(out) :: a(lda,*) end subroutine stdlib${ii}$_${ri}$laset #:endif #:endfor pure module subroutine stdlib${ii}$_claset( uplo, m, n, alpha, beta, a, lda ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, m, n complex(sp), intent(in) :: alpha, beta complex(sp), intent(out) :: a(lda,*) end subroutine stdlib${ii}$_claset pure module subroutine stdlib${ii}$_zlaset( uplo, m, n, alpha, beta, a, lda ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, m, n complex(dp), intent(in) :: alpha, beta complex(dp), intent(out) :: a(lda,*) end subroutine stdlib${ii}$_zlaset #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laset( uplo, m, n, alpha, beta, a, lda ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, m, n complex(${ck}$), intent(in) :: alpha, beta complex(${ck}$), intent(out) :: a(lda,*) end subroutine stdlib${ii}$_${ci}$laset #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slarnv( idist, iseed, n, x ) integer(${ik}$), intent(in) :: idist, n integer(${ik}$), intent(inout) :: iseed(4_${ik}$) real(sp), intent(out) :: x(*) end subroutine stdlib${ii}$_slarnv pure module subroutine stdlib${ii}$_dlarnv( idist, iseed, n, x ) integer(${ik}$), intent(in) :: idist, n integer(${ik}$), intent(inout) :: iseed(4_${ik}$) real(dp), intent(out) :: x(*) end subroutine stdlib${ii}$_dlarnv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larnv( idist, iseed, n, x ) integer(${ik}$), intent(in) :: idist, n integer(${ik}$), intent(inout) :: iseed(4_${ik}$) real(${rk}$), intent(out) :: x(*) end subroutine stdlib${ii}$_${ri}$larnv #:endif #:endfor pure module subroutine stdlib${ii}$_clarnv( idist, iseed, n, x ) integer(${ik}$), intent(in) :: idist, n integer(${ik}$), intent(inout) :: iseed(4_${ik}$) complex(sp), intent(out) :: x(*) end subroutine stdlib${ii}$_clarnv pure module subroutine stdlib${ii}$_zlarnv( idist, iseed, n, x ) integer(${ik}$), intent(in) :: idist, n integer(${ik}$), intent(inout) :: iseed(4_${ik}$) complex(dp), intent(out) :: x(*) end subroutine stdlib${ii}$_zlarnv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larnv( idist, iseed, n, x ) integer(${ik}$), intent(in) :: idist, n integer(${ik}$), intent(inout) :: iseed(4_${ik}$) complex(${ck}$), intent(out) :: x(*) end subroutine stdlib${ii}$_${ci}$larnv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slaruv( iseed, n, x ) integer(${ik}$), intent(in) :: n integer(${ik}$), intent(inout) :: iseed(4_${ik}$) real(sp), intent(out) :: x(n) end subroutine stdlib${ii}$_slaruv pure module subroutine stdlib${ii}$_dlaruv( iseed, n, x ) integer(${ik}$), intent(in) :: n integer(${ik}$), intent(inout) :: iseed(4_${ik}$) real(dp), intent(out) :: x(n) end subroutine stdlib${ii}$_dlaruv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laruv( iseed, n, x ) integer(${ik}$), intent(in) :: n integer(${ik}$), intent(inout) :: iseed(4_${ik}$) real(${rk}$), intent(out) :: x(n) end subroutine stdlib${ii}$_${ri}$laruv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slacpy( uplo, m, n, a, lda, b, ldb ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, ldb, m, n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: b(ldb,*) end subroutine stdlib${ii}$_slacpy pure module subroutine stdlib${ii}$_dlacpy( uplo, m, n, a, lda, b, ldb ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, ldb, m, n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: b(ldb,*) end subroutine stdlib${ii}$_dlacpy #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lacpy( uplo, m, n, a, lda, b, ldb ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, ldb, m, n real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: b(ldb,*) end subroutine stdlib${ii}$_${ri}$lacpy #:endif #:endfor pure module subroutine stdlib${ii}$_clacpy( uplo, m, n, a, lda, b, ldb ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, ldb, m, n complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: b(ldb,*) end subroutine stdlib${ii}$_clacpy pure module subroutine stdlib${ii}$_zlacpy( uplo, m, n, a, lda, b, ldb ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, ldb, m, n complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: b(ldb,*) end subroutine stdlib${ii}$_zlacpy #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lacpy( uplo, m, n, a, lda, b, ldb ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, ldb, m, n complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(out) :: b(ldb,*) end subroutine stdlib${ii}$_${ci}$lacpy #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_clacp2( uplo, m, n, a, lda, b, ldb ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, ldb, m, n real(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: b(ldb,*) end subroutine stdlib${ii}$_clacp2 pure module subroutine stdlib${ii}$_zlacp2( uplo, m, n, a, lda, b, ldb ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, ldb, m, n real(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: b(ldb,*) end subroutine stdlib${ii}$_zlacp2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lacp2( uplo, m, n, a, lda, b, ldb ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, ldb, m, n real(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(out) :: b(ldb,*) end subroutine stdlib${ii}$_${ci}$lacp2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stfttp( transr, uplo, n, arf, ap, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(out) :: ap(0_${ik}$:*) real(sp), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_stfttp pure module subroutine stdlib${ii}$_dtfttp( transr, uplo, n, arf, ap, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: ap(0_${ik}$:*) real(dp), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_dtfttp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tfttp( transr, uplo, n, arf, ap, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(${rk}$), intent(out) :: ap(0_${ik}$:*) real(${rk}$), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_${ri}$tfttp #:endif #:endfor pure module subroutine stdlib${ii}$_ctfttp( transr, uplo, n, arf, ap, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(sp), intent(out) :: ap(0_${ik}$:*) complex(sp), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_ctfttp pure module subroutine stdlib${ii}$_ztfttp( transr, uplo, n, arf, ap, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(dp), intent(out) :: ap(0_${ik}$:*) complex(dp), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_ztfttp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tfttp( transr, uplo, n, arf, ap, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(${ck}$), intent(out) :: ap(0_${ik}$:*) complex(${ck}$), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_${ci}$tfttp #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stfttr( transr, uplo, n, arf, a, lda, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(sp), intent(out) :: a(0_${ik}$:lda-1,0_${ik}$:*) real(sp), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_stfttr pure module subroutine stdlib${ii}$_dtfttr( transr, uplo, n, arf, a, lda, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(dp), intent(out) :: a(0_${ik}$:lda-1,0_${ik}$:*) real(dp), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_dtfttr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tfttr( transr, uplo, n, arf, a, lda, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(${rk}$), intent(out) :: a(0_${ik}$:lda-1,0_${ik}$:*) real(${rk}$), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_${ri}$tfttr #:endif #:endfor pure module subroutine stdlib${ii}$_ctfttr( transr, uplo, n, arf, a, lda, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(sp), intent(out) :: a(0_${ik}$:lda-1,0_${ik}$:*) complex(sp), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_ctfttr pure module subroutine stdlib${ii}$_ztfttr( transr, uplo, n, arf, a, lda, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(dp), intent(out) :: a(0_${ik}$:lda-1,0_${ik}$:*) complex(dp), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_ztfttr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tfttr( transr, uplo, n, arf, a, lda, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(${ck}$), intent(out) :: a(0_${ik}$:lda-1,0_${ik}$:*) complex(${ck}$), intent(in) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_${ci}$tfttr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stpttf( transr, uplo, n, ap, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(in) :: ap(0_${ik}$:*) real(sp), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_stpttf pure module subroutine stdlib${ii}$_dtpttf( transr, uplo, n, ap, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(in) :: ap(0_${ik}$:*) real(dp), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_dtpttf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tpttf( transr, uplo, n, ap, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(${rk}$), intent(in) :: ap(0_${ik}$:*) real(${rk}$), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_${ri}$tpttf #:endif #:endfor pure module subroutine stdlib${ii}$_ctpttf( transr, uplo, n, ap, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(sp), intent(in) :: ap(0_${ik}$:*) complex(sp), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_ctpttf pure module subroutine stdlib${ii}$_ztpttf( transr, uplo, n, ap, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(dp), intent(in) :: ap(0_${ik}$:*) complex(dp), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_ztpttf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tpttf( transr, uplo, n, ap, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n complex(${ck}$), intent(in) :: ap(0_${ik}$:*) complex(${ck}$), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_${ci}$tpttf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stpttr( uplo, n, ap, a, lda, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(sp), intent(out) :: a(lda,*) real(sp), intent(in) :: ap(*) end subroutine stdlib${ii}$_stpttr pure module subroutine stdlib${ii}$_dtpttr( uplo, n, ap, a, lda, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(dp), intent(out) :: a(lda,*) real(dp), intent(in) :: ap(*) end subroutine stdlib${ii}$_dtpttr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tpttr( uplo, n, ap, a, lda, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(${rk}$), intent(out) :: a(lda,*) real(${rk}$), intent(in) :: ap(*) end subroutine stdlib${ii}$_${ri}$tpttr #:endif #:endfor pure module subroutine stdlib${ii}$_ctpttr( uplo, n, ap, a, lda, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(sp), intent(out) :: a(lda,*) complex(sp), intent(in) :: ap(*) end subroutine stdlib${ii}$_ctpttr pure module subroutine stdlib${ii}$_ztpttr( uplo, n, ap, a, lda, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(dp), intent(out) :: a(lda,*) complex(dp), intent(in) :: ap(*) end subroutine stdlib${ii}$_ztpttr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tpttr( uplo, n, ap, a, lda, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(${ck}$), intent(out) :: a(lda,*) complex(${ck}$), intent(in) :: ap(*) end subroutine stdlib${ii}$_${ci}$tpttr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_strttf( transr, uplo, n, a, lda, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(sp), intent(in) :: a(0_${ik}$:lda-1,0_${ik}$:*) real(sp), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_strttf pure module subroutine stdlib${ii}$_dtrttf( transr, uplo, n, a, lda, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(dp), intent(in) :: a(0_${ik}$:lda-1,0_${ik}$:*) real(dp), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_dtrttf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$trttf( transr, uplo, n, a, lda, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(${rk}$), intent(in) :: a(0_${ik}$:lda-1,0_${ik}$:*) real(${rk}$), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_${ri}$trttf #:endif #:endfor pure module subroutine stdlib${ii}$_ctrttf( transr, uplo, n, a, lda, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(sp), intent(in) :: a(0_${ik}$:lda-1,0_${ik}$:*) complex(sp), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_ctrttf pure module subroutine stdlib${ii}$_ztrttf( transr, uplo, n, a, lda, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(dp), intent(in) :: a(0_${ik}$:lda-1,0_${ik}$:*) complex(dp), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_ztrttf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$trttf( transr, uplo, n, a, lda, arf, info ) character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(${ck}$), intent(in) :: a(0_${ik}$:lda-1,0_${ik}$:*) complex(${ck}$), intent(out) :: arf(0_${ik}$:*) end subroutine stdlib${ii}$_${ci}$trttf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_strttp( uplo, n, a, lda, ap, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: ap(*) end subroutine stdlib${ii}$_strttp pure module subroutine stdlib${ii}$_dtrttp( uplo, n, a, lda, ap, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: ap(*) end subroutine stdlib${ii}$_dtrttp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$trttp( uplo, n, a, lda, ap, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: ap(*) end subroutine stdlib${ii}$_${ri}$trttp #:endif #:endfor pure module subroutine stdlib${ii}$_ctrttp( uplo, n, a, lda, ap, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: ap(*) end subroutine stdlib${ii}$_ctrttp pure module subroutine stdlib${ii}$_ztrttp( uplo, n, a, lda, ap, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: ap(*) end subroutine stdlib${ii}$_ztrttp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$trttp( uplo, n, a, lda, ap, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n, lda complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(out) :: ap(*) end subroutine stdlib${ii}$_${ci}$trttp #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_dlag2s( m, n, a, lda, sa, ldsa, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldsa, m, n real(sp), intent(out) :: sa(ldsa,*) real(dp), intent(in) :: a(lda,*) end subroutine stdlib${ii}$_dlag2s #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lag2s( m, n, a, lda, sa, ldsa, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldsa, m, n real(dp), intent(out) :: sa(ldsa,*) real(${rk}$), intent(in) :: a(lda,*) end subroutine stdlib${ii}$_${ri}$lag2s #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_dlat2s( uplo, n, a, lda, sa, ldsa, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldsa, n real(sp), intent(out) :: sa(ldsa,*) real(dp), intent(in) :: a(lda,*) end subroutine stdlib${ii}$_dlat2s #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lat2s( uplo, n, a, lda, sa, ldsa, info ) character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldsa, n real(dp), intent(out) :: sa(ldsa,*) real(${rk}$), intent(in) :: a(lda,*) end subroutine stdlib${ii}$_${ri}$lat2s #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slag2d( m, n, sa, ldsa, a, lda, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldsa, m, n real(sp), intent(in) :: sa(ldsa,*) real(dp), intent(out) :: a(lda,*) end subroutine stdlib${ii}$_slag2d #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure logical(lk) module function stdlib${ii}$_sisnan( sin ) real(sp), intent(in) :: sin end function stdlib${ii}$_sisnan pure logical(lk) module function stdlib${ii}$_disnan( din ) real(dp), intent(in) :: din end function stdlib${ii}$_disnan #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure logical(lk) module function stdlib${ii}$_${ri}$isnan( din ) real(${rk}$), intent(in) :: din end function stdlib${ii}$_${ri}$isnan #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure logical(lk) module function stdlib${ii}$_slaisnan( sin1, sin2 ) real(sp), intent(in) :: sin1, sin2 end function stdlib${ii}$_slaisnan pure logical(lk) module function stdlib${ii}$_dlaisnan( din1, din2 ) real(dp), intent(in) :: din1, din2 end function stdlib${ii}$_dlaisnan #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure logical(lk) module function stdlib${ii}$_${ri}$laisnan( din1, din2 ) real(${rk}$), intent(in) :: din1, din2 end function stdlib${ii}$_${ri}$laisnan #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sladiv( a, b, c, d, p, q ) real(sp), intent(in) :: a, b, c, d real(sp), intent(out) :: p, q end subroutine stdlib${ii}$_sladiv pure module subroutine stdlib${ii}$_dladiv( a, b, c, d, p, q ) real(dp), intent(in) :: a, b, c, d real(dp), intent(out) :: p, q end subroutine stdlib${ii}$_dladiv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ladiv( a, b, c, d, p, q ) real(${rk}$), intent(in) :: a, b, c, d real(${rk}$), intent(out) :: p, q end subroutine stdlib${ii}$_${ri}$ladiv #:endif #:endfor pure complex(sp) module function stdlib${ii}$_cladiv( x, y ) complex(sp), intent(in) :: x, y end function stdlib${ii}$_cladiv pure complex(dp) module function stdlib${ii}$_zladiv( x, y ) complex(dp), intent(in) :: x, y end function stdlib${ii}$_zladiv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure complex(${ck}$) module function stdlib${ii}$_${ci}$ladiv( x, y ) complex(${ck}$), intent(in) :: x, y end function stdlib${ii}$_${ci}$ladiv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(sp) module function stdlib${ii}$_slapy2( x, y ) real(sp), intent(in) :: x, y end function stdlib${ii}$_slapy2 pure real(dp) module function stdlib${ii}$_dlapy2( x, y ) real(dp), intent(in) :: x, y end function stdlib${ii}$_dlapy2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$lapy2( x, y ) real(${rk}$), intent(in) :: x, y end function stdlib${ii}$_${ri}$lapy2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(sp) module function stdlib${ii}$_slapy3( x, y, z ) real(sp), intent(in) :: x, y, z end function stdlib${ii}$_slapy3 pure real(dp) module function stdlib${ii}$_dlapy3( x, y, z ) real(dp), intent(in) :: x, y, z end function stdlib${ii}$_dlapy3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$lapy3( x, y, z ) real(${rk}$), intent(in) :: x, y, z end function stdlib${ii}$_${ri}$lapy3 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_clacgv( n, x, incx ) integer(${ik}$), intent(in) :: incx, n complex(sp), intent(inout) :: x(*) end subroutine stdlib${ii}$_clacgv pure module subroutine stdlib${ii}$_zlacgv( n, x, incx ) integer(${ik}$), intent(in) :: incx, n complex(dp), intent(inout) :: x(*) end subroutine stdlib${ii}$_zlacgv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lacgv( n, x, incx ) integer(${ik}$), intent(in) :: incx, n complex(${ck}$), intent(inout) :: x(*) end subroutine stdlib${ii}$_${ci}$lacgv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slasrt( id, n, d, info ) character, intent(in) :: id integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: d(*) end subroutine stdlib${ii}$_slasrt pure module subroutine stdlib${ii}$_dlasrt( id, n, d, info ) character, intent(in) :: id integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: d(*) end subroutine stdlib${ii}$_dlasrt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasrt( id, n, d, info ) character, intent(in) :: id integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(${rk}$), intent(inout) :: d(*) end subroutine stdlib${ii}$_${ri}$lasrt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slassq( n, x, incx, scl, sumsq ) integer(${ik}$), intent(in) :: incx, n real(sp), intent(inout) :: scl, sumsq real(sp), intent(in) :: x(*) end subroutine stdlib${ii}$_slassq pure module subroutine stdlib${ii}$_dlassq( n, x, incx, scl, sumsq ) integer(${ik}$), intent(in) :: incx, n real(dp), intent(inout) :: scl, sumsq real(dp), intent(in) :: x(*) end subroutine stdlib${ii}$_dlassq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lassq( n, x, incx, scl, sumsq ) integer(${ik}$), intent(in) :: incx, n real(${rk}$), intent(inout) :: scl, sumsq real(${rk}$), intent(in) :: x(*) end subroutine stdlib${ii}$_${ri}$lassq #:endif #:endfor pure module subroutine stdlib${ii}$_classq( n, x, incx, scl, sumsq ) integer(${ik}$), intent(in) :: incx, n real(sp), intent(inout) :: scl, sumsq complex(sp), intent(in) :: x(*) end subroutine stdlib${ii}$_classq pure module subroutine stdlib${ii}$_zlassq( n, x, incx, scl, sumsq ) integer(${ik}$), intent(in) :: incx, n real(dp), intent(inout) :: scl, sumsq complex(dp), intent(in) :: x(*) end subroutine stdlib${ii}$_zlassq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lassq( n, x, incx, scl, sumsq ) integer(${ik}$), intent(in) :: incx, n real(${ck}$), intent(inout) :: scl, sumsq complex(${ck}$), intent(in) :: x(*) end subroutine stdlib${ii}$_${ci}$lassq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_srscl( n, sa, sx, incx ) integer(${ik}$), intent(in) :: incx, n real(sp), intent(in) :: sa real(sp), intent(inout) :: sx(*) end subroutine stdlib${ii}$_srscl pure module subroutine stdlib${ii}$_drscl( n, sa, sx, incx ) integer(${ik}$), intent(in) :: incx, n real(dp), intent(in) :: sa real(dp), intent(inout) :: sx(*) end subroutine stdlib${ii}$_drscl #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$rscl( n, sa, sx, incx ) integer(${ik}$), intent(in) :: incx, n real(${rk}$), intent(in) :: sa real(${rk}$), intent(inout) :: sx(*) end subroutine stdlib${ii}$_${ri}$rscl #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_csrscl( n, sa, sx, incx ) integer(${ik}$), intent(in) :: incx, n real(sp), intent(in) :: sa complex(sp), intent(inout) :: sx(*) end subroutine stdlib${ii}$_csrscl #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_zdrscl( n, sa, sx, incx ) integer(${ik}$), intent(in) :: incx, n real(dp), intent(in) :: sa complex(dp), intent(inout) :: sx(*) end subroutine stdlib${ii}$_zdrscl #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$drscl( n, sa, sx, incx ) integer(${ik}$), intent(in) :: incx, n real(${ck}$), intent(in) :: sa complex(${ck}$), intent(inout) :: sx(*) end subroutine stdlib${ii}$_${ci}$drscl #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, lda, m, n real(sp), intent(in) :: cfrom, cto real(sp), intent(inout) :: a(lda,*) end subroutine stdlib${ii}$_slascl pure module subroutine stdlib${ii}$_dlascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, lda, m, n real(dp), intent(in) :: cfrom, cto real(dp), intent(inout) :: a(lda,*) end subroutine stdlib${ii}$_dlascl #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, lda, m, n real(${rk}$), intent(in) :: cfrom, cto real(${rk}$), intent(inout) :: a(lda,*) end subroutine stdlib${ii}$_${ri}$lascl #:endif #:endfor pure module subroutine stdlib${ii}$_clascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, lda, m, n real(sp), intent(in) :: cfrom, cto complex(sp), intent(inout) :: a(lda,*) end subroutine stdlib${ii}$_clascl pure module subroutine stdlib${ii}$_zlascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, lda, m, n real(dp), intent(in) :: cfrom, cto complex(dp), intent(inout) :: a(lda,*) end subroutine stdlib${ii}$_zlascl #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, lda, m, n real(${ck}$), intent(in) :: cfrom, cto complex(${ck}$), intent(inout) :: a(lda,*) end subroutine stdlib${ii}$_${ci}$lascl #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_sla_geamv( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n, trans real(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) end subroutine stdlib${ii}$_sla_geamv module subroutine stdlib${ii}$_dla_geamv ( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n, trans real(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) end subroutine stdlib${ii}$_dla_geamv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$la_geamv ( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n, trans real(${rk}$), intent(in) :: a(lda,*), x(*) real(${rk}$), intent(inout) :: y(*) end subroutine stdlib${ii}$_${ri}$la_geamv #:endif #:endfor module subroutine stdlib${ii}$_cla_geamv( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n integer(${ik}$), intent(in) :: trans complex(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) end subroutine stdlib${ii}$_cla_geamv module subroutine stdlib${ii}$_zla_geamv( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n integer(${ik}$), intent(in) :: trans complex(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) end subroutine stdlib${ii}$_zla_geamv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$la_geamv( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) real(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n integer(${ik}$), intent(in) :: trans complex(${ck}$), intent(in) :: a(lda,*), x(*) real(${ck}$), intent(inout) :: y(*) end subroutine stdlib${ii}$_${ci}$la_geamv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_sla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans real(sp), intent(in) :: ab(ldab,*), x(*) real(sp), intent(inout) :: y(*) end subroutine stdlib${ii}$_sla_gbamv module subroutine stdlib${ii}$_dla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans real(dp), intent(in) :: ab(ldab,*), x(*) real(dp), intent(inout) :: y(*) end subroutine stdlib${ii}$_dla_gbamv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$la_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans real(${rk}$), intent(in) :: ab(ldab,*), x(*) real(${rk}$), intent(inout) :: y(*) end subroutine stdlib${ii}$_${ri}$la_gbamv #:endif #:endfor module subroutine stdlib${ii}$_cla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans complex(sp), intent(in) :: ab(ldab,*), x(*) real(sp), intent(inout) :: y(*) end subroutine stdlib${ii}$_cla_gbamv module subroutine stdlib${ii}$_zla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans complex(dp), intent(in) :: ab(ldab,*), x(*) real(dp), intent(inout) :: y(*) end subroutine stdlib${ii}$_zla_gbamv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$la_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) real(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans complex(${ck}$), intent(in) :: ab(ldab,*), x(*) real(${ck}$), intent(inout) :: y(*) end subroutine stdlib${ii}$_${ci}$la_gbamv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_cla_heamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n, uplo complex(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) end subroutine stdlib${ii}$_cla_heamv module subroutine stdlib${ii}$_zla_heamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n, uplo complex(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) end subroutine stdlib${ii}$_zla_heamv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$la_heamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) real(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n, uplo complex(${ck}$), intent(in) :: a(lda,*), x(*) real(${ck}$), intent(inout) :: y(*) end subroutine stdlib${ii}$_${ci}$la_heamv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sla_wwaddw( n, x, y, w ) integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: x(*), y(*) real(sp), intent(in) :: w(*) end subroutine stdlib${ii}$_sla_wwaddw pure module subroutine stdlib${ii}$_dla_wwaddw( n, x, y, w ) integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: x(*), y(*) real(dp), intent(in) :: w(*) end subroutine stdlib${ii}$_dla_wwaddw #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$la_wwaddw( n, x, y, w ) integer(${ik}$), intent(in) :: n real(${rk}$), intent(inout) :: x(*), y(*) real(${rk}$), intent(in) :: w(*) end subroutine stdlib${ii}$_${ri}$la_wwaddw #:endif #:endfor pure module subroutine stdlib${ii}$_cla_wwaddw( n, x, y, w ) integer(${ik}$), intent(in) :: n complex(sp), intent(inout) :: x(*), y(*) complex(sp), intent(in) :: w(*) end subroutine stdlib${ii}$_cla_wwaddw pure module subroutine stdlib${ii}$_zla_wwaddw( n, x, y, w ) integer(${ik}$), intent(in) :: n complex(dp), intent(inout) :: x(*), y(*) complex(dp), intent(in) :: w(*) end subroutine stdlib${ii}$_zla_wwaddw #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$la_wwaddw( n, x, y, w ) integer(${ik}$), intent(in) :: n complex(${ck}$), intent(inout) :: x(*), y(*) complex(${ck}$), intent(in) :: w(*) end subroutine stdlib${ii}$_${ci}$la_wwaddw #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cspmv( uplo, n, alpha, ap, x, incx, beta, y, incy ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, n complex(sp), intent(in) :: alpha, beta complex(sp), intent(in) :: ap(*), x(*) complex(sp), intent(inout) :: y(*) end subroutine stdlib${ii}$_cspmv pure module subroutine stdlib${ii}$_zspmv( uplo, n, alpha, ap, x, incx, beta, y, incy ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, n complex(dp), intent(in) :: alpha, beta complex(dp), intent(in) :: ap(*), x(*) complex(dp), intent(inout) :: y(*) end subroutine stdlib${ii}$_zspmv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$spmv( uplo, n, alpha, ap, x, incx, beta, y, incy ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, n complex(${ck}$), intent(in) :: alpha, beta complex(${ck}$), intent(in) :: ap(*), x(*) complex(${ck}$), intent(inout) :: y(*) end subroutine stdlib${ii}$_${ci}$spmv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cspr( uplo, n, alpha, x, incx, ap ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, n complex(sp), intent(in) :: alpha complex(sp), intent(inout) :: ap(*) complex(sp), intent(in) :: x(*) end subroutine stdlib${ii}$_cspr pure module subroutine stdlib${ii}$_zspr( uplo, n, alpha, x, incx, ap ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, n complex(dp), intent(in) :: alpha complex(dp), intent(inout) :: ap(*) complex(dp), intent(in) :: x(*) end subroutine stdlib${ii}$_zspr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$spr( uplo, n, alpha, x, incx, ap ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, n complex(${ck}$), intent(in) :: alpha complex(${ck}$), intent(inout) :: ap(*) complex(${ck}$), intent(in) :: x(*) end subroutine stdlib${ii}$_${ci}$spr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_csymv( uplo, n, alpha, a, lda, x, incx, beta, y, incy ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, lda, n complex(sp), intent(in) :: alpha, beta complex(sp), intent(in) :: a(lda,*), x(*) complex(sp), intent(inout) :: y(*) end subroutine stdlib${ii}$_csymv pure module subroutine stdlib${ii}$_zsymv( uplo, n, alpha, a, lda, x, incx, beta, y, incy ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, lda, n complex(dp), intent(in) :: alpha, beta complex(dp), intent(in) :: a(lda,*), x(*) complex(dp), intent(inout) :: y(*) end subroutine stdlib${ii}$_zsymv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$symv( uplo, n, alpha, a, lda, x, incx, beta, y, incy ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, lda, n complex(${ck}$), intent(in) :: alpha, beta complex(${ck}$), intent(in) :: a(lda,*), x(*) complex(${ck}$), intent(inout) :: y(*) end subroutine stdlib${ii}$_${ci}$symv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_csyr( uplo, n, alpha, x, incx, a, lda ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, lda, n complex(sp), intent(in) :: alpha complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: x(*) end subroutine stdlib${ii}$_csyr pure module subroutine stdlib${ii}$_zsyr( uplo, n, alpha, x, incx, a, lda ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, lda, n complex(dp), intent(in) :: alpha complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: x(*) end subroutine stdlib${ii}$_zsyr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$syr( uplo, n, alpha, x, incx, a, lda ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, lda, n complex(${ck}$), intent(in) :: alpha complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: x(*) end subroutine stdlib${ii}$_${ci}$syr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slagtm( trans, n, nrhs, alpha, dl, d, du, x, ldx, beta,b, ldb ) character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs real(sp), intent(in) :: alpha, beta real(sp), intent(inout) :: b(ldb,*) real(sp), intent(in) :: d(*), dl(*), du(*), x(ldx,*) end subroutine stdlib${ii}$_slagtm pure module subroutine stdlib${ii}$_dlagtm( trans, n, nrhs, alpha, dl, d, du, x, ldx, beta,b, ldb ) character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs real(dp), intent(in) :: alpha, beta real(dp), intent(inout) :: b(ldb,*) real(dp), intent(in) :: d(*), dl(*), du(*), x(ldx,*) end subroutine stdlib${ii}$_dlagtm #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lagtm( trans, n, nrhs, alpha, dl, d, du, x, ldx, beta,b, ldb ) character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs real(${rk}$), intent(in) :: alpha, beta real(${rk}$), intent(inout) :: b(ldb,*) real(${rk}$), intent(in) :: d(*), dl(*), du(*), x(ldx,*) end subroutine stdlib${ii}$_${ri}$lagtm #:endif #:endfor pure module subroutine stdlib${ii}$_clagtm( trans, n, nrhs, alpha, dl, d, du, x, ldx, beta,b, ldb ) character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs real(sp), intent(in) :: alpha, beta complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(in) :: d(*), dl(*), du(*), x(ldx,*) end subroutine stdlib${ii}$_clagtm pure module subroutine stdlib${ii}$_zlagtm( trans, n, nrhs, alpha, dl, d, du, x, ldx, beta,b, ldb ) character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs real(dp), intent(in) :: alpha, beta complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(in) :: d(*), dl(*), du(*), x(ldx,*) end subroutine stdlib${ii}$_zlagtm #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lagtm( trans, n, nrhs, alpha, dl, d, du, x, ldx, beta,b, ldb ) character, intent(in) :: trans integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs real(${ck}$), intent(in) :: alpha, beta complex(${ck}$), intent(inout) :: b(ldb,*) complex(${ck}$), intent(in) :: d(*), dl(*), du(*), x(ldx,*) end subroutine stdlib${ii}$_${ci}$lagtm #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_clacrm( m, n, a, lda, b, ldb, c, ldc, rwork ) integer(${ik}$), intent(in) :: lda, ldb, ldc, m, n real(sp), intent(in) :: b(ldb,*) real(sp), intent(out) :: rwork(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: c(ldc,*) end subroutine stdlib${ii}$_clacrm pure module subroutine stdlib${ii}$_zlacrm( m, n, a, lda, b, ldb, c, ldc, rwork ) integer(${ik}$), intent(in) :: lda, ldb, ldc, m, n real(dp), intent(in) :: b(ldb,*) real(dp), intent(out) :: rwork(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: c(ldc,*) end subroutine stdlib${ii}$_zlacrm #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lacrm( m, n, a, lda, b, ldb, c, ldc, rwork ) integer(${ik}$), intent(in) :: lda, ldb, ldc, m, n real(${ck}$), intent(in) :: b(ldb,*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(out) :: c(ldc,*) end subroutine stdlib${ii}$_${ci}$lacrm #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_clarcm( m, n, a, lda, b, ldb, c, ldc, rwork ) integer(${ik}$), intent(in) :: lda, ldb, ldc, m, n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: rwork(*) complex(sp), intent(in) :: b(ldb,*) complex(sp), intent(out) :: c(ldc,*) end subroutine stdlib${ii}$_clarcm pure module subroutine stdlib${ii}$_zlarcm( m, n, a, lda, b, ldb, c, ldc, rwork ) integer(${ik}$), intent(in) :: lda, ldb, ldc, m, n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: rwork(*) complex(dp), intent(in) :: b(ldb,*) complex(dp), intent(out) :: c(ldc,*) end subroutine stdlib${ii}$_zlarcm #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larcm( m, n, a, lda, b, ldb, c, ldc, rwork ) integer(${ik}$), intent(in) :: lda, ldb, ldc, m, n real(${ck}$), intent(in) :: a(lda,*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(in) :: b(ldb,*) complex(${ck}$), intent(out) :: c(ldc,*) end subroutine stdlib${ii}$_${ci}$larcm #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_chfrk( transr, uplo, trans, n, k, alpha, a, lda, beta,c ) real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: k, lda, n character, intent(in) :: trans, transr, uplo complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: c(*) end subroutine stdlib${ii}$_chfrk pure module subroutine stdlib${ii}$_zhfrk( transr, uplo, trans, n, k, alpha, a, lda, beta,c ) real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: k, lda, n character, intent(in) :: trans, transr, uplo complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: c(*) end subroutine stdlib${ii}$_zhfrk #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hfrk( transr, uplo, trans, n, k, alpha, a, lda, beta,c ) real(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: k, lda, n character, intent(in) :: trans, transr, uplo complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(inout) :: c(*) end subroutine stdlib${ii}$_${ci}$hfrk #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stfsm( transr, side, uplo, trans, diag, m, n, alpha, a,b, ldb ) character, intent(in) :: transr, diag, side, trans, uplo integer(${ik}$), intent(in) :: ldb, m, n real(sp), intent(in) :: alpha real(sp), intent(in) :: a(0_${ik}$:*) real(sp), intent(inout) :: b(0_${ik}$:ldb-1,0_${ik}$:*) end subroutine stdlib${ii}$_stfsm pure module subroutine stdlib${ii}$_dtfsm( transr, side, uplo, trans, diag, m, n, alpha, a,b, ldb ) character, intent(in) :: transr, diag, side, trans, uplo integer(${ik}$), intent(in) :: ldb, m, n real(dp), intent(in) :: alpha real(dp), intent(in) :: a(0_${ik}$:*) real(dp), intent(inout) :: b(0_${ik}$:ldb-1,0_${ik}$:*) end subroutine stdlib${ii}$_dtfsm #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tfsm( transr, side, uplo, trans, diag, m, n, alpha, a,b, ldb ) character, intent(in) :: transr, diag, side, trans, uplo integer(${ik}$), intent(in) :: ldb, m, n real(${rk}$), intent(in) :: alpha real(${rk}$), intent(in) :: a(0_${ik}$:*) real(${rk}$), intent(inout) :: b(0_${ik}$:ldb-1,0_${ik}$:*) end subroutine stdlib${ii}$_${ri}$tfsm #:endif #:endfor pure module subroutine stdlib${ii}$_ctfsm( transr, side, uplo, trans, diag, m, n, alpha, a,b, ldb ) character, intent(in) :: transr, diag, side, trans, uplo integer(${ik}$), intent(in) :: ldb, m, n complex(sp), intent(in) :: alpha complex(sp), intent(in) :: a(0_${ik}$:*) complex(sp), intent(inout) :: b(0_${ik}$:ldb-1,0_${ik}$:*) end subroutine stdlib${ii}$_ctfsm pure module subroutine stdlib${ii}$_ztfsm( transr, side, uplo, trans, diag, m, n, alpha, a,b, ldb ) character, intent(in) :: transr, diag, side, trans, uplo integer(${ik}$), intent(in) :: ldb, m, n complex(dp), intent(in) :: alpha complex(dp), intent(in) :: a(0_${ik}$:*) complex(dp), intent(inout) :: b(0_${ik}$:ldb-1,0_${ik}$:*) end subroutine stdlib${ii}$_ztfsm #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tfsm( transr, side, uplo, trans, diag, m, n, alpha, a,b, ldb ) character, intent(in) :: transr, diag, side, trans, uplo integer(${ik}$), intent(in) :: ldb, m, n complex(${ck}$), intent(in) :: alpha complex(${ck}$), intent(in) :: a(0_${ik}$:*) complex(${ck}$), intent(inout) :: b(0_${ik}$:ldb-1,0_${ik}$:*) end subroutine stdlib${ii}$_${ci}$tfsm #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_ssfrk( transr, uplo, trans, n, k, alpha, a, lda, beta,c ) real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: k, lda, n character, intent(in) :: trans, transr, uplo real(sp), intent(in) :: a(lda,*) real(sp), intent(inout) :: c(*) end subroutine stdlib${ii}$_ssfrk pure module subroutine stdlib${ii}$_dsfrk( transr, uplo, trans, n, k, alpha, a, lda, beta,c ) real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: k, lda, n character, intent(in) :: trans, transr, uplo real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: c(*) end subroutine stdlib${ii}$_dsfrk #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sfrk( transr, uplo, trans, n, k, alpha, a, lda, beta,c ) real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: k, lda, n character, intent(in) :: trans, transr, uplo real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(inout) :: c(*) end subroutine stdlib${ii}$_${ri}$sfrk #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_slange( norm, m, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) end function stdlib${ii}$_slange real(dp) module function stdlib${ii}$_dlange( norm, m, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) end function stdlib${ii}$_dlange #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lange( norm, m, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: work(*) end function stdlib${ii}$_${ri}$lange #:endif #:endfor real(sp) module function stdlib${ii}$_clange( norm, m, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) end function stdlib${ii}$_clange real(dp) module function stdlib${ii}$_zlange( norm, m, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) end function stdlib${ii}$_zlange #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lange( norm, m, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, m, n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: a(lda,*) end function stdlib${ii}$_${ci}$lange #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_slangb( norm, n, kl, ku, ab, ldab,work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: kl, ku, ldab, n real(sp), intent(in) :: ab(ldab,*) real(sp), intent(out) :: work(*) end function stdlib${ii}$_slangb real(dp) module function stdlib${ii}$_dlangb( norm, n, kl, ku, ab, ldab,work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: kl, ku, ldab, n real(dp), intent(in) :: ab(ldab,*) real(dp), intent(out) :: work(*) end function stdlib${ii}$_dlangb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$langb( norm, n, kl, ku, ab, ldab,work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: kl, ku, ldab, n real(${rk}$), intent(in) :: ab(ldab,*) real(${rk}$), intent(out) :: work(*) end function stdlib${ii}$_${ri}$langb #:endif #:endfor real(sp) module function stdlib${ii}$_clangb( norm, n, kl, ku, ab, ldab,work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: kl, ku, ldab, n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ab(ldab,*) end function stdlib${ii}$_clangb real(dp) module function stdlib${ii}$_zlangb( norm, n, kl, ku, ab, ldab,work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: kl, ku, ldab, n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ab(ldab,*) end function stdlib${ii}$_zlangb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$langb( norm, n, kl, ku, ab, ldab,work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: kl, ku, ldab, n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: ab(ldab,*) end function stdlib${ii}$_${ci}$langb #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(sp) module function stdlib${ii}$_slangt( norm, n, dl, d, du ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(sp), intent(in) :: d(*), dl(*), du(*) end function stdlib${ii}$_slangt pure real(dp) module function stdlib${ii}$_dlangt( norm, n, dl, d, du ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(dp), intent(in) :: d(*), dl(*), du(*) end function stdlib${ii}$_dlangt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$langt( norm, n, dl, d, du ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(${rk}$), intent(in) :: d(*), dl(*), du(*) end function stdlib${ii}$_${ri}$langt #:endif #:endfor pure real(sp) module function stdlib${ii}$_clangt( norm, n, dl, d, du ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n complex(sp), intent(in) :: d(*), dl(*), du(*) end function stdlib${ii}$_clangt pure real(dp) module function stdlib${ii}$_zlangt( norm, n, dl, d, du ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n complex(dp), intent(in) :: d(*), dl(*), du(*) end function stdlib${ii}$_zlangt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure real(${ck}$) module function stdlib${ii}$_${ci}$langt( norm, n, dl, d, du ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n complex(${ck}$), intent(in) :: d(*), dl(*), du(*) end function stdlib${ii}$_${ci}$langt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_slanhs( norm, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) end function stdlib${ii}$_slanhs real(dp) module function stdlib${ii}$_dlanhs( norm, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) end function stdlib${ii}$_dlanhs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lanhs( norm, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: work(*) end function stdlib${ii}$_${ri}$lanhs #:endif #:endfor real(sp) module function stdlib${ii}$_clanhs( norm, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) end function stdlib${ii}$_clanhs real(dp) module function stdlib${ii}$_zlanhs( norm, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) end function stdlib${ii}$_zlanhs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lanhs( norm, n, a, lda, work ) character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: a(lda,*) end function stdlib${ii}$_${ci}$lanhs #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_clanhf( norm, transr, uplo, n, a, work ) character, intent(in) :: norm, transr, uplo integer(${ik}$), intent(in) :: n real(sp), intent(out) :: work(0_${ik}$:*) complex(sp), intent(in) :: a(0_${ik}$:*) end function stdlib${ii}$_clanhf real(dp) module function stdlib${ii}$_zlanhf( norm, transr, uplo, n, a, work ) character, intent(in) :: norm, transr, uplo integer(${ik}$), intent(in) :: n real(dp), intent(out) :: work(0_${ik}$:*) complex(dp), intent(in) :: a(0_${ik}$:*) end function stdlib${ii}$_zlanhf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lanhf( norm, transr, uplo, n, a, work ) character, intent(in) :: norm, transr, uplo integer(${ik}$), intent(in) :: n real(${ck}$), intent(out) :: work(0_${ik}$:*) complex(${ck}$), intent(in) :: a(0_${ik}$:*) end function stdlib${ii}$_${ci}$lanhf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_slansf( norm, transr, uplo, n, a, work ) character, intent(in) :: norm, transr, uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: a(0_${ik}$:*) real(sp), intent(out) :: work(0_${ik}$:*) end function stdlib${ii}$_slansf real(dp) module function stdlib${ii}$_dlansf( norm, transr, uplo, n, a, work ) character, intent(in) :: norm, transr, uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: a(0_${ik}$:*) real(dp), intent(out) :: work(0_${ik}$:*) end function stdlib${ii}$_dlansf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lansf( norm, transr, uplo, n, a, work ) character, intent(in) :: norm, transr, uplo integer(${ik}$), intent(in) :: n real(${rk}$), intent(in) :: a(0_${ik}$:*) real(${rk}$), intent(out) :: work(0_${ik}$:*) end function stdlib${ii}$_${ri}$lansf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_clanhp( norm, uplo, n, ap, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ap(*) end function stdlib${ii}$_clanhp real(dp) module function stdlib${ii}$_zlanhp( norm, uplo, n, ap, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ap(*) end function stdlib${ii}$_zlanhp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lanhp( norm, uplo, n, ap, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: ap(*) end function stdlib${ii}$_${ci}$lanhp #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_slansp( norm, uplo, n, ap, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: ap(*) real(sp), intent(out) :: work(*) end function stdlib${ii}$_slansp real(dp) module function stdlib${ii}$_dlansp( norm, uplo, n, ap, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: ap(*) real(dp), intent(out) :: work(*) end function stdlib${ii}$_dlansp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lansp( norm, uplo, n, ap, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: n real(${rk}$), intent(in) :: ap(*) real(${rk}$), intent(out) :: work(*) end function stdlib${ii}$_${ri}$lansp #:endif #:endfor real(sp) module function stdlib${ii}$_clansp( norm, uplo, n, ap, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ap(*) end function stdlib${ii}$_clansp real(dp) module function stdlib${ii}$_zlansp( norm, uplo, n, ap, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ap(*) end function stdlib${ii}$_zlansp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lansp( norm, uplo, n, ap, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: ap(*) end function stdlib${ii}$_${ci}$lansp #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_clanhb( norm, uplo, n, k, ab, ldab,work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ab(ldab,*) end function stdlib${ii}$_clanhb real(dp) module function stdlib${ii}$_zlanhb( norm, uplo, n, k, ab, ldab,work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ab(ldab,*) end function stdlib${ii}$_zlanhb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lanhb( norm, uplo, n, k, ab, ldab,work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: ab(ldab,*) end function stdlib${ii}$_${ci}$lanhb #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_slansb( norm, uplo, n, k, ab, ldab,work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(sp), intent(in) :: ab(ldab,*) real(sp), intent(out) :: work(*) end function stdlib${ii}$_slansb real(dp) module function stdlib${ii}$_dlansb( norm, uplo, n, k, ab, ldab,work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(dp), intent(in) :: ab(ldab,*) real(dp), intent(out) :: work(*) end function stdlib${ii}$_dlansb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lansb( norm, uplo, n, k, ab, ldab,work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(${rk}$), intent(in) :: ab(ldab,*) real(${rk}$), intent(out) :: work(*) end function stdlib${ii}$_${ri}$lansb #:endif #:endfor real(sp) module function stdlib${ii}$_clansb( norm, uplo, n, k, ab, ldab,work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ab(ldab,*) end function stdlib${ii}$_clansb real(dp) module function stdlib${ii}$_zlansb( norm, uplo, n, k, ab, ldab,work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ab(ldab,*) end function stdlib${ii}$_zlansb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lansb( norm, uplo, n, k, ab, ldab,work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: ab(ldab,*) end function stdlib${ii}$_${ci}$lansb #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(sp) module function stdlib${ii}$_clanht( norm, n, d, e ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(sp), intent(in) :: d(*) complex(sp), intent(in) :: e(*) end function stdlib${ii}$_clanht pure real(dp) module function stdlib${ii}$_zlanht( norm, n, d, e ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(dp), intent(in) :: d(*) complex(dp), intent(in) :: e(*) end function stdlib${ii}$_zlanht #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure real(${ck}$) module function stdlib${ii}$_${ci}$lanht( norm, n, d, e ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(${ck}$), intent(in) :: d(*) complex(${ck}$), intent(in) :: e(*) end function stdlib${ii}$_${ci}$lanht #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(sp) module function stdlib${ii}$_slanst( norm, n, d, e ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(sp), intent(in) :: d(*), e(*) end function stdlib${ii}$_slanst pure real(dp) module function stdlib${ii}$_dlanst( norm, n, d, e ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(dp), intent(in) :: d(*), e(*) end function stdlib${ii}$_dlanst #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$lanst( norm, n, d, e ) character, intent(in) :: norm integer(${ik}$), intent(in) :: n real(${rk}$), intent(in) :: d(*), e(*) end function stdlib${ii}$_${ri}$lanst #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_slantr( norm, uplo, diag, m, n, a, lda,work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) end function stdlib${ii}$_slantr real(dp) module function stdlib${ii}$_dlantr( norm, uplo, diag, m, n, a, lda,work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) end function stdlib${ii}$_dlantr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lantr( norm, uplo, diag, m, n, a, lda,work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: work(*) end function stdlib${ii}$_${ri}$lantr #:endif #:endfor real(sp) module function stdlib${ii}$_clantr( norm, uplo, diag, m, n, a, lda,work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) end function stdlib${ii}$_clantr real(dp) module function stdlib${ii}$_zlantr( norm, uplo, diag, m, n, a, lda,work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) end function stdlib${ii}$_zlantr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lantr( norm, uplo, diag, m, n, a, lda,work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: a(lda,*) end function stdlib${ii}$_${ci}$lantr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_slantp( norm, uplo, diag, n, ap, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: ap(*) real(sp), intent(out) :: work(*) end function stdlib${ii}$_slantp real(dp) module function stdlib${ii}$_dlantp( norm, uplo, diag, n, ap, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: ap(*) real(dp), intent(out) :: work(*) end function stdlib${ii}$_dlantp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lantp( norm, uplo, diag, n, ap, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n real(${rk}$), intent(in) :: ap(*) real(${rk}$), intent(out) :: work(*) end function stdlib${ii}$_${ri}$lantp #:endif #:endfor real(sp) module function stdlib${ii}$_clantp( norm, uplo, diag, n, ap, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ap(*) end function stdlib${ii}$_clantp real(dp) module function stdlib${ii}$_zlantp( norm, uplo, diag, n, ap, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ap(*) end function stdlib${ii}$_zlantp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lantp( norm, uplo, diag, n, ap, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: ap(*) end function stdlib${ii}$_${ci}$lantp #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_slantb( norm, uplo, diag, n, k, ab,ldab, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(sp), intent(in) :: ab(ldab,*) real(sp), intent(out) :: work(*) end function stdlib${ii}$_slantb real(dp) module function stdlib${ii}$_dlantb( norm, uplo, diag, n, k, ab,ldab, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(dp), intent(in) :: ab(ldab,*) real(dp), intent(out) :: work(*) end function stdlib${ii}$_dlantb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lantb( norm, uplo, diag, n, k, ab,ldab, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(${rk}$), intent(in) :: ab(ldab,*) real(${rk}$), intent(out) :: work(*) end function stdlib${ii}$_${ri}$lantb #:endif #:endfor real(sp) module function stdlib${ii}$_clantb( norm, uplo, diag, n, k, ab,ldab, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ab(ldab,*) end function stdlib${ii}$_clantb real(dp) module function stdlib${ii}$_zlantb( norm, uplo, diag, n, k, ab,ldab, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ab(ldab,*) end function stdlib${ii}$_zlantb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lantb( norm, uplo, diag, n, k, ab,ldab, work ) character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: ab(ldab,*) end function stdlib${ii}$_${ci}$lantb #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_slansy( norm, uplo, n, a, lda, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) end function stdlib${ii}$_slansy real(dp) module function stdlib${ii}$_dlansy( norm, uplo, n, a, lda, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) end function stdlib${ii}$_dlansy #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lansy( norm, uplo, n, a, lda, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: work(*) end function stdlib${ii}$_${ri}$lansy #:endif #:endfor real(sp) module function stdlib${ii}$_clansy( norm, uplo, n, a, lda, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) end function stdlib${ii}$_clansy real(dp) module function stdlib${ii}$_zlansy( norm, uplo, n, a, lda, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) end function stdlib${ii}$_zlansy #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lansy( norm, uplo, n, a, lda, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: a(lda,*) end function stdlib${ii}$_${ci}$lansy #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_clanhe( norm, uplo, n, a, lda, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) end function stdlib${ii}$_clanhe real(dp) module function stdlib${ii}$_zlanhe( norm, uplo, n, a, lda, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) end function stdlib${ii}$_zlanhe #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lanhe( norm, uplo, n, a, lda, work ) character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: a(lda,*) end function stdlib${ii}$_${ci}$lanhe #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slartg( f, g, c, s, r ) real(sp), intent(out) :: c, r, s real(sp), intent(in) :: f, g end subroutine stdlib${ii}$_slartg pure module subroutine stdlib${ii}$_dlartg( f, g, c, s, r ) real(dp), intent(out) :: c, r, s real(dp), intent(in) :: f, g end subroutine stdlib${ii}$_dlartg #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lartg( f, g, c, s, r ) real(${rk}$), intent(out) :: c, r, s real(${rk}$), intent(in) :: f, g end subroutine stdlib${ii}$_${ri}$lartg #:endif #:endfor pure module subroutine stdlib${ii}$_clartg( f, g, c, s, r ) real(sp), intent(out) :: c complex(sp), intent(in) :: f, g complex(sp), intent(out) :: r, s end subroutine stdlib${ii}$_clartg pure module subroutine stdlib${ii}$_zlartg( f, g, c, s, r ) real(dp), intent(out) :: c complex(dp), intent(in) :: f, g complex(dp), intent(out) :: r, s end subroutine stdlib${ii}$_zlartg #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lartg( f, g, c, s, r ) real(${ck}$), intent(out) :: c complex(${ck}$), intent(in) :: f, g complex(${ck}$), intent(out) :: r, s end subroutine stdlib${ii}$_${ci}$lartg #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slartgp( f, g, cs, sn, r ) real(sp), intent(out) :: cs, r, sn real(sp), intent(in) :: f, g end subroutine stdlib${ii}$_slartgp pure module subroutine stdlib${ii}$_dlartgp( f, g, cs, sn, r ) real(dp), intent(out) :: cs, r, sn real(dp), intent(in) :: f, g end subroutine stdlib${ii}$_dlartgp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lartgp( f, g, cs, sn, r ) real(${rk}$), intent(out) :: cs, r, sn real(${rk}$), intent(in) :: f, g end subroutine stdlib${ii}$_${ri}$lartgp #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slasr( side, pivot, direct, m, n, c, s, a, lda ) character, intent(in) :: direct, pivot, side integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: c(*), s(*) end subroutine stdlib${ii}$_slasr pure module subroutine stdlib${ii}$_dlasr( side, pivot, direct, m, n, c, s, a, lda ) character, intent(in) :: direct, pivot, side integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: c(*), s(*) end subroutine stdlib${ii}$_dlasr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasr( side, pivot, direct, m, n, c, s, a, lda ) character, intent(in) :: direct, pivot, side integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: c(*), s(*) end subroutine stdlib${ii}$_${ri}$lasr #:endif #:endfor pure module subroutine stdlib${ii}$_clasr( side, pivot, direct, m, n, c, s, a, lda ) character, intent(in) :: direct, pivot, side integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(in) :: c(*), s(*) complex(sp), intent(inout) :: a(lda,*) end subroutine stdlib${ii}$_clasr pure module subroutine stdlib${ii}$_zlasr( side, pivot, direct, m, n, c, s, a, lda ) character, intent(in) :: direct, pivot, side integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(in) :: c(*), s(*) complex(dp), intent(inout) :: a(lda,*) end subroutine stdlib${ii}$_zlasr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lasr( side, pivot, direct, m, n, c, s, a, lda ) character, intent(in) :: direct, pivot, side integer(${ik}$), intent(in) :: lda, m, n real(${ck}$), intent(in) :: c(*), s(*) complex(${ck}$), intent(inout) :: a(lda,*) end subroutine stdlib${ii}$_${ci}$lasr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slargv( n, x, incx, y, incy, c, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(sp), intent(out) :: c(*) real(sp), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_slargv pure module subroutine stdlib${ii}$_dlargv( n, x, incx, y, incy, c, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(dp), intent(out) :: c(*) real(dp), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_dlargv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$largv( n, x, incx, y, incy, c, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(${rk}$), intent(out) :: c(*) real(${rk}$), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_${ri}$largv #:endif #:endfor pure module subroutine stdlib${ii}$_clargv( n, x, incx, y, incy, c, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(sp), intent(out) :: c(*) complex(sp), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_clargv pure module subroutine stdlib${ii}$_zlargv( n, x, incx, y, incy, c, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(dp), intent(out) :: c(*) complex(dp), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_zlargv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$largv( n, x, incx, y, incy, c, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(${ck}$), intent(out) :: c(*) complex(${ck}$), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_${ci}$largv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slartv( n, x, incx, y, incy, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(sp), intent(in) :: c(*), s(*) real(sp), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_slartv pure module subroutine stdlib${ii}$_dlartv( n, x, incx, y, incy, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(dp), intent(in) :: c(*), s(*) real(dp), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_dlartv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lartv( n, x, incx, y, incy, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(${rk}$), intent(in) :: c(*), s(*) real(${rk}$), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_${ri}$lartv #:endif #:endfor pure module subroutine stdlib${ii}$_clartv( n, x, incx, y, incy, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(sp), intent(in) :: c(*) complex(sp), intent(in) :: s(*) complex(sp), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_clartv pure module subroutine stdlib${ii}$_zlartv( n, x, incx, y, incy, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(dp), intent(in) :: c(*) complex(dp), intent(in) :: s(*) complex(dp), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_zlartv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lartv( n, x, incx, y, incy, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, incy, n real(${ck}$), intent(in) :: c(*) complex(${ck}$), intent(in) :: s(*) complex(${ck}$), intent(inout) :: x(*), y(*) end subroutine stdlib${ii}$_${ci}$lartv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slar2v( n, x, y, z, incx, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, n real(sp), intent(in) :: c(*), s(*) real(sp), intent(inout) :: x(*), y(*), z(*) end subroutine stdlib${ii}$_slar2v pure module subroutine stdlib${ii}$_dlar2v( n, x, y, z, incx, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, n real(dp), intent(in) :: c(*), s(*) real(dp), intent(inout) :: x(*), y(*), z(*) end subroutine stdlib${ii}$_dlar2v #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lar2v( n, x, y, z, incx, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, n real(${rk}$), intent(in) :: c(*), s(*) real(${rk}$), intent(inout) :: x(*), y(*), z(*) end subroutine stdlib${ii}$_${ri}$lar2v #:endif #:endfor pure module subroutine stdlib${ii}$_clar2v( n, x, y, z, incx, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, n real(sp), intent(in) :: c(*) complex(sp), intent(in) :: s(*) complex(sp), intent(inout) :: x(*), y(*), z(*) end subroutine stdlib${ii}$_clar2v pure module subroutine stdlib${ii}$_zlar2v( n, x, y, z, incx, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, n real(dp), intent(in) :: c(*) complex(dp), intent(in) :: s(*) complex(dp), intent(inout) :: x(*), y(*), z(*) end subroutine stdlib${ii}$_zlar2v #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lar2v( n, x, y, z, incx, c, s, incc ) integer(${ik}$), intent(in) :: incc, incx, n real(${ck}$), intent(in) :: c(*) complex(${ck}$), intent(in) :: s(*) complex(${ck}$), intent(inout) :: x(*), y(*), z(*) end subroutine stdlib${ii}$_${ci}$lar2v #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_clacrt( n, cx, incx, cy, incy, c, s ) integer(${ik}$), intent(in) :: incx, incy, n complex(sp), intent(in) :: c, s complex(sp), intent(inout) :: cx(*), cy(*) end subroutine stdlib${ii}$_clacrt pure module subroutine stdlib${ii}$_zlacrt( n, cx, incx, cy, incy, c, s ) integer(${ik}$), intent(in) :: incx, incy, n complex(dp), intent(in) :: c, s complex(dp), intent(inout) :: cx(*), cy(*) end subroutine stdlib${ii}$_zlacrt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lacrt( n, cx, incx, cy, incy, c, s ) integer(${ik}$), intent(in) :: incx, incy, n complex(${ck}$), intent(in) :: c, s complex(${ck}$), intent(inout) :: cx(*), cy(*) end subroutine stdlib${ii}$_${ci}$lacrt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slarf( side, m, n, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, ldc, m, n real(sp), intent(in) :: tau real(sp), intent(inout) :: c(ldc,*) real(sp), intent(in) :: v(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_slarf pure module subroutine stdlib${ii}$_dlarf( side, m, n, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, ldc, m, n real(dp), intent(in) :: tau real(dp), intent(inout) :: c(ldc,*) real(dp), intent(in) :: v(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dlarf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larf( side, m, n, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, ldc, m, n real(${rk}$), intent(in) :: tau real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(in) :: v(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$larf #:endif #:endfor pure module subroutine stdlib${ii}$_clarf( side, m, n, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, ldc, m, n complex(sp), intent(in) :: tau complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(in) :: v(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_clarf pure module subroutine stdlib${ii}$_zlarf( side, m, n, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, ldc, m, n complex(dp), intent(in) :: tau complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(in) :: v(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zlarf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larf( side, m, n, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, ldc, m, n complex(${ck}$), intent(in) :: tau complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(in) :: v(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$larf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slarfx( side, m, n, v, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n real(sp), intent(in) :: tau real(sp), intent(inout) :: c(ldc,*) real(sp), intent(in) :: v(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_slarfx pure module subroutine stdlib${ii}$_dlarfx( side, m, n, v, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n real(dp), intent(in) :: tau real(dp), intent(inout) :: c(ldc,*) real(dp), intent(in) :: v(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dlarfx #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larfx( side, m, n, v, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n real(${rk}$), intent(in) :: tau real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(in) :: v(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$larfx #:endif #:endfor pure module subroutine stdlib${ii}$_clarfx( side, m, n, v, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n complex(sp), intent(in) :: tau complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(in) :: v(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_clarfx pure module subroutine stdlib${ii}$_zlarfx( side, m, n, v, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n complex(dp), intent(in) :: tau complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(in) :: v(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zlarfx #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larfx( side, m, n, v, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n complex(${ck}$), intent(in) :: tau complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(in) :: v(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$larfx #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slarfy( uplo, n, v, incv, tau, c, ldc, work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n real(sp), intent(in) :: tau real(sp), intent(inout) :: c(ldc,*) real(sp), intent(in) :: v(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_slarfy pure module subroutine stdlib${ii}$_dlarfy( uplo, n, v, incv, tau, c, ldc, work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n real(dp), intent(in) :: tau real(dp), intent(inout) :: c(ldc,*) real(dp), intent(in) :: v(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dlarfy #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larfy( uplo, n, v, incv, tau, c, ldc, work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n real(${rk}$), intent(in) :: tau real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(in) :: v(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$larfy #:endif #:endfor pure module subroutine stdlib${ii}$_clarfy( uplo, n, v, incv, tau, c, ldc, work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n complex(sp), intent(in) :: tau complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(in) :: v(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_clarfy pure module subroutine stdlib${ii}$_zlarfy( uplo, n, v, incv, tau, c, ldc, work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n complex(dp), intent(in) :: tau complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(in) :: v(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zlarfy #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larfy( uplo, n, v, incv, tau, c, ldc, work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n complex(${ck}$), intent(in) :: tau complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(in) :: v(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$larfy #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n real(sp), intent(inout) :: c(ldc,*) real(sp), intent(in) :: t(ldt,*), v(ldv,*) real(sp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_slarfb pure module subroutine stdlib${ii}$_dlarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n real(dp), intent(inout) :: c(ldc,*) real(dp), intent(in) :: t(ldt,*), v(ldv,*) real(dp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_dlarfb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(in) :: t(ldt,*), v(ldv,*) real(${rk}$), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_${ri}$larfb #:endif #:endfor pure module subroutine stdlib${ii}$_clarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(in) :: t(ldt,*), v(ldv,*) complex(sp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_clarfb pure module subroutine stdlib${ii}$_zlarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(in) :: t(ldt,*), v(ldv,*) complex(dp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_zlarfb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(in) :: t(ldt,*), v(ldv,*) complex(${ck}$), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_${ci}$larfb #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slarfg( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n real(sp), intent(inout) :: alpha real(sp), intent(out) :: tau real(sp), intent(inout) :: x(*) end subroutine stdlib${ii}$_slarfg pure module subroutine stdlib${ii}$_dlarfg( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n real(dp), intent(inout) :: alpha real(dp), intent(out) :: tau real(dp), intent(inout) :: x(*) end subroutine stdlib${ii}$_dlarfg #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larfg( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n real(${rk}$), intent(inout) :: alpha real(${rk}$), intent(out) :: tau real(${rk}$), intent(inout) :: x(*) end subroutine stdlib${ii}$_${ri}$larfg #:endif #:endfor pure module subroutine stdlib${ii}$_clarfg( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n complex(sp), intent(inout) :: alpha complex(sp), intent(out) :: tau complex(sp), intent(inout) :: x(*) end subroutine stdlib${ii}$_clarfg pure module subroutine stdlib${ii}$_zlarfg( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n complex(dp), intent(inout) :: alpha complex(dp), intent(out) :: tau complex(dp), intent(inout) :: x(*) end subroutine stdlib${ii}$_zlarfg #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larfg( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n complex(${ck}$), intent(inout) :: alpha complex(${ck}$), intent(out) :: tau complex(${ck}$), intent(inout) :: x(*) end subroutine stdlib${ii}$_${ci}$larfg #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_slarfgp( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n real(sp), intent(inout) :: alpha real(sp), intent(out) :: tau real(sp), intent(inout) :: x(*) end subroutine stdlib${ii}$_slarfgp module subroutine stdlib${ii}$_dlarfgp( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n real(dp), intent(inout) :: alpha real(dp), intent(out) :: tau real(dp), intent(inout) :: x(*) end subroutine stdlib${ii}$_dlarfgp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$larfgp( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n real(${rk}$), intent(inout) :: alpha real(${rk}$), intent(out) :: tau real(${rk}$), intent(inout) :: x(*) end subroutine stdlib${ii}$_${ri}$larfgp #:endif #:endfor module subroutine stdlib${ii}$_clarfgp( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n complex(sp), intent(inout) :: alpha complex(sp), intent(out) :: tau complex(sp), intent(inout) :: x(*) end subroutine stdlib${ii}$_clarfgp module subroutine stdlib${ii}$_zlarfgp( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n complex(dp), intent(inout) :: alpha complex(dp), intent(out) :: tau complex(dp), intent(inout) :: x(*) end subroutine stdlib${ii}$_zlarfgp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$larfgp( n, alpha, x, incx, tau ) integer(${ik}$), intent(in) :: incx, n complex(${ck}$), intent(inout) :: alpha complex(${ck}$), intent(out) :: tau complex(${ck}$), intent(inout) :: x(*) end subroutine stdlib${ii}$_${ci}$larfgp #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slarft( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n real(sp), intent(out) :: t(ldt,*) real(sp), intent(in) :: tau(*), v(ldv,*) end subroutine stdlib${ii}$_slarft pure module subroutine stdlib${ii}$_dlarft( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n real(dp), intent(out) :: t(ldt,*) real(dp), intent(in) :: tau(*), v(ldv,*) end subroutine stdlib${ii}$_dlarft #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larft( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n real(${rk}$), intent(out) :: t(ldt,*) real(${rk}$), intent(in) :: tau(*), v(ldv,*) end subroutine stdlib${ii}$_${ri}$larft #:endif #:endfor pure module subroutine stdlib${ii}$_clarft( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n complex(sp), intent(out) :: t(ldt,*) complex(sp), intent(in) :: tau(*), v(ldv,*) end subroutine stdlib${ii}$_clarft pure module subroutine stdlib${ii}$_zlarft( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n complex(dp), intent(out) :: t(ldt,*) complex(dp), intent(in) :: tau(*), v(ldv,*) end subroutine stdlib${ii}$_zlarft #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larft( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n complex(${ck}$), intent(out) :: t(ldt,*) complex(${ck}$), intent(in) :: tau(*), v(ldv,*) end subroutine stdlib${ii}$_${ci}$larft #:endif #:endfor #:endfor end interface end module stdlib_lapack_base fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_auxiliary.fypp0000664000175000017500000012510415135654166025776 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_base) stdlib_lapack_auxiliary implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(sp) module function stdlib${ii}$_slamch( cmach ) !! SLAMCH determines single precision machine parameters. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: zero, one, eps ! Scalar Arguments character, intent(in) :: cmach ! ===================================================================== ! Local Scalars real(sp) :: sfmin, small, rmach ! Intrinsic Functions ! Executable Statements ! assume rounding, not chopping. always. if( stdlib_lsame( cmach, 'E' ) ) then rmach = eps else if( stdlib_lsame( cmach, 'S' ) ) then sfmin = tiny(zero) small = one / huge(zero) if( small>=sfmin ) then ! use small plus a bit, to avoid the possibility of rounding ! causing overflow when computing 1/sfmin. sfmin = small*( one+eps ) end if rmach = sfmin else if( stdlib_lsame( cmach, 'B' ) ) then rmach = radix(zero) else if( stdlib_lsame( cmach, 'P' ) ) then rmach = eps * radix(zero) else if( stdlib_lsame( cmach, 'N' ) ) then rmach = digits(zero) else if( stdlib_lsame( cmach, 'R' ) ) then rmach = one else if( stdlib_lsame( cmach, 'M' ) ) then rmach = minexponent(zero) else if( stdlib_lsame( cmach, 'U' ) ) then rmach = tiny(zero) else if( stdlib_lsame( cmach, 'L' ) ) then rmach = maxexponent(zero) else if( stdlib_lsame( cmach, 'O' ) ) then rmach = huge(zero) else rmach = zero end if stdlib${ii}$_slamch = rmach return end function stdlib${ii}$_slamch pure real(dp) module function stdlib${ii}$_dlamch( cmach ) !! DLAMCH determines double precision machine parameters. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: zero, one, eps ! Scalar Arguments character, intent(in) :: cmach ! ===================================================================== ! Local Scalars real(dp) :: sfmin, small, rmach ! Intrinsic Functions ! Executable Statements ! assume rounding, not chopping. always. if( stdlib_lsame( cmach, 'E' ) ) then rmach = eps else if( stdlib_lsame( cmach, 'S' ) ) then sfmin = tiny(zero) small = one / huge(zero) if( small>=sfmin ) then ! use small plus a bit, to avoid the possibility of rounding ! causing overflow when computing 1/sfmin. sfmin = small*( one+eps ) end if rmach = sfmin else if( stdlib_lsame( cmach, 'B' ) ) then rmach = radix(zero) else if( stdlib_lsame( cmach, 'P' ) ) then rmach = eps * radix(zero) else if( stdlib_lsame( cmach, 'N' ) ) then rmach = digits(zero) else if( stdlib_lsame( cmach, 'R' ) ) then rmach = one else if( stdlib_lsame( cmach, 'M' ) ) then rmach = minexponent(zero) else if( stdlib_lsame( cmach, 'U' ) ) then rmach = tiny(zero) else if( stdlib_lsame( cmach, 'L' ) ) then rmach = maxexponent(zero) else if( stdlib_lsame( cmach, 'O' ) ) then rmach = huge(zero) else rmach = zero end if stdlib${ii}$_dlamch = rmach return end function stdlib${ii}$_dlamch #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$lamch( cmach ) !! DLAMCH: determines quad precision machine parameters. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: zero, one, eps ! Scalar Arguments character, intent(in) :: cmach ! ===================================================================== ! Local Scalars real(${rk}$) :: sfmin, small, rmach ! Intrinsic Functions ! Executable Statements ! assume rounding, not chopping. always. if( stdlib_lsame( cmach, 'E' ) ) then rmach = eps else if( stdlib_lsame( cmach, 'S' ) ) then sfmin = tiny(zero) small = one / huge(zero) if( small>=sfmin ) then ! use small plus a bit, to avoid the possibility of rounding ! causing overflow when computing 1/sfmin. sfmin = small*( one+eps ) end if rmach = sfmin else if( stdlib_lsame( cmach, 'B' ) ) then rmach = radix(zero) else if( stdlib_lsame( cmach, 'P' ) ) then rmach = eps * radix(zero) else if( stdlib_lsame( cmach, 'N' ) ) then rmach = digits(zero) else if( stdlib_lsame( cmach, 'R' ) ) then rmach = one else if( stdlib_lsame( cmach, 'M' ) ) then rmach = minexponent(zero) else if( stdlib_lsame( cmach, 'U' ) ) then rmach = tiny(zero) else if( stdlib_lsame( cmach, 'L' ) ) then rmach = maxexponent(zero) else if( stdlib_lsame( cmach, 'O' ) ) then rmach = huge(zero) else rmach = zero end if stdlib${ii}$_${ri}$lamch = rmach return end function stdlib${ii}$_${ri}$lamch #:endif #:endfor pure real(sp) module function stdlib${ii}$_slamc3( a, b ) ! -- lapack auxiliary routine -- ! univ. of tennessee, univ. of california berkeley and nag ltd.. ! Scalar Arguments real(sp), intent(in) :: a, b ! ===================================================================== ! Executable Statements stdlib${ii}$_slamc3 = a + b return end function stdlib${ii}$_slamc3 pure real(dp) module function stdlib${ii}$_dlamc3( a, b ) ! -- lapack auxiliary routine -- ! univ. of tennessee, univ. of california berkeley and nag ltd.. ! Scalar Arguments real(dp), intent(in) :: a, b ! ===================================================================== ! Executable Statements stdlib${ii}$_dlamc3 = a + b return end function stdlib${ii}$_dlamc3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$lamc3( a, b ) ! -- lapack auxiliary routine -- ! univ. of tennessee, univ. of california berkeley and nag ltd.. ! Scalar Arguments real(${rk}$), intent(in) :: a, b ! ===================================================================== ! Executable Statements stdlib${ii}$_${ri}$lamc3 = a + b return end function stdlib${ii}$_${ri}$lamc3 #:endif #:endfor pure module subroutine stdlib${ii}$_slabad( small, large ) !! SLABAD takes as input the values computed by SLAMCH for underflow and !! overflow, and returns the square root of each of these values if the !! log of LARGE is sufficiently large. This subroutine is intended to !! identify machines with a large exponent range, such as the Crays, and !! redefine the underflow and overflow limits to be the square roots of !! the values computed by SLAMCH. This subroutine is needed because !! SLAMCH does not compensate for poor arithmetic in the upper half of !! the exponent range, as is found on a Cray. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(sp), intent(inout) :: large, small ! ===================================================================== ! Intrinsic Functions ! Executable Statements ! if it looks like we're on a cray, take the square root of ! small and large to avoid overflow and underflow problems. if( log10( large )>2000. ) then small = sqrt( small ) large = sqrt( large ) end if return end subroutine stdlib${ii}$_slabad pure module subroutine stdlib${ii}$_dlabad( small, large ) !! DLABAD takes as input the values computed by DLAMCH for underflow and !! overflow, and returns the square root of each of these values if the !! log of LARGE is sufficiently large. This subroutine is intended to !! identify machines with a large exponent range, such as the Crays, and !! redefine the underflow and overflow limits to be the square roots of !! the values computed by DLAMCH. This subroutine is needed because !! DLAMCH does not compensate for poor arithmetic in the upper half of !! the exponent range, as is found on a Cray. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(dp), intent(inout) :: large, small ! ===================================================================== ! Intrinsic Functions ! Executable Statements ! if it looks like we're on a cray, take the square root of ! small and large to avoid overflow and underflow problems. if( log10( large )>2000._dp ) then small = sqrt( small ) large = sqrt( large ) end if return end subroutine stdlib${ii}$_dlabad #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$labad( small, large ) !! DLABAD: takes as input the values computed by DLAMCH for underflow and !! overflow, and returns the square root of each of these values if the !! log of LARGE is sufficiently large. This subroutine is intended to !! identify machines with a large exponent range, such as the Crays, and !! redefine the underflow and overflow limits to be the square roots of !! the values computed by DLAMCH. This subroutine is needed because !! DLAMCH does not compensate for poor arithmetic in the upper half of !! the exponent range, as is found on a Cray. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments real(${rk}$), intent(inout) :: large, small ! ===================================================================== ! Intrinsic Functions ! Executable Statements ! if it looks like we're on a cray, take the square root of ! small and large to avoid overflow and underflow problems. if( log10( large )>2000._${rk}$ ) then small = sqrt( small ) large = sqrt( large ) end if return end subroutine stdlib${ii}$_${ri}$labad #:endif #:endfor pure real(sp) module function stdlib${ii}$_scsum1( n, cx, incx ) !! SCSUM1 takes the sum of the absolute values of a complex !! vector and returns a single precision result. !! Based on SCASUM from the Level 1 BLAS. !! The change is to use the 'genuine' absolute value. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: zero ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments complex(sp), intent(in) :: cx(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, nincx real(sp) :: stemp ! Intrinsic Functions ! Executable Statements stdlib${ii}$_scsum1 = zero stemp = zero if( n<=0 )return if( incx==1 )go to 20 ! code for increment not equal to 1 nincx = n*incx do i = 1, nincx, incx ! next line modified. stemp = stemp + abs( cx( i ) ) end do stdlib${ii}$_scsum1 = stemp return ! code for increment equal to 1 20 continue do i = 1, n ! next line modified. stemp = stemp + abs( cx( i ) ) end do stdlib${ii}$_scsum1 = stemp return end function stdlib${ii}$_scsum1 pure real(dp) module function stdlib${ii}$_dzsum1( n, cx, incx ) !! DZSUM1 takes the sum of the absolute values of a complex !! vector and returns a double precision result. !! Based on DZASUM from the Level 1 BLAS. !! The change is to use the 'genuine' absolute value. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: zero ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments complex(dp), intent(in) :: cx(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, nincx real(dp) :: stemp ! Intrinsic Functions ! Executable Statements stdlib${ii}$_dzsum1 = zero stemp = zero if( n<=0 )return if( incx==1 )go to 20 ! code for increment not equal to 1 nincx = n*incx do i = 1, nincx, incx ! next line modified. stemp = stemp + abs( cx( i ) ) end do stdlib${ii}$_dzsum1 = stemp return ! code for increment equal to 1 20 continue do i = 1, n ! next line modified. stemp = stemp + abs( cx( i ) ) end do stdlib${ii}$_dzsum1 = stemp return end function stdlib${ii}$_dzsum1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$zsum1( n, cx, incx ) !! DZSUM1: takes the sum of the absolute values of a complex !! vector and returns a quad precision result. !! Based on DZASUM from the Level 1 BLAS. !! The change is to use the 'genuine' absolute value. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: zero ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments complex(${rk}$), intent(in) :: cx(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, nincx real(${rk}$) :: stemp ! Intrinsic Functions ! Executable Statements stdlib${ii}$_${ri}$zsum1 = zero stemp = zero if( n<=0 )return if( incx==1 )go to 20 ! code for increment not equal to 1 nincx = n*incx do i = 1, nincx, incx ! next line modified. stemp = stemp + abs( cx( i ) ) end do stdlib${ii}$_${ri}$zsum1 = stemp return ! code for increment equal to 1 20 continue do i = 1, n ! next line modified. stemp = stemp + abs( cx( i ) ) end do stdlib${ii}$_${ri}$zsum1 = stemp return end function stdlib${ii}$_${ri}$zsum1 #:endif #:endfor pure module subroutine stdlib${ii}$_slaqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) !! SLAQSB equilibrates a symmetric band matrix A using the scaling !! factors in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: one ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(sp), intent(in) :: amax, scond ! Array Arguments real(sp), intent(inout) :: ab(ldab,*) real(sp), intent(in) :: s(*) ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1e+0_sp ! Local Scalars integer(${ik}$) :: i, j real(sp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) / stdlib${ii}$_slamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored in band format. do j = 1, n cj = s( j ) do i = max( 1, j-kd ), j ab( kd+1+i-j, j ) = cj*s( i )*ab( kd+1+i-j, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, min( n, j+kd ) ab( 1_${ik}$+i-j, j ) = cj*s( i )*ab( 1_${ik}$+i-j, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_slaqsb pure module subroutine stdlib${ii}$_dlaqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) !! DLAQSB equilibrates a symmetric band matrix A using the scaling !! factors in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: one ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(dp), intent(in) :: amax, scond ! Array Arguments real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(in) :: s(*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j real(dp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored in band format. do j = 1, n cj = s( j ) do i = max( 1, j-kd ), j ab( kd+1+i-j, j ) = cj*s( i )*ab( kd+1+i-j, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, min( n, j+kd ) ab( 1_${ik}$+i-j, j ) = cj*s( i )*ab( 1_${ik}$+i-j, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_dlaqsb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) !! DLAQSB: equilibrates a symmetric band matrix A using the scaling !! factors in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: one ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(${rk}$), intent(in) :: amax, scond ! Array Arguments real(${rk}$), intent(inout) :: ab(ldab,*) real(${rk}$), intent(in) :: s(*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: thresh = 0.1e+0_${rk}$ ! Local Scalars integer(${ik}$) :: i, j real(${rk}$) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${ri}$lamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored in band format. do j = 1, n cj = s( j ) do i = max( 1, j-kd ), j ab( kd+1+i-j, j ) = cj*s( i )*ab( kd+1+i-j, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, min( n, j+kd ) ab( 1_${ik}$+i-j, j ) = cj*s( i )*ab( 1_${ik}$+i-j, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_${ri}$laqsb #:endif #:endfor pure module subroutine stdlib${ii}$_claqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) !! CLAQSB equilibrates a symmetric band matrix A using the scaling !! factors in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: one ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(sp), intent(in) :: amax, scond ! Array Arguments real(sp), intent(in) :: s(*) complex(sp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1e+0_sp ! Local Scalars integer(${ik}$) :: i, j real(sp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) / stdlib${ii}$_slamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored in band format. do j = 1, n cj = s( j ) do i = max( 1, j-kd ), j ab( kd+1+i-j, j ) = cj*s( i )*ab( kd+1+i-j, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, min( n, j+kd ) ab( 1_${ik}$+i-j, j ) = cj*s( i )*ab( 1_${ik}$+i-j, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_claqsb pure module subroutine stdlib${ii}$_zlaqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) !! ZLAQSB equilibrates a symmetric band matrix A using the scaling !! factors in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: one ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(dp), intent(in) :: amax, scond ! Array Arguments real(dp), intent(in) :: s(*) complex(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j real(dp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored in band format. do j = 1, n cj = s( j ) do i = max( 1, j-kd ), j ab( kd+1+i-j, j ) = cj*s( i )*ab( kd+1+i-j, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, min( n, j+kd ) ab( 1_${ik}$+i-j, j ) = cj*s( i )*ab( 1_${ik}$+i-j, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_zlaqsb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqsb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) !! ZLAQSB: equilibrates a symmetric band matrix A using the scaling !! factors in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: one ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(${ck}$), intent(in) :: amax, scond ! Array Arguments real(${ck}$), intent(in) :: s(*) complex(${ck}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: thresh = 0.1e+0_${ck}$ ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored in band format. do j = 1, n cj = s( j ) do i = max( 1, j-kd ), j ab( kd+1+i-j, j ) = cj*s( i )*ab( kd+1+i-j, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, min( n, j+kd ) ab( 1_${ik}$+i-j, j ) = cj*s( i )*ab( 1_${ik}$+i-j, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_${ci}$laqsb #:endif #:endfor pure module subroutine stdlib${ii}$_sladiv1( a, b, c, d, p, q ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: one ! Scalar Arguments real(sp), intent(inout) :: a real(sp), intent(in) :: b, c, d real(sp), intent(out) :: p, q ! ===================================================================== ! Local Scalars real(sp) :: r, t ! Executable Statements r = d / c t = one / (c + d * r) p = stdlib${ii}$_sladiv2(a, b, c, d, r, t) a = -a q = stdlib${ii}$_sladiv2(b, a, c, d, r, t) return end subroutine stdlib${ii}$_sladiv1 pure module subroutine stdlib${ii}$_dladiv1( a, b, c, d, p, q ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: one ! Scalar Arguments real(dp), intent(inout) :: a real(dp), intent(in) :: b, c, d real(dp), intent(out) :: p, q ! ===================================================================== ! Local Scalars real(dp) :: r, t ! Executable Statements r = d / c t = one / (c + d * r) p = stdlib${ii}$_dladiv2(a, b, c, d, r, t) a = -a q = stdlib${ii}$_dladiv2(b, a, c, d, r, t) return end subroutine stdlib${ii}$_dladiv1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ladiv1( a, b, c, d, p, q ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: one ! Scalar Arguments real(${rk}$), intent(inout) :: a real(${rk}$), intent(in) :: b, c, d real(${rk}$), intent(out) :: p, q ! ===================================================================== ! Local Scalars real(${rk}$) :: r, t ! Executable Statements r = d / c t = one / (c + d * r) p = stdlib${ii}$_${ri}$ladiv2(a, b, c, d, r, t) a = -a q = stdlib${ii}$_${ri}$ladiv2(b, a, c, d, r, t) return end subroutine stdlib${ii}$_${ri}$ladiv1 #:endif #:endfor pure real(sp) module function stdlib${ii}$_sladiv2( a, b, c, d, r, t ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: zero ! Scalar Arguments real(sp), intent(in) :: a, b, c, d, r, t ! ===================================================================== ! Local Scalars real(sp) :: br ! Executable Statements if( r/=zero ) then br = b * r if( br/=zero ) then stdlib${ii}$_sladiv2 = (a + br) * t else stdlib${ii}$_sladiv2 = a * t + (b * t) * r end if else stdlib${ii}$_sladiv2 = (a + d * (b / c)) * t end if return end function stdlib${ii}$_sladiv2 pure real(dp) module function stdlib${ii}$_dladiv2( a, b, c, d, r, t ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: zero ! Scalar Arguments real(dp), intent(in) :: a, b, c, d, r, t ! ===================================================================== ! Local Scalars real(dp) :: br ! Executable Statements if( r/=zero ) then br = b * r if( br/=zero ) then stdlib${ii}$_dladiv2 = (a + br) * t else stdlib${ii}$_dladiv2 = a * t + (b * t) * r end if else stdlib${ii}$_dladiv2 = (a + d * (b / c)) * t end if return end function stdlib${ii}$_dladiv2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$ladiv2( a, b, c, d, r, t ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: zero ! Scalar Arguments real(${rk}$), intent(in) :: a, b, c, d, r, t ! ===================================================================== ! Local Scalars real(${rk}$) :: br ! Executable Statements if( r/=zero ) then br = b * r if( br/=zero ) then stdlib${ii}$_${ri}$ladiv2 = (a + br) * t else stdlib${ii}$_${ri}$ladiv2 = a * t + (b * t) * r end if else stdlib${ii}$_${ri}$ladiv2 = (a + d * (b / c)) * t end if return end function stdlib${ii}$_${ri}$ladiv2 #:endif #:endfor pure module subroutine stdlib${ii}$_crot( n, cx, incx, cy, incy, c, s ) !! CROT applies a plane rotation, where the cos (C) is real and the !! sin (S) is complex, and the vectors CX and CY are complex. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n real(sp), intent(in) :: c complex(sp), intent(in) :: s ! Array Arguments complex(sp), intent(inout) :: cx(*), cy(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ix, iy complex(sp) :: stemp ! Intrinsic Functions ! Executable Statements if( n<=0 )return if( incx==1 .and. incy==1 )go to 20 ! code for unequal increments or equal increments not equal to 1 ix = 1_${ik}$ iy = 1_${ik}$ if( incx<0_${ik}$ )ix = ( -n+1 )*incx + 1_${ik}$ if( incy<0_${ik}$ )iy = ( -n+1 )*incy + 1_${ik}$ do i = 1, n stemp = c*cx( ix ) + s*cy( iy ) cy( iy ) = c*cy( iy ) - conjg( s )*cx( ix ) cx( ix ) = stemp ix = ix + incx iy = iy + incy end do return ! code for both increments equal to 1 20 continue do i = 1, n stemp = c*cx( i ) + s*cy( i ) cy( i ) = c*cy( i ) - conjg( s )*cx( i ) cx( i ) = stemp end do return end subroutine stdlib${ii}$_crot pure module subroutine stdlib${ii}$_zrot( n, cx, incx, cy, incy, c, s ) !! ZROT applies a plane rotation, where the cos (C) is real and the !! sin (S) is complex, and the vectors CX and CY are complex. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n real(dp), intent(in) :: c complex(dp), intent(in) :: s ! Array Arguments complex(dp), intent(inout) :: cx(*), cy(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ix, iy complex(dp) :: stemp ! Intrinsic Functions ! Executable Statements if( n<=0 )return if( incx==1 .and. incy==1 )go to 20 ! code for unequal increments or equal increments not equal to 1 ix = 1_${ik}$ iy = 1_${ik}$ if( incx<0_${ik}$ )ix = ( -n+1 )*incx + 1_${ik}$ if( incy<0_${ik}$ )iy = ( -n+1 )*incy + 1_${ik}$ do i = 1, n stemp = c*cx( ix ) + s*cy( iy ) cy( iy ) = c*cy( iy ) - conjg( s )*cx( ix ) cx( ix ) = stemp ix = ix + incx iy = iy + incy end do return ! code for both increments equal to 1 20 continue do i = 1, n stemp = c*cx( i ) + s*cy( i ) cy( i ) = c*cy( i ) - conjg( s )*cx( i ) cx( i ) = stemp end do return end subroutine stdlib${ii}$_zrot #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$rot( n, cx, incx, cy, incy, c, s ) !! ZROT: applies a plane rotation, where the cos (C) is real and the !! sin (S) is complex, and the vectors CX and CY are complex. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n real(${ck}$), intent(in) :: c complex(${ck}$), intent(in) :: s ! Array Arguments complex(${ck}$), intent(inout) :: cx(*), cy(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ix, iy complex(${ck}$) :: stemp ! Intrinsic Functions ! Executable Statements if( n<=0 )return if( incx==1 .and. incy==1 )go to 20 ! code for unequal increments or equal increments not equal to 1 ix = 1_${ik}$ iy = 1_${ik}$ if( incx<0_${ik}$ )ix = ( -n+1 )*incx + 1_${ik}$ if( incy<0_${ik}$ )iy = ( -n+1 )*incy + 1_${ik}$ do i = 1, n stemp = c*cx( ix ) + s*cy( iy ) cy( iy ) = c*cy( iy ) - conjg( s )*cx( ix ) cx( ix ) = stemp ix = ix + incx iy = iy + incy end do return ! code for both increments equal to 1 20 continue do i = 1, n stemp = c*cx( i ) + s*cy( i ) cy( i ) = c*cy( i ) - conjg( s )*cx( i ) cx( i ) = stemp end do return end subroutine stdlib${ii}$_${ci}$rot #:endif #:endfor #:endfor end submodule stdlib_lapack_auxiliary fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_eigv_std_driver.fypp0000664000175000017500000166267515135654166027172 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_eigv_std_driver implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_ssyev( jobz, uplo, n, a, lda, w, work, lwork, info ) !! SSYEV computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale, llwork, lwkopt, nb real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_slascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_ssytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_ssytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_sorgtr to generate the orthogonal matrix, then call stdlib${ii}$_ssteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else call stdlib${ii}$_sorgtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) call stdlib${ii}$_ssteqr( jobz, n, w, work( inde ), a, lda, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_ssyev module subroutine stdlib${ii}$_dsyev( jobz, uplo, n, a, lda, w, work, lwork, info ) !! DSYEV computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale, llwork, lwkopt, nb real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_dlascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_dsytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_dsytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_dorgtr to generate the orthogonal matrix, then call stdlib${ii}$_dsteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else call stdlib${ii}$_dorgtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) call stdlib${ii}$_dsteqr( jobz, n, w, work( inde ), a, lda, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dsyev #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$syev( jobz, uplo, n, a, lda, w, work, lwork, info ) !! DSYEV: computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale, llwork, lwkopt, nb real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$lascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_${ri}$sytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ri}$sytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ri}$orgtr to generate the orthogonal matrix, then call stdlib${ii}$_${ri}$steqr. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else call stdlib${ii}$_${ri}$orgtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( inde ), a, lda, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$syev #:endif #:endfor module subroutine stdlib${ii}$_ssyevd( jobz, uplo, n, a, lda, w, work, lwork, iwork,liwork, info ) !! SSYEVD computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. !! Because of large use of BLAS of level 3, SSYEVD needs N**2 more !! workspace than SSYEVX. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwk2, indwrk, iscale, liopt, liwmin, llwork, & llwrk2, lopt, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_slascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_ssytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_ssytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_sstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_sormtr to multiply it by the ! householder transformations stored in a. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else call stdlib${ii}$_sstedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_sormtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_slacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_sscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lopt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_ssyevd module subroutine stdlib${ii}$_dsyevd( jobz, uplo, n, a, lda, w, work, lwork, iwork,liwork, info ) !! DSYEVD computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. !! Because of large use of BLAS of level 3, DSYEVD needs N**2 more !! workspace than DSYEVX. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwk2, indwrk, iscale, liopt, liwmin, llwork, & llwrk2, lopt, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_dlascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_dsytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_dsytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_dstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_dormtr to multiply it by the ! householder transformations stored in a. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else call stdlib${ii}$_dstedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_dormtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_dlacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_dscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lopt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_dsyevd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$syevd( jobz, uplo, n, a, lda, w, work, lwork, iwork,liwork, info ) !! DSYEVD: computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. !! Because of large use of BLAS of level 3, DSYEVD needs N**2 more !! workspace than DSYEVX. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwk2, indwrk, iscale, liopt, liwmin, llwork, & llwrk2, lopt, lwmin real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$lascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_${ri}$sytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_${ri}$sytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ri}$stedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_${ri}$ormtr to multiply it by the ! householder transformations stored in a. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else call stdlib${ii}$_${ri}$stedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_${ri}$ormtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_${ri}$lacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$scal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lopt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_${ri}$syevd #:endif #:endfor module subroutine stdlib${ii}$_ssyevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! SSYEVR computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A. Eigenvalues and eigenvectors can be !! selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. !! SSYEVR first reduces the matrix A to tridiagonal form T with a call !! to SSYTRD. Then, whenever possible, SSYEVR calls SSTEMR to compute !! the eigenspectrum using Relatively Robust Representations. SSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. !! For each unreduced block (submatrix) of T, !! (a) Compute T - sigma I = L D L^T, so that L and D !! define all the wanted eigenvalues to high relative accuracy. !! This means that small relative changes in the entries of D and L !! cause only small relative changes in the eigenvalues and !! eigenvectors. The standard (unfactored) representation of the !! tridiagonal matrix T does not have this property in general. !! (b) Compute the eigenvalues to suitable accuracy. !! If the eigenvectors are desired, the algorithm attains full !! accuracy of the computed eigenvalues only right before !! the corresponding vectors have to be computed, see steps c) and d). !! (c) For each cluster of close eigenvalues, select a new !! shift close to the cluster, find a new factorization, and refine !! the shifted eigenvalues to suitable accuracy. !! (d) For each eigenvalue with a large enough relative separation compute !! the corresponding eigenvector by forming a rank revealing twisted !! factorization. Go back to (c) for any clusters that remain. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see SSTEMR's documentation and: !! - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations !! to compute orthogonal eigenvectors of symmetric tridiagonal matrices," !! Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. !! - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and !! Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, !! 2004. Also LAPACK Working Note 154. !! - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", !! Computer Science Division Technical Report No. UCB/CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : SSYEVR calls SSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! SSYEVR calls SSTEBZ and SSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of SSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. isuppz, work, lwork,iwork, liwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, liwork, lwork, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: isuppz(*), iwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz, tryrac character :: order integer(${ik}$) :: i, ieeeok, iinfo, imax, indd, inddd, inde, indee, indibl, indifl, & indisp, indiwo, indtau, indwk, indwkn, iscale, j, jj, liwmin, llwork, llwrkn, lwkopt, & lwmin, nb, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. ieeeok = stdlib${ii}$_ilaenv( 10_${ik}$, 'SSYEVR', 'N', 1_${ik}$, 2_${ik}$, 3_${ik}$, 4_${ik}$ ) lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( ( lwork==-1_${ik}$ ) .or. ( liwork==-1_${ik}$ ) ) lwmin = max( 1_${ik}$, 26_${ik}$*n ) liwmin = max( 1_${ik}$, 10_${ik}$*n ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_slansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_sscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_sscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_ssterf or stdlib${ii}$_sstemr fail. ! work(indtau:indtau+n-1) stores the scalar factors of the ! elementary reflectors used in stdlib${ii}$_ssytrd. indtau = 1_${ik}$ ! work(indd:indd+n-1) stores the tridiagonal's diagonal entries. indd = indtau + n ! work(inde:inde+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_ssytrd. inde = indd + n ! work(inddd:inddd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_sstemr (the stdlib${ii}$_ssterf path copies the diagonal to w). inddd = inde + n ! work(indee:indee+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_ssterf and stdlib${ii}$_sstemr. indee = inddd + n ! indwk is the starting offset of the left-over workspace, and ! llwork is the remaining workspace size. indwk = indee + n llwork = lwork - indwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_sstebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_sstebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_sstein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_ssytrd to reduce symmetric matrix to tridiagonal form. call stdlib${ii}$_ssytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_ssterf or stdlib${ii}$_sstemr and stdlib${ii}$_sormtr. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig.or.test ) .and. ( ieeeok==1_${ik}$ ) ) then if( .not.wantz ) then call stdlib${ii}$_scopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, work( indee ), info ) else call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_scopy( n, work( indd ), 1_${ik}$, work( inddd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_sstemr( jobz, 'A', n, work( inddd ), work( indee ),vl, vu, il, iu, m,& w, z, ldz, n, isuppz,tryrac, work( indwk ), lwork, iwork, liwork,info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_sstemr. if( wantz .and. info==0_${ik}$ ) then indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_sormtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then ! everything worked. skip stdlib${ii}$_sstebz/stdlib${ii}$_sstein. iwork(:) are ! undefined. m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. ! also call stdlib${ii}$_sstebz and stdlib${ii}$_sstein if stdlib${ii}$_sstemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwk ),iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_sstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_sstein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_sormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. ! jump here if stdlib${ii}$_sstemr/stdlib${ii}$_sstein succeeded. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. note: we do not sort the ifail portion of iwork. ! it may not be initialized (if stdlib${ii}$_sstemr/stdlib${ii}$_sstein succeeded), and we do ! not return this detailed information to the user. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_dlansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_dscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_dscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_dsterf or stdlib${ii}$_dstemr fail. ! work(indtau:indtau+n-1) stores the scalar factors of the ! elementary reflectors used in stdlib${ii}$_dsytrd. indtau = 1_${ik}$ ! work(indd:indd+n-1) stores the tridiagonal's diagonal entries. indd = indtau + n ! work(inde:inde+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_dsytrd. inde = indd + n ! work(inddd:inddd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_dstemr (the stdlib${ii}$_dsterf path copies the diagonal to w). inddd = inde + n ! work(indee:indee+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_dsterf and stdlib${ii}$_dstemr. indee = inddd + n ! indwk is the starting offset of the left-over workspace, and ! llwork is the remaining workspace size. indwk = indee + n llwork = lwork - indwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_dstebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_dstebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_dstein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_dsytrd to reduce symmetric matrix to tridiagonal form. call stdlib${ii}$_dsytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_dsterf or stdlib${ii}$_dstemr and stdlib${ii}$_dormtr. if( ( alleig .or. ( indeig .and. il==1_${ik}$ .and. iu==n ) ) .and.ieeeok==1_${ik}$ ) then if( .not.wantz ) then call stdlib${ii}$_dcopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, work( indee ), info ) else call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dcopy( n, work( indd ), 1_${ik}$, work( inddd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_dstemr( jobz, 'A', n, work( inddd ), work( indee ),vl, vu, il, iu, m,& w, z, ldz, n, isuppz,tryrac, work( indwk ), lwork, iwork, liwork,info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_dstemr. if( wantz .and. info==0_${ik}$ ) then indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_dormtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then ! everything worked. skip stdlib${ii}$_dstebz/stdlib${ii}$_dstein. iwork(:) are ! undefined. m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_dstein. ! also call stdlib${ii}$_dstebz and stdlib${ii}$_dstein if stdlib${ii}$_dstemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwk ),iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_dstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_dstein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_dormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. ! jump here if stdlib${ii}$_dstemr/stdlib${ii}$_dstein succeeded. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. note: we do not sort the ifail portion of iwork. ! it may not be initialized (if stdlib${ii}$_dstemr/stdlib${ii}$_dstein succeeded), and we do ! not return this detailed information to the user. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_${ri}$lansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_${ri}$scal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_${ri}$scal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_${ri}$sterf or stdlib${ii}$_${ri}$stemr fail. ! work(indtau:indtau+n-1) stores the scalar factors of the ! elementary reflectors used in stdlib${ii}$_${ri}$sytrd. indtau = 1_${ik}$ ! work(indd:indd+n-1) stores the tridiagonal's diagonal entries. indd = indtau + n ! work(inde:inde+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_${ri}$sytrd. inde = indd + n ! work(inddd:inddd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_${ri}$stemr (the stdlib${ii}$_${ri}$sterf path copies the diagonal to w). inddd = inde + n ! work(indee:indee+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_${ri}$sterf and stdlib${ii}$_${ri}$stemr. indee = inddd + n ! indwk is the starting offset of the left-over workspace, and ! llwork is the remaining workspace size. indwk = indee + n llwork = lwork - indwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_${ri}$stebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_${ri}$stebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_${ri}$stein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_${ri}$sytrd to reduce symmetric matrix to tridiagonal form. call stdlib${ii}$_${ri}$sytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_${ri}$sterf or stdlib${ii}$_${ri}$stemr and stdlib${ii}$_${ri}$ormtr. if( ( alleig .or. ( indeig .and. il==1_${ik}$ .and. iu==n ) ) .and.ieeeok==1_${ik}$ ) then if( .not.wantz ) then call stdlib${ii}$_${ri}$copy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$sterf( n, w, work( indee ), info ) else call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n, work( indd ), 1_${ik}$, work( inddd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_${ri}$stemr( jobz, 'A', n, work( inddd ), work( indee ),vl, vu, il, iu, m,& w, z, ldz, n, isuppz,tryrac, work( indwk ), lwork, iwork, liwork,info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ri}$stemr. if( wantz .and. info==0_${ik}$ ) then indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_${ri}$ormtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then ! everything worked. skip stdlib${ii}$_${ri}$stebz/stdlib${ii}$_${ri}$stein. iwork(:) are ! undefined. m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${ri}$stebz and, if eigenvectors are desired, stdlib${ii}$_${ri}$stein. ! also call stdlib${ii}$_${ri}$stebz and stdlib${ii}$_${ri}$stein if stdlib${ii}$_${ri}$stemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_${ri}$stebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwk ),iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_${ri}$stein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ri}$stein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_${ri}$ormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. ! jump here if stdlib${ii}$_${ri}$stemr/stdlib${ii}$_${ri}$stein succeeded. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. note: we do not sort the ifail portion of iwork. ! it may not be initialized (if stdlib${ii}$_${ri}$stemr/stdlib${ii}$_${ri}$stein succeeded), and we do ! not return this detailed information to the user. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_slansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_sscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_sscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_ssytrd to reduce symmetric matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_ssytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_sorgtr and stdlib${ii}$_ssteqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_scopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, work( indee ), info ) else call stdlib${ii}$_slacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_sorgtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_sstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_sstein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_sormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_dlansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_dscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_dscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_dsytrd to reduce symmetric matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_dsytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_dorgtr and stdlib${ii}$_ssteqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_dcopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, work( indee ), info ) else call stdlib${ii}$_dlacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_dorgtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_dstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_dstein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_dormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_${ri}$lansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_${ri}$scal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_${ri}$scal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ri}$sytrd to reduce symmetric matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ri}$sytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_${ri}$sterf or stdlib${ii}$_${ri}$orgtr and stdlib${ii}$_dsteqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_${ri}$stebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_${ri}$copy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$sterf( n, w, work( indee ), info ) else call stdlib${ii}$_${ri}$lacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_${ri}$orgtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${ri}$stebz and, if eigenvectors are desired, stdlib${ii}$_dstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_${ri}$stebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_${ri}$stein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ri}$stein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_${ri}$ormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_sscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_ssptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_ssptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_sopgtr to generate the orthogonal matrix, then call stdlib${ii}$_ssteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_sopgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_ssteqr( jobz, n, w, work( inde ), z, ldz, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_sspev module subroutine stdlib${ii}$_dspev( jobz, uplo, n, ap, w, z, ldz, work, info ) !! DSPEV computes all the eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A in packed storage. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(dp), intent(inout) :: ap(*) real(dp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_dsptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_dsptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_dopgtr to generate the orthogonal matrix, then call stdlib${ii}$_dsteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_dopgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_dsteqr( jobz, n, w, work( inde ), z, ldz, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_dspev #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$spev( jobz, uplo, n, ap, w, z, ldz, work, info ) !! DSPEV: computes all the eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A in packed storage. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(${rk}$), intent(inout) :: ap(*) real(${rk}$), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_${ri}$sptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_${ri}$sptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ri}$opgtr to generate the orthogonal matrix, then call stdlib${ii}$_${ri}$steqr. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_${ri}$opgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( inde ), z, ldz, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ri}$spev #:endif #:endfor module subroutine stdlib${ii}$_sspevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,iwork, liwork, info ) !! SSPEVD computes all the eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: ap(*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwrk, iscale, liwmin, llwork, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_sscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_ssptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_ssptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_sstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_sopmtr to multiply it by the ! householder transformations represented in ap. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_sstedc( 'I', n, w, work( inde ), z, ldz, work( indwrk ),llwork, iwork, & liwork, info ) call stdlib${ii}$_sopmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_sscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_sspevd module subroutine stdlib${ii}$_dspevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,iwork, liwork, info ) !! DSPEVD computes all the eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: ap(*) real(dp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwrk, iscale, liwmin, llwork, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_dsptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_dsptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_dstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_dopmtr to multiply it by the ! householder transformations represented in ap. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_dstedc( 'I', n, w, work( inde ), z, ldz, work( indwrk ),llwork, iwork, & liwork, info ) call stdlib${ii}$_dopmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_dscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_dspevd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$spevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,iwork, liwork, info ) !! DSPEVD: computes all the eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: ap(*) real(${rk}$), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwrk, iscale, liwmin, llwork, lwmin real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_${ri}$sptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_${ri}$sptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ri}$stedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_${ri}$opmtr to multiply it by the ! householder transformations represented in ap. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ri}$stedc( 'I', n, w, work( inde ), z, ldz, work( indwrk ),llwork, iwork, & liwork, info ) call stdlib${ii}$_${ri}$opmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$scal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ri}$spevd #:endif #:endfor module subroutine stdlib${ii}$_sspevx( jobz, range, uplo, n, ap, vl, vu, il, iu,abstol, m, w, z, ldz, & !! SSPEVX computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A in packed storage. Eigenvalues/vectors !! can be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. work, iwork, ifail,info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, ldz, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(sp), intent(inout) :: ap(*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwo, indtau, & indwrk, iscale, itmp1, j, jj, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=ap( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = ap( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if ( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero endif anrm = stdlib${ii}$_slansp( 'M', uplo, n, ap, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_sscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_ssptrd to reduce symmetric packed matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n call stdlib${ii}$_ssptrd( uplo, n, ap, work( indd ), work( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_sopgtr and stdlib${ii}$_ssteqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_scopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, work( indee ), info ) else call stdlib${ii}$_sopgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_sstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_sstein. call stdlib${ii}$_sopmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=ap( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = ap( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_dlansp( 'M', uplo, n, ap, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_dsptrd to reduce symmetric packed matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n call stdlib${ii}$_dsptrd( uplo, n, ap, work( indd ), work( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_dopgtr and stdlib${ii}$_ssteqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_dcopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, work( indee ), info ) else call stdlib${ii}$_dopgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_dstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_dstein. call stdlib${ii}$_dopmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=ap( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = ap( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_${ri}$lansp( 'M', uplo, n, ap, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ri}$sptrd to reduce symmetric packed matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n call stdlib${ii}$_${ri}$sptrd( uplo, n, ap, work( indd ), work( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_${ri}$sterf or stdlib${ii}$_${ri}$opgtr and stdlib${ii}$_dsteqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_${ri}$stebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_${ri}$copy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$sterf( n, w, work( indee ), info ) else call stdlib${ii}$_${ri}$opgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${ri}$stebz and, if eigenvectors are desired, stdlib${ii}$_dstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_${ri}$stebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_${ri}$stein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ri}$stein. call stdlib${ii}$_${ri}$opmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_slascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_slascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_ssbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n call stdlib${ii}$_ssbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, call stdlib${ii}$_ssteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else call stdlib${ii}$_ssteqr( jobz, n, w, work( inde ), z, ldz, work( indwrk ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_ssbev module subroutine stdlib${ii}$_dsbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,info ) !! DSBEV computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, n ! Array Arguments real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, wantz integer(${ik}$) :: iinfo, imax, inde, indwrk, iscale real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_dlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_dlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_dsbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n call stdlib${ii}$_dsbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, call stdlib${ii}$_ssteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else call stdlib${ii}$_dsteqr( jobz, n, w, work( inde ), z, ldz, work( indwrk ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_dsbev #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$sbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,info ) !! DSBEV: computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, n ! Array Arguments real(${rk}$), intent(inout) :: ab(ldab,*) real(${rk}$), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, wantz integer(${ik}$) :: iinfo, imax, inde, indwrk, iscale real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ri}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ri}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_${ri}$sbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n call stdlib${ii}$_${ri}$sbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, call stdlib${ii}$_dsteqr. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( inde ), z, ldz, work( indwrk ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ri}$sbev #:endif #:endfor module subroutine stdlib${ii}$_ssbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, iwork, liwork, & !! SSBEVD computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. If eigenvectors are desired, it uses !! a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: ab(ldab,*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indwk2, indwrk, iscale, liwmin, llwrk2, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_slascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_slascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_ssbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_ssbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, call stdlib${ii}$_sstedc. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else call stdlib${ii}$_sstedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_sgemm( 'N', 'N', n, n, n, one, z, ldz, work( indwrk ), n,zero, work( & indwk2 ), n ) call stdlib${ii}$_slacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_sscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_ssbevd module subroutine stdlib${ii}$_dsbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, iwork, liwork, & !! DSBEVD computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. If eigenvectors are desired, it uses !! a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indwk2, indwrk, iscale, liwmin, llwrk2, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_dlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_dlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_dsbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_dsbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, call stdlib${ii}$_sstedc. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else call stdlib${ii}$_dstedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_dgemm( 'N', 'N', n, n, n, one, z, ldz, work( indwrk ), n,zero, work( & indwk2 ), n ) call stdlib${ii}$_dlacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_dscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_dsbevd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$sbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, iwork, liwork, & !! DSBEVD: computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. If eigenvectors are desired, it uses !! a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: ab(ldab,*) real(${rk}$), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indwk2, indwrk, iscale, liwmin, llwrk2, lwmin real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ri}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ri}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_${ri}$sbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_${ri}$sbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, call stdlib${ii}$_dstedc. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else call stdlib${ii}$_${ri}$stedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, n, n, one, z, ldz, work( indwrk ), n,zero, work( & indwk2 ), n ) call stdlib${ii}$_${ri}$lacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$scal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ri}$sbevd #:endif #:endfor module subroutine stdlib${ii}$_ssbevx( jobz, range, uplo, n, kd, ab, ldab, q, ldq, vl,vu, il, iu, abstol, & !! SSBEVX computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric band matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. m, w, z, ldz, work, iwork,ifail, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, kd, ldab, ldq, ldz, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(sp), intent(inout) :: ab(ldab,*) real(sp), intent(out) :: q(ldq,*), w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwo, indwrk, & iscale, itmp1, j, jj, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( ldab0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iun ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = tmp1 if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one end if return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if ( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero endif anrm = stdlib${ii}$_slansb( 'M', uplo, n, kd, ab, ldab, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_slascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_slascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_ssbtrd to reduce symmetric band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indwrk = inde + n call stdlib${ii}$_ssbtrd( jobz, uplo, n, kd, ab, ldab, work( indd ),work( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_ssteqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_scopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, work( indee ), info ) else call stdlib${ii}$_slacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_sstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_sstein. do j = 1, m call stdlib${ii}$_scopy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_sgemv( 'N', n, n, one, q, ldq, work, 1_${ik}$, zero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iun ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = tmp1 if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one end if return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_dlansb( 'M', uplo, n, kd, ab, ldab, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_dlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_dlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_dsbtrd to reduce symmetric band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indwrk = inde + n call stdlib${ii}$_dsbtrd( jobz, uplo, n, kd, ab, ldab, work( indd ),work( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_ssteqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_dcopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, work( indee ), info ) else call stdlib${ii}$_dlacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_dstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_dstein. do j = 1, m call stdlib${ii}$_dcopy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_dgemv( 'N', n, n, one, q, ldq, work, 1_${ik}$, zero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iun ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = tmp1 if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one end if return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_${ri}$lansb( 'M', uplo, n, kd, ab, ldab, work ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ri}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ri}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ri}$sbtrd to reduce symmetric band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indwrk = inde + n call stdlib${ii}$_${ri}$sbtrd( jobz, uplo, n, kd, ab, ldab, work( indd ),work( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_${ri}$sterf or stdlib${ii}$_dsteqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_${ri}$stebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_${ri}$copy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$sterf( n, w, work( indee ), info ) else call stdlib${ii}$_${ri}$lacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${ri}$stebz and, if eigenvectors are desired, stdlib${ii}$_dstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_${ri}$stebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_${ri}$stein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ri}$stein. do j = 1, m call stdlib${ii}$_${ri}$copy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'N', n, n, one, q, ldq, work, 1_${ik}$, zero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_clascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_chetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_chetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_cungtr to generate the unitary matrix, then call stdlib${ii}$_csteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_cungtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) indwrk = inde + n call stdlib${ii}$_csteqr( jobz, n, w, rwork( inde ), a, lda,rwork( indwrk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal complex workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cheev module subroutine stdlib${ii}$_zheev( jobz, uplo, n, a, lda, w, work, lwork, rwork,info ) !! ZHEEV computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale, llwork, lwkopt, nb real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_zlascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_zhetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_zhetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_zungtr to generate the unitary matrix, then call stdlib${ii}$_zsteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_zungtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) indwrk = inde + n call stdlib${ii}$_zsteqr( jobz, n, w, rwork( inde ), a, lda,rwork( indwrk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal complex workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zheev #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$heev( jobz, uplo, n, a, lda, w, work, lwork, rwork,info ) !! ZHEEV: computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale, llwork, lwkopt, nb real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_${ci}$lascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_${ci}$hetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ci}$hetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ci}$ungtr to generate the unitary matrix, then call stdlib${ii}$_${ci}$steqr. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_${ci}$ungtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) indwrk = inde + n call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( inde ), a, lda,rwork( indwrk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal complex workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$heev #:endif #:endfor module subroutine stdlib${ii}$_cheevd( jobz, uplo, n, a, lda, w, work, lwork, rwork,lrwork, iwork, liwork,& !! CHEEVD computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwk2, indwrk, iscale, liopt, & liwmin, llrwk, llwork, llwrk2, lopt, lropt, lrwmin, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_clascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_chetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n indrwk = inde + n indwk2 = indwrk + n*n llwork = lwork - indwrk + 1_${ik}$ llwrk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_chetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_cstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_cunmtr to multiply it to the ! householder transformations represented as householder vectors in ! a. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_cstedc( 'I', n, w, rwork( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, rwork( indrwk ), llrwk,iwork, liwork, info ) call stdlib${ii}$_cunmtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_clacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lopt rwork( 1_${ik}$ ) = lropt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_cheevd module subroutine stdlib${ii}$_zheevd( jobz, uplo, n, a, lda, w, work, lwork, rwork,lrwork, iwork, liwork,& !! ZHEEVD computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwk2, indwrk, iscale, liopt, & liwmin, llrwk, llwork, llwrk2, lopt, lropt, lrwmin, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_zlascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_zhetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n indrwk = inde + n indwk2 = indwrk + n*n llwork = lwork - indwrk + 1_${ik}$ llwrk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_zhetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_zstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_zunmtr to multiply it to the ! householder transformations represented as householder vectors in ! a. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_zstedc( 'I', n, w, rwork( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, rwork( indrwk ), llrwk,iwork, liwork, info ) call stdlib${ii}$_zunmtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_zlacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lopt rwork( 1_${ik}$ ) = lropt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_zheevd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$heevd( jobz, uplo, n, a, lda, w, work, lwork, rwork,lrwork, iwork, liwork,& !! ZHEEVD: computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwk2, indwrk, iscale, liopt, & liwmin, llrwk, llwork, llwrk2, lopt, lropt, lrwmin, lwmin real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_${ci}$lascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_${ci}$hetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n indrwk = inde + n indwk2 = indwrk + n*n llwork = lwork - indwrk + 1_${ik}$ llwrk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_${ci}$hetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ci}$stedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_${ci}$unmtr to multiply it to the ! householder transformations represented as householder vectors in ! a. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_${ci}$stedc( 'I', n, w, rwork( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, rwork( indrwk ), llrwk,iwork, liwork, info ) call stdlib${ii}$_${ci}$unmtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_${ci}$lacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lopt rwork( 1_${ik}$ ) = lropt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_${ci}$heevd #:endif #:endfor module subroutine stdlib${ii}$_cheevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! CHEEVR computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. !! CHEEVR first reduces the matrix A to tridiagonal form T with a call !! to CHETRD. Then, whenever possible, CHEEVR calls CSTEMR to compute !! the eigenspectrum using Relatively Robust Representations. CSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. !! For each unreduced block (submatrix) of T, !! (a) Compute T - sigma I = L D L^T, so that L and D !! define all the wanted eigenvalues to high relative accuracy. !! This means that small relative changes in the entries of D and L !! cause only small relative changes in the eigenvalues and !! eigenvectors. The standard (unfactored) representation of the !! tridiagonal matrix T does not have this property in general. !! (b) Compute the eigenvalues to suitable accuracy. !! If the eigenvectors are desired, the algorithm attains full !! accuracy of the computed eigenvalues only right before !! the corresponding vectors have to be computed, see steps c) and d). !! (c) For each cluster of close eigenvalues, select a new !! shift close to the cluster, find a new factorization, and refine !! the shifted eigenvalues to suitable accuracy. !! (d) For each eigenvalue with a large enough relative separation compute !! the corresponding eigenvector by forming a rank revealing twisted !! factorization. Go back to (c) for any clusters that remain. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see CSTEMR's documentation and: !! - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations !! to compute orthogonal eigenvectors of symmetric tridiagonal matrices," !! Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. !! - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and !! Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, !! 2004. Also LAPACK Working Note 154. !! - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", !! Computer Science Division Technical Report No. UCB/CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : CHEEVR calls CSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! CHEEVR calls SSTEBZ and CSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of CSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. isuppz, work, lwork,rwork, lrwork, iwork, liwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, liwork, lrwork, lwork, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: isuppz(*), iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz, tryrac character :: order integer(${ik}$) :: i, ieeeok, iinfo, imax, indibl, indifl, indisp, indiwo, indrd, indrdd, & indre, indree, indrwk, indtau, indwk, indwkn, iscale, itmp1, j, jj, liwmin, llwork, & llrwork, llwrkn, lrwmin, lwkopt, lwmin, nb, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. ieeeok = stdlib${ii}$_ilaenv( 10_${ik}$, 'CHEEVR', 'N', 1_${ik}$, 2_${ik}$, 3_${ik}$, 4_${ik}$ ) lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( ( lwork==-1_${ik}$ ) .or. ( lrwork==-1_${ik}$ ) .or.( liwork==-1_${ik}$ ) ) lrwmin = max( 1_${ik}$, 24_${ik}$*n ) liwmin = max( 1_${ik}$, 10_${ik}$*n ) lwmin = max( 1_${ik}$, 2_${ik}$*n ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_clansy( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_csscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_csscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_ssterf or stdlib${ii}$_cstemr fail. ! work(indtau:indtau+n-1) stores the complex scalar factors of the ! elementary reflectors used in stdlib${ii}$_chetrd. indtau = 1_${ik}$ ! indwk is the starting offset of the remaining complex workspace, ! and llwork is the remaining complex workspace size. indwk = indtau + n llwork = lwork - indwk + 1_${ik}$ ! rwork(indrd:indrd+n-1) stores the real tridiagonal's diagonal ! entries. indrd = 1_${ik}$ ! rwork(indre:indre+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_chetrd. indre = indrd + n ! rwork(indrdd:indrdd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_cstemr (the stdlib${ii}$_ssterf path copies the diagonal to w). indrdd = indre + n ! rwork(indree:indree+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_ssterf and stdlib${ii}$_cstemr. indree = indrdd + n ! indrwk is the starting offset of the left-over real workspace, and ! llrwork is the remaining workspace size. indrwk = indree + n llrwork = lrwork - indrwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_sstebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_sstebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_sstein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_chetrd to reduce hermitian matrix to tridiagonal form. call stdlib${ii}$_chetrd( uplo, n, a, lda, rwork( indrd ), rwork( indre ),work( indtau ), & work( indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_ssterf or stdlib${ii}$_cstemr and stdlib${ii}$_cunmtr. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig.or.test ) .and. ( ieeeok==1_${ik}$ ) ) then if( .not.wantz ) then call stdlib${ii}$_scopy( n, rwork( indrd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_scopy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, rwork( indree ), info ) else call stdlib${ii}$_scopy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_scopy( n, rwork( indrd ), 1_${ik}$, rwork( indrdd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_cstemr( jobz, 'A', n, rwork( indrdd ),rwork( indree ), vl, vu, il, & iu, m, w,z, ldz, n, isuppz, tryrac,rwork( indrwk ), llrwork,iwork, liwork, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_cstemr. if( wantz .and. info==0_${ik}$ ) then indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_cunmtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_cstein. ! also call stdlib${ii}$_sstebz and stdlib${ii}$_cstein if stdlib${ii}$_cstemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indrd ), rwork( & indre ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwo )& , info ) if( wantz ) then call stdlib${ii}$_cstein( n, rwork( indrd ), rwork( indre ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_cstein. indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_cunmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_zlansy( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_zdscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_zdscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_dsterf or stdlib${ii}$_zstemr fail. ! work(indtau:indtau+n-1) stores the complex scalar factors of the ! elementary reflectors used in stdlib${ii}$_zhetrd. indtau = 1_${ik}$ ! indwk is the starting offset of the remaining complex workspace, ! and llwork is the remaining complex workspace size. indwk = indtau + n llwork = lwork - indwk + 1_${ik}$ ! rwork(indrd:indrd+n-1) stores the real tridiagonal's diagonal ! entries. indrd = 1_${ik}$ ! rwork(indre:indre+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_zhetrd. indre = indrd + n ! rwork(indrdd:indrdd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_zstemr (the stdlib${ii}$_dsterf path copies the diagonal to w). indrdd = indre + n ! rwork(indree:indree+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_dsterf and stdlib${ii}$_zstemr. indree = indrdd + n ! indrwk is the starting offset of the left-over real workspace, and ! llrwork is the remaining workspace size. indrwk = indree + n llrwork = lrwork - indrwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_dstebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_dstebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_dstein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_zhetrd to reduce hermitian matrix to tridiagonal form. call stdlib${ii}$_zhetrd( uplo, n, a, lda, rwork( indrd ), rwork( indre ),work( indtau ), & work( indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_dsterf or stdlib${ii}$_zstemr and stdlib${ii}$_zunmtr. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig.or.test ) .and. ( ieeeok==1_${ik}$ ) ) then if( .not.wantz ) then call stdlib${ii}$_dcopy( n, rwork( indrd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_dcopy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, rwork( indree ), info ) else call stdlib${ii}$_dcopy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_dcopy( n, rwork( indrd ), 1_${ik}$, rwork( indrdd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_zstemr( jobz, 'A', n, rwork( indrdd ),rwork( indree ), vl, vu, il, & iu, m, w,z, ldz, n, isuppz, tryrac,rwork( indrwk ), llrwork,iwork, liwork, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_zstemr. if( wantz .and. info==0_${ik}$ ) then indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_zunmtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_zstein. ! also call stdlib${ii}$_dstebz and stdlib${ii}$_zstein if stdlib${ii}$_zstemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indrd ), rwork( & indre ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwo )& , info ) if( wantz ) then call stdlib${ii}$_zstein( n, rwork( indrd ), rwork( indre ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_zstein. indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_zunmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_${ci}$lansy( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_${ci}$dscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_${ci}$dscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_${c2ri(ci)}$sterf or stdlib${ii}$_${ci}$stemr fail. ! work(indtau:indtau+n-1) stores the complex scalar factors of the ! elementary reflectors used in stdlib${ii}$_${ci}$hetrd. indtau = 1_${ik}$ ! indwk is the starting offset of the remaining complex workspace, ! and llwork is the remaining complex workspace size. indwk = indtau + n llwork = lwork - indwk + 1_${ik}$ ! rwork(indrd:indrd+n-1) stores the real tridiagonal's diagonal ! entries. indrd = 1_${ik}$ ! rwork(indre:indre+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_${ci}$hetrd. indre = indrd + n ! rwork(indrdd:indrdd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_${ci}$stemr (the stdlib${ii}$_${c2ri(ci)}$sterf path copies the diagonal to w). indrdd = indre + n ! rwork(indree:indree+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_${c2ri(ci)}$sterf and stdlib${ii}$_${ci}$stemr. indree = indrdd + n ! indrwk is the starting offset of the left-over real workspace, and ! llrwork is the remaining workspace size. indrwk = indree + n llrwork = lrwork - indrwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_${c2ri(ci)}$stebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_${c2ri(ci)}$stebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_${c2ri(ci)}$stein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_${ci}$hetrd to reduce hermitian matrix to tridiagonal form. call stdlib${ii}$_${ci}$hetrd( uplo, n, a, lda, rwork( indrd ), rwork( indre ),work( indtau ), & work( indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_${c2ri(ci)}$sterf or stdlib${ii}$_${ci}$stemr and stdlib${ii}$_${ci}$unmtr. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig.or.test ) .and. ( ieeeok==1_${ik}$ ) ) then if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$copy( n, rwork( indrd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( indree ), info ) else call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$copy( n, rwork( indrd ), 1_${ik}$, rwork( indrdd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_${ci}$stemr( jobz, 'A', n, rwork( indrdd ),rwork( indree ), vl, vu, il, & iu, m, w,z, ldz, n, isuppz, tryrac,rwork( indrwk ), llrwork,iwork, liwork, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ci}$stemr. if( wantz .and. info==0_${ik}$ ) then indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_${ci}$unmtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${c2ri(ci)}$stebz and, if eigenvectors are desired, stdlib${ii}$_${ci}$stein. ! also call stdlib${ii}$_${c2ri(ci)}$stebz and stdlib${ii}$_${ci}$stein if stdlib${ii}$_${ci}$stemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_${c2ri(ci)}$stebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indrd ), rwork( & indre ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwo )& , info ) if( wantz ) then call stdlib${ii}$_${ci}$stein( n, rwork( indrd ), rwork( indre ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ci}$stein. indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_${ci}$unmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_clanhe( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_csscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_csscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_chetrd to reduce hermitian matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_chetrd( uplo, n, a, lda, rwork( indd ), rwork( inde ),work( indtau ), work(& indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_cungtr and stdlib${ii}$_csteqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_scopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_clacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_cungtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_csteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_cstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_cstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_cstein. call stdlib${ii}$_cunmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwrk ), llwork, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_zlanhe( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_zdscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_zdscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_zhetrd to reduce hermitian matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_zhetrd( uplo, n, a, lda, rwork( indd ), rwork( inde ),work( indtau ), work(& indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_zungtr and stdlib${ii}$_zsteqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_dcopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_zlacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_zungtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_zsteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_zstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_zstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_zstein. call stdlib${ii}$_zunmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwrk ), llwork, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iun ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_${ci}$lanhe( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_${ci}$dscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_${ci}$dscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ci}$hetrd to reduce hermitian matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ci}$hetrd( uplo, n, a, lda, rwork( indd ), rwork( inde ),work( indtau ), work(& indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_${c2ri(ci)}$sterf or stdlib${ii}$_${ci}$ungtr and stdlib${ii}$_${ci}$steqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_${c2ri(ci)}$stebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_${c2ri(ci)}$copy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_${ci}$lacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_${ci}$ungtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${c2ri(ci)}$stebz and, if eigenvectors are desired, stdlib${ii}$_${ci}$stein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_${c2ri(ci)}$stebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_${ci}$stein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ci}$stein. call stdlib${ii}$_${ci}$unmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwrk ), llwork, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_csscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_chptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ call stdlib${ii}$_chptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_cupgtr to generate the orthogonal matrix, then call stdlib${ii}$_csteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_cupgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) indrwk = inde + n call stdlib${ii}$_csteqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_chpev module subroutine stdlib${ii}$_zhpev( jobz, uplo, n, ap, w, z, ldz, work, rwork,info ) !! ZHPEV computes all the eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix in packed storage. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: ap(*) complex(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwrk, iscale real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_zdscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_zhptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ call stdlib${ii}$_zhptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_zupgtr to generate the orthogonal matrix, then call stdlib${ii}$_zsteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_zupgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) indrwk = inde + n call stdlib${ii}$_zsteqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_zhpev #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hpev( jobz, uplo, n, ap, w, z, ldz, work, rwork,info ) !! ZHPEV: computes all the eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix in packed storage. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: ap(*) complex(${ck}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwrk, iscale real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ci}$dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_${ci}$hptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ call stdlib${ii}$_${ci}$hptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ci}$upgtr to generate the orthogonal matrix, then call stdlib${ii}$_${ci}$steqr. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_${ci}$upgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) indrwk = inde + n call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ci}$hpev #:endif #:endfor module subroutine stdlib${ii}$_chpevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,rwork, lrwork, iwork, & !! CHPEVD computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. liwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: ap(*) complex(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwrk, iscale, liwmin, llrwk, & llwrk, lrwmin, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_csscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_chptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indrwk = inde + n indwrk = indtau + n llwrk = lwork - indwrk + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_chptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_cupgtr to generate the orthogonal matrix, then call stdlib${ii}$_cstedc. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_cstedc( 'I', n, w, rwork( inde ), z, ldz, work( indwrk ),llwrk, rwork( & indrwk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_cupmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_chpevd module subroutine stdlib${ii}$_zhpevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,rwork, lrwork, iwork, & !! ZHPEVD computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. liwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: ap(*) complex(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwrk, iscale, liwmin, llrwk, & llwrk, lrwmin, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_zdscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_zhptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indrwk = inde + n indwrk = indtau + n llwrk = lwork - indwrk + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_zhptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_zupgtr to generate the orthogonal matrix, then call stdlib${ii}$_zstedc. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_zstedc( 'I', n, w, rwork( inde ), z, ldz, work( indwrk ),llwrk, rwork( & indrwk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_zupmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_zhpevd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hpevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,rwork, lrwork, iwork, & !! ZHPEVD: computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. liwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: ap(*) complex(${ck}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwrk, iscale, liwmin, llrwk, & llwrk, lrwmin, lwmin real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ci}$dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_${ci}$hptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indrwk = inde + n indwrk = indtau + n llwrk = lwork - indwrk + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_${ci}$hptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ci}$upgtr to generate the orthogonal matrix, then call stdlib${ii}$_${ci}$stedc. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_${ci}$stedc( 'I', n, w, rwork( inde ), z, ldz, work( indwrk ),llwrk, rwork( & indrwk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_${ci}$upmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ci}$hpevd #:endif #:endfor module subroutine stdlib${ii}$_chpevx( jobz, range, uplo, n, ap, vl, vu, il, iu,abstol, m, w, z, ldz, & !! CHPEVX computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A in packed storage. !! Eigenvalues/vectors can be selected by specifying either a range of !! values or a range of indices for the desired eigenvalues. work, rwork, iwork,ifail, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, ldz, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: ap(*) complex(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwk, indrwk, & indtau, indwrk, iscale, itmp1, j, jj, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=real( ap( 1_${ik}$ ),KIND=sp) ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=sp) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if ( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero endif anrm = stdlib${ii}$_clanhp( 'M', uplo, n, ap, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_csscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_chptrd to reduce hermitian packed matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n call stdlib${ii}$_chptrd( uplo, n, ap, rwork( indd ), rwork( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_cupgtr and stdlib${ii}$_csteqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_scopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_cupgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_csteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_cstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_cstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_cstein. indwrk = indtau + n call stdlib${ii}$_cupmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=real( ap( 1_${ik}$ ),KIND=dp) ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=dp) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_zlanhp( 'M', uplo, n, ap, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_zdscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_zhptrd to reduce hermitian packed matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n call stdlib${ii}$_zhptrd( uplo, n, ap, rwork( indd ), rwork( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_zupgtr and stdlib${ii}$_zsteqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_dcopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_zupgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_zsteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_zstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_zstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_zstein. indwrk = indtau + n call stdlib${ii}$_zupmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=real( ap( 1_${ik}$ ),KIND=${ck}$) ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=${ck}$) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_${ci}$lanhp( 'M', uplo, n, ap, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ci}$dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ci}$hptrd to reduce hermitian packed matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n call stdlib${ii}$_${ci}$hptrd( uplo, n, ap, rwork( indd ), rwork( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_${c2ri(ci)}$sterf or stdlib${ii}$_${ci}$upgtr and stdlib${ii}$_${ci}$steqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_${c2ri(ci)}$stebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_${c2ri(ci)}$copy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_${ci}$upgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${c2ri(ci)}$stebz and, if eigenvectors are desired, stdlib${ii}$_${ci}$stein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_${c2ri(ci)}$stebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_${ci}$stein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ci}$stein. indwrk = indtau + n call stdlib${ii}$_${ci}$upmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_clascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_clascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_chbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ call stdlib${ii}$_chbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, call stdlib${ii}$_csteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else indrwk = inde + n call stdlib${ii}$_csteqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_chbev module subroutine stdlib${ii}$_zhbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,rwork, info ) !! ZHBEV computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, n ! Array Arguments real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: ab(ldab,*) complex(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, iscale real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_zlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_zlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_zhbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ call stdlib${ii}$_zhbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, call stdlib${ii}$_zsteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else indrwk = inde + n call stdlib${ii}$_zsteqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_zhbev #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,rwork, info ) !! ZHBEV: computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, n ! Array Arguments real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: ab(ldab,*) complex(${ck}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, iscale real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ci}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ci}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_${ci}$hbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ call stdlib${ii}$_${ci}$hbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, call stdlib${ii}$_${ci}$steqr. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else indrwk = inde + n call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ci}$hbev #:endif #:endfor module subroutine stdlib${ii}$_chbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, rwork, lrwork, & !! CHBEVD computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. If eigenvectors are desired, it !! uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, liwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: ab(ldab,*) complex(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indwk2, indwrk, iscale, liwmin, llrwk, llwk2, & lrwmin, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ .or. lrwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ lrwmin = 1_${ik}$ liwmin = 1_${ik}$ else if( wantz ) then lwmin = 2_${ik}$*n**2_${ik}$ lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n lrwmin = n liwmin = 1_${ik}$ end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_clascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_clascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_chbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = 1_${ik}$ + n*n llwk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indwrk + 1_${ik}$ call stdlib${ii}$_chbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, call stdlib${ii}$_cstedc. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_cstedc( 'I', n, w, rwork( inde ), work, n, work( indwk2 ),llwk2, rwork( & indwrk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_cgemm( 'N', 'N', n, n, n, cone, z, ldz, work, n, czero,work( indwk2 ), & n ) call stdlib${ii}$_clacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_chbevd module subroutine stdlib${ii}$_zhbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, rwork, lrwork, & !! ZHBEVD computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. If eigenvectors are desired, it !! uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, liwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: ab(ldab,*) complex(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indwk2, indwrk, iscale, liwmin, llrwk, llwk2, & lrwmin, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ .or. lrwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ lrwmin = 1_${ik}$ liwmin = 1_${ik}$ else if( wantz ) then lwmin = 2_${ik}$*n**2_${ik}$ lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n lrwmin = n liwmin = 1_${ik}$ end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_zlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_zlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_zhbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = 1_${ik}$ + n*n llwk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indwrk + 1_${ik}$ call stdlib${ii}$_zhbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, call stdlib${ii}$_zstedc. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_zstedc( 'I', n, w, rwork( inde ), work, n, work( indwk2 ),llwk2, rwork( & indwrk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_zgemm( 'N', 'N', n, n, n, cone, z, ldz, work, n, czero,work( indwk2 ), & n ) call stdlib${ii}$_zlacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_zhbevd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, rwork, lrwork, & !! ZHBEVD: computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. If eigenvectors are desired, it !! uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, liwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: ab(ldab,*) complex(${ck}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indwk2, indwrk, iscale, liwmin, llrwk, llwk2, & lrwmin, lwmin real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ .or. lrwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ lrwmin = 1_${ik}$ liwmin = 1_${ik}$ else if( wantz ) then lwmin = 2_${ik}$*n**2_${ik}$ lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n lrwmin = n liwmin = 1_${ik}$ end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ci}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ci}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_${ci}$hbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = 1_${ik}$ + n*n llwk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ci}$hbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, call stdlib${ii}$_${ci}$stedc. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_${ci}$stedc( 'I', n, w, rwork( inde ), work, n, work( indwk2 ),llwk2, rwork( & indwrk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', n, n, n, cone, z, ldz, work, n, czero,work( indwk2 ), & n ) call stdlib${ii}$_${ci}$lacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ci}$hbevd #:endif #:endfor module subroutine stdlib${ii}$_chbevx( jobz, range, uplo, n, kd, ab, ldab, q, ldq, vl,vu, il, iu, abstol, & !! CHBEVX computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian band matrix A. Eigenvalues and eigenvectors !! can be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. m, w, z, ldz, work, rwork,iwork, ifail, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, kd, ldab, ldq, ldz, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: ab(ldab,*) complex(sp), intent(out) :: q(ldq,*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwk, indrwk, & indwrk, iscale, itmp1, j, jj, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu complex(sp) :: ctmp1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( ldab0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iun ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = real( ctmp1,KIND=sp) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone end if return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if ( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero endif anrm = stdlib${ii}$_clanhb( 'M', uplo, n, kd, ab, ldab, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_clascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_clascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_chbtrd to reduce hermitian band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indwrk = 1_${ik}$ call stdlib${ii}$_chbtrd( jobz, uplo, n, kd, ab, ldab, rwork( indd ),rwork( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_csteqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_scopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_clacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_csteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_cstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_cstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_cstein. do j = 1, m call stdlib${ii}$_ccopy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_cgemv( 'N', n, n, cone, q, ldq, work, 1_${ik}$, czero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iun ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = real( ctmp1,KIND=dp) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone end if return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_zlanhb( 'M', uplo, n, kd, ab, ldab, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_zlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_zlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_zhbtrd to reduce hermitian band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indwrk = 1_${ik}$ call stdlib${ii}$_zhbtrd( jobz, uplo, n, kd, ab, ldab, rwork( indd ),rwork( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_zsteqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_dcopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_zlacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_zsteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_zstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_zstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_zstein. do j = 1, m call stdlib${ii}$_zcopy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_zgemv( 'N', n, n, cone, q, ldq, work, 1_${ik}$, czero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iun ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = real( ctmp1,KIND=${ck}$) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone end if return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_${ci}$lanhb( 'M', uplo, n, kd, ab, ldab, rwork ) if( anrm>zero .and. anrmrmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ci}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ci}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ci}$hbtrd to reduce hermitian band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indwrk = 1_${ik}$ call stdlib${ii}$_${ci}$hbtrd( jobz, uplo, n, kd, ab, ldab, rwork( indd ),rwork( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_${c2ri(ci)}$sterf or stdlib${ii}$_${ci}$steqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_${c2ri(ci)}$stebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_${c2ri(ci)}$copy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_${ci}$lacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${c2ri(ci)}$stebz and, if eigenvectors are desired, stdlib${ii}$_${ci}$stein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_${c2ri(ci)}$stebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_${ci}$stein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ci}$stein. do j = 1, m call stdlib${ii}$_${ci}$copy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'N', n, n, cone, q, ldq, work, 1_${ik}$, czero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*), e(*), taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iinfo, j, ldwrkx, ldwrky, lwkopt, minmn, nb, nbmin, nx, ws ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ nb = max( 1_${ik}$, stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEBRD', ' ', m, n, -1_${ik}$, -1_${ik}$ ) ) lwkopt = ( m+n )*nb work( 1_${ik}$ ) = real( lwkopt,KIND=sp) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=( m+n )*nbmin ) then nb = lwork / ( m+n ) else nb = 1_${ik}$ nx = minmn end if end if end if else nx = minmn end if do i = 1, minmn - nx, nb ! reduce rows and columns i:i+nb-1 to bidiagonal form and return ! the matrices x and y which are needed to update the unreduced ! part of the matrix call stdlib${ii}$_slabrd( m-i+1, n-i+1, nb, a( i, i ), lda, d( i ), e( i ),tauq( i ), & taup( i ), work, ldwrkx,work( ldwrkx*nb+1 ), ldwrky ) ! update the trailing submatrix a(i+nb:m,i+nb:n), using an update ! of the form a := a - v*y**t - x*u**t call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', m-i-nb+1, n-i-nb+1,nb, -one, a( i+& nb, i ), lda,work( ldwrkx*nb+nb+1 ), ldwrky, one,a( i+nb, i+nb ), lda ) call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-i-nb+1, n-i-nb+1,nb, -one, & work( nb+1 ), ldwrkx, a( i, i+nb ), lda,one, a( i+nb, i+nb ), lda ) ! copy diagonal and off-diagonal elements of b back into a if( m>=n ) then do j = i, i + nb - 1 a( j, j ) = d( j ) a( j, j+1 ) = e( j ) end do else do j = i, i + nb - 1 a( j, j ) = d( j ) a( j+1, j ) = e( j ) end do end if end do ! use unblocked code to reduce the remainder of the matrix call stdlib${ii}$_sgebd2( m-i+1, n-i+1, a( i, i ), lda, d( i ), e( i ),tauq( i ), taup( i ), & work, iinfo ) work( 1_${ik}$ ) = ws return end subroutine stdlib${ii}$_sgebrd pure module subroutine stdlib${ii}$_dgebrd( m, n, a, lda, d, e, tauq, taup, work, lwork,info ) !! DGEBRD reduces a general real M-by-N matrix A to upper or lower !! bidiagonal form B by an orthogonal transformation: Q**T * A * P = B. !! If m >= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*), e(*), taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iinfo, j, ldwrkx, ldwrky, lwkopt, minmn, nb, nbmin, nx, ws ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ nb = max( 1_${ik}$, stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEBRD', ' ', m, n, -1_${ik}$, -1_${ik}$ ) ) lwkopt = ( m+n )*nb work( 1_${ik}$ ) = real( lwkopt,KIND=dp) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=( m+n )*nbmin ) then nb = lwork / ( m+n ) else nb = 1_${ik}$ nx = minmn end if end if end if else nx = minmn end if do i = 1, minmn - nx, nb ! reduce rows and columns i:i+nb-1 to bidiagonal form and return ! the matrices x and y which are needed to update the unreduced ! part of the matrix call stdlib${ii}$_dlabrd( m-i+1, n-i+1, nb, a( i, i ), lda, d( i ), e( i ),tauq( i ), & taup( i ), work, ldwrkx,work( ldwrkx*nb+1 ), ldwrky ) ! update the trailing submatrix a(i+nb:m,i+nb:n), using an update ! of the form a := a - v*y**t - x*u**t call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', m-i-nb+1, n-i-nb+1,nb, -one, a( i+& nb, i ), lda,work( ldwrkx*nb+nb+1 ), ldwrky, one,a( i+nb, i+nb ), lda ) call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-i-nb+1, n-i-nb+1,nb, -one, & work( nb+1 ), ldwrkx, a( i, i+nb ), lda,one, a( i+nb, i+nb ), lda ) ! copy diagonal and off-diagonal elements of b back into a if( m>=n ) then do j = i, i + nb - 1 a( j, j ) = d( j ) a( j, j+1 ) = e( j ) end do else do j = i, i + nb - 1 a( j, j ) = d( j ) a( j+1, j ) = e( j ) end do end if end do ! use unblocked code to reduce the remainder of the matrix call stdlib${ii}$_dgebd2( m-i+1, n-i+1, a( i, i ), lda, d( i ), e( i ),tauq( i ), taup( i ), & work, iinfo ) work( 1_${ik}$ ) = ws return end subroutine stdlib${ii}$_dgebrd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gebrd( m, n, a, lda, d, e, tauq, taup, work, lwork,info ) !! DGEBRD: reduces a general real M-by-N matrix A to upper or lower !! bidiagonal form B by an orthogonal transformation: Q**T * A * P = B. !! If m >= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: d(*), e(*), taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iinfo, j, ldwrkx, ldwrky, lwkopt, minmn, nb, nbmin, nx, ws ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ nb = max( 1_${ik}$, stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEBRD', ' ', m, n, -1_${ik}$, -1_${ik}$ ) ) lwkopt = ( m+n )*nb work( 1_${ik}$ ) = real( lwkopt,KIND=${rk}$) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=( m+n )*nbmin ) then nb = lwork / ( m+n ) else nb = 1_${ik}$ nx = minmn end if end if end if else nx = minmn end if do i = 1, minmn - nx, nb ! reduce rows and columns i:i+nb-1 to bidiagonal form and return ! the matrices x and y which are needed to update the unreduced ! part of the matrix call stdlib${ii}$_${ri}$labrd( m-i+1, n-i+1, nb, a( i, i ), lda, d( i ), e( i ),tauq( i ), & taup( i ), work, ldwrkx,work( ldwrkx*nb+1 ), ldwrky ) ! update the trailing submatrix a(i+nb:m,i+nb:n), using an update ! of the form a := a - v*y**t - x*u**t call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', m-i-nb+1, n-i-nb+1,nb, -one, a( i+& nb, i ), lda,work( ldwrkx*nb+nb+1 ), ldwrky, one,a( i+nb, i+nb ), lda ) call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-i-nb+1, n-i-nb+1,nb, -one, & work( nb+1 ), ldwrkx, a( i, i+nb ), lda,one, a( i+nb, i+nb ), lda ) ! copy diagonal and off-diagonal elements of b back into a if( m>=n ) then do j = i, i + nb - 1 a( j, j ) = d( j ) a( j, j+1 ) = e( j ) end do else do j = i, i + nb - 1 a( j, j ) = d( j ) a( j+1, j ) = e( j ) end do end if end do ! use unblocked code to reduce the remainder of the matrix call stdlib${ii}$_${ri}$gebd2( m-i+1, n-i+1, a( i, i ), lda, d( i ), e( i ),tauq( i ), taup( i ), & work, iinfo ) work( 1_${ik}$ ) = ws return end subroutine stdlib${ii}$_${ri}$gebrd #:endif #:endfor pure module subroutine stdlib${ii}$_cgebrd( m, n, a, lda, d, e, tauq, taup, work, lwork,info ) !! CGEBRD reduces a general complex M-by-N matrix A to upper or lower !! bidiagonal form B by a unitary transformation: Q**H * A * P = B. !! If m >= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(sp), intent(out) :: d(*), e(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iinfo, j, ldwrkx, ldwrky, lwkopt, minmn, nb, nbmin, nx, ws ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ nb = max( 1_${ik}$, stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEBRD', ' ', m, n, -1_${ik}$, -1_${ik}$ ) ) lwkopt = ( m+n )*nb work( 1_${ik}$ ) = real( lwkopt,KIND=sp) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=( m+n )*nbmin ) then nb = lwork / ( m+n ) else nb = 1_${ik}$ nx = minmn end if end if end if else nx = minmn end if do i = 1, minmn - nx, nb ! reduce rows and columns i:i+ib-1 to bidiagonal form and return ! the matrices x and y which are needed to update the unreduced ! part of the matrix call stdlib${ii}$_clabrd( m-i+1, n-i+1, nb, a( i, i ), lda, d( i ), e( i ),tauq( i ), & taup( i ), work, ldwrkx,work( ldwrkx*nb+1 ), ldwrky ) ! update the trailing submatrix a(i+ib:m,i+ib:n), using ! an update of the form a := a - v*y**h - x*u**h call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m-i-nb+1,n-i-nb+1, nb, -& cone, a( i+nb, i ), lda,work( ldwrkx*nb+nb+1 ), ldwrky, cone,a( i+nb, i+nb ), lda ) call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-i-nb+1, n-i-nb+1,nb, -cone, & work( nb+1 ), ldwrkx, a( i, i+nb ), lda,cone, a( i+nb, i+nb ), lda ) ! copy diagonal and off-diagonal elements of b back into a if( m>=n ) then do j = i, i + nb - 1 a( j, j ) = d( j ) a( j, j+1 ) = e( j ) end do else do j = i, i + nb - 1 a( j, j ) = d( j ) a( j+1, j ) = e( j ) end do end if end do ! use unblocked code to reduce the remainder of the matrix call stdlib${ii}$_cgebd2( m-i+1, n-i+1, a( i, i ), lda, d( i ), e( i ),tauq( i ), taup( i ), & work, iinfo ) work( 1_${ik}$ ) = ws return end subroutine stdlib${ii}$_cgebrd pure module subroutine stdlib${ii}$_zgebrd( m, n, a, lda, d, e, tauq, taup, work, lwork,info ) !! ZGEBRD reduces a general complex M-by-N matrix A to upper or lower !! bidiagonal form B by a unitary transformation: Q**H * A * P = B. !! If m >= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(dp), intent(out) :: d(*), e(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iinfo, j, ldwrkx, ldwrky, lwkopt, minmn, nb, nbmin, nx, ws ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ nb = max( 1_${ik}$, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEBRD', ' ', m, n, -1_${ik}$, -1_${ik}$ ) ) lwkopt = ( m+n )*nb work( 1_${ik}$ ) = real( lwkopt,KIND=dp) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=( m+n )*nbmin ) then nb = lwork / ( m+n ) else nb = 1_${ik}$ nx = minmn end if end if end if else nx = minmn end if do i = 1, minmn - nx, nb ! reduce rows and columns i:i+ib-1 to bidiagonal form and return ! the matrices x and y which are needed to update the unreduced ! part of the matrix call stdlib${ii}$_zlabrd( m-i+1, n-i+1, nb, a( i, i ), lda, d( i ), e( i ),tauq( i ), & taup( i ), work, ldwrkx,work( ldwrkx*nb+1 ), ldwrky ) ! update the trailing submatrix a(i+ib:m,i+ib:n), using ! an update of the form a := a - v*y**h - x*u**h call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m-i-nb+1,n-i-nb+1, nb, -& cone, a( i+nb, i ), lda,work( ldwrkx*nb+nb+1 ), ldwrky, cone,a( i+nb, i+nb ), lda ) call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-i-nb+1, n-i-nb+1,nb, -cone, & work( nb+1 ), ldwrkx, a( i, i+nb ), lda,cone, a( i+nb, i+nb ), lda ) ! copy diagonal and off-diagonal elements of b back into a if( m>=n ) then do j = i, i + nb - 1 a( j, j ) = d( j ) a( j, j+1 ) = e( j ) end do else do j = i, i + nb - 1 a( j, j ) = d( j ) a( j+1, j ) = e( j ) end do end if end do ! use unblocked code to reduce the remainder of the matrix call stdlib${ii}$_zgebd2( m-i+1, n-i+1, a( i, i ), lda, d( i ), e( i ),tauq( i ), taup( i ), & work, iinfo ) work( 1_${ik}$ ) = ws return end subroutine stdlib${ii}$_zgebrd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gebrd( m, n, a, lda, d, e, tauq, taup, work, lwork,info ) !! ZGEBRD: reduces a general complex M-by-N matrix A to upper or lower !! bidiagonal form B by a unitary transformation: Q**H * A * P = B. !! If m >= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(${ck}$), intent(out) :: d(*), e(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iinfo, j, ldwrkx, ldwrky, lwkopt, minmn, nb, nbmin, nx, ws ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ nb = max( 1_${ik}$, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEBRD', ' ', m, n, -1_${ik}$, -1_${ik}$ ) ) lwkopt = ( m+n )*nb work( 1_${ik}$ ) = real( lwkopt,KIND=${ck}$) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=( m+n )*nbmin ) then nb = lwork / ( m+n ) else nb = 1_${ik}$ nx = minmn end if end if end if else nx = minmn end if do i = 1, minmn - nx, nb ! reduce rows and columns i:i+ib-1 to bidiagonal form and return ! the matrices x and y which are needed to update the unreduced ! part of the matrix call stdlib${ii}$_${ci}$labrd( m-i+1, n-i+1, nb, a( i, i ), lda, d( i ), e( i ),tauq( i ), & taup( i ), work, ldwrkx,work( ldwrkx*nb+1 ), ldwrky ) ! update the trailing submatrix a(i+ib:m,i+ib:n), using ! an update of the form a := a - v*y**h - x*u**h call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m-i-nb+1,n-i-nb+1, nb, -& cone, a( i+nb, i ), lda,work( ldwrkx*nb+nb+1 ), ldwrky, cone,a( i+nb, i+nb ), lda ) call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-i-nb+1, n-i-nb+1,nb, -cone, & work( nb+1 ), ldwrkx, a( i, i+nb ), lda,cone, a( i+nb, i+nb ), lda ) ! copy diagonal and off-diagonal elements of b back into a if( m>=n ) then do j = i, i + nb - 1 a( j, j ) = d( j ) a( j, j+1 ) = e( j ) end do else do j = i, i + nb - 1 a( j, j ) = d( j ) a( j+1, j ) = e( j ) end do end if end do ! use unblocked code to reduce the remainder of the matrix call stdlib${ii}$_${ci}$gebd2( m-i+1, n-i+1, a( i, i ), lda, d( i ), e( i ),tauq( i ), taup( i ), & work, iinfo ) work( 1_${ik}$ ) = ws return end subroutine stdlib${ii}$_${ci}$gebrd #:endif #:endfor pure module subroutine stdlib${ii}$_sgebd2( m, n, a, lda, d, e, tauq, taup, work, info ) !! SGEBD2 reduces a real general m by n matrix A to upper or lower !! bidiagonal form B by an orthogonal transformation: Q**T * A * P = B. !! If m >= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*), e(*), taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! reduce to upper bidiagonal form do i = 1, n ! generate elementary reflector h(i) to annihilate a(i+1:m,i) call stdlib${ii}$_slarfg( m-i+1, a( i, i ), a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = a( i, i ) a( i, i ) = one ! apply h(i) to a(i:m,i+1:n) from the left if( i= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*), e(*), taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! reduce to upper bidiagonal form do i = 1, n ! generate elementary reflector h(i) to annihilate a(i+1:m,i) call stdlib${ii}$_dlarfg( m-i+1, a( i, i ), a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = a( i, i ) a( i, i ) = one ! apply h(i) to a(i:m,i+1:n) from the left if( i= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: d(*), e(*), taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! reduce to upper bidiagonal form do i = 1, n ! generate elementary reflector h(i) to annihilate a(i+1:m,i) call stdlib${ii}$_${ri}$larfg( m-i+1, a( i, i ), a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = a( i, i ) a( i, i ) = one ! apply h(i) to a(i:m,i+1:n) from the left if( i= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(sp), intent(out) :: d(*), e(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(sp) :: alpha ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! reduce to upper bidiagonal form do i = 1, n ! generate elementary reflector h(i) to annihilate a(i+1:m,i) alpha = a( i, i ) call stdlib${ii}$_clarfg( m-i+1, alpha, a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = real( alpha,KIND=sp) a( i, i ) = cone ! apply h(i)**h to a(i:m,i+1:n) from the left if( i= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(dp), intent(out) :: d(*), e(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(dp) :: alpha ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! reduce to upper bidiagonal form do i = 1, n ! generate elementary reflector h(i) to annihilate a(i+1:m,i) alpha = a( i, i ) call stdlib${ii}$_zlarfg( m-i+1, alpha, a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = real( alpha,KIND=dp) a( i, i ) = cone ! apply h(i)**h to a(i:m,i+1:n) from the left if( i= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(${ck}$), intent(out) :: d(*), e(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: taup(*), tauq(*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(${ck}$) :: alpha ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! reduce to upper bidiagonal form do i = 1, n ! generate elementary reflector h(i) to annihilate a(i+1:m,i) alpha = a( i, i ) call stdlib${ii}$_${ci}$larfg( m-i+1, alpha, a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = real( alpha,KIND=${ck}$) a( i, i ) = cone ! apply h(i)**h to a(i:m,i+1:n) from the left if( i0_${ik}$ klu1 = kl + ku + 1_${ik}$ info = 0_${ik}$ if( .not.wantq .and. .not.wantpt .and. .not.stdlib_lsame( vect, 'N' ) )then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ncc<0_${ik}$ ) then info = -4_${ik}$ else if( kl<0_${ik}$ ) then info = -5_${ik}$ else if( ku<0_${ik}$ ) then info = -6_${ik}$ else if( ldab1_${ik}$ ) then ! reduce to upper bidiagonal form if ku > 0; if ku = 0, reduce ! first to lower bidiagonal form and then transform to upper ! bidiagonal if( ku>0_${ik}$ ) then ml0 = 1_${ik}$ mu0 = 2_${ik}$ else ml0 = 2_${ik}$ mu0 = 1_${ik}$ end if ! wherever possible, plane rotations are generated and applied in ! vector operations of length nr over the index set j1:j2:klu1. ! the sines of the plane rotations are stored in work(1:max(m,n)) ! and the cosines in work(max(m,n)+1:2*max(m,n)). mn = max( m, n ) klm = min( m-1, kl ) kun = min( n-1, ku ) kb = klm + kun kb1 = kb + 1_${ik}$ inca = kb1*ldab nr = 0_${ik}$ j1 = klm + 2_${ik}$ j2 = 1_${ik}$ - kun loop_90: do i = 1, minmn ! reduce i-th column and i-th row of matrix to bidiagonal form ml = klm + 1_${ik}$ mu = kun + 1_${ik}$ loop_80: do kk = 1, kb j1 = j1 + kb j2 = j2 + kb ! generate plane rotations to annihilate nonzero elements ! which have been created below the band if( nr>0_${ik}$ )call stdlib${ii}$_slargv( nr, ab( klu1, j1-klm-1 ), inca,work( j1 ), kb1, & work( mn+j1 ), kb1 ) ! apply plane rotations from the left do l = 1, kb if( j2-klm+l-1>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( klu1-l, j1-klm+l-1 ), inca,ab( & klu1-l+1, j1-klm+l-1 ), inca,work( mn+j1 ), work( j1 ), kb1 ) end do if( ml>ml0 ) then if( ml<=m-i+1 ) then ! generate plane rotation to annihilate a(i+ml-1,i) ! within the band, and apply rotation from the left call stdlib${ii}$_slartg( ab( ku+ml-1, i ), ab( ku+ml, i ),work( mn+i+ml-1 ), & work( i+ml-1 ),ra ) ab( ku+ml-1, i ) = ra if( in ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j-1,j+ku) above the band ! and store it in work(n+1:2*n) work( j+kun ) = work( j )*ab( 1_${ik}$, j+kun ) ab( 1_${ik}$, j+kun ) = work( mn+j )*ab( 1_${ik}$, j+kun ) end do ! generate plane rotations to annihilate nonzero elements ! which have been generated above the band if( nr>0_${ik}$ )call stdlib${ii}$_slargv( nr, ab( 1_${ik}$, j1+kun-1 ), inca,work( j1+kun ), kb1,& work( mn+j1+kun ),kb1 ) ! apply plane rotations from the right do l = 1, kb if( j2+l-1>m ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( l+1, j1+kun-1 ), inca,ab( l, j1+& kun ), inca,work( mn+j1+kun ), work( j1+kun ),kb1 ) end do if( ml==ml0 .and. mu>mu0 ) then if( mu<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+mu-1) ! within the band, and apply rotation from the right call stdlib${ii}$_slartg( ab( ku-mu+3, i+mu-2 ),ab( ku-mu+2, i+mu-1 ),work( & mn+i+mu-1 ), work( i+mu-1 ),ra ) ab( ku-mu+3, i+mu-2 ) = ra call stdlib${ii}$_srot( min( kl+mu-2, m-i ),ab( ku-mu+4, i+mu-2 ), 1_${ik}$,ab( ku-& mu+3, i+mu-1 ), 1_${ik}$,work( mn+i+mu-1 ), work( i+mu-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kb1 end if if( wantpt ) then ! accumulate product of plane rotations in p**t do j = j1, j2, kb1 call stdlib${ii}$_srot( n, pt( j+kun-1, 1_${ik}$ ), ldpt,pt( j+kun, 1_${ik}$ ), ldpt, work( & mn+j+kun ),work( j+kun ) ) end do end if if( j2+kb>m ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j+kl+ku,j+ku-1) below the ! band and store it in work(1:n) work( j+kb ) = work( j+kun )*ab( klu1, j+kun ) ab( klu1, j+kun ) = work( mn+j+kun )*ab( klu1, j+kun ) end do if( ml>ml0 ) then ml = ml - 1_${ik}$ else mu = mu - 1_${ik}$ end if end do loop_80 end do loop_90 end if if( ku==0_${ik}$ .and. kl>0_${ik}$ ) then ! a has been reduced to lower bidiagonal form ! transform lower bidiagonal form to upper bidiagonal by applying ! plane rotations from the left, storing diagonal elements in d ! and off-diagonal elements in e do i = 1, min( m-1, n ) call stdlib${ii}$_slartg( ab( 1_${ik}$, i ), ab( 2_${ik}$, i ), rc, rs, ra ) d( i ) = ra if( i0_${ik}$ ) then ! a has been reduced to upper bidiagonal form if( m1_${ik}$ ) then rb = -rs*ab( ku, i ) e( i-1 ) = rc*ab( ku, i ) end if if( wantpt )call stdlib${ii}$_srot( n, pt( i, 1_${ik}$ ), ldpt, pt( m+1, 1_${ik}$ ), ldpt,rc, rs ) end do else ! copy off-diagonal elements to e and diagonal elements to d do i = 1, minmn - 1 e( i ) = ab( ku, i+1 ) end do do i = 1, minmn d( i ) = ab( ku+1, i ) end do end if else ! a is diagonal. set elements of e to zero and copy diagonal ! elements to d. do i = 1, minmn - 1 e( i ) = zero end do do i = 1, minmn d( i ) = ab( 1_${ik}$, i ) end do end if return end subroutine stdlib${ii}$_sgbbrd pure module subroutine stdlib${ii}$_dgbbrd( vect, m, n, ncc, kl, ku, ab, ldab, d, e, q,ldq, pt, ldpt, c, & !! DGBBRD reduces a real general m-by-n band matrix A to upper !! bidiagonal form B by an orthogonal transformation: Q**T * A * P = B. !! The routine computes B, and optionally forms Q or P**T, or computes !! Q**T*C for a given matrix C. ldc, work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldc, ldpt, ldq, m, n, ncc ! Array Arguments real(dp), intent(inout) :: ab(ldab,*), c(ldc,*) real(dp), intent(out) :: d(*), e(*), pt(ldpt,*), q(ldq,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: wantb, wantc, wantpt, wantq integer(${ik}$) :: i, inca, j, j1, j2, kb, kb1, kk, klm, klu1, kun, l, minmn, ml, ml0, mn,& mu, mu0, nr, nrt real(dp) :: ra, rb, rc, rs ! Intrinsic Functions ! Executable Statements ! test the input parameters wantb = stdlib_lsame( vect, 'B' ) wantq = stdlib_lsame( vect, 'Q' ) .or. wantb wantpt = stdlib_lsame( vect, 'P' ) .or. wantb wantc = ncc>0_${ik}$ klu1 = kl + ku + 1_${ik}$ info = 0_${ik}$ if( .not.wantq .and. .not.wantpt .and. .not.stdlib_lsame( vect, 'N' ) )then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ncc<0_${ik}$ ) then info = -4_${ik}$ else if( kl<0_${ik}$ ) then info = -5_${ik}$ else if( ku<0_${ik}$ ) then info = -6_${ik}$ else if( ldab1_${ik}$ ) then ! reduce to upper bidiagonal form if ku > 0; if ku = 0, reduce ! first to lower bidiagonal form and then transform to upper ! bidiagonal if( ku>0_${ik}$ ) then ml0 = 1_${ik}$ mu0 = 2_${ik}$ else ml0 = 2_${ik}$ mu0 = 1_${ik}$ end if ! wherever possible, plane rotations are generated and applied in ! vector operations of length nr over the index set j1:j2:klu1. ! the sines of the plane rotations are stored in work(1:max(m,n)) ! and the cosines in work(max(m,n)+1:2*max(m,n)). mn = max( m, n ) klm = min( m-1, kl ) kun = min( n-1, ku ) kb = klm + kun kb1 = kb + 1_${ik}$ inca = kb1*ldab nr = 0_${ik}$ j1 = klm + 2_${ik}$ j2 = 1_${ik}$ - kun loop_90: do i = 1, minmn ! reduce i-th column and i-th row of matrix to bidiagonal form ml = klm + 1_${ik}$ mu = kun + 1_${ik}$ loop_80: do kk = 1, kb j1 = j1 + kb j2 = j2 + kb ! generate plane rotations to annihilate nonzero elements ! which have been created below the band if( nr>0_${ik}$ )call stdlib${ii}$_dlargv( nr, ab( klu1, j1-klm-1 ), inca,work( j1 ), kb1, & work( mn+j1 ), kb1 ) ! apply plane rotations from the left do l = 1, kb if( j2-klm+l-1>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( klu1-l, j1-klm+l-1 ), inca,ab( & klu1-l+1, j1-klm+l-1 ), inca,work( mn+j1 ), work( j1 ), kb1 ) end do if( ml>ml0 ) then if( ml<=m-i+1 ) then ! generate plane rotation to annihilate a(i+ml-1,i) ! within the band, and apply rotation from the left call stdlib${ii}$_dlartg( ab( ku+ml-1, i ), ab( ku+ml, i ),work( mn+i+ml-1 ), & work( i+ml-1 ),ra ) ab( ku+ml-1, i ) = ra if( in ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j-1,j+ku) above the band ! and store it in work(n+1:2*n) work( j+kun ) = work( j )*ab( 1_${ik}$, j+kun ) ab( 1_${ik}$, j+kun ) = work( mn+j )*ab( 1_${ik}$, j+kun ) end do ! generate plane rotations to annihilate nonzero elements ! which have been generated above the band if( nr>0_${ik}$ )call stdlib${ii}$_dlargv( nr, ab( 1_${ik}$, j1+kun-1 ), inca,work( j1+kun ), kb1,& work( mn+j1+kun ),kb1 ) ! apply plane rotations from the right do l = 1, kb if( j2+l-1>m ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( l+1, j1+kun-1 ), inca,ab( l, j1+& kun ), inca,work( mn+j1+kun ), work( j1+kun ),kb1 ) end do if( ml==ml0 .and. mu>mu0 ) then if( mu<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+mu-1) ! within the band, and apply rotation from the right call stdlib${ii}$_dlartg( ab( ku-mu+3, i+mu-2 ),ab( ku-mu+2, i+mu-1 ),work( & mn+i+mu-1 ), work( i+mu-1 ),ra ) ab( ku-mu+3, i+mu-2 ) = ra call stdlib${ii}$_drot( min( kl+mu-2, m-i ),ab( ku-mu+4, i+mu-2 ), 1_${ik}$,ab( ku-& mu+3, i+mu-1 ), 1_${ik}$,work( mn+i+mu-1 ), work( i+mu-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kb1 end if if( wantpt ) then ! accumulate product of plane rotations in p**t do j = j1, j2, kb1 call stdlib${ii}$_drot( n, pt( j+kun-1, 1_${ik}$ ), ldpt,pt( j+kun, 1_${ik}$ ), ldpt, work( & mn+j+kun ),work( j+kun ) ) end do end if if( j2+kb>m ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j+kl+ku,j+ku-1) below the ! band and store it in work(1:n) work( j+kb ) = work( j+kun )*ab( klu1, j+kun ) ab( klu1, j+kun ) = work( mn+j+kun )*ab( klu1, j+kun ) end do if( ml>ml0 ) then ml = ml - 1_${ik}$ else mu = mu - 1_${ik}$ end if end do loop_80 end do loop_90 end if if( ku==0_${ik}$ .and. kl>0_${ik}$ ) then ! a has been reduced to lower bidiagonal form ! transform lower bidiagonal form to upper bidiagonal by applying ! plane rotations from the left, storing diagonal elements in d ! and off-diagonal elements in e do i = 1, min( m-1, n ) call stdlib${ii}$_dlartg( ab( 1_${ik}$, i ), ab( 2_${ik}$, i ), rc, rs, ra ) d( i ) = ra if( i0_${ik}$ ) then ! a has been reduced to upper bidiagonal form if( m1_${ik}$ ) then rb = -rs*ab( ku, i ) e( i-1 ) = rc*ab( ku, i ) end if if( wantpt )call stdlib${ii}$_drot( n, pt( i, 1_${ik}$ ), ldpt, pt( m+1, 1_${ik}$ ), ldpt,rc, rs ) end do else ! copy off-diagonal elements to e and diagonal elements to d do i = 1, minmn - 1 e( i ) = ab( ku, i+1 ) end do do i = 1, minmn d( i ) = ab( ku+1, i ) end do end if else ! a is diagonal. set elements of e to zero and copy diagonal ! elements to d. do i = 1, minmn - 1 e( i ) = zero end do do i = 1, minmn d( i ) = ab( 1_${ik}$, i ) end do end if return end subroutine stdlib${ii}$_dgbbrd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gbbrd( vect, m, n, ncc, kl, ku, ab, ldab, d, e, q,ldq, pt, ldpt, c, & !! DGBBRD: reduces a real general m-by-n band matrix A to upper !! bidiagonal form B by an orthogonal transformation: Q**T * A * P = B. !! The routine computes B, and optionally forms Q or P**T, or computes !! Q**T*C for a given matrix C. ldc, work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldc, ldpt, ldq, m, n, ncc ! Array Arguments real(${rk}$), intent(inout) :: ab(ldab,*), c(ldc,*) real(${rk}$), intent(out) :: d(*), e(*), pt(ldpt,*), q(ldq,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: wantb, wantc, wantpt, wantq integer(${ik}$) :: i, inca, j, j1, j2, kb, kb1, kk, klm, klu1, kun, l, minmn, ml, ml0, mn,& mu, mu0, nr, nrt real(${rk}$) :: ra, rb, rc, rs ! Intrinsic Functions ! Executable Statements ! test the input parameters wantb = stdlib_lsame( vect, 'B' ) wantq = stdlib_lsame( vect, 'Q' ) .or. wantb wantpt = stdlib_lsame( vect, 'P' ) .or. wantb wantc = ncc>0_${ik}$ klu1 = kl + ku + 1_${ik}$ info = 0_${ik}$ if( .not.wantq .and. .not.wantpt .and. .not.stdlib_lsame( vect, 'N' ) )then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ncc<0_${ik}$ ) then info = -4_${ik}$ else if( kl<0_${ik}$ ) then info = -5_${ik}$ else if( ku<0_${ik}$ ) then info = -6_${ik}$ else if( ldab1_${ik}$ ) then ! reduce to upper bidiagonal form if ku > 0; if ku = 0, reduce ! first to lower bidiagonal form and then transform to upper ! bidiagonal if( ku>0_${ik}$ ) then ml0 = 1_${ik}$ mu0 = 2_${ik}$ else ml0 = 2_${ik}$ mu0 = 1_${ik}$ end if ! wherever possible, plane rotations are generated and applied in ! vector operations of length nr over the index set j1:j2:klu1. ! the sines of the plane rotations are stored in work(1:max(m,n)) ! and the cosines in work(max(m,n)+1:2*max(m,n)). mn = max( m, n ) klm = min( m-1, kl ) kun = min( n-1, ku ) kb = klm + kun kb1 = kb + 1_${ik}$ inca = kb1*ldab nr = 0_${ik}$ j1 = klm + 2_${ik}$ j2 = 1_${ik}$ - kun loop_90: do i = 1, minmn ! reduce i-th column and i-th row of matrix to bidiagonal form ml = klm + 1_${ik}$ mu = kun + 1_${ik}$ loop_80: do kk = 1, kb j1 = j1 + kb j2 = j2 + kb ! generate plane rotations to annihilate nonzero elements ! which have been created below the band if( nr>0_${ik}$ )call stdlib${ii}$_${ri}$largv( nr, ab( klu1, j1-klm-1 ), inca,work( j1 ), kb1, & work( mn+j1 ), kb1 ) ! apply plane rotations from the left do l = 1, kb if( j2-klm+l-1>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( klu1-l, j1-klm+l-1 ), inca,ab( & klu1-l+1, j1-klm+l-1 ), inca,work( mn+j1 ), work( j1 ), kb1 ) end do if( ml>ml0 ) then if( ml<=m-i+1 ) then ! generate plane rotation to annihilate a(i+ml-1,i) ! within the band, and apply rotation from the left call stdlib${ii}$_${ri}$lartg( ab( ku+ml-1, i ), ab( ku+ml, i ),work( mn+i+ml-1 ), & work( i+ml-1 ),ra ) ab( ku+ml-1, i ) = ra if( in ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j-1,j+ku) above the band ! and store it in work(n+1:2*n) work( j+kun ) = work( j )*ab( 1_${ik}$, j+kun ) ab( 1_${ik}$, j+kun ) = work( mn+j )*ab( 1_${ik}$, j+kun ) end do ! generate plane rotations to annihilate nonzero elements ! which have been generated above the band if( nr>0_${ik}$ )call stdlib${ii}$_${ri}$largv( nr, ab( 1_${ik}$, j1+kun-1 ), inca,work( j1+kun ), kb1,& work( mn+j1+kun ),kb1 ) ! apply plane rotations from the right do l = 1, kb if( j2+l-1>m ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( l+1, j1+kun-1 ), inca,ab( l, j1+& kun ), inca,work( mn+j1+kun ), work( j1+kun ),kb1 ) end do if( ml==ml0 .and. mu>mu0 ) then if( mu<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+mu-1) ! within the band, and apply rotation from the right call stdlib${ii}$_${ri}$lartg( ab( ku-mu+3, i+mu-2 ),ab( ku-mu+2, i+mu-1 ),work( & mn+i+mu-1 ), work( i+mu-1 ),ra ) ab( ku-mu+3, i+mu-2 ) = ra call stdlib${ii}$_${ri}$rot( min( kl+mu-2, m-i ),ab( ku-mu+4, i+mu-2 ), 1_${ik}$,ab( ku-& mu+3, i+mu-1 ), 1_${ik}$,work( mn+i+mu-1 ), work( i+mu-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kb1 end if if( wantpt ) then ! accumulate product of plane rotations in p**t do j = j1, j2, kb1 call stdlib${ii}$_${ri}$rot( n, pt( j+kun-1, 1_${ik}$ ), ldpt,pt( j+kun, 1_${ik}$ ), ldpt, work( & mn+j+kun ),work( j+kun ) ) end do end if if( j2+kb>m ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j+kl+ku,j+ku-1) below the ! band and store it in work(1:n) work( j+kb ) = work( j+kun )*ab( klu1, j+kun ) ab( klu1, j+kun ) = work( mn+j+kun )*ab( klu1, j+kun ) end do if( ml>ml0 ) then ml = ml - 1_${ik}$ else mu = mu - 1_${ik}$ end if end do loop_80 end do loop_90 end if if( ku==0_${ik}$ .and. kl>0_${ik}$ ) then ! a has been reduced to lower bidiagonal form ! transform lower bidiagonal form to upper bidiagonal by applying ! plane rotations from the left, storing diagonal elements in d ! and off-diagonal elements in e do i = 1, min( m-1, n ) call stdlib${ii}$_${ri}$lartg( ab( 1_${ik}$, i ), ab( 2_${ik}$, i ), rc, rs, ra ) d( i ) = ra if( i0_${ik}$ ) then ! a has been reduced to upper bidiagonal form if( m1_${ik}$ ) then rb = -rs*ab( ku, i ) e( i-1 ) = rc*ab( ku, i ) end if if( wantpt )call stdlib${ii}$_${ri}$rot( n, pt( i, 1_${ik}$ ), ldpt, pt( m+1, 1_${ik}$ ), ldpt,rc, rs ) end do else ! copy off-diagonal elements to e and diagonal elements to d do i = 1, minmn - 1 e( i ) = ab( ku, i+1 ) end do do i = 1, minmn d( i ) = ab( ku+1, i ) end do end if else ! a is diagonal. set elements of e to zero and copy diagonal ! elements to d. do i = 1, minmn - 1 e( i ) = zero end do do i = 1, minmn d( i ) = ab( 1_${ik}$, i ) end do end if return end subroutine stdlib${ii}$_${ri}$gbbrd #:endif #:endfor pure module subroutine stdlib${ii}$_cgbbrd( vect, m, n, ncc, kl, ku, ab, ldab, d, e, q,ldq, pt, ldpt, c, & !! CGBBRD reduces a complex general m-by-n band matrix A to real upper !! bidiagonal form B by a unitary transformation: Q**H * A * P = B. !! The routine computes B, and optionally forms Q or P**H, or computes !! Q**H*C for a given matrix C. ldc, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldc, ldpt, ldq, m, n, ncc ! Array Arguments real(sp), intent(out) :: d(*), e(*), rwork(*) complex(sp), intent(inout) :: ab(ldab,*), c(ldc,*) complex(sp), intent(out) :: pt(ldpt,*), q(ldq,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: wantb, wantc, wantpt, wantq integer(${ik}$) :: i, inca, j, j1, j2, kb, kb1, kk, klm, klu1, kun, l, minmn, ml, ml0, mu,& mu0, nr, nrt real(sp) :: abst, rc complex(sp) :: ra, rb, rs, t ! Intrinsic Functions ! Executable Statements ! test the input parameters wantb = stdlib_lsame( vect, 'B' ) wantq = stdlib_lsame( vect, 'Q' ) .or. wantb wantpt = stdlib_lsame( vect, 'P' ) .or. wantb wantc = ncc>0_${ik}$ klu1 = kl + ku + 1_${ik}$ info = 0_${ik}$ if( .not.wantq .and. .not.wantpt .and. .not.stdlib_lsame( vect, 'N' ) )then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ncc<0_${ik}$ ) then info = -4_${ik}$ else if( kl<0_${ik}$ ) then info = -5_${ik}$ else if( ku<0_${ik}$ ) then info = -6_${ik}$ else if( ldab1_${ik}$ ) then ! reduce to upper bidiagonal form if ku > 0; if ku = 0, reduce ! first to lower bidiagonal form and then transform to upper ! bidiagonal if( ku>0_${ik}$ ) then ml0 = 1_${ik}$ mu0 = 2_${ik}$ else ml0 = 2_${ik}$ mu0 = 1_${ik}$ end if ! wherever possible, plane rotations are generated and applied in ! vector operations of length nr over the index set j1:j2:klu1. ! the complex sines of the plane rotations are stored in work, ! and the real cosines in rwork. klm = min( m-1, kl ) kun = min( n-1, ku ) kb = klm + kun kb1 = kb + 1_${ik}$ inca = kb1*ldab nr = 0_${ik}$ j1 = klm + 2_${ik}$ j2 = 1_${ik}$ - kun loop_90: do i = 1, minmn ! reduce i-th column and i-th row of matrix to bidiagonal form ml = klm + 1_${ik}$ mu = kun + 1_${ik}$ loop_80: do kk = 1, kb j1 = j1 + kb j2 = j2 + kb ! generate plane rotations to annihilate nonzero elements ! which have been created below the band if( nr>0_${ik}$ )call stdlib${ii}$_clargv( nr, ab( klu1, j1-klm-1 ), inca,work( j1 ), kb1, & rwork( j1 ), kb1 ) ! apply plane rotations from the left do l = 1, kb if( j2-klm+l-1>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( klu1-l, j1-klm+l-1 ), inca,ab( & klu1-l+1, j1-klm+l-1 ), inca,rwork( j1 ), work( j1 ), kb1 ) end do if( ml>ml0 ) then if( ml<=m-i+1 ) then ! generate plane rotation to annihilate a(i+ml-1,i) ! within the band, and apply rotation from the left call stdlib${ii}$_clartg( ab( ku+ml-1, i ), ab( ku+ml, i ),rwork( i+ml-1 ), & work( i+ml-1 ), ra ) ab( ku+ml-1, i ) = ra if( in ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j-1,j+ku) above the band ! and store it in work(n+1:2*n) work( j+kun ) = work( j )*ab( 1_${ik}$, j+kun ) ab( 1_${ik}$, j+kun ) = rwork( j )*ab( 1_${ik}$, j+kun ) end do ! generate plane rotations to annihilate nonzero elements ! which have been generated above the band if( nr>0_${ik}$ )call stdlib${ii}$_clargv( nr, ab( 1_${ik}$, j1+kun-1 ), inca,work( j1+kun ), kb1,& rwork( j1+kun ),kb1 ) ! apply plane rotations from the right do l = 1, kb if( j2+l-1>m ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( l+1, j1+kun-1 ), inca,ab( l, j1+& kun ), inca,rwork( j1+kun ), work( j1+kun ), kb1 ) end do if( ml==ml0 .and. mu>mu0 ) then if( mu<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+mu-1) ! within the band, and apply rotation from the right call stdlib${ii}$_clartg( ab( ku-mu+3, i+mu-2 ),ab( ku-mu+2, i+mu-1 ),rwork( & i+mu-1 ), work( i+mu-1 ), ra ) ab( ku-mu+3, i+mu-2 ) = ra call stdlib${ii}$_crot( min( kl+mu-2, m-i ),ab( ku-mu+4, i+mu-2 ), 1_${ik}$,ab( ku-& mu+3, i+mu-1 ), 1_${ik}$,rwork( i+mu-1 ), work( i+mu-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kb1 end if if( wantpt ) then ! accumulate product of plane rotations in p**h do j = j1, j2, kb1 call stdlib${ii}$_crot( n, pt( j+kun-1, 1_${ik}$ ), ldpt,pt( j+kun, 1_${ik}$ ), ldpt, rwork(& j+kun ),conjg( work( j+kun ) ) ) end do end if if( j2+kb>m ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j+kl+ku,j+ku-1) below the ! band and store it in work(1:n) work( j+kb ) = work( j+kun )*ab( klu1, j+kun ) ab( klu1, j+kun ) = rwork( j+kun )*ab( klu1, j+kun ) end do if( ml>ml0 ) then ml = ml - 1_${ik}$ else mu = mu - 1_${ik}$ end if end do loop_80 end do loop_90 end if if( ku==0_${ik}$ .and. kl>0_${ik}$ ) then ! a has been reduced to complex lower bidiagonal form ! transform lower bidiagonal form to upper bidiagonal by applying ! plane rotations from the left, overwriting superdiagonal ! elements on subdiagonal elements do i = 1, min( m-1, n ) call stdlib${ii}$_clartg( ab( 1_${ik}$, i ), ab( 2_${ik}$, i ), rc, rs, ra ) ab( 1_${ik}$, i ) = ra if( i0_${ik}$ .and. m1_${ik}$ ) then rb = -conjg( rs )*ab( ku, i ) ab( ku, i ) = rc*ab( ku, i ) end if if( wantpt )call stdlib${ii}$_crot( n, pt( i, 1_${ik}$ ), ldpt, pt( m+1, 1_${ik}$ ), ldpt,rc, & conjg( rs ) ) end do end if end if ! make diagonal and superdiagonal elements real, storing them in d ! and e t = ab( ku+1, 1_${ik}$ ) loop_120: do i = 1, minmn abst = abs( t ) d( i ) = abst if( abst/=zero ) then t = t / abst else t = cone end if if( wantq )call stdlib${ii}$_cscal( m, t, q( 1_${ik}$, i ), 1_${ik}$ ) if( wantc )call stdlib${ii}$_cscal( ncc, conjg( t ), c( i, 1_${ik}$ ), ldc ) if( i0_${ik}$ klu1 = kl + ku + 1_${ik}$ info = 0_${ik}$ if( .not.wantq .and. .not.wantpt .and. .not.stdlib_lsame( vect, 'N' ) )then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ncc<0_${ik}$ ) then info = -4_${ik}$ else if( kl<0_${ik}$ ) then info = -5_${ik}$ else if( ku<0_${ik}$ ) then info = -6_${ik}$ else if( ldab1_${ik}$ ) then ! reduce to upper bidiagonal form if ku > 0; if ku = 0, reduce ! first to lower bidiagonal form and then transform to upper ! bidiagonal if( ku>0_${ik}$ ) then ml0 = 1_${ik}$ mu0 = 2_${ik}$ else ml0 = 2_${ik}$ mu0 = 1_${ik}$ end if ! wherever possible, plane rotations are generated and applied in ! vector operations of length nr over the index set j1:j2:klu1. ! the complex sines of the plane rotations are stored in work, ! and the real cosines in rwork. klm = min( m-1, kl ) kun = min( n-1, ku ) kb = klm + kun kb1 = kb + 1_${ik}$ inca = kb1*ldab nr = 0_${ik}$ j1 = klm + 2_${ik}$ j2 = 1_${ik}$ - kun loop_90: do i = 1, minmn ! reduce i-th column and i-th row of matrix to bidiagonal form ml = klm + 1_${ik}$ mu = kun + 1_${ik}$ loop_80: do kk = 1, kb j1 = j1 + kb j2 = j2 + kb ! generate plane rotations to annihilate nonzero elements ! which have been created below the band if( nr>0_${ik}$ )call stdlib${ii}$_zlargv( nr, ab( klu1, j1-klm-1 ), inca,work( j1 ), kb1, & rwork( j1 ), kb1 ) ! apply plane rotations from the left do l = 1, kb if( j2-klm+l-1>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( klu1-l, j1-klm+l-1 ), inca,ab( & klu1-l+1, j1-klm+l-1 ), inca,rwork( j1 ), work( j1 ), kb1 ) end do if( ml>ml0 ) then if( ml<=m-i+1 ) then ! generate plane rotation to annihilate a(i+ml-1,i) ! within the band, and apply rotation from the left call stdlib${ii}$_zlartg( ab( ku+ml-1, i ), ab( ku+ml, i ),rwork( i+ml-1 ), & work( i+ml-1 ), ra ) ab( ku+ml-1, i ) = ra if( in ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j-1,j+ku) above the band ! and store it in work(n+1:2*n) work( j+kun ) = work( j )*ab( 1_${ik}$, j+kun ) ab( 1_${ik}$, j+kun ) = rwork( j )*ab( 1_${ik}$, j+kun ) end do ! generate plane rotations to annihilate nonzero elements ! which have been generated above the band if( nr>0_${ik}$ )call stdlib${ii}$_zlargv( nr, ab( 1_${ik}$, j1+kun-1 ), inca,work( j1+kun ), kb1,& rwork( j1+kun ),kb1 ) ! apply plane rotations from the right do l = 1, kb if( j2+l-1>m ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( l+1, j1+kun-1 ), inca,ab( l, j1+& kun ), inca,rwork( j1+kun ), work( j1+kun ), kb1 ) end do if( ml==ml0 .and. mu>mu0 ) then if( mu<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+mu-1) ! within the band, and apply rotation from the right call stdlib${ii}$_zlartg( ab( ku-mu+3, i+mu-2 ),ab( ku-mu+2, i+mu-1 ),rwork( & i+mu-1 ), work( i+mu-1 ), ra ) ab( ku-mu+3, i+mu-2 ) = ra call stdlib${ii}$_zrot( min( kl+mu-2, m-i ),ab( ku-mu+4, i+mu-2 ), 1_${ik}$,ab( ku-& mu+3, i+mu-1 ), 1_${ik}$,rwork( i+mu-1 ), work( i+mu-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kb1 end if if( wantpt ) then ! accumulate product of plane rotations in p**h do j = j1, j2, kb1 call stdlib${ii}$_zrot( n, pt( j+kun-1, 1_${ik}$ ), ldpt,pt( j+kun, 1_${ik}$ ), ldpt, rwork(& j+kun ),conjg( work( j+kun ) ) ) end do end if if( j2+kb>m ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j+kl+ku,j+ku-1) below the ! band and store it in work(1:n) work( j+kb ) = work( j+kun )*ab( klu1, j+kun ) ab( klu1, j+kun ) = rwork( j+kun )*ab( klu1, j+kun ) end do if( ml>ml0 ) then ml = ml - 1_${ik}$ else mu = mu - 1_${ik}$ end if end do loop_80 end do loop_90 end if if( ku==0_${ik}$ .and. kl>0_${ik}$ ) then ! a has been reduced to complex lower bidiagonal form ! transform lower bidiagonal form to upper bidiagonal by applying ! plane rotations from the left, overwriting superdiagonal ! elements on subdiagonal elements do i = 1, min( m-1, n ) call stdlib${ii}$_zlartg( ab( 1_${ik}$, i ), ab( 2_${ik}$, i ), rc, rs, ra ) ab( 1_${ik}$, i ) = ra if( i0_${ik}$ .and. m1_${ik}$ ) then rb = -conjg( rs )*ab( ku, i ) ab( ku, i ) = rc*ab( ku, i ) end if if( wantpt )call stdlib${ii}$_zrot( n, pt( i, 1_${ik}$ ), ldpt, pt( m+1, 1_${ik}$ ), ldpt,rc, & conjg( rs ) ) end do end if end if ! make diagonal and superdiagonal elements real, storing them in d ! and e t = ab( ku+1, 1_${ik}$ ) loop_120: do i = 1, minmn abst = abs( t ) d( i ) = abst if( abst/=zero ) then t = t / abst else t = cone end if if( wantq )call stdlib${ii}$_zscal( m, t, q( 1_${ik}$, i ), 1_${ik}$ ) if( wantc )call stdlib${ii}$_zscal( ncc, conjg( t ), c( i, 1_${ik}$ ), ldc ) if( i0_${ik}$ klu1 = kl + ku + 1_${ik}$ info = 0_${ik}$ if( .not.wantq .and. .not.wantpt .and. .not.stdlib_lsame( vect, 'N' ) )then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ncc<0_${ik}$ ) then info = -4_${ik}$ else if( kl<0_${ik}$ ) then info = -5_${ik}$ else if( ku<0_${ik}$ ) then info = -6_${ik}$ else if( ldab1_${ik}$ ) then ! reduce to upper bidiagonal form if ku > 0; if ku = 0, reduce ! first to lower bidiagonal form and then transform to upper ! bidiagonal if( ku>0_${ik}$ ) then ml0 = 1_${ik}$ mu0 = 2_${ik}$ else ml0 = 2_${ik}$ mu0 = 1_${ik}$ end if ! wherever possible, plane rotations are generated and applied in ! vector operations of length nr over the index set j1:j2:klu1. ! the complex sines of the plane rotations are stored in work, ! and the real cosines in rwork. klm = min( m-1, kl ) kun = min( n-1, ku ) kb = klm + kun kb1 = kb + 1_${ik}$ inca = kb1*ldab nr = 0_${ik}$ j1 = klm + 2_${ik}$ j2 = 1_${ik}$ - kun loop_90: do i = 1, minmn ! reduce i-th column and i-th row of matrix to bidiagonal form ml = klm + 1_${ik}$ mu = kun + 1_${ik}$ loop_80: do kk = 1, kb j1 = j1 + kb j2 = j2 + kb ! generate plane rotations to annihilate nonzero elements ! which have been created below the band if( nr>0_${ik}$ )call stdlib${ii}$_${ci}$largv( nr, ab( klu1, j1-klm-1 ), inca,work( j1 ), kb1, & rwork( j1 ), kb1 ) ! apply plane rotations from the left do l = 1, kb if( j2-klm+l-1>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( klu1-l, j1-klm+l-1 ), inca,ab( & klu1-l+1, j1-klm+l-1 ), inca,rwork( j1 ), work( j1 ), kb1 ) end do if( ml>ml0 ) then if( ml<=m-i+1 ) then ! generate plane rotation to annihilate a(i+ml-1,i) ! within the band, and apply rotation from the left call stdlib${ii}$_${ci}$lartg( ab( ku+ml-1, i ), ab( ku+ml, i ),rwork( i+ml-1 ), & work( i+ml-1 ), ra ) ab( ku+ml-1, i ) = ra if( in ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j-1,j+ku) above the band ! and store it in work(n+1:2*n) work( j+kun ) = work( j )*ab( 1_${ik}$, j+kun ) ab( 1_${ik}$, j+kun ) = rwork( j )*ab( 1_${ik}$, j+kun ) end do ! generate plane rotations to annihilate nonzero elements ! which have been generated above the band if( nr>0_${ik}$ )call stdlib${ii}$_${ci}$largv( nr, ab( 1_${ik}$, j1+kun-1 ), inca,work( j1+kun ), kb1,& rwork( j1+kun ),kb1 ) ! apply plane rotations from the right do l = 1, kb if( j2+l-1>m ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( l+1, j1+kun-1 ), inca,ab( l, j1+& kun ), inca,rwork( j1+kun ), work( j1+kun ), kb1 ) end do if( ml==ml0 .and. mu>mu0 ) then if( mu<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+mu-1) ! within the band, and apply rotation from the right call stdlib${ii}$_${ci}$lartg( ab( ku-mu+3, i+mu-2 ),ab( ku-mu+2, i+mu-1 ),rwork( & i+mu-1 ), work( i+mu-1 ), ra ) ab( ku-mu+3, i+mu-2 ) = ra call stdlib${ii}$_${ci}$rot( min( kl+mu-2, m-i ),ab( ku-mu+4, i+mu-2 ), 1_${ik}$,ab( ku-& mu+3, i+mu-1 ), 1_${ik}$,rwork( i+mu-1 ), work( i+mu-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kb1 end if if( wantpt ) then ! accumulate product of plane rotations in p**h do j = j1, j2, kb1 call stdlib${ii}$_${ci}$rot( n, pt( j+kun-1, 1_${ik}$ ), ldpt,pt( j+kun, 1_${ik}$ ), ldpt, rwork(& j+kun ),conjg( work( j+kun ) ) ) end do end if if( j2+kb>m ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kb1 end if do j = j1, j2, kb1 ! create nonzero element a(j+kl+ku,j+ku-1) below the ! band and store it in work(1:n) work( j+kb ) = work( j+kun )*ab( klu1, j+kun ) ab( klu1, j+kun ) = rwork( j+kun )*ab( klu1, j+kun ) end do if( ml>ml0 ) then ml = ml - 1_${ik}$ else mu = mu - 1_${ik}$ end if end do loop_80 end do loop_90 end if if( ku==0_${ik}$ .and. kl>0_${ik}$ ) then ! a has been reduced to complex lower bidiagonal form ! transform lower bidiagonal form to upper bidiagonal by applying ! plane rotations from the left, overwriting superdiagonal ! elements on subdiagonal elements do i = 1, min( m-1, n ) call stdlib${ii}$_${ci}$lartg( ab( 1_${ik}$, i ), ab( 2_${ik}$, i ), rc, rs, ra ) ab( 1_${ik}$, i ) = ra if( i0_${ik}$ .and. m1_${ik}$ ) then rb = -conjg( rs )*ab( ku, i ) ab( ku, i ) = rc*ab( ku, i ) end if if( wantpt )call stdlib${ii}$_${ci}$rot( n, pt( i, 1_${ik}$ ), ldpt, pt( m+1, 1_${ik}$ ), ldpt,rc, & conjg( rs ) ) end do end if end if ! make diagonal and superdiagonal elements real, storing them in d ! and e t = ab( ku+1, 1_${ik}$ ) loop_120: do i = 1, minmn abst = abs( t ) d( i ) = abst if( abst/=zero ) then t = t / abst else t = cone end if if( wantq )call stdlib${ii}$_${ci}$scal( m, t, q( 1_${ik}$, i ), 1_${ik}$ ) if( wantc )call stdlib${ii}$_${ci}$scal( ncc, conjg( t ), c( i, 1_${ik}$ ), ldc ) if( im ) ) then info = -3_${ik}$ else if( lda sqrt(overflow_threshold), and ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_snrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_snrm2 is available, the if-then-else ! below should read "aapp = stdlib${ii}$_snrm2( m, a(1,p), 1 ) * d(p)". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_snrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else temp1 = zero aapp = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp )*d( p ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_sdot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_scopy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, d( p ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_sdot( m, work, 1_${ik}$, a( 1_${ik}$, q ),1_${ik}$ )*d( q ) / & aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_sdot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_scopy( m, a( 1_${ik}$, q ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, d( q ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_sdot( m, work, 1_${ik}$, a( 1_${ik}$, p ),1_${ik}$ )*d( p ) / & aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then ! Rotate ! rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq ) / aapq if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*d( p ) / d( q ) fastr( 4_${ik}$ ) = -t*d( q ) / d( p ) call stdlib${ii}$_srotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_srotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = d( p ) / d( q ) aqoap = d( q ) / d( p ) if( d( p )>=one ) then if( d( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap d( p ) = d( p )*cs d( q ) = d( q )*cs call stdlib${ii}$_srotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_srotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_saxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if end if else if( d( q )>=one ) then call stdlib${ii}$_saxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if else if( d( p )>=d( q ) ) then call stdlib${ii}$_saxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_saxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_scopy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, work, lda, & ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) temp1 = -aapq*d( p ) / d( q ) call stdlib${ii}$_saxpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_snrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*d( q ) else t = zero aaqq = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*d( q ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_snrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else t = zero aapp = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*d( p ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ........................................................ ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! Safe Gram Matrix Computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_sdot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_scopy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, d( p ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_sdot( m, work, 1_${ik}$, a( 1_${ik}$, q ),1_${ik}$ )*d( q ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_sdot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_scopy( m, a( 1_${ik}$, q ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, d( q ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_sdot( m, work, 1_${ik}$, a( 1_${ik}$, p ),1_${ik}$ )*d( p ) / & aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then notrot = 0_${ik}$ ! rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq ) / aapq if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*d( p ) / d( q ) fastr( 4_${ik}$ ) = -t*d( q ) / d( p ) call stdlib${ii}$_srotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_srotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = d( p ) / d( q ) aqoap = d( q ) / d( p ) if( d( p )>=one ) then if( d( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap d( p ) = d( p )*cs d( q ) = d( q )*cs call stdlib${ii}$_srotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_srotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_saxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_saxpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if d( p ) = d( p )*cs d( q ) = d( q ) / cs end if else if( d( q )>=one ) then call stdlib${ii}$_saxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_saxpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if d( p ) = d( p ) / cs d( q ) = d( q )*cs else if( d( p )>=d( q ) ) then call stdlib${ii}$_saxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_saxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else if( aapp>aaqq ) then call stdlib${ii}$_scopy( m, a( 1_${ik}$, p ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) temp1 = -aapq*d( p ) / d( q ) call stdlib${ii}$_saxpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_scopy( m, a( 1_${ik}$, q ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) temp1 = -aapq*d( q ) / d( p ) call stdlib${ii}$_saxpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q) ! .. recompute sva(q) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_snrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*d( q ) else t = zero aaqq = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*d( q ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_snrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else t = zero aapp = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*d( p ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_snrm2( m, a( 1_${ik}$, n ), 1_${ik}$ )*d( n ) else t = zero aapp = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp )*d( n ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:) reaching this point means that the procedure has completed the given ! number of iterations. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means that during the i-th sweep all pivots were ! below the given tolerance, causing early exit. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector d. do p = 1, n - 1 q = stdlib${ii}$_isamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = d( p ) d( p ) = d( q ) d( q ) = temp1 call stdlib${ii}$_sswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_sswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_sgsvj0 pure module subroutine stdlib${ii}$_dgsvj0( jobv, m, n, a, lda, d, sva, mv, v, ldv, eps,sfmin, tol, & !! DGSVJ0 is called from DGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as DGESVJ does, but !! it does not check convergence (stopping criterion). Few tuning !! parameters (marked by [TP]) are available for the implementer. nsweep, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n, nsweep real(dp), intent(in) :: eps, sfmin, tol character, intent(in) :: jobv ! Array Arguments real(dp), intent(inout) :: a(lda,*), sva(n), d(n), v(ldv,*) real(dp), intent(out) :: work(lwork) ! ===================================================================== ! Local Scalars real(dp) :: aapp, aapp0, aapq, aaqq, apoaq, aqoap, big, bigtheta, cs, mxaapq, mxsinj, & rootbig, rooteps, rootsfmin, roottol, small, sn, t, temp1, theta, thsign integer(${ik}$) :: blskip, emptsw, i, ibr, ierr, igl, ijblsk, ir1, iswrot, jbc, jgl, kbl, & lkahead, mvl, nbl, notrot, p, pskipped, q, rowskip, swband logical(lk) :: applv, rotok, rsvec ! Local Arrays real(dp) :: fastr(5_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. applv = stdlib_lsame( jobv, 'A' ) rsvec = stdlib_lsame( jobv, 'V' ) if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -3_${ik}$ else if( lda sqrt(overflow_threshold), and ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_dnrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_dnrm2 is available, the if-then-else ! below should read "aapp = stdlib${ii}$_dnrm2( m, a(1,p), 1 ) * d(p)". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else temp1 = zero aapp = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp )*d( p ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_ddot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, d( p ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_ddot( m, work, 1_${ik}$, a( 1_${ik}$, q ),1_${ik}$ )*d( q ) / & aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_ddot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, q ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, d( q ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_ddot( m, work, 1_${ik}$, a( 1_${ik}$, p ),1_${ik}$ )*d( p ) / & aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then ! Rotate ! rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/aapq if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*d( p ) / d( q ) fastr( 4_${ik}$ ) = -t*d( q ) / d( p ) call stdlib${ii}$_drotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_drotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = d( p ) / d( q ) aqoap = d( q ) / d( p ) if( d( p )>=one ) then if( d( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap d( p ) = d( p )*cs d( q ) = d( q )*cs call stdlib${ii}$_drotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_drotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_daxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if end if else if( d( q )>=one ) then call stdlib${ii}$_daxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if else if( d( p )>=d( q ) ) then call stdlib${ii}$_daxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_daxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_dcopy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, work, lda, & ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) temp1 = -aapq*d( p ) / d( q ) call stdlib${ii}$_daxpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*d( q ) else t = zero aaqq = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*d( q ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else t = zero aapp = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*d( p ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ........................................................ ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! -#- m x 2 jacobi svd -#- ! -#- safe gram matrix computation -#- if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_ddot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, d( p ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_ddot( m, work, 1_${ik}$, a( 1_${ik}$, q ),1_${ik}$ )*d( q ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_ddot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, q ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, d( q ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_ddot( m, work, 1_${ik}$, a( 1_${ik}$, p ),1_${ik}$ )*d( p ) / & aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then notrot = 0_${ik}$ ! rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/aapq if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*d( p ) / d( q ) fastr( 4_${ik}$ ) = -t*d( q ) / d( p ) call stdlib${ii}$_drotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_drotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = d( p ) / d( q ) aqoap = d( q ) / d( p ) if( d( p )>=one ) then if( d( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap d( p ) = d( p )*cs d( q ) = d( q )*cs call stdlib${ii}$_drotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_drotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_daxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_daxpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if d( p ) = d( p )*cs d( q ) = d( q ) / cs end if else if( d( q )>=one ) then call stdlib${ii}$_daxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_daxpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if d( p ) = d( p ) / cs d( q ) = d( q )*cs else if( d( p )>=d( q ) ) then call stdlib${ii}$_daxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_daxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else if( aapp>aaqq ) then call stdlib${ii}$_dcopy( m, a( 1_${ik}$, p ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) temp1 = -aapq*d( p ) / d( q ) call stdlib${ii}$_daxpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, q ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) temp1 = -aapq*d( q ) / d( p ) call stdlib${ii}$_daxpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q) ! .. recompute sva(q) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*d( q ) else t = zero aaqq = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*d( q ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else t = zero aapp = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*d( p ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, n ), 1_${ik}$ )*d( n ) else t = zero aapp = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp )*d( n ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:) reaching this point means that the procedure has completed the given ! number of iterations. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means that during the i-th sweep all pivots were ! below the given tolerance, causing early exit. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector d. do p = 1, n - 1 q = stdlib${ii}$_idamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = d( p ) d( p ) = d( q ) d( q ) = temp1 call stdlib${ii}$_dswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_dswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_dgsvj0 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gsvj0( jobv, m, n, a, lda, d, sva, mv, v, ldv, eps,sfmin, tol, & !! DGSVJ0: is called from DGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as DGESVJ does, but !! it does not check convergence (stopping criterion). Few tuning !! parameters (marked by [TP]) are available for the implementer. nsweep, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n, nsweep real(${rk}$), intent(in) :: eps, sfmin, tol character, intent(in) :: jobv ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), sva(n), d(n), v(ldv,*) real(${rk}$), intent(out) :: work(lwork) ! ===================================================================== ! Local Scalars real(${rk}$) :: aapp, aapp0, aapq, aaqq, apoaq, aqoap, big, bigtheta, cs, mxaapq, mxsinj, & rootbig, rooteps, rootsfmin, roottol, small, sn, t, temp1, theta, thsign integer(${ik}$) :: blskip, emptsw, i, ibr, ierr, igl, ijblsk, ir1, iswrot, jbc, jgl, kbl, & lkahead, mvl, nbl, notrot, p, pskipped, q, rowskip, swband logical(lk) :: applv, rotok, rsvec ! Local Arrays real(${rk}$) :: fastr(5_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. applv = stdlib_lsame( jobv, 'A' ) rsvec = stdlib_lsame( jobv, 'V' ) if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -3_${ik}$ else if( lda sqrt(overflow_threshold), and ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_${ri}$nrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_${ri}$nrm2 is available, the if-then-else ! below should read "aapp = stdlib${ii}$_${ri}$nrm2( m, a(1,p), 1 ) * d(p)". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else temp1 = zero aapp = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp )*d( p ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_${ri}$dot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, d( p ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_${ri}$dot( m, work, 1_${ik}$, a( 1_${ik}$, q ),1_${ik}$ )*d( q ) / & aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_${ri}$dot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, q ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, d( q ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_${ri}$dot( m, work, 1_${ik}$, a( 1_${ik}$, p ),1_${ik}$ )*d( p ) / & aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then ! Rotate ! rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/aapq if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*d( p ) / d( q ) fastr( 4_${ik}$ ) = -t*d( q ) / d( p ) call stdlib${ii}$_${ri}$rotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_${ri}$rotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = d( p ) / d( q ) aqoap = d( q ) / d( p ) if( d( p )>=one ) then if( d( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap d( p ) = d( p )*cs d( q ) = d( q )*cs call stdlib${ii}$_${ri}$rotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_${ri}$rotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_${ri}$axpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if end if else if( d( q )>=one ) then call stdlib${ii}$_${ri}$axpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if else if( d( p )>=d( q ) ) then call stdlib${ii}$_${ri}$axpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_${ri}$axpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, work, lda, & ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) temp1 = -aapq*d( p ) / d( q ) call stdlib${ii}$_${ri}$axpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*d( q ) else t = zero aaqq = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*d( q ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else t = zero aapp = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*d( p ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ........................................................ ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! -#- m x 2 jacobi svd -#- ! -#- safe gram matrix computation -#- if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_${ri}$dot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, d( p ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_${ri}$dot( m, work, 1_${ik}$, a( 1_${ik}$, q ),1_${ik}$ )*d( q ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_${ri}$dot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, q ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, d( q ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_${ri}$dot( m, work, 1_${ik}$, a( 1_${ik}$, p ),1_${ik}$ )*d( p ) / & aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then notrot = 0_${ik}$ ! rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/aapq if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*d( p ) / d( q ) fastr( 4_${ik}$ ) = -t*d( q ) / d( p ) call stdlib${ii}$_${ri}$rotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_${ri}$rotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = d( p ) / d( q ) aqoap = d( q ) / d( p ) if( d( p )>=one ) then if( d( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap d( p ) = d( p )*cs d( q ) = d( q )*cs call stdlib${ii}$_${ri}$rotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_${ri}$rotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_${ri}$axpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if d( p ) = d( p )*cs d( q ) = d( q ) / cs end if else if( d( q )>=one ) then call stdlib${ii}$_${ri}$axpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if d( p ) = d( p ) / cs d( q ) = d( q )*cs else if( d( p )>=d( q ) ) then call stdlib${ii}$_${ri}$axpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_${ri}$axpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else if( aapp>aaqq ) then call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, p ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) temp1 = -aapq*d( p ) / d( q ) call stdlib${ii}$_${ri}$axpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, q ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) temp1 = -aapq*d( q ) / d( p ) call stdlib${ii}$_${ri}$axpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q) ! .. recompute sva(q) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*d( q ) else t = zero aaqq = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*d( q ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else t = zero aapp = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*d( p ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, n ), 1_${ik}$ )*d( n ) else t = zero aapp = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp )*d( n ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:) reaching this point means that the procedure has completed the given ! number of iterations. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means that during the i-th sweep all pivots were ! below the given tolerance, causing early exit. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector d. do p = 1, n - 1 q = stdlib${ii}$_i${ri}$amax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = d( p ) d( p ) = d( q ) d( q ) = temp1 call stdlib${ii}$_${ri}$swap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_${ri}$swap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_${ri}$gsvj0 #:endif #:endfor pure module subroutine stdlib${ii}$_cgsvj0( jobv, m, n, a, lda, d, sva, mv, v, ldv, eps,sfmin, tol, & !! CGSVJ0 is called from CGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as CGESVJ does, but !! it does not check convergence (stopping criterion). Few tuning !! parameters (marked by [TP]) are available for the implementer. nsweep, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n, nsweep real(sp), intent(in) :: eps, sfmin, tol character, intent(in) :: jobv ! Array Arguments complex(sp), intent(inout) :: a(lda,*), d(n), v(ldv,*) complex(sp), intent(out) :: work(lwork) real(sp), intent(inout) :: sva(n) ! ===================================================================== ! Local Scalars complex(sp) :: aapq, ompq real(sp) :: aapp, aapp0, aapq1, aaqq, apoaq, aqoap, big, bigtheta, cs, mxaapq, mxsinj, & rootbig, rooteps, rootsfmin, roottol, small, sn, t, temp1, theta, thsign integer(${ik}$) :: blskip, emptsw, i, ibr, ierr, igl, ijblsk, ir1, iswrot, jbc, jgl, kbl, & lkahead, mvl, nbl, notrot, p, pskipped, q, rowskip, swband logical(lk) :: applv, rotok, rsvec ! Intrinsic Functions ! from lapack ! Executable Statements ! test the input parameters. applv = stdlib_lsame( jobv, 'A' ) rsvec = stdlib_lsame( jobv, 'V' ) if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -3_${ik}$ else if( lda sqrt(overflow_threshold), and to ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_scnrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_scnrm2 is available, the if-then-else-end if ! below should be replaced with "aapp = stdlib${ii}$_scnrm2( m, a(1,p), 1 )". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else temp1 = zero aapp = one call stdlib${ii}$_classq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work, lda, & ierr ) aapq = stdlib${ii}$_cdotc( m, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aapp ) / aaqq else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg( cwork(p) ) * cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) ! Rotate ! [rtd] rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/aapq1 if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_crot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if ( rsvec ) then call stdlib${ii}$_crot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_crot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if ( rsvec ) then call stdlib${ii}$_crot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if d(p) = -d(q) * ompq else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_ccopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) call stdlib${ii}$_caxpy( m, -aapq, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, q ), 1_${ik}$ ) else t = zero aaqq = one call stdlib${ii}$_classq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_classq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_cdotc( m, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / max(& aaqq,aapp) )/ min(aaqq,aapp) else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg(cwork(p))*cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/ aapq1 if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_crot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if( rsvec ) then call stdlib${ii}$_crot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_crot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if( rsvec ) then call stdlib${ii}$_crot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if d(p) = -d(q) * ompq else ! .. have to use modified gram-schmidt like transformation if( aapp>aaqq ) then call stdlib${ii}$_ccopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) call stdlib${ii}$_caxpy( m, -aapq, work,1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) call stdlib${ii}$_caxpy( m, -conjg(aapq),work, 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ & ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! .. recompute sva(q), sva(p) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, q ), 1_${ik}$) else t = zero aaqq = one call stdlib${ii}$_classq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_classq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, n ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_classq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector sva() of column norms. do p = 1, n - 1 q = stdlib${ii}$_isamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 aapq = d( p ) d( p ) = d( q ) d( q ) = aapq call stdlib${ii}$_cswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_cswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_cgsvj0 pure module subroutine stdlib${ii}$_zgsvj0( jobv, m, n, a, lda, d, sva, mv, v, ldv, eps,sfmin, tol, & !! ZGSVJ0 is called from ZGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as ZGESVJ does, but !! it does not check convergence (stopping criterion). Few tuning !! parameters (marked by [TP]) are available for the implementer. nsweep, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n, nsweep real(dp), intent(in) :: eps, sfmin, tol character, intent(in) :: jobv ! Array Arguments complex(dp), intent(inout) :: a(lda,*), d(n), v(ldv,*) complex(dp), intent(out) :: work(lwork) real(dp), intent(inout) :: sva(n) ! ===================================================================== ! Local Scalars complex(dp) :: aapq, ompq real(dp) :: aapp, aapp0, aapq1, aaqq, apoaq, aqoap, big, bigtheta, cs, mxaapq, mxsinj, & rootbig, rooteps, rootsfmin, roottol, small, sn, t, temp1, theta, thsign integer(${ik}$) :: blskip, emptsw, i, ibr, ierr, igl, ijblsk, ir1, iswrot, jbc, jgl, kbl, & lkahead, mvl, nbl, notrot, p, pskipped, q, rowskip, swband logical(lk) :: applv, rotok, rsvec ! Intrinsic Functions ! from lapack ! Executable Statements ! test the input parameters. applv = stdlib_lsame( jobv, 'A' ) rsvec = stdlib_lsame( jobv, 'V' ) if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -3_${ik}$ else if( lda sqrt(overflow_threshold), and to ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_dznrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_dznrm2 is available, the if-then-else-end if ! below should be replaced with "aapp = stdlib${ii}$_dznrm2( m, a(1,p), 1 )". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else temp1 = zero aapp = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work, lda, & ierr ) aapq = stdlib${ii}$_zdotc( m, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aapp ) / aaqq else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg( cwork(p) ) * cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) ! Rotate ! [rtd] rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/aapq1 if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_zrot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if ( rsvec ) then call stdlib${ii}$_zrot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_zrot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if ( rsvec ) then call stdlib${ii}$_zrot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if d(p) = -d(q) * ompq else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_zcopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) call stdlib${ii}$_zaxpy( m, -aapq, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, q ), 1_${ik}$ ) else t = zero aaqq = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_zdotc( m, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / max(& aaqq,aapp) )/ min(aaqq,aapp) else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg(cwork(p))*cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/ aapq1 if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_zrot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if( rsvec ) then call stdlib${ii}$_zrot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_zrot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if( rsvec ) then call stdlib${ii}$_zrot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if d(p) = -d(q) * ompq else ! .. have to use modified gram-schmidt like transformation if( aapp>aaqq ) then call stdlib${ii}$_zcopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) call stdlib${ii}$_zaxpy( m, -aapq, work,1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) call stdlib${ii}$_zaxpy( m, -conjg(aapq),work, 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ & ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! .. recompute sva(q), sva(p) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, q ), 1_${ik}$) else t = zero aaqq = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, n ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector sva() of column norms. do p = 1, n - 1 q = stdlib${ii}$_idamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 aapq = d( p ) d( p ) = d( q ) d( q ) = aapq call stdlib${ii}$_zswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_zswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_zgsvj0 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gsvj0( jobv, m, n, a, lda, d, sva, mv, v, ldv, eps,sfmin, tol, & !! ZGSVJ0: is called from ZGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as ZGESVJ does, but !! it does not check convergence (stopping criterion). Few tuning !! parameters (marked by [TP]) are available for the implementer. nsweep, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n, nsweep real(${ck}$), intent(in) :: eps, sfmin, tol character, intent(in) :: jobv ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), d(n), v(ldv,*) complex(${ck}$), intent(out) :: work(lwork) real(${ck}$), intent(inout) :: sva(n) ! ===================================================================== ! Local Scalars complex(${ck}$) :: aapq, ompq real(${ck}$) :: aapp, aapp0, aapq1, aaqq, apoaq, aqoap, big, bigtheta, cs, mxaapq, mxsinj, & rootbig, rooteps, rootsfmin, roottol, small, sn, t, temp1, theta, thsign integer(${ik}$) :: blskip, emptsw, i, ibr, ierr, igl, ijblsk, ir1, iswrot, jbc, jgl, kbl, & lkahead, mvl, nbl, notrot, p, pskipped, q, rowskip, swband logical(lk) :: applv, rotok, rsvec ! Intrinsic Functions ! from lapack ! Executable Statements ! test the input parameters. applv = stdlib_lsame( jobv, 'A' ) rsvec = stdlib_lsame( jobv, 'V' ) if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -3_${ik}$ else if( lda sqrt(overflow_threshold), and to ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_${c2ri(ci)}$znrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_${c2ri(ci)}$znrm2 is available, the if-then-else-end if ! below should be replaced with "aapp = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a(1,p), 1 )". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else temp1 = zero aapp = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work, lda, & ierr ) aapq = stdlib${ii}$_${ci}$dotc( m, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aapp ) / aaqq else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg( cwork(p) ) * cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) ! Rotate ! [rtd] rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/aapq1 if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_${ci}$rot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if ( rsvec ) then call stdlib${ii}$_${ci}$rot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_${ci}$rot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if ( rsvec ) then call stdlib${ii}$_${ci}$rot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if d(p) = -d(q) * ompq else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) call stdlib${ii}$_${ci}$axpy( m, -aapq, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, q ), 1_${ik}$ ) else t = zero aaqq = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_${ci}$dotc( m, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / max(& aaqq,aapp) )/ min(aaqq,aapp) else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg(cwork(p))*cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/ aapq1 if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_${ci}$rot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if( rsvec ) then call stdlib${ii}$_${ci}$rot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_${ci}$rot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if( rsvec ) then call stdlib${ii}$_${ci}$rot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if d(p) = -d(q) * ompq else ! .. have to use modified gram-schmidt like transformation if( aapp>aaqq ) then call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) call stdlib${ii}$_${ci}$axpy( m, -aapq, work,1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) call stdlib${ii}$_${ci}$axpy( m, -conjg(aapq),work, 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ & ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! .. recompute sva(q), sva(p) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, q ), 1_${ik}$) else t = zero aaqq = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, n ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector sva() of column norms. do p = 1, n - 1 q = stdlib${ii}$_i${c2ri(ci)}$amax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 aapq = d( p ) d( p ) = d( q ) d( q ) = aapq call stdlib${ii}$_${ci}$swap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_${ci}$swap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_${ci}$gsvj0 #:endif #:endfor pure module subroutine stdlib${ii}$_sgsvj1( jobv, m, n, n1, a, lda, d, sva, mv, v, ldv,eps, sfmin, tol, & !! SGSVJ1 is called from SGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as SGESVJ does, but !! it targets only particular pivots and it does not check convergence !! (stopping criterion). Few tuning parameters (marked by [TP]) are !! available for the implementer. !! Further Details !! ~~~~~~~~~~~~~~~ !! SGSVJ1 applies few sweeps of Jacobi rotations in the column space of !! the input M-by-N matrix A. The pivot pairs are taken from the (1,2) !! off-diagonal block in the corresponding N-by-N Gram matrix A^T * A. The !! block-entries (tiles) of the (1,2) off-diagonal block are marked by the !! [x]'s in the following scheme: !! | * * * [x] [x] [x]| !! | * * * [x] [x] [x]| Row-cycling in the nblr-by-nblc [x] blocks. !! | * * * [x] [x] [x]| Row-cyclic pivoting inside each [x] block. !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! In terms of the columns of A, the first N1 columns are rotated 'against' !! the remaining N-N1 columns, trying to increase the angle between the !! corresponding subspaces. The off-diagonal block is N1-by(N-N1) and it is !! tiled using quadratic tiles of side KBL. Here, KBL is a tuning parameter. !! The number of sweeps is given in NSWEEP and the orthogonality threshold !! is given in TOL. nsweep, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: eps, sfmin, tol integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n, n1, nsweep character, intent(in) :: jobv ! Array Arguments real(sp), intent(inout) :: a(lda,*), d(n), sva(n), v(ldv,*) real(sp), intent(out) :: work(lwork) ! ===================================================================== ! Local Scalars real(sp) :: aapp, aapp0, aapq, aaqq, apoaq, aqoap, big, bigtheta, cs, large, mxaapq, & mxsinj, rootbig, rooteps, rootsfmin, roottol, small, sn, t, temp1, theta, & thsign integer(${ik}$) :: blskip, emptsw, i, ibr, igl, ierr, ijblsk, iswrot, jbc, jgl, kbl, mvl, & notrot, nblc, nblr, p, pskipped, q, rowskip, swband logical(lk) :: applv, rotok, rsvec ! Local Arrays real(sp) :: fastr(5_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. applv = stdlib_lsame( jobv, 'A' ) rsvec = stdlib_lsame( jobv, 'V' ) if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -3_${ik}$ else if( n1<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! Safe Gram Matrix Computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_sdot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_scopy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, d( p ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_sdot( m, work, 1_${ik}$, a( 1_${ik}$, q ),1_${ik}$ )*d( q ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_sdot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_scopy( m, a( 1_${ik}$, q ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, d( q ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_sdot( m, work, 1_${ik}$, a( 1_${ik}$, p ),1_${ik}$ )*d( p ) / & aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then notrot = 0_${ik}$ ! rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq ) / aapq if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*d( p ) / d( q ) fastr( 4_${ik}$ ) = -t*d( q ) / d( p ) call stdlib${ii}$_srotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_srotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = d( p ) / d( q ) aqoap = d( q ) / d( p ) if( d( p )>=one ) then if( d( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap d( p ) = d( p )*cs d( q ) = d( q )*cs call stdlib${ii}$_srotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_srotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_saxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_saxpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if d( p ) = d( p )*cs d( q ) = d( q ) / cs end if else if( d( q )>=one ) then call stdlib${ii}$_saxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_saxpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if d( p ) = d( p ) / cs d( q ) = d( q )*cs else if( d( p )>=d( q ) ) then call stdlib${ii}$_saxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_saxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else if( aapp>aaqq ) then call stdlib${ii}$_scopy( m, a( 1_${ik}$, p ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) temp1 = -aapq*d( p ) / d( q ) call stdlib${ii}$_saxpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_scopy( m, a( 1_${ik}$, q ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) temp1 = -aapq*d( q ) / d( p ) call stdlib${ii}$_saxpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q) ! .. recompute sva(q) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_snrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*d( q ) else t = zero aaqq = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*d( q ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_snrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else t = zero aapp = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*d( p ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if ! if ( notrot >= emptsw ) go to 2011 if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapp= emptsw ) go to 2011 end if end do loop_2100 ! end of the p-loop end do loop_2010 ! end of the jbc-loop 2011 continue ! 2011 bailed out of the jbc-loop do p = igl, min( igl+kbl-1, n ) sva( p ) = abs( sva( p ) ) end do ! ** if ( notrot >= emptsw ) go to 1994 end do loop_2000 ! 2000 :: end of the ibr-loop ! .. update sva(n) if( ( sva( n )rootsfmin ) )then sva( n ) = stdlib${ii}$_snrm2( m, a( 1_${ik}$, n ), 1_${ik}$ )*d( n ) else t = zero aapp = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp )*d( n ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:) reaching this point means that the procedure has completed the given ! number of sweeps. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means that during the i-th sweep all pivots were ! below the given threshold, causing early exit. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector d do p = 1, n - 1 q = stdlib${ii}$_isamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = d( p ) d( p ) = d( q ) d( q ) = temp1 call stdlib${ii}$_sswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_sswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_sgsvj1 pure module subroutine stdlib${ii}$_dgsvj1( jobv, m, n, n1, a, lda, d, sva, mv, v, ldv,eps, sfmin, tol, & !! DGSVJ1 is called from DGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as DGESVJ does, but !! it targets only particular pivots and it does not check convergence !! (stopping criterion). Few tuning parameters (marked by [TP]) are !! available for the implementer. !! Further Details !! ~~~~~~~~~~~~~~~ !! DGSVJ1 applies few sweeps of Jacobi rotations in the column space of !! the input M-by-N matrix A. The pivot pairs are taken from the (1,2) !! off-diagonal block in the corresponding N-by-N Gram matrix A^T * A. The !! block-entries (tiles) of the (1,2) off-diagonal block are marked by the !! [x]'s in the following scheme: !! | * * * [x] [x] [x]| !! | * * * [x] [x] [x]| Row-cycling in the nblr-by-nblc [x] blocks. !! | * * * [x] [x] [x]| Row-cyclic pivoting inside each [x] block. !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! In terms of the columns of A, the first N1 columns are rotated 'against' !! the remaining N-N1 columns, trying to increase the angle between the !! corresponding subspaces. The off-diagonal block is N1-by(N-N1) and it is !! tiled using quadratic tiles of side KBL. Here, KBL is a tuning parameter. !! The number of sweeps is given in NSWEEP and the orthogonality threshold !! is given in TOL. nsweep, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: eps, sfmin, tol integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n, n1, nsweep character, intent(in) :: jobv ! Array Arguments real(dp), intent(inout) :: a(lda,*), d(n), sva(n), v(ldv,*) real(dp), intent(out) :: work(lwork) ! ===================================================================== ! Local Scalars real(dp) :: aapp, aapp0, aapq, aaqq, apoaq, aqoap, big, bigtheta, cs, large, mxaapq, & mxsinj, rootbig, rooteps, rootsfmin, roottol, small, sn, t, temp1, theta, & thsign integer(${ik}$) :: blskip, emptsw, i, ibr, igl, ierr, ijblsk, iswrot, jbc, jgl, kbl, mvl, & notrot, nblc, nblr, p, pskipped, q, rowskip, swband logical(lk) :: applv, rotok, rsvec ! Local Arrays real(dp) :: fastr(5_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. applv = stdlib_lsame( jobv, 'A' ) rsvec = stdlib_lsame( jobv, 'V' ) if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -3_${ik}$ else if( n1<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! Safe Gram Matrix Computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_ddot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, d( p ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_ddot( m, work, 1_${ik}$, a( 1_${ik}$, q ),1_${ik}$ )*d( q ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_ddot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, q ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, d( q ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_ddot( m, work, 1_${ik}$, a( 1_${ik}$, p ),1_${ik}$ )*d( p ) / & aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then notrot = 0_${ik}$ ! rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs(aqoap-apoaq) / aapq if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*d( p ) / d( q ) fastr( 4_${ik}$ ) = -t*d( q ) / d( p ) call stdlib${ii}$_drotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_drotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = d( p ) / d( q ) aqoap = d( q ) / d( p ) if( d( p )>=one ) then if( d( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap d( p ) = d( p )*cs d( q ) = d( q )*cs call stdlib${ii}$_drotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_drotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_daxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_daxpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if d( p ) = d( p )*cs d( q ) = d( q ) / cs end if else if( d( q )>=one ) then call stdlib${ii}$_daxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_daxpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if d( p ) = d( p ) / cs d( q ) = d( q )*cs else if( d( p )>=d( q ) ) then call stdlib${ii}$_daxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_daxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else if( aapp>aaqq ) then call stdlib${ii}$_dcopy( m, a( 1_${ik}$, p ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) temp1 = -aapq*d( p ) / d( q ) call stdlib${ii}$_daxpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, q ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) temp1 = -aapq*d( q ) / d( p ) call stdlib${ii}$_daxpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q) ! .. recompute sva(q) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*d( q ) else t = zero aaqq = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*d( q ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else t = zero aapp = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*d( p ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if ! if ( notrot >= emptsw ) go to 2011 if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapp= emptsw ) go to 2011 end if end do loop_2100 ! end of the p-loop end do loop_2010 ! end of the jbc-loop 2011 continue ! 2011 bailed out of the jbc-loop do p = igl, min( igl+kbl-1, n ) sva( p ) = abs( sva( p ) ) end do ! ** if ( notrot >= emptsw ) go to 1994 end do loop_2000 ! 2000 :: end of the ibr-loop ! .. update sva(n) if( ( sva( n )rootsfmin ) )then sva( n ) = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, n ), 1_${ik}$ )*d( n ) else t = zero aapp = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp )*d( n ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:) reaching this point means that the procedure has completed the given ! number of sweeps. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means that during the i-th sweep all pivots were ! below the given threshold, causing early exit. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector d do p = 1, n - 1 q = stdlib${ii}$_idamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = d( p ) d( p ) = d( q ) d( q ) = temp1 call stdlib${ii}$_dswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_dswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_dgsvj1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gsvj1( jobv, m, n, n1, a, lda, d, sva, mv, v, ldv,eps, sfmin, tol, & !! DGSVJ1: is called from DGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as DGESVJ does, but !! it targets only particular pivots and it does not check convergence !! (stopping criterion). Few tuning parameters (marked by [TP]) are !! available for the implementer. !! Further Details !! ~~~~~~~~~~~~~~~ !! DGSVJ1 applies few sweeps of Jacobi rotations in the column space of !! the input M-by-N matrix A. The pivot pairs are taken from the (1,2) !! off-diagonal block in the corresponding N-by-N Gram matrix A^T * A. The !! block-entries (tiles) of the (1,2) off-diagonal block are marked by the !! [x]'s in the following scheme: !! | * * * [x] [x] [x]| !! | * * * [x] [x] [x]| Row-cycling in the nblr-by-nblc [x] blocks. !! | * * * [x] [x] [x]| Row-cyclic pivoting inside each [x] block. !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! In terms of the columns of A, the first N1 columns are rotated 'against' !! the remaining N-N1 columns, trying to increase the angle between the !! corresponding subspaces. The off-diagonal block is N1-by(N-N1) and it is !! tiled using quadratic tiles of side KBL. Here, KBL is a tuning parameter. !! The number of sweeps is given in NSWEEP and the orthogonality threshold !! is given in TOL. nsweep, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: eps, sfmin, tol integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n, n1, nsweep character, intent(in) :: jobv ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), d(n), sva(n), v(ldv,*) real(${rk}$), intent(out) :: work(lwork) ! ===================================================================== ! Local Scalars real(${rk}$) :: aapp, aapp0, aapq, aaqq, apoaq, aqoap, big, bigtheta, cs, large, mxaapq, & mxsinj, rootbig, rooteps, rootsfmin, roottol, small, sn, t, temp1, theta, & thsign integer(${ik}$) :: blskip, emptsw, i, ibr, igl, ierr, ijblsk, iswrot, jbc, jgl, kbl, mvl, & notrot, nblc, nblr, p, pskipped, q, rowskip, swband logical(lk) :: applv, rotok, rsvec ! Local Arrays real(${rk}$) :: fastr(5_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. applv = stdlib_lsame( jobv, 'A' ) rsvec = stdlib_lsame( jobv, 'V' ) if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -3_${ik}$ else if( n1<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! Safe Gram Matrix Computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_${ri}$dot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, p ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, d( p ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_${ri}$dot( m, work, 1_${ik}$, a( 1_${ik}$, q ),1_${ik}$ )*d( q ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_${ri}$dot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*d( p )& *d( q ) / aaqq )/ aapp else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, q ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, d( q ),m, 1_${ik}$, work, lda,& ierr ) aapq = stdlib${ii}$_${ri}$dot( m, work, 1_${ik}$, a( 1_${ik}$, p ),1_${ik}$ )*d( p ) / & aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then notrot = 0_${ik}$ ! rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs(aqoap-apoaq) / aapq if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*d( p ) / d( q ) fastr( 4_${ik}$ ) = -t*d( q ) / d( p ) call stdlib${ii}$_${ri}$rotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_${ri}$rotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = d( p ) / d( q ) aqoap = d( q ) / d( p ) if( d( p )>=one ) then if( d( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap d( p ) = d( p )*cs d( q ) = d( q )*cs call stdlib${ii}$_${ri}$rotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_${ri}$rotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_${ri}$axpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if d( p ) = d( p )*cs d( q ) = d( q ) / cs end if else if( d( q )>=one ) then call stdlib${ii}$_${ri}$axpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if d( p ) = d( p ) / cs d( q ) = d( q )*cs else if( d( p )>=d( q ) ) then call stdlib${ii}$_${ri}$axpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) d( p ) = d( p )*cs d( q ) = d( q ) / cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_${ri}$axpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) d( p ) = d( p ) / cs d( q ) = d( q )*cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else if( aapp>aaqq ) then call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, p ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) temp1 = -aapq*d( p ) / d( q ) call stdlib${ii}$_${ri}$axpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, q ), 1_${ik}$, work,1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work, lda,& ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) temp1 = -aapq*d( q ) / d( p ) call stdlib${ii}$_${ri}$axpy( m, temp1, work, 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q) ! .. recompute sva(q) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*d( q ) else t = zero aaqq = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*d( q ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*d( p ) else t = zero aapp = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*d( p ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if ! if ( notrot >= emptsw ) go to 2011 if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapp= emptsw ) go to 2011 end if end do loop_2100 ! end of the p-loop end do loop_2010 ! end of the jbc-loop 2011 continue ! 2011 bailed out of the jbc-loop do p = igl, min( igl+kbl-1, n ) sva( p ) = abs( sva( p ) ) end do ! ** if ( notrot >= emptsw ) go to 1994 end do loop_2000 ! 2000 :: end of the ibr-loop ! .. update sva(n) if( ( sva( n )rootsfmin ) )then sva( n ) = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, n ), 1_${ik}$ )*d( n ) else t = zero aapp = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp )*d( n ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:) reaching this point means that the procedure has completed the given ! number of sweeps. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means that during the i-th sweep all pivots were ! below the given threshold, causing early exit. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector d do p = 1, n - 1 q = stdlib${ii}$_i${ri}$amax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = d( p ) d( p ) = d( q ) d( q ) = temp1 call stdlib${ii}$_${ri}$swap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_${ri}$swap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_${ri}$gsvj1 #:endif #:endfor pure module subroutine stdlib${ii}$_cgsvj1( jobv, m, n, n1, a, lda, d, sva, mv, v, ldv,eps, sfmin, tol, & !! CGSVJ1 is called from CGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as CGESVJ does, but !! it targets only particular pivots and it does not check convergence !! (stopping criterion). Few tuning parameters (marked by [TP]) are !! available for the implementer. !! Further Details !! ~~~~~~~~~~~~~~~ !! CGSVJ1 applies few sweeps of Jacobi rotations in the column space of !! the input M-by-N matrix A. The pivot pairs are taken from the (1,2) !! off-diagonal block in the corresponding N-by-N Gram matrix A^T * A. The !! block-entries (tiles) of the (1,2) off-diagonal block are marked by the !! [x]'s in the following scheme: !! | * * * [x] [x] [x]| !! | * * * [x] [x] [x]| Row-cycling in the nblr-by-nblc [x] blocks. !! | * * * [x] [x] [x]| Row-cyclic pivoting inside each [x] block. !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! In terms of the columns of A, the first N1 columns are rotated 'against' !! the remaining N-N1 columns, trying to increase the angle between the !! corresponding subspaces. The off-diagonal block is N1-by(N-N1) and it is !! tiled using quadratic tiles of side KBL. Here, KBL is a tuning parameter. !! The number of sweeps is given in NSWEEP and the orthogonality threshold !! is given in TOL. nsweep, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: eps, sfmin, tol integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n, n1, nsweep character, intent(in) :: jobv ! Array Arguments complex(sp), intent(inout) :: a(lda,*), d(n), v(ldv,*) complex(sp), intent(out) :: work(lwork) real(sp), intent(inout) :: sva(n) ! ===================================================================== ! Local Scalars complex(sp) :: aapq, ompq real(sp) :: aapp, aapp0, aapq1, aaqq, apoaq, aqoap, big, bigtheta, cs, mxaapq, mxsinj, & rootbig, rooteps, rootsfmin, roottol, small, sn, t, temp1, theta, thsign integer(${ik}$) :: blskip, emptsw, i, ibr, igl, ierr, ijblsk, iswrot, jbc, jgl, kbl, mvl, & notrot, nblc, nblr, p, pskipped, q, rowskip, swband logical(lk) :: applv, rotok, rsvec ! Intrinsic Functions ! From Lapack ! Executable Statements ! test the input parameters. applv = stdlib_lsame( jobv, 'A' ) rsvec = stdlib_lsame( jobv, 'V' ) if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -3_${ik}$ else if( n1<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_cdotc( m, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / max(& aaqq,aapp) )/ min(aaqq,aapp) else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg(cwork(p))*cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/ aapq1 if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_crot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if( rsvec ) then call stdlib${ii}$_crot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_crot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if( rsvec ) then call stdlib${ii}$_crot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if d(p) = -d(q) * ompq else ! .. have to use modified gram-schmidt like transformation if( aapp>aaqq ) then call stdlib${ii}$_ccopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) call stdlib${ii}$_caxpy( m, -aapq, work,1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) call stdlib${ii}$_caxpy( m, -conjg(aapq),work, 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ & ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! .. recompute sva(q), sva(p) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, q ), 1_${ik}$) else t = zero aaqq = one call stdlib${ii}$_classq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_classq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, n ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_classq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector sva() of column norms. do p = 1, n - 1 q = stdlib${ii}$_isamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 aapq = d( p ) d( p ) = d( q ) d( q ) = aapq call stdlib${ii}$_cswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_cswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_cgsvj1 pure module subroutine stdlib${ii}$_zgsvj1( jobv, m, n, n1, a, lda, d, sva, mv, v, ldv,eps, sfmin, tol, & !! ZGSVJ1 is called from ZGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as ZGESVJ does, but !! it targets only particular pivots and it does not check convergence !! (stopping criterion). Few tuning parameters (marked by [TP]) are !! available for the implementer. !! Further Details !! ~~~~~~~~~~~~~~~ !! ZGSVJ1 applies few sweeps of Jacobi rotations in the column space of !! the input M-by-N matrix A. The pivot pairs are taken from the (1,2) !! off-diagonal block in the corresponding N-by-N Gram matrix A^T * A. The !! block-entries (tiles) of the (1,2) off-diagonal block are marked by the !! [x]'s in the following scheme: !! | * * * [x] [x] [x]| !! | * * * [x] [x] [x]| Row-cycling in the nblr-by-nblc [x] blocks. !! | * * * [x] [x] [x]| Row-cyclic pivoting inside each [x] block. !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! In terms of the columns of A, the first N1 columns are rotated 'against' !! the remaining N-N1 columns, trying to increase the angle between the !! corresponding subspaces. The off-diagonal block is N1-by(N-N1) and it is !! tiled using quadratic tiles of side KBL. Here, KBL is a tuning parameter. !! The number of sweeps is given in NSWEEP and the orthogonality threshold !! is given in TOL. nsweep, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: eps, sfmin, tol integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n, n1, nsweep character, intent(in) :: jobv ! Array Arguments complex(dp), intent(inout) :: a(lda,*), d(n), v(ldv,*) complex(dp), intent(out) :: work(lwork) real(dp), intent(inout) :: sva(n) ! ===================================================================== ! Local Scalars complex(dp) :: aapq, ompq real(dp) :: aapp, aapp0, aapq1, aaqq, apoaq, aqoap, big, bigtheta, cs, mxaapq, mxsinj, & rootbig, rooteps, rootsfmin, roottol, small, sn, t, temp1, theta, thsign integer(${ik}$) :: blskip, emptsw, i, ibr, igl, ierr, ijblsk, iswrot, jbc, jgl, kbl, mvl, & notrot, nblc, nblr, p, pskipped, q, rowskip, swband logical(lk) :: applv, rotok, rsvec ! Intrinsic Functions ! From Lapack ! Executable Statements ! test the input parameters. applv = stdlib_lsame( jobv, 'A' ) rsvec = stdlib_lsame( jobv, 'V' ) if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -3_${ik}$ else if( n1<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_zdotc( m, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / max(& aaqq,aapp) )/ min(aaqq,aapp) else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg(cwork(p))*cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/ aapq1 if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_zrot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if( rsvec ) then call stdlib${ii}$_zrot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_zrot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if( rsvec ) then call stdlib${ii}$_zrot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if d(p) = -d(q) * ompq else ! .. have to use modified gram-schmidt like transformation if( aapp>aaqq ) then call stdlib${ii}$_zcopy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) call stdlib${ii}$_zaxpy( m, -aapq, work,1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) call stdlib${ii}$_zaxpy( m, -conjg(aapq),work, 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ & ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! .. recompute sva(q), sva(p) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, q ), 1_${ik}$) else t = zero aaqq = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, n ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector sva() of column norms. do p = 1, n - 1 q = stdlib${ii}$_idamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 aapq = d( p ) d( p ) = d( q ) d( q ) = aapq call stdlib${ii}$_zswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_zswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_zgsvj1 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gsvj1( jobv, m, n, n1, a, lda, d, sva, mv, v, ldv,eps, sfmin, tol, & !! ZGSVJ1: is called from ZGESVJ as a pre-processor and that is its main !! purpose. It applies Jacobi rotations in the same way as ZGESVJ does, but !! it targets only particular pivots and it does not check convergence !! (stopping criterion). Few tuning parameters (marked by [TP]) are !! available for the implementer. !! Further Details !! ~~~~~~~~~~~~~~~ !! ZGSVJ1 applies few sweeps of Jacobi rotations in the column space of !! the input M-by-N matrix A. The pivot pairs are taken from the (1,2) !! off-diagonal block in the corresponding N-by-N Gram matrix A^T * A. The !! block-entries (tiles) of the (1,2) off-diagonal block are marked by the !! [x]'s in the following scheme: !! | * * * [x] [x] [x]| !! | * * * [x] [x] [x]| Row-cycling in the nblr-by-nblc [x] blocks. !! | * * * [x] [x] [x]| Row-cyclic pivoting inside each [x] block. !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! |[x] [x] [x] * * * | !! In terms of the columns of A, the first N1 columns are rotated 'against' !! the remaining N-N1 columns, trying to increase the angle between the !! corresponding subspaces. The off-diagonal block is N1-by(N-N1) and it is !! tiled using quadratic tiles of side KBL. Here, KBL is a tuning parameter. !! The number of sweeps is given in NSWEEP and the orthogonality threshold !! is given in TOL. nsweep, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${ck}$), intent(in) :: eps, sfmin, tol integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n, n1, nsweep character, intent(in) :: jobv ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), d(n), v(ldv,*) complex(${ck}$), intent(out) :: work(lwork) real(${ck}$), intent(inout) :: sva(n) ! ===================================================================== ! Local Scalars complex(${ck}$) :: aapq, ompq real(${ck}$) :: aapp, aapp0, aapq1, aaqq, apoaq, aqoap, big, bigtheta, cs, mxaapq, mxsinj, & rootbig, rooteps, rootsfmin, roottol, small, sn, t, temp1, theta, thsign integer(${ik}$) :: blskip, emptsw, i, ibr, igl, ierr, ijblsk, iswrot, jbc, jgl, kbl, mvl, & notrot, nblc, nblr, p, pskipped, q, rowskip, swband logical(lk) :: applv, rotok, rsvec ! Intrinsic Functions ! From Lapack ! Executable Statements ! test the input parameters. applv = stdlib_lsame( jobv, 'A' ) rsvec = stdlib_lsame( jobv, 'V' ) if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -3_${ik}$ else if( n1<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_${ci}$dotc( m, work, 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / max(& aaqq,aapp) )/ min(aaqq,aapp) else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,work, lda, & ierr ) aapq = stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg(cwork(p))*cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/ aapq1 if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_${ci}$rot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if( rsvec ) then call stdlib${ii}$_${ci}$rot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_${ci}$rot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if( rsvec ) then call stdlib${ii}$_${ci}$rot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if d(p) = -d(q) * ompq else ! .. have to use modified gram-schmidt like transformation if( aapp>aaqq ) then call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) call stdlib${ii}$_${ci}$axpy( m, -aapq, work,1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, q ), 1_${ik}$,work, 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work,lda,& ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) call stdlib${ii}$_${ci}$axpy( m, -conjg(aapq),work, 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ & ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! .. recompute sva(q), sva(p) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, q ), 1_${ik}$) else t = zero aaqq = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, n ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the vector sva() of column norms. do p = 1, n - 1 q = stdlib${ii}$_i${c2ri(ci)}$amax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 aapq = d( p ) d( p ) = d( q ) d( q ) = aapq call stdlib${ii}$_${ci}$swap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_${ci}$swap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if end do return end subroutine stdlib${ii}$_${ci}$gsvj1 #:endif #:endfor pure module subroutine stdlib${ii}$_stgsja( jobu, jobv, jobq, m, p, n, k, l, a, lda, b,ldb, tola, tolb, & !! STGSJA computes the generalized singular value decomposition (GSVD) !! of two real upper triangular (or trapezoidal) matrices A and B. !! On entry, it is assumed that matrices A and B have the following !! forms, which may be obtained by the preprocessing subroutine SGGSVP !! from a general M-by-N matrix A and P-by-N matrix B: !! N-K-L K L !! A = K ( 0 A12 A13 ) if M-K-L >= 0; !! L ( 0 0 A23 ) !! M-K-L ( 0 0 0 ) !! N-K-L K L !! A = K ( 0 A12 A13 ) if M-K-L < 0; !! M-K ( 0 0 A23 ) !! N-K-L K L !! B = L ( 0 0 B13 ) !! P-L ( 0 0 0 ) !! where the K-by-K matrix A12 and L-by-L matrix B13 are nonsingular !! upper triangular; A23 is L-by-L upper triangular if M-K-L >= 0, !! otherwise A23 is (M-K)-by-L upper trapezoidal. !! On exit, !! U**T *A*Q = D1*( 0 R ), V**T *B*Q = D2*( 0 R ), !! where U, V and Q are orthogonal matrices. !! R is a nonsingular upper triangular matrix, and D1 and D2 are !! ``diagonal'' matrices, which are of the following structures: !! If M-K-L >= 0, !! K L !! D1 = K ( I 0 ) !! L ( 0 C ) !! M-K-L ( 0 0 ) !! K L !! D2 = L ( 0 S ) !! P-L ( 0 0 ) !! N-K-L K L !! ( 0 R ) = K ( 0 R11 R12 ) K !! L ( 0 0 R22 ) L !! where !! C = diag( ALPHA(K+1), ... , ALPHA(K+L) ), !! S = diag( BETA(K+1), ... , BETA(K+L) ), !! C**2 + S**2 = I. !! R is stored in A(1:K+L,N-K-L+1:N) on exit. !! If M-K-L < 0, !! K M-K K+L-M !! D1 = K ( I 0 0 ) !! M-K ( 0 C 0 ) !! K M-K K+L-M !! D2 = M-K ( 0 S 0 ) !! K+L-M ( 0 0 I ) !! P-L ( 0 0 0 ) !! N-K-L K M-K K+L-M !! ( 0 R ) = K ( 0 R11 R12 R13 ) !! M-K ( 0 0 R22 R23 ) !! K+L-M ( 0 0 0 R33 ) !! where !! C = diag( ALPHA(K+1), ... , ALPHA(M) ), !! S = diag( BETA(K+1), ... , BETA(M) ), !! C**2 + S**2 = I. !! R = ( R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) and R33 is stored !! ( 0 R22 R23 ) !! in B(M-K+1:L,N+M-K-L+1:N) on exit. !! The computation of the orthogonal transformation matrices U, V or Q !! is optional. These matrices may either be formed explicitly, or they !! may be postmultiplied into input matrices U1, V1, or Q1. alpha, beta, u, ldu, v, ldv,q, ldq, work, ncycle, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobq, jobu, jobv integer(${ik}$), intent(out) :: info, ncycle integer(${ik}$), intent(in) :: k, l, lda, ldb, ldq, ldu, ldv, m, n, p real(sp), intent(in) :: tola, tolb ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), u(ldu,*), v(ldv,*) real(sp), intent(out) :: alpha(*), beta(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 40_${ik}$ real(sp), parameter :: hugenum = huge(zero) ! Local Scalars logical(lk) :: initq, initu, initv, upper, wantq, wantu, wantv integer(${ik}$) :: i, j, kcycle real(sp) :: a1, a2, a3, b1, b2, b3, csq, csu, csv, error, gamma, rwk, snq, snu, snv, & ssmin ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters initu = stdlib_lsame( jobu, 'I' ) wantu = initu .or. stdlib_lsame( jobu, 'U' ) initv = stdlib_lsame( jobv, 'I' ) wantv = initv .or. stdlib_lsame( jobv, 'V' ) initq = stdlib_lsame( jobq, 'I' ) wantq = initq .or. stdlib_lsame( jobq, 'Q' ) info = 0_${ik}$ if( .not.( initu .or. wantu .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( initv .or. wantv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( initq .or. wantq .or. stdlib_lsame( jobq, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( p<0_${ik}$ ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda=-hugenum) ) then ! change sign if necessary if( gamma=beta( k+i ) ) then call stdlib${ii}$_sscal( l-i+1, one / alpha( k+i ), a( k+i, n-l+i ),lda ) else call stdlib${ii}$_sscal( l-i+1, one / beta( k+i ), b( i, n-l+i ),ldb ) call stdlib${ii}$_scopy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if else alpha( k+i ) = zero beta( k+i ) = one call stdlib${ii}$_scopy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if end do ! post-assignment do i = m + 1, k + l alpha( i ) = zero beta( i ) = one end do if( k+l= 0; !! L ( 0 0 A23 ) !! M-K-L ( 0 0 0 ) !! N-K-L K L !! A = K ( 0 A12 A13 ) if M-K-L < 0; !! M-K ( 0 0 A23 ) !! N-K-L K L !! B = L ( 0 0 B13 ) !! P-L ( 0 0 0 ) !! where the K-by-K matrix A12 and L-by-L matrix B13 are nonsingular !! upper triangular; A23 is L-by-L upper triangular if M-K-L >= 0, !! otherwise A23 is (M-K)-by-L upper trapezoidal. !! On exit, !! U**T *A*Q = D1*( 0 R ), V**T *B*Q = D2*( 0 R ), !! where U, V and Q are orthogonal matrices. !! R is a nonsingular upper triangular matrix, and D1 and D2 are !! ``diagonal'' matrices, which are of the following structures: !! If M-K-L >= 0, !! K L !! D1 = K ( I 0 ) !! L ( 0 C ) !! M-K-L ( 0 0 ) !! K L !! D2 = L ( 0 S ) !! P-L ( 0 0 ) !! N-K-L K L !! ( 0 R ) = K ( 0 R11 R12 ) K !! L ( 0 0 R22 ) L !! where !! C = diag( ALPHA(K+1), ... , ALPHA(K+L) ), !! S = diag( BETA(K+1), ... , BETA(K+L) ), !! C**2 + S**2 = I. !! R is stored in A(1:K+L,N-K-L+1:N) on exit. !! If M-K-L < 0, !! K M-K K+L-M !! D1 = K ( I 0 0 ) !! M-K ( 0 C 0 ) !! K M-K K+L-M !! D2 = M-K ( 0 S 0 ) !! K+L-M ( 0 0 I ) !! P-L ( 0 0 0 ) !! N-K-L K M-K K+L-M !! ( 0 R ) = K ( 0 R11 R12 R13 ) !! M-K ( 0 0 R22 R23 ) !! K+L-M ( 0 0 0 R33 ) !! where !! C = diag( ALPHA(K+1), ... , ALPHA(M) ), !! S = diag( BETA(K+1), ... , BETA(M) ), !! C**2 + S**2 = I. !! R = ( R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) and R33 is stored !! ( 0 R22 R23 ) !! in B(M-K+1:L,N+M-K-L+1:N) on exit. !! The computation of the orthogonal transformation matrices U, V or Q !! is optional. These matrices may either be formed explicitly, or they !! may be postmultiplied into input matrices U1, V1, or Q1. alpha, beta, u, ldu, v, ldv,q, ldq, work, ncycle, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobq, jobu, jobv integer(${ik}$), intent(out) :: info, ncycle integer(${ik}$), intent(in) :: k, l, lda, ldb, ldq, ldu, ldv, m, n, p real(dp), intent(in) :: tola, tolb ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), u(ldu,*), v(ldv,*) real(dp), intent(out) :: alpha(*), beta(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 40_${ik}$ real(dp), parameter :: hugenum = huge(zero) ! Local Scalars logical(lk) :: initq, initu, initv, upper, wantq, wantu, wantv integer(${ik}$) :: i, j, kcycle real(dp) :: a1, a2, a3, b1, b2, b3, csq, csu, csv, error, gamma, rwk, snq, snu, snv, & ssmin ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters initu = stdlib_lsame( jobu, 'I' ) wantu = initu .or. stdlib_lsame( jobu, 'U' ) initv = stdlib_lsame( jobv, 'I' ) wantv = initv .or. stdlib_lsame( jobv, 'V' ) initq = stdlib_lsame( jobq, 'I' ) wantq = initq .or. stdlib_lsame( jobq, 'Q' ) info = 0_${ik}$ if( .not.( initu .or. wantu .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( initv .or. wantv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( initq .or. wantq .or. stdlib_lsame( jobq, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( p<0_${ik}$ ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda=-hugenum) ) then ! change sign if necessary if( gamma=beta( k+i ) ) then call stdlib${ii}$_dscal( l-i+1, one / alpha( k+i ), a( k+i, n-l+i ),lda ) else call stdlib${ii}$_dscal( l-i+1, one / beta( k+i ), b( i, n-l+i ),ldb ) call stdlib${ii}$_dcopy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if else alpha( k+i ) = zero beta( k+i ) = one call stdlib${ii}$_dcopy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if end do ! post-assignment do i = m + 1, k + l alpha( i ) = zero beta( i ) = one end do if( k+l= 0; !! L ( 0 0 A23 ) !! M-K-L ( 0 0 0 ) !! N-K-L K L !! A = K ( 0 A12 A13 ) if M-K-L < 0; !! M-K ( 0 0 A23 ) !! N-K-L K L !! B = L ( 0 0 B13 ) !! P-L ( 0 0 0 ) !! where the K-by-K matrix A12 and L-by-L matrix B13 are nonsingular !! upper triangular; A23 is L-by-L upper triangular if M-K-L >= 0, !! otherwise A23 is (M-K)-by-L upper trapezoidal. !! On exit, !! U**T *A*Q = D1*( 0 R ), V**T *B*Q = D2*( 0 R ), !! where U, V and Q are orthogonal matrices. !! R is a nonsingular upper triangular matrix, and D1 and D2 are !! ``diagonal'' matrices, which are of the following structures: !! If M-K-L >= 0, !! K L !! D1 = K ( I 0 ) !! L ( 0 C ) !! M-K-L ( 0 0 ) !! K L !! D2 = L ( 0 S ) !! P-L ( 0 0 ) !! N-K-L K L !! ( 0 R ) = K ( 0 R11 R12 ) K !! L ( 0 0 R22 ) L !! where !! C = diag( ALPHA(K+1), ... , ALPHA(K+L) ), !! S = diag( BETA(K+1), ... , BETA(K+L) ), !! C**2 + S**2 = I. !! R is stored in A(1:K+L,N-K-L+1:N) on exit. !! If M-K-L < 0, !! K M-K K+L-M !! D1 = K ( I 0 0 ) !! M-K ( 0 C 0 ) !! K M-K K+L-M !! D2 = M-K ( 0 S 0 ) !! K+L-M ( 0 0 I ) !! P-L ( 0 0 0 ) !! N-K-L K M-K K+L-M !! ( 0 R ) = K ( 0 R11 R12 R13 ) !! M-K ( 0 0 R22 R23 ) !! K+L-M ( 0 0 0 R33 ) !! where !! C = diag( ALPHA(K+1), ... , ALPHA(M) ), !! S = diag( BETA(K+1), ... , BETA(M) ), !! C**2 + S**2 = I. !! R = ( R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) and R33 is stored !! ( 0 R22 R23 ) !! in B(M-K+1:L,N+M-K-L+1:N) on exit. !! The computation of the orthogonal transformation matrices U, V or Q !! is optional. These matrices may either be formed explicitly, or they !! may be postmultiplied into input matrices U1, V1, or Q1. alpha, beta, u, ldu, v, ldv,q, ldq, work, ncycle, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobq, jobu, jobv integer(${ik}$), intent(out) :: info, ncycle integer(${ik}$), intent(in) :: k, l, lda, ldb, ldq, ldu, ldv, m, n, p real(${rk}$), intent(in) :: tola, tolb ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), u(ldu,*), v(ldv,*) real(${rk}$), intent(out) :: alpha(*), beta(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 40_${ik}$ real(${rk}$), parameter :: hugenum = huge(zero) ! Local Scalars logical(lk) :: initq, initu, initv, upper, wantq, wantu, wantv integer(${ik}$) :: i, j, kcycle real(${rk}$) :: a1, a2, a3, b1, b2, b3, csq, csu, csv, error, gamma, rwk, snq, snu, snv, & ssmin ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters initu = stdlib_lsame( jobu, 'I' ) wantu = initu .or. stdlib_lsame( jobu, 'U' ) initv = stdlib_lsame( jobv, 'I' ) wantv = initv .or. stdlib_lsame( jobv, 'V' ) initq = stdlib_lsame( jobq, 'I' ) wantq = initq .or. stdlib_lsame( jobq, 'Q' ) info = 0_${ik}$ if( .not.( initu .or. wantu .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( initv .or. wantv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( initq .or. wantq .or. stdlib_lsame( jobq, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( p<0_${ik}$ ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda=-hugenum) ) then ! change sign if necessary if( gamma=beta( k+i ) ) then call stdlib${ii}$_${ri}$scal( l-i+1, one / alpha( k+i ), a( k+i, n-l+i ),lda ) else call stdlib${ii}$_${ri}$scal( l-i+1, one / beta( k+i ), b( i, n-l+i ),ldb ) call stdlib${ii}$_${ri}$copy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if else alpha( k+i ) = zero beta( k+i ) = one call stdlib${ii}$_${ri}$copy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if end do ! post-assignment do i = m + 1, k + l alpha( i ) = zero beta( i ) = one end do if( k+l= 0; !! L ( 0 0 A23 ) !! M-K-L ( 0 0 0 ) !! N-K-L K L !! A = K ( 0 A12 A13 ) if M-K-L < 0; !! M-K ( 0 0 A23 ) !! N-K-L K L !! B = L ( 0 0 B13 ) !! P-L ( 0 0 0 ) !! where the K-by-K matrix A12 and L-by-L matrix B13 are nonsingular !! upper triangular; A23 is L-by-L upper triangular if M-K-L >= 0, !! otherwise A23 is (M-K)-by-L upper trapezoidal. !! On exit, !! U**H *A*Q = D1*( 0 R ), V**H *B*Q = D2*( 0 R ), !! where U, V and Q are unitary matrices. !! R is a nonsingular upper triangular matrix, and D1 !! and D2 are ``diagonal'' matrices, which are of the following !! structures: !! If M-K-L >= 0, !! K L !! D1 = K ( I 0 ) !! L ( 0 C ) !! M-K-L ( 0 0 ) !! K L !! D2 = L ( 0 S ) !! P-L ( 0 0 ) !! N-K-L K L !! ( 0 R ) = K ( 0 R11 R12 ) K !! L ( 0 0 R22 ) L !! where !! C = diag( ALPHA(K+1), ... , ALPHA(K+L) ), !! S = diag( BETA(K+1), ... , BETA(K+L) ), !! C**2 + S**2 = I. !! R is stored in A(1:K+L,N-K-L+1:N) on exit. !! If M-K-L < 0, !! K M-K K+L-M !! D1 = K ( I 0 0 ) !! M-K ( 0 C 0 ) !! K M-K K+L-M !! D2 = M-K ( 0 S 0 ) !! K+L-M ( 0 0 I ) !! P-L ( 0 0 0 ) !! N-K-L K M-K K+L-M !! ( 0 R ) = K ( 0 R11 R12 R13 ) !! M-K ( 0 0 R22 R23 ) !! K+L-M ( 0 0 0 R33 ) !! where !! C = diag( ALPHA(K+1), ... , ALPHA(M) ), !! S = diag( BETA(K+1), ... , BETA(M) ), !! C**2 + S**2 = I. !! R = ( R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) and R33 is stored !! ( 0 R22 R23 ) !! in B(M-K+1:L,N+M-K-L+1:N) on exit. !! The computation of the unitary transformation matrices U, V or Q !! is optional. These matrices may either be formed explicitly, or they !! may be postmultiplied into input matrices U1, V1, or Q1. alpha, beta, u, ldu, v, ldv,q, ldq, work, ncycle, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobq, jobu, jobv integer(${ik}$), intent(out) :: info, ncycle integer(${ik}$), intent(in) :: k, l, lda, ldb, ldq, ldu, ldv, m, n, p real(sp), intent(in) :: tola, tolb ! Array Arguments real(sp), intent(out) :: alpha(*), beta(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), u(ldu,*), v(ldv,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 40_${ik}$ real(sp), parameter :: hugenum = huge(zero) ! Local Scalars logical(lk) :: initq, initu, initv, upper, wantq, wantu, wantv integer(${ik}$) :: i, j, kcycle real(sp) :: a1, a3, b1, b3, csq, csu, csv, error, gamma, rwk, ssmin complex(sp) :: a2, b2, snq, snu, snv ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters initu = stdlib_lsame( jobu, 'I' ) wantu = initu .or. stdlib_lsame( jobu, 'U' ) initv = stdlib_lsame( jobv, 'I' ) wantv = initv .or. stdlib_lsame( jobv, 'V' ) initq = stdlib_lsame( jobq, 'I' ) wantq = initq .or. stdlib_lsame( jobq, 'Q' ) info = 0_${ik}$ if( .not.( initu .or. wantu .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( initv .or. wantv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( initq .or. wantq .or. stdlib_lsame( jobq, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( p<0_${ik}$ ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda=-hugenum) ) then if( gamma=beta( k+i ) ) then call stdlib${ii}$_csscal( l-i+1, one / alpha( k+i ), a( k+i, n-l+i ),lda ) else call stdlib${ii}$_csscal( l-i+1, one / beta( k+i ), b( i, n-l+i ),ldb ) call stdlib${ii}$_ccopy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if else alpha( k+i ) = zero beta( k+i ) = one call stdlib${ii}$_ccopy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if end do ! post-assignment do i = m + 1, k + l alpha( i ) = zero beta( i ) = one end do if( k+l= 0; !! L ( 0 0 A23 ) !! M-K-L ( 0 0 0 ) !! N-K-L K L !! A = K ( 0 A12 A13 ) if M-K-L < 0; !! M-K ( 0 0 A23 ) !! N-K-L K L !! B = L ( 0 0 B13 ) !! P-L ( 0 0 0 ) !! where the K-by-K matrix A12 and L-by-L matrix B13 are nonsingular !! upper triangular; A23 is L-by-L upper triangular if M-K-L >= 0, !! otherwise A23 is (M-K)-by-L upper trapezoidal. !! On exit, !! U**H *A*Q = D1*( 0 R ), V**H *B*Q = D2*( 0 R ), !! where U, V and Q are unitary matrices. !! R is a nonsingular upper triangular matrix, and D1 !! and D2 are ``diagonal'' matrices, which are of the following !! structures: !! If M-K-L >= 0, !! K L !! D1 = K ( I 0 ) !! L ( 0 C ) !! M-K-L ( 0 0 ) !! K L !! D2 = L ( 0 S ) !! P-L ( 0 0 ) !! N-K-L K L !! ( 0 R ) = K ( 0 R11 R12 ) K !! L ( 0 0 R22 ) L !! where !! C = diag( ALPHA(K+1), ... , ALPHA(K+L) ), !! S = diag( BETA(K+1), ... , BETA(K+L) ), !! C**2 + S**2 = I. !! R is stored in A(1:K+L,N-K-L+1:N) on exit. !! If M-K-L < 0, !! K M-K K+L-M !! D1 = K ( I 0 0 ) !! M-K ( 0 C 0 ) !! K M-K K+L-M !! D2 = M-K ( 0 S 0 ) !! K+L-M ( 0 0 I ) !! P-L ( 0 0 0 ) !! N-K-L K M-K K+L-M !! ( 0 R ) = K ( 0 R11 R12 R13 ) !! M-K ( 0 0 R22 R23 ) !! K+L-M ( 0 0 0 R33 ) !! where !! C = diag( ALPHA(K+1), ... , ALPHA(M) ), !! S = diag( BETA(K+1), ... , BETA(M) ), !! C**2 + S**2 = I. !! R = ( R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) and R33 is stored !! ( 0 R22 R23 ) !! in B(M-K+1:L,N+M-K-L+1:N) on exit. !! The computation of the unitary transformation matrices U, V or Q !! is optional. These matrices may either be formed explicitly, or they !! may be postmultiplied into input matrices U1, V1, or Q1. alpha, beta, u, ldu, v, ldv,q, ldq, work, ncycle, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobq, jobu, jobv integer(${ik}$), intent(out) :: info, ncycle integer(${ik}$), intent(in) :: k, l, lda, ldb, ldq, ldu, ldv, m, n, p real(dp), intent(in) :: tola, tolb ! Array Arguments real(dp), intent(out) :: alpha(*), beta(*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), u(ldu,*), v(ldv,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 40_${ik}$ real(dp), parameter :: hugenum = huge(zero) ! Local Scalars logical(lk) :: initq, initu, initv, upper, wantq, wantu, wantv integer(${ik}$) :: i, j, kcycle real(dp) :: a1, a3, b1, b3, csq, csu, csv, error, gamma, rwk, ssmin complex(dp) :: a2, b2, snq, snu, snv ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters initu = stdlib_lsame( jobu, 'I' ) wantu = initu .or. stdlib_lsame( jobu, 'U' ) initv = stdlib_lsame( jobv, 'I' ) wantv = initv .or. stdlib_lsame( jobv, 'V' ) initq = stdlib_lsame( jobq, 'I' ) wantq = initq .or. stdlib_lsame( jobq, 'Q' ) info = 0_${ik}$ if( .not.( initu .or. wantu .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( initv .or. wantv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( initq .or. wantq .or. stdlib_lsame( jobq, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( p<0_${ik}$ ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda=-hugenum) ) then if( gamma=beta( k+i ) ) then call stdlib${ii}$_zdscal( l-i+1, one / alpha( k+i ), a( k+i, n-l+i ),lda ) else call stdlib${ii}$_zdscal( l-i+1, one / beta( k+i ), b( i, n-l+i ),ldb ) call stdlib${ii}$_zcopy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if else alpha( k+i ) = zero beta( k+i ) = one call stdlib${ii}$_zcopy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if end do ! post-assignment do i = m + 1, k + l alpha( i ) = zero beta( i ) = one end do if( k+l= 0; !! L ( 0 0 A23 ) !! M-K-L ( 0 0 0 ) !! N-K-L K L !! A = K ( 0 A12 A13 ) if M-K-L < 0; !! M-K ( 0 0 A23 ) !! N-K-L K L !! B = L ( 0 0 B13 ) !! P-L ( 0 0 0 ) !! where the K-by-K matrix A12 and L-by-L matrix B13 are nonsingular !! upper triangular; A23 is L-by-L upper triangular if M-K-L >= 0, !! otherwise A23 is (M-K)-by-L upper trapezoidal. !! On exit, !! U**H *A*Q = D1*( 0 R ), V**H *B*Q = D2*( 0 R ), !! where U, V and Q are unitary matrices. !! R is a nonsingular upper triangular matrix, and D1 !! and D2 are ``diagonal'' matrices, which are of the following !! structures: !! If M-K-L >= 0, !! K L !! D1 = K ( I 0 ) !! L ( 0 C ) !! M-K-L ( 0 0 ) !! K L !! D2 = L ( 0 S ) !! P-L ( 0 0 ) !! N-K-L K L !! ( 0 R ) = K ( 0 R11 R12 ) K !! L ( 0 0 R22 ) L !! where !! C = diag( ALPHA(K+1), ... , ALPHA(K+L) ), !! S = diag( BETA(K+1), ... , BETA(K+L) ), !! C**2 + S**2 = I. !! R is stored in A(1:K+L,N-K-L+1:N) on exit. !! If M-K-L < 0, !! K M-K K+L-M !! D1 = K ( I 0 0 ) !! M-K ( 0 C 0 ) !! K M-K K+L-M !! D2 = M-K ( 0 S 0 ) !! K+L-M ( 0 0 I ) !! P-L ( 0 0 0 ) !! N-K-L K M-K K+L-M !! ( 0 R ) = K ( 0 R11 R12 R13 ) !! M-K ( 0 0 R22 R23 ) !! K+L-M ( 0 0 0 R33 ) !! where !! C = diag( ALPHA(K+1), ... , ALPHA(M) ), !! S = diag( BETA(K+1), ... , BETA(M) ), !! C**2 + S**2 = I. !! R = ( R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) and R33 is stored !! ( 0 R22 R23 ) !! in B(M-K+1:L,N+M-K-L+1:N) on exit. !! The computation of the unitary transformation matrices U, V or Q !! is optional. These matrices may either be formed explicitly, or they !! may be postmultiplied into input matrices U1, V1, or Q1. alpha, beta, u, ldu, v, ldv,q, ldq, work, ncycle, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobq, jobu, jobv integer(${ik}$), intent(out) :: info, ncycle integer(${ik}$), intent(in) :: k, l, lda, ldb, ldq, ldu, ldv, m, n, p real(${ck}$), intent(in) :: tola, tolb ! Array Arguments real(${ck}$), intent(out) :: alpha(*), beta(*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), u(ldu,*), v(ldv,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 40_${ik}$ real(${ck}$), parameter :: hugenum = huge(zero) ! Local Scalars logical(lk) :: initq, initu, initv, upper, wantq, wantu, wantv integer(${ik}$) :: i, j, kcycle real(${ck}$) :: a1, a3, b1, b3, csq, csu, csv, error, gamma, rwk, ssmin complex(${ck}$) :: a2, b2, snq, snu, snv ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters initu = stdlib_lsame( jobu, 'I' ) wantu = initu .or. stdlib_lsame( jobu, 'U' ) initv = stdlib_lsame( jobv, 'I' ) wantv = initv .or. stdlib_lsame( jobv, 'V' ) initq = stdlib_lsame( jobq, 'I' ) wantq = initq .or. stdlib_lsame( jobq, 'Q' ) info = 0_${ik}$ if( .not.( initu .or. wantu .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( initv .or. wantv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( initq .or. wantq .or. stdlib_lsame( jobq, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( p<0_${ik}$ ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda=-hugenum) ) then if( gamma=beta( k+i ) ) then call stdlib${ii}$_${ci}$dscal( l-i+1, one / alpha( k+i ), a( k+i, n-l+i ),lda ) else call stdlib${ii}$_${ci}$dscal( l-i+1, one / beta( k+i ), b( i, n-l+i ),ldb ) call stdlib${ii}$_${ci}$copy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if else alpha( k+i ) = zero beta( k+i ) = one call stdlib${ii}$_${ci}$copy( l-i+1, b( i, n-l+i ), ldb, a( k+i, n-l+i ),lda ) end if end do ! post-assignment do i = m + 1, k + l alpha( i ) = zero beta( i ) = one end do if( k+l= k, Q = H(1) H(2) . . . H(k) and CUNGBR returns the first n !! columns of Q, where m >= n >= k; !! if m < k, Q = H(1) H(2) . . . H(m-1) and CUNGBR returns Q as an !! M-by-M matrix. !! If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**H !! is of order N: !! if k < n, P**H = G(k) . . . G(2) G(1) and CUNGBR returns the first m !! rows of P**H, where n >= m >= k; !! if k >= n, P**H = G(n-1) . . . G(2) G(1) and CUNGBR returns P**H as !! an N-by-N matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantq integer(${ik}$) :: i, iinfo, j, lwkopt, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantq = stdlib_lsame( vect, 'Q' ) mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.wantq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ .or. ( wantq .and. ( n>m .or. nn .or. m=k ) then call stdlib${ii}$_cungqr( m, n, k, a, lda, tau, work, -1_${ik}$, iinfo ) else if( m>1_${ik}$ ) then call stdlib${ii}$_cungqr( m-1, m-1, m-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if else if( k1_${ik}$ ) then call stdlib${ii}$_cunglq( n-1, n-1, n-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if end if lwkopt = real( work( 1_${ik}$ ),KIND=sp) lwkopt = max (lwkopt, mn) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CUNGBR', -info ) return else if( lquery ) then work( 1_${ik}$ ) = lwkopt return end if ! quick return if possible if( m==0_${ik}$ .or. n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( wantq ) then ! form q, determined by a call to stdlib${ii}$_cgebrd to reduce an m-by-k ! matrix if( m>=k ) then ! if m >= k, assume m >= n >= k call stdlib${ii}$_cungqr( m, n, k, a, lda, tau, work, lwork, iinfo ) else ! if m < k, assume m = n ! shift the vectors which define the elementary reflectors cone ! column to the right, and set the first row and column of q ! to those of the unit matrix do j = m, 2, -1 a( 1_${ik}$, j ) = czero do i = j + 1, m a( i, j ) = a( i, j-1 ) end do end do a( 1_${ik}$, 1_${ik}$ ) = cone do i = 2, m a( i, 1_${ik}$ ) = czero end do if( m>1_${ik}$ ) then ! form q(2:m,2:m) call stdlib${ii}$_cungqr( m-1, m-1, m-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if else ! form p**h, determined by a call to stdlib${ii}$_cgebrd to reduce a k-by-n ! matrix if( k= n, assume m = n ! shift the vectors which define the elementary reflectors cone ! row downward, and set the first row and column of p**h to ! those of the unit matrix a( 1_${ik}$, 1_${ik}$ ) = cone do i = 2, n a( i, 1_${ik}$ ) = czero end do do j = 2, n do i = j - 1, 2, -1 a( i, j ) = a( i-1, j ) end do a( 1_${ik}$, j ) = czero end do if( n>1_${ik}$ ) then ! form p**h(2:n,2:n) call stdlib${ii}$_cunglq( n-1, n-1, n-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cungbr pure module subroutine stdlib${ii}$_zungbr( vect, m, n, k, a, lda, tau, work, lwork, info ) !! ZUNGBR generates one of the complex unitary matrices Q or P**H !! determined by ZGEBRD when reducing a complex matrix A to bidiagonal !! form: A = Q * B * P**H. Q and P**H are defined as products of !! elementary reflectors H(i) or G(i) respectively. !! If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q !! is of order M: !! if m >= k, Q = H(1) H(2) . . . H(k) and ZUNGBR returns the first n !! columns of Q, where m >= n >= k; !! if m < k, Q = H(1) H(2) . . . H(m-1) and ZUNGBR returns Q as an !! M-by-M matrix. !! If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**H !! is of order N: !! if k < n, P**H = G(k) . . . G(2) G(1) and ZUNGBR returns the first m !! rows of P**H, where n >= m >= k; !! if k >= n, P**H = G(n-1) . . . G(2) G(1) and ZUNGBR returns P**H as !! an N-by-N matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantq integer(${ik}$) :: i, iinfo, j, lwkopt, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantq = stdlib_lsame( vect, 'Q' ) mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.wantq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ .or. ( wantq .and. ( n>m .or. nn .or. m=k ) then call stdlib${ii}$_zungqr( m, n, k, a, lda, tau, work, -1_${ik}$, iinfo ) else if( m>1_${ik}$ ) then call stdlib${ii}$_zungqr( m-1, m-1, m-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if else if( k1_${ik}$ ) then call stdlib${ii}$_zunglq( n-1, n-1, n-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if end if lwkopt = real( work( 1_${ik}$ ),KIND=dp) lwkopt = max (lwkopt, mn) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNGBR', -info ) return else if( lquery ) then work( 1_${ik}$ ) = lwkopt return end if ! quick return if possible if( m==0_${ik}$ .or. n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( wantq ) then ! form q, determined by a call to stdlib${ii}$_zgebrd to reduce an m-by-k ! matrix if( m>=k ) then ! if m >= k, assume m >= n >= k call stdlib${ii}$_zungqr( m, n, k, a, lda, tau, work, lwork, iinfo ) else ! if m < k, assume m = n ! shift the vectors which define the elementary reflectors cone ! column to the right, and set the first row and column of q ! to those of the unit matrix do j = m, 2, -1 a( 1_${ik}$, j ) = czero do i = j + 1, m a( i, j ) = a( i, j-1 ) end do end do a( 1_${ik}$, 1_${ik}$ ) = cone do i = 2, m a( i, 1_${ik}$ ) = czero end do if( m>1_${ik}$ ) then ! form q(2:m,2:m) call stdlib${ii}$_zungqr( m-1, m-1, m-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if else ! form p**h, determined by a call to stdlib${ii}$_zgebrd to reduce a k-by-n ! matrix if( k= n, assume m = n ! shift the vectors which define the elementary reflectors cone ! row downward, and set the first row and column of p**h to ! those of the unit matrix a( 1_${ik}$, 1_${ik}$ ) = cone do i = 2, n a( i, 1_${ik}$ ) = czero end do do j = 2, n do i = j - 1, 2, -1 a( i, j ) = a( i-1, j ) end do a( 1_${ik}$, j ) = czero end do if( n>1_${ik}$ ) then ! form p**h(2:n,2:n) call stdlib${ii}$_zunglq( n-1, n-1, n-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zungbr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ungbr( vect, m, n, k, a, lda, tau, work, lwork, info ) !! ZUNGBR: generates one of the complex unitary matrices Q or P**H !! determined by ZGEBRD when reducing a complex matrix A to bidiagonal !! form: A = Q * B * P**H. Q and P**H are defined as products of !! elementary reflectors H(i) or G(i) respectively. !! If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q !! is of order M: !! if m >= k, Q = H(1) H(2) . . . H(k) and ZUNGBR returns the first n !! columns of Q, where m >= n >= k; !! if m < k, Q = H(1) H(2) . . . H(m-1) and ZUNGBR returns Q as an !! M-by-M matrix. !! If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**H !! is of order N: !! if k < n, P**H = G(k) . . . G(2) G(1) and ZUNGBR returns the first m !! rows of P**H, where n >= m >= k; !! if k >= n, P**H = G(n-1) . . . G(2) G(1) and ZUNGBR returns P**H as !! an N-by-N matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantq integer(${ik}$) :: i, iinfo, j, lwkopt, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantq = stdlib_lsame( vect, 'Q' ) mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.wantq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ .or. ( wantq .and. ( n>m .or. nn .or. m=k ) then call stdlib${ii}$_${ci}$ungqr( m, n, k, a, lda, tau, work, -1_${ik}$, iinfo ) else if( m>1_${ik}$ ) then call stdlib${ii}$_${ci}$ungqr( m-1, m-1, m-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if else if( k1_${ik}$ ) then call stdlib${ii}$_${ci}$unglq( n-1, n-1, n-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if end if lwkopt = real( work( 1_${ik}$ ),KIND=${ck}$) lwkopt = max (lwkopt, mn) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNGBR', -info ) return else if( lquery ) then work( 1_${ik}$ ) = lwkopt return end if ! quick return if possible if( m==0_${ik}$ .or. n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( wantq ) then ! form q, determined by a call to stdlib${ii}$_${ci}$gebrd to reduce an m-by-k ! matrix if( m>=k ) then ! if m >= k, assume m >= n >= k call stdlib${ii}$_${ci}$ungqr( m, n, k, a, lda, tau, work, lwork, iinfo ) else ! if m < k, assume m = n ! shift the vectors which define the elementary reflectors cone ! column to the right, and set the first row and column of q ! to those of the unit matrix do j = m, 2, -1 a( 1_${ik}$, j ) = czero do i = j + 1, m a( i, j ) = a( i, j-1 ) end do end do a( 1_${ik}$, 1_${ik}$ ) = cone do i = 2, m a( i, 1_${ik}$ ) = czero end do if( m>1_${ik}$ ) then ! form q(2:m,2:m) call stdlib${ii}$_${ci}$ungqr( m-1, m-1, m-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if else ! form p**h, determined by a call to stdlib${ii}$_${ci}$gebrd to reduce a k-by-n ! matrix if( k= n, assume m = n ! shift the vectors which define the elementary reflectors cone ! row downward, and set the first row and column of p**h to ! those of the unit matrix a( 1_${ik}$, 1_${ik}$ ) = cone do i = 2, n a( i, 1_${ik}$ ) = czero end do do j = 2, n do i = j - 1, 2, -1 a( i, j ) = a( i-1, j ) end do a( 1_${ik}$, j ) = czero end do if( n>1_${ik}$ ) then ! form p**h(2:n,2:n) call stdlib${ii}$_${ci}$unglq( n-1, n-1, n-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$ungbr #:endif #:endfor pure module subroutine stdlib${ii}$_sorgbr( vect, m, n, k, a, lda, tau, work, lwork, info ) !! SORGBR generates one of the real orthogonal matrices Q or P**T !! determined by SGEBRD when reducing a real matrix A to bidiagonal !! form: A = Q * B * P**T. Q and P**T are defined as products of !! elementary reflectors H(i) or G(i) respectively. !! If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q !! is of order M: !! if m >= k, Q = H(1) H(2) . . . H(k) and SORGBR returns the first n !! columns of Q, where m >= n >= k; !! if m < k, Q = H(1) H(2) . . . H(m-1) and SORGBR returns Q as an !! M-by-M matrix. !! If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**T !! is of order N: !! if k < n, P**T = G(k) . . . G(2) G(1) and SORGBR returns the first m !! rows of P**T, where n >= m >= k; !! if k >= n, P**T = G(n-1) . . . G(2) G(1) and SORGBR returns P**T as !! an N-by-N matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantq integer(${ik}$) :: i, iinfo, j, lwkopt, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantq = stdlib_lsame( vect, 'Q' ) mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.wantq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ .or. ( wantq .and. ( n>m .or. nn .or. m=k ) then call stdlib${ii}$_sorgqr( m, n, k, a, lda, tau, work, -1_${ik}$, iinfo ) else if( m>1_${ik}$ ) then call stdlib${ii}$_sorgqr( m-1, m-1, m-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if else if( k1_${ik}$ ) then call stdlib${ii}$_sorglq( n-1, n-1, n-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if end if lwkopt = work( 1_${ik}$ ) lwkopt = max (lwkopt, mn) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SORGBR', -info ) return else if( lquery ) then work( 1_${ik}$ ) = lwkopt return end if ! quick return if possible if( m==0_${ik}$ .or. n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( wantq ) then ! form q, determined by a call to stdlib${ii}$_sgebrd to reduce an m-by-k ! matrix if( m>=k ) then ! if m >= k, assume m >= n >= k call stdlib${ii}$_sorgqr( m, n, k, a, lda, tau, work, lwork, iinfo ) else ! if m < k, assume m = n ! shift the vectors which define the elementary reflectors one ! column to the right, and set the first row and column of q ! to those of the unit matrix do j = m, 2, -1 a( 1_${ik}$, j ) = zero do i = j + 1, m a( i, j ) = a( i, j-1 ) end do end do a( 1_${ik}$, 1_${ik}$ ) = one do i = 2, m a( i, 1_${ik}$ ) = zero end do if( m>1_${ik}$ ) then ! form q(2:m,2:m) call stdlib${ii}$_sorgqr( m-1, m-1, m-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if else ! form p**t, determined by a call to stdlib${ii}$_sgebrd to reduce a k-by-n ! matrix if( k= n, assume m = n ! shift the vectors which define the elementary reflectors one ! row downward, and set the first row and column of p**t to ! those of the unit matrix a( 1_${ik}$, 1_${ik}$ ) = one do i = 2, n a( i, 1_${ik}$ ) = zero end do do j = 2, n do i = j - 1, 2, -1 a( i, j ) = a( i-1, j ) end do a( 1_${ik}$, j ) = zero end do if( n>1_${ik}$ ) then ! form p**t(2:n,2:n) call stdlib${ii}$_sorglq( n-1, n-1, n-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_sorgbr pure module subroutine stdlib${ii}$_dorgbr( vect, m, n, k, a, lda, tau, work, lwork, info ) !! DORGBR generates one of the real orthogonal matrices Q or P**T !! determined by DGEBRD when reducing a real matrix A to bidiagonal !! form: A = Q * B * P**T. Q and P**T are defined as products of !! elementary reflectors H(i) or G(i) respectively. !! If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q !! is of order M: !! if m >= k, Q = H(1) H(2) . . . H(k) and DORGBR returns the first n !! columns of Q, where m >= n >= k; !! if m < k, Q = H(1) H(2) . . . H(m-1) and DORGBR returns Q as an !! M-by-M matrix. !! If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**T !! is of order N: !! if k < n, P**T = G(k) . . . G(2) G(1) and DORGBR returns the first m !! rows of P**T, where n >= m >= k; !! if k >= n, P**T = G(n-1) . . . G(2) G(1) and DORGBR returns P**T as !! an N-by-N matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantq integer(${ik}$) :: i, iinfo, j, lwkopt, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantq = stdlib_lsame( vect, 'Q' ) mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.wantq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ .or. ( wantq .and. ( n>m .or. nn .or. m=k ) then call stdlib${ii}$_dorgqr( m, n, k, a, lda, tau, work, -1_${ik}$, iinfo ) else if( m>1_${ik}$ ) then call stdlib${ii}$_dorgqr( m-1, m-1, m-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if else if( k1_${ik}$ ) then call stdlib${ii}$_dorglq( n-1, n-1, n-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if end if lwkopt = work( 1_${ik}$ ) lwkopt = max (lwkopt, mn) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORGBR', -info ) return else if( lquery ) then work( 1_${ik}$ ) = lwkopt return end if ! quick return if possible if( m==0_${ik}$ .or. n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( wantq ) then ! form q, determined by a call to stdlib${ii}$_dgebrd to reduce an m-by-k ! matrix if( m>=k ) then ! if m >= k, assume m >= n >= k call stdlib${ii}$_dorgqr( m, n, k, a, lda, tau, work, lwork, iinfo ) else ! if m < k, assume m = n ! shift the vectors which define the elementary reflectors one ! column to the right, and set the first row and column of q ! to those of the unit matrix do j = m, 2, -1 a( 1_${ik}$, j ) = zero do i = j + 1, m a( i, j ) = a( i, j-1 ) end do end do a( 1_${ik}$, 1_${ik}$ ) = one do i = 2, m a( i, 1_${ik}$ ) = zero end do if( m>1_${ik}$ ) then ! form q(2:m,2:m) call stdlib${ii}$_dorgqr( m-1, m-1, m-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if else ! form p**t, determined by a call to stdlib${ii}$_dgebrd to reduce a k-by-n ! matrix if( k= n, assume m = n ! shift the vectors which define the elementary reflectors one ! row downward, and set the first row and column of p**t to ! those of the unit matrix a( 1_${ik}$, 1_${ik}$ ) = one do i = 2, n a( i, 1_${ik}$ ) = zero end do do j = 2, n do i = j - 1, 2, -1 a( i, j ) = a( i-1, j ) end do a( 1_${ik}$, j ) = zero end do if( n>1_${ik}$ ) then ! form p**t(2:n,2:n) call stdlib${ii}$_dorglq( n-1, n-1, n-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dorgbr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orgbr( vect, m, n, k, a, lda, tau, work, lwork, info ) !! DORGBR: generates one of the real orthogonal matrices Q or P**T !! determined by DGEBRD when reducing a real matrix A to bidiagonal !! form: A = Q * B * P**T. Q and P**T are defined as products of !! elementary reflectors H(i) or G(i) respectively. !! If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q !! is of order M: !! if m >= k, Q = H(1) H(2) . . . H(k) and DORGBR returns the first n !! columns of Q, where m >= n >= k; !! if m < k, Q = H(1) H(2) . . . H(m-1) and DORGBR returns Q as an !! M-by-M matrix. !! If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**T !! is of order N: !! if k < n, P**T = G(k) . . . G(2) G(1) and DORGBR returns the first m !! rows of P**T, where n >= m >= k; !! if k >= n, P**T = G(n-1) . . . G(2) G(1) and DORGBR returns P**T as !! an N-by-N matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantq integer(${ik}$) :: i, iinfo, j, lwkopt, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantq = stdlib_lsame( vect, 'Q' ) mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.wantq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ .or. ( wantq .and. ( n>m .or. nn .or. m=k ) then call stdlib${ii}$_${ri}$orgqr( m, n, k, a, lda, tau, work, -1_${ik}$, iinfo ) else if( m>1_${ik}$ ) then call stdlib${ii}$_${ri}$orgqr( m-1, m-1, m-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if else if( k1_${ik}$ ) then call stdlib${ii}$_${ri}$orglq( n-1, n-1, n-1, a, lda, tau, work, -1_${ik}$,iinfo ) end if end if end if lwkopt = work( 1_${ik}$ ) lwkopt = max (lwkopt, mn) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORGBR', -info ) return else if( lquery ) then work( 1_${ik}$ ) = lwkopt return end if ! quick return if possible if( m==0_${ik}$ .or. n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( wantq ) then ! form q, determined by a call to stdlib${ii}$_${ri}$gebrd to reduce an m-by-k ! matrix if( m>=k ) then ! if m >= k, assume m >= n >= k call stdlib${ii}$_${ri}$orgqr( m, n, k, a, lda, tau, work, lwork, iinfo ) else ! if m < k, assume m = n ! shift the vectors which define the elementary reflectors one ! column to the right, and set the first row and column of q ! to those of the unit matrix do j = m, 2, -1 a( 1_${ik}$, j ) = zero do i = j + 1, m a( i, j ) = a( i, j-1 ) end do end do a( 1_${ik}$, 1_${ik}$ ) = one do i = 2, m a( i, 1_${ik}$ ) = zero end do if( m>1_${ik}$ ) then ! form q(2:m,2:m) call stdlib${ii}$_${ri}$orgqr( m-1, m-1, m-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if else ! form p**t, determined by a call to stdlib${ii}$_${ri}$gebrd to reduce a k-by-n ! matrix if( k= n, assume m = n ! shift the vectors which define the elementary reflectors one ! row downward, and set the first row and column of p**t to ! those of the unit matrix a( 1_${ik}$, 1_${ik}$ ) = one do i = 2, n a( i, 1_${ik}$ ) = zero end do do j = 2, n do i = j - 1, 2, -1 a( i, j ) = a( i-1, j ) end do a( 1_${ik}$, j ) = zero end do if( n>1_${ik}$ ) then ! form p**t(2:n,2:n) call stdlib${ii}$_${ri}$orglq( n-1, n-1, n-1, a( 2_${ik}$, 2_${ik}$ ), lda, tau, work,lwork, iinfo ) end if end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$orgbr #:endif #:endfor pure module subroutine stdlib${ii}$_cunmbr( vect, side, trans, m, n, k, a, lda, tau, c,ldc, work, lwork, & !! If VECT = 'Q', CUNMBR: overwrites the general complex M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! If VECT = 'P', CUNMBR overwrites the general complex M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': P * C C * P !! TRANS = 'C': P**H * C C * P**H !! Here Q and P**H are the unitary matrices determined by CGEBRD when !! reducing a complex matrix A to bidiagonal form: A = Q * B * P**H. Q !! and P**H are defined as products of elementary reflectors H(i) and !! G(i) respectively. !! Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the !! order of the unitary matrix Q or P**H that is applied. !! If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: !! if nq >= k, Q = H(1) H(2) . . . H(k); !! if nq < k, Q = H(1) H(2) . . . H(nq-1). !! If VECT = 'P', A is assumed to have been a K-by-NQ matrix: !! if k < nq, P = G(1) G(2) . . . G(k); !! if k >= nq, P = G(1) G(2) . . . G(nq-1). info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: applyq, left, lquery, notran character :: transt integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ applyq = stdlib_lsame( vect, 'Q' ) left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q or p and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.applyq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -2_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( k<0_${ik}$ ) then info = -6_${ik}$ else if( ( applyq .and. lda0_${ik}$ .and. n>0_${ik}$ ) then if( applyq ) then if( left ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', side // trans, m-1, n, m-1,-1_${ik}$ ) else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', side // trans, m, n-1, n-1,-1_${ik}$ ) end if else if( left ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMLQ', side // trans, m-1, n, m-1,-1_${ik}$ ) else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMLQ', side // trans, m, n-1, n-1,-1_${ik}$ ) end if end if lwkopt = nw*nb else lwkopt = 1_${ik}$ end if work( 1_${ik}$ ) = lwkopt end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CUNMBR', -info ) return else if( lquery ) then return end if ! quick return if possible if( m==0 .or. n==0 )return if( applyq ) then ! apply q if( nq>=k ) then ! q was determined by a call to stdlib${ii}$_cgebrd with nq >= k call stdlib${ii}$_cunmqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, iinfo & ) else if( nq>1_${ik}$ ) then ! q was determined by a call to stdlib${ii}$_cgebrd with nq < k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_cunmqr( side, trans, mi, ni, nq-1, a( 2_${ik}$, 1_${ik}$ ), lda, tau,c( i1, i2 ), & ldc, work, lwork, iinfo ) end if else ! apply p if( notran ) then transt = 'C' else transt = 'N' end if if( nq>k ) then ! p was determined by a call to stdlib${ii}$_cgebrd with nq > k call stdlib${ii}$_cunmlq( side, transt, m, n, k, a, lda, tau, c, ldc,work, lwork, & iinfo ) else if( nq>1_${ik}$ ) then ! p was determined by a call to stdlib${ii}$_cgebrd with nq <= k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_cunmlq( side, transt, mi, ni, nq-1, a( 1_${ik}$, 2_${ik}$ ), lda,tau, c( i1, i2 ), & ldc, work, lwork, iinfo ) end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cunmbr pure module subroutine stdlib${ii}$_zunmbr( vect, side, trans, m, n, k, a, lda, tau, c,ldc, work, lwork, & !! If VECT = 'Q', ZUNMBR: overwrites the general complex M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! If VECT = 'P', ZUNMBR overwrites the general complex M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': P * C C * P !! TRANS = 'C': P**H * C C * P**H !! Here Q and P**H are the unitary matrices determined by ZGEBRD when !! reducing a complex matrix A to bidiagonal form: A = Q * B * P**H. Q !! and P**H are defined as products of elementary reflectors H(i) and !! G(i) respectively. !! Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the !! order of the unitary matrix Q or P**H that is applied. !! If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: !! if nq >= k, Q = H(1) H(2) . . . H(k); !! if nq < k, Q = H(1) H(2) . . . H(nq-1). !! If VECT = 'P', A is assumed to have been a K-by-NQ matrix: !! if k < nq, P = G(1) G(2) . . . G(k); !! if k >= nq, P = G(1) G(2) . . . G(nq-1). info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: applyq, left, lquery, notran character :: transt integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ applyq = stdlib_lsame( vect, 'Q' ) left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q or p and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.applyq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -2_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( k<0_${ik}$ ) then info = -6_${ik}$ else if( ( applyq .and. lda0_${ik}$ .and. n>0_${ik}$ ) then if( applyq ) then if( left ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', side // trans, m-1, n, m-1,-1_${ik}$ ) else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', side // trans, m, n-1, n-1,-1_${ik}$ ) end if else if( left ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMLQ', side // trans, m-1, n, m-1,-1_${ik}$ ) else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMLQ', side // trans, m, n-1, n-1,-1_${ik}$ ) end if end if lwkopt = nw*nb else lwkopt = 1_${ik}$ end if work( 1_${ik}$ ) = lwkopt end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNMBR', -info ) return else if( lquery ) then return end if ! quick return if possible if( m==0 .or. n==0 )return if( applyq ) then ! apply q if( nq>=k ) then ! q was determined by a call to stdlib${ii}$_zgebrd with nq >= k call stdlib${ii}$_zunmqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, iinfo & ) else if( nq>1_${ik}$ ) then ! q was determined by a call to stdlib${ii}$_zgebrd with nq < k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_zunmqr( side, trans, mi, ni, nq-1, a( 2_${ik}$, 1_${ik}$ ), lda, tau,c( i1, i2 ), & ldc, work, lwork, iinfo ) end if else ! apply p if( notran ) then transt = 'C' else transt = 'N' end if if( nq>k ) then ! p was determined by a call to stdlib${ii}$_zgebrd with nq > k call stdlib${ii}$_zunmlq( side, transt, m, n, k, a, lda, tau, c, ldc,work, lwork, & iinfo ) else if( nq>1_${ik}$ ) then ! p was determined by a call to stdlib${ii}$_zgebrd with nq <= k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_zunmlq( side, transt, mi, ni, nq-1, a( 1_${ik}$, 2_${ik}$ ), lda,tau, c( i1, i2 ), & ldc, work, lwork, iinfo ) end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zunmbr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unmbr( vect, side, trans, m, n, k, a, lda, tau, c,ldc, work, lwork, & !! If VECT = 'Q', ZUNMBR: overwrites the general complex M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! If VECT = 'P', ZUNMBR overwrites the general complex M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': P * C C * P !! TRANS = 'C': P**H * C C * P**H !! Here Q and P**H are the unitary matrices determined by ZGEBRD when !! reducing a complex matrix A to bidiagonal form: A = Q * B * P**H. Q !! and P**H are defined as products of elementary reflectors H(i) and !! G(i) respectively. !! Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the !! order of the unitary matrix Q or P**H that is applied. !! If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: !! if nq >= k, Q = H(1) H(2) . . . H(k); !! if nq < k, Q = H(1) H(2) . . . H(nq-1). !! If VECT = 'P', A is assumed to have been a K-by-NQ matrix: !! if k < nq, P = G(1) G(2) . . . G(k); !! if k >= nq, P = G(1) G(2) . . . G(nq-1). info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: applyq, left, lquery, notran character :: transt integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ applyq = stdlib_lsame( vect, 'Q' ) left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q or p and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.applyq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -2_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( k<0_${ik}$ ) then info = -6_${ik}$ else if( ( applyq .and. lda0_${ik}$ .and. n>0_${ik}$ ) then if( applyq ) then if( left ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', side // trans, m-1, n, m-1,-1_${ik}$ ) else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', side // trans, m, n-1, n-1,-1_${ik}$ ) end if else if( left ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMLQ', side // trans, m-1, n, m-1,-1_${ik}$ ) else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMLQ', side // trans, m, n-1, n-1,-1_${ik}$ ) end if end if lwkopt = nw*nb else lwkopt = 1_${ik}$ end if work( 1_${ik}$ ) = lwkopt end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNMBR', -info ) return else if( lquery ) then return end if ! quick return if possible if( m==0 .or. n==0 )return if( applyq ) then ! apply q if( nq>=k ) then ! q was determined by a call to stdlib${ii}$_${ci}$gebrd with nq >= k call stdlib${ii}$_${ci}$unmqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, iinfo & ) else if( nq>1_${ik}$ ) then ! q was determined by a call to stdlib${ii}$_${ci}$gebrd with nq < k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_${ci}$unmqr( side, trans, mi, ni, nq-1, a( 2_${ik}$, 1_${ik}$ ), lda, tau,c( i1, i2 ), & ldc, work, lwork, iinfo ) end if else ! apply p if( notran ) then transt = 'C' else transt = 'N' end if if( nq>k ) then ! p was determined by a call to stdlib${ii}$_${ci}$gebrd with nq > k call stdlib${ii}$_${ci}$unmlq( side, transt, m, n, k, a, lda, tau, c, ldc,work, lwork, & iinfo ) else if( nq>1_${ik}$ ) then ! p was determined by a call to stdlib${ii}$_${ci}$gebrd with nq <= k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_${ci}$unmlq( side, transt, mi, ni, nq-1, a( 1_${ik}$, 2_${ik}$ ), lda,tau, c( i1, i2 ), & ldc, work, lwork, iinfo ) end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$unmbr #:endif #:endfor pure module subroutine stdlib${ii}$_sormbr( vect, side, trans, m, n, k, a, lda, tau, c,ldc, work, lwork, & !! If VECT = 'Q', SORMBR: overwrites the general real M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! If VECT = 'P', SORMBR overwrites the general real M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': P * C C * P !! TRANS = 'T': P**T * C C * P**T !! Here Q and P**T are the orthogonal matrices determined by SGEBRD when !! reducing a real matrix A to bidiagonal form: A = Q * B * P**T. Q and !! P**T are defined as products of elementary reflectors H(i) and G(i) !! respectively. !! Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the !! order of the orthogonal matrix Q or P**T that is applied. !! If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: !! if nq >= k, Q = H(1) H(2) . . . H(k); !! if nq < k, Q = H(1) H(2) . . . H(nq-1). !! If VECT = 'P', A is assumed to have been a K-by-NQ matrix: !! if k < nq, P = G(1) G(2) . . . G(k); !! if k >= nq, P = G(1) G(2) . . . G(nq-1). info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: applyq, left, lquery, notran character :: transt integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ applyq = stdlib_lsame( vect, 'Q' ) left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q or p and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.applyq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -2_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( k<0_${ik}$ ) then info = -6_${ik}$ else if( ( applyq .and. lda=k ) then ! q was determined by a call to stdlib${ii}$_sgebrd with nq >= k call stdlib${ii}$_sormqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, iinfo & ) else if( nq>1_${ik}$ ) then ! q was determined by a call to stdlib${ii}$_sgebrd with nq < k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_sormqr( side, trans, mi, ni, nq-1, a( 2_${ik}$, 1_${ik}$ ), lda, tau,c( i1, i2 ), & ldc, work, lwork, iinfo ) end if else ! apply p if( notran ) then transt = 'T' else transt = 'N' end if if( nq>k ) then ! p was determined by a call to stdlib${ii}$_sgebrd with nq > k call stdlib${ii}$_sormlq( side, transt, m, n, k, a, lda, tau, c, ldc,work, lwork, & iinfo ) else if( nq>1_${ik}$ ) then ! p was determined by a call to stdlib${ii}$_sgebrd with nq <= k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_sormlq( side, transt, mi, ni, nq-1, a( 1_${ik}$, 2_${ik}$ ), lda,tau, c( i1, i2 ), & ldc, work, lwork, iinfo ) end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_sormbr pure module subroutine stdlib${ii}$_dormbr( vect, side, trans, m, n, k, a, lda, tau, c,ldc, work, lwork, & !! If VECT = 'Q', DORMBR: overwrites the general real M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! If VECT = 'P', DORMBR overwrites the general real M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': P * C C * P !! TRANS = 'T': P**T * C C * P**T !! Here Q and P**T are the orthogonal matrices determined by DGEBRD when !! reducing a real matrix A to bidiagonal form: A = Q * B * P**T. Q and !! P**T are defined as products of elementary reflectors H(i) and G(i) !! respectively. !! Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the !! order of the orthogonal matrix Q or P**T that is applied. !! If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: !! if nq >= k, Q = H(1) H(2) . . . H(k); !! if nq < k, Q = H(1) H(2) . . . H(nq-1). !! If VECT = 'P', A is assumed to have been a K-by-NQ matrix: !! if k < nq, P = G(1) G(2) . . . G(k); !! if k >= nq, P = G(1) G(2) . . . G(nq-1). info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: applyq, left, lquery, notran character :: transt integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ applyq = stdlib_lsame( vect, 'Q' ) left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q or p and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.applyq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -2_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( k<0_${ik}$ ) then info = -6_${ik}$ else if( ( applyq .and. lda=k ) then ! q was determined by a call to stdlib${ii}$_dgebrd with nq >= k call stdlib${ii}$_dormqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, iinfo & ) else if( nq>1_${ik}$ ) then ! q was determined by a call to stdlib${ii}$_dgebrd with nq < k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_dormqr( side, trans, mi, ni, nq-1, a( 2_${ik}$, 1_${ik}$ ), lda, tau,c( i1, i2 ), & ldc, work, lwork, iinfo ) end if else ! apply p if( notran ) then transt = 'T' else transt = 'N' end if if( nq>k ) then ! p was determined by a call to stdlib${ii}$_dgebrd with nq > k call stdlib${ii}$_dormlq( side, transt, m, n, k, a, lda, tau, c, ldc,work, lwork, & iinfo ) else if( nq>1_${ik}$ ) then ! p was determined by a call to stdlib${ii}$_dgebrd with nq <= k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_dormlq( side, transt, mi, ni, nq-1, a( 1_${ik}$, 2_${ik}$ ), lda,tau, c( i1, i2 ), & ldc, work, lwork, iinfo ) end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dormbr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ormbr( vect, side, trans, m, n, k, a, lda, tau, c,ldc, work, lwork, & !! If VECT = 'Q', DORMBR: overwrites the general real M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! If VECT = 'P', DORMBR overwrites the general real M-by-N matrix C !! with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': P * C C * P !! TRANS = 'T': P**T * C C * P**T !! Here Q and P**T are the orthogonal matrices determined by DGEBRD when !! reducing a real matrix A to bidiagonal form: A = Q * B * P**T. Q and !! P**T are defined as products of elementary reflectors H(i) and G(i) !! respectively. !! Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the !! order of the orthogonal matrix Q or P**T that is applied. !! If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: !! if nq >= k, Q = H(1) H(2) . . . H(k); !! if nq < k, Q = H(1) H(2) . . . H(nq-1). !! If VECT = 'P', A is assumed to have been a K-by-NQ matrix: !! if k < nq, P = G(1) G(2) . . . G(k); !! if k >= nq, P = G(1) G(2) . . . G(nq-1). info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: applyq, left, lquery, notran character :: transt integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ applyq = stdlib_lsame( vect, 'Q' ) left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q or p and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.applyq .and. .not.stdlib_lsame( vect, 'P' ) ) then info = -1_${ik}$ else if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -2_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( k<0_${ik}$ ) then info = -6_${ik}$ else if( ( applyq .and. lda=k ) then ! q was determined by a call to stdlib${ii}$_${ri}$gebrd with nq >= k call stdlib${ii}$_${ri}$ormqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, iinfo & ) else if( nq>1_${ik}$ ) then ! q was determined by a call to stdlib${ii}$_${ri}$gebrd with nq < k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_${ri}$ormqr( side, trans, mi, ni, nq-1, a( 2_${ik}$, 1_${ik}$ ), lda, tau,c( i1, i2 ), & ldc, work, lwork, iinfo ) end if else ! apply p if( notran ) then transt = 'T' else transt = 'N' end if if( nq>k ) then ! p was determined by a call to stdlib${ii}$_${ri}$gebrd with nq > k call stdlib${ii}$_${ri}$ormlq( side, transt, m, n, k, a, lda, tau, c, ldc,work, lwork, & iinfo ) else if( nq>1_${ik}$ ) then ! p was determined by a call to stdlib${ii}$_${ri}$gebrd with nq <= k if( left ) then mi = m - 1_${ik}$ ni = n i1 = 2_${ik}$ i2 = 1_${ik}$ else mi = m ni = n - 1_${ik}$ i1 = 1_${ik}$ i2 = 2_${ik}$ end if call stdlib${ii}$_${ri}$ormlq( side, transt, mi, ni, nq-1, a( 1_${ik}$, 2_${ik}$ ), lda,tau, c( i1, i2 ), & ldc, work, lwork, iinfo ) end if end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$ormbr #:endif #:endfor #:endfor end submodule stdlib_lapack_svd_comp fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_others.fypp0000664000175000017500000004533115135654166025276 0ustar alastairalastair#:include "common.fypp" module stdlib_lapack_others use stdlib_linalg_constants use stdlib_linalg_lapack_aux use stdlib_linalg_blas use stdlib_lapack_solve implicit none interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_sla_syrpvgrw( uplo, n, info, a, lda, af, ldaf, ipiv,work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(in) :: a(lda,*), af(ldaf,*) real(sp), intent(out) :: work(*) end function stdlib${ii}$_sla_syrpvgrw real(dp) module function stdlib${ii}$_dla_syrpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(in) :: a(lda,*), af(ldaf,*) real(dp), intent(out) :: work(*) end function stdlib${ii}$_dla_syrpvgrw #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$la_syrpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(in) :: a(lda,*), af(ldaf,*) real(${rk}$), intent(out) :: work(*) end function stdlib${ii}$_${ri}$la_syrpvgrw #:endif #:endfor real(sp) module function stdlib${ii}$_cla_syrpvgrw( uplo, n, info, a, lda, af, ldaf, ipiv,work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf complex(sp), intent(in) :: a(lda,*), af(ldaf,*) real(sp), intent(out) :: work(*) integer(${ik}$), intent(in) :: ipiv(*) end function stdlib${ii}$_cla_syrpvgrw real(dp) module function stdlib${ii}$_zla_syrpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf complex(dp), intent(in) :: a(lda,*), af(ldaf,*) real(dp), intent(out) :: work(*) integer(${ik}$), intent(in) :: ipiv(*) end function stdlib${ii}$_zla_syrpvgrw #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$la_syrpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*) real(${ck}$), intent(out) :: work(*) integer(${ik}$), intent(in) :: ipiv(*) end function stdlib${ii}$_${ci}$la_syrpvgrw #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure real(sp) module function stdlib${ii}$_sla_gerpvgrw( n, ncols, a, lda, af, ldaf ) integer(${ik}$), intent(in) :: n, ncols, lda, ldaf real(sp), intent(in) :: a(lda,*), af(ldaf,*) end function stdlib${ii}$_sla_gerpvgrw pure real(dp) module function stdlib${ii}$_dla_gerpvgrw( n, ncols, a, lda, af,ldaf ) integer(${ik}$), intent(in) :: n, ncols, lda, ldaf real(dp), intent(in) :: a(lda,*), af(ldaf,*) end function stdlib${ii}$_dla_gerpvgrw #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$la_gerpvgrw( n, ncols, a, lda, af,ldaf ) integer(${ik}$), intent(in) :: n, ncols, lda, ldaf real(${rk}$), intent(in) :: a(lda,*), af(ldaf,*) end function stdlib${ii}$_${ri}$la_gerpvgrw #:endif #:endfor pure real(sp) module function stdlib${ii}$_cla_gerpvgrw( n, ncols, a, lda, af, ldaf ) integer(${ik}$), intent(in) :: n, ncols, lda, ldaf complex(sp), intent(in) :: a(lda,*), af(ldaf,*) end function stdlib${ii}$_cla_gerpvgrw pure real(dp) module function stdlib${ii}$_zla_gerpvgrw( n, ncols, a, lda, af,ldaf ) integer(${ik}$), intent(in) :: n, ncols, lda, ldaf complex(dp), intent(in) :: a(lda,*), af(ldaf,*) end function stdlib${ii}$_zla_gerpvgrw #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure real(${ck}$) module function stdlib${ii}$_${ci}$la_gerpvgrw( n, ncols, a, lda, af,ldaf ) integer(${ik}$), intent(in) :: n, ncols, lda, ldaf complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*) end function stdlib${ii}$_${ci}$la_gerpvgrw #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_cla_gbrcond_c( trans, n, kl, ku, ab, ldab, afb,ldafb, ipiv, c, & capply, info, work,rwork ) character, intent(in) :: trans logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, kl, ku, ldab, ldafb integer(${ik}$) :: kd, ke integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: ab(ldab,*), afb(ldafb,*) complex(sp), intent(out) :: work(*) real(sp), intent(in) :: c(*) real(sp), intent(out) :: rwork(*) end function stdlib${ii}$_cla_gbrcond_c real(dp) module function stdlib${ii}$_zla_gbrcond_c( trans, n, kl, ku, ab,ldab, afb, ldafb, ipiv,c, & capply, info, work,rwork ) character, intent(in) :: trans logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, kl, ku, ldab, ldafb integer(${ik}$) :: kd, ke integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: ab(ldab,*), afb(ldafb,*) complex(dp), intent(out) :: work(*) real(dp), intent(in) :: c(*) real(dp), intent(out) :: rwork(*) end function stdlib${ii}$_zla_gbrcond_c #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$la_gbrcond_c( trans, n, kl, ku, ab,ldab, afb, ldafb, ipiv,c, & capply, info, work,rwork ) character, intent(in) :: trans logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, kl, ku, ldab, ldafb integer(${ik}$) :: kd, ke integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: ab(ldab,*), afb(ldafb,*) complex(${ck}$), intent(out) :: work(*) real(${ck}$), intent(in) :: c(*) real(${ck}$), intent(out) :: rwork(*) end function stdlib${ii}$_${ci}$la_gbrcond_c #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_cla_gercond_c( trans, n, a, lda, af, ldaf, ipiv, c,capply, info, & work, rwork ) character, intent(in) :: trans logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: a(lda,*), af(ldaf,*) complex(sp), intent(out) :: work(*) real(sp), intent(in) :: c(*) real(sp), intent(out) :: rwork(*) end function stdlib${ii}$_cla_gercond_c real(dp) module function stdlib${ii}$_zla_gercond_c( trans, n, a, lda, af,ldaf, ipiv, c, capply,info, & work, rwork ) character, intent(in) :: trans logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*), af(ldaf,*) complex(dp), intent(out) :: work(*) real(dp), intent(in) :: c(*) real(dp), intent(out) :: rwork(*) end function stdlib${ii}$_zla_gercond_c #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$la_gercond_c( trans, n, a, lda, af,ldaf, ipiv, c, capply,info, & work, rwork ) character, intent(in) :: trans logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*) complex(${ck}$), intent(out) :: work(*) real(${ck}$), intent(in) :: c(*) real(${ck}$), intent(out) :: rwork(*) end function stdlib${ii}$_${ci}$la_gercond_c #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_cla_hercond_c( uplo, n, a, lda, af, ldaf, ipiv, c,capply, info, & work, rwork ) character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: a(lda,*), af(ldaf,*) complex(sp), intent(out) :: work(*) real(sp), intent(in) :: c(*) real(sp), intent(out) :: rwork(*) end function stdlib${ii}$_cla_hercond_c real(dp) module function stdlib${ii}$_zla_hercond_c( uplo, n, a, lda, af,ldaf, ipiv, c, capply,info, work,& rwork ) character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*), af(ldaf,*) complex(dp), intent(out) :: work(*) real(dp), intent(in) :: c(*) real(dp), intent(out) :: rwork(*) end function stdlib${ii}$_zla_hercond_c #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$la_hercond_c( uplo, n, a, lda, af,ldaf, ipiv, c, capply,info, work,& rwork ) character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*) complex(${ck}$), intent(out) :: work(*) real(${ck}$), intent(in) :: c(*) real(${ck}$), intent(out) :: rwork(*) end function stdlib${ii}$_${ci}$la_hercond_c #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_sla_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n, uplo real(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) end subroutine stdlib${ii}$_sla_syamv module subroutine stdlib${ii}$_dla_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n, uplo real(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) end subroutine stdlib${ii}$_dla_syamv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$la_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n, uplo real(${rk}$), intent(in) :: a(lda,*), x(*) real(${rk}$), intent(inout) :: y(*) end subroutine stdlib${ii}$_${ri}$la_syamv #:endif #:endfor module subroutine stdlib${ii}$_cla_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n integer(${ik}$), intent(in) :: uplo complex(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) end subroutine stdlib${ii}$_cla_syamv module subroutine stdlib${ii}$_zla_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n integer(${ik}$), intent(in) :: uplo complex(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) end subroutine stdlib${ii}$_zla_syamv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$la_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) real(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n integer(${ik}$), intent(in) :: uplo complex(${ck}$), intent(in) :: a(lda,*), x(*) real(${ck}$), intent(inout) :: y(*) end subroutine stdlib${ii}$_${ci}$la_syamv #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_sla_syrcond( uplo, n, a, lda, af, ldaf, ipiv, cmode,c, info, work, & iwork ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, ldaf, cmode integer(${ik}$), intent(out) :: info integer(${ik}$), intent(out) :: iwork(*) integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(in) :: a(lda,*), af(ldaf,*), c(*) real(sp), intent(out) :: work(*) end function stdlib${ii}$_sla_syrcond real(dp) module function stdlib${ii}$_dla_syrcond( uplo, n, a, lda, af, ldaf,ipiv, cmode, c, info, work,& iwork ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, ldaf, cmode integer(${ik}$), intent(out) :: info integer(${ik}$), intent(out) :: iwork(*) integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(in) :: a(lda,*), af(ldaf,*), c(*) real(dp), intent(out) :: work(*) end function stdlib${ii}$_dla_syrcond #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$la_syrcond( uplo, n, a, lda, af, ldaf,ipiv, cmode, c, info, work,& iwork ) character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, ldaf, cmode integer(${ik}$), intent(out) :: info integer(${ik}$), intent(out) :: iwork(*) integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(in) :: a(lda,*), af(ldaf,*), c(*) real(${rk}$), intent(out) :: work(*) end function stdlib${ii}$_${ri}$la_syrcond #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_cla_syrcond_c( uplo, n, a, lda, af, ldaf, ipiv, c,capply, info, & work, rwork ) character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: a(lda,*), af(ldaf,*) complex(sp), intent(out) :: work(*) real(sp), intent(in) :: c(*) real(sp), intent(out) :: rwork(*) end function stdlib${ii}$_cla_syrcond_c real(dp) module function stdlib${ii}$_zla_syrcond_c( uplo, n, a, lda, af,ldaf, ipiv, c, capply,info, work,& rwork ) character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*), af(ldaf,*) complex(dp), intent(out) :: work(*) real(dp), intent(in) :: c(*) real(dp), intent(out) :: rwork(*) end function stdlib${ii}$_zla_syrcond_c #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$la_syrcond_c( uplo, n, a, lda, af,ldaf, ipiv, c, capply,info, work,& rwork ) character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*) complex(${ck}$), intent(out) :: work(*) real(${ck}$), intent(in) :: c(*) real(${ck}$), intent(out) :: rwork(*) end function stdlib${ii}$_${ci}$la_syrcond_c #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES real(sp) module function stdlib${ii}$_cla_porcond_c( uplo, n, a, lda, af, ldaf, c, capply,info, work, & rwork ) character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info complex(sp), intent(in) :: a(lda,*), af(ldaf,*) complex(sp), intent(out) :: work(*) real(sp), intent(in) :: c(*) real(sp), intent(out) :: rwork(*) end function stdlib${ii}$_cla_porcond_c real(dp) module function stdlib${ii}$_zla_porcond_c( uplo, n, a, lda, af,ldaf, c, capply, info,work, & rwork ) character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info complex(dp), intent(in) :: a(lda,*), af(ldaf,*) complex(dp), intent(out) :: work(*) real(dp), intent(in) :: c(*) real(dp), intent(out) :: rwork(*) end function stdlib${ii}$_zla_porcond_c #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$la_porcond_c( uplo, n, a, lda, af,ldaf, c, capply, info,work, & rwork ) character, intent(in) :: uplo logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, lda, ldaf integer(${ik}$), intent(out) :: info complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*) complex(${ck}$), intent(out) :: work(*) real(${ck}$), intent(in) :: c(*) real(${ck}$), intent(out) :: rwork(*) end function stdlib${ii}$_${ci}$la_porcond_c #:endif #:endfor #:endfor end interface end module stdlib_lapack_others fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_eigv_comp.fypp0000664000175000017500000175275315135654166025760 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_eigv_comp implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sggbal( job, n, a, lda, b, ldb, ilo, ihi, lscale,rscale, work, info ) !! SGGBAL balances a pair of general real matrices (A,B). This !! involves, first, permuting A and B by similarity transformations to !! isolate eigenvalues in the first 1 to ILO$-$1 and last IHI+1 to N !! elements on the diagonal; and second, applying a diagonal similarity !! transformation to rows and columns ILO to IHI to make the rows !! and columns as close in norm as possible. Both steps are optional. !! Balancing may reduce the 1-norm of the matrices, and improve the !! accuracy of the computed eigenvalues and/or eigenvectors in the !! generalized eigenvalue problem A*x = lambda*B*x. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: job integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldb, n ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: lscale(*), rscale(*), work(*) ! ===================================================================== ! Parameters real(sp), parameter :: sclfac = ten ! Local Scalars integer(${ik}$) :: i, icab, iflow, ip1, ir, irab, it, j, jc, jp1, k, kount, l, lcab, lm1, & lrab, lsfmax, lsfmin, m, nr, nrp2 real(sp) :: alpha, basl, beta, cab, cmax, coef, coef2, coef5, cor, ew, ewc, gamma, & pgamma, rab, sfmax, sfmin, sum, t, ta, tb, tc ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) & .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldacmax )cmax = abs( cor ) lscale( i ) = lscale( i ) + cor cor = alpha*work( i ) if( abs( cor )>cmax )cmax = abs( cor ) rscale( i ) = rscale( i ) + cor end do if( cmaxcmax )cmax = abs( cor ) lscale( i ) = lscale( i ) + cor cor = alpha*work( i ) if( abs( cor )>cmax )cmax = abs( cor ) rscale( i ) = rscale( i ) + cor end do if( cmaxcmax )cmax = abs( cor ) lscale( i ) = lscale( i ) + cor cor = alpha*work( i ) if( abs( cor )>cmax )cmax = abs( cor ) rscale( i ) = rscale( i ) + cor end do if( cmaxcmax )cmax = abs( cor ) lscale( i ) = lscale( i ) + cor cor = alpha*work( i ) if( abs( cor )>cmax )cmax = abs( cor ) rscale( i ) = rscale( i ) + cor end do if( cmaxcmax )cmax = abs( cor ) lscale( i ) = lscale( i ) + cor cor = alpha*work( i ) if( abs( cor )>cmax )cmax = abs( cor ) rscale( i ) = rscale( i ) + cor end do if( cmaxcmax )cmax = abs( cor ) lscale( i ) = lscale( i ) + cor cor = alpha*work( i ) if( abs( cor )>cmax )cmax = abs( cor ) rscale( i ) = rscale( i ) + cor end do if( cmaxn .or. ihin .or. ihin .or. ihin .or. ihin .or. ihin .or. ihin .or. ihi1_${ik}$ )call stdlib${ii}$_slaset( 'LOWER', n-1, n-1, zero, zero, b(2_${ik}$, 1_${ik}$), ldb ) ! quick return if possible nh = ihi - ilo + 1_${ik}$ if( nh<=1_${ik}$ ) then work( 1_${ik}$ ) = one return end if ! determine the blocksize. nbmin = stdlib${ii}$_ilaenv( 2_${ik}$, 'SGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) if( nb>1_${ik}$ .and. nb=6_${ik}$*n*nbmin ) then nb = lwork / ( 6_${ik}$*n ) else nb = 1_${ik}$ end if end if end if end if if( nb=nh ) then ! use unblocked code below jcol = ilo else ! use blocked code kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'SGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) blk22 = kacc22==2_${ik}$ do jcol = ilo, ihi-2, nb nnb = min( nb, ihi-jcol-1 ) ! initialize small orthogonal factors that will hold the ! accumulated givens rotations in workspace. ! n2nb denotes the number of 2*nnb-by-2*nnb factors ! nblst denotes the (possibly smaller) order of the last ! factor. n2nb = ( ihi-jcol-1 ) / nnb - 1_${ik}$ nblst = ihi - jcol - n2nb*nnb call stdlib${ii}$_slaset( 'ALL', nblst, nblst, zero, one, work, nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_slaset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, zero, one,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! reduce columns jcol:jcol+nnb-1 of a to hessenberg form. do j = jcol, jcol+nnb-1 ! reduce jth column of a. store cosines and sines in jth ! column of a and b, respectively. do i = ihi, j+2, -1 temp = a( i-1, j ) call stdlib${ii}$_slartg( temp, a( i, j ), c, s, a( i-1, j ) ) a( i, j ) = c b( i, j ) = s end do ! accumulate givens rotations into workspace array. ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 c = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 c = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! top denotes the number of top rows in a and b that will ! not be updated during the next steps. if( jcol<=2_${ik}$ ) then top = 0_${ik}$ else top = jcol end if ! propagate transformations through b and replace stored ! left sines/cosines by right sines/cosines. do jj = n, j+1, -1 ! update jjth column of b. do i = min( jj+1, ihi ), j+2, -1 c = a( i, j ) s = b( i, j ) temp = b( i, jj ) b( i, jj ) = c*temp - s*b( i-1, jj ) b( i-1, jj ) = s*temp + c*b( i-1, jj ) end do ! annihilate b( jj+1, jj ). if( jj0_${ik}$ ) then do i = jj, 1, -1 call stdlib${ii}$_srot( ihi-top, a( top+1, j+i+1 ), 1_${ik}$,a( top+1, j+i ), 1_${ik}$, a( & j+1+i, j ),-b( j+1+i, j ) ) end do end if ! update (j+1)th column of a by transformations from left. if ( j < jcol + nnb - 1_${ik}$ ) then len = 1_${ik}$ + j - jcol ! multiply with the trailing accumulated orthogonal ! matrix, which takes the form ! [ u11 u12 ] ! u = [ ], ! [ u21 u22 ] ! where u21 is a len-by-len matrix and u12 is lower ! triangular. jrow = ihi - nblst + 1_${ik}$ call stdlib${ii}$_sgemv( 'TRANSPOSE', nblst, len, one, work,nblst, a( jrow, j+1 )& , 1_${ik}$, zero,work( pw ), 1_${ik}$ ) ppw = pw + len do i = jrow, jrow+nblst-len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_strmv( 'LOWER', 'TRANSPOSE', 'NON-UNIT',nblst-len, work( & len*nblst + 1_${ik}$ ), nblst,work( pw+len ), 1_${ik}$ ) call stdlib${ii}$_sgemv( 'TRANSPOSE', len, nblst-len, one,work( (len+1)*nblst - & len + 1_${ik}$ ), nblst,a( jrow+nblst-len, j+1 ), 1_${ik}$, one,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+nblst-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ! multiply with the other accumulated orthogonal ! matrices, which take the form ! [ u11 u12 0 ] ! [ ] ! u = [ u21 u22 0 ], ! [ ] ! [ 0 0 i ] ! where i denotes the (nnb-len)-by-(nnb-len) identity ! matrix, u21 is a len-by-len upper triangular matrix ! and u12 is an nnb-by-nnb lower triangular matrix. ppwo = 1_${ik}$ + nblst*nblst j0 = jrow - nnb do jrow = j0, jcol+1, -nnb ppw = pw + len do i = jrow, jrow+nnb-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do ppw = pw do i = jrow+nnb, jrow+nnb+len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_strmv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', len,work( ppwo + & nnb ), 2_${ik}$*nnb, work( pw ),1_${ik}$ ) call stdlib${ii}$_strmv( 'LOWER', 'TRANSPOSE', 'NON-UNIT', nnb,work( ppwo + & 2_${ik}$*len*nnb ),2_${ik}$*nnb, work( pw + len ), 1_${ik}$ ) call stdlib${ii}$_sgemv( 'TRANSPOSE', nnb, len, one,work( ppwo ), 2_${ik}$*nnb, a( & jrow, j+1 ), 1_${ik}$,one, work( pw ), 1_${ik}$ ) call stdlib${ii}$_sgemv( 'TRANSPOSE', len, nnb, one,work( ppwo + 2_${ik}$*len*nnb + & nnb ), 2_${ik}$*nnb,a( jrow+nnb, j+1 ), 1_${ik}$, one,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+len+nnb-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do ! apply accumulated orthogonal matrices to a. cola = n - jcol - nnb + 1_${ik}$ j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_sgemm( 'TRANSPOSE', 'NO TRANSPOSE', nblst,cola, nblst, one, work, & nblst,a( j, jcol+nnb ), lda, zero, work( pw ),nblst ) call stdlib${ii}$_slacpy( 'ALL', nblst, cola, work( pw ), nblst,a( j, jcol+nnb ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of ! [ u11 u12 ] ! u = [ ] ! [ u21 u22 ], ! where all blocks are nnb-by-nnb, u21 is upper ! triangular and u12 is lower triangular. call stdlib${ii}$_sorm22( 'LEFT', 'TRANSPOSE', 2_${ik}$*nnb, cola, nnb,nnb, work( ppwo )& , 2_${ik}$*nnb,a( j, jcol+nnb ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_sgemm( 'TRANSPOSE', 'NO TRANSPOSE', 2_${ik}$*nnb,cola, 2_${ik}$*nnb, one, & work( ppwo ), 2_${ik}$*nnb,a( j, jcol+nnb ), lda, zero, work( pw ),2_${ik}$*nnb ) call stdlib${ii}$_slacpy( 'ALL', 2_${ik}$*nnb, cola, work( pw ), 2_${ik}$*nnb,a( j, jcol+nnb ),& lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! apply accumulated orthogonal matrices to q. if( wantq ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, one, q( & topq, j ), ldq,work, nblst, zero, work( pw ), nh ) call stdlib${ii}$_slacpy( 'ALL', nh, nblst, work( pw ), nh,q( topq, j ), ldq ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_sorm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,q( topq, j ), ldq, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, one,& q( topq, j ), ldq,work( ppwo ), 2_${ik}$*nnb, zero, work( pw ),nh ) call stdlib${ii}$_slacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,q( topq, j ), ldq ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! accumulate right givens rotations if required. if ( wantz .or. top>0_${ik}$ ) then ! initialize small orthogonal factors that will hold the ! accumulated givens rotations in workspace. call stdlib${ii}$_slaset( 'ALL', nblst, nblst, zero, one, work,nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_slaset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, zero, one,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! accumulate givens rotations into workspace array. do j = jcol, jcol+nnb-1 ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 c = a( i, j ) a( i, j ) = zero s = b( i, j ) b( i, j ) = zero do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 c = a( i, j ) a( i, j ) = zero s = b( i, j ) b( i, j ) = zero do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end do else call stdlib${ii}$_slaset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, zero, zero,a( jcol + 2_${ik}$, & jcol ), lda ) call stdlib${ii}$_slaset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, zero, zero,b( jcol + 2_${ik}$, & jcol ), ldb ) end if ! apply accumulated orthogonal matrices to a and b. if ( top>0_${ik}$ ) then j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, one, a( & 1_${ik}$, j ), lda,work, nblst, zero, work( pw ), top ) call stdlib${ii}$_slacpy( 'ALL', top, nblst, work( pw ), top,a( 1_${ik}$, j ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_sorm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,a( 1_${ik}$, j ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & one, a( 1_${ik}$, j ), lda,work( ppwo ), 2_${ik}$*nnb, zero,work( pw ), top ) call stdlib${ii}$_slacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,a( 1_${ik}$, j ), lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, one, b( & 1_${ik}$, j ), ldb,work, nblst, zero, work( pw ), top ) call stdlib${ii}$_slacpy( 'ALL', top, nblst, work( pw ), top,b( 1_${ik}$, j ), ldb ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_sorm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,b( 1_${ik}$, j ), ldb, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & one, b( 1_${ik}$, j ), ldb,work( ppwo ), 2_${ik}$*nnb, zero,work( pw ), top ) call stdlib${ii}$_slacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,b( 1_${ik}$, j ), ldb ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! apply accumulated orthogonal matrices to z. if( wantz ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, one, z( & topq, j ), ldz,work, nblst, zero, work( pw ), nh ) call stdlib${ii}$_slacpy( 'ALL', nh, nblst, work( pw ), nh,z( topq, j ), ldz ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_sorm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,z( topq, j ), ldz, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, one,& z( topq, j ), ldz,work( ppwo ), 2_${ik}$*nnb, zero, work( pw ),nh ) call stdlib${ii}$_slacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,z( topq, j ), ldz ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do end if ! use unblocked code to reduce the rest of the matrix ! avoid re-initialization of modified q and z. compq2 = compq compz2 = compz if ( jcol/=ilo ) then if ( wantq )compq2 = 'V' if ( wantz )compz2 = 'V' end if if ( jcoln .or. ihi1_${ik}$ )call stdlib${ii}$_dlaset( 'LOWER', n-1, n-1, zero, zero, b(2_${ik}$, 1_${ik}$), ldb ) ! quick return if possible nh = ihi - ilo + 1_${ik}$ if( nh<=1_${ik}$ ) then work( 1_${ik}$ ) = one return end if ! determine the blocksize. nbmin = stdlib${ii}$_ilaenv( 2_${ik}$, 'DGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) if( nb>1_${ik}$ .and. nb=6_${ik}$*n*nbmin ) then nb = lwork / ( 6_${ik}$*n ) else nb = 1_${ik}$ end if end if end if end if if( nb=nh ) then ! use unblocked code below jcol = ilo else ! use blocked code kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'DGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) blk22 = kacc22==2_${ik}$ do jcol = ilo, ihi-2, nb nnb = min( nb, ihi-jcol-1 ) ! initialize small orthogonal factors that will hold the ! accumulated givens rotations in workspace. ! n2nb denotes the number of 2*nnb-by-2*nnb factors ! nblst denotes the (possibly smaller) order of the last ! factor. n2nb = ( ihi-jcol-1 ) / nnb - 1_${ik}$ nblst = ihi - jcol - n2nb*nnb call stdlib${ii}$_dlaset( 'ALL', nblst, nblst, zero, one, work, nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_dlaset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, zero, one,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! reduce columns jcol:jcol+nnb-1 of a to hessenberg form. do j = jcol, jcol+nnb-1 ! reduce jth column of a. store cosines and sines in jth ! column of a and b, respectively. do i = ihi, j+2, -1 temp = a( i-1, j ) call stdlib${ii}$_dlartg( temp, a( i, j ), c, s, a( i-1, j ) ) a( i, j ) = c b( i, j ) = s end do ! accumulate givens rotations into workspace array. ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 c = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 c = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! top denotes the number of top rows in a and b that will ! not be updated during the next steps. if( jcol<=2_${ik}$ ) then top = 0_${ik}$ else top = jcol end if ! propagate transformations through b and replace stored ! left sines/cosines by right sines/cosines. do jj = n, j+1, -1 ! update jjth column of b. do i = min( jj+1, ihi ), j+2, -1 c = a( i, j ) s = b( i, j ) temp = b( i, jj ) b( i, jj ) = c*temp - s*b( i-1, jj ) b( i-1, jj ) = s*temp + c*b( i-1, jj ) end do ! annihilate b( jj+1, jj ). if( jj0_${ik}$ ) then do i = jj, 1, -1 call stdlib${ii}$_drot( ihi-top, a( top+1, j+i+1 ), 1_${ik}$,a( top+1, j+i ), 1_${ik}$, a( & j+1+i, j ),-b( j+1+i, j ) ) end do end if ! update (j+1)th column of a by transformations from left. if ( j < jcol + nnb - 1_${ik}$ ) then len = 1_${ik}$ + j - jcol ! multiply with the trailing accumulated orthogonal ! matrix, which takes the form ! [ u11 u12 ] ! u = [ ], ! [ u21 u22 ] ! where u21 is a len-by-len matrix and u12 is lower ! triangular. jrow = ihi - nblst + 1_${ik}$ call stdlib${ii}$_dgemv( 'TRANSPOSE', nblst, len, one, work,nblst, a( jrow, j+1 )& , 1_${ik}$, zero,work( pw ), 1_${ik}$ ) ppw = pw + len do i = jrow, jrow+nblst-len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_dtrmv( 'LOWER', 'TRANSPOSE', 'NON-UNIT',nblst-len, work( & len*nblst + 1_${ik}$ ), nblst,work( pw+len ), 1_${ik}$ ) call stdlib${ii}$_dgemv( 'TRANSPOSE', len, nblst-len, one,work( (len+1)*nblst - & len + 1_${ik}$ ), nblst,a( jrow+nblst-len, j+1 ), 1_${ik}$, one,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+nblst-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ! multiply with the other accumulated orthogonal ! matrices, which take the form ! [ u11 u12 0 ] ! [ ] ! u = [ u21 u22 0 ], ! [ ] ! [ 0 0 i ] ! where i denotes the (nnb-len)-by-(nnb-len) identity ! matrix, u21 is a len-by-len upper triangular matrix ! and u12 is an nnb-by-nnb lower triangular matrix. ppwo = 1_${ik}$ + nblst*nblst j0 = jrow - nnb do jrow = j0, jcol+1, -nnb ppw = pw + len do i = jrow, jrow+nnb-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do ppw = pw do i = jrow+nnb, jrow+nnb+len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_dtrmv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', len,work( ppwo + & nnb ), 2_${ik}$*nnb, work( pw ),1_${ik}$ ) call stdlib${ii}$_dtrmv( 'LOWER', 'TRANSPOSE', 'NON-UNIT', nnb,work( ppwo + & 2_${ik}$*len*nnb ),2_${ik}$*nnb, work( pw + len ), 1_${ik}$ ) call stdlib${ii}$_dgemv( 'TRANSPOSE', nnb, len, one,work( ppwo ), 2_${ik}$*nnb, a( & jrow, j+1 ), 1_${ik}$,one, work( pw ), 1_${ik}$ ) call stdlib${ii}$_dgemv( 'TRANSPOSE', len, nnb, one,work( ppwo + 2_${ik}$*len*nnb + & nnb ), 2_${ik}$*nnb,a( jrow+nnb, j+1 ), 1_${ik}$, one,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+len+nnb-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do ! apply accumulated orthogonal matrices to a. cola = n - jcol - nnb + 1_${ik}$ j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_dgemm( 'TRANSPOSE', 'NO TRANSPOSE', nblst,cola, nblst, one, work, & nblst,a( j, jcol+nnb ), lda, zero, work( pw ),nblst ) call stdlib${ii}$_dlacpy( 'ALL', nblst, cola, work( pw ), nblst,a( j, jcol+nnb ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of ! [ u11 u12 ] ! u = [ ] ! [ u21 u22 ], ! where all blocks are nnb-by-nnb, u21 is upper ! triangular and u12 is lower triangular. call stdlib${ii}$_dorm22( 'LEFT', 'TRANSPOSE', 2_${ik}$*nnb, cola, nnb,nnb, work( ppwo )& , 2_${ik}$*nnb,a( j, jcol+nnb ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_dgemm( 'TRANSPOSE', 'NO TRANSPOSE', 2_${ik}$*nnb,cola, 2_${ik}$*nnb, one, & work( ppwo ), 2_${ik}$*nnb,a( j, jcol+nnb ), lda, zero, work( pw ),2_${ik}$*nnb ) call stdlib${ii}$_dlacpy( 'ALL', 2_${ik}$*nnb, cola, work( pw ), 2_${ik}$*nnb,a( j, jcol+nnb ),& lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! apply accumulated orthogonal matrices to q. if( wantq ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, one, q( & topq, j ), ldq,work, nblst, zero, work( pw ), nh ) call stdlib${ii}$_dlacpy( 'ALL', nh, nblst, work( pw ), nh,q( topq, j ), ldq ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_dorm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,q( topq, j ), ldq, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, one,& q( topq, j ), ldq,work( ppwo ), 2_${ik}$*nnb, zero, work( pw ),nh ) call stdlib${ii}$_dlacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,q( topq, j ), ldq ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! accumulate right givens rotations if required. if ( wantz .or. top>0_${ik}$ ) then ! initialize small orthogonal factors that will hold the ! accumulated givens rotations in workspace. call stdlib${ii}$_dlaset( 'ALL', nblst, nblst, zero, one, work,nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_dlaset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, zero, one,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! accumulate givens rotations into workspace array. do j = jcol, jcol+nnb-1 ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 c = a( i, j ) a( i, j ) = zero s = b( i, j ) b( i, j ) = zero do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 c = a( i, j ) a( i, j ) = zero s = b( i, j ) b( i, j ) = zero do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end do else call stdlib${ii}$_dlaset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, zero, zero,a( jcol + 2_${ik}$, & jcol ), lda ) call stdlib${ii}$_dlaset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, zero, zero,b( jcol + 2_${ik}$, & jcol ), ldb ) end if ! apply accumulated orthogonal matrices to a and b. if ( top>0_${ik}$ ) then j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, one, a( & 1_${ik}$, j ), lda,work, nblst, zero, work( pw ), top ) call stdlib${ii}$_dlacpy( 'ALL', top, nblst, work( pw ), top,a( 1_${ik}$, j ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_dorm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,a( 1_${ik}$, j ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & one, a( 1_${ik}$, j ), lda,work( ppwo ), 2_${ik}$*nnb, zero,work( pw ), top ) call stdlib${ii}$_dlacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,a( 1_${ik}$, j ), lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, one, b( & 1_${ik}$, j ), ldb,work, nblst, zero, work( pw ), top ) call stdlib${ii}$_dlacpy( 'ALL', top, nblst, work( pw ), top,b( 1_${ik}$, j ), ldb ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_dorm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,b( 1_${ik}$, j ), ldb, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & one, b( 1_${ik}$, j ), ldb,work( ppwo ), 2_${ik}$*nnb, zero,work( pw ), top ) call stdlib${ii}$_dlacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,b( 1_${ik}$, j ), ldb ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! apply accumulated orthogonal matrices to z. if( wantz ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, one, z( & topq, j ), ldz,work, nblst, zero, work( pw ), nh ) call stdlib${ii}$_dlacpy( 'ALL', nh, nblst, work( pw ), nh,z( topq, j ), ldz ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_dorm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,z( topq, j ), ldz, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, one,& z( topq, j ), ldz,work( ppwo ), 2_${ik}$*nnb, zero, work( pw ),nh ) call stdlib${ii}$_dlacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,z( topq, j ), ldz ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do end if ! use unblocked code to reduce the rest of the matrix ! avoid re-initialization of modified q and z. compq2 = compq compz2 = compz if ( jcol/=ilo ) then if ( wantq )compq2 = 'V' if ( wantz )compz2 = 'V' end if if ( jcoln .or. ihi1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'LOWER', n-1, n-1, zero, zero, b(2_${ik}$, 1_${ik}$), ldb ) ! quick return if possible nh = ihi - ilo + 1_${ik}$ if( nh<=1_${ik}$ ) then work( 1_${ik}$ ) = one return end if ! determine the blocksize. nbmin = stdlib${ii}$_ilaenv( 2_${ik}$, 'DGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) if( nb>1_${ik}$ .and. nb=6_${ik}$*n*nbmin ) then nb = lwork / ( 6_${ik}$*n ) else nb = 1_${ik}$ end if end if end if end if if( nb=nh ) then ! use unblocked code below jcol = ilo else ! use blocked code kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'DGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) blk22 = kacc22==2_${ik}$ do jcol = ilo, ihi-2, nb nnb = min( nb, ihi-jcol-1 ) ! initialize small orthogonal factors that will hold the ! accumulated givens rotations in workspace. ! n2nb denotes the number of 2*nnb-by-2*nnb factors ! nblst denotes the (possibly smaller) order of the last ! factor. n2nb = ( ihi-jcol-1 ) / nnb - 1_${ik}$ nblst = ihi - jcol - n2nb*nnb call stdlib${ii}$_${ri}$laset( 'ALL', nblst, nblst, zero, one, work, nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_${ri}$laset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, zero, one,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! reduce columns jcol:jcol+nnb-1 of a to hessenberg form. do j = jcol, jcol+nnb-1 ! reduce jth column of a. store cosines and sines in jth ! column of a and b, respectively. do i = ihi, j+2, -1 temp = a( i-1, j ) call stdlib${ii}$_${ri}$lartg( temp, a( i, j ), c, s, a( i-1, j ) ) a( i, j ) = c b( i, j ) = s end do ! accumulate givens rotations into workspace array. ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 c = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 c = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! top denotes the number of top rows in a and b that will ! not be updated during the next steps. if( jcol<=2_${ik}$ ) then top = 0_${ik}$ else top = jcol end if ! propagate transformations through b and replace stored ! left sines/cosines by right sines/cosines. do jj = n, j+1, -1 ! update jjth column of b. do i = min( jj+1, ihi ), j+2, -1 c = a( i, j ) s = b( i, j ) temp = b( i, jj ) b( i, jj ) = c*temp - s*b( i-1, jj ) b( i-1, jj ) = s*temp + c*b( i-1, jj ) end do ! annihilate b( jj+1, jj ). if( jj0_${ik}$ ) then do i = jj, 1, -1 call stdlib${ii}$_${ri}$rot( ihi-top, a( top+1, j+i+1 ), 1_${ik}$,a( top+1, j+i ), 1_${ik}$, a( & j+1+i, j ),-b( j+1+i, j ) ) end do end if ! update (j+1)th column of a by transformations from left. if ( j < jcol + nnb - 1_${ik}$ ) then len = 1_${ik}$ + j - jcol ! multiply with the trailing accumulated orthogonal ! matrix, which takes the form ! [ u11 u12 ] ! u = [ ], ! [ u21 u22 ] ! where u21 is a len-by-len matrix and u12 is lower ! triangular. jrow = ihi - nblst + 1_${ik}$ call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', nblst, len, one, work,nblst, a( jrow, j+1 )& , 1_${ik}$, zero,work( pw ), 1_${ik}$ ) ppw = pw + len do i = jrow, jrow+nblst-len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_${ri}$trmv( 'LOWER', 'TRANSPOSE', 'NON-UNIT',nblst-len, work( & len*nblst + 1_${ik}$ ), nblst,work( pw+len ), 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', len, nblst-len, one,work( (len+1)*nblst - & len + 1_${ik}$ ), nblst,a( jrow+nblst-len, j+1 ), 1_${ik}$, one,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+nblst-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ! multiply with the other accumulated orthogonal ! matrices, which take the form ! [ u11 u12 0 ] ! [ ] ! u = [ u21 u22 0 ], ! [ ] ! [ 0 0 i ] ! where i denotes the (nnb-len)-by-(nnb-len) identity ! matrix, u21 is a len-by-len upper triangular matrix ! and u12 is an nnb-by-nnb lower triangular matrix. ppwo = 1_${ik}$ + nblst*nblst j0 = jrow - nnb do jrow = j0, jcol+1, -nnb ppw = pw + len do i = jrow, jrow+nnb-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do ppw = pw do i = jrow+nnb, jrow+nnb+len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_${ri}$trmv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', len,work( ppwo + & nnb ), 2_${ik}$*nnb, work( pw ),1_${ik}$ ) call stdlib${ii}$_${ri}$trmv( 'LOWER', 'TRANSPOSE', 'NON-UNIT', nnb,work( ppwo + & 2_${ik}$*len*nnb ),2_${ik}$*nnb, work( pw + len ), 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', nnb, len, one,work( ppwo ), 2_${ik}$*nnb, a( & jrow, j+1 ), 1_${ik}$,one, work( pw ), 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', len, nnb, one,work( ppwo + 2_${ik}$*len*nnb + & nnb ), 2_${ik}$*nnb,a( jrow+nnb, j+1 ), 1_${ik}$, one,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+len+nnb-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do ! apply accumulated orthogonal matrices to a. cola = n - jcol - nnb + 1_${ik}$ j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'NO TRANSPOSE', nblst,cola, nblst, one, work, & nblst,a( j, jcol+nnb ), lda, zero, work( pw ),nblst ) call stdlib${ii}$_${ri}$lacpy( 'ALL', nblst, cola, work( pw ), nblst,a( j, jcol+nnb ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of ! [ u11 u12 ] ! u = [ ] ! [ u21 u22 ], ! where all blocks are nnb-by-nnb, u21 is upper ! triangular and u12 is lower triangular. call stdlib${ii}$_${ri}$orm22( 'LEFT', 'TRANSPOSE', 2_${ik}$*nnb, cola, nnb,nnb, work( ppwo )& , 2_${ik}$*nnb,a( j, jcol+nnb ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'NO TRANSPOSE', 2_${ik}$*nnb,cola, 2_${ik}$*nnb, one, & work( ppwo ), 2_${ik}$*nnb,a( j, jcol+nnb ), lda, zero, work( pw ),2_${ik}$*nnb ) call stdlib${ii}$_${ri}$lacpy( 'ALL', 2_${ik}$*nnb, cola, work( pw ), 2_${ik}$*nnb,a( j, jcol+nnb ),& lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! apply accumulated orthogonal matrices to q. if( wantq ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, one, q( & topq, j ), ldq,work, nblst, zero, work( pw ), nh ) call stdlib${ii}$_${ri}$lacpy( 'ALL', nh, nblst, work( pw ), nh,q( topq, j ), ldq ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_${ri}$orm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,q( topq, j ), ldq, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, one,& q( topq, j ), ldq,work( ppwo ), 2_${ik}$*nnb, zero, work( pw ),nh ) call stdlib${ii}$_${ri}$lacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,q( topq, j ), ldq ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! accumulate right givens rotations if required. if ( wantz .or. top>0_${ik}$ ) then ! initialize small orthogonal factors that will hold the ! accumulated givens rotations in workspace. call stdlib${ii}$_${ri}$laset( 'ALL', nblst, nblst, zero, one, work,nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_${ri}$laset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, zero, one,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! accumulate givens rotations into workspace array. do j = jcol, jcol+nnb-1 ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 c = a( i, j ) a( i, j ) = zero s = b( i, j ) b( i, j ) = zero do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 c = a( i, j ) a( i, j ) = zero s = b( i, j ) b( i, j ) = zero do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = c*temp - s*work( jj ) work( jj ) = s*temp + c*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end do else call stdlib${ii}$_${ri}$laset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, zero, zero,a( jcol + 2_${ik}$, & jcol ), lda ) call stdlib${ii}$_${ri}$laset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, zero, zero,b( jcol + 2_${ik}$, & jcol ), ldb ) end if ! apply accumulated orthogonal matrices to a and b. if ( top>0_${ik}$ ) then j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, one, a( & 1_${ik}$, j ), lda,work, nblst, zero, work( pw ), top ) call stdlib${ii}$_${ri}$lacpy( 'ALL', top, nblst, work( pw ), top,a( 1_${ik}$, j ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_${ri}$orm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,a( 1_${ik}$, j ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & one, a( 1_${ik}$, j ), lda,work( ppwo ), 2_${ik}$*nnb, zero,work( pw ), top ) call stdlib${ii}$_${ri}$lacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,a( 1_${ik}$, j ), lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, one, b( & 1_${ik}$, j ), ldb,work, nblst, zero, work( pw ), top ) call stdlib${ii}$_${ri}$lacpy( 'ALL', top, nblst, work( pw ), top,b( 1_${ik}$, j ), ldb ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_${ri}$orm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,b( 1_${ik}$, j ), ldb, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & one, b( 1_${ik}$, j ), ldb,work( ppwo ), 2_${ik}$*nnb, zero,work( pw ), top ) call stdlib${ii}$_${ri}$lacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,b( 1_${ik}$, j ), ldb ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! apply accumulated orthogonal matrices to z. if( wantz ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, one, z( & topq, j ), ldz,work, nblst, zero, work( pw ), nh ) call stdlib${ii}$_${ri}$lacpy( 'ALL', nh, nblst, work( pw ), nh,z( topq, j ), ldz ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_${ri}$orm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,z( topq, j ), ldz, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, one,& z( topq, j ), ldz,work( ppwo ), 2_${ik}$*nnb, zero, work( pw ),nh ) call stdlib${ii}$_${ri}$lacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,z( topq, j ), ldz ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do end if ! use unblocked code to reduce the rest of the matrix ! avoid re-initialization of modified q and z. compq2 = compq compz2 = compz if ( jcol/=ilo ) then if ( wantq )compq2 = 'V' if ( wantz )compz2 = 'V' end if if ( jcoln .or. ihi1_${ik}$ )call stdlib${ii}$_claset( 'LOWER', n-1, n-1, czero, czero, b(2_${ik}$, 1_${ik}$), ldb ) ! quick return if possible nh = ihi - ilo + 1_${ik}$ if( nh<=1_${ik}$ ) then work( 1_${ik}$ ) = cone return end if ! determine the blocksize. nbmin = stdlib${ii}$_ilaenv( 2_${ik}$, 'CGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) if( nb>1_${ik}$ .and. nb=6_${ik}$*n*nbmin ) then nb = lwork / ( 6_${ik}$*n ) else nb = 1_${ik}$ end if end if end if end if if( nb=nh ) then ! use unblocked code below jcol = ilo else ! use blocked code kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'CGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) blk22 = kacc22==2_${ik}$ do jcol = ilo, ihi-2, nb nnb = min( nb, ihi-jcol-1 ) ! initialize small unitary factors that will hold the ! accumulated givens rotations in workspace. ! n2nb denotes the number of 2*nnb-by-2*nnb factors ! nblst denotes the (possibly smaller) order of the last ! factor. n2nb = ( ihi-jcol-1 ) / nnb - 1_${ik}$ nblst = ihi - jcol - n2nb*nnb call stdlib${ii}$_claset( 'ALL', nblst, nblst, czero, cone, work, nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_claset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, czero, cone,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! reduce columns jcol:jcol+nnb-1 of a to hessenberg form. do j = jcol, jcol+nnb-1 ! reduce jth column of a. store cosines and sines in jth ! column of a and b, respectively. do i = ihi, j+2, -1 temp = a( i-1, j ) call stdlib${ii}$_clartg( temp, a( i, j ), c, s, a( i-1, j ) ) a( i, j ) = cmplx( c,KIND=sp) b( i, j ) = s end do ! accumulate givens rotations into workspace array. ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 ctemp = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = ctemp*temp - s*work( jj ) work( jj ) = conjg( s )*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 ctemp = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = ctemp*temp - s*work( jj ) work( jj ) = conjg( s )*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! top denotes the number of top rows in a and b that will ! not be updated during the next steps. if( jcol<=2_${ik}$ ) then top = 0_${ik}$ else top = jcol end if ! propagate transformations through b and replace stored ! left sines/cosines by right sines/cosines. do jj = n, j+1, -1 ! update jjth column of b. do i = min( jj+1, ihi ), j+2, -1 ctemp = a( i, j ) s = b( i, j ) temp = b( i, jj ) b( i, jj ) = ctemp*temp - conjg( s )*b( i-1, jj ) b( i-1, jj ) = s*temp + ctemp*b( i-1, jj ) end do ! annihilate b( jj+1, jj ). if( jj0_${ik}$ ) then do i = jj, 1, -1 c = real( a( j+1+i, j ),KIND=sp) call stdlib${ii}$_crot( ihi-top, a( top+1, j+i+1 ), 1_${ik}$,a( top+1, j+i ), 1_${ik}$, c,-& conjg( b( j+1+i, j ) ) ) end do end if ! update (j+1)th column of a by transformations from left. if ( j < jcol + nnb - 1_${ik}$ ) then len = 1_${ik}$ + j - jcol ! multiply with the trailing accumulated unitary ! matrix, which takes the form ! [ u11 u12 ] ! u = [ ], ! [ u21 u22 ] ! where u21 is a len-by-len matrix and u12 is lower ! triangular. jrow = ihi - nblst + 1_${ik}$ call stdlib${ii}$_cgemv( 'CONJUGATE', nblst, len, cone, work,nblst, a( jrow, j+1 & ), 1_${ik}$, czero,work( pw ), 1_${ik}$ ) ppw = pw + len do i = jrow, jrow+nblst-len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_ctrmv( 'LOWER', 'CONJUGATE', 'NON-UNIT',nblst-len, work( & len*nblst + 1_${ik}$ ), nblst,work( pw+len ), 1_${ik}$ ) call stdlib${ii}$_cgemv( 'CONJUGATE', len, nblst-len, cone,work( (len+1)*nblst - & len + 1_${ik}$ ), nblst,a( jrow+nblst-len, j+1 ), 1_${ik}$, cone,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+nblst-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ! multiply with the other accumulated unitary ! matrices, which take the form ! [ u11 u12 0 ] ! [ ] ! u = [ u21 u22 0 ], ! [ ] ! [ 0 0 i ] ! where i denotes the (nnb-len)-by-(nnb-len) identity ! matrix, u21 is a len-by-len upper triangular matrix ! and u12 is an nnb-by-nnb lower triangular matrix. ppwo = 1_${ik}$ + nblst*nblst j0 = jrow - nnb do jrow = j0, jcol+1, -nnb ppw = pw + len do i = jrow, jrow+nnb-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do ppw = pw do i = jrow+nnb, jrow+nnb+len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_ctrmv( 'UPPER', 'CONJUGATE', 'NON-UNIT', len,work( ppwo + & nnb ), 2_${ik}$*nnb, work( pw ),1_${ik}$ ) call stdlib${ii}$_ctrmv( 'LOWER', 'CONJUGATE', 'NON-UNIT', nnb,work( ppwo + & 2_${ik}$*len*nnb ),2_${ik}$*nnb, work( pw + len ), 1_${ik}$ ) call stdlib${ii}$_cgemv( 'CONJUGATE', nnb, len, cone,work( ppwo ), 2_${ik}$*nnb, a( & jrow, j+1 ), 1_${ik}$,cone, work( pw ), 1_${ik}$ ) call stdlib${ii}$_cgemv( 'CONJUGATE', len, nnb, cone,work( ppwo + 2_${ik}$*len*nnb + & nnb ), 2_${ik}$*nnb,a( jrow+nnb, j+1 ), 1_${ik}$, cone,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+len+nnb-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do ! apply accumulated unitary matrices to a. cola = n - jcol - nnb + 1_${ik}$ j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_cgemm( 'CONJUGATE', 'NO TRANSPOSE', nblst,cola, nblst, cone, work, & nblst,a( j, jcol+nnb ), lda, czero, work( pw ),nblst ) call stdlib${ii}$_clacpy( 'ALL', nblst, cola, work( pw ), nblst,a( j, jcol+nnb ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of ! [ u11 u12 ] ! u = [ ] ! [ u21 u22 ], ! where all blocks are nnb-by-nnb, u21 is upper ! triangular and u12 is lower triangular. call stdlib${ii}$_cunm22( 'LEFT', 'CONJUGATE', 2_${ik}$*nnb, cola, nnb,nnb, work( ppwo )& , 2_${ik}$*nnb,a( j, jcol+nnb ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_cgemm( 'CONJUGATE', 'NO TRANSPOSE', 2_${ik}$*nnb,cola, 2_${ik}$*nnb, cone, & work( ppwo ), 2_${ik}$*nnb,a( j, jcol+nnb ), lda, czero, work( pw ),2_${ik}$*nnb ) call stdlib${ii}$_clacpy( 'ALL', 2_${ik}$*nnb, cola, work( pw ), 2_${ik}$*nnb,a( j, jcol+nnb ),& lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! apply accumulated unitary matrices to q. if( wantq ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, cone, q( & topq, j ), ldq,work, nblst, czero, work( pw ), nh ) call stdlib${ii}$_clacpy( 'ALL', nh, nblst, work( pw ), nh,q( topq, j ), ldq ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_cunm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,q( topq, j ), ldq, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, q( topq, j ), ldq,work( ppwo ), 2_${ik}$*nnb, czero, work( pw ),nh ) call stdlib${ii}$_clacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,q( topq, j ), ldq ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! accumulate right givens rotations if required. if ( wantz .or. top>0_${ik}$ ) then ! initialize small unitary factors that will hold the ! accumulated givens rotations in workspace. call stdlib${ii}$_claset( 'ALL', nblst, nblst, czero, cone, work,nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_claset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, czero, cone,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! accumulate givens rotations into workspace array. do j = jcol, jcol+nnb-1 ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 ctemp = a( i, j ) a( i, j ) = czero s = b( i, j ) b( i, j ) = czero do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = ctemp*temp -conjg( s )*work( jj ) work( jj ) = s*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 ctemp = a( i, j ) a( i, j ) = czero s = b( i, j ) b( i, j ) = czero do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = ctemp*temp -conjg( s )*work( jj ) work( jj ) = s*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end do else call stdlib${ii}$_claset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, czero, czero,a( jcol + 2_${ik}$, & jcol ), lda ) call stdlib${ii}$_claset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, czero, czero,b( jcol + 2_${ik}$, & jcol ), ldb ) end if ! apply accumulated unitary matrices to a and b. if ( top>0_${ik}$ ) then j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, cone, a( & 1_${ik}$, j ), lda,work, nblst, czero, work( pw ), top ) call stdlib${ii}$_clacpy( 'ALL', top, nblst, work( pw ), top,a( 1_${ik}$, j ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_cunm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,a( 1_${ik}$, j ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, a( 1_${ik}$, j ), lda,work( ppwo ), 2_${ik}$*nnb, czero,work( pw ), top ) call stdlib${ii}$_clacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,a( 1_${ik}$, j ), lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, cone, b( & 1_${ik}$, j ), ldb,work, nblst, czero, work( pw ), top ) call stdlib${ii}$_clacpy( 'ALL', top, nblst, work( pw ), top,b( 1_${ik}$, j ), ldb ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_cunm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,b( 1_${ik}$, j ), ldb, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, b( 1_${ik}$, j ), ldb,work( ppwo ), 2_${ik}$*nnb, czero,work( pw ), top ) call stdlib${ii}$_clacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,b( 1_${ik}$, j ), ldb ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! apply accumulated unitary matrices to z. if( wantz ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, cone, z( & topq, j ), ldz,work, nblst, czero, work( pw ), nh ) call stdlib${ii}$_clacpy( 'ALL', nh, nblst, work( pw ), nh,z( topq, j ), ldz ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_cunm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,z( topq, j ), ldz, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, z( topq, j ), ldz,work( ppwo ), 2_${ik}$*nnb, czero, work( pw ),nh ) call stdlib${ii}$_clacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,z( topq, j ), ldz ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do end if ! use unblocked code to reduce the rest of the matrix ! avoid re-initialization of modified q and z. compq2 = compq compz2 = compz if ( jcol/=ilo ) then if ( wantq )compq2 = 'V' if ( wantz )compz2 = 'V' end if if ( jcoln .or. ihi1_${ik}$ )call stdlib${ii}$_zlaset( 'LOWER', n-1, n-1, czero, czero, b(2_${ik}$, 1_${ik}$), ldb ) ! quick return if possible nh = ihi - ilo + 1_${ik}$ if( nh<=1_${ik}$ ) then work( 1_${ik}$ ) = cone return end if ! determine the blocksize. nbmin = stdlib${ii}$_ilaenv( 2_${ik}$, 'ZGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) if( nb>1_${ik}$ .and. nb=6_${ik}$*n*nbmin ) then nb = lwork / ( 6_${ik}$*n ) else nb = 1_${ik}$ end if end if end if end if if( nb=nh ) then ! use unblocked code below jcol = ilo else ! use blocked code kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'ZGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) blk22 = kacc22==2_${ik}$ do jcol = ilo, ihi-2, nb nnb = min( nb, ihi-jcol-1 ) ! initialize small unitary factors that will hold the ! accumulated givens rotations in workspace. ! n2nb denotes the number of 2*nnb-by-2*nnb factors ! nblst denotes the (possibly smaller) order of the last ! factor. n2nb = ( ihi-jcol-1 ) / nnb - 1_${ik}$ nblst = ihi - jcol - n2nb*nnb call stdlib${ii}$_zlaset( 'ALL', nblst, nblst, czero, cone, work, nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_zlaset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, czero, cone,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! reduce columns jcol:jcol+nnb-1 of a to hessenberg form. do j = jcol, jcol+nnb-1 ! reduce jth column of a. store cosines and sines in jth ! column of a and b, respectively. do i = ihi, j+2, -1 temp = a( i-1, j ) call stdlib${ii}$_zlartg( temp, a( i, j ), c, s, a( i-1, j ) ) a( i, j ) = cmplx( c,KIND=dp) b( i, j ) = s end do ! accumulate givens rotations into workspace array. ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 ctemp = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = ctemp*temp - s*work( jj ) work( jj ) = conjg( s )*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 ctemp = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = ctemp*temp - s*work( jj ) work( jj ) = conjg( s )*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! top denotes the number of top rows in a and b that will ! not be updated during the next steps. if( jcol<=2_${ik}$ ) then top = 0_${ik}$ else top = jcol end if ! propagate transformations through b and replace stored ! left sines/cosines by right sines/cosines. do jj = n, j+1, -1 ! update jjth column of b. do i = min( jj+1, ihi ), j+2, -1 ctemp = a( i, j ) s = b( i, j ) temp = b( i, jj ) b( i, jj ) = ctemp*temp - conjg( s )*b( i-1, jj ) b( i-1, jj ) = s*temp + ctemp*b( i-1, jj ) end do ! annihilate b( jj+1, jj ). if( jj0_${ik}$ ) then do i = jj, 1, -1 c = real( a( j+1+i, j ),KIND=dp) call stdlib${ii}$_zrot( ihi-top, a( top+1, j+i+1 ), 1_${ik}$,a( top+1, j+i ), 1_${ik}$, c,-& conjg( b( j+1+i, j ) ) ) end do end if ! update (j+1)th column of a by transformations from left. if ( j < jcol + nnb - 1_${ik}$ ) then len = 1_${ik}$ + j - jcol ! multiply with the trailing accumulated unitary ! matrix, which takes the form ! [ u11 u12 ] ! u = [ ], ! [ u21 u22 ] ! where u21 is a len-by-len matrix and u12 is lower ! triangular. jrow = ihi - nblst + 1_${ik}$ call stdlib${ii}$_zgemv( 'CONJUGATE', nblst, len, cone, work,nblst, a( jrow, j+1 & ), 1_${ik}$, czero,work( pw ), 1_${ik}$ ) ppw = pw + len do i = jrow, jrow+nblst-len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_ztrmv( 'LOWER', 'CONJUGATE', 'NON-UNIT',nblst-len, work( & len*nblst + 1_${ik}$ ), nblst,work( pw+len ), 1_${ik}$ ) call stdlib${ii}$_zgemv( 'CONJUGATE', len, nblst-len, cone,work( (len+1)*nblst - & len + 1_${ik}$ ), nblst,a( jrow+nblst-len, j+1 ), 1_${ik}$, cone,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+nblst-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ! multiply with the other accumulated unitary ! matrices, which take the form ! [ u11 u12 0 ] ! [ ] ! u = [ u21 u22 0 ], ! [ ] ! [ 0 0 i ] ! where i denotes the (nnb-len)-by-(nnb-len) identity ! matrix, u21 is a len-by-len upper triangular matrix ! and u12 is an nnb-by-nnb lower triangular matrix. ppwo = 1_${ik}$ + nblst*nblst j0 = jrow - nnb do jrow = j0, jcol+1, -nnb ppw = pw + len do i = jrow, jrow+nnb-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do ppw = pw do i = jrow+nnb, jrow+nnb+len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_ztrmv( 'UPPER', 'CONJUGATE', 'NON-UNIT', len,work( ppwo + & nnb ), 2_${ik}$*nnb, work( pw ),1_${ik}$ ) call stdlib${ii}$_ztrmv( 'LOWER', 'CONJUGATE', 'NON-UNIT', nnb,work( ppwo + & 2_${ik}$*len*nnb ),2_${ik}$*nnb, work( pw + len ), 1_${ik}$ ) call stdlib${ii}$_zgemv( 'CONJUGATE', nnb, len, cone,work( ppwo ), 2_${ik}$*nnb, a( & jrow, j+1 ), 1_${ik}$,cone, work( pw ), 1_${ik}$ ) call stdlib${ii}$_zgemv( 'CONJUGATE', len, nnb, cone,work( ppwo + 2_${ik}$*len*nnb + & nnb ), 2_${ik}$*nnb,a( jrow+nnb, j+1 ), 1_${ik}$, cone,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+len+nnb-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do ! apply accumulated unitary matrices to a. cola = n - jcol - nnb + 1_${ik}$ j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_zgemm( 'CONJUGATE', 'NO TRANSPOSE', nblst,cola, nblst, cone, work, & nblst,a( j, jcol+nnb ), lda, czero, work( pw ),nblst ) call stdlib${ii}$_zlacpy( 'ALL', nblst, cola, work( pw ), nblst,a( j, jcol+nnb ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of ! [ u11 u12 ] ! u = [ ] ! [ u21 u22 ], ! where all blocks are nnb-by-nnb, u21 is upper ! triangular and u12 is lower triangular. call stdlib${ii}$_zunm22( 'LEFT', 'CONJUGATE', 2_${ik}$*nnb, cola, nnb,nnb, work( ppwo )& , 2_${ik}$*nnb,a( j, jcol+nnb ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_zgemm( 'CONJUGATE', 'NO TRANSPOSE', 2_${ik}$*nnb,cola, 2_${ik}$*nnb, cone, & work( ppwo ), 2_${ik}$*nnb,a( j, jcol+nnb ), lda, czero, work( pw ),2_${ik}$*nnb ) call stdlib${ii}$_zlacpy( 'ALL', 2_${ik}$*nnb, cola, work( pw ), 2_${ik}$*nnb,a( j, jcol+nnb ),& lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! apply accumulated unitary matrices to q. if( wantq ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, cone, q( & topq, j ), ldq,work, nblst, czero, work( pw ), nh ) call stdlib${ii}$_zlacpy( 'ALL', nh, nblst, work( pw ), nh,q( topq, j ), ldq ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_zunm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,q( topq, j ), ldq, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, q( topq, j ), ldq,work( ppwo ), 2_${ik}$*nnb, czero, work( pw ),nh ) call stdlib${ii}$_zlacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,q( topq, j ), ldq ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! accumulate right givens rotations if required. if ( wantz .or. top>0_${ik}$ ) then ! initialize small unitary factors that will hold the ! accumulated givens rotations in workspace. call stdlib${ii}$_zlaset( 'ALL', nblst, nblst, czero, cone, work,nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_zlaset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, czero, cone,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! accumulate givens rotations into workspace array. do j = jcol, jcol+nnb-1 ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 ctemp = a( i, j ) a( i, j ) = czero s = b( i, j ) b( i, j ) = czero do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = ctemp*temp -conjg( s )*work( jj ) work( jj ) = s*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 ctemp = a( i, j ) a( i, j ) = czero s = b( i, j ) b( i, j ) = czero do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = ctemp*temp -conjg( s )*work( jj ) work( jj ) = s*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end do else call stdlib${ii}$_zlaset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, czero, czero,a( jcol + 2_${ik}$, & jcol ), lda ) call stdlib${ii}$_zlaset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, czero, czero,b( jcol + 2_${ik}$, & jcol ), ldb ) end if ! apply accumulated unitary matrices to a and b. if ( top>0_${ik}$ ) then j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, cone, a( & 1_${ik}$, j ), lda,work, nblst, czero, work( pw ), top ) call stdlib${ii}$_zlacpy( 'ALL', top, nblst, work( pw ), top,a( 1_${ik}$, j ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_zunm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,a( 1_${ik}$, j ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, a( 1_${ik}$, j ), lda,work( ppwo ), 2_${ik}$*nnb, czero,work( pw ), top ) call stdlib${ii}$_zlacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,a( 1_${ik}$, j ), lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, cone, b( & 1_${ik}$, j ), ldb,work, nblst, czero, work( pw ), top ) call stdlib${ii}$_zlacpy( 'ALL', top, nblst, work( pw ), top,b( 1_${ik}$, j ), ldb ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_zunm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,b( 1_${ik}$, j ), ldb, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, b( 1_${ik}$, j ), ldb,work( ppwo ), 2_${ik}$*nnb, czero,work( pw ), top ) call stdlib${ii}$_zlacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,b( 1_${ik}$, j ), ldb ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! apply accumulated unitary matrices to z. if( wantz ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, cone, z( & topq, j ), ldz,work, nblst, czero, work( pw ), nh ) call stdlib${ii}$_zlacpy( 'ALL', nh, nblst, work( pw ), nh,z( topq, j ), ldz ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_zunm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,z( topq, j ), ldz, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, z( topq, j ), ldz,work( ppwo ), 2_${ik}$*nnb, czero, work( pw ),nh ) call stdlib${ii}$_zlacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,z( topq, j ), ldz ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do end if ! use unblocked code to reduce the rest of the matrix ! avoid re-initialization of modified q and z. compq2 = compq compz2 = compz if ( jcol/=ilo ) then if ( wantq )compq2 = 'V' if ( wantz )compz2 = 'V' end if if ( jcoln .or. ihi1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'LOWER', n-1, n-1, czero, czero, b(2_${ik}$, 1_${ik}$), ldb ) ! quick return if possible nh = ihi - ilo + 1_${ik}$ if( nh<=1_${ik}$ ) then work( 1_${ik}$ ) = cone return end if ! determine the blocksize. nbmin = stdlib${ii}$_ilaenv( 2_${ik}$, 'ZGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) if( nb>1_${ik}$ .and. nb=6_${ik}$*n*nbmin ) then nb = lwork / ( 6_${ik}$*n ) else nb = 1_${ik}$ end if end if end if end if if( nb=nh ) then ! use unblocked code below jcol = ilo else ! use blocked code kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'ZGGHD3', ' ', n, ilo, ihi, -1_${ik}$ ) blk22 = kacc22==2_${ik}$ do jcol = ilo, ihi-2, nb nnb = min( nb, ihi-jcol-1 ) ! initialize small unitary factors that will hold the ! accumulated givens rotations in workspace. ! n2nb denotes the number of 2*nnb-by-2*nnb factors ! nblst denotes the (possibly smaller) order of the last ! factor. n2nb = ( ihi-jcol-1 ) / nnb - 1_${ik}$ nblst = ihi - jcol - n2nb*nnb call stdlib${ii}$_${ci}$laset( 'ALL', nblst, nblst, czero, cone, work, nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_${ci}$laset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, czero, cone,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! reduce columns jcol:jcol+nnb-1 of a to hessenberg form. do j = jcol, jcol+nnb-1 ! reduce jth column of a. store cosines and sines in jth ! column of a and b, respectively. do i = ihi, j+2, -1 temp = a( i-1, j ) call stdlib${ii}$_${ci}$lartg( temp, a( i, j ), c, s, a( i-1, j ) ) a( i, j ) = cmplx( c,KIND=${ck}$) b( i, j ) = s end do ! accumulate givens rotations into workspace array. ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 ctemp = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = ctemp*temp - s*work( jj ) work( jj ) = conjg( s )*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 ctemp = a( i, j ) s = b( i, j ) do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = ctemp*temp - s*work( jj ) work( jj ) = conjg( s )*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! top denotes the number of top rows in a and b that will ! not be updated during the next steps. if( jcol<=2_${ik}$ ) then top = 0_${ik}$ else top = jcol end if ! propagate transformations through b and replace stored ! left sines/cosines by right sines/cosines. do jj = n, j+1, -1 ! update jjth column of b. do i = min( jj+1, ihi ), j+2, -1 ctemp = a( i, j ) s = b( i, j ) temp = b( i, jj ) b( i, jj ) = ctemp*temp - conjg( s )*b( i-1, jj ) b( i-1, jj ) = s*temp + ctemp*b( i-1, jj ) end do ! annihilate b( jj+1, jj ). if( jj0_${ik}$ ) then do i = jj, 1, -1 c = real( a( j+1+i, j ),KIND=${ck}$) call stdlib${ii}$_${ci}$rot( ihi-top, a( top+1, j+i+1 ), 1_${ik}$,a( top+1, j+i ), 1_${ik}$, c,-& conjg( b( j+1+i, j ) ) ) end do end if ! update (j+1)th column of a by transformations from left. if ( j < jcol + nnb - 1_${ik}$ ) then len = 1_${ik}$ + j - jcol ! multiply with the trailing accumulated unitary ! matrix, which takes the form ! [ u11 u12 ] ! u = [ ], ! [ u21 u22 ] ! where u21 is a len-by-len matrix and u12 is lower ! triangular. jrow = ihi - nblst + 1_${ik}$ call stdlib${ii}$_${ci}$gemv( 'CONJUGATE', nblst, len, cone, work,nblst, a( jrow, j+1 & ), 1_${ik}$, czero,work( pw ), 1_${ik}$ ) ppw = pw + len do i = jrow, jrow+nblst-len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_${ci}$trmv( 'LOWER', 'CONJUGATE', 'NON-UNIT',nblst-len, work( & len*nblst + 1_${ik}$ ), nblst,work( pw+len ), 1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE', len, nblst-len, cone,work( (len+1)*nblst - & len + 1_${ik}$ ), nblst,a( jrow+nblst-len, j+1 ), 1_${ik}$, cone,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+nblst-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ! multiply with the other accumulated unitary ! matrices, which take the form ! [ u11 u12 0 ] ! [ ] ! u = [ u21 u22 0 ], ! [ ] ! [ 0 0 i ] ! where i denotes the (nnb-len)-by-(nnb-len) identity ! matrix, u21 is a len-by-len upper triangular matrix ! and u12 is an nnb-by-nnb lower triangular matrix. ppwo = 1_${ik}$ + nblst*nblst j0 = jrow - nnb do jrow = j0, jcol+1, -nnb ppw = pw + len do i = jrow, jrow+nnb-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do ppw = pw do i = jrow+nnb, jrow+nnb+len-1 work( ppw ) = a( i, j+1 ) ppw = ppw + 1_${ik}$ end do call stdlib${ii}$_${ci}$trmv( 'UPPER', 'CONJUGATE', 'NON-UNIT', len,work( ppwo + & nnb ), 2_${ik}$*nnb, work( pw ),1_${ik}$ ) call stdlib${ii}$_${ci}$trmv( 'LOWER', 'CONJUGATE', 'NON-UNIT', nnb,work( ppwo + & 2_${ik}$*len*nnb ),2_${ik}$*nnb, work( pw + len ), 1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE', nnb, len, cone,work( ppwo ), 2_${ik}$*nnb, a( & jrow, j+1 ), 1_${ik}$,cone, work( pw ), 1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE', len, nnb, cone,work( ppwo + 2_${ik}$*len*nnb + & nnb ), 2_${ik}$*nnb,a( jrow+nnb, j+1 ), 1_${ik}$, cone,work( pw+len ), 1_${ik}$ ) ppw = pw do i = jrow, jrow+len+nnb-1 a( i, j+1 ) = work( ppw ) ppw = ppw + 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do ! apply accumulated unitary matrices to a. cola = n - jcol - nnb + 1_${ik}$ j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_${ci}$gemm( 'CONJUGATE', 'NO TRANSPOSE', nblst,cola, nblst, cone, work, & nblst,a( j, jcol+nnb ), lda, czero, work( pw ),nblst ) call stdlib${ii}$_${ci}$lacpy( 'ALL', nblst, cola, work( pw ), nblst,a( j, jcol+nnb ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of ! [ u11 u12 ] ! u = [ ] ! [ u21 u22 ], ! where all blocks are nnb-by-nnb, u21 is upper ! triangular and u12 is lower triangular. call stdlib${ii}$_${ci}$unm22( 'LEFT', 'CONJUGATE', 2_${ik}$*nnb, cola, nnb,nnb, work( ppwo )& , 2_${ik}$*nnb,a( j, jcol+nnb ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_${ci}$gemm( 'CONJUGATE', 'NO TRANSPOSE', 2_${ik}$*nnb,cola, 2_${ik}$*nnb, cone, & work( ppwo ), 2_${ik}$*nnb,a( j, jcol+nnb ), lda, czero, work( pw ),2_${ik}$*nnb ) call stdlib${ii}$_${ci}$lacpy( 'ALL', 2_${ik}$*nnb, cola, work( pw ), 2_${ik}$*nnb,a( j, jcol+nnb ),& lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do ! apply accumulated unitary matrices to q. if( wantq ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, cone, q( & topq, j ), ldq,work, nblst, czero, work( pw ), nh ) call stdlib${ii}$_${ci}$lacpy( 'ALL', nh, nblst, work( pw ), nh,q( topq, j ), ldq ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_${ci}$unm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,q( topq, j ), ldq, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, q( topq, j ), ldq,work( ppwo ), 2_${ik}$*nnb, czero, work( pw ),nh ) call stdlib${ii}$_${ci}$lacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,q( topq, j ), ldq ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! accumulate right givens rotations if required. if ( wantz .or. top>0_${ik}$ ) then ! initialize small unitary factors that will hold the ! accumulated givens rotations in workspace. call stdlib${ii}$_${ci}$laset( 'ALL', nblst, nblst, czero, cone, work,nblst ) pw = nblst * nblst + 1_${ik}$ do i = 1, n2nb call stdlib${ii}$_${ci}$laset( 'ALL', 2_${ik}$*nnb, 2_${ik}$*nnb, czero, cone,work( pw ), 2_${ik}$*nnb ) pw = pw + 4_${ik}$*nnb*nnb end do ! accumulate givens rotations into workspace array. do j = jcol, jcol+nnb-1 ppw = ( nblst + 1_${ik}$ )*( nblst - 2_${ik}$ ) - j + jcol + 1_${ik}$ len = 2_${ik}$ + j - jcol jrow = j + n2nb*nnb + 2_${ik}$ do i = ihi, jrow, -1 ctemp = a( i, j ) a( i, j ) = czero s = b( i, j ) b( i, j ) = czero do jj = ppw, ppw+len-1 temp = work( jj + nblst ) work( jj + nblst ) = ctemp*temp -conjg( s )*work( jj ) work( jj ) = s*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - nblst - 1_${ik}$ end do ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2_${ik}$*nnb + nnb j0 = jrow - nnb do jrow = j0, j+2, -nnb ppw = ppwo len = 2_${ik}$ + j - jcol do i = jrow+nnb-1, jrow, -1 ctemp = a( i, j ) a( i, j ) = czero s = b( i, j ) b( i, j ) = czero do jj = ppw, ppw+len-1 temp = work( jj + 2_${ik}$*nnb ) work( jj + 2_${ik}$*nnb ) = ctemp*temp -conjg( s )*work( jj ) work( jj ) = s*temp + ctemp*work( jj ) end do len = len + 1_${ik}$ ppw = ppw - 2_${ik}$*nnb - 1_${ik}$ end do ppwo = ppwo + 4_${ik}$*nnb*nnb end do end do else call stdlib${ii}$_${ci}$laset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, czero, czero,a( jcol + 2_${ik}$, & jcol ), lda ) call stdlib${ii}$_${ci}$laset( 'LOWER', ihi - jcol - 1_${ik}$, nnb, czero, czero,b( jcol + 2_${ik}$, & jcol ), ldb ) end if ! apply accumulated unitary matrices to a and b. if ( top>0_${ik}$ ) then j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, cone, a( & 1_${ik}$, j ), lda,work, nblst, czero, work( pw ), top ) call stdlib${ii}$_${ci}$lacpy( 'ALL', top, nblst, work( pw ), top,a( 1_${ik}$, j ), lda ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_${ci}$unm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,a( 1_${ik}$, j ), lda, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, a( 1_${ik}$, j ), lda,work( ppwo ), 2_${ik}$*nnb, czero,work( pw ), top ) call stdlib${ii}$_${ci}$lacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,a( 1_${ik}$, j ), lda ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do j = ihi - nblst + 1_${ik}$ call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,nblst, nblst, cone, b( & 1_${ik}$, j ), ldb,work, nblst, czero, work( pw ), top ) call stdlib${ii}$_${ci}$lacpy( 'ALL', top, nblst, work( pw ), top,b( 1_${ik}$, j ), ldb ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_${ci}$unm22( 'RIGHT', 'NO TRANSPOSE', top, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,b( 1_${ik}$, j ), ldb, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', top,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, b( 1_${ik}$, j ), ldb,work( ppwo ), 2_${ik}$*nnb, czero,work( pw ), top ) call stdlib${ii}$_${ci}$lacpy( 'ALL', top, 2_${ik}$*nnb, work( pw ), top,b( 1_${ik}$, j ), ldb ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if ! apply accumulated unitary matrices to z. if( wantz ) then j = ihi - nblst + 1_${ik}$ if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ else topq = 1_${ik}$ nh = n end if call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,nblst, nblst, cone, z( & topq, j ), ldz,work, nblst, czero, work( pw ), nh ) call stdlib${ii}$_${ci}$lacpy( 'ALL', nh, nblst, work( pw ), nh,z( topq, j ), ldz ) ppwo = nblst*nblst + 1_${ik}$ j0 = j - nnb do j = j0, jcol+1, -nnb if ( initq ) then topq = max( 2_${ik}$, j - jcol + 1_${ik}$ ) nh = ihi - topq + 1_${ik}$ end if if ( blk22 ) then ! exploit the structure of u. call stdlib${ii}$_${ci}$unm22( 'RIGHT', 'NO TRANSPOSE', nh, 2_${ik}$*nnb,nnb, nnb, work( & ppwo ), 2_${ik}$*nnb,z( topq, j ), ldz, work( pw ),lwork-pw+1, ierr ) else ! ignore the structure of u. call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', nh,2_${ik}$*nnb, 2_${ik}$*nnb, & cone, z( topq, j ), ldz,work( ppwo ), 2_${ik}$*nnb, czero, work( pw ),nh ) call stdlib${ii}$_${ci}$lacpy( 'ALL', nh, 2_${ik}$*nnb, work( pw ), nh,z( topq, j ), ldz ) end if ppwo = ppwo + 4_${ik}$*nnb*nnb end do end if end do end if ! use unblocked code to reduce the rest of the matrix ! avoid re-initialization of modified q and z. compq2 = compq compz2 = compz if ( jcol/=ilo ) then if ( wantq )compq2 = 'V' if ( wantz )compz2 = 'V' end if if ( jcol 0, and P(j+1,j+1) > 0. !! Optionally, the orthogonal matrix Q from the generalized Schur !! factorization may be postmultiplied into an input matrix Q1, and the !! orthogonal matrix Z may be postmultiplied into an input matrix Z1. !! If Q1 and Z1 are the orthogonal matrices from SGGHRD that reduced !! the matrix pair (A,B) to generalized upper Hessenberg form, then the !! output matrices Q1*Q and Z1*Z are the orthogonal factors from the !! generalized Schur factorization of (A,B): !! A = (Q1*Q)*S*(Z1*Z)**T, B = (Q1*Q)*P*(Z1*Z)**T. !! To avoid overflow, eigenvalues of the matrix pair (H,T) (equivalently, !! of (A,B)) are computed as a pair of values (alpha,beta), where alpha is !! complex and beta real. !! If beta is nonzero, lambda = alpha / beta is an eigenvalue of the !! generalized nonsymmetric eigenvalue problem (GNEP) !! A*x = lambda*B*x !! and if alpha is nonzero, mu = beta / alpha is an eigenvalue of the !! alternate form of the GNEP !! mu*A*y = B*y. !! Real eigenvalues can be read directly from the generalized Schur !! form: !! alpha = S(i,i), beta = P(i,i). !! Ref: C.B. Moler !! Eigenvalue Problems", SIAM J. Numer. Anal., 10(1973), !! pp. 241--256. beta, q, ldq, z, ldz, work,lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compq, compz, job integer(${ik}$), intent(in) :: ihi, ilo, ldh, ldq, ldt, ldz, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments real(sp), intent(out) :: alphai(*), alphar(*), beta(*), work(*) real(sp), intent(inout) :: h(ldh,*), q(ldq,*), t(ldt,*), z(ldz,*) ! ===================================================================== ! Parameters real(sp), parameter :: safety = 1.0e+2_sp ! $ safety = one ) ! Local Scalars logical(lk) :: ilazr2, ilazro, ${ik}$ivt, ilq, ilschr, ilz, lquery integer(${ik}$) :: icompq, icompz, ifirst, ifrstm, iiter, ilast, ilastm, in, ischur, & istart, j, jc, jch, jiter, jr, maxit real(sp) :: a11, a12, a1i, a1r, a21, a22, a2i, a2r, ad11, ad11l, ad12, ad12l, ad21, & ad21l, ad22, ad22l, ad32l, an, anorm, ascale, atol, b11, b1a, b1i, b1r, b22, b2a, b2i, & b2r, bn, bnorm, bscale, btol, c, c11i, c11r, c12, c21, c22i, c22r, cl, cq, cr, cz, & eshift, s, s1, s1inv, s2, safmax, safmin, scale, sl, sqi, sqr, sr, szi, szr, t1, tau, & temp, temp2, tempi, tempr, u1, u12, u12l, u2, ulp, vs, w11, w12, w21, w22, wabs, wi, & wr, wr2 ! Local Arrays real(sp) :: v(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode job, compq, compz if( stdlib_lsame( job, 'E' ) ) then ilschr = .false. ischur = 1_${ik}$ else if( stdlib_lsame( job, 'S' ) ) then ilschr = .true. ischur = 2_${ik}$ else ischur = 0_${ik}$ end if if( stdlib_lsame( compq, 'N' ) ) then ilq = .false. icompq = 1_${ik}$ else if( stdlib_lsame( compq, 'V' ) ) then ilq = .true. icompq = 2_${ik}$ else if( stdlib_lsame( compq, 'I' ) ) then ilq = .true. icompq = 3_${ik}$ else icompq = 0_${ik}$ end if if( stdlib_lsame( compz, 'N' ) ) then ilz = .false. icompz = 1_${ik}$ else if( stdlib_lsame( compz, 'V' ) ) then ilz = .true. icompz = 2_${ik}$ else if( stdlib_lsame( compz, 'I' ) ) then ilz = .true. icompz = 3_${ik}$ else icompz = 0_${ik}$ end if ! check argument values info = 0_${ik}$ work( 1_${ik}$ ) = max( 1_${ik}$, n ) lquery = ( lwork==-1_${ik}$ ) if( ischur==0_${ik}$ ) then info = -1_${ik}$ else if( icompq==0_${ik}$ ) then info = -2_${ik}$ else if( icompz==0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ilo<1_${ik}$ ) then info = -5_${ik}$ else if( ihi>n .or. ihi ilo )temp = temp + abs ( t( j - 1_${ik}$, j ) ) if( abs( t( j, j ) )=btol ) then if( jch+1>=ilast ) then go to 80 else ifirst = jch + 1_${ik}$ go to 110 end if end if t( jch+1, jch+1 ) = zero end do go to 70 else ! only test 2 passed -- chase the zero to t(ilast,ilast) ! then process as in the case t(ilast,ilast)=0 do jch = j, ilast - 1 temp = t( jch, jch+1 ) call stdlib${ii}$_slartg( temp, t( jch+1, jch+1 ), c, s,t( jch, jch+1 ) ) t( jch+1, jch+1 ) = zero if( jchilast )ifrstm = ilo end if go to 350 ! qz step ! this iteration only involves rows/columns ifirst:ilast. we ! assume ifirst < ilast, and that the diagonal of b is non-zero. 110 continue iiter = iiter + 1_${ik}$ if( .not.ilschr ) then ifrstm = ifirst end if ! compute single shifts. ! at this point, ifirst < ilast, and the diagonal elements of ! t(ifirst:ilast,ifirst,ilast) are larger than btol (in ! magnitude) if( ( iiter / 10_${ik}$ )*10_${ik}$==iiter ) then ! exceptional shift. chosen for no particularly good reason. ! (single shift only.) if( ( real( maxit,KIND=sp)*safmin )*abs( h( ilast, ilast-1 ) ) abs( (wr2/s2)*t( & ilast, ilast )- h( ilast, ilast ) ) ) then temp = wr wr = wr2 wr2 = temp temp = s1 s1 = s2 s2 = temp end if temp = max( s1, safmin*max( one, abs( wr ), abs( wi ) ) ) if( wi/=zero )go to 200 end if ! fiddle with shift to avoid overflow temp = min( ascale, one )*( half*safmax ) if( s1>temp ) then scale = temp / s1 else scale = one end if temp = min( bscale, one )*( half*safmax ) if( abs( wr )>temp )scale = min( scale, temp / abs( wr ) ) s1 = scale*s1 wr = scale*wr ! now check for two consecutive small subdiagonals. do j = ilast - 1, ifirst + 1, -1 istart = j temp = abs( s1*h( j, j-1 ) ) temp2 = abs( s1*h( j, j )-wr*t( j, j ) ) tempr = max( temp, temp2 ) if( tempristart ) then temp = h( j, j-1 ) call stdlib${ii}$_slartg( temp, h( j+1, j-1 ), c, s, h( j, j-1 ) ) h( j+1, j-1 ) = zero end if do jc = j, ilastm temp = c*h( j, jc ) + s*h( j+1, jc ) h( j+1, jc ) = -s*h( j, jc ) + c*h( j+1, jc ) h( j, jc ) = temp temp2 = c*t( j, jc ) + s*t( j+1, jc ) t( j+1, jc ) = -s*t( j, jc ) + c*t( j+1, jc ) t( j, jc ) = temp2 end do if( ilq ) then do jr = 1, n temp = c*q( jr, j ) + s*q( jr, j+1 ) q( jr, j+1 ) = -s*q( jr, j ) + c*q( jr, j+1 ) q( jr, j ) = temp end do end if temp = t( j+1, j+1 ) call stdlib${ii}$_slartg( temp, t( j+1, j ), c, s, t( j+1, j+1 ) ) t( j+1, j ) = zero do jr = ifrstm, min( j+2, ilast ) temp = c*h( jr, j+1 ) + s*h( jr, j ) h( jr, j ) = -s*h( jr, j+1 ) + c*h( jr, j ) h( jr, j+1 ) = temp end do do jr = ifrstm, j temp = c*t( jr, j+1 ) + s*t( jr, j ) t( jr, j ) = -s*t( jr, j+1 ) + c*t( jr, j ) t( jr, j+1 ) = temp end do if( ilz ) then do jr = 1, n temp = c*z( jr, j+1 ) + s*z( jr, j ) z( jr, j ) = -s*z( jr, j+1 ) + c*z( jr, j ) z( jr, j+1 ) = temp end do end if end do loop_190 go to 350 ! use francis double-shift ! note: the francis double-shift should work with real shifts, ! but only if the block is at least 3x3. ! this code may break if this point is reached with ! a 2x2 block with real eigenvalues. 200 continue if( ifirst+1==ilast ) then ! special case -- 2x2 block with complex eigenvectors ! step 1: standardize, that is, rotate so that ! ( b11 0 ) ! b = ( ) with b11 non-negative. ! ( 0 b22 ) call stdlib${ii}$_slasv2( t( ilast-1, ilast-1 ), t( ilast-1, ilast ),t( ilast, ilast ),& b22, b11, sr, cr, sl, cl ) if( b11 unfl ) ! __ ! (sa - wb) ( cz -sz ) ! ( sz cz ) c11r = s1*a11 - wr*b11 c11i = -wi*b11 c12 = s1*a12 c21 = s1*a21 c22r = s1*a22 - wr*b22 c22i = -wi*b22 if( abs( c11r )+abs( c11i )+abs( c12 )>abs( c21 )+abs( c22r )+abs( c22i ) ) & then t1 = stdlib${ii}$_slapy3( c12, c11r, c11i ) cz = c12 / t1 szr = -c11r / t1 szi = -c11i / t1 else cz = stdlib${ii}$_slapy2( c22r, c22i ) if( cz<=safmin ) then cz = zero szr = one szi = zero else tempr = c22r / cz tempi = c22i / cz t1 = stdlib${ii}$_slapy2( cz, c21 ) cz = cz / t1 szr = -c21*tempr / t1 szi = c21*tempi / t1 end if end if ! compute givens rotation on left ! ( cq sq ) ! ( __ ) a or b ! ( -sq cq ) an = abs( a11 ) + abs( a12 ) + abs( a21 ) + abs( a22 ) bn = abs( b11 ) + abs( b22 ) wabs = abs( wr ) + abs( wi ) if( s1*an>wabs*bn ) then cq = cz*b11 sqr = szr*b22 sqi = -szi*b22 else a1r = cz*a11 + szr*a12 a1i = szi*a12 a2r = cz*a21 + szr*a22 a2i = szi*a22 cq = stdlib${ii}$_slapy2( a1r, a1i ) if( cq<=safmin ) then cq = zero sqr = one sqi = zero else tempr = a1r / cq tempi = a1i / cq sqr = tempr*a2r + tempi*a2i sqi = tempi*a2r - tempr*a2i end if end if t1 = stdlib${ii}$_slapy3( cq, sqr, sqi ) cq = cq / t1 sqr = sqr / t1 sqi = sqi / t1 ! compute diagonal elements of qbz tempr = sqr*szr - sqi*szi tempi = sqr*szi + sqi*szr b1r = cq*cz*b11 + tempr*b22 b1i = tempi*b22 b1a = stdlib${ii}$_slapy2( b1r, b1i ) b2r = cq*cz*b22 + tempr*b11 b2i = -tempi*b11 b2a = stdlib${ii}$_slapy2( b2r, b2i ) ! normalize so beta > 0, and im( alpha1 ) > 0 beta( ilast-1 ) = b1a beta( ilast ) = b2a alphar( ilast-1 ) = ( wr*b1a )*s1inv alphai( ilast-1 ) = ( wi*b1a )*s1inv alphar( ilast ) = ( wr*b2a )*s1inv alphai( ilast ) = -( wi*b2a )*s1inv ! step 3: go to next block -- exit if finished. ilast = ifirst - 1_${ik}$ if( ilastilast )ifrstm = ilo end if go to 350 else ! usual case: 3x3 or larger block, using francis implicit ! double-shift ! 2 ! eigenvalue equation is w - c w + d = 0, ! -1 2 -1 ! so compute 1st column of (a b ) - c a b + d ! using the formula in qzit (from eispack) ! we assume that the block is at least 3x3 ad11 = ( ascale*h( ilast-1, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad21 = ( ascale*h( ilast, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad12 = ( ascale*h( ilast-1, ilast ) ) /( bscale*t( ilast, ilast ) ) ad22 = ( ascale*h( ilast, ilast ) ) /( bscale*t( ilast, ilast ) ) u12 = t( ilast-1, ilast ) / t( ilast, ilast ) ad11l = ( ascale*h( ifirst, ifirst ) ) /( bscale*t( ifirst, ifirst ) ) ad21l = ( ascale*h( ifirst+1, ifirst ) ) /( bscale*t( ifirst, ifirst ) ) ad12l = ( ascale*h( ifirst, ifirst+1 ) ) /( bscale*t( ifirst+1, ifirst+1 ) ) ad22l = ( ascale*h( ifirst+1, ifirst+1 ) ) /( bscale*t( ifirst+1, ifirst+1 ) ) ad32l = ( ascale*h( ifirst+2, ifirst+1 ) ) /( bscale*t( ifirst+1, ifirst+1 ) ) u12l = t( ifirst, ifirst+1 ) / t( ifirst+1, ifirst+1 ) v( 1_${ik}$ ) = ( ad11-ad11l )*( ad22-ad11l ) - ad12*ad21 +ad21*u12*ad11l + ( ad12l-& ad11l*u12l )*ad21l v( 2_${ik}$ ) = ( ( ad22l-ad11l )-ad21l*u12l-( ad11-ad11l )-( ad22-ad11l )+ad21*u12 )& *ad21l v( 3_${ik}$ ) = ad32l*ad21l istart = ifirst call stdlib${ii}$_slarfg( 3_${ik}$, v( 1_${ik}$ ), v( 2_${ik}$ ), 1_${ik}$, tau ) v( 1_${ik}$ ) = one ! sweep loop_290: do j = istart, ilast - 2 ! all but last elements: use 3x3 householder transforms. ! zero (j-1)st column of a if( j>istart ) then v( 1_${ik}$ ) = h( j, j-1 ) v( 2_${ik}$ ) = h( j+1, j-1 ) v( 3_${ik}$ ) = h( j+2, j-1 ) call stdlib${ii}$_slarfg( 3_${ik}$, h( j, j-1 ), v( 2_${ik}$ ), 1_${ik}$, tau ) v( 1_${ik}$ ) = one h( j+1, j-1 ) = zero h( j+2, j-1 ) = zero end if do jc = j, ilastm temp = tau*( h( j, jc )+v( 2_${ik}$ )*h( j+1, jc )+v( 3_${ik}$ )*h( j+2, jc ) ) h( j, jc ) = h( j, jc ) - temp h( j+1, jc ) = h( j+1, jc ) - temp*v( 2_${ik}$ ) h( j+2, jc ) = h( j+2, jc ) - temp*v( 3_${ik}$ ) temp2 = tau*( t( j, jc )+v( 2_${ik}$ )*t( j+1, jc )+v( 3_${ik}$ )*t( j+2, jc ) ) t( j, jc ) = t( j, jc ) - temp2 t( j+1, jc ) = t( j+1, jc ) - temp2*v( 2_${ik}$ ) t( j+2, jc ) = t( j+2, jc ) - temp2*v( 3_${ik}$ ) end do if( ilq ) then do jr = 1, n temp = tau*( q( jr, j )+v( 2_${ik}$ )*q( jr, j+1 )+v( 3_${ik}$ )*q( jr, j+2 ) ) q( jr, j ) = q( jr, j ) - temp q( jr, j+1 ) = q( jr, j+1 ) - temp*v( 2_${ik}$ ) q( jr, j+2 ) = q( jr, j+2 ) - temp*v( 3_${ik}$ ) end do end if ! zero j-th column of b (see slagbc for details) ! swap rows to pivot ${ik}$ivt = .false. temp = max( abs( t( j+1, j+1 ) ), abs( t( j+1, j+2 ) ) ) temp2 = max( abs( t( j+2, j+1 ) ), abs( t( j+2, j+2 ) ) ) if( max( temp, temp2 )=temp2 ) then w11 = t( j+1, j+1 ) w21 = t( j+2, j+1 ) w12 = t( j+1, j+2 ) w22 = t( j+2, j+2 ) u1 = t( j+1, j ) u2 = t( j+2, j ) else w21 = t( j+1, j+1 ) w11 = t( j+2, j+1 ) w22 = t( j+1, j+2 ) w12 = t( j+2, j+2 ) u2 = t( j+1, j ) u1 = t( j+2, j ) end if ! swap columns if nec. if( abs( w12 )>abs( w11 ) ) then ${ik}$ivt = .true. temp = w12 temp2 = w22 w12 = w11 w22 = w21 w11 = temp w21 = temp2 end if ! lu-factor temp = w21 / w11 u2 = u2 - temp*u1 w22 = w22 - temp*w12 w21 = zero ! compute scale scale = one if( abs( w22 ) 0, and P(j+1,j+1) > 0. !! Optionally, the orthogonal matrix Q from the generalized Schur !! factorization may be postmultiplied into an input matrix Q1, and the !! orthogonal matrix Z may be postmultiplied into an input matrix Z1. !! If Q1 and Z1 are the orthogonal matrices from DGGHRD that reduced !! the matrix pair (A,B) to generalized upper Hessenberg form, then the !! output matrices Q1*Q and Z1*Z are the orthogonal factors from the !! generalized Schur factorization of (A,B): !! A = (Q1*Q)*S*(Z1*Z)**T, B = (Q1*Q)*P*(Z1*Z)**T. !! To avoid overflow, eigenvalues of the matrix pair (H,T) (equivalently, !! of (A,B)) are computed as a pair of values (alpha,beta), where alpha is !! complex and beta real. !! If beta is nonzero, lambda = alpha / beta is an eigenvalue of the !! generalized nonsymmetric eigenvalue problem (GNEP) !! A*x = lambda*B*x !! and if alpha is nonzero, mu = beta / alpha is an eigenvalue of the !! alternate form of the GNEP !! mu*A*y = B*y. !! Real eigenvalues can be read directly from the generalized Schur !! form: !! alpha = S(i,i), beta = P(i,i). !! Ref: C.B. Moler !! Eigenvalue Problems", SIAM J. Numer. Anal., 10(1973), !! pp. 241--256. beta, q, ldq, z, ldz, work,lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compq, compz, job integer(${ik}$), intent(in) :: ihi, ilo, ldh, ldq, ldt, ldz, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments real(dp), intent(out) :: alphai(*), alphar(*), beta(*), work(*) real(dp), intent(inout) :: h(ldh,*), q(ldq,*), t(ldt,*), z(ldz,*) ! ===================================================================== ! Parameters real(dp), parameter :: safety = 1.0e+2_dp ! $ safety = one ) ! Local Scalars logical(lk) :: ilazr2, ilazro, ${ik}$ivt, ilq, ilschr, ilz, lquery integer(${ik}$) :: icompq, icompz, ifirst, ifrstm, iiter, ilast, ilastm, in, ischur, & istart, j, jc, jch, jiter, jr, maxit real(dp) :: a11, a12, a1i, a1r, a21, a22, a2i, a2r, ad11, ad11l, ad12, ad12l, ad21, & ad21l, ad22, ad22l, ad32l, an, anorm, ascale, atol, b11, b1a, b1i, b1r, b22, b2a, b2i, & b2r, bn, bnorm, bscale, btol, c, c11i, c11r, c12, c21, c22i, c22r, cl, cq, cr, cz, & eshift, s, s1, s1inv, s2, safmax, safmin, scale, sl, sqi, sqr, sr, szi, szr, t1, tau, & temp, temp2, tempi, tempr, u1, u12, u12l, u2, ulp, vs, w11, w12, w21, w22, wabs, wi, & wr, wr2 ! Local Arrays real(dp) :: v(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode job, compq, compz if( stdlib_lsame( job, 'E' ) ) then ilschr = .false. ischur = 1_${ik}$ else if( stdlib_lsame( job, 'S' ) ) then ilschr = .true. ischur = 2_${ik}$ else ischur = 0_${ik}$ end if if( stdlib_lsame( compq, 'N' ) ) then ilq = .false. icompq = 1_${ik}$ else if( stdlib_lsame( compq, 'V' ) ) then ilq = .true. icompq = 2_${ik}$ else if( stdlib_lsame( compq, 'I' ) ) then ilq = .true. icompq = 3_${ik}$ else icompq = 0_${ik}$ end if if( stdlib_lsame( compz, 'N' ) ) then ilz = .false. icompz = 1_${ik}$ else if( stdlib_lsame( compz, 'V' ) ) then ilz = .true. icompz = 2_${ik}$ else if( stdlib_lsame( compz, 'I' ) ) then ilz = .true. icompz = 3_${ik}$ else icompz = 0_${ik}$ end if ! check argument values info = 0_${ik}$ work( 1_${ik}$ ) = max( 1_${ik}$, n ) lquery = ( lwork==-1_${ik}$ ) if( ischur==0_${ik}$ ) then info = -1_${ik}$ else if( icompq==0_${ik}$ ) then info = -2_${ik}$ else if( icompz==0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ilo<1_${ik}$ ) then info = -5_${ik}$ else if( ihi>n .or. ihi ilo )temp = temp + abs ( t( j - 1_${ik}$, j ) ) if( abs( t( j, j ) )=btol ) then if( jch+1>=ilast ) then go to 80 else ifirst = jch + 1_${ik}$ go to 110 end if end if t( jch+1, jch+1 ) = zero end do go to 70 else ! only test 2 passed -- chase the zero to t(ilast,ilast) ! then process as in the case t(ilast,ilast)=0 do jch = j, ilast - 1 temp = t( jch, jch+1 ) call stdlib${ii}$_dlartg( temp, t( jch+1, jch+1 ), c, s,t( jch, jch+1 ) ) t( jch+1, jch+1 ) = zero if( jchilast )ifrstm = ilo end if go to 350 ! qz step ! this iteration only involves rows/columns ifirst:ilast. we ! assume ifirst < ilast, and that the diagonal of b is non-zero. 110 continue iiter = iiter + 1_${ik}$ if( .not.ilschr ) then ifrstm = ifirst end if ! compute single shifts. ! at this point, ifirst < ilast, and the diagonal elements of ! t(ifirst:ilast,ifirst,ilast) are larger than btol (in ! magnitude) if( ( iiter / 10_${ik}$ )*10_${ik}$==iiter ) then ! exceptional shift. chosen for no particularly good reason. ! (single shift only.) if( ( real( maxit,KIND=dp)*safmin )*abs( h( ilast, ilast-1 ) ) abs( (wr2/s2)*t( & ilast, ilast )- h( ilast, ilast ) ) ) then temp = wr wr = wr2 wr2 = temp temp = s1 s1 = s2 s2 = temp end if temp = max( s1, safmin*max( one, abs( wr ), abs( wi ) ) ) if( wi/=zero )go to 200 end if ! fiddle with shift to avoid overflow temp = min( ascale, one )*( half*safmax ) if( s1>temp ) then scale = temp / s1 else scale = one end if temp = min( bscale, one )*( half*safmax ) if( abs( wr )>temp )scale = min( scale, temp / abs( wr ) ) s1 = scale*s1 wr = scale*wr ! now check for two consecutive small subdiagonals. do j = ilast - 1, ifirst + 1, -1 istart = j temp = abs( s1*h( j, j-1 ) ) temp2 = abs( s1*h( j, j )-wr*t( j, j ) ) tempr = max( temp, temp2 ) if( tempristart ) then temp = h( j, j-1 ) call stdlib${ii}$_dlartg( temp, h( j+1, j-1 ), c, s, h( j, j-1 ) ) h( j+1, j-1 ) = zero end if do jc = j, ilastm temp = c*h( j, jc ) + s*h( j+1, jc ) h( j+1, jc ) = -s*h( j, jc ) + c*h( j+1, jc ) h( j, jc ) = temp temp2 = c*t( j, jc ) + s*t( j+1, jc ) t( j+1, jc ) = -s*t( j, jc ) + c*t( j+1, jc ) t( j, jc ) = temp2 end do if( ilq ) then do jr = 1, n temp = c*q( jr, j ) + s*q( jr, j+1 ) q( jr, j+1 ) = -s*q( jr, j ) + c*q( jr, j+1 ) q( jr, j ) = temp end do end if temp = t( j+1, j+1 ) call stdlib${ii}$_dlartg( temp, t( j+1, j ), c, s, t( j+1, j+1 ) ) t( j+1, j ) = zero do jr = ifrstm, min( j+2, ilast ) temp = c*h( jr, j+1 ) + s*h( jr, j ) h( jr, j ) = -s*h( jr, j+1 ) + c*h( jr, j ) h( jr, j+1 ) = temp end do do jr = ifrstm, j temp = c*t( jr, j+1 ) + s*t( jr, j ) t( jr, j ) = -s*t( jr, j+1 ) + c*t( jr, j ) t( jr, j+1 ) = temp end do if( ilz ) then do jr = 1, n temp = c*z( jr, j+1 ) + s*z( jr, j ) z( jr, j ) = -s*z( jr, j+1 ) + c*z( jr, j ) z( jr, j+1 ) = temp end do end if end do loop_190 go to 350 ! use francis double-shift ! note: the francis double-shift should work with real shifts, ! but only if the block is at least 3x3. ! this code may break if this point is reached with ! a 2x2 block with real eigenvalues. 200 continue if( ifirst+1==ilast ) then ! special case -- 2x2 block with complex eigenvectors ! step 1: standardize, that is, rotate so that ! ( b11 0 ) ! b = ( ) with b11 non-negative. ! ( 0 b22 ) call stdlib${ii}$_dlasv2( t( ilast-1, ilast-1 ), t( ilast-1, ilast ),t( ilast, ilast ),& b22, b11, sr, cr, sl, cl ) if( b11 unfl ) ! __ ! (sa - wb) ( cz -sz ) ! ( sz cz ) c11r = s1*a11 - wr*b11 c11i = -wi*b11 c12 = s1*a12 c21 = s1*a21 c22r = s1*a22 - wr*b22 c22i = -wi*b22 if( abs( c11r )+abs( c11i )+abs( c12 )>abs( c21 )+abs( c22r )+abs( c22i ) ) & then t1 = stdlib${ii}$_dlapy3( c12, c11r, c11i ) cz = c12 / t1 szr = -c11r / t1 szi = -c11i / t1 else cz = stdlib${ii}$_dlapy2( c22r, c22i ) if( cz<=safmin ) then cz = zero szr = one szi = zero else tempr = c22r / cz tempi = c22i / cz t1 = stdlib${ii}$_dlapy2( cz, c21 ) cz = cz / t1 szr = -c21*tempr / t1 szi = c21*tempi / t1 end if end if ! compute givens rotation on left ! ( cq sq ) ! ( __ ) a or b ! ( -sq cq ) an = abs( a11 ) + abs( a12 ) + abs( a21 ) + abs( a22 ) bn = abs( b11 ) + abs( b22 ) wabs = abs( wr ) + abs( wi ) if( s1*an>wabs*bn ) then cq = cz*b11 sqr = szr*b22 sqi = -szi*b22 else a1r = cz*a11 + szr*a12 a1i = szi*a12 a2r = cz*a21 + szr*a22 a2i = szi*a22 cq = stdlib${ii}$_dlapy2( a1r, a1i ) if( cq<=safmin ) then cq = zero sqr = one sqi = zero else tempr = a1r / cq tempi = a1i / cq sqr = tempr*a2r + tempi*a2i sqi = tempi*a2r - tempr*a2i end if end if t1 = stdlib${ii}$_dlapy3( cq, sqr, sqi ) cq = cq / t1 sqr = sqr / t1 sqi = sqi / t1 ! compute diagonal elements of qbz tempr = sqr*szr - sqi*szi tempi = sqr*szi + sqi*szr b1r = cq*cz*b11 + tempr*b22 b1i = tempi*b22 b1a = stdlib${ii}$_dlapy2( b1r, b1i ) b2r = cq*cz*b22 + tempr*b11 b2i = -tempi*b11 b2a = stdlib${ii}$_dlapy2( b2r, b2i ) ! normalize so beta > 0, and im( alpha1 ) > 0 beta( ilast-1 ) = b1a beta( ilast ) = b2a alphar( ilast-1 ) = ( wr*b1a )*s1inv alphai( ilast-1 ) = ( wi*b1a )*s1inv alphar( ilast ) = ( wr*b2a )*s1inv alphai( ilast ) = -( wi*b2a )*s1inv ! step 3: go to next block -- exit if finished. ilast = ifirst - 1_${ik}$ if( ilastilast )ifrstm = ilo end if go to 350 else ! usual case: 3x3 or larger block, using francis implicit ! double-shift ! 2 ! eigenvalue equation is w - c w + d = 0, ! -1 2 -1 ! so compute 1st column of (a b ) - c a b + d ! using the formula in qzit (from eispack) ! we assume that the block is at least 3x3 ad11 = ( ascale*h( ilast-1, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad21 = ( ascale*h( ilast, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad12 = ( ascale*h( ilast-1, ilast ) ) /( bscale*t( ilast, ilast ) ) ad22 = ( ascale*h( ilast, ilast ) ) /( bscale*t( ilast, ilast ) ) u12 = t( ilast-1, ilast ) / t( ilast, ilast ) ad11l = ( ascale*h( ifirst, ifirst ) ) /( bscale*t( ifirst, ifirst ) ) ad21l = ( ascale*h( ifirst+1, ifirst ) ) /( bscale*t( ifirst, ifirst ) ) ad12l = ( ascale*h( ifirst, ifirst+1 ) ) /( bscale*t( ifirst+1, ifirst+1 ) ) ad22l = ( ascale*h( ifirst+1, ifirst+1 ) ) /( bscale*t( ifirst+1, ifirst+1 ) ) ad32l = ( ascale*h( ifirst+2, ifirst+1 ) ) /( bscale*t( ifirst+1, ifirst+1 ) ) u12l = t( ifirst, ifirst+1 ) / t( ifirst+1, ifirst+1 ) v( 1_${ik}$ ) = ( ad11-ad11l )*( ad22-ad11l ) - ad12*ad21 +ad21*u12*ad11l + ( ad12l-& ad11l*u12l )*ad21l v( 2_${ik}$ ) = ( ( ad22l-ad11l )-ad21l*u12l-( ad11-ad11l )-( ad22-ad11l )+ad21*u12 )& *ad21l v( 3_${ik}$ ) = ad32l*ad21l istart = ifirst call stdlib${ii}$_dlarfg( 3_${ik}$, v( 1_${ik}$ ), v( 2_${ik}$ ), 1_${ik}$, tau ) v( 1_${ik}$ ) = one ! sweep loop_290: do j = istart, ilast - 2 ! all but last elements: use 3x3 householder transforms. ! zero (j-1)st column of a if( j>istart ) then v( 1_${ik}$ ) = h( j, j-1 ) v( 2_${ik}$ ) = h( j+1, j-1 ) v( 3_${ik}$ ) = h( j+2, j-1 ) call stdlib${ii}$_dlarfg( 3_${ik}$, h( j, j-1 ), v( 2_${ik}$ ), 1_${ik}$, tau ) v( 1_${ik}$ ) = one h( j+1, j-1 ) = zero h( j+2, j-1 ) = zero end if do jc = j, ilastm temp = tau*( h( j, jc )+v( 2_${ik}$ )*h( j+1, jc )+v( 3_${ik}$ )*h( j+2, jc ) ) h( j, jc ) = h( j, jc ) - temp h( j+1, jc ) = h( j+1, jc ) - temp*v( 2_${ik}$ ) h( j+2, jc ) = h( j+2, jc ) - temp*v( 3_${ik}$ ) temp2 = tau*( t( j, jc )+v( 2_${ik}$ )*t( j+1, jc )+v( 3_${ik}$ )*t( j+2, jc ) ) t( j, jc ) = t( j, jc ) - temp2 t( j+1, jc ) = t( j+1, jc ) - temp2*v( 2_${ik}$ ) t( j+2, jc ) = t( j+2, jc ) - temp2*v( 3_${ik}$ ) end do if( ilq ) then do jr = 1, n temp = tau*( q( jr, j )+v( 2_${ik}$ )*q( jr, j+1 )+v( 3_${ik}$ )*q( jr, j+2 ) ) q( jr, j ) = q( jr, j ) - temp q( jr, j+1 ) = q( jr, j+1 ) - temp*v( 2_${ik}$ ) q( jr, j+2 ) = q( jr, j+2 ) - temp*v( 3_${ik}$ ) end do end if ! zero j-th column of b (see dlagbc for details) ! swap rows to pivot ${ik}$ivt = .false. temp = max( abs( t( j+1, j+1 ) ), abs( t( j+1, j+2 ) ) ) temp2 = max( abs( t( j+2, j+1 ) ), abs( t( j+2, j+2 ) ) ) if( max( temp, temp2 )=temp2 ) then w11 = t( j+1, j+1 ) w21 = t( j+2, j+1 ) w12 = t( j+1, j+2 ) w22 = t( j+2, j+2 ) u1 = t( j+1, j ) u2 = t( j+2, j ) else w21 = t( j+1, j+1 ) w11 = t( j+2, j+1 ) w22 = t( j+1, j+2 ) w12 = t( j+2, j+2 ) u2 = t( j+1, j ) u1 = t( j+2, j ) end if ! swap columns if nec. if( abs( w12 )>abs( w11 ) ) then ${ik}$ivt = .true. temp = w12 temp2 = w22 w12 = w11 w22 = w21 w11 = temp w21 = temp2 end if ! lu-factor temp = w21 / w11 u2 = u2 - temp*u1 w22 = w22 - temp*w12 w21 = zero ! compute scale scale = one if( abs( w22 ) 0, and P(j+1,j+1) > 0. !! Optionally, the orthogonal matrix Q from the generalized Schur !! factorization may be postmultiplied into an input matrix Q1, and the !! orthogonal matrix Z may be postmultiplied into an input matrix Z1. !! If Q1 and Z1 are the orthogonal matrices from DGGHRD that reduced !! the matrix pair (A,B) to generalized upper Hessenberg form, then the !! output matrices Q1*Q and Z1*Z are the orthogonal factors from the !! generalized Schur factorization of (A,B): !! A = (Q1*Q)*S*(Z1*Z)**T, B = (Q1*Q)*P*(Z1*Z)**T. !! To avoid overflow, eigenvalues of the matrix pair (H,T) (equivalently, !! of (A,B)) are computed as a pair of values (alpha,beta), where alpha is !! complex and beta real. !! If beta is nonzero, lambda = alpha / beta is an eigenvalue of the !! generalized nonsymmetric eigenvalue problem (GNEP) !! A*x = lambda*B*x !! and if alpha is nonzero, mu = beta / alpha is an eigenvalue of the !! alternate form of the GNEP !! mu*A*y = B*y. !! Real eigenvalues can be read directly from the generalized Schur !! form: !! alpha = S(i,i), beta = P(i,i). !! Ref: C.B. Moler !! Eigenvalue Problems", SIAM J. Numer. Anal., 10(1973), !! pp. 241--256. beta, q, ldq, z, ldz, work,lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compq, compz, job integer(${ik}$), intent(in) :: ihi, ilo, ldh, ldq, ldt, ldz, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), work(*) real(${rk}$), intent(inout) :: h(ldh,*), q(ldq,*), t(ldt,*), z(ldz,*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: safety = 1.0e+2_${rk}$ ! $ safety = one ) ! Local Scalars logical(lk) :: ilazr2, ilazro, ${ik}$ivt, ilq, ilschr, ilz, lquery integer(${ik}$) :: icompq, icompz, ifirst, ifrstm, iiter, ilast, ilastm, in, ischur, & istart, j, jc, jch, jiter, jr, maxit real(${rk}$) :: a11, a12, a1i, a1r, a21, a22, a2i, a2r, ad11, ad11l, ad12, ad12l, ad21, & ad21l, ad22, ad22l, ad32l, an, anorm, ascale, atol, b11, b1a, b1i, b1r, b22, b2a, b2i, & b2r, bn, bnorm, bscale, btol, c, c11i, c11r, c12, c21, c22i, c22r, cl, cq, cr, cz, & eshift, s, s1, s1inv, s2, safmax, safmin, scale, sl, sqi, sqr, sr, szi, szr, t1, tau, & temp, temp2, tempi, tempr, u1, u12, u12l, u2, ulp, vs, w11, w12, w21, w22, wabs, wi, & wr, wr2 ! Local Arrays real(${rk}$) :: v(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode job, compq, compz if( stdlib_lsame( job, 'E' ) ) then ilschr = .false. ischur = 1_${ik}$ else if( stdlib_lsame( job, 'S' ) ) then ilschr = .true. ischur = 2_${ik}$ else ischur = 0_${ik}$ end if if( stdlib_lsame( compq, 'N' ) ) then ilq = .false. icompq = 1_${ik}$ else if( stdlib_lsame( compq, 'V' ) ) then ilq = .true. icompq = 2_${ik}$ else if( stdlib_lsame( compq, 'I' ) ) then ilq = .true. icompq = 3_${ik}$ else icompq = 0_${ik}$ end if if( stdlib_lsame( compz, 'N' ) ) then ilz = .false. icompz = 1_${ik}$ else if( stdlib_lsame( compz, 'V' ) ) then ilz = .true. icompz = 2_${ik}$ else if( stdlib_lsame( compz, 'I' ) ) then ilz = .true. icompz = 3_${ik}$ else icompz = 0_${ik}$ end if ! check argument values info = 0_${ik}$ work( 1_${ik}$ ) = max( 1_${ik}$, n ) lquery = ( lwork==-1_${ik}$ ) if( ischur==0_${ik}$ ) then info = -1_${ik}$ else if( icompq==0_${ik}$ ) then info = -2_${ik}$ else if( icompz==0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ilo<1_${ik}$ ) then info = -5_${ik}$ else if( ihi>n .or. ihi ilo )temp = temp + abs ( t( j - 1_${ik}$, j ) ) if( abs( t( j, j ) )=btol ) then if( jch+1>=ilast ) then go to 80 else ifirst = jch + 1_${ik}$ go to 110 end if end if t( jch+1, jch+1 ) = zero end do go to 70 else ! only test 2 passed -- chase the zero to t(ilast,ilast) ! then process as in the case t(ilast,ilast)=0 do jch = j, ilast - 1 temp = t( jch, jch+1 ) call stdlib${ii}$_${ri}$lartg( temp, t( jch+1, jch+1 ), c, s,t( jch, jch+1 ) ) t( jch+1, jch+1 ) = zero if( jchilast )ifrstm = ilo end if go to 350 ! qz step ! this iteration only involves rows/columns ifirst:ilast. we ! assume ifirst < ilast, and that the diagonal of b is non-zero. 110 continue iiter = iiter + 1_${ik}$ if( .not.ilschr ) then ifrstm = ifirst end if ! compute single shifts. ! at this point, ifirst < ilast, and the diagonal elements of ! t(ifirst:ilast,ifirst,ilast) are larger than btol (in ! magnitude) if( ( iiter / 10_${ik}$ )*10_${ik}$==iiter ) then ! exceptional shift. chosen for no particularly good reason. ! (single shift only.) if( ( real( maxit,KIND=${rk}$)*safmin )*abs( h( ilast, ilast-1 ) ) abs( (wr2/s2)*t( & ilast, ilast )- h( ilast, ilast ) ) ) then temp = wr wr = wr2 wr2 = temp temp = s1 s1 = s2 s2 = temp end if temp = max( s1, safmin*max( one, abs( wr ), abs( wi ) ) ) if( wi/=zero )go to 200 end if ! fiddle with shift to avoid overflow temp = min( ascale, one )*( half*safmax ) if( s1>temp ) then scale = temp / s1 else scale = one end if temp = min( bscale, one )*( half*safmax ) if( abs( wr )>temp )scale = min( scale, temp / abs( wr ) ) s1 = scale*s1 wr = scale*wr ! now check for two consecutive small subdiagonals. do j = ilast - 1, ifirst + 1, -1 istart = j temp = abs( s1*h( j, j-1 ) ) temp2 = abs( s1*h( j, j )-wr*t( j, j ) ) tempr = max( temp, temp2 ) if( tempristart ) then temp = h( j, j-1 ) call stdlib${ii}$_${ri}$lartg( temp, h( j+1, j-1 ), c, s, h( j, j-1 ) ) h( j+1, j-1 ) = zero end if do jc = j, ilastm temp = c*h( j, jc ) + s*h( j+1, jc ) h( j+1, jc ) = -s*h( j, jc ) + c*h( j+1, jc ) h( j, jc ) = temp temp2 = c*t( j, jc ) + s*t( j+1, jc ) t( j+1, jc ) = -s*t( j, jc ) + c*t( j+1, jc ) t( j, jc ) = temp2 end do if( ilq ) then do jr = 1, n temp = c*q( jr, j ) + s*q( jr, j+1 ) q( jr, j+1 ) = -s*q( jr, j ) + c*q( jr, j+1 ) q( jr, j ) = temp end do end if temp = t( j+1, j+1 ) call stdlib${ii}$_${ri}$lartg( temp, t( j+1, j ), c, s, t( j+1, j+1 ) ) t( j+1, j ) = zero do jr = ifrstm, min( j+2, ilast ) temp = c*h( jr, j+1 ) + s*h( jr, j ) h( jr, j ) = -s*h( jr, j+1 ) + c*h( jr, j ) h( jr, j+1 ) = temp end do do jr = ifrstm, j temp = c*t( jr, j+1 ) + s*t( jr, j ) t( jr, j ) = -s*t( jr, j+1 ) + c*t( jr, j ) t( jr, j+1 ) = temp end do if( ilz ) then do jr = 1, n temp = c*z( jr, j+1 ) + s*z( jr, j ) z( jr, j ) = -s*z( jr, j+1 ) + c*z( jr, j ) z( jr, j+1 ) = temp end do end if end do loop_190 go to 350 ! use francis double-shift ! note: the francis double-shift should work with real shifts, ! but only if the block is at least 3x3. ! this code may break if this point is reached with ! a 2x2 block with real eigenvalues. 200 continue if( ifirst+1==ilast ) then ! special case -- 2x2 block with complex eigenvectors ! step 1: standardize, that is, rotate so that ! ( b11 0 ) ! b = ( ) with b11 non-negative. ! ( 0 b22 ) call stdlib${ii}$_${ri}$lasv2( t( ilast-1, ilast-1 ), t( ilast-1, ilast ),t( ilast, ilast ),& b22, b11, sr, cr, sl, cl ) if( b11 unfl ) ! __ ! (sa - wb) ( cz -sz ) ! ( sz cz ) c11r = s1*a11 - wr*b11 c11i = -wi*b11 c12 = s1*a12 c21 = s1*a21 c22r = s1*a22 - wr*b22 c22i = -wi*b22 if( abs( c11r )+abs( c11i )+abs( c12 )>abs( c21 )+abs( c22r )+abs( c22i ) ) & then t1 = stdlib${ii}$_${ri}$lapy3( c12, c11r, c11i ) cz = c12 / t1 szr = -c11r / t1 szi = -c11i / t1 else cz = stdlib${ii}$_${ri}$lapy2( c22r, c22i ) if( cz<=safmin ) then cz = zero szr = one szi = zero else tempr = c22r / cz tempi = c22i / cz t1 = stdlib${ii}$_${ri}$lapy2( cz, c21 ) cz = cz / t1 szr = -c21*tempr / t1 szi = c21*tempi / t1 end if end if ! compute givens rotation on left ! ( cq sq ) ! ( __ ) a or b ! ( -sq cq ) an = abs( a11 ) + abs( a12 ) + abs( a21 ) + abs( a22 ) bn = abs( b11 ) + abs( b22 ) wabs = abs( wr ) + abs( wi ) if( s1*an>wabs*bn ) then cq = cz*b11 sqr = szr*b22 sqi = -szi*b22 else a1r = cz*a11 + szr*a12 a1i = szi*a12 a2r = cz*a21 + szr*a22 a2i = szi*a22 cq = stdlib${ii}$_${ri}$lapy2( a1r, a1i ) if( cq<=safmin ) then cq = zero sqr = one sqi = zero else tempr = a1r / cq tempi = a1i / cq sqr = tempr*a2r + tempi*a2i sqi = tempi*a2r - tempr*a2i end if end if t1 = stdlib${ii}$_${ri}$lapy3( cq, sqr, sqi ) cq = cq / t1 sqr = sqr / t1 sqi = sqi / t1 ! compute diagonal elements of qbz tempr = sqr*szr - sqi*szi tempi = sqr*szi + sqi*szr b1r = cq*cz*b11 + tempr*b22 b1i = tempi*b22 b1a = stdlib${ii}$_${ri}$lapy2( b1r, b1i ) b2r = cq*cz*b22 + tempr*b11 b2i = -tempi*b11 b2a = stdlib${ii}$_${ri}$lapy2( b2r, b2i ) ! normalize so beta > 0, and im( alpha1 ) > 0 beta( ilast-1 ) = b1a beta( ilast ) = b2a alphar( ilast-1 ) = ( wr*b1a )*s1inv alphai( ilast-1 ) = ( wi*b1a )*s1inv alphar( ilast ) = ( wr*b2a )*s1inv alphai( ilast ) = -( wi*b2a )*s1inv ! step 3: go to next block -- exit if finished. ilast = ifirst - 1_${ik}$ if( ilastilast )ifrstm = ilo end if go to 350 else ! usual case: 3x3 or larger block, using francis implicit ! double-shift ! 2 ! eigenvalue equation is w - c w + d = 0, ! -1 2 -1 ! so compute 1st column of (a b ) - c a b + d ! using the formula in qzit (from eispack) ! we assume that the block is at least 3x3 ad11 = ( ascale*h( ilast-1, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad21 = ( ascale*h( ilast, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad12 = ( ascale*h( ilast-1, ilast ) ) /( bscale*t( ilast, ilast ) ) ad22 = ( ascale*h( ilast, ilast ) ) /( bscale*t( ilast, ilast ) ) u12 = t( ilast-1, ilast ) / t( ilast, ilast ) ad11l = ( ascale*h( ifirst, ifirst ) ) /( bscale*t( ifirst, ifirst ) ) ad21l = ( ascale*h( ifirst+1, ifirst ) ) /( bscale*t( ifirst, ifirst ) ) ad12l = ( ascale*h( ifirst, ifirst+1 ) ) /( bscale*t( ifirst+1, ifirst+1 ) ) ad22l = ( ascale*h( ifirst+1, ifirst+1 ) ) /( bscale*t( ifirst+1, ifirst+1 ) ) ad32l = ( ascale*h( ifirst+2, ifirst+1 ) ) /( bscale*t( ifirst+1, ifirst+1 ) ) u12l = t( ifirst, ifirst+1 ) / t( ifirst+1, ifirst+1 ) v( 1_${ik}$ ) = ( ad11-ad11l )*( ad22-ad11l ) - ad12*ad21 +ad21*u12*ad11l + ( ad12l-& ad11l*u12l )*ad21l v( 2_${ik}$ ) = ( ( ad22l-ad11l )-ad21l*u12l-( ad11-ad11l )-( ad22-ad11l )+ad21*u12 )& *ad21l v( 3_${ik}$ ) = ad32l*ad21l istart = ifirst call stdlib${ii}$_${ri}$larfg( 3_${ik}$, v( 1_${ik}$ ), v( 2_${ik}$ ), 1_${ik}$, tau ) v( 1_${ik}$ ) = one ! sweep loop_290: do j = istart, ilast - 2 ! all but last elements: use 3x3 householder transforms. ! zero (j-1)st column of a if( j>istart ) then v( 1_${ik}$ ) = h( j, j-1 ) v( 2_${ik}$ ) = h( j+1, j-1 ) v( 3_${ik}$ ) = h( j+2, j-1 ) call stdlib${ii}$_${ri}$larfg( 3_${ik}$, h( j, j-1 ), v( 2_${ik}$ ), 1_${ik}$, tau ) v( 1_${ik}$ ) = one h( j+1, j-1 ) = zero h( j+2, j-1 ) = zero end if do jc = j, ilastm temp = tau*( h( j, jc )+v( 2_${ik}$ )*h( j+1, jc )+v( 3_${ik}$ )*h( j+2, jc ) ) h( j, jc ) = h( j, jc ) - temp h( j+1, jc ) = h( j+1, jc ) - temp*v( 2_${ik}$ ) h( j+2, jc ) = h( j+2, jc ) - temp*v( 3_${ik}$ ) temp2 = tau*( t( j, jc )+v( 2_${ik}$ )*t( j+1, jc )+v( 3_${ik}$ )*t( j+2, jc ) ) t( j, jc ) = t( j, jc ) - temp2 t( j+1, jc ) = t( j+1, jc ) - temp2*v( 2_${ik}$ ) t( j+2, jc ) = t( j+2, jc ) - temp2*v( 3_${ik}$ ) end do if( ilq ) then do jr = 1, n temp = tau*( q( jr, j )+v( 2_${ik}$ )*q( jr, j+1 )+v( 3_${ik}$ )*q( jr, j+2 ) ) q( jr, j ) = q( jr, j ) - temp q( jr, j+1 ) = q( jr, j+1 ) - temp*v( 2_${ik}$ ) q( jr, j+2 ) = q( jr, j+2 ) - temp*v( 3_${ik}$ ) end do end if ! zero j-th column of b (see dlagbc for details) ! swap rows to pivot ${ik}$ivt = .false. temp = max( abs( t( j+1, j+1 ) ), abs( t( j+1, j+2 ) ) ) temp2 = max( abs( t( j+2, j+1 ) ), abs( t( j+2, j+2 ) ) ) if( max( temp, temp2 )=temp2 ) then w11 = t( j+1, j+1 ) w21 = t( j+2, j+1 ) w12 = t( j+1, j+2 ) w22 = t( j+2, j+2 ) u1 = t( j+1, j ) u2 = t( j+2, j ) else w21 = t( j+1, j+1 ) w11 = t( j+2, j+1 ) w22 = t( j+1, j+2 ) w12 = t( j+2, j+2 ) u2 = t( j+1, j ) u1 = t( j+2, j ) end if ! swap columns if nec. if( abs( w12 )>abs( w11 ) ) then ${ik}$ivt = .true. temp = w12 temp2 = w22 w12 = w11 w22 = w21 w11 = temp w21 = temp2 end if ! lu-factor temp = w21 / w11 u2 = u2 - temp*u1 w22 = w22 - temp*w12 w21 = zero ! compute scale scale = one if( abs( w22 )n .or. ihisafmin ) then signbc = conjg( t( j, j ) / absb ) t( j, j ) = absb if( ilschr ) then call stdlib${ii}$_cscal( j-1, signbc, t( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_cscal( j, signbc, h( 1_${ik}$, j ), 1_${ik}$ ) else call stdlib${ii}$_cscal( 1_${ik}$, signbc, h( j, j ), 1_${ik}$ ) end if if( ilz )call stdlib${ii}$_cscal( n, signbc, z( 1_${ik}$, j ), 1_${ik}$ ) else t( j, j ) = czero end if alpha( j ) = h( j, j ) beta( j ) = t( j, j ) end do ! if ihi < ilo, skip qz steps if( ihimaxit )go to 180 ! split the matrix if possible. ! two tests: ! 1: h(j,j-1)=0 or j=ilo ! 2: t(j,j)=0 ! special case: j=ilast if( ilast==ilo ) then go to 60 else if( abs1( h( ilast, ilast-1 ) )<=max( safmin, ulp*(abs1( h( ilast, ilast ) ) + & abs1( h( ilast-1, ilast-1 )) ) ) ) then h( ilast, ilast-1 ) = czero go to 60 end if end if if( abs( t( ilast, ilast ) )<=max( safmin, ulp*(abs( t( ilast - 1_${ik}$, ilast ) ) + abs( & t( ilast-1, ilast-1 )) ) ) ) then t( ilast, ilast ) = czero go to 50 end if ! general case: j ilo )temp = temp + abs ( t( j - 1_${ik}$, j ) ) if( abs( t( j, j ) )=btol ) then if( jch+1>=ilast ) then go to 60 else ifirst = jch + 1_${ik}$ go to 70 end if end if t( jch+1, jch+1 ) = czero end do go to 50 else ! only test 2 passed -- chase the zero to t(ilast,ilast) ! then process as in the case t(ilast,ilast)=0 do jch = j, ilast - 1 ctemp = t( jch, jch+1 ) call stdlib${ii}$_clartg( ctemp, t( jch+1, jch+1 ), c, s,t( jch, jch+1 ) ) t( jch+1, jch+1 ) = czero if( jchsafmin ) then signbc = conjg( t( ilast, ilast ) / absb ) t( ilast, ilast ) = absb if( ilschr ) then call stdlib${ii}$_cscal( ilast-ifrstm, signbc, t( ifrstm, ilast ), 1_${ik}$ ) call stdlib${ii}$_cscal( ilast+1-ifrstm, signbc, h( ifrstm, ilast ),1_${ik}$ ) else call stdlib${ii}$_cscal( 1_${ik}$, signbc, h( ilast, ilast ), 1_${ik}$ ) end if if( ilz )call stdlib${ii}$_cscal( n, signbc, z( 1_${ik}$, ilast ), 1_${ik}$ ) else t( ilast, ilast ) = czero end if alpha( ilast ) = h( ilast, ilast ) beta( ilast ) = t( ilast, ilast ) ! go to next block -- exit if finished. ilast = ilast - 1_${ik}$ if( ilastilast )ifrstm = ilo end if go to 160 ! qz step ! this iteration only involves rows/columns ifirst:ilast. we ! assume ifirst < ilast, and that the diagonal of b is non-zero. 70 continue iiter = iiter + 1_${ik}$ if( .not.ilschr ) then ifrstm = ifirst end if ! compute the shift. ! at this point, ifirst < ilast, and the diagonal elements of ! t(ifirst:ilast,ifirst,ilast) are larger than btol (in ! magnitude) if( ( iiter / 10_${ik}$ )*10_${ik}$/=iiter ) then ! the wilkinson shift (aep p.512_sp), i.e., the eigenvalue of ! the bottom-right 2x2 block of a inv(b) which is nearest to ! the bottom-right element. ! we factor b as u*d, where u has unit diagonals, and ! compute (a*inv(d))*inv(u). u12 = ( bscale*t( ilast-1, ilast ) ) /( bscale*t( ilast, ilast ) ) ad11 = ( ascale*h( ilast-1, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad21 = ( ascale*h( ilast, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad12 = ( ascale*h( ilast-1, ilast ) ) /( bscale*t( ilast, ilast ) ) ad22 = ( ascale*h( ilast, ilast ) ) /( bscale*t( ilast, ilast ) ) abi22 = ad22 - u12*ad21 abi12 = ad12 - u12*ad11 shift = abi22 ctemp = sqrt( abi12 )*sqrt( ad21 ) temp = abs1( ctemp ) if( ctemp/=zero ) then x = half*( ad11-shift ) temp2 = abs1( x ) temp = max( temp, abs1( x ) ) y = temp*sqrt( ( x / temp )**2_${ik}$+( ctemp / temp )**2_${ik}$ ) if( temp2>zero ) then if( real( x / temp2,KIND=sp)*real( y,KIND=sp)+aimag( x / temp2 )*aimag( y )& safmin ) & then eshift = eshift + ( ascale*h( ilast,ilast ) )/( bscale*t( ilast, ilast ) ) else eshift = eshift + ( ascale*h( ilast,ilast-1 ) )/( bscale*t( ilast-1, ilast-1 )& ) end if shift = eshift end if ! now check for two consecutive small subdiagonals. do j = ilast - 1, ifirst + 1, -1 istart = j ctemp = ascale*h( j, j ) - shift*( bscale*t( j, j ) ) temp = abs1( ctemp ) temp2 = ascale*abs1( h( j+1, j ) ) tempr = max( temp, temp2 ) if( tempristart ) then ctemp = h( j, j-1 ) call stdlib${ii}$_clartg( ctemp, h( j+1, j-1 ), c, s, h( j, j-1 ) ) h( j+1, j-1 ) = czero end if do jc = j, ilastm ctemp = c*h( j, jc ) + s*h( j+1, jc ) h( j+1, jc ) = -conjg( s )*h( j, jc ) + c*h( j+1, jc ) h( j, jc ) = ctemp ctemp2 = c*t( j, jc ) + s*t( j+1, jc ) t( j+1, jc ) = -conjg( s )*t( j, jc ) + c*t( j+1, jc ) t( j, jc ) = ctemp2 end do if( ilq ) then do jr = 1, n ctemp = c*q( jr, j ) + conjg( s )*q( jr, j+1 ) q( jr, j+1 ) = -s*q( jr, j ) + c*q( jr, j+1 ) q( jr, j ) = ctemp end do end if ctemp = t( j+1, j+1 ) call stdlib${ii}$_clartg( ctemp, t( j+1, j ), c, s, t( j+1, j+1 ) ) t( j+1, j ) = czero do jr = ifrstm, min( j+2, ilast ) ctemp = c*h( jr, j+1 ) + s*h( jr, j ) h( jr, j ) = -conjg( s )*h( jr, j+1 ) + c*h( jr, j ) h( jr, j+1 ) = ctemp end do do jr = ifrstm, j ctemp = c*t( jr, j+1 ) + s*t( jr, j ) t( jr, j ) = -conjg( s )*t( jr, j+1 ) + c*t( jr, j ) t( jr, j+1 ) = ctemp end do if( ilz ) then do jr = 1, n ctemp = c*z( jr, j+1 ) + s*z( jr, j ) z( jr, j ) = -conjg( s )*z( jr, j+1 ) + c*z( jr, j ) z( jr, j+1 ) = ctemp end do end if end do loop_150 160 continue end do loop_170 ! drop-through = non-convergence 180 continue info = ilast go to 210 ! successful completion of all qz steps 190 continue ! set eigenvalues 1:ilo-1 do j = 1, ilo - 1 absb = abs( t( j, j ) ) if( absb>safmin ) then signbc = conjg( t( j, j ) / absb ) t( j, j ) = absb if( ilschr ) then call stdlib${ii}$_cscal( j-1, signbc, t( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_cscal( j, signbc, h( 1_${ik}$, j ), 1_${ik}$ ) else call stdlib${ii}$_cscal( 1_${ik}$, signbc, h( j, j ), 1_${ik}$ ) end if if( ilz )call stdlib${ii}$_cscal( n, signbc, z( 1_${ik}$, j ), 1_${ik}$ ) else t( j, j ) = czero end if alpha( j ) = h( j, j ) beta( j ) = t( j, j ) end do ! normal termination info = 0_${ik}$ ! exit (other than argument error) -- return optimal workspace size 210 continue work( 1_${ik}$ ) = cmplx( n,KIND=sp) return end subroutine stdlib${ii}$_chgeqz module subroutine stdlib${ii}$_zhgeqz( job, compq, compz, n, ilo, ihi, h, ldh, t, ldt,alpha, beta, q, ldq,& !! ZHGEQZ computes the eigenvalues of a complex matrix pair (H,T), !! where H is an upper Hessenberg matrix and T is upper triangular, !! using the single-shift QZ method. !! Matrix pairs of this type are produced by the reduction to !! generalized upper Hessenberg form of a complex matrix pair (A,B): !! A = Q1*H*Z1**H, B = Q1*T*Z1**H, !! as computed by ZGGHRD. !! If JOB='S', then the Hessenberg-triangular pair (H,T) is !! also reduced to generalized Schur form, !! H = Q*S*Z**H, T = Q*P*Z**H, !! where Q and Z are unitary matrices and S and P are upper triangular. !! Optionally, the unitary matrix Q from the generalized Schur !! factorization may be postmultiplied into an input matrix Q1, and the !! unitary matrix Z may be postmultiplied into an input matrix Z1. !! If Q1 and Z1 are the unitary matrices from ZGGHRD that reduced !! the matrix pair (A,B) to generalized Hessenberg form, then the output !! matrices Q1*Q and Z1*Z are the unitary factors from the generalized !! Schur factorization of (A,B): !! A = (Q1*Q)*S*(Z1*Z)**H, B = (Q1*Q)*P*(Z1*Z)**H. !! To avoid overflow, eigenvalues of the matrix pair (H,T) !! (equivalently, of (A,B)) are computed as a pair of complex values !! (alpha,beta). If beta is nonzero, lambda = alpha / beta is an !! eigenvalue of the generalized nonsymmetric eigenvalue problem (GNEP) !! A*x = lambda*B*x !! and if alpha is nonzero, mu = beta / alpha is an eigenvalue of the !! alternate form of the GNEP !! mu*A*y = B*y. !! The values of alpha and beta for the i-th eigenvalue can be read !! directly from the generalized Schur form: alpha = S(i,i), !! beta = P(i,i). !! Ref: C.B. Moler !! Eigenvalue Problems", SIAM J. Numer. Anal., 10(1973), !! pp. 241--256. z, ldz, work, lwork,rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compq, compz, job integer(${ik}$), intent(in) :: ihi, ilo, ldh, ldq, ldt, ldz, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments real(dp), intent(out) :: rwork(*) complex(dp), intent(out) :: alpha(*), beta(*), work(*) complex(dp), intent(inout) :: h(ldh,*), q(ldq,*), t(ldt,*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: ilazr2, ilazro, ilq, ilschr, ilz, lquery integer(${ik}$) :: icompq, icompz, ifirst, ifrstm, iiter, ilast, ilastm, in, ischur, & istart, j, jc, jch, jiter, jr, maxit real(dp) :: absb, anorm, ascale, atol, bnorm, bscale, btol, c, safmin, temp, temp2, & tempr, ulp complex(dp) :: abi22, ad11, ad12, ad21, ad22, ctemp, ctemp2, ctemp3, eshift, s, shift, & signbc, u12, x, abi12, y ! Intrinsic Functions ! Statement Functions real(dp) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=dp) ) + abs( aimag( x ) ) ! Executable Statements ! decode job, compq, compz if( stdlib_lsame( job, 'E' ) ) then ilschr = .false. ischur = 1_${ik}$ else if( stdlib_lsame( job, 'S' ) ) then ilschr = .true. ischur = 2_${ik}$ else ilschr = .true. ischur = 0_${ik}$ end if if( stdlib_lsame( compq, 'N' ) ) then ilq = .false. icompq = 1_${ik}$ else if( stdlib_lsame( compq, 'V' ) ) then ilq = .true. icompq = 2_${ik}$ else if( stdlib_lsame( compq, 'I' ) ) then ilq = .true. icompq = 3_${ik}$ else ilq = .true. icompq = 0_${ik}$ end if if( stdlib_lsame( compz, 'N' ) ) then ilz = .false. icompz = 1_${ik}$ else if( stdlib_lsame( compz, 'V' ) ) then ilz = .true. icompz = 2_${ik}$ else if( stdlib_lsame( compz, 'I' ) ) then ilz = .true. icompz = 3_${ik}$ else ilz = .true. icompz = 0_${ik}$ end if ! check argument values info = 0_${ik}$ work( 1_${ik}$ ) = max( 1_${ik}$, n ) lquery = ( lwork==-1_${ik}$ ) if( ischur==0_${ik}$ ) then info = -1_${ik}$ else if( icompq==0_${ik}$ ) then info = -2_${ik}$ else if( icompz==0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ilo<1_${ik}$ ) then info = -5_${ik}$ else if( ihi>n .or. ihisafmin ) then signbc = conjg( t( j, j ) / absb ) t( j, j ) = absb if( ilschr ) then call stdlib${ii}$_zscal( j-1, signbc, t( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_zscal( j, signbc, h( 1_${ik}$, j ), 1_${ik}$ ) else call stdlib${ii}$_zscal( 1_${ik}$, signbc, h( j, j ), 1_${ik}$ ) end if if( ilz )call stdlib${ii}$_zscal( n, signbc, z( 1_${ik}$, j ), 1_${ik}$ ) else t( j, j ) = czero end if alpha( j ) = h( j, j ) beta( j ) = t( j, j ) end do ! if ihi < ilo, skip qz steps if( ihimaxit )go to 180 ! split the matrix if possible. ! two tests: ! 1: h(j,j-1)=0 or j=ilo ! 2: t(j,j)=0 ! special case: j=ilast if( ilast==ilo ) then go to 60 else if( abs1( h( ilast, ilast-1 ) )<=max( safmin, ulp*(abs1( h( ilast, ilast ) ) + & abs1( h( ilast-1, ilast-1 )) ) ) ) then h( ilast, ilast-1 ) = czero go to 60 end if end if if( abs( t( ilast, ilast ) )<=max( safmin, ulp*(abs( t( ilast - 1_${ik}$, ilast ) ) + abs( & t( ilast-1, ilast-1 )) ) ) ) then t( ilast, ilast ) = czero go to 50 end if ! general case: j ilo )temp = temp + abs ( t( j - 1_${ik}$, j ) ) if( abs( t( j, j ) )=btol ) then if( jch+1>=ilast ) then go to 60 else ifirst = jch + 1_${ik}$ go to 70 end if end if t( jch+1, jch+1 ) = czero end do go to 50 else ! only test 2 passed -- chase the zero to t(ilast,ilast) ! then process as in the case t(ilast,ilast)=0 do jch = j, ilast - 1 ctemp = t( jch, jch+1 ) call stdlib${ii}$_zlartg( ctemp, t( jch+1, jch+1 ), c, s,t( jch, jch+1 ) ) t( jch+1, jch+1 ) = czero if( jchsafmin ) then signbc = conjg( t( ilast, ilast ) / absb ) t( ilast, ilast ) = absb if( ilschr ) then call stdlib${ii}$_zscal( ilast-ifrstm, signbc, t( ifrstm, ilast ), 1_${ik}$ ) call stdlib${ii}$_zscal( ilast+1-ifrstm, signbc, h( ifrstm, ilast ),1_${ik}$ ) else call stdlib${ii}$_zscal( 1_${ik}$, signbc, h( ilast, ilast ), 1_${ik}$ ) end if if( ilz )call stdlib${ii}$_zscal( n, signbc, z( 1_${ik}$, ilast ), 1_${ik}$ ) else t( ilast, ilast ) = czero end if alpha( ilast ) = h( ilast, ilast ) beta( ilast ) = t( ilast, ilast ) ! go to next block -- exit if finished. ilast = ilast - 1_${ik}$ if( ilastilast )ifrstm = ilo end if go to 160 ! qz step ! this iteration only involves rows/columns ifirst:ilast. we ! assume ifirst < ilast, and that the diagonal of b is non-zero. 70 continue iiter = iiter + 1_${ik}$ if( .not.ilschr ) then ifrstm = ifirst end if ! compute the shift. ! at this point, ifirst < ilast, and the diagonal elements of ! t(ifirst:ilast,ifirst,ilast) are larger than btol (in ! magnitude) if( ( iiter / 10_${ik}$ )*10_${ik}$/=iiter ) then ! the wilkinson shift (aep p.512_dp), i.e., the eigenvalue of ! the bottom-right 2x2 block of a inv(b) which is nearest to ! the bottom-right element. ! we factor b as u*d, where u has unit diagonals, and ! compute (a*inv(d))*inv(u). u12 = ( bscale*t( ilast-1, ilast ) ) /( bscale*t( ilast, ilast ) ) ad11 = ( ascale*h( ilast-1, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad21 = ( ascale*h( ilast, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad12 = ( ascale*h( ilast-1, ilast ) ) /( bscale*t( ilast, ilast ) ) ad22 = ( ascale*h( ilast, ilast ) ) /( bscale*t( ilast, ilast ) ) abi22 = ad22 - u12*ad21 abi12 = ad12 - u12*ad11 shift = abi22 ctemp = sqrt( abi12 )*sqrt( ad21 ) temp = abs1( ctemp ) if( ctemp/=zero ) then x = half*( ad11-shift ) temp2 = abs1( x ) temp = max( temp, abs1( x ) ) y = temp*sqrt( ( x / temp )**2_${ik}$+( ctemp / temp )**2_${ik}$ ) if( temp2>zero ) then if( real( x / temp2,KIND=dp)*real( y,KIND=dp)+aimag( x / temp2 )*aimag( y )& safmin ) & then eshift = eshift + ( ascale*h( ilast,ilast ) )/( bscale*t( ilast, ilast ) ) else eshift = eshift + ( ascale*h( ilast,ilast-1 ) )/( bscale*t( ilast-1, ilast-1 )& ) end if shift = eshift end if ! now check for two consecutive small subdiagonals. do j = ilast - 1, ifirst + 1, -1 istart = j ctemp = ascale*h( j, j ) - shift*( bscale*t( j, j ) ) temp = abs1( ctemp ) temp2 = ascale*abs1( h( j+1, j ) ) tempr = max( temp, temp2 ) if( tempristart ) then ctemp = h( j, j-1 ) call stdlib${ii}$_zlartg( ctemp, h( j+1, j-1 ), c, s, h( j, j-1 ) ) h( j+1, j-1 ) = czero end if do jc = j, ilastm ctemp = c*h( j, jc ) + s*h( j+1, jc ) h( j+1, jc ) = -conjg( s )*h( j, jc ) + c*h( j+1, jc ) h( j, jc ) = ctemp ctemp2 = c*t( j, jc ) + s*t( j+1, jc ) t( j+1, jc ) = -conjg( s )*t( j, jc ) + c*t( j+1, jc ) t( j, jc ) = ctemp2 end do if( ilq ) then do jr = 1, n ctemp = c*q( jr, j ) + conjg( s )*q( jr, j+1 ) q( jr, j+1 ) = -s*q( jr, j ) + c*q( jr, j+1 ) q( jr, j ) = ctemp end do end if ctemp = t( j+1, j+1 ) call stdlib${ii}$_zlartg( ctemp, t( j+1, j ), c, s, t( j+1, j+1 ) ) t( j+1, j ) = czero do jr = ifrstm, min( j+2, ilast ) ctemp = c*h( jr, j+1 ) + s*h( jr, j ) h( jr, j ) = -conjg( s )*h( jr, j+1 ) + c*h( jr, j ) h( jr, j+1 ) = ctemp end do do jr = ifrstm, j ctemp = c*t( jr, j+1 ) + s*t( jr, j ) t( jr, j ) = -conjg( s )*t( jr, j+1 ) + c*t( jr, j ) t( jr, j+1 ) = ctemp end do if( ilz ) then do jr = 1, n ctemp = c*z( jr, j+1 ) + s*z( jr, j ) z( jr, j ) = -conjg( s )*z( jr, j+1 ) + c*z( jr, j ) z( jr, j+1 ) = ctemp end do end if end do loop_150 160 continue end do loop_170 ! drop-through = non-convergence 180 continue info = ilast go to 210 ! successful completion of all qz steps 190 continue ! set eigenvalues 1:ilo-1 do j = 1, ilo - 1 absb = abs( t( j, j ) ) if( absb>safmin ) then signbc = conjg( t( j, j ) / absb ) t( j, j ) = absb if( ilschr ) then call stdlib${ii}$_zscal( j-1, signbc, t( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_zscal( j, signbc, h( 1_${ik}$, j ), 1_${ik}$ ) else call stdlib${ii}$_zscal( 1_${ik}$, signbc, h( j, j ), 1_${ik}$ ) end if if( ilz )call stdlib${ii}$_zscal( n, signbc, z( 1_${ik}$, j ), 1_${ik}$ ) else t( j, j ) = czero end if alpha( j ) = h( j, j ) beta( j ) = t( j, j ) end do ! normal termination info = 0_${ik}$ ! exit (other than argument error) -- return optimal workspace size 210 continue work( 1_${ik}$ ) = cmplx( n,KIND=dp) return end subroutine stdlib${ii}$_zhgeqz #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hgeqz( job, compq, compz, n, ilo, ihi, h, ldh, t, ldt,alpha, beta, q, ldq,& !! ZHGEQZ: computes the eigenvalues of a complex matrix pair (H,T), !! where H is an upper Hessenberg matrix and T is upper triangular, !! using the single-shift QZ method. !! Matrix pairs of this type are produced by the reduction to !! generalized upper Hessenberg form of a complex matrix pair (A,B): !! A = Q1*H*Z1**H, B = Q1*T*Z1**H, !! as computed by ZGGHRD. !! If JOB='S', then the Hessenberg-triangular pair (H,T) is !! also reduced to generalized Schur form, !! H = Q*S*Z**H, T = Q*P*Z**H, !! where Q and Z are unitary matrices and S and P are upper triangular. !! Optionally, the unitary matrix Q from the generalized Schur !! factorization may be postmultiplied into an input matrix Q1, and the !! unitary matrix Z may be postmultiplied into an input matrix Z1. !! If Q1 and Z1 are the unitary matrices from ZGGHRD that reduced !! the matrix pair (A,B) to generalized Hessenberg form, then the output !! matrices Q1*Q and Z1*Z are the unitary factors from the generalized !! Schur factorization of (A,B): !! A = (Q1*Q)*S*(Z1*Z)**H, B = (Q1*Q)*P*(Z1*Z)**H. !! To avoid overflow, eigenvalues of the matrix pair (H,T) !! (equivalently, of (A,B)) are computed as a pair of complex values !! (alpha,beta). If beta is nonzero, lambda = alpha / beta is an !! eigenvalue of the generalized nonsymmetric eigenvalue problem (GNEP) !! A*x = lambda*B*x !! and if alpha is nonzero, mu = beta / alpha is an eigenvalue of the !! alternate form of the GNEP !! mu*A*y = B*y. !! The values of alpha and beta for the i-th eigenvalue can be read !! directly from the generalized Schur form: alpha = S(i,i), !! beta = P(i,i). !! Ref: C.B. Moler !! Eigenvalue Problems", SIAM J. Numer. Anal., 10(1973), !! pp. 241--256. z, ldz, work, lwork,rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compq, compz, job integer(${ik}$), intent(in) :: ihi, ilo, ldh, ldq, ldt, ldz, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(out) :: alpha(*), beta(*), work(*) complex(${ck}$), intent(inout) :: h(ldh,*), q(ldq,*), t(ldt,*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: ilazr2, ilazro, ilq, ilschr, ilz, lquery integer(${ik}$) :: icompq, icompz, ifirst, ifrstm, iiter, ilast, ilastm, in, ischur, & istart, j, jc, jch, jiter, jr, maxit real(${ck}$) :: absb, anorm, ascale, atol, bnorm, bscale, btol, c, safmin, temp, temp2, & tempr, ulp complex(${ck}$) :: abi22, ad11, ad12, ad21, ad22, ctemp, ctemp2, ctemp3, eshift, s, shift, & signbc, u12, x, abi12, y ! Intrinsic Functions ! Statement Functions real(${ck}$) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=${ck}$) ) + abs( aimag( x ) ) ! Executable Statements ! decode job, compq, compz if( stdlib_lsame( job, 'E' ) ) then ilschr = .false. ischur = 1_${ik}$ else if( stdlib_lsame( job, 'S' ) ) then ilschr = .true. ischur = 2_${ik}$ else ilschr = .true. ischur = 0_${ik}$ end if if( stdlib_lsame( compq, 'N' ) ) then ilq = .false. icompq = 1_${ik}$ else if( stdlib_lsame( compq, 'V' ) ) then ilq = .true. icompq = 2_${ik}$ else if( stdlib_lsame( compq, 'I' ) ) then ilq = .true. icompq = 3_${ik}$ else ilq = .true. icompq = 0_${ik}$ end if if( stdlib_lsame( compz, 'N' ) ) then ilz = .false. icompz = 1_${ik}$ else if( stdlib_lsame( compz, 'V' ) ) then ilz = .true. icompz = 2_${ik}$ else if( stdlib_lsame( compz, 'I' ) ) then ilz = .true. icompz = 3_${ik}$ else ilz = .true. icompz = 0_${ik}$ end if ! check argument values info = 0_${ik}$ work( 1_${ik}$ ) = max( 1_${ik}$, n ) lquery = ( lwork==-1_${ik}$ ) if( ischur==0_${ik}$ ) then info = -1_${ik}$ else if( icompq==0_${ik}$ ) then info = -2_${ik}$ else if( icompz==0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ilo<1_${ik}$ ) then info = -5_${ik}$ else if( ihi>n .or. ihisafmin ) then signbc = conjg( t( j, j ) / absb ) t( j, j ) = absb if( ilschr ) then call stdlib${ii}$_${ci}$scal( j-1, signbc, t( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( j, signbc, h( 1_${ik}$, j ), 1_${ik}$ ) else call stdlib${ii}$_${ci}$scal( 1_${ik}$, signbc, h( j, j ), 1_${ik}$ ) end if if( ilz )call stdlib${ii}$_${ci}$scal( n, signbc, z( 1_${ik}$, j ), 1_${ik}$ ) else t( j, j ) = czero end if alpha( j ) = h( j, j ) beta( j ) = t( j, j ) end do ! if ihi < ilo, skip qz steps if( ihimaxit )go to 180 ! split the matrix if possible. ! two tests: ! 1: h(j,j-1)=0 or j=ilo ! 2: t(j,j)=0 ! special case: j=ilast if( ilast==ilo ) then go to 60 else if( abs1( h( ilast, ilast-1 ) )<=max( safmin, ulp*(abs1( h( ilast, ilast ) ) + & abs1( h( ilast-1, ilast-1 )) ) ) ) then h( ilast, ilast-1 ) = czero go to 60 end if end if if( abs( t( ilast, ilast ) )<=max( safmin, ulp*(abs( t( ilast - 1_${ik}$, ilast ) ) + abs( & t( ilast-1, ilast-1 )) ) ) ) then t( ilast, ilast ) = czero go to 50 end if ! general case: j ilo )temp = temp + abs ( t( j - 1_${ik}$, j ) ) if( abs( t( j, j ) )=btol ) then if( jch+1>=ilast ) then go to 60 else ifirst = jch + 1_${ik}$ go to 70 end if end if t( jch+1, jch+1 ) = czero end do go to 50 else ! only test 2 passed -- chase the zero to t(ilast,ilast) ! then process as in the case t(ilast,ilast)=0 do jch = j, ilast - 1 ctemp = t( jch, jch+1 ) call stdlib${ii}$_${ci}$lartg( ctemp, t( jch+1, jch+1 ), c, s,t( jch, jch+1 ) ) t( jch+1, jch+1 ) = czero if( jchsafmin ) then signbc = conjg( t( ilast, ilast ) / absb ) t( ilast, ilast ) = absb if( ilschr ) then call stdlib${ii}$_${ci}$scal( ilast-ifrstm, signbc, t( ifrstm, ilast ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( ilast+1-ifrstm, signbc, h( ifrstm, ilast ),1_${ik}$ ) else call stdlib${ii}$_${ci}$scal( 1_${ik}$, signbc, h( ilast, ilast ), 1_${ik}$ ) end if if( ilz )call stdlib${ii}$_${ci}$scal( n, signbc, z( 1_${ik}$, ilast ), 1_${ik}$ ) else t( ilast, ilast ) = czero end if alpha( ilast ) = h( ilast, ilast ) beta( ilast ) = t( ilast, ilast ) ! go to next block -- exit if finished. ilast = ilast - 1_${ik}$ if( ilastilast )ifrstm = ilo end if go to 160 ! qz step ! this iteration only involves rows/columns ifirst:ilast. we ! assume ifirst < ilast, and that the diagonal of b is non-zero. 70 continue iiter = iiter + 1_${ik}$ if( .not.ilschr ) then ifrstm = ifirst end if ! compute the shift. ! at this point, ifirst < ilast, and the diagonal elements of ! t(ifirst:ilast,ifirst,ilast) are larger than btol (in ! magnitude) if( ( iiter / 10_${ik}$ )*10_${ik}$/=iiter ) then ! the wilkinson shift (aep p.512_${ck}$), i.e., the eigenvalue of ! the bottom-right 2x2 block of a inv(b) which is nearest to ! the bottom-right element. ! we factor b as u*d, where u has unit diagonals, and ! compute (a*inv(d))*inv(u). u12 = ( bscale*t( ilast-1, ilast ) ) /( bscale*t( ilast, ilast ) ) ad11 = ( ascale*h( ilast-1, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad21 = ( ascale*h( ilast, ilast-1 ) ) /( bscale*t( ilast-1, ilast-1 ) ) ad12 = ( ascale*h( ilast-1, ilast ) ) /( bscale*t( ilast, ilast ) ) ad22 = ( ascale*h( ilast, ilast ) ) /( bscale*t( ilast, ilast ) ) abi22 = ad22 - u12*ad21 abi12 = ad12 - u12*ad11 shift = abi22 ctemp = sqrt( abi12 )*sqrt( ad21 ) temp = abs1( ctemp ) if( ctemp/=zero ) then x = half*( ad11-shift ) temp2 = abs1( x ) temp = max( temp, abs1( x ) ) y = temp*sqrt( ( x / temp )**2_${ik}$+( ctemp / temp )**2_${ik}$ ) if( temp2>zero ) then if( real( x / temp2,KIND=${ck}$)*real( y,KIND=${ck}$)+aimag( x / temp2 )*aimag( y )& safmin ) & then eshift = eshift + ( ascale*h( ilast,ilast ) )/( bscale*t( ilast, ilast ) ) else eshift = eshift + ( ascale*h( ilast,ilast-1 ) )/( bscale*t( ilast-1, ilast-1 )& ) end if shift = eshift end if ! now check for two consecutive small subdiagonals. do j = ilast - 1, ifirst + 1, -1 istart = j ctemp = ascale*h( j, j ) - shift*( bscale*t( j, j ) ) temp = abs1( ctemp ) temp2 = ascale*abs1( h( j+1, j ) ) tempr = max( temp, temp2 ) if( tempristart ) then ctemp = h( j, j-1 ) call stdlib${ii}$_${ci}$lartg( ctemp, h( j+1, j-1 ), c, s, h( j, j-1 ) ) h( j+1, j-1 ) = czero end if do jc = j, ilastm ctemp = c*h( j, jc ) + s*h( j+1, jc ) h( j+1, jc ) = -conjg( s )*h( j, jc ) + c*h( j+1, jc ) h( j, jc ) = ctemp ctemp2 = c*t( j, jc ) + s*t( j+1, jc ) t( j+1, jc ) = -conjg( s )*t( j, jc ) + c*t( j+1, jc ) t( j, jc ) = ctemp2 end do if( ilq ) then do jr = 1, n ctemp = c*q( jr, j ) + conjg( s )*q( jr, j+1 ) q( jr, j+1 ) = -s*q( jr, j ) + c*q( jr, j+1 ) q( jr, j ) = ctemp end do end if ctemp = t( j+1, j+1 ) call stdlib${ii}$_${ci}$lartg( ctemp, t( j+1, j ), c, s, t( j+1, j+1 ) ) t( j+1, j ) = czero do jr = ifrstm, min( j+2, ilast ) ctemp = c*h( jr, j+1 ) + s*h( jr, j ) h( jr, j ) = -conjg( s )*h( jr, j+1 ) + c*h( jr, j ) h( jr, j+1 ) = ctemp end do do jr = ifrstm, j ctemp = c*t( jr, j+1 ) + s*t( jr, j ) t( jr, j ) = -conjg( s )*t( jr, j+1 ) + c*t( jr, j ) t( jr, j+1 ) = ctemp end do if( ilz ) then do jr = 1, n ctemp = c*z( jr, j+1 ) + s*z( jr, j ) z( jr, j ) = -conjg( s )*z( jr, j+1 ) + c*z( jr, j ) z( jr, j+1 ) = ctemp end do end if end do loop_150 160 continue end do loop_170 ! drop-through = non-convergence 180 continue info = ilast go to 210 ! successful completion of all qz steps 190 continue ! set eigenvalues 1:ilo-1 do j = 1, ilo - 1 absb = abs( t( j, j ) ) if( absb>safmin ) then signbc = conjg( t( j, j ) / absb ) t( j, j ) = absb if( ilschr ) then call stdlib${ii}$_${ci}$scal( j-1, signbc, t( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( j, signbc, h( 1_${ik}$, j ), 1_${ik}$ ) else call stdlib${ii}$_${ci}$scal( 1_${ik}$, signbc, h( j, j ), 1_${ik}$ ) end if if( ilz )call stdlib${ii}$_${ci}$scal( n, signbc, z( 1_${ik}$, j ), 1_${ik}$ ) else t( j, j ) = czero end if alpha( j ) = h( j, j ) beta( j ) = t( j, j ) end do ! normal termination info = 0_${ik}$ ! exit (other than argument error) -- return optimal workspace size 210 continue work( 1_${ik}$ ) = cmplx( n,KIND=${ck}$) return end subroutine stdlib${ii}$_${ci}$hgeqz #:endif #:endfor pure module subroutine stdlib${ii}$_sggbak( job, side, n, ilo, ihi, lscale, rscale, m, v,ldv, info ) !! SGGBAK forms the right or left eigenvectors of a real generalized !! eigenvalue problem A*x = lambda*B*x, by backward transformation on !! the computed eigenvectors of the balanced pair of matrices output by !! SGGBAL. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: job, side integer(${ik}$), intent(in) :: ihi, ilo, ldv, m, n integer(${ik}$), intent(out) :: info ! Array Arguments real(sp), intent(in) :: lscale(*), rscale(*) real(sp), intent(inout) :: v(ldv,*) ! ===================================================================== ! Local Scalars logical(lk) :: leftv, rightv integer(${ik}$) :: i, k ! Intrinsic Functions ! Executable Statements ! test the input parameters rightv = stdlib_lsame( side, 'R' ) leftv = stdlib_lsame( side, 'L' ) info = 0_${ik}$ if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) & .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then info = -1_${ik}$ else if( .not.rightv .and. .not.leftv ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ilo<1_${ik}$ ) then info = -4_${ik}$ else if( n==0_${ik}$ .and. ihi==0_${ik}$ .and. ilo/=1_${ik}$ ) then info = -4_${ik}$ else if( n>0_${ik}$ .and. ( ihimax( 1_${ik}$, n ) ) )then info = -5_${ik}$ else if( n==0_${ik}$ .and. ilo==1_${ik}$ .and. ihi/=0_${ik}$ ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -8_${ik}$ else if( ldv0_${ik}$ .and. ( ihimax( 1_${ik}$, n ) ) )then info = -5_${ik}$ else if( n==0_${ik}$ .and. ilo==1_${ik}$ .and. ihi/=0_${ik}$ ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -8_${ik}$ else if( ldv0_${ik}$ .and. ( ihimax( 1_${ik}$, n ) ) )then info = -5_${ik}$ else if( n==0_${ik}$ .and. ilo==1_${ik}$ .and. ihi/=0_${ik}$ ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -8_${ik}$ else if( ldv0_${ik}$ .and. ( ihimax( 1_${ik}$, n ) ) )then info = -5_${ik}$ else if( n==0_${ik}$ .and. ilo==1_${ik}$ .and. ihi/=0_${ik}$ ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -8_${ik}$ else if( ldv0_${ik}$ .and. ( ihimax( 1_${ik}$, n ) ) )then info = -5_${ik}$ else if( n==0_${ik}$ .and. ilo==1_${ik}$ .and. ihi/=0_${ik}$ ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -8_${ik}$ else if( ldv0_${ik}$ .and. ( ihimax( 1_${ik}$, n ) ) )then info = -5_${ik}$ else if( n==0_${ik}$ .and. ilo==1_${ik}$ .and. ihi/=0_${ik}$ ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -8_${ik}$ else if( ldv0_${ik}$ ) then mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ ) nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ ) else mb = 1_${ik}$ nb = n end if if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$ if( nb>n .or. nb<=m ) nb = n mintsz = m + 5_${ik}$ if ( nb>m .and. n>m ) then if( mod( n - m, nb - m )==0_${ik}$ ) then nblcks = ( n - m ) / ( nb - m ) else nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if ! determine if the workspace size satisfies minimal size if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then lwmin = max( 1_${ik}$, n ) lwopt = max( 1_${ik}$, mb*n ) else lwmin = max( 1_${ik}$, m ) lwopt = max( 1_${ik}$, mb*m ) end if lminws = .false. if( ( tsize=lwmin ) .and. ( & tsize>=mintsz ).and. ( .not.lquery ) ) then if( tsize=n ) ) then lwreq = max( 1_${ik}$, mb*n ) else lwreq = max( 1_${ik}$, mb*m ) end if if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) ) then call stdlib${ii}$_sgelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info ) else call stdlib${ii}$_slaswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info ) end if work( 1_${ik}$ ) = lwreq return end subroutine stdlib${ii}$_sgelq pure module subroutine stdlib${ii}$_dgelq( m, n, a, lda, t, tsize, work, lwork,info ) !! DGELQ computes an LQ factorization of a real M-by-N matrix A: !! A = ( L 0 ) * Q !! where: !! Q is a N-by-N orthogonal matrix; !! L is a lower-triangular M-by-M matrix; !! 0 is a M-by-(N-M) zero matrix, if M < N. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd. -- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, lminws, mint, minw integer(${ik}$) :: mb, nb, mintsz, nblcks, lwmin, lwopt, lwreq ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( tsize==-1_${ik}$ .or. tsize==-2_${ik}$ .or.lwork==-1_${ik}$ .or. lwork==-2_${ik}$ ) mint = .false. minw = .false. if( tsize==-2_${ik}$ .or. lwork==-2_${ik}$ ) then if( tsize/=-1_${ik}$ ) mint = .true. if( lwork/=-1_${ik}$ ) minw = .true. end if ! determine the block size if( min( m, n )>0_${ik}$ ) then mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ ) nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ ) else mb = 1_${ik}$ nb = n end if if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$ if( nb>n .or. nb<=m ) nb = n mintsz = m + 5_${ik}$ if ( nb>m .and. n>m ) then if( mod( n - m, nb - m )==0_${ik}$ ) then nblcks = ( n - m ) / ( nb - m ) else nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if ! determine if the workspace size satisfies minimal size if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then lwmin = max( 1_${ik}$, n ) lwopt = max( 1_${ik}$, mb*n ) else lwmin = max( 1_${ik}$, m ) lwopt = max( 1_${ik}$, mb*m ) end if lminws = .false. if( ( tsize=lwmin ) .and. ( & tsize>=mintsz ).and. ( .not.lquery ) ) then if( tsize=n ) ) then lwreq = max( 1_${ik}$, mb*n ) else lwreq = max( 1_${ik}$, mb*m ) end if if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) ) then call stdlib${ii}$_dgelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info ) else call stdlib${ii}$_dlaswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info ) end if work( 1_${ik}$ ) = lwreq return end subroutine stdlib${ii}$_dgelq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gelq( m, n, a, lda, t, tsize, work, lwork,info ) !! DGELQ: computes an LQ factorization of a real M-by-N matrix A: !! A = ( L 0 ) * Q !! where: !! Q is a N-by-N orthogonal matrix; !! L is a lower-triangular M-by-M matrix; !! 0 is a M-by-(N-M) zero matrix, if M < N. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd. -- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: t(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, lminws, mint, minw integer(${ik}$) :: mb, nb, mintsz, nblcks, lwmin, lwopt, lwreq ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( tsize==-1_${ik}$ .or. tsize==-2_${ik}$ .or.lwork==-1_${ik}$ .or. lwork==-2_${ik}$ ) mint = .false. minw = .false. if( tsize==-2_${ik}$ .or. lwork==-2_${ik}$ ) then if( tsize/=-1_${ik}$ ) mint = .true. if( lwork/=-1_${ik}$ ) minw = .true. end if ! determine the block size if( min( m, n )>0_${ik}$ ) then mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ ) nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ ) else mb = 1_${ik}$ nb = n end if if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$ if( nb>n .or. nb<=m ) nb = n mintsz = m + 5_${ik}$ if ( nb>m .and. n>m ) then if( mod( n - m, nb - m )==0_${ik}$ ) then nblcks = ( n - m ) / ( nb - m ) else nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if ! determine if the workspace size satisfies minimal size if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then lwmin = max( 1_${ik}$, n ) lwopt = max( 1_${ik}$, mb*n ) else lwmin = max( 1_${ik}$, m ) lwopt = max( 1_${ik}$, mb*m ) end if lminws = .false. if( ( tsize=lwmin ) .and. ( & tsize>=mintsz ).and. ( .not.lquery ) ) then if( tsize=n ) ) then lwreq = max( 1_${ik}$, mb*n ) else lwreq = max( 1_${ik}$, mb*m ) end if if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) ) then call stdlib${ii}$_${ri}$gelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info ) else call stdlib${ii}$_${ri}$laswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info ) end if work( 1_${ik}$ ) = lwreq return end subroutine stdlib${ii}$_${ri}$gelq #:endif #:endfor pure module subroutine stdlib${ii}$_cgelq( m, n, a, lda, t, tsize, work, lwork,info ) !! CGELQ computes an LQ factorization of a complex M-by-N matrix A: !! A = ( L 0 ) * Q !! where: !! Q is a N-by-N orthogonal matrix; !! L is a lower-triangular M-by-M matrix; !! 0 is a M-by-(N-M) zero matrix, if M < N. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd. -- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, lminws, mint, minw integer(${ik}$) :: mb, nb, mintsz, nblcks, lwmin, lwopt, lwreq ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( tsize==-1_${ik}$ .or. tsize==-2_${ik}$ .or.lwork==-1_${ik}$ .or. lwork==-2_${ik}$ ) mint = .false. minw = .false. if( tsize==-2_${ik}$ .or. lwork==-2_${ik}$ ) then if( tsize/=-1_${ik}$ ) mint = .true. if( lwork/=-1_${ik}$ ) minw = .true. end if ! determine the block size if( min( m, n )>0_${ik}$ ) then mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ ) nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ ) else mb = 1_${ik}$ nb = n end if if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$ if( nb>n .or. nb<=m ) nb = n mintsz = m + 5_${ik}$ if( nb>m .and. n>m ) then if( mod( n - m, nb - m )==0_${ik}$ ) then nblcks = ( n - m ) / ( nb - m ) else nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if ! determine if the workspace size satisfies minimal size if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then lwmin = max( 1_${ik}$, n ) lwopt = max( 1_${ik}$, mb*n ) else lwmin = max( 1_${ik}$, m ) lwopt = max( 1_${ik}$, mb*m ) end if lminws = .false. if( ( tsize=lwmin ) .and. ( & tsize>=mintsz ).and. ( .not.lquery ) ) then if( tsize=n ) ) then lwreq = max( 1_${ik}$, mb*n ) else lwreq = max( 1_${ik}$, mb*m ) end if if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) ) then call stdlib${ii}$_cgelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info ) else call stdlib${ii}$_claswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info ) end if work( 1_${ik}$ ) = lwreq return end subroutine stdlib${ii}$_cgelq pure module subroutine stdlib${ii}$_zgelq( m, n, a, lda, t, tsize, work, lwork,info ) !! ZGELQ computes an LQ factorization of a complex M-by-N matrix A: !! A = ( L 0 ) * Q !! where: !! Q is a N-by-N orthogonal matrix; !! L is a lower-triangular M-by-M matrix; !! 0 is a M-by-(N-M) zero matrix, if M < N. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd. -- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, lminws, mint, minw integer(${ik}$) :: mb, nb, mintsz, nblcks, lwmin, lwopt, lwreq ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( tsize==-1_${ik}$ .or. tsize==-2_${ik}$ .or.lwork==-1_${ik}$ .or. lwork==-2_${ik}$ ) mint = .false. minw = .false. if( tsize==-2_${ik}$ .or. lwork==-2_${ik}$ ) then if( tsize/=-1_${ik}$ ) mint = .true. if( lwork/=-1_${ik}$ ) minw = .true. end if ! determine the block size if( min( m, n )>0_${ik}$ ) then mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ ) nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ ) else mb = 1_${ik}$ nb = n end if if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$ if( nb>n .or. nb<=m ) nb = n mintsz = m + 5_${ik}$ if ( nb>m .and. n>m ) then if( mod( n - m, nb - m )==0_${ik}$ ) then nblcks = ( n - m ) / ( nb - m ) else nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if ! determine if the workspace size satisfies minimal size if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then lwmin = max( 1_${ik}$, n ) lwopt = max( 1_${ik}$, mb*n ) else lwmin = max( 1_${ik}$, m ) lwopt = max( 1_${ik}$, mb*m ) end if lminws = .false. if( ( tsize=lwmin ) .and. ( & tsize>=mintsz ).and. ( .not.lquery ) ) then if( tsize=n ) ) then lwreq = max( 1_${ik}$, mb*n ) else lwreq = max( 1_${ik}$, mb*m ) end if if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) ) then call stdlib${ii}$_zgelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info ) else call stdlib${ii}$_zlaswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info ) end if work( 1_${ik}$ ) = lwreq return end subroutine stdlib${ii}$_zgelq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gelq( m, n, a, lda, t, tsize, work, lwork,info ) !! ZGELQ: computes an LQ factorization of a complex M-by-N matrix A: !! A = ( L 0 ) * Q !! where: !! Q is a N-by-N orthogonal matrix; !! L is a lower-triangular M-by-M matrix; !! 0 is a M-by-(N-M) zero matrix, if M < N. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd. -- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: t(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, lminws, mint, minw integer(${ik}$) :: mb, nb, mintsz, nblcks, lwmin, lwopt, lwreq ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( tsize==-1_${ik}$ .or. tsize==-2_${ik}$ .or.lwork==-1_${ik}$ .or. lwork==-2_${ik}$ ) mint = .false. minw = .false. if( tsize==-2_${ik}$ .or. lwork==-2_${ik}$ ) then if( tsize/=-1_${ik}$ ) mint = .true. if( lwork/=-1_${ik}$ ) minw = .true. end if ! determine the block size if( min( m, n )>0_${ik}$ ) then mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ ) nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ ) else mb = 1_${ik}$ nb = n end if if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$ if( nb>n .or. nb<=m ) nb = n mintsz = m + 5_${ik}$ if ( nb>m .and. n>m ) then if( mod( n - m, nb - m )==0_${ik}$ ) then nblcks = ( n - m ) / ( nb - m ) else nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if ! determine if the workspace size satisfies minimal size if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then lwmin = max( 1_${ik}$, n ) lwopt = max( 1_${ik}$, mb*n ) else lwmin = max( 1_${ik}$, m ) lwopt = max( 1_${ik}$, mb*m ) end if lminws = .false. if( ( tsize=lwmin ) .and. ( & tsize>=mintsz ).and. ( .not.lquery ) ) then if( tsize=n ) ) then lwreq = max( 1_${ik}$, mb*n ) else lwreq = max( 1_${ik}$, mb*m ) end if if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) ) then call stdlib${ii}$_${ci}$gelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info ) else call stdlib${ii}$_${ci}$laswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info ) end if work( 1_${ik}$ ) = lwreq return end subroutine stdlib${ii}$_${ci}$gelq #:endif #:endfor pure module subroutine stdlib${ii}$_sgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & !! SGEMLQ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product !! of blocked elementary reflectors computed by short wide LQ !! factorization (SGELQ) info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc ! Array Arguments real(sp), intent(in) :: a(lda,*), t(*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: mb, nb, lw, nblcks, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments lquery = lwork==-1_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'T' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) mb = int( t( 2_${ik}$ ),KIND=${ik}$) nb = int( t( 3_${ik}$ ),KIND=${ik}$) if( left ) then lw = n * mb mn = m else lw = m * mb mn = n end if if( ( nb>k ) .and. ( mn>k ) ) then if( mod( mn - k, nb - k ) == 0_${ik}$ ) then nblcks = ( mn - k ) / ( nb - k ) else nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>mn ) then info = -5_${ik}$ else if( lda=max( m, n, & k ) ) ) then call stdlib${ii}$_sgemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info & ) else call stdlib${ii}$_slamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, & lwork, info ) end if work( 1_${ik}$ ) = real( lw,KIND=sp) return end subroutine stdlib${ii}$_sgemlq pure module subroutine stdlib${ii}$_dgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & !! DGEMLQ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product !! of blocked elementary reflectors computed by short wide LQ !! factorization (DGELQ) info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc ! Array Arguments real(dp), intent(in) :: a(lda,*), t(*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: mb, nb, lw, nblcks, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments lquery = lwork==-1_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'T' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) mb = int( t( 2_${ik}$ ),KIND=${ik}$) nb = int( t( 3_${ik}$ ),KIND=${ik}$) if( left ) then lw = n * mb mn = m else lw = m * mb mn = n end if if( ( nb>k ) .and. ( mn>k ) ) then if( mod( mn - k, nb - k ) == 0_${ik}$ ) then nblcks = ( mn - k ) / ( nb - k ) else nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>mn ) then info = -5_${ik}$ else if( lda=max( m, n, & k ) ) ) then call stdlib${ii}$_dgemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info & ) else call stdlib${ii}$_dlamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, & lwork, info ) end if work( 1_${ik}$ ) = lw return end subroutine stdlib${ii}$_dgemlq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & !! DGEMLQ: overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product !! of blocked elementary reflectors computed by short wide LQ !! factorization (DGELQ) info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), t(*) real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: mb, nb, lw, nblcks, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments lquery = lwork==-1_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'T' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) mb = int( t( 2_${ik}$ ),KIND=${ik}$) nb = int( t( 3_${ik}$ ),KIND=${ik}$) if( left ) then lw = n * mb mn = m else lw = m * mb mn = n end if if( ( nb>k ) .and. ( mn>k ) ) then if( mod( mn - k, nb - k ) == 0_${ik}$ ) then nblcks = ( mn - k ) / ( nb - k ) else nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>mn ) then info = -5_${ik}$ else if( lda=max( m, n, & k ) ) ) then call stdlib${ii}$_${ri}$gemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info & ) else call stdlib${ii}$_${ri}$lamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, & lwork, info ) end if work( 1_${ik}$ ) = lw return end subroutine stdlib${ii}$_${ri}$gemlq #:endif #:endfor pure module subroutine stdlib${ii}$_cgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & !! CGEMLQ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product !! of blocked elementary reflectors computed by short wide !! LQ factorization (CGELQ) info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc ! Array Arguments complex(sp), intent(in) :: a(lda,*), t(*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: mb, nb, lw, nblcks, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments lquery = lwork==-1_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'C' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) mb = int( t( 2_${ik}$ ),KIND=${ik}$) nb = int( t( 3_${ik}$ ),KIND=${ik}$) if( left ) then lw = n * mb mn = m else lw = m * mb mn = n end if if( ( nb>k ) .and. ( mn>k ) ) then if( mod( mn - k, nb - k ) == 0_${ik}$ ) then nblcks = ( mn - k ) / ( nb - k ) else nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>mn ) then info = -5_${ik}$ else if( lda=max( m, n, & k ) ) ) then call stdlib${ii}$_cgemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info & ) else call stdlib${ii}$_clamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, & lwork, info ) end if work( 1_${ik}$ ) = real( lw,KIND=sp) return end subroutine stdlib${ii}$_cgemlq pure module subroutine stdlib${ii}$_zgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & !! ZGEMLQ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product !! of blocked elementary reflectors computed by short wide !! LQ factorization (ZGELQ) info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc ! Array Arguments complex(dp), intent(in) :: a(lda,*), t(*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: mb, nb, lw, nblcks, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments lquery = lwork==-1_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'C' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) mb = int( t( 2_${ik}$ ),KIND=${ik}$) nb = int( t( 3_${ik}$ ),KIND=${ik}$) if( left ) then lw = n * mb mn = m else lw = m * mb mn = n end if if( ( nb>k ) .and. ( mn>k ) ) then if( mod( mn - k, nb - k ) == 0_${ik}$ ) then nblcks = ( mn - k ) / ( nb - k ) else nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>mn ) then info = -5_${ik}$ else if( lda=max( m, n, & k ) ) ) then call stdlib${ii}$_zgemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info & ) else call stdlib${ii}$_zlamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, & lwork, info ) end if work( 1_${ik}$ ) = lw return end subroutine stdlib${ii}$_zgemlq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & !! ZGEMLQ: overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product !! of blocked elementary reflectors computed by short wide !! LQ factorization (ZGELQ) info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), t(*) complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: mb, nb, lw, nblcks, mn ! Intrinsic Functions ! Executable Statements ! test the input arguments lquery = lwork==-1_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'C' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) mb = int( t( 2_${ik}$ ),KIND=${ik}$) nb = int( t( 3_${ik}$ ),KIND=${ik}$) if( left ) then lw = n * mb mn = m else lw = m * mb mn = n end if if( ( nb>k ) .and. ( mn>k ) ) then if( mod( mn - k, nb - k ) == 0_${ik}$ ) then nblcks = ( mn - k ) / ( nb - k ) else nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$ end if else nblcks = 1_${ik}$ end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>mn ) then info = -5_${ik}$ else if( lda=max( m, n, & k ) ) ) then call stdlib${ii}$_${ci}$gemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info & ) else call stdlib${ii}$_${ci}$lamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, & lwork, info ) end if work( 1_${ik}$ ) = lw return end subroutine stdlib${ii}$_${ci}$gemlq #:endif #:endfor pure module subroutine stdlib${ii}$_sgelqf( m, n, a, lda, tau, work, lwork, info ) !! SGELQF computes an LQ factorization of a real M-by-N matrix A: !! A = ( L 0 ) * Q !! where: !! Q is a N-by-N orthogonal matrix; !! L is a lower-triangular M-by-M matrix; !! 0 is a M-by-(N-M) zero matrix, if M < N. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, k, ldwork, lwkopt, nb, nbmin, nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) lwkopt = m*nb work( 1_${ik}$ ) = lwkopt lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ .and. nb=nbmin .and. nbm ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = ki + 1, 1, -nb ib = min( nb, k-i+1 ) if( i+ib<=m ) then ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_clarft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), & work, ldwork ) ! apply h**h to a(i+ib:m,i:n) from the right call stdlib${ii}$_clarfb( 'RIGHT', 'CONJUGATE TRANSPOSE', 'FORWARD','ROWWISE', m-i-& ib+1, n-i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), & ldwork ) end if ! apply h**h to columns i:n of current block call stdlib${ii}$_cungl2( ib, n-i+1, ib, a( i, i ), lda, tau( i ), work,iinfo ) ! set columns 1:i-1 of current block to czero do j = 1, i - 1 do l = i, i + ib - 1 a( l, j ) = czero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_cunglq pure module subroutine stdlib${ii}$_zunglq( m, n, k, a, lda, tau, work, lwork, info ) !! ZUNGLQ generates an M-by-N complex matrix Q with orthonormal rows, !! which is defined as the first M rows of a product of K elementary !! reflectors of order N !! Q = H(k)**H . . . H(2)**H H(1)**H !! as returned by ZGELQF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, j, ki, kk, l, ldwork, lwkopt, nb, nbmin, nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGLQ', ' ', m, n, k, -1_${ik}$ ) lwkopt = max( 1_${ik}$, m )*nb work( 1_${ik}$ ) = lwkopt lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( nm ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = ki + 1, 1, -nb ib = min( nb, k-i+1 ) if( i+ib<=m ) then ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_zlarft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), & work, ldwork ) ! apply h**h to a(i+ib:m,i:n) from the right call stdlib${ii}$_zlarfb( 'RIGHT', 'CONJUGATE TRANSPOSE', 'FORWARD','ROWWISE', m-i-& ib+1, n-i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), & ldwork ) end if ! apply h**h to columns i:n of current block call stdlib${ii}$_zungl2( ib, n-i+1, ib, a( i, i ), lda, tau( i ), work,iinfo ) ! set columns 1:i-1 of current block to czero do j = 1, i - 1 do l = i, i + ib - 1 a( l, j ) = czero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_zunglq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unglq( m, n, k, a, lda, tau, work, lwork, info ) !! ZUNGLQ: generates an M-by-N complex matrix Q with orthonormal rows, !! which is defined as the first M rows of a product of K elementary !! reflectors of order N !! Q = H(k)**H . . . H(2)**H H(1)**H !! as returned by ZGELQF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, j, ki, kk, l, ldwork, lwkopt, nb, nbmin, nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGLQ', ' ', m, n, k, -1_${ik}$ ) lwkopt = max( 1_${ik}$, m )*nb work( 1_${ik}$ ) = lwkopt lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( nm ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = ki + 1, 1, -nb ib = min( nb, k-i+1 ) if( i+ib<=m ) then ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_${ci}$larft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), & work, ldwork ) ! apply h**h to a(i+ib:m,i:n) from the right call stdlib${ii}$_${ci}$larfb( 'RIGHT', 'CONJUGATE TRANSPOSE', 'FORWARD','ROWWISE', m-i-& ib+1, n-i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), & ldwork ) end if ! apply h**h to columns i:n of current block call stdlib${ii}$_${ci}$ungl2( ib, n-i+1, ib, a( i, i ), lda, tau( i ), work,iinfo ) ! set columns 1:i-1 of current block to czero do j = 1, i - 1 do l = i, i + ib - 1 a( l, j ) = czero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_${ci}$unglq #:endif #:endfor pure module subroutine stdlib${ii}$_cungl2( m, n, k, a, lda, tau, work, info ) !! CUNGL2 generates an m-by-n complex matrix Q with orthonormal rows, !! which is defined as the first m rows of a product of k elementary !! reflectors of order n !! Q = H(k)**H . . . H(2)**H H(1)**H !! as returned by CGELQF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, l ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( nm ) then info = -3_${ik}$ else if( ldak .and. j<=m )a( j, j ) = cone end do end if do i = k, 1, -1 ! apply h(i)**h to a(i:m,i:n) from the right if( im ) then info = -3_${ik}$ else if( ldak .and. j<=m )a( j, j ) = cone end do end if do i = k, 1, -1 ! apply h(i)**h to a(i:m,i:n) from the right if( im ) then info = -3_${ik}$ else if( ldak .and. j<=m )a( j, j ) = cone end do end if do i = k, 1, -1 ! apply h(i)**h to a(i:m,i:n) from the right if( inq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_cunml2( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ else mi = m ic = 1_${ik}$ end if if( notran ) then transt = 'C' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_clarft( 'FORWARD', 'ROWWISE', nq-i+1, ib, a( i, i ),lda, tau( i ), & work( iwt ), ldt ) if( left ) then ! h or h**h is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**h is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**h call stdlib${ii}$_clarfb( side, transt, 'FORWARD', 'ROWWISE', mi, ni, ib,a( i, i ), & lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cunmlq pure module subroutine stdlib${ii}$_zunmlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) !! ZUNMLQ overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(k)**H . . . H(2)**H H(1)**H !! as returned by ZGELQF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran character :: transt integer(${ik}$) :: i, i1, i2, i3, ib, ic, iinfo, iwt, jc, ldwork, lwkopt, mi, nb, nbmin, & ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_zunml2( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ else mi = m ic = 1_${ik}$ end if if( notran ) then transt = 'C' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_zlarft( 'FORWARD', 'ROWWISE', nq-i+1, ib, a( i, i ),lda, tau( i ), & work( iwt ), ldt ) if( left ) then ! h or h**h is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**h is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**h call stdlib${ii}$_zlarfb( side, transt, 'FORWARD', 'ROWWISE', mi, ni, ib,a( i, i ), & lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zunmlq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unmlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) !! ZUNMLQ: overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(k)**H . . . H(2)**H H(1)**H !! as returned by ZGELQF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran character :: transt integer(${ik}$) :: i, i1, i2, i3, ib, ic, iinfo, iwt, jc, ldwork, lwkopt, mi, nb, nbmin, & ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_${ci}$unml2( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ else mi = m ic = 1_${ik}$ end if if( notran ) then transt = 'C' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_${ci}$larft( 'FORWARD', 'ROWWISE', nq-i+1, ib, a( i, i ),lda, tau( i ), & work( iwt ), ldt ) if( left ) then ! h or h**h is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**h is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**h call stdlib${ii}$_${ci}$larfb( side, transt, 'FORWARD', 'ROWWISE', mi, ni, ib,a( i, i ), & lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$unmlq #:endif #:endfor pure module subroutine stdlib${ii}$_cunml2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) !! CUNML2 overwrites the general complex m-by-n matrix C with !! Q * C if SIDE = 'L' and TRANS = 'N', or !! Q**H* C if SIDE = 'L' and TRANS = 'C', or !! C * Q if SIDE = 'R' and TRANS = 'N', or !! C * Q**H if SIDE = 'R' and TRANS = 'C', !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(k)**H . . . H(2)**H H(1)**H !! as returned by CGELQF. Q is of order m if SIDE = 'L' and of order n !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, notran integer(${ik}$) :: i, i1, i2, i3, ic, jc, mi, ni, nq complex(sp) :: aii, taui ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) ! nq is the order of q if( left ) then nq = m else nq = n end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( ldam ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = ki + 1, 1, -nb ib = min( nb, k-i+1 ) if( i+ib<=m ) then ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_slarft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), & work, ldwork ) ! apply h**t to a(i+ib:m,i:n) from the right call stdlib${ii}$_slarfb( 'RIGHT', 'TRANSPOSE', 'FORWARD', 'ROWWISE',m-i-ib+1, n-i+& 1_${ik}$, ib, a( i, i ), lda, work,ldwork, a( i+ib, i ), lda, work( ib+1 ),ldwork ) end if ! apply h**t to columns i:n of current block call stdlib${ii}$_sorgl2( ib, n-i+1, ib, a( i, i ), lda, tau( i ), work,iinfo ) ! set columns 1:i-1 of current block to zero do j = 1, i - 1 do l = i, i + ib - 1 a( l, j ) = zero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_sorglq pure module subroutine stdlib${ii}$_dorglq( m, n, k, a, lda, tau, work, lwork, info ) !! DORGLQ generates an M-by-N real matrix Q with orthonormal rows, !! which is defined as the first M rows of a product of K elementary !! reflectors of order N !! Q = H(k) . . . H(2) H(1) !! as returned by DGELQF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, j, ki, kk, l, ldwork, lwkopt, nb, nbmin, nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGLQ', ' ', m, n, k, -1_${ik}$ ) lwkopt = max( 1_${ik}$, m )*nb work( 1_${ik}$ ) = lwkopt lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( nm ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = ki + 1, 1, -nb ib = min( nb, k-i+1 ) if( i+ib<=m ) then ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_dlarft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), & work, ldwork ) ! apply h**t to a(i+ib:m,i:n) from the right call stdlib${ii}$_dlarfb( 'RIGHT', 'TRANSPOSE', 'FORWARD', 'ROWWISE',m-i-ib+1, n-i+& 1_${ik}$, ib, a( i, i ), lda, work,ldwork, a( i+ib, i ), lda, work( ib+1 ),ldwork ) end if ! apply h**t to columns i:n of current block call stdlib${ii}$_dorgl2( ib, n-i+1, ib, a( i, i ), lda, tau( i ), work,iinfo ) ! set columns 1:i-1 of current block to zero do j = 1, i - 1 do l = i, i + ib - 1 a( l, j ) = zero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_dorglq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orglq( m, n, k, a, lda, tau, work, lwork, info ) !! DORGLQ: generates an M-by-N real matrix Q with orthonormal rows, !! which is defined as the first M rows of a product of K elementary !! reflectors of order N !! Q = H(k) . . . H(2) H(1) !! as returned by DGELQF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, j, ki, kk, l, ldwork, lwkopt, nb, nbmin, nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGLQ', ' ', m, n, k, -1_${ik}$ ) lwkopt = max( 1_${ik}$, m )*nb work( 1_${ik}$ ) = lwkopt lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( nm ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = ki + 1, 1, -nb ib = min( nb, k-i+1 ) if( i+ib<=m ) then ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_${ri}$larft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), & work, ldwork ) ! apply h**t to a(i+ib:m,i:n) from the right call stdlib${ii}$_${ri}$larfb( 'RIGHT', 'TRANSPOSE', 'FORWARD', 'ROWWISE',m-i-ib+1, n-i+& 1_${ik}$, ib, a( i, i ), lda, work,ldwork, a( i+ib, i ), lda, work( ib+1 ),ldwork ) end if ! apply h**t to columns i:n of current block call stdlib${ii}$_${ri}$orgl2( ib, n-i+1, ib, a( i, i ), lda, tau( i ), work,iinfo ) ! set columns 1:i-1 of current block to zero do j = 1, i - 1 do l = i, i + ib - 1 a( l, j ) = zero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_${ri}$orglq #:endif #:endfor pure module subroutine stdlib${ii}$_sorgl2( m, n, k, a, lda, tau, work, info ) !! SORGL2 generates an m by n real matrix Q with orthonormal rows, !! which is defined as the first m rows of a product of k elementary !! reflectors of order n !! Q = H(k) . . . H(2) H(1) !! as returned by SGELQF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, l ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( nm ) then info = -3_${ik}$ else if( ldak .and. j<=m )a( j, j ) = one end do end if do i = k, 1, -1 ! apply h(i) to a(i:m,i:n) from the right if( im ) then info = -3_${ik}$ else if( ldak .and. j<=m )a( j, j ) = one end do end if do i = k, 1, -1 ! apply h(i) to a(i:m,i:n) from the right if( im ) then info = -3_${ik}$ else if( ldak .and. j<=m )a( j, j ) = one end do end if do i = k, 1, -1 ! apply h(i) to a(i:m,i:n) from the right if( inq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_sorml2( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ else mi = m ic = 1_${ik}$ end if if( notran ) then transt = 'T' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_slarft( 'FORWARD', 'ROWWISE', nq-i+1, ib, a( i, i ),lda, tau( i ), & work( iwt ), ldt ) if( left ) then ! h or h**t is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**t is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**t call stdlib${ii}$_slarfb( side, transt, 'FORWARD', 'ROWWISE', mi, ni, ib,a( i, i ), & lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_sormlq pure module subroutine stdlib${ii}$_dormlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) !! DORMLQ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by DGELQF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran character :: transt integer(${ik}$) :: i, i1, i2, i3, ib, ic, iinfo, iwt, jc, ldwork, lwkopt, mi, nb, nbmin, & ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_dorml2( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ else mi = m ic = 1_${ik}$ end if if( notran ) then transt = 'T' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_dlarft( 'FORWARD', 'ROWWISE', nq-i+1, ib, a( i, i ),lda, tau( i ), & work( iwt ), ldt ) if( left ) then ! h or h**t is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**t is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**t call stdlib${ii}$_dlarfb( side, transt, 'FORWARD', 'ROWWISE', mi, ni, ib,a( i, i ), & lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dormlq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ormlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) !! DORMLQ: overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by DGELQF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran character :: transt integer(${ik}$) :: i, i1, i2, i3, ib, ic, iinfo, iwt, jc, ldwork, lwkopt, mi, nb, nbmin, & ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_${ri}$orml2( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n jc = 1_${ik}$ else mi = m ic = 1_${ik}$ end if if( notran ) then transt = 'T' else transt = 'N' end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i) h(i+1) . . . h(i+ib-1) call stdlib${ii}$_${ri}$larft( 'FORWARD', 'ROWWISE', nq-i+1, ib, a( i, i ),lda, tau( i ), & work( iwt ), ldt ) if( left ) then ! h or h**t is applied to c(i:m,1:n) mi = m - i + 1_${ik}$ ic = i else ! h or h**t is applied to c(1:m,i:n) ni = n - i + 1_${ik}$ jc = i end if ! apply h or h**t call stdlib${ii}$_${ri}$larfb( side, transt, 'FORWARD', 'ROWWISE', mi, ni, ib,a( i, i ), & lda, work( iwt ), ldt,c( ic, jc ), ldc, work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$ormlq #:endif #:endfor pure module subroutine stdlib${ii}$_sorml2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) !! SORML2 overwrites the general real m by n matrix C with !! Q * C if SIDE = 'L' and TRANS = 'N', or !! Q**T* C if SIDE = 'L' and TRANS = 'T', or !! C * Q if SIDE = 'R' and TRANS = 'N', or !! C * Q**T if SIDE = 'R' and TRANS = 'T', !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by SGELQF. Q is of order m if SIDE = 'L' and of order n !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, notran integer(${ik}$) :: i, i1, i2, i3, ic, jc, mi, ni, nq real(sp) :: aii ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) ! nq is the order of q if( left ) then nq = m else nq = n end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( ldamin(m,n) .and. min(m,n)>0_${ik}$ ) )then info = -3_${ik}$ else if( ldamin(m,n) .and. min(m,n)>0_${ik}$ ) )then info = -3_${ik}$ else if( ldamin(m,n) .and. min(m,n)>0_${ik}$ ) )then info = -3_${ik}$ else if( ldamin(m,n) .and. min(m,n)>0_${ik}$ ))then info = -3_${ik}$ else if( ldamin(m,n) .and. min(m,n)>0_${ik}$ ))then info = -3_${ik}$ else if( ldamin(m,n) .and. min(m,n)>0_${ik}$ ))then info = -3_${ik}$ else if( ldaq ) then info = -5_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$)) then info = -6_${ik}$ else if( ldvq ) then info = -5_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$)) then info = -6_${ik}$ else if( ldvq ) then info = -5_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$)) then info = -6_${ik}$ else if( ldvq ) then info = -5_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$)) then info = -6_${ik}$ else if( ldvq ) then info = -5_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$)) then info = -6_${ik}$ else if( ldvq ) then info = -5_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$)) then info = -6_${ik}$ else if( ldvm .and. m>0_${ik}$ )) then info = -3_${ik}$ else if( nb<=0_${ik}$ ) then info = -4_${ik}$ else if( lda=n).or.(nb<=m).or.(nb>=n)) then call stdlib${ii}$_sgelqt( m, n, mb, a, lda, t, ldt, work, info) return end if kk = mod((n-m),(nb-m)) ii=n-kk+1 ! compute the lq factorization of the first block a(1:m,1:nb) call stdlib${ii}$_sgelqt( m, nb, mb, a(1_${ik}$,1_${ik}$), lda, t, ldt, work, info) ctr = 1_${ik}$ do i = nb+1, ii-nb+m , (nb-m) ! compute the qr factorization of the current block a(1:m,i:i+nb-m) call stdlib${ii}$_stplqt( m, nb-m, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, i ),lda, t(1_${ik}$, ctr * m + 1_${ik}$),& ldt, work, info ) ctr = ctr + 1_${ik}$ end do ! compute the qr factorization of the last block a(1:m,ii:n) if (ii<=n) then call stdlib${ii}$_stplqt( m, kk, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, ii ),lda, t(1_${ik}$, ctr * m + 1_${ik}$), & ldt,work, info ) end if work( 1_${ik}$ ) = m * mb return end subroutine stdlib${ii}$_slaswlq pure module subroutine stdlib${ii}$_dlaswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) !! DLASWLQ computes a blocked Tall-Skinny LQ factorization of !! a real M-by-N matrix A for M <= N: !! A = ( L 0 ) * Q, !! where: !! Q is a n-by-N orthogonal matrix, stored on exit in an implicit !! form in the elements above the diagonal of the array A and in !! the elements of the array T; !! L is a lower-triangular M-by-M matrix stored on exit in !! the elements on and below the diagonal of the array A. !! 0 is a M-by-(N-M) zero matrix, if M < N, and is not stored. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd. -- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, lwork, ldt ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*), t(ldt,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ii, kk, ctr ! External Subroutines ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ .or. nm .and. m>0_${ik}$ )) then info = -3_${ik}$ else if( nb<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n).or.(nb<=m).or.(nb>=n)) then call stdlib${ii}$_dgelqt( m, n, mb, a, lda, t, ldt, work, info) return end if kk = mod((n-m),(nb-m)) ii=n-kk+1 ! compute the lq factorization of the first block a(1:m,1:nb) call stdlib${ii}$_dgelqt( m, nb, mb, a(1_${ik}$,1_${ik}$), lda, t, ldt, work, info) ctr = 1_${ik}$ do i = nb+1, ii-nb+m , (nb-m) ! compute the qr factorization of the current block a(1:m,i:i+nb-m) call stdlib${ii}$_dtplqt( m, nb-m, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, i ),lda, t(1_${ik}$, ctr * m + 1_${ik}$),& ldt, work, info ) ctr = ctr + 1_${ik}$ end do ! compute the qr factorization of the last block a(1:m,ii:n) if (ii<=n) then call stdlib${ii}$_dtplqt( m, kk, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, ii ),lda, t(1_${ik}$, ctr * m + 1_${ik}$), & ldt,work, info ) end if work( 1_${ik}$ ) = m * mb return end subroutine stdlib${ii}$_dlaswlq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) !! DLASWLQ: computes a blocked Tall-Skinny LQ factorization of !! a real M-by-N matrix A for M <= N: !! A = ( L 0 ) * Q, !! where: !! Q is a n-by-N orthogonal matrix, stored on exit in an implicit !! form in the elements above the diagonal of the array A and in !! the elements of the array T; !! L is a lower-triangular M-by-M matrix stored on exit in !! the elements on and below the diagonal of the array A. !! 0 is a M-by-(N-M) zero matrix, if M < N, and is not stored. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd. -- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, lwork, ldt ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: work(*), t(ldt,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ii, kk, ctr ! External Subroutines ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ .or. nm .and. m>0_${ik}$ )) then info = -3_${ik}$ else if( nb<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n).or.(nb<=m).or.(nb>=n)) then call stdlib${ii}$_${ri}$gelqt( m, n, mb, a, lda, t, ldt, work, info) return end if kk = mod((n-m),(nb-m)) ii=n-kk+1 ! compute the lq factorization of the first block a(1:m,1:nb) call stdlib${ii}$_${ri}$gelqt( m, nb, mb, a(1_${ik}$,1_${ik}$), lda, t, ldt, work, info) ctr = 1_${ik}$ do i = nb+1, ii-nb+m , (nb-m) ! compute the qr factorization of the current block a(1:m,i:i+nb-m) call stdlib${ii}$_${ri}$tplqt( m, nb-m, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, i ),lda, t(1_${ik}$, ctr * m + 1_${ik}$),& ldt, work, info ) ctr = ctr + 1_${ik}$ end do ! compute the qr factorization of the last block a(1:m,ii:n) if (ii<=n) then call stdlib${ii}$_${ri}$tplqt( m, kk, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, ii ),lda, t(1_${ik}$, ctr * m + 1_${ik}$), & ldt,work, info ) end if work( 1_${ik}$ ) = m * mb return end subroutine stdlib${ii}$_${ri}$laswlq #:endif #:endfor pure module subroutine stdlib${ii}$_claswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) !! CLASWLQ computes a blocked Tall-Skinny LQ factorization of !! a complex M-by-N matrix A for M <= N: !! A = ( L 0 ) * Q, !! where: !! Q is a n-by-N orthogonal matrix, stored on exit in an implicit !! form in the elements above the diagonal of the array A and in !! the elements of the array T; !! L is a lower-triangular M-by-M matrix stored on exit in !! the elements on and below the diagonal of the array A. !! 0 is a M-by-(N-M) zero matrix, if M < N, and is not stored. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd. -- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, lwork, ldt ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*), t(ldt,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ii, kk, ctr ! External Subroutines ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ .or. nm .and. m>0_${ik}$ )) then info = -3_${ik}$ else if( nb<=0_${ik}$ ) then info = -4_${ik}$ else if( lda=n).or.(nb<=m).or.(nb>=n)) then call stdlib${ii}$_cgelqt( m, n, mb, a, lda, t, ldt, work, info) return end if kk = mod((n-m),(nb-m)) ii=n-kk+1 ! compute the lq factorization of the first block a(1:m,1:nb) call stdlib${ii}$_cgelqt( m, nb, mb, a(1_${ik}$,1_${ik}$), lda, t, ldt, work, info) ctr = 1_${ik}$ do i = nb+1, ii-nb+m , (nb-m) ! compute the qr factorization of the current block a(1:m,i:i+nb-m) call stdlib${ii}$_ctplqt( m, nb-m, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, i ),lda, t(1_${ik}$,ctr*m+1),ldt, & work, info ) ctr = ctr + 1_${ik}$ end do ! compute the qr factorization of the last block a(1:m,ii:n) if (ii<=n) then call stdlib${ii}$_ctplqt( m, kk, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, ii ),lda, t(1_${ik}$,ctr*m+1), ldt,& work, info ) end if work( 1_${ik}$ ) = m * mb return end subroutine stdlib${ii}$_claswlq pure module subroutine stdlib${ii}$_zlaswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) !! ZLASWLQ computes a blocked Tall-Skinny LQ factorization of !! a complexx M-by-N matrix A for M <= N: !! A = ( L 0 ) * Q, !! where: !! Q is a n-by-N orthogonal matrix, stored on exit in an implicit !! form in the elements above the diagonal of the array A and in !! the elements of the array T; !! L is a lower-triangular M-by-M matrix stored on exit in !! the elements on and below the diagonal of the array A. !! 0 is a M-by-(N-M) zero matrix, if M < N, and is not stored. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd. -- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, lwork, ldt ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*), t(ldt,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ii, kk, ctr ! External Subroutines ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ .or. nm .and. m>0_${ik}$ )) then info = -3_${ik}$ else if( nb<=0_${ik}$ ) then info = -4_${ik}$ else if( lda=n).or.(nb<=m).or.(nb>=n)) then call stdlib${ii}$_zgelqt( m, n, mb, a, lda, t, ldt, work, info) return end if kk = mod((n-m),(nb-m)) ii=n-kk+1 ! compute the lq factorization of the first block a(1:m,1:nb) call stdlib${ii}$_zgelqt( m, nb, mb, a(1_${ik}$,1_${ik}$), lda, t, ldt, work, info) ctr = 1_${ik}$ do i = nb+1, ii-nb+m , (nb-m) ! compute the qr factorization of the current block a(1:m,i:i+nb-m) call stdlib${ii}$_ztplqt( m, nb-m, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, i ),lda, t(1_${ik}$, ctr * m + 1_${ik}$),& ldt, work, info ) ctr = ctr + 1_${ik}$ end do ! compute the qr factorization of the last block a(1:m,ii:n) if (ii<=n) then call stdlib${ii}$_ztplqt( m, kk, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, ii ),lda, t(1_${ik}$, ctr * m + 1_${ik}$), & ldt,work, info ) end if work( 1_${ik}$ ) = m * mb return end subroutine stdlib${ii}$_zlaswlq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) !! ZLASWLQ: computes a blocked Tall-Skinny LQ factorization of !! a complexx M-by-N matrix A for M <= N: !! A = ( L 0 ) * Q, !! where: !! Q is a n-by-N orthogonal matrix, stored on exit in an implicit !! form in the elements above the diagonal of the array A and in !! the elements of the array T; !! L is a lower-triangular M-by-M matrix stored on exit in !! the elements on and below the diagonal of the array A. !! 0 is a M-by-(N-M) zero matrix, if M < N, and is not stored. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd. -- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, lwork, ldt ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*), t(ldt,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ii, kk, ctr ! External Subroutines ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ .or. nm .and. m>0_${ik}$ )) then info = -3_${ik}$ else if( nb<=0_${ik}$ ) then info = -4_${ik}$ else if( lda=n).or.(nb<=m).or.(nb>=n)) then call stdlib${ii}$_${ci}$gelqt( m, n, mb, a, lda, t, ldt, work, info) return end if kk = mod((n-m),(nb-m)) ii=n-kk+1 ! compute the lq factorization of the first block a(1:m,1:nb) call stdlib${ii}$_${ci}$gelqt( m, nb, mb, a(1_${ik}$,1_${ik}$), lda, t, ldt, work, info) ctr = 1_${ik}$ do i = nb+1, ii-nb+m , (nb-m) ! compute the qr factorization of the current block a(1:m,i:i+nb-m) call stdlib${ii}$_${ci}$tplqt( m, nb-m, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, i ),lda, t(1_${ik}$, ctr * m + 1_${ik}$),& ldt, work, info ) ctr = ctr + 1_${ik}$ end do ! compute the qr factorization of the last block a(1:m,ii:n) if (ii<=n) then call stdlib${ii}$_${ci}$tplqt( m, kk, 0_${ik}$, mb, a(1_${ik}$,1_${ik}$), lda, a( 1_${ik}$, ii ),lda, t(1_${ik}$, ctr * m + 1_${ik}$), & ldt,work, info ) end if work( 1_${ik}$ ) = m * mb return end subroutine stdlib${ii}$_${ci}$laswlq #:endif #:endfor pure module subroutine stdlib${ii}$_slamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & !! SLAMSWLQ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of blocked !! elementary reflectors computed by short wide LQ !! factorization (SLASWLQ) lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc ! Array Arguments real(sp), intent(in) :: a(lda,*), t(ldt,*) real(sp), intent(out) :: work(*) real(sp), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: i, ii, kk, lw, ctr ! External Subroutines ! Executable Statements ! test the input arguments lquery = lwork<0_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'T' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) if (left) then lw = n * mb else lw = m * mb end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( k<0_${ik}$ ) then info = -5_${ik}$ else if( m=max(m,n,k))) then call stdlib${ii}$_sgemlqt( side, trans, m, n, k, mb, a, lda,t, ldt, c, ldc, work, info) return end if if(left.and.tran) then ! multiply q to the last block of c kk = mod((m-k),(nb-k)) ctr = (m-k)/(nb-k) if (kk>0_${ik}$) then ii=m-kk+1 call stdlib${ii}$_stpmlqt('L','T',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1), ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) else ii=m+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+nb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_stpmlqt('L','T',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr*k+1),ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:nb) call stdlib${ii}$_sgemlqt('L','T',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (left.and.notran) then ! multiply q to the first block of c kk = mod((m-k),(nb-k)) ii=m-kk+1 ctr = 1_${ik}$ call stdlib${ii}$_sgemlqt('L','N',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (i:i+nb,1:n) call stdlib${ii}$_stpmlqt('L','N',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr * k+1), ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=m) then ! multiply q to the last block of c call stdlib${ii}$_stpmlqt('L','N',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) end if else if(right.and.notran) then ! multiply q to the last block of c kk = mod((n-k),(nb-k)) ctr = (n-k)/(nb-k) if (kk>0_${ik}$) then ii=n-kk+1 call stdlib${ii}$_stpmlqt('R','N',m , kk, k, 0_${ik}$, mb, a(1_${ik}$, ii), lda,t(1_${ik}$,ctr*k+1), ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,ii), ldc, work, info ) else ii=n+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_stpmlqt('R','N', m, nb-k, k, 0_${ik}$, mb, a(1_${ik}$, i), lda,t(1_${ik}$,ctr*k+1), ldt, & c(1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:mb) call stdlib${ii}$_sgemlqt('R','N',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (right.and.tran) then ! multiply q to the first block of c kk = mod((n-k),(nb-k)) ii=n-kk+1 ctr = 1_${ik}$ call stdlib${ii}$_sgemlqt('R','T',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) call stdlib${ii}$_stpmlqt('R','T',m , nb-k, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$, ctr*k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=n) then ! multiply q to the last block of c call stdlib${ii}$_stpmlqt('R','T',m , kk, k, 0_${ik}$,mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1),ldt, c(1_${ik}$,1_${ik}$),& ldc,c(1_${ik}$,ii), ldc, work, info ) end if end if work(1_${ik}$) = lw return end subroutine stdlib${ii}$_slamswlq pure module subroutine stdlib${ii}$_dlamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & !! DLAMSWLQ overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of blocked !! elementary reflectors computed by short wide LQ !! factorization (DLASWLQ) lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc ! Array Arguments real(dp), intent(in) :: a(lda,*), t(ldt,*) real(dp), intent(out) :: work(*) real(dp), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: i, ii, kk, ctr, lw ! External Subroutines ! Executable Statements ! test the input arguments lquery = lwork<0_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'T' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) if (left) then lw = n * mb else lw = m * mb end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( k<0_${ik}$ ) then info = -5_${ik}$ else if( m=max(m,n,k))) then call stdlib${ii}$_dgemlqt( side, trans, m, n, k, mb, a, lda,t, ldt, c, ldc, work, info) return end if if(left.and.tran) then ! multiply q to the last block of c kk = mod((m-k),(nb-k)) ctr = (m-k)/(nb-k) if (kk>0_${ik}$) then ii=m-kk+1 call stdlib${ii}$_dtpmlqt('L','T',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1), ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) else ii=m+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+nb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_dtpmlqt('L','T',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$, ctr*k+1),ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:nb) call stdlib${ii}$_dgemlqt('L','T',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (left.and.notran) then ! multiply q to the first block of c kk = mod((m-k),(nb-k)) ii=m-kk+1 ctr = 1_${ik}$ call stdlib${ii}$_dgemlqt('L','N',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (i:i+nb,1:n) call stdlib${ii}$_dtpmlqt('L','N',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr*k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=m) then ! multiply q to the last block of c call stdlib${ii}$_dtpmlqt('L','N',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) end if else if(right.and.notran) then ! multiply q to the last block of c kk = mod((n-k),(nb-k)) ctr = (n-k)/(nb-k) if (kk>0_${ik}$) then ii=n-kk+1 call stdlib${ii}$_dtpmlqt('R','N',m , kk, k, 0_${ik}$, mb, a(1_${ik}$, ii), lda,t(1_${ik}$,ctr *k+1), ldt, & c(1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,ii), ldc, work, info ) else ii=n+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_dtpmlqt('R','N', m, nb-k, k, 0_${ik}$, mb, a(1_${ik}$, i), lda,t(1_${ik}$,ctr*k+1), ldt, & c(1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:mb) call stdlib${ii}$_dgemlqt('R','N',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (right.and.tran) then ! multiply q to the first block of c kk = mod((n-k),(nb-k)) ctr = 1_${ik}$ ii=n-kk+1 call stdlib${ii}$_dgemlqt('R','T',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) call stdlib${ii}$_dtpmlqt('R','T',m , nb-k, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr*k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=n) then ! multiply q to the last block of c call stdlib${ii}$_dtpmlqt('R','T',m , kk, k, 0_${ik}$,mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1),ldt, c(1_${ik}$,1_${ik}$),& ldc,c(1_${ik}$,ii), ldc, work, info ) end if end if work(1_${ik}$) = lw return end subroutine stdlib${ii}$_dlamswlq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & !! DLAMSWLQ: overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of blocked !! elementary reflectors computed by short wide LQ !! factorization (DLASWLQ) lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), t(ldt,*) real(${rk}$), intent(out) :: work(*) real(${rk}$), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: i, ii, kk, ctr, lw ! External Subroutines ! Executable Statements ! test the input arguments lquery = lwork<0_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'T' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) if (left) then lw = n * mb else lw = m * mb end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( k<0_${ik}$ ) then info = -5_${ik}$ else if( m=max(m,n,k))) then call stdlib${ii}$_${ri}$gemlqt( side, trans, m, n, k, mb, a, lda,t, ldt, c, ldc, work, info) return end if if(left.and.tran) then ! multiply q to the last block of c kk = mod((m-k),(nb-k)) ctr = (m-k)/(nb-k) if (kk>0_${ik}$) then ii=m-kk+1 call stdlib${ii}$_${ri}$tpmlqt('L','T',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1), ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) else ii=m+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+nb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_${ri}$tpmlqt('L','T',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$, ctr*k+1),ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:nb) call stdlib${ii}$_${ri}$gemlqt('L','T',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (left.and.notran) then ! multiply q to the first block of c kk = mod((m-k),(nb-k)) ii=m-kk+1 ctr = 1_${ik}$ call stdlib${ii}$_${ri}$gemlqt('L','N',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (i:i+nb,1:n) call stdlib${ii}$_${ri}$tpmlqt('L','N',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr*k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=m) then ! multiply q to the last block of c call stdlib${ii}$_${ri}$tpmlqt('L','N',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) end if else if(right.and.notran) then ! multiply q to the last block of c kk = mod((n-k),(nb-k)) ctr = (n-k)/(nb-k) if (kk>0_${ik}$) then ii=n-kk+1 call stdlib${ii}$_${ri}$tpmlqt('R','N',m , kk, k, 0_${ik}$, mb, a(1_${ik}$, ii), lda,t(1_${ik}$,ctr *k+1), ldt, & c(1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,ii), ldc, work, info ) else ii=n+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_${ri}$tpmlqt('R','N', m, nb-k, k, 0_${ik}$, mb, a(1_${ik}$, i), lda,t(1_${ik}$,ctr*k+1), ldt, & c(1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:mb) call stdlib${ii}$_${ri}$gemlqt('R','N',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (right.and.tran) then ! multiply q to the first block of c kk = mod((n-k),(nb-k)) ctr = 1_${ik}$ ii=n-kk+1 call stdlib${ii}$_${ri}$gemlqt('R','T',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) call stdlib${ii}$_${ri}$tpmlqt('R','T',m , nb-k, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr*k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=n) then ! multiply q to the last block of c call stdlib${ii}$_${ri}$tpmlqt('R','T',m , kk, k, 0_${ik}$,mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1),ldt, c(1_${ik}$,1_${ik}$),& ldc,c(1_${ik}$,ii), ldc, work, info ) end if end if work(1_${ik}$) = lw return end subroutine stdlib${ii}$_${ri}$lamswlq #:endif #:endfor pure module subroutine stdlib${ii}$_clamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & !! CLAMSWLQ overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of blocked !! elementary reflectors computed by short wide LQ !! factorization (CLASWLQ) lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc ! Array Arguments complex(sp), intent(in) :: a(lda,*), t(ldt,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: i, ii, kk, lw, ctr ! External Subroutines ! Executable Statements ! test the input arguments lquery = lwork<0_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'C' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) if (left) then lw = n * mb else lw = m * mb end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( k<0_${ik}$ ) then info = -5_${ik}$ else if( m=max(m,n,k))) then call stdlib${ii}$_cgemlqt( side, trans, m, n, k, mb, a, lda,t, ldt, c, ldc, work, info) return end if if(left.and.tran) then ! multiply q to the last block of c kk = mod((m-k),(nb-k)) ctr = (m-k)/(nb-k) if (kk>0_${ik}$) then ii=m-kk+1 call stdlib${ii}$_ctpmlqt('L','C',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1), ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) else ii=m+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+nb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_ctpmlqt('L','C',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr*k+1),ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:nb) call stdlib${ii}$_cgemlqt('L','C',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (left.and.notran) then ! multiply q to the first block of c kk = mod((m-k),(nb-k)) ii = m-kk+1 ctr = 1_${ik}$ call stdlib${ii}$_cgemlqt('L','N',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (i:i+nb,1:n) call stdlib${ii}$_ctpmlqt('L','N',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$, ctr *k+1), ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=m) then ! multiply q to the last block of c call stdlib${ii}$_ctpmlqt('L','N',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$, ctr*k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) end if else if(right.and.notran) then ! multiply q to the last block of c kk = mod((n-k),(nb-k)) ctr = (n-k)/(nb-k) if (kk>0_${ik}$) then ii=n-kk+1 call stdlib${ii}$_ctpmlqt('R','N',m , kk, k, 0_${ik}$, mb, a(1_${ik}$, ii), lda,t(1_${ik}$,ctr*k+1), ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,ii), ldc, work, info ) else ii=n+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_ctpmlqt('R','N', m, nb-k, k, 0_${ik}$, mb, a(1_${ik}$, i), lda,t(1_${ik}$,ctr*k+1), ldt,& c(1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:mb) call stdlib${ii}$_cgemlqt('R','N',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (right.and.tran) then ! multiply q to the first block of c kk = mod((n-k),(nb-k)) ii=n-kk+1 ctr = 1_${ik}$ call stdlib${ii}$_cgemlqt('R','C',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) call stdlib${ii}$_ctpmlqt('R','C',m , nb-k, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr*k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=n) then ! multiply q to the last block of c call stdlib${ii}$_ctpmlqt('R','C',m , kk, k, 0_${ik}$,mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1),ldt, c(1_${ik}$,1_${ik}$),& ldc,c(1_${ik}$,ii), ldc, work, info ) end if end if work(1_${ik}$) = lw return end subroutine stdlib${ii}$_clamswlq pure module subroutine stdlib${ii}$_zlamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & !! ZLAMSWLQ overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of blocked !! elementary reflectors computed by short wide LQ !! factorization (ZLASWLQ) lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc ! Array Arguments complex(dp), intent(in) :: a(lda,*), t(ldt,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: i, ii, kk, lw, ctr ! External Subroutines ! Executable Statements ! test the input arguments lquery = lwork<0_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'C' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) if (left) then lw = n * mb else lw = m * mb end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( k<0_${ik}$ ) then info = -5_${ik}$ else if( m=max(m,n,k))) then call stdlib${ii}$_zgemlqt( side, trans, m, n, k, mb, a, lda,t, ldt, c, ldc, work, info) return end if if(left.and.tran) then ! multiply q to the last block of c kk = mod((m-k),(nb-k)) ctr = (m-k)/(nb-k) if (kk>0_${ik}$) then ii=m-kk+1 call stdlib${ii}$_ztpmlqt('L','C',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1), ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) else ii=m+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+nb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_ztpmlqt('L','C',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr*k+1),ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:nb) call stdlib${ii}$_zgemlqt('L','C',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (left.and.notran) then ! multiply q to the first block of c kk = mod((m-k),(nb-k)) ii=m-kk+1 ctr = 1_${ik}$ call stdlib${ii}$_zgemlqt('L','N',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (i:i+nb,1:n) call stdlib${ii}$_ztpmlqt('L','N',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$, ctr * k + 1_${ik}$), ldt, & c(1_${ik}$,1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=m) then ! multiply q to the last block of c call stdlib${ii}$_ztpmlqt('L','N',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$, ctr * k + 1_${ik}$), ldt, & c(1_${ik}$,1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) end if else if(right.and.notran) then ! multiply q to the last block of c kk = mod((n-k),(nb-k)) ctr = (n-k)/(nb-k) if (kk>0_${ik}$) then ii=n-kk+1 call stdlib${ii}$_ztpmlqt('R','N',m , kk, k, 0_${ik}$, mb, a(1_${ik}$, ii), lda,t(1_${ik}$, ctr * k + 1_${ik}$), & ldt, c(1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,ii), ldc, work, info ) else ii=n+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_ztpmlqt('R','N', m, nb-k, k, 0_${ik}$, mb, a(1_${ik}$, i), lda,t(1_${ik}$, ctr * k + 1_${ik}$), & ldt, c(1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:mb) call stdlib${ii}$_zgemlqt('R','N',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (right.and.tran) then ! multiply q to the first block of c kk = mod((n-k),(nb-k)) ii=n-kk+1 call stdlib${ii}$_zgemlqt('R','C',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) ctr = 1_${ik}$ do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) call stdlib${ii}$_ztpmlqt('R','C',m , nb-k, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr *k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=n) then ! multiply q to the last block of c call stdlib${ii}$_ztpmlqt('R','C',m , kk, k, 0_${ik}$,mb, a(1_${ik}$,ii), lda,t(1_${ik}$, ctr * k + 1_${ik}$),ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,ii), ldc, work, info ) end if end if work(1_${ik}$) = lw return end subroutine stdlib${ii}$_zlamswlq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & !! ZLAMSWLQ: overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of blocked !! elementary reflectors computed by short wide LQ !! factorization (ZLASWLQ) lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), t(ldt,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran, lquery integer(${ik}$) :: i, ii, kk, lw, ctr ! External Subroutines ! Executable Statements ! test the input arguments lquery = lwork<0_${ik}$ notran = stdlib_lsame( trans, 'N' ) tran = stdlib_lsame( trans, 'C' ) left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) if (left) then lw = n * mb else lw = m * mb end if info = 0_${ik}$ if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( k<0_${ik}$ ) then info = -5_${ik}$ else if( m=max(m,n,k))) then call stdlib${ii}$_${ci}$gemlqt( side, trans, m, n, k, mb, a, lda,t, ldt, c, ldc, work, info) return end if if(left.and.tran) then ! multiply q to the last block of c kk = mod((m-k),(nb-k)) ctr = (m-k)/(nb-k) if (kk>0_${ik}$) then ii=m-kk+1 call stdlib${ii}$_${ci}$tpmlqt('L','C',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$,ctr*k+1), ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) else ii=m+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+nb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_${ci}$tpmlqt('L','C',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr*k+1),ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:nb) call stdlib${ii}$_${ci}$gemlqt('L','C',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (left.and.notran) then ! multiply q to the first block of c kk = mod((m-k),(nb-k)) ii=m-kk+1 ctr = 1_${ik}$ call stdlib${ii}$_${ci}$gemlqt('L','N',nb , n, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (i:i+nb,1:n) call stdlib${ii}$_${ci}$tpmlqt('L','N',nb-k , n, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$, ctr * k + 1_${ik}$), ldt, & c(1_${ik}$,1_${ik}$), ldc,c(i,1_${ik}$), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=m) then ! multiply q to the last block of c call stdlib${ii}$_${ci}$tpmlqt('L','N',kk , n, k, 0_${ik}$, mb, a(1_${ik}$,ii), lda,t(1_${ik}$, ctr * k + 1_${ik}$), ldt, & c(1_${ik}$,1_${ik}$), ldc,c(ii,1_${ik}$), ldc, work, info ) end if else if(right.and.notran) then ! multiply q to the last block of c kk = mod((n-k),(nb-k)) ctr = (n-k)/(nb-k) if (kk>0_${ik}$) then ii=n-kk+1 call stdlib${ii}$_${ci}$tpmlqt('R','N',m , kk, k, 0_${ik}$, mb, a(1_${ik}$, ii), lda,t(1_${ik}$, ctr * k + 1_${ik}$), & ldt, c(1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,ii), ldc, work, info ) else ii=n+1 end if do i=ii-(nb-k),nb+1,-(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) ctr = ctr - 1_${ik}$ call stdlib${ii}$_${ci}$tpmlqt('R','N', m, nb-k, k, 0_${ik}$, mb, a(1_${ik}$, i), lda,t(1_${ik}$, ctr * k + 1_${ik}$), & ldt, c(1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) end do ! multiply q to the first block of c (1:m,1:mb) call stdlib${ii}$_${ci}$gemlqt('R','N',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) else if (right.and.tran) then ! multiply q to the first block of c kk = mod((n-k),(nb-k)) ii=n-kk+1 call stdlib${ii}$_${ci}$gemlqt('R','C',m , nb, k, mb, a(1_${ik}$,1_${ik}$), lda, t,ldt ,c(1_${ik}$,1_${ik}$), ldc, work, & info ) ctr = 1_${ik}$ do i=nb+1,ii-nb+k,(nb-k) ! multiply q to the current block of c (1:m,i:i+mb) call stdlib${ii}$_${ci}$tpmlqt('R','C',m , nb-k, k, 0_${ik}$,mb, a(1_${ik}$,i), lda,t(1_${ik}$,ctr *k+1), ldt, c(1_${ik}$,& 1_${ik}$), ldc,c(1_${ik}$,i), ldc, work, info ) ctr = ctr + 1_${ik}$ end do if(ii<=n) then ! multiply q to the last block of c call stdlib${ii}$_${ci}$tpmlqt('R','C',m , kk, k, 0_${ik}$,mb, a(1_${ik}$,ii), lda,t(1_${ik}$, ctr * k + 1_${ik}$),ldt, c(& 1_${ik}$,1_${ik}$), ldc,c(1_${ik}$,ii), ldc, work, info ) end if end if work(1_${ik}$) = lw return end subroutine stdlib${ii}$_${ci}$lamswlq #:endif #:endfor pure module subroutine stdlib${ii}$_stplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) !! STPLQT computes a blocked LQ factorization of a real !! "triangular-pentagonal" matrix C, which is composed of a !! triangular block A and pentagonal block B, using the compact !! WY representation for Q. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: t(ldt,*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ib, lb, nb, iinfo ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( l<0_${ik}$ .or. (l>min(m,n) .and. min(m,n)>=0_${ik}$)) then info = -3_${ik}$ else if( mb<1_${ik}$ .or. (mb>m .and. m>0_${ik}$)) then info = -4_${ik}$ else if( lda=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_stplqt2( ib, nb, lb, a(i,i), lda, b( i, 1_${ik}$ ), ldb,t(1_${ik}$, i ), ldt, iinfo ) ! update by applying h**t to b(i+ib:m,:) from the right if( i+ib<=m ) then call stdlib${ii}$_stprfb( 'R', 'N', 'F', 'R', m-i-ib+1, nb, ib, lb,b( i, 1_${ik}$ ), ldb, t( & 1_${ik}$, i ), ldt,a( i+ib, i ), lda, b( i+ib, 1_${ik}$ ), ldb,work, m-i-ib+1) end if end do return end subroutine stdlib${ii}$_stplqt pure module subroutine stdlib${ii}$_dtplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) !! DTPLQT computes a blocked LQ factorization of a real !! "triangular-pentagonal" matrix C, which is composed of a !! triangular block A and pentagonal block B, using the compact !! WY representation for Q. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: t(ldt,*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ib, lb, nb, iinfo ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( l<0_${ik}$ .or. (l>min(m,n) .and. min(m,n)>=0_${ik}$)) then info = -3_${ik}$ else if( mb<1_${ik}$ .or. (mb>m .and. m>0_${ik}$)) then info = -4_${ik}$ else if( lda=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_dtplqt2( ib, nb, lb, a(i,i), lda, b( i, 1_${ik}$ ), ldb,t(1_${ik}$, i ), ldt, iinfo ) ! update by applying h**t to b(i+ib:m,:) from the right if( i+ib<=m ) then call stdlib${ii}$_dtprfb( 'R', 'N', 'F', 'R', m-i-ib+1, nb, ib, lb,b( i, 1_${ik}$ ), ldb, t( & 1_${ik}$, i ), ldt,a( i+ib, i ), lda, b( i+ib, 1_${ik}$ ), ldb,work, m-i-ib+1) end if end do return end subroutine stdlib${ii}$_dtplqt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) !! DTPLQT: computes a blocked LQ factorization of a real !! "triangular-pentagonal" matrix C, which is composed of a !! triangular block A and pentagonal block B, using the compact !! WY representation for Q. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: t(ldt,*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ib, lb, nb, iinfo ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( l<0_${ik}$ .or. (l>min(m,n) .and. min(m,n)>=0_${ik}$)) then info = -3_${ik}$ else if( mb<1_${ik}$ .or. (mb>m .and. m>0_${ik}$)) then info = -4_${ik}$ else if( lda=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_${ri}$tplqt2( ib, nb, lb, a(i,i), lda, b( i, 1_${ik}$ ), ldb,t(1_${ik}$, i ), ldt, iinfo ) ! update by applying h**t to b(i+ib:m,:) from the right if( i+ib<=m ) then call stdlib${ii}$_${ri}$tprfb( 'R', 'N', 'F', 'R', m-i-ib+1, nb, ib, lb,b( i, 1_${ik}$ ), ldb, t( & 1_${ik}$, i ), ldt,a( i+ib, i ), lda, b( i+ib, 1_${ik}$ ), ldb,work, m-i-ib+1) end if end do return end subroutine stdlib${ii}$_${ri}$tplqt #:endif #:endfor pure module subroutine stdlib${ii}$_ctplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) !! CTPLQT computes a blocked LQ factorization of a complex !! "triangular-pentagonal" matrix C, which is composed of a !! triangular block A and pentagonal block B, using the compact !! WY representation for Q. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb ! Array Arguments complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: t(ldt,*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ib, lb, nb, iinfo ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( l<0_${ik}$ .or. (l>min(m,n) .and. min(m,n)>=0_${ik}$)) then info = -3_${ik}$ else if( mb<1_${ik}$ .or. (mb>m .and. m>0_${ik}$)) then info = -4_${ik}$ else if( lda=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_ctplqt2( ib, nb, lb, a(i,i), lda, b( i, 1_${ik}$ ), ldb,t(1_${ik}$, i ), ldt, iinfo ) ! update by applying h**t to b(i+ib:m,:) from the right if( i+ib<=m ) then call stdlib${ii}$_ctprfb( 'R', 'N', 'F', 'R', m-i-ib+1, nb, ib, lb,b( i, 1_${ik}$ ), ldb, t( & 1_${ik}$, i ), ldt,a( i+ib, i ), lda, b( i+ib, 1_${ik}$ ), ldb,work, m-i-ib+1) end if end do return end subroutine stdlib${ii}$_ctplqt pure module subroutine stdlib${ii}$_ztplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) !! ZTPLQT computes a blocked LQ factorization of a complex !! "triangular-pentagonal" matrix C, which is composed of a !! triangular block A and pentagonal block B, using the compact !! WY representation for Q. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb ! Array Arguments complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: t(ldt,*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ib, lb, nb, iinfo ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( l<0_${ik}$ .or. (l>min(m,n) .and. min(m,n)>=0_${ik}$)) then info = -3_${ik}$ else if( mb<1_${ik}$ .or. (mb>m .and. m>0_${ik}$)) then info = -4_${ik}$ else if( lda=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_ztplqt2( ib, nb, lb, a(i,i), lda, b( i, 1_${ik}$ ), ldb,t(1_${ik}$, i ), ldt, iinfo ) ! update by applying h**t to b(i+ib:m,:) from the right if( i+ib<=m ) then call stdlib${ii}$_ztprfb( 'R', 'N', 'F', 'R', m-i-ib+1, nb, ib, lb,b( i, 1_${ik}$ ), ldb, t( & 1_${ik}$, i ), ldt,a( i+ib, i ), lda, b( i+ib, 1_${ik}$ ), ldb,work, m-i-ib+1) end if end do return end subroutine stdlib${ii}$_ztplqt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) !! ZTPLQT: computes a blocked LQ factorization of a complex !! "triangular-pentagonal" matrix C, which is composed of a !! triangular block A and pentagonal block B, using the compact !! WY representation for Q. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: t(ldt,*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ib, lb, nb, iinfo ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( l<0_${ik}$ .or. (l>min(m,n) .and. min(m,n)>=0_${ik}$)) then info = -3_${ik}$ else if( mb<1_${ik}$ .or. (mb>m .and. m>0_${ik}$)) then info = -4_${ik}$ else if( lda=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_${ci}$tplqt2( ib, nb, lb, a(i,i), lda, b( i, 1_${ik}$ ), ldb,t(1_${ik}$, i ), ldt, iinfo ) ! update by applying h**t to b(i+ib:m,:) from the right if( i+ib<=m ) then call stdlib${ii}$_${ci}$tprfb( 'R', 'N', 'F', 'R', m-i-ib+1, nb, ib, lb,b( i, 1_${ik}$ ), ldb, t( & 1_${ik}$, i ), ldt,a( i+ib, i ), lda, b( i+ib, 1_${ik}$ ), ldb,work, m-i-ib+1) end if end do return end subroutine stdlib${ii}$_${ci}$tplqt #:endif #:endfor pure module subroutine stdlib${ii}$_stplqt2( m, n, l, a, lda, b, ldb, t, ldt, info ) !! STPLQT2 computes a LQ a factorization of a real "triangular-pentagonal" !! matrix C, which is composed of a triangular block A and pentagonal block B, !! using the compact WY representation for Q. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: t(ldt,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, p, mp, np real(sp) :: alpha ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( l<0_${ik}$ .or. l>min(m,n) ) then info = -3_${ik}$ else if( ldamin(m,n) ) then info = -3_${ik}$ else if( ldamin(m,n) ) then info = -3_${ik}$ else if( ldamin(m,n) ) then info = -3_${ik}$ else if( ldamin(m,n) ) then info = -3_${ik}$ else if( ldamin(m,n) ) then info = -3_${ik}$ else if( ldak ) then info = -6_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$) ) then info = -7_${ik}$ else if( ldv=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_stprfb( 'L', 'T', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. tran ) then do i = 1, k, mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_stprfb( 'R', 'N', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do else if( left .and. tran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( m-l+i+ib-1, m ) if( i>=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_stprfb( 'L', 'N', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. notran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_stprfb( 'R', 'T', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do end if return end subroutine stdlib${ii}$_stpmlqt pure module subroutine stdlib${ii}$_dtpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, ldb, & !! DTPMQRT applies a real orthogonal matrix Q obtained from a !! "triangular-pentagonal" real block reflector H to a general !! real matrix C, which consists of two blocks A and B. work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, mb, ldt ! Array Arguments real(dp), intent(in) :: v(ldv,*), t(ldt,*) real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran integer(${ik}$) :: i, ib, nb, lb, kf, ldaq ! Intrinsic Functions ! Executable Statements ! Test The Input Arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) tran = stdlib_lsame( trans, 'T' ) notran = stdlib_lsame( trans, 'N' ) if ( left ) then ldaq = max( 1_${ik}$, k ) else if ( right ) then ldaq = max( 1_${ik}$, m ) end if if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. l>k ) then info = -6_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$) ) then info = -7_${ik}$ else if( ldv=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_dtprfb( 'L', 'T', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. tran ) then do i = 1, k, mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_dtprfb( 'R', 'N', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do else if( left .and. tran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( m-l+i+ib-1, m ) if( i>=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_dtprfb( 'L', 'N', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. notran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_dtprfb( 'R', 'T', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do end if return end subroutine stdlib${ii}$_dtpmlqt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, ldb, & !! DTPMQRT applies a real orthogonal matrix Q obtained from a !! "triangular-pentagonal" real block reflector H to a general !! real matrix C, which consists of two blocks A and B. work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, mb, ldt ! Array Arguments real(${rk}$), intent(in) :: v(ldv,*), t(ldt,*) real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran integer(${ik}$) :: i, ib, nb, lb, kf, ldaq ! Intrinsic Functions ! Executable Statements ! Test The Input Arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) tran = stdlib_lsame( trans, 'T' ) notran = stdlib_lsame( trans, 'N' ) if ( left ) then ldaq = max( 1_${ik}$, k ) else if ( right ) then ldaq = max( 1_${ik}$, m ) end if if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. l>k ) then info = -6_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$) ) then info = -7_${ik}$ else if( ldv=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_${ri}$tprfb( 'L', 'T', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. tran ) then do i = 1, k, mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_${ri}$tprfb( 'R', 'N', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do else if( left .and. tran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( m-l+i+ib-1, m ) if( i>=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_${ri}$tprfb( 'L', 'N', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. notran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_${ri}$tprfb( 'R', 'T', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do end if return end subroutine stdlib${ii}$_${ri}$tpmlqt #:endif #:endfor pure module subroutine stdlib${ii}$_ctpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, ldb, & !! CTPMLQT applies a complex unitary matrix Q obtained from a !! "triangular-pentagonal" complex block reflector H to a general !! complex matrix C, which consists of two blocks A and B. work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, mb, ldt ! Array Arguments complex(sp), intent(in) :: v(ldv,*), t(ldt,*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran integer(${ik}$) :: i, ib, nb, lb, kf, ldaq ! Intrinsic Functions ! Executable Statements ! Test The Input Arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) tran = stdlib_lsame( trans, 'C' ) notran = stdlib_lsame( trans, 'N' ) if ( left ) then ldaq = max( 1_${ik}$, k ) else if ( right ) then ldaq = max( 1_${ik}$, m ) end if if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. l>k ) then info = -6_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$) ) then info = -7_${ik}$ else if( ldv=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_ctprfb( 'L', 'C', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. tran ) then do i = 1, k, mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_ctprfb( 'R', 'N', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do else if( left .and. tran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( m-l+i+ib-1, m ) if( i>=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_ctprfb( 'L', 'N', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. notran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_ctprfb( 'R', 'C', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do end if return end subroutine stdlib${ii}$_ctpmlqt pure module subroutine stdlib${ii}$_ztpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, ldb, & !! ZTPMLQT applies a complex unitary matrix Q obtained from a !! "triangular-pentagonal" complex block reflector H to a general !! complex matrix C, which consists of two blocks A and B. work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, mb, ldt ! Array Arguments complex(dp), intent(in) :: v(ldv,*), t(ldt,*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran integer(${ik}$) :: i, ib, nb, lb, kf, ldaq ! Intrinsic Functions ! Executable Statements ! Test The Input Arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) tran = stdlib_lsame( trans, 'C' ) notran = stdlib_lsame( trans, 'N' ) if ( left ) then ldaq = max( 1_${ik}$, k ) else if ( right ) then ldaq = max( 1_${ik}$, m ) end if if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. l>k ) then info = -6_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$) ) then info = -7_${ik}$ else if( ldv=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_ztprfb( 'L', 'C', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. tran ) then do i = 1, k, mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_ztprfb( 'R', 'N', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do else if( left .and. tran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( m-l+i+ib-1, m ) if( i>=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_ztprfb( 'L', 'N', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. notran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_ztprfb( 'R', 'C', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do end if return end subroutine stdlib${ii}$_ztpmlqt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, ldb, & !! ZTPMLQT: applies a complex unitary matrix Q obtained from a !! "triangular-pentagonal" complex block reflector H to a general !! complex matrix C, which consists of two blocks A and B. work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, mb, ldt ! Array Arguments complex(${ck}$), intent(in) :: v(ldv,*), t(ldt,*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, right, tran, notran integer(${ik}$) :: i, ib, nb, lb, kf, ldaq ! Intrinsic Functions ! Executable Statements ! Test The Input Arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) right = stdlib_lsame( side, 'R' ) tran = stdlib_lsame( trans, 'C' ) notran = stdlib_lsame( trans, 'N' ) if ( left ) then ldaq = max( 1_${ik}$, k ) else if ( right ) then ldaq = max( 1_${ik}$, m ) end if if( .not.left .and. .not.right ) then info = -1_${ik}$ else if( .not.tran .and. .not.notran ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ ) then info = -5_${ik}$ else if( l<0_${ik}$ .or. l>k ) then info = -6_${ik}$ else if( mb<1_${ik}$ .or. (mb>k .and. k>0_${ik}$) ) then info = -7_${ik}$ else if( ldv=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_${ci}$tprfb( 'L', 'C', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. tran ) then do i = 1, k, mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_${ci}$tprfb( 'R', 'N', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do else if( left .and. tran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( m-l+i+ib-1, m ) if( i>=l ) then lb = 0_${ik}$ else lb = 0_${ik}$ end if call stdlib${ii}$_${ci}$tprfb( 'L', 'N', 'F', 'R', nb, n, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( i, 1_${ik}$ ), lda, b, ldb, work, ib ) end do else if( right .and. notran ) then kf = ((k-1)/mb)*mb+1 do i = kf, 1, -mb ib = min( mb, k-i+1 ) nb = min( n-l+i+ib-1, n ) if( i>=l ) then lb = 0_${ik}$ else lb = nb-n+l-i+1 end if call stdlib${ii}$_${ci}$tprfb( 'R', 'C', 'F', 'R', m, nb, ib, lb,v( i, 1_${ik}$ ), ldv, t( 1_${ik}$, i ), & ldt,a( 1_${ik}$, i ), lda, b, ldb, work, m ) end do end if return end subroutine stdlib${ii}$_${ci}$tpmlqt #:endif #:endfor pure module subroutine stdlib${ii}$_sgeqlf( m, n, a, lda, tau, work, lwork, info ) !! SGEQLF computes a QL factorization of a real M-by-N matrix A: !! A = Q * L. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, k, ki, kk, ldwork, lwkopt, mu, nb, nbmin, nu, & nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_slarft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h**t to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_slarfb( 'LEFT', 'TRANSPOSE', 'BACKWARD','COLUMNWISE', m-k+i+ib-1, & n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), ldwork ) end if end do mu = m - k + i + nb - 1_${ik}$ nu = n - k + i + nb - 1_${ik}$ else mu = m nu = n end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ .and. nu>0_${ik}$ )call stdlib${ii}$_sgeql2( mu, nu, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_sgeqlf pure module subroutine stdlib${ii}$_dgeqlf( m, n, a, lda, tau, work, lwork, info ) !! DGEQLF computes a QL factorization of a real M-by-N matrix A: !! A = Q * L. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, k, ki, kk, ldwork, lwkopt, mu, nb, nbmin, nu, & nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_dlarft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h**t to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_dlarfb( 'LEFT', 'TRANSPOSE', 'BACKWARD','COLUMNWISE', m-k+i+ib-1, & n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), ldwork ) end if end do mu = m - k + i + nb - 1_${ik}$ nu = n - k + i + nb - 1_${ik}$ else mu = m nu = n end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ .and. nu>0_${ik}$ )call stdlib${ii}$_dgeql2( mu, nu, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_dgeqlf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$geqlf( m, n, a, lda, tau, work, lwork, info ) !! DGEQLF: computes a QL factorization of a real M-by-N matrix A: !! A = Q * L. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, k, ki, kk, ldwork, lwkopt, mu, nb, nbmin, nu, & nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_${ri}$larft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h**t to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_${ri}$larfb( 'LEFT', 'TRANSPOSE', 'BACKWARD','COLUMNWISE', m-k+i+ib-1, & n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), ldwork ) end if end do mu = m - k + i + nb - 1_${ik}$ nu = n - k + i + nb - 1_${ik}$ else mu = m nu = n end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ .and. nu>0_${ik}$ )call stdlib${ii}$_${ri}$geql2( mu, nu, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_${ri}$geqlf #:endif #:endfor pure module subroutine stdlib${ii}$_cgeqlf( m, n, a, lda, tau, work, lwork, info ) !! CGEQLF computes a QL factorization of a complex M-by-N matrix A: !! A = Q * L. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, k, ki, kk, ldwork, lwkopt, mu, nb, nbmin, nu, & nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_clarft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h**h to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_clarfb( 'LEFT', 'CONJUGATE TRANSPOSE', 'BACKWARD','COLUMNWISE', m-& k+i+ib-1, n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), & ldwork ) end if end do mu = m - k + i + nb - 1_${ik}$ nu = n - k + i + nb - 1_${ik}$ else mu = m nu = n end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ .and. nu>0_${ik}$ )call stdlib${ii}$_cgeql2( mu, nu, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_cgeqlf pure module subroutine stdlib${ii}$_zgeqlf( m, n, a, lda, tau, work, lwork, info ) !! ZGEQLF computes a QL factorization of a complex M-by-N matrix A: !! A = Q * L. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, k, ki, kk, ldwork, lwkopt, mu, nb, nbmin, nu, & nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_zlarft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h**h to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_zlarfb( 'LEFT', 'CONJUGATE TRANSPOSE', 'BACKWARD','COLUMNWISE', m-& k+i+ib-1, n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), & ldwork ) end if end do mu = m - k + i + nb - 1_${ik}$ nu = n - k + i + nb - 1_${ik}$ else mu = m nu = n end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ .and. nu>0_${ik}$ )call stdlib${ii}$_zgeql2( mu, nu, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_zgeqlf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$geqlf( m, n, a, lda, tau, work, lwork, info ) !! ZGEQLF: computes a QL factorization of a complex M-by-N matrix A: !! A = Q * L. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, k, ki, kk, ldwork, lwkopt, mu, nb, nbmin, nu, & nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_${ci}$larft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h**h to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_${ci}$larfb( 'LEFT', 'CONJUGATE TRANSPOSE', 'BACKWARD','COLUMNWISE', m-& k+i+ib-1, n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), & ldwork ) end if end do mu = m - k + i + nb - 1_${ik}$ nu = n - k + i + nb - 1_${ik}$ else mu = m nu = n end if ! use unblocked code to factor the last or only block if( mu>0_${ik}$ .and. nu>0_${ik}$ )call stdlib${ii}$_${ci}$geql2( mu, nu, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_${ci}$geqlf #:endif #:endfor pure module subroutine stdlib${ii}$_sgeql2( m, n, a, lda, tau, work, info ) !! SGEQL2 computes a QL factorization of a real m by n matrix A: !! A = Q * L. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, k real(sp) :: aii ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldam ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = k - kk + 1, k, nb ib = min( nb, k-i+1 ) if( n-k+i>1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_clarft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_clarfb( 'LEFT', 'NO TRANSPOSE', 'BACKWARD','COLUMNWISE', m-k+i+ib-& 1_${ik}$, n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), ldwork ) end if ! apply h to rows 1:m-k+i+ib-1 of current block call stdlib${ii}$_cung2l( m-k+i+ib-1, ib, ib, a( 1_${ik}$, n-k+i ), lda,tau( i ), work, iinfo & ) ! set rows m-k+i+ib:m of current block to czero do j = n - k + i, n - k + i + ib - 1 do l = m - k + i + ib, m a( l, j ) = czero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_cungql pure module subroutine stdlib${ii}$_zungql( m, n, k, a, lda, tau, work, lwork, info ) !! ZUNGQL generates an M-by-N complex matrix Q with orthonormal columns, !! which is defined as the last N columns of a product of K elementary !! reflectors of order M !! Q = H(k) . . . H(2) H(1) !! as returned by ZGEQLF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, j, kk, l, ldwork, lwkopt, nb, nbmin, nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ .or. n>m ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = k - kk + 1, k, nb ib = min( nb, k-i+1 ) if( n-k+i>1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_zlarft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_zlarfb( 'LEFT', 'NO TRANSPOSE', 'BACKWARD','COLUMNWISE', m-k+i+ib-& 1_${ik}$, n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), ldwork ) end if ! apply h to rows 1:m-k+i+ib-1 of current block call stdlib${ii}$_zung2l( m-k+i+ib-1, ib, ib, a( 1_${ik}$, n-k+i ), lda,tau( i ), work, iinfo & ) ! set rows m-k+i+ib:m of current block to czero do j = n - k + i, n - k + i + ib - 1 do l = m - k + i + ib, m a( l, j ) = czero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_zungql #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ungql( m, n, k, a, lda, tau, work, lwork, info ) !! ZUNGQL: generates an M-by-N complex matrix Q with orthonormal columns, !! which is defined as the last N columns of a product of K elementary !! reflectors of order M !! Q = H(k) . . . H(2) H(1) !! as returned by ZGEQLF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, j, kk, l, ldwork, lwkopt, nb, nbmin, nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ .or. n>m ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = k - kk + 1, k, nb ib = min( nb, k-i+1 ) if( n-k+i>1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_${ci}$larft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_${ci}$larfb( 'LEFT', 'NO TRANSPOSE', 'BACKWARD','COLUMNWISE', m-k+i+ib-& 1_${ik}$, n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), ldwork ) end if ! apply h to rows 1:m-k+i+ib-1 of current block call stdlib${ii}$_${ci}$ung2l( m-k+i+ib-1, ib, ib, a( 1_${ik}$, n-k+i ), lda,tau( i ), work, iinfo & ) ! set rows m-k+i+ib:m of current block to czero do j = n - k + i, n - k + i + ib - 1 do l = m - k + i + ib, m a( l, j ) = czero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_${ci}$ungql #:endif #:endfor pure module subroutine stdlib${ii}$_cunmql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) !! CUNMQL overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by CGEQLF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran integer(${ik}$) :: i, i1, i2, i3, ib, iinfo, iwt, ldwork, lwkopt, mi, nb, nbmin, ni, nq, & nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_cunm2l( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n else mi = m end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_clarft( 'BACKWARD', 'COLUMNWISE', nq-k+i+ib-1, ib,a( 1_${ik}$, i ), lda, & tau( i ), work( iwt ), ldt ) if( left ) then ! h or h**h is applied to c(1:m-k+i+ib-1,1:n) mi = m - k + i + ib - 1_${ik}$ else ! h or h**h is applied to c(1:m,1:n-k+i+ib-1) ni = n - k + i + ib - 1_${ik}$ end if ! apply h or h**h call stdlib${ii}$_clarfb( side, trans, 'BACKWARD', 'COLUMNWISE', mi, ni,ib, a( 1_${ik}$, i ), & lda, work( iwt ), ldt, c, ldc,work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cunmql pure module subroutine stdlib${ii}$_zunmql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) !! ZUNMQL overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by ZGEQLF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran integer(${ik}$) :: i, i1, i2, i3, ib, iinfo, iwt, ldwork, lwkopt, mi, nb, nbmin, ni, nq, & nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_zunm2l( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n else mi = m end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_zlarft( 'BACKWARD', 'COLUMNWISE', nq-k+i+ib-1, ib,a( 1_${ik}$, i ), lda, & tau( i ), work( iwt ), ldt ) if( left ) then ! h or h**h is applied to c(1:m-k+i+ib-1,1:n) mi = m - k + i + ib - 1_${ik}$ else ! h or h**h is applied to c(1:m,1:n-k+i+ib-1) ni = n - k + i + ib - 1_${ik}$ end if ! apply h or h**h call stdlib${ii}$_zlarfb( side, trans, 'BACKWARD', 'COLUMNWISE', mi, ni,ib, a( 1_${ik}$, i ), & lda, work( iwt ), ldt, c, ldc,work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zunmql #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unmql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) !! ZUNMQL: overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by ZGEQLF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran integer(${ik}$) :: i, i1, i2, i3, ib, iinfo, iwt, ldwork, lwkopt, mi, nb, nbmin, ni, nq, & nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_${ci}$unm2l( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n else mi = m end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_${ci}$larft( 'BACKWARD', 'COLUMNWISE', nq-k+i+ib-1, ib,a( 1_${ik}$, i ), lda, & tau( i ), work( iwt ), ldt ) if( left ) then ! h or h**h is applied to c(1:m-k+i+ib-1,1:n) mi = m - k + i + ib - 1_${ik}$ else ! h or h**h is applied to c(1:m,1:n-k+i+ib-1) ni = n - k + i + ib - 1_${ik}$ end if ! apply h or h**h call stdlib${ii}$_${ci}$larfb( side, trans, 'BACKWARD', 'COLUMNWISE', mi, ni,ib, a( 1_${ik}$, i ), & lda, work( iwt ), ldt, c, ldc,work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$unmql #:endif #:endfor pure module subroutine stdlib${ii}$_cung2l( m, n, k, a, lda, tau, work, info ) !! CUNG2L generates an m by n complex matrix Q with orthonormal columns, !! which is defined as the last n columns of a product of k elementary !! reflectors of order m !! Q = H(k) . . . H(2) H(1) !! as returned by CGEQLF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ii, j, l ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ .or. n>m ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( ldam ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( ldam ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( ldam ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = k - kk + 1, k, nb ib = min( nb, k-i+1 ) if( n-k+i>1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_slarft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_slarfb( 'LEFT', 'NO TRANSPOSE', 'BACKWARD','COLUMNWISE', m-k+i+ib-& 1_${ik}$, n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), ldwork ) end if ! apply h to rows 1:m-k+i+ib-1 of current block call stdlib${ii}$_sorg2l( m-k+i+ib-1, ib, ib, a( 1_${ik}$, n-k+i ), lda,tau( i ), work, iinfo & ) ! set rows m-k+i+ib:m of current block to zero do j = n - k + i, n - k + i + ib - 1 do l = m - k + i + ib, m a( l, j ) = zero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_sorgql pure module subroutine stdlib${ii}$_dorgql( m, n, k, a, lda, tau, work, lwork, info ) !! DORGQL generates an M-by-N real matrix Q with orthonormal columns, !! which is defined as the last N columns of a product of K elementary !! reflectors of order M !! Q = H(k) . . . H(2) H(1) !! as returned by DGEQLF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, j, kk, l, ldwork, lwkopt, nb, nbmin, nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ .or. n>m ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = k - kk + 1, k, nb ib = min( nb, k-i+1 ) if( n-k+i>1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_dlarft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_dlarfb( 'LEFT', 'NO TRANSPOSE', 'BACKWARD','COLUMNWISE', m-k+i+ib-& 1_${ik}$, n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), ldwork ) end if ! apply h to rows 1:m-k+i+ib-1 of current block call stdlib${ii}$_dorg2l( m-k+i+ib-1, ib, ib, a( 1_${ik}$, n-k+i ), lda,tau( i ), work, iinfo & ) ! set rows m-k+i+ib:m of current block to zero do j = n - k + i, n - k + i + ib - 1 do l = m - k + i + ib, m a( l, j ) = zero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_dorgql #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orgql( m, n, k, a, lda, tau, work, lwork, info ) !! DORGQL: generates an M-by-N real matrix Q with orthonormal columns, !! which is defined as the last N columns of a product of K elementary !! reflectors of order M !! Q = H(k) . . . H(2) H(1) !! as returned by DGEQLF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iws, j, kk, l, ldwork, lwkopt, nb, nbmin, nx ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ .or. n>m ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=nbmin .and. nb0_${ik}$ ) then ! use blocked code do i = k - kk + 1, k, nb ib = min( nb, k-i+1 ) if( n-k+i>1_${ik}$ ) then ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_${ri}$larft( 'BACKWARD', 'COLUMNWISE', m-k+i+ib-1, ib,a( 1_${ik}$, n-k+i ), & lda, tau( i ), work, ldwork ) ! apply h to a(1:m-k+i+ib-1,1:n-k+i-1) from the left call stdlib${ii}$_${ri}$larfb( 'LEFT', 'NO TRANSPOSE', 'BACKWARD','COLUMNWISE', m-k+i+ib-& 1_${ik}$, n-k+i-1, ib,a( 1_${ik}$, n-k+i ), lda, work, ldwork, a, lda,work( ib+1 ), ldwork ) end if ! apply h to rows 1:m-k+i+ib-1 of current block call stdlib${ii}$_${ri}$org2l( m-k+i+ib-1, ib, ib, a( 1_${ik}$, n-k+i ), lda,tau( i ), work, iinfo & ) ! set rows m-k+i+ib:m of current block to zero do j = n - k + i, n - k + i + ib - 1 do l = m - k + i + ib, m a( l, j ) = zero end do end do end do end if work( 1_${ik}$ ) = iws return end subroutine stdlib${ii}$_${ri}$orgql #:endif #:endfor pure module subroutine stdlib${ii}$_sormql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) !! SORMQL overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by SGEQLF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran integer(${ik}$) :: i, i1, i2, i3, ib, iinfo, iwt, ldwork, lwkopt, mi, nb, nbmin, ni, nq, & nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_sorm2l( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n else mi = m end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_slarft( 'BACKWARD', 'COLUMNWISE', nq-k+i+ib-1, ib,a( 1_${ik}$, i ), lda, & tau( i ), work( iwt ), ldt ) if( left ) then ! h or h**t is applied to c(1:m-k+i+ib-1,1:n) mi = m - k + i + ib - 1_${ik}$ else ! h or h**t is applied to c(1:m,1:n-k+i+ib-1) ni = n - k + i + ib - 1_${ik}$ end if ! apply h or h**t call stdlib${ii}$_slarfb( side, trans, 'BACKWARD', 'COLUMNWISE', mi, ni,ib, a( 1_${ik}$, i ), & lda, work( iwt ), ldt, c, ldc,work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_sormql pure module subroutine stdlib${ii}$_dormql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) !! DORMQL overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by DGEQLF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran integer(${ik}$) :: i, i1, i2, i3, ib, iinfo, iwt, ldwork, lwkopt, mi, nb, nbmin, ni, nq, & nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_dorm2l( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n else mi = m end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_dlarft( 'BACKWARD', 'COLUMNWISE', nq-k+i+ib-1, ib,a( 1_${ik}$, i ), lda, & tau( i ), work( iwt ), ldt ) if( left ) then ! h or h**t is applied to c(1:m-k+i+ib-1,1:n) mi = m - k + i + ib - 1_${ik}$ else ! h or h**t is applied to c(1:m,1:n-k+i+ib-1) ni = n - k + i + ib - 1_${ik}$ end if ! apply h or h**t call stdlib${ii}$_dlarfb( side, trans, 'BACKWARD', 'COLUMNWISE', mi, ni,ib, a( 1_${ik}$, i ), & lda, work( iwt ), ldt, c, ldc,work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dormql #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ormql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) !! DORMQL: overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix defined as the product of k !! elementary reflectors !! Q = H(k) . . . H(2) H(1) !! as returned by DGEQLF. Q is of order M if SIDE = 'L' and of order N !! if SIDE = 'R'. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: left, lquery, notran integer(${ik}$) :: i, i1, i2, i3, ib, iinfo, iwt, ldwork, lwkopt, mi, nb, nbmin, ni, nq, & nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( k<0_${ik}$ .or. k>nq ) then info = -5_${ik}$ else if( lda1_${ik}$ .and. nb=k ) then ! use unblocked code call stdlib${ii}$_${ri}$orm2l( side, trans, m, n, k, a, lda, tau, c, ldc, work,iinfo ) else ! use blocked code iwt = 1_${ik}$ + nw*nb if( ( left .and. notran ) .or.( .not.left .and. .not.notran ) ) then i1 = 1_${ik}$ i2 = k i3 = nb else i1 = ( ( k-1 ) / nb )*nb + 1_${ik}$ i2 = 1_${ik}$ i3 = -nb end if if( left ) then ni = n else mi = m end if do i = i1, i2, i3 ib = min( nb, k-i+1 ) ! form the triangular factor of the block reflector ! h = h(i+ib-1) . . . h(i+1) h(i) call stdlib${ii}$_${ri}$larft( 'BACKWARD', 'COLUMNWISE', nq-k+i+ib-1, ib,a( 1_${ik}$, i ), lda, & tau( i ), work( iwt ), ldt ) if( left ) then ! h or h**t is applied to c(1:m-k+i+ib-1,1:n) mi = m - k + i + ib - 1_${ik}$ else ! h or h**t is applied to c(1:m,1:n-k+i+ib-1) ni = n - k + i + ib - 1_${ik}$ end if ! apply h or h**t call stdlib${ii}$_${ri}$larfb( side, trans, 'BACKWARD', 'COLUMNWISE', mi, ni,ib, a( 1_${ik}$, i ), & lda, work( iwt ), ldt, c, ldc,work, ldwork ) end do end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$ormql #:endif #:endfor pure module subroutine stdlib${ii}$_sorg2l( m, n, k, a, lda, tau, work, info ) !! SORG2L generates an m by n real matrix Q with orthonormal columns, !! which is defined as the last n columns of a product of k elementary !! reflectors of order m !! Q = H(k) . . . H(2) H(1) !! as returned by SGEQLF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ii, j, l ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ .or. n>m ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( ldam ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( ldam ) then info = -2_${ik}$ else if( k<0_${ik}$ .or. k>n ) then info = -3_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( ldanq ) then info = -5_${ik}$ else if( lda0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_sger( k-1, nrhs, -one, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_sscal( nrhs, one / ap( kc+k-1 ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_sswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_sger( k-2, nrhs, -one, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_sger( k-2, nrhs, -one, ap( kc-( k-1 ) ), 1_${ik}$,b( k-1, 1_${ik}$ ), ldb, b( 1_${ik}$, 1_${ik}$ & ), ldb ) ! multiply by the inverse of the diagonal block. akm1k = ap( kc+k-2 ) akm1 = ap( kc-1 ) / akm1k ak = ap( kc+k-1 ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do kc = kc - k + 1_${ik}$ k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_sgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, ap( kc ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + k k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_sgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, ap( kc ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) call stdlib${ii}$_sgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb,ap( kc+k ), 1_${ik}$, one, b( k+& 1_${ik}$, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + 2_${ik}$*k + 1_${ik}$ k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_dger( k-1, nrhs, -one, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_dscal( nrhs, one / ap( kc+k-1 ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_dswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_dger( k-2, nrhs, -one, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_dger( k-2, nrhs, -one, ap( kc-( k-1 ) ), 1_${ik}$,b( k-1, 1_${ik}$ ), ldb, b( 1_${ik}$, 1_${ik}$ & ), ldb ) ! multiply by the inverse of the diagonal block. akm1k = ap( kc+k-2 ) akm1 = ap( kc-1 ) / akm1k ak = ap( kc+k-1 ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do kc = kc - k + 1_${ik}$ k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_dgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, ap( kc ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + k k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_dgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, ap( kc ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) call stdlib${ii}$_dgemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb,ap( kc+k ), 1_${ik}$, one, b( k+& 1_${ik}$, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + 2_${ik}$*k + 1_${ik}$ k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ri}$ger( k-1, nrhs, -one, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_${ri}$scal( nrhs, one / ap( kc+k-1 ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_${ri}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_${ri}$ger( k-2, nrhs, -one, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ri}$ger( k-2, nrhs, -one, ap( kc-( k-1 ) ), 1_${ik}$,b( k-1, 1_${ik}$ ), ldb, b( 1_${ik}$, 1_${ik}$ & ), ldb ) ! multiply by the inverse of the diagonal block. akm1k = ap( kc+k-2 ) akm1 = ap( kc-1 ) / akm1k ak = ap( kc+k-1 ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do kc = kc - k + 1_${ik}$ k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, ap( kc ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + k k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb, ap( kc ),1_${ik}$, one, b( k, & 1_${ik}$ ), ldb ) call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', k-1, nrhs, -one, b, ldb,ap( kc+k ), 1_${ik}$, one, b( k+& 1_${ik}$, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + 2_${ik}$*k + 1_${ik}$ k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_cgeru( k-1, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_cscal( nrhs, cone / ap( kc+k-1 ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_cswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_cgeru( k-2, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgeru( k-2, nrhs, -cone, ap( kc-( k-1 ) ), 1_${ik}$,b( k-1, 1_${ik}$ ), ldb, b( 1_${ik}$, & 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. akm1k = ap( kc+k-2 ) akm1 = ap( kc-1 ) / akm1k ak = ap( kc+k-1 ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do kc = kc - k + 1_${ik}$ k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_cgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, ap( kc ),1_${ik}$, cone, b( k,& 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + k k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_cgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, ap( kc ),1_${ik}$, cone, b( k,& 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb,ap( kc+k ), 1_${ik}$, cone, b( & k+1, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + 2_${ik}$*k + 1_${ik}$ k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_zgeru( k-1, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_zscal( nrhs, cone / ap( kc+k-1 ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_zswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_zgeru( k-2, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgeru( k-2, nrhs, -cone, ap( kc-( k-1 ) ), 1_${ik}$,b( k-1, 1_${ik}$ ), ldb, b( 1_${ik}$, & 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. akm1k = ap( kc+k-2 ) akm1 = ap( kc-1 ) / akm1k ak = ap( kc+k-1 ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do kc = kc - k + 1_${ik}$ k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_zgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, ap( kc ),1_${ik}$, cone, b( k,& 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + k k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_zgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, ap( kc ),1_${ik}$, cone, b( k,& 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb,ap( kc+k ), 1_${ik}$, cone, b( & k+1, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + 2_${ik}$*k + 1_${ik}$ k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ci}$geru( k-1, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_${ci}$scal( nrhs, cone / ap( kc+k-1 ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_${ci}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_${ci}$geru( k-2, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$geru( k-2, nrhs, -cone, ap( kc-( k-1 ) ), 1_${ik}$,b( k-1, 1_${ik}$ ), ldb, b( 1_${ik}$, & 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. akm1k = ap( kc+k-2 ) akm1 = ap( kc-1 ) / akm1k ak = ap( kc+k-1 ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do kc = kc - k + 1_${ik}$ k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ci}$gemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, ap( kc ),1_${ik}$, cone, b( k,& 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + k k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. call stdlib${ii}$_${ci}$gemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb, ap( kc ),1_${ik}$, cone, b( k,& 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'TRANSPOSE', k-1, nrhs, -cone, b, ldb,ap( kc+k ), 1_${ik}$, cone, b( & k+1, 1_${ik}$ ), ldb ) ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + 2_${ik}$*k + 1_${ik}$ k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0 .and. ap( kp )==zero )return kp = kp - info end do else ! lower triangular storage: examine d from top to bottom. kp = 1_${ik}$ do info = 1, n if( ipiv( info )>0 .and. ap( kp )==zero )return kp = kp + n - info + 1_${ik}$ end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 kcnext = kc + k if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc+k-1 ) = one / ap( kc+k-1 ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_scopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_sspmv( uplo, k-1, -one, ap, work, 1_${ik}$, zero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_sdot( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( ap( kcnext+k-1 ) ) ak = ap( kc+k-1 ) / t akp1 = ap( kcnext+k ) / t akkp1 = ap( kcnext+k-1 ) / t d = t*( ak*akp1-one ) ap( kc+k-1 ) = akp1 / d ap( kcnext+k ) = ak / d ap( kcnext+k-1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_scopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_sspmv( uplo, k-1, -one, ap, work, 1_${ik}$, zero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_sdot( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) ap( kcnext+k-1 ) = ap( kcnext+k-1 ) -stdlib${ii}$_sdot( k-1, ap( kc ), 1_${ik}$, ap( & kcnext ),1_${ik}$ ) call stdlib${ii}$_scopy( k-1, ap( kcnext ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_sspmv( uplo, k-1, -one, ap, work, 1_${ik}$, zero,ap( kcnext ), 1_${ik}$ ) ap( kcnext+k ) = ap( kcnext+k ) -stdlib${ii}$_sdot( k-1, work, 1_${ik}$, ap( kcnext ), 1_${ik}$ ) end if kstep = 2_${ik}$ kcnext = kcnext + k + 1_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) kpc = ( kp-1 )*kp / 2_${ik}$ + 1_${ik}$ call stdlib${ii}$_sswap( kp-1, ap( kc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, k - 1 kx = kx + j - 1_${ik}$ temp = ap( kc+j-1 ) ap( kc+j-1 ) = ap( kx ) ap( kx ) = temp end do temp = ap( kc+k-1 ) ap( kc+k-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = temp if( kstep==2_${ik}$ ) then temp = ap( kc+k+k-1 ) ap( kc+k+k-1 ) = ap( kc+k+kp-1 ) ap( kc+k+kp-1 ) = temp end if end if k = k + kstep kc = kcnext go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. npp = n*( n+1 ) / 2_${ik}$ k = n kc = npp 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 kcnext = kc - ( n-k+2 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc ) = one / ap( kc ) ! compute column k of the inverse. if( k0 .and. ap( kp )==zero )return kp = kp - info end do else ! lower triangular storage: examine d from top to bottom. kp = 1_${ik}$ do info = 1, n if( ipiv( info )>0 .and. ap( kp )==zero )return kp = kp + n - info + 1_${ik}$ end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 kcnext = kc + k if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc+k-1 ) = one / ap( kc+k-1 ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_dcopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dspmv( uplo, k-1, -one, ap, work, 1_${ik}$, zero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_ddot( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( ap( kcnext+k-1 ) ) ak = ap( kc+k-1 ) / t akp1 = ap( kcnext+k ) / t akkp1 = ap( kcnext+k-1 ) / t d = t*( ak*akp1-one ) ap( kc+k-1 ) = akp1 / d ap( kcnext+k ) = ak / d ap( kcnext+k-1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_dcopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dspmv( uplo, k-1, -one, ap, work, 1_${ik}$, zero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_ddot( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) ap( kcnext+k-1 ) = ap( kcnext+k-1 ) -stdlib${ii}$_ddot( k-1, ap( kc ), 1_${ik}$, ap( & kcnext ),1_${ik}$ ) call stdlib${ii}$_dcopy( k-1, ap( kcnext ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dspmv( uplo, k-1, -one, ap, work, 1_${ik}$, zero,ap( kcnext ), 1_${ik}$ ) ap( kcnext+k ) = ap( kcnext+k ) -stdlib${ii}$_ddot( k-1, work, 1_${ik}$, ap( kcnext ), 1_${ik}$ ) end if kstep = 2_${ik}$ kcnext = kcnext + k + 1_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) kpc = ( kp-1 )*kp / 2_${ik}$ + 1_${ik}$ call stdlib${ii}$_dswap( kp-1, ap( kc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, k - 1 kx = kx + j - 1_${ik}$ temp = ap( kc+j-1 ) ap( kc+j-1 ) = ap( kx ) ap( kx ) = temp end do temp = ap( kc+k-1 ) ap( kc+k-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = temp if( kstep==2_${ik}$ ) then temp = ap( kc+k+k-1 ) ap( kc+k+k-1 ) = ap( kc+k+kp-1 ) ap( kc+k+kp-1 ) = temp end if end if k = k + kstep kc = kcnext go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. npp = n*( n+1 ) / 2_${ik}$ k = n kc = npp 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 kcnext = kc - ( n-k+2 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc ) = one / ap( kc ) ! compute column k of the inverse. if( k0 .and. ap( kp )==zero )return kp = kp - info end do else ! lower triangular storage: examine d from top to bottom. kp = 1_${ik}$ do info = 1, n if( ipiv( info )>0 .and. ap( kp )==zero )return kp = kp + n - info + 1_${ik}$ end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 kcnext = kc + k if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc+k-1 ) = one / ap( kc+k-1 ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$spmv( uplo, k-1, -one, ap, work, 1_${ik}$, zero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_${ri}$dot( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( ap( kcnext+k-1 ) ) ak = ap( kc+k-1 ) / t akp1 = ap( kcnext+k ) / t akkp1 = ap( kcnext+k-1 ) / t d = t*( ak*akp1-one ) ap( kc+k-1 ) = akp1 / d ap( kcnext+k ) = ak / d ap( kcnext+k-1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$spmv( uplo, k-1, -one, ap, work, 1_${ik}$, zero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_${ri}$dot( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) ap( kcnext+k-1 ) = ap( kcnext+k-1 ) -stdlib${ii}$_${ri}$dot( k-1, ap( kc ), 1_${ik}$, ap( & kcnext ),1_${ik}$ ) call stdlib${ii}$_${ri}$copy( k-1, ap( kcnext ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$spmv( uplo, k-1, -one, ap, work, 1_${ik}$, zero,ap( kcnext ), 1_${ik}$ ) ap( kcnext+k ) = ap( kcnext+k ) -stdlib${ii}$_${ri}$dot( k-1, work, 1_${ik}$, ap( kcnext ), 1_${ik}$ ) end if kstep = 2_${ik}$ kcnext = kcnext + k + 1_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) kpc = ( kp-1 )*kp / 2_${ik}$ + 1_${ik}$ call stdlib${ii}$_${ri}$swap( kp-1, ap( kc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, k - 1 kx = kx + j - 1_${ik}$ temp = ap( kc+j-1 ) ap( kc+j-1 ) = ap( kx ) ap( kx ) = temp end do temp = ap( kc+k-1 ) ap( kc+k-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = temp if( kstep==2_${ik}$ ) then temp = ap( kc+k+k-1 ) ap( kc+k+k-1 ) = ap( kc+k+kp-1 ) ap( kc+k+kp-1 ) = temp end if end if k = k + kstep kc = kcnext go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. npp = n*( n+1 ) / 2_${ik}$ k = n kc = npp 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 kcnext = kc - ( n-k+2 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc ) = one / ap( kc ) ! compute column k of the inverse. if( k0 .and. ap( kp )==czero )return kp = kp - info end do else ! lower triangular storage: examine d from top to bottom. kp = 1_${ik}$ do info = 1, n if( ipiv( info )>0 .and. ap( kp )==czero )return kp = kp + n - info + 1_${ik}$ end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 kcnext = kc + k if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc+k-1 ) = cone / ap( kc+k-1 ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_cspmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_cdotu( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = ap( kcnext+k-1 ) ak = ap( kc+k-1 ) / t akp1 = ap( kcnext+k ) / t akkp1 = ap( kcnext+k-1 ) / t d = t*( ak*akp1-cone ) ap( kc+k-1 ) = akp1 / d ap( kcnext+k ) = ak / d ap( kcnext+k-1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_cspmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_cdotu( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) ap( kcnext+k-1 ) = ap( kcnext+k-1 ) -stdlib${ii}$_cdotu( k-1, ap( kc ), 1_${ik}$, ap( & kcnext ),1_${ik}$ ) call stdlib${ii}$_ccopy( k-1, ap( kcnext ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_cspmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kcnext ), 1_${ik}$ ) ap( kcnext+k ) = ap( kcnext+k ) -stdlib${ii}$_cdotu( k-1, work, 1_${ik}$, ap( kcnext ), 1_${ik}$ ) end if kstep = 2_${ik}$ kcnext = kcnext + k + 1_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) kpc = ( kp-1 )*kp / 2_${ik}$ + 1_${ik}$ call stdlib${ii}$_cswap( kp-1, ap( kc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, k - 1 kx = kx + j - 1_${ik}$ temp = ap( kc+j-1 ) ap( kc+j-1 ) = ap( kx ) ap( kx ) = temp end do temp = ap( kc+k-1 ) ap( kc+k-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = temp if( kstep==2_${ik}$ ) then temp = ap( kc+k+k-1 ) ap( kc+k+k-1 ) = ap( kc+k+kp-1 ) ap( kc+k+kp-1 ) = temp end if end if k = k + kstep kc = kcnext go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. npp = n*( n+1 ) / 2_${ik}$ k = n kc = npp 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 kcnext = kc - ( n-k+2 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc ) = cone / ap( kc ) ! compute column k of the inverse. if( k0 .and. ap( kp )==czero )return kp = kp - info end do else ! lower triangular storage: examine d from top to bottom. kp = 1_${ik}$ do info = 1, n if( ipiv( info )>0 .and. ap( kp )==czero )return kp = kp + n - info + 1_${ik}$ end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 kcnext = kc + k if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc+k-1 ) = cone / ap( kc+k-1 ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zspmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_zdotu( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = ap( kcnext+k-1 ) ak = ap( kc+k-1 ) / t akp1 = ap( kcnext+k ) / t akkp1 = ap( kcnext+k-1 ) / t d = t*( ak*akp1-cone ) ap( kc+k-1 ) = akp1 / d ap( kcnext+k ) = ak / d ap( kcnext+k-1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zspmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_zdotu( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) ap( kcnext+k-1 ) = ap( kcnext+k-1 ) -stdlib${ii}$_zdotu( k-1, ap( kc ), 1_${ik}$, ap( & kcnext ),1_${ik}$ ) call stdlib${ii}$_zcopy( k-1, ap( kcnext ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zspmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kcnext ), 1_${ik}$ ) ap( kcnext+k ) = ap( kcnext+k ) -stdlib${ii}$_zdotu( k-1, work, 1_${ik}$, ap( kcnext ), 1_${ik}$ ) end if kstep = 2_${ik}$ kcnext = kcnext + k + 1_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) kpc = ( kp-1 )*kp / 2_${ik}$ + 1_${ik}$ call stdlib${ii}$_zswap( kp-1, ap( kc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, k - 1 kx = kx + j - 1_${ik}$ temp = ap( kc+j-1 ) ap( kc+j-1 ) = ap( kx ) ap( kx ) = temp end do temp = ap( kc+k-1 ) ap( kc+k-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = temp if( kstep==2_${ik}$ ) then temp = ap( kc+k+k-1 ) ap( kc+k+k-1 ) = ap( kc+k+kp-1 ) ap( kc+k+kp-1 ) = temp end if end if k = k + kstep kc = kcnext go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. npp = n*( n+1 ) / 2_${ik}$ k = n kc = npp 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 kcnext = kc - ( n-k+2 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc ) = cone / ap( kc ) ! compute column k of the inverse. if( k0 .and. ap( kp )==czero )return kp = kp - info end do else ! lower triangular storage: examine d from top to bottom. kp = 1_${ik}$ do info = 1, n if( ipiv( info )>0 .and. ap( kp )==czero )return kp = kp + n - info + 1_${ik}$ end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 kcnext = kc + k if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc+k-1 ) = cone / ap( kc+k-1 ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$spmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_${ci}$dotu( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = ap( kcnext+k-1 ) ak = ap( kc+k-1 ) / t akp1 = ap( kcnext+k ) / t akkp1 = ap( kcnext+k-1 ) / t d = t*( ak*akp1-cone ) ap( kc+k-1 ) = akp1 / d ap( kcnext+k ) = ak / d ap( kcnext+k-1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$spmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero, ap( kc ),1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -stdlib${ii}$_${ci}$dotu( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ) ap( kcnext+k-1 ) = ap( kcnext+k-1 ) -stdlib${ii}$_${ci}$dotu( k-1, ap( kc ), 1_${ik}$, ap( & kcnext ),1_${ik}$ ) call stdlib${ii}$_${ci}$copy( k-1, ap( kcnext ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$spmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kcnext ), 1_${ik}$ ) ap( kcnext+k ) = ap( kcnext+k ) -stdlib${ii}$_${ci}$dotu( k-1, work, 1_${ik}$, ap( kcnext ), 1_${ik}$ ) end if kstep = 2_${ik}$ kcnext = kcnext + k + 1_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) kpc = ( kp-1 )*kp / 2_${ik}$ + 1_${ik}$ call stdlib${ii}$_${ci}$swap( kp-1, ap( kc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, k - 1 kx = kx + j - 1_${ik}$ temp = ap( kc+j-1 ) ap( kc+j-1 ) = ap( kx ) ap( kx ) = temp end do temp = ap( kc+k-1 ) ap( kc+k-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = temp if( kstep==2_${ik}$ ) then temp = ap( kc+k+k-1 ) ap( kc+k+k-1 ) = ap( kc+k+kp-1 ) ap( kc+k+kp-1 ) = temp end if end if k = k + kstep kc = kcnext go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. npp = n*( n+1 ) / 2_${ik}$ k = n kc = npp 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 kcnext = kc - ( n-k+2 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc ) = cone / ap( kc ) ! compute column k of the inverse. if( ksafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_ssptrs( uplo, n, 1_${ik}$, afp, ipiv, work( n+1 ), n, info ) call stdlib${ii}$_saxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_slacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_slacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_ssptrs( uplo, n, 1_${ik}$, afp, ipiv, work( n+1 ), n,info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_ssptrs( uplo, n, 1_${ik}$, afp, ipiv, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_ssprfs pure module subroutine stdlib${ii}$_dsprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, work,& !! DSPRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite !! and packed, and provides error bounds and backward error estimates !! for the solution. iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: afp(*), ap(*), b(ldb,*) real(dp), intent(out) :: berr(*), ferr(*), work(*) real(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_dsptrs( uplo, n, 1_${ik}$, afp, ipiv, work( n+1 ), n, info ) call stdlib${ii}$_daxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_dlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_dlacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_dsptrs( uplo, n, 1_${ik}$, afp, ipiv, work( n+1 ), n,info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_dsptrs( uplo, n, 1_${ik}$, afp, ipiv, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_dsprfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, work,& !! DSPRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite !! and packed, and provides error bounds and backward error estimates !! for the solution. iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: afp(*), ap(*), b(ldb,*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) real(${rk}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(${rk}$) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ri}$sptrs( uplo, n, 1_${ik}$, afp, ipiv, work( n+1 ), n, info ) call stdlib${ii}$_${ri}$axpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ri}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ri}$lacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_${ri}$sptrs( uplo, n, 1_${ik}$, afp, ipiv, work( n+1 ), n,info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_${ri}$sptrs( uplo, n, 1_${ik}$, afp, ipiv, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ri}$sprfs #:endif #:endfor pure module subroutine stdlib${ii}$_csprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, work,& !! CSPRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite !! and packed, and provides error bounds and backward error estimates !! for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: afp(*), ap(*), b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_csptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) call stdlib${ii}$_caxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_csptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_csptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_csprfs pure module subroutine stdlib${ii}$_zsprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, work,& !! ZSPRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite !! and packed, and provides error bounds and backward error estimates !! for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: afp(*), ap(*), b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_zsptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) call stdlib${ii}$_zaxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_zsptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_zsptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_zsprfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$sprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, work,& !! ZSPRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric indefinite !! and packed, and provides error bounds and backward error estimates !! for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: afp(*), ap(*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ci}$sptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) call stdlib${ii}$_${ci}$axpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_${ci}$sptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$sptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ci}$sprfs #:endif #:endfor pure module subroutine stdlib${ii}$_ssycon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,iwork, info ) !! SSYCON_ROOK estimates the reciprocal of the condition number (in the !! 1-norm) of a real symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by SSYTRF_ROOK. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(sp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_slacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_ssytrs_rook( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_ssycon_rook pure module subroutine stdlib${ii}$_dsycon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,iwork, info ) !! DSYCON_ROOK estimates the reciprocal of the condition number (in the !! 1-norm) of a real symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by DSYTRF_ROOK. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(dp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_dlacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_dsytrs_rook( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_dsycon_rook #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sycon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,iwork, info ) !! DSYCON_ROOK: estimates the reciprocal of the condition number (in the !! 1-norm) of a real symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by DSYTRF_ROOK. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(${rk}$), intent(in) :: anorm real(${rk}$), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(${rk}$) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_${ri}$lacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_${ri}$sytrs_rook( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_${ri}$sycon_rook #:endif #:endfor pure module subroutine stdlib${ii}$_csycon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) !! CSYCON_ROOK estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by CSYTRF_ROOK. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(sp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==czero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_csytrs_rook( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_csycon_rook pure module subroutine stdlib${ii}$_zsycon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) !! ZSYCON_ROOK estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by ZSYTRF_ROOK. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(dp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==czero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_zsytrs_rook( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_zsycon_rook #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$sycon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) !! ZSYCON_ROOK: estimates the reciprocal of the condition number (in the !! 1-norm) of a complex symmetric matrix A using the factorization !! A = U*D*U**T or A = L*D*L**T computed by ZSYTRF_ROOK. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(in) :: anorm real(${ck}$), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(${ck}$) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==czero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**t) or inv(u*d*u**t). call stdlib${ii}$_${ci}$sytrs_rook( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_${ci}$sycon_rook #:endif #:endfor pure module subroutine stdlib${ii}$_ssytrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) !! SSYTRF_ROOK computes the factorization of a real symmetric matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method. !! The form of the factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_slasyf_rook( uplo, k, nb, kb, a, lda,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_ssytf2_rook( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_slasyf_rook; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_slasyf_rook( uplo, n-k+1, nb, kb, a( k, k ), lda,ipiv( k ), work, & ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_ssytf2_rook( uplo, n-k+1, a( k, k ), lda, ipiv( k ),iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_ssytrf_rook pure module subroutine stdlib${ii}$_dsytrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) !! DSYTRF_ROOK computes the factorization of a real symmetric matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method. !! The form of the factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_dlasyf_rook( uplo, k, nb, kb, a, lda,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_dsytf2_rook( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_dlasyf_rook; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_dlasyf_rook( uplo, n-k+1, nb, kb, a( k, k ), lda,ipiv( k ), work, & ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_dsytf2_rook( uplo, n-k+1, a( k, k ), lda, ipiv( k ),iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dsytrf_rook #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sytrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) !! DSYTRF_ROOK: computes the factorization of a real symmetric matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method. !! The form of the factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_${ri}$lasyf_rook( uplo, k, nb, kb, a, lda,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_${ri}$sytf2_rook( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_${ri}$lasyf_rook; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_${ri}$lasyf_rook( uplo, n-k+1, nb, kb, a( k, k ), lda,ipiv( k ), work, & ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_${ri}$sytf2_rook( uplo, n-k+1, a( k, k ), lda, ipiv( k ),iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$sytrf_rook #:endif #:endfor pure module subroutine stdlib${ii}$_csytrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) !! CSYTRF_ROOK computes the factorization of a complex symmetric matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method. !! The form of the factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_clasyf_rook( uplo, k, nb, kb, a, lda,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_csytf2_rook( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_clasyf_rook; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_clasyf_rook( uplo, n-k+1, nb, kb, a( k, k ), lda,ipiv( k ), work, & ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_csytf2_rook( uplo, n-k+1, a( k, k ), lda, ipiv( k ),iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_csytrf_rook pure module subroutine stdlib${ii}$_zsytrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) !! ZSYTRF_ROOK computes the factorization of a complex symmetric matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method. !! The form of the factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_zlasyf_rook( uplo, k, nb, kb, a, lda,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_zsytf2_rook( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_zlasyf_rook; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_zlasyf_rook( uplo, n-k+1, nb, kb, a( k, k ), lda,ipiv( k ), work, & ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_zsytf2_rook( uplo, n-k+1, a( k, k ), lda, ipiv( k ),iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zsytrf_rook #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$sytrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) !! ZSYTRF_ROOK: computes the factorization of a complex symmetric matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method. !! The form of the factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is symmetric and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_${ci}$lasyf_rook( uplo, k, nb, kb, a, lda,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_${ci}$sytf2_rook( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_${ci}$lasyf_rook; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_${ci}$lasyf_rook( uplo, n-k+1, nb, kb, a( k, k ), lda,ipiv( k ), work, & ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_${ci}$sytf2_rook( uplo, n-k+1, a( k, k ), lda, ipiv( k ),iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$sytrf_rook #:endif #:endfor pure module subroutine stdlib${ii}$_slasyf_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) !! SLASYF_ROOK computes a partial factorization of a real symmetric !! matrix A using the bounded Bunch-Kaufman ("rook") diagonal !! pivoting method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! SLASYF_ROOK is an auxiliary routine called by SSYTRF_ROOK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars logical(lk) :: done integer(${ik}$) :: imax, itemp, j, jb, jj, jmax, jp1, jp2, k, kk, kw, kkw, kp, kstep, p, & ii real(sp) :: absakk, alpha, colmax, d11, d12, d21, d22, stemp, r1, rowmax, t, & sfmin ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight ! compute machine safe minimum sfmin = stdlib${ii}$_slamch( 'S' ) if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_isamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = abs( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_scopy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_isamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) stemp = abs( w( itemp, kw-1 ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(abs( w( imax, kw-1 ) )1_${ik}$ ) then if( abs( a( k, k ) )>=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_sscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = one / ( d11*d22-one ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_sgemv( 'NO TRANSPOSE', jj-j+1, n-k, -one,a( j, k+1 ), lda, w( jj, & kw+1 ), ldw, one,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -one, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,one, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n j = k + 1_${ik}$ 60 continue kstep = 1_${ik}$ jp1 = 1_${ik}$ jj = j jp2 = ipiv( j ) if( jp2<0_${ik}$ ) then jp2 = -jp2 j = j + 1_${ik}$ jp1 = -ipiv( j ) kstep = 2_${ik}$ end if j = j + 1_${ik}$ if( jp2/=jj .and. j<=n )call stdlib${ii}$_sswap( n-j+1, a( jp2, j ), lda, a( jj, j ), & lda ) jj = j - 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_sswap( n-j+1, a( jp1, j ), lda, a( jj, j & ), lda ) if( j<=n )go to 60 ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_scopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, one, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k+1, k-1, -one,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,one, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_isamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = abs( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( w( imax, k+1 ) )=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_sscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k=1_${ik}$ )call stdlib${ii}$_sswap( j, a( jp2, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) jj = j + 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_sswap( j, a( jp1, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), & lda ) if( j>=1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_slasyf_rook pure module subroutine stdlib${ii}$_dlasyf_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) !! DLASYF_ROOK computes a partial factorization of a real symmetric !! matrix A using the bounded Bunch-Kaufman ("rook") diagonal !! pivoting method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! DLASYF_ROOK is an auxiliary routine called by DSYTRF_ROOK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(dp), parameter :: sevten = 17.0e+0_dp ! Local Scalars logical(lk) :: done integer(${ik}$) :: imax, itemp, j, jb, jj, jmax, jp1, jp2, k, kk, kw, kkw, kp, kstep, p, & ii real(dp) :: absakk, alpha, colmax, d11, d12, d21, d22, dtemp, r1, rowmax, t, & sfmin ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight ! compute machine safe minimum sfmin = stdlib${ii}$_dlamch( 'S' ) if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_idamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = abs( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_dcopy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_idamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = abs( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(abs( w( imax, kw-1 ) )1_${ik}$ ) then if( abs( a( k, k ) )>=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_dscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = one / ( d11*d22-one ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_dgemv( 'NO TRANSPOSE', jj-j+1, n-k, -one,a( j, k+1 ), lda, w( jj, & kw+1 ), ldw, one,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -one, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,one, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n j = k + 1_${ik}$ 60 continue kstep = 1_${ik}$ jp1 = 1_${ik}$ jj = j jp2 = ipiv( j ) if( jp2<0_${ik}$ ) then jp2 = -jp2 j = j + 1_${ik}$ jp1 = -ipiv( j ) kstep = 2_${ik}$ end if j = j + 1_${ik}$ if( jp2/=jj .and. j<=n )call stdlib${ii}$_dswap( n-j+1, a( jp2, j ), lda, a( jj, j ), & lda ) jj = j - 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_dswap( n-j+1, a( jp1, j ), lda, a( jj, j & ), lda ) if( j<=n )go to 60 ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_dcopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, one, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k+1, k-1, -one,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,one, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_idamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = abs( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( w( imax, k+1 ) )=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_dscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k=1_${ik}$ )call stdlib${ii}$_dswap( j, a( jp2, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) jj = j + 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_dswap( j, a( jp1, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), & lda ) if( j>=1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_dlasyf_rook #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasyf_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) !! DLASYF_ROOK: computes a partial factorization of a real symmetric !! matrix A using the bounded Bunch-Kaufman ("rook") diagonal !! pivoting method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! DLASYF_ROOK is an auxiliary routine called by DSYTRF_ROOK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: sevten = 17.0e+0_${rk}$ ! Local Scalars logical(lk) :: done integer(${ik}$) :: imax, itemp, j, jb, jj, jmax, jp1, jp2, k, kk, kw, kkw, kp, kstep, p, & ii real(${rk}$) :: absakk, alpha, colmax, d11, d12, d21, d22, dtemp, r1, rowmax, t, & sfmin ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight ! compute machine safe minimum sfmin = stdlib${ii}$_${ri}$lamch( 'S' ) if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_i${ri}$amax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = abs( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_${ri}$copy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_i${ri}$amax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = abs( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(abs( w( imax, kw-1 ) )1_${ik}$ ) then if( abs( a( k, k ) )>=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_${ri}$scal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = one / ( d11*d22-one ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', jj-j+1, n-k, -one,a( j, k+1 ), lda, w( jj, & kw+1 ), ldw, one,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -one, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,one, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n j = k + 1_${ik}$ 60 continue kstep = 1_${ik}$ jp1 = 1_${ik}$ jj = j jp2 = ipiv( j ) if( jp2<0_${ik}$ ) then jp2 = -jp2 j = j + 1_${ik}$ jp1 = -ipiv( j ) kstep = 2_${ik}$ end if j = j + 1_${ik}$ if( jp2/=jj .and. j<=n )call stdlib${ii}$_${ri}$swap( n-j+1, a( jp2, j ), lda, a( jj, j ), & lda ) jj = j - 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_${ri}$swap( n-j+1, a( jp1, j ), lda, a( jj, j & ), lda ) if( j<=n )go to 60 ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_${ri}$copy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, one, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -one,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,one, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_i${ri}$amax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = abs( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( w( imax, k+1 ) )=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_${ri}$scal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k=1_${ik}$ )call stdlib${ii}$_${ri}$swap( j, a( jp2, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) jj = j + 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_${ri}$swap( j, a( jp1, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), & lda ) if( j>=1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_${ri}$lasyf_rook #:endif #:endfor pure module subroutine stdlib${ii}$_clasyf_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) !! CLASYF_ROOK computes a partial factorization of a complex symmetric !! matrix A using the bounded Bunch-Kaufman ("rook") diagonal !! pivoting method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! CLASYF_ROOK is an auxiliary routine called by CSYTRF_ROOK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars logical(lk) :: done integer(${ik}$) :: imax, itemp, j, jb, jj, jmax, jp1, jp2, k, kk, kw, kkw, kp, kstep, p, & ii real(sp) :: absakk, alpha, colmax, rowmax, stemp, sfmin complex(sp) :: d11, d12, d21, d22, r1, t, z ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=sp) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight ! compute machine safe minimum sfmin = stdlib${ii}$_slamch( 'S' ) if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_ccopy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_icamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) stemp = cabs1( w( itemp, kw-1 ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(cabs1( w( imax, kw-1 ) )1_${ik}$ ) then if( cabs1( a( k, k ) )>=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_cscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = cone / ( d11*d22-cone ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_cgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n j = k + 1_${ik}$ 60 continue kstep = 1_${ik}$ jp1 = 1_${ik}$ jj = j jp2 = ipiv( j ) if( jp2<0_${ik}$ ) then jp2 = -jp2 j = j + 1_${ik}$ jp1 = -ipiv( j ) kstep = 2_${ik}$ end if j = j + 1_${ik}$ if( jp2/=jj .and. j<=n )call stdlib${ii}$_cswap( n-j+1, a( jp2, j ), lda, a( jj, j ), & lda ) jj = j - 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_cswap( n-j+1, a( jp1, j ), lda, a( jj, j & ), lda ) if( j<=n )go to 60 ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_ccopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, cone, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_icamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( cabs1( w( imax, k+1 ) )=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_cscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k=1_${ik}$ )call stdlib${ii}$_cswap( j, a( jp2, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) jj = j + 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_cswap( j, a( jp1, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), & lda ) if( j>=1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_clasyf_rook pure module subroutine stdlib${ii}$_zlasyf_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) !! ZLASYF_ROOK computes a partial factorization of a complex symmetric !! matrix A using the bounded Bunch-Kaufman ("rook") diagonal !! pivoting method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! ZLASYF_ROOK is an auxiliary routine called by ZSYTRF_ROOK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(dp), parameter :: sevten = 17.0e+0_dp ! Local Scalars logical(lk) :: done integer(${ik}$) :: imax, itemp, j, jb, jj, jmax, jp1, jp2, k, kk, kw, kkw, kp, kstep, p, & ii real(dp) :: absakk, alpha, colmax, rowmax, dtemp, sfmin complex(dp) :: d11, d12, d21, d22, r1, t, z ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=dp) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight ! compute machine safe minimum sfmin = stdlib${ii}$_dlamch( 'S' ) if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_zcopy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_izamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = cabs1( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(cabs1( w( imax, kw-1 ) )1_${ik}$ ) then if( cabs1( a( k, k ) )>=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_zscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = cone / ( d11*d22-cone ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_zgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n j = k + 1_${ik}$ 60 continue kstep = 1_${ik}$ jp1 = 1_${ik}$ jj = j jp2 = ipiv( j ) if( jp2<0_${ik}$ ) then jp2 = -jp2 j = j + 1_${ik}$ jp1 = -ipiv( j ) kstep = 2_${ik}$ end if j = j + 1_${ik}$ if( jp2/=jj .and. j<=n )call stdlib${ii}$_zswap( n-j+1, a( jp2, j ), lda, a( jj, j ), & lda ) jj = j - 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_zswap( n-j+1, a( jp1, j ), lda, a( jj, j & ), lda ) if( j<=n )go to 60 ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_zcopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, cone, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_izamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( cabs1( w( imax, k+1 ) )=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_zscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k=1_${ik}$ )call stdlib${ii}$_zswap( j, a( jp2, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) jj = j + 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_zswap( j, a( jp1, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), & lda ) if( j>=1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_zlasyf_rook #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lasyf_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) !! ZLASYF_ROOK: computes a partial factorization of a complex symmetric !! matrix A using the bounded Bunch-Kaufman ("rook") diagonal !! pivoting method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! ZLASYF_ROOK is an auxiliary routine called by ZSYTRF_ROOK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: sevten = 17.0e+0_${ck}$ ! Local Scalars logical(lk) :: done integer(${ik}$) :: imax, itemp, j, jb, jj, jmax, jp1, jp2, k, kk, kw, kkw, kp, kstep, p, & ii real(${ck}$) :: absakk, alpha, colmax, rowmax, dtemp, sfmin complex(${ck}$) :: d11, d12, d21, d22, r1, t, z ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=${ck}$) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight ! compute machine safe minimum sfmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_${ci}$copy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_i${ci}$amax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = cabs1( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(cabs1( w( imax, kw-1 ) )1_${ik}$ ) then if( cabs1( a( k, k ) )>=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_${ci}$scal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = cone / ( d11*d22-cone ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n j = k + 1_${ik}$ 60 continue kstep = 1_${ik}$ jp1 = 1_${ik}$ jj = j jp2 = ipiv( j ) if( jp2<0_${ik}$ ) then jp2 = -jp2 j = j + 1_${ik}$ jp1 = -ipiv( j ) kstep = 2_${ik}$ end if j = j + 1_${ik}$ if( jp2/=jj .and. j<=n )call stdlib${ii}$_${ci}$swap( n-j+1, a( jp2, j ), lda, a( jj, j ), & lda ) jj = j - 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_${ci}$swap( n-j+1, a( jp1, j ), lda, a( jj, j & ), lda ) if( j<=n )go to 60 ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_${ci}$copy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, cone, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_i${ci}$amax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( cabs1( w( imax, k+1 ) )=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_${ci}$scal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k=1_${ik}$ )call stdlib${ii}$_${ci}$swap( j, a( jp2, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) jj = j + 1_${ik}$ if( jp1/=jj .and. kstep==2_${ik}$ )call stdlib${ii}$_${ci}$swap( j, a( jp1, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), & lda ) if( j>=1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_${ci}$lasyf_rook #:endif #:endfor pure module subroutine stdlib${ii}$_ssytf2_rook( uplo, n, a, lda, ipiv, info ) !! SSYTF2_ROOK computes the factorization of a real symmetric matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method: !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, U**T is the transpose of U, and D is symmetric and !! block diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars logical(lk) :: upper, done integer(${ik}$) :: i, imax, j, jmax, itemp, k, kk, kp, kstep, p, ii real(sp) :: absakk, alpha, colmax, d11, d12, d21, d22, rowmax, stemp, t, wk, wkm1, & wkp1, sfmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ ) then imax = stdlib${ii}$_isamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = abs( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_isamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) stemp = abs( a( itemp, imax ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )1_${ik}$ )call stdlib${ii}$_sswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_sswap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) if( kp>1_${ik}$ )call stdlib${ii}$_sswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_sswap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u if( k>1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_ssyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_sscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_ssyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = one / ( d11*d22-one ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )(k+1) )call stdlib${ii}$_sswap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_sswap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_ssyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_sscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_ssyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_idamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = abs( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_idamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = abs( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )1_${ik}$ )call stdlib${ii}$_dswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_dswap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) if( kp>1_${ik}$ )call stdlib${ii}$_dswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_dswap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u if( k>1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_dsyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_dscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_dsyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = one / ( d11*d22-one ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )(k+1) )call stdlib${ii}$_dswap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_dswap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_dsyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_dscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_dsyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_i${ri}$amax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = abs( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_i${ri}$amax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = abs( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )1_${ik}$ )call stdlib${ii}$_${ri}$swap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_${ri}$swap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) if( kp>1_${ik}$ )call stdlib${ii}$_${ri}$swap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_${ri}$swap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u if( k>1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_${ri}$syr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_${ri}$scal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ri}$syr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = one / ( d11*d22-one ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )(k+1) )call stdlib${ii}$_${ri}$swap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_${ri}$swap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_${ri}$syr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_${ri}$scal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ri}$syr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_icamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) stemp = cabs1( a( itemp, imax ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! cabs1( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1(a( imax, imax ))1_${ik}$ )call stdlib${ii}$_cswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_cswap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) if( kp>1_${ik}$ )call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_cswap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u if( k>1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( cabs1( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_csyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_cscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_csyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = cone / ( d11*d22-cone ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! cabs1( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1(a( imax, imax ))(k+1) )call stdlib${ii}$_cswap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_cswap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_csyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_cscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_csyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_izamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = cabs1( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! cabs1( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1(a( imax, imax ))1_${ik}$ )call stdlib${ii}$_zswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_zswap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) if( kp>1_${ik}$ )call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_zswap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u if( k>1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( cabs1( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_zsyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_zscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_zsyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = cone / ( d11*d22-cone ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! cabs1( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1(a( imax, imax ))(k+1) )call stdlib${ii}$_zswap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_zswap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_zsyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_zscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_zsyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_i${ci}$amax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = cabs1( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! cabs1( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1(a( imax, imax ))1_${ik}$ )call stdlib${ii}$_${ci}$swap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_${ci}$swap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) if( kp>1_${ik}$ )call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_${ci}$swap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u if( k>1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( cabs1( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_${ci}$syr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_${ci}$scal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ci}$syr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = cone / ( d11*d22-cone ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! cabs1( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1(a( imax, imax ))(k+1) )call stdlib${ii}$_${ci}$swap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_${ci}$swap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_${ci}$syr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_${ci}$scal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ci}$syr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_sger( k-1, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_sscal( nrhs, one / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k) then k-1 and -ipiv(k-1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k-1 ) if( kp/=k-1 )call stdlib${ii}$_sswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. if( k>2_${ik}$ ) then call stdlib${ii}$_sger( k-2, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) call stdlib${ii}$_sger( k-2, nrhs, -one, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ),& ldb ) end if ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ )call stdlib${ii}$_sgemv( 'TRANSPOSE', k-1, nrhs, -one, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, & one, b( k, 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_sgemv( 'TRANSPOSE', k-1, nrhs, -one, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, one, b( & k, 1_${ik}$ ), ldb ) call stdlib${ii}$_sgemv( 'TRANSPOSE', k-1, nrhs, -one, b,ldb, a( 1_${ik}$, k+1 ), 1_${ik}$, one, & b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k) then k+1 and -ipiv(k+1). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k+1 ) if( kp/=k+1 )call stdlib${ii}$_sswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_dger( k-1, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_dscal( nrhs, one / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k) then k-1 and -ipiv(k-1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k-1 ) if( kp/=k-1 )call stdlib${ii}$_dswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. if( k>2_${ik}$ ) then call stdlib${ii}$_dger( k-2, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) call stdlib${ii}$_dger( k-2, nrhs, -one, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ),& ldb ) end if ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ )call stdlib${ii}$_dgemv( 'TRANSPOSE', k-1, nrhs, -one, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, & one, b( k, 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_dgemv( 'TRANSPOSE', k-1, nrhs, -one, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, one, b( & k, 1_${ik}$ ), ldb ) call stdlib${ii}$_dgemv( 'TRANSPOSE', k-1, nrhs, -one, b,ldb, a( 1_${ik}$, k+1 ), 1_${ik}$, one, & b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k) then k+1 and -ipiv(k+1). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k+1 ) if( kp/=k+1 )call stdlib${ii}$_dswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ri}$ger( k-1, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_${ri}$scal( nrhs, one / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k) then k-1 and -ipiv(k-1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k-1 ) if( kp/=k-1 )call stdlib${ii}$_${ri}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. if( k>2_${ik}$ ) then call stdlib${ii}$_${ri}$ger( k-2, nrhs, -one, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) call stdlib${ii}$_${ri}$ger( k-2, nrhs, -one, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ),& ldb ) end if ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - one do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ )call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', k-1, nrhs, -one, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, & one, b( k, 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', k-1, nrhs, -one, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, one, b( & k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', k-1, nrhs, -one, b,ldb, a( 1_${ik}$, k+1 ), 1_${ik}$, one, & b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k) then k+1 and -ipiv(k+1). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k+1 ) if( kp/=k+1 )call stdlib${ii}$_${ri}$swap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_cgeru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_cscal( nrhs, cone / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k) then k-1 and -ipiv(k-1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k-1 ) if( kp/=k-1 )call stdlib${ii}$_cswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. if( k>2_${ik}$ ) then call stdlib${ii}$_cgeru( k-2, nrhs,-cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) call stdlib${ii}$_cgeru( k-2, nrhs,-cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ )& , ldb ) end if ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ )call stdlib${ii}$_cgemv( 'TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, & cone, b( k, 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_cgemv( 'TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, cone, & b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k+1 ), 1_${ik}$, cone,& b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k) then k+1 and -ipiv(k+1). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k+1 ) if( kp/=k+1 )call stdlib${ii}$_cswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_zgeru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_zscal( nrhs, cone / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k) then k-1 and -ipiv(k-1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k-1 ) if( kp/=k-1 )call stdlib${ii}$_zswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. if( k>2_${ik}$ ) then call stdlib${ii}$_zgeru( k-2, nrhs,-cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) call stdlib${ii}$_zgeru( k-2, nrhs,-cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ )& , ldb ) end if ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ )call stdlib${ii}$_zgemv( 'TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, & cone, b( k, 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_zgemv( 'TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, cone, & b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k+1 ), 1_${ik}$, cone,& b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k) then k+1 and -ipiv(k+1). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k+1 ) if( kp/=k+1 )call stdlib${ii}$_zswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ci}$geru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. call stdlib${ii}$_${ci}$scal( nrhs, cone / a( k, k ), b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k) then k-1 and -ipiv(k-1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k-1 ) if( kp/=k-1 )call stdlib${ii}$_${ci}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. if( k>2_${ik}$ ) then call stdlib${ii}$_${ci}$geru( k-2, nrhs,-cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) call stdlib${ii}$_${ci}$geru( k-2, nrhs,-cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ )& , ldb ) end if ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / akm1k b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**t *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**t(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ )call stdlib${ii}$_${ci}$gemv( 'TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, & cone, b( k, 1_${ik}$ ), ldb ) ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**t(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$gemv( 'TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), 1_${ik}$, cone, & b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k+1 ), 1_${ik}$, cone,& b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k) then k+1 and -ipiv(k+1). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k+1 ) if( kp/=k+1 )call stdlib${ii}$_${ci}$swap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**t. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**t(k)), where l(k) is the transformation ! stored in column k of a. if( k0 .and. a( info, info )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==zero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_scopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_ssymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_sdot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_scopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_ssymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_sdot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_sdot( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_scopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_ssymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_sdot( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if if( kstep==1_${ik}$ ) then ! interchange rows and columns k and ipiv(k) in the leading ! submatrix a(1:k+1,1:k+1) kp = ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_sswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_sswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if else ! interchange rows and columns k and k+1 with -ipiv(k) and ! -ipiv(k+1)in the leading submatrix a(1:k+1,1:k+1) kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_sswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_sswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if k = k + 1_${ik}$ kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_sswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_sswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if end if k = k + 1_${ik}$ go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k0 .and. a( info, info )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==zero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_dcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dsymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_ddot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_dcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dsymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_ddot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_ddot( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_dcopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_dsymv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_ddot( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if if( kstep==1_${ik}$ ) then ! interchange rows and columns k and ipiv(k) in the leading ! submatrix a(1:k+1,1:k+1) kp = ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_dswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_dswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if else ! interchange rows and columns k and k+1 with -ipiv(k) and ! -ipiv(k+1)in the leading submatrix a(1:k+1,1:k+1) kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_dswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_dswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if k = k + 1_${ik}$ kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_dswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_dswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if end if k = k + 1_${ik}$ go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k0 .and. a( info, info )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==zero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$symv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_${ri}$dot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$symv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_${ri}$dot( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_${ri}$dot( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$symv( uplo, k-1, -one, a, lda, work, 1_${ik}$, zero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_${ri}$dot( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if if( kstep==1_${ik}$ ) then ! interchange rows and columns k and ipiv(k) in the leading ! submatrix a(1:k+1,1:k+1) kp = ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_${ri}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_${ri}$swap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if else ! interchange rows and columns k and k+1 with -ipiv(k) and ! -ipiv(k+1)in the leading submatrix a(1:k+1,1:k+1) kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_${ri}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_${ri}$swap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if k = k + 1_${ik}$ kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_${ri}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_${ri}$swap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if end if k = k + 1_${ik}$ go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / a( k, k ) ! compute column k of the inverse. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_csymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_cdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = a( k, k+1 ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-cone ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_csymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_cdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_cdotu( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_csymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_cdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if if( kstep==1_${ik}$ ) then ! interchange rows and columns k and ipiv(k) in the leading ! submatrix a(1:k+1,1:k+1) kp = ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_cswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if else ! interchange rows and columns k and k+1 with -ipiv(k) and ! -ipiv(k+1)in the leading submatrix a(1:k+1,1:k+1) kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_cswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if k = k + 1_${ik}$ kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_cswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if end if k = k + 1_${ik}$ go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zsymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_zdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = a( k, k+1 ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-cone ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zsymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_zdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_zdotu( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zsymv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_zdotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if if( kstep==1_${ik}$ ) then ! interchange rows and columns k and ipiv(k) in the leading ! submatrix a(1:k+1,1:k+1) kp = ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_zswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if else ! interchange rows and columns k and k+1 with -ipiv(k) and ! -ipiv(k+1)in the leading submatrix a(1:k+1,1:k+1) kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_zswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if k = k + 1_${ik}$ kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_zswap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if end if k = k + 1_${ik}$ go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 40 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$symv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_${ci}$dotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = a( k, k+1 ) ak = a( k, k ) / t akp1 = a( k+1, k+1 ) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-cone ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$symv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - stdlib${ii}$_${ci}$dotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k ),1_${ik}$ ) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_${ci}$dotu( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$symv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -stdlib${ii}$_${ci}$dotu( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) end if kstep = 2_${ik}$ end if if( kstep==1_${ik}$ ) then ! interchange rows and columns k and ipiv(k) in the leading ! submatrix a(1:k+1,1:k+1) kp = ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_${ci}$swap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if else ! interchange rows and columns k and k+1 with -ipiv(k) and ! -ipiv(k+1)in the leading submatrix a(1:k+1,1:k+1) kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_${ci}$swap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if k = k + 1_${ik}$ kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) call stdlib${ii}$_${ci}$swap( k-kp-1, a( kp+1, k ), 1_${ik}$, a( kp, kp+1 ), lda ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if end if k = k + 1_${ik}$ go to 30 40 continue else ! compute inv(a) from the factorization a = l*d*l**t. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 50 continue ! if k < 1, exit from loop. if( k<1 )go to 60 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = cone / a( k, k ) ! compute column k of the inverse. if( k1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_slasyf_rk( uplo, k, nb, kb, a, lda, e,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_ssytf2_rk( uplo, k, a, lda, e, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k-kb+1:k and apply row permutations to the ! last k+1 colunms k+1:n after that block ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k n, exit from loop if( k>n )go to 35 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_slasyf_rk( uplo, n-k+1, nb, kb, a( k, k ), lda, e( k ),ipiv( k ), & work, ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_ssytf2_rk( uplo, n-k+1, a( k, k ), lda, e( k ),ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do i = k, k + kb - 1 if( ipiv( i )>0_${ik}$ ) then ipiv( i ) = ipiv( i ) + k - 1_${ik}$ else ipiv( i ) = ipiv( i ) - k + 1_${ik}$ end if end do ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k:k+kb-1 and apply row permutations to the ! first k-1 colunms 1:k-1 before that block ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k>1_${ik}$ ) then do i = k, ( k + kb - 1 ), 1 ip = abs( ipiv( i ) ) if( ip/=i ) then call stdlib${ii}$_sswap( k-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end do end if ! increase k and return to the start of the main loop k = k + kb go to 20 ! this label is the exit from main loop over k increasing ! from 1 to n in steps of kb 35 continue ! end lower end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_ssytrf_rk pure module subroutine stdlib${ii}$_dsytrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) !! DSYTRF_RK computes the factorization of a real symmetric matrix A !! using the bounded Bunch-Kaufman (rook) diagonal pivoting method: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. !! For more information see Further Details section. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: e(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: i, iinfo, ip, iws, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_dlasyf_rk( uplo, k, nb, kb, a, lda, e,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_dsytf2_rk( uplo, k, a, lda, e, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k-kb+1:k and apply row permutations to the ! last k+1 colunms k+1:n after that block ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k n, exit from loop if( k>n )go to 35 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_dlasyf_rk( uplo, n-k+1, nb, kb, a( k, k ), lda, e( k ),ipiv( k ), & work, ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_dsytf2_rk( uplo, n-k+1, a( k, k ), lda, e( k ),ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do i = k, k + kb - 1 if( ipiv( i )>0_${ik}$ ) then ipiv( i ) = ipiv( i ) + k - 1_${ik}$ else ipiv( i ) = ipiv( i ) - k + 1_${ik}$ end if end do ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k:k+kb-1 and apply row permutations to the ! first k-1 colunms 1:k-1 before that block ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k>1_${ik}$ ) then do i = k, ( k + kb - 1 ), 1 ip = abs( ipiv( i ) ) if( ip/=i ) then call stdlib${ii}$_dswap( k-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end do end if ! increase k and return to the start of the main loop k = k + kb go to 20 ! this label is the exit from main loop over k increasing ! from 1 to n in steps of kb 35 continue ! end lower end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dsytrf_rk #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sytrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) !! DSYTRF_RK: computes the factorization of a real symmetric matrix A !! using the bounded Bunch-Kaufman (rook) diagonal pivoting method: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. !! For more information see Further Details section. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: e(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: i, iinfo, ip, iws, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_${ri}$lasyf_rk( uplo, k, nb, kb, a, lda, e,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_${ri}$sytf2_rk( uplo, k, a, lda, e, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k-kb+1:k and apply row permutations to the ! last k+1 colunms k+1:n after that block ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k n, exit from loop if( k>n )go to 35 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_${ri}$lasyf_rk( uplo, n-k+1, nb, kb, a( k, k ), lda, e( k ),ipiv( k ), & work, ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_${ri}$sytf2_rk( uplo, n-k+1, a( k, k ), lda, e( k ),ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do i = k, k + kb - 1 if( ipiv( i )>0_${ik}$ ) then ipiv( i ) = ipiv( i ) + k - 1_${ik}$ else ipiv( i ) = ipiv( i ) - k + 1_${ik}$ end if end do ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k:k+kb-1 and apply row permutations to the ! first k-1 colunms 1:k-1 before that block ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k>1_${ik}$ ) then do i = k, ( k + kb - 1 ), 1 ip = abs( ipiv( i ) ) if( ip/=i ) then call stdlib${ii}$_${ri}$swap( k-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end do end if ! increase k and return to the start of the main loop k = k + kb go to 20 ! this label is the exit from main loop over k increasing ! from 1 to n in steps of kb 35 continue ! end lower end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$sytrf_rk #:endif #:endfor pure module subroutine stdlib${ii}$_csytrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) !! CSYTRF_RK computes the factorization of a complex symmetric matrix A !! using the bounded Bunch-Kaufman (rook) diagonal pivoting method: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. !! For more information see Further Details section. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: e(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: i, iinfo, ip, iws, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_clasyf_rk( uplo, k, nb, kb, a, lda, e,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_csytf2_rk( uplo, k, a, lda, e, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k-kb+1:k and apply row permutations to the ! last k+1 colunms k+1:n after that block ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k n, exit from loop if( k>n )go to 35 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_clasyf_rk( uplo, n-k+1, nb, kb, a( k, k ), lda, e( k ),ipiv( k ), & work, ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_csytf2_rk( uplo, n-k+1, a( k, k ), lda, e( k ),ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do i = k, k + kb - 1 if( ipiv( i )>0_${ik}$ ) then ipiv( i ) = ipiv( i ) + k - 1_${ik}$ else ipiv( i ) = ipiv( i ) - k + 1_${ik}$ end if end do ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k:k+kb-1 and apply row permutations to the ! first k-1 colunms 1:k-1 before that block ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k>1_${ik}$ ) then do i = k, ( k + kb - 1 ), 1 ip = abs( ipiv( i ) ) if( ip/=i ) then call stdlib${ii}$_cswap( k-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end do end if ! increase k and return to the start of the main loop k = k + kb go to 20 ! this label is the exit from main loop over k increasing ! from 1 to n in steps of kb 35 continue ! end lower end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_csytrf_rk pure module subroutine stdlib${ii}$_zsytrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) !! ZSYTRF_RK computes the factorization of a complex symmetric matrix A !! using the bounded Bunch-Kaufman (rook) diagonal pivoting method: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. !! For more information see Further Details section. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: e(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: i, iinfo, ip, iws, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_zlasyf_rk( uplo, k, nb, kb, a, lda, e,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_zsytf2_rk( uplo, k, a, lda, e, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k-kb+1:k and apply row permutations to the ! last k+1 colunms k+1:n after that block ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k n, exit from loop if( k>n )go to 35 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_zlasyf_rk( uplo, n-k+1, nb, kb, a( k, k ), lda, e( k ),ipiv( k ), & work, ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_zsytf2_rk( uplo, n-k+1, a( k, k ), lda, e( k ),ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do i = k, k + kb - 1 if( ipiv( i )>0_${ik}$ ) then ipiv( i ) = ipiv( i ) + k - 1_${ik}$ else ipiv( i ) = ipiv( i ) - k + 1_${ik}$ end if end do ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k:k+kb-1 and apply row permutations to the ! first k-1 colunms 1:k-1 before that block ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k>1_${ik}$ ) then do i = k, ( k + kb - 1 ), 1 ip = abs( ipiv( i ) ) if( ip/=i ) then call stdlib${ii}$_zswap( k-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end do end if ! increase k and return to the start of the main loop k = k + kb go to 20 ! this label is the exit from main loop over k increasing ! from 1 to n in steps of kb 35 continue ! end lower end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zsytrf_rk #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$sytrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) !! ZSYTRF_RK: computes the factorization of a complex symmetric matrix A !! using the bounded Bunch-Kaufman (rook) diagonal pivoting method: !! A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**T (or L**T) is the transpose of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is symmetric and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. !! For more information see Further Details section. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: e(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: i, iinfo, ip, iws, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_${ci}$lasyf_rk( uplo, k, nb, kb, a, lda, e,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_${ci}$sytf2_rk( uplo, k, a, lda, e, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k-kb+1:k and apply row permutations to the ! last k+1 colunms k+1:n after that block ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k n, exit from loop if( k>n )go to 35 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_${ci}$lasyf_rk( uplo, n-k+1, nb, kb, a( k, k ), lda, e( k ),ipiv( k ), & work, ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_${ci}$sytf2_rk( uplo, n-k+1, a( k, k ), lda, e( k ),ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do i = k, k + kb - 1 if( ipiv( i )>0_${ik}$ ) then ipiv( i ) = ipiv( i ) + k - 1_${ik}$ else ipiv( i ) = ipiv( i ) - k + 1_${ik}$ end if end do ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k:k+kb-1 and apply row permutations to the ! first k-1 colunms 1:k-1 before that block ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k>1_${ik}$ ) then do i = k, ( k + kb - 1 ), 1 ip = abs( ipiv( i ) ) if( ip/=i ) then call stdlib${ii}$_${ci}$swap( k-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end do end if ! increase k and return to the start of the main loop k = k + kb go to 20 ! this label is the exit from main loop over k increasing ! from 1 to n in steps of kb 35 continue ! end lower end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$sytrf_rk #:endif #:endfor pure module subroutine stdlib${ii}$_slasyf_rk( uplo, n, nb, kb, a, lda, e, ipiv, w, ldw,info ) !! SLASYF_RK computes a partial factorization of a real symmetric !! matrix A using the bounded Bunch-Kaufman (rook) diagonal !! pivoting method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**T U22**T ) !! A = ( L11 0 ) ( D 0 ) ( L11**T L21**T ) if UPLO = 'L', !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! SLASYF_RK is an auxiliary routine called by SSYTRF_RK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: e(*), w(ldw,*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars logical(lk) :: done integer(${ik}$) :: imax, itemp, j, jb, jj, jmax, k, kk, kw, kkw, kp, kstep, p, ii real(sp) :: absakk, alpha, colmax, d11, d12, d21, d22, stemp, r1, rowmax, t, & sfmin ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight ! compute machine safe minimum sfmin = stdlib${ii}$_slamch( 'S' ) if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 ! initialize the first entry of array e, where superdiagonal ! elements of d are stored e( 1_${ik}$ ) = zero ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_isamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = abs( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_scopy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = zero else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_isamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) stemp = abs( w( itemp, kw-1 ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(abs( w( imax, kw-1 ) )1_${ik}$ ) then if( abs( a( k, k ) )>=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_sscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the superdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = one / ( d11*d22-one ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy diagonal elements of d(k) to a, ! copy superdiagonal element of d(k) to e(k) and ! zero out superdiagonal entry of a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = zero a( k, k ) = w( k, kw ) e( k ) = w( k-1, kw ) e( k-1 ) = zero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_sgemv( 'NO TRANSPOSE', jj-j+1, n-k, -one,a( j, k+1 ), lda, w( jj, & kw+1 ), ldw, one,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -one, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ),ldw, one, a( 1_${ik}$, j ), lda ) end do ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! initialize the unused last entry of the subdiagonal array e. e( n ) = zero ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_scopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, one, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k+1, k-1, -one,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,one, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_isamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = abs( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( w( imax, k+1 ) )=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_sscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the subdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k1_${ik}$ ) then imax = stdlib${ii}$_idamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = abs( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_dcopy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = zero else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_idamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = abs( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(abs( w( imax, kw-1 ) )1_${ik}$ ) then if( abs( a( k, k ) )>=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_dscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the superdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = one / ( d11*d22-one ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy diagonal elements of d(k) to a, ! copy superdiagonal element of d(k) to e(k) and ! zero out superdiagonal entry of a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = zero a( k, k ) = w( k, kw ) e( k ) = w( k-1, kw ) e( k-1 ) = zero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_dgemv( 'NO TRANSPOSE', jj-j+1, n-k, -one,a( j, k+1 ), lda, w( jj, & kw+1 ), ldw, one,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -one, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ),ldw, one, a( 1_${ik}$, j ), lda ) end do ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! initialize the unused last entry of the subdiagonal array e. e( n ) = zero ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_dcopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, one, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k+1, k-1, -one,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,one, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_idamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = abs( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( w( imax, k+1 ) )=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_dscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the subdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k1_${ik}$ ) then imax = stdlib${ii}$_i${ri}$amax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = abs( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_${ri}$copy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = zero else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_i${ri}$amax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = abs( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(abs( w( imax, kw-1 ) )1_${ik}$ ) then if( abs( a( k, k ) )>=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_${ri}$scal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the superdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = one / ( d11*d22-one ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy diagonal elements of d(k) to a, ! copy superdiagonal element of d(k) to e(k) and ! zero out superdiagonal entry of a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = zero a( k, k ) = w( k, kw ) e( k ) = w( k-1, kw ) e( k-1 ) = zero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', jj-j+1, n-k, -one,a( j, k+1 ), lda, w( jj, & kw+1 ), ldw, one,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -one, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ),ldw, one, a( 1_${ik}$, j ), lda ) end do ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! initialize the unused last entry of the subdiagonal array e. e( n ) = zero ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_${ri}$copy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -one, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, one, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -one,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,one, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_i${ri}$amax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = abs( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! abs( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( w( imax, k+1 ) )=sfmin ) then r1 = one / a( k, k ) call stdlib${ii}$_${ri}$scal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=zero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the subdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_ccopy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_icamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) stemp = cabs1( w( itemp, kw-1 ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(cabs1( w( imax, kw-1 ) )1_${ik}$ ) then if( cabs1( a( k, k ) )>=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_cscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = cone / ( d11*d22-cone ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy diagonal elements of d(k) to a, ! copy superdiagonal element of d(k) to e(k) and ! zero out superdiagonal entry of a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = czero a( k, k ) = w( k, kw ) e( k ) = w( k-1, kw ) e( k-1 ) = czero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_cgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ),ldw, cone, a( 1_${ik}$, j ), lda ) end do ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_ccopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, cone, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_icamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( cabs1( w( imax, k+1 ) )=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_cscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_zcopy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_izamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = cabs1( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(cabs1( w( imax, kw-1 ) )1_${ik}$ ) then if( cabs1( a( k, k ) )>=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_zscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = cone / ( d11*d22-cone ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy diagonal elements of d(k) to a, ! copy superdiagonal element of d(k) to e(k) and ! zero out superdiagonal entry of a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = czero a( k, k ) = w( k, kw ) e( k ) = w( k-1, kw ) e( k-1 ) = czero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_zgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ),ldw, cone, a( 1_${ik}$, j ), lda ) end do ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_zcopy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, cone, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_izamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( cabs1( w( imax, k+1 ) )=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_zscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k call stdlib${ii}$_${ci}$copy( k, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! ============================================================ ! test for interchange ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_i${ci}$amax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = cabs1( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, kw-1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.(cabs1( w( imax, kw-1 ) )1_${ik}$ ) then if( cabs1( a( k, k ) )>=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_${ci}$scal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now ! hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u if( k>2_${ik}$ ) then ! store u(k) and u(k-1) in columns k and k-1 of a d12 = w( k-1, kw ) d11 = w( k, kw ) / d12 d22 = w( k-1, kw-1 ) / d12 t = cone / ( d11*d22-cone ) do j = 1, k - 2 a( j, k-1 ) = t*( (d11*w( j, kw-1 )-w( j, kw ) ) /d12 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /d12 ) end do end if ! copy diagonal elements of d(k) to a, ! copy superdiagonal element of d(k) to e(k) and ! zero out superdiagonal entry of a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = czero a( k, k ) = w( k, kw ) e( k ) = w( k-1, kw ) e( k-1 ) = czero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**t = a11 - u12*w**t ! computing blocks of nb columns at a time do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb,n-k, -cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ),ldw, cone, a( 1_${ik}$, j ), lda ) end do ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update it call stdlib${ii}$_${ci}$copy( n-k+1, a( k, k ), 1_${ik}$, w( k, k ), 1_${ik}$ ) if( k>1_${ik}$ )call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, & 1_${ik}$ ), ldw, cone, w( k, k ), 1_${ik}$ ) ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( w( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), & lda, w( imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_i${ci}$amax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for ! cabs1( w( imax, k+1 ) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( cabs1( w( imax, k+1 ) )=sfmin ) then r1 = cone / a( k, k ) call stdlib${ii}$_${ci}$scal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else if( a( k, k )/=czero ) then do ii = k + 1, n a( ii, k ) = a( ii, k ) / a( k, k ) end do end if ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l if( k1_${ik}$ ) then imax = stdlib${ii}$_isamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = abs( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = zero else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_isamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) stemp = abs( a( itemp, imax ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )1_${ik}$ )call stdlib${ii}$_sswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_sswap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ )call stdlib${ii}$_sswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_sswap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_ssyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_sscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_ssyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if ! store the superdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = one / ( d11*d22-one ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if ! copy superdiagonal elements of d(k) to e(k) and ! zero out superdiagonal entry of a e( k ) = a( k-1, k ) e( k-1 ) = zero a( k-1, k ) = zero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 34 continue else ! factorize a as l*d*l**t using the lower triangle of a ! initialize the unused last entry of the subdiagonal array e. e( n ) = zero ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 64 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )(k+1) )call stdlib${ii}$_sswap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_sswap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_sswap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_sswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_ssyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_sscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_ssyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if ! store the subdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_idamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = abs( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = zero else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_idamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = abs( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )1_${ik}$ )call stdlib${ii}$_dswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_dswap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ )call stdlib${ii}$_dswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_dswap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_dsyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_dscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_dsyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if ! store the superdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = one / ( d11*d22-one ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if ! copy superdiagonal elements of d(k) to e(k) and ! zero out superdiagonal entry of a e( k ) = a( k-1, k ) e( k-1 ) = zero a( k-1, k ) = zero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 34 continue else ! factorize a as l*d*l**t using the lower triangle of a ! initialize the unused last entry of the subdiagonal array e. e( n ) = zero ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 64 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )(k+1) )call stdlib${ii}$_dswap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_dswap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_dswap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_dswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_dsyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_dscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_dsyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if ! store the subdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_i${ri}$amax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = abs( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = zero else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_i${ri}$amax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = abs( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )1_${ik}$ )call stdlib${ii}$_${ri}$swap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_${ri}$swap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ )call stdlib${ii}$_${ri}$swap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_${ri}$swap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_${ri}$syr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_${ri}$scal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ri}$syr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if ! store the superdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = one / ( d11*d22-one ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if ! copy superdiagonal elements of d(k) to e(k) and ! zero out superdiagonal entry of a e( k ) = a( k-1, k ) e( k-1 ) = zero a( k-1, k ) = zero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 34 continue else ! factorize a as l*d*l**t using the lower triangle of a ! initialize the unused last entry of the subdiagonal array e. e( n ) = zero ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 64 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( abs( a( imax, imax ) )(k+1) )call stdlib${ii}$_${ri}$swap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_${ri}$swap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_${ri}$swap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_${ri}$swap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / a( k, k ) call stdlib${ii}$_${ri}$syr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_${ri}$scal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ri}$syr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if ! store the subdiagonal element of d in array e e( k ) = zero end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_icamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) stemp = cabs1( a( itemp, imax ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1( a( imax, imax ) )1_${ik}$ )call stdlib${ii}$_cswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_cswap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ )call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_cswap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( cabs1( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_csyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_cscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_csyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = cone / ( d11*d22-cone ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if ! copy superdiagonal elements of d(k) to e(k) and ! zero out superdiagonal entry of a e( k ) = a( k-1, k ) e( k-1 ) = czero a( k-1, k ) = czero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 34 continue else ! factorize a as l*d*l**t using the lower triangle of a ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 64 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = stemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1( a( imax, imax ) )(k+1) )call stdlib${ii}$_cswap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_cswap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_cswap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_cswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_csyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_cscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_csyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_izamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = cabs1( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1( a( imax, imax ) )1_${ik}$ )call stdlib${ii}$_zswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_zswap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ )call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_zswap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( cabs1( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_zsyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_zscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_zsyr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = cone / ( d11*d22-cone ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if ! copy superdiagonal elements of d(k) to e(k) and ! zero out superdiagonal entry of a e( k ) = a( k-1, k ) e( k-1 ) = czero a( k-1, k ) = czero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 34 continue else ! factorize a as l*d*l**t using the lower triangle of a ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 64 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1( a( imax, imax ) )(k+1) )call stdlib${ii}$_zswap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_zswap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_zswap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_zswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_zsyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_zscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_zsyr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! test for interchange ! equivalent to testing for (used to handle nan and inf) ! absakk>=alpha*colmax if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_i${ci}$amax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = cabs1( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1( a( imax, imax ) )1_${ik}$ )call stdlib${ii}$_${ci}$swap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) if( p<(k-1) )call stdlib${ii}$_${ci}$swap( k-p-1, a( p+1, k ), 1_${ik}$, a( p, p+1 ),lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ )call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) if( ( kk>1_${ik}$ ) .and. ( kp<(kk-1) ) )call stdlib${ii}$_${ci}$swap( kk-kp-1, a( kp+1, kk ), & 1_${ik}$, a( kp, kp+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( cabs1( a( k, k ) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_${ci}$syr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_${ci}$scal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ci}$syr( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then d12 = a( k-1, k ) d22 = a( k-1, k-1 ) / d12 d11 = a( k, k ) / d12 t = cone / ( d11*d22-cone ) do j = k - 2, 1, -1 wkm1 = t*( d11*a( j, k-1 )-a( j, k ) ) wk = t*( d22*a( j, k )-a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - (a( i, k ) / d12 )*wk -( a( i, k-1 ) / d12 )& *wkm1 end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d12 a( j, k-1 ) = wkm1 / d12 end do end if ! copy superdiagonal elements of d(k) to e(k) and ! zero out superdiagonal entry of a e( k ) = a( k-1, k ) e( k-1 ) = czero a( k-1, k ) = czero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 34 continue else ! factorize a as l*d*l**t using the lower triangle of a ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 64 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = cabs1( a( k, k ) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! equivalent to testing for (used to handle nan and inf) ! abs( a( imax, imax ) )>=alpha*rowmax if( .not.( cabs1( a( imax, imax ) )(k+1) )call stdlib${ii}$_${ci}$swap( p-k-1, a( k+1, k ), 1_${ik}$, a( p, k+1 ), lda ) t = a( k, k ) a( k, k ) = a( p, p ) a( p, p ) = t ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_${ci}$swap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) end if ! second swap kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp(kk+1) ) )call stdlib${ii}$_${ci}$swap( kp-kk-1, a( kk+1, kk ), & 1_${ik}$, a( kp, kk+1 ),lda ) t = a( kk, kk ) a( kk, kk ) = a( kp, kp ) a( kp, kp ) = t if( kstep==2_${ik}$ ) then t = a( k+1, k ) a( k+1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert lower triangle of a into l form by applying ! the interchanges in columns 1:k-1. if ( k>1_${ik}$ )call stdlib${ii}$_${ci}$swap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = l(k)*d(k) ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = cone / a( k, k ) call stdlib${ii}$_${ci}$syr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_${ci}$scal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = a( k, k ) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ci}$syr( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = zero a( i-1, i ) = zero i = i - 1_${ik}$ else e( i ) = zero end if i = i - 1_${ik}$ end do ! convert permutations and ipiv ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and zero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = zero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_sswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_sswap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is no interchnge of rows i and and ipiv(i), ! so this should be reflected in ipiv format for ! *sytrf_rk ( or *sytrf_bk) ipiv( i ) = i i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations and ipiv ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_sswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_sswap( i-1, a( ip, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is one interchange of rows i+1 and ipiv(i+1), ! so this should be recorded in consecutive entries ! in ipiv format for *sytrf ipiv( i ) = ipiv( i+1 ) end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_ssyconvf pure module subroutine stdlib${ii}$_dsyconvf( uplo, way, n, a, lda, e, ipiv, info ) !! If parameter WAY = 'C': !! DSYCONVF converts the factorization output format used in !! DSYTRF provided on entry in parameter A into the factorization !! output format used in DSYTRF_RK (or DSYTRF_BK) that is stored !! on exit in parameters A and E. It also converts in place details of !! the intechanges stored in IPIV from the format used in DSYTRF into !! the format used in DSYTRF_RK (or DSYTRF_BK). !! If parameter WAY = 'R': !! DSYCONVF performs the conversion in reverse direction, i.e. !! converts the factorization output format used in DSYTRF_RK !! (or DSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in DSYTRF that is stored !! on exit in parameter A. It also converts in place details of !! the intechanges stored in IPIV from the format used in DSYTRF_RK !! (or DSYTRF_BK) into the format used in DSYTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(inout) :: ipiv(*) real(dp), intent(inout) :: a(lda,*), e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = zero a( i-1, i ) = zero i = i - 1_${ik}$ else e( i ) = zero end if i = i - 1_${ik}$ end do ! convert permutations and ipiv ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and zero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = zero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_dswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_dswap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is no interchnge of rows i and and ipiv(i), ! so this should be reflected in ipiv format for ! *sytrf_rk ( or *sytrf_bk) ipiv( i ) = i i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations and ipiv ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_dswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_dswap( i-1, a( ip, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is one interchange of rows i+1 and ipiv(i+1), ! so this should be recorded in consecutive entries ! in ipiv format for *sytrf ipiv( i ) = ipiv( i+1 ) end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_dsyconvf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$syconvf( uplo, way, n, a, lda, e, ipiv, info ) !! If parameter WAY = 'C': !! DSYCONVF: converts the factorization output format used in !! DSYTRF provided on entry in parameter A into the factorization !! output format used in DSYTRF_RK (or DSYTRF_BK) that is stored !! on exit in parameters A and E. It also converts in place details of !! the intechanges stored in IPIV from the format used in DSYTRF into !! the format used in DSYTRF_RK (or DSYTRF_BK). !! If parameter WAY = 'R': !! DSYCONVF performs the conversion in reverse direction, i.e. !! converts the factorization output format used in DSYTRF_RK !! (or DSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in DSYTRF that is stored !! on exit in parameter A. It also converts in place details of !! the intechanges stored in IPIV from the format used in DSYTRF_RK !! (or DSYTRF_BK) into the format used in DSYTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(inout) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*), e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = zero a( i-1, i ) = zero i = i - 1_${ik}$ else e( i ) = zero end if i = i - 1_${ik}$ end do ! convert permutations and ipiv ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and zero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = zero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_${ri}$swap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_${ri}$swap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is no interchnge of rows i and and ipiv(i), ! so this should be reflected in ipiv format for ! *sytrf_rk ( or *sytrf_bk) ipiv( i ) = i i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations and ipiv ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_${ri}$swap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_${ri}$swap( i-1, a( ip, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is one interchange of rows i+1 and ipiv(i+1), ! so this should be recorded in consecutive entries ! in ipiv format for *sytrf ipiv( i ) = ipiv( i+1 ) end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_${ri}$syconvf #:endif #:endfor pure module subroutine stdlib${ii}$_csyconvf( uplo, way, n, a, lda, e, ipiv, info ) !! If parameter WAY = 'C': !! CSYCONVF converts the factorization output format used in !! CSYTRF provided on entry in parameter A into the factorization !! output format used in CSYTRF_RK (or CSYTRF_BK) that is stored !! on exit in parameters A and E. It also converts in place details of !! the intechanges stored in IPIV from the format used in CSYTRF into !! the format used in CSYTRF_RK (or CSYTRF_BK). !! If parameter WAY = 'R': !! CSYCONVF performs the conversion in reverse direction, i.e. !! converts the factorization output format used in CSYTRF_RK !! (or CSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in CSYTRF that is stored !! on exit in parameter A. It also converts in place details of !! the intechanges stored in IPIV from the format used in CSYTRF_RK !! (or CSYTRF_BK) into the format used in CSYTRF. !! CSYCONVF can also convert in Hermitian matrix case, i.e. between !! formats used in CHETRF and CHETRF_RK (or CHETRF_BK). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(inout) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*), e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = czero a( i-1, i ) = czero i = i - 1_${ik}$ else e( i ) = czero end if i = i - 1_${ik}$ end do ! convert permutations and ipiv ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and czero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = czero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_cswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_cswap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is no interchnge of rows i and and ipiv(i), ! so this should be reflected in ipiv format for ! *sytrf_rk ( or *sytrf_bk) ipiv( i ) = i i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations and ipiv ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_cswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_cswap( i-1, a( ip, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is cone interchange of rows i+1 and ipiv(i+1), ! so this should be recorded in consecutive entries ! in ipiv format for *sytrf ipiv( i ) = ipiv( i+1 ) end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_csyconvf pure module subroutine stdlib${ii}$_zsyconvf( uplo, way, n, a, lda, e, ipiv, info ) !! If parameter WAY = 'C': !! ZSYCONVF converts the factorization output format used in !! ZSYTRF provided on entry in parameter A into the factorization !! output format used in ZSYTRF_RK (or ZSYTRF_BK) that is stored !! on exit in parameters A and E. It also converts in place details of !! the intechanges stored in IPIV from the format used in ZSYTRF into !! the format used in ZSYTRF_RK (or ZSYTRF_BK). !! If parameter WAY = 'R': !! ZSYCONVF performs the conversion in reverse direction, i.e. !! converts the factorization output format used in ZSYTRF_RK !! (or ZSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in ZSYTRF that is stored !! on exit in parameter A. It also converts in place details of !! the intechanges stored in IPIV from the format used in ZSYTRF_RK !! (or ZSYTRF_BK) into the format used in ZSYTRF. !! ZSYCONVF can also convert in Hermitian matrix case, i.e. between !! formats used in ZHETRF and ZHETRF_RK (or ZHETRF_BK). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(inout) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*), e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = czero a( i-1, i ) = czero i = i - 1_${ik}$ else e( i ) = czero end if i = i - 1_${ik}$ end do ! convert permutations and ipiv ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and czero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = czero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_zswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_zswap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is no interchnge of rows i and and ipiv(i), ! so this should be reflected in ipiv format for ! *sytrf_rk ( or *sytrf_bk) ipiv( i ) = i i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations and ipiv ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_zswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_zswap( i-1, a( ip, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is cone interchange of rows i+1 and ipiv(i+1), ! so this should be recorded in consecutive entries ! in ipiv format for *sytrf ipiv( i ) = ipiv( i+1 ) end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_zsyconvf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$syconvf( uplo, way, n, a, lda, e, ipiv, info ) !! If parameter WAY = 'C': !! ZSYCONVF: converts the factorization output format used in !! ZSYTRF provided on entry in parameter A into the factorization !! output format used in ZSYTRF_RK (or ZSYTRF_BK) that is stored !! on exit in parameters A and E. It also converts in place details of !! the intechanges stored in IPIV from the format used in ZSYTRF into !! the format used in ZSYTRF_RK (or ZSYTRF_BK). !! If parameter WAY = 'R': !! ZSYCONVF performs the conversion in reverse direction, i.e. !! converts the factorization output format used in ZSYTRF_RK !! (or ZSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in ZSYTRF that is stored !! on exit in parameter A. It also converts in place details of !! the intechanges stored in IPIV from the format used in ZSYTRF_RK !! (or ZSYTRF_BK) into the format used in ZSYTRF. !! ZSYCONVF can also convert in Hermitian matrix case, i.e. between !! formats used in ZHETRF and ZHETRF_RK (or ZHETRF_BK). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(inout) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*), e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = czero a( i-1, i ) = czero i = i - 1_${ik}$ else e( i ) = czero end if i = i - 1_${ik}$ end do ! convert permutations and ipiv ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and czero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = czero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_${ci}$swap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_${ci}$swap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is no interchnge of rows i and and ipiv(i), ! so this should be reflected in ipiv format for ! *sytrf_rk ( or *sytrf_bk) ipiv( i ) = i i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations and ipiv ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_${ci}$swap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i) in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=(i+1) ) then call stdlib${ii}$_${ci}$swap( i-1, a( ip, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if end if ! convert ipiv ! there is cone interchange of rows i+1 and ipiv(i+1), ! so this should be recorded in consecutive entries ! in ipiv format for *sytrf ipiv( i ) = ipiv( i+1 ) end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_${ci}$syconvf #:endif #:endfor pure module subroutine stdlib${ii}$_ssyconvf_rook( uplo, way, n, a, lda, e, ipiv, info ) !! If parameter WAY = 'C': !! SSYCONVF_ROOK converts the factorization output format used in !! SSYTRF_ROOK provided on entry in parameter A into the factorization !! output format used in SSYTRF_RK (or SSYTRF_BK) that is stored !! on exit in parameters A and E. IPIV format for SSYTRF_ROOK and !! SSYTRF_RK (or SSYTRF_BK) is the same and is not converted. !! If parameter WAY = 'R': !! SSYCONVF_ROOK performs the conversion in reverse direction, i.e. !! converts the factorization output format used in SSYTRF_RK !! (or SSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in SSYTRF_ROOK that is stored !! on exit in parameter A. IPIV format for SSYTRF_ROOK and !! SSYTRF_RK (or SSYTRF_BK) is the same and is not converted. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(inout) :: a(lda,*), e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, ip2 ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = zero a( i-1, i ) = zero i = i - 1_${ik}$ else e( i ) = zero end if i = i - 1_${ik}$ end do ! convert permutations ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and zero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = zero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_sswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i and ipiv(i) and i+1 and ipiv(i+1) ! in a(i:n,1:i-1) ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_sswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if if( ip2/=(i+1) ) then call stdlib${ii}$_sswap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip2, 1_${ik}$ ), lda ) end if end if i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_sswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i+1) and i and ipiv(i) ! in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip2/=(i+1) ) then call stdlib${ii}$_sswap( i-1, a( ip2, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if if( ip/=i ) then call stdlib${ii}$_sswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_ssyconvf_rook pure module subroutine stdlib${ii}$_dsyconvf_rook( uplo, way, n, a, lda, e, ipiv, info ) !! If parameter WAY = 'C': !! DSYCONVF_ROOK converts the factorization output format used in !! DSYTRF_ROOK provided on entry in parameter A into the factorization !! output format used in DSYTRF_RK (or DSYTRF_BK) that is stored !! on exit in parameters A and E. IPIV format for DSYTRF_ROOK and !! DSYTRF_RK (or DSYTRF_BK) is the same and is not converted. !! If parameter WAY = 'R': !! DSYCONVF_ROOK performs the conversion in reverse direction, i.e. !! converts the factorization output format used in DSYTRF_RK !! (or DSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in DSYTRF_ROOK that is stored !! on exit in parameter A. IPIV format for DSYTRF_ROOK and !! DSYTRF_RK (or DSYTRF_BK) is the same and is not converted. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(inout) :: a(lda,*), e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, ip2 ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = zero a( i-1, i ) = zero i = i - 1_${ik}$ else e( i ) = zero end if i = i - 1_${ik}$ end do ! convert permutations ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and zero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = zero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_dswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i and ipiv(i) and i+1 and ipiv(i+1) ! in a(i:n,1:i-1) ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_dswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if if( ip2/=(i+1) ) then call stdlib${ii}$_dswap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip2, 1_${ik}$ ), lda ) end if end if i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_dswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i+1) and i and ipiv(i) ! in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip2/=(i+1) ) then call stdlib${ii}$_dswap( i-1, a( ip2, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if if( ip/=i ) then call stdlib${ii}$_dswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_dsyconvf_rook #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$syconvf_rook( uplo, way, n, a, lda, e, ipiv, info ) !! If parameter WAY = 'C': !! DSYCONVF_ROOK: converts the factorization output format used in !! DSYTRF_ROOK provided on entry in parameter A into the factorization !! output format used in DSYTRF_RK (or DSYTRF_BK) that is stored !! on exit in parameters A and E. IPIV format for DSYTRF_ROOK and !! DSYTRF_RK (or DSYTRF_BK) is the same and is not converted. !! If parameter WAY = 'R': !! DSYCONVF_ROOK performs the conversion in reverse direction, i.e. !! converts the factorization output format used in DSYTRF_RK !! (or DSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in DSYTRF_ROOK that is stored !! on exit in parameter A. IPIV format for DSYTRF_ROOK and !! DSYTRF_RK (or DSYTRF_BK) is the same and is not converted. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*), e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, ip2 ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = zero a( i-1, i ) = zero i = i - 1_${ik}$ else e( i ) = zero end if i = i - 1_${ik}$ end do ! convert permutations ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and zero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = zero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_${ri}$swap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i and ipiv(i) and i+1 and ipiv(i+1) ! in a(i:n,1:i-1) ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_${ri}$swap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if if( ip2/=(i+1) ) then call stdlib${ii}$_${ri}$swap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip2, 1_${ik}$ ), lda ) end if end if i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_${ri}$swap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i+1) and i and ipiv(i) ! in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip2/=(i+1) ) then call stdlib${ii}$_${ri}$swap( i-1, a( ip2, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if if( ip/=i ) then call stdlib${ii}$_${ri}$swap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_${ri}$syconvf_rook #:endif #:endfor pure module subroutine stdlib${ii}$_csyconvf_rook( uplo, way, n, a, lda, e, ipiv, info ) !! If parameter WAY = 'C': !! CSYCONVF_ROOK converts the factorization output format used in !! CSYTRF_ROOK provided on entry in parameter A into the factorization !! output format used in CSYTRF_RK (or CSYTRF_BK) that is stored !! on exit in parameters A and E. IPIV format for CSYTRF_ROOK and !! CSYTRF_RK (or CSYTRF_BK) is the same and is not converted. !! If parameter WAY = 'R': !! CSYCONVF_ROOK performs the conversion in reverse direction, i.e. !! converts the factorization output format used in CSYTRF_RK !! (or CSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in CSYTRF_ROOK that is stored !! on exit in parameter A. IPIV format for CSYTRF_ROOK and !! CSYTRF_RK (or CSYTRF_BK) is the same and is not converted. !! CSYCONVF_ROOK can also convert in Hermitian matrix case, i.e. between !! formats used in CHETRF_ROOK and CHETRF_RK (or CHETRF_BK). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*), e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, ip2 ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = czero a( i-1, i ) = czero i = i - 1_${ik}$ else e( i ) = czero end if i = i - 1_${ik}$ end do ! convert permutations ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and czero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = czero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_cswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i and ipiv(i) and i+1 and ipiv(i+1) ! in a(i:n,1:i-1) ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_cswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if if( ip2/=(i+1) ) then call stdlib${ii}$_cswap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip2, 1_${ik}$ ), lda ) end if end if i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_cswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i+1) and i and ipiv(i) ! in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip2/=(i+1) ) then call stdlib${ii}$_cswap( i-1, a( ip2, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if if( ip/=i ) then call stdlib${ii}$_cswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_csyconvf_rook pure module subroutine stdlib${ii}$_zsyconvf_rook( uplo, way, n, a, lda, e, ipiv, info ) !! If parameter WAY = 'C': !! ZSYCONVF_ROOK converts the factorization output format used in !! ZSYTRF_ROOK provided on entry in parameter A into the factorization !! output format used in ZSYTRF_RK (or ZSYTRF_BK) that is stored !! on exit in parameters A and E. IPIV format for ZSYTRF_ROOK and !! ZSYTRF_RK (or ZSYTRF_BK) is the same and is not converted. !! If parameter WAY = 'R': !! ZSYCONVF_ROOK performs the conversion in reverse direction, i.e. !! converts the factorization output format used in ZSYTRF_RK !! (or ZSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in ZSYTRF_ROOK that is stored !! on exit in parameter A. IPIV format for ZSYTRF_ROOK and !! ZSYTRF_RK (or ZSYTRF_BK) is the same and is not converted. !! ZSYCONVF_ROOK can also convert in Hermitian matrix case, i.e. between !! formats used in ZHETRF_ROOK and ZHETRF_RK (or ZHETRF_BK). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*), e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, ip2 ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = czero a( i-1, i ) = czero i = i - 1_${ik}$ else e( i ) = czero end if i = i - 1_${ik}$ end do ! convert permutations ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and czero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = czero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_zswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i and ipiv(i) and i+1 and ipiv(i+1) ! in a(i:n,1:i-1) ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_zswap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if if( ip2/=(i+1) ) then call stdlib${ii}$_zswap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip2, 1_${ik}$ ), lda ) end if end if i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_zswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i+1) and i and ipiv(i) ! in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip2/=(i+1) ) then call stdlib${ii}$_zswap( i-1, a( ip2, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if if( ip/=i ) then call stdlib${ii}$_zswap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_zsyconvf_rook #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$syconvf_rook( uplo, way, n, a, lda, e, ipiv, info ) !! If parameter WAY = 'C': !! ZSYCONVF_ROOK: converts the factorization output format used in !! ZSYTRF_ROOK provided on entry in parameter A into the factorization !! output format used in ZSYTRF_RK (or ZSYTRF_BK) that is stored !! on exit in parameters A and E. IPIV format for ZSYTRF_ROOK and !! ZSYTRF_RK (or ZSYTRF_BK) is the same and is not converted. !! If parameter WAY = 'R': !! ZSYCONVF_ROOK performs the conversion in reverse direction, i.e. !! converts the factorization output format used in ZSYTRF_RK !! (or ZSYTRF_BK) provided on entry in parameters A and E into !! the factorization output format used in ZSYTRF_ROOK that is stored !! on exit in parameter A. IPIV format for ZSYTRF_ROOK and !! ZSYTRF_RK (or ZSYTRF_BK) is the same and is not converted. !! ZSYCONVF_ROOK can also convert in Hermitian matrix case, i.e. between !! formats used in ZHETRF_ROOK and ZHETRF_RK (or ZHETRF_BK). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, way integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*), e(*) ! ===================================================================== ! External Subroutines logical(lk) :: upper, convert integer(${ik}$) :: i, ip, ip2 ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) convert = stdlib_lsame( way, 'C' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.convert .and. .not.stdlib_lsame( way, 'R' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda1 ) if( ipiv( i )<0_${ik}$ ) then e( i ) = a( i-1, i ) e( i-1 ) = czero a( i-1, i ) = czero i = i - 1_${ik}$ else e( i ) = czero end if i = i - 1_${ik}$ end do ! convert permutations ! apply permutations to submatrices of upper part of a ! in factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(1:i,n-i:n) ip = ipiv( i ) if( i1 ) if( ipiv( i )<0_${ik}$ ) then a( i-1, i ) = e( i ) i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! end a is upper end if else ! begin a is lower if ( convert ) then ! convert a (a is lower) ! convert value ! assign subdiagonal entries of d to array e and czero out ! corresponding entries in input storage a i = 1_${ik}$ e( n ) = czero do while ( i<=n ) if( i0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_${ci}$swap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i and ipiv(i) and i+1 and ipiv(i+1) ! in a(i:n,1:i-1) ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_${ci}$swap( i-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if if( ip2/=(i+1) ) then call stdlib${ii}$_${ci}$swap( i-1, a( i+1, 1_${ik}$ ), lda,a( ip2, 1_${ik}$ ), lda ) end if end if i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do else ! revert a (a is lower) ! revert permutations ! apply permutations to submatrices of lower part of a ! in reverse factorization order where i decreases from n to 1 i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then ! 1-by-1 pivot interchange ! swap rows i and ipiv(i) in a(i:n,1:i-1) ip = ipiv( i ) if ( i>1_${ik}$ ) then if( ip/=i ) then call stdlib${ii}$_${ci}$swap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if else ! 2-by-2 pivot interchange ! swap rows i+1 and ipiv(i+1) and i and ipiv(i) ! in a(i:n,1:i-1) i = i - 1_${ik}$ ip = -ipiv( i ) ip2 = -ipiv( i+1 ) if ( i>1_${ik}$ ) then if( ip2/=(i+1) ) then call stdlib${ii}$_${ci}$swap( i-1, a( ip2, 1_${ik}$ ), lda,a( i+1, 1_${ik}$ ), lda ) end if if( ip/=i ) then call stdlib${ii}$_${ci}$swap( i-1, a( ip, 1_${ik}$ ), lda,a( i, 1_${ik}$ ), lda ) end if end if end if i = i - 1_${ik}$ end do ! revert value ! assign subdiagonal entries of d from array e to ! subgiagonal entries of a. i = 1_${ik}$ do while ( i<=n-1 ) if( ipiv( i )<0_${ik}$ ) then a( i + 1_${ik}$, i ) = e( i ) i = i + 1_${ik}$ end if i = i + 1_${ik}$ end do end if ! end a is lower end if return end subroutine stdlib${ii}$_${ci}$syconvf_rook #:endif #:endfor pure module subroutine stdlib${ii}$_ssytrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) !! SSYTRF_AA computes the factorization of a real symmetric matrix A !! using the Aasen's algorithm. The form of the factorization is !! A = U**T*T*U or A = L*T*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is a symmetric tridiagonal matrix. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: j, lwkopt integer(${ik}$) :: nb, mj, nj, k1, k2, j1, j2, j3, jb real(sp) :: alpha ! Intrinsic Functions ! Executable Statements ! determine the block size nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SSYTRF_AA', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j + 1_${ik}$ jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_slasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( max(1_${ik}$, j), j+1 ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_sswap( j1-k1-2, a( 1_${ik}$, j2 ), 1_${ik}$,a( 1_${ik}$, ipiv(j2) ), 1_${ik}$ ) end if end do j = j + jb ! trailing submatrix update, where ! the row a(j1-1, j2-1:n) stores u(j1, j2+1:n) and ! work stores the current block of the auxiriarly matrix h if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j, j+1 ) a( j, j+1 ) = one call stdlib${ii}$_scopy( n-j, a( j-1, j+1 ), lda,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_sscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_sgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_sgemv( 'NO TRANSPOSE', mj, jb+1,-one, work( j3-j1+1+k1*n ), & n,a( j1-k2, j3 ), 1_${ik}$,one, a( j3, j3 ), lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block row with stdlib${ii}$_sgemm call stdlib${ii}$_sgemm( 'TRANSPOSE', 'TRANSPOSE',nj, n-j3+1, jb+1,-one, a( j1-& k2, j2 ), lda,work( j3-j1+1+k1*n ), n,one, a( j2, j3 ), lda ) end do ! recover t( j, j+1 ) a( j, j+1 ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_scopy( n-j, a( j+1, j+1 ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 10 else ! ..................................................... ! factorize a as l*d*l**t using the lower triangle of a ! ..................................................... ! copy first column a(1:n, 1) into h(1:n, 1) ! (stored in work(1:n)) call stdlib${ii}$_scopy( n, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) ! j is the main loop index, increasing from 1 to n in steps of ! jb, where jb is the number of columns factorized by stdlib${ii}$_slasyf; ! jb is either nb, or n-j+1 for the last block j = 0_${ik}$ 11 continue if( j>=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j+1 jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_slasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( j+1, max(1_${ik}$, j) ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_sswap( j1-k1-2, a( j2, 1_${ik}$ ), lda,a( ipiv(j2), 1_${ik}$ ), lda ) end if end do j = j + jb ! trailing submatrix update, where ! a(j2+1, j1-1) stores l(j2+1, j1) and ! work(j2+1, 1) stores h(j2+1, 1) if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j+1, j ) a( j+1, j ) = one call stdlib${ii}$_scopy( n-j, a( j+1, j-1 ), 1_${ik}$,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_sscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_sgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_sgemv( 'NO TRANSPOSE', mj, jb+1,-one, work( j3-j1+1+k1*n ), & n,a( j3, j1-k2 ), lda,one, a( j3, j3 ), 1_${ik}$ ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block in j2-th block column with stdlib${ii}$_sgemm call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE',n-j3+1, nj, jb+1,-one, work(& j3-j1+1+k1*n ), n,a( j2, j1-k2 ), lda,one, a( j3, j2 ), lda ) end do ! recover t( j+1, j ) a( j+1, j ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_scopy( n-j, a( j+1, j+1 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 11 end if 20 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_ssytrf_aa pure module subroutine stdlib${ii}$_dsytrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) !! DSYTRF_AA computes the factorization of a real symmetric matrix A !! using the Aasen's algorithm. The form of the factorization is !! A = U**T*T*U or A = L*T*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is a symmetric tridiagonal matrix. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: j, lwkopt integer(${ik}$) :: nb, mj, nj, k1, k2, j1, j2, j3, jb real(dp) :: alpha ! Intrinsic Functions ! Executable Statements ! determine the block size nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DSYTRF_AA', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j + 1_${ik}$ jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_dlasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( max(1_${ik}$, j), j+1 ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_dswap( j1-k1-2, a( 1_${ik}$, j2 ), 1_${ik}$,a( 1_${ik}$, ipiv(j2) ), 1_${ik}$ ) end if end do j = j + jb ! trailing submatrix update, where ! the row a(j1-1, j2-1:n) stores u(j1, j2+1:n) and ! work stores the current block of the auxiriarly matrix h if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j, j+1 ) a( j, j+1 ) = one call stdlib${ii}$_dcopy( n-j, a( j-1, j+1 ), lda,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_dscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_dgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_dgemv( 'NO TRANSPOSE', mj, jb+1,-one, work( j3-j1+1+k1*n ), & n,a( j1-k2, j3 ), 1_${ik}$,one, a( j3, j3 ), lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block row with stdlib${ii}$_dgemm call stdlib${ii}$_dgemm( 'TRANSPOSE', 'TRANSPOSE',nj, n-j3+1, jb+1,-one, a( j1-& k2, j2 ), lda,work( j3-j1+1+k1*n ), n,one, a( j2, j3 ), lda ) end do ! recover t( j, j+1 ) a( j, j+1 ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_dcopy( n-j, a( j+1, j+1 ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 10 else ! ..................................................... ! factorize a as l*d*l**t using the lower triangle of a ! ..................................................... ! copy first column a(1:n, 1) into h(1:n, 1) ! (stored in work(1:n)) call stdlib${ii}$_dcopy( n, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) ! j is the main loop index, increasing from 1 to n in steps of ! jb, where jb is the number of columns factorized by stdlib${ii}$_dlasyf; ! jb is either nb, or n-j+1 for the last block j = 0_${ik}$ 11 continue if( j>=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j+1 jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_dlasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( j+1, max(1_${ik}$, j) ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_dswap( j1-k1-2, a( j2, 1_${ik}$ ), lda,a( ipiv(j2), 1_${ik}$ ), lda ) end if end do j = j + jb ! trailing submatrix update, where ! a(j2+1, j1-1) stores l(j2+1, j1) and ! work(j2+1, 1) stores h(j2+1, 1) if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j+1, j ) a( j+1, j ) = one call stdlib${ii}$_dcopy( n-j, a( j+1, j-1 ), 1_${ik}$,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_dscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_dgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_dgemv( 'NO TRANSPOSE', mj, jb+1,-one, work( j3-j1+1+k1*n ), & n,a( j3, j1-k2 ), lda,one, a( j3, j3 ), 1_${ik}$ ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block in j2-th block column with stdlib${ii}$_dgemm call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE',n-j3+1, nj, jb+1,-one, work(& j3-j1+1+k1*n ), n,a( j2, j1-k2 ), lda,one, a( j3, j2 ), lda ) end do ! recover t( j+1, j ) a( j+1, j ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_dcopy( n-j, a( j+1, j+1 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 11 end if 20 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dsytrf_aa #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sytrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) !! DSYTRF_AA: computes the factorization of a real symmetric matrix A !! using the Aasen's algorithm. The form of the factorization is !! A = U**T*T*U or A = L*T*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is a symmetric tridiagonal matrix. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: j, lwkopt integer(${ik}$) :: nb, mj, nj, k1, k2, j1, j2, j3, jb real(${rk}$) :: alpha ! Intrinsic Functions ! Executable Statements ! determine the block size nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DSYTRF_AA', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j + 1_${ik}$ jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_${ri}$lasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( max(1_${ik}$, j), j+1 ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_${ri}$swap( j1-k1-2, a( 1_${ik}$, j2 ), 1_${ik}$,a( 1_${ik}$, ipiv(j2) ), 1_${ik}$ ) end if end do j = j + jb ! trailing submatrix update, where ! the row a(j1-1, j2-1:n) stores u(j1, j2+1:n) and ! work stores the current block of the auxiriarly matrix h if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j, j+1 ) a( j, j+1 ) = one call stdlib${ii}$_${ri}$copy( n-j, a( j-1, j+1 ), lda,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_${ri}$gemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', mj, jb+1,-one, work( j3-j1+1+k1*n ), & n,a( j1-k2, j3 ), 1_${ik}$,one, a( j3, j3 ), lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block row with stdlib${ii}$_${ri}$gemm call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'TRANSPOSE',nj, n-j3+1, jb+1,-one, a( j1-& k2, j2 ), lda,work( j3-j1+1+k1*n ), n,one, a( j2, j3 ), lda ) end do ! recover t( j, j+1 ) a( j, j+1 ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_${ri}$copy( n-j, a( j+1, j+1 ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 10 else ! ..................................................... ! factorize a as l*d*l**t using the lower triangle of a ! ..................................................... ! copy first column a(1:n, 1) into h(1:n, 1) ! (stored in work(1:n)) call stdlib${ii}$_${ri}$copy( n, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) ! j is the main loop index, increasing from 1 to n in steps of ! jb, where jb is the number of columns factorized by stdlib${ii}$_${ri}$lasyf; ! jb is either nb, or n-j+1 for the last block j = 0_${ik}$ 11 continue if( j>=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j+1 jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_${ri}$lasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( j+1, max(1_${ik}$, j) ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_${ri}$swap( j1-k1-2, a( j2, 1_${ik}$ ), lda,a( ipiv(j2), 1_${ik}$ ), lda ) end if end do j = j + jb ! trailing submatrix update, where ! a(j2+1, j1-1) stores l(j2+1, j1) and ! work(j2+1, 1) stores h(j2+1, 1) if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j+1, j ) a( j+1, j ) = one call stdlib${ii}$_${ri}$copy( n-j, a( j+1, j-1 ), 1_${ik}$,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_${ri}$gemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', mj, jb+1,-one, work( j3-j1+1+k1*n ), & n,a( j3, j1-k2 ), lda,one, a( j3, j3 ), 1_${ik}$ ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block in j2-th block column with stdlib${ii}$_${ri}$gemm call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE',n-j3+1, nj, jb+1,-one, work(& j3-j1+1+k1*n ), n,a( j2, j1-k2 ), lda,one, a( j3, j2 ), lda ) end do ! recover t( j+1, j ) a( j+1, j ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_${ri}$copy( n-j, a( j+1, j+1 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 11 end if 20 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$sytrf_aa #:endif #:endfor pure module subroutine stdlib${ii}$_csytrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) !! CSYTRF_AA computes the factorization of a complex symmetric matrix A !! using the Aasen's algorithm. The form of the factorization is !! A = U**T*T*U or A = L*T*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is a complex symmetric tridiagonal matrix. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: j, lwkopt integer(${ik}$) :: nb, mj, nj, k1, k2, j1, j2, j3, jb complex(sp) :: alpha ! Intrinsic Functions ! Executable Statements ! determine the block size nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CSYTRF_AA', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j + 1_${ik}$ jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_clasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( max(1_${ik}$, j), j+1 ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_cswap( j1-k1-2, a( 1_${ik}$, j2 ), 1_${ik}$,a( 1_${ik}$, ipiv(j2) ), 1_${ik}$ ) end if end do j = j + jb ! trailing submatrix update, where ! the row a(j1-1, j2-1:n) stores u(j1, j2+1:n) and ! work stores the current block of the auxiriarly matrix h if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j, j+1 ) a( j, j+1 ) = cone call stdlib${ii}$_ccopy( n-j, a( j-1, j+1 ), lda,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_cscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_cgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_cgemv( 'NO TRANSPOSE', mj, jb+1,-cone, work( j3-j1+1+k1*n ),& n,a( j1-k2, j3 ), 1_${ik}$,cone, a( j3, j3 ), lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block row with stdlib${ii}$_cgemm call stdlib${ii}$_cgemm( 'TRANSPOSE', 'TRANSPOSE',nj, n-j3+1, jb+1,-cone, a( j1-& k2, j2 ), lda,work( j3-j1+1+k1*n ), n,cone, a( j2, j3 ), lda ) end do ! recover t( j, j+1 ) a( j, j+1 ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_ccopy( n-j, a( j+1, j+1 ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 10 else ! ..................................................... ! factorize a as l*d*l**t using the lower triangle of a ! ..................................................... ! copy first column a(1:n, 1) into h(1:n, 1) ! (stored in work(1:n)) call stdlib${ii}$_ccopy( n, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) ! j is the main loop index, increasing from 1 to n in steps of ! jb, where jb is the number of columns factorized by stdlib${ii}$_clasyf; ! jb is either nb, or n-j+1 for the last block j = 0_${ik}$ 11 continue if( j>=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j+1 jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_clasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( j+1, max(1_${ik}$, j) ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_cswap( j1-k1-2, a( j2, 1_${ik}$ ), lda,a( ipiv(j2), 1_${ik}$ ), lda ) end if end do j = j + jb ! trailing submatrix update, where ! a(j2+1, j1-1) stores l(j2+1, j1) and ! work(j2+1, 1) stores h(j2+1, 1) if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j+1, j ) a( j+1, j ) = cone call stdlib${ii}$_ccopy( n-j, a( j+1, j-1 ), 1_${ik}$,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_cscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_cgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_cgemv( 'NO TRANSPOSE', mj, jb+1,-cone, work( j3-j1+1+k1*n ),& n,a( j3, j1-k2 ), lda,cone, a( j3, j3 ), 1_${ik}$ ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block in j2-th block column with stdlib${ii}$_cgemm call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'TRANSPOSE',n-j3+1, nj, jb+1,-cone, & work( j3-j1+1+k1*n ), n,a( j2, j1-k2 ), lda,cone, a( j3, j2 ), lda ) end do ! recover t( j+1, j ) a( j+1, j ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_ccopy( n-j, a( j+1, j+1 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 11 end if 20 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_csytrf_aa pure module subroutine stdlib${ii}$_zsytrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) !! ZSYTRF_AA computes the factorization of a complex symmetric matrix A !! using the Aasen's algorithm. The form of the factorization is !! A = U**T*T*U or A = L*T*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is a complex symmetric tridiagonal matrix. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: j, lwkopt integer(${ik}$) :: nb, mj, nj, k1, k2, j1, j2, j3, jb complex(dp) :: alpha ! Intrinsic Functions ! Executable Statements ! determine the block size nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZSYTRF_AA', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j + 1_${ik}$ jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_zlasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( max(1_${ik}$, j), j+1 ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_zswap( j1-k1-2, a( 1_${ik}$, j2 ), 1_${ik}$,a( 1_${ik}$, ipiv(j2) ), 1_${ik}$ ) end if end do j = j + jb ! trailing submatrix update, where ! the row a(j1-1, j2-1:n) stores u(j1, j2+1:n) and ! work stores the current block of the auxiriarly matrix h if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j, j+1 ) a( j, j+1 ) = cone call stdlib${ii}$_zcopy( n-j, a( j-1, j+1 ), lda,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_zscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_zgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_zgemv( 'NO TRANSPOSE', mj, jb+1,-cone, work( j3-j1+1+k1*n ),& n,a( j1-k2, j3 ), 1_${ik}$,cone, a( j3, j3 ), lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block row with stdlib${ii}$_zgemm call stdlib${ii}$_zgemm( 'TRANSPOSE', 'TRANSPOSE',nj, n-j3+1, jb+1,-cone, a( j1-& k2, j2 ), lda,work( j3-j1+1+k1*n ), n,cone, a( j2, j3 ), lda ) end do ! recover t( j, j+1 ) a( j, j+1 ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_zcopy( n-j, a( j+1, j+1 ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 10 else ! ..................................................... ! factorize a as l*d*l**t using the lower triangle of a ! ..................................................... ! copy first column a(1:n, 1) into h(1:n, 1) ! (stored in work(1:n)) call stdlib${ii}$_zcopy( n, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) ! j is the main loop index, increasing from 1 to n in steps of ! jb, where jb is the number of columns factorized by stdlib${ii}$_zlasyf; ! jb is either nb, or n-j+1 for the last block j = 0_${ik}$ 11 continue if( j>=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j+1 jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_zlasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( j+1, max(1_${ik}$, j) ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_zswap( j1-k1-2, a( j2, 1_${ik}$ ), lda,a( ipiv(j2), 1_${ik}$ ), lda ) end if end do j = j + jb ! trailing submatrix update, where ! a(j2+1, j1-1) stores l(j2+1, j1) and ! work(j2+1, 1) stores h(j2+1, 1) if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j+1, j ) a( j+1, j ) = cone call stdlib${ii}$_zcopy( n-j, a( j+1, j-1 ), 1_${ik}$,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_zscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_zgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_zgemv( 'NO TRANSPOSE', mj, jb+1,-cone, work( j3-j1+1+k1*n ),& n,a( j3, j1-k2 ), lda,cone, a( j3, j3 ), 1_${ik}$ ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block in j2-th block column with stdlib${ii}$_zgemm call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'TRANSPOSE',n-j3+1, nj, jb+1,-cone, & work( j3-j1+1+k1*n ), n,a( j2, j1-k2 ), lda,cone, a( j3, j2 ), lda ) end do ! recover t( j+1, j ) a( j+1, j ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_zcopy( n-j, a( j+1, j+1 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 11 end if 20 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zsytrf_aa #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$sytrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) !! ZSYTRF_AA: computes the factorization of a complex symmetric matrix A !! using the Aasen's algorithm. The form of the factorization is !! A = U**T*T*U or A = L*T*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is a complex symmetric tridiagonal matrix. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: j, lwkopt integer(${ik}$) :: nb, mj, nj, k1, k2, j1, j2, j3, jb complex(${ck}$) :: alpha ! Intrinsic Functions ! Executable Statements ! determine the block size nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZSYTRF_AA', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j + 1_${ik}$ jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_${ci}$lasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( max(1_${ik}$, j), j+1 ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_${ci}$swap( j1-k1-2, a( 1_${ik}$, j2 ), 1_${ik}$,a( 1_${ik}$, ipiv(j2) ), 1_${ik}$ ) end if end do j = j + jb ! trailing submatrix update, where ! the row a(j1-1, j2-1:n) stores u(j1, j2+1:n) and ! work stores the current block of the auxiriarly matrix h if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j, j+1 ) a( j, j+1 ) = cone call stdlib${ii}$_${ci}$copy( n-j, a( j-1, j+1 ), lda,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_${ci}$gemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', mj, jb+1,-cone, work( j3-j1+1+k1*n ),& n,a( j1-k2, j3 ), 1_${ik}$,cone, a( j3, j3 ), lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block row with stdlib${ii}$_${ci}$gemm call stdlib${ii}$_${ci}$gemm( 'TRANSPOSE', 'TRANSPOSE',nj, n-j3+1, jb+1,-cone, a( j1-& k2, j2 ), lda,work( j3-j1+1+k1*n ), n,cone, a( j2, j3 ), lda ) end do ! recover t( j, j+1 ) a( j, j+1 ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_${ci}$copy( n-j, a( j+1, j+1 ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 10 else ! ..................................................... ! factorize a as l*d*l**t using the lower triangle of a ! ..................................................... ! copy first column a(1:n, 1) into h(1:n, 1) ! (stored in work(1:n)) call stdlib${ii}$_${ci}$copy( n, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) ! j is the main loop index, increasing from 1 to n in steps of ! jb, where jb is the number of columns factorized by stdlib${ii}$_${ci}$lasyf; ! jb is either nb, or n-j+1 for the last block j = 0_${ik}$ 11 continue if( j>=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j+1 jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_${ci}$lasyf_aa( uplo, 2_${ik}$-k1, n-j, jb,a( j+1, max(1_${ik}$, j) ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_${ci}$swap( j1-k1-2, a( j2, 1_${ik}$ ), lda,a( ipiv(j2), 1_${ik}$ ), lda ) end if end do j = j + jb ! trailing submatrix update, where ! a(j2+1, j1-1) stores l(j2+1, j1) and ! work(j2+1, 1) stores h(j2+1, 1) if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = a( j+1, j ) a( j+1, j ) = cone call stdlib${ii}$_${ci}$copy( n-j, a( j+1, j-1 ), 1_${ik}$,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 and k2= 0 for the first panel, ! while k1=0 and k2=1 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_${ci}$gemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', mj, jb+1,-cone, work( j3-j1+1+k1*n ),& n,a( j3, j1-k2 ), lda,cone, a( j3, j3 ), 1_${ik}$ ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block in j2-th block column with stdlib${ii}$_${ci}$gemm call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'TRANSPOSE',n-j3+1, nj, jb+1,-cone, & work( j3-j1+1+k1*n ), n,a( j2, j1-k2 ), lda,cone, a( j3, j2 ), lda ) end do ! recover t( j+1, j ) a( j+1, j ) = alpha end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_${ci}$copy( n-j, a( j+1, j+1 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 11 end if 20 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$sytrf_aa #:endif #:endfor pure module subroutine stdlib${ii}$_slasyf_aa( uplo, j1, m, nb, a, lda, ipiv,h, ldh, work ) !! DLATRF_AA factorizes a panel of a real symmetric matrix A using !! the Aasen's algorithm. The panel consists of a set of NB rows of A !! when UPLO is U, or a set of NB columns when UPLO is L. !! In order to factorize the panel, the Aasen's algorithm requires the !! last row, or column, of the previous panel. The first row, or column, !! of A is set to be the first row, or column, of an identity matrix, !! which is used to factorize the first panel. !! The resulting J-th row of U, or J-th column of L, is stored in the !! (J-1)-th row, or column, of A (without the unit diagonals), while !! the diagonal and subdiagonal of A are overwritten by those of T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: m, nb, j1, lda, ldh ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*), h(ldh,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, k, k1, i1, i2, mj real(sp) :: piv, alpha ! Intrinsic Functions ! Executable Statements j = 1_${ik}$ ! k1 is the first column of the panel to be factorized ! i.e., k1 is 2 for the first block column, and 1 for the rest of the blocks k1 = (2_${ik}$-j1)+1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then ! ..................................................... ! factorize a as u**t*d*u using the upper triangle of a ! ..................................................... 10 continue if ( j>min(m, nb) )go to 20 ! k is the column to be factorized ! when being called from stdlib${ii}$_ssytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j, j:m) - h(j:m, 1:(j-1)) * l(j1:(j-1), j), ! where h(j:m, j) has been initialized to be a(j, j:m) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_sgemv( 'NO TRANSPOSE', mj, j-k1,-one, h( j, k1 ), ldh,a( 1_${ik}$, j ), 1_${ik}$,& one, h( j, j ), 1_${ik}$ ) end if ! copy h(i:m, i) into work call stdlib${ii}$_scopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j-1, j:m) * t(j-1,j), ! where a(j-1, j) stores t(j-1, j) and a(j-2, j:m) stores u(j-1, j:m) alpha = -a( k-1, j ) call stdlib${ii}$_saxpy( mj, alpha, a( k-2, j ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( k, j ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( k, j ) call stdlib${ii}$_saxpy( m-j, alpha, a( k-1, j+1 ), lda,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_isamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1, i1+1:m) with a(i1+1:m, i2) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_sswap( i2-i1-1, a( j1+i1-1, i1+1 ), lda,a( j1+i1, i2 ), 1_${ik}$ ) ! swap a(i1, i2+1:m) with a(i2, i2+1:m) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_sswap( i1-k1+1, a( 1_${ik}$, i1 ), 1_${ik}$,a( 1_${ik}$, i2 ), 1_${ik}$ ) end if else ipiv( j+1 ) = j+1 endif ! set a(j, j+1) = t(j, j+1) a( k, j+1 ) = work( 2_${ik}$ ) if( jmin( m, nb ) )go to 40 ! k is the column to be factorized ! when being called from stdlib${ii}$_ssytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j:m, j) - h(j:m, 1:(j-1)) * l(j, j1:(j-1))^t, ! where h(j:m, j) has been initialized to be a(j:m, j) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_sgemv( 'NO TRANSPOSE', mj, j-k1,-one, h( j, k1 ), ldh,a( j, 1_${ik}$ ), lda,& one, h( j, j ), 1_${ik}$ ) end if ! copy h(j:m, j) into work call stdlib${ii}$_scopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j:m, j-1) * t(j-1,j), ! where a(j-1, j) = t(j-1, j) and a(j, j-2) = l(j, j-1) alpha = -a( j, k-1 ) call stdlib${ii}$_saxpy( mj, alpha, a( j, k-2 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( j, k ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( j, k ) call stdlib${ii}$_saxpy( m-j, alpha, a( j+1, k-1 ), 1_${ik}$,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_isamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1+1:m, i1) with a(i2, i1+1:m) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_sswap( i2-i1-1, a( i1+1, j1+i1-1 ), 1_${ik}$,a( i2, j1+i1 ), lda ) ! swap a(i2+1:m, i1) with a(i2+1:m, i2) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_sswap( i1-k1+1, a( i1, 1_${ik}$ ), lda,a( i2, 1_${ik}$ ), lda ) end if else ipiv( j+1 ) = j+1 endif ! set a(j+1, j) = t(j+1, j) a( j+1, k ) = work( 2_${ik}$ ) if( jmin(m, nb) )go to 20 ! k is the column to be factorized ! when being called from stdlib${ii}$_dsytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j, j:m) - h(j:m, 1:(j-1)) * l(j1:(j-1), j), ! where h(j:m, j) has been initialized to be a(j, j:m) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_dgemv( 'NO TRANSPOSE', mj, j-k1,-one, h( j, k1 ), ldh,a( 1_${ik}$, j ), 1_${ik}$,& one, h( j, j ), 1_${ik}$ ) end if ! copy h(i:m, i) into work call stdlib${ii}$_dcopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j-1, j:m) * t(j-1,j), ! where a(j-1, j) stores t(j-1, j) and a(j-2, j:m) stores u(j-1, j:m) alpha = -a( k-1, j ) call stdlib${ii}$_daxpy( mj, alpha, a( k-2, j ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( k, j ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( k, j ) call stdlib${ii}$_daxpy( m-j, alpha, a( k-1, j+1 ), lda,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_idamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1, i1+1:m) with a(i1+1:m, i2) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_dswap( i2-i1-1, a( j1+i1-1, i1+1 ), lda,a( j1+i1, i2 ), 1_${ik}$ ) ! swap a(i1, i2+1:m) with a(i2, i2+1:m) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_dswap( i1-k1+1, a( 1_${ik}$, i1 ), 1_${ik}$,a( 1_${ik}$, i2 ), 1_${ik}$ ) end if else ipiv( j+1 ) = j+1 endif ! set a(j, j+1) = t(j, j+1) a( k, j+1 ) = work( 2_${ik}$ ) if( jmin( m, nb ) )go to 40 ! k is the column to be factorized ! when being called from stdlib${ii}$_dsytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j:m, j) - h(j:m, 1:(j-1)) * l(j, j1:(j-1))^t, ! where h(j:m, j) has been initialized to be a(j:m, j) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_dgemv( 'NO TRANSPOSE', mj, j-k1,-one, h( j, k1 ), ldh,a( j, 1_${ik}$ ), lda,& one, h( j, j ), 1_${ik}$ ) end if ! copy h(j:m, j) into work call stdlib${ii}$_dcopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j:m, j-1) * t(j-1,j), ! where a(j-1, j) = t(j-1, j) and a(j, j-2) = l(j, j-1) alpha = -a( j, k-1 ) call stdlib${ii}$_daxpy( mj, alpha, a( j, k-2 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( j, k ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( j, k ) call stdlib${ii}$_daxpy( m-j, alpha, a( j+1, k-1 ), 1_${ik}$,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_idamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1+1:m, i1) with a(i2, i1+1:m) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_dswap( i2-i1-1, a( i1+1, j1+i1-1 ), 1_${ik}$,a( i2, j1+i1 ), lda ) ! swap a(i2+1:m, i1) with a(i2+1:m, i2) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_dswap( i1-k1+1, a( i1, 1_${ik}$ ), lda,a( i2, 1_${ik}$ ), lda ) end if else ipiv( j+1 ) = j+1 endif ! set a(j+1, j) = t(j+1, j) a( j+1, k ) = work( 2_${ik}$ ) if( jmin(m, nb) )go to 20 ! k is the column to be factorized ! when being called from stdlib${ii}$_${ri}$sytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j, j:m) - h(j:m, 1:(j-1)) * l(j1:(j-1), j), ! where h(j:m, j) has been initialized to be a(j, j:m) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', mj, j-k1,-one, h( j, k1 ), ldh,a( 1_${ik}$, j ), 1_${ik}$,& one, h( j, j ), 1_${ik}$ ) end if ! copy h(i:m, i) into work call stdlib${ii}$_${ri}$copy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j-1, j:m) * t(j-1,j), ! where a(j-1, j) stores t(j-1, j) and a(j-2, j:m) stores u(j-1, j:m) alpha = -a( k-1, j ) call stdlib${ii}$_${ri}$axpy( mj, alpha, a( k-2, j ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( k, j ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( k, j ) call stdlib${ii}$_${ri}$axpy( m-j, alpha, a( k-1, j+1 ), lda,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_i${ri}$amax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1, i1+1:m) with a(i1+1:m, i2) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_${ri}$swap( i2-i1-1, a( j1+i1-1, i1+1 ), lda,a( j1+i1, i2 ), 1_${ik}$ ) ! swap a(i1, i2+1:m) with a(i2, i2+1:m) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_${ri}$swap( i1-k1+1, a( 1_${ik}$, i1 ), 1_${ik}$,a( 1_${ik}$, i2 ), 1_${ik}$ ) end if else ipiv( j+1 ) = j+1 endif ! set a(j, j+1) = t(j, j+1) a( k, j+1 ) = work( 2_${ik}$ ) if( jmin( m, nb ) )go to 40 ! k is the column to be factorized ! when being called from stdlib${ii}$_${ri}$sytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j:m, j) - h(j:m, 1:(j-1)) * l(j, j1:(j-1))^t, ! where h(j:m, j) has been initialized to be a(j:m, j) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', mj, j-k1,-one, h( j, k1 ), ldh,a( j, 1_${ik}$ ), lda,& one, h( j, j ), 1_${ik}$ ) end if ! copy h(j:m, j) into work call stdlib${ii}$_${ri}$copy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j:m, j-1) * t(j-1,j), ! where a(j-1, j) = t(j-1, j) and a(j, j-2) = l(j, j-1) alpha = -a( j, k-1 ) call stdlib${ii}$_${ri}$axpy( mj, alpha, a( j, k-2 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( j, k ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( j, k ) call stdlib${ii}$_${ri}$axpy( m-j, alpha, a( j+1, k-1 ), 1_${ik}$,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_i${ri}$amax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1+1:m, i1) with a(i2, i1+1:m) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_${ri}$swap( i2-i1-1, a( i1+1, j1+i1-1 ), 1_${ik}$,a( i2, j1+i1 ), lda ) ! swap a(i2+1:m, i1) with a(i2+1:m, i2) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_${ri}$swap( i1-k1+1, a( i1, 1_${ik}$ ), lda,a( i2, 1_${ik}$ ), lda ) end if else ipiv( j+1 ) = j+1 endif ! set a(j+1, j) = t(j+1, j) a( j+1, k ) = work( 2_${ik}$ ) if( jmin(m, nb) )go to 20 ! k is the column to be factorized ! when being called from stdlib${ii}$_csytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j, j:m) - h(j:m, 1:(j-1)) * l(j1:(j-1), j), ! where h(j:m, j) has been initialized to be a(j, j:m) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_cgemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( 1_${ik}$, j ), 1_${ik}$,& cone, h( j, j ), 1_${ik}$ ) end if ! copy h(i:m, i) into work call stdlib${ii}$_ccopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j-1, j:m) * t(j-1,j), ! where a(j-1, j) stores t(j-1, j) and a(j-2, j:m) stores u(j-1, j:m) alpha = -a( k-1, j ) call stdlib${ii}$_caxpy( mj, alpha, a( k-2, j ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( k, j ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( k, j ) call stdlib${ii}$_caxpy( m-j, alpha, a( k-1, j+1 ), lda,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_icamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1, i1+1:m) with a(i1+1:m, i2) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_cswap( i2-i1-1, a( j1+i1-1, i1+1 ), lda,a( j1+i1, i2 ), 1_${ik}$ ) ! swap a(i1, i2+1:m) with a(i2, i2+1:m) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_cswap( i1-k1+1, a( 1_${ik}$, i1 ), 1_${ik}$,a( 1_${ik}$, i2 ), 1_${ik}$ ) end if else ipiv( j+1 ) = j+1 endif ! set a(j, j+1) = t(j, j+1) a( k, j+1 ) = work( 2_${ik}$ ) if( jmin( m, nb ) )go to 40 ! k is the column to be factorized ! when being called from stdlib${ii}$_csytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j:m, j) - h(j:m, 1:(j-1)) * l(j, j1:(j-1))^t, ! where h(j:m, j) has been initialized to be a(j:m, j) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_cgemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( j, 1_${ik}$ ), & lda,cone, h( j, j ), 1_${ik}$ ) end if ! copy h(j:m, j) into work call stdlib${ii}$_ccopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j:m, j-1) * t(j-1,j), ! where a(j-1, j) = t(j-1, j) and a(j, j-2) = l(j, j-1) alpha = -a( j, k-1 ) call stdlib${ii}$_caxpy( mj, alpha, a( j, k-2 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( j, k ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( j, k ) call stdlib${ii}$_caxpy( m-j, alpha, a( j+1, k-1 ), 1_${ik}$,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_icamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1+1:m, i1) with a(i2, i1+1:m) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_cswap( i2-i1-1, a( i1+1, j1+i1-1 ), 1_${ik}$,a( i2, j1+i1 ), lda ) ! swap a(i2+1:m, i1) with a(i2+1:m, i2) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_cswap( i1-k1+1, a( i1, 1_${ik}$ ), lda,a( i2, 1_${ik}$ ), lda ) end if else ipiv( j+1 ) = j+1 endif ! set a(j+1, j) = t(j+1, j) a( j+1, k ) = work( 2_${ik}$ ) if( jmin(m, nb) )go to 20 ! k is the column to be factorized ! when being called from stdlib${ii}$_zsytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j, j:m) - h(j:m, 1:(j-1)) * l(j1:(j-1), j), ! where h(j:m, j) has been initialized to be a(j, j:m) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_zgemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( 1_${ik}$, j ), 1_${ik}$,& cone, h( j, j ), 1_${ik}$ ) end if ! copy h(i:m, i) into work call stdlib${ii}$_zcopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j-1, j:m) * t(j-1,j), ! where a(j-1, j) stores t(j-1, j) and a(j-2, j:m) stores u(j-1, j:m) alpha = -a( k-1, j ) call stdlib${ii}$_zaxpy( mj, alpha, a( k-2, j ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( k, j ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( k, j ) call stdlib${ii}$_zaxpy( m-j, alpha, a( k-1, j+1 ), lda,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_izamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1, i1+1:m) with a(i1+1:m, i2) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_zswap( i2-i1-1, a( j1+i1-1, i1+1 ), lda,a( j1+i1, i2 ), 1_${ik}$ ) ! swap a(i1, i2+1:m) with a(i2, i2+1:m) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_zswap( i1-k1+1, a( 1_${ik}$, i1 ), 1_${ik}$,a( 1_${ik}$, i2 ), 1_${ik}$ ) end if else ipiv( j+1 ) = j+1 endif ! set a(j, j+1) = t(j, j+1) a( k, j+1 ) = work( 2_${ik}$ ) if( jmin( m, nb ) )go to 40 ! k is the column to be factorized ! when being called from stdlib${ii}$_zsytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j:m, j) - h(j:m, 1:(j-1)) * l(j, j1:(j-1))^t, ! where h(j:m, j) has been initialized to be a(j:m, j) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_zgemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( j, 1_${ik}$ ), & lda,cone, h( j, j ), 1_${ik}$ ) end if ! copy h(j:m, j) into work call stdlib${ii}$_zcopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j:m, j-1) * t(j-1,j), ! where a(j-1, j) = t(j-1, j) and a(j, j-2) = l(j, j-1) alpha = -a( j, k-1 ) call stdlib${ii}$_zaxpy( mj, alpha, a( j, k-2 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( j, k ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( j, k ) call stdlib${ii}$_zaxpy( m-j, alpha, a( j+1, k-1 ), 1_${ik}$,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_izamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1+1:m, i1) with a(i2, i1+1:m) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_zswap( i2-i1-1, a( i1+1, j1+i1-1 ), 1_${ik}$,a( i2, j1+i1 ), lda ) ! swap a(i2+1:m, i1) with a(i2+1:m, i2) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_zswap( i1-k1+1, a( i1, 1_${ik}$ ), lda,a( i2, 1_${ik}$ ), lda ) end if else ipiv( j+1 ) = j+1 endif ! set a(j+1, j) = t(j+1, j) a( j+1, k ) = work( 2_${ik}$ ) if( jmin(m, nb) )go to 20 ! k is the column to be factorized ! when being called from stdlib${ii}$_${ci}$sytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j, j:m) - h(j:m, 1:(j-1)) * l(j1:(j-1), j), ! where h(j:m, j) has been initialized to be a(j, j:m) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( 1_${ik}$, j ), 1_${ik}$,& cone, h( j, j ), 1_${ik}$ ) end if ! copy h(i:m, i) into work call stdlib${ii}$_${ci}$copy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j-1, j:m) * t(j-1,j), ! where a(j-1, j) stores t(j-1, j) and a(j-2, j:m) stores u(j-1, j:m) alpha = -a( k-1, j ) call stdlib${ii}$_${ci}$axpy( mj, alpha, a( k-2, j ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( k, j ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( k, j ) call stdlib${ii}$_${ci}$axpy( m-j, alpha, a( k-1, j+1 ), lda,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_i${ci}$amax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1, i1+1:m) with a(i1+1:m, i2) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_${ci}$swap( i2-i1-1, a( j1+i1-1, i1+1 ), lda,a( j1+i1, i2 ), 1_${ik}$ ) ! swap a(i1, i2+1:m) with a(i2, i2+1:m) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_${ci}$swap( i1-k1+1, a( 1_${ik}$, i1 ), 1_${ik}$,a( 1_${ik}$, i2 ), 1_${ik}$ ) end if else ipiv( j+1 ) = j+1 endif ! set a(j, j+1) = t(j, j+1) a( k, j+1 ) = work( 2_${ik}$ ) if( jmin( m, nb ) )go to 40 ! k is the column to be factorized ! when being called from stdlib${ii}$_${ci}$sytrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:m, j) := a(j:m, j) - h(j:m, 1:(j-1)) * l(j, j1:(j-1))^t, ! where h(j:m, j) has been initialized to be a(j:m, j) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( j, 1_${ik}$ ), & lda,cone, h( j, j ), 1_${ik}$ ) end if ! copy h(j:m, j) into work call stdlib${ii}$_${ci}$copy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j:m, j-1) * t(j-1,j), ! where a(j-1, j) = t(j-1, j) and a(j, j-2) = l(j, j-1) alpha = -a( j, k-1 ) call stdlib${ii}$_${ci}$axpy( mj, alpha, a( j, k-2 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( j, k ) = work( 1_${ik}$ ) if( j1_${ik}$ ) then alpha = -a( j, k ) call stdlib${ii}$_${ci}$axpy( m-j, alpha, a( j+1, k-1 ), 1_${ik}$,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:m)|) i2 = stdlib${ii}$_i${ci}$amax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply symmetric pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1+1:m, i1) with a(i2, i1+1:m) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_${ci}$swap( i2-i1-1, a( i1+1, j1+i1-1 ), 1_${ik}$,a( i2, j1+i1 ), lda ) ! swap a(i2+1:m, i1) with a(i2+1:m, i2) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_${ci}$swap( i1-k1+1, a( i1, 1_${ik}$ ), lda,a( i2, 1_${ik}$ ), lda ) end if else ipiv( j+1 ) = j+1 endif ! set a(j+1, j) = t(j+1, j) a( j+1, k ) = work( 2_${ik}$ ) if( j1_${ik}$ ) then ! pivot, p**t * b -> b k = 1_${ik}$ do while ( k<=n ) kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ end do ! compute u**t \ b -> b [ (u**t \p**t * b) ] call stdlib${ii}$_strsm( 'L', 'U', 'T', 'U', n-1, nrhs, one, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ), & ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (u**t \p**t * b) ] call stdlib${ii}$_slacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'F', 1_${ik}$, n-1, a(1_${ik}$, 2_${ik}$), lda+1, work(1_${ik}$), 1_${ik}$) call stdlib${ii}$_slacpy( 'F', 1_${ik}$, n-1, a(1_${ik}$, 2_${ik}$), lda+1, work(2_${ik}$*n), 1_${ik}$) end if call stdlib${ii}$_sgtsv(n, nrhs, work(1_${ik}$), work(n), work(2_${ik}$*n), b, ldb,info) ! 3) backward substitution with u if( n>1_${ik}$ ) then ! compute u \ b -> b [ u \ (t \ (u**t \p**t * b) ) ] call stdlib${ii}$_strsm( 'L', 'U', 'N', 'U', n-1, nrhs, one, a( 1_${ik}$, 2_${ik}$ ),lda, b(2_${ik}$, 1_${ik}$), & ldb) ! pivot, p * b -> b [ p * (u \ (t \ (u**t \p**t * b) )) ] k = n do while ( k>=1 ) kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ end do end if else ! solve a*x = b, where a = l*t*l**t. ! 1) forward substitution with l if( n>1_${ik}$ ) then ! pivot, p**t * b -> b k = 1_${ik}$ do while ( k<=n ) kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ end do ! compute l \ b -> b [ (l \p**t * b) ] call stdlib${ii}$_strsm( 'L', 'L', 'N', 'U', n-1, nrhs, one, a( 2_${ik}$, 1_${ik}$),lda, b(2_${ik}$, 1_${ik}$), & ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (l \p**t * b) ] call stdlib${ii}$_slacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'F', 1_${ik}$, n-1, a(2_${ik}$, 1_${ik}$), lda+1, work(1_${ik}$), 1_${ik}$) call stdlib${ii}$_slacpy( 'F', 1_${ik}$, n-1, a(2_${ik}$, 1_${ik}$), lda+1, work(2_${ik}$*n), 1_${ik}$) end if call stdlib${ii}$_sgtsv(n, nrhs, work(1_${ik}$), work(n), work(2_${ik}$*n), b, ldb,info) ! 3) backward substitution with l**t if( n>1_${ik}$ ) then ! compute l**t \ b -> b [ l**t \ (t \ (l \p**t * b) ) ] call stdlib${ii}$_strsm( 'L', 'L', 'T', 'U', n-1, nrhs, one, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ), & ldb) ! pivot, p * b -> b [ p * (l**t \ (t \ (l \p**t * b) )) ] k = n do while ( k>=1 ) kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_sswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ end do end if end if return end subroutine stdlib${ii}$_ssytrs_aa pure module subroutine stdlib${ii}$_dsytrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) !! DSYTRS_AA solves a system of linear equations A*X = B with a real !! symmetric matrix A using the factorization A = U**T*T*U or !! A = L*T*L**T computed by DSYTRF_AA. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, nrhs, lda, ldb, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: b(ldb,*) real(dp), intent(out) :: work(*) ! ===================================================================== logical(lk) :: lquery, upper integer(${ik}$) :: k, kp, lwkopt ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute u**t \ b -> b [ (u**t \p**t * b) ] call stdlib${ii}$_dtrsm('L', 'U', 'T', 'U', n-1, nrhs, one, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ), & ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (u**t \p**t * b) ] call stdlib${ii}$_dlacpy( 'F', 1_${ik}$, n, a( 1_${ik}$, 1_${ik}$ ), lda+1, work( n ), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_dlacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_dgtsv( n, nrhs, work( 1_${ik}$ ), work( n ), work( 2_${ik}$*n ), b, ldb,info ) ! 3) backward substitution with u if( n>1_${ik}$ ) then ! compute u \ b -> b [ u \ (t \ (u**t \p**t * b) ) ] call stdlib${ii}$_dtrsm( 'L', 'U', 'N', 'U', n-1, nrhs, one, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ), & ldb) ! pivot, p * b -> b [ p * (u \ (t \ (u**t \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if else ! solve a*x = b, where a = l*t*l**t. ! 1) forward substitution with l if( n>1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute l \ b -> b [ (l \p**t * b) ] call stdlib${ii}$_dtrsm( 'L', 'L', 'N', 'U', n-1, nrhs, one, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ), & ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (l \p**t * b) ] call stdlib${ii}$_dlacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_dlacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_dgtsv( n, nrhs, work( 1_${ik}$ ), work(n), work( 2_${ik}$*n ), b, ldb,info) ! 3) backward substitution with l**t if( n>1_${ik}$ ) then ! compute (l**t \ b) -> b [ l**t \ (t \ (l \p**t * b) ) ] call stdlib${ii}$_dtrsm( 'L', 'L', 'T', 'U', n-1, nrhs, one, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ), & ldb) ! pivot, p * b -> b [ p * (l**t \ (t \ (l \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_dswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_dsytrs_aa #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sytrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) !! DSYTRS_AA: solves a system of linear equations A*X = B with a real !! symmetric matrix A using the factorization A = U**T*T*U or !! A = L*T*L**T computed by DSYTRF_AA. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, nrhs, lda, ldb, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(inout) :: b(ldb,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== logical(lk) :: lquery, upper integer(${ik}$) :: k, kp, lwkopt ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute u**t \ b -> b [ (u**t \p**t * b) ] call stdlib${ii}$_${ri}$trsm('L', 'U', 'T', 'U', n-1, nrhs, one, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ), & ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (u**t \p**t * b) ] call stdlib${ii}$_${ri}$lacpy( 'F', 1_${ik}$, n, a( 1_${ik}$, 1_${ik}$ ), lda+1, work( n ), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_${ri}$gtsv( n, nrhs, work( 1_${ik}$ ), work( n ), work( 2_${ik}$*n ), b, ldb,info ) ! 3) backward substitution with u if( n>1_${ik}$ ) then ! compute u \ b -> b [ u \ (t \ (u**t \p**t * b) ) ] call stdlib${ii}$_${ri}$trsm( 'L', 'U', 'N', 'U', n-1, nrhs, one, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ), & ldb) ! pivot, p * b -> b [ p * (u \ (t \ (u**t \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if else ! solve a*x = b, where a = l*t*l**t. ! 1) forward substitution with l if( n>1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute l \ b -> b [ (l \p**t * b) ] call stdlib${ii}$_${ri}$trsm( 'L', 'L', 'N', 'U', n-1, nrhs, one, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ), & ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (l \p**t * b) ] call stdlib${ii}$_${ri}$lacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_${ri}$gtsv( n, nrhs, work( 1_${ik}$ ), work(n), work( 2_${ik}$*n ), b, ldb,info) ! 3) backward substitution with l**t if( n>1_${ik}$ ) then ! compute (l**t \ b) -> b [ l**t \ (t \ (l \p**t * b) ) ] call stdlib${ii}$_${ri}$trsm( 'L', 'L', 'T', 'U', n-1, nrhs, one, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ), & ldb) ! pivot, p * b -> b [ p * (l**t \ (t \ (l \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ri}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_${ri}$sytrs_aa #:endif #:endfor pure module subroutine stdlib${ii}$_csytrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) !! CSYTRS_AA solves a system of linear equations A*X = B with a complex !! symmetric matrix A using the factorization A = U**T*T*U or !! A = L*T*L**T computed by CSYTRF_AA. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, nrhs, lda, ldb, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(out) :: work(*) ! ===================================================================== logical(lk) :: lquery, upper integer(${ik}$) :: k, kp, lwkopt ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute u**t \ b -> b [ (u**t \p**t * b) ] call stdlib${ii}$_ctrsm( 'L', 'U', 'T', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (u**t \p**t * b) ] call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n, a( 1_${ik}$, 1_${ik}$ ), lda+1, work( n ), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_cgtsv( n, nrhs, work( 1_${ik}$ ), work( n ), work( 2_${ik}$*n ), b, ldb,info ) ! 3) backward substitution with u if( n>1_${ik}$ ) then ! compute u \ b -> b [ u \ (t \ (u**t \p**t * b) ) ] call stdlib${ii}$_ctrsm( 'L', 'U', 'N', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) ! pivot, p * b -> b [ p * (u**t \ (t \ (u \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if else ! solve a*x = b, where a = l*t*l**t. ! 1) forward substitution with l if( n>1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute l \ b -> b [ (l \p**t * b) ] call stdlib${ii}$_ctrsm( 'L', 'L', 'N', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (l \p**t * b) ] call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_cgtsv( n, nrhs, work( 1_${ik}$ ), work(n), work( 2_${ik}$*n ), b, ldb,info) ! 3) backward substitution with l**t if( n>1_${ik}$ ) then ! compute (l**t \ b) -> b [ l**t \ (t \ (l \p**t * b) ) ] call stdlib${ii}$_ctrsm( 'L', 'L', 'T', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) ! pivot, p * b -> b [ p * (l**t \ (t \ (l \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_csytrs_aa pure module subroutine stdlib${ii}$_zsytrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) !! ZSYTRS_AA solves a system of linear equations A*X = B with a complex !! symmetric matrix A using the factorization A = U**T*T*U or !! A = L*T*L**T computed by ZSYTRF_AA. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, nrhs, lda, ldb, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(out) :: work(*) ! ===================================================================== logical(lk) :: lquery, upper integer(${ik}$) :: k, kp, lwkopt ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute u**t \ b -> b [ (u**t \p**t * b) ] call stdlib${ii}$_ztrsm( 'L', 'U', 'T', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (u**t \p**t * b) ] call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n, a( 1_${ik}$, 1_${ik}$ ), lda+1, work( n ), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_zgtsv( n, nrhs, work( 1_${ik}$ ), work( n ), work( 2_${ik}$*n ), b, ldb,info ) ! 3) backward substitution with u if( n>1_${ik}$ ) then ! compute u \ b -> b [ u \ (t \ (u**t \p**t * b) ) ] call stdlib${ii}$_ztrsm( 'L', 'U', 'N', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) ! pivot, p * b -> b [ p * (u \ (t \ (u**t \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if else ! solve a*x = b, where a = l*t*l**t. ! 1) forward substitution with l if( n>1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute l \ b -> b [ (l \p**t * b) ] call stdlib${ii}$_ztrsm( 'L', 'L', 'N', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (l \p**t * b) ] call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_zgtsv( n, nrhs, work( 1_${ik}$ ), work(n), work( 2_${ik}$*n ), b, ldb,info) ! 3) backward substitution with l**t if( n>1_${ik}$ ) then ! compute (l**t \ b) -> b [ l**t \ (t \ (l \p**t * b) ) ] call stdlib${ii}$_ztrsm( 'L', 'L', 'T', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) ! pivot, p * b -> b [ p * (l**t \ (t \ (l \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_zsytrs_aa #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$sytrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) !! ZSYTRS_AA: solves a system of linear equations A*X = B with a complex !! symmetric matrix A using the factorization A = U**T*T*U or !! A = L*T*L**T computed by ZSYTRF_AA. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, nrhs, lda, ldb, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(inout) :: b(ldb,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== logical(lk) :: lquery, upper integer(${ik}$) :: k, kp, lwkopt ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute u**t \ b -> b [ (u**t \p**t * b) ] call stdlib${ii}$_${ci}$trsm( 'L', 'U', 'T', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (u**t \p**t * b) ] call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n, a( 1_${ik}$, 1_${ik}$ ), lda+1, work( n ), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_${ci}$gtsv( n, nrhs, work( 1_${ik}$ ), work( n ), work( 2_${ik}$*n ), b, ldb,info ) ! 3) backward substitution with u if( n>1_${ik}$ ) then ! compute u \ b -> b [ u \ (t \ (u**t \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm( 'L', 'U', 'N', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) ! pivot, p * b -> b [ p * (u \ (t \ (u**t \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if else ! solve a*x = b, where a = l*t*l**t. ! 1) forward substitution with l if( n>1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute l \ b -> b [ (l \p**t * b) ] call stdlib${ii}$_${ci}$trsm( 'L', 'L', 'N', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (l \p**t * b) ] call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_${ci}$gtsv( n, nrhs, work( 1_${ik}$ ), work(n), work( 2_${ik}$*n ), b, ldb,info) ! 3) backward substitution with l**t if( n>1_${ik}$ ) then ! compute (l**t \ b) -> b [ l**t \ (t \ (l \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm( 'L', 'L', 'T', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) ! pivot, p * b -> b [ p * (l**t \ (t \ (l \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_${ci}$sytrs_aa #:endif #:endfor #:endfor end submodule stdlib_lapack_solve_ldl_comp2 fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_svd_comp2.fypp0000664000175000017500000045575115135654166025701 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_svd_comp2 implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slabrd( m, n, nb, a, lda, d, e, tauq, taup, x, ldx, y,ldy ) !! SLABRD reduces the first NB rows and columns of a real general !! m by n matrix A to upper or lower bidiagonal form by an orthogonal !! transformation Q**T * A * P, and returns the matrices X and Y which !! are needed to apply the transformation to the unreduced part of A. !! If m >= n, A is reduced to upper bidiagonal form; if m < n, to lower !! bidiagonal form. !! This is an auxiliary routine called by SGEBRD ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldx, ldy, m, n, nb ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*), e(*), taup(*), tauq(*), x(ldx,*), y(ldy,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( m>=n ) then ! reduce to upper bidiagonal form loop_10: do i = 1, nb ! update a(i:m,i) call stdlib${ii}$_sgemv( 'NO TRANSPOSE', m-i+1, i-1, -one, a( i, 1_${ik}$ ),lda, y( i, 1_${ik}$ ), & ldy, one, a( i, i ), 1_${ik}$ ) call stdlib${ii}$_sgemv( 'NO TRANSPOSE', m-i+1, i-1, -one, x( i, 1_${ik}$ ),ldx, a( 1_${ik}$, i ), 1_${ik}$,& one, a( i, i ), 1_${ik}$ ) ! generate reflection q(i) to annihilate a(i+1:m,i) call stdlib${ii}$_slarfg( m-i+1, a( i, i ), a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = a( i, i ) if( i= n, A is reduced to upper bidiagonal form; if m < n, to lower !! bidiagonal form. !! This is an auxiliary routine called by DGEBRD ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldx, ldy, m, n, nb ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*), e(*), taup(*), tauq(*), x(ldx,*), y(ldy,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( m>=n ) then ! reduce to upper bidiagonal form loop_10: do i = 1, nb ! update a(i:m,i) call stdlib${ii}$_dgemv( 'NO TRANSPOSE', m-i+1, i-1, -one, a( i, 1_${ik}$ ),lda, y( i, 1_${ik}$ ), & ldy, one, a( i, i ), 1_${ik}$ ) call stdlib${ii}$_dgemv( 'NO TRANSPOSE', m-i+1, i-1, -one, x( i, 1_${ik}$ ),ldx, a( 1_${ik}$, i ), 1_${ik}$,& one, a( i, i ), 1_${ik}$ ) ! generate reflection q(i) to annihilate a(i+1:m,i) call stdlib${ii}$_dlarfg( m-i+1, a( i, i ), a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = a( i, i ) if( i= n, A is reduced to upper bidiagonal form; if m < n, to lower !! bidiagonal form. !! This is an auxiliary routine called by DGEBRD ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldx, ldy, m, n, nb ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: d(*), e(*), taup(*), tauq(*), x(ldx,*), y(ldy,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( m>=n ) then ! reduce to upper bidiagonal form loop_10: do i = 1, nb ! update a(i:m,i) call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', m-i+1, i-1, -one, a( i, 1_${ik}$ ),lda, y( i, 1_${ik}$ ), & ldy, one, a( i, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', m-i+1, i-1, -one, x( i, 1_${ik}$ ),ldx, a( 1_${ik}$, i ), 1_${ik}$,& one, a( i, i ), 1_${ik}$ ) ! generate reflection q(i) to annihilate a(i+1:m,i) call stdlib${ii}$_${ri}$larfg( m-i+1, a( i, i ), a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = a( i, i ) if( i= n, A is reduced to upper bidiagonal form; if m < n, to lower !! bidiagonal form. !! This is an auxiliary routine called by CGEBRD ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldx, ldy, m, n, nb ! Array Arguments real(sp), intent(out) :: d(*), e(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: taup(*), tauq(*), x(ldx,*), y(ldy,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(sp) :: alpha ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( m>=n ) then ! reduce to upper bidiagonal form loop_10: do i = 1, nb ! update a(i:m,i) call stdlib${ii}$_clacgv( i-1, y( i, 1_${ik}$ ), ldy ) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', m-i+1, i-1, -cone, a( i, 1_${ik}$ ),lda, y( i, 1_${ik}$ ), & ldy, cone, a( i, i ), 1_${ik}$ ) call stdlib${ii}$_clacgv( i-1, y( i, 1_${ik}$ ), ldy ) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', m-i+1, i-1, -cone, x( i, 1_${ik}$ ),ldx, a( 1_${ik}$, i ), & 1_${ik}$, cone, a( i, i ), 1_${ik}$ ) ! generate reflection q(i) to annihilate a(i+1:m,i) alpha = a( i, i ) call stdlib${ii}$_clarfg( m-i+1, alpha, a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = real( alpha,KIND=sp) if( i= n, A is reduced to upper bidiagonal form; if m < n, to lower !! bidiagonal form. !! This is an auxiliary routine called by ZGEBRD ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldx, ldy, m, n, nb ! Array Arguments real(dp), intent(out) :: d(*), e(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: taup(*), tauq(*), x(ldx,*), y(ldy,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(dp) :: alpha ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( m>=n ) then ! reduce to upper bidiagonal form loop_10: do i = 1, nb ! update a(i:m,i) call stdlib${ii}$_zlacgv( i-1, y( i, 1_${ik}$ ), ldy ) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', m-i+1, i-1, -cone, a( i, 1_${ik}$ ),lda, y( i, 1_${ik}$ ), & ldy, cone, a( i, i ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( i-1, y( i, 1_${ik}$ ), ldy ) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', m-i+1, i-1, -cone, x( i, 1_${ik}$ ),ldx, a( 1_${ik}$, i ), & 1_${ik}$, cone, a( i, i ), 1_${ik}$ ) ! generate reflection q(i) to annihilate a(i+1:m,i) alpha = a( i, i ) call stdlib${ii}$_zlarfg( m-i+1, alpha, a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = real( alpha,KIND=dp) if( i= n, A is reduced to upper bidiagonal form; if m < n, to lower !! bidiagonal form. !! This is an auxiliary routine called by ZGEBRD ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldx, ldy, m, n, nb ! Array Arguments real(${ck}$), intent(out) :: d(*), e(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: taup(*), tauq(*), x(ldx,*), y(ldy,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(${ck}$) :: alpha ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( m>=n ) then ! reduce to upper bidiagonal form loop_10: do i = 1, nb ! update a(i:m,i) call stdlib${ii}$_${ci}$lacgv( i-1, y( i, 1_${ik}$ ), ldy ) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', m-i+1, i-1, -cone, a( i, 1_${ik}$ ),lda, y( i, 1_${ik}$ ), & ldy, cone, a( i, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( i-1, y( i, 1_${ik}$ ), ldy ) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', m-i+1, i-1, -cone, x( i, 1_${ik}$ ),ldx, a( 1_${ik}$, i ), & 1_${ik}$, cone, a( i, i ), 1_${ik}$ ) ! generate reflection q(i) to annihilate a(i+1:m,i) alpha = a( i, i ) call stdlib${ii}$_${ci}$larfg( m-i+1, alpha, a( min( i+1, m ), i ), 1_${ik}$,tauq( i ) ) d( i ) = real( alpha,KIND=${ck}$) if( ifa ) if( swap ) then pmax = 3_${ik}$ temp = ft ft = ht ht = temp temp = fa fa = ha ha = temp ! now fa .ge. ha end if gt = g ga = abs( gt ) if( ga==zero ) then ! diagonal matrix ssmin = ha ssmax = fa clt = one crt = one slt = zero srt = zero else gasmal = .true. if( ga>fa ) then pmax = 2_${ik}$ if( ( fa / ga )one ) then ssmin = fa / ( ga / ha ) else ssmin = ( fa / ga )*ha end if clt = one slt = ht / gt srt = one crt = ft / gt end if end if if( gasmal ) then ! normal case d = fa - ha if( d==fa ) then ! copes with infinite f or h l = one else l = d / fa end if ! note that 0 .le. l .le. 1 m = gt / ft ! note that abs(m) .le. 1/macheps t = two - l ! note that t .ge. 1 mm = m*m tt = t*t s = sqrt( tt+mm ) ! note that 1 .le. s .le. 1 + 1/macheps if( l==zero ) then r = abs( m ) else r = sqrt( l*l+mm ) end if ! note that 0 .le. r .le. 1 + 1/macheps a = half*( s+r ) ! note that 1 .le. a .le. 1 + abs(m) ssmin = ha / a ssmax = fa*a if( mm==zero ) then ! note that m is very tiny if( l==zero ) then t = sign( two, ft )*sign( one, gt ) else t = gt / sign( d, ft ) + m / t end if else t = ( m / ( s+t )+m / ( r+l ) )*( one+a ) end if l = sqrt( t*t+four ) crt = two / l srt = t / l clt = ( crt+srt*m ) / a slt = ( ht / ft )*srt / a end if end if if( swap ) then csl = srt snl = crt csr = slt snr = clt else csl = clt snl = slt csr = crt snr = srt end if ! correct signs of ssmax and ssmin if( pmax==1_${ik}$ )tsign = sign( one, csr )*sign( one, csl )*sign( one, f ) if( pmax==2_${ik}$ )tsign = sign( one, snr )*sign( one, csl )*sign( one, g ) if( pmax==3_${ik}$ )tsign = sign( one, snr )*sign( one, snl )*sign( one, h ) ssmax = sign( ssmax, tsign ) ssmin = sign( ssmin, tsign*sign( one, f )*sign( one, h ) ) return end subroutine stdlib${ii}$_slasv2 pure module subroutine stdlib${ii}$_dlasv2( f, g, h, ssmin, ssmax, snr, csr, snl, csl ) !! DLASV2 computes the singular value decomposition of a 2-by-2 !! triangular matrix !! [ F G ] !! [ 0 H ]. !! On return, abs(SSMAX) is the larger singular value, abs(SSMIN) is the !! smaller singular value, and (CSL,SNL) and (CSR,SNR) are the left and !! right singular vectors for abs(SSMAX), giving the decomposition !! [ CSL SNL ] [ F G ] [ CSR -SNR ] = [ SSMAX 0 ] !! [-SNL CSL ] [ 0 H ] [ SNR CSR ] [ 0 SSMIN ]. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(out) :: csl, csr, snl, snr, ssmax, ssmin real(dp), intent(in) :: f, g, h ! ===================================================================== ! Local Scalars logical(lk) :: gasmal, swap integer(${ik}$) :: pmax real(dp) :: a, clt, crt, d, fa, ft, ga, gt, ha, ht, l, m, mm, r, s, slt, srt, t, temp, & tsign, tt ! Intrinsic Functions ! Executable Statements ft = f fa = abs( ft ) ht = h ha = abs( h ) ! pmax points to the maximum absolute element of matrix ! pmax = 1 if f largest in absolute values ! pmax = 2 if g largest in absolute values ! pmax = 3 if h largest in absolute values pmax = 1_${ik}$ swap = ( ha>fa ) if( swap ) then pmax = 3_${ik}$ temp = ft ft = ht ht = temp temp = fa fa = ha ha = temp ! now fa .ge. ha end if gt = g ga = abs( gt ) if( ga==zero ) then ! diagonal matrix ssmin = ha ssmax = fa clt = one crt = one slt = zero srt = zero else gasmal = .true. if( ga>fa ) then pmax = 2_${ik}$ if( ( fa / ga )one ) then ssmin = fa / ( ga / ha ) else ssmin = ( fa / ga )*ha end if clt = one slt = ht / gt srt = one crt = ft / gt end if end if if( gasmal ) then ! normal case d = fa - ha if( d==fa ) then ! copes with infinite f or h l = one else l = d / fa end if ! note that 0 .le. l .le. 1 m = gt / ft ! note that abs(m) .le. 1/macheps t = two - l ! note that t .ge. 1 mm = m*m tt = t*t s = sqrt( tt+mm ) ! note that 1 .le. s .le. 1 + 1/macheps if( l==zero ) then r = abs( m ) else r = sqrt( l*l+mm ) end if ! note that 0 .le. r .le. 1 + 1/macheps a = half*( s+r ) ! note that 1 .le. a .le. 1 + abs(m) ssmin = ha / a ssmax = fa*a if( mm==zero ) then ! note that m is very tiny if( l==zero ) then t = sign( two, ft )*sign( one, gt ) else t = gt / sign( d, ft ) + m / t end if else t = ( m / ( s+t )+m / ( r+l ) )*( one+a ) end if l = sqrt( t*t+four ) crt = two / l srt = t / l clt = ( crt+srt*m ) / a slt = ( ht / ft )*srt / a end if end if if( swap ) then csl = srt snl = crt csr = slt snr = clt else csl = clt snl = slt csr = crt snr = srt end if ! correct signs of ssmax and ssmin if( pmax==1_${ik}$ )tsign = sign( one, csr )*sign( one, csl )*sign( one, f ) if( pmax==2_${ik}$ )tsign = sign( one, snr )*sign( one, csl )*sign( one, g ) if( pmax==3_${ik}$ )tsign = sign( one, snr )*sign( one, snl )*sign( one, h ) ssmax = sign( ssmax, tsign ) ssmin = sign( ssmin, tsign*sign( one, f )*sign( one, h ) ) return end subroutine stdlib${ii}$_dlasv2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasv2( f, g, h, ssmin, ssmax, snr, csr, snl, csl ) !! DLASV2: computes the singular value decomposition of a 2-by-2 !! triangular matrix !! [ F G ] !! [ 0 H ]. !! On return, abs(SSMAX) is the larger singular value, abs(SSMIN) is the !! smaller singular value, and (CSL,SNL) and (CSR,SNR) are the left and !! right singular vectors for abs(SSMAX), giving the decomposition !! [ CSL SNL ] [ F G ] [ CSR -SNR ] = [ SSMAX 0 ] !! [-SNL CSL ] [ 0 H ] [ SNR CSR ] [ 0 SSMIN ]. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(out) :: csl, csr, snl, snr, ssmax, ssmin real(${rk}$), intent(in) :: f, g, h ! ===================================================================== ! Local Scalars logical(lk) :: gasmal, swap integer(${ik}$) :: pmax real(${rk}$) :: a, clt, crt, d, fa, ft, ga, gt, ha, ht, l, m, mm, r, s, slt, srt, t, temp, & tsign, tt ! Intrinsic Functions ! Executable Statements ft = f fa = abs( ft ) ht = h ha = abs( h ) ! pmax points to the maximum absolute element of matrix ! pmax = 1 if f largest in absolute values ! pmax = 2 if g largest in absolute values ! pmax = 3 if h largest in absolute values pmax = 1_${ik}$ swap = ( ha>fa ) if( swap ) then pmax = 3_${ik}$ temp = ft ft = ht ht = temp temp = fa fa = ha ha = temp ! now fa .ge. ha end if gt = g ga = abs( gt ) if( ga==zero ) then ! diagonal matrix ssmin = ha ssmax = fa clt = one crt = one slt = zero srt = zero else gasmal = .true. if( ga>fa ) then pmax = 2_${ik}$ if( ( fa / ga )one ) then ssmin = fa / ( ga / ha ) else ssmin = ( fa / ga )*ha end if clt = one slt = ht / gt srt = one crt = ft / gt end if end if if( gasmal ) then ! normal case d = fa - ha if( d==fa ) then ! copes with infinite f or h l = one else l = d / fa end if ! note that 0 .le. l .le. 1 m = gt / ft ! note that abs(m) .le. 1/macheps t = two - l ! note that t .ge. 1 mm = m*m tt = t*t s = sqrt( tt+mm ) ! note that 1 .le. s .le. 1 + 1/macheps if( l==zero ) then r = abs( m ) else r = sqrt( l*l+mm ) end if ! note that 0 .le. r .le. 1 + 1/macheps a = half*( s+r ) ! note that 1 .le. a .le. 1 + abs(m) ssmin = ha / a ssmax = fa*a if( mm==zero ) then ! note that m is very tiny if( l==zero ) then t = sign( two, ft )*sign( one, gt ) else t = gt / sign( d, ft ) + m / t end if else t = ( m / ( s+t )+m / ( r+l ) )*( one+a ) end if l = sqrt( t*t+four ) crt = two / l srt = t / l clt = ( crt+srt*m ) / a slt = ( ht / ft )*srt / a end if end if if( swap ) then csl = srt snl = crt csr = slt snr = clt else csl = clt snl = slt csr = crt snr = srt end if ! correct signs of ssmax and ssmin if( pmax==1_${ik}$ )tsign = sign( one, csr )*sign( one, csl )*sign( one, f ) if( pmax==2_${ik}$ )tsign = sign( one, snr )*sign( one, csl )*sign( one, g ) if( pmax==3_${ik}$ )tsign = sign( one, snr )*sign( one, snl )*sign( one, h ) ssmax = sign( ssmax, tsign ) ssmin = sign( ssmin, tsign*sign( one, f )*sign( one, h ) ) return end subroutine stdlib${ii}$_${ri}$lasv2 #:endif #:endfor pure module subroutine stdlib${ii}$_slartgs( x, y, sigma, cs, sn ) !! SLARTGS generates a plane rotation designed to introduce a bulge in !! Golub-Reinsch-style implicit QR iteration for the bidiagonal SVD !! problem. X and Y are the top-row entries, and SIGMA is the shift. !! The computed CS and SN define a plane rotation satisfying !! [ CS SN ] . [ X^2 - SIGMA ] = [ R ], !! [ -SN CS ] [ X * Y ] [ 0 ] !! with R nonnegative. If X^2 - SIGMA and X * Y are 0, then the !! rotation is by PI/2. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(out) :: cs, sn real(sp), intent(in) :: sigma, x, y ! =================================================================== ! Local Scalars real(sp) :: r, s, thresh, w, z thresh = stdlib${ii}$_slamch('E') ! compute the first column of b**t*b - sigma^2*i, up to a scale ! factor. if( (sigma == zero .and. abs(x) < thresh) .or.(abs(x) == sigma .and. y == zero) ) & then z = zero w = zero else if( sigma == zero ) then if( x >= zero ) then z = x w = y else z = -x w = -y end if else if( abs(x) < thresh ) then z = -sigma*sigma w = zero else if( x >= zero ) then s = one else s = negone end if z = s * (abs(x)-sigma) * (s+sigma/x) w = s * y end if ! generate the rotation. ! call stdlib${ii}$_slartgp( z, w, cs, sn, r ) might seem more natural; ! reordering the arguments ensures that if z = 0 then the rotation ! is by pi/2. call stdlib${ii}$_slartgp( w, z, sn, cs, r ) return ! end stdlib${ii}$_slartgs end subroutine stdlib${ii}$_slartgs pure module subroutine stdlib${ii}$_dlartgs( x, y, sigma, cs, sn ) !! DLARTGS generates a plane rotation designed to introduce a bulge in !! Golub-Reinsch-style implicit QR iteration for the bidiagonal SVD !! problem. X and Y are the top-row entries, and SIGMA is the shift. !! The computed CS and SN define a plane rotation satisfying !! [ CS SN ] . [ X^2 - SIGMA ] = [ R ], !! [ -SN CS ] [ X * Y ] [ 0 ] !! with R nonnegative. If X^2 - SIGMA and X * Y are 0, then the !! rotation is by PI/2. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(out) :: cs, sn real(dp), intent(in) :: sigma, x, y ! =================================================================== ! Local Scalars real(dp) :: r, s, thresh, w, z thresh = stdlib${ii}$_dlamch('E') ! compute the first column of b**t*b - sigma^2*i, up to a scale ! factor. if( (sigma == zero .and. abs(x) < thresh) .or.(abs(x) == sigma .and. y == zero) ) & then z = zero w = zero else if( sigma == zero ) then if( x >= zero ) then z = x w = y else z = -x w = -y end if else if( abs(x) < thresh ) then z = -sigma*sigma w = zero else if( x >= zero ) then s = one else s = negone end if z = s * (abs(x)-sigma) * (s+sigma/x) w = s * y end if ! generate the rotation. ! call stdlib${ii}$_dlartgp( z, w, cs, sn, r ) might seem more natural; ! reordering the arguments ensures that if z = 0 then the rotation ! is by pi/2. call stdlib${ii}$_dlartgp( w, z, sn, cs, r ) return ! end stdlib${ii}$_dlartgs end subroutine stdlib${ii}$_dlartgs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lartgs( x, y, sigma, cs, sn ) !! DLARTGS: generates a plane rotation designed to introduce a bulge in !! Golub-Reinsch-style implicit QR iteration for the bidiagonal SVD !! problem. X and Y are the top-row entries, and SIGMA is the shift. !! The computed CS and SN define a plane rotation satisfying !! [ CS SN ] . [ X^2 - SIGMA ] = [ R ], !! [ -SN CS ] [ X * Y ] [ 0 ] !! with R nonnegative. If X^2 - SIGMA and X * Y are 0, then the !! rotation is by PI/2. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(out) :: cs, sn real(${rk}$), intent(in) :: sigma, x, y ! =================================================================== ! Local Scalars real(${rk}$) :: r, s, thresh, w, z thresh = stdlib${ii}$_${ri}$lamch('E') ! compute the first column of b**t*b - sigma^2*i, up to a scale ! factor. if( (sigma == zero .and. abs(x) < thresh) .or.(abs(x) == sigma .and. y == zero) ) & then z = zero w = zero else if( sigma == zero ) then if( x >= zero ) then z = x w = y else z = -x w = -y end if else if( abs(x) < thresh ) then z = -sigma*sigma w = zero else if( x >= zero ) then s = one else s = negone end if z = s * (abs(x)-sigma) * (s+sigma/x) w = s * y end if ! generate the rotation. ! call stdlib${ii}$_${ri}$lartgp( z, w, cs, sn, r ) might seem more natural; ! reordering the arguments ensures that if z = 0 then the rotation ! is by pi/2. call stdlib${ii}$_${ri}$lartgp( w, z, sn, cs, r ) return ! end stdlib${ii}$_${ri}$lartgs end subroutine stdlib${ii}$_${ri}$lartgs #:endif #:endfor pure module subroutine stdlib${ii}$_slags2( upper, a1, a2, a3, b1, b2, b3, csu, snu, csv,snv, csq, snq ) !! SLAGS2 computes 2-by-2 orthogonal matrices U, V and Q, such !! that if ( UPPER ) then !! U**T *A*Q = U**T *( A1 A2 )*Q = ( x 0 ) !! ( 0 A3 ) ( x x ) !! and !! V**T*B*Q = V**T *( B1 B2 )*Q = ( x 0 ) !! ( 0 B3 ) ( x x ) !! or if ( .NOT.UPPER ) then !! U**T *A*Q = U**T *( A1 0 )*Q = ( x x ) !! ( A2 A3 ) ( 0 x ) !! and !! V**T*B*Q = V**T*( B1 0 )*Q = ( x x ) !! ( B2 B3 ) ( 0 x ) !! The rows of the transformed A and B are parallel, where !! U = ( CSU SNU ), V = ( CSV SNV ), Q = ( CSQ SNQ ) !! ( -SNU CSU ) ( -SNV CSV ) ( -SNQ CSQ ) !! Z**T denotes the transpose of Z. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: upper real(sp), intent(in) :: a1, a2, a3, b1, b2, b3 real(sp), intent(out) :: csq, csu, csv, snq, snu, snv ! ===================================================================== ! Local Scalars real(sp) :: a, aua11, aua12, aua21, aua22, avb11, avb12, avb21, avb22, csl, csr, d, s1,& s2, snl, snr, ua11r, ua22r, vb11r, vb22r, b, c, r, ua11, ua12, ua21, ua22, vb11, vb12,& vb21, vb22 ! Intrinsic Functions ! Executable Statements if( upper ) then ! input matrices a and b are upper triangular matrices ! form matrix c = a*adj(b) = ( a b ) ! ( 0 d ) a = a1*b3 d = a3*b1 b = a2*b1 - a1*b2 ! the svd of real 2-by-2 triangular c ! ( csl -snl )*( a b )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( 0 d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_slasv2( a, b, d, s1, s2, snr, csr, snl, csl ) if( abs( csl )>=abs( snl ) .or. abs( csr )>=abs( snr ) )then ! compute the (1,1) and (1,2) elements of u**t *a and v**t *b, ! and (1,2) element of |u|**t *|a| and |v|**t *|b|. ua11r = csl*a1 ua12 = csl*a2 + snl*a3 vb11r = csr*b1 vb12 = csr*b2 + snr*b3 aua12 = abs( csl )*abs( a2 ) + abs( snl )*abs( a3 ) avb12 = abs( csr )*abs( b2 ) + abs( snr )*abs( b3 ) ! zero (1,2) elements of u**t *a and v**t *b if( ( abs( ua11r )+abs( ua12 ) )/=zero ) then if( aua12 / ( abs( ua11r )+abs( ua12 ) )<=avb12 /( abs( vb11r )+abs( vb12 ) ) & ) then call stdlib${ii}$_slartg( -ua11r, ua12, csq, snq, r ) else call stdlib${ii}$_slartg( -vb11r, vb12, csq, snq, r ) end if else call stdlib${ii}$_slartg( -vb11r, vb12, csq, snq, r ) end if csu = csl snu = -snl csv = csr snv = -snr else ! compute the (2,1) and (2,2) elements of u**t *a and v**t *b, ! and (2,2) element of |u|**t *|a| and |v|**t *|b|. ua21 = -snl*a1 ua22 = -snl*a2 + csl*a3 vb21 = -snr*b1 vb22 = -snr*b2 + csr*b3 aua22 = abs( snl )*abs( a2 ) + abs( csl )*abs( a3 ) avb22 = abs( snr )*abs( b2 ) + abs( csr )*abs( b3 ) ! zero (2,2) elements of u**t*a and v**t*b, and then swap. if( ( abs( ua21 )+abs( ua22 ) )/=zero ) then if( aua22 / ( abs( ua21 )+abs( ua22 ) )<=avb22 /( abs( vb21 )+abs( vb22 ) ) ) & then call stdlib${ii}$_slartg( -ua21, ua22, csq, snq, r ) else call stdlib${ii}$_slartg( -vb21, vb22, csq, snq, r ) end if else call stdlib${ii}$_slartg( -vb21, vb22, csq, snq, r ) end if csu = snl snu = csl csv = snr snv = csr end if else ! input matrices a and b are lower triangular matrices ! form matrix c = a*adj(b) = ( a 0 ) ! ( c d ) a = a1*b3 d = a3*b1 c = a2*b3 - a3*b2 ! the svd of real 2-by-2 triangular c ! ( csl -snl )*( a 0 )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( c d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_slasv2( a, c, d, s1, s2, snr, csr, snl, csl ) if( abs( csr )>=abs( snr ) .or. abs( csl )>=abs( snl ) )then ! compute the (2,1) and (2,2) elements of u**t *a and v**t *b, ! and (2,1) element of |u|**t *|a| and |v|**t *|b|. ua21 = -snr*a1 + csr*a2 ua22r = csr*a3 vb21 = -snl*b1 + csl*b2 vb22r = csl*b3 aua21 = abs( snr )*abs( a1 ) + abs( csr )*abs( a2 ) avb21 = abs( snl )*abs( b1 ) + abs( csl )*abs( b2 ) ! zero (2,1) elements of u**t *a and v**t *b. if( ( abs( ua21 )+abs( ua22r ) )/=zero ) then if( aua21 / ( abs( ua21 )+abs( ua22r ) )<=avb21 /( abs( vb21 )+abs( vb22r ) ) & ) then call stdlib${ii}$_slartg( ua22r, ua21, csq, snq, r ) else call stdlib${ii}$_slartg( vb22r, vb21, csq, snq, r ) end if else call stdlib${ii}$_slartg( vb22r, vb21, csq, snq, r ) end if csu = csr snu = -snr csv = csl snv = -snl else ! compute the (1,1) and (1,2) elements of u**t *a and v**t *b, ! and (1,1) element of |u|**t *|a| and |v|**t *|b|. ua11 = csr*a1 + snr*a2 ua12 = snr*a3 vb11 = csl*b1 + snl*b2 vb12 = snl*b3 aua11 = abs( csr )*abs( a1 ) + abs( snr )*abs( a2 ) avb11 = abs( csl )*abs( b1 ) + abs( snl )*abs( b2 ) ! zero (1,1) elements of u**t*a and v**t*b, and then swap. if( ( abs( ua11 )+abs( ua12 ) )/=zero ) then if( aua11 / ( abs( ua11 )+abs( ua12 ) )<=avb11 /( abs( vb11 )+abs( vb12 ) ) ) & then call stdlib${ii}$_slartg( ua12, ua11, csq, snq, r ) else call stdlib${ii}$_slartg( vb12, vb11, csq, snq, r ) end if else call stdlib${ii}$_slartg( vb12, vb11, csq, snq, r ) end if csu = snr snu = csr csv = snl snv = csl end if end if return end subroutine stdlib${ii}$_slags2 pure module subroutine stdlib${ii}$_dlags2( upper, a1, a2, a3, b1, b2, b3, csu, snu, csv,snv, csq, snq ) !! DLAGS2 computes 2-by-2 orthogonal matrices U, V and Q, such !! that if ( UPPER ) then !! U**T *A*Q = U**T *( A1 A2 )*Q = ( x 0 ) !! ( 0 A3 ) ( x x ) !! and !! V**T*B*Q = V**T *( B1 B2 )*Q = ( x 0 ) !! ( 0 B3 ) ( x x ) !! or if ( .NOT.UPPER ) then !! U**T *A*Q = U**T *( A1 0 )*Q = ( x x ) !! ( A2 A3 ) ( 0 x ) !! and !! V**T*B*Q = V**T*( B1 0 )*Q = ( x x ) !! ( B2 B3 ) ( 0 x ) !! The rows of the transformed A and B are parallel, where !! U = ( CSU SNU ), V = ( CSV SNV ), Q = ( CSQ SNQ ) !! ( -SNU CSU ) ( -SNV CSV ) ( -SNQ CSQ ) !! Z**T denotes the transpose of Z. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: upper real(dp), intent(in) :: a1, a2, a3, b1, b2, b3 real(dp), intent(out) :: csq, csu, csv, snq, snu, snv ! ===================================================================== ! Local Scalars real(dp) :: a, aua11, aua12, aua21, aua22, avb11, avb12, avb21, avb22, b, c, csl, csr, & d, r, s1, s2, snl, snr, ua11, ua11r, ua12, ua21, ua22, ua22r, vb11, vb11r, vb12, vb21, & vb22, vb22r ! Intrinsic Functions ! Executable Statements if( upper ) then ! input matrices a and b are upper triangular matrices ! form matrix c = a*adj(b) = ( a b ) ! ( 0 d ) a = a1*b3 d = a3*b1 b = a2*b1 - a1*b2 ! the svd of real 2-by-2 triangular c ! ( csl -snl )*( a b )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( 0 d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_dlasv2( a, b, d, s1, s2, snr, csr, snl, csl ) if( abs( csl )>=abs( snl ) .or. abs( csr )>=abs( snr ) )then ! compute the (1,1) and (1,2) elements of u**t *a and v**t *b, ! and (1,2) element of |u|**t *|a| and |v|**t *|b|. ua11r = csl*a1 ua12 = csl*a2 + snl*a3 vb11r = csr*b1 vb12 = csr*b2 + snr*b3 aua12 = abs( csl )*abs( a2 ) + abs( snl )*abs( a3 ) avb12 = abs( csr )*abs( b2 ) + abs( snr )*abs( b3 ) ! zero (1,2) elements of u**t *a and v**t *b if( ( abs( ua11r )+abs( ua12 ) )/=zero ) then if( aua12 / ( abs( ua11r )+abs( ua12 ) )<=avb12 /( abs( vb11r )+abs( vb12 ) ) & ) then call stdlib${ii}$_dlartg( -ua11r, ua12, csq, snq, r ) else call stdlib${ii}$_dlartg( -vb11r, vb12, csq, snq, r ) end if else call stdlib${ii}$_dlartg( -vb11r, vb12, csq, snq, r ) end if csu = csl snu = -snl csv = csr snv = -snr else ! compute the (2,1) and (2,2) elements of u**t *a and v**t *b, ! and (2,2) element of |u|**t *|a| and |v|**t *|b|. ua21 = -snl*a1 ua22 = -snl*a2 + csl*a3 vb21 = -snr*b1 vb22 = -snr*b2 + csr*b3 aua22 = abs( snl )*abs( a2 ) + abs( csl )*abs( a3 ) avb22 = abs( snr )*abs( b2 ) + abs( csr )*abs( b3 ) ! zero (2,2) elements of u**t*a and v**t*b, and then swap. if( ( abs( ua21 )+abs( ua22 ) )/=zero ) then if( aua22 / ( abs( ua21 )+abs( ua22 ) )<=avb22 /( abs( vb21 )+abs( vb22 ) ) ) & then call stdlib${ii}$_dlartg( -ua21, ua22, csq, snq, r ) else call stdlib${ii}$_dlartg( -vb21, vb22, csq, snq, r ) end if else call stdlib${ii}$_dlartg( -vb21, vb22, csq, snq, r ) end if csu = snl snu = csl csv = snr snv = csr end if else ! input matrices a and b are lower triangular matrices ! form matrix c = a*adj(b) = ( a 0 ) ! ( c d ) a = a1*b3 d = a3*b1 c = a2*b3 - a3*b2 ! the svd of real 2-by-2 triangular c ! ( csl -snl )*( a 0 )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( c d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_dlasv2( a, c, d, s1, s2, snr, csr, snl, csl ) if( abs( csr )>=abs( snr ) .or. abs( csl )>=abs( snl ) )then ! compute the (2,1) and (2,2) elements of u**t *a and v**t *b, ! and (2,1) element of |u|**t *|a| and |v|**t *|b|. ua21 = -snr*a1 + csr*a2 ua22r = csr*a3 vb21 = -snl*b1 + csl*b2 vb22r = csl*b3 aua21 = abs( snr )*abs( a1 ) + abs( csr )*abs( a2 ) avb21 = abs( snl )*abs( b1 ) + abs( csl )*abs( b2 ) ! zero (2,1) elements of u**t *a and v**t *b. if( ( abs( ua21 )+abs( ua22r ) )/=zero ) then if( aua21 / ( abs( ua21 )+abs( ua22r ) )<=avb21 /( abs( vb21 )+abs( vb22r ) ) & ) then call stdlib${ii}$_dlartg( ua22r, ua21, csq, snq, r ) else call stdlib${ii}$_dlartg( vb22r, vb21, csq, snq, r ) end if else call stdlib${ii}$_dlartg( vb22r, vb21, csq, snq, r ) end if csu = csr snu = -snr csv = csl snv = -snl else ! compute the (1,1) and (1,2) elements of u**t *a and v**t *b, ! and (1,1) element of |u|**t *|a| and |v|**t *|b|. ua11 = csr*a1 + snr*a2 ua12 = snr*a3 vb11 = csl*b1 + snl*b2 vb12 = snl*b3 aua11 = abs( csr )*abs( a1 ) + abs( snr )*abs( a2 ) avb11 = abs( csl )*abs( b1 ) + abs( snl )*abs( b2 ) ! zero (1,1) elements of u**t*a and v**t*b, and then swap. if( ( abs( ua11 )+abs( ua12 ) )/=zero ) then if( aua11 / ( abs( ua11 )+abs( ua12 ) )<=avb11 /( abs( vb11 )+abs( vb12 ) ) ) & then call stdlib${ii}$_dlartg( ua12, ua11, csq, snq, r ) else call stdlib${ii}$_dlartg( vb12, vb11, csq, snq, r ) end if else call stdlib${ii}$_dlartg( vb12, vb11, csq, snq, r ) end if csu = snr snu = csr csv = snl snv = csl end if end if return end subroutine stdlib${ii}$_dlags2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lags2( upper, a1, a2, a3, b1, b2, b3, csu, snu, csv,snv, csq, snq ) !! DLAGS2: computes 2-by-2 orthogonal matrices U, V and Q, such !! that if ( UPPER ) then !! U**T *A*Q = U**T *( A1 A2 )*Q = ( x 0 ) !! ( 0 A3 ) ( x x ) !! and !! V**T*B*Q = V**T *( B1 B2 )*Q = ( x 0 ) !! ( 0 B3 ) ( x x ) !! or if ( .NOT.UPPER ) then !! U**T *A*Q = U**T *( A1 0 )*Q = ( x x ) !! ( A2 A3 ) ( 0 x ) !! and !! V**T*B*Q = V**T*( B1 0 )*Q = ( x x ) !! ( B2 B3 ) ( 0 x ) !! The rows of the transformed A and B are parallel, where !! U = ( CSU SNU ), V = ( CSV SNV ), Q = ( CSQ SNQ ) !! ( -SNU CSU ) ( -SNV CSV ) ( -SNQ CSQ ) !! Z**T denotes the transpose of Z. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: upper real(${rk}$), intent(in) :: a1, a2, a3, b1, b2, b3 real(${rk}$), intent(out) :: csq, csu, csv, snq, snu, snv ! ===================================================================== ! Local Scalars real(${rk}$) :: a, aua11, aua12, aua21, aua22, avb11, avb12, avb21, avb22, b, c, csl, csr, & d, r, s1, s2, snl, snr, ua11, ua11r, ua12, ua21, ua22, ua22r, vb11, vb11r, vb12, vb21, & vb22, vb22r ! Intrinsic Functions ! Executable Statements if( upper ) then ! input matrices a and b are upper triangular matrices ! form matrix c = a*adj(b) = ( a b ) ! ( 0 d ) a = a1*b3 d = a3*b1 b = a2*b1 - a1*b2 ! the svd of real 2-by-2 triangular c ! ( csl -snl )*( a b )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( 0 d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_${ri}$lasv2( a, b, d, s1, s2, snr, csr, snl, csl ) if( abs( csl )>=abs( snl ) .or. abs( csr )>=abs( snr ) )then ! compute the (1,1) and (1,2) elements of u**t *a and v**t *b, ! and (1,2) element of |u|**t *|a| and |v|**t *|b|. ua11r = csl*a1 ua12 = csl*a2 + snl*a3 vb11r = csr*b1 vb12 = csr*b2 + snr*b3 aua12 = abs( csl )*abs( a2 ) + abs( snl )*abs( a3 ) avb12 = abs( csr )*abs( b2 ) + abs( snr )*abs( b3 ) ! zero (1,2) elements of u**t *a and v**t *b if( ( abs( ua11r )+abs( ua12 ) )/=zero ) then if( aua12 / ( abs( ua11r )+abs( ua12 ) )<=avb12 /( abs( vb11r )+abs( vb12 ) ) & ) then call stdlib${ii}$_${ri}$lartg( -ua11r, ua12, csq, snq, r ) else call stdlib${ii}$_${ri}$lartg( -vb11r, vb12, csq, snq, r ) end if else call stdlib${ii}$_${ri}$lartg( -vb11r, vb12, csq, snq, r ) end if csu = csl snu = -snl csv = csr snv = -snr else ! compute the (2,1) and (2,2) elements of u**t *a and v**t *b, ! and (2,2) element of |u|**t *|a| and |v|**t *|b|. ua21 = -snl*a1 ua22 = -snl*a2 + csl*a3 vb21 = -snr*b1 vb22 = -snr*b2 + csr*b3 aua22 = abs( snl )*abs( a2 ) + abs( csl )*abs( a3 ) avb22 = abs( snr )*abs( b2 ) + abs( csr )*abs( b3 ) ! zero (2,2) elements of u**t*a and v**t*b, and then swap. if( ( abs( ua21 )+abs( ua22 ) )/=zero ) then if( aua22 / ( abs( ua21 )+abs( ua22 ) )<=avb22 /( abs( vb21 )+abs( vb22 ) ) ) & then call stdlib${ii}$_${ri}$lartg( -ua21, ua22, csq, snq, r ) else call stdlib${ii}$_${ri}$lartg( -vb21, vb22, csq, snq, r ) end if else call stdlib${ii}$_${ri}$lartg( -vb21, vb22, csq, snq, r ) end if csu = snl snu = csl csv = snr snv = csr end if else ! input matrices a and b are lower triangular matrices ! form matrix c = a*adj(b) = ( a 0 ) ! ( c d ) a = a1*b3 d = a3*b1 c = a2*b3 - a3*b2 ! the svd of real 2-by-2 triangular c ! ( csl -snl )*( a 0 )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( c d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_${ri}$lasv2( a, c, d, s1, s2, snr, csr, snl, csl ) if( abs( csr )>=abs( snr ) .or. abs( csl )>=abs( snl ) )then ! compute the (2,1) and (2,2) elements of u**t *a and v**t *b, ! and (2,1) element of |u|**t *|a| and |v|**t *|b|. ua21 = -snr*a1 + csr*a2 ua22r = csr*a3 vb21 = -snl*b1 + csl*b2 vb22r = csl*b3 aua21 = abs( snr )*abs( a1 ) + abs( csr )*abs( a2 ) avb21 = abs( snl )*abs( b1 ) + abs( csl )*abs( b2 ) ! zero (2,1) elements of u**t *a and v**t *b. if( ( abs( ua21 )+abs( ua22r ) )/=zero ) then if( aua21 / ( abs( ua21 )+abs( ua22r ) )<=avb21 /( abs( vb21 )+abs( vb22r ) ) & ) then call stdlib${ii}$_${ri}$lartg( ua22r, ua21, csq, snq, r ) else call stdlib${ii}$_${ri}$lartg( vb22r, vb21, csq, snq, r ) end if else call stdlib${ii}$_${ri}$lartg( vb22r, vb21, csq, snq, r ) end if csu = csr snu = -snr csv = csl snv = -snl else ! compute the (1,1) and (1,2) elements of u**t *a and v**t *b, ! and (1,1) element of |u|**t *|a| and |v|**t *|b|. ua11 = csr*a1 + snr*a2 ua12 = snr*a3 vb11 = csl*b1 + snl*b2 vb12 = snl*b3 aua11 = abs( csr )*abs( a1 ) + abs( snr )*abs( a2 ) avb11 = abs( csl )*abs( b1 ) + abs( snl )*abs( b2 ) ! zero (1,1) elements of u**t*a and v**t*b, and then swap. if( ( abs( ua11 )+abs( ua12 ) )/=zero ) then if( aua11 / ( abs( ua11 )+abs( ua12 ) )<=avb11 /( abs( vb11 )+abs( vb12 ) ) ) & then call stdlib${ii}$_${ri}$lartg( ua12, ua11, csq, snq, r ) else call stdlib${ii}$_${ri}$lartg( vb12, vb11, csq, snq, r ) end if else call stdlib${ii}$_${ri}$lartg( vb12, vb11, csq, snq, r ) end if csu = snr snu = csr csv = snl snv = csl end if end if return end subroutine stdlib${ii}$_${ri}$lags2 #:endif #:endfor pure module subroutine stdlib${ii}$_clags2( upper, a1, a2, a3, b1, b2, b3, csu, snu, csv,snv, csq, snq ) !! CLAGS2 computes 2-by-2 unitary matrices U, V and Q, such !! that if ( UPPER ) then !! U**H *A*Q = U**H *( A1 A2 )*Q = ( x 0 ) !! ( 0 A3 ) ( x x ) !! and !! V**H*B*Q = V**H *( B1 B2 )*Q = ( x 0 ) !! ( 0 B3 ) ( x x ) !! or if ( .NOT.UPPER ) then !! U**H *A*Q = U**H *( A1 0 )*Q = ( x x ) !! ( A2 A3 ) ( 0 x ) !! and !! V**H *B*Q = V**H *( B1 0 )*Q = ( x x ) !! ( B2 B3 ) ( 0 x ) !! where !! U = ( CSU SNU ), V = ( CSV SNV ), !! ( -SNU**H CSU ) ( -SNV**H CSV ) !! Q = ( CSQ SNQ ) !! ( -SNQ**H CSQ ) !! The rows of the transformed A and B are parallel. Moreover, if the !! input 2-by-2 matrix A is not zero, then the transformed (1,1) entry !! of A is not zero. If the input matrices A and B are both not zero, !! then the transformed (2,2) element of B is not zero, except when the !! first rows of input A and B are parallel and the second rows are !! zero. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: upper real(sp), intent(in) :: a1, a3, b1, b3 real(sp), intent(out) :: csq, csu, csv complex(sp), intent(in) :: a2, b2 complex(sp), intent(out) :: snq, snu, snv ! ===================================================================== ! Local Scalars real(sp) :: a, aua11, aua12, aua21, aua22, avb11, avb12, avb21, avb22, csl, csr, d, fb,& fc, s1, s2, snl, snr, ua11r, ua22r, vb11r, vb22r complex(sp) :: b, c, d1, r, t, ua11, ua12, ua21, ua22, vb11, vb12, vb21, vb22 ! Intrinsic Functions ! Statement Functions real(sp) :: abs1 ! Statement Function Definitions abs1( t ) = abs( real( t,KIND=sp) ) + abs( aimag( t ) ) ! Executable Statements if( upper ) then ! input matrices a and b are upper triangular matrices ! form matrix c = a*adj(b) = ( a b ) ! ( 0 d ) a = a1*b3 d = a3*b1 b = a2*b1 - a1*b2 fb = abs( b ) ! transform complex 2-by-2 matrix c to real matrix by unitary ! diagonal matrix diag(1,d1). d1 = one if( fb/=zero )d1 = b / fb ! the svd of real 2 by 2 triangular c ! ( csl -snl )*( a b )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( 0 d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_slasv2( a, fb, d, s1, s2, snr, csr, snl, csl ) if( abs( csl )>=abs( snl ) .or. abs( csr )>=abs( snr ) )then ! compute the (1,1) and (1,2) elements of u**h *a and v**h *b, ! and (1,2) element of |u|**h *|a| and |v|**h *|b|. ua11r = csl*a1 ua12 = csl*a2 + d1*snl*a3 vb11r = csr*b1 vb12 = csr*b2 + d1*snr*b3 aua12 = abs( csl )*abs1( a2 ) + abs( snl )*abs( a3 ) avb12 = abs( csr )*abs1( b2 ) + abs( snr )*abs( b3 ) ! zero (1,2) elements of u**h *a and v**h *b if( ( abs( ua11r )+abs1( ua12 ) )==zero ) then call stdlib${ii}$_clartg( -cmplx( vb11r,KIND=sp), conjg( vb12 ), csq, snq,r ) else if( ( abs( vb11r )+abs1( vb12 ) )==zero ) then call stdlib${ii}$_clartg( -cmplx( ua11r,KIND=sp), conjg( ua12 ), csq, snq,r ) else if( aua12 / ( abs( ua11r )+abs1( ua12 ) )<=avb12 /( abs( vb11r )+abs1( vb12 & ) ) ) then call stdlib${ii}$_clartg( -cmplx( ua11r,KIND=sp), conjg( ua12 ), csq, snq,r ) else call stdlib${ii}$_clartg( -cmplx( vb11r,KIND=sp), conjg( vb12 ), csq, snq,r ) end if csu = csl snu = -d1*snl csv = csr snv = -d1*snr else ! compute the (2,1) and (2,2) elements of u**h *a and v**h *b, ! and (2,2) element of |u|**h *|a| and |v|**h *|b|. ua21 = -conjg( d1 )*snl*a1 ua22 = -conjg( d1 )*snl*a2 + csl*a3 vb21 = -conjg( d1 )*snr*b1 vb22 = -conjg( d1 )*snr*b2 + csr*b3 aua22 = abs( snl )*abs1( a2 ) + abs( csl )*abs( a3 ) avb22 = abs( snr )*abs1( b2 ) + abs( csr )*abs( b3 ) ! zero (2,2) elements of u**h *a and v**h *b, and then swap. if( ( abs1( ua21 )+abs1( ua22 ) )==zero ) then call stdlib${ii}$_clartg( -conjg( vb21 ), conjg( vb22 ), csq, snq, r ) else if( ( abs1( vb21 )+abs( vb22 ) )==zero ) then call stdlib${ii}$_clartg( -conjg( ua21 ), conjg( ua22 ), csq, snq, r ) else if( aua22 / ( abs1( ua21 )+abs1( ua22 ) )<=avb22 /( abs1( vb21 )+abs1( vb22 & ) ) ) then call stdlib${ii}$_clartg( -conjg( ua21 ), conjg( ua22 ), csq, snq, r ) else call stdlib${ii}$_clartg( -conjg( vb21 ), conjg( vb22 ), csq, snq, r ) end if csu = snl snu = d1*csl csv = snr snv = d1*csr end if else ! input matrices a and b are lower triangular matrices ! form matrix c = a*adj(b) = ( a 0 ) ! ( c d ) a = a1*b3 d = a3*b1 c = a2*b3 - a3*b2 fc = abs( c ) ! transform complex 2-by-2 matrix c to real matrix by unitary ! diagonal matrix diag(d1,1). d1 = one if( fc/=zero )d1 = c / fc ! the svd of real 2 by 2 triangular c ! ( csl -snl )*( a 0 )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( c d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_slasv2( a, fc, d, s1, s2, snr, csr, snl, csl ) if( abs( csr )>=abs( snr ) .or. abs( csl )>=abs( snl ) )then ! compute the (2,1) and (2,2) elements of u**h *a and v**h *b, ! and (2,1) element of |u|**h *|a| and |v|**h *|b|. ua21 = -d1*snr*a1 + csr*a2 ua22r = csr*a3 vb21 = -d1*snl*b1 + csl*b2 vb22r = csl*b3 aua21 = abs( snr )*abs( a1 ) + abs( csr )*abs1( a2 ) avb21 = abs( snl )*abs( b1 ) + abs( csl )*abs1( b2 ) ! zero (2,1) elements of u**h *a and v**h *b. if( ( abs1( ua21 )+abs( ua22r ) )==zero ) then call stdlib${ii}$_clartg( cmplx( vb22r,KIND=sp), vb21, csq, snq, r ) else if( ( abs1( vb21 )+abs( vb22r ) )==zero ) then call stdlib${ii}$_clartg( cmplx( ua22r,KIND=sp), ua21, csq, snq, r ) else if( aua21 / ( abs1( ua21 )+abs( ua22r ) )<=avb21 /( abs1( vb21 )+abs( vb22r & ) ) ) then call stdlib${ii}$_clartg( cmplx( ua22r,KIND=sp), ua21, csq, snq, r ) else call stdlib${ii}$_clartg( cmplx( vb22r,KIND=sp), vb21, csq, snq, r ) end if csu = csr snu = -conjg( d1 )*snr csv = csl snv = -conjg( d1 )*snl else ! compute the (1,1) and (1,2) elements of u**h *a and v**h *b, ! and (1,1) element of |u|**h *|a| and |v|**h *|b|. ua11 = csr*a1 + conjg( d1 )*snr*a2 ua12 = conjg( d1 )*snr*a3 vb11 = csl*b1 + conjg( d1 )*snl*b2 vb12 = conjg( d1 )*snl*b3 aua11 = abs( csr )*abs( a1 ) + abs( snr )*abs1( a2 ) avb11 = abs( csl )*abs( b1 ) + abs( snl )*abs1( b2 ) ! zero (1,1) elements of u**h *a and v**h *b, and then swap. if( ( abs1( ua11 )+abs1( ua12 ) )==zero ) then call stdlib${ii}$_clartg( vb12, vb11, csq, snq, r ) else if( ( abs1( vb11 )+abs1( vb12 ) )==zero ) then call stdlib${ii}$_clartg( ua12, ua11, csq, snq, r ) else if( aua11 / ( abs1( ua11 )+abs1( ua12 ) )<=avb11 /( abs1( vb11 )+abs1( vb12 & ) ) ) then call stdlib${ii}$_clartg( ua12, ua11, csq, snq, r ) else call stdlib${ii}$_clartg( vb12, vb11, csq, snq, r ) end if csu = snr snu = conjg( d1 )*csr csv = snl snv = conjg( d1 )*csl end if end if return end subroutine stdlib${ii}$_clags2 pure module subroutine stdlib${ii}$_zlags2( upper, a1, a2, a3, b1, b2, b3, csu, snu, csv,snv, csq, snq ) !! ZLAGS2 computes 2-by-2 unitary matrices U, V and Q, such !! that if ( UPPER ) then !! U**H *A*Q = U**H *( A1 A2 )*Q = ( x 0 ) !! ( 0 A3 ) ( x x ) !! and !! V**H*B*Q = V**H *( B1 B2 )*Q = ( x 0 ) !! ( 0 B3 ) ( x x ) !! or if ( .NOT.UPPER ) then !! U**H *A*Q = U**H *( A1 0 )*Q = ( x x ) !! ( A2 A3 ) ( 0 x ) !! and !! V**H *B*Q = V**H *( B1 0 )*Q = ( x x ) !! ( B2 B3 ) ( 0 x ) !! where !! U = ( CSU SNU ), V = ( CSV SNV ), !! ( -SNU**H CSU ) ( -SNV**H CSV ) !! Q = ( CSQ SNQ ) !! ( -SNQ**H CSQ ) !! The rows of the transformed A and B are parallel. Moreover, if the !! input 2-by-2 matrix A is not zero, then the transformed (1,1) entry !! of A is not zero. If the input matrices A and B are both not zero, !! then the transformed (2,2) element of B is not zero, except when the !! first rows of input A and B are parallel and the second rows are !! zero. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: upper real(dp), intent(in) :: a1, a3, b1, b3 real(dp), intent(out) :: csq, csu, csv complex(dp), intent(in) :: a2, b2 complex(dp), intent(out) :: snq, snu, snv ! ===================================================================== ! Local Scalars real(dp) :: a, aua11, aua12, aua21, aua22, avb12, avb11, avb21, avb22, csl, csr, d, fb,& fc, s1, s2, snl, snr, ua11r, ua22r, vb11r, vb22r complex(dp) :: b, c, d1, r, t, ua11, ua12, ua21, ua22, vb11, vb12, vb21, vb22 ! Intrinsic Functions ! Statement Functions real(dp) :: abs1 ! Statement Function Definitions abs1( t ) = abs( real( t,KIND=dp) ) + abs( aimag( t ) ) ! Executable Statements if( upper ) then ! input matrices a and b are upper triangular matrices ! form matrix c = a*adj(b) = ( a b ) ! ( 0 d ) a = a1*b3 d = a3*b1 b = a2*b1 - a1*b2 fb = abs( b ) ! transform complex 2-by-2 matrix c to real matrix by unitary ! diagonal matrix diag(1,d1). d1 = one if( fb/=zero )d1 = b / fb ! the svd of real 2 by 2 triangular c ! ( csl -snl )*( a b )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( 0 d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_dlasv2( a, fb, d, s1, s2, snr, csr, snl, csl ) if( abs( csl )>=abs( snl ) .or. abs( csr )>=abs( snr ) )then ! compute the (1,1) and (1,2) elements of u**h *a and v**h *b, ! and (1,2) element of |u|**h *|a| and |v|**h *|b|. ua11r = csl*a1 ua12 = csl*a2 + d1*snl*a3 vb11r = csr*b1 vb12 = csr*b2 + d1*snr*b3 aua12 = abs( csl )*abs1( a2 ) + abs( snl )*abs( a3 ) avb12 = abs( csr )*abs1( b2 ) + abs( snr )*abs( b3 ) ! zero (1,2) elements of u**h *a and v**h *b if( ( abs( ua11r )+abs1( ua12 ) )==zero ) then call stdlib${ii}$_zlartg( -cmplx( vb11r,KIND=dp), conjg( vb12 ), csq, snq,r ) else if( ( abs( vb11r )+abs1( vb12 ) )==zero ) then call stdlib${ii}$_zlartg( -cmplx( ua11r,KIND=dp), conjg( ua12 ), csq, snq,r ) else if( aua12 / ( abs( ua11r )+abs1( ua12 ) )<=avb12 /( abs( vb11r )+abs1( vb12 & ) ) ) then call stdlib${ii}$_zlartg( -cmplx( ua11r,KIND=dp), conjg( ua12 ), csq, snq,r ) else call stdlib${ii}$_zlartg( -cmplx( vb11r,KIND=dp), conjg( vb12 ), csq, snq,r ) end if csu = csl snu = -d1*snl csv = csr snv = -d1*snr else ! compute the (2,1) and (2,2) elements of u**h *a and v**h *b, ! and (2,2) element of |u|**h *|a| and |v|**h *|b|. ua21 = -conjg( d1 )*snl*a1 ua22 = -conjg( d1 )*snl*a2 + csl*a3 vb21 = -conjg( d1 )*snr*b1 vb22 = -conjg( d1 )*snr*b2 + csr*b3 aua22 = abs( snl )*abs1( a2 ) + abs( csl )*abs( a3 ) avb22 = abs( snr )*abs1( b2 ) + abs( csr )*abs( b3 ) ! zero (2,2) elements of u**h *a and v**h *b, and then swap. if( ( abs1( ua21 )+abs1( ua22 ) )==zero ) then call stdlib${ii}$_zlartg( -conjg( vb21 ), conjg( vb22 ), csq, snq,r ) else if( ( abs1( vb21 )+abs( vb22 ) )==zero ) then call stdlib${ii}$_zlartg( -conjg( ua21 ), conjg( ua22 ), csq, snq,r ) else if( aua22 / ( abs1( ua21 )+abs1( ua22 ) )<=avb22 /( abs1( vb21 )+abs1( vb22 & ) ) ) then call stdlib${ii}$_zlartg( -conjg( ua21 ), conjg( ua22 ), csq, snq,r ) else call stdlib${ii}$_zlartg( -conjg( vb21 ), conjg( vb22 ), csq, snq,r ) end if csu = snl snu = d1*csl csv = snr snv = d1*csr end if else ! input matrices a and b are lower triangular matrices ! form matrix c = a*adj(b) = ( a 0 ) ! ( c d ) a = a1*b3 d = a3*b1 c = a2*b3 - a3*b2 fc = abs( c ) ! transform complex 2-by-2 matrix c to real matrix by unitary ! diagonal matrix diag(d1,1). d1 = one if( fc/=zero )d1 = c / fc ! the svd of real 2 by 2 triangular c ! ( csl -snl )*( a 0 )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( c d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_dlasv2( a, fc, d, s1, s2, snr, csr, snl, csl ) if( abs( csr )>=abs( snr ) .or. abs( csl )>=abs( snl ) )then ! compute the (2,1) and (2,2) elements of u**h *a and v**h *b, ! and (2,1) element of |u|**h *|a| and |v|**h *|b|. ua21 = -d1*snr*a1 + csr*a2 ua22r = csr*a3 vb21 = -d1*snl*b1 + csl*b2 vb22r = csl*b3 aua21 = abs( snr )*abs( a1 ) + abs( csr )*abs1( a2 ) avb21 = abs( snl )*abs( b1 ) + abs( csl )*abs1( b2 ) ! zero (2,1) elements of u**h *a and v**h *b. if( ( abs1( ua21 )+abs( ua22r ) )==zero ) then call stdlib${ii}$_zlartg( cmplx( vb22r,KIND=dp), vb21, csq, snq, r ) else if( ( abs1( vb21 )+abs( vb22r ) )==zero ) then call stdlib${ii}$_zlartg( cmplx( ua22r,KIND=dp), ua21, csq, snq, r ) else if( aua21 / ( abs1( ua21 )+abs( ua22r ) )<=avb21 /( abs1( vb21 )+abs( vb22r & ) ) ) then call stdlib${ii}$_zlartg( cmplx( ua22r,KIND=dp), ua21, csq, snq, r ) else call stdlib${ii}$_zlartg( cmplx( vb22r,KIND=dp), vb21, csq, snq, r ) end if csu = csr snu = -conjg( d1 )*snr csv = csl snv = -conjg( d1 )*snl else ! compute the (1,1) and (1,2) elements of u**h *a and v**h *b, ! and (1,1) element of |u|**h *|a| and |v|**h *|b|. ua11 = csr*a1 + conjg( d1 )*snr*a2 ua12 = conjg( d1 )*snr*a3 vb11 = csl*b1 + conjg( d1 )*snl*b2 vb12 = conjg( d1 )*snl*b3 aua11 = abs( csr )*abs( a1 ) + abs( snr )*abs1( a2 ) avb11 = abs( csl )*abs( b1 ) + abs( snl )*abs1( b2 ) ! zero (1,1) elements of u**h *a and v**h *b, and then swap. if( ( abs1( ua11 )+abs1( ua12 ) )==zero ) then call stdlib${ii}$_zlartg( vb12, vb11, csq, snq, r ) else if( ( abs1( vb11 )+abs1( vb12 ) )==zero ) then call stdlib${ii}$_zlartg( ua12, ua11, csq, snq, r ) else if( aua11 / ( abs1( ua11 )+abs1( ua12 ) )<=avb11 /( abs1( vb11 )+abs1( vb12 & ) ) ) then call stdlib${ii}$_zlartg( ua12, ua11, csq, snq, r ) else call stdlib${ii}$_zlartg( vb12, vb11, csq, snq, r ) end if csu = snr snu = conjg( d1 )*csr csv = snl snv = conjg( d1 )*csl end if end if return end subroutine stdlib${ii}$_zlags2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lags2( upper, a1, a2, a3, b1, b2, b3, csu, snu, csv,snv, csq, snq ) !! ZLAGS2: computes 2-by-2 unitary matrices U, V and Q, such !! that if ( UPPER ) then !! U**H *A*Q = U**H *( A1 A2 )*Q = ( x 0 ) !! ( 0 A3 ) ( x x ) !! and !! V**H*B*Q = V**H *( B1 B2 )*Q = ( x 0 ) !! ( 0 B3 ) ( x x ) !! or if ( .NOT.UPPER ) then !! U**H *A*Q = U**H *( A1 0 )*Q = ( x x ) !! ( A2 A3 ) ( 0 x ) !! and !! V**H *B*Q = V**H *( B1 0 )*Q = ( x x ) !! ( B2 B3 ) ( 0 x ) !! where !! U = ( CSU SNU ), V = ( CSV SNV ), !! ( -SNU**H CSU ) ( -SNV**H CSV ) !! Q = ( CSQ SNQ ) !! ( -SNQ**H CSQ ) !! The rows of the transformed A and B are parallel. Moreover, if the !! input 2-by-2 matrix A is not zero, then the transformed (1,1) entry !! of A is not zero. If the input matrices A and B are both not zero, !! then the transformed (2,2) element of B is not zero, except when the !! first rows of input A and B are parallel and the second rows are !! zero. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: upper real(${ck}$), intent(in) :: a1, a3, b1, b3 real(${ck}$), intent(out) :: csq, csu, csv complex(${ck}$), intent(in) :: a2, b2 complex(${ck}$), intent(out) :: snq, snu, snv ! ===================================================================== ! Local Scalars real(${ck}$) :: a, aua11, aua12, aua21, aua22, avb12, avb11, avb21, avb22, csl, csr, d, fb,& fc, s1, s2, snl, snr, ua11r, ua22r, vb11r, vb22r complex(${ck}$) :: b, c, d1, r, t, ua11, ua12, ua21, ua22, vb11, vb12, vb21, vb22 ! Intrinsic Functions ! Statement Functions real(${ck}$) :: abs1 ! Statement Function Definitions abs1( t ) = abs( real( t,KIND=${ck}$) ) + abs( aimag( t ) ) ! Executable Statements if( upper ) then ! input matrices a and b are upper triangular matrices ! form matrix c = a*adj(b) = ( a b ) ! ( 0 d ) a = a1*b3 d = a3*b1 b = a2*b1 - a1*b2 fb = abs( b ) ! transform complex 2-by-2 matrix c to real matrix by unitary ! diagonal matrix diag(1,d1). d1 = one if( fb/=zero )d1 = b / fb ! the svd of real 2 by 2 triangular c ! ( csl -snl )*( a b )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( 0 d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_${c2ri(ci)}$lasv2( a, fb, d, s1, s2, snr, csr, snl, csl ) if( abs( csl )>=abs( snl ) .or. abs( csr )>=abs( snr ) )then ! compute the (1,1) and (1,2) elements of u**h *a and v**h *b, ! and (1,2) element of |u|**h *|a| and |v|**h *|b|. ua11r = csl*a1 ua12 = csl*a2 + d1*snl*a3 vb11r = csr*b1 vb12 = csr*b2 + d1*snr*b3 aua12 = abs( csl )*abs1( a2 ) + abs( snl )*abs( a3 ) avb12 = abs( csr )*abs1( b2 ) + abs( snr )*abs( b3 ) ! zero (1,2) elements of u**h *a and v**h *b if( ( abs( ua11r )+abs1( ua12 ) )==zero ) then call stdlib${ii}$_${ci}$lartg( -cmplx( vb11r,KIND=${ck}$), conjg( vb12 ), csq, snq,r ) else if( ( abs( vb11r )+abs1( vb12 ) )==zero ) then call stdlib${ii}$_${ci}$lartg( -cmplx( ua11r,KIND=${ck}$), conjg( ua12 ), csq, snq,r ) else if( aua12 / ( abs( ua11r )+abs1( ua12 ) )<=avb12 /( abs( vb11r )+abs1( vb12 & ) ) ) then call stdlib${ii}$_${ci}$lartg( -cmplx( ua11r,KIND=${ck}$), conjg( ua12 ), csq, snq,r ) else call stdlib${ii}$_${ci}$lartg( -cmplx( vb11r,KIND=${ck}$), conjg( vb12 ), csq, snq,r ) end if csu = csl snu = -d1*snl csv = csr snv = -d1*snr else ! compute the (2,1) and (2,2) elements of u**h *a and v**h *b, ! and (2,2) element of |u|**h *|a| and |v|**h *|b|. ua21 = -conjg( d1 )*snl*a1 ua22 = -conjg( d1 )*snl*a2 + csl*a3 vb21 = -conjg( d1 )*snr*b1 vb22 = -conjg( d1 )*snr*b2 + csr*b3 aua22 = abs( snl )*abs1( a2 ) + abs( csl )*abs( a3 ) avb22 = abs( snr )*abs1( b2 ) + abs( csr )*abs( b3 ) ! zero (2,2) elements of u**h *a and v**h *b, and then swap. if( ( abs1( ua21 )+abs1( ua22 ) )==zero ) then call stdlib${ii}$_${ci}$lartg( -conjg( vb21 ), conjg( vb22 ), csq, snq,r ) else if( ( abs1( vb21 )+abs( vb22 ) )==zero ) then call stdlib${ii}$_${ci}$lartg( -conjg( ua21 ), conjg( ua22 ), csq, snq,r ) else if( aua22 / ( abs1( ua21 )+abs1( ua22 ) )<=avb22 /( abs1( vb21 )+abs1( vb22 & ) ) ) then call stdlib${ii}$_${ci}$lartg( -conjg( ua21 ), conjg( ua22 ), csq, snq,r ) else call stdlib${ii}$_${ci}$lartg( -conjg( vb21 ), conjg( vb22 ), csq, snq,r ) end if csu = snl snu = d1*csl csv = snr snv = d1*csr end if else ! input matrices a and b are lower triangular matrices ! form matrix c = a*adj(b) = ( a 0 ) ! ( c d ) a = a1*b3 d = a3*b1 c = a2*b3 - a3*b2 fc = abs( c ) ! transform complex 2-by-2 matrix c to real matrix by unitary ! diagonal matrix diag(d1,1). d1 = one if( fc/=zero )d1 = c / fc ! the svd of real 2 by 2 triangular c ! ( csl -snl )*( a 0 )*( csr snr ) = ( r 0 ) ! ( snl csl ) ( c d ) ( -snr csr ) ( 0 t ) call stdlib${ii}$_${c2ri(ci)}$lasv2( a, fc, d, s1, s2, snr, csr, snl, csl ) if( abs( csr )>=abs( snr ) .or. abs( csl )>=abs( snl ) )then ! compute the (2,1) and (2,2) elements of u**h *a and v**h *b, ! and (2,1) element of |u|**h *|a| and |v|**h *|b|. ua21 = -d1*snr*a1 + csr*a2 ua22r = csr*a3 vb21 = -d1*snl*b1 + csl*b2 vb22r = csl*b3 aua21 = abs( snr )*abs( a1 ) + abs( csr )*abs1( a2 ) avb21 = abs( snl )*abs( b1 ) + abs( csl )*abs1( b2 ) ! zero (2,1) elements of u**h *a and v**h *b. if( ( abs1( ua21 )+abs( ua22r ) )==zero ) then call stdlib${ii}$_${ci}$lartg( cmplx( vb22r,KIND=${ck}$), vb21, csq, snq, r ) else if( ( abs1( vb21 )+abs( vb22r ) )==zero ) then call stdlib${ii}$_${ci}$lartg( cmplx( ua22r,KIND=${ck}$), ua21, csq, snq, r ) else if( aua21 / ( abs1( ua21 )+abs( ua22r ) )<=avb21 /( abs1( vb21 )+abs( vb22r & ) ) ) then call stdlib${ii}$_${ci}$lartg( cmplx( ua22r,KIND=${ck}$), ua21, csq, snq, r ) else call stdlib${ii}$_${ci}$lartg( cmplx( vb22r,KIND=${ck}$), vb21, csq, snq, r ) end if csu = csr snu = -conjg( d1 )*snr csv = csl snv = -conjg( d1 )*snl else ! compute the (1,1) and (1,2) elements of u**h *a and v**h *b, ! and (1,1) element of |u|**h *|a| and |v|**h *|b|. ua11 = csr*a1 + conjg( d1 )*snr*a2 ua12 = conjg( d1 )*snr*a3 vb11 = csl*b1 + conjg( d1 )*snl*b2 vb12 = conjg( d1 )*snl*b3 aua11 = abs( csr )*abs( a1 ) + abs( snr )*abs1( a2 ) avb11 = abs( csl )*abs( b1 ) + abs( snl )*abs1( b2 ) ! zero (1,1) elements of u**h *a and v**h *b, and then swap. if( ( abs1( ua11 )+abs1( ua12 ) )==zero ) then call stdlib${ii}$_${ci}$lartg( vb12, vb11, csq, snq, r ) else if( ( abs1( vb11 )+abs1( vb12 ) )==zero ) then call stdlib${ii}$_${ci}$lartg( ua12, ua11, csq, snq, r ) else if( aua11 / ( abs1( ua11 )+abs1( ua12 ) )<=avb11 /( abs1( vb11 )+abs1( vb12 & ) ) ) then call stdlib${ii}$_${ci}$lartg( ua12, ua11, csq, snq, r ) else call stdlib${ii}$_${ci}$lartg( vb12, vb11, csq, snq, r ) end if csu = snr snu = conjg( d1 )*csr csv = snl snv = conjg( d1 )*csl end if end if return end subroutine stdlib${ii}$_${ci}$lags2 #:endif #:endfor pure module subroutine stdlib${ii}$_slapll( n, x, incx, y, incy, ssmin ) !! Given two column vectors X and Y, let !! A = ( X Y ). !! The subroutine first computes the QR factorization of A = Q*R, !! and then computes the SVD of the 2-by-2 upper triangular matrix R. !! The smaller singular value of R is returned in SSMIN, which is used !! as the measurement of the linear dependency of the vectors X and Y. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n real(sp), intent(out) :: ssmin ! Array Arguments real(sp), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(sp) :: a11, a12, a22, c, ssmax, tau ! Executable Statements ! quick return if possible if( n<=1_${ik}$ ) then ssmin = zero return end if ! compute the qr factorization of the n-by-2 matrix ( x y ) call stdlib${ii}$_slarfg( n, x( 1_${ik}$ ), x( 1_${ik}$+incx ), incx, tau ) a11 = x( 1_${ik}$ ) x( 1_${ik}$ ) = one c = -tau*stdlib${ii}$_sdot( n, x, incx, y, incy ) call stdlib${ii}$_saxpy( n, c, x, incx, y, incy ) call stdlib${ii}$_slarfg( n-1, y( 1_${ik}$+incy ), y( 1_${ik}$+2*incy ), incy, tau ) a12 = y( 1_${ik}$ ) a22 = y( 1_${ik}$+incy ) ! compute the svd of 2-by-2 upper triangular matrix. call stdlib${ii}$_slas2( a11, a12, a22, ssmin, ssmax ) return end subroutine stdlib${ii}$_slapll pure module subroutine stdlib${ii}$_dlapll( n, x, incx, y, incy, ssmin ) !! Given two column vectors X and Y, let !! A = ( X Y ). !! The subroutine first computes the QR factorization of A = Q*R, !! and then computes the SVD of the 2-by-2 upper triangular matrix R. !! The smaller singular value of R is returned in SSMIN, which is used !! as the measurement of the linear dependency of the vectors X and Y. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n real(dp), intent(out) :: ssmin ! Array Arguments real(dp), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(dp) :: a11, a12, a22, c, ssmax, tau ! Executable Statements ! quick return if possible if( n<=1_${ik}$ ) then ssmin = zero return end if ! compute the qr factorization of the n-by-2 matrix ( x y ) call stdlib${ii}$_dlarfg( n, x( 1_${ik}$ ), x( 1_${ik}$+incx ), incx, tau ) a11 = x( 1_${ik}$ ) x( 1_${ik}$ ) = one c = -tau*stdlib${ii}$_ddot( n, x, incx, y, incy ) call stdlib${ii}$_daxpy( n, c, x, incx, y, incy ) call stdlib${ii}$_dlarfg( n-1, y( 1_${ik}$+incy ), y( 1_${ik}$+2*incy ), incy, tau ) a12 = y( 1_${ik}$ ) a22 = y( 1_${ik}$+incy ) ! compute the svd of 2-by-2 upper triangular matrix. call stdlib${ii}$_dlas2( a11, a12, a22, ssmin, ssmax ) return end subroutine stdlib${ii}$_dlapll #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lapll( n, x, incx, y, incy, ssmin ) !! Given two column vectors X and Y, let !! A = ( X Y ). !! The subroutine first computes the QR factorization of A = Q*R, !! and then computes the SVD of the 2-by-2 upper triangular matrix R. !! The smaller singular value of R is returned in SSMIN, which is used !! as the measurement of the linear dependency of the vectors X and Y. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n real(${rk}$), intent(out) :: ssmin ! Array Arguments real(${rk}$), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: a11, a12, a22, c, ssmax, tau ! Executable Statements ! quick return if possible if( n<=1_${ik}$ ) then ssmin = zero return end if ! compute the qr factorization of the n-by-2 matrix ( x y ) call stdlib${ii}$_${ri}$larfg( n, x( 1_${ik}$ ), x( 1_${ik}$+incx ), incx, tau ) a11 = x( 1_${ik}$ ) x( 1_${ik}$ ) = one c = -tau*stdlib${ii}$_${ri}$dot( n, x, incx, y, incy ) call stdlib${ii}$_${ri}$axpy( n, c, x, incx, y, incy ) call stdlib${ii}$_${ri}$larfg( n-1, y( 1_${ik}$+incy ), y( 1_${ik}$+2*incy ), incy, tau ) a12 = y( 1_${ik}$ ) a22 = y( 1_${ik}$+incy ) ! compute the svd of 2-by-2 upper triangular matrix. call stdlib${ii}$_${ri}$las2( a11, a12, a22, ssmin, ssmax ) return end subroutine stdlib${ii}$_${ri}$lapll #:endif #:endfor pure module subroutine stdlib${ii}$_clapll( n, x, incx, y, incy, ssmin ) !! Given two column vectors X and Y, let !! A = ( X Y ). !! The subroutine first computes the QR factorization of A = Q*R, !! and then computes the SVD of the 2-by-2 upper triangular matrix R. !! The smaller singular value of R is returned in SSMIN, which is used !! as the measurement of the linear dependency of the vectors X and Y. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n real(sp), intent(out) :: ssmin ! Array Arguments complex(sp), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(sp) :: ssmax complex(sp) :: a11, a12, a22, c, tau ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=1_${ik}$ ) then ssmin = zero return end if ! compute the qr factorization of the n-by-2 matrix ( x y ) call stdlib${ii}$_clarfg( n, x( 1_${ik}$ ), x( 1_${ik}$+incx ), incx, tau ) a11 = x( 1_${ik}$ ) x( 1_${ik}$ ) = cone c = -conjg( tau )*stdlib${ii}$_cdotc( n, x, incx, y, incy ) call stdlib${ii}$_caxpy( n, c, x, incx, y, incy ) call stdlib${ii}$_clarfg( n-1, y( 1_${ik}$+incy ), y( 1_${ik}$+2*incy ), incy, tau ) a12 = y( 1_${ik}$ ) a22 = y( 1_${ik}$+incy ) ! compute the svd of 2-by-2 upper triangular matrix. call stdlib${ii}$_slas2( abs( a11 ), abs( a12 ), abs( a22 ), ssmin, ssmax ) return end subroutine stdlib${ii}$_clapll pure module subroutine stdlib${ii}$_zlapll( n, x, incx, y, incy, ssmin ) !! Given two column vectors X and Y, let !! A = ( X Y ). !! The subroutine first computes the QR factorization of A = Q*R, !! and then computes the SVD of the 2-by-2 upper triangular matrix R. !! The smaller singular value of R is returned in SSMIN, which is used !! as the measurement of the linear dependency of the vectors X and Y. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n real(dp), intent(out) :: ssmin ! Array Arguments complex(dp), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(dp) :: ssmax complex(dp) :: a11, a12, a22, c, tau ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=1_${ik}$ ) then ssmin = zero return end if ! compute the qr factorization of the n-by-2 matrix ( x y ) call stdlib${ii}$_zlarfg( n, x( 1_${ik}$ ), x( 1_${ik}$+incx ), incx, tau ) a11 = x( 1_${ik}$ ) x( 1_${ik}$ ) = cone c = -conjg( tau )*stdlib${ii}$_zdotc( n, x, incx, y, incy ) call stdlib${ii}$_zaxpy( n, c, x, incx, y, incy ) call stdlib${ii}$_zlarfg( n-1, y( 1_${ik}$+incy ), y( 1_${ik}$+2*incy ), incy, tau ) a12 = y( 1_${ik}$ ) a22 = y( 1_${ik}$+incy ) ! compute the svd of 2-by-2 upper triangular matrix. call stdlib${ii}$_dlas2( abs( a11 ), abs( a12 ), abs( a22 ), ssmin, ssmax ) return end subroutine stdlib${ii}$_zlapll #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lapll( n, x, incx, y, incy, ssmin ) !! Given two column vectors X and Y, let !! A = ( X Y ). !! The subroutine first computes the QR factorization of A = Q*R, !! and then computes the SVD of the 2-by-2 upper triangular matrix R. !! The smaller singular value of R is returned in SSMIN, which is used !! as the measurement of the linear dependency of the vectors X and Y. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n real(${ck}$), intent(out) :: ssmin ! Array Arguments complex(${ck}$), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars real(${ck}$) :: ssmax complex(${ck}$) :: a11, a12, a22, c, tau ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=1_${ik}$ ) then ssmin = zero return end if ! compute the qr factorization of the n-by-2 matrix ( x y ) call stdlib${ii}$_${ci}$larfg( n, x( 1_${ik}$ ), x( 1_${ik}$+incx ), incx, tau ) a11 = x( 1_${ik}$ ) x( 1_${ik}$ ) = cone c = -conjg( tau )*stdlib${ii}$_${ci}$dotc( n, x, incx, y, incy ) call stdlib${ii}$_${ci}$axpy( n, c, x, incx, y, incy ) call stdlib${ii}$_${ci}$larfg( n-1, y( 1_${ik}$+incy ), y( 1_${ik}$+2*incy ), incy, tau ) a12 = y( 1_${ik}$ ) a22 = y( 1_${ik}$+incy ) ! compute the svd of 2-by-2 upper triangular matrix. call stdlib${ii}$_${c2ri(ci)}$las2( abs( a11 ), abs( a12 ), abs( a22 ), ssmin, ssmax ) return end subroutine stdlib${ii}$_${ci}$lapll #:endif #:endfor #:endfor end submodule stdlib_lapack_svd_comp2 fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_eigv_tridiag3.fypp0000664000175000017500000201160415135654166026510 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_eigv_tridiag3 implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sstev( jobz, n, d, e, z, ldz, work, info ) !! SSTEV computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric tridiagonal matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(sp), intent(inout) :: d(*), e(*) real(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: imax, iscale real(sp) :: bignum, eps, rmax, rmin, safmin, sigma, smlnum, tnrm ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_sscal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_sscal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) end if ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvalues and ! eigenvectors, call stdlib${ii}$_ssteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, d, e, info ) else call stdlib${ii}$_ssteqr( 'I', n, d, e, z, ldz, work, info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, d, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_sstev pure module subroutine stdlib${ii}$_dstev( jobz, n, d, e, z, ldz, work, info ) !! DSTEV computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric tridiagonal matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(dp), intent(inout) :: d(*), e(*) real(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: imax, iscale real(dp) :: bignum, eps, rmax, rmin, safmin, sigma, smlnum, tnrm ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_dscal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_dscal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) end if ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvalues and ! eigenvectors, call stdlib${ii}$_dsteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, d, e, info ) else call stdlib${ii}$_dsteqr( 'I', n, d, e, z, ldz, work, info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, d, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_dstev #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$stev( jobz, n, d, e, z, ldz, work, info ) !! DSTEV: computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric tridiagonal matrix A. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(${rk}$), intent(inout) :: d(*), e(*) real(${rk}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: imax, iscale real(${rk}$) :: bignum, eps, rmax, rmin, safmin, sigma, smlnum, tnrm ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) end if ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvalues and ! eigenvectors, call stdlib${ii}$_${ri}$steqr. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, d, e, info ) else call stdlib${ii}$_${ri}$steqr( 'I', n, d, e, z, ldz, work, info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, d, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ri}$stev #:endif #:endfor pure module subroutine stdlib${ii}$_sstevd( jobz, n, d, e, z, ldz, work, lwork, iwork,liwork, info ) !! SSTEVD computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric tridiagonal matrix. If eigenvectors are desired, it !! uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: d(*), e(*) real(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iscale, liwmin, lwmin real(sp) :: bignum, eps, rmax, rmin, safmin, sigma, smlnum, tnrm ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ liwmin = 1_${ik}$ lwmin = 1_${ik}$ if( n>1_${ik}$ .and. wantz ) then lwmin = 1_${ik}$ + 4_${ik}$*n + n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_sscal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_sscal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) end if ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvalues and ! eigenvectors, call stdlib${ii}$_sstedc. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, d, e, info ) else call stdlib${ii}$_sstedc( 'I', n, d, e, z, ldz, work, lwork, iwork, liwork,info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_sscal( n, one / sigma, d, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_sstevd pure module subroutine stdlib${ii}$_dstevd( jobz, n, d, e, z, ldz, work, lwork, iwork,liwork, info ) !! DSTEVD computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric tridiagonal matrix. If eigenvectors are desired, it !! uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: d(*), e(*) real(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iscale, liwmin, lwmin real(dp) :: bignum, eps, rmax, rmin, safmin, sigma, smlnum, tnrm ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ liwmin = 1_${ik}$ lwmin = 1_${ik}$ if( n>1_${ik}$ .and. wantz ) then lwmin = 1_${ik}$ + 4_${ik}$*n + n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_dscal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_dscal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) end if ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvalues and ! eigenvectors, call stdlib${ii}$_dstedc. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, d, e, info ) else call stdlib${ii}$_dstedc( 'I', n, d, e, z, ldz, work, lwork, iwork, liwork,info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_dscal( n, one / sigma, d, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_dstevd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$stevd( jobz, n, d, e, z, ldz, work, lwork, iwork,liwork, info ) !! DSTEVD: computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric tridiagonal matrix. If eigenvectors are desired, it !! uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: d(*), e(*) real(${rk}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iscale, liwmin, lwmin real(${rk}$) :: bignum, eps, rmax, rmin, safmin, sigma, smlnum, tnrm ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ liwmin = 1_${ik}$ lwmin = 1_${ik}$ if( n>1_${ik}$ .and. wantz ) then lwmin = 1_${ik}$ + 4_${ik}$*n + n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldzzero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) end if ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvalues and ! eigenvectors, call stdlib${ii}$_${ri}$stedc. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, d, e, info ) else call stdlib${ii}$_${ri}$stedc( 'I', n, d, e, z, ldz, work, lwork, iwork, liwork,info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$scal( n, one / sigma, d, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ri}$stevd #:endif #:endfor pure module subroutine stdlib${ii}$_sstevr( jobz, range, n, d, e, vl, vu, il, iu, abstol,m, w, z, ldz, & !! SSTEVR computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric tridiagonal matrix T. Eigenvalues and !! eigenvectors can be selected by specifying either a range of values !! or a range of indices for the desired eigenvalues. !! Whenever possible, SSTEVR calls SSTEMR to compute the !! eigenspectrum using Relatively Robust Representations. SSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. For the i-th !! unreduced block of T, !! (a) Compute T - sigma_i = L_i D_i L_i^T, such that L_i D_i L_i^T !! is a relatively robust representation, !! (b) Compute the eigenvalues, lambda_j, of L_i D_i L_i^T to high !! relative accuracy by the dqds algorithm, !! (c) If there is a cluster of close eigenvalues, "choose" sigma_i !! close to the cluster, and go to step (a), !! (d) Given the approximate eigenvalue lambda_j of L_i D_i L_i^T, !! compute the corresponding eigenvector by forming a !! rank-revealing twisted factorization. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", by Inderjit Dhillon, !! Computer Science Division Technical Report No. UCB//CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : SSTEVR calls SSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! SSTEVR calls SSTEBZ and SSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of SSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. isuppz, work, lwork, iwork,liwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobz, range integer(${ik}$), intent(in) :: il, iu, ldz, liwork, lwork, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: isuppz(*), iwork(*) real(sp), intent(inout) :: d(*), e(*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, test, lquery, valeig, wantz, tryrac character :: order integer(${ik}$) :: i, ieeeok, imax, indibl, indifl, indisp, indiwo, iscale, j, jj, liwmin,& lwmin, nsplit real(sp) :: bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, tnrm, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. ieeeok = stdlib${ii}$_ilaenv( 10_${ik}$, 'SSTEVR', 'N', 1_${ik}$, 2_${ik}$, 3_${ik}$, 4_${ik}$ ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( ( lwork==-1_${ik}$ ) .or. ( liwork==-1_${ik}$ ) ) lwmin = max( 1_${ik}$, 20_${ik}$*n ) liwmin = max(1_${ik}$, 10_${ik}$*n ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ if( valeig ) then vll = vl vuu = vu end if tnrm = stdlib${ii}$_slanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_sscal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_sscal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: these indices are used only ! if stdlib${ii}$_ssterf or stdlib${ii}$_sstemr fail. ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_sstebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_sstebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_sstein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indisp + n ! if all eigenvalues are desired, then ! call stdlib${ii}$_ssterf or stdlib${ii}$_sstemr. if this fails for some eigenvalue, then ! try stdlib${ii}$_sstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ieeeok==1_${ik}$ ) then call stdlib${ii}$_scopy( n-1, e( 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( .not.wantz ) then call stdlib${ii}$_scopy( n, d, 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, work, info ) else call stdlib${ii}$_scopy( n, d, 1_${ik}$, work( n+1 ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_sstemr( jobz, 'A', n, work( n+1 ), work, vl, vu, il,iu, m, w, z, ldz,& n, isuppz, tryrac,work( 2_${ik}$*n+1 ), lwork-2*n, iwork, liwork, info ) end if if( info==0_${ik}$ ) then m = n go to 10 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstol, d, e, m,nsplit, w, & iwork( indibl ), iwork( indisp ), work,iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_sstein( n, d, e, m, w, iwork( indibl ), iwork( indisp ),z, ldz, work, & iwork( indiwo ), iwork( indifl ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 10 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ if( valeig ) then vll = vl vuu = vu end if tnrm = stdlib${ii}$_dlanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_dscal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_dscal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: these indices are used only ! if stdlib${ii}$_dsterf or stdlib${ii}$_dstemr fail. ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_dstebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_dstebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_dstein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indisp + n ! if all eigenvalues are desired, then ! call stdlib${ii}$_dsterf or stdlib${ii}$_dstemr. if this fails for some eigenvalue, then ! try stdlib${ii}$_dstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ieeeok==1_${ik}$ ) then call stdlib${ii}$_dcopy( n-1, e( 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( .not.wantz ) then call stdlib${ii}$_dcopy( n, d, 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, work, info ) else call stdlib${ii}$_dcopy( n, d, 1_${ik}$, work( n+1 ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_dstemr( jobz, 'A', n, work( n+1 ), work, vl, vu, il,iu, m, w, z, ldz,& n, isuppz, tryrac,work( 2_${ik}$*n+1 ), lwork-2*n, iwork, liwork, info ) end if if( info==0_${ik}$ ) then m = n go to 10 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_dstein. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstol, d, e, m,nsplit, w, & iwork( indibl ), iwork( indisp ), work,iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_dstein( n, d, e, m, w, iwork( indibl ), iwork( indisp ),z, ldz, work, & iwork( indiwo ), iwork( indifl ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 10 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ if( valeig ) then vll = vl vuu = vu end if tnrm = stdlib${ii}$_${ri}$lanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: these indices are used only ! if stdlib${ii}$_${ri}$sterf or stdlib${ii}$_${ri}$stemr fail. ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_${ri}$stebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_${ri}$stebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_${ri}$stein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indisp + n ! if all eigenvalues are desired, then ! call stdlib${ii}$_${ri}$sterf or stdlib${ii}$_${ri}$stemr. if this fails for some eigenvalue, then ! try stdlib${ii}$_${ri}$stebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ieeeok==1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( n-1, e( 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( .not.wantz ) then call stdlib${ii}$_${ri}$copy( n, d, 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_${ri}$sterf( n, w, work, info ) else call stdlib${ii}$_${ri}$copy( n, d, 1_${ik}$, work( n+1 ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_${ri}$stemr( jobz, 'A', n, work( n+1 ), work, vl, vu, il,iu, m, w, z, ldz,& n, isuppz, tryrac,work( 2_${ik}$*n+1 ), lwork-2*n, iwork, liwork, info ) end if if( info==0_${ik}$ ) then m = n go to 10 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${ri}$stebz and, if eigenvectors are desired, stdlib${ii}$_${ri}$stein. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_${ri}$stebz( range, order, n, vll, vuu, il, iu, abstol, d, e, m,nsplit, w, & iwork( indibl ), iwork( indisp ), work,iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_${ri}$stein( n, d, e, m, w, iwork( indibl ), iwork( indisp ),z, ldz, work, & iwork( indiwo ), iwork( indifl ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 10 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ if ( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero endif tnrm = stdlib${ii}$_slanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_sscal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_sscal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! if all eigenvalues are desired and abstol is less than zero, then ! call stdlib${ii}$_ssterf or stdlib${ii}$_ssteqr. if this fails for some eigenvalue, then ! try stdlib${ii}$_sstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_scopy( n, d, 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_scopy( n-1, e( 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) indwrk = n + 1_${ik}$ if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work, info ) else call stdlib${ii}$_ssteqr( 'I', n, w, work, z, ldz, work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indwrk = 1_${ik}$ indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstol, d, e, m,nsplit, w, & iwork( indibl ), iwork( indisp ),work( indwrk ), iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_sstein( n, d, e, m, w, iwork( indibl ), iwork( indisp ),z, ldz, work( & indwrk ), iwork( indiwo ), ifail,info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if tnrm = stdlib${ii}$_dlanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_dscal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_dscal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! if all eigenvalues are desired and abstol is less than zero, then ! call stdlib${ii}$_dsterf or stdlib${ii}$_ssteqr. if this fails for some eigenvalue, then ! try stdlib${ii}$_dstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_dcopy( n, d, 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_dcopy( n-1, e( 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) indwrk = n + 1_${ik}$ if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work, info ) else call stdlib${ii}$_dsteqr( 'I', n, w, work, z, ldz, work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indwrk = 1_${ik}$ indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstol, d, e, m,nsplit, w, & iwork( indibl ), iwork( indisp ),work( indwrk ), iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_dstein( n, d, e, m, w, iwork( indibl ), iwork( indisp ),z, ldz, work( & indwrk ), iwork( indiwo ), ifail,info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iun ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if tnrm = stdlib${ii}$_${ri}$lanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then iscale = 1_${ik}$ sigma = rmax / tnrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( n, sigma, d, 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-1, sigma, e( 1_${ik}$ ), 1_${ik}$ ) if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! if all eigenvalues are desired and abstol is less than zero, then ! call stdlib${ii}$_${ri}$sterf or stdlib${ii}$_dsteqr. if this fails for some eigenvalue, then ! try stdlib${ii}$_${ri}$stebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_${ri}$copy( n, d, 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n-1, e( 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) indwrk = n + 1_${ik}$ if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work, info ) else call stdlib${ii}$_${ri}$steqr( 'I', n, w, work, z, ldz, work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${ri}$stebz and, if eigenvectors are desired, stdlib${ii}$_dstein. if( wantz ) then order = 'B' else order = 'E' end if indwrk = 1_${ik}$ indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_${ri}$stebz( range, order, n, vll, vuu, il, iu, abstol, d, e, m,nsplit, w, & iwork( indibl ), iwork( indisp ),work( indwrk ), iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_${ri}$stein( n, d, e, m, w, iwork( indibl ), iwork( indisp ),z, ldz, work( & indwrk ), iwork( indiwo ), ifail,info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. ldz0_${ik}$ )z( 1_${ik}$, 1_${ik}$ ) = one return end if if( icompz==2_${ik}$ )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, z, ldz ) ! call stdlib${ii}$_spttrf to factor the matrix. call stdlib${ii}$_spttrf( n, d, e, info ) if( info/=0 )return do i = 1, n d( i ) = sqrt( d( i ) ) end do do i = 1, n - 1 e( i ) = e( i )*d( i ) end do ! call stdlib${ii}$_sbdsqr to compute the singular values/vectors of the ! bidiagonal factor. if( icompz>0_${ik}$ ) then nru = n else nru = 0_${ik}$ end if call stdlib${ii}$_sbdsqr( 'LOWER', n, 0_${ik}$, nru, 0_${ik}$, d, e, vt, 1_${ik}$, z, ldz, c, 1_${ik}$,work, info ) ! square the singular values. if( info==0_${ik}$ ) then do i = 1, n d( i ) = d( i )*d( i ) end do else info = n + info end if return end subroutine stdlib${ii}$_spteqr pure module subroutine stdlib${ii}$_dpteqr( compz, n, d, e, z, ldz, work, info ) !! DPTEQR computes all eigenvalues and, optionally, eigenvectors of a !! symmetric positive definite tridiagonal matrix by first factoring the !! matrix using DPTTRF, and then calling DBDSQR to compute the singular !! values of the bidiagonal factor. !! This routine computes the eigenvalues of the positive definite !! tridiagonal matrix to high relative accuracy. This means that if the !! eigenvalues range over many orders of magnitude in size, then the !! small eigenvalues and corresponding eigenvectors will be computed !! more accurately than, for example, with the standard QR method. !! The eigenvectors of a full or band symmetric positive definite matrix !! can also be found if DSYTRD, DSPTRD, or DSBTRD has been used to !! reduce this matrix to tridiagonal form. (The reduction to tridiagonal !! form, however, may preclude the possibility of obtaining high !! relative accuracy in the small eigenvalues of the original matrix, if !! these eigenvalues range over many orders of magnitude.) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(dp), intent(inout) :: d(*), e(*), z(ldz,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Arrays real(dp) :: c(1_${ik}$,1_${ik}$), vt(1_${ik}$,1_${ik}$) ! Local Scalars integer(${ik}$) :: i, icompz, nru ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( stdlib_lsame( compz, 'N' ) ) then icompz = 0_${ik}$ else if( stdlib_lsame( compz, 'V' ) ) then icompz = 1_${ik}$ else if( stdlib_lsame( compz, 'I' ) ) then icompz = 2_${ik}$ else icompz = -1_${ik}$ end if if( icompz<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ( ldz<1_${ik}$ ) .or. ( icompz>0_${ik}$ .and. ldz0_${ik}$ )z( 1_${ik}$, 1_${ik}$ ) = one return end if if( icompz==2_${ik}$ )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, z, ldz ) ! call stdlib${ii}$_dpttrf to factor the matrix. call stdlib${ii}$_dpttrf( n, d, e, info ) if( info/=0 )return do i = 1, n d( i ) = sqrt( d( i ) ) end do do i = 1, n - 1 e( i ) = e( i )*d( i ) end do ! call stdlib${ii}$_dbdsqr to compute the singular values/vectors of the ! bidiagonal factor. if( icompz>0_${ik}$ ) then nru = n else nru = 0_${ik}$ end if call stdlib${ii}$_dbdsqr( 'LOWER', n, 0_${ik}$, nru, 0_${ik}$, d, e, vt, 1_${ik}$, z, ldz, c, 1_${ik}$,work, info ) ! square the singular values. if( info==0_${ik}$ ) then do i = 1, n d( i ) = d( i )*d( i ) end do else info = n + info end if return end subroutine stdlib${ii}$_dpteqr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$pteqr( compz, n, d, e, z, ldz, work, info ) !! DPTEQR: computes all eigenvalues and, optionally, eigenvectors of a !! symmetric positive definite tridiagonal matrix by first factoring the !! matrix using DPTTRF, and then calling DBDSQR to compute the singular !! values of the bidiagonal factor. !! This routine computes the eigenvalues of the positive definite !! tridiagonal matrix to high relative accuracy. This means that if the !! eigenvalues range over many orders of magnitude in size, then the !! small eigenvalues and corresponding eigenvectors will be computed !! more accurately than, for example, with the standard QR method. !! The eigenvectors of a full or band symmetric positive definite matrix !! can also be found if DSYTRD, DSPTRD, or DSBTRD has been used to !! reduce this matrix to tridiagonal form. (The reduction to tridiagonal !! form, however, may preclude the possibility of obtaining high !! relative accuracy in the small eigenvalues of the original matrix, if !! these eigenvalues range over many orders of magnitude.) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(${rk}$), intent(inout) :: d(*), e(*), z(ldz,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Arrays real(${rk}$) :: c(1_${ik}$,1_${ik}$), vt(1_${ik}$,1_${ik}$) ! Local Scalars integer(${ik}$) :: i, icompz, nru ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( stdlib_lsame( compz, 'N' ) ) then icompz = 0_${ik}$ else if( stdlib_lsame( compz, 'V' ) ) then icompz = 1_${ik}$ else if( stdlib_lsame( compz, 'I' ) ) then icompz = 2_${ik}$ else icompz = -1_${ik}$ end if if( icompz<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ( ldz<1_${ik}$ ) .or. ( icompz>0_${ik}$ .and. ldz0_${ik}$ )z( 1_${ik}$, 1_${ik}$ ) = one return end if if( icompz==2_${ik}$ )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, z, ldz ) ! call stdlib${ii}$_${ri}$pttrf to factor the matrix. call stdlib${ii}$_${ri}$pttrf( n, d, e, info ) if( info/=0 )return do i = 1, n d( i ) = sqrt( d( i ) ) end do do i = 1, n - 1 e( i ) = e( i )*d( i ) end do ! call stdlib${ii}$_${ri}$bdsqr to compute the singular values/vectors of the ! bidiagonal factor. if( icompz>0_${ik}$ ) then nru = n else nru = 0_${ik}$ end if call stdlib${ii}$_${ri}$bdsqr( 'LOWER', n, 0_${ik}$, nru, 0_${ik}$, d, e, vt, 1_${ik}$, z, ldz, c, 1_${ik}$,work, info ) ! square the singular values. if( info==0_${ik}$ ) then do i = 1, n d( i ) = d( i )*d( i ) end do else info = n + info end if return end subroutine stdlib${ii}$_${ri}$pteqr #:endif #:endfor pure module subroutine stdlib${ii}$_cpteqr( compz, n, d, e, z, ldz, work, info ) !! CPTEQR computes all eigenvalues and, optionally, eigenvectors of a !! symmetric positive definite tridiagonal matrix by first factoring the !! matrix using SPTTRF and then calling CBDSQR to compute the singular !! values of the bidiagonal factor. !! This routine computes the eigenvalues of the positive definite !! tridiagonal matrix to high relative accuracy. This means that if the !! eigenvalues range over many orders of magnitude in size, then the !! small eigenvalues and corresponding eigenvectors will be computed !! more accurately than, for example, with the standard QR method. !! The eigenvectors of a full or band positive definite Hermitian matrix !! can also be found if CHETRD, CHPTRD, or CHBTRD has been used to !! reduce this matrix to tridiagonal form. (The reduction to !! tridiagonal form, however, may preclude the possibility of obtaining !! high relative accuracy in the small eigenvalues of the original !! matrix, if these eigenvalues range over many orders of magnitude.) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(sp), intent(inout) :: d(*), e(*) real(sp), intent(out) :: work(*) complex(sp), intent(inout) :: z(ldz,*) ! ==================================================================== ! Local Arrays complex(sp) :: c(1_${ik}$,1_${ik}$), vt(1_${ik}$,1_${ik}$) ! Local Scalars integer(${ik}$) :: i, icompz, nru ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( stdlib_lsame( compz, 'N' ) ) then icompz = 0_${ik}$ else if( stdlib_lsame( compz, 'V' ) ) then icompz = 1_${ik}$ else if( stdlib_lsame( compz, 'I' ) ) then icompz = 2_${ik}$ else icompz = -1_${ik}$ end if if( icompz<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ( ldz<1_${ik}$ ) .or. ( icompz>0_${ik}$ .and. ldz0_${ik}$ )z( 1_${ik}$, 1_${ik}$ ) = cone return end if if( icompz==2_${ik}$ )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, z, ldz ) ! call stdlib${ii}$_spttrf to factor the matrix. call stdlib${ii}$_spttrf( n, d, e, info ) if( info/=0 )return do i = 1, n d( i ) = sqrt( d( i ) ) end do do i = 1, n - 1 e( i ) = e( i )*d( i ) end do ! call stdlib${ii}$_cbdsqr to compute the singular values/vectors of the ! bidiagonal factor. if( icompz>0_${ik}$ ) then nru = n else nru = 0_${ik}$ end if call stdlib${ii}$_cbdsqr( 'LOWER', n, 0_${ik}$, nru, 0_${ik}$, d, e, vt, 1_${ik}$, z, ldz, c, 1_${ik}$,work, info ) ! square the singular values. if( info==0_${ik}$ ) then do i = 1, n d( i ) = d( i )*d( i ) end do else info = n + info end if return end subroutine stdlib${ii}$_cpteqr pure module subroutine stdlib${ii}$_zpteqr( compz, n, d, e, z, ldz, work, info ) !! ZPTEQR computes all eigenvalues and, optionally, eigenvectors of a !! symmetric positive definite tridiagonal matrix by first factoring the !! matrix using DPTTRF and then calling ZBDSQR to compute the singular !! values of the bidiagonal factor. !! This routine computes the eigenvalues of the positive definite !! tridiagonal matrix to high relative accuracy. This means that if the !! eigenvalues range over many orders of magnitude in size, then the !! small eigenvalues and corresponding eigenvectors will be computed !! more accurately than, for example, with the standard QR method. !! The eigenvectors of a full or band positive definite Hermitian matrix !! can also be found if ZHETRD, ZHPTRD, or ZHBTRD has been used to !! reduce this matrix to tridiagonal form. (The reduction to !! tridiagonal form, however, may preclude the possibility of obtaining !! high relative accuracy in the small eigenvalues of the original !! matrix, if these eigenvalues range over many orders of magnitude.) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(dp), intent(inout) :: d(*), e(*) real(dp), intent(out) :: work(*) complex(dp), intent(inout) :: z(ldz,*) ! ==================================================================== ! Local Arrays complex(dp) :: c(1_${ik}$,1_${ik}$), vt(1_${ik}$,1_${ik}$) ! Local Scalars integer(${ik}$) :: i, icompz, nru ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( stdlib_lsame( compz, 'N' ) ) then icompz = 0_${ik}$ else if( stdlib_lsame( compz, 'V' ) ) then icompz = 1_${ik}$ else if( stdlib_lsame( compz, 'I' ) ) then icompz = 2_${ik}$ else icompz = -1_${ik}$ end if if( icompz<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ( ldz<1_${ik}$ ) .or. ( icompz>0_${ik}$ .and. ldz0_${ik}$ )z( 1_${ik}$, 1_${ik}$ ) = cone return end if if( icompz==2_${ik}$ )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, z, ldz ) ! call stdlib${ii}$_dpttrf to factor the matrix. call stdlib${ii}$_dpttrf( n, d, e, info ) if( info/=0 )return do i = 1, n d( i ) = sqrt( d( i ) ) end do do i = 1, n - 1 e( i ) = e( i )*d( i ) end do ! call stdlib${ii}$_zbdsqr to compute the singular values/vectors of the ! bidiagonal factor. if( icompz>0_${ik}$ ) then nru = n else nru = 0_${ik}$ end if call stdlib${ii}$_zbdsqr( 'LOWER', n, 0_${ik}$, nru, 0_${ik}$, d, e, vt, 1_${ik}$, z, ldz, c, 1_${ik}$,work, info ) ! square the singular values. if( info==0_${ik}$ ) then do i = 1, n d( i ) = d( i )*d( i ) end do else info = n + info end if return end subroutine stdlib${ii}$_zpteqr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$pteqr( compz, n, d, e, z, ldz, work, info ) !! ZPTEQR: computes all eigenvalues and, optionally, eigenvectors of a !! symmetric positive definite tridiagonal matrix by first factoring the !! matrix using DPTTRF and then calling ZBDSQR to compute the singular !! values of the bidiagonal factor. !! This routine computes the eigenvalues of the positive definite !! tridiagonal matrix to high relative accuracy. This means that if the !! eigenvalues range over many orders of magnitude in size, then the !! small eigenvalues and corresponding eigenvectors will be computed !! more accurately than, for example, with the standard QR method. !! The eigenvectors of a full or band positive definite Hermitian matrix !! can also be found if ZHETRD, ZHPTRD, or ZHBTRD has been used to !! reduce this matrix to tridiagonal form. (The reduction to !! tridiagonal form, however, may preclude the possibility of obtaining !! high relative accuracy in the small eigenvalues of the original !! matrix, if these eigenvalues range over many orders of magnitude.) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(${ck}$), intent(inout) :: d(*), e(*) real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: z(ldz,*) ! ==================================================================== ! Local Arrays complex(${ck}$) :: c(1_${ik}$,1_${ik}$), vt(1_${ik}$,1_${ik}$) ! Local Scalars integer(${ik}$) :: i, icompz, nru ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( stdlib_lsame( compz, 'N' ) ) then icompz = 0_${ik}$ else if( stdlib_lsame( compz, 'V' ) ) then icompz = 1_${ik}$ else if( stdlib_lsame( compz, 'I' ) ) then icompz = 2_${ik}$ else icompz = -1_${ik}$ end if if( icompz<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ( ldz<1_${ik}$ ) .or. ( icompz>0_${ik}$ .and. ldz0_${ik}$ )z( 1_${ik}$, 1_${ik}$ ) = cone return end if if( icompz==2_${ik}$ )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, z, ldz ) ! call stdlib${ii}$_${c2ri(ci)}$pttrf to factor the matrix. call stdlib${ii}$_${c2ri(ci)}$pttrf( n, d, e, info ) if( info/=0 )return do i = 1, n d( i ) = sqrt( d( i ) ) end do do i = 1, n - 1 e( i ) = e( i )*d( i ) end do ! call stdlib${ii}$_${ci}$bdsqr to compute the singular values/vectors of the ! bidiagonal factor. if( icompz>0_${ik}$ ) then nru = n else nru = 0_${ik}$ end if call stdlib${ii}$_${ci}$bdsqr( 'LOWER', n, 0_${ik}$, nru, 0_${ik}$, d, e, vt, 1_${ik}$, z, ldz, c, 1_${ik}$,work, info ) ! square the singular values. if( info==0_${ik}$ ) then do i = 1, n d( i ) = d( i )*d( i ) end do else info = n + info end if return end subroutine stdlib${ii}$_${ci}$pteqr #:endif #:endfor pure module subroutine stdlib${ii}$_sstebz( range, order, n, vl, vu, il, iu, abstol, d, e,m, nsplit, w, & !! SSTEBZ computes the eigenvalues of a symmetric tridiagonal !! matrix T. The user may ask for all eigenvalues, all eigenvalues !! in the half-open interval (VL, VU], or the IL-th through IU-th !! eigenvalues. !! To avoid overflow, the matrix must be scaled so that its !! largest element is no greater than overflow**(1/2) * underflow**(1/4) in absolute value, and for greatest !! accuracy, it should not be much smaller than that. !! See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal !! Matrix", Report CS41, Computer Science Dept., Stanford !! University, July 21, 1966. iblock, isplit, work, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: order, range integer(${ik}$), intent(in) :: il, iu, n integer(${ik}$), intent(out) :: info, m, nsplit real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: iblock(*), isplit(*), iwork(*) real(sp), intent(in) :: d(*), e(*) real(sp), intent(out) :: w(*), work(*) ! ===================================================================== ! Parameters real(sp), parameter :: fudge = 2.1_sp real(sp), parameter :: relfac = two ! Local Scalars logical(lk) :: ncnvrg, toofew integer(${ik}$) :: ib, ibegin, idiscl, idiscu, ie, iend, iinfo, im, in, ioff, iorder, & iout, irange, itmax, itmp1, iw, iwoff, j, jb, jdisc, je, nb, nwl, nwu real(sp) :: atoli, bnorm, gl, gu, pivmin, rtoli, safemn, tmp1, tmp2, tnorm, ulp, wkill,& wl, wlu, wu, wul ! Local Arrays integer(${ik}$) :: idumma(1_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! decode range if( stdlib_lsame( range, 'A' ) ) then irange = 1_${ik}$ else if( stdlib_lsame( range, 'V' ) ) then irange = 2_${ik}$ else if( stdlib_lsame( range, 'I' ) ) then irange = 3_${ik}$ else irange = 0_${ik}$ end if ! decode order if( stdlib_lsame( order, 'B' ) ) then iorder = 2_${ik}$ else if( stdlib_lsame( order, 'E' ) ) then iorder = 1_${ik}$ else iorder = 0_${ik}$ end if ! check for errors if( irange<=0_${ik}$ ) then info = -1_${ik}$ else if( iorder<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( irange==2_${ik}$ ) then if( vl>=vu ) info = -5_${ik}$ else if( irange==3_${ik}$ .and. ( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) )then info = -6_${ik}$ else if( irange==3_${ik}$ .and. ( iun ) )then info = -7_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSTEBZ', -info ) return end if ! initialize error flags info = 0_${ik}$ ncnvrg = .false. toofew = .false. ! quick return if possible m = 0_${ik}$ if( n==0 )return ! simplifications: if( irange==3_${ik}$ .and. il==1_${ik}$ .and. iu==n )irange = 1_${ik}$ ! get machine constants ! nb is the minimum vector length for vector bisection, or 0 ! if only scalar is to be done. safemn = stdlib${ii}$_slamch( 'S' ) ulp = stdlib${ii}$_slamch( 'P' ) rtoli = ulp*relfac nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SSTEBZ', ' ', n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) if( nb<=1_${ik}$ )nb = 0_${ik}$ ! special case when n=1 if( n==1_${ik}$ ) then nsplit = 1_${ik}$ isplit( 1_${ik}$ ) = 1_${ik}$ if( irange==2_${ik}$ .and. ( vl>=d( 1_${ik}$ ) .or. vutmp1 ) then isplit( nsplit ) = j - 1_${ik}$ nsplit = nsplit + 1_${ik}$ work( j-1 ) = zero else work( j-1 ) = tmp1 pivmin = max( pivmin, tmp1 ) end if end do isplit( nsplit ) = n pivmin = pivmin*safemn ! compute interval and atoli if( irange==3_${ik}$ ) then ! range='i': compute the interval containing eigenvalues ! il through iu. ! compute gershgorin interval for entire (split) matrix ! and use it as the initial interval gu = d( 1_${ik}$ ) gl = d( 1_${ik}$ ) tmp1 = zero do j = 1, n - 1 tmp2 = sqrt( work( j ) ) gu = max( gu, d( j )+tmp1+tmp2 ) gl = min( gl, d( j )-tmp1-tmp2 ) tmp1 = tmp2 end do gu = max( gu, d( n )+tmp1 ) gl = min( gl, d( n )-tmp1 ) tnorm = max( abs( gl ), abs( gu ) ) gl = gl - fudge*tnorm*ulp*n - fudge*two*pivmin gu = gu + fudge*tnorm*ulp*n + fudge*pivmin ! compute iteration parameters itmax = int( ( log( tnorm+pivmin )-log( pivmin ) ) /log( two ),KIND=${ik}$) + 2_${ik}$ if( abstol<=zero ) then atoli = ulp*tnorm else atoli = abstol end if work( n+1 ) = gl work( n+2 ) = gl work( n+3 ) = gu work( n+4 ) = gu work( n+5 ) = gl work( n+6 ) = gu iwork( 1_${ik}$ ) = -1_${ik}$ iwork( 2_${ik}$ ) = -1_${ik}$ iwork( 3_${ik}$ ) = n + 1_${ik}$ iwork( 4_${ik}$ ) = n + 1_${ik}$ iwork( 5_${ik}$ ) = il - 1_${ik}$ iwork( 6_${ik}$ ) = iu call stdlib${ii}$_slaebz( 3_${ik}$, itmax, n, 2_${ik}$, 2_${ik}$, nb, atoli, rtoli, pivmin, d, e,work, iwork( & 5_${ik}$ ), work( n+1 ), work( n+5 ), iout,iwork, w, iblock, iinfo ) if( iwork( 6_${ik}$ )==iu ) then wl = work( n+1 ) wlu = work( n+3 ) nwl = iwork( 1_${ik}$ ) wu = work( n+4 ) wul = work( n+2 ) nwu = iwork( 4_${ik}$ ) else wl = work( n+2 ) wlu = work( n+4 ) nwl = iwork( 2_${ik}$ ) wu = work( n+3 ) wul = work( n+1 ) nwu = iwork( 3_${ik}$ ) end if if( nwl<0_${ik}$ .or. nwl>=n .or. nwu<1_${ik}$ .or. nwu>n ) then info = 4_${ik}$ return end if else ! range='a' or 'v' -- set atoli tnorm = max( abs( d( 1_${ik}$ ) )+abs( e( 1_${ik}$ ) ),abs( d( n ) )+abs( e( n-1 ) ) ) do j = 2, n - 1 tnorm = max( tnorm, abs( d( j ) )+abs( e( j-1 ) )+abs( e( j ) ) ) end do if( abstol<=zero ) then atoli = ulp*tnorm else atoli = abstol end if if( irange==2_${ik}$ ) then wl = vl wu = vu else wl = zero wu = zero end if end if ! find eigenvalues -- loop over blocks and recompute nwl and nwu. ! nwl accumulates the number of eigenvalues .le. wl, ! nwu accumulates the number of eigenvalues .le. wu m = 0_${ik}$ iend = 0_${ik}$ info = 0_${ik}$ nwl = 0_${ik}$ nwu = 0_${ik}$ loop_70: do jb = 1, nsplit ioff = iend ibegin = ioff + 1_${ik}$ iend = isplit( jb ) in = iend - ioff if( in==1_${ik}$ ) then ! special case -- in=1 if( irange==1_${ik}$ .or. wl>=d( ibegin )-pivmin )nwl = nwl + 1_${ik}$ if( irange==1_${ik}$ .or. wu>=d( ibegin )-pivmin )nwu = nwu + 1_${ik}$ if( irange==1_${ik}$ .or. ( wl=d( ibegin )-pivmin ) ) & then m = m + 1_${ik}$ w( m ) = d( ibegin ) iblock( m ) = jb end if else ! general case -- in > 1 ! compute gershgorin interval ! and use it as the initial interval gu = d( ibegin ) gl = d( ibegin ) tmp1 = zero do j = ibegin, iend - 1 tmp2 = abs( e( j ) ) gu = max( gu, d( j )+tmp1+tmp2 ) gl = min( gl, d( j )-tmp1-tmp2 ) tmp1 = tmp2 end do gu = max( gu, d( iend )+tmp1 ) gl = min( gl, d( iend )-tmp1 ) bnorm = max( abs( gl ), abs( gu ) ) gl = gl - fudge*bnorm*ulp*in - fudge*pivmin gu = gu + fudge*bnorm*ulp*in + fudge*pivmin ! compute atoli for the current submatrix if( abstol<=zero ) then atoli = ulp*max( abs( gl ), abs( gu ) ) else atoli = abstol end if if( irange>1_${ik}$ ) then if( gu=gu )cycle loop_70 end if ! set up initial interval work( n+1 ) = gl work( n+in+1 ) = gu call stdlib${ii}$_slaebz( 1_${ik}$, 0_${ik}$, in, in, 1_${ik}$, nb, atoli, rtoli, pivmin,d( ibegin ), e( & ibegin ), work( ibegin ),idumma, work( n+1 ), work( n+2*in+1 ), im,iwork, w( m+1 & ), iblock( m+1 ), iinfo ) nwl = nwl + iwork( 1_${ik}$ ) nwu = nwu + iwork( in+1 ) iwoff = m - iwork( 1_${ik}$ ) ! compute eigenvalues itmax = int( ( log( gu-gl+pivmin )-log( pivmin ) ) /log( two ),KIND=${ik}$) + & 2_${ik}$ call stdlib${ii}$_slaebz( 2_${ik}$, itmax, in, in, 1_${ik}$, nb, atoli, rtoli, pivmin,d( ibegin ), e(& ibegin ), work( ibegin ),idumma, work( n+1 ), work( n+2*in+1 ), iout,iwork, w( & m+1 ), iblock( m+1 ), iinfo ) ! copy eigenvalues into w and iblock ! use -jb for block number for unconverged eigenvalues. do j = 1, iout tmp1 = half*( work( j+n )+work( j+in+n ) ) ! flag non-convergence. if( j>iout-iinfo ) then ncnvrg = .true. ib = -jb else ib = jb end if do je = iwork( j ) + 1 + iwoff,iwork( j+in ) + iwoff w( je ) = tmp1 iblock( je ) = ib end do end do m = m + im end if end do loop_70 ! if range='i', then (wl,wu) contains eigenvalues nwl+1,...,nwu ! if nwl+1 < il or nwu > iu, discard extra eigenvalues. if( irange==3_${ik}$ ) then im = 0_${ik}$ idiscl = il - 1_${ik}$ - nwl idiscu = nwu - iu if( idiscl>0_${ik}$ .or. idiscu>0_${ik}$ ) then do je = 1, m if( w( je )<=wlu .and. idiscl>0_${ik}$ ) then idiscl = idiscl - 1_${ik}$ else if( w( je )>=wul .and. idiscu>0_${ik}$ ) then idiscu = idiscu - 1_${ik}$ else im = im + 1_${ik}$ w( im ) = w( je ) iblock( im ) = iblock( je ) end if end do m = im end if if( idiscl>0_${ik}$ .or. idiscu>0_${ik}$ ) then ! code to deal with effects of bad arithmetic: ! some low eigenvalues to be discarded are not in (wl,wlu], ! or high eigenvalues to be discarded are not in (wul,wu] ! so just kill off the smallest idiscl/largest idiscu ! eigenvalues, by simply finding the smallest/largest ! eigenvalue(s). ! (if n(w) is monotone non-decreasing, this should never ! happen.) if( idiscl>0_${ik}$ ) then wkill = wu do jdisc = 1, idiscl iw = 0_${ik}$ do je = 1, m if( iblock( je )/=0_${ik}$ .and.( w( je )0_${ik}$ ) then wkill = wl do jdisc = 1, idiscu iw = 0_${ik}$ do je = 1, m if( iblock( je )/=0_${ik}$ .and.( w( je )>wkill .or. iw==0_${ik}$ ) ) then iw = je wkill = w( je ) end if end do iblock( iw ) = 0_${ik}$ end do end if im = 0_${ik}$ do je = 1, m if( iblock( je )/=0_${ik}$ ) then im = im + 1_${ik}$ w( im ) = w( je ) iblock( im ) = iblock( je ) end if end do m = im end if if( idiscl<0_${ik}$ .or. idiscu<0_${ik}$ ) then toofew = .true. end if end if ! if order='b', do nothing -- the eigenvalues are already sorted ! by block. ! if order='e', sort the eigenvalues from smallest to largest if( iorder==1_${ik}$ .and. nsplit>1_${ik}$ ) then do je = 1, m - 1 ie = 0_${ik}$ tmp1 = w( je ) do j = je + 1, m if( w( j )=vu )info = -5_${ik}$ else if( irange==3_${ik}$ .and. ( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) )then info = -6_${ik}$ else if( irange==3_${ik}$ .and. ( iun ) )then info = -7_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSTEBZ', -info ) return end if ! initialize error flags info = 0_${ik}$ ncnvrg = .false. toofew = .false. ! quick return if possible m = 0_${ik}$ if( n==0 )return ! simplifications: if( irange==3_${ik}$ .and. il==1_${ik}$ .and. iu==n )irange = 1_${ik}$ ! get machine constants ! nb is the minimum vector length for vector bisection, or 0 ! if only scalar is to be done. safemn = stdlib${ii}$_dlamch( 'S' ) ulp = stdlib${ii}$_dlamch( 'P' ) rtoli = ulp*relfac nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DSTEBZ', ' ', n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) if( nb<=1_${ik}$ )nb = 0_${ik}$ ! special case when n=1 if( n==1_${ik}$ ) then nsplit = 1_${ik}$ isplit( 1_${ik}$ ) = 1_${ik}$ if( irange==2_${ik}$ .and. ( vl>=d( 1_${ik}$ ) .or. vutmp1 ) then isplit( nsplit ) = j - 1_${ik}$ nsplit = nsplit + 1_${ik}$ work( j-1 ) = zero else work( j-1 ) = tmp1 pivmin = max( pivmin, tmp1 ) end if end do isplit( nsplit ) = n pivmin = pivmin*safemn ! compute interval and atoli if( irange==3_${ik}$ ) then ! range='i': compute the interval containing eigenvalues ! il through iu. ! compute gershgorin interval for entire (split) matrix ! and use it as the initial interval gu = d( 1_${ik}$ ) gl = d( 1_${ik}$ ) tmp1 = zero do j = 1, n - 1 tmp2 = sqrt( work( j ) ) gu = max( gu, d( j )+tmp1+tmp2 ) gl = min( gl, d( j )-tmp1-tmp2 ) tmp1 = tmp2 end do gu = max( gu, d( n )+tmp1 ) gl = min( gl, d( n )-tmp1 ) tnorm = max( abs( gl ), abs( gu ) ) gl = gl - fudge*tnorm*ulp*n - fudge*two*pivmin gu = gu + fudge*tnorm*ulp*n + fudge*pivmin ! compute iteration parameters itmax = int( ( log( tnorm+pivmin )-log( pivmin ) ) /log( two ),KIND=${ik}$) + 2_${ik}$ if( abstol<=zero ) then atoli = ulp*tnorm else atoli = abstol end if work( n+1 ) = gl work( n+2 ) = gl work( n+3 ) = gu work( n+4 ) = gu work( n+5 ) = gl work( n+6 ) = gu iwork( 1_${ik}$ ) = -1_${ik}$ iwork( 2_${ik}$ ) = -1_${ik}$ iwork( 3_${ik}$ ) = n + 1_${ik}$ iwork( 4_${ik}$ ) = n + 1_${ik}$ iwork( 5_${ik}$ ) = il - 1_${ik}$ iwork( 6_${ik}$ ) = iu call stdlib${ii}$_dlaebz( 3_${ik}$, itmax, n, 2_${ik}$, 2_${ik}$, nb, atoli, rtoli, pivmin, d, e,work, iwork( & 5_${ik}$ ), work( n+1 ), work( n+5 ), iout,iwork, w, iblock, iinfo ) if( iwork( 6_${ik}$ )==iu ) then wl = work( n+1 ) wlu = work( n+3 ) nwl = iwork( 1_${ik}$ ) wu = work( n+4 ) wul = work( n+2 ) nwu = iwork( 4_${ik}$ ) else wl = work( n+2 ) wlu = work( n+4 ) nwl = iwork( 2_${ik}$ ) wu = work( n+3 ) wul = work( n+1 ) nwu = iwork( 3_${ik}$ ) end if if( nwl<0_${ik}$ .or. nwl>=n .or. nwu<1_${ik}$ .or. nwu>n ) then info = 4_${ik}$ return end if else ! range='a' or 'v' -- set atoli tnorm = max( abs( d( 1_${ik}$ ) )+abs( e( 1_${ik}$ ) ),abs( d( n ) )+abs( e( n-1 ) ) ) do j = 2, n - 1 tnorm = max( tnorm, abs( d( j ) )+abs( e( j-1 ) )+abs( e( j ) ) ) end do if( abstol<=zero ) then atoli = ulp*tnorm else atoli = abstol end if if( irange==2_${ik}$ ) then wl = vl wu = vu else wl = zero wu = zero end if end if ! find eigenvalues -- loop over blocks and recompute nwl and nwu. ! nwl accumulates the number of eigenvalues .le. wl, ! nwu accumulates the number of eigenvalues .le. wu m = 0_${ik}$ iend = 0_${ik}$ info = 0_${ik}$ nwl = 0_${ik}$ nwu = 0_${ik}$ loop_70: do jb = 1, nsplit ioff = iend ibegin = ioff + 1_${ik}$ iend = isplit( jb ) in = iend - ioff if( in==1_${ik}$ ) then ! special case -- in=1 if( irange==1_${ik}$ .or. wl>=d( ibegin )-pivmin )nwl = nwl + 1_${ik}$ if( irange==1_${ik}$ .or. wu>=d( ibegin )-pivmin )nwu = nwu + 1_${ik}$ if( irange==1_${ik}$ .or. ( wl=d( ibegin )-pivmin ) ) & then m = m + 1_${ik}$ w( m ) = d( ibegin ) iblock( m ) = jb end if else ! general case -- in > 1 ! compute gershgorin interval ! and use it as the initial interval gu = d( ibegin ) gl = d( ibegin ) tmp1 = zero do j = ibegin, iend - 1 tmp2 = abs( e( j ) ) gu = max( gu, d( j )+tmp1+tmp2 ) gl = min( gl, d( j )-tmp1-tmp2 ) tmp1 = tmp2 end do gu = max( gu, d( iend )+tmp1 ) gl = min( gl, d( iend )-tmp1 ) bnorm = max( abs( gl ), abs( gu ) ) gl = gl - fudge*bnorm*ulp*in - fudge*pivmin gu = gu + fudge*bnorm*ulp*in + fudge*pivmin ! compute atoli for the current submatrix if( abstol<=zero ) then atoli = ulp*max( abs( gl ), abs( gu ) ) else atoli = abstol end if if( irange>1_${ik}$ ) then if( gu=gu )cycle loop_70 end if ! set up initial interval work( n+1 ) = gl work( n+in+1 ) = gu call stdlib${ii}$_dlaebz( 1_${ik}$, 0_${ik}$, in, in, 1_${ik}$, nb, atoli, rtoli, pivmin,d( ibegin ), e( & ibegin ), work( ibegin ),idumma, work( n+1 ), work( n+2*in+1 ), im,iwork, w( m+1 & ), iblock( m+1 ), iinfo ) nwl = nwl + iwork( 1_${ik}$ ) nwu = nwu + iwork( in+1 ) iwoff = m - iwork( 1_${ik}$ ) ! compute eigenvalues itmax = int( ( log( gu-gl+pivmin )-log( pivmin ) ) /log( two ),KIND=${ik}$) + & 2_${ik}$ call stdlib${ii}$_dlaebz( 2_${ik}$, itmax, in, in, 1_${ik}$, nb, atoli, rtoli, pivmin,d( ibegin ), e(& ibegin ), work( ibegin ),idumma, work( n+1 ), work( n+2*in+1 ), iout,iwork, w( & m+1 ), iblock( m+1 ), iinfo ) ! copy eigenvalues into w and iblock ! use -jb for block number for unconverged eigenvalues. do j = 1, iout tmp1 = half*( work( j+n )+work( j+in+n ) ) ! flag non-convergence. if( j>iout-iinfo ) then ncnvrg = .true. ib = -jb else ib = jb end if do je = iwork( j ) + 1 + iwoff,iwork( j+in ) + iwoff w( je ) = tmp1 iblock( je ) = ib end do end do m = m + im end if end do loop_70 ! if range='i', then (wl,wu) contains eigenvalues nwl+1,...,nwu ! if nwl+1 < il or nwu > iu, discard extra eigenvalues. if( irange==3_${ik}$ ) then im = 0_${ik}$ idiscl = il - 1_${ik}$ - nwl idiscu = nwu - iu if( idiscl>0_${ik}$ .or. idiscu>0_${ik}$ ) then do je = 1, m if( w( je )<=wlu .and. idiscl>0_${ik}$ ) then idiscl = idiscl - 1_${ik}$ else if( w( je )>=wul .and. idiscu>0_${ik}$ ) then idiscu = idiscu - 1_${ik}$ else im = im + 1_${ik}$ w( im ) = w( je ) iblock( im ) = iblock( je ) end if end do m = im end if if( idiscl>0_${ik}$ .or. idiscu>0_${ik}$ ) then ! code to deal with effects of bad arithmetic: ! some low eigenvalues to be discarded are not in (wl,wlu], ! or high eigenvalues to be discarded are not in (wul,wu] ! so just kill off the smallest idiscl/largest idiscu ! eigenvalues, by simply finding the smallest/largest ! eigenvalue(s). ! (if n(w) is monotone non-decreasing, this should never ! happen.) if( idiscl>0_${ik}$ ) then wkill = wu do jdisc = 1, idiscl iw = 0_${ik}$ do je = 1, m if( iblock( je )/=0_${ik}$ .and.( w( je )0_${ik}$ ) then wkill = wl do jdisc = 1, idiscu iw = 0_${ik}$ do je = 1, m if( iblock( je )/=0_${ik}$ .and.( w( je )>wkill .or. iw==0_${ik}$ ) ) then iw = je wkill = w( je ) end if end do iblock( iw ) = 0_${ik}$ end do end if im = 0_${ik}$ do je = 1, m if( iblock( je )/=0_${ik}$ ) then im = im + 1_${ik}$ w( im ) = w( je ) iblock( im ) = iblock( je ) end if end do m = im end if if( idiscl<0_${ik}$ .or. idiscu<0_${ik}$ ) then toofew = .true. end if end if ! if order='b', do nothing -- the eigenvalues are already sorted ! by block. ! if order='e', sort the eigenvalues from smallest to largest if( iorder==1_${ik}$ .and. nsplit>1_${ik}$ ) then do je = 1, m - 1 ie = 0_${ik}$ tmp1 = w( je ) do j = je + 1, m if( w( j )=vu )info = -5_${ik}$ else if( irange==3_${ik}$ .and. ( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) )then info = -6_${ik}$ else if( irange==3_${ik}$ .and. ( iun ) )then info = -7_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSTEBZ', -info ) return end if ! initialize error flags info = 0_${ik}$ ncnvrg = .false. toofew = .false. ! quick return if possible m = 0_${ik}$ if( n==0 )return ! simplifications: if( irange==3_${ik}$ .and. il==1_${ik}$ .and. iu==n )irange = 1_${ik}$ ! get machine constants ! nb is the minimum vector length for vector bisection, or 0 ! if only scalar is to be done. safemn = stdlib${ii}$_${ri}$lamch( 'S' ) ulp = stdlib${ii}$_${ri}$lamch( 'P' ) rtoli = ulp*relfac nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DSTEBZ', ' ', n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) if( nb<=1_${ik}$ )nb = 0_${ik}$ ! special case when n=1 if( n==1_${ik}$ ) then nsplit = 1_${ik}$ isplit( 1_${ik}$ ) = 1_${ik}$ if( irange==2_${ik}$ .and. ( vl>=d( 1_${ik}$ ) .or. vutmp1 ) then isplit( nsplit ) = j - 1_${ik}$ nsplit = nsplit + 1_${ik}$ work( j-1 ) = zero else work( j-1 ) = tmp1 pivmin = max( pivmin, tmp1 ) end if end do isplit( nsplit ) = n pivmin = pivmin*safemn ! compute interval and atoli if( irange==3_${ik}$ ) then ! range='i': compute the interval containing eigenvalues ! il through iu. ! compute gershgorin interval for entire (split) matrix ! and use it as the initial interval gu = d( 1_${ik}$ ) gl = d( 1_${ik}$ ) tmp1 = zero do j = 1, n - 1 tmp2 = sqrt( work( j ) ) gu = max( gu, d( j )+tmp1+tmp2 ) gl = min( gl, d( j )-tmp1-tmp2 ) tmp1 = tmp2 end do gu = max( gu, d( n )+tmp1 ) gl = min( gl, d( n )-tmp1 ) tnorm = max( abs( gl ), abs( gu ) ) gl = gl - fudge*tnorm*ulp*n - fudge*two*pivmin gu = gu + fudge*tnorm*ulp*n + fudge*pivmin ! compute iteration parameters itmax = int( ( log( tnorm+pivmin )-log( pivmin ) ) /log( two ),KIND=${ik}$) + 2_${ik}$ if( abstol<=zero ) then atoli = ulp*tnorm else atoli = abstol end if work( n+1 ) = gl work( n+2 ) = gl work( n+3 ) = gu work( n+4 ) = gu work( n+5 ) = gl work( n+6 ) = gu iwork( 1_${ik}$ ) = -1_${ik}$ iwork( 2_${ik}$ ) = -1_${ik}$ iwork( 3_${ik}$ ) = n + 1_${ik}$ iwork( 4_${ik}$ ) = n + 1_${ik}$ iwork( 5_${ik}$ ) = il - 1_${ik}$ iwork( 6_${ik}$ ) = iu call stdlib${ii}$_${ri}$laebz( 3_${ik}$, itmax, n, 2_${ik}$, 2_${ik}$, nb, atoli, rtoli, pivmin, d, e,work, iwork( & 5_${ik}$ ), work( n+1 ), work( n+5 ), iout,iwork, w, iblock, iinfo ) if( iwork( 6_${ik}$ )==iu ) then wl = work( n+1 ) wlu = work( n+3 ) nwl = iwork( 1_${ik}$ ) wu = work( n+4 ) wul = work( n+2 ) nwu = iwork( 4_${ik}$ ) else wl = work( n+2 ) wlu = work( n+4 ) nwl = iwork( 2_${ik}$ ) wu = work( n+3 ) wul = work( n+1 ) nwu = iwork( 3_${ik}$ ) end if if( nwl<0_${ik}$ .or. nwl>=n .or. nwu<1_${ik}$ .or. nwu>n ) then info = 4_${ik}$ return end if else ! range='a' or 'v' -- set atoli tnorm = max( abs( d( 1_${ik}$ ) )+abs( e( 1_${ik}$ ) ),abs( d( n ) )+abs( e( n-1 ) ) ) do j = 2, n - 1 tnorm = max( tnorm, abs( d( j ) )+abs( e( j-1 ) )+abs( e( j ) ) ) end do if( abstol<=zero ) then atoli = ulp*tnorm else atoli = abstol end if if( irange==2_${ik}$ ) then wl = vl wu = vu else wl = zero wu = zero end if end if ! find eigenvalues -- loop over blocks and recompute nwl and nwu. ! nwl accumulates the number of eigenvalues .le. wl, ! nwu accumulates the number of eigenvalues .le. wu m = 0_${ik}$ iend = 0_${ik}$ info = 0_${ik}$ nwl = 0_${ik}$ nwu = 0_${ik}$ loop_70: do jb = 1, nsplit ioff = iend ibegin = ioff + 1_${ik}$ iend = isplit( jb ) in = iend - ioff if( in==1_${ik}$ ) then ! special case -- in=1 if( irange==1_${ik}$ .or. wl>=d( ibegin )-pivmin )nwl = nwl + 1_${ik}$ if( irange==1_${ik}$ .or. wu>=d( ibegin )-pivmin )nwu = nwu + 1_${ik}$ if( irange==1_${ik}$ .or. ( wl=d( ibegin )-pivmin ) ) & then m = m + 1_${ik}$ w( m ) = d( ibegin ) iblock( m ) = jb end if else ! general case -- in > 1 ! compute gershgorin interval ! and use it as the initial interval gu = d( ibegin ) gl = d( ibegin ) tmp1 = zero do j = ibegin, iend - 1 tmp2 = abs( e( j ) ) gu = max( gu, d( j )+tmp1+tmp2 ) gl = min( gl, d( j )-tmp1-tmp2 ) tmp1 = tmp2 end do gu = max( gu, d( iend )+tmp1 ) gl = min( gl, d( iend )-tmp1 ) bnorm = max( abs( gl ), abs( gu ) ) gl = gl - fudge*bnorm*ulp*in - fudge*pivmin gu = gu + fudge*bnorm*ulp*in + fudge*pivmin ! compute atoli for the current submatrix if( abstol<=zero ) then atoli = ulp*max( abs( gl ), abs( gu ) ) else atoli = abstol end if if( irange>1_${ik}$ ) then if( gu=gu )cycle loop_70 end if ! set up initial interval work( n+1 ) = gl work( n+in+1 ) = gu call stdlib${ii}$_${ri}$laebz( 1_${ik}$, 0_${ik}$, in, in, 1_${ik}$, nb, atoli, rtoli, pivmin,d( ibegin ), e( & ibegin ), work( ibegin ),idumma, work( n+1 ), work( n+2*in+1 ), im,iwork, w( m+1 & ), iblock( m+1 ), iinfo ) nwl = nwl + iwork( 1_${ik}$ ) nwu = nwu + iwork( in+1 ) iwoff = m - iwork( 1_${ik}$ ) ! compute eigenvalues itmax = int( ( log( gu-gl+pivmin )-log( pivmin ) ) /log( two ),KIND=${ik}$) + & 2_${ik}$ call stdlib${ii}$_${ri}$laebz( 2_${ik}$, itmax, in, in, 1_${ik}$, nb, atoli, rtoli, pivmin,d( ibegin ), e(& ibegin ), work( ibegin ),idumma, work( n+1 ), work( n+2*in+1 ), iout,iwork, w( & m+1 ), iblock( m+1 ), iinfo ) ! copy eigenvalues into w and iblock ! use -jb for block number for unconverged eigenvalues. do j = 1, iout tmp1 = half*( work( j+n )+work( j+in+n ) ) ! flag non-convergence. if( j>iout-iinfo ) then ncnvrg = .true. ib = -jb else ib = jb end if do je = iwork( j ) + 1 + iwoff,iwork( j+in ) + iwoff w( je ) = tmp1 iblock( je ) = ib end do end do m = m + im end if end do loop_70 ! if range='i', then (wl,wu) contains eigenvalues nwl+1,...,nwu ! if nwl+1 < il or nwu > iu, discard extra eigenvalues. if( irange==3_${ik}$ ) then im = 0_${ik}$ idiscl = il - 1_${ik}$ - nwl idiscu = nwu - iu if( idiscl>0_${ik}$ .or. idiscu>0_${ik}$ ) then do je = 1, m if( w( je )<=wlu .and. idiscl>0_${ik}$ ) then idiscl = idiscl - 1_${ik}$ else if( w( je )>=wul .and. idiscu>0_${ik}$ ) then idiscu = idiscu - 1_${ik}$ else im = im + 1_${ik}$ w( im ) = w( je ) iblock( im ) = iblock( je ) end if end do m = im end if if( idiscl>0_${ik}$ .or. idiscu>0_${ik}$ ) then ! code to deal with effects of bad arithmetic: ! some low eigenvalues to be discarded are not in (wl,wlu], ! or high eigenvalues to be discarded are not in (wul,wu] ! so just kill off the smallest idiscl/largest idiscu ! eigenvalues, by simply finding the smallest/largest ! eigenvalue(s). ! (if n(w) is monotone non-decreasing, this should never ! happen.) if( idiscl>0_${ik}$ ) then wkill = wu do jdisc = 1, idiscl iw = 0_${ik}$ do je = 1, m if( iblock( je )/=0_${ik}$ .and.( w( je )0_${ik}$ ) then wkill = wl do jdisc = 1, idiscu iw = 0_${ik}$ do je = 1, m if( iblock( je )/=0_${ik}$ .and.( w( je )>wkill .or. iw==0_${ik}$ ) ) then iw = je wkill = w( je ) end if end do iblock( iw ) = 0_${ik}$ end do end if im = 0_${ik}$ do je = 1, m if( iblock( je )/=0_${ik}$ ) then im = im + 1_${ik}$ w( im ) = w( je ) iblock( im ) = iblock( je ) end if end do m = im end if if( idiscl<0_${ik}$ .or. idiscu<0_${ik}$ ) then toofew = .true. end if end if ! if order='b', do nothing -- the eigenvalues are already sorted ! by block. ! if order='e', sort the eigenvalues from smallest to largest if( iorder==1_${ik}$ .and. nsplit>1_${ik}$ ) then do je = 1, m - 1 ie = 0_${ik}$ tmp1 = w( je ) do j = je + 1, m if( w( j )n )go to 170 if( l1>1_${ik}$ )e( l1-1 ) = zero do m = l1, n - 1 if( abs( e( m ) )<=( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+1 ) ) ) )*eps ) & then e( m ) = zero go to 30 end if end do m = n 30 continue l = l1 lsv = l lend = m lendsv = lend l1 = m + 1_${ik}$ if( lend==l )go to 10 ! scale submatrix in rows and columns l to lend anorm = stdlib${ii}$_slanst( 'M', lend-l+1, d( l ), e( l ) ) iscale = 0_${ik}$ if( anorm==zero )go to 10 if( anorm>ssfmax ) then iscale = 1_${ik}$ call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l+1, 1_${ik}$, d( l ), n,info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l, 1_${ik}$, e( l ), n,info ) else if( anorm=l ) then ! ql iteration ! look for small subdiagonal element. 50 continue if( l/=lend ) then do m = l, lend - 1 if( abs( e( m ) )<=eps2*abs( d( m )*d( m+1 ) ) )go to 70 end do end if m = lend 70 continue if( mlend )e( m-1 ) = zero p = d( l ) if( m==l )go to 140 ! if remaining matrix is 2 by 2, use stdlib_slae2 to compute its ! eigenvalues. if( m==l-1 ) then rte = sqrt( e( l-1 ) ) call stdlib${ii}$_slae2( d( l ), rte, d( l-1 ), rt1, rt2 ) d( l ) = rt1 d( l-1 ) = rt2 e( l-1 ) = zero l = l - 2_${ik}$ if( l>=lend )go to 100 go to 150 end if if( jtot==nmaxit )go to 150 jtot = jtot + 1_${ik}$ ! form shift. rte = sqrt( e( l-1 ) ) sigma = ( d( l-1 )-p ) / ( two*rte ) r = stdlib${ii}$_slapy2( sigma, one ) sigma = p - ( rte / ( sigma+sign( r, sigma ) ) ) c = one s = zero gamma = d( m ) - sigma p = gamma*gamma ! inner loop do i = m, l - 1 bb = e( i ) r = p + bb if( i/=m )e( i-1 ) = s*r oldc = c c = p / r s = bb / r oldgam = gamma alpha = d( i+1 ) gamma = c*( alpha-sigma ) - s*oldgam d( i ) = oldgam + ( alpha-gamma ) if( c/=zero ) then p = ( gamma*gamma ) / c else p = oldc*bb end if end do e( l-1 ) = s*p d( l ) = sigma + gamma go to 100 ! eigenvalue found. 140 continue d( l ) = p l = l - 1_${ik}$ if( l>=lend )go to 100 go to 150 end if ! undo scaling if necessary 150 continue if( iscale==1_${ik}$ )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), & n, info ) if( iscale==2_${ik}$ )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), & n, info ) ! check for no convergence to an eigenvalue after a total ! of n*maxit iterations. if( jtotn )go to 170 if( l1>1_${ik}$ )e( l1-1 ) = zero do m = l1, n - 1 if( abs( e( m ) )<=( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+1 ) ) ) )*eps ) & then e( m ) = zero go to 30 end if end do m = n 30 continue l = l1 lsv = l lend = m lendsv = lend l1 = m + 1_${ik}$ if( lend==l )go to 10 ! scale submatrix in rows and columns l to lend anorm = stdlib${ii}$_dlanst( 'M', lend-l+1, d( l ), e( l ) ) iscale = 0_${ik}$ if( anorm==zero )go to 10 if( (anorm>ssfmax) ) then iscale = 1_${ik}$ call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l+1, 1_${ik}$, d( l ), n,info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l, 1_${ik}$, e( l ), n,info ) else if( anorm=l ) then ! ql iteration ! look for small subdiagonal element. 50 continue if( l/=lend ) then do m = l, lend - 1 if( abs( e( m ) )<=eps2*abs( d( m )*d( m+1 ) ) )go to 70 end do end if m = lend 70 continue if( mlend )e( m-1 ) = zero p = d( l ) if( m==l )go to 140 ! if remaining matrix is 2 by 2, use stdlib_dlae2 to compute its ! eigenvalues. if( m==l-1 ) then rte = sqrt( e( l-1 ) ) call stdlib${ii}$_dlae2( d( l ), rte, d( l-1 ), rt1, rt2 ) d( l ) = rt1 d( l-1 ) = rt2 e( l-1 ) = zero l = l - 2_${ik}$ if( l>=lend )go to 100 go to 150 end if if( jtot==nmaxit )go to 150 jtot = jtot + 1_${ik}$ ! form shift. rte = sqrt( e( l-1 ) ) sigma = ( d( l-1 )-p ) / ( two*rte ) r = stdlib${ii}$_dlapy2( sigma, one ) sigma = p - ( rte / ( sigma+sign( r, sigma ) ) ) c = one s = zero gamma = d( m ) - sigma p = gamma*gamma ! inner loop do i = m, l - 1 bb = e( i ) r = p + bb if( i/=m )e( i-1 ) = s*r oldc = c c = p / r s = bb / r oldgam = gamma alpha = d( i+1 ) gamma = c*( alpha-sigma ) - s*oldgam d( i ) = oldgam + ( alpha-gamma ) if( c/=zero ) then p = ( gamma*gamma ) / c else p = oldc*bb end if end do e( l-1 ) = s*p d( l ) = sigma + gamma go to 100 ! eigenvalue found. 140 continue d( l ) = p l = l - 1_${ik}$ if( l>=lend )go to 100 go to 150 end if ! undo scaling if necessary 150 continue if( iscale==1_${ik}$ )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), & n, info ) if( iscale==2_${ik}$ )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), & n, info ) ! check for no convergence to an eigenvalue after a total ! of n*maxit iterations. if( jtotn )go to 170 if( l1>1_${ik}$ )e( l1-1 ) = zero do m = l1, n - 1 if( abs( e( m ) )<=( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+1 ) ) ) )*eps ) & then e( m ) = zero go to 30 end if end do m = n 30 continue l = l1 lsv = l lend = m lendsv = lend l1 = m + 1_${ik}$ if( lend==l )go to 10 ! scale submatrix in rows and columns l to lend anorm = stdlib${ii}$_${ri}$lanst( 'M', lend-l+1, d( l ), e( l ) ) iscale = 0_${ik}$ if( anorm==zero )go to 10 if( (anorm>ssfmax) ) then iscale = 1_${ik}$ call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l+1, 1_${ik}$, d( l ), n,info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l, 1_${ik}$, e( l ), n,info ) else if( anorm=l ) then ! ql iteration ! look for small subdiagonal element. 50 continue if( l/=lend ) then do m = l, lend - 1 if( abs( e( m ) )<=eps2*abs( d( m )*d( m+1 ) ) )go to 70 end do end if m = lend 70 continue if( mlend )e( m-1 ) = zero p = d( l ) if( m==l )go to 140 ! if remaining matrix is 2 by 2, use stdlib_${ri}$lae2 to compute its ! eigenvalues. if( m==l-1 ) then rte = sqrt( e( l-1 ) ) call stdlib${ii}$_${ri}$lae2( d( l ), rte, d( l-1 ), rt1, rt2 ) d( l ) = rt1 d( l-1 ) = rt2 e( l-1 ) = zero l = l - 2_${ik}$ if( l>=lend )go to 100 go to 150 end if if( jtot==nmaxit )go to 150 jtot = jtot + 1_${ik}$ ! form shift. rte = sqrt( e( l-1 ) ) sigma = ( d( l-1 )-p ) / ( two*rte ) r = stdlib${ii}$_${ri}$lapy2( sigma, one ) sigma = p - ( rte / ( sigma+sign( r, sigma ) ) ) c = one s = zero gamma = d( m ) - sigma p = gamma*gamma ! inner loop do i = m, l - 1 bb = e( i ) r = p + bb if( i/=m )e( i-1 ) = s*r oldc = c c = p / r s = bb / r oldgam = gamma alpha = d( i+1 ) gamma = c*( alpha-sigma ) - s*oldgam d( i ) = oldgam + ( alpha-gamma ) if( c/=zero ) then p = ( gamma*gamma ) / c else p = oldc*bb end if end do e( l-1 ) = s*p d( l ) = sigma + gamma go to 100 ! eigenvalue found. 140 continue d( l ) = p l = l - 1_${ik}$ if( l>=lend )go to 100 go to 150 end if ! undo scaling if necessary 150 continue if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), & n, info ) if( iscale==2_${ik}$ )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), & n, info ) ! check for no convergence to an eigenvalue after a total ! of n*maxit iterations. if( jtot0_${ik}$ .and. ldztiny ) then finish = finish + 1_${ik}$ go to 20 end if end if ! (sub) problem determined. compute its size and solve it. m = finish - start + 1_${ik}$ if( m==1_${ik}$ ) then start = finish + 1_${ik}$ go to 10 end if if( m>smlsiz ) then ! scale. orgnrm = stdlib${ii}$_slanst( 'M', m, d( start ), e( start ) ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m, 1_${ik}$, d( start ), m,info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m-1, 1_${ik}$, e( start ),m-1, info ) if( icompz==1_${ik}$ ) then strtrw = 1_${ik}$ else strtrw = start end if call stdlib${ii}$_slaed0( icompz, n, m, d( start ), e( start ),z( strtrw, start ), & ldz, work( 1_${ik}$ ), n,work( storez ), iwork, info ) if( info/=0_${ik}$ ) then info = ( info / ( m+1 )+start-1 )*( n+1 ) +mod( info, ( m+1 ) ) + start - & 1_${ik}$ go to 50 end if ! scale back. call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, m, 1_${ik}$, d( start ), m,info ) else if( icompz==1_${ik}$ ) then ! since qr won't update a z matrix which is larger than ! the length of d, we must solve the sub-problem in a ! workspace and then multiply back into z. call stdlib${ii}$_ssteqr( 'I', m, d( start ), e( start ), work, m,work( m*m+1 ), & info ) call stdlib${ii}$_slacpy( 'A', n, m, z( 1_${ik}$, start ), ldz,work( storez ), n ) call stdlib${ii}$_sgemm( 'N', 'N', n, m, m, one,work( storez ), n, work, m, zero,& z( 1_${ik}$, start ), ldz ) else if( icompz==2_${ik}$ ) then call stdlib${ii}$_ssteqr( 'I', m, d( start ), e( start ),z( start, start ), ldz, & work, info ) else call stdlib${ii}$_ssterf( m, d( start ), e( start ), info ) end if if( info/=0_${ik}$ ) then info = start*( n+1 ) + finish go to 50 end if end if start = finish + 1_${ik}$ go to 10 end if ! endwhile if( icompz==0_${ik}$ ) then ! use quick sort call stdlib${ii}$_slasrt( 'I', n, d, info ) else ! use selection sort to minimize swaps of eigenvectors do ii = 2, n i = ii - 1_${ik}$ k = i p = d( i ) do j = ii, n if( d( j )

0_${ik}$ .and. ldztiny ) then finish = finish + 1_${ik}$ go to 20 end if end if ! (sub) problem determined. compute its size and solve it. m = finish - start + 1_${ik}$ if( m==1_${ik}$ ) then start = finish + 1_${ik}$ go to 10 end if if( m>smlsiz ) then ! scale. orgnrm = stdlib${ii}$_dlanst( 'M', m, d( start ), e( start ) ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m, 1_${ik}$, d( start ), m,info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m-1, 1_${ik}$, e( start ),m-1, info ) if( icompz==1_${ik}$ ) then strtrw = 1_${ik}$ else strtrw = start end if call stdlib${ii}$_dlaed0( icompz, n, m, d( start ), e( start ),z( strtrw, start ), & ldz, work( 1_${ik}$ ), n,work( storez ), iwork, info ) if( info/=0_${ik}$ ) then info = ( info / ( m+1 )+start-1 )*( n+1 ) +mod( info, ( m+1 ) ) + start - & 1_${ik}$ go to 50 end if ! scale back. call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, m, 1_${ik}$, d( start ), m,info ) else if( icompz==1_${ik}$ ) then ! since qr won't update a z matrix which is larger than ! the length of d, we must solve the sub-problem in a ! workspace and then multiply back into z. call stdlib${ii}$_dsteqr( 'I', m, d( start ), e( start ), work, m,work( m*m+1 ), & info ) call stdlib${ii}$_dlacpy( 'A', n, m, z( 1_${ik}$, start ), ldz,work( storez ), n ) call stdlib${ii}$_dgemm( 'N', 'N', n, m, m, one,work( storez ), n, work, m, zero,& z( 1_${ik}$, start ), ldz ) else if( icompz==2_${ik}$ ) then call stdlib${ii}$_dsteqr( 'I', m, d( start ), e( start ),z( start, start ), ldz, & work, info ) else call stdlib${ii}$_dsterf( m, d( start ), e( start ), info ) end if if( info/=0_${ik}$ ) then info = start*( n+1 ) + finish go to 50 end if end if start = finish + 1_${ik}$ go to 10 end if ! endwhile if( icompz==0_${ik}$ ) then ! use quick sort call stdlib${ii}$_dlasrt( 'I', n, d, info ) else ! use selection sort to minimize swaps of eigenvectors do ii = 2, n i = ii - 1_${ik}$ k = i p = d( i ) do j = ii, n if( d( j )

0_${ik}$ .and. ldztiny ) then finish = finish + 1_${ik}$ go to 20 end if end if ! (sub) problem determined. compute its size and solve it. m = finish - start + 1_${ik}$ if( m==1_${ik}$ ) then start = finish + 1_${ik}$ go to 10 end if if( m>smlsiz ) then ! scale. orgnrm = stdlib${ii}$_${ri}$lanst( 'M', m, d( start ), e( start ) ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m, 1_${ik}$, d( start ), m,info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m-1, 1_${ik}$, e( start ),m-1, info ) if( icompz==1_${ik}$ ) then strtrw = 1_${ik}$ else strtrw = start end if call stdlib${ii}$_${ri}$laed0( icompz, n, m, d( start ), e( start ),z( strtrw, start ), & ldz, work( 1_${ik}$ ), n,work( storez ), iwork, info ) if( info/=0_${ik}$ ) then info = ( info / ( m+1 )+start-1 )*( n+1 ) +mod( info, ( m+1 ) ) + start - & 1_${ik}$ go to 50 end if ! scale back. call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, m, 1_${ik}$, d( start ), m,info ) else if( icompz==1_${ik}$ ) then ! since qr won't update a z matrix which is larger than ! the length of d, we must solve the sub-problem in a ! workspace and then multiply back into z. call stdlib${ii}$_${ri}$steqr( 'I', m, d( start ), e( start ), work, m,work( m*m+1 ), & info ) call stdlib${ii}$_${ri}$lacpy( 'A', n, m, z( 1_${ik}$, start ), ldz,work( storez ), n ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, m, m, one,work( storez ), n, work, m, zero,& z( 1_${ik}$, start ), ldz ) else if( icompz==2_${ik}$ ) then call stdlib${ii}$_${ri}$steqr( 'I', m, d( start ), e( start ),z( start, start ), ldz, & work, info ) else call stdlib${ii}$_${ri}$sterf( m, d( start ), e( start ), info ) end if if( info/=0_${ik}$ ) then info = start*( n+1 ) + finish go to 50 end if end if start = finish + 1_${ik}$ go to 10 end if ! endwhile if( icompz==0_${ik}$ ) then ! use quick sort call stdlib${ii}$_${ri}$lasrt( 'I', n, d, info ) else ! use selection sort to minimize swaps of eigenvectors do ii = 2, n i = ii - 1_${ik}$ k = i p = d( i ) do j = ii, n if( d( j )

0_${ik}$ .and. ldztiny ) then finish = finish + 1_${ik}$ go to 40 end if end if ! (sub) problem determined. compute its size and solve it. m = finish - start + 1_${ik}$ if( m>smlsiz ) then ! scale. orgnrm = stdlib${ii}$_slanst( 'M', m, d( start ), e( start ) ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m, 1_${ik}$, d( start ), m,info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m-1, 1_${ik}$, e( start ),m-1, info ) call stdlib${ii}$_claed0( n, m, d( start ), e( start ), z( 1_${ik}$, start ),ldz, work, n, & rwork, iwork, info ) if( info>0_${ik}$ ) then info = ( info / ( m+1 )+start-1 )*( n+1 ) +mod( info, ( m+1 ) ) + start - & 1_${ik}$ go to 70 end if ! scale back. call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, m, 1_${ik}$, d( start ), m,info ) else call stdlib${ii}$_ssteqr( 'I', m, d( start ), e( start ), rwork, m,rwork( m*m+1 ), & info ) call stdlib${ii}$_clacrm( n, m, z( 1_${ik}$, start ), ldz, rwork, m, work, n,rwork( m*m+1 )& ) call stdlib${ii}$_clacpy( 'A', n, m, work, n, z( 1_${ik}$, start ), ldz ) if( info>0_${ik}$ ) then info = start*( n+1 ) + finish go to 70 end if end if start = finish + 1_${ik}$ go to 30 end if ! endwhile ! use selection sort to minimize swaps of eigenvectors do ii = 2, n i = ii - 1_${ik}$ k = i p = d( i ) do j = ii, n if( d( j )

0_${ik}$ .and. ldztiny ) then finish = finish + 1_${ik}$ go to 40 end if end if ! (sub) problem determined. compute its size and solve it. m = finish - start + 1_${ik}$ if( m>smlsiz ) then ! scale. orgnrm = stdlib${ii}$_dlanst( 'M', m, d( start ), e( start ) ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m, 1_${ik}$, d( start ), m,info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m-1, 1_${ik}$, e( start ),m-1, info ) call stdlib${ii}$_zlaed0( n, m, d( start ), e( start ), z( 1_${ik}$, start ),ldz, work, n, & rwork, iwork, info ) if( info>0_${ik}$ ) then info = ( info / ( m+1 )+start-1 )*( n+1 ) +mod( info, ( m+1 ) ) + start - & 1_${ik}$ go to 70 end if ! scale back. call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, m, 1_${ik}$, d( start ), m,info ) else call stdlib${ii}$_dsteqr( 'I', m, d( start ), e( start ), rwork, m,rwork( m*m+1 ), & info ) call stdlib${ii}$_zlacrm( n, m, z( 1_${ik}$, start ), ldz, rwork, m, work, n,rwork( m*m+1 )& ) call stdlib${ii}$_zlacpy( 'A', n, m, work, n, z( 1_${ik}$, start ), ldz ) if( info>0_${ik}$ ) then info = start*( n+1 ) + finish go to 70 end if end if start = finish + 1_${ik}$ go to 30 end if ! endwhile ! use selection sort to minimize swaps of eigenvectors do ii = 2, n i = ii - 1_${ik}$ k = i p = d( i ) do j = ii, n if( d( j )

0_${ik}$ .and. ldztiny ) then finish = finish + 1_${ik}$ go to 40 end if end if ! (sub) problem determined. compute its size and solve it. m = finish - start + 1_${ik}$ if( m>smlsiz ) then ! scale. orgnrm = stdlib${ii}$_${c2ri(ci)}$lanst( 'M', m, d( start ), e( start ) ) call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m, 1_${ik}$, d( start ), m,info ) call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, m-1, 1_${ik}$, e( start ),m-1, info ) call stdlib${ii}$_${ci}$laed0( n, m, d( start ), e( start ), z( 1_${ik}$, start ),ldz, work, n, & rwork, iwork, info ) if( info>0_${ik}$ ) then info = ( info / ( m+1 )+start-1 )*( n+1 ) +mod( info, ( m+1 ) ) + start - & 1_${ik}$ go to 70 end if ! scale back. call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, m, 1_${ik}$, d( start ), m,info ) else call stdlib${ii}$_${c2ri(ci)}$steqr( 'I', m, d( start ), e( start ), rwork, m,rwork( m*m+1 ), & info ) call stdlib${ii}$_${ci}$lacrm( n, m, z( 1_${ik}$, start ), ldz, rwork, m, work, n,rwork( m*m+1 )& ) call stdlib${ii}$_${ci}$lacpy( 'A', n, m, work, n, z( 1_${ik}$, start ), ldz ) if( info>0_${ik}$ ) then info = start*( n+1 ) + finish go to 70 end if end if start = finish + 1_${ik}$ go to 30 end if ! endwhile ! use selection sort to minimize swaps of eigenvectors do ii = 2, n i = ii - 1_${ik}$ k = i p = d( i ) do j = ii, n if( d( j )

n ) then info = -4_${ik}$ else if( ldz1_${ik}$ ) then eps1 = abs( eps*xj ) pertol = ten*eps1 sep = xj - xjm if( sepmaxits )go to 100 ! normalize and scale the righthand side vector pb. jmax = stdlib${ii}$_isamax( blksiz, work( indrv1+1 ), 1_${ik}$ ) scl = blksiz*onenrm*max( eps,abs( work( indrv4+blksiz ) ) ) /abs( work( indrv1+& jmax ) ) call stdlib${ii}$_sscal( blksiz, scl, work( indrv1+1 ), 1_${ik}$ ) ! solve the system lu = pb. call stdlib${ii}$_slagts( -1_${ik}$, blksiz, work( indrv4+1 ), work( indrv2+2 ),work( indrv3+& 1_${ik}$ ), work( indrv5+1 ), iwork,work( indrv1+1 ), tol, iinfo ) ! reorthogonalize by modified gram-schmidt if eigenvalues are ! close enough. if( jblk==1 )go to 90 if( abs( xj-xjm )>ortol )gpind = j if( gpind/=j ) then do i = gpind, j - 1 ctr = -stdlib${ii}$_sdot( blksiz, work( indrv1+1 ), 1_${ik}$, z( b1, i ),1_${ik}$ ) call stdlib${ii}$_saxpy( blksiz, ctr, z( b1, i ), 1_${ik}$,work( indrv1+1 ), 1_${ik}$ ) end do end if ! check the infinity norm of the iterate. 90 continue jmax = stdlib${ii}$_isamax( blksiz, work( indrv1+1 ), 1_${ik}$ ) nrm = abs( work( indrv1+jmax ) ) ! continue for additional iterations after norm reaches ! stopping criterion. if( nrmn ) then info = -4_${ik}$ else if( ldz1_${ik}$ ) then eps1 = abs( eps*xj ) pertol = ten*eps1 sep = xj - xjm if( sepmaxits )go to 100 ! normalize and scale the righthand side vector pb. jmax = stdlib${ii}$_idamax( blksiz, work( indrv1+1 ), 1_${ik}$ ) scl = blksiz*onenrm*max( eps,abs( work( indrv4+blksiz ) ) ) /abs( work( indrv1+& jmax ) ) call stdlib${ii}$_dscal( blksiz, scl, work( indrv1+1 ), 1_${ik}$ ) ! solve the system lu = pb. call stdlib${ii}$_dlagts( -1_${ik}$, blksiz, work( indrv4+1 ), work( indrv2+2 ),work( indrv3+& 1_${ik}$ ), work( indrv5+1 ), iwork,work( indrv1+1 ), tol, iinfo ) ! reorthogonalize by modified gram-schmidt if eigenvalues are ! close enough. if( jblk==1 )go to 90 if( abs( xj-xjm )>ortol )gpind = j if( gpind/=j ) then do i = gpind, j - 1 ztr = -stdlib${ii}$_ddot( blksiz, work( indrv1+1 ), 1_${ik}$, z( b1, i ),1_${ik}$ ) call stdlib${ii}$_daxpy( blksiz, ztr, z( b1, i ), 1_${ik}$,work( indrv1+1 ), 1_${ik}$ ) end do end if ! check the infinity norm of the iterate. 90 continue jmax = stdlib${ii}$_idamax( blksiz, work( indrv1+1 ), 1_${ik}$ ) nrm = abs( work( indrv1+jmax ) ) ! continue for additional iterations after norm reaches ! stopping criterion. if( nrmn ) then info = -4_${ik}$ else if( ldz1_${ik}$ ) then eps1 = abs( eps*xj ) pertol = ten*eps1 sep = xj - xjm if( sepmaxits )go to 100 ! normalize and scale the righthand side vector pb. jmax = stdlib${ii}$_i${ri}$amax( blksiz, work( indrv1+1 ), 1_${ik}$ ) scl = blksiz*onenrm*max( eps,abs( work( indrv4+blksiz ) ) ) /abs( work( indrv1+& jmax ) ) call stdlib${ii}$_${ri}$scal( blksiz, scl, work( indrv1+1 ), 1_${ik}$ ) ! solve the system lu = pb. call stdlib${ii}$_${ri}$lagts( -1_${ik}$, blksiz, work( indrv4+1 ), work( indrv2+2 ),work( indrv3+& 1_${ik}$ ), work( indrv5+1 ), iwork,work( indrv1+1 ), tol, iinfo ) ! reorthogonalize by modified gram-schmidt if eigenvalues are ! close enough. if( jblk==1 )go to 90 if( abs( xj-xjm )>ortol )gpind = j if( gpind/=j ) then do i = gpind, j - 1 ztr = -stdlib${ii}$_${ri}$dot( blksiz, work( indrv1+1 ), 1_${ik}$, z( b1, i ),1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( blksiz, ztr, z( b1, i ), 1_${ik}$,work( indrv1+1 ), 1_${ik}$ ) end do end if ! check the infinity norm of the iterate. 90 continue jmax = stdlib${ii}$_i${ri}$amax( blksiz, work( indrv1+1 ), 1_${ik}$ ) nrm = abs( work( indrv1+jmax ) ) ! continue for additional iterations after norm reaches ! stopping criterion. if( nrmn ) then info = -4_${ik}$ else if( ldz1_${ik}$ ) then eps1 = abs( eps*xj ) pertol = ten*eps1 sep = xj - xjm if( sepmaxits )go to 120 ! normalize and scale the righthand side vector pb. jmax = stdlib${ii}$_isamax( blksiz, work( indrv1+1 ), 1_${ik}$ ) scl = blksiz*onenrm*max( eps,abs( work( indrv4+blksiz ) ) ) /abs( work( indrv1+& jmax ) ) call stdlib${ii}$_sscal( blksiz, scl, work( indrv1+1 ), 1_${ik}$ ) ! solve the system lu = pb. call stdlib${ii}$_slagts( -1_${ik}$, blksiz, work( indrv4+1 ), work( indrv2+2 ),work( indrv3+& 1_${ik}$ ), work( indrv5+1 ), iwork,work( indrv1+1 ), tol, iinfo ) ! reorthogonalize by modified gram-schmidt if eigenvalues are ! close enough. if( jblk==1 )go to 110 if( abs( xj-xjm )>ortol )gpind = j if( gpind/=j ) then do i = gpind, j - 1 ctr = zero do jr = 1, blksiz ctr = ctr + work( indrv1+jr )*real( z( b1-1+jr, i ),KIND=sp) end do do jr = 1, blksiz work( indrv1+jr ) = work( indrv1+jr ) -ctr*real( z( b1-1+jr, i ),& KIND=sp) end do end do end if ! check the infinity norm of the iterate. 110 continue jmax = stdlib${ii}$_isamax( blksiz, work( indrv1+1 ), 1_${ik}$ ) nrm = abs( work( indrv1+jmax ) ) ! continue for additional iterations after norm reaches ! stopping criterion. if( nrmn ) then info = -4_${ik}$ else if( ldz1_${ik}$ ) then eps1 = abs( eps*xj ) pertol = ten*eps1 sep = xj - xjm if( sepmaxits )go to 120 ! normalize and scale the righthand side vector pb. jmax = stdlib${ii}$_idamax( blksiz, work( indrv1+1 ), 1_${ik}$ ) scl = blksiz*onenrm*max( eps,abs( work( indrv4+blksiz ) ) ) /abs( work( indrv1+& jmax ) ) call stdlib${ii}$_dscal( blksiz, scl, work( indrv1+1 ), 1_${ik}$ ) ! solve the system lu = pb. call stdlib${ii}$_dlagts( -1_${ik}$, blksiz, work( indrv4+1 ), work( indrv2+2 ),work( indrv3+& 1_${ik}$ ), work( indrv5+1 ), iwork,work( indrv1+1 ), tol, iinfo ) ! reorthogonalize by modified gram-schmidt if eigenvalues are ! close enough. if( jblk==1 )go to 110 if( abs( xj-xjm )>ortol )gpind = j if( gpind/=j ) then do i = gpind, j - 1 ztr = zero do jr = 1, blksiz ztr = ztr + work( indrv1+jr )*real( z( b1-1+jr, i ),KIND=dp) end do do jr = 1, blksiz work( indrv1+jr ) = work( indrv1+jr ) -ztr*real( z( b1-1+jr, i ),& KIND=dp) end do end do end if ! check the infinity norm of the iterate. 110 continue jmax = stdlib${ii}$_idamax( blksiz, work( indrv1+1 ), 1_${ik}$ ) nrm = abs( work( indrv1+jmax ) ) ! continue for additional iterations after norm reaches ! stopping criterion. if( nrmn ) then info = -4_${ik}$ else if( ldz1_${ik}$ ) then eps1 = abs( eps*xj ) pertol = ten*eps1 sep = xj - xjm if( sepmaxits )go to 120 ! normalize and scale the righthand side vector pb. jmax = stdlib${ii}$_i${c2ri(ci)}$amax( blksiz, work( indrv1+1 ), 1_${ik}$ ) scl = blksiz*onenrm*max( eps,abs( work( indrv4+blksiz ) ) ) /abs( work( indrv1+& jmax ) ) call stdlib${ii}$_${c2ri(ci)}$scal( blksiz, scl, work( indrv1+1 ), 1_${ik}$ ) ! solve the system lu = pb. call stdlib${ii}$_${c2ri(ci)}$lagts( -1_${ik}$, blksiz, work( indrv4+1 ), work( indrv2+2 ),work( indrv3+& 1_${ik}$ ), work( indrv5+1 ), iwork,work( indrv1+1 ), tol, iinfo ) ! reorthogonalize by modified gram-schmidt if eigenvalues are ! close enough. if( jblk==1 )go to 110 if( abs( xj-xjm )>ortol )gpind = j if( gpind/=j ) then do i = gpind, j - 1 ztr = zero do jr = 1, blksiz ztr = ztr + work( indrv1+jr )*real( z( b1-1+jr, i ),KIND=${ck}$) end do do jr = 1, blksiz work( indrv1+jr ) = work( indrv1+jr ) -ztr*real( z( b1-1+jr, i ),& KIND=${ck}$) end do end do end if ! check the infinity norm of the iterate. 110 continue jmax = stdlib${ii}$_i${c2ri(ci)}$amax( blksiz, work( indrv1+1 ), 1_${ik}$ ) nrm = abs( work( indrv1+jmax ) ) ! continue for additional iterations after norm reaches ! stopping criterion. if( nrm0_${ik}$ .and. wu<=wl ) then info = -7_${ik}$ else if( indeig .and. ( iil<1_${ik}$ .or. iil>n ) ) then info = -8_${ik}$ else if( indeig .and. ( iiun ) ) then info = -9_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz(1_${ik}$) = 1_${ik}$ isuppz(2_${ik}$) = 1_${ik}$ end if return end if if( n==2_${ik}$ ) then if( .not.wantz ) then call stdlib${ii}$_slae2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2 ) else if( wantz.and.(.not.zquery) ) then call stdlib${ii}$_slaev2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2, cs, sn ) end if if( alleig.or.(valeig.and.(r2>wl).and.(r2<=wu)).or.(indeig.and.(iil==1_${ik}$)) ) & then m = m+1 w( m ) = r2 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = -sn z( 2_${ik}$, m ) = cs ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif if( alleig.or.(valeig.and.(r1>wl).and.(r1<=wu)).or.(indeig.and.(iiu==2_${ik}$)) ) & then m = m+1 w( m ) = r1 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = cs z( 2_${ik}$, m ) = sn ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif else ! continue with general n indgrs = 1_${ik}$ inderr = 2_${ik}$*n + 1_${ik}$ indgp = 3_${ik}$*n + 1_${ik}$ indd = 4_${ik}$*n + 1_${ik}$ inde2 = 5_${ik}$*n + 1_${ik}$ indwrk = 6_${ik}$*n + 1_${ik}$ iinspl = 1_${ik}$ iindbl = n + 1_${ik}$ iindw = 2_${ik}$*n + 1_${ik}$ iindwk = 3_${ik}$*n + 1_${ik}$ ! scale matrix to allowable range, if necessary. ! the allowable range is related to the pivmin parameter; see the ! comments in stdlib${ii}$_slarrd. the preference for scaling small values ! up is heuristic; we expect users' matrices not to be close to the ! rmax threshold. scale = one tnrm = stdlib${ii}$_slanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then scale = rmax / tnrm end if if( scale/=one ) then call stdlib${ii}$_sscal( n, scale, d, 1_${ik}$ ) call stdlib${ii}$_sscal( n-1, scale, e, 1_${ik}$ ) tnrm = tnrm*scale if( valeig ) then ! if eigenvalues in interval have to be found, ! scale (wl, wu] accordingly wl = wl*scale wu = wu*scale endif end if ! compute the desired eigenvalues of the tridiagonal after splitting ! into smaller subblocks if the corresponding off-diagonal elements ! are small ! thresh is the splitting parameter for stdlib${ii}$_slarre ! a negative thresh forces the old splitting criterion based on the ! size of the off-diagonal. a positive thresh switches to splitting ! which preserves relative accuracy. if( tryrac ) then ! test whether the matrix warrants the more expensive relative approach. call stdlib${ii}$_slarrr( n, d, e, iinfo ) else ! the user does not care about relative accurately eigenvalues iinfo = -1_${ik}$ endif ! set the splitting criterion if (iinfo==0_${ik}$) then thresh = eps else thresh = -eps ! relative accuracy is desired but t does not guarantee it tryrac = .false. endif if( tryrac ) then ! copy original diagonal, needed to guarantee relative accuracy call stdlib${ii}$_scopy(n,d,1_${ik}$,work(indd),1_${ik}$) endif ! store the squares of the offdiagonal values of t do j = 1, n-1 work( inde2+j-1 ) = e(j)**2_${ik}$ end do ! set the tolerance parameters for bisection if( .not.wantz ) then ! stdlib${ii}$_slarre computes the eigenvalues to full precision. rtol1 = four * eps rtol2 = four * eps else ! stdlib${ii}$_slarre computes the eigenvalues to less than full precision. ! stdlib${ii}$_slarrv will refine the eigenvalue approximations, and we can ! need less accurate initial bisection in stdlib${ii}$_slarre. ! note: these settings do only affect the subset case and stdlib${ii}$_slarre rtol1 = max( sqrt(eps)*5.0e-2_sp, four * eps ) rtol2 = max( sqrt(eps)*5.0e-3_sp, four * eps ) endif call stdlib${ii}$_slarre( range, n, wl, wu, iil, iiu, d, e,work(inde2), rtol1, rtol2, & thresh, nsplit,iwork( iinspl ), m, w, work( inderr ),work( indgp ), iwork( iindbl ),& iwork( iindw ), work( indgrs ), pivmin,work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 10_${ik}$ + abs( iinfo ) return end if ! note that if range /= 'v', stdlib${ii}$_slarre computes bounds on the desired ! part of the spectrum. all desired eigenvalues are contained in ! (wl,wu] if( wantz ) then ! compute the desired eigenvectors corresponding to the computed ! eigenvalues call stdlib${ii}$_slarrv( n, wl, wu, d, e,pivmin, iwork( iinspl ), m,1_${ik}$, m, minrgp, & rtol1, rtol2,w, work( inderr ), work( indgp ), iwork( iindbl ),iwork( iindw ), & work( indgrs ), z, ldz,isuppz, work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 20_${ik}$ + abs( iinfo ) return end if else ! stdlib${ii}$_slarre computes eigenvalues of the (shifted) root representation ! stdlib${ii}$_slarrv returns the eigenvalues of the unshifted matrix. ! however, if the eigenvectors are not desired by the user, we need ! to apply the corresponding shifts from stdlib${ii}$_slarre to obtain the ! eigenvalues of the original matrix. do j = 1, m itmp = iwork( iindbl+j-1 ) w( j ) = w( j ) + e( iwork( iinspl+itmp-1 ) ) end do end if if ( tryrac ) then ! refine computed eigenvalues so that they are relatively accurate ! with respect to the original matrix t. ibegin = 1_${ik}$ wbegin = 1_${ik}$ loop_39: do jblk = 1, iwork( iindbl+m-1 ) iend = iwork( iinspl+jblk-1 ) in = iend - ibegin + 1_${ik}$ wend = wbegin - 1_${ik}$ ! check if any eigenvalues have to be refined in this block 36 continue if( wend1_${ik}$ .or. n==2_${ik}$ ) then if( .not. wantz ) then call stdlib${ii}$_slasrt( 'I', m, w, iinfo ) if( iinfo/=0_${ik}$ ) then info = 3_${ik}$ return end if else do j = 1, m - 1 i = 0_${ik}$ tmp = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. wu<=wl ) then info = -7_${ik}$ else if( indeig .and. ( iil<1_${ik}$ .or. iil>n ) ) then info = -8_${ik}$ else if( indeig .and. ( iiun ) ) then info = -9_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz(1_${ik}$) = 1_${ik}$ isuppz(2_${ik}$) = 1_${ik}$ end if return end if if( n==2_${ik}$ ) then if( .not.wantz ) then call stdlib${ii}$_dlae2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2 ) else if( wantz.and.(.not.zquery) ) then call stdlib${ii}$_dlaev2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2, cs, sn ) end if if( alleig.or.(valeig.and.(r2>wl).and.(r2<=wu)).or.(indeig.and.(iil==1_${ik}$)) ) & then m = m+1 w( m ) = r2 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = -sn z( 2_${ik}$, m ) = cs ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif if( alleig.or.(valeig.and.(r1>wl).and.(r1<=wu)).or.(indeig.and.(iiu==2_${ik}$)) ) & then m = m+1 w( m ) = r1 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = cs z( 2_${ik}$, m ) = sn ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif else ! continue with general n indgrs = 1_${ik}$ inderr = 2_${ik}$*n + 1_${ik}$ indgp = 3_${ik}$*n + 1_${ik}$ indd = 4_${ik}$*n + 1_${ik}$ inde2 = 5_${ik}$*n + 1_${ik}$ indwrk = 6_${ik}$*n + 1_${ik}$ iinspl = 1_${ik}$ iindbl = n + 1_${ik}$ iindw = 2_${ik}$*n + 1_${ik}$ iindwk = 3_${ik}$*n + 1_${ik}$ ! scale matrix to allowable range, if necessary. ! the allowable range is related to the pivmin parameter; see the ! comments in stdlib${ii}$_dlarrd. the preference for scaling small values ! up is heuristic; we expect users' matrices not to be close to the ! rmax threshold. scale = one tnrm = stdlib${ii}$_dlanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then scale = rmax / tnrm end if if( scale/=one ) then call stdlib${ii}$_dscal( n, scale, d, 1_${ik}$ ) call stdlib${ii}$_dscal( n-1, scale, e, 1_${ik}$ ) tnrm = tnrm*scale if( valeig ) then ! if eigenvalues in interval have to be found, ! scale (wl, wu] accordingly wl = wl*scale wu = wu*scale endif end if ! compute the desired eigenvalues of the tridiagonal after splitting ! into smaller subblocks if the corresponding off-diagonal elements ! are small ! thresh is the splitting parameter for stdlib${ii}$_dlarre ! a negative thresh forces the old splitting criterion based on the ! size of the off-diagonal. a positive thresh switches to splitting ! which preserves relative accuracy. if( tryrac ) then ! test whether the matrix warrants the more expensive relative approach. call stdlib${ii}$_dlarrr( n, d, e, iinfo ) else ! the user does not care about relative accurately eigenvalues iinfo = -1_${ik}$ endif ! set the splitting criterion if (iinfo==0_${ik}$) then thresh = eps else thresh = -eps ! relative accuracy is desired but t does not guarantee it tryrac = .false. endif if( tryrac ) then ! copy original diagonal, needed to guarantee relative accuracy call stdlib${ii}$_dcopy(n,d,1_${ik}$,work(indd),1_${ik}$) endif ! store the squares of the offdiagonal values of t do j = 1, n-1 work( inde2+j-1 ) = e(j)**2_${ik}$ end do ! set the tolerance parameters for bisection if( .not.wantz ) then ! stdlib${ii}$_dlarre computes the eigenvalues to full precision. rtol1 = four * eps rtol2 = four * eps else ! stdlib${ii}$_dlarre computes the eigenvalues to less than full precision. ! stdlib${ii}$_dlarrv will refine the eigenvalue approximations, and we can ! need less accurate initial bisection in stdlib${ii}$_dlarre. ! note: these settings do only affect the subset case and stdlib${ii}$_dlarre rtol1 = sqrt(eps) rtol2 = max( sqrt(eps)*5.0e-3_dp, four * eps ) endif call stdlib${ii}$_dlarre( range, n, wl, wu, iil, iiu, d, e,work(inde2), rtol1, rtol2, & thresh, nsplit,iwork( iinspl ), m, w, work( inderr ),work( indgp ), iwork( iindbl ),& iwork( iindw ), work( indgrs ), pivmin,work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 10_${ik}$ + abs( iinfo ) return end if ! note that if range /= 'v', stdlib${ii}$_dlarre computes bounds on the desired ! part of the spectrum. all desired eigenvalues are contained in ! (wl,wu] if( wantz ) then ! compute the desired eigenvectors corresponding to the computed ! eigenvalues call stdlib${ii}$_dlarrv( n, wl, wu, d, e,pivmin, iwork( iinspl ), m,1_${ik}$, m, minrgp, & rtol1, rtol2,w, work( inderr ), work( indgp ), iwork( iindbl ),iwork( iindw ), & work( indgrs ), z, ldz,isuppz, work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 20_${ik}$ + abs( iinfo ) return end if else ! stdlib${ii}$_dlarre computes eigenvalues of the (shifted) root representation ! stdlib${ii}$_dlarrv returns the eigenvalues of the unshifted matrix. ! however, if the eigenvectors are not desired by the user, we need ! to apply the corresponding shifts from stdlib${ii}$_dlarre to obtain the ! eigenvalues of the original matrix. do j = 1, m itmp = iwork( iindbl+j-1 ) w( j ) = w( j ) + e( iwork( iinspl+itmp-1 ) ) end do end if if ( tryrac ) then ! refine computed eigenvalues so that they are relatively accurate ! with respect to the original matrix t. ibegin = 1_${ik}$ wbegin = 1_${ik}$ loop_39: do jblk = 1, iwork( iindbl+m-1 ) iend = iwork( iinspl+jblk-1 ) in = iend - ibegin + 1_${ik}$ wend = wbegin - 1_${ik}$ ! check if any eigenvalues have to be refined in this block 36 continue if( wend1_${ik}$ .or. n==2_${ik}$ ) then if( .not. wantz ) then call stdlib${ii}$_dlasrt( 'I', m, w, iinfo ) if( iinfo/=0_${ik}$ ) then info = 3_${ik}$ return end if else do j = 1, m - 1 i = 0_${ik}$ tmp = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. wu<=wl ) then info = -7_${ik}$ else if( indeig .and. ( iil<1_${ik}$ .or. iil>n ) ) then info = -8_${ik}$ else if( indeig .and. ( iiun ) ) then info = -9_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz(1_${ik}$) = 1_${ik}$ isuppz(2_${ik}$) = 1_${ik}$ end if return end if if( n==2_${ik}$ ) then if( .not.wantz ) then call stdlib${ii}$_${ri}$lae2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2 ) else if( wantz.and.(.not.zquery) ) then call stdlib${ii}$_${ri}$laev2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2, cs, sn ) end if if( alleig.or.(valeig.and.(r2>wl).and.(r2<=wu)).or.(indeig.and.(iil==1_${ik}$)) ) & then m = m+1 w( m ) = r2 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = -sn z( 2_${ik}$, m ) = cs ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif if( alleig.or.(valeig.and.(r1>wl).and.(r1<=wu)).or.(indeig.and.(iiu==2_${ik}$)) ) & then m = m+1 w( m ) = r1 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = cs z( 2_${ik}$, m ) = sn ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif else ! continue with general n indgrs = 1_${ik}$ inderr = 2_${ik}$*n + 1_${ik}$ indgp = 3_${ik}$*n + 1_${ik}$ indd = 4_${ik}$*n + 1_${ik}$ inde2 = 5_${ik}$*n + 1_${ik}$ indwrk = 6_${ik}$*n + 1_${ik}$ iinspl = 1_${ik}$ iindbl = n + 1_${ik}$ iindw = 2_${ik}$*n + 1_${ik}$ iindwk = 3_${ik}$*n + 1_${ik}$ ! scale matrix to allowable range, if necessary. ! the allowable range is related to the pivmin parameter; see the ! comments in stdlib${ii}$_${ri}$larrd. the preference for scaling small values ! up is heuristic; we expect users' matrices not to be close to the ! rmax threshold. scale = one tnrm = stdlib${ii}$_${ri}$lanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then scale = rmax / tnrm end if if( scale/=one ) then call stdlib${ii}$_${ri}$scal( n, scale, d, 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-1, scale, e, 1_${ik}$ ) tnrm = tnrm*scale if( valeig ) then ! if eigenvalues in interval have to be found, ! scale (wl, wu] accordingly wl = wl*scale wu = wu*scale endif end if ! compute the desired eigenvalues of the tridiagonal after splitting ! into smaller subblocks if the corresponding off-diagonal elements ! are small ! thresh is the splitting parameter for stdlib${ii}$_${ri}$larre ! a negative thresh forces the old splitting criterion based on the ! size of the off-diagonal. a positive thresh switches to splitting ! which preserves relative accuracy. if( tryrac ) then ! test whether the matrix warrants the more expensive relative approach. call stdlib${ii}$_${ri}$larrr( n, d, e, iinfo ) else ! the user does not care about relative accurately eigenvalues iinfo = -1_${ik}$ endif ! set the splitting criterion if (iinfo==0_${ik}$) then thresh = eps else thresh = -eps ! relative accuracy is desired but t does not guarantee it tryrac = .false. endif if( tryrac ) then ! copy original diagonal, needed to guarantee relative accuracy call stdlib${ii}$_${ri}$copy(n,d,1_${ik}$,work(indd),1_${ik}$) endif ! store the squares of the offdiagonal values of t do j = 1, n-1 work( inde2+j-1 ) = e(j)**2_${ik}$ end do ! set the tolerance parameters for bisection if( .not.wantz ) then ! stdlib${ii}$_${ri}$larre computes the eigenvalues to full precision. rtol1 = four * eps rtol2 = four * eps else ! stdlib${ii}$_${ri}$larre computes the eigenvalues to less than full precision. ! stdlib${ii}$_${ri}$larrv will refine the eigenvalue approximations, and we can ! need less accurate initial bisection in stdlib${ii}$_${ri}$larre. ! note: these settings do only affect the subset case and stdlib${ii}$_${ri}$larre rtol1 = sqrt(eps) rtol2 = max( sqrt(eps)*5.0e-3_${rk}$, four * eps ) endif call stdlib${ii}$_${ri}$larre( range, n, wl, wu, iil, iiu, d, e,work(inde2), rtol1, rtol2, & thresh, nsplit,iwork( iinspl ), m, w, work( inderr ),work( indgp ), iwork( iindbl ),& iwork( iindw ), work( indgrs ), pivmin,work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 10_${ik}$ + abs( iinfo ) return end if ! note that if range /= 'v', stdlib${ii}$_${ri}$larre computes bounds on the desired ! part of the spectrum. all desired eigenvalues are contained in ! (wl,wu] if( wantz ) then ! compute the desired eigenvectors corresponding to the computed ! eigenvalues call stdlib${ii}$_${ri}$larrv( n, wl, wu, d, e,pivmin, iwork( iinspl ), m,1_${ik}$, m, minrgp, & rtol1, rtol2,w, work( inderr ), work( indgp ), iwork( iindbl ),iwork( iindw ), & work( indgrs ), z, ldz,isuppz, work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 20_${ik}$ + abs( iinfo ) return end if else ! stdlib${ii}$_${ri}$larre computes eigenvalues of the (shifted) root representation ! stdlib${ii}$_${ri}$larrv returns the eigenvalues of the unshifted matrix. ! however, if the eigenvectors are not desired by the user, we need ! to apply the corresponding shifts from stdlib${ii}$_${ri}$larre to obtain the ! eigenvalues of the original matrix. do j = 1, m itmp = iwork( iindbl+j-1 ) w( j ) = w( j ) + e( iwork( iinspl+itmp-1 ) ) end do end if if ( tryrac ) then ! refine computed eigenvalues so that they are relatively accurate ! with respect to the original matrix t. ibegin = 1_${ik}$ wbegin = 1_${ik}$ loop_39: do jblk = 1, iwork( iindbl+m-1 ) iend = iwork( iinspl+jblk-1 ) in = iend - ibegin + 1_${ik}$ wend = wbegin - 1_${ik}$ ! check if any eigenvalues have to be refined in this block 36 continue if( wend1_${ik}$ .or. n==2_${ik}$ ) then if( .not. wantz ) then call stdlib${ii}$_${ri}$lasrt( 'I', m, w, iinfo ) if( iinfo/=0_${ik}$ ) then info = 3_${ik}$ return end if else do j = 1, m - 1 i = 0_${ik}$ tmp = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. wu<=wl ) then info = -7_${ik}$ else if( indeig .and. ( iil<1_${ik}$ .or. iil>n ) ) then info = -8_${ik}$ else if( indeig .and. ( iiun ) ) then info = -9_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz(1_${ik}$) = 1_${ik}$ isuppz(2_${ik}$) = 1_${ik}$ end if return end if if( n==2_${ik}$ ) then if( .not.wantz ) then call stdlib${ii}$_slae2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2 ) else if( wantz.and.(.not.zquery) ) then call stdlib${ii}$_slaev2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2, cs, sn ) end if if( alleig.or.(valeig.and.(r2>wl).and.(r2<=wu)).or.(indeig.and.(iil==1_${ik}$)) ) & then m = m+1 w( m ) = r2 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = -sn z( 2_${ik}$, m ) = cs ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif if( alleig.or.(valeig.and.(r1>wl).and.(r1<=wu)).or.(indeig.and.(iiu==2_${ik}$)) ) & then m = m+1 w( m ) = r1 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = cs z( 2_${ik}$, m ) = sn ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif else ! continue with general n indgrs = 1_${ik}$ inderr = 2_${ik}$*n + 1_${ik}$ indgp = 3_${ik}$*n + 1_${ik}$ indd = 4_${ik}$*n + 1_${ik}$ inde2 = 5_${ik}$*n + 1_${ik}$ indwrk = 6_${ik}$*n + 1_${ik}$ iinspl = 1_${ik}$ iindbl = n + 1_${ik}$ iindw = 2_${ik}$*n + 1_${ik}$ iindwk = 3_${ik}$*n + 1_${ik}$ ! scale matrix to allowable range, if necessary. ! the allowable range is related to the pivmin parameter; see the ! comments in stdlib${ii}$_slarrd. the preference for scaling small values ! up is heuristic; we expect users' matrices not to be close to the ! rmax threshold. scale = one tnrm = stdlib${ii}$_slanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then scale = rmax / tnrm end if if( scale/=one ) then call stdlib${ii}$_sscal( n, scale, d, 1_${ik}$ ) call stdlib${ii}$_sscal( n-1, scale, e, 1_${ik}$ ) tnrm = tnrm*scale if( valeig ) then ! if eigenvalues in interval have to be found, ! scale (wl, wu] accordingly wl = wl*scale wu = wu*scale endif end if ! compute the desired eigenvalues of the tridiagonal after splitting ! into smaller subblocks if the corresponding off-diagonal elements ! are small ! thresh is the splitting parameter for stdlib${ii}$_slarre ! a negative thresh forces the old splitting criterion based on the ! size of the off-diagonal. a positive thresh switches to splitting ! which preserves relative accuracy. if( tryrac ) then ! test whether the matrix warrants the more expensive relative approach. call stdlib${ii}$_slarrr( n, d, e, iinfo ) else ! the user does not care about relative accurately eigenvalues iinfo = -1_${ik}$ endif ! set the splitting criterion if (iinfo==0_${ik}$) then thresh = eps else thresh = -eps ! relative accuracy is desired but t does not guarantee it tryrac = .false. endif if( tryrac ) then ! copy original diagonal, needed to guarantee relative accuracy call stdlib${ii}$_scopy(n,d,1_${ik}$,work(indd),1_${ik}$) endif ! store the squares of the offdiagonal values of t do j = 1, n-1 work( inde2+j-1 ) = e(j)**2_${ik}$ end do ! set the tolerance parameters for bisection if( .not.wantz ) then ! stdlib${ii}$_slarre computes the eigenvalues to full precision. rtol1 = four * eps rtol2 = four * eps else ! stdlib${ii}$_slarre computes the eigenvalues to less than full precision. ! stdlib${ii}$_clarrv will refine the eigenvalue approximations, and we only ! need less accurate initial bisection in stdlib${ii}$_slarre. ! note: these settings do only affect the subset case and stdlib${ii}$_slarre rtol1 = max( sqrt(eps)*5.0e-2_sp, four * eps ) rtol2 = max( sqrt(eps)*5.0e-3_sp, four * eps ) endif call stdlib${ii}$_slarre( range, n, wl, wu, iil, iiu, d, e,work(inde2), rtol1, rtol2, & thresh, nsplit,iwork( iinspl ), m, w, work( inderr ),work( indgp ), iwork( iindbl ),& iwork( iindw ), work( indgrs ), pivmin,work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 10_${ik}$ + abs( iinfo ) return end if ! note that if range /= 'v', stdlib${ii}$_slarre computes bounds on the desired ! part of the spectrum. all desired eigenvalues are contained in ! (wl,wu] if( wantz ) then ! compute the desired eigenvectors corresponding to the computed ! eigenvalues call stdlib${ii}$_clarrv( n, wl, wu, d, e,pivmin, iwork( iinspl ), m,1_${ik}$, m, minrgp, & rtol1, rtol2,w, work( inderr ), work( indgp ), iwork( iindbl ),iwork( iindw ), & work( indgrs ), z, ldz,isuppz, work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 20_${ik}$ + abs( iinfo ) return end if else ! stdlib${ii}$_slarre computes eigenvalues of the (shifted) root representation ! stdlib${ii}$_clarrv returns the eigenvalues of the unshifted matrix. ! however, if the eigenvectors are not desired by the user, we need ! to apply the corresponding shifts from stdlib${ii}$_slarre to obtain the ! eigenvalues of the original matrix. do j = 1, m itmp = iwork( iindbl+j-1 ) w( j ) = w( j ) + e( iwork( iinspl+itmp-1 ) ) end do end if if ( tryrac ) then ! refine computed eigenvalues so that they are relatively accurate ! with respect to the original matrix t. ibegin = 1_${ik}$ wbegin = 1_${ik}$ loop_39: do jblk = 1, iwork( iindbl+m-1 ) iend = iwork( iinspl+jblk-1 ) in = iend - ibegin + 1_${ik}$ wend = wbegin - 1_${ik}$ ! check if any eigenvalues have to be refined in this block 36 continue if( wend1_${ik}$ .or. n==2_${ik}$ ) then if( .not. wantz ) then call stdlib${ii}$_slasrt( 'I', m, w, iinfo ) if( iinfo/=0_${ik}$ ) then info = 3_${ik}$ return end if else do j = 1, m - 1 i = 0_${ik}$ tmp = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. wu<=wl ) then info = -7_${ik}$ else if( indeig .and. ( iil<1_${ik}$ .or. iil>n ) ) then info = -8_${ik}$ else if( indeig .and. ( iiun ) ) then info = -9_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz(1_${ik}$) = 1_${ik}$ isuppz(2_${ik}$) = 1_${ik}$ end if return end if if( n==2_${ik}$ ) then if( .not.wantz ) then call stdlib${ii}$_dlae2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2 ) else if( wantz.and.(.not.zquery) ) then call stdlib${ii}$_dlaev2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2, cs, sn ) end if if( alleig.or.(valeig.and.(r2>wl).and.(r2<=wu)).or.(indeig.and.(iil==1_${ik}$)) ) & then m = m+1 w( m ) = r2 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = -sn z( 2_${ik}$, m ) = cs ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif if( alleig.or.(valeig.and.(r1>wl).and.(r1<=wu)).or.(indeig.and.(iiu==2_${ik}$)) ) & then m = m+1 w( m ) = r1 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = cs z( 2_${ik}$, m ) = sn ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif else ! continue with general n indgrs = 1_${ik}$ inderr = 2_${ik}$*n + 1_${ik}$ indgp = 3_${ik}$*n + 1_${ik}$ indd = 4_${ik}$*n + 1_${ik}$ inde2 = 5_${ik}$*n + 1_${ik}$ indwrk = 6_${ik}$*n + 1_${ik}$ iinspl = 1_${ik}$ iindbl = n + 1_${ik}$ iindw = 2_${ik}$*n + 1_${ik}$ iindwk = 3_${ik}$*n + 1_${ik}$ ! scale matrix to allowable range, if necessary. ! the allowable range is related to the pivmin parameter; see the ! comments in stdlib${ii}$_dlarrd. the preference for scaling small values ! up is heuristic; we expect users' matrices not to be close to the ! rmax threshold. scale = one tnrm = stdlib${ii}$_dlanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then scale = rmax / tnrm end if if( scale/=one ) then call stdlib${ii}$_dscal( n, scale, d, 1_${ik}$ ) call stdlib${ii}$_dscal( n-1, scale, e, 1_${ik}$ ) tnrm = tnrm*scale if( valeig ) then ! if eigenvalues in interval have to be found, ! scale (wl, wu] accordingly wl = wl*scale wu = wu*scale endif end if ! compute the desired eigenvalues of the tridiagonal after splitting ! into smaller subblocks if the corresponding off-diagonal elements ! are small ! thresh is the splitting parameter for stdlib${ii}$_dlarre ! a negative thresh forces the old splitting criterion based on the ! size of the off-diagonal. a positive thresh switches to splitting ! which preserves relative accuracy. if( tryrac ) then ! test whether the matrix warrants the more expensive relative approach. call stdlib${ii}$_dlarrr( n, d, e, iinfo ) else ! the user does not care about relative accurately eigenvalues iinfo = -1_${ik}$ endif ! set the splitting criterion if (iinfo==0_${ik}$) then thresh = eps else thresh = -eps ! relative accuracy is desired but t does not guarantee it tryrac = .false. endif if( tryrac ) then ! copy original diagonal, needed to guarantee relative accuracy call stdlib${ii}$_dcopy(n,d,1_${ik}$,work(indd),1_${ik}$) endif ! store the squares of the offdiagonal values of t do j = 1, n-1 work( inde2+j-1 ) = e(j)**2_${ik}$ end do ! set the tolerance parameters for bisection if( .not.wantz ) then ! stdlib${ii}$_dlarre computes the eigenvalues to full precision. rtol1 = four * eps rtol2 = four * eps else ! stdlib${ii}$_dlarre computes the eigenvalues to less than full precision. ! stdlib${ii}$_zlarrv will refine the eigenvalue approximations, and we only ! need less accurate initial bisection in stdlib${ii}$_dlarre. ! note: these settings do only affect the subset case and stdlib${ii}$_dlarre rtol1 = sqrt(eps) rtol2 = max( sqrt(eps)*5.0e-3_dp, four * eps ) endif call stdlib${ii}$_dlarre( range, n, wl, wu, iil, iiu, d, e,work(inde2), rtol1, rtol2, & thresh, nsplit,iwork( iinspl ), m, w, work( inderr ),work( indgp ), iwork( iindbl ),& iwork( iindw ), work( indgrs ), pivmin,work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 10_${ik}$ + abs( iinfo ) return end if ! note that if range /= 'v', stdlib${ii}$_dlarre computes bounds on the desired ! part of the spectrum. all desired eigenvalues are contained in ! (wl,wu] if( wantz ) then ! compute the desired eigenvectors corresponding to the computed ! eigenvalues call stdlib${ii}$_zlarrv( n, wl, wu, d, e,pivmin, iwork( iinspl ), m,1_${ik}$, m, minrgp, & rtol1, rtol2,w, work( inderr ), work( indgp ), iwork( iindbl ),iwork( iindw ), & work( indgrs ), z, ldz,isuppz, work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 20_${ik}$ + abs( iinfo ) return end if else ! stdlib${ii}$_dlarre computes eigenvalues of the (shifted) root representation ! stdlib${ii}$_zlarrv returns the eigenvalues of the unshifted matrix. ! however, if the eigenvectors are not desired by the user, we need ! to apply the corresponding shifts from stdlib${ii}$_dlarre to obtain the ! eigenvalues of the original matrix. do j = 1, m itmp = iwork( iindbl+j-1 ) w( j ) = w( j ) + e( iwork( iinspl+itmp-1 ) ) end do end if if ( tryrac ) then ! refine computed eigenvalues so that they are relatively accurate ! with respect to the original matrix t. ibegin = 1_${ik}$ wbegin = 1_${ik}$ loop_39: do jblk = 1, iwork( iindbl+m-1 ) iend = iwork( iinspl+jblk-1 ) in = iend - ibegin + 1_${ik}$ wend = wbegin - 1_${ik}$ ! check if any eigenvalues have to be refined in this block 36 continue if( wend1_${ik}$ .or. n==2_${ik}$ ) then if( .not. wantz ) then call stdlib${ii}$_dlasrt( 'I', m, w, iinfo ) if( iinfo/=0_${ik}$ ) then info = 3_${ik}$ return end if else do j = 1, m - 1 i = 0_${ik}$ tmp = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. wu<=wl ) then info = -7_${ik}$ else if( indeig .and. ( iil<1_${ik}$ .or. iil>n ) ) then info = -8_${ik}$ else if( indeig .and. ( iiun ) ) then info = -9_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz=d( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = d( 1_${ik}$ ) end if end if if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz(1_${ik}$) = 1_${ik}$ isuppz(2_${ik}$) = 1_${ik}$ end if return end if if( n==2_${ik}$ ) then if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$lae2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2 ) else if( wantz.and.(.not.zquery) ) then call stdlib${ii}$_${c2ri(ci)}$laev2( d(1_${ik}$), e(1_${ik}$), d(2_${ik}$), r1, r2, cs, sn ) end if if( alleig.or.(valeig.and.(r2>wl).and.(r2<=wu)).or.(indeig.and.(iil==1_${ik}$)) ) & then m = m+1 w( m ) = r2 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = -sn z( 2_${ik}$, m ) = cs ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif if( alleig.or.(valeig.and.(r1>wl).and.(r1<=wu)).or.(indeig.and.(iiu==2_${ik}$)) ) & then m = m+1 w( m ) = r1 if( wantz.and.(.not.zquery) ) then z( 1_${ik}$, m ) = cs z( 2_${ik}$, m ) = sn ! note: at most one of sn and cs can be zero. if (sn/=zero) then if (cs/=zero) then isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ else isuppz(2_${ik}$*m-1) = 1_${ik}$ isuppz(2_${ik}$*m) = 1_${ik}$ end if else isuppz(2_${ik}$*m-1) = 2_${ik}$ isuppz(2_${ik}$*m) = 2_${ik}$ end if endif endif else ! continue with general n indgrs = 1_${ik}$ inderr = 2_${ik}$*n + 1_${ik}$ indgp = 3_${ik}$*n + 1_${ik}$ indd = 4_${ik}$*n + 1_${ik}$ inde2 = 5_${ik}$*n + 1_${ik}$ indwrk = 6_${ik}$*n + 1_${ik}$ iinspl = 1_${ik}$ iindbl = n + 1_${ik}$ iindw = 2_${ik}$*n + 1_${ik}$ iindwk = 3_${ik}$*n + 1_${ik}$ ! scale matrix to allowable range, if necessary. ! the allowable range is related to the pivmin parameter; see the ! comments in stdlib${ii}$_${c2ri(ci)}$larrd. the preference for scaling small values ! up is heuristic; we expect users' matrices not to be close to the ! rmax threshold. scale = one tnrm = stdlib${ii}$_${c2ri(ci)}$lanst( 'M', n, d, e ) if( tnrm>zero .and. tnrmrmax ) then scale = rmax / tnrm end if if( scale/=one ) then call stdlib${ii}$_${c2ri(ci)}$scal( n, scale, d, 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$scal( n-1, scale, e, 1_${ik}$ ) tnrm = tnrm*scale if( valeig ) then ! if eigenvalues in interval have to be found, ! scale (wl, wu] accordingly wl = wl*scale wu = wu*scale endif end if ! compute the desired eigenvalues of the tridiagonal after splitting ! into smaller subblocks if the corresponding off-diagonal elements ! are small ! thresh is the splitting parameter for stdlib${ii}$_${c2ri(ci)}$larre ! a negative thresh forces the old splitting criterion based on the ! size of the off-diagonal. a positive thresh switches to splitting ! which preserves relative accuracy. if( tryrac ) then ! test whether the matrix warrants the more expensive relative approach. call stdlib${ii}$_${c2ri(ci)}$larrr( n, d, e, iinfo ) else ! the user does not care about relative accurately eigenvalues iinfo = -1_${ik}$ endif ! set the splitting criterion if (iinfo==0_${ik}$) then thresh = eps else thresh = -eps ! relative accuracy is desired but t does not guarantee it tryrac = .false. endif if( tryrac ) then ! copy original diagonal, needed to guarantee relative accuracy call stdlib${ii}$_${c2ri(ci)}$copy(n,d,1_${ik}$,work(indd),1_${ik}$) endif ! store the squares of the offdiagonal values of t do j = 1, n-1 work( inde2+j-1 ) = e(j)**2_${ik}$ end do ! set the tolerance parameters for bisection if( .not.wantz ) then ! stdlib${ii}$_${c2ri(ci)}$larre computes the eigenvalues to full precision. rtol1 = four * eps rtol2 = four * eps else ! stdlib${ii}$_${c2ri(ci)}$larre computes the eigenvalues to less than full precision. ! stdlib${ii}$_${ci}$larrv will refine the eigenvalue approximations, and we only ! need less accurate initial bisection in stdlib${ii}$_${c2ri(ci)}$larre. ! note: these settings do only affect the subset case and stdlib${ii}$_${c2ri(ci)}$larre rtol1 = sqrt(eps) rtol2 = max( sqrt(eps)*5.0e-3_${ck}$, four * eps ) endif call stdlib${ii}$_${c2ri(ci)}$larre( range, n, wl, wu, iil, iiu, d, e,work(inde2), rtol1, rtol2, & thresh, nsplit,iwork( iinspl ), m, w, work( inderr ),work( indgp ), iwork( iindbl ),& iwork( iindw ), work( indgrs ), pivmin,work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 10_${ik}$ + abs( iinfo ) return end if ! note that if range /= 'v', stdlib${ii}$_${c2ri(ci)}$larre computes bounds on the desired ! part of the spectrum. all desired eigenvalues are contained in ! (wl,wu] if( wantz ) then ! compute the desired eigenvectors corresponding to the computed ! eigenvalues call stdlib${ii}$_${ci}$larrv( n, wl, wu, d, e,pivmin, iwork( iinspl ), m,1_${ik}$, m, minrgp, & rtol1, rtol2,w, work( inderr ), work( indgp ), iwork( iindbl ),iwork( iindw ), & work( indgrs ), z, ldz,isuppz, work( indwrk ), iwork( iindwk ), iinfo ) if( iinfo/=0_${ik}$ ) then info = 20_${ik}$ + abs( iinfo ) return end if else ! stdlib${ii}$_${c2ri(ci)}$larre computes eigenvalues of the (shifted) root representation ! stdlib${ii}$_${ci}$larrv returns the eigenvalues of the unshifted matrix. ! however, if the eigenvectors are not desired by the user, we need ! to apply the corresponding shifts from stdlib${ii}$_${c2ri(ci)}$larre to obtain the ! eigenvalues of the original matrix. do j = 1, m itmp = iwork( iindbl+j-1 ) w( j ) = w( j ) + e( iwork( iinspl+itmp-1 ) ) end do end if if ( tryrac ) then ! refine computed eigenvalues so that they are relatively accurate ! with respect to the original matrix t. ibegin = 1_${ik}$ wbegin = 1_${ik}$ loop_39: do jblk = 1, iwork( iindbl+m-1 ) iend = iwork( iinspl+jblk-1 ) in = iend - ibegin + 1_${ik}$ wend = wbegin - 1_${ik}$ ! check if any eigenvalues have to be refined in this block 36 continue if( wend1_${ik}$ .or. n==2_${ik}$ ) then if( .not. wantz ) then call stdlib${ii}$_${c2ri(ci)}$lasrt( 'I', m, w, iinfo ) if( iinfo/=0_${ik}$ ) then info = 3_${ik}$ return end if else do j = 1, m - 1 i = 0_${ik}$ tmp = w( j ) do jj = j + 1, m if( w( jj )0_${ik}$ .and. ldzn )go to 160 if( l1>1_${ik}$ )e( l1-1 ) = zero if( l1<=nm1 ) then do m = l1, nm1 tst = abs( e( m ) ) if( tst==zero )go to 30 if( tst<=( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+1 ) ) ) )*eps ) then e( m ) = zero go to 30 end if end do end if m = n 30 continue l = l1 lsv = l lend = m lendsv = lend l1 = m + 1_${ik}$ if( lend==l )go to 10 ! scale submatrix in rows and columns l to lend anorm = stdlib${ii}$_slanst( 'M', lend-l+1, d( l ), e( l ) ) iscale = 0_${ik}$ if( anorm==zero )go to 10 if( anorm>ssfmax ) then iscale = 1_${ik}$ call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l+1, 1_${ik}$, d( l ), n,info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l, 1_${ik}$, e( l ), n,info ) else if( anorml ) then ! ql iteration ! look for small subdiagonal element. 40 continue if( l/=lend ) then lendm1 = lend - 1_${ik}$ do m = l, lendm1 tst = abs( e( m ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+safmin )go to 60 end do end if m = lend 60 continue if( m0_${ik}$ ) then call stdlib${ii}$_slaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s ) work( l ) = c work( n-1+l ) = s call stdlib${ii}$_slasr( 'R', 'V', 'B', n, 2_${ik}$, work( l ),work( n-1+l ), z( 1_${ik}$, l ), & ldz ) else call stdlib${ii}$_slae2( d( l ), e( l ), d( l+1 ), rt1, rt2 ) end if d( l ) = rt1 d( l+1 ) = rt2 e( l ) = zero l = l + 2_${ik}$ if( l<=lend )go to 40 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l+1 )-p ) / ( two*e( l ) ) r = stdlib${ii}$_slapy2( g, one ) g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop mm1 = m - 1_${ik}$ do i = mm1, l, -1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_slartg( g, f, c, s, r ) if( i/=m-1 )e( i+1 ) = r g = d( i+1 ) - p r = ( d( i )-g )*s + two*c*b p = s*r d( i+1 ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = -s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = m - l + 1_${ik}$ call stdlib${ii}$_slasr( 'R', 'V', 'B', n, mm, work( l ), work( n-1+l ),z( 1_${ik}$, l ), ldz & ) end if d( l ) = d( l ) - p e( l ) = g go to 40 ! eigenvalue found. 80 continue d( l ) = p l = l + 1_${ik}$ if( l<=lend )go to 40 go to 140 else ! qr iteration ! look for small superdiagonal element. 90 continue if( l/=lend ) then lendp1 = lend + 1_${ik}$ do m = l, lendp1, -1 tst = abs( e( m-1 ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+safmin )go to 110 end do end if m = lend 110 continue if( m>lend )e( m-1 ) = zero p = d( l ) if( m==l )go to 130 ! if remaining matrix is 2-by-2, use stdlib_slae2 or stdlib${ii}$_slaev2 ! to compute its eigensystem. if( m==l-1 ) then if( icompz>0_${ik}$ ) then call stdlib${ii}$_slaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s ) work( m ) = c work( n-1+m ) = s call stdlib${ii}$_slasr( 'R', 'V', 'F', n, 2_${ik}$, work( m ),work( n-1+m ), z( 1_${ik}$, l-1 ), & ldz ) else call stdlib${ii}$_slae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 ) end if d( l-1 ) = rt1 d( l ) = rt2 e( l-1 ) = zero l = l - 2_${ik}$ if( l>=lend )go to 90 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l-1 )-p ) / ( two*e( l-1 ) ) r = stdlib${ii}$_slapy2( g, one ) g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop lm1 = l - 1_${ik}$ do i = m, lm1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_slartg( g, f, c, s, r ) if( i/=m )e( i-1 ) = r g = d( i ) - p r = ( d( i+1 )-g )*s + two*c*b p = s*r d( i ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = l - m + 1_${ik}$ call stdlib${ii}$_slasr( 'R', 'V', 'F', n, mm, work( m ), work( n-1+m ),z( 1_${ik}$, m ), ldz & ) end if d( l ) = d( l ) - p e( lm1 ) = g go to 90 ! eigenvalue found. 130 continue d( l ) = p l = l - 1_${ik}$ if( l>=lend )go to 90 go to 140 end if ! undo scaling if necessary 140 continue if( iscale==1_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) else if( iscale==2_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) end if ! check for no convergence to an eigenvalue after a total ! of n*maxit iterations. if( jtot0_${ik}$ .and. ldzn )go to 160 if( l1>1_${ik}$ )e( l1-1 ) = zero if( l1<=nm1 ) then do m = l1, nm1 tst = abs( e( m ) ) if( tst==zero )go to 30 if( tst<=( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+1 ) ) ) )*eps ) then e( m ) = zero go to 30 end if end do end if m = n 30 continue l = l1 lsv = l lend = m lendsv = lend l1 = m + 1_${ik}$ if( lend==l )go to 10 ! scale submatrix in rows and columns l to lend anorm = stdlib${ii}$_dlanst( 'M', lend-l+1, d( l ), e( l ) ) iscale = 0_${ik}$ if( anorm==zero )go to 10 if( anorm>ssfmax ) then iscale = 1_${ik}$ call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l+1, 1_${ik}$, d( l ), n,info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l, 1_${ik}$, e( l ), n,info ) else if( anorml ) then ! ql iteration ! look for small subdiagonal element. 40 continue if( l/=lend ) then lendm1 = lend - 1_${ik}$ do m = l, lendm1 tst = abs( e( m ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+safmin )go to 60 end do end if m = lend 60 continue if( m0_${ik}$ ) then call stdlib${ii}$_dlaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s ) work( l ) = c work( n-1+l ) = s call stdlib${ii}$_dlasr( 'R', 'V', 'B', n, 2_${ik}$, work( l ),work( n-1+l ), z( 1_${ik}$, l ), & ldz ) else call stdlib${ii}$_dlae2( d( l ), e( l ), d( l+1 ), rt1, rt2 ) end if d( l ) = rt1 d( l+1 ) = rt2 e( l ) = zero l = l + 2_${ik}$ if( l<=lend )go to 40 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l+1 )-p ) / ( two*e( l ) ) r = stdlib${ii}$_dlapy2( g, one ) g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop mm1 = m - 1_${ik}$ do i = mm1, l, -1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_dlartg( g, f, c, s, r ) if( i/=m-1 )e( i+1 ) = r g = d( i+1 ) - p r = ( d( i )-g )*s + two*c*b p = s*r d( i+1 ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = -s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = m - l + 1_${ik}$ call stdlib${ii}$_dlasr( 'R', 'V', 'B', n, mm, work( l ), work( n-1+l ),z( 1_${ik}$, l ), ldz & ) end if d( l ) = d( l ) - p e( l ) = g go to 40 ! eigenvalue found. 80 continue d( l ) = p l = l + 1_${ik}$ if( l<=lend )go to 40 go to 140 else ! qr iteration ! look for small superdiagonal element. 90 continue if( l/=lend ) then lendp1 = lend + 1_${ik}$ do m = l, lendp1, -1 tst = abs( e( m-1 ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+safmin )go to 110 end do end if m = lend 110 continue if( m>lend )e( m-1 ) = zero p = d( l ) if( m==l )go to 130 ! if remaining matrix is 2-by-2, use stdlib_dlae2 or stdlib${ii}$_slaev2 ! to compute its eigensystem. if( m==l-1 ) then if( icompz>0_${ik}$ ) then call stdlib${ii}$_dlaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s ) work( m ) = c work( n-1+m ) = s call stdlib${ii}$_dlasr( 'R', 'V', 'F', n, 2_${ik}$, work( m ),work( n-1+m ), z( 1_${ik}$, l-1 ), & ldz ) else call stdlib${ii}$_dlae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 ) end if d( l-1 ) = rt1 d( l ) = rt2 e( l-1 ) = zero l = l - 2_${ik}$ if( l>=lend )go to 90 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l-1 )-p ) / ( two*e( l-1 ) ) r = stdlib${ii}$_dlapy2( g, one ) g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop lm1 = l - 1_${ik}$ do i = m, lm1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_dlartg( g, f, c, s, r ) if( i/=m )e( i-1 ) = r g = d( i ) - p r = ( d( i+1 )-g )*s + two*c*b p = s*r d( i ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = l - m + 1_${ik}$ call stdlib${ii}$_dlasr( 'R', 'V', 'F', n, mm, work( m ), work( n-1+m ),z( 1_${ik}$, m ), ldz & ) end if d( l ) = d( l ) - p e( lm1 ) = g go to 90 ! eigenvalue found. 130 continue d( l ) = p l = l - 1_${ik}$ if( l>=lend )go to 90 go to 140 end if ! undo scaling if necessary 140 continue if( iscale==1_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) else if( iscale==2_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) end if ! check for no convergence to an eigenvalue after a total ! of n*maxit iterations. if( jtot0_${ik}$ .and. ldzn )go to 160 if( l1>1_${ik}$ )e( l1-1 ) = zero if( l1<=nm1 ) then do m = l1, nm1 tst = abs( e( m ) ) if( tst==zero )go to 30 if( tst<=( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+1 ) ) ) )*eps ) then e( m ) = zero go to 30 end if end do end if m = n 30 continue l = l1 lsv = l lend = m lendsv = lend l1 = m + 1_${ik}$ if( lend==l )go to 10 ! scale submatrix in rows and columns l to lend anorm = stdlib${ii}$_${ri}$lanst( 'M', lend-l+1, d( l ), e( l ) ) iscale = 0_${ik}$ if( anorm==zero )go to 10 if( anorm>ssfmax ) then iscale = 1_${ik}$ call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l+1, 1_${ik}$, d( l ), n,info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l, 1_${ik}$, e( l ), n,info ) else if( anorml ) then ! ql iteration ! look for small subdiagonal element. 40 continue if( l/=lend ) then lendm1 = lend - 1_${ik}$ do m = l, lendm1 tst = abs( e( m ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+safmin )go to 60 end do end if m = lend 60 continue if( m0_${ik}$ ) then call stdlib${ii}$_${ri}$laev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s ) work( l ) = c work( n-1+l ) = s call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'B', n, 2_${ik}$, work( l ),work( n-1+l ), z( 1_${ik}$, l ), & ldz ) else call stdlib${ii}$_${ri}$lae2( d( l ), e( l ), d( l+1 ), rt1, rt2 ) end if d( l ) = rt1 d( l+1 ) = rt2 e( l ) = zero l = l + 2_${ik}$ if( l<=lend )go to 40 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l+1 )-p ) / ( two*e( l ) ) r = stdlib${ii}$_${ri}$lapy2( g, one ) g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop mm1 = m - 1_${ik}$ do i = mm1, l, -1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_${ri}$lartg( g, f, c, s, r ) if( i/=m-1 )e( i+1 ) = r g = d( i+1 ) - p r = ( d( i )-g )*s + two*c*b p = s*r d( i+1 ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = -s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = m - l + 1_${ik}$ call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'B', n, mm, work( l ), work( n-1+l ),z( 1_${ik}$, l ), ldz & ) end if d( l ) = d( l ) - p e( l ) = g go to 40 ! eigenvalue found. 80 continue d( l ) = p l = l + 1_${ik}$ if( l<=lend )go to 40 go to 140 else ! qr iteration ! look for small superdiagonal element. 90 continue if( l/=lend ) then lendp1 = lend + 1_${ik}$ do m = l, lendp1, -1 tst = abs( e( m-1 ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+safmin )go to 110 end do end if m = lend 110 continue if( m>lend )e( m-1 ) = zero p = d( l ) if( m==l )go to 130 ! if remaining matrix is 2-by-2, use stdlib_${ri}$lae2 or stdlib${ii}$_dlaev2 ! to compute its eigensystem. if( m==l-1 ) then if( icompz>0_${ik}$ ) then call stdlib${ii}$_${ri}$laev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s ) work( m ) = c work( n-1+m ) = s call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'F', n, 2_${ik}$, work( m ),work( n-1+m ), z( 1_${ik}$, l-1 ), & ldz ) else call stdlib${ii}$_${ri}$lae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 ) end if d( l-1 ) = rt1 d( l ) = rt2 e( l-1 ) = zero l = l - 2_${ik}$ if( l>=lend )go to 90 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l-1 )-p ) / ( two*e( l-1 ) ) r = stdlib${ii}$_${ri}$lapy2( g, one ) g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop lm1 = l - 1_${ik}$ do i = m, lm1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_${ri}$lartg( g, f, c, s, r ) if( i/=m )e( i-1 ) = r g = d( i ) - p r = ( d( i+1 )-g )*s + two*c*b p = s*r d( i ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = l - m + 1_${ik}$ call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'F', n, mm, work( m ), work( n-1+m ),z( 1_${ik}$, m ), ldz & ) end if d( l ) = d( l ) - p e( lm1 ) = g go to 90 ! eigenvalue found. 130 continue d( l ) = p l = l - 1_${ik}$ if( l>=lend )go to 90 go to 140 end if ! undo scaling if necessary 140 continue if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) else if( iscale==2_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) end if ! check for no convergence to an eigenvalue after a total ! of n*maxit iterations. if( jtot0_${ik}$ .and. ldzn )go to 160 if( l1>1_${ik}$ )e( l1-1 ) = zero if( l1<=nm1 ) then do m = l1, nm1 tst = abs( e( m ) ) if( tst==zero )go to 30 if( tst<=( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+1 ) ) ) )*eps ) then e( m ) = zero go to 30 end if end do end if m = n 30 continue l = l1 lsv = l lend = m lendsv = lend l1 = m + 1_${ik}$ if( lend==l )go to 10 ! scale submatrix in rows and columns l to lend anorm = stdlib${ii}$_slanst( 'I', lend-l+1, d( l ), e( l ) ) iscale = 0_${ik}$ if( anorm==zero )go to 10 if( anorm>ssfmax ) then iscale = 1_${ik}$ call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l+1, 1_${ik}$, d( l ), n,info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l, 1_${ik}$, e( l ), n,info ) else if( anorml ) then ! ql iteration ! look for small subdiagonal element. 40 continue if( l/=lend ) then lendm1 = lend - 1_${ik}$ do m = l, lendm1 tst = abs( e( m ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+safmin )go to 60 end do end if m = lend 60 continue if( m0_${ik}$ ) then call stdlib${ii}$_slaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s ) work( l ) = c work( n-1+l ) = s call stdlib${ii}$_clasr( 'R', 'V', 'B', n, 2_${ik}$, work( l ),work( n-1+l ), z( 1_${ik}$, l ), & ldz ) else call stdlib${ii}$_slae2( d( l ), e( l ), d( l+1 ), rt1, rt2 ) end if d( l ) = rt1 d( l+1 ) = rt2 e( l ) = zero l = l + 2_${ik}$ if( l<=lend )go to 40 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l+1 )-p ) / ( two*e( l ) ) r = stdlib${ii}$_slapy2( g, one ) g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop mm1 = m - 1_${ik}$ do i = mm1, l, -1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_slartg( g, f, c, s, r ) if( i/=m-1 )e( i+1 ) = r g = d( i+1 ) - p r = ( d( i )-g )*s + two*c*b p = s*r d( i+1 ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = -s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = m - l + 1_${ik}$ call stdlib${ii}$_clasr( 'R', 'V', 'B', n, mm, work( l ), work( n-1+l ),z( 1_${ik}$, l ), ldz & ) end if d( l ) = d( l ) - p e( l ) = g go to 40 ! eigenvalue found. 80 continue d( l ) = p l = l + 1_${ik}$ if( l<=lend )go to 40 go to 140 else ! qr iteration ! look for small superdiagonal element. 90 continue if( l/=lend ) then lendp1 = lend + 1_${ik}$ do m = l, lendp1, -1 tst = abs( e( m-1 ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+safmin )go to 110 end do end if m = lend 110 continue if( m>lend )e( m-1 ) = zero p = d( l ) if( m==l )go to 130 ! if remaining matrix is 2-by-2, use stdlib_slae2 or stdlib${ii}$_slaev2 ! to compute its eigensystem. if( m==l-1 ) then if( icompz>0_${ik}$ ) then call stdlib${ii}$_slaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s ) work( m ) = c work( n-1+m ) = s call stdlib${ii}$_clasr( 'R', 'V', 'F', n, 2_${ik}$, work( m ),work( n-1+m ), z( 1_${ik}$, l-1 ), & ldz ) else call stdlib${ii}$_slae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 ) end if d( l-1 ) = rt1 d( l ) = rt2 e( l-1 ) = zero l = l - 2_${ik}$ if( l>=lend )go to 90 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l-1 )-p ) / ( two*e( l-1 ) ) r = stdlib${ii}$_slapy2( g, one ) g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop lm1 = l - 1_${ik}$ do i = m, lm1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_slartg( g, f, c, s, r ) if( i/=m )e( i-1 ) = r g = d( i ) - p r = ( d( i+1 )-g )*s + two*c*b p = s*r d( i ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = l - m + 1_${ik}$ call stdlib${ii}$_clasr( 'R', 'V', 'F', n, mm, work( m ), work( n-1+m ),z( 1_${ik}$, m ), ldz & ) end if d( l ) = d( l ) - p e( lm1 ) = g go to 90 ! eigenvalue found. 130 continue d( l ) = p l = l - 1_${ik}$ if( l>=lend )go to 90 go to 140 end if ! undo scaling if necessary 140 continue if( iscale==1_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) else if( iscale==2_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) end if ! check for no convergence to an eigenvalue after a total ! of n*maxit iterations. if( jtot==nmaxit ) then do i = 1, n - 1 if( e( i )/=zero )info = info + 1_${ik}$ end do return end if go to 10 ! order eigenvalues and eigenvectors. 160 continue if( icompz==0_${ik}$ ) then ! use quick sort call stdlib${ii}$_slasrt( 'I', n, d, info ) else ! use selection sort to minimize swaps of eigenvectors do ii = 2, n i = ii - 1_${ik}$ k = i p = d( i ) do j = ii, n if( d( j )

0_${ik}$ .and. ldzn )go to 160 if( l1>1_${ik}$ )e( l1-1 ) = zero if( l1<=nm1 ) then do m = l1, nm1 tst = abs( e( m ) ) if( tst==zero )go to 30 if( tst<=( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+1 ) ) ) )*eps ) then e( m ) = zero go to 30 end if end do end if m = n 30 continue l = l1 lsv = l lend = m lendsv = lend l1 = m + 1_${ik}$ if( lend==l )go to 10 ! scale submatrix in rows and columns l to lend anorm = stdlib${ii}$_dlanst( 'I', lend-l+1, d( l ), e( l ) ) iscale = 0_${ik}$ if( anorm==zero )go to 10 if( anorm>ssfmax ) then iscale = 1_${ik}$ call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l+1, 1_${ik}$, d( l ), n,info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l, 1_${ik}$, e( l ), n,info ) else if( anorml ) then ! ql iteration ! look for small subdiagonal element. 40 continue if( l/=lend ) then lendm1 = lend - 1_${ik}$ do m = l, lendm1 tst = abs( e( m ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+safmin )go to 60 end do end if m = lend 60 continue if( m0_${ik}$ ) then call stdlib${ii}$_dlaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s ) work( l ) = c work( n-1+l ) = s call stdlib${ii}$_zlasr( 'R', 'V', 'B', n, 2_${ik}$, work( l ),work( n-1+l ), z( 1_${ik}$, l ), & ldz ) else call stdlib${ii}$_dlae2( d( l ), e( l ), d( l+1 ), rt1, rt2 ) end if d( l ) = rt1 d( l+1 ) = rt2 e( l ) = zero l = l + 2_${ik}$ if( l<=lend )go to 40 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l+1 )-p ) / ( two*e( l ) ) r = stdlib${ii}$_dlapy2( g, one ) g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop mm1 = m - 1_${ik}$ do i = mm1, l, -1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_dlartg( g, f, c, s, r ) if( i/=m-1 )e( i+1 ) = r g = d( i+1 ) - p r = ( d( i )-g )*s + two*c*b p = s*r d( i+1 ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = -s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = m - l + 1_${ik}$ call stdlib${ii}$_zlasr( 'R', 'V', 'B', n, mm, work( l ), work( n-1+l ),z( 1_${ik}$, l ), ldz & ) end if d( l ) = d( l ) - p e( l ) = g go to 40 ! eigenvalue found. 80 continue d( l ) = p l = l + 1_${ik}$ if( l<=lend )go to 40 go to 140 else ! qr iteration ! look for small superdiagonal element. 90 continue if( l/=lend ) then lendp1 = lend + 1_${ik}$ do m = l, lendp1, -1 tst = abs( e( m-1 ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+safmin )go to 110 end do end if m = lend 110 continue if( m>lend )e( m-1 ) = zero p = d( l ) if( m==l )go to 130 ! if remaining matrix is 2-by-2, use stdlib_dlae2 or stdlib${ii}$_slaev2 ! to compute its eigensystem. if( m==l-1 ) then if( icompz>0_${ik}$ ) then call stdlib${ii}$_dlaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s ) work( m ) = c work( n-1+m ) = s call stdlib${ii}$_zlasr( 'R', 'V', 'F', n, 2_${ik}$, work( m ),work( n-1+m ), z( 1_${ik}$, l-1 ), & ldz ) else call stdlib${ii}$_dlae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 ) end if d( l-1 ) = rt1 d( l ) = rt2 e( l-1 ) = zero l = l - 2_${ik}$ if( l>=lend )go to 90 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l-1 )-p ) / ( two*e( l-1 ) ) r = stdlib${ii}$_dlapy2( g, one ) g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop lm1 = l - 1_${ik}$ do i = m, lm1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_dlartg( g, f, c, s, r ) if( i/=m )e( i-1 ) = r g = d( i ) - p r = ( d( i+1 )-g )*s + two*c*b p = s*r d( i ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = l - m + 1_${ik}$ call stdlib${ii}$_zlasr( 'R', 'V', 'F', n, mm, work( m ), work( n-1+m ),z( 1_${ik}$, m ), ldz & ) end if d( l ) = d( l ) - p e( lm1 ) = g go to 90 ! eigenvalue found. 130 continue d( l ) = p l = l - 1_${ik}$ if( l>=lend )go to 90 go to 140 end if ! undo scaling if necessary 140 continue if( iscale==1_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) else if( iscale==2_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) end if ! check for no convergence to an eigenvalue after a total ! of n*maxit iterations. if( jtot==nmaxit ) then do i = 1, n - 1 if( e( i )/=zero )info = info + 1_${ik}$ end do return end if go to 10 ! order eigenvalues and eigenvectors. 160 continue if( icompz==0_${ik}$ ) then ! use quick sort call stdlib${ii}$_dlasrt( 'I', n, d, info ) else ! use selection sort to minimize swaps of eigenvectors do ii = 2, n i = ii - 1_${ik}$ k = i p = d( i ) do j = ii, n if( d( j )

0_${ik}$ .and. ldzn )go to 160 if( l1>1_${ik}$ )e( l1-1 ) = zero if( l1<=nm1 ) then do m = l1, nm1 tst = abs( e( m ) ) if( tst==zero )go to 30 if( tst<=( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+1 ) ) ) )*eps ) then e( m ) = zero go to 30 end if end do end if m = n 30 continue l = l1 lsv = l lend = m lendsv = lend l1 = m + 1_${ik}$ if( lend==l )go to 10 ! scale submatrix in rows and columns l to lend anorm = stdlib${ii}$_${c2ri(ci)}$lanst( 'I', lend-l+1, d( l ), e( l ) ) iscale = 0_${ik}$ if( anorm==zero )go to 10 if( anorm>ssfmax ) then iscale = 1_${ik}$ call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l+1, 1_${ik}$, d( l ), n,info ) call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, anorm, ssfmax, lend-l, 1_${ik}$, e( l ), n,info ) else if( anorml ) then ! ql iteration ! look for small subdiagonal element. 40 continue if( l/=lend ) then lendm1 = lend - 1_${ik}$ do m = l, lendm1 tst = abs( e( m ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+safmin )go to 60 end do end if m = lend 60 continue if( m0_${ik}$ ) then call stdlib${ii}$_${c2ri(ci)}$laev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s ) work( l ) = c work( n-1+l ) = s call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'B', n, 2_${ik}$, work( l ),work( n-1+l ), z( 1_${ik}$, l ), & ldz ) else call stdlib${ii}$_${c2ri(ci)}$lae2( d( l ), e( l ), d( l+1 ), rt1, rt2 ) end if d( l ) = rt1 d( l+1 ) = rt2 e( l ) = zero l = l + 2_${ik}$ if( l<=lend )go to 40 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l+1 )-p ) / ( two*e( l ) ) r = stdlib${ii}$_${c2ri(ci)}$lapy2( g, one ) g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop mm1 = m - 1_${ik}$ do i = mm1, l, -1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_${c2ri(ci)}$lartg( g, f, c, s, r ) if( i/=m-1 )e( i+1 ) = r g = d( i+1 ) - p r = ( d( i )-g )*s + two*c*b p = s*r d( i+1 ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = -s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = m - l + 1_${ik}$ call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'B', n, mm, work( l ), work( n-1+l ),z( 1_${ik}$, l ), ldz & ) end if d( l ) = d( l ) - p e( l ) = g go to 40 ! eigenvalue found. 80 continue d( l ) = p l = l + 1_${ik}$ if( l<=lend )go to 40 go to 140 else ! qr iteration ! look for small superdiagonal element. 90 continue if( l/=lend ) then lendp1 = lend + 1_${ik}$ do m = l, lendp1, -1 tst = abs( e( m-1 ) )**2_${ik}$ if( tst<=( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+safmin )go to 110 end do end if m = lend 110 continue if( m>lend )e( m-1 ) = zero p = d( l ) if( m==l )go to 130 ! if remaining matrix is 2-by-2, use stdlib_${c2ri(ci)}$lae2 or stdlib${ii}$_dlaev2 ! to compute its eigensystem. if( m==l-1 ) then if( icompz>0_${ik}$ ) then call stdlib${ii}$_${c2ri(ci)}$laev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s ) work( m ) = c work( n-1+m ) = s call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'F', n, 2_${ik}$, work( m ),work( n-1+m ), z( 1_${ik}$, l-1 ), & ldz ) else call stdlib${ii}$_${c2ri(ci)}$lae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 ) end if d( l-1 ) = rt1 d( l ) = rt2 e( l-1 ) = zero l = l - 2_${ik}$ if( l>=lend )go to 90 go to 140 end if if( jtot==nmaxit )go to 140 jtot = jtot + 1_${ik}$ ! form shift. g = ( d( l-1 )-p ) / ( two*e( l-1 ) ) r = stdlib${ii}$_${c2ri(ci)}$lapy2( g, one ) g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) ) s = one c = one p = zero ! inner loop lm1 = l - 1_${ik}$ do i = m, lm1 f = s*e( i ) b = c*e( i ) call stdlib${ii}$_${c2ri(ci)}$lartg( g, f, c, s, r ) if( i/=m )e( i-1 ) = r g = d( i ) - p r = ( d( i+1 )-g )*s + two*c*b p = s*r d( i ) = g + p g = c*r - b ! if eigenvectors are desired, then save rotations. if( icompz>0_${ik}$ ) then work( i ) = c work( n-1+i ) = s end if end do ! if eigenvectors are desired, then apply saved rotations. if( icompz>0_${ik}$ ) then mm = l - m + 1_${ik}$ call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'F', n, mm, work( m ), work( n-1+m ),z( 1_${ik}$, m ), ldz & ) end if d( l ) = d( l ) - p e( lm1 ) = g go to 90 ! eigenvalue found. 130 continue d( l ) = p l = l - 1_${ik}$ if( l>=lend )go to 90 go to 140 end if ! undo scaling if necessary 140 continue if( iscale==1_${ik}$ ) then call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, ssfmax, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) else if( iscale==2_${ik}$ ) then call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv+1, 1_${ik}$,d( lsv ), n, info ) call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, ssfmin, anorm, lendsv-lsv, 1_${ik}$, e( lsv ),n, info ) end if ! check for no convergence to an eigenvalue after a total ! of n*maxit iterations. if( jtot==nmaxit ) then do i = 1, n - 1 if( e( i )/=zero )info = info + 1_${ik}$ end do return end if go to 10 ! order eigenvalues and eigenvectors. 160 continue if( icompz==0_${ik}$ ) then ! use quick sort call stdlib${ii}$_${c2ri(ci)}$lasrt( 'I', n, d, info ) else ! use selection sort to minimize swaps of eigenvectors do ii = 2, n i = ii - 1_${ik}$ k = i p = d( i ) do j = ii, n if( d( j )

=n .and. minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_sbdsqr mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'SGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) bdspac = 5_${ik}$*n ! compute space needed for stdlib${ii}$_sgeqrf call stdlib${ii}$_sgeqrf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sgeqrf = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_sorgqr call stdlib${ii}$_sorgqr( m, n, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgqr_n = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sorgqr( m, m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgqr_m = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_sgebrd call stdlib${ii}$_sgebrd( n, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sgebrd = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_sorgbr p call stdlib${ii}$_sorgbr( 'P', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_sorgbr q call stdlib${ii}$_sorgbr( 'Q', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') maxwrk = n + lwork_sgeqrf maxwrk = max( maxwrk, 3_${ik}$*n+lwork_sgebrd ) if( wntvo .or. wntvas )maxwrk = max( maxwrk, 3_${ik}$*n+lwork_sorgbr_p ) maxwrk = max( maxwrk, bdspac ) minwrk = max( 4_${ik}$*n, bdspac ) else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') wrkbl = n + lwork_sgeqrf wrkbl = max( wrkbl, n+lwork_sorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( n*n+wrkbl, n*n+m*n+n ) minwrk = max( 3_${ik}$*n+m, bdspac ) else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or ! 'a') wrkbl = n + lwork_sgeqrf wrkbl = max( wrkbl, n+lwork_sorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( n*n+wrkbl, n*n+m*n+n ) minwrk = max( 3_${ik}$*n+m, bdspac ) else if( wntus .and. wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') wrkbl = n + lwork_sgeqrf wrkbl = max( wrkbl, n+lwork_sorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n+m, bdspac ) else if( wntus .and. wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') wrkbl = n + lwork_sgeqrf wrkbl = max( wrkbl, n+lwork_sorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = max( 3_${ik}$*n+m, bdspac ) else if( wntus .and. wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' or ! 'a') wrkbl = n + lwork_sgeqrf wrkbl = max( wrkbl, n+lwork_sorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n+m, bdspac ) else if( wntua .and. wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') wrkbl = n + lwork_sgeqrf wrkbl = max( wrkbl, n+lwork_sorgqr_m ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n+m, bdspac ) else if( wntua .and. wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') wrkbl = n + lwork_sgeqrf wrkbl = max( wrkbl, n+lwork_sorgqr_m ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = max( 3_${ik}$*n+m, bdspac ) else if( wntua .and. wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' or ! 'a') wrkbl = n + lwork_sgeqrf wrkbl = max( wrkbl, n+lwork_sorgqr_m ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n+lwork_sorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n+m, bdspac ) end if else ! path 10 (m at least n, but not much larger) call stdlib${ii}$_sgebrd( m, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sgebrd = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = 3_${ik}$*n + lwork_sgebrd if( wntus .or. wntuo ) then call stdlib${ii}$_sorgbr( 'Q', m, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*n+lwork_sorgbr_q ) end if if( wntua ) then call stdlib${ii}$_sorgbr( 'Q', m, m, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*n+lwork_sorgbr_q ) end if if( .not.wntvn ) then maxwrk = max( maxwrk, 3_${ik}$*n+lwork_sorgbr_p ) end if maxwrk = max( maxwrk, bdspac ) minwrk = max( 3_${ik}$*n+m, bdspac ) end if else if( minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_sbdsqr mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'SGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) bdspac = 5_${ik}$*m ! compute space needed for stdlib${ii}$_sgelqf call stdlib${ii}$_sgelqf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sgelqf = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_sorglq call stdlib${ii}$_sorglq( n, n, m, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorglq_n = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sorglq( m, n, m, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorglq_m = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_sgebrd call stdlib${ii}$_sgebrd( m, m, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sgebrd = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_sorgbr p call stdlib${ii}$_sorgbr( 'P', m, m, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_sorgbr q call stdlib${ii}$_sorgbr( 'Q', m, m, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') maxwrk = m + lwork_sgelqf maxwrk = max( maxwrk, 3_${ik}$*m+lwork_sgebrd ) if( wntuo .or. wntuas )maxwrk = max( maxwrk, 3_${ik}$*m+lwork_sorgbr_q ) maxwrk = max( maxwrk, bdspac ) minwrk = max( 4_${ik}$*m, bdspac ) else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') wrkbl = m + lwork_sgelqf wrkbl = max( wrkbl, m+lwork_sorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( m*m+wrkbl, m*m+m*n+m ) minwrk = max( 3_${ik}$*m+n, bdspac ) else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', ! jobvt='o') wrkbl = m + lwork_sgelqf wrkbl = max( wrkbl, m+lwork_sorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( m*m+wrkbl, m*m+m*n+m ) minwrk = max( 3_${ik}$*m+n, bdspac ) else if( wntvs .and. wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') wrkbl = m + lwork_sgelqf wrkbl = max( wrkbl, m+lwork_sorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m+n, bdspac ) else if( wntvs .and. wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') wrkbl = m + lwork_sgelqf wrkbl = max( wrkbl, m+lwork_sorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = max( 3_${ik}$*m+n, bdspac ) maxwrk = max( maxwrk, minwrk ) else if( wntvs .and. wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') wrkbl = m + lwork_sgelqf wrkbl = max( wrkbl, m+lwork_sorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m+n, bdspac ) else if( wntva .and. wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') wrkbl = m + lwork_sgelqf wrkbl = max( wrkbl, m+lwork_sorglq_n ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m+n, bdspac ) else if( wntva .and. wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') wrkbl = m + lwork_sgelqf wrkbl = max( wrkbl, m+lwork_sorglq_n ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = max( 3_${ik}$*m+n, bdspac ) else if( wntva .and. wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') wrkbl = m + lwork_sgelqf wrkbl = max( wrkbl, m+lwork_sorglq_n ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m+lwork_sorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m+n, bdspac ) end if else ! path 10t(n greater than m, but not much larger) call stdlib${ii}$_sgebrd( m, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sgebrd = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = 3_${ik}$*m + lwork_sgebrd if( wntvs .or. wntvo ) then ! compute space needed for stdlib${ii}$_sorgbr p call stdlib${ii}$_sorgbr( 'P', m, n, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*m+lwork_sorgbr_p ) end if if( wntva ) then call stdlib${ii}$_sorgbr( 'P', n, n, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*m+lwork_sorgbr_p ) end if if( .not.wntun ) then maxwrk = max( maxwrk, 3_${ik}$*m+lwork_sorgbr_q ) end if maxwrk = max( maxwrk, bdspac ) minwrk = max( 3_${ik}$*m+n, bdspac ) end if end if maxwrk = max( maxwrk, minwrk ) work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') ! no left singular vectors to be computed itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out below r if( n > 1_${ik}$ ) then call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) ncvt = 0_${ik}$ if( wntvo .or. wntvas ) then ! if right singular vectors desired, generate p'. ! (workspace: need 4*n-1, prefer 3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) ncvt = n end if iwork = ie + n ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a if desired ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, ncvt, 0_${ik}$, 0_${ik}$, s, work( ie ), a, lda,dum, 1_${ik}$, dum, 1_${ik}$, & work( iwork ), info ) ! if right singular vectors desired in vt, copy them there if( wntvas )call stdlib${ii}$_slacpy( 'F', n, n, a, lda, vt, ldvt ) else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') ! n left singular vectors to be overwritten on a and ! no right singular vectors to be computed if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n+n )+lda*n ) then ! work(iu) is lda by n, work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n+n )+n*n ) then ! work(iu) is lda by n, work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n, work(ir) is n by n ldwrku = ( lwork-n*n-n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n+2*n, prefer n*n+n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to work(ir) and zero out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero, work( ir+1 ),ldwrkr ) ! generate q in a ! (workspace: need n*n+2*n, prefer n*n+n+n*nb) call stdlib${ii}$_sorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (workspace: need n*n+4*n, prefer n*n+3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r ! (workspace: need n*n+4*n, prefer n*n+3*n+n*nb) call stdlib${ii}$_sorgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (workspace: need n*n+bdspac) call stdlib${ii}$_sbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, work( ie ), dum, 1_${ik}$,work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) iu = ie + n ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (workspace: need n*n+2*n, prefer n*n+m*n+n) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_sgemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( ir )& , ldwrkr, zero,work( iu ), ldwrku ) call stdlib${ii}$_slacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (workspace: need 3*n+m, prefer 3*n+(m+n)*nb) call stdlib${ii}$_sgebrd( m, n, a, lda, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing a ! (workspace: need 4*n, prefer 3*n+n*nb) call stdlib${ii}$_sorgbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, work( ie ), dum, 1_${ik}$,a, lda, dum, 1_${ik}$, & work( iwork ), info ) end if else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or 'a') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n+n )+lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n+n )+n*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n and work(ir) is n by n ldwrku = ( lwork-n*n-n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n+2*n, prefer n*n+n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (workspace: need n*n+2*n, prefer n*n+n+n*nb) call stdlib${ii}$_sorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt, copying result to work(ir) ! (workspace: need n*n+4*n, prefer n*n+3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', n, n, vt, ldvt, work( ir ), ldwrkr ) ! generate left vectors bidiagonalizing r in work(ir) ! (workspace: need n*n+4*n, prefer n*n+3*n+n*nb) call stdlib${ii}$_sorgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (workspace: need n*n+4*n-1, prefer n*n+3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) and computing right ! singular vectors of r in vt ! (workspace: need n*n+bdspac) call stdlib${ii}$_sbdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ), vt, ldvt,work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) iu = ie + n ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (workspace: need n*n+2*n, prefer n*n+m*n+n) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_sgemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( ir )& , ldwrkr, zero,work( iu ), ldwrku ) call stdlib${ii}$_slacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (workspace: need 4*n, prefer 3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in a by left vectors bidiagonalizing r ! (workspace: need 3*n+m, prefer 3*n+m*nb) call stdlib${ii}$_sormbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), a, lda,& work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (workspace: need 4*n-1, prefer 3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), vt, ldvt,a, lda, dum, & 1_${ik}$, work( iwork ), info ) end if else if( wntus ) then if( wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') ! n left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n+2*n, prefer n*n+n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,work( ir+1 ), ldwrkr ) ! generate q in a ! (workspace: need n*n+2*n, prefer n*n+n+n*nb) call stdlib${ii}$_sorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (workspace: need n*n+4*n, prefer n*n+3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r in work(ir) ! (workspace: need n*n+4*n, prefer n*n+3*n+n*nb) call stdlib${ii}$_sorgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (workspace: need n*n+bdspac) call stdlib${ii}$_sbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, work( ie ), dum,1_${ik}$, work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! (workspace: need n*n) call stdlib${ii}$_sgemm( 'N', 'N', m, n, n, one, a, lda,work( ir ), ldwrkr, & zero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sorgqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (workspace: need 3*n+m, prefer 3*n+m*nb) call stdlib${ii}$_sormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, work( ie ), dum,1_${ik}$, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') ! n left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda+n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ! generate q in a ! (workspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) call stdlib${ii}$_sorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (workspace: need 2*n*n+4*n, ! prefer 2*n*n+3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need 2*n*n+4*n, prefer 2*n*n+3*n+n*nb) call stdlib${ii}$_sorgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (workspace: need 2*n*n+4*n-1, ! prefer 2*n*n+3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (workspace: need 2*n*n+bdspac) call stdlib${ii}$_sbdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, dum, 1_${ik}$, work( iwork ), info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (workspace: need n*n) call stdlib${ii}$_sgemm( 'N', 'N', m, n, n, one, a, lda,work( iu ), ldwrku, & zero, u, ldu ) ! copy right singular vectors of r to a ! (workspace: need n*n) call stdlib${ii}$_slacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sorgqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (workspace: need 3*n+m, prefer 3*n+m*nb) call stdlib${ii}$_sormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in a ! (workspace: need 4*n-1, prefer 3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), a,lda, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' ! or 'a') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n+2*n, prefer n*n+n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ! generate q in a ! (workspace: need n*n+2*n, prefer n*n+n+n*nb) call stdlib${ii}$_sorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (workspace: need n*n+4*n, prefer n*n+3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need n*n+4*n, prefer n*n+3*n+n*nb) call stdlib${ii}$_sorgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need n*n+4*n-1, ! prefer n*n+3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (workspace: need n*n+bdspac) call stdlib${ii}$_sbdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ), vt,ldvt, work( iu ),& ldwrku, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (workspace: need n*n) call stdlib${ii}$_sgemm( 'N', 'N', m, n, n, one, a, lda,work( iu ), ldwrku, & zero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sorgqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt & ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (workspace: need 4*n, prefer 3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (workspace: need 3*n+m, prefer 3*n+m*nb) call stdlib${ii}$_sormbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need 4*n-1, prefer 3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if else if( wntua ) then if( wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') ! m left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+max( n+m, 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need n*n+2*n, prefer n*n+n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, n, a, lda, u, ldu ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,work( ir+1 ), ldwrkr ) ! generate q in u ! (workspace: need n*n+n+m, prefer n*n+n+m*nb) call stdlib${ii}$_sorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (workspace: need n*n+4*n, prefer n*n+3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (workspace: need n*n+4*n, prefer n*n+3*n+n*nb) call stdlib${ii}$_sorgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (workspace: need n*n+bdspac) call stdlib${ii}$_sbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, work( ie ), dum,1_${ik}$, work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in u by left singular vectors of r in ! work(ir), storing result in a ! (workspace: need n*n) call stdlib${ii}$_sgemm( 'N', 'N', m, n, n, one, u, ldu,work( ir ), ldwrkr, & zero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_slacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n+m, prefer n+m*nb) call stdlib${ii}$_sorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (workspace: need 3*n+m, prefer 3*n+m*nb) call stdlib${ii}$_sormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, work( ie ), dum,1_${ik}$, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') ! m left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+max( n+m, 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda+n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n*n+n+m, prefer 2*n*n+n+m*nb) call stdlib${ii}$_sorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (workspace: need 2*n*n+4*n, ! prefer 2*n*n+3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need 2*n*n+4*n, prefer 2*n*n+3*n+n*nb) call stdlib${ii}$_sorgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (workspace: need 2*n*n+4*n-1, ! prefer 2*n*n+3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (workspace: need 2*n*n+bdspac) call stdlib${ii}$_sbdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, dum, 1_${ik}$, work( iwork ), info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (workspace: need n*n) call stdlib${ii}$_sgemm( 'N', 'N', m, n, n, one, u, ldu,work( iu ), ldwrku, & zero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_slacpy( 'F', m, n, a, lda, u, ldu ) ! copy right singular vectors of r from work(ir) to a call stdlib${ii}$_slacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n+m, prefer n+m*nb) call stdlib${ii}$_sorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (workspace: need 3*n+m, prefer 3*n+m*nb) call stdlib${ii}$_sormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in a ! (workspace: need 4*n-1, prefer 3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), a,lda, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' ! or 'a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( n+m, 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need n*n+2*n, prefer n*n+n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n*n+n+m, prefer n*n+n+m*nb) call stdlib${ii}$_sorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (workspace: need n*n+4*n, prefer n*n+3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need n*n+4*n, prefer n*n+3*n+n*nb) call stdlib${ii}$_sorgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need n*n+4*n-1, ! prefer n*n+3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (workspace: need n*n+bdspac) call stdlib${ii}$_sbdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ), vt,ldvt, work( iu ),& ldwrku, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (workspace: need n*n) call stdlib${ii}$_sgemm( 'N', 'N', m, n, n, one, u, ldu,work( iu ), ldwrku, & zero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_slacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n+m, prefer n+m*nb) call stdlib${ii}$_sorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r from a to vt, zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt & ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (workspace: need 4*n, prefer 3*n+2*n*nb) call stdlib${ii}$_sgebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (workspace: need 3*n+m, prefer 3*n+m*nb) call stdlib${ii}$_sormbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need 4*n-1, prefer 3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if end if else ! m < mnthr ! path 10 (m at least n, but not much larger) ! reduce to bidiagonal form without qr decomposition ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (workspace: need 3*n+m, prefer 3*n+(m+n)*nb) call stdlib${ii}$_sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (workspace: need 3*n+ncu, prefer 3*n+ncu*nb) call stdlib${ii}$_slacpy( 'L', m, n, a, lda, u, ldu ) if( wntus )ncu = n if( wntua )ncu = m call stdlib${ii}$_sorgbr( 'Q', m, ncu, n, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (workspace: need 4*n-1, prefer 3*n+(n-1)*nb) call stdlib${ii}$_slacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_sorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (workspace: need 4*n, prefer 3*n+n*nb) call stdlib${ii}$_sorgbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (workspace: need 4*n-1, prefer 3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if iwork = ie + n if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, dum,& 1_${ik}$, work( iwork ), info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, work( ie ), a, lda,u, ldu, dum, & 1_${ik}$, work( iwork ), info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, dum,& 1_${ik}$, work( iwork ), info ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') ! no right singular vectors to be computed itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ), lda ) ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuo .or. wntuas ) then ! if left singular vectors desired, generate q ! (workspace: need 4*m, prefer 3*m+m*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if iwork = ie + m nru = 0_${ik}$ if( wntuo .or. wntuas )nru = m ! perform bidiagonal qr iteration, computing left singular ! vectors of a in a if desired ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', m, 0_${ik}$, nru, 0_${ik}$, s, work( ie ), dum, 1_${ik}$, a,lda, dum, 1_${ik}$, & work( iwork ), info ) ! if left singular vectors desired in u, copy them there if( wntuas )call stdlib${ii}$_slacpy( 'F', m, m, a, lda, u, ldu ) else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') ! m right singular vectors to be overwritten on a and ! no left singular vectors to be computed if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n+m )+lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n+m )+m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m-m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m+2*m, prefer m*m+m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to work(ir) and zero out above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero,work( ir+ldwrkr ), ldwrkr ) ! generate q in a ! (workspace: need m*m+2*m, prefer m*m+m+m*nb) call stdlib${ii}$_sorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (workspace: need m*m+4*m, prefer m*m+3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l ! (workspace: need m*m+4*m-1, prefer m*m+3*m+(m-1)*nb) call stdlib${ii}$_sorgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (workspace: need m*m+bdspac) call stdlib${ii}$_sbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, dum,& 1_${ik}$, dum, 1_${ik}$,work( iwork ), info ) iu = ie + m ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (workspace: need m*m+2*m, prefer m*m+m*n+m) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_sgemm( 'N', 'N', m, blk, m, one, work( ir ),ldwrkr, a( 1_${ik}$, i & ), lda, zero,work( iu ), ldwrku ) call stdlib${ii}$_slacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (workspace: need 3*m+n, prefer 3*m+(m+n)*nb) call stdlib${ii}$_sgebrd( m, n, a, lda, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing a ! (workspace: need 4*m, prefer 3*m+m*nb) call stdlib${ii}$_sorgbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'L', m, n, 0_${ik}$, 0_${ik}$, s, work( ie ), a, lda,dum, 1_${ik}$, dum, 1_${ik}$, & work( iwork ), info ) end if else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', jobvt='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n+m )+lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n+m )+m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m-m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m+2*m, prefer m*m+m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing about above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (workspace: need m*m+2*m, prefer m*m+m+m*nb) call stdlib${ii}$_sorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u, copying result to work(ir) ! (workspace: need m*m+4*m, prefer m*m+3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', m, m, u, ldu, work( ir ), ldwrkr ) ! generate right vectors bidiagonalizing l in work(ir) ! (workspace: need m*m+4*m-1, prefer m*m+3*m+(m-1)*nb) call stdlib${ii}$_sorgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (workspace: need m*m+4*m, prefer m*m+3*m+m*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u, and computing right ! singular vectors of l in work(ir) ! (workspace: need m*m+bdspac) call stdlib${ii}$_sbdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, u, & ldu, dum, 1_${ik}$,work( iwork ), info ) iu = ie + m ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (workspace: need m*m+2*m, prefer m*m+m*n+m)) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_sgemm( 'N', 'N', m, blk, m, one, work( ir ),ldwrkr, a( 1_${ik}$, i & ), lda, zero,work( iu ), ldwrku ) call stdlib${ii}$_slacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (workspace: need 4*m, prefer 3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in a ! (workspace: need 3*m+n, prefer 3*m+n*nb) call stdlib${ii}$_sormbr( 'P', 'L', 'T', m, n, m, u, ldu,work( itaup ), a, lda, & work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (workspace: need 4*m, prefer 3*m+m*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), a, lda,u, ldu, dum, 1_${ik}$, & work( iwork ), info ) end if else if( wntvs ) then if( wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') ! m right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m+2*m, prefer m*m+m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero,work( ir+ldwrkr ), ldwrkr & ) ! generate q in a ! (workspace: need m*m+2*m, prefer m*m+m+m*nb) call stdlib${ii}$_sorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (workspace: need m*m+4*m, prefer m*m+3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l in ! work(ir) ! (workspace: need m*m+4*m, prefer m*m+3*m+(m-1)*nb) call stdlib${ii}$_sorgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (workspace: need m*m+bdspac) call stdlib${ii}$_sbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & dum, 1_${ik}$, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in a, storing result in vt ! (workspace: need m*m) call stdlib${ii}$_sgemm( 'N', 'N', m, n, m, one, work( ir ),ldwrkr, a, lda, & zero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy result to vt call stdlib${ii}$_slacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sorglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (workspace: need 3*m+n, prefer 3*m+n*nb) call stdlib${ii}$_sormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, work( ie ), vt,ldvt, dum, 1_${ik}$, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda+m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out below it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ! generate q in a ! (workspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) call stdlib${ii}$_sorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (workspace: need 2*m*m+4*m, ! prefer 2*m*m+3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need 2*m*m+4*m-1, ! prefer 2*m*m+3*m+(m-1)*nb) call stdlib${ii}$_sorgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (workspace: need 2*m*m+4*m, prefer 2*m*m+3*m+m*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (workspace: need 2*m*m+bdspac) call stdlib${ii}$_sbdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, dum, 1_${ik}$, work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (workspace: need m*m) call stdlib${ii}$_sgemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, a, lda, & zero, vt, ldvt ) ! copy left singular vectors of l to a ! (workspace: need m*m) call stdlib${ii}$_slacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sorglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (workspace: need 3*m+n, prefer 3*m+n*nb) call stdlib${ii}$_sormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors of l in a ! (workspace: need 4*m, prefer 3*m+m*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, compute left ! singular vectors of a in a and compute right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is lda by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m+2*m, prefer m*m+m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ! generate q in a ! (workspace: need m*m+2*m, prefer m*m+m+m*nb) call stdlib${ii}$_sorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (workspace: need m*m+4*m, prefer m*m+3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need m*m+4*m-1, ! prefer m*m+3*m+(m-1)*nb) call stdlib${ii}$_sorgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need m*m+4*m, prefer m*m+3*m+m*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (workspace: need m*m+bdspac) call stdlib${ii}$_sbdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & u, ldu, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (workspace: need m*m) call stdlib${ii}$_sgemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, a, lda, & zero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sorglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (workspace: need 4*m, prefer 3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (workspace: need 3*m+n, prefer 3*m+n*nb) call stdlib${ii}$_sormbr( 'P', 'L', 'T', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need 4*m, prefer 3*m+m*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if else if( wntva ) then if( wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') ! n right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+max( n+m, 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need m*m+2*m, prefer m*m+m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', m, n, a, lda, vt, ldvt ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero,work( ir+ldwrkr ), ldwrkr & ) ! generate q in vt ! (workspace: need m*m+m+n, prefer m*m+m+n*nb) call stdlib${ii}$_sorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (workspace: need m*m+4*m, prefer m*m+3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (workspace: need m*m+4*m-1, ! prefer m*m+3*m+(m-1)*nb) call stdlib${ii}$_sorgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (workspace: need m*m+bdspac) call stdlib${ii}$_sbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & dum, 1_${ik}$, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in vt, storing result in a ! (workspace: need m*m) call stdlib${ii}$_sgemm( 'N', 'N', m, n, m, one, work( ir ),ldwrkr, vt, ldvt, & zero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_slacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m+n, prefer m+n*nb) call stdlib${ii}$_sorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (workspace: need 3*m+n, prefer 3*m+n*nb) call stdlib${ii}$_sormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, work( ie ), vt,ldvt, dum, 1_${ik}$, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+max( n+m, 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda+m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m*m+m+n, prefer 2*m*m+m+n*nb) call stdlib${ii}$_sorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (workspace: need 2*m*m+4*m, ! prefer 2*m*m+3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need 2*m*m+4*m-1, ! prefer 2*m*m+3*m+(m-1)*nb) call stdlib${ii}$_sorgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (workspace: need 2*m*m+4*m, prefer 2*m*m+3*m+m*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (workspace: need 2*m*m+bdspac) call stdlib${ii}$_sbdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, dum, 1_${ik}$, work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (workspace: need m*m) call stdlib${ii}$_sgemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, vt, ldvt, & zero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_slacpy( 'F', m, n, a, lda, vt, ldvt ) ! copy left singular vectors of a from work(ir) to a call stdlib${ii}$_slacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m+n, prefer m+n*nb) call stdlib${ii}$_sorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (workspace: need 3*m+n, prefer 3*m+n*nb) call stdlib${ii}$_sormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in a ! (workspace: need 4*m, prefer 3*m+m*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+max( n+m, 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by m ldwrku = lda else ! work(iu) is m by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need m*m+2*m, prefer m*m+m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m*m+m+n, prefer m*m+m+n*nb) call stdlib${ii}$_sorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (workspace: need m*m+4*m, prefer m*m+3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_slacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need m*m+4*m, prefer m*m+3*m+(m-1)*nb) call stdlib${ii}$_sorgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need m*m+4*m, prefer m*m+3*m+m*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (workspace: need m*m+bdspac) call stdlib${ii}$_sbdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & u, ldu, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (workspace: need m*m) call stdlib${ii}$_sgemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, vt, ldvt, & zero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_slacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_slacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m+n, prefer m+n*nb) call stdlib${ii}$_sorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (workspace: need 4*m, prefer 3*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (workspace: need 3*m+n, prefer 3*m+n*nb) call stdlib${ii}$_sormbr( 'P', 'L', 'T', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need 4*m, prefer 3*m+m*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if end if else ! n < mnthr ! path 10t(n greater than m, but not much larger) ! reduce to bidiagonal form without lq decomposition ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (workspace: need 3*m+n, prefer 3*m+(m+n)*nb) call stdlib${ii}$_sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (workspace: need 4*m-1, prefer 3*m+(m-1)*nb) call stdlib${ii}$_slacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_sorgbr( 'Q', m, m, n, u, ldu, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (workspace: need 3*m+nrvt, prefer 3*m+nrvt*nb) call stdlib${ii}$_slacpy( 'U', m, n, a, lda, vt, ldvt ) if( wntva )nrvt = n if( wntvs )nrvt = m call stdlib${ii}$_sorgbr( 'P', nrvt, n, m, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (workspace: need 4*m-1, prefer 3*m+(m-1)*nb) call stdlib${ii}$_sorgbr( 'Q', m, m, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (workspace: need 4*m, prefer 3*m+m*nb) call stdlib${ii}$_sorgbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if iwork = ie + m if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, dum,& 1_${ik}$, work( iwork ), info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, work( ie ), a, lda,u, ldu, dum, & 1_${ik}$, work( iwork ), info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, dum,& 1_${ik}$, work( iwork ), info ) end if end if end if ! if stdlib${ii}$_sbdsqr failed to converge, copy unconverged superdiagonals ! to work( 2:minmn ) if( info/=0_${ik}$ ) then if( ie>2_${ik}$ ) then do i = 1, minmn - 1 work( i+1 ) = work( i+ie-1 ) end do end if if( ie<2_${ik}$ ) then do i = minmn - 1, 1, -1 work( i+1 ) = work( i+ie-1 ) end do end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( info/=0_${ik}$ .and. anrm>bignum )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn-1,& 1_${ik}$, work( 2_${ik}$ ),minmn, ierr ) if( anrm=n .and. minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_dbdsqr mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'DGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) bdspac = 5_${ik}$*n ! compute space needed for stdlib${ii}$_dgeqrf call stdlib${ii}$_dgeqrf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dgeqrf = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_dorgqr call stdlib${ii}$_dorgqr( m, n, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgqr_n = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dorgqr( m, m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgqr_m = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_dgebrd call stdlib${ii}$_dgebrd( n, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dgebrd = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_dorgbr p call stdlib${ii}$_dorgbr( 'P', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_dorgbr q call stdlib${ii}$_dorgbr( 'Q', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') maxwrk = n + lwork_dgeqrf maxwrk = max( maxwrk, 3_${ik}$*n + lwork_dgebrd ) if( wntvo .or. wntvas )maxwrk = max( maxwrk, 3_${ik}$*n + lwork_dorgbr_p ) maxwrk = max( maxwrk, bdspac ) minwrk = max( 4_${ik}$*n, bdspac ) else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') wrkbl = n + lwork_dgeqrf wrkbl = max( wrkbl, n + lwork_dorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( n*n + wrkbl, n*n + m*n + n ) minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or ! 'a') wrkbl = n + lwork_dgeqrf wrkbl = max( wrkbl, n + lwork_dorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( n*n + wrkbl, n*n + m*n + n ) minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntus .and. wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') wrkbl = n + lwork_dgeqrf wrkbl = max( wrkbl, n + lwork_dorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntus .and. wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') wrkbl = n + lwork_dgeqrf wrkbl = max( wrkbl, n + lwork_dorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntus .and. wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' or ! 'a') wrkbl = n + lwork_dgeqrf wrkbl = max( wrkbl, n + lwork_dorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntua .and. wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') wrkbl = n + lwork_dgeqrf wrkbl = max( wrkbl, n + lwork_dorgqr_m ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntua .and. wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') wrkbl = n + lwork_dgeqrf wrkbl = max( wrkbl, n + lwork_dorgqr_m ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntua .and. wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' or ! 'a') wrkbl = n + lwork_dgeqrf wrkbl = max( wrkbl, n + lwork_dorgqr_m ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) end if else ! path 10 (m at least n, but not much larger) call stdlib${ii}$_dgebrd( m, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dgebrd = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = 3_${ik}$*n + lwork_dgebrd if( wntus .or. wntuo ) then call stdlib${ii}$_dorgbr( 'Q', m, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*n + lwork_dorgbr_q ) end if if( wntua ) then call stdlib${ii}$_dorgbr( 'Q', m, m, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*n + lwork_dorgbr_q ) end if if( .not.wntvn ) then maxwrk = max( maxwrk, 3_${ik}$*n + lwork_dorgbr_p ) end if maxwrk = max( maxwrk, bdspac ) minwrk = max( 3_${ik}$*n + m, bdspac ) end if else if( minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_dbdsqr mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'DGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) bdspac = 5_${ik}$*m ! compute space needed for stdlib${ii}$_dgelqf call stdlib${ii}$_dgelqf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dgelqf = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_dorglq call stdlib${ii}$_dorglq( n, n, m, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorglq_n = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dorglq( m, n, m, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorglq_m = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_dgebrd call stdlib${ii}$_dgebrd( m, m, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dgebrd = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_dorgbr p call stdlib${ii}$_dorgbr( 'P', m, m, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_dorgbr q call stdlib${ii}$_dorgbr( 'Q', m, m, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') maxwrk = m + lwork_dgelqf maxwrk = max( maxwrk, 3_${ik}$*m + lwork_dgebrd ) if( wntuo .or. wntuas )maxwrk = max( maxwrk, 3_${ik}$*m + lwork_dorgbr_q ) maxwrk = max( maxwrk, bdspac ) minwrk = max( 4_${ik}$*m, bdspac ) else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') wrkbl = m + lwork_dgelqf wrkbl = max( wrkbl, m + lwork_dorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( m*m + wrkbl, m*m + m*n + m ) minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', ! jobvt='o') wrkbl = m + lwork_dgelqf wrkbl = max( wrkbl, m + lwork_dorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( m*m + wrkbl, m*m + m*n + m ) minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntvs .and. wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') wrkbl = m + lwork_dgelqf wrkbl = max( wrkbl, m + lwork_dorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntvs .and. wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') wrkbl = m + lwork_dgelqf wrkbl = max( wrkbl, m + lwork_dorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntvs .and. wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') wrkbl = m + lwork_dgelqf wrkbl = max( wrkbl, m + lwork_dorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntva .and. wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') wrkbl = m + lwork_dgelqf wrkbl = max( wrkbl, m + lwork_dorglq_n ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntva .and. wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') wrkbl = m + lwork_dgelqf wrkbl = max( wrkbl, m + lwork_dorglq_n ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntva .and. wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') wrkbl = m + lwork_dgelqf wrkbl = max( wrkbl, m + lwork_dorglq_n ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) end if else ! path 10t(n greater than m, but not much larger) call stdlib${ii}$_dgebrd( m, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dgebrd = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = 3_${ik}$*m + lwork_dgebrd if( wntvs .or. wntvo ) then ! compute space needed for stdlib${ii}$_dorgbr p call stdlib${ii}$_dorgbr( 'P', m, n, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*m + lwork_dorgbr_p ) end if if( wntva ) then call stdlib${ii}$_dorgbr( 'P', n, n, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*m + lwork_dorgbr_p ) end if if( .not.wntun ) then maxwrk = max( maxwrk, 3_${ik}$*m + lwork_dorgbr_q ) end if maxwrk = max( maxwrk, bdspac ) minwrk = max( 3_${ik}$*m + n, bdspac ) end if end if maxwrk = max( maxwrk, minwrk ) work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') ! no left singular vectors to be computed itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out below r if( n > 1_${ik}$ ) then call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) ncvt = 0_${ik}$ if( wntvo .or. wntvas ) then ! if right singular vectors desired, generate p'. ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) ncvt = n end if iwork = ie + n ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a if desired ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, ncvt, 0_${ik}$, 0_${ik}$, s, work( ie ), a, lda,dum, 1_${ik}$, dum, 1_${ik}$, & work( iwork ), info ) ! if right singular vectors desired in vt, copy them there if( wntvas )call stdlib${ii}$_dlacpy( 'F', n, n, a, lda, vt, ldvt ) else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') ! n left singular vectors to be overwritten on a and ! no right singular vectors to be computed if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n + n ) + lda*n ) then ! work(iu) is lda by n, work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n + n ) + n*n ) then ! work(iu) is lda by n, work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n, work(ir) is n by n ldwrku = ( lwork-n*n-n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to work(ir) and zero out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero, work( ir+1 ),ldwrkr ) ! generate q in a ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_dorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_dorgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (workspace: need n*n + bdspac) call stdlib${ii}$_dbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, work( ie ), dum, 1_${ik}$,work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) iu = ie + n ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (workspace: need n*n + 2*n, prefer n*n + m*n + n) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_dgemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( ir )& , ldwrkr, zero,work( iu ), ldwrku ) call stdlib${ii}$_dlacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (workspace: need 3*n + m, prefer 3*n + (m + n)*nb) call stdlib${ii}$_dgebrd( m, n, a, lda, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing a ! (workspace: need 4*n, prefer 3*n + n*nb) call stdlib${ii}$_dorgbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, work( ie ), dum, 1_${ik}$,a, lda, dum, 1_${ik}$, & work( iwork ), info ) end if else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or 'a') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n + n ) + lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n + n ) + n*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n and work(ir) is n by n ldwrku = ( lwork-n*n-n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_dorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt, copying result to work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', n, n, vt, ldvt, work( ir ), ldwrkr ) ! generate left vectors bidiagonalizing r in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_dorgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (workspace: need n*n + 4*n-1, prefer n*n + 3*n + (n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) and computing right ! singular vectors of r in vt ! (workspace: need n*n + bdspac) call stdlib${ii}$_dbdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ), vt, ldvt,work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) iu = ie + n ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (workspace: need n*n + 2*n, prefer n*n + m*n + n) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_dgemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( ir )& , ldwrkr, zero,work( iu ), ldwrku ) call stdlib${ii}$_dlacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in a by left vectors bidiagonalizing r ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_dormbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), a, lda,& work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), vt, ldvt,a, lda, dum, & 1_${ik}$, work( iwork ), info ) end if else if( wntus ) then if( wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') ! n left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,work( ir+1 ), ldwrkr ) ! generate q in a ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_dorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_dorgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (workspace: need n*n + bdspac) call stdlib${ii}$_dbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, work( ie ), dum,1_${ik}$, work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! (workspace: need n*n) call stdlib${ii}$_dgemm( 'N', 'N', m, n, n, one, a, lda,work( ir ), ldwrkr, & zero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dorgqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_dormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, work( ie ), dum,1_${ik}$, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') ! n left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda + n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need 2*n*n + 2*n, prefer 2*n*n + n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ! generate q in a ! (workspace: need 2*n*n + 2*n, prefer 2*n*n + n + n*nb) call stdlib${ii}$_dorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (workspace: need 2*n*n + 4*n, ! prefer 2*n*n+3*n+2*n*nb) call stdlib${ii}$_dgebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need 2*n*n + 4*n, prefer 2*n*n + 3*n + n*nb) call stdlib${ii}$_dorgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (workspace: need 2*n*n + 4*n-1, ! prefer 2*n*n+3*n+(n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (workspace: need 2*n*n + bdspac) call stdlib${ii}$_dbdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, dum, 1_${ik}$, work( iwork ), info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (workspace: need n*n) call stdlib${ii}$_dgemm( 'N', 'N', m, n, n, one, a, lda,work( iu ), ldwrku, & zero, u, ldu ) ! copy right singular vectors of r to a ! (workspace: need n*n) call stdlib${ii}$_dlacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dorgqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_dormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in a ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), a,lda, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' ! or 'a') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ! generate q in a ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_dorgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_dorgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need n*n + 4*n-1, ! prefer n*n+3*n+(n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (workspace: need n*n + bdspac) call stdlib${ii}$_dbdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ), vt,ldvt, work( iu ),& ldwrku, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (workspace: need n*n) call stdlib${ii}$_dgemm( 'N', 'N', m, n, n, one, a, lda,work( iu ), ldwrku, & zero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dorgqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt & ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_dormbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if else if( wntua ) then if( wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') ! m left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+max( n+m, 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, n, a, lda, u, ldu ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,work( ir+1 ), ldwrkr ) ! generate q in u ! (workspace: need n*n + n + m, prefer n*n + n + m*nb) call stdlib${ii}$_dorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_dorgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (workspace: need n*n + bdspac) call stdlib${ii}$_dbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, work( ie ), dum,1_${ik}$, work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in u by left singular vectors of r in ! work(ir), storing result in a ! (workspace: need n*n) call stdlib${ii}$_dgemm( 'N', 'N', m, n, n, one, u, ldu,work( ir ), ldwrkr, & zero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_dlacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n + m, prefer n + m*nb) call stdlib${ii}$_dorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_dormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, work( ie ), dum,1_${ik}$, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') ! m left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+max( n+m, 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda + n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n*n + 2*n, prefer 2*n*n + n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n*n + n + m, prefer 2*n*n + n + m*nb) call stdlib${ii}$_dorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (workspace: need 2*n*n + 4*n, ! prefer 2*n*n+3*n+2*n*nb) call stdlib${ii}$_dgebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need 2*n*n + 4*n, prefer 2*n*n + 3*n + n*nb) call stdlib${ii}$_dorgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (workspace: need 2*n*n + 4*n-1, ! prefer 2*n*n+3*n+(n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (workspace: need 2*n*n + bdspac) call stdlib${ii}$_dbdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, dum, 1_${ik}$, work( iwork ), info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (workspace: need n*n) call stdlib${ii}$_dgemm( 'N', 'N', m, n, n, one, u, ldu,work( iu ), ldwrku, & zero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_dlacpy( 'F', m, n, a, lda, u, ldu ) ! copy right singular vectors of r from work(ir) to a call stdlib${ii}$_dlacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n + m, prefer n + m*nb) call stdlib${ii}$_dorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_dormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in a ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), a,lda, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' ! or 'a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( n+m, 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n*n + n + m, prefer n*n + n + m*nb) call stdlib${ii}$_dorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_dorgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need n*n + 4*n-1, ! prefer n*n+3*n+(n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (workspace: need n*n + bdspac) call stdlib${ii}$_dbdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ), vt,ldvt, work( iu ),& ldwrku, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (workspace: need n*n) call stdlib${ii}$_dgemm( 'N', 'N', m, n, n, one, u, ldu,work( iu ), ldwrku, & zero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_dlacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n + m, prefer n + m*nb) call stdlib${ii}$_dorgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r from a to vt, zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt & ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_dgebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_dormbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if end if else ! m < mnthr ! path 10 (m at least n, but not much larger) ! reduce to bidiagonal form without qr decomposition ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (workspace: need 3*n + m, prefer 3*n + (m + n)*nb) call stdlib${ii}$_dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (workspace: need 3*n + ncu, prefer 3*n + ncu*nb) call stdlib${ii}$_dlacpy( 'L', m, n, a, lda, u, ldu ) if( wntus )ncu = n if( wntua )ncu = m call stdlib${ii}$_dorgbr( 'Q', m, ncu, n, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_dorgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (workspace: need 4*n, prefer 3*n + n*nb) call stdlib${ii}$_dorgbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if iwork = ie + n if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, dum,& 1_${ik}$, work( iwork ), info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, work( ie ), a, lda,u, ldu, dum, & 1_${ik}$, work( iwork ), info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, dum,& 1_${ik}$, work( iwork ), info ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') ! no right singular vectors to be computed itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ), lda ) ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuo .or. wntuas ) then ! if left singular vectors desired, generate q ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if iwork = ie + m nru = 0_${ik}$ if( wntuo .or. wntuas )nru = m ! perform bidiagonal qr iteration, computing left singular ! vectors of a in a if desired ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', m, 0_${ik}$, nru, 0_${ik}$, s, work( ie ), dum, 1_${ik}$, a,lda, dum, 1_${ik}$, & work( iwork ), info ) ! if left singular vectors desired in u, copy them there if( wntuas )call stdlib${ii}$_dlacpy( 'F', m, m, a, lda, u, ldu ) else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') ! m right singular vectors to be overwritten on a and ! no left singular vectors to be computed if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n + m ) + lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n + m ) + m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m-m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to work(ir) and zero out above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero,work( ir+ldwrkr ), ldwrkr ) ! generate q in a ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_dorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l ! (workspace: need m*m + 4*m-1, prefer m*m + 3*m + (m-1)*nb) call stdlib${ii}$_dorgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (workspace: need m*m + bdspac) call stdlib${ii}$_dbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, dum,& 1_${ik}$, dum, 1_${ik}$,work( iwork ), info ) iu = ie + m ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (workspace: need m*m + 2*m, prefer m*m + m*n + m) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_dgemm( 'N', 'N', m, blk, m, one, work( ir ),ldwrkr, a( 1_${ik}$, i & ), lda, zero,work( iu ), ldwrku ) call stdlib${ii}$_dlacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (workspace: need 3*m + n, prefer 3*m + (m + n)*nb) call stdlib${ii}$_dgebrd( m, n, a, lda, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing a ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_dorgbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'L', m, n, 0_${ik}$, 0_${ik}$, s, work( ie ), a, lda,dum, 1_${ik}$, dum, 1_${ik}$, & work( iwork ), info ) end if else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', jobvt='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n + m ) + lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n + m ) + m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m-m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing about above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_dorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u, copying result to work(ir) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', m, m, u, ldu, work( ir ), ldwrkr ) ! generate right vectors bidiagonalizing l in work(ir) ! (workspace: need m*m + 4*m-1, prefer m*m + 3*m + (m-1)*nb) call stdlib${ii}$_dorgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (workspace: need m*m + 4*m, prefer m*m + 3*m + m*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u, and computing right ! singular vectors of l in work(ir) ! (workspace: need m*m + bdspac) call stdlib${ii}$_dbdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, u, & ldu, dum, 1_${ik}$,work( iwork ), info ) iu = ie + m ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (workspace: need m*m + 2*m, prefer m*m + m*n + m)) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_dgemm( 'N', 'N', m, blk, m, one, work( ir ),ldwrkr, a( 1_${ik}$, i & ), lda, zero,work( iu ), ldwrku ) call stdlib${ii}$_dlacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in a ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_dormbr( 'P', 'L', 'T', m, n, m, u, ldu,work( itaup ), a, lda, & work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), a, lda,u, ldu, dum, 1_${ik}$, & work( iwork ), info ) end if else if( wntvs ) then if( wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') ! m right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero,work( ir+ldwrkr ), ldwrkr & ) ! generate q in a ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_dorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l in ! work(ir) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + (m-1)*nb) call stdlib${ii}$_dorgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (workspace: need m*m + bdspac) call stdlib${ii}$_dbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & dum, 1_${ik}$, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in a, storing result in vt ! (workspace: need m*m) call stdlib${ii}$_dgemm( 'N', 'N', m, n, m, one, work( ir ),ldwrkr, a, lda, & zero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy result to vt call stdlib${ii}$_dlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dorglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_dormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, work( ie ), vt,ldvt, dum, 1_${ik}$, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda + m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need 2*m*m + 2*m, prefer 2*m*m + m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out below it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ! generate q in a ! (workspace: need 2*m*m + 2*m, prefer 2*m*m + m + m*nb) call stdlib${ii}$_dorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (workspace: need 2*m*m + 4*m, ! prefer 2*m*m+3*m+2*m*nb) call stdlib${ii}$_dgebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need 2*m*m + 4*m-1, ! prefer 2*m*m+3*m+(m-1)*nb) call stdlib${ii}$_dorgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (workspace: need 2*m*m + 4*m, prefer 2*m*m + 3*m + m*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (workspace: need 2*m*m + bdspac) call stdlib${ii}$_dbdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, dum, 1_${ik}$, work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (workspace: need m*m) call stdlib${ii}$_dgemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, a, lda, & zero, vt, ldvt ) ! copy left singular vectors of l to a ! (workspace: need m*m) call stdlib${ii}$_dlacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dorglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_dormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors of l in a ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, compute left ! singular vectors of a in a and compute right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is lda by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ! generate q in a ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_dorglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need m*m + 4*m-1, ! prefer m*m+3*m+(m-1)*nb) call stdlib${ii}$_dorgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need m*m + 4*m, prefer m*m + 3*m + m*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (workspace: need m*m + bdspac) call stdlib${ii}$_dbdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & u, ldu, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (workspace: need m*m) call stdlib${ii}$_dgemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, a, lda, & zero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dorglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_dormbr( 'P', 'L', 'T', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if else if( wntva ) then if( wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') ! n right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+max( n + m, 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', m, n, a, lda, vt, ldvt ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero,work( ir+ldwrkr ), ldwrkr & ) ! generate q in vt ! (workspace: need m*m + m + n, prefer m*m + m + n*nb) call stdlib${ii}$_dorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (workspace: need m*m + 4*m-1, ! prefer m*m+3*m+(m-1)*nb) call stdlib${ii}$_dorgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (workspace: need m*m + bdspac) call stdlib${ii}$_dbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & dum, 1_${ik}$, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in vt, storing result in a ! (workspace: need m*m) call stdlib${ii}$_dgemm( 'N', 'N', m, n, m, one, work( ir ),ldwrkr, vt, ldvt, & zero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_dlacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m + n, prefer m + n*nb) call stdlib${ii}$_dorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_dormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, work( ie ), vt,ldvt, dum, 1_${ik}$, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+max( n + m, 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda + m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m*m + 2*m, prefer 2*m*m + m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m*m + m + n, prefer 2*m*m + m + n*nb) call stdlib${ii}$_dorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (workspace: need 2*m*m + 4*m, ! prefer 2*m*m+3*m+2*m*nb) call stdlib${ii}$_dgebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need 2*m*m + 4*m-1, ! prefer 2*m*m+3*m+(m-1)*nb) call stdlib${ii}$_dorgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (workspace: need 2*m*m + 4*m, prefer 2*m*m + 3*m + m*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (workspace: need 2*m*m + bdspac) call stdlib${ii}$_dbdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, dum, 1_${ik}$, work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (workspace: need m*m) call stdlib${ii}$_dgemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, vt, ldvt, & zero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_dlacpy( 'F', m, n, a, lda, vt, ldvt ) ! copy left singular vectors of a from work(ir) to a call stdlib${ii}$_dlacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m + n, prefer m + n*nb) call stdlib${ii}$_dorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_dormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in a ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+max( n + m, 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by m ldwrku = lda else ! work(iu) is m by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m*m + m + n, prefer m*m + m + n*nb) call stdlib${ii}$_dorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + (m-1)*nb) call stdlib${ii}$_dorgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need m*m + 4*m, prefer m*m + 3*m + m*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (workspace: need m*m + bdspac) call stdlib${ii}$_dbdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & u, ldu, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (workspace: need m*m) call stdlib${ii}$_dgemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, vt, ldvt, & zero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_dlacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_dlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m + n, prefer m + n*nb) call stdlib${ii}$_dorglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_dgebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_dormbr( 'P', 'L', 'T', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if end if else ! n < mnthr ! path 10t(n greater than m, but not much larger) ! reduce to bidiagonal form without lq decomposition ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (workspace: need 3*m + n, prefer 3*m + (m + n)*nb) call stdlib${ii}$_dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (workspace: need 4*m-1, prefer 3*m + (m-1)*nb) call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_dorgbr( 'Q', m, m, n, u, ldu, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (workspace: need 3*m + nrvt, prefer 3*m + nrvt*nb) call stdlib${ii}$_dlacpy( 'U', m, n, a, lda, vt, ldvt ) if( wntva )nrvt = n if( wntvs )nrvt = m call stdlib${ii}$_dorgbr( 'P', nrvt, n, m, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (workspace: need 4*m-1, prefer 3*m + (m-1)*nb) call stdlib${ii}$_dorgbr( 'Q', m, m, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_dorgbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if iwork = ie + m if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, dum,& 1_${ik}$, work( iwork ), info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, work( ie ), a, lda,u, ldu, dum, & 1_${ik}$, work( iwork ), info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, dum,& 1_${ik}$, work( iwork ), info ) end if end if end if ! if stdlib${ii}$_dbdsqr failed to converge, copy unconverged superdiagonals ! to work( 2:minmn ) if( info/=0_${ik}$ ) then if( ie>2_${ik}$ ) then do i = 1, minmn - 1 work( i+1 ) = work( i+ie-1 ) end do end if if( ie<2_${ik}$ ) then do i = minmn - 1, 1, -1 work( i+1 ) = work( i+ie-1 ) end do end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( info/=0_${ik}$ .and. anrm>bignum )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn-1,& 1_${ik}$, work( 2_${ik}$ ),minmn, ierr ) if( anrm=n .and. minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_${ri}$bdsqr mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'DGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) bdspac = 5_${ik}$*n ! compute space needed for stdlib${ii}$_${ri}$geqrf call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qgeqrf = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ri}$orgqr call stdlib${ii}$_${ri}$orgqr( m, n, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgqr_n = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$orgqr( m, m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgqr_m = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ri}$gebrd call stdlib${ii}$_${ri}$gebrd( n, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qgebrd = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ri}$orgbr p call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ri}$orgbr q call stdlib${ii}$_${ri}$orgbr( 'Q', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') maxwrk = n + lwork_qgeqrf maxwrk = max( maxwrk, 3_${ik}$*n + lwork_qgebrd ) if( wntvo .or. wntvas )maxwrk = max( maxwrk, 3_${ik}$*n + lwork_qorgbr_p ) maxwrk = max( maxwrk, bdspac ) minwrk = max( 4_${ik}$*n, bdspac ) else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') wrkbl = n + lwork_qgeqrf wrkbl = max( wrkbl, n + lwork_qorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( n*n + wrkbl, n*n + m*n + n ) minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or ! 'a') wrkbl = n + lwork_qgeqrf wrkbl = max( wrkbl, n + lwork_qorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( n*n + wrkbl, n*n + m*n + n ) minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntus .and. wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') wrkbl = n + lwork_qgeqrf wrkbl = max( wrkbl, n + lwork_qorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntus .and. wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') wrkbl = n + lwork_qgeqrf wrkbl = max( wrkbl, n + lwork_qorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntus .and. wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' or ! 'a') wrkbl = n + lwork_qgeqrf wrkbl = max( wrkbl, n + lwork_qorgqr_n ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntua .and. wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') wrkbl = n + lwork_qgeqrf wrkbl = max( wrkbl, n + lwork_qorgqr_m ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntua .and. wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') wrkbl = n + lwork_qgeqrf wrkbl = max( wrkbl, n + lwork_qorgqr_m ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) else if( wntua .and. wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' or ! 'a') wrkbl = n + lwork_qgeqrf wrkbl = max( wrkbl, n + lwork_qorgqr_m ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_q ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = n*n + wrkbl minwrk = max( 3_${ik}$*n + m, bdspac ) end if else ! path 10 (m at least n, but not much larger) call stdlib${ii}$_${ri}$gebrd( m, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qgebrd = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = 3_${ik}$*n + lwork_qgebrd if( wntus .or. wntuo ) then call stdlib${ii}$_${ri}$orgbr( 'Q', m, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*n + lwork_qorgbr_q ) end if if( wntua ) then call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*n + lwork_qorgbr_q ) end if if( .not.wntvn ) then maxwrk = max( maxwrk, 3_${ik}$*n + lwork_qorgbr_p ) end if maxwrk = max( maxwrk, bdspac ) minwrk = max( 3_${ik}$*n + m, bdspac ) end if else if( minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_${ri}$bdsqr mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'DGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) bdspac = 5_${ik}$*m ! compute space needed for stdlib${ii}$_${ri}$gelqf call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qgelqf = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ri}$orglq call stdlib${ii}$_${ri}$orglq( n, n, m, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorglq_n = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$orglq( m, n, m, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorglq_m = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ri}$gebrd call stdlib${ii}$_${ri}$gebrd( m, m, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qgebrd = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ri}$orgbr p call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ri}$orgbr q call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgbr_q = int( dum(1_${ik}$),KIND=${ik}$) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') maxwrk = m + lwork_qgelqf maxwrk = max( maxwrk, 3_${ik}$*m + lwork_qgebrd ) if( wntuo .or. wntuas )maxwrk = max( maxwrk, 3_${ik}$*m + lwork_qorgbr_q ) maxwrk = max( maxwrk, bdspac ) minwrk = max( 4_${ik}$*m, bdspac ) else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') wrkbl = m + lwork_qgelqf wrkbl = max( wrkbl, m + lwork_qorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( m*m + wrkbl, m*m + m*n + m ) minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', ! jobvt='o') wrkbl = m + lwork_qgelqf wrkbl = max( wrkbl, m + lwork_qorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = max( m*m + wrkbl, m*m + m*n + m ) minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntvs .and. wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') wrkbl = m + lwork_qgelqf wrkbl = max( wrkbl, m + lwork_qorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntvs .and. wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') wrkbl = m + lwork_qgelqf wrkbl = max( wrkbl, m + lwork_qorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntvs .and. wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') wrkbl = m + lwork_qgelqf wrkbl = max( wrkbl, m + lwork_qorglq_m ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntva .and. wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') wrkbl = m + lwork_qgelqf wrkbl = max( wrkbl, m + lwork_qorglq_n ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_p ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntva .and. wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') wrkbl = m + lwork_qgelqf wrkbl = max( wrkbl, m + lwork_qorglq_n ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) else if( wntva .and. wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') wrkbl = m + lwork_qgelqf wrkbl = max( wrkbl, m + lwork_qorglq_n ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_p ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qorgbr_q ) wrkbl = max( wrkbl, bdspac ) maxwrk = m*m + wrkbl minwrk = max( 3_${ik}$*m + n, bdspac ) end if else ! path 10t(n greater than m, but not much larger) call stdlib${ii}$_${ri}$gebrd( m, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qgebrd = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = 3_${ik}$*m + lwork_qgebrd if( wntvs .or. wntvo ) then ! compute space needed for stdlib${ii}$_${ri}$orgbr p call stdlib${ii}$_${ri}$orgbr( 'P', m, n, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*m + lwork_qorgbr_p ) end if if( wntva ) then call stdlib${ii}$_${ri}$orgbr( 'P', n, n, m, a, n, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgbr_p = int( dum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 3_${ik}$*m + lwork_qorgbr_p ) end if if( .not.wntun ) then maxwrk = max( maxwrk, 3_${ik}$*m + lwork_qorgbr_q ) end if maxwrk = max( maxwrk, bdspac ) minwrk = max( 3_${ik}$*m + n, bdspac ) end if end if maxwrk = max( maxwrk, minwrk ) work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') ! no left singular vectors to be computed itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out below r if( n > 1_${ik}$ ) then call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) ncvt = 0_${ik}$ if( wntvo .or. wntvas ) then ! if right singular vectors desired, generate p'. ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) ncvt = n end if iwork = ie + n ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a if desired ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, ncvt, 0_${ik}$, 0_${ik}$, s, work( ie ), a, lda,dum, 1_${ik}$, dum, 1_${ik}$, & work( iwork ), info ) ! if right singular vectors desired in vt, copy them there if( wntvas )call stdlib${ii}$_${ri}$lacpy( 'F', n, n, a, lda, vt, ldvt ) else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') ! n left singular vectors to be overwritten on a and ! no right singular vectors to be computed if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n + n ) + lda*n ) then ! work(iu) is lda by n, work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n + n ) + n*n ) then ! work(iu) is lda by n, work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n, work(ir) is n by n ldwrku = ( lwork-n*n-n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to work(ir) and zero out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero, work( ir+1 ),ldwrkr ) ! generate q in a ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_${ri}$orgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (workspace: need n*n + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, work( ie ), dum, 1_${ik}$,work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) iu = ie + n ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (workspace: need n*n + 2*n, prefer n*n + m*n + n) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( ir )& , ldwrkr, zero,work( iu ), ldwrku ) call stdlib${ii}$_${ri}$lacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (workspace: need 3*n + m, prefer 3*n + (m + n)*nb) call stdlib${ii}$_${ri}$gebrd( m, n, a, lda, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing a ! (workspace: need 4*n, prefer 3*n + n*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, work( ie ), dum, 1_${ik}$,a, lda, dum, 1_${ik}$, & work( iwork ), info ) end if else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or 'a') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n + n ) + lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n + n ) + n*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n and work(ir) is n by n ldwrku = ( lwork-n*n-n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_${ri}$orgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt, copying result to work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', n, n, vt, ldvt, work( ir ), ldwrkr ) ! generate left vectors bidiagonalizing r in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (workspace: need n*n + 4*n-1, prefer n*n + 3*n + (n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) and computing right ! singular vectors of r in vt ! (workspace: need n*n + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ), vt, ldvt,work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) iu = ie + n ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (workspace: need n*n + 2*n, prefer n*n + m*n + n) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( ir )& , ldwrkr, zero,work( iu ), ldwrku ) call stdlib${ii}$_${ri}$lacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$orgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in a by left vectors bidiagonalizing r ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), a, lda,& work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), vt, ldvt,a, lda, dum, & 1_${ik}$, work( iwork ), info ) end if else if( wntus ) then if( wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') ! n left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,work( ir+1 ), ldwrkr ) ! generate q in a ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_${ri}$orgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (workspace: need n*n + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, work( ie ), dum,1_${ik}$, work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! (workspace: need n*n) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, n, one, a, lda,work( ir ), ldwrkr, & zero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$orgqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, work( ie ), dum,1_${ik}$, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') ! n left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda + n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (workspace: need 2*n*n + 2*n, prefer 2*n*n + n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ! generate q in a ! (workspace: need 2*n*n + 2*n, prefer 2*n*n + n + n*nb) call stdlib${ii}$_${ri}$orgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (workspace: need 2*n*n + 4*n, ! prefer 2*n*n+3*n+2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need 2*n*n + 4*n, prefer 2*n*n + 3*n + n*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (workspace: need 2*n*n + 4*n-1, ! prefer 2*n*n+3*n+(n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (workspace: need 2*n*n + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, dum, 1_${ik}$, work( iwork ), info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (workspace: need n*n) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, n, one, a, lda,work( iu ), ldwrku, & zero, u, ldu ) ! copy right singular vectors of r to a ! (workspace: need n*n) call stdlib${ii}$_${ri}$lacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$orgqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in a ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), a,lda, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' ! or 'a') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ! generate q in a ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_${ri}$orgqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need n*n + 4*n-1, ! prefer n*n+3*n+(n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (workspace: need n*n + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ), vt,ldvt, work( iu ),& ldwrku, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (workspace: need n*n) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, n, one, a, lda,work( iu ), ldwrku, & zero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$orgqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt & ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if else if( wntua ) then if( wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') ! m left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+max( n+m, 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, n, a, lda, u, ldu ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,work( ir+1 ), ldwrkr ) ! generate q in u ! (workspace: need n*n + n + m, prefer n*n + n + m*nb) call stdlib${ii}$_${ri}$orgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (workspace: need n*n + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, work( ie ), dum,1_${ik}$, work( ir ), & ldwrkr, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in u by left singular vectors of r in ! work(ir), storing result in a ! (workspace: need n*n) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, n, one, u, ldu,work( ir ), ldwrkr, & zero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_${ri}$lacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n + m, prefer n + m*nb) call stdlib${ii}$_${ri}$orgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, work( ie ), dum,1_${ik}$, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') ! m left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+max( n+m, 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda + n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n*n + 2*n, prefer 2*n*n + n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need 2*n*n + n + m, prefer 2*n*n + n + m*nb) call stdlib${ii}$_${ri}$orgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (workspace: need 2*n*n + 4*n, ! prefer 2*n*n+3*n+2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need 2*n*n + 4*n, prefer 2*n*n + 3*n + n*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (workspace: need 2*n*n + 4*n-1, ! prefer 2*n*n+3*n+(n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (workspace: need 2*n*n + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, dum, 1_${ik}$, work( iwork ), info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (workspace: need n*n) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, n, one, u, ldu,work( iu ), ldwrku, & zero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_${ri}$lacpy( 'F', m, n, a, lda, u, ldu ) ! copy right singular vectors of r from work(ir) to a call stdlib${ii}$_${ri}$lacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n + m, prefer n + m*nb) call stdlib${ii}$_${ri}$orgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in a ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), a,lda, u, ldu, dum, & 1_${ik}$, work( iwork ),info ) end if else if( wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' ! or 'a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( n+m, 4_${ik}$*n, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need n*n + 2*n, prefer n*n + n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n*n + n + m, prefer n*n + n + m*nb) call stdlib${ii}$_${ri}$orgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,work( iu+1 ), ldwrku ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (workspace: need n*n + 4*n, prefer n*n + 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (workspace: need n*n + 4*n, prefer n*n + 3*n + n*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need n*n + 4*n-1, ! prefer n*n+3*n+(n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (workspace: need n*n + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, n, n, 0_${ik}$, s, work( ie ), vt,ldvt, work( iu ),& ldwrku, dum, 1_${ik}$,work( iwork ), info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (workspace: need n*n) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, n, one, u, ldu,work( iu ), ldwrku, & zero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_${ri}$lacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (workspace: need 2*n, prefer n + n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (workspace: need n + m, prefer n + m*nb) call stdlib${ii}$_${ri}$orgqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r from a to vt, zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero,vt( 2_${ik}$, 1_${ik}$ ), ldvt & ) ie = itau itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (workspace: need 4*n, prefer 3*n + 2*n*nb) call stdlib${ii}$_${ri}$gebrd( n, n, vt, ldvt, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (workspace: need 3*n + m, prefer 3*n + m*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) iwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if end if else ! m < mnthr ! path 10 (m at least n, but not much larger) ! reduce to bidiagonal form without qr decomposition ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (workspace: need 3*n + m, prefer 3*n + (m + n)*nb) call stdlib${ii}$_${ri}$gebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (workspace: need 3*n + ncu, prefer 3*n + ncu*nb) call stdlib${ii}$_${ri}$lacpy( 'L', m, n, a, lda, u, ldu ) if( wntus )ncu = n if( wntua )ncu = m call stdlib${ii}$_${ri}$orgbr( 'Q', m, ncu, n, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (workspace: need 4*n, prefer 3*n + n*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (workspace: need 4*n-1, prefer 3*n + (n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if iwork = ie + n if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, dum,& 1_${ik}$, work( iwork ), info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, work( ie ), a, lda,u, ldu, dum, & 1_${ik}$, work( iwork ), info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, dum,& 1_${ik}$, work( iwork ), info ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') ! no right singular vectors to be computed itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ), lda ) ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuo .or. wntuas ) then ! if left singular vectors desired, generate q ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if iwork = ie + m nru = 0_${ik}$ if( wntuo .or. wntuas )nru = m ! perform bidiagonal qr iteration, computing left singular ! vectors of a in a if desired ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, 0_${ik}$, nru, 0_${ik}$, s, work( ie ), dum, 1_${ik}$, a,lda, dum, 1_${ik}$, & work( iwork ), info ) ! if left singular vectors desired in u, copy them there if( wntuas )call stdlib${ii}$_${ri}$lacpy( 'F', m, m, a, lda, u, ldu ) else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') ! m right singular vectors to be overwritten on a and ! no left singular vectors to be computed if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n + m ) + lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n + m ) + m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m-m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to work(ir) and zero out above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero,work( ir+ldwrkr ), ldwrkr ) ! generate q in a ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_${ri}$orglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l ! (workspace: need m*m + 4*m-1, prefer m*m + 3*m + (m-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (workspace: need m*m + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, dum,& 1_${ik}$, dum, 1_${ik}$,work( iwork ), info ) iu = ie + m ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (workspace: need m*m + 2*m, prefer m*m + m*n + m) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, blk, m, one, work( ir ),ldwrkr, a( 1_${ik}$, i & ), lda, zero,work( iu ), ldwrku ) call stdlib${ii}$_${ri}$lacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (workspace: need 3*m + n, prefer 3*m + (m + n)*nb) call stdlib${ii}$_${ri}$gebrd( m, n, a, lda, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing a ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'L', m, n, 0_${ik}$, 0_${ik}$, s, work( ie ), a, lda,dum, 1_${ik}$, dum, 1_${ik}$, & work( iwork ), info ) end if else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', jobvt='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n + m ) + lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n + m ) + m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m-m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing about above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_${ri}$orglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u, copying result to work(ir) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', m, m, u, ldu, work( ir ), ldwrkr ) ! generate right vectors bidiagonalizing l in work(ir) ! (workspace: need m*m + 4*m-1, prefer m*m + 3*m + (m-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (workspace: need m*m + 4*m, prefer m*m + 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u, and computing right ! singular vectors of l in work(ir) ! (workspace: need m*m + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, u, & ldu, dum, 1_${ik}$,work( iwork ), info ) iu = ie + m ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (workspace: need m*m + 2*m, prefer m*m + m*n + m)) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, blk, m, one, work( ir ),ldwrkr, a( 1_${ik}$, i & ), lda, zero,work( iu ), ldwrku ) call stdlib${ii}$_${ri}$lacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$orglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( itaup & ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in a ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_${ri}$ormbr( 'P', 'L', 'T', m, n, m, u, ldu,work( itaup ), a, lda, & work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), a, lda,u, ldu, dum, 1_${ik}$, & work( iwork ), info ) end if else if( wntvs ) then if( wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') ! m right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero,work( ir+ldwrkr ), ldwrkr & ) ! generate q in a ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_${ri}$orglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l in ! work(ir) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + (m-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (workspace: need m*m + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & dum, 1_${ik}$, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in a, storing result in vt ! (workspace: need m*m) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, m, one, work( ir ),ldwrkr, a, lda, & zero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy result to vt call stdlib${ii}$_${ri}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$orglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_${ri}$ormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, work( ie ), vt,ldvt, dum, 1_${ik}$, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda + m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (workspace: need 2*m*m + 2*m, prefer 2*m*m + m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ! generate q in a ! (workspace: need 2*m*m + 2*m, prefer 2*m*m + m + m*nb) call stdlib${ii}$_${ri}$orglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (workspace: need 2*m*m + 4*m, ! prefer 2*m*m+3*m+2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need 2*m*m + 4*m-1, ! prefer 2*m*m+3*m+(m-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (workspace: need 2*m*m + 4*m, prefer 2*m*m + 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (workspace: need 2*m*m + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, dum, 1_${ik}$, work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (workspace: need m*m) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, a, lda, & zero, vt, ldvt ) ! copy left singular vectors of l to a ! (workspace: need m*m) call stdlib${ii}$_${ri}$lacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$orglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_${ri}$ormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors of l in a ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, compute left ! singular vectors of a in a and compute right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+max( 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is lda by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ! generate q in a ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_${ri}$orglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need m*m + 4*m-1, ! prefer m*m+3*m+(m-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need m*m + 4*m, prefer m*m + 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (workspace: need m*m + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & u, ldu, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (workspace: need m*m) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, a, lda, & zero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$orglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_${ri}$ormbr( 'P', 'L', 'T', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if else if( wntva ) then if( wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') ! n right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+max( n + m, 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero,work( ir+ldwrkr ), ldwrkr & ) ! generate q in vt ! (workspace: need m*m + m + n, prefer m*m + m + n*nb) call stdlib${ii}$_${ri}$orglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, work( ir ), ldwrkr, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (workspace: need m*m + 4*m-1, ! prefer m*m+3*m+(m-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (workspace: need m*m + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, work( ie ),work( ir ), ldwrkr, & dum, 1_${ik}$, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in vt, storing result in a ! (workspace: need m*m) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, m, one, work( ir ),ldwrkr, vt, ldvt, & zero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_${ri}$lacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m + n, prefer m + n*nb) call stdlib${ii}$_${ri}$orglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_${ri}$ormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, work( ie ), vt,ldvt, dum, 1_${ik}$, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+max( n + m, 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda + m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m*m + 2*m, prefer 2*m*m + m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need 2*m*m + m + n, prefer 2*m*m + m + n*nb) call stdlib${ii}$_${ri}$orglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (workspace: need 2*m*m + 4*m, ! prefer 2*m*m+3*m+2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need 2*m*m + 4*m-1, ! prefer 2*m*m+3*m+(m-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (workspace: need 2*m*m + 4*m, prefer 2*m*m + 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (workspace: need 2*m*m + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, dum, 1_${ik}$, work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (workspace: need m*m) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, vt, ldvt, & zero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_${ri}$lacpy( 'F', m, n, a, lda, vt, ldvt ) ! copy left singular vectors of a from work(ir) to a call stdlib${ii}$_${ri}$lacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m + n, prefer m + n*nb) call stdlib${ii}$_${ri}$orglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ),lda ) ! bidiagonalize l in a ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, a, lda, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_${ri}$ormbr( 'P', 'L', 'T', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in a ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, & dum, 1_${ik}$, work( iwork ),info ) end if else if( wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+max( n + m, 4_${ik}$*m, bdspac ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by m ldwrku = lda else ! work(iu) is m by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need m*m + 2*m, prefer m*m + m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m*m + m + n, prefer m*m + m + n*nb) call stdlib${ii}$_${ri}$orglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero,work( iu+ldwrku ), ldwrku & ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (workspace: need m*m + 4*m, prefer m*m + 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, work( iu ), ldwrku, s,work( ie ), work( itauq & ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (workspace: need m*m + 4*m, prefer m*m + 3*m + (m-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need m*m + 4*m, prefer m*m + 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (workspace: need m*m + bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, m, m, 0_${ik}$, s, work( ie ),work( iu ), ldwrku, & u, ldu, dum, 1_${ik}$,work( iwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (workspace: need m*m) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, m, one, work( iu ),ldwrku, vt, ldvt, & zero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_${ri}$lacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (workspace: need 2*m, prefer m + m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (workspace: need m + n, prefer m + n*nb) call stdlib${ii}$_${ri}$orglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ie = itau itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (workspace: need 4*m, prefer 3*m + 2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, u, ldu, s, work( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (workspace: need 3*m + n, prefer 3*m + n*nb) call stdlib${ii}$_${ri}$ormbr( 'P', 'L', 'T', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) iwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, n, m, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, & dum, 1_${ik}$, work( iwork ),info ) end if end if end if else ! n < mnthr ! path 10t(n greater than m, but not much larger) ! reduce to bidiagonal form without lq decomposition ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (workspace: need 3*m + n, prefer 3*m + (m + n)*nb) call stdlib${ii}$_${ri}$gebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (workspace: need 4*m-1, prefer 3*m + (m-1)*nb) call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, n, u, ldu, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (workspace: need 3*m + nrvt, prefer 3*m + nrvt*nb) call stdlib${ii}$_${ri}$lacpy( 'U', m, n, a, lda, vt, ldvt ) if( wntva )nrvt = n if( wntvs )nrvt = m call stdlib${ii}$_${ri}$orgbr( 'P', nrvt, n, m, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (workspace: need 4*m-1, prefer 3*m + (m-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'Q', m, m, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (workspace: need 4*m, prefer 3*m + m*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if iwork = ie + m if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, u, ldu, dum,& 1_${ik}$, work( iwork ), info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, work( ie ), a, lda,u, ldu, dum, & 1_${ik}$, work( iwork ), info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, work( ie ), vt,ldvt, a, lda, dum,& 1_${ik}$, work( iwork ), info ) end if end if end if ! if stdlib${ii}$_${ri}$bdsqr failed to converge, copy unconverged superdiagonals ! to work( 2:minmn ) if( info/=0_${ik}$ ) then if( ie>2_${ik}$ ) then do i = 1, minmn - 1 work( i+1 ) = work( i+ie-1 ) end do end if if( ie<2_${ik}$ ) then do i = minmn - 1, 1, -1 work( i+1 ) = work( i+ie-1 ) end do end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( info/=0_${ik}$ .and. anrm>bignum )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn-1,& 1_${ik}$, work( 2_${ik}$ ),minmn, ierr ) if( anrm=n .and. minmn>0_${ik}$ ) then ! space needed for stdlib${ii}$_zbdsqr is bdspac = 5*n mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'CGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) ! compute space needed for stdlib${ii}$_cgeqrf call stdlib${ii}$_cgeqrf( m, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cgeqrf = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_cungqr call stdlib${ii}$_cungqr( m, n, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cungqr_n = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cungqr( m, m, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cungqr_m = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_cgebrd call stdlib${ii}$_cgebrd( n, n, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cgebrd = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_cungbr call stdlib${ii}$_cungbr( 'P', n, n, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cungbr( 'Q', n, n, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'CGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') maxwrk = n + lwork_cgeqrf maxwrk = max( maxwrk, 2_${ik}$*n+lwork_cgebrd ) if( wntvo .or. wntvas )maxwrk = max( maxwrk, 2_${ik}$*n+lwork_cungbr_p ) minwrk = 3_${ik}$*n else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') wrkbl = n + lwork_cgeqrf wrkbl = max( wrkbl, n+lwork_cungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_q ) maxwrk = max( n*n+wrkbl, n*n+m*n ) minwrk = 2_${ik}$*n + m else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or ! 'a') wrkbl = n + lwork_cgeqrf wrkbl = max( wrkbl, n+lwork_cungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_p ) maxwrk = max( n*n+wrkbl, n*n+m*n ) minwrk = 2_${ik}$*n + m else if( wntus .and. wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') wrkbl = n + lwork_cgeqrf wrkbl = max( wrkbl, n+lwork_cungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_q ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntus .and. wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') wrkbl = n + lwork_cgeqrf wrkbl = max( wrkbl, n+lwork_cungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_p ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntus .and. wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' or ! 'a') wrkbl = n + lwork_cgeqrf wrkbl = max( wrkbl, n+lwork_cungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_p ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntua .and. wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') wrkbl = n + lwork_cgeqrf wrkbl = max( wrkbl, n+lwork_cungqr_m ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_q ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntua .and. wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') wrkbl = n + lwork_cgeqrf wrkbl = max( wrkbl, n+lwork_cungqr_m ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_p ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntua .and. wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' or ! 'a') wrkbl = n + lwork_cgeqrf wrkbl = max( wrkbl, n+lwork_cungqr_m ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_cungbr_p ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m end if else ! path 10 (m at least n, but not much larger) call stdlib${ii}$_cgebrd( m, n, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, & ierr ) lwork_cgebrd = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = 2_${ik}$*n + lwork_cgebrd if( wntus .or. wntuo ) then call stdlib${ii}$_cungbr( 'Q', m, n, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*n+lwork_cungbr_q ) end if if( wntua ) then call stdlib${ii}$_cungbr( 'Q', m, m, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*n+lwork_cungbr_q ) end if if( .not.wntvn ) then maxwrk = max( maxwrk, 2_${ik}$*n+lwork_cungbr_p ) end if minwrk = 2_${ik}$*n + m end if else if( minmn>0_${ik}$ ) then ! space needed for stdlib${ii}$_cbdsqr is bdspac = 5*m mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'CGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) ! compute space needed for stdlib${ii}$_cgelqf call stdlib${ii}$_cgelqf( m, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cgelqf = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_cunglq call stdlib${ii}$_cunglq( n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$,ierr ) lwork_cunglq_n = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cunglq( m, n, m, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cunglq_m = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_cgebrd call stdlib${ii}$_cgebrd( m, m, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cgebrd = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_cungbr p call stdlib${ii}$_cungbr( 'P', m, m, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_cungbr q call stdlib${ii}$_cungbr( 'Q', m, m, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') maxwrk = m + lwork_cgelqf maxwrk = max( maxwrk, 2_${ik}$*m+lwork_cgebrd ) if( wntuo .or. wntuas )maxwrk = max( maxwrk, 2_${ik}$*m+lwork_cungbr_q ) minwrk = 3_${ik}$*m else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') wrkbl = m + lwork_cgelqf wrkbl = max( wrkbl, m+lwork_cunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_p ) maxwrk = max( m*m+wrkbl, m*m+m*n ) minwrk = 2_${ik}$*m + n else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', ! jobvt='o') wrkbl = m + lwork_cgelqf wrkbl = max( wrkbl, m+lwork_cunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_q ) maxwrk = max( m*m+wrkbl, m*m+m*n ) minwrk = 2_${ik}$*m + n else if( wntvs .and. wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') wrkbl = m + lwork_cgelqf wrkbl = max( wrkbl, m+lwork_cunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_p ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntvs .and. wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') wrkbl = m + lwork_cgelqf wrkbl = max( wrkbl, m+lwork_cunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_q ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntvs .and. wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') wrkbl = m + lwork_cgelqf wrkbl = max( wrkbl, m+lwork_cunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_q ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntva .and. wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') wrkbl = m + lwork_cgelqf wrkbl = max( wrkbl, m+lwork_cunglq_n ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_p ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntva .and. wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') wrkbl = m + lwork_cgelqf wrkbl = max( wrkbl, m+lwork_cunglq_n ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_q ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntva .and. wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') wrkbl = m + lwork_cgelqf wrkbl = max( wrkbl, m+lwork_cunglq_n ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_cungbr_q ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n end if else ! path 10t(n greater than m, but not much larger) call stdlib${ii}$_cgebrd( m, n, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, & ierr ) lwork_cgebrd = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = 2_${ik}$*m + lwork_cgebrd if( wntvs .or. wntvo ) then ! compute space needed for stdlib${ii}$_cungbr p call stdlib${ii}$_cungbr( 'P', m, n, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*m+lwork_cungbr_p ) end if if( wntva ) then call stdlib${ii}$_cungbr( 'P', n, n, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*m+lwork_cungbr_p ) end if if( .not.wntun ) then maxwrk = max( maxwrk, 2_${ik}$*m+lwork_cungbr_q ) end if minwrk = 2_${ik}$*m + n end if end if maxwrk = max( minwrk, maxwrk ) work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') ! no left singular vectors to be computed itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: need 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out below r if( n > 1_${ik}$ ) then call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( iwork ), lwork-iwork+1,ierr ) ncvt = 0_${ik}$ if( wntvo .or. wntvas ) then ! if right singular vectors desired, generate p'. ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) ncvt = n end if irwork = ie + n ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a if desired ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, ncvt, 0_${ik}$, 0_${ik}$, s, rwork( ie ), a, lda,cdum, 1_${ik}$, cdum, & 1_${ik}$, rwork( irwork ), info ) ! if right singular vectors desired in vt, copy them there if( wntvas )call stdlib${ii}$_clacpy( 'F', n, n, a, lda, vt, ldvt ) else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') ! n left singular vectors to be overwritten on a and ! no right singular vectors to be computed if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*n ) then ! work(iu) is lda by n, work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+n*n ) then ! work(iu) is lda by n, work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n, work(ir) is n by n ldwrku = ( lwork-n*n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to work(ir) and zero out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,work( ir+1 ), ldwrkr ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ),& work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: need 0) call stdlib${ii}$_cungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, rwork( ie ), cdum, 1_${ik}$,work( ir ), & ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (cworkspace: need n*n+n, prefer n*n+m*n) ! (rworkspace: 0) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_cgemm( 'N', 'N', chunk, n, n, cone, a( i, 1_${ik}$ ),lda, work( ir & ), ldwrkr, czero,work( iu ), ldwrku ) call stdlib${ii}$_clacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (cworkspace: need 2*n+m, prefer 2*n+(m+n)*nb) ! (rworkspace: n) call stdlib${ii}$_cgebrd( m, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing a ! (cworkspace: need 3*n, prefer 2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a ! (cworkspace: need 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, rwork( ie ), cdum, 1_${ik}$,a, lda, cdum, & 1_${ik}$, rwork( irwork ), info ) end if else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or 'a') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+n*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n and work(ir) is n by n ldwrku = ( lwork-n*n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt, copying result to work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', n, n, vt, ldvt, work( ir ), ldwrkr ) ! generate left vectors bidiagonalizing r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (cworkspace: need n*n+3*n-1, prefer n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) and computing right ! singular vectors of r in vt ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ), vt,ldvt, work( ir ), & ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (cworkspace: need n*n+n, prefer n*n+m*n) ! (rworkspace: 0) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_cgemm( 'N', 'N', chunk, n, n, cone, a( i, 1_${ik}$ ),lda, work( ir & ), ldwrkr, czero,work( iu ), ldwrku ) call stdlib${ii}$_clacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: n) call stdlib${ii}$_cgebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in a by left vectors bidiagonalizing r ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), a, lda,& work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, cdum,& 1_${ik}$, rwork( irwork ),info ) end if else if( wntus ) then if( wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') ! n left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,work( ir+1 ), ldwrkr ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, work( ir ),& ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, n, cone, a, lda,work( ir ), ldwrkr, & czero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') ! n left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+3*n ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda+n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ! generate q in a ! (cworkspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*n*n+3*n, ! prefer 2*n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*n*n+3*n, prefer 2*n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*n*n+3*n-1, ! prefer 2*n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (cworkspace: need 2*n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, n, cone, a, lda,work( iu ), ldwrku, & czero, u, ldu ) ! copy right singular vectors of r to a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_clacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' ! or 'a') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need n*n+3*n-1, ! prefer n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ), vt,ldvt, work( iu )& , ldwrku, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, n, cone, a, lda,work( iu ), ldwrku, & czero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), & ldvt ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if else if( wntua ) then if( wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') ! m left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+max( n+m, 3_${ik}$*n ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,work( ir+1 ), ldwrkr ) ! generate q in u ! (cworkspace: need n*n+n+m, prefer n*n+n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, work( ir ),& ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in u by left singular vectors of r in ! work(ir), storing result in a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, n, cone, u, ldu,work( ir ), ldwrkr, & czero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_clacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n+m, prefer n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') ! m left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+max( n+m, 3_${ik}$*n ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda+n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n*n+n+m, prefer 2*n*n+n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*n*n+3*n, ! prefer 2*n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*n*n+3*n, prefer 2*n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*n*n+3*n-1, ! prefer 2*n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (cworkspace: need 2*n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, n, cone, u, ldu,work( iu ), ldwrku, & czero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_clacpy( 'F', m, n, a, lda, u, ldu ) ! copy right singular vectors of r from work(ir) to a call stdlib${ii}$_clacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n+m, prefer n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' ! or 'a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( n+m, 3_${ik}$*n ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n*n+n+m, prefer n*n+n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need n*n+3*n-1, ! prefer n*n+2*n+(n-1)*nb) ! (rworkspace: need 0) call stdlib${ii}$_cungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ), vt,ldvt, work( iu )& , ldwrku, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, n, cone, u, ldu,work( iu ), ldwrku, & czero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_clacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n+m, prefer n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r from a to vt, zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), & ldvt ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if end if else ! m < mnthr ! path 10 (m at least n, but not much larger) ! reduce to bidiagonal form without qr decomposition ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (cworkspace: need 2*n+m, prefer 2*n+(m+n)*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (cworkspace: need 2*n+ncu, prefer 2*n+ncu*nb) ! (rworkspace: 0) call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) if( wntus )ncu = n if( wntua )ncu = m call stdlib${ii}$_cungbr( 'Q', m, ncu, n, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_clacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_cungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (cworkspace: need 3*n, prefer 2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if irwork = ie + n if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, cdum,& 1_${ik}$, rwork( irwork ),info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$, rwork( irwork ),info ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') ! no right singular vectors to be computed itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero, a( 1_${ik}$, 2_${ik}$ ),lda ) ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( iwork ), lwork-iwork+1,ierr ) if( wntuo .or. wntuas ) then ! if left singular vectors desired, generate q ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if irwork = ie + m nru = 0_${ik}$ if( wntuo .or. wntuas )nru = m ! perform bidiagonal qr iteration, computing left singular ! vectors of a in a if desired ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, 0_${ik}$, nru, 0_${ik}$, s, rwork( ie ), cdum, 1_${ik}$,a, lda, cdum, & 1_${ik}$, rwork( irwork ), info ) ! if left singular vectors desired in u, copy them there if( wntuas )call stdlib${ii}$_clacpy( 'F', m, m, a, lda, u, ldu ) else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') ! m right singular vectors to be overwritten on a and ! no left singular vectors to be computed if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to work(ir) and zero out above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,work( ir+ldwrkr ), ldwrkr ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ),& work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l ! (cworkspace: need m*m+3*m-1, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & cdum, 1_${ik}$, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (cworkspace: need m*m+m, prefer m*m+m*n) ! (rworkspace: 0) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_cgemm( 'N', 'N', m, blk, m, cone, work( ir ),ldwrkr, a( 1_${ik}$, & i ), lda, czero,work( iu ), ldwrku ) call stdlib${ii}$_clacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (cworkspace: need 2*m+n, prefer 2*m+(m+n)*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'L', m, n, 0_${ik}$, 0_${ik}$, s, rwork( ie ), a, lda,cdum, 1_${ik}$, cdum, & 1_${ik}$, rwork( irwork ), info ) end if else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', jobvt='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing about above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u, copying result to work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', m, m, u, ldu, work( ir ), ldwrkr ) ! generate right vectors bidiagonalizing l in work(ir) ! (cworkspace: need m*m+3*m-1, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u, and computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, u, & ldu, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (cworkspace: need m*m+m, prefer m*m+m*n)) ! (rworkspace: 0) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_cgemm( 'N', 'N', m, blk, m, cone, work( ir ),ldwrkr, a( 1_${ik}$, & i ), lda, czero,work( iu ), ldwrku ) call stdlib${ii}$_clacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in a ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'P', 'L', 'C', m, n, m, u, ldu,work( itaup ), a, lda, & work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), a, lda,u, ldu, cdum, & 1_${ik}$, rwork( irwork ), info ) end if else if( wntvs ) then if( wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') ! m right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,work( ir+ldwrkr ), & ldwrkr ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l in ! work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & cdum, 1_${ik}$, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in a, storing result in vt ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, m, cone, work( ir ),ldwrkr, a, lda, & czero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy result to vt call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, rwork( ie ), vt,ldvt, cdum, 1_${ik}$, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+3*m ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda+m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out below it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ! generate q in a ! (cworkspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*m*m+3*m, ! prefer 2*m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*m*m+3*m-1, ! prefer 2*m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*m*m+3*m, prefer 2*m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (cworkspace: need 2*m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, a, lda, & czero, vt, ldvt ) ! copy left singular vectors of l to a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_clacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors of l in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is lda by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need m*m+3*m-1, ! prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & u, ldu, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, a, lda, & czero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,u( 1_${ik}$, 2_${ik}$ ), ldu ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'P', 'L', 'C', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if else if( wntva ) then if( wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') ! n right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+max( n+m, 3_${ik}$*m ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,work( ir+ldwrkr ), & ldwrkr ) ! generate q in vt ! (cworkspace: need m*m+m+n, prefer m*m+m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (cworkspace: need m*m+3*m-1, ! prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & cdum, 1_${ik}$, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in vt, storing result in a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, m, cone, work( ir ),ldwrkr, vt, ldvt,& czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_clacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m+n, prefer m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, rwork( ie ), vt,ldvt, cdum, 1_${ik}$, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+max( n+m, 3_${ik}$*m ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda+m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m*m+m+n, prefer 2*m*m+m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*m*m+3*m, ! prefer 2*m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*m*m+3*m-1, ! prefer 2*m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*m*m+3*m, prefer 2*m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (cworkspace: need 2*m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, vt, ldvt,& czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_clacpy( 'F', m, n, a, lda, vt, ldvt ) ! copy left singular vectors of a from work(ir) to a call stdlib${ii}$_clacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m+n, prefer m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+max( n+m, 3_${ik}$*m ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by m ldwrku = lda else ! work(iu) is m by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m*m+m+n, prefer m*m+m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_clacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & u, ldu, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_cgemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, vt, ldvt,& czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_clacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m+n, prefer m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,u( 1_${ik}$, 2_${ik}$ ), ldu ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_cunmbr( 'P', 'L', 'C', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if end if else ! n < mnthr ! path 10t(n greater than m, but not much larger) ! reduce to bidiagonal form without lq decomposition ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (cworkspace: need 2*m+n, prefer 2*m+(m+n)*nb) ! (rworkspace: m) call stdlib${ii}$_cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (cworkspace: need 3*m-1, prefer 2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_clacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_cungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (cworkspace: need 2*m+nrvt, prefer 2*m+nrvt*nb) ! (rworkspace: 0) call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) if( wntva )nrvt = n if( wntvs )nrvt = m call stdlib${ii}$_cungbr( 'P', nrvt, n, m, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (cworkspace: need 3*m-1, prefer 2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'Q', m, m, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_cungbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if irwork = ie + m if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, cdum,& 1_${ik}$, rwork( irwork ),info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$, rwork( irwork ),info ) end if end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( info/=0_${ik}$ .and. anrm>bignum )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn-1,& 1_${ik}$,rwork( ie ), minmn, ierr ) if( anrm=n .and. minmn>0_${ik}$ ) then ! space needed for stdlib${ii}$_zbdsqr is bdspac = 5*n mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'ZGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) ! compute space needed for stdlib${ii}$_zgeqrf call stdlib${ii}$_zgeqrf( m, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zgeqrf = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_zungqr call stdlib${ii}$_zungqr( m, n, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zungqr_n = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zungqr( m, m, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zungqr_m = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_zgebrd call stdlib${ii}$_zgebrd( n, n, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zgebrd = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_zungbr call stdlib${ii}$_zungbr( 'P', n, n, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zungbr( 'Q', n, n, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') maxwrk = n + lwork_zgeqrf maxwrk = max( maxwrk, 2_${ik}$*n+lwork_zgebrd ) if( wntvo .or. wntvas )maxwrk = max( maxwrk, 2_${ik}$*n+lwork_zungbr_p ) minwrk = 3_${ik}$*n else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') wrkbl = n + lwork_zgeqrf wrkbl = max( wrkbl, n+lwork_zungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_q ) maxwrk = max( n*n+wrkbl, n*n+m*n ) minwrk = 2_${ik}$*n + m else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or ! 'a') wrkbl = n + lwork_zgeqrf wrkbl = max( wrkbl, n+lwork_zungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_p ) maxwrk = max( n*n+wrkbl, n*n+m*n ) minwrk = 2_${ik}$*n + m else if( wntus .and. wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') wrkbl = n + lwork_zgeqrf wrkbl = max( wrkbl, n+lwork_zungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_q ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntus .and. wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') wrkbl = n + lwork_zgeqrf wrkbl = max( wrkbl, n+lwork_zungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_p ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntus .and. wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' or ! 'a') wrkbl = n + lwork_zgeqrf wrkbl = max( wrkbl, n+lwork_zungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_p ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntua .and. wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') wrkbl = n + lwork_zgeqrf wrkbl = max( wrkbl, n+lwork_zungqr_m ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_q ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntua .and. wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') wrkbl = n + lwork_zgeqrf wrkbl = max( wrkbl, n+lwork_zungqr_m ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_p ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntua .and. wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' or ! 'a') wrkbl = n + lwork_zgeqrf wrkbl = max( wrkbl, n+lwork_zungqr_m ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_zungbr_p ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m end if else ! path 10 (m at least n, but not much larger) call stdlib${ii}$_zgebrd( m, n, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, & ierr ) lwork_zgebrd = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = 2_${ik}$*n + lwork_zgebrd if( wntus .or. wntuo ) then call stdlib${ii}$_zungbr( 'Q', m, n, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*n+lwork_zungbr_q ) end if if( wntua ) then call stdlib${ii}$_zungbr( 'Q', m, m, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*n+lwork_zungbr_q ) end if if( .not.wntvn ) then maxwrk = max( maxwrk, 2_${ik}$*n+lwork_zungbr_p ) end if minwrk = 2_${ik}$*n + m end if else if( minmn>0_${ik}$ ) then ! space needed for stdlib${ii}$_zbdsqr is bdspac = 5*m mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'ZGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) ! compute space needed for stdlib${ii}$_zgelqf call stdlib${ii}$_zgelqf( m, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zgelqf = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_zunglq call stdlib${ii}$_zunglq( n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$,ierr ) lwork_zunglq_n = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zunglq( m, n, m, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zunglq_m = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_zgebrd call stdlib${ii}$_zgebrd( m, m, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zgebrd = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_zungbr p call stdlib${ii}$_zungbr( 'P', m, m, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_zungbr q call stdlib${ii}$_zungbr( 'Q', m, m, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') maxwrk = m + lwork_zgelqf maxwrk = max( maxwrk, 2_${ik}$*m+lwork_zgebrd ) if( wntuo .or. wntuas )maxwrk = max( maxwrk, 2_${ik}$*m+lwork_zungbr_q ) minwrk = 3_${ik}$*m else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') wrkbl = m + lwork_zgelqf wrkbl = max( wrkbl, m+lwork_zunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_p ) maxwrk = max( m*m+wrkbl, m*m+m*n ) minwrk = 2_${ik}$*m + n else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', ! jobvt='o') wrkbl = m + lwork_zgelqf wrkbl = max( wrkbl, m+lwork_zunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_q ) maxwrk = max( m*m+wrkbl, m*m+m*n ) minwrk = 2_${ik}$*m + n else if( wntvs .and. wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') wrkbl = m + lwork_zgelqf wrkbl = max( wrkbl, m+lwork_zunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_p ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntvs .and. wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') wrkbl = m + lwork_zgelqf wrkbl = max( wrkbl, m+lwork_zunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_q ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntvs .and. wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') wrkbl = m + lwork_zgelqf wrkbl = max( wrkbl, m+lwork_zunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_q ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntva .and. wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') wrkbl = m + lwork_zgelqf wrkbl = max( wrkbl, m+lwork_zunglq_n ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_p ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntva .and. wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') wrkbl = m + lwork_zgelqf wrkbl = max( wrkbl, m+lwork_zunglq_n ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_q ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntva .and. wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') wrkbl = m + lwork_zgelqf wrkbl = max( wrkbl, m+lwork_zunglq_n ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_zungbr_q ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n end if else ! path 10t(n greater than m, but not much larger) call stdlib${ii}$_zgebrd( m, n, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, & ierr ) lwork_zgebrd = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = 2_${ik}$*m + lwork_zgebrd if( wntvs .or. wntvo ) then ! compute space needed for stdlib${ii}$_zungbr p call stdlib${ii}$_zungbr( 'P', m, n, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*m+lwork_zungbr_p ) end if if( wntva ) then call stdlib${ii}$_zungbr( 'P', n, n, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*m+lwork_zungbr_p ) end if if( .not.wntun ) then maxwrk = max( maxwrk, 2_${ik}$*m+lwork_zungbr_q ) end if minwrk = 2_${ik}$*m + n end if end if maxwrk = max( maxwrk, minwrk ) work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') ! no left singular vectors to be computed itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: need 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out below r if( n > 1_${ik}$ ) then call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( iwork ), lwork-iwork+1,ierr ) ncvt = 0_${ik}$ if( wntvo .or. wntvas ) then ! if right singular vectors desired, generate p'. ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) ncvt = n end if irwork = ie + n ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a if desired ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, ncvt, 0_${ik}$, 0_${ik}$, s, rwork( ie ), a, lda,cdum, 1_${ik}$, cdum, & 1_${ik}$, rwork( irwork ), info ) ! if right singular vectors desired in vt, copy them there if( wntvas )call stdlib${ii}$_zlacpy( 'F', n, n, a, lda, vt, ldvt ) else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') ! n left singular vectors to be overwritten on a and ! no right singular vectors to be computed if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*n ) then ! work(iu) is lda by n, work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+n*n ) then ! work(iu) is lda by n, work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n, work(ir) is n by n ldwrku = ( lwork-n*n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to work(ir) and zero out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,work( ir+1 ), ldwrkr ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ),& work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: need 0) call stdlib${ii}$_zungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, rwork( ie ), cdum, 1_${ik}$,work( ir ), & ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (cworkspace: need n*n+n, prefer n*n+m*n) ! (rworkspace: 0) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_zgemm( 'N', 'N', chunk, n, n, cone, a( i, 1_${ik}$ ),lda, work( ir & ), ldwrkr, czero,work( iu ), ldwrku ) call stdlib${ii}$_zlacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (cworkspace: need 2*n+m, prefer 2*n+(m+n)*nb) ! (rworkspace: n) call stdlib${ii}$_zgebrd( m, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing a ! (cworkspace: need 3*n, prefer 2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a ! (cworkspace: need 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, rwork( ie ), cdum, 1_${ik}$,a, lda, cdum, & 1_${ik}$, rwork( irwork ), info ) end if else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or 'a') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+n*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n and work(ir) is n by n ldwrku = ( lwork-n*n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt, copying result to work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', n, n, vt, ldvt, work( ir ), ldwrkr ) ! generate left vectors bidiagonalizing r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (cworkspace: need n*n+3*n-1, prefer n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) and computing right ! singular vectors of r in vt ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ), vt,ldvt, work( ir ), & ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (cworkspace: need n*n+n, prefer n*n+m*n) ! (rworkspace: 0) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_zgemm( 'N', 'N', chunk, n, n, cone, a( i, 1_${ik}$ ),lda, work( ir & ), ldwrkr, czero,work( iu ), ldwrku ) call stdlib${ii}$_zlacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: n) call stdlib${ii}$_zgebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in a by left vectors bidiagonalizing r ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), a, lda,& work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, cdum,& 1_${ik}$, rwork( irwork ),info ) end if else if( wntus ) then if( wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') ! n left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,work( ir+1 ), ldwrkr ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, work( ir ),& ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, n, cone, a, lda,work( ir ), ldwrkr, & czero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') ! n left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+3*n ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda+n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ! generate q in a ! (cworkspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*n*n+3*n, ! prefer 2*n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*n*n+3*n, prefer 2*n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*n*n+3*n-1, ! prefer 2*n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (cworkspace: need 2*n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, n, cone, a, lda,work( iu ), ldwrku, & czero, u, ldu ) ! copy right singular vectors of r to a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_zlacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' ! or 'a') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need n*n+3*n-1, ! prefer n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ), vt,ldvt, work( iu )& , ldwrku, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, n, cone, a, lda,work( iu ), ldwrku, & czero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), & ldvt ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if else if( wntua ) then if( wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') ! m left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+max( n+m, 3_${ik}$*n ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,work( ir+1 ), ldwrkr ) ! generate q in u ! (cworkspace: need n*n+n+m, prefer n*n+n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, work( ir ),& ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in u by left singular vectors of r in ! work(ir), storing result in a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, n, cone, u, ldu,work( ir ), ldwrkr, & czero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n+m, prefer n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') ! m left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+max( n+m, 3_${ik}$*n ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda+n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n*n+n+m, prefer 2*n*n+n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*n*n+3*n, ! prefer 2*n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*n*n+3*n, prefer 2*n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*n*n+3*n-1, ! prefer 2*n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (cworkspace: need 2*n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, n, cone, u, ldu,work( iu ), ldwrku, & czero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, u, ldu ) ! copy right singular vectors of r from work(ir) to a call stdlib${ii}$_zlacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n+m, prefer n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' ! or 'a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( n+m, 3_${ik}$*n ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n*n+n+m, prefer n*n+n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need n*n+3*n-1, ! prefer n*n+2*n+(n-1)*nb) ! (rworkspace: need 0) call stdlib${ii}$_zungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ), vt,ldvt, work( iu )& , ldwrku, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, n, cone, u, ldu,work( iu ), ldwrku, & czero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n+m, prefer n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r from a to vt, zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), & ldvt ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if end if else ! m < mnthr ! path 10 (m at least n, but not much larger) ! reduce to bidiagonal form without qr decomposition ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (cworkspace: need 2*n+m, prefer 2*n+(m+n)*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (cworkspace: need 2*n+ncu, prefer 2*n+ncu*nb) ! (rworkspace: 0) call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) if( wntus )ncu = n if( wntua )ncu = m call stdlib${ii}$_zungbr( 'Q', m, ncu, n, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_zungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (cworkspace: need 3*n, prefer 2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if irwork = ie + n if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, cdum,& 1_${ik}$, rwork( irwork ),info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$, rwork( irwork ),info ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') ! no right singular vectors to be computed itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero, a( 1_${ik}$, 2_${ik}$ ),lda ) ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( iwork ), lwork-iwork+1,ierr ) if( wntuo .or. wntuas ) then ! if left singular vectors desired, generate q ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if irwork = ie + m nru = 0_${ik}$ if( wntuo .or. wntuas )nru = m ! perform bidiagonal qr iteration, computing left singular ! vectors of a in a if desired ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, 0_${ik}$, nru, 0_${ik}$, s, rwork( ie ), cdum, 1_${ik}$,a, lda, cdum, & 1_${ik}$, rwork( irwork ), info ) ! if left singular vectors desired in u, copy them there if( wntuas )call stdlib${ii}$_zlacpy( 'F', m, m, a, lda, u, ldu ) else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') ! m right singular vectors to be overwritten on a and ! no left singular vectors to be computed if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to work(ir) and zero out above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,work( ir+ldwrkr ), ldwrkr ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ),& work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l ! (cworkspace: need m*m+3*m-1, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & cdum, 1_${ik}$, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (cworkspace: need m*m+m, prefer m*m+m*n) ! (rworkspace: 0) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_zgemm( 'N', 'N', m, blk, m, cone, work( ir ),ldwrkr, a( 1_${ik}$, & i ), lda, czero,work( iu ), ldwrku ) call stdlib${ii}$_zlacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (cworkspace: need 2*m+n, prefer 2*m+(m+n)*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'L', m, n, 0_${ik}$, 0_${ik}$, s, rwork( ie ), a, lda,cdum, 1_${ik}$, cdum, & 1_${ik}$, rwork( irwork ), info ) end if else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', jobvt='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing about above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u, copying result to work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', m, m, u, ldu, work( ir ), ldwrkr ) ! generate right vectors bidiagonalizing l in work(ir) ! (cworkspace: need m*m+3*m-1, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u, and computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, u, & ldu, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (cworkspace: need m*m+m, prefer m*m+m*n)) ! (rworkspace: 0) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_zgemm( 'N', 'N', m, blk, m, cone, work( ir ),ldwrkr, a( 1_${ik}$, & i ), lda, czero,work( iu ), ldwrku ) call stdlib${ii}$_zlacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in a ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'P', 'L', 'C', m, n, m, u, ldu,work( itaup ), a, lda, & work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), a, lda,u, ldu, cdum, & 1_${ik}$, rwork( irwork ), info ) end if else if( wntvs ) then if( wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') ! m right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,work( ir+ldwrkr ), & ldwrkr ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l in ! work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & cdum, 1_${ik}$, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in a, storing result in vt ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, m, cone, work( ir ),ldwrkr, a, lda, & czero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy result to vt call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, rwork( ie ), vt,ldvt, cdum, 1_${ik}$, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+3*m ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda+m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out below it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ! generate q in a ! (cworkspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*m*m+3*m, ! prefer 2*m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*m*m+3*m-1, ! prefer 2*m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*m*m+3*m, prefer 2*m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (cworkspace: need 2*m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, a, lda, & czero, vt, ldvt ) ! copy left singular vectors of l to a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_zlacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors of l in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is lda by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need m*m+3*m-1, ! prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & u, ldu, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, a, lda, & czero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,u( 1_${ik}$, 2_${ik}$ ), ldu ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'P', 'L', 'C', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if else if( wntva ) then if( wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') ! n right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+max( n+m, 3_${ik}$*m ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,work( ir+ldwrkr ), & ldwrkr ) ! generate q in vt ! (cworkspace: need m*m+m+n, prefer m*m+m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (cworkspace: need m*m+3*m-1, ! prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & cdum, 1_${ik}$, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in vt, storing result in a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, m, cone, work( ir ),ldwrkr, vt, ldvt,& czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m+n, prefer m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, rwork( ie ), vt,ldvt, cdum, 1_${ik}$, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+max( n+m, 3_${ik}$*m ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda+m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m*m+m+n, prefer 2*m*m+m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*m*m+3*m, ! prefer 2*m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*m*m+3*m-1, ! prefer 2*m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*m*m+3*m, prefer 2*m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (cworkspace: need 2*m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, vt, ldvt,& czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, vt, ldvt ) ! copy left singular vectors of a from work(ir) to a call stdlib${ii}$_zlacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m+n, prefer m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+max( n+m, 3_${ik}$*m ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by m ldwrku = lda else ! work(iu) is m by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m*m+m+n, prefer m*m+m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & u, ldu, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_zgemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, vt, ldvt,& czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m+n, prefer m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,u( 1_${ik}$, 2_${ik}$ ), ldu ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_zunmbr( 'P', 'L', 'C', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if end if else ! n < mnthr ! path 10t(n greater than m, but not much larger) ! reduce to bidiagonal form without lq decomposition ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (cworkspace: need 2*m+n, prefer 2*m+(m+n)*nb) ! (rworkspace: m) call stdlib${ii}$_zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (cworkspace: need 3*m-1, prefer 2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_zungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (cworkspace: need 2*m+nrvt, prefer 2*m+nrvt*nb) ! (rworkspace: 0) call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) if( wntva )nrvt = n if( wntvs )nrvt = m call stdlib${ii}$_zungbr( 'P', nrvt, n, m, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (cworkspace: need 3*m-1, prefer 2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'Q', m, m, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_zungbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if irwork = ie + m if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, cdum,& 1_${ik}$, rwork( irwork ),info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$, rwork( irwork ),info ) end if end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( info/=0_${ik}$ .and. anrm>bignum )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn-1,& 1_${ik}$,rwork( ie ), minmn, ierr ) if( anrm=n .and. minmn>0_${ik}$ ) then ! space needed for stdlib${ii}$_${ci}$bdsqr is bdspac = 5*n mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'ZGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) ! compute space needed for stdlib${ii}$_${ci}$geqrf call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wgeqrf = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ci}$ungqr call stdlib${ii}$_${ci}$ungqr( m, n, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wungqr_n = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$ungqr( m, m, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wungqr_m = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ci}$gebrd call stdlib${ii}$_${ci}$gebrd( n, n, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wgebrd = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ci}$ungbr call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$ungbr( 'Q', n, n, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') maxwrk = n + lwork_wgeqrf maxwrk = max( maxwrk, 2_${ik}$*n+lwork_wgebrd ) if( wntvo .or. wntvas )maxwrk = max( maxwrk, 2_${ik}$*n+lwork_wungbr_p ) minwrk = 3_${ik}$*n else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') wrkbl = n + lwork_wgeqrf wrkbl = max( wrkbl, n+lwork_wungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_q ) maxwrk = max( n*n+wrkbl, n*n+m*n ) minwrk = 2_${ik}$*n + m else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or ! 'a') wrkbl = n + lwork_wgeqrf wrkbl = max( wrkbl, n+lwork_wungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_p ) maxwrk = max( n*n+wrkbl, n*n+m*n ) minwrk = 2_${ik}$*n + m else if( wntus .and. wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') wrkbl = n + lwork_wgeqrf wrkbl = max( wrkbl, n+lwork_wungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_q ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntus .and. wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') wrkbl = n + lwork_wgeqrf wrkbl = max( wrkbl, n+lwork_wungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_p ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntus .and. wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' or ! 'a') wrkbl = n + lwork_wgeqrf wrkbl = max( wrkbl, n+lwork_wungqr_n ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_p ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntua .and. wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') wrkbl = n + lwork_wgeqrf wrkbl = max( wrkbl, n+lwork_wungqr_m ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_q ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntua .and. wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') wrkbl = n + lwork_wgeqrf wrkbl = max( wrkbl, n+lwork_wungqr_m ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_p ) maxwrk = 2_${ik}$*n*n + wrkbl minwrk = 2_${ik}$*n + m else if( wntua .and. wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' or ! 'a') wrkbl = n + lwork_wgeqrf wrkbl = max( wrkbl, n+lwork_wungqr_m ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_q ) wrkbl = max( wrkbl, 2_${ik}$*n+lwork_wungbr_p ) maxwrk = n*n + wrkbl minwrk = 2_${ik}$*n + m end if else ! path 10 (m at least n, but not much larger) call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, & ierr ) lwork_wgebrd = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = 2_${ik}$*n + lwork_wgebrd if( wntus .or. wntuo ) then call stdlib${ii}$_${ci}$ungbr( 'Q', m, n, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*n+lwork_wungbr_q ) end if if( wntua ) then call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, n, a, lda, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*n+lwork_wungbr_q ) end if if( .not.wntvn ) then maxwrk = max( maxwrk, 2_${ik}$*n+lwork_wungbr_p ) end if minwrk = 2_${ik}$*n + m end if else if( minmn>0_${ik}$ ) then ! space needed for stdlib${ii}$_${ci}$bdsqr is bdspac = 5*m mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'ZGESVD', jobu // jobvt, m, n, 0_${ik}$, 0_${ik}$ ) ! compute space needed for stdlib${ii}$_${ci}$gelqf call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wgelqf = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ci}$unglq call stdlib${ii}$_${ci}$unglq( n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$,ierr ) lwork_wunglq_n = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$unglq( m, n, m, a, lda, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wunglq_m = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ci}$gebrd call stdlib${ii}$_${ci}$gebrd( m, m, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wgebrd = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ci}$ungbr p call stdlib${ii}$_${ci}$ungbr( 'P', m, m, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) ! compute space needed for stdlib${ii}$_${ci}$ungbr q call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wungbr_q = int( cdum(1_${ik}$),KIND=${ik}$) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') maxwrk = m + lwork_wgelqf maxwrk = max( maxwrk, 2_${ik}$*m+lwork_wgebrd ) if( wntuo .or. wntuas )maxwrk = max( maxwrk, 2_${ik}$*m+lwork_wungbr_q ) minwrk = 3_${ik}$*m else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') wrkbl = m + lwork_wgelqf wrkbl = max( wrkbl, m+lwork_wunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_p ) maxwrk = max( m*m+wrkbl, m*m+m*n ) minwrk = 2_${ik}$*m + n else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', ! jobvt='o') wrkbl = m + lwork_wgelqf wrkbl = max( wrkbl, m+lwork_wunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_q ) maxwrk = max( m*m+wrkbl, m*m+m*n ) minwrk = 2_${ik}$*m + n else if( wntvs .and. wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') wrkbl = m + lwork_wgelqf wrkbl = max( wrkbl, m+lwork_wunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_p ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntvs .and. wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') wrkbl = m + lwork_wgelqf wrkbl = max( wrkbl, m+lwork_wunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_q ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntvs .and. wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') wrkbl = m + lwork_wgelqf wrkbl = max( wrkbl, m+lwork_wunglq_m ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_q ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntva .and. wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') wrkbl = m + lwork_wgelqf wrkbl = max( wrkbl, m+lwork_wunglq_n ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_p ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntva .and. wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') wrkbl = m + lwork_wgelqf wrkbl = max( wrkbl, m+lwork_wunglq_n ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_q ) maxwrk = 2_${ik}$*m*m + wrkbl minwrk = 2_${ik}$*m + n else if( wntva .and. wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') wrkbl = m + lwork_wgelqf wrkbl = max( wrkbl, m+lwork_wunglq_n ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wgebrd ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_p ) wrkbl = max( wrkbl, 2_${ik}$*m+lwork_wungbr_q ) maxwrk = m*m + wrkbl minwrk = 2_${ik}$*m + n end if else ! path 10t(n greater than m, but not much larger) call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, & ierr ) lwork_wgebrd = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = 2_${ik}$*m + lwork_wgebrd if( wntvs .or. wntvo ) then ! compute space needed for stdlib${ii}$_${ci}$ungbr p call stdlib${ii}$_${ci}$ungbr( 'P', m, n, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*m+lwork_wungbr_p ) end if if( wntva ) then call stdlib${ii}$_${ci}$ungbr( 'P', n, n, m, a, n, cdum(1_${ik}$),cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wungbr_p = int( cdum(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, 2_${ik}$*m+lwork_wungbr_p ) end if if( .not.wntun ) then maxwrk = max( maxwrk, 2_${ik}$*m+lwork_wungbr_q ) end if minwrk = 2_${ik}$*m + n end if end if maxwrk = max( maxwrk, minwrk ) work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr ) then if( wntun ) then ! path 1 (m much larger than n, jobu='n') ! no left singular vectors to be computed itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: need 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out below r if( n > 1_${ik}$ ) then call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( iwork ), lwork-iwork+1,ierr ) ncvt = 0_${ik}$ if( wntvo .or. wntvas ) then ! if right singular vectors desired, generate p'. ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) ncvt = n end if irwork = ie + n ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a if desired ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, ncvt, 0_${ik}$, 0_${ik}$, s, rwork( ie ), a, lda,cdum, 1_${ik}$, cdum, & 1_${ik}$, rwork( irwork ), info ) ! if right singular vectors desired in vt, copy them there if( wntvas )call stdlib${ii}$_${ci}$lacpy( 'F', n, n, a, lda, vt, ldvt ) else if( wntuo .and. wntvn ) then ! path 2 (m much larger than n, jobu='o', jobvt='n') ! n left singular vectors to be overwritten on a and ! no right singular vectors to be computed if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*n ) then ! work(iu) is lda by n, work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+n*n ) then ! work(iu) is lda by n, work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n, work(ir) is n by n ldwrku = ( lwork-n*n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to work(ir) and zero out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,work( ir+1 ), ldwrkr ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ),& work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: need 0) call stdlib${ii}$_${ci}$ungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, rwork( ie ), cdum, 1_${ik}$,work( ir ), & ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (cworkspace: need n*n+n, prefer n*n+m*n) ! (rworkspace: 0) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', chunk, n, n, cone, a( i, 1_${ik}$ ),lda, work( ir & ), ldwrkr, czero,work( iu ), ldwrku ) call stdlib${ii}$_${ci}$lacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (cworkspace: need 2*n+m, prefer 2*n+(m+n)*nb) ! (rworkspace: n) call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing a ! (cworkspace: need 3*n, prefer 2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a ! (cworkspace: need 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, rwork( ie ), cdum, 1_${ik}$,a, lda, cdum, & 1_${ik}$, rwork( irwork ), info ) end if else if( wntuo .and. wntvas ) then ! path 3 (m much larger than n, jobu='o', jobvt='s' or 'a') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+n*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ldwrkr = n else ! work(iu) is ldwrku by n and work(ir) is n by n ldwrku = ( lwork-n*n ) / n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt, copying result to work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', n, n, vt, ldvt, work( ir ), ldwrkr ) ! generate left vectors bidiagonalizing r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), work( & iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (cworkspace: need n*n+3*n-1, prefer n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) and computing right ! singular vectors of r in vt ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ), vt,ldvt, work( ir ), & ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply q in a by left singular vectors of r in ! work(ir), storing result in work(iu) and copying to a ! (cworkspace: need n*n+n, prefer n*n+m*n) ! (rworkspace: 0) do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', chunk, n, n, cone, a( i, 1_${ik}$ ),lda, work( ir & ), ldwrkr, czero,work( iu ), ldwrku ) call stdlib${ii}$_${ci}$lacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), ldvt ) ! generate q in a ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: n) call stdlib${ii}$_${ci}$gebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in a by left vectors bidiagonalizing r ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), a, lda,& work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, cdum,& 1_${ik}$, rwork( irwork ),info ) end if else if( wntus ) then if( wntvn ) then ! path 4 (m much larger than n, jobu='s', jobvt='n') ! n left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,work( ir+1 ), ldwrkr ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, work( ir ),& ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, n, cone, a, lda,work( ir ), ldwrkr, & czero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvo ) then ! path 5 (m much larger than n, jobu='s', jobvt='o') ! n left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+3*n ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda+n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ! generate q in a ! (cworkspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*n*n+3*n, ! prefer 2*n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*n*n+3*n, prefer 2*n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*n*n+3*n-1, ! prefer 2*n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (cworkspace: need 2*n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, n, cone, a, lda,work( iu ), ldwrku, & czero, u, ldu ) ! copy right singular vectors of r to a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_${ci}$lacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left vectors bidiagonalizing r ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing r in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvas ) then ! path 6 (m much larger than n, jobu='s', jobvt='s' ! or 'a') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+3*n ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ! generate q in a ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, n, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need n*n+3*n-1, ! prefer n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ), vt,ldvt, work( iu )& , ldwrku, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in u ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, n, cone, a, lda,work( iu ), ldwrku, & czero, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, n, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to vt, zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), & ldvt ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if else if( wntua ) then if( wntvn ) then ! path 7 (m much larger than n, jobu='a', jobvt='n') ! m left singular vectors to be computed in u and ! no right singular vectors to be computed if( lwork>=n*n+max( n+m, 3_${ik}$*n ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(ir) is lda by n ldwrkr = lda else ! work(ir) is n by n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,work( ir+1 ), ldwrkr ) ! generate q in u ! (cworkspace: need n*n+n+m, prefer n*n+n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(ir) ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, 0_${ik}$, n, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, work( ir ),& ldwrkr, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in u by left singular vectors of r in ! work(ir), storing result in a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, n, cone, u, ldu,work( ir ), ldwrkr, & czero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n+m, prefer n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, 0_${ik}$, m, 0_${ik}$, s, rwork( ie ), cdum,1_${ik}$, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvo ) then ! path 8 (m much larger than n, jobu='a', jobvt='o') ! m left singular vectors to be computed in u and ! n right singular vectors to be overwritten on a if( lwork>=2_${ik}$*n*n+max( n+m, 3_${ik}$*n ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*n ) then ! work(iu) is lda by n and work(ir) is lda by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = lda else if( lwork>=wrkbl+( lda+n )*n ) then ! work(iu) is lda by n and work(ir) is n by n ldwrku = lda ir = iu + ldwrku*n ldwrkr = n else ! work(iu) is n by n and work(ir) is n by n ldwrku = n ir = iu + ldwrku*n ldwrkr = n end if itau = ir + ldwrkr*n iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n*n+2*n, prefer 2*n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need 2*n*n+n+m, prefer 2*n*n+n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*n*n+3*n, ! prefer 2*n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', n, n, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*n*n+3*n, prefer 2*n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*n*n+3*n-1, ! prefer 2*n*n+2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in work(ir) ! (cworkspace: need 2*n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & work( iu ),ldwrku, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, n, cone, u, ldu,work( iu ), ldwrku, & czero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, u, ldu ) ! copy right singular vectors of r from work(ir) to a call stdlib${ii}$_${ci}$lacpy( 'F', n, n, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n+m, prefer n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! zero out below r in a if( n > 1_${ik}$ ) then call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,a( 2_${ik}$, 1_${ik}$ ), lda ) end if ! bidiagonalize r in a ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in a ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'Q', 'R', 'N', m, n, n, a, lda,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) end if else if( wntvas ) then ! path 9 (m much larger than n, jobu='a', jobvt='s' ! or 'a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt if( lwork>=n*n+max( n+m, 3_${ik}$*n ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*n ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is n by n ldwrku = n end if itau = iu + ldwrku*n iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need n*n+2*n, prefer n*n+n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n*n+n+m, prefer n*n+n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r to work(iu), zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,work( iu+1 ), ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in work(iu), copying result to vt ! (cworkspace: need n*n+3*n, prefer n*n+2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', n, n, work( iu ), ldwrku, vt,ldvt ) ! generate left bidiagonalizing vectors in work(iu) ! (cworkspace: need n*n+3*n, prefer n*n+2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', n, n, n, work( iu ), ldwrku,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need n*n+3*n-1, ! prefer n*n+2*n+(n-1)*nb) ! (rworkspace: need 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of r in work(iu) and computing ! right singular vectors of r in vt ! (cworkspace: need n*n) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, n, n, 0_${ik}$, s, rwork( ie ), vt,ldvt, work( iu )& , ldwrku, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! (cworkspace: need n*n) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, n, cone, u, ldu,work( iu ), ldwrku, & czero, a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, u, ldu ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + n ! compute a=q*r, copying result to u ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! (cworkspace: need n+m, prefer n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungqr( m, m, n, u, ldu, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy r from a to vt, zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, vt, ldvt ) if( n>1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero,vt( 2_${ik}$, 1_${ik}$ ), & ldvt ) ie = 1_${ik}$ itauq = itau itaup = itauq + n iwork = itaup + n ! bidiagonalize r in vt ! (cworkspace: need 3*n, prefer 2*n+2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( n, n, vt, ldvt, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply q in u by left bidiagonalizing vectors ! in vt ! (cworkspace: need 2*n+m, prefer 2*n+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'Q', 'R', 'N', m, n, n, vt, ldvt,work( itauq ), u, & ldu, work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ),& lwork-iwork+1, ierr ) irwork = ie + n ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if end if else ! m < mnthr ! path 10 (m at least n, but not much larger) ! reduce to bidiagonal form without qr decomposition ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize a ! (cworkspace: need 2*n+m, prefer 2*n+(m+n)*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (cworkspace: need 2*n+ncu, prefer 2*n+ncu*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) if( wntus )ncu = n if( wntua )ncu = m call stdlib${ii}$_${ci}$ungbr( 'Q', m, ncu, n, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (cworkspace: need 3*n, prefer 2*n+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, n, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if irwork = ie + n if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, cdum,& 1_${ik}$, rwork( irwork ),info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$, rwork( irwork ),info ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr ) then if( wntvn ) then ! path 1t(n much larger than m, jobvt='n') ! no right singular vectors to be computed itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero, a( 1_${ik}$, 2_${ik}$ ),lda ) ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( iwork ), lwork-iwork+1,ierr ) if( wntuo .or. wntuas ) then ! if left singular vectors desired, generate q ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) end if irwork = ie + m nru = 0_${ik}$ if( wntuo .or. wntuas )nru = m ! perform bidiagonal qr iteration, computing left singular ! vectors of a in a if desired ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, 0_${ik}$, nru, 0_${ik}$, s, rwork( ie ), cdum, 1_${ik}$,a, lda, cdum, & 1_${ik}$, rwork( irwork ), info ) ! if left singular vectors desired in u, copy them there if( wntuas )call stdlib${ii}$_${ci}$lacpy( 'F', m, m, a, lda, u, ldu ) else if( wntvo .and. wntun ) then ! path 2t(n much larger than m, jobu='n', jobvt='o') ! m right singular vectors to be overwritten on a and ! no left singular vectors to be computed if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to work(ir) and zero out above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,work( ir+ldwrkr ), ldwrkr ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ),& work( itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l ! (cworkspace: need m*m+3*m-1, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & cdum, 1_${ik}$, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (cworkspace: need m*m+m, prefer m*m+m*n) ! (rworkspace: 0) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, blk, m, cone, work( ir ),ldwrkr, a( 1_${ik}$, & i ), lda, czero,work( iu ), ldwrku ) call stdlib${ii}$_${ci}$lacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (cworkspace: need 2*m+n, prefer 2*m+(m+n)*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'L', m, n, 0_${ik}$, 0_${ik}$, s, rwork( ie ), a, lda,cdum, 1_${ik}$, cdum, & 1_${ik}$, rwork( irwork ), info ) end if else if( wntvo .and. wntuas ) then ! path 3t(n much larger than m, jobu='s' or 'a', jobvt='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=max( wrkbl, lda*n )+lda*m ) then ! work(iu) is lda by n and work(ir) is lda by m ldwrku = lda chunk = n ldwrkr = lda else if( lwork>=max( wrkbl, lda*n )+m*m ) then ! work(iu) is lda by n and work(ir) is m by m ldwrku = lda chunk = n ldwrkr = m else ! work(iu) is m by chunk and work(ir) is m by m ldwrku = m chunk = ( lwork-m*m ) / m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing about above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u, copying result to work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', m, m, u, ldu, work( ir ), ldwrkr ) ! generate right vectors bidiagonalizing l in work(ir) ! (cworkspace: need m*m+3*m-1, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), work( & iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u, and computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, u, & ldu, cdum, 1_${ik}$,rwork( irwork ), info ) iu = itauq ! multiply right singular vectors of l in work(ir) by q ! in a, storing result in work(iu) and copying to a ! (cworkspace: need m*m+m, prefer m*m+m*n)) ! (rworkspace: 0) do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, blk, m, cone, work( ir ),ldwrkr, a( 1_${ik}$, & i ), lda, czero,work( iu ), ldwrku ) call stdlib${ii}$_${ci}$lacpy( 'F', m, blk, work( iu ), ldwrku,a( 1_${ik}$, i ), lda ) end do else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-iwork+& 1_${ik}$, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero, u( 1_${ik}$, 2_${ik}$ ),ldu ) ! generate q in a ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in a ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'P', 'L', 'C', m, n, m, u, ldu,work( itaup ), a, lda, & work( iwork ),lwork-iwork+1, ierr ) ! generate left vectors bidiagonalizing l in u ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), a, lda,u, ldu, cdum, & 1_${ik}$, rwork( irwork ), info ) end if else if( wntvs ) then if( wntun ) then ! path 4t(n much larger than m, jobu='n', jobvt='s') ! m right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,work( ir+ldwrkr ), & ldwrkr ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right vectors bidiagonalizing l in ! work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & cdum, 1_${ik}$, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in a, storing result in vt ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, m, cone, work( ir ),ldwrkr, a, lda, & czero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy result to vt call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, rwork( ie ), vt,ldvt, cdum, 1_${ik}$, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuo ) then ! path 5t(n much larger than m, jobu='o', jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+3*m ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda+m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q ! (cworkspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ! generate q in a ! (cworkspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*m*m+3*m, ! prefer 2*m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*m*m+3*m-1, ! prefer 2*m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*m*m+3*m, prefer 2*m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (cworkspace: need 2*m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, a, lda, & czero, vt, ldvt ) ! copy left singular vectors of l to a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_${ci}$lacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right vectors bidiagonalizing l by q in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors of l in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuas ) then ! path 6t(n much larger than m, jobu='s' or 'a', ! jobvt='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+3*m ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by n ldwrku = lda else ! work(iu) is lda by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ! generate q in a ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( m, n, m, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need m*m+3*m-1, ! prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & u, ldu, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in a, storing result in vt ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, a, lda, & czero, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( m, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,u( 1_${ik}$, 2_${ik}$ ), ldu ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'P', 'L', 'C', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if else if( wntva ) then if( wntun ) then ! path 7t(n much larger than m, jobu='n', jobvt='a') ! n right singular vectors to be computed in vt and ! no left singular vectors to be computed if( lwork>=m*m+max( n+m, 3_${ik}$*m ) ) then ! sufficient workspace for a fast algorithm ir = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(ir) is lda by m ldwrkr = lda else ! work(ir) is m by m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! copy l to work(ir), zeroing out above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, work( ir ),ldwrkr ) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,work( ir+ldwrkr ), & ldwrkr ) ! generate q in vt ! (cworkspace: need m*m+m+n, prefer m*m+m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(ir) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, work( ir ), ldwrkr, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) ! generate right bidiagonalizing vectors in work(ir) ! (cworkspace: need m*m+3*m-1, ! prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', m, m, m, work( ir ), ldwrkr,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of l in work(ir) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, m, 0_${ik}$, 0_${ik}$, s, rwork( ie ),work( ir ), ldwrkr, & cdum, 1_${ik}$, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(ir) by ! q in vt, storing result in a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, m, cone, work( ir ),ldwrkr, vt, ldvt,& czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m+n, prefer m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, n, 0_${ik}$, 0_${ik}$, s, rwork( ie ), vt,ldvt, cdum, 1_${ik}$, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuo ) then ! path 8t(n much larger than m, jobu='o', jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be overwritten on a if( lwork>=2_${ik}$*m*m+max( n+m, 3_${ik}$*m ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+2*lda*m ) then ! work(iu) is lda by m and work(ir) is lda by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = lda else if( lwork>=wrkbl+( lda+m )*m ) then ! work(iu) is lda by m and work(ir) is m by m ldwrku = lda ir = iu + ldwrku*m ldwrkr = m else ! work(iu) is m by m and work(ir) is m by m ldwrku = m ir = iu + ldwrku*m ldwrkr = m end if itau = ir + ldwrkr*m iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m*m+2*m, prefer 2*m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need 2*m*m+m+n, prefer 2*m*m+m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to ! work(ir) ! (cworkspace: need 2*m*m+3*m, ! prefer 2*m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, m, work( iu ), ldwrku,work( ir ), ldwrkr ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need 2*m*m+3*m-1, ! prefer 2*m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in work(ir) ! (cworkspace: need 2*m*m+3*m, prefer 2*m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, work( ir ), ldwrkr,work( itauq ), & work( iwork ),lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in work(ir) and computing ! right singular vectors of l in work(iu) ! (cworkspace: need 2*m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & work( ir ),ldwrkr, cdum, 1_${ik}$, rwork( irwork ),info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, vt, ldvt,& czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, vt, ldvt ) ! copy left singular vectors of a from work(ir) to a call stdlib${ii}$_${ci}$lacpy( 'F', m, m, work( ir ), ldwrkr, a,lda ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m+n, prefer m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! zero out above l in a if (m>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,a( 1_${ik}$, 2_${ik}$ ), lda ) ! bidiagonalize l in a ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, a, lda, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in a by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'P', 'L', 'C', m, n, m, a, lda,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, a, lda, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in a and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$,rwork( irwork ), info ) end if else if( wntuas ) then ! path 9t(n much larger than m, jobu='s' or 'a', ! jobvt='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u if( lwork>=m*m+max( n+m, 3_${ik}$*m ) ) then ! sufficient workspace for a fast algorithm iu = 1_${ik}$ if( lwork>=wrkbl+lda*m ) then ! work(iu) is lda by m ldwrku = lda else ! work(iu) is m by m ldwrku = m end if itau = iu + ldwrku*m iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m*m+m+n, prefer m*m+m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to work(iu), zeroing out above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,work( iu+ldwrku ), & ldwrku ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(iu), copying result to u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, work( iu ), ldwrku, s,rwork( ie ), work( & itauq ),work( itaup ), work( iwork ),lwork-iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, m, work( iu ), ldwrku, u,ldu ) ! generate right bidiagonalizing vectors in work(iu) ! (cworkspace: need m*m+3*m, prefer m*m+2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', m, m, m, work( iu ), ldwrku,work( itaup ), & work( iwork ),lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need m*m+3*m, prefer m*m+2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of l in u and computing right ! singular vectors of l in work(iu) ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, m, m, 0_${ik}$, s, rwork( ie ),work( iu ), ldwrku, & u, ldu, cdum, 1_${ik}$,rwork( irwork ), info ) ! multiply right singular vectors of l in work(iu) by ! q in vt, storing result in a ! (cworkspace: need m*m) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, m, cone, work( iu ),ldwrku, vt, ldvt,& czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, vt, ldvt ) else ! insufficient workspace for a fast algorithm itau = 1_${ik}$ iwork = itau + m ! compute a=l*q, copying result to vt ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ),work( iwork ), lwork-& iwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! (cworkspace: need m+n, prefer m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unglq( n, n, m, vt, ldvt, work( itau ),work( iwork ), & lwork-iwork+1, ierr ) ! copy l to u, zeroing out above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, u, ldu ) if (m>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,u( 1_${ik}$, 2_${ik}$ ), ldu ) ie = 1_${ik}$ itauq = itau itaup = itauq + m iwork = itaup + m ! bidiagonalize l in u ! (cworkspace: need 3*m, prefer 2*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, u, ldu, s, rwork( ie ),work( itauq ), work( & itaup ),work( iwork ), lwork-iwork+1, ierr ) ! multiply right bidiagonalizing vectors in u by q ! in vt ! (cworkspace: need 2*m+n, prefer 2*m+n*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$unmbr( 'P', 'L', 'C', m, n, m, u, ldu,work( itaup ), vt, & ldvt,work( iwork ), lwork-iwork+1, ierr ) ! generate left bidiagonalizing vectors in u ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, m, u, ldu, work( itauq ),work( iwork ), & lwork-iwork+1, ierr ) irwork = ie + m ! perform bidiagonal qr iteration, computing left ! singular vectors of a in u and computing right ! singular vectors of a in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, n, m, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$,rwork( irwork ), info ) end if end if end if else ! n < mnthr ! path 10t(n greater than m, but not much larger) ! reduce to bidiagonal form without lq decomposition ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (cworkspace: need 2*m+n, prefer 2*m+(m+n)*nb) ! (rworkspace: m) call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,ierr ) if( wntuas ) then ! if left singular vectors desired in u, copy result to u ! and generate left bidiagonalizing vectors in u ! (cworkspace: need 3*m-1, prefer 2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvas ) then ! if right singular vectors desired in vt, copy result to ! vt and generate right bidiagonalizing vectors in vt ! (cworkspace: need 2*m+nrvt, prefer 2*m+nrvt*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) if( wntva )nrvt = n if( wntvs )nrvt = m call stdlib${ii}$_${ci}$ungbr( 'P', nrvt, n, m, vt, ldvt, work( itaup ),work( iwork ), & lwork-iwork+1, ierr ) end if if( wntuo ) then ! if left singular vectors desired in a, generate left ! bidiagonalizing vectors in a ! (cworkspace: need 3*m-1, prefer 2*m+(m-1)*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, n, a, lda, work( itauq ),work( iwork ), lwork-& iwork+1, ierr ) end if if( wntvo ) then ! if right singular vectors desired in a, generate right ! bidiagonalizing vectors in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: 0) call stdlib${ii}$_${ci}$ungbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-& iwork+1, ierr ) end if irwork = ie + m if( wntuas .or. wntuo )nru = m if( wntun )nru = 0_${ik}$ if( wntvas .or. wntvo )ncvt = n if( wntvn )ncvt = 0_${ik}$ if( ( .not.wntuo ) .and. ( .not.wntvo ) ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, u, ldu, & cdum, 1_${ik}$, rwork( irwork ),info ) else if( ( .not.wntuo ) .and. wntvo ) then ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in u and computing right singular ! vectors in a ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, rwork( ie ), a,lda, u, ldu, cdum,& 1_${ik}$, rwork( irwork ),info ) else ! perform bidiagonal qr iteration, if desired, computing ! left singular vectors in a and computing right singular ! vectors in vt ! (cworkspace: 0) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'L', m, ncvt, nru, 0_${ik}$, s, rwork( ie ), vt,ldvt, a, lda, & cdum, 1_${ik}$, rwork( irwork ),info ) end if end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( info/=0_${ik}$ .and. anrm>bignum )call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn-1,& 1_${ik}$,rwork( ie ), minmn, ierr ) if( anrm= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N orthogonal matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. numrank, iwork, liwork,work, lwork, rwork, lrwork, info ) use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: joba, jobp, jobr, jobu, jobv integer(${ik}$), intent(in) :: m, n, lda, ldu, ldv, liwork, lrwork integer(${ik}$), intent(out) :: numrank, info integer(${ik}$), intent(inout) :: lwork ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: u(ldu,*), v(ldv,*), work(*) real(sp), intent(out) :: s(*), rwork(*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ierr, iwoff, nr, n1, optratio, p, q integer(${ik}$) :: lwcon, lwqp3, lwrk_sgelqf, lwrk_sgesvd, lwrk_sgesvd2, lwrk_sgeqp3, & lwrk_sgeqrf, lwrk_sormlq, lwrk_sormqr, lwrk_sormqr2, lwlqf, lwqrf, lwsvd, lwsvd2, & lworq, lworq2, lwunlq, minwrk, minwrk2, optwrk, optwrk2, iminwrk, rminwrk logical(lk) :: accla, acclm, acclh, ascaled, conda, dntwu, dntwv, lquery, lsvc0, lsvec,& rowprm, rsvec, rtrans, wntua, wntuf, wntur, wntus, wntva, wntvr real(sp) :: big, epsln, rtmp, sconda, sfmin ! Local Arrays real(sp) :: rdummy(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments wntus = stdlib_lsame( jobu, 'S' ) .or. stdlib_lsame( jobu, 'U' ) wntur = stdlib_lsame( jobu, 'R' ) wntua = stdlib_lsame( jobu, 'A' ) wntuf = stdlib_lsame( jobu, 'F' ) lsvc0 = wntus .or. wntur .or. wntua lsvec = lsvc0 .or. wntuf dntwu = stdlib_lsame( jobu, 'N' ) wntvr = stdlib_lsame( jobv, 'R' ) wntva = stdlib_lsame( jobv, 'A' ) .or. stdlib_lsame( jobv, 'V' ) rsvec = wntvr .or. wntva dntwv = stdlib_lsame( jobv, 'N' ) accla = stdlib_lsame( joba, 'A' ) acclm = stdlib_lsame( joba, 'M' ) conda = stdlib_lsame( joba, 'E' ) acclh = stdlib_lsame( joba, 'H' ) .or. conda rowprm = stdlib_lsame( jobp, 'P' ) rtrans = stdlib_lsame( jobr, 'T' ) if ( rowprm ) then if ( conda ) then iminwrk = max( 1_${ik}$, n + m - 1_${ik}$ + n ) else iminwrk = max( 1_${ik}$, n + m - 1_${ik}$ ) end if rminwrk = max( 2_${ik}$, m ) else if ( conda ) then iminwrk = max( 1_${ik}$, n + n ) else iminwrk = max( 1_${ik}$, n ) end if rminwrk = 2_${ik}$ end if lquery = (liwork == -1_${ik}$ .or. lwork == -1_${ik}$ .or. lrwork == -1_${ik}$) info = 0_${ik}$ if ( .not. ( accla .or. acclm .or. acclh ) ) then info = -1_${ik}$ else if ( .not.( rowprm .or. stdlib_lsame( jobp, 'N' ) ) ) then info = -2_${ik}$ else if ( .not.( rtrans .or. stdlib_lsame( jobr, 'N' ) ) ) then info = -3_${ik}$ else if ( .not.( lsvec .or. dntwu ) ) then info = -4_${ik}$ else if ( wntur .and. wntva ) then info = -5_${ik}$ else if ( .not.( rsvec .or. dntwv )) then info = -5_${ik}$ else if ( m<0_${ik}$ ) then info = -6_${ik}$ else if ( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -7_${ik}$ else if ( lda big / sqrt(real(m,KIND=sp)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_slascl('G',0_${ik}$,0_${ik}$,sqrt(real(m,KIND=sp)),one, m,n, a,lda, ierr) ascaled = .true. end if call stdlib${ii}$_slaswp( n, a, lda, 1_${ik}$, m-1, iwork(n+1), 1_${ik}$ ) end if ! .. at this stage, preemptive scaling is done only to avoid column ! norms overflows during the qr factorization. the svd procedure should ! have its own scaling to save the singular values from overflows and ! underflows. that depends on the svd procedure. if ( .not.rowprm ) then rtmp = stdlib${ii}$_slange( 'M', m, n, a, lda, rdummy ) if ( ( rtmp /= rtmp ) .or.( (rtmp*zero) /= zero ) ) then info = -8_${ik}$ call stdlib${ii}$_xerbla( 'SGESVDQ', -info ) return end if if ( rtmp > big / sqrt(real(m,KIND=sp)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_slascl('G',0_${ik}$,0_${ik}$, sqrt(real(m,KIND=sp)),one, m,n, a,lda, ierr) ascaled = .true. end if end if ! Qr Factorization With Column Pivoting ! a * p = q * [ r ] ! [ 0 ] do p = 1, n ! All Columns Are Free Columns iwork(p) = 0_${ik}$ end do call stdlib${ii}$_sgeqp3( m, n, a, lda, iwork, work, work(n+1), lwork-n,ierr ) ! if the user requested accuracy level allows truncation in the ! computed upper triangular factor, the matrix r is examined and, ! if possible, replaced with its leading upper trapezoidal part. epsln = stdlib${ii}$_slamch('E') sfmin = stdlib${ii}$_slamch('S') ! small = sfmin / epsln nr = n if ( accla ) then ! standard absolute error bound suffices. all sigma_i with ! sigma_i < n*eps*||a||_f are flushed to zero. this is an ! aggressive enforcement of lower numerical rank by introducing a ! backward error of the order of n*eps*||a||_f. nr = 1_${ik}$ rtmp = sqrt(real(n,KIND=sp))*epsln do p = 2, n if ( abs(a(p,p)) < (rtmp*abs(a(1,1))) ) go to 3002 nr = nr + 1_${ik}$ end do 3002 continue elseif ( acclm ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r is used as the criterion for being ! close-to-rank-deficient. the threshold is set to epsln=stdlib${ii}$_slamch('e'). ! [[this can be made more flexible by replacing this hard-coded value ! with a user specified threshold.]] also, the values that underflow ! will be truncated. nr = 1_${ik}$ do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < sfmin ) ) go to 3402 nr = nr + 1_${ik}$ end do 3402 continue else ! Rrqr Not Authorized To Determine Numerical Rank Except In The ! obvious case of zero pivots. ! .. inspect r for exact zeros on the diagonal; ! r(i,i)=0 => r(i:n,i:n)=0. nr = 1_${ik}$ do p = 2, n if ( abs(a(p,p)) == zero ) go to 3502 nr = nr + 1_${ik}$ end do 3502 continue if ( conda ) then ! estimate the scaled condition number of a. use the fact that it is ! the same as the scaled condition number of r. ! V Is Used As Workspace call stdlib${ii}$_slacpy( 'U', n, n, a, lda, v, ldv ) ! only the leading nr x nr submatrix of the triangular factor ! is considered. only if nr=n will this give a reliable error ! bound. however, even for nr < n, this can be used on an ! expert level and obtain useful information in the sense of ! perturbation theory. do p = 1, nr rtmp = stdlib${ii}$_snrm2( p, v(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_sscal( p, one/rtmp, v(1_${ik}$,p), 1_${ik}$ ) end do if ( .not. ( lsvec .or. rsvec ) ) then call stdlib${ii}$_spocon( 'U', nr, v, ldv, one, rtmp,work, iwork(n+iwoff), ierr & ) else call stdlib${ii}$_spocon( 'U', nr, v, ldv, one, rtmp,work(n+1), iwork(n+iwoff), & ierr ) end if sconda = one / sqrt(rtmp) ! for nr=n, sconda is an estimate of sqrt(||(r^* * r)^(-1)||_1), ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda ! see the reference [1] for more details. end if endif if ( wntur ) then n1 = nr else if ( wntus .or. wntuf) then n1 = n else if ( wntua ) then n1 = m end if if ( .not. ( rsvec .or. lsvec ) ) then ! ....................................................................... ! Only The Singular Values Are Requested ! ....................................................................... if ( rtrans ) then ! .. compute the singular values of r**t = [a](1:nr,1:n)**t ! .. set the lower triangle of [a] to [a](1:nr,1:n)**t and ! the upper triangle of [a] to zero. do p = 1, min( n, nr ) do q = p + 1, n a(q,p) = a(p,q) if ( q <= nr ) a(p,q) = zero end do end do call stdlib${ii}$_sgesvd( 'N', 'N', n, nr, a, lda, s, u, ldu,v, ldv, work, lwork, info & ) else ! .. compute the singular values of r = [a](1:nr,1:n) if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset( 'L', nr-1,nr-1, zero,zero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_sgesvd( 'N', 'N', nr, n, a, lda, s, u, ldu,v, ldv, work, lwork, info & ) end if else if ( lsvec .and. ( .not. rsvec) ) then ! ....................................................................... ! The Singular Values And The Left Singular Vectors Requested ! ......................................................................."""""""" if ( rtrans ) then ! .. apply stdlib${ii}$_sgesvd to r**t ! .. copy r**t into [u] and overwrite [u] with the right singular ! vectors of r do p = 1, nr do q = p, n u(q,p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset( 'U', nr-1,nr-1, zero,zero, u(1_${ik}$,2_${ik}$), ldu ) ! .. the left singular vectors not computed, the nr right singular ! vectors overwrite [u](1:nr,1:nr) as transposed. these ! will be pre-multiplied by q to build the left singular vectors of a. call stdlib${ii}$_sgesvd( 'N', 'O', n, nr, u, ldu, s, u, ldu,u, ldu, work(n+1), & lwork-n, info ) do p = 1, nr do q = p + 1, nr rtmp = u(q,p) u(q,p) = u(p,q) u(p,q) = rtmp end do end do else ! Apply Stdlib_Sgesvd To R ! .. copy r into [u] and overwrite [u] with the left singular vectors call stdlib${ii}$_slacpy( 'U', nr, n, a, lda, u, ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset( 'L', nr-1, nr-1, zero, zero, u(2_${ik}$,1_${ik}$), ldu ) ! .. the right singular vectors not computed, the nr left singular ! vectors overwrite [u](1:nr,1:nr) call stdlib${ii}$_sgesvd( 'O', 'N', nr, n, u, ldu, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) ! .. now [u](1:nr,1:nr) contains the nr left singular vectors of ! r. these will be pre-multiplied by q to build the left singular ! vectors of a. end if ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. ( .not.wntuf ) ) then call stdlib${ii}$_slaset('A', m-nr, nr, zero, zero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_slaset( 'A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1), ldu ) call stdlib${ii}$_slaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not.wntuf )call stdlib${ii}$_sormqr( 'L', 'N', m, n1, n, a, lda, work, u,ldu, work(& n+1), lwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_slaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) else if ( rsvec .and. ( .not. lsvec ) ) then ! ....................................................................... ! The Singular Values And The Right Singular Vectors Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_sgesvd to r**t ! .. copy r**t into v and overwrite v with the left singular vectors do p = 1, nr do q = p, n v(q,p) = (a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset( 'U', nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**t overwrite v, the right singular ! vectors not computed if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_sgesvd( 'O', 'N', n, nr, v, ldv, s, u, ldu,u, ldu, work(n+1), & lwork-n, info ) do p = 1, nr do q = p + 1, nr rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do if ( nr < n ) then do p = 1, nr do q = nr + 1, n v(p,q) = v(q,p) end do end do end if call stdlib${ii}$_slapmt( .false., nr, n, v, ldv, iwork ) else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:n,1:nr) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the qr factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_slaset('G', n, n-nr, zero, zero, v(1_${ik}$,nr+1), ldv) call stdlib${ii}$_sgesvd( 'O', 'N', n, n, v, ldv, s, u, ldu,u, ldu, work(n+1), & lwork-n, info ) do p = 1, n do q = p + 1, n rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do call stdlib${ii}$_slapmt( .false., n, n, v, ldv, iwork ) end if else ! Aply Stdlib_Sgesvd To R ! Copy R Into V And Overwrite V With The Right Singular Vectors call stdlib${ii}$_slacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset( 'L', nr-1, nr-1, zero, zero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors overwrite v, the nr left singular ! vectors stored in u(1:nr,1:nr) if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_sgesvd( 'N', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_slapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**t else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:nr,1:n) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the lq factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_slaset('G', n-nr, n, zero,zero, v(nr+1,1_${ik}$), ldv) call stdlib${ii}$_sgesvd( 'N', 'O', n, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_slapmt( .false., n, n, v, ldv, iwork ) end if ! .. now [v] contains the transposed matrix of the right singular ! vectors of a. end if else ! ....................................................................... ! Full Svd Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_sgesvd to r**t [[this option is left for r if ( wntvr .or. ( nr == n ) ) then ! .. copy r**t into [v] and overwrite [v] with the left singular ! vectors of r**t do p = 1, nr do q = p, n v(q,p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset( 'U', nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**t overwrite [v], the nr right ! singular vectors of r**t stored in [u](1:nr,1:nr) as transposed call stdlib${ii}$_sgesvd( 'O', 'A', n, nr, v, ldv, s, v, ldv,u, ldu, work(n+1), & lwork-n, info ) ! Assemble V do p = 1, nr do q = p + 1, nr rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do if ( nr < n ) then do p = 1, nr do q = nr+1, n v(p,q) = v(q,p) end do end do end if call stdlib${ii}$_slapmt( .false., nr, n, v, ldv, iwork ) do p = 1, nr do q = p + 1, nr rtmp = u(q,p) u(q,p) = u(p,q) u(p,q) = rtmp end do end do if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_slaset('A', m-nr,nr, zero,zero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_slaset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_slaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! .. copy r**t into [v] and overwrite [v] with the left singular ! vectors of r**t ! [[the optimal ratio n/nr for using qrf instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'sgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio*nr > n ) then do p = 1, nr do q = p, n v(q,p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset('U',nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_slaset('A',n,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_sgesvd( 'O', 'A', n, n, v, ldv, s, v, ldv,u, ldu, work(n+1), & lwork-n, info ) do p = 1, n do q = p + 1, n rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do call stdlib${ii}$_slapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). do p = 1, n do q = p + 1, n rtmp = u(q,p) u(q,p) = u(p,q) u(p,q) = rtmp end do end do if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_slaset('A',m-n,n,zero,zero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_slaset('A',n,n1-n,zero,zero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_slaset('A',m-n,n1-n,zero,one,u(n+1,n+1), ldu ) end if end if else ! .. copy r**t into [u] and overwrite [u] with the right ! singular vectors of r do p = 1, nr do q = p, n u(q,nr+p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset('U',nr-1,nr-1,zero,zero,u(1_${ik}$,nr+2),ldu) call stdlib${ii}$_sgeqrf( n, nr, u(1_${ik}$,nr+1), ldu, work(n+1),work(n+nr+1), lwork-& n-nr, ierr ) do p = 1, nr do q = 1, n v(q,p) = u(p,nr+q) end do end do call stdlib${ii}$_slaset('U',nr-1,nr-1,zero,zero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_sgesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v,ldv, work(n+nr+1)& ,lwork-n-nr, info ) call stdlib${ii}$_slaset('A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_slaset('A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_slaset('A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv) call stdlib${ii}$_sormqr('R','C', n, n, nr, u(1_${ik}$,nr+1), ldu,work(n+1),v,ldv,work(& n+nr+1),lwork-n-nr,ierr) call stdlib${ii}$_slapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_slaset('A',m-nr,nr,zero,zero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_slaset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_slaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1),ldu) end if end if end if end if else ! .. apply stdlib${ii}$_sgesvd to r [[this is the recommended option]] if ( wntvr .or. ( nr == n ) ) then ! .. copy r into [v] and overwrite v with the right singular vectors call stdlib${ii}$_slacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset( 'L', nr-1,nr-1, zero,zero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_sgesvd( 'S', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_slapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**t ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_slaset('A', m-nr,nr, zero,zero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_slaset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_slaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! The Requested Number Of The Left Singular Vectors ! is then n1 (n or m) ! [[the optimal ratio n/nr for using lq instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'sgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio * nr > n ) then call stdlib${ii}$_slacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset('L', nr-1,nr-1, zero,zero, v(2_${ik}$,1_${ik}$),ldv) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_slaset('A', n-nr,n, zero,zero, v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_sgesvd( 'S', 'O', n, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_slapmt( .false., n, n, v, ldv, iwork ) ! .. now [v] contains the transposed matrix of the right ! singular vectors of a. the leading n left singular vectors ! are in [u](1:n,1:n) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_slaset('A',m-n,n,zero,zero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_slaset('A',n,n1-n,zero,zero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_slaset( 'A',m-n,n1-n,zero,one,u(n+1,n+1), ldu ) end if end if else call stdlib${ii}$_slacpy( 'U', nr, n, a, lda, u(nr+1,1_${ik}$), ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset('L',nr-1,nr-1,zero,zero,u(nr+2,1_${ik}$),ldu) call stdlib${ii}$_sgelqf( nr, n, u(nr+1,1_${ik}$), ldu, work(n+1),work(n+nr+1), lwork-n-& nr, ierr ) call stdlib${ii}$_slacpy('L',nr,nr,u(nr+1,1_${ik}$),ldu,v,ldv) if ( nr > 1_${ik}$ )call stdlib${ii}$_slaset('U',nr-1,nr-1,zero,zero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_sgesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v, ldv, work(n+nr+& 1_${ik}$), lwork-n-nr, info ) call stdlib${ii}$_slaset('A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_slaset('A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_slaset('A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv) call stdlib${ii}$_sormlq('R','N',n,n,nr,u(nr+1,1_${ik}$),ldu,work(n+1),v, ldv, work(n+& nr+1),lwork-n-nr,ierr) call stdlib${ii}$_slapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_slaset('A',m-nr,nr,zero,zero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_slaset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_slaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if end if end if ! .. end of the "r**t or r" branch end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not. wntuf )call stdlib${ii}$_sormqr( 'L', 'N', m, n1, n, a, lda, work, u,ldu, work(& n+1), lwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_slaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) ! ... end of the "full svd" branch end if ! check whether some singular values are returned as zeros, e.g. ! due to underflow, and update the numerical rank. p = nr do q = p, 1, -1 if ( s(q) > zero ) go to 4002 nr = nr - 1_${ik}$ end do 4002 continue ! .. if numerical rank deficiency is detected, the truncated ! singular values are set to zero. if ( nr < n ) call stdlib${ii}$_slaset( 'G', n-nr,1_${ik}$, zero,zero, s(nr+1), n ) ! .. undo scaling; this may cause overflow in the largest singular ! values. if ( ascaled )call stdlib${ii}$_slascl( 'G',0_${ik}$,0_${ik}$, one,sqrt(real(m,KIND=sp)), nr,1_${ik}$, s, n, ierr & ) if ( conda ) rwork(1_${ik}$) = sconda rwork(2_${ik}$) = p - nr ! .. p-nr is the number of singular values that are computed as ! exact zeros in stdlib${ii}$_sgesvd() applied to the (possibly truncated) ! full row rank triangular (trapezoidal) factor of a. numrank = nr return end subroutine stdlib${ii}$_sgesvdq module subroutine stdlib${ii}$_dgesvdq( joba, jobp, jobr, jobu, jobv, m, n, a, lda,s, u, ldu, v, ldv, & !! DGESVDQ computes the singular value decomposition (SVD) of a real !! M-by-N matrix A, where M >= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N orthogonal matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. numrank, iwork, liwork,work, lwork, rwork, lrwork, info ) use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: joba, jobp, jobr, jobu, jobv integer(${ik}$), intent(in) :: m, n, lda, ldu, ldv, liwork, lrwork integer(${ik}$), intent(out) :: numrank, info integer(${ik}$), intent(inout) :: lwork ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: u(ldu,*), v(ldv,*), work(*) real(dp), intent(out) :: s(*), rwork(*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ierr, iwoff, nr, n1, optratio, p, q integer(${ik}$) :: lwcon, lwqp3, lwrk_dgelqf, lwrk_dgesvd, lwrk_dgesvd2, lwrk_dgeqp3, & lwrk_dgeqrf, lwrk_dormlq, lwrk_dormqr, lwrk_dormqr2, lwlqf, lwqrf, lwsvd, lwsvd2, & lworq, lworq2, lworlq, minwrk, minwrk2, optwrk, optwrk2, iminwrk, rminwrk logical(lk) :: accla, acclm, acclh, ascaled, conda, dntwu, dntwv, lquery, lsvc0, lsvec,& rowprm, rsvec, rtrans, wntua, wntuf, wntur, wntus, wntva, wntvr real(dp) :: big, epsln, rtmp, sconda, sfmin ! Local Arrays real(dp) :: rdummy(1_${ik}$) ! Intrinsic Functions ! test the input arguments wntus = stdlib_lsame( jobu, 'S' ) .or. stdlib_lsame( jobu, 'U' ) wntur = stdlib_lsame( jobu, 'R' ) wntua = stdlib_lsame( jobu, 'A' ) wntuf = stdlib_lsame( jobu, 'F' ) lsvc0 = wntus .or. wntur .or. wntua lsvec = lsvc0 .or. wntuf dntwu = stdlib_lsame( jobu, 'N' ) wntvr = stdlib_lsame( jobv, 'R' ) wntva = stdlib_lsame( jobv, 'A' ) .or. stdlib_lsame( jobv, 'V' ) rsvec = wntvr .or. wntva dntwv = stdlib_lsame( jobv, 'N' ) accla = stdlib_lsame( joba, 'A' ) acclm = stdlib_lsame( joba, 'M' ) conda = stdlib_lsame( joba, 'E' ) acclh = stdlib_lsame( joba, 'H' ) .or. conda rowprm = stdlib_lsame( jobp, 'P' ) rtrans = stdlib_lsame( jobr, 'T' ) if ( rowprm ) then if ( conda ) then iminwrk = max( 1_${ik}$, n + m - 1_${ik}$ + n ) else iminwrk = max( 1_${ik}$, n + m - 1_${ik}$ ) end if rminwrk = max( 2_${ik}$, m ) else if ( conda ) then iminwrk = max( 1_${ik}$, n + n ) else iminwrk = max( 1_${ik}$, n ) end if rminwrk = 2_${ik}$ end if lquery = (liwork == -1_${ik}$ .or. lwork == -1_${ik}$ .or. lrwork == -1_${ik}$) info = 0_${ik}$ if ( .not. ( accla .or. acclm .or. acclh ) ) then info = -1_${ik}$ else if ( .not.( rowprm .or. stdlib_lsame( jobp, 'N' ) ) ) then info = -2_${ik}$ else if ( .not.( rtrans .or. stdlib_lsame( jobr, 'N' ) ) ) then info = -3_${ik}$ else if ( .not.( lsvec .or. dntwu ) ) then info = -4_${ik}$ else if ( wntur .and. wntva ) then info = -5_${ik}$ else if ( .not.( rsvec .or. dntwv )) then info = -5_${ik}$ else if ( m<0_${ik}$ ) then info = -6_${ik}$ else if ( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -7_${ik}$ else if ( lda big / sqrt(real(m,KIND=dp)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_dlascl('G',0_${ik}$,0_${ik}$,sqrt(real(m,KIND=dp)),one, m,n, a,lda, ierr) ascaled = .true. end if call stdlib${ii}$_dlaswp( n, a, lda, 1_${ik}$, m-1, iwork(n+1), 1_${ik}$ ) end if ! .. at this stage, preemptive scaling is done only to avoid column ! norms overflows during the qr factorization. the svd procedure should ! have its own scaling to save the singular values from overflows and ! underflows. that depends on the svd procedure. if ( .not.rowprm ) then rtmp = stdlib${ii}$_dlange( 'M', m, n, a, lda, rdummy ) if ( ( rtmp /= rtmp ) .or.( (rtmp*zero) /= zero ) ) then info = -8_${ik}$ call stdlib${ii}$_xerbla( 'DGESVDQ', -info ) return end if if ( rtmp > big / sqrt(real(m,KIND=dp)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_dlascl('G',0_${ik}$,0_${ik}$, sqrt(real(m,KIND=dp)),one, m,n, a,lda, ierr) ascaled = .true. end if end if ! Qr Factorization With Column Pivoting ! a * p = q * [ r ] ! [ 0 ] do p = 1, n ! All Columns Are Free Columns iwork(p) = 0_${ik}$ end do call stdlib${ii}$_dgeqp3( m, n, a, lda, iwork, work, work(n+1), lwork-n,ierr ) ! if the user requested accuracy level allows truncation in the ! computed upper triangular factor, the matrix r is examined and, ! if possible, replaced with its leading upper trapezoidal part. epsln = stdlib${ii}$_dlamch('E') sfmin = stdlib${ii}$_dlamch('S') ! small = sfmin / epsln nr = n if ( accla ) then ! standard absolute error bound suffices. all sigma_i with ! sigma_i < n*eps*||a||_f are flushed to zero. this is an ! aggressive enforcement of lower numerical rank by introducing a ! backward error of the order of n*eps*||a||_f. nr = 1_${ik}$ rtmp = sqrt(real(n,KIND=dp))*epsln loop_3002: do p = 2, n if ( abs(a(p,p)) < (rtmp*abs(a(1,1))) ) exit loop_3002 nr = nr + 1_${ik}$ end do loop_3002 elseif ( acclm ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r is used as the criterion for being ! close-to-rank-deficient. the threshold is set to epsln=stdlib${ii}$_dlamch('e'). ! [[this can be made more flexible by replacing this hard-coded value ! with a user specified threshold.]] also, the values that underflow ! will be truncated. nr = 1_${ik}$ loop_3402: do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < sfmin ) ) exit loop_3402 nr = nr + 1_${ik}$ end do loop_3402 else ! Rrqr Not Authorized To Determine Numerical Rank Except In The ! obvious case of zero pivots. ! .. inspect r for exact zeros on the diagonal; ! r(i,i)=0 => r(i:n,i:n)=0. nr = 1_${ik}$ loop_3502: do p = 2, n if ( abs(a(p,p)) == zero ) exit loop_3502 nr = nr + 1_${ik}$ end do loop_3502 if ( conda ) then ! estimate the scaled condition number of a. use the fact that it is ! the same as the scaled condition number of r. ! V Is Used As Workspace call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, v, ldv ) ! only the leading nr x nr submatrix of the triangular factor ! is considered. only if nr=n will this give a reliable error ! bound. however, even for nr < n, this can be used on an ! expert level and obtain useful information in the sense of ! perturbation theory. do p = 1, nr rtmp = stdlib${ii}$_dnrm2( p, v(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_dscal( p, one/rtmp, v(1_${ik}$,p), 1_${ik}$ ) end do if ( .not. ( lsvec .or. rsvec ) ) then call stdlib${ii}$_dpocon( 'U', nr, v, ldv, one, rtmp,work, iwork(n+iwoff), ierr & ) else call stdlib${ii}$_dpocon( 'U', nr, v, ldv, one, rtmp,work(n+1), iwork(n+iwoff), & ierr ) end if sconda = one / sqrt(rtmp) ! for nr=n, sconda is an estimate of sqrt(||(r^* * r)^(-1)||_1), ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda ! see the reference [1] for more details. end if endif if ( wntur ) then n1 = nr else if ( wntus .or. wntuf) then n1 = n else if ( wntua ) then n1 = m end if if ( .not. ( rsvec .or. lsvec ) ) then ! ....................................................................... ! Only The Singular Values Are Requested ! ....................................................................... if ( rtrans ) then ! .. compute the singular values of r**t = [a](1:nr,1:n)**t ! .. set the lower triangle of [a] to [a](1:nr,1:n)**t and ! the upper triangle of [a] to zero. do p = 1, min( n, nr ) do q = p + 1, n a(q,p) = a(p,q) if ( q <= nr ) a(p,q) = zero end do end do call stdlib${ii}$_dgesvd( 'N', 'N', n, nr, a, lda, s, u, ldu,v, ldv, work, lwork, info & ) else ! .. compute the singular values of r = [a](1:nr,1:n) if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset( 'L', nr-1,nr-1, zero,zero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_dgesvd( 'N', 'N', nr, n, a, lda, s, u, ldu,v, ldv, work, lwork, info & ) end if else if ( lsvec .and. ( .not. rsvec) ) then ! ....................................................................... ! The Singular Values And The Left Singular Vectors Requested ! ......................................................................."""""""" if ( rtrans ) then ! .. apply stdlib${ii}$_dgesvd to r**t ! .. copy r**t into [u] and overwrite [u] with the right singular ! vectors of r do p = 1, nr do q = p, n u(q,p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset( 'U', nr-1,nr-1, zero,zero, u(1_${ik}$,2_${ik}$), ldu ) ! .. the left singular vectors not computed, the nr right singular ! vectors overwrite [u](1:nr,1:nr) as transposed. these ! will be pre-multiplied by q to build the left singular vectors of a. call stdlib${ii}$_dgesvd( 'N', 'O', n, nr, u, ldu, s, u, ldu,u, ldu, work(n+1), & lwork-n, info ) do p = 1, nr do q = p + 1, nr rtmp = u(q,p) u(q,p) = u(p,q) u(p,q) = rtmp end do end do else ! Apply Stdlib_Dgesvd To R ! .. copy r into [u] and overwrite [u] with the left singular vectors call stdlib${ii}$_dlacpy( 'U', nr, n, a, lda, u, ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset( 'L', nr-1, nr-1, zero, zero, u(2_${ik}$,1_${ik}$), ldu ) ! .. the right singular vectors not computed, the nr left singular ! vectors overwrite [u](1:nr,1:nr) call stdlib${ii}$_dgesvd( 'O', 'N', nr, n, u, ldu, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) ! .. now [u](1:nr,1:nr) contains the nr left singular vectors of ! r. these will be pre-multiplied by q to build the left singular ! vectors of a. end if ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. ( .not.wntuf ) ) then call stdlib${ii}$_dlaset('A', m-nr, nr, zero, zero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_dlaset( 'A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1), ldu ) call stdlib${ii}$_dlaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not.wntuf )call stdlib${ii}$_dormqr( 'L', 'N', m, n1, n, a, lda, work, u,ldu, work(& n+1), lwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_dlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) else if ( rsvec .and. ( .not. lsvec ) ) then ! ....................................................................... ! The Singular Values And The Right Singular Vectors Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_dgesvd to r**t ! .. copy r**t into v and overwrite v with the left singular vectors do p = 1, nr do q = p, n v(q,p) = (a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset( 'U', nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**t overwrite v, the right singular ! vectors not computed if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_dgesvd( 'O', 'N', n, nr, v, ldv, s, u, ldu,u, ldu, work(n+1), & lwork-n, info ) do p = 1, nr do q = p + 1, nr rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do if ( nr < n ) then do p = 1, nr do q = nr + 1, n v(p,q) = v(q,p) end do end do end if call stdlib${ii}$_dlapmt( .false., nr, n, v, ldv, iwork ) else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:n,1:nr) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the qr factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_dlaset('G', n, n-nr, zero, zero, v(1_${ik}$,nr+1), ldv) call stdlib${ii}$_dgesvd( 'O', 'N', n, n, v, ldv, s, u, ldu,u, ldu, work(n+1), & lwork-n, info ) do p = 1, n do q = p + 1, n rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do call stdlib${ii}$_dlapmt( .false., n, n, v, ldv, iwork ) end if else ! Aply Stdlib_Dgesvd To R ! Copy R Into V And Overwrite V With The Right Singular Vectors call stdlib${ii}$_dlacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset( 'L', nr-1, nr-1, zero, zero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors overwrite v, the nr left singular ! vectors stored in u(1:nr,1:nr) if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_dgesvd( 'N', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_dlapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**t else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:nr,1:n) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the lq factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_dlaset('G', n-nr, n, zero,zero, v(nr+1,1_${ik}$), ldv) call stdlib${ii}$_dgesvd( 'N', 'O', n, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_dlapmt( .false., n, n, v, ldv, iwork ) end if ! .. now [v] contains the transposed matrix of the right singular ! vectors of a. end if else ! ....................................................................... ! Full Svd Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_dgesvd to r**t [[this option is left for r if ( wntvr .or. ( nr == n ) ) then ! .. copy r**t into [v] and overwrite [v] with the left singular ! vectors of r**t do p = 1, nr do q = p, n v(q,p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset( 'U', nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**t overwrite [v], the nr right ! singular vectors of r**t stored in [u](1:nr,1:nr) as transposed call stdlib${ii}$_dgesvd( 'O', 'A', n, nr, v, ldv, s, v, ldv,u, ldu, work(n+1), & lwork-n, info ) ! Assemble V do p = 1, nr do q = p + 1, nr rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do if ( nr < n ) then do p = 1, nr do q = nr+1, n v(p,q) = v(q,p) end do end do end if call stdlib${ii}$_dlapmt( .false., nr, n, v, ldv, iwork ) do p = 1, nr do q = p + 1, nr rtmp = u(q,p) u(q,p) = u(p,q) u(p,q) = rtmp end do end do if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_dlaset('A', m-nr,nr, zero,zero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_dlaset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_dlaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! .. copy r**t into [v] and overwrite [v] with the left singular ! vectors of r**t ! [[the optimal ratio n/nr for using qrf instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'dgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio*nr > n ) then do p = 1, nr do q = p, n v(q,p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset('U',nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_dlaset('A',n,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_dgesvd( 'O', 'A', n, n, v, ldv, s, v, ldv,u, ldu, work(n+1), & lwork-n, info ) do p = 1, n do q = p + 1, n rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do call stdlib${ii}$_dlapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). do p = 1, n do q = p + 1, n rtmp = u(q,p) u(q,p) = u(p,q) u(p,q) = rtmp end do end do if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_dlaset('A',m-n,n,zero,zero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_dlaset('A',n,n1-n,zero,zero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_dlaset('A',m-n,n1-n,zero,one,u(n+1,n+1), ldu ) end if end if else ! .. copy r**t into [u] and overwrite [u] with the right ! singular vectors of r do p = 1, nr do q = p, n u(q,nr+p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset('U',nr-1,nr-1,zero,zero,u(1_${ik}$,nr+2),ldu) call stdlib${ii}$_dgeqrf( n, nr, u(1_${ik}$,nr+1), ldu, work(n+1),work(n+nr+1), lwork-& n-nr, ierr ) do p = 1, nr do q = 1, n v(q,p) = u(p,nr+q) end do end do if (nr>1_${ik}$) call stdlib${ii}$_dlaset('U',nr-1,nr-1,zero,zero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_dgesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v,ldv, work(n+nr+1)& ,lwork-n-nr, info ) call stdlib${ii}$_dlaset('A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_dlaset('A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_dlaset('A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv) call stdlib${ii}$_dormqr('R','C', n, n, nr, u(1_${ik}$,nr+1), ldu,work(n+1),v,ldv,work(& n+nr+1),lwork-n-nr,ierr) call stdlib${ii}$_dlapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_dlaset('A',m-nr,nr,zero,zero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_dlaset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_dlaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1),ldu) end if end if end if end if else ! .. apply stdlib${ii}$_dgesvd to r [[this is the recommended option]] if ( wntvr .or. ( nr == n ) ) then ! .. copy r into [v] and overwrite v with the right singular vectors call stdlib${ii}$_dlacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset( 'L', nr-1,nr-1, zero,zero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_dgesvd( 'S', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_dlapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**t ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_dlaset('A', m-nr,nr, zero,zero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_dlaset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_dlaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! The Requested Number Of The Left Singular Vectors ! is then n1 (n or m) ! [[the optimal ratio n/nr for using lq instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'dgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio * nr > n ) then call stdlib${ii}$_dlacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset('L', nr-1,nr-1, zero,zero, v(2_${ik}$,1_${ik}$),ldv) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_dlaset('A', n-nr,n, zero,zero, v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_dgesvd( 'S', 'O', n, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_dlapmt( .false., n, n, v, ldv, iwork ) ! .. now [v] contains the transposed matrix of the right ! singular vectors of a. the leading n left singular vectors ! are in [u](1:n,1:n) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_dlaset('A',m-n,n,zero,zero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_dlaset('A',n,n1-n,zero,zero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_dlaset( 'A',m-n,n1-n,zero,one,u(n+1,n+1), ldu ) end if end if else call stdlib${ii}$_dlacpy( 'U', nr, n, a, lda, u(nr+1,1_${ik}$), ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset('L',nr-1,nr-1,zero,zero,u(nr+2,1_${ik}$),ldu) call stdlib${ii}$_dgelqf( nr, n, u(nr+1,1_${ik}$), ldu, work(n+1),work(n+nr+1), lwork-n-& nr, ierr ) call stdlib${ii}$_dlacpy('L',nr,nr,u(nr+1,1_${ik}$),ldu,v,ldv) if ( nr > 1_${ik}$ )call stdlib${ii}$_dlaset('U',nr-1,nr-1,zero,zero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_dgesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v, ldv, work(n+nr+& 1_${ik}$), lwork-n-nr, info ) call stdlib${ii}$_dlaset('A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_dlaset('A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_dlaset('A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv) call stdlib${ii}$_dormlq('R','N',n,n,nr,u(nr+1,1_${ik}$),ldu,work(n+1),v, ldv, work(n+& nr+1),lwork-n-nr,ierr) call stdlib${ii}$_dlapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_dlaset('A',m-nr,nr,zero,zero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_dlaset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_dlaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if end if end if ! .. end of the "r**t or r" branch end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not. wntuf )call stdlib${ii}$_dormqr( 'L', 'N', m, n1, n, a, lda, work, u,ldu, work(& n+1), lwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_dlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) ! ... end of the "full svd" branch end if ! check whether some singular values are returned as zeros, e.g. ! due to underflow, and update the numerical rank. p = nr do q = p, 1, -1 if ( s(q) > zero ) go to 4002 nr = nr - 1_${ik}$ end do 4002 continue ! .. if numerical rank deficiency is detected, the truncated ! singular values are set to zero. if ( nr < n ) call stdlib${ii}$_dlaset( 'G', n-nr,1_${ik}$, zero,zero, s(nr+1), n ) ! .. undo scaling; this may cause overflow in the largest singular ! values. if ( ascaled )call stdlib${ii}$_dlascl( 'G',0_${ik}$,0_${ik}$, one,sqrt(real(m,KIND=dp)), nr,1_${ik}$, s, n, ierr & ) if ( conda ) rwork(1_${ik}$) = sconda rwork(2_${ik}$) = p - nr ! .. p-nr is the number of singular values that are computed as ! exact zeros in stdlib${ii}$_dgesvd() applied to the (possibly truncated) ! full row rank triangular (trapezoidal) factor of a. numrank = nr return end subroutine stdlib${ii}$_dgesvdq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$gesvdq( joba, jobp, jobr, jobu, jobv, m, n, a, lda,s, u, ldu, v, ldv, & !! DGESVDQ: computes the singular value decomposition (SVD) of a real !! M-by-N matrix A, where M >= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N orthogonal matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. numrank, iwork, liwork,work, lwork, rwork, lrwork, info ) use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: joba, jobp, jobr, jobu, jobv integer(${ik}$), intent(in) :: m, n, lda, ldu, ldv, liwork, lrwork integer(${ik}$), intent(out) :: numrank, info integer(${ik}$), intent(inout) :: lwork ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: u(ldu,*), v(ldv,*), work(*) real(${rk}$), intent(out) :: s(*), rwork(*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ierr, iwoff, nr, n1, optratio, p, q integer(${ik}$) :: lwcon, lwqp3, lwrk_qgelqf, lwrk_qgesvd, lwrk_qgesvd2, lwrk_qgeqp3, & lwrk_qgeqrf, lwrk_qormlq, lwrk_qormqr, lwrk_qormqr2, lwlqf, lwqrf, lwsvd, lwsvd2, & lworq, lworq2, lworlq, minwrk, minwrk2, optwrk, optwrk2, iminwrk, rminwrk logical(lk) :: accla, acclm, acclh, ascaled, conda, dntwu, dntwv, lquery, lsvc0, lsvec,& rowprm, rsvec, rtrans, wntua, wntuf, wntur, wntus, wntva, wntvr real(${rk}$) :: big, epsln, rtmp, sconda, sfmin ! Local Arrays real(${rk}$) :: rdummy(1_${ik}$) ! Intrinsic Functions ! test the input arguments wntus = stdlib_lsame( jobu, 'S' ) .or. stdlib_lsame( jobu, 'U' ) wntur = stdlib_lsame( jobu, 'R' ) wntua = stdlib_lsame( jobu, 'A' ) wntuf = stdlib_lsame( jobu, 'F' ) lsvc0 = wntus .or. wntur .or. wntua lsvec = lsvc0 .or. wntuf dntwu = stdlib_lsame( jobu, 'N' ) wntvr = stdlib_lsame( jobv, 'R' ) wntva = stdlib_lsame( jobv, 'A' ) .or. stdlib_lsame( jobv, 'V' ) rsvec = wntvr .or. wntva dntwv = stdlib_lsame( jobv, 'N' ) accla = stdlib_lsame( joba, 'A' ) acclm = stdlib_lsame( joba, 'M' ) conda = stdlib_lsame( joba, 'E' ) acclh = stdlib_lsame( joba, 'H' ) .or. conda rowprm = stdlib_lsame( jobp, 'P' ) rtrans = stdlib_lsame( jobr, 'T' ) if ( rowprm ) then if ( conda ) then iminwrk = max( 1_${ik}$, n + m - 1_${ik}$ + n ) else iminwrk = max( 1_${ik}$, n + m - 1_${ik}$ ) end if rminwrk = max( 2_${ik}$, m ) else if ( conda ) then iminwrk = max( 1_${ik}$, n + n ) else iminwrk = max( 1_${ik}$, n ) end if rminwrk = 2_${ik}$ end if lquery = (liwork == -1_${ik}$ .or. lwork == -1_${ik}$ .or. lrwork == -1_${ik}$) info = 0_${ik}$ if ( .not. ( accla .or. acclm .or. acclh ) ) then info = -1_${ik}$ else if ( .not.( rowprm .or. stdlib_lsame( jobp, 'N' ) ) ) then info = -2_${ik}$ else if ( .not.( rtrans .or. stdlib_lsame( jobr, 'N' ) ) ) then info = -3_${ik}$ else if ( .not.( lsvec .or. dntwu ) ) then info = -4_${ik}$ else if ( wntur .and. wntva ) then info = -5_${ik}$ else if ( .not.( rsvec .or. dntwv )) then info = -5_${ik}$ else if ( m<0_${ik}$ ) then info = -6_${ik}$ else if ( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -7_${ik}$ else if ( lda big / sqrt(real(m,KIND=${rk}$)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_${ri}$lascl('G',0_${ik}$,0_${ik}$,sqrt(real(m,KIND=${rk}$)),one, m,n, a,lda, ierr) ascaled = .true. end if call stdlib${ii}$_${ri}$laswp( n, a, lda, 1_${ik}$, m-1, iwork(n+1), 1_${ik}$ ) end if ! .. at this stage, preemptive scaling is done only to avoid column ! norms overflows during the qr factorization. the svd procedure should ! have its own scaling to save the singular values from overflows and ! underflows. that depends on the svd procedure. if ( .not.rowprm ) then rtmp = stdlib${ii}$_${ri}$lange( 'M', m, n, a, lda, rdummy ) if ( ( rtmp /= rtmp ) .or.( (rtmp*zero) /= zero ) ) then info = -8_${ik}$ call stdlib${ii}$_xerbla( 'DGESVDQ', -info ) return end if if ( rtmp > big / sqrt(real(m,KIND=${rk}$)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_${ri}$lascl('G',0_${ik}$,0_${ik}$, sqrt(real(m,KIND=${rk}$)),one, m,n, a,lda, ierr) ascaled = .true. end if end if ! Qr Factorization With Column Pivoting ! a * p = q * [ r ] ! [ 0 ] do p = 1, n ! All Columns Are Free Columns iwork(p) = 0_${ik}$ end do call stdlib${ii}$_${ri}$geqp3( m, n, a, lda, iwork, work, work(n+1), lwork-n,ierr ) ! if the user requested accuracy level allows truncation in the ! computed upper triangular factor, the matrix r is examined and, ! if possible, replaced with its leading upper trapezoidal part. epsln = stdlib${ii}$_${ri}$lamch('E') sfmin = stdlib${ii}$_${ri}$lamch('S') ! small = sfmin / epsln nr = n if ( accla ) then ! standard absolute error bound suffices. all sigma_i with ! sigma_i < n*eps*||a||_f are flushed to zero. this is an ! aggressive enforcement of lower numerical rank by introducing a ! backward error of the order of n*eps*||a||_f. nr = 1_${ik}$ rtmp = sqrt(real(n,KIND=${rk}$))*epsln loop_3002: do p = 2, n if ( abs(a(p,p)) < (rtmp*abs(a(1,1))) ) exit loop_3002 nr = nr + 1_${ik}$ end do loop_3002 elseif ( acclm ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r is used as the criterion for being ! close-to-rank-deficient. the threshold is set to epsln=stdlib${ii}$_${ri}$lamch('e'). ! [[this can be made more flexible by replacing this hard-coded value ! with a user specified threshold.]] also, the values that underflow ! will be truncated. nr = 1_${ik}$ loop_3402: do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < sfmin ) ) exit loop_3402 nr = nr + 1_${ik}$ end do loop_3402 else ! Rrqr Not Authorized To Determine Numerical Rank Except In The ! obvious case of zero pivots. ! .. inspect r for exact zeros on the diagonal; ! r(i,i)=0 => r(i:n,i:n)=0. nr = 1_${ik}$ loop_3502: do p = 2, n if ( abs(a(p,p)) == zero ) exit loop_3502 nr = nr + 1_${ik}$ end do loop_3502 if ( conda ) then ! estimate the scaled condition number of a. use the fact that it is ! the same as the scaled condition number of r. ! V Is Used As Workspace call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, v, ldv ) ! only the leading nr x nr submatrix of the triangular factor ! is considered. only if nr=n will this give a reliable error ! bound. however, even for nr < n, this can be used on an ! expert level and obtain useful information in the sense of ! perturbation theory. do p = 1, nr rtmp = stdlib${ii}$_${ri}$nrm2( p, v(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( p, one/rtmp, v(1_${ik}$,p), 1_${ik}$ ) end do if ( .not. ( lsvec .or. rsvec ) ) then call stdlib${ii}$_${ri}$pocon( 'U', nr, v, ldv, one, rtmp,work, iwork(n+iwoff), ierr & ) else call stdlib${ii}$_${ri}$pocon( 'U', nr, v, ldv, one, rtmp,work(n+1), iwork(n+iwoff), & ierr ) end if sconda = one / sqrt(rtmp) ! for nr=n, sconda is an estimate of sqrt(||(r^* * r)^(-1)||_1), ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda ! see the reference [1] for more details. end if endif if ( wntur ) then n1 = nr else if ( wntus .or. wntuf) then n1 = n else if ( wntua ) then n1 = m end if if ( .not. ( rsvec .or. lsvec ) ) then ! ....................................................................... ! Only The Singular Values Are Requested ! ....................................................................... if ( rtrans ) then ! .. compute the singular values of r**t = [a](1:nr,1:n)**t ! .. set the lower triangle of [a] to [a](1:nr,1:n)**t and ! the upper triangle of [a] to zero. do p = 1, min( n, nr ) do q = p + 1, n a(q,p) = a(p,q) if ( q <= nr ) a(p,q) = zero end do end do call stdlib${ii}$_${ri}$gesvd( 'N', 'N', n, nr, a, lda, s, u, ldu,v, ldv, work, lwork, info & ) else ! .. compute the singular values of r = [a](1:nr,1:n) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'L', nr-1,nr-1, zero,zero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_${ri}$gesvd( 'N', 'N', nr, n, a, lda, s, u, ldu,v, ldv, work, lwork, info & ) end if else if ( lsvec .and. ( .not. rsvec) ) then ! ....................................................................... ! The Singular Values And The Left Singular Vectors Requested ! ......................................................................."""""""" if ( rtrans ) then ! .. apply stdlib${ii}$_${ri}$gesvd to r**t ! .. copy r**t into [u] and overwrite [u] with the right singular ! vectors of r do p = 1, nr do q = p, n u(q,p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'U', nr-1,nr-1, zero,zero, u(1_${ik}$,2_${ik}$), ldu ) ! .. the left singular vectors not computed, the nr right singular ! vectors overwrite [u](1:nr,1:nr) as transposed. these ! will be pre-multiplied by q to build the left singular vectors of a. call stdlib${ii}$_${ri}$gesvd( 'N', 'O', n, nr, u, ldu, s, u, ldu,u, ldu, work(n+1), & lwork-n, info ) do p = 1, nr do q = p + 1, nr rtmp = u(q,p) u(q,p) = u(p,q) u(p,q) = rtmp end do end do else ! Apply Stdlib_Dgesvd To R ! .. copy r into [u] and overwrite [u] with the left singular vectors call stdlib${ii}$_${ri}$lacpy( 'U', nr, n, a, lda, u, ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'L', nr-1, nr-1, zero, zero, u(2_${ik}$,1_${ik}$), ldu ) ! .. the right singular vectors not computed, the nr left singular ! vectors overwrite [u](1:nr,1:nr) call stdlib${ii}$_${ri}$gesvd( 'O', 'N', nr, n, u, ldu, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) ! .. now [u](1:nr,1:nr) contains the nr left singular vectors of ! r. these will be pre-multiplied by q to build the left singular ! vectors of a. end if ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. ( .not.wntuf ) ) then call stdlib${ii}$_${ri}$laset('A', m-nr, nr, zero, zero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_${ri}$laset( 'A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1), ldu ) call stdlib${ii}$_${ri}$laset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not.wntuf )call stdlib${ii}$_${ri}$ormqr( 'L', 'N', m, n1, n, a, lda, work, u,ldu, work(& n+1), lwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_${ri}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) else if ( rsvec .and. ( .not. lsvec ) ) then ! ....................................................................... ! The Singular Values And The Right Singular Vectors Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_${ri}$gesvd to r**t ! .. copy r**t into v and overwrite v with the left singular vectors do p = 1, nr do q = p, n v(q,p) = (a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'U', nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**t overwrite v, the right singular ! vectors not computed if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_${ri}$gesvd( 'O', 'N', n, nr, v, ldv, s, u, ldu,u, ldu, work(n+1), & lwork-n, info ) do p = 1, nr do q = p + 1, nr rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do if ( nr < n ) then do p = 1, nr do q = nr + 1, n v(p,q) = v(q,p) end do end do end if call stdlib${ii}$_${ri}$lapmt( .false., nr, n, v, ldv, iwork ) else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:n,1:nr) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the qr factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_${ri}$laset('G', n, n-nr, zero, zero, v(1_${ik}$,nr+1), ldv) call stdlib${ii}$_${ri}$gesvd( 'O', 'N', n, n, v, ldv, s, u, ldu,u, ldu, work(n+1), & lwork-n, info ) do p = 1, n do q = p + 1, n rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do call stdlib${ii}$_${ri}$lapmt( .false., n, n, v, ldv, iwork ) end if else ! Aply Stdlib_Dgesvd To R ! Copy R Into V And Overwrite V With The Right Singular Vectors call stdlib${ii}$_${ri}$lacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'L', nr-1, nr-1, zero, zero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors overwrite v, the nr left singular ! vectors stored in u(1:nr,1:nr) if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_${ri}$gesvd( 'N', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_${ri}$lapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**t else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:nr,1:n) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the lq factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_${ri}$laset('G', n-nr, n, zero,zero, v(nr+1,1_${ik}$), ldv) call stdlib${ii}$_${ri}$gesvd( 'N', 'O', n, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_${ri}$lapmt( .false., n, n, v, ldv, iwork ) end if ! .. now [v] contains the transposed matrix of the right singular ! vectors of a. end if else ! ....................................................................... ! Full Svd Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_${ri}$gesvd to r**t [[this option is left for r if ( wntvr .or. ( nr == n ) ) then ! .. copy r**t into [v] and overwrite [v] with the left singular ! vectors of r**t do p = 1, nr do q = p, n v(q,p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'U', nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**t overwrite [v], the nr right ! singular vectors of r**t stored in [u](1:nr,1:nr) as transposed call stdlib${ii}$_${ri}$gesvd( 'O', 'A', n, nr, v, ldv, s, v, ldv,u, ldu, work(n+1), & lwork-n, info ) ! Assemble V do p = 1, nr do q = p + 1, nr rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do if ( nr < n ) then do p = 1, nr do q = nr+1, n v(p,q) = v(q,p) end do end do end if call stdlib${ii}$_${ri}$lapmt( .false., nr, n, v, ldv, iwork ) do p = 1, nr do q = p + 1, nr rtmp = u(q,p) u(q,p) = u(p,q) u(p,q) = rtmp end do end do if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ri}$laset('A', m-nr,nr, zero,zero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_${ri}$laset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_${ri}$laset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! .. copy r**t into [v] and overwrite [v] with the left singular ! vectors of r**t ! [[the optimal ratio n/nr for using qrf instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'dgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio*nr > n ) then do p = 1, nr do q = p, n v(q,p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset('U',nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_${ri}$laset('A',n,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_${ri}$gesvd( 'O', 'A', n, n, v, ldv, s, v, ldv,u, ldu, work(n+1), & lwork-n, info ) do p = 1, n do q = p + 1, n rtmp = v(q,p) v(q,p) = v(p,q) v(p,q) = rtmp end do end do call stdlib${ii}$_${ri}$lapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). do p = 1, n do q = p + 1, n rtmp = u(q,p) u(q,p) = u(p,q) u(p,q) = rtmp end do end do if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ri}$laset('A',m-n,n,zero,zero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_${ri}$laset('A',n,n1-n,zero,zero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_${ri}$laset('A',m-n,n1-n,zero,one,u(n+1,n+1), ldu ) end if end if else ! .. copy r**t into [u] and overwrite [u] with the right ! singular vectors of r do p = 1, nr do q = p, n u(q,nr+p) = a(p,q) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset('U',nr-1,nr-1,zero,zero,u(1_${ik}$,nr+2),ldu) call stdlib${ii}$_${ri}$geqrf( n, nr, u(1_${ik}$,nr+1), ldu, work(n+1),work(n+nr+1), lwork-& n-nr, ierr ) do p = 1, nr do q = 1, n v(q,p) = u(p,nr+q) end do end do if (nr>1_${ik}$) call stdlib${ii}$_${ri}$laset('U',nr-1,nr-1,zero,zero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_${ri}$gesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v,ldv, work(n+nr+1)& ,lwork-n-nr, info ) call stdlib${ii}$_${ri}$laset('A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_${ri}$laset('A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_${ri}$laset('A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv) call stdlib${ii}$_${ri}$ormqr('R','C', n, n, nr, u(1_${ik}$,nr+1), ldu,work(n+1),v,ldv,work(& n+nr+1),lwork-n-nr,ierr) call stdlib${ii}$_${ri}$lapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ri}$laset('A',m-nr,nr,zero,zero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_${ri}$laset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_${ri}$laset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1),ldu) end if end if end if end if else ! .. apply stdlib${ii}$_${ri}$gesvd to r [[this is the recommended option]] if ( wntvr .or. ( nr == n ) ) then ! .. copy r into [v] and overwrite v with the right singular vectors call stdlib${ii}$_${ri}$lacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'L', nr-1,nr-1, zero,zero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_${ri}$gesvd( 'S', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_${ri}$lapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**t ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ri}$laset('A', m-nr,nr, zero,zero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_${ri}$laset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_${ri}$laset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! The Requested Number Of The Left Singular Vectors ! is then n1 (n or m) ! [[the optimal ratio n/nr for using lq instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'dgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio * nr > n ) then call stdlib${ii}$_${ri}$lacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset('L', nr-1,nr-1, zero,zero, v(2_${ik}$,1_${ik}$),ldv) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_${ri}$laset('A', n-nr,n, zero,zero, v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_${ri}$gesvd( 'S', 'O', n, n, v, ldv, s, u, ldu,v, ldv, work(n+1), & lwork-n, info ) call stdlib${ii}$_${ri}$lapmt( .false., n, n, v, ldv, iwork ) ! .. now [v] contains the transposed matrix of the right ! singular vectors of a. the leading n left singular vectors ! are in [u](1:n,1:n) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ri}$laset('A',m-n,n,zero,zero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_${ri}$laset('A',n,n1-n,zero,zero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_${ri}$laset( 'A',m-n,n1-n,zero,one,u(n+1,n+1), ldu ) end if end if else call stdlib${ii}$_${ri}$lacpy( 'U', nr, n, a, lda, u(nr+1,1_${ik}$), ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset('L',nr-1,nr-1,zero,zero,u(nr+2,1_${ik}$),ldu) call stdlib${ii}$_${ri}$gelqf( nr, n, u(nr+1,1_${ik}$), ldu, work(n+1),work(n+nr+1), lwork-n-& nr, ierr ) call stdlib${ii}$_${ri}$lacpy('L',nr,nr,u(nr+1,1_${ik}$),ldu,v,ldv) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ri}$laset('U',nr-1,nr-1,zero,zero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_${ri}$gesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v, ldv, work(n+nr+& 1_${ik}$), lwork-n-nr, info ) call stdlib${ii}$_${ri}$laset('A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_${ri}$laset('A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_${ri}$laset('A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv) call stdlib${ii}$_${ri}$ormlq('R','N',n,n,nr,u(nr+1,1_${ik}$),ldu,work(n+1),v, ldv, work(n+& nr+1),lwork-n-nr,ierr) call stdlib${ii}$_${ri}$lapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ri}$laset('A',m-nr,nr,zero,zero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_${ri}$laset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_${ri}$laset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if end if end if ! .. end of the "r**t or r" branch end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not. wntuf )call stdlib${ii}$_${ri}$ormqr( 'L', 'N', m, n1, n, a, lda, work, u,ldu, work(& n+1), lwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_${ri}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) ! ... end of the "full svd" branch end if ! check whether some singular values are returned as zeros, e.g. ! due to underflow, and update the numerical rank. p = nr do q = p, 1, -1 if ( s(q) > zero ) go to 4002 nr = nr - 1_${ik}$ end do 4002 continue ! .. if numerical rank deficiency is detected, the truncated ! singular values are set to zero. if ( nr < n ) call stdlib${ii}$_${ri}$laset( 'G', n-nr,1_${ik}$, zero,zero, s(nr+1), n ) ! .. undo scaling; this may cause overflow in the largest singular ! values. if ( ascaled )call stdlib${ii}$_${ri}$lascl( 'G',0_${ik}$,0_${ik}$, one,sqrt(real(m,KIND=${rk}$)), nr,1_${ik}$, s, n, ierr & ) if ( conda ) rwork(1_${ik}$) = sconda rwork(2_${ik}$) = p - nr ! .. p-nr is the number of singular values that are computed as ! exact zeros in stdlib${ii}$_${ri}$gesvd() applied to the (possibly truncated) ! full row rank triangular (trapezoidal) factor of a. numrank = nr return end subroutine stdlib${ii}$_${ri}$gesvdq #:endif #:endfor module subroutine stdlib${ii}$_cgesvdq( joba, jobp, jobr, jobu, jobv, m, n, a, lda,s, u, ldu, v, ldv, & !! CGESVDQ computes the singular value decomposition (SVD) of a complex !! M-by-N matrix A, where M >= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N unitary matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. numrank, iwork, liwork,cwork, lcwork, rwork, lrwork, info ) use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: joba, jobp, jobr, jobu, jobv integer(${ik}$), intent(in) :: m, n, lda, ldu, ldv, liwork, lrwork integer(${ik}$), intent(out) :: numrank, info integer(${ik}$), intent(inout) :: lcwork ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: u(ldu,*), v(ldv,*), cwork(*) real(sp), intent(out) :: s(*), rwork(*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ierr, nr, n1, optratio, p, q integer(${ik}$) :: lwcon, lwqp3, lwrk_cgelqf, lwrk_cgesvd, lwrk_cgesvd2, lwrk_cgeqp3, & lwrk_cgeqrf, lwrk_cunmlq, lwrk_cunmqr, lwrk_cunmqr2, lwlqf, lwqrf, lwsvd, lwsvd2, & lwunq, lwunq2, lwunlq, minwrk, minwrk2, optwrk, optwrk2, iminwrk, rminwrk logical(lk) :: accla, acclm, acclh, ascaled, conda, dntwu, dntwv, lquery, lsvc0, lsvec,& rowprm, rsvec, rtrans, wntua, wntuf, wntur, wntus, wntva, wntvr real(sp) :: big, epsln, rtmp, sconda, sfmin complex(sp) :: ctmp ! Local Arrays complex(sp) :: cdummy(1_${ik}$) real(sp) :: rdummy(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments wntus = stdlib_lsame( jobu, 'S' ) .or. stdlib_lsame( jobu, 'U' ) wntur = stdlib_lsame( jobu, 'R' ) wntua = stdlib_lsame( jobu, 'A' ) wntuf = stdlib_lsame( jobu, 'F' ) lsvc0 = wntus .or. wntur .or. wntua lsvec = lsvc0 .or. wntuf dntwu = stdlib_lsame( jobu, 'N' ) wntvr = stdlib_lsame( jobv, 'R' ) wntva = stdlib_lsame( jobv, 'A' ) .or. stdlib_lsame( jobv, 'V' ) rsvec = wntvr .or. wntva dntwv = stdlib_lsame( jobv, 'N' ) accla = stdlib_lsame( joba, 'A' ) acclm = stdlib_lsame( joba, 'M' ) conda = stdlib_lsame( joba, 'E' ) acclh = stdlib_lsame( joba, 'H' ) .or. conda rowprm = stdlib_lsame( jobp, 'P' ) rtrans = stdlib_lsame( jobr, 'T' ) if ( rowprm ) then iminwrk = max( 1_${ik}$, n + m - 1_${ik}$ ) rminwrk = max( 2_${ik}$, m, 5_${ik}$*n ) else iminwrk = max( 1_${ik}$, n ) rminwrk = max( 2_${ik}$, 5_${ik}$*n ) end if lquery = (liwork == -1_${ik}$ .or. lcwork == -1_${ik}$ .or. lrwork == -1_${ik}$) info = 0_${ik}$ if ( .not. ( accla .or. acclm .or. acclh ) ) then info = -1_${ik}$ else if ( .not.( rowprm .or. stdlib_lsame( jobp, 'N' ) ) ) then info = -2_${ik}$ else if ( .not.( rtrans .or. stdlib_lsame( jobr, 'N' ) ) ) then info = -3_${ik}$ else if ( .not.( lsvec .or. dntwu ) ) then info = -4_${ik}$ else if ( wntur .and. wntva ) then info = -5_${ik}$ else if ( .not.( rsvec .or. dntwv )) then info = -5_${ik}$ else if ( m<0_${ik}$ ) then info = -6_${ik}$ else if ( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -7_${ik}$ else if ( lda big / sqrt(real(m,KIND=sp)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_clascl('G',0_${ik}$,0_${ik}$,sqrt(real(m,KIND=sp)),one, m,n, a,lda, ierr) ascaled = .true. end if call stdlib${ii}$_claswp( n, a, lda, 1_${ik}$, m-1, iwork(n+1), 1_${ik}$ ) end if ! .. at this stage, preemptive scaling is done only to avoid column ! norms overflows during the qr factorization. the svd procedure should ! have its own scaling to save the singular values from overflows and ! underflows. that depends on the svd procedure. if ( .not.rowprm ) then rtmp = stdlib${ii}$_clange( 'M', m, n, a, lda, rwork ) if ( ( rtmp /= rtmp ) .or.( (rtmp*zero) /= zero ) ) then info = - 8_${ik}$ call stdlib${ii}$_xerbla( 'CGESVDQ', -info ) return end if if ( rtmp > big / sqrt(real(m,KIND=sp)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_clascl('G',0_${ik}$,0_${ik}$, sqrt(real(m,KIND=sp)),one, m,n, a,lda, ierr) ascaled = .true. end if end if ! Qr Factorization With Column Pivoting ! a * p = q * [ r ] ! [ 0 ] do p = 1, n ! All Columns Are Free Columns iwork(p) = 0_${ik}$ end do call stdlib${ii}$_cgeqp3( m, n, a, lda, iwork, cwork, cwork(n+1), lcwork-n,rwork, ierr ) ! if the user requested accuracy level allows truncation in the ! computed upper triangular factor, the matrix r is examined and, ! if possible, replaced with its leading upper trapezoidal part. epsln = stdlib${ii}$_slamch('E') sfmin = stdlib${ii}$_slamch('S') ! small = sfmin / epsln nr = n if ( accla ) then ! standard absolute error bound suffices. all sigma_i with ! sigma_i < n*eps*||a||_f are flushed to zero. this is an ! aggressive enforcement of lower numerical rank by introducing a ! backward error of the order of n*eps*||a||_f. nr = 1_${ik}$ rtmp = sqrt(real(n,KIND=sp))*epsln loop_3002: do p = 2, n if ( abs(a(p,p)) < (rtmp*abs(a(1,1))) ) exit loop_3002 nr = nr + 1_${ik}$ end do loop_3002 elseif ( acclm ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r is used as the criterion for being ! close-to-rank-deficient. the threshold is set to epsln=stdlib${ii}$_slamch('e'). ! [[this can be made more flexible by replacing this hard-coded value ! with a user specified threshold.]] also, the values that underflow ! will be truncated. nr = 1_${ik}$ loop_3402: do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < sfmin ) ) exit loop_3402 nr = nr + 1_${ik}$ end do loop_3402 else ! Rrqr Not Authorized To Determine Numerical Rank Except In The ! obvious case of zero pivots. ! .. inspect r for exact zeros on the diagonal; ! r(i,i)=0 => r(i:n,i:n)=0. nr = 1_${ik}$ loop_3502: do p = 2, n if ( abs(a(p,p)) == zero ) exit loop_3502 nr = nr + 1_${ik}$ end do loop_3502 if ( conda ) then ! estimate the scaled condition number of a. use the fact that it is ! the same as the scaled condition number of r. ! V Is Used As Workspace call stdlib${ii}$_clacpy( 'U', n, n, a, lda, v, ldv ) ! only the leading nr x nr submatrix of the triangular factor ! is considered. only if nr=n will this give a reliable error ! bound. however, even for nr < n, this can be used on an ! expert level and obtain useful information in the sense of ! perturbation theory. do p = 1, nr rtmp = stdlib${ii}$_scnrm2( p, v(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_csscal( p, one/rtmp, v(1_${ik}$,p), 1_${ik}$ ) end do if ( .not. ( lsvec .or. rsvec ) ) then call stdlib${ii}$_cpocon( 'U', nr, v, ldv, one, rtmp,cwork, rwork, ierr ) else call stdlib${ii}$_cpocon( 'U', nr, v, ldv, one, rtmp,cwork(n+1), rwork, ierr ) end if sconda = one / sqrt(rtmp) ! for nr=n, sconda is an estimate of sqrt(||(r^* * r)^(-1)||_1), ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda ! see the reference [1] for more details. end if endif if ( wntur ) then n1 = nr else if ( wntus .or. wntuf) then n1 = n else if ( wntua ) then n1 = m end if if ( .not. ( rsvec .or. lsvec ) ) then ! ....................................................................... ! Only The Singular Values Are Requested ! ....................................................................... if ( rtrans ) then ! .. compute the singular values of r**h = [a](1:nr,1:n)**h ! .. set the lower triangle of [a] to [a](1:nr,1:n)**h and ! the upper triangle of [a] to zero. do p = 1, min( n, nr ) a(p,p) = conjg(a(p,p)) do q = p + 1, n a(q,p) = conjg(a(p,q)) if ( q <= nr ) a(p,q) = czero end do end do call stdlib${ii}$_cgesvd( 'N', 'N', n, nr, a, lda, s, u, ldu,v, ldv, cwork, lcwork, & rwork, info ) else ! .. compute the singular values of r = [a](1:nr,1:n) if ( nr > 1_${ik}$ )call stdlib${ii}$_claset( 'L', nr-1,nr-1, czero,czero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_cgesvd( 'N', 'N', nr, n, a, lda, s, u, ldu,v, ldv, cwork, lcwork, & rwork, info ) end if else if ( lsvec .and. ( .not. rsvec) ) then ! ....................................................................... ! The Singular Values And The Left Singular Vectors Requested ! ......................................................................."""""""" if ( rtrans ) then ! .. apply stdlib${ii}$_cgesvd to r**h ! .. copy r**h into [u] and overwrite [u] with the right singular ! vectors of r do p = 1, nr do q = p, n u(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_claset( 'U', nr-1,nr-1, czero,czero, u(1_${ik}$,2_${ik}$), ldu ) ! .. the left singular vectors not computed, the nr right singular ! vectors overwrite [u](1:nr,1:nr) as conjugate transposed. these ! will be pre-multiplied by q to build the left singular vectors of a. call stdlib${ii}$_cgesvd( 'N', 'O', n, nr, u, ldu, s, u, ldu,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, nr u(p,p) = conjg(u(p,p)) do q = p + 1, nr ctmp = conjg(u(q,p)) u(q,p) = conjg(u(p,q)) u(p,q) = ctmp end do end do else ! Apply Stdlib_Cgesvd To R ! .. copy r into [u] and overwrite [u] with the left singular vectors call stdlib${ii}$_clacpy( 'U', nr, n, a, lda, u, ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_claset( 'L', nr-1, nr-1, czero, czero, u(2_${ik}$,1_${ik}$), ldu ) ! .. the right singular vectors not computed, the nr left singular ! vectors overwrite [u](1:nr,1:nr) call stdlib${ii}$_cgesvd( 'O', 'N', nr, n, u, ldu, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) ! .. now [u](1:nr,1:nr) contains the nr left singular vectors of ! r. these will be pre-multiplied by q to build the left singular ! vectors of a. end if ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. ( .not.wntuf ) ) then call stdlib${ii}$_claset('A', m-nr, nr, czero, czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_claset( 'A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1), ldu ) call stdlib${ii}$_claset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not.wntuf )call stdlib${ii}$_cunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, & cwork(n+1), lcwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_claswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) else if ( rsvec .and. ( .not. lsvec ) ) then ! ....................................................................... ! The Singular Values And The Right Singular Vectors Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_cgesvd to r**h ! .. copy r**h into v and overwrite v with the left singular vectors do p = 1, nr do q = p, n v(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_claset( 'U', nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**h overwrite v, the right singular ! vectors not computed if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_cgesvd( 'O', 'N', n, nr, v, ldv, s, u, ldu,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, nr v(p,p) = conjg(v(p,p)) do q = p + 1, nr ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do if ( nr < n ) then do p = 1, nr do q = nr + 1, n v(p,q) = conjg(v(q,p)) end do end do end if call stdlib${ii}$_clapmt( .false., nr, n, v, ldv, iwork ) else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:n,1:nr) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the qr factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_claset('G', n, n-nr, czero, czero, v(1_${ik}$,nr+1), ldv) call stdlib${ii}$_cgesvd( 'O', 'N', n, n, v, ldv, s, u, ldu,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, n v(p,p) = conjg(v(p,p)) do q = p + 1, n ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do call stdlib${ii}$_clapmt( .false., n, n, v, ldv, iwork ) end if else ! Aply Stdlib_Cgesvd To R ! Copy R Into V And Overwrite V With The Right Singular Vectors call stdlib${ii}$_clacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_claset( 'L', nr-1, nr-1, czero, czero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors overwrite v, the nr left singular ! vectors stored in u(1:nr,1:nr) if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_cgesvd( 'N', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_clapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**h else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:nr,1:n) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the lq factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_claset('G', n-nr, n, czero,czero, v(nr+1,1_${ik}$), ldv) call stdlib${ii}$_cgesvd( 'N', 'O', n, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_clapmt( .false., n, n, v, ldv, iwork ) end if ! .. now [v] contains the adjoint of the matrix of the right singular ! vectors of a. end if else ! ....................................................................... ! Full Svd Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_cgesvd to r**h [[this option is left for r if ( wntvr .or. ( nr == n ) ) then ! .. copy r**h into [v] and overwrite [v] with the left singular ! vectors of r**h do p = 1, nr do q = p, n v(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_claset( 'U', nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**h overwrite [v], the nr right ! singular vectors of r**h stored in [u](1:nr,1:nr) as conjugate ! transposed call stdlib${ii}$_cgesvd( 'O', 'A', n, nr, v, ldv, s, v, ldv,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) ! Assemble V do p = 1, nr v(p,p) = conjg(v(p,p)) do q = p + 1, nr ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do if ( nr < n ) then do p = 1, nr do q = nr+1, n v(p,q) = conjg(v(q,p)) end do end do end if call stdlib${ii}$_clapmt( .false., nr, n, v, ldv, iwork ) do p = 1, nr u(p,p) = conjg(u(p,p)) do q = p + 1, nr ctmp = conjg(u(q,p)) u(q,p) = conjg(u(p,q)) u(p,q) = ctmp end do end do if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_claset('A', m-nr,nr, czero,czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_claset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_claset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! .. copy r**h into [v] and overwrite [v] with the left singular ! vectors of r**h ! [[the optimal ratio n/nr for using qrf instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'cgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio*nr > n ) then do p = 1, nr do q = p, n v(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_claset('U',nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_claset('A',n,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_cgesvd( 'O', 'A', n, n, v, ldv, s, v, ldv,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, n v(p,p) = conjg(v(p,p)) do q = p + 1, n ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do call stdlib${ii}$_clapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). do p = 1, n u(p,p) = conjg(u(p,p)) do q = p + 1, n ctmp = conjg(u(q,p)) u(q,p) = conjg(u(p,q)) u(p,q) = ctmp end do end do if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_claset('A',m-n,n,czero,czero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_claset('A',n,n1-n,czero,czero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_claset('A',m-n,n1-n,czero,cone,u(n+1,n+1), ldu ) end if end if else ! .. copy r**h into [u] and overwrite [u] with the right ! singular vectors of r do p = 1, nr do q = p, n u(q,nr+p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_claset('U',nr-1,nr-1,czero,czero,u(1_${ik}$,nr+2),ldu) call stdlib${ii}$_cgeqrf( n, nr, u(1_${ik}$,nr+1), ldu, cwork(n+1),cwork(n+nr+1), & lcwork-n-nr, ierr ) do p = 1, nr do q = 1, n v(q,p) = conjg(u(p,nr+q)) end do end do if (nr>1_${ik}$) call stdlib${ii}$_claset('U',nr-1,nr-1,czero,czero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_cgesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v,ldv, cwork(n+nr+& 1_${ik}$),lcwork-n-nr,rwork, info ) call stdlib${ii}$_claset('A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_claset('A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_claset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) call stdlib${ii}$_cunmqr('R','C', n, n, nr, u(1_${ik}$,nr+1), ldu,cwork(n+1),v,ldv,& cwork(n+nr+1),lcwork-n-nr,ierr) call stdlib${ii}$_clapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_claset('A',m-nr,nr,czero,czero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_claset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_claset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1),ldu) end if end if end if end if else ! .. apply stdlib${ii}$_cgesvd to r [[this is the recommended option]] if ( wntvr .or. ( nr == n ) ) then ! .. copy r into [v] and overwrite v with the right singular vectors call stdlib${ii}$_clacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_claset( 'L', nr-1,nr-1, czero,czero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_cgesvd( 'S', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_clapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**h ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_claset('A', m-nr,nr, czero,czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_claset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_claset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! The Requested Number Of The Left Singular Vectors ! is then n1 (n or m) ! [[the optimal ratio n/nr for using lq instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'cgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio * nr > n ) then call stdlib${ii}$_clacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_claset('L', nr-1,nr-1, czero,czero, v(2_${ik}$,1_${ik}$),ldv) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_claset('A', n-nr,n, czero,czero, v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_cgesvd( 'S', 'O', n, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_clapmt( .false., n, n, v, ldv, iwork ) ! .. now [v] contains the adjoint of the matrix of the right ! singular vectors of a. the leading n left singular vectors ! are in [u](1:n,1:n) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_claset('A',m-n,n,czero,czero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_claset('A',n,n1-n,czero,czero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_claset( 'A',m-n,n1-n,czero,cone,u(n+1,n+1), ldu ) end if end if else call stdlib${ii}$_clacpy( 'U', nr, n, a, lda, u(nr+1,1_${ik}$), ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_claset('L',nr-1,nr-1,czero,czero,u(nr+2,1_${ik}$),ldu) call stdlib${ii}$_cgelqf( nr, n, u(nr+1,1_${ik}$), ldu, cwork(n+1),cwork(n+nr+1), & lcwork-n-nr, ierr ) call stdlib${ii}$_clacpy('L',nr,nr,u(nr+1,1_${ik}$),ldu,v,ldv) if ( nr > 1_${ik}$ )call stdlib${ii}$_claset('U',nr-1,nr-1,czero,czero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_cgesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v, ldv, cwork(n+nr+& 1_${ik}$), lcwork-n-nr, rwork, info ) call stdlib${ii}$_claset('A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_claset('A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_claset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) call stdlib${ii}$_cunmlq('R','N',n,n,nr,u(nr+1,1_${ik}$),ldu,cwork(n+1),v, ldv, cwork(n+& nr+1),lcwork-n-nr,ierr) call stdlib${ii}$_clapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_claset('A',m-nr,nr,czero,czero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_claset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_claset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if end if end if ! .. end of the "r**h or r" branch end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not. wntuf )call stdlib${ii}$_cunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, & cwork(n+1), lcwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_claswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) ! ... end of the "full svd" branch end if ! check whether some singular values are returned as zeros, e.g. ! due to underflow, and update the numerical rank. p = nr do q = p, 1, -1 if ( s(q) > zero ) go to 4002 nr = nr - 1_${ik}$ end do 4002 continue ! .. if numerical rank deficiency is detected, the truncated ! singular values are set to zero. if ( nr < n ) call stdlib${ii}$_slaset( 'G', n-nr,1_${ik}$, zero,zero, s(nr+1), n ) ! .. undo scaling; this may cause overflow in the largest singular ! values. if ( ascaled )call stdlib${ii}$_slascl( 'G',0_${ik}$,0_${ik}$, one,sqrt(real(m,KIND=sp)), nr,1_${ik}$, s, n, ierr & ) if ( conda ) rwork(1_${ik}$) = sconda rwork(2_${ik}$) = p - nr ! .. p-nr is the number of singular values that are computed as ! exact zeros in stdlib${ii}$_cgesvd() applied to the (possibly truncated) ! full row rank triangular (trapezoidal) factor of a. numrank = nr return end subroutine stdlib${ii}$_cgesvdq module subroutine stdlib${ii}$_zgesvdq( joba, jobp, jobr, jobu, jobv, m, n, a, lda,s, u, ldu, v, ldv, & !! ZCGESVDQ computes the singular value decomposition (SVD) of a complex !! M-by-N matrix A, where M >= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N unitary matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. numrank, iwork, liwork,cwork, lcwork, rwork, lrwork, info ) use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: joba, jobp, jobr, jobu, jobv integer(${ik}$), intent(in) :: m, n, lda, ldu, ldv, liwork, lrwork integer(${ik}$), intent(out) :: numrank, info integer(${ik}$), intent(inout) :: lcwork ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: u(ldu,*), v(ldv,*), cwork(*) real(dp), intent(out) :: s(*), rwork(*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ierr, nr, n1, optratio, p, q integer(${ik}$) :: lwcon, lwqp3, lwrk_zgelqf, lwrk_zgesvd, lwrk_zgesvd2, lwrk_zgeqp3, & lwrk_zgeqrf, lwrk_zunmlq, lwrk_zunmqr, lwrk_zunmqr2, lwlqf, lwqrf, lwsvd, lwsvd2, & lwunq, lwunq2, lwunlq, minwrk, minwrk2, optwrk, optwrk2, iminwrk, rminwrk logical(lk) :: accla, acclm, acclh, ascaled, conda, dntwu, dntwv, lquery, lsvc0, lsvec,& rowprm, rsvec, rtrans, wntua, wntuf, wntur, wntus, wntva, wntvr real(dp) :: big, epsln, rtmp, sconda, sfmin complex(dp) :: ctmp ! Local Arrays complex(dp) :: cdummy(1_${ik}$) real(dp) :: rdummy(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments wntus = stdlib_lsame( jobu, 'S' ) .or. stdlib_lsame( jobu, 'U' ) wntur = stdlib_lsame( jobu, 'R' ) wntua = stdlib_lsame( jobu, 'A' ) wntuf = stdlib_lsame( jobu, 'F' ) lsvc0 = wntus .or. wntur .or. wntua lsvec = lsvc0 .or. wntuf dntwu = stdlib_lsame( jobu, 'N' ) wntvr = stdlib_lsame( jobv, 'R' ) wntva = stdlib_lsame( jobv, 'A' ) .or. stdlib_lsame( jobv, 'V' ) rsvec = wntvr .or. wntva dntwv = stdlib_lsame( jobv, 'N' ) accla = stdlib_lsame( joba, 'A' ) acclm = stdlib_lsame( joba, 'M' ) conda = stdlib_lsame( joba, 'E' ) acclh = stdlib_lsame( joba, 'H' ) .or. conda rowprm = stdlib_lsame( jobp, 'P' ) rtrans = stdlib_lsame( jobr, 'T' ) if ( rowprm ) then iminwrk = max( 1_${ik}$, n + m - 1_${ik}$ ) rminwrk = max( 2_${ik}$, m, 5_${ik}$*n ) else iminwrk = max( 1_${ik}$, n ) rminwrk = max( 2_${ik}$, 5_${ik}$*n ) end if lquery = (liwork == -1_${ik}$ .or. lcwork == -1_${ik}$ .or. lrwork == -1_${ik}$) info = 0_${ik}$ if ( .not. ( accla .or. acclm .or. acclh ) ) then info = -1_${ik}$ else if ( .not.( rowprm .or. stdlib_lsame( jobp, 'N' ) ) ) then info = -2_${ik}$ else if ( .not.( rtrans .or. stdlib_lsame( jobr, 'N' ) ) ) then info = -3_${ik}$ else if ( .not.( lsvec .or. dntwu ) ) then info = -4_${ik}$ else if ( wntur .and. wntva ) then info = -5_${ik}$ else if ( .not.( rsvec .or. dntwv )) then info = -5_${ik}$ else if ( m<0_${ik}$ ) then info = -6_${ik}$ else if ( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -7_${ik}$ else if ( lda big / sqrt(real(m,KIND=dp)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_zlascl('G',0_${ik}$,0_${ik}$,sqrt(real(m,KIND=dp)),one, m,n, a,lda, ierr) ascaled = .true. end if call stdlib${ii}$_zlaswp( n, a, lda, 1_${ik}$, m-1, iwork(n+1), 1_${ik}$ ) end if ! .. at this stage, preemptive scaling is done only to avoid column ! norms overflows during the qr factorization. the svd procedure should ! have its own scaling to save the singular values from overflows and ! underflows. that depends on the svd procedure. if ( .not.rowprm ) then rtmp = stdlib${ii}$_zlange( 'M', m, n, a, lda, rwork ) if ( ( rtmp /= rtmp ) .or.( (rtmp*zero) /= zero ) ) then info = -8_${ik}$ call stdlib${ii}$_xerbla( 'ZGESVDQ', -info ) return end if if ( rtmp > big / sqrt(real(m,KIND=dp)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_zlascl('G',0_${ik}$,0_${ik}$, sqrt(real(m,KIND=dp)),one, m,n, a,lda, ierr) ascaled = .true. end if end if ! Qr Factorization With Column Pivoting ! a * p = q * [ r ] ! [ 0 ] do p = 1, n ! All Columns Are Free Columns iwork(p) = 0_${ik}$ end do call stdlib${ii}$_zgeqp3( m, n, a, lda, iwork, cwork, cwork(n+1), lcwork-n,rwork, ierr ) ! if the user requested accuracy level allows truncation in the ! computed upper triangular factor, the matrix r is examined and, ! if possible, replaced with its leading upper trapezoidal part. epsln = stdlib${ii}$_dlamch('E') sfmin = stdlib${ii}$_dlamch('S') ! small = sfmin / epsln nr = n if ( accla ) then ! standard absolute error bound suffices. all sigma_i with ! sigma_i < n*eps*||a||_f are flushed to zero. this is an ! aggressive enforcement of lower numerical rank by introducing a ! backward error of the order of n*eps*||a||_f. nr = 1_${ik}$ rtmp = sqrt(real(n,KIND=dp))*epsln loop_3002: do p = 2, n if ( abs(a(p,p)) < (rtmp*abs(a(1,1))) ) exit loop_3002 nr = nr + 1_${ik}$ end do loop_3002 elseif ( acclm ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r is used as the criterion for being ! close-to-rank-deficient. the threshold is set to epsln=stdlib${ii}$_dlamch('e'). ! [[this can be made more flexible by replacing this hard-coded value ! with a user specified threshold.]] also, the values that underflow ! will be truncated. nr = 1_${ik}$ loop_3402: do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < sfmin ) ) exit loop_3402 nr = nr + 1_${ik}$ end do loop_3402 else ! Rrqr Not Authorized To Determine Numerical Rank Except In The ! obvious case of zero pivots. ! .. inspect r for exact zeros on the diagonal; ! r(i,i)=0 => r(i:n,i:n)=0. nr = 1_${ik}$ loop_3502: do p = 2, n if ( abs(a(p,p)) == zero ) exit loop_3502 nr = nr + 1_${ik}$ end do loop_3502 if ( conda ) then ! estimate the scaled condition number of a. use the fact that it is ! the same as the scaled condition number of r. ! V Is Used As Workspace call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, v, ldv ) ! only the leading nr x nr submatrix of the triangular factor ! is considered. only if nr=n will this give a reliable error ! bound. however, even for nr < n, this can be used on an ! expert level and obtain useful information in the sense of ! perturbation theory. do p = 1, nr rtmp = stdlib${ii}$_dznrm2( p, v(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_zdscal( p, one/rtmp, v(1_${ik}$,p), 1_${ik}$ ) end do if ( .not. ( lsvec .or. rsvec ) ) then call stdlib${ii}$_zpocon( 'U', nr, v, ldv, one, rtmp,cwork, rwork, ierr ) else call stdlib${ii}$_zpocon( 'U', nr, v, ldv, one, rtmp,cwork(n+1), rwork, ierr ) end if sconda = one / sqrt(rtmp) ! for nr=n, sconda is an estimate of sqrt(||(r^* * r)^(-1)||_1), ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda ! see the reference [1] for more details. end if endif if ( wntur ) then n1 = nr else if ( wntus .or. wntuf) then n1 = n else if ( wntua ) then n1 = m end if if ( .not. ( rsvec .or. lsvec ) ) then ! ....................................................................... ! Only The Singular Values Are Requested ! ....................................................................... if ( rtrans ) then ! .. compute the singular values of r**h = [a](1:nr,1:n)**h ! .. set the lower triangle of [a] to [a](1:nr,1:n)**h and ! the upper triangle of [a] to zero. do p = 1, min( n, nr ) a(p,p) = conjg(a(p,p)) do q = p + 1, n a(q,p) = conjg(a(p,q)) if ( q <= nr ) a(p,q) = czero end do end do call stdlib${ii}$_zgesvd( 'N', 'N', n, nr, a, lda, s, u, ldu,v, ldv, cwork, lcwork, & rwork, info ) else ! .. compute the singular values of r = [a](1:nr,1:n) if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset( 'L', nr-1,nr-1, czero,czero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_zgesvd( 'N', 'N', nr, n, a, lda, s, u, ldu,v, ldv, cwork, lcwork, & rwork, info ) end if else if ( lsvec .and. ( .not. rsvec) ) then ! ....................................................................... ! The Singular Values And The Left Singular Vectors Requested ! ......................................................................."""""""" if ( rtrans ) then ! .. apply stdlib${ii}$_zgesvd to r**h ! .. copy r**h into [u] and overwrite [u] with the right singular ! vectors of r do p = 1, nr do q = p, n u(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset( 'U', nr-1,nr-1, czero,czero, u(1_${ik}$,2_${ik}$), ldu ) ! .. the left singular vectors not computed, the nr right singular ! vectors overwrite [u](1:nr,1:nr) as conjugate transposed. these ! will be pre-multiplied by q to build the left singular vectors of a. call stdlib${ii}$_zgesvd( 'N', 'O', n, nr, u, ldu, s, u, ldu,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, nr u(p,p) = conjg(u(p,p)) do q = p + 1, nr ctmp = conjg(u(q,p)) u(q,p) = conjg(u(p,q)) u(p,q) = ctmp end do end do else ! Apply Stdlib_Zgesvd To R ! .. copy r into [u] and overwrite [u] with the left singular vectors call stdlib${ii}$_zlacpy( 'U', nr, n, a, lda, u, ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset( 'L', nr-1, nr-1, czero, czero, u(2_${ik}$,1_${ik}$), ldu ) ! .. the right singular vectors not computed, the nr left singular ! vectors overwrite [u](1:nr,1:nr) call stdlib${ii}$_zgesvd( 'O', 'N', nr, n, u, ldu, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) ! .. now [u](1:nr,1:nr) contains the nr left singular vectors of ! r. these will be pre-multiplied by q to build the left singular ! vectors of a. end if ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. ( .not.wntuf ) ) then call stdlib${ii}$_zlaset('A', m-nr, nr, czero, czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_zlaset( 'A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1), ldu ) call stdlib${ii}$_zlaset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not.wntuf )call stdlib${ii}$_zunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, & cwork(n+1), lcwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_zlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) else if ( rsvec .and. ( .not. lsvec ) ) then ! ....................................................................... ! The Singular Values And The Right Singular Vectors Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_zgesvd to r**h ! .. copy r**h into v and overwrite v with the left singular vectors do p = 1, nr do q = p, n v(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset( 'U', nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**h overwrite v, the right singular ! vectors not computed if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_zgesvd( 'O', 'N', n, nr, v, ldv, s, u, ldu,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, nr v(p,p) = conjg(v(p,p)) do q = p + 1, nr ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do if ( nr < n ) then do p = 1, nr do q = nr + 1, n v(p,q) = conjg(v(q,p)) end do end do end if call stdlib${ii}$_zlapmt( .false., nr, n, v, ldv, iwork ) else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:n,1:nr) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the qr factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_zlaset('G', n, n-nr, czero, czero, v(1_${ik}$,nr+1), ldv) call stdlib${ii}$_zgesvd( 'O', 'N', n, n, v, ldv, s, u, ldu,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, n v(p,p) = conjg(v(p,p)) do q = p + 1, n ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do call stdlib${ii}$_zlapmt( .false., n, n, v, ldv, iwork ) end if else ! Aply Stdlib_Zgesvd To R ! Copy R Into V And Overwrite V With The Right Singular Vectors call stdlib${ii}$_zlacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset( 'L', nr-1, nr-1, czero, czero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors overwrite v, the nr left singular ! vectors stored in u(1:nr,1:nr) if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_zgesvd( 'N', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_zlapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**h else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:nr,1:n) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the lq factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_zlaset('G', n-nr, n, czero,czero, v(nr+1,1_${ik}$), ldv) call stdlib${ii}$_zgesvd( 'N', 'O', n, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_zlapmt( .false., n, n, v, ldv, iwork ) end if ! .. now [v] contains the adjoint of the matrix of the right singular ! vectors of a. end if else ! ....................................................................... ! Full Svd Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_zgesvd to r**h [[this option is left for r if ( wntvr .or. ( nr == n ) ) then ! .. copy r**h into [v] and overwrite [v] with the left singular ! vectors of r**h do p = 1, nr do q = p, n v(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset( 'U', nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**h overwrite [v], the nr right ! singular vectors of r**h stored in [u](1:nr,1:nr) as conjugate ! transposed call stdlib${ii}$_zgesvd( 'O', 'A', n, nr, v, ldv, s, v, ldv,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) ! Assemble V do p = 1, nr v(p,p) = conjg(v(p,p)) do q = p + 1, nr ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do if ( nr < n ) then do p = 1, nr do q = nr+1, n v(p,q) = conjg(v(q,p)) end do end do end if call stdlib${ii}$_zlapmt( .false., nr, n, v, ldv, iwork ) do p = 1, nr u(p,p) = conjg(u(p,p)) do q = p + 1, nr ctmp = conjg(u(q,p)) u(q,p) = conjg(u(p,q)) u(p,q) = ctmp end do end do if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_zlaset('A', m-nr,nr, czero,czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_zlaset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_zlaset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! .. copy r**h into [v] and overwrite [v] with the left singular ! vectors of r**h ! [[the optimal ratio n/nr for using qrf instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'zgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio*nr > n ) then do p = 1, nr do q = p, n v(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset('U',nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_zlaset('A',n,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_zgesvd( 'O', 'A', n, n, v, ldv, s, v, ldv,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, n v(p,p) = conjg(v(p,p)) do q = p + 1, n ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do call stdlib${ii}$_zlapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). do p = 1, n u(p,p) = conjg(u(p,p)) do q = p + 1, n ctmp = conjg(u(q,p)) u(q,p) = conjg(u(p,q)) u(p,q) = ctmp end do end do if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_zlaset('A',m-n,n,czero,czero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_zlaset('A',n,n1-n,czero,czero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_zlaset('A',m-n,n1-n,czero,cone,u(n+1,n+1), ldu ) end if end if else ! .. copy r**h into [u] and overwrite [u] with the right ! singular vectors of r do p = 1, nr do q = p, n u(q,nr+p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset('U',nr-1,nr-1,czero,czero,u(1_${ik}$,nr+2),ldu) call stdlib${ii}$_zgeqrf( n, nr, u(1_${ik}$,nr+1), ldu, cwork(n+1),cwork(n+nr+1), & lcwork-n-nr, ierr ) do p = 1, nr do q = 1, n v(q,p) = conjg(u(p,nr+q)) end do end do if (nr>1_${ik}$) call stdlib${ii}$_zlaset('U',nr-1,nr-1,czero,czero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_zgesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v,ldv, cwork(n+nr+& 1_${ik}$),lcwork-n-nr,rwork, info ) call stdlib${ii}$_zlaset('A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_zlaset('A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_zlaset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) call stdlib${ii}$_zunmqr('R','C', n, n, nr, u(1_${ik}$,nr+1), ldu,cwork(n+1),v,ldv,& cwork(n+nr+1),lcwork-n-nr,ierr) call stdlib${ii}$_zlapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_zlaset('A',m-nr,nr,czero,czero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_zlaset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_zlaset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1),ldu) end if end if end if end if else ! .. apply stdlib${ii}$_zgesvd to r [[this is the recommended option]] if ( wntvr .or. ( nr == n ) ) then ! .. copy r into [v] and overwrite v with the right singular vectors call stdlib${ii}$_zlacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset( 'L', nr-1,nr-1, czero,czero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_zgesvd( 'S', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_zlapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**h ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_zlaset('A', m-nr,nr, czero,czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_zlaset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_zlaset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! The Requested Number Of The Left Singular Vectors ! is then n1 (n or m) ! [[the optimal ratio n/nr for using lq instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'zgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio * nr > n ) then call stdlib${ii}$_zlacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset('L', nr-1,nr-1, czero,czero, v(2_${ik}$,1_${ik}$),ldv) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_zlaset('A', n-nr,n, czero,czero, v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_zgesvd( 'S', 'O', n, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_zlapmt( .false., n, n, v, ldv, iwork ) ! .. now [v] contains the adjoint of the matrix of the right ! singular vectors of a. the leading n left singular vectors ! are in [u](1:n,1:n) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_zlaset('A',m-n,n,czero,czero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_zlaset('A',n,n1-n,czero,czero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_zlaset( 'A',m-n,n1-n,czero,cone,u(n+1,n+1), ldu ) end if end if else call stdlib${ii}$_zlacpy( 'U', nr, n, a, lda, u(nr+1,1_${ik}$), ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset('L',nr-1,nr-1,czero,czero,u(nr+2,1_${ik}$),ldu) call stdlib${ii}$_zgelqf( nr, n, u(nr+1,1_${ik}$), ldu, cwork(n+1),cwork(n+nr+1), & lcwork-n-nr, ierr ) call stdlib${ii}$_zlacpy('L',nr,nr,u(nr+1,1_${ik}$),ldu,v,ldv) if ( nr > 1_${ik}$ )call stdlib${ii}$_zlaset('U',nr-1,nr-1,czero,czero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_zgesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v, ldv, cwork(n+nr+& 1_${ik}$), lcwork-n-nr, rwork, info ) call stdlib${ii}$_zlaset('A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_zlaset('A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_zlaset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) call stdlib${ii}$_zunmlq('R','N',n,n,nr,u(nr+1,1_${ik}$),ldu,cwork(n+1),v, ldv, cwork(n+& nr+1),lcwork-n-nr,ierr) call stdlib${ii}$_zlapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_zlaset('A',m-nr,nr,czero,czero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_zlaset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_zlaset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if end if end if ! .. end of the "r**h or r" branch end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not. wntuf )call stdlib${ii}$_zunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, & cwork(n+1), lcwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_zlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) ! ... end of the "full svd" branch end if ! check whether some singular values are returned as zeros, e.g. ! due to underflow, and update the numerical rank. p = nr do q = p, 1, -1 if ( s(q) > zero ) go to 4002 nr = nr - 1_${ik}$ end do 4002 continue ! .. if numerical rank deficiency is detected, the truncated ! singular values are set to zero. if ( nr < n ) call stdlib${ii}$_dlaset( 'G', n-nr,1_${ik}$, zero,zero, s(nr+1), n ) ! .. undo scaling; this may cause overflow in the largest singular ! values. if ( ascaled )call stdlib${ii}$_dlascl( 'G',0_${ik}$,0_${ik}$, one,sqrt(real(m,KIND=dp)), nr,1_${ik}$, s, n, ierr & ) if ( conda ) rwork(1_${ik}$) = sconda rwork(2_${ik}$) = p - nr ! .. p-nr is the number of singular values that are computed as ! exact zeros in stdlib${ii}$_zgesvd() applied to the (possibly truncated) ! full row rank triangular (trapezoidal) factor of a. numrank = nr return end subroutine stdlib${ii}$_zgesvdq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$gesvdq( joba, jobp, jobr, jobu, jobv, m, n, a, lda,s, u, ldu, v, ldv, & !! ZCGESVDQ computes the singular value decomposition (SVD) of a complex !! M-by-N matrix A, where M >= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N unitary matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. numrank, iwork, liwork,cwork, lcwork, rwork, lrwork, info ) use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: joba, jobp, jobr, jobu, jobv integer(${ik}$), intent(in) :: m, n, lda, ldu, ldv, liwork, lrwork integer(${ik}$), intent(out) :: numrank, info integer(${ik}$), intent(inout) :: lcwork ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: u(ldu,*), v(ldv,*), cwork(*) real(${ck}$), intent(out) :: s(*), rwork(*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ierr, nr, n1, optratio, p, q integer(${ik}$) :: lwcon, lwqp3, lwrk_wgelqf, lwrk_wgesvd, lwrk_wgesvd2, lwrk_wgeqp3, & lwrk_wgeqrf, lwrk_wunmlq, lwrk_wunmqr, lwrk_wunmqr2, lwlqf, lwqrf, lwsvd, lwsvd2, & lwunq, lwunq2, lwunlq, minwrk, minwrk2, optwrk, optwrk2, iminwrk, rminwrk logical(lk) :: accla, acclm, acclh, ascaled, conda, dntwu, dntwv, lquery, lsvc0, lsvec,& rowprm, rsvec, rtrans, wntua, wntuf, wntur, wntus, wntva, wntvr real(${ck}$) :: big, epsln, rtmp, sconda, sfmin complex(${ck}$) :: ctmp ! Local Arrays complex(${ck}$) :: cdummy(1_${ik}$) real(${ck}$) :: rdummy(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments wntus = stdlib_lsame( jobu, 'S' ) .or. stdlib_lsame( jobu, 'U' ) wntur = stdlib_lsame( jobu, 'R' ) wntua = stdlib_lsame( jobu, 'A' ) wntuf = stdlib_lsame( jobu, 'F' ) lsvc0 = wntus .or. wntur .or. wntua lsvec = lsvc0 .or. wntuf dntwu = stdlib_lsame( jobu, 'N' ) wntvr = stdlib_lsame( jobv, 'R' ) wntva = stdlib_lsame( jobv, 'A' ) .or. stdlib_lsame( jobv, 'V' ) rsvec = wntvr .or. wntva dntwv = stdlib_lsame( jobv, 'N' ) accla = stdlib_lsame( joba, 'A' ) acclm = stdlib_lsame( joba, 'M' ) conda = stdlib_lsame( joba, 'E' ) acclh = stdlib_lsame( joba, 'H' ) .or. conda rowprm = stdlib_lsame( jobp, 'P' ) rtrans = stdlib_lsame( jobr, 'T' ) if ( rowprm ) then iminwrk = max( 1_${ik}$, n + m - 1_${ik}$ ) rminwrk = max( 2_${ik}$, m, 5_${ik}$*n ) else iminwrk = max( 1_${ik}$, n ) rminwrk = max( 2_${ik}$, 5_${ik}$*n ) end if lquery = (liwork == -1_${ik}$ .or. lcwork == -1_${ik}$ .or. lrwork == -1_${ik}$) info = 0_${ik}$ if ( .not. ( accla .or. acclm .or. acclh ) ) then info = -1_${ik}$ else if ( .not.( rowprm .or. stdlib_lsame( jobp, 'N' ) ) ) then info = -2_${ik}$ else if ( .not.( rtrans .or. stdlib_lsame( jobr, 'N' ) ) ) then info = -3_${ik}$ else if ( .not.( lsvec .or. dntwu ) ) then info = -4_${ik}$ else if ( wntur .and. wntva ) then info = -5_${ik}$ else if ( .not.( rsvec .or. dntwv )) then info = -5_${ik}$ else if ( m<0_${ik}$ ) then info = -6_${ik}$ else if ( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -7_${ik}$ else if ( lda big / sqrt(real(m,KIND=${ck}$)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_${ci}$lascl('G',0_${ik}$,0_${ik}$,sqrt(real(m,KIND=${ck}$)),one, m,n, a,lda, ierr) ascaled = .true. end if call stdlib${ii}$_${ci}$laswp( n, a, lda, 1_${ik}$, m-1, iwork(n+1), 1_${ik}$ ) end if ! .. at this stage, preemptive scaling is done only to avoid column ! norms overflows during the qr factorization. the svd procedure should ! have its own scaling to save the singular values from overflows and ! underflows. that depends on the svd procedure. if ( .not.rowprm ) then rtmp = stdlib${ii}$_${ci}$lange( 'M', m, n, a, lda, rwork ) if ( ( rtmp /= rtmp ) .or.( (rtmp*zero) /= zero ) ) then info = -8_${ik}$ call stdlib${ii}$_xerbla( 'ZGESVDQ', -info ) return end if if ( rtmp > big / sqrt(real(m,KIND=${ck}$)) ) then ! .. to prevent overflow in the qr factorization, scale the ! matrix by 1/sqrt(m) if too large entry detected call stdlib${ii}$_${ci}$lascl('G',0_${ik}$,0_${ik}$, sqrt(real(m,KIND=${ck}$)),one, m,n, a,lda, ierr) ascaled = .true. end if end if ! Qr Factorization With Column Pivoting ! a * p = q * [ r ] ! [ 0 ] do p = 1, n ! All Columns Are Free Columns iwork(p) = 0_${ik}$ end do call stdlib${ii}$_${ci}$geqp3( m, n, a, lda, iwork, cwork, cwork(n+1), lcwork-n,rwork, ierr ) ! if the user requested accuracy level allows truncation in the ! computed upper triangular factor, the matrix r is examined and, ! if possible, replaced with its leading upper trapezoidal part. epsln = stdlib${ii}$_${c2ri(ci)}$lamch('E') sfmin = stdlib${ii}$_${c2ri(ci)}$lamch('S') ! small = sfmin / epsln nr = n if ( accla ) then ! standard absolute error bound suffices. all sigma_i with ! sigma_i < n*eps*||a||_f are flushed to zero. this is an ! aggressive enforcement of lower numerical rank by introducing a ! backward error of the order of n*eps*||a||_f. nr = 1_${ik}$ rtmp = sqrt(real(n,KIND=${ck}$))*epsln loop_3002: do p = 2, n if ( abs(a(p,p)) < (rtmp*abs(a(1,1))) ) exit loop_3002 nr = nr + 1_${ik}$ end do loop_3002 elseif ( acclm ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r is used as the criterion for being ! close-to-rank-deficient. the threshold is set to epsln=stdlib${ii}$_${c2ri(ci)}$lamch('e'). ! [[this can be made more flexible by replacing this hard-coded value ! with a user specified threshold.]] also, the values that underflow ! will be truncated. nr = 1_${ik}$ loop_3402: do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < sfmin ) ) exit loop_3402 nr = nr + 1_${ik}$ end do loop_3402 else ! Rrqr Not Authorized To Determine Numerical Rank Except In The ! obvious case of zero pivots. ! .. inspect r for exact zeros on the diagonal; ! r(i,i)=0 => r(i:n,i:n)=0. nr = 1_${ik}$ loop_3502: do p = 2, n if ( abs(a(p,p)) == zero ) exit loop_3502 nr = nr + 1_${ik}$ end do loop_3502 if ( conda ) then ! estimate the scaled condition number of a. use the fact that it is ! the same as the scaled condition number of r. ! V Is Used As Workspace call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, v, ldv ) ! only the leading nr x nr submatrix of the triangular factor ! is considered. only if nr=n will this give a reliable error ! bound. however, even for nr < n, this can be used on an ! expert level and obtain useful information in the sense of ! perturbation theory. do p = 1, nr rtmp = stdlib${ii}$_${c2ri(ci)}$znrm2( p, v(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( p, one/rtmp, v(1_${ik}$,p), 1_${ik}$ ) end do if ( .not. ( lsvec .or. rsvec ) ) then call stdlib${ii}$_${ci}$pocon( 'U', nr, v, ldv, one, rtmp,cwork, rwork, ierr ) else call stdlib${ii}$_${ci}$pocon( 'U', nr, v, ldv, one, rtmp,cwork(n+1), rwork, ierr ) end if sconda = one / sqrt(rtmp) ! for nr=n, sconda is an estimate of sqrt(||(r^* * r)^(-1)||_1), ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda ! see the reference [1] for more details. end if endif if ( wntur ) then n1 = nr else if ( wntus .or. wntuf) then n1 = n else if ( wntua ) then n1 = m end if if ( .not. ( rsvec .or. lsvec ) ) then ! ....................................................................... ! Only The Singular Values Are Requested ! ....................................................................... if ( rtrans ) then ! .. compute the singular values of r**h = [a](1:nr,1:n)**h ! .. set the lower triangle of [a] to [a](1:nr,1:n)**h and ! the upper triangle of [a] to zero. do p = 1, min( n, nr ) a(p,p) = conjg(a(p,p)) do q = p + 1, n a(q,p) = conjg(a(p,q)) if ( q <= nr ) a(p,q) = czero end do end do call stdlib${ii}$_${ci}$gesvd( 'N', 'N', n, nr, a, lda, s, u, ldu,v, ldv, cwork, lcwork, & rwork, info ) else ! .. compute the singular values of r = [a](1:nr,1:n) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'L', nr-1,nr-1, czero,czero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_${ci}$gesvd( 'N', 'N', nr, n, a, lda, s, u, ldu,v, ldv, cwork, lcwork, & rwork, info ) end if else if ( lsvec .and. ( .not. rsvec) ) then ! ....................................................................... ! The Singular Values And The Left Singular Vectors Requested ! ......................................................................."""""""" if ( rtrans ) then ! .. apply stdlib${ii}$_${ci}$gesvd to r**h ! .. copy r**h into [u] and overwrite [u] with the right singular ! vectors of r do p = 1, nr do q = p, n u(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'U', nr-1,nr-1, czero,czero, u(1_${ik}$,2_${ik}$), ldu ) ! .. the left singular vectors not computed, the nr right singular ! vectors overwrite [u](1:nr,1:nr) as conjugate transposed. these ! will be pre-multiplied by q to build the left singular vectors of a. call stdlib${ii}$_${ci}$gesvd( 'N', 'O', n, nr, u, ldu, s, u, ldu,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, nr u(p,p) = conjg(u(p,p)) do q = p + 1, nr ctmp = conjg(u(q,p)) u(q,p) = conjg(u(p,q)) u(p,q) = ctmp end do end do else ! Apply Stdlib_Zgesvd To R ! .. copy r into [u] and overwrite [u] with the left singular vectors call stdlib${ii}$_${ci}$lacpy( 'U', nr, n, a, lda, u, ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'L', nr-1, nr-1, czero, czero, u(2_${ik}$,1_${ik}$), ldu ) ! .. the right singular vectors not computed, the nr left singular ! vectors overwrite [u](1:nr,1:nr) call stdlib${ii}$_${ci}$gesvd( 'O', 'N', nr, n, u, ldu, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) ! .. now [u](1:nr,1:nr) contains the nr left singular vectors of ! r. these will be pre-multiplied by q to build the left singular ! vectors of a. end if ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. ( .not.wntuf ) ) then call stdlib${ii}$_${ci}$laset('A', m-nr, nr, czero, czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_${ci}$laset( 'A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1), ldu ) call stdlib${ii}$_${ci}$laset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not.wntuf )call stdlib${ii}$_${ci}$unmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, & cwork(n+1), lcwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_${ci}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) else if ( rsvec .and. ( .not. lsvec ) ) then ! ....................................................................... ! The Singular Values And The Right Singular Vectors Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_${ci}$gesvd to r**h ! .. copy r**h into v and overwrite v with the left singular vectors do p = 1, nr do q = p, n v(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'U', nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**h overwrite v, the right singular ! vectors not computed if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_${ci}$gesvd( 'O', 'N', n, nr, v, ldv, s, u, ldu,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, nr v(p,p) = conjg(v(p,p)) do q = p + 1, nr ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do if ( nr < n ) then do p = 1, nr do q = nr + 1, n v(p,q) = conjg(v(q,p)) end do end do end if call stdlib${ii}$_${ci}$lapmt( .false., nr, n, v, ldv, iwork ) else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:n,1:nr) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the qr factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_${ci}$laset('G', n, n-nr, czero, czero, v(1_${ik}$,nr+1), ldv) call stdlib${ii}$_${ci}$gesvd( 'O', 'N', n, n, v, ldv, s, u, ldu,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, n v(p,p) = conjg(v(p,p)) do q = p + 1, n ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do call stdlib${ii}$_${ci}$lapmt( .false., n, n, v, ldv, iwork ) end if else ! Aply Stdlib_Zgesvd To R ! Copy R Into V And Overwrite V With The Right Singular Vectors call stdlib${ii}$_${ci}$lacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'L', nr-1, nr-1, czero, czero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors overwrite v, the nr left singular ! vectors stored in u(1:nr,1:nr) if ( wntvr .or. ( nr == n ) ) then call stdlib${ii}$_${ci}$gesvd( 'N', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_${ci}$lapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**h else ! .. need all n right singular vectors and nr < n ! [!] this is simple implementation that augments [v](1:nr,1:n) ! by padding a zero block. in the case nr << n, a more efficient ! way is to first use the lq factorization. for more details ! how to implement this, see the " full svd " branch. call stdlib${ii}$_${ci}$laset('G', n-nr, n, czero,czero, v(nr+1,1_${ik}$), ldv) call stdlib${ii}$_${ci}$gesvd( 'N', 'O', n, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_${ci}$lapmt( .false., n, n, v, ldv, iwork ) end if ! .. now [v] contains the adjoint of the matrix of the right singular ! vectors of a. end if else ! ....................................................................... ! Full Svd Requested ! ....................................................................... if ( rtrans ) then ! .. apply stdlib${ii}$_${ci}$gesvd to r**h [[this option is left for r if ( wntvr .or. ( nr == n ) ) then ! .. copy r**h into [v] and overwrite [v] with the left singular ! vectors of r**h do p = 1, nr do q = p, n v(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'U', nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$), ldv ) ! .. the left singular vectors of r**h overwrite [v], the nr right ! singular vectors of r**h stored in [u](1:nr,1:nr) as conjugate ! transposed call stdlib${ii}$_${ci}$gesvd( 'O', 'A', n, nr, v, ldv, s, v, ldv,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) ! Assemble V do p = 1, nr v(p,p) = conjg(v(p,p)) do q = p + 1, nr ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do if ( nr < n ) then do p = 1, nr do q = nr+1, n v(p,q) = conjg(v(q,p)) end do end do end if call stdlib${ii}$_${ci}$lapmt( .false., nr, n, v, ldv, iwork ) do p = 1, nr u(p,p) = conjg(u(p,p)) do q = p + 1, nr ctmp = conjg(u(q,p)) u(q,p) = conjg(u(p,q)) u(p,q) = ctmp end do end do if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ci}$laset('A', m-nr,nr, czero,czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_${ci}$laset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_${ci}$laset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! .. copy r**h into [v] and overwrite [v] with the left singular ! vectors of r**h ! [[the optimal ratio n/nr for using qrf instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'zgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio*nr > n ) then do p = 1, nr do q = p, n v(q,p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset('U',nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_${ci}$laset('A',n,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_${ci}$gesvd( 'O', 'A', n, n, v, ldv, s, v, ldv,u, ldu, cwork(n+1), & lcwork-n, rwork, info ) do p = 1, n v(p,p) = conjg(v(p,p)) do q = p + 1, n ctmp = conjg(v(q,p)) v(q,p) = conjg(v(p,q)) v(p,q) = ctmp end do end do call stdlib${ii}$_${ci}$lapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). do p = 1, n u(p,p) = conjg(u(p,p)) do q = p + 1, n ctmp = conjg(u(q,p)) u(q,p) = conjg(u(p,q)) u(p,q) = ctmp end do end do if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ci}$laset('A',m-n,n,czero,czero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_${ci}$laset('A',n,n1-n,czero,czero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_${ci}$laset('A',m-n,n1-n,czero,cone,u(n+1,n+1), ldu ) end if end if else ! .. copy r**h into [u] and overwrite [u] with the right ! singular vectors of r do p = 1, nr do q = p, n u(q,nr+p) = conjg(a(p,q)) end do end do if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset('U',nr-1,nr-1,czero,czero,u(1_${ik}$,nr+2),ldu) call stdlib${ii}$_${ci}$geqrf( n, nr, u(1_${ik}$,nr+1), ldu, cwork(n+1),cwork(n+nr+1), & lcwork-n-nr, ierr ) do p = 1, nr do q = 1, n v(q,p) = conjg(u(p,nr+q)) end do end do if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset('U',nr-1,nr-1,czero,czero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_${ci}$gesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v,ldv, cwork(n+nr+& 1_${ik}$),lcwork-n-nr,rwork, info ) call stdlib${ii}$_${ci}$laset('A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_${ci}$laset('A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_${ci}$laset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) call stdlib${ii}$_${ci}$unmqr('R','C', n, n, nr, u(1_${ik}$,nr+1), ldu,cwork(n+1),v,ldv,& cwork(n+nr+1),lcwork-n-nr,ierr) call stdlib${ii}$_${ci}$lapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ci}$laset('A',m-nr,nr,czero,czero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_${ci}$laset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_${ci}$laset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1),ldu) end if end if end if end if else ! .. apply stdlib${ii}$_${ci}$gesvd to r [[this is the recommended option]] if ( wntvr .or. ( nr == n ) ) then ! .. copy r into [v] and overwrite v with the right singular vectors call stdlib${ii}$_${ci}$lacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'L', nr-1,nr-1, czero,czero, v(2_${ik}$,1_${ik}$), ldv ) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_${ci}$gesvd( 'S', 'O', nr, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_${ci}$lapmt( .false., nr, n, v, ldv, iwork ) ! .. now [v](1:nr,1:n) contains v(1:n,1:nr)**h ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ci}$laset('A', m-nr,nr, czero,czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_${ci}$laset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_${ci}$laset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if else ! .. need all n right singular vectors and nr < n ! The Requested Number Of The Left Singular Vectors ! is then n1 (n or m) ! [[the optimal ratio n/nr for using lq instead of padding ! with zeros. here hard coded to 2; it must be at least ! two due to work space constraints.]] ! optratio = stdlib${ii}$_ilaenv(6, 'zgesvd', 's' // 'o', nr,n,0,0) ! optratio = max( optratio, 2 ) optratio = 2_${ik}$ if ( optratio * nr > n ) then call stdlib${ii}$_${ci}$lacpy( 'U', nr, n, a, lda, v, ldv ) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset('L', nr-1,nr-1, czero,czero, v(2_${ik}$,1_${ik}$),ldv) ! .. the right singular vectors of r overwrite [v], the nr left ! singular vectors of r stored in [u](1:nr,1:nr) call stdlib${ii}$_${ci}$laset('A', n-nr,n, czero,czero, v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_${ci}$gesvd( 'S', 'O', n, n, v, ldv, s, u, ldu,v, ldv, cwork(n+1), & lcwork-n, rwork, info ) call stdlib${ii}$_${ci}$lapmt( .false., n, n, v, ldv, iwork ) ! .. now [v] contains the adjoint of the matrix of the right ! singular vectors of a. the leading n left singular vectors ! are in [u](1:n,1:n) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x n1), i.e. (m x n) or (m x m). if ( ( n < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ci}$laset('A',m-n,n,czero,czero,u(n+1,1_${ik}$),ldu) if ( n < n1 ) then call stdlib${ii}$_${ci}$laset('A',n,n1-n,czero,czero,u(1_${ik}$,n+1),ldu) call stdlib${ii}$_${ci}$laset( 'A',m-n,n1-n,czero,cone,u(n+1,n+1), ldu ) end if end if else call stdlib${ii}$_${ci}$lacpy( 'U', nr, n, a, lda, u(nr+1,1_${ik}$), ldu ) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset('L',nr-1,nr-1,czero,czero,u(nr+2,1_${ik}$),ldu) call stdlib${ii}$_${ci}$gelqf( nr, n, u(nr+1,1_${ik}$), ldu, cwork(n+1),cwork(n+nr+1), & lcwork-n-nr, ierr ) call stdlib${ii}$_${ci}$lacpy('L',nr,nr,u(nr+1,1_${ik}$),ldu,v,ldv) if ( nr > 1_${ik}$ )call stdlib${ii}$_${ci}$laset('U',nr-1,nr-1,czero,czero,v(1_${ik}$,2_${ik}$),ldv) call stdlib${ii}$_${ci}$gesvd( 'S', 'O', nr, nr, v, ldv, s, u, ldu,v, ldv, cwork(n+nr+& 1_${ik}$), lcwork-n-nr, rwork, info ) call stdlib${ii}$_${ci}$laset('A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_${ci}$laset('A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_${ci}$laset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) call stdlib${ii}$_${ci}$unmlq('R','N',n,n,nr,u(nr+1,1_${ik}$),ldu,cwork(n+1),v, ldv, cwork(n+& nr+1),lcwork-n-nr,ierr) call stdlib${ii}$_${ci}$lapmt( .false., n, n, v, ldv, iwork ) ! Assemble The Left Singular Vector Matrix U Of Dimensions ! (m x nr) or (m x n) or (m x m). if ( ( nr < m ) .and. .not.(wntuf)) then call stdlib${ii}$_${ci}$laset('A',m-nr,nr,czero,czero,u(nr+1,1_${ik}$),ldu) if ( nr < n1 ) then call stdlib${ii}$_${ci}$laset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_${ci}$laset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1), ldu ) end if end if end if end if ! .. end of the "r**h or r" branch end if ! the q matrix from the first qrf is built into the left singular ! vectors matrix u. if ( .not. wntuf )call stdlib${ii}$_${ci}$unmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, & cwork(n+1), lcwork-n, ierr ) if ( rowprm .and. .not.wntuf )call stdlib${ii}$_${ci}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(n+1), -& 1_${ik}$ ) ! ... end of the "full svd" branch end if ! check whether some singular values are returned as zeros, e.g. ! due to underflow, and update the numerical rank. p = nr do q = p, 1, -1 if ( s(q) > zero ) go to 4002 nr = nr - 1_${ik}$ end do 4002 continue ! .. if numerical rank deficiency is detected, the truncated ! singular values are set to zero. if ( nr < n ) call stdlib${ii}$_${c2ri(ci)}$laset( 'G', n-nr,1_${ik}$, zero,zero, s(nr+1), n ) ! .. undo scaling; this may cause overflow in the largest singular ! values. if ( ascaled )call stdlib${ii}$_${c2ri(ci)}$lascl( 'G',0_${ik}$,0_${ik}$, one,sqrt(real(m,KIND=${ck}$)), nr,1_${ik}$, s, n, ierr & ) if ( conda ) rwork(1_${ik}$) = sconda rwork(2_${ik}$) = p - nr ! .. p-nr is the number of singular values that are computed as ! exact zeros in stdlib${ii}$_${ci}$gesvd() applied to the (possibly truncated) ! full row rank triangular (trapezoidal) factor of a. numrank = nr return end subroutine stdlib${ii}$_${ci}$gesvdq #:endif #:endfor #:endfor end submodule stdlib_lapack_eigv_svd_drivers fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_solve_chol.fypp0000664000175000017500000057635415135654166026145 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_solve) stdlib_lapack_solve_chol implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sposv( uplo, n, nrhs, a, lda, b, ldb, info ) !! SPOSV computes the solution to a real system of linear equations !! A * X = B, !! where A is an N-by-N symmetric positive definite matrix and X and B !! are N-by-NRHS matrices. !! The Cholesky decomposition is used to factor A as !! A = U**T* U, if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix and L is a lower triangular !! matrix. The factored form of A is then used to solve the system of !! equations A * X = B. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*) ! ===================================================================== ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_slansy( '1', uplo, n, a, lda, work ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_spocon( uplo, n, af, ldaf, anorm, rcond, work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_slacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_spotrs( uplo, n, nrhs, af, ldaf, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_sporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x, ldx,ferr, berr, work, & iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_dlansy( '1', uplo, n, a, lda, work ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_dpocon( uplo, n, af, ldaf, anorm, rcond, work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_dlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_dpotrs( uplo, n, nrhs, af, ldaf, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_dporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x, ldx,ferr, berr, work, & iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_${ri}$lansy( '1', uplo, n, a, lda, work ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ri}$pocon( uplo, n, af, ldaf, anorm, rcond, work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_${ri}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ri}$potrs( uplo, n, nrhs, af, ldaf, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_${ri}$porfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x, ldx,ferr, berr, work, & iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_clanhe( '1', uplo, n, a, lda, rwork ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_cpocon( uplo, n, af, ldaf, anorm, rcond, work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_clacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_cpotrs( uplo, n, nrhs, af, ldaf, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_cporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x, ldx,ferr, berr, work, & rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_zlanhe( '1', uplo, n, a, lda, rwork ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_zpocon( uplo, n, af, ldaf, anorm, rcond, work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_zlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_zpotrs( uplo, n, nrhs, af, ldaf, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_zporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x, ldx,ferr, berr, work, & rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_${ci}$lanhe( '1', uplo, n, a, lda, rwork ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ci}$pocon( uplo, n, af, ldaf, anorm, rcond, work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_${ci}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ci}$potrs( uplo, n, nrhs, af, ldaf, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_${ci}$porfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x, ldx,ferr, berr, work, & rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_slansp( 'I', uplo, n, ap, work ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_sppcon( uplo, n, afp, anorm, rcond, work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_slacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_spptrs( uplo, n, nrhs, afp, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_spprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr, berr,work, iwork, & info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_dlansp( 'I', uplo, n, ap, work ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_dppcon( uplo, n, afp, anorm, rcond, work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_dlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_dpptrs( uplo, n, nrhs, afp, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_dpprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr, berr,work, iwork, & info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_${ri}$lansp( 'I', uplo, n, ap, work ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ri}$ppcon( uplo, n, afp, anorm, rcond, work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_${ri}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ri}$pptrs( uplo, n, nrhs, afp, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_${ri}$pprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr, berr,work, iwork, & info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_clanhp( 'I', uplo, n, ap, rwork ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_cppcon( uplo, n, afp, anorm, rcond, work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_clacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_cpptrs( uplo, n, nrhs, afp, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_cpprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr, berr,work, rwork, & info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_zlanhp( 'I', uplo, n, ap, rwork ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_zppcon( uplo, n, afp, anorm, rcond, work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_zlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_zpptrs( uplo, n, nrhs, afp, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_zpprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr, berr,work, rwork, & info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_${ci}$lanhp( 'I', uplo, n, ap, rwork ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ci}$ppcon( uplo, n, afp, anorm, rcond, work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_${ci}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ci}$pptrs( uplo, n, nrhs, afp, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_${ci}$pprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr, berr,work, rwork, & info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_slansb( '1', uplo, n, kd, ab, ldab, work ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_spbcon( uplo, n, kd, afb, ldafb, anorm, rcond, work, iwork,info ) ! compute the solution matrix x. call stdlib${ii}$_slacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_spbtrs( uplo, n, kd, nrhs, afb, ldafb, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_spbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b, ldb, x,ldx, ferr, berr,& work, iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_dlansb( '1', uplo, n, kd, ab, ldab, work ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_dpbcon( uplo, n, kd, afb, ldafb, anorm, rcond, work, iwork,info ) ! compute the solution matrix x. call stdlib${ii}$_dlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_dpbtrs( uplo, n, kd, nrhs, afb, ldafb, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_dpbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b, ldb, x,ldx, ferr, berr,& work, iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_${ri}$lansb( '1', uplo, n, kd, ab, ldab, work ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ri}$pbcon( uplo, n, kd, afb, ldafb, anorm, rcond, work, iwork,info ) ! compute the solution matrix x. call stdlib${ii}$_${ri}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ri}$pbtrs( uplo, n, kd, nrhs, afb, ldafb, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_${ri}$pbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b, ldb, x,ldx, ferr, berr,& work, iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_clanhb( '1', uplo, n, kd, ab, ldab, rwork ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_cpbcon( uplo, n, kd, afb, ldafb, anorm, rcond, work, rwork,info ) ! compute the solution matrix x. call stdlib${ii}$_clacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_cpbtrs( uplo, n, kd, nrhs, afb, ldafb, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_cpbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b, ldb, x,ldx, ferr, berr,& work, rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_zlanhb( '1', uplo, n, kd, ab, ldab, rwork ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_zpbcon( uplo, n, kd, afb, ldafb, anorm, rcond, work, rwork,info ) ! compute the solution matrix x. call stdlib${ii}$_zlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_zpbtrs( uplo, n, kd, nrhs, afb, ldafb, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_zpbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b, ldb, x,ldx, ferr, berr,& work, rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then scond = max( smin, smlnum ) / min( smax, bignum ) else scond = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_${ci}$lanhb( '1', uplo, n, kd, ab, ldab, rwork ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ci}$pbcon( uplo, n, kd, afb, ldafb, anorm, rcond, work, rwork,info ) ! compute the solution matrix x. call stdlib${ii}$_${ci}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ci}$pbtrs( uplo, n, kd, nrhs, afb, ldafb, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_${ci}$pbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b, ldb, x,ldx, ferr, berr,& work, rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( rcequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = s( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / scond end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond1_${ik}$ )call stdlib${ii}$_scopy( n-1, e, 1_${ik}$, ef, 1_${ik}$ ) call stdlib${ii}$_spttrf( n, df, ef, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_slanst( '1', n, d, e ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_sptcon( n, df, ef, anorm, rcond, work, info ) ! compute the solution vectors x. call stdlib${ii}$_slacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_spttrs( n, nrhs, df, ef, x, ldx, info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_sptrfs( n, nrhs, d, e, df, ef, b, ldb, x, ldx, ferr, berr,work, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond1_${ik}$ )call stdlib${ii}$_dcopy( n-1, e, 1_${ik}$, ef, 1_${ik}$ ) call stdlib${ii}$_dpttrf( n, df, ef, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_dlanst( '1', n, d, e ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_dptcon( n, df, ef, anorm, rcond, work, info ) ! compute the solution vectors x. call stdlib${ii}$_dlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_dpttrs( n, nrhs, df, ef, x, ldx, info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_dptrfs( n, nrhs, d, e, df, ef, b, ldb, x, ldx, ferr, berr,work, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond1_${ik}$ )call stdlib${ii}$_${ri}$copy( n-1, e, 1_${ik}$, ef, 1_${ik}$ ) call stdlib${ii}$_${ri}$pttrf( n, df, ef, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_${ri}$lanst( '1', n, d, e ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ri}$ptcon( n, df, ef, anorm, rcond, work, info ) ! compute the solution vectors x. call stdlib${ii}$_${ri}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ri}$pttrs( n, nrhs, df, ef, x, ldx, info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_${ri}$ptrfs( n, nrhs, d, e, df, ef, b, ldb, x, ldx, ferr, berr,work, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond1_${ik}$ )call stdlib${ii}$_ccopy( n-1, e, 1_${ik}$, ef, 1_${ik}$ ) call stdlib${ii}$_cpttrf( n, df, ef, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_clanht( '1', n, d, e ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_cptcon( n, df, ef, anorm, rcond, rwork, info ) ! compute the solution vectors x. call stdlib${ii}$_clacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_cpttrs( 'LOWER', n, nrhs, df, ef, x, ldx, info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_cptrfs( 'LOWER', n, nrhs, d, e, df, ef, b, ldb, x, ldx, ferr,berr, work, & rwork, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond1_${ik}$ )call stdlib${ii}$_zcopy( n-1, e, 1_${ik}$, ef, 1_${ik}$ ) call stdlib${ii}$_zpttrf( n, df, ef, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_zlanht( '1', n, d, e ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_zptcon( n, df, ef, anorm, rcond, rwork, info ) ! compute the solution vectors x. call stdlib${ii}$_zlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_zpttrs( 'LOWER', n, nrhs, df, ef, x, ldx, info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_zptrfs( 'LOWER', n, nrhs, d, e, df, ef, b, ldb, x, ldx, ferr,berr, work, & rwork, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond1_${ik}$ )call stdlib${ii}$_${ci}$copy( n-1, e, 1_${ik}$, ef, 1_${ik}$ ) call stdlib${ii}$_${ci}$pttrf( n, df, ef, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. anorm = stdlib${ii}$_${ci}$lanht( '1', n, d, e ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ci}$ptcon( n, df, ef, anorm, rcond, rwork, info ) ! compute the solution vectors x. call stdlib${ii}$_${ci}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ci}$pttrs( 'LOWER', n, nrhs, df, ef, x, ldx, info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_${ci}$ptrfs( 'LOWER', n, nrhs, d, e, df, ef, b, ldb, x, ldx, ferr,berr, work, & rwork, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**h) or inv(u*d*u**h). call stdlib${ii}$_chetrs( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_checon pure module subroutine stdlib${ii}$_zhecon( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) !! ZHECON estimates the reciprocal of the condition number of a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by ZHETRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(dp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**h) or inv(u*d*u**h). call stdlib${ii}$_zhetrs( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_zhecon #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hecon( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) !! ZHECON: estimates the reciprocal of the condition number of a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by ZHETRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(in) :: anorm real(${ck}$), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(${ck}$) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**h) or inv(u*d*u**h). call stdlib${ii}$_${ci}$hetrs( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_${ci}$hecon #:endif #:endfor pure module subroutine stdlib${ii}$_chetrf( uplo, n, a, lda, ipiv, work, lwork, info ) !! CHETRF computes the factorization of a complex Hermitian matrix A !! using the Bunch-Kaufman diagonal pivoting method. The form of the !! factorization is !! A = U*D*U**H or A = L*D*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_clahef( uplo, k, nb, kb, a, lda, ipiv, work, n, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_chetf2( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_clahef; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_clahef( uplo, n-k+1, nb, kb, a( k, k ), lda, ipiv( k ),work, n, & iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_chetf2( uplo, n-k+1, a( k, k ), lda, ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_chetrf pure module subroutine stdlib${ii}$_zhetrf( uplo, n, a, lda, ipiv, work, lwork, info ) !! ZHETRF computes the factorization of a complex Hermitian matrix A !! using the Bunch-Kaufman diagonal pivoting method. The form of the !! factorization is !! A = U*D*U**H or A = L*D*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_zlahef( uplo, k, nb, kb, a, lda, ipiv, work, n, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_zhetf2( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_zlahef; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_zlahef( uplo, n-k+1, nb, kb, a( k, k ), lda, ipiv( k ),work, n, & iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_zhetf2( uplo, n-k+1, a( k, k ), lda, ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zhetrf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hetrf( uplo, n, a, lda, ipiv, work, lwork, info ) !! ZHETRF: computes the factorization of a complex Hermitian matrix A !! using the Bunch-Kaufman diagonal pivoting method. The form of the !! factorization is !! A = U*D*U**H or A = L*D*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_${ci}$lahef( uplo, k, nb, kb, a, lda, ipiv, work, n, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_${ci}$hetf2( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_${ci}$lahef; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_${ci}$lahef( uplo, n-k+1, nb, kb, a( k, k ), lda, ipiv( k ),work, n, & iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_${ci}$hetf2( uplo, n-k+1, a( k, k ), lda, ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$hetrf #:endif #:endfor pure module subroutine stdlib${ii}$_clahef( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) !! CLAHEF computes a partial factorization of a complex Hermitian !! matrix A using the Bunch-Kaufman diagonal pivoting method. The !! partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**H U22**H ) !! A = ( L11 0 ) ( D 0 ) ( L11**H L21**H ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**H denotes the conjugate transpose of U. !! CLAHEF is an auxiliary routine called by CHETRF. It uses blocked code !! (calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or !! A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars integer(${ik}$) :: imax, j, jb, jj, jmax, jp, k, kk, kkw, kp, kstep, kw real(sp) :: absakk, alpha, colmax, r1, rowmax, t complex(sp) :: d11, d21, d22, z ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=sp) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 (note that conjg(w) is actually stored) ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=sp) else ! ============================================================ ! begin pivot search ! case(1) if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! begin pivot search along imax row ! copy column imax to column kw-1 of w and update it call stdlib${ii}$_ccopy( imax-1, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) w( imax, kw-1 ) = real( a( imax, imax ),KIND=sp) call stdlib${ii}$_ccopy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_clacgv( k-imax, w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then jmax = stdlib${ii}$_icamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( w( jmax, kw-1 ) ) ) end if ! case(2) if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k ! case(3) else if( abs( real( w( imax, kw-1 ),KIND=sp) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column kw-1 of w to column kw of w call stdlib${ii}$_ccopy( k, w( 1_${ik}$, kw-1 ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) ! case(4) else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if ! end pivot search along imax row end if ! end pivot search ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k - kstep + 1_${ik}$ ! kkw is the column of w which corresponds to column kk of a kkw = nb + kk - n ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kkw of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k-1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=sp) call stdlib${ii}$_ccopy( kk-1-kp, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) call stdlib${ii}$_clacgv( kk-1-kp, a( kp, kp+1 ), lda ) if( kp>1_${ik}$ )call stdlib${ii}$_ccopy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k1_${ik}$ ) then ! (note: no need to check if a(k,k) is not zero, ! since that was ensured earlier in pivot search: ! case a(k,k) = 0 falls into 2x2 pivot case(4)) r1 = one / real( a( k, k ),KIND=sp) call stdlib${ii}$_csscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) ! (2) conjugate column w(kw) call stdlib${ii}$_clacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now hold ! ( w(kw-1) w(kw) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! (1) store u(1:k-2,k-1) and u(1:k-2,k) and 2-by-2 ! block d(k-1:k,k-1:k) in columns k-1 and k of a. ! (note: 2-by-2 diagonal block u(k-1:k,k-1:k) is a unit ! block and not stored) ! a(k-1:k,k-1:k) := d(k-1:k,k-1:k) = w(k-1:k,kw-1:kw) ! a(1:k-2,k-1:k) := u(1:k-2,k:k-1:k) = ! = w(1:k-2,kw-1:kw) * ( d(k-1:k,k-1:k)**(-1) ) if( k>2_${ik}$ ) then ! factor out the columns of the inverse of 2-by-2 pivot ! block d, so that each column contains 1, to reduce the ! number of flops when we multiply panel ! ( w(kw-1) w(kw) ) by this inverse, i.e. by d**(-1). ! d**(-1) = ( d11 cj(d21) )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-|d21|**2) * ( ( d22) (-cj(d21) ) ) = ! ( (-d21) ( d11 ) ) ! = 1/(|d21|**2) * 1/((d11/cj(d21))*(d22/d21)-1) * ! * ( d21*( d22/d21 ) conj(d21)*( - 1 ) ) = ! ( ( -1 ) ( d11/conj(d21) ) ) ! = 1/(|d21|**2) * 1/(d22*d11-1) * ! * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = (1/|d21|**2) * t * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( (t/conj(d21))*( d11 ) (t/d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( conj(d21)*( d11 ) d21*( -1 ) ) ! ( ( -1 ) ( d22 ) ), ! where d11 = d22/d21, ! d22 = d11/conj(d21), ! d21 = t/d21, ! t = 1/(d22*d11-1). ! (note: no need to check for division by zero, ! since that was ensured earlier in pivot search: ! (a) d21 != 0, since in 2x2 pivot case(4) ! |d21| should be larger than |d11| and |d22|; ! (b) (d22*d11 - 1) != 0, since from (a), ! both |d11| < 1, |d22| < 1, hence |d22*d11| << 1.) d21 = w( k-1, kw ) d11 = w( k, kw ) / conjg( d21 ) d22 = w( k-1, kw-1 ) / d21 t = one / ( real( d11*d22,KIND=sp)-one ) d21 = t / d21 ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = d21*( d11*w( j, kw-1 )-w( j, kw ) ) a( j, k ) = conjg( d21 )*( d22*w( j, kw )-w( j, kw-1 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) ! (2) conjugate columns w(kw) and w(kw-1) call stdlib${ii}$_clacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) call stdlib${ii}$_clacgv( k-2, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**h = a11 - u12*w**h ! computing blocks of nb columns at a time (note that conjg(w) is ! actually stored) do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 a( jj, jj ) = real( a( jj, jj ),KIND=sp) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) a( jj, jj ) = real( a( jj, jj ),KIND=sp) end do ! update the rectangular superdiagonal block call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( 1_${ik}$, k+1 ), & lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in of rows in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows j and jp ! at each step j ! (here, j is a diagonal index) jj = j jp = ipiv( j ) if( jp<0_${ik}$ ) then jp = -jp ! (here, j is a diagonal index) j = j + 1_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp/=jj .and. j<=n )call stdlib${ii}$_cswap( n-j+1, a( jp, j ), lda, a( jj, j ), & lda ) if( j<=n )go to 60 ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 (note that conjg(w) is actually stored) ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ ! copy column k of a to column k of w and update it w( k, k ) = real( a( k, k ),KIND=sp) if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! begin pivot search along imax row ! copy column imax to column k+1 of w and update it call stdlib${ii}$_ccopy( imax-k, a( imax, k ), lda, w( k, k+1 ), 1_${ik}$ ) call stdlib${ii}$_clacgv( imax-k, w( k, k+1 ), 1_${ik}$ ) w( imax, k+1 ) = real( a( imax, imax ),KIND=sp) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k ! case(3) else if( abs( real( w( imax, k+1 ),KIND=sp) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column k+1 of w to column k of w call stdlib${ii}$_ccopy( n-k+1, w( k, k+1 ), 1_${ik}$, w( k, k ), 1_${ik}$ ) ! case(4) else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if ! end pivot search along imax row end if ! end pivot search ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k + kstep - 1_${ik}$ ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=sp) call stdlib${ii}$_ccopy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) call stdlib${ii}$_clacgv( kp-kk-1, a( kp, kk+1 ), lda ) if( kp1_${ik}$ )call stdlib${ii}$_cswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_cswap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! (1) store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) ! (note: no need to use for hermitian matrix ! a( k, k ) = real( w( k, k),KIND=sp) to separately copy diagonal ! element d(k,k) from w (potentially saves only one load)) call stdlib${ii}$_ccopy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=1_${ik}$ )call stdlib${ii}$_cswap( j, a( jp, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) if( j>=1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_clahef pure module subroutine stdlib${ii}$_zlahef( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) !! ZLAHEF computes a partial factorization of a complex Hermitian !! matrix A using the Bunch-Kaufman diagonal pivoting method. The !! partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**H U22**H ) !! A = ( L11 0 ) ( D 0 ) ( L11**H L21**H ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**H denotes the conjugate transpose of U. !! ZLAHEF is an auxiliary routine called by ZHETRF. It uses blocked code !! (calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or !! A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(dp), parameter :: sevten = 17.0e+0_dp ! Local Scalars integer(${ik}$) :: imax, j, jb, jj, jmax, jp, k, kk, kkw, kp, kstep, kw real(dp) :: absakk, alpha, colmax, r1, rowmax, t complex(dp) :: d11, d21, d22, z ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=dp) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 (note that conjg(w) is actually stored) ! k is the main loop index, decreasing from n in steps of 1 or 2 ! kw is the column of w which corresponds to column k of a k = n 10 continue kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=dp) else ! ============================================================ ! begin pivot search ! case(1) if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! begin pivot search along imax row ! copy column imax to column kw-1 of w and update it call stdlib${ii}$_zcopy( imax-1, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) w( imax, kw-1 ) = real( a( imax, imax ),KIND=dp) call stdlib${ii}$_zcopy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( k-imax, w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then jmax = stdlib${ii}$_izamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( w( jmax, kw-1 ) ) ) end if ! case(2) if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k ! case(3) else if( abs( real( w( imax, kw-1 ),KIND=dp) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column kw-1 of w to column kw of w call stdlib${ii}$_zcopy( k, w( 1_${ik}$, kw-1 ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) ! case(4) else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if ! end pivot search along imax row end if ! end pivot search ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k - kstep + 1_${ik}$ ! kkw is the column of w which corresponds to column kk of a kkw = nb + kk - n ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kkw of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k-1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=dp) call stdlib${ii}$_zcopy( kk-1-kp, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) call stdlib${ii}$_zlacgv( kk-1-kp, a( kp, kp+1 ), lda ) if( kp>1_${ik}$ )call stdlib${ii}$_zcopy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k1_${ik}$ ) then ! (note: no need to check if a(k,k) is not zero, ! since that was ensured earlier in pivot search: ! case a(k,k) = 0 falls into 2x2 pivot case(4)) r1 = one / real( a( k, k ),KIND=dp) call stdlib${ii}$_zdscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) ! (2) conjugate column w(kw) call stdlib${ii}$_zlacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now hold ! ( w(kw-1) w(kw) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! (1) store u(1:k-2,k-1) and u(1:k-2,k) and 2-by-2 ! block d(k-1:k,k-1:k) in columns k-1 and k of a. ! (note: 2-by-2 diagonal block u(k-1:k,k-1:k) is a unit ! block and not stored) ! a(k-1:k,k-1:k) := d(k-1:k,k-1:k) = w(k-1:k,kw-1:kw) ! a(1:k-2,k-1:k) := u(1:k-2,k:k-1:k) = ! = w(1:k-2,kw-1:kw) * ( d(k-1:k,k-1:k)**(-1) ) if( k>2_${ik}$ ) then ! factor out the columns of the inverse of 2-by-2 pivot ! block d, so that each column contains 1, to reduce the ! number of flops when we multiply panel ! ( w(kw-1) w(kw) ) by this inverse, i.e. by d**(-1). ! d**(-1) = ( d11 cj(d21) )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-|d21|**2) * ( ( d22) (-cj(d21) ) ) = ! ( (-d21) ( d11 ) ) ! = 1/(|d21|**2) * 1/((d11/cj(d21))*(d22/d21)-1) * ! * ( d21*( d22/d21 ) conj(d21)*( - 1 ) ) = ! ( ( -1 ) ( d11/conj(d21) ) ) ! = 1/(|d21|**2) * 1/(d22*d11-1) * ! * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = (1/|d21|**2) * t * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( (t/conj(d21))*( d11 ) (t/d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( conj(d21)*( d11 ) d21*( -1 ) ) ! ( ( -1 ) ( d22 ) ), ! where d11 = d22/d21, ! d22 = d11/conj(d21), ! d21 = t/d21, ! t = 1/(d22*d11-1). ! (note: no need to check for division by zero, ! since that was ensured earlier in pivot search: ! (a) d21 != 0, since in 2x2 pivot case(4) ! |d21| should be larger than |d11| and |d22|; ! (b) (d22*d11 - 1) != 0, since from (a), ! both |d11| < 1, |d22| < 1, hence |d22*d11| << 1.) d21 = w( k-1, kw ) d11 = w( k, kw ) / conjg( d21 ) d22 = w( k-1, kw-1 ) / d21 t = one / ( real( d11*d22,KIND=dp)-one ) d21 = t / d21 ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = d21*( d11*w( j, kw-1 )-w( j, kw ) ) a( j, k ) = conjg( d21 )*( d22*w( j, kw )-w( j, kw-1 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) ! (2) conjugate columns w(kw) and w(kw-1) call stdlib${ii}$_zlacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( k-2, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**h = a11 - u12*w**h ! computing blocks of nb columns at a time (note that conjg(w) is ! actually stored) do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 a( jj, jj ) = real( a( jj, jj ),KIND=dp) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) a( jj, jj ) = real( a( jj, jj ),KIND=dp) end do ! update the rectangular superdiagonal block call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( 1_${ik}$, k+1 ), & lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows jj and jp at each ! step j ! (here, j is a diagonal index) jj = j jp = ipiv( j ) if( jp<0_${ik}$ ) then jp = -jp ! (here, j is a diagonal index) j = j + 1_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp/=jj .and. j<=n )call stdlib${ii}$_zswap( n-j+1, a( jp, j ), lda, a( jj, j ), & lda ) if( j=nb .and. nbn )go to 90 kstep = 1_${ik}$ ! copy column k of a to column k of w and update it w( k, k ) = real( a( k, k ),KIND=dp) if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! begin pivot search along imax row ! copy column imax to column k+1 of w and update it call stdlib${ii}$_zcopy( imax-k, a( imax, k ), lda, w( k, k+1 ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( imax-k, w( k, k+1 ), 1_${ik}$ ) w( imax, k+1 ) = real( a( imax, imax ),KIND=dp) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k ! case(3) else if( abs( real( w( imax, k+1 ),KIND=dp) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column k+1 of w to column k of w call stdlib${ii}$_zcopy( n-k+1, w( k, k+1 ), 1_${ik}$, w( k, k ), 1_${ik}$ ) ! case(4) else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if ! end pivot search along imax row end if ! end pivot search ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k + kstep - 1_${ik}$ ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=dp) call stdlib${ii}$_zcopy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) call stdlib${ii}$_zlacgv( kp-kk-1, a( kp, kk+1 ), lda ) if( kp1_${ik}$ )call stdlib${ii}$_zswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_zswap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! (1) store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) ! (note: no need to use for hermitian matrix ! a( k, k ) = real( w( k, k),KIND=dp) to separately copy diagonal ! element d(k,k) from w (potentially saves only one load)) call stdlib${ii}$_zcopy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=1_${ik}$ )call stdlib${ii}$_zswap( j, a( jp, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) if( j>1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_zlahef #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lahef( uplo, n, nb, kb, a, lda, ipiv, w, ldw, info ) !! ZLAHEF: computes a partial factorization of a complex Hermitian !! matrix A using the Bunch-Kaufman diagonal pivoting method. The !! partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**H U22**H ) !! A = ( L11 0 ) ( D 0 ) ( L11**H L21**H ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**H denotes the conjugate transpose of U. !! ZLAHEF is an auxiliary routine called by ZHETRF. It uses blocked code !! (calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or !! A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: sevten = 17.0e+0_${ck}$ ! Local Scalars integer(${ik}$) :: imax, j, jb, jj, jmax, jp, k, kk, kkw, kp, kstep, kw real(${ck}$) :: absakk, alpha, colmax, r1, rowmax, t complex(${ck}$) :: d11, d21, d22, z ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=${ck}$) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 (note that conjg(w) is actually stored) ! k is the main loop index, decreasing from n in steps of 1 or 2 ! kw is the column of w which corresponds to column k of a k = n 10 continue kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=${ck}$) else ! ============================================================ ! begin pivot search ! case(1) if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! begin pivot search along imax row ! copy column imax to column kw-1 of w and update it call stdlib${ii}$_${ci}$copy( imax-1, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) w( imax, kw-1 ) = real( a( imax, imax ),KIND=${ck}$) call stdlib${ii}$_${ci}$copy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( k-imax, w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then jmax = stdlib${ii}$_i${ci}$amax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( w( jmax, kw-1 ) ) ) end if ! case(2) if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k ! case(3) else if( abs( real( w( imax, kw-1 ),KIND=${ck}$) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column kw-1 of w to column kw of w call stdlib${ii}$_${ci}$copy( k, w( 1_${ik}$, kw-1 ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) ! case(4) else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if ! end pivot search along imax row end if ! end pivot search ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k - kstep + 1_${ik}$ ! kkw is the column of w which corresponds to column kk of a kkw = nb + kk - n ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kkw of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k-1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=${ck}$) call stdlib${ii}$_${ci}$copy( kk-1-kp, a( kp+1, kk ), 1_${ik}$, a( kp, kp+1 ),lda ) call stdlib${ii}$_${ci}$lacgv( kk-1-kp, a( kp, kp+1 ), lda ) if( kp>1_${ik}$ )call stdlib${ii}$_${ci}$copy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k1_${ik}$ ) then ! (note: no need to check if a(k,k) is not zero, ! since that was ensured earlier in pivot search: ! case a(k,k) = 0 falls into 2x2 pivot case(4)) r1 = one / real( a( k, k ),KIND=${ck}$) call stdlib${ii}$_${ci}$dscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) ! (2) conjugate column w(kw) call stdlib${ii}$_${ci}$lacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now hold ! ( w(kw-1) w(kw) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! (1) store u(1:k-2,k-1) and u(1:k-2,k) and 2-by-2 ! block d(k-1:k,k-1:k) in columns k-1 and k of a. ! (note: 2-by-2 diagonal block u(k-1:k,k-1:k) is a unit ! block and not stored) ! a(k-1:k,k-1:k) := d(k-1:k,k-1:k) = w(k-1:k,kw-1:kw) ! a(1:k-2,k-1:k) := u(1:k-2,k:k-1:k) = ! = w(1:k-2,kw-1:kw) * ( d(k-1:k,k-1:k)**(-1) ) if( k>2_${ik}$ ) then ! factor out the columns of the inverse of 2-by-2 pivot ! block d, so that each column contains 1, to reduce the ! number of flops when we multiply panel ! ( w(kw-1) w(kw) ) by this inverse, i.e. by d**(-1). ! d**(-1) = ( d11 cj(d21) )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-|d21|**2) * ( ( d22) (-cj(d21) ) ) = ! ( (-d21) ( d11 ) ) ! = 1/(|d21|**2) * 1/((d11/cj(d21))*(d22/d21)-1) * ! * ( d21*( d22/d21 ) conj(d21)*( - 1 ) ) = ! ( ( -1 ) ( d11/conj(d21) ) ) ! = 1/(|d21|**2) * 1/(d22*d11-1) * ! * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = (1/|d21|**2) * t * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( (t/conj(d21))*( d11 ) (t/d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( conj(d21)*( d11 ) d21*( -1 ) ) ! ( ( -1 ) ( d22 ) ), ! where d11 = d22/d21, ! d22 = d11/conj(d21), ! d21 = t/d21, ! t = 1/(d22*d11-1). ! (note: no need to check for division by zero, ! since that was ensured earlier in pivot search: ! (a) d21 != 0, since in 2x2 pivot case(4) ! |d21| should be larger than |d11| and |d22|; ! (b) (d22*d11 - 1) != 0, since from (a), ! both |d11| < 1, |d22| < 1, hence |d22*d11| << 1.) d21 = w( k-1, kw ) d11 = w( k, kw ) / conjg( d21 ) d22 = w( k-1, kw-1 ) / d21 t = one / ( real( d11*d22,KIND=${ck}$)-one ) d21 = t / d21 ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = d21*( d11*w( j, kw-1 )-w( j, kw ) ) a( j, k ) = conjg( d21 )*( d22*w( j, kw )-w( j, kw-1 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) ! (2) conjugate columns w(kw) and w(kw-1) call stdlib${ii}$_${ci}$lacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( k-2, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**h = a11 - u12*w**h ! computing blocks of nb columns at a time (note that conjg(w) is ! actually stored) do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 a( jj, jj ) = real( a( jj, jj ),KIND=${ck}$) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) a( jj, jj ) = real( a( jj, jj ),KIND=${ck}$) end do ! update the rectangular superdiagonal block call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( 1_${ik}$, k+1 ), & lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows jj and jp at each ! step j ! (here, j is a diagonal index) jj = j jp = ipiv( j ) if( jp<0_${ik}$ ) then jp = -jp ! (here, j is a diagonal index) j = j + 1_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp/=jj .and. j<=n )call stdlib${ii}$_${ci}$swap( n-j+1, a( jp, j ), lda, a( jj, j ), & lda ) if( j=nb .and. nbn )go to 90 kstep = 1_${ik}$ ! copy column k of a to column k of w and update it w( k, k ) = real( a( k, k ),KIND=${ck}$) if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! begin pivot search along imax row ! copy column imax to column k+1 of w and update it call stdlib${ii}$_${ci}$copy( imax-k, a( imax, k ), lda, w( k, k+1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( imax-k, w( k, k+1 ), 1_${ik}$ ) w( imax, k+1 ) = real( a( imax, imax ),KIND=${ck}$) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k ! case(3) else if( abs( real( w( imax, k+1 ),KIND=${ck}$) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax ! copy column k+1 of w to column k of w call stdlib${ii}$_${ci}$copy( n-k+1, w( k, k+1 ), 1_${ik}$, w( k, k ), 1_${ik}$ ) ! case(4) else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if ! end pivot search along imax row end if ! end pivot search ! ============================================================ ! kk is the column of a where pivoting step stopped kk = k + kstep - 1_${ik}$ ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=${ck}$) call stdlib${ii}$_${ci}$copy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) call stdlib${ii}$_${ci}$lacgv( kp-kk-1, a( kp, kk+1 ), lda ) if( kp1_${ik}$ )call stdlib${ii}$_${ci}$swap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$swap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! (1) store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) ! (note: no need to use for hermitian matrix ! a( k, k ) = real( w( k, k),KIND=${ck}$) to separately copy diagonal ! element d(k,k) from w (potentially saves only one load)) call stdlib${ii}$_${ci}$copy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=1_${ik}$ )call stdlib${ii}$_${ci}$swap( j, a( jp, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) if( j>1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_${ci}$lahef #:endif #:endfor pure module subroutine stdlib${ii}$_chetf2( uplo, n, a, lda, ipiv, info ) !! CHETF2 computes the factorization of a complex Hermitian matrix A !! using the Bunch-Kaufman diagonal pivoting method: !! A = U*D*U**H or A = L*D*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, U**H is the conjugate transpose of U, and D is !! Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, imax, j, jmax, k, kk, kp, kstep real(sp) :: absakk, alpha, colmax, d, d11, d22, r1, rowmax, tt complex(sp) :: d12, d21, t, wk, wkm1, wkp1, zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) .or. stdlib${ii}$_sisnan(absakk) ) then ! column k is or underflow, or contains a nan: ! set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=sp) else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = imax + stdlib${ii}$_icamax( k-imax, a( imax, imax+1 ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_icamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( a( jmax, imax ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( a( imax, imax ),KIND=sp) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, kk - 1 t = conjg( a( j, kk ) ) a( j, kk ) = conjg( a( kp, j ) ) a( kp, j ) = t end do a( kp, kk ) = conjg( a( kp, kk ) ) r1 = real( a( kk, kk ),KIND=sp) a( kk, kk ) = real( a( kp, kp ),KIND=sp) a( kp, kp ) = r1 if( kstep==2_${ik}$ ) then a( k, k ) = real( a( k, k ),KIND=sp) t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if else a( k, k ) = real( a( k, k ),KIND=sp) if( kstep==2_${ik}$ )a( k-1, k-1 ) = real( a( k-1, k-1 ),KIND=sp) end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**h = a - w(k)*1/d(k)*w(k)**h r1 = one / real( a( k, k ),KIND=sp) call stdlib${ii}$_cher( uplo, k-1, -r1, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_csscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**h ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**h if( k>2_${ik}$ ) then d = stdlib${ii}$_slapy2( real( a( k-1, k ),KIND=sp),aimag( a( k-1, k ) ) ) d22 = real( a( k-1, k-1 ),KIND=sp) / d d11 = real( a( k, k ),KIND=sp) / d tt = one / ( d11*d22-one ) d12 = a( k-1, k ) / d d = tt / d do j = k - 2, 1, -1 wkm1 = d*( d11*a( j, k-1 )-conjg( d12 )*a( j, k ) ) wk = d*( d22*a( j, k )-d12*a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - a( i, k )*conjg( wk ) -a( i, k-1 )*conjg( & wkm1 ) end do a( j, k ) = wk a( j, k-1 ) = wkm1 a( j, j ) = cmplx( real( a( j, j ),KIND=sp), zero,KIND=sp) end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 50 continue ! if k > n, exit from loop if( k>n )go to 90 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( a( k, k ),KIND=sp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value jmax = k - 1_${ik}$ + stdlib${ii}$_icamax( imax-k, a( imax, k ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( a( imax, imax ),KIND=sp) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) .or. stdlib${ii}$_disnan(absakk) ) then ! column k is zero or underflow, or contains a nan: ! set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=dp) else ! ============================================================ ! test for interchange if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine only rowmax. jmax = imax + stdlib${ii}$_izamax( k-imax, a( imax, imax+1 ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_izamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( a( jmax, imax ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( a( imax, imax ),KIND=dp) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, kk - 1 t = conjg( a( j, kk ) ) a( j, kk ) = conjg( a( kp, j ) ) a( kp, j ) = t end do a( kp, kk ) = conjg( a( kp, kk ) ) r1 = real( a( kk, kk ),KIND=dp) a( kk, kk ) = real( a( kp, kp ),KIND=dp) a( kp, kp ) = r1 if( kstep==2_${ik}$ ) then a( k, k ) = real( a( k, k ),KIND=dp) t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if else a( k, k ) = real( a( k, k ),KIND=dp) if( kstep==2_${ik}$ )a( k-1, k-1 ) = real( a( k-1, k-1 ),KIND=dp) end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**h = a - w(k)*1/d(k)*w(k)**h r1 = one / real( a( k, k ),KIND=dp) call stdlib${ii}$_zher( uplo, k-1, -r1, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_zdscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**h ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**h if( k>2_${ik}$ ) then d = stdlib${ii}$_dlapy2( real( a( k-1, k ),KIND=dp),aimag( a( k-1, k ) ) ) d22 = real( a( k-1, k-1 ),KIND=dp) / d d11 = real( a( k, k ),KIND=dp) / d tt = one / ( d11*d22-one ) d12 = a( k-1, k ) / d d = tt / d do j = k - 2, 1, -1 wkm1 = d*( d11*a( j, k-1 )-conjg( d12 )*a( j, k ) ) wk = d*( d22*a( j, k )-d12*a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - a( i, k )*conjg( wk ) -a( i, k-1 )*conjg( & wkm1 ) end do a( j, k ) = wk a( j, k-1 ) = wkm1 a( j, j ) = cmplx( real( a( j, j ),KIND=dp), zero,KIND=dp) end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 50 continue ! if k > n, exit from loop if( k>n )go to 90 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( a( k, k ),KIND=dp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine only rowmax. jmax = k - 1_${ik}$ + stdlib${ii}$_izamax( imax-k, a( imax, k ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( a( imax, imax ),KIND=dp) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( (max( absakk, colmax )==zero) .or. stdlib${ii}$_${c2ri(ci)}$isnan(absakk) ) then ! column k is zero or underflow, or contains a nan: ! set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=${ck}$) else ! ============================================================ ! test for interchange if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine only rowmax. jmax = imax + stdlib${ii}$_i${ci}$amax( k-imax, a( imax, imax+1 ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_i${ci}$amax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( a( jmax, imax ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( a( imax, imax ),KIND=${ck}$) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ kk = k - kstep + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, kk - 1 t = conjg( a( j, kk ) ) a( j, kk ) = conjg( a( kp, j ) ) a( kp, j ) = t end do a( kp, kk ) = conjg( a( kp, kk ) ) r1 = real( a( kk, kk ),KIND=${ck}$) a( kk, kk ) = real( a( kp, kp ),KIND=${ck}$) a( kp, kp ) = r1 if( kstep==2_${ik}$ ) then a( k, k ) = real( a( k, k ),KIND=${ck}$) t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if else a( k, k ) = real( a( k, k ),KIND=${ck}$) if( kstep==2_${ik}$ )a( k-1, k-1 ) = real( a( k-1, k-1 ),KIND=${ck}$) end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**h = a - w(k)*1/d(k)*w(k)**h r1 = one / real( a( k, k ),KIND=${ck}$) call stdlib${ii}$_${ci}$her( uplo, k-1, -r1, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_${ci}$dscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**h ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**h if( k>2_${ik}$ ) then d = stdlib${ii}$_${c2ri(ci)}$lapy2( real( a( k-1, k ),KIND=${ck}$),aimag( a( k-1, k ) ) ) d22 = real( a( k-1, k-1 ),KIND=${ck}$) / d d11 = real( a( k, k ),KIND=${ck}$) / d tt = one / ( d11*d22-one ) d12 = a( k-1, k ) / d d = tt / d do j = k - 2, 1, -1 wkm1 = d*( d11*a( j, k-1 )-conjg( d12 )*a( j, k ) ) wk = d*( d22*a( j, k )-d12*a( j, k-1 ) ) do i = j, 1, -1 a( i, j ) = a( i, j ) - a( i, k )*conjg( wk ) -a( i, k-1 )*conjg( & wkm1 ) end do a( j, k ) = wk a( j, k-1 ) = wkm1 a( j, j ) = cmplx( real( a( j, j ),KIND=${ck}$), zero,KIND=${ck}$) end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 50 continue ! if k > n, exit from loop if( k>n )go to 90 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( a( k, k ),KIND=${ck}$) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine only rowmax. jmax = k - 1_${ik}$ + stdlib${ii}$_i${ci}$amax( imax-k, a( imax, k ), lda ) rowmax = cabs1( a( imax, jmax ) ) if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( a( imax, imax ),KIND=${ck}$) )>=alpha*rowmax )then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if ! ============================================================ kk = k + kstep - 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_cgeru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. s = real( cone,KIND=sp) / real( a( k, k ),KIND=sp) call stdlib${ii}$_csscal( nrhs, s, b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_cswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_cgeru( k-2, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) call stdlib${ii}$_cgeru( k-2, nrhs, -cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / conjg( akm1k ) b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**h *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**h(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ ) then call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) end if ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**h(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k+1 )& , 1_${ik}$, cone, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**h. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**h(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_zgeru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. s = real( cone,KIND=dp) / real( a( k, k ),KIND=dp) call stdlib${ii}$_zdscal( nrhs, s, b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_zswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_zgeru( k-2, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) call stdlib${ii}$_zgeru( k-2, nrhs, -cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / conjg( akm1k ) b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**h *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**h(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ ) then call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) end if ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**h(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k+1 )& , 1_${ik}$, cone, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**h. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**h(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ci}$geru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. s = real( cone,KIND=${ck}$) / real( a( k, k ),KIND=${ck}$) call stdlib${ii}$_${ci}$dscal( nrhs, s, b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_${ci}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_${ci}$geru( k-2, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) call stdlib${ii}$_${ci}$geru( k-2, nrhs, -cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / conjg( akm1k ) b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**h *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**h(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) end if ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**h(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k+1 )& , 1_${ik}$, cone, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**h. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**h(k)), where l(k) is the transformation ! stored in column k of a. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=sp) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_chemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_cdotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=sp) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = real( a( k, k ),KIND=sp) / t akp1 = real( a( k+1, k+1 ),KIND=sp) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_chemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_cdotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=sp) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_cdotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_chemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -real( stdlib${ii}$_cdotc( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ),& 1_${ik}$ ),KIND=sp) end if kstep = 2_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp if( kstep==2_${ik}$ ) then temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if end if k = k + kstep go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=sp) ! compute column k of the inverse. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=dp) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zhemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_zdotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=dp) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = real( a( k, k ),KIND=dp) / t akp1 = real( a( k+1, k+1 ),KIND=dp) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zhemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_zdotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=dp) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_zdotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zhemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -real( stdlib${ii}$_zdotc( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ),& 1_${ik}$ ),KIND=dp) end if kstep = 2_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp if( kstep==2_${ik}$ ) then temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if end if k = k + kstep go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=dp) ! compute column k of the inverse. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=${ck}$) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$hemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_${ci}$dotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=${ck}$) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = real( a( k, k ),KIND=${ck}$) / t akp1 = real( a( k+1, k+1 ),KIND=${ck}$) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$hemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_${ci}$dotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=${ck}$) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_${ci}$dotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$hemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -real( stdlib${ii}$_${ci}$dotc( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ),& 1_${ik}$ ),KIND=${ck}$) end if kstep = 2_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp if( kstep==2_${ik}$ ) then temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if end if k = k + kstep go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=${ck}$) ! compute column k of the inverse. if( ksafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_chetrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) call stdlib${ii}$_caxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_chetrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_chetrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_cherfs pure module subroutine stdlib${ii}$_zherfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! ZHERFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian indefinite, and !! provides error bounds and backward error estimates for the solution. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_zhetrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) call stdlib${ii}$_zaxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_zhetrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_zhetrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_zherfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$herfs( uplo, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! ZHERFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian indefinite, and !! provides error bounds and backward error estimates for the solution. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ci}$hetrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) call stdlib${ii}$_${ci}$axpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_${ci}$hetrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$hetrs( uplo, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ci}$herfs #:endif #:endfor pure module subroutine stdlib${ii}$_cheequb( uplo, n, a, lda, s, scond, amax, work, info ) !! CHEEQUB computes row and column scalings intended to equilibrate a !! Hermitian matrix A (with respect to the Euclidean norm) and reduce !! its condition number. The scale factors S are computed by the BIN !! algorithm (see references) so that the scaled matrix B with elements !! B(i,j) = S(i)*A(i,j)*S(j) has a condition number within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(sp), intent(out) :: amax, scond character, intent(in) :: uplo ! Array Arguments complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) real(sp), intent(out) :: s(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: max_iter = 100_${ik}$ ! Local Scalars integer(${ik}$) :: i, j, iter real(sp) :: avg, std, tol, c0, c1, c2, t, u, si, d, base, smin, smax, smlnum, bignum, & scale, sumsq logical(lk) :: up complex(sp) :: zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not. ( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) ) then info = -1_${ik}$ else if ( n < 0_${ik}$ ) then info = -2_${ik}$ else if ( lda < max( 1_${ik}$, n ) ) then info = -4_${ik}$ end if if ( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHEEQUB', -info ) return end if up = stdlib_lsame( uplo, 'U' ) amax = zero ! quick return if possible. if ( n == 0_${ik}$ ) then scond = one return end if do i = 1, n s( i ) = zero end do amax = zero if ( up ) then do j = 1, n do i = 1, j-1 s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) end do else do j = 1, n s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) do i = j+1, n s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do end do end if do j = 1, n s( j ) = one / s( j ) end do tol = one / sqrt( two * n ) do iter = 1, max_iter scale = zero sumsq = zero ! beta = |a|s do i = 1, n work( i ) = zero end do if ( up ) then do j = 1, n do i = 1, j-1 work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) end do else do j = 1, n work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) do i = j+1, n work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do end do end if ! avg = s^t beta / n avg = zero do i = 1, n avg = avg + real( s( i )*work( i ),KIND=sp) end do avg = avg / n std = zero do i = n+1, 2*n work( i ) = s( i-n ) * work( i-n ) - avg end do call stdlib${ii}$_classq( n, work( n+1 ), 1_${ik}$, scale, sumsq ) std = scale * sqrt( sumsq / n ) if ( std < tol * avg ) goto 999 do i = 1, n t = cabs1( a( i, i ) ) si = s( i ) c2 = ( n-1 ) * t c1 = real( ( n-2 ) * ( work( i ) - t*si ),KIND=sp) c0 = real( -(t*si)*si + 2_${ik}$*work( i )*si - n*avg,KIND=sp) d = c1*c1 - 4_${ik}$*c0*c2 if ( d <= 0_${ik}$ ) then info = -1_${ik}$ return end if si = -2_${ik}$*c0 / ( c1 + sqrt( d ) ) d = si - s( i ) u = zero if ( up ) then do j = 1, i t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do else do j = 1, i t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do end if avg = avg + real( ( u + work( i ) ) * d / n,KIND=sp) s( i ) = si end do end do 999 continue smlnum = stdlib${ii}$_slamch( 'SAFEMIN' ) bignum = one / smlnum smin = bignum smax = zero t = one / sqrt( avg ) base = stdlib${ii}$_slamch( 'B' ) u = one / log( base ) do i = 1, n s( i ) = base ** int( u * log( s( i ) * t ),KIND=${ik}$) smin = min( smin, s( i ) ) smax = max( smax, s( i ) ) end do scond = max( smin, smlnum ) / min( smax, bignum ) end subroutine stdlib${ii}$_cheequb pure module subroutine stdlib${ii}$_zheequb( uplo, n, a, lda, s, scond, amax, work, info ) !! ZHEEQUB computes row and column scalings intended to equilibrate a !! Hermitian matrix A (with respect to the Euclidean norm) and reduce !! its condition number. The scale factors S are computed by the BIN !! algorithm (see references) so that the scaled matrix B with elements !! B(i,j) = S(i)*A(i,j)*S(j) has a condition number within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(dp), intent(out) :: amax, scond character, intent(in) :: uplo ! Array Arguments complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) real(dp), intent(out) :: s(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: max_iter = 100_${ik}$ ! Local Scalars integer(${ik}$) :: i, j, iter real(dp) :: avg, std, tol, c0, c1, c2, t, u, si, d, base, smin, smax, smlnum, bignum, & scale, sumsq logical(lk) :: up complex(dp) :: zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not. ( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) ) then info = -1_${ik}$ else if ( n < 0_${ik}$ ) then info = -2_${ik}$ else if ( lda < max( 1_${ik}$, n ) ) then info = -4_${ik}$ end if if ( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHEEQUB', -info ) return end if up = stdlib_lsame( uplo, 'U' ) amax = zero ! quick return if possible. if ( n == 0_${ik}$ ) then scond = one return end if do i = 1, n s( i ) = zero end do amax = zero if ( up ) then do j = 1, n do i = 1, j-1 s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) end do else do j = 1, n s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) do i = j+1, n s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do end do end if do j = 1, n s( j ) = one / s( j ) end do tol = one / sqrt( two * n ) do iter = 1, max_iter scale = zero sumsq = zero ! beta = |a|s do i = 1, n work( i ) = zero end do if ( up ) then do j = 1, n do i = 1, j-1 work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) end do else do j = 1, n work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) do i = j+1, n work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do end do end if ! avg = s^t beta / n avg = zero do i = 1, n avg = avg + real( s( i )*work( i ),KIND=dp) end do avg = avg / n std = zero do i = n+1, 2*n work( i ) = s( i-n ) * work( i-n ) - avg end do call stdlib${ii}$_zlassq( n, work( n+1 ), 1_${ik}$, scale, sumsq ) std = scale * sqrt( sumsq / n ) if ( std < tol * avg ) goto 999 do i = 1, n t = cabs1( a( i, i ) ) si = s( i ) c2 = ( n-1 ) * t c1 = ( n-2 ) * ( real( work( i ),KIND=dp) - t*si ) c0 = -(t*si)*si + 2_${ik}$ * real( work( i ),KIND=dp) * si - n*avg d = c1*c1 - 4_${ik}$*c0*c2 if ( d <= 0_${ik}$ ) then info = -1_${ik}$ return end if si = -2_${ik}$*c0 / ( c1 + sqrt( d ) ) d = si - s( i ) u = zero if ( up ) then do j = 1, i t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do else do j = 1, i t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do end if avg = avg + ( u + real( work( i ),KIND=dp) ) * d / n s( i ) = si end do end do 999 continue smlnum = stdlib${ii}$_dlamch( 'SAFEMIN' ) bignum = one / smlnum smin = bignum smax = zero t = one / sqrt( avg ) base = stdlib${ii}$_dlamch( 'B' ) u = one / log( base ) do i = 1, n s( i ) = base ** int( u * log( s( i ) * t ),KIND=${ik}$) smin = min( smin, s( i ) ) smax = max( smax, s( i ) ) end do scond = max( smin, smlnum ) / min( smax, bignum ) end subroutine stdlib${ii}$_zheequb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$heequb( uplo, n, a, lda, s, scond, amax, work, info ) !! ZHEEQUB: computes row and column scalings intended to equilibrate a !! Hermitian matrix A (with respect to the Euclidean norm) and reduce !! its condition number. The scale factors S are computed by the BIN !! algorithm (see references) so that the scaled matrix B with elements !! B(i,j) = S(i)*A(i,j)*S(j) has a condition number within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(out) :: amax, scond character, intent(in) :: uplo ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) real(${ck}$), intent(out) :: s(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: max_iter = 100_${ik}$ ! Local Scalars integer(${ik}$) :: i, j, iter real(${ck}$) :: avg, std, tol, c0, c1, c2, t, u, si, d, base, smin, smax, smlnum, bignum, & scale, sumsq logical(lk) :: up complex(${ck}$) :: zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not. ( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) ) then info = -1_${ik}$ else if ( n < 0_${ik}$ ) then info = -2_${ik}$ else if ( lda < max( 1_${ik}$, n ) ) then info = -4_${ik}$ end if if ( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHEEQUB', -info ) return end if up = stdlib_lsame( uplo, 'U' ) amax = zero ! quick return if possible. if ( n == 0_${ik}$ ) then scond = one return end if do i = 1, n s( i ) = zero end do amax = zero if ( up ) then do j = 1, n do i = 1, j-1 s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) end do else do j = 1, n s( j ) = max( s( j ), cabs1( a( j, j ) ) ) amax = max( amax, cabs1( a( j, j ) ) ) do i = j+1, n s( i ) = max( s( i ), cabs1( a( i, j ) ) ) s( j ) = max( s( j ), cabs1( a( i, j ) ) ) amax = max( amax, cabs1( a( i, j ) ) ) end do end do end if do j = 1, n s( j ) = one / s( j ) end do tol = one / sqrt( two * n ) do iter = 1, max_iter scale = zero sumsq = zero ! beta = |a|s do i = 1, n work( i ) = zero end do if ( up ) then do j = 1, n do i = 1, j-1 work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) end do else do j = 1, n work( j ) = work( j ) + cabs1( a( j, j ) ) * s( j ) do i = j+1, n work( i ) = work( i ) + cabs1( a( i, j ) ) * s( j ) work( j ) = work( j ) + cabs1( a( i, j ) ) * s( i ) end do end do end if ! avg = s^t beta / n avg = zero do i = 1, n avg = avg + real( s( i )*work( i ),KIND=${ck}$) end do avg = avg / n std = zero do i = n+1, 2*n work( i ) = s( i-n ) * work( i-n ) - avg end do call stdlib${ii}$_${ci}$lassq( n, work( n+1 ), 1_${ik}$, scale, sumsq ) std = scale * sqrt( sumsq / n ) if ( std < tol * avg ) goto 999 do i = 1, n t = cabs1( a( i, i ) ) si = s( i ) c2 = ( n-1 ) * t c1 = ( n-2 ) * ( real( work( i ),KIND=${ck}$) - t*si ) c0 = -(t*si)*si + 2_${ik}$ * real( work( i ),KIND=${ck}$) * si - n*avg d = c1*c1 - 4_${ik}$*c0*c2 if ( d <= 0_${ik}$ ) then info = -1_${ik}$ return end if si = -2_${ik}$*c0 / ( c1 + sqrt( d ) ) d = si - s( i ) u = zero if ( up ) then do j = 1, i t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do else do j = 1, i t = cabs1( a( i, j ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do do j = i+1,n t = cabs1( a( j, i ) ) u = u + s( j )*t work( j ) = work( j ) + d*t end do end if avg = avg + ( u + real( work( i ),KIND=${ck}$) ) * d / n s( i ) = si end do end do 999 continue smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFEMIN' ) bignum = one / smlnum smin = bignum smax = zero t = one / sqrt( avg ) base = stdlib${ii}$_${c2ri(ci)}$lamch( 'B' ) u = one / log( base ) do i = 1, n s( i ) = base ** int( u * log( s( i ) * t ),KIND=${ik}$) smin = min( smin, s( i ) ) smax = max( smax, s( i ) ) end do scond = max( smin, smlnum ) / min( smax, bignum ) end subroutine stdlib${ii}$_${ci}$heequb #:endif #:endfor pure module subroutine stdlib${ii}$_chetrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) !! CHETRS2 solves a system of linear equations A*X = B with a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHETRF and converted by CSYCONV. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, j, k, kp real(sp) :: s complex(sp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp==-ipiv( k-1 ) )call stdlib${ii}$_cswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb & ) k=k-2 end if end do ! compute (u \p**t * b) -> b [ (u \p**t * b) ] call stdlib${ii}$_ctrsm('L','U','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (u \p**t * b) ] i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then s = real( cone,KIND=sp) / real( a( i, i ),KIND=sp) call stdlib${ii}$_csscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) elseif ( i > 1_${ik}$) then if ( ipiv(i-1) == ipiv(i) ) then akm1k = work(i) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / conjg( akm1k ) b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ endif endif i = i - 1_${ik}$ end do ! compute (u**h \ b) -> b [ u**h \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_ctrsm('L','U','C','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (u**h \ (d \ (u \p**t * b) )) ] k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k < n .and. kp==-ipiv( k+1 ) )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp,& 1_${ik}$ ), ldb ) k=k+2 endif end do else ! solve a*x = b, where a = l*d*l**h. ! p**t * b k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k+1). kp = -ipiv( k+1 ) if( kp==-ipiv( k ) )call stdlib${ii}$_cswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+2 endif end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_ctrsm('L','L','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (l \p**t * b) ] i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then s = real( cone,KIND=sp) / real( a( i, i ),KIND=sp) call stdlib${ii}$_csscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) else akm1k = work(i) akm1 = a( i, i ) / conjg( akm1k ) ak = a( i+1, i+1 ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i, j ) / conjg( akm1k ) bk = b( i+1, j ) / akm1k b( i, j ) = ( ak*bkm1-bk ) / denom b( i+1, j ) = ( akm1*bk-bkm1 ) / denom end do i = i + 1_${ik}$ endif i = i + 1_${ik}$ end do ! compute (l**h \ b) -> b [ l**h \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_ctrsm('L','L','C','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (l**h \ (d \ (l \p**t * b) )) ] k=n do while ( k >= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k>1_${ik}$ .and. kp==-ipiv( k-1 ) )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, & 1_${ik}$ ), ldb ) k=k-2 endif end do end if ! revert a call stdlib${ii}$_csyconv( uplo, 'R', n, a, lda, ipiv, work, iinfo ) return end subroutine stdlib${ii}$_chetrs2 pure module subroutine stdlib${ii}$_zhetrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) !! ZHETRS2 solves a system of linear equations A*X = B with a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by ZHETRF and converted by ZSYCONV. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, j, k, kp real(dp) :: s complex(dp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp==-ipiv( k-1 ) )call stdlib${ii}$_zswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb & ) k=k-2 end if end do ! compute (u \p**t * b) -> b [ (u \p**t * b) ] call stdlib${ii}$_ztrsm('L','U','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (u \p**t * b) ] i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then s = real( cone,KIND=dp) / real( a( i, i ),KIND=dp) call stdlib${ii}$_zdscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) elseif ( i > 1_${ik}$) then if ( ipiv(i-1) == ipiv(i) ) then akm1k = work(i) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / conjg( akm1k ) b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ endif endif i = i - 1_${ik}$ end do ! compute (u**h \ b) -> b [ u**h \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_ztrsm('L','U','C','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (u**h \ (d \ (u \p**t * b) )) ] k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k < n .and. kp==-ipiv( k+1 ) )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp,& 1_${ik}$ ), ldb ) k=k+2 endif end do else ! solve a*x = b, where a = l*d*l**h. ! p**t * b k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k+1). kp = -ipiv( k+1 ) if( kp==-ipiv( k ) )call stdlib${ii}$_zswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+2 endif end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_ztrsm('L','L','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (l \p**t * b) ] i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then s = real( cone,KIND=dp) / real( a( i, i ),KIND=dp) call stdlib${ii}$_zdscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) else akm1k = work(i) akm1 = a( i, i ) / conjg( akm1k ) ak = a( i+1, i+1 ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i, j ) / conjg( akm1k ) bk = b( i+1, j ) / akm1k b( i, j ) = ( ak*bkm1-bk ) / denom b( i+1, j ) = ( akm1*bk-bkm1 ) / denom end do i = i + 1_${ik}$ endif i = i + 1_${ik}$ end do ! compute (l**h \ b) -> b [ l**h \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_ztrsm('L','L','C','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (l**h \ (d \ (l \p**t * b) )) ] k=n do while ( k >= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k>1_${ik}$ .and. kp==-ipiv( k-1 ) )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, & 1_${ik}$ ), ldb ) k=k-2 endif end do end if ! revert a call stdlib${ii}$_zsyconv( uplo, 'R', n, a, lda, ipiv, work, iinfo ) return end subroutine stdlib${ii}$_zhetrs2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hetrs2( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, info ) !! ZHETRS2: solves a system of linear equations A*X = B with a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by ZHETRF and converted by ZSYCONV. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, j, k, kp real(${ck}$) :: s complex(${ck}$) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp==-ipiv( k-1 ) )call stdlib${ii}$_${ci}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb & ) k=k-2 end if end do ! compute (u \p**t * b) -> b [ (u \p**t * b) ] call stdlib${ii}$_${ci}$trsm('L','U','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (u \p**t * b) ] i=n do while ( i >= 1 ) if( ipiv(i) > 0_${ik}$ ) then s = real( cone,KIND=${ck}$) / real( a( i, i ),KIND=${ck}$) call stdlib${ii}$_${ci}$dscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) elseif ( i > 1_${ik}$) then if ( ipiv(i-1) == ipiv(i) ) then akm1k = work(i) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / conjg( akm1k ) b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ endif endif i = i - 1_${ik}$ end do ! compute (u**h \ b) -> b [ u**h \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm('L','U','C','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (u**h \ (d \ (u \p**t * b) )) ] k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k < n .and. kp==-ipiv( k+1 ) )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp,& 1_${ik}$ ), ldb ) k=k+2 endif end do else ! solve a*x = b, where a = l*d*l**h. ! p**t * b k=1_${ik}$ do while ( k <= n ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+1 else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k+1). kp = -ipiv( k+1 ) if( kp==-ipiv( k ) )call stdlib${ii}$_${ci}$swap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k+2 endif end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_${ci}$trsm('L','L','N','U',n,nrhs,cone,a,lda,b,ldb) ! compute d \ b -> b [ d \ (l \p**t * b) ] i=1_${ik}$ do while ( i <= n ) if( ipiv(i) > 0_${ik}$ ) then s = real( cone,KIND=${ck}$) / real( a( i, i ),KIND=${ck}$) call stdlib${ii}$_${ci}$dscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) else akm1k = work(i) akm1 = a( i, i ) / conjg( akm1k ) ak = a( i+1, i+1 ) / akm1k denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i, j ) / conjg( akm1k ) bk = b( i+1, j ) / akm1k b( i, j ) = ( ak*bkm1-bk ) / denom b( i+1, j ) = ( akm1*bk-bkm1 ) / denom end do i = i + 1_${ik}$ endif i = i + 1_${ik}$ end do ! compute (l**h \ b) -> b [ l**h \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm('L','L','C','U',n,nrhs,cone,a,lda,b,ldb) ! p * b [ p * (l**h \ (d \ (l \p**t * b) )) ] k=n do while ( k >= 1 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k=k-1 else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( k>1_${ik}$ .and. kp==-ipiv( k-1 ) )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, & 1_${ik}$ ), ldb ) k=k-2 endif end do end if ! revert a call stdlib${ii}$_${ci}$syconv( uplo, 'R', n, a, lda, ipiv, work, iinfo ) return end subroutine stdlib${ii}$_${ci}$hetrs2 #:endif #:endfor pure module subroutine stdlib${ii}$_chetrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) !! CHETRS_3 solves a system of linear equations A * X = B with a complex !! Hermitian matrix A using the factorization computed !! by CHETRF_RK or CHETRF_BK: !! A = P*U*D*(U**H)*(P**T) or A = P*L*D*(L**H)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**H (or L**H) is the conjugate of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is Hermitian and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This algorithm is using Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: a(lda,*), e(*) complex(sp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, j, k, kp real(sp) :: s complex(sp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda b [ (u \p**t * b) ] call stdlib${ii}$_ctrsm( 'L', 'U', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (u \p**t * b) ] i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then s = real( cone,KIND=sp) / real( a( i, i ),KIND=sp) call stdlib${ii}$_csscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) else if ( i>1_${ik}$ ) then akm1k = e( i ) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / conjg( akm1k ) b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! compute (u**h \ b) -> b [ u**h \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_ctrsm( 'L', 'U', 'C', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (u**h \ (d \ (u \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for upper case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do else ! begin lower ! solve a*x = b, where a = l*d*l**h. ! p**t * b ! interchange rows k and ipiv(k) of matrix b in the same order ! that the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_ctrsm( 'L', 'L', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (l \p**t * b) ] i = 1_${ik}$ do while ( i<=n ) if( ipiv( i )>0_${ik}$ ) then s = real( cone,KIND=sp) / real( a( i, i ),KIND=sp) call stdlib${ii}$_csscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) else if( i b [ l**h \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_ctrsm('L', 'L', 'C', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (l**h \ (d \ (l \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = n, 1, -1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! end lower end if return end subroutine stdlib${ii}$_chetrs_3 pure module subroutine stdlib${ii}$_zhetrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) !! ZHETRS_3 solves a system of linear equations A * X = B with a complex !! Hermitian matrix A using the factorization computed !! by ZHETRF_RK or ZHETRF_BK: !! A = P*U*D*(U**H)*(P**T) or A = P*L*D*(L**H)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**H (or L**H) is the conjugate of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is Hermitian and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This algorithm is using Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*), e(*) complex(dp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, j, k, kp real(dp) :: s complex(dp) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda b [ (u \p**t * b) ] call stdlib${ii}$_ztrsm( 'L', 'U', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (u \p**t * b) ] i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then s = real( cone,KIND=dp) / real( a( i, i ),KIND=dp) call stdlib${ii}$_zdscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) else if ( i>1_${ik}$ ) then akm1k = e( i ) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / conjg( akm1k ) b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! compute (u**h \ b) -> b [ u**h \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_ztrsm( 'L', 'U', 'C', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (u**h \ (d \ (u \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for upper case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do else ! begin lower ! solve a*x = b, where a = l*d*l**h. ! p**t * b ! interchange rows k and ipiv(k) of matrix b in the same order ! that the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_ztrsm( 'L', 'L', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (l \p**t * b) ] i = 1_${ik}$ do while ( i<=n ) if( ipiv( i )>0_${ik}$ ) then s = real( cone,KIND=dp) / real( a( i, i ),KIND=dp) call stdlib${ii}$_zdscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) else if( i b [ l**h \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_ztrsm('L', 'L', 'C', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (l**h \ (d \ (l \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = n, 1, -1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! end lower end if return end subroutine stdlib${ii}$_zhetrs_3 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hetrs_3( uplo, n, nrhs, a, lda, e, ipiv, b, ldb,info ) !! ZHETRS_3: solves a system of linear equations A * X = B with a complex !! Hermitian matrix A using the factorization computed !! by ZHETRF_RK or ZHETRF_BK: !! A = P*U*D*(U**H)*(P**T) or A = P*L*D*(L**H)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**H (or L**H) is the conjugate of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is Hermitian and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This algorithm is using Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*), e(*) complex(${ck}$), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, j, k, kp real(${ck}$) :: s complex(${ck}$) :: ak, akm1, akm1k, bk, bkm1, denom ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda b [ (u \p**t * b) ] call stdlib${ii}$_${ci}$trsm( 'L', 'U', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (u \p**t * b) ] i = n do while ( i>=1 ) if( ipiv( i )>0_${ik}$ ) then s = real( cone,KIND=${ck}$) / real( a( i, i ),KIND=${ck}$) call stdlib${ii}$_${ci}$dscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) else if ( i>1_${ik}$ ) then akm1k = e( i ) akm1 = a( i-1, i-1 ) / akm1k ak = a( i, i ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( i-1, j ) / akm1k bk = b( i, j ) / conjg( akm1k ) b( i-1, j ) = ( ak*bkm1-bk ) / denom b( i, j ) = ( akm1*bk-bkm1 ) / denom end do i = i - 1_${ik}$ end if i = i - 1_${ik}$ end do ! compute (u**h \ b) -> b [ u**h \ (d \ (u \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm( 'L', 'U', 'C', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (u**h \ (d \ (u \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for upper case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do else ! begin lower ! solve a*x = b, where a = l*d*l**h. ! p**t * b ! interchange rows k and ipiv(k) of matrix b in the same order ! that the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = 1, n, 1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! compute (l \p**t * b) -> b [ (l \p**t * b) ] call stdlib${ii}$_${ci}$trsm( 'L', 'L', 'N', 'U', n, nrhs, cone, a, lda, b, ldb ) ! compute d \ b -> b [ d \ (l \p**t * b) ] i = 1_${ik}$ do while ( i<=n ) if( ipiv( i )>0_${ik}$ ) then s = real( cone,KIND=${ck}$) / real( a( i, i ),KIND=${ck}$) call stdlib${ii}$_${ci}$dscal( nrhs, s, b( i, 1_${ik}$ ), ldb ) else if( i b [ l**h \ (d \ (l \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm('L', 'L', 'C', 'U', n, nrhs, cone, a, lda, b, ldb ) ! p * b [ p * (l**h \ (d \ (l \p**t * b) )) ] ! interchange rows k and ipiv(k) of matrix b in reverse order ! from the formation order of ipiv(i) vector for lower case. ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv(i) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) do k = n, 1, -1 kp = abs( ipiv( k ) ) if( kp/=k ) then call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end if end do ! end lower end if return end subroutine stdlib${ii}$_${ci}$hetrs_3 #:endif #:endfor pure module subroutine stdlib${ii}$_cheswapr( uplo, n, a, lda, i1, i2) !! CHESWAPR applies an elementary permutation on the rows and the columns of !! a hermitian matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1, i2, lda, n ! Array Arguments complex(sp), intent(inout) :: a(lda,n) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i complex(sp) :: tmp ! Executable Statements upper = stdlib_lsame( uplo, 'U' ) if (upper) then ! upper ! first swap ! - swap column i1 and i2 from i1 to i1-1 call stdlib${ii}$_cswap( i1-1, a(1_${ik}$,i1), 1_${ik}$, a(1_${ik}$,i2), 1_${ik}$ ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap row i1 from i1+1 to i2-1 with col i2 from i1+1 to i2-1 ! - swap a(i2,i1) and a(i1,i2) tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1,i1+i) a(i1,i1+i)=conjg(a(i1+i,i2)) a(i1+i,i2)=conjg(tmp) end do a(i1,i2)=conjg(a(i1,i2)) ! third swap ! - swap row i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i1,i) a(i1,i)=a(i2,i) a(i2,i)=tmp end do else ! lower ! first swap ! - swap row i1 and i2 from 1 to i1-1 call stdlib${ii}$_cswap ( i1-1, a(i1,1_${ik}$), lda, a(i2,1_${ik}$), lda ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap col i1 from i1+1 to i2-1 with row i2 from i1+1 to i2-1 ! - swap a(i2,i1) and a(i1,i2) tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1+i,i1) a(i1+i,i1)=conjg(a(i2,i1+i)) a(i2,i1+i)=conjg(tmp) end do a(i2,i1)=conjg(a(i2,i1)) ! third swap ! - swap col i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i,i1) a(i,i1)=a(i,i2) a(i,i2)=tmp end do endif end subroutine stdlib${ii}$_cheswapr pure module subroutine stdlib${ii}$_zheswapr( uplo, n, a, lda, i1, i2) !! ZHESWAPR applies an elementary permutation on the rows and the columns of !! a hermitian matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1, i2, lda, n ! Array Arguments complex(dp), intent(inout) :: a(lda,n) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i complex(dp) :: tmp ! Executable Statements upper = stdlib_lsame( uplo, 'U' ) if (upper) then ! upper ! first swap ! - swap column i1 and i2 from i1 to i1-1 call stdlib${ii}$_zswap( i1-1, a(1_${ik}$,i1), 1_${ik}$, a(1_${ik}$,i2), 1_${ik}$ ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap row i1 from i1+1 to i2-1 with col i2 from i1+1 to i2-1 ! - swap a(i2,i1) and a(i1,i2) tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1,i1+i) a(i1,i1+i)=conjg(a(i1+i,i2)) a(i1+i,i2)=conjg(tmp) end do a(i1,i2)=conjg(a(i1,i2)) ! third swap ! - swap row i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i1,i) a(i1,i)=a(i2,i) a(i2,i)=tmp end do else ! lower ! first swap ! - swap row i1 and i2 from 1 to i1-1 call stdlib${ii}$_zswap ( i1-1, a(i1,1_${ik}$), lda, a(i2,1_${ik}$), lda ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap col i1 from i1+1 to i2-1 with row i2 from i1+1 to i2-1 ! - swap a(i2,i1) and a(i1,i2) tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1+i,i1) a(i1+i,i1)=conjg(a(i2,i1+i)) a(i2,i1+i)=conjg(tmp) end do a(i2,i1)=conjg(a(i2,i1)) ! third swap ! - swap col i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i,i1) a(i,i1)=a(i,i2) a(i,i2)=tmp end do endif end subroutine stdlib${ii}$_zheswapr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$heswapr( uplo, n, a, lda, i1, i2) !! ZHESWAPR: applies an elementary permutation on the rows and the columns of !! a hermitian matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: i1, i2, lda, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,n) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i complex(${ck}$) :: tmp ! Executable Statements upper = stdlib_lsame( uplo, 'U' ) if (upper) then ! upper ! first swap ! - swap column i1 and i2 from i1 to i1-1 call stdlib${ii}$_${ci}$swap( i1-1, a(1_${ik}$,i1), 1_${ik}$, a(1_${ik}$,i2), 1_${ik}$ ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap row i1 from i1+1 to i2-1 with col i2 from i1+1 to i2-1 ! - swap a(i2,i1) and a(i1,i2) tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1,i1+i) a(i1,i1+i)=conjg(a(i1+i,i2)) a(i1+i,i2)=conjg(tmp) end do a(i1,i2)=conjg(a(i1,i2)) ! third swap ! - swap row i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i1,i) a(i1,i)=a(i2,i) a(i2,i)=tmp end do else ! lower ! first swap ! - swap row i1 and i2 from 1 to i1-1 call stdlib${ii}$_${ci}$swap ( i1-1, a(i1,1_${ik}$), lda, a(i2,1_${ik}$), lda ) ! second swap : ! - swap a(i1,i1) and a(i2,i2) ! - swap col i1 from i1+1 to i2-1 with row i2 from i1+1 to i2-1 ! - swap a(i2,i1) and a(i1,i2) tmp=a(i1,i1) a(i1,i1)=a(i2,i2) a(i2,i2)=tmp do i=1,i2-i1-1 tmp=a(i1+i,i1) a(i1+i,i1)=conjg(a(i2,i1+i)) a(i2,i1+i)=conjg(tmp) end do a(i2,i1)=conjg(a(i2,i1)) ! third swap ! - swap col i1 and i2 from i2+1 to n do i=i2+1,n tmp=a(i,i1) a(i,i1)=a(i,i2) a(i,i2)=tmp end do endif end subroutine stdlib${ii}$_${ci}$heswapr #:endif #:endfor pure module subroutine stdlib${ii}$_chpcon( uplo, n, ap, ipiv, anorm, rcond, work, info ) !! CHPCON estimates the reciprocal of the condition number of a complex !! Hermitian packed matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: ap(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ip, kase real(sp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( anorm0 .and. ap( ip )==zero )return ip = ip - i end do else ! lower triangular storage: examine d from top to bottom. ip = 1_${ik}$ do i = 1, n if( ipiv( i )>0 .and. ap( ip )==zero )return ip = ip + n - i + 1_${ik}$ end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**h) or inv(u*d*u**h). call stdlib${ii}$_chptrs( uplo, n, 1_${ik}$, ap, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_chpcon pure module subroutine stdlib${ii}$_zhpcon( uplo, n, ap, ipiv, anorm, rcond, work, info ) !! ZHPCON estimates the reciprocal of the condition number of a complex !! Hermitian packed matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by ZHPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: ap(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ip, kase real(dp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( anorm0 .and. ap( ip )==zero )return ip = ip - i end do else ! lower triangular storage: examine d from top to bottom. ip = 1_${ik}$ do i = 1, n if( ipiv( i )>0 .and. ap( ip )==zero )return ip = ip + n - i + 1_${ik}$ end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**h) or inv(u*d*u**h). call stdlib${ii}$_zhptrs( uplo, n, 1_${ik}$, ap, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_zhpcon #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hpcon( uplo, n, ap, ipiv, anorm, rcond, work, info ) !! ZHPCON: estimates the reciprocal of the condition number of a complex !! Hermitian packed matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by ZHPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(${ck}$), intent(in) :: anorm real(${ck}$), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: ap(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ip, kase real(${ck}$) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( anorm0 .and. ap( ip )==zero )return ip = ip - i end do else ! lower triangular storage: examine d from top to bottom. ip = 1_${ik}$ do i = 1, n if( ipiv( i )>0 .and. ap( ip )==zero )return ip = ip + n - i + 1_${ik}$ end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**h) or inv(u*d*u**h). call stdlib${ii}$_${ci}$hptrs( uplo, n, 1_${ik}$, ap, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_${ci}$hpcon #:endif #:endfor pure module subroutine stdlib${ii}$_chptrf( uplo, n, ap, ipiv, info ) !! CHPTRF computes the factorization of a complex Hermitian packed !! matrix A using the Bunch-Kaufman diagonal pivoting method: !! A = U*D*U**H or A = L*D*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: ap(*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, imax, j, jmax, k, kc, kk, knc, kp, kpc, kstep, kx, npp real(sp) :: absakk, alpha, colmax, d, d11, d22, r1, rowmax, tt complex(sp) :: d12, d21, t, wk, wkm1, wkp1, zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHPTRF', -info ) return end if ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight if( upper ) then ! factorize a as u*d*u**h using the upper triangle of a ! k is the main loop index, decreasing from n to 1 in steps of ! 1 or 2 k = n kc = ( n-1 )*n / 2_${ik}$ + 1_${ik}$ 10 continue knc = kc ! if k < 1, exit from loop if( k<1 )go to 110 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( ap( kc+k-1 ),KIND=sp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value if( k>1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, ap( kc ), 1_${ik}$ ) colmax = cabs1( ap( kc+imax-1 ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero: set info and continue if( info==0_${ik}$ )info = k kp = k ap( kc+k-1 ) = real( ap( kc+k-1 ),KIND=sp) else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero jmax = imax kx = imax*( imax+1 ) / 2_${ik}$ + imax do j = imax + 1, k if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + j end do kpc = ( imax-1 )*imax / 2_${ik}$ + 1_${ik}$ if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_icamax( imax-1, ap( kpc ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( ap( kpc+jmax-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( ap( kpc+imax-1 ),KIND=sp) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kstep==2_${ik}$ )knc = knc - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_cswap( kp-1, ap( knc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, kk - 1 kx = kx + j - 1_${ik}$ t = conjg( ap( knc+j-1 ) ) ap( knc+j-1 ) = conjg( ap( kx ) ) ap( kx ) = t end do ap( kx+kk-1 ) = conjg( ap( kx+kk-1 ) ) r1 = real( ap( knc+kk-1 ),KIND=sp) ap( knc+kk-1 ) = real( ap( kpc+kp-1 ),KIND=sp) ap( kpc+kp-1 ) = r1 if( kstep==2_${ik}$ ) then ap( kc+k-1 ) = real( ap( kc+k-1 ),KIND=sp) t = ap( kc+k-2 ) ap( kc+k-2 ) = ap( kc+kp-1 ) ap( kc+kp-1 ) = t end if else ap( kc+k-1 ) = real( ap( kc+k-1 ),KIND=sp) if( kstep==2_${ik}$ )ap( kc-1 ) = real( ap( kc-1 ),KIND=sp) end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**h = a - w(k)*1/d(k)*w(k)**h r1 = one / real( ap( kc+k-1 ),KIND=sp) call stdlib${ii}$_chpr( uplo, k-1, -r1, ap( kc ), 1_${ik}$, ap ) ! store u(k) in column k call stdlib${ii}$_csscal( k-1, r1, ap( kc ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**h ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**h if( k>2_${ik}$ ) then d = stdlib${ii}$_slapy2( real( ap( k-1+( k-1 )*k / 2_${ik}$ ),KIND=sp),aimag( ap( k-1+( & k-1 )*k / 2_${ik}$ ) ) ) d22 = real( ap( k-1+( k-2 )*( k-1 ) / 2_${ik}$ ),KIND=sp) / d d11 = real( ap( k+( k-1 )*k / 2_${ik}$ ),KIND=sp) / d tt = one / ( d11*d22-one ) d12 = ap( k-1+( k-1 )*k / 2_${ik}$ ) / d d = tt / d do j = k - 2, 1, -1 wkm1 = d*( d11*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ )-conjg( d12 )*ap( j+( k-1 )*k & / 2_${ik}$ ) ) wk = d*( d22*ap( j+( k-1 )*k / 2_${ik}$ )-d12*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) ) do i = j, 1, -1 ap( i+( j-1 )*j / 2_${ik}$ ) = ap( i+( j-1 )*j / 2_${ik}$ ) -ap( i+( k-1 )*k / 2_${ik}$ )& *conjg( wk ) -ap( i+( k-2 )*( k-1 ) / 2_${ik}$ )*conjg( wkm1 ) end do ap( j+( k-1 )*k / 2_${ik}$ ) = wk ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) = wkm1 ap( j+( j-1 )*j / 2_${ik}$ ) = cmplx( real( ap( j+( j-1 )*j / 2_${ik}$ ),KIND=sp), & zero,KIND=sp) end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep kc = knc - k go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ kc = 1_${ik}$ npp = n*( n+1 ) / 2_${ik}$ 60 continue knc = kc ! if k > n, exit from loop if( k>n )go to 110 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( ap( kc ),KIND=sp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero kx = kc + imax - k do j = k, imax - 1 if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + n - j end do kpc = npp - ( n-imax+1 )*( n-imax+2 ) / 2_${ik}$ + 1_${ik}$ if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( ap( kpc ),KIND=sp) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kstep==2_${ik}$ )knc = knc + n - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, ap( kc ), 1_${ik}$ ) colmax = cabs1( ap( kc+imax-1 ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero: set info and continue if( info==0_${ik}$ )info = k kp = k ap( kc+k-1 ) = real( ap( kc+k-1 ),KIND=dp) else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero jmax = imax kx = imax*( imax+1 ) / 2_${ik}$ + imax do j = imax + 1, k if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + j end do kpc = ( imax-1 )*imax / 2_${ik}$ + 1_${ik}$ if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_izamax( imax-1, ap( kpc ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( ap( kpc+jmax-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( ap( kpc+imax-1 ),KIND=dp) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kstep==2_${ik}$ )knc = knc - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_zswap( kp-1, ap( knc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, kk - 1 kx = kx + j - 1_${ik}$ t = conjg( ap( knc+j-1 ) ) ap( knc+j-1 ) = conjg( ap( kx ) ) ap( kx ) = t end do ap( kx+kk-1 ) = conjg( ap( kx+kk-1 ) ) r1 = real( ap( knc+kk-1 ),KIND=dp) ap( knc+kk-1 ) = real( ap( kpc+kp-1 ),KIND=dp) ap( kpc+kp-1 ) = r1 if( kstep==2_${ik}$ ) then ap( kc+k-1 ) = real( ap( kc+k-1 ),KIND=dp) t = ap( kc+k-2 ) ap( kc+k-2 ) = ap( kc+kp-1 ) ap( kc+kp-1 ) = t end if else ap( kc+k-1 ) = real( ap( kc+k-1 ),KIND=dp) if( kstep==2_${ik}$ )ap( kc-1 ) = real( ap( kc-1 ),KIND=dp) end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**h = a - w(k)*1/d(k)*w(k)**h r1 = one / real( ap( kc+k-1 ),KIND=dp) call stdlib${ii}$_zhpr( uplo, k-1, -r1, ap( kc ), 1_${ik}$, ap ) ! store u(k) in column k call stdlib${ii}$_zdscal( k-1, r1, ap( kc ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**h ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**h if( k>2_${ik}$ ) then d = stdlib${ii}$_dlapy2( real( ap( k-1+( k-1 )*k / 2_${ik}$ ),KIND=dp),aimag( ap( k-1+( & k-1 )*k / 2_${ik}$ ) ) ) d22 = real( ap( k-1+( k-2 )*( k-1 ) / 2_${ik}$ ),KIND=dp) / d d11 = real( ap( k+( k-1 )*k / 2_${ik}$ ),KIND=dp) / d tt = one / ( d11*d22-one ) d12 = ap( k-1+( k-1 )*k / 2_${ik}$ ) / d d = tt / d do j = k - 2, 1, -1 wkm1 = d*( d11*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ )-conjg( d12 )*ap( j+( k-1 )*k & / 2_${ik}$ ) ) wk = d*( d22*ap( j+( k-1 )*k / 2_${ik}$ )-d12*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) ) do i = j, 1, -1 ap( i+( j-1 )*j / 2_${ik}$ ) = ap( i+( j-1 )*j / 2_${ik}$ ) -ap( i+( k-1 )*k / 2_${ik}$ )& *conjg( wk ) -ap( i+( k-2 )*( k-1 ) / 2_${ik}$ )*conjg( wkm1 ) end do ap( j+( k-1 )*k / 2_${ik}$ ) = wk ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) = wkm1 ap( j+( j-1 )*j / 2_${ik}$ ) = cmplx( real( ap( j+( j-1 )*j / 2_${ik}$ ),KIND=dp), & zero,KIND=dp) end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep kc = knc - k go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ kc = 1_${ik}$ npp = n*( n+1 ) / 2_${ik}$ 60 continue knc = kc ! if k > n, exit from loop if( k>n )go to 110 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( ap( kc ),KIND=dp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero kx = kc + imax - k do j = k, imax - 1 if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + n - j end do kpc = npp - ( n-imax+1 )*( n-imax+2 ) / 2_${ik}$ + 1_${ik}$ if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( ap( kpc ),KIND=dp) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kstep==2_${ik}$ )knc = knc + n - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, ap( kc ), 1_${ik}$ ) colmax = cabs1( ap( kc+imax-1 ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero: set info and continue if( info==0_${ik}$ )info = k kp = k ap( kc+k-1 ) = real( ap( kc+k-1 ),KIND=${ck}$) else if( absakk>=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero jmax = imax kx = imax*( imax+1 ) / 2_${ik}$ + imax do j = imax + 1, k if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + j end do kpc = ( imax-1 )*imax / 2_${ik}$ + 1_${ik}$ if( imax>1_${ik}$ ) then jmax = stdlib${ii}$_i${ci}$amax( imax-1, ap( kpc ), 1_${ik}$ ) rowmax = max( rowmax, cabs1( ap( kpc+jmax-1 ) ) ) end if if( absakk>=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( ap( kpc+imax-1 ),KIND=${ck}$) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k-1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k - kstep + 1_${ik}$ if( kstep==2_${ik}$ )knc = knc - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the leading ! submatrix a(1:k,1:k) call stdlib${ii}$_${ci}$swap( kp-1, ap( knc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, kk - 1 kx = kx + j - 1_${ik}$ t = conjg( ap( knc+j-1 ) ) ap( knc+j-1 ) = conjg( ap( kx ) ) ap( kx ) = t end do ap( kx+kk-1 ) = conjg( ap( kx+kk-1 ) ) r1 = real( ap( knc+kk-1 ),KIND=${ck}$) ap( knc+kk-1 ) = real( ap( kpc+kp-1 ),KIND=${ck}$) ap( kpc+kp-1 ) = r1 if( kstep==2_${ik}$ ) then ap( kc+k-1 ) = real( ap( kc+k-1 ),KIND=${ck}$) t = ap( kc+k-2 ) ap( kc+k-2 ) = ap( kc+kp-1 ) ap( kc+kp-1 ) = t end if else ap( kc+k-1 ) = real( ap( kc+k-1 ),KIND=${ck}$) if( kstep==2_${ik}$ )ap( kc-1 ) = real( ap( kc-1 ),KIND=${ck}$) end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**h = a - w(k)*1/d(k)*w(k)**h r1 = one / real( ap( kc+k-1 ),KIND=${ck}$) call stdlib${ii}$_${ci}$hpr( uplo, k-1, -r1, ap( kc ), 1_${ik}$, ap ) ! store u(k) in column k call stdlib${ii}$_${ci}$dscal( k-1, r1, ap( kc ), 1_${ik}$ ) else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**h ! = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )**h if( k>2_${ik}$ ) then d = stdlib${ii}$_${c2ri(ci)}$lapy2( real( ap( k-1+( k-1 )*k / 2_${ik}$ ),KIND=${ck}$),aimag( ap( k-1+( & k-1 )*k / 2_${ik}$ ) ) ) d22 = real( ap( k-1+( k-2 )*( k-1 ) / 2_${ik}$ ),KIND=${ck}$) / d d11 = real( ap( k+( k-1 )*k / 2_${ik}$ ),KIND=${ck}$) / d tt = one / ( d11*d22-one ) d12 = ap( k-1+( k-1 )*k / 2_${ik}$ ) / d d = tt / d do j = k - 2, 1, -1 wkm1 = d*( d11*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ )-conjg( d12 )*ap( j+( k-1 )*k & / 2_${ik}$ ) ) wk = d*( d22*ap( j+( k-1 )*k / 2_${ik}$ )-d12*ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) ) do i = j, 1, -1 ap( i+( j-1 )*j / 2_${ik}$ ) = ap( i+( j-1 )*j / 2_${ik}$ ) -ap( i+( k-1 )*k / 2_${ik}$ )& *conjg( wk ) -ap( i+( k-2 )*( k-1 ) / 2_${ik}$ )*conjg( wkm1 ) end do ap( j+( k-1 )*k / 2_${ik}$ ) = wk ap( j+( k-2 )*( k-1 ) / 2_${ik}$ ) = wkm1 ap( j+( j-1 )*j / 2_${ik}$ ) = cmplx( real( ap( j+( j-1 )*j / 2_${ik}$ ),KIND=${ck}$), & zero,KIND=${ck}$) end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -kp ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep kc = knc - k go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ kc = 1_${ik}$ npp = n*( n+1 ) / 2_${ik}$ 60 continue knc = kc ! if k > n, exit from loop if( k>n )go to 110 kstep = 1_${ik}$ ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( ap( kc ),KIND=${ck}$) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value if( k=alpha*colmax ) then ! no interchange, use 1-by-1 pivot block kp = k else ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value rowmax = zero kx = kc + imax - k do j = k, imax - 1 if( cabs1( ap( kx ) )>rowmax ) then rowmax = cabs1( ap( kx ) ) jmax = j end if kx = kx + n - j end do kpc = npp - ( n-imax+1 )*( n-imax+2 ) / 2_${ik}$ + 1_${ik}$ if( imax=alpha*colmax*( colmax / rowmax ) ) then ! no interchange, use 1-by-1 pivot block kp = k else if( abs( real( ap( kpc ),KIND=${ck}$) )>=alpha*rowmax ) then ! interchange rows and columns k and imax, use 1-by-1 ! pivot block kp = imax else ! interchange rows and columns k+1 and imax, use 2-by-2 ! pivot block kp = imax kstep = 2_${ik}$ end if end if kk = k + kstep - 1_${ik}$ if( kstep==2_${ik}$ )knc = knc + n - k + 1_${ik}$ if( kp/=kk ) then ! interchange rows and columns kk and kp in the trailing ! submatrix a(k:n,k:n) if( kp0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_cgeru( k-1, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. s = real( cone,KIND=sp) / real( ap( kc+k-1 ),KIND=sp) call stdlib${ii}$_csscal( nrhs, s, b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_cswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_cgeru( k-2, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgeru( k-2, nrhs, -cone, ap( kc-( k-1 ) ), 1_${ik}$,b( k-1, 1_${ik}$ ), ldb, b( 1_${ik}$, & 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. akm1k = ap( kc+k-2 ) akm1 = ap( kc-1 ) / akm1k ak = ap( kc+k-1 ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / conjg( akm1k ) b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do kc = kc - k + 1_${ik}$ k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**h *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**h(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ ) then call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, ap( kc ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) end if ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + k k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**h(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, ap( kc ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, ap( kc+k ),& 1_${ik}$, cone, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + 2_${ik}$*k + 1_${ik}$ k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**h. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**h(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_zgeru( k-1, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. s = real( cone,KIND=dp) / real( ap( kc+k-1 ),KIND=dp) call stdlib${ii}$_zdscal( nrhs, s, b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_zswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_zgeru( k-2, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgeru( k-2, nrhs, -cone, ap( kc-( k-1 ) ), 1_${ik}$,b( k-1, 1_${ik}$ ), ldb, b( 1_${ik}$, & 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. akm1k = ap( kc+k-2 ) akm1 = ap( kc-1 ) / akm1k ak = ap( kc+k-1 ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / conjg( akm1k ) b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do kc = kc - k + 1_${ik}$ k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**h *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**h(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ ) then call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, ap( kc ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) end if ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + k k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**h(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, ap( kc ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, ap( kc+k ),& 1_${ik}$, cone, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + 2_${ik}$*k + 1_${ik}$ k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**h. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**h(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ci}$geru( k-1, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. s = real( cone,KIND=${ck}$) / real( ap( kc+k-1 ),KIND=${ck}$) call stdlib${ii}$_${ci}$dscal( nrhs, s, b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k-1 and -ipiv(k). kp = -ipiv( k ) if( kp/=k-1 )call stdlib${ii}$_${ci}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_${ci}$geru( k-2, nrhs, -cone, ap( kc ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$geru( k-2, nrhs, -cone, ap( kc-( k-1 ) ), 1_${ik}$,b( k-1, 1_${ik}$ ), ldb, b( 1_${ik}$, & 1_${ik}$ ), ldb ) ! multiply by the inverse of the diagonal block. akm1k = ap( kc+k-2 ) akm1 = ap( kc-1 ) / akm1k ak = ap( kc+k-1 ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / conjg( akm1k ) b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do kc = kc - k + 1_${ik}$ k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**h *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**h(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, ap( kc ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) end if ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + k k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**h(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, ap( kc ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, ap( kc+k ),& 1_${ik}$, cone, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k). kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kc = kc + 2_${ik}$*k + 1_${ik}$ k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**h. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**h(k)), where l(k) is the transformation ! stored in column k of a. if( k0 .and. ap( kp )==czero )return kp = kp - info end do else ! lower triangular storage: examine d from top to bottom. kp = 1_${ik}$ do info = 1, n if( ipiv( info )>0 .and. ap( kp )==czero )return kp = kp + n - info + 1_${ik}$ end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 kcnext = kc + k if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc+k-1 ) = one / real( ap( kc+k-1 ),KIND=sp) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_chpmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kc ), 1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -real( stdlib${ii}$_cdotc( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ),& KIND=sp) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( ap( kcnext+k-1 ) ) ak = real( ap( kc+k-1 ),KIND=sp) / t akp1 = real( ap( kcnext+k ),KIND=sp) / t akkp1 = ap( kcnext+k-1 ) / t d = t*( ak*akp1-one ) ap( kc+k-1 ) = akp1 / d ap( kcnext+k ) = ak / d ap( kcnext+k-1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_chpmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kc ), 1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -real( stdlib${ii}$_cdotc( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ),& KIND=sp) ap( kcnext+k-1 ) = ap( kcnext+k-1 ) -stdlib${ii}$_cdotc( k-1, ap( kc ), 1_${ik}$, ap( & kcnext ),1_${ik}$ ) call stdlib${ii}$_ccopy( k-1, ap( kcnext ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_chpmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kcnext ), 1_${ik}$ ) ap( kcnext+k ) = ap( kcnext+k ) -real( stdlib${ii}$_cdotc( k-1, work, 1_${ik}$, ap( kcnext & ),1_${ik}$ ),KIND=sp) end if kstep = 2_${ik}$ kcnext = kcnext + k + 1_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) kpc = ( kp-1 )*kp / 2_${ik}$ + 1_${ik}$ call stdlib${ii}$_cswap( kp-1, ap( kc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, k - 1 kx = kx + j - 1_${ik}$ temp = conjg( ap( kc+j-1 ) ) ap( kc+j-1 ) = conjg( ap( kx ) ) ap( kx ) = temp end do ap( kc+kp-1 ) = conjg( ap( kc+kp-1 ) ) temp = ap( kc+k-1 ) ap( kc+k-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = temp if( kstep==2_${ik}$ ) then temp = ap( kc+k+k-1 ) ap( kc+k+k-1 ) = ap( kc+k+kp-1 ) ap( kc+k+kp-1 ) = temp end if end if k = k + kstep kc = kcnext go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. npp = n*( n+1 ) / 2_${ik}$ k = n kc = npp 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 kcnext = kc - ( n-k+2 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc ) = one / real( ap( kc ),KIND=sp) ! compute column k of the inverse. if( k0 .and. ap( kp )==czero )return kp = kp - info end do else ! lower triangular storage: examine d from top to bottom. kp = 1_${ik}$ do info = 1, n if( ipiv( info )>0 .and. ap( kp )==czero )return kp = kp + n - info + 1_${ik}$ end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 kcnext = kc + k if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc+k-1 ) = one / real( ap( kc+k-1 ),KIND=dp) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zhpmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kc ), 1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -real( stdlib${ii}$_zdotc( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ),& KIND=dp) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( ap( kcnext+k-1 ) ) ak = real( ap( kc+k-1 ),KIND=dp) / t akp1 = real( ap( kcnext+k ),KIND=dp) / t akkp1 = ap( kcnext+k-1 ) / t d = t*( ak*akp1-one ) ap( kc+k-1 ) = akp1 / d ap( kcnext+k ) = ak / d ap( kcnext+k-1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zhpmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kc ), 1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -real( stdlib${ii}$_zdotc( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ),& KIND=dp) ap( kcnext+k-1 ) = ap( kcnext+k-1 ) -stdlib${ii}$_zdotc( k-1, ap( kc ), 1_${ik}$, ap( & kcnext ),1_${ik}$ ) call stdlib${ii}$_zcopy( k-1, ap( kcnext ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zhpmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kcnext ), 1_${ik}$ ) ap( kcnext+k ) = ap( kcnext+k ) -real( stdlib${ii}$_zdotc( k-1, work, 1_${ik}$, ap( kcnext & ),1_${ik}$ ),KIND=dp) end if kstep = 2_${ik}$ kcnext = kcnext + k + 1_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) kpc = ( kp-1 )*kp / 2_${ik}$ + 1_${ik}$ call stdlib${ii}$_zswap( kp-1, ap( kc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, k - 1 kx = kx + j - 1_${ik}$ temp = conjg( ap( kc+j-1 ) ) ap( kc+j-1 ) = conjg( ap( kx ) ) ap( kx ) = temp end do ap( kc+kp-1 ) = conjg( ap( kc+kp-1 ) ) temp = ap( kc+k-1 ) ap( kc+k-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = temp if( kstep==2_${ik}$ ) then temp = ap( kc+k+k-1 ) ap( kc+k+k-1 ) = ap( kc+k+kp-1 ) ap( kc+k+kp-1 ) = temp end if end if k = k + kstep kc = kcnext go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. npp = n*( n+1 ) / 2_${ik}$ k = n kc = npp 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 kcnext = kc - ( n-k+2 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc ) = one / real( ap( kc ),KIND=dp) ! compute column k of the inverse. if( k0 .and. ap( kp )==czero )return kp = kp - info end do else ! lower triangular storage: examine d from top to bottom. kp = 1_${ik}$ do info = 1, n if( ipiv( info )>0 .and. ap( kp )==czero )return kp = kp + n - info + 1_${ik}$ end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ kc = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 50 kcnext = kc + k if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc+k-1 ) = one / real( ap( kc+k-1 ),KIND=${ck}$) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$hpmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kc ), 1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -real( stdlib${ii}$_${ci}$dotc( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ),& KIND=${ck}$) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( ap( kcnext+k-1 ) ) ak = real( ap( kc+k-1 ),KIND=${ck}$) / t akp1 = real( ap( kcnext+k ),KIND=${ck}$) / t akkp1 = ap( kcnext+k-1 ) / t d = t*( ak*akp1-one ) ap( kc+k-1 ) = akp1 / d ap( kcnext+k ) = ak / d ap( kcnext+k-1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, ap( kc ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$hpmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kc ), 1_${ik}$ ) ap( kc+k-1 ) = ap( kc+k-1 ) -real( stdlib${ii}$_${ci}$dotc( k-1, work, 1_${ik}$, ap( kc ), 1_${ik}$ ),& KIND=${ck}$) ap( kcnext+k-1 ) = ap( kcnext+k-1 ) -stdlib${ii}$_${ci}$dotc( k-1, ap( kc ), 1_${ik}$, ap( & kcnext ),1_${ik}$ ) call stdlib${ii}$_${ci}$copy( k-1, ap( kcnext ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$hpmv( uplo, k-1, -cone, ap, work, 1_${ik}$, czero,ap( kcnext ), 1_${ik}$ ) ap( kcnext+k ) = ap( kcnext+k ) -real( stdlib${ii}$_${ci}$dotc( k-1, work, 1_${ik}$, ap( kcnext & ),1_${ik}$ ),KIND=${ck}$) end if kstep = 2_${ik}$ kcnext = kcnext + k + 1_${ik}$ end if kp = abs( ipiv( k ) ) if( kp/=k ) then ! interchange rows and columns k and kp in the leading ! submatrix a(1:k+1,1:k+1) kpc = ( kp-1 )*kp / 2_${ik}$ + 1_${ik}$ call stdlib${ii}$_${ci}$swap( kp-1, ap( kc ), 1_${ik}$, ap( kpc ), 1_${ik}$ ) kx = kpc + kp - 1_${ik}$ do j = kp + 1, k - 1 kx = kx + j - 1_${ik}$ temp = conjg( ap( kc+j-1 ) ) ap( kc+j-1 ) = conjg( ap( kx ) ) ap( kx ) = temp end do ap( kc+kp-1 ) = conjg( ap( kc+kp-1 ) ) temp = ap( kc+k-1 ) ap( kc+k-1 ) = ap( kpc+kp-1 ) ap( kpc+kp-1 ) = temp if( kstep==2_${ik}$ ) then temp = ap( kc+k+k-1 ) ap( kc+k+k-1 ) = ap( kc+k+kp-1 ) ap( kc+k+kp-1 ) = temp end if end if k = k + kstep kc = kcnext go to 30 50 continue else ! compute inv(a) from the factorization a = l*d*l**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. npp = n*( n+1 ) / 2_${ik}$ k = n kc = npp 60 continue ! if k < 1, exit from loop. if( k<1 )go to 80 kcnext = kc - ( n-k+2 ) if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. ap( kc ) = one / real( ap( kc ),KIND=${ck}$) ! compute column k of the inverse. if( k0_${ik}$ ) then mm = m mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'SGELSS', ' ', m, n, nrhs, -1_${ik}$ ) if( m>=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than ! columns ! compute space needed for stdlib${ii}$_sgeqrf call stdlib${ii}$_sgeqrf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, info ) lwork_sgeqrf=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_sormqr call stdlib${ii}$_sormqr( 'L', 'T', m, nrhs, n, a, lda, dum(1_${ik}$), b,ldb, dum(1_${ik}$), -1_${ik}$, & info ) lwork_sormqr=dum(1_${ik}$) mm = n maxwrk = max( maxwrk, n + lwork_sgeqrf ) maxwrk = max( maxwrk, n + lwork_sormqr ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined ! compute workspace needed for stdlib${ii}$_sbdsqr bdspac = max( 1_${ik}$, 5_${ik}$*n ) ! compute space needed for stdlib${ii}$_sgebrd call stdlib${ii}$_sgebrd( mm, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, info & ) lwork_sgebrd=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_sormbr call stdlib${ii}$_sormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$),& -1_${ik}$, info ) lwork_sormbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_sorgbr call stdlib${ii}$_sorgbr( 'P', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_sorgbr=dum(1_${ik}$) ! compute total workspace needed maxwrk = max( maxwrk, 3_${ik}$*n + lwork_sgebrd ) maxwrk = max( maxwrk, 3_${ik}$*n + lwork_sormbr ) maxwrk = max( maxwrk, 3_${ik}$*n + lwork_sorgbr ) maxwrk = max( maxwrk, bdspac ) maxwrk = max( maxwrk, n*nrhs ) minwrk = max( 3_${ik}$*n + mm, 3_${ik}$*n + nrhs, bdspac ) maxwrk = max( minwrk, maxwrk ) end if if( n>m ) then ! compute workspace needed for stdlib${ii}$_sbdsqr bdspac = max( 1_${ik}$, 5_${ik}$*m ) minwrk = max( 3_${ik}$*m+nrhs, 3_${ik}$*m+n, bdspac ) if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows ! compute space needed for stdlib${ii}$_sgebrd call stdlib${ii}$_sgebrd( m, m, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & info ) lwork_sgebrd=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_sormbr call stdlib${ii}$_sormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_sormbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_sorgbr call stdlib${ii}$_sorgbr( 'P', m, m, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_sorgbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_sormlq call stdlib${ii}$_sormlq( 'L', 'T', n, nrhs, m, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$), -& 1_${ik}$, info ) lwork_sormlq=dum(1_${ik}$) ! compute total workspace needed maxwrk = m + m*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGELQF', ' ', m, n, -1_${ik}$,-1_${ik}$ ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + lwork_sgebrd ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + lwork_sormbr ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + lwork_sorgbr ) maxwrk = max( maxwrk, m*m + m + bdspac ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m + m + m*nrhs ) else maxwrk = max( maxwrk, m*m + 2_${ik}$*m ) end if maxwrk = max( maxwrk, m + lwork_sormlq ) else ! path 2 - underdetermined ! compute space needed for stdlib${ii}$_sgebrd call stdlib${ii}$_sgebrd( m, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & info ) lwork_sgebrd=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_sormbr call stdlib${ii}$_sormbr( 'Q', 'L', 'T', m, nrhs, m, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_sormbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_sorgbr call stdlib${ii}$_sorgbr( 'P', m, n, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_sorgbr=dum(1_${ik}$) maxwrk = 3_${ik}$*m + lwork_sgebrd maxwrk = max( maxwrk, 3_${ik}$*m + lwork_sormbr ) maxwrk = max( maxwrk, 3_${ik}$*m + lwork_sorgbr ) maxwrk = max( maxwrk, bdspac ) maxwrk = max( maxwrk, n*nrhs ) end if end if maxwrk = max( minwrk, maxwrk ) end if work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_slaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) call stdlib${ii}$_slaset( 'F', minmn, 1_${ik}$, zero, zero, s, minmn ) rank = 0_${ik}$ go to 70 end if ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_slange( 'M', m, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! overdetermined case if( m>=n ) then ! path 1 - overdetermined or exactly determined mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns mm = n itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & info ) ! multiply b by transpose(q) ! (workspace: need n+nrhs, prefer n+nrhs*nb) call stdlib${ii}$_sormqr( 'L', 'T', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & iwork ), lwork-iwork+1, info ) ! zero out below r if( n>1_${ik}$ )call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) end if ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (workspace: need 3*n+mm, prefer 3*n+(mm+n)*nb) call stdlib${ii}$_sgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work(& iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r ! (workspace: need 3*n+nrhs, prefer 3*n+nrhs*nb) call stdlib${ii}$_sormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in a ! (workspace: need 4*n-1, prefer 3*n+(n-1)*nb) call stdlib${ii}$_sorgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) iwork = ie + n ! perform bidiagonal qr iteration ! multiply b by transpose of left singular vectors ! compute right singular vectors in a ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'U', n, n, 0_${ik}$, nrhs, s, work( ie ), a, lda, dum,1_${ik}$, b, ldb, work( & iwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_srscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_slaset( 'F', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors ! (workspace: need n, prefer n*nrhs) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_sgemm( 'T', 'N', n, nrhs, n, one, a, lda, b, ldb, zero,work, ldb ) call stdlib${ii}$_slacpy( 'G', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_sgemm( 'T', 'N', n, bl, n, one, a, lda, b( 1_${ik}$, i ),ldb, zero, work,& n ) call stdlib${ii}$_slacpy( 'G', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_sgemv( 'T', n, n, one, a, lda, b, 1_${ik}$, zero, work, 1_${ik}$ ) call stdlib${ii}$_scopy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if else if( n>=mnthr .and. lwork>=4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) then ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm ldwork = m if( lwork>=max( 4_${ik}$*m+m*lda+max( m, 2_${ik}$*m-4, nrhs, n-3*m ),m*lda+m+m*nrhs ) )ldwork = & lda itau = 1_${ik}$ iwork = m + 1_${ik}$ ! compute a=l*q ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, info ) il = iwork ! copy l to work(il), zeroing out above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, work( il+ldwork ),ldwork ) ie = il + ldwork*m itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(il) ! (workspace: need m*m+5*m, prefer m*m+4*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, work( il ), ldwork, s, work( ie ),work( itauq ), work( & itaup ), work( iwork ),lwork-iwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l ! (workspace: need m*m+4*m+nrhs, prefer m*m+4*m+nrhs*nb) call stdlib${ii}$_sormbr( 'Q', 'L', 'T', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( iwork ),lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in work(il) ! (workspace: need m*m+5*m-1, prefer m*m+4*m+(m-1)*nb) call stdlib${ii}$_sorgbr( 'P', m, m, m, work( il ), ldwork, work( itaup ),work( iwork ), & lwork-iwork+1, info ) iwork = ie + m ! perform bidiagonal qr iteration, ! computing right singular vectors of l in work(il) and ! multiplying b by transpose of left singular vectors ! (workspace: need m*m+m+bdspac) call stdlib${ii}$_sbdsqr( 'U', m, m, 0_${ik}$, nrhs, s, work( ie ), work( il ),ldwork, a, lda, b,& ldb, work( iwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_srscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_slaset( 'F', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) end if end do iwork = ie ! multiply b by right singular vectors of l in work(il) ! (workspace: need m*m+2*m, prefer m*m+m+m*nrhs) if( lwork>=ldb*nrhs+iwork-1 .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_sgemm( 'T', 'N', m, nrhs, m, one, work( il ), ldwork,b, ldb, zero, & work( iwork ), ldb ) call stdlib${ii}$_slacpy( 'G', m, nrhs, work( iwork ), ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = ( lwork-iwork+1 ) / m do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_sgemm( 'T', 'N', m, bl, m, one, work( il ), ldwork,b( 1_${ik}$, i ), ldb,& zero, work( iwork ), m ) call stdlib${ii}$_slacpy( 'G', m, bl, work( iwork ), m, b( 1_${ik}$, i ),ldb ) end do else call stdlib${ii}$_sgemv( 'T', m, m, one, work( il ), ldwork, b( 1_${ik}$, 1_${ik}$ ),1_${ik}$, zero, work( & iwork ), 1_${ik}$ ) call stdlib${ii}$_scopy( m, work( iwork ), 1_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) end if ! zero out below first m rows of b call stdlib${ii}$_slaset( 'F', n-m, nrhs, zero, zero, b( m+1, 1_${ik}$ ), ldb ) iwork = itau + m ! multiply transpose(q) by b ! (workspace: need m+nrhs, prefer m+nrhs*nb) call stdlib${ii}$_sormlq( 'L', 'T', n, nrhs, m, a, lda, work( itau ), b,ldb, work( iwork )& , lwork-iwork+1, info ) else ! path 2 - remaining underdetermined cases ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (workspace: need 3*m+n, prefer 3*m+(m+n)*nb) call stdlib${ii}$_sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work( & iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors ! (workspace: need 3*m+nrhs, prefer 3*m+nrhs*nb) call stdlib${ii}$_sormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors in a ! (workspace: need 4*m, prefer 3*m+m*nb) call stdlib${ii}$_sorgbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) iwork = ie + m ! perform bidiagonal qr iteration, ! computing right singular vectors of a in a and ! multiplying b by transpose of left singular vectors ! (workspace: need bdspac) call stdlib${ii}$_sbdsqr( 'L', m, n, 0_${ik}$, nrhs, s, work( ie ), a, lda, dum,1_${ik}$, b, ldb, work( & iwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_srscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_slaset( 'F', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors of a ! (workspace: need n, prefer n*nrhs) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_sgemm( 'T', 'N', n, nrhs, m, one, a, lda, b, ldb, zero,work, ldb ) call stdlib${ii}$_slacpy( 'F', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_sgemm( 'T', 'N', n, bl, m, one, a, lda, b( 1_${ik}$, i ),ldb, zero, work,& n ) call stdlib${ii}$_slacpy( 'F', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_sgemv( 'T', m, n, one, a, lda, b, 1_${ik}$, zero, work, 1_${ik}$ ) call stdlib${ii}$_scopy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 70 continue work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_sgelss module subroutine stdlib${ii}$_dgelss( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, info ) !! DGELSS computes the minimum norm solution to a real linear least !! squares problem: !! Minimize 2-norm(| b - A*x |). !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix !! X. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(dp), intent(in) :: rcond ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: s(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: bdspac, bl, chunk, i, iascl, ibscl, ie, il, itau, itaup, itauq, iwork, & ldwork, maxmn, maxwrk, minmn, minwrk, mm, mnthr integer(${ik}$) :: lwork_dgeqrf, lwork_dormqr, lwork_dgebrd, lwork_dormbr, lwork_dorgbr, & lwork_dormlq, lwork_dgelqf real(dp) :: anrm, bignum, bnrm, eps, sfmin, smlnum, thr ! Local Arrays real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ minmn = min( m, n ) maxmn = max( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then mm = m mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'DGELSS', ' ', m, n, nrhs, -1_${ik}$ ) if( m>=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than ! columns ! compute space needed for stdlib${ii}$_dgeqrf call stdlib${ii}$_dgeqrf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, info ) lwork_dgeqrf=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_dormqr call stdlib${ii}$_dormqr( 'L', 'T', m, nrhs, n, a, lda, dum(1_${ik}$), b,ldb, dum(1_${ik}$), -1_${ik}$, & info ) lwork_dormqr=dum(1_${ik}$) mm = n maxwrk = max( maxwrk, n + lwork_dgeqrf ) maxwrk = max( maxwrk, n + lwork_dormqr ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined ! compute workspace needed for stdlib${ii}$_dbdsqr bdspac = max( 1_${ik}$, 5_${ik}$*n ) ! compute space needed for stdlib${ii}$_dgebrd call stdlib${ii}$_dgebrd( mm, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, info & ) lwork_dgebrd=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_dormbr call stdlib${ii}$_dormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$),& -1_${ik}$, info ) lwork_dormbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_dorgbr call stdlib${ii}$_dorgbr( 'P', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_dorgbr=dum(1_${ik}$) ! compute total workspace needed maxwrk = max( maxwrk, 3_${ik}$*n + lwork_dgebrd ) maxwrk = max( maxwrk, 3_${ik}$*n + lwork_dormbr ) maxwrk = max( maxwrk, 3_${ik}$*n + lwork_dorgbr ) maxwrk = max( maxwrk, bdspac ) maxwrk = max( maxwrk, n*nrhs ) minwrk = max( 3_${ik}$*n + mm, 3_${ik}$*n + nrhs, bdspac ) maxwrk = max( minwrk, maxwrk ) end if if( n>m ) then ! compute workspace needed for stdlib${ii}$_dbdsqr bdspac = max( 1_${ik}$, 5_${ik}$*m ) minwrk = max( 3_${ik}$*m+nrhs, 3_${ik}$*m+n, bdspac ) if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows ! compute space needed for stdlib${ii}$_dgelqf call stdlib${ii}$_dgelqf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$),-1_${ik}$, info ) lwork_dgelqf=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_dgebrd call stdlib${ii}$_dgebrd( m, m, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & info ) lwork_dgebrd=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_dormbr call stdlib${ii}$_dormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_dormbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_dorgbr call stdlib${ii}$_dorgbr( 'P', m, m, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_dorgbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_dormlq call stdlib${ii}$_dormlq( 'L', 'T', n, nrhs, m, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$), -& 1_${ik}$, info ) lwork_dormlq=dum(1_${ik}$) ! compute total workspace needed maxwrk = m + lwork_dgelqf maxwrk = max( maxwrk, m*m + 4_${ik}$*m + lwork_dgebrd ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + lwork_dormbr ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + lwork_dorgbr ) maxwrk = max( maxwrk, m*m + m + bdspac ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m + m + m*nrhs ) else maxwrk = max( maxwrk, m*m + 2_${ik}$*m ) end if maxwrk = max( maxwrk, m + lwork_dormlq ) else ! path 2 - underdetermined ! compute space needed for stdlib${ii}$_dgebrd call stdlib${ii}$_dgebrd( m, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & info ) lwork_dgebrd=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_dormbr call stdlib${ii}$_dormbr( 'Q', 'L', 'T', m, nrhs, m, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_dormbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_dorgbr call stdlib${ii}$_dorgbr( 'P', m, n, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_dorgbr=dum(1_${ik}$) maxwrk = 3_${ik}$*m + lwork_dgebrd maxwrk = max( maxwrk, 3_${ik}$*m + lwork_dormbr ) maxwrk = max( maxwrk, 3_${ik}$*m + lwork_dorgbr ) maxwrk = max( maxwrk, bdspac ) maxwrk = max( maxwrk, n*nrhs ) end if end if maxwrk = max( minwrk, maxwrk ) end if work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_dlaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) call stdlib${ii}$_dlaset( 'F', minmn, 1_${ik}$, zero, zero, s, minmn ) rank = 0_${ik}$ go to 70 end if ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_dlange( 'M', m, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! overdetermined case if( m>=n ) then ! path 1 - overdetermined or exactly determined mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns mm = n itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & info ) ! multiply b by transpose(q) ! (workspace: need n+nrhs, prefer n+nrhs*nb) call stdlib${ii}$_dormqr( 'L', 'T', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & iwork ), lwork-iwork+1, info ) ! zero out below r if( n>1_${ik}$ )call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) end if ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (workspace: need 3*n+mm, prefer 3*n+(mm+n)*nb) call stdlib${ii}$_dgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work(& iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r ! (workspace: need 3*n+nrhs, prefer 3*n+nrhs*nb) call stdlib${ii}$_dormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in a ! (workspace: need 4*n-1, prefer 3*n+(n-1)*nb) call stdlib${ii}$_dorgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) iwork = ie + n ! perform bidiagonal qr iteration ! multiply b by transpose of left singular vectors ! compute right singular vectors in a ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'U', n, n, 0_${ik}$, nrhs, s, work( ie ), a, lda, dum,1_${ik}$, b, ldb, work( & iwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_drscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_dlaset( 'F', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors ! (workspace: need n, prefer n*nrhs) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_dgemm( 'T', 'N', n, nrhs, n, one, a, lda, b, ldb, zero,work, ldb ) call stdlib${ii}$_dlacpy( 'G', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_dgemm( 'T', 'N', n, bl, n, one, a, lda, b( 1_${ik}$, i ),ldb, zero, work,& n ) call stdlib${ii}$_dlacpy( 'G', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_dgemv( 'T', n, n, one, a, lda, b, 1_${ik}$, zero, work, 1_${ik}$ ) call stdlib${ii}$_dcopy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if else if( n>=mnthr .and. lwork>=4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) then ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm ldwork = m if( lwork>=max( 4_${ik}$*m+m*lda+max( m, 2_${ik}$*m-4, nrhs, n-3*m ),m*lda+m+m*nrhs ) )ldwork = & lda itau = 1_${ik}$ iwork = m + 1_${ik}$ ! compute a=l*q ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, info ) il = iwork ! copy l to work(il), zeroing out above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, work( il+ldwork ),ldwork ) ie = il + ldwork*m itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(il) ! (workspace: need m*m+5*m, prefer m*m+4*m+2*m*nb) call stdlib${ii}$_dgebrd( m, m, work( il ), ldwork, s, work( ie ),work( itauq ), work( & itaup ), work( iwork ),lwork-iwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l ! (workspace: need m*m+4*m+nrhs, prefer m*m+4*m+nrhs*nb) call stdlib${ii}$_dormbr( 'Q', 'L', 'T', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( iwork ),lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in work(il) ! (workspace: need m*m+5*m-1, prefer m*m+4*m+(m-1)*nb) call stdlib${ii}$_dorgbr( 'P', m, m, m, work( il ), ldwork, work( itaup ),work( iwork ), & lwork-iwork+1, info ) iwork = ie + m ! perform bidiagonal qr iteration, ! computing right singular vectors of l in work(il) and ! multiplying b by transpose of left singular vectors ! (workspace: need m*m+m+bdspac) call stdlib${ii}$_dbdsqr( 'U', m, m, 0_${ik}$, nrhs, s, work( ie ), work( il ),ldwork, a, lda, b,& ldb, work( iwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_drscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_dlaset( 'F', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) end if end do iwork = ie ! multiply b by right singular vectors of l in work(il) ! (workspace: need m*m+2*m, prefer m*m+m+m*nrhs) if( lwork>=ldb*nrhs+iwork-1 .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_dgemm( 'T', 'N', m, nrhs, m, one, work( il ), ldwork,b, ldb, zero, & work( iwork ), ldb ) call stdlib${ii}$_dlacpy( 'G', m, nrhs, work( iwork ), ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = ( lwork-iwork+1 ) / m do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_dgemm( 'T', 'N', m, bl, m, one, work( il ), ldwork,b( 1_${ik}$, i ), ldb,& zero, work( iwork ), m ) call stdlib${ii}$_dlacpy( 'G', m, bl, work( iwork ), m, b( 1_${ik}$, i ),ldb ) end do else call stdlib${ii}$_dgemv( 'T', m, m, one, work( il ), ldwork, b( 1_${ik}$, 1_${ik}$ ),1_${ik}$, zero, work( & iwork ), 1_${ik}$ ) call stdlib${ii}$_dcopy( m, work( iwork ), 1_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) end if ! zero out below first m rows of b call stdlib${ii}$_dlaset( 'F', n-m, nrhs, zero, zero, b( m+1, 1_${ik}$ ), ldb ) iwork = itau + m ! multiply transpose(q) by b ! (workspace: need m+nrhs, prefer m+nrhs*nb) call stdlib${ii}$_dormlq( 'L', 'T', n, nrhs, m, a, lda, work( itau ), b,ldb, work( iwork )& , lwork-iwork+1, info ) else ! path 2 - remaining underdetermined cases ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (workspace: need 3*m+n, prefer 3*m+(m+n)*nb) call stdlib${ii}$_dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work( & iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors ! (workspace: need 3*m+nrhs, prefer 3*m+nrhs*nb) call stdlib${ii}$_dormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors in a ! (workspace: need 4*m, prefer 3*m+m*nb) call stdlib${ii}$_dorgbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) iwork = ie + m ! perform bidiagonal qr iteration, ! computing right singular vectors of a in a and ! multiplying b by transpose of left singular vectors ! (workspace: need bdspac) call stdlib${ii}$_dbdsqr( 'L', m, n, 0_${ik}$, nrhs, s, work( ie ), a, lda, dum,1_${ik}$, b, ldb, work( & iwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_drscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_dlaset( 'F', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors of a ! (workspace: need n, prefer n*nrhs) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_dgemm( 'T', 'N', n, nrhs, m, one, a, lda, b, ldb, zero,work, ldb ) call stdlib${ii}$_dlacpy( 'F', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_dgemm( 'T', 'N', n, bl, m, one, a, lda, b( 1_${ik}$, i ),ldb, zero, work,& n ) call stdlib${ii}$_dlacpy( 'F', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_dgemv( 'T', m, n, one, a, lda, b, 1_${ik}$, zero, work, 1_${ik}$ ) call stdlib${ii}$_dcopy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 70 continue work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_dgelss #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$gelss( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, info ) !! DGELSS: computes the minimum norm solution to a real linear least !! squares problem: !! Minimize 2-norm(| b - A*x |). !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix !! X. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(${rk}$), intent(in) :: rcond ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: s(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: bdspac, bl, chunk, i, iascl, ibscl, ie, il, itau, itaup, itauq, iwork, & ldwork, maxmn, maxwrk, minmn, minwrk, mm, mnthr integer(${ik}$) :: lwork_qgeqrf, lwork_qormqr, lwork_qgebrd, lwork_qormbr, lwork_qorgbr, & lwork_qormlq, lwork_qgelqf real(${rk}$) :: anrm, bignum, bnrm, eps, sfmin, smlnum, thr ! Local Arrays real(${rk}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ minmn = min( m, n ) maxmn = max( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then mm = m mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'DGELSS', ' ', m, n, nrhs, -1_${ik}$ ) if( m>=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than ! columns ! compute space needed for stdlib${ii}$_${ri}$geqrf call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, info ) lwork_qgeqrf=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_${ri}$ormqr call stdlib${ii}$_${ri}$ormqr( 'L', 'T', m, nrhs, n, a, lda, dum(1_${ik}$), b,ldb, dum(1_${ik}$), -1_${ik}$, & info ) lwork_qormqr=dum(1_${ik}$) mm = n maxwrk = max( maxwrk, n + lwork_qgeqrf ) maxwrk = max( maxwrk, n + lwork_qormqr ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined ! compute workspace needed for stdlib${ii}$_${ri}$bdsqr bdspac = max( 1_${ik}$, 5_${ik}$*n ) ! compute space needed for stdlib${ii}$_${ri}$gebrd call stdlib${ii}$_${ri}$gebrd( mm, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, info & ) lwork_qgebrd=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_${ri}$ormbr call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$),& -1_${ik}$, info ) lwork_qormbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_${ri}$orgbr call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_qorgbr=dum(1_${ik}$) ! compute total workspace needed maxwrk = max( maxwrk, 3_${ik}$*n + lwork_qgebrd ) maxwrk = max( maxwrk, 3_${ik}$*n + lwork_qormbr ) maxwrk = max( maxwrk, 3_${ik}$*n + lwork_qorgbr ) maxwrk = max( maxwrk, bdspac ) maxwrk = max( maxwrk, n*nrhs ) minwrk = max( 3_${ik}$*n + mm, 3_${ik}$*n + nrhs, bdspac ) maxwrk = max( minwrk, maxwrk ) end if if( n>m ) then ! compute workspace needed for stdlib${ii}$_${ri}$bdsqr bdspac = max( 1_${ik}$, 5_${ik}$*m ) minwrk = max( 3_${ik}$*m+nrhs, 3_${ik}$*m+n, bdspac ) if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows ! compute space needed for stdlib${ii}$_${ri}$gelqf call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$),-1_${ik}$, info ) lwork_qgelqf=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_${ri}$gebrd call stdlib${ii}$_${ri}$gebrd( m, m, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & info ) lwork_qgebrd=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_${ri}$ormbr call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_qormbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_${ri}$orgbr call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_qorgbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_${ri}$ormlq call stdlib${ii}$_${ri}$ormlq( 'L', 'T', n, nrhs, m, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$), -& 1_${ik}$, info ) lwork_qormlq=dum(1_${ik}$) ! compute total workspace needed maxwrk = m + lwork_qgelqf maxwrk = max( maxwrk, m*m + 4_${ik}$*m + lwork_qgebrd ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + lwork_qormbr ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + lwork_qorgbr ) maxwrk = max( maxwrk, m*m + m + bdspac ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m + m + m*nrhs ) else maxwrk = max( maxwrk, m*m + 2_${ik}$*m ) end if maxwrk = max( maxwrk, m + lwork_qormlq ) else ! path 2 - underdetermined ! compute space needed for stdlib${ii}$_${ri}$gebrd call stdlib${ii}$_${ri}$gebrd( m, n, a, lda, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & info ) lwork_qgebrd=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_${ri}$ormbr call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'T', m, nrhs, m, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_qormbr=dum(1_${ik}$) ! compute space needed for stdlib${ii}$_${ri}$orgbr call stdlib${ii}$_${ri}$orgbr( 'P', m, n, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_qorgbr=dum(1_${ik}$) maxwrk = 3_${ik}$*m + lwork_qgebrd maxwrk = max( maxwrk, 3_${ik}$*m + lwork_qormbr ) maxwrk = max( maxwrk, 3_${ik}$*m + lwork_qorgbr ) maxwrk = max( maxwrk, bdspac ) maxwrk = max( maxwrk, n*nrhs ) end if end if maxwrk = max( minwrk, maxwrk ) end if work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_${ri}$laset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) call stdlib${ii}$_${ri}$laset( 'F', minmn, 1_${ik}$, zero, zero, s, minmn ) rank = 0_${ik}$ go to 70 end if ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ri}$lange( 'M', m, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! overdetermined case if( m>=n ) then ! path 1 - overdetermined or exactly determined mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns mm = n itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & info ) ! multiply b by transpose(q) ! (workspace: need n+nrhs, prefer n+nrhs*nb) call stdlib${ii}$_${ri}$ormqr( 'L', 'T', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & iwork ), lwork-iwork+1, info ) ! zero out below r if( n>1_${ik}$ )call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) end if ie = 1_${ik}$ itauq = ie + n itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (workspace: need 3*n+mm, prefer 3*n+(mm+n)*nb) call stdlib${ii}$_${ri}$gebrd( mm, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work(& iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r ! (workspace: need 3*n+nrhs, prefer 3*n+nrhs*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in a ! (workspace: need 4*n-1, prefer 3*n+(n-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) iwork = ie + n ! perform bidiagonal qr iteration ! multiply b by transpose of left singular vectors ! compute right singular vectors in a ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', n, n, 0_${ik}$, nrhs, s, work( ie ), a, lda, dum,1_${ik}$, b, ldb, work( & iwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_${ri}$rscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_${ri}$laset( 'F', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors ! (workspace: need n, prefer n*nrhs) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'T', 'N', n, nrhs, n, one, a, lda, b, ldb, zero,work, ldb ) call stdlib${ii}$_${ri}$lacpy( 'G', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_${ri}$gemm( 'T', 'N', n, bl, n, one, a, lda, b( 1_${ik}$, i ),ldb, zero, work,& n ) call stdlib${ii}$_${ri}$lacpy( 'G', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_${ri}$gemv( 'T', n, n, one, a, lda, b, 1_${ik}$, zero, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if else if( n>=mnthr .and. lwork>=4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) then ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm ldwork = m if( lwork>=max( 4_${ik}$*m+m*lda+max( m, 2_${ik}$*m-4, nrhs, n-3*m ),m*lda+m+m*nrhs ) )ldwork = & lda itau = 1_${ik}$ iwork = m + 1_${ik}$ ! compute a=l*q ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, info ) il = iwork ! copy l to work(il), zeroing out above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, work( il+ldwork ),ldwork ) ie = il + ldwork*m itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(il) ! (workspace: need m*m+5*m, prefer m*m+4*m+2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, work( il ), ldwork, s, work( ie ),work( itauq ), work( & itaup ), work( iwork ),lwork-iwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l ! (workspace: need m*m+4*m+nrhs, prefer m*m+4*m+nrhs*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'T', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( iwork ),lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in work(il) ! (workspace: need m*m+5*m-1, prefer m*m+4*m+(m-1)*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, work( il ), ldwork, work( itaup ),work( iwork ), & lwork-iwork+1, info ) iwork = ie + m ! perform bidiagonal qr iteration, ! computing right singular vectors of l in work(il) and ! multiplying b by transpose of left singular vectors ! (workspace: need m*m+m+bdspac) call stdlib${ii}$_${ri}$bdsqr( 'U', m, m, 0_${ik}$, nrhs, s, work( ie ), work( il ),ldwork, a, lda, b,& ldb, work( iwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_${ri}$rscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_${ri}$laset( 'F', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) end if end do iwork = ie ! multiply b by right singular vectors of l in work(il) ! (workspace: need m*m+2*m, prefer m*m+m+m*nrhs) if( lwork>=ldb*nrhs+iwork-1 .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'T', 'N', m, nrhs, m, one, work( il ), ldwork,b, ldb, zero, & work( iwork ), ldb ) call stdlib${ii}$_${ri}$lacpy( 'G', m, nrhs, work( iwork ), ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = ( lwork-iwork+1 ) / m do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_${ri}$gemm( 'T', 'N', m, bl, m, one, work( il ), ldwork,b( 1_${ik}$, i ), ldb,& zero, work( iwork ), m ) call stdlib${ii}$_${ri}$lacpy( 'G', m, bl, work( iwork ), m, b( 1_${ik}$, i ),ldb ) end do else call stdlib${ii}$_${ri}$gemv( 'T', m, m, one, work( il ), ldwork, b( 1_${ik}$, 1_${ik}$ ),1_${ik}$, zero, work( & iwork ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( m, work( iwork ), 1_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) end if ! zero out below first m rows of b call stdlib${ii}$_${ri}$laset( 'F', n-m, nrhs, zero, zero, b( m+1, 1_${ik}$ ), ldb ) iwork = itau + m ! multiply transpose(q) by b ! (workspace: need m+nrhs, prefer m+nrhs*nb) call stdlib${ii}$_${ri}$ormlq( 'L', 'T', n, nrhs, m, a, lda, work( itau ), b,ldb, work( iwork )& , lwork-iwork+1, info ) else ! path 2 - remaining underdetermined cases ie = 1_${ik}$ itauq = ie + m itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (workspace: need 3*m+n, prefer 3*m+(m+n)*nb) call stdlib${ii}$_${ri}$gebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work( & iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors ! (workspace: need 3*m+nrhs, prefer 3*m+nrhs*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors in a ! (workspace: need 4*m, prefer 3*m+m*nb) call stdlib${ii}$_${ri}$orgbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) iwork = ie + m ! perform bidiagonal qr iteration, ! computing right singular vectors of a in a and ! multiplying b by transpose of left singular vectors ! (workspace: need bdspac) call stdlib${ii}$_${ri}$bdsqr( 'L', m, n, 0_${ik}$, nrhs, s, work( ie ), a, lda, dum,1_${ik}$, b, ldb, work( & iwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_${ri}$rscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_${ri}$laset( 'F', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors of a ! (workspace: need n, prefer n*nrhs) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'T', 'N', n, nrhs, m, one, a, lda, b, ldb, zero,work, ldb ) call stdlib${ii}$_${ri}$lacpy( 'F', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_${ri}$gemm( 'T', 'N', n, bl, m, one, a, lda, b( 1_${ik}$, i ),ldb, zero, work,& n ) call stdlib${ii}$_${ri}$lacpy( 'F', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_${ri}$gemv( 'T', m, n, one, a, lda, b, 1_${ik}$, zero, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 70 continue work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ri}$gelss #:endif #:endfor module subroutine stdlib${ii}$_cgelss( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, rwork, & !! CGELSS computes the minimum norm solution to a complex linear !! least squares problem: !! Minimize 2-norm(| b - A*x |). !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix !! X. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(sp), intent(in) :: rcond ! Array Arguments real(sp), intent(out) :: rwork(*), s(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: bl, chunk, i, iascl, ibscl, ie, il, irwork, itau, itaup, itauq, iwork, & ldwork, maxmn, maxwrk, minmn, minwrk, mm, mnthr integer(${ik}$) :: lwork_cgeqrf, lwork_cunmqr, lwork_cgebrd, lwork_cunmbr, lwork_cungbr, & lwork_cunmlq, lwork_cgelqf real(sp) :: anrm, bignum, bnrm, eps, sfmin, smlnum, thr ! Local Arrays complex(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ minmn = min( m, n ) maxmn = max( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then mm = m mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'CGELSS', ' ', m, n, nrhs, -1_${ik}$ ) if( m>=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than ! columns ! compute space needed for stdlib${ii}$_cgeqrf call stdlib${ii}$_cgeqrf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, info ) lwork_cgeqrf = real( dum(1_${ik}$),KIND=sp) ! compute space needed for stdlib${ii}$_cunmqr call stdlib${ii}$_cunmqr( 'L', 'C', m, nrhs, n, a, lda, dum(1_${ik}$), b,ldb, dum(1_${ik}$), -1_${ik}$, & info ) lwork_cunmqr = real( dum(1_${ik}$),KIND=sp) mm = n maxwrk = max( maxwrk, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', m,n, -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, n + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', 'LC',m, nrhs, n, -& 1_${ik}$ ) ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined ! compute space needed for stdlib${ii}$_cgebrd call stdlib${ii}$_cgebrd( mm, n, a, lda, s, s, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),-1_${ik}$, info ) lwork_cgebrd = real( dum(1_${ik}$),KIND=sp) ! compute space needed for stdlib${ii}$_cunmbr call stdlib${ii}$_cunmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$),& -1_${ik}$, info ) lwork_cunmbr = real( dum(1_${ik}$),KIND=sp) ! compute space needed for stdlib${ii}$_cungbr call stdlib${ii}$_cungbr( 'P', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_cungbr = real( dum(1_${ik}$),KIND=sp) ! compute total workspace needed maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cgebrd ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cunmbr ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cungbr ) maxwrk = max( maxwrk, n*nrhs ) minwrk = 2_${ik}$*n + max( nrhs, m ) end if if( n>m ) then minwrk = 2_${ik}$*m + max( nrhs, n ) if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows ! compute space needed for stdlib${ii}$_cgelqf call stdlib${ii}$_cgelqf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$),-1_${ik}$, info ) lwork_cgelqf = real( dum(1_${ik}$),KIND=sp) ! compute space needed for stdlib${ii}$_cgebrd call stdlib${ii}$_cgebrd( m, m, a, lda, s, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_cgebrd = real( dum(1_${ik}$),KIND=sp) ! compute space needed for stdlib${ii}$_cunmbr call stdlib${ii}$_cunmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_cunmbr = real( dum(1_${ik}$),KIND=sp) ! compute space needed for stdlib${ii}$_cungbr call stdlib${ii}$_cungbr( 'P', m, m, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_cungbr = real( dum(1_${ik}$),KIND=sp) ! compute space needed for stdlib${ii}$_cunmlq call stdlib${ii}$_cunmlq( 'L', 'C', n, nrhs, m, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$), -& 1_${ik}$, info ) lwork_cunmlq = real( dum(1_${ik}$),KIND=sp) ! compute total workspace needed maxwrk = m + lwork_cgelqf maxwrk = max( maxwrk, 3_${ik}$*m + m*m + lwork_cgebrd ) maxwrk = max( maxwrk, 3_${ik}$*m + m*m + lwork_cunmbr ) maxwrk = max( maxwrk, 3_${ik}$*m + m*m + lwork_cungbr ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m + m + m*nrhs ) else maxwrk = max( maxwrk, m*m + 2_${ik}$*m ) end if maxwrk = max( maxwrk, m + lwork_cunmlq ) else ! path 2 - underdetermined ! compute space needed for stdlib${ii}$_cgebrd call stdlib${ii}$_cgebrd( m, n, a, lda, s, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_cgebrd = real( dum(1_${ik}$),KIND=sp) ! compute space needed for stdlib${ii}$_cunmbr call stdlib${ii}$_cunmbr( 'Q', 'L', 'C', m, nrhs, m, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_cunmbr = real( dum(1_${ik}$),KIND=sp) ! compute space needed for stdlib${ii}$_cungbr call stdlib${ii}$_cungbr( 'P', m, n, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_cungbr = real( dum(1_${ik}$),KIND=sp) maxwrk = 2_${ik}$*m + lwork_cgebrd maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cunmbr ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cungbr ) maxwrk = max( maxwrk, n*nrhs ) end if end if maxwrk = max( minwrk, maxwrk ) end if work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_claset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) call stdlib${ii}$_slaset( 'F', minmn, 1_${ik}$, zero, zero, s, minmn ) rank = 0_${ik}$ go to 70 end if ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_clange( 'M', m, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! overdetermined case if( m>=n ) then ! path 1 - overdetermined or exactly determined mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns mm = n itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & info ) ! multiply b by transpose(q) ! (cworkspace: need n+nrhs, prefer n+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_cunmqr( 'L', 'C', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & iwork ), lwork-iwork+1, info ) ! zero out below r if( n>1_${ik}$ )call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (cworkspace: need 2*n+mm, prefer 2*n+(mm+n)*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r ! (cworkspace: need 2*n+nrhs, prefer 2*n+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_cunmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) irwork = ie + n ! perform bidiagonal qr iteration ! multiply b by transpose of left singular vectors ! compute right singular vectors in a ! (cworkspace: none) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', n, n, 0_${ik}$, nrhs, s, rwork( ie ), a, lda, dum,1_${ik}$, b, ldb, & rwork( irwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_csrscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_claset( 'F', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors ! (cworkspace: need n, prefer n*nrhs) ! (rworkspace: none) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_cgemm( 'C', 'N', n, nrhs, n, cone, a, lda, b, ldb,czero, work, ldb ) call stdlib${ii}$_clacpy( 'G', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_cgemm( 'C', 'N', n, bl, n, cone, a, lda, b( 1_${ik}$, i ),ldb, czero, & work, n ) call stdlib${ii}$_clacpy( 'G', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_cgemv( 'C', n, n, cone, a, lda, b, 1_${ik}$, czero, work, 1_${ik}$ ) call stdlib${ii}$_ccopy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if else if( n>=mnthr .and. lwork>=3_${ik}$*m+m*m+max( m, nrhs, n-2*m ) )then ! underdetermined case, m much less than n ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm ldwork = m if( lwork>=3_${ik}$*m+m*lda+max( m, nrhs, n-2*m ) )ldwork = lda itau = 1_${ik}$ iwork = m + 1_${ik}$ ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: none) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, info ) il = iwork ! copy l to work(il), zeroing out above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero, work( il+ldwork ),ldwork ) ie = 1_${ik}$ itauq = il + ldwork*m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(il) ! (cworkspace: need m*m+4*m, prefer m*m+3*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_cgebrd( m, m, work( il ), ldwork, s, rwork( ie ),work( itauq ), work( & itaup ), work( iwork ),lwork-iwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l ! (cworkspace: need m*m+3*m+nrhs, prefer m*m+3*m+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_cunmbr( 'Q', 'L', 'C', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( iwork ),lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in work(il) ! (cworkspace: need m*m+4*m-1, prefer m*m+3*m+(m-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cungbr( 'P', m, m, m, work( il ), ldwork, work( itaup ),work( iwork ), & lwork-iwork+1, info ) irwork = ie + m ! perform bidiagonal qr iteration, computing right singular ! vectors of l in work(il) and multiplying b by transpose of ! left singular vectors ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'U', m, m, 0_${ik}$, nrhs, s, rwork( ie ), work( il ),ldwork, a, lda, & b, ldb, rwork( irwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_csrscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_claset( 'F', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) end if end do iwork = il + m*ldwork ! multiply b by right singular vectors of l in work(il) ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nrhs) ! (rworkspace: none) if( lwork>=ldb*nrhs+iwork-1 .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_cgemm( 'C', 'N', m, nrhs, m, cone, work( il ), ldwork,b, ldb, czero, & work( iwork ), ldb ) call stdlib${ii}$_clacpy( 'G', m, nrhs, work( iwork ), ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = ( lwork-iwork+1 ) / m do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_cgemm( 'C', 'N', m, bl, m, cone, work( il ), ldwork,b( 1_${ik}$, i ), & ldb, czero, work( iwork ), m ) call stdlib${ii}$_clacpy( 'G', m, bl, work( iwork ), m, b( 1_${ik}$, i ),ldb ) end do else call stdlib${ii}$_cgemv( 'C', m, m, cone, work( il ), ldwork, b( 1_${ik}$, 1_${ik}$ ),1_${ik}$, czero, work(& iwork ), 1_${ik}$ ) call stdlib${ii}$_ccopy( m, work( iwork ), 1_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) end if ! zero out below first m rows of b call stdlib${ii}$_claset( 'F', n-m, nrhs, czero, czero, b( m+1, 1_${ik}$ ), ldb ) iwork = itau + m ! multiply transpose(q) by b ! (cworkspace: need m+nrhs, prefer m+nhrs*nb) ! (rworkspace: none) call stdlib${ii}$_cunmlq( 'L', 'C', n, nrhs, m, a, lda, work( itau ), b,ldb, work( iwork )& , lwork-iwork+1, info ) else ! path 2 - remaining underdetermined cases ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (cworkspace: need 3*m, prefer 2*m+(m+n)*nb) ! (rworkspace: need n) call stdlib${ii}$_cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), work(& iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors ! (cworkspace: need 2*m+nrhs, prefer 2*m+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_cunmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: none) call stdlib${ii}$_cungbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) irwork = ie + m ! perform bidiagonal qr iteration, ! computing right singular vectors of a in a and ! multiplying b by transpose of left singular vectors ! (cworkspace: none) ! (rworkspace: need bdspac) call stdlib${ii}$_cbdsqr( 'L', m, n, 0_${ik}$, nrhs, s, rwork( ie ), a, lda, dum,1_${ik}$, b, ldb, & rwork( irwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_csrscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_claset( 'F', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors of a ! (cworkspace: need n, prefer n*nrhs) ! (rworkspace: none) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_cgemm( 'C', 'N', n, nrhs, m, cone, a, lda, b, ldb,czero, work, ldb ) call stdlib${ii}$_clacpy( 'G', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_cgemm( 'C', 'N', n, bl, m, cone, a, lda, b( 1_${ik}$, i ),ldb, czero, & work, n ) call stdlib${ii}$_clacpy( 'F', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_cgemv( 'C', m, n, cone, a, lda, b, 1_${ik}$, czero, work, 1_${ik}$ ) call stdlib${ii}$_ccopy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 70 continue work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_cgelss module subroutine stdlib${ii}$_zgelss( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, rwork, & !! ZGELSS computes the minimum norm solution to a complex linear !! least squares problem: !! Minimize 2-norm(| b - A*x |). !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix !! X. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(dp), intent(in) :: rcond ! Array Arguments real(dp), intent(out) :: rwork(*), s(*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: bl, chunk, i, iascl, ibscl, ie, il, irwork, itau, itaup, itauq, iwork, & ldwork, maxmn, maxwrk, minmn, minwrk, mm, mnthr integer(${ik}$) :: lwork_zgeqrf, lwork_zunmqr, lwork_zgebrd, lwork_zunmbr, lwork_zungbr, & lwork_zunmlq, lwork_zgelqf real(dp) :: anrm, bignum, bnrm, eps, sfmin, smlnum, thr ! Local Arrays complex(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ minmn = min( m, n ) maxmn = max( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then mm = m mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'ZGELSS', ' ', m, n, nrhs, -1_${ik}$ ) if( m>=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than ! columns ! compute space needed for stdlib${ii}$_zgeqrf call stdlib${ii}$_zgeqrf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, info ) lwork_zgeqrf = real( dum(1_${ik}$),KIND=dp) ! compute space needed for stdlib${ii}$_zunmqr call stdlib${ii}$_zunmqr( 'L', 'C', m, nrhs, n, a, lda, dum(1_${ik}$), b,ldb, dum(1_${ik}$), -1_${ik}$, & info ) lwork_zunmqr = real( dum(1_${ik}$),KIND=dp) mm = n maxwrk = max( maxwrk, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', m,n, -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, n + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', 'LC',m, nrhs, n, -& 1_${ik}$ ) ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined ! compute space needed for stdlib${ii}$_zgebrd call stdlib${ii}$_zgebrd( mm, n, a, lda, s, s, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),-1_${ik}$, info ) lwork_zgebrd = real( dum(1_${ik}$),KIND=dp) ! compute space needed for stdlib${ii}$_zunmbr call stdlib${ii}$_zunmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$),& -1_${ik}$, info ) lwork_zunmbr = real( dum(1_${ik}$),KIND=dp) ! compute space needed for stdlib${ii}$_zungbr call stdlib${ii}$_zungbr( 'P', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_zungbr = real( dum(1_${ik}$),KIND=dp) ! compute total workspace needed maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zgebrd ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zunmbr ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zungbr ) maxwrk = max( maxwrk, n*nrhs ) minwrk = 2_${ik}$*n + max( nrhs, m ) end if if( n>m ) then minwrk = 2_${ik}$*m + max( nrhs, n ) if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows ! compute space needed for stdlib${ii}$_zgelqf call stdlib${ii}$_zgelqf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$),-1_${ik}$, info ) lwork_zgelqf = real( dum(1_${ik}$),KIND=dp) ! compute space needed for stdlib${ii}$_zgebrd call stdlib${ii}$_zgebrd( m, m, a, lda, s, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_zgebrd = real( dum(1_${ik}$),KIND=dp) ! compute space needed for stdlib${ii}$_zunmbr call stdlib${ii}$_zunmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_zunmbr = real( dum(1_${ik}$),KIND=dp) ! compute space needed for stdlib${ii}$_zungbr call stdlib${ii}$_zungbr( 'P', m, m, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_zungbr = real( dum(1_${ik}$),KIND=dp) ! compute space needed for stdlib${ii}$_zunmlq call stdlib${ii}$_zunmlq( 'L', 'C', n, nrhs, m, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$), -& 1_${ik}$, info ) lwork_zunmlq = real( dum(1_${ik}$),KIND=dp) ! compute total workspace needed maxwrk = m + lwork_zgelqf maxwrk = max( maxwrk, 3_${ik}$*m + m*m + lwork_zgebrd ) maxwrk = max( maxwrk, 3_${ik}$*m + m*m + lwork_zunmbr ) maxwrk = max( maxwrk, 3_${ik}$*m + m*m + lwork_zungbr ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m + m + m*nrhs ) else maxwrk = max( maxwrk, m*m + 2_${ik}$*m ) end if maxwrk = max( maxwrk, m + lwork_zunmlq ) else ! path 2 - underdetermined ! compute space needed for stdlib${ii}$_zgebrd call stdlib${ii}$_zgebrd( m, n, a, lda, s, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_zgebrd = real( dum(1_${ik}$),KIND=dp) ! compute space needed for stdlib${ii}$_zunmbr call stdlib${ii}$_zunmbr( 'Q', 'L', 'C', m, nrhs, m, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_zunmbr = real( dum(1_${ik}$),KIND=dp) ! compute space needed for stdlib${ii}$_zungbr call stdlib${ii}$_zungbr( 'P', m, n, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_zungbr = real( dum(1_${ik}$),KIND=dp) maxwrk = 2_${ik}$*m + lwork_zgebrd maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zunmbr ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zungbr ) maxwrk = max( maxwrk, n*nrhs ) end if end if maxwrk = max( minwrk, maxwrk ) end if work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_zlaset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) call stdlib${ii}$_dlaset( 'F', minmn, 1_${ik}$, zero, zero, s, minmn ) rank = 0_${ik}$ go to 70 end if ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_zlange( 'M', m, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! overdetermined case if( m>=n ) then ! path 1 - overdetermined or exactly determined mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns mm = n itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & info ) ! multiply b by transpose(q) ! (cworkspace: need n+nrhs, prefer n+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_zunmqr( 'L', 'C', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & iwork ), lwork-iwork+1, info ) ! zero out below r if( n>1_${ik}$ )call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (cworkspace: need 2*n+mm, prefer 2*n+(mm+n)*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r ! (cworkspace: need 2*n+nrhs, prefer 2*n+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_zunmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) irwork = ie + n ! perform bidiagonal qr iteration ! multiply b by transpose of left singular vectors ! compute right singular vectors in a ! (cworkspace: none) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', n, n, 0_${ik}$, nrhs, s, rwork( ie ), a, lda, dum,1_${ik}$, b, ldb, & rwork( irwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_zdrscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_zlaset( 'F', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors ! (cworkspace: need n, prefer n*nrhs) ! (rworkspace: none) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_zgemm( 'C', 'N', n, nrhs, n, cone, a, lda, b, ldb,czero, work, ldb ) call stdlib${ii}$_zlacpy( 'G', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_zgemm( 'C', 'N', n, bl, n, cone, a, lda, b( 1_${ik}$, i ),ldb, czero, & work, n ) call stdlib${ii}$_zlacpy( 'G', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_zgemv( 'C', n, n, cone, a, lda, b, 1_${ik}$, czero, work, 1_${ik}$ ) call stdlib${ii}$_zcopy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if else if( n>=mnthr .and. lwork>=3_${ik}$*m+m*m+max( m, nrhs, n-2*m ) )then ! underdetermined case, m much less than n ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm ldwork = m if( lwork>=3_${ik}$*m+m*lda+max( m, nrhs, n-2*m ) )ldwork = lda itau = 1_${ik}$ iwork = m + 1_${ik}$ ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: none) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, info ) il = iwork ! copy l to work(il), zeroing out above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero, work( il+ldwork ),ldwork ) ie = 1_${ik}$ itauq = il + ldwork*m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(il) ! (cworkspace: need m*m+4*m, prefer m*m+3*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_zgebrd( m, m, work( il ), ldwork, s, rwork( ie ),work( itauq ), work( & itaup ), work( iwork ),lwork-iwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l ! (cworkspace: need m*m+3*m+nrhs, prefer m*m+3*m+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_zunmbr( 'Q', 'L', 'C', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( iwork ),lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in work(il) ! (cworkspace: need m*m+4*m-1, prefer m*m+3*m+(m-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zungbr( 'P', m, m, m, work( il ), ldwork, work( itaup ),work( iwork ), & lwork-iwork+1, info ) irwork = ie + m ! perform bidiagonal qr iteration, computing right singular ! vectors of l in work(il) and multiplying b by transpose of ! left singular vectors ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'U', m, m, 0_${ik}$, nrhs, s, rwork( ie ), work( il ),ldwork, a, lda, & b, ldb, rwork( irwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_zdrscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_zlaset( 'F', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) end if end do iwork = il + m*ldwork ! multiply b by right singular vectors of l in work(il) ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nrhs) ! (rworkspace: none) if( lwork>=ldb*nrhs+iwork-1 .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_zgemm( 'C', 'N', m, nrhs, m, cone, work( il ), ldwork,b, ldb, czero, & work( iwork ), ldb ) call stdlib${ii}$_zlacpy( 'G', m, nrhs, work( iwork ), ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = ( lwork-iwork+1 ) / m do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_zgemm( 'C', 'N', m, bl, m, cone, work( il ), ldwork,b( 1_${ik}$, i ), & ldb, czero, work( iwork ), m ) call stdlib${ii}$_zlacpy( 'G', m, bl, work( iwork ), m, b( 1_${ik}$, i ),ldb ) end do else call stdlib${ii}$_zgemv( 'C', m, m, cone, work( il ), ldwork, b( 1_${ik}$, 1_${ik}$ ),1_${ik}$, czero, work(& iwork ), 1_${ik}$ ) call stdlib${ii}$_zcopy( m, work( iwork ), 1_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) end if ! zero out below first m rows of b call stdlib${ii}$_zlaset( 'F', n-m, nrhs, czero, czero, b( m+1, 1_${ik}$ ), ldb ) iwork = itau + m ! multiply transpose(q) by b ! (cworkspace: need m+nrhs, prefer m+nhrs*nb) ! (rworkspace: none) call stdlib${ii}$_zunmlq( 'L', 'C', n, nrhs, m, a, lda, work( itau ), b,ldb, work( iwork )& , lwork-iwork+1, info ) else ! path 2 - remaining underdetermined cases ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (cworkspace: need 3*m, prefer 2*m+(m+n)*nb) ! (rworkspace: need n) call stdlib${ii}$_zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), work(& iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors ! (cworkspace: need 2*m+nrhs, prefer 2*m+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_zunmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: none) call stdlib${ii}$_zungbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) irwork = ie + m ! perform bidiagonal qr iteration, ! computing right singular vectors of a in a and ! multiplying b by transpose of left singular vectors ! (cworkspace: none) ! (rworkspace: need bdspac) call stdlib${ii}$_zbdsqr( 'L', m, n, 0_${ik}$, nrhs, s, rwork( ie ), a, lda, dum,1_${ik}$, b, ldb, & rwork( irwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_zdrscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_zlaset( 'F', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors of a ! (cworkspace: need n, prefer n*nrhs) ! (rworkspace: none) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_zgemm( 'C', 'N', n, nrhs, m, cone, a, lda, b, ldb,czero, work, ldb ) call stdlib${ii}$_zlacpy( 'G', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_zgemm( 'C', 'N', n, bl, m, cone, a, lda, b( 1_${ik}$, i ),ldb, czero, & work, n ) call stdlib${ii}$_zlacpy( 'F', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_zgemv( 'C', m, n, cone, a, lda, b, 1_${ik}$, czero, work, 1_${ik}$ ) call stdlib${ii}$_zcopy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 70 continue work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_zgelss #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$gelss( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, rwork, & !! ZGELSS: computes the minimum norm solution to a complex linear !! least squares problem: !! Minimize 2-norm(| b - A*x |). !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix !! X. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(${ck}$), intent(in) :: rcond ! Array Arguments real(${ck}$), intent(out) :: rwork(*), s(*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: bl, chunk, i, iascl, ibscl, ie, il, irwork, itau, itaup, itauq, iwork, & ldwork, maxmn, maxwrk, minmn, minwrk, mm, mnthr integer(${ik}$) :: lwork_wgeqrf, lwork_wunmqr, lwork_wgebrd, lwork_wunmbr, lwork_wungbr, & lwork_wunmlq, lwork_wgelqf real(${ck}$) :: anrm, bignum, bnrm, eps, sfmin, smlnum, thr ! Local Arrays complex(${ck}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ minmn = min( m, n ) maxmn = max( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then mm = m mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'ZGELSS', ' ', m, n, nrhs, -1_${ik}$ ) if( m>=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than ! columns ! compute space needed for stdlib${ii}$_${ci}$geqrf call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, info ) lwork_wgeqrf = real( dum(1_${ik}$),KIND=${ck}$) ! compute space needed for stdlib${ii}$_${ci}$unmqr call stdlib${ii}$_${ci}$unmqr( 'L', 'C', m, nrhs, n, a, lda, dum(1_${ik}$), b,ldb, dum(1_${ik}$), -1_${ik}$, & info ) lwork_wunmqr = real( dum(1_${ik}$),KIND=${ck}$) mm = n maxwrk = max( maxwrk, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', m,n, -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, n + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', 'LC',m, nrhs, n, -& 1_${ik}$ ) ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined ! compute space needed for stdlib${ii}$_${ci}$gebrd call stdlib${ii}$_${ci}$gebrd( mm, n, a, lda, s, s, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),-1_${ik}$, info ) lwork_wgebrd = real( dum(1_${ik}$),KIND=${ck}$) ! compute space needed for stdlib${ii}$_${ci}$unmbr call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$),& -1_${ik}$, info ) lwork_wunmbr = real( dum(1_${ik}$),KIND=${ck}$) ! compute space needed for stdlib${ii}$_${ci}$ungbr call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_wungbr = real( dum(1_${ik}$),KIND=${ck}$) ! compute total workspace needed maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wgebrd ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wunmbr ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wungbr ) maxwrk = max( maxwrk, n*nrhs ) minwrk = 2_${ik}$*n + max( nrhs, m ) end if if( n>m ) then minwrk = 2_${ik}$*m + max( nrhs, n ) if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows ! compute space needed for stdlib${ii}$_${ci}$gelqf call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, dum(1_${ik}$), dum(1_${ik}$),-1_${ik}$, info ) lwork_wgelqf = real( dum(1_${ik}$),KIND=${ck}$) ! compute space needed for stdlib${ii}$_${ci}$gebrd call stdlib${ii}$_${ci}$gebrd( m, m, a, lda, s, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_wgebrd = real( dum(1_${ik}$),KIND=${ck}$) ! compute space needed for stdlib${ii}$_${ci}$unmbr call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_wunmbr = real( dum(1_${ik}$),KIND=${ck}$) ! compute space needed for stdlib${ii}$_${ci}$ungbr call stdlib${ii}$_${ci}$ungbr( 'P', m, m, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_wungbr = real( dum(1_${ik}$),KIND=${ck}$) ! compute space needed for stdlib${ii}$_${ci}$unmlq call stdlib${ii}$_${ci}$unmlq( 'L', 'C', n, nrhs, m, a, lda, dum(1_${ik}$),b, ldb, dum(1_${ik}$), -& 1_${ik}$, info ) lwork_wunmlq = real( dum(1_${ik}$),KIND=${ck}$) ! compute total workspace needed maxwrk = m + lwork_wgelqf maxwrk = max( maxwrk, 3_${ik}$*m + m*m + lwork_wgebrd ) maxwrk = max( maxwrk, 3_${ik}$*m + m*m + lwork_wunmbr ) maxwrk = max( maxwrk, 3_${ik}$*m + m*m + lwork_wungbr ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m + m + m*nrhs ) else maxwrk = max( maxwrk, m*m + 2_${ik}$*m ) end if maxwrk = max( maxwrk, m + lwork_wunmlq ) else ! path 2 - underdetermined ! compute space needed for stdlib${ii}$_${ci}$gebrd call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_wgebrd = real( dum(1_${ik}$),KIND=${ck}$) ! compute space needed for stdlib${ii}$_${ci}$unmbr call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'C', m, nrhs, m, a, lda,dum(1_${ik}$), b, ldb, dum(& 1_${ik}$), -1_${ik}$, info ) lwork_wunmbr = real( dum(1_${ik}$),KIND=${ck}$) ! compute space needed for stdlib${ii}$_${ci}$ungbr call stdlib${ii}$_${ci}$ungbr( 'P', m, n, m, a, lda, dum(1_${ik}$),dum(1_${ik}$), -1_${ik}$, info ) lwork_wungbr = real( dum(1_${ik}$),KIND=${ck}$) maxwrk = 2_${ik}$*m + lwork_wgebrd maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wunmbr ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wungbr ) maxwrk = max( maxwrk, n*nrhs ) end if end if maxwrk = max( minwrk, maxwrk ) end if work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_${ci}$laset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) call stdlib${ii}$_${c2ri(ci)}$laset( 'F', minmn, 1_${ik}$, zero, zero, s, minmn ) rank = 0_${ik}$ go to 70 end if ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ci}$lange( 'M', m, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! overdetermined case if( m>=n ) then ! path 1 - overdetermined or exactly determined mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns mm = n itau = 1_${ik}$ iwork = itau + n ! compute a=q*r ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, & info ) ! multiply b by transpose(q) ! (cworkspace: need n+nrhs, prefer n+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unmqr( 'L', 'C', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & iwork ), lwork-iwork+1, info ) ! zero out below r if( n>1_${ik}$ )call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n iwork = itaup + n ! bidiagonalize r in a ! (cworkspace: need 2*n+mm, prefer 2*n+(mm+n)*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r ! (cworkspace: need 2*n+nrhs, prefer 2*n+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in a ! (cworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) irwork = ie + n ! perform bidiagonal qr iteration ! multiply b by transpose of left singular vectors ! compute right singular vectors in a ! (cworkspace: none) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', n, n, 0_${ik}$, nrhs, s, rwork( ie ), a, lda, dum,1_${ik}$, b, ldb, & rwork( irwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_${ci}$drscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_${ci}$laset( 'F', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors ! (cworkspace: need n, prefer n*nrhs) ! (rworkspace: none) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'C', 'N', n, nrhs, n, cone, a, lda, b, ldb,czero, work, ldb ) call stdlib${ii}$_${ci}$lacpy( 'G', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_${ci}$gemm( 'C', 'N', n, bl, n, cone, a, lda, b( 1_${ik}$, i ),ldb, czero, & work, n ) call stdlib${ii}$_${ci}$lacpy( 'G', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_${ci}$gemv( 'C', n, n, cone, a, lda, b, 1_${ik}$, czero, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$copy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if else if( n>=mnthr .and. lwork>=3_${ik}$*m+m*m+max( m, nrhs, n-2*m ) )then ! underdetermined case, m much less than n ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm ldwork = m if( lwork>=3_${ik}$*m+m*lda+max( m, nrhs, n-2*m ) )ldwork = lda itau = 1_${ik}$ iwork = m + 1_${ik}$ ! compute a=l*q ! (cworkspace: need 2*m, prefer m+m*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ), work( iwork ),lwork-iwork+1, info ) il = iwork ! copy l to work(il), zeroing out above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero, work( il+ldwork ),ldwork ) ie = 1_${ik}$ itauq = il + ldwork*m itaup = itauq + m iwork = itaup + m ! bidiagonalize l in work(il) ! (cworkspace: need m*m+4*m, prefer m*m+3*m+2*m*nb) ! (rworkspace: need m) call stdlib${ii}$_${ci}$gebrd( m, m, work( il ), ldwork, s, rwork( ie ),work( itauq ), work( & itaup ), work( iwork ),lwork-iwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l ! (cworkspace: need m*m+3*m+nrhs, prefer m*m+3*m+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'C', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( iwork ),lwork-iwork+1, info ) ! generate right bidiagonalizing vectors of r in work(il) ! (cworkspace: need m*m+4*m-1, prefer m*m+3*m+(m-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$ungbr( 'P', m, m, m, work( il ), ldwork, work( itaup ),work( iwork ), & lwork-iwork+1, info ) irwork = ie + m ! perform bidiagonal qr iteration, computing right singular ! vectors of l in work(il) and multiplying b by transpose of ! left singular vectors ! (cworkspace: need m*m) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'U', m, m, 0_${ik}$, nrhs, s, rwork( ie ), work( il ),ldwork, a, lda, & b, ldb, rwork( irwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_${ci}$drscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_${ci}$laset( 'F', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) end if end do iwork = il + m*ldwork ! multiply b by right singular vectors of l in work(il) ! (cworkspace: need m*m+2*m, prefer m*m+m+m*nrhs) ! (rworkspace: none) if( lwork>=ldb*nrhs+iwork-1 .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'C', 'N', m, nrhs, m, cone, work( il ), ldwork,b, ldb, czero, & work( iwork ), ldb ) call stdlib${ii}$_${ci}$lacpy( 'G', m, nrhs, work( iwork ), ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = ( lwork-iwork+1 ) / m do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_${ci}$gemm( 'C', 'N', m, bl, m, cone, work( il ), ldwork,b( 1_${ik}$, i ), & ldb, czero, work( iwork ), m ) call stdlib${ii}$_${ci}$lacpy( 'G', m, bl, work( iwork ), m, b( 1_${ik}$, i ),ldb ) end do else call stdlib${ii}$_${ci}$gemv( 'C', m, m, cone, work( il ), ldwork, b( 1_${ik}$, 1_${ik}$ ),1_${ik}$, czero, work(& iwork ), 1_${ik}$ ) call stdlib${ii}$_${ci}$copy( m, work( iwork ), 1_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) end if ! zero out below first m rows of b call stdlib${ii}$_${ci}$laset( 'F', n-m, nrhs, czero, czero, b( m+1, 1_${ik}$ ), ldb ) iwork = itau + m ! multiply transpose(q) by b ! (cworkspace: need m+nrhs, prefer m+nhrs*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unmlq( 'L', 'C', n, nrhs, m, a, lda, work( itau ), b,ldb, work( iwork )& , lwork-iwork+1, info ) else ! path 2 - remaining underdetermined cases ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m iwork = itaup + m ! bidiagonalize a ! (cworkspace: need 3*m, prefer 2*m+(m+n)*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), work(& iwork ), lwork-iwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors ! (cworkspace: need 2*m+nrhs, prefer 2*m+nrhs*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & iwork ), lwork-iwork+1, info ) ! generate right bidiagonalizing vectors in a ! (cworkspace: need 3*m, prefer 2*m+m*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$ungbr( 'P', m, n, m, a, lda, work( itaup ),work( iwork ), lwork-iwork+& 1_${ik}$, info ) irwork = ie + m ! perform bidiagonal qr iteration, ! computing right singular vectors of a in a and ! multiplying b by transpose of left singular vectors ! (cworkspace: none) ! (rworkspace: need bdspac) call stdlib${ii}$_${ci}$bdsqr( 'L', m, n, 0_${ik}$, nrhs, s, rwork( ie ), a, lda, dum,1_${ik}$, b, ldb, & rwork( irwork ), info ) if( info/=0 )go to 70 ! multiply b by reciprocals of singular values thr = max( rcond*s( 1_${ik}$ ), sfmin ) if( rcondthr ) then call stdlib${ii}$_${ci}$drscl( nrhs, s( i ), b( i, 1_${ik}$ ), ldb ) rank = rank + 1_${ik}$ else call stdlib${ii}$_${ci}$laset( 'F', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) end if end do ! multiply b by right singular vectors of a ! (cworkspace: need n, prefer n*nrhs) ! (rworkspace: none) if( lwork>=ldb*nrhs .and. nrhs>1_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'C', 'N', n, nrhs, m, cone, a, lda, b, ldb,czero, work, ldb ) call stdlib${ii}$_${ci}$lacpy( 'G', n, nrhs, work, ldb, b, ldb ) else if( nrhs>1_${ik}$ ) then chunk = lwork / n do i = 1, nrhs, chunk bl = min( nrhs-i+1, chunk ) call stdlib${ii}$_${ci}$gemm( 'C', 'N', n, bl, m, cone, a, lda, b( 1_${ik}$, i ),ldb, czero, & work, n ) call stdlib${ii}$_${ci}$lacpy( 'F', n, bl, work, n, b( 1_${ik}$, i ), ldb ) end do else call stdlib${ii}$_${ci}$gemv( 'C', m, n, cone, a, lda, b, 1_${ik}$, czero, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$copy( n, work, 1_${ik}$, b, 1_${ik}$ ) end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 70 continue work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ci}$gelss #:endif #:endfor module subroutine stdlib${ii}$_sgelsy( m, n, nrhs, a, lda, b, ldb, jpvt, rcond, rank,work, lwork, info ) !! SGELSY computes the minimum-norm solution to a real linear least !! squares problem: !! minimize || A * X - B || !! using a complete orthogonal factorization of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. !! The routine first computes a QR factorization with column pivoting: !! A * P = Q * [ R11 R12 ] !! [ 0 R22 ] !! with R11 defined as the largest leading submatrix whose estimated !! condition number is less than 1/RCOND. The order of R11, RANK, !! is the effective rank of A. !! Then, R22 is considered to be negligible, and R12 is annihilated !! by orthogonal transformations from the right, arriving at the !! complete orthogonal factorization: !! A * P = Q * [ T11 0 ] * Z !! [ 0 0 ] !! The minimum-norm solution is then !! X = P * Z**T [ inv(T11)*Q1**T*B ] !! [ 0 ] !! where Q1 consists of the first RANK columns of Q. !! This routine is basically identical to the original xGELSX except !! three differences: !! o The call to the subroutine xGEQPF has been substituted by the !! the call to the subroutine xGEQP3. This subroutine is a Blas-3 !! version of the QR factorization with column pivoting. !! o Matrix B (the right hand side) is updated with Blas-3. !! o The permutation of matrix B (the right hand side) is faster and !! more simple. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(sp), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(inout) :: jpvt(*) real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: imax = 1_${ik}$ integer(${ik}$), parameter :: imin = 2_${ik}$ ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iascl, ibscl, ismax, ismin, j, lwkmin, lwkopt, mn, nb, nb1, nb2, & nb3, nb4 real(sp) :: anrm, bignum, bnrm, c1, c2, s1, s2, smax, smaxpr, smin, sminpr, smlnum, & wsize ! Intrinsic Functions ! Executable Statements mn = min( m, n ) ismin = mn + 1_${ik}$ ismax = 2_${ik}$*mn + 1_${ik}$ ! test the input arguments. info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_slaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) rank = 0_${ik}$ go to 70 end if bnrm = stdlib${ii}$_slange( 'M', m, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! compute qr factorization with column pivoting of a: ! a * p = q * r call stdlib${ii}$_sgeqp3( m, n, a, lda, jpvt, work( 1_${ik}$ ), work( mn+1 ),lwork-mn, info ) wsize = mn + work( mn+1 ) ! workspace: mn+2*n+nb*(n+1). ! details of householder rotations stored in work(1:mn). ! determine rank using incremental condition estimation work( ismin ) = one work( ismax ) = one smax = abs( a( 1_${ik}$, 1_${ik}$ ) ) smin = smax if( abs( a( 1_${ik}$, 1_${ik}$ ) )==zero ) then rank = 0_${ik}$ call stdlib${ii}$_slaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) go to 70 else rank = 1_${ik}$ end if 10 continue if( rankzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_dlaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) rank = 0_${ik}$ go to 70 end if bnrm = stdlib${ii}$_dlange( 'M', m, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! compute qr factorization with column pivoting of a: ! a * p = q * r call stdlib${ii}$_dgeqp3( m, n, a, lda, jpvt, work( 1_${ik}$ ), work( mn+1 ),lwork-mn, info ) wsize = mn + work( mn+1 ) ! workspace: mn+2*n+nb*(n+1). ! details of householder rotations stored in work(1:mn). ! determine rank using incremental condition estimation work( ismin ) = one work( ismax ) = one smax = abs( a( 1_${ik}$, 1_${ik}$ ) ) smin = smax if( abs( a( 1_${ik}$, 1_${ik}$ ) )==zero ) then rank = 0_${ik}$ call stdlib${ii}$_dlaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) go to 70 else rank = 1_${ik}$ end if 10 continue if( rankzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_${ri}$laset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) rank = 0_${ik}$ go to 70 end if bnrm = stdlib${ii}$_${ri}$lange( 'M', m, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! compute qr factorization with column pivoting of a: ! a * p = q * r call stdlib${ii}$_${ri}$geqp3( m, n, a, lda, jpvt, work( 1_${ik}$ ), work( mn+1 ),lwork-mn, info ) wsize = mn + work( mn+1 ) ! workspace: mn+2*n+nb*(n+1). ! details of householder rotations stored in work(1:mn). ! determine rank using incremental condition estimation work( ismin ) = one work( ismax ) = one smax = abs( a( 1_${ik}$, 1_${ik}$ ) ) smin = smax if( abs( a( 1_${ik}$, 1_${ik}$ ) )==zero ) then rank = 0_${ik}$ call stdlib${ii}$_${ri}$laset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) go to 70 else rank = 1_${ik}$ end if 10 continue if( rankzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_claset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) rank = 0_${ik}$ go to 70 end if bnrm = stdlib${ii}$_clange( 'M', m, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! compute qr factorization with column pivoting of a: ! a * p = q * r call stdlib${ii}$_cgeqp3( m, n, a, lda, jpvt, work( 1_${ik}$ ), work( mn+1 ),lwork-mn, rwork, info ) wsize = mn + real( work( mn+1 ),KIND=sp) ! complex workspace: mn+nb*(n+1). real workspace 2*n. ! details of householder rotations stored in work(1:mn). ! determine rank using incremental condition estimation work( ismin ) = cone work( ismax ) = cone smax = abs( a( 1_${ik}$, 1_${ik}$ ) ) smin = smax if( abs( a( 1_${ik}$, 1_${ik}$ ) )==zero ) then rank = 0_${ik}$ call stdlib${ii}$_claset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) go to 70 else rank = 1_${ik}$ end if 10 continue if( rankzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_zlaset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) rank = 0_${ik}$ go to 70 end if bnrm = stdlib${ii}$_zlange( 'M', m, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! compute qr factorization with column pivoting of a: ! a * p = q * r call stdlib${ii}$_zgeqp3( m, n, a, lda, jpvt, work( 1_${ik}$ ), work( mn+1 ),lwork-mn, rwork, info ) wsize = mn + real( work( mn+1 ),KIND=dp) ! complex workspace: mn+nb*(n+1). real workspace 2*n. ! details of householder rotations stored in work(1:mn). ! determine rank using incremental condition estimation work( ismin ) = cone work( ismax ) = cone smax = abs( a( 1_${ik}$, 1_${ik}$ ) ) smin = smax if( abs( a( 1_${ik}$, 1_${ik}$ ) )==zero ) then rank = 0_${ik}$ call stdlib${ii}$_zlaset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) go to 70 else rank = 1_${ik}$ end if 10 continue if( rankzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_${ci}$laset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) rank = 0_${ik}$ go to 70 end if bnrm = stdlib${ii}$_${ci}$lange( 'M', m, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! compute qr factorization with column pivoting of a: ! a * p = q * r call stdlib${ii}$_${ci}$geqp3( m, n, a, lda, jpvt, work( 1_${ik}$ ), work( mn+1 ),lwork-mn, rwork, info ) wsize = mn + real( work( mn+1 ),KIND=${ck}$) ! complex workspace: mn+nb*(n+1). real workspace 2*n. ! details of householder rotations stored in work(1:mn). ! determine rank using incremental condition estimation work( ismin ) = cone work( ismax ) = cone smax = abs( a( 1_${ik}$, 1_${ik}$ ) ) smin = smax if( abs( a( 1_${ik}$, 1_${ik}$ ) )==zero ) then rank = 0_${ik}$ call stdlib${ii}$_${ci}$laset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) go to 70 else rank = 1_${ik}$ end if 10 continue if( rank= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'T' and m >= n: find the minimum norm solution of !! an underdetermined system A**T * X = B. !! 4. If TRANS = 'T' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**T * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tpsd integer(${ik}$) :: brow, i, iascl, ibscl, j, mn, nb, scllen, wsize real(sp) :: anrm, bignum, bnrm, smlnum ! Local Arrays real(sp) :: rwork(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or. stdlib_lsame( trans, 'T' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', 'LN', m, nrhs, n,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', 'LT', m, nrhs, n,-1_${ik}$ ) ) end if else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMLQ', 'LT', n, nrhs, m,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMLQ', 'LN', n, nrhs, m,-1_${ik}$ ) ) end if end if wsize = max( 1_${ik}$, mn + max( mn, nrhs )*nb ) work( 1_${ik}$ ) = real( wsize,KIND=sp) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SGELS ', -info ) return else if( lquery ) then return end if ! quick return if possible if( min( m, n, nrhs )==0_${ik}$ ) then call stdlib${ii}$_slaset( 'FULL', max( m, n ), nrhs, zero, zero, b, ldb ) return end if ! get machine parameters smlnum = stdlib${ii}$_slamch( 'S' ) / stdlib${ii}$_slamch( 'P' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) ! scale a, b if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_slange( 'M', m, n, a, lda, rwork ) iascl = 0_${ik}$ if( anrm>zero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_slaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) go to 50 end if brow = m if( tpsd )brow = n bnrm = stdlib${ii}$_slange( 'M', brow, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_sgeqrf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least n, optimally n*nb if( .not.tpsd ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**t * b(1:m,1:nrhs) call stdlib${ii}$_sormqr( 'LEFT', 'TRANSPOSE', m, nrhs, n, a, lda,work( 1_${ik}$ ), b, ldb, & work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_strtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = n else ! underdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**t) * b(1:n,1:nrhs) call stdlib${ii}$_strtrs( 'UPPER', 'TRANSPOSE', 'NON-UNIT', n, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = zero do j = 1, nrhs do i = n + 1, m b( i, j ) = zero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_sormqr( 'LEFT', 'NO TRANSPOSE', m, nrhs, n, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_sgelqf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least m, optimally m*nb. if( .not.tpsd ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_strtrs( 'LOWER', 'NO TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = zero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**t * b(1:m,1:nrhs) call stdlib${ii}$_sormlq( 'LEFT', 'TRANSPOSE', n, nrhs, m, a, lda,work( 1_${ik}$ ), b, ldb, & work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**t * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_sormlq( 'LEFT', 'NO TRANSPOSE', n, nrhs, m, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**t) * b(1:m,1:nrhs) call stdlib${ii}$_strtrs( 'LOWER', 'TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( wsize,KIND=sp) return end subroutine stdlib${ii}$_sgels module subroutine stdlib${ii}$_dgels( trans, m, n, nrhs, a, lda, b, ldb, work, lwork,info ) !! DGELS solves overdetermined or underdetermined real linear systems !! involving an M-by-N matrix A, or its transpose, using a QR or LQ !! factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'T' and m >= n: find the minimum norm solution of !! an underdetermined system A**T * X = B. !! 4. If TRANS = 'T' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**T * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tpsd integer(${ik}$) :: brow, i, iascl, ibscl, j, mn, nb, scllen, wsize real(dp) :: anrm, bignum, bnrm, smlnum ! Local Arrays real(dp) :: rwork(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or. stdlib_lsame( trans, 'T' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', 'LN', m, nrhs, n,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', 'LT', m, nrhs, n,-1_${ik}$ ) ) end if else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMLQ', 'LT', n, nrhs, m,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMLQ', 'LN', n, nrhs, m,-1_${ik}$ ) ) end if end if wsize = max( 1_${ik}$, mn+max( mn, nrhs )*nb ) work( 1_${ik}$ ) = real( wsize,KIND=dp) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGELS ', -info ) return else if( lquery ) then return end if ! quick return if possible if( min( m, n, nrhs )==0_${ik}$ ) then call stdlib${ii}$_dlaset( 'FULL', max( m, n ), nrhs, zero, zero, b, ldb ) return end if ! get machine parameters smlnum = stdlib${ii}$_dlamch( 'S' ) / stdlib${ii}$_dlamch( 'P' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) ! scale a, b if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_dlange( 'M', m, n, a, lda, rwork ) iascl = 0_${ik}$ if( anrm>zero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_dlaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) go to 50 end if brow = m if( tpsd )brow = n bnrm = stdlib${ii}$_dlange( 'M', brow, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_dgeqrf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least n, optimally n*nb if( .not.tpsd ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**t * b(1:m,1:nrhs) call stdlib${ii}$_dormqr( 'LEFT', 'TRANSPOSE', m, nrhs, n, a, lda,work( 1_${ik}$ ), b, ldb, & work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_dtrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = n else ! underdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**t) * b(1:n,1:nrhs) call stdlib${ii}$_dtrtrs( 'UPPER', 'TRANSPOSE', 'NON-UNIT', n, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = zero do j = 1, nrhs do i = n + 1, m b( i, j ) = zero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_dormqr( 'LEFT', 'NO TRANSPOSE', m, nrhs, n, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_dgelqf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least m, optimally m*nb. if( .not.tpsd ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_dtrtrs( 'LOWER', 'NO TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = zero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**t * b(1:m,1:nrhs) call stdlib${ii}$_dormlq( 'LEFT', 'TRANSPOSE', n, nrhs, m, a, lda,work( 1_${ik}$ ), b, ldb, & work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**t * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_dormlq( 'LEFT', 'NO TRANSPOSE', n, nrhs, m, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**t) * b(1:m,1:nrhs) call stdlib${ii}$_dtrtrs( 'LOWER', 'TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( wsize,KIND=dp) return end subroutine stdlib${ii}$_dgels #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$gels( trans, m, n, nrhs, a, lda, b, ldb, work, lwork,info ) !! DGELS: solves overdetermined or underdetermined real linear systems !! involving an M-by-N matrix A, or its transpose, using a QR or LQ !! factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'T' and m >= n: find the minimum norm solution of !! an underdetermined system A**T * X = B. !! 4. If TRANS = 'T' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**T * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tpsd integer(${ik}$) :: brow, i, iascl, ibscl, j, mn, nb, scllen, wsize real(${rk}$) :: anrm, bignum, bnrm, smlnum ! Local Arrays real(${rk}$) :: rwork(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or. stdlib_lsame( trans, 'T' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', 'LN', m, nrhs, n,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', 'LT', m, nrhs, n,-1_${ik}$ ) ) end if else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMLQ', 'LT', n, nrhs, m,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMLQ', 'LN', n, nrhs, m,-1_${ik}$ ) ) end if end if wsize = max( 1_${ik}$, mn+max( mn, nrhs )*nb ) work( 1_${ik}$ ) = real( wsize,KIND=${rk}$) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGELS ', -info ) return else if( lquery ) then return end if ! quick return if possible if( min( m, n, nrhs )==0_${ik}$ ) then call stdlib${ii}$_${ri}$laset( 'FULL', max( m, n ), nrhs, zero, zero, b, ldb ) return end if ! get machine parameters smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) / stdlib${ii}$_${ri}$lamch( 'P' ) bignum = one / smlnum call stdlib${ii}$_${ri}$labad( smlnum, bignum ) ! scale a, b if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ri}$lange( 'M', m, n, a, lda, rwork ) iascl = 0_${ik}$ if( anrm>zero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_${ri}$laset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) go to 50 end if brow = m if( tpsd )brow = n bnrm = stdlib${ii}$_${ri}$lange( 'M', brow, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least n, optimally n*nb if( .not.tpsd ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**t * b(1:m,1:nrhs) call stdlib${ii}$_${ri}$ormqr( 'LEFT', 'TRANSPOSE', m, nrhs, n, a, lda,work( 1_${ik}$ ), b, ldb, & work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_${ri}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = n else ! underdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**t) * b(1:n,1:nrhs) call stdlib${ii}$_${ri}$trtrs( 'UPPER', 'TRANSPOSE', 'NON-UNIT', n, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = zero do j = 1, nrhs do i = n + 1, m b( i, j ) = zero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_${ri}$ormqr( 'LEFT', 'NO TRANSPOSE', m, nrhs, n, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least m, optimally m*nb. if( .not.tpsd ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_${ri}$trtrs( 'LOWER', 'NO TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = zero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**t * b(1:m,1:nrhs) call stdlib${ii}$_${ri}$ormlq( 'LEFT', 'TRANSPOSE', n, nrhs, m, a, lda,work( 1_${ik}$ ), b, ldb, & work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**t * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_${ri}$ormlq( 'LEFT', 'NO TRANSPOSE', n, nrhs, m, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**t) * b(1:m,1:nrhs) call stdlib${ii}$_${ri}$trtrs( 'LOWER', 'TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( wsize,KIND=${rk}$) return end subroutine stdlib${ii}$_${ri}$gels #:endif #:endfor module subroutine stdlib${ii}$_cgels( trans, m, n, nrhs, a, lda, b, ldb, work, lwork,info ) !! CGELS solves overdetermined or underdetermined complex linear systems !! involving an M-by-N matrix A, or its conjugate-transpose, using a QR !! or LQ factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'C' and m >= n: find the minimum norm solution of !! an underdetermined system A**H * X = B. !! 4. If TRANS = 'C' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**H * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tpsd integer(${ik}$) :: brow, i, iascl, ibscl, j, mn, nb, scllen, wsize real(sp) :: anrm, bignum, bnrm, smlnum ! Local Arrays real(sp) :: rwork(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or. stdlib_lsame( trans, 'C' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', 'LN', m, nrhs, n,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', 'LC', m, nrhs, n,-1_${ik}$ ) ) end if else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMLQ', 'LC', n, nrhs, m,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMLQ', 'LN', n, nrhs, m,-1_${ik}$ ) ) end if end if wsize = max( 1_${ik}$, mn + max( mn, nrhs )*nb ) work( 1_${ik}$ ) = real( wsize,KIND=sp) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CGELS ', -info ) return else if( lquery ) then return end if ! quick return if possible if( min( m, n, nrhs )==0_${ik}$ ) then call stdlib${ii}$_claset( 'FULL', max( m, n ), nrhs, czero, czero, b, ldb ) return end if ! get machine parameters smlnum = stdlib${ii}$_slamch( 'S' ) / stdlib${ii}$_slamch( 'P' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) ! scale a, b if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_clange( 'M', m, n, a, lda, rwork ) iascl = 0_${ik}$ if( anrm>zero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_claset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) go to 50 end if brow = m if( tpsd )brow = n bnrm = stdlib${ii}$_clange( 'M', brow, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_cgeqrf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least n, optimally n*nb if( .not.tpsd ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**h * b(1:m,1:nrhs) call stdlib${ii}$_cunmqr( 'LEFT', 'CONJUGATE TRANSPOSE', m, nrhs, n, a,lda, work( 1_${ik}$ ), & b, ldb, work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_ctrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = n else ! underdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**h) * b(1:n,1:nrhs) call stdlib${ii}$_ctrtrs( 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT',n, nrhs, a, lda, b,& ldb, info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = zero do j = 1, nrhs do i = n + 1, m b( i, j ) = czero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_cunmqr( 'LEFT', 'NO TRANSPOSE', m, nrhs, n, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_cgelqf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least m, optimally m*nb. if( .not.tpsd ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_ctrtrs( 'LOWER', 'NO TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = czero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**h * b(1:m,1:nrhs) call stdlib${ii}$_cunmlq( 'LEFT', 'CONJUGATE TRANSPOSE', n, nrhs, m, a,lda, work( 1_${ik}$ ), & b, ldb, work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**h * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_cunmlq( 'LEFT', 'NO TRANSPOSE', n, nrhs, m, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**h) * b(1:m,1:nrhs) call stdlib${ii}$_ctrtrs( 'LOWER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',m, nrhs, a, lda, & b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( wsize,KIND=sp) return end subroutine stdlib${ii}$_cgels module subroutine stdlib${ii}$_zgels( trans, m, n, nrhs, a, lda, b, ldb, work, lwork,info ) !! ZGELS solves overdetermined or underdetermined complex linear systems !! involving an M-by-N matrix A, or its conjugate-transpose, using a QR !! or LQ factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'C' and m >= n: find the minimum norm solution of !! an underdetermined system A**H * X = B. !! 4. If TRANS = 'C' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**H * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tpsd integer(${ik}$) :: brow, i, iascl, ibscl, j, mn, nb, scllen, wsize real(dp) :: anrm, bignum, bnrm, smlnum ! Local Arrays real(dp) :: rwork(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or. stdlib_lsame( trans, 'C' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', 'LN', m, nrhs, n,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', 'LC', m, nrhs, n,-1_${ik}$ ) ) end if else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMLQ', 'LC', n, nrhs, m,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMLQ', 'LN', n, nrhs, m,-1_${ik}$ ) ) end if end if wsize = max( 1_${ik}$, mn+max( mn, nrhs )*nb ) work( 1_${ik}$ ) = real( wsize,KIND=dp) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGELS ', -info ) return else if( lquery ) then return end if ! quick return if possible if( min( m, n, nrhs )==0_${ik}$ ) then call stdlib${ii}$_zlaset( 'FULL', max( m, n ), nrhs, czero, czero, b, ldb ) return end if ! get machine parameters smlnum = stdlib${ii}$_dlamch( 'S' ) / stdlib${ii}$_dlamch( 'P' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) ! scale a, b if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_zlange( 'M', m, n, a, lda, rwork ) iascl = 0_${ik}$ if( anrm>zero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_zlaset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) go to 50 end if brow = m if( tpsd )brow = n bnrm = stdlib${ii}$_zlange( 'M', brow, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_zgeqrf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least n, optimally n*nb if( .not.tpsd ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**h * b(1:m,1:nrhs) call stdlib${ii}$_zunmqr( 'LEFT', 'CONJUGATE TRANSPOSE', m, nrhs, n, a,lda, work( 1_${ik}$ ), & b, ldb, work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_ztrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = n else ! underdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**h) * b(1:n,1:nrhs) call stdlib${ii}$_ztrtrs( 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT',n, nrhs, a, lda, b,& ldb, info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = zero do j = 1, nrhs do i = n + 1, m b( i, j ) = czero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_zunmqr( 'LEFT', 'NO TRANSPOSE', m, nrhs, n, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_zgelqf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least m, optimally m*nb. if( .not.tpsd ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_ztrtrs( 'LOWER', 'NO TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = czero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**h * b(1:m,1:nrhs) call stdlib${ii}$_zunmlq( 'LEFT', 'CONJUGATE TRANSPOSE', n, nrhs, m, a,lda, work( 1_${ik}$ ), & b, ldb, work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**h * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_zunmlq( 'LEFT', 'NO TRANSPOSE', n, nrhs, m, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**h) * b(1:m,1:nrhs) call stdlib${ii}$_ztrtrs( 'LOWER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',m, nrhs, a, lda, & b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( wsize,KIND=dp) return end subroutine stdlib${ii}$_zgels #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$gels( trans, m, n, nrhs, a, lda, b, ldb, work, lwork,info ) !! ZGELS: solves overdetermined or underdetermined complex linear systems !! involving an M-by-N matrix A, or its conjugate-transpose, using a QR !! or LQ factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'C' and m >= n: find the minimum norm solution of !! an underdetermined system A**H * X = B. !! 4. If TRANS = 'C' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**H * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tpsd integer(${ik}$) :: brow, i, iascl, ibscl, j, mn, nb, scllen, wsize real(${ck}$) :: anrm, bignum, bnrm, smlnum ! Local Arrays real(${ck}$) :: rwork(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or. stdlib_lsame( trans, 'C' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', 'LN', m, nrhs, n,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', 'LC', m, nrhs, n,-1_${ik}$ ) ) end if else nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) if( tpsd ) then nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMLQ', 'LC', n, nrhs, m,-1_${ik}$ ) ) else nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMLQ', 'LN', n, nrhs, m,-1_${ik}$ ) ) end if end if wsize = max( 1_${ik}$, mn+max( mn, nrhs )*nb ) work( 1_${ik}$ ) = real( wsize,KIND=${ck}$) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGELS ', -info ) return else if( lquery ) then return end if ! quick return if possible if( min( m, n, nrhs )==0_${ik}$ ) then call stdlib${ii}$_${ci}$laset( 'FULL', max( m, n ), nrhs, czero, czero, b, ldb ) return end if ! get machine parameters smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) / stdlib${ii}$_${c2ri(ci)}$lamch( 'P' ) bignum = one / smlnum call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum ) ! scale a, b if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ci}$lange( 'M', m, n, a, lda, rwork ) iascl = 0_${ik}$ if( anrm>zero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_${ci}$laset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) go to 50 end if brow = m if( tpsd )brow = n bnrm = stdlib${ii}$_${ci}$lange( 'M', brow, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least n, optimally n*nb if( .not.tpsd ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**h * b(1:m,1:nrhs) call stdlib${ii}$_${ci}$unmqr( 'LEFT', 'CONJUGATE TRANSPOSE', m, nrhs, n, a,lda, work( 1_${ik}$ ), & b, ldb, work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_${ci}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = n else ! underdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**h) * b(1:n,1:nrhs) call stdlib${ii}$_${ci}$trtrs( 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT',n, nrhs, a, lda, b,& ldb, info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = zero do j = 1, nrhs do i = n + 1, m b( i, j ) = czero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_${ci}$unmqr( 'LEFT', 'NO TRANSPOSE', m, nrhs, n, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( 1_${ik}$ ), work( mn+1 ), lwork-mn,info ) ! workspace at least m, optimally m*nb. if( .not.tpsd ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_${ci}$trtrs( 'LOWER', 'NO TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = czero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**h * b(1:m,1:nrhs) call stdlib${ii}$_${ci}$unmlq( 'LEFT', 'CONJUGATE TRANSPOSE', n, nrhs, m, a,lda, work( 1_${ik}$ ), & b, ldb, work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**h * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_${ci}$unmlq( 'LEFT', 'NO TRANSPOSE', n, nrhs, m, a, lda,work( 1_${ik}$ ), b, ldb,& work( mn+1 ), lwork-mn,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**h) * b(1:m,1:nrhs) call stdlib${ii}$_${ci}$trtrs( 'LOWER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',m, nrhs, a, lda, & b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( wsize,KIND=${ck}$) return end subroutine stdlib${ii}$_${ci}$gels #:endif #:endfor module subroutine stdlib${ii}$_sgelsd( m, n, nrhs, a, lda, b, ldb, s, rcond,rank, work, lwork, iwork, & !! SGELSD computes the minimum-norm solution to a real linear least !! squares problem: !! minimize 2-norm(| b - A*x |) !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. !! The problem is solved in three steps: !! (1) Reduce the coefficient matrix A to bidiagonal form with !! Householder transformations, reducing the original problem !! into a "bidiagonal least squares problem" (BLS) !! (2) Solve the BLS using a divide and conquer approach. !! (3) Apply back all the Householder transformations to solve !! the original least squares problem. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(sp), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: s(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: iascl, ibscl, ie, il, itau, itaup, itauq, ldwork, liwork, maxmn, & maxwrk, minmn, minwrk, mm, mnthr, nlvl, nwork, smlsiz, wlalsd real(sp) :: anrm, bignum, bnrm, eps, sfmin, smlnum ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ minmn = min( m, n ) maxmn = max( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then smlsiz = stdlib${ii}$_ilaenv( 9_${ik}$, 'SGELSD', ' ', 0_${ik}$, 0_${ik}$, 0_${ik}$, 0_${ik}$ ) mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'SGELSD', ' ', m, n, nrhs, -1_${ik}$ ) nlvl = max( int( log( real( minmn,KIND=sp) / real( smlsiz + 1_${ik}$,KIND=sp) ) /log( & two ),KIND=${ik}$) + 1_${ik}$, 0_${ik}$ ) liwork = 3_${ik}$*minmn*nlvl + 11_${ik}$*minmn mm = m if( m>=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than ! columns. mm = n maxwrk = max( maxwrk, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', m,n, -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, n + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', 'LT',m, nrhs, n, -& 1_${ik}$ ) ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined. maxwrk = max( maxwrk, 3_${ik}$*n + ( mm + n )*stdlib${ii}$_ilaenv( 1_${ik}$,'SGEBRD', ' ', mm, n, & -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, 3_${ik}$*n + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMBR','QLT', mm, nrhs, & n, -1_${ik}$ ) ) maxwrk = max( maxwrk, 3_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'SORMBR', 'PLN', n, & nrhs, n, -1_${ik}$ ) ) wlalsd = 9_${ik}$*n + 2_${ik}$*n*smlsiz + 8_${ik}$*n*nlvl + n*nrhs +( smlsiz + 1_${ik}$ )**2_${ik}$ maxwrk = max( maxwrk, 3_${ik}$*n + wlalsd ) minwrk = max( 3_${ik}$*n + mm, 3_${ik}$*n + nrhs, 3_${ik}$*n + wlalsd ) end if if( n>m ) then wlalsd = 9_${ik}$*m + 2_${ik}$*m*smlsiz + 8_${ik}$*m*nlvl + m*nrhs +( smlsiz + 1_${ik}$ )**2_${ik}$ if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows. maxwrk = m + m*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGELQF', ' ', m, n, -1_${ik}$,-1_${ik}$ ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + 2_${ik}$*m*stdlib${ii}$_ilaenv( 1_${ik}$,'SGEBRD', ' ', m, m,& -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$,'SORMBR', 'QLT', m,& nrhs, m, -1_${ik}$ ) ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + ( m - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'SORMBR', & 'PLN', m, nrhs, m, -1_${ik}$ ) ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m + m + m*nrhs ) else maxwrk = max( maxwrk, m*m + 2_${ik}$*m ) end if maxwrk = max( maxwrk, m + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMLQ','LT', n, nrhs, m,& -1_${ik}$ ) ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + wlalsd ) ! xxx: ensure the path 2a case below is triggered. the workspace ! calculation should use queries for all routines eventually. maxwrk = max( maxwrk,4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) else ! path 2 - remaining underdetermined cases. maxwrk = 3_${ik}$*m + ( n + m )*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEBRD', ' ', m,n, -1_${ik}$, -1_${ik}$ ) maxwrk = max( maxwrk, 3_${ik}$*m + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMBR','QLT', m, nrhs,& n, -1_${ik}$ ) ) maxwrk = max( maxwrk, 3_${ik}$*m + m*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMBR','PLN', n, nrhs, m,& -1_${ik}$ ) ) maxwrk = max( maxwrk, 3_${ik}$*m + wlalsd ) end if minwrk = max( 3_${ik}$*m + nrhs, 3_${ik}$*m + m, 3_${ik}$*m + wlalsd ) end if end if minwrk = min( minwrk, maxwrk ) work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_slaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) call stdlib${ii}$_slaset( 'F', minmn, 1_${ik}$, zero, zero, s, 1_${ik}$ ) rank = 0_${ik}$ go to 10 end if ! scale b if max entry outside range [smlnum,bignum]. bnrm = stdlib${ii}$_slange( 'M', m, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! if m < n make sure certain entries of b are zero. if( m=n ) then ! path 1 - overdetermined or exactly determined. mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns. mm = n itau = 1_${ik}$ nwork = itau + n ! compute a=q*r. ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & info ) ! multiply b by transpose(q). ! (workspace: need n+nrhs, prefer n+nrhs*nb) call stdlib${ii}$_sormqr( 'L', 'T', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & nwork ), lwork-nwork+1, info ) ! zero out below r. if( n>1_${ik}$ ) then call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) end if end if ie = 1_${ik}$ itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a. ! (workspace: need 3*n+mm, prefer 3*n+(mm+n)*nb) call stdlib${ii}$_sgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work(& nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r. ! (workspace: need 3*n+nrhs, prefer 3*n+nrhs*nb) call stdlib${ii}$_sormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_slalsd( 'U', smlsiz, n, nrhs, s, work( ie ), b, ldb,rcond, rank, work( & nwork ), iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of r. call stdlib${ii}$_sormbr( 'P', 'L', 'N', n, nrhs, n, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) else if( n>=mnthr .and. lwork>=4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m, wlalsd ) ) & then ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm. ldwork = m if( lwork>=max( 4_${ik}$*m+m*lda+max( m, 2_${ik}$*m-4, nrhs, n-3*m ),m*lda+m+m*nrhs, 4_${ik}$*m+m*lda+& wlalsd ) )ldwork = lda itau = 1_${ik}$ nwork = m + 1_${ik}$ ! compute a=l*q. ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, info ) il = nwork ! copy l to work(il), zeroing out above its diagonal. call stdlib${ii}$_slacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, work( il+ldwork ),ldwork ) ie = il + ldwork*m itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il). ! (workspace: need m*m+5*m, prefer m*m+4*m+2*m*nb) call stdlib${ii}$_sgebrd( m, m, work( il ), ldwork, s, work( ie ),work( itauq ), work( & itaup ), work( nwork ),lwork-nwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l. ! (workspace: need m*m+4*m+nrhs, prefer m*m+4*m+nrhs*nb) call stdlib${ii}$_sormbr( 'Q', 'L', 'T', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_slalsd( 'U', smlsiz, m, nrhs, s, work( ie ), b, ldb,rcond, rank, work( & nwork ), iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of l. call stdlib${ii}$_sormbr( 'P', 'L', 'N', m, nrhs, m, work( il ), ldwork,work( itaup ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! zero out below first m rows of b. call stdlib${ii}$_slaset( 'F', n-m, nrhs, zero, zero, b( m+1, 1_${ik}$ ), ldb ) nwork = itau + m ! multiply transpose(q) by b. ! (workspace: need m+nrhs, prefer m+nrhs*nb) call stdlib${ii}$_sormlq( 'L', 'T', n, nrhs, m, a, lda, work( itau ), b,ldb, work( nwork )& , lwork-nwork+1, info ) else ! path 2 - remaining underdetermined cases. ie = 1_${ik}$ itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize a. ! (workspace: need 3*m+n, prefer 3*m+(m+n)*nb) call stdlib${ii}$_sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work( & nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors. ! (workspace: need 3*m+nrhs, prefer 3*m+nrhs*nb) call stdlib${ii}$_sormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_slalsd( 'L', smlsiz, m, nrhs, s, work( ie ), b, ldb,rcond, rank, work( & nwork ), iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of a. call stdlib${ii}$_sormbr( 'P', 'L', 'N', n, nrhs, m, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) end if ! undo scaling. if( iascl==1_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 10 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork return end subroutine stdlib${ii}$_sgelsd module subroutine stdlib${ii}$_dgelsd( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, iwork, & !! DGELSD computes the minimum-norm solution to a real linear least !! squares problem: !! minimize 2-norm(| b - A*x |) !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. !! The problem is solved in three steps: !! (1) Reduce the coefficient matrix A to bidiagonal form with !! Householder transformations, reducing the original problem !! into a "bidiagonal least squares problem" (BLS) !! (2) Solve the BLS using a divide and conquer approach. !! (3) Apply back all the Householder transformations to solve !! the original least squares problem. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(dp), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: s(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: iascl, ibscl, ie, il, itau, itaup, itauq, ldwork, liwork, maxmn, & maxwrk, minmn, minwrk, mm, mnthr, nlvl, nwork, smlsiz, wlalsd real(dp) :: anrm, bignum, bnrm, eps, sfmin, smlnum ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ minmn = min( m, n ) maxmn = max( m, n ) mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'DGELSD', ' ', m, n, nrhs, -1_${ik}$ ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns. mm = n maxwrk = max( maxwrk, n+n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', m, n,-1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, n+nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', 'LT', m, nrhs, n, -1_${ik}$ ) ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined. maxwrk = max( maxwrk, 3_${ik}$*n+( mm+n )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEBRD', ' ', mm, n, -1_${ik}$, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, 3_${ik}$*n+nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'QLT', mm, nrhs, n, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, 3_${ik}$*n+( n-1 )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'PLN', n, nrhs, n, & -1_${ik}$ ) ) wlalsd = 9_${ik}$*n+2*n*smlsiz+8*n*nlvl+n*nrhs+(smlsiz+1)**2_${ik}$ maxwrk = max( maxwrk, 3_${ik}$*n+wlalsd ) minwrk = max( 3_${ik}$*n+mm, 3_${ik}$*n+nrhs, 3_${ik}$*n+wlalsd ) end if if( n>m ) then wlalsd = 9_${ik}$*m+2*m*smlsiz+8*m*nlvl+m*nrhs+(smlsiz+1)**2_${ik}$ if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows. maxwrk = m + m*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) maxwrk = max( maxwrk, m*m+4*m+2*m*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEBRD', ' ', m, m, -1_${ik}$, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, m*m+4*m+nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'QLT', m, nrhs,& m, -1_${ik}$ ) ) maxwrk = max( maxwrk, m*m+4*m+( m-1 )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'PLN', m, & nrhs, m, -1_${ik}$ ) ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m+m+m*nrhs ) else maxwrk = max( maxwrk, m*m+2*m ) end if maxwrk = max( maxwrk, m+nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMLQ', 'LT', n, nrhs, m, -1_${ik}$ & ) ) maxwrk = max( maxwrk, m*m+4*m+wlalsd ) ! xxx: ensure the path 2a case below is triggered. the workspace ! calculation should use queries for all routines eventually. maxwrk = max( maxwrk,4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) else ! path 2 - remaining underdetermined cases. maxwrk = 3_${ik}$*m + ( n+m )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEBRD', ' ', m, n,-1_${ik}$, -1_${ik}$ ) maxwrk = max( maxwrk, 3_${ik}$*m+nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'QLT', m, nrhs, n, & -1_${ik}$ ) ) maxwrk = max( maxwrk, 3_${ik}$*m+m*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'PLN', n, nrhs, m, -1_${ik}$ & ) ) maxwrk = max( maxwrk, 3_${ik}$*m+wlalsd ) end if minwrk = max( 3_${ik}$*m+nrhs, 3_${ik}$*m+m, 3_${ik}$*m+wlalsd ) end if minwrk = min( minwrk, maxwrk ) work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_dlaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) call stdlib${ii}$_dlaset( 'F', minmn, 1_${ik}$, zero, zero, s, 1_${ik}$ ) rank = 0_${ik}$ go to 10 end if ! scale b if max entry outside range [smlnum,bignum]. bnrm = stdlib${ii}$_dlange( 'M', m, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! if m < n make sure certain entries of b are zero. if( m=n ) then ! path 1 - overdetermined or exactly determined. mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns. mm = n itau = 1_${ik}$ nwork = itau + n ! compute a=q*r. ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & info ) ! multiply b by transpose(q). ! (workspace: need n+nrhs, prefer n+nrhs*nb) call stdlib${ii}$_dormqr( 'L', 'T', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & nwork ), lwork-nwork+1, info ) ! zero out below r. if( n>1_${ik}$ ) then call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) end if end if ie = 1_${ik}$ itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a. ! (workspace: need 3*n+mm, prefer 3*n+(mm+n)*nb) call stdlib${ii}$_dgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work(& nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r. ! (workspace: need 3*n+nrhs, prefer 3*n+nrhs*nb) call stdlib${ii}$_dormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_dlalsd( 'U', smlsiz, n, nrhs, s, work( ie ), b, ldb,rcond, rank, work( & nwork ), iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of r. call stdlib${ii}$_dormbr( 'P', 'L', 'N', n, nrhs, n, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) else if( n>=mnthr .and. lwork>=4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m, wlalsd ) ) & then ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm. ldwork = m if( lwork>=max( 4_${ik}$*m+m*lda+max( m, 2_${ik}$*m-4, nrhs, n-3*m ),m*lda+m+m*nrhs, 4_${ik}$*m+m*lda+& wlalsd ) )ldwork = lda itau = 1_${ik}$ nwork = m + 1_${ik}$ ! compute a=l*q. ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, info ) il = nwork ! copy l to work(il), zeroing out above its diagonal. call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, work( il+ldwork ),ldwork ) ie = il + ldwork*m itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il). ! (workspace: need m*m+5*m, prefer m*m+4*m+2*m*nb) call stdlib${ii}$_dgebrd( m, m, work( il ), ldwork, s, work( ie ),work( itauq ), work( & itaup ), work( nwork ),lwork-nwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l. ! (workspace: need m*m+4*m+nrhs, prefer m*m+4*m+nrhs*nb) call stdlib${ii}$_dormbr( 'Q', 'L', 'T', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_dlalsd( 'U', smlsiz, m, nrhs, s, work( ie ), b, ldb,rcond, rank, work( & nwork ), iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of l. call stdlib${ii}$_dormbr( 'P', 'L', 'N', m, nrhs, m, work( il ), ldwork,work( itaup ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! zero out below first m rows of b. call stdlib${ii}$_dlaset( 'F', n-m, nrhs, zero, zero, b( m+1, 1_${ik}$ ), ldb ) nwork = itau + m ! multiply transpose(q) by b. ! (workspace: need m+nrhs, prefer m+nrhs*nb) call stdlib${ii}$_dormlq( 'L', 'T', n, nrhs, m, a, lda, work( itau ), b,ldb, work( nwork )& , lwork-nwork+1, info ) else ! path 2 - remaining underdetermined cases. ie = 1_${ik}$ itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize a. ! (workspace: need 3*m+n, prefer 3*m+(m+n)*nb) call stdlib${ii}$_dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work( & nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors. ! (workspace: need 3*m+nrhs, prefer 3*m+nrhs*nb) call stdlib${ii}$_dormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_dlalsd( 'L', smlsiz, m, nrhs, s, work( ie ), b, ldb,rcond, rank, work( & nwork ), iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of a. call stdlib${ii}$_dormbr( 'P', 'L', 'N', n, nrhs, m, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) end if ! undo scaling. if( iascl==1_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 10 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork return end subroutine stdlib${ii}$_dgelsd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$gelsd( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, iwork, & !! DGELSD: computes the minimum-norm solution to a real linear least !! squares problem: !! minimize 2-norm(| b - A*x |) !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. !! The problem is solved in three steps: !! (1) Reduce the coefficient matrix A to bidiagonal form with !! Householder transformations, reducing the original problem !! into a "bidiagonal least squares problem" (BLS) !! (2) Solve the BLS using a divide and conquer approach. !! (3) Apply back all the Householder transformations to solve !! the original least squares problem. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(${rk}$), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: s(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: iascl, ibscl, ie, il, itau, itaup, itauq, ldwork, liwork, maxmn, & maxwrk, minmn, minwrk, mm, mnthr, nlvl, nwork, smlsiz, wlalsd real(${rk}$) :: anrm, bignum, bnrm, eps, sfmin, smlnum ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ minmn = min( m, n ) maxmn = max( m, n ) mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'DGELSD', ' ', m, n, nrhs, -1_${ik}$ ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns. mm = n maxwrk = max( maxwrk, n+n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', m, n,-1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, n+nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', 'LT', m, nrhs, n, -1_${ik}$ ) ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined. maxwrk = max( maxwrk, 3_${ik}$*n+( mm+n )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEBRD', ' ', mm, n, -1_${ik}$, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, 3_${ik}$*n+nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'QLT', mm, nrhs, n, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, 3_${ik}$*n+( n-1 )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'PLN', n, nrhs, n, & -1_${ik}$ ) ) wlalsd = 9_${ik}$*n+2*n*smlsiz+8*n*nlvl+n*nrhs+(smlsiz+1)**2_${ik}$ maxwrk = max( maxwrk, 3_${ik}$*n+wlalsd ) minwrk = max( 3_${ik}$*n+mm, 3_${ik}$*n+nrhs, 3_${ik}$*n+wlalsd ) end if if( n>m ) then wlalsd = 9_${ik}$*m+2*m*smlsiz+8*m*nlvl+m*nrhs+(smlsiz+1)**2_${ik}$ if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows. maxwrk = m + m*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) maxwrk = max( maxwrk, m*m+4*m+2*m*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEBRD', ' ', m, m, -1_${ik}$, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, m*m+4*m+nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'QLT', m, nrhs,& m, -1_${ik}$ ) ) maxwrk = max( maxwrk, m*m+4*m+( m-1 )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'PLN', m, & nrhs, m, -1_${ik}$ ) ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m+m+m*nrhs ) else maxwrk = max( maxwrk, m*m+2*m ) end if maxwrk = max( maxwrk, m+nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMLQ', 'LT', n, nrhs, m, -1_${ik}$ & ) ) maxwrk = max( maxwrk, m*m+4*m+wlalsd ) ! xxx: ensure the path 2a case below is triggered. the workspace ! calculation should use queries for all routines eventually. maxwrk = max( maxwrk,4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) else ! path 2 - remaining underdetermined cases. maxwrk = 3_${ik}$*m + ( n+m )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEBRD', ' ', m, n,-1_${ik}$, -1_${ik}$ ) maxwrk = max( maxwrk, 3_${ik}$*m+nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'QLT', m, nrhs, n, & -1_${ik}$ ) ) maxwrk = max( maxwrk, 3_${ik}$*m+m*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMBR', 'PLN', n, nrhs, m, -1_${ik}$ & ) ) maxwrk = max( maxwrk, 3_${ik}$*m+wlalsd ) end if minwrk = max( 3_${ik}$*m+nrhs, 3_${ik}$*m+m, 3_${ik}$*m+wlalsd ) end if minwrk = min( minwrk, maxwrk ) work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_${ri}$laset( 'F', max( m, n ), nrhs, zero, zero, b, ldb ) call stdlib${ii}$_${ri}$laset( 'F', minmn, 1_${ik}$, zero, zero, s, 1_${ik}$ ) rank = 0_${ik}$ go to 10 end if ! scale b if max entry outside range [smlnum,bignum]. bnrm = stdlib${ii}$_${ri}$lange( 'M', m, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! if m < n make sure certain entries of b are zero. if( m=n ) then ! path 1 - overdetermined or exactly determined. mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns. mm = n itau = 1_${ik}$ nwork = itau + n ! compute a=q*r. ! (workspace: need 2*n, prefer n+n*nb) call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & info ) ! multiply b by transpose(q). ! (workspace: need n+nrhs, prefer n+nrhs*nb) call stdlib${ii}$_${ri}$ormqr( 'L', 'T', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & nwork ), lwork-nwork+1, info ) ! zero out below r. if( n>1_${ik}$ ) then call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) end if end if ie = 1_${ik}$ itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a. ! (workspace: need 3*n+mm, prefer 3*n+(mm+n)*nb) call stdlib${ii}$_${ri}$gebrd( mm, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work(& nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r. ! (workspace: need 3*n+nrhs, prefer 3*n+nrhs*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_${ri}$lalsd( 'U', smlsiz, n, nrhs, s, work( ie ), b, ldb,rcond, rank, work( & nwork ), iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of r. call stdlib${ii}$_${ri}$ormbr( 'P', 'L', 'N', n, nrhs, n, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) else if( n>=mnthr .and. lwork>=4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m, wlalsd ) ) & then ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm. ldwork = m if( lwork>=max( 4_${ik}$*m+m*lda+max( m, 2_${ik}$*m-4, nrhs, n-3*m ),m*lda+m+m*nrhs, 4_${ik}$*m+m*lda+& wlalsd ) )ldwork = lda itau = 1_${ik}$ nwork = m + 1_${ik}$ ! compute a=l*q. ! (workspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, info ) il = nwork ! copy l to work(il), zeroing out above its diagonal. call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, work( il+ldwork ),ldwork ) ie = il + ldwork*m itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il). ! (workspace: need m*m+5*m, prefer m*m+4*m+2*m*nb) call stdlib${ii}$_${ri}$gebrd( m, m, work( il ), ldwork, s, work( ie ),work( itauq ), work( & itaup ), work( nwork ),lwork-nwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l. ! (workspace: need m*m+4*m+nrhs, prefer m*m+4*m+nrhs*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'T', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_${ri}$lalsd( 'U', smlsiz, m, nrhs, s, work( ie ), b, ldb,rcond, rank, work( & nwork ), iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of l. call stdlib${ii}$_${ri}$ormbr( 'P', 'L', 'N', m, nrhs, m, work( il ), ldwork,work( itaup ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! zero out below first m rows of b. call stdlib${ii}$_${ri}$laset( 'F', n-m, nrhs, zero, zero, b( m+1, 1_${ik}$ ), ldb ) nwork = itau + m ! multiply transpose(q) by b. ! (workspace: need m+nrhs, prefer m+nrhs*nb) call stdlib${ii}$_${ri}$ormlq( 'L', 'T', n, nrhs, m, a, lda, work( itau ), b,ldb, work( nwork )& , lwork-nwork+1, info ) else ! path 2 - remaining underdetermined cases. ie = 1_${ik}$ itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize a. ! (workspace: need 3*m+n, prefer 3*m+(m+n)*nb) call stdlib${ii}$_${ri}$gebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), work( & nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors. ! (workspace: need 3*m+nrhs, prefer 3*m+nrhs*nb) call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_${ri}$lalsd( 'L', smlsiz, m, nrhs, s, work( ie ), b, ldb,rcond, rank, work( & nwork ), iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of a. call stdlib${ii}$_${ri}$ormbr( 'P', 'L', 'N', n, nrhs, m, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) end if ! undo scaling. if( iascl==1_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 10 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork return end subroutine stdlib${ii}$_${ri}$gelsd #:endif #:endfor module subroutine stdlib${ii}$_cgelsd( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, rwork, & !! CGELSD computes the minimum-norm solution to a real linear least !! squares problem: !! minimize 2-norm(| b - A*x |) !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. !! The problem is solved in three steps: !! (1) Reduce the coefficient matrix A to bidiagonal form with !! Householder transformations, reducing the original problem !! into a "bidiagonal least squares problem" (BLS) !! (2) Solve the BLS using a divide and conquer approach. !! (3) Apply back all the Householder transformations to solve !! the original least squares problem. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(sp), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: rwork(*), s(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: iascl, ibscl, ie, il, itau, itaup, itauq, ldwork, liwork, lrwork, & maxmn, maxwrk, minmn, minwrk, mm, mnthr, nlvl, nrwork, nwork, smlsiz real(sp) :: anrm, bignum, bnrm, eps, sfmin, smlnum ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ minmn = min( m, n ) maxmn = max( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then smlsiz = stdlib${ii}$_ilaenv( 9_${ik}$, 'CGELSD', ' ', 0_${ik}$, 0_${ik}$, 0_${ik}$, 0_${ik}$ ) mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'CGELSD', ' ', m, n, nrhs, -1_${ik}$ ) nlvl = max( int( log( real( minmn,KIND=sp) / real( smlsiz + 1_${ik}$,KIND=sp) ) /log( & two ),KIND=${ik}$) + 1_${ik}$, 0_${ik}$ ) liwork = 3_${ik}$*minmn*nlvl + 11_${ik}$*minmn mm = m if( m>=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than ! columns. mm = n maxwrk = max( maxwrk, n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', m, n,-1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', 'LC', m,nrhs, n, -1_${ik}$ ) ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined. lrwork = 10_${ik}$*n + 2_${ik}$*n*smlsiz + 8_${ik}$*n*nlvl + 3_${ik}$*smlsiz*nrhs +max( (smlsiz+1)**2_${ik}$, n*(& 1_${ik}$+nrhs) + 2_${ik}$*nrhs ) maxwrk = max( maxwrk, 2_${ik}$*n + ( mm + n )*stdlib${ii}$_ilaenv( 1_${ik}$,'CGEBRD', ' ', mm, n, & -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*n + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMBR','QLC', mm, nrhs, & n, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'CUNMBR', 'PLN', n, & nrhs, n, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*n + n*nrhs ) minwrk = max( 2_${ik}$*n + mm, 2_${ik}$*n + n*nrhs ) end if if( n>m ) then lrwork = 10_${ik}$*m + 2_${ik}$*m*smlsiz + 8_${ik}$*m*nlvl + 3_${ik}$*smlsiz*nrhs +max( (smlsiz+1)**2_${ik}$, n*(& 1_${ik}$+nrhs) + 2_${ik}$*nrhs ) if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows. maxwrk = m + m*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGELQF', ' ', m, n, -1_${ik}$,-1_${ik}$ ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + 2_${ik}$*m*stdlib${ii}$_ilaenv( 1_${ik}$,'CGEBRD', ' ', m, m,& -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$,'CUNMBR', 'QLC', m,& nrhs, m, -1_${ik}$ ) ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + ( m - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'CUNMLQ', & 'LC', n, nrhs, m, -1_${ik}$ ) ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m + m + m*nrhs ) else maxwrk = max( maxwrk, m*m + 2_${ik}$*m ) end if maxwrk = max( maxwrk, m*m + 4_${ik}$*m + m*nrhs ) ! xxx: ensure the path 2a case below is triggered. the workspace ! calculation should use queries for all routines eventually. maxwrk = max( maxwrk,4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) else ! path 2 - underdetermined. maxwrk = 2_${ik}$*m + ( n + m )*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEBRD', ' ', m,n, -1_${ik}$, -1_${ik}$ ) maxwrk = max( maxwrk, 2_${ik}$*m + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMBR','QLC', m, nrhs,& m, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*m + m*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMBR','PLN', n, nrhs, m,& -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*m + m*nrhs ) end if minwrk = max( 2_${ik}$*m + n, 2_${ik}$*m + m*nrhs ) end if end if minwrk = min( minwrk, maxwrk ) work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork rwork( 1_${ik}$ ) = lrwork if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_claset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) call stdlib${ii}$_slaset( 'F', minmn, 1_${ik}$, zero, zero, s, 1_${ik}$ ) rank = 0_${ik}$ go to 10 end if ! scale b if max entry outside range [smlnum,bignum]. bnrm = stdlib${ii}$_clange( 'M', m, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! if m < n make sure b(m+1:n,:) = 0 if( m=n ) then ! path 1 - overdetermined or exactly determined. mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns mm = n itau = 1_${ik}$ nwork = itau + n ! compute a=q*r. ! (rworkspace: need n) ! (cworkspace: need n, prefer n*nb) call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & info ) ! multiply b by transpose(q). ! (rworkspace: need n) ! (cworkspace: need nrhs, prefer nrhs*nb) call stdlib${ii}$_cunmqr( 'L', 'C', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & nwork ), lwork-nwork+1, info ) ! zero out below r. if( n>1_${ik}$ ) then call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if end if itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ie = 1_${ik}$ nrwork = ie + n ! bidiagonalize r in a. ! (rworkspace: need n) ! (cworkspace: need 2*n+mm, prefer 2*n+(mm+n)*nb) call stdlib${ii}$_cgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r. ! (cworkspace: need 2*n+nrhs, prefer 2*n+nrhs*nb) call stdlib${ii}$_cunmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_clalsd( 'U', smlsiz, n, nrhs, s, rwork( ie ), b, ldb,rcond, rank, work( & nwork ), rwork( nrwork ),iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of r. call stdlib${ii}$_cunmbr( 'P', 'L', 'N', n, nrhs, n, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) else if( n>=mnthr .and. lwork>=4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) then ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm. ldwork = m if( lwork>=max( 4_${ik}$*m+m*lda+max( m, 2_${ik}$*m-4, nrhs, n-3*m ),m*lda+m+m*nrhs ) )ldwork = & lda itau = 1_${ik}$ nwork = m + 1_${ik}$ ! compute a=l*q. ! (cworkspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, info ) il = nwork ! copy l to work(il), zeroing out above its diagonal. call stdlib${ii}$_clacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero, work( il+ldwork ),ldwork ) itauq = il + ldwork*m itaup = itauq + m nwork = itaup + m ie = 1_${ik}$ nrwork = ie + m ! bidiagonalize l in work(il). ! (rworkspace: need m) ! (cworkspace: need m*m+4*m, prefer m*m+4*m+2*m*nb) call stdlib${ii}$_cgebrd( m, m, work( il ), ldwork, s, rwork( ie ),work( itauq ), work( & itaup ), work( nwork ),lwork-nwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l. ! (cworkspace: need m*m+4*m+nrhs, prefer m*m+4*m+nrhs*nb) call stdlib${ii}$_cunmbr( 'Q', 'L', 'C', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_clalsd( 'U', smlsiz, m, nrhs, s, rwork( ie ), b, ldb,rcond, rank, work( & nwork ), rwork( nrwork ),iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of l. call stdlib${ii}$_cunmbr( 'P', 'L', 'N', m, nrhs, m, work( il ), ldwork,work( itaup ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! zero out below first m rows of b. call stdlib${ii}$_claset( 'F', n-m, nrhs, czero, czero, b( m+1, 1_${ik}$ ), ldb ) nwork = itau + m ! multiply transpose(q) by b. ! (cworkspace: need nrhs, prefer nrhs*nb) call stdlib${ii}$_cunmlq( 'L', 'C', n, nrhs, m, a, lda, work( itau ), b,ldb, work( nwork )& , lwork-nwork+1, info ) else ! path 2 - remaining underdetermined cases. itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ie = 1_${ik}$ nrwork = ie + m ! bidiagonalize a. ! (rworkspace: need m) ! (cworkspace: need 2*m+n, prefer 2*m+(m+n)*nb) call stdlib${ii}$_cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), work(& nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors. ! (cworkspace: need 2*m+nrhs, prefer 2*m+nrhs*nb) call stdlib${ii}$_cunmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_clalsd( 'L', smlsiz, m, nrhs, s, rwork( ie ), b, ldb,rcond, rank, work( & nwork ), rwork( nrwork ),iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of a. call stdlib${ii}$_cunmbr( 'P', 'L', 'N', n, nrhs, m, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) end if ! undo scaling. if( iascl==1_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 10 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork rwork( 1_${ik}$ ) = lrwork return end subroutine stdlib${ii}$_cgelsd module subroutine stdlib${ii}$_zgelsd( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, rwork, & !! ZGELSD computes the minimum-norm solution to a real linear least !! squares problem: !! minimize 2-norm(| b - A*x |) !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. !! The problem is solved in three steps: !! (1) Reduce the coefficient matrix A to bidiagonal form with !! Householder transformations, reducing the original problem !! into a "bidiagonal least squares problem" (BLS) !! (2) Solve the BLS using a divide and conquer approach. !! (3) Apply back all the Householder transformations to solve !! the original least squares problem. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(dp), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(out) :: rwork(*), s(*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: iascl, ibscl, ie, il, itau, itaup, itauq, ldwork, liwork, lrwork, & maxmn, maxwrk, minmn, minwrk, mm, mnthr, nlvl, nrwork, nwork, smlsiz real(dp) :: anrm, bignum, bnrm, eps, sfmin, smlnum ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ minmn = min( m, n ) maxmn = max( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then smlsiz = stdlib${ii}$_ilaenv( 9_${ik}$, 'ZGELSD', ' ', 0_${ik}$, 0_${ik}$, 0_${ik}$, 0_${ik}$ ) mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'ZGELSD', ' ', m, n, nrhs, -1_${ik}$ ) nlvl = max( int( log( real( minmn,KIND=dp) / real( smlsiz + 1_${ik}$,KIND=dp) ) /log( & two ),KIND=${ik}$) + 1_${ik}$, 0_${ik}$ ) liwork = 3_${ik}$*minmn*nlvl + 11_${ik}$*minmn mm = m if( m>=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than ! columns. mm = n maxwrk = max( maxwrk, n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', m, n,-1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', 'LC', m,nrhs, n, -1_${ik}$ ) ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined. lrwork = 10_${ik}$*n + 2_${ik}$*n*smlsiz + 8_${ik}$*n*nlvl + 3_${ik}$*smlsiz*nrhs +max( (smlsiz+1)**2_${ik}$, n*(& 1_${ik}$+nrhs) + 2_${ik}$*nrhs ) maxwrk = max( maxwrk, 2_${ik}$*n + ( mm + n )*stdlib${ii}$_ilaenv( 1_${ik}$,'ZGEBRD', ' ', mm, n, & -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*n + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMBR','QLC', mm, nrhs, & n, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'ZUNMBR', 'PLN', n, & nrhs, n, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*n + n*nrhs ) minwrk = max( 2_${ik}$*n + mm, 2_${ik}$*n + n*nrhs ) end if if( n>m ) then lrwork = 10_${ik}$*m + 2_${ik}$*m*smlsiz + 8_${ik}$*m*nlvl + 3_${ik}$*smlsiz*nrhs +max( (smlsiz+1)**2_${ik}$, n*(& 1_${ik}$+nrhs) + 2_${ik}$*nrhs ) if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows. maxwrk = m + m*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQF', ' ', m, n, -1_${ik}$,-1_${ik}$ ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + 2_${ik}$*m*stdlib${ii}$_ilaenv( 1_${ik}$,'ZGEBRD', ' ', m, m,& -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$,'ZUNMBR', 'QLC', m,& nrhs, m, -1_${ik}$ ) ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + ( m - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'ZUNMLQ', & 'LC', n, nrhs, m, -1_${ik}$ ) ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m + m + m*nrhs ) else maxwrk = max( maxwrk, m*m + 2_${ik}$*m ) end if maxwrk = max( maxwrk, m*m + 4_${ik}$*m + m*nrhs ) ! xxx: ensure the path 2a case below is triggered. the workspace ! calculation should use queries for all routines eventually. maxwrk = max( maxwrk,4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) else ! path 2 - underdetermined. maxwrk = 2_${ik}$*m + ( n + m )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEBRD', ' ', m,n, -1_${ik}$, -1_${ik}$ ) maxwrk = max( maxwrk, 2_${ik}$*m + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMBR','QLC', m, nrhs,& m, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*m + m*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMBR','PLN', n, nrhs, m,& -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*m + m*nrhs ) end if minwrk = max( 2_${ik}$*m + n, 2_${ik}$*m + m*nrhs ) end if end if minwrk = min( minwrk, maxwrk ) work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork rwork( 1_${ik}$ ) = lrwork if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_zlaset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) call stdlib${ii}$_dlaset( 'F', minmn, 1_${ik}$, zero, zero, s, 1_${ik}$ ) rank = 0_${ik}$ go to 10 end if ! scale b if max entry outside range [smlnum,bignum]. bnrm = stdlib${ii}$_zlange( 'M', m, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! if m < n make sure b(m+1:n,:) = 0 if( m=n ) then ! path 1 - overdetermined or exactly determined. mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns mm = n itau = 1_${ik}$ nwork = itau + n ! compute a=q*r. ! (rworkspace: need n) ! (cworkspace: need n, prefer n*nb) call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & info ) ! multiply b by transpose(q). ! (rworkspace: need n) ! (cworkspace: need nrhs, prefer nrhs*nb) call stdlib${ii}$_zunmqr( 'L', 'C', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & nwork ), lwork-nwork+1, info ) ! zero out below r. if( n>1_${ik}$ ) then call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if end if itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ie = 1_${ik}$ nrwork = ie + n ! bidiagonalize r in a. ! (rworkspace: need n) ! (cworkspace: need 2*n+mm, prefer 2*n+(mm+n)*nb) call stdlib${ii}$_zgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r. ! (cworkspace: need 2*n+nrhs, prefer 2*n+nrhs*nb) call stdlib${ii}$_zunmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_zlalsd( 'U', smlsiz, n, nrhs, s, rwork( ie ), b, ldb,rcond, rank, work( & nwork ), rwork( nrwork ),iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of r. call stdlib${ii}$_zunmbr( 'P', 'L', 'N', n, nrhs, n, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) else if( n>=mnthr .and. lwork>=4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) then ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm. ldwork = m if( lwork>=max( 4_${ik}$*m+m*lda+max( m, 2_${ik}$*m-4, nrhs, n-3*m ),m*lda+m+m*nrhs ) )ldwork = & lda itau = 1_${ik}$ nwork = m + 1_${ik}$ ! compute a=l*q. ! (cworkspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, info ) il = nwork ! copy l to work(il), zeroing out above its diagonal. call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero, work( il+ldwork ),ldwork ) itauq = il + ldwork*m itaup = itauq + m nwork = itaup + m ie = 1_${ik}$ nrwork = ie + m ! bidiagonalize l in work(il). ! (rworkspace: need m) ! (cworkspace: need m*m+4*m, prefer m*m+4*m+2*m*nb) call stdlib${ii}$_zgebrd( m, m, work( il ), ldwork, s, rwork( ie ),work( itauq ), work( & itaup ), work( nwork ),lwork-nwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l. ! (cworkspace: need m*m+4*m+nrhs, prefer m*m+4*m+nrhs*nb) call stdlib${ii}$_zunmbr( 'Q', 'L', 'C', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_zlalsd( 'U', smlsiz, m, nrhs, s, rwork( ie ), b, ldb,rcond, rank, work( & nwork ), rwork( nrwork ),iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of l. call stdlib${ii}$_zunmbr( 'P', 'L', 'N', m, nrhs, m, work( il ), ldwork,work( itaup ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! zero out below first m rows of b. call stdlib${ii}$_zlaset( 'F', n-m, nrhs, czero, czero, b( m+1, 1_${ik}$ ), ldb ) nwork = itau + m ! multiply transpose(q) by b. ! (cworkspace: need nrhs, prefer nrhs*nb) call stdlib${ii}$_zunmlq( 'L', 'C', n, nrhs, m, a, lda, work( itau ), b,ldb, work( nwork )& , lwork-nwork+1, info ) else ! path 2 - remaining underdetermined cases. itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ie = 1_${ik}$ nrwork = ie + m ! bidiagonalize a. ! (rworkspace: need m) ! (cworkspace: need 2*m+n, prefer 2*m+(m+n)*nb) call stdlib${ii}$_zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), work(& nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors. ! (cworkspace: need 2*m+nrhs, prefer 2*m+nrhs*nb) call stdlib${ii}$_zunmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_zlalsd( 'L', smlsiz, m, nrhs, s, rwork( ie ), b, ldb,rcond, rank, work( & nwork ), rwork( nrwork ),iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of a. call stdlib${ii}$_zunmbr( 'P', 'L', 'N', n, nrhs, m, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) end if ! undo scaling. if( iascl==1_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 10 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork rwork( 1_${ik}$ ) = lrwork return end subroutine stdlib${ii}$_zgelsd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$gelsd( m, n, nrhs, a, lda, b, ldb, s, rcond, rank,work, lwork, rwork, & !! ZGELSD: computes the minimum-norm solution to a real linear least !! squares problem: !! minimize 2-norm(| b - A*x |) !! using the singular value decomposition (SVD) of A. A is an M-by-N !! matrix which may be rank-deficient. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. !! The problem is solved in three steps: !! (1) Reduce the coefficient matrix A to bidiagonal form with !! Householder transformations, reducing the original problem !! into a "bidiagonal least squares problem" (BLS) !! (2) Solve the BLS using a divide and conquer approach. !! (3) Apply back all the Householder transformations to solve !! the original least squares problem. !! The effective rank of A is determined by treating as zero those !! singular values which are less than RCOND times the largest singular !! value. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs real(${ck}$), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(out) :: rwork(*), s(*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: iascl, ibscl, ie, il, itau, itaup, itauq, ldwork, liwork, lrwork, & maxmn, maxwrk, minmn, minwrk, mm, mnthr, nlvl, nrwork, nwork, smlsiz real(${ck}$) :: anrm, bignum, bnrm, eps, sfmin, smlnum ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ minmn = min( m, n ) maxmn = max( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then smlsiz = stdlib${ii}$_ilaenv( 9_${ik}$, 'ZGELSD', ' ', 0_${ik}$, 0_${ik}$, 0_${ik}$, 0_${ik}$ ) mnthr = stdlib${ii}$_ilaenv( 6_${ik}$, 'ZGELSD', ' ', m, n, nrhs, -1_${ik}$ ) nlvl = max( int( log( real( minmn,KIND=${ck}$) / real( smlsiz + 1_${ik}$,KIND=${ck}$) ) /log( & two ),KIND=${ik}$) + 1_${ik}$, 0_${ik}$ ) liwork = 3_${ik}$*minmn*nlvl + 11_${ik}$*minmn mm = m if( m>=n .and. m>=mnthr ) then ! path 1a - overdetermined, with many more rows than ! columns. mm = n maxwrk = max( maxwrk, n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', m, n,-1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', 'LC', m,nrhs, n, -1_${ik}$ ) ) end if if( m>=n ) then ! path 1 - overdetermined or exactly determined. lrwork = 10_${ik}$*n + 2_${ik}$*n*smlsiz + 8_${ik}$*n*nlvl + 3_${ik}$*smlsiz*nrhs +max( (smlsiz+1)**2_${ik}$, n*(& 1_${ik}$+nrhs) + 2_${ik}$*nrhs ) maxwrk = max( maxwrk, 2_${ik}$*n + ( mm + n )*stdlib${ii}$_ilaenv( 1_${ik}$,'ZGEBRD', ' ', mm, n, & -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*n + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMBR','QLC', mm, nrhs, & n, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'ZUNMBR', 'PLN', n, & nrhs, n, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*n + n*nrhs ) minwrk = max( 2_${ik}$*n + mm, 2_${ik}$*n + n*nrhs ) end if if( n>m ) then lrwork = 10_${ik}$*m + 2_${ik}$*m*smlsiz + 8_${ik}$*m*nlvl + 3_${ik}$*smlsiz*nrhs +max( (smlsiz+1)**2_${ik}$, n*(& 1_${ik}$+nrhs) + 2_${ik}$*nrhs ) if( n>=mnthr ) then ! path 2a - underdetermined, with many more columns ! than rows. maxwrk = m + m*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQF', ' ', m, n, -1_${ik}$,-1_${ik}$ ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + 2_${ik}$*m*stdlib${ii}$_ilaenv( 1_${ik}$,'ZGEBRD', ' ', m, m,& -1_${ik}$, -1_${ik}$ ) ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$,'ZUNMBR', 'QLC', m,& nrhs, m, -1_${ik}$ ) ) maxwrk = max( maxwrk, m*m + 4_${ik}$*m + ( m - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'ZUNMLQ', & 'LC', n, nrhs, m, -1_${ik}$ ) ) if( nrhs>1_${ik}$ ) then maxwrk = max( maxwrk, m*m + m + m*nrhs ) else maxwrk = max( maxwrk, m*m + 2_${ik}$*m ) end if maxwrk = max( maxwrk, m*m + 4_${ik}$*m + m*nrhs ) ! xxx: ensure the path 2a case below is triggered. the workspace ! calculation should use queries for all routines eventually. maxwrk = max( maxwrk,4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) else ! path 2 - underdetermined. maxwrk = 2_${ik}$*m + ( n + m )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEBRD', ' ', m,n, -1_${ik}$, -1_${ik}$ ) maxwrk = max( maxwrk, 2_${ik}$*m + nrhs*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMBR','QLC', m, nrhs,& m, -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*m + m*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMBR','PLN', n, nrhs, m,& -1_${ik}$ ) ) maxwrk = max( maxwrk, 2_${ik}$*m + m*nrhs ) end if minwrk = max( 2_${ik}$*m + n, 2_${ik}$*m + m*nrhs ) end if end if minwrk = min( minwrk, maxwrk ) work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork rwork( 1_${ik}$ ) = lrwork if( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_${ci}$laset( 'F', max( m, n ), nrhs, czero, czero, b, ldb ) call stdlib${ii}$_${c2ri(ci)}$laset( 'F', minmn, 1_${ik}$, zero, zero, s, 1_${ik}$ ) rank = 0_${ik}$ go to 10 end if ! scale b if max entry outside range [smlnum,bignum]. bnrm = stdlib${ii}$_${ci}$lange( 'M', m, nrhs, b, ldb, rwork ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum. call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, m, nrhs, b, ldb, info ) ibscl = 2_${ik}$ end if ! if m < n make sure b(m+1:n,:) = 0 if( m=n ) then ! path 1 - overdetermined or exactly determined. mm = m if( m>=mnthr ) then ! path 1a - overdetermined, with many more rows than columns mm = n itau = 1_${ik}$ nwork = itau + n ! compute a=q*r. ! (rworkspace: need n) ! (cworkspace: need n, prefer n*nb) call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & info ) ! multiply b by transpose(q). ! (rworkspace: need n) ! (cworkspace: need nrhs, prefer nrhs*nb) call stdlib${ii}$_${ci}$unmqr( 'L', 'C', m, nrhs, n, a, lda, work( itau ), b,ldb, work( & nwork ), lwork-nwork+1, info ) ! zero out below r. if( n>1_${ik}$ ) then call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) end if end if itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ie = 1_${ik}$ nrwork = ie + n ! bidiagonalize r in a. ! (rworkspace: need n) ! (cworkspace: need 2*n+mm, prefer 2*n+(mm+n)*nb) call stdlib${ii}$_${ci}$gebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors of r. ! (cworkspace: need 2*n+nrhs, prefer 2*n+nrhs*nb) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_${ci}$lalsd( 'U', smlsiz, n, nrhs, s, rwork( ie ), b, ldb,rcond, rank, work( & nwork ), rwork( nrwork ),iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of r. call stdlib${ii}$_${ci}$unmbr( 'P', 'L', 'N', n, nrhs, n, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) else if( n>=mnthr .and. lwork>=4_${ik}$*m+m*m+max( m, 2_${ik}$*m-4, nrhs, n-3*m ) ) then ! path 2a - underdetermined, with many more columns than rows ! and sufficient workspace for an efficient algorithm. ldwork = m if( lwork>=max( 4_${ik}$*m+m*lda+max( m, 2_${ik}$*m-4, nrhs, n-3*m ),m*lda+m+m*nrhs ) )ldwork = & lda itau = 1_${ik}$ nwork = m + 1_${ik}$ ! compute a=l*q. ! (cworkspace: need 2*m, prefer m+m*nb) call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, info ) il = nwork ! copy l to work(il), zeroing out above its diagonal. call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, work( il ), ldwork ) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero, work( il+ldwork ),ldwork ) itauq = il + ldwork*m itaup = itauq + m nwork = itaup + m ie = 1_${ik}$ nrwork = ie + m ! bidiagonalize l in work(il). ! (rworkspace: need m) ! (cworkspace: need m*m+4*m, prefer m*m+4*m+2*m*nb) call stdlib${ii}$_${ci}$gebrd( m, m, work( il ), ldwork, s, rwork( ie ),work( itauq ), work( & itaup ), work( nwork ),lwork-nwork+1, info ) ! multiply b by transpose of left bidiagonalizing vectors of l. ! (cworkspace: need m*m+4*m+nrhs, prefer m*m+4*m+nrhs*nb) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'C', m, nrhs, m, work( il ), ldwork,work( itauq ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_${ci}$lalsd( 'U', smlsiz, m, nrhs, s, rwork( ie ), b, ldb,rcond, rank, work( & nwork ), rwork( nrwork ),iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of l. call stdlib${ii}$_${ci}$unmbr( 'P', 'L', 'N', m, nrhs, m, work( il ), ldwork,work( itaup ), b, & ldb, work( nwork ),lwork-nwork+1, info ) ! zero out below first m rows of b. call stdlib${ii}$_${ci}$laset( 'F', n-m, nrhs, czero, czero, b( m+1, 1_${ik}$ ), ldb ) nwork = itau + m ! multiply transpose(q) by b. ! (cworkspace: need nrhs, prefer nrhs*nb) call stdlib${ii}$_${ci}$unmlq( 'L', 'C', n, nrhs, m, a, lda, work( itau ), b,ldb, work( nwork )& , lwork-nwork+1, info ) else ! path 2 - remaining underdetermined cases. itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ie = 1_${ik}$ nrwork = ie + m ! bidiagonalize a. ! (rworkspace: need m) ! (cworkspace: need 2*m+n, prefer 2*m+(m+n)*nb) call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), work(& nwork ), lwork-nwork+1,info ) ! multiply b by transpose of left bidiagonalizing vectors. ! (cworkspace: need 2*m+nrhs, prefer 2*m+nrhs*nb) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda, work( itauq ),b, ldb, work( & nwork ), lwork-nwork+1, info ) ! solve the bidiagonal least squares problem. call stdlib${ii}$_${ci}$lalsd( 'L', smlsiz, m, nrhs, s, rwork( ie ), b, ldb,rcond, rank, work( & nwork ), rwork( nrwork ),iwork, info ) if( info/=0_${ik}$ ) then go to 10 end if ! multiply b by right bidiagonalizing vectors of a. call stdlib${ii}$_${ci}$unmbr( 'P', 'L', 'N', n, nrhs, m, a, lda, work( itaup ),b, ldb, work( & nwork ), lwork-nwork+1, info ) end if ! undo scaling. if( iascl==1_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, n, nrhs, b, ldb, info ) call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, anrm, minmn, 1_${ik}$, s, minmn,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, n, nrhs, b, ldb, info ) call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, n, nrhs, b, ldb, info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, n, nrhs, b, ldb, info ) end if 10 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwork rwork( 1_${ik}$ ) = lrwork return end subroutine stdlib${ii}$_${ci}$gelsd #:endif #:endfor module subroutine stdlib${ii}$_sgetsls( trans, m, n, nrhs, a, lda, b, ldb,work, lwork, info ) !! SGETSLS solves overdetermined or underdetermined real linear systems !! involving an M-by-N matrix A, using a tall skinny QR or short wide LQ !! factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'T' and m >= n: find the minimum norm solution of !! an undetermined system A**T * X = B. !! 4. If TRANS = 'T' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**T * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tran integer(${ik}$) :: i, iascl, ibscl, j, maxmn, brow, scllen, tszo, tszm, lwo, lwm, lw1, & lw2, wsizeo, wsizem, info2 real(sp) :: anrm, bignum, bnrm, smlnum, tq(5_${ik}$), workq(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ maxmn = max( m, n ) tran = stdlib_lsame( trans, 'T' ) lquery = ( lwork==-1_${ik}$ .or. lwork==-2_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or.stdlib_lsame( trans, 'T' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then call stdlib${ii}$_sgeqr( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_sgemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_sgeqr( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_sgemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm else call stdlib${ii}$_sgelq( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_sgemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_sgelq( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_sgemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm end if if( ( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_slaset( 'F', maxmn, nrhs, zero, zero, b, ldb ) go to 50 end if brow = m if ( tran ) then brow = n end if bnrm = stdlib${ii}$_slange( 'M', brow, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if ( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_sgeqr( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) if ( .not.tran ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**t * b(1:m,1:nrhs) call stdlib${ii}$_sgemqr( 'L' , 'T', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, work(& 1_${ik}$ ), lw2,info ) ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_strtrs( 'U', 'N', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = n else ! overdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**t) * b(1:n,1:nrhs) call stdlib${ii}$_strtrs( 'U', 'T', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = zero do j = 1, nrhs do i = n + 1, m b( i, j ) = zero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_sgemqr( 'L', 'N', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_sgelq( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) ! workspace at least m, optimally m*nb. if( .not.tran ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_strtrs( 'L', 'N', 'N', m, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = zero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**t * b(1:m,1:nrhs) call stdlib${ii}$_sgemlq( 'L', 'T', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**t * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_sgemlq( 'L', 'N', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**t) * b(1:m,1:nrhs) call stdlib${ii}$_strtrs( 'LOWER', 'TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( tszo + lwo,KIND=sp) return end subroutine stdlib${ii}$_sgetsls module subroutine stdlib${ii}$_dgetsls( trans, m, n, nrhs, a, lda, b, ldb,work, lwork, info ) !! DGETSLS solves overdetermined or underdetermined real linear systems !! involving an M-by-N matrix A, using a tall skinny QR or short wide LQ !! factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'T' and m >= n: find the minimum norm solution of !! an undetermined system A**T * X = B. !! 4. If TRANS = 'T' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**T * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tran integer(${ik}$) :: i, iascl, ibscl, j, maxmn, brow, scllen, tszo, tszm, lwo, lwm, lw1, & lw2, wsizeo, wsizem, info2 real(dp) :: anrm, bignum, bnrm, smlnum, tq(5_${ik}$), workq(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ maxmn = max( m, n ) tran = stdlib_lsame( trans, 'T' ) lquery = ( lwork==-1_${ik}$ .or. lwork==-2_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or.stdlib_lsame( trans, 'T' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then call stdlib${ii}$_dgeqr( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_dgemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_dgeqr( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_dgemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm else call stdlib${ii}$_dgelq( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_dgemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_dgelq( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_dgemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm end if if( ( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_dlaset( 'F', maxmn, nrhs, zero, zero, b, ldb ) go to 50 end if brow = m if ( tran ) then brow = n end if bnrm = stdlib${ii}$_dlange( 'M', brow, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if ( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_dgeqr( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) if ( .not.tran ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**t * b(1:m,1:nrhs) call stdlib${ii}$_dgemqr( 'L' , 'T', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, work(& 1_${ik}$ ), lw2,info ) ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_dtrtrs( 'U', 'N', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = n else ! overdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**t) * b(1:n,1:nrhs) call stdlib${ii}$_dtrtrs( 'U', 'T', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = zero do j = 1, nrhs do i = n + 1, m b( i, j ) = zero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_dgemqr( 'L', 'N', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_dgelq( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) ! workspace at least m, optimally m*nb. if( .not.tran ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_dtrtrs( 'L', 'N', 'N', m, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = zero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**t * b(1:m,1:nrhs) call stdlib${ii}$_dgemlq( 'L', 'T', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**t * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_dgemlq( 'L', 'N', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**t) * b(1:m,1:nrhs) call stdlib${ii}$_dtrtrs( 'LOWER', 'TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( tszo + lwo,KIND=dp) return end subroutine stdlib${ii}$_dgetsls #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$getsls( trans, m, n, nrhs, a, lda, b, ldb,work, lwork, info ) !! DGETSLS: solves overdetermined or underdetermined real linear systems !! involving an M-by-N matrix A, using a tall skinny QR or short wide LQ !! factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'T' and m >= n: find the minimum norm solution of !! an undetermined system A**T * X = B. !! 4. If TRANS = 'T' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**T * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tran integer(${ik}$) :: i, iascl, ibscl, j, maxmn, brow, scllen, tszo, tszm, lwo, lwm, lw1, & lw2, wsizeo, wsizem, info2 real(${rk}$) :: anrm, bignum, bnrm, smlnum, tq(5_${ik}$), workq(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ maxmn = max( m, n ) tran = stdlib_lsame( trans, 'T' ) lquery = ( lwork==-1_${ik}$ .or. lwork==-2_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or.stdlib_lsame( trans, 'T' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then call stdlib${ii}$_${ri}$geqr( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_${ri}$gemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ri}$geqr( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_${ri}$gemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm else call stdlib${ii}$_${ri}$gelq( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_${ri}$gemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ri}$gelq( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_${ri}$gemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm end if if( ( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_${ri}$laset( 'F', maxmn, nrhs, zero, zero, b, ldb ) go to 50 end if brow = m if ( tran ) then brow = n end if bnrm = stdlib${ii}$_${ri}$lange( 'M', brow, nrhs, b, ldb, work ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if ( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_${ri}$geqr( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) if ( .not.tran ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**t * b(1:m,1:nrhs) call stdlib${ii}$_${ri}$gemqr( 'L' , 'T', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, work(& 1_${ik}$ ), lw2,info ) ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_${ri}$trtrs( 'U', 'N', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = n else ! overdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**t) * b(1:n,1:nrhs) call stdlib${ii}$_${ri}$trtrs( 'U', 'T', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = zero do j = 1, nrhs do i = n + 1, m b( i, j ) = zero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_${ri}$gemqr( 'L', 'N', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_${ri}$gelq( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) ! workspace at least m, optimally m*nb. if( .not.tran ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_${ri}$trtrs( 'L', 'N', 'N', m, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = zero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**t * b(1:m,1:nrhs) call stdlib${ii}$_${ri}$gemlq( 'L', 'T', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**t * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_${ri}$gemlq( 'L', 'N', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**t) * b(1:m,1:nrhs) call stdlib${ii}$_${ri}$trtrs( 'LOWER', 'TRANSPOSE', 'NON-UNIT', m, nrhs,a, lda, b, ldb, & info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( tszo + lwo,KIND=${rk}$) return end subroutine stdlib${ii}$_${ri}$getsls #:endif #:endfor module subroutine stdlib${ii}$_cgetsls( trans, m, n, nrhs, a, lda, b, ldb,work, lwork, info ) !! CGETSLS solves overdetermined or underdetermined complex linear systems !! involving an M-by-N matrix A, using a tall skinny QR or short wide LQ !! factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'C' and m >= n: find the minimum norm solution of !! an undetermined system A**T * X = B. !! 4. If TRANS = 'C' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**T * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tran integer(${ik}$) :: i, iascl, ibscl, j, maxmn, brow, scllen, tszo, tszm, lwo, lwm, lw1, & lw2, wsizeo, wsizem, info2 real(sp) :: anrm, bignum, bnrm, smlnum, dum(1_${ik}$) complex(sp) :: tq(5_${ik}$), workq(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ maxmn = max( m, n ) tran = stdlib_lsame( trans, 'C' ) lquery = ( lwork==-1_${ik}$ .or. lwork==-2_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or.stdlib_lsame( trans, 'C' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then call stdlib${ii}$_cgeqr( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_cgemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_cgeqr( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_cgemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm else call stdlib${ii}$_cgelq( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_cgemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_cgelq( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_cgemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm end if if( ( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_claset( 'F', maxmn, nrhs, czero, czero, b, ldb ) go to 50 end if brow = m if ( tran ) then brow = n end if bnrm = stdlib${ii}$_clange( 'M', brow, nrhs, b, ldb, dum ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if ( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_cgeqr( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) if ( .not.tran ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**t * b(1:m,1:nrhs) call stdlib${ii}$_cgemqr( 'L' , 'C', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, work(& 1_${ik}$ ), lw2,info ) ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_ctrtrs( 'U', 'N', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = n else ! overdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**t) * b(1:n,1:nrhs) call stdlib${ii}$_ctrtrs( 'U', 'C', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = czero do j = 1, nrhs do i = n + 1, m b( i, j ) = czero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_cgemqr( 'L', 'N', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_cgelq( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) ! workspace at least m, optimally m*nb. if( .not.tran ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_ctrtrs( 'L', 'N', 'N', m, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = czero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**t * b(1:m,1:nrhs) call stdlib${ii}$_cgemlq( 'L', 'C', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**t * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_cgemlq( 'L', 'N', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**t) * b(1:m,1:nrhs) call stdlib${ii}$_ctrtrs( 'L', 'C', 'N', m, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( tszo + lwo,KIND=sp) return end subroutine stdlib${ii}$_cgetsls module subroutine stdlib${ii}$_zgetsls( trans, m, n, nrhs, a, lda, b, ldb,work, lwork, info ) !! ZGETSLS solves overdetermined or underdetermined complex linear systems !! involving an M-by-N matrix A, using a tall skinny QR or short wide LQ !! factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'C' and m >= n: find the minimum norm solution of !! an undetermined system A**T * X = B. !! 4. If TRANS = 'C' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**T * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tran integer(${ik}$) :: i, iascl, ibscl, j, maxmn, brow, scllen, tszo, tszm, lwo, lwm, lw1, & lw2, wsizeo, wsizem, info2 real(dp) :: anrm, bignum, bnrm, smlnum, dum(1_${ik}$) complex(dp) :: tq(5_${ik}$), workq(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ maxmn = max( m, n ) tran = stdlib_lsame( trans, 'C' ) lquery = ( lwork==-1_${ik}$ .or. lwork==-2_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or.stdlib_lsame( trans, 'C' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then call stdlib${ii}$_zgeqr( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_zgemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_zgeqr( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_zgemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm else call stdlib${ii}$_zgelq( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_zgemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_zgelq( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_zgemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm end if if( ( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_zlaset( 'F', maxmn, nrhs, czero, czero, b, ldb ) go to 50 end if brow = m if ( tran ) then brow = n end if bnrm = stdlib${ii}$_zlange( 'M', brow, nrhs, b, ldb, dum ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if ( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_zgeqr( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) if ( .not.tran ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**t * b(1:m,1:nrhs) call stdlib${ii}$_zgemqr( 'L' , 'C', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, work(& 1_${ik}$ ), lw2,info ) ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_ztrtrs( 'U', 'N', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = n else ! overdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**t) * b(1:n,1:nrhs) call stdlib${ii}$_ztrtrs( 'U', 'C', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = czero do j = 1, nrhs do i = n + 1, m b( i, j ) = czero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_zgemqr( 'L', 'N', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_zgelq( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) ! workspace at least m, optimally m*nb. if( .not.tran ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_ztrtrs( 'L', 'N', 'N', m, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = czero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**t * b(1:m,1:nrhs) call stdlib${ii}$_zgemlq( 'L', 'C', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**t * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_zgemlq( 'L', 'N', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**t) * b(1:m,1:nrhs) call stdlib${ii}$_ztrtrs( 'L', 'C', 'N', m, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( tszo + lwo,KIND=dp) return end subroutine stdlib${ii}$_zgetsls #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$getsls( trans, m, n, nrhs, a, lda, b, ldb,work, lwork, info ) !! ZGETSLS: solves overdetermined or underdetermined complex linear systems !! involving an M-by-N matrix A, using a tall skinny QR or short wide LQ !! factorization of A. It is assumed that A has full rank. !! The following options are provided: !! 1. If TRANS = 'N' and m >= n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A*X ||. !! 2. If TRANS = 'N' and m < n: find the minimum norm solution of !! an underdetermined system A * X = B. !! 3. If TRANS = 'C' and m >= n: find the minimum norm solution of !! an undetermined system A**T * X = B. !! 4. If TRANS = 'C' and m < n: find the least squares solution of !! an overdetermined system, i.e., solve the least squares problem !! minimize || B - A**T * X ||. !! Several right hand side vectors b and solution vectors x can be !! handled in a single call; they are stored as the columns of the !! M-by-NRHS right hand side matrix B and the N-by-NRHS solution !! matrix X. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, nrhs ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, tran integer(${ik}$) :: i, iascl, ibscl, j, maxmn, brow, scllen, tszo, tszm, lwo, lwm, lw1, & lw2, wsizeo, wsizem, info2 real(${ck}$) :: anrm, bignum, bnrm, smlnum, dum(1_${ik}$) complex(${ck}$) :: tq(5_${ik}$), workq(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ maxmn = max( m, n ) tran = stdlib_lsame( trans, 'C' ) lquery = ( lwork==-1_${ik}$ .or. lwork==-2_${ik}$ ) if( .not.( stdlib_lsame( trans, 'N' ) .or.stdlib_lsame( trans, 'C' ) ) ) then info = -1_${ik}$ else if( m<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( lda=n ) then call stdlib${ii}$_${ci}$geqr( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_${ci}$gemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ci}$geqr( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_${ci}$gemqr( 'L', trans, m, nrhs, n, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm else call stdlib${ii}$_${ci}$gelq( m, n, a, lda, tq, -1_${ik}$, workq, -1_${ik}$, info2 ) tszo = int( tq( 1_${ik}$ ),KIND=${ik}$) lwo = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_${ci}$gemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszo, b, ldb, workq, -1_${ik}$, & info2 ) lwo = max( lwo, int( workq( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ci}$gelq( m, n, a, lda, tq, -2_${ik}$, workq, -2_${ik}$, info2 ) tszm = int( tq( 1_${ik}$ ),KIND=${ik}$) lwm = int( workq( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_${ci}$gemlq( 'L', trans, n, nrhs, m, a, lda, tq,tszm, b, ldb, workq, -1_${ik}$, & info2 ) lwm = max( lwm, int( workq( 1_${ik}$ ),KIND=${ik}$) ) wsizeo = tszo + lwo wsizem = tszm + lwm end if if( ( lworkzero .and. anrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, info ) iascl = 2_${ik}$ else if( anrm==zero ) then ! matrix all zero. return zero solution. call stdlib${ii}$_${ci}$laset( 'F', maxmn, nrhs, czero, czero, b, ldb ) go to 50 end if brow = m if ( tran ) then brow = n end if bnrm = stdlib${ii}$_${ci}$lange( 'M', brow, nrhs, b, ldb, dum ) ibscl = 0_${ik}$ if( bnrm>zero .and. bnrmbignum ) then ! scale matrix norm down to bignum call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bignum, brow, nrhs, b, ldb,info ) ibscl = 2_${ik}$ end if if ( m>=n ) then ! compute qr factorization of a call stdlib${ii}$_${ci}$geqr( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) if ( .not.tran ) then ! least-squares problem min || a * x - b || ! b(1:m,1:nrhs) := q**t * b(1:m,1:nrhs) call stdlib${ii}$_${ci}$gemqr( 'L' , 'C', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, work(& 1_${ik}$ ), lw2,info ) ! b(1:n,1:nrhs) := inv(r) * b(1:n,1:nrhs) call stdlib${ii}$_${ci}$trtrs( 'U', 'N', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = n else ! overdetermined system of equations a**t * x = b ! b(1:n,1:nrhs) := inv(r**t) * b(1:n,1:nrhs) call stdlib${ii}$_${ci}$trtrs( 'U', 'C', 'N', n, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(n+1:m,1:nrhs) = czero do j = 1, nrhs do i = n + 1, m b( i, j ) = czero end do end do ! b(1:m,1:nrhs) := q(1:n,:) * b(1:n,1:nrhs) call stdlib${ii}$_${ci}$gemqr( 'L', 'N', m, nrhs, n, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) scllen = m end if else ! compute lq factorization of a call stdlib${ii}$_${ci}$gelq( m, n, a, lda, work( lw2+1 ), lw1,work( 1_${ik}$ ), lw2, info ) ! workspace at least m, optimally m*nb. if( .not.tran ) then ! underdetermined system of equations a * x = b ! b(1:m,1:nrhs) := inv(l) * b(1:m,1:nrhs) call stdlib${ii}$_${ci}$trtrs( 'L', 'N', 'N', m, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if ! b(m+1:n,1:nrhs) = 0 do j = 1, nrhs do i = m + 1, n b( i, j ) = czero end do end do ! b(1:n,1:nrhs) := q(1:n,:)**t * b(1:m,1:nrhs) call stdlib${ii}$_${ci}$gemlq( 'L', 'C', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb scllen = n else ! overdetermined system min || a**t * x - b || ! b(1:n,1:nrhs) := q * b(1:n,1:nrhs) call stdlib${ii}$_${ci}$gemlq( 'L', 'N', n, nrhs, m, a, lda,work( lw2+1 ), lw1, b, ldb, & work( 1_${ik}$ ), lw2,info ) ! workspace at least nrhs, optimally nrhs*nb ! b(1:m,1:nrhs) := inv(l**t) * b(1:m,1:nrhs) call stdlib${ii}$_${ci}$trtrs( 'L', 'C', 'N', m, nrhs,a, lda, b, ldb, info ) if( info>0_${ik}$ ) then return end if scllen = m end if end if ! undo scaling if( iascl==1_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, smlnum, scllen, nrhs, b, ldb,info ) else if( iascl==2_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, scllen, nrhs, b, ldb,info ) end if if( ibscl==1_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, smlnum, bnrm, scllen, nrhs, b, ldb,info ) else if( ibscl==2_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, bnrm, scllen, nrhs, b, ldb,info ) end if 50 continue work( 1_${ik}$ ) = real( tszo + lwo,KIND=${ck}$) return end subroutine stdlib${ii}$_${ci}$getsls #:endif #:endfor #:endfor end submodule stdlib_lapack_lsq fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_cosine_sine2.fypp0000664000175000017500000110266115135654166026353 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_cosine_sine2 implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES recursive module subroutine stdlib${ii}$_sorcsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, x11, & !! SORCSD computes the CS decomposition of an M-by-M partitioned !! orthogonal matrix X: !! [ I 0 0 | 0 0 0 ] !! [ 0 C 0 | 0 -S 0 ] !! [ X11 | X12 ] [ U1 | ] [ 0 0 0 | 0 0 -I ] [ V1 | ]**T !! X = [-----------] = [---------] [---------------------] [---------] . !! [ X21 | X22 ] [ | U2 ] [ 0 0 0 | I 0 0 ] [ | V2 ] !! [ 0 S 0 | 0 C 0 ] !! [ 0 0 I | 0 0 0 ] !! X11 is P-by-Q. The orthogonal matrices U1, U2, V1, and V2 are P-by-P, !! (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are !! R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in !! which R = MIN(P,M-P,Q,M-Q). ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, & work, lwork, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12, ldx21, ldx22, & lwork, m, p, q ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: theta(*) real(sp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*), work(*) real(sp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! =================================================================== ! Local Arrays real(sp) :: dummy(1_${ik}$) ! Local Scalars character :: transt, signst integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, itauq2, j, lbbcsdwork, & lbbcsdworkmin, lbbcsdworkopt, lorbdbwork, lorbdbworkmin, lorbdbworkopt, lorglqwork, & lorglqworkmin, lorglqworkopt, lorgqrwork, lorgqrworkmin, lorgqrworkopt, lworkmin, & lworkopt logical(lk) :: colmajor, defaultsigns, lquery, wantu1, wantu2, wantv1t, wantv2t ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) defaultsigns = .not. stdlib_lsame( signs, 'O' ) lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -7_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -8_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -9_${ik}$ else if ( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -11_${ik}$ else if (.not. colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if (colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if (.not. colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ else if (colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -15_${ik}$ else if (.not. colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -15_${ik}$ else if (colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -17_${ik}$ else if (.not. colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -17_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -20_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -22_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -24_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -26_${ik}$ end if ! work with transpose if convenient if( info == 0_${ik}$ .and. min( p, m-p ) < min( q, m-q ) ) then if( colmajor ) then transt = 'T' else transt = 'N' end if if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_sorcsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,q, p, x11, & ldx11, x21, ldx21, x12, ldx12, x22,ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,& u2, ldu2, work, lwork, iwork, info ) return end if ! work with permutation [ 0 i; i 0 ] * x * [ 0 i; i 0 ] if ! convenient if( info == 0_${ik}$ .and. m-q < q ) then if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_sorcsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,m-p, m-q, x22, & ldx22, x21, ldx21, x12, ldx12, x11,ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, & v1t,ldv1t, work, lwork, iwork, info ) return end if ! compute workspace if( info == 0_${ik}$ ) then iphi = 2_${ik}$ itaup1 = iphi + max( 1_${ik}$, q - 1_${ik}$ ) itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m - p ) itauq2 = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_sorgqr( m-q, m-q, m-q, dummy, max(1_${ik}$,m-q), dummy, work, -1_${ik}$,childinfo ) lorgqrworkopt = int( work(1_${ik}$),KIND=${ik}$) lorgqrworkmin = max( 1_${ik}$, m - q ) iorglq = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_sorglq( m-q, m-q, m-q, dummy, max(1_${ik}$,m-q), dummy, work, -1_${ik}$,childinfo ) lorglqworkopt = int( work(1_${ik}$),KIND=${ik}$) lorglqworkmin = max( 1_${ik}$, m - q ) iorbdb = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_sorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & ldx22, dummy, dummy, dummy, dummy, dummy,dummy,work,-1_${ik}$,childinfo ) lorbdbworkopt = int( work(1_${ik}$),KIND=${ik}$) lorbdbworkmin = lorbdbworkopt ib11d = itauq2 + max( 1_${ik}$, m - q ) ib11e = ib11d + max( 1_${ik}$, q ) ib12d = ib11e + max( 1_${ik}$, q - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, q ) ib21d = ib12e + max( 1_${ik}$, q - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, q ) ib22d = ib21e + max( 1_${ik}$, q - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, q ) ibbcsd = ib22e + max( 1_${ik}$, q - 1_${ik}$ ) call stdlib${ii}$_sbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,dummy, dummy, u1, & ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, dummy, dummy, dummy, dummy, dummy, dummy,& dummy, dummy, work, -1_${ik}$, childinfo ) lbbcsdworkopt = int( work(1_${ik}$),KIND=${ik}$) lbbcsdworkmin = lbbcsdworkopt lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,iorbdb + & lorbdbworkopt, ibbcsd + lbbcsdworkopt ) - 1_${ik}$ lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,iorbdb + & lorbdbworkopt, ibbcsd + lbbcsdworkmin ) - 1_${ik}$ work(1_${ik}$) = max(lworkopt,lworkmin) if( lwork < lworkmin .and. .not. lquery ) then info = -22_${ik}$ else lorgqrwork = lwork - iorgqr + 1_${ik}$ lorglqwork = lwork - iorglq + 1_${ik}$ lorbdbwork = lwork - iorbdb + 1_${ik}$ lbbcsdwork = lwork - ibbcsd + 1_${ik}$ end if end if ! abort if any illegal arguments if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SORCSD', -info ) return else if( lquery ) then return end if ! transform to bidiagonal block form call stdlib${ii}$_sorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,ldx21, x22, & ldx22, theta, work(iphi), work(itaup1),work(itaup2), work(itauq1), work(itauq2),work(& iorbdb), lorbdbwork, childinfo ) ! accumulate householder reflectors if( colmajor ) then if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_sorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqrwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_sorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqrwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'U', q-1, q-1, x11(1_${ik}$,2_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = one do j = 2, q v1t(1_${ik}$,j) = zero v1t(j,1_${ik}$) = zero end do call stdlib${ii}$_sorglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglqwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'U', p, m-q, x12, ldx12, v2t, ldv2t ) call stdlib${ii}$_slacpy( 'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,v2t(p+1,p+1), ldv2t ) call stdlib${ii}$_sorglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorglq), & lorglqwork, info ) end if else if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'U', q, p, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_sorglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),lorglqwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'U', q, m-p, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_sorglq( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorglq), lorglqwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', q-1, q-1, x11(2_${ik}$,1_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = one do j = 2, q v1t(1_${ik}$,j) = zero v1t(j,1_${ik}$) = zero end do call stdlib${ii}$_sorgqr( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorgqr), & lorgqrwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', m-q, p, x12, ldx12, v2t, ldv2t ) call stdlib${ii}$_slacpy( 'L', m-p-q, m-p-q, x22(p+1,q+1), ldx22,v2t(p+1,p+1), ldv2t ) call stdlib${ii}$_sorgqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorgqr), & lorgqrwork, info ) end if end if ! compute the csd of the matrix in bidiagonal-block form call stdlib${ii}$_sbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,work(iphi), u1,& ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, work(ib11d), work(ib11e), work(ib12d),work(& ib12e), work(ib21d), work(ib21e), work(ib22d),work(ib22e), work(ibbcsd), lbbcsdwork, & info ) ! permute rows and columns to place identity submatrices in top- ! left corner of (1,1)-block and/or bottom-right corner of (1,2)- ! block and/or bottom-right corner of (2,1)-block and/or top-left ! corner of (2,2)-block if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do if( colmajor ) then call stdlib${ii}$_slapmt( .false., m-p, m-p, u2, ldu2, iwork ) else call stdlib${ii}$_slapmr( .false., m-p, m-p, u2, ldu2, iwork ) end if end if if( m > 0_${ik}$ .and. wantv2t ) then do i = 1, p iwork(i) = m - p - q + i end do do i = p + 1, m - q iwork(i) = i - p end do if( .not. colmajor ) then call stdlib${ii}$_slapmt( .false., m-q, m-q, v2t, ldv2t, iwork ) else call stdlib${ii}$_slapmr( .false., m-q, m-q, v2t, ldv2t, iwork ) end if end if return ! end stdlib${ii}$_sorcsd end subroutine stdlib${ii}$_sorcsd recursive module subroutine stdlib${ii}$_dorcsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, x11, & !! DORCSD computes the CS decomposition of an M-by-M partitioned !! orthogonal matrix X: !! [ I 0 0 | 0 0 0 ] !! [ 0 C 0 | 0 -S 0 ] !! [ X11 | X12 ] [ U1 | ] [ 0 0 0 | 0 0 -I ] [ V1 | ]**T !! X = [-----------] = [---------] [---------------------] [---------] . !! [ X21 | X22 ] [ | U2 ] [ 0 0 0 | I 0 0 ] [ | V2 ] !! [ 0 S 0 | 0 C 0 ] !! [ 0 0 I | 0 0 0 ] !! X11 is P-by-Q. The orthogonal matrices U1, U2, V1, and V2 are P-by-P, !! (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are !! R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in !! which R = MIN(P,M-P,Q,M-Q). ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, & work, lwork, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12, ldx21, ldx22, & lwork, m, p, q ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(out) :: theta(*) real(dp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*), work(*) real(dp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! =================================================================== ! Local Scalars character :: transt, signst integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, itauq2, j, lbbcsdwork, & lbbcsdworkmin, lbbcsdworkopt, lorbdbwork, lorbdbworkmin, lorbdbworkopt, lorglqwork, & lorglqworkmin, lorglqworkopt, lorgqrwork, lorgqrworkmin, lorgqrworkopt, lworkmin, & lworkopt logical(lk) :: colmajor, defaultsigns, lquery, wantu1, wantu2, wantv1t, wantv2t ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) defaultsigns = .not. stdlib_lsame( signs, 'O' ) lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -7_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -8_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -9_${ik}$ else if ( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -11_${ik}$ else if (.not. colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if (colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if (.not. colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ else if (colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -15_${ik}$ else if (.not. colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -15_${ik}$ else if (colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -17_${ik}$ else if (.not. colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -17_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -20_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -22_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -24_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -26_${ik}$ end if ! work with transpose if convenient if( info == 0_${ik}$ .and. min( p, m-p ) < min( q, m-q ) ) then if( colmajor ) then transt = 'T' else transt = 'N' end if if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_dorcsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,q, p, x11, & ldx11, x21, ldx21, x12, ldx12, x22,ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,& u2, ldu2, work, lwork, iwork, info ) return end if ! work with permutation [ 0 i; i 0 ] * x * [ 0 i; i 0 ] if ! convenient if( info == 0_${ik}$ .and. m-q < q ) then if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_dorcsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,m-p, m-q, x22, & ldx22, x21, ldx21, x12, ldx12, x11,ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, & v1t,ldv1t, work, lwork, iwork, info ) return end if ! compute workspace if( info == 0_${ik}$ ) then iphi = 2_${ik}$ itaup1 = iphi + max( 1_${ik}$, q - 1_${ik}$ ) itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m - p ) itauq2 = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_dorgqr( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo ) lorgqrworkopt = int( work(1_${ik}$),KIND=${ik}$) lorgqrworkmin = max( 1_${ik}$, m - q ) iorglq = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_dorglq( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo ) lorglqworkopt = int( work(1_${ik}$),KIND=${ik}$) lorglqworkmin = max( 1_${ik}$, m - q ) iorbdb = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_dorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & ldx22, theta, v1t, u1, u2, v1t,v2t, work, -1_${ik}$, childinfo ) lorbdbworkopt = int( work(1_${ik}$),KIND=${ik}$) lorbdbworkmin = lorbdbworkopt ib11d = itauq2 + max( 1_${ik}$, m - q ) ib11e = ib11d + max( 1_${ik}$, q ) ib12d = ib11e + max( 1_${ik}$, q - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, q ) ib21d = ib12e + max( 1_${ik}$, q - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, q ) ib22d = ib21e + max( 1_${ik}$, q - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, q ) ibbcsd = ib22e + max( 1_${ik}$, q - 1_${ik}$ ) call stdlib${ii}$_dbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, theta, u1, & ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, u1, u1, u1, u1, u1, u1, u1, u1, work, -1_${ik}$,& childinfo ) lbbcsdworkopt = int( work(1_${ik}$),KIND=${ik}$) lbbcsdworkmin = lbbcsdworkopt lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,iorbdb + & lorbdbworkopt, ibbcsd + lbbcsdworkopt ) - 1_${ik}$ lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,iorbdb + & lorbdbworkopt, ibbcsd + lbbcsdworkmin ) - 1_${ik}$ work(1_${ik}$) = max(lworkopt,lworkmin) if( lwork < lworkmin .and. .not. lquery ) then info = -22_${ik}$ else lorgqrwork = lwork - iorgqr + 1_${ik}$ lorglqwork = lwork - iorglq + 1_${ik}$ lorbdbwork = lwork - iorbdb + 1_${ik}$ lbbcsdwork = lwork - ibbcsd + 1_${ik}$ end if end if ! abort if any illegal arguments if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORCSD', -info ) return else if( lquery ) then return end if ! transform to bidiagonal block form call stdlib${ii}$_dorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,ldx21, x22, & ldx22, theta, work(iphi), work(itaup1),work(itaup2), work(itauq1), work(itauq2),work(& iorbdb), lorbdbwork, childinfo ) ! accumulate householder reflectors if( colmajor ) then if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqrwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqrwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'U', q-1, q-1, x11(1_${ik}$,2_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = one do j = 2, q v1t(1_${ik}$,j) = zero v1t(j,1_${ik}$) = zero end do call stdlib${ii}$_dorglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglqwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'U', p, m-q, x12, ldx12, v2t, ldv2t ) if (m-p > q) then call stdlib${ii}$_dlacpy( 'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,v2t(p+1,p+1), & ldv2t ) end if if (m > q) then call stdlib${ii}$_dorglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorglq), & lorglqwork, info ) end if end if else if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'U', q, p, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_dorglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),lorglqwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'U', q, m-p, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_dorglq( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorglq), lorglqwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', q-1, q-1, x11(2_${ik}$,1_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = one do j = 2, q v1t(1_${ik}$,j) = zero v1t(j,1_${ik}$) = zero end do call stdlib${ii}$_dorgqr( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorgqr), & lorgqrwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', m-q, p, x12, ldx12, v2t, ldv2t ) call stdlib${ii}$_dlacpy( 'L', m-p-q, m-p-q, x22(p+1,q+1), ldx22,v2t(p+1,p+1), ldv2t ) call stdlib${ii}$_dorgqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorgqr), & lorgqrwork, info ) end if end if ! compute the csd of the matrix in bidiagonal-block form call stdlib${ii}$_dbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,work(iphi), u1,& ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, work(ib11d), work(ib11e), work(ib12d),work(& ib12e), work(ib21d), work(ib21e), work(ib22d),work(ib22e), work(ibbcsd), lbbcsdwork, & info ) ! permute rows and columns to place identity submatrices in top- ! left corner of (1,1)-block and/or bottom-right corner of (1,2)- ! block and/or bottom-right corner of (2,1)-block and/or top-left ! corner of (2,2)-block if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do if( colmajor ) then call stdlib${ii}$_dlapmt( .false., m-p, m-p, u2, ldu2, iwork ) else call stdlib${ii}$_dlapmr( .false., m-p, m-p, u2, ldu2, iwork ) end if end if if( m > 0_${ik}$ .and. wantv2t ) then do i = 1, p iwork(i) = m - p - q + i end do do i = p + 1, m - q iwork(i) = i - p end do if( .not. colmajor ) then call stdlib${ii}$_dlapmt( .false., m-q, m-q, v2t, ldv2t, iwork ) else call stdlib${ii}$_dlapmr( .false., m-q, m-q, v2t, ldv2t, iwork ) end if end if return ! end stdlib${ii}$_dorcsd end subroutine stdlib${ii}$_dorcsd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] recursive module subroutine stdlib${ii}$_${ri}$orcsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, x11, & !! DORCSD: computes the CS decomposition of an M-by-M partitioned !! orthogonal matrix X: !! [ I 0 0 | 0 0 0 ] !! [ 0 C 0 | 0 -S 0 ] !! [ X11 | X12 ] [ U1 | ] [ 0 0 0 | 0 0 -I ] [ V1 | ]**T !! X = [-----------] = [---------] [---------------------] [---------] . !! [ X21 | X22 ] [ | U2 ] [ 0 0 0 | I 0 0 ] [ | V2 ] !! [ 0 S 0 | 0 C 0 ] !! [ 0 0 I | 0 0 0 ] !! X11 is P-by-Q. The orthogonal matrices U1, U2, V1, and V2 are P-by-P, !! (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are !! R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in !! which R = MIN(P,M-P,Q,M-Q). ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, & work, lwork, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12, ldx21, ldx22, & lwork, m, p, q ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(out) :: theta(*) real(${rk}$), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*), work(*) real(${rk}$), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! =================================================================== ! Local Scalars character :: transt, signst integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, itauq2, j, lbbcsdwork, & lbbcsdworkmin, lbbcsdworkopt, lorbdbwork, lorbdbworkmin, lorbdbworkopt, lorglqwork, & lorglqworkmin, lorglqworkopt, lorgqrwork, lorgqrworkmin, lorgqrworkopt, lworkmin, & lworkopt logical(lk) :: colmajor, defaultsigns, lquery, wantu1, wantu2, wantv1t, wantv2t ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) defaultsigns = .not. stdlib_lsame( signs, 'O' ) lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -7_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -8_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -9_${ik}$ else if ( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -11_${ik}$ else if (.not. colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if (colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if (.not. colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ else if (colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -15_${ik}$ else if (.not. colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -15_${ik}$ else if (colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -17_${ik}$ else if (.not. colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -17_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -20_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -22_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -24_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -26_${ik}$ end if ! work with transpose if convenient if( info == 0_${ik}$ .and. min( p, m-p ) < min( q, m-q ) ) then if( colmajor ) then transt = 'T' else transt = 'N' end if if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_${ri}$orcsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,q, p, x11, & ldx11, x21, ldx21, x12, ldx12, x22,ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,& u2, ldu2, work, lwork, iwork, info ) return end if ! work with permutation [ 0 i; i 0 ] * x * [ 0 i; i 0 ] if ! convenient if( info == 0_${ik}$ .and. m-q < q ) then if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_${ri}$orcsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,m-p, m-q, x22, & ldx22, x21, ldx21, x12, ldx12, x11,ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, & v1t,ldv1t, work, lwork, iwork, info ) return end if ! compute workspace if( info == 0_${ik}$ ) then iphi = 2_${ik}$ itaup1 = iphi + max( 1_${ik}$, q - 1_${ik}$ ) itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m - p ) itauq2 = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_${ri}$orgqr( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo ) lorgqrworkopt = int( work(1_${ik}$),KIND=${ik}$) lorgqrworkmin = max( 1_${ik}$, m - q ) iorglq = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_${ri}$orglq( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo ) lorglqworkopt = int( work(1_${ik}$),KIND=${ik}$) lorglqworkmin = max( 1_${ik}$, m - q ) iorbdb = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_${ri}$orbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & ldx22, theta, v1t, u1, u2, v1t,v2t, work, -1_${ik}$, childinfo ) lorbdbworkopt = int( work(1_${ik}$),KIND=${ik}$) lorbdbworkmin = lorbdbworkopt ib11d = itauq2 + max( 1_${ik}$, m - q ) ib11e = ib11d + max( 1_${ik}$, q ) ib12d = ib11e + max( 1_${ik}$, q - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, q ) ib21d = ib12e + max( 1_${ik}$, q - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, q ) ib22d = ib21e + max( 1_${ik}$, q - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, q ) ibbcsd = ib22e + max( 1_${ik}$, q - 1_${ik}$ ) call stdlib${ii}$_${ri}$bbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, theta, u1, & ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, u1, u1, u1, u1, u1, u1, u1, u1, work, -1_${ik}$,& childinfo ) lbbcsdworkopt = int( work(1_${ik}$),KIND=${ik}$) lbbcsdworkmin = lbbcsdworkopt lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,iorbdb + & lorbdbworkopt, ibbcsd + lbbcsdworkopt ) - 1_${ik}$ lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,iorbdb + & lorbdbworkopt, ibbcsd + lbbcsdworkmin ) - 1_${ik}$ work(1_${ik}$) = max(lworkopt,lworkmin) if( lwork < lworkmin .and. .not. lquery ) then info = -22_${ik}$ else lorgqrwork = lwork - iorgqr + 1_${ik}$ lorglqwork = lwork - iorglq + 1_${ik}$ lorbdbwork = lwork - iorbdb + 1_${ik}$ lbbcsdwork = lwork - ibbcsd + 1_${ik}$ end if end if ! abort if any illegal arguments if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORCSD', -info ) return else if( lquery ) then return end if ! transform to bidiagonal block form call stdlib${ii}$_${ri}$orbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,ldx21, x22, & ldx22, theta, work(iphi), work(itaup1),work(itaup2), work(itauq1), work(itauq2),work(& iorbdb), lorbdbwork, childinfo ) ! accumulate householder reflectors if( colmajor ) then if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_${ri}$orgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqrwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_${ri}$orgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqrwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'U', q-1, q-1, x11(1_${ik}$,2_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = one do j = 2, q v1t(1_${ik}$,j) = zero v1t(j,1_${ik}$) = zero end do call stdlib${ii}$_${ri}$orglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglqwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'U', p, m-q, x12, ldx12, v2t, ldv2t ) if (m-p > q) then call stdlib${ii}$_${ri}$lacpy( 'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,v2t(p+1,p+1), & ldv2t ) end if if (m > q) then call stdlib${ii}$_${ri}$orglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorglq), & lorglqwork, info ) end if end if else if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'U', q, p, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_${ri}$orglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),lorglqwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'U', q, m-p, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_${ri}$orglq( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorglq), lorglqwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', q-1, q-1, x11(2_${ik}$,1_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = one do j = 2, q v1t(1_${ik}$,j) = zero v1t(j,1_${ik}$) = zero end do call stdlib${ii}$_${ri}$orgqr( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorgqr), & lorgqrwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', m-q, p, x12, ldx12, v2t, ldv2t ) call stdlib${ii}$_${ri}$lacpy( 'L', m-p-q, m-p-q, x22(p+1,q+1), ldx22,v2t(p+1,p+1), ldv2t ) call stdlib${ii}$_${ri}$orgqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorgqr), & lorgqrwork, info ) end if end if ! compute the csd of the matrix in bidiagonal-block form call stdlib${ii}$_${ri}$bbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,work(iphi), u1,& ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, work(ib11d), work(ib11e), work(ib12d),work(& ib12e), work(ib21d), work(ib21e), work(ib22d),work(ib22e), work(ibbcsd), lbbcsdwork, & info ) ! permute rows and columns to place identity submatrices in top- ! left corner of (1,1)-block and/or bottom-right corner of (1,2)- ! block and/or bottom-right corner of (2,1)-block and/or top-left ! corner of (2,2)-block if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do if( colmajor ) then call stdlib${ii}$_${ri}$lapmt( .false., m-p, m-p, u2, ldu2, iwork ) else call stdlib${ii}$_${ri}$lapmr( .false., m-p, m-p, u2, ldu2, iwork ) end if end if if( m > 0_${ik}$ .and. wantv2t ) then do i = 1, p iwork(i) = m - p - q + i end do do i = p + 1, m - q iwork(i) = i - p end do if( .not. colmajor ) then call stdlib${ii}$_${ri}$lapmt( .false., m-q, m-q, v2t, ldv2t, iwork ) else call stdlib${ii}$_${ri}$lapmr( .false., m-q, m-q, v2t, ldv2t, iwork ) end if end if return ! end stdlib${ii}$_${ri}$orcsd end subroutine stdlib${ii}$_${ri}$orcsd #:endif #:endfor module subroutine stdlib${ii}$_sorcsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta, & !! SORCSD2BY1 computes the CS decomposition of an M-by-Q matrix X with !! orthonormal columns that has been partitioned into a 2-by-1 block !! structure: !! [ I1 0 0 ] !! [ 0 C 0 ] !! [ X11 ] [ U1 | ] [ 0 0 0 ] !! X = [-----] = [---------] [----------] V1**T . !! [ X21 ] [ | U2 ] [ 0 0 0 ] !! [ 0 S 0 ] !! [ 0 0 I2] !! X11 is P-by-Q. The orthogonal matrices U1, U2, and V1 are P-by-P, !! (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R !! nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which !! R = MIN(P,M-P,Q,M-Q). I1 is a K1-by-K1 identity matrix and I2 is a !! K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0). u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, lwork, ldx11, ldx21, m, p, q ! Array Arguments real(sp), intent(out) :: theta(*) real(sp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), work(*) real(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, j, lbbcsd, lorbdb, & lorglq, lorglqmin, lorglqopt, lorgqr, lorgqrmin, lorgqropt, lworkmin, lworkopt, & r logical(lk) :: lquery, wantu1, wantu2, wantv1t ! Local Arrays real(sp) :: dum1(1_${ik}$), dum2(1_${ik}$,1_${ik}$) ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -4_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -5_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -6_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -8_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -10_${ik}$ else if( wantu1 .and. ldu1 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if( wantu2 .and. ldu2 < max( 1_${ik}$, m - p ) ) then info = -15_${ik}$ else if( wantv1t .and. ldv1t < max( 1_${ik}$, q ) ) then info = -17_${ik}$ end if r = min( p, m-p, q, m-q ) ! compute workspace ! work layout: ! |-------------------------------------------------------| ! | lworkopt (1) | ! |-------------------------------------------------------| ! | phi (max(1,r-1)) | ! |-------------------------------------------------------| ! | taup1 (max(1,p)) | b11d (r) | ! | taup2 (max(1,m-p)) | b11e (r-1) | ! | tauq1 (max(1,q)) | b12d (r) | ! |-----------------------------------------| b12e (r-1) | ! | stdlib${ii}$_sorbdb work | stdlib${ii}$_sorgqr work | stdlib${ii}$_sorglq work | b21d (r) | ! | | | | b21e (r-1) | ! | | | | b22d (r) | ! | | | | b22e (r-1) | ! | | | | stdlib${ii}$_sbbcsd work | ! |-------------------------------------------------------| if( info == 0_${ik}$ ) then iphi = 2_${ik}$ ib11d = iphi + max( 1_${ik}$, r-1 ) ib11e = ib11d + max( 1_${ik}$, r ) ib12d = ib11e + max( 1_${ik}$, r - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, r ) ib21d = ib12e + max( 1_${ik}$, r - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, r ) ib22d = ib21e + max( 1_${ik}$, r - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, r ) ibbcsd = ib22e + max( 1_${ik}$, r - 1_${ik}$ ) itaup1 = iphi + max( 1_${ik}$, r-1 ) itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m-p ) iorbdb = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq1 + max( 1_${ik}$, q ) iorglq = itauq1 + max( 1_${ik}$, q ) lorgqrmin = 1_${ik}$ lorgqropt = 1_${ik}$ lorglqmin = 1_${ik}$ lorglqopt = 1_${ik}$ if( r == q ) then call stdlib${ii}$_sorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1, work, -1_${ik}$,childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_sorgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) endif if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_sorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_sorglq( q-1, q-1, q-1, v1t, ldv1t,dum1, work(1_${ik}$), -1_${ik}$, childinfo ) lorglqmin = max( lorglqmin, q-1 ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_sbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,dum1, u1, & ldu1, u2, ldu2, v1t, ldv1t, dum2,1_${ik}$, dum1, dum1, dum1, dum1, dum1,dum1, dum1, & dum1, work(1_${ik}$), -1_${ik}$, childinfo) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) else if( r == p ) then call stdlib${ii}$_sorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_sorgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, dum1,work(1_${ik}$), -1_${ik}$, childinfo & ) lorgqrmin = max( lorgqrmin, p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_sorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_sorglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_sbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,dum1, v1t, & ldv1t, dum2, 1_${ik}$, u1, ldu1, u2,ldu2, dum1, dum1, dum1, dum1, dum1,dum1, dum1, dum1,& work(1_${ik}$), -1_${ik}$, childinfo) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) else if( r == m-p ) then call stdlib${ii}$_sorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_sorgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_sorgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2, dum1,work(1_${ik}$), -1_${ik}$, & childinfo ) lorgqrmin = max( lorgqrmin, m-p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_sorglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_sbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, dum1, & dum2, 1_${ik}$, v1t, ldv1t, u2, ldu2,u1, ldu1, dum1, dum1, dum1, dum1,dum1, dum1, dum1, & dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) else call stdlib${ii}$_sorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1, dum1,work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = m + int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_sorgqr( p, p, m-q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_sorgqr( m-p, m-p, m-q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_sorglq( q, q, q, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_sbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, dum1, u2, & ldu2, u1, ldu1, dum2, 1_${ik}$,v1t, ldv1t, dum1, dum1, dum1, dum1,dum1, dum1, dum1, & dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) end if lworkmin = max( iorbdb+lorbdb-1,iorgqr+lorgqrmin-1,iorglq+lorglqmin-1,ibbcsd+lbbcsd-& 1_${ik}$ ) lworkopt = max( iorbdb+lorbdb-1,iorgqr+lorgqropt-1,iorglq+lorglqopt-1,ibbcsd+lbbcsd-& 1_${ik}$ ) work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -19_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SORCSD2BY1', -info ) return else if( lquery ) then return end if lorgqr = lwork-iorgqr+1 lorglq = lwork-iorglq+1 ! handle four cases separately: r = q, r = p, r = m-p, and r = m-q, ! in which r = min(p,m-p,q,m-q) if( r == q ) then ! case 1: r = q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_sorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_sorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_sorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then v1t(1_${ik}$,1_${ik}$) = one do j = 2, q v1t(1_${ik}$,j) = zero v1t(j,1_${ik}$) = zero end do call stdlib${ii}$_slacpy( 'U', q-1, q-1, x21(1_${ik}$,2_${ik}$), ldx21, v1t(2_${ik}$,2_${ik}$),ldv1t ) call stdlib${ii}$_sorglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglq, childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_sbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,work(iphi), u1, & ldu1, u2, ldu2, v1t, ldv1t,dum2, 1_${ik}$, work(ib11d), work(ib11e), work(ib12d),work(& ib12e), work(ib21d), work(ib21e),work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,& childinfo ) ! permute rows and columns to place zero submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_slapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == p ) then ! case 2: r = p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_sorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then u1(1_${ik}$,1_${ik}$) = one do j = 2, p u1(1_${ik}$,j) = zero u1(j,1_${ik}$) = zero end do call stdlib${ii}$_slacpy( 'L', p-1, p-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$), ldu1 ) call stdlib${ii}$_sorgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, work(itaup1),work(iorgqr), & lorgqr, childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_sorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'U', p, q, x11, ldx11, v1t, ldv1t ) call stdlib${ii}$_sorglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_sbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,work(iphi), v1t, & ldv1t, dum1, 1_${ik}$, u1, ldu1, u2,ldu2, work(ib11d), work(ib11e), work(ib12d),work(ib12e)& , work(ib21d), work(ib21e),work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,childinfo & ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_slapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == m-p ) then ! case 3: r = m-p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_sorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_sorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then u2(1_${ik}$,1_${ik}$) = one do j = 2, m-p u2(1_${ik}$,j) = zero u2(j,1_${ik}$) = zero end do call stdlib${ii}$_slacpy( 'L', m-p-1, m-p-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_sorgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,work(itaup2), work(iorgqr)& , lorgqr, childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'U', m-p, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_sorglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_sbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, work(iphi), & dum1, 1_${ik}$, v1t, ldv1t, u2,ldu2, u1, ldu1, work(ib11d), work(ib11e),work(ib12d), work(& ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, & childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > r ) then do i = 1, r iwork(i) = q - r + i end do do i = r + 1, q iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_slapmt( .false., p, q, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_slapmr( .false., q, q, v1t, ldv1t, iwork ) end if end if else ! case 4: r = m-q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_sorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), work(iorbdb+m),lorbdb-m, childinfo ) ! accumulate householder reflectors if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_scopy( m-p, work(iorbdb+p), 1_${ik}$, u2, 1_${ik}$ ) end if if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_scopy( p, work(iorbdb), 1_${ik}$, u1, 1_${ik}$ ) do j = 2, p u1(1_${ik}$,j) = zero end do call stdlib${ii}$_slacpy( 'L', p-1, m-q-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$),ldu1 ) call stdlib${ii}$_sorgqr( p, p, m-q, u1, ldu1, work(itaup1),work(iorgqr), lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then do j = 2, m-p u2(1_${ik}$,j) = zero end do call stdlib${ii}$_slacpy( 'L', m-p-1, m-q-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_sorgqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_slacpy( 'U', m-q, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_slacpy( 'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,v1t(m-q+1,m-q+& 1_${ik}$), ldv1t ) call stdlib${ii}$_slacpy( 'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,v1t(p+1,p+1), ldv1t ) call stdlib${ii}$_sorglq( q, q, q, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_sbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, work(iphi), & u2, ldu2, u1, ldu1, dum1, 1_${ik}$,v1t, ldv1t, work(ib11d), work(ib11e), work(ib12d),work(& ib12e), work(ib21d), work(ib21e),work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,& childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( p > r ) then do i = 1, r iwork(i) = p - r + i end do do i = r + 1, p iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_slapmt( .false., p, p, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_slapmr( .false., p, q, v1t, ldv1t, iwork ) end if end if end if return end subroutine stdlib${ii}$_sorcsd2by1 module subroutine stdlib${ii}$_dorcsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta, & !! DORCSD2BY1 computes the CS decomposition of an M-by-Q matrix X with !! orthonormal columns that has been partitioned into a 2-by-1 block !! structure: !! [ I1 0 0 ] !! [ 0 C 0 ] !! [ X11 ] [ U1 | ] [ 0 0 0 ] !! X = [-----] = [---------] [----------] V1**T . !! [ X21 ] [ | U2 ] [ 0 0 0 ] !! [ 0 S 0 ] !! [ 0 0 I2] !! X11 is P-by-Q. The orthogonal matrices U1, U2, and V1 are P-by-P, !! (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R !! nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which !! R = MIN(P,M-P,Q,M-Q). I1 is a K1-by-K1 identity matrix and I2 is a !! K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0). u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, iwork, info ) ! -- lapack computational routine (3.5.0_dp) -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, lwork, ldx11, ldx21, m, p, q ! Array Arguments real(dp), intent(out) :: theta(*) real(dp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), work(*) real(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, j, lbbcsd, lorbdb, & lorglq, lorglqmin, lorglqopt, lorgqr, lorgqrmin, lorgqropt, lworkmin, lworkopt, & r logical(lk) :: lquery, wantu1, wantu2, wantv1t ! Local Arrays real(dp) :: dum1(1_${ik}$), dum2(1_${ik}$,1_${ik}$) ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -4_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -5_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -6_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -8_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -10_${ik}$ else if( wantu1 .and. ldu1 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if( wantu2 .and. ldu2 < max( 1_${ik}$, m - p ) ) then info = -15_${ik}$ else if( wantv1t .and. ldv1t < max( 1_${ik}$, q ) ) then info = -17_${ik}$ end if r = min( p, m-p, q, m-q ) ! compute workspace ! work layout: ! |-------------------------------------------------------| ! | lworkopt (1) | ! |-------------------------------------------------------| ! | phi (max(1,r-1)) | ! |-------------------------------------------------------| ! | taup1 (max(1,p)) | b11d (r) | ! | taup2 (max(1,m-p)) | b11e (r-1) | ! | tauq1 (max(1,q)) | b12d (r) | ! |-----------------------------------------| b12e (r-1) | ! | stdlib${ii}$_dorbdb work | stdlib${ii}$_dorgqr work | stdlib${ii}$_dorglq work | b21d (r) | ! | | | | b21e (r-1) | ! | | | | b22d (r) | ! | | | | b22e (r-1) | ! | | | | stdlib${ii}$_dbbcsd work | ! |-------------------------------------------------------| if( info == 0_${ik}$ ) then iphi = 2_${ik}$ ib11d = iphi + max( 1_${ik}$, r-1 ) ib11e = ib11d + max( 1_${ik}$, r ) ib12d = ib11e + max( 1_${ik}$, r - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, r ) ib21d = ib12e + max( 1_${ik}$, r - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, r ) ib22d = ib21e + max( 1_${ik}$, r - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, r ) ibbcsd = ib22e + max( 1_${ik}$, r - 1_${ik}$ ) itaup1 = iphi + max( 1_${ik}$, r-1 ) itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m-p ) iorbdb = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq1 + max( 1_${ik}$, q ) iorglq = itauq1 + max( 1_${ik}$, q ) lorgqrmin = 1_${ik}$ lorgqropt = 1_${ik}$ lorglqmin = 1_${ik}$ lorglqopt = 1_${ik}$ if( r == q ) then call stdlib${ii}$_dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1, work,-1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_dorgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) endif if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_dorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_dorglq( q-1, q-1, q-1, v1t, ldv1t,dum1, work(1_${ik}$), -1_${ik}$, childinfo ) lorglqmin = max( lorglqmin, q-1 ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_dbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,dum1, u1, & ldu1, u2, ldu2, v1t, ldv1t,dum2, 1_${ik}$, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1,& work(1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) else if( r == p ) then call stdlib${ii}$_dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1,work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_dorgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, dum1,work(1_${ik}$), -1_${ik}$, childinfo & ) lorgqrmin = max( lorgqrmin, p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_dorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_dorglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_dbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,dum1, v1t, & ldv1t, dum2, 1_${ik}$, u1, ldu1,u2, ldu2, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1, & work(1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) else if( r == m-p ) then call stdlib${ii}$_dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1,work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_dorgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_dorgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,dum1, work(1_${ik}$), -1_${ik}$, & childinfo ) lorgqrmin = max( lorgqrmin, m-p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_dorglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_dbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, dum1, & dum2, 1_${ik}$, v1t, ldv1t, u2,ldu2, u1, ldu1, dum1, dum1, dum1,dum1, dum1, dum1, dum1,& dum1, work(1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) else call stdlib${ii}$_dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1,dum1, work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = m + int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_dorgqr( p, p, m-q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_dorgqr( m-p, m-p, m-q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_dorglq( q, q, q, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_dbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, dum1, u2, & ldu2, u1, ldu1, dum2,1_${ik}$, v1t, ldv1t, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1,& work(1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) end if lworkmin = max( iorbdb+lorbdb-1,iorgqr+lorgqrmin-1,iorglq+lorglqmin-1,ibbcsd+lbbcsd-& 1_${ik}$ ) lworkopt = max( iorbdb+lorbdb-1,iorgqr+lorgqropt-1,iorglq+lorglqopt-1,ibbcsd+lbbcsd-& 1_${ik}$ ) work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -19_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORCSD2BY1', -info ) return else if( lquery ) then return end if lorgqr = lwork-iorgqr+1 lorglq = lwork-iorglq+1 ! handle four cases separately: r = q, r = p, r = m-p, and r = m-q, ! in which r = min(p,m-p,q,m-q) if( r == q ) then ! case 1: r = q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then v1t(1_${ik}$,1_${ik}$) = one do j = 2, q v1t(1_${ik}$,j) = zero v1t(j,1_${ik}$) = zero end do call stdlib${ii}$_dlacpy( 'U', q-1, q-1, x21(1_${ik}$,2_${ik}$), ldx21, v1t(2_${ik}$,2_${ik}$),ldv1t ) call stdlib${ii}$_dorglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglq, childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_dbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,work(iphi), u1, & ldu1, u2, ldu2, v1t, ldv1t,dum2, 1_${ik}$, work(ib11d), work(ib11e),work(ib12d), work(& ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, & childinfo ) ! permute rows and columns to place zero submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_dlapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == p ) then ! case 2: r = p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then u1(1_${ik}$,1_${ik}$) = one do j = 2, p u1(1_${ik}$,j) = zero u1(j,1_${ik}$) = zero end do call stdlib${ii}$_dlacpy( 'L', p-1, p-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$), ldu1 ) call stdlib${ii}$_dorgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, work(itaup1),work(iorgqr), & lorgqr, childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'U', p, q, x11, ldx11, v1t, ldv1t ) call stdlib${ii}$_dorglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_dbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,work(iphi), v1t, & ldv1t, dum2, 1_${ik}$, u1, ldu1, u2,ldu2, work(ib11d), work(ib11e), work(ib12d),work(ib12e)& , work(ib21d), work(ib21e),work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,childinfo & ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_dlapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == m-p ) then ! case 3: r = m-p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then u2(1_${ik}$,1_${ik}$) = one do j = 2, m-p u2(1_${ik}$,j) = zero u2(j,1_${ik}$) = zero end do call stdlib${ii}$_dlacpy( 'L', m-p-1, m-p-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_dorgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,work(itaup2), work(iorgqr)& , lorgqr, childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'U', m-p, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_dorglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_dbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, work(iphi), & dum2, 1_${ik}$, v1t, ldv1t, u2,ldu2, u1, ldu1, work(ib11d), work(ib11e),work(ib12d), work(& ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, & childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > r ) then do i = 1, r iwork(i) = q - r + i end do do i = r + 1, q iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_dlapmt( .false., p, q, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_dlapmr( .false., q, q, v1t, ldv1t, iwork ) end if end if else ! case 4: r = m-q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), work(iorbdb+m),lorbdb-m, childinfo ) ! accumulate householder reflectors if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_dcopy( m-p, work(iorbdb+p), 1_${ik}$, u2, 1_${ik}$ ) end if if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_dcopy( p, work(iorbdb), 1_${ik}$, u1, 1_${ik}$ ) do j = 2, p u1(1_${ik}$,j) = zero end do call stdlib${ii}$_dlacpy( 'L', p-1, m-q-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$),ldu1 ) call stdlib${ii}$_dorgqr( p, p, m-q, u1, ldu1, work(itaup1),work(iorgqr), lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then do j = 2, m-p u2(1_${ik}$,j) = zero end do call stdlib${ii}$_dlacpy( 'L', m-p-1, m-q-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_dorgqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_dlacpy( 'U', m-q, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_dlacpy( 'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,v1t(m-q+1,m-q+& 1_${ik}$), ldv1t ) call stdlib${ii}$_dlacpy( 'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,v1t(p+1,p+1), ldv1t ) call stdlib${ii}$_dorglq( q, q, q, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_dbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, work(iphi), & u2, ldu2, u1, ldu1, dum2,1_${ik}$, v1t, ldv1t, work(ib11d), work(ib11e),work(ib12d), work(& ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, & childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( p > r ) then do i = 1, r iwork(i) = p - r + i end do do i = r + 1, p iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_dlapmt( .false., p, p, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_dlapmr( .false., p, q, v1t, ldv1t, iwork ) end if end if end if return end subroutine stdlib${ii}$_dorcsd2by1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$orcsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta, & !! DORCSD2BY1: computes the CS decomposition of an M-by-Q matrix X with !! orthonormal columns that has been partitioned into a 2-by-1 block !! structure: !! [ I1 0 0 ] !! [ 0 C 0 ] !! [ X11 ] [ U1 | ] [ 0 0 0 ] !! X = [-----] = [---------] [----------] V1**T . !! [ X21 ] [ | U2 ] [ 0 0 0 ] !! [ 0 S 0 ] !! [ 0 0 I2] !! X11 is P-by-Q. The orthogonal matrices U1, U2, and V1 are P-by-P, !! (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R !! nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which !! R = MIN(P,M-P,Q,M-Q). I1 is a K1-by-K1 identity matrix and I2 is a !! K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0). u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, iwork, info ) ! -- lapack computational routine (3.5.0_${rk}$) -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, lwork, ldx11, ldx21, m, p, q ! Array Arguments real(${rk}$), intent(out) :: theta(*) real(${rk}$), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), work(*) real(${rk}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, j, lbbcsd, lorbdb, & lorglq, lorglqmin, lorglqopt, lorgqr, lorgqrmin, lorgqropt, lworkmin, lworkopt, & r logical(lk) :: lquery, wantu1, wantu2, wantv1t ! Local Arrays real(${rk}$) :: dum1(1_${ik}$), dum2(1_${ik}$,1_${ik}$) ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -4_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -5_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -6_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -8_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -10_${ik}$ else if( wantu1 .and. ldu1 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if( wantu2 .and. ldu2 < max( 1_${ik}$, m - p ) ) then info = -15_${ik}$ else if( wantv1t .and. ldv1t < max( 1_${ik}$, q ) ) then info = -17_${ik}$ end if r = min( p, m-p, q, m-q ) ! compute workspace ! work layout: ! |-------------------------------------------------------| ! | lworkopt (1) | ! |-------------------------------------------------------| ! | phi (max(1,r-1)) | ! |-------------------------------------------------------| ! | taup1 (max(1,p)) | b11d (r) | ! | taup2 (max(1,m-p)) | b11e (r-1) | ! | tauq1 (max(1,q)) | b12d (r) | ! |-----------------------------------------| b12e (r-1) | ! | stdlib${ii}$_${ri}$orbdb work | stdlib${ii}$_${ri}$orgqr work | stdlib${ii}$_${ri}$orglq work | b21d (r) | ! | | | | b21e (r-1) | ! | | | | b22d (r) | ! | | | | b22e (r-1) | ! | | | | stdlib${ii}$_${ri}$bbcsd work | ! |-------------------------------------------------------| if( info == 0_${ik}$ ) then iphi = 2_${ik}$ ib11d = iphi + max( 1_${ik}$, r-1 ) ib11e = ib11d + max( 1_${ik}$, r ) ib12d = ib11e + max( 1_${ik}$, r - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, r ) ib21d = ib12e + max( 1_${ik}$, r - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, r ) ib22d = ib21e + max( 1_${ik}$, r - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, r ) ibbcsd = ib22e + max( 1_${ik}$, r - 1_${ik}$ ) itaup1 = iphi + max( 1_${ik}$, r-1 ) itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m-p ) iorbdb = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq1 + max( 1_${ik}$, q ) iorglq = itauq1 + max( 1_${ik}$, q ) lorgqrmin = 1_${ik}$ lorgqropt = 1_${ik}$ lorglqmin = 1_${ik}$ lorglqopt = 1_${ik}$ if( r == q ) then call stdlib${ii}$_${ri}$orbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1, work,-1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) endif if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orglq( q-1, q-1, q-1, v1t, ldv1t,dum1, work(1_${ik}$), -1_${ik}$, childinfo ) lorglqmin = max( lorglqmin, q-1 ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_${ri}$bbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,dum1, u1, & ldu1, u2, ldu2, v1t, ldv1t,dum2, 1_${ik}$, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1,& work(1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) else if( r == p ) then call stdlib${ii}$_${ri}$orbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1,work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, dum1,work(1_${ik}$), -1_${ik}$, childinfo & ) lorgqrmin = max( lorgqrmin, p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_${ri}$bbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,dum1, v1t, & ldv1t, dum2, 1_${ik}$, u1, ldu1,u2, ldu2, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1, & work(1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) else if( r == m-p ) then call stdlib${ii}$_${ri}$orbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1,work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,dum1, work(1_${ik}$), -1_${ik}$, & childinfo ) lorgqrmin = max( lorgqrmin, m-p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_${ri}$bbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, dum1, & dum2, 1_${ik}$, v1t, ldv1t, u2,ldu2, u1, ldu1, dum1, dum1, dum1,dum1, dum1, dum1, dum1,& dum1, work(1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) else call stdlib${ii}$_${ri}$orbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, & dum1,dum1, work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = m + int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orgqr( p, p, m-q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orgqr( m-p, m-p, m-q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ri}$orglq( q, q, q, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_${ri}$bbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, dum1, u2, & ldu2, u1, ldu1, dum2,1_${ik}$, v1t, ldv1t, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1,& work(1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( work(1_${ik}$),KIND=${ik}$) end if lworkmin = max( iorbdb+lorbdb-1,iorgqr+lorgqrmin-1,iorglq+lorglqmin-1,ibbcsd+lbbcsd-& 1_${ik}$ ) lworkopt = max( iorbdb+lorbdb-1,iorgqr+lorgqropt-1,iorglq+lorglqopt-1,ibbcsd+lbbcsd-& 1_${ik}$ ) work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -19_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORCSD2BY1', -info ) return else if( lquery ) then return end if lorgqr = lwork-iorgqr+1 lorglq = lwork-iorglq+1 ! handle four cases separately: r = q, r = p, r = m-p, and r = m-q, ! in which r = min(p,m-p,q,m-q) if( r == q ) then ! case 1: r = q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_${ri}$orbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_${ri}$orgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_${ri}$orgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then v1t(1_${ik}$,1_${ik}$) = one do j = 2, q v1t(1_${ik}$,j) = zero v1t(j,1_${ik}$) = zero end do call stdlib${ii}$_${ri}$lacpy( 'U', q-1, q-1, x21(1_${ik}$,2_${ik}$), ldx21, v1t(2_${ik}$,2_${ik}$),ldv1t ) call stdlib${ii}$_${ri}$orglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglq, childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_${ri}$bbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,work(iphi), u1, & ldu1, u2, ldu2, v1t, ldv1t,dum2, 1_${ik}$, work(ib11d), work(ib11e),work(ib12d), work(& ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, & childinfo ) ! permute rows and columns to place zero submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_${ri}$lapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == p ) then ! case 2: r = p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_${ri}$orbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then u1(1_${ik}$,1_${ik}$) = one do j = 2, p u1(1_${ik}$,j) = zero u1(j,1_${ik}$) = zero end do call stdlib${ii}$_${ri}$lacpy( 'L', p-1, p-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$), ldu1 ) call stdlib${ii}$_${ri}$orgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, work(itaup1),work(iorgqr), & lorgqr, childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_${ri}$orgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'U', p, q, x11, ldx11, v1t, ldv1t ) call stdlib${ii}$_${ri}$orglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_${ri}$bbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,work(iphi), v1t, & ldv1t, dum2, 1_${ik}$, u1, ldu1, u2,ldu2, work(ib11d), work(ib11e), work(ib12d),work(ib12e)& , work(ib21d), work(ib21e),work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,childinfo & ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_${ri}$lapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == m-p ) then ! case 3: r = m-p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_${ri}$orbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_${ri}$orgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then u2(1_${ik}$,1_${ik}$) = one do j = 2, m-p u2(1_${ik}$,j) = zero u2(j,1_${ik}$) = zero end do call stdlib${ii}$_${ri}$lacpy( 'L', m-p-1, m-p-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_${ri}$orgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,work(itaup2), work(iorgqr)& , lorgqr, childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'U', m-p, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_${ri}$orglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_${ri}$bbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, work(iphi), & dum2, 1_${ik}$, v1t, ldv1t, u2,ldu2, u1, ldu1, work(ib11d), work(ib11e),work(ib12d), work(& ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, & childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > r ) then do i = 1, r iwork(i) = q - r + i end do do i = r + 1, q iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_${ri}$lapmt( .false., p, q, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_${ri}$lapmr( .false., q, q, v1t, ldv1t, iwork ) end if end if else ! case 4: r = m-q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_${ri}$orbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)& , work(itaup2),work(itauq1), work(iorbdb), work(iorbdb+m),lorbdb-m, childinfo ) ! accumulate householder reflectors if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$copy( m-p, work(iorbdb+p), 1_${ik}$, u2, 1_${ik}$ ) end if if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ri}$copy( p, work(iorbdb), 1_${ik}$, u1, 1_${ik}$ ) do j = 2, p u1(1_${ik}$,j) = zero end do call stdlib${ii}$_${ri}$lacpy( 'L', p-1, m-q-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$),ldu1 ) call stdlib${ii}$_${ri}$orgqr( p, p, m-q, u1, ldu1, work(itaup1),work(iorgqr), lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then do j = 2, m-p u2(1_${ik}$,j) = zero end do call stdlib${ii}$_${ri}$lacpy( 'L', m-p-1, m-q-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_${ri}$orgqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'U', m-q, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_${ri}$lacpy( 'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,v1t(m-q+1,m-q+& 1_${ik}$), ldv1t ) call stdlib${ii}$_${ri}$lacpy( 'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,v1t(p+1,p+1), ldv1t ) call stdlib${ii}$_${ri}$orglq( q, q, q, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_${ri}$bbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, work(iphi), & u2, ldu2, u1, ldu1, dum2,1_${ik}$, v1t, ldv1t, work(ib11d), work(ib11e),work(ib12d), work(& ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, & childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( p > r ) then do i = 1, r iwork(i) = p - r + i end do do i = r + 1, p iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_${ri}$lapmt( .false., p, p, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_${ri}$lapmr( .false., p, q, v1t, ldv1t, iwork ) end if end if end if return end subroutine stdlib${ii}$_${ri}$orcsd2by1 #:endif #:endfor module subroutine stdlib${ii}$_sorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & !! SORBDB simultaneously bidiagonalizes the blocks of an M-by-M !! partitioned orthogonal matrix X: !! [ B11 | B12 0 0 ] !! [ X11 | X12 ] [ P1 | ] [ 0 | 0 -I 0 ] [ Q1 | ]**T !! X = [-----------] = [---------] [----------------] [---------] . !! [ X21 | X22 ] [ | P2 ] [ B21 | B22 0 0 ] [ | Q2 ] !! [ 0 | 0 0 I ] !! X11 is P-by-Q. Q must be no larger than P, M-P, or M-Q. (If this is !! not the case, then X must be transposed and/or permuted. This can be !! done in constant time using the TRANS and SIGNS options. See SORCSD !! for details.) !! The orthogonal matrices P1, P2, Q1, and Q2 are P-by-P, (M-P)-by- !! (M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. They are !! represented implicitly by Householder vectors. !! B11, B12, B21, and B22 are Q-by-Q bidiagonal matrices represented !! implicitly by angles THETA, PHI. ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldx11, ldx12, ldx21, ldx22, lwork, m, p, q ! Array Arguments real(sp), intent(out) :: phi(*), theta(*) real(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), tauq2(*), work(*) real(sp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! ==================================================================== ! Parameters ! Local Scalars logical(lk) :: colmajor, lquery integer(${ik}$) :: i, lworkmin, lworkopt real(sp) :: z1, z2, z3, z4 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ colmajor = .not. stdlib_lsame( trans, 'T' ) if( .not. stdlib_lsame( signs, 'O' ) ) then z1 = one z2 = one z3 = one z4 = one else z1 = one z2 = -one z3 = one z4 = -one end if lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -3_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -4_${ik}$ else if( q < 0_${ik}$ .or. q > p .or. q > m-p .or.q > m-q ) then info = -5_${ik}$ else if( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -7_${ik}$ else if( .not.colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -7_${ik}$ else if( colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -9_${ik}$ else if( .not.colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -9_${ik}$ else if( colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -11_${ik}$ else if( .not.colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if( colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -13_${ik}$ else if( .not.colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then lworkopt = m - q lworkmin = m - q work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not. lquery ) then info = -21_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'XORBDB', -info ) return else if( lquery ) then return end if ! handle column-major and row-major separately if( colmajor ) then ! reduce columns 1, ..., q of x11, x12, x21, and x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_sscal( p-i+1, z1, x11(i,i), 1_${ik}$ ) else call stdlib${ii}$_sscal( p-i+1, z1*cos(phi(i-1)), x11(i,i), 1_${ik}$ ) call stdlib${ii}$_saxpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i,i-1),1_${ik}$, x11(i,i), 1_${ik}$ ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_sscal( m-p-i+1, z2, x21(i,i), 1_${ik}$ ) else call stdlib${ii}$_sscal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), 1_${ik}$ ) call stdlib${ii}$_saxpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i,i-1),1_${ik}$, x21(i,i), & 1_${ik}$ ) end if theta(i) = atan2( stdlib${ii}$_snrm2( m-p-i+1, x21(i,i), 1_${ik}$ ),stdlib${ii}$_snrm2( p-i+1, x11(& i,i), 1_${ik}$ ) ) if( p > i ) then call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) else if( p == i ) then call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i,i), 1_${ik}$, taup1(i) ) end if x11(i,i) = one if ( m-p > i ) then call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$,taup2(i) ) else if ( m-p == i ) then call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i,i), 1_${ik}$, taup2(i) ) end if x21(i,i) = one if ( q > i ) then call stdlib${ii}$_slarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i),x11(i,i+1), ldx11, & work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_slarf( 'L', p-i+1, m-q-i+1, x11(i,i), 1_${ik}$, taup1(i),x12(i,i), ldx12,& work ) end if if ( q > i ) then call stdlib${ii}$_slarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21,& work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_slarf( 'L', m-p-i+1, m-q-i+1, x21(i,i), 1_${ik}$, taup2(i),x22(i,i), & ldx22, work ) end if if( i < q ) then call stdlib${ii}$_sscal( q-i, -z1*z3*sin(theta(i)), x11(i,i+1),ldx11 ) call stdlib${ii}$_saxpy( q-i, z2*z3*cos(theta(i)), x21(i,i+1), ldx21,x11(i,i+1), & ldx11 ) end if call stdlib${ii}$_sscal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), ldx12 ) call stdlib${ii}$_saxpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), ldx22,x12(i,i), ldx12 & ) if( i < q )phi(i) = atan2( stdlib${ii}$_snrm2( q-i, x11(i,i+1), ldx11 ),stdlib${ii}$_snrm2( & m-q-i+1, x12(i,i), ldx12 ) ) if( i < q ) then if ( q-i == 1_${ik}$ ) then call stdlib${ii}$_slarfgp( q-i, x11(i,i+1), x11(i,i+1), ldx11,tauq1(i) ) else call stdlib${ii}$_slarfgp( q-i, x11(i,i+1), x11(i,i+2), ldx11,tauq1(i) ) end if x11(i,i+1) = one end if if ( q+i-1 < m ) then if ( m-q == i ) then call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if end if x12(i,i) = one if( i < q ) then call stdlib${ii}$_slarf( 'R', p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x11(i+1,i+1), & ldx11, work ) call stdlib${ii}$_slarf( 'R', m-p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x21(i+1,i+1), & ldx21, work ) end if if ( p > i ) then call stdlib${ii}$_slarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if ( m-p > i ) then call stdlib${ii}$_slarf( 'R', m-p-i, m-q-i+1, x12(i,i), ldx12,tauq2(i), x22(i+1,i), & ldx22, work ) end if end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_sscal( m-q-i+1, -z1*z4, x12(i,i), ldx12 ) if ( i >= m-q ) then call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if x12(i,i) = one if ( p > i ) then call stdlib${ii}$_slarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_slarf( 'R', m-p-q, m-q-i+1, x12(i,i), ldx12,tauq2(i),& x22(q+1,i), ldx22, work ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_sscal( m-p-q-i+1, z2*z4, x22(q+i,p+i), ldx22 ) if ( i == m-p-q ) then call stdlib${ii}$_slarfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i),ldx22, tauq2(p+i) ) else call stdlib${ii}$_slarfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i+1),ldx22, tauq2(p+i)& ) end if x22(q+i,p+i) = one if ( i < m-p-q ) then call stdlib${ii}$_slarf( 'R', m-p-q-i, m-p-q-i+1, x22(q+i,p+i), ldx22,tauq2(p+i), & x22(q+i+1,p+i), ldx22, work ) end if end do else ! reduce columns 1, ..., q of x11, x12, x21, x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_sscal( p-i+1, z1, x11(i,i), ldx11 ) else call stdlib${ii}$_sscal( p-i+1, z1*cos(phi(i-1)), x11(i,i), ldx11 ) call stdlib${ii}$_saxpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i-1,i),ldx12, x11(i,i),& ldx11 ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_sscal( m-p-i+1, z2, x21(i,i), ldx21 ) else call stdlib${ii}$_sscal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), ldx21 ) call stdlib${ii}$_saxpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i-1,i),ldx22, x21(i,& i), ldx21 ) end if theta(i) = atan2( stdlib${ii}$_snrm2( m-p-i+1, x21(i,i), ldx21 ),stdlib${ii}$_snrm2( p-i+1, & x11(i,i), ldx11 ) ) call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i,i+1), ldx11, taup1(i) ) x11(i,i) = one if ( i == m-p ) then call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i,i), ldx21,taup2(i) ) else call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i,i+1), ldx21,taup2(i) ) end if x21(i,i) = one if ( q > i ) then call stdlib${ii}$_slarf( 'R', q-i, p-i+1, x11(i,i), ldx11, taup1(i),x11(i+1,i), & ldx11, work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_slarf( 'R', m-q-i+1, p-i+1, x11(i,i), ldx11,taup1(i), x12(i,i), & ldx12, work ) end if if ( q > i ) then call stdlib${ii}$_slarf( 'R', q-i, m-p-i+1, x21(i,i), ldx21, taup2(i),x21(i+1,i), & ldx21, work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_slarf( 'R', m-q-i+1, m-p-i+1, x21(i,i), ldx21,taup2(i), x22(i,i), & ldx22, work ) end if if( i < q ) then call stdlib${ii}$_sscal( q-i, -z1*z3*sin(theta(i)), x11(i+1,i), 1_${ik}$ ) call stdlib${ii}$_saxpy( q-i, z2*z3*cos(theta(i)), x21(i+1,i), 1_${ik}$,x11(i+1,i), 1_${ik}$ ) end if call stdlib${ii}$_sscal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), 1_${ik}$ ) call stdlib${ii}$_saxpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), 1_${ik}$,x12(i,i), 1_${ik}$ ) if( i < q )phi(i) = atan2( stdlib${ii}$_snrm2( q-i, x11(i+1,i), 1_${ik}$ ),stdlib${ii}$_snrm2( m-q-& i+1, x12(i,i), 1_${ik}$ ) ) if( i < q ) then if ( q-i == 1_${ik}$) then call stdlib${ii}$_slarfgp( q-i, x11(i+1,i), x11(i+1,i), 1_${ik}$,tauq1(i) ) else call stdlib${ii}$_slarfgp( q-i, x11(i+1,i), x11(i+2,i), 1_${ik}$,tauq1(i) ) end if x11(i+1,i) = one end if if ( m-q > i ) then call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$,tauq2(i) ) else call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i,i), 1_${ik}$,tauq2(i) ) end if x12(i,i) = one if( i < q ) then call stdlib${ii}$_slarf( 'L', q-i, p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x11(i+1,i+1), ldx11,& work ) call stdlib${ii}$_slarf( 'L', q-i, m-p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x21(i+1,i+1), & ldx21, work ) end if call stdlib${ii}$_slarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12, & work ) if ( m-p-i > 0_${ik}$ ) then call stdlib${ii}$_slarf( 'L', m-q-i+1, m-p-i, x12(i,i), 1_${ik}$, tauq2(i),x22(i,i+1), & ldx22, work ) end if end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_sscal( m-q-i+1, -z1*z4, x12(i,i), 1_${ik}$ ) call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) ) x12(i,i) = one if ( p > i ) then call stdlib${ii}$_slarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12,& work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_slarf( 'L', m-q-i+1, m-p-q, x12(i,i), 1_${ik}$, tauq2(i),& x22(i,q+1), ldx22, work ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_sscal( m-p-q-i+1, z2*z4, x22(p+i,q+i), 1_${ik}$ ) if ( m-p-q == i ) then call stdlib${ii}$_slarfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i,q+i), 1_${ik}$,tauq2(p+i) ) x22(p+i,q+i) = one else call stdlib${ii}$_slarfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i+1,q+i), 1_${ik}$,tauq2(p+i) ) x22(p+i,q+i) = one call stdlib${ii}$_slarf( 'L', m-p-q-i+1, m-p-q-i, x22(p+i,q+i), 1_${ik}$,tauq2(p+i), x22(p+& i,q+i+1), ldx22, work ) end if end do end if return end subroutine stdlib${ii}$_sorbdb module subroutine stdlib${ii}$_dorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & !! DORBDB simultaneously bidiagonalizes the blocks of an M-by-M !! partitioned orthogonal matrix X: !! [ B11 | B12 0 0 ] !! [ X11 | X12 ] [ P1 | ] [ 0 | 0 -I 0 ] [ Q1 | ]**T !! X = [-----------] = [---------] [----------------] [---------] . !! [ X21 | X22 ] [ | P2 ] [ B21 | B22 0 0 ] [ | Q2 ] !! [ 0 | 0 0 I ] !! X11 is P-by-Q. Q must be no larger than P, M-P, or M-Q. (If this is !! not the case, then X must be transposed and/or permuted. This can be !! done in constant time using the TRANS and SIGNS options. See DORCSD !! for details.) !! The orthogonal matrices P1, P2, Q1, and Q2 are P-by-P, (M-P)-by- !! (M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. They are !! represented implicitly by Householder vectors. !! B11, B12, B21, and B22 are Q-by-Q bidiagonal matrices represented !! implicitly by angles THETA, PHI. ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldx11, ldx12, ldx21, ldx22, lwork, m, p, q ! Array Arguments real(dp), intent(out) :: phi(*), theta(*) real(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), tauq2(*), work(*) real(dp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! ==================================================================== ! Parameters ! Local Scalars logical(lk) :: colmajor, lquery integer(${ik}$) :: i, lworkmin, lworkopt real(dp) :: z1, z2, z3, z4 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ colmajor = .not. stdlib_lsame( trans, 'T' ) if( .not. stdlib_lsame( signs, 'O' ) ) then z1 = one z2 = one z3 = one z4 = one else z1 = one z2 = -one z3 = one z4 = -one end if lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -3_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -4_${ik}$ else if( q < 0_${ik}$ .or. q > p .or. q > m-p .or.q > m-q ) then info = -5_${ik}$ else if( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -7_${ik}$ else if( .not.colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -7_${ik}$ else if( colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -9_${ik}$ else if( .not.colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -9_${ik}$ else if( colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -11_${ik}$ else if( .not.colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if( colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -13_${ik}$ else if( .not.colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then lworkopt = m - q lworkmin = m - q work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not. lquery ) then info = -21_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'XORBDB', -info ) return else if( lquery ) then return end if ! handle column-major and row-major separately if( colmajor ) then ! reduce columns 1, ..., q of x11, x12, x21, and x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_dscal( p-i+1, z1, x11(i,i), 1_${ik}$ ) else call stdlib${ii}$_dscal( p-i+1, z1*cos(phi(i-1)), x11(i,i), 1_${ik}$ ) call stdlib${ii}$_daxpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i,i-1),1_${ik}$, x11(i,i), 1_${ik}$ ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_dscal( m-p-i+1, z2, x21(i,i), 1_${ik}$ ) else call stdlib${ii}$_dscal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), 1_${ik}$ ) call stdlib${ii}$_daxpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i,i-1),1_${ik}$, x21(i,i), & 1_${ik}$ ) end if theta(i) = atan2( stdlib${ii}$_dnrm2( m-p-i+1, x21(i,i), 1_${ik}$ ),stdlib${ii}$_dnrm2( p-i+1, x11(& i,i), 1_${ik}$ ) ) if( p > i ) then call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) else if( p == i ) then call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i,i), 1_${ik}$, taup1(i) ) end if x11(i,i) = one if ( m-p > i ) then call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$,taup2(i) ) else if ( m-p == i ) then call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i,i), 1_${ik}$, taup2(i) ) end if x21(i,i) = one if ( q > i ) then call stdlib${ii}$_dlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i),x11(i,i+1), ldx11, & work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_dlarf( 'L', p-i+1, m-q-i+1, x11(i,i), 1_${ik}$, taup1(i),x12(i,i), ldx12,& work ) end if if ( q > i ) then call stdlib${ii}$_dlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21,& work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_dlarf( 'L', m-p-i+1, m-q-i+1, x21(i,i), 1_${ik}$, taup2(i),x22(i,i), & ldx22, work ) end if if( i < q ) then call stdlib${ii}$_dscal( q-i, -z1*z3*sin(theta(i)), x11(i,i+1),ldx11 ) call stdlib${ii}$_daxpy( q-i, z2*z3*cos(theta(i)), x21(i,i+1), ldx21,x11(i,i+1), & ldx11 ) end if call stdlib${ii}$_dscal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), ldx12 ) call stdlib${ii}$_daxpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), ldx22,x12(i,i), ldx12 & ) if( i < q )phi(i) = atan2( stdlib${ii}$_dnrm2( q-i, x11(i,i+1), ldx11 ),stdlib${ii}$_dnrm2( & m-q-i+1, x12(i,i), ldx12 ) ) if( i < q ) then if ( q-i == 1_${ik}$ ) then call stdlib${ii}$_dlarfgp( q-i, x11(i,i+1), x11(i,i+1), ldx11,tauq1(i) ) else call stdlib${ii}$_dlarfgp( q-i, x11(i,i+1), x11(i,i+2), ldx11,tauq1(i) ) end if x11(i,i+1) = one end if if ( q+i-1 < m ) then if ( m-q == i ) then call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if end if x12(i,i) = one if( i < q ) then call stdlib${ii}$_dlarf( 'R', p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x11(i+1,i+1), & ldx11, work ) call stdlib${ii}$_dlarf( 'R', m-p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x21(i+1,i+1), & ldx21, work ) end if if ( p > i ) then call stdlib${ii}$_dlarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if ( m-p > i ) then call stdlib${ii}$_dlarf( 'R', m-p-i, m-q-i+1, x12(i,i), ldx12,tauq2(i), x22(i+1,i), & ldx22, work ) end if end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_dscal( m-q-i+1, -z1*z4, x12(i,i), ldx12 ) if ( i >= m-q ) then call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if x12(i,i) = one if ( p > i ) then call stdlib${ii}$_dlarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_dlarf( 'R', m-p-q, m-q-i+1, x12(i,i), ldx12,tauq2(i),& x22(q+1,i), ldx22, work ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_dscal( m-p-q-i+1, z2*z4, x22(q+i,p+i), ldx22 ) if ( i == m-p-q ) then call stdlib${ii}$_dlarfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i),ldx22, tauq2(p+i) ) else call stdlib${ii}$_dlarfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i+1),ldx22, tauq2(p+i)& ) end if x22(q+i,p+i) = one if ( i < m-p-q ) then call stdlib${ii}$_dlarf( 'R', m-p-q-i, m-p-q-i+1, x22(q+i,p+i), ldx22,tauq2(p+i), & x22(q+i+1,p+i), ldx22, work ) end if end do else ! reduce columns 1, ..., q of x11, x12, x21, x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_dscal( p-i+1, z1, x11(i,i), ldx11 ) else call stdlib${ii}$_dscal( p-i+1, z1*cos(phi(i-1)), x11(i,i), ldx11 ) call stdlib${ii}$_daxpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i-1,i),ldx12, x11(i,i),& ldx11 ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_dscal( m-p-i+1, z2, x21(i,i), ldx21 ) else call stdlib${ii}$_dscal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), ldx21 ) call stdlib${ii}$_daxpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i-1,i),ldx22, x21(i,& i), ldx21 ) end if theta(i) = atan2( stdlib${ii}$_dnrm2( m-p-i+1, x21(i,i), ldx21 ),stdlib${ii}$_dnrm2( p-i+1, & x11(i,i), ldx11 ) ) call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i,i+1), ldx11, taup1(i) ) x11(i,i) = one if ( i == m-p ) then call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i,i), ldx21,taup2(i) ) else call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i,i+1), ldx21,taup2(i) ) end if x21(i,i) = one if ( q > i ) then call stdlib${ii}$_dlarf( 'R', q-i, p-i+1, x11(i,i), ldx11, taup1(i),x11(i+1,i), & ldx11, work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_dlarf( 'R', m-q-i+1, p-i+1, x11(i,i), ldx11,taup1(i), x12(i,i), & ldx12, work ) end if if ( q > i ) then call stdlib${ii}$_dlarf( 'R', q-i, m-p-i+1, x21(i,i), ldx21, taup2(i),x21(i+1,i), & ldx21, work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_dlarf( 'R', m-q-i+1, m-p-i+1, x21(i,i), ldx21,taup2(i), x22(i,i), & ldx22, work ) end if if( i < q ) then call stdlib${ii}$_dscal( q-i, -z1*z3*sin(theta(i)), x11(i+1,i), 1_${ik}$ ) call stdlib${ii}$_daxpy( q-i, z2*z3*cos(theta(i)), x21(i+1,i), 1_${ik}$,x11(i+1,i), 1_${ik}$ ) end if call stdlib${ii}$_dscal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), 1_${ik}$ ) call stdlib${ii}$_daxpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), 1_${ik}$,x12(i,i), 1_${ik}$ ) if( i < q )phi(i) = atan2( stdlib${ii}$_dnrm2( q-i, x11(i+1,i), 1_${ik}$ ),stdlib${ii}$_dnrm2( m-q-& i+1, x12(i,i), 1_${ik}$ ) ) if( i < q ) then if ( q-i == 1_${ik}$) then call stdlib${ii}$_dlarfgp( q-i, x11(i+1,i), x11(i+1,i), 1_${ik}$,tauq1(i) ) else call stdlib${ii}$_dlarfgp( q-i, x11(i+1,i), x11(i+2,i), 1_${ik}$,tauq1(i) ) end if x11(i+1,i) = one end if if ( m-q > i ) then call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$,tauq2(i) ) else call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i,i), 1_${ik}$,tauq2(i) ) end if x12(i,i) = one if( i < q ) then call stdlib${ii}$_dlarf( 'L', q-i, p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x11(i+1,i+1), ldx11,& work ) call stdlib${ii}$_dlarf( 'L', q-i, m-p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x21(i+1,i+1), & ldx21, work ) end if call stdlib${ii}$_dlarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12, & work ) if ( m-p-i > 0_${ik}$ ) then call stdlib${ii}$_dlarf( 'L', m-q-i+1, m-p-i, x12(i,i), 1_${ik}$, tauq2(i),x22(i,i+1), & ldx22, work ) end if end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_dscal( m-q-i+1, -z1*z4, x12(i,i), 1_${ik}$ ) call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) ) x12(i,i) = one if ( p > i ) then call stdlib${ii}$_dlarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12,& work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_dlarf( 'L', m-q-i+1, m-p-q, x12(i,i), 1_${ik}$, tauq2(i),& x22(i,q+1), ldx22, work ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_dscal( m-p-q-i+1, z2*z4, x22(p+i,q+i), 1_${ik}$ ) if ( m-p-q == i ) then call stdlib${ii}$_dlarfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i,q+i), 1_${ik}$,tauq2(p+i) ) else call stdlib${ii}$_dlarfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i+1,q+i), 1_${ik}$,tauq2(p+i) ) call stdlib${ii}$_dlarf( 'L', m-p-q-i+1, m-p-q-i, x22(p+i,q+i), 1_${ik}$,tauq2(p+i), x22(p+& i,q+i+1), ldx22, work ) end if x22(p+i,q+i) = one end do end if return end subroutine stdlib${ii}$_dorbdb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$orbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & !! DORBDB: simultaneously bidiagonalizes the blocks of an M-by-M !! partitioned orthogonal matrix X: !! [ B11 | B12 0 0 ] !! [ X11 | X12 ] [ P1 | ] [ 0 | 0 -I 0 ] [ Q1 | ]**T !! X = [-----------] = [---------] [----------------] [---------] . !! [ X21 | X22 ] [ | P2 ] [ B21 | B22 0 0 ] [ | Q2 ] !! [ 0 | 0 0 I ] !! X11 is P-by-Q. Q must be no larger than P, M-P, or M-Q. (If this is !! not the case, then X must be transposed and/or permuted. This can be !! done in constant time using the TRANS and SIGNS options. See DORCSD !! for details.) !! The orthogonal matrices P1, P2, Q1, and Q2 are P-by-P, (M-P)-by- !! (M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. They are !! represented implicitly by Householder vectors. !! B11, B12, B21, and B22 are Q-by-Q bidiagonal matrices represented !! implicitly by angles THETA, PHI. ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldx11, ldx12, ldx21, ldx22, lwork, m, p, q ! Array Arguments real(${rk}$), intent(out) :: phi(*), theta(*) real(${rk}$), intent(out) :: taup1(*), taup2(*), tauq1(*), tauq2(*), work(*) real(${rk}$), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! ==================================================================== ! Parameters ! Local Scalars logical(lk) :: colmajor, lquery integer(${ik}$) :: i, lworkmin, lworkopt real(${rk}$) :: z1, z2, z3, z4 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ colmajor = .not. stdlib_lsame( trans, 'T' ) if( .not. stdlib_lsame( signs, 'O' ) ) then z1 = one z2 = one z3 = one z4 = one else z1 = one z2 = -one z3 = one z4 = -one end if lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -3_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -4_${ik}$ else if( q < 0_${ik}$ .or. q > p .or. q > m-p .or.q > m-q ) then info = -5_${ik}$ else if( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -7_${ik}$ else if( .not.colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -7_${ik}$ else if( colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -9_${ik}$ else if( .not.colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -9_${ik}$ else if( colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -11_${ik}$ else if( .not.colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if( colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -13_${ik}$ else if( .not.colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then lworkopt = m - q lworkmin = m - q work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not. lquery ) then info = -21_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'XORBDB', -info ) return else if( lquery ) then return end if ! handle column-major and row-major separately if( colmajor ) then ! reduce columns 1, ..., q of x11, x12, x21, and x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( p-i+1, z1, x11(i,i), 1_${ik}$ ) else call stdlib${ii}$_${ri}$scal( p-i+1, z1*cos(phi(i-1)), x11(i,i), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i,i-1),1_${ik}$, x11(i,i), 1_${ik}$ ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( m-p-i+1, z2, x21(i,i), 1_${ik}$ ) else call stdlib${ii}$_${ri}$scal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i,i-1),1_${ik}$, x21(i,i), & 1_${ik}$ ) end if theta(i) = atan2( stdlib${ii}$_${ri}$nrm2( m-p-i+1, x21(i,i), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( p-i+1, x11(& i,i), 1_${ik}$ ) ) if( p > i ) then call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) else if( p == i ) then call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i,i), 1_${ik}$, taup1(i) ) end if x11(i,i) = one if ( m-p > i ) then call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$,taup2(i) ) else if ( m-p == i ) then call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i,i), 1_${ik}$, taup2(i) ) end if x21(i,i) = one if ( q > i ) then call stdlib${ii}$_${ri}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i),x11(i,i+1), ldx11, & work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_${ri}$larf( 'L', p-i+1, m-q-i+1, x11(i,i), 1_${ik}$, taup1(i),x12(i,i), ldx12,& work ) end if if ( q > i ) then call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21,& work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, m-q-i+1, x21(i,i), 1_${ik}$, taup2(i),x22(i,i), & ldx22, work ) end if if( i < q ) then call stdlib${ii}$_${ri}$scal( q-i, -z1*z3*sin(theta(i)), x11(i,i+1),ldx11 ) call stdlib${ii}$_${ri}$axpy( q-i, z2*z3*cos(theta(i)), x21(i,i+1), ldx21,x11(i,i+1), & ldx11 ) end if call stdlib${ii}$_${ri}$scal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), ldx12 ) call stdlib${ii}$_${ri}$axpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), ldx22,x12(i,i), ldx12 & ) if( i < q )phi(i) = atan2( stdlib${ii}$_${ri}$nrm2( q-i, x11(i,i+1), ldx11 ),stdlib${ii}$_${ri}$nrm2( & m-q-i+1, x12(i,i), ldx12 ) ) if( i < q ) then if ( q-i == 1_${ik}$ ) then call stdlib${ii}$_${ri}$larfgp( q-i, x11(i,i+1), x11(i,i+1), ldx11,tauq1(i) ) else call stdlib${ii}$_${ri}$larfgp( q-i, x11(i,i+1), x11(i,i+2), ldx11,tauq1(i) ) end if x11(i,i+1) = one end if if ( q+i-1 < m ) then if ( m-q == i ) then call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if end if x12(i,i) = one if( i < q ) then call stdlib${ii}$_${ri}$larf( 'R', p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x11(i+1,i+1), & ldx11, work ) call stdlib${ii}$_${ri}$larf( 'R', m-p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x21(i+1,i+1), & ldx21, work ) end if if ( p > i ) then call stdlib${ii}$_${ri}$larf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if ( m-p > i ) then call stdlib${ii}$_${ri}$larf( 'R', m-p-i, m-q-i+1, x12(i,i), ldx12,tauq2(i), x22(i+1,i), & ldx22, work ) end if end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_${ri}$scal( m-q-i+1, -z1*z4, x12(i,i), ldx12 ) if ( i >= m-q ) then call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if x12(i,i) = one if ( p > i ) then call stdlib${ii}$_${ri}$larf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_${ri}$larf( 'R', m-p-q, m-q-i+1, x12(i,i), ldx12,tauq2(i),& x22(q+1,i), ldx22, work ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_${ri}$scal( m-p-q-i+1, z2*z4, x22(q+i,p+i), ldx22 ) if ( i == m-p-q ) then call stdlib${ii}$_${ri}$larfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i),ldx22, tauq2(p+i) ) else call stdlib${ii}$_${ri}$larfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i+1),ldx22, tauq2(p+i)& ) end if x22(q+i,p+i) = one if ( i < m-p-q ) then call stdlib${ii}$_${ri}$larf( 'R', m-p-q-i, m-p-q-i+1, x22(q+i,p+i), ldx22,tauq2(p+i), & x22(q+i+1,p+i), ldx22, work ) end if end do else ! reduce columns 1, ..., q of x11, x12, x21, x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( p-i+1, z1, x11(i,i), ldx11 ) else call stdlib${ii}$_${ri}$scal( p-i+1, z1*cos(phi(i-1)), x11(i,i), ldx11 ) call stdlib${ii}$_${ri}$axpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i-1,i),ldx12, x11(i,i),& ldx11 ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( m-p-i+1, z2, x21(i,i), ldx21 ) else call stdlib${ii}$_${ri}$scal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), ldx21 ) call stdlib${ii}$_${ri}$axpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i-1,i),ldx22, x21(i,& i), ldx21 ) end if theta(i) = atan2( stdlib${ii}$_${ri}$nrm2( m-p-i+1, x21(i,i), ldx21 ),stdlib${ii}$_${ri}$nrm2( p-i+1, & x11(i,i), ldx11 ) ) call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i,i+1), ldx11, taup1(i) ) x11(i,i) = one if ( i == m-p ) then call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i,i), ldx21,taup2(i) ) else call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i,i+1), ldx21,taup2(i) ) end if x21(i,i) = one if ( q > i ) then call stdlib${ii}$_${ri}$larf( 'R', q-i, p-i+1, x11(i,i), ldx11, taup1(i),x11(i+1,i), & ldx11, work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_${ri}$larf( 'R', m-q-i+1, p-i+1, x11(i,i), ldx11,taup1(i), x12(i,i), & ldx12, work ) end if if ( q > i ) then call stdlib${ii}$_${ri}$larf( 'R', q-i, m-p-i+1, x21(i,i), ldx21, taup2(i),x21(i+1,i), & ldx21, work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_${ri}$larf( 'R', m-q-i+1, m-p-i+1, x21(i,i), ldx21,taup2(i), x22(i,i), & ldx22, work ) end if if( i < q ) then call stdlib${ii}$_${ri}$scal( q-i, -z1*z3*sin(theta(i)), x11(i+1,i), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( q-i, z2*z3*cos(theta(i)), x21(i+1,i), 1_${ik}$,x11(i+1,i), 1_${ik}$ ) end if call stdlib${ii}$_${ri}$scal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), 1_${ik}$,x12(i,i), 1_${ik}$ ) if( i < q )phi(i) = atan2( stdlib${ii}$_${ri}$nrm2( q-i, x11(i+1,i), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( m-q-& i+1, x12(i,i), 1_${ik}$ ) ) if( i < q ) then if ( q-i == 1_${ik}$) then call stdlib${ii}$_${ri}$larfgp( q-i, x11(i+1,i), x11(i+1,i), 1_${ik}$,tauq1(i) ) else call stdlib${ii}$_${ri}$larfgp( q-i, x11(i+1,i), x11(i+2,i), 1_${ik}$,tauq1(i) ) end if x11(i+1,i) = one end if if ( m-q > i ) then call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$,tauq2(i) ) else call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i,i), 1_${ik}$,tauq2(i) ) end if x12(i,i) = one if( i < q ) then call stdlib${ii}$_${ri}$larf( 'L', q-i, p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x11(i+1,i+1), ldx11,& work ) call stdlib${ii}$_${ri}$larf( 'L', q-i, m-p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x21(i+1,i+1), & ldx21, work ) end if call stdlib${ii}$_${ri}$larf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12, & work ) if ( m-p-i > 0_${ik}$ ) then call stdlib${ii}$_${ri}$larf( 'L', m-q-i+1, m-p-i, x12(i,i), 1_${ik}$, tauq2(i),x22(i,i+1), & ldx22, work ) end if end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_${ri}$scal( m-q-i+1, -z1*z4, x12(i,i), 1_${ik}$ ) call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) ) x12(i,i) = one if ( p > i ) then call stdlib${ii}$_${ri}$larf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12,& work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_${ri}$larf( 'L', m-q-i+1, m-p-q, x12(i,i), 1_${ik}$, tauq2(i),& x22(i,q+1), ldx22, work ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_${ri}$scal( m-p-q-i+1, z2*z4, x22(p+i,q+i), 1_${ik}$ ) if ( m-p-q == i ) then call stdlib${ii}$_${ri}$larfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i,q+i), 1_${ik}$,tauq2(p+i) ) else call stdlib${ii}$_${ri}$larfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i+1,q+i), 1_${ik}$,tauq2(p+i) ) call stdlib${ii}$_${ri}$larf( 'L', m-p-q-i+1, m-p-q-i, x22(p+i,q+i), 1_${ik}$,tauq2(p+i), x22(p+& i,q+i+1), ldx22, work ) end if x22(p+i,q+i) = one end do end if return end subroutine stdlib${ii}$_${ri}$orbdb #:endif #:endfor module subroutine stdlib${ii}$_sorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! SORBDB1 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. Q must be no larger than P, !! M-P, or M-Q. Routines SORBDB2, SORBDB3, and SORBDB4 handle cases in !! which Q is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are Q-by-Q bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(sp), intent(out) :: phi(*), theta(*) real(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) real(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(sp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < q .or. m-p < q ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. m-q < q ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-2 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SORBDB1', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., q of x11 and x21 do i = 1, q call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) theta(i) = atan2( x21(i,i), x11(i,i) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i) = one x21(i,i) = one call stdlib${ii}$_slarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(& ilarf) ) call stdlib${ii}$_slarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(& ilarf) ) if( i < q ) then call stdlib${ii}$_srot( q-i, x11(i,i+1), ldx11, x21(i,i+1), ldx21, c, s ) call stdlib${ii}$_slarfgp( q-i, x21(i,i+1), x21(i,i+2), ldx21, tauq1(i) ) s = x21(i,i+1) x21(i,i+1) = one call stdlib${ii}$_slarf( 'R', p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x11(i+1,i+1), & ldx11, work(ilarf) ) call stdlib${ii}$_slarf( 'R', m-p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x21(i+1,i+1), & ldx21, work(ilarf) ) c = sqrt( stdlib${ii}$_snrm2( p-i, x11(i+1,i+1), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_snrm2( m-p-i, x21(i+1,& i+1), 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) call stdlib${ii}$_sorbdb5( p-i, m-p-i, q-i-1, x11(i+1,i+1), 1_${ik}$,x21(i+1,i+1), 1_${ik}$, x11(i+1,& i+2), ldx11,x21(i+1,i+2), ldx21, work(iorbdb5), lorbdb5,childinfo ) end if end do return end subroutine stdlib${ii}$_sorbdb1 module subroutine stdlib${ii}$_dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! DORBDB1 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. Q must be no larger than P, !! M-P, or M-Q. Routines DORBDB2, DORBDB3, and DORBDB4 handle cases in !! which Q is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are Q-by-Q bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(dp), intent(out) :: phi(*), theta(*) real(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) real(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(dp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < q .or. m-p < q ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. m-q < q ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-2 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB1', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., q of x11 and x21 do i = 1, q call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) theta(i) = atan2( x21(i,i), x11(i,i) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i) = one x21(i,i) = one call stdlib${ii}$_dlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(& ilarf) ) call stdlib${ii}$_dlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(& ilarf) ) if( i < q ) then call stdlib${ii}$_drot( q-i, x11(i,i+1), ldx11, x21(i,i+1), ldx21, c, s ) call stdlib${ii}$_dlarfgp( q-i, x21(i,i+1), x21(i,i+2), ldx21, tauq1(i) ) s = x21(i,i+1) x21(i,i+1) = one call stdlib${ii}$_dlarf( 'R', p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x11(i+1,i+1), & ldx11, work(ilarf) ) call stdlib${ii}$_dlarf( 'R', m-p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x21(i+1,i+1), & ldx21, work(ilarf) ) c = sqrt( stdlib${ii}$_dnrm2( p-i, x11(i+1,i+1), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dnrm2( m-p-i, x21(i+1,& i+1), 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) call stdlib${ii}$_dorbdb5( p-i, m-p-i, q-i-1, x11(i+1,i+1), 1_${ik}$,x21(i+1,i+1), 1_${ik}$, x11(i+1,& i+2), ldx11,x21(i+1,i+2), ldx21, work(iorbdb5), lorbdb5,childinfo ) end if end do return end subroutine stdlib${ii}$_dorbdb1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$orbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! DORBDB1: simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. Q must be no larger than P, !! M-P, or M-Q. Routines DORBDB2, DORBDB3, and DORBDB4 handle cases in !! which Q is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are Q-by-Q bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(${rk}$), intent(out) :: phi(*), theta(*) real(${rk}$), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) real(${rk}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(${rk}$) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < q .or. m-p < q ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. m-q < q ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-2 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB1', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., q of x11 and x21 do i = 1, q call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) theta(i) = atan2( x21(i,i), x11(i,i) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i) = one x21(i,i) = one call stdlib${ii}$_${ri}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(& ilarf) ) call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(& ilarf) ) if( i < q ) then call stdlib${ii}$_${ri}$rot( q-i, x11(i,i+1), ldx11, x21(i,i+1), ldx21, c, s ) call stdlib${ii}$_${ri}$larfgp( q-i, x21(i,i+1), x21(i,i+2), ldx21, tauq1(i) ) s = x21(i,i+1) x21(i,i+1) = one call stdlib${ii}$_${ri}$larf( 'R', p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x11(i+1,i+1), & ldx11, work(ilarf) ) call stdlib${ii}$_${ri}$larf( 'R', m-p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x21(i+1,i+1), & ldx21, work(ilarf) ) c = sqrt( stdlib${ii}$_${ri}$nrm2( p-i, x11(i+1,i+1), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${ri}$nrm2( m-p-i, x21(i+1,& i+1), 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) call stdlib${ii}$_${ri}$orbdb5( p-i, m-p-i, q-i-1, x11(i+1,i+1), 1_${ik}$,x21(i+1,i+1), 1_${ik}$, x11(i+1,& i+2), ldx11,x21(i+1,i+2), ldx21, work(iorbdb5), lorbdb5,childinfo ) end if end do return end subroutine stdlib${ii}$_${ri}$orbdb1 #:endif #:endfor module subroutine stdlib${ii}$_sorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! SORBDB2 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. P must be no larger than M-P, !! Q, or M-Q. Routines SORBDB1, SORBDB3, and SORBDB4 handle cases in !! which P is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are P-by-P bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(sp), intent(out) :: phi(*), theta(*) real(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) real(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(sp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < 0_${ik}$ .or. p > m-p ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. q < p .or. m-q < p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SORBDB2', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., p of x11 and x21 do i = 1, p if( i > 1_${ik}$ ) then call stdlib${ii}$_srot( q-i+1, x11(i,i), ldx11, x21(i-1,i), ldx21, c, s ) end if call stdlib${ii}$_slarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) c = x11(i,i) x11(i,i) = one call stdlib${ii}$_slarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_slarf( 'R', m-p-i+1, q-i+1, x11(i,i), ldx11, tauq1(i),x21(i,i), ldx21, & work(ilarf) ) s = sqrt( stdlib${ii}$_snrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_snrm2( m-p-i+1, x21(i,i), 1_${ik}$ & )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_sorbdb5( p-i, m-p-i+1, q-i, x11(i+1,i), 1_${ik}$, x21(i,i), 1_${ik}$,x11(i+1,i+1), & ldx11, x21(i,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_sscal( p-i, negone, x11(i+1,i), 1_${ik}$ ) call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) if( i < p ) then call stdlib${ii}$_slarfgp( p-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, taup1(i) ) phi(i) = atan2( x11(i+1,i), x21(i,i) ) c = cos( phi(i) ) s = sin( phi(i) ) x11(i+1,i) = one call stdlib${ii}$_slarf( 'L', p-i, q-i, x11(i+1,i), 1_${ik}$, taup1(i),x11(i+1,i+1), ldx11, & work(ilarf) ) end if x21(i,i) = one call stdlib${ii}$_slarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(& ilarf) ) end do ! reduce the bottom-right portion of x21 to the identity matrix do i = p + 1, q call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) x21(i,i) = one call stdlib${ii}$_slarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(& ilarf) ) end do return end subroutine stdlib${ii}$_sorbdb2 module subroutine stdlib${ii}$_dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! DORBDB2 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. P must be no larger than M-P, !! Q, or M-Q. Routines DORBDB1, DORBDB3, and DORBDB4 handle cases in !! which P is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are P-by-P bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(dp), intent(out) :: phi(*), theta(*) real(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) real(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(dp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < 0_${ik}$ .or. p > m-p ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. q < p .or. m-q < p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB2', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., p of x11 and x21 do i = 1, p if( i > 1_${ik}$ ) then call stdlib${ii}$_drot( q-i+1, x11(i,i), ldx11, x21(i-1,i), ldx21, c, s ) end if call stdlib${ii}$_dlarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) c = x11(i,i) x11(i,i) = one call stdlib${ii}$_dlarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_dlarf( 'R', m-p-i+1, q-i+1, x11(i,i), ldx11, tauq1(i),x21(i,i), ldx21, & work(ilarf) ) s = sqrt( stdlib${ii}$_dnrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dnrm2( m-p-i+1, x21(i,i), 1_${ik}$ & )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_dorbdb5( p-i, m-p-i+1, q-i, x11(i+1,i), 1_${ik}$, x21(i,i), 1_${ik}$,x11(i+1,i+1), & ldx11, x21(i,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_dscal( p-i, negone, x11(i+1,i), 1_${ik}$ ) call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) if( i < p ) then call stdlib${ii}$_dlarfgp( p-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, taup1(i) ) phi(i) = atan2( x11(i+1,i), x21(i,i) ) c = cos( phi(i) ) s = sin( phi(i) ) x11(i+1,i) = one call stdlib${ii}$_dlarf( 'L', p-i, q-i, x11(i+1,i), 1_${ik}$, taup1(i),x11(i+1,i+1), ldx11, & work(ilarf) ) end if x21(i,i) = one call stdlib${ii}$_dlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(& ilarf) ) end do ! reduce the bottom-right portion of x21 to the identity matrix do i = p + 1, q call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) x21(i,i) = one call stdlib${ii}$_dlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(& ilarf) ) end do return end subroutine stdlib${ii}$_dorbdb2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$orbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! DORBDB2: simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. P must be no larger than M-P, !! Q, or M-Q. Routines DORBDB1, DORBDB3, and DORBDB4 handle cases in !! which P is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are P-by-P bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(${rk}$), intent(out) :: phi(*), theta(*) real(${rk}$), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) real(${rk}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(${rk}$) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < 0_${ik}$ .or. p > m-p ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. q < p .or. m-q < p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB2', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., p of x11 and x21 do i = 1, p if( i > 1_${ik}$ ) then call stdlib${ii}$_${ri}$rot( q-i+1, x11(i,i), ldx11, x21(i-1,i), ldx21, c, s ) end if call stdlib${ii}$_${ri}$larfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) c = x11(i,i) x11(i,i) = one call stdlib${ii}$_${ri}$larf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_${ri}$larf( 'R', m-p-i+1, q-i+1, x11(i,i), ldx11, tauq1(i),x21(i,i), ldx21, & work(ilarf) ) s = sqrt( stdlib${ii}$_${ri}$nrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${ri}$nrm2( m-p-i+1, x21(i,i), 1_${ik}$ & )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_${ri}$orbdb5( p-i, m-p-i+1, q-i, x11(i+1,i), 1_${ik}$, x21(i,i), 1_${ik}$,x11(i+1,i+1), & ldx11, x21(i,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_${ri}$scal( p-i, negone, x11(i+1,i), 1_${ik}$ ) call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) if( i < p ) then call stdlib${ii}$_${ri}$larfgp( p-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, taup1(i) ) phi(i) = atan2( x11(i+1,i), x21(i,i) ) c = cos( phi(i) ) s = sin( phi(i) ) x11(i+1,i) = one call stdlib${ii}$_${ri}$larf( 'L', p-i, q-i, x11(i+1,i), 1_${ik}$, taup1(i),x11(i+1,i+1), ldx11, & work(ilarf) ) end if x21(i,i) = one call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(& ilarf) ) end do ! reduce the bottom-right portion of x21 to the identity matrix do i = p + 1, q call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) x21(i,i) = one call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(& ilarf) ) end do return end subroutine stdlib${ii}$_${ri}$orbdb2 #:endif #:endfor module subroutine stdlib${ii}$_sorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! SORBDB3 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-P must be no larger than P, !! Q, or M-Q. Routines SORBDB1, SORBDB2, and SORBDB4 handle cases in !! which M-P is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-P)-by-(M-P) bidiagonal matrices represented !! implicitly by angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(sp), intent(out) :: phi(*), theta(*) real(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) real(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(sp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( 2_${ik}$*p < m .or. p > m ) then info = -2_${ik}$ else if( q < m-p .or. m-q < m-p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SORBDB3', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., m-p of x11 and x21 do i = 1, m-p if( i > 1_${ik}$ ) then call stdlib${ii}$_srot( q-i+1, x11(i-1,i), ldx11, x21(i,i), ldx11, c, s ) end if call stdlib${ii}$_slarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) s = x21(i,i) x21(i,i) = one call stdlib${ii}$_slarf( 'R', p-i+1, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i,i), ldx11, & work(ilarf) ) call stdlib${ii}$_slarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) c = sqrt( stdlib${ii}$_snrm2( p-i+1, x11(i,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_snrm2( m-p-i, x21(i+1,i), 1_${ik}$ & )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_sorbdb5( p-i+1, m-p-i, q-i, x11(i,i), 1_${ik}$, x21(i+1,i), 1_${ik}$,x11(i,i+1), & ldx11, x21(i+1,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) if( i < m-p ) then call stdlib${ii}$_slarfgp( m-p-i, x21(i+1,i), x21(i+2,i), 1_${ik}$, taup2(i) ) phi(i) = atan2( x21(i+1,i), x11(i,i) ) c = cos( phi(i) ) s = sin( phi(i) ) x21(i+1,i) = one call stdlib${ii}$_slarf( 'L', m-p-i, q-i, x21(i+1,i), 1_${ik}$, taup2(i),x21(i+1,i+1), ldx21, & work(ilarf) ) end if x11(i,i) = one call stdlib${ii}$_slarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(& ilarf) ) end do ! reduce the bottom-right portion of x11 to the identity matrix do i = m-p + 1, q call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) x11(i,i) = one call stdlib${ii}$_slarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(& ilarf) ) end do return end subroutine stdlib${ii}$_sorbdb3 module subroutine stdlib${ii}$_dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! DORBDB3 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-P must be no larger than P, !! Q, or M-Q. Routines DORBDB1, DORBDB2, and DORBDB4 handle cases in !! which M-P is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-P)-by-(M-P) bidiagonal matrices represented !! implicitly by angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(dp), intent(out) :: phi(*), theta(*) real(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) real(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(dp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( 2_${ik}$*p < m .or. p > m ) then info = -2_${ik}$ else if( q < m-p .or. m-q < m-p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB3', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., m-p of x11 and x21 do i = 1, m-p if( i > 1_${ik}$ ) then call stdlib${ii}$_drot( q-i+1, x11(i-1,i), ldx11, x21(i,i), ldx11, c, s ) end if call stdlib${ii}$_dlarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) s = x21(i,i) x21(i,i) = one call stdlib${ii}$_dlarf( 'R', p-i+1, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i,i), ldx11, & work(ilarf) ) call stdlib${ii}$_dlarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) c = sqrt( stdlib${ii}$_dnrm2( p-i+1, x11(i,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dnrm2( m-p-i, x21(i+1,i), 1_${ik}$ & )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_dorbdb5( p-i+1, m-p-i, q-i, x11(i,i), 1_${ik}$, x21(i+1,i), 1_${ik}$,x11(i,i+1), & ldx11, x21(i+1,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) if( i < m-p ) then call stdlib${ii}$_dlarfgp( m-p-i, x21(i+1,i), x21(i+2,i), 1_${ik}$, taup2(i) ) phi(i) = atan2( x21(i+1,i), x11(i,i) ) c = cos( phi(i) ) s = sin( phi(i) ) x21(i+1,i) = one call stdlib${ii}$_dlarf( 'L', m-p-i, q-i, x21(i+1,i), 1_${ik}$, taup2(i),x21(i+1,i+1), ldx21, & work(ilarf) ) end if x11(i,i) = one call stdlib${ii}$_dlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(& ilarf) ) end do ! reduce the bottom-right portion of x11 to the identity matrix do i = m-p + 1, q call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) x11(i,i) = one call stdlib${ii}$_dlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(& ilarf) ) end do return end subroutine stdlib${ii}$_dorbdb3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$orbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! DORBDB3: simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-P must be no larger than P, !! Q, or M-Q. Routines DORBDB1, DORBDB2, and DORBDB4 handle cases in !! which M-P is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-P)-by-(M-P) bidiagonal matrices represented !! implicitly by angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(${rk}$), intent(out) :: phi(*), theta(*) real(${rk}$), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) real(${rk}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(${rk}$) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( 2_${ik}$*p < m .or. p > m ) then info = -2_${ik}$ else if( q < m-p .or. m-q < m-p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB3', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., m-p of x11 and x21 do i = 1, m-p if( i > 1_${ik}$ ) then call stdlib${ii}$_${ri}$rot( q-i+1, x11(i-1,i), ldx11, x21(i,i), ldx11, c, s ) end if call stdlib${ii}$_${ri}$larfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) s = x21(i,i) x21(i,i) = one call stdlib${ii}$_${ri}$larf( 'R', p-i+1, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i,i), ldx11, & work(ilarf) ) call stdlib${ii}$_${ri}$larf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) c = sqrt( stdlib${ii}$_${ri}$nrm2( p-i+1, x11(i,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${ri}$nrm2( m-p-i, x21(i+1,i), 1_${ik}$ & )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_${ri}$orbdb5( p-i+1, m-p-i, q-i, x11(i,i), 1_${ik}$, x21(i+1,i), 1_${ik}$,x11(i,i+1), & ldx11, x21(i+1,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) if( i < m-p ) then call stdlib${ii}$_${ri}$larfgp( m-p-i, x21(i+1,i), x21(i+2,i), 1_${ik}$, taup2(i) ) phi(i) = atan2( x21(i+1,i), x11(i,i) ) c = cos( phi(i) ) s = sin( phi(i) ) x21(i+1,i) = one call stdlib${ii}$_${ri}$larf( 'L', m-p-i, q-i, x21(i+1,i), 1_${ik}$, taup2(i),x21(i+1,i+1), ldx21, & work(ilarf) ) end if x11(i,i) = one call stdlib${ii}$_${ri}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(& ilarf) ) end do ! reduce the bottom-right portion of x11 to the identity matrix do i = m-p + 1, q call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) x11(i,i) = one call stdlib${ii}$_${ri}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(& ilarf) ) end do return end subroutine stdlib${ii}$_${ri}$orbdb3 #:endif #:endfor module subroutine stdlib${ii}$_sorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! SORBDB4 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-Q must be no larger than P, !! M-P, or Q. Routines SORBDB1, SORBDB2, and SORBDB3 handle cases in !! which M-Q is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-Q)-by-(M-Q) bidiagonal matrices represented !! implicitly by angles THETA, PHI. phantom, work, lwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(sp), intent(out) :: phi(*), theta(*) real(sp), intent(out) :: phantom(*), taup1(*), taup2(*), tauq1(*), work(*) real(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(sp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, j, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < m-q .or. m-p < m-q ) then info = -2_${ik}$ else if( q < m-q .or. q > m ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( q-1, p-1, m-p-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q lworkopt = ilarf + llarf - 1_${ik}$ lworkopt = max( lworkopt, iorbdb5 + lorbdb5 - 1_${ik}$ ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SORBDB4', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., m-q of x11 and x21 do i = 1, m-q if( i == 1_${ik}$ ) then do j = 1, m phantom(j) = zero end do call stdlib${ii}$_sorbdb5( p, m-p, q, phantom(1_${ik}$), 1_${ik}$, phantom(p+1), 1_${ik}$,x11, ldx11, x21, & ldx21, work(iorbdb5),lorbdb5, childinfo ) call stdlib${ii}$_sscal( p, negone, phantom(1_${ik}$), 1_${ik}$ ) call stdlib${ii}$_slarfgp( p, phantom(1_${ik}$), phantom(2_${ik}$), 1_${ik}$, taup1(1_${ik}$) ) call stdlib${ii}$_slarfgp( m-p, phantom(p+1), phantom(p+2), 1_${ik}$, taup2(1_${ik}$) ) theta(i) = atan2( phantom(1_${ik}$), phantom(p+1) ) c = cos( theta(i) ) s = sin( theta(i) ) phantom(1_${ik}$) = one phantom(p+1) = one call stdlib${ii}$_slarf( 'L', p, q, phantom(1_${ik}$), 1_${ik}$, taup1(1_${ik}$), x11, ldx11,work(ilarf) ) call stdlib${ii}$_slarf( 'L', m-p, q, phantom(p+1), 1_${ik}$, taup2(1_${ik}$), x21,ldx21, work(ilarf)& ) else call stdlib${ii}$_sorbdb5( p-i+1, m-p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,x21(i,i-1), 1_${ik}$, x11(i,i)& , ldx11, x21(i,i),ldx21, work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_sscal( p-i+1, negone, x11(i,i-1), 1_${ik}$ ) call stdlib${ii}$_slarfgp( p-i+1, x11(i,i-1), x11(i+1,i-1), 1_${ik}$, taup1(i) ) call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i-1), x21(i+1,i-1), 1_${ik}$,taup2(i) ) theta(i) = atan2( x11(i,i-1), x21(i,i-1) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i-1) = one x21(i,i-1) = one call stdlib${ii}$_slarf( 'L', p-i+1, q-i+1, x11(i,i-1), 1_${ik}$, taup1(i),x11(i,i), ldx11, & work(ilarf) ) call stdlib${ii}$_slarf( 'L', m-p-i+1, q-i+1, x21(i,i-1), 1_${ik}$, taup2(i),x21(i,i), ldx21, & work(ilarf) ) end if call stdlib${ii}$_srot( q-i+1, x11(i,i), ldx11, x21(i,i), ldx21, s, -c ) call stdlib${ii}$_slarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) c = x21(i,i) x21(i,i) = one call stdlib${ii}$_slarf( 'R', p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_slarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) if( i < m-q ) then s = sqrt( stdlib${ii}$_snrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_snrm2( m-p-i, x21(i+1,i),& 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) end if end do ! reduce the bottom-right portion of x11 to [ i 0 ] do i = m - q + 1, p call stdlib${ii}$_slarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) x11(i,i) = one call stdlib${ii}$_slarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_slarf( 'R', q-p, q-i+1, x11(i,i), ldx11, tauq1(i),x21(m-q+1,i), ldx21, & work(ilarf) ) end do ! reduce the bottom-right portion of x21 to [ 0 i ] do i = p + 1, q call stdlib${ii}$_slarfgp( q-i+1, x21(m-q+i-p,i), x21(m-q+i-p,i+1), ldx21,tauq1(i) ) x21(m-q+i-p,i) = one call stdlib${ii}$_slarf( 'R', q-i, q-i+1, x21(m-q+i-p,i), ldx21, tauq1(i),x21(m-q+i-p+1,i)& , ldx21, work(ilarf) ) end do return end subroutine stdlib${ii}$_sorbdb4 module subroutine stdlib${ii}$_dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! DORBDB4 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-Q must be no larger than P, !! M-P, or Q. Routines DORBDB1, DORBDB2, and DORBDB3 handle cases in !! which M-Q is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-Q)-by-(M-Q) bidiagonal matrices represented !! implicitly by angles THETA, PHI. phantom, work, lwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(dp), intent(out) :: phi(*), theta(*) real(dp), intent(out) :: phantom(*), taup1(*), taup2(*), tauq1(*), work(*) real(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(dp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, j, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < m-q .or. m-p < m-q ) then info = -2_${ik}$ else if( q < m-q .or. q > m ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( q-1, p-1, m-p-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q lworkopt = ilarf + llarf - 1_${ik}$ lworkopt = max( lworkopt, iorbdb5 + lorbdb5 - 1_${ik}$ ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB4', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., m-q of x11 and x21 do i = 1, m-q if( i == 1_${ik}$ ) then do j = 1, m phantom(j) = zero end do call stdlib${ii}$_dorbdb5( p, m-p, q, phantom(1_${ik}$), 1_${ik}$, phantom(p+1), 1_${ik}$,x11, ldx11, x21, & ldx21, work(iorbdb5),lorbdb5, childinfo ) call stdlib${ii}$_dscal( p, negone, phantom(1_${ik}$), 1_${ik}$ ) call stdlib${ii}$_dlarfgp( p, phantom(1_${ik}$), phantom(2_${ik}$), 1_${ik}$, taup1(1_${ik}$) ) call stdlib${ii}$_dlarfgp( m-p, phantom(p+1), phantom(p+2), 1_${ik}$, taup2(1_${ik}$) ) theta(i) = atan2( phantom(1_${ik}$), phantom(p+1) ) c = cos( theta(i) ) s = sin( theta(i) ) phantom(1_${ik}$) = one phantom(p+1) = one call stdlib${ii}$_dlarf( 'L', p, q, phantom(1_${ik}$), 1_${ik}$, taup1(1_${ik}$), x11, ldx11,work(ilarf) ) call stdlib${ii}$_dlarf( 'L', m-p, q, phantom(p+1), 1_${ik}$, taup2(1_${ik}$), x21,ldx21, work(ilarf)& ) else call stdlib${ii}$_dorbdb5( p-i+1, m-p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,x21(i,i-1), 1_${ik}$, x11(i,i)& , ldx11, x21(i,i),ldx21, work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_dscal( p-i+1, negone, x11(i,i-1), 1_${ik}$ ) call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i-1), x11(i+1,i-1), 1_${ik}$, taup1(i) ) call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i-1), x21(i+1,i-1), 1_${ik}$,taup2(i) ) theta(i) = atan2( x11(i,i-1), x21(i,i-1) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i-1) = one x21(i,i-1) = one call stdlib${ii}$_dlarf( 'L', p-i+1, q-i+1, x11(i,i-1), 1_${ik}$, taup1(i),x11(i,i), ldx11, & work(ilarf) ) call stdlib${ii}$_dlarf( 'L', m-p-i+1, q-i+1, x21(i,i-1), 1_${ik}$, taup2(i),x21(i,i), ldx21, & work(ilarf) ) end if call stdlib${ii}$_drot( q-i+1, x11(i,i), ldx11, x21(i,i), ldx21, s, -c ) call stdlib${ii}$_dlarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) c = x21(i,i) x21(i,i) = one call stdlib${ii}$_dlarf( 'R', p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_dlarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) if( i < m-q ) then s = sqrt( stdlib${ii}$_dnrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dnrm2( m-p-i, x21(i+1,i),& 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) end if end do ! reduce the bottom-right portion of x11 to [ i 0 ] do i = m - q + 1, p call stdlib${ii}$_dlarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) x11(i,i) = one call stdlib${ii}$_dlarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_dlarf( 'R', q-p, q-i+1, x11(i,i), ldx11, tauq1(i),x21(m-q+1,i), ldx21, & work(ilarf) ) end do ! reduce the bottom-right portion of x21 to [ 0 i ] do i = p + 1, q call stdlib${ii}$_dlarfgp( q-i+1, x21(m-q+i-p,i), x21(m-q+i-p,i+1), ldx21,tauq1(i) ) x21(m-q+i-p,i) = one call stdlib${ii}$_dlarf( 'R', q-i, q-i+1, x21(m-q+i-p,i), ldx21, tauq1(i),x21(m-q+i-p+1,i)& , ldx21, work(ilarf) ) end do return end subroutine stdlib${ii}$_dorbdb4 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$orbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! DORBDB4: simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-Q must be no larger than P, !! M-P, or Q. Routines DORBDB1, DORBDB2, and DORBDB3 handle cases in !! which M-Q is not the minimum dimension. !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-Q)-by-(M-Q) bidiagonal matrices represented !! implicitly by angles THETA, PHI. phantom, work, lwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(${rk}$), intent(out) :: phi(*), theta(*) real(${rk}$), intent(out) :: phantom(*), taup1(*), taup2(*), tauq1(*), work(*) real(${rk}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(${rk}$) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, j, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < m-q .or. m-p < m-q ) then info = -2_${ik}$ else if( q < m-q .or. q > m ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( q-1, p-1, m-p-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q lworkopt = ilarf + llarf - 1_${ik}$ lworkopt = max( lworkopt, iorbdb5 + lorbdb5 - 1_${ik}$ ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB4', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., m-q of x11 and x21 do i = 1, m-q if( i == 1_${ik}$ ) then do j = 1, m phantom(j) = zero end do call stdlib${ii}$_${ri}$orbdb5( p, m-p, q, phantom(1_${ik}$), 1_${ik}$, phantom(p+1), 1_${ik}$,x11, ldx11, x21, & ldx21, work(iorbdb5),lorbdb5, childinfo ) call stdlib${ii}$_${ri}$scal( p, negone, phantom(1_${ik}$), 1_${ik}$ ) call stdlib${ii}$_${ri}$larfgp( p, phantom(1_${ik}$), phantom(2_${ik}$), 1_${ik}$, taup1(1_${ik}$) ) call stdlib${ii}$_${ri}$larfgp( m-p, phantom(p+1), phantom(p+2), 1_${ik}$, taup2(1_${ik}$) ) theta(i) = atan2( phantom(1_${ik}$), phantom(p+1) ) c = cos( theta(i) ) s = sin( theta(i) ) phantom(1_${ik}$) = one phantom(p+1) = one call stdlib${ii}$_${ri}$larf( 'L', p, q, phantom(1_${ik}$), 1_${ik}$, taup1(1_${ik}$), x11, ldx11,work(ilarf) ) call stdlib${ii}$_${ri}$larf( 'L', m-p, q, phantom(p+1), 1_${ik}$, taup2(1_${ik}$), x21,ldx21, work(ilarf)& ) else call stdlib${ii}$_${ri}$orbdb5( p-i+1, m-p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,x21(i,i-1), 1_${ik}$, x11(i,i)& , ldx11, x21(i,i),ldx21, work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_${ri}$scal( p-i+1, negone, x11(i,i-1), 1_${ik}$ ) call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i-1), x11(i+1,i-1), 1_${ik}$, taup1(i) ) call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i-1), x21(i+1,i-1), 1_${ik}$,taup2(i) ) theta(i) = atan2( x11(i,i-1), x21(i,i-1) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i-1) = one x21(i,i-1) = one call stdlib${ii}$_${ri}$larf( 'L', p-i+1, q-i+1, x11(i,i-1), 1_${ik}$, taup1(i),x11(i,i), ldx11, & work(ilarf) ) call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, q-i+1, x21(i,i-1), 1_${ik}$, taup2(i),x21(i,i), ldx21, & work(ilarf) ) end if call stdlib${ii}$_${ri}$rot( q-i+1, x11(i,i), ldx11, x21(i,i), ldx21, s, -c ) call stdlib${ii}$_${ri}$larfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) c = x21(i,i) x21(i,i) = one call stdlib${ii}$_${ri}$larf( 'R', p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_${ri}$larf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) if( i < m-q ) then s = sqrt( stdlib${ii}$_${ri}$nrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${ri}$nrm2( m-p-i, x21(i+1,i),& 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) end if end do ! reduce the bottom-right portion of x11 to [ i 0 ] do i = m - q + 1, p call stdlib${ii}$_${ri}$larfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) x11(i,i) = one call stdlib${ii}$_${ri}$larf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_${ri}$larf( 'R', q-p, q-i+1, x11(i,i), ldx11, tauq1(i),x21(m-q+1,i), ldx21, & work(ilarf) ) end do ! reduce the bottom-right portion of x21 to [ 0 i ] do i = p + 1, q call stdlib${ii}$_${ri}$larfgp( q-i+1, x21(m-q+i-p,i), x21(m-q+i-p,i+1), ldx21,tauq1(i) ) x21(m-q+i-p,i) = one call stdlib${ii}$_${ri}$larf( 'R', q-i, q-i+1, x21(m-q+i-p,i), ldx21, tauq1(i),x21(m-q+i-p+1,i)& , ldx21, work(ilarf) ) end do return end subroutine stdlib${ii}$_${ri}$orbdb4 #:endif #:endfor pure module subroutine stdlib${ii}$_sorbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & !! SORBDB5 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then some other vector from the orthogonal complement !! is returned. This vector is chosen in an arbitrary but deterministic !! way. lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments real(sp), intent(in) :: q1(ldq1,*), q2(ldq2,*) real(sp), intent(out) :: work(*) real(sp), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, j ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SORBDB5', -info ) return end if ! project x onto the orthogonal complement of q call stdlib${ii}$_sorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2, ldq2,work, lwork, & childinfo ) ! if the projection is nonzero, then return if( stdlib${ii}$_snrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_snrm2(m2,x2,incx2) /= zero ) & then return end if ! project each standard basis vector e_1,...,e_m1 in turn, stopping ! when a nonzero projection is found do i = 1, m1 do j = 1, m1 x1(j) = zero end do x1(i) = one do j = 1, m2 x2(j) = zero end do call stdlib${ii}$_sorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_snrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_snrm2(m2,x2,incx2) /= zero ) & then return end if end do ! project each standard basis vector e_(m1+1),...,e_(m1+m2) in turn, ! stopping when a nonzero projection is found do i = 1, m2 do j = 1, m1 x1(j) = zero end do do j = 1, m2 x2(j) = zero end do x2(i) = one call stdlib${ii}$_sorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_snrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_snrm2(m2,x2,incx2) /= zero ) & then return end if end do return end subroutine stdlib${ii}$_sorbdb5 pure module subroutine stdlib${ii}$_dorbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & !! DORBDB5 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then some other vector from the orthogonal complement !! is returned. This vector is chosen in an arbitrary but deterministic !! way. lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments real(dp), intent(in) :: q1(ldq1,*), q2(ldq2,*) real(dp), intent(out) :: work(*) real(dp), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, j ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB5', -info ) return end if ! project x onto the orthogonal complement of q call stdlib${ii}$_dorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2, ldq2,work, lwork, & childinfo ) ! if the projection is nonzero, then return if( stdlib${ii}$_dnrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_dnrm2(m2,x2,incx2) /= zero ) & then return end if ! project each standard basis vector e_1,...,e_m1 in turn, stopping ! when a nonzero projection is found do i = 1, m1 do j = 1, m1 x1(j) = zero end do x1(i) = one do j = 1, m2 x2(j) = zero end do call stdlib${ii}$_dorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_dnrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_dnrm2(m2,x2,incx2) /= zero ) & then return end if end do ! project each standard basis vector e_(m1+1),...,e_(m1+m2) in turn, ! stopping when a nonzero projection is found do i = 1, m2 do j = 1, m1 x1(j) = zero end do do j = 1, m2 x2(j) = zero end do x2(i) = one call stdlib${ii}$_dorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_dnrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_dnrm2(m2,x2,incx2) /= zero ) & then return end if end do return end subroutine stdlib${ii}$_dorbdb5 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & !! DORBDB5: orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then some other vector from the orthogonal complement !! is returned. This vector is chosen in an arbitrary but deterministic !! way. lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments real(${rk}$), intent(in) :: q1(ldq1,*), q2(ldq2,*) real(${rk}$), intent(out) :: work(*) real(${rk}$), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, j ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB5', -info ) return end if ! project x onto the orthogonal complement of q call stdlib${ii}$_${ri}$orbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2, ldq2,work, lwork, & childinfo ) ! if the projection is nonzero, then return if( stdlib${ii}$_${ri}$nrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_${ri}$nrm2(m2,x2,incx2) /= zero ) & then return end if ! project each standard basis vector e_1,...,e_m1 in turn, stopping ! when a nonzero projection is found do i = 1, m1 do j = 1, m1 x1(j) = zero end do x1(i) = one do j = 1, m2 x2(j) = zero end do call stdlib${ii}$_${ri}$orbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_${ri}$nrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_${ri}$nrm2(m2,x2,incx2) /= zero ) & then return end if end do ! project each standard basis vector e_(m1+1),...,e_(m1+m2) in turn, ! stopping when a nonzero projection is found do i = 1, m2 do j = 1, m1 x1(j) = zero end do do j = 1, m2 x2(j) = zero end do x2(i) = one call stdlib${ii}$_${ri}$orbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_${ri}$nrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_${ri}$nrm2(m2,x2,incx2) /= zero ) & then return end if end do return end subroutine stdlib${ii}$_${ri}$orbdb5 #:endif #:endfor pure module subroutine stdlib${ii}$_sorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & !! SORBDB6 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then the zero vector is returned. lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments real(sp), intent(in) :: q1(ldq1,*), q2(ldq2,*) real(sp), intent(out) :: work(*) real(sp), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Parameters real(sp), parameter :: alphasq = 0.01_sp ! Local Scalars integer(${ik}$) :: i real(sp) :: normsq1, normsq2, scl1, scl2, ssq1, ssq2 ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SORBDB6', -info ) return end if ! first, project x onto the orthogonal complement of q's column ! space scl1 = zero ssq1 = one call stdlib${ii}$_slassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_slassq( m2, x2, incx2, scl2, ssq2 ) normsq1 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = zero end do else call stdlib${ii}$_sgemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ ) end if call stdlib${ii}$_sgemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ ) call stdlib${ii}$_sgemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 ) call stdlib${ii}$_sgemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_slassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_slassq( m2, x2, incx2, scl2, ssq2 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if projection is sufficiently large in norm, then stop. ! if projection is zero, then stop. ! otherwise, project again. if( normsq2 >= alphasq*normsq1 ) then return end if if( normsq2 == zero ) then return end if normsq1 = normsq2 do i = 1, n work(i) = zero end do if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = zero end do else call stdlib${ii}$_sgemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ ) end if call stdlib${ii}$_sgemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ ) call stdlib${ii}$_sgemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 ) call stdlib${ii}$_sgemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_slassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_slassq( m1, x1, incx1, scl1, ssq1 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if second projection is sufficiently large in norm, then do ! nothing more. alternatively, if it shrunk significantly, then ! truncate it to zero. if( normsq2 < alphasq*normsq1 ) then do i = 1, m1 x1(i) = zero end do do i = 1, m2 x2(i) = zero end do end if return end subroutine stdlib${ii}$_sorbdb6 pure module subroutine stdlib${ii}$_dorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & !! DORBDB6 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then the zero vector is returned. lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments real(dp), intent(in) :: q1(ldq1,*), q2(ldq2,*) real(dp), intent(out) :: work(*) real(dp), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Parameters real(dp), parameter :: alphasq = 0.01_dp ! Local Scalars integer(${ik}$) :: i real(dp) :: normsq1, normsq2, scl1, scl2, ssq1, ssq2 ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB6', -info ) return end if ! first, project x onto the orthogonal complement of q's column ! space scl1 = zero ssq1 = one call stdlib${ii}$_dlassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_dlassq( m2, x2, incx2, scl2, ssq2 ) normsq1 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = zero end do else call stdlib${ii}$_dgemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ ) end if call stdlib${ii}$_dgemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ ) call stdlib${ii}$_dgemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 ) call stdlib${ii}$_dgemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_dlassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_dlassq( m2, x2, incx2, scl2, ssq2 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if projection is sufficiently large in norm, then stop. ! if projection is zero, then stop. ! otherwise, project again. if( normsq2 >= alphasq*normsq1 ) then return end if if( normsq2 == zero ) then return end if normsq1 = normsq2 do i = 1, n work(i) = zero end do if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = zero end do else call stdlib${ii}$_dgemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ ) end if call stdlib${ii}$_dgemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ ) call stdlib${ii}$_dgemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 ) call stdlib${ii}$_dgemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_dlassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_dlassq( m1, x1, incx1, scl1, ssq1 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if second projection is sufficiently large in norm, then do ! nothing more. alternatively, if it shrunk significantly, then ! truncate it to zero. if( normsq2 < alphasq*normsq1 ) then do i = 1, m1 x1(i) = zero end do do i = 1, m2 x2(i) = zero end do end if return end subroutine stdlib${ii}$_dorbdb6 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & !! DORBDB6: orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then the zero vector is returned. lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments real(${rk}$), intent(in) :: q1(ldq1,*), q2(ldq2,*) real(${rk}$), intent(out) :: work(*) real(${rk}$), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: alphasq = 0.01_${rk}$ ! Local Scalars integer(${ik}$) :: i real(${rk}$) :: normsq1, normsq2, scl1, scl2, ssq1, ssq2 ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DORBDB6', -info ) return end if ! first, project x onto the orthogonal complement of q's column ! space scl1 = zero ssq1 = one call stdlib${ii}$_${ri}$lassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_${ri}$lassq( m2, x2, incx2, scl2, ssq2 ) normsq1 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = zero end do else call stdlib${ii}$_${ri}$gemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ ) end if call stdlib${ii}$_${ri}$gemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 ) call stdlib${ii}$_${ri}$gemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_${ri}$lassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_${ri}$lassq( m2, x2, incx2, scl2, ssq2 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if projection is sufficiently large in norm, then stop. ! if projection is zero, then stop. ! otherwise, project again. if( normsq2 >= alphasq*normsq1 ) then return end if if( normsq2 == zero ) then return end if normsq1 = normsq2 do i = 1, n work(i) = zero end do if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = zero end do else call stdlib${ii}$_${ri}$gemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ ) end if call stdlib${ii}$_${ri}$gemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 ) call stdlib${ii}$_${ri}$gemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_${ri}$lassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_${ri}$lassq( m1, x1, incx1, scl1, ssq1 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if second projection is sufficiently large in norm, then do ! nothing more. alternatively, if it shrunk significantly, then ! truncate it to zero. if( normsq2 < alphasq*normsq1 ) then do i = 1, m1 x1(i) = zero end do do i = 1, m2 x2(i) = zero end do end if return end subroutine stdlib${ii}$_${ri}$orbdb6 #:endif #:endfor pure module subroutine stdlib${ii}$_slapmr( forwrd, m, n, x, ldx, k ) !! SLAPMR rearranges the rows of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M. !! If FORWRD = .TRUE., forward permutation: !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M. !! If FORWRD = .FALSE., backward permutation: !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) real(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, in, j, jj real(sp) :: temp ! Executable Statements if( m<=1 )return do i = 1, m k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, m if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do jj = 1, n temp = x( j, jj ) x( j, jj ) = x( in, jj ) x( in, jj ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, m if( k( i )>0 )go to 80 k( i ) = -k( i ) j = k( i ) 60 continue if( j==i )go to 80 do jj = 1, n temp = x( i, jj ) x( i, jj ) = x( j, jj ) x( j, jj ) = temp end do k( j ) = -k( j ) j = k( j ) go to 60 80 continue end do end if return end subroutine stdlib${ii}$_slapmr pure module subroutine stdlib${ii}$_dlapmr( forwrd, m, n, x, ldx, k ) !! DLAPMR rearranges the rows of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M. !! If FORWRD = .TRUE., forward permutation: !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M. !! If FORWRD = .FALSE., backward permutation: !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) real(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, in, j, jj real(dp) :: temp ! Executable Statements if( m<=1 )return do i = 1, m k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, m if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do jj = 1, n temp = x( j, jj ) x( j, jj ) = x( in, jj ) x( in, jj ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, m if( k( i )>0 )go to 80 k( i ) = -k( i ) j = k( i ) 60 continue if( j==i )go to 80 do jj = 1, n temp = x( i, jj ) x( i, jj ) = x( j, jj ) x( j, jj ) = temp end do k( j ) = -k( j ) j = k( j ) go to 60 80 continue end do end if return end subroutine stdlib${ii}$_dlapmr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lapmr( forwrd, m, n, x, ldx, k ) !! DLAPMR: rearranges the rows of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M. !! If FORWRD = .TRUE., forward permutation: !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M. !! If FORWRD = .FALSE., backward permutation: !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) real(${rk}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, in, j, jj real(${rk}$) :: temp ! Executable Statements if( m<=1 )return do i = 1, m k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, m if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do jj = 1, n temp = x( j, jj ) x( j, jj ) = x( in, jj ) x( in, jj ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, m if( k( i )>0 )go to 80 k( i ) = -k( i ) j = k( i ) 60 continue if( j==i )go to 80 do jj = 1, n temp = x( i, jj ) x( i, jj ) = x( j, jj ) x( j, jj ) = temp end do k( j ) = -k( j ) j = k( j ) go to 60 80 continue end do end if return end subroutine stdlib${ii}$_${ri}$lapmr #:endif #:endfor pure module subroutine stdlib${ii}$_clapmr( forwrd, m, n, x, ldx, k ) !! CLAPMR rearranges the rows of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M. !! If FORWRD = .TRUE., forward permutation: !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M. !! If FORWRD = .FALSE., backward permutation: !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) complex(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, in, j, jj complex(sp) :: temp ! Executable Statements if( m<=1 )return do i = 1, m k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, m if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do jj = 1, n temp = x( j, jj ) x( j, jj ) = x( in, jj ) x( in, jj ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, m if( k( i )>0 )go to 80 k( i ) = -k( i ) j = k( i ) 60 continue if( j==i )go to 80 do jj = 1, n temp = x( i, jj ) x( i, jj ) = x( j, jj ) x( j, jj ) = temp end do k( j ) = -k( j ) j = k( j ) go to 60 80 continue end do end if return end subroutine stdlib${ii}$_clapmr pure module subroutine stdlib${ii}$_zlapmr( forwrd, m, n, x, ldx, k ) !! ZLAPMR rearranges the rows of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M. !! If FORWRD = .TRUE., forward permutation: !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M. !! If FORWRD = .FALSE., backward permutation: !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) complex(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, in, j, jj complex(dp) :: temp ! Executable Statements if( m<=1 )return do i = 1, m k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, m if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do jj = 1, n temp = x( j, jj ) x( j, jj ) = x( in, jj ) x( in, jj ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, m if( k( i )>0 )go to 80 k( i ) = -k( i ) j = k( i ) 60 continue if( j==i )go to 80 do jj = 1, n temp = x( i, jj ) x( i, jj ) = x( j, jj ) x( j, jj ) = temp end do k( j ) = -k( j ) j = k( j ) go to 60 80 continue end do end if return end subroutine stdlib${ii}$_zlapmr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lapmr( forwrd, m, n, x, ldx, k ) !! ZLAPMR: rearranges the rows of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M. !! If FORWRD = .TRUE., forward permutation: !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M. !! If FORWRD = .FALSE., backward permutation: !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, in, j, jj complex(${ck}$) :: temp ! Executable Statements if( m<=1 )return do i = 1, m k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, m if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do jj = 1, n temp = x( j, jj ) x( j, jj ) = x( in, jj ) x( in, jj ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, m if( k( i )>0 )go to 80 k( i ) = -k( i ) j = k( i ) 60 continue if( j==i )go to 80 do jj = 1, n temp = x( i, jj ) x( i, jj ) = x( j, jj ) x( j, jj ) = temp end do k( j ) = -k( j ) j = k( j ) go to 60 80 continue end do end if return end subroutine stdlib${ii}$_${ci}$lapmr #:endif #:endfor pure module subroutine stdlib${ii}$_slapmt( forwrd, m, n, x, ldx, k ) !! SLAPMT rearranges the columns of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N. !! If FORWRD = .TRUE., forward permutation: !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N. !! If FORWRD = .FALSE., backward permutation: !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) real(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ii, j, in real(sp) :: temp ! Executable Statements if( n<=1 )return do i = 1, n k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, n if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do ii = 1, m temp = x( ii, j ) x( ii, j ) = x( ii, in ) x( ii, in ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, n if( k( i )>0 )go to 100 k( i ) = -k( i ) j = k( i ) 80 continue if( j==i )go to 100 do ii = 1, m temp = x( ii, i ) x( ii, i ) = x( ii, j ) x( ii, j ) = temp end do k( j ) = -k( j ) j = k( j ) go to 80 100 continue end do end if return end subroutine stdlib${ii}$_slapmt pure module subroutine stdlib${ii}$_dlapmt( forwrd, m, n, x, ldx, k ) !! DLAPMT rearranges the columns of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N. !! If FORWRD = .TRUE., forward permutation: !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N. !! If FORWRD = .FALSE., backward permutation: !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) real(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ii, in, j real(dp) :: temp ! Executable Statements if( n<=1 )return do i = 1, n k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, n if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do ii = 1, m temp = x( ii, j ) x( ii, j ) = x( ii, in ) x( ii, in ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, n if( k( i )>0 )go to 80 k( i ) = -k( i ) j = k( i ) 60 continue if( j==i )go to 80 do ii = 1, m temp = x( ii, i ) x( ii, i ) = x( ii, j ) x( ii, j ) = temp end do k( j ) = -k( j ) j = k( j ) go to 60 80 continue end do end if return end subroutine stdlib${ii}$_dlapmt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lapmt( forwrd, m, n, x, ldx, k ) !! DLAPMT: rearranges the columns of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N. !! If FORWRD = .TRUE., forward permutation: !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N. !! If FORWRD = .FALSE., backward permutation: !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) real(${rk}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ii, in, j real(${rk}$) :: temp ! Executable Statements if( n<=1 )return do i = 1, n k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, n if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do ii = 1, m temp = x( ii, j ) x( ii, j ) = x( ii, in ) x( ii, in ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, n if( k( i )>0 )go to 80 k( i ) = -k( i ) j = k( i ) 60 continue if( j==i )go to 80 do ii = 1, m temp = x( ii, i ) x( ii, i ) = x( ii, j ) x( ii, j ) = temp end do k( j ) = -k( j ) j = k( j ) go to 60 80 continue end do end if return end subroutine stdlib${ii}$_${ri}$lapmt #:endif #:endfor pure module subroutine stdlib${ii}$_clapmt( forwrd, m, n, x, ldx, k ) !! CLAPMT rearranges the columns of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N. !! If FORWRD = .TRUE., forward permutation: !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N. !! If FORWRD = .FALSE., backward permutation: !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) complex(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ii, j, in complex(sp) :: temp ! Executable Statements if( n<=1 )return do i = 1, n k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, n if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do ii = 1, m temp = x( ii, j ) x( ii, j ) = x( ii, in ) x( ii, in ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, n if( k( i )>0 )go to 100 k( i ) = -k( i ) j = k( i ) 80 continue if( j==i )go to 100 do ii = 1, m temp = x( ii, i ) x( ii, i ) = x( ii, j ) x( ii, j ) = temp end do k( j ) = -k( j ) j = k( j ) go to 80 100 continue end do end if return end subroutine stdlib${ii}$_clapmt pure module subroutine stdlib${ii}$_zlapmt( forwrd, m, n, x, ldx, k ) !! ZLAPMT rearranges the columns of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N. !! If FORWRD = .TRUE., forward permutation: !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N. !! If FORWRD = .FALSE., backward permutation: !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) complex(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ii, in, j complex(dp) :: temp ! Executable Statements if( n<=1 )return do i = 1, n k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, n if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do ii = 1, m temp = x( ii, j ) x( ii, j ) = x( ii, in ) x( ii, in ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, n if( k( i )>0 )go to 80 k( i ) = -k( i ) j = k( i ) 60 continue if( j==i )go to 80 do ii = 1, m temp = x( ii, i ) x( ii, i ) = x( ii, j ) x( ii, j ) = temp end do k( j ) = -k( j ) j = k( j ) go to 60 80 continue end do end if return end subroutine stdlib${ii}$_zlapmt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lapmt( forwrd, m, n, x, ldx, k ) !! ZLAPMT: rearranges the columns of the M by N matrix X as specified !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N. !! If FORWRD = .TRUE., forward permutation: !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N. !! If FORWRD = .FALSE., backward permutation: !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: forwrd integer(${ik}$), intent(in) :: ldx, m, n ! Array Arguments integer(${ik}$), intent(inout) :: k(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ii, in, j complex(${ck}$) :: temp ! Executable Statements if( n<=1 )return do i = 1, n k( i ) = -k( i ) end do if( forwrd ) then ! forward permutation do i = 1, n if( k( i )>0 )go to 40 j = i k( j ) = -k( j ) in = k( j ) 20 continue if( k( in )>0 )go to 40 do ii = 1, m temp = x( ii, j ) x( ii, j ) = x( ii, in ) x( ii, in ) = temp end do k( in ) = -k( in ) j = in in = k( in ) go to 20 40 continue end do else ! backward permutation do i = 1, n if( k( i )>0 )go to 80 k( i ) = -k( i ) j = k( i ) 60 continue if( j==i )go to 80 do ii = 1, m temp = x( ii, i ) x( ii, i ) = x( ii, j ) x( ii, j ) = temp end do k( j ) = -k( j ) j = k( j ) go to 60 80 continue end do end if return end subroutine stdlib${ii}$_${ci}$lapmt #:endif #:endfor #:endfor end submodule stdlib_lapack_cosine_sine2 fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_solve_ldl_comp4.fypp0000664000175000017500000236576715135654166027103 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_solve) stdlib_lapack_solve_ldl_comp4 implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_chprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, work,& !! CHPRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian indefinite !! and packed, and provides error bounds and backward error estimates !! for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: afp(*), ap(*), b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_chptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) call stdlib${ii}$_caxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_chptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_chptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_chprfs pure module subroutine stdlib${ii}$_zhprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, work,& !! ZHPRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian indefinite !! and packed, and provides error bounds and backward error estimates !! for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: afp(*), ap(*), b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_zhptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) call stdlib${ii}$_zaxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_zhptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_zhptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_zhprfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hprfs( uplo, n, nrhs, ap, afp, ipiv, b, ldb, x, ldx,ferr, berr, work,& !! ZHPRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian indefinite !! and packed, and provides error bounds and backward error estimates !! for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: afp(*), ap(*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ci}$hptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) call stdlib${ii}$_${ci}$axpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_${ci}$hptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$hptrs( uplo, n, 1_${ik}$, afp, ipiv, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ci}$hprfs #:endif #:endfor pure module subroutine stdlib${ii}$_checon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) !! CHECON_ROOK estimates the reciprocal of the condition number of a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHETRF_ROOK. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(sp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**h) or inv(u*d*u**h). call stdlib${ii}$_chetrs_rook( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_checon_rook pure module subroutine stdlib${ii}$_zhecon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) !! ZHECON_ROOK estimates the reciprocal of the condition number of a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHETRF_ROOK. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(dp), intent(in) :: anorm real(dp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(dp) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**h) or inv(u*d*u**h). call stdlib${ii}$_zhetrs_rook( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_zhecon_rook #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hecon_rook( uplo, n, a, lda, ipiv, anorm, rcond, work,info ) !! ZHECON_ROOK: estimates the reciprocal of the condition number of a complex !! Hermitian matrix A using the factorization A = U*D*U**H or !! A = L*D*L**H computed by CHETRF_ROOK. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(in) :: anorm real(${ck}$), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, kase real(${ck}$) :: ainvnm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 .and. a( i, i )==zero )return end do else ! lower triangular storage: examine d from top to bottom. do i = 1, n if( ipiv( i )>0 .and. a( i, i )==zero )return end do end if ! estimate the 1-norm of the inverse. kase = 0_${ik}$ 30 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then ! multiply by inv(l*d*l**h) or inv(u*d*u**h). call stdlib${ii}$_${ci}$hetrs_rook( uplo, n, 1_${ik}$, a, lda, ipiv, work, n, info ) go to 30 end if ! compute the estimate of the reciprocal condition number. if( ainvnm/=zero )rcond = ( one / ainvnm ) / anorm return end subroutine stdlib${ii}$_${ci}$hecon_rook #:endif #:endfor pure module subroutine stdlib${ii}$_chetrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) !! CHETRF_ROOK computes the factorization of a complex Hermitian matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method. !! The form of the factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_clahef_rook( uplo, k, nb, kb, a, lda,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_chetf2_rook( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_clahef_rook; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_clahef_rook( uplo, n-k+1, nb, kb, a( k, k ), lda,ipiv( k ), work, & ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_chetf2_rook( uplo, n-k+1, a( k, k ), lda, ipiv( k ),iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_chetrf_rook pure module subroutine stdlib${ii}$_zhetrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) !! ZHETRF_ROOK computes the factorization of a complex Hermitian matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method. !! The form of the factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_zlahef_rook( uplo, k, nb, kb, a, lda,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_zhetf2_rook( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_zlahef_rook; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_zlahef_rook( uplo, n-k+1, nb, kb, a( k, k ), lda,ipiv( k ), work, & ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_zhetf2_rook( uplo, n-k+1, a( k, k ), lda, ipiv( k ),iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zhetrf_rook #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hetrf_rook( uplo, n, a, lda, ipiv, work, lwork, info ) !! ZHETRF_ROOK: computes the factorization of a complex Hermitian matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method. !! The form of the factorization is !! A = U*D*U**T or A = L*D*L**T !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and D is Hermitian and block diagonal with !! 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: iinfo, iws, j, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_${ci}$lahef_rook( uplo, k, nb, kb, a, lda,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_${ci}$hetf2_rook( uplo, k, a, lda, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! decrease k and return to the start of the main loop k = k - kb go to 10 else ! factorize a as l*d*l**t using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! kb, where kb is the number of columns factorized by stdlib${ii}$_${ci}$lahef_rook; ! kb is either nb or nb-1, or n-k+1 for the last block k = 1_${ik}$ 20 continue ! if k > n, exit from loop if( k>n )go to 40 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_${ci}$lahef_rook( uplo, n-k+1, nb, kb, a( k, k ), lda,ipiv( k ), work, & ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_${ci}$hetf2_rook( uplo, n-k+1, a( k, k ), lda, ipiv( k ),iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do j = k, k + kb - 1 if( ipiv( j )>0_${ik}$ ) then ipiv( j ) = ipiv( j ) + k - 1_${ik}$ else ipiv( j ) = ipiv( j ) - k + 1_${ik}$ end if end do ! increase k and return to the start of the main loop k = k + kb go to 20 end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$hetrf_rook #:endif #:endfor pure module subroutine stdlib${ii}$_clahef_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) !! CLAHEF_ROOK computes a partial factorization of a complex Hermitian !! matrix A using the bounded Bunch-Kaufman ("rook") diagonal pivoting !! method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**H U22**H ) !! A = ( L11 0 ) ( D 0 ) ( L11**H L21**H ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**H denotes the conjugate transpose of U. !! CLAHEF_ROOK is an auxiliary routine called by CHETRF_ROOK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars logical(lk) :: done integer(${ik}$) :: imax, itemp, ii, j, jb, jj, jmax, jp1, jp2, k, kk, kkw, kp, kstep, kw, & p real(sp) :: absakk, alpha, colmax, stemp, r1, rowmax, t, sfmin complex(sp) :: d11, d21, d22, z ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=sp) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight ! compute machine safe minimum sfmin = stdlib${ii}$_slamch( 'S' ) if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 (note that conjg(w) is actually stored) ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ )call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) w( k, kw ) = real( a( k, k ),KIND=sp) if( k1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( w( k, kw ),KIND=sp) if( k>1_${ik}$ )call stdlib${ii}$_ccopy( k-1, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_ccopy( imax-1, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ),1_${ik}$ ) w( imax, kw-1 ) = real( a( imax, imax ),KIND=sp) call stdlib${ii}$_ccopy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_clacgv( k-imax, w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then itemp = stdlib${ii}$_icamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) stemp = cabs1( w( itemp, kw-1 ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=sp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,kw-1 ),KIND=sp) )1_${ik}$ )call stdlib${ii}$_ccopy( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! interchange rows k and p in the last k+1 to n columns of a ! (columns k and k-1 of a for 2-by-2 pivot will be ! later overwritten). interchange rows k and p ! in last kkw to nb columns of w. if( k1_${ik}$ )call stdlib${ii}$_ccopy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k1_${ik}$ ) then ! (note: no need to check if a(k,k) is not zero, ! since that was ensured earlier in pivot search: ! case a(k,k) = 0 falls into 2x2 pivot case(3)) ! handle division by a small number t = real( a( k, k ),KIND=sp) if( abs( t )>=sfmin ) then r1 = one / t call stdlib${ii}$_csscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else do ii = 1, k-1 a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(kw) call stdlib${ii}$_clacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now hold ! ( w(kw-1) w(kw) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! (1) store u(1:k-2,k-1) and u(1:k-2,k) and 2-by-2 ! block d(k-1:k,k-1:k) in columns k-1 and k of a. ! (note: 2-by-2 diagonal block u(k-1:k,k-1:k) is a unit ! block and not stored) ! a(k-1:k,k-1:k) := d(k-1:k,k-1:k) = w(k-1:k,kw-1:kw) ! a(1:k-2,k-1:k) := u(1:k-2,k:k-1:k) = ! = w(1:k-2,kw-1:kw) * ( d(k-1:k,k-1:k)**(-1) ) if( k>2_${ik}$ ) then ! factor out the columns of the inverse of 2-by-2 pivot ! block d, so that each column contains 1, to reduce the ! number of flops when we multiply panel ! ( w(kw-1) w(kw) ) by this inverse, i.e. by d**(-1). ! d**(-1) = ( d11 cj(d21) )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-|d21|**2) * ( ( d22) (-cj(d21) ) ) = ! ( (-d21) ( d11 ) ) ! = 1/(|d21|**2) * 1/((d11/cj(d21))*(d22/d21)-1) * ! * ( d21*( d22/d21 ) conj(d21)*( - 1 ) ) = ! ( ( -1 ) ( d11/conj(d21) ) ) ! = 1/(|d21|**2) * 1/(d22*d11-1) * ! * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = (1/|d21|**2) * t * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( (t/conj(d21))*( d11 ) (t/d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! handle division by a small number. (note: order of ! operations is important) ! = ( t*(( d11 )/conj(d21)) t*(( -1 )/d21 ) ) ! ( (( -1 ) ) (( d22 ) ) ), ! where d11 = d22/d21, ! d22 = d11/conj(d21), ! d21 = d21, ! t = 1/(d22*d11-1). ! (note: no need to check for division by zero, ! since that was ensured earlier in pivot search: ! (a) d21 != 0 in 2x2 pivot case(4), ! since |d21| should be larger than |d11| and |d22|; ! (b) (d22*d11 - 1) != 0, since from (a), ! both |d11| < 1, |d22| < 1, hence |d22*d11| << 1.) d21 = w( k-1, kw ) d11 = w( k, kw ) / conjg( d21 ) d22 = w( k-1, kw-1 ) / d21 t = one / ( real( d11*d22,KIND=sp)-one ) ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = t*( ( d11*w( j, kw-1 )-w( j, kw ) ) /d21 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /conjg( d21 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) ! (2) conjugate columns w(kw) and w(kw-1) call stdlib${ii}$_clacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) call stdlib${ii}$_clacgv( k-2, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**h = a11 - u12*w**h ! computing blocks of nb columns at a time (note that conjg(w) is ! actually stored) do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 a( jj, jj ) = real( a( jj, jj ),KIND=sp) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) a( jj, jj ) = real( a( jj, jj ),KIND=sp) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in of rows in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows j and jp2 ! (or j and jp2, and j+1 and jp1) at each step j kstep = 1_${ik}$ jp1 = 1_${ik}$ ! (here, j is a diagonal index) jj = j jp2 = ipiv( j ) if( jp2<0_${ik}$ ) then jp2 = -jp2 ! (here, j is a diagonal index) j = j + 1_${ik}$ jp1 = -ipiv( j ) kstep = 2_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp2/=jj .and. j<=n )call stdlib${ii}$_cswap( n-j+1, a( jp2, j ), lda, a( jj, j ), & lda ) jj = jj + 1_${ik}$ if( kstep==2_${ik}$ .and. jp1/=jj .and. j<=n )call stdlib${ii}$_cswap( n-j+1, a( jp1, j ), & lda, a( jj, j ), lda ) if( j=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update column k of w w( k, k ) = real( a( k, k ),KIND=sp) if( k1_${ik}$ ) then call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, 1_${ik}$ ), & ldw, cone, w( k, k ), 1_${ik}$ ) w( k, k ) = real( w( k, k ),KIND=sp) end if ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( w( k, k ),KIND=sp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), lda, w( & imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) w( imax, k+1 ) = real( w( imax, k+1 ),KIND=sp) end if ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_icamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = stemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,k+1 ),KIND=sp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,k+1 ),KIND=sp) )1_${ik}$ )call stdlib${ii}$_cswap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) call stdlib${ii}$_cswap( kk, w( k, 1_${ik}$ ), ldw, w( p, 1_${ik}$ ), ldw ) end if ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=sp) call stdlib${ii}$_ccopy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) call stdlib${ii}$_clacgv( kp-kk-1, a( kp, kk+1 ), lda ) if( kp1_${ik}$ )call stdlib${ii}$_cswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_cswap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! (1) store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) ! (note: no need to use for hermitian matrix ! a( k, k ) = real( w( k, k),KIND=sp) to separately copy diagonal ! element d(k,k) from w (potentially saves only one load)) call stdlib${ii}$_ccopy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=sfmin ) then r1 = one / t call stdlib${ii}$_csscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else do ii = k + 1, n a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(k) call stdlib${ii}$_clacgv( n-k, w( k+1, k ), 1_${ik}$ ) end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! (1) store l(k+2:n,k) and l(k+2:n,k+1) and 2-by-2 ! block d(k:k+1,k:k+1) in columns k and k+1 of a. ! note: 2-by-2 diagonal block l(k:k+1,k:k+1) is a unit ! block and not stored. ! a(k:k+1,k:k+1) := d(k:k+1,k:k+1) = w(k:k+1,k:k+1) ! a(k+2:n,k:k+1) := l(k+2:n,k:k+1) = ! = w(k+2:n,k:k+1) * ( d(k:k+1,k:k+1)**(-1) ) if( k=1_${ik}$ )call stdlib${ii}$_cswap( j, a( jp2, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) jj = jj -1_${ik}$ if( kstep==2_${ik}$ .and. jp1/=jj .and. j>=1_${ik}$ )call stdlib${ii}$_cswap( j, a( jp1, 1_${ik}$ ), lda, a(& jj, 1_${ik}$ ), lda ) if( j>1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_clahef_rook pure module subroutine stdlib${ii}$_zlahef_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) !! ZLAHEF_ROOK computes a partial factorization of a complex Hermitian !! matrix A using the bounded Bunch-Kaufman ("rook") diagonal pivoting !! method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**H U22**H ) !! A = ( L11 0 ) ( D 0 ) ( L11**H L21**H ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**H denotes the conjugate transpose of U. !! ZLAHEF_ROOK is an auxiliary routine called by ZHETRF_ROOK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(dp), parameter :: sevten = 17.0e+0_dp ! Local Scalars logical(lk) :: done integer(${ik}$) :: imax, itemp, ii, j, jb, jj, jmax, jp1, jp2, k, kk, kkw, kp, kstep, kw, & p real(dp) :: absakk, alpha, colmax, dtemp, r1, rowmax, t, sfmin complex(dp) :: d11, d21, d22, z ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=dp) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight ! compute machine safe minimum sfmin = stdlib${ii}$_dlamch( 'S' ) if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 (note that conjg(w) is actually stored) ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ )call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) w( k, kw ) = real( a( k, k ),KIND=dp) if( k1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( w( k, kw ),KIND=dp) if( k>1_${ik}$ )call stdlib${ii}$_zcopy( k-1, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_zcopy( imax-1, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ),1_${ik}$ ) w( imax, kw-1 ) = real( a( imax, imax ),KIND=dp) call stdlib${ii}$_zcopy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( k-imax, w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then itemp = stdlib${ii}$_izamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = cabs1( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=dp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,kw-1 ),KIND=dp) )1_${ik}$ )call stdlib${ii}$_zcopy( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! interchange rows k and p in the last k+1 to n columns of a ! (columns k and k-1 of a for 2-by-2 pivot will be ! later overwritten). interchange rows k and p ! in last kkw to nb columns of w. if( k1_${ik}$ )call stdlib${ii}$_zcopy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k1_${ik}$ ) then ! (note: no need to check if a(k,k) is not zero, ! since that was ensured earlier in pivot search: ! case a(k,k) = 0 falls into 2x2 pivot case(3)) ! handle division by a small number t = real( a( k, k ),KIND=dp) if( abs( t )>=sfmin ) then r1 = one / t call stdlib${ii}$_zdscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else do ii = 1, k-1 a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(kw) call stdlib${ii}$_zlacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now hold ! ( w(kw-1) w(kw) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! (1) store u(1:k-2,k-1) and u(1:k-2,k) and 2-by-2 ! block d(k-1:k,k-1:k) in columns k-1 and k of a. ! (note: 2-by-2 diagonal block u(k-1:k,k-1:k) is a unit ! block and not stored) ! a(k-1:k,k-1:k) := d(k-1:k,k-1:k) = w(k-1:k,kw-1:kw) ! a(1:k-2,k-1:k) := u(1:k-2,k:k-1:k) = ! = w(1:k-2,kw-1:kw) * ( d(k-1:k,k-1:k)**(-1) ) if( k>2_${ik}$ ) then ! factor out the columns of the inverse of 2-by-2 pivot ! block d, so that each column contains 1, to reduce the ! number of flops when we multiply panel ! ( w(kw-1) w(kw) ) by this inverse, i.e. by d**(-1). ! d**(-1) = ( d11 cj(d21) )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-|d21|**2) * ( ( d22) (-cj(d21) ) ) = ! ( (-d21) ( d11 ) ) ! = 1/(|d21|**2) * 1/((d11/cj(d21))*(d22/d21)-1) * ! * ( d21*( d22/d21 ) conj(d21)*( - 1 ) ) = ! ( ( -1 ) ( d11/conj(d21) ) ) ! = 1/(|d21|**2) * 1/(d22*d11-1) * ! * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = (1/|d21|**2) * t * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( (t/conj(d21))*( d11 ) (t/d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! handle division by a small number. (note: order of ! operations is important) ! = ( t*(( d11 )/conj(d21)) t*(( -1 )/d21 ) ) ! ( (( -1 ) ) (( d22 ) ) ), ! where d11 = d22/d21, ! d22 = d11/conj(d21), ! d21 = d21, ! t = 1/(d22*d11-1). ! (note: no need to check for division by zero, ! since that was ensured earlier in pivot search: ! (a) d21 != 0 in 2x2 pivot case(4), ! since |d21| should be larger than |d11| and |d22|; ! (b) (d22*d11 - 1) != 0, since from (a), ! both |d11| < 1, |d22| < 1, hence |d22*d11| << 1.) d21 = w( k-1, kw ) d11 = w( k, kw ) / conjg( d21 ) d22 = w( k-1, kw-1 ) / d21 t = one / ( real( d11*d22,KIND=dp)-one ) ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = t*( ( d11*w( j, kw-1 )-w( j, kw ) ) /d21 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /conjg( d21 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) ! (2) conjugate columns w(kw) and w(kw-1) call stdlib${ii}$_zlacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( k-2, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**h = a11 - u12*w**h ! computing blocks of nb columns at a time (note that conjg(w) is ! actually stored) do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 a( jj, jj ) = real( a( jj, jj ),KIND=dp) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) a( jj, jj ) = real( a( jj, jj ),KIND=dp) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in of rows in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows j and jp2 ! (or j and jp2, and j+1 and jp1) at each step j kstep = 1_${ik}$ jp1 = 1_${ik}$ ! (here, j is a diagonal index) jj = j jp2 = ipiv( j ) if( jp2<0_${ik}$ ) then jp2 = -jp2 ! (here, j is a diagonal index) j = j + 1_${ik}$ jp1 = -ipiv( j ) kstep = 2_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp2/=jj .and. j<=n )call stdlib${ii}$_zswap( n-j+1, a( jp2, j ), lda, a( jj, j ), & lda ) jj = jj + 1_${ik}$ if( kstep==2_${ik}$ .and. jp1/=jj .and. j<=n )call stdlib${ii}$_zswap( n-j+1, a( jp1, j ), & lda, a( jj, j ), lda ) if( j=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update column k of w w( k, k ) = real( a( k, k ),KIND=dp) if( k1_${ik}$ ) then call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, 1_${ik}$ ), & ldw, cone, w( k, k ), 1_${ik}$ ) w( k, k ) = real( w( k, k ),KIND=dp) end if ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( w( k, k ),KIND=dp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), lda, w( & imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) w( imax, k+1 ) = real( w( imax, k+1 ),KIND=dp) end if ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_izamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,k+1 ),KIND=dp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,k+1 ),KIND=dp) )1_${ik}$ )call stdlib${ii}$_zswap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) call stdlib${ii}$_zswap( kk, w( k, 1_${ik}$ ), ldw, w( p, 1_${ik}$ ), ldw ) end if ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=dp) call stdlib${ii}$_zcopy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) call stdlib${ii}$_zlacgv( kp-kk-1, a( kp, kk+1 ), lda ) if( kp1_${ik}$ )call stdlib${ii}$_zswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_zswap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! (1) store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) ! (note: no need to use for hermitian matrix ! a( k, k ) = real( w( k, k),KIND=dp) to separately copy diagonal ! element d(k,k) from w (potentially saves only one load)) call stdlib${ii}$_zcopy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=sfmin ) then r1 = one / t call stdlib${ii}$_zdscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else do ii = k + 1, n a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(k) call stdlib${ii}$_zlacgv( n-k, w( k+1, k ), 1_${ik}$ ) end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! (1) store l(k+2:n,k) and l(k+2:n,k+1) and 2-by-2 ! block d(k:k+1,k:k+1) in columns k and k+1 of a. ! note: 2-by-2 diagonal block l(k:k+1,k:k+1) is a unit ! block and not stored. ! a(k:k+1,k:k+1) := d(k:k+1,k:k+1) = w(k:k+1,k:k+1) ! a(k+2:n,k:k+1) := l(k+2:n,k:k+1) = ! = w(k+2:n,k:k+1) * ( d(k:k+1,k:k+1)**(-1) ) if( k=1_${ik}$ )call stdlib${ii}$_zswap( j, a( jp2, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) jj = jj -1_${ik}$ if( kstep==2_${ik}$ .and. jp1/=jj .and. j>=1_${ik}$ )call stdlib${ii}$_zswap( j, a( jp1, 1_${ik}$ ), lda, a(& jj, 1_${ik}$ ), lda ) if( j>1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_zlahef_rook #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lahef_rook( uplo, n, nb, kb, a, lda, ipiv, w, ldw,info ) !! ZLAHEF_ROOK: computes a partial factorization of a complex Hermitian !! matrix A using the bounded Bunch-Kaufman ("rook") diagonal pivoting !! method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**H U22**H ) !! A = ( L11 0 ) ( D 0 ) ( L11**H L21**H ) if UPLO = 'L' !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! Note that U**H denotes the conjugate transpose of U. !! ZLAHEF_ROOK is an auxiliary routine called by ZHETRF_ROOK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: w(ldw,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: sevten = 17.0e+0_${ck}$ ! Local Scalars logical(lk) :: done integer(${ik}$) :: imax, itemp, ii, j, jb, jj, jmax, jp1, jp2, k, kk, kkw, kp, kstep, kw, & p real(${ck}$) :: absakk, alpha, colmax, dtemp, r1, rowmax, t, sfmin complex(${ck}$) :: d11, d21, d22, z ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=${ck}$) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight ! compute machine safe minimum sfmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 (note that conjg(w) is actually stored) ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ )call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) w( k, kw ) = real( a( k, k ),KIND=${ck}$) if( k1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( w( k, kw ),KIND=${ck}$) if( k>1_${ik}$ )call stdlib${ii}$_${ci}$copy( k-1, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_${ci}$copy( imax-1, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ),1_${ik}$ ) w( imax, kw-1 ) = real( a( imax, imax ),KIND=${ck}$) call stdlib${ii}$_${ci}$copy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( k-imax, w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then itemp = stdlib${ii}$_i${ci}$amax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = cabs1( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=${ck}$) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,kw-1 ),KIND=${ck}$) )1_${ik}$ )call stdlib${ii}$_${ci}$copy( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! interchange rows k and p in the last k+1 to n columns of a ! (columns k and k-1 of a for 2-by-2 pivot will be ! later overwritten). interchange rows k and p ! in last kkw to nb columns of w. if( k1_${ik}$ )call stdlib${ii}$_${ci}$copy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k1_${ik}$ ) then ! (note: no need to check if a(k,k) is not zero, ! since that was ensured earlier in pivot search: ! case a(k,k) = 0 falls into 2x2 pivot case(3)) ! handle division by a small number t = real( a( k, k ),KIND=${ck}$) if( abs( t )>=sfmin ) then r1 = one / t call stdlib${ii}$_${ci}$dscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else do ii = 1, k-1 a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(kw) call stdlib${ii}$_${ci}$lacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now hold ! ( w(kw-1) w(kw) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! (1) store u(1:k-2,k-1) and u(1:k-2,k) and 2-by-2 ! block d(k-1:k,k-1:k) in columns k-1 and k of a. ! (note: 2-by-2 diagonal block u(k-1:k,k-1:k) is a unit ! block and not stored) ! a(k-1:k,k-1:k) := d(k-1:k,k-1:k) = w(k-1:k,kw-1:kw) ! a(1:k-2,k-1:k) := u(1:k-2,k:k-1:k) = ! = w(1:k-2,kw-1:kw) * ( d(k-1:k,k-1:k)**(-1) ) if( k>2_${ik}$ ) then ! factor out the columns of the inverse of 2-by-2 pivot ! block d, so that each column contains 1, to reduce the ! number of flops when we multiply panel ! ( w(kw-1) w(kw) ) by this inverse, i.e. by d**(-1). ! d**(-1) = ( d11 cj(d21) )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-|d21|**2) * ( ( d22) (-cj(d21) ) ) = ! ( (-d21) ( d11 ) ) ! = 1/(|d21|**2) * 1/((d11/cj(d21))*(d22/d21)-1) * ! * ( d21*( d22/d21 ) conj(d21)*( - 1 ) ) = ! ( ( -1 ) ( d11/conj(d21) ) ) ! = 1/(|d21|**2) * 1/(d22*d11-1) * ! * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = (1/|d21|**2) * t * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( (t/conj(d21))*( d11 ) (t/d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! handle division by a small number. (note: order of ! operations is important) ! = ( t*(( d11 )/conj(d21)) t*(( -1 )/d21 ) ) ! ( (( -1 ) ) (( d22 ) ) ), ! where d11 = d22/d21, ! d22 = d11/conj(d21), ! d21 = d21, ! t = 1/(d22*d11-1). ! (note: no need to check for division by zero, ! since that was ensured earlier in pivot search: ! (a) d21 != 0 in 2x2 pivot case(4), ! since |d21| should be larger than |d11| and |d22|; ! (b) (d22*d11 - 1) != 0, since from (a), ! both |d11| < 1, |d22| < 1, hence |d22*d11| << 1.) d21 = w( k-1, kw ) d11 = w( k, kw ) / conjg( d21 ) d22 = w( k-1, kw-1 ) / d21 t = one / ( real( d11*d22,KIND=${ck}$)-one ) ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = t*( ( d11*w( j, kw-1 )-w( j, kw ) ) /d21 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /conjg( d21 ) ) end do end if ! copy d(k) to a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = w( k-1, kw ) a( k, k ) = w( k, kw ) ! (2) conjugate columns w(kw) and w(kw-1) call stdlib${ii}$_${ci}$lacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( k-2, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**h = a11 - u12*w**h ! computing blocks of nb columns at a time (note that conjg(w) is ! actually stored) do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 a( jj, jj ) = real( a( jj, jj ),KIND=${ck}$) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) a( jj, jj ) = real( a( jj, jj ),KIND=${ck}$) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! put u12 in standard form by partially undoing the interchanges ! in of rows in columns k+1:n looping backwards from k+1 to n j = k + 1_${ik}$ 60 continue ! undo the interchanges (if any) of rows j and jp2 ! (or j and jp2, and j+1 and jp1) at each step j kstep = 1_${ik}$ jp1 = 1_${ik}$ ! (here, j is a diagonal index) jj = j jp2 = ipiv( j ) if( jp2<0_${ik}$ ) then jp2 = -jp2 ! (here, j is a diagonal index) j = j + 1_${ik}$ jp1 = -ipiv( j ) kstep = 2_${ik}$ end if ! (note: here, j is used to determine row length. length n-j+1 ! of the rows to swap back doesn't include diagonal element) j = j + 1_${ik}$ if( jp2/=jj .and. j<=n )call stdlib${ii}$_${ci}$swap( n-j+1, a( jp2, j ), lda, a( jj, j ), & lda ) jj = jj + 1_${ik}$ if( kstep==2_${ik}$ .and. jp1/=jj .and. j<=n )call stdlib${ii}$_${ci}$swap( n-j+1, a( jp1, j ), & lda, a( jj, j ), lda ) if( j=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update column k of w w( k, k ) = real( a( k, k ),KIND=${ck}$) if( k1_${ik}$ ) then call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, 1_${ik}$ ), & ldw, cone, w( k, k ), 1_${ik}$ ) w( k, k ) = real( w( k, k ),KIND=${ck}$) end if ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( w( k, k ),KIND=${ck}$) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), lda, w( & imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) w( imax, k+1 ) = real( w( imax, k+1 ),KIND=${ck}$) end if ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_i${ci}$amax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,k+1 ),KIND=${ck}$) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,k+1 ),KIND=${ck}$) )1_${ik}$ )call stdlib${ii}$_${ci}$swap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$swap( kk, w( k, 1_${ik}$ ), ldw, w( p, 1_${ik}$ ), ldw ) end if ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=${ck}$) call stdlib${ii}$_${ci}$copy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) call stdlib${ii}$_${ci}$lacgv( kp-kk-1, a( kp, kk+1 ), lda ) if( kp1_${ik}$ )call stdlib${ii}$_${ci}$swap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$swap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! (1) store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) ! (note: no need to use for hermitian matrix ! a( k, k ) = real( w( k, k),KIND=${ck}$) to separately copy diagonal ! element d(k,k) from w (potentially saves only one load)) call stdlib${ii}$_${ci}$copy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=sfmin ) then r1 = one / t call stdlib${ii}$_${ci}$dscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else do ii = k + 1, n a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(k) call stdlib${ii}$_${ci}$lacgv( n-k, w( k+1, k ), 1_${ik}$ ) end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! (1) store l(k+2:n,k) and l(k+2:n,k+1) and 2-by-2 ! block d(k:k+1,k:k+1) in columns k and k+1 of a. ! note: 2-by-2 diagonal block l(k:k+1,k:k+1) is a unit ! block and not stored. ! a(k:k+1,k:k+1) := d(k:k+1,k:k+1) = w(k:k+1,k:k+1) ! a(k+2:n,k:k+1) := l(k+2:n,k:k+1) = ! = w(k+2:n,k:k+1) * ( d(k:k+1,k:k+1)**(-1) ) if( k=1_${ik}$ )call stdlib${ii}$_${ci}$swap( j, a( jp2, 1_${ik}$ ), lda, a( jj, 1_${ik}$ ), lda ) jj = jj -1_${ik}$ if( kstep==2_${ik}$ .and. jp1/=jj .and. j>=1_${ik}$ )call stdlib${ii}$_${ci}$swap( j, a( jp1, 1_${ik}$ ), lda, a(& jj, 1_${ik}$ ), lda ) if( j>1 )go to 120 ! set kb to the number of columns factorized kb = k - 1_${ik}$ end if return end subroutine stdlib${ii}$_${ci}$lahef_rook #:endif #:endfor pure module subroutine stdlib${ii}$_chetf2_rook( uplo, n, a, lda, ipiv, info ) !! CHETF2_ROOK computes the factorization of a complex Hermitian matrix A !! using the bounded Bunch-Kaufman ("rook") diagonal pivoting method: !! A = U*D*U**H or A = L*D*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, U**H is the conjugate transpose of U, and D is !! Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) ! ====================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars logical(lk) :: done, upper integer(${ik}$) :: i, ii, imax, itemp, j, jmax, k, kk, kp, kstep, p real(sp) :: absakk, alpha, colmax, d, d11, d22, r1, stemp, rowmax, tt, sfmin complex(sp) :: d12, d21, t, wk, wkm1, wkp1, z ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=sp) ) + abs( aimag( z ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( ( max( absakk, colmax )==zero ) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=sp) else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_icamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) stemp = cabs1( a( itemp, imax ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=sp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=sp) )1_${ik}$ )call stdlib${ii}$_cswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = p + 1, k - 1 t = conjg( a( j, k ) ) a( j, k ) = conjg( a( p, j ) ) a( p, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( p, k ) = conjg( a( p, k ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( k, k ),KIND=sp) a( k, k ) = real( a( p, p ),KIND=sp) a( p, p ) = r1 end if ! for both 1x1 and 2x2 pivots, interchange rows and ! columns kk and kp in the leading submatrix a(1:k,1:k) if( kp/=kk ) then ! (1) swap columnar parts if( kp>1_${ik}$ )call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = kp + 1, kk - 1 t = conjg( a( j, kk ) ) a( j, kk ) = conjg( a( kp, j ) ) a( kp, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( kp, kk ) = conjg( a( kp, kk ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( kk, kk ),KIND=sp) a( kk, kk ) = real( a( kp, kp ),KIND=sp) a( kp, kp ) = r1 if( kstep==2_${ik}$ ) then ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=sp) ! (5) swap row elements t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if else ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=sp) if( kstep==2_${ik}$ )a( k-1, k-1 ) = real( a( k-1, k-1 ),KIND=sp) end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u if( k>1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( real( a( k, k ),KIND=sp) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / real( a( k, k ),KIND=sp) call stdlib${ii}$_cher( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_csscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=sp) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_cher( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then ! d = |a12| d = stdlib${ii}$_slapy2( real( a( k-1, k ),KIND=sp),aimag( a( k-1, k ) ) ) d11 = real( a( k, k ) / d,KIND=sp) d22 = real( a( k-1, k-1 ) / d,KIND=sp) d12 = a( k-1, k ) / d tt = one / ( d11*d22-one ) do j = k - 2, 1, -1 ! compute d21 * ( w(k)w(k+1) ) * inv(d(k)) for row j wkm1 = tt*( d11*a( j, k-1 )-conjg( d12 )*a( j, k ) ) wk = tt*( d22*a( j, k )-d12*a( j, k-1 ) ) ! perform a rank-2 update of a(1:k-2,1:k-2) do i = j, 1, -1 a( i, j ) = a( i, j ) -( a( i, k ) / d )*conjg( wk ) -( a( i, k-1 ) & / d )*conjg( wkm1 ) end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d a( j, k-1 ) = wkm1 / d ! (*) make sure that diagonal element of pivot is real a( j, j ) = cmplx( real( a( j, j ),KIND=sp), zero,KIND=sp) end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( a( k, k ),KIND=sp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakkrowmax ) then rowmax = stemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=sp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=sp) )=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / real( a( k, k ),KIND=sp) call stdlib${ii}$_cher( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_csscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=sp) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_cher( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( ( max( absakk, colmax )==zero ) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=dp) else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_izamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = cabs1( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=dp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=dp) )1_${ik}$ )call stdlib${ii}$_zswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = p + 1, k - 1 t = conjg( a( j, k ) ) a( j, k ) = conjg( a( p, j ) ) a( p, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( p, k ) = conjg( a( p, k ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( k, k ),KIND=dp) a( k, k ) = real( a( p, p ),KIND=dp) a( p, p ) = r1 end if ! for both 1x1 and 2x2 pivots, interchange rows and ! columns kk and kp in the leading submatrix a(1:k,1:k) if( kp/=kk ) then ! (1) swap columnar parts if( kp>1_${ik}$ )call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = kp + 1, kk - 1 t = conjg( a( j, kk ) ) a( j, kk ) = conjg( a( kp, j ) ) a( kp, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( kp, kk ) = conjg( a( kp, kk ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( kk, kk ),KIND=dp) a( kk, kk ) = real( a( kp, kp ),KIND=dp) a( kp, kp ) = r1 if( kstep==2_${ik}$ ) then ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=dp) ! (5) swap row elements t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if else ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=dp) if( kstep==2_${ik}$ )a( k-1, k-1 ) = real( a( k-1, k-1 ),KIND=dp) end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u if( k>1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( real( a( k, k ),KIND=dp) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / real( a( k, k ),KIND=dp) call stdlib${ii}$_zher( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_zdscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=dp) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_zher( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then ! d = |a12| d = stdlib${ii}$_dlapy2( real( a( k-1, k ),KIND=dp),aimag( a( k-1, k ) ) ) d11 = real( a( k, k ) / d,KIND=dp) d22 = real( a( k-1, k-1 ) / d,KIND=dp) d12 = a( k-1, k ) / d tt = one / ( d11*d22-one ) do j = k - 2, 1, -1 ! compute d21 * ( w(k)w(k+1) ) * inv(d(k)) for row j wkm1 = tt*( d11*a( j, k-1 )-conjg( d12 )*a( j, k ) ) wk = tt*( d22*a( j, k )-d12*a( j, k-1 ) ) ! perform a rank-2 update of a(1:k-2,1:k-2) do i = j, 1, -1 a( i, j ) = a( i, j ) -( a( i, k ) / d )*conjg( wk ) -( a( i, k-1 ) & / d )*conjg( wkm1 ) end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d a( j, k-1 ) = wkm1 / d ! (*) make sure that diagonal element of pivot is real a( j, j ) = cmplx( real( a( j, j ),KIND=dp), zero,KIND=dp) end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( a( k, k ),KIND=dp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=dp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=dp) )=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / real( a( k, k ),KIND=dp) call stdlib${ii}$_zher( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_zdscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=dp) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_zher( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( ( max( absakk, colmax )==zero ) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=${ck}$) else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_i${ci}$amax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = cabs1( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=${ck}$) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=${ck}$) )1_${ik}$ )call stdlib${ii}$_${ci}$swap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = p + 1, k - 1 t = conjg( a( j, k ) ) a( j, k ) = conjg( a( p, j ) ) a( p, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( p, k ) = conjg( a( p, k ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( k, k ),KIND=${ck}$) a( k, k ) = real( a( p, p ),KIND=${ck}$) a( p, p ) = r1 end if ! for both 1x1 and 2x2 pivots, interchange rows and ! columns kk and kp in the leading submatrix a(1:k,1:k) if( kp/=kk ) then ! (1) swap columnar parts if( kp>1_${ik}$ )call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = kp + 1, kk - 1 t = conjg( a( j, kk ) ) a( j, kk ) = conjg( a( kp, j ) ) a( kp, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( kp, kk ) = conjg( a( kp, kk ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( kk, kk ),KIND=${ck}$) a( kk, kk ) = real( a( kp, kp ),KIND=${ck}$) a( kp, kp ) = r1 if( kstep==2_${ik}$ ) then ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=${ck}$) ! (5) swap row elements t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if else ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=${ck}$) if( kstep==2_${ik}$ )a( k-1, k-1 ) = real( a( k-1, k-1 ),KIND=${ck}$) end if ! update the leading submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k now holds ! w(k) = u(k)*d(k) ! where u(k) is the k-th column of u if( k>1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( real( a( k, k ),KIND=${ck}$) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / real( a( k, k ),KIND=${ck}$) call stdlib${ii}$_${ci}$her( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_${ci}$dscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=${ck}$) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ci}$her( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then ! d = |a12| d = stdlib${ii}$_${c2ri(ci)}$lapy2( real( a( k-1, k ),KIND=${ck}$),aimag( a( k-1, k ) ) ) d11 = real( a( k, k ) / d,KIND=${ck}$) d22 = real( a( k-1, k-1 ) / d,KIND=${ck}$) d12 = a( k-1, k ) / d tt = one / ( d11*d22-one ) do j = k - 2, 1, -1 ! compute d21 * ( w(k)w(k+1) ) * inv(d(k)) for row j wkm1 = tt*( d11*a( j, k-1 )-conjg( d12 )*a( j, k ) ) wk = tt*( d22*a( j, k )-d12*a( j, k-1 ) ) ! perform a rank-2 update of a(1:k-2,1:k-2) do i = j, 1, -1 a( i, j ) = a( i, j ) -( a( i, k ) / d )*conjg( wk ) -( a( i, k-1 ) & / d )*conjg( wkm1 ) end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d a( j, k-1 ) = wkm1 / d ! (*) make sure that diagonal element of pivot is real a( j, j ) = cmplx( real( a( j, j ),KIND=${ck}$), zero,KIND=${ck}$) end do end if end if end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 else ! factorize a as l*d*l**h using the lower triangle of a ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 70 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( a( k, k ),KIND=${ck}$) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=${ck}$) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=${ck}$) )=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / real( a( k, k ),KIND=${ck}$) call stdlib${ii}$_${ci}$her( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_${ci}$dscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=${ck}$) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ci}$her( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_cgeru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. s = real( cone,KIND=sp) / real( a( k, k ),KIND=sp) call stdlib${ii}$_csscal( nrhs, s, b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k), then k-1 and -ipiv(k-1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k-1) if( kp/=k-1 )call stdlib${ii}$_cswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_cgeru( k-2, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) call stdlib${ii}$_cgeru( k-2, nrhs, -cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / conjg( akm1k ) b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**h *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**h(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ ) then call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) end if ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**h(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k+1 )& , 1_${ik}$, cone, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k), then k+1 and -ipiv(k+1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k+1 ) if( kp/=k+1 )call stdlib${ii}$_cswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**h. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**h(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_zgeru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. s = real( cone,KIND=dp) / real( a( k, k ),KIND=dp) call stdlib${ii}$_zdscal( nrhs, s, b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k), then k-1 and -ipiv(k-1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k-1) if( kp/=k-1 )call stdlib${ii}$_zswap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_zgeru( k-2, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) call stdlib${ii}$_zgeru( k-2, nrhs, -cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / conjg( akm1k ) b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**h *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**h(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ ) then call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) end if ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**h(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k+1 )& , 1_${ik}$, cone, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k), then k+1 and -ipiv(k+1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k+1 ) if( kp/=k+1 )call stdlib${ii}$_zswap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**h. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**h(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in column k of a. call stdlib${ii}$_${ci}$geru( k-1, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) ! multiply by the inverse of the diagonal block. s = real( cone,KIND=${ck}$) / real( a( k, k ),KIND=${ck}$) call stdlib${ii}$_${ci}$dscal( nrhs, s, b( k, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ else ! 2 x 2 diagonal block ! interchange rows k and -ipiv(k), then k-1 and -ipiv(k-1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k-1) if( kp/=k-1 )call stdlib${ii}$_${ci}$swap( nrhs, b( k-1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(u(k)), where u(k) is the transformation ! stored in columns k-1 and k of a. call stdlib${ii}$_${ci}$geru( k-2, nrhs, -cone, a( 1_${ik}$, k ), 1_${ik}$, b( k, 1_${ik}$ ), ldb,b( 1_${ik}$, 1_${ik}$ ), ldb & ) call stdlib${ii}$_${ci}$geru( k-2, nrhs, -cone, a( 1_${ik}$, k-1 ), 1_${ik}$, b( k-1, 1_${ik}$ ),ldb, b( 1_${ik}$, 1_${ik}$ ), & ldb ) ! multiply by the inverse of the diagonal block. akm1k = a( k-1, k ) akm1 = a( k-1, k-1 ) / akm1k ak = a( k, k ) / conjg( akm1k ) denom = akm1*ak - cone do j = 1, nrhs bkm1 = b( k-1, j ) / akm1k bk = b( k, j ) / conjg( akm1k ) b( k-1, j ) = ( ak*bkm1-bk ) / denom b( k, j ) = ( akm1*bk-bkm1 ) / denom end do k = k - 2_${ik}$ end if go to 10 30 continue ! next solve u**h *x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 40 continue ! if k > n, exit from loop. if( k>n )go to 50 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(u**h(k)), where u(k) is the transformation ! stored in column k of a. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) end if ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ else ! 2 x 2 diagonal block ! multiply by inv(u**h(k+1)), where u(k+1) is the transformation ! stored in columns k and k+1 of a. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k ), & 1_${ik}$, cone, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', k-1, nrhs, -cone, b,ldb, a( 1_${ik}$, k+1 )& , 1_${ik}$, cone, b( k+1, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( k+1, 1_${ik}$ ), ldb ) end if ! interchange rows k and -ipiv(k), then k+1 and -ipiv(k+1) kp = -ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) kp = -ipiv( k+1 ) if( kp/=k+1 )call stdlib${ii}$_${ci}$swap( nrhs, b( k+1, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 2_${ik}$ end if go to 40 50 continue else ! solve a*x = b, where a = l*d*l**h. ! first solve l*d*x = b, overwriting b with x. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 60 continue ! if k > n, exit from loop. if( k>n )go to 80 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! interchange rows k and ipiv(k). kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) ! multiply by inv(l(k)), where l(k) is the transformation ! stored in column k of a. if( k0_${ik}$ ) then ! 1 x 1 diagonal block ! multiply by inv(l**h(k)), where l(k) is the transformation ! stored in column k of a. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 70 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=sp) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_chemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_cdotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=sp) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = real( a( k, k ),KIND=sp) / t akp1 = real( a( k+1, k+1 ),KIND=sp) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_chemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_cdotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=sp) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_cdotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_chemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -real( stdlib${ii}$_cdotc( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ),& 1_${ik}$ ),KIND=sp) end if kstep = 2_${ik}$ end if if( kstep==1_${ik}$ ) then ! interchange rows and columns k and ipiv(k) in the leading ! submatrix a(1:k,1:k) kp = ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if else ! interchange rows and columns k and k+1 with -ipiv(k) and ! -ipiv(k+1) in the leading submatrix a(k+1:n,k+1:n) ! (1) interchange rows and columns k and -ipiv(k) kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if ! (2) interchange rows and columns k+1 and -ipiv(k+1) k = k + 1_${ik}$ kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if end if k = k + 1_${ik}$ go to 30 70 continue else ! compute inv(a) from the factorization a = l*d*l**h. ! k is the main loop index, decreasing from n to 1 in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 80 continue ! if k < 1, exit from loop. if( k<1 )go to 120 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=sp) ! compute column k of the inverse. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 70 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=dp) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zhemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_zdotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=dp) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = real( a( k, k ),KIND=dp) / t akp1 = real( a( k+1, k+1 ),KIND=dp) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zhemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_zdotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=dp) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_zdotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_zhemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -real( stdlib${ii}$_zdotc( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ),& 1_${ik}$ ),KIND=dp) end if kstep = 2_${ik}$ end if if( kstep==1_${ik}$ ) then ! interchange rows and columns k and ipiv(k) in the leading ! submatrix a(1:k,1:k) kp = ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if else ! interchange rows and columns k and k+1 with -ipiv(k) and ! -ipiv(k+1) in the leading submatrix a(k+1:n,k+1:n) ! (1) interchange rows and columns k and -ipiv(k) kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if ! (2) interchange rows and columns k+1 and -ipiv(k+1) k = k + 1_${ik}$ kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if end if k = k + 1_${ik}$ go to 30 70 continue else ! compute inv(a) from the factorization a = l*d*l**h. ! k is the main loop index, decreasing from n to 1 in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 80 continue ! if k < 1, exit from loop. if( k<1 )go to 120 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=dp) ! compute column k of the inverse. if( k0 .and. a( info, info )==czero )return end do else ! lower triangular storage: examine d from top to bottom. do info = 1, n if( ipiv( info )>0 .and. a( info, info )==czero )return end do end if info = 0_${ik}$ if( upper ) then ! compute inv(a) from the factorization a = u*d*u**h. ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = 1_${ik}$ 30 continue ! if k > n, exit from loop. if( k>n )go to 70 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=${ck}$) ! compute column k of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$hemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_${ci}$dotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=${ck}$) end if kstep = 1_${ik}$ else ! 2 x 2 diagonal block ! invert the diagonal block. t = abs( a( k, k+1 ) ) ak = real( a( k, k ),KIND=${ck}$) / t akp1 = real( a( k+1, k+1 ),KIND=${ck}$) / t akkp1 = a( k, k+1 ) / t d = t*( ak*akp1-one ) a( k, k ) = akp1 / d a( k+1, k+1 ) = ak / d a( k, k+1 ) = -akkp1 / d ! compute columns k and k+1 of the inverse. if( k>1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$hemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k ), 1_${ik}$ ) a( k, k ) = a( k, k ) - real( stdlib${ii}$_${ci}$dotc( k-1, work, 1_${ik}$, a( 1_${ik}$,k ), 1_${ik}$ ),& KIND=${ck}$) a( k, k+1 ) = a( k, k+1 ) -stdlib${ii}$_${ci}$dotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, k+1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k+1 ), 1_${ik}$, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$hemv( uplo, k-1, -cone, a, lda, work, 1_${ik}$, czero,a( 1_${ik}$, k+1 ), 1_${ik}$ ) a( k+1, k+1 ) = a( k+1, k+1 ) -real( stdlib${ii}$_${ci}$dotc( k-1, work, 1_${ik}$, a( 1_${ik}$, k+1 ),& 1_${ik}$ ),KIND=${ck}$) end if kstep = 2_${ik}$ end if if( kstep==1_${ik}$ ) then ! interchange rows and columns k and ipiv(k) in the leading ! submatrix a(1:k,1:k) kp = ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if else ! interchange rows and columns k and k+1 with -ipiv(k) and ! -ipiv(k+1) in the leading submatrix a(k+1:n,k+1:n) ! (1) interchange rows and columns k and -ipiv(k) kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp temp = a( k, k+1 ) a( k, k+1 ) = a( kp, k+1 ) a( kp, k+1 ) = temp end if ! (2) interchange rows and columns k+1 and -ipiv(k+1) k = k + 1_${ik}$ kp = -ipiv( k ) if( kp/=k ) then if( kp>1_${ik}$ )call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) do j = kp + 1, k - 1 temp = conjg( a( j, k ) ) a( j, k ) = conjg( a( kp, j ) ) a( kp, j ) = temp end do a( kp, k ) = conjg( a( kp, k ) ) temp = a( k, k ) a( k, k ) = a( kp, kp ) a( kp, kp ) = temp end if end if k = k + 1_${ik}$ go to 30 70 continue else ! compute inv(a) from the factorization a = l*d*l**h. ! k is the main loop index, decreasing from n to 1 in steps of ! 1 or 2, depending on the size of the diagonal blocks. k = n 80 continue ! if k < 1, exit from loop. if( k<1 )go to 120 if( ipiv( k )>0_${ik}$ ) then ! 1 x 1 diagonal block ! invert the diagonal block. a( k, k ) = one / real( a( k, k ),KIND=${ck}$) ! compute column k of the inverse. if( k1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_clahef_rk( uplo, k, nb, kb, a, lda, e,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_chetf2_rk( uplo, k, a, lda, e, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k-kb+1:k and apply row permutations to the ! last k+1 colunms k+1:n after that block ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k n, exit from loop if( k>n )go to 35 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_clahef_rk( uplo, n-k+1, nb, kb, a( k, k ), lda, e( k ),ipiv( k ), & work, ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_chetf2_rk( uplo, n-k+1, a( k, k ), lda, e( k ),ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do i = k, k + kb - 1 if( ipiv( i )>0_${ik}$ ) then ipiv( i ) = ipiv( i ) + k - 1_${ik}$ else ipiv( i ) = ipiv( i ) - k + 1_${ik}$ end if end do ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k:k+kb-1 and apply row permutations to the ! first k-1 colunms 1:k-1 before that block ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k>1_${ik}$ ) then do i = k, ( k + kb - 1 ), 1 ip = abs( ipiv( i ) ) if( ip/=i ) then call stdlib${ii}$_cswap( k-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end do end if ! increase k and return to the start of the main loop k = k + kb go to 20 ! this label is the exit from main loop over k increasing ! from 1 to n in steps of kb 35 continue ! end lower end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_chetrf_rk pure module subroutine stdlib${ii}$_zhetrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) !! ZHETRF_RK computes the factorization of a complex Hermitian matrix A !! using the bounded Bunch-Kaufman (rook) diagonal pivoting method: !! A = P*U*D*(U**H)*(P**T) or A = P*L*D*(L**H)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**H (or L**H) is the conjugate of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is Hermitian and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. !! For more information see Further Details section. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: e(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: i, iinfo, ip, iws, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_zlahef_rk( uplo, k, nb, kb, a, lda, e,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_zhetf2_rk( uplo, k, a, lda, e, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k-kb+1:k and apply row permutations to the ! last k+1 colunms k+1:n after that block ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k n, exit from loop if( k>n )go to 35 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_zlahef_rk( uplo, n-k+1, nb, kb, a( k, k ), lda, e( k ),ipiv( k ), & work, ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_zhetf2_rk( uplo, n-k+1, a( k, k ), lda, e( k ),ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do i = k, k + kb - 1 if( ipiv( i )>0_${ik}$ ) then ipiv( i ) = ipiv( i ) + k - 1_${ik}$ else ipiv( i ) = ipiv( i ) - k + 1_${ik}$ end if end do ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k:k+kb-1 and apply row permutations to the ! first k-1 colunms 1:k-1 before that block ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k>1_${ik}$ ) then do i = k, ( k + kb - 1 ), 1 ip = abs( ipiv( i ) ) if( ip/=i ) then call stdlib${ii}$_zswap( k-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end do end if ! increase k and return to the start of the main loop k = k + kb go to 20 ! this label is the exit from main loop over k increasing ! from 1 to n in steps of kb 35 continue ! end lower end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zhetrf_rk #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hetrf_rk( uplo, n, a, lda, e, ipiv, work, lwork,info ) !! ZHETRF_RK: computes the factorization of a complex Hermitian matrix A !! using the bounded Bunch-Kaufman (rook) diagonal pivoting method: !! A = P*U*D*(U**H)*(P**T) or A = P*L*D*(L**H)*(P**T), !! where U (or L) is unit upper (or lower) triangular matrix, !! U**H (or L**H) is the conjugate of U (or L), P is a permutation !! matrix, P**T is the transpose of P, and D is Hermitian and block !! diagonal with 1-by-1 and 2-by-2 diagonal blocks. !! This is the blocked version of the algorithm, calling Level 3 BLAS. !! For more information see Further Details section. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: e(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: i, iinfo, ip, iws, k, kb, ldwork, lwkopt, nb, nbmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda1_${ik}$ .and. nbnb ) then ! factorize columns k-kb+1:k of a and use blocked code to ! update columns 1:k-kb call stdlib${ii}$_${ci}$lahef_rk( uplo, k, nb, kb, a, lda, e,ipiv, work, ldwork, iinfo ) else ! use unblocked code to factorize columns 1:k of a call stdlib${ii}$_${ci}$hetf2_rk( uplo, k, a, lda, e, ipiv, iinfo ) kb = k end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! no need to adjust ipiv ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k-kb+1:k and apply row permutations to the ! last k+1 colunms k+1:n after that block ! (we can do the simple loop over ipiv with decrement -1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k n, exit from loop if( k>n )go to 35 if( k<=n-nb ) then ! factorize columns k:k+kb-1 of a and use blocked code to ! update columns k+kb:n call stdlib${ii}$_${ci}$lahef_rk( uplo, n-k+1, nb, kb, a( k, k ), lda, e( k ),ipiv( k ), & work, ldwork, iinfo ) else ! use unblocked code to factorize columns k:n of a call stdlib${ii}$_${ci}$hetf2_rk( uplo, n-k+1, a( k, k ), lda, e( k ),ipiv( k ), iinfo ) kb = n - k + 1_${ik}$ end if ! set info on the first occurrence of a zero pivot if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + k - 1_${ik}$ ! adjust ipiv do i = k, k + kb - 1 if( ipiv( i )>0_${ik}$ ) then ipiv( i ) = ipiv( i ) + k - 1_${ik}$ else ipiv( i ) = ipiv( i ) - k + 1_${ik}$ end if end do ! apply permutations to the leading panel 1:k-1 ! read ipiv from the last block factored, i.e. ! indices k:k+kb-1 and apply row permutations to the ! first k-1 colunms 1:k-1 before that block ! (we can do the simple loop over ipiv with increment 1, ! since the abs value of ipiv( i ) represents the row index ! of the interchange with row i in both 1x1 and 2x2 pivot cases) if( k>1_${ik}$ ) then do i = k, ( k + kb - 1 ), 1 ip = abs( ipiv( i ) ) if( ip/=i ) then call stdlib${ii}$_${ci}$swap( k-1, a( i, 1_${ik}$ ), lda,a( ip, 1_${ik}$ ), lda ) end if end do end if ! increase k and return to the start of the main loop k = k + kb go to 20 ! this label is the exit from main loop over k increasing ! from 1 to n in steps of kb 35 continue ! end lower end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$hetrf_rk #:endif #:endfor pure module subroutine stdlib${ii}$_clahef_rk( uplo, n, nb, kb, a, lda, e, ipiv, w, ldw,info ) !! CLAHEF_RK computes a partial factorization of a complex Hermitian !! matrix A using the bounded Bunch-Kaufman (rook) diagonal !! pivoting method. The partial factorization has the form: !! A = ( I U12 ) ( A11 0 ) ( I 0 ) if UPLO = 'U', or: !! ( 0 U22 ) ( 0 D ) ( U12**H U22**H ) !! A = ( L11 0 ) ( D 0 ) ( L11**H L21**H ) if UPLO = 'L', !! ( L21 I ) ( 0 A22 ) ( 0 I ) !! where the order of D is at most NB. The actual order is returned in !! the argument KB, and is either NB or NB-1, or N if N <= NB. !! CLAHEF_RK is an auxiliary routine called by CHETRF_RK. It uses !! blocked code (calling Level 3 BLAS) to update the submatrix !! A11 (if UPLO = 'U') or A22 (if UPLO = 'L'). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, kb integer(${ik}$), intent(in) :: lda, ldw, n, nb ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: w(ldw,*), e(*) ! ===================================================================== ! Parameters real(sp), parameter :: sevten = 17.0e+0_sp ! Local Scalars logical(lk) :: done integer(${ik}$) :: imax, itemp, ii, j, jb, jj, jmax, k, kk, kkw, kp, kstep, kw, p real(sp) :: absakk, alpha, colmax, stemp, r1, rowmax, t, sfmin complex(sp) :: d11, d21, d22, z ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( z ) = abs( real( z,KIND=sp) ) + abs( aimag( z ) ) ! Executable Statements info = 0_${ik}$ ! initialize alpha for use in choosing pivot block size. alpha = ( one+sqrt( sevten ) ) / eight ! compute machine safe minimum sfmin = stdlib${ii}$_slamch( 'S' ) if( stdlib_lsame( uplo, 'U' ) ) then ! factorize the trailing columns of a using the upper triangle ! of a and working backwards, and compute the matrix w = u12*d ! for use in updating a11 (note that conjg(w) is actually stored) ! initialize the first entry of array e, where superdiagonal ! elements of d are stored e( 1_${ik}$ ) = czero ! k is the main loop index, decreasing from n in steps of 1 or 2 k = n 10 continue ! kw is the column of w which corresponds to column k of a kw = nb + k - n ! exit from loop if( ( k<=n-nb+1 .and. nb1_${ik}$ )call stdlib${ii}$_ccopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) w( k, kw ) = real( a( k, k ),KIND=sp) if( k1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( w( k, kw ),KIND=sp) if( k>1_${ik}$ )call stdlib${ii}$_ccopy( k-1, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_ccopy( imax-1, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ),1_${ik}$ ) w( imax, kw-1 ) = real( a( imax, imax ),KIND=sp) call stdlib${ii}$_ccopy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_clacgv( k-imax, w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then itemp = stdlib${ii}$_icamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) stemp = cabs1( w( itemp, kw-1 ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=sp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,kw-1 ),KIND=sp) )1_${ik}$ )call stdlib${ii}$_ccopy( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! interchange rows k and p in the last k+1 to n columns of a ! (columns k and k-1 of a for 2-by-2 pivot will be ! later overwritten). interchange rows k and p ! in last kkw to nb columns of w. if( k1_${ik}$ )call stdlib${ii}$_ccopy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k1_${ik}$ ) then ! (note: no need to check if a(k,k) is not zero, ! since that was ensured earlier in pivot search: ! case a(k,k) = 0 falls into 2x2 pivot case(3)) ! handle division by a small number t = real( a( k, k ),KIND=sp) if( abs( t )>=sfmin ) then r1 = one / t call stdlib${ii}$_csscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else do ii = 1, k-1 a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(kw) call stdlib${ii}$_clacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now hold ! ( w(kw-1) w(kw) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! (1) store u(1:k-2,k-1) and u(1:k-2,k) and 2-by-2 ! block d(k-1:k,k-1:k) in columns k-1 and k of a. ! (note: 2-by-2 diagonal block u(k-1:k,k-1:k) is a unit ! block and not stored) ! a(k-1:k,k-1:k) := d(k-1:k,k-1:k) = w(k-1:k,kw-1:kw) ! a(1:k-2,k-1:k) := u(1:k-2,k:k-1:k) = ! = w(1:k-2,kw-1:kw) * ( d(k-1:k,k-1:k)**(-1) ) if( k>2_${ik}$ ) then ! factor out the columns of the inverse of 2-by-2 pivot ! block d, so that each column contains 1, to reduce the ! number of flops when we multiply panel ! ( w(kw-1) w(kw) ) by this inverse, i.e. by d**(-1). ! d**(-1) = ( d11 cj(d21) )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-|d21|**2) * ( ( d22) (-cj(d21) ) ) = ! ( (-d21) ( d11 ) ) ! = 1/(|d21|**2) * 1/((d11/cj(d21))*(d22/d21)-1) * ! * ( d21*( d22/d21 ) conj(d21)*( - 1 ) ) = ! ( ( -1 ) ( d11/conj(d21) ) ) ! = 1/(|d21|**2) * 1/(d22*d11-1) * ! * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = (1/|d21|**2) * t * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( (t/conj(d21))*( d11 ) (t/d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! handle division by a small number. (note: order of ! operations is important) ! = ( t*(( d11 )/conj(d21)) t*(( -1 )/d21 ) ) ! ( (( -1 ) ) (( d22 ) ) ), ! where d11 = d22/d21, ! d22 = d11/conj(d21), ! d21 = d21, ! t = 1/(d22*d11-1). ! (note: no need to check for division by zero, ! since that was ensured earlier in pivot search: ! (a) d21 != 0 in 2x2 pivot case(4), ! since |d21| should be larger than |d11| and |d22|; ! (b) (d22*d11 - 1) != 0, since from (a), ! both |d11| < 1, |d22| < 1, hence |d22*d11| << 1.) d21 = w( k-1, kw ) d11 = w( k, kw ) / conjg( d21 ) d22 = w( k-1, kw-1 ) / d21 t = one / ( real( d11*d22,KIND=sp)-one ) ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = t*( ( d11*w( j, kw-1 )-w( j, kw ) ) /d21 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /conjg( d21 ) ) end do end if ! copy diagonal elements of d(k) to a, ! copy superdiagonal element of d(k) to e(k) and ! zero out superdiagonal entry of a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = czero a( k, k ) = w( k, kw ) e( k ) = w( k-1, kw ) e( k-1 ) = czero ! (2) conjugate columns w(kw) and w(kw-1) call stdlib${ii}$_clacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) call stdlib${ii}$_clacgv( k-2, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**h = a11 - u12*w**h ! computing blocks of nb columns at a time (note that conjg(w) is ! actually stored) do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 a( jj, jj ) = real( a( jj, jj ),KIND=sp) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) a( jj, jj ) = real( a( jj, jj ),KIND=sp) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 (note that conjg(w) is actually stored) ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update column k of w w( k, k ) = real( a( k, k ),KIND=sp) if( k1_${ik}$ ) then call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, 1_${ik}$ ), & ldw, cone, w( k, k ), 1_${ik}$ ) w( k, k ) = real( w( k, k ),KIND=sp) end if ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( w( k, k ),KIND=sp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), lda, w( & imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) w( imax, k+1 ) = real( w( imax, k+1 ),KIND=sp) end if ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_icamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = stemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,k+1 ),KIND=sp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,k+1 ),KIND=sp) )1_${ik}$ )call stdlib${ii}$_cswap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) call stdlib${ii}$_cswap( kk, w( k, 1_${ik}$ ), ldw, w( p, 1_${ik}$ ), ldw ) end if ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=sp) call stdlib${ii}$_ccopy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) call stdlib${ii}$_clacgv( kp-kk-1, a( kp, kk+1 ), lda ) if( kp1_${ik}$ )call stdlib${ii}$_cswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_cswap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! (1) store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) ! (note: no need to use for hermitian matrix ! a( k, k ) = real( w( k, k),KIND=sp) to separately copy diagonal ! element d(k,k) from w (potentially saves only one load)) call stdlib${ii}$_ccopy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=sfmin ) then r1 = one / t call stdlib${ii}$_csscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else do ii = k + 1, n a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(k) call stdlib${ii}$_clacgv( n-k, w( k+1, k ), 1_${ik}$ ) ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! (1) store l(k+2:n,k) and l(k+2:n,k+1) and 2-by-2 ! block d(k:k+1,k:k+1) in columns k and k+1 of a. ! note: 2-by-2 diagonal block l(k:k+1,k:k+1) is a unit ! block and not stored. ! a(k:k+1,k:k+1) := d(k:k+1,k:k+1) = w(k:k+1,k:k+1) ! a(k+2:n,k:k+1) := l(k+2:n,k:k+1) = ! = w(k+2:n,k:k+1) * ( d(k:k+1,k:k+1)**(-1) ) if( k1_${ik}$ )call stdlib${ii}$_zcopy( k-1, a( 1_${ik}$, k ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) w( k, kw ) = real( a( k, k ),KIND=dp) if( k1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( w( k, kw ),KIND=dp) if( k>1_${ik}$ )call stdlib${ii}$_zcopy( k-1, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_zcopy( imax-1, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ),1_${ik}$ ) w( imax, kw-1 ) = real( a( imax, imax ),KIND=dp) call stdlib${ii}$_zcopy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( k-imax, w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then itemp = stdlib${ii}$_izamax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = cabs1( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=dp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,kw-1 ),KIND=dp) )1_${ik}$ )call stdlib${ii}$_zcopy( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! interchange rows k and p in the last k+1 to n columns of a ! (columns k and k-1 of a for 2-by-2 pivot will be ! later overwritten). interchange rows k and p ! in last kkw to nb columns of w. if( k1_${ik}$ )call stdlib${ii}$_zcopy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k1_${ik}$ ) then ! (note: no need to check if a(k,k) is not zero, ! since that was ensured earlier in pivot search: ! case a(k,k) = 0 falls into 2x2 pivot case(3)) ! handle division by a small number t = real( a( k, k ),KIND=dp) if( abs( t )>=sfmin ) then r1 = one / t call stdlib${ii}$_zdscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else do ii = 1, k-1 a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(kw) call stdlib${ii}$_zlacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now hold ! ( w(kw-1) w(kw) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! (1) store u(1:k-2,k-1) and u(1:k-2,k) and 2-by-2 ! block d(k-1:k,k-1:k) in columns k-1 and k of a. ! (note: 2-by-2 diagonal block u(k-1:k,k-1:k) is a unit ! block and not stored) ! a(k-1:k,k-1:k) := d(k-1:k,k-1:k) = w(k-1:k,kw-1:kw) ! a(1:k-2,k-1:k) := u(1:k-2,k:k-1:k) = ! = w(1:k-2,kw-1:kw) * ( d(k-1:k,k-1:k)**(-1) ) if( k>2_${ik}$ ) then ! factor out the columns of the inverse of 2-by-2 pivot ! block d, so that each column contains 1, to reduce the ! number of flops when we multiply panel ! ( w(kw-1) w(kw) ) by this inverse, i.e. by d**(-1). ! d**(-1) = ( d11 cj(d21) )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-|d21|**2) * ( ( d22) (-cj(d21) ) ) = ! ( (-d21) ( d11 ) ) ! = 1/(|d21|**2) * 1/((d11/cj(d21))*(d22/d21)-1) * ! * ( d21*( d22/d21 ) conj(d21)*( - 1 ) ) = ! ( ( -1 ) ( d11/conj(d21) ) ) ! = 1/(|d21|**2) * 1/(d22*d11-1) * ! * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = (1/|d21|**2) * t * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( (t/conj(d21))*( d11 ) (t/d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! handle division by a small number. (note: order of ! operations is important) ! = ( t*(( d11 )/conj(d21)) t*(( -1 )/d21 ) ) ! ( (( -1 ) ) (( d22 ) ) ), ! where d11 = d22/d21, ! d22 = d11/conj(d21), ! d21 = d21, ! t = 1/(d22*d11-1). ! (note: no need to check for division by zero, ! since that was ensured earlier in pivot search: ! (a) d21 != 0 in 2x2 pivot case(4), ! since |d21| should be larger than |d11| and |d22|; ! (b) (d22*d11 - 1) != 0, since from (a), ! both |d11| < 1, |d22| < 1, hence |d22*d11| << 1.) d21 = w( k-1, kw ) d11 = w( k, kw ) / conjg( d21 ) d22 = w( k-1, kw-1 ) / d21 t = one / ( real( d11*d22,KIND=dp)-one ) ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = t*( ( d11*w( j, kw-1 )-w( j, kw ) ) /d21 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /conjg( d21 ) ) end do end if ! copy diagonal elements of d(k) to a, ! copy superdiagonal element of d(k) to e(k) and ! zero out superdiagonal entry of a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = czero a( k, k ) = w( k, kw ) e( k ) = w( k-1, kw ) e( k-1 ) = czero ! (2) conjugate columns w(kw) and w(kw-1) call stdlib${ii}$_zlacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( k-2, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**h = a11 - u12*w**h ! computing blocks of nb columns at a time (note that conjg(w) is ! actually stored) do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 a( jj, jj ) = real( a( jj, jj ),KIND=dp) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) a( jj, jj ) = real( a( jj, jj ),KIND=dp) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 (note that conjg(w) is actually stored) ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update column k of w w( k, k ) = real( a( k, k ),KIND=dp) if( k1_${ik}$ ) then call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, 1_${ik}$ ), & ldw, cone, w( k, k ), 1_${ik}$ ) w( k, k ) = real( w( k, k ),KIND=dp) end if ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( w( k, k ),KIND=dp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), lda, w( & imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) w( imax, k+1 ) = real( w( imax, k+1 ),KIND=dp) end if ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_izamax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,k+1 ),KIND=dp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,k+1 ),KIND=dp) )1_${ik}$ )call stdlib${ii}$_zswap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) call stdlib${ii}$_zswap( kk, w( k, 1_${ik}$ ), ldw, w( p, 1_${ik}$ ), ldw ) end if ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=dp) call stdlib${ii}$_zcopy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) call stdlib${ii}$_zlacgv( kp-kk-1, a( kp, kk+1 ), lda ) if( kp1_${ik}$ )call stdlib${ii}$_zswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_zswap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! (1) store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) ! (note: no need to use for hermitian matrix ! a( k, k ) = real( w( k, k),KIND=dp) to separately copy diagonal ! element d(k,k) from w (potentially saves only one load)) call stdlib${ii}$_zcopy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=sfmin ) then r1 = one / t call stdlib${ii}$_zdscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else do ii = k + 1, n a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(k) call stdlib${ii}$_zlacgv( n-k, w( k+1, k ), 1_${ik}$ ) ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! (1) store l(k+2:n,k) and l(k+2:n,k+1) and 2-by-2 ! block d(k:k+1,k:k+1) in columns k and k+1 of a. ! note: 2-by-2 diagonal block l(k:k+1,k:k+1) is a unit ! block and not stored. ! a(k:k+1,k:k+1) := d(k:k+1,k:k+1) = w(k:k+1,k:k+1) ! a(k+2:n,k:k+1) := l(k+2:n,k:k+1) = ! = w(k+2:n,k:k+1) * ( d(k:k+1,k:k+1)**(-1) ) if( k1_${ik}$ )call stdlib${ii}$_${ci}$copy( k-1, a( 1_${ik}$, k ), 1_${ik}$, w( 1_${ik}$, kw ), 1_${ik}$ ) w( k, kw ) = real( a( k, k ),KIND=${ck}$) if( k1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) colmax = cabs1( w( imax, kw ) ) else colmax = zero end if if( max( absakk, colmax )==zero ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( w( k, kw ),KIND=${ck}$) if( k>1_${ik}$ )call stdlib${ii}$_${ci}$copy( k-1, w( 1_${ik}$, kw ), 1_${ik}$, a( 1_${ik}$, k ), 1_${ik}$ ) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ )call stdlib${ii}$_${ci}$copy( imax-1, a( 1_${ik}$, imax ), 1_${ik}$, w( 1_${ik}$, kw-1 ),1_${ik}$ ) w( imax, kw-1 ) = real( a( imax, imax ),KIND=${ck}$) call stdlib${ii}$_${ci}$copy( k-imax, a( imax, imax+1 ), lda,w( imax+1, kw-1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( k-imax, w( imax+1, kw-1 ), 1_${ik}$ ) if( k1_${ik}$ ) then itemp = stdlib${ii}$_i${ci}$amax( imax-1, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) dtemp = cabs1( w( itemp, kw-1 ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=${ck}$) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,kw-1 ),KIND=${ck}$) )1_${ik}$ )call stdlib${ii}$_${ci}$copy( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! interchange rows k and p in the last k+1 to n columns of a ! (columns k and k-1 of a for 2-by-2 pivot will be ! later overwritten). interchange rows k and p ! in last kkw to nb columns of w. if( k1_${ik}$ )call stdlib${ii}$_${ci}$copy( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! interchange rows kk and kp in last k+1 to n columns of a ! (columns k (or k and k-1 for 2-by-2 pivot) of a will be ! later overwritten). interchange rows kk and kp ! in last kkw to nb columns of w. if( k1_${ik}$ ) then ! (note: no need to check if a(k,k) is not zero, ! since that was ensured earlier in pivot search: ! case a(k,k) = 0 falls into 2x2 pivot case(3)) ! handle division by a small number t = real( a( k, k ),KIND=${ck}$) if( abs( t )>=sfmin ) then r1 = one / t call stdlib${ii}$_${ci}$dscal( k-1, r1, a( 1_${ik}$, k ), 1_${ik}$ ) else do ii = 1, k-1 a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(kw) call stdlib${ii}$_${ci}$lacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns kw and kw-1 of w now hold ! ( w(kw-1) w(kw) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! (1) store u(1:k-2,k-1) and u(1:k-2,k) and 2-by-2 ! block d(k-1:k,k-1:k) in columns k-1 and k of a. ! (note: 2-by-2 diagonal block u(k-1:k,k-1:k) is a unit ! block and not stored) ! a(k-1:k,k-1:k) := d(k-1:k,k-1:k) = w(k-1:k,kw-1:kw) ! a(1:k-2,k-1:k) := u(1:k-2,k:k-1:k) = ! = w(1:k-2,kw-1:kw) * ( d(k-1:k,k-1:k)**(-1) ) if( k>2_${ik}$ ) then ! factor out the columns of the inverse of 2-by-2 pivot ! block d, so that each column contains 1, to reduce the ! number of flops when we multiply panel ! ( w(kw-1) w(kw) ) by this inverse, i.e. by d**(-1). ! d**(-1) = ( d11 cj(d21) )**(-1) = ! ( d21 d22 ) ! = 1/(d11*d22-|d21|**2) * ( ( d22) (-cj(d21) ) ) = ! ( (-d21) ( d11 ) ) ! = 1/(|d21|**2) * 1/((d11/cj(d21))*(d22/d21)-1) * ! * ( d21*( d22/d21 ) conj(d21)*( - 1 ) ) = ! ( ( -1 ) ( d11/conj(d21) ) ) ! = 1/(|d21|**2) * 1/(d22*d11-1) * ! * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = (1/|d21|**2) * t * ( d21*( d11 ) conj(d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! = ( (t/conj(d21))*( d11 ) (t/d21)*( -1 ) ) = ! ( ( -1 ) ( d22 ) ) ! handle division by a small number. (note: order of ! operations is important) ! = ( t*(( d11 )/conj(d21)) t*(( -1 )/d21 ) ) ! ( (( -1 ) ) (( d22 ) ) ), ! where d11 = d22/d21, ! d22 = d11/conj(d21), ! d21 = d21, ! t = 1/(d22*d11-1). ! (note: no need to check for division by zero, ! since that was ensured earlier in pivot search: ! (a) d21 != 0 in 2x2 pivot case(4), ! since |d21| should be larger than |d11| and |d22|; ! (b) (d22*d11 - 1) != 0, since from (a), ! both |d11| < 1, |d22| < 1, hence |d22*d11| << 1.) d21 = w( k-1, kw ) d11 = w( k, kw ) / conjg( d21 ) d22 = w( k-1, kw-1 ) / d21 t = one / ( real( d11*d22,KIND=${ck}$)-one ) ! update elements in columns a(k-1) and a(k) as ! dot products of rows of ( w(kw-1) w(kw) ) and columns ! of d**(-1) do j = 1, k - 2 a( j, k-1 ) = t*( ( d11*w( j, kw-1 )-w( j, kw ) ) /d21 ) a( j, k ) = t*( ( d22*w( j, kw )-w( j, kw-1 ) ) /conjg( d21 ) ) end do end if ! copy diagonal elements of d(k) to a, ! copy superdiagonal element of d(k) to e(k) and ! zero out superdiagonal entry of a a( k-1, k-1 ) = w( k-1, kw-1 ) a( k-1, k ) = czero a( k, k ) = w( k, kw ) e( k ) = w( k-1, kw ) e( k-1 ) = czero ! (2) conjugate columns w(kw) and w(kw-1) call stdlib${ii}$_${ci}$lacgv( k-1, w( 1_${ik}$, kw ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( k-2, w( 1_${ik}$, kw-1 ), 1_${ik}$ ) end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 30 continue ! update the upper triangle of a11 (= a(1:k,1:k)) as ! a11 := a11 - u12*d*u12**h = a11 - u12*w**h ! computing blocks of nb columns at a time (note that conjg(w) is ! actually stored) do j = ( ( k-1 ) / nb )*nb + 1, 1, -nb jb = min( nb, k-j+1 ) ! update the upper triangle of the diagonal block do jj = j, j + jb - 1 a( jj, jj ) = real( a( jj, jj ),KIND=${ck}$) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', jj-j+1, n-k, -cone,a( j, k+1 ), lda, w( jj,& kw+1 ), ldw, cone,a( j, jj ), 1_${ik}$ ) a( jj, jj ) = real( a( jj, jj ),KIND=${ck}$) end do ! update the rectangular superdiagonal block if( j>=2_${ik}$ )call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', j-1, jb, n-k,-cone, a( & 1_${ik}$, k+1 ), lda, w( j, kw+1 ), ldw,cone, a( 1_${ik}$, j ), lda ) end do ! set kb to the number of columns factorized kb = n - k else ! factorize the leading columns of a using the lower triangle ! of a and working forwards, and compute the matrix w = l21*d ! for use in updating a22 (note that conjg(w) is actually stored) ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 in steps of 1 or 2 k = 1_${ik}$ 70 continue ! exit from loop if( ( k>=nb .and. nbn )go to 90 kstep = 1_${ik}$ p = k ! copy column k of a to column k of w and update column k of w w( k, k ) = real( a( k, k ),KIND=${ck}$) if( k1_${ik}$ ) then call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -cone, a( k, 1_${ik}$ ),lda, w( k, 1_${ik}$ ), & ldw, cone, w( k, k ), 1_${ik}$ ) w( k, k ) = real( w( k, k ),KIND=${ck}$) end if ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( w( k, k ),KIND=${ck}$) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k+1, k-1, -cone,a( k, 1_${ik}$ ), lda, w( & imax, 1_${ik}$ ), ldw,cone, w( k, k+1 ), 1_${ik}$ ) w( imax, k+1 ) = real( w( imax, k+1 ),KIND=${ck}$) end if ! jmax is the column-index of the largest off-diagonal ! element in row imax, and rowmax is its absolute value. ! determine both rowmax and jmax. if( imax/=k ) then jmax = k - 1_${ik}$ + stdlib${ii}$_i${ci}$amax( imax-k, w( k, k+1 ), 1_${ik}$ ) rowmax = cabs1( w( jmax, k+1 ) ) else rowmax = zero end if if( imaxrowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,k+1 ),KIND=${ck}$) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( w( imax,k+1 ),KIND=${ck}$) )1_${ik}$ )call stdlib${ii}$_${ci}$swap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$swap( kk, w( k, 1_${ik}$ ), ldw, w( p, 1_${ik}$ ), ldw ) end if ! interchange rows and columns kp and kk. ! updated column kp is already stored in column kk of w. if( kp/=kk ) then ! copy non-updated column kk to column kp of submatrix a ! at step k. no need to copy element into column k ! (or k and k+1 for 2-by-2 pivot) of a, since these columns ! will be later overwritten. a( kp, kp ) = real( a( kk, kk ),KIND=${ck}$) call stdlib${ii}$_${ci}$copy( kp-kk-1, a( kk+1, kk ), 1_${ik}$, a( kp, kk+1 ),lda ) call stdlib${ii}$_${ci}$lacgv( kp-kk-1, a( kp, kk+1 ), lda ) if( kp1_${ik}$ )call stdlib${ii}$_${ci}$swap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$swap( kk, w( kk, 1_${ik}$ ), ldw, w( kp, 1_${ik}$ ), ldw ) end if if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of w now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l ! (1) store subdiag. elements of column l(k) ! and 1-by-1 block d(k) in column k of a. ! (note: diagonal element l(k,k) is a unit element ! and not stored) ! a(k,k) := d(k,k) = w(k,k) ! a(k+1:n,k) := l(k+1:n,k) = w(k+1:n,k)/d(k,k) ! (note: no need to use for hermitian matrix ! a( k, k ) = real( w( k, k),KIND=${ck}$) to separately copy diagonal ! element d(k,k) from w (potentially saves only one load)) call stdlib${ii}$_${ci}$copy( n-k+1, w( k, k ), 1_${ik}$, a( k, k ), 1_${ik}$ ) if( k=sfmin ) then r1 = one / t call stdlib${ii}$_${ci}$dscal( n-k, r1, a( k+1, k ), 1_${ik}$ ) else do ii = k + 1, n a( ii, k ) = a( ii, k ) / t end do end if ! (2) conjugate column w(k) call stdlib${ii}$_${ci}$lacgv( n-k, w( k+1, k ), 1_${ik}$ ) ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 of w now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! (1) store l(k+2:n,k) and l(k+2:n,k+1) and 2-by-2 ! block d(k:k+1,k:k+1) in columns k and k+1 of a. ! note: 2-by-2 diagonal block l(k:k+1,k:k+1) is a unit ! block and not stored. ! a(k:k+1,k:k+1) := d(k:k+1,k:k+1) = w(k:k+1,k:k+1) ! a(k+2:n,k:k+1) := l(k+2:n,k:k+1) = ! = w(k+2:n,k:k+1) * ( d(k:k+1,k:k+1)**(-1) ) if( k1_${ik}$ ) then imax = stdlib${ii}$_icamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( ( max( absakk, colmax )==zero ) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=sp) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_icamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) stemp = cabs1( a( itemp, imax ) ) if( stemp>rowmax ) then rowmax = stemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=sp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=sp) )1_${ik}$ )call stdlib${ii}$_cswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = p + 1, k - 1 t = conjg( a( j, k ) ) a( j, k ) = conjg( a( p, j ) ) a( p, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( p, k ) = conjg( a( p, k ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( k, k ),KIND=sp) a( k, k ) = real( a( p, p ),KIND=sp) a( p, p ) = r1 ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ )call stdlib${ii}$_cswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = kp + 1, kk - 1 t = conjg( a( j, kk ) ) a( j, kk ) = conjg( a( kp, j ) ) a( kp, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( kp, kk ) = conjg( a( kp, kk ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( kk, kk ),KIND=sp) a( kk, kk ) = real( a( kp, kp ),KIND=sp) a( kp, kp ) = r1 if( kstep==2_${ik}$ ) then ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=sp) ! (5) swap row elements t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( real( a( k, k ),KIND=sp) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / real( a( k, k ),KIND=sp) call stdlib${ii}$_cher( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_csscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=sp) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_cher( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then ! d = |a12| d = stdlib${ii}$_slapy2( real( a( k-1, k ),KIND=sp),aimag( a( k-1, k ) ) ) d11 = real( a( k, k ) / d,KIND=sp) d22 = real( a( k-1, k-1 ) / d,KIND=sp) d12 = a( k-1, k ) / d tt = one / ( d11*d22-one ) do j = k - 2, 1, -1 ! compute d21 * ( w(k)w(k+1) ) * inv(d(k)) for row j wkm1 = tt*( d11*a( j, k-1 )-conjg( d12 )*a( j, k ) ) wk = tt*( d22*a( j, k )-d12*a( j, k-1 ) ) ! perform a rank-2 update of a(1:k-2,1:k-2) do i = j, 1, -1 a( i, j ) = a( i, j ) -( a( i, k ) / d )*conjg( wk ) -( a( i, k-1 ) & / d )*conjg( wkm1 ) end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d a( j, k-1 ) = wkm1 / d ! (*) make sure that diagonal element of pivot is real a( j, j ) = cmplx( real( a( j, j ),KIND=sp), zero,KIND=sp) end do end if ! copy superdiagonal elements of d(k) to e(k) and ! zero out superdiagonal entry of a e( k ) = a( k-1, k ) e( k-1 ) = czero a( k-1, k ) = czero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 34 continue else ! factorize a as l*d*l**h using the lower triangle of a ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 64 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( a( k, k ),KIND=sp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakkrowmax ) then rowmax = stemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=sp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=sp) )1_${ik}$ )call stdlib${ii}$_cswap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) end if ! for both 1x1 and 2x2 pivots, interchange rows and ! columns kk and kp in the trailing submatrix a(k:n,k:n) if( kp/=kk ) then ! (1) swap columnar parts if( kp1_${ik}$ )call stdlib${ii}$_cswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) else ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=sp) if( kstep==2_${ik}$ )a( k+1, k+1 ) = real( a( k+1, k+1 ),KIND=sp) end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of a now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / real( a( k, k ),KIND=sp) call stdlib${ii}$_cher( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_csscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=sp) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_cher( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_izamax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( ( max( absakk, colmax )==zero ) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=dp) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_izamax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = cabs1( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=dp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=dp) )1_${ik}$ )call stdlib${ii}$_zswap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = p + 1, k - 1 t = conjg( a( j, k ) ) a( j, k ) = conjg( a( p, j ) ) a( p, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( p, k ) = conjg( a( p, k ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( k, k ),KIND=dp) a( k, k ) = real( a( p, p ),KIND=dp) a( p, p ) = r1 ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ )call stdlib${ii}$_zswap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = kp + 1, kk - 1 t = conjg( a( j, kk ) ) a( j, kk ) = conjg( a( kp, j ) ) a( kp, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( kp, kk ) = conjg( a( kp, kk ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( kk, kk ),KIND=dp) a( kk, kk ) = real( a( kp, kp ),KIND=dp) a( kp, kp ) = r1 if( kstep==2_${ik}$ ) then ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=dp) ! (5) swap row elements t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( real( a( k, k ),KIND=dp) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / real( a( k, k ),KIND=dp) call stdlib${ii}$_zher( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_zdscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=dp) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_zher( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then ! d = |a12| d = stdlib${ii}$_dlapy2( real( a( k-1, k ),KIND=dp),aimag( a( k-1, k ) ) ) d11 = real( a( k, k ) / d,KIND=dp) d22 = real( a( k-1, k-1 ) / d,KIND=dp) d12 = a( k-1, k ) / d tt = one / ( d11*d22-one ) do j = k - 2, 1, -1 ! compute d21 * ( w(k)w(k+1) ) * inv(d(k)) for row j wkm1 = tt*( d11*a( j, k-1 )-conjg( d12 )*a( j, k ) ) wk = tt*( d22*a( j, k )-d12*a( j, k-1 ) ) ! perform a rank-2 update of a(1:k-2,1:k-2) do i = j, 1, -1 a( i, j ) = a( i, j ) -( a( i, k ) / d )*conjg( wk ) -( a( i, k-1 ) & / d )*conjg( wkm1 ) end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d a( j, k-1 ) = wkm1 / d ! (*) make sure that diagonal element of pivot is real a( j, j ) = cmplx( real( a( j, j ),KIND=dp), zero,KIND=dp) end do end if ! copy superdiagonal elements of d(k) to e(k) and ! zero out superdiagonal entry of a e( k ) = a( k-1, k ) e( k-1 ) = czero a( k-1, k ) = czero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 34 continue else ! factorize a as l*d*l**h using the lower triangle of a ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 64 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( a( k, k ),KIND=dp) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=dp) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=dp) )1_${ik}$ )call stdlib${ii}$_zswap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) end if ! for both 1x1 and 2x2 pivots, interchange rows and ! columns kk and kp in the trailing submatrix a(k:n,k:n) if( kp/=kk ) then ! (1) swap columnar parts if( kp1_${ik}$ )call stdlib${ii}$_zswap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) else ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=dp) if( kstep==2_${ik}$ )a( k+1, k+1 ) = real( a( k+1, k+1 ),KIND=dp) end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of a now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / real( a( k, k ),KIND=dp) call stdlib${ii}$_zher( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_zdscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=dp) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_zher( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k1_${ik}$ ) then imax = stdlib${ii}$_i${ci}$amax( k-1, a( 1_${ik}$, k ), 1_${ik}$ ) colmax = cabs1( a( imax, k ) ) else colmax = zero end if if( ( max( absakk, colmax )==zero ) ) then ! column k is zero or underflow: set info and continue if( info==0_${ik}$ )info = k kp = k a( k, k ) = real( a( k, k ),KIND=${ck}$) ! set e( k ) to zero if( k>1_${ik}$ )e( k ) = czero else ! ============================================================ ! begin pivot search ! case(1) ! equivalent to testing for absakk>=alpha*colmax ! (used to handle nan and inf) if( .not.( absakk1_${ik}$ ) then itemp = stdlib${ii}$_i${ci}$amax( imax-1, a( 1_${ik}$, imax ), 1_${ik}$ ) dtemp = cabs1( a( itemp, imax ) ) if( dtemp>rowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=${ck}$) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=${ck}$) )1_${ik}$ )call stdlib${ii}$_${ci}$swap( p-1, a( 1_${ik}$, k ), 1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = p + 1, k - 1 t = conjg( a( j, k ) ) a( j, k ) = conjg( a( p, j ) ) a( p, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( p, k ) = conjg( a( p, k ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( k, k ),KIND=${ck}$) a( k, k ) = real( a( p, p ),KIND=${ck}$) a( p, p ) = r1 ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ )call stdlib${ii}$_${ci}$swap( kp-1, a( 1_${ik}$, kk ), 1_${ik}$, a( 1_${ik}$, kp ), 1_${ik}$ ) ! (2) swap and conjugate middle parts do j = kp + 1, kk - 1 t = conjg( a( j, kk ) ) a( j, kk ) = conjg( a( kp, j ) ) a( kp, j ) = t end do ! (3) swap and conjugate corner elements at row-col interserction a( kp, kk ) = conjg( a( kp, kk ) ) ! (4) swap diagonal elements at row-col intersection r1 = real( a( kk, kk ),KIND=${ck}$) a( kk, kk ) = real( a( kp, kp ),KIND=${ck}$) a( kp, kp ) = r1 if( kstep==2_${ik}$ ) then ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=${ck}$) ! (5) swap row elements t = a( k-1, k ) a( k-1, k ) = a( kp, k ) a( kp, k ) = t end if ! convert upper triangle of a into u form by applying ! the interchanges in columns k+1:n. if( k1_${ik}$ ) then ! perform a rank-1 update of a(1:k-1,1:k-1) and ! store u(k) in column k if( abs( real( a( k, k ),KIND=${ck}$) )>=sfmin ) then ! perform a rank-1 update of a(1:k-1,1:k-1) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*1/d(k)*w(k)**t d11 = one / real( a( k, k ),KIND=${ck}$) call stdlib${ii}$_${ci}$her( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) ! store u(k) in column k call stdlib${ii}$_${ci}$dscal( k-1, d11, a( 1_${ik}$, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=${ck}$) do ii = 1, k - 1 a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - u(k)*d(k)*u(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ci}$her( uplo, k-1, -d11, a( 1_${ik}$, k ), 1_${ik}$, a, lda ) end if ! store the superdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k-1 now hold ! ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k) ! where u(k) and u(k-1) are the k-th and (k-1)-th columns ! of u ! perform a rank-2 update of a(1:k-2,1:k-2) as ! a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )**t ! = a - ( ( a(k-1)a(k) )*inv(d(k)) ) * ( a(k-1)a(k) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k>2_${ik}$ ) then ! d = |a12| d = stdlib${ii}$_${c2ri(ci)}$lapy2( real( a( k-1, k ),KIND=${ck}$),aimag( a( k-1, k ) ) ) d11 = real( a( k, k ) / d,KIND=${ck}$) d22 = real( a( k-1, k-1 ) / d,KIND=${ck}$) d12 = a( k-1, k ) / d tt = one / ( d11*d22-one ) do j = k - 2, 1, -1 ! compute d21 * ( w(k)w(k+1) ) * inv(d(k)) for row j wkm1 = tt*( d11*a( j, k-1 )-conjg( d12 )*a( j, k ) ) wk = tt*( d22*a( j, k )-d12*a( j, k-1 ) ) ! perform a rank-2 update of a(1:k-2,1:k-2) do i = j, 1, -1 a( i, j ) = a( i, j ) -( a( i, k ) / d )*conjg( wk ) -( a( i, k-1 ) & / d )*conjg( wkm1 ) end do ! store u(k) and u(k-1) in cols k and k-1 for row j a( j, k ) = wk / d a( j, k-1 ) = wkm1 / d ! (*) make sure that diagonal element of pivot is real a( j, j ) = cmplx( real( a( j, j ),KIND=${ck}$), zero,KIND=${ck}$) end do end if ! copy superdiagonal elements of d(k) to e(k) and ! zero out superdiagonal entry of a e( k ) = a( k-1, k ) e( k-1 ) = czero a( k-1, k ) = czero end if ! end column k is nonsingular end if ! store details of the interchanges in ipiv if( kstep==1_${ik}$ ) then ipiv( k ) = kp else ipiv( k ) = -p ipiv( k-1 ) = -kp end if ! decrease k and return to the start of the main loop k = k - kstep go to 10 34 continue else ! factorize a as l*d*l**h using the lower triangle of a ! initialize the unused last entry of the subdiagonal array e. e( n ) = czero ! k is the main loop index, increasing from 1 to n in steps of ! 1 or 2 k = 1_${ik}$ 40 continue ! if k > n, exit from loop if( k>n )go to 64 kstep = 1_${ik}$ p = k ! determine rows and columns to be interchanged and whether ! a 1-by-1 or 2-by-2 pivot block will be used absakk = abs( real( a( k, k ),KIND=${ck}$) ) ! imax is the row-index of the largest off-diagonal element in ! column k, and colmax is its absolute value. ! determine both colmax and imax. if( k=alpha*colmax ! (used to handle nan and inf) if( .not.( absakkrowmax ) then rowmax = dtemp jmax = itemp end if end if ! case(2) ! equivalent to testing for ! abs( real( w( imax,kw-1 ),KIND=${ck}$) )>=alpha*rowmax ! (used to handle nan and inf) if( .not.( abs( real( a( imax, imax ),KIND=${ck}$) )1_${ik}$ )call stdlib${ii}$_${ci}$swap( k-1, a( k, 1_${ik}$ ), lda, a( p, 1_${ik}$ ), lda ) end if ! for both 1x1 and 2x2 pivots, interchange rows and ! columns kk and kp in the trailing submatrix a(k:n,k:n) if( kp/=kk ) then ! (1) swap columnar parts if( kp1_${ik}$ )call stdlib${ii}$_${ci}$swap( k-1, a( kk, 1_${ik}$ ), lda, a( kp, 1_${ik}$ ), lda ) else ! (*) make sure that diagonal element of pivot is real a( k, k ) = real( a( k, k ),KIND=${ck}$) if( kstep==2_${ik}$ )a( k+1, k+1 ) = real( a( k+1, k+1 ),KIND=${ck}$) end if ! update the trailing submatrix if( kstep==1_${ik}$ ) then ! 1-by-1 pivot block d(k): column k of a now holds ! w(k) = l(k)*d(k), ! where l(k) is the k-th column of l if( k=sfmin ) then ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t d11 = one / real( a( k, k ),KIND=${ck}$) call stdlib${ii}$_${ci}$her( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) ! store l(k) in column k call stdlib${ii}$_${ci}$dscal( n-k, d11, a( k+1, k ), 1_${ik}$ ) else ! store l(k) in column k d11 = real( a( k, k ),KIND=${ck}$) do ii = k + 1, n a( ii, k ) = a( ii, k ) / d11 end do ! perform a rank-1 update of a(k+1:n,k+1:n) as ! a := a - l(k)*d(k)*l(k)**t ! = a - w(k)*(1/d(k))*w(k)**t ! = a - (w(k)/d(k))*(d(k))*(w(k)/d(k))**t call stdlib${ii}$_${ci}$her( uplo, n-k, -d11, a( k+1, k ), 1_${ik}$,a( k+1, k+1 ), lda ) end if ! store the subdiagonal element of d in array e e( k ) = czero end if else ! 2-by-2 pivot block d(k): columns k and k+1 now hold ! ( w(k) w(k+1) ) = ( l(k) l(k+1) )*d(k) ! where l(k) and l(k+1) are the k-th and (k+1)-th columns ! of l ! perform a rank-2 update of a(k+2:n,k+2:n) as ! a := a - ( l(k) l(k+1) ) * d(k) * ( l(k) l(k+1) )**t ! = a - ( ( a(k)a(k+1) )*inv(d(k) ) * ( a(k)a(k+1) )**t ! and store l(k) and l(k+1) in columns k and k+1 if( k=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j + 1_${ik}$ jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_clahef_aa( uplo, 2_${ik}$-k1, n-j, jb,a( max(1_${ik}$, j), j+1 ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_cswap( j1-k1-2, a( 1_${ik}$, j2 ), 1_${ik}$,a( 1_${ik}$, ipiv(j2) ), 1_${ik}$ ) end if end do j = j + jb ! trailing submatrix update, where ! the row a(j1-1, j2-1:n) stores u(j1, j2+1:n) and ! work stores the current block of the auxiriarly matrix h if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = conjg( a( j, j+1 ) ) a( j, j+1 ) = cone call stdlib${ii}$_ccopy( n-j, a( j-1, j+1 ), lda,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_cscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=0 and k2=1 for the first panel, ! and k1=1 and k2=0 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_cgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_cgemm( 'CONJUGATE TRANSPOSE', 'TRANSPOSE',1_${ik}$, mj, jb+1,-cone,& a( j1-k2, j3 ), lda,work( (j3-j1+1)+k1*n ), n,cone, a( j3, j3 ), lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block row with stdlib${ii}$_cgemm call stdlib${ii}$_cgemm( 'CONJUGATE TRANSPOSE', 'TRANSPOSE',nj, n-j3+1, jb+1,-& cone, a( j1-k2, j2 ), lda,work( (j3-j1+1)+k1*n ), n,cone, a( j2, j3 ), lda & ) end do ! recover t( j, j+1 ) a( j, j+1 ) = conjg( alpha ) end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_ccopy( n-j, a( j+1, j+1 ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 10 else ! ..................................................... ! factorize a as l*d*l**h using the lower triangle of a ! ..................................................... ! copy first column a(1:n, 1) into h(1:n, 1) ! (stored in work(1:n)) call stdlib${ii}$_ccopy( n, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) ! j is the main loop index, increasing from 1 to n in steps of ! jb, where jb is the number of columns factorized by stdlib${ii}$_clahef; ! jb is either nb, or n-j+1 for the last block j = 0_${ik}$ 11 continue if( j>=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j+1 jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_clahef_aa( uplo, 2_${ik}$-k1, n-j, jb,a( j+1, max(1_${ik}$, j) ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_cswap( j1-k1-2, a( j2, 1_${ik}$ ), lda,a( ipiv(j2), 1_${ik}$ ), lda ) end if end do j = j + jb ! trailing submatrix update, where ! a(j2+1, j1-1) stores l(j2+1, j1) and ! work(j2+1, 1) stores h(j2+1, 1) if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = conjg( a( j+1, j ) ) a( j+1, j ) = cone call stdlib${ii}$_ccopy( n-j, a( j+1, j-1 ), 1_${ik}$,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_cscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=0 and k2=1 for the first panel, ! and k1=1 and k2=0 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_cgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',mj, 1_${ik}$, jb+1,-& cone, work( (j3-j1+1)+k1*n ), n,a( j3, j1-k2 ), lda,cone, a( j3, j3 ), & lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block column with stdlib${ii}$_cgemm call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',n-j3+1, nj, jb+1,-& cone, work( (j3-j1+1)+k1*n ), n,a( j2, j1-k2 ), lda,cone, a( j3, j2 ), lda & ) end do ! recover t( j+1, j ) a( j+1, j ) = conjg( alpha ) end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_ccopy( n-j, a( j+1, j+1 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 11 end if 20 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_chetrf_aa pure module subroutine stdlib${ii}$_zhetrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) !! ZHETRF_AA computes the factorization of a complex hermitian matrix A !! using the Aasen's algorithm. The form of the factorization is !! A = U**H*T*U or A = L*T*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is a hermitian tridiagonal matrix. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: j, lwkopt integer(${ik}$) :: nb, mj, nj, k1, k2, j1, j2, j3, jb complex(dp) :: alpha ! Intrinsic Functions ! Executable Statements ! determine the block size nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZHETRF_AA', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j + 1_${ik}$ jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_zlahef_aa( uplo, 2_${ik}$-k1, n-j, jb,a( max(1_${ik}$, j), j+1 ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_zswap( j1-k1-2, a( 1_${ik}$, j2 ), 1_${ik}$,a( 1_${ik}$, ipiv(j2) ), 1_${ik}$ ) end if end do j = j + jb ! trailing submatrix update, where ! the row a(j1-1, j2-1:n) stores u(j1, j2+1:n) and ! work stores the current block of the auxiriarly matrix h if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = conjg( a( j, j+1 ) ) a( j, j+1 ) = cone call stdlib${ii}$_zcopy( n-j, a( j-1, j+1 ), lda,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_zscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=0 and k2=1 for the first panel, ! and k1=1 and k2=0 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_zgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_zgemm( 'CONJUGATE TRANSPOSE', 'TRANSPOSE',1_${ik}$, mj, jb+1,-cone,& a( j1-k2, j3 ), lda,work( (j3-j1+1)+k1*n ), n,cone, a( j3, j3 ), lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block row with stdlib${ii}$_zgemm call stdlib${ii}$_zgemm( 'CONJUGATE TRANSPOSE', 'TRANSPOSE',nj, n-j3+1, jb+1,-& cone, a( j1-k2, j2 ), lda,work( (j3-j1+1)+k1*n ), n,cone, a( j2, j3 ), lda & ) end do ! recover t( j, j+1 ) a( j, j+1 ) = conjg( alpha ) end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_zcopy( n-j, a( j+1, j+1 ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 10 else ! ..................................................... ! factorize a as l*d*l**h using the lower triangle of a ! ..................................................... ! copy first column a(1:n, 1) into h(1:n, 1) ! (stored in work(1:n)) call stdlib${ii}$_zcopy( n, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) ! j is the main loop index, increasing from 1 to n in steps of ! jb, where jb is the number of columns factorized by stdlib${ii}$_zlahef; ! jb is either nb, or n-j+1 for the last block j = 0_${ik}$ 11 continue if( j>=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j+1 jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_zlahef_aa( uplo, 2_${ik}$-k1, n-j, jb,a( j+1, max(1_${ik}$, j) ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_zswap( j1-k1-2, a( j2, 1_${ik}$ ), lda,a( ipiv(j2), 1_${ik}$ ), lda ) end if end do j = j + jb ! trailing submatrix update, where ! a(j2+1, j1-1) stores l(j2+1, j1) and ! work(j2+1, 1) stores h(j2+1, 1) if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = conjg( a( j+1, j ) ) a( j+1, j ) = cone call stdlib${ii}$_zcopy( n-j, a( j+1, j-1 ), 1_${ik}$,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_zscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=0 and k2=1 for the first panel, ! and k1=1 and k2=0 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_zgemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',mj, 1_${ik}$, jb+1,-& cone, work( (j3-j1+1)+k1*n ), n,a( j3, j1-k2 ), lda,cone, a( j3, j3 ), & lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block column with stdlib${ii}$_zgemm call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',n-j3+1, nj, jb+1,-& cone, work( (j3-j1+1)+k1*n ), n,a( j2, j1-k2 ), lda,cone, a( j3, j2 ), lda & ) end do ! recover t( j+1, j ) a( j+1, j ) = conjg( alpha ) end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_zcopy( n-j, a( j+1, j+1 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 11 end if 20 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zhetrf_aa #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hetrf_aa( uplo, n, a, lda, ipiv, work, lwork, info) !! ZHETRF_AA: computes the factorization of a complex hermitian matrix A !! using the Aasen's algorithm. The form of the factorization is !! A = U**H*T*U or A = L*T*L**H !! where U (or L) is a product of permutation and unit upper (lower) !! triangular matrices, and T is a hermitian tridiagonal matrix. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, upper integer(${ik}$) :: j, lwkopt integer(${ik}$) :: nb, mj, nj, k1, k2, j1, j2, j3, jb complex(${ck}$) :: alpha ! Intrinsic Functions ! Executable Statements ! determine the block size nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZHETRF_AA', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j + 1_${ik}$ jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_${ci}$lahef_aa( uplo, 2_${ik}$-k1, n-j, jb,a( max(1_${ik}$, j), j+1 ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_${ci}$swap( j1-k1-2, a( 1_${ik}$, j2 ), 1_${ik}$,a( 1_${ik}$, ipiv(j2) ), 1_${ik}$ ) end if end do j = j + jb ! trailing submatrix update, where ! the row a(j1-1, j2-1:n) stores u(j1, j2+1:n) and ! work stores the current block of the auxiriarly matrix h if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = conjg( a( j, j+1 ) ) a( j, j+1 ) = cone call stdlib${ii}$_${ci}$copy( n-j, a( j-1, j+1 ), lda,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=0 and k2=1 for the first panel, ! and k1=1 and k2=0 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_${ci}$gemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_${ci}$gemm( 'CONJUGATE TRANSPOSE', 'TRANSPOSE',1_${ik}$, mj, jb+1,-cone,& a( j1-k2, j3 ), lda,work( (j3-j1+1)+k1*n ), n,cone, a( j3, j3 ), lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block row with stdlib${ii}$_${ci}$gemm call stdlib${ii}$_${ci}$gemm( 'CONJUGATE TRANSPOSE', 'TRANSPOSE',nj, n-j3+1, jb+1,-& cone, a( j1-k2, j2 ), lda,work( (j3-j1+1)+k1*n ), n,cone, a( j2, j3 ), lda & ) end do ! recover t( j, j+1 ) a( j, j+1 ) = conjg( alpha ) end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_${ci}$copy( n-j, a( j+1, j+1 ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 10 else ! ..................................................... ! factorize a as l*d*l**h using the lower triangle of a ! ..................................................... ! copy first column a(1:n, 1) into h(1:n, 1) ! (stored in work(1:n)) call stdlib${ii}$_${ci}$copy( n, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) ! j is the main loop index, increasing from 1 to n in steps of ! jb, where jb is the number of columns factorized by stdlib${ii}$_${ci}$lahef; ! jb is either nb, or n-j+1 for the last block j = 0_${ik}$ 11 continue if( j>=n )go to 20 ! each step of the main loop ! j is the last column of the previous panel ! j1 is the first column of the current panel ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=1 for the first panel, and ! k1=0 for the rest j1 = j+1 jb = min( n-j1+1, nb ) k1 = max(1_${ik}$, j)-j ! panel factorization call stdlib${ii}$_${ci}$lahef_aa( uplo, 2_${ik}$-k1, n-j, jb,a( j+1, max(1_${ik}$, j) ), lda,ipiv( j+1 ), & work, n, work( n*nb+1 ) ) ! adjust ipiv and apply it back (j-th step picks (j+1)-th pivot) do j2 = j+2, min(n, j+jb+1) ipiv( j2 ) = ipiv( j2 ) + j if( (j2/=ipiv(j2)) .and. ((j1-k1)>2_${ik}$) ) then call stdlib${ii}$_${ci}$swap( j1-k1-2, a( j2, 1_${ik}$ ), lda,a( ipiv(j2), 1_${ik}$ ), lda ) end if end do j = j + jb ! trailing submatrix update, where ! a(j2+1, j1-1) stores l(j2+1, j1) and ! work(j2+1, 1) stores h(j2+1, 1) if( j1_${ik}$ .or. jb>1_${ik}$ ) then ! merge rank-1 update with blas-3 update alpha = conjg( a( j+1, j ) ) a( j+1, j ) = cone call stdlib${ii}$_${ci}$copy( n-j, a( j+1, j-1 ), 1_${ik}$,work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1_${ik}$ ) ! k1 identifies if the previous column of the panel has been ! explicitly stored, e.g., k1=0 and k2=1 for the first panel, ! and k1=1 and k2=0 for the rest if( j1>1_${ik}$ ) then ! not first panel k2 = 1_${ik}$ else ! first panel k2 = 0_${ik}$ ! first update skips the first column jb = jb - 1_${ik}$ end if do j2 = j+1, n, nb nj = min( nb, n-j2+1 ) ! update (j2, j2) diagonal block with stdlib${ii}$_${ci}$gemv j3 = j2 do mj = nj-1, 1, -1 call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',mj, 1_${ik}$, jb+1,-& cone, work( (j3-j1+1)+k1*n ), n,a( j3, j1-k2 ), lda,cone, a( j3, j3 ), & lda ) j3 = j3 + 1_${ik}$ end do ! update off-diagonal block of j2-th block column with stdlib${ii}$_${ci}$gemm call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',n-j3+1, nj, jb+1,-& cone, work( (j3-j1+1)+k1*n ), n,a( j2, j1-k2 ), lda,cone, a( j3, j2 ), lda & ) end do ! recover t( j+1, j ) a( j+1, j ) = conjg( alpha ) end if ! work(j+1, 1) stores h(j+1, 1) call stdlib${ii}$_${ci}$copy( n-j, a( j+1, j+1 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if go to 11 end if 20 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$hetrf_aa #:endif #:endfor pure module subroutine stdlib${ii}$_clahef_aa( uplo, j1, m, nb, a, lda, ipiv,h, ldh, work ) !! CLAHEF_AA factorizes a panel of a complex hermitian matrix A using !! the Aasen's algorithm. The panel consists of a set of NB rows of A !! when UPLO is U, or a set of NB columns when UPLO is L. !! In order to factorize the panel, the Aasen's algorithm requires the !! last row, or column, of the previous panel. The first row, or column, !! of A is set to be the first row, or column, of an identity matrix, !! which is used to factorize the first panel. !! The resulting J-th row of U, or J-th column of L, is stored in the !! (J-1)-th row, or column, of A (without the unit diagonals), while !! the diagonal and subdiagonal of A are overwritten by those of T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: m, nb, j1, lda, ldh ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*), h(ldh,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, k, k1, i1, i2, mj complex(sp) :: piv, alpha ! Intrinsic Functions ! Executable Statements j = 1_${ik}$ ! k1 is the first column of the panel to be factorized ! i.e., k1 is 2 for the first block column, and 1 for the rest of the blocks k1 = (2_${ik}$-j1)+1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then ! ..................................................... ! factorize a as u**t*d*u using the upper triangle of a ! ..................................................... 10 continue if ( j>min(m, nb) )go to 20 ! k is the column to be factorized ! when being called from stdlib${ii}$_chetrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:n, j) := a(j, j:n) - h(j:n, 1:(j-1)) * l(j1:(j-1), j), ! where h(j:n, j) has been initialized to be a(j, j:n) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_clacgv( j-k1, a( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( 1_${ik}$, j ), 1_${ik}$,& cone, h( j, j ), 1_${ik}$ ) call stdlib${ii}$_clacgv( j-k1, a( 1_${ik}$, j ), 1_${ik}$ ) end if ! copy h(i:n, i) into work call stdlib${ii}$_ccopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j-1, j:n) * t(j-1,j), ! where a(j-1, j) stores t(j-1, j) and a(j-2, j:n) stores u(j-1, j:n) alpha = -conjg( a( k-1, j ) ) call stdlib${ii}$_caxpy( mj, alpha, a( k-2, j ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( k, j ) = real( work( 1_${ik}$ ),KIND=sp) if( j1_${ik}$ ) then alpha = -a( k, j ) call stdlib${ii}$_caxpy( m-j, alpha, a( k-1, j+1 ), lda,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:n)|) i2 = stdlib${ii}$_icamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply hermitian pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1, i1+1:n) with a(i1+1:n, i2) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_cswap( i2-i1-1, a( j1+i1-1, i1+1 ), lda,a( j1+i1, i2 ), 1_${ik}$ ) call stdlib${ii}$_clacgv( i2-i1, a( j1+i1-1, i1+1 ), lda ) call stdlib${ii}$_clacgv( i2-i1-1, a( j1+i1, i2 ), 1_${ik}$ ) ! swap a(i1, i2+1:n) with a(i2, i2+1:n) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_cswap( i1-k1+1, a( 1_${ik}$, i1 ), 1_${ik}$,a( 1_${ik}$, i2 ), 1_${ik}$ ) end if else ipiv( j+1 ) = j+1 endif ! set a(j, j+1) = t(j, j+1) a( k, j+1 ) = work( 2_${ik}$ ) if( jmin( m, nb ) )go to 40 ! k is the column to be factorized ! when being called from stdlib${ii}$_chetrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:n, j) := a(j:n, j) - h(j:n, 1:(j-1)) * l(j, j1:(j-1))^t, ! where h(j:n, j) has been initialized to be a(j:n, j) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_clacgv( j-k1, a( j, 1_${ik}$ ), lda ) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( j, 1_${ik}$ ), & lda,cone, h( j, j ), 1_${ik}$ ) call stdlib${ii}$_clacgv( j-k1, a( j, 1_${ik}$ ), lda ) end if ! copy h(j:n, j) into work call stdlib${ii}$_ccopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j:n, j-1) * t(j-1,j), ! where a(j-1, j) = t(j-1, j) and a(j, j-2) = l(j, j-1) alpha = -conjg( a( j, k-1 ) ) call stdlib${ii}$_caxpy( mj, alpha, a( j, k-2 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( j, k ) = real( work( 1_${ik}$ ),KIND=sp) if( j1_${ik}$ ) then alpha = -a( j, k ) call stdlib${ii}$_caxpy( m-j, alpha, a( j+1, k-1 ), 1_${ik}$,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:n)|) i2 = stdlib${ii}$_icamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply hermitian pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1+1:n, i1) with a(i2, i1+1:n) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_cswap( i2-i1-1, a( i1+1, j1+i1-1 ), 1_${ik}$,a( i2, j1+i1 ), lda ) call stdlib${ii}$_clacgv( i2-i1, a( i1+1, j1+i1-1 ), 1_${ik}$ ) call stdlib${ii}$_clacgv( i2-i1-1, a( i2, j1+i1 ), lda ) ! swap a(i2+1:n, i1) with a(i2+1:n, i2) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_cswap( i1-k1+1, a( i1, 1_${ik}$ ), lda,a( i2, 1_${ik}$ ), lda ) end if else ipiv( j+1 ) = j+1 endif ! set a(j+1, j) = t(j+1, j) a( j+1, k ) = work( 2_${ik}$ ) if( jmin(m, nb) )go to 20 ! k is the column to be factorized ! when being called from stdlib${ii}$_zhetrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:n, j) := a(j, j:n) - h(j:n, 1:(j-1)) * l(j1:(j-1), j), ! where h(j:n, j) has been initialized to be a(j, j:n) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_zlacgv( j-k1, a( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( 1_${ik}$, j ), 1_${ik}$,& cone, h( j, j ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( j-k1, a( 1_${ik}$, j ), 1_${ik}$ ) end if ! copy h(i:n, i) into work call stdlib${ii}$_zcopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j-1, j:n) * t(j-1,j), ! where a(j-1, j) stores t(j-1, j) and a(j-2, j:n) stores u(j-1, j:n) alpha = -conjg( a( k-1, j ) ) call stdlib${ii}$_zaxpy( mj, alpha, a( k-2, j ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( k, j ) = real( work( 1_${ik}$ ),KIND=dp) if( j1_${ik}$ ) then alpha = -a( k, j ) call stdlib${ii}$_zaxpy( m-j, alpha, a( k-1, j+1 ), lda,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:n)|) i2 = stdlib${ii}$_izamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply hermitian pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1, i1+1:n) with a(i1+1:n, i2) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_zswap( i2-i1-1, a( j1+i1-1, i1+1 ), lda,a( j1+i1, i2 ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( i2-i1, a( j1+i1-1, i1+1 ), lda ) call stdlib${ii}$_zlacgv( i2-i1-1, a( j1+i1, i2 ), 1_${ik}$ ) ! swap a(i1, i2+1:n) with a(i2, i2+1:n) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_zswap( i1-k1+1, a( 1_${ik}$, i1 ), 1_${ik}$,a( 1_${ik}$, i2 ), 1_${ik}$ ) end if else ipiv( j+1 ) = j+1 endif ! set a(j, j+1) = t(j, j+1) a( k, j+1 ) = work( 2_${ik}$ ) if( jmin( m, nb ) )go to 40 ! k is the column to be factorized ! when being called from stdlib${ii}$_zhetrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:n, j) := a(j:n, j) - h(j:n, 1:(j-1)) * l(j, j1:(j-1))^t, ! where h(j:n, j) has been initialized to be a(j:n, j) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_zlacgv( j-k1, a( j, 1_${ik}$ ), lda ) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( j, 1_${ik}$ ), & lda,cone, h( j, j ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( j-k1, a( j, 1_${ik}$ ), lda ) end if ! copy h(j:n, j) into work call stdlib${ii}$_zcopy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j:n, j-1) * t(j-1,j), ! where a(j-1, j) = t(j-1, j) and a(j, j-2) = l(j, j-1) alpha = -conjg( a( j, k-1 ) ) call stdlib${ii}$_zaxpy( mj, alpha, a( j, k-2 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( j, k ) = real( work( 1_${ik}$ ),KIND=dp) if( j1_${ik}$ ) then alpha = -a( j, k ) call stdlib${ii}$_zaxpy( m-j, alpha, a( j+1, k-1 ), 1_${ik}$,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:n)|) i2 = stdlib${ii}$_izamax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply hermitian pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1+1:n, i1) with a(i2, i1+1:n) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_zswap( i2-i1-1, a( i1+1, j1+i1-1 ), 1_${ik}$,a( i2, j1+i1 ), lda ) call stdlib${ii}$_zlacgv( i2-i1, a( i1+1, j1+i1-1 ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( i2-i1-1, a( i2, j1+i1 ), lda ) ! swap a(i2+1:n, i1) with a(i2+1:n, i2) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_zswap( i1-k1+1, a( i1, 1_${ik}$ ), lda,a( i2, 1_${ik}$ ), lda ) end if else ipiv( j+1 ) = j+1 endif ! set a(j+1, j) = t(j+1, j) a( j+1, k ) = work( 2_${ik}$ ) if( jmin(m, nb) )go to 20 ! k is the column to be factorized ! when being called from stdlib${ii}$_${ci}$hetrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:n, j) := a(j, j:n) - h(j:n, 1:(j-1)) * l(j1:(j-1), j), ! where h(j:n, j) has been initialized to be a(j, j:n) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_${ci}$lacgv( j-k1, a( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( 1_${ik}$, j ), 1_${ik}$,& cone, h( j, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( j-k1, a( 1_${ik}$, j ), 1_${ik}$ ) end if ! copy h(i:n, i) into work call stdlib${ii}$_${ci}$copy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j-1, j:n) * t(j-1,j), ! where a(j-1, j) stores t(j-1, j) and a(j-2, j:n) stores u(j-1, j:n) alpha = -conjg( a( k-1, j ) ) call stdlib${ii}$_${ci}$axpy( mj, alpha, a( k-2, j ), lda, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( k, j ) = real( work( 1_${ik}$ ),KIND=${ck}$) if( j1_${ik}$ ) then alpha = -a( k, j ) call stdlib${ii}$_${ci}$axpy( m-j, alpha, a( k-1, j+1 ), lda,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:n)|) i2 = stdlib${ii}$_i${ci}$amax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply hermitian pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1, i1+1:n) with a(i1+1:n, i2) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_${ci}$swap( i2-i1-1, a( j1+i1-1, i1+1 ), lda,a( j1+i1, i2 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( i2-i1, a( j1+i1-1, i1+1 ), lda ) call stdlib${ii}$_${ci}$lacgv( i2-i1-1, a( j1+i1, i2 ), 1_${ik}$ ) ! swap a(i1, i2+1:n) with a(i2, i2+1:n) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_${ci}$swap( i1-k1+1, a( 1_${ik}$, i1 ), 1_${ik}$,a( 1_${ik}$, i2 ), 1_${ik}$ ) end if else ipiv( j+1 ) = j+1 endif ! set a(j, j+1) = t(j, j+1) a( k, j+1 ) = work( 2_${ik}$ ) if( jmin( m, nb ) )go to 40 ! k is the column to be factorized ! when being called from stdlib${ii}$_${ci}$hetrf_aa, ! > for the first block column, j1 is 1, hence j1+j-1 is j, ! > for the rest of the columns, j1 is 2, and j1+j-1 is j+1, k = j1+j-1 if( j==m ) then ! only need to compute t(j, j) mj = 1_${ik}$ else mj = m-j+1 end if ! h(j:n, j) := a(j:n, j) - h(j:n, 1:(j-1)) * l(j, j1:(j-1))^t, ! where h(j:n, j) has been initialized to be a(j:n, j) if( k>2_${ik}$ ) then ! k is the column to be factorized ! > for the first block column, k is j, skipping the first two ! columns ! > for the rest of the columns, k is j+1, skipping only the ! first column call stdlib${ii}$_${ci}$lacgv( j-k1, a( j, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', mj, j-k1,-cone, h( j, k1 ), ldh,a( j, 1_${ik}$ ), & lda,cone, h( j, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( j-k1, a( j, 1_${ik}$ ), lda ) end if ! copy h(j:n, j) into work call stdlib${ii}$_${ci}$copy( mj, h( j, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) if( j>k1 ) then ! compute work := work - l(j:n, j-1) * t(j-1,j), ! where a(j-1, j) = t(j-1, j) and a(j, j-2) = l(j, j-1) alpha = -conjg( a( j, k-1 ) ) call stdlib${ii}$_${ci}$axpy( mj, alpha, a( j, k-2 ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) end if ! set a(j, j) = t(j, j) a( j, k ) = real( work( 1_${ik}$ ),KIND=${ck}$) if( j1_${ik}$ ) then alpha = -a( j, k ) call stdlib${ii}$_${ci}$axpy( m-j, alpha, a( j+1, k-1 ), 1_${ik}$,work( 2_${ik}$ ), 1_${ik}$ ) endif ! find max(|work(2:n)|) i2 = stdlib${ii}$_i${ci}$amax( m-j, work( 2_${ik}$ ), 1_${ik}$ ) + 1_${ik}$ piv = work( i2 ) ! apply hermitian pivot if( (i2/=2_${ik}$) .and. (piv/=0_${ik}$) ) then ! swap work(i1) and work(i2) i1 = 2_${ik}$ work( i2 ) = work( i1 ) work( i1 ) = piv ! swap a(i1+1:n, i1) with a(i2, i1+1:n) i1 = i1+j-1 i2 = i2+j-1 call stdlib${ii}$_${ci}$swap( i2-i1-1, a( i1+1, j1+i1-1 ), 1_${ik}$,a( i2, j1+i1 ), lda ) call stdlib${ii}$_${ci}$lacgv( i2-i1, a( i1+1, j1+i1-1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( i2-i1-1, a( i2, j1+i1 ), lda ) ! swap a(i2+1:n, i1) with a(i2+1:n, i2) if( i2(k1-1) ) then ! swap l(1:i1-1, i1) with l(1:i1-1, i2), ! skipping the first column call stdlib${ii}$_${ci}$swap( i1-k1+1, a( i1, 1_${ik}$ ), lda,a( i2, 1_${ik}$ ), lda ) end if else ipiv( j+1 ) = j+1 endif ! set a(j+1, j) = t(j+1, j) a( j+1, k ) = work( 2_${ik}$ ) if( j1_${ik}$ ) then ! pivot, p**t * b -> b k = 1_${ik}$ do while ( k<=n ) kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ end do ! compute u**h \ b -> b [ (u**h \p**t * b) ] call stdlib${ii}$_ctrsm( 'L', 'U', 'C', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (u**h \p**t * b) ] call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$) call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$) call stdlib${ii}$_clacgv( n-1, work( 1_${ik}$ ), 1_${ik}$ ) end if call stdlib${ii}$_cgtsv(n, nrhs, work(1_${ik}$), work(n), work(2_${ik}$*n), b, ldb,info) ! 3) backward substitution with u if( n>1_${ik}$ ) then ! compute u \ b -> b [ u \ (t \ (u**h \p**t * b) ) ] call stdlib${ii}$_ctrsm( 'L', 'U', 'N', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b(2_${ik}$, 1_${ik}$), & ldb) ! pivot, p * b -> b [ p * (u \ (t \ (u**h \p**t * b) )) ] k = n do while ( k>=1 ) kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ end do end if else ! solve a*x = b, where a = l*t*l**h. ! 1) forward substitution with l if( n>1_${ik}$ ) then ! pivot, p**t * b -> b k = 1_${ik}$ do while ( k<=n ) kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k + 1_${ik}$ end do ! compute l \ b -> b [ (l \p**t * b) ] call stdlib${ii}$_ctrsm( 'L', 'L', 'N', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$),lda, b(2_${ik}$, 1_${ik}$), & ldb ) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (l \p**t * b) ] call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_clacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$) call stdlib${ii}$_clacgv( n-1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_cgtsv(n, nrhs, work(1_${ik}$), work(n), work(2_${ik}$*n), b, ldb,info) ! 3) backward substitution with l**h if( n>1_${ik}$ ) then ! compute (l**h \ b) -> b [ l**h \ (t \ (l \p**t * b) ) ] call stdlib${ii}$_ctrsm( 'L', 'L', 'C', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb ) ! pivot, p * b -> b [ p * (l**h \ (t \ (l \p**t * b) )) ] k = n do while ( k>=1 ) kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_cswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) k = k - 1_${ik}$ end do end if end if return end subroutine stdlib${ii}$_chetrs_aa pure module subroutine stdlib${ii}$_zhetrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) !! ZHETRS_AA solves a system of linear equations A*X = B with a complex !! hermitian matrix A using the factorization A = U**H*T*U or !! A = L*T*L**H computed by ZHETRF_AA. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, nrhs, lda, ldb, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(out) :: work(*) ! ===================================================================== logical(lk) :: lquery, upper integer(${ik}$) :: k, kp, lwkopt ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute u**h \ b -> b [ (u**h \p**t * b) ] call stdlib${ii}$_ztrsm( 'L', 'U', 'C', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb ) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (u**h \p**t * b) ] call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$ ) if( n>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$) call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( n-1, work( 1_${ik}$ ), 1_${ik}$ ) end if call stdlib${ii}$_zgtsv( n, nrhs, work(1_${ik}$), work(n), work(2_${ik}$*n), b, ldb,info ) ! 3) backward substitution with u if( n>1_${ik}$ ) then ! compute u \ b -> b [ u \ (t \ (u**h \p**t * b) ) ] call stdlib${ii}$_ztrsm( 'L', 'U', 'N', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b(2_${ik}$, 1_${ik}$), & ldb) ! pivot, p * b [ p * (u**h \ (t \ (u \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if else ! solve a*x = b, where a = l*t*l**h. ! 1) forward substitution with l if( n>1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute l \ b -> b [ (l \p**t * b) ] call stdlib${ii}$_ztrsm( 'L', 'L', 'N', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$ ),lda, b(2_${ik}$, 1_${ik}$), & ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (l \p**t * b) ] call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$) call stdlib${ii}$_zlacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$) call stdlib${ii}$_zlacgv( n-1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_zgtsv(n, nrhs, work(1_${ik}$), work(n), work(2_${ik}$*n), b, ldb,info) ! 3) backward substitution with l**h if( n>1_${ik}$ ) then ! compute l**h \ b -> b [ l**h \ (t \ (l \p**t * b) ) ] call stdlib${ii}$_ztrsm( 'L', 'L', 'C', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) ! pivot, p * b [ p * (l**h \ (t \ (l \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_zswap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_zhetrs_aa #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hetrs_aa( uplo, n, nrhs, a, lda, ipiv, b, ldb,work, lwork, info ) !! ZHETRS_AA: solves a system of linear equations A*X = B with a complex !! hermitian matrix A using the factorization A = U**H*T*U or !! A = L*T*L**H computed by ZHETRF_AA. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, nrhs, lda, ldb, lwork integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(inout) :: b(ldb,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== logical(lk) :: lquery, upper integer(${ik}$) :: k, kp, lwkopt ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) lquery = ( lwork==-1_${ik}$ ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( lda1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute u**h \ b -> b [ (u**h \p**t * b) ] call stdlib${ii}$_${ci}$trsm( 'L', 'U', 'C', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb ) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (u**h \p**t * b) ] call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$ ) if( n>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$) call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n-1, a( 1_${ik}$, 2_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( n-1, work( 1_${ik}$ ), 1_${ik}$ ) end if call stdlib${ii}$_${ci}$gtsv( n, nrhs, work(1_${ik}$), work(n), work(2_${ik}$*n), b, ldb,info ) ! 3) backward substitution with u if( n>1_${ik}$ ) then ! compute u \ b -> b [ u \ (t \ (u**h \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm( 'L', 'U', 'N', 'U', n-1, nrhs, cone, a( 1_${ik}$, 2_${ik}$ ),lda, b(2_${ik}$, 1_${ik}$), & ldb) ! pivot, p * b [ p * (u**h \ (t \ (u \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if else ! solve a*x = b, where a = l*t*l**h. ! 1) forward substitution with l if( n>1_${ik}$ ) then ! pivot, p**t * b -> b do k = 1, n kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do ! compute l \ b -> b [ (l \p**t * b) ] call stdlib${ii}$_${ci}$trsm( 'L', 'L', 'N', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$ ),lda, b(2_${ik}$, 1_${ik}$), & ldb) end if ! 2) solve with triangular matrix t ! compute t \ b -> b [ t \ (l \p**t * b) ] call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n, a(1_${ik}$, 1_${ik}$), lda+1, work(n), 1_${ik}$) if( n>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 1_${ik}$ ), 1_${ik}$) call stdlib${ii}$_${ci}$lacpy( 'F', 1_${ik}$, n-1, a( 2_${ik}$, 1_${ik}$ ), lda+1, work( 2_${ik}$*n ), 1_${ik}$) call stdlib${ii}$_${ci}$lacgv( n-1, work( 2_${ik}$*n ), 1_${ik}$ ) end if call stdlib${ii}$_${ci}$gtsv(n, nrhs, work(1_${ik}$), work(n), work(2_${ik}$*n), b, ldb,info) ! 3) backward substitution with l**h if( n>1_${ik}$ ) then ! compute l**h \ b -> b [ l**h \ (t \ (l \p**t * b) ) ] call stdlib${ii}$_${ci}$trsm( 'L', 'L', 'C', 'U', n-1, nrhs, cone, a( 2_${ik}$, 1_${ik}$ ),lda, b( 2_${ik}$, 1_${ik}$ ),& ldb) ! pivot, p * b [ p * (l**h \ (t \ (l \p**t * b) )) ] do k = n, 1, -1 kp = ipiv( k ) if( kp/=k )call stdlib${ii}$_${ci}$swap( nrhs, b( k, 1_${ik}$ ), ldb, b( kp, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_${ci}$hetrs_aa #:endif #:endfor pure module subroutine stdlib${ii}$_slaqsy( uplo, n, a, lda, s, scond, amax, equed ) !! SLAQSY equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, n real(sp), intent(in) :: amax, scond ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: s(*) ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1e+0_sp ! Local Scalars integer(${ik}$) :: i, j real(sp) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) / stdlib${ii}$_slamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. do j = 1, n cj = s( j ) do i = 1, j a( i, j ) = cj*s( i )*a( i, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, n a( i, j ) = cj*s( i )*a( i, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_slaqsy pure module subroutine stdlib${ii}$_dlaqsy( uplo, n, a, lda, s, scond, amax, equed ) !! DLAQSY equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, n real(dp), intent(in) :: amax, scond ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: s(*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j real(dp) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. do j = 1, n cj = s( j ) do i = 1, j a( i, j ) = cj*s( i )*a( i, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, n a( i, j ) = cj*s( i )*a( i, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_dlaqsy #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqsy( uplo, n, a, lda, s, scond, amax, equed ) !! DLAQSY: equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, n real(${rk}$), intent(in) :: amax, scond ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: s(*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: thresh = 0.1e+0_${rk}$ ! Local Scalars integer(${ik}$) :: i, j real(${rk}$) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${ri}$lamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. do j = 1, n cj = s( j ) do i = 1, j a( i, j ) = cj*s( i )*a( i, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, n a( i, j ) = cj*s( i )*a( i, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_${ri}$laqsy #:endif #:endfor pure module subroutine stdlib${ii}$_claqsy( uplo, n, a, lda, s, scond, amax, equed ) !! CLAQSY equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, n real(sp), intent(in) :: amax, scond ! Array Arguments real(sp), intent(in) :: s(*) complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1e+0_sp ! Local Scalars integer(${ik}$) :: i, j real(sp) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) / stdlib${ii}$_slamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. do j = 1, n cj = s( j ) do i = 1, j a( i, j ) = cj*s( i )*a( i, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, n a( i, j ) = cj*s( i )*a( i, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_claqsy pure module subroutine stdlib${ii}$_zlaqsy( uplo, n, a, lda, s, scond, amax, equed ) !! ZLAQSY equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, n real(dp), intent(in) :: amax, scond ! Array Arguments real(dp), intent(in) :: s(*) complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j real(dp) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. do j = 1, n cj = s( j ) do i = 1, j a( i, j ) = cj*s( i )*a( i, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, n a( i, j ) = cj*s( i )*a( i, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_zlaqsy #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqsy( uplo, n, a, lda, s, scond, amax, equed ) !! ZLAQSY: equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(in) :: amax, scond ! Array Arguments real(${ck}$), intent(in) :: s(*) complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: thresh = 0.1e+0_${ck}$ ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. do j = 1, n cj = s( j ) do i = 1, j a( i, j ) = cj*s( i )*a( i, j ) end do end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) do i = j, n a( i, j ) = cj*s( i )*a( i, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_${ci}$laqsy #:endif #:endfor #:endfor end submodule stdlib_lapack_solve_ldl_comp4 fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_eigv_gen.fypp0000664000175000017500000377501315135654166025567 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_eigv_gen implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_sgeev( jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr,ldvr, work, lwork, & !! SGEEV computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: vl(ldvl,*), vr(ldvr,*), wi(*), work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, itau, iwrk, k, lwork_trevc, maxwrk, & minwrk, nout real(sp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_sgebal( 'B', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = ibal + n iwrk = itau + n call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_slacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'E', 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_shseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 4*n, prefer n + n + 2*n*nb) call stdlib${ii}$_strevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (workspace: need n) call stdlib${ii}$_sgebak( 'B', 'L', n, ilo, ihi, work( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_slartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_srot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (workspace: need n) call stdlib${ii}$_sgebak( 'B', 'R', n, ilo, ihi, work( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_slartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_srot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_sgeev module subroutine stdlib${ii}$_dgeev( jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr,ldvr, work, lwork, & !! DGEEV computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: vl(ldvl,*), vr(ldvr,*), wi(*), work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, itau, iwrk, k, lwork_trevc, maxwrk, & minwrk, nout real(dp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_dgebal( 'B', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = ibal + n iwrk = itau + n call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_dlacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'E', 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_dhseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 4*n, prefer n + n + 2*n*nb) call stdlib${ii}$_dtrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (workspace: need n) call stdlib${ii}$_dgebak( 'B', 'L', n, ilo, ihi, work( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_dlartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_drot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (workspace: need n) call stdlib${ii}$_dgebak( 'B', 'R', n, ilo, ihi, work( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_dlartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_drot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_dgeev #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$geev( jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr,ldvr, work, lwork, & !! DGEEV: computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: vl(ldvl,*), vr(ldvr,*), wi(*), work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, itau, iwrk, k, lwork_trevc, maxwrk, & minwrk, nout real(${rk}$) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(${rk}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ri}$gebal( 'B', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = ibal + n iwrk = itau + n call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_${ri}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'E', 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_${ri}$hseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 4*n, prefer n + n + 2*n*nb) call stdlib${ii}$_${ri}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (workspace: need n) call stdlib${ii}$_${ri}$gebak( 'B', 'L', n, ilo, ihi, work( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_i${ri}$amax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_${ri}$rot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (workspace: need n) call stdlib${ii}$_${ri}$gebak( 'B', 'R', n, ilo, ihi, work( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_i${ri}$amax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_${ri}$rot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ri}$geev #:endif #:endfor module subroutine stdlib${ii}$_cgeev( jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr,work, lwork, rwork, & !! CGEEV computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, irwork, itau, iwrk, k, lwork_trevc, & maxwrk, minwrk, nout real(sp) :: anrm, bignum, cscale, eps, scl, smlnum complex(sp) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_cgebal( 'B', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_clacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'E', 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_chseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need 2*n) irwork = ibal + n call stdlib${ii}$_ctrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork( irwork ), n, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_cgebak( 'B', 'L', n, ilo, ihi, rwork( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_scnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_csscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vl( k, i ),KIND=sp)**2_${ik}$ +aimag( vl( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_isamax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_cscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=sp), zero,KIND=sp) end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_cgebak( 'B', 'R', n, ilo, ihi, rwork( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_scnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_csscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vr( k, i ),KIND=sp)**2_${ik}$ +aimag( vr( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_isamax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_cscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=sp), zero,KIND=sp) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_cgeev module subroutine stdlib${ii}$_zgeev( jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr,work, lwork, rwork, & !! ZGEEV computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, irwork, itau, iwrk, k, lwork_trevc, & maxwrk, minwrk, nout real(dp) :: anrm, bignum, cscale, eps, scl, smlnum complex(dp) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_zgebal( 'B', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_zlacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'E', 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_zhseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need 2*n) irwork = ibal + n call stdlib${ii}$_ztrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork( irwork ), n, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_zgebak( 'B', 'L', n, ilo, ihi, rwork( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_dznrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_zdscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vl( k, i ),KIND=dp)**2_${ik}$ +aimag( vl( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_idamax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_zscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=dp), zero,KIND=dp) end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_zgebak( 'B', 'R', n, ilo, ihi, rwork( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_dznrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_zdscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vr( k, i ),KIND=dp)**2_${ik}$ +aimag( vr( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_idamax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_zscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=dp), zero,KIND=dp) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_zgeev #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$geev( jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr,work, lwork, rwork, & !! ZGEEV: computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, irwork, itau, iwrk, k, lwork_trevc, & maxwrk, minwrk, nout real(${ck}$) :: anrm, bignum, cscale, eps, scl, smlnum complex(${ck}$) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(${ck}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ci}$gebal( 'B', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_${ci}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'E', 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_${ci}$hseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need 2*n) irwork = ibal + n call stdlib${ii}$_${ci}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork( irwork ), n, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebak( 'B', 'L', n, ilo, ihi, rwork( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vl( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vl( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_${ci}$scal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=${ck}$), zero,KIND=${ck}$) end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebak( 'B', 'R', n, ilo, ihi, rwork( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vr( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vr( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_${ci}$scal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=${ck}$), zero,KIND=${ck}$) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ci}$geev #:endif #:endfor module subroutine stdlib${ii}$_sgeevx( balanc, jobvl, jobvr, sense, n, a, lda, wr, wi,vl, ldvl, vr, ldvr, & !! SGEEVX computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_sp of the LAPACK !! Users' Guide. ilo, ihi, scale, abnrm,rconde, rcondv, work, lwork, iwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(sp), intent(out) :: abnrm ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: rconde(*), rcondv(*), scale(*), vl(ldvl,*), vr(ldvr,*), wi(*),& work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(sp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ).or. & stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_sgebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_slange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (workspace: need 2*n, prefer n+n*nb) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_slacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( job, 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_shseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 3*n, prefer n + 2*n*nb) call stdlib${ii}$_strevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if ! compute condition numbers if desired ! (workspace: need n*n+6*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_strsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, iwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_sgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, work, 1_${ik}$ ) call stdlib${ii}$_slartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_srot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_sgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, work, 1_${ik}$ ) call stdlib${ii}$_slartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_srot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_sgeevx module subroutine stdlib${ii}$_dgeevx( balanc, jobvl, jobvr, sense, n, a, lda, wr, wi,vl, ldvl, vr, ldvr, & !! DGEEVX computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_dp of the LAPACK !! Users' Guide. ilo, ihi, scale, abnrm,rconde, rcondv, work, lwork, iwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(dp), intent(out) :: abnrm ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: rconde(*), rcondv(*), scale(*), vl(ldvl,*), vr(ldvr,*), wi(*),& work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(dp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ).or. & stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_dgebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_dlange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (workspace: need 2*n, prefer n+n*nb) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_dlacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( job, 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_dhseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 3*n, prefer n + 2*n*nb) call stdlib${ii}$_dtrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if ! compute condition numbers if desired ! (workspace: need n*n+6*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_dtrsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, iwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_dgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, work, 1_${ik}$ ) call stdlib${ii}$_dlartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_drot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_dgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, work, 1_${ik}$ ) call stdlib${ii}$_dlartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_drot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_dgeevx #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$geevx( balanc, jobvl, jobvr, sense, n, a, lda, wr, wi,vl, ldvl, vr, ldvr, & !! DGEEVX: computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_${rk}$ of the LAPACK !! Users' Guide. ilo, ihi, scale, abnrm,rconde, rcondv, work, lwork, iwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(${rk}$), intent(out) :: abnrm ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: rconde(*), rcondv(*), scale(*), vl(ldvl,*), vr(ldvr,*), wi(*),& work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(${rk}$) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(${rk}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ).or. & stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_${ri}$gebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_${ri}$lange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (workspace: need 2*n, prefer n+n*nb) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_${ri}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( job, 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_${ri}$hseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 3*n, prefer n + 2*n*nb) call stdlib${ii}$_${ri}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if ! compute condition numbers if desired ! (workspace: need n*n+6*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_${ri}$trsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, iwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_${ri}$gebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$lartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_${ri}$rot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_${ri}$gebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$lartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_${ri}$rot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ri}$geevx #:endif #:endfor module subroutine stdlib${ii}$_cgeevx( balanc, jobvl, jobvr, sense, n, a, lda, w, vl,ldvl, vr, ldvr, ilo, & !! CGEEVX computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_sp of the LAPACK !! Users' Guide. ihi, scale, abnrm, rconde,rcondv, work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(sp), intent(out) :: abnrm ! Array Arguments real(sp), intent(out) :: rconde(*), rcondv(*), rwork(*), scale(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(sp) :: anrm, bignum, cscale, eps, scl, smlnum complex(sp) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ) & .or.stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_cgebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_clange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_clacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( job, 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_chseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_ctrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork, n, ierr ) end if ! compute condition numbers if desired ! (cworkspace: need n*n+2*n unless sense = 'e') ! (rworkspace: need 2*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_ctrsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, rwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_cgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_scnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_csscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vl( k, i ),KIND=sp)**2_${ik}$ +aimag( vl( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, rwork, 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_cscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=sp), zero,KIND=sp) end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_cgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_scnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_csscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vr( k, i ),KIND=sp)**2_${ik}$ +aimag( vr( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, rwork, 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_cscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=sp), zero,KIND=sp) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_cgeevx module subroutine stdlib${ii}$_zgeevx( balanc, jobvl, jobvr, sense, n, a, lda, w, vl,ldvl, vr, ldvr, ilo, & !! ZGEEVX computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_dp of the LAPACK !! Users' Guide. ihi, scale, abnrm, rconde,rcondv, work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(dp), intent(out) :: abnrm ! Array Arguments real(dp), intent(out) :: rconde(*), rcondv(*), rwork(*), scale(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(dp) :: anrm, bignum, cscale, eps, scl, smlnum complex(dp) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ) & .or.stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_zgebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_zlange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_zlacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( job, 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_zhseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_ztrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork, n, ierr ) end if ! compute condition numbers if desired ! (cworkspace: need n*n+2*n unless sense = 'e') ! (rworkspace: need 2*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_ztrsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, rwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_zgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_dznrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_zdscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vl( k, i ),KIND=dp)**2_${ik}$ +aimag( vl( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, rwork, 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_zscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=dp), zero,KIND=dp) end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_zgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_dznrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_zdscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vr( k, i ),KIND=dp)**2_${ik}$ +aimag( vr( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, rwork, 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_zscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=dp), zero,KIND=dp) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_zgeevx #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$geevx( balanc, jobvl, jobvr, sense, n, a, lda, w, vl,ldvl, vr, ldvr, ilo, & !! ZGEEVX: computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_${ck}$ of the LAPACK !! Users' Guide. ihi, scale, abnrm, rconde,rcondv, work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(${ck}$), intent(out) :: abnrm ! Array Arguments real(${ck}$), intent(out) :: rconde(*), rcondv(*), rwork(*), scale(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(${ck}$) :: anrm, bignum, cscale, eps, scl, smlnum complex(${ck}$) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(${ck}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ) & .or.stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_${ci}$gebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_${ci}$lange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_${ci}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( job, 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_${ci}$hseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork, n, ierr ) end if ! compute condition numbers if desired ! (cworkspace: need n*n+2*n unless sense = 'e') ! (rworkspace: need 2*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_${ci}$trsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, rwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_${ci}$gebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vl( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vl( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork, 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_${ci}$scal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=${ck}$), zero,KIND=${ck}$) end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_${ci}$gebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vr( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vr( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork, 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_${ci}$scal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=${ck}$), zero,KIND=${ck}$) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ci}$geevx #:endif #:endfor module subroutine stdlib${ii}$_sgees( jobvs, sort, select, n, a, lda, sdim, wr, wi,vs, ldvs, work, lwork, & !! SGEES computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A matrix is in real Schur form if it is upper quasi-triangular with !! 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the !! form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_s) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, maxwrk, minwrk real(sp) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_sgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (workspace: none needed) call stdlib${ii}$_strsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, s, sep, & work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,icond ) if( icond>0_${ik}$ )info = n + icond end if if( wantvs ) then ! undo balancing ! (workspace: need n) call stdlib${ii}$_sgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_scopy( n, a, lda+1, wr, 1_${ik}$ ) if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi,max( ilo-1, 1_${ik}$ ), & ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i1_${ik}$ )call stdlib${ii}$_sswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_sswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_sswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if ! undo scaling for the imaginary part of the eigenvalues call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_sgees module subroutine stdlib${ii}$_dgees( jobvs, sort, select, n, a, lda, sdim, wr, wi,vs, ldvs, work, lwork, & !! DGEES computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A matrix is in real Schur form if it is upper quasi-triangular with !! 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the !! form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_d) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, maxwrk, minwrk real(dp) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_dgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (workspace: none needed) call stdlib${ii}$_dtrsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, s, sep, & work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,icond ) if( icond>0_${ik}$ )info = n + icond end if if( wantvs ) then ! undo balancing ! (workspace: need n) call stdlib${ii}$_dgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_dcopy( n, a, lda+1, wr, 1_${ik}$ ) if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi,max( ilo-1, 1_${ik}$ ), & ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i1_${ik}$ )call stdlib${ii}$_dswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_dswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_dswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if ! undo scaling for the imaginary part of the eigenvalues call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_dgees #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$gees( jobvs, sort, select, n, a, lda, sdim, wr, wi,vs, ldvs, work, lwork, & !! DGEES: computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A matrix is in real Schur form if it is upper quasi-triangular with !! 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the !! form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_${ri}$) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, maxwrk, minwrk real(${rk}$) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(${rk}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ri}$gebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (workspace: none needed) call stdlib${ii}$_${ri}$trsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, s, sep, & work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,icond ) if( icond>0_${ik}$ )info = n + icond end if if( wantvs ) then ! undo balancing ! (workspace: need n) call stdlib${ii}$_${ri}$gebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ri}$copy( n, a, lda+1, wr, 1_${ik}$ ) if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi,max( ilo-1, 1_${ik}$ ), & ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i1_${ik}$ )call stdlib${ii}$_${ri}$swap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_${ri}$swap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_${ri}$swap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if ! undo scaling for the imaginary part of the eigenvalues call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ri}$gees #:endif #:endfor module subroutine stdlib${ii}$_cgees( jobvs, sort, select, n, a, lda, sdim, w, vs,ldvs, work, lwork, & !! CGEES computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A complex matrix is in Schur form if it is upper triangular. rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_c) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, maxwrk, & minwrk real(sp) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_cgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (cworkspace: none) ! (rworkspace: none) call stdlib${ii}$_ctrsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,s, sep, work( & iwrk ), lwork-iwrk+1, icond ) end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_cgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_ccopy( n, a, lda+1, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_cgees module subroutine stdlib${ii}$_zgees( jobvs, sort, select, n, a, lda, sdim, w, vs,ldvs, work, lwork, & !! ZGEES computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A complex matrix is in Schur form if it is upper triangular. rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_z) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, maxwrk, & minwrk real(dp) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_zgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (cworkspace: none) ! (rworkspace: none) call stdlib${ii}$_ztrsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,s, sep, work( & iwrk ), lwork-iwrk+1, icond ) end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_zgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_zcopy( n, a, lda+1, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_zgees #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$gees( jobvs, sort, select, n, a, lda, sdim, w, vs,ldvs, work, lwork, & !! ZGEES: computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A complex matrix is in Schur form if it is upper triangular. rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_${ci}$) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, maxwrk, & minwrk real(${ck}$) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays real(${ck}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ci}$gebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (cworkspace: none) ! (rworkspace: none) call stdlib${ii}$_${ci}$trsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,s, sep, work( & iwrk ), lwork-iwrk+1, icond ) end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ci}$copy( n, a, lda+1, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ci}$gees #:endif #:endfor module subroutine stdlib${ii}$_sgeesx( jobvs, sort, select, sense, n, a, lda, sdim,wr, wi, vs, ldvs, & !! SGEESX computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_sp of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A real matrix is in real Schur form if it is upper quasi-triangular !! with 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in !! the form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). rconde, rcondv, work, lwork,iwork, liwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, liwork, lwork, n real(sp), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_s) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantsb, wantse, wantsn, wantst, & wantsv, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, lwrk, liwrk, maxwrk, minwrk real(sp) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_sgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (rworkspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (rworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (rworkspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (rworkspace: if sense is not 'n', need n+2*sdim*(n-sdim) ! otherwise, need n ) ! (iworkspace: if sense is 'v' or 'b', need sdim*(n-sdim) ! otherwise, need 0 ) call stdlib${ii}$_strsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, rconde, & rcondv, work( iwrk ), lwork-iwrk+1,iwork, liwork, icond ) if( .not.wantsn )maxwrk = max( maxwrk, n+2*sdim*( n-sdim ) ) if( icond==-15_${ik}$ ) then ! not enough real workspace info = -16_${ik}$ else if( icond==-17_${ik}$ ) then ! not enough integer workspace info = -18_${ik}$ else if( icond>0_${ik}$ ) then ! stdlib${ii}$_strsen failed to reorder or to restore standard schur form info = icond + n end if end if if( wantvs ) then ! undo balancing ! (rworkspace: need n) call stdlib${ii}$_sgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_scopy( n, a, lda+1, wr, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i1_${ik}$ )call stdlib${ii}$_sswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_sswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_sswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk if( wantsv .or. wantsb ) then iwork( 1_${ik}$ ) = sdim*(n-sdim) else iwork( 1_${ik}$ ) = 1_${ik}$ end if return end subroutine stdlib${ii}$_sgeesx module subroutine stdlib${ii}$_dgeesx( jobvs, sort, select, sense, n, a, lda, sdim,wr, wi, vs, ldvs, & !! DGEESX computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_dp of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A real matrix is in real Schur form if it is upper quasi-triangular !! with 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in !! the form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). rconde, rcondv, work, lwork,iwork, liwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, liwork, lwork, n real(dp), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_d) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantsb, wantse, wantsn, wantst, & wantsv, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, liwrk, lwrk, maxwrk, minwrk real(dp) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_dgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (rworkspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (rworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (rworkspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (rworkspace: if sense is not 'n', need n+2*sdim*(n-sdim) ! otherwise, need n ) ! (iworkspace: if sense is 'v' or 'b', need sdim*(n-sdim) ! otherwise, need 0 ) call stdlib${ii}$_dtrsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, rconde, & rcondv, work( iwrk ), lwork-iwrk+1,iwork, liwork, icond ) if( .not.wantsn )maxwrk = max( maxwrk, n+2*sdim*( n-sdim ) ) if( icond==-15_${ik}$ ) then ! not enough real workspace info = -16_${ik}$ else if( icond==-17_${ik}$ ) then ! not enough integer workspace info = -18_${ik}$ else if( icond>0_${ik}$ ) then ! stdlib${ii}$_dtrsen failed to reorder or to restore standard schur form info = icond + n end if end if if( wantvs ) then ! undo balancing ! (rworkspace: need n) call stdlib${ii}$_dgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_dcopy( n, a, lda+1, wr, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i1_${ik}$ )call stdlib${ii}$_dswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_dswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_dswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk if( wantsv .or. wantsb ) then iwork( 1_${ik}$ ) = max( 1_${ik}$, sdim*( n-sdim ) ) else iwork( 1_${ik}$ ) = 1_${ik}$ end if return end subroutine stdlib${ii}$_dgeesx #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$geesx( jobvs, sort, select, sense, n, a, lda, sdim,wr, wi, vs, ldvs, & !! DGEESX: computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_${rk}$ of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A real matrix is in real Schur form if it is upper quasi-triangular !! with 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in !! the form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). rconde, rcondv, work, lwork,iwork, liwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, liwork, lwork, n real(${rk}$), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_${ri}$) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantsb, wantse, wantsn, wantst, & wantsv, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, liwrk, lwrk, maxwrk, minwrk real(${rk}$) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(${rk}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ri}$gebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (rworkspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (rworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (rworkspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (rworkspace: if sense is not 'n', need n+2*sdim*(n-sdim) ! otherwise, need n ) ! (iworkspace: if sense is 'v' or 'b', need sdim*(n-sdim) ! otherwise, need 0 ) call stdlib${ii}$_${ri}$trsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, rconde, & rcondv, work( iwrk ), lwork-iwrk+1,iwork, liwork, icond ) if( .not.wantsn )maxwrk = max( maxwrk, n+2*sdim*( n-sdim ) ) if( icond==-15_${ik}$ ) then ! not enough real workspace info = -16_${ik}$ else if( icond==-17_${ik}$ ) then ! not enough integer workspace info = -18_${ik}$ else if( icond>0_${ik}$ ) then ! stdlib${ii}$_${ri}$trsen failed to reorder or to restore standard schur form info = icond + n end if end if if( wantvs ) then ! undo balancing ! (rworkspace: need n) call stdlib${ii}$_${ri}$gebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ri}$copy( n, a, lda+1, wr, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i1_${ik}$ )call stdlib${ii}$_${ri}$swap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_${ri}$swap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_${ri}$swap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk if( wantsv .or. wantsb ) then iwork( 1_${ik}$ ) = max( 1_${ik}$, sdim*( n-sdim ) ) else iwork( 1_${ik}$ ) = 1_${ik}$ end if return end subroutine stdlib${ii}$_${ri}$geesx #:endif #:endfor module subroutine stdlib${ii}$_cgeesx( jobvs, sort, select, sense, n, a, lda, sdim, w,vs, ldvs, rconde, & !! CGEESX computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_sp of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A complex matrix is in Schur form if it is upper triangular. rcondv, work, lwork, rwork,bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n real(sp), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_c) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantsb, wantse, wantsn, wantst, wantsv, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, lwrk, & maxwrk, minwrk real(sp) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_cgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (cworkspace: if sense is not 'n', need 2*sdim*(n-sdim) ! otherwise, need none ) ! (rworkspace: none) call stdlib${ii}$_ctrsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,rconde, & rcondv, work( iwrk ), lwork-iwrk+1,icond ) if( .not.wantsn )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( icond==-14_${ik}$ ) then ! not enough complex workspace info = -15_${ik}$ end if end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_cgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_ccopy( n, a, lda+1, w, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_cgeesx module subroutine stdlib${ii}$_zgeesx( jobvs, sort, select, sense, n, a, lda, sdim, w,vs, ldvs, rconde, & !! ZGEESX computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_dp of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A complex matrix is in Schur form if it is upper triangular. rcondv, work, lwork, rwork,bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n real(dp), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_z) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantsb, wantse, wantsn, wantst, wantsv, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, lwrk, & maxwrk, minwrk real(dp) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_zgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (cworkspace: if sense is not 'n', need 2*sdim*(n-sdim) ! otherwise, need none ) ! (rworkspace: none) call stdlib${ii}$_ztrsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,rconde, & rcondv, work( iwrk ), lwork-iwrk+1,icond ) if( .not.wantsn )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( icond==-14_${ik}$ ) then ! not enough complex workspace info = -15_${ik}$ end if end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_zgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_zcopy( n, a, lda+1, w, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_zgeesx #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$geesx( jobvs, sort, select, sense, n, a, lda, sdim, w,vs, ldvs, rconde, & !! ZGEESX: computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_${ck}$ of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A complex matrix is in Schur form if it is upper triangular. rcondv, work, lwork, rwork,bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n real(${ck}$), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_${ci}$) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantsb, wantse, wantsn, wantst, wantsv, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, lwrk, & maxwrk, minwrk real(${ck}$) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(${ck}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ci}$gebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (cworkspace: if sense is not 'n', need 2*sdim*(n-sdim) ! otherwise, need none ) ! (rworkspace: none) call stdlib${ii}$_${ci}$trsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,rconde, & rcondv, work( iwrk ), lwork-iwrk+1,icond ) if( .not.wantsn )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( icond==-14_${ik}$ ) then ! not enough complex workspace info = -15_${ik}$ end if end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ci}$copy( n, a, lda+1, w, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ci}$geesx #:endif #:endfor module subroutine stdlib${ii}$_sggev3( jobvl, jobvr, n, a, lda, b, ldb, alphar,alphai, beta, vl, ldvl, vr,& !! SGGEV3 computes for a pair of N-by-N real nonsymmetric matrices (A,B) !! the generalized eigenvalues, and optionally, the left and/or right !! generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B . !! where u(j)**H is the conjugate-transpose of u(j). ldvr, work, lwork,info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, & iwrk, jc, jr, lwkopt real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldazero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_sorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_sgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk, ierr ) else call stdlib${ii}$_sgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_slaqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_stgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )zero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_dorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_dgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk, ierr ) else call stdlib${ii}$_dgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_dlaqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_dtgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )zero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ri}$gghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk, ierr ) else call stdlib${ii}$_${ri}$gghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ri}$laqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ri}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )zero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_cungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_cgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk,ierr ) else call stdlib${ii}$_cgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_claqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ctgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( tempzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_zungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_zgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk, ierr ) else call stdlib${ii}$_zgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_zlaqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ztgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( tempzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ci}$gghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk, ierr ) else call stdlib${ii}$_${ci}$gghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ci}$laqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ci}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( tempzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_sorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_sgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_sgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_shgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors ! (workspace: need 6*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_stgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )zero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_dorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_dgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_dgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_dhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors ! (workspace: need 6*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_dtgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )zero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ri}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_${ri}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ri}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors ! (workspace: need 6*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ri}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )zero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (complex workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_cungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_cgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_cgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_chgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors ! (real workspace: need 2*n) ! (complex workspace: need 2*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ctgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( tempzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (complex workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_zungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_zgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_zgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_zhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors ! (real workspace: need 2*n) ! (complex workspace: need 2*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ztgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( tempzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (complex workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ci}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_${ci}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ci}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors ! (real workspace: need 2*n) ! (complex workspace: need 2*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ci}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( tempzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_sggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,work, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_slange( '1', n, n, a, lda, work( 1_${ik}$ ) ) if( ilascl ) then work( 1_${ik}$ ) = abnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = work( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_slange( '1', n, n, b, ldb, work( 1_${ik}$ ) ) if( ilbscl ) then work( 1_${ik}$ ) = bbnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = work( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_sorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_sgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_sgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_shgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr, work,lwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 130 end if ! compute eigenvectors and estimate condition numbers if desired ! (workspace: stdlib${ii}$_stgevc: need 6*n ! stdlib${ii}$_stgsna: need 2*n*(n+2)+16 if sense = 'v' or 'b', ! need n otherwise ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_stgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 130 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_stgevc) and estimate condition ! numbers (stdlib${ii}$_stgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to recalculate ! eigenvectors and estimate one condition numbers at a time. pair = .false. loop_20: do i = 1, n if( pair ) then pair = .false. cycle loop_20 end if mm = 1_${ik}$ if( izero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_dggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,work, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_dlange( '1', n, n, a, lda, work( 1_${ik}$ ) ) if( ilascl ) then work( 1_${ik}$ ) = abnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = work( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_dlange( '1', n, n, b, ldb, work( 1_${ik}$ ) ) if( ilbscl ) then work( 1_${ik}$ ) = bbnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = work( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_dorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_dgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_dgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_dhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr, work,lwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 130 end if ! compute eigenvectors and estimate condition numbers if desired ! (workspace: stdlib${ii}$_dtgevc: need 6*n ! stdlib${ii}$_dtgsna: need 2*n*(n+2)+16 if sense = 'v' or 'b', ! need n otherwise ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_dtgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 130 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_dtgevc) and estimate condition ! numbers (stdlib${ii}$_dtgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to recalculate ! eigenvectors and estimate one condition numbers at a time. pair = .false. loop_20: do i = 1, n if( pair ) then pair = .false. cycle loop_20 end if mm = 1_${ik}$ if( izero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_${ri}$ggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,work, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_${ri}$lange( '1', n, n, a, lda, work( 1_${ik}$ ) ) if( ilascl ) then work( 1_${ik}$ ) = abnrm call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = work( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_${ri}$lange( '1', n, n, b, ldb, work( 1_${ik}$ ) ) if( ilbscl ) then work( 1_${ik}$ ) = bbnrm call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = work( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ri}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_${ri}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ri}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr, work,lwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 130 end if ! compute eigenvectors and estimate condition numbers if desired ! (workspace: stdlib${ii}$_${ri}$tgevc: need 6*n ! stdlib${ii}$_${ri}$tgsna: need 2*n*(n+2)+16 if sense = 'v' or 'b', ! need n otherwise ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ri}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 130 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_${ri}$tgevc) and estimate condition ! numbers (stdlib${ii}$_${ri}$tgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to recalculate ! eigenvectors and estimate one condition numbers at a time. pair = .false. loop_20: do i = 1, n if( pair ) then pair = .false. cycle loop_20 end if mm = 1_${ik}$ if( izero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (real workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_cggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,rwork, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_clange( '1', n, n, a, lda, rwork( 1_${ik}$ ) ) if( ilascl ) then rwork( 1_${ik}$ ) = abnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = rwork( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_clange( '1', n, n, b, ldb, rwork( 1_${ik}$ ) ) if( ilbscl ) then rwork( 1_${ik}$ ) = bbnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = rwork( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the unitary transformation to a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_cungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_cgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_cgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_chgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 90 end if ! compute eigenvectors and estimate condition numbers if desired ! stdlib${ii}$_ctgevc: (complex workspace: need 2*n ) ! (real workspace: need 2*n ) ! stdlib${ii}$_ctgsna: (complex workspace: need 2*n*n if sense='v' or 'b') ! (integer workspace: need n+2 ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ctgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work( iwrk ), rwork,ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_ctgevc) and estimate condition ! numbers (stdlib${ii}$_ctgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to ! re-calculate eigenvectors and estimate the condition numbers ! one at a time. do i = 1, n do j = 1, n bwork( j ) = .false. end do bwork( i ) = .true. iwrk = n + 1_${ik}$ iwrk1 = iwrk + n if( wantse .or. wantsb ) then call stdlib${ii}$_ctgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, 1_${ik}$, m,work( iwrk1 ), rwork, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if call stdlib${ii}$_ctgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, rconde( i ),rcondv( i ), 1_${ik}$, m, work( iwrk1 ),lwork-iwrk1+1, iwork, & ierr ) end do end if end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_cggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr ) loop_50: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( tempzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (real workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_zggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,rwork, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_zlange( '1', n, n, a, lda, rwork( 1_${ik}$ ) ) if( ilascl ) then rwork( 1_${ik}$ ) = abnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = rwork( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_zlange( '1', n, n, b, ldb, rwork( 1_${ik}$ ) ) if( ilbscl ) then rwork( 1_${ik}$ ) = bbnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = rwork( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the unitary transformation to a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_zungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_zgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_zgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_zhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 90 end if ! compute eigenvectors and estimate condition numbers if desired ! stdlib${ii}$_ztgevc: (complex workspace: need 2*n ) ! (real workspace: need 2*n ) ! stdlib${ii}$_ztgsna: (complex workspace: need 2*n*n if sense='v' or 'b') ! (integer workspace: need n+2 ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ztgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work( iwrk ), rwork,ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_ztgevc) and estimate condition ! numbers (stdlib${ii}$_ztgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to ! re-calculate eigenvectors and estimate the condition numbers ! one at a time. do i = 1, n do j = 1, n bwork( j ) = .false. end do bwork( i ) = .true. iwrk = n + 1_${ik}$ iwrk1 = iwrk + n if( wantse .or. wantsb ) then call stdlib${ii}$_ztgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, 1_${ik}$, m,work( iwrk1 ), rwork, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if call stdlib${ii}$_ztgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, rconde( i ),rcondv( i ), 1_${ik}$, m, work( iwrk1 ),lwork-iwrk1+1, iwork, & ierr ) end do end if end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_zggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr ) loop_50: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( tempzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (real workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_${ci}$ggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,rwork, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_${ci}$lange( '1', n, n, a, lda, rwork( 1_${ik}$ ) ) if( ilascl ) then rwork( 1_${ik}$ ) = abnrm call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = rwork( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_${ci}$lange( '1', n, n, b, ldb, rwork( 1_${ik}$ ) ) if( ilbscl ) then rwork( 1_${ik}$ ) = bbnrm call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = rwork( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the unitary transformation to a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ci}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_${ci}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ci}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 90 end if ! compute eigenvectors and estimate condition numbers if desired ! stdlib${ii}$_${ci}$tgevc: (complex workspace: need 2*n ) ! (real workspace: need 2*n ) ! stdlib${ii}$_${ci}$tgsna: (complex workspace: need 2*n*n if sense='v' or 'b') ! (integer workspace: need n+2 ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ci}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work( iwrk ), rwork,ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_${ci}$tgevc) and estimate condition ! numbers (stdlib${ii}$_${ci}$tgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to ! re-calculate eigenvectors and estimate the condition numbers ! one at a time. do i = 1, n do j = 1, n bwork( j ) = .false. end do bwork( i ) = .true. iwrk = n + 1_${ik}$ iwrk1 = iwrk + n if( wantse .or. wantsb ) then call stdlib${ii}$_${ci}$tgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, 1_${ik}$, m,work( iwrk1 ), rwork, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if call stdlib${ii}$_${ci}$tgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, rconde( i ),rcondv( i ), 1_${ik}$, m, work( iwrk1 ),lwork-iwrk1+1, iwork, & ierr ) end do end if end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_${ci}$ggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr ) loop_50: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( tempzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl if( ilvsl ) then call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_sorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form call stdlib${ii}$_sgghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& work( iwrk ), lwork+1-iwrk, ierr ) ! perform qz algorithm, computing schur vectors if desired iwrk = itau call stdlib${ii}$_slaqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 40 end if ! sort eigenvalues alpha/beta if desired sdim = 0_${ik}$ if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do call stdlib${ii}$_stgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, & vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,& ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr if( ilvsl )call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_sggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl )then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i )/safmax )>( anrmto/anrm ) .or.( safmin/alphar( i ) )>( & anrm/anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i )/alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i )/safmax )>( anrmto/anrm ) .or.( safmin/alphai( i ) )>( & anrm/anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i+1 )/alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl )then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i )/safmax )>( bnrmto/bnrm ) .or.( safmin/beta( i ) )>( & bnrm/bnrmto ) ) then work( 1_${ik}$ ) = abs(b( i, i )/beta( i )) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_slascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_sgges3 module subroutine stdlib${ii}$_dgges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alphar, & !! DGGES3 computes for a pair of N-by-N real nonsymmetric matrices (A,B), !! the generalized eigenvalues, the generalized real Schur form (S,T), !! optionally, the left and/or right matrices of Schur vectors (VSL and !! VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T ) !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! quasi-triangular matrix S and the upper triangular matrix T.The !! leading columns of VSL and VSR then form an orthonormal basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! DGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or both being zero. !! A pair of matrices (S,T) is in generalized real Schur form if T is !! upper triangular with non-negative diagonal and S is block upper !! triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond !! to real generalized eigenvalues, while 2-by-2 blocks of S will be !! "standardized" by making the corresponding elements of T have the !! form: !! [ a 0 ] !! [ 0 b ] !! and the pair of corresponding 2-by-2 blocks in S and T will have a !! complex conjugate pair of generalized eigenvalues. alphai, beta, vsl, ldvsl,vsr, ldvsr, work, lwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), & work(*) ! Function Arguments procedure(stdlib_selctg_d) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, & wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, & itau, iwrk, lwkopt real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, & smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(dp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl if( ilvsl ) then call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_dorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form call stdlib${ii}$_dgghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& work( iwrk ), lwork+1-iwrk,ierr ) ! perform qz algorithm, computing schur vectors if desired iwrk = itau call stdlib${ii}$_dlaqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 50 end if ! sort eigenvalues alpha/beta if desired sdim = 0_${ik}$ if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do call stdlib${ii}$_dtgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, & vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,& ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr if( ilvsl )call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_dggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( & anrm / anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )& )>( anrm / anrmto ) )then work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( & bnrm / bnrmto ) ) then work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_dlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 50 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dgges3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$gges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alphar, & !! DGGES3: computes for a pair of N-by-N real nonsymmetric matrices (A,B), !! the generalized eigenvalues, the generalized real Schur form (S,T), !! optionally, the left and/or right matrices of Schur vectors (VSL and !! VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T ) !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! quasi-triangular matrix S and the upper triangular matrix T.The !! leading columns of VSL and VSR then form an orthonormal basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! DGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or both being zero. !! A pair of matrices (S,T) is in generalized real Schur form if T is !! upper triangular with non-negative diagonal and S is block upper !! triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond !! to real generalized eigenvalues, while 2-by-2 blocks of S will be !! "standardized" by making the corresponding elements of T have the !! form: !! [ a 0 ] !! [ 0 b ] !! and the pair of corresponding 2-by-2 blocks in S and T will have a !! complex conjugate pair of generalized eigenvalues. alphai, beta, vsl, ldvsl,vsr, ldvsr, work, lwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), & work(*) ! Function Arguments procedure(stdlib_selctg_${ri}$) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, & wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, & itau, iwrk, lwkopt real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, & smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(${rk}$) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl if( ilvsl ) then call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form call stdlib${ii}$_${ri}$gghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& work( iwrk ), lwork+1-iwrk,ierr ) ! perform qz algorithm, computing schur vectors if desired iwrk = itau call stdlib${ii}$_${ri}$laqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 50 end if ! sort eigenvalues alpha/beta if desired sdim = 0_${ik}$ if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do call stdlib${ii}$_${ri}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, & vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,& ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr if( ilvsl )call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_${ri}$ggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( & anrm / anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )& )>( anrm / anrmto ) )then work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( & bnrm / bnrmto ) ) then work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_${ri}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 50 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$gges3 #:endif #:endfor module subroutine stdlib${ii}$_cgges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alpha, beta, & !! CGGES3 computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, the generalized complex Schur !! form (S, T), and optionally left and/or right Schur vectors (VSL !! and VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H ) !! where (VSR)**H is the conjugate-transpose of VSR. !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! triangular matrix S and the upper triangular matrix T. The leading !! columns of VSL and VSR then form an unitary basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! CGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0, and even for both being zero. !! A pair of matrices (S,T) is in generalized complex Schur form if S !! and T are upper triangular and, in addition, the diagonal elements !! of T are non-negative real numbers. vsl, ldvsl, vsr, ldvsr,work, lwork, rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_c) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, & itau, iwrk, lwkopt real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(sp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl if( ilvsl ) then call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_cungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsr, ldvsr ) ! reduce to generalized hessenberg form call stdlib${ii}$_cgghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& work( iwrk ), lwork+1-iwrk, ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired iwrk = itau call stdlib${ii}$_claqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 30 end if ! sort eigenvalues alpha/beta if desired if( wantst ) then ! undo scaling on eigenvalues before selecting if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alpha( i ), beta( i ) ) end do call stdlib${ii}$_ctgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, & ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr if( ilvsl )call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_cggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsr, ldvsr, ierr ) ! undo scaling if( ilascl ) then call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. sdim = 0_${ik}$ do i = 1, n cursl = selctg( alpha( i ), beta( i ) ) if( cursl )sdim = sdim + 1_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ lastsl = cursl end do end if 30 continue work( 1_${ik}$ ) = cmplx( lwkopt,KIND=sp) return end subroutine stdlib${ii}$_cgges3 module subroutine stdlib${ii}$_zgges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alpha, beta, & !! ZGGES3 computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, the generalized complex Schur !! form (S, T), and optionally left and/or right Schur vectors (VSL !! and VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H ) !! where (VSR)**H is the conjugate-transpose of VSR. !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! triangular matrix S and the upper triangular matrix T. The leading !! columns of VSL and VSR then form an unitary basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! ZGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0, and even for both being zero. !! A pair of matrices (S,T) is in generalized complex Schur form if S !! and T are upper triangular and, in addition, the diagonal elements !! of T are non-negative real numbers. vsl, ldvsl, vsr, ldvsr,work, lwork, rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_z) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, & itau, iwrk, lwkopt real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(dp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl if( ilvsl ) then call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_zungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsr, ldvsr ) ! reduce to generalized hessenberg form call stdlib${ii}$_zgghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& work( iwrk ), lwork+1-iwrk, ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired iwrk = itau call stdlib${ii}$_zlaqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 30 end if ! sort eigenvalues alpha/beta if desired if( wantst ) then ! undo scaling on eigenvalues before selecting if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alpha( i ), beta( i ) ) end do call stdlib${ii}$_ztgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, & ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr if( ilvsl )call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_zggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsr, ldvsr, ierr ) ! undo scaling if( ilascl ) then call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. sdim = 0_${ik}$ do i = 1, n cursl = selctg( alpha( i ), beta( i ) ) if( cursl )sdim = sdim + 1_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ lastsl = cursl end do end if 30 continue work( 1_${ik}$ ) = cmplx( lwkopt,KIND=dp) return end subroutine stdlib${ii}$_zgges3 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$gges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alpha, beta, & !! ZGGES3: computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, the generalized complex Schur !! form (S, T), and optionally left and/or right Schur vectors (VSL !! and VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H ) !! where (VSR)**H is the conjugate-transpose of VSR. !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! triangular matrix S and the upper triangular matrix T. The leading !! columns of VSL and VSR then form an unitary basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! ZGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0, and even for both being zero. !! A pair of matrices (S,T) is in generalized complex Schur form if S !! and T are upper triangular and, in addition, the diagonal elements !! of T are non-negative real numbers. vsl, ldvsl, vsr, ldvsr,work, lwork, rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_${ci}$) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, & itau, iwrk, lwkopt real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(${ck}$) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl if( ilvsl ) then call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsr, ldvsr ) ! reduce to generalized hessenberg form call stdlib${ii}$_${ci}$gghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& work( iwrk ), lwork+1-iwrk, ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired iwrk = itau call stdlib${ii}$_${ci}$laqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 30 end if ! sort eigenvalues alpha/beta if desired if( wantst ) then ! undo scaling on eigenvalues before selecting if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alpha( i ), beta( i ) ) end do call stdlib${ii}$_${ci}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, & ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr if( ilvsl )call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_${ci}$ggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsr, ldvsr, ierr ) ! undo scaling if( ilascl ) then call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. sdim = 0_${ik}$ do i = 1, n cursl = selctg( alpha( i ), beta( i ) ) if( cursl )sdim = sdim + 1_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ lastsl = cursl end do end if 30 continue work( 1_${ik}$ ) = cmplx( lwkopt,KIND=${ck}$) return end subroutine stdlib${ii}$_${ci}$gges3 #:endif #:endfor module subroutine stdlib${ii}$_sgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alphar, & !! SGGES computes for a pair of N-by-N real nonsymmetric matrices (A,B), !! the generalized eigenvalues, the generalized real Schur form (S,T), !! optionally, the left and/or right matrices of Schur vectors (VSL and !! VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T ) !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! quasi-triangular matrix S and the upper triangular matrix T.The !! leading columns of VSL and VSR then form an orthonormal basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! SGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or both being zero. !! A pair of matrices (S,T) is in generalized real Schur form if T is !! upper triangular with non-negative diagonal and S is block upper !! triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond !! to real generalized eigenvalues, while 2-by-2 blocks of S will be !! "standardized" by making the corresponding elements of T have the !! form: !! [ a 0 ] !! [ 0 b ] !! and the pair of corresponding 2-by-2 blocks in S and T will have a !! complex conjugate pair of generalized eigenvalues. alphai, beta, vsl, ldvsl, vsr,ldvsr, work, lwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), & work(*) ! Function Arguments procedure(stdlib_selctg_s) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, & wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, & itau, iwrk, maxwrk, minwrk real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, & smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(sp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda0_${ik}$ )then minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ ) maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ & ) ) if( ilvsl ) then maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORGQR', ' ', n, 1_${ik}$, n, & -1_${ik}$ ) ) end if else minwrk = 1_${ik}$ maxwrk = 1_${ik}$ end if work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need 6*n + 2*n space for storing balancing factors) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_sorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_sgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) ! perform qz algorithm, computing schur vectors if desired ! (workspace: need n) iwrk = itau call stdlib${ii}$_shgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 40 end if ! sort eigenvalues alpha/beta if desired ! (workspace: need 4*n+16 ) sdim = 0_${ik}$ if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do call stdlib${ii}$_stgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, & vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,& ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_sggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl )then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i )/safmax )>( anrmto/anrm ) .or.( safmin/alphar( i ) )>( & anrm/anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i )/alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i )/safmax )>( anrmto/anrm ) .or.( safmin/alphai( i ) )>( & anrm/anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i+1 )/alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl )then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i )/safmax )>( bnrmto/bnrm ) .or.( safmin/beta( i ) )>( & bnrm/bnrmto ) ) then work( 1_${ik}$ ) = abs(b( i, i )/beta( i )) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_slascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 40 continue work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_sgges module subroutine stdlib${ii}$_dgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alphar, & !! DGGES computes for a pair of N-by-N real nonsymmetric matrices (A,B), !! the generalized eigenvalues, the generalized real Schur form (S,T), !! optionally, the left and/or right matrices of Schur vectors (VSL and !! VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T ) !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! quasi-triangular matrix S and the upper triangular matrix T.The !! leading columns of VSL and VSR then form an orthonormal basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! DGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or both being zero. !! A pair of matrices (S,T) is in generalized real Schur form if T is !! upper triangular with non-negative diagonal and S is block upper !! triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond !! to real generalized eigenvalues, while 2-by-2 blocks of S will be !! "standardized" by making the corresponding elements of T have the !! form: !! [ a 0 ] !! [ 0 b ] !! and the pair of corresponding 2-by-2 blocks in S and T will have a !! complex conjugate pair of generalized eigenvalues. alphai, beta, vsl, ldvsl, vsr,ldvsr, work, lwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), & work(*) ! Function Arguments procedure(stdlib_selctg_d) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, & wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, & itau, iwrk, maxwrk, minwrk real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, & smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(dp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda0_${ik}$ )then minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ ) maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ & ) ) if( ilvsl ) then maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, & -1_${ik}$ ) ) end if else minwrk = 1_${ik}$ maxwrk = 1_${ik}$ end if work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need 6*n + 2*n space for storing balancing factors) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_dorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_dgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) ! perform qz algorithm, computing schur vectors if desired ! (workspace: need n) iwrk = itau call stdlib${ii}$_dhgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 50 end if ! sort eigenvalues alpha/beta if desired ! (workspace: need 4*n+16 ) sdim = 0_${ik}$ if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do call stdlib${ii}$_dtgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, & vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,& ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_dggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( & anrm / anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )& )>( anrm / anrmto ) )then work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( & bnrm / bnrmto ) ) then work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_dlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 50 continue work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_dgges #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$gges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alphar, & !! DGGES: computes for a pair of N-by-N real nonsymmetric matrices (A,B), !! the generalized eigenvalues, the generalized real Schur form (S,T), !! optionally, the left and/or right matrices of Schur vectors (VSL and !! VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T ) !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! quasi-triangular matrix S and the upper triangular matrix T.The !! leading columns of VSL and VSR then form an orthonormal basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! DGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or both being zero. !! A pair of matrices (S,T) is in generalized real Schur form if T is !! upper triangular with non-negative diagonal and S is block upper !! triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond !! to real generalized eigenvalues, while 2-by-2 blocks of S will be !! "standardized" by making the corresponding elements of T have the !! form: !! [ a 0 ] !! [ 0 b ] !! and the pair of corresponding 2-by-2 blocks in S and T will have a !! complex conjugate pair of generalized eigenvalues. alphai, beta, vsl, ldvsl, vsr,ldvsr, work, lwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), & work(*) ! Function Arguments procedure(stdlib_selctg_${ri}$) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, & wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, & itau, iwrk, maxwrk, minwrk real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, & smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(${rk}$) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda0_${ik}$ )then minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ ) maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ & ) ) if( ilvsl ) then maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, & -1_${ik}$ ) ) end if else minwrk = 1_${ik}$ maxwrk = 1_${ik}$ end if work( 1_${ik}$ ) = maxwrk if( lworkzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need 6*n + 2*n space for storing balancing factors) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_${ri}$gghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) ! perform qz algorithm, computing schur vectors if desired ! (workspace: need n) iwrk = itau call stdlib${ii}$_${ri}$hgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 50 end if ! sort eigenvalues alpha/beta if desired ! (workspace: need 4*n+16 ) sdim = 0_${ik}$ if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do call stdlib${ii}$_${ri}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, & vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,& ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_${ri}$ggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( & anrm / anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )& )>( anrm / anrmto ) )then work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( & bnrm / bnrmto ) ) then work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_${ri}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 50 continue work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ri}$gges #:endif #:endfor module subroutine stdlib${ii}$_cgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alpha, beta, & !! CGGES computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, the generalized complex Schur !! form (S, T), and optionally left and/or right Schur vectors (VSL !! and VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H ) !! where (VSR)**H is the conjugate-transpose of VSR. !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! triangular matrix S and the upper triangular matrix T. The leading !! columns of VSL and VSR then form an unitary basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! CGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0, and even for both being zero. !! A pair of matrices (S,T) is in generalized complex Schur form if S !! and T are upper triangular and, in addition, the diagonal elements !! of T are non-negative real numbers. vsl, ldvsl, vsr, ldvsr, work,lwork, rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_c) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, & itau, iwrk, lwkmin, lwkopt real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(sp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (complex workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_cungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_cgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau call stdlib${ii}$_chgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 30 end if ! sort eigenvalues alpha/beta if desired ! (workspace: none needed) if( wantst ) then ! undo scaling on eigenvalues before selecting if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alpha( i ), beta( i ) ) end do call stdlib${ii}$_ctgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, & ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_cggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsr, ldvsr, ierr ) ! undo scaling if( ilascl ) then call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. sdim = 0_${ik}$ do i = 1, n cursl = selctg( alpha( i ), beta( i ) ) if( cursl )sdim = sdim + 1_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ lastsl = cursl end do end if 30 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cgges module subroutine stdlib${ii}$_zgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alpha, beta, & !! ZGGES computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, the generalized complex Schur !! form (S, T), and optionally left and/or right Schur vectors (VSL !! and VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H ) !! where (VSR)**H is the conjugate-transpose of VSR. !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! triangular matrix S and the upper triangular matrix T. The leading !! columns of VSL and VSR then form an unitary basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! ZGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0, and even for both being zero. !! A pair of matrices (S,T) is in generalized complex Schur form if S !! and T are upper triangular and, in addition, the diagonal elements !! of T are non-negative real numbers. vsl, ldvsl, vsr, ldvsr, work,lwork, rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_z) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, & itau, iwrk, lwkmin, lwkopt real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(dp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (complex workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_zungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_zgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau call stdlib${ii}$_zhgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 30 end if ! sort eigenvalues alpha/beta if desired ! (workspace: none needed) if( wantst ) then ! undo scaling on eigenvalues before selecting if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alpha( i ), beta( i ) ) end do call stdlib${ii}$_ztgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, & ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_zggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsr, ldvsr, ierr ) ! undo scaling if( ilascl ) then call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. sdim = 0_${ik}$ do i = 1, n cursl = selctg( alpha( i ), beta( i ) ) if( cursl )sdim = sdim + 1_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ lastsl = cursl end do end if 30 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zgges #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$gges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alpha, beta, & !! ZGGES: computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, the generalized complex Schur !! form (S, T), and optionally left and/or right Schur vectors (VSL !! and VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H ) !! where (VSR)**H is the conjugate-transpose of VSR. !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! triangular matrix S and the upper triangular matrix T. The leading !! columns of VSL and VSR then form an unitary basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! ZGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0, and even for both being zero. !! A pair of matrices (S,T) is in generalized complex Schur form if S !! and T are upper triangular and, in addition, the diagonal elements !! of T are non-negative real numbers. vsl, ldvsl, vsr, ldvsr, work,lwork, rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_${ci}$) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, & itau, iwrk, lwkmin, lwkopt real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(${ck}$) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldazero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (complex workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_${ci}$gghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau call stdlib${ii}$_${ci}$hgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 30 end if ! sort eigenvalues alpha/beta if desired ! (workspace: none needed) if( wantst ) then ! undo scaling on eigenvalues before selecting if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alpha( i ), beta( i ) ) end do call stdlib${ii}$_${ci}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, & ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_${ci}$ggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsr, ldvsr, ierr ) ! undo scaling if( ilascl ) then call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. sdim = 0_${ik}$ do i = 1, n cursl = selctg( alpha( i ), beta( i ) ) if( cursl )sdim = sdim + 1_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ lastsl = cursl end do end if 30 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$gges #:endif #:endfor module subroutine stdlib${ii}$_sggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, & !! SGGESX computes for a pair of N-by-N real nonsymmetric matrices !! (A,B), the generalized eigenvalues, the real Schur form (S,T), and, !! optionally, the left and/or right matrices of Schur vectors (VSL and !! VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL) S (VSR)**T, (VSL) T (VSR)**T ) !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! quasi-triangular matrix S and the upper triangular matrix T; computes !! a reciprocal condition number for the average of the selected !! eigenvalues (RCONDE); and computes a reciprocal condition number for !! the right and left deflating subspaces corresponding to the selected !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form !! an orthonormal basis for the corresponding left and right eigenspaces !! (deflating subspaces). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or for both being zero. !! A pair of matrices (S,T) is in generalized real Schur form if T is !! upper triangular with non-negative diagonal and S is block upper !! triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond !! to real generalized eigenvalues, while 2-by-2 blocks of S will be !! "standardized" by making the corresponding elements of T have the !! form: !! [ a 0 ] !! [ 0 b ] !! and the pair of corresponding 2-by-2 blocks in S and T will have a !! complex conjugate pair of generalized eigenvalues. alphar, alphai, beta, vsl, ldvsl,vsr, ldvsr, rconde, rcondv, work, lwork, iwork,liwork, & bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: alphai(*), alphar(*), beta(*), rconde(2_${ik}$), rcondv(2_${ik}$), vsl(& ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_s) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, wantsb, & wantse, wantsn, wantst, wantsv integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, ip, iright, & irows, itau, iwrk, liwmin, lwrk, maxwrk, minwrk real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, safmax, safmin, & smlnum ! Local Arrays real(sp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( wantsn ) then ijob = 0_${ik}$ else if( wantse ) then ijob = 1_${ik}$ else if( wantsv ) then ijob = 2_${ik}$ else if( wantsb ) then ijob = 4_${ik}$ end if ! test the input arguments info = 0_${ik}$ if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda0_${ik}$) then minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ ) maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ & ) ) if( ilvsl ) then maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORGQR', ' ', n, 1_${ik}$, n, & -1_${ik}$ ) ) end if lwrk = maxwrk if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ ) else minwrk = 1_${ik}$ maxwrk = 1_${ik}$ lwrk = 1_${ik}$ end if work( 1_${ik}$ ) = lwrk if( wantsn .or. n==0_${ik}$ ) then liwmin = 1_${ik}$ else liwmin = n + 6_${ik}$ end if iwork( 1_${ik}$ ) = liwmin if( lworkzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need 6*n + 2*n for permutation parameters) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_sorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_sgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired ! (workspace: need n) iwrk = itau call stdlib${ii}$_shgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 50 end if ! sort eigenvalues alpha/beta and compute the reciprocal of ! condition number(s) ! (workspace: if ijob >= 1, need max( 8*(n+1), 2*sdim*(n-sdim) ) ! otherwise, need 8*(n+1) ) if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do ! reorder eigenvalues, transform generalized schur vectors, and ! compute reciprocal condition numbers call stdlib${ii}$_stgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,sdim, pl, pr, dif, work( iwrk ), lwork-iwrk+1,iwork, & liwork, ierr ) if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( ierr==-22_${ik}$ ) then ! not enough real workspace info = -22_${ik}$ else if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then rconde( 1_${ik}$ ) = pl rconde( 2_${ik}$ ) = pr end if if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then rcondv( 1_${ik}$ ) = dif( 1_${ik}$ ) rcondv( 2_${ik}$ ) = dif( 2_${ik}$ ) end if if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if end if ! apply permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_sggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( & anrm / anrmto ) )then work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i ) / safmax )>( anrmto / anrm ).or. ( safmin / alphai( i )& )>( anrm / anrmto ) )then work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( & bnrm / bnrmto ) ) then work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_slascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 50 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_sggesx module subroutine stdlib${ii}$_dggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, & !! DGGESX computes for a pair of N-by-N real nonsymmetric matrices !! (A,B), the generalized eigenvalues, the real Schur form (S,T), and, !! optionally, the left and/or right matrices of Schur vectors (VSL and !! VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL) S (VSR)**T, (VSL) T (VSR)**T ) !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! quasi-triangular matrix S and the upper triangular matrix T; computes !! a reciprocal condition number for the average of the selected !! eigenvalues (RCONDE); and computes a reciprocal condition number for !! the right and left deflating subspaces corresponding to the selected !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form !! an orthonormal basis for the corresponding left and right eigenspaces !! (deflating subspaces). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or for both being zero. !! A pair of matrices (S,T) is in generalized real Schur form if T is !! upper triangular with non-negative diagonal and S is block upper !! triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond !! to real generalized eigenvalues, while 2-by-2 blocks of S will be !! "standardized" by making the corresponding elements of T have the !! form: !! [ a 0 ] !! [ 0 b ] !! and the pair of corresponding 2-by-2 blocks in S and T will have a !! complex conjugate pair of generalized eigenvalues. alphar, alphai, beta, vsl, ldvsl,vsr, ldvsr, rconde, rcondv, work, lwork, iwork,liwork, & bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: alphai(*), alphar(*), beta(*), rconde(2_${ik}$), rcondv(2_${ik}$), vsl(& ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_d) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, wantsb, & wantse, wantsn, wantst, wantsv integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, ip, iright, & irows, itau, iwrk, liwmin, lwrk, maxwrk, minwrk real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, safmax, safmin, & smlnum ! Local Arrays real(dp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( wantsn ) then ijob = 0_${ik}$ else if( wantse ) then ijob = 1_${ik}$ else if( wantsv ) then ijob = 2_${ik}$ else if( wantsb ) then ijob = 4_${ik}$ end if ! test the input arguments info = 0_${ik}$ if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda0_${ik}$) then minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ ) maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ & ) ) if( ilvsl ) then maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, & -1_${ik}$ ) ) end if lwrk = maxwrk if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ ) else minwrk = 1_${ik}$ maxwrk = 1_${ik}$ lwrk = 1_${ik}$ end if work( 1_${ik}$ ) = lwrk if( wantsn .or. n==0_${ik}$ ) then liwmin = 1_${ik}$ else liwmin = n + 6_${ik}$ end if iwork( 1_${ik}$ ) = liwmin if( lworkzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need 6*n + 2*n for permutation parameters) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_dorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_dgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired ! (workspace: need n) iwrk = itau call stdlib${ii}$_dhgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 60 end if ! sort eigenvalues alpha/beta and compute the reciprocal of ! condition number(s) ! (workspace: if ijob >= 1, need max( 8*(n+1), 2*sdim*(n-sdim) ) ! otherwise, need 8*(n+1) ) if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do ! reorder eigenvalues, transform generalized schur vectors, and ! compute reciprocal condition numbers call stdlib${ii}$_dtgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,sdim, pl, pr, dif, work( iwrk ), lwork-iwrk+1,iwork, & liwork, ierr ) if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( ierr==-22_${ik}$ ) then ! not enough real workspace info = -22_${ik}$ else if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then rconde( 1_${ik}$ ) = pl rconde( 2_${ik}$ ) = pr end if if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then rcondv( 1_${ik}$ ) = dif( 1_${ik}$ ) rcondv( 2_${ik}$ ) = dif( 2_${ik}$ ) end if if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if end if ! apply permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_dggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( & anrm / anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )& )>( anrm / anrmto ) )then work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( & bnrm / bnrmto ) ) then work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_dlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 60 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_dggesx #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$ggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, & !! DGGESX: computes for a pair of N-by-N real nonsymmetric matrices !! (A,B), the generalized eigenvalues, the real Schur form (S,T), and, !! optionally, the left and/or right matrices of Schur vectors (VSL and !! VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL) S (VSR)**T, (VSL) T (VSR)**T ) !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! quasi-triangular matrix S and the upper triangular matrix T; computes !! a reciprocal condition number for the average of the selected !! eigenvalues (RCONDE); and computes a reciprocal condition number for !! the right and left deflating subspaces corresponding to the selected !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form !! an orthonormal basis for the corresponding left and right eigenspaces !! (deflating subspaces). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or for both being zero. !! A pair of matrices (S,T) is in generalized real Schur form if T is !! upper triangular with non-negative diagonal and S is block upper !! triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond !! to real generalized eigenvalues, while 2-by-2 blocks of S will be !! "standardized" by making the corresponding elements of T have the !! form: !! [ a 0 ] !! [ 0 b ] !! and the pair of corresponding 2-by-2 blocks in S and T will have a !! complex conjugate pair of generalized eigenvalues. alphar, alphai, beta, vsl, ldvsl,vsr, ldvsr, rconde, rcondv, work, lwork, iwork,liwork, & bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), rconde(2_${ik}$), rcondv(2_${ik}$), vsl(& ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_${ri}$) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, wantsb, & wantse, wantsn, wantst, wantsv integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, ip, iright, & irows, itau, iwrk, liwmin, lwrk, maxwrk, minwrk real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, safmax, safmin, & smlnum ! Local Arrays real(${rk}$) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( wantsn ) then ijob = 0_${ik}$ else if( wantse ) then ijob = 1_${ik}$ else if( wantsv ) then ijob = 2_${ik}$ else if( wantsb ) then ijob = 4_${ik}$ end if ! test the input arguments info = 0_${ik}$ if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda0_${ik}$) then minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ ) maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ & ) ) if( ilvsl ) then maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, & -1_${ik}$ ) ) end if lwrk = maxwrk if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ ) else minwrk = 1_${ik}$ maxwrk = 1_${ik}$ lwrk = 1_${ik}$ end if work( 1_${ik}$ ) = lwrk if( wantsn .or. n==0_${ik}$ ) then liwmin = 1_${ik}$ else liwmin = n + 6_${ik}$ end if iwork( 1_${ik}$ ) = liwmin if( lworkzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need 6*n + 2*n for permutation parameters) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_${ri}$gghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired ! (workspace: need n) iwrk = itau call stdlib${ii}$_${ri}$hgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 60 end if ! sort eigenvalues alpha/beta and compute the reciprocal of ! condition number(s) ! (workspace: if ijob >= 1, need max( 8*(n+1), 2*sdim*(n-sdim) ) ! otherwise, need 8*(n+1) ) if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do ! reorder eigenvalues, transform generalized schur vectors, and ! compute reciprocal condition numbers call stdlib${ii}$_${ri}$tgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,sdim, pl, pr, dif, work( iwrk ), lwork-iwrk+1,iwork, & liwork, ierr ) if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( ierr==-22_${ik}$ ) then ! not enough real workspace info = -22_${ik}$ else if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then rconde( 1_${ik}$ ) = pl rconde( 2_${ik}$ ) = pr end if if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then rcondv( 1_${ik}$ ) = dif( 1_${ik}$ ) rcondv( 2_${ik}$ ) = dif( 2_${ik}$ ) end if if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if end if ! apply permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_${ri}$ggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( & anrm / anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )& )>( anrm / anrmto ) )then work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( & bnrm / bnrmto ) ) then work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_${ri}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 60 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ri}$ggesx #:endif #:endfor module subroutine stdlib${ii}$_cggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, alpha,& !! CGGESX computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, the complex Schur form (S,T), !! and, optionally, the left and/or right matrices of Schur vectors (VSL !! and VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL) S (VSR)**H, (VSL) T (VSR)**H ) !! where (VSR)**H is the conjugate-transpose of VSR. !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! triangular matrix S and the upper triangular matrix T; computes !! a reciprocal condition number for the average of the selected !! eigenvalues (RCONDE); and computes a reciprocal condition number for !! the right and left deflating subspaces corresponding to the selected !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form !! an orthonormal basis for the corresponding left and right eigenspaces !! (deflating subspaces). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or for both being zero. !! A pair of matrices (S,T) is in generalized complex Schur form if T is !! upper triangular with non-negative diagonal and S is upper !! triangular. beta, vsl, ldvsl, vsr,ldvsr, rconde, rcondv, work, lwork, rwork,iwork, liwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: rconde(2_${ik}$), rcondv(2_${ik}$), rwork(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_c) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantsb, wantse, & wantsn, wantst, wantsv integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, iright, irows, & irwrk, itau, iwrk, liwmin, lwrk, maxwrk, minwrk real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, smlnum ! Local Arrays real(sp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( wantsn ) then ijob = 0_${ik}$ else if( wantse ) then ijob = 1_${ik}$ else if( wantsv ) then ijob = 2_${ik}$ else if( wantsb ) then ijob = 4_${ik}$ end if ! test the input arguments info = 0_${ik}$ if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda0_${ik}$) then minwrk = 2_${ik}$*n maxwrk = n*(1_${ik}$ + stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) ) if( ilvsl ) then maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) & ) end if lwrk = maxwrk if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ ) else minwrk = 1_${ik}$ maxwrk = 1_${ik}$ lwrk = 1_${ik}$ end if work( 1_${ik}$ ) = lwrk if( wantsn .or. n==0_${ik}$ ) then liwmin = 1_${ik}$ else liwmin = n + 2_${ik}$ end if iwork( 1_${ik}$ ) = liwmin if( lworkzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the unitary transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (complex workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_cungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_cgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau call stdlib${ii}$_chgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 40 end if ! sort eigenvalues alpha/beta and compute the reciprocal of ! condition number(s) if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alpha( i ), beta( i ) ) end do ! reorder eigenvalues, transform generalized schur vectors, and ! compute reciprocal condition numbers ! (complex workspace: if ijob >= 1, need max(1, 2*sdim*(n-sdim)) ! otherwise, need 1 ) call stdlib${ii}$_ctgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, sdim, pl, pr,dif, work( iwrk ), lwork-iwrk+1, iwork, liwork,ierr & ) if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( ierr==-21_${ik}$ ) then ! not enough complex workspace info = -21_${ik}$ else if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then rconde( 1_${ik}$ ) = pl rconde( 2_${ik}$ ) = pr end if if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then rcondv( 1_${ik}$ ) = dif( 1_${ik}$ ) rcondv( 2_${ik}$ ) = dif( 2_${ik}$ ) end if if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if end if ! apply permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_cggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsr, ldvsr, ierr ) ! undo scaling if( ilascl ) then call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. sdim = 0_${ik}$ do i = 1, n cursl = selctg( alpha( i ), beta( i ) ) if( cursl )sdim = sdim + 1_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ lastsl = cursl end do end if 40 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_cggesx module subroutine stdlib${ii}$_zggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, alpha,& !! ZGGESX computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, the complex Schur form (S,T), !! and, optionally, the left and/or right matrices of Schur vectors (VSL !! and VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL) S (VSR)**H, (VSL) T (VSR)**H ) !! where (VSR)**H is the conjugate-transpose of VSR. !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! triangular matrix S and the upper triangular matrix T; computes !! a reciprocal condition number for the average of the selected !! eigenvalues (RCONDE); and computes a reciprocal condition number for !! the right and left deflating subspaces corresponding to the selected !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form !! an orthonormal basis for the corresponding left and right eigenspaces !! (deflating subspaces). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or for both being zero. !! A pair of matrices (S,T) is in generalized complex Schur form if T is !! upper triangular with non-negative diagonal and S is upper !! triangular. beta, vsl, ldvsl, vsr,ldvsr, rconde, rcondv, work, lwork, rwork,iwork, liwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(out) :: rconde(2_${ik}$), rcondv(2_${ik}$), rwork(*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_z) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantsb, wantse, & wantsn, wantst, wantsv integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, iright, irows, & irwrk, itau, iwrk, liwmin, lwrk, maxwrk, minwrk real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, smlnum ! Local Arrays real(dp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( wantsn ) then ijob = 0_${ik}$ else if( wantse ) then ijob = 1_${ik}$ else if( wantsv ) then ijob = 2_${ik}$ else if( wantsb ) then ijob = 4_${ik}$ end if ! test the input arguments info = 0_${ik}$ if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda0_${ik}$) then minwrk = 2_${ik}$*n maxwrk = n*(1_${ik}$ + stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) ) if( ilvsl ) then maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) & ) end if lwrk = maxwrk if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ ) else minwrk = 1_${ik}$ maxwrk = 1_${ik}$ lwrk = 1_${ik}$ end if work( 1_${ik}$ ) = lwrk if( wantsn .or. n==0_${ik}$ ) then liwmin = 1_${ik}$ else liwmin = n + 2_${ik}$ end if iwork( 1_${ik}$ ) = liwmin if( lworkzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the unitary transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (complex workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_zungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_zgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau call stdlib${ii}$_zhgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 40 end if ! sort eigenvalues alpha/beta and compute the reciprocal of ! condition number(s) if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alpha( i ), beta( i ) ) end do ! reorder eigenvalues, transform generalized schur vectors, and ! compute reciprocal condition numbers ! (complex workspace: if ijob >= 1, need max(1, 2*sdim*(n-sdim)) ! otherwise, need 1 ) call stdlib${ii}$_ztgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, sdim, pl, pr,dif, work( iwrk ), lwork-iwrk+1, iwork, liwork,ierr & ) if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( ierr==-21_${ik}$ ) then ! not enough complex workspace info = -21_${ik}$ else if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then rconde( 1_${ik}$ ) = pl rconde( 2_${ik}$ ) = pr end if if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then rcondv( 1_${ik}$ ) = dif( 1_${ik}$ ) rcondv( 2_${ik}$ ) = dif( 2_${ik}$ ) end if if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if end if ! apply permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_zggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsr, ldvsr, ierr ) ! undo scaling if( ilascl ) then call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. sdim = 0_${ik}$ do i = 1, n cursl = selctg( alpha( i ), beta( i ) ) if( cursl )sdim = sdim + 1_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ lastsl = cursl end do end if 40 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_zggesx #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$ggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, alpha,& !! ZGGESX: computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, the complex Schur form (S,T), !! and, optionally, the left and/or right matrices of Schur vectors (VSL !! and VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL) S (VSR)**H, (VSL) T (VSR)**H ) !! where (VSR)**H is the conjugate-transpose of VSR. !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! triangular matrix S and the upper triangular matrix T; computes !! a reciprocal condition number for the average of the selected !! eigenvalues (RCONDE); and computes a reciprocal condition number for !! the right and left deflating subspaces corresponding to the selected !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form !! an orthonormal basis for the corresponding left and right eigenspaces !! (deflating subspaces). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or for both being zero. !! A pair of matrices (S,T) is in generalized complex Schur form if T is !! upper triangular with non-negative diagonal and S is upper !! triangular. beta, vsl, ldvsl, vsr,ldvsr, rconde, rcondv, work, lwork, rwork,iwork, liwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(out) :: rconde(2_${ik}$), rcondv(2_${ik}$), rwork(*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_${ci}$) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantsb, wantse, & wantsn, wantst, wantsv integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, iright, irows, & irwrk, itau, iwrk, liwmin, lwrk, maxwrk, minwrk real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, smlnum ! Local Arrays real(${ck}$) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( wantsn ) then ijob = 0_${ik}$ else if( wantse ) then ijob = 1_${ik}$ else if( wantsv ) then ijob = 2_${ik}$ else if( wantsb ) then ijob = 4_${ik}$ end if ! test the input arguments info = 0_${ik}$ if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -5_${ik}$ else if( n<0_${ik}$ ) then info = -6_${ik}$ else if( lda0_${ik}$) then minwrk = 2_${ik}$*n maxwrk = n*(1_${ik}$ + stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) ) if( ilvsl ) then maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) & ) end if lwrk = maxwrk if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ ) else minwrk = 1_${ik}$ maxwrk = 1_${ik}$ lwrk = 1_${ik}$ end if work( 1_${ik}$ ) = lwrk if( wantsn .or. n==0_${ik}$ ) then liwmin = 1_${ik}$ else liwmin = n + 2_${ik}$ end if iwork( 1_${ik}$ ) = liwmin if( lworkzero .and. anrmbignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrmbignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the unitary transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl ! (complex workspace: need n, prefer n*nb) if( ilvsl ) then call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsr, ldvsr ) ! reduce to generalized hessenberg form ! (workspace: none needed) call stdlib${ii}$_${ci}$gghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau call stdlib${ii}$_${ci}$hgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 40 end if ! sort eigenvalues alpha/beta and compute the reciprocal of ! condition number(s) if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alpha( i ), beta( i ) ) end do ! reorder eigenvalues, transform generalized schur vectors, and ! compute reciprocal condition numbers ! (complex workspace: if ijob >= 1, need max(1, 2*sdim*(n-sdim)) ! otherwise, need 1 ) call stdlib${ii}$_${ci}$tgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, sdim, pl, pr,dif, work( iwrk ), lwork-iwrk+1, iwork, liwork,ierr & ) if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( ierr==-21_${ik}$ ) then ! not enough complex workspace info = -21_${ik}$ else if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then rconde( 1_${ik}$ ) = pl rconde( 2_${ik}$ ) = pr end if if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then rcondv( 1_${ik}$ ) = dif( 1_${ik}$ ) rcondv( 2_${ik}$ ) = dif( 2_${ik}$ ) end if if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if end if ! apply permutation to vsl and vsr ! (workspace: none needed) if( ilvsl )call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_${ci}$ggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsr, ldvsr, ierr ) ! undo scaling if( ilascl ) then call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. sdim = 0_${ik}$ do i = 1, n cursl = selctg( alpha( i ), beta( i ) ) if( cursl )sdim = sdim + 1_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ lastsl = cursl end do end if 40 continue work( 1_${ik}$ ) = maxwrk iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ci}$ggesx #:endif #:endfor pure module subroutine stdlib${ii}$_sgebal( job, n, a, lda, ilo, ihi, scale, info ) !! SGEBAL balances a general real matrix A. This involves, first, !! permuting A by a similarity transformation to isolate eigenvalues !! in the first 1 to ILO-1 and last IHI+1 to N elements on the !! diagonal; and second, applying a diagonal similarity transformation !! to rows and columns ILO to IHI to make the rows and columns as !! close in norm as possible. Both steps are optional. !! Balancing may reduce the 1-norm of the matrix, and improve the !! accuracy of the computed eigenvalues and/or eigenvectors. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: job integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: scale(*) ! ===================================================================== ! Parameters real(sp), parameter :: sclfac = 2.0e+0_sp real(sp), parameter :: factor = 0.95e+0_sp ! Local Scalars logical(lk) :: noconv integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m real(sp) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2 ! Intrinsic Functions ! test the input parameters info = 0_${ik}$ if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) & .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170 f = f*sclfac c = c*sclfac ca = ca*sclfac r = r / sclfac g = g / sclfac ra = ra / sclfac go to 160 170 continue g = c / sclfac 180 continue if( g=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190 if( stdlib${ii}$_sisnan( c+f+ca+r+g+ra ) ) then ! exit if nan to avoid infinite loop info = -3_${ik}$ call stdlib${ii}$_xerbla( 'SGEBAL', -info ) return end if f = f / sclfac c = c / sclfac g = g / sclfac ca = ca / sclfac r = r*sclfac ra = ra*sclfac go to 180 ! now balance. 190 continue if( ( c+r )>=factor*s )cycle loop_200 if( fone .and. scale( i )>one ) then if( scale( i )>=sfmax1 / f )cycle loop_200 end if g = one / f scale( i ) = scale( i )*f noconv = .true. call stdlib${ii}$_sscal( n-k+1, g, a( i, k ), lda ) call stdlib${ii}$_sscal( l, f, a( 1_${ik}$, i ), 1_${ik}$ ) end do loop_200 if( noconv )go to 140 210 continue ilo = k ihi = l return end subroutine stdlib${ii}$_sgebal pure module subroutine stdlib${ii}$_dgebal( job, n, a, lda, ilo, ihi, scale, info ) !! DGEBAL balances a general real matrix A. This involves, first, !! permuting A by a similarity transformation to isolate eigenvalues !! in the first 1 to ILO-1 and last IHI+1 to N elements on the !! diagonal; and second, applying a diagonal similarity transformation !! to rows and columns ILO to IHI to make the rows and columns as !! close in norm as possible. Both steps are optional. !! Balancing may reduce the 1-norm of the matrix, and improve the !! accuracy of the computed eigenvalues and/or eigenvectors. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: job integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: scale(*) ! ===================================================================== ! Parameters real(dp), parameter :: sclfac = 2.0e+0_dp real(dp), parameter :: factor = 0.95e+0_dp ! Local Scalars logical(lk) :: noconv integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m real(dp) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2 ! Intrinsic Functions ! test the input parameters info = 0_${ik}$ if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) & .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170 if( stdlib${ii}$_disnan( c+f+ca+r+g+ra ) ) then ! exit if nan to avoid infinite loop info = -3_${ik}$ call stdlib${ii}$_xerbla( 'DGEBAL', -info ) return end if f = f*sclfac c = c*sclfac ca = ca*sclfac r = r / sclfac g = g / sclfac ra = ra / sclfac go to 160 170 continue g = c / sclfac 180 continue if( g=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190 f = f / sclfac c = c / sclfac g = g / sclfac ca = ca / sclfac r = r*sclfac ra = ra*sclfac go to 180 ! now balance. 190 continue if( ( c+r )>=factor*s )cycle loop_200 if( fone .and. scale( i )>one ) then if( scale( i )>=sfmax1 / f )cycle loop_200 end if g = one / f scale( i ) = scale( i )*f noconv = .true. call stdlib${ii}$_dscal( n-k+1, g, a( i, k ), lda ) call stdlib${ii}$_dscal( l, f, a( 1_${ik}$, i ), 1_${ik}$ ) end do loop_200 if( noconv )go to 140 210 continue ilo = k ihi = l return end subroutine stdlib${ii}$_dgebal #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gebal( job, n, a, lda, ilo, ihi, scale, info ) !! DGEBAL: balances a general real matrix A. This involves, first, !! permuting A by a similarity transformation to isolate eigenvalues !! in the first 1 to ILO-1 and last IHI+1 to N elements on the !! diagonal; and second, applying a diagonal similarity transformation !! to rows and columns ILO to IHI to make the rows and columns as !! close in norm as possible. Both steps are optional. !! Balancing may reduce the 1-norm of the matrix, and improve the !! accuracy of the computed eigenvalues and/or eigenvectors. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: job integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: scale(*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: sclfac = 2.0e+0_${rk}$ real(${rk}$), parameter :: factor = 0.95e+0_${rk}$ ! Local Scalars logical(lk) :: noconv integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m real(${rk}$) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2 ! Intrinsic Functions ! test the input parameters info = 0_${ik}$ if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) & .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170 if( stdlib${ii}$_${ri}$isnan( c+f+ca+r+g+ra ) ) then ! exit if nan to avoid infinite loop info = -3_${ik}$ call stdlib${ii}$_xerbla( 'DGEBAL', -info ) return end if f = f*sclfac c = c*sclfac ca = ca*sclfac r = r / sclfac g = g / sclfac ra = ra / sclfac go to 160 170 continue g = c / sclfac 180 continue if( g=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190 f = f / sclfac c = c / sclfac g = g / sclfac ca = ca / sclfac r = r*sclfac ra = ra*sclfac go to 180 ! now balance. 190 continue if( ( c+r )>=factor*s )cycle loop_200 if( fone .and. scale( i )>one ) then if( scale( i )>=sfmax1 / f )cycle loop_200 end if g = one / f scale( i ) = scale( i )*f noconv = .true. call stdlib${ii}$_${ri}$scal( n-k+1, g, a( i, k ), lda ) call stdlib${ii}$_${ri}$scal( l, f, a( 1_${ik}$, i ), 1_${ik}$ ) end do loop_200 if( noconv )go to 140 210 continue ilo = k ihi = l return end subroutine stdlib${ii}$_${ri}$gebal #:endif #:endfor pure module subroutine stdlib${ii}$_cgebal( job, n, a, lda, ilo, ihi, scale, info ) !! CGEBAL balances a general complex matrix A. This involves, first, !! permuting A by a similarity transformation to isolate eigenvalues !! in the first 1 to ILO-1 and last IHI+1 to N elements on the !! diagonal; and second, applying a diagonal similarity transformation !! to rows and columns ILO to IHI to make the rows and columns as !! close in norm as possible. Both steps are optional. !! Balancing may reduce the 1-norm of the matrix, and improve the !! accuracy of the computed eigenvalues and/or eigenvectors. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: job integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(out) :: scale(*) complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(sp), parameter :: sclfac = 2.0e+0_sp real(sp), parameter :: factor = 0.95e+0_sp ! Local Scalars logical(lk) :: noconv integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m real(sp) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2 ! Intrinsic Functions ! test the input parameters info = 0_${ik}$ if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) & .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170 if( stdlib${ii}$_sisnan( c+f+ca+r+g+ra ) ) then ! exit if nan to avoid infinite loop info = -3_${ik}$ call stdlib${ii}$_xerbla( 'CGEBAL', -info ) return end if f = f*sclfac c = c*sclfac ca = ca*sclfac r = r / sclfac g = g / sclfac ra = ra / sclfac go to 160 170 continue g = c / sclfac 180 continue if( g=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190 f = f / sclfac c = c / sclfac g = g / sclfac ca = ca / sclfac r = r*sclfac ra = ra*sclfac go to 180 ! now balance. 190 continue if( ( c+r )>=factor*s )cycle loop_200 if( fone .and. scale( i )>one ) then if( scale( i )>=sfmax1 / f )cycle loop_200 end if g = one / f scale( i ) = scale( i )*f noconv = .true. call stdlib${ii}$_csscal( n-k+1, g, a( i, k ), lda ) call stdlib${ii}$_csscal( l, f, a( 1_${ik}$, i ), 1_${ik}$ ) end do loop_200 if( noconv )go to 140 210 continue ilo = k ihi = l return end subroutine stdlib${ii}$_cgebal pure module subroutine stdlib${ii}$_zgebal( job, n, a, lda, ilo, ihi, scale, info ) !! ZGEBAL balances a general complex matrix A. This involves, first, !! permuting A by a similarity transformation to isolate eigenvalues !! in the first 1 to ILO-1 and last IHI+1 to N elements on the !! diagonal; and second, applying a diagonal similarity transformation !! to rows and columns ILO to IHI to make the rows and columns as !! close in norm as possible. Both steps are optional. !! Balancing may reduce the 1-norm of the matrix, and improve the !! accuracy of the computed eigenvalues and/or eigenvectors. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: job integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(dp), intent(out) :: scale(*) complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(dp), parameter :: sclfac = 2.0e+0_dp real(dp), parameter :: factor = 0.95e+0_dp ! Local Scalars logical(lk) :: noconv integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m real(dp) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2 ! Intrinsic Functions ! test the input parameters info = 0_${ik}$ if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) & .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170 if( stdlib${ii}$_disnan( c+f+ca+r+g+ra ) ) then ! exit if nan to avoid infinite loop info = -3_${ik}$ call stdlib${ii}$_xerbla( 'ZGEBAL', -info ) return end if f = f*sclfac c = c*sclfac ca = ca*sclfac r = r / sclfac g = g / sclfac ra = ra / sclfac go to 160 170 continue g = c / sclfac 180 continue if( g=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190 f = f / sclfac c = c / sclfac g = g / sclfac ca = ca / sclfac r = r*sclfac ra = ra*sclfac go to 180 ! now balance. 190 continue if( ( c+r )>=factor*s )cycle loop_200 if( fone .and. scale( i )>one ) then if( scale( i )>=sfmax1 / f )cycle loop_200 end if g = one / f scale( i ) = scale( i )*f noconv = .true. call stdlib${ii}$_zdscal( n-k+1, g, a( i, k ), lda ) call stdlib${ii}$_zdscal( l, f, a( 1_${ik}$, i ), 1_${ik}$ ) end do loop_200 if( noconv )go to 140 210 continue ilo = k ihi = l return end subroutine stdlib${ii}$_zgebal #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gebal( job, n, a, lda, ilo, ihi, scale, info ) !! ZGEBAL: balances a general complex matrix A. This involves, first, !! permuting A by a similarity transformation to isolate eigenvalues !! in the first 1 to ILO-1 and last IHI+1 to N elements on the !! diagonal; and second, applying a diagonal similarity transformation !! to rows and columns ILO to IHI to make the rows and columns as !! close in norm as possible. Both steps are optional. !! Balancing may reduce the 1-norm of the matrix, and improve the !! accuracy of the computed eigenvalues and/or eigenvectors. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: job integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(${ck}$), intent(out) :: scale(*) complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: sclfac = 2.0e+0_${ck}$ real(${ck}$), parameter :: factor = 0.95e+0_${ck}$ ! Local Scalars logical(lk) :: noconv integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m real(${ck}$) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2 ! Intrinsic Functions ! test the input parameters info = 0_${ik}$ if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) & .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170 if( stdlib${ii}$_${c2ri(ci)}$isnan( c+f+ca+r+g+ra ) ) then ! exit if nan to avoid infinite loop info = -3_${ik}$ call stdlib${ii}$_xerbla( 'ZGEBAL', -info ) return end if f = f*sclfac c = c*sclfac ca = ca*sclfac r = r / sclfac g = g / sclfac ra = ra / sclfac go to 160 170 continue g = c / sclfac 180 continue if( g=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190 f = f / sclfac c = c / sclfac g = g / sclfac ca = ca / sclfac r = r*sclfac ra = ra*sclfac go to 180 ! now balance. 190 continue if( ( c+r )>=factor*s )cycle loop_200 if( fone .and. scale( i )>one ) then if( scale( i )>=sfmax1 / f )cycle loop_200 end if g = one / f scale( i ) = scale( i )*f noconv = .true. call stdlib${ii}$_${ci}$dscal( n-k+1, g, a( i, k ), lda ) call stdlib${ii}$_${ci}$dscal( l, f, a( 1_${ik}$, i ), 1_${ik}$ ) end do loop_200 if( noconv )go to 140 210 continue ilo = k ihi = l return end subroutine stdlib${ii}$_${ci}$gebal #:endif #:endfor pure module subroutine stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info ) !! SGEHRD reduces a real general matrix A to upper Hessenberg form H by !! an orthogonal similarity transformation: Q**T * A * Q = H . ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx real(sp) :: ei ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=(n*nbmin + tsize) ) then nb = (lwork-tsize) / n else nb = 1_${ik}$ end if end if end if end if ldwork = n if( nb=nh ) then ! use unblocked code below i = ilo else ! use blocked code iwt = 1_${ik}$ + n*nb do i = ilo, ihi - 1 - nx, nb ib = min( nb, ihi-i ) ! reduce columns i:i+ib-1 to hessenberg form, returning the ! matrices v and t of the block reflector h = i - v*t*v**t ! which performs the reduction, and also the matrix y = a*v*t call stdlib${ii}$_slahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, & ldwork ) ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the ! right, computing a := a - y * v**t. v(i+ib,ib-1) must be set ! to 1 ei = a( i+ib, i+ib-1 ) a( i+ib, i+ib-1 ) = one call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE',ihi, ihi-i-ib+1,ib, -one, work, & ldwork, a( i+ib, i ), lda, one,a( 1_${ik}$, i+ib ), lda ) a( i+ib, i+ib-1 ) = ei ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the ! right call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'TRANSPOSE','UNIT', i, ib-1,one, a( i+1, i )& , lda, work, ldwork ) do j = 0, ib-2 call stdlib${ii}$_saxpy( i, -one, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ ) end do ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the ! left call stdlib${ii}$_slarfb( 'LEFT', 'TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, n-i-ib+1, & ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, ldwork ) end do end if ! use unblocked code to reduce the rest of the matrix call stdlib${ii}$_sgehd2( n, i, ihi, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_sgehrd pure module subroutine stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info ) !! DGEHRD reduces a real general matrix A to upper Hessenberg form H by !! an orthogonal similarity transformation: Q**T * A * Q = H . ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx real(dp) :: ei ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=(n*nbmin + tsize) ) then nb = (lwork-tsize) / n else nb = 1_${ik}$ end if end if end if end if ldwork = n if( nb=nh ) then ! use unblocked code below i = ilo else ! use blocked code iwt = 1_${ik}$ + n*nb do i = ilo, ihi - 1 - nx, nb ib = min( nb, ihi-i ) ! reduce columns i:i+ib-1 to hessenberg form, returning the ! matrices v and t of the block reflector h = i - v*t*v**t ! which performs the reduction, and also the matrix y = a*v*t call stdlib${ii}$_dlahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, & ldwork ) ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the ! right, computing a := a - y * v**t. v(i+ib,ib-1) must be set ! to 1 ei = a( i+ib, i+ib-1 ) a( i+ib, i+ib-1 ) = one call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE',ihi, ihi-i-ib+1,ib, -one, work, & ldwork, a( i+ib, i ), lda, one,a( 1_${ik}$, i+ib ), lda ) a( i+ib, i+ib-1 ) = ei ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the ! right call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'TRANSPOSE','UNIT', i, ib-1,one, a( i+1, i )& , lda, work, ldwork ) do j = 0, ib-2 call stdlib${ii}$_daxpy( i, -one, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ ) end do ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the ! left call stdlib${ii}$_dlarfb( 'LEFT', 'TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, n-i-ib+1, & ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, ldwork ) end do end if ! use unblocked code to reduce the rest of the matrix call stdlib${ii}$_dgehd2( n, i, ihi, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dgehrd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, tau, work, lwork, info ) !! DGEHRD: reduces a real general matrix A to upper Hessenberg form H by !! an orthogonal similarity transformation: Q**T * A * Q = H . ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx real(${rk}$) :: ei ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=(n*nbmin + tsize) ) then nb = (lwork-tsize) / n else nb = 1_${ik}$ end if end if end if end if ldwork = n if( nb=nh ) then ! use unblocked code below i = ilo else ! use blocked code iwt = 1_${ik}$ + n*nb do i = ilo, ihi - 1 - nx, nb ib = min( nb, ihi-i ) ! reduce columns i:i+ib-1 to hessenberg form, returning the ! matrices v and t of the block reflector h = i - v*t*v**t ! which performs the reduction, and also the matrix y = a*v*t call stdlib${ii}$_${ri}$lahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, & ldwork ) ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the ! right, computing a := a - y * v**t. v(i+ib,ib-1) must be set ! to 1 ei = a( i+ib, i+ib-1 ) a( i+ib, i+ib-1 ) = one call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE',ihi, ihi-i-ib+1,ib, -one, work, & ldwork, a( i+ib, i ), lda, one,a( 1_${ik}$, i+ib ), lda ) a( i+ib, i+ib-1 ) = ei ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the ! right call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'TRANSPOSE','UNIT', i, ib-1,one, a( i+1, i )& , lda, work, ldwork ) do j = 0, ib-2 call stdlib${ii}$_${ri}$axpy( i, -one, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ ) end do ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the ! left call stdlib${ii}$_${ri}$larfb( 'LEFT', 'TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, n-i-ib+1, & ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, ldwork ) end do end if ! use unblocked code to reduce the rest of the matrix call stdlib${ii}$_${ri}$gehd2( n, i, ihi, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$gehrd #:endif #:endfor pure module subroutine stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info ) !! CGEHRD reduces a complex general matrix A to upper Hessenberg form H by !! an unitary similarity transformation: Q**H * A * Q = H . ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx complex(sp) :: ei ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=(n*nbmin+tsize) ) then nb = (lwork-tsize) / n else nb = 1_${ik}$ end if end if end if end if ldwork = n if( nb=nh ) then ! use unblocked code below i = ilo else ! use blocked code iwt = 1_${ik}$ + n*nb do i = ilo, ihi - 1 - nx, nb ib = min( nb, ihi-i ) ! reduce columns i:i+ib-1 to hessenberg form, returning the ! matrices v and t of the block reflector h = i - v*t*v**h ! which performs the reduction, and also the matrix y = a*v*t call stdlib${ii}$_clahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, & ldwork ) ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the ! right, computing a := a - y * v**h. v(i+ib,ib-1) must be set ! to 1 ei = a( i+ib, i+ib-1 ) a( i+ib, i+ib-1 ) = cone call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',ihi, ihi-i-ib+1,ib, -& cone, work, ldwork, a( i+ib, i ), lda, cone,a( 1_${ik}$, i+ib ), lda ) a( i+ib, i+ib-1 ) = ei ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the ! right call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', i, ib-1,cone, & a( i+1, i ), lda, work, ldwork ) do j = 0, ib-2 call stdlib${ii}$_caxpy( i, -cone, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ ) end do ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the ! left call stdlib${ii}$_clarfb( 'LEFT', 'CONJUGATE TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, & n-i-ib+1, ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, & ldwork ) end do end if ! use unblocked code to reduce the rest of the matrix call stdlib${ii}$_cgehd2( n, i, ihi, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cgehrd pure module subroutine stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info ) !! ZGEHRD reduces a complex general matrix A to upper Hessenberg form H by !! an unitary similarity transformation: Q**H * A * Q = H . ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx complex(dp) :: ei ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=(n*nbmin + tsize) ) then nb = (lwork-tsize) / n else nb = 1_${ik}$ end if end if end if end if ldwork = n if( nb=nh ) then ! use unblocked code below i = ilo else ! use blocked code iwt = 1_${ik}$ + n*nb do i = ilo, ihi - 1 - nx, nb ib = min( nb, ihi-i ) ! reduce columns i:i+ib-1 to hessenberg form, returning the ! matrices v and t of the block reflector h = i - v*t*v**h ! which performs the reduction, and also the matrix y = a*v*t call stdlib${ii}$_zlahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, & ldwork ) ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the ! right, computing a := a - y * v**h. v(i+ib,ib-1) must be set ! to 1 ei = a( i+ib, i+ib-1 ) a( i+ib, i+ib-1 ) = cone call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',ihi, ihi-i-ib+1,ib, -& cone, work, ldwork, a( i+ib, i ), lda, cone,a( 1_${ik}$, i+ib ), lda ) a( i+ib, i+ib-1 ) = ei ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the ! right call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', i, ib-1,cone, & a( i+1, i ), lda, work, ldwork ) do j = 0, ib-2 call stdlib${ii}$_zaxpy( i, -cone, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ ) end do ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the ! left call stdlib${ii}$_zlarfb( 'LEFT', 'CONJUGATE TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, & n-i-ib+1, ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, & ldwork ) end do end if ! use unblocked code to reduce the rest of the matrix call stdlib${ii}$_zgehd2( n, i, ihi, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zgehrd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, tau, work, lwork, info ) !! ZGEHRD: reduces a complex general matrix A to upper Hessenberg form H by !! an unitary similarity transformation: Q**H * A * Q = H . ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldt = nbmax+1 integer(${ik}$), parameter :: tsize = ldt*nbmax ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx complex(${ck}$) :: ei ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda1_${ik}$ .and. nb=(n*nbmin + tsize) ) then nb = (lwork-tsize) / n else nb = 1_${ik}$ end if end if end if end if ldwork = n if( nb=nh ) then ! use unblocked code below i = ilo else ! use blocked code iwt = 1_${ik}$ + n*nb do i = ilo, ihi - 1 - nx, nb ib = min( nb, ihi-i ) ! reduce columns i:i+ib-1 to hessenberg form, returning the ! matrices v and t of the block reflector h = i - v*t*v**h ! which performs the reduction, and also the matrix y = a*v*t call stdlib${ii}$_${ci}$lahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, & ldwork ) ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the ! right, computing a := a - y * v**h. v(i+ib,ib-1) must be set ! to 1 ei = a( i+ib, i+ib-1 ) a( i+ib, i+ib-1 ) = cone call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',ihi, ihi-i-ib+1,ib, -& cone, work, ldwork, a( i+ib, i ), lda, cone,a( 1_${ik}$, i+ib ), lda ) a( i+ib, i+ib-1 ) = ei ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the ! right call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', i, ib-1,cone, & a( i+1, i ), lda, work, ldwork ) do j = 0, ib-2 call stdlib${ii}$_${ci}$axpy( i, -cone, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ ) end do ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the ! left call stdlib${ii}$_${ci}$larfb( 'LEFT', 'CONJUGATE TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, & n-i-ib+1, ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, & ldwork ) end do end if ! use unblocked code to reduce the rest of the matrix call stdlib${ii}$_${ci}$gehd2( n, i, ihi, a, lda, tau, work, iinfo ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$gehrd #:endif #:endfor pure module subroutine stdlib${ii}$_sgehd2( n, ilo, ihi, a, lda, tau, work, info ) !! SGEHD2 reduces a real general matrix A to upper Hessenberg form H by !! an orthogonal similarity transformation: Q**T * A * Q = H . ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, n integer(${ik}$), intent(out) :: info ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(sp) :: aii ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( ldamax( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( ldamax( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( ldamax( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( ldamax( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( ldamax( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( ldamax( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -7_${ik}$ else if( ldv=ilo .and. i<=ihi )cycle loop_40 if( i=ilo .and. i<=ihi )cycle loop_50 if( imax( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -7_${ik}$ else if( ldv=ilo .and. i<=ihi )cycle loop_40 if( i=ilo .and. i<=ihi )cycle loop_50 if( imax( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -7_${ik}$ else if( ldv=ilo .and. i<=ihi )cycle loop_40 if( i=ilo .and. i<=ihi )cycle loop_50 if( imax( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -7_${ik}$ else if( ldv=ilo .and. i<=ihi )cycle loop_40 if( i=ilo .and. i<=ihi )cycle loop_50 if( imax( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -7_${ik}$ else if( ldv=ilo .and. i<=ihi )cycle loop_40 if( i=ilo .and. i<=ihi )cycle loop_50 if( imax( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -7_${ik}$ else if( ldv=ilo .and. i<=ihi )cycle loop_40 if( i=ilo .and. i<=ihi )cycle loop_50 if( i1_${ik}$ ) then ! update a(k+1:n,i) ! update i-th column of a - y * v**t call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k, i-1, -one, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), & lda, one, a( k+1, i ), 1_${ik}$ ) ! apply i - v * t**t * v**t to this column (call it b) from the ! left, using the last column of t as workspace ! let v = ( v1 ) and b = ( b1 ) (first i-1 rows) ! ( v2 ) ( b2 ) ! where v1 is unit lower triangular ! w := v1**t * b1 call stdlib${ii}$_scopy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ ) call stdlib${ii}$_strmv( 'LOWER', 'TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, t( 1_${ik}$, nb ),& 1_${ik}$ ) ! w := w + v2**t * b2 call stdlib${ii}$_sgemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ),lda, a( k+i, i ), & 1_${ik}$, one, t( 1_${ik}$, nb ), 1_${ik}$ ) ! w := t**t * w call stdlib${ii}$_strmv( 'UPPER', 'TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, nb ), 1_${ik}$ ) ! b2 := b2 - v2*w call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k-i+1, i-1, -one,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb )& , 1_${ik}$, one, a( k+i, i ), 1_${ik}$ ) ! b1 := b1 - v1*w call stdlib${ii}$_strmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, & nb ), 1_${ik}$ ) call stdlib${ii}$_saxpy( i-1, -one, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ ) a( k+i-1, i-1 ) = ei end if ! generate the elementary reflector h(i) to annihilate ! a(k+i+1:n,i) call stdlib${ii}$_slarfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) ) ei = a( k+i, i ) a( k+i, i ) = one ! compute y(k+1:n,i) call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k, n-k-i+1,one, a( k+1, i+1 ),lda, a( k+i, i ),& 1_${ik}$, zero, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_sgemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ), lda,a( k+i, i ), 1_${ik}$, & zero, t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k, i-1, -one,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, & one, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ ) ! compute t(1:i,i) call stdlib${ii}$_sscal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_strmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ ) t( i, i ) = tau( i ) end do loop_10 a( k+nb, nb ) = ei ! compute y(1:k,1:nb) call stdlib${ii}$_slacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy ) call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,one, a( k+1, 1_${ik}$ ), & lda, y, ldy ) if( n>k+nb )call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, one,a( 1_${ik}$, & 2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, one, y,ldy ) call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,one, t, ldt, y, & ldy ) return end subroutine stdlib${ii}$_slahr2 pure module subroutine stdlib${ii}$_dlahr2( n, k, nb, a, lda, tau, t, ldt, y, ldy ) !! DLAHR2 reduces the first NB columns of A real general n-BY-(n-k+1) !! matrix A so that elements below the k-th subdiagonal are zero. The !! reduction is performed by an orthogonal similarity transformation !! Q**T * A * Q. The routine returns the matrices V and T which determine !! Q as a block reflector I - V*T*V**T, and also the matrix Y = A * V * T. !! This is an auxiliary routine called by DGEHRD. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: k, lda, ldt, ldy, n, nb ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,nb), tau(nb), y(ldy,nb) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(dp) :: ei ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=1 )return loop_10: do i = 1, nb if( i>1_${ik}$ ) then ! update a(k+1:n,i) ! update i-th column of a - y * v**t call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k, i-1, -one, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), & lda, one, a( k+1, i ), 1_${ik}$ ) ! apply i - v * t**t * v**t to this column (call it b) from the ! left, using the last column of t as workspace ! let v = ( v1 ) and b = ( b1 ) (first i-1 rows) ! ( v2 ) ( b2 ) ! where v1 is unit lower triangular ! w := v1**t * b1 call stdlib${ii}$_dcopy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ ) call stdlib${ii}$_dtrmv( 'LOWER', 'TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, t( 1_${ik}$, nb ),& 1_${ik}$ ) ! w := w + v2**t * b2 call stdlib${ii}$_dgemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ),lda, a( k+i, i ), & 1_${ik}$, one, t( 1_${ik}$, nb ), 1_${ik}$ ) ! w := t**t * w call stdlib${ii}$_dtrmv( 'UPPER', 'TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, nb ), 1_${ik}$ ) ! b2 := b2 - v2*w call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k-i+1, i-1, -one,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb )& , 1_${ik}$, one, a( k+i, i ), 1_${ik}$ ) ! b1 := b1 - v1*w call stdlib${ii}$_dtrmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, & nb ), 1_${ik}$ ) call stdlib${ii}$_daxpy( i-1, -one, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ ) a( k+i-1, i-1 ) = ei end if ! generate the elementary reflector h(i) to annihilate ! a(k+i+1:n,i) call stdlib${ii}$_dlarfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) ) ei = a( k+i, i ) a( k+i, i ) = one ! compute y(k+1:n,i) call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k, n-k-i+1,one, a( k+1, i+1 ),lda, a( k+i, i ),& 1_${ik}$, zero, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_dgemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ), lda,a( k+i, i ), 1_${ik}$, & zero, t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k, i-1, -one,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, & one, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ ) ! compute t(1:i,i) call stdlib${ii}$_dscal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dtrmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ ) t( i, i ) = tau( i ) end do loop_10 a( k+nb, nb ) = ei ! compute y(1:k,1:nb) call stdlib${ii}$_dlacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy ) call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,one, a( k+1, 1_${ik}$ ), & lda, y, ldy ) if( n>k+nb )call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, one,a( 1_${ik}$, & 2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, one, y,ldy ) call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,one, t, ldt, y, & ldy ) return end subroutine stdlib${ii}$_dlahr2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lahr2( n, k, nb, a, lda, tau, t, ldt, y, ldy ) !! DLAHR2: reduces the first NB columns of A real general n-BY-(n-k+1) !! matrix A so that elements below the k-th subdiagonal are zero. The !! reduction is performed by an orthogonal similarity transformation !! Q**T * A * Q. The routine returns the matrices V and T which determine !! Q as a block reflector I - V*T*V**T, and also the matrix Y = A * V * T. !! This is an auxiliary routine called by DGEHRD. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: k, lda, ldt, ldy, n, nb ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: t(ldt,nb), tau(nb), y(ldy,nb) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(${rk}$) :: ei ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=1 )return loop_10: do i = 1, nb if( i>1_${ik}$ ) then ! update a(k+1:n,i) ! update i-th column of a - y * v**t call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k, i-1, -one, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), & lda, one, a( k+1, i ), 1_${ik}$ ) ! apply i - v * t**t * v**t to this column (call it b) from the ! left, using the last column of t as workspace ! let v = ( v1 ) and b = ( b1 ) (first i-1 rows) ! ( v2 ) ( b2 ) ! where v1 is unit lower triangular ! w := v1**t * b1 call stdlib${ii}$_${ri}$copy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ ) call stdlib${ii}$_${ri}$trmv( 'LOWER', 'TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, t( 1_${ik}$, nb ),& 1_${ik}$ ) ! w := w + v2**t * b2 call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ),lda, a( k+i, i ), & 1_${ik}$, one, t( 1_${ik}$, nb ), 1_${ik}$ ) ! w := t**t * w call stdlib${ii}$_${ri}$trmv( 'UPPER', 'TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, nb ), 1_${ik}$ ) ! b2 := b2 - v2*w call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k-i+1, i-1, -one,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb )& , 1_${ik}$, one, a( k+i, i ), 1_${ik}$ ) ! b1 := b1 - v1*w call stdlib${ii}$_${ri}$trmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, & nb ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( i-1, -one, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ ) a( k+i-1, i-1 ) = ei end if ! generate the elementary reflector h(i) to annihilate ! a(k+i+1:n,i) call stdlib${ii}$_${ri}$larfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) ) ei = a( k+i, i ) a( k+i, i ) = one ! compute y(k+1:n,i) call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k, n-k-i+1,one, a( k+1, i+1 ),lda, a( k+i, i ),& 1_${ik}$, zero, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ), lda,a( k+i, i ), 1_${ik}$, & zero, t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k, i-1, -one,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, & one, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ ) ! compute t(1:i,i) call stdlib${ii}$_${ri}$scal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$trmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ ) t( i, i ) = tau( i ) end do loop_10 a( k+nb, nb ) = ei ! compute y(1:k,1:nb) call stdlib${ii}$_${ri}$lacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy ) call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,one, a( k+1, 1_${ik}$ ), & lda, y, ldy ) if( n>k+nb )call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, one,a( 1_${ik}$, & 2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, one, y,ldy ) call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,one, t, ldt, y, & ldy ) return end subroutine stdlib${ii}$_${ri}$lahr2 #:endif #:endfor pure module subroutine stdlib${ii}$_clahr2( n, k, nb, a, lda, tau, t, ldt, y, ldy ) !! CLAHR2 reduces the first NB columns of A complex general n-BY-(n-k+1) !! matrix A so that elements below the k-th subdiagonal are zero. The !! reduction is performed by an unitary similarity transformation !! Q**H * A * Q. The routine returns the matrices V and T which determine !! Q as a block reflector I - V*T*v**H, and also the matrix Y = A * V * T. !! This is an auxiliary routine called by CGEHRD. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: k, lda, ldt, ldy, n, nb ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,nb), tau(nb), y(ldy,nb) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(sp) :: ei ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=1 )return loop_10: do i = 1, nb if( i>1_${ik}$ ) then ! update a(k+1:n,i) ! update i-th column of a - y * v**h call stdlib${ii}$_clacgv( i-1, a( k+i-1, 1_${ik}$ ), lda ) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k, i-1, -cone, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), & lda, cone, a( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_clacgv( i-1, a( k+i-1, 1_${ik}$ ), lda ) ! apply i - v * t**h * v**h to this column (call it b) from the ! left, using the last column of t as workspace ! let v = ( v1 ) and b = ( b1 ) (first i-1 rows) ! ( v2 ) ( b2 ) ! where v1 is unit lower triangular ! w := v1**h * b1 call stdlib${ii}$_ccopy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ ) call stdlib${ii}$_ctrmv( 'LOWER', 'CONJUGATE TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, & t( 1_${ik}$, nb ), 1_${ik}$ ) ! w := w + v2**h * b2 call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ),lda, a( & k+i, i ), 1_${ik}$, cone, t( 1_${ik}$, nb ), 1_${ik}$ ) ! w := t**h * w call stdlib${ii}$_ctrmv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, & nb ), 1_${ik}$ ) ! b2 := b2 - v2*w call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k-i+1, i-1, -cone,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb & ), 1_${ik}$, cone, a( k+i, i ), 1_${ik}$ ) ! b1 := b1 - v1*w call stdlib${ii}$_ctrmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, & nb ), 1_${ik}$ ) call stdlib${ii}$_caxpy( i-1, -cone, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ ) a( k+i-1, i-1 ) = ei end if ! generate the elementary reflector h(i) to annihilate ! a(k+i+1:n,i) call stdlib${ii}$_clarfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) ) ei = a( k+i, i ) a( k+i, i ) = cone ! compute y(k+1:n,i) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k, n-k-i+1,cone, a( k+1, i+1 ),lda, a( k+i, i )& , 1_${ik}$, czero, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ), lda,a( k+& i, i ), 1_${ik}$, czero, t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k, i-1, -cone,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, & cone, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_cscal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ ) ! compute t(1:i,i) call stdlib${ii}$_cscal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_ctrmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ ) t( i, i ) = tau( i ) end do loop_10 a( k+nb, nb ) = ei ! compute y(1:k,1:nb) call stdlib${ii}$_clacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy ) call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,cone, a( k+1, 1_${ik}$ ), & lda, y, ldy ) if( n>k+nb )call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, cone,a( 1_${ik}$,& 2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, cone, y,ldy ) call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,cone, t, ldt, y, & ldy ) return end subroutine stdlib${ii}$_clahr2 pure module subroutine stdlib${ii}$_zlahr2( n, k, nb, a, lda, tau, t, ldt, y, ldy ) !! ZLAHR2 reduces the first NB columns of A complex general n-BY-(n-k+1) !! matrix A so that elements below the k-th subdiagonal are zero. The !! reduction is performed by an unitary similarity transformation !! Q**H * A * Q. The routine returns the matrices V and T which determine !! Q as a block reflector I - V*T*V**H, and also the matrix Y = A * V * T. !! This is an auxiliary routine called by ZGEHRD. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: k, lda, ldt, ldy, n, nb ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,nb), tau(nb), y(ldy,nb) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(dp) :: ei ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=1 )return loop_10: do i = 1, nb if( i>1_${ik}$ ) then ! update a(k+1:n,i) ! update i-th column of a - y * v**h call stdlib${ii}$_zlacgv( i-1, a( k+i-1, 1_${ik}$ ), lda ) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k, i-1, -cone, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), & lda, cone, a( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( i-1, a( k+i-1, 1_${ik}$ ), lda ) ! apply i - v * t**h * v**h to this column (call it b) from the ! left, using the last column of t as workspace ! let v = ( v1 ) and b = ( b1 ) (first i-1 rows) ! ( v2 ) ( b2 ) ! where v1 is unit lower triangular ! w := v1**h * b1 call stdlib${ii}$_zcopy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ ) call stdlib${ii}$_ztrmv( 'LOWER', 'CONJUGATE TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, & t( 1_${ik}$, nb ), 1_${ik}$ ) ! w := w + v2**h * b2 call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ),lda, a( & k+i, i ), 1_${ik}$, cone, t( 1_${ik}$, nb ), 1_${ik}$ ) ! w := t**h * w call stdlib${ii}$_ztrmv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, & nb ), 1_${ik}$ ) ! b2 := b2 - v2*w call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k-i+1, i-1, -cone,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb & ), 1_${ik}$, cone, a( k+i, i ), 1_${ik}$ ) ! b1 := b1 - v1*w call stdlib${ii}$_ztrmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, & nb ), 1_${ik}$ ) call stdlib${ii}$_zaxpy( i-1, -cone, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ ) a( k+i-1, i-1 ) = ei end if ! generate the elementary reflector h(i) to annihilate ! a(k+i+1:n,i) call stdlib${ii}$_zlarfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) ) ei = a( k+i, i ) a( k+i, i ) = cone ! compute y(k+1:n,i) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k, n-k-i+1,cone, a( k+1, i+1 ),lda, a( k+i, i )& , 1_${ik}$, czero, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ), lda,a( k+& i, i ), 1_${ik}$, czero, t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k, i-1, -cone,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, & cone, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_zscal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ ) ! compute t(1:i,i) call stdlib${ii}$_zscal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_ztrmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ ) t( i, i ) = tau( i ) end do loop_10 a( k+nb, nb ) = ei ! compute y(1:k,1:nb) call stdlib${ii}$_zlacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy ) call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,cone, a( k+1, 1_${ik}$ ), & lda, y, ldy ) if( n>k+nb )call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, cone,a( 1_${ik}$,& 2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, cone, y,ldy ) call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,cone, t, ldt, y, & ldy ) return end subroutine stdlib${ii}$_zlahr2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lahr2( n, k, nb, a, lda, tau, t, ldt, y, ldy ) !! ZLAHR2: reduces the first NB columns of A complex general n-BY-(n-k+1) !! matrix A so that elements below the k-th subdiagonal are zero. The !! reduction is performed by an unitary similarity transformation !! Q**H * A * Q. The routine returns the matrices V and T which determine !! Q as a block reflector I - V*T*V**H, and also the matrix Y = A * V * T. !! This is an auxiliary routine called by ZGEHRD. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: k, lda, ldt, ldy, n, nb ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: t(ldt,nb), tau(nb), y(ldy,nb) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(${ck}$) :: ei ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=1 )return loop_10: do i = 1, nb if( i>1_${ik}$ ) then ! update a(k+1:n,i) ! update i-th column of a - y * v**h call stdlib${ii}$_${ci}$lacgv( i-1, a( k+i-1, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k, i-1, -cone, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), & lda, cone, a( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( i-1, a( k+i-1, 1_${ik}$ ), lda ) ! apply i - v * t**h * v**h to this column (call it b) from the ! left, using the last column of t as workspace ! let v = ( v1 ) and b = ( b1 ) (first i-1 rows) ! ( v2 ) ( b2 ) ! where v1 is unit lower triangular ! w := v1**h * b1 call stdlib${ii}$_${ci}$copy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ ) call stdlib${ii}$_${ci}$trmv( 'LOWER', 'CONJUGATE TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, & t( 1_${ik}$, nb ), 1_${ik}$ ) ! w := w + v2**h * b2 call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ),lda, a( & k+i, i ), 1_${ik}$, cone, t( 1_${ik}$, nb ), 1_${ik}$ ) ! w := t**h * w call stdlib${ii}$_${ci}$trmv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, & nb ), 1_${ik}$ ) ! b2 := b2 - v2*w call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k-i+1, i-1, -cone,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb & ), 1_${ik}$, cone, a( k+i, i ), 1_${ik}$ ) ! b1 := b1 - v1*w call stdlib${ii}$_${ci}$trmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, & nb ), 1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( i-1, -cone, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ ) a( k+i-1, i-1 ) = ei end if ! generate the elementary reflector h(i) to annihilate ! a(k+i+1:n,i) call stdlib${ii}$_${ci}$larfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) ) ei = a( k+i, i ) a( k+i, i ) = cone ! compute y(k+1:n,i) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k, n-k-i+1,cone, a( k+1, i+1 ),lda, a( k+i, i )& , 1_${ik}$, czero, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ), lda,a( k+& i, i ), 1_${ik}$, czero, t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k, i-1, -cone,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, & cone, y( k+1, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ ) ! compute t(1:i,i) call stdlib${ii}$_${ci}$scal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$trmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ ) t( i, i ) = tau( i ) end do loop_10 a( k+nb, nb ) = ei ! compute y(1:k,1:nb) call stdlib${ii}$_${ci}$lacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy ) call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,cone, a( k+1, 1_${ik}$ ), & lda, y, ldy ) if( n>k+nb )call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, cone,a( 1_${ik}$,& 2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, cone, y,ldy ) call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,cone, t, ldt, y, & ldy ) return end subroutine stdlib${ii}$_${ci}$lahr2 #:endif #:endfor pure module subroutine stdlib${ii}$_cunghr( n, ilo, ihi, a, lda, tau, work, lwork, info ) !! CUNGHR generates a complex unitary matrix Q which is defined as the !! product of IHI-ILO elementary reflectors of order N, as returned by !! CGEHRD: !! Q = H(ilo) H(ilo+1) . . . H(ihi-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iinfo, j, lwkopt, nb, nh ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nh = ihi - ilo lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then ! generate q(ilo+1:ihi,ilo+1:ihi) call stdlib${ii}$_cungqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, & iinfo ) end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cunghr pure module subroutine stdlib${ii}$_zunghr( n, ilo, ihi, a, lda, tau, work, lwork, info ) !! ZUNGHR generates a complex unitary matrix Q which is defined as the !! product of IHI-ILO elementary reflectors of order N, as returned by !! ZGEHRD: !! Q = H(ilo) H(ilo+1) . . . H(ihi-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iinfo, j, lwkopt, nb, nh ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nh = ihi - ilo lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then ! generate q(ilo+1:ihi,ilo+1:ihi) call stdlib${ii}$_zungqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, & iinfo ) end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zunghr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unghr( n, ilo, ihi, a, lda, tau, work, lwork, info ) !! ZUNGHR: generates a complex unitary matrix Q which is defined as the !! product of IHI-ILO elementary reflectors of order N, as returned by !! ZGEHRD: !! Q = H(ilo) H(ilo+1) . . . H(ihi-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iinfo, j, lwkopt, nb, nh ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nh = ihi - ilo lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then ! generate q(ilo+1:ihi,ilo+1:ihi) call stdlib${ii}$_${ci}$ungqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, & iinfo ) end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$unghr #:endif #:endfor pure module subroutine stdlib${ii}$_cunmhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, lwork, & !! CUNMHR overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix of order nq, with nq = m if !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of !! IHI-ILO elementary reflectors, as returned by CGEHRD: !! Q = H(ilo) H(ilo+1) . . . H(ihi-1). info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(in) :: ihi, ilo, lda, ldc, lwork, m, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, lquery integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, nh, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nh = ihi - ilo left = stdlib_lsame( side, 'L' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.stdlib_lsame( trans, 'N' ) .and. .not.stdlib_lsame( trans, 'C' ) )& then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, nq ) ) then info = -5_${ik}$ else if( ihinq ) then info = -6_${ik}$ else if( ldamax( 1_${ik}$, nq ) ) then info = -5_${ik}$ else if( ihinq ) then info = -6_${ik}$ else if( ldamax( 1_${ik}$, nq ) ) then info = -5_${ik}$ else if( ihinq ) then info = -6_${ik}$ else if( ldamax( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then ! generate q(ilo+1:ihi,ilo+1:ihi) call stdlib${ii}$_sorgqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, & iinfo ) end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_sorghr pure module subroutine stdlib${ii}$_dorghr( n, ilo, ihi, a, lda, tau, work, lwork, info ) !! DORGHR generates a real orthogonal matrix Q which is defined as the !! product of IHI-ILO elementary reflectors of order N, as returned by !! DGEHRD: !! Q = H(ilo) H(ilo+1) . . . H(ihi-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iinfo, j, lwkopt, nb, nh ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nh = ihi - ilo lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then ! generate q(ilo+1:ihi,ilo+1:ihi) call stdlib${ii}$_dorgqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, & iinfo ) end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dorghr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orghr( n, ilo, ihi, a, lda, tau, work, lwork, info ) !! DORGHR: generates a real orthogonal matrix Q which is defined as the !! product of IHI-ILO elementary reflectors of order N, as returned by !! DGEHRD: !! Q = H(ilo) H(ilo+1) . . . H(ihi-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n integer(${ik}$), intent(out) :: info ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, iinfo, j, lwkopt, nb, nh ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nh = ihi - ilo lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -2_${ik}$ else if( ihin ) then info = -3_${ik}$ else if( lda0_${ik}$ ) then ! generate q(ilo+1:ihi,ilo+1:ihi) call stdlib${ii}$_${ri}$orgqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, & iinfo ) end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$orghr #:endif #:endfor pure module subroutine stdlib${ii}$_sormhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, lwork, & !! SORMHR overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix of order nq, with nq = m if !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of !! IHI-ILO elementary reflectors, as returned by SGEHRD: !! Q = H(ilo) H(ilo+1) . . . H(ihi-1). info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(in) :: ihi, ilo, lda, ldc, lwork, m, n integer(${ik}$), intent(out) :: info ! Array Arguments real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, lquery integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, nh, ni, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ nh = ihi - ilo left = stdlib_lsame( side, 'L' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q and nw is the minimum dimension of work if( left ) then nq = m nw = max( 1_${ik}$, n ) else nq = n nw = max( 1_${ik}$, m ) end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.stdlib_lsame( trans, 'N' ) .and. .not.stdlib_lsame( trans, 'T' ) )& then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, nq ) ) then info = -5_${ik}$ else if( ihinq ) then info = -6_${ik}$ else if( ldamax( 1_${ik}$, nq ) ) then info = -5_${ik}$ else if( ihinq ) then info = -6_${ik}$ else if( ldamax( 1_${ik}$, nq ) ) then info = -5_${ik}$ else if( ihinq ) then info = -6_${ik}$ else if( lda1_${ik}$ ) then call stdlib${ii}$_slassq( n-1, dl, 1_${ik}$, scale, sum ) call stdlib${ii}$_slassq( n-1, du, 1_${ik}$, scale, sum ) end if anorm = scale*sqrt( sum ) end if stdlib${ii}$_slangt = anorm return end function stdlib${ii}$_slangt pure real(dp) module function stdlib${ii}$_dlangt( norm, n, dl, d, du ) !! DLANGT returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real tridiagonal matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(in) :: d(*), dl(*), du(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(dp) :: anorm, scale, sum, temp ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then anorm = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). anorm = abs( d( n ) ) do i = 1, n - 1 if( anorm1_${ik}$ ) then call stdlib${ii}$_dlassq( n-1, dl, 1_${ik}$, scale, sum ) call stdlib${ii}$_dlassq( n-1, du, 1_${ik}$, scale, sum ) end if anorm = scale*sqrt( sum ) end if stdlib${ii}$_dlangt = anorm return end function stdlib${ii}$_dlangt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$langt( norm, n, dl, d, du ) !! DLANGT: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real tridiagonal matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: n ! Array Arguments real(${rk}$), intent(in) :: d(*), dl(*), du(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(${rk}$) :: anorm, scale, sum, temp ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then anorm = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). anorm = abs( d( n ) ) do i = 1, n - 1 if( anorm1_${ik}$ ) then call stdlib${ii}$_${ri}$lassq( n-1, dl, 1_${ik}$, scale, sum ) call stdlib${ii}$_${ri}$lassq( n-1, du, 1_${ik}$, scale, sum ) end if anorm = scale*sqrt( sum ) end if stdlib${ii}$_${ri}$langt = anorm return end function stdlib${ii}$_${ri}$langt #:endif #:endfor pure real(sp) module function stdlib${ii}$_clangt( norm, n, dl, d, du ) !! CLANGT returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex tridiagonal matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: n ! Array Arguments complex(sp), intent(in) :: d(*), dl(*), du(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(sp) :: anorm, scale, sum, temp ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then anorm = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). anorm = abs( d( n ) ) do i = 1, n - 1 if( anorm1_${ik}$ ) then call stdlib${ii}$_classq( n-1, dl, 1_${ik}$, scale, sum ) call stdlib${ii}$_classq( n-1, du, 1_${ik}$, scale, sum ) end if anorm = scale*sqrt( sum ) end if stdlib${ii}$_clangt = anorm return end function stdlib${ii}$_clangt pure real(dp) module function stdlib${ii}$_zlangt( norm, n, dl, d, du ) !! ZLANGT returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex tridiagonal matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: n ! Array Arguments complex(dp), intent(in) :: d(*), dl(*), du(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(dp) :: anorm, scale, sum, temp ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then anorm = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). anorm = abs( d( n ) ) do i = 1, n - 1 if( anorm1_${ik}$ ) then call stdlib${ii}$_zlassq( n-1, dl, 1_${ik}$, scale, sum ) call stdlib${ii}$_zlassq( n-1, du, 1_${ik}$, scale, sum ) end if anorm = scale*sqrt( sum ) end if stdlib${ii}$_zlangt = anorm return end function stdlib${ii}$_zlangt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure real(${ck}$) module function stdlib${ii}$_${ci}$langt( norm, n, dl, d, du ) !! ZLANGT: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex tridiagonal matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: n ! Array Arguments complex(${ck}$), intent(in) :: d(*), dl(*), du(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(${ck}$) :: anorm, scale, sum, temp ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then anorm = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). anorm = abs( d( n ) ) do i = 1, n - 1 if( anorm1_${ik}$ ) then call stdlib${ii}$_${ci}$lassq( n-1, dl, 1_${ik}$, scale, sum ) call stdlib${ii}$_${ci}$lassq( n-1, du, 1_${ik}$, scale, sum ) end if anorm = scale*sqrt( sum ) end if stdlib${ii}$_${ci}$langt = anorm return end function stdlib${ii}$_${ci}$langt #:endif #:endfor real(sp) module function stdlib${ii}$_slanhs( norm, n, a, lda, work ) !! SLANHS returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! Hessenberg matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero do j = 1, n do i = 1, min( n, j+1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero do j = 1, n sum = zero do i = 1, min( n, j+1 ) sum = sum + abs( a( i, j ) ) end do if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, min( n, j+1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one do j = 1, n call stdlib${ii}$_slassq( min( n, j+1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do value = scale*sqrt( sum ) end if stdlib${ii}$_slanhs = value return end function stdlib${ii}$_slanhs real(dp) module function stdlib${ii}$_dlanhs( norm, n, a, lda, work ) !! DLANHS returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! Hessenberg matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero do j = 1, n do i = 1, min( n, j+1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero do j = 1, n sum = zero do i = 1, min( n, j+1 ) sum = sum + abs( a( i, j ) ) end do if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, min( n, j+1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one do j = 1, n call stdlib${ii}$_dlassq( min( n, j+1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do value = scale*sqrt( sum ) end if stdlib${ii}$_dlanhs = value return end function stdlib${ii}$_dlanhs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lanhs( norm, n, a, lda, work ) !! DLANHS: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! Hessenberg matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${rk}$) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero do j = 1, n do i = 1, min( n, j+1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero do j = 1, n sum = zero do i = 1, min( n, j+1 ) sum = sum + abs( a( i, j ) ) end do if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, min( n, j+1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one do j = 1, n call stdlib${ii}$_${ri}$lassq( min( n, j+1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do value = scale*sqrt( sum ) end if stdlib${ii}$_${ri}$lanhs = value return end function stdlib${ii}$_${ri}$lanhs #:endif #:endfor real(sp) module function stdlib${ii}$_clanhs( norm, n, a, lda, work ) !! CLANHS returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! Hessenberg matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero do j = 1, n do i = 1, min( n, j+1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero do j = 1, n sum = zero do i = 1, min( n, j+1 ) sum = sum + abs( a( i, j ) ) end do if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, min( n, j+1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one do j = 1, n call stdlib${ii}$_classq( min( n, j+1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do value = scale*sqrt( sum ) end if stdlib${ii}$_clanhs = value return end function stdlib${ii}$_clanhs real(dp) module function stdlib${ii}$_zlanhs( norm, n, a, lda, work ) !! ZLANHS returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! Hessenberg matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero do j = 1, n do i = 1, min( n, j+1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero do j = 1, n sum = zero do i = 1, min( n, j+1 ) sum = sum + abs( a( i, j ) ) end do if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, min( n, j+1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one do j = 1, n call stdlib${ii}$_zlassq( min( n, j+1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do value = scale*sqrt( sum ) end if stdlib${ii}$_zlanhs = value return end function stdlib${ii}$_zlanhs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lanhs( norm, n, a, lda, work ) !! ZLANHS: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! Hessenberg matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero do j = 1, n do i = 1, min( n, j+1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero do j = 1, n sum = zero do i = 1, min( n, j+1 ) sum = sum + abs( a( i, j ) ) end do if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, min( n, j+1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one do j = 1, n call stdlib${ii}$_${ci}$lassq( min( n, j+1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do value = scale*sqrt( sum ) end if stdlib${ii}$_${ci}$lanhs = value return end function stdlib${ii}$_${ci}$lanhs #:endif #:endfor real(sp) module function stdlib${ii}$_clanhf( norm, transr, uplo, n, a, work ) !! CLANHF returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex Hermitian matrix A in RFP format. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, transr, uplo integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(out) :: work(0_${ik}$:*) complex(sp), intent(in) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, ifm, ilu, noe, n1, k, l, lda real(sp) :: scale, s, value, aa, temp ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then stdlib${ii}$_clanhf = zero return else if( n==1_${ik}$ ) then stdlib${ii}$_clanhf = abs(real(a(0_${ik}$),KIND=sp)) return end if ! set noe = 1 if n is odd. if n is even set noe=0 noe = 1_${ik}$ if( mod( n, 2_${ik}$ )==0_${ik}$ )noe = 0_${ik}$ ! set ifm = 0 when form='c' or 'c' and 1 otherwise ifm = 1_${ik}$ if( stdlib_lsame( transr, 'C' ) )ifm = 0_${ik}$ ! set ilu = 0 when uplo='u or 'u' and 1 otherwise ilu = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) )ilu = 0_${ik}$ ! set lda = (n+1)/2 when ifm = 0 ! set lda = n when ifm = 1 and noe = 1 ! set lda = n+1 when ifm = 1 and noe = 0 if( ifm==1_${ik}$ ) then if( noe==1_${ik}$ ) then lda = n else ! noe=0 lda = n + 1_${ik}$ end if else ! ifm=0 lda = ( n+1 ) / 2_${ik}$ end if if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). k = ( n+1 ) / 2_${ik}$ value = zero if( noe==1_${ik}$ ) then ! n is odd if( ifm==1_${ik}$ ) then ! a is n by k if( ilu==1_${ik}$ ) then ! uplo ='l' j = 0_${ik}$ ! -> l(0,0) temp = abs( real( a( j+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = 1, n - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do do j = 1, k - 1 do i = 0, j - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do i = j - 1_${ik}$ ! l(k+j,k+j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp i = j ! -> l(j,j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = j + 1, n - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 2 do i = 0, k + j - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do i = k + j - 1_${ik}$ ! -> u(i,i) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp i = i + 1_${ik}$ ! =k+j; i -> u(j,j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = k + j + 1, n - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do do i = 0, n - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp ! j=k-1 end do ! i=n-1 -> u(n-1,n-1) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end if else ! xpose case; a is k by n if( ilu==1_${ik}$ ) then ! uplo ='l' do j = 0, k - 2 do i = 0, j - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do i = j ! l(i,i) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp i = j + 1_${ik}$ ! l(j+k,j+k) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = j + 2, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do j = k - 1_${ik}$ do i = 0, k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do i = k - 1_${ik}$ ! -> l(i,i) is at a(i,j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do j = k, n - 1 do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 2 do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do j = k - 1_${ik}$ ! -> u(j,j) is at a(0,j) temp = abs( real( a( 0_${ik}$+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do do j = k, n - 1 do i = 0, j - k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do i = j - k ! -> u(i,i) at a(i,j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp i = j - k + 1_${ik}$ ! u(j,j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = j - k + 2, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do end if end if else ! n is even if( ifm==1_${ik}$ ) then ! a is n+1 by k if( ilu==1_${ik}$ ) then ! uplo ='l' j = 0_${ik}$ ! -> l(k,k) temp = abs( real( a( j+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp temp = abs( real( a( j+1+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = 2, n temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do do j = 1, k - 1 do i = 0, j - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do i = j ! l(k+j,k+j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp i = j + 1_${ik}$ ! -> l(j,j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = j + 2, n temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 2 do i = 0, k + j - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do i = k + j ! -> u(i,i) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp i = i + 1_${ik}$ ! =k+j+1; i -> u(j,j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = k + j + 2, n temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do do i = 0, n - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp ! j=k-1 end do ! i=n-1 -> u(n-1,n-1) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp i = n ! -> u(k-1,k-1) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end if else ! xpose case; a is k by n+1 if( ilu==1_${ik}$ ) then ! uplo ='l' j = 0_${ik}$ ! -> l(k,k) at a(0,0) temp = abs( real( a( j+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do do j = 1, k - 1 do i = 0, j - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do i = j - 1_${ik}$ ! l(i,i) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp i = j ! l(j+k,j+k) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = j + 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do j = k do i = 0, k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do i = k - 1_${ik}$ ! -> l(i,i) is at a(i,j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do j = k + 1, n do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 1 do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do j = k ! -> u(j,j) is at a(0,j) temp = abs( real( a( 0_${ik}$+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do do j = k + 1, n - 1 do i = 0, j - k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do i = j - k - 1_${ik}$ ! -> u(i,i) at a(i,j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp i = j - k ! u(j,j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp do i = j - k + 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end do j = n do i = 0, k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do i = k - 1_${ik}$ ! u(k,k) at a(i,j) temp = abs( real( a( i+j*lda ),KIND=sp) ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end if end if end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is hermitian). if( ifm==1_${ik}$ ) then ! a is 'n' k = n / 2_${ik}$ if( noe==1_${ik}$ ) then ! n is odd if( ilu==0_${ik}$ ) then ! uplo = 'u' do i = 0, k - 1 work( i ) = zero end do do j = 0, k s = zero do i = 0, k + j - 1 aa = abs( a( i+j*lda ) ) ! -> a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( real( a( i+j*lda ),KIND=sp) ) ! -> a(j+k,j+k) work( j+k ) = s + aa if( i==k+k )go to 10 i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=sp) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do 10 continue value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do else ! ilu = 1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do if( j>0_${ik}$ ) then aa = abs( real( a( i+j*lda ),KIND=sp) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ end if aa = abs( real( a( i+j*lda ),KIND=sp) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then ! uplo = 'u' do i = 0, k - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k + j - 1 aa = abs( a( i+j*lda ) ) ! -> a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( real( a( i+j*lda ),KIND=sp) ) ! -> a(j+k,j+k) work( j+k ) = s + aa i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=sp) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do else ! ilu = 1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do aa = abs( real( a( i+j*lda ),KIND=sp) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=sp) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end if end if else ! ifm=0 k = n / 2_${ik}$ if( noe==1_${ik}$ ) then ! n is odd if( ilu==0_${ik}$ ) then ! uplo = 'u' n1 = k ! n/2 k = k + 1_${ik}$ ! k is the row size and lda do i = n1, n - 1 work( i ) = zero end do do j = 0, n1 - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,n1+i) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = s end do ! j=n1=k-1 is special s = abs( real( a( 0_${ik}$+j*lda ),KIND=sp) ) ! a(k-1,k-1) do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k-1,i+n1) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k, n - 1 s = zero do i = 0, j - k - 1 aa = abs( a( i+j*lda ) ) ! a(i,j-k) work( i ) = work( i ) + aa s = s + aa end do ! i=j-k aa = abs( real( a( i+j*lda ),KIND=sp) ) ! a(j-k,j-k) s = s + aa work( j-k ) = work( j-k ) + s i = i + 1_${ik}$ s = abs( real( a( i+j*lda ),KIND=sp) ) ! a(j,j) do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do else ! ilu=1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = 0, k - 2 ! process s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( real( a( i+j*lda ),KIND=sp) ) ! i=j so process of a(j,j) s = s + aa work( j ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( real( a( i+j*lda ),KIND=sp) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k-1 is special :process col a(k-1,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( real( a( i+j*lda ),KIND=sp) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k, n - 1 ! process col j of a = a(j,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then ! uplo = 'u' do i = k, n - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i+k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = s end do ! j=k aa = abs( real( a( 0_${ik}$+j*lda ),KIND=sp) ) ! a(k,k) s = aa do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k,k+i) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k + 1, n - 1 s = zero do i = 0, j - 2 - k aa = abs( a( i+j*lda ) ) ! a(i,j-k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=j-1-k aa = abs( real( a( i+j*lda ),KIND=sp) ) ! a(j-k-1,j-k-1) s = s + aa work( j-k-1 ) = work( j-k-1 ) + s i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=sp) ) ! a(j,j) s = aa do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do ! j=n s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(i,k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( real( a( i+j*lda ),KIND=sp) ) ! a(k-1,k-1) s = s + aa work( i ) = work( i ) + s value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do else ! ilu=1 do i = k, n - 1 work( i ) = zero end do ! j=0 is special :process col a(k:n-1,k) s = abs( real( a( 0_${ik}$ ),KIND=sp) ) ! a(k,k) do i = 1, k - 1 aa = abs( a( i ) ) ! a(k+i,k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( k ) = work( k ) + s do j = 1, k - 1 ! process s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( real( a( i+j*lda ),KIND=sp) ) ! i=j-1 so process of a(j-1,j-1) s = s + aa work( j-1 ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( real( a( i+j*lda ),KIND=sp) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k is special :process col a(k,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( real( a( i+j*lda ),KIND=sp) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k + 1, n ! process col j-1 of a = a(j-1,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do work( j-1 ) = work( j-1 ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end if end if end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). k = ( n+1 ) / 2_${ik}$ scale = zero s = one if( noe==1_${ik}$ ) then ! n is odd if( ifm==1_${ik}$ ) then ! a is normal if( ilu==0_${ik}$ ) then ! a is upper do j = 0, k - 3 call stdlib${ii}$_classq( k-j-2, a( k+j+1+j*lda ), 1_${ik}$, scale, s ) ! l at a(k,0) end do do j = 0, k - 1 call stdlib${ii}$_classq( k+j-1, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! trap u at a(0,0) end do s = s + s ! double s for the off diagonal elements l = k - 1_${ik}$ ! -> u(k,k) at a(k-1,0) do i = 0, k - 2 aa = real( a( l ),KIND=sp) ! u(k+i,k+i) if( aa/=zero ) then if( scale l(k,k) at a(0,1) do i = 1, k - 1 aa = real( a( l ),KIND=sp) ! l(k-1+i,k-1+i) if( aa/=zero ) then if( scale u(k-1,k-1) at a(0,k-1) aa = real( a( l ),KIND=sp) ! u(k-1,k-1) if( aa/=zero ) then if( scale u(0,0) at a(0,k) do j = k, n - 1 aa = real( a( l ),KIND=sp) ! -> u(j-k,j-k) if( aa/=zero ) then if( scale u(j,j) if( aa/=zero ) then if( scale l(0,0) at a(0,0) do i = 0, k - 2 aa = real( a( l ),KIND=sp) ! l(i,i) if( aa/=zero ) then if( scale k-1 + (k-1)*lda or l(k-1,k-1) at a(k-1,k-1) aa = real( a( l ),KIND=sp) ! l(k-1,k-1) at a(k-1,k-1) if( aa/=zero ) then if( scale u(k,k) at a(k,0) do i = 0, k - 1 aa = real( a( l ),KIND=sp) ! u(k+i,k+i) if( aa/=zero ) then if( scale l(k,k) at a(0,0) do i = 0, k - 1 aa = real( a( l ),KIND=sp) ! l(k-1+i,k-1+i) if( aa/=zero ) then if( scale u(k,k) at a(0,k) aa = real( a( l ),KIND=sp) ! u(k,k) if( aa/=zero ) then if( scale u(0,0) at a(0,k+1) do j = k + 1, n - 1 aa = real( a( l ),KIND=sp) ! -> u(j-k-1,j-k-1) if( aa/=zero ) then if( scale u(j,j) if( aa/=zero ) then if( scale u(k-1,k-1) at a(k-1,n) aa = real( a( l ),KIND=sp) ! u(k,k) if( aa/=zero ) then if( scale l(k,k) at a(0,0) aa = real( a( l ),KIND=sp) ! l(k,k) at a(0,0) if( aa/=zero ) then if( scale l(0,0) at a(0,1) do i = 0, k - 2 aa = real( a( l ),KIND=sp) ! l(i,i) if( aa/=zero ) then if( scale k - 1 + k*lda or l(k-1,k-1) at a(k-1,k) aa = real( a( l ),KIND=sp) ! l(k-1,k-1) at a(k-1,k) if( aa/=zero ) then if( scale l(0,0) temp = abs( real( a( j+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = 1, n - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do do j = 1, k - 1 do i = 0, j - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do i = j - 1_${ik}$ ! l(k+j,k+j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp i = j ! -> l(j,j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = j + 1, n - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 2 do i = 0, k + j - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do i = k + j - 1_${ik}$ ! -> u(i,i) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp i = i + 1_${ik}$ ! =k+j; i -> u(j,j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = k + j + 1, n - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do do i = 0, n - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp ! j=k-1 end do ! i=n-1 -> u(n-1,n-1) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end if else ! xpose case; a is k by n if( ilu==1_${ik}$ ) then ! uplo ='l' do j = 0, k - 2 do i = 0, j - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do i = j ! l(i,i) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp i = j + 1_${ik}$ ! l(j+k,j+k) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = j + 2, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do j = k - 1_${ik}$ do i = 0, k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do i = k - 1_${ik}$ ! -> l(i,i) is at a(i,j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do j = k, n - 1 do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 2 do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do j = k - 1_${ik}$ ! -> u(j,j) is at a(0,j) temp = abs( real( a( 0_${ik}$+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do do j = k, n - 1 do i = 0, j - k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do i = j - k ! -> u(i,i) at a(i,j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp i = j - k + 1_${ik}$ ! u(j,j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = j - k + 2, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do end if end if else ! n is even if( ifm==1_${ik}$ ) then ! a is n+1 by k if( ilu==1_${ik}$ ) then ! uplo ='l' j = 0_${ik}$ ! -> l(k,k) temp = abs( real( a( j+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp temp = abs( real( a( j+1+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = 2, n temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do do j = 1, k - 1 do i = 0, j - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do i = j ! l(k+j,k+j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp i = j + 1_${ik}$ ! -> l(j,j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = j + 2, n temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 2 do i = 0, k + j - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do i = k + j ! -> u(i,i) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp i = i + 1_${ik}$ ! =k+j+1; i -> u(j,j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = k + j + 2, n temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do do i = 0, n - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp ! j=k-1 end do ! i=n-1 -> u(n-1,n-1) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp i = n ! -> u(k-1,k-1) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end if else ! xpose case; a is k by n+1 if( ilu==1_${ik}$ ) then ! uplo ='l' j = 0_${ik}$ ! -> l(k,k) at a(0,0) temp = abs( real( a( j+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do do j = 1, k - 1 do i = 0, j - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do i = j - 1_${ik}$ ! l(i,i) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp i = j ! l(j+k,j+k) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = j + 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do j = k do i = 0, k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do i = k - 1_${ik}$ ! -> l(i,i) is at a(i,j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do j = k + 1, n do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 1 do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do j = k ! -> u(j,j) is at a(0,j) temp = abs( real( a( 0_${ik}$+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do do j = k + 1, n - 1 do i = 0, j - k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do i = j - k - 1_${ik}$ ! -> u(i,i) at a(i,j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp i = j - k ! u(j,j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp do i = j - k + 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do j = n do i = 0, k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do i = k - 1_${ik}$ ! u(k,k) at a(i,j) temp = abs( real( a( i+j*lda ),KIND=dp) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end if end if end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is hermitian). if( ifm==1_${ik}$ ) then ! a is 'n' k = n / 2_${ik}$ if( noe==1_${ik}$ ) then ! n is odd if( ilu==0_${ik}$ ) then ! uplo = 'u' do i = 0, k - 1 work( i ) = zero end do do j = 0, k s = zero do i = 0, k + j - 1 aa = abs( a( i+j*lda ) ) ! -> a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( real( a( i+j*lda ),KIND=dp) ) ! -> a(j+k,j+k) work( j+k ) = s + aa if( i==k+k )go to 10 i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=dp) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do 10 continue value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do else ! ilu = 1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do if( j>0_${ik}$ ) then aa = abs( real( a( i+j*lda ),KIND=dp) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ end if aa = abs( real( a( i+j*lda ),KIND=dp) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then ! uplo = 'u' do i = 0, k - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k + j - 1 aa = abs( a( i+j*lda ) ) ! -> a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( real( a( i+j*lda ),KIND=dp) ) ! -> a(j+k,j+k) work( j+k ) = s + aa i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=dp) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do else ! ilu = 1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do aa = abs( real( a( i+j*lda ),KIND=dp) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=dp) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end if end if else ! ifm=0 k = n / 2_${ik}$ if( noe==1_${ik}$ ) then ! n is odd if( ilu==0_${ik}$ ) then ! uplo = 'u' n1 = k ! n/2 k = k + 1_${ik}$ ! k is the row size and lda do i = n1, n - 1 work( i ) = zero end do do j = 0, n1 - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,n1+i) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = s end do ! j=n1=k-1 is special s = abs( real( a( 0_${ik}$+j*lda ),KIND=dp) ) ! a(k-1,k-1) do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k-1,i+n1) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k, n - 1 s = zero do i = 0, j - k - 1 aa = abs( a( i+j*lda ) ) ! a(i,j-k) work( i ) = work( i ) + aa s = s + aa end do ! i=j-k aa = abs( real( a( i+j*lda ),KIND=dp) ) ! a(j-k,j-k) s = s + aa work( j-k ) = work( j-k ) + s i = i + 1_${ik}$ s = abs( real( a( i+j*lda ),KIND=dp) ) ! a(j,j) do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do else ! ilu=1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = 0, k - 2 ! process s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( real( a( i+j*lda ),KIND=dp) ) ! i=j so process of a(j,j) s = s + aa work( j ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( real( a( i+j*lda ),KIND=dp) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k-1 is special :process col a(k-1,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( real( a( i+j*lda ),KIND=dp) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k, n - 1 ! process col j of a = a(j,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then ! uplo = 'u' do i = k, n - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i+k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = s end do ! j=k aa = abs( real( a( 0_${ik}$+j*lda ),KIND=dp) ) ! a(k,k) s = aa do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k,k+i) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k + 1, n - 1 s = zero do i = 0, j - 2 - k aa = abs( a( i+j*lda ) ) ! a(i,j-k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=j-1-k aa = abs( real( a( i+j*lda ),KIND=dp) ) ! a(j-k-1,j-k-1) s = s + aa work( j-k-1 ) = work( j-k-1 ) + s i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=dp) ) ! a(j,j) s = aa do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do ! j=n s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(i,k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( real( a( i+j*lda ),KIND=dp) ) ! a(k-1,k-1) s = s + aa work( i ) = work( i ) + s value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do else ! ilu=1 do i = k, n - 1 work( i ) = zero end do ! j=0 is special :process col a(k:n-1,k) s = abs( real( a( 0_${ik}$ ),KIND=dp) ) ! a(k,k) do i = 1, k - 1 aa = abs( a( i ) ) ! a(k+i,k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( k ) = work( k ) + s do j = 1, k - 1 ! process s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( real( a( i+j*lda ),KIND=dp) ) ! i=j-1 so process of a(j-1,j-1) s = s + aa work( j-1 ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( real( a( i+j*lda ),KIND=dp) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k is special :process col a(k,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( real( a( i+j*lda ),KIND=dp) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k + 1, n ! process col j-1 of a = a(j-1,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do work( j-1 ) = work( j-1 ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end if end if end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). k = ( n+1 ) / 2_${ik}$ scale = zero s = one if( noe==1_${ik}$ ) then ! n is odd if( ifm==1_${ik}$ ) then ! a is normal if( ilu==0_${ik}$ ) then ! a is upper do j = 0, k - 3 call stdlib${ii}$_zlassq( k-j-2, a( k+j+1+j*lda ), 1_${ik}$, scale, s ) ! l at a(k,0) end do do j = 0, k - 1 call stdlib${ii}$_zlassq( k+j-1, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! trap u at a(0,0) end do s = s + s ! double s for the off diagonal elements l = k - 1_${ik}$ ! -> u(k,k) at a(k-1,0) do i = 0, k - 2 aa = real( a( l ),KIND=dp) ! u(k+i,k+i) if( aa/=zero ) then if( scale l(k,k) at a(0,1) do i = 1, k - 1 aa = real( a( l ),KIND=dp) ! l(k-1+i,k-1+i) if( aa/=zero ) then if( scale u(k-1,k-1) at a(0,k-1) aa = real( a( l ),KIND=dp) ! u(k-1,k-1) if( aa/=zero ) then if( scale u(0,0) at a(0,k) do j = k, n - 1 aa = real( a( l ),KIND=dp) ! -> u(j-k,j-k) if( aa/=zero ) then if( scale u(j,j) if( aa/=zero ) then if( scale l(0,0) at a(0,0) do i = 0, k - 2 aa = real( a( l ),KIND=dp) ! l(i,i) if( aa/=zero ) then if( scale k-1 + (k-1)*lda or l(k-1,k-1) at a(k-1,k-1) aa = real( a( l ),KIND=dp) ! l(k-1,k-1) at a(k-1,k-1) if( aa/=zero ) then if( scale u(k,k) at a(k,0) do i = 0, k - 1 aa = real( a( l ),KIND=dp) ! u(k+i,k+i) if( aa/=zero ) then if( scale l(k,k) at a(0,0) do i = 0, k - 1 aa = real( a( l ),KIND=dp) ! l(k-1+i,k-1+i) if( aa/=zero ) then if( scale u(k,k) at a(0,k) aa = real( a( l ),KIND=dp) ! u(k,k) if( aa/=zero ) then if( scale u(0,0) at a(0,k+1) do j = k + 1, n - 1 aa = real( a( l ),KIND=dp) ! -> u(j-k-1,j-k-1) if( aa/=zero ) then if( scale u(j,j) if( aa/=zero ) then if( scale u(k-1,k-1) at a(k-1,n) aa = real( a( l ),KIND=dp) ! u(k,k) if( aa/=zero ) then if( scale l(k,k) at a(0,0) aa = real( a( l ),KIND=dp) ! l(k,k) at a(0,0) if( aa/=zero ) then if( scale l(0,0) at a(0,1) do i = 0, k - 2 aa = real( a( l ),KIND=dp) ! l(i,i) if( aa/=zero ) then if( scale k - 1 + k*lda or l(k-1,k-1) at a(k-1,k) aa = real( a( l ),KIND=dp) ! l(k-1,k-1) at a(k-1,k) if( aa/=zero ) then if( scale l(0,0) temp = abs( real( a( j+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = 1, n - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do do j = 1, k - 1 do i = 0, j - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do i = j - 1_${ik}$ ! l(k+j,k+j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp i = j ! -> l(j,j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = j + 1, n - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 2 do i = 0, k + j - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do i = k + j - 1_${ik}$ ! -> u(i,i) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp i = i + 1_${ik}$ ! =k+j; i -> u(j,j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = k + j + 1, n - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do do i = 0, n - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp ! j=k-1 end do ! i=n-1 -> u(n-1,n-1) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end if else ! xpose case; a is k by n if( ilu==1_${ik}$ ) then ! uplo ='l' do j = 0, k - 2 do i = 0, j - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do i = j ! l(i,i) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp i = j + 1_${ik}$ ! l(j+k,j+k) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = j + 2, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do j = k - 1_${ik}$ do i = 0, k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do i = k - 1_${ik}$ ! -> l(i,i) is at a(i,j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do j = k, n - 1 do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 2 do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do j = k - 1_${ik}$ ! -> u(j,j) is at a(0,j) temp = abs( real( a( 0_${ik}$+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do do j = k, n - 1 do i = 0, j - k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do i = j - k ! -> u(i,i) at a(i,j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp i = j - k + 1_${ik}$ ! u(j,j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = j - k + 2, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do end if end if else ! n is even if( ifm==1_${ik}$ ) then ! a is n+1 by k if( ilu==1_${ik}$ ) then ! uplo ='l' j = 0_${ik}$ ! -> l(k,k) temp = abs( real( a( j+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp temp = abs( real( a( j+1+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = 2, n temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do do j = 1, k - 1 do i = 0, j - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do i = j ! l(k+j,k+j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp i = j + 1_${ik}$ ! -> l(j,j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = j + 2, n temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 2 do i = 0, k + j - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do i = k + j ! -> u(i,i) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp i = i + 1_${ik}$ ! =k+j+1; i -> u(j,j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = k + j + 2, n temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do do i = 0, n - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp ! j=k-1 end do ! i=n-1 -> u(n-1,n-1) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp i = n ! -> u(k-1,k-1) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end if else ! xpose case; a is k by n+1 if( ilu==1_${ik}$ ) then ! uplo ='l' j = 0_${ik}$ ! -> l(k,k) at a(0,0) temp = abs( real( a( j+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do do j = 1, k - 1 do i = 0, j - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do i = j - 1_${ik}$ ! l(i,i) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp i = j ! l(j+k,j+k) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = j + 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do j = k do i = 0, k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do i = k - 1_${ik}$ ! -> l(i,i) is at a(i,j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do j = k + 1, n do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do else ! uplo = 'u' do j = 0, k - 1 do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do j = k ! -> u(j,j) is at a(0,j) temp = abs( real( a( 0_${ik}$+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do do j = k + 1, n - 1 do i = 0, j - k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do i = j - k - 1_${ik}$ ! -> u(i,i) at a(i,j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp i = j - k ! u(j,j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp do i = j - k + 1, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end do j = n do i = 0, k - 2 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do i = k - 1_${ik}$ ! u(k,k) at a(i,j) temp = abs( real( a( i+j*lda ),KIND=${ck}$) ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end if end if end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is hermitian). if( ifm==1_${ik}$ ) then ! a is 'n' k = n / 2_${ik}$ if( noe==1_${ik}$ ) then ! n is odd if( ilu==0_${ik}$ ) then ! uplo = 'u' do i = 0, k - 1 work( i ) = zero end do do j = 0, k s = zero do i = 0, k + j - 1 aa = abs( a( i+j*lda ) ) ! -> a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! -> a(j+k,j+k) work( j+k ) = s + aa if( i==k+k )go to 10 i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do 10 continue value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do else ! ilu = 1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do if( j>0_${ik}$ ) then aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ end if aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then ! uplo = 'u' do i = 0, k - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k + j - 1 aa = abs( a( i+j*lda ) ) ! -> a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! -> a(j+k,j+k) work( j+k ) = s + aa i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do else ! ilu = 1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end if end if else ! ifm=0 k = n / 2_${ik}$ if( noe==1_${ik}$ ) then ! n is odd if( ilu==0_${ik}$ ) then ! uplo = 'u' n1 = k ! n/2 k = k + 1_${ik}$ ! k is the row size and lda do i = n1, n - 1 work( i ) = zero end do do j = 0, n1 - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,n1+i) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = s end do ! j=n1=k-1 is special s = abs( real( a( 0_${ik}$+j*lda ),KIND=${ck}$) ) ! a(k-1,k-1) do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k-1,i+n1) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k, n - 1 s = zero do i = 0, j - k - 1 aa = abs( a( i+j*lda ) ) ! a(i,j-k) work( i ) = work( i ) + aa s = s + aa end do ! i=j-k aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! a(j-k,j-k) s = s + aa work( j-k ) = work( j-k ) + s i = i + 1_${ik}$ s = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! a(j,j) do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do else ! ilu=1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = 0, k - 2 ! process s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! i=j so process of a(j,j) s = s + aa work( j ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k-1 is special :process col a(k-1,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k, n - 1 ! process col j of a = a(j,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then ! uplo = 'u' do i = k, n - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i+k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = s end do ! j=k aa = abs( real( a( 0_${ik}$+j*lda ),KIND=${ck}$) ) ! a(k,k) s = aa do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k,k+i) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k + 1, n - 1 s = zero do i = 0, j - 2 - k aa = abs( a( i+j*lda ) ) ! a(i,j-k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=j-1-k aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! a(j-k-1,j-k-1) s = s + aa work( j-k-1 ) = work( j-k-1 ) + s i = i + 1_${ik}$ aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! a(j,j) s = aa do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do ! j=n s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(i,k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! a(k-1,k-1) s = s + aa work( i ) = work( i ) + s value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do else ! ilu=1 do i = k, n - 1 work( i ) = zero end do ! j=0 is special :process col a(k:n-1,k) s = abs( real( a( 0_${ik}$ ),KIND=${ck}$) ) ! a(k,k) do i = 1, k - 1 aa = abs( a( i ) ) ! a(k+i,k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( k ) = work( k ) + s do j = 1, k - 1 ! process s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! i=j-1 so process of a(j-1,j-1) s = s + aa work( j-1 ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k is special :process col a(k,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( real( a( i+j*lda ),KIND=${ck}$) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k + 1, n ! process col j-1 of a = a(j-1,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do work( j-1 ) = work( j-1 ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${c2ri(ci)}$isnan( temp ) )value = temp end do end if end if end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). k = ( n+1 ) / 2_${ik}$ scale = zero s = one if( noe==1_${ik}$ ) then ! n is odd if( ifm==1_${ik}$ ) then ! a is normal if( ilu==0_${ik}$ ) then ! a is upper do j = 0, k - 3 call stdlib${ii}$_${ci}$lassq( k-j-2, a( k+j+1+j*lda ), 1_${ik}$, scale, s ) ! l at a(k,0) end do do j = 0, k - 1 call stdlib${ii}$_${ci}$lassq( k+j-1, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! trap u at a(0,0) end do s = s + s ! double s for the off diagonal elements l = k - 1_${ik}$ ! -> u(k,k) at a(k-1,0) do i = 0, k - 2 aa = real( a( l ),KIND=${ck}$) ! u(k+i,k+i) if( aa/=zero ) then if( scale l(k,k) at a(0,1) do i = 1, k - 1 aa = real( a( l ),KIND=${ck}$) ! l(k-1+i,k-1+i) if( aa/=zero ) then if( scale u(k-1,k-1) at a(0,k-1) aa = real( a( l ),KIND=${ck}$) ! u(k-1,k-1) if( aa/=zero ) then if( scale u(0,0) at a(0,k) do j = k, n - 1 aa = real( a( l ),KIND=${ck}$) ! -> u(j-k,j-k) if( aa/=zero ) then if( scale u(j,j) if( aa/=zero ) then if( scale l(0,0) at a(0,0) do i = 0, k - 2 aa = real( a( l ),KIND=${ck}$) ! l(i,i) if( aa/=zero ) then if( scale k-1 + (k-1)*lda or l(k-1,k-1) at a(k-1,k-1) aa = real( a( l ),KIND=${ck}$) ! l(k-1,k-1) at a(k-1,k-1) if( aa/=zero ) then if( scale u(k,k) at a(k,0) do i = 0, k - 1 aa = real( a( l ),KIND=${ck}$) ! u(k+i,k+i) if( aa/=zero ) then if( scale l(k,k) at a(0,0) do i = 0, k - 1 aa = real( a( l ),KIND=${ck}$) ! l(k-1+i,k-1+i) if( aa/=zero ) then if( scale u(k,k) at a(0,k) aa = real( a( l ),KIND=${ck}$) ! u(k,k) if( aa/=zero ) then if( scale u(0,0) at a(0,k+1) do j = k + 1, n - 1 aa = real( a( l ),KIND=${ck}$) ! -> u(j-k-1,j-k-1) if( aa/=zero ) then if( scale u(j,j) if( aa/=zero ) then if( scale u(k-1,k-1) at a(k-1,n) aa = real( a( l ),KIND=${ck}$) ! u(k,k) if( aa/=zero ) then if( scale l(k,k) at a(0,0) aa = real( a( l ),KIND=${ck}$) ! l(k,k) at a(0,0) if( aa/=zero ) then if( scale l(0,0) at a(0,1) do i = 0, k - 2 aa = real( a( l ),KIND=${ck}$) ! l(i,i) if( aa/=zero ) then if( scale k - 1 + k*lda or l(k-1,k-1) at a(k-1,k) aa = real( a( l ),KIND=${ck}$) ! l(k-1,k-1) at a(k-1,k) if( aa/=zero ) then if( scale a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) work( j+k ) = s + aa if( i==k+k )go to 10 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do 10 continue value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do else ! ilu = 1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do if( j>0_${ik}$ ) then aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ end if aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then do i = 0, k - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k + j - 1 aa = abs( a( i+j*lda ) ) ! -> a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) work( j+k ) = s + aa i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do else ! ilu = 1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end if end if else ! ifm=0 k = n / 2_${ik}$ if( noe==1_${ik}$ ) then ! n is odd if( ilu==0_${ik}$ ) then n1 = k ! n/2 k = k + 1_${ik}$ ! k is the row size and lda do i = n1, n - 1 work( i ) = zero end do do j = 0, n1 - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,n1+i) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = s end do ! j=n1=k-1 is special s = abs( a( 0_${ik}$+j*lda ) ) ! a(k-1,k-1) do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k-1,i+n1) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k, n - 1 s = zero do i = 0, j - k - 1 aa = abs( a( i+j*lda ) ) ! a(i,j-k) work( i ) = work( i ) + aa s = s + aa end do ! i=j-k aa = abs( a( i+j*lda ) ) ! a(j-k,j-k) s = s + aa work( j-k ) = work( j-k ) + s i = i + 1_${ik}$ s = abs( a( i+j*lda ) ) ! a(j,j) do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do else ! ilu=1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = 0, k - 2 ! process s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( a( i+j*lda ) ) ! i=j so process of a(j,j) s = s + aa work( j ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( a( i+j*lda ) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k-1 is special :process col a(k-1,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( a( i+j*lda ) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k, n - 1 ! process col j of a = a(j,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then do i = k, n - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i+k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = s end do ! j=k aa = abs( a( 0_${ik}$+j*lda ) ) ! a(k,k) s = aa do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k,k+i) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k + 1, n - 1 s = zero do i = 0, j - 2 - k aa = abs( a( i+j*lda ) ) ! a(i,j-k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=j-1-k aa = abs( a( i+j*lda ) ) ! a(j-k-1,j-k-1) s = s + aa work( j-k-1 ) = work( j-k-1 ) + s i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,j) s = aa do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do ! j=n s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(i,k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( a( i+j*lda ) ) ! a(k-1,k-1) s = s + aa work( i ) = work( i ) + s value = work ( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do else ! ilu=1 do i = k, n - 1 work( i ) = zero end do ! j=0 is special :process col a(k:n-1,k) s = abs( a( 0_${ik}$ ) ) ! a(k,k) do i = 1, k - 1 aa = abs( a( i ) ) ! a(k+i,k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( k ) = work( k ) + s do j = 1, k - 1 ! process s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( a( i+j*lda ) ) ! i=j-1 so process of a(j-1,j-1) s = s + aa work( j-1 ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( a( i+j*lda ) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k is special :process col a(k,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( a( i+j*lda ) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k + 1, n ! process col j-1 of a = a(j-1,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do work( j-1 ) = work( j-1 ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_sisnan( temp ) )value = temp end do end if end if end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). k = ( n+1 ) / 2_${ik}$ scale = zero s = one if( noe==1_${ik}$ ) then ! n is odd if( ifm==1_${ik}$ ) then ! a is normal if( ilu==0_${ik}$ ) then ! a is upper do j = 0, k - 3 call stdlib${ii}$_slassq( k-j-2, a( k+j+1+j*lda ), 1_${ik}$, scale, s ) ! l at a(k,0) end do do j = 0, k - 1 call stdlib${ii}$_slassq( k+j-1, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! trap u at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_slassq( k-1, a( k ), lda+1, scale, s ) ! tri l at a(k,0) call stdlib${ii}$_slassq( k, a( k-1 ), lda+1, scale, s ) ! tri u at a(k-1,0) else ! ilu=1 do j = 0, k - 1 call stdlib${ii}$_slassq( n-j-1, a( j+1+j*lda ), 1_${ik}$, scale, s ) ! trap l at a(0,0) end do do j = 0, k - 2 call stdlib${ii}$_slassq( j, a( 0_${ik}$+( 1_${ik}$+j )*lda ), 1_${ik}$, scale, s ) ! u at a(0,1) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_slassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri l at a(0,0) call stdlib${ii}$_slassq( k-1, a( 0_${ik}$+lda ), lda+1, scale, s ) ! tri u at a(0,1) end if else ! a is xpose if( ilu==0_${ik}$ ) then ! a**t is upper do j = 1, k - 2 call stdlib${ii}$_slassq( j, a( 0_${ik}$+( k+j )*lda ), 1_${ik}$, scale, s ) ! u at a(0,k) end do do j = 0, k - 2 call stdlib${ii}$_slassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k-1 rect. at a(0,0) end do do j = 0, k - 2 call stdlib${ii}$_slassq( k-j-1, a( j+1+( j+k-1 )*lda ), 1_${ik}$,scale, s ) ! l at a(0,k-1) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_slassq( k-1, a( 0_${ik}$+k*lda ), lda+1, scale, s ) ! tri u at a(0,k) call stdlib${ii}$_slassq( k, a( 0_${ik}$+( k-1 )*lda ), lda+1, scale, s ) ! tri l at a(0,k-1) else ! a**t is lower do j = 1, k - 1 call stdlib${ii}$_slassq( j, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! u at a(0,0) end do do j = k, n - 1 call stdlib${ii}$_slassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k-1 rect. at a(0,k) end do do j = 0, k - 3 call stdlib${ii}$_slassq( k-j-2, a( j+2+j*lda ), 1_${ik}$, scale, s ) ! l at a(1,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_slassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri u at a(0,0) call stdlib${ii}$_slassq( k-1, a( 1_${ik}$ ), lda+1, scale, s ) ! tri l at a(1,0) end if end if else ! n is even if( ifm==1_${ik}$ ) then ! a is normal if( ilu==0_${ik}$ ) then ! a is upper do j = 0, k - 2 call stdlib${ii}$_slassq( k-j-1, a( k+j+2+j*lda ), 1_${ik}$, scale, s ) ! l at a(k+1,0) end do do j = 0, k - 1 call stdlib${ii}$_slassq( k+j, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! trap u at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_slassq( k, a( k+1 ), lda+1, scale, s ) ! tri l at a(k+1,0) call stdlib${ii}$_slassq( k, a( k ), lda+1, scale, s ) ! tri u at a(k,0) else ! ilu=1 do j = 0, k - 1 call stdlib${ii}$_slassq( n-j-1, a( j+2+j*lda ), 1_${ik}$, scale, s ) ! trap l at a(1,0) end do do j = 1, k - 1 call stdlib${ii}$_slassq( j, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! u at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_slassq( k, a( 1_${ik}$ ), lda+1, scale, s ) ! tri l at a(1,0) call stdlib${ii}$_slassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri u at a(0,0) end if else ! a is xpose if( ilu==0_${ik}$ ) then ! a**t is upper do j = 1, k - 1 call stdlib${ii}$_slassq( j, a( 0_${ik}$+( k+1+j )*lda ), 1_${ik}$, scale, s ) ! u at a(0,k+1) end do do j = 0, k - 1 call stdlib${ii}$_slassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k rect. at a(0,0) end do do j = 0, k - 2 call stdlib${ii}$_slassq( k-j-1, a( j+1+( j+k )*lda ), 1_${ik}$, scale,s ) ! l at a(0,k) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_slassq( k, a( 0_${ik}$+( k+1 )*lda ), lda+1, scale, s ) ! tri u at a(0,k+1) call stdlib${ii}$_slassq( k, a( 0_${ik}$+k*lda ), lda+1, scale, s ) ! tri l at a(0,k) else ! a**t is lower do j = 1, k - 1 call stdlib${ii}$_slassq( j, a( 0_${ik}$+( j+1 )*lda ), 1_${ik}$, scale, s ) ! u at a(0,1) end do do j = k + 1, n call stdlib${ii}$_slassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k rect. at a(0,k+1) end do do j = 0, k - 2 call stdlib${ii}$_slassq( k-j-1, a( j+1+j*lda ), 1_${ik}$, scale, s ) ! l at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_slassq( k, a( lda ), lda+1, scale, s ) ! tri l at a(0,1) call stdlib${ii}$_slassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri u at a(0,0) end if end if end if value = scale*sqrt( s ) end if stdlib${ii}$_slansf = value return end function stdlib${ii}$_slansf real(dp) module function stdlib${ii}$_dlansf( norm, transr, uplo, n, a, work ) !! DLANSF returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real symmetric matrix A in RFP format. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, transr, uplo integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(in) :: a(0_${ik}$:*) real(dp), intent(out) :: work(0_${ik}$:*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, ifm, ilu, noe, n1, k, l, lda real(dp) :: scale, s, value, aa, temp ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then stdlib${ii}$_dlansf = zero return else if( n==1_${ik}$ ) then stdlib${ii}$_dlansf = abs( a(0_${ik}$) ) return end if ! set noe = 1 if n is odd. if n is even set noe=0 noe = 1_${ik}$ if( mod( n, 2_${ik}$ )==0_${ik}$ )noe = 0_${ik}$ ! set ifm = 0 when form='t or 't' and 1 otherwise ifm = 1_${ik}$ if( stdlib_lsame( transr, 'T' ) )ifm = 0_${ik}$ ! set ilu = 0 when uplo='u or 'u' and 1 otherwise ilu = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) )ilu = 0_${ik}$ ! set lda = (n+1)/2 when ifm = 0 ! set lda = n when ifm = 1 and noe = 1 ! set lda = n+1 when ifm = 1 and noe = 0 if( ifm==1_${ik}$ ) then if( noe==1_${ik}$ ) then lda = n else ! noe=0 lda = n + 1_${ik}$ end if else ! ifm=0 lda = ( n+1 ) / 2_${ik}$ end if if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). k = ( n+1 ) / 2_${ik}$ value = zero if( noe==1_${ik}$ ) then ! n is odd if( ifm==1_${ik}$ ) then ! a is n by k do j = 0, k - 1 do i = 0, n - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do else ! xpose case; a is k by n do j = 0, n - 1 do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do end if else ! n is even if( ifm==1_${ik}$ ) then ! a is n+1 by k do j = 0, k - 1 do i = 0, n temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do else ! xpose case; a is k by n+1 do j = 0, n do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end do end if end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). if( ifm==1_${ik}$ ) then k = n / 2_${ik}$ if( noe==1_${ik}$ ) then ! n is odd if( ilu==0_${ik}$ ) then do i = 0, k - 1 work( i ) = zero end do do j = 0, k s = zero do i = 0, k + j - 1 aa = abs( a( i+j*lda ) ) ! -> a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) work( j+k ) = s + aa if( i==k+k )go to 10 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do 10 continue value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do else ! ilu = 1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do if( j>0_${ik}$ ) then aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ end if aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then do i = 0, k - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k + j - 1 aa = abs( a( i+j*lda ) ) ! -> a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) work( j+k ) = s + aa i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do else ! ilu = 1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end if end if else ! ifm=0 k = n / 2_${ik}$ if( noe==1_${ik}$ ) then ! n is odd if( ilu==0_${ik}$ ) then n1 = k ! n/2 k = k + 1_${ik}$ ! k is the row size and lda do i = n1, n - 1 work( i ) = zero end do do j = 0, n1 - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,n1+i) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = s end do ! j=n1=k-1 is special s = abs( a( 0_${ik}$+j*lda ) ) ! a(k-1,k-1) do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k-1,i+n1) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k, n - 1 s = zero do i = 0, j - k - 1 aa = abs( a( i+j*lda ) ) ! a(i,j-k) work( i ) = work( i ) + aa s = s + aa end do ! i=j-k aa = abs( a( i+j*lda ) ) ! a(j-k,j-k) s = s + aa work( j-k ) = work( j-k ) + s i = i + 1_${ik}$ s = abs( a( i+j*lda ) ) ! a(j,j) do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do else ! ilu=1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = 0, k - 2 ! process s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( a( i+j*lda ) ) ! i=j so process of a(j,j) s = s + aa work( j ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( a( i+j*lda ) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k-1 is special :process col a(k-1,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( a( i+j*lda ) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k, n - 1 ! process col j of a = a(j,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then do i = k, n - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i+k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = s end do ! j=k aa = abs( a( 0_${ik}$+j*lda ) ) ! a(k,k) s = aa do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k,k+i) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k + 1, n - 1 s = zero do i = 0, j - 2 - k aa = abs( a( i+j*lda ) ) ! a(i,j-k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=j-1-k aa = abs( a( i+j*lda ) ) ! a(j-k-1,j-k-1) s = s + aa work( j-k-1 ) = work( j-k-1 ) + s i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,j) s = aa do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do ! j=n s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(i,k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( a( i+j*lda ) ) ! a(k-1,k-1) s = s + aa work( i ) = work( i ) + s value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do else ! ilu=1 do i = k, n - 1 work( i ) = zero end do ! j=0 is special :process col a(k:n-1,k) s = abs( a( 0_${ik}$ ) ) ! a(k,k) do i = 1, k - 1 aa = abs( a( i ) ) ! a(k+i,k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( k ) = work( k ) + s do j = 1, k - 1 ! process s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( a( i+j*lda ) ) ! i=j-1 so process of a(j-1,j-1) s = s + aa work( j-1 ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( a( i+j*lda ) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k is special :process col a(k,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( a( i+j*lda ) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k + 1, n ! process col j-1 of a = a(j-1,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do work( j-1 ) = work( j-1 ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_disnan( temp ) )value = temp end do end if end if end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). k = ( n+1 ) / 2_${ik}$ scale = zero s = one if( noe==1_${ik}$ ) then ! n is odd if( ifm==1_${ik}$ ) then ! a is normal if( ilu==0_${ik}$ ) then ! a is upper do j = 0, k - 3 call stdlib${ii}$_dlassq( k-j-2, a( k+j+1+j*lda ), 1_${ik}$, scale, s ) ! l at a(k,0) end do do j = 0, k - 1 call stdlib${ii}$_dlassq( k+j-1, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! trap u at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_dlassq( k-1, a( k ), lda+1, scale, s ) ! tri l at a(k,0) call stdlib${ii}$_dlassq( k, a( k-1 ), lda+1, scale, s ) ! tri u at a(k-1,0) else ! ilu=1 do j = 0, k - 1 call stdlib${ii}$_dlassq( n-j-1, a( j+1+j*lda ), 1_${ik}$, scale, s ) ! trap l at a(0,0) end do do j = 0, k - 2 call stdlib${ii}$_dlassq( j, a( 0_${ik}$+( 1_${ik}$+j )*lda ), 1_${ik}$, scale, s ) ! u at a(0,1) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_dlassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri l at a(0,0) call stdlib${ii}$_dlassq( k-1, a( 0_${ik}$+lda ), lda+1, scale, s ) ! tri u at a(0,1) end if else ! a is xpose if( ilu==0_${ik}$ ) then ! a**t is upper do j = 1, k - 2 call stdlib${ii}$_dlassq( j, a( 0_${ik}$+( k+j )*lda ), 1_${ik}$, scale, s ) ! u at a(0,k) end do do j = 0, k - 2 call stdlib${ii}$_dlassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k-1 rect. at a(0,0) end do do j = 0, k - 2 call stdlib${ii}$_dlassq( k-j-1, a( j+1+( j+k-1 )*lda ), 1_${ik}$,scale, s ) ! l at a(0,k-1) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_dlassq( k-1, a( 0_${ik}$+k*lda ), lda+1, scale, s ) ! tri u at a(0,k) call stdlib${ii}$_dlassq( k, a( 0_${ik}$+( k-1 )*lda ), lda+1, scale, s ) ! tri l at a(0,k-1) else ! a**t is lower do j = 1, k - 1 call stdlib${ii}$_dlassq( j, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! u at a(0,0) end do do j = k, n - 1 call stdlib${ii}$_dlassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k-1 rect. at a(0,k) end do do j = 0, k - 3 call stdlib${ii}$_dlassq( k-j-2, a( j+2+j*lda ), 1_${ik}$, scale, s ) ! l at a(1,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_dlassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri u at a(0,0) call stdlib${ii}$_dlassq( k-1, a( 1_${ik}$ ), lda+1, scale, s ) ! tri l at a(1,0) end if end if else ! n is even if( ifm==1_${ik}$ ) then ! a is normal if( ilu==0_${ik}$ ) then ! a is upper do j = 0, k - 2 call stdlib${ii}$_dlassq( k-j-1, a( k+j+2+j*lda ), 1_${ik}$, scale, s ) ! l at a(k+1,0) end do do j = 0, k - 1 call stdlib${ii}$_dlassq( k+j, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! trap u at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_dlassq( k, a( k+1 ), lda+1, scale, s ) ! tri l at a(k+1,0) call stdlib${ii}$_dlassq( k, a( k ), lda+1, scale, s ) ! tri u at a(k,0) else ! ilu=1 do j = 0, k - 1 call stdlib${ii}$_dlassq( n-j-1, a( j+2+j*lda ), 1_${ik}$, scale, s ) ! trap l at a(1,0) end do do j = 1, k - 1 call stdlib${ii}$_dlassq( j, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! u at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_dlassq( k, a( 1_${ik}$ ), lda+1, scale, s ) ! tri l at a(1,0) call stdlib${ii}$_dlassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri u at a(0,0) end if else ! a is xpose if( ilu==0_${ik}$ ) then ! a**t is upper do j = 1, k - 1 call stdlib${ii}$_dlassq( j, a( 0_${ik}$+( k+1+j )*lda ), 1_${ik}$, scale, s ) ! u at a(0,k+1) end do do j = 0, k - 1 call stdlib${ii}$_dlassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k rect. at a(0,0) end do do j = 0, k - 2 call stdlib${ii}$_dlassq( k-j-1, a( j+1+( j+k )*lda ), 1_${ik}$, scale,s ) ! l at a(0,k) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_dlassq( k, a( 0_${ik}$+( k+1 )*lda ), lda+1, scale, s ) ! tri u at a(0,k+1) call stdlib${ii}$_dlassq( k, a( 0_${ik}$+k*lda ), lda+1, scale, s ) ! tri l at a(0,k) else ! a**t is lower do j = 1, k - 1 call stdlib${ii}$_dlassq( j, a( 0_${ik}$+( j+1 )*lda ), 1_${ik}$, scale, s ) ! u at a(0,1) end do do j = k + 1, n call stdlib${ii}$_dlassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k rect. at a(0,k+1) end do do j = 0, k - 2 call stdlib${ii}$_dlassq( k-j-1, a( j+1+j*lda ), 1_${ik}$, scale, s ) ! l at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_dlassq( k, a( lda ), lda+1, scale, s ) ! tri l at a(0,1) call stdlib${ii}$_dlassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri u at a(0,0) end if end if end if value = scale*sqrt( s ) end if stdlib${ii}$_dlansf = value return end function stdlib${ii}$_dlansf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lansf( norm, transr, uplo, n, a, work ) !! DLANSF: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real symmetric matrix A in RFP format. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, transr, uplo integer(${ik}$), intent(in) :: n ! Array Arguments real(${rk}$), intent(in) :: a(0_${ik}$:*) real(${rk}$), intent(out) :: work(0_${ik}$:*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, ifm, ilu, noe, n1, k, l, lda real(${rk}$) :: scale, s, value, aa, temp ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then stdlib${ii}$_${ri}$lansf = zero return else if( n==1_${ik}$ ) then stdlib${ii}$_${ri}$lansf = abs( a(0_${ik}$) ) return end if ! set noe = 1 if n is odd. if n is even set noe=0 noe = 1_${ik}$ if( mod( n, 2_${ik}$ )==0_${ik}$ )noe = 0_${ik}$ ! set ifm = 0 when form='t or 't' and 1 otherwise ifm = 1_${ik}$ if( stdlib_lsame( transr, 'T' ) )ifm = 0_${ik}$ ! set ilu = 0 when uplo='u or 'u' and 1 otherwise ilu = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) )ilu = 0_${ik}$ ! set lda = (n+1)/2 when ifm = 0 ! set lda = n when ifm = 1 and noe = 1 ! set lda = n+1 when ifm = 1 and noe = 0 if( ifm==1_${ik}$ ) then if( noe==1_${ik}$ ) then lda = n else ! noe=0 lda = n + 1_${ik}$ end if else ! ifm=0 lda = ( n+1 ) / 2_${ik}$ end if if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). k = ( n+1 ) / 2_${ik}$ value = zero if( noe==1_${ik}$ ) then ! n is odd if( ifm==1_${ik}$ ) then ! a is n by k do j = 0, k - 1 do i = 0, n - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do end do else ! xpose case; a is k by n do j = 0, n - 1 do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do end do end if else ! n is even if( ifm==1_${ik}$ ) then ! a is n+1 by k do j = 0, k - 1 do i = 0, n temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do end do else ! xpose case; a is k by n+1 do j = 0, n do i = 0, k - 1 temp = abs( a( i+j*lda ) ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do end do end if end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). if( ifm==1_${ik}$ ) then k = n / 2_${ik}$ if( noe==1_${ik}$ ) then ! n is odd if( ilu==0_${ik}$ ) then do i = 0, k - 1 work( i ) = zero end do do j = 0, k s = zero do i = 0, k + j - 1 aa = abs( a( i+j*lda ) ) ! -> a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) work( j+k ) = s + aa if( i==k+k )go to 10 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do 10 continue value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do else ! ilu = 1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do if( j>0_${ik}$ ) then aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ end if aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then do i = 0, k - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k + j - 1 aa = abs( a( i+j*lda ) ) ! -> a(i,j+k) s = s + aa work( i ) = work( i ) + aa end do aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) work( j+k ) = s + aa i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = work( j ) + aa s = zero do l = j + 1, k - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do else ! ilu = 1 do i = k, n - 1 work( i ) = zero end do do j = k - 1, 0, -1 s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! -> a(j+k,i+k) s = s + aa work( i+k ) = work( i+k ) + aa end do aa = abs( a( i+j*lda ) ) ! -> a(j+k,j+k) s = s + aa work( i+k ) = work( i+k ) + s ! i=j i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(j,j) work( j ) = aa s = zero do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! -> a(l,j) s = s + aa work( l ) = work( l ) + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do end if end if else ! ifm=0 k = n / 2_${ik}$ if( noe==1_${ik}$ ) then ! n is odd if( ilu==0_${ik}$ ) then n1 = k ! n/2 k = k + 1_${ik}$ ! k is the row size and lda do i = n1, n - 1 work( i ) = zero end do do j = 0, n1 - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,n1+i) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = s end do ! j=n1=k-1 is special s = abs( a( 0_${ik}$+j*lda ) ) ! a(k-1,k-1) do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k-1,i+n1) work( i+n1 ) = work( i+n1 ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k, n - 1 s = zero do i = 0, j - k - 1 aa = abs( a( i+j*lda ) ) ! a(i,j-k) work( i ) = work( i ) + aa s = s + aa end do ! i=j-k aa = abs( a( i+j*lda ) ) ! a(j-k,j-k) s = s + aa work( j-k ) = work( j-k ) + s i = i + 1_${ik}$ s = abs( a( i+j*lda ) ) ! a(j,j) do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do else ! ilu=1 k = k + 1_${ik}$ ! k=(n+1)/2 for n odd and ilu=1 do i = k, n - 1 work( i ) = zero end do do j = 0, k - 2 ! process s = zero do i = 0, j - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( a( i+j*lda ) ) ! i=j so process of a(j,j) s = s + aa work( j ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( a( i+j*lda ) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k-1 is special :process col a(k-1,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( a( i+j*lda ) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k, n - 1 ! process col j of a = a(j,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i) work( i ) = work( i ) + aa s = s + aa end do work( j ) = work( j ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do end if else ! n is even if( ilu==0_${ik}$ ) then do i = k, n - 1 work( i ) = zero end do do j = 0, k - 1 s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j,i+k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = s end do ! j=k aa = abs( a( 0_${ik}$+j*lda ) ) ! a(k,k) s = aa do i = 1, k - 1 aa = abs( a( i+j*lda ) ) ! a(k,k+i) work( i+k ) = work( i+k ) + aa s = s + aa end do work( j ) = work( j ) + s do j = k + 1, n - 1 s = zero do i = 0, j - 2 - k aa = abs( a( i+j*lda ) ) ! a(i,j-k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=j-1-k aa = abs( a( i+j*lda ) ) ! a(j-k-1,j-k-1) s = s + aa work( j-k-1 ) = work( j-k-1 ) + s i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,j) s = aa do l = j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(j,l) work( l ) = work( l ) + aa s = s + aa end do work( j ) = work( j ) + s end do ! j=n s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(i,k-1) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( a( i+j*lda ) ) ! a(k-1,k-1) s = s + aa work( i ) = work( i ) + s value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do else ! ilu=1 do i = k, n - 1 work( i ) = zero end do ! j=0 is special :process col a(k:n-1,k) s = abs( a( 0_${ik}$ ) ) ! a(k,k) do i = 1, k - 1 aa = abs( a( i ) ) ! a(k+i,k) work( i+k ) = work( i+k ) + aa s = s + aa end do work( k ) = work( k ) + s do j = 1, k - 1 ! process s = zero do i = 0, j - 2 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do aa = abs( a( i+j*lda ) ) ! i=j-1 so process of a(j-1,j-1) s = s + aa work( j-1 ) = s ! is initialised here i = i + 1_${ik}$ ! i=j process a(j+k,j+k) aa = abs( a( i+j*lda ) ) s = aa do l = k + j + 1, n - 1 i = i + 1_${ik}$ aa = abs( a( i+j*lda ) ) ! a(l,k+j) s = s + aa work( l ) = work( l ) + aa end do work( k+j ) = work( k+j ) + s end do ! j=k is special :process col a(k,0:k-1) s = zero do i = 0, k - 2 aa = abs( a( i+j*lda ) ) ! a(k,i) work( i ) = work( i ) + aa s = s + aa end do ! i=k-1 aa = abs( a( i+j*lda ) ) ! a(k-1,k-1) s = s + aa work( i ) = s ! done with col j=k+1 do j = k + 1, n ! process col j-1 of a = a(j-1,0:k-1) s = zero do i = 0, k - 1 aa = abs( a( i+j*lda ) ) ! a(j-1,i) work( i ) = work( i ) + aa s = s + aa end do work( j-1 ) = work( j-1 ) + s end do value = work( 0_${ik}$ ) do i = 1, n-1 temp = work( i ) if( value < temp .or. stdlib${ii}$_${ri}$isnan( temp ) )value = temp end do end if end if end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). k = ( n+1 ) / 2_${ik}$ scale = zero s = one if( noe==1_${ik}$ ) then ! n is odd if( ifm==1_${ik}$ ) then ! a is normal if( ilu==0_${ik}$ ) then ! a is upper do j = 0, k - 3 call stdlib${ii}$_${ri}$lassq( k-j-2, a( k+j+1+j*lda ), 1_${ik}$, scale, s ) ! l at a(k,0) end do do j = 0, k - 1 call stdlib${ii}$_${ri}$lassq( k+j-1, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! trap u at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_${ri}$lassq( k-1, a( k ), lda+1, scale, s ) ! tri l at a(k,0) call stdlib${ii}$_${ri}$lassq( k, a( k-1 ), lda+1, scale, s ) ! tri u at a(k-1,0) else ! ilu=1 do j = 0, k - 1 call stdlib${ii}$_${ri}$lassq( n-j-1, a( j+1+j*lda ), 1_${ik}$, scale, s ) ! trap l at a(0,0) end do do j = 0, k - 2 call stdlib${ii}$_${ri}$lassq( j, a( 0_${ik}$+( 1_${ik}$+j )*lda ), 1_${ik}$, scale, s ) ! u at a(0,1) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_${ri}$lassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri l at a(0,0) call stdlib${ii}$_${ri}$lassq( k-1, a( 0_${ik}$+lda ), lda+1, scale, s ) ! tri u at a(0,1) end if else ! a is xpose if( ilu==0_${ik}$ ) then ! a**t is upper do j = 1, k - 2 call stdlib${ii}$_${ri}$lassq( j, a( 0_${ik}$+( k+j )*lda ), 1_${ik}$, scale, s ) ! u at a(0,k) end do do j = 0, k - 2 call stdlib${ii}$_${ri}$lassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k-1 rect. at a(0,0) end do do j = 0, k - 2 call stdlib${ii}$_${ri}$lassq( k-j-1, a( j+1+( j+k-1 )*lda ), 1_${ik}$,scale, s ) ! l at a(0,k-1) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_${ri}$lassq( k-1, a( 0_${ik}$+k*lda ), lda+1, scale, s ) ! tri u at a(0,k) call stdlib${ii}$_${ri}$lassq( k, a( 0_${ik}$+( k-1 )*lda ), lda+1, scale, s ) ! tri l at a(0,k-1) else ! a**t is lower do j = 1, k - 1 call stdlib${ii}$_${ri}$lassq( j, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! u at a(0,0) end do do j = k, n - 1 call stdlib${ii}$_${ri}$lassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k-1 rect. at a(0,k) end do do j = 0, k - 3 call stdlib${ii}$_${ri}$lassq( k-j-2, a( j+2+j*lda ), 1_${ik}$, scale, s ) ! l at a(1,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_${ri}$lassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri u at a(0,0) call stdlib${ii}$_${ri}$lassq( k-1, a( 1_${ik}$ ), lda+1, scale, s ) ! tri l at a(1,0) end if end if else ! n is even if( ifm==1_${ik}$ ) then ! a is normal if( ilu==0_${ik}$ ) then ! a is upper do j = 0, k - 2 call stdlib${ii}$_${ri}$lassq( k-j-1, a( k+j+2+j*lda ), 1_${ik}$, scale, s ) ! l at a(k+1,0) end do do j = 0, k - 1 call stdlib${ii}$_${ri}$lassq( k+j, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! trap u at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_${ri}$lassq( k, a( k+1 ), lda+1, scale, s ) ! tri l at a(k+1,0) call stdlib${ii}$_${ri}$lassq( k, a( k ), lda+1, scale, s ) ! tri u at a(k,0) else ! ilu=1 do j = 0, k - 1 call stdlib${ii}$_${ri}$lassq( n-j-1, a( j+2+j*lda ), 1_${ik}$, scale, s ) ! trap l at a(1,0) end do do j = 1, k - 1 call stdlib${ii}$_${ri}$lassq( j, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! u at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_${ri}$lassq( k, a( 1_${ik}$ ), lda+1, scale, s ) ! tri l at a(1,0) call stdlib${ii}$_${ri}$lassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri u at a(0,0) end if else ! a is xpose if( ilu==0_${ik}$ ) then ! a**t is upper do j = 1, k - 1 call stdlib${ii}$_${ri}$lassq( j, a( 0_${ik}$+( k+1+j )*lda ), 1_${ik}$, scale, s ) ! u at a(0,k+1) end do do j = 0, k - 1 call stdlib${ii}$_${ri}$lassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k rect. at a(0,0) end do do j = 0, k - 2 call stdlib${ii}$_${ri}$lassq( k-j-1, a( j+1+( j+k )*lda ), 1_${ik}$, scale,s ) ! l at a(0,k) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_${ri}$lassq( k, a( 0_${ik}$+( k+1 )*lda ), lda+1, scale, s ) ! tri u at a(0,k+1) call stdlib${ii}$_${ri}$lassq( k, a( 0_${ik}$+k*lda ), lda+1, scale, s ) ! tri l at a(0,k) else ! a**t is lower do j = 1, k - 1 call stdlib${ii}$_${ri}$lassq( j, a( 0_${ik}$+( j+1 )*lda ), 1_${ik}$, scale, s ) ! u at a(0,1) end do do j = k + 1, n call stdlib${ii}$_${ri}$lassq( k, a( 0_${ik}$+j*lda ), 1_${ik}$, scale, s ) ! k by k rect. at a(0,k+1) end do do j = 0, k - 2 call stdlib${ii}$_${ri}$lassq( k-j-1, a( j+1+j*lda ), 1_${ik}$, scale, s ) ! l at a(0,0) end do s = s + s ! double s for the off diagonal elements call stdlib${ii}$_${ri}$lassq( k, a( lda ), lda+1, scale, s ) ! tri l at a(0,1) call stdlib${ii}$_${ri}$lassq( k, a( 0_${ik}$ ), lda+1, scale, s ) ! tri u at a(0,0) end if end if end if value = scale*sqrt( s ) end if stdlib${ii}$_${ri}$lansf = value return end function stdlib${ii}$_${ri}$lansf #:endif #:endfor real(sp) module function stdlib${ii}$_clanhp( norm, uplo, n, ap, work ) !! CLANHP returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex hermitian matrix A, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ap(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, k real(sp) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then k = 0_${ik}$ do j = 1, n do i = k + 1, k + j - 1 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do k = k + j sum = abs( real( ap( k ),KIND=sp) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else k = 1_${ik}$ do j = 1, n sum = abs( real( ap( k ),KIND=sp) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum do i = k + 1, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is hermitian). value = zero k = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero do i = 1, j - 1 absa = abs( ap( k ) ) sum = sum + absa work( i ) = work( i ) + absa k = k + 1_${ik}$ end do work( j ) = sum + abs( real( ap( k ),KIND=sp) ) k = k + 1_${ik}$ end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( real( ap( k ),KIND=sp) ) k = k + 1_${ik}$ do i = j + 1, n absa = abs( ap( k ) ) sum = sum + absa work( i ) = work( i ) + absa k = k + 1_${ik}$ end do if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one k = 2_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_classq( j-1, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do else do j = 1, n - 1 call stdlib${ii}$_classq( n-j, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do end if sum = 2_${ik}$*sum k = 1_${ik}$ do i = 1, n if( real( ap( k ),KIND=sp)/=zero ) then absa = abs( real( ap( k ),KIND=sp) ) if( scale0_${ik}$ ) then if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_classq( min( j-1, k ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do l = k + 1_${ik}$ else do j = 1, n - 1 call stdlib${ii}$_classq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do l = 1_${ik}$ end if sum = 2_${ik}$*sum else l = 1_${ik}$ end if do j = 1, n if( real( ab( l, j ),KIND=sp)/=zero ) then absa = abs( real( ab( l, j ),KIND=sp) ) if( scale0_${ik}$ ) then if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_zlassq( min( j-1, k ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do l = k + 1_${ik}$ else do j = 1, n - 1 call stdlib${ii}$_zlassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do l = 1_${ik}$ end if sum = 2_${ik}$*sum else l = 1_${ik}$ end if do j = 1, n if( real( ab( l, j ),KIND=dp)/=zero ) then absa = abs( real( ab( l, j ),KIND=dp) ) if( scale0_${ik}$ ) then if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_${ci}$lassq( min( j-1, k ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do l = k + 1_${ik}$ else do j = 1, n - 1 call stdlib${ii}$_${ci}$lassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do l = 1_${ik}$ end if sum = 2_${ik}$*sum else l = 1_${ik}$ end if do j = 1, n if( real( ab( l, j ),KIND=${ck}$)/=zero ) then absa = abs( real( ab( l, j ),KIND=${ck}$) ) if( scale0_${ik}$ ) then if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_slassq( min( j-1, k ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do l = k + 1_${ik}$ else do j = 1, n - 1 call stdlib${ii}$_slassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do l = 1_${ik}$ end if sum = 2_${ik}$*sum else l = 1_${ik}$ end if call stdlib${ii}$_slassq( n, ab( l, 1_${ik}$ ), ldab, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_slansb = value return end function stdlib${ii}$_slansb real(dp) module function stdlib${ii}$_dlansb( norm, uplo, n, k, ab, ldab,work ) !! DLANSB returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n symmetric band matrix A, with k super-diagonals. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n ! Array Arguments real(dp), intent(in) :: ab(ldab,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, l real(dp) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k + 1 sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = 1, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero l = k + 1_${ik}$ - j do i = max( 1, j-k ), j - 1 absa = abs( ab( l+i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( ab( k+1, j ) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( ab( 1_${ik}$, j ) ) l = 1_${ik}$ - j do i = j + 1, min( n, j+k ) absa = abs( ab( l+i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( k>0_${ik}$ ) then if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_dlassq( min( j-1, k ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do l = k + 1_${ik}$ else do j = 1, n - 1 call stdlib${ii}$_dlassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do l = 1_${ik}$ end if sum = 2_${ik}$*sum else l = 1_${ik}$ end if call stdlib${ii}$_dlassq( n, ab( l, 1_${ik}$ ), ldab, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_dlansb = value return end function stdlib${ii}$_dlansb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lansb( norm, uplo, n, k, ab, ldab,work ) !! DLANSB: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n symmetric band matrix A, with k super-diagonals. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n ! Array Arguments real(${rk}$), intent(in) :: ab(ldab,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, l real(${rk}$) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k + 1 sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = 1, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero l = k + 1_${ik}$ - j do i = max( 1, j-k ), j - 1 absa = abs( ab( l+i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( ab( k+1, j ) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( ab( 1_${ik}$, j ) ) l = 1_${ik}$ - j do i = j + 1, min( n, j+k ) absa = abs( ab( l+i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( k>0_${ik}$ ) then if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_${ri}$lassq( min( j-1, k ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do l = k + 1_${ik}$ else do j = 1, n - 1 call stdlib${ii}$_${ri}$lassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do l = 1_${ik}$ end if sum = 2_${ik}$*sum else l = 1_${ik}$ end if call stdlib${ii}$_${ri}$lassq( n, ab( l, 1_${ik}$ ), ldab, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_${ri}$lansb = value return end function stdlib${ii}$_${ri}$lansb #:endif #:endfor real(sp) module function stdlib${ii}$_clansb( norm, uplo, n, k, ab, ldab,work ) !! CLANSB returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n symmetric band matrix A, with k super-diagonals. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n ! Array Arguments real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, l real(sp) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k + 1 sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else do j = 1, n do i = 1, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero l = k + 1_${ik}$ - j do i = max( 1, j-k ), j - 1 absa = abs( ab( l+i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( ab( k+1, j ) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( ab( 1_${ik}$, j ) ) l = 1_${ik}$ - j do i = j + 1, min( n, j+k ) absa = abs( ab( l+i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( k>0_${ik}$ ) then if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_classq( min( j-1, k ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do l = k + 1_${ik}$ else do j = 1, n - 1 call stdlib${ii}$_classq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do l = 1_${ik}$ end if sum = 2_${ik}$*sum else l = 1_${ik}$ end if call stdlib${ii}$_classq( n, ab( l, 1_${ik}$ ), ldab, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_clansb = value return end function stdlib${ii}$_clansb real(dp) module function stdlib${ii}$_zlansb( norm, uplo, n, k, ab, ldab,work ) !! ZLANSB returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n symmetric band matrix A, with k super-diagonals. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n ! Array Arguments real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, l real(dp) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k + 1 sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = 1, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero l = k + 1_${ik}$ - j do i = max( 1, j-k ), j - 1 absa = abs( ab( l+i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( ab( k+1, j ) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( ab( 1_${ik}$, j ) ) l = 1_${ik}$ - j do i = j + 1, min( n, j+k ) absa = abs( ab( l+i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( k>0_${ik}$ ) then if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_zlassq( min( j-1, k ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do l = k + 1_${ik}$ else do j = 1, n - 1 call stdlib${ii}$_zlassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do l = 1_${ik}$ end if sum = 2_${ik}$*sum else l = 1_${ik}$ end if call stdlib${ii}$_zlassq( n, ab( l, 1_${ik}$ ), ldab, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_zlansb = value return end function stdlib${ii}$_zlansb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lansb( norm, uplo, n, k, ab, ldab,work ) !! ZLANSB: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n symmetric band matrix A, with k super-diagonals. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: k, ldab, n ! Array Arguments real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, l real(${ck}$) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k + 1 sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = 1, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero l = k + 1_${ik}$ - j do i = max( 1, j-k ), j - 1 absa = abs( ab( l+i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( ab( k+1, j ) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( ab( 1_${ik}$, j ) ) l = 1_${ik}$ - j do i = j + 1, min( n, j+k ) absa = abs( ab( l+i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( k>0_${ik}$ ) then if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_${ci}$lassq( min( j-1, k ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do l = k + 1_${ik}$ else do j = 1, n - 1 call stdlib${ii}$_${ci}$lassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do l = 1_${ik}$ end if sum = 2_${ik}$*sum else l = 1_${ik}$ end if call stdlib${ii}$_${ci}$lassq( n, ab( l, 1_${ik}$ ), ldab, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_${ci}$lansb = value return end function stdlib${ii}$_${ci}$lansb #:endif #:endfor pure real(sp) module function stdlib${ii}$_clanht( norm, n, d, e ) !! CLANHT returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex Hermitian tridiagonal matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(in) :: d(*) complex(sp), intent(in) :: e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(sp) :: anorm, scale, sum ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then anorm = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). anorm = abs( d( n ) ) do i = 1, n - 1 sum = abs( d( i ) ) if( anorm < sum .or. stdlib${ii}$_sisnan( sum ) ) anorm = sum sum = abs( e( i ) ) if( anorm < sum .or. stdlib${ii}$_sisnan( sum ) ) anorm = sum end do else if( stdlib_lsame( norm, 'O' ) .or. norm=='1' .or.stdlib_lsame( norm, 'I' ) ) & then ! find norm1(a). if( n==1_${ik}$ ) then anorm = abs( d( 1_${ik}$ ) ) else anorm = abs( d( 1_${ik}$ ) )+abs( e( 1_${ik}$ ) ) sum = abs( e( n-1 ) )+abs( d( n ) ) if( anorm < sum .or. stdlib${ii}$_sisnan( sum ) ) anorm = sum do i = 2, n - 1 sum = abs( d( i ) )+abs( e( i ) )+abs( e( i-1 ) ) if( anorm < sum .or. stdlib${ii}$_sisnan( sum ) ) anorm = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( n>1_${ik}$ ) then call stdlib${ii}$_classq( n-1, e, 1_${ik}$, scale, sum ) sum = 2_${ik}$*sum end if call stdlib${ii}$_slassq( n, d, 1_${ik}$, scale, sum ) anorm = scale*sqrt( sum ) end if stdlib${ii}$_clanht = anorm return end function stdlib${ii}$_clanht pure real(dp) module function stdlib${ii}$_zlanht( norm, n, d, e ) !! ZLANHT returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex Hermitian tridiagonal matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(in) :: d(*) complex(dp), intent(in) :: e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(dp) :: anorm, scale, sum ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then anorm = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). anorm = abs( d( n ) ) do i = 1, n - 1 sum = abs( d( i ) ) if( anorm < sum .or. stdlib${ii}$_disnan( sum ) ) anorm = sum sum = abs( e( i ) ) if( anorm < sum .or. stdlib${ii}$_disnan( sum ) ) anorm = sum end do else if( stdlib_lsame( norm, 'O' ) .or. norm=='1' .or.stdlib_lsame( norm, 'I' ) ) & then ! find norm1(a). if( n==1_${ik}$ ) then anorm = abs( d( 1_${ik}$ ) ) else anorm = abs( d( 1_${ik}$ ) )+abs( e( 1_${ik}$ ) ) sum = abs( e( n-1 ) )+abs( d( n ) ) if( anorm < sum .or. stdlib${ii}$_disnan( sum ) ) anorm = sum do i = 2, n - 1 sum = abs( d( i ) )+abs( e( i ) )+abs( e( i-1 ) ) if( anorm < sum .or. stdlib${ii}$_disnan( sum ) ) anorm = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( n>1_${ik}$ ) then call stdlib${ii}$_zlassq( n-1, e, 1_${ik}$, scale, sum ) sum = 2_${ik}$*sum end if call stdlib${ii}$_dlassq( n, d, 1_${ik}$, scale, sum ) anorm = scale*sqrt( sum ) end if stdlib${ii}$_zlanht = anorm return end function stdlib${ii}$_zlanht #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure real(${ck}$) module function stdlib${ii}$_${ci}$lanht( norm, n, d, e ) !! ZLANHT: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex Hermitian tridiagonal matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: n ! Array Arguments real(${ck}$), intent(in) :: d(*) complex(${ck}$), intent(in) :: e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(${ck}$) :: anorm, scale, sum ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then anorm = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). anorm = abs( d( n ) ) do i = 1, n - 1 sum = abs( d( i ) ) if( anorm < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) anorm = sum sum = abs( e( i ) ) if( anorm < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) anorm = sum end do else if( stdlib_lsame( norm, 'O' ) .or. norm=='1' .or.stdlib_lsame( norm, 'I' ) ) & then ! find norm1(a). if( n==1_${ik}$ ) then anorm = abs( d( 1_${ik}$ ) ) else anorm = abs( d( 1_${ik}$ ) )+abs( e( 1_${ik}$ ) ) sum = abs( e( n-1 ) )+abs( d( n ) ) if( anorm < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) anorm = sum do i = 2, n - 1 sum = abs( d( i ) )+abs( e( i ) )+abs( e( i-1 ) ) if( anorm < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) anorm = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( n>1_${ik}$ ) then call stdlib${ii}$_${ci}$lassq( n-1, e, 1_${ik}$, scale, sum ) sum = 2_${ik}$*sum end if call stdlib${ii}$_${c2ri(ci)}$lassq( n, d, 1_${ik}$, scale, sum ) anorm = scale*sqrt( sum ) end if stdlib${ii}$_${ci}$lanht = anorm return end function stdlib${ii}$_${ci}$lanht #:endif #:endfor pure real(sp) module function stdlib${ii}$_slanst( norm, n, d, e ) !! SLANST returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real symmetric tridiagonal matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(in) :: d(*), e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(sp) :: anorm, scale, sum ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then anorm = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). anorm = abs( d( n ) ) do i = 1, n - 1 sum = abs( d( i ) ) if( anorm < sum .or. stdlib${ii}$_sisnan( sum ) ) anorm = sum sum = abs( e( i ) ) if( anorm < sum .or. stdlib${ii}$_sisnan( sum ) ) anorm = sum end do else if( stdlib_lsame( norm, 'O' ) .or. norm=='1' .or.stdlib_lsame( norm, 'I' ) ) & then ! find norm1(a). if( n==1_${ik}$ ) then anorm = abs( d( 1_${ik}$ ) ) else anorm = abs( d( 1_${ik}$ ) )+abs( e( 1_${ik}$ ) ) sum = abs( e( n-1 ) )+abs( d( n ) ) if( anorm < sum .or. stdlib${ii}$_sisnan( sum ) ) anorm = sum do i = 2, n - 1 sum = abs( d( i ) )+abs( e( i ) )+abs( e( i-1 ) ) if( anorm < sum .or. stdlib${ii}$_sisnan( sum ) ) anorm = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( n>1_${ik}$ ) then call stdlib${ii}$_slassq( n-1, e, 1_${ik}$, scale, sum ) sum = 2_${ik}$*sum end if call stdlib${ii}$_slassq( n, d, 1_${ik}$, scale, sum ) anorm = scale*sqrt( sum ) end if stdlib${ii}$_slanst = anorm return end function stdlib${ii}$_slanst pure real(dp) module function stdlib${ii}$_dlanst( norm, n, d, e ) !! DLANST returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real symmetric tridiagonal matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(in) :: d(*), e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(dp) :: anorm, scale, sum ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then anorm = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). anorm = abs( d( n ) ) do i = 1, n - 1 sum = abs( d( i ) ) if( anorm < sum .or. stdlib${ii}$_disnan( sum ) ) anorm = sum sum = abs( e( i ) ) if( anorm < sum .or. stdlib${ii}$_disnan( sum ) ) anorm = sum end do else if( stdlib_lsame( norm, 'O' ) .or. norm=='1' .or.stdlib_lsame( norm, 'I' ) ) & then ! find norm1(a). if( n==1_${ik}$ ) then anorm = abs( d( 1_${ik}$ ) ) else anorm = abs( d( 1_${ik}$ ) )+abs( e( 1_${ik}$ ) ) sum = abs( e( n-1 ) )+abs( d( n ) ) if( anorm < sum .or. stdlib${ii}$_disnan( sum ) ) anorm = sum do i = 2, n - 1 sum = abs( d( i ) )+abs( e( i ) )+abs( e( i-1 ) ) if( anorm < sum .or. stdlib${ii}$_disnan( sum ) ) anorm = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( n>1_${ik}$ ) then call stdlib${ii}$_dlassq( n-1, e, 1_${ik}$, scale, sum ) sum = 2_${ik}$*sum end if call stdlib${ii}$_dlassq( n, d, 1_${ik}$, scale, sum ) anorm = scale*sqrt( sum ) end if stdlib${ii}$_dlanst = anorm return end function stdlib${ii}$_dlanst #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$lanst( norm, n, d, e ) !! DLANST: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real symmetric tridiagonal matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(in) :: n ! Array Arguments real(${rk}$), intent(in) :: d(*), e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(${rk}$) :: anorm, scale, sum ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then anorm = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). anorm = abs( d( n ) ) do i = 1, n - 1 sum = abs( d( i ) ) if( anorm < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) anorm = sum sum = abs( e( i ) ) if( anorm < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) anorm = sum end do else if( stdlib_lsame( norm, 'O' ) .or. norm=='1' .or.stdlib_lsame( norm, 'I' ) ) & then ! find norm1(a). if( n==1_${ik}$ ) then anorm = abs( d( 1_${ik}$ ) ) else anorm = abs( d( 1_${ik}$ ) )+abs( e( 1_${ik}$ ) ) sum = abs( e( n-1 ) )+abs( d( n ) ) if( anorm < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) anorm = sum do i = 2, n - 1 sum = abs( d( i ) )+abs( e( i ) )+abs( e( i-1 ) ) if( anorm < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) anorm = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( n>1_${ik}$ ) then call stdlib${ii}$_${ri}$lassq( n-1, e, 1_${ik}$, scale, sum ) sum = 2_${ik}$*sum end if call stdlib${ii}$_${ri}$lassq( n, d, 1_${ik}$, scale, sum ) anorm = scale*sqrt( sum ) end if stdlib${ii}$_${ri}$lanst = anorm return end function stdlib${ii}$_${ri}$lanst #:endif #:endfor real(sp) module function stdlib${ii}$_slantr( norm, uplo, diag, m, n, a, lda,work ) !! SLANTR returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! trapezoidal or triangular matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j real(sp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( min( m, n )==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j-1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else do j = 1, n do i = j + 1, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( ( udiag ) .and. ( j<=m ) ) then sum = one do i = 1, j - 1 sum = sum + abs( a( i, j ) ) end do else sum = zero do i = 1, min( m, j ) sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = j + 1, m sum = sum + abs( a( i, j ) ) end do else sum = zero do i = j, m sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, m work( i ) = one end do do j = 1, n do i = 1, min( m, j-1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = 1, min( m, j ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, min( m, n ) work( i ) = one end do do i = n + 1, m work( i ) = zero end do do j = 1, n do i = j + 1, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = j, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if end if value = zero do i = 1, m sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 2, n call stdlib${ii}$_slassq( min( m, j-1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_slassq( min( m, j ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 1, n call stdlib${ii}$_slassq( m-j, a( min( m, j+1 ), j ), 1_${ik}$, scale,sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_slassq( m-j+1, a( j, j ), 1_${ik}$, scale, sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_slantr = value return end function stdlib${ii}$_slantr real(dp) module function stdlib${ii}$_dlantr( norm, uplo, diag, m, n, a, lda,work ) !! DLANTR returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! trapezoidal or triangular matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j real(dp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( min( m, n )==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j-1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = j + 1, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( ( udiag ) .and. ( j<=m ) ) then sum = one do i = 1, j - 1 sum = sum + abs( a( i, j ) ) end do else sum = zero do i = 1, min( m, j ) sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = j + 1, m sum = sum + abs( a( i, j ) ) end do else sum = zero do i = j, m sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, m work( i ) = one end do do j = 1, n do i = 1, min( m, j-1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = 1, min( m, j ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, min( m, n ) work( i ) = one end do do i = n + 1, m work( i ) = zero end do do j = 1, n do i = j + 1, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = j, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if end if value = zero do i = 1, m sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 2, n call stdlib${ii}$_dlassq( min( m, j-1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_dlassq( min( m, j ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 1, n call stdlib${ii}$_dlassq( m-j, a( min( m, j+1 ), j ), 1_${ik}$, scale,sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_dlassq( m-j+1, a( j, j ), 1_${ik}$, scale, sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_dlantr = value return end function stdlib${ii}$_dlantr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lantr( norm, uplo, diag, m, n, a, lda,work ) !! DLANTR: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! trapezoidal or triangular matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j real(${rk}$) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( min( m, n )==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j-1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = j + 1, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( ( udiag ) .and. ( j<=m ) ) then sum = one do i = 1, j - 1 sum = sum + abs( a( i, j ) ) end do else sum = zero do i = 1, min( m, j ) sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = j + 1, m sum = sum + abs( a( i, j ) ) end do else sum = zero do i = j, m sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, m work( i ) = one end do do j = 1, n do i = 1, min( m, j-1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = 1, min( m, j ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, min( m, n ) work( i ) = one end do do i = n + 1, m work( i ) = zero end do do j = 1, n do i = j + 1, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = j, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if end if value = zero do i = 1, m sum = work( i ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 2, n call stdlib${ii}$_${ri}$lassq( min( m, j-1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_${ri}$lassq( min( m, j ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 1, n call stdlib${ii}$_${ri}$lassq( m-j, a( min( m, j+1 ), j ), 1_${ik}$, scale,sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_${ri}$lassq( m-j+1, a( j, j ), 1_${ik}$, scale, sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_${ri}$lantr = value return end function stdlib${ii}$_${ri}$lantr #:endif #:endfor real(sp) module function stdlib${ii}$_clantr( norm, uplo, diag, m, n, a, lda,work ) !! CLANTR returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! trapezoidal or triangular matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j real(sp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( min( m, n )==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j-1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else do j = 1, n do i = j + 1, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( ( udiag ) .and. ( j<=m ) ) then sum = one do i = 1, j - 1 sum = sum + abs( a( i, j ) ) end do else sum = zero do i = 1, min( m, j ) sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = j + 1, m sum = sum + abs( a( i, j ) ) end do else sum = zero do i = j, m sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, m work( i ) = one end do do j = 1, n do i = 1, min( m, j-1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = 1, min( m, j ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, min( m, n ) work( i ) = one end do do i = n + 1, m work( i ) = zero end do do j = 1, n do i = j + 1, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = j, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if end if value = zero do i = 1, m sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 2, n call stdlib${ii}$_classq( min( m, j-1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_classq( min( m, j ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 1, n call stdlib${ii}$_classq( m-j, a( min( m, j+1 ), j ), 1_${ik}$, scale,sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_classq( m-j+1, a( j, j ), 1_${ik}$, scale, sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_clantr = value return end function stdlib${ii}$_clantr real(dp) module function stdlib${ii}$_zlantr( norm, uplo, diag, m, n, a, lda,work ) !! ZLANTR returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! trapezoidal or triangular matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j real(dp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( min( m, n )==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j-1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = j + 1, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( ( udiag ) .and. ( j<=m ) ) then sum = one do i = 1, j - 1 sum = sum + abs( a( i, j ) ) end do else sum = zero do i = 1, min( m, j ) sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = j + 1, m sum = sum + abs( a( i, j ) ) end do else sum = zero do i = j, m sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, m work( i ) = one end do do j = 1, n do i = 1, min( m, j-1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = 1, min( m, j ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, min( m, n ) work( i ) = one end do do i = n + 1, m work( i ) = zero end do do j = 1, n do i = j + 1, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = j, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if end if value = zero do i = 1, m sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 2, n call stdlib${ii}$_zlassq( min( m, j-1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_zlassq( min( m, j ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 1, n call stdlib${ii}$_zlassq( m-j, a( min( m, j+1 ), j ), 1_${ik}$, scale,sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_zlassq( m-j+1, a( j, j ), 1_${ik}$, scale, sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_zlantr = value return end function stdlib${ii}$_zlantr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lantr( norm, uplo, diag, m, n, a, lda,work ) !! ZLANTR: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! trapezoidal or triangular matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j real(${ck}$) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( min( m, n )==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j-1 ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = j + 1, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, min( m, j ) sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, m sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( ( udiag ) .and. ( j<=m ) ) then sum = one do i = 1, j - 1 sum = sum + abs( a( i, j ) ) end do else sum = zero do i = 1, min( m, j ) sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = j + 1, m sum = sum + abs( a( i, j ) ) end do else sum = zero do i = j, m sum = sum + abs( a( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, m work( i ) = one end do do j = 1, n do i = 1, min( m, j-1 ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = 1, min( m, j ) work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, min( m, n ) work( i ) = one end do do i = n + 1, m work( i ) = zero end do do j = 1, n do i = j + 1, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do else do i = 1, m work( i ) = zero end do do j = 1, n do i = j, m work( i ) = work( i ) + abs( a( i, j ) ) end do end do end if end if value = zero do i = 1, m sum = work( i ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 2, n call stdlib${ii}$_${ci}$lassq( min( m, j-1 ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_${ci}$lassq( min( m, j ), a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = min( m, n ) do j = 1, n call stdlib${ii}$_${ci}$lassq( m-j, a( min( m, j+1 ), j ), 1_${ik}$, scale,sum ) end do else scale = zero sum = one do j = 1, n call stdlib${ii}$_${ci}$lassq( m-j+1, a( j, j ), 1_${ik}$, scale, sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_${ci}$lantr = value return end function stdlib${ii}$_${ci}$lantr #:endif #:endfor real(sp) module function stdlib${ii}$_slantp( norm, uplo, diag, n, ap, work ) !! SLANTP returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! triangular matrix A, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(in) :: ap(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, k real(sp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). k = 1_${ik}$ if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 2 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k + 1, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 1 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero k = 1_${ik}$ udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = k, k + j - 2 sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + j - 1 sum = sum + abs( ap( i ) ) end do end if k = k + j if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = k + 1, k + n - j sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + n - j sum = sum + abs( ap( i ) ) end do end if k = k + n - j + 1_${ik}$ if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). k = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n do i = 1, j - 1 work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do k = k + 1_${ik}$ end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, j work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n k = k + 1_${ik}$ do i = j + 1, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = j, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if end if value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 2, n call stdlib${ii}$_slassq( j-1, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_slassq( j, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 1, n - 1 call stdlib${ii}$_slassq( n-j, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_slassq( n-j+1, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_slantp = value return end function stdlib${ii}$_slantp real(dp) module function stdlib${ii}$_dlantp( norm, uplo, diag, n, ap, work ) !! DLANTP returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! triangular matrix A, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(in) :: ap(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, k real(dp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). k = 1_${ik}$ if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 2 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k + 1, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 1 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero k = 1_${ik}$ udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = k, k + j - 2 sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + j - 1 sum = sum + abs( ap( i ) ) end do end if k = k + j if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = k + 1, k + n - j sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + n - j sum = sum + abs( ap( i ) ) end do end if k = k + n - j + 1_${ik}$ if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). k = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n do i = 1, j - 1 work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do k = k + 1_${ik}$ end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, j work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n k = k + 1_${ik}$ do i = j + 1, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = j, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if end if value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 2, n call stdlib${ii}$_dlassq( j-1, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_dlassq( j, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 1, n - 1 call stdlib${ii}$_dlassq( n-j, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_dlassq( n-j+1, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_dlantp = value return end function stdlib${ii}$_dlantp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lantp( norm, uplo, diag, n, ap, work ) !! DLANTP: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! triangular matrix A, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n ! Array Arguments real(${rk}$), intent(in) :: ap(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, k real(${rk}$) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). k = 1_${ik}$ if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 2 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k + 1, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 1 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero k = 1_${ik}$ udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = k, k + j - 2 sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + j - 1 sum = sum + abs( ap( i ) ) end do end if k = k + j if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = k + 1, k + n - j sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + n - j sum = sum + abs( ap( i ) ) end do end if k = k + n - j + 1_${ik}$ if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). k = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n do i = 1, j - 1 work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do k = k + 1_${ik}$ end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, j work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n k = k + 1_${ik}$ do i = j + 1, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = j, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if end if value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 2, n call stdlib${ii}$_${ri}$lassq( j-1, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_${ri}$lassq( j, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 1, n - 1 call stdlib${ii}$_${ri}$lassq( n-j, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_${ri}$lassq( n-j+1, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_${ri}$lantp = value return end function stdlib${ii}$_${ri}$lantp #:endif #:endfor real(sp) module function stdlib${ii}$_clantp( norm, uplo, diag, n, ap, work ) !! CLANTP returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! triangular matrix A, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ap(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, k real(sp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). k = 1_${ik}$ if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 2 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k + 1, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 1 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero k = 1_${ik}$ udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = k, k + j - 2 sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + j - 1 sum = sum + abs( ap( i ) ) end do end if k = k + j if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = k + 1, k + n - j sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + n - j sum = sum + abs( ap( i ) ) end do end if k = k + n - j + 1_${ik}$ if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). k = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n do i = 1, j - 1 work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do k = k + 1_${ik}$ end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, j work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n k = k + 1_${ik}$ do i = j + 1, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = j, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if end if value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 2, n call stdlib${ii}$_classq( j-1, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_classq( j, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 1, n - 1 call stdlib${ii}$_classq( n-j, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_classq( n-j+1, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_clantp = value return end function stdlib${ii}$_clantp real(dp) module function stdlib${ii}$_zlantp( norm, uplo, diag, n, ap, work ) !! ZLANTP returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! triangular matrix A, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ap(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, k real(dp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). k = 1_${ik}$ if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 2 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k + 1, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 1 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero k = 1_${ik}$ udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = k, k + j - 2 sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + j - 1 sum = sum + abs( ap( i ) ) end do end if k = k + j if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = k + 1, k + n - j sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + n - j sum = sum + abs( ap( i ) ) end do end if k = k + n - j + 1_${ik}$ if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). k = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n do i = 1, j - 1 work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do k = k + 1_${ik}$ end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, j work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n k = k + 1_${ik}$ do i = j + 1, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = j, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if end if value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 2, n call stdlib${ii}$_zlassq( j-1, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_zlassq( j, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 1, n - 1 call stdlib${ii}$_zlassq( n-j, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_zlassq( n-j+1, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_zlantp = value return end function stdlib${ii}$_zlantp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lantp( norm, uplo, diag, n, ap, work ) !! ZLANTP: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! triangular matrix A, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: n ! Array Arguments real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: ap(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, k real(${ck}$) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). k = 1_${ik}$ if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 2 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k + 1, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = k, k + j - 1 sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do k = k + j end do else do j = 1, n do i = k, k + n - j sum = abs( ap( i ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do k = k + n - j + 1_${ik}$ end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero k = 1_${ik}$ udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = k, k + j - 2 sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + j - 1 sum = sum + abs( ap( i ) ) end do end if k = k + j if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = k + 1, k + n - j sum = sum + abs( ap( i ) ) end do else sum = zero do i = k, k + n - j sum = sum + abs( ap( i ) ) end do end if k = k + n - j + 1_${ik}$ if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). k = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n do i = 1, j - 1 work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do k = k + 1_${ik}$ end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = 1, j work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n k = k + 1_${ik}$ do i = j + 1, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do else do i = 1, n work( i ) = zero end do do j = 1, n do i = j, n work( i ) = work( i ) + abs( ap( k ) ) k = k + 1_${ik}$ end do end do end if end if value = zero do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 2, n call stdlib${ii}$_${ci}$lassq( j-1, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_${ci}$lassq( j, ap( k ), 1_${ik}$, scale, sum ) k = k + j end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n k = 2_${ik}$ do j = 1, n - 1 call stdlib${ii}$_${ci}$lassq( n-j, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do else scale = zero sum = one k = 1_${ik}$ do j = 1, n call stdlib${ii}$_${ci}$lassq( n-j+1, ap( k ), 1_${ik}$, scale, sum ) k = k + n - j + 1_${ik}$ end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_${ci}$lantp = value return end function stdlib${ii}$_${ci}$lantp #:endif #:endfor real(sp) module function stdlib${ii}$_slantb( norm, uplo, diag, n, k, ab,ldab, work ) !! SLANTB returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n triangular band matrix A, with ( k + 1 ) diagonals. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n ! Array Arguments real(sp), intent(in) :: ab(ldab,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, l real(sp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else do j = 1, n do i = 2, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k + 1 sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else do j = 1, n do i = 1, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = max( k+2-j, 1 ), k sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = max( k+2-j, 1 ), k + 1 sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = 2, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = 1, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). value = zero if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j - 1 work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = 1_${ik}$ - j do i = j + 1, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = 1_${ik}$ - j do i = j, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if end if do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 2, n call stdlib${ii}$_slassq( min( j-1, k ),ab( max( k+2-j, 1_${ik}$ ), j ), 1_${ik}$, scale,& sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_slassq( min( j, k+1 ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 1, n - 1 call stdlib${ii}$_slassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_slassq( min( n-j+1, k+1 ), ab( 1_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_slantb = value return end function stdlib${ii}$_slantb real(dp) module function stdlib${ii}$_dlantb( norm, uplo, diag, n, k, ab,ldab, work ) !! DLANTB returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n triangular band matrix A, with ( k + 1 ) diagonals. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n ! Array Arguments real(dp), intent(in) :: ab(ldab,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, l real(dp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = 2, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k + 1 sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = 1, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = max( k+2-j, 1 ), k sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = max( k+2-j, 1 ), k + 1 sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = 2, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = 1, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). value = zero if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j - 1 work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = 1_${ik}$ - j do i = j + 1, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = 1_${ik}$ - j do i = j, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if end if do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 2, n call stdlib${ii}$_dlassq( min( j-1, k ),ab( max( k+2-j, 1_${ik}$ ), j ), 1_${ik}$, scale,& sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_dlassq( min( j, k+1 ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 1, n - 1 call stdlib${ii}$_dlassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_dlassq( min( n-j+1, k+1 ), ab( 1_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_dlantb = value return end function stdlib${ii}$_dlantb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lantb( norm, uplo, diag, n, k, ab,ldab, work ) !! DLANTB: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n triangular band matrix A, with ( k + 1 ) diagonals. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n ! Array Arguments real(${rk}$), intent(in) :: ab(ldab,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, l real(${rk}$) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = 2, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k + 1 sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = 1, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = max( k+2-j, 1 ), k sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = max( k+2-j, 1 ), k + 1 sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = 2, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = 1, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). value = zero if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j - 1 work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = 1_${ik}$ - j do i = j + 1, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = 1_${ik}$ - j do i = j, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if end if do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 2, n call stdlib${ii}$_${ri}$lassq( min( j-1, k ),ab( max( k+2-j, 1_${ik}$ ), j ), 1_${ik}$, scale,& sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_${ri}$lassq( min( j, k+1 ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 1, n - 1 call stdlib${ii}$_${ri}$lassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_${ri}$lassq( min( n-j+1, k+1 ), ab( 1_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_${ri}$lantb = value return end function stdlib${ii}$_${ri}$lantb #:endif #:endfor real(sp) module function stdlib${ii}$_clantb( norm, uplo, diag, n, k, ab,ldab, work ) !! CLANTB returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n triangular band matrix A, with ( k + 1 ) diagonals. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n ! Array Arguments real(sp), intent(out) :: work(*) complex(sp), intent(in) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, l real(sp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else do j = 1, n do i = 2, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k + 1 sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else do j = 1, n do i = 1, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = max( k+2-j, 1 ), k sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = max( k+2-j, 1 ), k + 1 sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = 2, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = 1, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). value = zero if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j - 1 work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = 1_${ik}$ - j do i = j + 1, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = 1_${ik}$ - j do i = j, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if end if do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 2, n call stdlib${ii}$_classq( min( j-1, k ),ab( max( k+2-j, 1_${ik}$ ), j ), 1_${ik}$, scale,& sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_classq( min( j, k+1 ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 1, n - 1 call stdlib${ii}$_classq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_classq( min( n-j+1, k+1 ), ab( 1_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_clantb = value return end function stdlib${ii}$_clantb real(dp) module function stdlib${ii}$_zlantb( norm, uplo, diag, n, k, ab,ldab, work ) !! ZLANTB returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n triangular band matrix A, with ( k + 1 ) diagonals. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n ! Array Arguments real(dp), intent(out) :: work(*) complex(dp), intent(in) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, l real(dp) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = 2, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k + 1 sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = 1, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = max( k+2-j, 1 ), k sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = max( k+2-j, 1 ), k + 1 sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = 2, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = 1, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). value = zero if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j - 1 work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = 1_${ik}$ - j do i = j + 1, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = 1_${ik}$ - j do i = j, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if end if do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 2, n call stdlib${ii}$_zlassq( min( j-1, k ),ab( max( k+2-j, 1_${ik}$ ), j ), 1_${ik}$, scale,& sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_zlassq( min( j, k+1 ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 1, n - 1 call stdlib${ii}$_zlassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_zlassq( min( n-j+1, k+1 ), ab( 1_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_zlantb = value return end function stdlib${ii}$_zlantb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lantb( norm, uplo, diag, n, k, ab,ldab, work ) !! ZLANTB: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of an !! n by n triangular band matrix A, with ( k + 1 ) diagonals. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(in) :: k, ldab, n ! Array Arguments real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: udiag integer(${ik}$) :: i, j, l real(${ck}$) :: scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). if( stdlib_lsame( diag, 'U' ) ) then value = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = 2, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do end if else value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = max( k+2-j, 1 ), k + 1 sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = 1, min( n+1-j, k+1 ) sum = abs( ab( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do end if end if else if( ( stdlib_lsame( norm, 'O' ) ) .or. ( norm=='1' ) ) then ! find norm1(a). value = zero udiag = stdlib_lsame( diag, 'U' ) if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n if( udiag ) then sum = one do i = max( k+2-j, 1 ), k sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = max( k+2-j, 1 ), k + 1 sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do else do j = 1, n if( udiag ) then sum = one do i = 2, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do else sum = zero do i = 1, min( n+1-j, k+1 ) sum = sum + abs( ab( i, j ) ) end do end if if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end if else if( stdlib_lsame( norm, 'I' ) ) then ! find normi(a). value = zero if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j - 1 work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = k + 1_${ik}$ - j do i = max( 1, j-k ), j work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if else if( stdlib_lsame( diag, 'U' ) ) then do i = 1, n work( i ) = one end do do j = 1, n l = 1_${ik}$ - j do i = j + 1, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do else do i = 1, n work( i ) = zero end do do j = 1, n l = 1_${ik}$ - j do i = j, min( n, j+k ) work( i ) = work( i ) + abs( ab( l+i, j ) ) end do end do end if end if do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). if( stdlib_lsame( uplo, 'U' ) ) then if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 2, n call stdlib${ii}$_${ci}$lassq( min( j-1, k ),ab( max( k+2-j, 1_${ik}$ ), j ), 1_${ik}$, scale,& sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_${ci}$lassq( min( j, k+1 ), ab( max( k+2-j, 1_${ik}$ ), j ),1_${ik}$, scale, sum ) end do end if else if( stdlib_lsame( diag, 'U' ) ) then scale = one sum = n if( k>0_${ik}$ ) then do j = 1, n - 1 call stdlib${ii}$_${ci}$lassq( min( n-j, k ), ab( 2_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if else scale = zero sum = one do j = 1, n call stdlib${ii}$_${ci}$lassq( min( n-j+1, k+1 ), ab( 1_${ik}$, j ), 1_${ik}$, scale,sum ) end do end if end if value = scale*sqrt( sum ) end if stdlib${ii}$_${ci}$lantb = value return end function stdlib${ii}$_${ci}$lantb #:endif #:endfor real(sp) module function stdlib${ii}$_slansy( norm, uplo, n, a, lda, work ) !! SLANSY returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real symmetric matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, j sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, n sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero do i = 1, j - 1 absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( a( j, j ) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( a( j, j ) ) do i = j + 1, n absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_slassq( j-1, a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else do j = 1, n - 1 call stdlib${ii}$_slassq( n-j, a( j+1, j ), 1_${ik}$, scale, sum ) end do end if sum = 2_${ik}$*sum call stdlib${ii}$_slassq( n, a, lda+1, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_slansy = value return end function stdlib${ii}$_slansy real(dp) module function stdlib${ii}$_dlansy( norm, uplo, n, a, lda, work ) !! DLANSY returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real symmetric matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, j sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, n sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero do i = 1, j - 1 absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( a( j, j ) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( a( j, j ) ) do i = j + 1, n absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_dlassq( j-1, a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else do j = 1, n - 1 call stdlib${ii}$_dlassq( n-j, a( j+1, j ), 1_${ik}$, scale, sum ) end do end if sum = 2_${ik}$*sum call stdlib${ii}$_dlassq( n, a, lda+1, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_dlansy = value return end function stdlib${ii}$_dlansy #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$lansy( norm, uplo, n, a, lda, work ) !! DLANSY: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! real symmetric matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${rk}$) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, j sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, n sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero do i = 1, j - 1 absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( a( j, j ) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( a( j, j ) ) do i = j + 1, n absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_${ri}$isnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_${ri}$lassq( j-1, a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else do j = 1, n - 1 call stdlib${ii}$_${ri}$lassq( n-j, a( j+1, j ), 1_${ik}$, scale, sum ) end do end if sum = 2_${ik}$*sum call stdlib${ii}$_${ri}$lassq( n, a, lda+1, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_${ri}$lansy = value return end function stdlib${ii}$_${ri}$lansy #:endif #:endfor real(sp) module function stdlib${ii}$_clansy( norm, uplo, n, a, lda, work ) !! CLANSY returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex symmetric matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, j sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, n sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero do i = 1, j - 1 absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( a( j, j ) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( a( j, j ) ) do i = j + 1, n absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_classq( j-1, a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else do j = 1, n - 1 call stdlib${ii}$_classq( n-j, a( j+1, j ), 1_${ik}$, scale, sum ) end do end if sum = 2_${ik}$*sum call stdlib${ii}$_classq( n, a, lda+1, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_clansy = value return end function stdlib${ii}$_clansy real(dp) module function stdlib${ii}$_zlansy( norm, uplo, n, a, lda, work ) !! ZLANSY returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex symmetric matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(dp), intent(out) :: work(*) complex(dp), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, j sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, n sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero do i = 1, j - 1 absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( a( j, j ) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( a( j, j ) ) do i = j + 1, n absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_disnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_zlassq( j-1, a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else do j = 1, n - 1 call stdlib${ii}$_zlassq( n-j, a( j+1, j ), 1_${ik}$, scale, sum ) end do end if sum = 2_${ik}$*sum call stdlib${ii}$_zlassq( n, a, lda+1, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_zlansy = value return end function stdlib${ii}$_zlansy #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$lansy( norm, uplo, n, a, lda, work ) !! ZLANSY: returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex symmetric matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, j sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do else do j = 1, n do i = j, n sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is symmetric). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero do i = 1, j - 1 absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( a( j, j ) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( a( j, j ) ) do i = j + 1, n absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_${c2ri(ci)}$isnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_${ci}$lassq( j-1, a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else do j = 1, n - 1 call stdlib${ii}$_${ci}$lassq( n-j, a( j+1, j ), 1_${ik}$, scale, sum ) end do end if sum = 2_${ik}$*sum call stdlib${ii}$_${ci}$lassq( n, a, lda+1, scale, sum ) value = scale*sqrt( sum ) end if stdlib${ii}$_${ci}$lansy = value return end function stdlib${ii}$_${ci}$lansy #:endif #:endfor real(sp) module function stdlib${ii}$_clanhe( norm, uplo, n, a, lda, work ) !! CLANHE returns the value of the one norm, or the Frobenius norm, or !! the infinity norm, or the element of largest absolute value of a !! complex hermitian matrix A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm, uplo integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(out) :: work(*) complex(sp), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: absa, scale, sum, value ! Intrinsic Functions ! Executable Statements if( n==0_${ik}$ ) then value = zero else if( stdlib_lsame( norm, 'M' ) ) then ! find max(abs(a(i,j))). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n do i = 1, j - 1 sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do sum = abs( real( a( j, j ),KIND=sp) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do j = 1, n sum = abs( real( a( j, j ),KIND=sp) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum do i = j + 1, n sum = abs( a( i, j ) ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end do end if else if( ( stdlib_lsame( norm, 'I' ) ) .or. ( stdlib_lsame( norm, 'O' ) ) .or.( & norm=='1' ) ) then ! find normi(a) ( = norm1(a), since a is hermitian). value = zero if( stdlib_lsame( uplo, 'U' ) ) then do j = 1, n sum = zero do i = 1, j - 1 absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do work( j ) = sum + abs( real( a( j, j ),KIND=sp) ) end do do i = 1, n sum = work( i ) if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do else do i = 1, n work( i ) = zero end do do j = 1, n sum = work( j ) + abs( real( a( j, j ),KIND=sp) ) do i = j + 1, n absa = abs( a( i, j ) ) sum = sum + absa work( i ) = work( i ) + absa end do if( value < sum .or. stdlib${ii}$_sisnan( sum ) ) value = sum end do end if else if( ( stdlib_lsame( norm, 'F' ) ) .or. ( stdlib_lsame( norm, 'E' ) ) ) & then ! find normf(a). scale = zero sum = one if( stdlib_lsame( uplo, 'U' ) ) then do j = 2, n call stdlib${ii}$_classq( j-1, a( 1_${ik}$, j ), 1_${ik}$, scale, sum ) end do else do j = 1, n - 1 call stdlib${ii}$_classq( n-j, a( j+1, j ), 1_${ik}$, scale, sum ) end do end if sum = 2_${ik}$*sum do i = 1, n if( real( a( i, i ),KIND=sp)/=zero ) then absa = abs( real( a( i, i ),KIND=sp) ) if( scale0 ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = 1, k work( k ) = max( abs( af( i, k ) ), work( k ) ) end do k = k - 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k-1 ) work( n+k-1 ) = work( n+kp ) work( n+kp ) = tmp do i = 1, k-1 work( k ) = max( abs( af( i, k ) ), work( k ) ) work( k-1 ) = max( abs( af( i, k-1 ) ), work( k-1 ) ) end do work( k ) = max( abs( af( k, k ) ), work( k ) ) k = k - 2_${ik}$ end if end do k = ncols do while ( k <= n ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k + 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k + 2_${ik}$ end if end do else k = 1_${ik}$ do while ( k <= ncols ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = k, n work( k ) = max( abs( af( i, k ) ), work( k ) ) end do k = k + 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k+1 ) work( n+k+1 ) = work( n+kp ) work( n+kp ) = tmp do i = k+1, n work( k ) = max( abs( af( i, k ) ), work( k ) ) work( k+1 ) = max( abs( af(i, k+1 ) ), work( k+1 ) ) end do work( k ) = max( abs( af( k, k ) ), work( k ) ) k = k + 2_${ik}$ end if end do k = ncols do while ( k >= 1 ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k - 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k - 2_${ik}$ endif end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( upper ) then do i = ncols, n umax = work( i ) amax = work( n+i ) if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( n+i ) if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_sla_syrpvgrw = rpvgrw end function stdlib${ii}$_sla_syrpvgrw real(dp) module function stdlib${ii}$_dla_syrpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) !! DLA_SYRPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(in) :: a(lda,*), af(ldaf,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ncols, i, j, k, kp real(dp) :: amax, umax, rpvgrw, tmp logical(lk) :: upper ! Intrinsic Functions ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) if ( info==0_${ik}$ ) then if ( upper ) then ncols = 1_${ik}$ else ncols = n end if else ncols = info end if rpvgrw = one do i = 1, 2*n work( i ) = zero end do ! find the max magnitude entry of each column of a. compute the max ! for all n columns so we can apply the pivot permutation while ! looping below. assume a full factorization is the common case. if ( upper ) then do j = 1, n do i = 1, j work( n+i ) = max( abs( a( i, j ) ), work( n+i ) ) work( n+j ) = max( abs( a( i, j ) ), work( n+j ) ) end do end do else do j = 1, n do i = j, n work( n+i ) = max( abs( a( i, j ) ), work( n+i ) ) work( n+j ) = max( abs( a( i, j ) ), work( n+j ) ) end do end do end if ! now find the max magnitude entry of each column of u or l. also ! permute the magnitudes of a above so they're in the same order as ! the factor. ! the iteration orders and permutations were copied from stdlib${ii}$_dsytrs. ! calls to stdlib${ii}$_sswap would be severe overkill. if ( upper ) then k = n do while ( k < ncols .and. k>0 ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = 1, k work( k ) = max( abs( af( i, k ) ), work( k ) ) end do k = k - 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k-1 ) work( n+k-1 ) = work( n+kp ) work( n+kp ) = tmp do i = 1, k-1 work( k ) = max( abs( af( i, k ) ), work( k ) ) work( k-1 ) = max( abs( af( i, k-1 ) ), work( k-1 ) ) end do work( k ) = max( abs( af( k, k ) ), work( k ) ) k = k - 2_${ik}$ end if end do k = ncols do while ( k <= n ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k + 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k + 2_${ik}$ end if end do else k = 1_${ik}$ do while ( k <= ncols ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = k, n work( k ) = max( abs( af( i, k ) ), work( k ) ) end do k = k + 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k+1 ) work( n+k+1 ) = work( n+kp ) work( n+kp ) = tmp do i = k+1, n work( k ) = max( abs( af( i, k ) ), work( k ) ) work( k+1 ) = max( abs( af(i, k+1 ) ), work( k+1 ) ) end do work( k ) = max( abs( af( k, k ) ), work( k ) ) k = k + 2_${ik}$ end if end do k = ncols do while ( k >= 1 ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k - 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k - 2_${ik}$ endif end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( upper ) then do i = ncols, n umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_dla_syrpvgrw = rpvgrw end function stdlib${ii}$_dla_syrpvgrw #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$la_syrpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) !! DLA_SYRPVGRW: computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(in) :: a(lda,*), af(ldaf,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ncols, i, j, k, kp real(${rk}$) :: amax, umax, rpvgrw, tmp logical(lk) :: upper ! Intrinsic Functions ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) if ( info==0_${ik}$ ) then if ( upper ) then ncols = 1_${ik}$ else ncols = n end if else ncols = info end if rpvgrw = one do i = 1, 2*n work( i ) = zero end do ! find the max magnitude entry of each column of a. compute the max ! for all n columns so we can apply the pivot permutation while ! looping below. assume a full factorization is the common case. if ( upper ) then do j = 1, n do i = 1, j work( n+i ) = max( abs( a( i, j ) ), work( n+i ) ) work( n+j ) = max( abs( a( i, j ) ), work( n+j ) ) end do end do else do j = 1, n do i = j, n work( n+i ) = max( abs( a( i, j ) ), work( n+i ) ) work( n+j ) = max( abs( a( i, j ) ), work( n+j ) ) end do end do end if ! now find the max magnitude entry of each column of u or l. also ! permute the magnitudes of a above so they're in the same order as ! the factor. ! the iteration orders and permutations were copied from stdlib${ii}$_${ri}$sytrs. ! calls to stdlib${ii}$_dswap would be severe overkill. if ( upper ) then k = n do while ( k < ncols .and. k>0 ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = 1, k work( k ) = max( abs( af( i, k ) ), work( k ) ) end do k = k - 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k-1 ) work( n+k-1 ) = work( n+kp ) work( n+kp ) = tmp do i = 1, k-1 work( k ) = max( abs( af( i, k ) ), work( k ) ) work( k-1 ) = max( abs( af( i, k-1 ) ), work( k-1 ) ) end do work( k ) = max( abs( af( k, k ) ), work( k ) ) k = k - 2_${ik}$ end if end do k = ncols do while ( k <= n ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k + 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k + 2_${ik}$ end if end do else k = 1_${ik}$ do while ( k <= ncols ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = k, n work( k ) = max( abs( af( i, k ) ), work( k ) ) end do k = k + 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k+1 ) work( n+k+1 ) = work( n+kp ) work( n+kp ) = tmp do i = k+1, n work( k ) = max( abs( af( i, k ) ), work( k ) ) work( k+1 ) = max( abs( af(i, k+1 ) ), work( k+1 ) ) end do work( k ) = max( abs( af( k, k ) ), work( k ) ) k = k + 2_${ik}$ end if end do k = ncols do while ( k >= 1 ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k - 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k - 2_${ik}$ endif end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( upper ) then do i = ncols, n umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_${ri}$la_syrpvgrw = rpvgrw end function stdlib${ii}$_${ri}$la_syrpvgrw #:endif #:endfor real(sp) module function stdlib${ii}$_cla_syrpvgrw( uplo, n, info, a, lda, af, ldaf, ipiv,work ) !! CLA_SYRPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf ! Array Arguments complex(sp), intent(in) :: a(lda,*), af(ldaf,*) real(sp), intent(out) :: work(*) integer(${ik}$), intent(in) :: ipiv(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ncols, i, j, k, kp real(sp) :: amax, umax, rpvgrw, tmp logical(lk) :: upper complex(sp) :: zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag ( zdum ) ) ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) if ( info==0_${ik}$ ) then if ( upper ) then ncols = 1_${ik}$ else ncols = n end if else ncols = info end if rpvgrw = one do i = 1, 2*n work( i ) = zero end do ! find the max magnitude entry of each column of a. compute the max ! for all n columns so we can apply the pivot permutation while ! looping below. assume a full factorization is the common case. if ( upper ) then do j = 1, n do i = 1, j work( n+i ) = max( cabs1( a( i, j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i, j ) ), work( n+j ) ) end do end do else do j = 1, n do i = j, n work( n+i ) = max( cabs1( a( i, j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i, j ) ), work( n+j ) ) end do end do end if ! now find the max magnitude entry of each column of u or l. also ! permute the magnitudes of a above so they're in the same order as ! the factor. ! the iteration orders and permutations were copied from stdlib${ii}$_csytrs. ! calls to stdlib${ii}$_sswap would be severe overkill. if ( upper ) then k = n do while ( k < ncols .and. k>0 ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = 1, k work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k - 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k-1 ) work( n+k-1 ) = work( n+kp ) work( n+kp ) = tmp do i = 1, k-1 work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k-1 ) =max( cabs1( af( i, k-1 ) ), work( k-1 ) ) end do work( k ) = max( cabs1( af( k, k ) ), work( k ) ) k = k - 2_${ik}$ end if end do k = ncols do while ( k <= n ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k + 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k + 2_${ik}$ end if end do else k = 1_${ik}$ do while ( k <= ncols ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = k, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k + 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k+1 ) work( n+k+1 ) = work( n+kp ) work( n+kp ) = tmp do i = k+1, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k+1 ) =max( cabs1( af( i, k+1 ) ), work( k+1 ) ) end do work( k ) = max( cabs1( af( k, k ) ), work( k ) ) k = k + 2_${ik}$ end if end do k = ncols do while ( k >= 1 ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k - 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k - 2_${ik}$ endif end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( upper ) then do i = ncols, n umax = work( i ) amax = work( n+i ) if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( n+i ) if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_cla_syrpvgrw = rpvgrw end function stdlib${ii}$_cla_syrpvgrw real(dp) module function stdlib${ii}$_zla_syrpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) !! ZLA_SYRPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf ! Array Arguments complex(dp), intent(in) :: a(lda,*), af(ldaf,*) real(dp), intent(out) :: work(*) integer(${ik}$), intent(in) :: ipiv(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ncols, i, j, k, kp real(dp) :: amax, umax, rpvgrw, tmp logical(lk) :: upper complex(dp) :: zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag ( zdum ) ) ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) if ( info==0_${ik}$ ) then if ( upper ) then ncols = 1_${ik}$ else ncols = n end if else ncols = info end if rpvgrw = one do i = 1, 2*n work( i ) = zero end do ! find the max magnitude entry of each column of a. compute the max ! for all n columns so we can apply the pivot permutation while ! looping below. assume a full factorization is the common case. if ( upper ) then do j = 1, n do i = 1, j work( n+i ) = max( cabs1( a( i, j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i, j ) ), work( n+j ) ) end do end do else do j = 1, n do i = j, n work( n+i ) = max( cabs1( a( i, j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i, j ) ), work( n+j ) ) end do end do end if ! now find the max magnitude entry of each column of u or l. also ! permute the magnitudes of a above so they're in the same order as ! the factor. ! the iteration orders and permutations were copied from stdlib${ii}$_zsytrs. ! calls to stdlib${ii}$_sswap would be severe overkill. if ( upper ) then k = n do while ( k < ncols .and. k>0 ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = 1, k work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k - 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k-1 ) work( n+k-1 ) = work( n+kp ) work( n+kp ) = tmp do i = 1, k-1 work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k-1 ) =max( cabs1( af( i, k-1 ) ), work( k-1 ) ) end do work( k ) = max( cabs1( af( k, k ) ), work( k ) ) k = k - 2_${ik}$ end if end do k = ncols do while ( k <= n ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k + 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k + 2_${ik}$ end if end do else k = 1_${ik}$ do while ( k <= ncols ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = k, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k + 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k+1 ) work( n+k+1 ) = work( n+kp ) work( n+kp ) = tmp do i = k+1, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k+1 ) =max( cabs1( af( i, k+1 ) ), work( k+1 ) ) end do work( k ) = max( cabs1( af( k, k ) ), work( k ) ) k = k + 2_${ik}$ end if end do k = ncols do while ( k >= 1 ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k - 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k - 2_${ik}$ endif end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( upper ) then do i = ncols, n umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_zla_syrpvgrw = rpvgrw end function stdlib${ii}$_zla_syrpvgrw #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$la_syrpvgrw( uplo, n, info, a, lda, af,ldaf, ipiv, work ) !! ZLA_SYRPVGRW: computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, info, lda, ldaf ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*) real(${ck}$), intent(out) :: work(*) integer(${ik}$), intent(in) :: ipiv(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ncols, i, j, k, kp real(${ck}$) :: amax, umax, rpvgrw, tmp logical(lk) :: upper complex(${ck}$) :: zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag ( zdum ) ) ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) if ( info==0_${ik}$ ) then if ( upper ) then ncols = 1_${ik}$ else ncols = n end if else ncols = info end if rpvgrw = one do i = 1, 2*n work( i ) = zero end do ! find the max magnitude entry of each column of a. compute the max ! for all n columns so we can apply the pivot permutation while ! looping below. assume a full factorization is the common case. if ( upper ) then do j = 1, n do i = 1, j work( n+i ) = max( cabs1( a( i, j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i, j ) ), work( n+j ) ) end do end do else do j = 1, n do i = j, n work( n+i ) = max( cabs1( a( i, j ) ), work( n+i ) ) work( n+j ) = max( cabs1( a( i, j ) ), work( n+j ) ) end do end do end if ! now find the max magnitude entry of each column of u or l. also ! permute the magnitudes of a above so they're in the same order as ! the factor. ! the iteration orders and permutations were copied from stdlib${ii}$_${ci}$sytrs. ! calls to stdlib${ii}$_dswap would be severe overkill. if ( upper ) then k = n do while ( k < ncols .and. k>0 ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = 1, k work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k - 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k-1 ) work( n+k-1 ) = work( n+kp ) work( n+kp ) = tmp do i = 1, k-1 work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k-1 ) =max( cabs1( af( i, k-1 ) ), work( k-1 ) ) end do work( k ) = max( cabs1( af( k, k ) ), work( k ) ) k = k - 2_${ik}$ end if end do k = ncols do while ( k <= n ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k + 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k + 2_${ik}$ end if end do else k = 1_${ik}$ do while ( k <= ncols ) if ( ipiv( k )>0_${ik}$ ) then ! 1x1 pivot kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if do i = k, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) end do k = k + 1_${ik}$ else ! 2x2 pivot kp = -ipiv( k ) tmp = work( n+k+1 ) work( n+k+1 ) = work( n+kp ) work( n+kp ) = tmp do i = k+1, n work( k ) = max( cabs1( af( i, k ) ), work( k ) ) work( k+1 ) =max( cabs1( af( i, k+1 ) ), work( k+1 ) ) end do work( k ) = max( cabs1( af( k, k ) ), work( k ) ) k = k + 2_${ik}$ end if end do k = ncols do while ( k >= 1 ) if ( ipiv( k )>0_${ik}$ ) then kp = ipiv( k ) if ( kp /= k ) then tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp end if k = k - 1_${ik}$ else kp = -ipiv( k ) tmp = work( n+k ) work( n+k ) = work( n+kp ) work( n+kp ) = tmp k = k - 2_${ik}$ endif end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( upper ) then do i = ncols, n umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( n+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_${ci}$la_syrpvgrw = rpvgrw end function stdlib${ii}$_${ci}$la_syrpvgrw #:endif #:endfor pure real(sp) module function stdlib${ii}$_sla_gerpvgrw( n, ncols, a, lda, af, ldaf ) !! SLA_GERPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, ncols, lda, ldaf ! Array Arguments real(sp), intent(in) :: a(lda,*), af(ldaf,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: amax, umax, rpvgrw ! Intrinsic Functions ! Executable Statements rpvgrw = one do j = 1, ncols amax = zero umax = zero do i = 1, n amax = max( abs( a( i, j ) ), amax ) end do do i = 1, j umax = max( abs( af( i, j ) ), umax ) end do if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do stdlib${ii}$_sla_gerpvgrw = rpvgrw end function stdlib${ii}$_sla_gerpvgrw pure real(dp) module function stdlib${ii}$_dla_gerpvgrw( n, ncols, a, lda, af,ldaf ) !! DLA_GERPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, ncols, lda, ldaf ! Array Arguments real(dp), intent(in) :: a(lda,*), af(ldaf,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: amax, umax, rpvgrw ! Intrinsic Functions ! Executable Statements rpvgrw = one do j = 1, ncols amax = zero umax = zero do i = 1, n amax = max( abs( a( i, j ) ), amax ) end do do i = 1, j umax = max( abs( af( i, j ) ), umax ) end do if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do stdlib${ii}$_dla_gerpvgrw = rpvgrw end function stdlib${ii}$_dla_gerpvgrw #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$la_gerpvgrw( n, ncols, a, lda, af,ldaf ) !! DLA_GERPVGRW: computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, ncols, lda, ldaf ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), af(ldaf,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${rk}$) :: amax, umax, rpvgrw ! Intrinsic Functions ! Executable Statements rpvgrw = one do j = 1, ncols amax = zero umax = zero do i = 1, n amax = max( abs( a( i, j ) ), amax ) end do do i = 1, j umax = max( abs( af( i, j ) ), umax ) end do if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do stdlib${ii}$_${ri}$la_gerpvgrw = rpvgrw end function stdlib${ii}$_${ri}$la_gerpvgrw #:endif #:endfor pure real(sp) module function stdlib${ii}$_cla_gerpvgrw( n, ncols, a, lda, af, ldaf ) !! CLA_GERPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, ncols, lda, ldaf ! Array Arguments complex(sp), intent(in) :: a(lda,*), af(ldaf,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: amax, umax, rpvgrw complex(sp) :: zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements rpvgrw = one do j = 1, ncols amax = zero umax = zero do i = 1, n amax = max( cabs1( a( i, j ) ), amax ) end do do i = 1, j umax = max( cabs1( af( i, j ) ), umax ) end do if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do stdlib${ii}$_cla_gerpvgrw = rpvgrw end function stdlib${ii}$_cla_gerpvgrw pure real(dp) module function stdlib${ii}$_zla_gerpvgrw( n, ncols, a, lda, af,ldaf ) !! ZLA_GERPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, ncols, lda, ldaf ! Array Arguments complex(dp), intent(in) :: a(lda,*), af(ldaf,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: amax, umax, rpvgrw complex(dp) :: zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements rpvgrw = one do j = 1, ncols amax = zero umax = zero do i = 1, n amax = max( cabs1( a( i, j ) ), amax ) end do do i = 1, j umax = max( cabs1( af( i, j ) ), umax ) end do if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do stdlib${ii}$_zla_gerpvgrw = rpvgrw end function stdlib${ii}$_zla_gerpvgrw #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure real(${ck}$) module function stdlib${ii}$_${ci}$la_gerpvgrw( n, ncols, a, lda, af,ldaf ) !! ZLA_GERPVGRW: computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, ncols, lda, ldaf ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: amax, umax, rpvgrw complex(${ck}$) :: zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements rpvgrw = one do j = 1, ncols amax = zero umax = zero do i = 1, n amax = max( cabs1( a( i, j ) ), amax ) end do do i = 1, j umax = max( cabs1( af( i, j ) ), umax ) end do if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do stdlib${ii}$_${ci}$la_gerpvgrw = rpvgrw end function stdlib${ii}$_${ci}$la_gerpvgrw #:endif #:endfor real(sp) module function stdlib${ii}$_cla_gbrcond_c( trans, n, kl, ku, ab, ldab, afb,ldafb, ipiv, c, & !! CLA_GBRCOND_C Computes the infinity norm condition number of !! op(A) * inv(diag(C)) where C is a REAL vector. capply, info, work,rwork ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans logical(lk), intent(in) :: capply integer(${ik}$), intent(in) :: n, kl, ku, ldab, ldafb integer(${ik}$) :: kd, ke integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: ab(ldab,*), afb(ldafb,*) complex(sp), intent(out) :: work(*) real(sp), intent(in) :: c(*) real(sp), intent(out) :: rwork(*) ! ===================================================================== ! Local Scalars logical(lk) :: notrans integer(${ik}$) :: kase, i, j real(sp) :: ainvnm, anorm, tmp complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements stdlib${ii}$_cla_gbrcond_c = zero info = 0_${ik}$ notrans = stdlib_lsame( trans, 'N' ) if ( .not. notrans .and. .not. stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ .or. kl>n-1 ) then info = -3_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = -4_${ik}$ else if( ldabn-1 ) then info = -3_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = -4_${ik}$ else if( ldabn-1 ) then info = -3_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = -4_${ik}$ else if( ldab0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(n^2) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do do j = i+1, n temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do do j = i+1, n temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_sla_syamv module subroutine stdlib${ii}$_dla_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) !! DLA_SYAMV performs the matrix-vector operation !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! n by n symmetric matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n, uplo ! Array Arguments real(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(dp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( uplo/=stdlib${ii}$_ilauplo( 'U' ) .and.uplo/=stdlib${ii}$_ilauplo( 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ )then info = 2_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(n^2) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do do j = i+1, n temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do do j = i+1, n temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_dla_syamv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$la_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) !! DLA_SYAMV: performs the matrix-vector operation !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! n by n symmetric matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n, uplo ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), x(*) real(${rk}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_wero real(${rk}$) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( uplo/=stdlib${ii}$_ilauplo( 'U' ) .and.uplo/=stdlib${ii}$_ilauplo( 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ )then info = 2_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(n^2) symb_wero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = abs( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do do j = i+1, n temp = abs( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = abs( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do do j = i+1, n temp = abs( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = abs( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = abs( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = abs( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = abs( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_${ri}$la_syamv #:endif #:endfor module subroutine stdlib${ii}$_cla_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) !! CLA_SYAMV performs the matrix-vector operation !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! n by n symmetric matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n integer(${ik}$), intent(in) :: uplo ! Array Arguments complex(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(sp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky complex(sp) :: zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag ( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( uplo/=stdlib${ii}$_ilauplo( 'U' ) .and.uplo/=stdlib${ii}$_ilauplo( 'L' ) )then info = 1_${ik}$ else if( n<0_${ik}$ )then info = 2_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(n^2) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_cla_syamv module subroutine stdlib${ii}$_zla_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) !! ZLA_SYAMV performs the matrix-vector operation !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! n by n symmetric matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n integer(${ik}$), intent(in) :: uplo ! Array Arguments complex(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(dp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky complex(dp) :: zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag ( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( uplo/=stdlib${ii}$_ilauplo( 'U' ) .and.uplo/=stdlib${ii}$_ilauplo( 'L' ) )then info = 1_${ik}$ else if( n<0_${ik}$ )then info = 2_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(n^2) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_zla_syamv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$la_syamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) !! ZLA_SYAMV: performs the matrix-vector operation !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! n by n symmetric matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n integer(${ik}$), intent(in) :: uplo ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), x(*) real(${ck}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_wero real(${ck}$) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky complex(${ck}$) :: zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag ( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( uplo/=stdlib${ii}$_ilauplo( 'U' ) .and.uplo/=stdlib${ii}$_ilauplo( 'L' ) )then info = 1_${ik}$ else if( n<0_${ik}$ )then info = 2_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(n^2) symb_wero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_${ci}$la_syamv #:endif #:endfor real(sp) module function stdlib${ii}$_sla_syrcond( uplo, n, a, lda, af, ldaf, ipiv, cmode,c, info, work, & !! SLA_SYRCOND estimates the Skeel condition number of op(A) * op2(C) !! where op2 is determined by CMODE as follows !! CMODE = 1 op2(C) = C !! CMODE = 0 op2(C) = I !! CMODE = -1 op2(C) = inv(C) !! The Skeel condition number cond(A) = norminf( |inv(A)||A| ) !! is computed by computing scaling factors R such that !! diag(R)*A*op2(C) is row equilibrated and computing the standard !! infinity-norm condition number. iwork ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, ldaf, cmode integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(in) :: a(lda,*), af(ldaf,*), c(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars character :: normin integer(${ik}$) :: kase, i, j real(sp) :: ainvnm, smlnum, tmp logical(lk) :: up ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements stdlib${ii}$_sla_syrcond = zero info = 0_${ik}$ if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_ssygs2( itype, uplo, n, a, lda, b, ldb, info ) else ! use blocked code if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**t)*a*inv(u) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(k:n,k:n) call stdlib${ii}$_ssygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_strsm( 'LEFT', uplo, 'TRANSPOSE', 'NON-UNIT',kb, n-k-kb+1, & one, b( k, k ), ldb,a( k, k+kb ), lda ) call stdlib${ii}$_ssymm( 'LEFT', uplo, kb, n-k-kb+1, -half,a( k, k ), lda, b( & k, k+kb ), ldb, one,a( k, k+kb ), lda ) call stdlib${ii}$_ssyr2k( uplo, 'TRANSPOSE', n-k-kb+1, kb, -one,a( k, k+kb ), & lda, b( k, k+kb ), ldb,one, a( k+kb, k+kb ), lda ) call stdlib${ii}$_ssymm( 'LEFT', uplo, kb, n-k-kb+1, -half,a( k, k ), lda, b( & k, k+kb ), ldb, one,a( k, k+kb ), lda ) call stdlib${ii}$_strsm( 'RIGHT', uplo, 'NO TRANSPOSE','NON-UNIT', kb, n-k-kb+& 1_${ik}$, one,b( k+kb, k+kb ), ldb, a( k, k+kb ),lda ) end if end do else ! compute inv(l)*a*inv(l**t) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(k:n,k:n) call stdlib${ii}$_ssygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_strsm( 'RIGHT', uplo, 'TRANSPOSE', 'NON-UNIT',n-k-kb+1, kb, & one, b( k, k ), ldb,a( k+kb, k ), lda ) call stdlib${ii}$_ssymm( 'RIGHT', uplo, n-k-kb+1, kb, -half,a( k, k ), lda, b(& k+kb, k ), ldb, one,a( k+kb, k ), lda ) call stdlib${ii}$_ssyr2k( uplo, 'NO TRANSPOSE', n-k-kb+1, kb,-one, a( k+kb, k & ), lda, b( k+kb, k ),ldb, one, a( k+kb, k+kb ), lda ) call stdlib${ii}$_ssymm( 'RIGHT', uplo, n-k-kb+1, kb, -half,a( k, k ), lda, b(& k+kb, k ), ldb, one,a( k+kb, k ), lda ) call stdlib${ii}$_strsm( 'LEFT', uplo, 'NO TRANSPOSE','NON-UNIT', n-k-kb+1, & kb, one,b( k+kb, k+kb ), ldb, a( k+kb, k ),lda ) end if end do end if else if( upper ) then ! compute u*a*u**t do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_strmm( 'LEFT', uplo, 'NO TRANSPOSE', 'NON-UNIT',k-1, kb, one, & b, ldb, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_ssymm( 'RIGHT', uplo, k-1, kb, half, a( k, k ),lda, b( 1_${ik}$, k ), & ldb, one, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_ssyr2k( uplo, 'NO TRANSPOSE', k-1, kb, one,a( 1_${ik}$, k ), lda, b( & 1_${ik}$, k ), ldb, one, a,lda ) call stdlib${ii}$_ssymm( 'RIGHT', uplo, k-1, kb, half, a( k, k ),lda, b( 1_${ik}$, k ), & ldb, one, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_strmm( 'RIGHT', uplo, 'TRANSPOSE', 'NON-UNIT',k-1, kb, one, b( & k, k ), ldb, a( 1_${ik}$, k ),lda ) call stdlib${ii}$_ssygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do else ! compute l**t*a*l do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_strmm( 'RIGHT', uplo, 'NO TRANSPOSE', 'NON-UNIT',kb, k-1, one, & b, ldb, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_ssymm( 'LEFT', uplo, kb, k-1, half, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, one, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_ssyr2k( uplo, 'TRANSPOSE', k-1, kb, one,a( k, 1_${ik}$ ), lda, b( k, & 1_${ik}$ ), ldb, one, a,lda ) call stdlib${ii}$_ssymm( 'LEFT', uplo, kb, k-1, half, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, one, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_strmm( 'LEFT', uplo, 'TRANSPOSE', 'NON-UNIT', kb,k-1, one, b( & k, k ), ldb, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_ssygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do end if end if end if return end subroutine stdlib${ii}$_ssygst pure module subroutine stdlib${ii}$_dsygst( itype, uplo, n, a, lda, b, ldb, info ) !! DSYGST reduces a real symmetric-definite generalized eigenproblem !! to standard form. !! If ITYPE = 1, the problem is A*x = lambda*B*x, !! and A is overwritten by inv(U**T)*A*inv(U) or inv(L)*A*inv(L**T) !! If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or !! B*A*x = lambda*x, and A is overwritten by U*A*U**T or L**T*A*L. !! B must have been previously factorized as U**T*U or L*L**T by DPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype, lda, ldb, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: k, kb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( itype<1_${ik}$ .or. itype>3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_dsygs2( itype, uplo, n, a, lda, b, ldb, info ) else ! use blocked code if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**t)*a*inv(u) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(k:n,k:n) call stdlib${ii}$_dsygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_dtrsm( 'LEFT', uplo, 'TRANSPOSE', 'NON-UNIT',kb, n-k-kb+1, & one, b( k, k ), ldb,a( k, k+kb ), lda ) call stdlib${ii}$_dsymm( 'LEFT', uplo, kb, n-k-kb+1, -half,a( k, k ), lda, b( & k, k+kb ), ldb, one,a( k, k+kb ), lda ) call stdlib${ii}$_dsyr2k( uplo, 'TRANSPOSE', n-k-kb+1, kb, -one,a( k, k+kb ), & lda, b( k, k+kb ), ldb,one, a( k+kb, k+kb ), lda ) call stdlib${ii}$_dsymm( 'LEFT', uplo, kb, n-k-kb+1, -half,a( k, k ), lda, b( & k, k+kb ), ldb, one,a( k, k+kb ), lda ) call stdlib${ii}$_dtrsm( 'RIGHT', uplo, 'NO TRANSPOSE','NON-UNIT', kb, n-k-kb+& 1_${ik}$, one,b( k+kb, k+kb ), ldb, a( k, k+kb ),lda ) end if end do else ! compute inv(l)*a*inv(l**t) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(k:n,k:n) call stdlib${ii}$_dsygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_dtrsm( 'RIGHT', uplo, 'TRANSPOSE', 'NON-UNIT',n-k-kb+1, kb, & one, b( k, k ), ldb,a( k+kb, k ), lda ) call stdlib${ii}$_dsymm( 'RIGHT', uplo, n-k-kb+1, kb, -half,a( k, k ), lda, b(& k+kb, k ), ldb, one,a( k+kb, k ), lda ) call stdlib${ii}$_dsyr2k( uplo, 'NO TRANSPOSE', n-k-kb+1, kb,-one, a( k+kb, k & ), lda, b( k+kb, k ),ldb, one, a( k+kb, k+kb ), lda ) call stdlib${ii}$_dsymm( 'RIGHT', uplo, n-k-kb+1, kb, -half,a( k, k ), lda, b(& k+kb, k ), ldb, one,a( k+kb, k ), lda ) call stdlib${ii}$_dtrsm( 'LEFT', uplo, 'NO TRANSPOSE','NON-UNIT', n-k-kb+1, & kb, one,b( k+kb, k+kb ), ldb, a( k+kb, k ),lda ) end if end do end if else if( upper ) then ! compute u*a*u**t do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_dtrmm( 'LEFT', uplo, 'NO TRANSPOSE', 'NON-UNIT',k-1, kb, one, & b, ldb, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_dsymm( 'RIGHT', uplo, k-1, kb, half, a( k, k ),lda, b( 1_${ik}$, k ), & ldb, one, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_dsyr2k( uplo, 'NO TRANSPOSE', k-1, kb, one,a( 1_${ik}$, k ), lda, b( & 1_${ik}$, k ), ldb, one, a,lda ) call stdlib${ii}$_dsymm( 'RIGHT', uplo, k-1, kb, half, a( k, k ),lda, b( 1_${ik}$, k ), & ldb, one, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_dtrmm( 'RIGHT', uplo, 'TRANSPOSE', 'NON-UNIT',k-1, kb, one, b( & k, k ), ldb, a( 1_${ik}$, k ),lda ) call stdlib${ii}$_dsygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do else ! compute l**t*a*l do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_dtrmm( 'RIGHT', uplo, 'NO TRANSPOSE', 'NON-UNIT',kb, k-1, one, & b, ldb, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_dsymm( 'LEFT', uplo, kb, k-1, half, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, one, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_dsyr2k( uplo, 'TRANSPOSE', k-1, kb, one,a( k, 1_${ik}$ ), lda, b( k, & 1_${ik}$ ), ldb, one, a,lda ) call stdlib${ii}$_dsymm( 'LEFT', uplo, kb, k-1, half, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, one, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_dtrmm( 'LEFT', uplo, 'TRANSPOSE', 'NON-UNIT', kb,k-1, one, b( & k, k ), ldb, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_dsygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do end if end if end if return end subroutine stdlib${ii}$_dsygst #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sygst( itype, uplo, n, a, lda, b, ldb, info ) !! DSYGST: reduces a real symmetric-definite generalized eigenproblem !! to standard form. !! If ITYPE = 1, the problem is A*x = lambda*B*x, !! and A is overwritten by inv(U**T)*A*inv(U) or inv(L)*A*inv(L**T) !! If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or !! B*A*x = lambda*x, and A is overwritten by U*A*U**T or L**T*A*L. !! B must have been previously factorized as U**T*U or L*L**T by DPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype, lda, ldb, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: k, kb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( itype<1_${ik}$ .or. itype>3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_${ri}$sygs2( itype, uplo, n, a, lda, b, ldb, info ) else ! use blocked code if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**t)*a*inv(u) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(k:n,k:n) call stdlib${ii}$_${ri}$sygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_${ri}$trsm( 'LEFT', uplo, 'TRANSPOSE', 'NON-UNIT',kb, n-k-kb+1, & one, b( k, k ), ldb,a( k, k+kb ), lda ) call stdlib${ii}$_${ri}$symm( 'LEFT', uplo, kb, n-k-kb+1, -half,a( k, k ), lda, b( & k, k+kb ), ldb, one,a( k, k+kb ), lda ) call stdlib${ii}$_${ri}$syr2k( uplo, 'TRANSPOSE', n-k-kb+1, kb, -one,a( k, k+kb ), & lda, b( k, k+kb ), ldb,one, a( k+kb, k+kb ), lda ) call stdlib${ii}$_${ri}$symm( 'LEFT', uplo, kb, n-k-kb+1, -half,a( k, k ), lda, b( & k, k+kb ), ldb, one,a( k, k+kb ), lda ) call stdlib${ii}$_${ri}$trsm( 'RIGHT', uplo, 'NO TRANSPOSE','NON-UNIT', kb, n-k-kb+& 1_${ik}$, one,b( k+kb, k+kb ), ldb, a( k, k+kb ),lda ) end if end do else ! compute inv(l)*a*inv(l**t) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(k:n,k:n) call stdlib${ii}$_${ri}$sygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_${ri}$trsm( 'RIGHT', uplo, 'TRANSPOSE', 'NON-UNIT',n-k-kb+1, kb, & one, b( k, k ), ldb,a( k+kb, k ), lda ) call stdlib${ii}$_${ri}$symm( 'RIGHT', uplo, n-k-kb+1, kb, -half,a( k, k ), lda, b(& k+kb, k ), ldb, one,a( k+kb, k ), lda ) call stdlib${ii}$_${ri}$syr2k( uplo, 'NO TRANSPOSE', n-k-kb+1, kb,-one, a( k+kb, k & ), lda, b( k+kb, k ),ldb, one, a( k+kb, k+kb ), lda ) call stdlib${ii}$_${ri}$symm( 'RIGHT', uplo, n-k-kb+1, kb, -half,a( k, k ), lda, b(& k+kb, k ), ldb, one,a( k+kb, k ), lda ) call stdlib${ii}$_${ri}$trsm( 'LEFT', uplo, 'NO TRANSPOSE','NON-UNIT', n-k-kb+1, & kb, one,b( k+kb, k+kb ), ldb, a( k+kb, k ),lda ) end if end do end if else if( upper ) then ! compute u*a*u**t do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_${ri}$trmm( 'LEFT', uplo, 'NO TRANSPOSE', 'NON-UNIT',k-1, kb, one, & b, ldb, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_${ri}$symm( 'RIGHT', uplo, k-1, kb, half, a( k, k ),lda, b( 1_${ik}$, k ), & ldb, one, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_${ri}$syr2k( uplo, 'NO TRANSPOSE', k-1, kb, one,a( 1_${ik}$, k ), lda, b( & 1_${ik}$, k ), ldb, one, a,lda ) call stdlib${ii}$_${ri}$symm( 'RIGHT', uplo, k-1, kb, half, a( k, k ),lda, b( 1_${ik}$, k ), & ldb, one, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_${ri}$trmm( 'RIGHT', uplo, 'TRANSPOSE', 'NON-UNIT',k-1, kb, one, b( & k, k ), ldb, a( 1_${ik}$, k ),lda ) call stdlib${ii}$_${ri}$sygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do else ! compute l**t*a*l do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_${ri}$trmm( 'RIGHT', uplo, 'NO TRANSPOSE', 'NON-UNIT',kb, k-1, one, & b, ldb, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_${ri}$symm( 'LEFT', uplo, kb, k-1, half, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, one, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_${ri}$syr2k( uplo, 'TRANSPOSE', k-1, kb, one,a( k, 1_${ik}$ ), lda, b( k, & 1_${ik}$ ), ldb, one, a,lda ) call stdlib${ii}$_${ri}$symm( 'LEFT', uplo, kb, k-1, half, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, one, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_${ri}$trmm( 'LEFT', uplo, 'TRANSPOSE', 'NON-UNIT', kb,k-1, one, b( & k, k ), ldb, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_${ri}$sygs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do end if end if end if return end subroutine stdlib${ii}$_${ri}$sygst #:endif #:endfor pure module subroutine stdlib${ii}$_ssygs2( itype, uplo, n, a, lda, b, ldb, info ) !! SSYGS2 reduces a real symmetric-definite generalized eigenproblem !! to standard form. !! If ITYPE = 1, the problem is A*x = lambda*B*x, !! and A is overwritten by inv(U**T)*A*inv(U) or inv(L)*A*inv(L**T) !! If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or !! B*A*x = lambda*x, and A is overwritten by U*A*U**T or L**T *A*L. !! B must have been previously factorized as U**T *U or L*L**T by SPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype, lda, ldb, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: k real(sp) :: akk, bkk, ct ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( itype<1_${ik}$ .or. itype>3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSPGST', -info ) return end if if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**t)*a*inv(u) ! j1 and jj are the indices of a(1,j) and a(j,j) jj = 0_${ik}$ do j = 1, n j1 = jj + 1_${ik}$ jj = jj + j ! compute the j-th column of the upper triangle of a bjj = bp( jj ) call stdlib${ii}$_stpsv( uplo, 'TRANSPOSE', 'NONUNIT', j, bp,ap( j1 ), 1_${ik}$ ) call stdlib${ii}$_sspmv( uplo, j-1, -one, ap, bp( j1 ), 1_${ik}$, one,ap( j1 ), 1_${ik}$ ) call stdlib${ii}$_sscal( j-1, one / bjj, ap( j1 ), 1_${ik}$ ) ap( jj ) = ( ap( jj )-stdlib${ii}$_sdot( j-1, ap( j1 ), 1_${ik}$, bp( j1 ),1_${ik}$ ) ) / & bjj end do else ! compute inv(l)*a*inv(l**t) ! kk and k1k1 are the indices of a(k,k) and a(k+1,k+1) kk = 1_${ik}$ do k = 1, n k1k1 = kk + n - k + 1_${ik}$ ! update the lower triangle of a(k:n,k:n) akk = ap( kk ) bkk = bp( kk ) akk = akk / bkk**2_${ik}$ ap( kk ) = akk if( k3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSPGST', -info ) return end if if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**t)*a*inv(u) ! j1 and jj are the indices of a(1,j) and a(j,j) jj = 0_${ik}$ do j = 1, n j1 = jj + 1_${ik}$ jj = jj + j ! compute the j-th column of the upper triangle of a bjj = bp( jj ) call stdlib${ii}$_dtpsv( uplo, 'TRANSPOSE', 'NONUNIT', j, bp,ap( j1 ), 1_${ik}$ ) call stdlib${ii}$_dspmv( uplo, j-1, -one, ap, bp( j1 ), 1_${ik}$, one,ap( j1 ), 1_${ik}$ ) call stdlib${ii}$_dscal( j-1, one / bjj, ap( j1 ), 1_${ik}$ ) ap( jj ) = ( ap( jj )-stdlib${ii}$_ddot( j-1, ap( j1 ), 1_${ik}$, bp( j1 ),1_${ik}$ ) ) / & bjj end do else ! compute inv(l)*a*inv(l**t) ! kk and k1k1 are the indices of a(k,k) and a(k+1,k+1) kk = 1_${ik}$ do k = 1, n k1k1 = kk + n - k + 1_${ik}$ ! update the lower triangle of a(k:n,k:n) akk = ap( kk ) bkk = bp( kk ) akk = akk / bkk**2_${ik}$ ap( kk ) = akk if( k3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSPGST', -info ) return end if if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**t)*a*inv(u) ! j1 and jj are the indices of a(1,j) and a(j,j) jj = 0_${ik}$ do j = 1, n j1 = jj + 1_${ik}$ jj = jj + j ! compute the j-th column of the upper triangle of a bjj = bp( jj ) call stdlib${ii}$_${ri}$tpsv( uplo, 'TRANSPOSE', 'NONUNIT', j, bp,ap( j1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$spmv( uplo, j-1, -one, ap, bp( j1 ), 1_${ik}$, one,ap( j1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( j-1, one / bjj, ap( j1 ), 1_${ik}$ ) ap( jj ) = ( ap( jj )-stdlib${ii}$_${ri}$dot( j-1, ap( j1 ), 1_${ik}$, bp( j1 ),1_${ik}$ ) ) / & bjj end do else ! compute inv(l)*a*inv(l**t) ! kk and k1k1 are the indices of a(k,k) and a(k+1,k+1) kk = 1_${ik}$ do k = 1, n k1k1 = kk + n - k + 1_${ik}$ ! update the lower triangle of a(k:n,k:n) akk = ap( kk ) bkk = bp( kk ) akk = akk / bkk**2_${ik}$ ap( kk ) = akk if( kka ) then info = -5_${ik}$ else if( ldabn-1 )go to 480 end if if( upper ) then ! transform a, working with the upper triangle if( update ) then ! form inv(s(i))**t * a * inv(s(i)) bii = bb( kb1, i ) do j = i, i1 ab( i-j+ka1, j ) = ab( i-j+ka1, j ) / bii end do do j = max( 1, i-ka ), i ab( j-i+ka1, i ) = ab( j-i+ka1, i ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -bb( j-i+kb1, i )*ab( k-i+ka1, i ) -bb(& k-i+kb1, i )*ab( j-i+ka1, i ) +ab( ka1, i )*bb( j-i+kb1, i )*bb( k-i+kb1, & i ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -bb( k-i+kb1, i )*ab( j-i+ka1, i ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( k-j+ka1, j ) = ab( k-j+ka1, j ) -bb( k-i+kb1, i )*ab( i-j+ka1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_sscal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_sger( n-m, kbt, -one, x( m+1, i ), 1_${ik}$,bb( kb1-kbt, i ), & 1_${ik}$, x( m+1, i-kbt ), ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+ka1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_130: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i,i-k+ka+1) call stdlib${ii}$_slartg( ab( k+1, i-k+ka ), ra1,work( n+i-k+ka-m ), work( i-k+& ka-m ),ra ) ! create nonzero element a(i-k,i-k+ka+1) outside the ! band and store it in work(i-k) t = -bb( kb1-k, i )*ra1 work( i-k ) = work( n+i-k+ka-m )*t -work( i-k+ka-m )*ab( 1_${ik}$, i-k+ka ) ab( 1_${ik}$, i-k+ka ) = work( i-k+ka-m )*t +work( n+i-k+ka-m )*ab( 1_${ik}$, i-k+ka ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = work( n+j-m )*ab( 1_${ik}$, j+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_slargv( nrt, ab( 1_${ik}$, j2t ), inca, work( j2t-m ), ka1,work( & n+j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_slartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, work(& n+j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_slar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & work( n+j2-m ),work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca,work( n+j2-m ), work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_srot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j-m ), & work( j-m ) ) end do end if end do loop_130 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt,i-kbt+ka+1) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kb1-kbt, i )*ra1 end if end if loop_170: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( l, j2-l+1 ), inca,ab( l+1, j2-l+1 ), & inca, work( n+j2-ka ),work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) work( n+j ) = work( n+j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j) work( j ) = work( j )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = work( n+j )*ab( 1_${ik}$, j+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_slargv( nr, ab( 1_${ik}$, j2 ), inca, work( j2 ), ka1,work( n+j2 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_slartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, work(& n+j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_slar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & work( n+j2 ),work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, work( n+j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_srot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j ), work( & j ) ) end do end if end do loop_210 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca,work( n+j2-m ), work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, i - kb + 2*ka + 1, -1 work( n+j-m ) = work( n+j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**t * a * inv(s(i)) bii = bb( 1_${ik}$, i ) do j = i, i1 ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do j = max( 1, i-ka ), i ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( k-j+1, j ) = ab( k-j+1, j ) -bb( i-j+1, j )*ab( i-k+1, k ) -bb( i-k+1, & k )*ab( i-j+1, j ) +ab( 1_${ik}$, i )*bb( i-j+1, j )*bb( i-k+1, k ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( k-j+1, j ) = ab( k-j+1, j ) -bb( i-k+1, k )*ab( i-j+1, j ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( j-k+1, k ) = ab( j-k+1, k ) -bb( i-k+1, k )*ab( j-i+1, i ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_sscal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_sger( n-m, kbt, -one, x( m+1, i ), 1_${ik}$,bb( kbt+1, i-kbt )& , ldbb-1,x( m+1, i-kbt ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_360: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i-k+ka+1,i) call stdlib${ii}$_slartg( ab( ka1-k, i ), ra1, work( n+i-k+ka-m ),work( i-k+ka-m & ), ra ) ! create nonzero element a(i-k+ka+1,i-k) outside the ! band and store it in work(i-k) t = -bb( k+1, i-k )*ra1 work( i-k ) = work( n+i-k+ka-m )*t -work( i-k+ka-m )*ab( ka1, i-k ) ab( ka1, i-k ) = work( i-k+ka-m )*t +work( n+i-k+ka-m )*ab( ka1, i-k ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = work( n+j-m )*ab( ka1, j-ka+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_slargv( nrt, ab( ka1, j2t-ka ), inca, work( j2t-m ),ka1, & work( n+j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_slartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, work( & n+j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_slar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, work( n+& j2-m ), work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, work( n+j2-m ),work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_srot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j-m ), & work( j-m ) ) end do end if end do loop_360 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt+ka+1,i-kbt) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kbt+1, i-kbt )*ra1 end if end if loop_400: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( ka1-l+1, j2-ka ), inca,ab( ka1-l, j2-& ka+1 ), inca,work( n+j2-ka ), work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) work( n+j ) = work( n+j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j) work( j ) = work( j )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = work( n+j )*ab( ka1, j-ka+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_slargv( nr, ab( ka1, j2-ka ), inca, work( j2 ), ka1,work( n+j2 ), & ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_slartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, work( & n+j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_slar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, work( n+& j2 ), work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, work( n+j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_srot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j ), work( & j ) ) end do end if end do loop_440 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, work( n+j2-m ),work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, i - kb + 2*ka + 1, -1 work( n+j-m ) = work( n+j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if end if go to 10 480 continue ! **************************** phase 2 ***************************** ! the logical structure of this phase is: ! update = .true. ! do i = 1, m ! use s(i) to update a and create a new bulge ! apply rotations to push all bulges ka positions upward ! end do ! update = .false. ! do i = m - ka - 1, 2, -1 ! apply rotations to push all bulges ka positions upward ! end do ! to avoid duplicating code, the two loops are merged. update = .true. i = 0_${ik}$ 490 continue if( update ) then i = i + 1_${ik}$ kbt = min( kb, m-i ) i0 = i + 1_${ik}$ i1 = max( 1_${ik}$, i-ka ) i2 = i + kbt - ka1 if( i>m ) then update = .false. i = i - 1_${ik}$ i0 = m + 1_${ik}$ if( ka==0 )return go to 490 end if else i = i - ka if( i<2 )return end if if( i0_${ik}$ )call stdlib${ii}$_sger( nx, kbt, -one, x( 1_${ik}$, i ), 1_${ik}$, bb( kb, i+1 ),ldbb-& 1_${ik}$, x( 1_${ik}$, i+1 ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+ka1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_610: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_slargv( nrt, ab( 1_${ik}$, j1+ka ), inca, work( j1 ), ka1,work( & n+j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_slartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca, & work( n+j1 ),work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_slar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & work( n+j1 ),work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& work( n+j1t ),work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_srot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+j ), work( j ) ) end do end if end do loop_610 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt-ka-1,i+kbt) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kb1-kbt, i+kbt )*ra1 end if end if loop_650: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( l, j1t+ka ), inca,ab( l+1, j1t+ka-1 ),& inca,work( n+m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) work( n+m-kb+j ) = work( n+m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j-1,j+ka) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( 1_${ik}$, j+ka-1 ) ab( 1_${ik}$, j+ka-1 ) = work( n+m-kb+j )*ab( 1_${ik}$, j+ka-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_650 loop_690: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_slargv( nr, ab( 1_${ik}$, j1+ka ), inca, work( m-kb+j1 ),ka1, work( n+m-& kb+j1 ), ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_slartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca,& work( n+m-kb+j1 ), work( m-kb+j1 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_slar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & work( n+m-kb+j1 ),work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& work( n+m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_srot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+m-kb+j ), work( & m-kb+j ) ) end do end if end do loop_690 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& work( n+j1t ),work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, min( i+kb, m ) - 2*ka - 1 work( n+j ) = work( n+j+ka ) work( j ) = work( j+ka ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**t * a * inv(s(i)) bii = bb( 1_${ik}$, i ) do j = i1, i ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do j = i, min( n, i+ka ) ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do k = i + 1, i + kbt do j = k, i + kbt ab( j-k+1, k ) = ab( j-k+1, k ) -bb( j-i+1, i )*ab( k-i+1, i ) -bb( k-i+1, & i )*ab( j-i+1, i ) +ab( 1_${ik}$, i )*bb( j-i+1, i )*bb( k-i+1, i ) end do do j = i + kbt + 1, min( n, i+ka ) ab( j-k+1, k ) = ab( j-k+1, k ) -bb( k-i+1, i )*ab( j-i+1, i ) end do end do do j = i1, i do k = i + 1, min( j+ka, i+kbt ) ab( k-j+1, j ) = ab( k-j+1, j ) -bb( k-i+1, i )*ab( i-j+1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_sscal( nx, one / bii, x( 1_${ik}$, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_sger( nx, kbt, -one, x( 1_${ik}$, i ), 1_${ik}$, bb( 2_${ik}$, i ), 1_${ik}$,x( 1_${ik}$, & i+1 ), ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_840: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_slargv( nrt, ab( ka1, j1 ), inca, work( j1 ), ka1,work( n+& j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_slartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, work( n+& j1 ), work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_slar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, work( & n+j1 ),work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,work( n+j1t ), work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_srot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+j ), work( j ) ) end do end if end do loop_840 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt,i+kbt-ka-1) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kbt+1, i )*ra1 end if end if loop_880: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( ka1-l+1, j1t+l-1 ), inca,ab( ka1-l, & j1t+l-1 ), inca,work( n+m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) work( n+m-kb+j ) = work( n+m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j+ka,j-1) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( ka1, j-1 ) ab( ka1, j-1 ) = work( n+m-kb+j )*ab( ka1, j-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_880 loop_920: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_slargv( nr, ab( ka1, j1 ), inca, work( m-kb+j1 ),ka1, work( n+m-& kb+j1 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_slartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, work( n+& m-kb+j1 ), work( m-kb+j1 ),ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_slar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, work( & n+m-kb+j1 ),work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,work( n+m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_srot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+m-kb+j ), work( & m-kb+j ) ) end do end if end do loop_920 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,work( n+j1t ), work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, min( i+kb, m ) - 2*ka - 1 work( n+j ) = work( n+j+ka ) work( j ) = work( j+ka ) end do end if end if go to 490 end subroutine stdlib${ii}$_ssbgst pure module subroutine stdlib${ii}$_dsbgst( vect, uplo, n, ka, kb, ab, ldab, bb, ldbb, x,ldx, work, info ) !! DSBGST reduces a real symmetric-definite banded generalized !! eigenproblem A*x = lambda*B*x to standard form C*y = lambda*y, !! such that C has the same bandwidth as A. !! B must have been previously factorized as S**T*S by DPBSTF, using a !! split Cholesky factorization. A is overwritten by C = X**T*A*X, where !! X = S**(-1)*Q and Q is an orthogonal matrix chosen to preserve the !! bandwidth of A. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka, kb, ldab, ldbb, ldx, n ! Array Arguments real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(in) :: bb(ldbb,*) real(dp), intent(out) :: work(*), x(ldx,*) ! ===================================================================== ! Local Scalars logical(lk) :: update, upper, wantx integer(${ik}$) :: i, i0, i1, i2, inca, j, j1, j1t, j2, j2t, k, ka1, kb1, kbt, l, m, nr, & nrt, nx real(dp) :: bii, ra, ra1, t ! Intrinsic Functions ! Executable Statements ! test the input parameters wantx = stdlib_lsame( vect, 'V' ) upper = stdlib_lsame( uplo, 'U' ) ka1 = ka + 1_${ik}$ kb1 = kb + 1_${ik}$ info = 0_${ik}$ if( .not.wantx .and. .not.stdlib_lsame( vect, 'N' ) ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ka<0_${ik}$ ) then info = -4_${ik}$ else if( kb<0_${ik}$ .or. kb>ka ) then info = -5_${ik}$ else if( ldabn-1 )go to 480 end if if( upper ) then ! transform a, working with the upper triangle if( update ) then ! form inv(s(i))**t * a * inv(s(i)) bii = bb( kb1, i ) do j = i, i1 ab( i-j+ka1, j ) = ab( i-j+ka1, j ) / bii end do do j = max( 1, i-ka ), i ab( j-i+ka1, i ) = ab( j-i+ka1, i ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -bb( j-i+kb1, i )*ab( k-i+ka1, i ) -bb(& k-i+kb1, i )*ab( j-i+ka1, i ) +ab( ka1, i )*bb( j-i+kb1, i )*bb( k-i+kb1, & i ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -bb( k-i+kb1, i )*ab( j-i+ka1, i ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( k-j+ka1, j ) = ab( k-j+ka1, j ) -bb( k-i+kb1, i )*ab( i-j+ka1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_dscal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_dger( n-m, kbt, -one, x( m+1, i ), 1_${ik}$,bb( kb1-kbt, i ), & 1_${ik}$, x( m+1, i-kbt ), ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+ka1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_130: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i,i-k+ka+1) call stdlib${ii}$_dlartg( ab( k+1, i-k+ka ), ra1,work( n+i-k+ka-m ), work( i-k+& ka-m ),ra ) ! create nonzero element a(i-k,i-k+ka+1) outside the ! band and store it in work(i-k) t = -bb( kb1-k, i )*ra1 work( i-k ) = work( n+i-k+ka-m )*t -work( i-k+ka-m )*ab( 1_${ik}$, i-k+ka ) ab( 1_${ik}$, i-k+ka ) = work( i-k+ka-m )*t +work( n+i-k+ka-m )*ab( 1_${ik}$, i-k+ka ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = work( n+j-m )*ab( 1_${ik}$, j+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_dlargv( nrt, ab( 1_${ik}$, j2t ), inca, work( j2t-m ), ka1,work( & n+j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_dlartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, work(& n+j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_dlar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & work( n+j2-m ),work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca,work( n+j2-m ), work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_drot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j-m ), & work( j-m ) ) end do end if end do loop_130 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt,i-kbt+ka+1) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kb1-kbt, i )*ra1 end if end if loop_170: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( l, j2-l+1 ), inca,ab( l+1, j2-l+1 ), & inca, work( n+j2-ka ),work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) work( n+j ) = work( n+j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j) work( j ) = work( j )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = work( n+j )*ab( 1_${ik}$, j+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_dlargv( nr, ab( 1_${ik}$, j2 ), inca, work( j2 ), ka1,work( n+j2 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_dlartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, work(& n+j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_dlar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & work( n+j2 ),work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, work( n+j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_drot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j ), work( & j ) ) end do end if end do loop_210 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca,work( n+j2-m ), work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, i - kb + 2*ka + 1, -1 work( n+j-m ) = work( n+j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**t * a * inv(s(i)) bii = bb( 1_${ik}$, i ) do j = i, i1 ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do j = max( 1, i-ka ), i ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( k-j+1, j ) = ab( k-j+1, j ) -bb( i-j+1, j )*ab( i-k+1, k ) -bb( i-k+1, & k )*ab( i-j+1, j ) +ab( 1_${ik}$, i )*bb( i-j+1, j )*bb( i-k+1, k ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( k-j+1, j ) = ab( k-j+1, j ) -bb( i-k+1, k )*ab( i-j+1, j ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( j-k+1, k ) = ab( j-k+1, k ) -bb( i-k+1, k )*ab( j-i+1, i ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_dscal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_dger( n-m, kbt, -one, x( m+1, i ), 1_${ik}$,bb( kbt+1, i-kbt )& , ldbb-1,x( m+1, i-kbt ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_360: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i-k+ka+1,i) call stdlib${ii}$_dlartg( ab( ka1-k, i ), ra1, work( n+i-k+ka-m ),work( i-k+ka-m & ), ra ) ! create nonzero element a(i-k+ka+1,i-k) outside the ! band and store it in work(i-k) t = -bb( k+1, i-k )*ra1 work( i-k ) = work( n+i-k+ka-m )*t -work( i-k+ka-m )*ab( ka1, i-k ) ab( ka1, i-k ) = work( i-k+ka-m )*t +work( n+i-k+ka-m )*ab( ka1, i-k ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = work( n+j-m )*ab( ka1, j-ka+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_dlargv( nrt, ab( ka1, j2t-ka ), inca, work( j2t-m ),ka1, & work( n+j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_dlartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, work( & n+j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_dlar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, work( n+& j2-m ), work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, work( n+j2-m ),work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_drot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j-m ), & work( j-m ) ) end do end if end do loop_360 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt+ka+1,i-kbt) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kbt+1, i-kbt )*ra1 end if end if loop_400: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( ka1-l+1, j2-ka ), inca,ab( ka1-l, j2-& ka+1 ), inca,work( n+j2-ka ), work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) work( n+j ) = work( n+j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j) work( j ) = work( j )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = work( n+j )*ab( ka1, j-ka+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_dlargv( nr, ab( ka1, j2-ka ), inca, work( j2 ), ka1,work( n+j2 ), & ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_dlartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, work( & n+j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_dlar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, work( n+& j2 ), work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, work( n+j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_drot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j ), work( & j ) ) end do end if end do loop_440 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, work( n+j2-m ),work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, i - kb + 2*ka + 1, -1 work( n+j-m ) = work( n+j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if end if go to 10 480 continue ! **************************** phase 2 ***************************** ! the logical structure of this phase is: ! update = .true. ! do i = 1, m ! use s(i) to update a and create a new bulge ! apply rotations to push all bulges ka positions upward ! end do ! update = .false. ! do i = m - ka - 1, 2, -1 ! apply rotations to push all bulges ka positions upward ! end do ! to avoid duplicating code, the two loops are merged. update = .true. i = 0_${ik}$ 490 continue if( update ) then i = i + 1_${ik}$ kbt = min( kb, m-i ) i0 = i + 1_${ik}$ i1 = max( 1_${ik}$, i-ka ) i2 = i + kbt - ka1 if( i>m ) then update = .false. i = i - 1_${ik}$ i0 = m + 1_${ik}$ if( ka==0 )return go to 490 end if else i = i - ka if( i<2 )return end if if( i0_${ik}$ )call stdlib${ii}$_dger( nx, kbt, -one, x( 1_${ik}$, i ), 1_${ik}$, bb( kb, i+1 ),ldbb-& 1_${ik}$, x( 1_${ik}$, i+1 ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+ka1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_610: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_dlargv( nrt, ab( 1_${ik}$, j1+ka ), inca, work( j1 ), ka1,work( & n+j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_dlartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca, & work( n+j1 ),work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_dlar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & work( n+j1 ),work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& work( n+j1t ),work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_drot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+j ), work( j ) ) end do end if end do loop_610 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt-ka-1,i+kbt) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kb1-kbt, i+kbt )*ra1 end if end if loop_650: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( l, j1t+ka ), inca,ab( l+1, j1t+ka-1 ),& inca,work( n+m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) work( n+m-kb+j ) = work( n+m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j-1,j+ka) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( 1_${ik}$, j+ka-1 ) ab( 1_${ik}$, j+ka-1 ) = work( n+m-kb+j )*ab( 1_${ik}$, j+ka-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_650 loop_690: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_dlargv( nr, ab( 1_${ik}$, j1+ka ), inca, work( m-kb+j1 ),ka1, work( n+m-& kb+j1 ), ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_dlartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca,& work( n+m-kb+j1 ), work( m-kb+j1 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_dlar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & work( n+m-kb+j1 ),work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& work( n+m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_drot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+m-kb+j ), work( & m-kb+j ) ) end do end if end do loop_690 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& work( n+j1t ),work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, min( i+kb, m ) - 2*ka - 1 work( n+j ) = work( n+j+ka ) work( j ) = work( j+ka ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**t * a * inv(s(i)) bii = bb( 1_${ik}$, i ) do j = i1, i ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do j = i, min( n, i+ka ) ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do k = i + 1, i + kbt do j = k, i + kbt ab( j-k+1, k ) = ab( j-k+1, k ) -bb( j-i+1, i )*ab( k-i+1, i ) -bb( k-i+1, & i )*ab( j-i+1, i ) +ab( 1_${ik}$, i )*bb( j-i+1, i )*bb( k-i+1, i ) end do do j = i + kbt + 1, min( n, i+ka ) ab( j-k+1, k ) = ab( j-k+1, k ) -bb( k-i+1, i )*ab( j-i+1, i ) end do end do do j = i1, i do k = i + 1, min( j+ka, i+kbt ) ab( k-j+1, j ) = ab( k-j+1, j ) -bb( k-i+1, i )*ab( i-j+1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_dscal( nx, one / bii, x( 1_${ik}$, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_dger( nx, kbt, -one, x( 1_${ik}$, i ), 1_${ik}$, bb( 2_${ik}$, i ), 1_${ik}$,x( 1_${ik}$, & i+1 ), ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_840: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_dlargv( nrt, ab( ka1, j1 ), inca, work( j1 ), ka1,work( n+& j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_dlartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, work( n+& j1 ), work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_dlar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, work( & n+j1 ),work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,work( n+j1t ), work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_drot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+j ), work( j ) ) end do end if end do loop_840 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt,i+kbt-ka-1) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kbt+1, i )*ra1 end if end if loop_880: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( ka1-l+1, j1t+l-1 ), inca,ab( ka1-l, & j1t+l-1 ), inca,work( n+m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) work( n+m-kb+j ) = work( n+m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j+ka,j-1) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( ka1, j-1 ) ab( ka1, j-1 ) = work( n+m-kb+j )*ab( ka1, j-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_880 loop_920: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_dlargv( nr, ab( ka1, j1 ), inca, work( m-kb+j1 ),ka1, work( n+m-& kb+j1 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_dlartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, work( n+& m-kb+j1 ), work( m-kb+j1 ),ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_dlar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, work( & n+m-kb+j1 ),work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,work( n+m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_drot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+m-kb+j ), work( & m-kb+j ) ) end do end if end do loop_920 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,work( n+j1t ), work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, min( i+kb, m ) - 2*ka - 1 work( n+j ) = work( n+j+ka ) work( j ) = work( j+ka ) end do end if end if go to 490 end subroutine stdlib${ii}$_dsbgst #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sbgst( vect, uplo, n, ka, kb, ab, ldab, bb, ldbb, x,ldx, work, info ) !! DSBGST: reduces a real symmetric-definite banded generalized !! eigenproblem A*x = lambda*B*x to standard form C*y = lambda*y, !! such that C has the same bandwidth as A. !! B must have been previously factorized as S**T*S by DPBSTF, using a !! split Cholesky factorization. A is overwritten by C = X**T*A*X, where !! X = S**(-1)*Q and Q is an orthogonal matrix chosen to preserve the !! bandwidth of A. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka, kb, ldab, ldbb, ldx, n ! Array Arguments real(${rk}$), intent(inout) :: ab(ldab,*) real(${rk}$), intent(in) :: bb(ldbb,*) real(${rk}$), intent(out) :: work(*), x(ldx,*) ! ===================================================================== ! Local Scalars logical(lk) :: update, upper, wantx integer(${ik}$) :: i, i0, i1, i2, inca, j, j1, j1t, j2, j2t, k, ka1, kb1, kbt, l, m, nr, & nrt, nx real(${rk}$) :: bii, ra, ra1, t ! Intrinsic Functions ! Executable Statements ! test the input parameters wantx = stdlib_lsame( vect, 'V' ) upper = stdlib_lsame( uplo, 'U' ) ka1 = ka + 1_${ik}$ kb1 = kb + 1_${ik}$ info = 0_${ik}$ if( .not.wantx .and. .not.stdlib_lsame( vect, 'N' ) ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ka<0_${ik}$ ) then info = -4_${ik}$ else if( kb<0_${ik}$ .or. kb>ka ) then info = -5_${ik}$ else if( ldabn-1 )go to 480 end if if( upper ) then ! transform a, working with the upper triangle if( update ) then ! form inv(s(i))**t * a * inv(s(i)) bii = bb( kb1, i ) do j = i, i1 ab( i-j+ka1, j ) = ab( i-j+ka1, j ) / bii end do do j = max( 1, i-ka ), i ab( j-i+ka1, i ) = ab( j-i+ka1, i ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -bb( j-i+kb1, i )*ab( k-i+ka1, i ) -bb(& k-i+kb1, i )*ab( j-i+ka1, i ) +ab( ka1, i )*bb( j-i+kb1, i )*bb( k-i+kb1, & i ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -bb( k-i+kb1, i )*ab( j-i+ka1, i ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( k-j+ka1, j ) = ab( k-j+ka1, j ) -bb( k-i+kb1, i )*ab( i-j+ka1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_${ri}$scal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_${ri}$ger( n-m, kbt, -one, x( m+1, i ), 1_${ik}$,bb( kb1-kbt, i ), & 1_${ik}$, x( m+1, i-kbt ), ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+ka1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_130: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i,i-k+ka+1) call stdlib${ii}$_${ri}$lartg( ab( k+1, i-k+ka ), ra1,work( n+i-k+ka-m ), work( i-k+& ka-m ),ra ) ! create nonzero element a(i-k,i-k+ka+1) outside the ! band and store it in work(i-k) t = -bb( kb1-k, i )*ra1 work( i-k ) = work( n+i-k+ka-m )*t -work( i-k+ka-m )*ab( 1_${ik}$, i-k+ka ) ab( 1_${ik}$, i-k+ka ) = work( i-k+ka-m )*t +work( n+i-k+ka-m )*ab( 1_${ik}$, i-k+ka ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = work( n+j-m )*ab( 1_${ik}$, j+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$largv( nrt, ab( 1_${ik}$, j2t ), inca, work( j2t-m ), ka1,work( & n+j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_${ri}$lartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, work(& n+j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_${ri}$lar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & work( n+j2-m ),work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca,work( n+j2-m ), work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_${ri}$rot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j-m ), & work( j-m ) ) end do end if end do loop_130 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt,i-kbt+ka+1) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kb1-kbt, i )*ra1 end if end if loop_170: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( l, j2-l+1 ), inca,ab( l+1, j2-l+1 ), & inca, work( n+j2-ka ),work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) work( n+j ) = work( n+j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j) work( j ) = work( j )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = work( n+j )*ab( 1_${ik}$, j+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_${ri}$largv( nr, ab( 1_${ik}$, j2 ), inca, work( j2 ), ka1,work( n+j2 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_${ri}$lartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, work(& n+j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_${ri}$lar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & work( n+j2 ),work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, work( n+j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_${ri}$rot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j ), work( & j ) ) end do end if end do loop_210 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca,work( n+j2-m ), work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, i - kb + 2*ka + 1, -1 work( n+j-m ) = work( n+j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**t * a * inv(s(i)) bii = bb( 1_${ik}$, i ) do j = i, i1 ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do j = max( 1, i-ka ), i ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( k-j+1, j ) = ab( k-j+1, j ) -bb( i-j+1, j )*ab( i-k+1, k ) -bb( i-k+1, & k )*ab( i-j+1, j ) +ab( 1_${ik}$, i )*bb( i-j+1, j )*bb( i-k+1, k ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( k-j+1, j ) = ab( k-j+1, j ) -bb( i-k+1, k )*ab( i-j+1, j ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( j-k+1, k ) = ab( j-k+1, k ) -bb( i-k+1, k )*ab( j-i+1, i ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_${ri}$scal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_${ri}$ger( n-m, kbt, -one, x( m+1, i ), 1_${ik}$,bb( kbt+1, i-kbt )& , ldbb-1,x( m+1, i-kbt ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_360: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i-k+ka+1,i) call stdlib${ii}$_${ri}$lartg( ab( ka1-k, i ), ra1, work( n+i-k+ka-m ),work( i-k+ka-m & ), ra ) ! create nonzero element a(i-k+ka+1,i-k) outside the ! band and store it in work(i-k) t = -bb( k+1, i-k )*ra1 work( i-k ) = work( n+i-k+ka-m )*t -work( i-k+ka-m )*ab( ka1, i-k ) ab( ka1, i-k ) = work( i-k+ka-m )*t +work( n+i-k+ka-m )*ab( ka1, i-k ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = work( n+j-m )*ab( ka1, j-ka+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$largv( nrt, ab( ka1, j2t-ka ), inca, work( j2t-m ),ka1, & work( n+j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_${ri}$lartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, work( & n+j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_${ri}$lar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, work( n+& j2-m ), work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, work( n+j2-m ),work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_${ri}$rot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j-m ), & work( j-m ) ) end do end if end do loop_360 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt+ka+1,i-kbt) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kbt+1, i-kbt )*ra1 end if end if loop_400: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( ka1-l+1, j2-ka ), inca,ab( ka1-l, j2-& ka+1 ), inca,work( n+j2-ka ), work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) work( n+j ) = work( n+j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j) work( j ) = work( j )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = work( n+j )*ab( ka1, j-ka+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_${ri}$largv( nr, ab( ka1, j2-ka ), inca, work( j2 ), ka1,work( n+j2 ), & ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_${ri}$lartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, work( & n+j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_${ri}$lar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, work( n+& j2 ), work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, work( n+j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_${ri}$rot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,work( n+j ), work( & j ) ) end do end if end do loop_440 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, work( n+j2-m ),work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, i - kb + 2*ka + 1, -1 work( n+j-m ) = work( n+j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if end if go to 10 480 continue ! **************************** phase 2 ***************************** ! the logical structure of this phase is: ! update = .true. ! do i = 1, m ! use s(i) to update a and create a new bulge ! apply rotations to push all bulges ka positions upward ! end do ! update = .false. ! do i = m - ka - 1, 2, -1 ! apply rotations to push all bulges ka positions upward ! end do ! to avoid duplicating code, the two loops are merged. update = .true. i = 0_${ik}$ 490 continue if( update ) then i = i + 1_${ik}$ kbt = min( kb, m-i ) i0 = i + 1_${ik}$ i1 = max( 1_${ik}$, i-ka ) i2 = i + kbt - ka1 if( i>m ) then update = .false. i = i - 1_${ik}$ i0 = m + 1_${ik}$ if( ka==0 )return go to 490 end if else i = i - ka if( i<2 )return end if if( i0_${ik}$ )call stdlib${ii}$_${ri}$ger( nx, kbt, -one, x( 1_${ik}$, i ), 1_${ik}$, bb( kb, i+1 ),ldbb-& 1_${ik}$, x( 1_${ik}$, i+1 ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+ka1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_610: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_${ri}$largv( nrt, ab( 1_${ik}$, j1+ka ), inca, work( j1 ), ka1,work( & n+j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_${ri}$lartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca, & work( n+j1 ),work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_${ri}$lar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & work( n+j1 ),work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& work( n+j1t ),work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_${ri}$rot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+j ), work( j ) ) end do end if end do loop_610 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt-ka-1,i+kbt) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kb1-kbt, i+kbt )*ra1 end if end if loop_650: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( l, j1t+ka ), inca,ab( l+1, j1t+ka-1 ),& inca,work( n+m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) work( n+m-kb+j ) = work( n+m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j-1,j+ka) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( 1_${ik}$, j+ka-1 ) ab( 1_${ik}$, j+ka-1 ) = work( n+m-kb+j )*ab( 1_${ik}$, j+ka-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_650 loop_690: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_${ri}$largv( nr, ab( 1_${ik}$, j1+ka ), inca, work( m-kb+j1 ),ka1, work( n+m-& kb+j1 ), ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_${ri}$lartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca,& work( n+m-kb+j1 ), work( m-kb+j1 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_${ri}$lar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & work( n+m-kb+j1 ),work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& work( n+m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_${ri}$rot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+m-kb+j ), work( & m-kb+j ) ) end do end if end do loop_690 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& work( n+j1t ),work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, min( i+kb, m ) - 2*ka - 1 work( n+j ) = work( n+j+ka ) work( j ) = work( j+ka ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**t * a * inv(s(i)) bii = bb( 1_${ik}$, i ) do j = i1, i ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do j = i, min( n, i+ka ) ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do k = i + 1, i + kbt do j = k, i + kbt ab( j-k+1, k ) = ab( j-k+1, k ) -bb( j-i+1, i )*ab( k-i+1, i ) -bb( k-i+1, & i )*ab( j-i+1, i ) +ab( 1_${ik}$, i )*bb( j-i+1, i )*bb( k-i+1, i ) end do do j = i + kbt + 1, min( n, i+ka ) ab( j-k+1, k ) = ab( j-k+1, k ) -bb( k-i+1, i )*ab( j-i+1, i ) end do end do do j = i1, i do k = i + 1, min( j+ka, i+kbt ) ab( k-j+1, j ) = ab( k-j+1, j ) -bb( k-i+1, i )*ab( i-j+1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_${ri}$scal( nx, one / bii, x( 1_${ik}$, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_${ri}$ger( nx, kbt, -one, x( 1_${ik}$, i ), 1_${ik}$, bb( 2_${ik}$, i ), 1_${ik}$,x( 1_${ik}$, & i+1 ), ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_840: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_${ri}$largv( nrt, ab( ka1, j1 ), inca, work( j1 ), ka1,work( n+& j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_${ri}$lartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, work( n+& j1 ), work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_${ri}$lar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, work( & n+j1 ),work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,work( n+j1t ), work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_${ri}$rot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+j ), work( j ) ) end do end if end do loop_840 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt,i+kbt-ka-1) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kbt+1, i )*ra1 end if end if loop_880: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( ka1-l+1, j1t+l-1 ), inca,ab( ka1-l, & j1t+l-1 ), inca,work( n+m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) work( n+m-kb+j ) = work( n+m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j+ka,j-1) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( ka1, j-1 ) ab( ka1, j-1 ) = work( n+m-kb+j )*ab( ka1, j-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_880 loop_920: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_${ri}$largv( nr, ab( ka1, j1 ), inca, work( m-kb+j1 ),ka1, work( n+m-& kb+j1 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_${ri}$lartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, work( n+& m-kb+j1 ), work( m-kb+j1 ),ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_${ri}$lar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, work( & n+m-kb+j1 ),work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,work( n+m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_${ri}$rot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,work( n+m-kb+j ), work( & m-kb+j ) ) end do end if end do loop_920 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,work( n+j1t ), work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, min( i+kb, m ) - 2*ka - 1 work( n+j ) = work( n+j+ka ) work( j ) = work( j+ka ) end do end if end if go to 490 end subroutine stdlib${ii}$_${ri}$sbgst #:endif #:endfor pure module subroutine stdlib${ii}$_chegst( itype, uplo, n, a, lda, b, ldb, info ) !! CHEGST reduces a complex Hermitian-definite generalized !! eigenproblem to standard form. !! If ITYPE = 1, the problem is A*x = lambda*B*x, !! and A is overwritten by inv(U**H)*A*inv(U) or inv(L)*A*inv(L**H) !! If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or !! B*A*x = lambda*x, and A is overwritten by U*A*U**H or L**H*A*L. !! B must have been previously factorized as U**H*U or L*L**H by CPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype, lda, ldb, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*), b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: k, kb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( itype<1_${ik}$ .or. itype>3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_chegs2( itype, uplo, n, a, lda, b, ldb, info ) else ! use blocked code if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**h)*a*inv(u) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(k:n,k:n) call stdlib${ii}$_chegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_ctrsm( 'LEFT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', kb, & n-k-kb+1, cone,b( k, k ), ldb, a( k, k+kb ), lda ) call stdlib${ii}$_chemm( 'LEFT', uplo, kb, n-k-kb+1, -chalf,a( k, k ), lda, b(& k, k+kb ), ldb,cone, a( k, k+kb ), lda ) call stdlib${ii}$_cher2k( uplo, 'CONJUGATE TRANSPOSE', n-k-kb+1,kb, -cone, a( & k, k+kb ), lda,b( k, k+kb ), ldb, one,a( k+kb, k+kb ), lda ) call stdlib${ii}$_chemm( 'LEFT', uplo, kb, n-k-kb+1, -chalf,a( k, k ), lda, b(& k, k+kb ), ldb,cone, a( k, k+kb ), lda ) call stdlib${ii}$_ctrsm( 'RIGHT', uplo, 'NO TRANSPOSE','NON-UNIT', kb, n-k-kb+& 1_${ik}$, cone,b( k+kb, k+kb ), ldb, a( k, k+kb ),lda ) end if end do else ! compute inv(l)*a*inv(l**h) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(k:n,k:n) call stdlib${ii}$_chegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_ctrsm( 'RIGHT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', n-k-& kb+1, kb, cone,b( k, k ), ldb, a( k+kb, k ), lda ) call stdlib${ii}$_chemm( 'RIGHT', uplo, n-k-kb+1, kb, -chalf,a( k, k ), lda, & b( k+kb, k ), ldb,cone, a( k+kb, k ), lda ) call stdlib${ii}$_cher2k( uplo, 'NO TRANSPOSE', n-k-kb+1, kb,-cone, a( k+kb, & k ), lda,b( k+kb, k ), ldb, one,a( k+kb, k+kb ), lda ) call stdlib${ii}$_chemm( 'RIGHT', uplo, n-k-kb+1, kb, -chalf,a( k, k ), lda, & b( k+kb, k ), ldb,cone, a( k+kb, k ), lda ) call stdlib${ii}$_ctrsm( 'LEFT', uplo, 'NO TRANSPOSE','NON-UNIT', n-k-kb+1, & kb, cone,b( k+kb, k+kb ), ldb, a( k+kb, k ),lda ) end if end do end if else if( upper ) then ! compute u*a*u**h do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_ctrmm( 'LEFT', uplo, 'NO TRANSPOSE', 'NON-UNIT',k-1, kb, cone, & b, ldb, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_chemm( 'RIGHT', uplo, k-1, kb, chalf, a( k, k ),lda, b( 1_${ik}$, k ),& ldb, cone, a( 1_${ik}$, k ),lda ) call stdlib${ii}$_cher2k( uplo, 'NO TRANSPOSE', k-1, kb, cone,a( 1_${ik}$, k ), lda, b( & 1_${ik}$, k ), ldb, one, a,lda ) call stdlib${ii}$_chemm( 'RIGHT', uplo, k-1, kb, chalf, a( k, k ),lda, b( 1_${ik}$, k ),& ldb, cone, a( 1_${ik}$, k ),lda ) call stdlib${ii}$_ctrmm( 'RIGHT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', k-1, & kb, cone, b( k, k ), ldb,a( 1_${ik}$, k ), lda ) call stdlib${ii}$_chegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do else ! compute l**h*a*l do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_ctrmm( 'RIGHT', uplo, 'NO TRANSPOSE', 'NON-UNIT',kb, k-1, cone,& b, ldb, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_chemm( 'LEFT', uplo, kb, k-1, chalf, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, cone, a( k, 1_${ik}$ ),lda ) call stdlib${ii}$_cher2k( uplo, 'CONJUGATE TRANSPOSE', k-1, kb,cone, a( k, 1_${ik}$ ), & lda, b( k, 1_${ik}$ ), ldb,one, a, lda ) call stdlib${ii}$_chemm( 'LEFT', uplo, kb, k-1, chalf, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, cone, a( k, 1_${ik}$ ),lda ) call stdlib${ii}$_ctrmm( 'LEFT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', kb, k-1,& cone, b( k, k ), ldb,a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_chegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do end if end if end if return end subroutine stdlib${ii}$_chegst pure module subroutine stdlib${ii}$_zhegst( itype, uplo, n, a, lda, b, ldb, info ) !! ZHEGST reduces a complex Hermitian-definite generalized !! eigenproblem to standard form. !! If ITYPE = 1, the problem is A*x = lambda*B*x, !! and A is overwritten by inv(U**H)*A*inv(U) or inv(L)*A*inv(L**H) !! If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or !! B*A*x = lambda*x, and A is overwritten by U*A*U**H or L**H*A*L. !! B must have been previously factorized as U**H*U or L*L**H by ZPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype, lda, ldb, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*), b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: k, kb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( itype<1_${ik}$ .or. itype>3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_zhegs2( itype, uplo, n, a, lda, b, ldb, info ) else ! use blocked code if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**h)*a*inv(u) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(k:n,k:n) call stdlib${ii}$_zhegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_ztrsm( 'LEFT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', kb, & n-k-kb+1, cone,b( k, k ), ldb, a( k, k+kb ), lda ) call stdlib${ii}$_zhemm( 'LEFT', uplo, kb, n-k-kb+1, -chalf,a( k, k ), lda, b(& k, k+kb ), ldb,cone, a( k, k+kb ), lda ) call stdlib${ii}$_zher2k( uplo, 'CONJUGATE TRANSPOSE', n-k-kb+1,kb, -cone, a( & k, k+kb ), lda,b( k, k+kb ), ldb, one,a( k+kb, k+kb ), lda ) call stdlib${ii}$_zhemm( 'LEFT', uplo, kb, n-k-kb+1, -chalf,a( k, k ), lda, b(& k, k+kb ), ldb,cone, a( k, k+kb ), lda ) call stdlib${ii}$_ztrsm( 'RIGHT', uplo, 'NO TRANSPOSE','NON-UNIT', kb, n-k-kb+& 1_${ik}$, cone,b( k+kb, k+kb ), ldb, a( k, k+kb ),lda ) end if end do else ! compute inv(l)*a*inv(l**h) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(k:n,k:n) call stdlib${ii}$_zhegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_ztrsm( 'RIGHT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', n-k-& kb+1, kb, cone,b( k, k ), ldb, a( k+kb, k ), lda ) call stdlib${ii}$_zhemm( 'RIGHT', uplo, n-k-kb+1, kb, -chalf,a( k, k ), lda, & b( k+kb, k ), ldb,cone, a( k+kb, k ), lda ) call stdlib${ii}$_zher2k( uplo, 'NO TRANSPOSE', n-k-kb+1, kb,-cone, a( k+kb, & k ), lda,b( k+kb, k ), ldb, one,a( k+kb, k+kb ), lda ) call stdlib${ii}$_zhemm( 'RIGHT', uplo, n-k-kb+1, kb, -chalf,a( k, k ), lda, & b( k+kb, k ), ldb,cone, a( k+kb, k ), lda ) call stdlib${ii}$_ztrsm( 'LEFT', uplo, 'NO TRANSPOSE','NON-UNIT', n-k-kb+1, & kb, cone,b( k+kb, k+kb ), ldb, a( k+kb, k ),lda ) end if end do end if else if( upper ) then ! compute u*a*u**h do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_ztrmm( 'LEFT', uplo, 'NO TRANSPOSE', 'NON-UNIT',k-1, kb, cone, & b, ldb, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_zhemm( 'RIGHT', uplo, k-1, kb, chalf, a( k, k ),lda, b( 1_${ik}$, k ),& ldb, cone, a( 1_${ik}$, k ),lda ) call stdlib${ii}$_zher2k( uplo, 'NO TRANSPOSE', k-1, kb, cone,a( 1_${ik}$, k ), lda, b( & 1_${ik}$, k ), ldb, one, a,lda ) call stdlib${ii}$_zhemm( 'RIGHT', uplo, k-1, kb, chalf, a( k, k ),lda, b( 1_${ik}$, k ),& ldb, cone, a( 1_${ik}$, k ),lda ) call stdlib${ii}$_ztrmm( 'RIGHT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', k-1, & kb, cone, b( k, k ), ldb,a( 1_${ik}$, k ), lda ) call stdlib${ii}$_zhegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do else ! compute l**h*a*l do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_ztrmm( 'RIGHT', uplo, 'NO TRANSPOSE', 'NON-UNIT',kb, k-1, cone,& b, ldb, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_zhemm( 'LEFT', uplo, kb, k-1, chalf, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, cone, a( k, 1_${ik}$ ),lda ) call stdlib${ii}$_zher2k( uplo, 'CONJUGATE TRANSPOSE', k-1, kb,cone, a( k, 1_${ik}$ ), & lda, b( k, 1_${ik}$ ), ldb,one, a, lda ) call stdlib${ii}$_zhemm( 'LEFT', uplo, kb, k-1, chalf, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, cone, a( k, 1_${ik}$ ),lda ) call stdlib${ii}$_ztrmm( 'LEFT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', kb, k-1,& cone, b( k, k ), ldb,a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_zhegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do end if end if end if return end subroutine stdlib${ii}$_zhegst #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hegst( itype, uplo, n, a, lda, b, ldb, info ) !! ZHEGST: reduces a complex Hermitian-definite generalized !! eigenproblem to standard form. !! If ITYPE = 1, the problem is A*x = lambda*B*x, !! and A is overwritten by inv(U**H)*A*inv(U) or inv(L)*A*inv(L**H) !! If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or !! B*A*x = lambda*x, and A is overwritten by U*A*U**H or L**H*A*L. !! B must have been previously factorized as U**H*U or L*L**H by ZPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype, lda, ldb, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: k, kb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( itype<1_${ik}$ .or. itype>3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_${ci}$hegs2( itype, uplo, n, a, lda, b, ldb, info ) else ! use blocked code if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**h)*a*inv(u) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(k:n,k:n) call stdlib${ii}$_${ci}$hegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_${ci}$trsm( 'LEFT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', kb, & n-k-kb+1, cone,b( k, k ), ldb, a( k, k+kb ), lda ) call stdlib${ii}$_${ci}$hemm( 'LEFT', uplo, kb, n-k-kb+1, -chalf,a( k, k ), lda, b(& k, k+kb ), ldb,cone, a( k, k+kb ), lda ) call stdlib${ii}$_${ci}$her2k( uplo, 'CONJUGATE TRANSPOSE', n-k-kb+1,kb, -cone, a( & k, k+kb ), lda,b( k, k+kb ), ldb, one,a( k+kb, k+kb ), lda ) call stdlib${ii}$_${ci}$hemm( 'LEFT', uplo, kb, n-k-kb+1, -chalf,a( k, k ), lda, b(& k, k+kb ), ldb,cone, a( k, k+kb ), lda ) call stdlib${ii}$_${ci}$trsm( 'RIGHT', uplo, 'NO TRANSPOSE','NON-UNIT', kb, n-k-kb+& 1_${ik}$, cone,b( k+kb, k+kb ), ldb, a( k, k+kb ),lda ) end if end do else ! compute inv(l)*a*inv(l**h) do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(k:n,k:n) call stdlib${ii}$_${ci}$hegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) if( k+kb<=n ) then call stdlib${ii}$_${ci}$trsm( 'RIGHT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', n-k-& kb+1, kb, cone,b( k, k ), ldb, a( k+kb, k ), lda ) call stdlib${ii}$_${ci}$hemm( 'RIGHT', uplo, n-k-kb+1, kb, -chalf,a( k, k ), lda, & b( k+kb, k ), ldb,cone, a( k+kb, k ), lda ) call stdlib${ii}$_${ci}$her2k( uplo, 'NO TRANSPOSE', n-k-kb+1, kb,-cone, a( k+kb, & k ), lda,b( k+kb, k ), ldb, one,a( k+kb, k+kb ), lda ) call stdlib${ii}$_${ci}$hemm( 'RIGHT', uplo, n-k-kb+1, kb, -chalf,a( k, k ), lda, & b( k+kb, k ), ldb,cone, a( k+kb, k ), lda ) call stdlib${ii}$_${ci}$trsm( 'LEFT', uplo, 'NO TRANSPOSE','NON-UNIT', n-k-kb+1, & kb, cone,b( k+kb, k+kb ), ldb, a( k+kb, k ),lda ) end if end do end if else if( upper ) then ! compute u*a*u**h do k = 1, n, nb kb = min( n-k+1, nb ) ! update the upper triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_${ci}$trmm( 'LEFT', uplo, 'NO TRANSPOSE', 'NON-UNIT',k-1, kb, cone, & b, ldb, a( 1_${ik}$, k ), lda ) call stdlib${ii}$_${ci}$hemm( 'RIGHT', uplo, k-1, kb, chalf, a( k, k ),lda, b( 1_${ik}$, k ),& ldb, cone, a( 1_${ik}$, k ),lda ) call stdlib${ii}$_${ci}$her2k( uplo, 'NO TRANSPOSE', k-1, kb, cone,a( 1_${ik}$, k ), lda, b( & 1_${ik}$, k ), ldb, one, a,lda ) call stdlib${ii}$_${ci}$hemm( 'RIGHT', uplo, k-1, kb, chalf, a( k, k ),lda, b( 1_${ik}$, k ),& ldb, cone, a( 1_${ik}$, k ),lda ) call stdlib${ii}$_${ci}$trmm( 'RIGHT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', k-1, & kb, cone, b( k, k ), ldb,a( 1_${ik}$, k ), lda ) call stdlib${ii}$_${ci}$hegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do else ! compute l**h*a*l do k = 1, n, nb kb = min( n-k+1, nb ) ! update the lower triangle of a(1:k+kb-1,1:k+kb-1) call stdlib${ii}$_${ci}$trmm( 'RIGHT', uplo, 'NO TRANSPOSE', 'NON-UNIT',kb, k-1, cone,& b, ldb, a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$hemm( 'LEFT', uplo, kb, k-1, chalf, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, cone, a( k, 1_${ik}$ ),lda ) call stdlib${ii}$_${ci}$her2k( uplo, 'CONJUGATE TRANSPOSE', k-1, kb,cone, a( k, 1_${ik}$ ), & lda, b( k, 1_${ik}$ ), ldb,one, a, lda ) call stdlib${ii}$_${ci}$hemm( 'LEFT', uplo, kb, k-1, chalf, a( k, k ),lda, b( k, 1_${ik}$ ), & ldb, cone, a( k, 1_${ik}$ ),lda ) call stdlib${ii}$_${ci}$trmm( 'LEFT', uplo, 'CONJUGATE TRANSPOSE','NON-UNIT', kb, k-1,& cone, b( k, k ), ldb,a( k, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$hegs2( itype, uplo, kb, a( k, k ), lda,b( k, k ), ldb, info ) end do end if end if end if return end subroutine stdlib${ii}$_${ci}$hegst #:endif #:endfor pure module subroutine stdlib${ii}$_chegs2( itype, uplo, n, a, lda, b, ldb, info ) !! CHEGS2 reduces a complex Hermitian-definite generalized !! eigenproblem to standard form. !! If ITYPE = 1, the problem is A*x = lambda*B*x, !! and A is overwritten by inv(U**H)*A*inv(U) or inv(L)*A*inv(L**H) !! If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or !! B*A*x = lambda*x, and A is overwritten by U*A*U**H or L**H *A*L. !! B must have been previously factorized as U**H *U or L*L**H by ZPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: itype, lda, ldb, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*), b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: k real(sp) :: akk, bkk complex(sp) :: ct ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( itype<1_${ik}$ .or. itype>3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHPGST', -info ) return end if if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**h)*a*inv(u) ! j1 and jj are the indices of a(1,j) and a(j,j) jj = 0_${ik}$ do j = 1, n j1 = jj + 1_${ik}$ jj = jj + j ! compute the j-th column of the upper triangle of a ap( jj ) = real( ap( jj ),KIND=sp) bjj = real( bp( jj ),KIND=sp) call stdlib${ii}$_ctpsv( uplo, 'CONJUGATE TRANSPOSE', 'NON-UNIT', j,bp, ap( j1 ), 1_${ik}$ & ) call stdlib${ii}$_chpmv( uplo, j-1, -cone, ap, bp( j1 ), 1_${ik}$, cone,ap( j1 ), 1_${ik}$ ) call stdlib${ii}$_csscal( j-1, one / bjj, ap( j1 ), 1_${ik}$ ) ap( jj ) = ( ap( jj )-stdlib${ii}$_cdotc( j-1, ap( j1 ), 1_${ik}$, bp( j1 ),1_${ik}$ ) ) / & bjj end do else ! compute inv(l)*a*inv(l**h) ! kk and k1k1 are the indices of a(k,k) and a(k+1,k+1) kk = 1_${ik}$ do k = 1, n k1k1 = kk + n - k + 1_${ik}$ ! update the lower triangle of a(k:n,k:n) akk = real( ap( kk ),KIND=sp) bkk = real( bp( kk ),KIND=sp) akk = akk / bkk**2_${ik}$ ap( kk ) = akk if( k3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHPGST', -info ) return end if if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**h)*a*inv(u) ! j1 and jj are the indices of a(1,j) and a(j,j) jj = 0_${ik}$ do j = 1, n j1 = jj + 1_${ik}$ jj = jj + j ! compute the j-th column of the upper triangle of a ap( jj ) = real( ap( jj ),KIND=dp) bjj = real( bp( jj ),KIND=dp) call stdlib${ii}$_ztpsv( uplo, 'CONJUGATE TRANSPOSE', 'NON-UNIT', j,bp, ap( j1 ), 1_${ik}$ & ) call stdlib${ii}$_zhpmv( uplo, j-1, -cone, ap, bp( j1 ), 1_${ik}$, cone,ap( j1 ), 1_${ik}$ ) call stdlib${ii}$_zdscal( j-1, one / bjj, ap( j1 ), 1_${ik}$ ) ap( jj ) = ( ap( jj )-stdlib${ii}$_zdotc( j-1, ap( j1 ), 1_${ik}$, bp( j1 ),1_${ik}$ ) ) / & bjj end do else ! compute inv(l)*a*inv(l**h) ! kk and k1k1 are the indices of a(k,k) and a(k+1,k+1) kk = 1_${ik}$ do k = 1, n k1k1 = kk + n - k + 1_${ik}$ ! update the lower triangle of a(k:n,k:n) akk = real( ap( kk ),KIND=dp) bkk = real( bp( kk ),KIND=dp) akk = akk / bkk**2_${ik}$ ap( kk ) = akk if( k3_${ik}$ ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHPGST', -info ) return end if if( itype==1_${ik}$ ) then if( upper ) then ! compute inv(u**h)*a*inv(u) ! j1 and jj are the indices of a(1,j) and a(j,j) jj = 0_${ik}$ do j = 1, n j1 = jj + 1_${ik}$ jj = jj + j ! compute the j-th column of the upper triangle of a ap( jj ) = real( ap( jj ),KIND=${ck}$) bjj = real( bp( jj ),KIND=${ck}$) call stdlib${ii}$_${ci}$tpsv( uplo, 'CONJUGATE TRANSPOSE', 'NON-UNIT', j,bp, ap( j1 ), 1_${ik}$ & ) call stdlib${ii}$_${ci}$hpmv( uplo, j-1, -cone, ap, bp( j1 ), 1_${ik}$, cone,ap( j1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( j-1, one / bjj, ap( j1 ), 1_${ik}$ ) ap( jj ) = ( ap( jj )-stdlib${ii}$_${ci}$dotc( j-1, ap( j1 ), 1_${ik}$, bp( j1 ),1_${ik}$ ) ) / & bjj end do else ! compute inv(l)*a*inv(l**h) ! kk and k1k1 are the indices of a(k,k) and a(k+1,k+1) kk = 1_${ik}$ do k = 1, n k1k1 = kk + n - k + 1_${ik}$ ! update the lower triangle of a(k:n,k:n) akk = real( ap( kk ),KIND=${ck}$) bkk = real( bp( kk ),KIND=${ck}$) akk = akk / bkk**2_${ik}$ ap( kk ) = akk if( kka ) then info = -5_${ik}$ else if( ldabn-1 )go to 480 end if if( upper ) then ! transform a, working with the upper triangle if( update ) then ! form inv(s(i))**h * a * inv(s(i)) bii = real( bb( kb1, i ),KIND=sp) ab( ka1, i ) = ( real( ab( ka1, i ),KIND=sp) / bii ) / bii do j = i + 1, i1 ab( i-j+ka1, j ) = ab( i-j+ka1, j ) / bii end do do j = max( 1, i-ka ), i - 1 ab( j-i+ka1, i ) = ab( j-i+ka1, i ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -bb( j-i+kb1, i )*conjg( ab( k-i+ka1, & i ) ) -conjg( bb( k-i+kb1, i ) )*ab( j-i+ka1, i ) +real( ab( ka1, i ),& KIND=sp)*bb( j-i+kb1, i )*conjg( bb( k-i+kb1, i ) ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -conjg( bb( k-i+kb1, i ) )*ab( j-i+ka1,& i ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( k-j+ka1, j ) = ab( k-j+ka1, j ) -bb( k-i+kb1, i )*ab( i-j+ka1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_csscal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_cgerc( n-m, kbt, -cone, x( m+1, i ), 1_${ik}$,bb( kb1-kbt, i )& , 1_${ik}$, x( m+1, i-kbt ),ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+ka1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_130: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i,i-k+ka+1) call stdlib${ii}$_clartg( ab( k+1, i-k+ka ), ra1,rwork( i-k+ka-m ), work( i-k+ka-& m ), ra ) ! create nonzero element a(i-k,i-k+ka+1) outside the ! band and store it in work(i-k) t = -bb( kb1-k, i )*ra1 work( i-k ) = rwork( i-k+ka-m )*t -conjg( work( i-k+ka-m ) )*ab( 1_${ik}$, i-k+ka & ) ab( 1_${ik}$, i-k+ka ) = work( i-k+ka-m )*t +rwork( i-k+ka-m )*ab( 1_${ik}$, i-k+ka ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = rwork( j-m )*ab( 1_${ik}$, j+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_clargv( nrt, ab( 1_${ik}$, j2t ), inca, work( j2t-m ), ka1,rwork(& j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_clartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, & rwork( j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_clar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & rwork( j2-m ),work( j2-m ), ka1 ) call stdlib${ii}$_clacgv( nr, work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, rwork( j2-m ),work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_crot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j-m ), & conjg( work( j-m ) ) ) end do end if end do loop_130 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt,i-kbt+ka+1) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kb1-kbt, i )*ra1 end if end if loop_170: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( l, j2-l+1 ), inca,ab( l+1, j2-l+1 ), & inca, rwork( j2-ka ),work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) rwork( j ) = rwork( j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j) work( j ) = work( j )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = rwork( j )*ab( 1_${ik}$, j+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_clargv( nr, ab( 1_${ik}$, j2 ), inca, work( j2 ), ka1,rwork( j2 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_clartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, & rwork( j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_clar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & rwork( j2 ),work( j2 ), ka1 ) call stdlib${ii}$_clacgv( nr, work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, rwork( j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_crot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j ), conjg( & work( j ) ) ) end do end if end do loop_210 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, rwork( j2-m ),work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, j2 + ka, -1 rwork( j-m ) = rwork( j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**h * a * inv(s(i)) bii = real( bb( 1_${ik}$, i ),KIND=sp) ab( 1_${ik}$, i ) = ( real( ab( 1_${ik}$, i ),KIND=sp) / bii ) / bii do j = i + 1, i1 ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do j = max( 1, i-ka ), i - 1 ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( k-j+1, j ) = ab( k-j+1, j ) -bb( i-j+1, j )*conjg( ab( i-k+1,k ) ) - & conjg( bb( i-k+1, k ) )*ab( i-j+1, j ) + real( ab( 1_${ik}$, i ),KIND=sp)*bb( i-j+& 1_${ik}$, j )*conjg( bb( i-k+1,k ) ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( k-j+1, j ) = ab( k-j+1, j ) -conjg( bb( i-k+1, k ) )*ab( i-j+1, j ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( j-k+1, k ) = ab( j-k+1, k ) -bb( i-k+1, k )*ab( j-i+1, i ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_csscal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_cgeru( n-m, kbt, -cone, x( m+1, i ), 1_${ik}$,bb( kbt+1, i-& kbt ), ldbb-1,x( m+1, i-kbt ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_360: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i-k+ka+1,i) call stdlib${ii}$_clartg( ab( ka1-k, i ), ra1, rwork( i-k+ka-m ),work( i-k+ka-m )& , ra ) ! create nonzero element a(i-k+ka+1,i-k) outside the ! band and store it in work(i-k) t = -bb( k+1, i-k )*ra1 work( i-k ) = rwork( i-k+ka-m )*t -conjg( work( i-k+ka-m ) )*ab( ka1, i-k ) ab( ka1, i-k ) = work( i-k+ka-m )*t +rwork( i-k+ka-m )*ab( ka1, i-k ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = rwork( j-m )*ab( ka1, j-ka+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_clargv( nrt, ab( ka1, j2t-ka ), inca, work( j2t-m ),ka1, & rwork( j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_clartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, rwork(& j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_clar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, rwork( & j2-m ), work( j2-m ), ka1 ) call stdlib${ii}$_clacgv( nr, work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, rwork( j2-m ),work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_crot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j-m ), work(& j-m ) ) end do end if end do loop_360 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt+ka+1,i-kbt) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kbt+1, i-kbt )*ra1 end if end if loop_400: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( ka1-l+1, j2-ka ), inca,ab( ka1-l, j2-& ka+1 ), inca,rwork( j2-ka ), work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) rwork( j ) = rwork( j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j) work( j ) = work( j )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = rwork( j )*ab( ka1, j-ka+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_clargv( nr, ab( ka1, j2-ka ), inca, work( j2 ), ka1,rwork( j2 ), & ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_clartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, rwork(& j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_clar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, rwork( & j2 ), work( j2 ), ka1 ) call stdlib${ii}$_clacgv( nr, work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, rwork( j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_crot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j ), work( & j ) ) end do end if end do loop_440 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, rwork( j2-m ),work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, j2 + ka, -1 rwork( j-m ) = rwork( j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if end if go to 10 480 continue ! **************************** phase 2 ***************************** ! the logical structure of this phase is: ! update = .true. ! do i = 1, m ! use s(i) to update a and create a new bulge ! apply rotations to push all bulges ka positions upward ! end do ! update = .false. ! do i = m - ka - 1, 2, -1 ! apply rotations to push all bulges ka positions upward ! end do ! to avoid duplicating code, the two loops are merged. update = .true. i = 0_${ik}$ 490 continue if( update ) then i = i + 1_${ik}$ kbt = min( kb, m-i ) i0 = i + 1_${ik}$ i1 = max( 1_${ik}$, i-ka ) i2 = i + kbt - ka1 if( i>m ) then update = .false. i = i - 1_${ik}$ i0 = m + 1_${ik}$ if( ka==0 )return go to 490 end if else i = i - ka if( i<2 )return end if if( i0_${ik}$ )call stdlib${ii}$_cgeru( nx, kbt, -cone, x( 1_${ik}$, i ), 1_${ik}$,bb( kb, i+1 ), & ldbb-1, x( 1_${ik}$, i+1 ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+ka1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_610: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_clargv( nrt, ab( 1_${ik}$, j1+ka ), inca, work( j1 ), ka1,rwork( & j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_clartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca, & rwork( j1 ),work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_clar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & rwork( j1 ), work( j1 ),ka1 ) call stdlib${ii}$_clacgv( nr, work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& rwork( j1t ),work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_crot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( j ), work( j ) ) end do end if end do loop_610 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt-ka-1,i+kbt) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kb1-kbt, i+kbt )*ra1 end if end if loop_650: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( l, j1t+ka ), inca,ab( l+1, j1t+ka-1 ),& inca,rwork( m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) rwork( m-kb+j ) = rwork( m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j-1,j+ka) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( 1_${ik}$, j+ka-1 ) ab( 1_${ik}$, j+ka-1 ) = rwork( m-kb+j )*ab( 1_${ik}$, j+ka-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_650 loop_690: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_clargv( nr, ab( 1_${ik}$, j1+ka ), inca, work( m-kb+j1 ),ka1, rwork( m-& kb+j1 ), ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_clartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca, & rwork( m-kb+j1 ),work( m-kb+j1 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_clar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & rwork( m-kb+j1 ),work( m-kb+j1 ), ka1 ) call stdlib${ii}$_clacgv( nr, work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& rwork( m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_crot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( m-kb+j ), work( & m-kb+j ) ) end do end if end do loop_690 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& rwork( j1t ),work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, i2 - ka rwork( j ) = rwork( j+ka ) work( j ) = work( j+ka ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**h * a * inv(s(i)) bii = real( bb( 1_${ik}$, i ),KIND=sp) ab( 1_${ik}$, i ) = ( real( ab( 1_${ik}$, i ),KIND=sp) / bii ) / bii do j = i1, i - 1 ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do j = i + 1, min( n, i+ka ) ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do k = i + 1, i + kbt do j = k, i + kbt ab( j-k+1, k ) = ab( j-k+1, k ) -bb( j-i+1, i )*conjg( ab( k-i+1,i ) ) - & conjg( bb( k-i+1, i ) )*ab( j-i+1, i ) + real( ab( 1_${ik}$, i ),KIND=sp)*bb( j-i+& 1_${ik}$, i )*conjg( bb( k-i+1,i ) ) end do do j = i + kbt + 1, min( n, i+ka ) ab( j-k+1, k ) = ab( j-k+1, k ) -conjg( bb( k-i+1, i ) )*ab( j-i+1, i ) end do end do do j = i1, i do k = i + 1, min( j+ka, i+kbt ) ab( k-j+1, j ) = ab( k-j+1, j ) -bb( k-i+1, i )*ab( i-j+1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_csscal( nx, one / bii, x( 1_${ik}$, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_cgerc( nx, kbt, -cone, x( 1_${ik}$, i ), 1_${ik}$, bb( 2_${ik}$, i ),1_${ik}$, x( & 1_${ik}$, i+1 ), ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_840: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_clargv( nrt, ab( ka1, j1 ), inca, work( j1 ), ka1,rwork( & j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_clartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, rwork( & j1 ), work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_clar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, rwork(& j1 ),work( j1 ), ka1 ) call stdlib${ii}$_clacgv( nr, work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,rwork( j1t ), work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_crot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( j ), conjg( work(& j ) ) ) end do end if end do loop_840 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt,i+kbt-ka-1) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kbt+1, i )*ra1 end if end if loop_880: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( ka1-l+1, j1t+l-1 ), inca,ab( ka1-l, & j1t+l-1 ), inca,rwork( m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) rwork( m-kb+j ) = rwork( m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j+ka,j-1) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( ka1, j-1 ) ab( ka1, j-1 ) = rwork( m-kb+j )*ab( ka1, j-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_880 loop_920: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_clargv( nr, ab( ka1, j1 ), inca, work( m-kb+j1 ),ka1, rwork( m-kb+& j1 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_clartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, rwork( & m-kb+j1 ), work( m-kb+j1 ),ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_clar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, rwork(& m-kb+j1 ),work( m-kb+j1 ), ka1 ) call stdlib${ii}$_clacgv( nr, work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,rwork( m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_crot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( m-kb+j ), conjg( & work( m-kb+j ) ) ) end do end if end do loop_920 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,rwork( j1t ), work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, i2 - ka rwork( j ) = rwork( j+ka ) work( j ) = work( j+ka ) end do end if end if go to 490 end subroutine stdlib${ii}$_chbgst pure module subroutine stdlib${ii}$_zhbgst( vect, uplo, n, ka, kb, ab, ldab, bb, ldbb, x,ldx, work, rwork,& !! ZHBGST reduces a complex Hermitian-definite banded generalized !! eigenproblem A*x = lambda*B*x to standard form C*y = lambda*y, !! such that C has the same bandwidth as A. !! B must have been previously factorized as S**H*S by ZPBSTF, using a !! split Cholesky factorization. A is overwritten by C = X**H*A*X, where !! X = S**(-1)*Q and Q is a unitary matrix chosen to preserve the !! bandwidth of A. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka, kb, ldab, ldbb, ldx, n ! Array Arguments real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: ab(ldab,*) complex(dp), intent(in) :: bb(ldbb,*) complex(dp), intent(out) :: work(*), x(ldx,*) ! ===================================================================== ! Local Scalars logical(lk) :: update, upper, wantx integer(${ik}$) :: i, i0, i1, i2, inca, j, j1, j1t, j2, j2t, k, ka1, kb1, kbt, l, m, nr, & nrt, nx real(dp) :: bii complex(dp) :: ra, ra1, t ! Intrinsic Functions ! Executable Statements ! test the input parameters wantx = stdlib_lsame( vect, 'V' ) upper = stdlib_lsame( uplo, 'U' ) ka1 = ka + 1_${ik}$ kb1 = kb + 1_${ik}$ info = 0_${ik}$ if( .not.wantx .and. .not.stdlib_lsame( vect, 'N' ) ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ka<0_${ik}$ ) then info = -4_${ik}$ else if( kb<0_${ik}$ .or. kb>ka ) then info = -5_${ik}$ else if( ldabn-1 )go to 480 end if if( upper ) then ! transform a, working with the upper triangle if( update ) then ! form inv(s(i))**h * a * inv(s(i)) bii = real( bb( kb1, i ),KIND=dp) ab( ka1, i ) = ( real( ab( ka1, i ),KIND=dp) / bii ) / bii do j = i + 1, i1 ab( i-j+ka1, j ) = ab( i-j+ka1, j ) / bii end do do j = max( 1, i-ka ), i - 1 ab( j-i+ka1, i ) = ab( j-i+ka1, i ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -bb( j-i+kb1, i )*conjg( ab( k-i+ka1, & i ) ) -conjg( bb( k-i+kb1, i ) )*ab( j-i+ka1, i ) +real( ab( ka1, i ),& KIND=dp)*bb( j-i+kb1, i )*conjg( bb( k-i+kb1, i ) ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -conjg( bb( k-i+kb1, i ) )*ab( j-i+ka1,& i ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( k-j+ka1, j ) = ab( k-j+ka1, j ) -bb( k-i+kb1, i )*ab( i-j+ka1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_zdscal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_zgerc( n-m, kbt, -cone, x( m+1, i ), 1_${ik}$,bb( kb1-kbt, i )& , 1_${ik}$, x( m+1, i-kbt ),ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+ka1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_130: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i,i-k+ka+1) call stdlib${ii}$_zlartg( ab( k+1, i-k+ka ), ra1,rwork( i-k+ka-m ), work( i-k+ka-& m ), ra ) ! create nonzero element a(i-k,i-k+ka+1) outside the ! band and store it in work(i-k) t = -bb( kb1-k, i )*ra1 work( i-k ) = rwork( i-k+ka-m )*t -conjg( work( i-k+ka-m ) )*ab( 1_${ik}$, i-k+ka & ) ab( 1_${ik}$, i-k+ka ) = work( i-k+ka-m )*t +rwork( i-k+ka-m )*ab( 1_${ik}$, i-k+ka ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = rwork( j-m )*ab( 1_${ik}$, j+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_zlargv( nrt, ab( 1_${ik}$, j2t ), inca, work( j2t-m ), ka1,rwork(& j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_zlartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, & rwork( j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_zlar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & rwork( j2-m ),work( j2-m ), ka1 ) call stdlib${ii}$_zlacgv( nr, work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, rwork( j2-m ),work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_zrot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j-m ), & conjg( work( j-m ) ) ) end do end if end do loop_130 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt,i-kbt+ka+1) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kb1-kbt, i )*ra1 end if end if loop_170: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( l, j2-l+1 ), inca,ab( l+1, j2-l+1 ), & inca, rwork( j2-ka ),work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) rwork( j ) = rwork( j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j) work( j ) = work( j )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = rwork( j )*ab( 1_${ik}$, j+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_zlargv( nr, ab( 1_${ik}$, j2 ), inca, work( j2 ), ka1,rwork( j2 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_zlartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, & rwork( j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_zlar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & rwork( j2 ),work( j2 ), ka1 ) call stdlib${ii}$_zlacgv( nr, work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, rwork( j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_zrot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j ), conjg( & work( j ) ) ) end do end if end do loop_210 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, rwork( j2-m ),work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, j2 + ka, -1 rwork( j-m ) = rwork( j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**h * a * inv(s(i)) bii = real( bb( 1_${ik}$, i ),KIND=dp) ab( 1_${ik}$, i ) = ( real( ab( 1_${ik}$, i ),KIND=dp) / bii ) / bii do j = i + 1, i1 ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do j = max( 1, i-ka ), i - 1 ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( k-j+1, j ) = ab( k-j+1, j ) -bb( i-j+1, j )*conjg( ab( i-k+1,k ) ) - & conjg( bb( i-k+1, k ) )*ab( i-j+1, j ) + real( ab( 1_${ik}$, i ),KIND=dp)*bb( i-j+& 1_${ik}$, j )*conjg( bb( i-k+1,k ) ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( k-j+1, j ) = ab( k-j+1, j ) -conjg( bb( i-k+1, k ) )*ab( i-j+1, j ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( j-k+1, k ) = ab( j-k+1, k ) -bb( i-k+1, k )*ab( j-i+1, i ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_zdscal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_zgeru( n-m, kbt, -cone, x( m+1, i ), 1_${ik}$,bb( kbt+1, i-& kbt ), ldbb-1,x( m+1, i-kbt ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_360: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i-k+ka+1,i) call stdlib${ii}$_zlartg( ab( ka1-k, i ), ra1, rwork( i-k+ka-m ),work( i-k+ka-m )& , ra ) ! create nonzero element a(i-k+ka+1,i-k) outside the ! band and store it in work(i-k) t = -bb( k+1, i-k )*ra1 work( i-k ) = rwork( i-k+ka-m )*t -conjg( work( i-k+ka-m ) )*ab( ka1, i-k ) ab( ka1, i-k ) = work( i-k+ka-m )*t +rwork( i-k+ka-m )*ab( ka1, i-k ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = rwork( j-m )*ab( ka1, j-ka+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_zlargv( nrt, ab( ka1, j2t-ka ), inca, work( j2t-m ),ka1, & rwork( j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_zlartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, rwork(& j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_zlar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, rwork( & j2-m ), work( j2-m ), ka1 ) call stdlib${ii}$_zlacgv( nr, work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, rwork( j2-m ),work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_zrot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j-m ), work(& j-m ) ) end do end if end do loop_360 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt+ka+1,i-kbt) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kbt+1, i-kbt )*ra1 end if end if loop_400: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( ka1-l+1, j2-ka ), inca,ab( ka1-l, j2-& ka+1 ), inca,rwork( j2-ka ), work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) rwork( j ) = rwork( j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j) work( j ) = work( j )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = rwork( j )*ab( ka1, j-ka+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_zlargv( nr, ab( ka1, j2-ka ), inca, work( j2 ), ka1,rwork( j2 ), & ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_zlartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, rwork(& j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_zlar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, rwork( & j2 ), work( j2 ), ka1 ) call stdlib${ii}$_zlacgv( nr, work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, rwork( j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_zrot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j ), work( & j ) ) end do end if end do loop_440 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, rwork( j2-m ),work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, j2 + ka, -1 rwork( j-m ) = rwork( j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if end if go to 10 480 continue ! **************************** phase 2 ***************************** ! the logical structure of this phase is: ! update = .true. ! do i = 1, m ! use s(i) to update a and create a new bulge ! apply rotations to push all bulges ka positions upward ! end do ! update = .false. ! do i = m - ka - 1, 2, -1 ! apply rotations to push all bulges ka positions upward ! end do ! to avoid duplicating code, the two loops are merged. update = .true. i = 0_${ik}$ 490 continue if( update ) then i = i + 1_${ik}$ kbt = min( kb, m-i ) i0 = i + 1_${ik}$ i1 = max( 1_${ik}$, i-ka ) i2 = i + kbt - ka1 if( i>m ) then update = .false. i = i - 1_${ik}$ i0 = m + 1_${ik}$ if( ka==0 )return go to 490 end if else i = i - ka if( i<2 )return end if if( i0_${ik}$ )call stdlib${ii}$_zgeru( nx, kbt, -cone, x( 1_${ik}$, i ), 1_${ik}$,bb( kb, i+1 ), & ldbb-1, x( 1_${ik}$, i+1 ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+ka1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_610: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_zlargv( nrt, ab( 1_${ik}$, j1+ka ), inca, work( j1 ), ka1,rwork( & j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_zlartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca, & rwork( j1 ),work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_zlar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & rwork( j1 ), work( j1 ),ka1 ) call stdlib${ii}$_zlacgv( nr, work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& rwork( j1t ),work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_zrot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( j ), work( j ) ) end do end if end do loop_610 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt-ka-1,i+kbt) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kb1-kbt, i+kbt )*ra1 end if end if loop_650: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( l, j1t+ka ), inca,ab( l+1, j1t+ka-1 ),& inca,rwork( m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) rwork( m-kb+j ) = rwork( m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j-1,j+ka) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( 1_${ik}$, j+ka-1 ) ab( 1_${ik}$, j+ka-1 ) = rwork( m-kb+j )*ab( 1_${ik}$, j+ka-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_650 loop_690: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_zlargv( nr, ab( 1_${ik}$, j1+ka ), inca, work( m-kb+j1 ),ka1, rwork( m-& kb+j1 ), ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_zlartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca, & rwork( m-kb+j1 ),work( m-kb+j1 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_zlar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & rwork( m-kb+j1 ),work( m-kb+j1 ), ka1 ) call stdlib${ii}$_zlacgv( nr, work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& rwork( m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_zrot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( m-kb+j ), work( & m-kb+j ) ) end do end if end do loop_690 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& rwork( j1t ),work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, i2 - ka rwork( j ) = rwork( j+ka ) work( j ) = work( j+ka ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**h * a * inv(s(i)) bii = real( bb( 1_${ik}$, i ),KIND=dp) ab( 1_${ik}$, i ) = ( real( ab( 1_${ik}$, i ),KIND=dp) / bii ) / bii do j = i1, i - 1 ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do j = i + 1, min( n, i+ka ) ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do k = i + 1, i + kbt do j = k, i + kbt ab( j-k+1, k ) = ab( j-k+1, k ) -bb( j-i+1, i )*conjg( ab( k-i+1,i ) ) - & conjg( bb( k-i+1, i ) )*ab( j-i+1, i ) + real( ab( 1_${ik}$, i ),KIND=dp)*bb( j-i+& 1_${ik}$, i )*conjg( bb( k-i+1,i ) ) end do do j = i + kbt + 1, min( n, i+ka ) ab( j-k+1, k ) = ab( j-k+1, k ) -conjg( bb( k-i+1, i ) )*ab( j-i+1, i ) end do end do do j = i1, i do k = i + 1, min( j+ka, i+kbt ) ab( k-j+1, j ) = ab( k-j+1, j ) -bb( k-i+1, i )*ab( i-j+1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_zdscal( nx, one / bii, x( 1_${ik}$, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_zgerc( nx, kbt, -cone, x( 1_${ik}$, i ), 1_${ik}$, bb( 2_${ik}$, i ),1_${ik}$, x( & 1_${ik}$, i+1 ), ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_840: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_zlargv( nrt, ab( ka1, j1 ), inca, work( j1 ), ka1,rwork( & j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_zlartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, rwork( & j1 ), work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_zlar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, rwork(& j1 ),work( j1 ), ka1 ) call stdlib${ii}$_zlacgv( nr, work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,rwork( j1t ), work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_zrot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( j ), conjg( work(& j ) ) ) end do end if end do loop_840 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt,i+kbt-ka-1) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kbt+1, i )*ra1 end if end if loop_880: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( ka1-l+1, j1t+l-1 ), inca,ab( ka1-l, & j1t+l-1 ), inca,rwork( m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) rwork( m-kb+j ) = rwork( m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j+ka,j-1) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( ka1, j-1 ) ab( ka1, j-1 ) = rwork( m-kb+j )*ab( ka1, j-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_880 loop_920: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_zlargv( nr, ab( ka1, j1 ), inca, work( m-kb+j1 ),ka1, rwork( m-kb+& j1 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_zlartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, rwork( & m-kb+j1 ), work( m-kb+j1 ),ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_zlar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, rwork(& m-kb+j1 ),work( m-kb+j1 ), ka1 ) call stdlib${ii}$_zlacgv( nr, work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,rwork( m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_zrot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( m-kb+j ), conjg( & work( m-kb+j ) ) ) end do end if end do loop_920 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,rwork( j1t ), work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, i2 - ka rwork( j ) = rwork( j+ka ) work( j ) = work( j+ka ) end do end if end if go to 490 end subroutine stdlib${ii}$_zhbgst #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hbgst( vect, uplo, n, ka, kb, ab, ldab, bb, ldbb, x,ldx, work, rwork,& !! ZHBGST: reduces a complex Hermitian-definite banded generalized !! eigenproblem A*x = lambda*B*x to standard form C*y = lambda*y, !! such that C has the same bandwidth as A. !! B must have been previously factorized as S**H*S by ZPBSTF, using a !! split Cholesky factorization. A is overwritten by C = X**H*A*X, where !! X = S**(-1)*Q and Q is a unitary matrix chosen to preserve the !! bandwidth of A. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ka, kb, ldab, ldbb, ldx, n ! Array Arguments real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: ab(ldab,*) complex(${ck}$), intent(in) :: bb(ldbb,*) complex(${ck}$), intent(out) :: work(*), x(ldx,*) ! ===================================================================== ! Local Scalars logical(lk) :: update, upper, wantx integer(${ik}$) :: i, i0, i1, i2, inca, j, j1, j1t, j2, j2t, k, ka1, kb1, kbt, l, m, nr, & nrt, nx real(${ck}$) :: bii complex(${ck}$) :: ra, ra1, t ! Intrinsic Functions ! Executable Statements ! test the input parameters wantx = stdlib_lsame( vect, 'V' ) upper = stdlib_lsame( uplo, 'U' ) ka1 = ka + 1_${ik}$ kb1 = kb + 1_${ik}$ info = 0_${ik}$ if( .not.wantx .and. .not.stdlib_lsame( vect, 'N' ) ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ka<0_${ik}$ ) then info = -4_${ik}$ else if( kb<0_${ik}$ .or. kb>ka ) then info = -5_${ik}$ else if( ldabn-1 )go to 480 end if if( upper ) then ! transform a, working with the upper triangle if( update ) then ! form inv(s(i))**h * a * inv(s(i)) bii = real( bb( kb1, i ),KIND=${ck}$) ab( ka1, i ) = ( real( ab( ka1, i ),KIND=${ck}$) / bii ) / bii do j = i + 1, i1 ab( i-j+ka1, j ) = ab( i-j+ka1, j ) / bii end do do j = max( 1, i-ka ), i - 1 ab( j-i+ka1, i ) = ab( j-i+ka1, i ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -bb( j-i+kb1, i )*conjg( ab( k-i+ka1, & i ) ) -conjg( bb( k-i+kb1, i ) )*ab( j-i+ka1, i ) +real( ab( ka1, i ),& KIND=${ck}$)*bb( j-i+kb1, i )*conjg( bb( k-i+kb1, i ) ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( j-k+ka1, k ) = ab( j-k+ka1, k ) -conjg( bb( k-i+kb1, i ) )*ab( j-i+ka1,& i ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( k-j+ka1, j ) = ab( k-j+ka1, j ) -bb( k-i+kb1, i )*ab( i-j+ka1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_${ci}$dscal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_${ci}$gerc( n-m, kbt, -cone, x( m+1, i ), 1_${ik}$,bb( kb1-kbt, i )& , 1_${ik}$, x( m+1, i-kbt ),ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+ka1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_130: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i,i-k+ka+1) call stdlib${ii}$_${ci}$lartg( ab( k+1, i-k+ka ), ra1,rwork( i-k+ka-m ), work( i-k+ka-& m ), ra ) ! create nonzero element a(i-k,i-k+ka+1) outside the ! band and store it in work(i-k) t = -bb( kb1-k, i )*ra1 work( i-k ) = rwork( i-k+ka-m )*t -conjg( work( i-k+ka-m ) )*ab( 1_${ik}$, i-k+ka & ) ab( 1_${ik}$, i-k+ka ) = work( i-k+ka-m )*t +rwork( i-k+ka-m )*ab( 1_${ik}$, i-k+ka ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = rwork( j-m )*ab( 1_${ik}$, j+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$largv( nrt, ab( 1_${ik}$, j2t ), inca, work( j2t-m ), ka1,rwork(& j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_${ci}$lartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, & rwork( j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_${ci}$lar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & rwork( j2-m ),work( j2-m ), ka1 ) call stdlib${ii}$_${ci}$lacgv( nr, work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, rwork( j2-m ),work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_${ci}$rot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j-m ), & conjg( work( j-m ) ) ) end do end if end do loop_130 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt,i-kbt+ka+1) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kb1-kbt, i )*ra1 end if end if loop_170: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( l, j2-l+1 ), inca,ab( l+1, j2-l+1 ), & inca, rwork( j2-ka ),work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) rwork( j ) = rwork( j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j-ka,j+1) outside the band ! and store it in work(j) work( j ) = work( j )*ab( 1_${ik}$, j+1 ) ab( 1_${ik}$, j+1 ) = rwork( j )*ab( 1_${ik}$, j+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_${ci}$largv( nr, ab( 1_${ik}$, j2 ), inca, work( j2 ), ka1,rwork( j2 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_${ci}$lartv( nr, ab( ka1-l, j2 ), inca,ab( ka-l, j2+1 ), inca, & rwork( j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_${ci}$lar2v( nr, ab( ka1, j2 ), ab( ka1, j2+1 ),ab( ka, j2+1 ), inca, & rwork( j2 ),work( j2 ), ka1 ) call stdlib${ii}$_${ci}$lacgv( nr, work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, rwork( j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_${ci}$rot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j ), conjg( & work( j ) ) ) end do end if end do loop_210 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( l, j2+ka1-l ), inca,ab( l+1, j2+ka1-l & ), inca, rwork( j2-m ),work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, j2 + ka, -1 rwork( j-m ) = rwork( j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**h * a * inv(s(i)) bii = real( bb( 1_${ik}$, i ),KIND=${ck}$) ab( 1_${ik}$, i ) = ( real( ab( 1_${ik}$, i ),KIND=${ck}$) / bii ) / bii do j = i + 1, i1 ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do j = max( 1, i-ka ), i - 1 ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do k = i - kbt, i - 1 do j = i - kbt, k ab( k-j+1, j ) = ab( k-j+1, j ) -bb( i-j+1, j )*conjg( ab( i-k+1,k ) ) - & conjg( bb( i-k+1, k ) )*ab( i-j+1, j ) + real( ab( 1_${ik}$, i ),KIND=${ck}$)*bb( i-j+& 1_${ik}$, j )*conjg( bb( i-k+1,k ) ) end do do j = max( 1, i-ka ), i - kbt - 1 ab( k-j+1, j ) = ab( k-j+1, j ) -conjg( bb( i-k+1, k ) )*ab( i-j+1, j ) end do end do do j = i, i1 do k = max( j-ka, i-kbt ), i - 1 ab( j-k+1, k ) = ab( j-k+1, k ) -bb( i-k+1, k )*ab( j-i+1, i ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_${ci}$dscal( n-m, one / bii, x( m+1, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_${ci}$geru( n-m, kbt, -cone, x( m+1, i ), 1_${ik}$,bb( kbt+1, i-& kbt ), ldbb-1,x( m+1, i-kbt ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions down toward the bottom of the ! band loop_360: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i-k+ka1_${ik}$ ) then ! generate rotation to annihilate a(i-k+ka+1,i) call stdlib${ii}$_${ci}$lartg( ab( ka1-k, i ), ra1, rwork( i-k+ka-m ),work( i-k+ka-m )& , ra ) ! create nonzero element a(i-k+ka+1,i-k) outside the ! band and store it in work(i-k) t = -bb( k+1, i-k )*ra1 work( i-k ) = rwork( i-k+ka-m )*t -conjg( work( i-k+ka-m ) )*ab( ka1, i-k ) ab( ka1, i-k ) = work( i-k+ka-m )*t +rwork( i-k+ka-m )*ab( ka1, i-k ) ra1 = ra end if end if j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 if( update ) then j2t = max( j2, i+2*ka-k+1 ) else j2t = j2 end if nrt = ( n-j2t+ka ) / ka1 do j = j2t, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j-m) work( j-m ) = work( j-m )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = rwork( j-m )*ab( ka1, j-ka+1 ) end do ! generate rotations in 1st set to annihilate elements which ! have been created outside the band if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$largv( nrt, ab( ka1, j2t-ka ), inca, work( j2t-m ),ka1, & rwork( j2t-m ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_${ci}$lartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, rwork(& j2-m ),work( j2-m ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_${ci}$lar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, rwork( & j2-m ), work( j2-m ), ka1 ) call stdlib${ii}$_${ci}$lacgv( nr, work( j2-m ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, rwork( j2-m ),work( j2-m ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j2, j1, ka1 call stdlib${ii}$_${ci}$rot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j-m ), work(& j-m ) ) end do end if end do loop_360 if( update ) then if( i2<=n .and. kbt>0_${ik}$ ) then ! create nonzero element a(i-kbt+ka+1,i-kbt) outside the ! band and store it in work(i-kbt) work( i-kbt ) = -bb( kbt+1, i-kbt )*ra1 end if end if loop_400: do k = kb, 1, -1 if( update ) then j2 = i - k - 1_${ik}$ + max( 2_${ik}$, k-i0+1 )*ka1 else j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+1 )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( n-j2+ka+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( ka1-l+1, j2-ka ), inca,ab( ka1-l, j2-& ka+1 ), inca,rwork( j2-ka ), work( j2-ka ), ka1 ) end do nr = ( n-j2+ka ) / ka1 j1 = j2 + ( nr-1 )*ka1 do j = j1, j2, -ka1 work( j ) = work( j-ka ) rwork( j ) = rwork( j-ka ) end do do j = j2, j1, ka1 ! create nonzero element a(j+1,j-ka) outside the band ! and store it in work(j) work( j ) = work( j )*ab( ka1, j-ka+1 ) ab( ka1, j-ka+1 ) = rwork( j )*ab( ka1, j-ka+1 ) end do if( update ) then if( i-k0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_${ci}$largv( nr, ab( ka1, j2-ka ), inca, work( j2 ), ka1,rwork( j2 ), & ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_${ci}$lartv( nr, ab( l+1, j2-l ), inca,ab( l+2, j2-l ), inca, rwork(& j2 ),work( j2 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_${ci}$lar2v( nr, ab( 1_${ik}$, j2 ), ab( 1_${ik}$, j2+1 ), ab( 2_${ik}$, j2 ),inca, rwork( & j2 ), work( j2 ), ka1 ) call stdlib${ii}$_${ci}$lacgv( nr, work( j2 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, rwork( j2 ),work( j2 ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j2, j1, ka1 call stdlib${ii}$_${ci}$rot( n-m, x( m+1, j ), 1_${ik}$, x( m+1, j+1 ), 1_${ik}$,rwork( j ), work( & j ) ) end do end if end do loop_440 do k = 1, kb - 1 j2 = i - k - 1_${ik}$ + max( 1_${ik}$, k-i0+2 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( n-j2+l ) / ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( ka1-l+1, j2 ), inca,ab( ka1-l, j2+1 ),& inca, rwork( j2-m ),work( j2-m ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = n - 1, j2 + ka, -1 rwork( j-m ) = rwork( j-ka-m ) work( j-m ) = work( j-ka-m ) end do end if end if go to 10 480 continue ! **************************** phase 2 ***************************** ! the logical structure of this phase is: ! update = .true. ! do i = 1, m ! use s(i) to update a and create a new bulge ! apply rotations to push all bulges ka positions upward ! end do ! update = .false. ! do i = m - ka - 1, 2, -1 ! apply rotations to push all bulges ka positions upward ! end do ! to avoid duplicating code, the two loops are merged. update = .true. i = 0_${ik}$ 490 continue if( update ) then i = i + 1_${ik}$ kbt = min( kb, m-i ) i0 = i + 1_${ik}$ i1 = max( 1_${ik}$, i-ka ) i2 = i + kbt - ka1 if( i>m ) then update = .false. i = i - 1_${ik}$ i0 = m + 1_${ik}$ if( ka==0 )return go to 490 end if else i = i - ka if( i<2 )return end if if( i0_${ik}$ )call stdlib${ii}$_${ci}$geru( nx, kbt, -cone, x( 1_${ik}$, i ), 1_${ik}$,bb( kb, i+1 ), & ldbb-1, x( 1_${ik}$, i+1 ), ldx ) end if ! store a(i1,i) in ra1 for use in next loop over k ra1 = ab( i1-i+ka1, i ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_610: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_${ci}$largv( nrt, ab( 1_${ik}$, j1+ka ), inca, work( j1 ), ka1,rwork( & j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the left do l = 1, ka - 1 call stdlib${ii}$_${ci}$lartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca, & rwork( j1 ),work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_${ci}$lar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & rwork( j1 ), work( j1 ),ka1 ) call stdlib${ii}$_${ci}$lacgv( nr, work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& rwork( j1t ),work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_${ci}$rot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( j ), work( j ) ) end do end if end do loop_610 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt-ka-1,i+kbt) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kb1-kbt, i+kbt )*ra1 end if end if loop_650: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the right do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( l, j1t+ka ), inca,ab( l+1, j1t+ka-1 ),& inca,rwork( m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) rwork( m-kb+j ) = rwork( m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j-1,j+ka) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( 1_${ik}$, j+ka-1 ) ab( 1_${ik}$, j+ka-1 ) = rwork( m-kb+j )*ab( 1_${ik}$, j+ka-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_650 loop_690: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_${ci}$largv( nr, ab( 1_${ik}$, j1+ka ), inca, work( m-kb+j1 ),ka1, rwork( m-& kb+j1 ), ka1 ) ! apply rotations in 2nd set from the left do l = 1, ka - 1 call stdlib${ii}$_${ci}$lartv( nr, ab( ka1-l, j1+l ), inca,ab( ka-l, j1+l ), inca, & rwork( m-kb+j1 ),work( m-kb+j1 ), ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_${ci}$lar2v( nr, ab( ka1, j1 ), ab( ka1, j1-1 ),ab( ka, j1 ), inca, & rwork( m-kb+j1 ),work( m-kb+j1 ), ka1 ) call stdlib${ii}$_${ci}$lacgv( nr, work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the right do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& rwork( m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_${ci}$rot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( m-kb+j ), work( & m-kb+j ) ) end do end if end do loop_690 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the right do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( l, j1t ), inca,ab( l+1, j1t-1 ), inca,& rwork( j1t ),work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, i2 - ka rwork( j ) = rwork( j+ka ) work( j ) = work( j+ka ) end do end if else ! transform a, working with the lower triangle if( update ) then ! form inv(s(i))**h * a * inv(s(i)) bii = real( bb( 1_${ik}$, i ),KIND=${ck}$) ab( 1_${ik}$, i ) = ( real( ab( 1_${ik}$, i ),KIND=${ck}$) / bii ) / bii do j = i1, i - 1 ab( i-j+1, j ) = ab( i-j+1, j ) / bii end do do j = i + 1, min( n, i+ka ) ab( j-i+1, i ) = ab( j-i+1, i ) / bii end do do k = i + 1, i + kbt do j = k, i + kbt ab( j-k+1, k ) = ab( j-k+1, k ) -bb( j-i+1, i )*conjg( ab( k-i+1,i ) ) - & conjg( bb( k-i+1, i ) )*ab( j-i+1, i ) + real( ab( 1_${ik}$, i ),KIND=${ck}$)*bb( j-i+& 1_${ik}$, i )*conjg( bb( k-i+1,i ) ) end do do j = i + kbt + 1, min( n, i+ka ) ab( j-k+1, k ) = ab( j-k+1, k ) -conjg( bb( k-i+1, i ) )*ab( j-i+1, i ) end do end do do j = i1, i do k = i + 1, min( j+ka, i+kbt ) ab( k-j+1, j ) = ab( k-j+1, j ) -bb( k-i+1, i )*ab( i-j+1, j ) end do end do if( wantx ) then ! post-multiply x by inv(s(i)) call stdlib${ii}$_${ci}$dscal( nx, one / bii, x( 1_${ik}$, i ), 1_${ik}$ ) if( kbt>0_${ik}$ )call stdlib${ii}$_${ci}$gerc( nx, kbt, -cone, x( 1_${ik}$, i ), 1_${ik}$, bb( 2_${ik}$, i ),1_${ik}$, x( & 1_${ik}$, i+1 ), ldx ) end if ! store a(i,i1) in ra1 for use in next loop over k ra1 = ab( i-i1+1, i1 ) end if ! generate and apply vectors of rotations to chase all the ! existing bulges ka positions up toward the top of the band loop_840: do k = 1, kb - 1 if( update ) then ! determine the rotations which would annihilate the bulge ! which has in theory just been created if( i+k-ka1>0_${ik}$ .and. i+k0_${ik}$ )call stdlib${ii}$_${ci}$largv( nrt, ab( ka1, j1 ), inca, work( j1 ), ka1,rwork( & j1 ), ka1 ) if( nr>0_${ik}$ ) then ! apply rotations in 1st set from the right do l = 1, ka - 1 call stdlib${ii}$_${ci}$lartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, rwork( & j1 ), work( j1 ), ka1 ) end do ! apply rotations in 1st set from both sides to diagonal ! blocks call stdlib${ii}$_${ci}$lar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, rwork(& j1 ),work( j1 ), ka1 ) call stdlib${ii}$_${ci}$lacgv( nr, work( j1 ), ka1 ) end if ! start applying rotations in 1st set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,rwork( j1t ), work( j1t ), ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 1st set do j = j1, j2, ka1 call stdlib${ii}$_${ci}$rot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( j ), conjg( work(& j ) ) ) end do end if end do loop_840 if( update ) then if( i2>0_${ik}$ .and. kbt>0_${ik}$ ) then ! create nonzero element a(i+kbt,i+kbt-ka-1) outside the ! band and store it in work(m-kb+i+kbt) work( m-kb+i+kbt ) = -bb( kbt+1, i )*ra1 end if end if loop_880: do k = kb, 1, -1 if( update ) then j2 = i + k + 1_${ik}$ - max( 2_${ik}$, k+i0-m )*ka1 else j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 end if ! finish applying rotations in 2nd set from the left do l = kb - k, 1, -1 nrt = ( j2+ka+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( ka1-l+1, j1t+l-1 ), inca,ab( ka1-l, & j1t+l-1 ), inca,rwork( m-kb+j1t+ka ),work( m-kb+j1t+ka ), ka1 ) end do nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 do j = j1, j2, ka1 work( m-kb+j ) = work( m-kb+j+ka ) rwork( m-kb+j ) = rwork( m-kb+j+ka ) end do do j = j1, j2, ka1 ! create nonzero element a(j+ka,j-1) outside the band ! and store it in work(m-kb+j) work( m-kb+j ) = work( m-kb+j )*ab( ka1, j-1 ) ab( ka1, j-1 ) = rwork( m-kb+j )*ab( ka1, j-1 ) end do if( update ) then if( i+k>ka1 .and. k<=kbt )work( m-kb+i+k-ka ) = work( m-kb+i+k ) end if end do loop_880 loop_920: do k = kb, 1, -1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m )*ka1 nr = ( j2+ka-1 ) / ka1 j1 = j2 - ( nr-1 )*ka1 if( nr>0_${ik}$ ) then ! generate rotations in 2nd set to annihilate elements ! which have been created outside the band call stdlib${ii}$_${ci}$largv( nr, ab( ka1, j1 ), inca, work( m-kb+j1 ),ka1, rwork( m-kb+& j1 ), ka1 ) ! apply rotations in 2nd set from the right do l = 1, ka - 1 call stdlib${ii}$_${ci}$lartv( nr, ab( l+1, j1 ), inca, ab( l+2, j1-1 ),inca, rwork( & m-kb+j1 ), work( m-kb+j1 ),ka1 ) end do ! apply rotations in 2nd set from both sides to diagonal ! blocks call stdlib${ii}$_${ci}$lar2v( nr, ab( 1_${ik}$, j1 ), ab( 1_${ik}$, j1-1 ),ab( 2_${ik}$, j1-1 ), inca, rwork(& m-kb+j1 ),work( m-kb+j1 ), ka1 ) call stdlib${ii}$_${ci}$lacgv( nr, work( m-kb+j1 ), ka1 ) end if ! start applying rotations in 2nd set from the left do l = ka - 1, kb - k + 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,rwork( m-kb+j1t ), work( m-kb+j1t ),ka1 ) end do if( wantx ) then ! post-multiply x by product of rotations in 2nd set do j = j1, j2, ka1 call stdlib${ii}$_${ci}$rot( nx, x( 1_${ik}$, j ), 1_${ik}$, x( 1_${ik}$, j-1 ), 1_${ik}$,rwork( m-kb+j ), conjg( & work( m-kb+j ) ) ) end do end if end do loop_920 do k = 1, kb - 1 j2 = i + k + 1_${ik}$ - max( 1_${ik}$, k+i0-m+1 )*ka1 ! finish applying rotations in 1st set from the left do l = kb - k, 1, -1 nrt = ( j2+l-1 ) / ka1 j1t = j2 - ( nrt-1 )*ka1 if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( ka1-l+1, j1t-ka1+l ), inca,ab( ka1-l, & j1t-ka1+l ), inca,rwork( j1t ), work( j1t ), ka1 ) end do end do if( kb>1_${ik}$ ) then do j = 2, i2 - ka rwork( j ) = rwork( j+ka ) work( j ) = work( j+ka ) end do end if end if go to 490 end subroutine stdlib${ii}$_${ci}$hbgst #:endif #:endfor pure module subroutine stdlib${ii}$_spbstf( uplo, n, kd, ab, ldab, info ) !! SPBSTF computes a split Cholesky factorization of a real !! symmetric positive definite band matrix A. !! This routine is designed to be used in conjunction with SSBGST. !! The factorization has the form A = S**T*S where S is a band matrix !! of the same bandwidth as A and the following structure: !! S = ( U ) !! ( M L ) !! where U is upper triangular of order m = (n+kd)/2, and L is lower !! triangular of order n-m. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments real(sp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, km, m real(sp) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_sscal( km, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_ssyr( 'UPPER', km, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) end if end do else ! factorize a(m+1:n,m+1:n) as l**t*l, and update a(1:m,1:m). do j = n, m + 1, -1 ! compute s(j,j) and test for non-positive-definiteness. ajj = ab( 1_${ik}$, j ) if( ajj<=zero )go to 50 ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( j-1, kd ) ! compute elements j-km:j-1 of the j-th row and update the ! trailing submatrix within the band. call stdlib${ii}$_sscal( km, one / ajj, ab( km+1, j-km ), kld ) call stdlib${ii}$_ssyr( 'LOWER', km, -one, ab( km+1, j-km ), kld,ab( 1_${ik}$, j-km ), kld ) end do ! factorize the updated submatrix a(1:m,1:m) as u**t*u. do j = 1, m ! compute s(j,j) and test for non-positive-definiteness. ajj = ab( 1_${ik}$, j ) if( ajj<=zero )go to 50 ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( kd, m-j ) ! compute elements j+1:j+km of the j-th column and update the ! trailing submatrix within the band. if( km>0_${ik}$ ) then call stdlib${ii}$_sscal( km, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_ssyr( 'LOWER', km, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 50 continue info = j return end subroutine stdlib${ii}$_spbstf pure module subroutine stdlib${ii}$_dpbstf( uplo, n, kd, ab, ldab, info ) !! DPBSTF computes a split Cholesky factorization of a real !! symmetric positive definite band matrix A. !! This routine is designed to be used in conjunction with DSBGST. !! The factorization has the form A = S**T*S where S is a band matrix !! of the same bandwidth as A and the following structure: !! S = ( U ) !! ( M L ) !! where U is upper triangular of order m = (n+kd)/2, and L is lower !! triangular of order n-m. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments real(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, km, m real(dp) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_dscal( km, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_dsyr( 'UPPER', km, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) end if end do else ! factorize a(m+1:n,m+1:n) as l**t*l, and update a(1:m,1:m). do j = n, m + 1, -1 ! compute s(j,j) and test for non-positive-definiteness. ajj = ab( 1_${ik}$, j ) if( ajj<=zero )go to 50 ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( j-1, kd ) ! compute elements j-km:j-1 of the j-th row and update the ! trailing submatrix within the band. call stdlib${ii}$_dscal( km, one / ajj, ab( km+1, j-km ), kld ) call stdlib${ii}$_dsyr( 'LOWER', km, -one, ab( km+1, j-km ), kld,ab( 1_${ik}$, j-km ), kld ) end do ! factorize the updated submatrix a(1:m,1:m) as u**t*u. do j = 1, m ! compute s(j,j) and test for non-positive-definiteness. ajj = ab( 1_${ik}$, j ) if( ajj<=zero )go to 50 ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( kd, m-j ) ! compute elements j+1:j+km of the j-th column and update the ! trailing submatrix within the band. if( km>0_${ik}$ ) then call stdlib${ii}$_dscal( km, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_dsyr( 'LOWER', km, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 50 continue info = j return end subroutine stdlib${ii}$_dpbstf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$pbstf( uplo, n, kd, ab, ldab, info ) !! DPBSTF: computes a split Cholesky factorization of a real !! symmetric positive definite band matrix A. !! This routine is designed to be used in conjunction with DSBGST. !! The factorization has the form A = S**T*S where S is a band matrix !! of the same bandwidth as A and the following structure: !! S = ( U ) !! ( M L ) !! where U is upper triangular of order m = (n+kd)/2, and L is lower !! triangular of order n-m. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments real(${rk}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, km, m real(${rk}$) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_${ri}$scal( km, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_${ri}$syr( 'UPPER', km, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) end if end do else ! factorize a(m+1:n,m+1:n) as l**t*l, and update a(1:m,1:m). do j = n, m + 1, -1 ! compute s(j,j) and test for non-positive-definiteness. ajj = ab( 1_${ik}$, j ) if( ajj<=zero )go to 50 ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( j-1, kd ) ! compute elements j-km:j-1 of the j-th row and update the ! trailing submatrix within the band. call stdlib${ii}$_${ri}$scal( km, one / ajj, ab( km+1, j-km ), kld ) call stdlib${ii}$_${ri}$syr( 'LOWER', km, -one, ab( km+1, j-km ), kld,ab( 1_${ik}$, j-km ), kld ) end do ! factorize the updated submatrix a(1:m,1:m) as u**t*u. do j = 1, m ! compute s(j,j) and test for non-positive-definiteness. ajj = ab( 1_${ik}$, j ) if( ajj<=zero )go to 50 ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( kd, m-j ) ! compute elements j+1:j+km of the j-th column and update the ! trailing submatrix within the band. if( km>0_${ik}$ ) then call stdlib${ii}$_${ri}$scal( km, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ri}$syr( 'LOWER', km, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 50 continue info = j return end subroutine stdlib${ii}$_${ri}$pbstf #:endif #:endfor pure module subroutine stdlib${ii}$_cpbstf( uplo, n, kd, ab, ldab, info ) !! CPBSTF computes a split Cholesky factorization of a complex !! Hermitian positive definite band matrix A. !! This routine is designed to be used in conjunction with CHBGST. !! The factorization has the form A = S**H*S where S is a band matrix !! of the same bandwidth as A and the following structure: !! S = ( U ) !! ( M L ) !! where U is upper triangular of order m = (n+kd)/2, and L is lower !! triangular of order n-m. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments complex(sp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, km, m real(sp) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_csscal( km, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_clacgv( km, ab( kd, j+1 ), kld ) call stdlib${ii}$_cher( 'UPPER', km, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) call stdlib${ii}$_clacgv( km, ab( kd, j+1 ), kld ) end if end do else ! factorize a(m+1:n,m+1:n) as l**h*l, and update a(1:m,1:m). do j = n, m + 1, -1 ! compute s(j,j) and test for non-positive-definiteness. ajj = real( ab( 1_${ik}$, j ),KIND=sp) if( ajj<=zero ) then ab( 1_${ik}$, j ) = ajj go to 50 end if ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( j-1, kd ) ! compute elements j-km:j-1 of the j-th row and update the ! trailing submatrix within the band. call stdlib${ii}$_csscal( km, one / ajj, ab( km+1, j-km ), kld ) call stdlib${ii}$_clacgv( km, ab( km+1, j-km ), kld ) call stdlib${ii}$_cher( 'LOWER', km, -one, ab( km+1, j-km ), kld,ab( 1_${ik}$, j-km ), kld ) call stdlib${ii}$_clacgv( km, ab( km+1, j-km ), kld ) end do ! factorize the updated submatrix a(1:m,1:m) as u**h*u. do j = 1, m ! compute s(j,j) and test for non-positive-definiteness. ajj = real( ab( 1_${ik}$, j ),KIND=sp) if( ajj<=zero ) then ab( 1_${ik}$, j ) = ajj go to 50 end if ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( kd, m-j ) ! compute elements j+1:j+km of the j-th column and update the ! trailing submatrix within the band. if( km>0_${ik}$ ) then call stdlib${ii}$_csscal( km, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_cher( 'LOWER', km, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 50 continue info = j return end subroutine stdlib${ii}$_cpbstf pure module subroutine stdlib${ii}$_zpbstf( uplo, n, kd, ab, ldab, info ) !! ZPBSTF computes a split Cholesky factorization of a complex !! Hermitian positive definite band matrix A. !! This routine is designed to be used in conjunction with ZHBGST. !! The factorization has the form A = S**H*S where S is a band matrix !! of the same bandwidth as A and the following structure: !! S = ( U ) !! ( M L ) !! where U is upper triangular of order m = (n+kd)/2, and L is lower !! triangular of order n-m. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments complex(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, km, m real(dp) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_zdscal( km, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_zlacgv( km, ab( kd, j+1 ), kld ) call stdlib${ii}$_zher( 'UPPER', km, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) call stdlib${ii}$_zlacgv( km, ab( kd, j+1 ), kld ) end if end do else ! factorize a(m+1:n,m+1:n) as l**h*l, and update a(1:m,1:m). do j = n, m + 1, -1 ! compute s(j,j) and test for non-positive-definiteness. ajj = real( ab( 1_${ik}$, j ),KIND=dp) if( ajj<=zero ) then ab( 1_${ik}$, j ) = ajj go to 50 end if ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( j-1, kd ) ! compute elements j-km:j-1 of the j-th row and update the ! trailing submatrix within the band. call stdlib${ii}$_zdscal( km, one / ajj, ab( km+1, j-km ), kld ) call stdlib${ii}$_zlacgv( km, ab( km+1, j-km ), kld ) call stdlib${ii}$_zher( 'LOWER', km, -one, ab( km+1, j-km ), kld,ab( 1_${ik}$, j-km ), kld ) call stdlib${ii}$_zlacgv( km, ab( km+1, j-km ), kld ) end do ! factorize the updated submatrix a(1:m,1:m) as u**h*u. do j = 1, m ! compute s(j,j) and test for non-positive-definiteness. ajj = real( ab( 1_${ik}$, j ),KIND=dp) if( ajj<=zero ) then ab( 1_${ik}$, j ) = ajj go to 50 end if ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( kd, m-j ) ! compute elements j+1:j+km of the j-th column and update the ! trailing submatrix within the band. if( km>0_${ik}$ ) then call stdlib${ii}$_zdscal( km, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_zher( 'LOWER', km, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 50 continue info = j return end subroutine stdlib${ii}$_zpbstf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$pbstf( uplo, n, kd, ab, ldab, info ) !! ZPBSTF: computes a split Cholesky factorization of a complex !! Hermitian positive definite band matrix A. !! This routine is designed to be used in conjunction with ZHBGST. !! The factorization has the form A = S**H*S where S is a band matrix !! of the same bandwidth as A and the following structure: !! S = ( U ) !! ( M L ) !! where U is upper triangular of order m = (n+kd)/2, and L is lower !! triangular of order n-m. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments complex(${ck}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, km, m real(${ck}$) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_${ci}$dscal( km, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_${ci}$lacgv( km, ab( kd, j+1 ), kld ) call stdlib${ii}$_${ci}$her( 'UPPER', km, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) call stdlib${ii}$_${ci}$lacgv( km, ab( kd, j+1 ), kld ) end if end do else ! factorize a(m+1:n,m+1:n) as l**h*l, and update a(1:m,1:m). do j = n, m + 1, -1 ! compute s(j,j) and test for non-positive-definiteness. ajj = real( ab( 1_${ik}$, j ),KIND=${ck}$) if( ajj<=zero ) then ab( 1_${ik}$, j ) = ajj go to 50 end if ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( j-1, kd ) ! compute elements j-km:j-1 of the j-th row and update the ! trailing submatrix within the band. call stdlib${ii}$_${ci}$dscal( km, one / ajj, ab( km+1, j-km ), kld ) call stdlib${ii}$_${ci}$lacgv( km, ab( km+1, j-km ), kld ) call stdlib${ii}$_${ci}$her( 'LOWER', km, -one, ab( km+1, j-km ), kld,ab( 1_${ik}$, j-km ), kld ) call stdlib${ii}$_${ci}$lacgv( km, ab( km+1, j-km ), kld ) end do ! factorize the updated submatrix a(1:m,1:m) as u**h*u. do j = 1, m ! compute s(j,j) and test for non-positive-definiteness. ajj = real( ab( 1_${ik}$, j ),KIND=${ck}$) if( ajj<=zero ) then ab( 1_${ik}$, j ) = ajj go to 50 end if ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj km = min( kd, m-j ) ! compute elements j+1:j+km of the j-th column and update the ! trailing submatrix within the band. if( km>0_${ik}$ ) then call stdlib${ii}$_${ci}$dscal( km, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$her( 'LOWER', km, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 50 continue info = j return end subroutine stdlib${ii}$_${ci}$pbstf #:endif #:endfor pure module subroutine stdlib${ii}$_slag2( a, lda, b, ldb, safmin, scale1, scale2, wr1,wr2, wi ) !! SLAG2 computes the eigenvalues of a 2 x 2 generalized eigenvalue !! problem A - w B, with scaling as necessary to avoid over-/underflow. !! The scaling factor "s" results in a modified eigenvalue equation !! s A - w B !! where s is a non-negative scaling factor chosen so that w, w B, !! and s A do not overflow and, if possible, do not underflow, either. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldb real(sp), intent(in) :: safmin real(sp), intent(out) :: scale1, scale2, wi, wr1, wr2 ! Array Arguments real(sp), intent(in) :: a(lda,*), b(ldb,*) ! ===================================================================== ! Parameters real(sp), parameter :: fuzzy1 = one+1.0e-5_sp ! Local Scalars real(sp) :: a11, a12, a21, a22, abi22, anorm, as11, as12, as22, ascale, b11, b12, b22, & binv11, binv22, bmin, bnorm, bscale, bsize, c1, c2, c3, c4, c5, diff, discr, pp, qq, r,& rtmax, rtmin, s1, s2, safmax, shift, ss, sum, wabs, wbig, wdet, wscale, wsize, & wsmall ! Intrinsic Functions ! Executable Statements rtmin = sqrt( safmin ) rtmax = one / rtmin safmax = one / safmin ! scale a anorm = max( abs( a( 1_${ik}$, 1_${ik}$ ) )+abs( a( 2_${ik}$, 1_${ik}$ ) ),abs( a( 1_${ik}$, 2_${ik}$ ) )+abs( a( 2_${ik}$, 2_${ik}$ ) ), & safmin ) ascale = one / anorm a11 = ascale*a( 1_${ik}$, 1_${ik}$ ) a21 = ascale*a( 2_${ik}$, 1_${ik}$ ) a12 = ascale*a( 1_${ik}$, 2_${ik}$ ) a22 = ascale*a( 2_${ik}$, 2_${ik}$ ) ! perturb b if necessary to insure non-singularity b11 = b( 1_${ik}$, 1_${ik}$ ) b12 = b( 1_${ik}$, 2_${ik}$ ) b22 = b( 2_${ik}$, 2_${ik}$ ) bmin = rtmin*max( abs( b11 ), abs( b12 ), abs( b22 ), rtmin ) if( abs( b11 )=one ) then discr = ( rtmin*pp )**2_${ik}$ + qq*safmin r = sqrt( abs( discr ) )*rtmax else if( pp**2_${ik}$+abs( qq )<=safmin ) then discr = ( rtmax*pp )**2_${ik}$ + qq*safmax r = sqrt( abs( discr ) )*rtmin else discr = pp**2_${ik}$ + qq r = sqrt( abs( discr ) ) end if end if ! note: the test of r in the following if is to cover the case when ! discr is small and negative and is flushed to zero during ! the calculation of r. on machines which have a consistent ! flush-to-zero threshold and handle numbers above that ! threshold correctly, it would not be necessary. if( discr>=zero .or. r==zero ) then sum = pp + sign( r, pp ) diff = pp - sign( r, pp ) wbig = shift + sum ! compute smaller eigenvalue wsmall = shift + diff if( half*abs( wbig )>max( abs( wsmall ), safmin ) ) then wdet = ( a11*a22-a12*a21 )*( binv11*binv22 ) wsmall = wdet / wbig end if ! choose (real) eigenvalue closest to 2,2 element of a*b**(-1) ! for wr1. if( pp>abi22 ) then wr1 = min( wbig, wsmall ) wr2 = max( wbig, wsmall ) else wr1 = max( wbig, wsmall ) wr2 = min( wbig, wsmall ) end if wi = zero else ! complex eigenvalues wr1 = shift + pp wr2 = wr1 wi = r end if ! further scaling to avoid underflow and overflow in computing ! scale1 and overflow in computing w*b. ! this scale factor (wscale) is bounded from above using c1 and c2, ! and from below using c3 and c4. ! c1 implements the condition s a must never overflow. ! c2 implements the condition w b must never overflow. ! c3, with c2, ! implement the condition that s a - w b must never overflow. ! c4 implements the condition s should not underflow. ! c5 implements the condition max(s,|w|) should be at least 2. c1 = bsize*( safmin*max( one, ascale ) ) c2 = safmin*max( one, bnorm ) c3 = bsize*safmin if( ascale<=one .and. bsize<=one ) then c4 = min( one, ( ascale / safmin )*bsize ) else c4 = one end if if( ascale<=one .or. bsize<=one ) then c5 = min( one, ascale*bsize ) else c5 = one end if ! scale first eigenvalue wabs = abs( wr1 ) + abs( wi ) wsize = max( safmin, c1, fuzzy1*( wabs*c2+c3 ),min( c4, half*max( wabs, c5 ) ) ) if( wsize/=one ) then wscale = one / wsize if( wsize>one ) then scale1 = ( max( ascale, bsize )*wscale )*min( ascale, bsize ) else scale1 = ( min( ascale, bsize )*wscale )*max( ascale, bsize ) end if wr1 = wr1*wscale if( wi/=zero ) then wi = wi*wscale wr2 = wr1 scale2 = scale1 end if else scale1 = ascale*bsize scale2 = scale1 end if ! scale second eigenvalue (if real) if( wi==zero ) then wsize = max( safmin, c1, fuzzy1*( abs( wr2 )*c2+c3 ),min( c4, half*max( abs( wr2 ), & c5 ) ) ) if( wsize/=one ) then wscale = one / wsize if( wsize>one ) then scale2 = ( max( ascale, bsize )*wscale )*min( ascale, bsize ) else scale2 = ( min( ascale, bsize )*wscale )*max( ascale, bsize ) end if wr2 = wr2*wscale else scale2 = ascale*bsize end if end if return end subroutine stdlib${ii}$_slag2 pure module subroutine stdlib${ii}$_dlag2( a, lda, b, ldb, safmin, scale1, scale2, wr1,wr2, wi ) !! DLAG2 computes the eigenvalues of a 2 x 2 generalized eigenvalue !! problem A - w B, with scaling as necessary to avoid over-/underflow. !! The scaling factor "s" results in a modified eigenvalue equation !! s A - w B !! where s is a non-negative scaling factor chosen so that w, w B, !! and s A do not overflow and, if possible, do not underflow, either. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldb real(dp), intent(in) :: safmin real(dp), intent(out) :: scale1, scale2, wi, wr1, wr2 ! Array Arguments real(dp), intent(in) :: a(lda,*), b(ldb,*) ! ===================================================================== ! Parameters real(dp), parameter :: fuzzy1 = one+1.0e-5_dp ! Local Scalars real(dp) :: a11, a12, a21, a22, abi22, anorm, as11, as12, as22, ascale, b11, b12, b22, & binv11, binv22, bmin, bnorm, bscale, bsize, c1, c2, c3, c4, c5, diff, discr, pp, qq, r,& rtmax, rtmin, s1, s2, safmax, shift, ss, sum, wabs, wbig, wdet, wscale, wsize, & wsmall ! Intrinsic Functions ! Executable Statements rtmin = sqrt( safmin ) rtmax = one / rtmin safmax = one / safmin ! scale a anorm = max( abs( a( 1_${ik}$, 1_${ik}$ ) )+abs( a( 2_${ik}$, 1_${ik}$ ) ),abs( a( 1_${ik}$, 2_${ik}$ ) )+abs( a( 2_${ik}$, 2_${ik}$ ) ), & safmin ) ascale = one / anorm a11 = ascale*a( 1_${ik}$, 1_${ik}$ ) a21 = ascale*a( 2_${ik}$, 1_${ik}$ ) a12 = ascale*a( 1_${ik}$, 2_${ik}$ ) a22 = ascale*a( 2_${ik}$, 2_${ik}$ ) ! perturb b if necessary to insure non-singularity b11 = b( 1_${ik}$, 1_${ik}$ ) b12 = b( 1_${ik}$, 2_${ik}$ ) b22 = b( 2_${ik}$, 2_${ik}$ ) bmin = rtmin*max( abs( b11 ), abs( b12 ), abs( b22 ), rtmin ) if( abs( b11 )=one ) then discr = ( rtmin*pp )**2_${ik}$ + qq*safmin r = sqrt( abs( discr ) )*rtmax else if( pp**2_${ik}$+abs( qq )<=safmin ) then discr = ( rtmax*pp )**2_${ik}$ + qq*safmax r = sqrt( abs( discr ) )*rtmin else discr = pp**2_${ik}$ + qq r = sqrt( abs( discr ) ) end if end if ! note: the test of r in the following if is to cover the case when ! discr is small and negative and is flushed to zero during ! the calculation of r. on machines which have a consistent ! flush-to-zero threshold and handle numbers above that ! threshold correctly, it would not be necessary. if( discr>=zero .or. r==zero ) then sum = pp + sign( r, pp ) diff = pp - sign( r, pp ) wbig = shift + sum ! compute smaller eigenvalue wsmall = shift + diff if( half*abs( wbig )>max( abs( wsmall ), safmin ) ) then wdet = ( a11*a22-a12*a21 )*( binv11*binv22 ) wsmall = wdet / wbig end if ! choose (real) eigenvalue closest to 2,2 element of a*b**(-1) ! for wr1. if( pp>abi22 ) then wr1 = min( wbig, wsmall ) wr2 = max( wbig, wsmall ) else wr1 = max( wbig, wsmall ) wr2 = min( wbig, wsmall ) end if wi = zero else ! complex eigenvalues wr1 = shift + pp wr2 = wr1 wi = r end if ! further scaling to avoid underflow and overflow in computing ! scale1 and overflow in computing w*b. ! this scale factor (wscale) is bounded from above using c1 and c2, ! and from below using c3 and c4. ! c1 implements the condition s a must never overflow. ! c2 implements the condition w b must never overflow. ! c3, with c2, ! implement the condition that s a - w b must never overflow. ! c4 implements the condition s should not underflow. ! c5 implements the condition max(s,|w|) should be at least 2. c1 = bsize*( safmin*max( one, ascale ) ) c2 = safmin*max( one, bnorm ) c3 = bsize*safmin if( ascale<=one .and. bsize<=one ) then c4 = min( one, ( ascale / safmin )*bsize ) else c4 = one end if if( ascale<=one .or. bsize<=one ) then c5 = min( one, ascale*bsize ) else c5 = one end if ! scale first eigenvalue wabs = abs( wr1 ) + abs( wi ) wsize = max( safmin, c1, fuzzy1*( wabs*c2+c3 ),min( c4, half*max( wabs, c5 ) ) ) if( wsize/=one ) then wscale = one / wsize if( wsize>one ) then scale1 = ( max( ascale, bsize )*wscale )*min( ascale, bsize ) else scale1 = ( min( ascale, bsize )*wscale )*max( ascale, bsize ) end if wr1 = wr1*wscale if( wi/=zero ) then wi = wi*wscale wr2 = wr1 scale2 = scale1 end if else scale1 = ascale*bsize scale2 = scale1 end if ! scale second eigenvalue (if real) if( wi==zero ) then wsize = max( safmin, c1, fuzzy1*( abs( wr2 )*c2+c3 ),min( c4, half*max( abs( wr2 ), & c5 ) ) ) if( wsize/=one ) then wscale = one / wsize if( wsize>one ) then scale2 = ( max( ascale, bsize )*wscale )*min( ascale, bsize ) else scale2 = ( min( ascale, bsize )*wscale )*max( ascale, bsize ) end if wr2 = wr2*wscale else scale2 = ascale*bsize end if end if return end subroutine stdlib${ii}$_dlag2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lag2( a, lda, b, ldb, safmin, scale1, scale2, wr1,wr2, wi ) !! DLAG2: computes the eigenvalues of a 2 x 2 generalized eigenvalue !! problem A - w B, with scaling as necessary to avoid over-/underflow. !! The scaling factor "s" results in a modified eigenvalue equation !! s A - w B !! where s is a non-negative scaling factor chosen so that w, w B, !! and s A do not overflow and, if possible, do not underflow, either. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldb real(${rk}$), intent(in) :: safmin real(${rk}$), intent(out) :: scale1, scale2, wi, wr1, wr2 ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), b(ldb,*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: fuzzy1 = one+1.0e-5_${rk}$ ! Local Scalars real(${rk}$) :: a11, a12, a21, a22, abi22, anorm, as11, as12, as22, ascale, b11, b12, b22, & binv11, binv22, bmin, bnorm, bscale, bsize, c1, c2, c3, c4, c5, diff, discr, pp, qq, r,& rtmax, rtmin, s1, s2, safmax, shift, ss, sum, wabs, wbig, wdet, wscale, wsize, & wsmall ! Intrinsic Functions ! Executable Statements rtmin = sqrt( safmin ) rtmax = one / rtmin safmax = one / safmin ! scale a anorm = max( abs( a( 1_${ik}$, 1_${ik}$ ) )+abs( a( 2_${ik}$, 1_${ik}$ ) ),abs( a( 1_${ik}$, 2_${ik}$ ) )+abs( a( 2_${ik}$, 2_${ik}$ ) ), & safmin ) ascale = one / anorm a11 = ascale*a( 1_${ik}$, 1_${ik}$ ) a21 = ascale*a( 2_${ik}$, 1_${ik}$ ) a12 = ascale*a( 1_${ik}$, 2_${ik}$ ) a22 = ascale*a( 2_${ik}$, 2_${ik}$ ) ! perturb b if necessary to insure non-singularity b11 = b( 1_${ik}$, 1_${ik}$ ) b12 = b( 1_${ik}$, 2_${ik}$ ) b22 = b( 2_${ik}$, 2_${ik}$ ) bmin = rtmin*max( abs( b11 ), abs( b12 ), abs( b22 ), rtmin ) if( abs( b11 )=one ) then discr = ( rtmin*pp )**2_${ik}$ + qq*safmin r = sqrt( abs( discr ) )*rtmax else if( pp**2_${ik}$+abs( qq )<=safmin ) then discr = ( rtmax*pp )**2_${ik}$ + qq*safmax r = sqrt( abs( discr ) )*rtmin else discr = pp**2_${ik}$ + qq r = sqrt( abs( discr ) ) end if end if ! note: the test of r in the following if is to cover the case when ! discr is small and negative and is flushed to zero during ! the calculation of r. on machines which have a consistent ! flush-to-zero threshold and handle numbers above that ! threshold correctly, it would not be necessary. if( discr>=zero .or. r==zero ) then sum = pp + sign( r, pp ) diff = pp - sign( r, pp ) wbig = shift + sum ! compute smaller eigenvalue wsmall = shift + diff if( half*abs( wbig )>max( abs( wsmall ), safmin ) ) then wdet = ( a11*a22-a12*a21 )*( binv11*binv22 ) wsmall = wdet / wbig end if ! choose (real) eigenvalue closest to 2,2 element of a*b**(-1) ! for wr1. if( pp>abi22 ) then wr1 = min( wbig, wsmall ) wr2 = max( wbig, wsmall ) else wr1 = max( wbig, wsmall ) wr2 = min( wbig, wsmall ) end if wi = zero else ! complex eigenvalues wr1 = shift + pp wr2 = wr1 wi = r end if ! further scaling to avoid underflow and overflow in computing ! scale1 and overflow in computing w*b. ! this scale factor (wscale) is bounded from above using c1 and c2, ! and from below using c3 and c4. ! c1 implements the condition s a must never overflow. ! c2 implements the condition w b must never overflow. ! c3, with c2, ! implement the condition that s a - w b must never overflow. ! c4 implements the condition s should not underflow. ! c5 implements the condition max(s,|w|) should be at least 2. c1 = bsize*( safmin*max( one, ascale ) ) c2 = safmin*max( one, bnorm ) c3 = bsize*safmin if( ascale<=one .and. bsize<=one ) then c4 = min( one, ( ascale / safmin )*bsize ) else c4 = one end if if( ascale<=one .or. bsize<=one ) then c5 = min( one, ascale*bsize ) else c5 = one end if ! scale first eigenvalue wabs = abs( wr1 ) + abs( wi ) wsize = max( safmin, c1, fuzzy1*( wabs*c2+c3 ),min( c4, half*max( wabs, c5 ) ) ) if( wsize/=one ) then wscale = one / wsize if( wsize>one ) then scale1 = ( max( ascale, bsize )*wscale )*min( ascale, bsize ) else scale1 = ( min( ascale, bsize )*wscale )*max( ascale, bsize ) end if wr1 = wr1*wscale if( wi/=zero ) then wi = wi*wscale wr2 = wr1 scale2 = scale1 end if else scale1 = ascale*bsize scale2 = scale1 end if ! scale second eigenvalue (if real) if( wi==zero ) then wsize = max( safmin, c1, fuzzy1*( abs( wr2 )*c2+c3 ),min( c4, half*max( abs( wr2 ), & c5 ) ) ) if( wsize/=one ) then wscale = one / wsize if( wsize>one ) then scale2 = ( max( ascale, bsize )*wscale )*min( ascale, bsize ) else scale2 = ( min( ascale, bsize )*wscale )*max( ascale, bsize ) end if wr2 = wr2*wscale else scale2 = ascale*bsize end if end if return end subroutine stdlib${ii}$_${ri}$lag2 #:endif #:endfor #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_dlag2${ri}$( m, n, sa, ldsa, a, lda, info ) !! DLAG2Q converts a DOUBLE PRECISION matrix, SA, to an EXTENDED !! PRECISION matrix, A. !! Note that while it is possible to overflow while converting !! from double to single, it is not possible to overflow when !! converting from single to double. !! This is an auxiliary routine so there is no argument checking. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldsa, m, n ! Array Arguments real(dp), intent(in) :: sa(ldsa,*) real(${rk}$), intent(out) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j ! Executable Statements info = 0_${ik}$ do j = 1, n do i = 1, m a( i, j ) = sa( i, j ) end do end do return end subroutine stdlib${ii}$_dlag2${ri}$ #:endif #:endfor pure module subroutine stdlib${ii}$_sorm22( side, trans, m, n, n1, n2, q, ldq, c, ldc,work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans integer(${ik}$), intent(in) :: m, n, n1, n2, ldq, ldc, lwork integer(${ik}$), intent(out) :: info ! Array Arguments real(sp), intent(in) :: q(ldq,*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: left, lquery, notran integer(${ik}$) :: i, ldwork, len, lwkopt, nb, nq, nw ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) ! nq is the order of q; ! nw is the minimum dimension of work. if( left ) then nq = m else nq = n end if nw = nq if( n1==0_${ik}$ .or. n2==0_${ik}$ ) nw = 1_${ik}$ if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.stdlib_lsame( trans, 'N' ) .and. .not.stdlib_lsame( trans, 'T' ) )& then info = -2_${ik}$ else if( m<0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( n1<0_${ik}$ .or. n1+n2/=nq ) then info = -5_${ik}$ else if( n2<0_${ik}$ ) then info = -6_${ik}$ else if( ldq=d( i+1 ) end do if( sing .and. k>0_${ik}$ ) then if( incr )incr = incr .and. zero<=d( 1_${ik}$ ) if( decr )decr = decr .and. d( k )>=zero end if if( .not.( incr .or. decr ) )info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SDISNA', -info ) return end if ! quick return if possible if( k==0 )return ! compute reciprocal condition numbers if( k==1_${ik}$ ) then sep( 1_${ik}$ ) = stdlib${ii}$_slamch( 'O' ) else oldgap = abs( d( 2_${ik}$ )-d( 1_${ik}$ ) ) sep( 1_${ik}$ ) = oldgap do i = 2, k - 1 newgap = abs( d( i+1 )-d( i ) ) sep( i ) = min( oldgap, newgap ) oldgap = newgap end do sep( k ) = oldgap end if if( sing ) then if( ( left .and. m>n ) .or. ( right .and. m=d( i+1 ) end do if( sing .and. k>0_${ik}$ ) then if( incr )incr = incr .and. zero<=d( 1_${ik}$ ) if( decr )decr = decr .and. d( k )>=zero end if if( .not.( incr .or. decr ) )info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DDISNA', -info ) return end if ! quick return if possible if( k==0 )return ! compute reciprocal condition numbers if( k==1_${ik}$ ) then sep( 1_${ik}$ ) = stdlib${ii}$_dlamch( 'O' ) else oldgap = abs( d( 2_${ik}$ )-d( 1_${ik}$ ) ) sep( 1_${ik}$ ) = oldgap do i = 2, k - 1 newgap = abs( d( i+1 )-d( i ) ) sep( i ) = min( oldgap, newgap ) oldgap = newgap end do sep( k ) = oldgap end if if( sing ) then if( ( left .and. m>n ) .or. ( right .and. m=d( i+1 ) end do if( sing .and. k>0_${ik}$ ) then if( incr )incr = incr .and. zero<=d( 1_${ik}$ ) if( decr )decr = decr .and. d( k )>=zero end if if( .not.( incr .or. decr ) )info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DDISNA', -info ) return end if ! quick return if possible if( k==0 )return ! compute reciprocal condition numbers if( k==1_${ik}$ ) then sep( 1_${ik}$ ) = stdlib${ii}$_${ri}$lamch( 'O' ) else oldgap = abs( d( 2_${ik}$ )-d( 1_${ik}$ ) ) sep( 1_${ik}$ ) = oldgap do i = 2, k - 1 newgap = abs( d( i+1 )-d( i ) ) sep( i ) = min( oldgap, newgap ) oldgap = newgap end do sep( k ) = oldgap end if if( sing ) then if( ( left .and. m>n ) .or. ( right .and. m1_${ik}$ ) then ! generate elementary reflector h(i) to annihilate ! a(1:i-2,i) call stdlib${ii}$_slarfg( i-1, a( i-1, i ), a( 1_${ik}$, i ), 1_${ik}$, tau( i-1 ) ) e( i-1 ) = a( i-1, i ) a( i-1, i ) = one ! compute w(1:i-1,i) call stdlib${ii}$_ssymv( 'UPPER', i-1, one, a, lda, a( 1_${ik}$, i ), 1_${ik}$,zero, w( 1_${ik}$, iw ), & 1_${ik}$ ) if( i1_${ik}$ ) then ! generate elementary reflector h(i) to annihilate ! a(1:i-2,i) call stdlib${ii}$_dlarfg( i-1, a( i-1, i ), a( 1_${ik}$, i ), 1_${ik}$, tau( i-1 ) ) e( i-1 ) = a( i-1, i ) a( i-1, i ) = one ! compute w(1:i-1,i) call stdlib${ii}$_dsymv( 'UPPER', i-1, one, a, lda, a( 1_${ik}$, i ), 1_${ik}$,zero, w( 1_${ik}$, iw ), & 1_${ik}$ ) if( i1_${ik}$ ) then ! generate elementary reflector h(i) to annihilate ! a(1:i-2,i) call stdlib${ii}$_${ri}$larfg( i-1, a( i-1, i ), a( 1_${ik}$, i ), 1_${ik}$, tau( i-1 ) ) e( i-1 ) = a( i-1, i ) a( i-1, i ) = one ! compute w(1:i-1,i) call stdlib${ii}$_${ri}$symv( 'UPPER', i-1, one, a, lda, a( 1_${ik}$, i ), 1_${ik}$,zero, w( 1_${ik}$, iw ), & 1_${ik}$ ) if( i1_${ik}$ ) then ! generate elementary reflector h(i) to annihilate ! a(1:i-2,i) alpha = a( i-1, i ) call stdlib${ii}$_clarfg( i-1, alpha, a( 1_${ik}$, i ), 1_${ik}$, tau( i-1 ) ) e( i-1 ) = real( alpha,KIND=sp) a( i-1, i ) = cone ! compute w(1:i-1,i) call stdlib${ii}$_chemv( 'UPPER', i-1, cone, a, lda, a( 1_${ik}$, i ), 1_${ik}$,czero, w( 1_${ik}$, iw ),& 1_${ik}$ ) if( i1_${ik}$ ) then ! generate elementary reflector h(i) to annihilate ! a(1:i-2,i) alpha = a( i-1, i ) call stdlib${ii}$_zlarfg( i-1, alpha, a( 1_${ik}$, i ), 1_${ik}$, tau( i-1 ) ) e( i-1 ) = real( alpha,KIND=dp) a( i-1, i ) = cone ! compute w(1:i-1,i) call stdlib${ii}$_zhemv( 'UPPER', i-1, cone, a, lda, a( 1_${ik}$, i ), 1_${ik}$,czero, w( 1_${ik}$, iw ),& 1_${ik}$ ) if( i1_${ik}$ ) then ! generate elementary reflector h(i) to annihilate ! a(1:i-2,i) alpha = a( i-1, i ) call stdlib${ii}$_${ci}$larfg( i-1, alpha, a( 1_${ik}$, i ), 1_${ik}$, tau( i-1 ) ) e( i-1 ) = real( alpha,KIND=${ck}$) a( i-1, i ) = cone ! compute w(1:i-1,i) call stdlib${ii}$_${ci}$hemv( 'UPPER', i-1, cone, a, lda, a( 1_${ik}$, i ), 1_${ik}$,czero, w( 1_${ik}$, iw ),& 1_${ik}$ ) if( iabs( c ) ) then acmx = a acmn = c else acmx = c acmn = a end if if( adf>ab ) then rt = adf*sqrt( one+( ab / adf )**2_${ik}$ ) else if( adfzero ) then rt1 = half*( sm+rt ) ! order of execution important. ! to get fully accurate smaller eigenvalue, ! next line needs to be executed in higher precision. rt2 = ( acmx / rt1 )*acmn - ( b / rt1 )*b else ! includes case rt1 = rt2 = 0 rt1 = half*rt rt2 = -half*rt end if return end subroutine stdlib${ii}$_slae2 pure module subroutine stdlib${ii}$_dlae2( a, b, c, rt1, rt2 ) !! DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix !! [ A B ] !! [ B C ]. !! On return, RT1 is the eigenvalue of larger absolute value, and RT2 !! is the eigenvalue of smaller absolute value. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: a, b, c real(dp), intent(out) :: rt1, rt2 ! ===================================================================== ! Local Scalars real(dp) :: ab, acmn, acmx, adf, df, rt, sm, tb ! Intrinsic Functions ! Executable Statements ! compute the eigenvalues sm = a + c df = a - c adf = abs( df ) tb = b + b ab = abs( tb ) if( abs( a )>abs( c ) ) then acmx = a acmn = c else acmx = c acmn = a end if if( adf>ab ) then rt = adf*sqrt( one+( ab / adf )**2_${ik}$ ) else if( adfzero ) then rt1 = half*( sm+rt ) ! order of execution important. ! to get fully accurate smaller eigenvalue, ! next line needs to be executed in higher precision. rt2 = ( acmx / rt1 )*acmn - ( b / rt1 )*b else ! includes case rt1 = rt2 = 0 rt1 = half*rt rt2 = -half*rt end if return end subroutine stdlib${ii}$_dlae2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lae2( a, b, c, rt1, rt2 ) !! DLAE2: computes the eigenvalues of a 2-by-2 symmetric matrix !! [ A B ] !! [ B C ]. !! On return, RT1 is the eigenvalue of larger absolute value, and RT2 !! is the eigenvalue of smaller absolute value. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: a, b, c real(${rk}$), intent(out) :: rt1, rt2 ! ===================================================================== ! Local Scalars real(${rk}$) :: ab, acmn, acmx, adf, df, rt, sm, tb ! Intrinsic Functions ! Executable Statements ! compute the eigenvalues sm = a + c df = a - c adf = abs( df ) tb = b + b ab = abs( tb ) if( abs( a )>abs( c ) ) then acmx = a acmn = c else acmx = c acmn = a end if if( adf>ab ) then rt = adf*sqrt( one+( ab / adf )**2_${ik}$ ) else if( adfzero ) then rt1 = half*( sm+rt ) ! order of execution important. ! to get fully accurate smaller eigenvalue, ! next line needs to be executed in higher precision. rt2 = ( acmx / rt1 )*acmn - ( b / rt1 )*b else ! includes case rt1 = rt2 = 0 rt1 = half*rt rt2 = -half*rt end if return end subroutine stdlib${ii}$_${ri}$lae2 #:endif #:endfor pure module subroutine stdlib${ii}$_claesy( a, b, c, rt1, rt2, evscal, cs1, sn1 ) !! CLAESY computes the eigendecomposition of a 2-by-2 symmetric matrix !! ( ( A, B );( B, C ) ) !! provided the norm of the matrix of eigenvectors is larger than !! some threshold value. !! RT1 is the eigenvalue of larger absolute value, and RT2 of !! smaller absolute value. If the eigenvectors are computed, then !! on return ( CS1, SN1 ) is the unit eigenvector for RT1, hence !! [ CS1 SN1 ] . [ A B ] . [ CS1 -SN1 ] = [ RT1 0 ] !! [ -SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ] ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments complex(sp), intent(in) :: a, b, c complex(sp), intent(out) :: cs1, evscal, rt1, rt2, sn1 ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1_sp ! Local Scalars real(sp) :: babs, evnorm, tabs, z complex(sp) :: s, t, tmp ! Intrinsic Functions ! Executable Statements ! special case: the matrix is actually diagonal. ! to avoid divide by zero later, we treat this case separately. if( abs( b )==zero ) then rt1 = a rt2 = c if( abs( rt1 )zero )t = z*sqrt( ( t / z )**2_${ik}$+( b / z )**2_${ik}$ ) ! compute the two eigenvalues. rt1 and rt2 are exchanged ! if necessary so that rt1 will have the greater magnitude. rt1 = s + t rt2 = s - t if( abs( rt1 )one ) then t = tabs*sqrt( ( one / tabs )**2_${ik}$+( sn1 / tabs )**2_${ik}$ ) else t = sqrt( cone+sn1*sn1 ) end if evnorm = abs( t ) if( evnorm>=thresh ) then evscal = cone / t cs1 = evscal sn1 = sn1*evscal else evscal = zero end if end if return end subroutine stdlib${ii}$_claesy pure module subroutine stdlib${ii}$_zlaesy( a, b, c, rt1, rt2, evscal, cs1, sn1 ) !! ZLAESY computes the eigendecomposition of a 2-by-2 symmetric matrix !! ( ( A, B );( B, C ) ) !! provided the norm of the matrix of eigenvectors is larger than !! some threshold value. !! RT1 is the eigenvalue of larger absolute value, and RT2 of !! smaller absolute value. If the eigenvectors are computed, then !! on return ( CS1, SN1 ) is the unit eigenvector for RT1, hence !! [ CS1 SN1 ] . [ A B ] . [ CS1 -SN1 ] = [ RT1 0 ] !! [ -SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ] ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments complex(dp), intent(in) :: a, b, c complex(dp), intent(out) :: cs1, evscal, rt1, rt2, sn1 ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1_dp ! Local Scalars real(dp) :: babs, evnorm, tabs, z complex(dp) :: s, t, tmp ! Intrinsic Functions ! Executable Statements ! special case: the matrix is actually diagonal. ! to avoid divide by zero later, we treat this case separately. if( abs( b )==zero ) then rt1 = a rt2 = c if( abs( rt1 )zero )t = z*sqrt( ( t / z )**2_${ik}$+( b / z )**2_${ik}$ ) ! compute the two eigenvalues. rt1 and rt2 are exchanged ! if necessary so that rt1 will have the greater magnitude. rt1 = s + t rt2 = s - t if( abs( rt1 )one ) then t = tabs*sqrt( ( one / tabs )**2_${ik}$+( sn1 / tabs )**2_${ik}$ ) else t = sqrt( cone+sn1*sn1 ) end if evnorm = abs( t ) if( evnorm>=thresh ) then evscal = cone / t cs1 = evscal sn1 = sn1*evscal else evscal = zero end if end if return end subroutine stdlib${ii}$_zlaesy #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laesy( a, b, c, rt1, rt2, evscal, cs1, sn1 ) !! ZLAESY: computes the eigendecomposition of a 2-by-2 symmetric matrix !! ( ( A, B );( B, C ) ) !! provided the norm of the matrix of eigenvectors is larger than !! some threshold value. !! RT1 is the eigenvalue of larger absolute value, and RT2 of !! smaller absolute value. If the eigenvectors are computed, then !! on return ( CS1, SN1 ) is the unit eigenvector for RT1, hence !! [ CS1 SN1 ] . [ A B ] . [ CS1 -SN1 ] = [ RT1 0 ] !! [ -SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ] ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments complex(${ck}$), intent(in) :: a, b, c complex(${ck}$), intent(out) :: cs1, evscal, rt1, rt2, sn1 ! ===================================================================== ! Parameters real(${ck}$), parameter :: thresh = 0.1_${ck}$ ! Local Scalars real(${ck}$) :: babs, evnorm, tabs, z complex(${ck}$) :: s, t, tmp ! Intrinsic Functions ! Executable Statements ! special case: the matrix is actually diagonal. ! to avoid divide by zero later, we treat this case separately. if( abs( b )==zero ) then rt1 = a rt2 = c if( abs( rt1 )zero )t = z*sqrt( ( t / z )**2_${ik}$+( b / z )**2_${ik}$ ) ! compute the two eigenvalues. rt1 and rt2 are exchanged ! if necessary so that rt1 will have the greater magnitude. rt1 = s + t rt2 = s - t if( abs( rt1 )one ) then t = tabs*sqrt( ( one / tabs )**2_${ik}$+( sn1 / tabs )**2_${ik}$ ) else t = sqrt( cone+sn1*sn1 ) end if evnorm = abs( t ) if( evnorm>=thresh ) then evscal = cone / t cs1 = evscal sn1 = sn1*evscal else evscal = zero end if end if return end subroutine stdlib${ii}$_${ci}$laesy #:endif #:endfor pure module subroutine stdlib${ii}$_slaev2( a, b, c, rt1, rt2, cs1, sn1 ) !! SLAEV2 computes the eigendecomposition of a 2-by-2 symmetric matrix !! [ A B ] !! [ B C ]. !! On return, RT1 is the eigenvalue of larger absolute value, RT2 is the !! eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right !! eigenvector for RT1, giving the decomposition !! [ CS1 SN1 ] [ A B ] [ CS1 -SN1 ] = [ RT1 0 ] !! [-SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ]. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: a, b, c real(sp), intent(out) :: cs1, rt1, rt2, sn1 ! ===================================================================== ! Local Scalars integer(${ik}$) :: sgn1, sgn2 real(sp) :: ab, acmn, acmx, acs, adf, cs, ct, df, rt, sm, tb, tn ! Intrinsic Functions ! Executable Statements ! compute the eigenvalues sm = a + c df = a - c adf = abs( df ) tb = b + b ab = abs( tb ) if( abs( a )>abs( c ) ) then acmx = a acmn = c else acmx = c acmn = a end if if( adf>ab ) then rt = adf*sqrt( one+( ab / adf )**2_${ik}$ ) else if( adfzero ) then rt1 = half*( sm+rt ) sgn1 = 1_${ik}$ ! order of execution important. ! to get fully accurate smaller eigenvalue, ! next line needs to be executed in higher precision. rt2 = ( acmx / rt1 )*acmn - ( b / rt1 )*b else ! includes case rt1 = rt2 = 0 rt1 = half*rt rt2 = -half*rt sgn1 = 1_${ik}$ end if ! compute the eigenvector if( df>=zero ) then cs = df + rt sgn2 = 1_${ik}$ else cs = df - rt sgn2 = -1_${ik}$ end if acs = abs( cs ) if( acs>ab ) then ct = -tb / cs sn1 = one / sqrt( one+ct*ct ) cs1 = ct*sn1 else if( ab==zero ) then cs1 = one sn1 = zero else tn = -cs / tb cs1 = one / sqrt( one+tn*tn ) sn1 = tn*cs1 end if end if if( sgn1==sgn2 ) then tn = cs1 cs1 = -sn1 sn1 = tn end if return end subroutine stdlib${ii}$_slaev2 pure module subroutine stdlib${ii}$_dlaev2( a, b, c, rt1, rt2, cs1, sn1 ) !! DLAEV2 computes the eigendecomposition of a 2-by-2 symmetric matrix !! [ A B ] !! [ B C ]. !! On return, RT1 is the eigenvalue of larger absolute value, RT2 is the !! eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right !! eigenvector for RT1, giving the decomposition !! [ CS1 SN1 ] [ A B ] [ CS1 -SN1 ] = [ RT1 0 ] !! [-SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ]. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: a, b, c real(dp), intent(out) :: cs1, rt1, rt2, sn1 ! ===================================================================== ! Local Scalars integer(${ik}$) :: sgn1, sgn2 real(dp) :: ab, acmn, acmx, acs, adf, cs, ct, df, rt, sm, tb, tn ! Intrinsic Functions ! Executable Statements ! compute the eigenvalues sm = a + c df = a - c adf = abs( df ) tb = b + b ab = abs( tb ) if( abs( a )>abs( c ) ) then acmx = a acmn = c else acmx = c acmn = a end if if( adf>ab ) then rt = adf*sqrt( one+( ab / adf )**2_${ik}$ ) else if( adfzero ) then rt1 = half*( sm+rt ) sgn1 = 1_${ik}$ ! order of execution important. ! to get fully accurate smaller eigenvalue, ! next line needs to be executed in higher precision. rt2 = ( acmx / rt1 )*acmn - ( b / rt1 )*b else ! includes case rt1 = rt2 = 0 rt1 = half*rt rt2 = -half*rt sgn1 = 1_${ik}$ end if ! compute the eigenvector if( df>=zero ) then cs = df + rt sgn2 = 1_${ik}$ else cs = df - rt sgn2 = -1_${ik}$ end if acs = abs( cs ) if( acs>ab ) then ct = -tb / cs sn1 = one / sqrt( one+ct*ct ) cs1 = ct*sn1 else if( ab==zero ) then cs1 = one sn1 = zero else tn = -cs / tb cs1 = one / sqrt( one+tn*tn ) sn1 = tn*cs1 end if end if if( sgn1==sgn2 ) then tn = cs1 cs1 = -sn1 sn1 = tn end if return end subroutine stdlib${ii}$_dlaev2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laev2( a, b, c, rt1, rt2, cs1, sn1 ) !! DLAEV2: computes the eigendecomposition of a 2-by-2 symmetric matrix !! [ A B ] !! [ B C ]. !! On return, RT1 is the eigenvalue of larger absolute value, RT2 is the !! eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right !! eigenvector for RT1, giving the decomposition !! [ CS1 SN1 ] [ A B ] [ CS1 -SN1 ] = [ RT1 0 ] !! [-SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ]. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: a, b, c real(${rk}$), intent(out) :: cs1, rt1, rt2, sn1 ! ===================================================================== ! Local Scalars integer(${ik}$) :: sgn1, sgn2 real(${rk}$) :: ab, acmn, acmx, acs, adf, cs, ct, df, rt, sm, tb, tn ! Intrinsic Functions ! Executable Statements ! compute the eigenvalues sm = a + c df = a - c adf = abs( df ) tb = b + b ab = abs( tb ) if( abs( a )>abs( c ) ) then acmx = a acmn = c else acmx = c acmn = a end if if( adf>ab ) then rt = adf*sqrt( one+( ab / adf )**2_${ik}$ ) else if( adfzero ) then rt1 = half*( sm+rt ) sgn1 = 1_${ik}$ ! order of execution important. ! to get fully accurate smaller eigenvalue, ! next line needs to be executed in higher precision. rt2 = ( acmx / rt1 )*acmn - ( b / rt1 )*b else ! includes case rt1 = rt2 = 0 rt1 = half*rt rt2 = -half*rt sgn1 = 1_${ik}$ end if ! compute the eigenvector if( df>=zero ) then cs = df + rt sgn2 = 1_${ik}$ else cs = df - rt sgn2 = -1_${ik}$ end if acs = abs( cs ) if( acs>ab ) then ct = -tb / cs sn1 = one / sqrt( one+ct*ct ) cs1 = ct*sn1 else if( ab==zero ) then cs1 = one sn1 = zero else tn = -cs / tb cs1 = one / sqrt( one+tn*tn ) sn1 = tn*cs1 end if end if if( sgn1==sgn2 ) then tn = cs1 cs1 = -sn1 sn1 = tn end if return end subroutine stdlib${ii}$_${ri}$laev2 #:endif #:endfor pure module subroutine stdlib${ii}$_claev2( a, b, c, rt1, rt2, cs1, sn1 ) !! CLAEV2 computes the eigendecomposition of a 2-by-2 Hermitian matrix !! [ A B ] !! [ CONJG(B) C ]. !! On return, RT1 is the eigenvalue of larger absolute value, RT2 is the !! eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right !! eigenvector for RT1, giving the decomposition !! [ CS1 CONJG(SN1) ] [ A B ] [ CS1 -CONJG(SN1) ] = [ RT1 0 ] !! [-SN1 CS1 ] [ CONJG(B) C ] [ SN1 CS1 ] [ 0 RT2 ]. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(out) :: cs1, rt1, rt2 complex(sp), intent(in) :: a, b, c complex(sp), intent(out) :: sn1 ! ===================================================================== ! Local Scalars real(sp) :: t complex(sp) :: w ! Intrinsic Functions ! Executable Statements if( abs( b )==zero ) then w = one else w = conjg( b ) / abs( b ) end if call stdlib${ii}$_slaev2( real( a,KIND=sp), abs( b ), real( c,KIND=sp), rt1, rt2, cs1, t ) sn1 = w*t return end subroutine stdlib${ii}$_claev2 pure module subroutine stdlib${ii}$_zlaev2( a, b, c, rt1, rt2, cs1, sn1 ) !! ZLAEV2 computes the eigendecomposition of a 2-by-2 Hermitian matrix !! [ A B ] !! [ CONJG(B) C ]. !! On return, RT1 is the eigenvalue of larger absolute value, RT2 is the !! eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right !! eigenvector for RT1, giving the decomposition !! [ CS1 CONJG(SN1) ] [ A B ] [ CS1 -CONJG(SN1) ] = [ RT1 0 ] !! [-SN1 CS1 ] [ CONJG(B) C ] [ SN1 CS1 ] [ 0 RT2 ]. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(out) :: cs1, rt1, rt2 complex(dp), intent(in) :: a, b, c complex(dp), intent(out) :: sn1 ! ===================================================================== ! Local Scalars real(dp) :: t complex(dp) :: w ! Intrinsic Functions ! Executable Statements if( abs( b )==zero ) then w = one else w = conjg( b ) / abs( b ) end if call stdlib${ii}$_dlaev2( real( a,KIND=dp), abs( b ), real( c,KIND=dp), rt1, rt2, cs1, t ) sn1 = w*t return end subroutine stdlib${ii}$_zlaev2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laev2( a, b, c, rt1, rt2, cs1, sn1 ) !! ZLAEV2: computes the eigendecomposition of a 2-by-2 Hermitian matrix !! [ A B ] !! [ CONJG(B) C ]. !! On return, RT1 is the eigenvalue of larger absolute value, RT2 is the !! eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right !! eigenvector for RT1, giving the decomposition !! [ CS1 CONJG(SN1) ] [ A B ] [ CS1 -CONJG(SN1) ] = [ RT1 0 ] !! [-SN1 CS1 ] [ CONJG(B) C ] [ SN1 CS1 ] [ 0 RT2 ]. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${ck}$), intent(out) :: cs1, rt1, rt2 complex(${ck}$), intent(in) :: a, b, c complex(${ck}$), intent(out) :: sn1 ! ===================================================================== ! Local Scalars real(${ck}$) :: t complex(${ck}$) :: w ! Intrinsic Functions ! Executable Statements if( abs( b )==zero ) then w = one else w = conjg( b ) / abs( b ) end if call stdlib${ii}$_${c2ri(ci)}$laev2( real( a,KIND=${ck}$), abs( b ), real( c,KIND=${ck}$), rt1, rt2, cs1, t ) sn1 = w*t return end subroutine stdlib${ii}$_${ci}$laev2 #:endif #:endfor pure module subroutine stdlib${ii}$_slagtf( n, a, lambda, b, c, tol, d, in, info ) !! SLAGTF factorizes the matrix (T - lambda*I), where T is an n by n !! tridiagonal matrix and lambda is a scalar, as !! T - lambda*I = PLU, !! where P is a permutation matrix, L is a unit lower tridiagonal matrix !! with at most one non-zero sub-diagonal elements per column and U is !! an upper triangular matrix with at most two non-zero super-diagonal !! elements per column. !! The factorization is obtained by Gaussian elimination with partial !! pivoting and implicit row scaling. !! The parameter LAMBDA is included in the routine so that SLAGTF may !! be used, in conjunction with SLAGTS, to obtain eigenvectors of T by !! inverse iteration. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(in) :: lambda, tol ! Array Arguments integer(${ik}$), intent(out) :: in(*) real(sp), intent(inout) :: a(*), b(*), c(*) real(sp), intent(out) :: d(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: k real(sp) :: eps, mult, piv1, piv2, scale1, scale2, temp, tl ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'SLAGTF', -info ) return end if if( n==0 )return a( 1_${ik}$ ) = a( 1_${ik}$ ) - lambda in( n ) = 0_${ik}$ if( n==1_${ik}$ ) then if( a( 1_${ik}$ )==zero )in( 1_${ik}$ ) = 1_${ik}$ return end if eps = stdlib${ii}$_slamch( 'EPSILON' ) tl = max( tol, eps ) scale1 = abs( a( 1_${ik}$ ) ) + abs( b( 1_${ik}$ ) ) loop_10: do k = 1, n - 1 a( k+1 ) = a( k+1 ) - lambda scale2 = abs( c( k ) ) + abs( a( k+1 ) ) if( k<( n-1 ) )scale2 = scale2 + abs( b( k+1 ) ) if( a( k )==zero ) then piv1 = zero else piv1 = abs( a( k ) ) / scale1 end if if( c( k )==zero ) then in( k ) = 0_${ik}$ piv2 = zero scale1 = scale2 if( k<( n-1 ) )d( k ) = zero else piv2 = abs( c( k ) ) / scale2 if( piv2<=piv1 ) then in( k ) = 0_${ik}$ scale1 = scale2 c( k ) = c( k ) / a( k ) a( k+1 ) = a( k+1 ) - c( k )*b( k ) if( k<( n-1 ) )d( k ) = zero else in( k ) = 1_${ik}$ mult = a( k ) / c( k ) a( k ) = c( k ) temp = a( k+1 ) a( k+1 ) = b( k ) - mult*temp if( k<( n-1 ) ) then d( k ) = b( k+1 ) b( k+1 ) = -mult*d( k ) end if b( k ) = temp c( k ) = mult end if end if if( ( max( piv1, piv2 )<=tl ) .and. ( in( n )==0_${ik}$ ) )in( n ) = k end do loop_10 if( ( abs( a( n ) )<=scale1*tl ) .and. ( in( n )==0_${ik}$ ) )in( n ) = n return end subroutine stdlib${ii}$_slagtf pure module subroutine stdlib${ii}$_dlagtf( n, a, lambda, b, c, tol, d, in, info ) !! DLAGTF factorizes the matrix (T - lambda*I), where T is an n by n !! tridiagonal matrix and lambda is a scalar, as !! T - lambda*I = PLU, !! where P is a permutation matrix, L is a unit lower tridiagonal matrix !! with at most one non-zero sub-diagonal elements per column and U is !! an upper triangular matrix with at most two non-zero super-diagonal !! elements per column. !! The factorization is obtained by Gaussian elimination with partial !! pivoting and implicit row scaling. !! The parameter LAMBDA is included in the routine so that DLAGTF may !! be used, in conjunction with DLAGTS, to obtain eigenvectors of T by !! inverse iteration. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(in) :: lambda, tol ! Array Arguments integer(${ik}$), intent(out) :: in(*) real(dp), intent(inout) :: a(*), b(*), c(*) real(dp), intent(out) :: d(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: k real(dp) :: eps, mult, piv1, piv2, scale1, scale2, temp, tl ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'DLAGTF', -info ) return end if if( n==0 )return a( 1_${ik}$ ) = a( 1_${ik}$ ) - lambda in( n ) = 0_${ik}$ if( n==1_${ik}$ ) then if( a( 1_${ik}$ )==zero )in( 1_${ik}$ ) = 1_${ik}$ return end if eps = stdlib${ii}$_dlamch( 'EPSILON' ) tl = max( tol, eps ) scale1 = abs( a( 1_${ik}$ ) ) + abs( b( 1_${ik}$ ) ) loop_10: do k = 1, n - 1 a( k+1 ) = a( k+1 ) - lambda scale2 = abs( c( k ) ) + abs( a( k+1 ) ) if( k<( n-1 ) )scale2 = scale2 + abs( b( k+1 ) ) if( a( k )==zero ) then piv1 = zero else piv1 = abs( a( k ) ) / scale1 end if if( c( k )==zero ) then in( k ) = 0_${ik}$ piv2 = zero scale1 = scale2 if( k<( n-1 ) )d( k ) = zero else piv2 = abs( c( k ) ) / scale2 if( piv2<=piv1 ) then in( k ) = 0_${ik}$ scale1 = scale2 c( k ) = c( k ) / a( k ) a( k+1 ) = a( k+1 ) - c( k )*b( k ) if( k<( n-1 ) )d( k ) = zero else in( k ) = 1_${ik}$ mult = a( k ) / c( k ) a( k ) = c( k ) temp = a( k+1 ) a( k+1 ) = b( k ) - mult*temp if( k<( n-1 ) ) then d( k ) = b( k+1 ) b( k+1 ) = -mult*d( k ) end if b( k ) = temp c( k ) = mult end if end if if( ( max( piv1, piv2 )<=tl ) .and. ( in( n )==0_${ik}$ ) )in( n ) = k end do loop_10 if( ( abs( a( n ) )<=scale1*tl ) .and. ( in( n )==0_${ik}$ ) )in( n ) = n return end subroutine stdlib${ii}$_dlagtf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lagtf( n, a, lambda, b, c, tol, d, in, info ) !! DLAGTF: factorizes the matrix (T - lambda*I), where T is an n by n !! tridiagonal matrix and lambda is a scalar, as !! T - lambda*I = PLU, !! where P is a permutation matrix, L is a unit lower tridiagonal matrix !! with at most one non-zero sub-diagonal elements per column and U is !! an upper triangular matrix with at most two non-zero super-diagonal !! elements per column. !! The factorization is obtained by Gaussian elimination with partial !! pivoting and implicit row scaling. !! The parameter LAMBDA is included in the routine so that DLAGTF may !! be used, in conjunction with DLAGTS, to obtain eigenvectors of T by !! inverse iteration. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(${rk}$), intent(in) :: lambda, tol ! Array Arguments integer(${ik}$), intent(out) :: in(*) real(${rk}$), intent(inout) :: a(*), b(*), c(*) real(${rk}$), intent(out) :: d(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: k real(${rk}$) :: eps, mult, piv1, piv2, scale1, scale2, temp, tl ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'DLAGTF', -info ) return end if if( n==0 )return a( 1_${ik}$ ) = a( 1_${ik}$ ) - lambda in( n ) = 0_${ik}$ if( n==1_${ik}$ ) then if( a( 1_${ik}$ )==zero )in( 1_${ik}$ ) = 1_${ik}$ return end if eps = stdlib${ii}$_${ri}$lamch( 'EPSILON' ) tl = max( tol, eps ) scale1 = abs( a( 1_${ik}$ ) ) + abs( b( 1_${ik}$ ) ) loop_10: do k = 1, n - 1 a( k+1 ) = a( k+1 ) - lambda scale2 = abs( c( k ) ) + abs( a( k+1 ) ) if( k<( n-1 ) )scale2 = scale2 + abs( b( k+1 ) ) if( a( k )==zero ) then piv1 = zero else piv1 = abs( a( k ) ) / scale1 end if if( c( k )==zero ) then in( k ) = 0_${ik}$ piv2 = zero scale1 = scale2 if( k<( n-1 ) )d( k ) = zero else piv2 = abs( c( k ) ) / scale2 if( piv2<=piv1 ) then in( k ) = 0_${ik}$ scale1 = scale2 c( k ) = c( k ) / a( k ) a( k+1 ) = a( k+1 ) - c( k )*b( k ) if( k<( n-1 ) )d( k ) = zero else in( k ) = 1_${ik}$ mult = a( k ) / c( k ) a( k ) = c( k ) temp = a( k+1 ) a( k+1 ) = b( k ) - mult*temp if( k<( n-1 ) ) then d( k ) = b( k+1 ) b( k+1 ) = -mult*d( k ) end if b( k ) = temp c( k ) = mult end if end if if( ( max( piv1, piv2 )<=tl ) .and. ( in( n )==0_${ik}$ ) )in( n ) = k end do loop_10 if( ( abs( a( n ) )<=scale1*tl ) .and. ( in( n )==0_${ik}$ ) )in( n ) = n return end subroutine stdlib${ii}$_${ri}$lagtf #:endif #:endfor pure module subroutine stdlib${ii}$_slagts( job, n, a, b, c, d, in, y, tol, info ) !! SLAGTS may be used to solve one of the systems of equations !! (T - lambda*I)*x = y or (T - lambda*I)**T*x = y, !! where T is an n by n tridiagonal matrix, for x, following the !! factorization of (T - lambda*I) as !! (T - lambda*I) = P*L*U , !! by routine SLAGTF. The choice of equation to be solved is !! controlled by the argument JOB, and in each case there is an option !! to perturb zero or very small diagonal elements of U, this option !! being intended for use in applications such as inverse iteration. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: job, n real(sp), intent(inout) :: tol ! Array Arguments integer(${ik}$), intent(in) :: in(*) real(sp), intent(in) :: a(*), b(*), c(*), d(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: k real(sp) :: absak, ak, bignum, eps, pert, sfmin, temp ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( ( abs( job )>2_${ik}$ ) .or. ( job==0_${ik}$ ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SLAGTS', -info ) return end if if( n==0 )return eps = stdlib${ii}$_slamch( 'EPSILON' ) sfmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) bignum = one / sfmin if( job<0_${ik}$ ) then if( tol<=zero ) then tol = abs( a( 1_${ik}$ ) ) if( n>1_${ik}$ )tol = max( tol, abs( a( 2_${ik}$ ) ), abs( b( 1_${ik}$ ) ) ) do k = 3, n tol = max( tol, abs( a( k ) ), abs( b( k-1 ) ),abs( d( k-2 ) ) ) end do tol = tol*eps if( tol==zero )tol = eps end if end if if( abs( job )==1_${ik}$ ) then do k = 2, n if( in( k-1 )==0_${ik}$ ) then y( k ) = y( k ) - c( k-1 )*y( k-1 ) else temp = y( k-1 ) y( k-1 ) = y( k ) y( k ) = temp - c( k-1 )*y( k ) end if end do if( job==1_${ik}$ ) then loop_30: do k = n, 1, -1 if( k<=n-2 ) then temp = y( k ) - b( k )*y( k+1 ) - d( k )*y( k+2 ) else if( k==n-1 ) then temp = y( k ) - b( k )*y( k+1 ) else temp = y( k ) end if ak = a( k ) absak = abs( ak ) if( absakabsak )then info = k return else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then info = k return end if end if y( k ) = temp / ak end do loop_30 else loop_50: do k = n, 1, -1 if( k<=n-2 ) then temp = y( k ) - b( k )*y( k+1 ) - d( k )*y( k+2 ) else if( k==n-1 ) then temp = y( k ) - b( k )*y( k+1 ) else temp = y( k ) end if ak = a( k ) pert = sign( tol, ak ) 40 continue absak = abs( ak ) if( absakabsak )then ak = ak + pert pert = 2_${ik}$*pert go to 40 else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then ak = ak + pert pert = 2_${ik}$*pert go to 40 end if end if y( k ) = temp / ak end do loop_50 end if else ! come to here if job = 2 or -2 if( job==2_${ik}$ ) then loop_60: do k = 1, n if( k>=3_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) - d( k-2 )*y( k-2 ) else if( k==2_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) else temp = y( k ) end if ak = a( k ) absak = abs( ak ) if( absakabsak )then info = k return else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then info = k return end if end if y( k ) = temp / ak end do loop_60 else loop_80: do k = 1, n if( k>=3_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) - d( k-2 )*y( k-2 ) else if( k==2_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) else temp = y( k ) end if ak = a( k ) pert = sign( tol, ak ) 70 continue absak = abs( ak ) if( absakabsak )then ak = ak + pert pert = 2_${ik}$*pert go to 70 else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then ak = ak + pert pert = 2_${ik}$*pert go to 70 end if end if y( k ) = temp / ak end do loop_80 end if do k = n, 2, -1 if( in( k-1 )==0_${ik}$ ) then y( k-1 ) = y( k-1 ) - c( k-1 )*y( k ) else temp = y( k-1 ) y( k-1 ) = y( k ) y( k ) = temp - c( k-1 )*y( k ) end if end do end if end subroutine stdlib${ii}$_slagts pure module subroutine stdlib${ii}$_dlagts( job, n, a, b, c, d, in, y, tol, info ) !! DLAGTS may be used to solve one of the systems of equations !! (T - lambda*I)*x = y or (T - lambda*I)**T*x = y, !! where T is an n by n tridiagonal matrix, for x, following the !! factorization of (T - lambda*I) as !! (T - lambda*I) = P*L*U , !! by routine DLAGTF. The choice of equation to be solved is !! controlled by the argument JOB, and in each case there is an option !! to perturb zero or very small diagonal elements of U, this option !! being intended for use in applications such as inverse iteration. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: job, n real(dp), intent(inout) :: tol ! Array Arguments integer(${ik}$), intent(in) :: in(*) real(dp), intent(in) :: a(*), b(*), c(*), d(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: k real(dp) :: absak, ak, bignum, eps, pert, sfmin, temp ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( ( abs( job )>2_${ik}$ ) .or. ( job==0_${ik}$ ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLAGTS', -info ) return end if if( n==0 )return eps = stdlib${ii}$_dlamch( 'EPSILON' ) sfmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) bignum = one / sfmin if( job<0_${ik}$ ) then if( tol<=zero ) then tol = abs( a( 1_${ik}$ ) ) if( n>1_${ik}$ )tol = max( tol, abs( a( 2_${ik}$ ) ), abs( b( 1_${ik}$ ) ) ) do k = 3, n tol = max( tol, abs( a( k ) ), abs( b( k-1 ) ),abs( d( k-2 ) ) ) end do tol = tol*eps if( tol==zero )tol = eps end if end if if( abs( job )==1_${ik}$ ) then do k = 2, n if( in( k-1 )==0_${ik}$ ) then y( k ) = y( k ) - c( k-1 )*y( k-1 ) else temp = y( k-1 ) y( k-1 ) = y( k ) y( k ) = temp - c( k-1 )*y( k ) end if end do if( job==1_${ik}$ ) then loop_30: do k = n, 1, -1 if( k<=n-2 ) then temp = y( k ) - b( k )*y( k+1 ) - d( k )*y( k+2 ) else if( k==n-1 ) then temp = y( k ) - b( k )*y( k+1 ) else temp = y( k ) end if ak = a( k ) absak = abs( ak ) if( absakabsak )then info = k return else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then info = k return end if end if y( k ) = temp / ak end do loop_30 else loop_50: do k = n, 1, -1 if( k<=n-2 ) then temp = y( k ) - b( k )*y( k+1 ) - d( k )*y( k+2 ) else if( k==n-1 ) then temp = y( k ) - b( k )*y( k+1 ) else temp = y( k ) end if ak = a( k ) pert = sign( tol, ak ) 40 continue absak = abs( ak ) if( absakabsak )then ak = ak + pert pert = 2_${ik}$*pert go to 40 else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then ak = ak + pert pert = 2_${ik}$*pert go to 40 end if end if y( k ) = temp / ak end do loop_50 end if else ! come to here if job = 2 or -2 if( job==2_${ik}$ ) then loop_60: do k = 1, n if( k>=3_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) - d( k-2 )*y( k-2 ) else if( k==2_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) else temp = y( k ) end if ak = a( k ) absak = abs( ak ) if( absakabsak )then info = k return else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then info = k return end if end if y( k ) = temp / ak end do loop_60 else loop_80: do k = 1, n if( k>=3_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) - d( k-2 )*y( k-2 ) else if( k==2_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) else temp = y( k ) end if ak = a( k ) pert = sign( tol, ak ) 70 continue absak = abs( ak ) if( absakabsak )then ak = ak + pert pert = 2_${ik}$*pert go to 70 else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then ak = ak + pert pert = 2_${ik}$*pert go to 70 end if end if y( k ) = temp / ak end do loop_80 end if do k = n, 2, -1 if( in( k-1 )==0_${ik}$ ) then y( k-1 ) = y( k-1 ) - c( k-1 )*y( k ) else temp = y( k-1 ) y( k-1 ) = y( k ) y( k ) = temp - c( k-1 )*y( k ) end if end do end if end subroutine stdlib${ii}$_dlagts #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lagts( job, n, a, b, c, d, in, y, tol, info ) !! DLAGTS: may be used to solve one of the systems of equations !! (T - lambda*I)*x = y or (T - lambda*I)**T*x = y, !! where T is an n by n tridiagonal matrix, for x, following the !! factorization of (T - lambda*I) as !! (T - lambda*I) = P*L*U , !! by routine DLAGTF. The choice of equation to be solved is !! controlled by the argument JOB, and in each case there is an option !! to perturb zero or very small diagonal elements of U, this option !! being intended for use in applications such as inverse iteration. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: job, n real(${rk}$), intent(inout) :: tol ! Array Arguments integer(${ik}$), intent(in) :: in(*) real(${rk}$), intent(in) :: a(*), b(*), c(*), d(*) real(${rk}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: k real(${rk}$) :: absak, ak, bignum, eps, pert, sfmin, temp ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( ( abs( job )>2_${ik}$ ) .or. ( job==0_${ik}$ ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLAGTS', -info ) return end if if( n==0 )return eps = stdlib${ii}$_${ri}$lamch( 'EPSILON' ) sfmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) bignum = one / sfmin if( job<0_${ik}$ ) then if( tol<=zero ) then tol = abs( a( 1_${ik}$ ) ) if( n>1_${ik}$ )tol = max( tol, abs( a( 2_${ik}$ ) ), abs( b( 1_${ik}$ ) ) ) do k = 3, n tol = max( tol, abs( a( k ) ), abs( b( k-1 ) ),abs( d( k-2 ) ) ) end do tol = tol*eps if( tol==zero )tol = eps end if end if if( abs( job )==1_${ik}$ ) then do k = 2, n if( in( k-1 )==0_${ik}$ ) then y( k ) = y( k ) - c( k-1 )*y( k-1 ) else temp = y( k-1 ) y( k-1 ) = y( k ) y( k ) = temp - c( k-1 )*y( k ) end if end do if( job==1_${ik}$ ) then loop_30: do k = n, 1, -1 if( k<=n-2 ) then temp = y( k ) - b( k )*y( k+1 ) - d( k )*y( k+2 ) else if( k==n-1 ) then temp = y( k ) - b( k )*y( k+1 ) else temp = y( k ) end if ak = a( k ) absak = abs( ak ) if( absakabsak )then info = k return else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then info = k return end if end if y( k ) = temp / ak end do loop_30 else loop_50: do k = n, 1, -1 if( k<=n-2 ) then temp = y( k ) - b( k )*y( k+1 ) - d( k )*y( k+2 ) else if( k==n-1 ) then temp = y( k ) - b( k )*y( k+1 ) else temp = y( k ) end if ak = a( k ) pert = sign( tol, ak ) 40 continue absak = abs( ak ) if( absakabsak )then ak = ak + pert pert = 2_${ik}$*pert go to 40 else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then ak = ak + pert pert = 2_${ik}$*pert go to 40 end if end if y( k ) = temp / ak end do loop_50 end if else ! come to here if job = 2 or -2 if( job==2_${ik}$ ) then loop_60: do k = 1, n if( k>=3_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) - d( k-2 )*y( k-2 ) else if( k==2_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) else temp = y( k ) end if ak = a( k ) absak = abs( ak ) if( absakabsak )then info = k return else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then info = k return end if end if y( k ) = temp / ak end do loop_60 else loop_80: do k = 1, n if( k>=3_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) - d( k-2 )*y( k-2 ) else if( k==2_${ik}$ ) then temp = y( k ) - b( k-1 )*y( k-1 ) else temp = y( k ) end if ak = a( k ) pert = sign( tol, ak ) 70 continue absak = abs( ak ) if( absakabsak )then ak = ak + pert pert = 2_${ik}$*pert go to 70 else temp = temp*bignum ak = ak*bignum end if else if( abs( temp )>absak*bignum ) then ak = ak + pert pert = 2_${ik}$*pert go to 70 end if end if y( k ) = temp / ak end do loop_80 end if do k = n, 2, -1 if( in( k-1 )==0_${ik}$ ) then y( k-1 ) = y( k-1 ) - c( k-1 )*y( k ) else temp = y( k-1 ) y( k-1 ) = y( k ) y( k ) = temp - c( k-1 )*y( k ) end if end do end if end subroutine stdlib${ii}$_${ri}$lagts #:endif #:endfor pure module subroutine stdlib${ii}$_ssptrd( uplo, n, ap, d, e, tau, info ) !! SSPTRD reduces a real symmetric matrix A stored in packed form to !! symmetric tridiagonal form T by an orthogonal similarity !! transformation: Q**T * A * Q = T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(inout) :: ap(*) real(sp), intent(out) :: d(*), e(*), tau(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, i1, i1i1, ii real(sp) :: alpha, taui ! Executable Statements ! test the input parameters info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSPTRD', -info ) return end if ! quick return if possible if( n<=0 )return if( upper ) then ! reduce the upper triangle of a. ! i1 is the index in ap of a(1,i+1). i1 = n*( n-1 ) / 2_${ik}$ + 1_${ik}$ do i = n - 1, 1, -1 ! generate elementary reflector h(i) = i - tau * v * v**t ! to annihilate a(1:i-1,i+1) call stdlib${ii}$_slarfg( i, ap( i1+i-1 ), ap( i1 ), 1_${ik}$, taui ) e( i ) = ap( i1+i-1 ) if( taui/=zero ) then ! apply h(i) from both sides to a(1:i,1:i) ap( i1+i-1 ) = one ! compute y := tau * a * v storing y in tau(1:i) call stdlib${ii}$_sspmv( uplo, i, taui, ap, ap( i1 ), 1_${ik}$, zero, tau,1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**t *v) * v alpha = -half*taui*stdlib${ii}$_sdot( i, tau, 1_${ik}$, ap( i1 ), 1_${ik}$ ) call stdlib${ii}$_saxpy( i, alpha, ap( i1 ), 1_${ik}$, tau, 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**t - w * v**t call stdlib${ii}$_sspr2( uplo, i, -one, ap( i1 ), 1_${ik}$, tau, 1_${ik}$, ap ) ap( i1+i-1 ) = e( i ) end if d( i+1 ) = ap( i1+i ) tau( i ) = taui i1 = i1 - i end do d( 1_${ik}$ ) = ap( 1_${ik}$ ) else ! reduce the lower triangle of a. ii is the index in ap of ! a(i,i) and i1i1 is the index of a(i+1,i+1). ii = 1_${ik}$ do i = 1, n - 1 i1i1 = ii + n - i + 1_${ik}$ ! generate elementary reflector h(i) = i - tau * v * v**t ! to annihilate a(i+2:n,i) call stdlib${ii}$_slarfg( n-i, ap( ii+1 ), ap( ii+2 ), 1_${ik}$, taui ) e( i ) = ap( ii+1 ) if( taui/=zero ) then ! apply h(i) from both sides to a(i+1:n,i+1:n) ap( ii+1 ) = one ! compute y := tau * a * v storing y in tau(i:n-1) call stdlib${ii}$_sspmv( uplo, n-i, taui, ap( i1i1 ), ap( ii+1 ), 1_${ik}$,zero, tau( i ), & 1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**t *v) * v alpha = -half*taui*stdlib${ii}$_sdot( n-i, tau( i ), 1_${ik}$, ap( ii+1 ),1_${ik}$ ) call stdlib${ii}$_saxpy( n-i, alpha, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**t - w * v**t call stdlib${ii}$_sspr2( uplo, n-i, -one, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$,ap( i1i1 ) ) ap( ii+1 ) = e( i ) end if d( i ) = ap( ii ) tau( i ) = taui ii = i1i1 end do d( n ) = ap( ii ) end if return end subroutine stdlib${ii}$_ssptrd pure module subroutine stdlib${ii}$_dsptrd( uplo, n, ap, d, e, tau, info ) !! DSPTRD reduces a real symmetric matrix A stored in packed form to !! symmetric tridiagonal form T by an orthogonal similarity !! transformation: Q**T * A * Q = T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(inout) :: ap(*) real(dp), intent(out) :: d(*), e(*), tau(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, i1, i1i1, ii real(dp) :: alpha, taui ! Executable Statements ! test the input parameters info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSPTRD', -info ) return end if ! quick return if possible if( n<=0 )return if( upper ) then ! reduce the upper triangle of a. ! i1 is the index in ap of a(1,i+1). i1 = n*( n-1 ) / 2_${ik}$ + 1_${ik}$ do i = n - 1, 1, -1 ! generate elementary reflector h(i) = i - tau * v * v**t ! to annihilate a(1:i-1,i+1) call stdlib${ii}$_dlarfg( i, ap( i1+i-1 ), ap( i1 ), 1_${ik}$, taui ) e( i ) = ap( i1+i-1 ) if( taui/=zero ) then ! apply h(i) from both sides to a(1:i,1:i) ap( i1+i-1 ) = one ! compute y := tau * a * v storing y in tau(1:i) call stdlib${ii}$_dspmv( uplo, i, taui, ap, ap( i1 ), 1_${ik}$, zero, tau,1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**t *v) * v alpha = -half*taui*stdlib${ii}$_ddot( i, tau, 1_${ik}$, ap( i1 ), 1_${ik}$ ) call stdlib${ii}$_daxpy( i, alpha, ap( i1 ), 1_${ik}$, tau, 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**t - w * v**t call stdlib${ii}$_dspr2( uplo, i, -one, ap( i1 ), 1_${ik}$, tau, 1_${ik}$, ap ) ap( i1+i-1 ) = e( i ) end if d( i+1 ) = ap( i1+i ) tau( i ) = taui i1 = i1 - i end do d( 1_${ik}$ ) = ap( 1_${ik}$ ) else ! reduce the lower triangle of a. ii is the index in ap of ! a(i,i) and i1i1 is the index of a(i+1,i+1). ii = 1_${ik}$ do i = 1, n - 1 i1i1 = ii + n - i + 1_${ik}$ ! generate elementary reflector h(i) = i - tau * v * v**t ! to annihilate a(i+2:n,i) call stdlib${ii}$_dlarfg( n-i, ap( ii+1 ), ap( ii+2 ), 1_${ik}$, taui ) e( i ) = ap( ii+1 ) if( taui/=zero ) then ! apply h(i) from both sides to a(i+1:n,i+1:n) ap( ii+1 ) = one ! compute y := tau * a * v storing y in tau(i:n-1) call stdlib${ii}$_dspmv( uplo, n-i, taui, ap( i1i1 ), ap( ii+1 ), 1_${ik}$,zero, tau( i ), & 1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**t *v) * v alpha = -half*taui*stdlib${ii}$_ddot( n-i, tau( i ), 1_${ik}$, ap( ii+1 ),1_${ik}$ ) call stdlib${ii}$_daxpy( n-i, alpha, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**t - w * v**t call stdlib${ii}$_dspr2( uplo, n-i, -one, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$,ap( i1i1 ) ) ap( ii+1 ) = e( i ) end if d( i ) = ap( ii ) tau( i ) = taui ii = i1i1 end do d( n ) = ap( ii ) end if return end subroutine stdlib${ii}$_dsptrd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sptrd( uplo, n, ap, d, e, tau, info ) !! DSPTRD: reduces a real symmetric matrix A stored in packed form to !! symmetric tridiagonal form T by an orthogonal similarity !! transformation: Q**T * A * Q = T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(${rk}$), intent(inout) :: ap(*) real(${rk}$), intent(out) :: d(*), e(*), tau(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, i1, i1i1, ii real(${rk}$) :: alpha, taui ! Executable Statements ! test the input parameters info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSPTRD', -info ) return end if ! quick return if possible if( n<=0 )return if( upper ) then ! reduce the upper triangle of a. ! i1 is the index in ap of a(1,i+1). i1 = n*( n-1 ) / 2_${ik}$ + 1_${ik}$ do i = n - 1, 1, -1 ! generate elementary reflector h(i) = i - tau * v * v**t ! to annihilate a(1:i-1,i+1) call stdlib${ii}$_${ri}$larfg( i, ap( i1+i-1 ), ap( i1 ), 1_${ik}$, taui ) e( i ) = ap( i1+i-1 ) if( taui/=zero ) then ! apply h(i) from both sides to a(1:i,1:i) ap( i1+i-1 ) = one ! compute y := tau * a * v storing y in tau(1:i) call stdlib${ii}$_${ri}$spmv( uplo, i, taui, ap, ap( i1 ), 1_${ik}$, zero, tau,1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**t *v) * v alpha = -half*taui*stdlib${ii}$_${ri}$dot( i, tau, 1_${ik}$, ap( i1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( i, alpha, ap( i1 ), 1_${ik}$, tau, 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**t - w * v**t call stdlib${ii}$_${ri}$spr2( uplo, i, -one, ap( i1 ), 1_${ik}$, tau, 1_${ik}$, ap ) ap( i1+i-1 ) = e( i ) end if d( i+1 ) = ap( i1+i ) tau( i ) = taui i1 = i1 - i end do d( 1_${ik}$ ) = ap( 1_${ik}$ ) else ! reduce the lower triangle of a. ii is the index in ap of ! a(i,i) and i1i1 is the index of a(i+1,i+1). ii = 1_${ik}$ do i = 1, n - 1 i1i1 = ii + n - i + 1_${ik}$ ! generate elementary reflector h(i) = i - tau * v * v**t ! to annihilate a(i+2:n,i) call stdlib${ii}$_${ri}$larfg( n-i, ap( ii+1 ), ap( ii+2 ), 1_${ik}$, taui ) e( i ) = ap( ii+1 ) if( taui/=zero ) then ! apply h(i) from both sides to a(i+1:n,i+1:n) ap( ii+1 ) = one ! compute y := tau * a * v storing y in tau(i:n-1) call stdlib${ii}$_${ri}$spmv( uplo, n-i, taui, ap( i1i1 ), ap( ii+1 ), 1_${ik}$,zero, tau( i ), & 1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**t *v) * v alpha = -half*taui*stdlib${ii}$_${ri}$dot( n-i, tau( i ), 1_${ik}$, ap( ii+1 ),1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( n-i, alpha, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**t - w * v**t call stdlib${ii}$_${ri}$spr2( uplo, n-i, -one, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$,ap( i1i1 ) ) ap( ii+1 ) = e( i ) end if d( i ) = ap( ii ) tau( i ) = taui ii = i1i1 end do d( n ) = ap( ii ) end if return end subroutine stdlib${ii}$_${ri}$sptrd #:endif #:endfor pure module subroutine stdlib${ii}$_sopgtr( uplo, n, ap, tau, q, ldq, work, info ) !! SOPGTR generates a real orthogonal matrix Q which is defined as the !! product of n-1 elementary reflectors H(i) of order n, as returned by !! SSPTRD using packed storage: !! if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), !! if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq, n ! Array Arguments real(sp), intent(in) :: ap(*), tau(*) real(sp), intent(out) :: q(ldq,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, ij, j ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldq1_${ik}$ ) then ! generate q(2:n,2:n) call stdlib${ii}$_sorg2r( n-1, n-1, n-1, q( 2_${ik}$, 2_${ik}$ ), ldq, tau, work,iinfo ) end if end if return end subroutine stdlib${ii}$_sopgtr pure module subroutine stdlib${ii}$_dopgtr( uplo, n, ap, tau, q, ldq, work, info ) !! DOPGTR generates a real orthogonal matrix Q which is defined as the !! product of n-1 elementary reflectors H(i) of order n, as returned by !! DSPTRD using packed storage: !! if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), !! if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq, n ! Array Arguments real(dp), intent(in) :: ap(*), tau(*) real(dp), intent(out) :: q(ldq,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, ij, j ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldq1_${ik}$ ) then ! generate q(2:n,2:n) call stdlib${ii}$_dorg2r( n-1, n-1, n-1, q( 2_${ik}$, 2_${ik}$ ), ldq, tau, work,iinfo ) end if end if return end subroutine stdlib${ii}$_dopgtr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$opgtr( uplo, n, ap, tau, q, ldq, work, info ) !! DOPGTR: generates a real orthogonal matrix Q which is defined as the !! product of n-1 elementary reflectors H(i) of order n, as returned by !! DSPTRD using packed storage: !! if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), !! if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq, n ! Array Arguments real(${rk}$), intent(in) :: ap(*), tau(*) real(${rk}$), intent(out) :: q(ldq,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, ij, j ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldq1_${ik}$ ) then ! generate q(2:n,2:n) call stdlib${ii}$_${ri}$org2r( n-1, n-1, n-1, q( 2_${ik}$, 2_${ik}$ ), ldq, tau, work,iinfo ) end if end if return end subroutine stdlib${ii}$_${ri}$opgtr #:endif #:endfor pure module subroutine stdlib${ii}$_sopmtr( side, uplo, trans, m, n, ap, tau, c, ldc, work,info ) !! SOPMTR overwrites the general real M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'T': Q**T * C C * Q**T !! where Q is a real orthogonal matrix of order nq, with nq = m if !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of !! nq-1 elementary reflectors, as returned by SSPTRD using packed !! storage: !! if UPLO = 'U', Q = H(nq-1) . . . H(2) H(1); !! if UPLO = 'L', Q = H(1) H(2) . . . H(nq-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc, m, n ! Array Arguments real(sp), intent(inout) :: ap(*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: forwrd, left, notran, upper integer(${ik}$) :: i, i1, i2, i3, ic, ii, jc, mi, ni, nq real(sp) :: aii ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) upper = stdlib_lsame( uplo, 'U' ) ! nq is the order of q if( left ) then nq = m else nq = n end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldc1_${ik}$ ) then ! reduce to tridiagonal form, working with upper triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ loop_90: do i = 1, n - 2 ! reduce i-th row of matrix to tridiagonal form loop_80: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_slargv( nr, ab( 1_${ik}$, j1-1 ), inca, work( j1 ),kd1, d( j1 ), & kd1 ) ! apply rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_slartv or stdlib${ii}$_srot is used if( nr>=2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_slartv( nr, ab( l+1, j1-1 ), inca,ab( l, j1 ), inca, & d( j1 ),work( j1 ), kd1 ) end do else jend = j1 + ( nr-1 )*kd1 do jinc = j1, jend, kd1 call stdlib${ii}$_srot( kdm1, ab( 2_${ik}$, jinc-1 ), 1_${ik}$,ab( 1_${ik}$, jinc ), 1_${ik}$, d( & jinc ),work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+k-1) ! within the band call stdlib${ii}$_slartg( ab( kd-k+3, i+k-2 ),ab( kd-k+2, i+k-1 ), d( i+k-& 1_${ik}$ ),work( i+k-1 ), temp ) ab( kd-k+3, i+k-2 ) = temp ! apply rotation from the right call stdlib${ii}$_srot( k-3, ab( kd-k+4, i+k-2 ), 1_${ik}$,ab( kd-k+3, i+k-1 ), 1_${ik}$,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_slar2v( nr, ab( kd1, j1-1 ), ab( kd1, j1 ),ab( kd, & j1 ), inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the left if( nr>0_${ik}$ ) then if( 2_${ik}$*kd-1n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( kd-l, j1+l ), inca,ab( kd-& l+1, j1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do jin = j1, j1end, kd1 call stdlib${ii}$_srot( kd-1, ab( kd-1, jin+1 ), incx,ab( kd, jin+1 )& , incx,d( jin ), work( jin ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_srot( lend, ab( kd-1, last+1 ), incx,ab( kd, & last+1 ), incx, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_srot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & work( j ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_srot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), work( j & ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j-1,j+kd) outside the band ! and store it in work work( j+kd ) = work( j )*ab( 1_${ik}$, j+kd ) ab( 1_${ik}$, j+kd ) = d( j )*ab( 1_${ik}$, j+kd ) end do end do loop_80 end do loop_90 end if if( kd>0_${ik}$ ) then ! copy off-diagonal elements to e do i = 1, n - 1 e( i ) = ab( kd, i+1 ) end do else ! set e to zero if original matrix was diagonal do i = 1, n - 1 e( i ) = zero end do end if ! copy diagonal elements to d do i = 1, n d( i ) = ab( kd1, i ) end do else if( kd>1_${ik}$ ) then ! reduce to tridiagonal form, working with lower triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ loop_210: do i = 1, n - 2 ! reduce i-th column of matrix to tridiagonal form loop_200: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_slargv( nr, ab( kd1, j1-kd1 ), inca,work( j1 ), kd1, d( j1 )& , kd1 ) ! apply plane rotations from one side ! dependent on the the number of diagonals either ! stdlib${ii}$_slartv or stdlib${ii}$_srot is used if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_slartv( nr, ab( kd1-l, j1-kd1+l ), inca,ab( kd1-l+1, & j1-kd1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else jend = j1 + kd1*( nr-1 ) do jinc = j1, jend, kd1 call stdlib${ii}$_srot( kdm1, ab( kd, jinc-kd ), incx,ab( kd1, jinc-kd )& , incx,d( jinc ), work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i+k-1,i) ! within the band call stdlib${ii}$_slartg( ab( k-1, i ), ab( k, i ),d( i+k-1 ), work( i+k-1 & ), temp ) ab( k-1, i ) = temp ! apply rotation from the left call stdlib${ii}$_srot( k-3, ab( k-2, i+1 ), ldab-1,ab( k-1, i+1 ), ldab-1,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_slar2v( nr, ab( 1_${ik}$, j1-1 ), ab( 1_${ik}$, j1 ),ab( 2_${ik}$, j1-1 ),& inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_slartv or stdlib${ii}$_srot is used if( nr>0_${ik}$ ) then if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 if( j2+l>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_slartv( nrt, ab( l+2, j1-1 ), inca,ab( l+1,& j1 ), inca, d( j1 ),work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do j1inc = j1, j1end, kd1 call stdlib${ii}$_srot( kdm1, ab( 3_${ik}$, j1inc-1 ), 1_${ik}$,ab( 2_${ik}$, j1inc ), 1_${ik}$, & d( j1inc ),work( j1inc ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_srot( lend, ab( 3_${ik}$, last-1 ), 1_${ik}$,ab( 2_${ik}$, last ),& 1_${ik}$, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_srot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & work( j ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_srot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), work( j & ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j+kd,j-1) outside the ! band and store it in work work( j+kd ) = work( j )*ab( kd1, j ) ab( kd1, j ) = d( j )*ab( kd1, j ) end do end do loop_200 end do loop_210 end if if( kd>0_${ik}$ ) then ! copy off-diagonal elements to e do i = 1, n - 1 e( i ) = ab( 2_${ik}$, i ) end do else ! set e to zero if original matrix was diagonal do i = 1, n - 1 e( i ) = zero end do end if ! copy diagonal elements to d do i = 1, n d( i ) = ab( 1_${ik}$, i ) end do end if return end subroutine stdlib${ii}$_ssbtrd pure module subroutine stdlib${ii}$_dsbtrd( vect, uplo, n, kd, ab, ldab, d, e, q, ldq,work, info ) !! DSBTRD reduces a real symmetric band matrix A to symmetric !! tridiagonal form T by an orthogonal similarity transformation: !! Q**T * A * Q = T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldq, n ! Array Arguments real(dp), intent(inout) :: ab(ldab,*), q(ldq,*) real(dp), intent(out) :: d(*), e(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: initq, upper, wantq integer(${ik}$) :: i, i2, ibl, inca, incx, iqaend, iqb, iqend, j, j1, j1end, j1inc, j2, & jend, jin, jinc, k, kd1, kdm1, kdn, l, last, lend, nq, nr, nrt real(dp) :: temp ! Intrinsic Functions ! Executable Statements ! test the input parameters initq = stdlib_lsame( vect, 'V' ) wantq = initq .or. stdlib_lsame( vect, 'U' ) upper = stdlib_lsame( uplo, 'U' ) kd1 = kd + 1_${ik}$ kdm1 = kd - 1_${ik}$ incx = ldab - 1_${ik}$ iqend = 1_${ik}$ info = 0_${ik}$ if( .not.wantq .and. .not.stdlib_lsame( vect, 'N' ) ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab1_${ik}$ ) then ! reduce to tridiagonal form, working with upper triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ loop_90: do i = 1, n - 2 ! reduce i-th row of matrix to tridiagonal form loop_80: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_dlargv( nr, ab( 1_${ik}$, j1-1 ), inca, work( j1 ),kd1, d( j1 ), & kd1 ) ! apply rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_dlartv or stdlib${ii}$_drot is used if( nr>=2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_dlartv( nr, ab( l+1, j1-1 ), inca,ab( l, j1 ), inca, & d( j1 ),work( j1 ), kd1 ) end do else jend = j1 + ( nr-1 )*kd1 do jinc = j1, jend, kd1 call stdlib${ii}$_drot( kdm1, ab( 2_${ik}$, jinc-1 ), 1_${ik}$,ab( 1_${ik}$, jinc ), 1_${ik}$, d( & jinc ),work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+k-1) ! within the band call stdlib${ii}$_dlartg( ab( kd-k+3, i+k-2 ),ab( kd-k+2, i+k-1 ), d( i+k-& 1_${ik}$ ),work( i+k-1 ), temp ) ab( kd-k+3, i+k-2 ) = temp ! apply rotation from the right call stdlib${ii}$_drot( k-3, ab( kd-k+4, i+k-2 ), 1_${ik}$,ab( kd-k+3, i+k-1 ), 1_${ik}$,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_dlar2v( nr, ab( kd1, j1-1 ), ab( kd1, j1 ),ab( kd, & j1 ), inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the left if( nr>0_${ik}$ ) then if( 2_${ik}$*kd-1n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( kd-l, j1+l ), inca,ab( kd-& l+1, j1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do jin = j1, j1end, kd1 call stdlib${ii}$_drot( kd-1, ab( kd-1, jin+1 ), incx,ab( kd, jin+1 )& , incx,d( jin ), work( jin ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_drot( lend, ab( kd-1, last+1 ), incx,ab( kd, & last+1 ), incx, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_drot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & work( j ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_drot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), work( j & ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j-1,j+kd) outside the band ! and store it in work work( j+kd ) = work( j )*ab( 1_${ik}$, j+kd ) ab( 1_${ik}$, j+kd ) = d( j )*ab( 1_${ik}$, j+kd ) end do end do loop_80 end do loop_90 end if if( kd>0_${ik}$ ) then ! copy off-diagonal elements to e do i = 1, n - 1 e( i ) = ab( kd, i+1 ) end do else ! set e to zero if original matrix was diagonal do i = 1, n - 1 e( i ) = zero end do end if ! copy diagonal elements to d do i = 1, n d( i ) = ab( kd1, i ) end do else if( kd>1_${ik}$ ) then ! reduce to tridiagonal form, working with lower triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ loop_210: do i = 1, n - 2 ! reduce i-th column of matrix to tridiagonal form loop_200: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_dlargv( nr, ab( kd1, j1-kd1 ), inca,work( j1 ), kd1, d( j1 )& , kd1 ) ! apply plane rotations from one side ! dependent on the the number of diagonals either ! stdlib${ii}$_dlartv or stdlib${ii}$_drot is used if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_dlartv( nr, ab( kd1-l, j1-kd1+l ), inca,ab( kd1-l+1, & j1-kd1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else jend = j1 + kd1*( nr-1 ) do jinc = j1, jend, kd1 call stdlib${ii}$_drot( kdm1, ab( kd, jinc-kd ), incx,ab( kd1, jinc-kd )& , incx,d( jinc ), work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i+k-1,i) ! within the band call stdlib${ii}$_dlartg( ab( k-1, i ), ab( k, i ),d( i+k-1 ), work( i+k-1 & ), temp ) ab( k-1, i ) = temp ! apply rotation from the left call stdlib${ii}$_drot( k-3, ab( k-2, i+1 ), ldab-1,ab( k-1, i+1 ), ldab-1,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_dlar2v( nr, ab( 1_${ik}$, j1-1 ), ab( 1_${ik}$, j1 ),ab( 2_${ik}$, j1-1 ),& inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_dlartv or stdlib${ii}$_drot is used if( nr>0_${ik}$ ) then if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 if( j2+l>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_dlartv( nrt, ab( l+2, j1-1 ), inca,ab( l+1,& j1 ), inca, d( j1 ),work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do j1inc = j1, j1end, kd1 call stdlib${ii}$_drot( kdm1, ab( 3_${ik}$, j1inc-1 ), 1_${ik}$,ab( 2_${ik}$, j1inc ), 1_${ik}$, & d( j1inc ),work( j1inc ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_drot( lend, ab( 3_${ik}$, last-1 ), 1_${ik}$,ab( 2_${ik}$, last ),& 1_${ik}$, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_drot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & work( j ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_drot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), work( j & ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j+kd,j-1) outside the ! band and store it in work work( j+kd ) = work( j )*ab( kd1, j ) ab( kd1, j ) = d( j )*ab( kd1, j ) end do end do loop_200 end do loop_210 end if if( kd>0_${ik}$ ) then ! copy off-diagonal elements to e do i = 1, n - 1 e( i ) = ab( 2_${ik}$, i ) end do else ! set e to zero if original matrix was diagonal do i = 1, n - 1 e( i ) = zero end do end if ! copy diagonal elements to d do i = 1, n d( i ) = ab( 1_${ik}$, i ) end do end if return end subroutine stdlib${ii}$_dsbtrd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$sbtrd( vect, uplo, n, kd, ab, ldab, d, e, q, ldq,work, info ) !! DSBTRD: reduces a real symmetric band matrix A to symmetric !! tridiagonal form T by an orthogonal similarity transformation: !! Q**T * A * Q = T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo, vect integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldq, n ! Array Arguments real(${rk}$), intent(inout) :: ab(ldab,*), q(ldq,*) real(${rk}$), intent(out) :: d(*), e(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: initq, upper, wantq integer(${ik}$) :: i, i2, ibl, inca, incx, iqaend, iqb, iqend, j, j1, j1end, j1inc, j2, & jend, jin, jinc, k, kd1, kdm1, kdn, l, last, lend, nq, nr, nrt real(${rk}$) :: temp ! Intrinsic Functions ! Executable Statements ! test the input parameters initq = stdlib_lsame( vect, 'V' ) wantq = initq .or. stdlib_lsame( vect, 'U' ) upper = stdlib_lsame( uplo, 'U' ) kd1 = kd + 1_${ik}$ kdm1 = kd - 1_${ik}$ incx = ldab - 1_${ik}$ iqend = 1_${ik}$ info = 0_${ik}$ if( .not.wantq .and. .not.stdlib_lsame( vect, 'N' ) ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab1_${ik}$ ) then ! reduce to tridiagonal form, working with upper triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ loop_90: do i = 1, n - 2 ! reduce i-th row of matrix to tridiagonal form loop_80: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_${ri}$largv( nr, ab( 1_${ik}$, j1-1 ), inca, work( j1 ),kd1, d( j1 ), & kd1 ) ! apply rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_${ri}$lartv or stdlib${ii}$_${ri}$rot is used if( nr>=2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_${ri}$lartv( nr, ab( l+1, j1-1 ), inca,ab( l, j1 ), inca, & d( j1 ),work( j1 ), kd1 ) end do else jend = j1 + ( nr-1 )*kd1 do jinc = j1, jend, kd1 call stdlib${ii}$_${ri}$rot( kdm1, ab( 2_${ik}$, jinc-1 ), 1_${ik}$,ab( 1_${ik}$, jinc ), 1_${ik}$, d( & jinc ),work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+k-1) ! within the band call stdlib${ii}$_${ri}$lartg( ab( kd-k+3, i+k-2 ),ab( kd-k+2, i+k-1 ), d( i+k-& 1_${ik}$ ),work( i+k-1 ), temp ) ab( kd-k+3, i+k-2 ) = temp ! apply rotation from the right call stdlib${ii}$_${ri}$rot( k-3, ab( kd-k+4, i+k-2 ), 1_${ik}$,ab( kd-k+3, i+k-1 ), 1_${ik}$,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_${ri}$lar2v( nr, ab( kd1, j1-1 ), ab( kd1, j1 ),ab( kd, & j1 ), inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the left if( nr>0_${ik}$ ) then if( 2_${ik}$*kd-1n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( kd-l, j1+l ), inca,ab( kd-& l+1, j1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do jin = j1, j1end, kd1 call stdlib${ii}$_${ri}$rot( kd-1, ab( kd-1, jin+1 ), incx,ab( kd, jin+1 )& , incx,d( jin ), work( jin ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_${ri}$rot( lend, ab( kd-1, last+1 ), incx,ab( kd, & last+1 ), incx, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_${ri}$rot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & work( j ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_${ri}$rot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), work( j & ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j-1,j+kd) outside the band ! and store it in work work( j+kd ) = work( j )*ab( 1_${ik}$, j+kd ) ab( 1_${ik}$, j+kd ) = d( j )*ab( 1_${ik}$, j+kd ) end do end do loop_80 end do loop_90 end if if( kd>0_${ik}$ ) then ! copy off-diagonal elements to e do i = 1, n - 1 e( i ) = ab( kd, i+1 ) end do else ! set e to zero if original matrix was diagonal do i = 1, n - 1 e( i ) = zero end do end if ! copy diagonal elements to d do i = 1, n d( i ) = ab( kd1, i ) end do else if( kd>1_${ik}$ ) then ! reduce to tridiagonal form, working with lower triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ loop_210: do i = 1, n - 2 ! reduce i-th column of matrix to tridiagonal form loop_200: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_${ri}$largv( nr, ab( kd1, j1-kd1 ), inca,work( j1 ), kd1, d( j1 )& , kd1 ) ! apply plane rotations from one side ! dependent on the the number of diagonals either ! stdlib${ii}$_${ri}$lartv or stdlib${ii}$_${ri}$rot is used if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_${ri}$lartv( nr, ab( kd1-l, j1-kd1+l ), inca,ab( kd1-l+1, & j1-kd1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else jend = j1 + kd1*( nr-1 ) do jinc = j1, jend, kd1 call stdlib${ii}$_${ri}$rot( kdm1, ab( kd, jinc-kd ), incx,ab( kd1, jinc-kd )& , incx,d( jinc ), work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i+k-1,i) ! within the band call stdlib${ii}$_${ri}$lartg( ab( k-1, i ), ab( k, i ),d( i+k-1 ), work( i+k-1 & ), temp ) ab( k-1, i ) = temp ! apply rotation from the left call stdlib${ii}$_${ri}$rot( k-3, ab( k-2, i+1 ), ldab-1,ab( k-1, i+1 ), ldab-1,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_${ri}$lar2v( nr, ab( 1_${ik}$, j1-1 ), ab( 1_${ik}$, j1 ),ab( 2_${ik}$, j1-1 ),& inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_${ri}$lartv or stdlib${ii}$_${ri}$rot is used if( nr>0_${ik}$ ) then if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 if( j2+l>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_${ri}$lartv( nrt, ab( l+2, j1-1 ), inca,ab( l+1,& j1 ), inca, d( j1 ),work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do j1inc = j1, j1end, kd1 call stdlib${ii}$_${ri}$rot( kdm1, ab( 3_${ik}$, j1inc-1 ), 1_${ik}$,ab( 2_${ik}$, j1inc ), 1_${ik}$, & d( j1inc ),work( j1inc ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_${ri}$rot( lend, ab( 3_${ik}$, last-1 ), 1_${ik}$,ab( 2_${ik}$, last ),& 1_${ik}$, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_${ri}$rot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & work( j ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_${ri}$rot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), work( j & ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j+kd,j-1) outside the ! band and store it in work work( j+kd ) = work( j )*ab( kd1, j ) ab( kd1, j ) = d( j )*ab( kd1, j ) end do end do loop_200 end do loop_210 end if if( kd>0_${ik}$ ) then ! copy off-diagonal elements to e do i = 1, n - 1 e( i ) = ab( 2_${ik}$, i ) end do else ! set e to zero if original matrix was diagonal do i = 1, n - 1 e( i ) = zero end do end if ! copy diagonal elements to d do i = 1, n d( i ) = ab( 1_${ik}$, i ) end do end if return end subroutine stdlib${ii}$_${ri}$sbtrd #:endif #:endfor pure module subroutine stdlib${ii}$_chptrd( uplo, n, ap, d, e, tau, info ) !! CHPTRD reduces a complex Hermitian matrix A stored in packed form to !! real symmetric tridiagonal form T by a unitary similarity !! transformation: Q**H * A * Q = T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(out) :: d(*), e(*) complex(sp), intent(inout) :: ap(*) complex(sp), intent(out) :: tau(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, i1, i1i1, ii complex(sp) :: alpha, taui ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHPTRD', -info ) return end if ! quick return if possible if( n<=0 )return if( upper ) then ! reduce the upper triangle of a. ! i1 is the index in ap of a(1,i+1). i1 = n*( n-1 ) / 2_${ik}$ + 1_${ik}$ ap( i1+n-1 ) = real( ap( i1+n-1 ),KIND=sp) do i = n - 1, 1, -1 ! generate elementary reflector h(i) = i - tau * v * v**h ! to annihilate a(1:i-1,i+1) alpha = ap( i1+i-1 ) call stdlib${ii}$_clarfg( i, alpha, ap( i1 ), 1_${ik}$, taui ) e( i ) = real( alpha,KIND=sp) if( taui/=czero ) then ! apply h(i) from both sides to a(1:i,1:i) ap( i1+i-1 ) = cone ! compute y := tau * a * v storing y in tau(1:i) call stdlib${ii}$_chpmv( uplo, i, taui, ap, ap( i1 ), 1_${ik}$, czero, tau,1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**h *v) * v alpha = -chalf*taui*stdlib${ii}$_cdotc( i, tau, 1_${ik}$, ap( i1 ), 1_${ik}$ ) call stdlib${ii}$_caxpy( i, alpha, ap( i1 ), 1_${ik}$, tau, 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**h - w * v**h call stdlib${ii}$_chpr2( uplo, i, -cone, ap( i1 ), 1_${ik}$, tau, 1_${ik}$, ap ) end if ap( i1+i-1 ) = e( i ) d( i+1 ) = real( ap( i1+i ),KIND=sp) tau( i ) = taui i1 = i1 - i end do d( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=sp) else ! reduce the lower triangle of a. ii is the index in ap of ! a(i,i) and i1i1 is the index of a(i+1,i+1). ii = 1_${ik}$ ap( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=sp) do i = 1, n - 1 i1i1 = ii + n - i + 1_${ik}$ ! generate elementary reflector h(i) = i - tau * v * v**h ! to annihilate a(i+2:n,i) alpha = ap( ii+1 ) call stdlib${ii}$_clarfg( n-i, alpha, ap( ii+2 ), 1_${ik}$, taui ) e( i ) = real( alpha,KIND=sp) if( taui/=czero ) then ! apply h(i) from both sides to a(i+1:n,i+1:n) ap( ii+1 ) = cone ! compute y := tau * a * v storing y in tau(i:n-1) call stdlib${ii}$_chpmv( uplo, n-i, taui, ap( i1i1 ), ap( ii+1 ), 1_${ik}$,czero, tau( i ),& 1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**h *v) * v alpha = -chalf*taui*stdlib${ii}$_cdotc( n-i, tau( i ), 1_${ik}$, ap( ii+1 ),1_${ik}$ ) call stdlib${ii}$_caxpy( n-i, alpha, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**h - w * v**h call stdlib${ii}$_chpr2( uplo, n-i, -cone, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$,ap( i1i1 ) ) end if ap( ii+1 ) = e( i ) d( i ) = real( ap( ii ),KIND=sp) tau( i ) = taui ii = i1i1 end do d( n ) = real( ap( ii ),KIND=sp) end if return end subroutine stdlib${ii}$_chptrd pure module subroutine stdlib${ii}$_zhptrd( uplo, n, ap, d, e, tau, info ) !! ZHPTRD reduces a complex Hermitian matrix A stored in packed form to !! real symmetric tridiagonal form T by a unitary similarity !! transformation: Q**H * A * Q = T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(out) :: d(*), e(*) complex(dp), intent(inout) :: ap(*) complex(dp), intent(out) :: tau(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, i1, i1i1, ii complex(dp) :: alpha, taui ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHPTRD', -info ) return end if ! quick return if possible if( n<=0 )return if( upper ) then ! reduce the upper triangle of a. ! i1 is the index in ap of a(1,i+1). i1 = n*( n-1 ) / 2_${ik}$ + 1_${ik}$ ap( i1+n-1 ) = real( ap( i1+n-1 ),KIND=dp) do i = n - 1, 1, -1 ! generate elementary reflector h(i) = i - tau * v * v**h ! to annihilate a(1:i-1,i+1) alpha = ap( i1+i-1 ) call stdlib${ii}$_zlarfg( i, alpha, ap( i1 ), 1_${ik}$, taui ) e( i ) = real( alpha,KIND=dp) if( taui/=czero ) then ! apply h(i) from both sides to a(1:i,1:i) ap( i1+i-1 ) = cone ! compute y := tau * a * v storing y in tau(1:i) call stdlib${ii}$_zhpmv( uplo, i, taui, ap, ap( i1 ), 1_${ik}$, czero, tau,1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**h *v) * v alpha = -chalf*taui*stdlib${ii}$_zdotc( i, tau, 1_${ik}$, ap( i1 ), 1_${ik}$ ) call stdlib${ii}$_zaxpy( i, alpha, ap( i1 ), 1_${ik}$, tau, 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**h - w * v**h call stdlib${ii}$_zhpr2( uplo, i, -cone, ap( i1 ), 1_${ik}$, tau, 1_${ik}$, ap ) end if ap( i1+i-1 ) = e( i ) d( i+1 ) = real( ap( i1+i ),KIND=dp) tau( i ) = taui i1 = i1 - i end do d( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=dp) else ! reduce the lower triangle of a. ii is the index in ap of ! a(i,i) and i1i1 is the index of a(i+1,i+1). ii = 1_${ik}$ ap( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=dp) do i = 1, n - 1 i1i1 = ii + n - i + 1_${ik}$ ! generate elementary reflector h(i) = i - tau * v * v**h ! to annihilate a(i+2:n,i) alpha = ap( ii+1 ) call stdlib${ii}$_zlarfg( n-i, alpha, ap( ii+2 ), 1_${ik}$, taui ) e( i ) = real( alpha,KIND=dp) if( taui/=czero ) then ! apply h(i) from both sides to a(i+1:n,i+1:n) ap( ii+1 ) = cone ! compute y := tau * a * v storing y in tau(i:n-1) call stdlib${ii}$_zhpmv( uplo, n-i, taui, ap( i1i1 ), ap( ii+1 ), 1_${ik}$,czero, tau( i ),& 1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**h *v) * v alpha = -chalf*taui*stdlib${ii}$_zdotc( n-i, tau( i ), 1_${ik}$, ap( ii+1 ),1_${ik}$ ) call stdlib${ii}$_zaxpy( n-i, alpha, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**h - w * v**h call stdlib${ii}$_zhpr2( uplo, n-i, -cone, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$,ap( i1i1 ) ) end if ap( ii+1 ) = e( i ) d( i ) = real( ap( ii ),KIND=dp) tau( i ) = taui ii = i1i1 end do d( n ) = real( ap( ii ),KIND=dp) end if return end subroutine stdlib${ii}$_zhptrd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hptrd( uplo, n, ap, d, e, tau, info ) !! ZHPTRD: reduces a complex Hermitian matrix A stored in packed form to !! real symmetric tridiagonal form T by a unitary similarity !! transformation: Q**H * A * Q = T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(${ck}$), intent(out) :: d(*), e(*) complex(${ck}$), intent(inout) :: ap(*) complex(${ck}$), intent(out) :: tau(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, i1, i1i1, ii complex(${ck}$) :: alpha, taui ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHPTRD', -info ) return end if ! quick return if possible if( n<=0 )return if( upper ) then ! reduce the upper triangle of a. ! i1 is the index in ap of a(1,i+1). i1 = n*( n-1 ) / 2_${ik}$ + 1_${ik}$ ap( i1+n-1 ) = real( ap( i1+n-1 ),KIND=${ck}$) do i = n - 1, 1, -1 ! generate elementary reflector h(i) = i - tau * v * v**h ! to annihilate a(1:i-1,i+1) alpha = ap( i1+i-1 ) call stdlib${ii}$_${ci}$larfg( i, alpha, ap( i1 ), 1_${ik}$, taui ) e( i ) = real( alpha,KIND=${ck}$) if( taui/=czero ) then ! apply h(i) from both sides to a(1:i,1:i) ap( i1+i-1 ) = cone ! compute y := tau * a * v storing y in tau(1:i) call stdlib${ii}$_${ci}$hpmv( uplo, i, taui, ap, ap( i1 ), 1_${ik}$, czero, tau,1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**h *v) * v alpha = -chalf*taui*stdlib${ii}$_${ci}$dotc( i, tau, 1_${ik}$, ap( i1 ), 1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( i, alpha, ap( i1 ), 1_${ik}$, tau, 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**h - w * v**h call stdlib${ii}$_${ci}$hpr2( uplo, i, -cone, ap( i1 ), 1_${ik}$, tau, 1_${ik}$, ap ) end if ap( i1+i-1 ) = e( i ) d( i+1 ) = real( ap( i1+i ),KIND=${ck}$) tau( i ) = taui i1 = i1 - i end do d( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=${ck}$) else ! reduce the lower triangle of a. ii is the index in ap of ! a(i,i) and i1i1 is the index of a(i+1,i+1). ii = 1_${ik}$ ap( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=${ck}$) do i = 1, n - 1 i1i1 = ii + n - i + 1_${ik}$ ! generate elementary reflector h(i) = i - tau * v * v**h ! to annihilate a(i+2:n,i) alpha = ap( ii+1 ) call stdlib${ii}$_${ci}$larfg( n-i, alpha, ap( ii+2 ), 1_${ik}$, taui ) e( i ) = real( alpha,KIND=${ck}$) if( taui/=czero ) then ! apply h(i) from both sides to a(i+1:n,i+1:n) ap( ii+1 ) = cone ! compute y := tau * a * v storing y in tau(i:n-1) call stdlib${ii}$_${ci}$hpmv( uplo, n-i, taui, ap( i1i1 ), ap( ii+1 ), 1_${ik}$,czero, tau( i ),& 1_${ik}$ ) ! compute w := y - 1/2 * tau * (y**h *v) * v alpha = -chalf*taui*stdlib${ii}$_${ci}$dotc( n-i, tau( i ), 1_${ik}$, ap( ii+1 ),1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( n-i, alpha, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$ ) ! apply the transformation as a rank-2 update: ! a := a - v * w**h - w * v**h call stdlib${ii}$_${ci}$hpr2( uplo, n-i, -cone, ap( ii+1 ), 1_${ik}$, tau( i ), 1_${ik}$,ap( i1i1 ) ) end if ap( ii+1 ) = e( i ) d( i ) = real( ap( ii ),KIND=${ck}$) tau( i ) = taui ii = i1i1 end do d( n ) = real( ap( ii ),KIND=${ck}$) end if return end subroutine stdlib${ii}$_${ci}$hptrd #:endif #:endfor pure module subroutine stdlib${ii}$_cupgtr( uplo, n, ap, tau, q, ldq, work, info ) !! CUPGTR generates a complex unitary matrix Q which is defined as the !! product of n-1 elementary reflectors H(i) of order n, as returned by !! CHPTRD using packed storage: !! if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), !! if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq, n ! Array Arguments complex(sp), intent(in) :: ap(*), tau(*) complex(sp), intent(out) :: q(ldq,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, ij, j ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldq1_${ik}$ ) then ! generate q(2:n,2:n) call stdlib${ii}$_cung2r( n-1, n-1, n-1, q( 2_${ik}$, 2_${ik}$ ), ldq, tau, work,iinfo ) end if end if return end subroutine stdlib${ii}$_cupgtr pure module subroutine stdlib${ii}$_zupgtr( uplo, n, ap, tau, q, ldq, work, info ) !! ZUPGTR generates a complex unitary matrix Q which is defined as the !! product of n-1 elementary reflectors H(i) of order n, as returned by !! ZHPTRD using packed storage: !! if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), !! if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq, n ! Array Arguments complex(dp), intent(in) :: ap(*), tau(*) complex(dp), intent(out) :: q(ldq,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, ij, j ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldq1_${ik}$ ) then ! generate q(2:n,2:n) call stdlib${ii}$_zung2r( n-1, n-1, n-1, q( 2_${ik}$, 2_${ik}$ ), ldq, tau, work,iinfo ) end if end if return end subroutine stdlib${ii}$_zupgtr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$upgtr( uplo, n, ap, tau, q, ldq, work, info ) !! ZUPGTR: generates a complex unitary matrix Q which is defined as the !! product of n-1 elementary reflectors H(i) of order n, as returned by !! ZHPTRD using packed storage: !! if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), !! if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq, n ! Array Arguments complex(${ck}$), intent(in) :: ap(*), tau(*) complex(${ck}$), intent(out) :: q(ldq,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, iinfo, ij, j ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldq1_${ik}$ ) then ! generate q(2:n,2:n) call stdlib${ii}$_${ci}$ung2r( n-1, n-1, n-1, q( 2_${ik}$, 2_${ik}$ ), ldq, tau, work,iinfo ) end if end if return end subroutine stdlib${ii}$_${ci}$upgtr #:endif #:endfor pure module subroutine stdlib${ii}$_cupmtr( side, uplo, trans, m, n, ap, tau, c, ldc, work,info ) !! CUPMTR overwrites the general complex M-by-N matrix C with !! SIDE = 'L' SIDE = 'R' !! TRANS = 'N': Q * C C * Q !! TRANS = 'C': Q**H * C C * Q**H !! where Q is a complex unitary matrix of order nq, with nq = m if !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of !! nq-1 elementary reflectors, as returned by CHPTRD using packed !! storage: !! if UPLO = 'U', Q = H(nq-1) . . . H(2) H(1); !! if UPLO = 'L', Q = H(1) H(2) . . . H(nq-1). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc, m, n ! Array Arguments complex(sp), intent(inout) :: ap(*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: forwrd, left, notran, upper integer(${ik}$) :: i, i1, i2, i3, ic, ii, jc, mi, ni, nq complex(sp) :: aii, taui ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ left = stdlib_lsame( side, 'L' ) notran = stdlib_lsame( trans, 'N' ) upper = stdlib_lsame( uplo, 'U' ) ! nq is the order of q if( left ) then nq = m else nq = n end if if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldc1_${ik}$ ) then ! reduce to complex hermitian tridiagonal form, working with ! the upper triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ ab( kd1, 1_${ik}$ ) = real( ab( kd1, 1_${ik}$ ),KIND=sp) loop_90: do i = 1, n - 2 ! reduce i-th row of matrix to tridiagonal form loop_80: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_clargv( nr, ab( 1_${ik}$, j1-1 ), inca, work( j1 ),kd1, d( j1 ), & kd1 ) ! apply rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_clartv or stdlib${ii}$_crot is used if( nr>=2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_clartv( nr, ab( l+1, j1-1 ), inca,ab( l, j1 ), inca, & d( j1 ),work( j1 ), kd1 ) end do else jend = j1 + ( nr-1 )*kd1 do jinc = j1, jend, kd1 call stdlib${ii}$_crot( kdm1, ab( 2_${ik}$, jinc-1 ), 1_${ik}$,ab( 1_${ik}$, jinc ), 1_${ik}$, d( & jinc ),work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+k-1) ! within the band call stdlib${ii}$_clartg( ab( kd-k+3, i+k-2 ),ab( kd-k+2, i+k-1 ), d( i+k-& 1_${ik}$ ),work( i+k-1 ), temp ) ab( kd-k+3, i+k-2 ) = temp ! apply rotation from the right call stdlib${ii}$_crot( k-3, ab( kd-k+4, i+k-2 ), 1_${ik}$,ab( kd-k+3, i+k-1 ), 1_${ik}$,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_clar2v( nr, ab( kd1, j1-1 ), ab( kd1, j1 ),ab( kd, & j1 ), inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the left if( nr>0_${ik}$ ) then call stdlib${ii}$_clacgv( nr, work( j1 ), kd1 ) if( 2_${ik}$*kd-1n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( kd-l, j1+l ), inca,ab( kd-& l+1, j1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do jin = j1, j1end, kd1 call stdlib${ii}$_crot( kd-1, ab( kd-1, jin+1 ), incx,ab( kd, jin+1 )& , incx,d( jin ), work( jin ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_crot( lend, ab( kd-1, last+1 ), incx,ab( kd, & last+1 ), incx, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_crot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & conjg( work( j ) ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_crot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), conjg( & work( j ) ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j-1,j+kd) outside the band ! and store it in work work( j+kd ) = work( j )*ab( 1_${ik}$, j+kd ) ab( 1_${ik}$, j+kd ) = d( j )*ab( 1_${ik}$, j+kd ) end do end do loop_80 end do loop_90 end if if( kd>0_${ik}$ ) then ! make off-diagonal elements real and copy them to e do i = 1, n - 1 t = ab( kd, i+1 ) abst = abs( t ) ab( kd, i+1 ) = abst e( i ) = abst if( abst/=zero ) then t = t / abst else t = cone end if if( i1_${ik}$ ) then ! reduce to complex hermitian tridiagonal form, working with ! the lower triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ ab( 1_${ik}$, 1_${ik}$ ) = real( ab( 1_${ik}$, 1_${ik}$ ),KIND=sp) loop_210: do i = 1, n - 2 ! reduce i-th column of matrix to tridiagonal form loop_200: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_clargv( nr, ab( kd1, j1-kd1 ), inca,work( j1 ), kd1, d( j1 )& , kd1 ) ! apply plane rotations from one side ! dependent on the the number of diagonals either ! stdlib${ii}$_clartv or stdlib${ii}$_crot is used if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_clartv( nr, ab( kd1-l, j1-kd1+l ), inca,ab( kd1-l+1, & j1-kd1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else jend = j1 + kd1*( nr-1 ) do jinc = j1, jend, kd1 call stdlib${ii}$_crot( kdm1, ab( kd, jinc-kd ), incx,ab( kd1, jinc-kd )& , incx,d( jinc ), work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i+k-1,i) ! within the band call stdlib${ii}$_clartg( ab( k-1, i ), ab( k, i ),d( i+k-1 ), work( i+k-1 & ), temp ) ab( k-1, i ) = temp ! apply rotation from the left call stdlib${ii}$_crot( k-3, ab( k-2, i+1 ), ldab-1,ab( k-1, i+1 ), ldab-1,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_clar2v( nr, ab( 1_${ik}$, j1-1 ), ab( 1_${ik}$, j1 ),ab( 2_${ik}$, j1-1 ),& inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_clartv or stdlib${ii}$_crot is used if( nr>0_${ik}$ ) then call stdlib${ii}$_clacgv( nr, work( j1 ), kd1 ) if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 if( j2+l>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_clartv( nrt, ab( l+2, j1-1 ), inca,ab( l+1,& j1 ), inca, d( j1 ),work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do j1inc = j1, j1end, kd1 call stdlib${ii}$_crot( kdm1, ab( 3_${ik}$, j1inc-1 ), 1_${ik}$,ab( 2_${ik}$, j1inc ), 1_${ik}$, & d( j1inc ),work( j1inc ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_crot( lend, ab( 3_${ik}$, last-1 ), 1_${ik}$,ab( 2_${ik}$, last ),& 1_${ik}$, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_crot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & work( j ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_crot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), work( j & ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j+kd,j-1) outside the ! band and store it in work work( j+kd ) = work( j )*ab( kd1, j ) ab( kd1, j ) = d( j )*ab( kd1, j ) end do end do loop_200 end do loop_210 end if if( kd>0_${ik}$ ) then ! make off-diagonal elements real and copy them to e do i = 1, n - 1 t = ab( 2_${ik}$, i ) abst = abs( t ) ab( 2_${ik}$, i ) = abst e( i ) = abst if( abst/=zero ) then t = t / abst else t = cone end if if( i1_${ik}$ ) then ! reduce to complex hermitian tridiagonal form, working with ! the upper triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ ab( kd1, 1_${ik}$ ) = real( ab( kd1, 1_${ik}$ ),KIND=dp) loop_90: do i = 1, n - 2 ! reduce i-th row of matrix to tridiagonal form loop_80: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_zlargv( nr, ab( 1_${ik}$, j1-1 ), inca, work( j1 ),kd1, d( j1 ), & kd1 ) ! apply rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_zlartv or stdlib${ii}$_zrot is used if( nr>=2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_zlartv( nr, ab( l+1, j1-1 ), inca,ab( l, j1 ), inca, & d( j1 ),work( j1 ), kd1 ) end do else jend = j1 + ( nr-1 )*kd1 do jinc = j1, jend, kd1 call stdlib${ii}$_zrot( kdm1, ab( 2_${ik}$, jinc-1 ), 1_${ik}$,ab( 1_${ik}$, jinc ), 1_${ik}$, d( & jinc ),work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+k-1) ! within the band call stdlib${ii}$_zlartg( ab( kd-k+3, i+k-2 ),ab( kd-k+2, i+k-1 ), d( i+k-& 1_${ik}$ ),work( i+k-1 ), temp ) ab( kd-k+3, i+k-2 ) = temp ! apply rotation from the right call stdlib${ii}$_zrot( k-3, ab( kd-k+4, i+k-2 ), 1_${ik}$,ab( kd-k+3, i+k-1 ), 1_${ik}$,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_zlar2v( nr, ab( kd1, j1-1 ), ab( kd1, j1 ),ab( kd, & j1 ), inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the left if( nr>0_${ik}$ ) then call stdlib${ii}$_zlacgv( nr, work( j1 ), kd1 ) if( 2_${ik}$*kd-1n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( kd-l, j1+l ), inca,ab( kd-& l+1, j1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do jin = j1, j1end, kd1 call stdlib${ii}$_zrot( kd-1, ab( kd-1, jin+1 ), incx,ab( kd, jin+1 )& , incx,d( jin ), work( jin ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_zrot( lend, ab( kd-1, last+1 ), incx,ab( kd, & last+1 ), incx, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_zrot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & conjg( work( j ) ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_zrot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), conjg( & work( j ) ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j-1,j+kd) outside the band ! and store it in work work( j+kd ) = work( j )*ab( 1_${ik}$, j+kd ) ab( 1_${ik}$, j+kd ) = d( j )*ab( 1_${ik}$, j+kd ) end do end do loop_80 end do loop_90 end if if( kd>0_${ik}$ ) then ! make off-diagonal elements real and copy them to e do i = 1, n - 1 t = ab( kd, i+1 ) abst = abs( t ) ab( kd, i+1 ) = abst e( i ) = abst if( abst/=zero ) then t = t / abst else t = cone end if if( i1_${ik}$ ) then ! reduce to complex hermitian tridiagonal form, working with ! the lower triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ ab( 1_${ik}$, 1_${ik}$ ) = real( ab( 1_${ik}$, 1_${ik}$ ),KIND=dp) loop_210: do i = 1, n - 2 ! reduce i-th column of matrix to tridiagonal form loop_200: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_zlargv( nr, ab( kd1, j1-kd1 ), inca,work( j1 ), kd1, d( j1 )& , kd1 ) ! apply plane rotations from one side ! dependent on the the number of diagonals either ! stdlib${ii}$_zlartv or stdlib${ii}$_zrot is used if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_zlartv( nr, ab( kd1-l, j1-kd1+l ), inca,ab( kd1-l+1, & j1-kd1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else jend = j1 + kd1*( nr-1 ) do jinc = j1, jend, kd1 call stdlib${ii}$_zrot( kdm1, ab( kd, jinc-kd ), incx,ab( kd1, jinc-kd )& , incx,d( jinc ), work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i+k-1,i) ! within the band call stdlib${ii}$_zlartg( ab( k-1, i ), ab( k, i ),d( i+k-1 ), work( i+k-1 & ), temp ) ab( k-1, i ) = temp ! apply rotation from the left call stdlib${ii}$_zrot( k-3, ab( k-2, i+1 ), ldab-1,ab( k-1, i+1 ), ldab-1,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_zlar2v( nr, ab( 1_${ik}$, j1-1 ), ab( 1_${ik}$, j1 ),ab( 2_${ik}$, j1-1 ),& inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_zlartv or stdlib${ii}$_zrot is used if( nr>0_${ik}$ ) then call stdlib${ii}$_zlacgv( nr, work( j1 ), kd1 ) if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 if( j2+l>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_zlartv( nrt, ab( l+2, j1-1 ), inca,ab( l+1,& j1 ), inca, d( j1 ),work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do j1inc = j1, j1end, kd1 call stdlib${ii}$_zrot( kdm1, ab( 3_${ik}$, j1inc-1 ), 1_${ik}$,ab( 2_${ik}$, j1inc ), 1_${ik}$, & d( j1inc ),work( j1inc ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_zrot( lend, ab( 3_${ik}$, last-1 ), 1_${ik}$,ab( 2_${ik}$, last ),& 1_${ik}$, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_zrot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & work( j ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_zrot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), work( j & ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j+kd,j-1) outside the ! band and store it in work work( j+kd ) = work( j )*ab( kd1, j ) ab( kd1, j ) = d( j )*ab( kd1, j ) end do end do loop_200 end do loop_210 end if if( kd>0_${ik}$ ) then ! make off-diagonal elements real and copy them to e do i = 1, n - 1 t = ab( 2_${ik}$, i ) abst = abs( t ) ab( 2_${ik}$, i ) = abst e( i ) = abst if( abst/=zero ) then t = t / abst else t = cone end if if( i1_${ik}$ ) then ! reduce to complex hermitian tridiagonal form, working with ! the upper triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ ab( kd1, 1_${ik}$ ) = real( ab( kd1, 1_${ik}$ ),KIND=${ck}$) loop_90: do i = 1, n - 2 ! reduce i-th row of matrix to tridiagonal form loop_80: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_${ci}$largv( nr, ab( 1_${ik}$, j1-1 ), inca, work( j1 ),kd1, d( j1 ), & kd1 ) ! apply rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_${ci}$lartv or stdlib${ii}$_${ci}$rot is used if( nr>=2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_${ci}$lartv( nr, ab( l+1, j1-1 ), inca,ab( l, j1 ), inca, & d( j1 ),work( j1 ), kd1 ) end do else jend = j1 + ( nr-1 )*kd1 do jinc = j1, jend, kd1 call stdlib${ii}$_${ci}$rot( kdm1, ab( 2_${ik}$, jinc-1 ), 1_${ik}$,ab( 1_${ik}$, jinc ), 1_${ik}$, d( & jinc ),work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i,i+k-1) ! within the band call stdlib${ii}$_${ci}$lartg( ab( kd-k+3, i+k-2 ),ab( kd-k+2, i+k-1 ), d( i+k-& 1_${ik}$ ),work( i+k-1 ), temp ) ab( kd-k+3, i+k-2 ) = temp ! apply rotation from the right call stdlib${ii}$_${ci}$rot( k-3, ab( kd-k+4, i+k-2 ), 1_${ik}$,ab( kd-k+3, i+k-1 ), 1_${ik}$,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_${ci}$lar2v( nr, ab( kd1, j1-1 ), ab( kd1, j1 ),ab( kd, & j1 ), inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the left if( nr>0_${ik}$ ) then call stdlib${ii}$_${ci}$lacgv( nr, work( j1 ), kd1 ) if( 2_${ik}$*kd-1n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( kd-l, j1+l ), inca,ab( kd-& l+1, j1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do jin = j1, j1end, kd1 call stdlib${ii}$_${ci}$rot( kd-1, ab( kd-1, jin+1 ), incx,ab( kd, jin+1 )& , incx,d( jin ), work( jin ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_${ci}$rot( lend, ab( kd-1, last+1 ), incx,ab( kd, & last+1 ), incx, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_${ci}$rot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & conjg( work( j ) ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_${ci}$rot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), conjg( & work( j ) ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j-1,j+kd) outside the band ! and store it in work work( j+kd ) = work( j )*ab( 1_${ik}$, j+kd ) ab( 1_${ik}$, j+kd ) = d( j )*ab( 1_${ik}$, j+kd ) end do end do loop_80 end do loop_90 end if if( kd>0_${ik}$ ) then ! make off-diagonal elements real and copy them to e do i = 1, n - 1 t = ab( kd, i+1 ) abst = abs( t ) ab( kd, i+1 ) = abst e( i ) = abst if( abst/=zero ) then t = t / abst else t = cone end if if( i1_${ik}$ ) then ! reduce to complex hermitian tridiagonal form, working with ! the lower triangle nr = 0_${ik}$ j1 = kdn + 2_${ik}$ j2 = 1_${ik}$ ab( 1_${ik}$, 1_${ik}$ ) = real( ab( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) loop_210: do i = 1, n - 2 ! reduce i-th column of matrix to tridiagonal form loop_200: do k = kdn + 1, 2, -1 j1 = j1 + kdn j2 = j2 + kdn if( nr>0_${ik}$ ) then ! generate plane rotations to annihilate nonzero ! elements which have been created outside the band call stdlib${ii}$_${ci}$largv( nr, ab( kd1, j1-kd1 ), inca,work( j1 ), kd1, d( j1 )& , kd1 ) ! apply plane rotations from one side ! dependent on the the number of diagonals either ! stdlib${ii}$_${ci}$lartv or stdlib${ii}$_${ci}$rot is used if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 call stdlib${ii}$_${ci}$lartv( nr, ab( kd1-l, j1-kd1+l ), inca,ab( kd1-l+1, & j1-kd1+l ), inca,d( j1 ), work( j1 ), kd1 ) end do else jend = j1 + kd1*( nr-1 ) do jinc = j1, jend, kd1 call stdlib${ii}$_${ci}$rot( kdm1, ab( kd, jinc-kd ), incx,ab( kd1, jinc-kd )& , incx,d( jinc ), work( jinc ) ) end do end if end if if( k>2_${ik}$ ) then if( k<=n-i+1 ) then ! generate plane rotation to annihilate a(i+k-1,i) ! within the band call stdlib${ii}$_${ci}$lartg( ab( k-1, i ), ab( k, i ),d( i+k-1 ), work( i+k-1 & ), temp ) ab( k-1, i ) = temp ! apply rotation from the left call stdlib${ii}$_${ci}$rot( k-3, ab( k-2, i+1 ), ldab-1,ab( k-1, i+1 ), ldab-1,& d( i+k-1 ),work( i+k-1 ) ) end if nr = nr + 1_${ik}$ j1 = j1 - kdn - 1_${ik}$ end if ! apply plane rotations from both sides to diagonal ! blocks if( nr>0_${ik}$ )call stdlib${ii}$_${ci}$lar2v( nr, ab( 1_${ik}$, j1-1 ), ab( 1_${ik}$, j1 ),ab( 2_${ik}$, j1-1 ),& inca, d( j1 ),work( j1 ), kd1 ) ! apply plane rotations from the right ! dependent on the the number of diagonals either ! stdlib${ii}$_${ci}$lartv or stdlib${ii}$_${ci}$rot is used if( nr>0_${ik}$ ) then call stdlib${ii}$_${ci}$lacgv( nr, work( j1 ), kd1 ) if( nr>2_${ik}$*kd-1 ) then do l = 1, kd - 1 if( j2+l>n ) then nrt = nr - 1_${ik}$ else nrt = nr end if if( nrt>0_${ik}$ )call stdlib${ii}$_${ci}$lartv( nrt, ab( l+2, j1-1 ), inca,ab( l+1,& j1 ), inca, d( j1 ),work( j1 ), kd1 ) end do else j1end = j1 + kd1*( nr-2 ) if( j1end>=j1 ) then do j1inc = j1, j1end, kd1 call stdlib${ii}$_${ci}$rot( kdm1, ab( 3_${ik}$, j1inc-1 ), 1_${ik}$,ab( 2_${ik}$, j1inc ), 1_${ik}$, & d( j1inc ),work( j1inc ) ) end do end if lend = min( kdm1, n-j2 ) last = j1end + kd1 if( lend>0_${ik}$ )call stdlib${ii}$_${ci}$rot( lend, ab( 3_${ik}$, last-1 ), 1_${ik}$,ab( 2_${ik}$, last ),& 1_${ik}$, d( last ),work( last ) ) end if end if if( wantq ) then ! accumulate product of plane rotations in q if( initq ) then ! take advantage of the fact that q was ! initially the identity matrix iqend = max( iqend, j2 ) i2 = max( 0_${ik}$, k-3 ) iqaend = 1_${ik}$ + i*kd if( k==2_${ik}$ )iqaend = iqaend + kd iqaend = min( iqaend, iqend ) do j = j1, j2, kd1 ibl = i - i2 / kdm1 i2 = i2 + 1_${ik}$ iqb = max( 1_${ik}$, j-ibl ) nq = 1_${ik}$ + iqaend - iqb iqaend = min( iqaend+kd, iqend ) call stdlib${ii}$_${ci}$rot( nq, q( iqb, j-1 ), 1_${ik}$, q( iqb, j ),1_${ik}$, d( j ), & work( j ) ) end do else do j = j1, j2, kd1 call stdlib${ii}$_${ci}$rot( n, q( 1_${ik}$, j-1 ), 1_${ik}$, q( 1_${ik}$, j ), 1_${ik}$,d( j ), work( j & ) ) end do end if end if if( j2+kdn>n ) then ! adjust j2 to keep within the bounds of the matrix nr = nr - 1_${ik}$ j2 = j2 - kdn - 1_${ik}$ end if do j = j1, j2, kd1 ! create nonzero element a(j+kd,j-1) outside the ! band and store it in work work( j+kd ) = work( j )*ab( kd1, j ) ab( kd1, j ) = d( j )*ab( kd1, j ) end do end do loop_200 end do loop_210 end if if( kd>0_${ik}$ ) then ! make off-diagonal elements real and copy them to e do i = 1, n - 1 t = ab( 2_${ik}$, i ) abst = abs( t ) ab( 2_${ik}$, i ) = abst e( i ) = abst if( abst/=zero ) then t = t / abst else t = cone end if if( i0_${ik}$ ) then i = 1_${ik}$ + (lastv-1) * incv else i = 1_${ik}$ end if ! look for the last non-zero row in v. do while( lastv>0 .and. v( i )==zero ) lastv = lastv - 1_${ik}$ i = i - incv end do if( applyleft ) then ! scan for the last non-zero column in c(1:lastv,:). lastc = stdlib${ii}$_ilaslc(lastv, n, c, ldc) else ! scan for the last non-zero row in c(:,1:lastv). lastc = stdlib${ii}$_ilaslr(m, lastv, c, ldc) end if end if ! note that lastc.eq.0_sp renders the blas operations null; no special ! case is needed at this level. if( applyleft ) then ! form h * c if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastv,1:lastc)**t * v(1:lastv,1) call stdlib${ii}$_sgemv( 'TRANSPOSE', lastv, lastc, one, c, ldc, v, incv,zero, work, 1_${ik}$ & ) ! c(1:lastv,1:lastc) := c(...) - v(1:lastv,1) * w(1:lastc,1)**t call stdlib${ii}$_sger( lastv, lastc, -tau, v, incv, work, 1_${ik}$, c, ldc ) end if else ! form c * h if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastc,1:lastv) * v(1:lastv,1) call stdlib${ii}$_sgemv( 'NO TRANSPOSE', lastc, lastv, one, c, ldc,v, incv, zero, work,& 1_${ik}$ ) ! c(1:lastc,1:lastv) := c(...) - w(1:lastc,1) * v(1:lastv,1)**t call stdlib${ii}$_sger( lastc, lastv, -tau, work, 1_${ik}$, v, incv, c, ldc ) end if end if return end subroutine stdlib${ii}$_slarf pure module subroutine stdlib${ii}$_dlarf( side, m, n, v, incv, tau, c, ldc, work ) !! DLARF applies a real elementary reflector H to a real m by n matrix !! C, from either the left or the right. H is represented in the form !! H = I - tau * v * v**T !! where tau is a real scalar and v is a real vector. !! If tau = 0, then H is taken to be the unit matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side integer(${ik}$), intent(in) :: incv, ldc, m, n real(dp), intent(in) :: tau ! Array Arguments real(dp), intent(inout) :: c(ldc,*) real(dp), intent(in) :: v(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: applyleft integer(${ik}$) :: i, lastv, lastc ! Executable Statements applyleft = stdlib_lsame( side, 'L' ) lastv = 0_${ik}$ lastc = 0_${ik}$ if( tau/=zero ) then ! set up variables for scanning v. lastv begins pointing to the end ! of v. if( applyleft ) then lastv = m else lastv = n end if if( incv>0_${ik}$ ) then i = 1_${ik}$ + (lastv-1) * incv else i = 1_${ik}$ end if ! look for the last non-zero row in v. do while( lastv>0 .and. v( i )==zero ) lastv = lastv - 1_${ik}$ i = i - incv end do if( applyleft ) then ! scan for the last non-zero column in c(1:lastv,:). lastc = stdlib${ii}$_iladlc(lastv, n, c, ldc) else ! scan for the last non-zero row in c(:,1:lastv). lastc = stdlib${ii}$_iladlr(m, lastv, c, ldc) end if end if ! note that lastc.eq.0_dp renders the blas operations null; no special ! case is needed at this level. if( applyleft ) then ! form h * c if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastv,1:lastc)**t * v(1:lastv,1) call stdlib${ii}$_dgemv( 'TRANSPOSE', lastv, lastc, one, c, ldc, v, incv,zero, work, 1_${ik}$ & ) ! c(1:lastv,1:lastc) := c(...) - v(1:lastv,1) * w(1:lastc,1)**t call stdlib${ii}$_dger( lastv, lastc, -tau, v, incv, work, 1_${ik}$, c, ldc ) end if else ! form c * h if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastc,1:lastv) * v(1:lastv,1) call stdlib${ii}$_dgemv( 'NO TRANSPOSE', lastc, lastv, one, c, ldc,v, incv, zero, work,& 1_${ik}$ ) ! c(1:lastc,1:lastv) := c(...) - w(1:lastc,1) * v(1:lastv,1)**t call stdlib${ii}$_dger( lastc, lastv, -tau, work, 1_${ik}$, v, incv, c, ldc ) end if end if return end subroutine stdlib${ii}$_dlarf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larf( side, m, n, v, incv, tau, c, ldc, work ) !! DLARF: applies a real elementary reflector H to a real m by n matrix !! C, from either the left or the right. H is represented in the form !! H = I - tau * v * v**T !! where tau is a real scalar and v is a real vector. !! If tau = 0, then H is taken to be the unit matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side integer(${ik}$), intent(in) :: incv, ldc, m, n real(${rk}$), intent(in) :: tau ! Array Arguments real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(in) :: v(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: applyleft integer(${ik}$) :: i, lastv, lastc ! Executable Statements applyleft = stdlib_lsame( side, 'L' ) lastv = 0_${ik}$ lastc = 0_${ik}$ if( tau/=zero ) then ! set up variables for scanning v. lastv begins pointing to the end ! of v. if( applyleft ) then lastv = m else lastv = n end if if( incv>0_${ik}$ ) then i = 1_${ik}$ + (lastv-1) * incv else i = 1_${ik}$ end if ! look for the last non-zero row in v. do while( lastv>0 .and. v( i )==zero ) lastv = lastv - 1_${ik}$ i = i - incv end do if( applyleft ) then ! scan for the last non-zero column in c(1:lastv,:). lastc = stdlib${ii}$_ila${ri}$lc(lastv, n, c, ldc) else ! scan for the last non-zero row in c(:,1:lastv). lastc = stdlib${ii}$_ila${ri}$lr(m, lastv, c, ldc) end if end if ! note that lastc.eq.0_${rk}$ renders the blas operations null; no special ! case is needed at this level. if( applyleft ) then ! form h * c if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastv,1:lastc)**t * v(1:lastv,1) call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', lastv, lastc, one, c, ldc, v, incv,zero, work, 1_${ik}$ & ) ! c(1:lastv,1:lastc) := c(...) - v(1:lastv,1) * w(1:lastc,1)**t call stdlib${ii}$_${ri}$ger( lastv, lastc, -tau, v, incv, work, 1_${ik}$, c, ldc ) end if else ! form c * h if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastc,1:lastv) * v(1:lastv,1) call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', lastc, lastv, one, c, ldc,v, incv, zero, work,& 1_${ik}$ ) ! c(1:lastc,1:lastv) := c(...) - w(1:lastc,1) * v(1:lastv,1)**t call stdlib${ii}$_${ri}$ger( lastc, lastv, -tau, work, 1_${ik}$, v, incv, c, ldc ) end if end if return end subroutine stdlib${ii}$_${ri}$larf #:endif #:endfor pure module subroutine stdlib${ii}$_clarf( side, m, n, v, incv, tau, c, ldc, work ) !! CLARF applies a complex elementary reflector H to a complex M-by-N !! matrix C, from either the left or the right. H is represented in the !! form !! H = I - tau * v * v**H !! where tau is a complex scalar and v is a complex vector. !! If tau = 0, then H is taken to be the unit matrix. !! To apply H**H (the conjugate transpose of H), supply conjg(tau) instead !! tau. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side integer(${ik}$), intent(in) :: incv, ldc, m, n complex(sp), intent(in) :: tau ! Array Arguments complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(in) :: v(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: applyleft integer(${ik}$) :: i, lastv, lastc ! Executable Statements applyleft = stdlib_lsame( side, 'L' ) lastv = 0_${ik}$ lastc = 0_${ik}$ if( tau/=czero ) then ! set up variables for scanning v. lastv begins pointing to the end ! of v. if( applyleft ) then lastv = m else lastv = n end if if( incv>0_${ik}$ ) then i = 1_${ik}$ + (lastv-1) * incv else i = 1_${ik}$ end if ! look for the last non-czero row in v. do while( lastv>0 .and. v( i )==czero ) lastv = lastv - 1_${ik}$ i = i - incv end do if( applyleft ) then ! scan for the last non-czero column in c(1:lastv,:). lastc = stdlib${ii}$_ilaclc(lastv, n, c, ldc) else ! scan for the last non-czero row in c(:,1:lastv). lastc = stdlib${ii}$_ilaclr(m, lastv, c, ldc) end if end if ! note that lastc.eq.0_sp renders the blas operations null; no special ! case is needed at this level. if( applyleft ) then ! form h * c if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastv,1:lastc)**h * v(1:lastv,1) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', lastv, lastc, cone,c, ldc, v, incv, & czero, work, 1_${ik}$ ) ! c(1:lastv,1:lastc) := c(...) - v(1:lastv,1) * w(1:lastc,1)**h call stdlib${ii}$_cgerc( lastv, lastc, -tau, v, incv, work, 1_${ik}$, c, ldc ) end if else ! form c * h if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastc,1:lastv) * v(1:lastv,1) call stdlib${ii}$_cgemv( 'NO TRANSPOSE', lastc, lastv, cone, c, ldc,v, incv, czero, & work, 1_${ik}$ ) ! c(1:lastc,1:lastv) := c(...) - w(1:lastc,1) * v(1:lastv,1)**h call stdlib${ii}$_cgerc( lastc, lastv, -tau, work, 1_${ik}$, v, incv, c, ldc ) end if end if return end subroutine stdlib${ii}$_clarf pure module subroutine stdlib${ii}$_zlarf( side, m, n, v, incv, tau, c, ldc, work ) !! ZLARF applies a complex elementary reflector H to a complex M-by-N !! matrix C, from either the left or the right. H is represented in the !! form !! H = I - tau * v * v**H !! where tau is a complex scalar and v is a complex vector. !! If tau = 0, then H is taken to be the unit matrix. !! To apply H**H, supply conjg(tau) instead !! tau. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side integer(${ik}$), intent(in) :: incv, ldc, m, n complex(dp), intent(in) :: tau ! Array Arguments complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(in) :: v(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: applyleft integer(${ik}$) :: i, lastv, lastc ! Executable Statements applyleft = stdlib_lsame( side, 'L' ) lastv = 0_${ik}$ lastc = 0_${ik}$ if( tau/=czero ) then ! set up variables for scanning v. lastv begins pointing to the end ! of v. if( applyleft ) then lastv = m else lastv = n end if if( incv>0_${ik}$ ) then i = 1_${ik}$ + (lastv-1) * incv else i = 1_${ik}$ end if ! look for the last non-czero row in v. do while( lastv>0 .and. v( i )==czero ) lastv = lastv - 1_${ik}$ i = i - incv end do if( applyleft ) then ! scan for the last non-czero column in c(1:lastv,:). lastc = stdlib${ii}$_ilazlc(lastv, n, c, ldc) else ! scan for the last non-czero row in c(:,1:lastv). lastc = stdlib${ii}$_ilazlr(m, lastv, c, ldc) end if end if ! note that lastc.eq.0_dp renders the blas operations null; no special ! case is needed at this level. if( applyleft ) then ! form h * c if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastv,1:lastc)**h * v(1:lastv,1) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', lastv, lastc, cone,c, ldc, v, incv, & czero, work, 1_${ik}$ ) ! c(1:lastv,1:lastc) := c(...) - v(1:lastv,1) * w(1:lastc,1)**h call stdlib${ii}$_zgerc( lastv, lastc, -tau, v, incv, work, 1_${ik}$, c, ldc ) end if else ! form c * h if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastc,1:lastv) * v(1:lastv,1) call stdlib${ii}$_zgemv( 'NO TRANSPOSE', lastc, lastv, cone, c, ldc,v, incv, czero, & work, 1_${ik}$ ) ! c(1:lastc,1:lastv) := c(...) - w(1:lastc,1) * v(1:lastv,1)**h call stdlib${ii}$_zgerc( lastc, lastv, -tau, work, 1_${ik}$, v, incv, c, ldc ) end if end if return end subroutine stdlib${ii}$_zlarf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larf( side, m, n, v, incv, tau, c, ldc, work ) !! ZLARF: applies a complex elementary reflector H to a complex M-by-N !! matrix C, from either the left or the right. H is represented in the !! form !! H = I - tau * v * v**H !! where tau is a complex scalar and v is a complex vector. !! If tau = 0, then H is taken to be the unit matrix. !! To apply H**H, supply conjg(tau) instead !! tau. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side integer(${ik}$), intent(in) :: incv, ldc, m, n complex(${ck}$), intent(in) :: tau ! Array Arguments complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(in) :: v(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: applyleft integer(${ik}$) :: i, lastv, lastc ! Executable Statements applyleft = stdlib_lsame( side, 'L' ) lastv = 0_${ik}$ lastc = 0_${ik}$ if( tau/=czero ) then ! set up variables for scanning v. lastv begins pointing to the end ! of v. if( applyleft ) then lastv = m else lastv = n end if if( incv>0_${ik}$ ) then i = 1_${ik}$ + (lastv-1) * incv else i = 1_${ik}$ end if ! look for the last non-czero row in v. do while( lastv>0 .and. v( i )==czero ) lastv = lastv - 1_${ik}$ i = i - incv end do if( applyleft ) then ! scan for the last non-czero column in c(1:lastv,:). lastc = stdlib${ii}$_ila${ci}$lc(lastv, n, c, ldc) else ! scan for the last non-czero row in c(:,1:lastv). lastc = stdlib${ii}$_ila${ci}$lr(m, lastv, c, ldc) end if end if ! note that lastc.eq.0_${ck}$ renders the blas operations null; no special ! case is needed at this level. if( applyleft ) then ! form h * c if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastv,1:lastc)**h * v(1:lastv,1) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', lastv, lastc, cone,c, ldc, v, incv, & czero, work, 1_${ik}$ ) ! c(1:lastv,1:lastc) := c(...) - v(1:lastv,1) * w(1:lastc,1)**h call stdlib${ii}$_${ci}$gerc( lastv, lastc, -tau, v, incv, work, 1_${ik}$, c, ldc ) end if else ! form c * h if( lastv>0_${ik}$ ) then ! w(1:lastc,1) := c(1:lastc,1:lastv) * v(1:lastv,1) call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', lastc, lastv, cone, c, ldc,v, incv, czero, & work, 1_${ik}$ ) ! c(1:lastc,1:lastv) := c(...) - w(1:lastc,1) * v(1:lastv,1)**h call stdlib${ii}$_${ci}$gerc( lastc, lastv, -tau, work, 1_${ik}$, v, incv, c, ldc ) end if end if return end subroutine stdlib${ii}$_${ci}$larf #:endif #:endfor pure module subroutine stdlib${ii}$_slarfx( side, m, n, v, tau, c, ldc, work ) !! SLARFX applies a real elementary reflector H to a real m by n !! matrix C, from either the left or the right. H is represented in the !! form !! H = I - tau * v * v**T !! where tau is a real scalar and v is a real vector. !! If tau = 0, then H is taken to be the unit matrix !! This version uses inline code if H has order < 11. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n real(sp), intent(in) :: tau ! Array Arguments real(sp), intent(inout) :: c(ldc,*) real(sp), intent(in) :: v(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j real(sp) :: sum, t1, t10, t2, t3, t4, t5, t6, t7, t8, t9, v1, v10, v2, v3, v4, v5, v6, & v7, v8, v9 ! Executable Statements if( tau==zero )return if( stdlib_lsame( side, 'L' ) ) then ! form h * c, where h has order m. go to ( 10, 30, 50, 70, 90, 110, 130, 150,170, 190 )m ! code for general m call stdlib${ii}$_slarf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 10 continue ! special code for 1 x 1 householder t1 = one - tau*v( 1_${ik}$ )*v( 1_${ik}$ ) do j = 1, n c( 1_${ik}$, j ) = t1*c( 1_${ik}$, j ) end do go to 410 30 continue ! special code for 2 x 2 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 end do go to 410 50 continue ! special code for 3 x 3 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 end do go to 410 70 continue ! special code for 4 x 4 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 end do go to 410 90 continue ! special code for 5 x 5 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 end do go to 410 110 continue ! special code for 6 x 6 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 end do go to 410 130 continue ! special code for 7 x 7 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 end do go to 410 150 continue ! special code for 8 x 8 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 end do go to 410 170 continue ! special code for 9 x 9 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 end do go to 410 190 continue ! special code for 10 x 10 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 v10 = v( 10_${ik}$ ) t10 = tau*v10 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) +v10*c( 10_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 c( 10_${ik}$, j ) = c( 10_${ik}$, j ) - sum*t10 end do go to 410 else ! form c * h, where h has order n. go to ( 210, 230, 250, 270, 290, 310, 330, 350,370, 390 )n ! code for general n call stdlib${ii}$_slarf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 210 continue ! special code for 1 x 1 householder t1 = one - tau*v( 1_${ik}$ )*v( 1_${ik}$ ) do j = 1, m c( j, 1_${ik}$ ) = t1*c( j, 1_${ik}$ ) end do go to 410 230 continue ! special code for 2 x 2 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 end do go to 410 250 continue ! special code for 3 x 3 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 end do go to 410 270 continue ! special code for 4 x 4 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 end do go to 410 290 continue ! special code for 5 x 5 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 end do go to 410 310 continue ! special code for 6 x 6 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 end do go to 410 330 continue ! special code for 7 x 7 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 end do go to 410 350 continue ! special code for 8 x 8 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 end do go to 410 370 continue ! special code for 9 x 9 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 end do go to 410 390 continue ! special code for 10 x 10 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 v10 = v( 10_${ik}$ ) t10 = tau*v10 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) +v10*c( j, 10_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 c( j, 10_${ik}$ ) = c( j, 10_${ik}$ ) - sum*t10 end do go to 410 end if 410 return end subroutine stdlib${ii}$_slarfx pure module subroutine stdlib${ii}$_dlarfx( side, m, n, v, tau, c, ldc, work ) !! DLARFX applies a real elementary reflector H to a real m by n !! matrix C, from either the left or the right. H is represented in the !! form !! H = I - tau * v * v**T !! where tau is a real scalar and v is a real vector. !! If tau = 0, then H is taken to be the unit matrix !! This version uses inline code if H has order < 11. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n real(dp), intent(in) :: tau ! Array Arguments real(dp), intent(inout) :: c(ldc,*) real(dp), intent(in) :: v(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j real(dp) :: sum, t1, t10, t2, t3, t4, t5, t6, t7, t8, t9, v1, v10, v2, v3, v4, v5, v6, & v7, v8, v9 ! Executable Statements if( tau==zero )return if( stdlib_lsame( side, 'L' ) ) then ! form h * c, where h has order m. go to ( 10, 30, 50, 70, 90, 110, 130, 150,170, 190 )m ! code for general m call stdlib${ii}$_dlarf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 10 continue ! special code for 1 x 1 householder t1 = one - tau*v( 1_${ik}$ )*v( 1_${ik}$ ) do j = 1, n c( 1_${ik}$, j ) = t1*c( 1_${ik}$, j ) end do go to 410 30 continue ! special code for 2 x 2 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 end do go to 410 50 continue ! special code for 3 x 3 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 end do go to 410 70 continue ! special code for 4 x 4 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 end do go to 410 90 continue ! special code for 5 x 5 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 end do go to 410 110 continue ! special code for 6 x 6 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 end do go to 410 130 continue ! special code for 7 x 7 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 end do go to 410 150 continue ! special code for 8 x 8 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 end do go to 410 170 continue ! special code for 9 x 9 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 end do go to 410 190 continue ! special code for 10 x 10 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 v10 = v( 10_${ik}$ ) t10 = tau*v10 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) +v10*c( 10_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 c( 10_${ik}$, j ) = c( 10_${ik}$, j ) - sum*t10 end do go to 410 else ! form c * h, where h has order n. go to ( 210, 230, 250, 270, 290, 310, 330, 350,370, 390 )n ! code for general n call stdlib${ii}$_dlarf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 210 continue ! special code for 1 x 1 householder t1 = one - tau*v( 1_${ik}$ )*v( 1_${ik}$ ) do j = 1, m c( j, 1_${ik}$ ) = t1*c( j, 1_${ik}$ ) end do go to 410 230 continue ! special code for 2 x 2 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 end do go to 410 250 continue ! special code for 3 x 3 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 end do go to 410 270 continue ! special code for 4 x 4 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 end do go to 410 290 continue ! special code for 5 x 5 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 end do go to 410 310 continue ! special code for 6 x 6 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 end do go to 410 330 continue ! special code for 7 x 7 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 end do go to 410 350 continue ! special code for 8 x 8 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 end do go to 410 370 continue ! special code for 9 x 9 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 end do go to 410 390 continue ! special code for 10 x 10 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 v10 = v( 10_${ik}$ ) t10 = tau*v10 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) +v10*c( j, 10_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 c( j, 10_${ik}$ ) = c( j, 10_${ik}$ ) - sum*t10 end do go to 410 end if 410 continue return end subroutine stdlib${ii}$_dlarfx #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larfx( side, m, n, v, tau, c, ldc, work ) !! DLARFX: applies a real elementary reflector H to a real m by n !! matrix C, from either the left or the right. H is represented in the !! form !! H = I - tau * v * v**T !! where tau is a real scalar and v is a real vector. !! If tau = 0, then H is taken to be the unit matrix !! This version uses inline code if H has order < 11. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n real(${rk}$), intent(in) :: tau ! Array Arguments real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(in) :: v(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j real(${rk}$) :: sum, t1, t10, t2, t3, t4, t5, t6, t7, t8, t9, v1, v10, v2, v3, v4, v5, v6, & v7, v8, v9 ! Executable Statements if( tau==zero )return if( stdlib_lsame( side, 'L' ) ) then ! form h * c, where h has order m. go to ( 10, 30, 50, 70, 90, 110, 130, 150,170, 190 )m ! code for general m call stdlib${ii}$_${ri}$larf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 10 continue ! special code for 1 x 1 householder t1 = one - tau*v( 1_${ik}$ )*v( 1_${ik}$ ) do j = 1, n c( 1_${ik}$, j ) = t1*c( 1_${ik}$, j ) end do go to 410 30 continue ! special code for 2 x 2 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 end do go to 410 50 continue ! special code for 3 x 3 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 end do go to 410 70 continue ! special code for 4 x 4 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 end do go to 410 90 continue ! special code for 5 x 5 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 end do go to 410 110 continue ! special code for 6 x 6 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 end do go to 410 130 continue ! special code for 7 x 7 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 end do go to 410 150 continue ! special code for 8 x 8 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 end do go to 410 170 continue ! special code for 9 x 9 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 end do go to 410 190 continue ! special code for 10 x 10 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 v10 = v( 10_${ik}$ ) t10 = tau*v10 do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) +v10*c( 10_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 c( 10_${ik}$, j ) = c( 10_${ik}$, j ) - sum*t10 end do go to 410 else ! form c * h, where h has order n. go to ( 210, 230, 250, 270, 290, 310, 330, 350,370, 390 )n ! code for general n call stdlib${ii}$_${ri}$larf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 210 continue ! special code for 1 x 1 householder t1 = one - tau*v( 1_${ik}$ )*v( 1_${ik}$ ) do j = 1, m c( j, 1_${ik}$ ) = t1*c( j, 1_${ik}$ ) end do go to 410 230 continue ! special code for 2 x 2 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 end do go to 410 250 continue ! special code for 3 x 3 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 end do go to 410 270 continue ! special code for 4 x 4 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 end do go to 410 290 continue ! special code for 5 x 5 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 end do go to 410 310 continue ! special code for 6 x 6 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 end do go to 410 330 continue ! special code for 7 x 7 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 end do go to 410 350 continue ! special code for 8 x 8 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 end do go to 410 370 continue ! special code for 9 x 9 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 end do go to 410 390 continue ! special code for 10 x 10 householder v1 = v( 1_${ik}$ ) t1 = tau*v1 v2 = v( 2_${ik}$ ) t2 = tau*v2 v3 = v( 3_${ik}$ ) t3 = tau*v3 v4 = v( 4_${ik}$ ) t4 = tau*v4 v5 = v( 5_${ik}$ ) t5 = tau*v5 v6 = v( 6_${ik}$ ) t6 = tau*v6 v7 = v( 7_${ik}$ ) t7 = tau*v7 v8 = v( 8_${ik}$ ) t8 = tau*v8 v9 = v( 9_${ik}$ ) t9 = tau*v9 v10 = v( 10_${ik}$ ) t10 = tau*v10 do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) +v10*c( j, 10_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 c( j, 10_${ik}$ ) = c( j, 10_${ik}$ ) - sum*t10 end do go to 410 end if 410 continue return end subroutine stdlib${ii}$_${ri}$larfx #:endif #:endfor pure module subroutine stdlib${ii}$_clarfx( side, m, n, v, tau, c, ldc, work ) !! CLARFX applies a complex elementary reflector H to a complex m by n !! matrix C, from either the left or the right. H is represented in the !! form !! H = I - tau * v * v**H !! where tau is a complex scalar and v is a complex vector. !! If tau = 0, then H is taken to be the unit matrix !! This version uses inline code if H has order < 11. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n complex(sp), intent(in) :: tau ! Array Arguments complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(in) :: v(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j complex(sp) :: sum, t1, t10, t2, t3, t4, t5, t6, t7, t8, t9, v1, v10, v2, v3, v4, v5, & v6, v7, v8, v9 ! Intrinsic Functions ! Executable Statements if( tau==czero )return if( stdlib_lsame( side, 'L' ) ) then ! form h * c, where h has order m. go to ( 10, 30, 50, 70, 90, 110, 130, 150,170, 190 )m ! code for general m call stdlib${ii}$_clarf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 10 continue ! special code for 1 x 1 householder t1 = cone - tau*v( 1_${ik}$ )*conjg( v( 1_${ik}$ ) ) do j = 1, n c( 1_${ik}$, j ) = t1*c( 1_${ik}$, j ) end do go to 410 30 continue ! special code for 2 x 2 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 end do go to 410 50 continue ! special code for 3 x 3 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 end do go to 410 70 continue ! special code for 4 x 4 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 end do go to 410 90 continue ! special code for 5 x 5 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 end do go to 410 110 continue ! special code for 6 x 6 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 end do go to 410 130 continue ! special code for 7 x 7 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 end do go to 410 150 continue ! special code for 8 x 8 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) v8 = conjg( v( 8_${ik}$ ) ) t8 = tau*conjg( v8 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 end do go to 410 170 continue ! special code for 9 x 9 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) v8 = conjg( v( 8_${ik}$ ) ) t8 = tau*conjg( v8 ) v9 = conjg( v( 9_${ik}$ ) ) t9 = tau*conjg( v9 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 end do go to 410 190 continue ! special code for 10 x 10 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) v8 = conjg( v( 8_${ik}$ ) ) t8 = tau*conjg( v8 ) v9 = conjg( v( 9_${ik}$ ) ) t9 = tau*conjg( v9 ) v10 = conjg( v( 10_${ik}$ ) ) t10 = tau*conjg( v10 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) +v10*c( 10_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 c( 10_${ik}$, j ) = c( 10_${ik}$, j ) - sum*t10 end do go to 410 else ! form c * h, where h has order n. go to ( 210, 230, 250, 270, 290, 310, 330, 350,370, 390 )n ! code for general n call stdlib${ii}$_clarf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 210 continue ! special code for 1 x 1 householder t1 = cone - tau*v( 1_${ik}$ )*conjg( v( 1_${ik}$ ) ) do j = 1, m c( j, 1_${ik}$ ) = t1*c( j, 1_${ik}$ ) end do go to 410 230 continue ! special code for 2 x 2 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 end do go to 410 250 continue ! special code for 3 x 3 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 end do go to 410 270 continue ! special code for 4 x 4 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 end do go to 410 290 continue ! special code for 5 x 5 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 end do go to 410 310 continue ! special code for 6 x 6 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 end do go to 410 330 continue ! special code for 7 x 7 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 end do go to 410 350 continue ! special code for 8 x 8 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) v8 = v( 8_${ik}$ ) t8 = tau*conjg( v8 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 end do go to 410 370 continue ! special code for 9 x 9 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) v8 = v( 8_${ik}$ ) t8 = tau*conjg( v8 ) v9 = v( 9_${ik}$ ) t9 = tau*conjg( v9 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 end do go to 410 390 continue ! special code for 10 x 10 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) v8 = v( 8_${ik}$ ) t8 = tau*conjg( v8 ) v9 = v( 9_${ik}$ ) t9 = tau*conjg( v9 ) v10 = v( 10_${ik}$ ) t10 = tau*conjg( v10 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) +v10*c( j, 10_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 c( j, 10_${ik}$ ) = c( j, 10_${ik}$ ) - sum*t10 end do go to 410 end if 410 return end subroutine stdlib${ii}$_clarfx pure module subroutine stdlib${ii}$_zlarfx( side, m, n, v, tau, c, ldc, work ) !! ZLARFX applies a complex elementary reflector H to a complex m by n !! matrix C, from either the left or the right. H is represented in the !! form !! H = I - tau * v * v**H !! where tau is a complex scalar and v is a complex vector. !! If tau = 0, then H is taken to be the unit matrix !! This version uses inline code if H has order < 11. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n complex(dp), intent(in) :: tau ! Array Arguments complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(in) :: v(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j complex(dp) :: sum, t1, t10, t2, t3, t4, t5, t6, t7, t8, t9, v1, v10, v2, v3, v4, v5, & v6, v7, v8, v9 ! Intrinsic Functions ! Executable Statements if( tau==czero )return if( stdlib_lsame( side, 'L' ) ) then ! form h * c, where h has order m. go to ( 10, 30, 50, 70, 90, 110, 130, 150,170, 190 )m ! code for general m call stdlib${ii}$_zlarf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 10 continue ! special code for 1 x 1 householder t1 = cone - tau*v( 1_${ik}$ )*conjg( v( 1_${ik}$ ) ) do j = 1, n c( 1_${ik}$, j ) = t1*c( 1_${ik}$, j ) end do go to 410 30 continue ! special code for 2 x 2 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 end do go to 410 50 continue ! special code for 3 x 3 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 end do go to 410 70 continue ! special code for 4 x 4 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 end do go to 410 90 continue ! special code for 5 x 5 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 end do go to 410 110 continue ! special code for 6 x 6 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 end do go to 410 130 continue ! special code for 7 x 7 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 end do go to 410 150 continue ! special code for 8 x 8 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) v8 = conjg( v( 8_${ik}$ ) ) t8 = tau*conjg( v8 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 end do go to 410 170 continue ! special code for 9 x 9 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) v8 = conjg( v( 8_${ik}$ ) ) t8 = tau*conjg( v8 ) v9 = conjg( v( 9_${ik}$ ) ) t9 = tau*conjg( v9 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 end do go to 410 190 continue ! special code for 10 x 10 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) v8 = conjg( v( 8_${ik}$ ) ) t8 = tau*conjg( v8 ) v9 = conjg( v( 9_${ik}$ ) ) t9 = tau*conjg( v9 ) v10 = conjg( v( 10_${ik}$ ) ) t10 = tau*conjg( v10 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) +v10*c( 10_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 c( 10_${ik}$, j ) = c( 10_${ik}$, j ) - sum*t10 end do go to 410 else ! form c * h, where h has order n. go to ( 210, 230, 250, 270, 290, 310, 330, 350,370, 390 )n ! code for general n call stdlib${ii}$_zlarf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 210 continue ! special code for 1 x 1 householder t1 = cone - tau*v( 1_${ik}$ )*conjg( v( 1_${ik}$ ) ) do j = 1, m c( j, 1_${ik}$ ) = t1*c( j, 1_${ik}$ ) end do go to 410 230 continue ! special code for 2 x 2 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 end do go to 410 250 continue ! special code for 3 x 3 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 end do go to 410 270 continue ! special code for 4 x 4 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 end do go to 410 290 continue ! special code for 5 x 5 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 end do go to 410 310 continue ! special code for 6 x 6 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 end do go to 410 330 continue ! special code for 7 x 7 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 end do go to 410 350 continue ! special code for 8 x 8 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) v8 = v( 8_${ik}$ ) t8 = tau*conjg( v8 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 end do go to 410 370 continue ! special code for 9 x 9 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) v8 = v( 8_${ik}$ ) t8 = tau*conjg( v8 ) v9 = v( 9_${ik}$ ) t9 = tau*conjg( v9 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 end do go to 410 390 continue ! special code for 10 x 10 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) v8 = v( 8_${ik}$ ) t8 = tau*conjg( v8 ) v9 = v( 9_${ik}$ ) t9 = tau*conjg( v9 ) v10 = v( 10_${ik}$ ) t10 = tau*conjg( v10 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) +v10*c( j, 10_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 c( j, 10_${ik}$ ) = c( j, 10_${ik}$ ) - sum*t10 end do go to 410 end if 410 continue return end subroutine stdlib${ii}$_zlarfx #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larfx( side, m, n, v, tau, c, ldc, work ) !! ZLARFX: applies a complex elementary reflector H to a complex m by n !! matrix C, from either the left or the right. H is represented in the !! form !! H = I - tau * v * v**H !! where tau is a complex scalar and v is a complex vector. !! If tau = 0, then H is taken to be the unit matrix !! This version uses inline code if H has order < 11. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: side integer(${ik}$), intent(in) :: ldc, m, n complex(${ck}$), intent(in) :: tau ! Array Arguments complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(in) :: v(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j complex(${ck}$) :: sum, t1, t10, t2, t3, t4, t5, t6, t7, t8, t9, v1, v10, v2, v3, v4, v5, & v6, v7, v8, v9 ! Intrinsic Functions ! Executable Statements if( tau==czero )return if( stdlib_lsame( side, 'L' ) ) then ! form h * c, where h has order m. go to ( 10, 30, 50, 70, 90, 110, 130, 150,170, 190 )m ! code for general m call stdlib${ii}$_${ci}$larf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 10 continue ! special code for 1 x 1 householder t1 = cone - tau*v( 1_${ik}$ )*conjg( v( 1_${ik}$ ) ) do j = 1, n c( 1_${ik}$, j ) = t1*c( 1_${ik}$, j ) end do go to 410 30 continue ! special code for 2 x 2 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 end do go to 410 50 continue ! special code for 3 x 3 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 end do go to 410 70 continue ! special code for 4 x 4 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 end do go to 410 90 continue ! special code for 5 x 5 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 end do go to 410 110 continue ! special code for 6 x 6 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 end do go to 410 130 continue ! special code for 7 x 7 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 end do go to 410 150 continue ! special code for 8 x 8 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) v8 = conjg( v( 8_${ik}$ ) ) t8 = tau*conjg( v8 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 end do go to 410 170 continue ! special code for 9 x 9 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) v8 = conjg( v( 8_${ik}$ ) ) t8 = tau*conjg( v8 ) v9 = conjg( v( 9_${ik}$ ) ) t9 = tau*conjg( v9 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 end do go to 410 190 continue ! special code for 10 x 10 householder v1 = conjg( v( 1_${ik}$ ) ) t1 = tau*conjg( v1 ) v2 = conjg( v( 2_${ik}$ ) ) t2 = tau*conjg( v2 ) v3 = conjg( v( 3_${ik}$ ) ) t3 = tau*conjg( v3 ) v4 = conjg( v( 4_${ik}$ ) ) t4 = tau*conjg( v4 ) v5 = conjg( v( 5_${ik}$ ) ) t5 = tau*conjg( v5 ) v6 = conjg( v( 6_${ik}$ ) ) t6 = tau*conjg( v6 ) v7 = conjg( v( 7_${ik}$ ) ) t7 = tau*conjg( v7 ) v8 = conjg( v( 8_${ik}$ ) ) t8 = tau*conjg( v8 ) v9 = conjg( v( 9_${ik}$ ) ) t9 = tau*conjg( v9 ) v10 = conjg( v( 10_${ik}$ ) ) t10 = tau*conjg( v10 ) do j = 1, n sum = v1*c( 1_${ik}$, j ) + v2*c( 2_${ik}$, j ) + v3*c( 3_${ik}$, j ) +v4*c( 4_${ik}$, j ) + v5*c( 5_${ik}$, j ) + & v6*c( 6_${ik}$, j ) +v7*c( 7_${ik}$, j ) + v8*c( 8_${ik}$, j ) + v9*c( 9_${ik}$, j ) +v10*c( 10_${ik}$, j ) c( 1_${ik}$, j ) = c( 1_${ik}$, j ) - sum*t1 c( 2_${ik}$, j ) = c( 2_${ik}$, j ) - sum*t2 c( 3_${ik}$, j ) = c( 3_${ik}$, j ) - sum*t3 c( 4_${ik}$, j ) = c( 4_${ik}$, j ) - sum*t4 c( 5_${ik}$, j ) = c( 5_${ik}$, j ) - sum*t5 c( 6_${ik}$, j ) = c( 6_${ik}$, j ) - sum*t6 c( 7_${ik}$, j ) = c( 7_${ik}$, j ) - sum*t7 c( 8_${ik}$, j ) = c( 8_${ik}$, j ) - sum*t8 c( 9_${ik}$, j ) = c( 9_${ik}$, j ) - sum*t9 c( 10_${ik}$, j ) = c( 10_${ik}$, j ) - sum*t10 end do go to 410 else ! form c * h, where h has order n. go to ( 210, 230, 250, 270, 290, 310, 330, 350,370, 390 )n ! code for general n call stdlib${ii}$_${ci}$larf( side, m, n, v, 1_${ik}$, tau, c, ldc, work ) go to 410 210 continue ! special code for 1 x 1 householder t1 = cone - tau*v( 1_${ik}$ )*conjg( v( 1_${ik}$ ) ) do j = 1, m c( j, 1_${ik}$ ) = t1*c( j, 1_${ik}$ ) end do go to 410 230 continue ! special code for 2 x 2 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 end do go to 410 250 continue ! special code for 3 x 3 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 end do go to 410 270 continue ! special code for 4 x 4 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 end do go to 410 290 continue ! special code for 5 x 5 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 end do go to 410 310 continue ! special code for 6 x 6 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 end do go to 410 330 continue ! special code for 7 x 7 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 end do go to 410 350 continue ! special code for 8 x 8 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) v8 = v( 8_${ik}$ ) t8 = tau*conjg( v8 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 end do go to 410 370 continue ! special code for 9 x 9 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) v8 = v( 8_${ik}$ ) t8 = tau*conjg( v8 ) v9 = v( 9_${ik}$ ) t9 = tau*conjg( v9 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 end do go to 410 390 continue ! special code for 10 x 10 householder v1 = v( 1_${ik}$ ) t1 = tau*conjg( v1 ) v2 = v( 2_${ik}$ ) t2 = tau*conjg( v2 ) v3 = v( 3_${ik}$ ) t3 = tau*conjg( v3 ) v4 = v( 4_${ik}$ ) t4 = tau*conjg( v4 ) v5 = v( 5_${ik}$ ) t5 = tau*conjg( v5 ) v6 = v( 6_${ik}$ ) t6 = tau*conjg( v6 ) v7 = v( 7_${ik}$ ) t7 = tau*conjg( v7 ) v8 = v( 8_${ik}$ ) t8 = tau*conjg( v8 ) v9 = v( 9_${ik}$ ) t9 = tau*conjg( v9 ) v10 = v( 10_${ik}$ ) t10 = tau*conjg( v10 ) do j = 1, m sum = v1*c( j, 1_${ik}$ ) + v2*c( j, 2_${ik}$ ) + v3*c( j, 3_${ik}$ ) +v4*c( j, 4_${ik}$ ) + v5*c( j, 5_${ik}$ ) + & v6*c( j, 6_${ik}$ ) +v7*c( j, 7_${ik}$ ) + v8*c( j, 8_${ik}$ ) + v9*c( j, 9_${ik}$ ) +v10*c( j, 10_${ik}$ ) c( j, 1_${ik}$ ) = c( j, 1_${ik}$ ) - sum*t1 c( j, 2_${ik}$ ) = c( j, 2_${ik}$ ) - sum*t2 c( j, 3_${ik}$ ) = c( j, 3_${ik}$ ) - sum*t3 c( j, 4_${ik}$ ) = c( j, 4_${ik}$ ) - sum*t4 c( j, 5_${ik}$ ) = c( j, 5_${ik}$ ) - sum*t5 c( j, 6_${ik}$ ) = c( j, 6_${ik}$ ) - sum*t6 c( j, 7_${ik}$ ) = c( j, 7_${ik}$ ) - sum*t7 c( j, 8_${ik}$ ) = c( j, 8_${ik}$ ) - sum*t8 c( j, 9_${ik}$ ) = c( j, 9_${ik}$ ) - sum*t9 c( j, 10_${ik}$ ) = c( j, 10_${ik}$ ) - sum*t10 end do go to 410 end if 410 continue return end subroutine stdlib${ii}$_${ci}$larfx #:endif #:endfor pure module subroutine stdlib${ii}$_slarfy( uplo, n, v, incv, tau, c, ldc, work ) !! SLARFY applies an elementary reflector, or Householder matrix, H, !! to an n x n symmetric matrix C, from both the left and the right. !! H is represented in the form !! H = I - tau * v * v' !! where tau is a scalar and v is a vector. !! If tau is zero, then H is taken to be the unit matrix. ! -- lapack test routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n real(sp), intent(in) :: tau ! Array Arguments real(sp), intent(inout) :: c(ldc,*) real(sp), intent(in) :: v(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars real(sp) :: alpha ! Executable Statements if( tau==zero )return ! form w:= c * v call stdlib${ii}$_ssymv( uplo, n, one, c, ldc, v, incv, zero, work, 1_${ik}$ ) alpha = -half*tau*stdlib${ii}$_sdot( n, work, 1_${ik}$, v, incv ) call stdlib${ii}$_saxpy( n, alpha, v, incv, work, 1_${ik}$ ) ! c := c - v * w' - w * v' call stdlib${ii}$_ssyr2( uplo, n, -tau, v, incv, work, 1_${ik}$, c, ldc ) return end subroutine stdlib${ii}$_slarfy pure module subroutine stdlib${ii}$_dlarfy( uplo, n, v, incv, tau, c, ldc, work ) !! DLARFY applies an elementary reflector, or Householder matrix, H, !! to an n x n symmetric matrix C, from both the left and the right. !! H is represented in the form !! H = I - tau * v * v' !! where tau is a scalar and v is a vector. !! If tau is zero, then H is taken to be the unit matrix. ! -- lapack test routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n real(dp), intent(in) :: tau ! Array Arguments real(dp), intent(inout) :: c(ldc,*) real(dp), intent(in) :: v(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars real(dp) :: alpha ! Executable Statements if( tau==zero )return ! form w:= c * v call stdlib${ii}$_dsymv( uplo, n, one, c, ldc, v, incv, zero, work, 1_${ik}$ ) alpha = -half*tau*stdlib${ii}$_ddot( n, work, 1_${ik}$, v, incv ) call stdlib${ii}$_daxpy( n, alpha, v, incv, work, 1_${ik}$ ) ! c := c - v * w' - w * v' call stdlib${ii}$_dsyr2( uplo, n, -tau, v, incv, work, 1_${ik}$, c, ldc ) return end subroutine stdlib${ii}$_dlarfy #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larfy( uplo, n, v, incv, tau, c, ldc, work ) !! DLARFY: applies an elementary reflector, or Householder matrix, H, !! to an n x n symmetric matrix C, from both the left and the right. !! H is represented in the form !! H = I - tau * v * v' !! where tau is a scalar and v is a vector. !! If tau is zero, then H is taken to be the unit matrix. ! -- lapack test routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n real(${rk}$), intent(in) :: tau ! Array Arguments real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(in) :: v(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: alpha ! Executable Statements if( tau==zero )return ! form w:= c * v call stdlib${ii}$_${ri}$symv( uplo, n, one, c, ldc, v, incv, zero, work, 1_${ik}$ ) alpha = -half*tau*stdlib${ii}$_${ri}$dot( n, work, 1_${ik}$, v, incv ) call stdlib${ii}$_${ri}$axpy( n, alpha, v, incv, work, 1_${ik}$ ) ! c := c - v * w' - w * v' call stdlib${ii}$_${ri}$syr2( uplo, n, -tau, v, incv, work, 1_${ik}$, c, ldc ) return end subroutine stdlib${ii}$_${ri}$larfy #:endif #:endfor pure module subroutine stdlib${ii}$_clarfy( uplo, n, v, incv, tau, c, ldc, work ) !! CLARFY applies an elementary reflector, or Householder matrix, H, !! to an n x n Hermitian matrix C, from both the left and the right. !! H is represented in the form !! H = I - tau * v * v' !! where tau is a scalar and v is a vector. !! If tau is zero, then H is taken to be the unit matrix. ! -- lapack test routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n complex(sp), intent(in) :: tau ! Array Arguments complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(in) :: v(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars complex(sp) :: alpha ! Executable Statements if( tau==czero )return ! form w:= c * v call stdlib${ii}$_chemv( uplo, n, cone, c, ldc, v, incv, czero, work, 1_${ik}$ ) alpha = -chalf*tau*stdlib${ii}$_cdotc( n, work, 1_${ik}$, v, incv ) call stdlib${ii}$_caxpy( n, alpha, v, incv, work, 1_${ik}$ ) ! c := c - v * w' - w * v' call stdlib${ii}$_cher2( uplo, n, -tau, v, incv, work, 1_${ik}$, c, ldc ) return end subroutine stdlib${ii}$_clarfy pure module subroutine stdlib${ii}$_zlarfy( uplo, n, v, incv, tau, c, ldc, work ) !! ZLARFY applies an elementary reflector, or Householder matrix, H, !! to an n x n Hermitian matrix C, from both the left and the right. !! H is represented in the form !! H = I - tau * v * v' !! where tau is a scalar and v is a vector. !! If tau is zero, then H is taken to be the unit matrix. ! -- lapack test routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n complex(dp), intent(in) :: tau ! Array Arguments complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(in) :: v(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars complex(dp) :: alpha ! Executable Statements if( tau==czero )return ! form w:= c * v call stdlib${ii}$_zhemv( uplo, n, cone, c, ldc, v, incv, czero, work, 1_${ik}$ ) alpha = -chalf*tau*stdlib${ii}$_zdotc( n, work, 1_${ik}$, v, incv ) call stdlib${ii}$_zaxpy( n, alpha, v, incv, work, 1_${ik}$ ) ! c := c - v * w' - w * v' call stdlib${ii}$_zher2( uplo, n, -tau, v, incv, work, 1_${ik}$, c, ldc ) return end subroutine stdlib${ii}$_zlarfy #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larfy( uplo, n, v, incv, tau, c, ldc, work ) !! ZLARFY: applies an elementary reflector, or Householder matrix, H, !! to an n x n Hermitian matrix C, from both the left and the right. !! H is represented in the form !! H = I - tau * v * v' !! where tau is a scalar and v is a vector. !! If tau is zero, then H is taken to be the unit matrix. ! -- lapack test routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incv, ldc, n complex(${ck}$), intent(in) :: tau ! Array Arguments complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(in) :: v(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: alpha ! Executable Statements if( tau==czero )return ! form w:= c * v call stdlib${ii}$_${ci}$hemv( uplo, n, cone, c, ldc, v, incv, czero, work, 1_${ik}$ ) alpha = -chalf*tau*stdlib${ii}$_${ci}$dotc( n, work, 1_${ik}$, v, incv ) call stdlib${ii}$_${ci}$axpy( n, alpha, v, incv, work, 1_${ik}$ ) ! c := c - v * w' - w * v' call stdlib${ii}$_${ci}$her2( uplo, n, -tau, v, incv, work, 1_${ik}$, c, ldc ) return end subroutine stdlib${ii}$_${ci}$larfy #:endif #:endfor pure module subroutine stdlib${ii}$_slarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & !! SLARFB applies a real block reflector H or its transpose H**T to a !! real m by n matrix C, from either the left or the right. work, ldwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n ! Array Arguments real(sp), intent(inout) :: c(ldc,*) real(sp), intent(in) :: t(ldt,*), v(ldv,*) real(sp), intent(out) :: work(ldwork,*) ! ===================================================================== ! Local Scalars character :: transt integer(${ik}$) :: i, j ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( stdlib_lsame( trans, 'N' ) ) then transt = 'T' else transt = 'N' end if if( stdlib_lsame( storev, 'C' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 ) (first k rows) ! ( v2 ) ! where v1 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v = (c1**t * v1 + c2**t * v2) (stored in work) ! w := c1**t do j = 1, k call stdlib${ii}$_scopy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, one, v, ldv,& work, ldwork ) if( m>k ) then ! w := w + c2**t * v2 call stdlib${ii}$_sgemm( 'TRANSPOSE', 'NO TRANSPOSE', n, k, m-k,one, c( k+1, 1_${ik}$ ),& ldc, v( k+1, 1_${ik}$ ), ldv,one, work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v * w**t if( m>k ) then ! c2 := c2 - v2 * w**t call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', m-k, n, k,-one, v( k+1, 1_${ik}$ )& , ldv, work, ldwork, one,c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1**t call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', n, k,one, v, ldv, & work, ldwork ) ! c1 := c1 - w**t do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_scopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, one, v, ldv,& work, ldwork ) if( n>k ) then ! w := w + c2 * v2 call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,one, c( 1_${ik}$, k+& 1_${ik}$ ), ldc, v( k+1, 1_${ik}$ ), ldv,one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v**t if( n>k ) then ! c2 := c2 - w * v2**t call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, n-k, k,-one, work, & ldwork, v( k+1, 1_${ik}$ ), ldv, one,c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1**t call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', m, k,one, v, ldv, & work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 ) ! ( v2 ) (last k rows) ! where v2 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v = (c1**t * v1 + c2**t * v2) (stored in work) ! w := c2**t do j = 1, k call stdlib${ii}$_scopy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, one, v( m-k+& 1_${ik}$, 1_${ik}$ ), ldv, work, ldwork ) if( m>k ) then ! w := w + c1**t * v1 call stdlib${ii}$_sgemm( 'TRANSPOSE', 'NO TRANSPOSE', n, k, m-k,one, c, ldc, v, & ldv, one, work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v * w**t if( m>k ) then ! c1 := c1 - v1 * w**t call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', m-k, n, k,-one, v, ldv, & work, ldwork, one, c, ldc ) end if ! w := w * v2**t call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', n, k,one, v( m-k+1, & 1_${ik}$ ), ldv, work, ldwork ) ! c2 := c2 - w**t do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h' where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_scopy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, one, v( n-k+& 1_${ik}$, 1_${ik}$ ), ldv, work, ldwork ) if( n>k ) then ! w := w + c1 * v1 call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,one, c, ldc, & v, ldv, one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v**t if( n>k ) then ! c1 := c1 - w * v1**t call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, n-k, k,-one, work, & ldwork, v, ldv, one, c, ldc ) end if ! w := w * v2**t call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', m, k,one, v( n-k+1, & 1_${ik}$ ), ldv, work, ldwork ) ! c2 := c2 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if else if( stdlib_lsame( storev, 'R' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 v2 ) (v1: first k columns) ! where v1 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v**t = (c1**t * v1**t + c2**t * v2**t) (stored in work) ! w := c1**t do j = 1, k call stdlib${ii}$_scopy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**t call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', n, k,one, v, ldv, & work, ldwork ) if( m>k ) then ! w := w + c2**t * v2**t call stdlib${ii}$_sgemm( 'TRANSPOSE', 'TRANSPOSE', n, k, m-k, one,c( k+1, 1_${ik}$ ), & ldc, v( 1_${ik}$, k+1 ), ldv, one,work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v**t * w**t if( m>k ) then ! c2 := c2 - v2**t * w**t call stdlib${ii}$_sgemm( 'TRANSPOSE', 'TRANSPOSE', m-k, n, k, -one,v( 1_${ik}$, k+1 ), & ldv, work, ldwork, one,c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1 call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, one, v, ldv,& work, ldwork ) ! c1 := c1 - w**t do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t where c = ( c1 c2 ) ! w := c * v**t = (c1*v1**t + c2*v2**t) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_scopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**t call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', m, k,one, v, ldv, & work, ldwork ) if( n>k ) then ! w := w + c2 * v2**t call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, n-k,one, c( 1_${ik}$, k+1 ),& ldc, v( 1_${ik}$, k+1 ), ldv,one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c2 := c2 - w * v2 call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-one, work, & ldwork, v( 1_${ik}$, k+1 ), ldv, one,c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1 call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, one, v, ldv,& work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 v2 ) (v2: last k columns) ! where v2 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v**t = (c1**t * v1**t + c2**t * v2**t) (stored in work) ! w := c2**t do j = 1, k call stdlib${ii}$_scopy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**t call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', n, k,one, v( 1_${ik}$, m-k+& 1_${ik}$ ), ldv, work, ldwork ) if( m>k ) then ! w := w + c1**t * v1**t call stdlib${ii}$_sgemm( 'TRANSPOSE', 'TRANSPOSE', n, k, m-k, one,c, ldc, v, ldv,& one, work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v**t * w**t if( m>k ) then ! c1 := c1 - v1**t * w**t call stdlib${ii}$_sgemm( 'TRANSPOSE', 'TRANSPOSE', m-k, n, k, -one,v, ldv, work, & ldwork, one, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, one, v( 1_${ik}$, & m-k+1 ), ldv, work, ldwork ) ! c2 := c2 - w**t do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t where c = ( c1 c2 ) ! w := c * v**t = (c1*v1**t + c2*v2**t) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_scopy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**t call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', m, k,one, v( 1_${ik}$, n-k+& 1_${ik}$ ), ldv, work, ldwork ) if( n>k ) then ! w := w + c1 * v1**t call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, n-k,one, c, ldc, v, & ldv, one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c1 := c1 - w * v1 call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-one, work, & ldwork, v, ldv, one, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, one, v( 1_${ik}$, & n-k+1 ), ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if end if return end subroutine stdlib${ii}$_slarfb pure module subroutine stdlib${ii}$_dlarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & !! DLARFB applies a real block reflector H or its transpose H**T to a !! real m by n matrix C, from either the left or the right. work, ldwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n ! Array Arguments real(dp), intent(inout) :: c(ldc,*) real(dp), intent(in) :: t(ldt,*), v(ldv,*) real(dp), intent(out) :: work(ldwork,*) ! ===================================================================== ! Local Scalars character :: transt integer(${ik}$) :: i, j ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( stdlib_lsame( trans, 'N' ) ) then transt = 'T' else transt = 'N' end if if( stdlib_lsame( storev, 'C' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 ) (first k rows) ! ( v2 ) ! where v1 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v = (c1**t * v1 + c2**t * v2) (stored in work) ! w := c1**t do j = 1, k call stdlib${ii}$_dcopy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, one, v, ldv,& work, ldwork ) if( m>k ) then ! w := w + c2**t * v2 call stdlib${ii}$_dgemm( 'TRANSPOSE', 'NO TRANSPOSE', n, k, m-k,one, c( k+1, 1_${ik}$ ),& ldc, v( k+1, 1_${ik}$ ), ldv,one, work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v * w**t if( m>k ) then ! c2 := c2 - v2 * w**t call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', m-k, n, k,-one, v( k+1, 1_${ik}$ )& , ldv, work, ldwork, one,c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1**t call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', n, k,one, v, ldv, & work, ldwork ) ! c1 := c1 - w**t do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_dcopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, one, v, ldv,& work, ldwork ) if( n>k ) then ! w := w + c2 * v2 call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,one, c( 1_${ik}$, k+& 1_${ik}$ ), ldc, v( k+1, 1_${ik}$ ), ldv,one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v**t if( n>k ) then ! c2 := c2 - w * v2**t call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, n-k, k,-one, work, & ldwork, v( k+1, 1_${ik}$ ), ldv, one,c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1**t call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', m, k,one, v, ldv, & work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 ) ! ( v2 ) (last k rows) ! where v2 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v = (c1**t * v1 + c2**t * v2) (stored in work) ! w := c2**t do j = 1, k call stdlib${ii}$_dcopy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, one, v( m-k+& 1_${ik}$, 1_${ik}$ ), ldv, work, ldwork ) if( m>k ) then ! w := w + c1**t * v1 call stdlib${ii}$_dgemm( 'TRANSPOSE', 'NO TRANSPOSE', n, k, m-k,one, c, ldc, v, & ldv, one, work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v * w**t if( m>k ) then ! c1 := c1 - v1 * w**t call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', m-k, n, k,-one, v, ldv, & work, ldwork, one, c, ldc ) end if ! w := w * v2**t call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', n, k,one, v( m-k+1, & 1_${ik}$ ), ldv, work, ldwork ) ! c2 := c2 - w**t do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_dcopy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, one, v( n-k+& 1_${ik}$, 1_${ik}$ ), ldv, work, ldwork ) if( n>k ) then ! w := w + c1 * v1 call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,one, c, ldc, & v, ldv, one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v**t if( n>k ) then ! c1 := c1 - w * v1**t call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, n-k, k,-one, work, & ldwork, v, ldv, one, c, ldc ) end if ! w := w * v2**t call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', m, k,one, v( n-k+1, & 1_${ik}$ ), ldv, work, ldwork ) ! c2 := c2 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if else if( stdlib_lsame( storev, 'R' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 v2 ) (v1: first k columns) ! where v1 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v**t = (c1**t * v1**t + c2**t * v2**t) (stored in work) ! w := c1**t do j = 1, k call stdlib${ii}$_dcopy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**t call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', n, k,one, v, ldv, & work, ldwork ) if( m>k ) then ! w := w + c2**t * v2**t call stdlib${ii}$_dgemm( 'TRANSPOSE', 'TRANSPOSE', n, k, m-k, one,c( k+1, 1_${ik}$ ), & ldc, v( 1_${ik}$, k+1 ), ldv, one,work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v**t * w**t if( m>k ) then ! c2 := c2 - v2**t * w**t call stdlib${ii}$_dgemm( 'TRANSPOSE', 'TRANSPOSE', m-k, n, k, -one,v( 1_${ik}$, k+1 ), & ldv, work, ldwork, one,c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1 call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, one, v, ldv,& work, ldwork ) ! c1 := c1 - w**t do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t where c = ( c1 c2 ) ! w := c * v**t = (c1*v1**t + c2*v2**t) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_dcopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**t call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', m, k,one, v, ldv, & work, ldwork ) if( n>k ) then ! w := w + c2 * v2**t call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, n-k,one, c( 1_${ik}$, k+1 ),& ldc, v( 1_${ik}$, k+1 ), ldv,one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c2 := c2 - w * v2 call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-one, work, & ldwork, v( 1_${ik}$, k+1 ), ldv, one,c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1 call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, one, v, ldv,& work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 v2 ) (v2: last k columns) ! where v2 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v**t = (c1**t * v1**t + c2**t * v2**t) (stored in work) ! w := c2**t do j = 1, k call stdlib${ii}$_dcopy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**t call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', n, k,one, v( 1_${ik}$, m-k+& 1_${ik}$ ), ldv, work, ldwork ) if( m>k ) then ! w := w + c1**t * v1**t call stdlib${ii}$_dgemm( 'TRANSPOSE', 'TRANSPOSE', n, k, m-k, one,c, ldc, v, ldv,& one, work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v**t * w**t if( m>k ) then ! c1 := c1 - v1**t * w**t call stdlib${ii}$_dgemm( 'TRANSPOSE', 'TRANSPOSE', m-k, n, k, -one,v, ldv, work, & ldwork, one, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, one, v( 1_${ik}$, & m-k+1 ), ldv, work, ldwork ) ! c2 := c2 - w**t do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h' where c = ( c1 c2 ) ! w := c * v**t = (c1*v1**t + c2*v2**t) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_dcopy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**t call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', m, k,one, v( 1_${ik}$, n-k+& 1_${ik}$ ), ldv, work, ldwork ) if( n>k ) then ! w := w + c1 * v1**t call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, n-k,one, c, ldc, v, & ldv, one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c1 := c1 - w * v1 call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-one, work, & ldwork, v, ldv, one, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, one, v( 1_${ik}$, & n-k+1 ), ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if end if return end subroutine stdlib${ii}$_dlarfb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & !! DLARFB: applies a real block reflector H or its transpose H**T to a !! real m by n matrix C, from either the left or the right. work, ldwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(in) :: t(ldt,*), v(ldv,*) real(${rk}$), intent(out) :: work(ldwork,*) ! ===================================================================== ! Local Scalars character :: transt integer(${ik}$) :: i, j ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( stdlib_lsame( trans, 'N' ) ) then transt = 'T' else transt = 'N' end if if( stdlib_lsame( storev, 'C' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 ) (first k rows) ! ( v2 ) ! where v1 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v = (c1**t * v1 + c2**t * v2) (stored in work) ! w := c1**t do j = 1, k call stdlib${ii}$_${ri}$copy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, one, v, ldv,& work, ldwork ) if( m>k ) then ! w := w + c2**t * v2 call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'NO TRANSPOSE', n, k, m-k,one, c( k+1, 1_${ik}$ ),& ldc, v( k+1, 1_${ik}$ ), ldv,one, work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v * w**t if( m>k ) then ! c2 := c2 - v2 * w**t call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', m-k, n, k,-one, v( k+1, 1_${ik}$ )& , ldv, work, ldwork, one,c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', n, k,one, v, ldv, & work, ldwork ) ! c1 := c1 - w**t do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_${ri}$copy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, one, v, ldv,& work, ldwork ) if( n>k ) then ! w := w + c2 * v2 call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,one, c( 1_${ik}$, k+& 1_${ik}$ ), ldc, v( k+1, 1_${ik}$ ), ldv,one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v**t if( n>k ) then ! c2 := c2 - w * v2**t call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', m, n-k, k,-one, work, & ldwork, v( k+1, 1_${ik}$ ), ldv, one,c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', m, k,one, v, ldv, & work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 ) ! ( v2 ) (last k rows) ! where v2 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v = (c1**t * v1 + c2**t * v2) (stored in work) ! w := c2**t do j = 1, k call stdlib${ii}$_${ri}$copy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, one, v( m-k+& 1_${ik}$, 1_${ik}$ ), ldv, work, ldwork ) if( m>k ) then ! w := w + c1**t * v1 call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'NO TRANSPOSE', n, k, m-k,one, c, ldc, v, & ldv, one, work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v * w**t if( m>k ) then ! c1 := c1 - v1 * w**t call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', m-k, n, k,-one, v, ldv, & work, ldwork, one, c, ldc ) end if ! w := w * v2**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', n, k,one, v( m-k+1, & 1_${ik}$ ), ldv, work, ldwork ) ! c2 := c2 - w**t do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_${ri}$copy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, one, v( n-k+& 1_${ik}$, 1_${ik}$ ), ldv, work, ldwork ) if( n>k ) then ! w := w + c1 * v1 call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,one, c, ldc, & v, ldv, one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v**t if( n>k ) then ! c1 := c1 - w * v1**t call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', m, n-k, k,-one, work, & ldwork, v, ldv, one, c, ldc ) end if ! w := w * v2**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', m, k,one, v( n-k+1, & 1_${ik}$ ), ldv, work, ldwork ) ! c2 := c2 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if else if( stdlib_lsame( storev, 'R' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 v2 ) (v1: first k columns) ! where v1 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v**t = (c1**t * v1**t + c2**t * v2**t) (stored in work) ! w := c1**t do j = 1, k call stdlib${ii}$_${ri}$copy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', n, k,one, v, ldv, & work, ldwork ) if( m>k ) then ! w := w + c2**t * v2**t call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'TRANSPOSE', n, k, m-k, one,c( k+1, 1_${ik}$ ), & ldc, v( 1_${ik}$, k+1 ), ldv, one,work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v**t * w**t if( m>k ) then ! c2 := c2 - v2**t * w**t call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'TRANSPOSE', m-k, n, k, -one,v( 1_${ik}$, k+1 ), & ldv, work, ldwork, one,c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1 call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, one, v, ldv,& work, ldwork ) ! c1 := c1 - w**t do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**t where c = ( c1 c2 ) ! w := c * v**t = (c1*v1**t + c2*v2**t) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_${ri}$copy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', m, k,one, v, ldv, & work, ldwork ) if( n>k ) then ! w := w + c2 * v2**t call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, n-k,one, c( 1_${ik}$, k+1 ),& ldc, v( 1_${ik}$, k+1 ), ldv,one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c2 := c2 - w * v2 call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-one, work, & ldwork, v( 1_${ik}$, k+1 ), ldv, one,c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1 call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, one, v, ldv,& work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 v2 ) (v2: last k columns) ! where v2 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**t * c where c = ( c1 ) ! ( c2 ) ! w := c**t * v**t = (c1**t * v1**t + c2**t * v2**t) (stored in work) ! w := c2**t do j = 1, k call stdlib${ii}$_${ri}$copy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', n, k,one, v( 1_${ik}$, m-k+& 1_${ik}$ ), ldv, work, ldwork ) if( m>k ) then ! w := w + c1**t * v1**t call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'TRANSPOSE', n, k, m-k, one,c, ldc, v, ldv,& one, work, ldwork ) end if ! w := w * t**t or w * t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,one, t, ldt, & work, ldwork ) ! c := c - v**t * w**t if( m>k ) then ! c1 := c1 - v1**t * w**t call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'TRANSPOSE', m-k, n, k, -one,v, ldv, work, & ldwork, one, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, one, v( 1_${ik}$, & m-k+1 ), ldv, work, ldwork ) ! c2 := c2 - w**t do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) - work( i, j ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h' where c = ( c1 c2 ) ! w := c * v**t = (c1*v1**t + c2*v2**t) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_${ri}$copy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', m, k,one, v( 1_${ik}$, n-k+& 1_${ik}$ ), ldv, work, ldwork ) if( n>k ) then ! w := w + c1 * v1**t call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', m, k, n-k,one, c, ldc, v, & ldv, one, work, ldwork ) end if ! w := w * t or w * t**t call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,one, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c1 := c1 - w * v1 call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-one, work, & ldwork, v, ldv, one, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, one, v( 1_${ik}$, & n-k+1 ), ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if end if return end subroutine stdlib${ii}$_${ri}$larfb #:endif #:endfor pure module subroutine stdlib${ii}$_clarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & work, ldwork ) !! CLARFB applies a complex block reflector H or its transpose H**H to a !! complex M-by-N matrix C, from either the left or the right. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n ! Array Arguments complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(in) :: t(ldt,*), v(ldv,*) complex(sp), intent(out) :: work(ldwork,*) ! ===================================================================== ! Local Scalars character :: transt integer(${ik}$) :: i, j ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( stdlib_lsame( trans, 'N' ) ) then transt = 'C' else transt = 'N' end if if( stdlib_lsame( storev, 'C' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 ) (first k rows) ! ( v2 ) ! where v1 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v = (c1**h * v1 + c2**h * v2) (stored in work) ! w := c1**h do j = 1, k call stdlib${ii}$_ccopy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_clacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v, & ldv, work, ldwork ) if( m>k ) then ! w := w + c2**h *v2 call stdlib${ii}$_cgemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', n,k, m-k, cone, & c( k+1, 1_${ik}$ ), ldc,v( k+1, 1_${ik}$ ), ldv, cone, work, ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v * w**h if( m>k ) then ! c2 := c2 - v2 * w**h call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',m-k, n, k, -cone, & v( k+1, 1_${ik}$ ), ldv, work,ldwork, cone, c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1**h call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v, ldv, work, ldwork ) ! c1 := c1 - w**h do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_ccopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v, & ldv, work, ldwork ) if( n>k ) then ! w := w + c2 * v2 call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,cone, c( 1_${ik}$, k+& 1_${ik}$ ), ldc, v( k+1, 1_${ik}$ ), ldv,cone, work, ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v**h if( n>k ) then ! c2 := c2 - w * v2**h call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,n-k, k, -cone, & work, ldwork, v( k+1, 1_${ik}$ ),ldv, cone, c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1**h call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v, ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 ) ! ( v2 ) (last k rows) ! where v2 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v = (c1**h * v1 + c2**h * v2) (stored in work) ! w := c2**h do j = 1, k call stdlib${ii}$_ccopy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_clacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v( m-& k+1, 1_${ik}$ ), ldv, work, ldwork ) if( m>k ) then ! w := w + c1**h * v1 call stdlib${ii}$_cgemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', n,k, m-k, cone, & c, ldc, v, ldv, cone, work,ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v * w**h if( m>k ) then ! c1 := c1 - v1 * w**h call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',m-k, n, k, -cone, & v, ldv, work, ldwork,cone, c, ldc ) end if ! w := w * v2**h call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v( m-k+1, 1_${ik}$ ), ldv, work,ldwork ) ! c2 := c2 - w**h do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) -conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_ccopy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v( n-& k+1, 1_${ik}$ ), ldv, work, ldwork ) if( n>k ) then ! w := w + c1 * v1 call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,cone, c, ldc, & v, ldv, cone, work, ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v**h if( n>k ) then ! c1 := c1 - w * v1**h call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,n-k, k, -cone, & work, ldwork, v, ldv, cone,c, ldc ) end if ! w := w * v2**h call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v( n-k+1, 1_${ik}$ ), ldv, work,ldwork ) ! c2 := c2 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if else if( stdlib_lsame( storev, 'R' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 v2 ) (v1: first k columns) ! where v1 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v**h = (c1**h * v1**h + c2**h * v2**h) (stored in work) ! w := c1**h do j = 1, k call stdlib${ii}$_ccopy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_clacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**h call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v, ldv, work, ldwork ) if( m>k ) then ! w := w + c2**h * v2**h call stdlib${ii}$_cgemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', n, k, m-k, & cone,c( k+1, 1_${ik}$ ), ldc, v( 1_${ik}$, k+1 ), ldv, cone,work, ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v**h * w**h if( m>k ) then ! c2 := c2 - v2**h * w**h call stdlib${ii}$_cgemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', m-k, n, k, & -cone,v( 1_${ik}$, k+1 ), ldv, work, ldwork, cone,c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1 call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v, & ldv, work, ldwork ) ! c1 := c1 - w**h do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v**h = (c1*v1**h + c2*v2**h) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_ccopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**h call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v, ldv, work, ldwork ) if( n>k ) then ! w := w + c2 * v2**h call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,k, n-k, cone, & c( 1_${ik}$, k+1 ), ldc,v( 1_${ik}$, k+1 ), ldv, cone, work, ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c2 := c2 - w * v2 call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-cone, work, & ldwork, v( 1_${ik}$, k+1 ), ldv, cone,c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1 call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v, & ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 v2 ) (v2: last k columns) ! where v2 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v**h = (c1**h * v1**h + c2**h * v2**h) (stored in work) ! w := c2**h do j = 1, k call stdlib${ii}$_ccopy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_clacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**h call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v( 1_${ik}$, m-k+1 ), ldv, work,ldwork ) if( m>k ) then ! w := w + c1**h * v1**h call stdlib${ii}$_cgemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', n, k, m-k, & cone, c,ldc, v, ldv, cone, work, ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v**h * w**h if( m>k ) then ! c1 := c1 - v1**h * w**h call stdlib${ii}$_cgemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', m-k, n, k, & -cone, v,ldv, work, ldwork, cone, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v( 1_${ik}$, & m-k+1 ), ldv, work, ldwork ) ! c2 := c2 - w**h do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) -conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v**h = (c1*v1**h + c2*v2**h) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_ccopy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**h call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v( 1_${ik}$, n-k+1 ), ldv, work,ldwork ) if( n>k ) then ! w := w + c1 * v1**h call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,k, n-k, cone, & c, ldc, v, ldv, cone, work,ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c1 := c1 - w * v1 call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-cone, work, & ldwork, v, ldv, cone, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v( 1_${ik}$, & n-k+1 ), ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if end if return end subroutine stdlib${ii}$_clarfb pure module subroutine stdlib${ii}$_zlarfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & !! ZLARFB applies a complex block reflector H or its transpose H**H to a !! complex M-by-N matrix C, from either the left or the right. work, ldwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n ! Array Arguments complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(in) :: t(ldt,*), v(ldv,*) complex(dp), intent(out) :: work(ldwork,*) ! ===================================================================== ! Local Scalars character :: transt integer(${ik}$) :: i, j ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( stdlib_lsame( trans, 'N' ) ) then transt = 'C' else transt = 'N' end if if( stdlib_lsame( storev, 'C' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 ) (first k rows) ! ( v2 ) ! where v1 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v = (c1**h * v1 + c2**h * v2) (stored in work) ! w := c1**h do j = 1, k call stdlib${ii}$_zcopy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v, & ldv, work, ldwork ) if( m>k ) then ! w := w + c2**h * v2 call stdlib${ii}$_zgemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', n,k, m-k, cone, & c( k+1, 1_${ik}$ ), ldc,v( k+1, 1_${ik}$ ), ldv, cone, work, ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v * w**h if( m>k ) then ! c2 := c2 - v2 * w**h call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',m-k, n, k, -cone, & v( k+1, 1_${ik}$ ), ldv, work,ldwork, cone, c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1**h call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v, ldv, work, ldwork ) ! c1 := c1 - w**h do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_zcopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v, & ldv, work, ldwork ) if( n>k ) then ! w := w + c2 * v2 call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,cone, c( 1_${ik}$, k+& 1_${ik}$ ), ldc, v( k+1, 1_${ik}$ ), ldv,cone, work, ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v**h if( n>k ) then ! c2 := c2 - w * v2**h call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,n-k, k, -cone, & work, ldwork, v( k+1, 1_${ik}$ ),ldv, cone, c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1**h call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v, ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 ) ! ( v2 ) (last k rows) ! where v2 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v = (c1**h * v1 + c2**h * v2) (stored in work) ! w := c2**h do j = 1, k call stdlib${ii}$_zcopy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v( m-& k+1, 1_${ik}$ ), ldv, work, ldwork ) if( m>k ) then ! w := w + c1**h * v1 call stdlib${ii}$_zgemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', n,k, m-k, cone, & c, ldc, v, ldv, cone, work,ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v * w**h if( m>k ) then ! c1 := c1 - v1 * w**h call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',m-k, n, k, -cone, & v, ldv, work, ldwork,cone, c, ldc ) end if ! w := w * v2**h call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v( m-k+1, 1_${ik}$ ), ldv, work,ldwork ) ! c2 := c2 - w**h do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) -conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_zcopy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v( n-& k+1, 1_${ik}$ ), ldv, work, ldwork ) if( n>k ) then ! w := w + c1 * v1 call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,cone, c, ldc, & v, ldv, cone, work, ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v**h if( n>k ) then ! c1 := c1 - w * v1**h call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,n-k, k, -cone, & work, ldwork, v, ldv, cone,c, ldc ) end if ! w := w * v2**h call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v( n-k+1, 1_${ik}$ ), ldv, work,ldwork ) ! c2 := c2 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if else if( stdlib_lsame( storev, 'R' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 v2 ) (v1: first k columns) ! where v1 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v**h = (c1**h * v1**h + c2**h * v2**h) (stored in work) ! w := c1**h do j = 1, k call stdlib${ii}$_zcopy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**h call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v, ldv, work, ldwork ) if( m>k ) then ! w := w + c2**h * v2**h call stdlib${ii}$_zgemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', n, k, m-k, & cone,c( k+1, 1_${ik}$ ), ldc, v( 1_${ik}$, k+1 ), ldv, cone,work, ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v**h * w**h if( m>k ) then ! c2 := c2 - v2**h * w**h call stdlib${ii}$_zgemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', m-k, n, k, & -cone,v( 1_${ik}$, k+1 ), ldv, work, ldwork, cone,c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1 call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v, & ldv, work, ldwork ) ! c1 := c1 - w**h do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v**h = (c1*v1**h + c2*v2**h) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_zcopy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**h call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v, ldv, work, ldwork ) if( n>k ) then ! w := w + c2 * v2**h call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,k, n-k, cone, & c( 1_${ik}$, k+1 ), ldc,v( 1_${ik}$, k+1 ), ldv, cone, work, ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c2 := c2 - w * v2 call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-cone, work, & ldwork, v( 1_${ik}$, k+1 ), ldv, cone,c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1 call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v, & ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 v2 ) (v2: last k columns) ! where v2 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v**h = (c1**h * v1**h + c2**h * v2**h) (stored in work) ! w := c2**h do j = 1, k call stdlib${ii}$_zcopy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_zlacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**h call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v( 1_${ik}$, m-k+1 ), ldv, work,ldwork ) if( m>k ) then ! w := w + c1**h * v1**h call stdlib${ii}$_zgemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', n, k, m-k, & cone, c,ldc, v, ldv, cone, work, ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v**h * w**h if( m>k ) then ! c1 := c1 - v1**h * w**h call stdlib${ii}$_zgemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', m-k, n, k, & -cone, v,ldv, work, ldwork, cone, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v( 1_${ik}$, & m-k+1 ), ldv, work, ldwork ) ! c2 := c2 - w**h do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) -conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v**h = (c1*v1**h + c2*v2**h) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_zcopy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**h call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v( 1_${ik}$, n-k+1 ), ldv, work,ldwork ) if( n>k ) then ! w := w + c1 * v1**h call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,k, n-k, cone, & c, ldc, v, ldv, cone, work,ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c1 := c1 - w * v1 call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-cone, work, & ldwork, v, ldv, cone, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v( 1_${ik}$, & n-k+1 ), ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if end if return end subroutine stdlib${ii}$_zlarfb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larfb( side, trans, direct, storev, m, n, k, v, ldv,t, ldt, c, ldc, & !! ZLARFB: applies a complex block reflector H or its transpose H**H to a !! complex M-by-N matrix C, from either the left or the right. work, ldwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, ldc, ldt, ldv, ldwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(in) :: t(ldt,*), v(ldv,*) complex(${ck}$), intent(out) :: work(ldwork,*) ! ===================================================================== ! Local Scalars character :: transt integer(${ik}$) :: i, j ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0 .or. n<=0 )return if( stdlib_lsame( trans, 'N' ) ) then transt = 'C' else transt = 'N' end if if( stdlib_lsame( storev, 'C' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 ) (first k rows) ! ( v2 ) ! where v1 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v = (c1**h * v1 + c2**h * v2) (stored in work) ! w := c1**h do j = 1, k call stdlib${ii}$_${ci}$copy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v, & ldv, work, ldwork ) if( m>k ) then ! w := w + c2**h * v2 call stdlib${ii}$_${ci}$gemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', n,k, m-k, cone, & c( k+1, 1_${ik}$ ), ldc,v( k+1, 1_${ik}$ ), ldv, cone, work, ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v * w**h if( m>k ) then ! c2 := c2 - v2 * w**h call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',m-k, n, k, -cone, & v( k+1, 1_${ik}$ ), ldv, work,ldwork, cone, c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v, ldv, work, ldwork ) ! c1 := c1 - w**h do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_${ci}$copy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1 call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v, & ldv, work, ldwork ) if( n>k ) then ! w := w + c2 * v2 call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,cone, c( 1_${ik}$, k+& 1_${ik}$ ), ldc, v( k+1, 1_${ik}$ ), ldv,cone, work, ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v**h if( n>k ) then ! c2 := c2 - w * v2**h call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,n-k, k, -cone, & work, ldwork, v( k+1, 1_${ik}$ ),ldv, cone, c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v, ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 ) ! ( v2 ) (last k rows) ! where v2 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v = (c1**h * v1 + c2**h * v2) (stored in work) ! w := c2**h do j = 1, k call stdlib${ii}$_${ci}$copy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v( m-& k+1, 1_${ik}$ ), ldv, work, ldwork ) if( m>k ) then ! w := w + c1**h * v1 call stdlib${ii}$_${ci}$gemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', n,k, m-k, cone, & c, ldc, v, ldv, cone, work,ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v * w**h if( m>k ) then ! c1 := c1 - v1 * w**h call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',m-k, n, k, -cone, & v, ldv, work, ldwork,cone, c, ldc ) end if ! w := w * v2**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v( m-k+1, 1_${ik}$ ), ldv, work,ldwork ) ! c2 := c2 - w**h do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) -conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v = (c1*v1 + c2*v2) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_${ci}$copy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2 call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v( n-& k+1, 1_${ik}$ ), ldv, work, ldwork ) if( n>k ) then ! w := w + c1 * v1 call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, k, n-k,cone, c, ldc, & v, ldv, cone, work, ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v**h if( n>k ) then ! c1 := c1 - w * v1**h call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,n-k, k, -cone, & work, ldwork, v, ldv, cone,c, ldc ) end if ! w := w * v2**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v( n-k+1, 1_${ik}$ ), ldv, work,ldwork ) ! c2 := c2 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if else if( stdlib_lsame( storev, 'R' ) ) then if( stdlib_lsame( direct, 'F' ) ) then ! let v = ( v1 v2 ) (v1: first k columns) ! where v1 is unit upper triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v**h = (c1**h * v1**h + c2**h * v2**h) (stored in work) ! w := c1**h do j = 1, k call stdlib${ii}$_${ci}$copy( n, c( j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v, ldv, work, ldwork ) if( m>k ) then ! w := w + c2**h * v2**h call stdlib${ii}$_${ci}$gemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', n, k, m-k, & cone,c( k+1, 1_${ik}$ ), ldc, v( 1_${ik}$, k+1 ), ldv, cone,work, ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v**h * w**h if( m>k ) then ! c2 := c2 - v2**h * w**h call stdlib${ii}$_${ci}$gemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', m-k, n, k, & -cone,v( 1_${ik}$, k+1 ), ldv, work, ldwork, cone,c( k+1, 1_${ik}$ ), ldc ) end if ! w := w * v1 call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v, & ldv, work, ldwork ) ! c1 := c1 - w**h do j = 1, k do i = 1, n c( j, i ) = c( j, i ) - conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v**h = (c1*v1**h + c2*v2**h) (stored in work) ! w := c1 do j = 1, k call stdlib${ii}$_${ci}$copy( m, c( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v1**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v, ldv, work, ldwork ) if( n>k ) then ! w := w + c2 * v2**h call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,k, n-k, cone, & c( 1_${ik}$, k+1 ), ldc,v( 1_${ik}$, k+1 ), ldv, cone, work, ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c2 := c2 - w * v2 call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-cone, work, & ldwork, v( 1_${ik}$, k+1 ), ldv, cone,c( 1_${ik}$, k+1 ), ldc ) end if ! w := w * v1 call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v, & ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, j ) = c( i, j ) - work( i, j ) end do end do end if else ! let v = ( v1 v2 ) (v2: last k columns) ! where v2 is unit lower triangular. if( stdlib_lsame( side, 'L' ) ) then ! form h * c or h**h * c where c = ( c1 ) ! ( c2 ) ! w := c**h * v**h = (c1**h * v1**h + c2**h * v2**h) (stored in work) ! w := c2**h do j = 1, k call stdlib${ii}$_${ci}$copy( n, c( m-k+j, 1_${ik}$ ), ldc, work( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( n, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', n, k, cone,& v( 1_${ik}$, m-k+1 ), ldv, work,ldwork ) if( m>k ) then ! w := w + c1**h * v1**h call stdlib${ii}$_${ci}$gemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', n, k, m-k, & cone, c,ldc, v, ldv, cone, work, ldwork ) end if ! w := w * t**h or w * t call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', transt, 'NON-UNIT', n, k,cone, t, ldt, & work, ldwork ) ! c := c - v**h * w**h if( m>k ) then ! c1 := c1 - v1**h * w**h call stdlib${ii}$_${ci}$gemm( 'CONJUGATE TRANSPOSE','CONJUGATE TRANSPOSE', m-k, n, k, & -cone, v,ldv, work, ldwork, cone, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', n,k, cone, v( 1_${ik}$, & m-k+1 ), ldv, work, ldwork ) ! c2 := c2 - w**h do j = 1, k do i = 1, n c( m-k+j, i ) = c( m-k+j, i ) -conjg( work( i, j ) ) end do end do else if( stdlib_lsame( side, 'R' ) ) then ! form c * h or c * h**h where c = ( c1 c2 ) ! w := c * v**h = (c1*v1**h + c2*v2**h) (stored in work) ! w := c2 do j = 1, k call stdlib${ii}$_${ci}$copy( m, c( 1_${ik}$, n-k+j ), 1_${ik}$, work( 1_${ik}$, j ), 1_${ik}$ ) end do ! w := w * v2**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', m, k, cone,& v( 1_${ik}$, n-k+1 ), ldv, work,ldwork ) if( n>k ) then ! w := w + c1 * v1**h call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE', m,k, n-k, cone, & c, ldc, v, ldv, cone, work,ldwork ) end if ! w := w * t or w * t**h call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', trans, 'NON-UNIT', m, k,cone, t, ldt, & work, ldwork ) ! c := c - w * v if( n>k ) then ! c1 := c1 - w * v1 call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m, n-k, k,-cone, work, & ldwork, v, ldv, cone, c, ldc ) end if ! w := w * v2 call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', m,k, cone, v( 1_${ik}$, & n-k+1 ), ldv, work, ldwork ) ! c1 := c1 - w do j = 1, k do i = 1, m c( i, n-k+j ) = c( i, n-k+j ) - work( i, j ) end do end do end if end if end if return end subroutine stdlib${ii}$_${ci}$larfb #:endif #:endfor pure module subroutine stdlib${ii}$_slarfg( n, alpha, x, incx, tau ) !! SLARFG generates a real elementary reflector H of order n, such !! that !! H * ( alpha ) = ( beta ), H**T * H = I. !! ( x ) ( 0 ) !! where alpha and beta are scalars, and x is an (n-1)-element real !! vector. H is represented in the form !! H = I - tau * ( 1 ) * ( 1 v**T ) , !! ( v ) !! where tau is a real scalar and v is a real (n-1)-element !! vector. !! If the elements of x are all zero, then tau = 0 and H is taken to be !! the unit matrix. !! Otherwise 1 <= tau <= 2. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n real(sp), intent(inout) :: alpha real(sp), intent(out) :: tau ! Array Arguments real(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, knt real(sp) :: beta, rsafmn, safmin, xnorm ! Intrinsic Functions ! Executable Statements if( n<=1_${ik}$ ) then tau = zero return end if xnorm = stdlib${ii}$_snrm2( n-1, x, incx ) if( xnorm==zero ) then ! h = i tau = zero else ! general case beta = -sign( stdlib${ii}$_slapy2( alpha, xnorm ), alpha ) safmin = stdlib${ii}$_slamch( 'S' ) / stdlib${ii}$_slamch( 'E' ) knt = 0_${ik}$ if( abs( beta )= 0. if( alpha>=zero ) then ! when tau.eq.zero, the vector is special-cased to be ! all zeros in the application routines. we do not need ! to clear it. tau = zero else ! however, the application routines rely on explicit ! zero checks when tau.ne.zero, and we must clear x. tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = 0_${ik}$ end do alpha = -alpha end if else ! general case beta = sign( stdlib${ii}$_slapy2( alpha, xnorm ), alpha ) smlnum = stdlib${ii}$_slamch( 'S' ) / stdlib${ii}$_slamch( 'E' ) knt = 0_${ik}$ if( abs( beta )=zero ) then tau = zero else tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = 0_${ik}$ end do beta = -savealpha end if else ! this is the general case. call stdlib${ii}$_sscal( n-1, one / alpha, x, incx ) end if ! if beta is subnormal, it may lose relative accuracy do j = 1, knt beta = beta*smlnum end do alpha = beta end if return end subroutine stdlib${ii}$_slarfgp module subroutine stdlib${ii}$_dlarfgp( n, alpha, x, incx, tau ) !! DLARFGP generates a real elementary reflector H of order n, such !! that !! H * ( alpha ) = ( beta ), H**T * H = I. !! ( x ) ( 0 ) !! where alpha and beta are scalars, beta is non-negative, and x is !! an (n-1)-element real vector. H is represented in the form !! H = I - tau * ( 1 ) * ( 1 v**T ) , !! ( v ) !! where tau is a real scalar and v is a real (n-1)-element !! vector. !! If the elements of x are all zero, then tau = 0 and H is taken to be !! the unit matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n real(dp), intent(inout) :: alpha real(dp), intent(out) :: tau ! Array Arguments real(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, knt real(dp) :: beta, bignum, savealpha, smlnum, xnorm ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then tau = zero return end if xnorm = stdlib${ii}$_dnrm2( n-1, x, incx ) if( xnorm==zero ) then ! h = [+/-1, 0; i], sign chosen so alpha >= 0 if( alpha>=zero ) then ! when tau.eq.zero, the vector is special-cased to be ! all zeros in the application routines. we do not need ! to clear it. tau = zero else ! however, the application routines rely on explicit ! zero checks when tau.ne.zero, and we must clear x. tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = 0_${ik}$ end do alpha = -alpha end if else ! general case beta = sign( stdlib${ii}$_dlapy2( alpha, xnorm ), alpha ) smlnum = stdlib${ii}$_dlamch( 'S' ) / stdlib${ii}$_dlamch( 'E' ) knt = 0_${ik}$ if( abs( beta )=zero ) then tau = zero else tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = 0_${ik}$ end do beta = -savealpha end if else ! this is the general case. call stdlib${ii}$_dscal( n-1, one / alpha, x, incx ) end if ! if beta is subnormal, it may lose relative accuracy do j = 1, knt beta = beta*smlnum end do alpha = beta end if return end subroutine stdlib${ii}$_dlarfgp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$larfgp( n, alpha, x, incx, tau ) !! DLARFGP: generates a real elementary reflector H of order n, such !! that !! H * ( alpha ) = ( beta ), H**T * H = I. !! ( x ) ( 0 ) !! where alpha and beta are scalars, beta is non-negative, and x is !! an (n-1)-element real vector. H is represented in the form !! H = I - tau * ( 1 ) * ( 1 v**T ) , !! ( v ) !! where tau is a real scalar and v is a real (n-1)-element !! vector. !! If the elements of x are all zero, then tau = 0 and H is taken to be !! the unit matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n real(${rk}$), intent(inout) :: alpha real(${rk}$), intent(out) :: tau ! Array Arguments real(${rk}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, knt real(${rk}$) :: beta, bignum, savealpha, smlnum, xnorm ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then tau = zero return end if xnorm = stdlib${ii}$_${ri}$nrm2( n-1, x, incx ) if( xnorm==zero ) then ! h = [+/-1, 0; i], sign chosen so alpha >= 0 if( alpha>=zero ) then ! when tau.eq.zero, the vector is special-cased to be ! all zeros in the application routines. we do not need ! to clear it. tau = zero else ! however, the application routines rely on explicit ! zero checks when tau.ne.zero, and we must clear x. tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = 0_${ik}$ end do alpha = -alpha end if else ! general case beta = sign( stdlib${ii}$_${ri}$lapy2( alpha, xnorm ), alpha ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) / stdlib${ii}$_${ri}$lamch( 'E' ) knt = 0_${ik}$ if( abs( beta )=zero ) then tau = zero else tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = 0_${ik}$ end do beta = -savealpha end if else ! this is the general case. call stdlib${ii}$_${ri}$scal( n-1, one / alpha, x, incx ) end if ! if beta is subnormal, it may lose relative accuracy do j = 1, knt beta = beta*smlnum end do alpha = beta end if return end subroutine stdlib${ii}$_${ri}$larfgp #:endif #:endfor module subroutine stdlib${ii}$_clarfgp( n, alpha, x, incx, tau ) !! CLARFGP generates a complex elementary reflector H of order n, such !! that !! H**H * ( alpha ) = ( beta ), H**H * H = I. !! ( x ) ( 0 ) !! where alpha and beta are scalars, beta is real and non-negative, and !! x is an (n-1)-element complex vector. H is represented in the form !! H = I - tau * ( 1 ) * ( 1 v**H ) , !! ( v ) !! where tau is a complex scalar and v is a complex (n-1)-element !! vector. Note that H is not hermitian. !! If the elements of x are all zero and alpha is real, then tau = 0 !! and H is taken to be the unit matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n complex(sp), intent(inout) :: alpha complex(sp), intent(out) :: tau ! Array Arguments complex(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, knt real(sp) :: alphi, alphr, beta, bignum, smlnum, xnorm complex(sp) :: savealpha ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then tau = zero return end if xnorm = stdlib${ii}$_scnrm2( n-1, x, incx ) alphr = real( alpha,KIND=sp) alphi = aimag( alpha ) if( xnorm==zero ) then ! h = [1-alpha/abs(alpha) 0; 0 i], sign chosen so alpha >= 0. if( alphi==zero ) then if( alphr>=zero ) then ! when tau.eq.zero, the vector is special-cased to be ! all zeros in the application routines. we do not need ! to clear it. tau = zero else ! however, the application routines rely on explicit ! zero checks when tau.ne.zero, and we must clear x. tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do alpha = -alpha end if else ! only "reflecting" the diagonal entry to be real and non-negative. xnorm = stdlib${ii}$_slapy2( alphr, alphi ) tau = cmplx( one - alphr / xnorm, -alphi / xnorm,KIND=sp) do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do alpha = xnorm end if else ! general case beta = sign( stdlib${ii}$_slapy3( alphr, alphi, xnorm ), alphr ) smlnum = stdlib${ii}$_slamch( 'S' ) / stdlib${ii}$_slamch( 'E' ) bignum = one / smlnum knt = 0_${ik}$ if( abs( beta )=zero ) then tau = zero else tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do beta = real( -savealpha,KIND=sp) end if else xnorm = stdlib${ii}$_slapy2( alphr, alphi ) tau = cmplx( one - alphr / xnorm, -alphi / xnorm,KIND=sp) do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do beta = xnorm end if else ! this is the general case. call stdlib${ii}$_cscal( n-1, alpha, x, incx ) end if ! if beta is subnormal, it may lose relative accuracy do j = 1, knt beta = beta*smlnum end do alpha = beta end if return end subroutine stdlib${ii}$_clarfgp module subroutine stdlib${ii}$_zlarfgp( n, alpha, x, incx, tau ) !! ZLARFGP generates a complex elementary reflector H of order n, such !! that !! H**H * ( alpha ) = ( beta ), H**H * H = I. !! ( x ) ( 0 ) !! where alpha and beta are scalars, beta is real and non-negative, and !! x is an (n-1)-element complex vector. H is represented in the form !! H = I - tau * ( 1 ) * ( 1 v**H ) , !! ( v ) !! where tau is a complex scalar and v is a complex (n-1)-element !! vector. Note that H is not hermitian. !! If the elements of x are all zero and alpha is real, then tau = 0 !! and H is taken to be the unit matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n complex(dp), intent(inout) :: alpha complex(dp), intent(out) :: tau ! Array Arguments complex(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, knt real(dp) :: alphi, alphr, beta, bignum, smlnum, xnorm complex(dp) :: savealpha ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then tau = zero return end if xnorm = stdlib${ii}$_dznrm2( n-1, x, incx ) alphr = real( alpha,KIND=dp) alphi = aimag( alpha ) if( xnorm==zero ) then ! h = [1-alpha/abs(alpha) 0; 0 i], sign chosen so alpha >= 0. if( alphi==zero ) then if( alphr>=zero ) then ! when tau.eq.zero, the vector is special-cased to be ! all zeros in the application routines. we do not need ! to clear it. tau = zero else ! however, the application routines rely on explicit ! zero checks when tau.ne.zero, and we must clear x. tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do alpha = -alpha end if else ! only "reflecting" the diagonal entry to be real and non-negative. xnorm = stdlib${ii}$_dlapy2( alphr, alphi ) tau = cmplx( one - alphr / xnorm, -alphi / xnorm,KIND=dp) do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do alpha = xnorm end if else ! general case beta = sign( stdlib${ii}$_dlapy3( alphr, alphi, xnorm ), alphr ) smlnum = stdlib${ii}$_dlamch( 'S' ) / stdlib${ii}$_dlamch( 'E' ) bignum = one / smlnum knt = 0_${ik}$ if( abs( beta )=zero ) then tau = zero else tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do beta = real( -savealpha,KIND=dp) end if else xnorm = stdlib${ii}$_dlapy2( alphr, alphi ) tau = cmplx( one - alphr / xnorm, -alphi / xnorm,KIND=dp) do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do beta = xnorm end if else ! this is the general case. call stdlib${ii}$_zscal( n-1, alpha, x, incx ) end if ! if beta is subnormal, it may lose relative accuracy do j = 1, knt beta = beta*smlnum end do alpha = beta end if return end subroutine stdlib${ii}$_zlarfgp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$larfgp( n, alpha, x, incx, tau ) !! ZLARFGP: generates a complex elementary reflector H of order n, such !! that !! H**H * ( alpha ) = ( beta ), H**H * H = I. !! ( x ) ( 0 ) !! where alpha and beta are scalars, beta is real and non-negative, and !! x is an (n-1)-element complex vector. H is represented in the form !! H = I - tau * ( 1 ) * ( 1 v**H ) , !! ( v ) !! where tau is a complex scalar and v is a complex (n-1)-element !! vector. Note that H is not hermitian. !! If the elements of x are all zero and alpha is real, then tau = 0 !! and H is taken to be the unit matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n complex(${ck}$), intent(inout) :: alpha complex(${ck}$), intent(out) :: tau ! Array Arguments complex(${ck}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, knt real(${ck}$) :: alphi, alphr, beta, bignum, smlnum, xnorm complex(${ck}$) :: savealpha ! Intrinsic Functions ! Executable Statements if( n<=0_${ik}$ ) then tau = zero return end if xnorm = stdlib${ii}$_${c2ri(ci)}$znrm2( n-1, x, incx ) alphr = real( alpha,KIND=${ck}$) alphi = aimag( alpha ) if( xnorm==zero ) then ! h = [1-alpha/abs(alpha) 0; 0 i], sign chosen so alpha >= 0. if( alphi==zero ) then if( alphr>=zero ) then ! when tau.eq.zero, the vector is special-cased to be ! all zeros in the application routines. we do not need ! to clear it. tau = zero else ! however, the application routines rely on explicit ! zero checks when tau.ne.zero, and we must clear x. tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do alpha = -alpha end if else ! only "reflecting" the diagonal entry to be real and non-negative. xnorm = stdlib${ii}$_${c2ri(ci)}$lapy2( alphr, alphi ) tau = cmplx( one - alphr / xnorm, -alphi / xnorm,KIND=${ck}$) do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do alpha = xnorm end if else ! general case beta = sign( stdlib${ii}$_${c2ri(ci)}$lapy3( alphr, alphi, xnorm ), alphr ) smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) / stdlib${ii}$_${c2ri(ci)}$lamch( 'E' ) bignum = one / smlnum knt = 0_${ik}$ if( abs( beta )=zero ) then tau = zero else tau = two do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do beta = real( -savealpha,KIND=${ck}$) end if else xnorm = stdlib${ii}$_${c2ri(ci)}$lapy2( alphr, alphi ) tau = cmplx( one - alphr / xnorm, -alphi / xnorm,KIND=${ck}$) do j = 1, n-1 x( 1_${ik}$ + (j-1)*incx ) = zero end do beta = xnorm end if else ! this is the general case. call stdlib${ii}$_${ci}$scal( n-1, alpha, x, incx ) end if ! if beta is subnormal, it may lose relative accuracy do j = 1, knt beta = beta*smlnum end do alpha = beta end if return end subroutine stdlib${ii}$_${ci}$larfgp #:endif #:endfor pure module subroutine stdlib${ii}$_slarft( direct, storev, n, k, v, ldv, tau, t, ldt ) !! SLARFT forms the triangular factor T of a real block reflector H !! of order n, which is defined as a product of k elementary reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**T !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**T * T * V ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments real(sp), intent(out) :: t(ldt,*) real(sp), intent(in) :: tau(*), v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, prevlastv, lastv ! Executable Statements ! quick return if possible if( n==0 )return if( stdlib_lsame( direct, 'F' ) ) then prevlastv = n do i = 1, k prevlastv = max( i, prevlastv ) if( tau( i )==zero ) then ! h(i) = i do j = 1, i t( j, i ) = zero end do else ! general case if( stdlib_lsame( storev, 'C' ) ) then ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( lastv, i )/=zero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * v( i , j ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(i:j,1:i-1)**t * v(i:j,i) call stdlib${ii}$_sgemv( 'TRANSPOSE', j-i, i-1, -tau( i ),v( i+1, 1_${ik}$ ), ldv, v( i+& 1_${ik}$, i ), 1_${ik}$, one,t( 1_${ik}$, i ), 1_${ik}$ ) else ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( i, lastv )/=zero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * v( j , i ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(1:i-1,i:j) * v(i,i:j)**t call stdlib${ii}$_sgemv( 'NO TRANSPOSE', i-1, j-i, -tau( i ),v( 1_${ik}$, i+1 ), ldv, v(& i, i+1 ), ldv,one, t( 1_${ik}$, i ), 1_${ik}$ ) end if ! t(1:i-1,i) := t(1:i-1,1:i-1) * t(1:i-1,i) call stdlib${ii}$_strmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', i-1, t,ldt, t( 1_${ik}$, i ),& 1_${ik}$ ) t( i, i ) = tau( i ) if( i>1_${ik}$ ) then prevlastv = max( prevlastv, lastv ) else prevlastv = lastv end if end if end do else prevlastv = 1_${ik}$ do i = k, 1, -1 if( tau( i )==zero ) then ! h(i) = i do j = i, k t( j, i ) = zero end do else ! general case if( i1_${ik}$ ) then prevlastv = min( prevlastv, lastv ) else prevlastv = lastv end if end if t( i, i ) = tau( i ) end if end do end if return end subroutine stdlib${ii}$_slarft pure module subroutine stdlib${ii}$_dlarft( direct, storev, n, k, v, ldv, tau, t, ldt ) !! DLARFT forms the triangular factor T of a real block reflector H !! of order n, which is defined as a product of k elementary reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**T !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**T * T * V ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments real(dp), intent(out) :: t(ldt,*) real(dp), intent(in) :: tau(*), v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, prevlastv, lastv ! Executable Statements ! quick return if possible if( n==0 )return if( stdlib_lsame( direct, 'F' ) ) then prevlastv = n do i = 1, k prevlastv = max( i, prevlastv ) if( tau( i )==zero ) then ! h(i) = i do j = 1, i t( j, i ) = zero end do else ! general case if( stdlib_lsame( storev, 'C' ) ) then ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( lastv, i )/=zero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * v( i , j ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(i:j,1:i-1)**t * v(i:j,i) call stdlib${ii}$_dgemv( 'TRANSPOSE', j-i, i-1, -tau( i ),v( i+1, 1_${ik}$ ), ldv, v( i+& 1_${ik}$, i ), 1_${ik}$, one,t( 1_${ik}$, i ), 1_${ik}$ ) else ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( i, lastv )/=zero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * v( j , i ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(1:i-1,i:j) * v(i,i:j)**t call stdlib${ii}$_dgemv( 'NO TRANSPOSE', i-1, j-i, -tau( i ),v( 1_${ik}$, i+1 ), ldv, v(& i, i+1 ), ldv, one,t( 1_${ik}$, i ), 1_${ik}$ ) end if ! t(1:i-1,i) := t(1:i-1,1:i-1) * t(1:i-1,i) call stdlib${ii}$_dtrmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', i-1, t,ldt, t( 1_${ik}$, i ),& 1_${ik}$ ) t( i, i ) = tau( i ) if( i>1_${ik}$ ) then prevlastv = max( prevlastv, lastv ) else prevlastv = lastv end if end if end do else prevlastv = 1_${ik}$ do i = k, 1, -1 if( tau( i )==zero ) then ! h(i) = i do j = i, k t( j, i ) = zero end do else ! general case if( i1_${ik}$ ) then prevlastv = min( prevlastv, lastv ) else prevlastv = lastv end if end if t( i, i ) = tau( i ) end if end do end if return end subroutine stdlib${ii}$_dlarft #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larft( direct, storev, n, k, v, ldv, tau, t, ldt ) !! DLARFT: forms the triangular factor T of a real block reflector H !! of order n, which is defined as a product of k elementary reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**T !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**T * T * V ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments real(${rk}$), intent(out) :: t(ldt,*) real(${rk}$), intent(in) :: tau(*), v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, prevlastv, lastv ! Executable Statements ! quick return if possible if( n==0 )return if( stdlib_lsame( direct, 'F' ) ) then prevlastv = n do i = 1, k prevlastv = max( i, prevlastv ) if( tau( i )==zero ) then ! h(i) = i do j = 1, i t( j, i ) = zero end do else ! general case if( stdlib_lsame( storev, 'C' ) ) then ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( lastv, i )/=zero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * v( i , j ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(i:j,1:i-1)**t * v(i:j,i) call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', j-i, i-1, -tau( i ),v( i+1, 1_${ik}$ ), ldv, v( i+& 1_${ik}$, i ), 1_${ik}$, one,t( 1_${ik}$, i ), 1_${ik}$ ) else ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( i, lastv )/=zero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * v( j , i ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(1:i-1,i:j) * v(i,i:j)**t call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', i-1, j-i, -tau( i ),v( 1_${ik}$, i+1 ), ldv, v(& i, i+1 ), ldv, one,t( 1_${ik}$, i ), 1_${ik}$ ) end if ! t(1:i-1,i) := t(1:i-1,1:i-1) * t(1:i-1,i) call stdlib${ii}$_${ri}$trmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', i-1, t,ldt, t( 1_${ik}$, i ),& 1_${ik}$ ) t( i, i ) = tau( i ) if( i>1_${ik}$ ) then prevlastv = max( prevlastv, lastv ) else prevlastv = lastv end if end if end do else prevlastv = 1_${ik}$ do i = k, 1, -1 if( tau( i )==zero ) then ! h(i) = i do j = i, k t( j, i ) = zero end do else ! general case if( i1_${ik}$ ) then prevlastv = min( prevlastv, lastv ) else prevlastv = lastv end if end if t( i, i ) = tau( i ) end if end do end if return end subroutine stdlib${ii}$_${ri}$larft #:endif #:endfor pure module subroutine stdlib${ii}$_clarft( direct, storev, n, k, v, ldv, tau, t, ldt ) !! CLARFT forms the triangular factor T of a complex block reflector H !! of order n, which is defined as a product of k elementary reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**H !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**H * T * V ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments complex(sp), intent(out) :: t(ldt,*) complex(sp), intent(in) :: tau(*), v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, prevlastv, lastv ! Executable Statements ! quick return if possible if( n==0 )return if( stdlib_lsame( direct, 'F' ) ) then prevlastv = n do i = 1, k prevlastv = max( prevlastv, i ) if( tau( i )==czero ) then ! h(i) = i do j = 1, i t( j, i ) = czero end do else ! general case if( stdlib_lsame( storev, 'C' ) ) then ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( lastv, i )/=czero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * conjg( v( i , j ) ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(i:j,1:i-1)**h * v(i:j,i) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', j-i, i-1,-tau( i ), v( i+1, 1_${ik}$ ), & ldv,v( i+1, i ), 1_${ik}$,cone, t( 1_${ik}$, i ), 1_${ik}$ ) else ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( i, lastv )/=czero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * v( j , i ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(1:i-1,i:j) * v(i,i:j)**h call stdlib${ii}$_cgemm( 'N', 'C', i-1, 1_${ik}$, j-i, -tau( i ),v( 1_${ik}$, i+1 ), ldv, v( i,& i+1 ), ldv,cone, t( 1_${ik}$, i ), ldt ) end if ! t(1:i-1,i) := t(1:i-1,1:i-1) * t(1:i-1,i) call stdlib${ii}$_ctrmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', i-1, t,ldt, t( 1_${ik}$, i ),& 1_${ik}$ ) t( i, i ) = tau( i ) if( i>1_${ik}$ ) then prevlastv = max( prevlastv, lastv ) else prevlastv = lastv end if end if end do else prevlastv = 1_${ik}$ do i = k, 1, -1 if( tau( i )==czero ) then ! h(i) = i do j = i, k t( j, i ) = czero end do else ! general case if( i1_${ik}$ ) then prevlastv = min( prevlastv, lastv ) else prevlastv = lastv end if end if t( i, i ) = tau( i ) end if end do end if return end subroutine stdlib${ii}$_clarft pure module subroutine stdlib${ii}$_zlarft( direct, storev, n, k, v, ldv, tau, t, ldt ) !! ZLARFT forms the triangular factor T of a complex block reflector H !! of order n, which is defined as a product of k elementary reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**H !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**H * T * V ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments complex(dp), intent(out) :: t(ldt,*) complex(dp), intent(in) :: tau(*), v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, prevlastv, lastv ! Executable Statements ! quick return if possible if( n==0 )return if( stdlib_lsame( direct, 'F' ) ) then prevlastv = n do i = 1, k prevlastv = max( prevlastv, i ) if( tau( i )==czero ) then ! h(i) = i do j = 1, i t( j, i ) = czero end do else ! general case if( stdlib_lsame( storev, 'C' ) ) then ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( lastv, i )/=czero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * conjg( v( i , j ) ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(i:j,1:i-1)**h * v(i:j,i) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', j-i, i-1,-tau( i ), v( i+1, 1_${ik}$ ), & ldv,v( i+1, i ), 1_${ik}$, cone, t( 1_${ik}$, i ), 1_${ik}$ ) else ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( i, lastv )/=czero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * v( j , i ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(1:i-1,i:j) * v(i,i:j)**h call stdlib${ii}$_zgemm( 'N', 'C', i-1, 1_${ik}$, j-i, -tau( i ),v( 1_${ik}$, i+1 ), ldv, v( i,& i+1 ), ldv,cone, t( 1_${ik}$, i ), ldt ) end if ! t(1:i-1,i) := t(1:i-1,1:i-1) * t(1:i-1,i) call stdlib${ii}$_ztrmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', i-1, t,ldt, t( 1_${ik}$, i ),& 1_${ik}$ ) t( i, i ) = tau( i ) if( i>1_${ik}$ ) then prevlastv = max( prevlastv, lastv ) else prevlastv = lastv end if end if end do else prevlastv = 1_${ik}$ do i = k, 1, -1 if( tau( i )==czero ) then ! h(i) = i do j = i, k t( j, i ) = czero end do else ! general case if( i1_${ik}$ ) then prevlastv = min( prevlastv, lastv ) else prevlastv = lastv end if end if t( i, i ) = tau( i ) end if end do end if return end subroutine stdlib${ii}$_zlarft #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larft( direct, storev, n, k, v, ldv, tau, t, ldt ) !! ZLARFT: forms the triangular factor T of a complex block reflector H !! of order n, which is defined as a product of k elementary reflectors. !! If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; !! If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. !! If STOREV = 'C', the vector which defines the elementary reflector !! H(i) is stored in the i-th column of the array V, and !! H = I - V * T * V**H !! If STOREV = 'R', the vector which defines the elementary reflector !! H(i) is stored in the i-th row of the array V, and !! H = I - V**H * T * V ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n ! Array Arguments complex(${ck}$), intent(out) :: t(ldt,*) complex(${ck}$), intent(in) :: tau(*), v(ldv,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, prevlastv, lastv ! Executable Statements ! quick return if possible if( n==0 )return if( stdlib_lsame( direct, 'F' ) ) then prevlastv = n do i = 1, k prevlastv = max( prevlastv, i ) if( tau( i )==czero ) then ! h(i) = i do j = 1, i t( j, i ) = czero end do else ! general case if( stdlib_lsame( storev, 'C' ) ) then ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( lastv, i )/=czero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * conjg( v( i , j ) ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(i:j,1:i-1)**h * v(i:j,i) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', j-i, i-1,-tau( i ), v( i+1, 1_${ik}$ ), & ldv,v( i+1, i ), 1_${ik}$, cone, t( 1_${ik}$, i ), 1_${ik}$ ) else ! skip any trailing zeros. do lastv = n, i+1, -1 if( v( i, lastv )/=czero ) exit end do do j = 1, i-1 t( j, i ) = -tau( i ) * v( j , i ) end do j = min( lastv, prevlastv ) ! t(1:i-1,i) := - tau(i) * v(1:i-1,i:j) * v(i,i:j)**h call stdlib${ii}$_${ci}$gemm( 'N', 'C', i-1, 1_${ik}$, j-i, -tau( i ),v( 1_${ik}$, i+1 ), ldv, v( i,& i+1 ), ldv,cone, t( 1_${ik}$, i ), ldt ) end if ! t(1:i-1,i) := t(1:i-1,1:i-1) * t(1:i-1,i) call stdlib${ii}$_${ci}$trmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', i-1, t,ldt, t( 1_${ik}$, i ),& 1_${ik}$ ) t( i, i ) = tau( i ) if( i>1_${ik}$ ) then prevlastv = max( prevlastv, lastv ) else prevlastv = lastv end if end if end do else prevlastv = 1_${ik}$ do i = k, 1, -1 if( tau( i )==czero ) then ! h(i) = i do j = i, k t( j, i ) = czero end do else ! general case if( i1_${ik}$ ) then prevlastv = min( prevlastv, lastv ) else prevlastv = lastv end if end if t( i, i ) = tau( i ) end if end do end if return end subroutine stdlib${ii}$_${ci}$larft #:endif #:endfor #:endfor end submodule stdlib_lapack_householder_reflectors fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_blas_like_scalar.fypp0000664000175000017500000006606315135654166027251 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_base) stdlib_lapack_blas_like_scalar implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure logical(lk) module function stdlib${ii}$_sisnan( sin ) !! SISNAN returns .TRUE. if its argument is NaN, and .FALSE. !! otherwise. To be replaced by the Fortran 2003 intrinsic in the !! future. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: sin ! ===================================================================== ! Executable Statements stdlib${ii}$_sisnan = stdlib${ii}$_slaisnan(sin,sin) return end function stdlib${ii}$_sisnan pure logical(lk) module function stdlib${ii}$_disnan( din ) !! DISNAN returns .TRUE. if its argument is NaN, and .FALSE. !! otherwise. To be replaced by the Fortran 2003 intrinsic in the !! future. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: din ! ===================================================================== ! Executable Statements stdlib${ii}$_disnan = stdlib${ii}$_dlaisnan(din,din) return end function stdlib${ii}$_disnan #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure logical(lk) module function stdlib${ii}$_${ri}$isnan( din ) !! DISNAN: returns .TRUE. if its argument is NaN, and .FALSE. !! otherwise. To be replaced by the Fortran 2003 intrinsic in the !! future. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: din ! ===================================================================== ! Executable Statements stdlib${ii}$_${ri}$isnan = stdlib${ii}$_${ri}$laisnan(din,din) return end function stdlib${ii}$_${ri}$isnan #:endif #:endfor pure logical(lk) module function stdlib${ii}$_slaisnan( sin1, sin2 ) !! This routine is not for general use. It exists solely to avoid !! over-optimization in SISNAN. !! SLAISNAN checks for NaNs by comparing its two arguments for !! inequality. NaN is the only floating-point value where NaN != NaN !! returns .TRUE. To check for NaNs, pass the same variable as both use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone !! arguments. !! A compiler must assume that the two arguments are !! not the same variable, and the test will not be optimized away. !! Interprocedural or whole-program optimization may delete this !! test. The ISNAN functions will be replaced by the correct !! Fortran 03 intrinsic once the intrinsic is widely available. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: sin1, sin2 ! ===================================================================== ! Executable Statements stdlib${ii}$_slaisnan = (sin1/=sin2) return end function stdlib${ii}$_slaisnan pure logical(lk) module function stdlib${ii}$_dlaisnan( din1, din2 ) !! This routine is not for general use. It exists solely to avoid !! over-optimization in DISNAN. !! DLAISNAN checks for NaNs by comparing its two arguments for !! inequality. NaN is the only floating-point value where NaN != NaN !! returns .TRUE. To check for NaNs, pass the same variable as both use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone !! arguments. !! A compiler must assume that the two arguments are !! not the same variable, and the test will not be optimized away. !! Interprocedural or whole-program optimization may delete this !! test. The ISNAN functions will be replaced by the correct !! Fortran 03 intrinsic once the intrinsic is widely available. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: din1, din2 ! ===================================================================== ! Executable Statements stdlib${ii}$_dlaisnan = (din1/=din2) return end function stdlib${ii}$_dlaisnan #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure logical(lk) module function stdlib${ii}$_${ri}$laisnan( din1, din2 ) !! This routine is not for general use. It exists solely to avoid !! over-optimization in DISNAN. !! DLAISNAN: checks for NaNs by comparing its two arguments for !! inequality. NaN is the only floating-point value where NaN != NaN !! returns .TRUE. To check for NaNs, pass the same variable as both use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone !! arguments. !! A compiler must assume that the two arguments are !! not the same variable, and the test will not be optimized away. !! Interprocedural or whole-program optimization may delete this !! test. The ISNAN functions will be replaced by the correct !! Fortran 03 intrinsic once the intrinsic is widely available. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: din1, din2 ! ===================================================================== ! Executable Statements stdlib${ii}$_${ri}$laisnan = (din1/=din2) return end function stdlib${ii}$_${ri}$laisnan #:endif #:endfor pure module subroutine stdlib${ii}$_sladiv( a, b, c, d, p, q ) !! SLADIV performs complex division in real arithmetic !! a + i*b !! p + i*q = --------- !! c + i*d !! The algorithm is due to Michael Baudin and Robert L. Smith !! and can be found in the paper !! "A Robust Complex Division in Scilab" ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: a, b, c, d real(sp), intent(out) :: p, q ! ===================================================================== ! Parameters real(sp), parameter :: bs = two ! Local Scalars real(sp) :: aa, bb, cc, dd, ab, cd, s, ov, un, be, eps ! Intrinsic Functions ! Executable Statements aa = a bb = b cc = c dd = d ab = max( abs(a), abs(b) ) cd = max( abs(c), abs(d) ) s = one ov = stdlib${ii}$_slamch( 'OVERFLOW THRESHOLD' ) un = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'EPSILON' ) be = bs / (eps*eps) if( ab >= half*ov ) then aa = half * aa bb = half * bb s = two * s end if if( cd >= half*ov ) then cc = half * cc dd = half * dd s = half * s end if if( ab <= un*bs/eps ) then aa = aa * be bb = bb * be s = s / be end if if( cd <= un*bs/eps ) then cc = cc * be dd = dd * be s = s * be end if if( abs( d )<=abs( c ) ) then call stdlib${ii}$_sladiv1(aa, bb, cc, dd, p, q) else call stdlib${ii}$_sladiv1(bb, aa, dd, cc, p, q) q = -q end if p = p * s q = q * s return end subroutine stdlib${ii}$_sladiv pure module subroutine stdlib${ii}$_dladiv( a, b, c, d, p, q ) !! DLADIV performs complex division in real arithmetic !! a + i*b !! p + i*q = --------- !! c + i*d !! The algorithm is due to Michael Baudin and Robert L. Smith !! and can be found in the paper !! "A Robust Complex Division in Scilab" ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: a, b, c, d real(dp), intent(out) :: p, q ! ===================================================================== ! Parameters real(dp), parameter :: bs = two ! Local Scalars real(dp) :: aa, bb, cc, dd, ab, cd, s, ov, un, be, eps ! Intrinsic Functions ! Executable Statements aa = a bb = b cc = c dd = d ab = max( abs(a), abs(b) ) cd = max( abs(c), abs(d) ) s = one ov = stdlib${ii}$_dlamch( 'OVERFLOW THRESHOLD' ) un = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'EPSILON' ) be = bs / (eps*eps) if( ab >= half*ov ) then aa = half * aa bb = half * bb s = two * s end if if( cd >= half*ov ) then cc = half * cc dd = half * dd s = half * s end if if( ab <= un*bs/eps ) then aa = aa * be bb = bb * be s = s / be end if if( cd <= un*bs/eps ) then cc = cc * be dd = dd * be s = s * be end if if( abs( d )<=abs( c ) ) then call stdlib${ii}$_dladiv1(aa, bb, cc, dd, p, q) else call stdlib${ii}$_dladiv1(bb, aa, dd, cc, p, q) q = -q end if p = p * s q = q * s return end subroutine stdlib${ii}$_dladiv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ladiv( a, b, c, d, p, q ) !! DLADIV: performs complex division in real arithmetic !! a + i*b !! p + i*q = --------- !! c + i*d !! The algorithm is due to Michael Baudin and Robert L. Smith !! and can be found in the paper !! "A Robust Complex Division in Scilab" ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: a, b, c, d real(${rk}$), intent(out) :: p, q ! ===================================================================== ! Parameters real(${rk}$), parameter :: bs = two ! Local Scalars real(${rk}$) :: aa, bb, cc, dd, ab, cd, s, ov, un, be, eps ! Intrinsic Functions ! Executable Statements aa = a bb = b cc = c dd = d ab = max( abs(a), abs(b) ) cd = max( abs(c), abs(d) ) s = one ov = stdlib${ii}$_${ri}$lamch( 'OVERFLOW THRESHOLD' ) un = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'EPSILON' ) be = bs / (eps*eps) if( ab >= half*ov ) then aa = half * aa bb = half * bb s = two * s end if if( cd >= half*ov ) then cc = half * cc dd = half * dd s = half * s end if if( ab <= un*bs/eps ) then aa = aa * be bb = bb * be s = s / be end if if( cd <= un*bs/eps ) then cc = cc * be dd = dd * be s = s * be end if if( abs( d )<=abs( c ) ) then call stdlib${ii}$_${ri}$ladiv1(aa, bb, cc, dd, p, q) else call stdlib${ii}$_${ri}$ladiv1(bb, aa, dd, cc, p, q) q = -q end if p = p * s q = q * s return end subroutine stdlib${ii}$_${ri}$ladiv #:endif #:endfor pure complex(sp) module function stdlib${ii}$_cladiv( x, y ) !! CLADIV := X / Y, where X and Y are complex. The computation of X / Y !! will not overflow on an intermediary step unless the results !! overflows. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments complex(sp), intent(in) :: x, y ! ===================================================================== ! Local Scalars real(sp) :: zi, zr ! Intrinsic Functions ! Executable Statements call stdlib${ii}$_sladiv( real( x,KIND=sp), aimag( x ), real( y,KIND=sp), aimag( y ), zr,zi ) stdlib${ii}$_cladiv = cmplx( zr, zi,KIND=sp) return end function stdlib${ii}$_cladiv pure complex(dp) module function stdlib${ii}$_zladiv( x, y ) !! ZLADIV := X / Y, where X and Y are complex. The computation of X / Y !! will not overflow on an intermediary step unless the results !! overflows. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments complex(dp), intent(in) :: x, y ! ===================================================================== ! Local Scalars real(dp) :: zi, zr ! Intrinsic Functions ! Executable Statements call stdlib${ii}$_dladiv( real( x,KIND=dp), aimag( x ), real( y,KIND=dp), aimag( y ), zr,zi ) stdlib${ii}$_zladiv = cmplx( zr, zi,KIND=dp) return end function stdlib${ii}$_zladiv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure complex(${ck}$) module function stdlib${ii}$_${ci}$ladiv( x, y ) !! ZLADIV: := X / Y, where X and Y are complex. The computation of X / Y !! will not overflow on an intermediary step unless the results !! overflows. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments complex(${ck}$), intent(in) :: x, y ! ===================================================================== ! Local Scalars real(${ck}$) :: zi, zr ! Intrinsic Functions ! Executable Statements call stdlib${ii}$_${c2ri(ci)}$ladiv( real( x,KIND=${ck}$), aimag( x ), real( y,KIND=${ck}$), aimag( y ), zr,zi ) stdlib${ii}$_${ci}$ladiv = cmplx( zr, zi,KIND=${ck}$) return end function stdlib${ii}$_${ci}$ladiv #:endif #:endfor pure real(sp) module function stdlib${ii}$_slapy2( x, y ) !! SLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary !! overflow and unnecessary underflow. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: x, y ! ===================================================================== ! Local Scalars real(sp) :: w, xabs, yabs, z, hugeval logical(lk) :: x_is_nan, y_is_nan ! Intrinsic Functions ! Executable Statements x_is_nan = stdlib${ii}$_sisnan( x ) y_is_nan = stdlib${ii}$_sisnan( y ) if ( x_is_nan ) stdlib${ii}$_slapy2 = x if ( y_is_nan ) stdlib${ii}$_slapy2 = y hugeval = stdlib${ii}$_slamch( 'OVERFLOW' ) if ( .not.( x_is_nan.or.y_is_nan ) ) then xabs = abs( x ) yabs = abs( y ) w = max( xabs, yabs ) z = min( xabs, yabs ) if( z==zero .or. w>hugeval ) then stdlib${ii}$_slapy2 = w else stdlib${ii}$_slapy2 = w*sqrt( one+( z / w )**2_${ik}$ ) end if end if return end function stdlib${ii}$_slapy2 pure real(dp) module function stdlib${ii}$_dlapy2( x, y ) !! DLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary !! overflow and unnecessary underflow. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: x, y ! ===================================================================== ! Local Scalars real(dp) :: w, xabs, yabs, z, hugeval logical(lk) :: x_is_nan, y_is_nan ! Intrinsic Functions ! Executable Statements x_is_nan = stdlib${ii}$_disnan( x ) y_is_nan = stdlib${ii}$_disnan( y ) if ( x_is_nan ) stdlib${ii}$_dlapy2 = x if ( y_is_nan ) stdlib${ii}$_dlapy2 = y hugeval = stdlib${ii}$_dlamch( 'OVERFLOW' ) if ( .not.( x_is_nan.or.y_is_nan ) ) then xabs = abs( x ) yabs = abs( y ) w = max( xabs, yabs ) z = min( xabs, yabs ) if( z==zero .or. w>hugeval ) then stdlib${ii}$_dlapy2 = w else stdlib${ii}$_dlapy2 = w*sqrt( one+( z / w )**2_${ik}$ ) end if end if return end function stdlib${ii}$_dlapy2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$lapy2( x, y ) !! DLAPY2: returns sqrt(x**2+y**2), taking care not to cause unnecessary !! overflow and unnecessary underflow. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: x, y ! ===================================================================== ! Local Scalars real(${rk}$) :: w, xabs, yabs, z, hugeval logical(lk) :: x_is_nan, y_is_nan ! Intrinsic Functions ! Executable Statements x_is_nan = stdlib${ii}$_${ri}$isnan( x ) y_is_nan = stdlib${ii}$_${ri}$isnan( y ) if ( x_is_nan ) stdlib${ii}$_${ri}$lapy2 = x if ( y_is_nan ) stdlib${ii}$_${ri}$lapy2 = y hugeval = stdlib${ii}$_${ri}$lamch( 'OVERFLOW' ) if ( .not.( x_is_nan.or.y_is_nan ) ) then xabs = abs( x ) yabs = abs( y ) w = max( xabs, yabs ) z = min( xabs, yabs ) if( z==zero .or. w>hugeval ) then stdlib${ii}$_${ri}$lapy2 = w else stdlib${ii}$_${ri}$lapy2 = w*sqrt( one+( z / w )**2_${ik}$ ) end if end if return end function stdlib${ii}$_${ri}$lapy2 #:endif #:endfor pure real(sp) module function stdlib${ii}$_slapy3( x, y, z ) !! SLAPY3 returns sqrt(x**2+y**2+z**2), taking care not to cause !! unnecessary overflow and unnecessary underflow. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: x, y, z ! ===================================================================== ! Local Scalars real(sp) :: w, xabs, yabs, zabs, hugeval ! Intrinsic Functions ! Executable Statements hugeval = stdlib${ii}$_slamch( 'OVERFLOW' ) xabs = abs( x ) yabs = abs( y ) zabs = abs( z ) w = max( xabs, yabs, zabs ) if( w==zero .or. w>hugeval ) then ! w can be zero for max(0,nan,0) ! adding all three entries together will make sure ! nan will not disappear. stdlib${ii}$_slapy3 = xabs + yabs + zabs else stdlib${ii}$_slapy3 = w*sqrt( ( xabs / w )**2_${ik}$+( yabs / w )**2_${ik}$+( zabs / w )**2_${ik}$ ) end if return end function stdlib${ii}$_slapy3 pure real(dp) module function stdlib${ii}$_dlapy3( x, y, z ) !! DLAPY3 returns sqrt(x**2+y**2+z**2), taking care not to cause !! unnecessary overflow and unnecessary underflow. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: x, y, z ! ===================================================================== ! Local Scalars real(dp) :: w, xabs, yabs, zabs, hugeval ! Intrinsic Functions ! Executable Statements hugeval = stdlib${ii}$_dlamch( 'OVERFLOW' ) xabs = abs( x ) yabs = abs( y ) zabs = abs( z ) w = max( xabs, yabs, zabs ) if( w==zero .or. w>hugeval ) then ! w can be zero for max(0,nan,0) ! adding all three entries together will make sure ! nan will not disappear. stdlib${ii}$_dlapy3 = xabs + yabs + zabs else stdlib${ii}$_dlapy3 = w*sqrt( ( xabs / w )**2_${ik}$+( yabs / w )**2_${ik}$+( zabs / w )**2_${ik}$ ) end if return end function stdlib${ii}$_dlapy3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure real(${rk}$) module function stdlib${ii}$_${ri}$lapy3( x, y, z ) !! DLAPY3: returns sqrt(x**2+y**2+z**2), taking care not to cause !! unnecessary overflow and unnecessary underflow. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: x, y, z ! ===================================================================== ! Local Scalars real(${rk}$) :: w, xabs, yabs, zabs, hugeval ! Intrinsic Functions ! Executable Statements hugeval = stdlib${ii}$_${ri}$lamch( 'OVERFLOW' ) xabs = abs( x ) yabs = abs( y ) zabs = abs( z ) w = max( xabs, yabs, zabs ) if( w==zero .or. w>hugeval ) then ! w can be zero for max(0,nan,0) ! adding all three entries together will make sure ! nan will not disappear. stdlib${ii}$_${ri}$lapy3 = xabs + yabs + zabs else stdlib${ii}$_${ri}$lapy3 = w*sqrt( ( xabs / w )**2_${ik}$+( yabs / w )**2_${ik}$+( zabs / w )**2_${ik}$ ) end if return end function stdlib${ii}$_${ri}$lapy3 #:endif #:endfor #:endfor end submodule stdlib_lapack_blas_like_scalar fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_eigv_tridiag.fypp0000664000175000017500000142312215135654166026426 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_eigv_tridiag implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slaebz( ijob, nitmax, n, mmax, minp, nbmin, abstol,reltol, pivmin, d, & !! SLAEBZ contains the iteration loops which compute and use the !! function N(w), which is the count of eigenvalues of a symmetric !! tridiagonal matrix T less than or equal to its argument w. It !! performs a choice of two types of loops: !! IJOB=1, followed by !! IJOB=2: It takes as input a list of intervals and returns a list of !! sufficiently small intervals whose union contains the same !! eigenvalues as the union of the original intervals. !! The input intervals are (AB(j,1),AB(j,2)], j=1,...,MINP. !! The output interval (AB(j,1),AB(j,2)] will contain !! eigenvalues NAB(j,1)+1,...,NAB(j,2), where 1 <= j <= MOUT. !! IJOB=3: It performs a binary search in each input interval !! (AB(j,1),AB(j,2)] for a point w(j) such that !! N(w(j))=NVAL(j), and uses C(j) as the starting point of !! the search. If such a w(j) is found, then on output !! AB(j,1)=AB(j,2)=w. If no such w(j) is found, then on output !! (AB(j,1),AB(j,2)] will be a small interval containing the !! point where N(w) jumps through NVAL(j), unless that point !! lies outside the initial interval. !! Note that the intervals are in all cases half-open intervals, !! i.e., of the form (a,b] , which includes b but not a . !! To avoid underflow, the matrix should be scaled so that its largest !! element is no greater than overflow**(1/2) * underflow**(1/4) !! in absolute value. To assure the most accurate computation !! of small eigenvalues, the matrix should be scaled to be !! not much smaller than that, either. !! See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal !! Matrix", Report CS41, Computer Science Dept., Stanford !! University, July 21, 1966 !! Note: the arguments are, in general, *not* checked for unreasonable !! values. e, e2, nval, ab, c, mout,nab, work, iwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ijob, minp, mmax, n, nbmin, nitmax integer(${ik}$), intent(out) :: info, mout real(sp), intent(in) :: abstol, pivmin, reltol ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) integer(${ik}$), intent(inout) :: nab(mmax,*), nval(*) real(sp), intent(inout) :: ab(mmax,*), c(*) real(sp), intent(in) :: d(*), e(*), e2(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: itmp1, itmp2, j, ji, jit, jp, kf, kfnew, kl, klnew real(sp) :: tmp1, tmp2 ! Intrinsic Functions ! Executable Statements ! check for errors info = 0_${ik}$ if( ijob<1_${ik}$ .or. ijob>3_${ik}$ ) then info = -1_${ik}$ return end if ! initialize nab if( ijob==1_${ik}$ ) then ! compute the number of eigenvalues in the initial intervals. mout = 0_${ik}$ do ji = 1, minp do jp = 1, 2 tmp1 = d( 1_${ik}$ ) - ab( ji, jp ) if( abs( tmp1 )=nbmin .and. nbmin>0_${ik}$ ) then ! begin of parallel version of the loop do ji = kf, kl ! compute n(c), the number of eigenvalues less than c work( ji ) = d( 1_${ik}$ ) - c( ji ) iwork( ji ) = 0_${ik}$ if( work( ji )<=pivmin ) then iwork( ji ) = 1_${ik}$ work( ji ) = min( work( ji ), -pivmin ) end if do j = 2, n work( ji ) = d( j ) - e2( j-1 ) / work( ji ) - c( ji ) if( work( ji )<=pivmin ) then iwork( ji ) = iwork( ji ) + 1_${ik}$ work( ji ) = min( work( ji ), -pivmin ) end if end do end do if( ijob<=2_${ik}$ ) then ! ijob=2: choose all intervals containing eigenvalues. klnew = kl loop_70: do ji = kf, kl ! insure that n(w) is monotone iwork( ji ) = min( nab( ji, 2_${ik}$ ),max( nab( ji, 1_${ik}$ ), iwork( ji ) ) ) ! update the queue -- add intervals if both halves ! contain eigenvalues. if( iwork( ji )==nab( ji, 2_${ik}$ ) ) then ! no eigenvalue in the upper interval: ! just use the lower interval. ab( ji, 2_${ik}$ ) = c( ji ) else if( iwork( ji )==nab( ji, 1_${ik}$ ) ) then ! no eigenvalue in the lower interval: ! just use the upper interval. ab( ji, 1_${ik}$ ) = c( ji ) else klnew = klnew + 1_${ik}$ if( klnew<=mmax ) then ! eigenvalue in both intervals -- add upper to ! queue. ab( klnew, 2_${ik}$ ) = ab( ji, 2_${ik}$ ) nab( klnew, 2_${ik}$ ) = nab( ji, 2_${ik}$ ) ab( klnew, 1_${ik}$ ) = c( ji ) nab( klnew, 1_${ik}$ ) = iwork( ji ) ab( ji, 2_${ik}$ ) = c( ji ) nab( ji, 2_${ik}$ ) = iwork( ji ) else info = mmax + 1_${ik}$ end if end if end do loop_70 if( info/=0 )return kl = klnew else ! ijob=3: binary search. keep only the interval containing ! w s.t. n(w) = nval do ji = kf, kl if( iwork( ji )<=nval( ji ) ) then ab( ji, 1_${ik}$ ) = c( ji ) nab( ji, 1_${ik}$ ) = iwork( ji ) end if if( iwork( ji )>=nval( ji ) ) then ab( ji, 2_${ik}$ ) = c( ji ) nab( ji, 2_${ik}$ ) = iwork( ji ) end if end do end if else ! end of parallel version of the loop ! begin of serial version of the loop klnew = kl loop_100: do ji = kf, kl ! compute n(w), the number of eigenvalues less than w tmp1 = c( ji ) tmp2 = d( 1_${ik}$ ) - tmp1 itmp1 = 0_${ik}$ if( tmp2<=pivmin ) then itmp1 = 1_${ik}$ tmp2 = min( tmp2, -pivmin ) end if do j = 2, n tmp2 = d( j ) - e2( j-1 ) / tmp2 - tmp1 if( tmp2<=pivmin ) then itmp1 = itmp1 + 1_${ik}$ tmp2 = min( tmp2, -pivmin ) end if end do if( ijob<=2_${ik}$ ) then ! ijob=2: choose all intervals containing eigenvalues. ! insure that n(w) is monotone itmp1 = min( nab( ji, 2_${ik}$ ),max( nab( ji, 1_${ik}$ ), itmp1 ) ) ! update the queue -- add intervals if both halves ! contain eigenvalues. if( itmp1==nab( ji, 2_${ik}$ ) ) then ! no eigenvalue in the upper interval: ! just use the lower interval. ab( ji, 2_${ik}$ ) = tmp1 else if( itmp1==nab( ji, 1_${ik}$ ) ) then ! no eigenvalue in the lower interval: ! just use the upper interval. ab( ji, 1_${ik}$ ) = tmp1 else if( klnew=nval( ji ) ) then ab( ji, 2_${ik}$ ) = tmp1 nab( ji, 2_${ik}$ ) = itmp1 end if end if end do loop_100 kl = klnew end if ! check for convergence kfnew = kf loop_110: do ji = kf, kl tmp1 = abs( ab( ji, 2_${ik}$ )-ab( ji, 1_${ik}$ ) ) tmp2 = max( abs( ab( ji, 2_${ik}$ ) ), abs( ab( ji, 1_${ik}$ ) ) ) if( tmp1=nab( ji, 2_${ik}$ ) ) & then ! converged -- swap with position kfnew, ! then increment kfnew if( ji>kfnew ) then tmp1 = ab( ji, 1_${ik}$ ) tmp2 = ab( ji, 2_${ik}$ ) itmp1 = nab( ji, 1_${ik}$ ) itmp2 = nab( ji, 2_${ik}$ ) ab( ji, 1_${ik}$ ) = ab( kfnew, 1_${ik}$ ) ab( ji, 2_${ik}$ ) = ab( kfnew, 2_${ik}$ ) nab( ji, 1_${ik}$ ) = nab( kfnew, 1_${ik}$ ) nab( ji, 2_${ik}$ ) = nab( kfnew, 2_${ik}$ ) ab( kfnew, 1_${ik}$ ) = tmp1 ab( kfnew, 2_${ik}$ ) = tmp2 nab( kfnew, 1_${ik}$ ) = itmp1 nab( kfnew, 2_${ik}$ ) = itmp2 if( ijob==3_${ik}$ ) then itmp1 = nval( ji ) nval( ji ) = nval( kfnew ) nval( kfnew ) = itmp1 end if end if kfnew = kfnew + 1_${ik}$ end if end do loop_110 kf = kfnew ! choose midpoints do ji = kf, kl c( ji ) = half*( ab( ji, 1_${ik}$ )+ab( ji, 2_${ik}$ ) ) end do ! if no more intervals to refine, quit. if( kf>kl )go to 140 end do loop_130 ! converged 140 continue info = max( kl+1-kf, 0_${ik}$ ) mout = kl return end subroutine stdlib${ii}$_slaebz pure module subroutine stdlib${ii}$_dlaebz( ijob, nitmax, n, mmax, minp, nbmin, abstol,reltol, pivmin, d, & !! DLAEBZ contains the iteration loops which compute and use the !! function N(w), which is the count of eigenvalues of a symmetric !! tridiagonal matrix T less than or equal to its argument w. It !! performs a choice of two types of loops: !! IJOB=1, followed by !! IJOB=2: It takes as input a list of intervals and returns a list of !! sufficiently small intervals whose union contains the same !! eigenvalues as the union of the original intervals. !! The input intervals are (AB(j,1),AB(j,2)], j=1,...,MINP. !! The output interval (AB(j,1),AB(j,2)] will contain !! eigenvalues NAB(j,1)+1,...,NAB(j,2), where 1 <= j <= MOUT. !! IJOB=3: It performs a binary search in each input interval !! (AB(j,1),AB(j,2)] for a point w(j) such that !! N(w(j))=NVAL(j), and uses C(j) as the starting point of !! the search. If such a w(j) is found, then on output !! AB(j,1)=AB(j,2)=w. If no such w(j) is found, then on output !! (AB(j,1),AB(j,2)] will be a small interval containing the !! point where N(w) jumps through NVAL(j), unless that point !! lies outside the initial interval. !! Note that the intervals are in all cases half-open intervals, !! i.e., of the form (a,b] , which includes b but not a . !! To avoid underflow, the matrix should be scaled so that its largest !! element is no greater than overflow**(1/2) * underflow**(1/4) !! in absolute value. To assure the most accurate computation !! of small eigenvalues, the matrix should be scaled to be !! not much smaller than that, either. !! See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal !! Matrix", Report CS41, Computer Science Dept., Stanford !! University, July 21, 1966 !! Note: the arguments are, in general, *not* checked for unreasonable !! values. e, e2, nval, ab, c, mout,nab, work, iwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ijob, minp, mmax, n, nbmin, nitmax integer(${ik}$), intent(out) :: info, mout real(dp), intent(in) :: abstol, pivmin, reltol ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) integer(${ik}$), intent(inout) :: nab(mmax,*), nval(*) real(dp), intent(inout) :: ab(mmax,*), c(*) real(dp), intent(in) :: d(*), e(*), e2(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: itmp1, itmp2, j, ji, jit, jp, kf, kfnew, kl, klnew real(dp) :: tmp1, tmp2 ! Intrinsic Functions ! Executable Statements ! check for errors info = 0_${ik}$ if( ijob<1_${ik}$ .or. ijob>3_${ik}$ ) then info = -1_${ik}$ return end if ! initialize nab if( ijob==1_${ik}$ ) then ! compute the number of eigenvalues in the initial intervals. mout = 0_${ik}$ do ji = 1, minp do jp = 1, 2 tmp1 = d( 1_${ik}$ ) - ab( ji, jp ) if( abs( tmp1 )=nbmin .and. nbmin>0_${ik}$ ) then ! begin of parallel version of the loop do ji = kf, kl ! compute n(c), the number of eigenvalues less than c work( ji ) = d( 1_${ik}$ ) - c( ji ) iwork( ji ) = 0_${ik}$ if( work( ji )<=pivmin ) then iwork( ji ) = 1_${ik}$ work( ji ) = min( work( ji ), -pivmin ) end if do j = 2, n work( ji ) = d( j ) - e2( j-1 ) / work( ji ) - c( ji ) if( work( ji )<=pivmin ) then iwork( ji ) = iwork( ji ) + 1_${ik}$ work( ji ) = min( work( ji ), -pivmin ) end if end do end do if( ijob<=2_${ik}$ ) then ! ijob=2: choose all intervals containing eigenvalues. klnew = kl loop_70: do ji = kf, kl ! insure that n(w) is monotone iwork( ji ) = min( nab( ji, 2_${ik}$ ),max( nab( ji, 1_${ik}$ ), iwork( ji ) ) ) ! update the queue -- add intervals if both halves ! contain eigenvalues. if( iwork( ji )==nab( ji, 2_${ik}$ ) ) then ! no eigenvalue in the upper interval: ! just use the lower interval. ab( ji, 2_${ik}$ ) = c( ji ) else if( iwork( ji )==nab( ji, 1_${ik}$ ) ) then ! no eigenvalue in the lower interval: ! just use the upper interval. ab( ji, 1_${ik}$ ) = c( ji ) else klnew = klnew + 1_${ik}$ if( klnew<=mmax ) then ! eigenvalue in both intervals -- add upper to ! queue. ab( klnew, 2_${ik}$ ) = ab( ji, 2_${ik}$ ) nab( klnew, 2_${ik}$ ) = nab( ji, 2_${ik}$ ) ab( klnew, 1_${ik}$ ) = c( ji ) nab( klnew, 1_${ik}$ ) = iwork( ji ) ab( ji, 2_${ik}$ ) = c( ji ) nab( ji, 2_${ik}$ ) = iwork( ji ) else info = mmax + 1_${ik}$ end if end if end do loop_70 if( info/=0 )return kl = klnew else ! ijob=3: binary search. keep only the interval containing ! w s.t. n(w) = nval do ji = kf, kl if( iwork( ji )<=nval( ji ) ) then ab( ji, 1_${ik}$ ) = c( ji ) nab( ji, 1_${ik}$ ) = iwork( ji ) end if if( iwork( ji )>=nval( ji ) ) then ab( ji, 2_${ik}$ ) = c( ji ) nab( ji, 2_${ik}$ ) = iwork( ji ) end if end do end if else ! end of parallel version of the loop ! begin of serial version of the loop klnew = kl loop_100: do ji = kf, kl ! compute n(w), the number of eigenvalues less than w tmp1 = c( ji ) tmp2 = d( 1_${ik}$ ) - tmp1 itmp1 = 0_${ik}$ if( tmp2<=pivmin ) then itmp1 = 1_${ik}$ tmp2 = min( tmp2, -pivmin ) end if do j = 2, n tmp2 = d( j ) - e2( j-1 ) / tmp2 - tmp1 if( tmp2<=pivmin ) then itmp1 = itmp1 + 1_${ik}$ tmp2 = min( tmp2, -pivmin ) end if end do if( ijob<=2_${ik}$ ) then ! ijob=2: choose all intervals containing eigenvalues. ! insure that n(w) is monotone itmp1 = min( nab( ji, 2_${ik}$ ),max( nab( ji, 1_${ik}$ ), itmp1 ) ) ! update the queue -- add intervals if both halves ! contain eigenvalues. if( itmp1==nab( ji, 2_${ik}$ ) ) then ! no eigenvalue in the upper interval: ! just use the lower interval. ab( ji, 2_${ik}$ ) = tmp1 else if( itmp1==nab( ji, 1_${ik}$ ) ) then ! no eigenvalue in the lower interval: ! just use the upper interval. ab( ji, 1_${ik}$ ) = tmp1 else if( klnew=nval( ji ) ) then ab( ji, 2_${ik}$ ) = tmp1 nab( ji, 2_${ik}$ ) = itmp1 end if end if end do loop_100 kl = klnew end if ! check for convergence kfnew = kf loop_110: do ji = kf, kl tmp1 = abs( ab( ji, 2_${ik}$ )-ab( ji, 1_${ik}$ ) ) tmp2 = max( abs( ab( ji, 2_${ik}$ ) ), abs( ab( ji, 1_${ik}$ ) ) ) if( tmp1=nab( ji, 2_${ik}$ ) ) & then ! converged -- swap with position kfnew, ! then increment kfnew if( ji>kfnew ) then tmp1 = ab( ji, 1_${ik}$ ) tmp2 = ab( ji, 2_${ik}$ ) itmp1 = nab( ji, 1_${ik}$ ) itmp2 = nab( ji, 2_${ik}$ ) ab( ji, 1_${ik}$ ) = ab( kfnew, 1_${ik}$ ) ab( ji, 2_${ik}$ ) = ab( kfnew, 2_${ik}$ ) nab( ji, 1_${ik}$ ) = nab( kfnew, 1_${ik}$ ) nab( ji, 2_${ik}$ ) = nab( kfnew, 2_${ik}$ ) ab( kfnew, 1_${ik}$ ) = tmp1 ab( kfnew, 2_${ik}$ ) = tmp2 nab( kfnew, 1_${ik}$ ) = itmp1 nab( kfnew, 2_${ik}$ ) = itmp2 if( ijob==3_${ik}$ ) then itmp1 = nval( ji ) nval( ji ) = nval( kfnew ) nval( kfnew ) = itmp1 end if end if kfnew = kfnew + 1_${ik}$ end if end do loop_110 kf = kfnew ! choose midpoints do ji = kf, kl c( ji ) = half*( ab( ji, 1_${ik}$ )+ab( ji, 2_${ik}$ ) ) end do ! if no more intervals to refine, quit. if( kf>kl )go to 140 end do loop_130 ! converged 140 continue info = max( kl+1-kf, 0_${ik}$ ) mout = kl return end subroutine stdlib${ii}$_dlaebz #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laebz( ijob, nitmax, n, mmax, minp, nbmin, abstol,reltol, pivmin, d, & !! DLAEBZ: contains the iteration loops which compute and use the !! function N(w), which is the count of eigenvalues of a symmetric !! tridiagonal matrix T less than or equal to its argument w. It !! performs a choice of two types of loops: !! IJOB=1, followed by !! IJOB=2: It takes as input a list of intervals and returns a list of !! sufficiently small intervals whose union contains the same !! eigenvalues as the union of the original intervals. !! The input intervals are (AB(j,1),AB(j,2)], j=1,...,MINP. !! The output interval (AB(j,1),AB(j,2)] will contain !! eigenvalues NAB(j,1)+1,...,NAB(j,2), where 1 <= j <= MOUT. !! IJOB=3: It performs a binary search in each input interval !! (AB(j,1),AB(j,2)] for a point w(j) such that !! N(w(j))=NVAL(j), and uses C(j) as the starting point of !! the search. If such a w(j) is found, then on output !! AB(j,1)=AB(j,2)=w. If no such w(j) is found, then on output !! (AB(j,1),AB(j,2)] will be a small interval containing the !! point where N(w) jumps through NVAL(j), unless that point !! lies outside the initial interval. !! Note that the intervals are in all cases half-open intervals, !! i.e., of the form (a,b] , which includes b but not a . !! To avoid underflow, the matrix should be scaled so that its largest !! element is no greater than overflow**(1/2) * underflow**(1/4) !! in absolute value. To assure the most accurate computation !! of small eigenvalues, the matrix should be scaled to be !! not much smaller than that, either. !! See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal !! Matrix", Report CS41, Computer Science Dept., Stanford !! University, July 21, 1966 !! Note: the arguments are, in general, *not* checked for unreasonable !! values. e, e2, nval, ab, c, mout,nab, work, iwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ijob, minp, mmax, n, nbmin, nitmax integer(${ik}$), intent(out) :: info, mout real(${rk}$), intent(in) :: abstol, pivmin, reltol ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) integer(${ik}$), intent(inout) :: nab(mmax,*), nval(*) real(${rk}$), intent(inout) :: ab(mmax,*), c(*) real(${rk}$), intent(in) :: d(*), e(*), e2(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: itmp1, itmp2, j, ji, jit, jp, kf, kfnew, kl, klnew real(${rk}$) :: tmp1, tmp2 ! Intrinsic Functions ! Executable Statements ! check for errors info = 0_${ik}$ if( ijob<1_${ik}$ .or. ijob>3_${ik}$ ) then info = -1_${ik}$ return end if ! initialize nab if( ijob==1_${ik}$ ) then ! compute the number of eigenvalues in the initial intervals. mout = 0_${ik}$ do ji = 1, minp do jp = 1, 2 tmp1 = d( 1_${ik}$ ) - ab( ji, jp ) if( abs( tmp1 )=nbmin .and. nbmin>0_${ik}$ ) then ! begin of parallel version of the loop do ji = kf, kl ! compute n(c), the number of eigenvalues less than c work( ji ) = d( 1_${ik}$ ) - c( ji ) iwork( ji ) = 0_${ik}$ if( work( ji )<=pivmin ) then iwork( ji ) = 1_${ik}$ work( ji ) = min( work( ji ), -pivmin ) end if do j = 2, n work( ji ) = d( j ) - e2( j-1 ) / work( ji ) - c( ji ) if( work( ji )<=pivmin ) then iwork( ji ) = iwork( ji ) + 1_${ik}$ work( ji ) = min( work( ji ), -pivmin ) end if end do end do if( ijob<=2_${ik}$ ) then ! ijob=2: choose all intervals containing eigenvalues. klnew = kl loop_70: do ji = kf, kl ! insure that n(w) is monotone iwork( ji ) = min( nab( ji, 2_${ik}$ ),max( nab( ji, 1_${ik}$ ), iwork( ji ) ) ) ! update the queue -- add intervals if both halves ! contain eigenvalues. if( iwork( ji )==nab( ji, 2_${ik}$ ) ) then ! no eigenvalue in the upper interval: ! just use the lower interval. ab( ji, 2_${ik}$ ) = c( ji ) else if( iwork( ji )==nab( ji, 1_${ik}$ ) ) then ! no eigenvalue in the lower interval: ! just use the upper interval. ab( ji, 1_${ik}$ ) = c( ji ) else klnew = klnew + 1_${ik}$ if( klnew<=mmax ) then ! eigenvalue in both intervals -- add upper to ! queue. ab( klnew, 2_${ik}$ ) = ab( ji, 2_${ik}$ ) nab( klnew, 2_${ik}$ ) = nab( ji, 2_${ik}$ ) ab( klnew, 1_${ik}$ ) = c( ji ) nab( klnew, 1_${ik}$ ) = iwork( ji ) ab( ji, 2_${ik}$ ) = c( ji ) nab( ji, 2_${ik}$ ) = iwork( ji ) else info = mmax + 1_${ik}$ end if end if end do loop_70 if( info/=0 )return kl = klnew else ! ijob=3: binary search. keep only the interval containing ! w s.t. n(w) = nval do ji = kf, kl if( iwork( ji )<=nval( ji ) ) then ab( ji, 1_${ik}$ ) = c( ji ) nab( ji, 1_${ik}$ ) = iwork( ji ) end if if( iwork( ji )>=nval( ji ) ) then ab( ji, 2_${ik}$ ) = c( ji ) nab( ji, 2_${ik}$ ) = iwork( ji ) end if end do end if else ! end of parallel version of the loop ! begin of serial version of the loop klnew = kl loop_100: do ji = kf, kl ! compute n(w), the number of eigenvalues less than w tmp1 = c( ji ) tmp2 = d( 1_${ik}$ ) - tmp1 itmp1 = 0_${ik}$ if( tmp2<=pivmin ) then itmp1 = 1_${ik}$ tmp2 = min( tmp2, -pivmin ) end if do j = 2, n tmp2 = d( j ) - e2( j-1 ) / tmp2 - tmp1 if( tmp2<=pivmin ) then itmp1 = itmp1 + 1_${ik}$ tmp2 = min( tmp2, -pivmin ) end if end do if( ijob<=2_${ik}$ ) then ! ijob=2: choose all intervals containing eigenvalues. ! insure that n(w) is monotone itmp1 = min( nab( ji, 2_${ik}$ ),max( nab( ji, 1_${ik}$ ), itmp1 ) ) ! update the queue -- add intervals if both halves ! contain eigenvalues. if( itmp1==nab( ji, 2_${ik}$ ) ) then ! no eigenvalue in the upper interval: ! just use the lower interval. ab( ji, 2_${ik}$ ) = tmp1 else if( itmp1==nab( ji, 1_${ik}$ ) ) then ! no eigenvalue in the lower interval: ! just use the upper interval. ab( ji, 1_${ik}$ ) = tmp1 else if( klnew=nval( ji ) ) then ab( ji, 2_${ik}$ ) = tmp1 nab( ji, 2_${ik}$ ) = itmp1 end if end if end do loop_100 kl = klnew end if ! check for convergence kfnew = kf loop_110: do ji = kf, kl tmp1 = abs( ab( ji, 2_${ik}$ )-ab( ji, 1_${ik}$ ) ) tmp2 = max( abs( ab( ji, 2_${ik}$ ) ), abs( ab( ji, 1_${ik}$ ) ) ) if( tmp1=nab( ji, 2_${ik}$ ) ) & then ! converged -- swap with position kfnew, ! then increment kfnew if( ji>kfnew ) then tmp1 = ab( ji, 1_${ik}$ ) tmp2 = ab( ji, 2_${ik}$ ) itmp1 = nab( ji, 1_${ik}$ ) itmp2 = nab( ji, 2_${ik}$ ) ab( ji, 1_${ik}$ ) = ab( kfnew, 1_${ik}$ ) ab( ji, 2_${ik}$ ) = ab( kfnew, 2_${ik}$ ) nab( ji, 1_${ik}$ ) = nab( kfnew, 1_${ik}$ ) nab( ji, 2_${ik}$ ) = nab( kfnew, 2_${ik}$ ) ab( kfnew, 1_${ik}$ ) = tmp1 ab( kfnew, 2_${ik}$ ) = tmp2 nab( kfnew, 1_${ik}$ ) = itmp1 nab( kfnew, 2_${ik}$ ) = itmp2 if( ijob==3_${ik}$ ) then itmp1 = nval( ji ) nval( ji ) = nval( kfnew ) nval( kfnew ) = itmp1 end if end if kfnew = kfnew + 1_${ik}$ end if end do loop_110 kf = kfnew ! choose midpoints do ji = kf, kl c( ji ) = half*( ab( ji, 1_${ik}$ )+ab( ji, 2_${ik}$ ) ) end do ! if no more intervals to refine, quit. if( kf>kl )go to 140 end do loop_130 ! converged 140 continue info = max( kl+1-kf, 0_${ik}$ ) mout = kl return end subroutine stdlib${ii}$_${ri}$laebz #:endif #:endfor pure integer(${ik}$) module function stdlib${ii}$_slaneg( n, d, lld, sigma, pivmin, r ) !! SLANEG computes the Sturm count, the number of negative pivots !! encountered while factoring tridiagonal T - sigma I = L D L^T. !! This implementation works directly on the factors without forming !! the tridiagonal matrix T. The Sturm count is also the number of !! eigenvalues of T less than sigma. !! This routine is called from SLARRB. !! The current routine does not use the PIVMIN parameter but rather !! requires IEEE-754 propagation of Infinities and NaNs. This !! routine also has no input range restrictions but does require !! default exception handling such that x/0 produces Inf when x is !! non-zero, and Inf/Inf produces NaN. For more information, see: !! Marques, Riedy, and Voemel, "Benefits of IEEE-754 Features in !! Modern Symmetric Tridiagonal Eigensolvers," SIAM Journal on !! Scientific Computing, v28, n5, 2006. DOI 10.1137/050641624 !! (Tech report version in LAWN 172 with the same title.) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, r real(sp), intent(in) :: pivmin, sigma ! Array Arguments real(sp), intent(in) :: d(*), lld(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: blklen = 128_${ik}$ ! some architectures propagate infinities and nans very slowly, so ! the code computes counts in blklen chunks. then a nan can ! propagate at most blklen columns before being detected. this is ! not a general tuning parameter; it needs only to be just large ! enough that the overhead is tiny in common cases. ! Local Scalars integer(${ik}$) :: bj, j, neg1, neg2, negcnt real(sp) :: bsav, dminus, dplus, gamma, p, t, tmp logical(lk) :: sawnan ! Intrinsic Functions ! Executable Statements negcnt = 0_${ik}$ ! i) upper part: l d l^t - sigma i = l+ d+ l+^t t = -sigma loop_210: do bj = 1, r-1, blklen neg1 = 0_${ik}$ bsav = t do j = bj, min(bj+blklen-1, r-1) dplus = d( j ) + t if( dplus2_${ik}$ ) then info = -1_${ik}$ else if( ( icompq==1_${ik}$ ) .and. ( qsizsmlsiz ) then do j = subpbs, 1, -1 iwork( 2_${ik}$*j ) = ( iwork( j )+1_${ik}$ ) / 2_${ik}$ iwork( 2_${ik}$*j-1 ) = iwork( j ) / 2_${ik}$ end do tlvls = tlvls + 1_${ik}$ subpbs = 2_${ik}$*subpbs go to 10 end if do j = 2, subpbs iwork( j ) = iwork( j ) + iwork( j-1 ) end do ! divide the matrix into subpbs submatrices of size at most smlsiz+1 ! using rank-1 modifications (cuts). spm1 = subpbs - 1_${ik}$ do i = 1, spm1 submat = iwork( i ) + 1_${ik}$ smm1 = submat - 1_${ik}$ d( smm1 ) = d( smm1 ) - abs( e( smm1 ) ) d( submat ) = d( submat ) - abs( e( smm1 ) ) end do indxq = 4_${ik}$*n + 3_${ik}$ if( icompq/=2_${ik}$ ) then ! set up workspaces for eigenvalues only/accumulate new vectors ! routine temp = log( real( n,KIND=sp) ) / log( two ) lgn = int( temp,KIND=${ik}$) if( 2_${ik}$**lgn 1 ) curlvl = 1_${ik}$ 80 continue if( subpbs>1_${ik}$ ) then spm2 = subpbs - 2_${ik}$ loop_90: do i = 0, spm2, 2 if( i==0_${ik}$ ) then submat = 1_${ik}$ matsiz = iwork( 2_${ik}$ ) msd2 = iwork( 1_${ik}$ ) curprb = 0_${ik}$ else submat = iwork( i ) + 1_${ik}$ matsiz = iwork( i+2 ) - iwork( i ) msd2 = matsiz / 2_${ik}$ curprb = curprb + 1_${ik}$ end if ! merge lower order eigensystems (of size msd2 and matsiz - msd2) ! into an eigensystem of size matsiz. ! stdlib${ii}$_slaed1 is used only for the full eigensystem of a tridiagonal ! matrix. ! stdlib${ii}$_slaed7 handles the cases in which eigenvalues only or eigenvalues ! and eigenvectors of a full symmetric matrix (which was reduced to ! tridiagonal form) are desired. if( icompq==2_${ik}$ ) then call stdlib${ii}$_slaed1( matsiz, d( submat ), q( submat, submat ),ldq, iwork( & indxq+submat ),e( submat+msd2-1 ), msd2, work,iwork( subpbs+1 ), info ) else call stdlib${ii}$_slaed7( icompq, matsiz, qsiz, tlvls, curlvl, curprb,d( submat ), & qstore( 1_${ik}$, submat ), ldqs,iwork( indxq+submat ), e( submat+msd2-1 ),msd2, & work( iq ), iwork( iqptr ),iwork( iprmpt ), iwork( iperm ),iwork( igivpt ), & iwork( igivcl ),work( igivnm ), work( iwrem ),iwork( subpbs+1 ), info ) end if if( info/=0 )go to 130 iwork( i / 2_${ik}$+1 ) = iwork( i+2 ) end do loop_90 subpbs = subpbs / 2_${ik}$ curlvl = curlvl + 1_${ik}$ go to 80 end if ! end while ! re-merge the eigenvalues/vectors which were deflated at the final ! merge step. if( icompq==1_${ik}$ ) then do i = 1, n j = iwork( indxq+i ) work( i ) = d( j ) call stdlib${ii}$_scopy( qsiz, qstore( 1_${ik}$, j ), 1_${ik}$, q( 1_${ik}$, i ), 1_${ik}$ ) end do call stdlib${ii}$_scopy( n, work, 1_${ik}$, d, 1_${ik}$ ) else if( icompq==2_${ik}$ ) then do i = 1, n j = iwork( indxq+i ) work( i ) = d( j ) call stdlib${ii}$_scopy( n, q( 1_${ik}$, j ), 1_${ik}$, work( n*i+1 ), 1_${ik}$ ) end do call stdlib${ii}$_scopy( n, work, 1_${ik}$, d, 1_${ik}$ ) call stdlib${ii}$_slacpy( 'A', n, n, work( n+1 ), n, q, ldq ) else do i = 1, n j = iwork( indxq+i ) work( i ) = d( j ) end do call stdlib${ii}$_scopy( n, work, 1_${ik}$, d, 1_${ik}$ ) end if go to 140 130 continue info = submat*( n+1 ) + submat + matsiz - 1_${ik}$ 140 continue return end subroutine stdlib${ii}$_slaed0 pure module subroutine stdlib${ii}$_dlaed0( icompq, qsiz, n, d, e, q, ldq, qstore, ldqs,work, iwork, info & !! DLAED0 computes all eigenvalues and corresponding eigenvectors of a !! symmetric tridiagonal matrix using the divide and conquer method. ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: icompq, ldq, ldqs, n, qsiz integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: d(*), e(*), q(ldq,*) real(dp), intent(out) :: qstore(ldqs,*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: curlvl, curprb, curr, i, igivcl, igivnm, igivpt, indxq, iperm, iprmpt, & iq, iqptr, iwrem, j, k, lgn, matsiz, msd2, smlsiz, smm1, spm1, spm2, submat, subpbs, & tlvls real(dp) :: temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( icompq<0_${ik}$ .or. icompq>2_${ik}$ ) then info = -1_${ik}$ else if( ( icompq==1_${ik}$ ) .and. ( qsizsmlsiz ) then do j = subpbs, 1, -1 iwork( 2_${ik}$*j ) = ( iwork( j )+1_${ik}$ ) / 2_${ik}$ iwork( 2_${ik}$*j-1 ) = iwork( j ) / 2_${ik}$ end do tlvls = tlvls + 1_${ik}$ subpbs = 2_${ik}$*subpbs go to 10 end if do j = 2, subpbs iwork( j ) = iwork( j ) + iwork( j-1 ) end do ! divide the matrix into subpbs submatrices of size at most smlsiz+1 ! using rank-1 modifications (cuts). spm1 = subpbs - 1_${ik}$ do i = 1, spm1 submat = iwork( i ) + 1_${ik}$ smm1 = submat - 1_${ik}$ d( smm1 ) = d( smm1 ) - abs( e( smm1 ) ) d( submat ) = d( submat ) - abs( e( smm1 ) ) end do indxq = 4_${ik}$*n + 3_${ik}$ if( icompq/=2_${ik}$ ) then ! set up workspaces for eigenvalues only/accumulate new vectors ! routine temp = log( real( n,KIND=dp) ) / log( two ) lgn = int( temp,KIND=${ik}$) if( 2_${ik}$**lgn 1 ) curlvl = 1_${ik}$ 80 continue if( subpbs>1_${ik}$ ) then spm2 = subpbs - 2_${ik}$ loop_90: do i = 0, spm2, 2 if( i==0_${ik}$ ) then submat = 1_${ik}$ matsiz = iwork( 2_${ik}$ ) msd2 = iwork( 1_${ik}$ ) curprb = 0_${ik}$ else submat = iwork( i ) + 1_${ik}$ matsiz = iwork( i+2 ) - iwork( i ) msd2 = matsiz / 2_${ik}$ curprb = curprb + 1_${ik}$ end if ! merge lower order eigensystems (of size msd2 and matsiz - msd2) ! into an eigensystem of size matsiz. ! stdlib${ii}$_dlaed1 is used only for the full eigensystem of a tridiagonal ! matrix. ! stdlib${ii}$_dlaed7 handles the cases in which eigenvalues only or eigenvalues ! and eigenvectors of a full symmetric matrix (which was reduced to ! tridiagonal form) are desired. if( icompq==2_${ik}$ ) then call stdlib${ii}$_dlaed1( matsiz, d( submat ), q( submat, submat ),ldq, iwork( & indxq+submat ),e( submat+msd2-1 ), msd2, work,iwork( subpbs+1 ), info ) else call stdlib${ii}$_dlaed7( icompq, matsiz, qsiz, tlvls, curlvl, curprb,d( submat ), & qstore( 1_${ik}$, submat ), ldqs,iwork( indxq+submat ), e( submat+msd2-1 ),msd2, & work( iq ), iwork( iqptr ),iwork( iprmpt ), iwork( iperm ),iwork( igivpt ), & iwork( igivcl ),work( igivnm ), work( iwrem ),iwork( subpbs+1 ), info ) end if if( info/=0 )go to 130 iwork( i / 2_${ik}$+1 ) = iwork( i+2 ) end do loop_90 subpbs = subpbs / 2_${ik}$ curlvl = curlvl + 1_${ik}$ go to 80 end if ! end while ! re-merge the eigenvalues/vectors which were deflated at the final ! merge step. if( icompq==1_${ik}$ ) then do i = 1, n j = iwork( indxq+i ) work( i ) = d( j ) call stdlib${ii}$_dcopy( qsiz, qstore( 1_${ik}$, j ), 1_${ik}$, q( 1_${ik}$, i ), 1_${ik}$ ) end do call stdlib${ii}$_dcopy( n, work, 1_${ik}$, d, 1_${ik}$ ) else if( icompq==2_${ik}$ ) then do i = 1, n j = iwork( indxq+i ) work( i ) = d( j ) call stdlib${ii}$_dcopy( n, q( 1_${ik}$, j ), 1_${ik}$, work( n*i+1 ), 1_${ik}$ ) end do call stdlib${ii}$_dcopy( n, work, 1_${ik}$, d, 1_${ik}$ ) call stdlib${ii}$_dlacpy( 'A', n, n, work( n+1 ), n, q, ldq ) else do i = 1, n j = iwork( indxq+i ) work( i ) = d( j ) end do call stdlib${ii}$_dcopy( n, work, 1_${ik}$, d, 1_${ik}$ ) end if go to 140 130 continue info = submat*( n+1 ) + submat + matsiz - 1_${ik}$ 140 continue return end subroutine stdlib${ii}$_dlaed0 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laed0( icompq, qsiz, n, d, e, q, ldq, qstore, ldqs,work, iwork, info & !! DLAED0: computes all eigenvalues and corresponding eigenvectors of a !! symmetric tridiagonal matrix using the divide and conquer method. ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: icompq, ldq, ldqs, n, qsiz integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: d(*), e(*), q(ldq,*) real(${rk}$), intent(out) :: qstore(ldqs,*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: curlvl, curprb, curr, i, igivcl, igivnm, igivpt, indxq, iperm, iprmpt, & iq, iqptr, iwrem, j, k, lgn, matsiz, msd2, smlsiz, smm1, spm1, spm2, submat, subpbs, & tlvls real(${rk}$) :: temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( icompq<0_${ik}$ .or. icompq>2_${ik}$ ) then info = -1_${ik}$ else if( ( icompq==1_${ik}$ ) .and. ( qsizsmlsiz ) then do j = subpbs, 1, -1 iwork( 2_${ik}$*j ) = ( iwork( j )+1_${ik}$ ) / 2_${ik}$ iwork( 2_${ik}$*j-1 ) = iwork( j ) / 2_${ik}$ end do tlvls = tlvls + 1_${ik}$ subpbs = 2_${ik}$*subpbs go to 10 end if do j = 2, subpbs iwork( j ) = iwork( j ) + iwork( j-1 ) end do ! divide the matrix into subpbs submatrices of size at most smlsiz+1 ! using rank-1 modifications (cuts). spm1 = subpbs - 1_${ik}$ do i = 1, spm1 submat = iwork( i ) + 1_${ik}$ smm1 = submat - 1_${ik}$ d( smm1 ) = d( smm1 ) - abs( e( smm1 ) ) d( submat ) = d( submat ) - abs( e( smm1 ) ) end do indxq = 4_${ik}$*n + 3_${ik}$ if( icompq/=2_${ik}$ ) then ! set up workspaces for eigenvalues only/accumulate new vectors ! routine temp = log( real( n,KIND=${rk}$) ) / log( two ) lgn = int( temp,KIND=${ik}$) if( 2_${ik}$**lgn 1 ) curlvl = 1_${ik}$ 80 continue if( subpbs>1_${ik}$ ) then spm2 = subpbs - 2_${ik}$ loop_90: do i = 0, spm2, 2 if( i==0_${ik}$ ) then submat = 1_${ik}$ matsiz = iwork( 2_${ik}$ ) msd2 = iwork( 1_${ik}$ ) curprb = 0_${ik}$ else submat = iwork( i ) + 1_${ik}$ matsiz = iwork( i+2 ) - iwork( i ) msd2 = matsiz / 2_${ik}$ curprb = curprb + 1_${ik}$ end if ! merge lower order eigensystems (of size msd2 and matsiz - msd2) ! into an eigensystem of size matsiz. ! stdlib${ii}$_${ri}$laed1 is used only for the full eigensystem of a tridiagonal ! matrix. ! stdlib${ii}$_${ri}$laed7 handles the cases in which eigenvalues only or eigenvalues ! and eigenvectors of a full symmetric matrix (which was reduced to ! tridiagonal form) are desired. if( icompq==2_${ik}$ ) then call stdlib${ii}$_${ri}$laed1( matsiz, d( submat ), q( submat, submat ),ldq, iwork( & indxq+submat ),e( submat+msd2-1 ), msd2, work,iwork( subpbs+1 ), info ) else call stdlib${ii}$_${ri}$laed7( icompq, matsiz, qsiz, tlvls, curlvl, curprb,d( submat ), & qstore( 1_${ik}$, submat ), ldqs,iwork( indxq+submat ), e( submat+msd2-1 ),msd2, & work( iq ), iwork( iqptr ),iwork( iprmpt ), iwork( iperm ),iwork( igivpt ), & iwork( igivcl ),work( igivnm ), work( iwrem ),iwork( subpbs+1 ), info ) end if if( info/=0 )go to 130 iwork( i / 2_${ik}$+1 ) = iwork( i+2 ) end do loop_90 subpbs = subpbs / 2_${ik}$ curlvl = curlvl + 1_${ik}$ go to 80 end if ! end while ! re-merge the eigenvalues/vectors which were deflated at the final ! merge step. if( icompq==1_${ik}$ ) then do i = 1, n j = iwork( indxq+i ) work( i ) = d( j ) call stdlib${ii}$_${ri}$copy( qsiz, qstore( 1_${ik}$, j ), 1_${ik}$, q( 1_${ik}$, i ), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$copy( n, work, 1_${ik}$, d, 1_${ik}$ ) else if( icompq==2_${ik}$ ) then do i = 1, n j = iwork( indxq+i ) work( i ) = d( j ) call stdlib${ii}$_${ri}$copy( n, q( 1_${ik}$, j ), 1_${ik}$, work( n*i+1 ), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$copy( n, work, 1_${ik}$, d, 1_${ik}$ ) call stdlib${ii}$_${ri}$lacpy( 'A', n, n, work( n+1 ), n, q, ldq ) else do i = 1, n j = iwork( indxq+i ) work( i ) = d( j ) end do call stdlib${ii}$_${ri}$copy( n, work, 1_${ik}$, d, 1_${ik}$ ) end if go to 140 130 continue info = submat*( n+1 ) + submat + matsiz - 1_${ik}$ 140 continue return end subroutine stdlib${ii}$_${ri}$laed0 #:endif #:endfor pure module subroutine stdlib${ii}$_claed0( qsiz, n, d, e, q, ldq, qstore, ldqs, rwork,iwork, info ) !! Using the divide and conquer method, CLAED0: computes all eigenvalues !! of a symmetric tridiagonal matrix which is one diagonal block of !! those from reducing a dense or band Hermitian matrix and !! corresponding eigenvectors of the dense or band matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq, ldqs, n, qsiz ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: d(*), e(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: q(ldq,*) complex(sp), intent(out) :: qstore(ldqs,*) ! ===================================================================== ! warning: n could be as big as qsiz! ! Local Scalars integer(${ik}$) :: curlvl, curprb, curr, i, igivcl, igivnm, igivpt, indxq, iperm, iprmpt, & iq, iqptr, iwrem, j, k, lgn, ll, matsiz, msd2, smlsiz, smm1, spm1, spm2, submat, & subpbs, tlvls real(sp) :: temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ ! if( icompq < 0 .or. icompq > 2 ) then ! info = -1 ! else if( ( icompq == 1 ) .and. ( qsiz < max( 0, n ) ) ) ! $ then if( qsizsmlsiz ) then do j = subpbs, 1, -1 iwork( 2_${ik}$*j ) = ( iwork( j )+1_${ik}$ ) / 2_${ik}$ iwork( 2_${ik}$*j-1 ) = iwork( j ) / 2_${ik}$ end do tlvls = tlvls + 1_${ik}$ subpbs = 2_${ik}$*subpbs go to 10 end if do j = 2, subpbs iwork( j ) = iwork( j ) + iwork( j-1 ) end do ! divide the matrix into subpbs submatrices of size at most smlsiz+1 ! using rank-1 modifications (cuts). spm1 = subpbs - 1_${ik}$ do i = 1, spm1 submat = iwork( i ) + 1_${ik}$ smm1 = submat - 1_${ik}$ d( smm1 ) = d( smm1 ) - abs( e( smm1 ) ) d( submat ) = d( submat ) - abs( e( smm1 ) ) end do indxq = 4_${ik}$*n + 3_${ik}$ ! set up workspaces for eigenvalues only/accumulate new vectors ! routine temp = log( real( n,KIND=sp) ) / log( two ) lgn = int( temp,KIND=${ik}$) if( 2_${ik}$**lgn0_${ik}$ ) then info = submat*( n+1 ) + submat + matsiz - 1_${ik}$ return end if k = 1_${ik}$ do j = submat, iwork( i+1 ) iwork( indxq+j ) = k k = k + 1_${ik}$ end do end do ! successively merge eigensystems of adjacent submatrices ! into eigensystem for the corresponding larger matrix. ! while ( subpbs > 1 ) curlvl = 1_${ik}$ 80 continue if( subpbs>1_${ik}$ ) then spm2 = subpbs - 2_${ik}$ do i = 0, spm2, 2 if( i==0_${ik}$ ) then submat = 1_${ik}$ matsiz = iwork( 2_${ik}$ ) msd2 = iwork( 1_${ik}$ ) curprb = 0_${ik}$ else submat = iwork( i ) + 1_${ik}$ matsiz = iwork( i+2 ) - iwork( i ) msd2 = matsiz / 2_${ik}$ curprb = curprb + 1_${ik}$ end if ! merge lower order eigensystems (of size msd2 and matsiz - msd2) ! into an eigensystem of size matsiz. stdlib${ii}$_claed7 handles the case ! when the eigenvectors of a full or band hermitian matrix (which ! was reduced to tridiagonal form) are desired. ! i am free to use q as a valuable working space until loop 150. call stdlib${ii}$_claed7( matsiz, msd2, qsiz, tlvls, curlvl, curprb,d( submat ), & qstore( 1_${ik}$, submat ), ldqs,e( submat+msd2-1 ), iwork( indxq+submat ),rwork( iq ), & iwork( iqptr ), iwork( iprmpt ),iwork( iperm ), iwork( igivpt ),iwork( igivcl ), & rwork( igivnm ),q( 1_${ik}$, submat ), rwork( iwrem ),iwork( subpbs+1 ), info ) if( info>0_${ik}$ ) then info = submat*( n+1 ) + submat + matsiz - 1_${ik}$ return end if iwork( i / 2_${ik}$+1 ) = iwork( i+2 ) end do subpbs = subpbs / 2_${ik}$ curlvl = curlvl + 1_${ik}$ go to 80 end if ! end while ! re-merge the eigenvalues/vectors which were deflated at the final ! merge step. do i = 1, n j = iwork( indxq+i ) rwork( i ) = d( j ) call stdlib${ii}$_ccopy( qsiz, qstore( 1_${ik}$, j ), 1_${ik}$, q( 1_${ik}$, i ), 1_${ik}$ ) end do call stdlib${ii}$_scopy( n, rwork, 1_${ik}$, d, 1_${ik}$ ) return end subroutine stdlib${ii}$_claed0 pure module subroutine stdlib${ii}$_zlaed0( qsiz, n, d, e, q, ldq, qstore, ldqs, rwork,iwork, info ) !! Using the divide and conquer method, ZLAED0: computes all eigenvalues !! of a symmetric tridiagonal matrix which is one diagonal block of !! those from reducing a dense or band Hermitian matrix and !! corresponding eigenvectors of the dense or band matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq, ldqs, n, qsiz ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: d(*), e(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: q(ldq,*) complex(dp), intent(out) :: qstore(ldqs,*) ! ===================================================================== ! warning: n could be as big as qsiz! ! Local Scalars integer(${ik}$) :: curlvl, curprb, curr, i, igivcl, igivnm, igivpt, indxq, iperm, iprmpt, & iq, iqptr, iwrem, j, k, lgn, ll, matsiz, msd2, smlsiz, smm1, spm1, spm2, submat, & subpbs, tlvls real(dp) :: temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ ! if( icompq < 0 .or. icompq > 2 ) then ! info = -1 ! else if( ( icompq == 1 ) .and. ( qsiz < max( 0, n ) ) ) ! $ then if( qsizsmlsiz ) then do j = subpbs, 1, -1 iwork( 2_${ik}$*j ) = ( iwork( j )+1_${ik}$ ) / 2_${ik}$ iwork( 2_${ik}$*j-1 ) = iwork( j ) / 2_${ik}$ end do tlvls = tlvls + 1_${ik}$ subpbs = 2_${ik}$*subpbs go to 10 end if do j = 2, subpbs iwork( j ) = iwork( j ) + iwork( j-1 ) end do ! divide the matrix into subpbs submatrices of size at most smlsiz+1 ! using rank-1 modifications (cuts). spm1 = subpbs - 1_${ik}$ do i = 1, spm1 submat = iwork( i ) + 1_${ik}$ smm1 = submat - 1_${ik}$ d( smm1 ) = d( smm1 ) - abs( e( smm1 ) ) d( submat ) = d( submat ) - abs( e( smm1 ) ) end do indxq = 4_${ik}$*n + 3_${ik}$ ! set up workspaces for eigenvalues only/accumulate new vectors ! routine temp = log( real( n,KIND=dp) ) / log( two ) lgn = int( temp,KIND=${ik}$) if( 2_${ik}$**lgn0_${ik}$ ) then info = submat*( n+1 ) + submat + matsiz - 1_${ik}$ return end if k = 1_${ik}$ do j = submat, iwork( i+1 ) iwork( indxq+j ) = k k = k + 1_${ik}$ end do end do ! successively merge eigensystems of adjacent submatrices ! into eigensystem for the corresponding larger matrix. ! while ( subpbs > 1 ) curlvl = 1_${ik}$ 80 continue if( subpbs>1_${ik}$ ) then spm2 = subpbs - 2_${ik}$ do i = 0, spm2, 2 if( i==0_${ik}$ ) then submat = 1_${ik}$ matsiz = iwork( 2_${ik}$ ) msd2 = iwork( 1_${ik}$ ) curprb = 0_${ik}$ else submat = iwork( i ) + 1_${ik}$ matsiz = iwork( i+2 ) - iwork( i ) msd2 = matsiz / 2_${ik}$ curprb = curprb + 1_${ik}$ end if ! merge lower order eigensystems (of size msd2 and matsiz - msd2) ! into an eigensystem of size matsiz. stdlib${ii}$_zlaed7 handles the case ! when the eigenvectors of a full or band hermitian matrix (which ! was reduced to tridiagonal form) are desired. ! i am free to use q as a valuable working space until loop 150. call stdlib${ii}$_zlaed7( matsiz, msd2, qsiz, tlvls, curlvl, curprb,d( submat ), & qstore( 1_${ik}$, submat ), ldqs,e( submat+msd2-1 ), iwork( indxq+submat ),rwork( iq ), & iwork( iqptr ), iwork( iprmpt ),iwork( iperm ), iwork( igivpt ),iwork( igivcl ), & rwork( igivnm ),q( 1_${ik}$, submat ), rwork( iwrem ),iwork( subpbs+1 ), info ) if( info>0_${ik}$ ) then info = submat*( n+1 ) + submat + matsiz - 1_${ik}$ return end if iwork( i / 2_${ik}$+1 ) = iwork( i+2 ) end do subpbs = subpbs / 2_${ik}$ curlvl = curlvl + 1_${ik}$ go to 80 end if ! end while ! re-merge the eigenvalues/vectors which were deflated at the final ! merge step. do i = 1, n j = iwork( indxq+i ) rwork( i ) = d( j ) call stdlib${ii}$_zcopy( qsiz, qstore( 1_${ik}$, j ), 1_${ik}$, q( 1_${ik}$, i ), 1_${ik}$ ) end do call stdlib${ii}$_dcopy( n, rwork, 1_${ik}$, d, 1_${ik}$ ) return end subroutine stdlib${ii}$_zlaed0 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laed0( qsiz, n, d, e, q, ldq, qstore, ldqs, rwork,iwork, info ) !! Using the divide and conquer method, ZLAED0: computes all eigenvalues !! of a symmetric tridiagonal matrix which is one diagonal block of !! those from reducing a dense or band Hermitian matrix and !! corresponding eigenvectors of the dense or band matrix. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq, ldqs, n, qsiz ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(inout) :: d(*), e(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: q(ldq,*) complex(${ck}$), intent(out) :: qstore(ldqs,*) ! ===================================================================== ! warning: n could be as big as qsiz! ! Local Scalars integer(${ik}$) :: curlvl, curprb, curr, i, igivcl, igivnm, igivpt, indxq, iperm, iprmpt, & iq, iqptr, iwrem, j, k, lgn, ll, matsiz, msd2, smlsiz, smm1, spm1, spm2, submat, & subpbs, tlvls real(${ck}$) :: temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ ! if( icompq < 0 .or. icompq > 2 ) then ! info = -1 ! else if( ( icompq == 1 ) .and. ( qsiz < max( 0, n ) ) ) ! $ then if( qsizsmlsiz ) then do j = subpbs, 1, -1 iwork( 2_${ik}$*j ) = ( iwork( j )+1_${ik}$ ) / 2_${ik}$ iwork( 2_${ik}$*j-1 ) = iwork( j ) / 2_${ik}$ end do tlvls = tlvls + 1_${ik}$ subpbs = 2_${ik}$*subpbs go to 10 end if do j = 2, subpbs iwork( j ) = iwork( j ) + iwork( j-1 ) end do ! divide the matrix into subpbs submatrices of size at most smlsiz+1 ! using rank-1 modifications (cuts). spm1 = subpbs - 1_${ik}$ do i = 1, spm1 submat = iwork( i ) + 1_${ik}$ smm1 = submat - 1_${ik}$ d( smm1 ) = d( smm1 ) - abs( e( smm1 ) ) d( submat ) = d( submat ) - abs( e( smm1 ) ) end do indxq = 4_${ik}$*n + 3_${ik}$ ! set up workspaces for eigenvalues only/accumulate new vectors ! routine temp = log( real( n,KIND=${ck}$) ) / log( two ) lgn = int( temp,KIND=${ik}$) if( 2_${ik}$**lgn0_${ik}$ ) then info = submat*( n+1 ) + submat + matsiz - 1_${ik}$ return end if k = 1_${ik}$ do j = submat, iwork( i+1 ) iwork( indxq+j ) = k k = k + 1_${ik}$ end do end do ! successively merge eigensystems of adjacent submatrices ! into eigensystem for the corresponding larger matrix. ! while ( subpbs > 1 ) curlvl = 1_${ik}$ 80 continue if( subpbs>1_${ik}$ ) then spm2 = subpbs - 2_${ik}$ do i = 0, spm2, 2 if( i==0_${ik}$ ) then submat = 1_${ik}$ matsiz = iwork( 2_${ik}$ ) msd2 = iwork( 1_${ik}$ ) curprb = 0_${ik}$ else submat = iwork( i ) + 1_${ik}$ matsiz = iwork( i+2 ) - iwork( i ) msd2 = matsiz / 2_${ik}$ curprb = curprb + 1_${ik}$ end if ! merge lower order eigensystems (of size msd2 and matsiz - msd2) ! into an eigensystem of size matsiz. stdlib${ii}$_${ci}$laed7 handles the case ! when the eigenvectors of a full or band hermitian matrix (which ! was reduced to tridiagonal form) are desired. ! i am free to use q as a valuable working space until loop 150. call stdlib${ii}$_${ci}$laed7( matsiz, msd2, qsiz, tlvls, curlvl, curprb,d( submat ), & qstore( 1_${ik}$, submat ), ldqs,e( submat+msd2-1 ), iwork( indxq+submat ),rwork( iq ), & iwork( iqptr ), iwork( iprmpt ),iwork( iperm ), iwork( igivpt ),iwork( igivcl ), & rwork( igivnm ),q( 1_${ik}$, submat ), rwork( iwrem ),iwork( subpbs+1 ), info ) if( info>0_${ik}$ ) then info = submat*( n+1 ) + submat + matsiz - 1_${ik}$ return end if iwork( i / 2_${ik}$+1 ) = iwork( i+2 ) end do subpbs = subpbs / 2_${ik}$ curlvl = curlvl + 1_${ik}$ go to 80 end if ! end while ! re-merge the eigenvalues/vectors which were deflated at the final ! merge step. do i = 1, n j = iwork( indxq+i ) rwork( i ) = d( j ) call stdlib${ii}$_${ci}$copy( qsiz, qstore( 1_${ik}$, j ), 1_${ik}$, q( 1_${ik}$, i ), 1_${ik}$ ) end do call stdlib${ii}$_${c2ri(ci)}$copy( n, rwork, 1_${ik}$, d, 1_${ik}$ ) return end subroutine stdlib${ii}$_${ci}$laed0 #:endif #:endfor pure module subroutine stdlib${ii}$_slaed1( n, d, q, ldq, indxq, rho, cutpnt, work, iwork,info ) !! SLAED1 computes the updated eigensystem of a diagonal !! matrix after modification by a rank-one symmetric matrix. This !! routine is used only for the eigenproblem which requires all !! eigenvalues and eigenvectors of a tridiagonal matrix. SLAED7 handles !! the case in which eigenvalues only or eigenvalues and eigenvectors !! of a full symmetric matrix (which was reduced to tridiagonal form) !! are desired. !! T = Q(in) ( D(in) + RHO * Z*Z**T ) Q**T(in) = Q(out) * D(out) * Q**T(out) !! where Z = Q**T*u, u is a vector of length N with ones in the !! CUTPNT and CUTPNT + 1 th elements and zeros elsewhere. !! The eigenvectors of the original matrix are stored in Q, and the !! eigenvalues are in D. The algorithm consists of three stages: !! The first stage consists of deflating the size of the problem !! when there are multiple eigenvalues or if there is a zero in !! the Z vector. For each such occurrence the dimension of the !! secular equation problem is reduced by one. This stage is !! performed by the routine SLAED2. !! The second stage consists of calculating the updated !! eigenvalues. This is done by finding the roots of the secular !! equation via the routine SLAED4 (as called by SLAED3). !! This routine also calculates the eigenvectors of the current !! problem. !! The final stage consists of computing the updated eigenvectors !! directly using the updated eigenvalues. The eigenvectors for !! the current problem are multiplied with the eigenvectors from !! the overall problem. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: cutpnt, ldq, n integer(${ik}$), intent(out) :: info real(sp), intent(inout) :: rho ! Array Arguments integer(${ik}$), intent(inout) :: indxq(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: d(*), q(ldq,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: coltyp, cpp1, i, idlmda, indx, indxc, indxp, iq2, is, iw, iz, k, n1, & n2 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ldqcutpnt .or. ( n / 2_${ik}$ )cutpnt .or. ( n / 2_${ik}$ )cutpnt .or. ( n / 2_${ik}$ )n1 .or. ( n / 2_${ik}$ )n )go to 100 if( rho*abs( z( nj ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ coltyp( nj ) = 4_${ik}$ indxp( k2 ) = nj else ! check if eigenvalues are close enough to allow deflation. s = z( pj ) c = z( nj ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_slapy2( c, s ) t = d( nj ) - d( pj ) c = c / tau s = -s / tau if( abs( t*c*s )<=tol ) then ! deflation is possible. z( nj ) = tau z( pj ) = zero if( coltyp( nj )/=coltyp( pj ) )coltyp( nj ) = 2_${ik}$ coltyp( pj ) = 4_${ik}$ call stdlib${ii}$_srot( n, q( 1_${ik}$, pj ), 1_${ik}$, q( 1_${ik}$, nj ), 1_${ik}$, c, s ) t = d( pj )*c**2_${ik}$ + d( nj )*s**2_${ik}$ d( nj ) = d( pj )*s**2_${ik}$ + d( nj )*c**2_${ik}$ d( pj ) = t k2 = k2 - 1_${ik}$ i = 1_${ik}$ 90 continue if( k2+i<=n ) then if( d( pj )n1 .or. ( n / 2_${ik}$ )n )go to 100 if( rho*abs( z( nj ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ coltyp( nj ) = 4_${ik}$ indxp( k2 ) = nj else ! check if eigenvalues are close enough to allow deflation. s = z( pj ) c = z( nj ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_dlapy2( c, s ) t = d( nj ) - d( pj ) c = c / tau s = -s / tau if( abs( t*c*s )<=tol ) then ! deflation is possible. z( nj ) = tau z( pj ) = zero if( coltyp( nj )/=coltyp( pj ) )coltyp( nj ) = 2_${ik}$ coltyp( pj ) = 4_${ik}$ call stdlib${ii}$_drot( n, q( 1_${ik}$, pj ), 1_${ik}$, q( 1_${ik}$, nj ), 1_${ik}$, c, s ) t = d( pj )*c**2_${ik}$ + d( nj )*s**2_${ik}$ d( nj ) = d( pj )*s**2_${ik}$ + d( nj )*c**2_${ik}$ d( pj ) = t k2 = k2 - 1_${ik}$ i = 1_${ik}$ 90 continue if( k2+i<=n ) then if( d( pj )n1 .or. ( n / 2_${ik}$ )n )go to 100 if( rho*abs( z( nj ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ coltyp( nj ) = 4_${ik}$ indxp( k2 ) = nj else ! check if eigenvalues are close enough to allow deflation. s = z( pj ) c = z( nj ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_${ri}$lapy2( c, s ) t = d( nj ) - d( pj ) c = c / tau s = -s / tau if( abs( t*c*s )<=tol ) then ! deflation is possible. z( nj ) = tau z( pj ) = zero if( coltyp( nj )/=coltyp( pj ) )coltyp( nj ) = 2_${ik}$ coltyp( pj ) = 4_${ik}$ call stdlib${ii}$_${ri}$rot( n, q( 1_${ik}$, pj ), 1_${ik}$, q( 1_${ik}$, nj ), 1_${ik}$, c, s ) t = d( pj )*c**2_${ik}$ + d( nj )*s**2_${ik}$ d( nj ) = d( pj )*s**2_${ik}$ + d( nj )*c**2_${ik}$ d( pj ) = t k2 = k2 - 1_${ik}$ i = 1_${ik}$ 90 continue if( k2+i<=n ) then if( d( pj ) 0. This is arranged by the calling routine, and is !! no loss in generality. The rank-one modified system is thus !! diag( D ) + RHO * Z * Z_transpose. !! where we assume the Euclidean norm of Z is 1. !! The method consists of approximating the rational functions in the !! secular equation by simpler interpolating rational functions. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i, n integer(${ik}$), intent(out) :: info real(sp), intent(out) :: dlam real(sp), intent(in) :: rho ! Array Arguments real(sp), intent(in) :: d(*), z(*) real(sp), intent(out) :: delta(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 30_${ik}$ ! Local Scalars logical(lk) :: orgati, swtch, swtch3 integer(${ik}$) :: ii, iim1, iip1, ip1, iter, j, niter real(sp) :: a, b, c, del, dltlb, dltub, dphi, dpsi, dw, eps, erretm, eta, midpt, phi, & prew, psi, rhoinv, tau, temp, temp1, w ! Local Arrays real(sp) :: zz(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! since this routine is called in an inner loop, we do no argument ! checking. ! quick return for n=1 and 2. info = 0_${ik}$ if( n==1_${ik}$ ) then ! presumably, i=1 upon entry dlam = d( 1_${ik}$ ) + rho*z( 1_${ik}$ )*z( 1_${ik}$ ) delta( 1_${ik}$ ) = one return end if if( n==2_${ik}$ ) then call stdlib${ii}$_slaed5( i, d, z, delta, rho, dlam ) return end if ! compute machine epsilon eps = stdlib${ii}$_slamch( 'EPSILON' ) rhoinv = one / rho ! the case i = n if( i==n ) then ! initialize some basic variables ii = n - 1_${ik}$ niter = 1_${ik}$ ! calculate initial guess midpt = rho / two ! if ||z||_2 is not one, then temp should be set to ! rho * ||z||_2^2 / two do j = 1, n delta( j ) = ( d( j )-d( i ) ) - midpt end do psi = zero do j = 1, n - 2 psi = psi + z( j )*z( j ) / delta( j ) end do c = rhoinv + psi w = c + z( ii )*z( ii ) / delta( ii ) +z( n )*z( n ) / delta( n ) if( w<=zero ) then temp = z( n-1 )*z( n-1 ) / ( d( n )-d( n-1 )+rho ) +z( n )*z( n ) / rho if( c<=temp ) then tau = rho else del = d( n ) - d( n-1 ) a = -c*del + z( n-1 )*z( n-1 ) + z( n )*z( n ) b = z( n )*z( n )*del if( a=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = tau + eta if( temp>dltub .or. temp=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = tau + eta if( temp>dltub .or. tempzero ) then ! d(i)< the ith eigenvalue < (d(i)+d(i+1))/2 ! we choose d(i) as origin. orgati = .true. a = c*del + z( i )*z( i ) + z( ip1 )*z( ip1 ) b = z( i )*z( i )*del if( a>zero ) then tau = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) else tau = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) end if dltlb = zero dltub = midpt else ! (d(i)+d(i+1))/2 <= the ith eigenvalue < d(i+1) ! we choose d(i+1) as origin. orgati = .false. a = c*del - z( i )*z( i ) - z( ip1 )*z( ip1 ) b = z( ip1 )*z( ip1 )*del if( azero )swtch3 = .true. end if if( ii==1_${ik}$ .or. ii==n )swtch3 = .false. temp = z( ii ) / delta( ii ) dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = w + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv +three*abs( temp ) + abs( tau )& *dw ! test for convergence if( abs( w )<=eps*erretm ) then if( orgati ) then dlam = d( i ) + tau else dlam = d( ip1 ) + tau end if go to 250 end if if( w<=zero ) then dltlb = max( dltlb, tau ) else dltub = min( dltub, tau ) end if ! calculate the new step niter = niter + 1_${ik}$ if( .not.swtch3 ) then if( orgati ) then c = w - delta( ip1 )*dw - ( d( i )-d( ip1 ) )*( z( i ) / delta( i ) )& **2_${ik}$ else c = w - delta( i )*dw - ( d( ip1 )-d( i ) )*( z( ip1 ) / delta( ip1 ) )& **2_${ik}$ end if a = ( delta( i )+delta( ip1 ) )*w -delta( i )*delta( ip1 )*dw b = delta( i )*delta( ip1 )*w if( c==zero ) then if( a==zero ) then if( orgati ) then a = z( i )*z( i ) + delta( ip1 )*delta( ip1 )*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) + delta( i )*delta( i )*( dpsi+dphi ) end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles temp = rhoinv + psi + phi if( orgati ) then temp1 = z( iim1 ) / delta( iim1 ) temp1 = temp1*temp1 c = temp - delta( iip1 )*( dpsi+dphi ) -( d( iim1 )-d( iip1 ) )*temp1 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) zz( 3_${ik}$ ) = delta( iip1 )*delta( iip1 )*( ( dpsi-temp1 )+dphi ) else temp1 = z( iip1 ) / delta( iip1 ) temp1 = temp1*temp1 c = temp - delta( iim1 )*( dpsi+dphi ) -( d( iip1 )-d( iim1 ) )*temp1 zz( 1_${ik}$ ) = delta( iim1 )*delta( iim1 )*( dpsi+( dphi-temp1 ) ) zz( 3_${ik}$ ) = z( iip1 )*z( iip1 ) end if zz( 2_${ik}$ ) = z( ii )*z( ii ) call stdlib${ii}$_slaed6( niter, orgati, c, delta( iim1 ), zz, w, eta,info ) if( info/=0 )go to 250 end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw temp = tau + eta if( temp>dltub .or. tempabs( prew ) / ten )swtch = .true. else if( w>abs( prew ) / ten )swtch = .true. end if tau = tau + eta ! main loop to update the values of the array delta iter = niter + 1_${ik}$ loop_240: do niter = iter, maxit ! test for convergence if( abs( w )<=eps*erretm ) then if( orgati ) then dlam = d( i ) + tau else dlam = d( ip1 ) + tau end if go to 250 end if if( w<=zero ) then dltlb = max( dltlb, tau ) else dltub = min( dltub, tau ) end if ! calculate the new step if( .not.swtch3 ) then if( .not.swtch ) then if( orgati ) then c = w - delta( ip1 )*dw -( d( i )-d( ip1 ) )*( z( i ) / delta( i ) )& **2_${ik}$ else c = w - delta( i )*dw - ( d( ip1 )-d( i ) )*( z( ip1 ) / delta( ip1 ) )& **2_${ik}$ end if else temp = z( ii ) / delta( ii ) if( orgati ) then dpsi = dpsi + temp*temp else dphi = dphi + temp*temp end if c = w - delta( i )*dpsi - delta( ip1 )*dphi end if a = ( delta( i )+delta( ip1 ) )*w -delta( i )*delta( ip1 )*dw b = delta( i )*delta( ip1 )*w if( c==zero ) then if( a==zero ) then if( .not.swtch ) then if( orgati ) then a = z( i )*z( i ) + delta( ip1 )*delta( ip1 )*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) +delta( i )*delta( i )*( dpsi+dphi ) end if else a = delta( i )*delta( i )*dpsi +delta( ip1 )*delta( ip1 )& *dphi end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles temp = rhoinv + psi + phi if( swtch ) then c = temp - delta( iim1 )*dpsi - delta( iip1 )*dphi zz( 1_${ik}$ ) = delta( iim1 )*delta( iim1 )*dpsi zz( 3_${ik}$ ) = delta( iip1 )*delta( iip1 )*dphi else if( orgati ) then temp1 = z( iim1 ) / delta( iim1 ) temp1 = temp1*temp1 c = temp - delta( iip1 )*( dpsi+dphi ) -( d( iim1 )-d( iip1 ) )& *temp1 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) zz( 3_${ik}$ ) = delta( iip1 )*delta( iip1 )*( ( dpsi-temp1 )+dphi ) else temp1 = z( iip1 ) / delta( iip1 ) temp1 = temp1*temp1 c = temp - delta( iim1 )*( dpsi+dphi ) -( d( iip1 )-d( iim1 ) )& *temp1 zz( 1_${ik}$ ) = delta( iim1 )*delta( iim1 )*( dpsi+( dphi-temp1 ) ) zz( 3_${ik}$ ) = z( iip1 )*z( iip1 ) end if end if call stdlib${ii}$_slaed6( niter, orgati, c, delta( iim1 ), zz, w, eta,info ) if( info/=0 )go to 250 end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw temp = tau + eta if( temp>dltub .or. tempzero .and. abs( w )>abs( prew ) / ten )swtch = .not.swtch end do loop_240 ! return with info = 1, niter = maxit and not converged info = 1_${ik}$ if( orgati ) then dlam = d( i ) + tau else dlam = d( ip1 ) + tau end if end if 250 continue return end subroutine stdlib${ii}$_slaed4 pure module subroutine stdlib${ii}$_dlaed4( n, i, d, z, delta, rho, dlam, info ) !! This subroutine computes the I-th updated eigenvalue of a symmetric !! rank-one modification to a diagonal matrix whose elements are !! given in the array d, and that !! D(i) < D(j) for i < j !! and that RHO > 0. This is arranged by the calling routine, and is !! no loss in generality. The rank-one modified system is thus !! diag( D ) + RHO * Z * Z_transpose. !! where we assume the Euclidean norm of Z is 1. !! The method consists of approximating the rational functions in the !! secular equation by simpler interpolating rational functions. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i, n integer(${ik}$), intent(out) :: info real(dp), intent(out) :: dlam real(dp), intent(in) :: rho ! Array Arguments real(dp), intent(in) :: d(*), z(*) real(dp), intent(out) :: delta(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 30_${ik}$ ! Local Scalars logical(lk) :: orgati, swtch, swtch3 integer(${ik}$) :: ii, iim1, iip1, ip1, iter, j, niter real(dp) :: a, b, c, del, dltlb, dltub, dphi, dpsi, dw, eps, erretm, eta, midpt, phi, & prew, psi, rhoinv, tau, temp, temp1, w ! Local Arrays real(dp) :: zz(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! since this routine is called in an inner loop, we do no argument ! checking. ! quick return for n=1 and 2. info = 0_${ik}$ if( n==1_${ik}$ ) then ! presumably, i=1 upon entry dlam = d( 1_${ik}$ ) + rho*z( 1_${ik}$ )*z( 1_${ik}$ ) delta( 1_${ik}$ ) = one return end if if( n==2_${ik}$ ) then call stdlib${ii}$_dlaed5( i, d, z, delta, rho, dlam ) return end if ! compute machine epsilon eps = stdlib${ii}$_dlamch( 'EPSILON' ) rhoinv = one / rho ! the case i = n if( i==n ) then ! initialize some basic variables ii = n - 1_${ik}$ niter = 1_${ik}$ ! calculate initial guess midpt = rho / two ! if ||z||_2 is not one, then temp should be set to ! rho * ||z||_2^2 / two do j = 1, n delta( j ) = ( d( j )-d( i ) ) - midpt end do psi = zero do j = 1, n - 2 psi = psi + z( j )*z( j ) / delta( j ) end do c = rhoinv + psi w = c + z( ii )*z( ii ) / delta( ii ) +z( n )*z( n ) / delta( n ) if( w<=zero ) then temp = z( n-1 )*z( n-1 ) / ( d( n )-d( n-1 )+rho ) +z( n )*z( n ) / rho if( c<=temp ) then tau = rho else del = d( n ) - d( n-1 ) a = -c*del + z( n-1 )*z( n-1 ) + z( n )*z( n ) b = z( n )*z( n )*del if( a=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = tau + eta if( temp>dltub .or. temp=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = tau + eta if( temp>dltub .or. tempzero ) then ! d(i)< the ith eigenvalue < (d(i)+d(i+1))/2 ! we choose d(i) as origin. orgati = .true. a = c*del + z( i )*z( i ) + z( ip1 )*z( ip1 ) b = z( i )*z( i )*del if( a>zero ) then tau = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) else tau = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) end if dltlb = zero dltub = midpt else ! (d(i)+d(i+1))/2 <= the ith eigenvalue < d(i+1) ! we choose d(i+1) as origin. orgati = .false. a = c*del - z( i )*z( i ) - z( ip1 )*z( ip1 ) b = z( ip1 )*z( ip1 )*del if( azero )swtch3 = .true. end if if( ii==1_${ik}$ .or. ii==n )swtch3 = .false. temp = z( ii ) / delta( ii ) dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = w + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv +three*abs( temp ) + abs( tau )& *dw ! test for convergence if( abs( w )<=eps*erretm ) then if( orgati ) then dlam = d( i ) + tau else dlam = d( ip1 ) + tau end if go to 250 end if if( w<=zero ) then dltlb = max( dltlb, tau ) else dltub = min( dltub, tau ) end if ! calculate the new step niter = niter + 1_${ik}$ if( .not.swtch3 ) then if( orgati ) then c = w - delta( ip1 )*dw - ( d( i )-d( ip1 ) )*( z( i ) / delta( i ) )& **2_${ik}$ else c = w - delta( i )*dw - ( d( ip1 )-d( i ) )*( z( ip1 ) / delta( ip1 ) )& **2_${ik}$ end if a = ( delta( i )+delta( ip1 ) )*w -delta( i )*delta( ip1 )*dw b = delta( i )*delta( ip1 )*w if( c==zero ) then if( a==zero ) then if( orgati ) then a = z( i )*z( i ) + delta( ip1 )*delta( ip1 )*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) + delta( i )*delta( i )*( dpsi+dphi ) end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles temp = rhoinv + psi + phi if( orgati ) then temp1 = z( iim1 ) / delta( iim1 ) temp1 = temp1*temp1 c = temp - delta( iip1 )*( dpsi+dphi ) -( d( iim1 )-d( iip1 ) )*temp1 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) zz( 3_${ik}$ ) = delta( iip1 )*delta( iip1 )*( ( dpsi-temp1 )+dphi ) else temp1 = z( iip1 ) / delta( iip1 ) temp1 = temp1*temp1 c = temp - delta( iim1 )*( dpsi+dphi ) -( d( iip1 )-d( iim1 ) )*temp1 zz( 1_${ik}$ ) = delta( iim1 )*delta( iim1 )*( dpsi+( dphi-temp1 ) ) zz( 3_${ik}$ ) = z( iip1 )*z( iip1 ) end if zz( 2_${ik}$ ) = z( ii )*z( ii ) call stdlib${ii}$_dlaed6( niter, orgati, c, delta( iim1 ), zz, w, eta,info ) if( info/=0 )go to 250 end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw temp = tau + eta if( temp>dltub .or. tempabs( prew ) / ten )swtch = .true. else if( w>abs( prew ) / ten )swtch = .true. end if tau = tau + eta ! main loop to update the values of the array delta iter = niter + 1_${ik}$ loop_240: do niter = iter, maxit ! test for convergence if( abs( w )<=eps*erretm ) then if( orgati ) then dlam = d( i ) + tau else dlam = d( ip1 ) + tau end if go to 250 end if if( w<=zero ) then dltlb = max( dltlb, tau ) else dltub = min( dltub, tau ) end if ! calculate the new step if( .not.swtch3 ) then if( .not.swtch ) then if( orgati ) then c = w - delta( ip1 )*dw -( d( i )-d( ip1 ) )*( z( i ) / delta( i ) )& **2_${ik}$ else c = w - delta( i )*dw - ( d( ip1 )-d( i ) )*( z( ip1 ) / delta( ip1 ) )& **2_${ik}$ end if else temp = z( ii ) / delta( ii ) if( orgati ) then dpsi = dpsi + temp*temp else dphi = dphi + temp*temp end if c = w - delta( i )*dpsi - delta( ip1 )*dphi end if a = ( delta( i )+delta( ip1 ) )*w -delta( i )*delta( ip1 )*dw b = delta( i )*delta( ip1 )*w if( c==zero ) then if( a==zero ) then if( .not.swtch ) then if( orgati ) then a = z( i )*z( i ) + delta( ip1 )*delta( ip1 )*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) +delta( i )*delta( i )*( dpsi+dphi ) end if else a = delta( i )*delta( i )*dpsi +delta( ip1 )*delta( ip1 )& *dphi end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles temp = rhoinv + psi + phi if( swtch ) then c = temp - delta( iim1 )*dpsi - delta( iip1 )*dphi zz( 1_${ik}$ ) = delta( iim1 )*delta( iim1 )*dpsi zz( 3_${ik}$ ) = delta( iip1 )*delta( iip1 )*dphi else if( orgati ) then temp1 = z( iim1 ) / delta( iim1 ) temp1 = temp1*temp1 c = temp - delta( iip1 )*( dpsi+dphi ) -( d( iim1 )-d( iip1 ) )& *temp1 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) zz( 3_${ik}$ ) = delta( iip1 )*delta( iip1 )*( ( dpsi-temp1 )+dphi ) else temp1 = z( iip1 ) / delta( iip1 ) temp1 = temp1*temp1 c = temp - delta( iim1 )*( dpsi+dphi ) -( d( iip1 )-d( iim1 ) )& *temp1 zz( 1_${ik}$ ) = delta( iim1 )*delta( iim1 )*( dpsi+( dphi-temp1 ) ) zz( 3_${ik}$ ) = z( iip1 )*z( iip1 ) end if end if call stdlib${ii}$_dlaed6( niter, orgati, c, delta( iim1 ), zz, w, eta,info ) if( info/=0 )go to 250 end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw temp = tau + eta if( temp>dltub .or. tempzero .and. abs( w )>abs( prew ) / ten )swtch = .not.swtch end do loop_240 ! return with info = 1, niter = maxit and not converged info = 1_${ik}$ if( orgati ) then dlam = d( i ) + tau else dlam = d( ip1 ) + tau end if end if 250 continue return end subroutine stdlib${ii}$_dlaed4 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laed4( n, i, d, z, delta, rho, dlam, info ) !! This subroutine computes the I-th updated eigenvalue of a symmetric !! rank-one modification to a diagonal matrix whose elements are !! given in the array d, and that !! D(i) < D(j) for i < j !! and that RHO > 0. This is arranged by the calling routine, and is !! no loss in generality. The rank-one modified system is thus !! diag( D ) + RHO * Z * Z_transpose. !! where we assume the Euclidean norm of Z is 1. !! The method consists of approximating the rational functions in the !! secular equation by simpler interpolating rational functions. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i, n integer(${ik}$), intent(out) :: info real(${rk}$), intent(out) :: dlam real(${rk}$), intent(in) :: rho ! Array Arguments real(${rk}$), intent(in) :: d(*), z(*) real(${rk}$), intent(out) :: delta(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 30_${ik}$ ! Local Scalars logical(lk) :: orgati, swtch, swtch3 integer(${ik}$) :: ii, iim1, iip1, ip1, iter, j, niter real(${rk}$) :: a, b, c, del, dltlb, dltub, dphi, dpsi, dw, eps, erretm, eta, midpt, phi, & prew, psi, rhoinv, tau, temp, temp1, w ! Local Arrays real(${rk}$) :: zz(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! since this routine is called in an inner loop, we do no argument ! checking. ! quick return for n=1 and 2. info = 0_${ik}$ if( n==1_${ik}$ ) then ! presumably, i=1 upon entry dlam = d( 1_${ik}$ ) + rho*z( 1_${ik}$ )*z( 1_${ik}$ ) delta( 1_${ik}$ ) = one return end if if( n==2_${ik}$ ) then call stdlib${ii}$_${ri}$laed5( i, d, z, delta, rho, dlam ) return end if ! compute machine epsilon eps = stdlib${ii}$_${ri}$lamch( 'EPSILON' ) rhoinv = one / rho ! the case i = n if( i==n ) then ! initialize some basic variables ii = n - 1_${ik}$ niter = 1_${ik}$ ! calculate initial guess midpt = rho / two ! if ||z||_2 is not one, then temp should be set to ! rho * ||z||_2^2 / two do j = 1, n delta( j ) = ( d( j )-d( i ) ) - midpt end do psi = zero do j = 1, n - 2 psi = psi + z( j )*z( j ) / delta( j ) end do c = rhoinv + psi w = c + z( ii )*z( ii ) / delta( ii ) +z( n )*z( n ) / delta( n ) if( w<=zero ) then temp = z( n-1 )*z( n-1 ) / ( d( n )-d( n-1 )+rho ) +z( n )*z( n ) / rho if( c<=temp ) then tau = rho else del = d( n ) - d( n-1 ) a = -c*del + z( n-1 )*z( n-1 ) + z( n )*z( n ) b = z( n )*z( n )*del if( a=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = tau + eta if( temp>dltub .or. temp=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = tau + eta if( temp>dltub .or. tempzero ) then ! d(i)< the ith eigenvalue < (d(i)+d(i+1))/2 ! we choose d(i) as origin. orgati = .true. a = c*del + z( i )*z( i ) + z( ip1 )*z( ip1 ) b = z( i )*z( i )*del if( a>zero ) then tau = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) else tau = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) end if dltlb = zero dltub = midpt else ! (d(i)+d(i+1))/2 <= the ith eigenvalue < d(i+1) ! we choose d(i+1) as origin. orgati = .false. a = c*del - z( i )*z( i ) - z( ip1 )*z( ip1 ) b = z( ip1 )*z( ip1 )*del if( azero )swtch3 = .true. end if if( ii==1_${ik}$ .or. ii==n )swtch3 = .false. temp = z( ii ) / delta( ii ) dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = w + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv +three*abs( temp ) + abs( tau )& *dw ! test for convergence if( abs( w )<=eps*erretm ) then if( orgati ) then dlam = d( i ) + tau else dlam = d( ip1 ) + tau end if go to 250 end if if( w<=zero ) then dltlb = max( dltlb, tau ) else dltub = min( dltub, tau ) end if ! calculate the new step niter = niter + 1_${ik}$ if( .not.swtch3 ) then if( orgati ) then c = w - delta( ip1 )*dw - ( d( i )-d( ip1 ) )*( z( i ) / delta( i ) )& **2_${ik}$ else c = w - delta( i )*dw - ( d( ip1 )-d( i ) )*( z( ip1 ) / delta( ip1 ) )& **2_${ik}$ end if a = ( delta( i )+delta( ip1 ) )*w -delta( i )*delta( ip1 )*dw b = delta( i )*delta( ip1 )*w if( c==zero ) then if( a==zero ) then if( orgati ) then a = z( i )*z( i ) + delta( ip1 )*delta( ip1 )*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) + delta( i )*delta( i )*( dpsi+dphi ) end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles temp = rhoinv + psi + phi if( orgati ) then temp1 = z( iim1 ) / delta( iim1 ) temp1 = temp1*temp1 c = temp - delta( iip1 )*( dpsi+dphi ) -( d( iim1 )-d( iip1 ) )*temp1 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) zz( 3_${ik}$ ) = delta( iip1 )*delta( iip1 )*( ( dpsi-temp1 )+dphi ) else temp1 = z( iip1 ) / delta( iip1 ) temp1 = temp1*temp1 c = temp - delta( iim1 )*( dpsi+dphi ) -( d( iip1 )-d( iim1 ) )*temp1 zz( 1_${ik}$ ) = delta( iim1 )*delta( iim1 )*( dpsi+( dphi-temp1 ) ) zz( 3_${ik}$ ) = z( iip1 )*z( iip1 ) end if zz( 2_${ik}$ ) = z( ii )*z( ii ) call stdlib${ii}$_${ri}$laed6( niter, orgati, c, delta( iim1 ), zz, w, eta,info ) if( info/=0 )go to 250 end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw temp = tau + eta if( temp>dltub .or. tempabs( prew ) / ten )swtch = .true. else if( w>abs( prew ) / ten )swtch = .true. end if tau = tau + eta ! main loop to update the values of the array delta iter = niter + 1_${ik}$ loop_240: do niter = iter, maxit ! test for convergence if( abs( w )<=eps*erretm ) then if( orgati ) then dlam = d( i ) + tau else dlam = d( ip1 ) + tau end if go to 250 end if if( w<=zero ) then dltlb = max( dltlb, tau ) else dltub = min( dltub, tau ) end if ! calculate the new step if( .not.swtch3 ) then if( .not.swtch ) then if( orgati ) then c = w - delta( ip1 )*dw -( d( i )-d( ip1 ) )*( z( i ) / delta( i ) )& **2_${ik}$ else c = w - delta( i )*dw - ( d( ip1 )-d( i ) )*( z( ip1 ) / delta( ip1 ) )& **2_${ik}$ end if else temp = z( ii ) / delta( ii ) if( orgati ) then dpsi = dpsi + temp*temp else dphi = dphi + temp*temp end if c = w - delta( i )*dpsi - delta( ip1 )*dphi end if a = ( delta( i )+delta( ip1 ) )*w -delta( i )*delta( ip1 )*dw b = delta( i )*delta( ip1 )*w if( c==zero ) then if( a==zero ) then if( .not.swtch ) then if( orgati ) then a = z( i )*z( i ) + delta( ip1 )*delta( ip1 )*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) +delta( i )*delta( i )*( dpsi+dphi ) end if else a = delta( i )*delta( i )*dpsi +delta( ip1 )*delta( ip1 )& *dphi end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles temp = rhoinv + psi + phi if( swtch ) then c = temp - delta( iim1 )*dpsi - delta( iip1 )*dphi zz( 1_${ik}$ ) = delta( iim1 )*delta( iim1 )*dpsi zz( 3_${ik}$ ) = delta( iip1 )*delta( iip1 )*dphi else if( orgati ) then temp1 = z( iim1 ) / delta( iim1 ) temp1 = temp1*temp1 c = temp - delta( iip1 )*( dpsi+dphi ) -( d( iim1 )-d( iip1 ) )& *temp1 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) zz( 3_${ik}$ ) = delta( iip1 )*delta( iip1 )*( ( dpsi-temp1 )+dphi ) else temp1 = z( iip1 ) / delta( iip1 ) temp1 = temp1*temp1 c = temp - delta( iim1 )*( dpsi+dphi ) -( d( iip1 )-d( iim1 ) )& *temp1 zz( 1_${ik}$ ) = delta( iim1 )*delta( iim1 )*( dpsi+( dphi-temp1 ) ) zz( 3_${ik}$ ) = z( iip1 )*z( iip1 ) end if end if call stdlib${ii}$_${ri}$laed6( niter, orgati, c, delta( iim1 ), zz, w, eta,info ) if( info/=0 )go to 250 end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw temp = tau + eta if( temp>dltub .or. tempzero .and. abs( w )>abs( prew ) / ten )swtch = .not.swtch end do loop_240 ! return with info = 1, niter = maxit and not converged info = 1_${ik}$ if( orgati ) then dlam = d( i ) + tau else dlam = d( ip1 ) + tau end if end if 250 continue return end subroutine stdlib${ii}$_${ri}$laed4 #:endif #:endfor pure module subroutine stdlib${ii}$_slaed5( i, d, z, delta, rho, dlam ) !! This subroutine computes the I-th eigenvalue of a symmetric rank-one !! modification of a 2-by-2 diagonal matrix !! diag( D ) + RHO * Z * transpose(Z) . !! The diagonal elements in the array D are assumed to satisfy !! D(i) < D(j) for i < j . !! We also assume RHO > 0 and that the Euclidean norm of the vector !! Z is one. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i real(sp), intent(out) :: dlam real(sp), intent(in) :: rho ! Array Arguments real(sp), intent(in) :: d(2_${ik}$), z(2_${ik}$) real(sp), intent(out) :: delta(2_${ik}$) ! ===================================================================== ! Local Scalars real(sp) :: b, c, del, tau, temp, w ! Intrinsic Functions ! Executable Statements del = d( 2_${ik}$ ) - d( 1_${ik}$ ) if( i==1_${ik}$ ) then w = one + two*rho*( z( 2_${ik}$ )*z( 2_${ik}$ )-z( 1_${ik}$ )*z( 1_${ik}$ ) ) / del if( w>zero ) then b = del + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 1_${ik}$ )*z( 1_${ik}$ )*del ! b > zero, always tau = two*c / ( b+sqrt( abs( b*b-four*c ) ) ) dlam = d( 1_${ik}$ ) + tau delta( 1_${ik}$ ) = -z( 1_${ik}$ ) / tau delta( 2_${ik}$ ) = z( 2_${ik}$ ) / ( del-tau ) else b = -del + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*del if( b>zero ) then tau = -two*c / ( b+sqrt( b*b+four*c ) ) else tau = ( b-sqrt( b*b+four*c ) ) / two end if dlam = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -z( 1_${ik}$ ) / ( del+tau ) delta( 2_${ik}$ ) = -z( 2_${ik}$ ) / tau end if temp = sqrt( delta( 1_${ik}$ )*delta( 1_${ik}$ )+delta( 2_${ik}$ )*delta( 2_${ik}$ ) ) delta( 1_${ik}$ ) = delta( 1_${ik}$ ) / temp delta( 2_${ik}$ ) = delta( 2_${ik}$ ) / temp else ! now i=2 b = -del + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*del if( b>zero ) then tau = ( b+sqrt( b*b+four*c ) ) / two else tau = two*c / ( -b+sqrt( b*b+four*c ) ) end if dlam = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -z( 1_${ik}$ ) / ( del+tau ) delta( 2_${ik}$ ) = -z( 2_${ik}$ ) / tau temp = sqrt( delta( 1_${ik}$ )*delta( 1_${ik}$ )+delta( 2_${ik}$ )*delta( 2_${ik}$ ) ) delta( 1_${ik}$ ) = delta( 1_${ik}$ ) / temp delta( 2_${ik}$ ) = delta( 2_${ik}$ ) / temp end if return end subroutine stdlib${ii}$_slaed5 pure module subroutine stdlib${ii}$_dlaed5( i, d, z, delta, rho, dlam ) !! This subroutine computes the I-th eigenvalue of a symmetric rank-one !! modification of a 2-by-2 diagonal matrix !! diag( D ) + RHO * Z * transpose(Z) . !! The diagonal elements in the array D are assumed to satisfy !! D(i) < D(j) for i < j . !! We also assume RHO > 0 and that the Euclidean norm of the vector !! Z is one. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i real(dp), intent(out) :: dlam real(dp), intent(in) :: rho ! Array Arguments real(dp), intent(in) :: d(2_${ik}$), z(2_${ik}$) real(dp), intent(out) :: delta(2_${ik}$) ! ===================================================================== ! Local Scalars real(dp) :: b, c, del, tau, temp, w ! Intrinsic Functions ! Executable Statements del = d( 2_${ik}$ ) - d( 1_${ik}$ ) if( i==1_${ik}$ ) then w = one + two*rho*( z( 2_${ik}$ )*z( 2_${ik}$ )-z( 1_${ik}$ )*z( 1_${ik}$ ) ) / del if( w>zero ) then b = del + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 1_${ik}$ )*z( 1_${ik}$ )*del ! b > zero, always tau = two*c / ( b+sqrt( abs( b*b-four*c ) ) ) dlam = d( 1_${ik}$ ) + tau delta( 1_${ik}$ ) = -z( 1_${ik}$ ) / tau delta( 2_${ik}$ ) = z( 2_${ik}$ ) / ( del-tau ) else b = -del + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*del if( b>zero ) then tau = -two*c / ( b+sqrt( b*b+four*c ) ) else tau = ( b-sqrt( b*b+four*c ) ) / two end if dlam = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -z( 1_${ik}$ ) / ( del+tau ) delta( 2_${ik}$ ) = -z( 2_${ik}$ ) / tau end if temp = sqrt( delta( 1_${ik}$ )*delta( 1_${ik}$ )+delta( 2_${ik}$ )*delta( 2_${ik}$ ) ) delta( 1_${ik}$ ) = delta( 1_${ik}$ ) / temp delta( 2_${ik}$ ) = delta( 2_${ik}$ ) / temp else ! now i=2 b = -del + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*del if( b>zero ) then tau = ( b+sqrt( b*b+four*c ) ) / two else tau = two*c / ( -b+sqrt( b*b+four*c ) ) end if dlam = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -z( 1_${ik}$ ) / ( del+tau ) delta( 2_${ik}$ ) = -z( 2_${ik}$ ) / tau temp = sqrt( delta( 1_${ik}$ )*delta( 1_${ik}$ )+delta( 2_${ik}$ )*delta( 2_${ik}$ ) ) delta( 1_${ik}$ ) = delta( 1_${ik}$ ) / temp delta( 2_${ik}$ ) = delta( 2_${ik}$ ) / temp end if return end subroutine stdlib${ii}$_dlaed5 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laed5( i, d, z, delta, rho, dlam ) !! This subroutine computes the I-th eigenvalue of a symmetric rank-one !! modification of a 2-by-2 diagonal matrix !! diag( D ) + RHO * Z * transpose(Z) . !! The diagonal elements in the array D are assumed to satisfy !! D(i) < D(j) for i < j . !! We also assume RHO > 0 and that the Euclidean norm of the vector !! Z is one. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i real(${rk}$), intent(out) :: dlam real(${rk}$), intent(in) :: rho ! Array Arguments real(${rk}$), intent(in) :: d(2_${ik}$), z(2_${ik}$) real(${rk}$), intent(out) :: delta(2_${ik}$) ! ===================================================================== ! Local Scalars real(${rk}$) :: b, c, del, tau, temp, w ! Intrinsic Functions ! Executable Statements del = d( 2_${ik}$ ) - d( 1_${ik}$ ) if( i==1_${ik}$ ) then w = one + two*rho*( z( 2_${ik}$ )*z( 2_${ik}$ )-z( 1_${ik}$ )*z( 1_${ik}$ ) ) / del if( w>zero ) then b = del + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 1_${ik}$ )*z( 1_${ik}$ )*del ! b > zero, always tau = two*c / ( b+sqrt( abs( b*b-four*c ) ) ) dlam = d( 1_${ik}$ ) + tau delta( 1_${ik}$ ) = -z( 1_${ik}$ ) / tau delta( 2_${ik}$ ) = z( 2_${ik}$ ) / ( del-tau ) else b = -del + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*del if( b>zero ) then tau = -two*c / ( b+sqrt( b*b+four*c ) ) else tau = ( b-sqrt( b*b+four*c ) ) / two end if dlam = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -z( 1_${ik}$ ) / ( del+tau ) delta( 2_${ik}$ ) = -z( 2_${ik}$ ) / tau end if temp = sqrt( delta( 1_${ik}$ )*delta( 1_${ik}$ )+delta( 2_${ik}$ )*delta( 2_${ik}$ ) ) delta( 1_${ik}$ ) = delta( 1_${ik}$ ) / temp delta( 2_${ik}$ ) = delta( 2_${ik}$ ) / temp else ! now i=2 b = -del + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*del if( b>zero ) then tau = ( b+sqrt( b*b+four*c ) ) / two else tau = two*c / ( -b+sqrt( b*b+four*c ) ) end if dlam = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -z( 1_${ik}$ ) / ( del+tau ) delta( 2_${ik}$ ) = -z( 2_${ik}$ ) / tau temp = sqrt( delta( 1_${ik}$ )*delta( 1_${ik}$ )+delta( 2_${ik}$ )*delta( 2_${ik}$ ) ) delta( 1_${ik}$ ) = delta( 1_${ik}$ ) / temp delta( 2_${ik}$ ) = delta( 2_${ik}$ ) / temp end if return end subroutine stdlib${ii}$_${ri}$laed5 #:endif #:endfor pure module subroutine stdlib${ii}$_slaed6( kniter, orgati, rho, d, z, finit, tau, info ) !! SLAED6 computes the positive or negative root (closest to the origin) !! of !! z(1) z(2) z(3) !! f(x) = rho + --------- + ---------- + --------- !! d(1)-x d(2)-x d(3)-x !! It is assumed that !! if ORGATI = .true. the root is between d(2) and d(3); !! otherwise it is between d(1) and d(2) !! This routine will be called by SLAED4 when necessary. In most cases, !! the root sought is the smallest in magnitude, though it might not be !! in some extremely rare situations. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: orgati integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kniter real(sp), intent(in) :: finit, rho real(sp), intent(out) :: tau ! Array Arguments real(sp), intent(in) :: d(3_${ik}$), z(3_${ik}$) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 40_${ik}$ ! Local Arrays real(sp) :: dscale(3_${ik}$), zscale(3_${ik}$) ! Local Scalars logical(lk) :: scale integer(${ik}$) :: i, iter, niter real(sp) :: a, b, base, c, ddf, df, eps, erretm, eta, f, fc, sclfac, sclinv, small1, & small2, sminv1, sminv2, temp, temp1, temp2, temp3, temp4, lbd, ubd ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( orgati ) then lbd = d(2_${ik}$) ubd = d(3_${ik}$) else lbd = d(1_${ik}$) ubd = d(2_${ik}$) end if if( finit < zero )then lbd = zero else ubd = zero end if niter = 1_${ik}$ tau = zero if( kniter==2_${ik}$ ) then if( orgati ) then temp = ( d( 3_${ik}$ )-d( 2_${ik}$ ) ) / two c = rho + z( 1_${ik}$ ) / ( ( d( 1_${ik}$ )-d( 2_${ik}$ ) )-temp ) a = c*( d( 2_${ik}$ )+d( 3_${ik}$ ) ) + z( 2_${ik}$ ) + z( 3_${ik}$ ) b = c*d( 2_${ik}$ )*d( 3_${ik}$ ) + z( 2_${ik}$ )*d( 3_${ik}$ ) + z( 3_${ik}$ )*d( 2_${ik}$ ) else temp = ( d( 1_${ik}$ )-d( 2_${ik}$ ) ) / two c = rho + z( 3_${ik}$ ) / ( ( d( 3_${ik}$ )-d( 2_${ik}$ ) )-temp ) a = c*( d( 1_${ik}$ )+d( 2_${ik}$ ) ) + z( 1_${ik}$ ) + z( 2_${ik}$ ) b = c*d( 1_${ik}$ )*d( 2_${ik}$ ) + z( 1_${ik}$ )*d( 2_${ik}$ ) + z( 2_${ik}$ )*d( 1_${ik}$ ) end if temp = max( abs( a ), abs( b ), abs( c ) ) a = a / temp b = b / temp c = c / temp if( c==zero ) then tau = b / a else if( a<=zero ) then tau = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else tau = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if if( tau < lbd .or. tau > ubd )tau = ( lbd+ubd )/two if( d(1_${ik}$)==tau .or. d(2_${ik}$)==tau .or. d(3_${ik}$)==tau ) then tau = zero else temp = finit + tau*z(1_${ik}$)/( d(1_${ik}$)*( d( 1_${ik}$ )-tau ) ) +tau*z(2_${ik}$)/( d(2_${ik}$)*( d( 2_${ik}$ )-tau ) )& +tau*z(3_${ik}$)/( d(3_${ik}$)*( d( 3_${ik}$ )-tau ) ) if( temp <= zero )then lbd = tau else ubd = tau end if if( abs( finit )<=abs( temp ) )tau = zero end if end if ! get machine parameters for possible scaling to avoid overflow ! modified by sven: parameters small1, sminv1, small2, ! sminv2, eps are not saved anymore between one call to the ! others but recomputed at each call eps = stdlib${ii}$_slamch( 'EPSILON' ) base = stdlib${ii}$_slamch( 'BASE' ) small1 = base**( int( log( stdlib${ii}$_slamch( 'SAFMIN' ) ) / log( base ) /three,KIND=${ik}$) ) sminv1 = one / small1 small2 = small1*small1 sminv2 = sminv1*sminv1 ! determine if scaling of inputs necessary to avoid overflow ! when computing 1/temp**3 if( orgati ) then temp = min( abs( d( 2_${ik}$ )-tau ), abs( d( 3_${ik}$ )-tau ) ) else temp = min( abs( d( 1_${ik}$ )-tau ), abs( d( 2_${ik}$ )-tau ) ) end if scale = .false. if( temp<=small1 ) then scale = .true. if( temp<=small2 ) then ! scale up by power of radix nearest 1/safmin**(2/3) sclfac = sminv2 sclinv = small2 else ! scale up by power of radix nearest 1/safmin**(1/3) sclfac = sminv1 sclinv = small1 end if ! scaling up safe because d, z, tau scaled elsewhere to be o(1) do i = 1, 3 dscale( i ) = d( i )*sclfac zscale( i ) = z( i )*sclfac end do tau = tau*sclfac lbd = lbd*sclfac ubd = ubd*sclfac else ! copy d and z to dscale and zscale do i = 1, 3 dscale( i ) = d( i ) zscale( i ) = z( i ) end do end if fc = zero df = zero ddf = zero do i = 1, 3 temp = one / ( dscale( i )-tau ) temp1 = zscale( i )*temp temp2 = temp1*temp temp3 = temp2*temp fc = fc + temp1 / dscale( i ) df = df + temp2 ddf = ddf + temp3 end do f = finit + tau*fc if( abs( f )<=zero )go to 60 if( f <= zero )then lbd = tau else ubd = tau end if ! iteration begins -- use gragg-thornton-warner cubic convergent ! scheme ! it is not hard to see that ! 1) iterations will go up monotonically ! if finit < 0; ! 2) iterations will go down monotonically ! if finit > 0. iter = niter + 1_${ik}$ loop_50: do niter = iter, maxit if( orgati ) then temp1 = dscale( 2_${ik}$ ) - tau temp2 = dscale( 3_${ik}$ ) - tau else temp1 = dscale( 1_${ik}$ ) - tau temp2 = dscale( 2_${ik}$ ) - tau end if a = ( temp1+temp2 )*f - temp1*temp2*df b = temp1*temp2*f c = f - ( temp1+temp2 )*df + temp1*temp2*ddf temp = max( abs( a ), abs( b ), abs( c ) ) a = a / temp b = b / temp c = c / temp if( c==zero ) then eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if if( f*eta>=zero ) then eta = -f / df end if tau = tau + eta if( tau < lbd .or. tau > ubd )tau = ( lbd + ubd )/two fc = zero erretm = zero df = zero ddf = zero do i = 1, 3 if ( ( dscale( i )-tau )/=zero ) then temp = one / ( dscale( i )-tau ) temp1 = zscale( i )*temp temp2 = temp1*temp temp3 = temp2*temp temp4 = temp1 / dscale( i ) fc = fc + temp4 erretm = erretm + abs( temp4 ) df = df + temp2 ddf = ddf + temp3 else go to 60 end if end do f = finit + tau*fc erretm = eight*( abs( finit )+abs( tau )*erretm ) +abs( tau )*df if( ( abs( f )<=four*eps*erretm ) .or.( (ubd-lbd)<=four*eps*abs(tau) ) )go to 60 if( f <= zero )then lbd = tau else ubd = tau end if end do loop_50 info = 1_${ik}$ 60 continue ! undo scaling if( scale )tau = tau*sclinv return end subroutine stdlib${ii}$_slaed6 pure module subroutine stdlib${ii}$_dlaed6( kniter, orgati, rho, d, z, finit, tau, info ) !! DLAED6 computes the positive or negative root (closest to the origin) !! of !! z(1) z(2) z(3) !! f(x) = rho + --------- + ---------- + --------- !! d(1)-x d(2)-x d(3)-x !! It is assumed that !! if ORGATI = .true. the root is between d(2) and d(3); !! otherwise it is between d(1) and d(2) !! This routine will be called by DLAED4 when necessary. In most cases, !! the root sought is the smallest in magnitude, though it might not be !! in some extremely rare situations. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: orgati integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kniter real(dp), intent(in) :: finit, rho real(dp), intent(out) :: tau ! Array Arguments real(dp), intent(in) :: d(3_${ik}$), z(3_${ik}$) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 40_${ik}$ ! Local Arrays real(dp) :: dscale(3_${ik}$), zscale(3_${ik}$) ! Local Scalars logical(lk) :: scale integer(${ik}$) :: i, iter, niter real(dp) :: a, b, base, c, ddf, df, eps, erretm, eta, f, fc, sclfac, sclinv, small1, & small2, sminv1, sminv2, temp, temp1, temp2, temp3, temp4, lbd, ubd ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( orgati ) then lbd = d(2_${ik}$) ubd = d(3_${ik}$) else lbd = d(1_${ik}$) ubd = d(2_${ik}$) end if if( finit < zero )then lbd = zero else ubd = zero end if niter = 1_${ik}$ tau = zero if( kniter==2_${ik}$ ) then if( orgati ) then temp = ( d( 3_${ik}$ )-d( 2_${ik}$ ) ) / two c = rho + z( 1_${ik}$ ) / ( ( d( 1_${ik}$ )-d( 2_${ik}$ ) )-temp ) a = c*( d( 2_${ik}$ )+d( 3_${ik}$ ) ) + z( 2_${ik}$ ) + z( 3_${ik}$ ) b = c*d( 2_${ik}$ )*d( 3_${ik}$ ) + z( 2_${ik}$ )*d( 3_${ik}$ ) + z( 3_${ik}$ )*d( 2_${ik}$ ) else temp = ( d( 1_${ik}$ )-d( 2_${ik}$ ) ) / two c = rho + z( 3_${ik}$ ) / ( ( d( 3_${ik}$ )-d( 2_${ik}$ ) )-temp ) a = c*( d( 1_${ik}$ )+d( 2_${ik}$ ) ) + z( 1_${ik}$ ) + z( 2_${ik}$ ) b = c*d( 1_${ik}$ )*d( 2_${ik}$ ) + z( 1_${ik}$ )*d( 2_${ik}$ ) + z( 2_${ik}$ )*d( 1_${ik}$ ) end if temp = max( abs( a ), abs( b ), abs( c ) ) a = a / temp b = b / temp c = c / temp if( c==zero ) then tau = b / a else if( a<=zero ) then tau = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else tau = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if if( tau < lbd .or. tau > ubd )tau = ( lbd+ubd )/two if( d(1_${ik}$)==tau .or. d(2_${ik}$)==tau .or. d(3_${ik}$)==tau ) then tau = zero else temp = finit + tau*z(1_${ik}$)/( d(1_${ik}$)*( d( 1_${ik}$ )-tau ) ) +tau*z(2_${ik}$)/( d(2_${ik}$)*( d( 2_${ik}$ )-tau ) )& +tau*z(3_${ik}$)/( d(3_${ik}$)*( d( 3_${ik}$ )-tau ) ) if( temp <= zero )then lbd = tau else ubd = tau end if if( abs( finit )<=abs( temp ) )tau = zero end if end if ! get machine parameters for possible scaling to avoid overflow ! modified by sven: parameters small1, sminv1, small2, ! sminv2, eps are not saved anymore between one call to the ! others but recomputed at each call eps = stdlib${ii}$_dlamch( 'EPSILON' ) base = stdlib${ii}$_dlamch( 'BASE' ) small1 = base**( int( log( stdlib${ii}$_dlamch( 'SAFMIN' ) ) / log( base ) /three,KIND=${ik}$) ) sminv1 = one / small1 small2 = small1*small1 sminv2 = sminv1*sminv1 ! determine if scaling of inputs necessary to avoid overflow ! when computing 1/temp**3 if( orgati ) then temp = min( abs( d( 2_${ik}$ )-tau ), abs( d( 3_${ik}$ )-tau ) ) else temp = min( abs( d( 1_${ik}$ )-tau ), abs( d( 2_${ik}$ )-tau ) ) end if scale = .false. if( temp<=small1 ) then scale = .true. if( temp<=small2 ) then ! scale up by power of radix nearest 1/safmin**(2/3) sclfac = sminv2 sclinv = small2 else ! scale up by power of radix nearest 1/safmin**(1/3) sclfac = sminv1 sclinv = small1 end if ! scaling up safe because d, z, tau scaled elsewhere to be o(1) do i = 1, 3 dscale( i ) = d( i )*sclfac zscale( i ) = z( i )*sclfac end do tau = tau*sclfac lbd = lbd*sclfac ubd = ubd*sclfac else ! copy d and z to dscale and zscale do i = 1, 3 dscale( i ) = d( i ) zscale( i ) = z( i ) end do end if fc = zero df = zero ddf = zero do i = 1, 3 temp = one / ( dscale( i )-tau ) temp1 = zscale( i )*temp temp2 = temp1*temp temp3 = temp2*temp fc = fc + temp1 / dscale( i ) df = df + temp2 ddf = ddf + temp3 end do f = finit + tau*fc if( abs( f )<=zero )go to 60 if( f <= zero )then lbd = tau else ubd = tau end if ! iteration begins -- use gragg-thornton-warner cubic convergent ! scheme ! it is not hard to see that ! 1) iterations will go up monotonically ! if finit < 0; ! 2) iterations will go down monotonically ! if finit > 0. iter = niter + 1_${ik}$ loop_50: do niter = iter, maxit if( orgati ) then temp1 = dscale( 2_${ik}$ ) - tau temp2 = dscale( 3_${ik}$ ) - tau else temp1 = dscale( 1_${ik}$ ) - tau temp2 = dscale( 2_${ik}$ ) - tau end if a = ( temp1+temp2 )*f - temp1*temp2*df b = temp1*temp2*f c = f - ( temp1+temp2 )*df + temp1*temp2*ddf temp = max( abs( a ), abs( b ), abs( c ) ) a = a / temp b = b / temp c = c / temp if( c==zero ) then eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if if( f*eta>=zero ) then eta = -f / df end if tau = tau + eta if( tau < lbd .or. tau > ubd )tau = ( lbd + ubd )/two fc = zero erretm = zero df = zero ddf = zero do i = 1, 3 if ( ( dscale( i )-tau )/=zero ) then temp = one / ( dscale( i )-tau ) temp1 = zscale( i )*temp temp2 = temp1*temp temp3 = temp2*temp temp4 = temp1 / dscale( i ) fc = fc + temp4 erretm = erretm + abs( temp4 ) df = df + temp2 ddf = ddf + temp3 else go to 60 end if end do f = finit + tau*fc erretm = eight*( abs( finit )+abs( tau )*erretm ) +abs( tau )*df if( ( abs( f )<=four*eps*erretm ) .or.( (ubd-lbd)<=four*eps*abs(tau) ) ) go to 60 if( f <= zero )then lbd = tau else ubd = tau end if end do loop_50 info = 1_${ik}$ 60 continue ! undo scaling if( scale )tau = tau*sclinv return end subroutine stdlib${ii}$_dlaed6 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laed6( kniter, orgati, rho, d, z, finit, tau, info ) !! DLAED6: computes the positive or negative root (closest to the origin) !! of !! z(1) z(2) z(3) !! f(x) = rho + --------- + ---------- + --------- !! d(1)-x d(2)-x d(3)-x !! It is assumed that !! if ORGATI = .true. the root is between d(2) and d(3); !! otherwise it is between d(1) and d(2) !! This routine will be called by DLAED4 when necessary. In most cases, !! the root sought is the smallest in magnitude, though it might not be !! in some extremely rare situations. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: orgati integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kniter real(${rk}$), intent(in) :: finit, rho real(${rk}$), intent(out) :: tau ! Array Arguments real(${rk}$), intent(in) :: d(3_${ik}$), z(3_${ik}$) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 40_${ik}$ ! Local Arrays real(${rk}$) :: dscale(3_${ik}$), zscale(3_${ik}$) ! Local Scalars logical(lk) :: scale integer(${ik}$) :: i, iter, niter real(${rk}$) :: a, b, base, c, ddf, df, eps, erretm, eta, f, fc, sclfac, sclinv, small1, & small2, sminv1, sminv2, temp, temp1, temp2, temp3, temp4, lbd, ubd ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( orgati ) then lbd = d(2_${ik}$) ubd = d(3_${ik}$) else lbd = d(1_${ik}$) ubd = d(2_${ik}$) end if if( finit < zero )then lbd = zero else ubd = zero end if niter = 1_${ik}$ tau = zero if( kniter==2_${ik}$ ) then if( orgati ) then temp = ( d( 3_${ik}$ )-d( 2_${ik}$ ) ) / two c = rho + z( 1_${ik}$ ) / ( ( d( 1_${ik}$ )-d( 2_${ik}$ ) )-temp ) a = c*( d( 2_${ik}$ )+d( 3_${ik}$ ) ) + z( 2_${ik}$ ) + z( 3_${ik}$ ) b = c*d( 2_${ik}$ )*d( 3_${ik}$ ) + z( 2_${ik}$ )*d( 3_${ik}$ ) + z( 3_${ik}$ )*d( 2_${ik}$ ) else temp = ( d( 1_${ik}$ )-d( 2_${ik}$ ) ) / two c = rho + z( 3_${ik}$ ) / ( ( d( 3_${ik}$ )-d( 2_${ik}$ ) )-temp ) a = c*( d( 1_${ik}$ )+d( 2_${ik}$ ) ) + z( 1_${ik}$ ) + z( 2_${ik}$ ) b = c*d( 1_${ik}$ )*d( 2_${ik}$ ) + z( 1_${ik}$ )*d( 2_${ik}$ ) + z( 2_${ik}$ )*d( 1_${ik}$ ) end if temp = max( abs( a ), abs( b ), abs( c ) ) a = a / temp b = b / temp c = c / temp if( c==zero ) then tau = b / a else if( a<=zero ) then tau = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else tau = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if if( tau < lbd .or. tau > ubd )tau = ( lbd+ubd )/two if( d(1_${ik}$)==tau .or. d(2_${ik}$)==tau .or. d(3_${ik}$)==tau ) then tau = zero else temp = finit + tau*z(1_${ik}$)/( d(1_${ik}$)*( d( 1_${ik}$ )-tau ) ) +tau*z(2_${ik}$)/( d(2_${ik}$)*( d( 2_${ik}$ )-tau ) )& +tau*z(3_${ik}$)/( d(3_${ik}$)*( d( 3_${ik}$ )-tau ) ) if( temp <= zero )then lbd = tau else ubd = tau end if if( abs( finit )<=abs( temp ) )tau = zero end if end if ! get machine parameters for possible scaling to avoid overflow ! modified by sven: parameters small1, sminv1, small2, ! sminv2, eps are not saved anymore between one call to the ! others but recomputed at each call eps = stdlib${ii}$_${ri}$lamch( 'EPSILON' ) base = stdlib${ii}$_${ri}$lamch( 'BASE' ) small1 = base**( int( log( stdlib${ii}$_${ri}$lamch( 'SAFMIN' ) ) / log( base ) /three,KIND=${ik}$) ) sminv1 = one / small1 small2 = small1*small1 sminv2 = sminv1*sminv1 ! determine if scaling of inputs necessary to avoid overflow ! when computing 1/temp**3 if( orgati ) then temp = min( abs( d( 2_${ik}$ )-tau ), abs( d( 3_${ik}$ )-tau ) ) else temp = min( abs( d( 1_${ik}$ )-tau ), abs( d( 2_${ik}$ )-tau ) ) end if scale = .false. if( temp<=small1 ) then scale = .true. if( temp<=small2 ) then ! scale up by power of radix nearest 1/safmin**(2/3) sclfac = sminv2 sclinv = small2 else ! scale up by power of radix nearest 1/safmin**(1/3) sclfac = sminv1 sclinv = small1 end if ! scaling up safe because d, z, tau scaled elsewhere to be o(1) do i = 1, 3 dscale( i ) = d( i )*sclfac zscale( i ) = z( i )*sclfac end do tau = tau*sclfac lbd = lbd*sclfac ubd = ubd*sclfac else ! copy d and z to dscale and zscale do i = 1, 3 dscale( i ) = d( i ) zscale( i ) = z( i ) end do end if fc = zero df = zero ddf = zero do i = 1, 3 temp = one / ( dscale( i )-tau ) temp1 = zscale( i )*temp temp2 = temp1*temp temp3 = temp2*temp fc = fc + temp1 / dscale( i ) df = df + temp2 ddf = ddf + temp3 end do f = finit + tau*fc if( abs( f )<=zero )go to 60 if( f <= zero )then lbd = tau else ubd = tau end if ! iteration begins -- use gragg-thornton-warner cubic convergent ! scheme ! it is not hard to see that ! 1) iterations will go up monotonically ! if finit < 0; ! 2) iterations will go down monotonically ! if finit > 0. iter = niter + 1_${ik}$ loop_50: do niter = iter, maxit if( orgati ) then temp1 = dscale( 2_${ik}$ ) - tau temp2 = dscale( 3_${ik}$ ) - tau else temp1 = dscale( 1_${ik}$ ) - tau temp2 = dscale( 2_${ik}$ ) - tau end if a = ( temp1+temp2 )*f - temp1*temp2*df b = temp1*temp2*f c = f - ( temp1+temp2 )*df + temp1*temp2*ddf temp = max( abs( a ), abs( b ), abs( c ) ) a = a / temp b = b / temp c = c / temp if( c==zero ) then eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if if( f*eta>=zero ) then eta = -f / df end if tau = tau + eta if( tau < lbd .or. tau > ubd )tau = ( lbd + ubd )/two fc = zero erretm = zero df = zero ddf = zero do i = 1, 3 if ( ( dscale( i )-tau )/=zero ) then temp = one / ( dscale( i )-tau ) temp1 = zscale( i )*temp temp2 = temp1*temp temp3 = temp2*temp temp4 = temp1 / dscale( i ) fc = fc + temp4 erretm = erretm + abs( temp4 ) df = df + temp2 ddf = ddf + temp3 else go to 60 end if end do f = finit + tau*fc erretm = eight*( abs( finit )+abs( tau )*erretm ) +abs( tau )*df if( ( abs( f )<=four*eps*erretm ) .or.( (ubd-lbd)<=four*eps*abs(tau) ) ) goto 60 if( f <= zero )then lbd = tau else ubd = tau end if end do loop_50 info = 1_${ik}$ 60 continue ! undo scaling if( scale )tau = tau*sclinv return end subroutine stdlib${ii}$_${ri}$laed6 #:endif #:endfor pure module subroutine stdlib${ii}$_slaed7( icompq, n, qsiz, tlvls, curlvl, curpbm, d, q,ldq, indxq, rho, & !! SLAED7 computes the updated eigensystem of a diagonal !! matrix after modification by a rank-one symmetric matrix. This !! routine is used only for the eigenproblem which requires all !! eigenvalues and optionally eigenvectors of a dense symmetric matrix !! that has been reduced to tridiagonal form. SLAED1 handles !! the case in which all eigenvalues and eigenvectors of a symmetric !! tridiagonal matrix are desired. !! T = Q(in) ( D(in) + RHO * Z*Z**T ) Q**T(in) = Q(out) * D(out) * Q**T(out) !! where Z = Q**Tu, u is a vector of length N with ones in the !! CUTPNT and CUTPNT + 1 th elements and zeros elsewhere. !! The eigenvectors of the original matrix are stored in Q, and the !! eigenvalues are in D. The algorithm consists of three stages: !! The first stage consists of deflating the size of the problem !! when there are multiple eigenvalues or if there is a zero in !! the Z vector. For each such occurrence the dimension of the !! secular equation problem is reduced by one. This stage is !! performed by the routine SLAED8. !! The second stage consists of calculating the updated !! eigenvalues. This is done by finding the roots of the secular !! equation via the routine SLAED4 (as called by SLAED9). !! This routine also calculates the eigenvectors of the current !! problem. !! The final stage consists of computing the updated eigenvectors !! directly using the updated eigenvalues. The eigenvectors for !! the current problem are multiplied with the eigenvectors from !! the overall problem. cutpnt, qstore, qptr, prmptr,perm, givptr, givcol, givnum, work, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: curlvl, curpbm, cutpnt, icompq, ldq, n, qsiz, tlvls integer(${ik}$), intent(out) :: info real(sp), intent(inout) :: rho ! Array Arguments integer(${ik}$), intent(inout) :: givcol(2_${ik}$,*), givptr(*), perm(*), prmptr(*), qptr(*) integer(${ik}$), intent(out) :: indxq(*), iwork(*) real(sp), intent(inout) :: d(*), givnum(2_${ik}$,*), q(ldq,*), qstore(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: coltyp, curr, i, idlmda, indx, indxc, indxp, iq2, is, iw, iz, k, ldq2, & n1, n2, ptr ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( icompq<0_${ik}$ .or. icompq>1_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( icompq==1_${ik}$ .and. qsizcutpnt .or. n1_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( icompq==1_${ik}$ .and. qsizcutpnt .or. n1_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( icompq==1_${ik}$ .and. qsizcutpnt .or. n1 ) then ! info = -1 ! else if( n<0 ) then if( n<0_${ik}$ ) then info = -1_${ik}$ else if( min( 1_${ik}$, n )>cutpnt .or. n1 ) then ! info = -1 ! else if( n<0 ) then if( n<0_${ik}$ ) then info = -1_${ik}$ else if( min( 1_${ik}$, n )>cutpnt .or. n1 ) then ! info = -1 ! else if( n<0 ) then if( n<0_${ik}$ ) then info = -1_${ik}$ else if( min( 1_${ik}$, n )>cutpnt .or. n1_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( icompq==1_${ik}$ .and. qsizn ) then info = -10_${ik}$ else if( ldq2n )go to 100 if( rho*abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ indxp( k2 ) = j else ! check if eigenvalues are close enough to allow deflation. s = z( jlam ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_slapy2( c, s ) t = d( j ) - d( jlam ) c = c / tau s = -s / tau if( abs( t*c*s )<=tol ) then ! deflation is possible. z( j ) = tau z( jlam ) = zero ! record the appropriate givens rotation givptr = givptr + 1_${ik}$ givcol( 1_${ik}$, givptr ) = indxq( indx( jlam ) ) givcol( 2_${ik}$, givptr ) = indxq( indx( j ) ) givnum( 1_${ik}$, givptr ) = c givnum( 2_${ik}$, givptr ) = s if( icompq==1_${ik}$ ) then call stdlib${ii}$_srot( qsiz, q( 1_${ik}$, indxq( indx( jlam ) ) ), 1_${ik}$,q( 1_${ik}$, indxq( indx( j & ) ) ), 1_${ik}$, c, s ) end if t = d( jlam )*c*c + d( j )*s*s d( j ) = d( jlam )*s*s + d( j )*c*c d( jlam ) = t k2 = k2 - 1_${ik}$ i = 1_${ik}$ 90 continue if( k2+i<=n ) then if( d( jlam )1_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( icompq==1_${ik}$ .and. qsizn ) then info = -10_${ik}$ else if( ldq2n )go to 100 if( rho*abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ indxp( k2 ) = j else ! check if eigenvalues are close enough to allow deflation. s = z( jlam ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_dlapy2( c, s ) t = d( j ) - d( jlam ) c = c / tau s = -s / tau if( abs( t*c*s )<=tol ) then ! deflation is possible. z( j ) = tau z( jlam ) = zero ! record the appropriate givens rotation givptr = givptr + 1_${ik}$ givcol( 1_${ik}$, givptr ) = indxq( indx( jlam ) ) givcol( 2_${ik}$, givptr ) = indxq( indx( j ) ) givnum( 1_${ik}$, givptr ) = c givnum( 2_${ik}$, givptr ) = s if( icompq==1_${ik}$ ) then call stdlib${ii}$_drot( qsiz, q( 1_${ik}$, indxq( indx( jlam ) ) ), 1_${ik}$,q( 1_${ik}$, indxq( indx( j & ) ) ), 1_${ik}$, c, s ) end if t = d( jlam )*c*c + d( j )*s*s d( j ) = d( jlam )*s*s + d( j )*c*c d( jlam ) = t k2 = k2 - 1_${ik}$ i = 1_${ik}$ 90 continue if( k2+i<=n ) then if( d( jlam )1_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( icompq==1_${ik}$ .and. qsizn ) then info = -10_${ik}$ else if( ldq2n )go to 100 if( rho*abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ indxp( k2 ) = j else ! check if eigenvalues are close enough to allow deflation. s = z( jlam ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_${ri}$lapy2( c, s ) t = d( j ) - d( jlam ) c = c / tau s = -s / tau if( abs( t*c*s )<=tol ) then ! deflation is possible. z( j ) = tau z( jlam ) = zero ! record the appropriate givens rotation givptr = givptr + 1_${ik}$ givcol( 1_${ik}$, givptr ) = indxq( indx( jlam ) ) givcol( 2_${ik}$, givptr ) = indxq( indx( j ) ) givnum( 1_${ik}$, givptr ) = c givnum( 2_${ik}$, givptr ) = s if( icompq==1_${ik}$ ) then call stdlib${ii}$_${ri}$rot( qsiz, q( 1_${ik}$, indxq( indx( jlam ) ) ), 1_${ik}$,q( 1_${ik}$, indxq( indx( j & ) ) ), 1_${ik}$, c, s ) end if t = d( jlam )*c*c + d( j )*s*s d( j ) = d( jlam )*s*s + d( j )*c*c d( jlam ) = t k2 = k2 - 1_${ik}$ i = 1_${ik}$ 90 continue if( k2+i<=n ) then if( d( jlam )n ) then info = -8_${ik}$ else if( ldq2n )go to 90 if( rho*abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ indxp( k2 ) = j else ! check if eigenvalues are close enough to allow deflation. s = z( jlam ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_slapy2( c, s ) t = d( j ) - d( jlam ) c = c / tau s = -s / tau if( abs( t*c*s )<=tol ) then ! deflation is possible. z( j ) = tau z( jlam ) = zero ! record the appropriate givens rotation givptr = givptr + 1_${ik}$ givcol( 1_${ik}$, givptr ) = indxq( indx( jlam ) ) givcol( 2_${ik}$, givptr ) = indxq( indx( j ) ) givnum( 1_${ik}$, givptr ) = c givnum( 2_${ik}$, givptr ) = s call stdlib${ii}$_csrot( qsiz, q( 1_${ik}$, indxq( indx( jlam ) ) ), 1_${ik}$,q( 1_${ik}$, indxq( indx( j ) & ) ), 1_${ik}$, c, s ) t = d( jlam )*c*c + d( j )*s*s d( j ) = d( jlam )*s*s + d( j )*c*c d( jlam ) = t k2 = k2 - 1_${ik}$ i = 1_${ik}$ 80 continue if( k2+i<=n ) then if( d( jlam )n ) then info = -8_${ik}$ else if( ldq2n )go to 90 if( rho*abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ indxp( k2 ) = j else ! check if eigenvalues are close enough to allow deflation. s = z( jlam ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_dlapy2( c, s ) t = d( j ) - d( jlam ) c = c / tau s = -s / tau if( abs( t*c*s )<=tol ) then ! deflation is possible. z( j ) = tau z( jlam ) = zero ! record the appropriate givens rotation givptr = givptr + 1_${ik}$ givcol( 1_${ik}$, givptr ) = indxq( indx( jlam ) ) givcol( 2_${ik}$, givptr ) = indxq( indx( j ) ) givnum( 1_${ik}$, givptr ) = c givnum( 2_${ik}$, givptr ) = s call stdlib${ii}$_zdrot( qsiz, q( 1_${ik}$, indxq( indx( jlam ) ) ), 1_${ik}$,q( 1_${ik}$, indxq( indx( j ) & ) ), 1_${ik}$, c, s ) t = d( jlam )*c*c + d( j )*s*s d( j ) = d( jlam )*s*s + d( j )*c*c d( jlam ) = t k2 = k2 - 1_${ik}$ i = 1_${ik}$ 80 continue if( k2+i<=n ) then if( d( jlam )n ) then info = -8_${ik}$ else if( ldq2n )go to 90 if( rho*abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ indxp( k2 ) = j else ! check if eigenvalues are close enough to allow deflation. s = z( jlam ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_${c2ri(ci)}$lapy2( c, s ) t = d( j ) - d( jlam ) c = c / tau s = -s / tau if( abs( t*c*s )<=tol ) then ! deflation is possible. z( j ) = tau z( jlam ) = zero ! record the appropriate givens rotation givptr = givptr + 1_${ik}$ givcol( 1_${ik}$, givptr ) = indxq( indx( jlam ) ) givcol( 2_${ik}$, givptr ) = indxq( indx( j ) ) givnum( 1_${ik}$, givptr ) = c givnum( 2_${ik}$, givptr ) = s call stdlib${ii}$_${ci}$drot( qsiz, q( 1_${ik}$, indxq( indx( jlam ) ) ), 1_${ik}$,q( 1_${ik}$, indxq( indx( j ) & ) ), 1_${ik}$, c, s ) t = d( jlam )*c*c + d( j )*s*s d( j ) = d( jlam )*s*s + d( j )*c*c d( jlam ) = t k2 = k2 - 1_${ik}$ i = 1_${ik}$ 80 continue if( k2+i<=n ) then if( d( jlam )max( 1_${ik}$, k ) ) then info = -2_${ik}$ else if( max( 1_${ik}$, kstop )max( 1_${ik}$, k ) )then info = -3_${ik}$ else if( nmax( 1_${ik}$, k ) ) then info = -2_${ik}$ else if( max( 1_${ik}$, kstop )max( 1_${ik}$, k ) )then info = -3_${ik}$ else if( nmax( 1_${ik}$, k ) ) then info = -2_${ik}$ else if( max( 1_${ik}$, kstop )max( 1_${ik}$, k ) )then info = -3_${ik}$ else if( n0_${ik}$ .and. ldvt0_${ik}$ .and. ldc0_${ik}$ ) .or. ( nru>0_${ik}$ ) .or. ( ncc>0_${ik}$ ) ! if no singular vectors desired, use qd algorithm if( .not.rotate ) then call stdlib${ii}$_slasq1( n, d, e, work, info ) ! if info equals 2, dqds didn't finish, try to finish if( info /= 2 ) return info = 0_${ik}$ end if nm1 = n - 1_${ik}$ nm12 = nm1 + nm1 nm13 = nm12 + nm1 idir = 0_${ik}$ ! get machine constants eps = stdlib${ii}$_slamch( 'EPSILON' ) unfl = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) ! if matrix lower bidiagonal, rotate to be upper bidiagonal ! by applying givens rotations on the left if( lower ) then do i = 1, n - 1 call stdlib${ii}$_slartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) work( i ) = cs work( nm1+i ) = sn end do ! update singular vectors if desired if( nru>0_${ik}$ )call stdlib${ii}$_slasr( 'R', 'V', 'F', nru, n, work( 1_${ik}$ ), work( n ), u,ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_slasr( 'L', 'V', 'F', n, ncc, work( 1_${ik}$ ), work( n ), c,ldc ) end if ! compute singular values to relative accuracy tol ! (by setting tol to be negative, algorithm will compute ! singular values to absolute accuracy abs(tol)*norm(input matrix)) tolmul = max( ten, min( hndrd, eps**meigth ) ) tol = tolmul*eps ! compute approximate maximum, minimum singular values smax = zero do i = 1, n smax = max( smax, abs( d( i ) ) ) end do do i = 1, n - 1 smax = max( smax, abs( e( i ) ) ) end do sminl = zero if( tol>=zero ) then ! relative accuracy desired sminoa = abs( d( 1_${ik}$ ) ) if( sminoa==zero )go to 50 mu = sminoa do i = 2, n mu = abs( d( i ) )*( mu / ( mu+abs( e( i-1 ) ) ) ) sminoa = min( sminoa, mu ) if( sminoa==zero )go to 50 end do 50 continue sminoa = sminoa / sqrt( real( n,KIND=sp) ) thresh = max( tol*sminoa, maxitr*(n*(n*unfl)) ) else ! absolute accuracy desired thresh = max( abs( tol )*smax, maxitr*(n*(n*unfl)) ) end if ! prepare for main iteration loop for the singular values ! (maxit is the maximum number of passes through the inner ! loop permitted before nonconvergence signalled.) maxitdivn = maxitr*n iterdivn = 0_${ik}$ iter = -1_${ik}$ oldll = -1_${ik}$ oldm = -1_${ik}$ ! m points to last element of unconverged part of matrix m = n ! begin main iteration loop 60 continue ! check for convergence or exceeding iteration count if( m<=1 )go to 160 if( iter>=n ) then iter = iter - n iterdivn = iterdivn + 1_${ik}$ if( iterdivn>=maxitdivn )go to 200 end if ! find diagonal block of matrix to work on if( tol0_${ik}$ )call stdlib${ii}$_srot( ncvt, vt( m-1, 1_${ik}$ ), ldvt, vt( m, 1_${ik}$ ), ldvt, cosr,sinr & ) if( nru>0_${ik}$ )call stdlib${ii}$_srot( nru, u( 1_${ik}$, m-1 ), 1_${ik}$, u( 1_${ik}$, m ), 1_${ik}$, cosl, sinl ) if( ncc>0_${ik}$ )call stdlib${ii}$_srot( ncc, c( m-1, 1_${ik}$ ), ldc, c( m, 1_${ik}$ ), ldc, cosl,sinl ) m = m - 2_${ik}$ go to 60 end if ! if working on new submatrix, choose shift direction ! (from larger end diagonal element towards smaller) if( ll>oldm .or. m=abs( d( m ) ) ) then ! chase bulge from top (big end) to bottom (small end) idir = 1_${ik}$ else ! chase bulge from bottom (big end) to top (small end) idir = 2_${ik}$ end if end if ! apply convergence tests if( idir==1_${ik}$ ) then ! run convergence test in forward direction ! first apply standard test to bottom of matrix if( abs( e( m-1 ) )<=abs( tol )*abs( d( m ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion forward mu = abs( d( ll ) ) sminl = mu do lll = ll, m - 1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll+1 ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if else ! run convergence test in backward direction ! first apply standard test to top of matrix if( abs( e( ll ) )<=abs( tol )*abs( d( ll ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion backward mu = abs( d( m ) ) sminl = mu do lll = m - 1, ll, -1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if end if oldll = ll oldm = m ! compute shift. first, test if shifting would ruin relative ! accuracy, and if so set the shift to zero. if( tol>=zero .and. n*tol*( sminl / smax )<=max( eps, hndrth*tol ) ) then ! use a zero shift to avoid loss of relative accuracy shift = zero else ! compute the shift from 2-by-2 block at end of matrix if( idir==1_${ik}$ ) then sll = abs( d( ll ) ) call stdlib${ii}$_slas2( d( m-1 ), e( m-1 ), d( m ), shift, r ) else sll = abs( d( m ) ) call stdlib${ii}$_slas2( d( ll ), e( ll ), d( ll+1 ), shift, r ) end if ! test if shift negligible, and if so set to zero if( sll>zero ) then if( ( shift / sll )**2_${ik}$ll )e( i-1 ) = oldsn*r call stdlib${ii}$_slartg( oldcs*r, d( i+1 )*sn, oldcs, oldsn, d( i ) ) work( i-ll+1 ) = cs work( i-ll+1+nm1 ) = sn work( i-ll+1+nm12 ) = oldcs work( i-ll+1+nm13 ) = oldsn end do h = d( m )*cs d( m ) = h*oldcs e( m-1 ) = h*oldsn ! update singular vectors if( ncvt>0_${ik}$ )call stdlib${ii}$_slasr( 'L', 'V', 'F', m-ll+1, ncvt, work( 1_${ik}$ ),work( n ), & vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_slasr( 'R', 'V', 'F', nru, m-ll+1, work( nm12+1 ),work( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_slasr( 'L', 'V', 'F', m-ll+1, ncc, work( nm12+1 ),work( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates cs = one oldcs = one do i = m, ll + 1, -1 call stdlib${ii}$_slartg( d( i )*cs, e( i-1 ), cs, sn, r ) if( i0_${ik}$ )call stdlib${ii}$_slasr( 'L', 'V', 'B', m-ll+1, ncvt, work( nm12+1 ),work( & nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_slasr( 'R', 'V', 'B', nru, m-ll+1, work( 1_${ik}$ ),work( n ), u(& 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_slasr( 'L', 'V', 'B', m-ll+1, ncc, work( 1_${ik}$ ),work( n ), c(& ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero end if else ! use nonzero shift if( idir==1_${ik}$ ) then ! chase bulge from top to bottom ! save cosines and sines for later singular vector updates f = ( abs( d( ll ) )-shift )*( sign( one, d( ll ) )+shift / d( ll ) ) g = e( ll ) do i = ll, m - 1 call stdlib${ii}$_slartg( f, g, cosr, sinr, r ) if( i>ll )e( i-1 ) = r f = cosr*d( i ) + sinr*e( i ) e( i ) = cosr*e( i ) - sinr*d( i ) g = sinr*d( i+1 ) d( i+1 ) = cosr*d( i+1 ) call stdlib${ii}$_slartg( f, g, cosl, sinl, r ) d( i ) = r f = cosl*e( i ) + sinl*d( i+1 ) d( i+1 ) = cosl*d( i+1 ) - sinl*e( i ) if( i0_${ik}$ )call stdlib${ii}$_slasr( 'L', 'V', 'F', m-ll+1, ncvt, work( 1_${ik}$ ),work( n ), & vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_slasr( 'R', 'V', 'F', nru, m-ll+1, work( nm12+1 ),work( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_slasr( 'L', 'V', 'F', m-ll+1, ncc, work( nm12+1 ),work( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates f = ( abs( d( m ) )-shift )*( sign( one, d( m ) )+shift /d( m ) ) g = e( m-1 ) do i = m, ll + 1, -1 call stdlib${ii}$_slartg( f, g, cosr, sinr, r ) if( ill+1 ) then g = sinl*e( i-2 ) e( i-2 ) = cosl*e( i-2 ) end if work( i-ll ) = cosr work( i-ll+nm1 ) = -sinr work( i-ll+nm12 ) = cosl work( i-ll+nm13 ) = -sinl end do e( ll ) = f ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero ! update singular vectors if desired if( ncvt>0_${ik}$ )call stdlib${ii}$_slasr( 'L', 'V', 'B', m-ll+1, ncvt, work( nm12+1 ),work( & nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_slasr( 'R', 'V', 'B', nru, m-ll+1, work( 1_${ik}$ ),work( n ), u(& 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_slasr( 'L', 'V', 'B', m-ll+1, ncc, work( 1_${ik}$ ),work( n ), c(& ll, 1_${ik}$ ), ldc ) end if end if ! qr iteration finished, go back and check convergence go to 60 ! all singular values converged, so make them positive 160 continue do i = 1, n if( d( i )0_${ik}$ )call stdlib${ii}$_sscal( ncvt, negone, vt( i, 1_${ik}$ ), ldvt ) end if end do ! sort the singular values into decreasing order (insertion sort on ! singular values, but only one transposition per singular vector) do i = 1, n - 1 ! scan for smallest d(i) isub = 1_${ik}$ smin = d( 1_${ik}$ ) do j = 2, n + 1 - i if( d( j )<=smin ) then isub = j smin = d( j ) end if end do if( isub/=n+1-i ) then ! swap singular values and vectors d( isub ) = d( n+1-i ) d( n+1-i ) = smin if( ncvt>0_${ik}$ )call stdlib${ii}$_sswap( ncvt, vt( isub, 1_${ik}$ ), ldvt, vt( n+1-i, 1_${ik}$ ),ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_sswap( nru, u( 1_${ik}$, isub ), 1_${ik}$, u( 1_${ik}$, n+1-i ), 1_${ik}$ ) if( ncc>0_${ik}$ )call stdlib${ii}$_sswap( ncc, c( isub, 1_${ik}$ ), ldc, c( n+1-i, 1_${ik}$ ), ldc ) end if end do go to 220 ! maximum number of iterations exceeded, failure to converge 200 continue info = 0_${ik}$ do i = 1, n - 1 if( e( i )/=zero )info = info + 1_${ik}$ end do 220 continue return end subroutine stdlib${ii}$_sbdsqr pure module subroutine stdlib${ii}$_dbdsqr( uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u,ldu, c, ldc, work, & !! DBDSQR computes the singular values and, optionally, the right and/or !! left singular vectors from the singular value decomposition (SVD) of !! a real N-by-N (upper or lower) bidiagonal matrix B using the implicit !! zero-shift QR algorithm. The SVD of B has the form !! B = Q * S * P**T !! where S is the diagonal matrix of singular values, Q is an orthogonal !! matrix of left singular vectors, and P is an orthogonal matrix of !! right singular vectors. If left singular vectors are requested, this !! subroutine actually returns U*Q instead of Q, and, if right singular !! vectors are requested, this subroutine returns P**T*VT instead of !! P**T, for given real input matrices U and VT. When U and VT are the !! orthogonal matrices that reduce a general matrix A to bidiagonal !! form: A = U*B*VT, as computed by DGEBRD, then !! A = (U*Q) * S * (P**T*VT) !! is the SVD of A. Optionally, the subroutine may also compute Q**T*C !! for a given real input matrix C. !! See "Computing Small Singular Values of Bidiagonal Matrices With !! Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan, !! LAPACK Working Note #3 (or SIAM J. Sci. Statist. Comput. vol. 11, !! no. 5, pp. 873-912, Sept 1990) and !! "Accurate singular values and differential qd algorithms," by !! B. Parlett and V. Fernando, Technical Report CPAM-554, Mathematics !! Department, University of California at Berkeley, July 1992 !! for a detailed description of the algorithm. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc, ldu, ldvt, n, ncc, ncvt, nru ! Array Arguments real(dp), intent(inout) :: c(ldc,*), d(*), e(*), u(ldu,*), vt(ldvt,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters real(dp), parameter :: hndrth = 0.01_dp real(dp), parameter :: hndrd = 100.0_dp real(dp), parameter :: meigth = -0.125_dp integer(${ik}$), parameter :: maxitr = 6_${ik}$ ! Local Scalars logical(lk) :: lower, rotate integer(${ik}$) :: i, idir, isub, iter, iterdivn, j, ll, lll, m, maxitdivn, nm1, nm12, & nm13, oldll, oldm real(dp) :: abse, abss, cosl, cosr, cs, eps, f, g, h, mu, oldcs, oldsn, r, shift, & sigmn, sigmx, sinl, sinr, sll, smax, smin, sminl, sminoa, sn, thresh, tol, tolmul, & unfl ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ lower = stdlib_lsame( uplo, 'L' ) if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.lower ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ncvt<0_${ik}$ ) then info = -3_${ik}$ else if( nru<0_${ik}$ ) then info = -4_${ik}$ else if( ncc<0_${ik}$ ) then info = -5_${ik}$ else if( ( ncvt==0_${ik}$ .and. ldvt<1_${ik}$ ) .or.( ncvt>0_${ik}$ .and. ldvt0_${ik}$ .and. ldc0_${ik}$ ) .or. ( nru>0_${ik}$ ) .or. ( ncc>0_${ik}$ ) ! if no singular vectors desired, use qd algorithm if( .not.rotate ) then call stdlib${ii}$_dlasq1( n, d, e, work, info ) ! if info equals 2, dqds didn't finish, try to finish if( info /= 2 ) return info = 0_${ik}$ end if nm1 = n - 1_${ik}$ nm12 = nm1 + nm1 nm13 = nm12 + nm1 idir = 0_${ik}$ ! get machine constants eps = stdlib${ii}$_dlamch( 'EPSILON' ) unfl = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) ! if matrix lower bidiagonal, rotate to be upper bidiagonal ! by applying givens rotations on the left if( lower ) then do i = 1, n - 1 call stdlib${ii}$_dlartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) work( i ) = cs work( nm1+i ) = sn end do ! update singular vectors if desired if( nru>0_${ik}$ )call stdlib${ii}$_dlasr( 'R', 'V', 'F', nru, n, work( 1_${ik}$ ), work( n ), u,ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_dlasr( 'L', 'V', 'F', n, ncc, work( 1_${ik}$ ), work( n ), c,ldc ) end if ! compute singular values to relative accuracy tol ! (by setting tol to be negative, algorithm will compute ! singular values to absolute accuracy abs(tol)*norm(input matrix)) tolmul = max( ten, min( hndrd, eps**meigth ) ) tol = tolmul*eps ! compute approximate maximum, minimum singular values smax = zero do i = 1, n smax = max( smax, abs( d( i ) ) ) end do do i = 1, n - 1 smax = max( smax, abs( e( i ) ) ) end do sminl = zero if( tol>=zero ) then ! relative accuracy desired sminoa = abs( d( 1_${ik}$ ) ) if( sminoa==zero )go to 50 mu = sminoa do i = 2, n mu = abs( d( i ) )*( mu / ( mu+abs( e( i-1 ) ) ) ) sminoa = min( sminoa, mu ) if( sminoa==zero )go to 50 end do 50 continue sminoa = sminoa / sqrt( real( n,KIND=dp) ) thresh = max( tol*sminoa, maxitr*(n*(n*unfl)) ) else ! absolute accuracy desired thresh = max( abs( tol )*smax, maxitr*(n*(n*unfl)) ) end if ! prepare for main iteration loop for the singular values ! (maxit is the maximum number of passes through the inner ! loop permitted before nonconvergence signalled.) maxitdivn = maxitr*n iterdivn = 0_${ik}$ iter = -1_${ik}$ oldll = -1_${ik}$ oldm = -1_${ik}$ ! m points to last element of unconverged part of matrix m = n ! begin main iteration loop 60 continue ! check for convergence or exceeding iteration count if( m<=1 )go to 160 if( iter>=n ) then iter = iter - n iterdivn = iterdivn + 1_${ik}$ if( iterdivn>=maxitdivn )go to 200 end if ! find diagonal block of matrix to work on if( tol0_${ik}$ )call stdlib${ii}$_drot( ncvt, vt( m-1, 1_${ik}$ ), ldvt, vt( m, 1_${ik}$ ), ldvt, cosr,sinr & ) if( nru>0_${ik}$ )call stdlib${ii}$_drot( nru, u( 1_${ik}$, m-1 ), 1_${ik}$, u( 1_${ik}$, m ), 1_${ik}$, cosl, sinl ) if( ncc>0_${ik}$ )call stdlib${ii}$_drot( ncc, c( m-1, 1_${ik}$ ), ldc, c( m, 1_${ik}$ ), ldc, cosl,sinl ) m = m - 2_${ik}$ go to 60 end if ! if working on new submatrix, choose shift direction ! (from larger end diagonal element towards smaller) if( ll>oldm .or. m=abs( d( m ) ) ) then ! chase bulge from top (big end) to bottom (small end) idir = 1_${ik}$ else ! chase bulge from bottom (big end) to top (small end) idir = 2_${ik}$ end if end if ! apply convergence tests if( idir==1_${ik}$ ) then ! run convergence test in forward direction ! first apply standard test to bottom of matrix if( abs( e( m-1 ) )<=abs( tol )*abs( d( m ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion forward mu = abs( d( ll ) ) sminl = mu do lll = ll, m - 1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll+1 ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if else ! run convergence test in backward direction ! first apply standard test to top of matrix if( abs( e( ll ) )<=abs( tol )*abs( d( ll ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion backward mu = abs( d( m ) ) sminl = mu do lll = m - 1, ll, -1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if end if oldll = ll oldm = m ! compute shift. first, test if shifting would ruin relative ! accuracy, and if so set the shift to zero. if( tol>=zero .and. n*tol*( sminl / smax )<=max( eps, hndrth*tol ) ) then ! use a zero shift to avoid loss of relative accuracy shift = zero else ! compute the shift from 2-by-2 block at end of matrix if( idir==1_${ik}$ ) then sll = abs( d( ll ) ) call stdlib${ii}$_dlas2( d( m-1 ), e( m-1 ), d( m ), shift, r ) else sll = abs( d( m ) ) call stdlib${ii}$_dlas2( d( ll ), e( ll ), d( ll+1 ), shift, r ) end if ! test if shift negligible, and if so set to zero if( sll>zero ) then if( ( shift / sll )**2_${ik}$ll )e( i-1 ) = oldsn*r call stdlib${ii}$_dlartg( oldcs*r, d( i+1 )*sn, oldcs, oldsn, d( i ) ) work( i-ll+1 ) = cs work( i-ll+1+nm1 ) = sn work( i-ll+1+nm12 ) = oldcs work( i-ll+1+nm13 ) = oldsn end do h = d( m )*cs d( m ) = h*oldcs e( m-1 ) = h*oldsn ! update singular vectors if( ncvt>0_${ik}$ )call stdlib${ii}$_dlasr( 'L', 'V', 'F', m-ll+1, ncvt, work( 1_${ik}$ ),work( n ), & vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_dlasr( 'R', 'V', 'F', nru, m-ll+1, work( nm12+1 ),work( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_dlasr( 'L', 'V', 'F', m-ll+1, ncc, work( nm12+1 ),work( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates cs = one oldcs = one do i = m, ll + 1, -1 call stdlib${ii}$_dlartg( d( i )*cs, e( i-1 ), cs, sn, r ) if( i0_${ik}$ )call stdlib${ii}$_dlasr( 'L', 'V', 'B', m-ll+1, ncvt, work( nm12+1 ),work( & nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_dlasr( 'R', 'V', 'B', nru, m-ll+1, work( 1_${ik}$ ),work( n ), u(& 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_dlasr( 'L', 'V', 'B', m-ll+1, ncc, work( 1_${ik}$ ),work( n ), c(& ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero end if else ! use nonzero shift if( idir==1_${ik}$ ) then ! chase bulge from top to bottom ! save cosines and sines for later singular vector updates f = ( abs( d( ll ) )-shift )*( sign( one, d( ll ) )+shift / d( ll ) ) g = e( ll ) do i = ll, m - 1 call stdlib${ii}$_dlartg( f, g, cosr, sinr, r ) if( i>ll )e( i-1 ) = r f = cosr*d( i ) + sinr*e( i ) e( i ) = cosr*e( i ) - sinr*d( i ) g = sinr*d( i+1 ) d( i+1 ) = cosr*d( i+1 ) call stdlib${ii}$_dlartg( f, g, cosl, sinl, r ) d( i ) = r f = cosl*e( i ) + sinl*d( i+1 ) d( i+1 ) = cosl*d( i+1 ) - sinl*e( i ) if( i0_${ik}$ )call stdlib${ii}$_dlasr( 'L', 'V', 'F', m-ll+1, ncvt, work( 1_${ik}$ ),work( n ), & vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_dlasr( 'R', 'V', 'F', nru, m-ll+1, work( nm12+1 ),work( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_dlasr( 'L', 'V', 'F', m-ll+1, ncc, work( nm12+1 ),work( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates f = ( abs( d( m ) )-shift )*( sign( one, d( m ) )+shift /d( m ) ) g = e( m-1 ) do i = m, ll + 1, -1 call stdlib${ii}$_dlartg( f, g, cosr, sinr, r ) if( ill+1 ) then g = sinl*e( i-2 ) e( i-2 ) = cosl*e( i-2 ) end if work( i-ll ) = cosr work( i-ll+nm1 ) = -sinr work( i-ll+nm12 ) = cosl work( i-ll+nm13 ) = -sinl end do e( ll ) = f ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero ! update singular vectors if desired if( ncvt>0_${ik}$ )call stdlib${ii}$_dlasr( 'L', 'V', 'B', m-ll+1, ncvt, work( nm12+1 ),work( & nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_dlasr( 'R', 'V', 'B', nru, m-ll+1, work( 1_${ik}$ ),work( n ), u(& 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_dlasr( 'L', 'V', 'B', m-ll+1, ncc, work( 1_${ik}$ ),work( n ), c(& ll, 1_${ik}$ ), ldc ) end if end if ! qr iteration finished, go back and check convergence go to 60 ! all singular values converged, so make them positive 160 continue do i = 1, n if( d( i )0_${ik}$ )call stdlib${ii}$_dscal( ncvt, negone, vt( i, 1_${ik}$ ), ldvt ) end if end do ! sort the singular values into decreasing order (insertion sort on ! singular values, but only one transposition per singular vector) do i = 1, n - 1 ! scan for smallest d(i) isub = 1_${ik}$ smin = d( 1_${ik}$ ) do j = 2, n + 1 - i if( d( j )<=smin ) then isub = j smin = d( j ) end if end do if( isub/=n+1-i ) then ! swap singular values and vectors d( isub ) = d( n+1-i ) d( n+1-i ) = smin if( ncvt>0_${ik}$ )call stdlib${ii}$_dswap( ncvt, vt( isub, 1_${ik}$ ), ldvt, vt( n+1-i, 1_${ik}$ ),ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_dswap( nru, u( 1_${ik}$, isub ), 1_${ik}$, u( 1_${ik}$, n+1-i ), 1_${ik}$ ) if( ncc>0_${ik}$ )call stdlib${ii}$_dswap( ncc, c( isub, 1_${ik}$ ), ldc, c( n+1-i, 1_${ik}$ ), ldc ) end if end do go to 220 ! maximum number of iterations exceeded, failure to converge 200 continue info = 0_${ik}$ do i = 1, n - 1 if( e( i )/=zero )info = info + 1_${ik}$ end do 220 continue return end subroutine stdlib${ii}$_dbdsqr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$bdsqr( uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u,ldu, c, ldc, work, & !! DBDSQR: computes the singular values and, optionally, the right and/or !! left singular vectors from the singular value decomposition (SVD) of !! a real N-by-N (upper or lower) bidiagonal matrix B using the implicit !! zero-shift QR algorithm. The SVD of B has the form !! B = Q * S * P**T !! where S is the diagonal matrix of singular values, Q is an orthogonal !! matrix of left singular vectors, and P is an orthogonal matrix of !! right singular vectors. If left singular vectors are requested, this !! subroutine actually returns U*Q instead of Q, and, if right singular !! vectors are requested, this subroutine returns P**T*VT instead of !! P**T, for given real input matrices U and VT. When U and VT are the !! orthogonal matrices that reduce a general matrix A to bidiagonal !! form: A = U*B*VT, as computed by DGEBRD, then !! A = (U*Q) * S * (P**T*VT) !! is the SVD of A. Optionally, the subroutine may also compute Q**T*C !! for a given real input matrix C. !! See "Computing Small Singular Values of Bidiagonal Matrices With !! Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan, !! LAPACK Working Note #3 (or SIAM J. Sci. Statist. Comput. vol. 11, !! no. 5, pp. 873-912, Sept 1990) and !! "Accurate singular values and differential qd algorithms," by !! B. Parlett and V. Fernando, Technical Report CPAM-554, Mathematics !! Department, University of California at Berkeley, July 1992 !! for a detailed description of the algorithm. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc, ldu, ldvt, n, ncc, ncvt, nru ! Array Arguments real(${rk}$), intent(inout) :: c(ldc,*), d(*), e(*), u(ldu,*), vt(ldvt,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: hndrth = 0.01_${rk}$ real(${rk}$), parameter :: hndrd = 100.0_${rk}$ real(${rk}$), parameter :: meigth = -0.125_${rk}$ integer(${ik}$), parameter :: maxitr = 6_${ik}$ ! Local Scalars logical(lk) :: lower, rotate integer(${ik}$) :: i, idir, isub, iter, iterdivn, j, ll, lll, m, maxitdivn, nm1, nm12, & nm13, oldll, oldm real(${rk}$) :: abse, abss, cosl, cosr, cs, eps, f, g, h, mu, oldcs, oldsn, r, shift, & sigmn, sigmx, sinl, sinr, sll, smax, smin, sminl, sminoa, sn, thresh, tol, tolmul, & unfl ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ lower = stdlib_lsame( uplo, 'L' ) if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.lower ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ncvt<0_${ik}$ ) then info = -3_${ik}$ else if( nru<0_${ik}$ ) then info = -4_${ik}$ else if( ncc<0_${ik}$ ) then info = -5_${ik}$ else if( ( ncvt==0_${ik}$ .and. ldvt<1_${ik}$ ) .or.( ncvt>0_${ik}$ .and. ldvt0_${ik}$ .and. ldc0_${ik}$ ) .or. ( nru>0_${ik}$ ) .or. ( ncc>0_${ik}$ ) ! if no singular vectors desired, use qd algorithm if( .not.rotate ) then call stdlib${ii}$_${ri}$lasq1( n, d, e, work, info ) ! if info equals 2, dqds didn't finish, try to finish if( info /= 2 ) return info = 0_${ik}$ end if nm1 = n - 1_${ik}$ nm12 = nm1 + nm1 nm13 = nm12 + nm1 idir = 0_${ik}$ ! get machine constants eps = stdlib${ii}$_${ri}$lamch( 'EPSILON' ) unfl = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) ! if matrix lower bidiagonal, rotate to be upper bidiagonal ! by applying givens rotations on the left if( lower ) then do i = 1, n - 1 call stdlib${ii}$_${ri}$lartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) work( i ) = cs work( nm1+i ) = sn end do ! update singular vectors if desired if( nru>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'F', nru, n, work( 1_${ik}$ ), work( n ), u,ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', n, ncc, work( 1_${ik}$ ), work( n ), c,ldc ) end if ! compute singular values to relative accuracy tol ! (by setting tol to be negative, algorithm will compute ! singular values to absolute accuracy abs(tol)*norm(input matrix)) tolmul = max( ten, min( hndrd, eps**meigth ) ) tol = tolmul*eps ! compute approximate maximum, minimum singular values smax = zero do i = 1, n smax = max( smax, abs( d( i ) ) ) end do do i = 1, n - 1 smax = max( smax, abs( e( i ) ) ) end do sminl = zero if( tol>=zero ) then ! relative accuracy desired sminoa = abs( d( 1_${ik}$ ) ) if( sminoa==zero )go to 50 mu = sminoa do i = 2, n mu = abs( d( i ) )*( mu / ( mu+abs( e( i-1 ) ) ) ) sminoa = min( sminoa, mu ) if( sminoa==zero )go to 50 end do 50 continue sminoa = sminoa / sqrt( real( n,KIND=${rk}$) ) thresh = max( tol*sminoa, maxitr*(n*(n*unfl)) ) else ! absolute accuracy desired thresh = max( abs( tol )*smax, maxitr*(n*(n*unfl)) ) end if ! prepare for main iteration loop for the singular values ! (maxit is the maximum number of passes through the inner ! loop permitted before nonconvergence signalled.) maxitdivn = maxitr*n iterdivn = 0_${ik}$ iter = -1_${ik}$ oldll = -1_${ik}$ oldm = -1_${ik}$ ! m points to last element of unconverged part of matrix m = n ! begin main iteration loop 60 continue ! check for convergence or exceeding iteration count if( m<=1 )go to 160 if( iter>=n ) then iter = iter - n iterdivn = iterdivn + 1_${ik}$ if( iterdivn>=maxitdivn )go to 200 end if ! find diagonal block of matrix to work on if( tol0_${ik}$ )call stdlib${ii}$_${ri}$rot( ncvt, vt( m-1, 1_${ik}$ ), ldvt, vt( m, 1_${ik}$ ), ldvt, cosr,sinr & ) if( nru>0_${ik}$ )call stdlib${ii}$_${ri}$rot( nru, u( 1_${ik}$, m-1 ), 1_${ik}$, u( 1_${ik}$, m ), 1_${ik}$, cosl, sinl ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ri}$rot( ncc, c( m-1, 1_${ik}$ ), ldc, c( m, 1_${ik}$ ), ldc, cosl,sinl ) m = m - 2_${ik}$ go to 60 end if ! if working on new submatrix, choose shift direction ! (from larger end diagonal element towards smaller) if( ll>oldm .or. m=abs( d( m ) ) ) then ! chase bulge from top (big end) to bottom (small end) idir = 1_${ik}$ else ! chase bulge from bottom (big end) to top (small end) idir = 2_${ik}$ end if end if ! apply convergence tests if( idir==1_${ik}$ ) then ! run convergence test in forward direction ! first apply standard test to bottom of matrix if( abs( e( m-1 ) )<=abs( tol )*abs( d( m ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion forward mu = abs( d( ll ) ) sminl = mu do lll = ll, m - 1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll+1 ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if else ! run convergence test in backward direction ! first apply standard test to top of matrix if( abs( e( ll ) )<=abs( tol )*abs( d( ll ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion backward mu = abs( d( m ) ) sminl = mu do lll = m - 1, ll, -1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if end if oldll = ll oldm = m ! compute shift. first, test if shifting would ruin relative ! accuracy, and if so set the shift to zero. if( tol>=zero .and. n*tol*( sminl / smax )<=max( eps, hndrth*tol ) ) then ! use a zero shift to avoid loss of relative accuracy shift = zero else ! compute the shift from 2-by-2 block at end of matrix if( idir==1_${ik}$ ) then sll = abs( d( ll ) ) call stdlib${ii}$_${ri}$las2( d( m-1 ), e( m-1 ), d( m ), shift, r ) else sll = abs( d( m ) ) call stdlib${ii}$_${ri}$las2( d( ll ), e( ll ), d( ll+1 ), shift, r ) end if ! test if shift negligible, and if so set to zero if( sll>zero ) then if( ( shift / sll )**2_${ik}$ll )e( i-1 ) = oldsn*r call stdlib${ii}$_${ri}$lartg( oldcs*r, d( i+1 )*sn, oldcs, oldsn, d( i ) ) work( i-ll+1 ) = cs work( i-ll+1+nm1 ) = sn work( i-ll+1+nm12 ) = oldcs work( i-ll+1+nm13 ) = oldsn end do h = d( m )*cs d( m ) = h*oldcs e( m-1 ) = h*oldsn ! update singular vectors if( ncvt>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', m-ll+1, ncvt, work( 1_${ik}$ ),work( n ), & vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'F', nru, m-ll+1, work( nm12+1 ),work( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', m-ll+1, ncc, work( nm12+1 ),work( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates cs = one oldcs = one do i = m, ll + 1, -1 call stdlib${ii}$_${ri}$lartg( d( i )*cs, e( i-1 ), cs, sn, r ) if( i0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'B', m-ll+1, ncvt, work( nm12+1 ),work( & nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'B', nru, m-ll+1, work( 1_${ik}$ ),work( n ), u(& 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'B', m-ll+1, ncc, work( 1_${ik}$ ),work( n ), c(& ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero end if else ! use nonzero shift if( idir==1_${ik}$ ) then ! chase bulge from top to bottom ! save cosines and sines for later singular vector updates f = ( abs( d( ll ) )-shift )*( sign( one, d( ll ) )+shift / d( ll ) ) g = e( ll ) do i = ll, m - 1 call stdlib${ii}$_${ri}$lartg( f, g, cosr, sinr, r ) if( i>ll )e( i-1 ) = r f = cosr*d( i ) + sinr*e( i ) e( i ) = cosr*e( i ) - sinr*d( i ) g = sinr*d( i+1 ) d( i+1 ) = cosr*d( i+1 ) call stdlib${ii}$_${ri}$lartg( f, g, cosl, sinl, r ) d( i ) = r f = cosl*e( i ) + sinl*d( i+1 ) d( i+1 ) = cosl*d( i+1 ) - sinl*e( i ) if( i0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', m-ll+1, ncvt, work( 1_${ik}$ ),work( n ), & vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'F', nru, m-ll+1, work( nm12+1 ),work( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', m-ll+1, ncc, work( nm12+1 ),work( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates f = ( abs( d( m ) )-shift )*( sign( one, d( m ) )+shift /d( m ) ) g = e( m-1 ) do i = m, ll + 1, -1 call stdlib${ii}$_${ri}$lartg( f, g, cosr, sinr, r ) if( ill+1 ) then g = sinl*e( i-2 ) e( i-2 ) = cosl*e( i-2 ) end if work( i-ll ) = cosr work( i-ll+nm1 ) = -sinr work( i-ll+nm12 ) = cosl work( i-ll+nm13 ) = -sinl end do e( ll ) = f ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero ! update singular vectors if desired if( ncvt>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'B', m-ll+1, ncvt, work( nm12+1 ),work( & nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'B', nru, m-ll+1, work( 1_${ik}$ ),work( n ), u(& 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'B', m-ll+1, ncc, work( 1_${ik}$ ),work( n ), c(& ll, 1_${ik}$ ), ldc ) end if end if ! qr iteration finished, go back and check convergence go to 60 ! all singular values converged, so make them positive 160 continue do i = 1, n if( d( i )0_${ik}$ )call stdlib${ii}$_${ri}$scal( ncvt, negone, vt( i, 1_${ik}$ ), ldvt ) end if end do ! sort the singular values into decreasing order (insertion sort on ! singular values, but only one transposition per singular vector) do i = 1, n - 1 ! scan for smallest d(i) isub = 1_${ik}$ smin = d( 1_${ik}$ ) do j = 2, n + 1 - i if( d( j )<=smin ) then isub = j smin = d( j ) end if end do if( isub/=n+1-i ) then ! swap singular values and vectors d( isub ) = d( n+1-i ) d( n+1-i ) = smin if( ncvt>0_${ik}$ )call stdlib${ii}$_${ri}$swap( ncvt, vt( isub, 1_${ik}$ ), ldvt, vt( n+1-i, 1_${ik}$ ),ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_${ri}$swap( nru, u( 1_${ik}$, isub ), 1_${ik}$, u( 1_${ik}$, n+1-i ), 1_${ik}$ ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ri}$swap( ncc, c( isub, 1_${ik}$ ), ldc, c( n+1-i, 1_${ik}$ ), ldc ) end if end do go to 220 ! maximum number of iterations exceeded, failure to converge 200 continue info = 0_${ik}$ do i = 1, n - 1 if( e( i )/=zero )info = info + 1_${ik}$ end do 220 continue return end subroutine stdlib${ii}$_${ri}$bdsqr #:endif #:endfor pure module subroutine stdlib${ii}$_cbdsqr( uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u,ldu, c, ldc, rwork,& !! CBDSQR computes the singular values and, optionally, the right and/or !! left singular vectors from the singular value decomposition (SVD) of !! a real N-by-N (upper or lower) bidiagonal matrix B using the implicit !! zero-shift QR algorithm. The SVD of B has the form !! B = Q * S * P**H !! where S is the diagonal matrix of singular values, Q is an orthogonal !! matrix of left singular vectors, and P is an orthogonal matrix of !! right singular vectors. If left singular vectors are requested, this !! subroutine actually returns U*Q instead of Q, and, if right singular !! vectors are requested, this subroutine returns P**H*VT instead of !! P**H, for given complex input matrices U and VT. When U and VT are !! the unitary matrices that reduce a general matrix A to bidiagonal !! form: A = U*B*VT, as computed by CGEBRD, then !! A = (U*Q) * S * (P**H*VT) !! is the SVD of A. Optionally, the subroutine may also compute Q**H*C !! for a given complex input matrix C. !! See "Computing Small Singular Values of Bidiagonal Matrices With !! Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan, !! LAPACK Working Note #3 (or SIAM J. Sci. Statist. Comput. vol. 11, !! no. 5, pp. 873-912, Sept 1990) and !! "Accurate singular values and differential qd algorithms," by !! B. Parlett and V. Fernando, Technical Report CPAM-554, Mathematics !! Department, University of California at Berkeley, July 1992 !! for a detailed description of the algorithm. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc, ldu, ldvt, n, ncc, ncvt, nru ! Array Arguments real(sp), intent(inout) :: d(*), e(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: c(ldc,*), u(ldu,*), vt(ldvt,*) ! ===================================================================== ! Parameters real(sp), parameter :: hndrth = 0.01_sp real(sp), parameter :: hndrd = 100.0_sp real(sp), parameter :: meigth = -0.125_sp integer(${ik}$), parameter :: maxitr = 6_${ik}$ ! Local Scalars logical(lk) :: lower, rotate integer(${ik}$) :: i, idir, isub, iter, j, ll, lll, m, maxit, nm1, nm12, nm13, oldll, & oldm real(sp) :: abse, abss, cosl, cosr, cs, eps, f, g, h, mu, oldcs, oldsn, r, shift, & sigmn, sigmx, sinl, sinr, sll, smax, smin, sminl, sminoa, sn, thresh, tol, tolmul, & unfl ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ lower = stdlib_lsame( uplo, 'L' ) if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.lower ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ncvt<0_${ik}$ ) then info = -3_${ik}$ else if( nru<0_${ik}$ ) then info = -4_${ik}$ else if( ncc<0_${ik}$ ) then info = -5_${ik}$ else if( ( ncvt==0_${ik}$ .and. ldvt<1_${ik}$ ) .or.( ncvt>0_${ik}$ .and. ldvt0_${ik}$ .and. ldc0_${ik}$ ) .or. ( nru>0_${ik}$ ) .or. ( ncc>0_${ik}$ ) ! if no singular vectors desired, use qd algorithm if( .not.rotate ) then call stdlib${ii}$_slasq1( n, d, e, rwork, info ) ! if info equals 2, dqds didn't finish, try to finish if( info /= 2 ) return info = 0_${ik}$ end if nm1 = n - 1_${ik}$ nm12 = nm1 + nm1 nm13 = nm12 + nm1 idir = 0_${ik}$ ! get machine constants eps = stdlib${ii}$_slamch( 'EPSILON' ) unfl = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) ! if matrix lower bidiagonal, rotate to be upper bidiagonal ! by applying givens rotations on the left if( lower ) then do i = 1, n - 1 call stdlib${ii}$_slartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) rwork( i ) = cs rwork( nm1+i ) = sn end do ! update singular vectors if desired if( nru>0_${ik}$ )call stdlib${ii}$_clasr( 'R', 'V', 'F', nru, n, rwork( 1_${ik}$ ), rwork( n ),u, ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_clasr( 'L', 'V', 'F', n, ncc, rwork( 1_${ik}$ ), rwork( n ),c, ldc ) end if ! compute singular values to relative accuracy tol ! (by setting tol to be negative, algorithm will compute ! singular values to absolute accuracy abs(tol)*norm(input matrix)) tolmul = max( ten, min( hndrd, eps**meigth ) ) tol = tolmul*eps ! compute approximate maximum, minimum singular values smax = zero do i = 1, n smax = max( smax, abs( d( i ) ) ) end do do i = 1, n - 1 smax = max( smax, abs( e( i ) ) ) end do sminl = zero if( tol>=zero ) then ! relative accuracy desired sminoa = abs( d( 1_${ik}$ ) ) if( sminoa==zero )go to 50 mu = sminoa do i = 2, n mu = abs( d( i ) )*( mu / ( mu+abs( e( i-1 ) ) ) ) sminoa = min( sminoa, mu ) if( sminoa==zero )go to 50 end do 50 continue sminoa = sminoa / sqrt( real( n,KIND=sp) ) thresh = max( tol*sminoa, maxitr*n*n*unfl ) else ! absolute accuracy desired thresh = max( abs( tol )*smax, maxitr*n*n*unfl ) end if ! prepare for main iteration loop for the singular values ! (maxit is the maximum number of passes through the inner ! loop permitted before nonconvergence signalled.) maxit = maxitr*n*n iter = 0_${ik}$ oldll = -1_${ik}$ oldm = -1_${ik}$ ! m points to last element of unconverged part of matrix m = n ! begin main iteration loop 60 continue ! check for convergence or exceeding iteration count if( m<=1 )go to 160 if( iter>maxit )go to 200 ! find diagonal block of matrix to work on if( tol0_${ik}$ )call stdlib${ii}$_csrot( ncvt, vt( m-1, 1_${ik}$ ), ldvt, vt( m, 1_${ik}$ ), ldvt,cosr, & sinr ) if( nru>0_${ik}$ )call stdlib${ii}$_csrot( nru, u( 1_${ik}$, m-1 ), 1_${ik}$, u( 1_${ik}$, m ), 1_${ik}$, cosl, sinl ) if( ncc>0_${ik}$ )call stdlib${ii}$_csrot( ncc, c( m-1, 1_${ik}$ ), ldc, c( m, 1_${ik}$ ), ldc, cosl,sinl ) m = m - 2_${ik}$ go to 60 end if ! if working on new submatrix, choose shift direction ! (from larger end diagonal element towards smaller) if( ll>oldm .or. m=abs( d( m ) ) ) then ! chase bulge from top (big end) to bottom (small end) idir = 1_${ik}$ else ! chase bulge from bottom (big end) to top (small end) idir = 2_${ik}$ end if end if ! apply convergence tests if( idir==1_${ik}$ ) then ! run convergence test in forward direction ! first apply standard test to bottom of matrix if( abs( e( m-1 ) )<=abs( tol )*abs( d( m ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion forward mu = abs( d( ll ) ) sminl = mu do lll = ll, m - 1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll+1 ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if else ! run convergence test in backward direction ! first apply standard test to top of matrix if( abs( e( ll ) )<=abs( tol )*abs( d( ll ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion backward mu = abs( d( m ) ) sminl = mu do lll = m - 1, ll, -1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if end if oldll = ll oldm = m ! compute shift. first, test if shifting would ruin relative ! accuracy, and if so set the shift to zero. if( tol>=zero .and. n*tol*( sminl / smax )<=max( eps, hndrth*tol ) ) then ! use a zero shift to avoid loss of relative accuracy shift = zero else ! compute the shift from 2-by-2 block at end of matrix if( idir==1_${ik}$ ) then sll = abs( d( ll ) ) call stdlib${ii}$_slas2( d( m-1 ), e( m-1 ), d( m ), shift, r ) else sll = abs( d( m ) ) call stdlib${ii}$_slas2( d( ll ), e( ll ), d( ll+1 ), shift, r ) end if ! test if shift negligible, and if so set to zero if( sll>zero ) then if( ( shift / sll )**2_${ik}$ll )e( i-1 ) = oldsn*r call stdlib${ii}$_slartg( oldcs*r, d( i+1 )*sn, oldcs, oldsn, d( i ) ) rwork( i-ll+1 ) = cs rwork( i-ll+1+nm1 ) = sn rwork( i-ll+1+nm12 ) = oldcs rwork( i-ll+1+nm13 ) = oldsn end do h = d( m )*cs d( m ) = h*oldcs e( m-1 ) = h*oldsn ! update singular vectors if( ncvt>0_${ik}$ )call stdlib${ii}$_clasr( 'L', 'V', 'F', m-ll+1, ncvt, rwork( 1_${ik}$ ),rwork( n )& , vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_clasr( 'R', 'V', 'F', nru, m-ll+1, rwork( nm12+1 ),rwork( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_clasr( 'L', 'V', 'F', m-ll+1, ncc, rwork( nm12+1 ),rwork( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates cs = one oldcs = one do i = m, ll + 1, -1 call stdlib${ii}$_slartg( d( i )*cs, e( i-1 ), cs, sn, r ) if( i0_${ik}$ )call stdlib${ii}$_clasr( 'L', 'V', 'B', m-ll+1, ncvt, rwork( nm12+1 ),& rwork( nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_clasr( 'R', 'V', 'B', nru, m-ll+1, rwork( 1_${ik}$ ),rwork( n ), & u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_clasr( 'L', 'V', 'B', m-ll+1, ncc, rwork( 1_${ik}$ ),rwork( n ), & c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero end if else ! use nonzero shift if( idir==1_${ik}$ ) then ! chase bulge from top to bottom ! save cosines and sines for later singular vector updates f = ( abs( d( ll ) )-shift )*( sign( one, d( ll ) )+shift / d( ll ) ) g = e( ll ) do i = ll, m - 1 call stdlib${ii}$_slartg( f, g, cosr, sinr, r ) if( i>ll )e( i-1 ) = r f = cosr*d( i ) + sinr*e( i ) e( i ) = cosr*e( i ) - sinr*d( i ) g = sinr*d( i+1 ) d( i+1 ) = cosr*d( i+1 ) call stdlib${ii}$_slartg( f, g, cosl, sinl, r ) d( i ) = r f = cosl*e( i ) + sinl*d( i+1 ) d( i+1 ) = cosl*d( i+1 ) - sinl*e( i ) if( i0_${ik}$ )call stdlib${ii}$_clasr( 'L', 'V', 'F', m-ll+1, ncvt, rwork( 1_${ik}$ ),rwork( n )& , vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_clasr( 'R', 'V', 'F', nru, m-ll+1, rwork( nm12+1 ),rwork( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_clasr( 'L', 'V', 'F', m-ll+1, ncc, rwork( nm12+1 ),rwork( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates f = ( abs( d( m ) )-shift )*( sign( one, d( m ) )+shift /d( m ) ) g = e( m-1 ) do i = m, ll + 1, -1 call stdlib${ii}$_slartg( f, g, cosr, sinr, r ) if( ill+1 ) then g = sinl*e( i-2 ) e( i-2 ) = cosl*e( i-2 ) end if rwork( i-ll ) = cosr rwork( i-ll+nm1 ) = -sinr rwork( i-ll+nm12 ) = cosl rwork( i-ll+nm13 ) = -sinl end do e( ll ) = f ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero ! update singular vectors if desired if( ncvt>0_${ik}$ )call stdlib${ii}$_clasr( 'L', 'V', 'B', m-ll+1, ncvt, rwork( nm12+1 ),& rwork( nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_clasr( 'R', 'V', 'B', nru, m-ll+1, rwork( 1_${ik}$ ),rwork( n ), & u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_clasr( 'L', 'V', 'B', m-ll+1, ncc, rwork( 1_${ik}$ ),rwork( n ), & c( ll, 1_${ik}$ ), ldc ) end if end if ! qr iteration finished, go back and check convergence go to 60 ! all singular values converged, so make them positive 160 continue do i = 1, n if( d( i )0_${ik}$ )call stdlib${ii}$_csscal( ncvt, negone, vt( i, 1_${ik}$ ), ldvt ) end if end do ! sort the singular values into decreasing order (insertion sort on ! singular values, but only one transposition per singular vector) do i = 1, n - 1 ! scan for smallest d(i) isub = 1_${ik}$ smin = d( 1_${ik}$ ) do j = 2, n + 1 - i if( d( j )<=smin ) then isub = j smin = d( j ) end if end do if( isub/=n+1-i ) then ! swap singular values and vectors d( isub ) = d( n+1-i ) d( n+1-i ) = smin if( ncvt>0_${ik}$ )call stdlib${ii}$_cswap( ncvt, vt( isub, 1_${ik}$ ), ldvt, vt( n+1-i, 1_${ik}$ ),ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_cswap( nru, u( 1_${ik}$, isub ), 1_${ik}$, u( 1_${ik}$, n+1-i ), 1_${ik}$ ) if( ncc>0_${ik}$ )call stdlib${ii}$_cswap( ncc, c( isub, 1_${ik}$ ), ldc, c( n+1-i, 1_${ik}$ ), ldc ) end if end do go to 220 ! maximum number of iterations exceeded, failure to converge 200 continue info = 0_${ik}$ do i = 1, n - 1 if( e( i )/=zero )info = info + 1_${ik}$ end do 220 continue return end subroutine stdlib${ii}$_cbdsqr pure module subroutine stdlib${ii}$_zbdsqr( uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u,ldu, c, ldc, rwork,& !! ZBDSQR computes the singular values and, optionally, the right and/or !! left singular vectors from the singular value decomposition (SVD) of !! a real N-by-N (upper or lower) bidiagonal matrix B using the implicit !! zero-shift QR algorithm. The SVD of B has the form !! B = Q * S * P**H !! where S is the diagonal matrix of singular values, Q is an orthogonal !! matrix of left singular vectors, and P is an orthogonal matrix of !! right singular vectors. If left singular vectors are requested, this !! subroutine actually returns U*Q instead of Q, and, if right singular !! vectors are requested, this subroutine returns P**H*VT instead of !! P**H, for given complex input matrices U and VT. When U and VT are !! the unitary matrices that reduce a general matrix A to bidiagonal !! form: A = U*B*VT, as computed by ZGEBRD, then !! A = (U*Q) * S * (P**H*VT) !! is the SVD of A. Optionally, the subroutine may also compute Q**H*C !! for a given complex input matrix C. !! See "Computing Small Singular Values of Bidiagonal Matrices With !! Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan, !! LAPACK Working Note #3 (or SIAM J. Sci. Statist. Comput. vol. 11, !! no. 5, pp. 873-912, Sept 1990) and !! "Accurate singular values and differential qd algorithms," by !! B. Parlett and V. Fernando, Technical Report CPAM-554, Mathematics !! Department, University of California at Berkeley, July 1992 !! for a detailed description of the algorithm. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc, ldu, ldvt, n, ncc, ncvt, nru ! Array Arguments real(dp), intent(inout) :: d(*), e(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: c(ldc,*), u(ldu,*), vt(ldvt,*) ! ===================================================================== ! Parameters real(dp), parameter :: hndrth = 0.01_dp real(dp), parameter :: hndrd = 100.0_dp real(dp), parameter :: meigth = -0.125_dp integer(${ik}$), parameter :: maxitr = 6_${ik}$ ! Local Scalars logical(lk) :: lower, rotate integer(${ik}$) :: i, idir, isub, iter, j, ll, lll, m, maxit, nm1, nm12, nm13, oldll, & oldm real(dp) :: abse, abss, cosl, cosr, cs, eps, f, g, h, mu, oldcs, oldsn, r, shift, & sigmn, sigmx, sinl, sinr, sll, smax, smin, sminl, sminoa, sn, thresh, tol, tolmul, & unfl ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ lower = stdlib_lsame( uplo, 'L' ) if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.lower ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ncvt<0_${ik}$ ) then info = -3_${ik}$ else if( nru<0_${ik}$ ) then info = -4_${ik}$ else if( ncc<0_${ik}$ ) then info = -5_${ik}$ else if( ( ncvt==0_${ik}$ .and. ldvt<1_${ik}$ ) .or.( ncvt>0_${ik}$ .and. ldvt0_${ik}$ .and. ldc0_${ik}$ ) .or. ( nru>0_${ik}$ ) .or. ( ncc>0_${ik}$ ) ! if no singular vectors desired, use qd algorithm if( .not.rotate ) then call stdlib${ii}$_dlasq1( n, d, e, rwork, info ) ! if info equals 2, dqds didn't finish, try to finish if( info /= 2 ) return info = 0_${ik}$ end if nm1 = n - 1_${ik}$ nm12 = nm1 + nm1 nm13 = nm12 + nm1 idir = 0_${ik}$ ! get machine constants eps = stdlib${ii}$_dlamch( 'EPSILON' ) unfl = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) ! if matrix lower bidiagonal, rotate to be upper bidiagonal ! by applying givens rotations on the left if( lower ) then do i = 1, n - 1 call stdlib${ii}$_dlartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) rwork( i ) = cs rwork( nm1+i ) = sn end do ! update singular vectors if desired if( nru>0_${ik}$ )call stdlib${ii}$_zlasr( 'R', 'V', 'F', nru, n, rwork( 1_${ik}$ ), rwork( n ),u, ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_zlasr( 'L', 'V', 'F', n, ncc, rwork( 1_${ik}$ ), rwork( n ),c, ldc ) end if ! compute singular values to relative accuracy tol ! (by setting tol to be negative, algorithm will compute ! singular values to absolute accuracy abs(tol)*norm(input matrix)) tolmul = max( ten, min( hndrd, eps**meigth ) ) tol = tolmul*eps ! compute approximate maximum, minimum singular values smax = zero do i = 1, n smax = max( smax, abs( d( i ) ) ) end do do i = 1, n - 1 smax = max( smax, abs( e( i ) ) ) end do sminl = zero if( tol>=zero ) then ! relative accuracy desired sminoa = abs( d( 1_${ik}$ ) ) if( sminoa==zero )go to 50 mu = sminoa do i = 2, n mu = abs( d( i ) )*( mu / ( mu+abs( e( i-1 ) ) ) ) sminoa = min( sminoa, mu ) if( sminoa==zero )go to 50 end do 50 continue sminoa = sminoa / sqrt( real( n,KIND=dp) ) thresh = max( tol*sminoa, maxitr*n*n*unfl ) else ! absolute accuracy desired thresh = max( abs( tol )*smax, maxitr*n*n*unfl ) end if ! prepare for main iteration loop for the singular values ! (maxit is the maximum number of passes through the inner ! loop permitted before nonconvergence signalled.) maxit = maxitr*n*n iter = 0_${ik}$ oldll = -1_${ik}$ oldm = -1_${ik}$ ! m points to last element of unconverged part of matrix m = n ! begin main iteration loop 60 continue ! check for convergence or exceeding iteration count if( m<=1 )go to 160 if( iter>maxit )go to 200 ! find diagonal block of matrix to work on if( tol0_${ik}$ )call stdlib${ii}$_zdrot( ncvt, vt( m-1, 1_${ik}$ ), ldvt, vt( m, 1_${ik}$ ), ldvt,cosr, & sinr ) if( nru>0_${ik}$ )call stdlib${ii}$_zdrot( nru, u( 1_${ik}$, m-1 ), 1_${ik}$, u( 1_${ik}$, m ), 1_${ik}$, cosl, sinl ) if( ncc>0_${ik}$ )call stdlib${ii}$_zdrot( ncc, c( m-1, 1_${ik}$ ), ldc, c( m, 1_${ik}$ ), ldc, cosl,sinl ) m = m - 2_${ik}$ go to 60 end if ! if working on new submatrix, choose shift direction ! (from larger end diagonal element towards smaller) if( ll>oldm .or. m=abs( d( m ) ) ) then ! chase bulge from top (big end) to bottom (small end) idir = 1_${ik}$ else ! chase bulge from bottom (big end) to top (small end) idir = 2_${ik}$ end if end if ! apply convergence tests if( idir==1_${ik}$ ) then ! run convergence test in forward direction ! first apply standard test to bottom of matrix if( abs( e( m-1 ) )<=abs( tol )*abs( d( m ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion forward mu = abs( d( ll ) ) sminl = mu do lll = ll, m - 1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll+1 ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if else ! run convergence test in backward direction ! first apply standard test to top of matrix if( abs( e( ll ) )<=abs( tol )*abs( d( ll ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion backward mu = abs( d( m ) ) sminl = mu do lll = m - 1, ll, -1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if end if oldll = ll oldm = m ! compute shift. first, test if shifting would ruin relative ! accuracy, and if so set the shift to zero. if( tol>=zero .and. n*tol*( sminl / smax )<=max( eps, hndrth*tol ) ) then ! use a zero shift to avoid loss of relative accuracy shift = zero else ! compute the shift from 2-by-2 block at end of matrix if( idir==1_${ik}$ ) then sll = abs( d( ll ) ) call stdlib${ii}$_dlas2( d( m-1 ), e( m-1 ), d( m ), shift, r ) else sll = abs( d( m ) ) call stdlib${ii}$_dlas2( d( ll ), e( ll ), d( ll+1 ), shift, r ) end if ! test if shift negligible, and if so set to zero if( sll>zero ) then if( ( shift / sll )**2_${ik}$ll )e( i-1 ) = oldsn*r call stdlib${ii}$_dlartg( oldcs*r, d( i+1 )*sn, oldcs, oldsn, d( i ) ) rwork( i-ll+1 ) = cs rwork( i-ll+1+nm1 ) = sn rwork( i-ll+1+nm12 ) = oldcs rwork( i-ll+1+nm13 ) = oldsn end do h = d( m )*cs d( m ) = h*oldcs e( m-1 ) = h*oldsn ! update singular vectors if( ncvt>0_${ik}$ )call stdlib${ii}$_zlasr( 'L', 'V', 'F', m-ll+1, ncvt, rwork( 1_${ik}$ ),rwork( n )& , vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_zlasr( 'R', 'V', 'F', nru, m-ll+1, rwork( nm12+1 ),rwork( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_zlasr( 'L', 'V', 'F', m-ll+1, ncc, rwork( nm12+1 ),rwork( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates cs = one oldcs = one do i = m, ll + 1, -1 call stdlib${ii}$_dlartg( d( i )*cs, e( i-1 ), cs, sn, r ) if( i0_${ik}$ )call stdlib${ii}$_zlasr( 'L', 'V', 'B', m-ll+1, ncvt, rwork( nm12+1 ),& rwork( nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_zlasr( 'R', 'V', 'B', nru, m-ll+1, rwork( 1_${ik}$ ),rwork( n ), & u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_zlasr( 'L', 'V', 'B', m-ll+1, ncc, rwork( 1_${ik}$ ),rwork( n ), & c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero end if else ! use nonzero shift if( idir==1_${ik}$ ) then ! chase bulge from top to bottom ! save cosines and sines for later singular vector updates f = ( abs( d( ll ) )-shift )*( sign( one, d( ll ) )+shift / d( ll ) ) g = e( ll ) do i = ll, m - 1 call stdlib${ii}$_dlartg( f, g, cosr, sinr, r ) if( i>ll )e( i-1 ) = r f = cosr*d( i ) + sinr*e( i ) e( i ) = cosr*e( i ) - sinr*d( i ) g = sinr*d( i+1 ) d( i+1 ) = cosr*d( i+1 ) call stdlib${ii}$_dlartg( f, g, cosl, sinl, r ) d( i ) = r f = cosl*e( i ) + sinl*d( i+1 ) d( i+1 ) = cosl*d( i+1 ) - sinl*e( i ) if( i0_${ik}$ )call stdlib${ii}$_zlasr( 'L', 'V', 'F', m-ll+1, ncvt, rwork( 1_${ik}$ ),rwork( n )& , vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_zlasr( 'R', 'V', 'F', nru, m-ll+1, rwork( nm12+1 ),rwork( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_zlasr( 'L', 'V', 'F', m-ll+1, ncc, rwork( nm12+1 ),rwork( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates f = ( abs( d( m ) )-shift )*( sign( one, d( m ) )+shift /d( m ) ) g = e( m-1 ) do i = m, ll + 1, -1 call stdlib${ii}$_dlartg( f, g, cosr, sinr, r ) if( ill+1 ) then g = sinl*e( i-2 ) e( i-2 ) = cosl*e( i-2 ) end if rwork( i-ll ) = cosr rwork( i-ll+nm1 ) = -sinr rwork( i-ll+nm12 ) = cosl rwork( i-ll+nm13 ) = -sinl end do e( ll ) = f ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero ! update singular vectors if desired if( ncvt>0_${ik}$ )call stdlib${ii}$_zlasr( 'L', 'V', 'B', m-ll+1, ncvt, rwork( nm12+1 ),& rwork( nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_zlasr( 'R', 'V', 'B', nru, m-ll+1, rwork( 1_${ik}$ ),rwork( n ), & u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_zlasr( 'L', 'V', 'B', m-ll+1, ncc, rwork( 1_${ik}$ ),rwork( n ), & c( ll, 1_${ik}$ ), ldc ) end if end if ! qr iteration finished, go back and check convergence go to 60 ! all singular values converged, so make them positive 160 continue do i = 1, n if( d( i )0_${ik}$ )call stdlib${ii}$_zdscal( ncvt, negone, vt( i, 1_${ik}$ ), ldvt ) end if end do ! sort the singular values into decreasing order (insertion sort on ! singular values, but only one transposition per singular vector) do i = 1, n - 1 ! scan for smallest d(i) isub = 1_${ik}$ smin = d( 1_${ik}$ ) do j = 2, n + 1 - i if( d( j )<=smin ) then isub = j smin = d( j ) end if end do if( isub/=n+1-i ) then ! swap singular values and vectors d( isub ) = d( n+1-i ) d( n+1-i ) = smin if( ncvt>0_${ik}$ )call stdlib${ii}$_zswap( ncvt, vt( isub, 1_${ik}$ ), ldvt, vt( n+1-i, 1_${ik}$ ),ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_zswap( nru, u( 1_${ik}$, isub ), 1_${ik}$, u( 1_${ik}$, n+1-i ), 1_${ik}$ ) if( ncc>0_${ik}$ )call stdlib${ii}$_zswap( ncc, c( isub, 1_${ik}$ ), ldc, c( n+1-i, 1_${ik}$ ), ldc ) end if end do go to 220 ! maximum number of iterations exceeded, failure to converge 200 continue info = 0_${ik}$ do i = 1, n - 1 if( e( i )/=zero )info = info + 1_${ik}$ end do 220 continue return end subroutine stdlib${ii}$_zbdsqr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$bdsqr( uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u,ldu, c, ldc, rwork,& !! ZBDSQR: computes the singular values and, optionally, the right and/or !! left singular vectors from the singular value decomposition (SVD) of !! a real N-by-N (upper or lower) bidiagonal matrix B using the implicit !! zero-shift QR algorithm. The SVD of B has the form !! B = Q * S * P**H !! where S is the diagonal matrix of singular values, Q is an orthogonal !! matrix of left singular vectors, and P is an orthogonal matrix of !! right singular vectors. If left singular vectors are requested, this !! subroutine actually returns U*Q instead of Q, and, if right singular !! vectors are requested, this subroutine returns P**H*VT instead of !! P**H, for given complex input matrices U and VT. When U and VT are !! the unitary matrices that reduce a general matrix A to bidiagonal !! form: A = U*B*VT, as computed by ZGEBRD, then !! A = (U*Q) * S * (P**H*VT) !! is the SVD of A. Optionally, the subroutine may also compute Q**H*C !! for a given complex input matrix C. !! See "Computing Small Singular Values of Bidiagonal Matrices With !! Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan, !! LAPACK Working Note #3 (or SIAM J. Sci. Statist. Comput. vol. 11, !! no. 5, pp. 873-912, Sept 1990) and !! "Accurate singular values and differential qd algorithms," by !! B. Parlett and V. Fernando, Technical Report CPAM-554, Mathematics !! Department, University of California at Berkeley, July 1992 !! for a detailed description of the algorithm. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc, ldu, ldvt, n, ncc, ncvt, nru ! Array Arguments real(${ck}$), intent(inout) :: d(*), e(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: c(ldc,*), u(ldu,*), vt(ldvt,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: hndrth = 0.01_${ck}$ real(${ck}$), parameter :: hndrd = 100.0_${ck}$ real(${ck}$), parameter :: meigth = -0.125_${ck}$ integer(${ik}$), parameter :: maxitr = 6_${ik}$ ! Local Scalars logical(lk) :: lower, rotate integer(${ik}$) :: i, idir, isub, iter, j, ll, lll, m, maxit, nm1, nm12, nm13, oldll, & oldm real(${ck}$) :: abse, abss, cosl, cosr, cs, eps, f, g, h, mu, oldcs, oldsn, r, shift, & sigmn, sigmx, sinl, sinr, sll, smax, smin, sminl, sminoa, sn, thresh, tol, tolmul, & unfl ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ lower = stdlib_lsame( uplo, 'L' ) if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.lower ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ncvt<0_${ik}$ ) then info = -3_${ik}$ else if( nru<0_${ik}$ ) then info = -4_${ik}$ else if( ncc<0_${ik}$ ) then info = -5_${ik}$ else if( ( ncvt==0_${ik}$ .and. ldvt<1_${ik}$ ) .or.( ncvt>0_${ik}$ .and. ldvt0_${ik}$ .and. ldc0_${ik}$ ) .or. ( nru>0_${ik}$ ) .or. ( ncc>0_${ik}$ ) ! if no singular vectors desired, use qd algorithm if( .not.rotate ) then call stdlib${ii}$_${c2ri(ci)}$lasq1( n, d, e, rwork, info ) ! if info equals 2, dqds didn't finish, try to finish if( info /= 2 ) return info = 0_${ik}$ end if nm1 = n - 1_${ik}$ nm12 = nm1 + nm1 nm13 = nm12 + nm1 idir = 0_${ik}$ ! get machine constants eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'EPSILON' ) unfl = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) ! if matrix lower bidiagonal, rotate to be upper bidiagonal ! by applying givens rotations on the left if( lower ) then do i = 1, n - 1 call stdlib${ii}$_${c2ri(ci)}$lartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) rwork( i ) = cs rwork( nm1+i ) = sn end do ! update singular vectors if desired if( nru>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'F', nru, n, rwork( 1_${ik}$ ), rwork( n ),u, ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'F', n, ncc, rwork( 1_${ik}$ ), rwork( n ),c, ldc ) end if ! compute singular values to relative accuracy tol ! (by setting tol to be negative, algorithm will compute ! singular values to absolute accuracy abs(tol)*norm(input matrix)) tolmul = max( ten, min( hndrd, eps**meigth ) ) tol = tolmul*eps ! compute approximate maximum, minimum singular values smax = zero do i = 1, n smax = max( smax, abs( d( i ) ) ) end do do i = 1, n - 1 smax = max( smax, abs( e( i ) ) ) end do sminl = zero if( tol>=zero ) then ! relative accuracy desired sminoa = abs( d( 1_${ik}$ ) ) if( sminoa==zero )go to 50 mu = sminoa do i = 2, n mu = abs( d( i ) )*( mu / ( mu+abs( e( i-1 ) ) ) ) sminoa = min( sminoa, mu ) if( sminoa==zero )go to 50 end do 50 continue sminoa = sminoa / sqrt( real( n,KIND=${ck}$) ) thresh = max( tol*sminoa, maxitr*n*n*unfl ) else ! absolute accuracy desired thresh = max( abs( tol )*smax, maxitr*n*n*unfl ) end if ! prepare for main iteration loop for the singular values ! (maxit is the maximum number of passes through the inner ! loop permitted before nonconvergence signalled.) maxit = maxitr*n*n iter = 0_${ik}$ oldll = -1_${ik}$ oldm = -1_${ik}$ ! m points to last element of unconverged part of matrix m = n ! begin main iteration loop 60 continue ! check for convergence or exceeding iteration count if( m<=1 )go to 160 if( iter>maxit )go to 200 ! find diagonal block of matrix to work on if( tol0_${ik}$ )call stdlib${ii}$_${ci}$drot( ncvt, vt( m-1, 1_${ik}$ ), ldvt, vt( m, 1_${ik}$ ), ldvt,cosr, & sinr ) if( nru>0_${ik}$ )call stdlib${ii}$_${ci}$drot( nru, u( 1_${ik}$, m-1 ), 1_${ik}$, u( 1_${ik}$, m ), 1_${ik}$, cosl, sinl ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ci}$drot( ncc, c( m-1, 1_${ik}$ ), ldc, c( m, 1_${ik}$ ), ldc, cosl,sinl ) m = m - 2_${ik}$ go to 60 end if ! if working on new submatrix, choose shift direction ! (from larger end diagonal element towards smaller) if( ll>oldm .or. m=abs( d( m ) ) ) then ! chase bulge from top (big end) to bottom (small end) idir = 1_${ik}$ else ! chase bulge from bottom (big end) to top (small end) idir = 2_${ik}$ end if end if ! apply convergence tests if( idir==1_${ik}$ ) then ! run convergence test in forward direction ! first apply standard test to bottom of matrix if( abs( e( m-1 ) )<=abs( tol )*abs( d( m ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion forward mu = abs( d( ll ) ) sminl = mu do lll = ll, m - 1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll+1 ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if else ! run convergence test in backward direction ! first apply standard test to top of matrix if( abs( e( ll ) )<=abs( tol )*abs( d( ll ) ) .or.( tol=zero ) then ! if relative accuracy desired, ! apply convergence criterion backward mu = abs( d( m ) ) sminl = mu do lll = m - 1, ll, -1 if( abs( e( lll ) )<=tol*mu ) then e( lll ) = zero go to 60 end if mu = abs( d( lll ) )*( mu / ( mu+abs( e( lll ) ) ) ) sminl = min( sminl, mu ) end do end if end if oldll = ll oldm = m ! compute shift. first, test if shifting would ruin relative ! accuracy, and if so set the shift to zero. if( tol>=zero .and. n*tol*( sminl / smax )<=max( eps, hndrth*tol ) ) then ! use a zero shift to avoid loss of relative accuracy shift = zero else ! compute the shift from 2-by-2 block at end of matrix if( idir==1_${ik}$ ) then sll = abs( d( ll ) ) call stdlib${ii}$_${c2ri(ci)}$las2( d( m-1 ), e( m-1 ), d( m ), shift, r ) else sll = abs( d( m ) ) call stdlib${ii}$_${c2ri(ci)}$las2( d( ll ), e( ll ), d( ll+1 ), shift, r ) end if ! test if shift negligible, and if so set to zero if( sll>zero ) then if( ( shift / sll )**2_${ik}$ll )e( i-1 ) = oldsn*r call stdlib${ii}$_${c2ri(ci)}$lartg( oldcs*r, d( i+1 )*sn, oldcs, oldsn, d( i ) ) rwork( i-ll+1 ) = cs rwork( i-ll+1+nm1 ) = sn rwork( i-ll+1+nm12 ) = oldcs rwork( i-ll+1+nm13 ) = oldsn end do h = d( m )*cs d( m ) = h*oldcs e( m-1 ) = h*oldsn ! update singular vectors if( ncvt>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'F', m-ll+1, ncvt, rwork( 1_${ik}$ ),rwork( n )& , vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'F', nru, m-ll+1, rwork( nm12+1 ),rwork( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'F', m-ll+1, ncc, rwork( nm12+1 ),rwork( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates cs = one oldcs = one do i = m, ll + 1, -1 call stdlib${ii}$_${c2ri(ci)}$lartg( d( i )*cs, e( i-1 ), cs, sn, r ) if( i0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'B', m-ll+1, ncvt, rwork( nm12+1 ),& rwork( nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'B', nru, m-ll+1, rwork( 1_${ik}$ ),rwork( n ), & u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'B', m-ll+1, ncc, rwork( 1_${ik}$ ),rwork( n ), & c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero end if else ! use nonzero shift if( idir==1_${ik}$ ) then ! chase bulge from top to bottom ! save cosines and sines for later singular vector updates f = ( abs( d( ll ) )-shift )*( sign( one, d( ll ) )+shift / d( ll ) ) g = e( ll ) do i = ll, m - 1 call stdlib${ii}$_${c2ri(ci)}$lartg( f, g, cosr, sinr, r ) if( i>ll )e( i-1 ) = r f = cosr*d( i ) + sinr*e( i ) e( i ) = cosr*e( i ) - sinr*d( i ) g = sinr*d( i+1 ) d( i+1 ) = cosr*d( i+1 ) call stdlib${ii}$_${c2ri(ci)}$lartg( f, g, cosl, sinl, r ) d( i ) = r f = cosl*e( i ) + sinl*d( i+1 ) d( i+1 ) = cosl*d( i+1 ) - sinl*e( i ) if( i0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'F', m-ll+1, ncvt, rwork( 1_${ik}$ ),rwork( n )& , vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'F', nru, m-ll+1, rwork( nm12+1 ),rwork( & nm13+1 ), u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'F', m-ll+1, ncc, rwork( nm12+1 ),rwork( & nm13+1 ), c( ll, 1_${ik}$ ), ldc ) ! test convergence if( abs( e( m-1 ) )<=thresh )e( m-1 ) = zero else ! chase bulge from bottom to top ! save cosines and sines for later singular vector updates f = ( abs( d( m ) )-shift )*( sign( one, d( m ) )+shift /d( m ) ) g = e( m-1 ) do i = m, ll + 1, -1 call stdlib${ii}$_${c2ri(ci)}$lartg( f, g, cosr, sinr, r ) if( ill+1 ) then g = sinl*e( i-2 ) e( i-2 ) = cosl*e( i-2 ) end if rwork( i-ll ) = cosr rwork( i-ll+nm1 ) = -sinr rwork( i-ll+nm12 ) = cosl rwork( i-ll+nm13 ) = -sinl end do e( ll ) = f ! test convergence if( abs( e( ll ) )<=thresh )e( ll ) = zero ! update singular vectors if desired if( ncvt>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'B', m-ll+1, ncvt, rwork( nm12+1 ),& rwork( nm13+1 ), vt( ll, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'B', nru, m-ll+1, rwork( 1_${ik}$ ),rwork( n ), & u( 1_${ik}$, ll ), ldu ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'B', m-ll+1, ncc, rwork( 1_${ik}$ ),rwork( n ), & c( ll, 1_${ik}$ ), ldc ) end if end if ! qr iteration finished, go back and check convergence go to 60 ! all singular values converged, so make them positive 160 continue do i = 1, n if( d( i )0_${ik}$ )call stdlib${ii}$_${ci}$dscal( ncvt, negone, vt( i, 1_${ik}$ ), ldvt ) end if end do ! sort the singular values into decreasing order (insertion sort on ! singular values, but only one transposition per singular vector) do i = 1, n - 1 ! scan for smallest d(i) isub = 1_${ik}$ smin = d( 1_${ik}$ ) do j = 2, n + 1 - i if( d( j )<=smin ) then isub = j smin = d( j ) end if end do if( isub/=n+1-i ) then ! swap singular values and vectors d( isub ) = d( n+1-i ) d( n+1-i ) = smin if( ncvt>0_${ik}$ )call stdlib${ii}$_${ci}$swap( ncvt, vt( isub, 1_${ik}$ ), ldvt, vt( n+1-i, 1_${ik}$ ),ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_${ci}$swap( nru, u( 1_${ik}$, isub ), 1_${ik}$, u( 1_${ik}$, n+1-i ), 1_${ik}$ ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ci}$swap( ncc, c( isub, 1_${ik}$ ), ldc, c( n+1-i, 1_${ik}$ ), ldc ) end if end do go to 220 ! maximum number of iterations exceeded, failure to converge 200 continue info = 0_${ik}$ do i = 1, n - 1 if( e( i )/=zero )info = info + 1_${ik}$ end do 220 continue return end subroutine stdlib${ii}$_${ci}$bdsqr #:endif #:endfor pure module subroutine stdlib${ii}$_sbdsdc( uplo, compq, n, d, e, u, ldu, vt, ldvt, q, iq,work, iwork, & !! SBDSDC computes the singular value decomposition (SVD) of a real !! N-by-N (upper or lower) bidiagonal matrix B: B = U * S * VT, !! using a divide and conquer method, where S is a diagonal matrix !! with non-negative diagonal elements (the singular values of B), and !! U and VT are orthogonal matrices of left and right singular vectors, !! respectively. SBDSDC can be used to compute all singular values, !! and optionally, singular vectors or singular vectors in compact form. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or Cray-2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. See SLASD3 for details. !! The code currently calls SLASDQ if singular values only are desired. !! However, it can be slightly modified to compute singular values !! using the divide and conquer method. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compq, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu, ldvt, n ! Array Arguments integer(${ik}$), intent(out) :: iq(*), iwork(*) real(sp), intent(inout) :: d(*), e(*) real(sp), intent(out) :: q(*), u(ldu,*), vt(ldvt,*), work(*) ! ===================================================================== ! changed dimension statement in comment describing e from (n) to ! (n-1). sven, 17 feb 05. ! ===================================================================== ! Local Scalars integer(${ik}$) :: difl, difr, givcol, givnum, givptr, i, ic, icompq, ierr, ii, is, iu, & iuplo, ivt, j, k, kk, mlvl, nm1, nsize, perm, poles, qstart, smlsiz, smlszp, sqre, & start, wstart, z real(sp) :: cs, eps, orgnrm, p, r, sn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ iuplo = 0_${ik}$ if( stdlib_lsame( uplo, 'U' ) )iuplo = 1_${ik}$ if( stdlib_lsame( uplo, 'L' ) )iuplo = 2_${ik}$ if( stdlib_lsame( compq, 'N' ) ) then icompq = 0_${ik}$ else if( stdlib_lsame( compq, 'P' ) ) then icompq = 1_${ik}$ else if( stdlib_lsame( compq, 'I' ) ) then icompq = 2_${ik}$ else icompq = -1_${ik}$ end if if( iuplo==0_${ik}$ ) then info = -1_${ik}$ else if( icompq<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ( ldu<1_${ik}$ ) .or. ( ( icompq==2_${ik}$ ) .and. ( ldu=eps ) then ! a subproblem with e(nm1) not too small but i = nm1. nsize = n - start + 1_${ik}$ else ! a subproblem with e(nm1) small. this implies an ! 1-by-1 subproblem at d(n). solve this 1-by-1 problem ! first. nsize = i - start + 1_${ik}$ if( icompq==2_${ik}$ ) then u( n, n ) = sign( one, d( n ) ) vt( n, n ) = one else if( icompq==1_${ik}$ ) then q( n+( qstart-1 )*n ) = sign( one, d( n ) ) q( n+( smlsiz+qstart-1 )*n ) = one end if d( n ) = abs( d( n ) ) end if if( icompq==2_${ik}$ ) then call stdlib${ii}$_slasd0( nsize, sqre, d( start ), e( start ),u( start, start ), & ldu, vt( start, start ),ldvt, smlsiz, iwork, work( wstart ), info ) else call stdlib${ii}$_slasda( icompq, smlsiz, nsize, sqre, d( start ),e( start ), q( & start+( iu+qstart-2 )*n ), n,q( start+( ivt+qstart-2 )*n ),iq( start+k*n ), q(& start+( difl+qstart-2 )*n ), q( start+( difr+qstart-2 )*n ),q( start+( z+& qstart-2 )*n ),q( start+( poles+qstart-2 )*n ),iq( start+givptr*n ), iq( & start+givcol*n ),n, iq( start+perm*n ),q( start+( givnum+qstart-2 )*n ),q( & start+( ic+qstart-2 )*n ),q( start+( is+qstart-2 )*n ),work( wstart ), iwork,& info ) end if if( info/=0_${ik}$ ) then return end if start = i + 1_${ik}$ end if end do loop_30 ! unscale call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, ierr ) 40 continue ! use selection sort to minimize swaps of singular vectors do ii = 2, n i = ii - 1_${ik}$ kk = i p = d( i ) do j = ii, n if( d( j )>p ) then kk = j p = d( j ) end if end do if( kk/=i ) then d( kk ) = d( i ) d( i ) = p if( icompq==1_${ik}$ ) then iq( i ) = kk else if( icompq==2_${ik}$ ) then call stdlib${ii}$_sswap( n, u( 1_${ik}$, i ), 1_${ik}$, u( 1_${ik}$, kk ), 1_${ik}$ ) call stdlib${ii}$_sswap( n, vt( i, 1_${ik}$ ), ldvt, vt( kk, 1_${ik}$ ), ldvt ) end if else if( icompq==1_${ik}$ ) then iq( i ) = i end if end do ! if icompq = 1, use iq(n,1) as the indicator for uplo if( icompq==1_${ik}$ ) then if( iuplo==1_${ik}$ ) then iq( n ) = 1_${ik}$ else iq( n ) = 0_${ik}$ end if end if ! if b is lower bidiagonal, update u by those givens rotations ! which rotated b to be upper bidiagonal if( ( iuplo==2_${ik}$ ) .and. ( icompq==2_${ik}$ ) )call stdlib${ii}$_slasr( 'L', 'V', 'B', n, n, work( 1_${ik}$ )& , work( n ), u, ldu ) return end subroutine stdlib${ii}$_sbdsdc pure module subroutine stdlib${ii}$_dbdsdc( uplo, compq, n, d, e, u, ldu, vt, ldvt, q, iq,work, iwork, & !! DBDSDC computes the singular value decomposition (SVD) of a real !! N-by-N (upper or lower) bidiagonal matrix B: B = U * S * VT, !! using a divide and conquer method, where S is a diagonal matrix !! with non-negative diagonal elements (the singular values of B), and !! U and VT are orthogonal matrices of left and right singular vectors, !! respectively. DBDSDC can be used to compute all singular values, !! and optionally, singular vectors or singular vectors in compact form. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or Cray-2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. See DLASD3 for details. !! The code currently calls DLASDQ if singular values only are desired. !! However, it can be slightly modified to compute singular values !! using the divide and conquer method. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compq, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu, ldvt, n ! Array Arguments integer(${ik}$), intent(out) :: iq(*), iwork(*) real(dp), intent(inout) :: d(*), e(*) real(dp), intent(out) :: q(*), u(ldu,*), vt(ldvt,*), work(*) ! ===================================================================== ! changed dimension statement in comment describing e from (n) to ! (n-1). sven, 17 feb 05. ! ===================================================================== ! Local Scalars integer(${ik}$) :: difl, difr, givcol, givnum, givptr, i, ic, icompq, ierr, ii, is, iu, & iuplo, ivt, j, k, kk, mlvl, nm1, nsize, perm, poles, qstart, smlsiz, smlszp, sqre, & start, wstart, z real(dp) :: cs, eps, orgnrm, p, r, sn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ iuplo = 0_${ik}$ if( stdlib_lsame( uplo, 'U' ) )iuplo = 1_${ik}$ if( stdlib_lsame( uplo, 'L' ) )iuplo = 2_${ik}$ if( stdlib_lsame( compq, 'N' ) ) then icompq = 0_${ik}$ else if( stdlib_lsame( compq, 'P' ) ) then icompq = 1_${ik}$ else if( stdlib_lsame( compq, 'I' ) ) then icompq = 2_${ik}$ else icompq = -1_${ik}$ end if if( iuplo==0_${ik}$ ) then info = -1_${ik}$ else if( icompq<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ( ldu<1_${ik}$ ) .or. ( ( icompq==2_${ik}$ ) .and. ( ldu=eps ) then ! a subproblem with e(nm1) not too small but i = nm1. nsize = n - start + 1_${ik}$ else ! a subproblem with e(nm1) small. this implies an ! 1-by-1 subproblem at d(n). solve this 1-by-1 problem ! first. nsize = i - start + 1_${ik}$ if( icompq==2_${ik}$ ) then u( n, n ) = sign( one, d( n ) ) vt( n, n ) = one else if( icompq==1_${ik}$ ) then q( n+( qstart-1 )*n ) = sign( one, d( n ) ) q( n+( smlsiz+qstart-1 )*n ) = one end if d( n ) = abs( d( n ) ) end if if( icompq==2_${ik}$ ) then call stdlib${ii}$_dlasd0( nsize, sqre, d( start ), e( start ),u( start, start ), & ldu, vt( start, start ),ldvt, smlsiz, iwork, work( wstart ), info ) else call stdlib${ii}$_dlasda( icompq, smlsiz, nsize, sqre, d( start ),e( start ), q( & start+( iu+qstart-2 )*n ), n,q( start+( ivt+qstart-2 )*n ),iq( start+k*n ), q(& start+( difl+qstart-2 )*n ), q( start+( difr+qstart-2 )*n ),q( start+( z+& qstart-2 )*n ),q( start+( poles+qstart-2 )*n ),iq( start+givptr*n ), iq( & start+givcol*n ),n, iq( start+perm*n ),q( start+( givnum+qstart-2 )*n ),q( & start+( ic+qstart-2 )*n ),q( start+( is+qstart-2 )*n ),work( wstart ), iwork,& info ) end if if( info/=0_${ik}$ ) then return end if start = i + 1_${ik}$ end if end do loop_30 ! unscale call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, ierr ) 40 continue ! use selection sort to minimize swaps of singular vectors do ii = 2, n i = ii - 1_${ik}$ kk = i p = d( i ) do j = ii, n if( d( j )>p ) then kk = j p = d( j ) end if end do if( kk/=i ) then d( kk ) = d( i ) d( i ) = p if( icompq==1_${ik}$ ) then iq( i ) = kk else if( icompq==2_${ik}$ ) then call stdlib${ii}$_dswap( n, u( 1_${ik}$, i ), 1_${ik}$, u( 1_${ik}$, kk ), 1_${ik}$ ) call stdlib${ii}$_dswap( n, vt( i, 1_${ik}$ ), ldvt, vt( kk, 1_${ik}$ ), ldvt ) end if else if( icompq==1_${ik}$ ) then iq( i ) = i end if end do ! if icompq = 1, use iq(n,1) as the indicator for uplo if( icompq==1_${ik}$ ) then if( iuplo==1_${ik}$ ) then iq( n ) = 1_${ik}$ else iq( n ) = 0_${ik}$ end if end if ! if b is lower bidiagonal, update u by those givens rotations ! which rotated b to be upper bidiagonal if( ( iuplo==2_${ik}$ ) .and. ( icompq==2_${ik}$ ) )call stdlib${ii}$_dlasr( 'L', 'V', 'B', n, n, work( 1_${ik}$ )& , work( n ), u, ldu ) return end subroutine stdlib${ii}$_dbdsdc #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$bdsdc( uplo, compq, n, d, e, u, ldu, vt, ldvt, q, iq,work, iwork, & !! DBDSDC: computes the singular value decomposition (SVD) of a real !! N-by-N (upper or lower) bidiagonal matrix B: B = U * S * VT, !! using a divide and conquer method, where S is a diagonal matrix !! with non-negative diagonal elements (the singular values of B), and !! U and VT are orthogonal matrices of left and right singular vectors, !! respectively. DBDSDC can be used to compute all singular values, !! and optionally, singular vectors or singular vectors in compact form. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or Cray-2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. See DLASD3 for details. !! The code currently calls DLASDQ if singular values only are desired. !! However, it can be slightly modified to compute singular values !! using the divide and conquer method. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compq, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu, ldvt, n ! Array Arguments integer(${ik}$), intent(out) :: iq(*), iwork(*) real(${rk}$), intent(inout) :: d(*), e(*) real(${rk}$), intent(out) :: q(*), u(ldu,*), vt(ldvt,*), work(*) ! ===================================================================== ! changed dimension statement in comment describing e from (n) to ! (n-1). sven, 17 feb 05. ! ===================================================================== ! Local Scalars integer(${ik}$) :: difl, difr, givcol, givnum, givptr, i, ic, icompq, ierr, ii, is, iu, & iuplo, ivt, j, k, kk, mlvl, nm1, nsize, perm, poles, qstart, smlsiz, smlszp, sqre, & start, wstart, z real(${rk}$) :: cs, eps, orgnrm, p, r, sn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ iuplo = 0_${ik}$ if( stdlib_lsame( uplo, 'U' ) )iuplo = 1_${ik}$ if( stdlib_lsame( uplo, 'L' ) )iuplo = 2_${ik}$ if( stdlib_lsame( compq, 'N' ) ) then icompq = 0_${ik}$ else if( stdlib_lsame( compq, 'P' ) ) then icompq = 1_${ik}$ else if( stdlib_lsame( compq, 'I' ) ) then icompq = 2_${ik}$ else icompq = -1_${ik}$ end if if( iuplo==0_${ik}$ ) then info = -1_${ik}$ else if( icompq<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ( ldu<1_${ik}$ ) .or. ( ( icompq==2_${ik}$ ) .and. ( ldu=eps ) then ! a subproblem with e(nm1) not too small but i = nm1. nsize = n - start + 1_${ik}$ else ! a subproblem with e(nm1) small. this implies an ! 1-by-1 subproblem at d(n). solve this 1-by-1 problem ! first. nsize = i - start + 1_${ik}$ if( icompq==2_${ik}$ ) then u( n, n ) = sign( one, d( n ) ) vt( n, n ) = one else if( icompq==1_${ik}$ ) then q( n+( qstart-1 )*n ) = sign( one, d( n ) ) q( n+( smlsiz+qstart-1 )*n ) = one end if d( n ) = abs( d( n ) ) end if if( icompq==2_${ik}$ ) then call stdlib${ii}$_${ri}$lasd0( nsize, sqre, d( start ), e( start ),u( start, start ), & ldu, vt( start, start ),ldvt, smlsiz, iwork, work( wstart ), info ) else call stdlib${ii}$_${ri}$lasda( icompq, smlsiz, nsize, sqre, d( start ),e( start ), q( & start+( iu+qstart-2 )*n ), n,q( start+( ivt+qstart-2 )*n ),iq( start+k*n ), q(& start+( difl+qstart-2 )*n ), q( start+( difr+qstart-2 )*n ),q( start+( z+& qstart-2 )*n ),q( start+( poles+qstart-2 )*n ),iq( start+givptr*n ), iq( & start+givcol*n ),n, iq( start+perm*n ),q( start+( givnum+qstart-2 )*n ),q( & start+( ic+qstart-2 )*n ),q( start+( is+qstart-2 )*n ),work( wstart ), iwork,& info ) end if if( info/=0_${ik}$ ) then return end if start = i + 1_${ik}$ end if end do loop_30 ! unscale call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, ierr ) 40 continue ! use selection sort to minimize swaps of singular vectors do ii = 2, n i = ii - 1_${ik}$ kk = i p = d( i ) do j = ii, n if( d( j )>p ) then kk = j p = d( j ) end if end do if( kk/=i ) then d( kk ) = d( i ) d( i ) = p if( icompq==1_${ik}$ ) then iq( i ) = kk else if( icompq==2_${ik}$ ) then call stdlib${ii}$_${ri}$swap( n, u( 1_${ik}$, i ), 1_${ik}$, u( 1_${ik}$, kk ), 1_${ik}$ ) call stdlib${ii}$_${ri}$swap( n, vt( i, 1_${ik}$ ), ldvt, vt( kk, 1_${ik}$ ), ldvt ) end if else if( icompq==1_${ik}$ ) then iq( i ) = i end if end do ! if icompq = 1, use iq(n,1) as the indicator for uplo if( icompq==1_${ik}$ ) then if( iuplo==1_${ik}$ ) then iq( n ) = 1_${ik}$ else iq( n ) = 0_${ik}$ end if end if ! if b is lower bidiagonal, update u by those givens rotations ! which rotated b to be upper bidiagonal if( ( iuplo==2_${ik}$ ) .and. ( icompq==2_${ik}$ ) )call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'B', n, n, work( 1_${ik}$ )& , work( n ), u, ldu ) return end subroutine stdlib${ii}$_${ri}$bdsdc #:endif #:endfor #:endfor end submodule stdlib_lapack_eigv_svd_drivers3 fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_eigv_gen3.fypp0000664000175000017500000365534215135654166025654 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_eigv_gen3 implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_slaqtr( ltran, lreal, n, t, ldt, b, w, scale, x, work,info ) !! SLAQTR solves the real quasi-triangular system !! op(T)*p = scale*c, if LREAL = .TRUE. !! or the complex quasi-triangular systems !! op(T + iB)*(p+iq) = scale*(c+id), if LREAL = .FALSE. !! in real arithmetic, where T is upper quasi-triangular. !! If LREAL = .FALSE., then the first diagonal block of T must be !! 1 by 1, B is the specially structured matrix !! B = [ b(1) b(2) ... b(n) ] !! [ w ] !! [ w ] !! [ . ] !! [ w ] !! op(A) = A or A**T, A**T denotes the transpose of !! matrix A. !! On input, X = [ c ]. On output, X = [ p ]. !! [ d ] [ q ] !! This subroutine is designed for the condition number estimation !! in routine STRSNA. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: lreal, ltran integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldt, n real(sp), intent(out) :: scale real(sp), intent(in) :: w ! Array Arguments real(sp), intent(in) :: b(*), t(ldt,*) real(sp), intent(out) :: work(*) real(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran integer(${ik}$) :: i, ierr, j, j1, j2, jnext, k, n1, n2 real(sp) :: bignum, eps, rec, scaloc, si, smin, sminw, smlnum, sr, tjj, tmp, xj, xmax, & xnorm, z ! Local Arrays real(sp) :: d(2_${ik}$,2_${ik}$), v(2_${ik}$,2_${ik}$) ! Intrinsic Functions ! Executable Statements ! do not test the input parameters for errors notran = .not.ltran info = 0_${ik}$ ! quick return if possible if( n==0 )return ! set constants to control overflow eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) / eps bignum = one / smlnum xnorm = stdlib${ii}$_slange( 'M', n, n, t, ldt, d ) if( .not.lreal )xnorm = max( xnorm, abs( w ), stdlib${ii}$_slange( 'M', n, 1_${ik}$, b, n, d ) ) smin = max( smlnum, eps*xnorm ) ! compute 1-norm of each column of strictly upper triangular ! part of t to control overflow in triangular solver. work( 1_${ik}$ ) = zero do j = 2, n work( j ) = stdlib${ii}$_sasum( j-1, t( 1_${ik}$, j ), 1_${ik}$ ) end do if( .not.lreal ) then do i = 2, n work( i ) = work( i ) + abs( b( i ) ) end do end if n2 = 2_${ik}$*n n1 = n if( .not.lreal )n1 = n2 k = stdlib${ii}$_isamax( n1, x, 1_${ik}$ ) xmax = abs( x( k ) ) scale = one if( xmax>bignum ) then scale = bignum / xmax call stdlib${ii}$_sscal( n1, scale, x, 1_${ik}$ ) xmax = bignum end if if( lreal ) then if( notran ) then ! solve t*p = scale*c jnext = n loop_30: do j = n, 1, -1 if( j>jnext )cycle loop_30 j1 = j j2 = j jnext = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnext = j - 2_${ik}$ end if end if if( j1==j2 ) then ! meet 1 by 1 diagonal block ! scale to avoid overflow when computing ! x(j) = b(j)/t(j,j) xj = abs( x( j1 ) ) tjj = abs( t( j1, j1 ) ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) / tmp xj = abs( x( j1 ) ) ! scale x if necessary to avoid overflow when adding a ! multiple of column j1 of t. if( xj>one ) then rec = one / xj if( work( j1 )>( bignum-xmax )*rec ) then call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if end if if( j1>1_${ik}$ ) then call stdlib${ii}$_saxpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) k = stdlib${ii}$_isamax( j1-1, x, 1_${ik}$ ) xmax = abs( x( k ) ) end if else ! meet 2 by 2 diagonal block ! call 2 by 2 linear system solve, to take ! care of possible overflow by scaling factor. d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) call stdlib${ii}$_slaln2( .false., 2_${ik}$, 1_${ik}$, smin, one, t( j1, j1 ),ldt, one, one, d,& 2_${ik}$, zero, zero, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_sscal( n, scaloc, x, 1_${ik}$ ) scale = scale*scaloc end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) ! scale v(1,1) (= x(j1)) and/or v(2,1) (=x(j2)) ! to avoid overflow in updating right-hand side. xj = max( abs( v( 1_${ik}$, 1_${ik}$ ) ), abs( v( 2_${ik}$, 1_${ik}$ ) ) ) if( xj>one ) then rec = one / xj if( max( work( j1 ), work( j2 ) )>( bignum-xmax )*rec ) then call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if end if ! update right-hand side if( j1>1_${ik}$ ) then call stdlib${ii}$_saxpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_saxpy( j1-1, -x( j2 ), t( 1_${ik}$, j2 ), 1_${ik}$, x, 1_${ik}$ ) k = stdlib${ii}$_isamax( j1-1, x, 1_${ik}$ ) xmax = abs( x( k ) ) end if end if end do loop_30 else ! solve t**t*p = scale*c jnext = 1_${ik}$ loop_40: do j = 1, n if( jone ) then rec = one / xmax if( work( j1 )>( bignum-xj )*rec ) then call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) - stdlib${ii}$_sdot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) xj = abs( x( j1 ) ) tjj = abs( t( j1, j1 ) ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) / tmp xmax = max( xmax, abs( x( j1 ) ) ) else ! 2 by 2 diagonal block ! scale if necessary to avoid overflow in forming the ! right-hand side elements by inner product. xj = max( abs( x( j1 ) ), abs( x( j2 ) ) ) if( xmax>one ) then rec = one / xmax if( max( work( j2 ), work( j1 ) )>( bignum-xj )*rec ) then call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) - stdlib${ii}$_sdot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x,1_${ik}$ ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) - stdlib${ii}$_sdot( j1-1, t( 1_${ik}$, j2 ), 1_${ik}$, x,1_${ik}$ ) call stdlib${ii}$_slaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, t( j1, j1 ),ldt, one, one, d, & 2_${ik}$, zero, zero, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_sscal( n, scaloc, x, 1_${ik}$ ) scale = scale*scaloc end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) xmax = max( abs( x( j1 ) ), abs( x( j2 ) ), xmax ) end if end do loop_40 end if else sminw = max( eps*abs( w ), smin ) if( notran ) then ! solve (t + ib)*(p+iq) = c+id jnext = n loop_70: do j = n, 1, -1 if( j>jnext )cycle loop_70 j1 = j j2 = j jnext = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnext = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1 by 1 diagonal block ! scale if necessary to avoid overflow in division z = w if( j1==1_${ik}$ )z = b( 1_${ik}$ ) xj = abs( x( j1 ) ) + abs( x( n+j1 ) ) tjj = abs( t( j1, j1 ) ) + abs( z ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_sscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if call stdlib${ii}$_sladiv( x( j1 ), x( n+j1 ), tmp, z, sr, si ) x( j1 ) = sr x( n+j1 ) = si xj = abs( x( j1 ) ) + abs( x( n+j1 ) ) ! scale x if necessary to avoid overflow when adding a ! multiple of column j1 of t. if( xj>one ) then rec = one / xj if( work( j1 )>( bignum-xmax )*rec ) then call stdlib${ii}$_sscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec end if end if if( j1>1_${ik}$ ) then call stdlib${ii}$_saxpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_saxpy( j1-1, -x( n+j1 ), t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) x( 1_${ik}$ ) = x( 1_${ik}$ ) + b( j1 )*x( n+j1 ) x( n+1 ) = x( n+1 ) - b( j1 )*x( j1 ) xmax = zero do k = 1, j1 - 1 xmax = max( xmax, abs( x( k ) )+abs( x( k+n ) ) ) end do end if else ! meet 2 by 2 diagonal block d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) d( 1_${ik}$, 2_${ik}$ ) = x( n+j1 ) d( 2_${ik}$, 2_${ik}$ ) = x( n+j2 ) call stdlib${ii}$_slaln2( .false., 2_${ik}$, 2_${ik}$, sminw, one, t( j1, j1 ),ldt, one, one, & d, 2_${ik}$, zero, -w, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_sscal( 2_${ik}$*n, scaloc, x, 1_${ik}$ ) scale = scaloc*scale end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) x( n+j1 ) = v( 1_${ik}$, 2_${ik}$ ) x( n+j2 ) = v( 2_${ik}$, 2_${ik}$ ) ! scale x(j1), .... to avoid overflow in ! updating right hand side. xj = max( abs( v( 1_${ik}$, 1_${ik}$ ) )+abs( v( 1_${ik}$, 2_${ik}$ ) ),abs( v( 2_${ik}$, 1_${ik}$ ) )+abs( v( 2_${ik}$, 2_${ik}$ )& ) ) if( xj>one ) then rec = one / xj if( max( work( j1 ), work( j2 ) )>( bignum-xmax )*rec ) then call stdlib${ii}$_sscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec end if end if ! update the right-hand side. if( j1>1_${ik}$ ) then call stdlib${ii}$_saxpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_saxpy( j1-1, -x( j2 ), t( 1_${ik}$, j2 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_saxpy( j1-1, -x( n+j1 ), t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) call stdlib${ii}$_saxpy( j1-1, -x( n+j2 ), t( 1_${ik}$, j2 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) x( 1_${ik}$ ) = x( 1_${ik}$ ) + b( j1 )*x( n+j1 ) +b( j2 )*x( n+j2 ) x( n+1 ) = x( n+1 ) - b( j1 )*x( j1 ) -b( j2 )*x( j2 ) xmax = zero do k = 1, j1 - 1 xmax = max( abs( x( k ) )+abs( x( k+n ) ),xmax ) end do end if end if end do loop_70 else ! solve (t + ib)**t*(p+iq) = c+id jnext = 1_${ik}$ loop_80: do j = 1, n if( jone ) then rec = one / xmax if( work( j1 )>( bignum-xj )*rec ) then call stdlib${ii}$_sscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) - stdlib${ii}$_sdot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) x( n+j1 ) = x( n+j1 ) - stdlib${ii}$_sdot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) if( j1>1_${ik}$ ) then x( j1 ) = x( j1 ) - b( j1 )*x( n+1 ) x( n+j1 ) = x( n+j1 ) + b( j1 )*x( 1_${ik}$ ) end if xj = abs( x( j1 ) ) + abs( x( j1+n ) ) z = w if( j1==1_${ik}$ )z = b( 1_${ik}$ ) ! scale if necessary to avoid overflow in ! complex division tjj = abs( t( j1, j1 ) ) + abs( z ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_sscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if call stdlib${ii}$_sladiv( x( j1 ), x( n+j1 ), tmp, -z, sr, si ) x( j1 ) = sr x( j1+n ) = si xmax = max( abs( x( j1 ) )+abs( x( j1+n ) ), xmax ) else ! 2 by 2 diagonal block ! scale if necessary to avoid overflow in forming the ! right-hand side element by inner product. xj = max( abs( x( j1 ) )+abs( x( n+j1 ) ),abs( x( j2 ) )+abs( x( n+j2 ) ) ) if( xmax>one ) then rec = one / xmax if( max( work( j1 ), work( j2 ) )>( bignum-xj ) / xmax ) then call stdlib${ii}$_sscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) - stdlib${ii}$_sdot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x,1_${ik}$ ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) - stdlib${ii}$_sdot( j1-1, t( 1_${ik}$, j2 ), 1_${ik}$, x,1_${ik}$ ) d( 1_${ik}$, 2_${ik}$ ) = x( n+j1 ) - stdlib${ii}$_sdot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) d( 2_${ik}$, 2_${ik}$ ) = x( n+j2 ) - stdlib${ii}$_sdot( j1-1, t( 1_${ik}$, j2 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) d( 1_${ik}$, 1_${ik}$ ) = d( 1_${ik}$, 1_${ik}$ ) - b( j1 )*x( n+1 ) d( 2_${ik}$, 1_${ik}$ ) = d( 2_${ik}$, 1_${ik}$ ) - b( j2 )*x( n+1 ) d( 1_${ik}$, 2_${ik}$ ) = d( 1_${ik}$, 2_${ik}$ ) + b( j1 )*x( 1_${ik}$ ) d( 2_${ik}$, 2_${ik}$ ) = d( 2_${ik}$, 2_${ik}$ ) + b( j2 )*x( 1_${ik}$ ) call stdlib${ii}$_slaln2( .true., 2_${ik}$, 2_${ik}$, sminw, one, t( j1, j1 ),ldt, one, one, d,& 2_${ik}$, zero, w, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_sscal( n2, scaloc, x, 1_${ik}$ ) scale = scaloc*scale end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) x( n+j1 ) = v( 1_${ik}$, 2_${ik}$ ) x( n+j2 ) = v( 2_${ik}$, 2_${ik}$ ) xmax = max( abs( x( j1 ) )+abs( x( n+j1 ) ),abs( x( j2 ) )+abs( x( n+j2 ) )& , xmax ) end if end do loop_80 end if end if return end subroutine stdlib${ii}$_slaqtr module subroutine stdlib${ii}$_dlaqtr( ltran, lreal, n, t, ldt, b, w, scale, x, work,info ) !! DLAQTR solves the real quasi-triangular system !! op(T)*p = scale*c, if LREAL = .TRUE. !! or the complex quasi-triangular systems !! op(T + iB)*(p+iq) = scale*(c+id), if LREAL = .FALSE. !! in real arithmetic, where T is upper quasi-triangular. !! If LREAL = .FALSE., then the first diagonal block of T must be !! 1 by 1, B is the specially structured matrix !! B = [ b(1) b(2) ... b(n) ] !! [ w ] !! [ w ] !! [ . ] !! [ w ] !! op(A) = A or A**T, A**T denotes the transpose of !! matrix A. !! On input, X = [ c ]. On output, X = [ p ]. !! [ d ] [ q ] !! This subroutine is designed for the condition number estimation !! in routine DTRSNA. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: lreal, ltran integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldt, n real(dp), intent(out) :: scale real(dp), intent(in) :: w ! Array Arguments real(dp), intent(in) :: b(*), t(ldt,*) real(dp), intent(out) :: work(*) real(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran integer(${ik}$) :: i, ierr, j, j1, j2, jnext, k, n1, n2 real(dp) :: bignum, eps, rec, scaloc, si, smin, sminw, smlnum, sr, tjj, tmp, xj, xmax, & xnorm, z ! Local Arrays real(dp) :: d(2_${ik}$,2_${ik}$), v(2_${ik}$,2_${ik}$) ! Intrinsic Functions ! Executable Statements ! do not test the input parameters for errors notran = .not.ltran info = 0_${ik}$ ! quick return if possible if( n==0 )return ! set constants to control overflow eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) / eps bignum = one / smlnum xnorm = stdlib${ii}$_dlange( 'M', n, n, t, ldt, d ) if( .not.lreal )xnorm = max( xnorm, abs( w ), stdlib${ii}$_dlange( 'M', n, 1_${ik}$, b, n, d ) ) smin = max( smlnum, eps*xnorm ) ! compute 1-norm of each column of strictly upper triangular ! part of t to control overflow in triangular solver. work( 1_${ik}$ ) = zero do j = 2, n work( j ) = stdlib${ii}$_dasum( j-1, t( 1_${ik}$, j ), 1_${ik}$ ) end do if( .not.lreal ) then do i = 2, n work( i ) = work( i ) + abs( b( i ) ) end do end if n2 = 2_${ik}$*n n1 = n if( .not.lreal )n1 = n2 k = stdlib${ii}$_idamax( n1, x, 1_${ik}$ ) xmax = abs( x( k ) ) scale = one if( xmax>bignum ) then scale = bignum / xmax call stdlib${ii}$_dscal( n1, scale, x, 1_${ik}$ ) xmax = bignum end if if( lreal ) then if( notran ) then ! solve t*p = scale*c jnext = n loop_30: do j = n, 1, -1 if( j>jnext )cycle loop_30 j1 = j j2 = j jnext = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnext = j - 2_${ik}$ end if end if if( j1==j2 ) then ! meet 1 by 1 diagonal block ! scale to avoid overflow when computing ! x(j) = b(j)/t(j,j) xj = abs( x( j1 ) ) tjj = abs( t( j1, j1 ) ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) / tmp xj = abs( x( j1 ) ) ! scale x if necessary to avoid overflow when adding a ! multiple of column j1 of t. if( xj>one ) then rec = one / xj if( work( j1 )>( bignum-xmax )*rec ) then call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if end if if( j1>1_${ik}$ ) then call stdlib${ii}$_daxpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) k = stdlib${ii}$_idamax( j1-1, x, 1_${ik}$ ) xmax = abs( x( k ) ) end if else ! meet 2 by 2 diagonal block ! call 2 by 2 linear system solve, to take ! care of possible overflow by scaling factor. d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) call stdlib${ii}$_dlaln2( .false., 2_${ik}$, 1_${ik}$, smin, one, t( j1, j1 ),ldt, one, one, d,& 2_${ik}$, zero, zero, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_dscal( n, scaloc, x, 1_${ik}$ ) scale = scale*scaloc end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) ! scale v(1,1) (= x(j1)) and/or v(2,1) (=x(j2)) ! to avoid overflow in updating right-hand side. xj = max( abs( v( 1_${ik}$, 1_${ik}$ ) ), abs( v( 2_${ik}$, 1_${ik}$ ) ) ) if( xj>one ) then rec = one / xj if( max( work( j1 ), work( j2 ) )>( bignum-xmax )*rec ) then call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if end if ! update right-hand side if( j1>1_${ik}$ ) then call stdlib${ii}$_daxpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_daxpy( j1-1, -x( j2 ), t( 1_${ik}$, j2 ), 1_${ik}$, x, 1_${ik}$ ) k = stdlib${ii}$_idamax( j1-1, x, 1_${ik}$ ) xmax = abs( x( k ) ) end if end if end do loop_30 else ! solve t**t*p = scale*c jnext = 1_${ik}$ loop_40: do j = 1, n if( jone ) then rec = one / xmax if( work( j1 )>( bignum-xj )*rec ) then call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) - stdlib${ii}$_ddot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) xj = abs( x( j1 ) ) tjj = abs( t( j1, j1 ) ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) / tmp xmax = max( xmax, abs( x( j1 ) ) ) else ! 2 by 2 diagonal block ! scale if necessary to avoid overflow in forming the ! right-hand side elements by inner product. xj = max( abs( x( j1 ) ), abs( x( j2 ) ) ) if( xmax>one ) then rec = one / xmax if( max( work( j2 ), work( j1 ) )>( bignum-xj )*rec ) then call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) - stdlib${ii}$_ddot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x,1_${ik}$ ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) - stdlib${ii}$_ddot( j1-1, t( 1_${ik}$, j2 ), 1_${ik}$, x,1_${ik}$ ) call stdlib${ii}$_dlaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, t( j1, j1 ),ldt, one, one, d, & 2_${ik}$, zero, zero, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_dscal( n, scaloc, x, 1_${ik}$ ) scale = scale*scaloc end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) xmax = max( abs( x( j1 ) ), abs( x( j2 ) ), xmax ) end if end do loop_40 end if else sminw = max( eps*abs( w ), smin ) if( notran ) then ! solve (t + ib)*(p+iq) = c+id jnext = n loop_70: do j = n, 1, -1 if( j>jnext )cycle loop_70 j1 = j j2 = j jnext = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnext = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1 by 1 diagonal block ! scale if necessary to avoid overflow in division z = w if( j1==1_${ik}$ )z = b( 1_${ik}$ ) xj = abs( x( j1 ) ) + abs( x( n+j1 ) ) tjj = abs( t( j1, j1 ) ) + abs( z ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_dscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if call stdlib${ii}$_dladiv( x( j1 ), x( n+j1 ), tmp, z, sr, si ) x( j1 ) = sr x( n+j1 ) = si xj = abs( x( j1 ) ) + abs( x( n+j1 ) ) ! scale x if necessary to avoid overflow when adding a ! multiple of column j1 of t. if( xj>one ) then rec = one / xj if( work( j1 )>( bignum-xmax )*rec ) then call stdlib${ii}$_dscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec end if end if if( j1>1_${ik}$ ) then call stdlib${ii}$_daxpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_daxpy( j1-1, -x( n+j1 ), t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) x( 1_${ik}$ ) = x( 1_${ik}$ ) + b( j1 )*x( n+j1 ) x( n+1 ) = x( n+1 ) - b( j1 )*x( j1 ) xmax = zero do k = 1, j1 - 1 xmax = max( xmax, abs( x( k ) )+abs( x( k+n ) ) ) end do end if else ! meet 2 by 2 diagonal block d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) d( 1_${ik}$, 2_${ik}$ ) = x( n+j1 ) d( 2_${ik}$, 2_${ik}$ ) = x( n+j2 ) call stdlib${ii}$_dlaln2( .false., 2_${ik}$, 2_${ik}$, sminw, one, t( j1, j1 ),ldt, one, one, & d, 2_${ik}$, zero, -w, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_dscal( 2_${ik}$*n, scaloc, x, 1_${ik}$ ) scale = scaloc*scale end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) x( n+j1 ) = v( 1_${ik}$, 2_${ik}$ ) x( n+j2 ) = v( 2_${ik}$, 2_${ik}$ ) ! scale x(j1), .... to avoid overflow in ! updating right hand side. xj = max( abs( v( 1_${ik}$, 1_${ik}$ ) )+abs( v( 1_${ik}$, 2_${ik}$ ) ),abs( v( 2_${ik}$, 1_${ik}$ ) )+abs( v( 2_${ik}$, 2_${ik}$ )& ) ) if( xj>one ) then rec = one / xj if( max( work( j1 ), work( j2 ) )>( bignum-xmax )*rec ) then call stdlib${ii}$_dscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec end if end if ! update the right-hand side. if( j1>1_${ik}$ ) then call stdlib${ii}$_daxpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_daxpy( j1-1, -x( j2 ), t( 1_${ik}$, j2 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_daxpy( j1-1, -x( n+j1 ), t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) call stdlib${ii}$_daxpy( j1-1, -x( n+j2 ), t( 1_${ik}$, j2 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) x( 1_${ik}$ ) = x( 1_${ik}$ ) + b( j1 )*x( n+j1 ) +b( j2 )*x( n+j2 ) x( n+1 ) = x( n+1 ) - b( j1 )*x( j1 ) -b( j2 )*x( j2 ) xmax = zero do k = 1, j1 - 1 xmax = max( abs( x( k ) )+abs( x( k+n ) ),xmax ) end do end if end if end do loop_70 else ! solve (t + ib)**t*(p+iq) = c+id jnext = 1_${ik}$ loop_80: do j = 1, n if( jone ) then rec = one / xmax if( work( j1 )>( bignum-xj )*rec ) then call stdlib${ii}$_dscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) - stdlib${ii}$_ddot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) x( n+j1 ) = x( n+j1 ) - stdlib${ii}$_ddot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) if( j1>1_${ik}$ ) then x( j1 ) = x( j1 ) - b( j1 )*x( n+1 ) x( n+j1 ) = x( n+j1 ) + b( j1 )*x( 1_${ik}$ ) end if xj = abs( x( j1 ) ) + abs( x( j1+n ) ) z = w if( j1==1_${ik}$ )z = b( 1_${ik}$ ) ! scale if necessary to avoid overflow in ! complex division tjj = abs( t( j1, j1 ) ) + abs( z ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_dscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if call stdlib${ii}$_dladiv( x( j1 ), x( n+j1 ), tmp, -z, sr, si ) x( j1 ) = sr x( j1+n ) = si xmax = max( abs( x( j1 ) )+abs( x( j1+n ) ), xmax ) else ! 2 by 2 diagonal block ! scale if necessary to avoid overflow in forming the ! right-hand side element by inner product. xj = max( abs( x( j1 ) )+abs( x( n+j1 ) ),abs( x( j2 ) )+abs( x( n+j2 ) ) ) if( xmax>one ) then rec = one / xmax if( max( work( j1 ), work( j2 ) )>( bignum-xj ) / xmax ) then call stdlib${ii}$_dscal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) - stdlib${ii}$_ddot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x,1_${ik}$ ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) - stdlib${ii}$_ddot( j1-1, t( 1_${ik}$, j2 ), 1_${ik}$, x,1_${ik}$ ) d( 1_${ik}$, 2_${ik}$ ) = x( n+j1 ) - stdlib${ii}$_ddot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) d( 2_${ik}$, 2_${ik}$ ) = x( n+j2 ) - stdlib${ii}$_ddot( j1-1, t( 1_${ik}$, j2 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) d( 1_${ik}$, 1_${ik}$ ) = d( 1_${ik}$, 1_${ik}$ ) - b( j1 )*x( n+1 ) d( 2_${ik}$, 1_${ik}$ ) = d( 2_${ik}$, 1_${ik}$ ) - b( j2 )*x( n+1 ) d( 1_${ik}$, 2_${ik}$ ) = d( 1_${ik}$, 2_${ik}$ ) + b( j1 )*x( 1_${ik}$ ) d( 2_${ik}$, 2_${ik}$ ) = d( 2_${ik}$, 2_${ik}$ ) + b( j2 )*x( 1_${ik}$ ) call stdlib${ii}$_dlaln2( .true., 2_${ik}$, 2_${ik}$, sminw, one, t( j1, j1 ),ldt, one, one, d,& 2_${ik}$, zero, w, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_dscal( n2, scaloc, x, 1_${ik}$ ) scale = scaloc*scale end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) x( n+j1 ) = v( 1_${ik}$, 2_${ik}$ ) x( n+j2 ) = v( 2_${ik}$, 2_${ik}$ ) xmax = max( abs( x( j1 ) )+abs( x( n+j1 ) ),abs( x( j2 ) )+abs( x( n+j2 ) )& , xmax ) end if end do loop_80 end if end if return end subroutine stdlib${ii}$_dlaqtr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$laqtr( ltran, lreal, n, t, ldt, b, w, scale, x, work,info ) !! DLAQTR: solves the real quasi-triangular system !! op(T)*p = scale*c, if LREAL = .TRUE. !! or the complex quasi-triangular systems !! op(T + iB)*(p+iq) = scale*(c+id), if LREAL = .FALSE. !! in real arithmetic, where T is upper quasi-triangular. !! If LREAL = .FALSE., then the first diagonal block of T must be !! 1 by 1, B is the specially structured matrix !! B = [ b(1) b(2) ... b(n) ] !! [ w ] !! [ w ] !! [ . ] !! [ w ] !! op(A) = A or A**T, A**T denotes the transpose of !! matrix A. !! On input, X = [ c ]. On output, X = [ p ]. !! [ d ] [ q ] !! This subroutine is designed for the condition number estimation !! in routine DTRSNA. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: lreal, ltran integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldt, n real(${rk}$), intent(out) :: scale real(${rk}$), intent(in) :: w ! Array Arguments real(${rk}$), intent(in) :: b(*), t(ldt,*) real(${rk}$), intent(out) :: work(*) real(${rk}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran integer(${ik}$) :: i, ierr, j, j1, j2, jnext, k, n1, n2 real(${rk}$) :: bignum, eps, rec, scaloc, si, smin, sminw, smlnum, sr, tjj, tmp, xj, xmax, & xnorm, z ! Local Arrays real(${rk}$) :: d(2_${ik}$,2_${ik}$), v(2_${ik}$,2_${ik}$) ! Intrinsic Functions ! Executable Statements ! do not test the input parameters for errors notran = .not.ltran info = 0_${ik}$ ! quick return if possible if( n==0 )return ! set constants to control overflow eps = stdlib${ii}$_${ri}$lamch( 'P' ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) / eps bignum = one / smlnum xnorm = stdlib${ii}$_${ri}$lange( 'M', n, n, t, ldt, d ) if( .not.lreal )xnorm = max( xnorm, abs( w ), stdlib${ii}$_${ri}$lange( 'M', n, 1_${ik}$, b, n, d ) ) smin = max( smlnum, eps*xnorm ) ! compute 1-norm of each column of strictly upper triangular ! part of t to control overflow in triangular solver. work( 1_${ik}$ ) = zero do j = 2, n work( j ) = stdlib${ii}$_${ri}$asum( j-1, t( 1_${ik}$, j ), 1_${ik}$ ) end do if( .not.lreal ) then do i = 2, n work( i ) = work( i ) + abs( b( i ) ) end do end if n2 = 2_${ik}$*n n1 = n if( .not.lreal )n1 = n2 k = stdlib${ii}$_i${ri}$amax( n1, x, 1_${ik}$ ) xmax = abs( x( k ) ) scale = one if( xmax>bignum ) then scale = bignum / xmax call stdlib${ii}$_${ri}$scal( n1, scale, x, 1_${ik}$ ) xmax = bignum end if if( lreal ) then if( notran ) then ! solve t*p = scale*c jnext = n loop_30: do j = n, 1, -1 if( j>jnext )cycle loop_30 j1 = j j2 = j jnext = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnext = j - 2_${ik}$ end if end if if( j1==j2 ) then ! meet 1 by 1 diagonal block ! scale to avoid overflow when computing ! x(j) = b(j)/t(j,j) xj = abs( x( j1 ) ) tjj = abs( t( j1, j1 ) ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) / tmp xj = abs( x( j1 ) ) ! scale x if necessary to avoid overflow when adding a ! multiple of column j1 of t. if( xj>one ) then rec = one / xj if( work( j1 )>( bignum-xmax )*rec ) then call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if end if if( j1>1_${ik}$ ) then call stdlib${ii}$_${ri}$axpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) k = stdlib${ii}$_i${ri}$amax( j1-1, x, 1_${ik}$ ) xmax = abs( x( k ) ) end if else ! meet 2 by 2 diagonal block ! call 2 by 2 linear system solve, to take ! care of possible overflow by scaling factor. d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) call stdlib${ii}$_${ri}$laln2( .false., 2_${ik}$, 1_${ik}$, smin, one, t( j1, j1 ),ldt, one, one, d,& 2_${ik}$, zero, zero, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_${ri}$scal( n, scaloc, x, 1_${ik}$ ) scale = scale*scaloc end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) ! scale v(1,1) (= x(j1)) and/or v(2,1) (=x(j2)) ! to avoid overflow in updating right-hand side. xj = max( abs( v( 1_${ik}$, 1_${ik}$ ) ), abs( v( 2_${ik}$, 1_${ik}$ ) ) ) if( xj>one ) then rec = one / xj if( max( work( j1 ), work( j2 ) )>( bignum-xmax )*rec ) then call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if end if ! update right-hand side if( j1>1_${ik}$ ) then call stdlib${ii}$_${ri}$axpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j1-1, -x( j2 ), t( 1_${ik}$, j2 ), 1_${ik}$, x, 1_${ik}$ ) k = stdlib${ii}$_i${ri}$amax( j1-1, x, 1_${ik}$ ) xmax = abs( x( k ) ) end if end if end do loop_30 else ! solve t**t*p = scale*c jnext = 1_${ik}$ loop_40: do j = 1, n if( jone ) then rec = one / xmax if( work( j1 )>( bignum-xj )*rec ) then call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) - stdlib${ii}$_${ri}$dot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) xj = abs( x( j1 ) ) tjj = abs( t( j1, j1 ) ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) / tmp xmax = max( xmax, abs( x( j1 ) ) ) else ! 2 by 2 diagonal block ! scale if necessary to avoid overflow in forming the ! right-hand side elements by inner product. xj = max( abs( x( j1 ) ), abs( x( j2 ) ) ) if( xmax>one ) then rec = one / xmax if( max( work( j2 ), work( j1 ) )>( bignum-xj )*rec ) then call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) - stdlib${ii}$_${ri}$dot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x,1_${ik}$ ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) - stdlib${ii}$_${ri}$dot( j1-1, t( 1_${ik}$, j2 ), 1_${ik}$, x,1_${ik}$ ) call stdlib${ii}$_${ri}$laln2( .true., 2_${ik}$, 1_${ik}$, smin, one, t( j1, j1 ),ldt, one, one, d, & 2_${ik}$, zero, zero, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_${ri}$scal( n, scaloc, x, 1_${ik}$ ) scale = scale*scaloc end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) xmax = max( abs( x( j1 ) ), abs( x( j2 ) ), xmax ) end if end do loop_40 end if else sminw = max( eps*abs( w ), smin ) if( notran ) then ! solve (t + ib)*(p+iq) = c+id jnext = n loop_70: do j = n, 1, -1 if( j>jnext )cycle loop_70 j1 = j j2 = j jnext = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnext = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1 by 1 diagonal block ! scale if necessary to avoid overflow in division z = w if( j1==1_${ik}$ )z = b( 1_${ik}$ ) xj = abs( x( j1 ) ) + abs( x( n+j1 ) ) tjj = abs( t( j1, j1 ) ) + abs( z ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_${ri}$scal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if call stdlib${ii}$_${ri}$ladiv( x( j1 ), x( n+j1 ), tmp, z, sr, si ) x( j1 ) = sr x( n+j1 ) = si xj = abs( x( j1 ) ) + abs( x( n+j1 ) ) ! scale x if necessary to avoid overflow when adding a ! multiple of column j1 of t. if( xj>one ) then rec = one / xj if( work( j1 )>( bignum-xmax )*rec ) then call stdlib${ii}$_${ri}$scal( n2, rec, x, 1_${ik}$ ) scale = scale*rec end if end if if( j1>1_${ik}$ ) then call stdlib${ii}$_${ri}$axpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j1-1, -x( n+j1 ), t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) x( 1_${ik}$ ) = x( 1_${ik}$ ) + b( j1 )*x( n+j1 ) x( n+1 ) = x( n+1 ) - b( j1 )*x( j1 ) xmax = zero do k = 1, j1 - 1 xmax = max( xmax, abs( x( k ) )+abs( x( k+n ) ) ) end do end if else ! meet 2 by 2 diagonal block d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) d( 1_${ik}$, 2_${ik}$ ) = x( n+j1 ) d( 2_${ik}$, 2_${ik}$ ) = x( n+j2 ) call stdlib${ii}$_${ri}$laln2( .false., 2_${ik}$, 2_${ik}$, sminw, one, t( j1, j1 ),ldt, one, one, & d, 2_${ik}$, zero, -w, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_${ri}$scal( 2_${ik}$*n, scaloc, x, 1_${ik}$ ) scale = scaloc*scale end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) x( n+j1 ) = v( 1_${ik}$, 2_${ik}$ ) x( n+j2 ) = v( 2_${ik}$, 2_${ik}$ ) ! scale x(j1), .... to avoid overflow in ! updating right hand side. xj = max( abs( v( 1_${ik}$, 1_${ik}$ ) )+abs( v( 1_${ik}$, 2_${ik}$ ) ),abs( v( 2_${ik}$, 1_${ik}$ ) )+abs( v( 2_${ik}$, 2_${ik}$ )& ) ) if( xj>one ) then rec = one / xj if( max( work( j1 ), work( j2 ) )>( bignum-xmax )*rec ) then call stdlib${ii}$_${ri}$scal( n2, rec, x, 1_${ik}$ ) scale = scale*rec end if end if ! update the right-hand side. if( j1>1_${ik}$ ) then call stdlib${ii}$_${ri}$axpy( j1-1, -x( j1 ), t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j1-1, -x( j2 ), t( 1_${ik}$, j2 ), 1_${ik}$, x, 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j1-1, -x( n+j1 ), t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j1-1, -x( n+j2 ), t( 1_${ik}$, j2 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) x( 1_${ik}$ ) = x( 1_${ik}$ ) + b( j1 )*x( n+j1 ) +b( j2 )*x( n+j2 ) x( n+1 ) = x( n+1 ) - b( j1 )*x( j1 ) -b( j2 )*x( j2 ) xmax = zero do k = 1, j1 - 1 xmax = max( abs( x( k ) )+abs( x( k+n ) ),xmax ) end do end if end if end do loop_70 else ! solve (t + ib)**t*(p+iq) = c+id jnext = 1_${ik}$ loop_80: do j = 1, n if( jone ) then rec = one / xmax if( work( j1 )>( bignum-xj )*rec ) then call stdlib${ii}$_${ri}$scal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j1 ) = x( j1 ) - stdlib${ii}$_${ri}$dot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x, 1_${ik}$ ) x( n+j1 ) = x( n+j1 ) - stdlib${ii}$_${ri}$dot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) if( j1>1_${ik}$ ) then x( j1 ) = x( j1 ) - b( j1 )*x( n+1 ) x( n+j1 ) = x( n+j1 ) + b( j1 )*x( 1_${ik}$ ) end if xj = abs( x( j1 ) ) + abs( x( j1+n ) ) z = w if( j1==1_${ik}$ )z = b( 1_${ik}$ ) ! scale if necessary to avoid overflow in ! complex division tjj = abs( t( j1, j1 ) ) + abs( z ) tmp = t( j1, j1 ) if( tjjbignum*tjj ) then rec = one / xj call stdlib${ii}$_${ri}$scal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if call stdlib${ii}$_${ri}$ladiv( x( j1 ), x( n+j1 ), tmp, -z, sr, si ) x( j1 ) = sr x( j1+n ) = si xmax = max( abs( x( j1 ) )+abs( x( j1+n ) ), xmax ) else ! 2 by 2 diagonal block ! scale if necessary to avoid overflow in forming the ! right-hand side element by inner product. xj = max( abs( x( j1 ) )+abs( x( n+j1 ) ),abs( x( j2 ) )+abs( x( n+j2 ) ) ) if( xmax>one ) then rec = one / xmax if( max( work( j1 ), work( j2 ) )>( bignum-xj ) / xmax ) then call stdlib${ii}$_${ri}$scal( n2, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if d( 1_${ik}$, 1_${ik}$ ) = x( j1 ) - stdlib${ii}$_${ri}$dot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, x,1_${ik}$ ) d( 2_${ik}$, 1_${ik}$ ) = x( j2 ) - stdlib${ii}$_${ri}$dot( j1-1, t( 1_${ik}$, j2 ), 1_${ik}$, x,1_${ik}$ ) d( 1_${ik}$, 2_${ik}$ ) = x( n+j1 ) - stdlib${ii}$_${ri}$dot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) d( 2_${ik}$, 2_${ik}$ ) = x( n+j2 ) - stdlib${ii}$_${ri}$dot( j1-1, t( 1_${ik}$, j2 ), 1_${ik}$,x( n+1 ), 1_${ik}$ ) d( 1_${ik}$, 1_${ik}$ ) = d( 1_${ik}$, 1_${ik}$ ) - b( j1 )*x( n+1 ) d( 2_${ik}$, 1_${ik}$ ) = d( 2_${ik}$, 1_${ik}$ ) - b( j2 )*x( n+1 ) d( 1_${ik}$, 2_${ik}$ ) = d( 1_${ik}$, 2_${ik}$ ) + b( j1 )*x( 1_${ik}$ ) d( 2_${ik}$, 2_${ik}$ ) = d( 2_${ik}$, 2_${ik}$ ) + b( j2 )*x( 1_${ik}$ ) call stdlib${ii}$_${ri}$laln2( .true., 2_${ik}$, 2_${ik}$, sminw, one, t( j1, j1 ),ldt, one, one, d,& 2_${ik}$, zero, w, v, 2_${ik}$,scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 2_${ik}$ if( scaloc/=one ) then call stdlib${ii}$_${ri}$scal( n2, scaloc, x, 1_${ik}$ ) scale = scaloc*scale end if x( j1 ) = v( 1_${ik}$, 1_${ik}$ ) x( j2 ) = v( 2_${ik}$, 1_${ik}$ ) x( n+j1 ) = v( 1_${ik}$, 2_${ik}$ ) x( n+j2 ) = v( 2_${ik}$, 2_${ik}$ ) xmax = max( abs( x( j1 ) )+abs( x( n+j1 ) ),abs( x( j2 ) )+abs( x( n+j2 ) )& , xmax ) end if end do loop_80 end if end if return end subroutine stdlib${ii}$_${ri}$laqtr #:endif #:endfor pure module subroutine stdlib${ii}$_slahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, & !! SLAHQR is an auxiliary routine called by SHSEQR to update the !! eigenvalues and Schur decomposition already computed by SHSEQR, by !! dealing with the Hessenberg submatrix in rows and columns ILO to !! IHI. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(sp), intent(inout) :: h(ldh,*), z(ldz,*) real(sp), intent(out) :: wi(*), wr(*) ! ========================================================= ! Parameters real(sp), parameter :: dat1 = 3.0_sp/4.0_sp real(sp), parameter :: dat2 = -0.4375_sp integer(${ik}$), parameter :: kexsh = 10_${ik}$ ! Local Scalars real(sp) :: aa, ab, ba, bb, cs, det, h11, h12, h21, h21s, h22, rt1i, rt1r, rt2i, rt2r, & rtdisc, s, safmax, safmin, smlnum, sn, sum, t1, t2, t3, tr, tst, ulp, v2, v3 integer(${ik}$) :: i, i1, i2, its, itmax, j, k, l, m, nh, nr, nz, kdefl ! Local Arrays real(sp) :: v(3_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n==0 )return if( ilo==ihi ) then wr( ilo ) = h( ilo, ilo ) wi( ilo ) = zero return end if ! ==== clear out the trash ==== do j = ilo, ihi - 3 h( j+2, j ) = zero h( j+3, j ) = zero end do if( ilo<=ihi-2 )h( ihi, ihi-2 ) = zero nh = ihi - ilo + 1_${ik}$ nz = ihiz - iloz + 1_${ik}$ ! set machine-dependent constants for the stopping criterion. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( nh,KIND=sp) / ulp ) ! i1 and i2 are the indices of the first row and last column of h ! to which transformations must be applied. if eigenvalues only are ! being computed, i1 and i2 are set inside the main loop. if( wantt ) then i1 = 1_${ik}$ i2 = n end if ! itmax is the total number of qr iterations allowed. itmax = 30_${ik}$ * max( 10_${ik}$, nh ) ! kdefl counts the number of iterations since a deflation kdefl = 0_${ik}$ ! the main loop begins here. i is the loop index and decreases from ! ihi to ilo in steps of 1 or 2. each iteration of the loop works ! with the active submatrix in rows and columns l to i. ! eigenvalues i+1 to ihi have already converged. either l = ilo or ! h(l,l-1) is negligible so that the matrix splits. i = ihi 20 continue l = ilo if( i=ilo )tst = tst + abs( h( k-1, k-2 ) ) if( k+1<=ihi )tst = tst + abs( h( k+1, k ) ) end if ! ==== the following is a conservative small subdiagonal ! . deflation criterion due to ahues ! . 1997). it has better mathematical foundation and ! . improves accuracy in some cases. ==== if( abs( h( k, k-1 ) )<=ulp*tst ) then ab = max( abs( h( k, k-1 ) ), abs( h( k-1, k ) ) ) ba = min( abs( h( k, k-1 ) ), abs( h( k-1, k ) ) ) aa = max( abs( h( k, k ) ),abs( h( k-1, k-1 )-h( k, k ) ) ) bb = min( abs( h( k, k ) ),abs( h( k-1, k-1 )-h( k, k ) ) ) s = aa + ab if( ba*( ab / s )<=max( smlnum,ulp*( bb*( aa / s ) ) ) )go to 40 end if end do 40 continue l = k if( l>ilo ) then ! h(l,l-1) is negligible h( l, l-1 ) = zero end if ! exit from loop if a submatrix of order 1 or 2 has split off. if( l>=i-1 )go to 150 kdefl = kdefl + 1_${ik}$ ! now the active submatrix is in rows and columns l to i. if ! eigenvalues only are being computed, only the active submatrix ! need be transformed. if( .not.wantt ) then i1 = l i2 = i end if if( mod(kdefl,2_${ik}$*kexsh)==0_${ik}$ ) then ! exceptional shift. s = abs( h( i, i-1 ) ) + abs( h( i-1, i-2 ) ) h11 = dat1*s + h( i, i ) h12 = dat2*s h21 = s h22 = h11 else if( mod(kdefl,kexsh)==0_${ik}$ ) then ! exceptional shift. s = abs( h( l+1, l ) ) + abs( h( l+2, l+1 ) ) h11 = dat1*s + h( l, l ) h12 = dat2*s h21 = s h22 = h11 else ! prepare to use francis' double shift ! (i.e. 2nd degree generalized rayleigh quotient) h11 = h( i-1, i-1 ) h21 = h( i, i-1 ) h12 = h( i-1, i ) h22 = h( i, i ) end if s = abs( h11 ) + abs( h12 ) + abs( h21 ) + abs( h22 ) if( s==zero ) then rt1r = zero rt1i = zero rt2r = zero rt2i = zero else h11 = h11 / s h21 = h21 / s h12 = h12 / s h22 = h22 / s tr = ( h11+h22 ) / two det = ( h11-tr )*( h22-tr ) - h12*h21 rtdisc = sqrt( abs( det ) ) if( det>=zero ) then ! ==== complex conjugate shifts ==== rt1r = tr*s rt2r = rt1r rt1i = rtdisc*s rt2i = -rt1i else ! ==== realshifts (use only one of them,KIND=sp) ==== rt1r = tr + rtdisc rt2r = tr - rtdisc if( abs( rt1r-h22 )<=abs( rt2r-h22 ) ) then rt1r = rt1r*s rt2r = rt1r else rt2r = rt2r*s rt1r = rt2r end if rt1i = zero rt2i = zero end if end if ! look for two consecutive small subdiagonal elements. do m = i - 2, l, -1 ! determine the effect of starting the double-shift qr ! iteration at row m, and see if this would make h(m,m-1) ! negligible. (the following uses scaling to avoid ! overflows and most underflows.) h21s = h( m+1, m ) s = abs( h( m, m )-rt2r ) + abs( rt2i ) + abs( h21s ) h21s = h( m+1, m ) / s v( 1_${ik}$ ) = h21s*h( m, m+1 ) + ( h( m, m )-rt1r )*( ( h( m, m )-rt2r ) / s ) - & rt1i*( rt2i / s ) v( 2_${ik}$ ) = h21s*( h( m, m )+h( m+1, m+1 )-rt1r-rt2r ) v( 3_${ik}$ ) = h21s*h( m+2, m+1 ) s = abs( v( 1_${ik}$ ) ) + abs( v( 2_${ik}$ ) ) + abs( v( 3_${ik}$ ) ) v( 1_${ik}$ ) = v( 1_${ik}$ ) / s v( 2_${ik}$ ) = v( 2_${ik}$ ) / s v( 3_${ik}$ ) = v( 3_${ik}$ ) / s if( m==l )go to 60 if( abs( h( m, m-1 ) )*( abs( v( 2_${ik}$ ) )+abs( v( 3_${ik}$ ) ) )<=ulp*abs( v( 1_${ik}$ ) )*( abs( & h( m-1, m-1 ) )+abs( h( m,m ) )+abs( h( m+1, m+1 ) ) ) )go to 60 end do 60 continue ! double-shift qr step loop_130: do k = m, i - 1 ! the first iteration of this loop determines a reflection g ! from the vector v and applies it from left and right to h, ! thus creating a nonzero bulge below the subdiagonal. ! each subsequent iteration determines a reflection g to ! restore the hessenberg form in the (k-1)th column, and thus ! chases the bulge one step toward the bottom of the active ! submatrix. nr is the order of g. nr = min( 3_${ik}$, i-k+1 ) if( k>m )call stdlib${ii}$_scopy( nr, h( k, k-1 ), 1_${ik}$, v, 1_${ik}$ ) call stdlib${ii}$_slarfg( nr, v( 1_${ik}$ ), v( 2_${ik}$ ), 1_${ik}$, t1 ) if( k>m ) then h( k, k-1 ) = v( 1_${ik}$ ) h( k+1, k-1 ) = zero if( kl ) then ! ==== use the following instead of ! . h( k, k-1 ) = -h( k, k-1 ) to ! . avoid a bug when v(2) and v(3) ! . underflow. ==== h( k, k-1 ) = h( k, k-1 )*( one-t1 ) end if v2 = v( 2_${ik}$ ) t2 = t1*v2 if( nr==3_${ik}$ ) then v3 = v( 3_${ik}$ ) t3 = t1*v3 ! apply g from the left to transform the rows of the matrix ! in columns k to i2. do j = k, i2 sum = h( k, j ) + v2*h( k+1, j ) + v3*h( k+2, j ) h( k, j ) = h( k, j ) - sum*t1 h( k+1, j ) = h( k+1, j ) - sum*t2 h( k+2, j ) = h( k+2, j ) - sum*t3 end do ! apply g from the right to transform the columns of the ! matrix in rows i1 to min(k+3,i). do j = i1, min( k+3, i ) sum = h( j, k ) + v2*h( j, k+1 ) + v3*h( j, k+2 ) h( j, k ) = h( j, k ) - sum*t1 h( j, k+1 ) = h( j, k+1 ) - sum*t2 h( j, k+2 ) = h( j, k+2 ) - sum*t3 end do if( wantz ) then ! accumulate transformations in the matrix z do j = iloz, ihiz sum = z( j, k ) + v2*z( j, k+1 ) + v3*z( j, k+2 ) z( j, k ) = z( j, k ) - sum*t1 z( j, k+1 ) = z( j, k+1 ) - sum*t2 z( j, k+2 ) = z( j, k+2 ) - sum*t3 end do end if else if( nr==2_${ik}$ ) then ! apply g from the left to transform the rows of the matrix ! in columns k to i2. do j = k, i2 sum = h( k, j ) + v2*h( k+1, j ) h( k, j ) = h( k, j ) - sum*t1 h( k+1, j ) = h( k+1, j ) - sum*t2 end do ! apply g from the right to transform the columns of the ! matrix in rows i1 to min(k+3,i). do j = i1, i sum = h( j, k ) + v2*h( j, k+1 ) h( j, k ) = h( j, k ) - sum*t1 h( j, k+1 ) = h( j, k+1 ) - sum*t2 end do if( wantz ) then ! accumulate transformations in the matrix z do j = iloz, ihiz sum = z( j, k ) + v2*z( j, k+1 ) z( j, k ) = z( j, k ) - sum*t1 z( j, k+1 ) = z( j, k+1 ) - sum*t2 end do end if end if end do loop_130 end do loop_140 ! failure to converge in remaining number of iterations info = i return 150 continue if( l==i ) then ! h(i,i-1) is negligible: one eigenvalue has converged. wr( i ) = h( i, i ) wi( i ) = zero else if( l==i-1 ) then ! h(i-1,i-2) is negligible: a pair of eigenvalues have converged. ! transform the 2-by-2 submatrix to standard schur form, ! and compute and store the eigenvalues. call stdlib${ii}$_slanv2( h( i-1, i-1 ), h( i-1, i ), h( i, i-1 ),h( i, i ), wr( i-1 ), & wi( i-1 ), wr( i ), wi( i ),cs, sn ) if( wantt ) then ! apply the transformation to the rest of h. if( i2>i )call stdlib${ii}$_srot( i2-i, h( i-1, i+1 ), ldh, h( i, i+1 ), ldh,cs, sn ) call stdlib${ii}$_srot( i-i1-1, h( i1, i-1 ), 1_${ik}$, h( i1, i ), 1_${ik}$, cs, sn ) end if if( wantz ) then ! apply the transformation to z. call stdlib${ii}$_srot( nz, z( iloz, i-1 ), 1_${ik}$, z( iloz, i ), 1_${ik}$, cs, sn ) end if end if ! reset deflation counter kdefl = 0_${ik}$ ! return to start of the main loop with new value of i. i = l - 1_${ik}$ go to 20 160 continue return end subroutine stdlib${ii}$_slahqr pure module subroutine stdlib${ii}$_dlahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, & !! DLAHQR is an auxiliary routine called by DHSEQR to update the !! eigenvalues and Schur decomposition already computed by DHSEQR, by !! dealing with the Hessenberg submatrix in rows and columns ILO to !! IHI. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(dp), intent(inout) :: h(ldh,*), z(ldz,*) real(dp), intent(out) :: wi(*), wr(*) ! ========================================================= ! Parameters real(dp), parameter :: dat1 = 3.0_dp/4.0_dp real(dp), parameter :: dat2 = -0.4375_dp integer(${ik}$), parameter :: kexsh = 10_${ik}$ ! Local Scalars real(dp) :: aa, ab, ba, bb, cs, det, h11, h12, h21, h21s, h22, rt1i, rt1r, rt2i, rt2r, & rtdisc, s, safmax, safmin, smlnum, sn, sum, t1, t2, t3, tr, tst, ulp, v2, v3 integer(${ik}$) :: i, i1, i2, its, itmax, j, k, l, m, nh, nr, nz, kdefl ! Local Arrays real(dp) :: v(3_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n==0 )return if( ilo==ihi ) then wr( ilo ) = h( ilo, ilo ) wi( ilo ) = zero return end if ! ==== clear out the trash ==== do j = ilo, ihi - 3 h( j+2, j ) = zero h( j+3, j ) = zero end do if( ilo<=ihi-2 )h( ihi, ihi-2 ) = zero nh = ihi - ilo + 1_${ik}$ nz = ihiz - iloz + 1_${ik}$ ! set machine-dependent constants for the stopping criterion. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( nh,KIND=dp) / ulp ) ! i1 and i2 are the indices of the first row and last column of h ! to which transformations must be applied. if eigenvalues only are ! being computed, i1 and i2 are set inside the main loop. if( wantt ) then i1 = 1_${ik}$ i2 = n end if ! itmax is the total number of qr iterations allowed. itmax = 30_${ik}$ * max( 10_${ik}$, nh ) ! kdefl counts the number of iterations since a deflation kdefl = 0_${ik}$ ! the main loop begins here. i is the loop index and decreases from ! ihi to ilo in steps of 1 or 2. each iteration of the loop works ! with the active submatrix in rows and columns l to i. ! eigenvalues i+1 to ihi have already converged. either l = ilo or ! h(l,l-1) is negligible so that the matrix splits. i = ihi 20 continue l = ilo if( i=ilo )tst = tst + abs( h( k-1, k-2 ) ) if( k+1<=ihi )tst = tst + abs( h( k+1, k ) ) end if ! ==== the following is a conservative small subdiagonal ! . deflation criterion due to ahues ! . 1997). it has better mathematical foundation and ! . improves accuracy in some cases. ==== if( abs( h( k, k-1 ) )<=ulp*tst ) then ab = max( abs( h( k, k-1 ) ), abs( h( k-1, k ) ) ) ba = min( abs( h( k, k-1 ) ), abs( h( k-1, k ) ) ) aa = max( abs( h( k, k ) ),abs( h( k-1, k-1 )-h( k, k ) ) ) bb = min( abs( h( k, k ) ),abs( h( k-1, k-1 )-h( k, k ) ) ) s = aa + ab if( ba*( ab / s )<=max( smlnum,ulp*( bb*( aa / s ) ) ) )go to 40 end if end do 40 continue l = k if( l>ilo ) then ! h(l,l-1) is negligible h( l, l-1 ) = zero end if ! exit from loop if a submatrix of order 1 or 2 has split off. if( l>=i-1 )go to 150 kdefl = kdefl + 1_${ik}$ ! now the active submatrix is in rows and columns l to i. if ! eigenvalues only are being computed, only the active submatrix ! need be transformed. if( .not.wantt ) then i1 = l i2 = i end if if( mod(kdefl,2_${ik}$*kexsh)==0_${ik}$ ) then ! exceptional shift. s = abs( h( i, i-1 ) ) + abs( h( i-1, i-2 ) ) h11 = dat1*s + h( i, i ) h12 = dat2*s h21 = s h22 = h11 else if( mod(kdefl,kexsh)==0_${ik}$ ) then ! exceptional shift. s = abs( h( l+1, l ) ) + abs( h( l+2, l+1 ) ) h11 = dat1*s + h( l, l ) h12 = dat2*s h21 = s h22 = h11 else ! prepare to use francis' double shift ! (i.e. 2nd degree generalized rayleigh quotient) h11 = h( i-1, i-1 ) h21 = h( i, i-1 ) h12 = h( i-1, i ) h22 = h( i, i ) end if s = abs( h11 ) + abs( h12 ) + abs( h21 ) + abs( h22 ) if( s==zero ) then rt1r = zero rt1i = zero rt2r = zero rt2i = zero else h11 = h11 / s h21 = h21 / s h12 = h12 / s h22 = h22 / s tr = ( h11+h22 ) / two det = ( h11-tr )*( h22-tr ) - h12*h21 rtdisc = sqrt( abs( det ) ) if( det>=zero ) then ! ==== complex conjugate shifts ==== rt1r = tr*s rt2r = rt1r rt1i = rtdisc*s rt2i = -rt1i else ! ==== realshifts (use only one of them,KIND=dp) ==== rt1r = tr + rtdisc rt2r = tr - rtdisc if( abs( rt1r-h22 )<=abs( rt2r-h22 ) ) then rt1r = rt1r*s rt2r = rt1r else rt2r = rt2r*s rt1r = rt2r end if rt1i = zero rt2i = zero end if end if ! look for two consecutive small subdiagonal elements. do m = i - 2, l, -1 ! determine the effect of starting the double-shift qr ! iteration at row m, and see if this would make h(m,m-1) ! negligible. (the following uses scaling to avoid ! overflows and most underflows.) h21s = h( m+1, m ) s = abs( h( m, m )-rt2r ) + abs( rt2i ) + abs( h21s ) h21s = h( m+1, m ) / s v( 1_${ik}$ ) = h21s*h( m, m+1 ) + ( h( m, m )-rt1r )*( ( h( m, m )-rt2r ) / s ) - & rt1i*( rt2i / s ) v( 2_${ik}$ ) = h21s*( h( m, m )+h( m+1, m+1 )-rt1r-rt2r ) v( 3_${ik}$ ) = h21s*h( m+2, m+1 ) s = abs( v( 1_${ik}$ ) ) + abs( v( 2_${ik}$ ) ) + abs( v( 3_${ik}$ ) ) v( 1_${ik}$ ) = v( 1_${ik}$ ) / s v( 2_${ik}$ ) = v( 2_${ik}$ ) / s v( 3_${ik}$ ) = v( 3_${ik}$ ) / s if( m==l )go to 60 if( abs( h( m, m-1 ) )*( abs( v( 2_${ik}$ ) )+abs( v( 3_${ik}$ ) ) )<=ulp*abs( v( 1_${ik}$ ) )*( abs( & h( m-1, m-1 ) )+abs( h( m,m ) )+abs( h( m+1, m+1 ) ) ) )go to 60 end do 60 continue ! double-shift qr step loop_130: do k = m, i - 1 ! the first iteration of this loop determines a reflection g ! from the vector v and applies it from left and right to h, ! thus creating a nonzero bulge below the subdiagonal. ! each subsequent iteration determines a reflection g to ! restore the hessenberg form in the (k-1)th column, and thus ! chases the bulge one step toward the bottom of the active ! submatrix. nr is the order of g. nr = min( 3_${ik}$, i-k+1 ) if( k>m )call stdlib${ii}$_dcopy( nr, h( k, k-1 ), 1_${ik}$, v, 1_${ik}$ ) call stdlib${ii}$_dlarfg( nr, v( 1_${ik}$ ), v( 2_${ik}$ ), 1_${ik}$, t1 ) if( k>m ) then h( k, k-1 ) = v( 1_${ik}$ ) h( k+1, k-1 ) = zero if( kl ) then ! ==== use the following instead of ! . h( k, k-1 ) = -h( k, k-1 ) to ! . avoid a bug when v(2) and v(3) ! . underflow. ==== h( k, k-1 ) = h( k, k-1 )*( one-t1 ) end if v2 = v( 2_${ik}$ ) t2 = t1*v2 if( nr==3_${ik}$ ) then v3 = v( 3_${ik}$ ) t3 = t1*v3 ! apply g from the left to transform the rows of the matrix ! in columns k to i2. do j = k, i2 sum = h( k, j ) + v2*h( k+1, j ) + v3*h( k+2, j ) h( k, j ) = h( k, j ) - sum*t1 h( k+1, j ) = h( k+1, j ) - sum*t2 h( k+2, j ) = h( k+2, j ) - sum*t3 end do ! apply g from the right to transform the columns of the ! matrix in rows i1 to min(k+3,i). do j = i1, min( k+3, i ) sum = h( j, k ) + v2*h( j, k+1 ) + v3*h( j, k+2 ) h( j, k ) = h( j, k ) - sum*t1 h( j, k+1 ) = h( j, k+1 ) - sum*t2 h( j, k+2 ) = h( j, k+2 ) - sum*t3 end do if( wantz ) then ! accumulate transformations in the matrix z do j = iloz, ihiz sum = z( j, k ) + v2*z( j, k+1 ) + v3*z( j, k+2 ) z( j, k ) = z( j, k ) - sum*t1 z( j, k+1 ) = z( j, k+1 ) - sum*t2 z( j, k+2 ) = z( j, k+2 ) - sum*t3 end do end if else if( nr==2_${ik}$ ) then ! apply g from the left to transform the rows of the matrix ! in columns k to i2. do j = k, i2 sum = h( k, j ) + v2*h( k+1, j ) h( k, j ) = h( k, j ) - sum*t1 h( k+1, j ) = h( k+1, j ) - sum*t2 end do ! apply g from the right to transform the columns of the ! matrix in rows i1 to min(k+3,i). do j = i1, i sum = h( j, k ) + v2*h( j, k+1 ) h( j, k ) = h( j, k ) - sum*t1 h( j, k+1 ) = h( j, k+1 ) - sum*t2 end do if( wantz ) then ! accumulate transformations in the matrix z do j = iloz, ihiz sum = z( j, k ) + v2*z( j, k+1 ) z( j, k ) = z( j, k ) - sum*t1 z( j, k+1 ) = z( j, k+1 ) - sum*t2 end do end if end if end do loop_130 end do loop_140 ! failure to converge in remaining number of iterations info = i return 150 continue if( l==i ) then ! h(i,i-1) is negligible: one eigenvalue has converged. wr( i ) = h( i, i ) wi( i ) = zero else if( l==i-1 ) then ! h(i-1,i-2) is negligible: a pair of eigenvalues have converged. ! transform the 2-by-2 submatrix to standard schur form, ! and compute and store the eigenvalues. call stdlib${ii}$_dlanv2( h( i-1, i-1 ), h( i-1, i ), h( i, i-1 ),h( i, i ), wr( i-1 ), & wi( i-1 ), wr( i ), wi( i ),cs, sn ) if( wantt ) then ! apply the transformation to the rest of h. if( i2>i )call stdlib${ii}$_drot( i2-i, h( i-1, i+1 ), ldh, h( i, i+1 ), ldh,cs, sn ) call stdlib${ii}$_drot( i-i1-1, h( i1, i-1 ), 1_${ik}$, h( i1, i ), 1_${ik}$, cs, sn ) end if if( wantz ) then ! apply the transformation to z. call stdlib${ii}$_drot( nz, z( iloz, i-1 ), 1_${ik}$, z( iloz, i ), 1_${ik}$, cs, sn ) end if end if ! reset deflation counter kdefl = 0_${ik}$ ! return to start of the main loop with new value of i. i = l - 1_${ik}$ go to 20 160 continue return end subroutine stdlib${ii}$_dlahqr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, & !! DLAHQR: is an auxiliary routine called by DHSEQR to update the !! eigenvalues and Schur decomposition already computed by DHSEQR, by !! dealing with the Hessenberg submatrix in rows and columns ILO to !! IHI. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(${rk}$), intent(inout) :: h(ldh,*), z(ldz,*) real(${rk}$), intent(out) :: wi(*), wr(*) ! ========================================================= ! Parameters real(${rk}$), parameter :: dat1 = 3.0_${rk}$/4.0_${rk}$ real(${rk}$), parameter :: dat2 = -0.4375_${rk}$ integer(${ik}$), parameter :: kexsh = 10_${ik}$ ! Local Scalars real(${rk}$) :: aa, ab, ba, bb, cs, det, h11, h12, h21, h21s, h22, rt1i, rt1r, rt2i, rt2r, & rtdisc, s, safmax, safmin, smlnum, sn, sum, t1, t2, t3, tr, tst, ulp, v2, v3 integer(${ik}$) :: i, i1, i2, its, itmax, j, k, l, m, nh, nr, nz, kdefl ! Local Arrays real(${rk}$) :: v(3_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n==0 )return if( ilo==ihi ) then wr( ilo ) = h( ilo, ilo ) wi( ilo ) = zero return end if ! ==== clear out the trash ==== do j = ilo, ihi - 3 h( j+2, j ) = zero h( j+3, j ) = zero end do if( ilo<=ihi-2 )h( ihi, ihi-2 ) = zero nh = ihi - ilo + 1_${ik}$ nz = ihiz - iloz + 1_${ik}$ ! set machine-dependent constants for the stopping criterion. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_${ri}$labad( safmin, safmax ) ulp = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin*( real( nh,KIND=${rk}$) / ulp ) ! i1 and i2 are the indices of the first row and last column of h ! to which transformations must be applied. if eigenvalues only are ! being computed, i1 and i2 are set inside the main loop. if( wantt ) then i1 = 1_${ik}$ i2 = n end if ! itmax is the total number of qr iterations allowed. itmax = 30_${ik}$ * max( 10_${ik}$, nh ) ! kdefl counts the number of iterations since a deflation kdefl = 0_${ik}$ ! the main loop begins here. i is the loop index and decreases from ! ihi to ilo in steps of 1 or 2. each iteration of the loop works ! with the active submatrix in rows and columns l to i. ! eigenvalues i+1 to ihi have already converged. either l = ilo or ! h(l,l-1) is negligible so that the matrix splits. i = ihi 20 continue l = ilo if( i=ilo )tst = tst + abs( h( k-1, k-2 ) ) if( k+1<=ihi )tst = tst + abs( h( k+1, k ) ) end if ! ==== the following is a conservative small subdiagonal ! . deflation criterion due to ahues ! . 1997). it has better mathematical foundation and ! . improves accuracy in some cases. ==== if( abs( h( k, k-1 ) )<=ulp*tst ) then ab = max( abs( h( k, k-1 ) ), abs( h( k-1, k ) ) ) ba = min( abs( h( k, k-1 ) ), abs( h( k-1, k ) ) ) aa = max( abs( h( k, k ) ),abs( h( k-1, k-1 )-h( k, k ) ) ) bb = min( abs( h( k, k ) ),abs( h( k-1, k-1 )-h( k, k ) ) ) s = aa + ab if( ba*( ab / s )<=max( smlnum,ulp*( bb*( aa / s ) ) ) )go to 40 end if end do 40 continue l = k if( l>ilo ) then ! h(l,l-1) is negligible h( l, l-1 ) = zero end if ! exit from loop if a submatrix of order 1 or 2 has split off. if( l>=i-1 )go to 150 kdefl = kdefl + 1_${ik}$ ! now the active submatrix is in rows and columns l to i. if ! eigenvalues only are being computed, only the active submatrix ! need be transformed. if( .not.wantt ) then i1 = l i2 = i end if if( mod(kdefl,2_${ik}$*kexsh)==0_${ik}$ ) then ! exceptional shift. s = abs( h( i, i-1 ) ) + abs( h( i-1, i-2 ) ) h11 = dat1*s + h( i, i ) h12 = dat2*s h21 = s h22 = h11 else if( mod(kdefl,kexsh)==0_${ik}$ ) then ! exceptional shift. s = abs( h( l+1, l ) ) + abs( h( l+2, l+1 ) ) h11 = dat1*s + h( l, l ) h12 = dat2*s h21 = s h22 = h11 else ! prepare to use francis' double shift ! (i.e. 2nd degree generalized rayleigh quotient) h11 = h( i-1, i-1 ) h21 = h( i, i-1 ) h12 = h( i-1, i ) h22 = h( i, i ) end if s = abs( h11 ) + abs( h12 ) + abs( h21 ) + abs( h22 ) if( s==zero ) then rt1r = zero rt1i = zero rt2r = zero rt2i = zero else h11 = h11 / s h21 = h21 / s h12 = h12 / s h22 = h22 / s tr = ( h11+h22 ) / two det = ( h11-tr )*( h22-tr ) - h12*h21 rtdisc = sqrt( abs( det ) ) if( det>=zero ) then ! ==== complex conjugate shifts ==== rt1r = tr*s rt2r = rt1r rt1i = rtdisc*s rt2i = -rt1i else ! ==== realshifts (use only one of them,KIND=${rk}$) ==== rt1r = tr + rtdisc rt2r = tr - rtdisc if( abs( rt1r-h22 )<=abs( rt2r-h22 ) ) then rt1r = rt1r*s rt2r = rt1r else rt2r = rt2r*s rt1r = rt2r end if rt1i = zero rt2i = zero end if end if ! look for two consecutive small subdiagonal elements. do m = i - 2, l, -1 ! determine the effect of starting the double-shift qr ! iteration at row m, and see if this would make h(m,m-1) ! negligible. (the following uses scaling to avoid ! overflows and most underflows.) h21s = h( m+1, m ) s = abs( h( m, m )-rt2r ) + abs( rt2i ) + abs( h21s ) h21s = h( m+1, m ) / s v( 1_${ik}$ ) = h21s*h( m, m+1 ) + ( h( m, m )-rt1r )*( ( h( m, m )-rt2r ) / s ) - & rt1i*( rt2i / s ) v( 2_${ik}$ ) = h21s*( h( m, m )+h( m+1, m+1 )-rt1r-rt2r ) v( 3_${ik}$ ) = h21s*h( m+2, m+1 ) s = abs( v( 1_${ik}$ ) ) + abs( v( 2_${ik}$ ) ) + abs( v( 3_${ik}$ ) ) v( 1_${ik}$ ) = v( 1_${ik}$ ) / s v( 2_${ik}$ ) = v( 2_${ik}$ ) / s v( 3_${ik}$ ) = v( 3_${ik}$ ) / s if( m==l )go to 60 if( abs( h( m, m-1 ) )*( abs( v( 2_${ik}$ ) )+abs( v( 3_${ik}$ ) ) )<=ulp*abs( v( 1_${ik}$ ) )*( abs( & h( m-1, m-1 ) )+abs( h( m,m ) )+abs( h( m+1, m+1 ) ) ) )go to 60 end do 60 continue ! double-shift qr step loop_130: do k = m, i - 1 ! the first iteration of this loop determines a reflection g ! from the vector v and applies it from left and right to h, ! thus creating a nonzero bulge below the subdiagonal. ! each subsequent iteration determines a reflection g to ! restore the hessenberg form in the (k-1)th column, and thus ! chases the bulge one step toward the bottom of the active ! submatrix. nr is the order of g. nr = min( 3_${ik}$, i-k+1 ) if( k>m )call stdlib${ii}$_${ri}$copy( nr, h( k, k-1 ), 1_${ik}$, v, 1_${ik}$ ) call stdlib${ii}$_${ri}$larfg( nr, v( 1_${ik}$ ), v( 2_${ik}$ ), 1_${ik}$, t1 ) if( k>m ) then h( k, k-1 ) = v( 1_${ik}$ ) h( k+1, k-1 ) = zero if( kl ) then ! ==== use the following instead of ! . h( k, k-1 ) = -h( k, k-1 ) to ! . avoid a bug when v(2) and v(3) ! . underflow. ==== h( k, k-1 ) = h( k, k-1 )*( one-t1 ) end if v2 = v( 2_${ik}$ ) t2 = t1*v2 if( nr==3_${ik}$ ) then v3 = v( 3_${ik}$ ) t3 = t1*v3 ! apply g from the left to transform the rows of the matrix ! in columns k to i2. do j = k, i2 sum = h( k, j ) + v2*h( k+1, j ) + v3*h( k+2, j ) h( k, j ) = h( k, j ) - sum*t1 h( k+1, j ) = h( k+1, j ) - sum*t2 h( k+2, j ) = h( k+2, j ) - sum*t3 end do ! apply g from the right to transform the columns of the ! matrix in rows i1 to min(k+3,i). do j = i1, min( k+3, i ) sum = h( j, k ) + v2*h( j, k+1 ) + v3*h( j, k+2 ) h( j, k ) = h( j, k ) - sum*t1 h( j, k+1 ) = h( j, k+1 ) - sum*t2 h( j, k+2 ) = h( j, k+2 ) - sum*t3 end do if( wantz ) then ! accumulate transformations in the matrix z do j = iloz, ihiz sum = z( j, k ) + v2*z( j, k+1 ) + v3*z( j, k+2 ) z( j, k ) = z( j, k ) - sum*t1 z( j, k+1 ) = z( j, k+1 ) - sum*t2 z( j, k+2 ) = z( j, k+2 ) - sum*t3 end do end if else if( nr==2_${ik}$ ) then ! apply g from the left to transform the rows of the matrix ! in columns k to i2. do j = k, i2 sum = h( k, j ) + v2*h( k+1, j ) h( k, j ) = h( k, j ) - sum*t1 h( k+1, j ) = h( k+1, j ) - sum*t2 end do ! apply g from the right to transform the columns of the ! matrix in rows i1 to min(k+3,i). do j = i1, i sum = h( j, k ) + v2*h( j, k+1 ) h( j, k ) = h( j, k ) - sum*t1 h( j, k+1 ) = h( j, k+1 ) - sum*t2 end do if( wantz ) then ! accumulate transformations in the matrix z do j = iloz, ihiz sum = z( j, k ) + v2*z( j, k+1 ) z( j, k ) = z( j, k ) - sum*t1 z( j, k+1 ) = z( j, k+1 ) - sum*t2 end do end if end if end do loop_130 end do loop_140 ! failure to converge in remaining number of iterations info = i return 150 continue if( l==i ) then ! h(i,i-1) is negligible: one eigenvalue has converged. wr( i ) = h( i, i ) wi( i ) = zero else if( l==i-1 ) then ! h(i-1,i-2) is negligible: a pair of eigenvalues have converged. ! transform the 2-by-2 submatrix to standard schur form, ! and compute and store the eigenvalues. call stdlib${ii}$_${ri}$lanv2( h( i-1, i-1 ), h( i-1, i ), h( i, i-1 ),h( i, i ), wr( i-1 ), & wi( i-1 ), wr( i ), wi( i ),cs, sn ) if( wantt ) then ! apply the transformation to the rest of h. if( i2>i )call stdlib${ii}$_${ri}$rot( i2-i, h( i-1, i+1 ), ldh, h( i, i+1 ), ldh,cs, sn ) call stdlib${ii}$_${ri}$rot( i-i1-1, h( i1, i-1 ), 1_${ik}$, h( i1, i ), 1_${ik}$, cs, sn ) end if if( wantz ) then ! apply the transformation to z. call stdlib${ii}$_${ri}$rot( nz, z( iloz, i-1 ), 1_${ik}$, z( iloz, i ), 1_${ik}$, cs, sn ) end if end if ! reset deflation counter kdefl = 0_${ik}$ ! return to start of the main loop with new value of i. i = l - 1_${ik}$ go to 20 160 continue return end subroutine stdlib${ii}$_${ri}$lahqr #:endif #:endfor pure module subroutine stdlib${ii}$_clahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, info & !! CLAHQR is an auxiliary routine called by CHSEQR to update the !! eigenvalues and Schur decomposition already computed by CHSEQR, by !! dealing with the Hessenberg submatrix in rows and columns ILO to !! IHI. ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(sp), intent(inout) :: h(ldh,*), z(ldz,*) complex(sp), intent(out) :: w(*) ! ========================================================= ! Parameters real(sp), parameter :: dat1 = 3.0_sp/4.0_sp integer(${ik}$), parameter :: kexsh = 10_${ik}$ ! Local Scalars complex(sp) :: cdum, h11, h11s, h22, sc, sum, t, t1, temp, u, v2, x, y real(sp) :: aa, ab, ba, bb, h10, h21, rtemp, s, safmax, safmin, smlnum, sx, t2, tst, & ulp integer(${ik}$) :: i, i1, i2, its, itmax, j, jhi, jlo, k, l, m, nh, nz, kdefl ! Local Arrays complex(sp) :: v(2_${ik}$) ! Statement Functions real(sp) :: cabs1 ! Intrinsic Functions ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n==0 )return if( ilo==ihi ) then w( ilo ) = h( ilo, ilo ) return end if ! ==== clear out the trash ==== do j = ilo, ihi - 3 h( j+2, j ) = czero h( j+3, j ) = czero end do if( ilo<=ihi-2 )h( ihi, ihi-2 ) = czero ! ==== ensure that subdiagonal entries are real ==== if( wantt ) then jlo = 1_${ik}$ jhi = n else jlo = ilo jhi = ihi end if do i = ilo + 1, ihi if( aimag( h( i, i-1 ) )/=zero ) then ! ==== the following redundant normalization ! . avoids problems with both gradual and ! . sudden underflow in abs(h(i,i-1)) ==== sc = h( i, i-1 ) / cabs1( h( i, i-1 ) ) sc = conjg( sc ) / abs( sc ) h( i, i-1 ) = abs( h( i, i-1 ) ) call stdlib${ii}$_cscal( jhi-i+1, sc, h( i, i ), ldh ) call stdlib${ii}$_cscal( min( jhi, i+1 )-jlo+1, conjg( sc ), h( jlo, i ),1_${ik}$ ) if( wantz )call stdlib${ii}$_cscal( ihiz-iloz+1, conjg( sc ), z( iloz, i ), 1_${ik}$ ) end if end do nh = ihi - ilo + 1_${ik}$ nz = ihiz - iloz + 1_${ik}$ ! set machine-dependent constants for the stopping criterion. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( nh,KIND=sp) / ulp ) ! i1 and i2 are the indices of the first row and last column of h ! to which transformations must be applied. if eigenvalues only are ! being computed, i1 and i2 are set inside the main loop. if( wantt ) then i1 = 1_${ik}$ i2 = n end if ! itmax is the total number of qr iterations allowed. itmax = 30_${ik}$ * max( 10_${ik}$, nh ) ! kdefl counts the number of iterations since a deflation kdefl = 0_${ik}$ ! the main loop begins here. i is the loop index and decreases from ! ihi to ilo in steps of 1. each iteration of the loop works ! with the active submatrix in rows and columns l to i. ! eigenvalues i+1 to ihi have already converged. either l = ilo, or ! h(l,l-1) is negligible so that the matrix splits. i = ihi 30 continue if( i=ilo )tst = tst + abs( real( h( k-1, k-2 ),KIND=sp) ) if( k+1<=ihi )tst = tst + abs( real( h( k+1, k ),KIND=sp) ) end if ! ==== the following is a conservative small subdiagonal ! . deflation criterion due to ahues ! . 1997). it has better mathematical foundation and ! . improves accuracy in some examples. ==== if( abs( real( h( k, k-1 ),KIND=sp) )<=ulp*tst ) then ab = max( cabs1( h( k, k-1 ) ), cabs1( h( k-1, k ) ) ) ba = min( cabs1( h( k, k-1 ) ), cabs1( h( k-1, k ) ) ) aa = max( cabs1( h( k, k ) ),cabs1( h( k-1, k-1 )-h( k, k ) ) ) bb = min( cabs1( h( k, k ) ),cabs1( h( k-1, k-1 )-h( k, k ) ) ) s = aa + ab if( ba*( ab / s )<=max( smlnum,ulp*( bb*( aa / s ) ) ) )go to 50 end if end do 50 continue l = k if( l>ilo ) then ! h(l,l-1) is negligible h( l, l-1 ) = czero end if ! exit from loop if a submatrix of order 1 has split off. if( l>=i )go to 140 kdefl = kdefl + 1_${ik}$ ! now the active submatrix is in rows and columns l to i. if ! eigenvalues only are being computed, only the active submatrix ! need be transformed. if( .not.wantt ) then i1 = l i2 = i end if if( mod(kdefl,2_${ik}$*kexsh)==0_${ik}$ ) then ! exceptional shift. s = dat1*abs( real( h( i, i-1 ),KIND=sp) ) t = s + h( i, i ) else if( mod(kdefl,kexsh)==0_${ik}$ ) then ! exceptional shift. s = dat1*abs( real( h( l+1, l ),KIND=sp) ) t = s + h( l, l ) else ! wilkinson's shift. t = h( i, i ) u = sqrt( h( i-1, i ) )*sqrt( h( i, i-1 ) ) s = cabs1( u ) if( s/=zero ) then x = half*( h( i-1, i-1 )-t ) sx = cabs1( x ) s = max( s, cabs1( x ) ) y = s*sqrt( ( x / s )**2_${ik}$+( u / s )**2_${ik}$ ) if( sx>zero ) then if( real( x / sx,KIND=sp)*real( y,KIND=sp)+aimag( x / sx )*aimag( y )& m )call stdlib${ii}$_ccopy( 2_${ik}$, h( k, k-1 ), 1_${ik}$, v, 1_${ik}$ ) call stdlib${ii}$_clarfg( 2_${ik}$, v( 1_${ik}$ ), v( 2_${ik}$ ), 1_${ik}$, t1 ) if( k>m ) then h( k, k-1 ) = v( 1_${ik}$ ) h( k+1, k-1 ) = czero end if v2 = v( 2_${ik}$ ) t2 = real( t1*v2,KIND=sp) ! apply g from the left to transform the rows of the matrix ! in columns k to i2. do j = k, i2 sum = conjg( t1 )*h( k, j ) + t2*h( k+1, j ) h( k, j ) = h( k, j ) - sum h( k+1, j ) = h( k+1, j ) - sum*v2 end do ! apply g from the right to transform the columns of the ! matrix in rows i1 to min(k+2,i). do j = i1, min( k+2, i ) sum = t1*h( j, k ) + t2*h( j, k+1 ) h( j, k ) = h( j, k ) - sum h( j, k+1 ) = h( j, k+1 ) - sum*conjg( v2 ) end do if( wantz ) then ! accumulate transformations in the matrix z do j = iloz, ihiz sum = t1*z( j, k ) + t2*z( j, k+1 ) z( j, k ) = z( j, k ) - sum z( j, k+1 ) = z( j, k+1 ) - sum*conjg( v2 ) end do end if if( k==m .and. m>l ) then ! if the qr step was started at row m > l because two ! consecutive small subdiagonals were found, then extra ! scaling must be performed to ensure that h(m,m-1) remains ! real. temp = cone - t1 temp = temp / abs( temp ) h( m+1, m ) = h( m+1, m )*conjg( temp ) if( m+2<=i )h( m+2, m+1 ) = h( m+2, m+1 )*temp do j = m, i if( j/=m+1 ) then if( i2>j )call stdlib${ii}$_cscal( i2-j, temp, h( j, j+1 ), ldh ) call stdlib${ii}$_cscal( j-i1, conjg( temp ), h( i1, j ), 1_${ik}$ ) if( wantz ) then call stdlib${ii}$_cscal( nz, conjg( temp ), z( iloz, j ), 1_${ik}$ ) end if end if end do end if end do loop_120 ! ensure that h(i,i-1) is real. temp = h( i, i-1 ) if( aimag( temp )/=zero ) then rtemp = abs( temp ) h( i, i-1 ) = rtemp temp = temp / rtemp if( i2>i )call stdlib${ii}$_cscal( i2-i, conjg( temp ), h( i, i+1 ), ldh ) call stdlib${ii}$_cscal( i-i1, temp, h( i1, i ), 1_${ik}$ ) if( wantz ) then call stdlib${ii}$_cscal( nz, temp, z( iloz, i ), 1_${ik}$ ) end if end if end do loop_130 ! failure to converge in remaining number of iterations info = i return 140 continue ! h(i,i-1) is negligible: cone eigenvalue has converged. w( i ) = h( i, i ) ! reset deflation counter kdefl = 0_${ik}$ ! return to start of the main loop with new value of i. i = l - 1_${ik}$ go to 30 150 continue return end subroutine stdlib${ii}$_clahqr pure module subroutine stdlib${ii}$_zlahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, info & !! ZLAHQR is an auxiliary routine called by CHSEQR to update the !! eigenvalues and Schur decomposition already computed by CHSEQR, by !! dealing with the Hessenberg submatrix in rows and columns ILO to !! IHI. ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(dp), intent(inout) :: h(ldh,*), z(ldz,*) complex(dp), intent(out) :: w(*) ! ========================================================= ! Parameters real(dp), parameter :: dat1 = 3.0_dp/4.0_dp integer(${ik}$), parameter :: kexsh = 10_${ik}$ ! Local Scalars complex(dp) :: cdum, h11, h11s, h22, sc, sum, t, t1, temp, u, v2, x, y real(dp) :: aa, ab, ba, bb, h10, h21, rtemp, s, safmax, safmin, smlnum, sx, t2, tst, & ulp integer(${ik}$) :: i, i1, i2, its, itmax, j, jhi, jlo, k, l, m, nh, nz, kdefl ! Local Arrays complex(dp) :: v(2_${ik}$) ! Statement Functions real(dp) :: cabs1 ! Intrinsic Functions ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n==0 )return if( ilo==ihi ) then w( ilo ) = h( ilo, ilo ) return end if ! ==== clear out the trash ==== do j = ilo, ihi - 3 h( j+2, j ) = czero h( j+3, j ) = czero end do if( ilo<=ihi-2 )h( ihi, ihi-2 ) = czero ! ==== ensure that subdiagonal entries are real ==== if( wantt ) then jlo = 1_${ik}$ jhi = n else jlo = ilo jhi = ihi end if do i = ilo + 1, ihi if( aimag( h( i, i-1 ) )/=zero ) then ! ==== the following redundant normalization ! . avoids problems with both gradual and ! . sudden underflow in abs(h(i,i-1)) ==== sc = h( i, i-1 ) / cabs1( h( i, i-1 ) ) sc = conjg( sc ) / abs( sc ) h( i, i-1 ) = abs( h( i, i-1 ) ) call stdlib${ii}$_zscal( jhi-i+1, sc, h( i, i ), ldh ) call stdlib${ii}$_zscal( min( jhi, i+1 )-jlo+1, conjg( sc ),h( jlo, i ), 1_${ik}$ ) if( wantz )call stdlib${ii}$_zscal( ihiz-iloz+1, conjg( sc ), z( iloz, i ), 1_${ik}$ ) end if end do nh = ihi - ilo + 1_${ik}$ nz = ihiz - iloz + 1_${ik}$ ! set machine-dependent constants for the stopping criterion. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( nh,KIND=dp) / ulp ) ! i1 and i2 are the indices of the first row and last column of h ! to which transformations must be applied. if eigenvalues only are ! being computed, i1 and i2 are set inside the main loop. if( wantt ) then i1 = 1_${ik}$ i2 = n end if ! itmax is the total number of qr iterations allowed. itmax = 30_${ik}$ * max( 10_${ik}$, nh ) ! kdefl counts the number of iterations since a deflation kdefl = 0_${ik}$ ! the main loop begins here. i is the loop index and decreases from ! ihi to ilo in steps of 1. each iteration of the loop works ! with the active submatrix in rows and columns l to i. ! eigenvalues i+1 to ihi have already converged. either l = ilo, or ! h(l,l-1) is negligible so that the matrix splits. i = ihi 30 continue if( i=ilo )tst = tst + abs( real( h( k-1, k-2 ),KIND=dp) ) if( k+1<=ihi )tst = tst + abs( real( h( k+1, k ),KIND=dp) ) end if ! ==== the following is a conservative small subdiagonal ! . deflation criterion due to ahues ! . 1997). it has better mathematical foundation and ! . improves accuracy in some examples. ==== if( abs( real( h( k, k-1 ),KIND=dp) )<=ulp*tst ) then ab = max( cabs1( h( k, k-1 ) ), cabs1( h( k-1, k ) ) ) ba = min( cabs1( h( k, k-1 ) ), cabs1( h( k-1, k ) ) ) aa = max( cabs1( h( k, k ) ),cabs1( h( k-1, k-1 )-h( k, k ) ) ) bb = min( cabs1( h( k, k ) ),cabs1( h( k-1, k-1 )-h( k, k ) ) ) s = aa + ab if( ba*( ab / s )<=max( smlnum,ulp*( bb*( aa / s ) ) ) )go to 50 end if end do 50 continue l = k if( l>ilo ) then ! h(l,l-1) is negligible h( l, l-1 ) = czero end if ! exit from loop if a submatrix of order 1 has split off. if( l>=i )go to 140 kdefl = kdefl + 1_${ik}$ ! now the active submatrix is in rows and columns l to i. if ! eigenvalues only are being computed, only the active submatrix ! need be transformed. if( .not.wantt ) then i1 = l i2 = i end if if( mod(kdefl,2_${ik}$*kexsh)==0_${ik}$ ) then ! exceptional shift. s = dat1*abs( real( h( i, i-1 ),KIND=dp) ) t = s + h( i, i ) else if( mod(kdefl,kexsh)==0_${ik}$ ) then ! exceptional shift. s = dat1*abs( real( h( l+1, l ),KIND=dp) ) t = s + h( l, l ) else ! wilkinson's shift. t = h( i, i ) u = sqrt( h( i-1, i ) )*sqrt( h( i, i-1 ) ) s = cabs1( u ) if( s/=zero ) then x = half*( h( i-1, i-1 )-t ) sx = cabs1( x ) s = max( s, cabs1( x ) ) y = s*sqrt( ( x / s )**2_${ik}$+( u / s )**2_${ik}$ ) if( sx>zero ) then if( real( x / sx,KIND=dp)*real( y,KIND=dp)+aimag( x / sx )*aimag( y )& m )call stdlib${ii}$_zcopy( 2_${ik}$, h( k, k-1 ), 1_${ik}$, v, 1_${ik}$ ) call stdlib${ii}$_zlarfg( 2_${ik}$, v( 1_${ik}$ ), v( 2_${ik}$ ), 1_${ik}$, t1 ) if( k>m ) then h( k, k-1 ) = v( 1_${ik}$ ) h( k+1, k-1 ) = czero end if v2 = v( 2_${ik}$ ) t2 = real( t1*v2,KIND=dp) ! apply g from the left to transform the rows of the matrix ! in columns k to i2. do j = k, i2 sum = conjg( t1 )*h( k, j ) + t2*h( k+1, j ) h( k, j ) = h( k, j ) - sum h( k+1, j ) = h( k+1, j ) - sum*v2 end do ! apply g from the right to transform the columns of the ! matrix in rows i1 to min(k+2,i). do j = i1, min( k+2, i ) sum = t1*h( j, k ) + t2*h( j, k+1 ) h( j, k ) = h( j, k ) - sum h( j, k+1 ) = h( j, k+1 ) - sum*conjg( v2 ) end do if( wantz ) then ! accumulate transformations in the matrix z do j = iloz, ihiz sum = t1*z( j, k ) + t2*z( j, k+1 ) z( j, k ) = z( j, k ) - sum z( j, k+1 ) = z( j, k+1 ) - sum*conjg( v2 ) end do end if if( k==m .and. m>l ) then ! if the qr step was started at row m > l because two ! consecutive small subdiagonals were found, then extra ! scaling must be performed to ensure that h(m,m-1) remains ! real. temp = cone - t1 temp = temp / abs( temp ) h( m+1, m ) = h( m+1, m )*conjg( temp ) if( m+2<=i )h( m+2, m+1 ) = h( m+2, m+1 )*temp do j = m, i if( j/=m+1 ) then if( i2>j )call stdlib${ii}$_zscal( i2-j, temp, h( j, j+1 ), ldh ) call stdlib${ii}$_zscal( j-i1, conjg( temp ), h( i1, j ), 1_${ik}$ ) if( wantz ) then call stdlib${ii}$_zscal( nz, conjg( temp ), z( iloz, j ),1_${ik}$ ) end if end if end do end if end do loop_120 ! ensure that h(i,i-1) is real. temp = h( i, i-1 ) if( aimag( temp )/=zero ) then rtemp = abs( temp ) h( i, i-1 ) = rtemp temp = temp / rtemp if( i2>i )call stdlib${ii}$_zscal( i2-i, conjg( temp ), h( i, i+1 ), ldh ) call stdlib${ii}$_zscal( i-i1, temp, h( i1, i ), 1_${ik}$ ) if( wantz ) then call stdlib${ii}$_zscal( nz, temp, z( iloz, i ), 1_${ik}$ ) end if end if end do loop_130 ! failure to converge in remaining number of iterations info = i return 140 continue ! h(i,i-1) is negligible: cone eigenvalue has converged. w( i ) = h( i, i ) ! reset deflation counter kdefl = 0_${ik}$ ! return to start of the main loop with new value of i. i = l - 1_${ik}$ go to 30 150 continue return end subroutine stdlib${ii}$_zlahqr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, info & !! ZLAHQR: is an auxiliary routine called by CHSEQR to update the !! eigenvalues and Schur decomposition already computed by CHSEQR, by !! dealing with the Hessenberg submatrix in rows and columns ILO to !! IHI. ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(${ck}$), intent(inout) :: h(ldh,*), z(ldz,*) complex(${ck}$), intent(out) :: w(*) ! ========================================================= ! Parameters real(${ck}$), parameter :: dat1 = 3.0_${ck}$/4.0_${ck}$ integer(${ik}$), parameter :: kexsh = 10_${ik}$ ! Local Scalars complex(${ck}$) :: cdum, h11, h11s, h22, sc, sum, t, t1, temp, u, v2, x, y real(${ck}$) :: aa, ab, ba, bb, h10, h21, rtemp, s, safmax, safmin, smlnum, sx, t2, tst, & ulp integer(${ik}$) :: i, i1, i2, its, itmax, j, jhi, jlo, k, l, m, nh, nz, kdefl ! Local Arrays complex(${ck}$) :: v(2_${ik}$) ! Statement Functions real(${ck}$) :: cabs1 ! Intrinsic Functions ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n==0 )return if( ilo==ihi ) then w( ilo ) = h( ilo, ilo ) return end if ! ==== clear out the trash ==== do j = ilo, ihi - 3 h( j+2, j ) = czero h( j+3, j ) = czero end do if( ilo<=ihi-2 )h( ihi, ihi-2 ) = czero ! ==== ensure that subdiagonal entries are real ==== if( wantt ) then jlo = 1_${ik}$ jhi = n else jlo = ilo jhi = ihi end if do i = ilo + 1, ihi if( aimag( h( i, i-1 ) )/=zero ) then ! ==== the following redundant normalization ! . avoids problems with both gradual and ! . sudden underflow in abs(h(i,i-1)) ==== sc = h( i, i-1 ) / cabs1( h( i, i-1 ) ) sc = conjg( sc ) / abs( sc ) h( i, i-1 ) = abs( h( i, i-1 ) ) call stdlib${ii}$_${ci}$scal( jhi-i+1, sc, h( i, i ), ldh ) call stdlib${ii}$_${ci}$scal( min( jhi, i+1 )-jlo+1, conjg( sc ),h( jlo, i ), 1_${ik}$ ) if( wantz )call stdlib${ii}$_${ci}$scal( ihiz-iloz+1, conjg( sc ), z( iloz, i ), 1_${ik}$ ) end if end do nh = ihi - ilo + 1_${ik}$ nz = ihiz - iloz + 1_${ik}$ ! set machine-dependent constants for the stopping criterion. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_${c2ri(ci)}$labad( safmin, safmax ) ulp = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin*( real( nh,KIND=${ck}$) / ulp ) ! i1 and i2 are the indices of the first row and last column of h ! to which transformations must be applied. if eigenvalues only are ! being computed, i1 and i2 are set inside the main loop. if( wantt ) then i1 = 1_${ik}$ i2 = n end if ! itmax is the total number of qr iterations allowed. itmax = 30_${ik}$ * max( 10_${ik}$, nh ) ! kdefl counts the number of iterations since a deflation kdefl = 0_${ik}$ ! the main loop begins here. i is the loop index and decreases from ! ihi to ilo in steps of 1. each iteration of the loop works ! with the active submatrix in rows and columns l to i. ! eigenvalues i+1 to ihi have already converged. either l = ilo, or ! h(l,l-1) is negligible so that the matrix splits. i = ihi 30 continue if( i=ilo )tst = tst + abs( real( h( k-1, k-2 ),KIND=${ck}$) ) if( k+1<=ihi )tst = tst + abs( real( h( k+1, k ),KIND=${ck}$) ) end if ! ==== the following is a conservative small subdiagonal ! . deflation criterion due to ahues ! . 1997). it has better mathematical foundation and ! . improves accuracy in some examples. ==== if( abs( real( h( k, k-1 ),KIND=${ck}$) )<=ulp*tst ) then ab = max( cabs1( h( k, k-1 ) ), cabs1( h( k-1, k ) ) ) ba = min( cabs1( h( k, k-1 ) ), cabs1( h( k-1, k ) ) ) aa = max( cabs1( h( k, k ) ),cabs1( h( k-1, k-1 )-h( k, k ) ) ) bb = min( cabs1( h( k, k ) ),cabs1( h( k-1, k-1 )-h( k, k ) ) ) s = aa + ab if( ba*( ab / s )<=max( smlnum,ulp*( bb*( aa / s ) ) ) )go to 50 end if end do 50 continue l = k if( l>ilo ) then ! h(l,l-1) is negligible h( l, l-1 ) = czero end if ! exit from loop if a submatrix of order 1 has split off. if( l>=i )go to 140 kdefl = kdefl + 1_${ik}$ ! now the active submatrix is in rows and columns l to i. if ! eigenvalues only are being computed, only the active submatrix ! need be transformed. if( .not.wantt ) then i1 = l i2 = i end if if( mod(kdefl,2_${ik}$*kexsh)==0_${ik}$ ) then ! exceptional shift. s = dat1*abs( real( h( i, i-1 ),KIND=${ck}$) ) t = s + h( i, i ) else if( mod(kdefl,kexsh)==0_${ik}$ ) then ! exceptional shift. s = dat1*abs( real( h( l+1, l ),KIND=${ck}$) ) t = s + h( l, l ) else ! wilkinson's shift. t = h( i, i ) u = sqrt( h( i-1, i ) )*sqrt( h( i, i-1 ) ) s = cabs1( u ) if( s/=zero ) then x = half*( h( i-1, i-1 )-t ) sx = cabs1( x ) s = max( s, cabs1( x ) ) y = s*sqrt( ( x / s )**2_${ik}$+( u / s )**2_${ik}$ ) if( sx>zero ) then if( real( x / sx,KIND=${ck}$)*real( y,KIND=${ck}$)+aimag( x / sx )*aimag( y )& m )call stdlib${ii}$_${ci}$copy( 2_${ik}$, h( k, k-1 ), 1_${ik}$, v, 1_${ik}$ ) call stdlib${ii}$_${ci}$larfg( 2_${ik}$, v( 1_${ik}$ ), v( 2_${ik}$ ), 1_${ik}$, t1 ) if( k>m ) then h( k, k-1 ) = v( 1_${ik}$ ) h( k+1, k-1 ) = czero end if v2 = v( 2_${ik}$ ) t2 = real( t1*v2,KIND=${ck}$) ! apply g from the left to transform the rows of the matrix ! in columns k to i2. do j = k, i2 sum = conjg( t1 )*h( k, j ) + t2*h( k+1, j ) h( k, j ) = h( k, j ) - sum h( k+1, j ) = h( k+1, j ) - sum*v2 end do ! apply g from the right to transform the columns of the ! matrix in rows i1 to min(k+2,i). do j = i1, min( k+2, i ) sum = t1*h( j, k ) + t2*h( j, k+1 ) h( j, k ) = h( j, k ) - sum h( j, k+1 ) = h( j, k+1 ) - sum*conjg( v2 ) end do if( wantz ) then ! accumulate transformations in the matrix z do j = iloz, ihiz sum = t1*z( j, k ) + t2*z( j, k+1 ) z( j, k ) = z( j, k ) - sum z( j, k+1 ) = z( j, k+1 ) - sum*conjg( v2 ) end do end if if( k==m .and. m>l ) then ! if the qr step was started at row m > l because two ! consecutive small subdiagonals were found, then extra ! scaling must be performed to ensure that h(m,m-1) remains ! real. temp = cone - t1 temp = temp / abs( temp ) h( m+1, m ) = h( m+1, m )*conjg( temp ) if( m+2<=i )h( m+2, m+1 ) = h( m+2, m+1 )*temp do j = m, i if( j/=m+1 ) then if( i2>j )call stdlib${ii}$_${ci}$scal( i2-j, temp, h( j, j+1 ), ldh ) call stdlib${ii}$_${ci}$scal( j-i1, conjg( temp ), h( i1, j ), 1_${ik}$ ) if( wantz ) then call stdlib${ii}$_${ci}$scal( nz, conjg( temp ), z( iloz, j ),1_${ik}$ ) end if end if end do end if end do loop_120 ! ensure that h(i,i-1) is real. temp = h( i, i-1 ) if( aimag( temp )/=zero ) then rtemp = abs( temp ) h( i, i-1 ) = rtemp temp = temp / rtemp if( i2>i )call stdlib${ii}$_${ci}$scal( i2-i, conjg( temp ), h( i, i+1 ), ldh ) call stdlib${ii}$_${ci}$scal( i-i1, temp, h( i1, i ), 1_${ik}$ ) if( wantz ) then call stdlib${ii}$_${ci}$scal( nz, temp, z( iloz, i ), 1_${ik}$ ) end if end if end do loop_130 ! failure to converge in remaining number of iterations info = i return 140 continue ! h(i,i-1) is negligible: cone eigenvalue has converged. w( i ) = h( i, i ) ! reset deflation counter kdefl = 0_${ik}$ ! return to start of the main loop with new value of i. i = l - 1_${ik}$ go to 30 150 continue return end subroutine stdlib${ii}$_${ci}$lahqr #:endif #:endfor module subroutine stdlib${ii}$_slaqr0( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, work,& !! SLAQR0 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**T, where T is an upper quasi-triangular matrix (the !! Schur form), and Z is the orthogonal matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input orthogonal !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(sp), intent(inout) :: h(ldh,*), z(ldz,*) real(sp), intent(out) :: wi(*), work(*), wr(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(sp), parameter :: wilk1 = 0.75_sp real(sp), parameter :: wilk2 = -0.4375_sp ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_slahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constants wilk1 and wilk2 are used to form the ! . exceptional shifts. ==== ! Local Scalars real(sp) :: aa, bb, cc, cs, dd, sn, ss, swap integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2_${ik}$) :: jbcmpz ! Local Arrays real(sp) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = one return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_slahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_slahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, & ihiz, z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'SLAQR0', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'SLAQR0', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_slaqr3 ==== call stdlib${ii}$_slaqr3( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, wr, wi, h, ldh, n, h, ldh,n, h, ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_slaqr5, stdlib${ii}$_slaqr3) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=sp) return end if ! ==== stdlib${ii}$_slahqr/stdlib${ii}$_slaqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'SLAQR0', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'SLAQR0', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'SLAQR0', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_80: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( abs( h( kwtop, kwtop-1 ) )>abs( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_slaqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, wr, wi, h( kv, 1_${ik}$ ), ldh,nho, h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh,& work, lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_slaqr3 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_slaqr3 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, max( ks+1, ktop+2 ), -2 ss = abs( h( i, i-1 ) ) + abs( h( i-1, i-2 ) ) aa = wilk1*ss + h( i, i ) bb = ss cc = wilk2*ss dd = aa call stdlib${ii}$_slanv2( aa, bb, cc, dd, wr( i-1 ), wi( i-1 ),wr( i ), wi( i & ), cs, sn ) end do if( ks==ktop ) then wr( ks+1 ) = h( ks+1, ks+1 ) wi( ks+1 ) = zero wr( ks ) = wr( ks+1 ) wi( ks ) = wi( ks+1 ) end if else ! ==== got ns/2 or fewer shifts? use stdlib_slaqr4 or ! . stdlib${ii}$_slahqr on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_slacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) if( ns>nmin ) then call stdlib${ii}$_slaqr4( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, wr( & ks ),wi( ks ), 1_${ik}$, 1_${ik}$, zdum, 1_${ik}$, work,lwork, inf ) else call stdlib${ii}$_slahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, wr( & ks ),wi( ks ), 1_${ik}$, 1_${ik}$, zdum, 1_${ik}$, inf ) end if ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. ==== if( ks>=kbot ) then aa = h( kbot-1, kbot-1 ) cc = h( kbot, kbot-1 ) bb = h( kbot-1, kbot ) dd = h( kbot, kbot ) call stdlib${ii}$_slanv2( aa, bb, cc, dd, wr( kbot-1 ),wi( kbot-1 ), wr( & kbot ),wi( kbot ), cs, sn ) ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ! . bubble sort keeps complex conjugate ! . pairs together. ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( abs( wr( i ) )+abs( wi( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_80 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 90 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=sp) end subroutine stdlib${ii}$_slaqr0 module subroutine stdlib${ii}$_dlaqr0( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, work,& !! DLAQR0 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**T, where T is an upper quasi-triangular matrix (the !! Schur form), and Z is the orthogonal matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input orthogonal !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(dp), intent(inout) :: h(ldh,*), z(ldz,*) real(dp), intent(out) :: wi(*), work(*), wr(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(dp), parameter :: wilk1 = 0.75_dp real(dp), parameter :: wilk2 = -0.4375_dp ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_dlahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constants wilk1 and wilk2 are used to form the ! . exceptional shifts. ==== ! Local Scalars real(dp) :: aa, bb, cc, cs, dd, sn, ss, swap integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2_${ik}$) :: jbcmpz ! Local Arrays real(dp) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = one return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_dlahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_dlahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, & ihiz, z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'DLAQR0', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'DLAQR0', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_dlaqr3 ==== call stdlib${ii}$_dlaqr3( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, wr, wi, h, ldh, n, h, ldh,n, h, ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_dlaqr5, stdlib${ii}$_dlaqr3) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=dp) return end if ! ==== stdlib${ii}$_dlahqr/stdlib${ii}$_dlaqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'DLAQR0', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'DLAQR0', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'DLAQR0', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_80: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( abs( h( kwtop, kwtop-1 ) )>abs( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_dlaqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, wr, wi, h( kv, 1_${ik}$ ), ldh,nho, h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh,& work, lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_dlaqr3 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_dlaqr3 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, max( ks+1, ktop+2 ), -2 ss = abs( h( i, i-1 ) ) + abs( h( i-1, i-2 ) ) aa = wilk1*ss + h( i, i ) bb = ss cc = wilk2*ss dd = aa call stdlib${ii}$_dlanv2( aa, bb, cc, dd, wr( i-1 ), wi( i-1 ),wr( i ), wi( i & ), cs, sn ) end do if( ks==ktop ) then wr( ks+1 ) = h( ks+1, ks+1 ) wi( ks+1 ) = zero wr( ks ) = wr( ks+1 ) wi( ks ) = wi( ks+1 ) end if else ! ==== got ns/2 or fewer shifts? use stdlib_dlaqr4 or ! . stdlib${ii}$_dlahqr on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_dlacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) if( ns>nmin ) then call stdlib${ii}$_dlaqr4( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, wr( & ks ),wi( ks ), 1_${ik}$, 1_${ik}$, zdum, 1_${ik}$, work,lwork, inf ) else call stdlib${ii}$_dlahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, wr( & ks ),wi( ks ), 1_${ik}$, 1_${ik}$, zdum, 1_${ik}$, inf ) end if ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. ==== if( ks>=kbot ) then aa = h( kbot-1, kbot-1 ) cc = h( kbot, kbot-1 ) bb = h( kbot-1, kbot ) dd = h( kbot, kbot ) call stdlib${ii}$_dlanv2( aa, bb, cc, dd, wr( kbot-1 ),wi( kbot-1 ), wr( & kbot ),wi( kbot ), cs, sn ) ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ! . bubble sort keeps complex conjugate ! . pairs together. ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( abs( wr( i ) )+abs( wi( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_80 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 90 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=dp) end subroutine stdlib${ii}$_dlaqr0 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$laqr0( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, work,& !! DLAQR0: computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**T, where T is an upper quasi-triangular matrix (the !! Schur form), and Z is the orthogonal matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input orthogonal !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(${rk}$), intent(inout) :: h(ldh,*), z(ldz,*) real(${rk}$), intent(out) :: wi(*), work(*), wr(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(${rk}$), parameter :: wilk1 = 0.75_${rk}$ real(${rk}$), parameter :: wilk2 = -0.4375_${rk}$ ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_${ri}$lahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constants wilk1 and wilk2 are used to form the ! . exceptional shifts. ==== ! Local Scalars real(${rk}$) :: aa, bb, cc, cs, dd, sn, ss, swap integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2_${ik}$) :: jbcmpz ! Local Arrays real(${rk}$) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = one return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_${ri}$lahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_${ri}$lahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, & ihiz, z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'DLAQR0', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'DLAQR0', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_${ri}$laqr3 ==== call stdlib${ii}$_${ri}$laqr3( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, wr, wi, h, ldh, n, h, ldh,n, h, ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_${ri}$laqr5, stdlib${ii}$_${ri}$laqr3) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=${rk}$) return end if ! ==== stdlib${ii}$_${ri}$lahqr/stdlib${ii}$_${ri}$laqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'DLAQR0', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'DLAQR0', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'DLAQR0', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_80: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( abs( h( kwtop, kwtop-1 ) )>abs( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_${ri}$laqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, wr, wi, h( kv, 1_${ik}$ ), ldh,nho, h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh,& work, lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_${ri}$laqr3 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_${ri}$laqr3 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, max( ks+1, ktop+2 ), -2 ss = abs( h( i, i-1 ) ) + abs( h( i-1, i-2 ) ) aa = wilk1*ss + h( i, i ) bb = ss cc = wilk2*ss dd = aa call stdlib${ii}$_${ri}$lanv2( aa, bb, cc, dd, wr( i-1 ), wi( i-1 ),wr( i ), wi( i & ), cs, sn ) end do if( ks==ktop ) then wr( ks+1 ) = h( ks+1, ks+1 ) wi( ks+1 ) = zero wr( ks ) = wr( ks+1 ) wi( ks ) = wi( ks+1 ) end if else ! ==== got ns/2 or fewer shifts? use stdlib_${ri}$laqr4 or ! . stdlib${ii}$_${ri}$lahqr on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_${ri}$lacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) if( ns>nmin ) then call stdlib${ii}$_${ri}$laqr4( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, wr( & ks ),wi( ks ), 1_${ik}$, 1_${ik}$, zdum, 1_${ik}$, work,lwork, inf ) else call stdlib${ii}$_${ri}$lahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, wr( & ks ),wi( ks ), 1_${ik}$, 1_${ik}$, zdum, 1_${ik}$, inf ) end if ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. ==== if( ks>=kbot ) then aa = h( kbot-1, kbot-1 ) cc = h( kbot, kbot-1 ) bb = h( kbot-1, kbot ) dd = h( kbot, kbot ) call stdlib${ii}$_${ri}$lanv2( aa, bb, cc, dd, wr( kbot-1 ),wi( kbot-1 ), wr( & kbot ),wi( kbot ), cs, sn ) ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ! . bubble sort keeps complex conjugate ! . pairs together. ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( abs( wr( i ) )+abs( wi( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_80 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 90 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=${rk}$) end subroutine stdlib${ii}$_${ri}$laqr0 #:endif #:endfor pure module subroutine stdlib${ii}$_claqr0( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, work,& !! CLAQR0 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*H*(QZ)**H. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(sp), intent(inout) :: h(ldh,*), z(ldz,*) complex(sp), intent(out) :: w(*), work(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(sp), parameter :: wilk1 = 0.75_sp ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_clahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constant wilk1 is used to form the exceptional ! . shifts. ==== ! Local Scalars complex(sp) :: aa, bb, cc, cdum, dd, det, rtdisc, swap, tr2 real(sp) :: s integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2) :: jbcmpz ! Local Arrays complex(sp) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = cone return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_clahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_clahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, & z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'CLAQR0', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'CLAQR0', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_claqr3 ==== call stdlib${ii}$_claqr3( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, w, h, ldh, n, h, ldh, n, h,ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_claqr5, stdlib${ii}$_claqr3) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=sp) return end if ! ==== stdlib${ii}$_clahqr/stdlib${ii}$_claqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'CLAQR0', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'CLAQR0', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'CLAQR0', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_70: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( cabs1( h( kwtop, kwtop-1 ) )>cabs1( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_claqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, w, h( kv, 1_${ik}$ ), ldh, nho,h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh, work,& lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_claqr3 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_claqr3 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, ks + 1, -2 w( i ) = h( i, i ) + wilk1*cabs1( h( i, i-1 ) ) w( i-1 ) = w( i ) end do else ! ==== got ns/2 or fewer shifts? use stdlib_claqr4 or ! . stdlib${ii}$_clahqr on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_clacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) if( ns>nmin ) then call stdlib${ii}$_claqr4( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, w( & ks ), 1_${ik}$, 1_${ik}$,zdum, 1_${ik}$, work, lwork, inf ) else call stdlib${ii}$_clahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, w( & ks ), 1_${ik}$, 1_${ik}$,zdum, 1_${ik}$, inf ) end if ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. scale to avoid ! . overflows, underflows and subnormals. ! . (the scale factor s can not be czero, ! . because h(kbot,kbot-1) is nonzero.) ==== if( ks>=kbot ) then s = cabs1( h( kbot-1, kbot-1 ) ) +cabs1( h( kbot, kbot-1 ) ) +cabs1( & h( kbot-1, kbot ) ) +cabs1( h( kbot, kbot ) ) aa = h( kbot-1, kbot-1 ) / s cc = h( kbot, kbot-1 ) / s bb = h( kbot-1, kbot ) / s dd = h( kbot, kbot ) / s tr2 = ( aa+dd ) / two det = ( aa-tr2 )*( dd-tr2 ) - bb*cc rtdisc = sqrt( -det ) w( kbot-1 ) = ( tr2+rtdisc )*s w( kbot ) = ( tr2-rtdisc )*s ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( cabs1( w( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_70 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 80 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=sp) end subroutine stdlib${ii}$_claqr0 pure module subroutine stdlib${ii}$_zlaqr0( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, work,& !! ZLAQR0 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*H*(QZ)**H. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(dp), intent(inout) :: h(ldh,*), z(ldz,*) complex(dp), intent(out) :: w(*), work(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(dp), parameter :: wilk1 = 0.75_dp ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_zlahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constant wilk1 is used to form the exceptional ! . shifts. ==== ! Local Scalars complex(dp) :: aa, bb, cc, cdum, dd, det, rtdisc, swap, tr2 real(dp) :: s integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2) :: jbcmpz ! Local Arrays complex(dp) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = cone return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_zlahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_zlahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, & z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'ZLAQR0', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'ZLAQR0', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_zlaqr3 ==== call stdlib${ii}$_zlaqr3( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, w, h, ldh, n, h, ldh, n, h,ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_zlaqr5, stdlib${ii}$_zlaqr3) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=dp) return end if ! ==== stdlib${ii}$_zlahqr/stdlib${ii}$_zlaqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'ZLAQR0', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'ZLAQR0', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'ZLAQR0', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_70: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( cabs1( h( kwtop, kwtop-1 ) )>cabs1( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_zlaqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, w, h( kv, 1_${ik}$ ), ldh, nho,h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh, work,& lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_zlaqr3 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_zlaqr3 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, ks + 1, -2 w( i ) = h( i, i ) + wilk1*cabs1( h( i, i-1 ) ) w( i-1 ) = w( i ) end do else ! ==== got ns/2 or fewer shifts? use stdlib_zlaqr4 or ! . stdlib${ii}$_zlahqr on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_zlacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) if( ns>nmin ) then call stdlib${ii}$_zlaqr4( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, w( & ks ), 1_${ik}$, 1_${ik}$,zdum, 1_${ik}$, work, lwork, inf ) else call stdlib${ii}$_zlahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, w( & ks ), 1_${ik}$, 1_${ik}$,zdum, 1_${ik}$, inf ) end if ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. scale to avoid ! . overflows, underflows and subnormals. ! . (the scale factor s can not be czero, ! . because h(kbot,kbot-1) is nonzero.) ==== if( ks>=kbot ) then s = cabs1( h( kbot-1, kbot-1 ) ) +cabs1( h( kbot, kbot-1 ) ) +cabs1( & h( kbot-1, kbot ) ) +cabs1( h( kbot, kbot ) ) aa = h( kbot-1, kbot-1 ) / s cc = h( kbot, kbot-1 ) / s bb = h( kbot-1, kbot ) / s dd = h( kbot, kbot ) / s tr2 = ( aa+dd ) / two det = ( aa-tr2 )*( dd-tr2 ) - bb*cc rtdisc = sqrt( -det ) w( kbot-1 ) = ( tr2+rtdisc )*s w( kbot ) = ( tr2-rtdisc )*s ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( cabs1( w( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_70 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 80 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=dp) end subroutine stdlib${ii}$_zlaqr0 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqr0( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, work,& !! ZLAQR0: computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*H*(QZ)**H. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(${ck}$), intent(inout) :: h(ldh,*), z(ldz,*) complex(${ck}$), intent(out) :: w(*), work(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(${ck}$), parameter :: wilk1 = 0.75_${ck}$ ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_${ci}$lahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constant wilk1 is used to form the exceptional ! . shifts. ==== ! Local Scalars complex(${ck}$) :: aa, bb, cc, cdum, dd, det, rtdisc, swap, tr2 real(${ck}$) :: s integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2) :: jbcmpz ! Local Arrays complex(${ck}$) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = cone return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_${ci}$lahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_${ci}$lahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, & z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'ZLAQR0', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'ZLAQR0', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_${ci}$laqr3 ==== call stdlib${ii}$_${ci}$laqr3( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, w, h, ldh, n, h, ldh, n, h,ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_${ci}$laqr5, stdlib${ii}$_${ci}$laqr3) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=${ck}$) return end if ! ==== stdlib${ii}$_${ci}$lahqr/stdlib${ii}$_${ci}$laqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'ZLAQR0', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'ZLAQR0', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'ZLAQR0', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_70: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( cabs1( h( kwtop, kwtop-1 ) )>cabs1( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_${ci}$laqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, w, h( kv, 1_${ik}$ ), ldh, nho,h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh, work,& lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_${ci}$laqr3 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_${ci}$laqr3 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, ks + 1, -2 w( i ) = h( i, i ) + wilk1*cabs1( h( i, i-1 ) ) w( i-1 ) = w( i ) end do else ! ==== got ns/2 or fewer shifts? use stdlib_${ci}$laqr4 or ! . stdlib${ii}$_${ci}$lahqr on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_${ci}$lacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) if( ns>nmin ) then call stdlib${ii}$_${ci}$laqr4( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, w( & ks ), 1_${ik}$, 1_${ik}$,zdum, 1_${ik}$, work, lwork, inf ) else call stdlib${ii}$_${ci}$lahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, w( & ks ), 1_${ik}$, 1_${ik}$,zdum, 1_${ik}$, inf ) end if ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. scale to avoid ! . overflows, underflows and subnormals. ! . (the scale factor s can not be czero, ! . because h(kbot,kbot-1) is nonzero.) ==== if( ks>=kbot ) then s = cabs1( h( kbot-1, kbot-1 ) ) +cabs1( h( kbot, kbot-1 ) ) +cabs1( & h( kbot-1, kbot ) ) +cabs1( h( kbot, kbot ) ) aa = h( kbot-1, kbot-1 ) / s cc = h( kbot, kbot-1 ) / s bb = h( kbot-1, kbot ) / s dd = h( kbot, kbot ) / s tr2 = ( aa+dd ) / two det = ( aa-tr2 )*( dd-tr2 ) - bb*cc rtdisc = sqrt( -det ) w( kbot-1 ) = ( tr2+rtdisc )*s w( kbot ) = ( tr2-rtdisc )*s ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( cabs1( w( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_70 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 80 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=${ck}$) end subroutine stdlib${ii}$_${ci}$laqr0 #:endif #:endfor pure module subroutine stdlib${ii}$_slaqr1( n, h, ldh, sr1, si1, sr2, si2, v ) !! Given a 2-by-2 or 3-by-3 matrix H, SLAQR1: sets v to a !! scalar multiple of the first column of the product !! (*) K = (H - (sr1 + i*si1)*I)*(H - (sr2 + i*si2)*I) !! scaling to avoid overflows and most underflows. It !! is assumed that either !! 1) sr1 = sr2 and si1 = -si2 !! or !! 2) si1 = si2 = 0. !! This is useful for starting double implicit shift bulges !! in the QR algorithm. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: si1, si2, sr1, sr2 integer(${ik}$), intent(in) :: ldh, n ! Array Arguments real(sp), intent(in) :: h(ldh,*) real(sp), intent(out) :: v(*) ! ================================================================ ! Local Scalars real(sp) :: h21s, h31s, s ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n/=2_${ik}$ .and. n/=3_${ik}$ ) then return end if if( n==2_${ik}$ ) then s = abs( h( 1_${ik}$, 1_${ik}$ )-sr2 ) + abs( si2 ) + abs( h( 2_${ik}$, 1_${ik}$ ) ) if( s==zero ) then v( 1_${ik}$ ) = zero v( 2_${ik}$ ) = zero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = h21s*h( 1_${ik}$, 2_${ik}$ ) + ( h( 1_${ik}$, 1_${ik}$ )-sr1 )*( ( h( 1_${ik}$, 1_${ik}$ )-sr2 ) / s ) - si1*( & si2 / s ) v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-sr1-sr2 ) end if else s = abs( h( 1_${ik}$, 1_${ik}$ )-sr2 ) + abs( si2 ) + abs( h( 2_${ik}$, 1_${ik}$ ) ) +abs( h( 3_${ik}$, 1_${ik}$ ) ) if( s==zero ) then v( 1_${ik}$ ) = zero v( 2_${ik}$ ) = zero v( 3_${ik}$ ) = zero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s h31s = h( 3_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = ( h( 1_${ik}$, 1_${ik}$ )-sr1 )*( ( h( 1_${ik}$, 1_${ik}$ )-sr2 ) / s ) -si1*( si2 / s ) + h( 1_${ik}$, 2_${ik}$ )& *h21s + h( 1_${ik}$, 3_${ik}$ )*h31s v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-sr1-sr2 ) +h( 2_${ik}$, 3_${ik}$ )*h31s v( 3_${ik}$ ) = h31s*( h( 1_${ik}$, 1_${ik}$ )+h( 3_${ik}$, 3_${ik}$ )-sr1-sr2 ) +h21s*h( 3_${ik}$, 2_${ik}$ ) end if end if end subroutine stdlib${ii}$_slaqr1 pure module subroutine stdlib${ii}$_dlaqr1( n, h, ldh, sr1, si1, sr2, si2, v ) !! Given a 2-by-2 or 3-by-3 matrix H, DLAQR1: sets v to a !! scalar multiple of the first column of the product !! (*) K = (H - (sr1 + i*si1)*I)*(H - (sr2 + i*si2)*I) !! scaling to avoid overflows and most underflows. It !! is assumed that either !! 1) sr1 = sr2 and si1 = -si2 !! or !! 2) si1 = si2 = 0. !! This is useful for starting double implicit shift bulges !! in the QR algorithm. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: si1, si2, sr1, sr2 integer(${ik}$), intent(in) :: ldh, n ! Array Arguments real(dp), intent(in) :: h(ldh,*) real(dp), intent(out) :: v(*) ! ================================================================ ! Local Scalars real(dp) :: h21s, h31s, s ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n/=2_${ik}$ .and. n/=3_${ik}$ ) then return end if if( n==2_${ik}$ ) then s = abs( h( 1_${ik}$, 1_${ik}$ )-sr2 ) + abs( si2 ) + abs( h( 2_${ik}$, 1_${ik}$ ) ) if( s==zero ) then v( 1_${ik}$ ) = zero v( 2_${ik}$ ) = zero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = h21s*h( 1_${ik}$, 2_${ik}$ ) + ( h( 1_${ik}$, 1_${ik}$ )-sr1 )*( ( h( 1_${ik}$, 1_${ik}$ )-sr2 ) / s ) - si1*( & si2 / s ) v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-sr1-sr2 ) end if else s = abs( h( 1_${ik}$, 1_${ik}$ )-sr2 ) + abs( si2 ) + abs( h( 2_${ik}$, 1_${ik}$ ) ) +abs( h( 3_${ik}$, 1_${ik}$ ) ) if( s==zero ) then v( 1_${ik}$ ) = zero v( 2_${ik}$ ) = zero v( 3_${ik}$ ) = zero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s h31s = h( 3_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = ( h( 1_${ik}$, 1_${ik}$ )-sr1 )*( ( h( 1_${ik}$, 1_${ik}$ )-sr2 ) / s ) -si1*( si2 / s ) + h( 1_${ik}$, 2_${ik}$ )& *h21s + h( 1_${ik}$, 3_${ik}$ )*h31s v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-sr1-sr2 ) +h( 2_${ik}$, 3_${ik}$ )*h31s v( 3_${ik}$ ) = h31s*( h( 1_${ik}$, 1_${ik}$ )+h( 3_${ik}$, 3_${ik}$ )-sr1-sr2 ) +h21s*h( 3_${ik}$, 2_${ik}$ ) end if end if end subroutine stdlib${ii}$_dlaqr1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqr1( n, h, ldh, sr1, si1, sr2, si2, v ) !! Given a 2-by-2 or 3-by-3 matrix H, DLAQR1: sets v to a !! scalar multiple of the first column of the product !! (*) K = (H - (sr1 + i*si1)*I)*(H - (sr2 + i*si2)*I) !! scaling to avoid overflows and most underflows. It !! is assumed that either !! 1) sr1 = sr2 and si1 = -si2 !! or !! 2) si1 = si2 = 0. !! This is useful for starting double implicit shift bulges !! in the QR algorithm. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: si1, si2, sr1, sr2 integer(${ik}$), intent(in) :: ldh, n ! Array Arguments real(${rk}$), intent(in) :: h(ldh,*) real(${rk}$), intent(out) :: v(*) ! ================================================================ ! Local Scalars real(${rk}$) :: h21s, h31s, s ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n/=2_${ik}$ .and. n/=3_${ik}$ ) then return end if if( n==2_${ik}$ ) then s = abs( h( 1_${ik}$, 1_${ik}$ )-sr2 ) + abs( si2 ) + abs( h( 2_${ik}$, 1_${ik}$ ) ) if( s==zero ) then v( 1_${ik}$ ) = zero v( 2_${ik}$ ) = zero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = h21s*h( 1_${ik}$, 2_${ik}$ ) + ( h( 1_${ik}$, 1_${ik}$ )-sr1 )*( ( h( 1_${ik}$, 1_${ik}$ )-sr2 ) / s ) - si1*( & si2 / s ) v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-sr1-sr2 ) end if else s = abs( h( 1_${ik}$, 1_${ik}$ )-sr2 ) + abs( si2 ) + abs( h( 2_${ik}$, 1_${ik}$ ) ) +abs( h( 3_${ik}$, 1_${ik}$ ) ) if( s==zero ) then v( 1_${ik}$ ) = zero v( 2_${ik}$ ) = zero v( 3_${ik}$ ) = zero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s h31s = h( 3_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = ( h( 1_${ik}$, 1_${ik}$ )-sr1 )*( ( h( 1_${ik}$, 1_${ik}$ )-sr2 ) / s ) -si1*( si2 / s ) + h( 1_${ik}$, 2_${ik}$ )& *h21s + h( 1_${ik}$, 3_${ik}$ )*h31s v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-sr1-sr2 ) +h( 2_${ik}$, 3_${ik}$ )*h31s v( 3_${ik}$ ) = h31s*( h( 1_${ik}$, 1_${ik}$ )+h( 3_${ik}$, 3_${ik}$ )-sr1-sr2 ) +h21s*h( 3_${ik}$, 2_${ik}$ ) end if end if end subroutine stdlib${ii}$_${ri}$laqr1 #:endif #:endfor pure module subroutine stdlib${ii}$_claqr1( n, h, ldh, s1, s2, v ) !! Given a 2-by-2 or 3-by-3 matrix H, CLAQR1: sets v to a !! scalar multiple of the first column of the product !! (*) K = (H - s1*I)*(H - s2*I) !! scaling to avoid overflows and most underflows. !! This is useful for starting double implicit shift bulges !! in the QR algorithm. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments complex(sp), intent(in) :: s1, s2 integer(${ik}$), intent(in) :: ldh, n ! Array Arguments complex(sp), intent(in) :: h(ldh,*) complex(sp), intent(out) :: v(*) ! ================================================================ ! Parameters ! Local Scalars complex(sp) :: cdum, h21s, h31s real(sp) :: s ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements ! quick return if possible if( n/=2_${ik}$ .and. n/=3_${ik}$ ) then return end if if( n==2_${ik}$ ) then s = cabs1( h( 1_${ik}$, 1_${ik}$ )-s2 ) + cabs1( h( 2_${ik}$, 1_${ik}$ ) ) if( s==zero ) then v( 1_${ik}$ ) = czero v( 2_${ik}$ ) = czero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = h21s*h( 1_${ik}$, 2_${ik}$ ) + ( h( 1_${ik}$, 1_${ik}$ )-s1 )*( ( h( 1_${ik}$, 1_${ik}$ )-s2 ) / s ) v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-s1-s2 ) end if else s = cabs1( h( 1_${ik}$, 1_${ik}$ )-s2 ) + cabs1( h( 2_${ik}$, 1_${ik}$ ) ) +cabs1( h( 3_${ik}$, 1_${ik}$ ) ) if( s==czero ) then v( 1_${ik}$ ) = czero v( 2_${ik}$ ) = czero v( 3_${ik}$ ) = czero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s h31s = h( 3_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = ( h( 1_${ik}$, 1_${ik}$ )-s1 )*( ( h( 1_${ik}$, 1_${ik}$ )-s2 ) / s ) +h( 1_${ik}$, 2_${ik}$ )*h21s + h( 1_${ik}$, 3_${ik}$ )& *h31s v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-s1-s2 ) + h( 2_${ik}$, 3_${ik}$ )*h31s v( 3_${ik}$ ) = h31s*( h( 1_${ik}$, 1_${ik}$ )+h( 3_${ik}$, 3_${ik}$ )-s1-s2 ) + h21s*h( 3_${ik}$, 2_${ik}$ ) end if end if end subroutine stdlib${ii}$_claqr1 pure module subroutine stdlib${ii}$_zlaqr1( n, h, ldh, s1, s2, v ) !! Given a 2-by-2 or 3-by-3 matrix H, ZLAQR1: sets v to a !! scalar multiple of the first column of the product !! (*) K = (H - s1*I)*(H - s2*I) !! scaling to avoid overflows and most underflows. !! This is useful for starting double implicit shift bulges !! in the QR algorithm. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments complex(dp), intent(in) :: s1, s2 integer(${ik}$), intent(in) :: ldh, n ! Array Arguments complex(dp), intent(in) :: h(ldh,*) complex(dp), intent(out) :: v(*) ! ================================================================ ! Parameters ! Local Scalars complex(dp) :: cdum, h21s, h31s real(dp) :: s ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements ! quick return if possible if( n/=2_${ik}$ .and. n/=3_${ik}$ ) then return end if if( n==2_${ik}$ ) then s = cabs1( h( 1_${ik}$, 1_${ik}$ )-s2 ) + cabs1( h( 2_${ik}$, 1_${ik}$ ) ) if( s==zero ) then v( 1_${ik}$ ) = czero v( 2_${ik}$ ) = czero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = h21s*h( 1_${ik}$, 2_${ik}$ ) + ( h( 1_${ik}$, 1_${ik}$ )-s1 )*( ( h( 1_${ik}$, 1_${ik}$ )-s2 ) / s ) v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-s1-s2 ) end if else s = cabs1( h( 1_${ik}$, 1_${ik}$ )-s2 ) + cabs1( h( 2_${ik}$, 1_${ik}$ ) ) +cabs1( h( 3_${ik}$, 1_${ik}$ ) ) if( s==czero ) then v( 1_${ik}$ ) = czero v( 2_${ik}$ ) = czero v( 3_${ik}$ ) = czero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s h31s = h( 3_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = ( h( 1_${ik}$, 1_${ik}$ )-s1 )*( ( h( 1_${ik}$, 1_${ik}$ )-s2 ) / s ) +h( 1_${ik}$, 2_${ik}$ )*h21s + h( 1_${ik}$, 3_${ik}$ )& *h31s v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-s1-s2 ) + h( 2_${ik}$, 3_${ik}$ )*h31s v( 3_${ik}$ ) = h31s*( h( 1_${ik}$, 1_${ik}$ )+h( 3_${ik}$, 3_${ik}$ )-s1-s2 ) + h21s*h( 3_${ik}$, 2_${ik}$ ) end if end if end subroutine stdlib${ii}$_zlaqr1 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqr1( n, h, ldh, s1, s2, v ) !! Given a 2-by-2 or 3-by-3 matrix H, ZLAQR1: sets v to a !! scalar multiple of the first column of the product !! (*) K = (H - s1*I)*(H - s2*I) !! scaling to avoid overflows and most underflows. !! This is useful for starting double implicit shift bulges !! in the QR algorithm. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments complex(${ck}$), intent(in) :: s1, s2 integer(${ik}$), intent(in) :: ldh, n ! Array Arguments complex(${ck}$), intent(in) :: h(ldh,*) complex(${ck}$), intent(out) :: v(*) ! ================================================================ ! Parameters ! Local Scalars complex(${ck}$) :: cdum, h21s, h31s real(${ck}$) :: s ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements ! quick return if possible if( n/=2_${ik}$ .and. n/=3_${ik}$ ) then return end if if( n==2_${ik}$ ) then s = cabs1( h( 1_${ik}$, 1_${ik}$ )-s2 ) + cabs1( h( 2_${ik}$, 1_${ik}$ ) ) if( s==zero ) then v( 1_${ik}$ ) = czero v( 2_${ik}$ ) = czero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = h21s*h( 1_${ik}$, 2_${ik}$ ) + ( h( 1_${ik}$, 1_${ik}$ )-s1 )*( ( h( 1_${ik}$, 1_${ik}$ )-s2 ) / s ) v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-s1-s2 ) end if else s = cabs1( h( 1_${ik}$, 1_${ik}$ )-s2 ) + cabs1( h( 2_${ik}$, 1_${ik}$ ) ) +cabs1( h( 3_${ik}$, 1_${ik}$ ) ) if( s==czero ) then v( 1_${ik}$ ) = czero v( 2_${ik}$ ) = czero v( 3_${ik}$ ) = czero else h21s = h( 2_${ik}$, 1_${ik}$ ) / s h31s = h( 3_${ik}$, 1_${ik}$ ) / s v( 1_${ik}$ ) = ( h( 1_${ik}$, 1_${ik}$ )-s1 )*( ( h( 1_${ik}$, 1_${ik}$ )-s2 ) / s ) +h( 1_${ik}$, 2_${ik}$ )*h21s + h( 1_${ik}$, 3_${ik}$ )& *h31s v( 2_${ik}$ ) = h21s*( h( 1_${ik}$, 1_${ik}$ )+h( 2_${ik}$, 2_${ik}$ )-s1-s2 ) + h( 2_${ik}$, 3_${ik}$ )*h31s v( 3_${ik}$ ) = h31s*( h( 1_${ik}$, 1_${ik}$ )+h( 3_${ik}$, 3_${ik}$ )-s1-s2 ) + h21s*h( 3_${ik}$, 2_${ik}$ ) end if end if end subroutine stdlib${ii}$_${ci}$laqr1 #:endif #:endfor module subroutine stdlib${ii}$_slaqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, ns, nd,& !! SLAQR2 is identical to SLAQR3 except that it avoids !! recursion by calling SLAHQR instead of SLAQR4. !! Aggressive early deflation: !! This subroutine accepts as input an upper Hessenberg matrix !! H and performs an orthogonal similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an orthogonal similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. sr, si, v, ldv, nh, t,ldt, nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(sp), intent(inout) :: h(ldh,*), z(ldz,*) real(sp), intent(out) :: si(*), sr(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Local Scalars real(sp) :: aa, bb, beta, cc, cs, dd, evi, evk, foo, s, safmax, safmin, smlnum, sn, & tau, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, k, kcol, kend, kln, krow, kwtop, & ltop, lwk1, lwk2, lwkopt logical(lk) :: bulge, sorted ! Intrinsic Functions ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_sgehrd ==== call stdlib${ii}$_sgehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_sormhr ==== call stdlib${ii}$_sormhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = jw + max( lwk1, lwk2 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=sp) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = one if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=sp) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = zero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sr( kwtop ) = h( kwtop, kwtop ) si( kwtop ) = zero ns = 1_${ik}$ nd = 0_${ik}$ if( abs( s )<=max( smlnum, ulp*abs( h( kwtop, kwtop ) ) ) )then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = zero end if work( 1_${ik}$ ) = one return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_slacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_scopy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_slaset( 'A', jw, jw, zero, one, v, ldv ) call stdlib${ii}$_slahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr( kwtop ),si( kwtop ), 1_${ik}$, jw, & v, ldv, infqr ) ! ==== stdlib${ii}$_strexc needs a clean margin near the diagonal ==== do j = 1, jw - 3 t( j+2, j ) = zero t( j+3, j ) = zero end do if( jw>2_${ik}$ )t( jw, jw-2 ) = zero ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ 20 continue if( ilst<=ns ) then if( ns==1_${ik}$ ) then bulge = .false. else bulge = t( ns, ns-1 )/=zero end if ! ==== small spike tip test for deflation ==== if( .not.bulge ) then ! ==== real eigenvalue ==== foo = abs( t( ns, ns ) ) if( foo==zero )foo = abs( s ) if( abs( s*v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) ) then ! ==== deflatable ==== ns = ns - 1_${ik}$ else ! ==== undeflatable. move it up out of the way. ! . (stdlib${ii}$_strexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_strexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 1_${ik}$ end if else ! ==== complex conjugate pair ==== foo = abs( t( ns, ns ) ) + sqrt( abs( t( ns, ns-1 ) ) )*sqrt( abs( t( ns-1, ns ) & ) ) if( foo==zero )foo = abs( s ) if( max( abs( s*v( 1_${ik}$, ns ) ), abs( s*v( 1_${ik}$, ns-1 ) ) )<=max( smlnum, ulp*foo ) ) & then ! ==== deflatable ==== ns = ns - 2_${ik}$ else ! ==== undeflatable. move them up out of the way. ! . fortunately, stdlib${ii}$_strexc does the right thing with ! . ilst in case of a rare exchange failure. ==== ifst = ns call stdlib${ii}$_strexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 2_${ik}$ end if end if ! ==== end deflation detection loop ==== go to 20 end if ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = zero if( ns=evk ) then i = k else sorted = .false. ifst = i ilst = k call stdlib${ii}$_strexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) if( info==0_${ik}$ ) then i = ilst else i = k end if end if if( i==kend ) then k = i + 1_${ik}$ else if( t( i+1, i )==zero ) then k = i + 1_${ik}$ else k = i + 2_${ik}$ end if go to 40 end if go to 30 50 continue end if ! ==== restore shift/eigenvalue array from t ==== i = jw 60 continue if( i>=infqr+1 ) then if( i==infqr+1 ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else if( t( i, i-1 )==zero ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else aa = t( i-1, i-1 ) cc = t( i, i-1 ) bb = t( i-1, i ) dd = t( i, i ) call stdlib${ii}$_slanv2( aa, bb, cc, dd, sr( kwtop+i-2 ),si( kwtop+i-2 ), sr( kwtop+i-& 1_${ik}$ ),si( kwtop+i-1 ), cs, sn ) i = i - 2_${ik}$ end if go to 60 end if if( ns1_${ik}$ .and. s/=zero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_scopy( ns, v, ldv, work, 1_${ik}$ ) beta = work( 1_${ik}$ ) call stdlib${ii}$_slarfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = one call stdlib${ii}$_slaset( 'L', jw-2, jw-2, zero, zero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_slarf( 'L', ns, jw, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_slarf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_slarf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_sgehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*v( 1_${ik}$, 1_${ik}$ ) call stdlib${ii}$_slacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_scopy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=zero )call stdlib${ii}$_sormhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_sgemm( 'N', 'N', kln, jw, jw, one, h( krow, kwtop ),ldh, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_slacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_sgemm( 'C', 'N', jw, kln, jw, one, v, ldv,h( kwtop, kcol ), ldh, & zero, t, ldt ) call stdlib${ii}$_slacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_sgemm( 'N', 'N', kln, jw, jw, one, z( krow, kwtop ),ldz, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_slacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=sp) end subroutine stdlib${ii}$_slaqr2 module subroutine stdlib${ii}$_dlaqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, ns, nd,& !! DLAQR2 is identical to DLAQR3 except that it avoids !! recursion by calling DLAHQR instead of DLAQR4. !! Aggressive early deflation: !! This subroutine accepts as input an upper Hessenberg matrix !! H and performs an orthogonal similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an orthogonal similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. sr, si, v, ldv, nh, t,ldt, nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(dp), intent(inout) :: h(ldh,*), z(ldz,*) real(dp), intent(out) :: si(*), sr(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Local Scalars real(dp) :: aa, bb, beta, cc, cs, dd, evi, evk, foo, s, safmax, safmin, smlnum, sn, & tau, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, k, kcol, kend, kln, krow, kwtop, & ltop, lwk1, lwk2, lwkopt logical(lk) :: bulge, sorted ! Intrinsic Functions ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_dgehrd ==== call stdlib${ii}$_dgehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_dormhr ==== call stdlib${ii}$_dormhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = jw + max( lwk1, lwk2 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=dp) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = one if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=dp) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = zero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sr( kwtop ) = h( kwtop, kwtop ) si( kwtop ) = zero ns = 1_${ik}$ nd = 0_${ik}$ if( abs( s )<=max( smlnum, ulp*abs( h( kwtop, kwtop ) ) ) )then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = zero end if work( 1_${ik}$ ) = one return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_dlacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_dcopy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_dlaset( 'A', jw, jw, zero, one, v, ldv ) call stdlib${ii}$_dlahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr( kwtop ),si( kwtop ), 1_${ik}$, jw, & v, ldv, infqr ) ! ==== stdlib${ii}$_dtrexc needs a clean margin near the diagonal ==== do j = 1, jw - 3 t( j+2, j ) = zero t( j+3, j ) = zero end do if( jw>2_${ik}$ )t( jw, jw-2 ) = zero ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ 20 continue if( ilst<=ns ) then if( ns==1_${ik}$ ) then bulge = .false. else bulge = t( ns, ns-1 )/=zero end if ! ==== small spike tip test for deflation ==== if( .not.bulge ) then ! ==== real eigenvalue ==== foo = abs( t( ns, ns ) ) if( foo==zero )foo = abs( s ) if( abs( s*v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) ) then ! ==== deflatable ==== ns = ns - 1_${ik}$ else ! ==== undeflatable. move it up out of the way. ! . (stdlib${ii}$_dtrexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_dtrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 1_${ik}$ end if else ! ==== complex conjugate pair ==== foo = abs( t( ns, ns ) ) + sqrt( abs( t( ns, ns-1 ) ) )*sqrt( abs( t( ns-1, ns ) & ) ) if( foo==zero )foo = abs( s ) if( max( abs( s*v( 1_${ik}$, ns ) ), abs( s*v( 1_${ik}$, ns-1 ) ) )<=max( smlnum, ulp*foo ) ) & then ! ==== deflatable ==== ns = ns - 2_${ik}$ else ! ==== undeflatable. move them up out of the way. ! . fortunately, stdlib${ii}$_dtrexc does the right thing with ! . ilst in case of a rare exchange failure. ==== ifst = ns call stdlib${ii}$_dtrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 2_${ik}$ end if end if ! ==== end deflation detection loop ==== go to 20 end if ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = zero if( ns=evk ) then i = k else sorted = .false. ifst = i ilst = k call stdlib${ii}$_dtrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) if( info==0_${ik}$ ) then i = ilst else i = k end if end if if( i==kend ) then k = i + 1_${ik}$ else if( t( i+1, i )==zero ) then k = i + 1_${ik}$ else k = i + 2_${ik}$ end if go to 40 end if go to 30 50 continue end if ! ==== restore shift/eigenvalue array from t ==== i = jw 60 continue if( i>=infqr+1 ) then if( i==infqr+1 ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else if( t( i, i-1 )==zero ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else aa = t( i-1, i-1 ) cc = t( i, i-1 ) bb = t( i-1, i ) dd = t( i, i ) call stdlib${ii}$_dlanv2( aa, bb, cc, dd, sr( kwtop+i-2 ),si( kwtop+i-2 ), sr( kwtop+i-& 1_${ik}$ ),si( kwtop+i-1 ), cs, sn ) i = i - 2_${ik}$ end if go to 60 end if if( ns1_${ik}$ .and. s/=zero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_dcopy( ns, v, ldv, work, 1_${ik}$ ) beta = work( 1_${ik}$ ) call stdlib${ii}$_dlarfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = one call stdlib${ii}$_dlaset( 'L', jw-2, jw-2, zero, zero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_dlarf( 'L', ns, jw, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_dlarf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_dlarf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_dgehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*v( 1_${ik}$, 1_${ik}$ ) call stdlib${ii}$_dlacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_dcopy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=zero )call stdlib${ii}$_dormhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_dgemm( 'N', 'N', kln, jw, jw, one, h( krow, kwtop ),ldh, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_dlacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_dgemm( 'C', 'N', jw, kln, jw, one, v, ldv,h( kwtop, kcol ), ldh, & zero, t, ldt ) call stdlib${ii}$_dlacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_dgemm( 'N', 'N', kln, jw, jw, one, z( krow, kwtop ),ldz, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_dlacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=dp) end subroutine stdlib${ii}$_dlaqr2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$laqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, ns, nd,& !! DLAQR2: is identical to DLAQR3 except that it avoids !! recursion by calling DLAHQR instead of DLAQR4. !! Aggressive early deflation: !! This subroutine accepts as input an upper Hessenberg matrix !! H and performs an orthogonal similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an orthogonal similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. sr, si, v, ldv, nh, t,ldt, nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(${rk}$), intent(inout) :: h(ldh,*), z(ldz,*) real(${rk}$), intent(out) :: si(*), sr(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Local Scalars real(${rk}$) :: aa, bb, beta, cc, cs, dd, evi, evk, foo, s, safmax, safmin, smlnum, sn, & tau, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, k, kcol, kend, kln, krow, kwtop, & ltop, lwk1, lwk2, lwkopt logical(lk) :: bulge, sorted ! Intrinsic Functions ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_${ri}$gehrd ==== call stdlib${ii}$_${ri}$gehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_${ri}$ormhr ==== call stdlib${ii}$_${ri}$ormhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = jw + max( lwk1, lwk2 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=${rk}$) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = one if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_${ri}$labad( safmin, safmax ) ulp = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=${rk}$) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = zero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sr( kwtop ) = h( kwtop, kwtop ) si( kwtop ) = zero ns = 1_${ik}$ nd = 0_${ik}$ if( abs( s )<=max( smlnum, ulp*abs( h( kwtop, kwtop ) ) ) )then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = zero end if work( 1_${ik}$ ) = one return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_${ri}$lacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_${ri}$copy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_${ri}$laset( 'A', jw, jw, zero, one, v, ldv ) call stdlib${ii}$_${ri}$lahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr( kwtop ),si( kwtop ), 1_${ik}$, jw, & v, ldv, infqr ) ! ==== stdlib${ii}$_${ri}$trexc needs a clean margin near the diagonal ==== do j = 1, jw - 3 t( j+2, j ) = zero t( j+3, j ) = zero end do if( jw>2_${ik}$ )t( jw, jw-2 ) = zero ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ 20 continue if( ilst<=ns ) then if( ns==1_${ik}$ ) then bulge = .false. else bulge = t( ns, ns-1 )/=zero end if ! ==== small spike tip test for deflation ==== if( .not.bulge ) then ! ==== real eigenvalue ==== foo = abs( t( ns, ns ) ) if( foo==zero )foo = abs( s ) if( abs( s*v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) ) then ! ==== deflatable ==== ns = ns - 1_${ik}$ else ! ==== undeflatable. move it up out of the way. ! . (stdlib${ii}$_${ri}$trexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_${ri}$trexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 1_${ik}$ end if else ! ==== complex conjugate pair ==== foo = abs( t( ns, ns ) ) + sqrt( abs( t( ns, ns-1 ) ) )*sqrt( abs( t( ns-1, ns ) & ) ) if( foo==zero )foo = abs( s ) if( max( abs( s*v( 1_${ik}$, ns ) ), abs( s*v( 1_${ik}$, ns-1 ) ) )<=max( smlnum, ulp*foo ) ) & then ! ==== deflatable ==== ns = ns - 2_${ik}$ else ! ==== undeflatable. move them up out of the way. ! . fortunately, stdlib${ii}$_${ri}$trexc does the right thing with ! . ilst in case of a rare exchange failure. ==== ifst = ns call stdlib${ii}$_${ri}$trexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 2_${ik}$ end if end if ! ==== end deflation detection loop ==== go to 20 end if ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = zero if( ns=evk ) then i = k else sorted = .false. ifst = i ilst = k call stdlib${ii}$_${ri}$trexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) if( info==0_${ik}$ ) then i = ilst else i = k end if end if if( i==kend ) then k = i + 1_${ik}$ else if( t( i+1, i )==zero ) then k = i + 1_${ik}$ else k = i + 2_${ik}$ end if go to 40 end if go to 30 50 continue end if ! ==== restore shift/eigenvalue array from t ==== i = jw 60 continue if( i>=infqr+1 ) then if( i==infqr+1 ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else if( t( i, i-1 )==zero ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else aa = t( i-1, i-1 ) cc = t( i, i-1 ) bb = t( i-1, i ) dd = t( i, i ) call stdlib${ii}$_${ri}$lanv2( aa, bb, cc, dd, sr( kwtop+i-2 ),si( kwtop+i-2 ), sr( kwtop+i-& 1_${ik}$ ),si( kwtop+i-1 ), cs, sn ) i = i - 2_${ik}$ end if go to 60 end if if( ns1_${ik}$ .and. s/=zero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_${ri}$copy( ns, v, ldv, work, 1_${ik}$ ) beta = work( 1_${ik}$ ) call stdlib${ii}$_${ri}$larfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = one call stdlib${ii}$_${ri}$laset( 'L', jw-2, jw-2, zero, zero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_${ri}$larf( 'L', ns, jw, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_${ri}$larf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_${ri}$larf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_${ri}$gehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*v( 1_${ik}$, 1_${ik}$ ) call stdlib${ii}$_${ri}$lacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_${ri}$copy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=zero )call stdlib${ii}$_${ri}$ormhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', kln, jw, jw, one, h( krow, kwtop ),ldh, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_${ri}$lacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_${ri}$gemm( 'C', 'N', jw, kln, jw, one, v, ldv,h( kwtop, kcol ), ldh, & zero, t, ldt ) call stdlib${ii}$_${ri}$lacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', kln, jw, jw, one, z( krow, kwtop ),ldz, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_${ri}$lacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=${rk}$) end subroutine stdlib${ii}$_${ri}$laqr2 #:endif #:endfor pure module subroutine stdlib${ii}$_claqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & !! CLAQR2 is identical to CLAQR3 except that it avoids !! recursion by calling CLAHQR instead of CLAQR4. !! Aggressive early deflation: !! This subroutine accepts as input an upper Hessenberg matrix !! H and performs an unitary similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an unitary similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. ns, nd, sh, v, ldv, nh, t, ldt,nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(sp), intent(inout) :: h(ldh,*), z(ldz,*) complex(sp), intent(out) :: sh(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Parameters ! Local Scalars complex(sp) :: beta, cdum, s, tau real(sp) :: foo, safmax, safmin, smlnum, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, kcol, kln, knt, krow, kwtop, ltop, & lwk1, lwk2, lwkopt ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_cgehrd ==== call stdlib${ii}$_cgehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_cunmhr ==== call stdlib${ii}$_cunmhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = jw + max( lwk1, lwk2 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=sp) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = cone if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=sp) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = czero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sh( kwtop ) = h( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if( cabs1( s )<=max( smlnum, ulp*cabs1( h( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = czero end if work( 1_${ik}$ ) = cone return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_clacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_ccopy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_claset( 'A', jw, jw, czero, cone, v, ldv ) call stdlib${ii}$_clahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh( kwtop ), 1_${ik}$,jw, v, ldv, & infqr ) ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ do knt = infqr + 1, jw ! ==== small spike tip deflation test ==== foo = cabs1( t( ns, ns ) ) if( foo==zero )foo = cabs1( s ) if( cabs1( s )*cabs1( v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) )then ! ==== cone more converged eigenvalue ==== ns = ns - 1_${ik}$ else ! ==== cone undeflatable eigenvalue. move it up out of the ! . way. (stdlib${ii}$_ctrexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_ctrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) ilst = ilst + 1_${ik}$ end if end do ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = czero if( nscabs1( t( ifst, ifst ) ) )ifst = j end do ilst = i if( ifst/=ilst )call stdlib${ii}$_ctrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) end do end if ! ==== restore shift/eigenvalue array from t ==== do i = infqr + 1, jw sh( kwtop+i-1 ) = t( i, i ) end do if( ns1_${ik}$ .and. s/=czero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_ccopy( ns, v, ldv, work, 1_${ik}$ ) do i = 1, ns work( i ) = conjg( work( i ) ) end do beta = work( 1_${ik}$ ) call stdlib${ii}$_clarfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = cone call stdlib${ii}$_claset( 'L', jw-2, jw-2, czero, czero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_clarf( 'L', ns, jw, work, 1_${ik}$, conjg( tau ), t, ldt,work( jw+1 ) ) call stdlib${ii}$_clarf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_clarf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_cgehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*conjg( v( 1_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_clacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_ccopy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=czero )call stdlib${ii}$_cunmhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_cgemm( 'N', 'N', kln, jw, jw, cone, h( krow, kwtop ),ldh, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_clacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_cgemm( 'C', 'N', jw, kln, jw, cone, v, ldv,h( kwtop, kcol ), ldh, & czero, t, ldt ) call stdlib${ii}$_clacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_cgemm( 'N', 'N', kln, jw, jw, cone, z( krow, kwtop ),ldz, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_clacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=sp) end subroutine stdlib${ii}$_claqr2 pure module subroutine stdlib${ii}$_zlaqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & !! ZLAQR2 is identical to ZLAQR3 except that it avoids !! recursion by calling ZLAHQR instead of ZLAQR4. !! Aggressive early deflation: !! ZLAQR2 accepts as input an upper Hessenberg matrix !! H and performs an unitary similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an unitary similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. ns, nd, sh, v, ldv, nh, t, ldt,nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(dp), intent(inout) :: h(ldh,*), z(ldz,*) complex(dp), intent(out) :: sh(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Parameters ! Local Scalars complex(dp) :: beta, cdum, s, tau real(dp) :: foo, safmax, safmin, smlnum, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, kcol, kln, knt, krow, kwtop, ltop, & lwk1, lwk2, lwkopt ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_zgehrd ==== call stdlib${ii}$_zgehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_zunmhr ==== call stdlib${ii}$_zunmhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = jw + max( lwk1, lwk2 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=dp) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = cone if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=dp) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = czero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sh( kwtop ) = h( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if( cabs1( s )<=max( smlnum, ulp*cabs1( h( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = czero end if work( 1_${ik}$ ) = cone return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_zlacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_zcopy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_zlaset( 'A', jw, jw, czero, cone, v, ldv ) call stdlib${ii}$_zlahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh( kwtop ), 1_${ik}$,jw, v, ldv, & infqr ) ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ do knt = infqr + 1, jw ! ==== small spike tip deflation test ==== foo = cabs1( t( ns, ns ) ) if( foo==zero )foo = cabs1( s ) if( cabs1( s )*cabs1( v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) )then ! ==== cone more converged eigenvalue ==== ns = ns - 1_${ik}$ else ! ==== cone undeflatable eigenvalue. move it up out of the ! . way. (stdlib${ii}$_ztrexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_ztrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) ilst = ilst + 1_${ik}$ end if end do ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = czero if( nscabs1( t( ifst, ifst ) ) )ifst = j end do ilst = i if( ifst/=ilst )call stdlib${ii}$_ztrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) end do end if ! ==== restore shift/eigenvalue array from t ==== do i = infqr + 1, jw sh( kwtop+i-1 ) = t( i, i ) end do if( ns1_${ik}$ .and. s/=czero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_zcopy( ns, v, ldv, work, 1_${ik}$ ) do i = 1, ns work( i ) = conjg( work( i ) ) end do beta = work( 1_${ik}$ ) call stdlib${ii}$_zlarfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = cone call stdlib${ii}$_zlaset( 'L', jw-2, jw-2, czero, czero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_zlarf( 'L', ns, jw, work, 1_${ik}$, conjg( tau ), t, ldt,work( jw+1 ) ) call stdlib${ii}$_zlarf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_zlarf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_zgehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*conjg( v( 1_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_zlacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_zcopy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=czero )call stdlib${ii}$_zunmhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_zgemm( 'N', 'N', kln, jw, jw, cone, h( krow, kwtop ),ldh, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_zlacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_zgemm( 'C', 'N', jw, kln, jw, cone, v, ldv,h( kwtop, kcol ), ldh, & czero, t, ldt ) call stdlib${ii}$_zlacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_zgemm( 'N', 'N', kln, jw, jw, cone, z( krow, kwtop ),ldz, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_zlacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=dp) end subroutine stdlib${ii}$_zlaqr2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & !! ZLAQR2: is identical to ZLAQR3 except that it avoids !! recursion by calling ZLAHQR instead of ZLAQR4. !! Aggressive early deflation: !! ZLAQR2 accepts as input an upper Hessenberg matrix !! H and performs an unitary similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an unitary similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. ns, nd, sh, v, ldv, nh, t, ldt,nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(${ck}$), intent(inout) :: h(ldh,*), z(ldz,*) complex(${ck}$), intent(out) :: sh(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Parameters ! Local Scalars complex(${ck}$) :: beta, cdum, s, tau real(${ck}$) :: foo, safmax, safmin, smlnum, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, kcol, kln, knt, krow, kwtop, ltop, & lwk1, lwk2, lwkopt ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_${ci}$gehrd ==== call stdlib${ii}$_${ci}$gehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_${ci}$unmhr ==== call stdlib${ii}$_${ci}$unmhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = jw + max( lwk1, lwk2 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=${ck}$) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = cone if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_${c2ri(ci)}$labad( safmin, safmax ) ulp = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=${ck}$) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = czero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sh( kwtop ) = h( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if( cabs1( s )<=max( smlnum, ulp*cabs1( h( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = czero end if work( 1_${ik}$ ) = cone return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_${ci}$lacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_${ci}$copy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_${ci}$laset( 'A', jw, jw, czero, cone, v, ldv ) call stdlib${ii}$_${ci}$lahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh( kwtop ), 1_${ik}$,jw, v, ldv, & infqr ) ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ do knt = infqr + 1, jw ! ==== small spike tip deflation test ==== foo = cabs1( t( ns, ns ) ) if( foo==zero )foo = cabs1( s ) if( cabs1( s )*cabs1( v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) )then ! ==== cone more converged eigenvalue ==== ns = ns - 1_${ik}$ else ! ==== cone undeflatable eigenvalue. move it up out of the ! . way. (stdlib${ii}$_${ci}$trexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_${ci}$trexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) ilst = ilst + 1_${ik}$ end if end do ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = czero if( nscabs1( t( ifst, ifst ) ) )ifst = j end do ilst = i if( ifst/=ilst )call stdlib${ii}$_${ci}$trexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) end do end if ! ==== restore shift/eigenvalue array from t ==== do i = infqr + 1, jw sh( kwtop+i-1 ) = t( i, i ) end do if( ns1_${ik}$ .and. s/=czero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_${ci}$copy( ns, v, ldv, work, 1_${ik}$ ) do i = 1, ns work( i ) = conjg( work( i ) ) end do beta = work( 1_${ik}$ ) call stdlib${ii}$_${ci}$larfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = cone call stdlib${ii}$_${ci}$laset( 'L', jw-2, jw-2, czero, czero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_${ci}$larf( 'L', ns, jw, work, 1_${ik}$, conjg( tau ), t, ldt,work( jw+1 ) ) call stdlib${ii}$_${ci}$larf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_${ci}$larf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_${ci}$gehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*conjg( v( 1_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_${ci}$lacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_${ci}$copy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=czero )call stdlib${ii}$_${ci}$unmhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', kln, jw, jw, cone, h( krow, kwtop ),ldh, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_${ci}$lacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_${ci}$gemm( 'C', 'N', jw, kln, jw, cone, v, ldv,h( kwtop, kcol ), ldh, & czero, t, ldt ) call stdlib${ii}$_${ci}$lacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', kln, jw, jw, cone, z( krow, kwtop ),ldz, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_${ci}$lacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=${ck}$) end subroutine stdlib${ii}$_${ci}$laqr2 #:endif #:endfor module subroutine stdlib${ii}$_slaqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, ns, nd,& !! Aggressive early deflation: !! SLAQR3 accepts as input an upper Hessenberg matrix !! H and performs an orthogonal similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an orthogonal similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. sr, si, v, ldv, nh, t,ldt, nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(sp), intent(inout) :: h(ldh,*), z(ldz,*) real(sp), intent(out) :: si(*), sr(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Local Scalars real(sp) :: aa, bb, beta, cc, cs, dd, evi, evk, foo, s, safmax, safmin, smlnum, sn, & tau, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, k, kcol, kend, kln, krow, kwtop, & ltop, lwk1, lwk2, lwk3, lwkopt, nmin logical(lk) :: bulge, sorted ! Intrinsic Functions ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_sgehrd ==== call stdlib${ii}$_sgehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_sormhr ==== call stdlib${ii}$_sormhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_slaqr4 ==== call stdlib${ii}$_slaqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr, si, 1_${ik}$, jw,v, ldv, work, -& 1_${ik}$, infqr ) lwk3 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = max( jw+max( lwk1, lwk2 ), lwk3 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=sp) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = one if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=sp) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = zero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sr( kwtop ) = h( kwtop, kwtop ) si( kwtop ) = zero ns = 1_${ik}$ nd = 0_${ik}$ if( abs( s )<=max( smlnum, ulp*abs( h( kwtop, kwtop ) ) ) )then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = zero end if work( 1_${ik}$ ) = one return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_slacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_scopy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_slaset( 'A', jw, jw, zero, one, v, ldv ) nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'SLAQR3', 'SV', jw, 1_${ik}$, jw, lwork ) if( jw>nmin ) then call stdlib${ii}$_slaqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr( kwtop ),si( kwtop ), 1_${ik}$, & jw, v, ldv, work, lwork, infqr ) else call stdlib${ii}$_slahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr( kwtop ),si( kwtop ), 1_${ik}$, & jw, v, ldv, infqr ) end if ! ==== stdlib${ii}$_strexc needs a clean margin near the diagonal ==== do j = 1, jw - 3 t( j+2, j ) = zero t( j+3, j ) = zero end do if( jw>2_${ik}$ )t( jw, jw-2 ) = zero ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ 20 continue if( ilst<=ns ) then if( ns==1_${ik}$ ) then bulge = .false. else bulge = t( ns, ns-1 )/=zero end if ! ==== small spike tip test for deflation ==== if( .not. bulge ) then ! ==== real eigenvalue ==== foo = abs( t( ns, ns ) ) if( foo==zero )foo = abs( s ) if( abs( s*v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) ) then ! ==== deflatable ==== ns = ns - 1_${ik}$ else ! ==== undeflatable. move it up out of the way. ! . (stdlib${ii}$_strexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_strexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 1_${ik}$ end if else ! ==== complex conjugate pair ==== foo = abs( t( ns, ns ) ) + sqrt( abs( t( ns, ns-1 ) ) )*sqrt( abs( t( ns-1, ns ) & ) ) if( foo==zero )foo = abs( s ) if( max( abs( s*v( 1_${ik}$, ns ) ), abs( s*v( 1_${ik}$, ns-1 ) ) )<=max( smlnum, ulp*foo ) ) & then ! ==== deflatable ==== ns = ns - 2_${ik}$ else ! ==== undeflatable. move them up out of the way. ! . fortunately, stdlib${ii}$_strexc does the right thing with ! . ilst in case of a rare exchange failure. ==== ifst = ns call stdlib${ii}$_strexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 2_${ik}$ end if end if ! ==== end deflation detection loop ==== go to 20 end if ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = zero if( ns=evk ) then i = k else sorted = .false. ifst = i ilst = k call stdlib${ii}$_strexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) if( info==0_${ik}$ ) then i = ilst else i = k end if end if if( i==kend ) then k = i + 1_${ik}$ else if( t( i+1, i )==zero ) then k = i + 1_${ik}$ else k = i + 2_${ik}$ end if go to 40 end if go to 30 50 continue end if ! ==== restore shift/eigenvalue array from t ==== i = jw 60 continue if( i>=infqr+1 ) then if( i==infqr+1 ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else if( t( i, i-1 )==zero ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else aa = t( i-1, i-1 ) cc = t( i, i-1 ) bb = t( i-1, i ) dd = t( i, i ) call stdlib${ii}$_slanv2( aa, bb, cc, dd, sr( kwtop+i-2 ),si( kwtop+i-2 ), sr( kwtop+i-& 1_${ik}$ ),si( kwtop+i-1 ), cs, sn ) i = i - 2_${ik}$ end if go to 60 end if if( ns1_${ik}$ .and. s/=zero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_scopy( ns, v, ldv, work, 1_${ik}$ ) beta = work( 1_${ik}$ ) call stdlib${ii}$_slarfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = one call stdlib${ii}$_slaset( 'L', jw-2, jw-2, zero, zero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_slarf( 'L', ns, jw, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_slarf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_slarf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_sgehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*v( 1_${ik}$, 1_${ik}$ ) call stdlib${ii}$_slacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_scopy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=zero )call stdlib${ii}$_sormhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_sgemm( 'N', 'N', kln, jw, jw, one, h( krow, kwtop ),ldh, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_slacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_sgemm( 'C', 'N', jw, kln, jw, one, v, ldv,h( kwtop, kcol ), ldh, & zero, t, ldt ) call stdlib${ii}$_slacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_sgemm( 'N', 'N', kln, jw, jw, one, z( krow, kwtop ),ldz, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_slacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=sp) end subroutine stdlib${ii}$_slaqr3 module subroutine stdlib${ii}$_dlaqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, ns, nd,& !! Aggressive early deflation: !! DLAQR3 accepts as input an upper Hessenberg matrix !! H and performs an orthogonal similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an orthogonal similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. sr, si, v, ldv, nh, t,ldt, nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(dp), intent(inout) :: h(ldh,*), z(ldz,*) real(dp), intent(out) :: si(*), sr(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Local Scalars real(dp) :: aa, bb, beta, cc, cs, dd, evi, evk, foo, s, safmax, safmin, smlnum, sn, & tau, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, k, kcol, kend, kln, krow, kwtop, & ltop, lwk1, lwk2, lwk3, lwkopt, nmin logical(lk) :: bulge, sorted ! Intrinsic Functions ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_dgehrd ==== call stdlib${ii}$_dgehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_dormhr ==== call stdlib${ii}$_dormhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_dlaqr4 ==== call stdlib${ii}$_dlaqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr, si, 1_${ik}$, jw,v, ldv, work, -& 1_${ik}$, infqr ) lwk3 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = max( jw+max( lwk1, lwk2 ), lwk3 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=dp) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = one if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=dp) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = zero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sr( kwtop ) = h( kwtop, kwtop ) si( kwtop ) = zero ns = 1_${ik}$ nd = 0_${ik}$ if( abs( s )<=max( smlnum, ulp*abs( h( kwtop, kwtop ) ) ) )then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = zero end if work( 1_${ik}$ ) = one return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_dlacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_dcopy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_dlaset( 'A', jw, jw, zero, one, v, ldv ) nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'DLAQR3', 'SV', jw, 1_${ik}$, jw, lwork ) if( jw>nmin ) then call stdlib${ii}$_dlaqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr( kwtop ),si( kwtop ), 1_${ik}$, & jw, v, ldv, work, lwork, infqr ) else call stdlib${ii}$_dlahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr( kwtop ),si( kwtop ), 1_${ik}$, & jw, v, ldv, infqr ) end if ! ==== stdlib${ii}$_dtrexc needs a clean margin near the diagonal ==== do j = 1, jw - 3 t( j+2, j ) = zero t( j+3, j ) = zero end do if( jw>2_${ik}$ )t( jw, jw-2 ) = zero ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ 20 continue if( ilst<=ns ) then if( ns==1_${ik}$ ) then bulge = .false. else bulge = t( ns, ns-1 )/=zero end if ! ==== small spike tip test for deflation ==== if( .not. bulge ) then ! ==== real eigenvalue ==== foo = abs( t( ns, ns ) ) if( foo==zero )foo = abs( s ) if( abs( s*v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) ) then ! ==== deflatable ==== ns = ns - 1_${ik}$ else ! ==== undeflatable. move it up out of the way. ! . (stdlib${ii}$_dtrexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_dtrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 1_${ik}$ end if else ! ==== complex conjugate pair ==== foo = abs( t( ns, ns ) ) + sqrt( abs( t( ns, ns-1 ) ) )*sqrt( abs( t( ns-1, ns ) & ) ) if( foo==zero )foo = abs( s ) if( max( abs( s*v( 1_${ik}$, ns ) ), abs( s*v( 1_${ik}$, ns-1 ) ) )<=max( smlnum, ulp*foo ) ) & then ! ==== deflatable ==== ns = ns - 2_${ik}$ else ! ==== undeflatable. move them up out of the way. ! . fortunately, stdlib${ii}$_dtrexc does the right thing with ! . ilst in case of a rare exchange failure. ==== ifst = ns call stdlib${ii}$_dtrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 2_${ik}$ end if end if ! ==== end deflation detection loop ==== go to 20 end if ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = zero if( ns=evk ) then i = k else sorted = .false. ifst = i ilst = k call stdlib${ii}$_dtrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) if( info==0_${ik}$ ) then i = ilst else i = k end if end if if( i==kend ) then k = i + 1_${ik}$ else if( t( i+1, i )==zero ) then k = i + 1_${ik}$ else k = i + 2_${ik}$ end if go to 40 end if go to 30 50 continue end if ! ==== restore shift/eigenvalue array from t ==== i = jw 60 continue if( i>=infqr+1 ) then if( i==infqr+1 ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else if( t( i, i-1 )==zero ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else aa = t( i-1, i-1 ) cc = t( i, i-1 ) bb = t( i-1, i ) dd = t( i, i ) call stdlib${ii}$_dlanv2( aa, bb, cc, dd, sr( kwtop+i-2 ),si( kwtop+i-2 ), sr( kwtop+i-& 1_${ik}$ ),si( kwtop+i-1 ), cs, sn ) i = i - 2_${ik}$ end if go to 60 end if if( ns1_${ik}$ .and. s/=zero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_dcopy( ns, v, ldv, work, 1_${ik}$ ) beta = work( 1_${ik}$ ) call stdlib${ii}$_dlarfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = one call stdlib${ii}$_dlaset( 'L', jw-2, jw-2, zero, zero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_dlarf( 'L', ns, jw, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_dlarf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_dlarf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_dgehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*v( 1_${ik}$, 1_${ik}$ ) call stdlib${ii}$_dlacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_dcopy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=zero )call stdlib${ii}$_dormhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_dgemm( 'N', 'N', kln, jw, jw, one, h( krow, kwtop ),ldh, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_dlacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_dgemm( 'C', 'N', jw, kln, jw, one, v, ldv,h( kwtop, kcol ), ldh, & zero, t, ldt ) call stdlib${ii}$_dlacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_dgemm( 'N', 'N', kln, jw, jw, one, z( krow, kwtop ),ldz, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_dlacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=dp) end subroutine stdlib${ii}$_dlaqr3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$laqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, ns, nd,& !! Aggressive early deflation: !! DLAQR3: accepts as input an upper Hessenberg matrix !! H and performs an orthogonal similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an orthogonal similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. sr, si, v, ldv, nh, t,ldt, nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(${rk}$), intent(inout) :: h(ldh,*), z(ldz,*) real(${rk}$), intent(out) :: si(*), sr(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Local Scalars real(${rk}$) :: aa, bb, beta, cc, cs, dd, evi, evk, foo, s, safmax, safmin, smlnum, sn, & tau, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, k, kcol, kend, kln, krow, kwtop, & ltop, lwk1, lwk2, lwk3, lwkopt, nmin logical(lk) :: bulge, sorted ! Intrinsic Functions ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_${ri}$gehrd ==== call stdlib${ii}$_${ri}$gehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_${ri}$ormhr ==== call stdlib${ii}$_${ri}$ormhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_${ri}$laqr4 ==== call stdlib${ii}$_${ri}$laqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr, si, 1_${ik}$, jw,v, ldv, work, -& 1_${ik}$, infqr ) lwk3 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = max( jw+max( lwk1, lwk2 ), lwk3 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=${rk}$) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = one if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_${ri}$labad( safmin, safmax ) ulp = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=${rk}$) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = zero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sr( kwtop ) = h( kwtop, kwtop ) si( kwtop ) = zero ns = 1_${ik}$ nd = 0_${ik}$ if( abs( s )<=max( smlnum, ulp*abs( h( kwtop, kwtop ) ) ) )then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = zero end if work( 1_${ik}$ ) = one return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_${ri}$lacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_${ri}$copy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_${ri}$laset( 'A', jw, jw, zero, one, v, ldv ) nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'DLAQR3', 'SV', jw, 1_${ik}$, jw, lwork ) if( jw>nmin ) then call stdlib${ii}$_${ri}$laqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr( kwtop ),si( kwtop ), 1_${ik}$, & jw, v, ldv, work, lwork, infqr ) else call stdlib${ii}$_${ri}$lahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sr( kwtop ),si( kwtop ), 1_${ik}$, & jw, v, ldv, infqr ) end if ! ==== stdlib${ii}$_${ri}$trexc needs a clean margin near the diagonal ==== do j = 1, jw - 3 t( j+2, j ) = zero t( j+3, j ) = zero end do if( jw>2_${ik}$ )t( jw, jw-2 ) = zero ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ 20 continue if( ilst<=ns ) then if( ns==1_${ik}$ ) then bulge = .false. else bulge = t( ns, ns-1 )/=zero end if ! ==== small spike tip test for deflation ==== if( .not. bulge ) then ! ==== real eigenvalue ==== foo = abs( t( ns, ns ) ) if( foo==zero )foo = abs( s ) if( abs( s*v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) ) then ! ==== deflatable ==== ns = ns - 1_${ik}$ else ! ==== undeflatable. move it up out of the way. ! . (stdlib${ii}$_${ri}$trexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_${ri}$trexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 1_${ik}$ end if else ! ==== complex conjugate pair ==== foo = abs( t( ns, ns ) ) + sqrt( abs( t( ns, ns-1 ) ) )*sqrt( abs( t( ns-1, ns ) & ) ) if( foo==zero )foo = abs( s ) if( max( abs( s*v( 1_${ik}$, ns ) ), abs( s*v( 1_${ik}$, ns-1 ) ) )<=max( smlnum, ulp*foo ) ) & then ! ==== deflatable ==== ns = ns - 2_${ik}$ else ! ==== undeflatable. move them up out of the way. ! . fortunately, stdlib${ii}$_${ri}$trexc does the right thing with ! . ilst in case of a rare exchange failure. ==== ifst = ns call stdlib${ii}$_${ri}$trexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) ilst = ilst + 2_${ik}$ end if end if ! ==== end deflation detection loop ==== go to 20 end if ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = zero if( ns=evk ) then i = k else sorted = .false. ifst = i ilst = k call stdlib${ii}$_${ri}$trexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, work,info ) if( info==0_${ik}$ ) then i = ilst else i = k end if end if if( i==kend ) then k = i + 1_${ik}$ else if( t( i+1, i )==zero ) then k = i + 1_${ik}$ else k = i + 2_${ik}$ end if go to 40 end if go to 30 50 continue end if ! ==== restore shift/eigenvalue array from t ==== i = jw 60 continue if( i>=infqr+1 ) then if( i==infqr+1 ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else if( t( i, i-1 )==zero ) then sr( kwtop+i-1 ) = t( i, i ) si( kwtop+i-1 ) = zero i = i - 1_${ik}$ else aa = t( i-1, i-1 ) cc = t( i, i-1 ) bb = t( i-1, i ) dd = t( i, i ) call stdlib${ii}$_${ri}$lanv2( aa, bb, cc, dd, sr( kwtop+i-2 ),si( kwtop+i-2 ), sr( kwtop+i-& 1_${ik}$ ),si( kwtop+i-1 ), cs, sn ) i = i - 2_${ik}$ end if go to 60 end if if( ns1_${ik}$ .and. s/=zero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_${ri}$copy( ns, v, ldv, work, 1_${ik}$ ) beta = work( 1_${ik}$ ) call stdlib${ii}$_${ri}$larfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = one call stdlib${ii}$_${ri}$laset( 'L', jw-2, jw-2, zero, zero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_${ri}$larf( 'L', ns, jw, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_${ri}$larf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_${ri}$larf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_${ri}$gehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*v( 1_${ik}$, 1_${ik}$ ) call stdlib${ii}$_${ri}$lacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_${ri}$copy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=zero )call stdlib${ii}$_${ri}$ormhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', kln, jw, jw, one, h( krow, kwtop ),ldh, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_${ri}$lacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_${ri}$gemm( 'C', 'N', jw, kln, jw, one, v, ldv,h( kwtop, kcol ), ldh, & zero, t, ldt ) call stdlib${ii}$_${ri}$lacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', kln, jw, jw, one, z( krow, kwtop ),ldz, v, ldv, & zero, wv, ldwv ) call stdlib${ii}$_${ri}$lacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=${rk}$) end subroutine stdlib${ii}$_${ri}$laqr3 #:endif #:endfor pure module subroutine stdlib${ii}$_claqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & !! Aggressive early deflation: !! CLAQR3 accepts as input an upper Hessenberg matrix !! H and performs an unitary similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an unitary similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. ns, nd, sh, v, ldv, nh, t, ldt,nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(sp), intent(inout) :: h(ldh,*), z(ldz,*) complex(sp), intent(out) :: sh(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Parameters ! Local Scalars complex(sp) :: beta, cdum, s, tau real(sp) :: foo, safmax, safmin, smlnum, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, kcol, kln, knt, krow, kwtop, ltop, & lwk1, lwk2, lwk3, lwkopt, nmin ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_cgehrd ==== call stdlib${ii}$_cgehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_cunmhr ==== call stdlib${ii}$_cunmhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_claqr4 ==== call stdlib${ii}$_claqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh, 1_${ik}$, jw, v,ldv, work, -1_${ik}$, & infqr ) lwk3 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = max( jw+max( lwk1, lwk2 ), lwk3 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=sp) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = cone if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=sp) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = czero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sh( kwtop ) = h( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if( cabs1( s )<=max( smlnum, ulp*cabs1( h( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = czero end if work( 1_${ik}$ ) = cone return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_clacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_ccopy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_claset( 'A', jw, jw, czero, cone, v, ldv ) nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'CLAQR3', 'SV', jw, 1_${ik}$, jw, lwork ) if( jw>nmin ) then call stdlib${ii}$_claqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh( kwtop ), 1_${ik}$,jw, v, ldv, & work, lwork, infqr ) else call stdlib${ii}$_clahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh( kwtop ), 1_${ik}$,jw, v, ldv, & infqr ) end if ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ do knt = infqr + 1, jw ! ==== small spike tip deflation test ==== foo = cabs1( t( ns, ns ) ) if( foo==zero )foo = cabs1( s ) if( cabs1( s )*cabs1( v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) )then ! ==== cone more converged eigenvalue ==== ns = ns - 1_${ik}$ else ! ==== cone undeflatable eigenvalue. move it up out of the ! . way. (stdlib${ii}$_ctrexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_ctrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) ilst = ilst + 1_${ik}$ end if end do ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = czero if( nscabs1( t( ifst, ifst ) ) )ifst = j end do ilst = i if( ifst/=ilst )call stdlib${ii}$_ctrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) end do end if ! ==== restore shift/eigenvalue array from t ==== do i = infqr + 1, jw sh( kwtop+i-1 ) = t( i, i ) end do if( ns1_${ik}$ .and. s/=czero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_ccopy( ns, v, ldv, work, 1_${ik}$ ) do i = 1, ns work( i ) = conjg( work( i ) ) end do beta = work( 1_${ik}$ ) call stdlib${ii}$_clarfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = cone call stdlib${ii}$_claset( 'L', jw-2, jw-2, czero, czero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_clarf( 'L', ns, jw, work, 1_${ik}$, conjg( tau ), t, ldt,work( jw+1 ) ) call stdlib${ii}$_clarf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_clarf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_cgehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*conjg( v( 1_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_clacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_ccopy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=czero )call stdlib${ii}$_cunmhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_cgemm( 'N', 'N', kln, jw, jw, cone, h( krow, kwtop ),ldh, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_clacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_cgemm( 'C', 'N', jw, kln, jw, cone, v, ldv,h( kwtop, kcol ), ldh, & czero, t, ldt ) call stdlib${ii}$_clacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_cgemm( 'N', 'N', kln, jw, jw, cone, z( krow, kwtop ),ldz, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_clacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=sp) end subroutine stdlib${ii}$_claqr3 pure module subroutine stdlib${ii}$_zlaqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & !! Aggressive early deflation: !! ZLAQR3 accepts as input an upper Hessenberg matrix !! H and performs an unitary similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an unitary similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. ns, nd, sh, v, ldv, nh, t, ldt,nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(dp), intent(inout) :: h(ldh,*), z(ldz,*) complex(dp), intent(out) :: sh(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Parameters ! Local Scalars complex(dp) :: beta, cdum, s, tau real(dp) :: foo, safmax, safmin, smlnum, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, kcol, kln, knt, krow, kwtop, ltop, & lwk1, lwk2, lwk3, lwkopt, nmin ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_zgehrd ==== call stdlib${ii}$_zgehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_zunmhr ==== call stdlib${ii}$_zunmhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_zlaqr4 ==== call stdlib${ii}$_zlaqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh, 1_${ik}$, jw, v,ldv, work, -1_${ik}$, & infqr ) lwk3 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = max( jw+max( lwk1, lwk2 ), lwk3 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=dp) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = cone if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=dp) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = czero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sh( kwtop ) = h( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if( cabs1( s )<=max( smlnum, ulp*cabs1( h( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = czero end if work( 1_${ik}$ ) = cone return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_zlacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_zcopy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_zlaset( 'A', jw, jw, czero, cone, v, ldv ) nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'ZLAQR3', 'SV', jw, 1_${ik}$, jw, lwork ) if( jw>nmin ) then call stdlib${ii}$_zlaqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh( kwtop ), 1_${ik}$,jw, v, ldv, & work, lwork, infqr ) else call stdlib${ii}$_zlahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh( kwtop ), 1_${ik}$,jw, v, ldv, & infqr ) end if ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ do knt = infqr + 1, jw ! ==== small spike tip deflation test ==== foo = cabs1( t( ns, ns ) ) if( foo==zero )foo = cabs1( s ) if( cabs1( s )*cabs1( v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) )then ! ==== cone more converged eigenvalue ==== ns = ns - 1_${ik}$ else ! ==== cone undeflatable eigenvalue. move it up out of the ! . way. (stdlib${ii}$_ztrexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_ztrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) ilst = ilst + 1_${ik}$ end if end do ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = czero if( nscabs1( t( ifst, ifst ) ) )ifst = j end do ilst = i if( ifst/=ilst )call stdlib${ii}$_ztrexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) end do end if ! ==== restore shift/eigenvalue array from t ==== do i = infqr + 1, jw sh( kwtop+i-1 ) = t( i, i ) end do if( ns1_${ik}$ .and. s/=czero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_zcopy( ns, v, ldv, work, 1_${ik}$ ) do i = 1, ns work( i ) = conjg( work( i ) ) end do beta = work( 1_${ik}$ ) call stdlib${ii}$_zlarfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = cone call stdlib${ii}$_zlaset( 'L', jw-2, jw-2, czero, czero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_zlarf( 'L', ns, jw, work, 1_${ik}$, conjg( tau ), t, ldt,work( jw+1 ) ) call stdlib${ii}$_zlarf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_zlarf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_zgehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*conjg( v( 1_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_zlacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_zcopy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=czero )call stdlib${ii}$_zunmhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_zgemm( 'N', 'N', kln, jw, jw, cone, h( krow, kwtop ),ldh, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_zlacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_zgemm( 'C', 'N', jw, kln, jw, cone, v, ldv,h( kwtop, kcol ), ldh, & czero, t, ldt ) call stdlib${ii}$_zlacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_zgemm( 'N', 'N', kln, jw, jw, cone, z( krow, kwtop ),ldz, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_zlacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=dp) end subroutine stdlib${ii}$_zlaqr3 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqr3( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & !! Aggressive early deflation: !! ZLAQR3: accepts as input an upper Hessenberg matrix !! H and performs an unitary similarity transformation !! designed to detect and deflate fully converged eigenvalues from !! a trailing principal submatrix. On output H has been over- !! written by a new Hessenberg matrix that is a perturbation of !! an unitary similarity transformation of H. It is to be !! hoped that the final version of H has many zero subdiagonal !! entries. ns, nd, sh, v, ldv, nh, t, ldt,nv, wv, ldwv, work, lwork ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kbot, ktop, ldh, ldt, ldv, ldwv, ldz, lwork, n,& nh, nv, nw integer(${ik}$), intent(out) :: nd, ns logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(${ck}$), intent(inout) :: h(ldh,*), z(ldz,*) complex(${ck}$), intent(out) :: sh(*), t(ldt,*), v(ldv,*), work(*), wv(ldwv,*) ! ================================================================ ! Parameters ! Local Scalars complex(${ck}$) :: beta, cdum, s, tau real(${ck}$) :: foo, safmax, safmin, smlnum, ulp integer(${ik}$) :: i, ifst, ilst, info, infqr, j, jw, kcol, kln, knt, krow, kwtop, ltop, & lwk1, lwk2, lwk3, lwkopt, nmin ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements ! ==== estimate optimal workspace. ==== jw = min( nw, kbot-ktop+1 ) if( jw<=2_${ik}$ ) then lwkopt = 1_${ik}$ else ! ==== workspace query call to stdlib${ii}$_${ci}$gehrd ==== call stdlib${ii}$_${ci}$gehrd( jw, 1_${ik}$, jw-1, t, ldt, work, work, -1_${ik}$, info ) lwk1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_${ci}$unmhr ==== call stdlib${ii}$_${ci}$unmhr( 'R', 'N', jw, jw, 1_${ik}$, jw-1, t, ldt, work, v, ldv,work, -1_${ik}$, info ) lwk2 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== workspace query call to stdlib${ii}$_${ci}$laqr4 ==== call stdlib${ii}$_${ci}$laqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh, 1_${ik}$, jw, v,ldv, work, -1_${ik}$, & infqr ) lwk3 = int( work( 1_${ik}$ ),KIND=${ik}$) ! ==== optimal workspace ==== lwkopt = max( jw+max( lwk1, lwk2 ), lwk3 ) end if ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=${ck}$) return end if ! ==== nothing to do ... ! ... for an empty active block ... ==== ns = 0_${ik}$ nd = 0_${ik}$ work( 1_${ik}$ ) = cone if( ktop>kbot )return ! ... nor for an empty deflation window. ==== if( nw<1 )return ! ==== machine constants ==== safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_${c2ri(ci)}$labad( safmin, safmax ) ulp = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=${ck}$) / ulp ) ! ==== setup deflation window ==== jw = min( nw, kbot-ktop+1 ) kwtop = kbot - jw + 1_${ik}$ if( kwtop==ktop ) then s = czero else s = h( kwtop, kwtop-1 ) end if if( kbot==kwtop ) then ! ==== 1-by-1 deflation window: not much to do ==== sh( kwtop ) = h( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if( cabs1( s )<=max( smlnum, ulp*cabs1( h( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if( kwtop>ktop )h( kwtop, kwtop-1 ) = czero end if work( 1_${ik}$ ) = cone return end if ! ==== convert to spike-triangular form. (in case of a ! . rare qr failure, this routine continues to do ! . aggressive early deflation using that part of ! . the deflation window that converged using infqr ! . here and there to keep track.) ==== call stdlib${ii}$_${ci}$lacpy( 'U', jw, jw, h( kwtop, kwtop ), ldh, t, ldt ) call stdlib${ii}$_${ci}$copy( jw-1, h( kwtop+1, kwtop ), ldh+1, t( 2_${ik}$, 1_${ik}$ ), ldt+1 ) call stdlib${ii}$_${ci}$laset( 'A', jw, jw, czero, cone, v, ldv ) nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'ZLAQR3', 'SV', jw, 1_${ik}$, jw, lwork ) if( jw>nmin ) then call stdlib${ii}$_${ci}$laqr4( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh( kwtop ), 1_${ik}$,jw, v, ldv, & work, lwork, infqr ) else call stdlib${ii}$_${ci}$lahqr( .true., .true., jw, 1_${ik}$, jw, t, ldt, sh( kwtop ), 1_${ik}$,jw, v, ldv, & infqr ) end if ! ==== deflation detection loop ==== ns = jw ilst = infqr + 1_${ik}$ do knt = infqr + 1, jw ! ==== small spike tip deflation test ==== foo = cabs1( t( ns, ns ) ) if( foo==zero )foo = cabs1( s ) if( cabs1( s )*cabs1( v( 1_${ik}$, ns ) )<=max( smlnum, ulp*foo ) )then ! ==== cone more converged eigenvalue ==== ns = ns - 1_${ik}$ else ! ==== cone undeflatable eigenvalue. move it up out of the ! . way. (stdlib${ii}$_${ci}$trexc can not fail in this case.) ==== ifst = ns call stdlib${ii}$_${ci}$trexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) ilst = ilst + 1_${ik}$ end if end do ! ==== return to hessenberg form ==== if( ns==0_${ik}$ )s = czero if( nscabs1( t( ifst, ifst ) ) )ifst = j end do ilst = i if( ifst/=ilst )call stdlib${ii}$_${ci}$trexc( 'V', jw, t, ldt, v, ldv, ifst, ilst, info ) end do end if ! ==== restore shift/eigenvalue array from t ==== do i = infqr + 1, jw sh( kwtop+i-1 ) = t( i, i ) end do if( ns1_${ik}$ .and. s/=czero ) then ! ==== reflect spike back into lower triangle ==== call stdlib${ii}$_${ci}$copy( ns, v, ldv, work, 1_${ik}$ ) do i = 1, ns work( i ) = conjg( work( i ) ) end do beta = work( 1_${ik}$ ) call stdlib${ii}$_${ci}$larfg( ns, beta, work( 2_${ik}$ ), 1_${ik}$, tau ) work( 1_${ik}$ ) = cone call stdlib${ii}$_${ci}$laset( 'L', jw-2, jw-2, czero, czero, t( 3_${ik}$, 1_${ik}$ ), ldt ) call stdlib${ii}$_${ci}$larf( 'L', ns, jw, work, 1_${ik}$, conjg( tau ), t, ldt,work( jw+1 ) ) call stdlib${ii}$_${ci}$larf( 'R', ns, ns, work, 1_${ik}$, tau, t, ldt,work( jw+1 ) ) call stdlib${ii}$_${ci}$larf( 'R', jw, ns, work, 1_${ik}$, tau, v, ldv,work( jw+1 ) ) call stdlib${ii}$_${ci}$gehrd( jw, 1_${ik}$, ns, t, ldt, work, work( jw+1 ),lwork-jw, info ) end if ! ==== copy updated reduced window into place ==== if( kwtop>1_${ik}$ )h( kwtop, kwtop-1 ) = s*conjg( v( 1_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_${ci}$lacpy( 'U', jw, jw, t, ldt, h( kwtop, kwtop ), ldh ) call stdlib${ii}$_${ci}$copy( jw-1, t( 2_${ik}$, 1_${ik}$ ), ldt+1, h( kwtop+1, kwtop ),ldh+1 ) ! ==== accumulate orthogonal matrix in order update ! . h and z, if requested. ==== if( ns>1_${ik}$ .and. s/=czero )call stdlib${ii}$_${ci}$unmhr( 'R', 'N', jw, ns, 1_${ik}$, ns, t, ldt, work, & v, ldv,work( jw+1 ), lwork-jw, info ) ! ==== update vertical slab in h ==== if( wantt ) then ltop = 1_${ik}$ else ltop = ktop end if do krow = ltop, kwtop - 1, nv kln = min( nv, kwtop-krow ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', kln, jw, jw, cone, h( krow, kwtop ),ldh, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_${ci}$lacpy( 'A', kln, jw, wv, ldwv, h( krow, kwtop ), ldh ) end do ! ==== update horizontal slab in h ==== if( wantt ) then do kcol = kbot + 1, n, nh kln = min( nh, n-kcol+1 ) call stdlib${ii}$_${ci}$gemm( 'C', 'N', jw, kln, jw, cone, v, ldv,h( kwtop, kcol ), ldh, & czero, t, ldt ) call stdlib${ii}$_${ci}$lacpy( 'A', jw, kln, t, ldt, h( kwtop, kcol ),ldh ) end do end if ! ==== update vertical slab in z ==== if( wantz ) then do krow = iloz, ihiz, nv kln = min( nv, ihiz-krow+1 ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', kln, jw, jw, cone, z( krow, kwtop ),ldz, v, ldv, & czero, wv, ldwv ) call stdlib${ii}$_${ci}$lacpy( 'A', kln, jw, wv, ldwv, z( krow, kwtop ),ldz ) end do end if end if ! ==== return the number of deflations ... ==== nd = jw - ns ! ==== ... and the number of shifts. (subtracting ! . infqr from the spike length takes care ! . of the case of a rare qr failure while ! . calculating eigenvalues of the deflation ! . window.) ==== ns = ns - infqr ! ==== return optimal workspace. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=${ck}$) end subroutine stdlib${ii}$_${ci}$laqr3 #:endif #:endfor module subroutine stdlib${ii}$_slaqr4( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, work,& !! SLAQR4 implements one level of recursion for SLAQR0. !! It is a complete implementation of the small bulge multi-shift !! QR algorithm. It may be called by SLAQR0 and, for large enough !! deflation window size, it may be called by SLAQR3. This !! subroutine is identical to SLAQR0 except that it calls SLAQR2 !! instead of SLAQR3. !! SLAQR4 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**T, where T is an upper quasi-triangular matrix (the !! Schur form), and Z is the orthogonal matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input orthogonal !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(sp), intent(inout) :: h(ldh,*), z(ldz,*) real(sp), intent(out) :: wi(*), work(*), wr(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(sp), parameter :: wilk1 = 0.75_sp real(sp), parameter :: wilk2 = -0.4375_sp ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_slahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constants wilk1 and wilk2 are used to form the ! . exceptional shifts. ==== ! Local Scalars real(sp) :: aa, bb, cc, cs, dd, sn, ss, swap integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2_${ik}$) :: jbcmpz ! Local Arrays real(sp) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = one return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_slahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_slahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, & ihiz, z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'SLAQR4', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'SLAQR4', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_slaqr2 ==== call stdlib${ii}$_slaqr2( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, wr, wi, h, ldh, n, h, ldh,n, h, ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_slaqr5, stdlib${ii}$_slaqr2) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=sp) return end if ! ==== stdlib${ii}$_slahqr/stdlib${ii}$_slaqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'SLAQR4', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'SLAQR4', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'SLAQR4', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_80: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( abs( h( kwtop, kwtop-1 ) )>abs( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_slaqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, wr, wi, h( kv, 1_${ik}$ ), ldh,nho, h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh,& work, lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_slaqr2 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_slaqr2 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, max( ks+1, ktop+2 ), -2 ss = abs( h( i, i-1 ) ) + abs( h( i-1, i-2 ) ) aa = wilk1*ss + h( i, i ) bb = ss cc = wilk2*ss dd = aa call stdlib${ii}$_slanv2( aa, bb, cc, dd, wr( i-1 ), wi( i-1 ),wr( i ), wi( i & ), cs, sn ) end do if( ks==ktop ) then wr( ks+1 ) = h( ks+1, ks+1 ) wi( ks+1 ) = zero wr( ks ) = wr( ks+1 ) wi( ks ) = wi( ks+1 ) end if else ! ==== got ns/2 or fewer shifts? use stdlib_slahqr ! . on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_slacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) call stdlib${ii}$_slahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, wr( ks & ), wi( ks ),1_${ik}$, 1_${ik}$, zdum, 1_${ik}$, inf ) ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. ==== if( ks>=kbot ) then aa = h( kbot-1, kbot-1 ) cc = h( kbot, kbot-1 ) bb = h( kbot-1, kbot ) dd = h( kbot, kbot ) call stdlib${ii}$_slanv2( aa, bb, cc, dd, wr( kbot-1 ),wi( kbot-1 ), wr( & kbot ),wi( kbot ), cs, sn ) ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ! . bubble sort keeps complex conjugate ! . pairs together. ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( abs( wr( i ) )+abs( wi( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_80 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 90 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=sp) end subroutine stdlib${ii}$_slaqr4 module subroutine stdlib${ii}$_dlaqr4( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, work,& !! DLAQR4 implements one level of recursion for DLAQR0. !! It is a complete implementation of the small bulge multi-shift !! QR algorithm. It may be called by DLAQR0 and, for large enough !! deflation window size, it may be called by DLAQR3. This !! subroutine is identical to DLAQR0 except that it calls DLAQR2 !! instead of DLAQR3. !! DLAQR4 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**T, where T is an upper quasi-triangular matrix (the !! Schur form), and Z is the orthogonal matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input orthogonal !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(dp), intent(inout) :: h(ldh,*), z(ldz,*) real(dp), intent(out) :: wi(*), work(*), wr(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(dp), parameter :: wilk1 = 0.75_dp real(dp), parameter :: wilk2 = -0.4375_dp ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_dlahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constants wilk1 and wilk2 are used to form the ! . exceptional shifts. ==== ! Local Scalars real(dp) :: aa, bb, cc, cs, dd, sn, ss, swap integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2_${ik}$) :: jbcmpz ! Local Arrays real(dp) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = one return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_dlahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_dlahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, & ihiz, z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'DLAQR4', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'DLAQR4', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_dlaqr2 ==== call stdlib${ii}$_dlaqr2( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, wr, wi, h, ldh, n, h, ldh,n, h, ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_dlaqr5, stdlib${ii}$_dlaqr2) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=dp) return end if ! ==== stdlib${ii}$_dlahqr/stdlib${ii}$_dlaqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'DLAQR4', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'DLAQR4', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'DLAQR4', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_80: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( abs( h( kwtop, kwtop-1 ) )>abs( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_dlaqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, wr, wi, h( kv, 1_${ik}$ ), ldh,nho, h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh,& work, lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_dlaqr2 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_dlaqr2 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, max( ks+1, ktop+2 ), -2 ss = abs( h( i, i-1 ) ) + abs( h( i-1, i-2 ) ) aa = wilk1*ss + h( i, i ) bb = ss cc = wilk2*ss dd = aa call stdlib${ii}$_dlanv2( aa, bb, cc, dd, wr( i-1 ), wi( i-1 ),wr( i ), wi( i & ), cs, sn ) end do if( ks==ktop ) then wr( ks+1 ) = h( ks+1, ks+1 ) wi( ks+1 ) = zero wr( ks ) = wr( ks+1 ) wi( ks ) = wi( ks+1 ) end if else ! ==== got ns/2 or fewer shifts? use stdlib_dlahqr ! . on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_dlacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) call stdlib${ii}$_dlahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, wr( ks & ), wi( ks ),1_${ik}$, 1_${ik}$, zdum, 1_${ik}$, inf ) ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. ==== if( ks>=kbot ) then aa = h( kbot-1, kbot-1 ) cc = h( kbot, kbot-1 ) bb = h( kbot-1, kbot ) dd = h( kbot, kbot ) call stdlib${ii}$_dlanv2( aa, bb, cc, dd, wr( kbot-1 ),wi( kbot-1 ), wr( & kbot ),wi( kbot ), cs, sn ) ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ! . bubble sort keeps complex conjugate ! . pairs together. ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( abs( wr( i ) )+abs( wi( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_80 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 90 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=dp) end subroutine stdlib${ii}$_dlaqr4 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$laqr4( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, ihiz, z, ldz, work,& !! DLAQR4: implements one level of recursion for DLAQR0. !! It is a complete implementation of the small bulge multi-shift !! QR algorithm. It may be called by DLAQR0 and, for large enough !! deflation window size, it may be called by DLAQR3. This !! subroutine is identical to DLAQR0 except that it calls DLAQR2 !! instead of DLAQR3. !! DLAQR4 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**T, where T is an upper quasi-triangular matrix (the !! Schur form), and Z is the orthogonal matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input orthogonal !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(${rk}$), intent(inout) :: h(ldh,*), z(ldz,*) real(${rk}$), intent(out) :: wi(*), work(*), wr(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(${rk}$), parameter :: wilk1 = 0.75_${rk}$ real(${rk}$), parameter :: wilk2 = -0.4375_${rk}$ ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_${ri}$lahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constants wilk1 and wilk2 are used to form the ! . exceptional shifts. ==== ! Local Scalars real(${rk}$) :: aa, bb, cc, cs, dd, sn, ss, swap integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2_${ik}$) :: jbcmpz ! Local Arrays real(${rk}$) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = one return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_${ri}$lahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_${ri}$lahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi,iloz, & ihiz, z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'DLAQR4', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'DLAQR4', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_${ri}$laqr2 ==== call stdlib${ii}$_${ri}$laqr2( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, wr, wi, h, ldh, n, h, ldh,n, h, ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_${ri}$laqr5, stdlib${ii}$_${ri}$laqr2) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lwkopt,KIND=${rk}$) return end if ! ==== stdlib${ii}$_${ri}$lahqr/stdlib${ii}$_${ri}$laqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'DLAQR4', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'DLAQR4', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'DLAQR4', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_80: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( abs( h( kwtop, kwtop-1 ) )>abs( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_${ri}$laqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, wr, wi, h( kv, 1_${ik}$ ), ldh,nho, h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh,& work, lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_${ri}$laqr2 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_${ri}$laqr2 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, max( ks+1, ktop+2 ), -2 ss = abs( h( i, i-1 ) ) + abs( h( i-1, i-2 ) ) aa = wilk1*ss + h( i, i ) bb = ss cc = wilk2*ss dd = aa call stdlib${ii}$_${ri}$lanv2( aa, bb, cc, dd, wr( i-1 ), wi( i-1 ),wr( i ), wi( i & ), cs, sn ) end do if( ks==ktop ) then wr( ks+1 ) = h( ks+1, ks+1 ) wi( ks+1 ) = zero wr( ks ) = wr( ks+1 ) wi( ks ) = wi( ks+1 ) end if else ! ==== got ns/2 or fewer shifts? use stdlib_${ri}$lahqr ! . on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_${ri}$lacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) call stdlib${ii}$_${ri}$lahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, wr( ks & ), wi( ks ),1_${ik}$, 1_${ik}$, zdum, 1_${ik}$, inf ) ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. ==== if( ks>=kbot ) then aa = h( kbot-1, kbot-1 ) cc = h( kbot, kbot-1 ) bb = h( kbot-1, kbot ) dd = h( kbot, kbot ) call stdlib${ii}$_${ri}$lanv2( aa, bb, cc, dd, wr( kbot-1 ),wi( kbot-1 ), wr( & kbot ),wi( kbot ), cs, sn ) ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ! . bubble sort keeps complex conjugate ! . pairs together. ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( abs( wr( i ) )+abs( wi( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_80 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 90 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = real( lwkopt,KIND=${rk}$) end subroutine stdlib${ii}$_${ri}$laqr4 #:endif #:endfor pure module subroutine stdlib${ii}$_claqr4( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, work,& !! CLAQR4 implements one level of recursion for CLAQR0. !! It is a complete implementation of the small bulge multi-shift !! QR algorithm. It may be called by CLAQR0 and, for large enough !! deflation window size, it may be called by CLAQR3. This !! subroutine is identical to CLAQR0 except that it calls CLAQR2 !! instead of CLAQR3. !! CLAQR4 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*H*(QZ)**H. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(sp), intent(inout) :: h(ldh,*), z(ldz,*) complex(sp), intent(out) :: w(*), work(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(sp), parameter :: wilk1 = 0.75_sp ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_clahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constant wilk1 is used to form the exceptional ! . shifts. ==== ! Local Scalars complex(sp) :: aa, bb, cc, cdum, dd, det, rtdisc, swap, tr2 real(sp) :: s integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2) :: jbcmpz ! Local Arrays complex(sp) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = cone return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_clahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_clahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, & z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'CLAQR4', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'CLAQR4', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_claqr2 ==== call stdlib${ii}$_claqr2( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, w, h, ldh, n, h, ldh, n, h,ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_claqr5, stdlib${ii}$_claqr2) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=sp) return end if ! ==== stdlib${ii}$_clahqr/stdlib${ii}$_claqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'CLAQR4', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'CLAQR4', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'CLAQR4', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_70: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( cabs1( h( kwtop, kwtop-1 ) )>cabs1( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_claqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, w, h( kv, 1_${ik}$ ), ldh, nho,h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh, work,& lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_claqr2 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_claqr2 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, ks + 1, -2 w( i ) = h( i, i ) + wilk1*cabs1( h( i, i-1 ) ) w( i-1 ) = w( i ) end do else ! ==== got ns/2 or fewer shifts? use stdlib_clahqr ! . on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_clacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) call stdlib${ii}$_clahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, w( ks )& , 1_${ik}$, 1_${ik}$, zdum,1_${ik}$, inf ) ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. scale to avoid ! . overflows, underflows and subnormals. ! . (the scale factor s can not be czero, ! . because h(kbot,kbot-1) is nonzero.) ==== if( ks>=kbot ) then s = cabs1( h( kbot-1, kbot-1 ) ) +cabs1( h( kbot, kbot-1 ) ) +cabs1( & h( kbot-1, kbot ) ) +cabs1( h( kbot, kbot ) ) aa = h( kbot-1, kbot-1 ) / s cc = h( kbot, kbot-1 ) / s bb = h( kbot-1, kbot ) / s dd = h( kbot, kbot ) / s tr2 = ( aa+dd ) / two det = ( aa-tr2 )*( dd-tr2 ) - bb*cc rtdisc = sqrt( -det ) w( kbot-1 ) = ( tr2+rtdisc )*s w( kbot ) = ( tr2-rtdisc )*s ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( cabs1( w( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_70 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 80 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=sp) end subroutine stdlib${ii}$_claqr4 pure module subroutine stdlib${ii}$_zlaqr4( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, work,& !! ZLAQR4 implements one level of recursion for ZLAQR0. !! It is a complete implementation of the small bulge multi-shift !! QR algorithm. It may be called by ZLAQR0 and, for large enough !! deflation window size, it may be called by ZLAQR3. This !! subroutine is identical to ZLAQR0 except that it calls ZLAQR2 !! instead of ZLAQR3. !! ZLAQR4 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*H*(QZ)**H. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(dp), intent(inout) :: h(ldh,*), z(ldz,*) complex(dp), intent(out) :: w(*), work(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(dp), parameter :: wilk1 = 0.75_dp ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_zlahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constant wilk1 is used to form the exceptional ! . shifts. ==== ! Local Scalars complex(dp) :: aa, bb, cc, cdum, dd, det, rtdisc, swap, tr2 real(dp) :: s integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2) :: jbcmpz ! Local Arrays complex(dp) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = cone return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_zlahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_zlahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, & z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'ZLAQR4', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'ZLAQR4', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_zlaqr2 ==== call stdlib${ii}$_zlaqr2( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, w, h, ldh, n, h, ldh, n, h,ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_zlaqr5, stdlib${ii}$_zlaqr2) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=dp) return end if ! ==== stdlib${ii}$_zlahqr/stdlib${ii}$_zlaqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'ZLAQR4', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'ZLAQR4', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'ZLAQR4', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_70: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( cabs1( h( kwtop, kwtop-1 ) )>cabs1( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_zlaqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, w, h( kv, 1_${ik}$ ), ldh, nho,h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh, work,& lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_zlaqr2 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_zlaqr2 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, ks + 1, -2 w( i ) = h( i, i ) + wilk1*cabs1( h( i, i-1 ) ) w( i-1 ) = w( i ) end do else ! ==== got ns/2 or fewer shifts? use stdlib_zlahqr ! . on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_zlacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) call stdlib${ii}$_zlahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, w( ks )& , 1_${ik}$, 1_${ik}$, zdum,1_${ik}$, inf ) ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. scale to avoid ! . overflows, underflows and subnormals. ! . (the scale factor s can not be czero, ! . because h(kbot,kbot-1) is nonzero.) ==== if( ks>=kbot ) then s = cabs1( h( kbot-1, kbot-1 ) ) +cabs1( h( kbot, kbot-1 ) ) +cabs1( & h( kbot-1, kbot ) ) +cabs1( h( kbot, kbot ) ) aa = h( kbot-1, kbot-1 ) / s cc = h( kbot, kbot-1 ) / s bb = h( kbot-1, kbot ) / s dd = h( kbot, kbot ) / s tr2 = ( aa+dd ) / two det = ( aa-tr2 )*( dd-tr2 ) - bb*cc rtdisc = sqrt( -det ) w( kbot-1 ) = ( tr2+rtdisc )*s w( kbot ) = ( tr2-rtdisc )*s ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( cabs1( w( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_70 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 80 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=dp) end subroutine stdlib${ii}$_zlaqr4 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqr4( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, z, ldz, work,& !! ZLAQR4: implements one level of recursion for ZLAQR0. !! It is a complete implementation of the small bulge multi-shift !! QR algorithm. It may be called by ZLAQR0 and, for large enough !! deflation window size, it may be called by ZLAQR3. This !! subroutine is identical to ZLAQR0 except that it calls ZLAQR2 !! instead of ZLAQR3. !! ZLAQR4 computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*H*(QZ)**H. lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ihiz, ilo, iloz, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(${ck}$), intent(inout) :: h(ldh,*), z(ldz,*) complex(${ck}$), intent(out) :: w(*), work(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: kexnw = 5_${ik}$ integer(${ik}$), parameter :: kexsh = 6_${ik}$ real(${ck}$), parameter :: wilk1 = 0.75_${ck}$ ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_${ci}$lahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== exceptional deflation windows: try to cure rare ! . slow convergence by varying the size of the ! . deflation window after kexnw iterations. ==== ! ==== exceptional shifts: try to cure rare slow convergence ! . with ad-hoc exceptional shifts every kexsh iterations. ! . ==== ! ==== the constant wilk1 is used to form the exceptional ! . shifts. ==== ! Local Scalars complex(${ck}$) :: aa, bb, cc, cdum, dd, det, rtdisc, swap, tr2 real(${ck}$) :: s integer(${ik}$) :: i, inf, it, itmax, k, kacc22, kbot, kdu, ks, kt, ktop, ku, kv, kwh, & kwtop, kwv, ld, ls, lwkopt, ndec, ndfl, nh, nho, nibble, nmin, ns, nsmax, nsr, nve, nw,& nwmax, nwr, nwupbd logical(lk) :: sorted character(len=2) :: jbcmpz ! Local Arrays complex(${ck}$) :: zdum(1_${ik}$,1_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! ==== quick return for n = 0: nothing to do. ==== if( n==0_${ik}$ ) then work( 1_${ik}$ ) = cone return end if if( n<=ntiny ) then ! ==== tiny matrices must use stdlib_${ci}$lahqr. ==== lwkopt = 1_${ik}$ if( lwork/=-1_${ik}$ )call stdlib${ii}$_${ci}$lahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, iloz,ihiz, & z, ldz, info ) else ! ==== use small bulge multi-shift qr with aggressive early ! . deflation on larger-than-tiny matrices. ==== ! ==== hope for the best. ==== info = 0_${ik}$ ! ==== set up job flags for stdlib${ii}$_ilaenv. ==== if( wantt ) then jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'S' else jbcmpz( 1_${ik}$: 1_${ik}$ ) = 'E' end if if( wantz ) then jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'V' else jbcmpz( 2_${ik}$: 2_${ik}$ ) = 'N' end if ! ==== nwr = recommended deflation window size. at this ! . point, n > ntiny = 15, so there is enough ! . subdiagonal workspace for nwr>=2 as required. ! . (in fact, there is enough subdiagonal space for ! . nwr>=4.) ==== nwr = stdlib${ii}$_ilaenv( 13_${ik}$, 'ZLAQR4', jbcmpz, n, ilo, ihi, lwork ) nwr = max( 2_${ik}$, nwr ) nwr = min( ihi-ilo+1, ( n-1 ) / 3_${ik}$, nwr ) ! ==== nsr = recommended number of simultaneous shifts. ! . at this point n > ntiny = 15, so there is at ! . enough subdiagonal workspace for nsr to be even ! . and greater than or equal to two as required. ==== nsr = stdlib${ii}$_ilaenv( 15_${ik}$, 'ZLAQR4', jbcmpz, n, ilo, ihi, lwork ) nsr = min( nsr, ( n-3 ) / 6_${ik}$, ihi-ilo ) nsr = max( 2_${ik}$, nsr-mod( nsr, 2_${ik}$ ) ) ! ==== estimate optimal workspace ==== ! ==== workspace query call to stdlib${ii}$_${ci}$laqr2 ==== call stdlib${ii}$_${ci}$laqr2( wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz,ihiz, z, ldz, ls,& ld, w, h, ldh, n, h, ldh, n, h,ldh, work, -1_${ik}$ ) ! ==== optimal workspace = max(stdlib${ii}$_${ci}$laqr5, stdlib${ii}$_${ci}$laqr2) ==== lwkopt = max( 3_${ik}$*nsr / 2_${ik}$, int( work( 1_${ik}$ ),KIND=${ik}$) ) ! ==== quick return in case of workspace query. ==== if( lwork==-1_${ik}$ ) then work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=${ck}$) return end if ! ==== stdlib${ii}$_${ci}$lahqr/stdlib${ii}$_${ci}$laqr0 crossover point ==== nmin = stdlib${ii}$_ilaenv( 12_${ik}$, 'ZLAQR4', jbcmpz, n, ilo, ihi, lwork ) nmin = max( ntiny, nmin ) ! ==== nibble crossover point ==== nibble = stdlib${ii}$_ilaenv( 14_${ik}$, 'ZLAQR4', jbcmpz, n, ilo, ihi, lwork ) nibble = max( 0_${ik}$, nibble ) ! ==== accumulate reflections during ttswp? use block ! . 2-by-2 structure during matrix-matrix multiply? ==== kacc22 = stdlib${ii}$_ilaenv( 16_${ik}$, 'ZLAQR4', jbcmpz, n, ilo, ihi, lwork ) kacc22 = max( 0_${ik}$, kacc22 ) kacc22 = min( 2_${ik}$, kacc22 ) ! ==== nwmax = the largest possible deflation window for ! . which there is sufficient workspace. ==== nwmax = min( ( n-1 ) / 3_${ik}$, lwork / 2_${ik}$ ) nw = nwmax ! ==== nsmax = the largest number of simultaneous shifts ! . for which there is sufficient workspace. ==== nsmax = min( ( n-3 ) / 6_${ik}$, 2_${ik}$*lwork / 3_${ik}$ ) nsmax = nsmax - mod( nsmax, 2_${ik}$ ) ! ==== ndfl: an iteration count restarted at deflation. ==== ndfl = 1_${ik}$ ! ==== itmax = iteration limit ==== itmax = max( 30_${ik}$, 2_${ik}$*kexsh )*max( 10_${ik}$, ( ihi-ilo+1 ) ) ! ==== last row and column in the active block ==== kbot = ihi ! ==== main loop ==== loop_70: do it = 1, itmax ! ==== done when kbot falls below ilo ==== if( kbot=nh-1 ) then nw = nh else kwtop = kbot - nw + 1_${ik}$ if( cabs1( h( kwtop, kwtop-1 ) )>cabs1( h( kwtop-1, kwtop-2 ) ) )nw = nw + & 1_${ik}$ end if end if if( ndfl=0_${ik}$ .or. nw>=nwupbd ) then ndec = ndec + 1_${ik}$ if( nw-ndec<2_${ik}$ )ndec = 0_${ik}$ nw = nw - ndec end if ! ==== aggressive early deflation: ! . split workspace under the subdiagonal into ! . - an nw-by-nw work array v in the lower ! . left-hand-corner, ! . - an nw-by-at-least-nw-but-more-is-better ! . (nw-by-nho) horizontal work array along ! . the bottom edge, ! . - an at-least-nw-but-more-is-better (nhv-by-nw) ! . vertical work array along the left-hand-edge. ! . ==== kv = n - nw + 1_${ik}$ kt = nw + 1_${ik}$ nho = ( n-nw-1 ) - kt + 1_${ik}$ kwv = nw + 2_${ik}$ nve = ( n-nw ) - kwv + 1_${ik}$ ! ==== aggressive early deflation ==== call stdlib${ii}$_${ci}$laqr2( wantt, wantz, n, ktop, kbot, nw, h, ldh, iloz,ihiz, z, ldz, & ls, ld, w, h( kv, 1_${ik}$ ), ldh, nho,h( kv, kt ), ldh, nve, h( kwv, 1_${ik}$ ), ldh, work,& lwork ) ! ==== adjust kbot accounting for new deflations. ==== kbot = kbot - ld ! ==== ks points to the shifts. ==== ks = kbot - ls + 1_${ik}$ ! ==== skip an expensive qr sweep if there is a (partly ! . heuristic) reason to expect that many eigenvalues ! . will deflate without it. here, the qr sweep is ! . skipped if many eigenvalues have just been deflated ! . or if the remaining active block is small. if( ( ld==0_${ik}$ ) .or. ( ( 100_${ik}$*ld<=nw*nibble ) .and. ( kbot-ktop+1>min( nmin, nwmax )& ) ) ) then ! ==== ns = nominal number of simultaneous shifts. ! . this may be lowered (slightly) if stdlib${ii}$_${ci}$laqr2 ! . did not provide that many shifts. ==== ns = min( nsmax, nsr, max( 2_${ik}$, kbot-ktop ) ) ns = ns - mod( ns, 2_${ik}$ ) ! ==== if there have been no deflations ! . in a multiple of kexsh iterations, ! . then try exceptional shifts. ! . otherwise use shifts provided by ! . stdlib${ii}$_${ci}$laqr2 above or from the eigenvalues ! . of a trailing principal submatrix. ==== if( mod( ndfl, kexsh )==0_${ik}$ ) then ks = kbot - ns + 1_${ik}$ do i = kbot, ks + 1, -2 w( i ) = h( i, i ) + wilk1*cabs1( h( i, i-1 ) ) w( i-1 ) = w( i ) end do else ! ==== got ns/2 or fewer shifts? use stdlib_${ci}$lahqr ! . on a trailing principal submatrix to ! . get more. (since ns<=nsmax<=(n-3)/6, ! . there is enough space below the subdiagonal ! . to fit an ns-by-ns scratch array.) ==== if( kbot-ks+1<=ns / 2_${ik}$ ) then ks = kbot - ns + 1_${ik}$ kt = n - ns + 1_${ik}$ call stdlib${ii}$_${ci}$lacpy( 'A', ns, ns, h( ks, ks ), ldh,h( kt, 1_${ik}$ ), ldh ) call stdlib${ii}$_${ci}$lahqr( .false., .false., ns, 1_${ik}$, ns,h( kt, 1_${ik}$ ), ldh, w( ks )& , 1_${ik}$, 1_${ik}$, zdum,1_${ik}$, inf ) ks = ks + inf ! ==== in case of a rare qr failure use ! . eigenvalues of the trailing 2-by-2 ! . principal submatrix. scale to avoid ! . overflows, underflows and subnormals. ! . (the scale factor s can not be czero, ! . because h(kbot,kbot-1) is nonzero.) ==== if( ks>=kbot ) then s = cabs1( h( kbot-1, kbot-1 ) ) +cabs1( h( kbot, kbot-1 ) ) +cabs1( & h( kbot-1, kbot ) ) +cabs1( h( kbot, kbot ) ) aa = h( kbot-1, kbot-1 ) / s cc = h( kbot, kbot-1 ) / s bb = h( kbot-1, kbot ) / s dd = h( kbot, kbot ) / s tr2 = ( aa+dd ) / two det = ( aa-tr2 )*( dd-tr2 ) - bb*cc rtdisc = sqrt( -det ) w( kbot-1 ) = ( tr2+rtdisc )*s w( kbot ) = ( tr2-rtdisc )*s ks = kbot - 1_${ik}$ end if end if if( kbot-ks+1>ns ) then ! ==== sort the shifts (helps a little) ==== sorted = .false. do k = kbot, ks + 1, -1 if( sorted )go to 60 sorted = .true. do i = ks, k - 1 if( cabs1( w( i ) )0_${ik}$ ) then ndfl = 1_${ik}$ else ndfl = ndfl + 1_${ik}$ end if ! ==== end of main loop ==== end do loop_70 ! ==== iteration limit exceeded. set info to show where ! . the problem occurred and exit. ==== info = kbot 80 continue end if ! ==== return the optimal value of lwork. ==== work( 1_${ik}$ ) = cmplx( lwkopt, 0_${ik}$,KIND=${ck}$) end subroutine stdlib${ii}$_${ci}$laqr4 #:endif #:endfor pure module subroutine stdlib${ii}$_slaqr5( wantt, wantz, kacc22, n, ktop, kbot, nshfts,sr, si, h, ldh, & !! SLAQR5 , called by SLAQR0, performs a !! single small-bulge multi-shift QR sweep. iloz, ihiz, z, ldz, v, ldv, u,ldu, nv, wv, ldwv, nh, wh, ldwh ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kacc22, kbot, ktop, ldh, ldu, ldv, ldwh, ldwv, & ldz, n, nh, nshfts, nv logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(sp), intent(inout) :: h(ldh,*), si(*), sr(*), z(ldz,*) real(sp), intent(out) :: u(ldu,*), v(ldv,*), wh(ldwh,*), wv(ldwv,*) ! ================================================================ ! Local Scalars real(sp) :: alpha, beta, h11, h12, h21, h22, refsum, safmax, safmin, scl, smlnum, swap,& tst1, tst2, ulp integer(${ik}$) :: i, i2, i4, incol, j, jbot, jcol, jlen, jrow, jtop, k, k1, kdu, kms, & krcol, m, m22, mbot, mtop, nbmps, ndcol, ns, nu logical(lk) :: accum, bmp22 ! Intrinsic Functions ! Local Arrays real(sp) :: vt(3_${ik}$) ! Executable Statements ! ==== if there are no shifts, then there is nothing to do. ==== if( nshfts<2 )return ! ==== if the active block is empty or 1-by-1, then there ! . is nothing to do. ==== if( ktop>=kbot )return ! ==== shuffle shifts into pairs of real shifts and pairs ! . of complex conjugate shifts assuming complex ! . conjugate shifts are already adjacent to one ! . another. ==== do i = 1, nshfts - 2, 2 if( si( i )/=-si( i+1 ) ) then swap = sr( i ) sr( i ) = sr( i+1 ) sr( i+1 ) = sr( i+2 ) sr( i+2 ) = swap swap = si( i ) si( i ) = si( i+1 ) si( i+1 ) = si( i+2 ) si( i+2 ) = swap end if end do ! ==== nshfts is supposed to be even, but if it is odd, ! . then simply reduce it by one. the shuffle above ! . ensures that the dropped shift is real and that ! . the remaining shifts are paired. ==== ns = nshfts - mod( nshfts, 2_${ik}$ ) ! ==== machine constants for deflation ==== safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=sp) / ulp ) ! ==== use accumulated reflections to update far-from-diagonal ! . entries ? ==== accum = ( kacc22==1_${ik}$ ) .or. ( kacc22==2_${ik}$ ) ! ==== clear trash ==== if( ktop+2<=kbot )h( ktop+2, ktop ) = zero ! ==== nbmps = number of 2-shift bulges in the chain ==== nbmps = ns / 2_${ik}$ ! ==== kdu = width of slab ==== kdu = 4_${ik}$*nbmps ! ==== create and chase chains of nbmps bulges ==== loop_180: do incol = ktop - 2*nbmps + 1, kbot - 2, 2*nbmps ! jtop = index from which updates from the right start. if( accum ) then jtop = max( ktop, incol ) else if( wantt ) then jtop = 1_${ik}$ else jtop = ktop end if ndcol = incol + kdu if( accum )call stdlib${ii}$_slaset( 'ALL', kdu, kdu, zero, one, u, ldu ) ! ==== near-the-diagonal bulge chase. the following loop ! . performs the near-the-diagonal part of a small bulge ! . multi-shift qr sweep. each 4*nbmps column diagonal ! . chunk extends from column incol to column ndcol ! . (including both column incol and column ndcol). the ! . following loop chases a 2*nbmps+1 column long chain of ! . nbmps bulges 2*nbmps-1 columns to the right. (incol ! . may be less than ktop and and ndcol may be greater than ! . kbot indicating phantom columns from which to chase ! . bulges before they are actually introduced or to which ! . to chase bulges beyond column kbot.) ==== loop_145: do krcol = incol, min( incol+2*nbmps-1, kbot-2 ) ! ==== bulges number mtop to mbot are active double implicit ! . shift bulges. there may or may not also be small ! . 2-by-2 bulge, if there is room. the inactive bulges ! . (if any) must wait until the active bulges have moved ! . down the diagonal to make room. the phantom matrix ! . paradigm described above helps keep track. ==== mtop = max( 1_${ik}$, ( ktop-krcol ) / 2_${ik}$+1 ) mbot = min( nbmps, ( kbot-krcol-1 ) / 2_${ik}$ ) m22 = mbot + 1_${ik}$ bmp22 = ( mbot=ktop ) then if( h( k+1, k )/=zero ) then tst1 = abs( h( k, k ) ) + abs( h( k+1, k+1 ) ) if( tst1==zero ) then if( k>=ktop+1 )tst1 = tst1 + abs( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + abs( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + abs( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + abs( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + abs( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + abs( h( k+4, k+1 ) ) end if if( abs( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) )then h12 = max( abs( h( k+1, k ) ),abs( h( k, k+1 ) ) ) h21 = min( abs( h( k+1, k ) ),abs( h( k, k+1 ) ) ) h11 = max( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) ) & then h( k+1, k ) = zero end if end if end if end if ! ==== accumulate orthogonal transformations. ==== if( accum ) then kms = k - incol do j = max( 1, ktop-incol ), kdu refsum = v( 1_${ik}$, m22 )*( u( j, kms+1 )+v( 2_${ik}$, m22 )*u( j, kms+2 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) - refsum*v( 2_${ik}$, m22 ) end do else if( wantz ) then do j = iloz, ihiz refsum = v( 1_${ik}$, m22 )*( z( j, k+1 )+v( 2_${ik}$, m22 )*z( j, k+2 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) - refsum*v( 2_${ik}$, m22 ) end do end if end if ! ==== normal case: chain of 3-by-3 reflections ==== loop_80: do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) if( k==ktop-1 ) then call stdlib${ii}$_slaqr1( 3_${ik}$, h( ktop, ktop ), ldh, sr( 2_${ik}$*m-1 ),si( 2_${ik}$*m-1 ), sr( & 2_${ik}$*m ), si( 2_${ik}$*m ),v( 1_${ik}$, m ) ) alpha = v( 1_${ik}$, m ) call stdlib${ii}$_slarfg( 3_${ik}$, alpha, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) else ! ==== perform delayed transformation of row below ! . mth bulge. exploit fact that first two elements ! . of row are actually zero. ==== refsum = v( 1_${ik}$, m )*v( 3_${ik}$, m )*h( k+3, k+2 ) h( k+3, k ) = -refsum h( k+3, k+1 ) = -refsum*v( 2_${ik}$, m ) h( k+3, k+2 ) = h( k+3, k+2 ) - refsum*v( 3_${ik}$, m ) ! ==== calculate reflection to move ! . mth bulge one step. ==== beta = h( k+1, k ) v( 2_${ik}$, m ) = h( k+2, k ) v( 3_${ik}$, m ) = h( k+3, k ) call stdlib${ii}$_slarfg( 3_${ik}$, beta, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) ! ==== a bulge may collapse because of vigilant ! . deflation or destructive underflow. in the ! . underflow case, try the two-small-subdiagonals ! . trick to try to reinflate the bulge. ==== if( h( k+3, k )/=zero .or. h( k+3, k+1 )/=zero .or. h( k+3, k+2 )==zero ) & then ! ==== typical case: not collapsed (yet). ==== h( k+1, k ) = beta h( k+2, k ) = zero h( k+3, k ) = zero else ! ==== atypical case: collapsed. attempt to ! . reintroduce ignoring h(k+1,k) and h(k+2,k). ! . if the fill resulting from the new ! . reflector is too large, then abandon it. ! . otherwise, use the new one. ==== call stdlib${ii}$_slaqr1( 3_${ik}$, h( k+1, k+1 ), ldh, sr( 2_${ik}$*m-1 ),si( 2_${ik}$*m-1 ), sr( & 2_${ik}$*m ), si( 2_${ik}$*m ),vt ) alpha = vt( 1_${ik}$ ) call stdlib${ii}$_slarfg( 3_${ik}$, alpha, vt( 2_${ik}$ ), 1_${ik}$, vt( 1_${ik}$ ) ) refsum = vt( 1_${ik}$ )*( h( k+1, k )+vt( 2_${ik}$ )*h( k+2, k ) ) if( abs( h( k+2, k )-refsum*vt( 2_${ik}$ ) )+abs( refsum*vt( 3_${ik}$ ) )>ulp*( abs( & h( k, k ) )+abs( h( k+1,k+1 ) )+abs( h( k+2, k+2 ) ) ) ) then ! ==== starting a new bulge here would ! . create non-negligible fill. use ! . the old one with trepidation. ==== h( k+1, k ) = beta h( k+2, k ) = zero h( k+3, k ) = zero else ! ==== starting a new bulge here would ! . create only negligible fill. ! . replace the old reflector with ! . the new one. ==== h( k+1, k ) = h( k+1, k ) - refsum h( k+2, k ) = zero h( k+3, k ) = zero v( 1_${ik}$, m ) = vt( 1_${ik}$ ) v( 2_${ik}$, m ) = vt( 2_${ik}$ ) v( 3_${ik}$, m ) = vt( 3_${ik}$ ) end if end if end if ! ==== apply reflection from the right and ! . the first column of update from the left. ! . these updates are required for the vigilant ! . deflation check. we still delay most of the ! . updates from the left for efficiency. ==== do j = jtop, min( kbot, k+3 ) refsum = v( 1_${ik}$, m )*( h( j, k+1 )+v( 2_${ik}$, m )*h( j, k+2 )+v( 3_${ik}$, m )*h( j, k+3 & ) ) h( j, k+1 ) = h( j, k+1 ) - refsum h( j, k+2 ) = h( j, k+2 ) - refsum*v( 2_${ik}$, m ) h( j, k+3 ) = h( j, k+3 ) - refsum*v( 3_${ik}$, m ) end do ! ==== perform update from left for subsequent ! . column. ==== refsum = v( 1_${ik}$, m )*( h( k+1, k+1 )+v( 2_${ik}$, m )*h( k+2, k+1 )+v( 3_${ik}$, m )*h( k+3, & k+1 ) ) h( k+1, k+1 ) = h( k+1, k+1 ) - refsum h( k+2, k+1 ) = h( k+2, k+1 ) - refsum*v( 2_${ik}$, m ) h( k+3, k+1 ) = h( k+3, k+1 ) - refsum*v( 3_${ik}$, m ) ! ==== the following convergence test requires that ! . the tradition small-compared-to-nearby-diagonals ! . criterion and the ahues ! . criteria both be satisfied. the latter improves ! . accuracy in some examples. falling back on an ! . alternate convergence criterion when tst1 or tst2 ! . is zero (as done here) is traditional but probably ! . unnecessary. ==== if( k=ktop+1 )tst1 = tst1 + abs( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + abs( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + abs( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + abs( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + abs( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + abs( h( k+4, k+1 ) ) end if if( abs( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) )then h12 = max( abs( h( k+1, k ) ), abs( h( k, k+1 ) ) ) h21 = min( abs( h( k+1, k ) ), abs( h( k, k+1 ) ) ) h11 = max( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) ) & then h( k+1, k ) = zero end if end if end if end do loop_80 ! ==== multiply h by reflections from the left ==== if( accum ) then jbot = min( ndcol, kbot ) else if( wantt ) then jbot = n else jbot = kbot end if do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = max( ktop, krcol + 2*m ), jbot refsum = v( 1_${ik}$, m )*( h( k+1, j )+v( 2_${ik}$, m )*h( k+2, j )+v( 3_${ik}$, m )*h( k+3, j & ) ) h( k+1, j ) = h( k+1, j ) - refsum h( k+2, j ) = h( k+2, j ) - refsum*v( 2_${ik}$, m ) h( k+3, j ) = h( k+3, j ) - refsum*v( 3_${ik}$, m ) end do end do ! ==== accumulate orthogonal transformations. ==== if( accum ) then ! ==== accumulate u. (if needed, update z later ! . with an efficient matrix-matrix ! . multiply.) ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) kms = k - incol i2 = max( 1_${ik}$, ktop-incol ) i2 = max( i2, kms-(krcol-incol)+1_${ik}$ ) i4 = min( kdu, krcol + 2_${ik}$*( mbot-1 ) - incol + 5_${ik}$ ) do j = i2, i4 refsum = v( 1_${ik}$, m )*( u( j, kms+1 )+v( 2_${ik}$, m )*u( j, kms+2 )+v( 3_${ik}$, m )*u( & j, kms+3 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) - refsum*v( 2_${ik}$, m ) u( j, kms+3 ) = u( j, kms+3 ) - refsum*v( 3_${ik}$, m ) end do end do else if( wantz ) then ! ==== u is not accumulated, so update z ! . now by multiplying by reflections ! . from the right. ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = iloz, ihiz refsum = v( 1_${ik}$, m )*( z( j, k+1 )+v( 2_${ik}$, m )*z( j, k+2 )+v( 3_${ik}$, m )*z( j, & k+3 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) - refsum*v( 2_${ik}$, m ) z( j, k+3 ) = z( j, k+3 ) - refsum*v( 3_${ik}$, m ) end do end do end if ! ==== end of near-the-diagonal bulge chase. ==== end do loop_145 ! ==== use u (if accumulated) to update far-from-diagonal ! . entries in h. if required, use u to update z as ! . well. ==== if( accum ) then if( wantt ) then jtop = 1_${ik}$ jbot = n else jtop = ktop jbot = kbot end if k1 = max( 1_${ik}$, ktop-incol ) nu = ( kdu-max( 0_${ik}$, ndcol-kbot ) ) - k1 + 1_${ik}$ ! ==== horizontal multiply ==== do jcol = min( ndcol, kbot ) + 1, jbot, nh jlen = min( nh, jbot-jcol+1 ) call stdlib${ii}$_sgemm( 'C', 'N', nu, jlen, nu, one, u( k1, k1 ),ldu, h( incol+k1, & jcol ), ldh, zero, wh,ldwh ) call stdlib${ii}$_slacpy( 'ALL', nu, jlen, wh, ldwh,h( incol+k1, jcol ), ldh ) end do ! ==== vertical multiply ==== do jrow = jtop, max( ktop, incol ) - 1, nv jlen = min( nv, max( ktop, incol )-jrow ) call stdlib${ii}$_sgemm( 'N', 'N', jlen, nu, nu, one,h( jrow, incol+k1 ), ldh, u( & k1, k1 ),ldu, zero, wv, ldwv ) call stdlib${ii}$_slacpy( 'ALL', jlen, nu, wv, ldwv,h( jrow, incol+k1 ), ldh ) end do ! ==== z multiply (also vertical) ==== if( wantz ) then do jrow = iloz, ihiz, nv jlen = min( nv, ihiz-jrow+1 ) call stdlib${ii}$_sgemm( 'N', 'N', jlen, nu, nu, one,z( jrow, incol+k1 ), ldz, u(& k1, k1 ),ldu, zero, wv, ldwv ) call stdlib${ii}$_slacpy( 'ALL', jlen, nu, wv, ldwv,z( jrow, incol+k1 ), ldz ) end do end if end if end do loop_180 end subroutine stdlib${ii}$_slaqr5 pure module subroutine stdlib${ii}$_dlaqr5( wantt, wantz, kacc22, n, ktop, kbot, nshfts,sr, si, h, ldh, & !! DLAQR5 , called by DLAQR0, performs a !! single small-bulge multi-shift QR sweep. iloz, ihiz, z, ldz, v, ldv, u,ldu, nv, wv, ldwv, nh, wh, ldwh ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kacc22, kbot, ktop, ldh, ldu, ldv, ldwh, ldwv, & ldz, n, nh, nshfts, nv logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(dp), intent(inout) :: h(ldh,*), si(*), sr(*), z(ldz,*) real(dp), intent(out) :: u(ldu,*), v(ldv,*), wh(ldwh,*), wv(ldwv,*) ! ================================================================ ! Local Scalars real(dp) :: alpha, beta, h11, h12, h21, h22, refsum, safmax, safmin, scl, smlnum, swap,& tst1, tst2, ulp integer(${ik}$) :: i, i2, i4, incol, j, jbot, jcol, jlen, jrow, jtop, k, k1, kdu, kms, & krcol, m, m22, mbot, mtop, nbmps, ndcol, ns, nu logical(lk) :: accum, bmp22 ! Intrinsic Functions ! Local Arrays real(dp) :: vt(3_${ik}$) ! Executable Statements ! ==== if there are no shifts, then there is nothing to do. ==== if( nshfts<2 )return ! ==== if the active block is empty or 1-by-1, then there ! . is nothing to do. ==== if( ktop>=kbot )return ! ==== shuffle shifts into pairs of real shifts and pairs ! . of complex conjugate shifts assuming complex ! . conjugate shifts are already adjacent to one ! . another. ==== do i = 1, nshfts - 2, 2 if( si( i )/=-si( i+1 ) ) then swap = sr( i ) sr( i ) = sr( i+1 ) sr( i+1 ) = sr( i+2 ) sr( i+2 ) = swap swap = si( i ) si( i ) = si( i+1 ) si( i+1 ) = si( i+2 ) si( i+2 ) = swap end if end do ! ==== nshfts is supposed to be even, but if it is odd, ! . then simply reduce it by one. the shuffle above ! . ensures that the dropped shift is real and that ! . the remaining shifts are paired. ==== ns = nshfts - mod( nshfts, 2_${ik}$ ) ! ==== machine constants for deflation ==== safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=dp) / ulp ) ! ==== use accumulated reflections to update far-from-diagonal ! . entries ? ==== accum = ( kacc22==1_${ik}$ ) .or. ( kacc22==2_${ik}$ ) ! ==== clear trash ==== if( ktop+2<=kbot )h( ktop+2, ktop ) = zero ! ==== nbmps = number of 2-shift bulges in the chain ==== nbmps = ns / 2_${ik}$ ! ==== kdu = width of slab ==== kdu = 4_${ik}$*nbmps ! ==== create and chase chains of nbmps bulges ==== loop_180: do incol = ktop - 2*nbmps + 1, kbot - 2, 2*nbmps ! jtop = index from which updates from the right start. if( accum ) then jtop = max( ktop, incol ) else if( wantt ) then jtop = 1_${ik}$ else jtop = ktop end if ndcol = incol + kdu if( accum )call stdlib${ii}$_dlaset( 'ALL', kdu, kdu, zero, one, u, ldu ) ! ==== near-the-diagonal bulge chase. the following loop ! . performs the near-the-diagonal part of a small bulge ! . multi-shift qr sweep. each 4*nbmps column diagonal ! . chunk extends from column incol to column ndcol ! . (including both column incol and column ndcol). the ! . following loop chases a 2*nbmps+1 column long chain of ! . nbmps bulges 2*nbmps columns to the right. (incol ! . may be less than ktop and and ndcol may be greater than ! . kbot indicating phantom columns from which to chase ! . bulges before they are actually introduced or to which ! . to chase bulges beyond column kbot.) ==== loop_145: do krcol = incol, min( incol+2*nbmps-1, kbot-2 ) ! ==== bulges number mtop to mbot are active double implicit ! . shift bulges. there may or may not also be small ! . 2-by-2 bulge, if there is room. the inactive bulges ! . (if any) must wait until the active bulges have moved ! . down the diagonal to make room. the phantom matrix ! . paradigm described above helps keep track. ==== mtop = max( 1_${ik}$, ( ktop-krcol ) / 2_${ik}$+1 ) mbot = min( nbmps, ( kbot-krcol-1 ) / 2_${ik}$ ) m22 = mbot + 1_${ik}$ bmp22 = ( mbot=ktop ) then if( h( k+1, k )/=zero ) then tst1 = abs( h( k, k ) ) + abs( h( k+1, k+1 ) ) if( tst1==zero ) then if( k>=ktop+1 )tst1 = tst1 + abs( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + abs( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + abs( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + abs( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + abs( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + abs( h( k+4, k+1 ) ) end if if( abs( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) ) then h12 = max( abs( h( k+1, k ) ),abs( h( k, k+1 ) ) ) h21 = min( abs( h( k+1, k ) ),abs( h( k, k+1 ) ) ) h11 = max( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) ) & then h( k+1, k ) = zero end if end if end if end if ! ==== accumulate orthogonal transformations. ==== if( accum ) then kms = k - incol do j = max( 1, ktop-incol ), kdu refsum = v( 1_${ik}$, m22 )*( u( j, kms+1 )+v( 2_${ik}$, m22 )*u( j, kms+2 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) - refsum*v( 2_${ik}$, m22 ) end do else if( wantz ) then do j = iloz, ihiz refsum = v( 1_${ik}$, m22 )*( z( j, k+1 )+v( 2_${ik}$, m22 )*z( j, k+2 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) - refsum*v( 2_${ik}$, m22 ) end do end if end if ! ==== normal case: chain of 3-by-3 reflections ==== loop_80: do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) if( k==ktop-1 ) then call stdlib${ii}$_dlaqr1( 3_${ik}$, h( ktop, ktop ), ldh, sr( 2_${ik}$*m-1 ),si( 2_${ik}$*m-1 ), sr( & 2_${ik}$*m ), si( 2_${ik}$*m ),v( 1_${ik}$, m ) ) alpha = v( 1_${ik}$, m ) call stdlib${ii}$_dlarfg( 3_${ik}$, alpha, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) else ! ==== perform delayed transformation of row below ! . mth bulge. exploit fact that first two elements ! . of row are actually zero. ==== refsum = v( 1_${ik}$, m )*v( 3_${ik}$, m )*h( k+3, k+2 ) h( k+3, k ) = -refsum h( k+3, k+1 ) = -refsum*v( 2_${ik}$, m ) h( k+3, k+2 ) = h( k+3, k+2 ) - refsum*v( 3_${ik}$, m ) ! ==== calculate reflection to move ! . mth bulge one step. ==== beta = h( k+1, k ) v( 2_${ik}$, m ) = h( k+2, k ) v( 3_${ik}$, m ) = h( k+3, k ) call stdlib${ii}$_dlarfg( 3_${ik}$, beta, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) ! ==== a bulge may collapse because of vigilant ! . deflation or destructive underflow. in the ! . underflow case, try the two-small-subdiagonals ! . trick to try to reinflate the bulge. ==== if( h( k+3, k )/=zero .or. h( k+3, k+1 )/=zero .or. h( k+3, k+2 )==zero ) & then ! ==== typical case: not collapsed (yet). ==== h( k+1, k ) = beta h( k+2, k ) = zero h( k+3, k ) = zero else ! ==== atypical case: collapsed. attempt to ! . reintroduce ignoring h(k+1,k) and h(k+2,k). ! . if the fill resulting from the new ! . reflector is too large, then abandon it. ! . otherwise, use the new one. ==== call stdlib${ii}$_dlaqr1( 3_${ik}$, h( k+1, k+1 ), ldh, sr( 2_${ik}$*m-1 ),si( 2_${ik}$*m-1 ), sr( & 2_${ik}$*m ), si( 2_${ik}$*m ),vt ) alpha = vt( 1_${ik}$ ) call stdlib${ii}$_dlarfg( 3_${ik}$, alpha, vt( 2_${ik}$ ), 1_${ik}$, vt( 1_${ik}$ ) ) refsum = vt( 1_${ik}$ )*( h( k+1, k )+vt( 2_${ik}$ )*h( k+2, k ) ) if( abs( h( k+2, k )-refsum*vt( 2_${ik}$ ) )+abs( refsum*vt( 3_${ik}$ ) )>ulp*( abs( & h( k, k ) )+abs( h( k+1,k+1 ) )+abs( h( k+2, k+2 ) ) ) ) then ! ==== starting a new bulge here would ! . create non-negligible fill. use ! . the old one with trepidation. ==== h( k+1, k ) = beta h( k+2, k ) = zero h( k+3, k ) = zero else ! ==== starting a new bulge here would ! . create only negligible fill. ! . replace the old reflector with ! . the new one. ==== h( k+1, k ) = h( k+1, k ) - refsum h( k+2, k ) = zero h( k+3, k ) = zero v( 1_${ik}$, m ) = vt( 1_${ik}$ ) v( 2_${ik}$, m ) = vt( 2_${ik}$ ) v( 3_${ik}$, m ) = vt( 3_${ik}$ ) end if end if end if ! ==== apply reflection from the right and ! . the first column of update from the left. ! . these updates are required for the vigilant ! . deflation check. we still delay most of the ! . updates from the left for efficiency. ==== do j = jtop, min( kbot, k+3 ) refsum = v( 1_${ik}$, m )*( h( j, k+1 )+v( 2_${ik}$, m )*h( j, k+2 )+v( 3_${ik}$, m )*h( j, k+3 & ) ) h( j, k+1 ) = h( j, k+1 ) - refsum h( j, k+2 ) = h( j, k+2 ) - refsum*v( 2_${ik}$, m ) h( j, k+3 ) = h( j, k+3 ) - refsum*v( 3_${ik}$, m ) end do ! ==== perform update from left for subsequent ! . column. ==== refsum = v( 1_${ik}$, m )*( h( k+1, k+1 )+v( 2_${ik}$, m )*h( k+2, k+1 )+v( 3_${ik}$, m )*h( k+3, & k+1 ) ) h( k+1, k+1 ) = h( k+1, k+1 ) - refsum h( k+2, k+1 ) = h( k+2, k+1 ) - refsum*v( 2_${ik}$, m ) h( k+3, k+1 ) = h( k+3, k+1 ) - refsum*v( 3_${ik}$, m ) ! ==== the following convergence test requires that ! . the tradition small-compared-to-nearby-diagonals ! . criterion and the ahues ! . criteria both be satisfied. the latter improves ! . accuracy in some examples. falling back on an ! . alternate convergence criterion when tst1 or tst2 ! . is zero (as done here) is traditional but probably ! . unnecessary. ==== if( k=ktop+1 )tst1 = tst1 + abs( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + abs( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + abs( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + abs( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + abs( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + abs( h( k+4, k+1 ) ) end if if( abs( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) )then h12 = max( abs( h( k+1, k ) ), abs( h( k, k+1 ) ) ) h21 = min( abs( h( k+1, k ) ), abs( h( k, k+1 ) ) ) h11 = max( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) ) & then h( k+1, k ) = zero end if end if end if end do loop_80 ! ==== multiply h by reflections from the left ==== if( accum ) then jbot = min( ndcol, kbot ) else if( wantt ) then jbot = n else jbot = kbot end if do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = max( ktop, krcol + 2*m ), jbot refsum = v( 1_${ik}$, m )*( h( k+1, j )+v( 2_${ik}$, m )*h( k+2, j )+v( 3_${ik}$, m )*h( k+3, j & ) ) h( k+1, j ) = h( k+1, j ) - refsum h( k+2, j ) = h( k+2, j ) - refsum*v( 2_${ik}$, m ) h( k+3, j ) = h( k+3, j ) - refsum*v( 3_${ik}$, m ) end do end do ! ==== accumulate orthogonal transformations. ==== if( accum ) then ! ==== accumulate u. (if needed, update z later ! . with an efficient matrix-matrix ! . multiply.) ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) kms = k - incol i2 = max( 1_${ik}$, ktop-incol ) i2 = max( i2, kms-(krcol-incol)+1_${ik}$ ) i4 = min( kdu, krcol + 2_${ik}$*( mbot-1 ) - incol + 5_${ik}$ ) do j = i2, i4 refsum = v( 1_${ik}$, m )*( u( j, kms+1 )+v( 2_${ik}$, m )*u( j, kms+2 )+v( 3_${ik}$, m )*u( & j, kms+3 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) - refsum*v( 2_${ik}$, m ) u( j, kms+3 ) = u( j, kms+3 ) - refsum*v( 3_${ik}$, m ) end do end do else if( wantz ) then ! ==== u is not accumulated, so update z ! . now by multiplying by reflections ! . from the right. ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = iloz, ihiz refsum = v( 1_${ik}$, m )*( z( j, k+1 )+v( 2_${ik}$, m )*z( j, k+2 )+v( 3_${ik}$, m )*z( j, & k+3 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) - refsum*v( 2_${ik}$, m ) z( j, k+3 ) = z( j, k+3 ) - refsum*v( 3_${ik}$, m ) end do end do end if ! ==== end of near-the-diagonal bulge chase. ==== end do loop_145 ! ==== use u (if accumulated) to update far-from-diagonal ! . entries in h. if required, use u to update z as ! . well. ==== if( accum ) then if( wantt ) then jtop = 1_${ik}$ jbot = n else jtop = ktop jbot = kbot end if k1 = max( 1_${ik}$, ktop-incol ) nu = ( kdu-max( 0_${ik}$, ndcol-kbot ) ) - k1 + 1_${ik}$ ! ==== horizontal multiply ==== do jcol = min( ndcol, kbot ) + 1, jbot, nh jlen = min( nh, jbot-jcol+1 ) call stdlib${ii}$_dgemm( 'C', 'N', nu, jlen, nu, one, u( k1, k1 ),ldu, h( incol+k1, & jcol ), ldh, zero, wh,ldwh ) call stdlib${ii}$_dlacpy( 'ALL', nu, jlen, wh, ldwh,h( incol+k1, jcol ), ldh ) end do ! ==== vertical multiply ==== do jrow = jtop, max( ktop, incol ) - 1, nv jlen = min( nv, max( ktop, incol )-jrow ) call stdlib${ii}$_dgemm( 'N', 'N', jlen, nu, nu, one,h( jrow, incol+k1 ), ldh, u( & k1, k1 ),ldu, zero, wv, ldwv ) call stdlib${ii}$_dlacpy( 'ALL', jlen, nu, wv, ldwv,h( jrow, incol+k1 ), ldh ) end do ! ==== z multiply (also vertical) ==== if( wantz ) then do jrow = iloz, ihiz, nv jlen = min( nv, ihiz-jrow+1 ) call stdlib${ii}$_dgemm( 'N', 'N', jlen, nu, nu, one,z( jrow, incol+k1 ), ldz, u(& k1, k1 ),ldu, zero, wv, ldwv ) call stdlib${ii}$_dlacpy( 'ALL', jlen, nu, wv, ldwv,z( jrow, incol+k1 ), ldz ) end do end if end if end do loop_180 end subroutine stdlib${ii}$_dlaqr5 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqr5( wantt, wantz, kacc22, n, ktop, kbot, nshfts,sr, si, h, ldh, & !! DLAQR5:, called by DLAQR0, performs a !! single small-bulge multi-shift QR sweep. iloz, ihiz, z, ldz, v, ldv, u,ldu, nv, wv, ldwv, nh, wh, ldwh ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kacc22, kbot, ktop, ldh, ldu, ldv, ldwh, ldwv, & ldz, n, nh, nshfts, nv logical(lk), intent(in) :: wantt, wantz ! Array Arguments real(${rk}$), intent(inout) :: h(ldh,*), si(*), sr(*), z(ldz,*) real(${rk}$), intent(out) :: u(ldu,*), v(ldv,*), wh(ldwh,*), wv(ldwv,*) ! ================================================================ ! Local Scalars real(${rk}$) :: alpha, beta, h11, h12, h21, h22, refsum, safmax, safmin, scl, smlnum, swap,& tst1, tst2, ulp integer(${ik}$) :: i, i2, i4, incol, j, jbot, jcol, jlen, jrow, jtop, k, k1, kdu, kms, & krcol, m, m22, mbot, mtop, nbmps, ndcol, ns, nu logical(lk) :: accum, bmp22 ! Intrinsic Functions ! Local Arrays real(${rk}$) :: vt(3_${ik}$) ! Executable Statements ! ==== if there are no shifts, then there is nothing to do. ==== if( nshfts<2 )return ! ==== if the active block is empty or 1-by-1, then there ! . is nothing to do. ==== if( ktop>=kbot )return ! ==== shuffle shifts into pairs of real shifts and pairs ! . of complex conjugate shifts assuming complex ! . conjugate shifts are already adjacent to one ! . another. ==== do i = 1, nshfts - 2, 2 if( si( i )/=-si( i+1 ) ) then swap = sr( i ) sr( i ) = sr( i+1 ) sr( i+1 ) = sr( i+2 ) sr( i+2 ) = swap swap = si( i ) si( i ) = si( i+1 ) si( i+1 ) = si( i+2 ) si( i+2 ) = swap end if end do ! ==== nshfts is supposed to be even, but if it is odd, ! . then simply reduce it by one. the shuffle above ! . ensures that the dropped shift is real and that ! . the remaining shifts are paired. ==== ns = nshfts - mod( nshfts, 2_${ik}$ ) ! ==== machine constants for deflation ==== safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_${ri}$labad( safmin, safmax ) ulp = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=${rk}$) / ulp ) ! ==== use accumulated reflections to update far-from-diagonal ! . entries ? ==== accum = ( kacc22==1_${ik}$ ) .or. ( kacc22==2_${ik}$ ) ! ==== clear trash ==== if( ktop+2<=kbot )h( ktop+2, ktop ) = zero ! ==== nbmps = number of 2-shift bulges in the chain ==== nbmps = ns / 2_${ik}$ ! ==== kdu = width of slab ==== kdu = 4_${ik}$*nbmps ! ==== create and chase chains of nbmps bulges ==== loop_180: do incol = ktop - 2*nbmps + 1, kbot - 2, 2*nbmps ! jtop = index from which updates from the right start. if( accum ) then jtop = max( ktop, incol ) else if( wantt ) then jtop = 1_${ik}$ else jtop = ktop end if ndcol = incol + kdu if( accum )call stdlib${ii}$_${ri}$laset( 'ALL', kdu, kdu, zero, one, u, ldu ) ! ==== near-the-diagonal bulge chase. the following loop ! . performs the near-the-diagonal part of a small bulge ! . multi-shift qr sweep. each 4*nbmps column diagonal ! . chunk extends from column incol to column ndcol ! . (including both column incol and column ndcol). the ! . following loop chases a 2*nbmps+1 column long chain of ! . nbmps bulges 2*nbmps columns to the right. (incol ! . may be less than ktop and and ndcol may be greater than ! . kbot indicating phantom columns from which to chase ! . bulges before they are actually introduced or to which ! . to chase bulges beyond column kbot.) ==== loop_145: do krcol = incol, min( incol+2*nbmps-1, kbot-2 ) ! ==== bulges number mtop to mbot are active double implicit ! . shift bulges. there may or may not also be small ! . 2-by-2 bulge, if there is room. the inactive bulges ! . (if any) must wait until the active bulges have moved ! . down the diagonal to make room. the phantom matrix ! . paradigm described above helps keep track. ==== mtop = max( 1_${ik}$, ( ktop-krcol ) / 2_${ik}$+1 ) mbot = min( nbmps, ( kbot-krcol-1 ) / 2_${ik}$ ) m22 = mbot + 1_${ik}$ bmp22 = ( mbot=ktop ) then if( h( k+1, k )/=zero ) then tst1 = abs( h( k, k ) ) + abs( h( k+1, k+1 ) ) if( tst1==zero ) then if( k>=ktop+1 )tst1 = tst1 + abs( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + abs( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + abs( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + abs( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + abs( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + abs( h( k+4, k+1 ) ) end if if( abs( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) ) then h12 = max( abs( h( k+1, k ) ),abs( h( k, k+1 ) ) ) h21 = min( abs( h( k+1, k ) ),abs( h( k, k+1 ) ) ) h11 = max( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) ) & then h( k+1, k ) = zero end if end if end if end if ! ==== accumulate orthogonal transformations. ==== if( accum ) then kms = k - incol do j = max( 1, ktop-incol ), kdu refsum = v( 1_${ik}$, m22 )*( u( j, kms+1 )+v( 2_${ik}$, m22 )*u( j, kms+2 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) - refsum*v( 2_${ik}$, m22 ) end do else if( wantz ) then do j = iloz, ihiz refsum = v( 1_${ik}$, m22 )*( z( j, k+1 )+v( 2_${ik}$, m22 )*z( j, k+2 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) - refsum*v( 2_${ik}$, m22 ) end do end if end if ! ==== normal case: chain of 3-by-3 reflections ==== loop_80: do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) if( k==ktop-1 ) then call stdlib${ii}$_${ri}$laqr1( 3_${ik}$, h( ktop, ktop ), ldh, sr( 2_${ik}$*m-1 ),si( 2_${ik}$*m-1 ), sr( & 2_${ik}$*m ), si( 2_${ik}$*m ),v( 1_${ik}$, m ) ) alpha = v( 1_${ik}$, m ) call stdlib${ii}$_${ri}$larfg( 3_${ik}$, alpha, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) else ! ==== perform delayed transformation of row below ! . mth bulge. exploit fact that first two elements ! . of row are actually zero. ==== refsum = v( 1_${ik}$, m )*v( 3_${ik}$, m )*h( k+3, k+2 ) h( k+3, k ) = -refsum h( k+3, k+1 ) = -refsum*v( 2_${ik}$, m ) h( k+3, k+2 ) = h( k+3, k+2 ) - refsum*v( 3_${ik}$, m ) ! ==== calculate reflection to move ! . mth bulge one step. ==== beta = h( k+1, k ) v( 2_${ik}$, m ) = h( k+2, k ) v( 3_${ik}$, m ) = h( k+3, k ) call stdlib${ii}$_${ri}$larfg( 3_${ik}$, beta, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) ! ==== a bulge may collapse because of vigilant ! . deflation or destructive underflow. in the ! . underflow case, try the two-small-subdiagonals ! . trick to try to reinflate the bulge. ==== if( h( k+3, k )/=zero .or. h( k+3, k+1 )/=zero .or. h( k+3, k+2 )==zero ) & then ! ==== typical case: not collapsed (yet). ==== h( k+1, k ) = beta h( k+2, k ) = zero h( k+3, k ) = zero else ! ==== atypical case: collapsed. attempt to ! . reintroduce ignoring h(k+1,k) and h(k+2,k). ! . if the fill resulting from the new ! . reflector is too large, then abandon it. ! . otherwise, use the new one. ==== call stdlib${ii}$_${ri}$laqr1( 3_${ik}$, h( k+1, k+1 ), ldh, sr( 2_${ik}$*m-1 ),si( 2_${ik}$*m-1 ), sr( & 2_${ik}$*m ), si( 2_${ik}$*m ),vt ) alpha = vt( 1_${ik}$ ) call stdlib${ii}$_${ri}$larfg( 3_${ik}$, alpha, vt( 2_${ik}$ ), 1_${ik}$, vt( 1_${ik}$ ) ) refsum = vt( 1_${ik}$ )*( h( k+1, k )+vt( 2_${ik}$ )*h( k+2, k ) ) if( abs( h( k+2, k )-refsum*vt( 2_${ik}$ ) )+abs( refsum*vt( 3_${ik}$ ) )>ulp*( abs( & h( k, k ) )+abs( h( k+1,k+1 ) )+abs( h( k+2, k+2 ) ) ) ) then ! ==== starting a new bulge here would ! . create non-negligible fill. use ! . the old one with trepidation. ==== h( k+1, k ) = beta h( k+2, k ) = zero h( k+3, k ) = zero else ! ==== starting a new bulge here would ! . create only negligible fill. ! . replace the old reflector with ! . the new one. ==== h( k+1, k ) = h( k+1, k ) - refsum h( k+2, k ) = zero h( k+3, k ) = zero v( 1_${ik}$, m ) = vt( 1_${ik}$ ) v( 2_${ik}$, m ) = vt( 2_${ik}$ ) v( 3_${ik}$, m ) = vt( 3_${ik}$ ) end if end if end if ! ==== apply reflection from the right and ! . the first column of update from the left. ! . these updates are required for the vigilant ! . deflation check. we still delay most of the ! . updates from the left for efficiency. ==== do j = jtop, min( kbot, k+3 ) refsum = v( 1_${ik}$, m )*( h( j, k+1 )+v( 2_${ik}$, m )*h( j, k+2 )+v( 3_${ik}$, m )*h( j, k+3 & ) ) h( j, k+1 ) = h( j, k+1 ) - refsum h( j, k+2 ) = h( j, k+2 ) - refsum*v( 2_${ik}$, m ) h( j, k+3 ) = h( j, k+3 ) - refsum*v( 3_${ik}$, m ) end do ! ==== perform update from left for subsequent ! . column. ==== refsum = v( 1_${ik}$, m )*( h( k+1, k+1 )+v( 2_${ik}$, m )*h( k+2, k+1 )+v( 3_${ik}$, m )*h( k+3, & k+1 ) ) h( k+1, k+1 ) = h( k+1, k+1 ) - refsum h( k+2, k+1 ) = h( k+2, k+1 ) - refsum*v( 2_${ik}$, m ) h( k+3, k+1 ) = h( k+3, k+1 ) - refsum*v( 3_${ik}$, m ) ! ==== the following convergence test requires that ! . the tradition small-compared-to-nearby-diagonals ! . criterion and the ahues ! . criteria both be satisfied. the latter improves ! . accuracy in some examples. falling back on an ! . alternate convergence criterion when tst1 or tst2 ! . is zero (as done here) is traditional but probably ! . unnecessary. ==== if( k=ktop+1 )tst1 = tst1 + abs( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + abs( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + abs( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + abs( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + abs( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + abs( h( k+4, k+1 ) ) end if if( abs( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) )then h12 = max( abs( h( k+1, k ) ), abs( h( k, k+1 ) ) ) h21 = min( abs( h( k+1, k ) ), abs( h( k, k+1 ) ) ) h11 = max( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( abs( h( k+1, k+1 ) ),abs( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) ) & then h( k+1, k ) = zero end if end if end if end do loop_80 ! ==== multiply h by reflections from the left ==== if( accum ) then jbot = min( ndcol, kbot ) else if( wantt ) then jbot = n else jbot = kbot end if do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = max( ktop, krcol + 2*m ), jbot refsum = v( 1_${ik}$, m )*( h( k+1, j )+v( 2_${ik}$, m )*h( k+2, j )+v( 3_${ik}$, m )*h( k+3, j & ) ) h( k+1, j ) = h( k+1, j ) - refsum h( k+2, j ) = h( k+2, j ) - refsum*v( 2_${ik}$, m ) h( k+3, j ) = h( k+3, j ) - refsum*v( 3_${ik}$, m ) end do end do ! ==== accumulate orthogonal transformations. ==== if( accum ) then ! ==== accumulate u. (if needed, update z later ! . with an efficient matrix-matrix ! . multiply.) ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) kms = k - incol i2 = max( 1_${ik}$, ktop-incol ) i2 = max( i2, kms-(krcol-incol)+1_${ik}$ ) i4 = min( kdu, krcol + 2_${ik}$*( mbot-1 ) - incol + 5_${ik}$ ) do j = i2, i4 refsum = v( 1_${ik}$, m )*( u( j, kms+1 )+v( 2_${ik}$, m )*u( j, kms+2 )+v( 3_${ik}$, m )*u( & j, kms+3 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) - refsum*v( 2_${ik}$, m ) u( j, kms+3 ) = u( j, kms+3 ) - refsum*v( 3_${ik}$, m ) end do end do else if( wantz ) then ! ==== u is not accumulated, so update z ! . now by multiplying by reflections ! . from the right. ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = iloz, ihiz refsum = v( 1_${ik}$, m )*( z( j, k+1 )+v( 2_${ik}$, m )*z( j, k+2 )+v( 3_${ik}$, m )*z( j, & k+3 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) - refsum*v( 2_${ik}$, m ) z( j, k+3 ) = z( j, k+3 ) - refsum*v( 3_${ik}$, m ) end do end do end if ! ==== end of near-the-diagonal bulge chase. ==== end do loop_145 ! ==== use u (if accumulated) to update far-from-diagonal ! . entries in h. if required, use u to update z as ! . well. ==== if( accum ) then if( wantt ) then jtop = 1_${ik}$ jbot = n else jtop = ktop jbot = kbot end if k1 = max( 1_${ik}$, ktop-incol ) nu = ( kdu-max( 0_${ik}$, ndcol-kbot ) ) - k1 + 1_${ik}$ ! ==== horizontal multiply ==== do jcol = min( ndcol, kbot ) + 1, jbot, nh jlen = min( nh, jbot-jcol+1 ) call stdlib${ii}$_${ri}$gemm( 'C', 'N', nu, jlen, nu, one, u( k1, k1 ),ldu, h( incol+k1, & jcol ), ldh, zero, wh,ldwh ) call stdlib${ii}$_${ri}$lacpy( 'ALL', nu, jlen, wh, ldwh,h( incol+k1, jcol ), ldh ) end do ! ==== vertical multiply ==== do jrow = jtop, max( ktop, incol ) - 1, nv jlen = min( nv, max( ktop, incol )-jrow ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', jlen, nu, nu, one,h( jrow, incol+k1 ), ldh, u( & k1, k1 ),ldu, zero, wv, ldwv ) call stdlib${ii}$_${ri}$lacpy( 'ALL', jlen, nu, wv, ldwv,h( jrow, incol+k1 ), ldh ) end do ! ==== z multiply (also vertical) ==== if( wantz ) then do jrow = iloz, ihiz, nv jlen = min( nv, ihiz-jrow+1 ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', jlen, nu, nu, one,z( jrow, incol+k1 ), ldz, u(& k1, k1 ),ldu, zero, wv, ldwv ) call stdlib${ii}$_${ri}$lacpy( 'ALL', jlen, nu, wv, ldwv,z( jrow, incol+k1 ), ldz ) end do end if end if end do loop_180 end subroutine stdlib${ii}$_${ri}$laqr5 #:endif #:endfor pure module subroutine stdlib${ii}$_claqr5( wantt, wantz, kacc22, n, ktop, kbot, nshfts, s,h, ldh, iloz, & !! CLAQR5 called by CLAQR0 performs a !! single small-bulge multi-shift QR sweep. ihiz, z, ldz, v, ldv, u, ldu, nv,wv, ldwv, nh, wh, ldwh ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kacc22, kbot, ktop, ldh, ldu, ldv, ldwh, ldwv, & ldz, n, nh, nshfts, nv logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(sp), intent(inout) :: h(ldh,*), s(*), z(ldz,*) complex(sp), intent(out) :: u(ldu,*), v(ldv,*), wh(ldwh,*), wv(ldwv,*) ! ================================================================ ! Parameters ! Local Scalars complex(sp) :: alpha, beta, cdum, refsum real(sp) :: h11, h12, h21, h22, safmax, safmin, scl, smlnum, tst1, tst2, ulp integer(${ik}$) :: i2, i4, incol, j, jbot, jcol, jlen, jrow, jtop, k, k1, kdu, kms, krcol,& m, m22, mbot, mtop, nbmps, ndcol, ns, nu logical(lk) :: accum, bmp22 ! Intrinsic Functions ! Local Arrays complex(sp) :: vt(3_${ik}$) ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements ! ==== if there are no shifts, then there is nothing to do. ==== if( nshfts<2 )return ! ==== if the active block is empty or 1-by-1, then there ! . is nothing to do. ==== if( ktop>=kbot )return ! ==== nshfts is supposed to be even, but if it is odd, ! . then simply reduce it by cone. ==== ns = nshfts - mod( nshfts, 2_${ik}$ ) ! ==== machine constants for deflation ==== safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=sp) / ulp ) ! ==== use accumulated reflections to update far-from-diagonal ! . entries ? ==== accum = ( kacc22==1_${ik}$ ) .or. ( kacc22==2_${ik}$ ) ! ==== clear trash ==== if( ktop+2<=kbot )h( ktop+2, ktop ) = czero ! ==== nbmps = number of 2-shift bulges in the chain ==== nbmps = ns / 2_${ik}$ ! ==== kdu = width of slab ==== kdu = 4_${ik}$*nbmps ! ==== create and chase chains of nbmps bulges ==== loop_180: do incol = ktop - 2*nbmps + 1, kbot - 2, 2*nbmps ! jtop = index from which updates from the right start. if( accum ) then jtop = max( ktop, incol ) else if( wantt ) then jtop = 1_${ik}$ else jtop = ktop end if ndcol = incol + kdu if( accum )call stdlib${ii}$_claset( 'ALL', kdu, kdu, czero, cone, u, ldu ) ! ==== near-the-diagonal bulge chase. the following loop ! . performs the near-the-diagonal part of a small bulge ! . multi-shift qr sweep. each 4*nbmps column diagonal ! . chunk extends from column incol to column ndcol ! . (including both column incol and column ndcol). the ! . following loop chases a 2*nbmps+1 column long chain of ! . nbmps bulges 2*nbmps columns to the right. (incol ! . may be less than ktop and and ndcol may be greater than ! . kbot indicating phantom columns from which to chase ! . bulges before they are actually introduced or to which ! . to chase bulges beyond column kbot.) ==== loop_145: do krcol = incol, min( incol+2*nbmps-1, kbot-2 ) ! ==== bulges number mtop to mbot are active double implicit ! . shift bulges. there may or may not also be small ! . 2-by-2 bulge, if there is room. the inactive bulges ! . (if any) must wait until the active bulges have moved ! . down the diagonal to make room. the phantom matrix ! . paradigm described above helps keep track. ==== mtop = max( 1_${ik}$, ( ktop-krcol ) / 2_${ik}$+1 ) mbot = min( nbmps, ( kbot-krcol-1 ) / 2_${ik}$ ) m22 = mbot + 1_${ik}$ bmp22 = ( mbot=ktop) then if( h( k+1, k )/=czero ) then tst1 = cabs1( h( k, k ) ) + cabs1( h( k+1, k+1 ) ) if( tst1==zero ) then if( k>=ktop+1 )tst1 = tst1 + cabs1( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + cabs1( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + cabs1( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + cabs1( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + cabs1( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + cabs1( h( k+4, k+1 ) ) end if if( cabs1( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) ) then h12 = max( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h21 = min( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h11 = max( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) )h( & k+1, k ) = czero end if end if end if ! ==== accumulate orthogonal transformations. ==== if( accum ) then kms = k - incol do j = max( 1, ktop-incol ), kdu refsum = v( 1_${ik}$, m22 )*( u( j, kms+1 )+v( 2_${ik}$, m22 )*u( j, kms+2 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) -refsum*conjg( v( 2_${ik}$, m22 ) ) end do else if( wantz ) then do j = iloz, ihiz refsum = v( 1_${ik}$, m22 )*( z( j, k+1 )+v( 2_${ik}$, m22 )*z( j, k+2 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) -refsum*conjg( v( 2_${ik}$, m22 ) ) end do end if end if ! ==== normal case: chain of 3-by-3 reflections ==== loop_80: do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) if( k==ktop-1 ) then call stdlib${ii}$_claqr1( 3_${ik}$, h( ktop, ktop ), ldh, s( 2_${ik}$*m-1 ),s( 2_${ik}$*m ), v( 1_${ik}$, m )& ) alpha = v( 1_${ik}$, m ) call stdlib${ii}$_clarfg( 3_${ik}$, alpha, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) else ! ==== perform delayed transformation of row below ! . mth bulge. exploit fact that first two elements ! . of row are actually czero. ==== refsum = v( 1_${ik}$, m )*v( 3_${ik}$, m )*h( k+3, k+2 ) h( k+3, k ) = -refsum h( k+3, k+1 ) = -refsum*conjg( v( 2_${ik}$, m ) ) h( k+3, k+2 ) = h( k+3, k+2 ) -refsum*conjg( v( 3_${ik}$, m ) ) ! ==== calculate reflection to move ! . mth bulge cone step. ==== beta = h( k+1, k ) v( 2_${ik}$, m ) = h( k+2, k ) v( 3_${ik}$, m ) = h( k+3, k ) call stdlib${ii}$_clarfg( 3_${ik}$, beta, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) ! ==== a bulge may collapse because of vigilant ! . deflation or destructive underflow. in the ! . underflow case, try the two-small-subdiagonals ! . trick to try to reinflate the bulge. ==== if( h( k+3, k )/=czero .or. h( k+3, k+1 )/=czero .or. h( k+3, k+2 )==czero & ) then ! ==== typical case: not collapsed (yet). ==== h( k+1, k ) = beta h( k+2, k ) = czero h( k+3, k ) = czero else ! ==== atypical case: collapsed. attempt to ! . reintroduce ignoring h(k+1,k) and h(k+2,k). ! . if the fill resulting from the new ! . reflector is too large, then abandon it. ! . otherwise, use the new cone. ==== call stdlib${ii}$_claqr1( 3_${ik}$, h( k+1, k+1 ), ldh, s( 2_${ik}$*m-1 ),s( 2_${ik}$*m ), vt ) alpha = vt( 1_${ik}$ ) call stdlib${ii}$_clarfg( 3_${ik}$, alpha, vt( 2_${ik}$ ), 1_${ik}$, vt( 1_${ik}$ ) ) refsum = conjg( vt( 1_${ik}$ ) )*( h( k+1, k )+conjg( vt( 2_${ik}$ ) )*h( k+2, k ) ) if( cabs1( h( k+2, k )-refsum*vt( 2_${ik}$ ) )+cabs1( refsum*vt( 3_${ik}$ ) )>ulp*( & cabs1( h( k, k ) )+cabs1( h( k+1,k+1 ) )+cabs1( h( k+2, k+2 ) ) ) ) & then ! ==== starting a new bulge here would ! . create non-negligible fill. use ! . the old cone with trepidation. ==== h( k+1, k ) = beta h( k+2, k ) = czero h( k+3, k ) = czero else ! ==== starting a new bulge here would ! . create only negligible fill. ! . replace the old reflector with ! . the new cone. ==== h( k+1, k ) = h( k+1, k ) - refsum h( k+2, k ) = czero h( k+3, k ) = czero v( 1_${ik}$, m ) = vt( 1_${ik}$ ) v( 2_${ik}$, m ) = vt( 2_${ik}$ ) v( 3_${ik}$, m ) = vt( 3_${ik}$ ) end if end if end if ! ==== apply reflection from the right and ! . the first column of update from the left. ! . these updates are required for the vigilant ! . deflation check. we still delay most of the ! . updates from the left for efficiency. ==== do j = jtop, min( kbot, k+3 ) refsum = v( 1_${ik}$, m )*( h( j, k+1 )+v( 2_${ik}$, m )*h( j, k+2 )+v( 3_${ik}$, m )*h( j, k+3 & ) ) h( j, k+1 ) = h( j, k+1 ) - refsum h( j, k+2 ) = h( j, k+2 ) -refsum*conjg( v( 2_${ik}$, m ) ) h( j, k+3 ) = h( j, k+3 ) -refsum*conjg( v( 3_${ik}$, m ) ) end do ! ==== perform update from left for subsequent ! . column. ==== refsum = conjg( v( 1_${ik}$, m ) )*( h( k+1, k+1 )+conjg( v( 2_${ik}$, m ) )*h( k+2, k+1 )+& conjg( v( 3_${ik}$, m ) )*h( k+3, k+1 ) ) h( k+1, k+1 ) = h( k+1, k+1 ) - refsum h( k+2, k+1 ) = h( k+2, k+1 ) - refsum*v( 2_${ik}$, m ) h( k+3, k+1 ) = h( k+3, k+1 ) - refsum*v( 3_${ik}$, m ) ! ==== the following convergence test requires that ! . the tradition small-compared-to-nearby-diagonals ! . criterion and the ahues ! . criteria both be satisfied. the latter improves ! . accuracy in some examples. falling back on an ! . alternate convergence criterion when tst1 or tst2 ! . is czero (as done here) is traditional but probably ! . unnecessary. ==== if( k=ktop+1 )tst1 = tst1 + cabs1( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + cabs1( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + cabs1( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + cabs1( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + cabs1( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + cabs1( h( k+4, k+1 ) ) end if if( cabs1( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) )then h12 = max( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h21 = min( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h11 = max( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) )h( k+1,& k ) = czero end if end if end do loop_80 ! ==== multiply h by reflections from the left ==== if( accum ) then jbot = min( ndcol, kbot ) else if( wantt ) then jbot = n else jbot = kbot end if do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = max( ktop, krcol + 2*m ), jbot refsum = conjg( v( 1_${ik}$, m ) )*( h( k+1, j )+conjg( v( 2_${ik}$, m ) )*h( k+2, j )+& conjg( v( 3_${ik}$, m ) )*h( k+3, j ) ) h( k+1, j ) = h( k+1, j ) - refsum h( k+2, j ) = h( k+2, j ) - refsum*v( 2_${ik}$, m ) h( k+3, j ) = h( k+3, j ) - refsum*v( 3_${ik}$, m ) end do end do ! ==== accumulate orthogonal transformations. ==== if( accum ) then ! ==== accumulate u. (if needed, update z later ! . with an efficient matrix-matrix ! . multiply.) ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) kms = k - incol i2 = max( 1_${ik}$, ktop-incol ) i2 = max( i2, kms-(krcol-incol)+1_${ik}$ ) i4 = min( kdu, krcol + 2_${ik}$*( mbot-1 ) - incol + 5_${ik}$ ) do j = i2, i4 refsum = v( 1_${ik}$, m )*( u( j, kms+1 )+v( 2_${ik}$, m )*u( j, kms+2 )+v( 3_${ik}$, m )*u( & j, kms+3 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) -refsum*conjg( v( 2_${ik}$, m ) ) u( j, kms+3 ) = u( j, kms+3 ) -refsum*conjg( v( 3_${ik}$, m ) ) end do end do else if( wantz ) then ! ==== u is not accumulated, so update z ! . now by multiplying by reflections ! . from the right. ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = iloz, ihiz refsum = v( 1_${ik}$, m )*( z( j, k+1 )+v( 2_${ik}$, m )*z( j, k+2 )+v( 3_${ik}$, m )*z( j, & k+3 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) -refsum*conjg( v( 2_${ik}$, m ) ) z( j, k+3 ) = z( j, k+3 ) -refsum*conjg( v( 3_${ik}$, m ) ) end do end do end if ! ==== end of near-the-diagonal bulge chase. ==== end do loop_145 ! ==== use u (if accumulated) to update far-from-diagonal ! . entries in h. if required, use u to update z as ! . well. ==== if( accum ) then if( wantt ) then jtop = 1_${ik}$ jbot = n else jtop = ktop jbot = kbot end if k1 = max( 1_${ik}$, ktop-incol ) nu = ( kdu-max( 0_${ik}$, ndcol-kbot ) ) - k1 + 1_${ik}$ ! ==== horizontal multiply ==== do jcol = min( ndcol, kbot ) + 1, jbot, nh jlen = min( nh, jbot-jcol+1 ) call stdlib${ii}$_cgemm( 'C', 'N', nu, jlen, nu, cone, u( k1, k1 ),ldu, h( incol+k1,& jcol ), ldh, czero, wh,ldwh ) call stdlib${ii}$_clacpy( 'ALL', nu, jlen, wh, ldwh,h( incol+k1, jcol ), ldh ) end do ! ==== vertical multiply ==== do jrow = jtop, max( ktop, incol ) - 1, nv jlen = min( nv, max( ktop, incol )-jrow ) call stdlib${ii}$_cgemm( 'N', 'N', jlen, nu, nu, cone,h( jrow, incol+k1 ), ldh, u( & k1, k1 ),ldu, czero, wv, ldwv ) call stdlib${ii}$_clacpy( 'ALL', jlen, nu, wv, ldwv,h( jrow, incol+k1 ), ldh ) end do ! ==== z multiply (also vertical) ==== if( wantz ) then do jrow = iloz, ihiz, nv jlen = min( nv, ihiz-jrow+1 ) call stdlib${ii}$_cgemm( 'N', 'N', jlen, nu, nu, cone,z( jrow, incol+k1 ), ldz, & u( k1, k1 ),ldu, czero, wv, ldwv ) call stdlib${ii}$_clacpy( 'ALL', jlen, nu, wv, ldwv,z( jrow, incol+k1 ), ldz ) end do end if end if end do loop_180 end subroutine stdlib${ii}$_claqr5 pure module subroutine stdlib${ii}$_zlaqr5( wantt, wantz, kacc22, n, ktop, kbot, nshfts, s,h, ldh, iloz, & !! ZLAQR5 , called by ZLAQR0, performs a !! single small-bulge multi-shift QR sweep. ihiz, z, ldz, v, ldv, u, ldu, nv,wv, ldwv, nh, wh, ldwh ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kacc22, kbot, ktop, ldh, ldu, ldv, ldwh, ldwv, & ldz, n, nh, nshfts, nv logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(dp), intent(inout) :: h(ldh,*), s(*), z(ldz,*) complex(dp), intent(out) :: u(ldu,*), v(ldv,*), wh(ldwh,*), wv(ldwv,*) ! ================================================================ ! Parameters ! Local Scalars complex(dp) :: alpha, beta, cdum, refsum real(dp) :: h11, h12, h21, h22, safmax, safmin, scl, smlnum, tst1, tst2, ulp integer(${ik}$) :: i2, i4, incol, j, jbot, jcol, jlen, jrow, jtop, k, k1, kdu, kms, krcol,& m, m22, mbot, mtop, nbmps, ndcol, ns, nu logical(lk) :: accum, bmp22 ! Intrinsic Functions ! Local Arrays complex(dp) :: vt(3_${ik}$) ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements ! ==== if there are no shifts, then there is nothing to do. ==== if( nshfts<2 )return ! ==== if the active block is empty or 1-by-1, then there ! . is nothing to do. ==== if( ktop>=kbot )return ! ==== nshfts is supposed to be even, but if it is odd, ! . then simply reduce it by cone. ==== ns = nshfts - mod( nshfts, 2_${ik}$ ) ! ==== machine constants for deflation ==== safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=dp) / ulp ) ! ==== use accumulated reflections to update far-from-diagonal ! . entries ? ==== accum = ( kacc22==1_${ik}$ ) .or. ( kacc22==2_${ik}$ ) ! ==== clear trash ==== if( ktop+2<=kbot )h( ktop+2, ktop ) = czero ! ==== nbmps = number of 2-shift bulges in the chain ==== nbmps = ns / 2_${ik}$ ! ==== kdu = width of slab ==== kdu = 4_${ik}$*nbmps ! ==== create and chase chains of nbmps bulges ==== loop_180: do incol = ktop - 2*nbmps + 1, kbot - 2, 2*nbmps ! jtop = index from which updates from the right start. if( accum ) then jtop = max( ktop, incol ) else if( wantt ) then jtop = 1_${ik}$ else jtop = ktop end if ndcol = incol + kdu if( accum )call stdlib${ii}$_zlaset( 'ALL', kdu, kdu, czero, cone, u, ldu ) ! ==== near-the-diagonal bulge chase. the following loop ! . performs the near-the-diagonal part of a small bulge ! . multi-shift qr sweep. each 4*nbmps column diagonal ! . chunk extends from column incol to column ndcol ! . (including both column incol and column ndcol). the ! . following loop chases a 2*nbmps+1 column long chain of ! . nbmps bulges 2*nbmps columns to the right. (incol ! . may be less than ktop and and ndcol may be greater than ! . kbot indicating phantom columns from which to chase ! . bulges before they are actually introduced or to which ! . to chase bulges beyond column kbot.) ==== loop_145: do krcol = incol, min( incol+2*nbmps-1, kbot-2 ) ! ==== bulges number mtop to mbot are active double implicit ! . shift bulges. there may or may not also be small ! . 2-by-2 bulge, if there is room. the inactive bulges ! . (if any) must wait until the active bulges have moved ! . down the diagonal to make room. the phantom matrix ! . paradigm described above helps keep track. ==== mtop = max( 1_${ik}$, ( ktop-krcol ) / 2_${ik}$+1 ) mbot = min( nbmps, ( kbot-krcol-1 ) / 2_${ik}$ ) m22 = mbot + 1_${ik}$ bmp22 = ( mbot=ktop ) then if( h( k+1, k )/=czero ) then tst1 = cabs1( h( k, k ) ) + cabs1( h( k+1, k+1 ) ) if( tst1==zero ) then if( k>=ktop+1 )tst1 = tst1 + cabs1( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + cabs1( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + cabs1( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + cabs1( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + cabs1( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + cabs1( h( k+4, k+1 ) ) end if if( cabs1( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) ) then h12 = max( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h21 = min( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h11 = max( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) )h( & k+1, k ) = czero end if end if end if ! ==== accumulate orthogonal transformations. ==== if( accum ) then kms = k - incol do j = max( 1, ktop-incol ), kdu refsum = v( 1_${ik}$, m22 )*( u( j, kms+1 )+v( 2_${ik}$, m22 )*u( j, kms+2 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) -refsum*conjg( v( 2_${ik}$, m22 ) ) end do else if( wantz ) then do j = iloz, ihiz refsum = v( 1_${ik}$, m22 )*( z( j, k+1 )+v( 2_${ik}$, m22 )*z( j, k+2 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) -refsum*conjg( v( 2_${ik}$, m22 ) ) end do end if end if ! ==== normal case: chain of 3-by-3 reflections ==== loop_80: do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) if( k==ktop-1 ) then call stdlib${ii}$_zlaqr1( 3_${ik}$, h( ktop, ktop ), ldh, s( 2_${ik}$*m-1 ),s( 2_${ik}$*m ), v( 1_${ik}$, m )& ) alpha = v( 1_${ik}$, m ) call stdlib${ii}$_zlarfg( 3_${ik}$, alpha, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) else ! ==== perform delayed transformation of row below ! . mth bulge. exploit fact that first two elements ! . of row are actually czero. ==== refsum = v( 1_${ik}$, m )*v( 3_${ik}$, m )*h( k+3, k+2 ) h( k+3, k ) = -refsum h( k+3, k+1 ) = -refsum*conjg( v( 2_${ik}$, m ) ) h( k+3, k+2 ) = h( k+3, k+2 ) -refsum*conjg( v( 3_${ik}$, m ) ) ! ==== calculate reflection to move ! . mth bulge cone step. ==== beta = h( k+1, k ) v( 2_${ik}$, m ) = h( k+2, k ) v( 3_${ik}$, m ) = h( k+3, k ) call stdlib${ii}$_zlarfg( 3_${ik}$, beta, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) ! ==== a bulge may collapse because of vigilant ! . deflation or destructive underflow. in the ! . underflow case, try the two-small-subdiagonals ! . trick to try to reinflate the bulge. ==== if( h( k+3, k )/=czero .or. h( k+3, k+1 )/=czero .or. h( k+3, k+2 )==czero & ) then ! ==== typical case: not collapsed (yet). ==== h( k+1, k ) = beta h( k+2, k ) = czero h( k+3, k ) = czero else ! ==== atypical case: collapsed. attempt to ! . reintroduce ignoring h(k+1,k) and h(k+2,k). ! . if the fill resulting from the new ! . reflector is too large, then abandon it. ! . otherwise, use the new cone. ==== call stdlib${ii}$_zlaqr1( 3_${ik}$, h( k+1, k+1 ), ldh, s( 2_${ik}$*m-1 ),s( 2_${ik}$*m ), vt ) alpha = vt( 1_${ik}$ ) call stdlib${ii}$_zlarfg( 3_${ik}$, alpha, vt( 2_${ik}$ ), 1_${ik}$, vt( 1_${ik}$ ) ) refsum = conjg( vt( 1_${ik}$ ) )*( h( k+1, k )+conjg( vt( 2_${ik}$ ) )*h( k+2, k ) ) if( cabs1( h( k+2, k )-refsum*vt( 2_${ik}$ ) )+cabs1( refsum*vt( 3_${ik}$ ) )>ulp*( & cabs1( h( k, k ) )+cabs1( h( k+1,k+1 ) )+cabs1( h( k+2, k+2 ) ) ) ) & then ! ==== starting a new bulge here would ! . create non-negligible fill. use ! . the old cone with trepidation. ==== h( k+1, k ) = beta h( k+2, k ) = czero h( k+3, k ) = czero else ! ==== starting a new bulge here would ! . create only negligible fill. ! . replace the old reflector with ! . the new cone. ==== h( k+1, k ) = h( k+1, k ) - refsum h( k+2, k ) = czero h( k+3, k ) = czero v( 1_${ik}$, m ) = vt( 1_${ik}$ ) v( 2_${ik}$, m ) = vt( 2_${ik}$ ) v( 3_${ik}$, m ) = vt( 3_${ik}$ ) end if end if end if ! ==== apply reflection from the right and ! . the first column of update from the left. ! . these updates are required for the vigilant ! . deflation check. we still delay most of the ! . updates from the left for efficiency. ==== do j = jtop, min( kbot, k+3 ) refsum = v( 1_${ik}$, m )*( h( j, k+1 )+v( 2_${ik}$, m )*h( j, k+2 )+v( 3_${ik}$, m )*h( j, k+3 & ) ) h( j, k+1 ) = h( j, k+1 ) - refsum h( j, k+2 ) = h( j, k+2 ) -refsum*conjg( v( 2_${ik}$, m ) ) h( j, k+3 ) = h( j, k+3 ) -refsum*conjg( v( 3_${ik}$, m ) ) end do ! ==== perform update from left for subsequent ! . column. ==== refsum = conjg( v( 1_${ik}$, m ) )*( h( k+1, k+1 )+conjg( v( 2_${ik}$, m ) )*h( k+2, k+1 )+& conjg( v( 3_${ik}$, m ) )*h( k+3, k+1 ) ) h( k+1, k+1 ) = h( k+1, k+1 ) - refsum h( k+2, k+1 ) = h( k+2, k+1 ) - refsum*v( 2_${ik}$, m ) h( k+3, k+1 ) = h( k+3, k+1 ) - refsum*v( 3_${ik}$, m ) ! ==== the following convergence test requires that ! . the tradition small-compared-to-nearby-diagonals ! . criterion and the ahues ! . criteria both be satisfied. the latter improves ! . accuracy in some examples. falling back on an ! . alternate convergence criterion when tst1 or tst2 ! . is czero (as done here) is traditional but probably ! . unnecessary. ==== if( k=ktop+1 )tst1 = tst1 + cabs1( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + cabs1( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + cabs1( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + cabs1( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + cabs1( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + cabs1( h( k+4, k+1 ) ) end if if( cabs1( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) )then h12 = max( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h21 = min( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h11 = max( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) )h( k+1,& k ) = czero end if end if end do loop_80 ! ==== multiply h by reflections from the left ==== if( accum ) then jbot = min( ndcol, kbot ) else if( wantt ) then jbot = n else jbot = kbot end if do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = max( ktop, krcol + 2*m ), jbot refsum = conjg( v( 1_${ik}$, m ) )*( h( k+1, j )+conjg( v( 2_${ik}$, m ) )*h( k+2, j )+& conjg( v( 3_${ik}$, m ) )*h( k+3, j ) ) h( k+1, j ) = h( k+1, j ) - refsum h( k+2, j ) = h( k+2, j ) - refsum*v( 2_${ik}$, m ) h( k+3, j ) = h( k+3, j ) - refsum*v( 3_${ik}$, m ) end do end do ! ==== accumulate orthogonal transformations. ==== if( accum ) then ! ==== accumulate u. (if needed, update z later ! . with an efficient matrix-matrix ! . multiply.) ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) kms = k - incol i2 = max( 1_${ik}$, ktop-incol ) i2 = max( i2, kms-(krcol-incol)+1_${ik}$ ) i4 = min( kdu, krcol + 2_${ik}$*( mbot-1 ) - incol + 5_${ik}$ ) do j = i2, i4 refsum = v( 1_${ik}$, m )*( u( j, kms+1 )+v( 2_${ik}$, m )*u( j, kms+2 )+v( 3_${ik}$, m )*u( & j, kms+3 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) -refsum*conjg( v( 2_${ik}$, m ) ) u( j, kms+3 ) = u( j, kms+3 ) -refsum*conjg( v( 3_${ik}$, m ) ) end do end do else if( wantz ) then ! ==== u is not accumulated, so update z ! . now by multiplying by reflections ! . from the right. ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = iloz, ihiz refsum = v( 1_${ik}$, m )*( z( j, k+1 )+v( 2_${ik}$, m )*z( j, k+2 )+v( 3_${ik}$, m )*z( j, & k+3 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) -refsum*conjg( v( 2_${ik}$, m ) ) z( j, k+3 ) = z( j, k+3 ) -refsum*conjg( v( 3_${ik}$, m ) ) end do end do end if ! ==== end of near-the-diagonal bulge chase. ==== end do loop_145 ! ==== use u (if accumulated) to update far-from-diagonal ! . entries in h. if required, use u to update z as ! . well. ==== if( accum ) then if( wantt ) then jtop = 1_${ik}$ jbot = n else jtop = ktop jbot = kbot end if k1 = max( 1_${ik}$, ktop-incol ) nu = ( kdu-max( 0_${ik}$, ndcol-kbot ) ) - k1 + 1_${ik}$ ! ==== horizontal multiply ==== do jcol = min( ndcol, kbot ) + 1, jbot, nh jlen = min( nh, jbot-jcol+1 ) call stdlib${ii}$_zgemm( 'C', 'N', nu, jlen, nu, cone, u( k1, k1 ),ldu, h( incol+k1,& jcol ), ldh, czero, wh,ldwh ) call stdlib${ii}$_zlacpy( 'ALL', nu, jlen, wh, ldwh,h( incol+k1, jcol ), ldh ) end do ! ==== vertical multiply ==== do jrow = jtop, max( ktop, incol ) - 1, nv jlen = min( nv, max( ktop, incol )-jrow ) call stdlib${ii}$_zgemm( 'N', 'N', jlen, nu, nu, cone,h( jrow, incol+k1 ), ldh, u( & k1, k1 ),ldu, czero, wv, ldwv ) call stdlib${ii}$_zlacpy( 'ALL', jlen, nu, wv, ldwv,h( jrow, incol+k1 ), ldh ) end do ! ==== z multiply (also vertical) ==== if( wantz ) then do jrow = iloz, ihiz, nv jlen = min( nv, ihiz-jrow+1 ) call stdlib${ii}$_zgemm( 'N', 'N', jlen, nu, nu, cone,z( jrow, incol+k1 ), ldz, & u( k1, k1 ),ldu, czero, wv, ldwv ) call stdlib${ii}$_zlacpy( 'ALL', jlen, nu, wv, ldwv,z( jrow, incol+k1 ), ldz ) end do end if end if end do loop_180 end subroutine stdlib${ii}$_zlaqr5 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqr5( wantt, wantz, kacc22, n, ktop, kbot, nshfts, s,h, ldh, iloz, & !! ZLAQR5:, called by ZLAQR0, performs a !! single small-bulge multi-shift QR sweep. ihiz, z, ldz, v, ldv, u, ldu, nv,wv, ldwv, nh, wh, ldwh ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihiz, iloz, kacc22, kbot, ktop, ldh, ldu, ldv, ldwh, ldwv, & ldz, n, nh, nshfts, nv logical(lk), intent(in) :: wantt, wantz ! Array Arguments complex(${ck}$), intent(inout) :: h(ldh,*), s(*), z(ldz,*) complex(${ck}$), intent(out) :: u(ldu,*), v(ldv,*), wh(ldwh,*), wv(ldwv,*) ! ================================================================ ! Parameters ! Local Scalars complex(${ck}$) :: alpha, beta, cdum, refsum real(${ck}$) :: h11, h12, h21, h22, safmax, safmin, scl, smlnum, tst1, tst2, ulp integer(${ik}$) :: i2, i4, incol, j, jbot, jcol, jlen, jrow, jtop, k, k1, kdu, kms, krcol,& m, m22, mbot, mtop, nbmps, ndcol, ns, nu logical(lk) :: accum, bmp22 ! Intrinsic Functions ! Local Arrays complex(${ck}$) :: vt(3_${ik}$) ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements ! ==== if there are no shifts, then there is nothing to do. ==== if( nshfts<2 )return ! ==== if the active block is empty or 1-by-1, then there ! . is nothing to do. ==== if( ktop>=kbot )return ! ==== nshfts is supposed to be even, but if it is odd, ! . then simply reduce it by cone. ==== ns = nshfts - mod( nshfts, 2_${ik}$ ) ! ==== machine constants for deflation ==== safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safmax = one / safmin call stdlib${ii}$_${c2ri(ci)}$labad( safmin, safmax ) ulp = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=${ck}$) / ulp ) ! ==== use accumulated reflections to update far-from-diagonal ! . entries ? ==== accum = ( kacc22==1_${ik}$ ) .or. ( kacc22==2_${ik}$ ) ! ==== clear trash ==== if( ktop+2<=kbot )h( ktop+2, ktop ) = czero ! ==== nbmps = number of 2-shift bulges in the chain ==== nbmps = ns / 2_${ik}$ ! ==== kdu = width of slab ==== kdu = 4_${ik}$*nbmps ! ==== create and chase chains of nbmps bulges ==== loop_180: do incol = ktop - 2*nbmps + 1, kbot - 2, 2*nbmps ! jtop = index from which updates from the right start. if( accum ) then jtop = max( ktop, incol ) else if( wantt ) then jtop = 1_${ik}$ else jtop = ktop end if ndcol = incol + kdu if( accum )call stdlib${ii}$_${ci}$laset( 'ALL', kdu, kdu, czero, cone, u, ldu ) ! ==== near-the-diagonal bulge chase. the following loop ! . performs the near-the-diagonal part of a small bulge ! . multi-shift qr sweep. each 4*nbmps column diagonal ! . chunk extends from column incol to column ndcol ! . (including both column incol and column ndcol). the ! . following loop chases a 2*nbmps+1 column long chain of ! . nbmps bulges 2*nbmps columns to the right. (incol ! . may be less than ktop and and ndcol may be greater than ! . kbot indicating phantom columns from which to chase ! . bulges before they are actually introduced or to which ! . to chase bulges beyond column kbot.) ==== loop_145: do krcol = incol, min( incol+2*nbmps-1, kbot-2 ) ! ==== bulges number mtop to mbot are active double implicit ! . shift bulges. there may or may not also be small ! . 2-by-2 bulge, if there is room. the inactive bulges ! . (if any) must wait until the active bulges have moved ! . down the diagonal to make room. the phantom matrix ! . paradigm described above helps keep track. ==== mtop = max( 1_${ik}$, ( ktop-krcol ) / 2_${ik}$+1 ) mbot = min( nbmps, ( kbot-krcol-1 ) / 2_${ik}$ ) m22 = mbot + 1_${ik}$ bmp22 = ( mbot=ktop ) then if( h( k+1, k )/=czero ) then tst1 = cabs1( h( k, k ) ) + cabs1( h( k+1, k+1 ) ) if( tst1==zero ) then if( k>=ktop+1 )tst1 = tst1 + cabs1( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + cabs1( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + cabs1( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + cabs1( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + cabs1( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + cabs1( h( k+4, k+1 ) ) end if if( cabs1( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) ) then h12 = max( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h21 = min( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h11 = max( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) )h( & k+1, k ) = czero end if end if end if ! ==== accumulate orthogonal transformations. ==== if( accum ) then kms = k - incol do j = max( 1, ktop-incol ), kdu refsum = v( 1_${ik}$, m22 )*( u( j, kms+1 )+v( 2_${ik}$, m22 )*u( j, kms+2 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) -refsum*conjg( v( 2_${ik}$, m22 ) ) end do else if( wantz ) then do j = iloz, ihiz refsum = v( 1_${ik}$, m22 )*( z( j, k+1 )+v( 2_${ik}$, m22 )*z( j, k+2 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) -refsum*conjg( v( 2_${ik}$, m22 ) ) end do end if end if ! ==== normal case: chain of 3-by-3 reflections ==== loop_80: do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) if( k==ktop-1 ) then call stdlib${ii}$_${ci}$laqr1( 3_${ik}$, h( ktop, ktop ), ldh, s( 2_${ik}$*m-1 ),s( 2_${ik}$*m ), v( 1_${ik}$, m )& ) alpha = v( 1_${ik}$, m ) call stdlib${ii}$_${ci}$larfg( 3_${ik}$, alpha, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) else ! ==== perform delayed transformation of row below ! . mth bulge. exploit fact that first two elements ! . of row are actually czero. ==== refsum = v( 1_${ik}$, m )*v( 3_${ik}$, m )*h( k+3, k+2 ) h( k+3, k ) = -refsum h( k+3, k+1 ) = -refsum*conjg( v( 2_${ik}$, m ) ) h( k+3, k+2 ) = h( k+3, k+2 ) -refsum*conjg( v( 3_${ik}$, m ) ) ! ==== calculate reflection to move ! . mth bulge cone step. ==== beta = h( k+1, k ) v( 2_${ik}$, m ) = h( k+2, k ) v( 3_${ik}$, m ) = h( k+3, k ) call stdlib${ii}$_${ci}$larfg( 3_${ik}$, beta, v( 2_${ik}$, m ), 1_${ik}$, v( 1_${ik}$, m ) ) ! ==== a bulge may collapse because of vigilant ! . deflation or destructive underflow. in the ! . underflow case, try the two-small-subdiagonals ! . trick to try to reinflate the bulge. ==== if( h( k+3, k )/=czero .or. h( k+3, k+1 )/=czero .or. h( k+3, k+2 )==czero & ) then ! ==== typical case: not collapsed (yet). ==== h( k+1, k ) = beta h( k+2, k ) = czero h( k+3, k ) = czero else ! ==== atypical case: collapsed. attempt to ! . reintroduce ignoring h(k+1,k) and h(k+2,k). ! . if the fill resulting from the new ! . reflector is too large, then abandon it. ! . otherwise, use the new cone. ==== call stdlib${ii}$_${ci}$laqr1( 3_${ik}$, h( k+1, k+1 ), ldh, s( 2_${ik}$*m-1 ),s( 2_${ik}$*m ), vt ) alpha = vt( 1_${ik}$ ) call stdlib${ii}$_${ci}$larfg( 3_${ik}$, alpha, vt( 2_${ik}$ ), 1_${ik}$, vt( 1_${ik}$ ) ) refsum = conjg( vt( 1_${ik}$ ) )*( h( k+1, k )+conjg( vt( 2_${ik}$ ) )*h( k+2, k ) ) if( cabs1( h( k+2, k )-refsum*vt( 2_${ik}$ ) )+cabs1( refsum*vt( 3_${ik}$ ) )>ulp*( & cabs1( h( k, k ) )+cabs1( h( k+1,k+1 ) )+cabs1( h( k+2, k+2 ) ) ) ) & then ! ==== starting a new bulge here would ! . create non-negligible fill. use ! . the old cone with trepidation. ==== h( k+1, k ) = beta h( k+2, k ) = czero h( k+3, k ) = czero else ! ==== starting a new bulge here would ! . create only negligible fill. ! . replace the old reflector with ! . the new cone. ==== h( k+1, k ) = h( k+1, k ) - refsum h( k+2, k ) = czero h( k+3, k ) = czero v( 1_${ik}$, m ) = vt( 1_${ik}$ ) v( 2_${ik}$, m ) = vt( 2_${ik}$ ) v( 3_${ik}$, m ) = vt( 3_${ik}$ ) end if end if end if ! ==== apply reflection from the right and ! . the first column of update from the left. ! . these updates are required for the vigilant ! . deflation check. we still delay most of the ! . updates from the left for efficiency. ==== do j = jtop, min( kbot, k+3 ) refsum = v( 1_${ik}$, m )*( h( j, k+1 )+v( 2_${ik}$, m )*h( j, k+2 )+v( 3_${ik}$, m )*h( j, k+3 & ) ) h( j, k+1 ) = h( j, k+1 ) - refsum h( j, k+2 ) = h( j, k+2 ) -refsum*conjg( v( 2_${ik}$, m ) ) h( j, k+3 ) = h( j, k+3 ) -refsum*conjg( v( 3_${ik}$, m ) ) end do ! ==== perform update from left for subsequent ! . column. ==== refsum = conjg( v( 1_${ik}$, m ) )*( h( k+1, k+1 )+conjg( v( 2_${ik}$, m ) )*h( k+2, k+1 )+& conjg( v( 3_${ik}$, m ) )*h( k+3, k+1 ) ) h( k+1, k+1 ) = h( k+1, k+1 ) - refsum h( k+2, k+1 ) = h( k+2, k+1 ) - refsum*v( 2_${ik}$, m ) h( k+3, k+1 ) = h( k+3, k+1 ) - refsum*v( 3_${ik}$, m ) ! ==== the following convergence test requires that ! . the tradition small-compared-to-nearby-diagonals ! . criterion and the ahues ! . criteria both be satisfied. the latter improves ! . accuracy in some examples. falling back on an ! . alternate convergence criterion when tst1 or tst2 ! . is czero (as done here) is traditional but probably ! . unnecessary. ==== if( k=ktop+1 )tst1 = tst1 + cabs1( h( k, k-1 ) ) if( k>=ktop+2 )tst1 = tst1 + cabs1( h( k, k-2 ) ) if( k>=ktop+3 )tst1 = tst1 + cabs1( h( k, k-3 ) ) if( k<=kbot-2 )tst1 = tst1 + cabs1( h( k+2, k+1 ) ) if( k<=kbot-3 )tst1 = tst1 + cabs1( h( k+3, k+1 ) ) if( k<=kbot-4 )tst1 = tst1 + cabs1( h( k+4, k+1 ) ) end if if( cabs1( h( k+1, k ) )<=max( smlnum, ulp*tst1 ) )then h12 = max( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h21 = min( cabs1( h( k+1, k ) ),cabs1( h( k, k+1 ) ) ) h11 = max( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) h22 = min( cabs1( h( k+1, k+1 ) ),cabs1( h( k, k )-h( k+1, k+1 ) ) ) scl = h11 + h12 tst2 = h22*( h11 / scl ) if( tst2==zero .or. h21*( h12 / scl )<=max( smlnum, ulp*tst2 ) )h( k+1,& k ) = czero end if end if end do loop_80 ! ==== multiply h by reflections from the left ==== if( accum ) then jbot = min( ndcol, kbot ) else if( wantt ) then jbot = n else jbot = kbot end if do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = max( ktop, krcol + 2*m ), jbot refsum = conjg( v( 1_${ik}$, m ) )*( h( k+1, j )+conjg( v( 2_${ik}$, m ) )*h( k+2, j )+& conjg( v( 3_${ik}$, m ) )*h( k+3, j ) ) h( k+1, j ) = h( k+1, j ) - refsum h( k+2, j ) = h( k+2, j ) - refsum*v( 2_${ik}$, m ) h( k+3, j ) = h( k+3, j ) - refsum*v( 3_${ik}$, m ) end do end do ! ==== accumulate orthogonal transformations. ==== if( accum ) then ! ==== accumulate u. (if needed, update z later ! . with an efficient matrix-matrix ! . multiply.) ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) kms = k - incol i2 = max( 1_${ik}$, ktop-incol ) i2 = max( i2, kms-(krcol-incol)+1_${ik}$ ) i4 = min( kdu, krcol + 2_${ik}$*( mbot-1 ) - incol + 5_${ik}$ ) do j = i2, i4 refsum = v( 1_${ik}$, m )*( u( j, kms+1 )+v( 2_${ik}$, m )*u( j, kms+2 )+v( 3_${ik}$, m )*u( & j, kms+3 ) ) u( j, kms+1 ) = u( j, kms+1 ) - refsum u( j, kms+2 ) = u( j, kms+2 ) -refsum*conjg( v( 2_${ik}$, m ) ) u( j, kms+3 ) = u( j, kms+3 ) -refsum*conjg( v( 3_${ik}$, m ) ) end do end do else if( wantz ) then ! ==== u is not accumulated, so update z ! . now by multiplying by reflections ! . from the right. ==== do m = mbot, mtop, -1 k = krcol + 2_${ik}$*( m-1 ) do j = iloz, ihiz refsum = v( 1_${ik}$, m )*( z( j, k+1 )+v( 2_${ik}$, m )*z( j, k+2 )+v( 3_${ik}$, m )*z( j, & k+3 ) ) z( j, k+1 ) = z( j, k+1 ) - refsum z( j, k+2 ) = z( j, k+2 ) -refsum*conjg( v( 2_${ik}$, m ) ) z( j, k+3 ) = z( j, k+3 ) -refsum*conjg( v( 3_${ik}$, m ) ) end do end do end if ! ==== end of near-the-diagonal bulge chase. ==== end do loop_145 ! ==== use u (if accumulated) to update far-from-diagonal ! . entries in h. if required, use u to update z as ! . well. ==== if( accum ) then if( wantt ) then jtop = 1_${ik}$ jbot = n else jtop = ktop jbot = kbot end if k1 = max( 1_${ik}$, ktop-incol ) nu = ( kdu-max( 0_${ik}$, ndcol-kbot ) ) - k1 + 1_${ik}$ ! ==== horizontal multiply ==== do jcol = min( ndcol, kbot ) + 1, jbot, nh jlen = min( nh, jbot-jcol+1 ) call stdlib${ii}$_${ci}$gemm( 'C', 'N', nu, jlen, nu, cone, u( k1, k1 ),ldu, h( incol+k1,& jcol ), ldh, czero, wh,ldwh ) call stdlib${ii}$_${ci}$lacpy( 'ALL', nu, jlen, wh, ldwh,h( incol+k1, jcol ), ldh ) end do ! ==== vertical multiply ==== do jrow = jtop, max( ktop, incol ) - 1, nv jlen = min( nv, max( ktop, incol )-jrow ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', jlen, nu, nu, cone,h( jrow, incol+k1 ), ldh, u( & k1, k1 ),ldu, czero, wv, ldwv ) call stdlib${ii}$_${ci}$lacpy( 'ALL', jlen, nu, wv, ldwv,h( jrow, incol+k1 ), ldh ) end do ! ==== z multiply (also vertical) ==== if( wantz ) then do jrow = iloz, ihiz, nv jlen = min( nv, ihiz-jrow+1 ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', jlen, nu, nu, cone,z( jrow, incol+k1 ), ldz, & u( k1, k1 ),ldu, czero, wv, ldwv ) call stdlib${ii}$_${ci}$lacpy( 'ALL', jlen, nu, wv, ldwv,z( jrow, incol+k1 ), ldz ) end do end if end if end do loop_180 end subroutine stdlib${ii}$_${ci}$laqr5 #:endif #:endfor recursive module subroutine stdlib${ii}$_slaqz0( wants, wantq, wantz, n, ilo, ihi, a,lda, b, ldb, alphar, & !! SLAQZ0 computes the eigenvalues of a real matrix pair (H,T), !! where H is an upper Hessenberg matrix and T is upper triangular, !! using the double-shift QZ method. !! Matrix pairs of this type are produced by the reduction to !! generalized upper Hessenberg form of a real matrix pair (A,B): !! A = Q1*H*Z1**T, B = Q1*T*Z1**T, !! as computed by SGGHRD. !! If JOB='S', then the Hessenberg-triangular pair (H,T) is !! also reduced to generalized Schur form, !! H = Q*S*Z**T, T = Q*P*Z**T, !! where Q and Z are orthogonal matrices, P is an upper triangular !! matrix, and S is a quasi-triangular matrix with 1-by-1 and 2-by-2 !! diagonal blocks. !! The 1-by-1 blocks correspond to real eigenvalues of the matrix pair !! (H,T) and the 2-by-2 blocks correspond to complex conjugate pairs of !! eigenvalues. !! Additionally, the 2-by-2 upper triangular diagonal blocks of P !! corresponding to 2-by-2 blocks of S are reduced to positive diagonal !! form, i.e., if S(j+1,j) is non-zero, then P(j+1,j) = P(j,j+1) = 0, !! P(j,j) > 0, and P(j+1,j+1) > 0. !! Optionally, the orthogonal matrix Q from the generalized Schur !! factorization may be postmultiplied into an input matrix Q1, and the !! orthogonal matrix Z may be postmultiplied into an input matrix Z1. !! If Q1 and Z1 are the orthogonal matrices from SGGHRD that reduced !! the matrix pair (A,B) to generalized upper Hessenberg form, then the !! output matrices Q1*Q and Z1*Z are the orthogonal factors from the !! generalized Schur factorization of (A,B): !! A = (Q1*Q)*S*(Z1*Z)**T, B = (Q1*Q)*P*(Z1*Z)**T. !! To avoid overflow, eigenvalues of the matrix pair (H,T) (equivalently, !! of (A,B)) are computed as a pair of values (alpha,beta), where alpha is !! complex and beta real. !! If beta is nonzero, lambda = alpha / beta is an eigenvalue of the !! generalized nonsymmetric eigenvalue problem (GNEP) !! A*x = lambda*B*x !! and if alpha is nonzero, mu = beta / alpha is an eigenvalue of the !! alternate form of the GNEP !! mu*A*y = B*y. !! Real eigenvalues can be read directly from the generalized Schur !! form: !! alpha = S(i,i), beta = P(i,i). !! Ref: C.B. Moler !! Eigenvalue Problems", SIAM J. Numer. Anal., 10(1973), !! pp. 241--256. !! Ref: B. Kagstrom, D. Kressner, "Multishift Variants of the QZ !! Algorithm with Aggressive Early Deflation", SIAM J. Numer. !! Anal., 29(2006), pp. 199--227. !! Ref: T. Steel, D. Camps, K. Meerbergen, R. Vandebril "A multishift, !! multipole rational QZ method with agressive early deflation" alphai, beta,q, ldq, z, ldz, work, lwork, rec,info ) use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments character, intent( in ) :: wants, wantq, wantz integer(${ik}$), intent( in ) :: n, ilo, ihi, lda, ldb, ldq, ldz, lwork,rec integer(${ik}$), intent( out ) :: info real(sp), intent( inout ) :: a( lda, * ), b( ldb, * ), q( ldq, * ),z( ldz, * ), alphar(& * ), alphai( * ), beta( * ), work( * ) ! ================================================================ ! local scalars real(sp) :: smlnum, ulp, eshift, safmin, safmax, c1, s1, temp, swap integer(${ik}$) :: istart, istop, iiter, maxit, istart2, k, ld, nshifts, nblock, nw, nmin,& nibble, n_undeflated, n_deflated, ns, sweep_info, shiftpos, lworkreq, k2, istartm, & istopm, iwants, iwantq, iwantz, norm_info, aed_info, nwr, nbr, nsr, itemp1, itemp2, & rcost, i logical(lk) :: ilschur, ilq, ilz character(len=3_${ik}$) :: jbcmpz if( stdlib_lsame( wants, 'E' ) ) then ilschur = .false. iwants = 1_${ik}$ else if( stdlib_lsame( wants, 'S' ) ) then ilschur = .true. iwants = 2_${ik}$ else iwants = 0_${ik}$ end if if( stdlib_lsame( wantq, 'N' ) ) then ilq = .false. iwantq = 1_${ik}$ else if( stdlib_lsame( wantq, 'V' ) ) then ilq = .true. iwantq = 2_${ik}$ else if( stdlib_lsame( wantq, 'I' ) ) then ilq = .true. iwantq = 3_${ik}$ else iwantq = 0_${ik}$ end if if( stdlib_lsame( wantz, 'N' ) ) then ilz = .false. iwantz = 1_${ik}$ else if( stdlib_lsame( wantz, 'V' ) ) then ilz = .true. iwantz = 2_${ik}$ else if( stdlib_lsame( wantz, 'I' ) ) then ilz = .true. iwantz = 3_${ik}$ else iwantz = 0_${ik}$ end if ! check argument values info = 0_${ik}$ if( iwants==0_${ik}$ ) then info = -1_${ik}$ else if( iwantq==0_${ik}$ ) then info = -2_${ik}$ else if( iwantz==0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ilo<1_${ik}$ ) then info = -5_${ik}$ else if( ihi>n .or. ihi= 2_${ik}$ ) then call stdlib${ii}$_shgeqz( wants, wantq, wantz, n, ilo, ihi, a, lda, b, ldb,alphar, alphai,& beta, q, ldq, z, ldz, work,lwork, info ) return end if ! find out required workspace ! workspace query to stdlib${ii}$_slaqz3 nw = max( nwr, nmin ) call stdlib${ii}$_slaqz3( ilschur, ilq, ilz, n, ilo, ihi, nw, a, lda, b, ldb,q, ldq, z, ldz, & n_undeflated, n_deflated, alphar,alphai, beta, work, nw, work, nw, work, -1_${ik}$, rec,& aed_info ) itemp1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! workspace query to stdlib${ii}$_slaqz4 call stdlib${ii}$_slaqz4( ilschur, ilq, ilz, n, ilo, ihi, nsr, nbr, alphar,alphai, beta, a, & lda, b, ldb, q, ldq, z, ldz, work,nbr, work, nbr, work, -1_${ik}$, sweep_info ) itemp2 = int( work( 1_${ik}$ ),KIND=${ik}$) lworkreq = max( itemp1+2*nw**2_${ik}$, itemp2+2*nbr**2_${ik}$ ) if ( lwork ==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lworkreq,KIND=sp) return else if ( lwork < lworkreq ) then info = -19_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SLAQZ0', info ) return end if ! initialize q and z if( iwantq==3_${ik}$ ) call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, q, ldq ) if( iwantz==3_${ik}$ ) call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, z, ldz ) ! get machine constants safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=sp)/ulp ) istart = ilo istop = ihi maxit = 3_${ik}$*( ihi-ilo+1 ) ld = 0_${ik}$ do iiter = 1, maxit if( iiter >= maxit ) then info = istop+1 goto 80 end if if ( istart+1 >= istop ) then istop = istart exit end if ! check deflations at the end if ( abs( a( istop-1, istop-2 ) ) <= max( smlnum,ulp*( abs( a( istop-1, istop-1 ) )+& abs( a( istop-2,istop-2 ) ) ) ) ) then a( istop-1, istop-2 ) = zero istop = istop-2 ld = 0_${ik}$ eshift = zero else if ( abs( a( istop, istop-1 ) ) <= max( smlnum,ulp*( abs( a( istop, istop ) )+& abs( a( istop-1,istop-1 ) ) ) ) ) then a( istop, istop-1 ) = zero istop = istop-1 ld = 0_${ik}$ eshift = zero end if ! check deflations at the start if ( abs( a( istart+2, istart+1 ) ) <= max( smlnum,ulp*( abs( a( istart+1, istart+1 & ) )+abs( a( istart+2,istart+2 ) ) ) ) ) then a( istart+2, istart+1 ) = zero istart = istart+2 ld = 0_${ik}$ eshift = zero else if ( abs( a( istart+1, istart ) ) <= max( smlnum,ulp*( abs( a( istart, istart )& )+abs( a( istart+1,istart+1 ) ) ) ) ) then a( istart+1, istart ) = zero istart = istart+1 ld = 0_${ik}$ eshift = zero end if if ( istart+1 >= istop ) then exit end if ! check interior deflations istart2 = istart do k = istop, istart+1, -1 if ( abs( a( k, k-1 ) ) <= max( smlnum, ulp*( abs( a( k,k ) )+abs( a( k-1, k-1 ) & ) ) ) ) then a( k, k-1 ) = zero istart2 = k exit end if end do ! get range to apply rotations to if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = istart2 istopm = istop end if ! check infinite eigenvalues, this is done without blocking so might ! slow down the method when many infinite eigenvalues are present k = istop do while ( k>=istart2 ) temp = zero if( k < istop ) then temp = temp+abs( b( k, k+1 ) ) end if if( k > istart2 ) then temp = temp+abs( b( k-1, k ) ) end if if( abs( b( k, k ) ) < max( smlnum, ulp*temp ) ) then ! a diagonal element of b is negligable, move it ! to the top and deflate it do k2 = k, istart2+1, -1 call stdlib${ii}$_slartg( b( k2-1, k2 ), b( k2-1, k2-1 ), c1, s1,temp ) b( k2-1, k2 ) = temp b( k2-1, k2-1 ) = zero call stdlib${ii}$_srot( k2-2-istartm+1, b( istartm, k2 ), 1_${ik}$,b( istartm, k2-1 ), & 1_${ik}$, c1, s1 ) call stdlib${ii}$_srot( min( k2+1, istop )-istartm+1, a( istartm,k2 ), 1_${ik}$, a( & istartm, k2-1 ), 1_${ik}$, c1, s1 ) if ( ilz ) then call stdlib${ii}$_srot( n, z( 1_${ik}$, k2 ), 1_${ik}$, z( 1_${ik}$, k2-1 ), 1_${ik}$, c1,s1 ) end if if( k2= istop ) then istop = istart2-1 ld = 0_${ik}$ eshift = zero cycle end if nw = nwr nshifts = nsr nblock = nbr if ( istop-istart2+1 < nmin ) then ! setting nw to the size of the subblock will make aed deflate ! all the eigenvalues. this is slightly more efficient than just ! using qz_small because the off diagonal part gets updated via blas. if ( istop-istart+1 < nmin ) then nw = istop-istart+1 istart2 = istart else nw = istop-istart2+1 end if end if ! time for aed call stdlib${ii}$_slaqz3( ilschur, ilq, ilz, n, istart2, istop, nw, a, lda,b, ldb, q, ldq,& z, ldz, n_undeflated, n_deflated,alphar, alphai, beta, work, nw, work( nw**2_${ik}$+1 ),& nw, work( 2_${ik}$*nw**2_${ik}$+1 ), lwork-2*nw**2_${ik}$, rec,aed_info ) if ( n_deflated > 0_${ik}$ ) then istop = istop-n_deflated ld = 0_${ik}$ eshift = zero end if if ( 100_${ik}$*n_deflated > nibble*( n_deflated+n_undeflated ) .or.istop-istart2+1 < nmin & ) then ! aed has uncovered many eigenvalues. skip a qz sweep and run ! aed again. cycle end if ld = ld+1 ns = min( nshifts, istop-istart2 ) ns = min( ns, n_undeflated ) shiftpos = istop-n_deflated-n_undeflated+1 ! shuffle shifts to put double shifts in front ! this ensures that we don't split up a double shift do i = shiftpos, shiftpos+n_undeflated-1, 2 if( alphai( i )/=-alphai( i+1 ) ) then swap = alphar( i ) alphar( i ) = alphar( i+1 ) alphar( i+1 ) = alphar( i+2 ) alphar( i+2 ) = swap swap = alphai( i ) alphai( i ) = alphai( i+1 ) alphai( i+1 ) = alphai( i+2 ) alphai( i+2 ) = swap swap = beta( i ) beta( i ) = beta( i+1 ) beta( i+1 ) = beta( i+2 ) beta( i+2 ) = swap end if end do if ( mod( ld, 6_${ik}$ ) == 0_${ik}$ ) then ! exceptional shift. chosen for no particularly good reason. if( ( real( maxit,KIND=sp)*safmin )*abs( a( istop,istop-1 ) ) 0, and P(j+1,j+1) > 0. !! Optionally, the orthogonal matrix Q from the generalized Schur !! factorization may be postmultiplied into an input matrix Q1, and the !! orthogonal matrix Z may be postmultiplied into an input matrix Z1. !! If Q1 and Z1 are the orthogonal matrices from DGGHRD that reduced !! the matrix pair (A,B) to generalized upper Hessenberg form, then the !! output matrices Q1*Q and Z1*Z are the orthogonal factors from the !! generalized Schur factorization of (A,B): !! A = (Q1*Q)*S*(Z1*Z)**T, B = (Q1*Q)*P*(Z1*Z)**T. !! To avoid overflow, eigenvalues of the matrix pair (H,T) (equivalently, !! of (A,B)) are computed as a pair of values (alpha,beta), where alpha is !! complex and beta real. !! If beta is nonzero, lambda = alpha / beta is an eigenvalue of the !! generalized nonsymmetric eigenvalue problem (GNEP) !! A*x = lambda*B*x !! and if alpha is nonzero, mu = beta / alpha is an eigenvalue of the !! alternate form of the GNEP !! mu*A*y = B*y. !! Real eigenvalues can be read directly from the generalized Schur !! form: !! alpha = S(i,i), beta = P(i,i). !! Ref: C.B. Moler !! Eigenvalue Problems", SIAM J. Numer. Anal., 10(1973), !! pp. 241--256. !! Ref: B. Kagstrom, D. Kressner, "Multishift Variants of the QZ !! Algorithm with Aggressive Early Deflation", SIAM J. Numer. !! Anal., 29(2006), pp. 199--227. !! Ref: T. Steel, D. Camps, K. Meerbergen, R. Vandebril "A multishift, !! multipole rational QZ method with agressive early deflation" alphai, beta,q, ldq, z, ldz, work, lwork, rec,info ) use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments character, intent( in ) :: wants, wantq, wantz integer(${ik}$), intent( in ) :: n, ilo, ihi, lda, ldb, ldq, ldz, lwork,rec integer(${ik}$), intent( out ) :: info real(dp), intent( inout ) :: a( lda, * ), b( ldb, * ),q( ldq, * ), z( ldz, * ), alphar(& * ),alphai( * ), beta( * ), work( * ) ! ================================================================ ! local scalars real(dp) :: smlnum, ulp, eshift, safmin, safmax, c1, s1, temp, swap integer(${ik}$) :: istart, istop, iiter, maxit, istart2, k, ld, nshifts, nblock, nw, nmin,& nibble, n_undeflated, n_deflated, ns, sweep_info, shiftpos, lworkreq, k2, istartm, & istopm, iwants, iwantq, iwantz, norm_info, aed_info, nwr, nbr, nsr, itemp1, itemp2, & rcost, i logical(lk) :: ilschur, ilq, ilz character(len=3_${ik}$) :: jbcmpz if( stdlib_lsame( wants, 'E' ) ) then ilschur = .false. iwants = 1_${ik}$ else if( stdlib_lsame( wants, 'S' ) ) then ilschur = .true. iwants = 2_${ik}$ else iwants = 0_${ik}$ end if if( stdlib_lsame( wantq, 'N' ) ) then ilq = .false. iwantq = 1_${ik}$ else if( stdlib_lsame( wantq, 'V' ) ) then ilq = .true. iwantq = 2_${ik}$ else if( stdlib_lsame( wantq, 'I' ) ) then ilq = .true. iwantq = 3_${ik}$ else iwantq = 0_${ik}$ end if if( stdlib_lsame( wantz, 'N' ) ) then ilz = .false. iwantz = 1_${ik}$ else if( stdlib_lsame( wantz, 'V' ) ) then ilz = .true. iwantz = 2_${ik}$ else if( stdlib_lsame( wantz, 'I' ) ) then ilz = .true. iwantz = 3_${ik}$ else iwantz = 0_${ik}$ end if ! check argument values info = 0_${ik}$ if( iwants==0_${ik}$ ) then info = -1_${ik}$ else if( iwantq==0_${ik}$ ) then info = -2_${ik}$ else if( iwantz==0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ilo<1_${ik}$ ) then info = -5_${ik}$ else if( ihi>n .or. ihi= 2_${ik}$ ) then call stdlib${ii}$_dhgeqz( wants, wantq, wantz, n, ilo, ihi, a, lda, b, ldb,alphar, alphai,& beta, q, ldq, z, ldz, work,lwork, info ) return end if ! find out required workspace ! workspace query to stdlib${ii}$_dlaqz3 nw = max( nwr, nmin ) call stdlib${ii}$_dlaqz3( ilschur, ilq, ilz, n, ilo, ihi, nw, a, lda, b, ldb,q, ldq, z, ldz, & n_undeflated, n_deflated, alphar,alphai, beta, work, nw, work, nw, work, -1_${ik}$, rec,& aed_info ) itemp1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! workspace query to stdlib${ii}$_dlaqz4 call stdlib${ii}$_dlaqz4( ilschur, ilq, ilz, n, ilo, ihi, nsr, nbr, alphar,alphai, beta, a, & lda, b, ldb, q, ldq, z, ldz, work,nbr, work, nbr, work, -1_${ik}$, sweep_info ) itemp2 = int( work( 1_${ik}$ ),KIND=${ik}$) lworkreq = max( itemp1+2*nw**2_${ik}$, itemp2+2*nbr**2_${ik}$ ) if ( lwork ==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lworkreq,KIND=dp) return else if ( lwork < lworkreq ) then info = -19_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLAQZ0', info ) return end if ! initialize q and z if( iwantq==3_${ik}$ ) call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, q, ldq ) if( iwantz==3_${ik}$ ) call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, z, ldz ) ! get machine constants safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=dp)/ulp ) istart = ilo istop = ihi maxit = 3_${ik}$*( ihi-ilo+1 ) ld = 0_${ik}$ do iiter = 1, maxit if( iiter >= maxit ) then info = istop+1 goto 80 end if if ( istart+1 >= istop ) then istop = istart exit end if ! check deflations at the end if ( abs( a( istop-1, istop-2 ) ) <= max( smlnum,ulp*( abs( a( istop-1, istop-1 ) )+& abs( a( istop-2,istop-2 ) ) ) ) ) then a( istop-1, istop-2 ) = zero istop = istop-2 ld = 0_${ik}$ eshift = zero else if ( abs( a( istop, istop-1 ) ) <= max( smlnum,ulp*( abs( a( istop, istop ) )+& abs( a( istop-1,istop-1 ) ) ) ) ) then a( istop, istop-1 ) = zero istop = istop-1 ld = 0_${ik}$ eshift = zero end if ! check deflations at the start if ( abs( a( istart+2, istart+1 ) ) <= max( smlnum,ulp*( abs( a( istart+1, istart+1 & ) )+abs( a( istart+2,istart+2 ) ) ) ) ) then a( istart+2, istart+1 ) = zero istart = istart+2 ld = 0_${ik}$ eshift = zero else if ( abs( a( istart+1, istart ) ) <= max( smlnum,ulp*( abs( a( istart, istart )& )+abs( a( istart+1,istart+1 ) ) ) ) ) then a( istart+1, istart ) = zero istart = istart+1 ld = 0_${ik}$ eshift = zero end if if ( istart+1 >= istop ) then exit end if ! check interior deflations istart2 = istart do k = istop, istart+1, -1 if ( abs( a( k, k-1 ) ) <= max( smlnum, ulp*( abs( a( k,k ) )+abs( a( k-1, k-1 ) & ) ) ) ) then a( k, k-1 ) = zero istart2 = k exit end if end do ! get range to apply rotations to if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = istart2 istopm = istop end if ! check infinite eigenvalues, this is done without blocking so might ! slow down the method when many infinite eigenvalues are present k = istop do while ( k>=istart2 ) temp = zero if( k < istop ) then temp = temp+abs( b( k, k+1 ) ) end if if( k > istart2 ) then temp = temp+abs( b( k-1, k ) ) end if if( abs( b( k, k ) ) < max( smlnum, ulp*temp ) ) then ! a diagonal element of b is negligable, move it ! to the top and deflate it do k2 = k, istart2+1, -1 call stdlib${ii}$_dlartg( b( k2-1, k2 ), b( k2-1, k2-1 ), c1, s1,temp ) b( k2-1, k2 ) = temp b( k2-1, k2-1 ) = zero call stdlib${ii}$_drot( k2-2-istartm+1, b( istartm, k2 ), 1_${ik}$,b( istartm, k2-1 ), & 1_${ik}$, c1, s1 ) call stdlib${ii}$_drot( min( k2+1, istop )-istartm+1, a( istartm,k2 ), 1_${ik}$, a( & istartm, k2-1 ), 1_${ik}$, c1, s1 ) if ( ilz ) then call stdlib${ii}$_drot( n, z( 1_${ik}$, k2 ), 1_${ik}$, z( 1_${ik}$, k2-1 ), 1_${ik}$, c1,s1 ) end if if( k2= istop ) then istop = istart2-1 ld = 0_${ik}$ eshift = zero cycle end if nw = nwr nshifts = nsr nblock = nbr if ( istop-istart2+1 < nmin ) then ! setting nw to the size of the subblock will make aed deflate ! all the eigenvalues. this is slightly more efficient than just ! using stdlib${ii}$_dhgeqz because the off diagonal part gets updated via blas. if ( istop-istart+1 < nmin ) then nw = istop-istart+1 istart2 = istart else nw = istop-istart2+1 end if end if ! time for aed call stdlib${ii}$_dlaqz3( ilschur, ilq, ilz, n, istart2, istop, nw, a, lda,b, ldb, q, ldq,& z, ldz, n_undeflated, n_deflated,alphar, alphai, beta, work, nw, work( nw**2_${ik}$+1 ),& nw, work( 2_${ik}$*nw**2_${ik}$+1 ), lwork-2*nw**2_${ik}$, rec,aed_info ) if ( n_deflated > 0_${ik}$ ) then istop = istop-n_deflated ld = 0_${ik}$ eshift = zero end if if ( 100_${ik}$*n_deflated > nibble*( n_deflated+n_undeflated ) .or.istop-istart2+1 < nmin & ) then ! aed has uncovered many eigenvalues. skip a qz sweep and run ! aed again. cycle end if ld = ld+1 ns = min( nshifts, istop-istart2 ) ns = min( ns, n_undeflated ) shiftpos = istop-n_deflated-n_undeflated+1 ! shuffle shifts to put double shifts in front ! this ensures that we don't split up a double shift do i = shiftpos, shiftpos+n_undeflated-1, 2 if( alphai( i )/=-alphai( i+1 ) ) then swap = alphar( i ) alphar( i ) = alphar( i+1 ) alphar( i+1 ) = alphar( i+2 ) alphar( i+2 ) = swap swap = alphai( i ) alphai( i ) = alphai( i+1 ) alphai( i+1 ) = alphai( i+2 ) alphai( i+2 ) = swap swap = beta( i ) beta( i ) = beta( i+1 ) beta( i+1 ) = beta( i+2 ) beta( i+2 ) = swap end if end do if ( mod( ld, 6_${ik}$ ) == 0_${ik}$ ) then ! exceptional shift. chosen for no particularly good reason. if( ( real( maxit,KIND=dp)*safmin )*abs( a( istop,istop-1 ) ) 0, and P(j+1,j+1) > 0. !! Optionally, the orthogonal matrix Q from the generalized Schur !! factorization may be postmultiplied into an input matrix Q1, and the !! orthogonal matrix Z may be postmultiplied into an input matrix Z1. !! If Q1 and Z1 are the orthogonal matrices from DGGHRD that reduced !! the matrix pair (A,B) to generalized upper Hessenberg form, then the !! output matrices Q1*Q and Z1*Z are the orthogonal factors from the !! generalized Schur factorization of (A,B): !! A = (Q1*Q)*S*(Z1*Z)**T, B = (Q1*Q)*P*(Z1*Z)**T. !! To avoid overflow, eigenvalues of the matrix pair (H,T) (equivalently, !! of (A,B)) are computed as a pair of values (alpha,beta), where alpha is !! complex and beta real. !! If beta is nonzero, lambda = alpha / beta is an eigenvalue of the !! generalized nonsymmetric eigenvalue problem (GNEP) !! A*x = lambda*B*x !! and if alpha is nonzero, mu = beta / alpha is an eigenvalue of the !! alternate form of the GNEP !! mu*A*y = B*y. !! Real eigenvalues can be read directly from the generalized Schur !! form: !! alpha = S(i,i), beta = P(i,i). !! Ref: C.B. Moler !! Eigenvalue Problems", SIAM J. Numer. Anal., 10(1973), !! pp. 241--256. !! Ref: B. Kagstrom, D. Kressner, "Multishift Variants of the QZ !! Algorithm with Aggressive Early Deflation", SIAM J. Numer. !! Anal., 29(2006), pp. 199--227. !! Ref: T. Steel, D. Camps, K. Meerbergen, R. Vandebril "A multishift, !! multipole rational QZ method with agressive early deflation" alphai, beta,q, ldq, z, ldz, work, lwork, rec,info ) use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments character, intent( in ) :: wants, wantq, wantz integer(${ik}$), intent( in ) :: n, ilo, ihi, lda, ldb, ldq, ldz, lwork,rec integer(${ik}$), intent( out ) :: info real(${rk}$), intent( inout ) :: a( lda, * ), b( ldb, * ),q( ldq, * ), z( ldz, * ), alphar(& * ),alphai( * ), beta( * ), work( * ) ! ================================================================ ! local scalars real(${rk}$) :: smlnum, ulp, eshift, safmin, safmax, c1, s1, temp, swap integer(${ik}$) :: istart, istop, iiter, maxit, istart2, k, ld, nshifts, nblock, nw, nmin,& nibble, n_undeflated, n_qeflated, ns, sweep_info, shiftpos, lworkreq, k2, istartm, & istopm, iwants, iwantq, iwantz, norm_info, aed_info, nwr, nbr, nsr, itemp1, itemp2, & rcost, i logical(lk) :: ilschur, ilq, ilz character(len=3_${ik}$) :: jbcmpz if( stdlib_lsame( wants, 'E' ) ) then ilschur = .false. iwants = 1_${ik}$ else if( stdlib_lsame( wants, 'S' ) ) then ilschur = .true. iwants = 2_${ik}$ else iwants = 0_${ik}$ end if if( stdlib_lsame( wantq, 'N' ) ) then ilq = .false. iwantq = 1_${ik}$ else if( stdlib_lsame( wantq, 'V' ) ) then ilq = .true. iwantq = 2_${ik}$ else if( stdlib_lsame( wantq, 'I' ) ) then ilq = .true. iwantq = 3_${ik}$ else iwantq = 0_${ik}$ end if if( stdlib_lsame( wantz, 'N' ) ) then ilz = .false. iwantz = 1_${ik}$ else if( stdlib_lsame( wantz, 'V' ) ) then ilz = .true. iwantz = 2_${ik}$ else if( stdlib_lsame( wantz, 'I' ) ) then ilz = .true. iwantz = 3_${ik}$ else iwantz = 0_${ik}$ end if ! check argument values info = 0_${ik}$ if( iwants==0_${ik}$ ) then info = -1_${ik}$ else if( iwantq==0_${ik}$ ) then info = -2_${ik}$ else if( iwantz==0_${ik}$ ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ilo<1_${ik}$ ) then info = -5_${ik}$ else if( ihi>n .or. ihi= 2_${ik}$ ) then call stdlib${ii}$_${ri}$hgeqz( wants, wantq, wantz, n, ilo, ihi, a, lda, b, ldb,alphar, alphai,& beta, q, ldq, z, ldz, work,lwork, info ) return end if ! find out required workspace ! workspace query to stdlib${ii}$_${ri}$laqz3 nw = max( nwr, nmin ) call stdlib${ii}$_${ri}$laqz3( ilschur, ilq, ilz, n, ilo, ihi, nw, a, lda, b, ldb,q, ldq, z, ldz, & n_undeflated, n_qeflated, alphar,alphai, beta, work, nw, work, nw, work, -1_${ik}$, rec,& aed_info ) itemp1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! workspace query to stdlib${ii}$_${ri}$laqz4 call stdlib${ii}$_${ri}$laqz4( ilschur, ilq, ilz, n, ilo, ihi, nsr, nbr, alphar,alphai, beta, a, & lda, b, ldb, q, ldq, z, ldz, work,nbr, work, nbr, work, -1_${ik}$, sweep_info ) itemp2 = int( work( 1_${ik}$ ),KIND=${ik}$) lworkreq = max( itemp1+2*nw**2_${ik}$, itemp2+2*nbr**2_${ik}$ ) if ( lwork ==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lworkreq,KIND=${rk}$) return else if ( lwork < lworkreq ) then info = -19_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLAQZ0', info ) return end if ! initialize q and z if( iwantq==3_${ik}$ ) call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, q, ldq ) if( iwantz==3_${ik}$ ) call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, z, ldz ) ! get machine constants safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_${ri}$labad( safmin, safmax ) ulp = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=${rk}$)/ulp ) istart = ilo istop = ihi maxit = 3_${ik}$*( ihi-ilo+1 ) ld = 0_${ik}$ do iiter = 1, maxit if( iiter >= maxit ) then info = istop+1 goto 80 end if if ( istart+1 >= istop ) then istop = istart exit end if ! check deflations at the end if ( abs( a( istop-1, istop-2 ) ) <= max( smlnum,ulp*( abs( a( istop-1, istop-1 ) )+& abs( a( istop-2,istop-2 ) ) ) ) ) then a( istop-1, istop-2 ) = zero istop = istop-2 ld = 0_${ik}$ eshift = zero else if ( abs( a( istop, istop-1 ) ) <= max( smlnum,ulp*( abs( a( istop, istop ) )+& abs( a( istop-1,istop-1 ) ) ) ) ) then a( istop, istop-1 ) = zero istop = istop-1 ld = 0_${ik}$ eshift = zero end if ! check deflations at the start if ( abs( a( istart+2, istart+1 ) ) <= max( smlnum,ulp*( abs( a( istart+1, istart+1 & ) )+abs( a( istart+2,istart+2 ) ) ) ) ) then a( istart+2, istart+1 ) = zero istart = istart+2 ld = 0_${ik}$ eshift = zero else if ( abs( a( istart+1, istart ) ) <= max( smlnum,ulp*( abs( a( istart, istart )& )+abs( a( istart+1,istart+1 ) ) ) ) ) then a( istart+1, istart ) = zero istart = istart+1 ld = 0_${ik}$ eshift = zero end if if ( istart+1 >= istop ) then exit end if ! check interior deflations istart2 = istart do k = istop, istart+1, -1 if ( abs( a( k, k-1 ) ) <= max( smlnum, ulp*( abs( a( k,k ) )+abs( a( k-1, k-1 ) & ) ) ) ) then a( k, k-1 ) = zero istart2 = k exit end if end do ! get range to apply rotations to if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = istart2 istopm = istop end if ! check infinite eigenvalues, this is done without blocking so might ! slow down the method when many infinite eigenvalues are present k = istop do while ( k>=istart2 ) temp = zero if( k < istop ) then temp = temp+abs( b( k, k+1 ) ) end if if( k > istart2 ) then temp = temp+abs( b( k-1, k ) ) end if if( abs( b( k, k ) ) < max( smlnum, ulp*temp ) ) then ! a diagonal element of b is negligable, move it ! to the top and deflate it do k2 = k, istart2+1, -1 call stdlib${ii}$_${ri}$lartg( b( k2-1, k2 ), b( k2-1, k2-1 ), c1, s1,temp ) b( k2-1, k2 ) = temp b( k2-1, k2-1 ) = zero call stdlib${ii}$_${ri}$rot( k2-2-istartm+1, b( istartm, k2 ), 1_${ik}$,b( istartm, k2-1 ), & 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$rot( min( k2+1, istop )-istartm+1, a( istartm,k2 ), 1_${ik}$, a( & istartm, k2-1 ), 1_${ik}$, c1, s1 ) if ( ilz ) then call stdlib${ii}$_${ri}$rot( n, z( 1_${ik}$, k2 ), 1_${ik}$, z( 1_${ik}$, k2-1 ), 1_${ik}$, c1,s1 ) end if if( k2= istop ) then istop = istart2-1 ld = 0_${ik}$ eshift = zero cycle end if nw = nwr nshifts = nsr nblock = nbr if ( istop-istart2+1 < nmin ) then ! setting nw to the size of the subblock will make aed deflate ! all the eigenvalues. this is slightly more efficient than just ! using stdlib${ii}$_${ri}$hgeqz because the off diagonal part gets updated via blas. if ( istop-istart+1 < nmin ) then nw = istop-istart+1 istart2 = istart else nw = istop-istart2+1 end if end if ! time for aed call stdlib${ii}$_${ri}$laqz3( ilschur, ilq, ilz, n, istart2, istop, nw, a, lda,b, ldb, q, ldq,& z, ldz, n_undeflated, n_qeflated,alphar, alphai, beta, work, nw, work( nw**2_${ik}$+1 ),& nw, work( 2_${ik}$*nw**2_${ik}$+1 ), lwork-2*nw**2_${ik}$, rec,aed_info ) if ( n_qeflated > 0_${ik}$ ) then istop = istop-n_qeflated ld = 0_${ik}$ eshift = zero end if if ( 100_${ik}$*n_qeflated > nibble*( n_qeflated+n_undeflated ) .or.istop-istart2+1 < nmin & ) then ! aed has uncovered many eigenvalues. skip a qz sweep and run ! aed again. cycle end if ld = ld+1 ns = min( nshifts, istop-istart2 ) ns = min( ns, n_undeflated ) shiftpos = istop-n_qeflated-n_undeflated+1 ! shuffle shifts to put double shifts in front ! this ensures that we don't split up a double shift do i = shiftpos, shiftpos+n_undeflated-1, 2 if( alphai( i )/=-alphai( i+1 ) ) then swap = alphar( i ) alphar( i ) = alphar( i+1 ) alphar( i+1 ) = alphar( i+2 ) alphar( i+2 ) = swap swap = alphai( i ) alphai( i ) = alphai( i+1 ) alphai( i+1 ) = alphai( i+2 ) alphai( i+2 ) = swap swap = beta( i ) beta( i ) = beta( i+1 ) beta( i+1 ) = beta( i+2 ) beta( i+2 ) = swap end if end do if ( mod( ld, 6_${ik}$ ) == 0_${ik}$ ) then ! exceptional shift. chosen for no particularly good reason. if( ( real( maxit,KIND=${rk}$)*safmin )*abs( a( istop,istop-1 ) )n .or. ihi= 2_${ik}$ ) then call stdlib${ii}$_chgeqz( wants, wantq, wantz, n, ilo, ihi, a, lda, b, ldb,alpha, beta, q,& ldq, z, ldz, work, lwork, rwork,info ) return end if ! find out required workspace ! workspace query to stdlib${ii}$_claqz2 nw = max( nwr, nmin ) call stdlib${ii}$_claqz2( ilschur, ilq, ilz, n, ilo, ihi, nw, a, lda, b, ldb,q, ldq, z, ldz, & n_undeflated, n_deflated, alpha,beta, work, nw, work, nw, work, -1_${ik}$, rwork, rec,& aed_info ) itemp1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! workspace query to stdlib${ii}$_claqz3 call stdlib${ii}$_claqz3( ilschur, ilq, ilz, n, ilo, ihi, nsr, nbr, alpha,beta, a, lda, b, & ldb, q, ldq, z, ldz, work, nbr,work, nbr, work, -1_${ik}$, sweep_info ) itemp2 = int( work( 1_${ik}$ ),KIND=${ik}$) lworkreq = max( itemp1+2*nw**2_${ik}$, itemp2+2*nbr**2_${ik}$ ) if ( lwork ==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lworkreq,KIND=sp) return else if ( lwork < lworkreq ) then info = -19_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CLAQZ0', info ) return end if ! initialize q and z if( iwantq==3_${ik}$ ) call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, q,ldq ) if( iwantz==3_${ik}$ ) call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, z,ldz ) ! get machine constants safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=sp)/ulp ) istart = ilo istop = ihi maxit = 30_${ik}$*( ihi-ilo+1 ) ld = 0_${ik}$ do iiter = 1, maxit if( iiter >= maxit ) then info = istop+1 goto 80 end if if ( istart+1 >= istop ) then istop = istart exit end if ! check deflations at the end if ( abs( a( istop, istop-1 ) ) <= max( smlnum,ulp*( abs( a( istop, istop ) )+abs( & a( istop-1,istop-1 ) ) ) ) ) then a( istop, istop-1 ) = czero istop = istop-1 ld = 0_${ik}$ eshift = czero end if ! check deflations at the start if ( abs( a( istart+1, istart ) ) <= max( smlnum,ulp*( abs( a( istart, istart ) )+& abs( a( istart+1,istart+1 ) ) ) ) ) then a( istart+1, istart ) = czero istart = istart+1 ld = 0_${ik}$ eshift = czero end if if ( istart+1 >= istop ) then exit end if ! check interior deflations istart2 = istart do k = istop, istart+1, -1 if ( abs( a( k, k-1 ) ) <= max( smlnum, ulp*( abs( a( k,k ) )+abs( a( k-1, k-1 ) & ) ) ) ) then a( k, k-1 ) = czero istart2 = k exit end if end do ! get range to apply rotations to if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = istart2 istopm = istop end if ! check infinite eigenvalues, this is done without blocking so might ! slow down the method when many infinite eigenvalues are present k = istop do while ( k>=istart2 ) tempr = zero if( k < istop ) then tempr = tempr+abs( b( k, k+1 ) ) end if if( k > istart2 ) then tempr = tempr+abs( b( k-1, k ) ) end if if( abs( b( k, k ) ) < max( smlnum, ulp*tempr ) ) then ! a diagonal element of b is negligable, move it ! to the top and deflate it do k2 = k, istart2+1, -1 call stdlib${ii}$_clartg( b( k2-1, k2 ), b( k2-1, k2-1 ), c1, s1,temp ) b( k2-1, k2 ) = temp b( k2-1, k2-1 ) = czero call stdlib${ii}$_crot( k2-2-istartm+1, b( istartm, k2 ), 1_${ik}$,b( istartm, k2-1 ), & 1_${ik}$, c1, s1 ) call stdlib${ii}$_crot( min( k2+1, istop )-istartm+1, a( istartm,k2 ), 1_${ik}$, a( & istartm, k2-1 ), 1_${ik}$, c1, s1 ) if ( ilz ) then call stdlib${ii}$_crot( n, z( 1_${ik}$, k2 ), 1_${ik}$, z( 1_${ik}$, k2-1 ), 1_${ik}$, c1,s1 ) end if if( k2= istop ) then istop = istart2-1 ld = 0_${ik}$ eshift = czero cycle end if nw = nwr nshifts = nsr nblock = nbr if ( istop-istart2+1 < nmin ) then ! setting nw to the size of the subblock will make aed deflate ! all the eigenvalues. this is slightly more efficient than just ! using stdlib${ii}$_chgeqz because the off diagonal part gets updated via blas. if ( istop-istart+1 < nmin ) then nw = istop-istart+1 istart2 = istart else nw = istop-istart2+1 end if end if ! time for aed call stdlib${ii}$_claqz2( ilschur, ilq, ilz, n, istart2, istop, nw, a, lda,b, ldb, q, ldq,& z, ldz, n_undeflated, n_deflated,alpha, beta, work, nw, work( nw**2_${ik}$+1 ), nw,work( & 2_${ik}$*nw**2_${ik}$+1 ), lwork-2*nw**2_${ik}$, rwork, rec,aed_info ) if ( n_deflated > 0_${ik}$ ) then istop = istop-n_deflated ld = 0_${ik}$ eshift = czero end if if ( 100_${ik}$*n_deflated > nibble*( n_deflated+n_undeflated ) .or.istop-istart2+1 < nmin & ) then ! aed has uncovered many eigenvalues. skip a qz sweep and run ! aed again. cycle end if ld = ld+1 ns = min( nshifts, istop-istart2 ) ns = min( ns, n_undeflated ) shiftpos = istop-n_deflated-n_undeflated+1 if ( mod( ld, 6_${ik}$ ) == 0_${ik}$ ) then ! exceptional shift. chosen for no particularly good reason. if( ( real( maxit,KIND=sp)*safmin )*abs( a( istop,istop-1 ) )n .or. ihi= 2_${ik}$ ) then call stdlib${ii}$_zhgeqz( wants, wantq, wantz, n, ilo, ihi, a, lda, b, ldb,alpha, beta, q,& ldq, z, ldz, work, lwork, rwork,info ) return end if ! find out required workspace ! workspace query to stdlib${ii}$_zlaqz2 nw = max( nwr, nmin ) call stdlib${ii}$_zlaqz2( ilschur, ilq, ilz, n, ilo, ihi, nw, a, lda, b, ldb,q, ldq, z, ldz, & n_undeflated, n_deflated, alpha,beta, work, nw, work, nw, work, -1_${ik}$, rwork, rec,& aed_info ) itemp1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! workspace query to stdlib${ii}$_zlaqz3 call stdlib${ii}$_zlaqz3( ilschur, ilq, ilz, n, ilo, ihi, nsr, nbr, alpha,beta, a, lda, b, & ldb, q, ldq, z, ldz, work, nbr,work, nbr, work, -1_${ik}$, sweep_info ) itemp2 = int( work( 1_${ik}$ ),KIND=${ik}$) lworkreq = max( itemp1+2*nw**2_${ik}$, itemp2+2*nbr**2_${ik}$ ) if ( lwork ==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lworkreq,KIND=dp) return else if ( lwork < lworkreq ) then info = -19_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLAQZ0', info ) return end if ! initialize q and z if( iwantq==3_${ik}$ ) call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, q,ldq ) if( iwantz==3_${ik}$ ) call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, z,ldz ) ! get machine constants safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=dp)/ulp ) istart = ilo istop = ihi maxit = 30_${ik}$*( ihi-ilo+1 ) ld = 0_${ik}$ do iiter = 1, maxit if( iiter >= maxit ) then info = istop+1 goto 80 end if if ( istart+1 >= istop ) then istop = istart exit end if ! check deflations at the end if ( abs( a( istop, istop-1 ) ) <= max( smlnum,ulp*( abs( a( istop, istop ) )+abs( & a( istop-1,istop-1 ) ) ) ) ) then a( istop, istop-1 ) = czero istop = istop-1 ld = 0_${ik}$ eshift = czero end if ! check deflations at the start if ( abs( a( istart+1, istart ) ) <= max( smlnum,ulp*( abs( a( istart, istart ) )+& abs( a( istart+1,istart+1 ) ) ) ) ) then a( istart+1, istart ) = czero istart = istart+1 ld = 0_${ik}$ eshift = czero end if if ( istart+1 >= istop ) then exit end if ! check interior deflations istart2 = istart do k = istop, istart+1, -1 if ( abs( a( k, k-1 ) ) <= max( smlnum, ulp*( abs( a( k,k ) )+abs( a( k-1, k-1 ) & ) ) ) ) then a( k, k-1 ) = czero istart2 = k exit end if end do ! get range to apply rotations to if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = istart2 istopm = istop end if ! check infinite eigenvalues, this is done without blocking so might ! slow down the method when many infinite eigenvalues are present k = istop do while ( k>=istart2 ) tempr = zero if( k < istop ) then tempr = tempr+abs( b( k, k+1 ) ) end if if( k > istart2 ) then tempr = tempr+abs( b( k-1, k ) ) end if if( abs( b( k, k ) ) < max( smlnum, ulp*tempr ) ) then ! a diagonal element of b is negligable, move it ! to the top and deflate it do k2 = k, istart2+1, -1 call stdlib${ii}$_zlartg( b( k2-1, k2 ), b( k2-1, k2-1 ), c1, s1,temp ) b( k2-1, k2 ) = temp b( k2-1, k2-1 ) = czero call stdlib${ii}$_zrot( k2-2-istartm+1, b( istartm, k2 ), 1_${ik}$,b( istartm, k2-1 ), & 1_${ik}$, c1, s1 ) call stdlib${ii}$_zrot( min( k2+1, istop )-istartm+1, a( istartm,k2 ), 1_${ik}$, a( & istartm, k2-1 ), 1_${ik}$, c1, s1 ) if ( ilz ) then call stdlib${ii}$_zrot( n, z( 1_${ik}$, k2 ), 1_${ik}$, z( 1_${ik}$, k2-1 ), 1_${ik}$, c1,s1 ) end if if( k2= istop ) then istop = istart2-1 ld = 0_${ik}$ eshift = czero cycle end if nw = nwr nshifts = nsr nblock = nbr if ( istop-istart2+1 < nmin ) then ! setting nw to the size of the subblock will make aed deflate ! all the eigenvalues. this is slightly more efficient than just ! using qz_small because the off diagonal part gets updated via blas. if ( istop-istart+1 < nmin ) then nw = istop-istart+1 istart2 = istart else nw = istop-istart2+1 end if end if ! time for aed call stdlib${ii}$_zlaqz2( ilschur, ilq, ilz, n, istart2, istop, nw, a, lda,b, ldb, q, ldq,& z, ldz, n_undeflated, n_deflated,alpha, beta, work, nw, work( nw**2_${ik}$+1 ), nw,work( & 2_${ik}$*nw**2_${ik}$+1 ), lwork-2*nw**2_${ik}$, rwork, rec,aed_info ) if ( n_deflated > 0_${ik}$ ) then istop = istop-n_deflated ld = 0_${ik}$ eshift = czero end if if ( 100_${ik}$*n_deflated > nibble*( n_deflated+n_undeflated ) .or.istop-istart2+1 < nmin & ) then ! aed has uncovered many eigenvalues. skip a qz sweep and run ! aed again. cycle end if ld = ld+1 ns = min( nshifts, istop-istart2 ) ns = min( ns, n_undeflated ) shiftpos = istop-n_deflated-n_undeflated+1 if ( mod( ld, 6_${ik}$ ) == 0_${ik}$ ) then ! exceptional shift. chosen for no particularly good reason. if( ( real( maxit,KIND=dp)*safmin )*abs( a( istop,istop-1 ) )n .or. ihi= 2_${ik}$ ) then call stdlib${ii}$_${ci}$hgeqz( wants, wantq, wantz, n, ilo, ihi, a, lda, b, ldb,alpha, beta, q,& ldq, z, ldz, work, lwork, rwork,info ) return end if ! find out required workspace ! workspace query to stdlib${ii}$_${ci}$laqz2 nw = max( nwr, nmin ) call stdlib${ii}$_${ci}$laqz2( ilschur, ilq, ilz, n, ilo, ihi, nw, a, lda, b, ldb,q, ldq, z, ldz, & n_undeflated, n_qeflated, alpha,beta, work, nw, work, nw, work, -1_${ik}$, rwork, rec,& aed_info ) itemp1 = int( work( 1_${ik}$ ),KIND=${ik}$) ! workspace query to stdlib${ii}$_${ci}$laqz3 call stdlib${ii}$_${ci}$laqz3( ilschur, ilq, ilz, n, ilo, ihi, nsr, nbr, alpha,beta, a, lda, b, & ldb, q, ldq, z, ldz, work, nbr,work, nbr, work, -1_${ik}$, sweep_info ) itemp2 = int( work( 1_${ik}$ ),KIND=${ik}$) lworkreq = max( itemp1+2*nw**2_${ik}$, itemp2+2*nbr**2_${ik}$ ) if ( lwork ==-1_${ik}$ ) then work( 1_${ik}$ ) = real( lworkreq,KIND=${ck}$) return else if ( lwork < lworkreq ) then info = -19_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLAQZ0', info ) return end if ! initialize q and z if( iwantq==3_${ik}$ ) call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, q,ldq ) if( iwantz==3_${ik}$ ) call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, z,ldz ) ! get machine constants safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_${c2ri(ci)}$labad( safmin, safmax ) ulp = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=${ck}$)/ulp ) istart = ilo istop = ihi maxit = 30_${ik}$*( ihi-ilo+1 ) ld = 0_${ik}$ do iiter = 1, maxit if( iiter >= maxit ) then info = istop+1 goto 80 end if if ( istart+1 >= istop ) then istop = istart exit end if ! check deflations at the end if ( abs( a( istop, istop-1 ) ) <= max( smlnum,ulp*( abs( a( istop, istop ) )+abs( & a( istop-1,istop-1 ) ) ) ) ) then a( istop, istop-1 ) = czero istop = istop-1 ld = 0_${ik}$ eshift = czero end if ! check deflations at the start if ( abs( a( istart+1, istart ) ) <= max( smlnum,ulp*( abs( a( istart, istart ) )+& abs( a( istart+1,istart+1 ) ) ) ) ) then a( istart+1, istart ) = czero istart = istart+1 ld = 0_${ik}$ eshift = czero end if if ( istart+1 >= istop ) then exit end if ! check interior deflations istart2 = istart do k = istop, istart+1, -1 if ( abs( a( k, k-1 ) ) <= max( smlnum, ulp*( abs( a( k,k ) )+abs( a( k-1, k-1 ) & ) ) ) ) then a( k, k-1 ) = czero istart2 = k exit end if end do ! get range to apply rotations to if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = istart2 istopm = istop end if ! check infinite eigenvalues, this is done without blocking so might ! slow down the method when many infinite eigenvalues are present k = istop do while ( k>=istart2 ) tempr = zero if( k < istop ) then tempr = tempr+abs( b( k, k+1 ) ) end if if( k > istart2 ) then tempr = tempr+abs( b( k-1, k ) ) end if if( abs( b( k, k ) ) < max( smlnum, ulp*tempr ) ) then ! a diagonal element of b is negligable, move it ! to the top and deflate it do k2 = k, istart2+1, -1 call stdlib${ii}$_${ci}$lartg( b( k2-1, k2 ), b( k2-1, k2-1 ), c1, s1,temp ) b( k2-1, k2 ) = temp b( k2-1, k2-1 ) = czero call stdlib${ii}$_${ci}$rot( k2-2-istartm+1, b( istartm, k2 ), 1_${ik}$,b( istartm, k2-1 ), & 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ci}$rot( min( k2+1, istop )-istartm+1, a( istartm,k2 ), 1_${ik}$, a( & istartm, k2-1 ), 1_${ik}$, c1, s1 ) if ( ilz ) then call stdlib${ii}$_${ci}$rot( n, z( 1_${ik}$, k2 ), 1_${ik}$, z( 1_${ik}$, k2-1 ), 1_${ik}$, c1,s1 ) end if if( k2= istop ) then istop = istart2-1 ld = 0_${ik}$ eshift = czero cycle end if nw = nwr nshifts = nsr nblock = nbr if ( istop-istart2+1 < nmin ) then ! setting nw to the size of the subblock will make aed deflate ! all the eigenvalues. this is slightly more efficient than just ! using qz_small because the off diagonal part gets updated via blas. if ( istop-istart+1 < nmin ) then nw = istop-istart+1 istart2 = istart else nw = istop-istart2+1 end if end if ! time for aed call stdlib${ii}$_${ci}$laqz2( ilschur, ilq, ilz, n, istart2, istop, nw, a, lda,b, ldb, q, ldq,& z, ldz, n_undeflated, n_qeflated,alpha, beta, work, nw, work( nw**2_${ik}$+1 ), nw,work( & 2_${ik}$*nw**2_${ik}$+1 ), lwork-2*nw**2_${ik}$, rwork, rec,aed_info ) if ( n_qeflated > 0_${ik}$ ) then istop = istop-n_qeflated ld = 0_${ik}$ eshift = czero end if if ( 100_${ik}$*n_qeflated > nibble*( n_qeflated+n_undeflated ) .or.istop-istart2+1 < nmin & ) then ! aed has uncovered many eigenvalues. skip a qz sweep and run ! aed again. cycle end if ld = ld+1 ns = min( nshifts, istop-istart2 ) ns = min( ns, n_undeflated ) shiftpos = istop-n_qeflated-n_undeflated+1 if ( mod( ld, 6_${ik}$ ) == 0_${ik}$ ) then ! exceptional shift. chosen for no particularly good reason. if( ( real( maxit,KIND=${ck}$)*safmin )*abs( a( istop,istop-1 ) )= safmin .and. scale1 <= safmax ) then w( 1_${ik}$ ) = w( 1_${ik}$ )/scale1 w( 2_${ik}$ ) = w( 2_${ik}$ )/scale1 end if ! solve linear system w( 2_${ik}$ ) = w( 2_${ik}$ )/b( 2_${ik}$, 2_${ik}$ ) w( 1_${ik}$ ) = ( w( 1_${ik}$ )-b( 1_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )/b( 1_${ik}$, 1_${ik}$ ) scale2 = sqrt( abs( w( 1_${ik}$ ) ) ) * sqrt( abs( w( 2_${ik}$ ) ) ) if( scale2 >= safmin .and. scale2 <= safmax ) then w( 1_${ik}$ ) = w( 1_${ik}$ )/scale2 w( 2_${ik}$ ) = w( 2_${ik}$ )/scale2 end if ! apply second shift v( 1_${ik}$ ) = beta2*( a( 1_${ik}$, 1_${ik}$ )*w( 1_${ik}$ )+a( 1_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )-sr2*( b( 1_${ik}$,1_${ik}$ )*w( 1_${ik}$ )+b( 1_${ik}$, 2_${ik}$ )*w(& 2_${ik}$ ) ) v( 2_${ik}$ ) = beta2*( a( 2_${ik}$, 1_${ik}$ )*w( 1_${ik}$ )+a( 2_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )-sr2*( b( 2_${ik}$,1_${ik}$ )*w( 1_${ik}$ )+b( 2_${ik}$, 2_${ik}$ )*w(& 2_${ik}$ ) ) v( 3_${ik}$ ) = beta2*( a( 3_${ik}$, 1_${ik}$ )*w( 1_${ik}$ )+a( 3_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )-sr2*( b( 3_${ik}$,1_${ik}$ )*w( 1_${ik}$ )+b( 3_${ik}$, 2_${ik}$ )*w(& 2_${ik}$ ) ) ! account for imaginary part v( 1_${ik}$ ) = v( 1_${ik}$ )+si*si*b( 1_${ik}$, 1_${ik}$ )/scale1/scale2 ! check for overflow if( abs( v( 1_${ik}$ ) )>safmax .or. abs( v( 2_${ik}$ ) ) > safmax .or.abs( v( 3_${ik}$ ) )>safmax .or. & stdlib${ii}$_sisnan( v( 1_${ik}$ ) ) .or.stdlib${ii}$_sisnan( v( 2_${ik}$ ) ) .or. stdlib${ii}$_sisnan( v( 3_${ik}$ ) ) ) & then v( 1_${ik}$ ) = zero v( 2_${ik}$ ) = zero v( 3_${ik}$ ) = zero end if end subroutine stdlib${ii}$_slaqz1 pure module subroutine stdlib${ii}$_dlaqz1( a, lda, b, ldb, sr1, sr2, si, beta1, beta2,v ) !! Given a 3-by-3 matrix pencil (A,B), DLAQZ1: sets v to a !! scalar multiple of the first column of the product !! (*) K = (A - (beta2*sr2 - i*si)*B)*B^(-1)*(beta1*A - (sr2 + i*si2)*B)*B^(-1). !! It is assumed that either !! 1) sr1 = sr2 !! or !! 2) si = 0. !! This is useful for starting double implicit shift bulges !! in the QZ algorithm. use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments integer(${ik}$), intent( in ) :: lda, ldb real(dp), intent( in ) :: a( lda, * ), b( ldb, * ), sr1,sr2, si, beta1, beta2 real(dp), intent( out ) :: v( * ) ! ================================================================ ! local scalars real(dp) :: w(2_${ik}$), safmin, safmax, scale1, scale2 safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one/safmin ! calculate first shifted vector w( 1_${ik}$ ) = beta1*a( 1_${ik}$, 1_${ik}$ )-sr1*b( 1_${ik}$, 1_${ik}$ ) w( 2_${ik}$ ) = beta1*a( 2_${ik}$, 1_${ik}$ )-sr1*b( 2_${ik}$, 1_${ik}$ ) scale1 = sqrt( abs( w( 1_${ik}$ ) ) ) * sqrt( abs( w( 2_${ik}$ ) ) ) if( scale1 >= safmin .and. scale1 <= safmax ) then w( 1_${ik}$ ) = w( 1_${ik}$ )/scale1 w( 2_${ik}$ ) = w( 2_${ik}$ )/scale1 end if ! solve linear system w( 2_${ik}$ ) = w( 2_${ik}$ )/b( 2_${ik}$, 2_${ik}$ ) w( 1_${ik}$ ) = ( w( 1_${ik}$ )-b( 1_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )/b( 1_${ik}$, 1_${ik}$ ) scale2 = sqrt( abs( w( 1_${ik}$ ) ) ) * sqrt( abs( w( 2_${ik}$ ) ) ) if( scale2 >= safmin .and. scale2 <= safmax ) then w( 1_${ik}$ ) = w( 1_${ik}$ )/scale2 w( 2_${ik}$ ) = w( 2_${ik}$ )/scale2 end if ! apply second shift v( 1_${ik}$ ) = beta2*( a( 1_${ik}$, 1_${ik}$ )*w( 1_${ik}$ )+a( 1_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )-sr2*( b( 1_${ik}$,1_${ik}$ )*w( 1_${ik}$ )+b( 1_${ik}$, 2_${ik}$ )*w(& 2_${ik}$ ) ) v( 2_${ik}$ ) = beta2*( a( 2_${ik}$, 1_${ik}$ )*w( 1_${ik}$ )+a( 2_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )-sr2*( b( 2_${ik}$,1_${ik}$ )*w( 1_${ik}$ )+b( 2_${ik}$, 2_${ik}$ )*w(& 2_${ik}$ ) ) v( 3_${ik}$ ) = beta2*( a( 3_${ik}$, 1_${ik}$ )*w( 1_${ik}$ )+a( 3_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )-sr2*( b( 3_${ik}$,1_${ik}$ )*w( 1_${ik}$ )+b( 3_${ik}$, 2_${ik}$ )*w(& 2_${ik}$ ) ) ! account for imaginary part v( 1_${ik}$ ) = v( 1_${ik}$ )+si*si*b( 1_${ik}$, 1_${ik}$ )/scale1/scale2 ! check for overflow if( abs( v( 1_${ik}$ ) )>safmax .or. abs( v( 2_${ik}$ ) ) > safmax .or.abs( v( 3_${ik}$ ) )>safmax .or. & stdlib${ii}$_disnan( v( 1_${ik}$ ) ) .or.stdlib${ii}$_disnan( v( 2_${ik}$ ) ) .or. stdlib${ii}$_disnan( v( 3_${ik}$ ) ) ) & then v( 1_${ik}$ ) = zero v( 2_${ik}$ ) = zero v( 3_${ik}$ ) = zero end if end subroutine stdlib${ii}$_dlaqz1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqz1( a, lda, b, ldb, sr1, sr2, si, beta1, beta2,v ) !! Given a 3-by-3 matrix pencil (A,B), DLAQZ1: sets v to a !! scalar multiple of the first column of the product !! (*) K = (A - (beta2*sr2 - i*si)*B)*B^(-1)*(beta1*A - (sr2 + i*si2)*B)*B^(-1). !! It is assumed that either !! 1) sr1 = sr2 !! or !! 2) si = 0. !! This is useful for starting double implicit shift bulges !! in the QZ algorithm. use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments integer(${ik}$), intent( in ) :: lda, ldb real(${rk}$), intent( in ) :: a( lda, * ), b( ldb, * ), sr1,sr2, si, beta1, beta2 real(${rk}$), intent( out ) :: v( * ) ! ================================================================ ! local scalars real(${rk}$) :: w(2_${ik}$), safmin, safmax, scale1, scale2 safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) safmax = one/safmin ! calculate first shifted vector w( 1_${ik}$ ) = beta1*a( 1_${ik}$, 1_${ik}$ )-sr1*b( 1_${ik}$, 1_${ik}$ ) w( 2_${ik}$ ) = beta1*a( 2_${ik}$, 1_${ik}$ )-sr1*b( 2_${ik}$, 1_${ik}$ ) scale1 = sqrt( abs( w( 1_${ik}$ ) ) ) * sqrt( abs( w( 2_${ik}$ ) ) ) if( scale1 >= safmin .and. scale1 <= safmax ) then w( 1_${ik}$ ) = w( 1_${ik}$ )/scale1 w( 2_${ik}$ ) = w( 2_${ik}$ )/scale1 end if ! solve linear system w( 2_${ik}$ ) = w( 2_${ik}$ )/b( 2_${ik}$, 2_${ik}$ ) w( 1_${ik}$ ) = ( w( 1_${ik}$ )-b( 1_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )/b( 1_${ik}$, 1_${ik}$ ) scale2 = sqrt( abs( w( 1_${ik}$ ) ) ) * sqrt( abs( w( 2_${ik}$ ) ) ) if( scale2 >= safmin .and. scale2 <= safmax ) then w( 1_${ik}$ ) = w( 1_${ik}$ )/scale2 w( 2_${ik}$ ) = w( 2_${ik}$ )/scale2 end if ! apply second shift v( 1_${ik}$ ) = beta2*( a( 1_${ik}$, 1_${ik}$ )*w( 1_${ik}$ )+a( 1_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )-sr2*( b( 1_${ik}$,1_${ik}$ )*w( 1_${ik}$ )+b( 1_${ik}$, 2_${ik}$ )*w(& 2_${ik}$ ) ) v( 2_${ik}$ ) = beta2*( a( 2_${ik}$, 1_${ik}$ )*w( 1_${ik}$ )+a( 2_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )-sr2*( b( 2_${ik}$,1_${ik}$ )*w( 1_${ik}$ )+b( 2_${ik}$, 2_${ik}$ )*w(& 2_${ik}$ ) ) v( 3_${ik}$ ) = beta2*( a( 3_${ik}$, 1_${ik}$ )*w( 1_${ik}$ )+a( 3_${ik}$, 2_${ik}$ )*w( 2_${ik}$ ) )-sr2*( b( 3_${ik}$,1_${ik}$ )*w( 1_${ik}$ )+b( 3_${ik}$, 2_${ik}$ )*w(& 2_${ik}$ ) ) ! account for imaginary part v( 1_${ik}$ ) = v( 1_${ik}$ )+si*si*b( 1_${ik}$, 1_${ik}$ )/scale1/scale2 ! check for overflow if( abs( v( 1_${ik}$ ) )>safmax .or. abs( v( 2_${ik}$ ) ) > safmax .or.abs( v( 3_${ik}$ ) )>safmax .or. & stdlib${ii}$_${ri}$isnan( v( 1_${ik}$ ) ) .or.stdlib${ii}$_${ri}$isnan( v( 2_${ik}$ ) ) .or. stdlib${ii}$_${ri}$isnan( v( 3_${ik}$ ) ) ) & then v( 1_${ik}$ ) = zero v( 2_${ik}$ ) = zero v( 3_${ik}$ ) = zero end if end subroutine stdlib${ii}$_${ri}$laqz1 #:endif #:endfor pure module subroutine stdlib${ii}$_claqz1( ilq, ilz, k, istartm, istopm, ihi, a, lda, b,ldb, nq, qstart, & !! CLAQZ1 chases a 1x1 shift bulge in a matrix pencil down a single position q, ldq, nz, zstart, z, ldz ) use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilq, ilz integer(${ik}$), intent( in ) :: k, lda, ldb, ldq, ldz, istartm, istopm,nq, nz, qstart, & zstart, ihi complex(sp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ================================================================ ! local variables real(sp) :: c complex(sp) :: s, temp if( k+1 == ihi ) then ! shift is located on the edge of the matrix, remove it call stdlib${ii}$_clartg( b( ihi, ihi ), b( ihi, ihi-1 ), c, s, temp ) b( ihi, ihi ) = temp b( ihi, ihi-1 ) = czero call stdlib${ii}$_crot( ihi-istartm, b( istartm, ihi ), 1_${ik}$, b( istartm,ihi-1 ), 1_${ik}$, c, s ) call stdlib${ii}$_crot( ihi-istartm+1, a( istartm, ihi ), 1_${ik}$, a( istartm,ihi-1 ), 1_${ik}$, c, s ) if ( ilz ) then call stdlib${ii}$_crot( nz, z( 1_${ik}$, ihi-zstart+1 ), 1_${ik}$, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, c, s ) end if else ! normal operation, move bulge down ! apply transformation from the right call stdlib${ii}$_clartg( b( k+1, k+1 ), b( k+1, k ), c, s, temp ) b( k+1, k+1 ) = temp b( k+1, k ) = czero call stdlib${ii}$_crot( k+2-istartm+1, a( istartm, k+1 ), 1_${ik}$, a( istartm,k ), 1_${ik}$, c, s ) call stdlib${ii}$_crot( k-istartm+1, b( istartm, k+1 ), 1_${ik}$, b( istartm, k ),1_${ik}$, c, s ) if ( ilz ) then call stdlib${ii}$_crot( nz, z( 1_${ik}$, k+1-zstart+1 ), 1_${ik}$, z( 1_${ik}$, k-zstart+1 ),1_${ik}$, c, s ) end if ! apply transformation from the left call stdlib${ii}$_clartg( a( k+1, k ), a( k+2, k ), c, s, temp ) a( k+1, k ) = temp a( k+2, k ) = czero call stdlib${ii}$_crot( istopm-k, a( k+1, k+1 ), lda, a( k+2, k+1 ), lda, c,s ) call stdlib${ii}$_crot( istopm-k, b( k+1, k+1 ), ldb, b( k+2, k+1 ), ldb, c,s ) if ( ilq ) then call stdlib${ii}$_crot( nq, q( 1_${ik}$, k+1-qstart+1 ), 1_${ik}$, q( 1_${ik}$, k+2-qstart+1 ), 1_${ik}$, c, conjg(& s ) ) end if end if end subroutine stdlib${ii}$_claqz1 pure module subroutine stdlib${ii}$_zlaqz1( ilq, ilz, k, istartm, istopm, ihi, a, lda, b,ldb, nq, qstart, & !! ZLAQZ1 chases a 1x1 shift bulge in a matrix pencil down a single position q, ldq, nz, zstart, z, ldz ) use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilq, ilz integer(${ik}$), intent( in ) :: k, lda, ldb, ldq, ldz, istartm, istopm,nq, nz, qstart, & zstart, ihi complex(dp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ================================================================ ! local variables real(dp) :: c complex(dp) :: s, temp if( k+1 == ihi ) then ! shift is located on the edge of the matrix, remove it call stdlib${ii}$_zlartg( b( ihi, ihi ), b( ihi, ihi-1 ), c, s, temp ) b( ihi, ihi ) = temp b( ihi, ihi-1 ) = czero call stdlib${ii}$_zrot( ihi-istartm, b( istartm, ihi ), 1_${ik}$, b( istartm,ihi-1 ), 1_${ik}$, c, s ) call stdlib${ii}$_zrot( ihi-istartm+1, a( istartm, ihi ), 1_${ik}$, a( istartm,ihi-1 ), 1_${ik}$, c, s ) if ( ilz ) then call stdlib${ii}$_zrot( nz, z( 1_${ik}$, ihi-zstart+1 ), 1_${ik}$, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, c, s ) end if else ! normal operation, move bulge down ! apply transformation from the right call stdlib${ii}$_zlartg( b( k+1, k+1 ), b( k+1, k ), c, s, temp ) b( k+1, k+1 ) = temp b( k+1, k ) = czero call stdlib${ii}$_zrot( k+2-istartm+1, a( istartm, k+1 ), 1_${ik}$, a( istartm,k ), 1_${ik}$, c, s ) call stdlib${ii}$_zrot( k-istartm+1, b( istartm, k+1 ), 1_${ik}$, b( istartm, k ),1_${ik}$, c, s ) if ( ilz ) then call stdlib${ii}$_zrot( nz, z( 1_${ik}$, k+1-zstart+1 ), 1_${ik}$, z( 1_${ik}$, k-zstart+1 ),1_${ik}$, c, s ) end if ! apply transformation from the left call stdlib${ii}$_zlartg( a( k+1, k ), a( k+2, k ), c, s, temp ) a( k+1, k ) = temp a( k+2, k ) = czero call stdlib${ii}$_zrot( istopm-k, a( k+1, k+1 ), lda, a( k+2, k+1 ), lda, c,s ) call stdlib${ii}$_zrot( istopm-k, b( k+1, k+1 ), ldb, b( k+2, k+1 ), ldb, c,s ) if ( ilq ) then call stdlib${ii}$_zrot( nq, q( 1_${ik}$, k+1-qstart+1 ), 1_${ik}$, q( 1_${ik}$, k+2-qstart+1 ), 1_${ik}$, c, conjg(& s ) ) end if end if end subroutine stdlib${ii}$_zlaqz1 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqz1( ilq, ilz, k, istartm, istopm, ihi, a, lda, b,ldb, nq, qstart, & !! ZLAQZ1: chases a 1x1 shift bulge in a matrix pencil down a single position q, ldq, nz, zstart, z, ldz ) use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilq, ilz integer(${ik}$), intent( in ) :: k, lda, ldb, ldq, ldz, istartm, istopm,nq, nz, qstart, & zstart, ihi complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ================================================================ ! local variables real(${ck}$) :: c complex(${ck}$) :: s, temp if( k+1 == ihi ) then ! shift is located on the edge of the matrix, remove it call stdlib${ii}$_${ci}$lartg( b( ihi, ihi ), b( ihi, ihi-1 ), c, s, temp ) b( ihi, ihi ) = temp b( ihi, ihi-1 ) = czero call stdlib${ii}$_${ci}$rot( ihi-istartm, b( istartm, ihi ), 1_${ik}$, b( istartm,ihi-1 ), 1_${ik}$, c, s ) call stdlib${ii}$_${ci}$rot( ihi-istartm+1, a( istartm, ihi ), 1_${ik}$, a( istartm,ihi-1 ), 1_${ik}$, c, s ) if ( ilz ) then call stdlib${ii}$_${ci}$rot( nz, z( 1_${ik}$, ihi-zstart+1 ), 1_${ik}$, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, c, s ) end if else ! normal operation, move bulge down ! apply transformation from the right call stdlib${ii}$_${ci}$lartg( b( k+1, k+1 ), b( k+1, k ), c, s, temp ) b( k+1, k+1 ) = temp b( k+1, k ) = czero call stdlib${ii}$_${ci}$rot( k+2-istartm+1, a( istartm, k+1 ), 1_${ik}$, a( istartm,k ), 1_${ik}$, c, s ) call stdlib${ii}$_${ci}$rot( k-istartm+1, b( istartm, k+1 ), 1_${ik}$, b( istartm, k ),1_${ik}$, c, s ) if ( ilz ) then call stdlib${ii}$_${ci}$rot( nz, z( 1_${ik}$, k+1-zstart+1 ), 1_${ik}$, z( 1_${ik}$, k-zstart+1 ),1_${ik}$, c, s ) end if ! apply transformation from the left call stdlib${ii}$_${ci}$lartg( a( k+1, k ), a( k+2, k ), c, s, temp ) a( k+1, k ) = temp a( k+2, k ) = czero call stdlib${ii}$_${ci}$rot( istopm-k, a( k+1, k+1 ), lda, a( k+2, k+1 ), lda, c,s ) call stdlib${ii}$_${ci}$rot( istopm-k, b( k+1, k+1 ), ldb, b( k+2, k+1 ), ldb, c,s ) if ( ilq ) then call stdlib${ii}$_${ci}$rot( nq, q( 1_${ik}$, k+1-qstart+1 ), 1_${ik}$, q( 1_${ik}$, k+2-qstart+1 ), 1_${ik}$, c, conjg(& s ) ) end if end if end subroutine stdlib${ii}$_${ci}$laqz1 #:endif #:endfor pure module subroutine stdlib${ii}$_slaqz2( ilq, ilz, k, istartm, istopm, ihi, a, lda, b,ldb, nq, qstart, & !! SLAQZ2 chases a 2x2 shift bulge in a matrix pencil down a single position q, ldq, nz, zstart, z, ldz ) use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilq, ilz integer(${ik}$), intent( in ) :: k, lda, ldb, ldq, ldz, istartm, istopm,nq, nz, qstart, & zstart, ihi real(sp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ================================================================ ! local variables real(sp) :: h(2_${ik}$,3_${ik}$), c1, s1, c2, s2, temp if( k+2 == ihi ) then ! shift is located on the edge of the matrix, remove it h = b( ihi-1:ihi, ihi-2:ihi ) ! make h upper triangular call stdlib${ii}$_slartg( h( 1_${ik}$, 1_${ik}$ ), h( 2_${ik}$, 1_${ik}$ ), c1, s1, temp ) h( 2_${ik}$, 1_${ik}$ ) = zero h( 1_${ik}$, 1_${ik}$ ) = temp call stdlib${ii}$_srot( 2_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 2_${ik}$, h( 2_${ik}$, 2_${ik}$ ), 2_${ik}$, c1, s1 ) call stdlib${ii}$_slartg( h( 2_${ik}$, 3_${ik}$ ), h( 2_${ik}$, 2_${ik}$ ), c1, s1, temp ) call stdlib${ii}$_srot( 1_${ik}$, h( 1_${ik}$, 3_${ik}$ ), 1_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_slartg( h( 1_${ik}$, 2_${ik}$ ), h( 1_${ik}$, 1_${ik}$ ), c2, s2, temp ) call stdlib${ii}$_srot( ihi-istartm+1, b( istartm, ihi ), 1_${ik}$, b( istartm,ihi-1 ), 1_${ik}$, c1, & s1 ) call stdlib${ii}$_srot( ihi-istartm+1, b( istartm, ihi-1 ), 1_${ik}$, b( istartm,ihi-2 ), 1_${ik}$, c2, & s2 ) b( ihi-1, ihi-2 ) = zero b( ihi, ihi-2 ) = zero call stdlib${ii}$_srot( ihi-istartm+1, a( istartm, ihi ), 1_${ik}$, a( istartm,ihi-1 ), 1_${ik}$, c1, & s1 ) call stdlib${ii}$_srot( ihi-istartm+1, a( istartm, ihi-1 ), 1_${ik}$, a( istartm,ihi-2 ), 1_${ik}$, c2, & s2 ) if ( ilz ) then call stdlib${ii}$_srot( nz, z( 1_${ik}$, ihi-zstart+1 ), 1_${ik}$, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, c1, s1 & ) call stdlib${ii}$_srot( nz, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, z( 1_${ik}$,ihi-2-zstart+1 ), 1_${ik}$, c2, & s2 ) end if call stdlib${ii}$_slartg( a( ihi-1, ihi-2 ), a( ihi, ihi-2 ), c1, s1,temp ) a( ihi-1, ihi-2 ) = temp a( ihi, ihi-2 ) = zero call stdlib${ii}$_srot( istopm-ihi+2, a( ihi-1, ihi-1 ), lda, a( ihi,ihi-1 ), lda, c1, s1 & ) call stdlib${ii}$_srot( istopm-ihi+2, b( ihi-1, ihi-1 ), ldb, b( ihi,ihi-1 ), ldb, c1, s1 & ) if ( ilq ) then call stdlib${ii}$_srot( nq, q( 1_${ik}$, ihi-1-qstart+1 ), 1_${ik}$, q( 1_${ik}$, ihi-qstart+1 ), 1_${ik}$, c1, s1 & ) end if call stdlib${ii}$_slartg( b( ihi, ihi ), b( ihi, ihi-1 ), c1, s1, temp ) b( ihi, ihi ) = temp b( ihi, ihi-1 ) = zero call stdlib${ii}$_srot( ihi-istartm, b( istartm, ihi ), 1_${ik}$, b( istartm,ihi-1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_srot( ihi-istartm+1, a( istartm, ihi ), 1_${ik}$, a( istartm,ihi-1 ), 1_${ik}$, c1, & s1 ) if ( ilz ) then call stdlib${ii}$_srot( nz, z( 1_${ik}$, ihi-zstart+1 ), 1_${ik}$, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, c1, s1 & ) end if else ! normal operation, move bulge down h = b( k+1:k+2, k:k+2 ) ! make h upper triangular call stdlib${ii}$_slartg( h( 1_${ik}$, 1_${ik}$ ), h( 2_${ik}$, 1_${ik}$ ), c1, s1, temp ) h( 2_${ik}$, 1_${ik}$ ) = zero h( 1_${ik}$, 1_${ik}$ ) = temp call stdlib${ii}$_srot( 2_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 2_${ik}$, h( 2_${ik}$, 2_${ik}$ ), 2_${ik}$, c1, s1 ) ! calculate z1 and z2 call stdlib${ii}$_slartg( h( 2_${ik}$, 3_${ik}$ ), h( 2_${ik}$, 2_${ik}$ ), c1, s1, temp ) call stdlib${ii}$_srot( 1_${ik}$, h( 1_${ik}$, 3_${ik}$ ), 1_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_slartg( h( 1_${ik}$, 2_${ik}$ ), h( 1_${ik}$, 1_${ik}$ ), c2, s2, temp ) ! apply transformations from the right call stdlib${ii}$_srot( k+3-istartm+1, a( istartm, k+2 ), 1_${ik}$, a( istartm,k+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_srot( k+3-istartm+1, a( istartm, k+1 ), 1_${ik}$, a( istartm,k ), 1_${ik}$, c2, s2 ) call stdlib${ii}$_srot( k+2-istartm+1, b( istartm, k+2 ), 1_${ik}$, b( istartm,k+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_srot( k+2-istartm+1, b( istartm, k+1 ), 1_${ik}$, b( istartm,k ), 1_${ik}$, c2, s2 ) if ( ilz ) then call stdlib${ii}$_srot( nz, z( 1_${ik}$, k+2-zstart+1 ), 1_${ik}$, z( 1_${ik}$, k+1-zstart+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_srot( nz, z( 1_${ik}$, k+1-zstart+1 ), 1_${ik}$, z( 1_${ik}$, k-zstart+1 ),1_${ik}$, c2, s2 ) end if b( k+1, k ) = zero b( k+2, k ) = zero ! calculate q1 and q2 call stdlib${ii}$_slartg( a( k+2, k ), a( k+3, k ), c1, s1, temp ) a( k+2, k ) = temp a( k+3, k ) = zero call stdlib${ii}$_slartg( a( k+1, k ), a( k+2, k ), c2, s2, temp ) a( k+1, k ) = temp a( k+2, k ) = zero ! apply transformations from the left call stdlib${ii}$_srot( istopm-k, a( k+2, k+1 ), lda, a( k+3, k+1 ), lda,c1, s1 ) call stdlib${ii}$_srot( istopm-k, a( k+1, k+1 ), lda, a( k+2, k+1 ), lda,c2, s2 ) call stdlib${ii}$_srot( istopm-k, b( k+2, k+1 ), ldb, b( k+3, k+1 ), ldb,c1, s1 ) call stdlib${ii}$_srot( istopm-k, b( k+1, k+1 ), ldb, b( k+2, k+1 ), ldb,c2, s2 ) if ( ilq ) then call stdlib${ii}$_srot( nq, q( 1_${ik}$, k+2-qstart+1 ), 1_${ik}$, q( 1_${ik}$, k+3-qstart+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_srot( nq, q( 1_${ik}$, k+1-qstart+1 ), 1_${ik}$, q( 1_${ik}$, k+2-qstart+1 ), 1_${ik}$, c2, s2 ) end if end if end subroutine stdlib${ii}$_slaqz2 pure module subroutine stdlib${ii}$_dlaqz2( ilq, ilz, k, istartm, istopm, ihi, a, lda, b,ldb, nq, qstart, & !! DLAQZ2 chases a 2x2 shift bulge in a matrix pencil down a single position q, ldq, nz, zstart, z, ldz ) use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilq, ilz integer(${ik}$), intent( in ) :: k, lda, ldb, ldq, ldz, istartm, istopm,nq, nz, qstart, & zstart, ihi real(dp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ================================================================ ! local variables real(dp) :: h(2_${ik}$,3_${ik}$), c1, s1, c2, s2, temp if( k+2 == ihi ) then ! shift is located on the edge of the matrix, remove it h = b( ihi-1:ihi, ihi-2:ihi ) ! make h upper triangular call stdlib${ii}$_dlartg( h( 1_${ik}$, 1_${ik}$ ), h( 2_${ik}$, 1_${ik}$ ), c1, s1, temp ) h( 2_${ik}$, 1_${ik}$ ) = zero h( 1_${ik}$, 1_${ik}$ ) = temp call stdlib${ii}$_drot( 2_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 2_${ik}$, h( 2_${ik}$, 2_${ik}$ ), 2_${ik}$, c1, s1 ) call stdlib${ii}$_dlartg( h( 2_${ik}$, 3_${ik}$ ), h( 2_${ik}$, 2_${ik}$ ), c1, s1, temp ) call stdlib${ii}$_drot( 1_${ik}$, h( 1_${ik}$, 3_${ik}$ ), 1_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_dlartg( h( 1_${ik}$, 2_${ik}$ ), h( 1_${ik}$, 1_${ik}$ ), c2, s2, temp ) call stdlib${ii}$_drot( ihi-istartm+1, b( istartm, ihi ), 1_${ik}$, b( istartm,ihi-1 ), 1_${ik}$, c1, & s1 ) call stdlib${ii}$_drot( ihi-istartm+1, b( istartm, ihi-1 ), 1_${ik}$, b( istartm,ihi-2 ), 1_${ik}$, c2, & s2 ) b( ihi-1, ihi-2 ) = zero b( ihi, ihi-2 ) = zero call stdlib${ii}$_drot( ihi-istartm+1, a( istartm, ihi ), 1_${ik}$, a( istartm,ihi-1 ), 1_${ik}$, c1, & s1 ) call stdlib${ii}$_drot( ihi-istartm+1, a( istartm, ihi-1 ), 1_${ik}$, a( istartm,ihi-2 ), 1_${ik}$, c2, & s2 ) if ( ilz ) then call stdlib${ii}$_drot( nz, z( 1_${ik}$, ihi-zstart+1 ), 1_${ik}$, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, c1, s1 & ) call stdlib${ii}$_drot( nz, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, z( 1_${ik}$,ihi-2-zstart+1 ), 1_${ik}$, c2, & s2 ) end if call stdlib${ii}$_dlartg( a( ihi-1, ihi-2 ), a( ihi, ihi-2 ), c1, s1,temp ) a( ihi-1, ihi-2 ) = temp a( ihi, ihi-2 ) = zero call stdlib${ii}$_drot( istopm-ihi+2, a( ihi-1, ihi-1 ), lda, a( ihi,ihi-1 ), lda, c1, s1 & ) call stdlib${ii}$_drot( istopm-ihi+2, b( ihi-1, ihi-1 ), ldb, b( ihi,ihi-1 ), ldb, c1, s1 & ) if ( ilq ) then call stdlib${ii}$_drot( nq, q( 1_${ik}$, ihi-1-qstart+1 ), 1_${ik}$, q( 1_${ik}$, ihi-qstart+1 ), 1_${ik}$, c1, s1 & ) end if call stdlib${ii}$_dlartg( b( ihi, ihi ), b( ihi, ihi-1 ), c1, s1, temp ) b( ihi, ihi ) = temp b( ihi, ihi-1 ) = zero call stdlib${ii}$_drot( ihi-istartm, b( istartm, ihi ), 1_${ik}$, b( istartm,ihi-1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_drot( ihi-istartm+1, a( istartm, ihi ), 1_${ik}$, a( istartm,ihi-1 ), 1_${ik}$, c1, & s1 ) if ( ilz ) then call stdlib${ii}$_drot( nz, z( 1_${ik}$, ihi-zstart+1 ), 1_${ik}$, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, c1, s1 & ) end if else ! normal operation, move bulge down h = b( k+1:k+2, k:k+2 ) ! make h upper triangular call stdlib${ii}$_dlartg( h( 1_${ik}$, 1_${ik}$ ), h( 2_${ik}$, 1_${ik}$ ), c1, s1, temp ) h( 2_${ik}$, 1_${ik}$ ) = zero h( 1_${ik}$, 1_${ik}$ ) = temp call stdlib${ii}$_drot( 2_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 2_${ik}$, h( 2_${ik}$, 2_${ik}$ ), 2_${ik}$, c1, s1 ) ! calculate z1 and z2 call stdlib${ii}$_dlartg( h( 2_${ik}$, 3_${ik}$ ), h( 2_${ik}$, 2_${ik}$ ), c1, s1, temp ) call stdlib${ii}$_drot( 1_${ik}$, h( 1_${ik}$, 3_${ik}$ ), 1_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_dlartg( h( 1_${ik}$, 2_${ik}$ ), h( 1_${ik}$, 1_${ik}$ ), c2, s2, temp ) ! apply transformations from the right call stdlib${ii}$_drot( k+3-istartm+1, a( istartm, k+2 ), 1_${ik}$, a( istartm,k+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_drot( k+3-istartm+1, a( istartm, k+1 ), 1_${ik}$, a( istartm,k ), 1_${ik}$, c2, s2 ) call stdlib${ii}$_drot( k+2-istartm+1, b( istartm, k+2 ), 1_${ik}$, b( istartm,k+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_drot( k+2-istartm+1, b( istartm, k+1 ), 1_${ik}$, b( istartm,k ), 1_${ik}$, c2, s2 ) if ( ilz ) then call stdlib${ii}$_drot( nz, z( 1_${ik}$, k+2-zstart+1 ), 1_${ik}$, z( 1_${ik}$, k+1-zstart+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_drot( nz, z( 1_${ik}$, k+1-zstart+1 ), 1_${ik}$, z( 1_${ik}$, k-zstart+1 ),1_${ik}$, c2, s2 ) end if b( k+1, k ) = zero b( k+2, k ) = zero ! calculate q1 and q2 call stdlib${ii}$_dlartg( a( k+2, k ), a( k+3, k ), c1, s1, temp ) a( k+2, k ) = temp a( k+3, k ) = zero call stdlib${ii}$_dlartg( a( k+1, k ), a( k+2, k ), c2, s2, temp ) a( k+1, k ) = temp a( k+2, k ) = zero ! apply transformations from the left call stdlib${ii}$_drot( istopm-k, a( k+2, k+1 ), lda, a( k+3, k+1 ), lda,c1, s1 ) call stdlib${ii}$_drot( istopm-k, a( k+1, k+1 ), lda, a( k+2, k+1 ), lda,c2, s2 ) call stdlib${ii}$_drot( istopm-k, b( k+2, k+1 ), ldb, b( k+3, k+1 ), ldb,c1, s1 ) call stdlib${ii}$_drot( istopm-k, b( k+1, k+1 ), ldb, b( k+2, k+1 ), ldb,c2, s2 ) if ( ilq ) then call stdlib${ii}$_drot( nq, q( 1_${ik}$, k+2-qstart+1 ), 1_${ik}$, q( 1_${ik}$, k+3-qstart+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_drot( nq, q( 1_${ik}$, k+1-qstart+1 ), 1_${ik}$, q( 1_${ik}$, k+2-qstart+1 ), 1_${ik}$, c2, s2 ) end if end if end subroutine stdlib${ii}$_dlaqz2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqz2( ilq, ilz, k, istartm, istopm, ihi, a, lda, b,ldb, nq, qstart, & !! DLAQZ2: chases a 2x2 shift bulge in a matrix pencil down a single position q, ldq, nz, zstart, z, ldz ) use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilq, ilz integer(${ik}$), intent( in ) :: k, lda, ldb, ldq, ldz, istartm, istopm,nq, nz, qstart, & zstart, ihi real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ================================================================ ! local variables real(${rk}$) :: h(2_${ik}$,3_${ik}$), c1, s1, c2, s2, temp if( k+2 == ihi ) then ! shift is located on the edge of the matrix, remove it h = b( ihi-1:ihi, ihi-2:ihi ) ! make h upper triangular call stdlib${ii}$_${ri}$lartg( h( 1_${ik}$, 1_${ik}$ ), h( 2_${ik}$, 1_${ik}$ ), c1, s1, temp ) h( 2_${ik}$, 1_${ik}$ ) = zero h( 1_${ik}$, 1_${ik}$ ) = temp call stdlib${ii}$_${ri}$rot( 2_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 2_${ik}$, h( 2_${ik}$, 2_${ik}$ ), 2_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$lartg( h( 2_${ik}$, 3_${ik}$ ), h( 2_${ik}$, 2_${ik}$ ), c1, s1, temp ) call stdlib${ii}$_${ri}$rot( 1_${ik}$, h( 1_${ik}$, 3_${ik}$ ), 1_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$lartg( h( 1_${ik}$, 2_${ik}$ ), h( 1_${ik}$, 1_${ik}$ ), c2, s2, temp ) call stdlib${ii}$_${ri}$rot( ihi-istartm+1, b( istartm, ihi ), 1_${ik}$, b( istartm,ihi-1 ), 1_${ik}$, c1, & s1 ) call stdlib${ii}$_${ri}$rot( ihi-istartm+1, b( istartm, ihi-1 ), 1_${ik}$, b( istartm,ihi-2 ), 1_${ik}$, c2, & s2 ) b( ihi-1, ihi-2 ) = zero b( ihi, ihi-2 ) = zero call stdlib${ii}$_${ri}$rot( ihi-istartm+1, a( istartm, ihi ), 1_${ik}$, a( istartm,ihi-1 ), 1_${ik}$, c1, & s1 ) call stdlib${ii}$_${ri}$rot( ihi-istartm+1, a( istartm, ihi-1 ), 1_${ik}$, a( istartm,ihi-2 ), 1_${ik}$, c2, & s2 ) if ( ilz ) then call stdlib${ii}$_${ri}$rot( nz, z( 1_${ik}$, ihi-zstart+1 ), 1_${ik}$, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, c1, s1 & ) call stdlib${ii}$_${ri}$rot( nz, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, z( 1_${ik}$,ihi-2-zstart+1 ), 1_${ik}$, c2, & s2 ) end if call stdlib${ii}$_${ri}$lartg( a( ihi-1, ihi-2 ), a( ihi, ihi-2 ), c1, s1,temp ) a( ihi-1, ihi-2 ) = temp a( ihi, ihi-2 ) = zero call stdlib${ii}$_${ri}$rot( istopm-ihi+2, a( ihi-1, ihi-1 ), lda, a( ihi,ihi-1 ), lda, c1, s1 & ) call stdlib${ii}$_${ri}$rot( istopm-ihi+2, b( ihi-1, ihi-1 ), ldb, b( ihi,ihi-1 ), ldb, c1, s1 & ) if ( ilq ) then call stdlib${ii}$_${ri}$rot( nq, q( 1_${ik}$, ihi-1-qstart+1 ), 1_${ik}$, q( 1_${ik}$, ihi-qstart+1 ), 1_${ik}$, c1, s1 & ) end if call stdlib${ii}$_${ri}$lartg( b( ihi, ihi ), b( ihi, ihi-1 ), c1, s1, temp ) b( ihi, ihi ) = temp b( ihi, ihi-1 ) = zero call stdlib${ii}$_${ri}$rot( ihi-istartm, b( istartm, ihi ), 1_${ik}$, b( istartm,ihi-1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$rot( ihi-istartm+1, a( istartm, ihi ), 1_${ik}$, a( istartm,ihi-1 ), 1_${ik}$, c1, & s1 ) if ( ilz ) then call stdlib${ii}$_${ri}$rot( nz, z( 1_${ik}$, ihi-zstart+1 ), 1_${ik}$, z( 1_${ik}$, ihi-1-zstart+1 ), 1_${ik}$, c1, s1 & ) end if else ! normal operation, move bulge down h = b( k+1:k+2, k:k+2 ) ! make h upper triangular call stdlib${ii}$_${ri}$lartg( h( 1_${ik}$, 1_${ik}$ ), h( 2_${ik}$, 1_${ik}$ ), c1, s1, temp ) h( 2_${ik}$, 1_${ik}$ ) = zero h( 1_${ik}$, 1_${ik}$ ) = temp call stdlib${ii}$_${ri}$rot( 2_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 2_${ik}$, h( 2_${ik}$, 2_${ik}$ ), 2_${ik}$, c1, s1 ) ! calculate z1 and z2 call stdlib${ii}$_${ri}$lartg( h( 2_${ik}$, 3_${ik}$ ), h( 2_${ik}$, 2_${ik}$ ), c1, s1, temp ) call stdlib${ii}$_${ri}$rot( 1_${ik}$, h( 1_${ik}$, 3_${ik}$ ), 1_${ik}$, h( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$lartg( h( 1_${ik}$, 2_${ik}$ ), h( 1_${ik}$, 1_${ik}$ ), c2, s2, temp ) ! apply transformations from the right call stdlib${ii}$_${ri}$rot( k+3-istartm+1, a( istartm, k+2 ), 1_${ik}$, a( istartm,k+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$rot( k+3-istartm+1, a( istartm, k+1 ), 1_${ik}$, a( istartm,k ), 1_${ik}$, c2, s2 ) call stdlib${ii}$_${ri}$rot( k+2-istartm+1, b( istartm, k+2 ), 1_${ik}$, b( istartm,k+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$rot( k+2-istartm+1, b( istartm, k+1 ), 1_${ik}$, b( istartm,k ), 1_${ik}$, c2, s2 ) if ( ilz ) then call stdlib${ii}$_${ri}$rot( nz, z( 1_${ik}$, k+2-zstart+1 ), 1_${ik}$, z( 1_${ik}$, k+1-zstart+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$rot( nz, z( 1_${ik}$, k+1-zstart+1 ), 1_${ik}$, z( 1_${ik}$, k-zstart+1 ),1_${ik}$, c2, s2 ) end if b( k+1, k ) = zero b( k+2, k ) = zero ! calculate q1 and q2 call stdlib${ii}$_${ri}$lartg( a( k+2, k ), a( k+3, k ), c1, s1, temp ) a( k+2, k ) = temp a( k+3, k ) = zero call stdlib${ii}$_${ri}$lartg( a( k+1, k ), a( k+2, k ), c2, s2, temp ) a( k+1, k ) = temp a( k+2, k ) = zero ! apply transformations from the left call stdlib${ii}$_${ri}$rot( istopm-k, a( k+2, k+1 ), lda, a( k+3, k+1 ), lda,c1, s1 ) call stdlib${ii}$_${ri}$rot( istopm-k, a( k+1, k+1 ), lda, a( k+2, k+1 ), lda,c2, s2 ) call stdlib${ii}$_${ri}$rot( istopm-k, b( k+2, k+1 ), ldb, b( k+3, k+1 ), ldb,c1, s1 ) call stdlib${ii}$_${ri}$rot( istopm-k, b( k+1, k+1 ), ldb, b( k+2, k+1 ), ldb,c2, s2 ) if ( ilq ) then call stdlib${ii}$_${ri}$rot( nq, q( 1_${ik}$, k+2-qstart+1 ), 1_${ik}$, q( 1_${ik}$, k+3-qstart+1 ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$rot( nq, q( 1_${ik}$, k+1-qstart+1 ), 1_${ik}$, q( 1_${ik}$, k+2-qstart+1 ), 1_${ik}$, c2, s2 ) end if end if end subroutine stdlib${ii}$_${ri}$laqz2 #:endif #:endfor recursive module subroutine stdlib${ii}$_claqz2( ilschur, ilq, ilz, n, ilo, ihi, nw,a, lda, b, ldb, q, & !! CLAQZ2 performs AED ldq, z, ldz, ns,nd, alpha, beta, qc, ldqc, zc, ldzc,work, lwork, rwork, rec, info ) use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, nw, lda, ldb, ldq, ldz,ldqc, ldzc, lwork, & rec complex(sp), intent( inout ) :: a( lda, * ), b( ldb, * ), q( ldq, * ),z( ldz, * ), & alpha( * ), beta( * ) integer(${ik}$), intent( out ) :: ns, nd, info complex(sp), intent(inout) :: qc(ldqc,*), zc(ldzc,*) complex(sp), intent(out) :: work(*) real(sp), intent(out) :: rwork(*) ! ================================================================ ! local scalars integer(${ik}$) :: jw, kwtop, kwbot, istopm, istartm, k, k2, ctgexc_info, ifst, ilst, & lworkreq, qz_small_info real(sp) :: smlnum, ulp, safmin, safmax, c1, tempr complex(sp) :: s, s1, temp info = 0_${ik}$ ! set up deflation window jw = min( nw, ihi-ilo+1 ) kwtop = ihi-jw+1 if ( kwtop == ilo ) then s = czero else s = a( kwtop, kwtop-1 ) end if ! determine required workspace ifst = 1_${ik}$ ilst = jw call stdlib${ii}$_claqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alpha, beta, qc, ldqc, zc,ldzc, work, -1_${ik}$, rwork, rec+1, qz_small_info ) lworkreq = int( work( 1_${ik}$ ),KIND=${ik}$)+2_${ik}$*jw**2_${ik}$ lworkreq = max( lworkreq, n*nw, 2_${ik}$*nw**2_${ik}$+n ) if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = lworkreq return else if ( lwork < lworkreq ) then info = -26_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CLAQZ2', -info ) return end if ! get machine constants safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=sp)/ulp ) if ( ihi == kwtop ) then ! 1 by 1 deflation window, just try a regular deflation alpha( kwtop ) = a( kwtop, kwtop ) beta( kwtop ) = b( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if ( abs( s ) <= max( smlnum, ulp*abs( a( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if ( kwtop > ilo ) then a( kwtop, kwtop-1 ) = czero end if end if end if ! store window in case of convergence failure call stdlib${ii}$_clacpy( 'ALL', jw, jw, a( kwtop, kwtop ), lda, work, jw ) call stdlib${ii}$_clacpy( 'ALL', jw, jw, b( kwtop, kwtop ), ldb, work( jw**2_${ik}$+1 ), jw ) ! transform window to real schur form call stdlib${ii}$_claset( 'FULL', jw, jw, czero, cone, qc, ldqc ) call stdlib${ii}$_claset( 'FULL', jw, jw, czero, cone, zc, ldzc ) call stdlib${ii}$_claqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alpha, beta, qc, ldqc, zc,ldzc, work( 2_${ik}$*jw**2_${ik}$+1 ), lwork-2*jw**2_${ik}$, rwork,rec+1, & qz_small_info ) if( qz_small_info /= 0_${ik}$ ) then ! convergence failure, restore the window and exit nd = 0_${ik}$ ns = jw-qz_small_info call stdlib${ii}$_clacpy( 'ALL', jw, jw, work, jw, a( kwtop, kwtop ), lda ) call stdlib${ii}$_clacpy( 'ALL', jw, jw, work( jw**2_${ik}$+1 ), jw, b( kwtop,kwtop ), ldb ) return end if ! deflation detection loop if ( kwtop == ilo .or. s == czero ) then kwbot = kwtop-1 else kwbot = ihi k = 1_${ik}$ k2 = 1_${ik}$ do while ( k <= jw ) ! try to deflate eigenvalue tempr = abs( a( kwbot, kwbot ) ) if( tempr == zero ) then tempr = abs( s ) end if if ( ( abs( s*qc( 1_${ik}$, kwbot-kwtop+1 ) ) ) <= max( ulp*tempr, smlnum ) ) & then ! deflatable kwbot = kwbot-1 else ! not deflatable, move out of the way ifst = kwbot-kwtop+1 ilst = k2 call stdlib${ii}$_ctgexc( .true., .true., jw, a( kwtop, kwtop ),lda, b( kwtop, & kwtop ), ldb, qc, ldqc,zc, ldzc, ifst, ilst, ctgexc_info ) k2 = k2+1 end if k = k+1 end do end if ! store eigenvalues nd = ihi-kwbot ns = jw-nd k = kwtop do while ( k <= ihi ) alpha( k ) = a( k, k ) beta( k ) = b( k, k ) k = k+1 end do if ( kwtop /= ilo .and. s /= czero ) then ! reflect spike back, this will create optimally packed bulges a( kwtop:kwbot, kwtop-1 ) = a( kwtop, kwtop-1 ) *conjg( qc( 1_${ik}$,1_${ik}$:jw-nd ) ) do k = kwbot-1, kwtop, -1 call stdlib${ii}$_clartg( a( k, kwtop-1 ), a( k+1, kwtop-1 ), c1, s1,temp ) a( k, kwtop-1 ) = temp a( k+1, kwtop-1 ) = czero k2 = max( kwtop, k-1 ) call stdlib${ii}$_crot( ihi-k2+1, a( k, k2 ), lda, a( k+1, k2 ), lda, c1,s1 ) call stdlib${ii}$_crot( ihi-( k-1 )+1_${ik}$, b( k, k-1 ), ldb, b( k+1, k-1 ),ldb, c1, s1 ) call stdlib${ii}$_crot( jw, qc( 1_${ik}$, k-kwtop+1 ), 1_${ik}$, qc( 1_${ik}$, k+1-kwtop+1 ),1_${ik}$, c1, conjg( & s1 ) ) end do ! chase bulges down istartm = kwtop istopm = ihi k = kwbot-1 do while ( k >= kwtop ) ! move bulge down and remove it do k2 = k, kwbot-1 call stdlib${ii}$_claqz1( .true., .true., k2, kwtop, kwtop+jw-1,kwbot, a, lda, b, & ldb, jw, kwtop, qc, ldqc,jw, kwtop, zc, ldzc ) end do k = k-1 end do end if ! apply qc and zc to rest of the matrix if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if if ( istopm-ihi > 0_${ik}$ ) then call stdlib${ii}$_cgemm( 'C', 'N', jw, istopm-ihi, jw, cone, qc, ldqc,a( kwtop, ihi+1 ), & lda, czero, work, jw ) call stdlib${ii}$_clacpy( 'ALL', jw, istopm-ihi, work, jw, a( kwtop,ihi+1 ), lda ) call stdlib${ii}$_cgemm( 'C', 'N', jw, istopm-ihi, jw, cone, qc, ldqc,b( kwtop, ihi+1 ), & ldb, czero, work, jw ) call stdlib${ii}$_clacpy( 'ALL', jw, istopm-ihi, work, jw, b( kwtop,ihi+1 ), ldb ) end if if ( ilq ) then call stdlib${ii}$_cgemm( 'N', 'N', n, jw, jw, cone, q( 1_${ik}$, kwtop ), ldq, qc,ldqc, czero, & work, n ) call stdlib${ii}$_clacpy( 'ALL', n, jw, work, n, q( 1_${ik}$, kwtop ), ldq ) end if if ( kwtop-1-istartm+1 > 0_${ik}$ ) then call stdlib${ii}$_cgemm( 'N', 'N', kwtop-istartm, jw, jw, cone, a( istartm,kwtop ), lda, & zc, ldzc, czero, work,kwtop-istartm ) call stdlib${ii}$_clacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,a( istartm, kwtop )& , lda ) call stdlib${ii}$_cgemm( 'N', 'N', kwtop-istartm, jw, jw, cone, b( istartm,kwtop ), ldb, & zc, ldzc, czero, work,kwtop-istartm ) call stdlib${ii}$_clacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,b( istartm, kwtop )& , ldb ) end if if ( ilz ) then call stdlib${ii}$_cgemm( 'N', 'N', n, jw, jw, cone, z( 1_${ik}$, kwtop ), ldz, zc,ldzc, czero, & work, n ) call stdlib${ii}$_clacpy( 'ALL', n, jw, work, n, z( 1_${ik}$, kwtop ), ldz ) end if end subroutine stdlib${ii}$_claqz2 recursive module subroutine stdlib${ii}$_zlaqz2( ilschur, ilq, ilz, n, ilo, ihi, nw,a, lda, b, ldb, q, & !! ZLAQZ2 performs AED ldq, z, ldz, ns,nd, alpha, beta, qc, ldqc, zc, ldzc,work, lwork, rwork, rec, info ) use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, nw, lda, ldb, ldq, ldz,ldqc, ldzc, lwork, & rec complex(dp), intent( inout ) :: a( lda, * ), b( ldb, * ), q( ldq,* ), z( ldz, * ), & alpha( * ), beta( * ) integer(${ik}$), intent( out ) :: ns, nd, info complex(dp), intent(inout) :: qc(ldqc,*), zc(ldzc,*) complex(dp), intent(out) :: work(*) real(dp), intent(out) :: rwork(*) ! ================================================================ ! local scalars integer(${ik}$) :: jw, kwtop, kwbot, istopm, istartm, k, k2, ztgexc_info, ifst, ilst, & lworkreq, qz_small_info real(dp) ::smlnum, ulp, safmin, safmax, c1, tempr complex(dp) :: s, s1, temp info = 0_${ik}$ ! set up deflation window jw = min( nw, ihi-ilo+1 ) kwtop = ihi-jw+1 if ( kwtop == ilo ) then s = czero else s = a( kwtop, kwtop-1 ) end if ! determine required workspace ifst = 1_${ik}$ ilst = jw call stdlib${ii}$_zlaqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alpha, beta, qc, ldqc, zc,ldzc, work, -1_${ik}$, rwork, rec+1, qz_small_info ) lworkreq = int( work( 1_${ik}$ ),KIND=${ik}$)+2_${ik}$*jw**2_${ik}$ lworkreq = max( lworkreq, n*nw, 2_${ik}$*nw**2_${ik}$+n ) if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = lworkreq return else if ( lwork < lworkreq ) then info = -26_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLAQZ2', -info ) return end if ! get machine constants safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=dp)/ulp ) if ( ihi == kwtop ) then ! 1 by 1 deflation window, just try a regular deflation alpha( kwtop ) = a( kwtop, kwtop ) beta( kwtop ) = b( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if ( abs( s ) <= max( smlnum, ulp*abs( a( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if ( kwtop > ilo ) then a( kwtop, kwtop-1 ) = czero end if end if end if ! store window in case of convergence failure call stdlib${ii}$_zlacpy( 'ALL', jw, jw, a( kwtop, kwtop ), lda, work, jw ) call stdlib${ii}$_zlacpy( 'ALL', jw, jw, b( kwtop, kwtop ), ldb, work( jw**2_${ik}$+1 ), jw ) ! transform window to real schur form call stdlib${ii}$_zlaset( 'FULL', jw, jw, czero, cone, qc, ldqc ) call stdlib${ii}$_zlaset( 'FULL', jw, jw, czero, cone, zc, ldzc ) call stdlib${ii}$_zlaqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alpha, beta, qc, ldqc, zc,ldzc, work( 2_${ik}$*jw**2_${ik}$+1 ), lwork-2*jw**2_${ik}$, rwork,rec+1, & qz_small_info ) if( qz_small_info /= 0_${ik}$ ) then ! convergence failure, restore the window and exit nd = 0_${ik}$ ns = jw-qz_small_info call stdlib${ii}$_zlacpy( 'ALL', jw, jw, work, jw, a( kwtop, kwtop ), lda ) call stdlib${ii}$_zlacpy( 'ALL', jw, jw, work( jw**2_${ik}$+1 ), jw, b( kwtop,kwtop ), ldb ) return end if ! deflation detection loop if ( kwtop == ilo .or. s == czero ) then kwbot = kwtop-1 else kwbot = ihi k = 1_${ik}$ k2 = 1_${ik}$ do while ( k <= jw ) ! try to deflate eigenvalue tempr = abs( a( kwbot, kwbot ) ) if( tempr == zero ) then tempr = abs( s ) end if if ( ( abs( s*qc( 1_${ik}$, kwbot-kwtop+1 ) ) ) <= max( ulp*tempr, smlnum ) ) & then ! deflatable kwbot = kwbot-1 else ! not deflatable, move out of the way ifst = kwbot-kwtop+1 ilst = k2 call stdlib${ii}$_ztgexc( .true., .true., jw, a( kwtop, kwtop ),lda, b( kwtop, & kwtop ), ldb, qc, ldqc,zc, ldzc, ifst, ilst, ztgexc_info ) k2 = k2+1 end if k = k+1 end do end if ! store eigenvalues nd = ihi-kwbot ns = jw-nd k = kwtop do while ( k <= ihi ) alpha( k ) = a( k, k ) beta( k ) = b( k, k ) k = k+1 end do if ( kwtop /= ilo .and. s /= czero ) then ! reflect spike back, this will create optimally packed bulges a( kwtop:kwbot, kwtop-1 ) = a( kwtop, kwtop-1 ) *conjg( qc( 1_${ik}$,1_${ik}$:jw-nd ) ) do k = kwbot-1, kwtop, -1 call stdlib${ii}$_zlartg( a( k, kwtop-1 ), a( k+1, kwtop-1 ), c1, s1,temp ) a( k, kwtop-1 ) = temp a( k+1, kwtop-1 ) = czero k2 = max( kwtop, k-1 ) call stdlib${ii}$_zrot( ihi-k2+1, a( k, k2 ), lda, a( k+1, k2 ), lda, c1,s1 ) call stdlib${ii}$_zrot( ihi-( k-1 )+1_${ik}$, b( k, k-1 ), ldb, b( k+1, k-1 ),ldb, c1, s1 ) call stdlib${ii}$_zrot( jw, qc( 1_${ik}$, k-kwtop+1 ), 1_${ik}$, qc( 1_${ik}$, k+1-kwtop+1 ),1_${ik}$, c1, conjg( & s1 ) ) end do ! chase bulges down istartm = kwtop istopm = ihi k = kwbot-1 do while ( k >= kwtop ) ! move bulge down and remove it do k2 = k, kwbot-1 call stdlib${ii}$_zlaqz1( .true., .true., k2, kwtop, kwtop+jw-1,kwbot, a, lda, b, & ldb, jw, kwtop, qc, ldqc,jw, kwtop, zc, ldzc ) end do k = k-1 end do end if ! apply qc and zc to rest of the matrix if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if if ( istopm-ihi > 0_${ik}$ ) then call stdlib${ii}$_zgemm( 'C', 'N', jw, istopm-ihi, jw, cone, qc, ldqc,a( kwtop, ihi+1 ), & lda, czero, work, jw ) call stdlib${ii}$_zlacpy( 'ALL', jw, istopm-ihi, work, jw, a( kwtop,ihi+1 ), lda ) call stdlib${ii}$_zgemm( 'C', 'N', jw, istopm-ihi, jw, cone, qc, ldqc,b( kwtop, ihi+1 ), & ldb, czero, work, jw ) call stdlib${ii}$_zlacpy( 'ALL', jw, istopm-ihi, work, jw, b( kwtop,ihi+1 ), ldb ) end if if ( ilq ) then call stdlib${ii}$_zgemm( 'N', 'N', n, jw, jw, cone, q( 1_${ik}$, kwtop ), ldq, qc,ldqc, czero, & work, n ) call stdlib${ii}$_zlacpy( 'ALL', n, jw, work, n, q( 1_${ik}$, kwtop ), ldq ) end if if ( kwtop-1-istartm+1 > 0_${ik}$ ) then call stdlib${ii}$_zgemm( 'N', 'N', kwtop-istartm, jw, jw, cone, a( istartm,kwtop ), lda, & zc, ldzc, czero, work,kwtop-istartm ) call stdlib${ii}$_zlacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,a( istartm, kwtop )& , lda ) call stdlib${ii}$_zgemm( 'N', 'N', kwtop-istartm, jw, jw, cone, b( istartm,kwtop ), ldb, & zc, ldzc, czero, work,kwtop-istartm ) call stdlib${ii}$_zlacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,b( istartm, kwtop )& , ldb ) end if if ( ilz ) then call stdlib${ii}$_zgemm( 'N', 'N', n, jw, jw, cone, z( 1_${ik}$, kwtop ), ldz, zc,ldzc, czero, & work, n ) call stdlib${ii}$_zlacpy( 'ALL', n, jw, work, n, z( 1_${ik}$, kwtop ), ldz ) end if end subroutine stdlib${ii}$_zlaqz2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] recursive module subroutine stdlib${ii}$_${ci}$laqz2( ilschur, ilq, ilz, n, ilo, ihi, nw,a, lda, b, ldb, q, & !! ZLAQZ2: performs AED ldq, z, ldz, ns,nd, alpha, beta, qc, ldqc, zc, ldzc,work, lwork, rwork, rec, info ) use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, nw, lda, ldb, ldq, ldz,ldqc, ldzc, lwork, & rec complex(${ck}$), intent( inout ) :: a( lda, * ), b( ldb, * ), q( ldq,* ), z( ldz, * ), & alpha( * ), beta( * ) integer(${ik}$), intent( out ) :: ns, nd, info complex(${ck}$), intent(inout) :: qc(ldqc,*), zc(ldzc,*) complex(${ck}$), intent(out) :: work(*) real(${ck}$), intent(out) :: rwork(*) ! ================================================================ ! local scalars integer(${ik}$) :: jw, kwtop, kwbot, istopm, istartm, k, k2, ztgexc_info, ifst, ilst, & lworkreq, qz_small_info real(${ck}$) ::smlnum, ulp, safmin, safmax, c1, tempr complex(${ck}$) :: s, s1, temp info = 0_${ik}$ ! set up deflation window jw = min( nw, ihi-ilo+1 ) kwtop = ihi-jw+1 if ( kwtop == ilo ) then s = czero else s = a( kwtop, kwtop-1 ) end if ! determine required workspace ifst = 1_${ik}$ ilst = jw call stdlib${ii}$_${ci}$laqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alpha, beta, qc, ldqc, zc,ldzc, work, -1_${ik}$, rwork, rec+1, qz_small_info ) lworkreq = int( work( 1_${ik}$ ),KIND=${ik}$)+2_${ik}$*jw**2_${ik}$ lworkreq = max( lworkreq, n*nw, 2_${ik}$*nw**2_${ik}$+n ) if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = lworkreq return else if ( lwork < lworkreq ) then info = -26_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLAQZ2', -info ) return end if ! get machine constants safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_${c2ri(ci)}$labad( safmin, safmax ) ulp = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=${ck}$)/ulp ) if ( ihi == kwtop ) then ! 1 by 1 deflation window, just try a regular deflation alpha( kwtop ) = a( kwtop, kwtop ) beta( kwtop ) = b( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if ( abs( s ) <= max( smlnum, ulp*abs( a( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if ( kwtop > ilo ) then a( kwtop, kwtop-1 ) = czero end if end if end if ! store window in case of convergence failure call stdlib${ii}$_${ci}$lacpy( 'ALL', jw, jw, a( kwtop, kwtop ), lda, work, jw ) call stdlib${ii}$_${ci}$lacpy( 'ALL', jw, jw, b( kwtop, kwtop ), ldb, work( jw**2_${ik}$+1 ), jw ) ! transform window to real schur form call stdlib${ii}$_${ci}$laset( 'FULL', jw, jw, czero, cone, qc, ldqc ) call stdlib${ii}$_${ci}$laset( 'FULL', jw, jw, czero, cone, zc, ldzc ) call stdlib${ii}$_${ci}$laqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alpha, beta, qc, ldqc, zc,ldzc, work( 2_${ik}$*jw**2_${ik}$+1 ), lwork-2*jw**2_${ik}$, rwork,rec+1, & qz_small_info ) if( qz_small_info /= 0_${ik}$ ) then ! convergence failure, restore the window and exit nd = 0_${ik}$ ns = jw-qz_small_info call stdlib${ii}$_${ci}$lacpy( 'ALL', jw, jw, work, jw, a( kwtop, kwtop ), lda ) call stdlib${ii}$_${ci}$lacpy( 'ALL', jw, jw, work( jw**2_${ik}$+1 ), jw, b( kwtop,kwtop ), ldb ) return end if ! deflation detection loop if ( kwtop == ilo .or. s == czero ) then kwbot = kwtop-1 else kwbot = ihi k = 1_${ik}$ k2 = 1_${ik}$ do while ( k <= jw ) ! try to deflate eigenvalue tempr = abs( a( kwbot, kwbot ) ) if( tempr == zero ) then tempr = abs( s ) end if if ( ( abs( s*qc( 1_${ik}$, kwbot-kwtop+1 ) ) ) <= max( ulp*tempr, smlnum ) ) & then ! deflatable kwbot = kwbot-1 else ! not deflatable, move out of the way ifst = kwbot-kwtop+1 ilst = k2 call stdlib${ii}$_${ci}$tgexc( .true., .true., jw, a( kwtop, kwtop ),lda, b( kwtop, & kwtop ), ldb, qc, ldqc,zc, ldzc, ifst, ilst, ztgexc_info ) k2 = k2+1 end if k = k+1 end do end if ! store eigenvalues nd = ihi-kwbot ns = jw-nd k = kwtop do while ( k <= ihi ) alpha( k ) = a( k, k ) beta( k ) = b( k, k ) k = k+1 end do if ( kwtop /= ilo .and. s /= czero ) then ! reflect spike back, this will create optimally packed bulges a( kwtop:kwbot, kwtop-1 ) = a( kwtop, kwtop-1 ) *conjg( qc( 1_${ik}$,1_${ik}$:jw-nd ) ) do k = kwbot-1, kwtop, -1 call stdlib${ii}$_${ci}$lartg( a( k, kwtop-1 ), a( k+1, kwtop-1 ), c1, s1,temp ) a( k, kwtop-1 ) = temp a( k+1, kwtop-1 ) = czero k2 = max( kwtop, k-1 ) call stdlib${ii}$_${ci}$rot( ihi-k2+1, a( k, k2 ), lda, a( k+1, k2 ), lda, c1,s1 ) call stdlib${ii}$_${ci}$rot( ihi-( k-1 )+1_${ik}$, b( k, k-1 ), ldb, b( k+1, k-1 ),ldb, c1, s1 ) call stdlib${ii}$_${ci}$rot( jw, qc( 1_${ik}$, k-kwtop+1 ), 1_${ik}$, qc( 1_${ik}$, k+1-kwtop+1 ),1_${ik}$, c1, conjg( & s1 ) ) end do ! chase bulges down istartm = kwtop istopm = ihi k = kwbot-1 do while ( k >= kwtop ) ! move bulge down and remove it do k2 = k, kwbot-1 call stdlib${ii}$_${ci}$laqz1( .true., .true., k2, kwtop, kwtop+jw-1,kwbot, a, lda, b, & ldb, jw, kwtop, qc, ldqc,jw, kwtop, zc, ldzc ) end do k = k-1 end do end if ! apply qc and zc to rest of the matrix if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if if ( istopm-ihi > 0_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'C', 'N', jw, istopm-ihi, jw, cone, qc, ldqc,a( kwtop, ihi+1 ), & lda, czero, work, jw ) call stdlib${ii}$_${ci}$lacpy( 'ALL', jw, istopm-ihi, work, jw, a( kwtop,ihi+1 ), lda ) call stdlib${ii}$_${ci}$gemm( 'C', 'N', jw, istopm-ihi, jw, cone, qc, ldqc,b( kwtop, ihi+1 ), & ldb, czero, work, jw ) call stdlib${ii}$_${ci}$lacpy( 'ALL', jw, istopm-ihi, work, jw, b( kwtop,ihi+1 ), ldb ) end if if ( ilq ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', n, jw, jw, cone, q( 1_${ik}$, kwtop ), ldq, qc,ldqc, czero, & work, n ) call stdlib${ii}$_${ci}$lacpy( 'ALL', n, jw, work, n, q( 1_${ik}$, kwtop ), ldq ) end if if ( kwtop-1-istartm+1 > 0_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', kwtop-istartm, jw, jw, cone, a( istartm,kwtop ), lda, & zc, ldzc, czero, work,kwtop-istartm ) call stdlib${ii}$_${ci}$lacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,a( istartm, kwtop )& , lda ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', kwtop-istartm, jw, jw, cone, b( istartm,kwtop ), ldb, & zc, ldzc, czero, work,kwtop-istartm ) call stdlib${ii}$_${ci}$lacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,b( istartm, kwtop )& , ldb ) end if if ( ilz ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', n, jw, jw, cone, z( 1_${ik}$, kwtop ), ldz, zc,ldzc, czero, & work, n ) call stdlib${ii}$_${ci}$lacpy( 'ALL', n, jw, work, n, z( 1_${ik}$, kwtop ), ldz ) end if end subroutine stdlib${ii}$_${ci}$laqz2 #:endif #:endfor recursive module subroutine stdlib${ii}$_slaqz3( ilschur, ilq, ilz, n, ilo, ihi, nw,a, lda, b, ldb, q, & !! SLAQZ3 performs AED ldq, z, ldz, ns,nd, alphar, alphai, beta, qc, ldqc,zc, ldzc, work, lwork, rec, info ) use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, nw, lda, ldb, ldq, ldz,ldqc, ldzc, lwork, & rec real(sp), intent( inout ) :: a( lda, * ), b( ldb, * ), q( ldq, * ),z( ldz, * ), alphar(& * ), alphai( * ), beta( * ) integer(${ik}$), intent( out ) :: ns, nd, info real(sp), intent(inout) :: qc(ldqc,*), zc(ldzc,*) real(sp), intent(out) :: work(*) ! ================================================================ ! local scalars logical(lk) :: bulge integer(${ik}$) :: jw, kwtop, kwbot, istopm, istartm, k, k2, stgexc_info, ifst, ilst, & lworkreq, qz_small_info real(sp) :: s, smlnum, ulp, safmin, safmax, c1, s1, temp info = 0_${ik}$ ! set up deflation window jw = min( nw, ihi-ilo+1 ) kwtop = ihi-jw+1 if ( kwtop == ilo ) then s = zero else s = a( kwtop, kwtop-1 ) end if ! determine required workspace ifst = 1_${ik}$ ilst = jw call stdlib${ii}$_stgexc( .true., .true., jw, a, lda, b, ldb, qc, ldqc, zc,ldzc, ifst, ilst, & work, -1_${ik}$, stgexc_info ) lworkreq = int( work( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_slaqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alphar, alphai, beta, qc,ldqc, zc, ldzc, work, -1_${ik}$, rec+1, qz_small_info ) lworkreq = max( lworkreq, int( work( 1_${ik}$ ),KIND=${ik}$)+2_${ik}$*jw**2_${ik}$ ) lworkreq = max( lworkreq, n*nw, 2_${ik}$*nw**2_${ik}$+n ) if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = lworkreq return else if ( lwork < lworkreq ) then info = -26_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SLAQZ3', -info ) return end if ! get machine constants safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_slabad( safmin, safmax ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=sp)/ulp ) if ( ihi == kwtop ) then ! 1 by 1 deflation window, just try a regular deflation alphar( kwtop ) = a( kwtop, kwtop ) alphai( kwtop ) = zero beta( kwtop ) = b( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if ( abs( s ) <= max( smlnum, ulp*abs( a( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if ( kwtop > ilo ) then a( kwtop, kwtop-1 ) = zero end if end if end if ! store window in case of convergence failure call stdlib${ii}$_slacpy( 'ALL', jw, jw, a( kwtop, kwtop ), lda, work, jw ) call stdlib${ii}$_slacpy( 'ALL', jw, jw, b( kwtop, kwtop ), ldb, work( jw**2_${ik}$+1 ), jw ) ! transform window to real schur form call stdlib${ii}$_slaset( 'FULL', jw, jw, zero, one, qc, ldqc ) call stdlib${ii}$_slaset( 'FULL', jw, jw, zero, one, zc, ldzc ) call stdlib${ii}$_slaqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alphar, alphai, beta, qc,ldqc, zc, ldzc, work( 2_${ik}$*jw**2_${ik}$+1 ), lwork-2*jw**2_${ik}$,rec+1, & qz_small_info ) if( qz_small_info /= 0_${ik}$ ) then ! convergence failure, restore the window and exit nd = 0_${ik}$ ns = jw-qz_small_info call stdlib${ii}$_slacpy( 'ALL', jw, jw, work, jw, a( kwtop, kwtop ), lda ) call stdlib${ii}$_slacpy( 'ALL', jw, jw, work( jw**2_${ik}$+1 ), jw, b( kwtop,kwtop ), ldb ) return end if ! deflation detection loop if ( kwtop == ilo .or. s == zero ) then kwbot = kwtop-1 else kwbot = ihi k = 1_${ik}$ k2 = 1_${ik}$ do while ( k <= jw ) bulge = .false. if ( kwbot-kwtop+1 >= 2_${ik}$ ) then bulge = a( kwbot, kwbot-1 ) /= zero end if if ( bulge ) then ! try to deflate complex conjugate eigenvalue pair temp = abs( a( kwbot, kwbot ) )+sqrt( abs( a( kwbot,kwbot-1 ) ) )*sqrt( abs( & a( kwbot-1, kwbot ) ) ) if( temp == zero )then temp = abs( s ) end if if ( max( abs( s*qc( 1_${ik}$, kwbot-kwtop ) ), abs( s*qc( 1_${ik}$,kwbot-kwtop+1 ) ) ) <= & max( smlnum,ulp*temp ) ) then ! deflatable kwbot = kwbot-2 else ! not deflatable, move out of the way ifst = kwbot-kwtop+1 ilst = k2 call stdlib${ii}$_stgexc( .true., .true., jw, a( kwtop, kwtop ),lda, b( kwtop, & kwtop ), ldb, qc, ldqc,zc, ldzc, ifst, ilst, work, lwork,stgexc_info ) k2 = k2+2 end if k = k+2 else ! try to deflate real eigenvalue temp = abs( a( kwbot, kwbot ) ) if( temp == zero ) then temp = abs( s ) end if if ( ( abs( s*qc( 1_${ik}$, kwbot-kwtop+1 ) ) ) <= max( ulp*temp, smlnum ) ) & then ! deflatable kwbot = kwbot-1 else ! not deflatable, move out of the way ifst = kwbot-kwtop+1 ilst = k2 call stdlib${ii}$_stgexc( .true., .true., jw, a( kwtop, kwtop ),lda, b( kwtop, & kwtop ), ldb, qc, ldqc,zc, ldzc, ifst, ilst, work, lwork,stgexc_info ) k2 = k2+1 end if k = k+1 end if end do end if ! store eigenvalues nd = ihi-kwbot ns = jw-nd k = kwtop do while ( k <= ihi ) bulge = .false. if ( k < ihi ) then if ( a( k+1, k ) /= zero ) then bulge = .true. end if end if if ( bulge ) then ! 2x2 eigenvalue block call stdlib${ii}$_slag2( a( k, k ), lda, b( k, k ), ldb, safmin,beta( k ), beta( k+1 ),& alphar( k ),alphar( k+1 ), alphai( k ) ) alphai( k+1 ) = -alphai( k ) k = k+2 else ! 1x1 eigenvalue block alphar( k ) = a( k, k ) alphai( k ) = zero beta( k ) = b( k, k ) k = k+1 end if end do if ( kwtop /= ilo .and. s /= zero ) then ! reflect spike back, this will create optimally packed bulges a( kwtop:kwbot, kwtop-1 ) = a( kwtop, kwtop-1 )*qc( 1_${ik}$,1_${ik}$:jw-nd ) do k = kwbot-1, kwtop, -1 call stdlib${ii}$_slartg( a( k, kwtop-1 ), a( k+1, kwtop-1 ), c1, s1,temp ) a( k, kwtop-1 ) = temp a( k+1, kwtop-1 ) = zero k2 = max( kwtop, k-1 ) call stdlib${ii}$_srot( ihi-k2+1, a( k, k2 ), lda, a( k+1, k2 ), lda, c1,s1 ) call stdlib${ii}$_srot( ihi-( k-1 )+1_${ik}$, b( k, k-1 ), ldb, b( k+1, k-1 ),ldb, c1, s1 ) call stdlib${ii}$_srot( jw, qc( 1_${ik}$, k-kwtop+1 ), 1_${ik}$, qc( 1_${ik}$, k+1-kwtop+1 ),1_${ik}$, c1, s1 ) end do ! chase bulges down istartm = kwtop istopm = ihi k = kwbot-1 do while ( k >= kwtop ) if ( ( k >= kwtop+1 ) .and. a( k+1, k-1 ) /= zero ) then ! move double pole block down and remove it do k2 = k-1, kwbot-2 call stdlib${ii}$_slaqz2( .true., .true., k2, kwtop, kwtop+jw-1,kwbot, a, lda, b,& ldb, jw, kwtop, qc,ldqc, jw, kwtop, zc, ldzc ) end do k = k-2 else ! k points to single shift do k2 = k, kwbot-2 ! move shift down call stdlib${ii}$_slartg( b( k2+1, k2+1 ), b( k2+1, k2 ), c1, s1,temp ) b( k2+1, k2+1 ) = temp b( k2+1, k2 ) = zero call stdlib${ii}$_srot( k2+2-istartm+1, a( istartm, k2+1 ), 1_${ik}$,a( istartm, k2 ), & 1_${ik}$, c1, s1 ) call stdlib${ii}$_srot( k2-istartm+1, b( istartm, k2+1 ), 1_${ik}$,b( istartm, k2 ), 1_${ik}$, & c1, s1 ) call stdlib${ii}$_srot( jw, zc( 1_${ik}$, k2+1-kwtop+1 ), 1_${ik}$, zc( 1_${ik}$,k2-kwtop+1 ), 1_${ik}$, c1, & s1 ) call stdlib${ii}$_slartg( a( k2+1, k2 ), a( k2+2, k2 ), c1, s1,temp ) a( k2+1, k2 ) = temp a( k2+2, k2 ) = zero call stdlib${ii}$_srot( istopm-k2, a( k2+1, k2+1 ), lda, a( k2+2,k2+1 ), lda, c1,& s1 ) call stdlib${ii}$_srot( istopm-k2, b( k2+1, k2+1 ), ldb, b( k2+2,k2+1 ), ldb, c1,& s1 ) call stdlib${ii}$_srot( jw, qc( 1_${ik}$, k2+1-kwtop+1 ), 1_${ik}$, qc( 1_${ik}$,k2+2-kwtop+1 ), 1_${ik}$, & c1, s1 ) end do ! remove the shift call stdlib${ii}$_slartg( b( kwbot, kwbot ), b( kwbot, kwbot-1 ), c1,s1, temp ) b( kwbot, kwbot ) = temp b( kwbot, kwbot-1 ) = zero call stdlib${ii}$_srot( kwbot-istartm, b( istartm, kwbot ), 1_${ik}$,b( istartm, kwbot-1 ),& 1_${ik}$, c1, s1 ) call stdlib${ii}$_srot( kwbot-istartm+1, a( istartm, kwbot ), 1_${ik}$,a( istartm, kwbot-1 & ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_srot( jw, zc( 1_${ik}$, kwbot-kwtop+1 ), 1_${ik}$, zc( 1_${ik}$,kwbot-1-kwtop+1 ), 1_${ik}$, & c1, s1 ) k = k-1 end if end do end if ! apply qc and zc to rest of the matrix if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if if ( istopm-ihi > 0_${ik}$ ) then call stdlib${ii}$_sgemm( 'T', 'N', jw, istopm-ihi, jw, one, qc, ldqc,a( kwtop, ihi+1 ), & lda, zero, work, jw ) call stdlib${ii}$_slacpy( 'ALL', jw, istopm-ihi, work, jw, a( kwtop,ihi+1 ), lda ) call stdlib${ii}$_sgemm( 'T', 'N', jw, istopm-ihi, jw, one, qc, ldqc,b( kwtop, ihi+1 ), & ldb, zero, work, jw ) call stdlib${ii}$_slacpy( 'ALL', jw, istopm-ihi, work, jw, b( kwtop,ihi+1 ), ldb ) end if if ( ilq ) then call stdlib${ii}$_sgemm( 'N', 'N', n, jw, jw, one, q( 1_${ik}$, kwtop ), ldq, qc,ldqc, zero, & work, n ) call stdlib${ii}$_slacpy( 'ALL', n, jw, work, n, q( 1_${ik}$, kwtop ), ldq ) end if if ( kwtop-1-istartm+1 > 0_${ik}$ ) then call stdlib${ii}$_sgemm( 'N', 'N', kwtop-istartm, jw, jw, one, a( istartm,kwtop ), lda, & zc, ldzc, zero, work,kwtop-istartm ) call stdlib${ii}$_slacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,a( istartm, kwtop & ), lda ) call stdlib${ii}$_sgemm( 'N', 'N', kwtop-istartm, jw, jw, one, b( istartm,kwtop ), ldb, & zc, ldzc, zero, work,kwtop-istartm ) call stdlib${ii}$_slacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,b( istartm, kwtop & ), ldb ) end if if ( ilz ) then call stdlib${ii}$_sgemm( 'N', 'N', n, jw, jw, one, z( 1_${ik}$, kwtop ), ldz, zc,ldzc, zero, & work, n ) call stdlib${ii}$_slacpy( 'ALL', n, jw, work, n, z( 1_${ik}$, kwtop ), ldz ) end if end subroutine stdlib${ii}$_slaqz3 recursive module subroutine stdlib${ii}$_dlaqz3( ilschur, ilq, ilz, n, ilo, ihi, nw,a, lda, b, ldb, q, & !! DLAQZ3 performs AED ldq, z, ldz, ns,nd, alphar, alphai, beta, qc, ldqc,zc, ldzc, work, lwork, rec, info ) use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, nw, lda, ldb, ldq, ldz,ldqc, ldzc, lwork, & rec real(dp), intent( inout ) :: a( lda, * ), b( ldb, * ),q( ldq, * ), z( ldz, * ), alphar(& * ),alphai( * ), beta( * ) integer(${ik}$), intent( out ) :: ns, nd, info real(dp), intent(inout) :: qc(ldqc,*), zc(ldzc,*) real(dp), intent(out) :: work(*) ! ================================================================ ! local scalars logical(lk) :: bulge integer(${ik}$) :: jw, kwtop, kwbot, istopm, istartm, k, k2, dtgexc_info, ifst, ilst, & lworkreq, qz_small_info real(dp) :: s, smlnum, ulp, safmin, safmax, c1, s1, temp info = 0_${ik}$ ! set up deflation window jw = min( nw, ihi-ilo+1 ) kwtop = ihi-jw+1 if ( kwtop == ilo ) then s = zero else s = a( kwtop, kwtop-1 ) end if ! determine required workspace ifst = 1_${ik}$ ilst = jw call stdlib${ii}$_dtgexc( .true., .true., jw, a, lda, b, ldb, qc, ldqc, zc,ldzc, ifst, ilst, & work, -1_${ik}$, dtgexc_info ) lworkreq = int( work( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_dlaqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alphar, alphai, beta, qc,ldqc, zc, ldzc, work, -1_${ik}$, rec+1, qz_small_info ) lworkreq = max( lworkreq, int( work( 1_${ik}$ ),KIND=${ik}$)+2_${ik}$*jw**2_${ik}$ ) lworkreq = max( lworkreq, n*nw, 2_${ik}$*nw**2_${ik}$+n ) if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = lworkreq return else if ( lwork < lworkreq ) then info = -26_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLAQZ3', -info ) return end if ! get machine constants safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_dlabad( safmin, safmax ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=dp)/ulp ) if ( ihi == kwtop ) then ! 1 by 1 deflation window, just try a regular deflation alphar( kwtop ) = a( kwtop, kwtop ) alphai( kwtop ) = zero beta( kwtop ) = b( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if ( abs( s ) <= max( smlnum, ulp*abs( a( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if ( kwtop > ilo ) then a( kwtop, kwtop-1 ) = zero end if end if end if ! store window in case of convergence failure call stdlib${ii}$_dlacpy( 'ALL', jw, jw, a( kwtop, kwtop ), lda, work, jw ) call stdlib${ii}$_dlacpy( 'ALL', jw, jw, b( kwtop, kwtop ), ldb, work( jw**2_${ik}$+1 ), jw ) ! transform window to real schur form call stdlib${ii}$_dlaset( 'FULL', jw, jw, zero, one, qc, ldqc ) call stdlib${ii}$_dlaset( 'FULL', jw, jw, zero, one, zc, ldzc ) call stdlib${ii}$_dlaqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alphar, alphai, beta, qc,ldqc, zc, ldzc, work( 2_${ik}$*jw**2_${ik}$+1 ), lwork-2*jw**2_${ik}$,rec+1, & qz_small_info ) if( qz_small_info /= 0_${ik}$ ) then ! convergence failure, restore the window and exit nd = 0_${ik}$ ns = jw-qz_small_info call stdlib${ii}$_dlacpy( 'ALL', jw, jw, work, jw, a( kwtop, kwtop ), lda ) call stdlib${ii}$_dlacpy( 'ALL', jw, jw, work( jw**2_${ik}$+1 ), jw, b( kwtop,kwtop ), ldb ) return end if ! deflation detection loop if ( kwtop == ilo .or. s == zero ) then kwbot = kwtop-1 else kwbot = ihi k = 1_${ik}$ k2 = 1_${ik}$ do while ( k <= jw ) bulge = .false. if ( kwbot-kwtop+1 >= 2_${ik}$ ) then bulge = a( kwbot, kwbot-1 ) /= zero end if if ( bulge ) then ! try to deflate complex conjugate eigenvalue pair temp = abs( a( kwbot, kwbot ) )+sqrt( abs( a( kwbot,kwbot-1 ) ) )*sqrt( abs( & a( kwbot-1, kwbot ) ) ) if( temp == zero )then temp = abs( s ) end if if ( max( abs( s*qc( 1_${ik}$, kwbot-kwtop ) ), abs( s*qc( 1_${ik}$,kwbot-kwtop+1 ) ) ) <= & max( smlnum,ulp*temp ) ) then ! deflatable kwbot = kwbot-2 else ! not deflatable, move out of the way ifst = kwbot-kwtop+1 ilst = k2 call stdlib${ii}$_dtgexc( .true., .true., jw, a( kwtop, kwtop ),lda, b( kwtop, & kwtop ), ldb, qc, ldqc,zc, ldzc, ifst, ilst, work, lwork,dtgexc_info ) k2 = k2+2 end if k = k+2 else ! try to deflate real eigenvalue temp = abs( a( kwbot, kwbot ) ) if( temp == zero ) then temp = abs( s ) end if if ( ( abs( s*qc( 1_${ik}$, kwbot-kwtop+1 ) ) ) <= max( ulp*temp, smlnum ) ) & then ! deflatable kwbot = kwbot-1 else ! not deflatable, move out of the way ifst = kwbot-kwtop+1 ilst = k2 call stdlib${ii}$_dtgexc( .true., .true., jw, a( kwtop, kwtop ),lda, b( kwtop, & kwtop ), ldb, qc, ldqc,zc, ldzc, ifst, ilst, work, lwork,dtgexc_info ) k2 = k2+1 end if k = k+1 end if end do end if ! store eigenvalues nd = ihi-kwbot ns = jw-nd k = kwtop do while ( k <= ihi ) bulge = .false. if ( k < ihi ) then if ( a( k+1, k ) /= zero ) then bulge = .true. end if end if if ( bulge ) then ! 2x2 eigenvalue block call stdlib${ii}$_dlag2( a( k, k ), lda, b( k, k ), ldb, safmin,beta( k ), beta( k+1 ),& alphar( k ),alphar( k+1 ), alphai( k ) ) alphai( k+1 ) = -alphai( k ) k = k+2 else ! 1x1 eigenvalue block alphar( k ) = a( k, k ) alphai( k ) = zero beta( k ) = b( k, k ) k = k+1 end if end do if ( kwtop /= ilo .and. s /= zero ) then ! reflect spike back, this will create optimally packed bulges a( kwtop:kwbot, kwtop-1 ) = a( kwtop, kwtop-1 )*qc( 1_${ik}$,1_${ik}$:jw-nd ) do k = kwbot-1, kwtop, -1 call stdlib${ii}$_dlartg( a( k, kwtop-1 ), a( k+1, kwtop-1 ), c1, s1,temp ) a( k, kwtop-1 ) = temp a( k+1, kwtop-1 ) = zero k2 = max( kwtop, k-1 ) call stdlib${ii}$_drot( ihi-k2+1, a( k, k2 ), lda, a( k+1, k2 ), lda, c1,s1 ) call stdlib${ii}$_drot( ihi-( k-1 )+1_${ik}$, b( k, k-1 ), ldb, b( k+1, k-1 ),ldb, c1, s1 ) call stdlib${ii}$_drot( jw, qc( 1_${ik}$, k-kwtop+1 ), 1_${ik}$, qc( 1_${ik}$, k+1-kwtop+1 ),1_${ik}$, c1, s1 ) end do ! chase bulges down istartm = kwtop istopm = ihi k = kwbot-1 do while ( k >= kwtop ) if ( ( k >= kwtop+1 ) .and. a( k+1, k-1 ) /= zero ) then ! move double pole block down and remove it do k2 = k-1, kwbot-2 call stdlib${ii}$_dlaqz2( .true., .true., k2, kwtop, kwtop+jw-1,kwbot, a, lda, b,& ldb, jw, kwtop, qc,ldqc, jw, kwtop, zc, ldzc ) end do k = k-2 else ! k points to single shift do k2 = k, kwbot-2 ! move shift down call stdlib${ii}$_dlartg( b( k2+1, k2+1 ), b( k2+1, k2 ), c1, s1,temp ) b( k2+1, k2+1 ) = temp b( k2+1, k2 ) = zero call stdlib${ii}$_drot( k2+2-istartm+1, a( istartm, k2+1 ), 1_${ik}$,a( istartm, k2 ), & 1_${ik}$, c1, s1 ) call stdlib${ii}$_drot( k2-istartm+1, b( istartm, k2+1 ), 1_${ik}$,b( istartm, k2 ), 1_${ik}$, & c1, s1 ) call stdlib${ii}$_drot( jw, zc( 1_${ik}$, k2+1-kwtop+1 ), 1_${ik}$, zc( 1_${ik}$,k2-kwtop+1 ), 1_${ik}$, c1, & s1 ) call stdlib${ii}$_dlartg( a( k2+1, k2 ), a( k2+2, k2 ), c1, s1,temp ) a( k2+1, k2 ) = temp a( k2+2, k2 ) = zero call stdlib${ii}$_drot( istopm-k2, a( k2+1, k2+1 ), lda, a( k2+2,k2+1 ), lda, c1,& s1 ) call stdlib${ii}$_drot( istopm-k2, b( k2+1, k2+1 ), ldb, b( k2+2,k2+1 ), ldb, c1,& s1 ) call stdlib${ii}$_drot( jw, qc( 1_${ik}$, k2+1-kwtop+1 ), 1_${ik}$, qc( 1_${ik}$,k2+2-kwtop+1 ), 1_${ik}$, & c1, s1 ) end do ! remove the shift call stdlib${ii}$_dlartg( b( kwbot, kwbot ), b( kwbot, kwbot-1 ), c1,s1, temp ) b( kwbot, kwbot ) = temp b( kwbot, kwbot-1 ) = zero call stdlib${ii}$_drot( kwbot-istartm, b( istartm, kwbot ), 1_${ik}$,b( istartm, kwbot-1 ),& 1_${ik}$, c1, s1 ) call stdlib${ii}$_drot( kwbot-istartm+1, a( istartm, kwbot ), 1_${ik}$,a( istartm, kwbot-1 & ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_drot( jw, zc( 1_${ik}$, kwbot-kwtop+1 ), 1_${ik}$, zc( 1_${ik}$,kwbot-1-kwtop+1 ), 1_${ik}$, & c1, s1 ) k = k-1 end if end do end if ! apply qc and zc to rest of the matrix if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if if ( istopm-ihi > 0_${ik}$ ) then call stdlib${ii}$_dgemm( 'T', 'N', jw, istopm-ihi, jw, one, qc, ldqc,a( kwtop, ihi+1 ), & lda, zero, work, jw ) call stdlib${ii}$_dlacpy( 'ALL', jw, istopm-ihi, work, jw, a( kwtop,ihi+1 ), lda ) call stdlib${ii}$_dgemm( 'T', 'N', jw, istopm-ihi, jw, one, qc, ldqc,b( kwtop, ihi+1 ), & ldb, zero, work, jw ) call stdlib${ii}$_dlacpy( 'ALL', jw, istopm-ihi, work, jw, b( kwtop,ihi+1 ), ldb ) end if if ( ilq ) then call stdlib${ii}$_dgemm( 'N', 'N', n, jw, jw, one, q( 1_${ik}$, kwtop ), ldq, qc,ldqc, zero, & work, n ) call stdlib${ii}$_dlacpy( 'ALL', n, jw, work, n, q( 1_${ik}$, kwtop ), ldq ) end if if ( kwtop-1-istartm+1 > 0_${ik}$ ) then call stdlib${ii}$_dgemm( 'N', 'N', kwtop-istartm, jw, jw, one, a( istartm,kwtop ), lda, & zc, ldzc, zero, work,kwtop-istartm ) call stdlib${ii}$_dlacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,a( istartm, kwtop & ), lda ) call stdlib${ii}$_dgemm( 'N', 'N', kwtop-istartm, jw, jw, one, b( istartm,kwtop ), ldb, & zc, ldzc, zero, work,kwtop-istartm ) call stdlib${ii}$_dlacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,b( istartm, kwtop & ), ldb ) end if if ( ilz ) then call stdlib${ii}$_dgemm( 'N', 'N', n, jw, jw, one, z( 1_${ik}$, kwtop ), ldz, zc,ldzc, zero, & work, n ) call stdlib${ii}$_dlacpy( 'ALL', n, jw, work, n, z( 1_${ik}$, kwtop ), ldz ) end if end subroutine stdlib${ii}$_dlaqz3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] recursive module subroutine stdlib${ii}$_${ri}$laqz3( ilschur, ilq, ilz, n, ilo, ihi, nw,a, lda, b, ldb, q, & !! DLAQZ3: performs AED ldq, z, ldz, ns,nd, alphar, alphai, beta, qc, ldqc,zc, ldzc, work, lwork, rec, info ) use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, nw, lda, ldb, ldq, ldz,ldqc, ldzc, lwork, & rec real(${rk}$), intent( inout ) :: a( lda, * ), b( ldb, * ),q( ldq, * ), z( ldz, * ), alphar(& * ),alphai( * ), beta( * ) integer(${ik}$), intent( out ) :: ns, nd, info real(${rk}$), intent(inout) :: qc(ldqc,*), zc(ldzc,*) real(${rk}$), intent(out) :: work(*) ! ================================================================ ! local scalars logical(lk) :: bulge integer(${ik}$) :: jw, kwtop, kwbot, istopm, istartm, k, k2, dtgexc_info, ifst, ilst, & lworkreq, qz_small_info real(${rk}$) :: s, smlnum, ulp, safmin, safmax, c1, s1, temp info = 0_${ik}$ ! set up deflation window jw = min( nw, ihi-ilo+1 ) kwtop = ihi-jw+1 if ( kwtop == ilo ) then s = zero else s = a( kwtop, kwtop-1 ) end if ! determine required workspace ifst = 1_${ik}$ ilst = jw call stdlib${ii}$_${ri}$tgexc( .true., .true., jw, a, lda, b, ldb, qc, ldqc, zc,ldzc, ifst, ilst, & work, -1_${ik}$, dtgexc_info ) lworkreq = int( work( 1_${ik}$ ),KIND=${ik}$) call stdlib${ii}$_${ri}$laqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alphar, alphai, beta, qc,ldqc, zc, ldzc, work, -1_${ik}$, rec+1, qz_small_info ) lworkreq = max( lworkreq, int( work( 1_${ik}$ ),KIND=${ik}$)+2_${ik}$*jw**2_${ik}$ ) lworkreq = max( lworkreq, n*nw, 2_${ik}$*nw**2_${ik}$+n ) if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = lworkreq return else if ( lwork < lworkreq ) then info = -26_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLAQZ3', -info ) return end if ! get machine constants safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_${ri}$labad( safmin, safmax ) ulp = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin*( real( n,KIND=${rk}$)/ulp ) if ( ihi == kwtop ) then ! 1 by 1 deflation window, just try a regular deflation alphar( kwtop ) = a( kwtop, kwtop ) alphai( kwtop ) = zero beta( kwtop ) = b( kwtop, kwtop ) ns = 1_${ik}$ nd = 0_${ik}$ if ( abs( s ) <= max( smlnum, ulp*abs( a( kwtop,kwtop ) ) ) ) then ns = 0_${ik}$ nd = 1_${ik}$ if ( kwtop > ilo ) then a( kwtop, kwtop-1 ) = zero end if end if end if ! store window in case of convergence failure call stdlib${ii}$_${ri}$lacpy( 'ALL', jw, jw, a( kwtop, kwtop ), lda, work, jw ) call stdlib${ii}$_${ri}$lacpy( 'ALL', jw, jw, b( kwtop, kwtop ), ldb, work( jw**2_${ik}$+1 ), jw ) ! transform window to real schur form call stdlib${ii}$_${ri}$laset( 'FULL', jw, jw, zero, one, qc, ldqc ) call stdlib${ii}$_${ri}$laset( 'FULL', jw, jw, zero, one, zc, ldzc ) call stdlib${ii}$_${ri}$laqz0( 'S', 'V', 'V', jw, 1_${ik}$, jw, a( kwtop, kwtop ), lda,b( kwtop, kwtop ),& ldb, alphar, alphai, beta, qc,ldqc, zc, ldzc, work( 2_${ik}$*jw**2_${ik}$+1 ), lwork-2*jw**2_${ik}$,rec+1, & qz_small_info ) if( qz_small_info /= 0_${ik}$ ) then ! convergence failure, restore the window and exit nd = 0_${ik}$ ns = jw-qz_small_info call stdlib${ii}$_${ri}$lacpy( 'ALL', jw, jw, work, jw, a( kwtop, kwtop ), lda ) call stdlib${ii}$_${ri}$lacpy( 'ALL', jw, jw, work( jw**2_${ik}$+1 ), jw, b( kwtop,kwtop ), ldb ) return end if ! deflation detection loop if ( kwtop == ilo .or. s == zero ) then kwbot = kwtop-1 else kwbot = ihi k = 1_${ik}$ k2 = 1_${ik}$ do while ( k <= jw ) bulge = .false. if ( kwbot-kwtop+1 >= 2_${ik}$ ) then bulge = a( kwbot, kwbot-1 ) /= zero end if if ( bulge ) then ! try to deflate complex conjugate eigenvalue pair temp = abs( a( kwbot, kwbot ) )+sqrt( abs( a( kwbot,kwbot-1 ) ) )*sqrt( abs( & a( kwbot-1, kwbot ) ) ) if( temp == zero )then temp = abs( s ) end if if ( max( abs( s*qc( 1_${ik}$, kwbot-kwtop ) ), abs( s*qc( 1_${ik}$,kwbot-kwtop+1 ) ) ) <= & max( smlnum,ulp*temp ) ) then ! deflatable kwbot = kwbot-2 else ! not deflatable, move out of the way ifst = kwbot-kwtop+1 ilst = k2 call stdlib${ii}$_${ri}$tgexc( .true., .true., jw, a( kwtop, kwtop ),lda, b( kwtop, & kwtop ), ldb, qc, ldqc,zc, ldzc, ifst, ilst, work, lwork,dtgexc_info ) k2 = k2+2 end if k = k+2 else ! try to deflate real eigenvalue temp = abs( a( kwbot, kwbot ) ) if( temp == zero ) then temp = abs( s ) end if if ( ( abs( s*qc( 1_${ik}$, kwbot-kwtop+1 ) ) ) <= max( ulp*temp, smlnum ) ) & then ! deflatable kwbot = kwbot-1 else ! not deflatable, move out of the way ifst = kwbot-kwtop+1 ilst = k2 call stdlib${ii}$_${ri}$tgexc( .true., .true., jw, a( kwtop, kwtop ),lda, b( kwtop, & kwtop ), ldb, qc, ldqc,zc, ldzc, ifst, ilst, work, lwork,dtgexc_info ) k2 = k2+1 end if k = k+1 end if end do end if ! store eigenvalues nd = ihi-kwbot ns = jw-nd k = kwtop do while ( k <= ihi ) bulge = .false. if ( k < ihi ) then if ( a( k+1, k ) /= zero ) then bulge = .true. end if end if if ( bulge ) then ! 2x2 eigenvalue block call stdlib${ii}$_${ri}$lag2( a( k, k ), lda, b( k, k ), ldb, safmin,beta( k ), beta( k+1 ),& alphar( k ),alphar( k+1 ), alphai( k ) ) alphai( k+1 ) = -alphai( k ) k = k+2 else ! 1x1 eigenvalue block alphar( k ) = a( k, k ) alphai( k ) = zero beta( k ) = b( k, k ) k = k+1 end if end do if ( kwtop /= ilo .and. s /= zero ) then ! reflect spike back, this will create optimally packed bulges a( kwtop:kwbot, kwtop-1 ) = a( kwtop, kwtop-1 )*qc( 1_${ik}$,1_${ik}$:jw-nd ) do k = kwbot-1, kwtop, -1 call stdlib${ii}$_${ri}$lartg( a( k, kwtop-1 ), a( k+1, kwtop-1 ), c1, s1,temp ) a( k, kwtop-1 ) = temp a( k+1, kwtop-1 ) = zero k2 = max( kwtop, k-1 ) call stdlib${ii}$_${ri}$rot( ihi-k2+1, a( k, k2 ), lda, a( k+1, k2 ), lda, c1,s1 ) call stdlib${ii}$_${ri}$rot( ihi-( k-1 )+1_${ik}$, b( k, k-1 ), ldb, b( k+1, k-1 ),ldb, c1, s1 ) call stdlib${ii}$_${ri}$rot( jw, qc( 1_${ik}$, k-kwtop+1 ), 1_${ik}$, qc( 1_${ik}$, k+1-kwtop+1 ),1_${ik}$, c1, s1 ) end do ! chase bulges down istartm = kwtop istopm = ihi k = kwbot-1 do while ( k >= kwtop ) if ( ( k >= kwtop+1 ) .and. a( k+1, k-1 ) /= zero ) then ! move double pole block down and remove it do k2 = k-1, kwbot-2 call stdlib${ii}$_${ri}$laqz2( .true., .true., k2, kwtop, kwtop+jw-1,kwbot, a, lda, b,& ldb, jw, kwtop, qc,ldqc, jw, kwtop, zc, ldzc ) end do k = k-2 else ! k points to single shift do k2 = k, kwbot-2 ! move shift down call stdlib${ii}$_${ri}$lartg( b( k2+1, k2+1 ), b( k2+1, k2 ), c1, s1,temp ) b( k2+1, k2+1 ) = temp b( k2+1, k2 ) = zero call stdlib${ii}$_${ri}$rot( k2+2-istartm+1, a( istartm, k2+1 ), 1_${ik}$,a( istartm, k2 ), & 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$rot( k2-istartm+1, b( istartm, k2+1 ), 1_${ik}$,b( istartm, k2 ), 1_${ik}$, & c1, s1 ) call stdlib${ii}$_${ri}$rot( jw, zc( 1_${ik}$, k2+1-kwtop+1 ), 1_${ik}$, zc( 1_${ik}$,k2-kwtop+1 ), 1_${ik}$, c1, & s1 ) call stdlib${ii}$_${ri}$lartg( a( k2+1, k2 ), a( k2+2, k2 ), c1, s1,temp ) a( k2+1, k2 ) = temp a( k2+2, k2 ) = zero call stdlib${ii}$_${ri}$rot( istopm-k2, a( k2+1, k2+1 ), lda, a( k2+2,k2+1 ), lda, c1,& s1 ) call stdlib${ii}$_${ri}$rot( istopm-k2, b( k2+1, k2+1 ), ldb, b( k2+2,k2+1 ), ldb, c1,& s1 ) call stdlib${ii}$_${ri}$rot( jw, qc( 1_${ik}$, k2+1-kwtop+1 ), 1_${ik}$, qc( 1_${ik}$,k2+2-kwtop+1 ), 1_${ik}$, & c1, s1 ) end do ! remove the shift call stdlib${ii}$_${ri}$lartg( b( kwbot, kwbot ), b( kwbot, kwbot-1 ), c1,s1, temp ) b( kwbot, kwbot ) = temp b( kwbot, kwbot-1 ) = zero call stdlib${ii}$_${ri}$rot( kwbot-istartm, b( istartm, kwbot ), 1_${ik}$,b( istartm, kwbot-1 ),& 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$rot( kwbot-istartm+1, a( istartm, kwbot ), 1_${ik}$,a( istartm, kwbot-1 & ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$rot( jw, zc( 1_${ik}$, kwbot-kwtop+1 ), 1_${ik}$, zc( 1_${ik}$,kwbot-1-kwtop+1 ), 1_${ik}$, & c1, s1 ) k = k-1 end if end do end if ! apply qc and zc to rest of the matrix if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if if ( istopm-ihi > 0_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'T', 'N', jw, istopm-ihi, jw, one, qc, ldqc,a( kwtop, ihi+1 ), & lda, zero, work, jw ) call stdlib${ii}$_${ri}$lacpy( 'ALL', jw, istopm-ihi, work, jw, a( kwtop,ihi+1 ), lda ) call stdlib${ii}$_${ri}$gemm( 'T', 'N', jw, istopm-ihi, jw, one, qc, ldqc,b( kwtop, ihi+1 ), & ldb, zero, work, jw ) call stdlib${ii}$_${ri}$lacpy( 'ALL', jw, istopm-ihi, work, jw, b( kwtop,ihi+1 ), ldb ) end if if ( ilq ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, jw, jw, one, q( 1_${ik}$, kwtop ), ldq, qc,ldqc, zero, & work, n ) call stdlib${ii}$_${ri}$lacpy( 'ALL', n, jw, work, n, q( 1_${ik}$, kwtop ), ldq ) end if if ( kwtop-1-istartm+1 > 0_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', kwtop-istartm, jw, jw, one, a( istartm,kwtop ), lda, & zc, ldzc, zero, work,kwtop-istartm ) call stdlib${ii}$_${ri}$lacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,a( istartm, kwtop & ), lda ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', kwtop-istartm, jw, jw, one, b( istartm,kwtop ), ldb, & zc, ldzc, zero, work,kwtop-istartm ) call stdlib${ii}$_${ri}$lacpy( 'ALL', kwtop-istartm, jw, work, kwtop-istartm,b( istartm, kwtop & ), ldb ) end if if ( ilz ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, jw, jw, one, z( 1_${ik}$, kwtop ), ldz, zc,ldzc, zero, & work, n ) call stdlib${ii}$_${ri}$lacpy( 'ALL', n, jw, work, n, z( 1_${ik}$, kwtop ), ldz ) end if end subroutine stdlib${ii}$_${ri}$laqz3 #:endif #:endfor pure module subroutine stdlib${ii}$_claqz3( ilschur, ilq, ilz, n, ilo, ihi, nshifts,nblock_desired, alpha,& !! CLAQZ3 Executes a single multishift QZ sweep beta, a, lda, b, ldb,q, ldq, z, ldz, qc, ldqc, zc, ldzc, work,lwork, info ) use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! function arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, lda, ldb, ldq, ldz, lwork,nshifts, & nblock_desired, ldqc, ldzc complex(sp), intent( inout ) :: a( lda, * ), b( ldb, * ), q( ldq, * ),z( ldz, * ), qc( & ldqc, * ), zc( ldzc, * ), work( * ),alpha( * ), beta( * ) integer(${ik}$), intent( out ) :: info ! ================================================================ ! local scalars integer(${ik}$) :: i, j, ns, istartm, istopm, sheight, swidth, k, np, istartb, istopb, & ishift, nblock, npos real(sp) :: safmin, safmax, c, scale complex(sp) :: temp, temp2, temp3, s info = 0_${ik}$ if ( nblock_desired < nshifts+1 ) then info = -8_${ik}$ end if if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = n*nblock_desired return else if ( lwork < n*nblock_desired ) then info = -25_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CLAQZ3', -info ) return end if ! executable statements ! get machine constants safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_slabad( safmin, safmax ) if ( ilo >= ihi ) then return end if if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if ns = nshifts npos = max( nblock_desired-ns, 1_${ik}$ ) ! the following block introduces the shifts and chases ! them down one by one just enough to make space for ! the other shifts. the near-the-diagonal block is ! of size (ns+1) x ns. call stdlib${ii}$_claset( 'FULL', ns+1, ns+1, czero, cone, qc, ldqc ) call stdlib${ii}$_claset( 'FULL', ns, ns, czero, cone, zc, ldzc ) do i = 1, ns ! introduce the shift scale = sqrt( abs( alpha( i ) ) ) * sqrt( abs( beta( i ) ) ) if( scale >= safmin .and. scale <= safmax ) then alpha( i ) = alpha( i )/scale beta( i ) = beta( i )/scale end if temp2 = beta( i )*a( ilo, ilo )-alpha( i )*b( ilo, ilo ) temp3 = beta( i )*a( ilo+1, ilo ) if ( abs( temp2 ) > safmax .or.abs( temp3 ) > safmax ) then temp2 = cone temp3 = czero end if call stdlib${ii}$_clartg( temp2, temp3, c, s, temp ) call stdlib${ii}$_crot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda, c,s ) call stdlib${ii}$_crot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb, c,s ) call stdlib${ii}$_crot( ns+1, qc( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, qc( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c, conjg( s ) ) ! chase the shift down do j = 1, ns-i call stdlib${ii}$_claqz1( .true., .true., j, 1_${ik}$, ns, ihi-ilo+1, a( ilo,ilo ), lda, b( & ilo, ilo ), ldb, ns+1, 1_${ik}$, qc,ldqc, ns, 1_${ik}$, zc, ldzc ) end do end do ! update the rest of the pencil ! update a(ilo:ilo+ns,ilo+ns:istopm) and b(ilo:ilo+ns,ilo+ns:istopm) ! from the left with qc(1:ns+1,1:ns+1)' sheight = ns+1 swidth = istopm-( ilo+ns )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,a( ilo, ilo+& ns ), lda, czero, work, sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight, a( ilo,ilo+ns ), lda ) call stdlib${ii}$_cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,b( ilo, ilo+& ns ), ldb, czero, work, sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight, b( ilo,ilo+ns ), ldb ) end if if ( ilq ) then call stdlib${ii}$_cgemm( 'N', 'N', n, sheight, sheight, cone, q( 1_${ik}$, ilo ),ldq, qc, ldqc, & czero, work, n ) call stdlib${ii}$_clacpy( 'ALL', n, sheight, work, n, q( 1_${ik}$, ilo ), ldq ) end if ! update a(istartm:ilo-1,ilo:ilo+ns-1) and b(istartm:ilo-1,ilo:ilo+ns-1) ! from the right with zc(1:ns,1:ns) sheight = ilo-1-istartm+1 swidth = ns if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_cgemm( 'N', 'N', sheight, swidth, swidth, cone,a( istartm, ilo ), lda, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ilo ), lda ) call stdlib${ii}$_cgemm( 'N', 'N', sheight, swidth, swidth, cone,b( istartm, ilo ), ldb, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ilo ), ldb ) end if if ( ilz ) then call stdlib${ii}$_cgemm( 'N', 'N', n, swidth, swidth, cone, z( 1_${ik}$, ilo ),ldz, zc, ldzc, & czero, work, n ) call stdlib${ii}$_clacpy( 'ALL', n, swidth, work, n, z( 1_${ik}$, ilo ), ldz ) end if ! the following block chases the shifts down to the bottom ! right block. if possible, a shift is moved down npos ! positions at a time k = ilo do while ( k < ihi-ns ) np = min( ihi-ns-k, npos ) ! size of the near-the-diagonal block nblock = ns+np ! istartb points to the first row we will be updating istartb = k+1 ! istopb points to the last column we will be updating istopb = k+nblock-1 call stdlib${ii}$_claset( 'FULL', ns+np, ns+np, czero, cone, qc, ldqc ) call stdlib${ii}$_claset( 'FULL', ns+np, ns+np, czero, cone, zc, ldzc ) ! near the diagonal shift chase do i = ns-1, 0, -1 do j = 0, np-1 ! move down the block with index k+i+j, updating ! the (ns+np x ns+np) block: ! (k:k+ns+np,k:k+ns+np-1) call stdlib${ii}$_claqz1( .true., .true., k+i+j, istartb, istopb, ihi,a, lda, b, & ldb, nblock, k+1, qc, ldqc,nblock, k, zc, ldzc ) end do end do ! update rest of the pencil ! update a(k+1:k+ns+np, k+ns+np:istopm) and ! b(k+1:k+ns+np, k+ns+np:istopm) ! from the left with qc(1:ns+np,1:ns+np)' sheight = ns+np swidth = istopm-( k+ns+np )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc,ldqc, a( k+1, k+& ns+np ), lda, czero, work,sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight, a( k+1,k+ns+np ), lda & ) call stdlib${ii}$_cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc,ldqc, b( k+1, k+& ns+np ), ldb, czero, work,sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight, b( k+1,k+ns+np ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_cgemm( 'N', 'N', n, nblock, nblock, cone, q( 1_${ik}$, k+1 ),ldq, qc, ldqc, & czero, work, n ) call stdlib${ii}$_clacpy( 'ALL', n, nblock, work, n, q( 1_${ik}$, k+1 ), ldq ) end if ! update a(istartm:k,k:k+ns+npos-1) and b(istartm:k,k:k+ns+npos-1) ! from the right with zc(1:ns+np,1:ns+np) sheight = k-istartm+1 swidth = nblock if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_cgemm( 'N', 'N', sheight, swidth, swidth, cone,a( istartm, k ), lda, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight,a( istartm, k ), lda ) call stdlib${ii}$_cgemm( 'N', 'N', sheight, swidth, swidth, cone,b( istartm, k ), ldb, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight,b( istartm, k ), ldb ) end if if ( ilz ) then call stdlib${ii}$_cgemm( 'N', 'N', n, nblock, nblock, cone, z( 1_${ik}$, k ),ldz, zc, ldzc, & czero, work, n ) call stdlib${ii}$_clacpy( 'ALL', n, nblock, work, n, z( 1_${ik}$, k ), ldz ) end if k = k+np end do ! the following block removes the shifts from the bottom right corner ! one by one. updates are initially applied to a(ihi-ns+1:ihi,ihi-ns:ihi). call stdlib${ii}$_claset( 'FULL', ns, ns, czero, cone, qc, ldqc ) call stdlib${ii}$_claset( 'FULL', ns+1, ns+1, czero, cone, zc, ldzc ) ! istartb points to the first row we will be updating istartb = ihi-ns+1 ! istopb points to the last column we will be updating istopb = ihi do i = 1, ns ! chase the shift down to the bottom right corner do ishift = ihi-i, ihi-1 call stdlib${ii}$_claqz1( .true., .true., ishift, istartb, istopb, ihi,a, lda, b, ldb, & ns, ihi-ns+1, qc, ldqc, ns+1,ihi-ns, zc, ldzc ) end do end do ! update rest of the pencil ! update a(ihi-ns+1:ihi, ihi+1:istopm) ! from the left with qc(1:ns,1:ns)' sheight = ns swidth = istopm-( ihi+1 )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,a( ihi-ns+1, & ihi+1 ), lda, czero, work, sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight,a( ihi-ns+1, ihi+1 ), lda & ) call stdlib${ii}$_cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,b( ihi-ns+1, & ihi+1 ), ldb, czero, work, sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight,b( ihi-ns+1, ihi+1 ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_cgemm( 'N', 'N', n, ns, ns, cone, q( 1_${ik}$, ihi-ns+1 ), ldq,qc, ldqc, czero,& work, n ) call stdlib${ii}$_clacpy( 'ALL', n, ns, work, n, q( 1_${ik}$, ihi-ns+1 ), ldq ) end if ! update a(istartm:ihi-ns,ihi-ns:ihi) ! from the right with zc(1:ns+1,1:ns+1) sheight = ihi-ns-istartm+1 swidth = ns+1 if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_cgemm( 'N', 'N', sheight, swidth, swidth, cone,a( istartm, ihi-ns ), & lda, zc, ldzc, czero, work,sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ihi-ns ), lda & ) call stdlib${ii}$_cgemm( 'N', 'N', sheight, swidth, swidth, cone,b( istartm, ihi-ns ), & ldb, zc, ldzc, czero, work,sheight ) call stdlib${ii}$_clacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ihi-ns ), ldb & ) end if if ( ilz ) then call stdlib${ii}$_cgemm( 'N', 'N', n, ns+1, ns+1, cone, z( 1_${ik}$, ihi-ns ), ldz,zc, ldzc, & czero, work, n ) call stdlib${ii}$_clacpy( 'ALL', n, ns+1, work, n, z( 1_${ik}$, ihi-ns ), ldz ) end if end subroutine stdlib${ii}$_claqz3 pure module subroutine stdlib${ii}$_zlaqz3( ilschur, ilq, ilz, n, ilo, ihi, nshifts,nblock_desired, alpha,& !! ZLAQZ3 Executes a single multishift QZ sweep beta, a, lda, b, ldb,q, ldq, z, ldz, qc, ldqc, zc, ldzc, work,lwork, info ) use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! function arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, lda, ldb, ldq, ldz, lwork,nshifts, & nblock_desired, ldqc, ldzc complex(dp), intent( inout ) :: a( lda, * ), b( ldb, * ), q( ldq,* ), z( ldz, * ), qc( & ldqc, * ), zc( ldzc, * ), work( * ),alpha( * ), beta( * ) integer(${ik}$), intent( out ) :: info ! ================================================================ ! local scalars integer(${ik}$) :: i, j, ns, istartm, istopm, sheight, swidth, k, np, istartb, istopb, & ishift, nblock, npos real(dp) :: safmin, safmax, c, scale complex(dp) :: temp, temp2, temp3, s info = 0_${ik}$ if ( nblock_desired < nshifts+1 ) then info = -8_${ik}$ end if if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = n*nblock_desired return else if ( lwork < n*nblock_desired ) then info = -25_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLAQZ3', -info ) return end if ! executable statements ! get machine constants safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_dlabad( safmin, safmax ) if ( ilo >= ihi ) then return end if if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if ns = nshifts npos = max( nblock_desired-ns, 1_${ik}$ ) ! the following block introduces the shifts and chases ! them down one by one just enough to make space for ! the other shifts. the near-the-diagonal block is ! of size (ns+1) x ns. call stdlib${ii}$_zlaset( 'FULL', ns+1, ns+1, czero, cone, qc, ldqc ) call stdlib${ii}$_zlaset( 'FULL', ns, ns, czero, cone, zc, ldzc ) do i = 1, ns ! introduce the shift scale = sqrt( abs( alpha( i ) ) ) * sqrt( abs( beta( i ) ) ) if( scale >= safmin .and. scale <= safmax ) then alpha( i ) = alpha( i )/scale beta( i ) = beta( i )/scale end if temp2 = beta( i )*a( ilo, ilo )-alpha( i )*b( ilo, ilo ) temp3 = beta( i )*a( ilo+1, ilo ) if ( abs( temp2 ) > safmax .or.abs( temp3 ) > safmax ) then temp2 = cone temp3 = czero end if call stdlib${ii}$_zlartg( temp2, temp3, c, s, temp ) call stdlib${ii}$_zrot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda, c,s ) call stdlib${ii}$_zrot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb, c,s ) call stdlib${ii}$_zrot( ns+1, qc( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, qc( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c,conjg( s ) ) ! chase the shift down do j = 1, ns-i call stdlib${ii}$_zlaqz1( .true., .true., j, 1_${ik}$, ns, ihi-ilo+1, a( ilo,ilo ), lda, b( & ilo, ilo ), ldb, ns+1, 1_${ik}$, qc,ldqc, ns, 1_${ik}$, zc, ldzc ) end do end do ! update the rest of the pencil ! update a(ilo:ilo+ns,ilo+ns:istopm) and b(ilo:ilo+ns,ilo+ns:istopm) ! from the left with qc(1:ns+1,1:ns+1)' sheight = ns+1 swidth = istopm-( ilo+ns )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_zgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,a( ilo, ilo+& ns ), lda, czero, work, sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight, a( ilo,ilo+ns ), lda ) call stdlib${ii}$_zgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,b( ilo, ilo+& ns ), ldb, czero, work, sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight, b( ilo,ilo+ns ), ldb ) end if if ( ilq ) then call stdlib${ii}$_zgemm( 'N', 'N', n, sheight, sheight, cone, q( 1_${ik}$, ilo ),ldq, qc, ldqc, & czero, work, n ) call stdlib${ii}$_zlacpy( 'ALL', n, sheight, work, n, q( 1_${ik}$, ilo ), ldq ) end if ! update a(istartm:ilo-1,ilo:ilo+ns-1) and b(istartm:ilo-1,ilo:ilo+ns-1) ! from the right with zc(1:ns,1:ns) sheight = ilo-1-istartm+1 swidth = ns if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_zgemm( 'N', 'N', sheight, swidth, swidth, cone,a( istartm, ilo ), lda, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ilo ), lda ) call stdlib${ii}$_zgemm( 'N', 'N', sheight, swidth, swidth, cone,b( istartm, ilo ), ldb, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ilo ), ldb ) end if if ( ilz ) then call stdlib${ii}$_zgemm( 'N', 'N', n, swidth, swidth, cone, z( 1_${ik}$, ilo ),ldz, zc, ldzc, & czero, work, n ) call stdlib${ii}$_zlacpy( 'ALL', n, swidth, work, n, z( 1_${ik}$, ilo ), ldz ) end if ! the following block chases the shifts down to the bottom ! right block. if possible, a shift is moved down npos ! positions at a time k = ilo do while ( k < ihi-ns ) np = min( ihi-ns-k, npos ) ! size of the near-the-diagonal block nblock = ns+np ! istartb points to the first row we will be updating istartb = k+1 ! istopb points to the last column we will be updating istopb = k+nblock-1 call stdlib${ii}$_zlaset( 'FULL', ns+np, ns+np, czero, cone, qc, ldqc ) call stdlib${ii}$_zlaset( 'FULL', ns+np, ns+np, czero, cone, zc, ldzc ) ! near the diagonal shift chase do i = ns-1, 0, -1 do j = 0, np-1 ! move down the block with index k+i+j, updating ! the (ns+np x ns+np) block: ! (k:k+ns+np,k:k+ns+np-1) call stdlib${ii}$_zlaqz1( .true., .true., k+i+j, istartb, istopb, ihi,a, lda, b, & ldb, nblock, k+1, qc, ldqc,nblock, k, zc, ldzc ) end do end do ! update rest of the pencil ! update a(k+1:k+ns+np, k+ns+np:istopm) and ! b(k+1:k+ns+np, k+ns+np:istopm) ! from the left with qc(1:ns+np,1:ns+np)' sheight = ns+np swidth = istopm-( k+ns+np )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_zgemm( 'C', 'N', sheight, swidth, sheight, cone, qc,ldqc, a( k+1, k+& ns+np ), lda, czero, work,sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight, a( k+1,k+ns+np ), lda & ) call stdlib${ii}$_zgemm( 'C', 'N', sheight, swidth, sheight, cone, qc,ldqc, b( k+1, k+& ns+np ), ldb, czero, work,sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight, b( k+1,k+ns+np ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_zgemm( 'N', 'N', n, nblock, nblock, cone, q( 1_${ik}$, k+1 ),ldq, qc, ldqc, & czero, work, n ) call stdlib${ii}$_zlacpy( 'ALL', n, nblock, work, n, q( 1_${ik}$, k+1 ), ldq ) end if ! update a(istartm:k,k:k+ns+npos-1) and b(istartm:k,k:k+ns+npos-1) ! from the right with zc(1:ns+np,1:ns+np) sheight = k-istartm+1 swidth = nblock if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_zgemm( 'N', 'N', sheight, swidth, swidth, cone,a( istartm, k ), lda, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight,a( istartm, k ), lda ) call stdlib${ii}$_zgemm( 'N', 'N', sheight, swidth, swidth, cone,b( istartm, k ), ldb, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight,b( istartm, k ), ldb ) end if if ( ilz ) then call stdlib${ii}$_zgemm( 'N', 'N', n, nblock, nblock, cone, z( 1_${ik}$, k ),ldz, zc, ldzc, & czero, work, n ) call stdlib${ii}$_zlacpy( 'ALL', n, nblock, work, n, z( 1_${ik}$, k ), ldz ) end if k = k+np end do ! the following block removes the shifts from the bottom right corner ! one by one. updates are initially applied to a(ihi-ns+1:ihi,ihi-ns:ihi). call stdlib${ii}$_zlaset( 'FULL', ns, ns, czero, cone, qc, ldqc ) call stdlib${ii}$_zlaset( 'FULL', ns+1, ns+1, czero, cone, zc, ldzc ) ! istartb points to the first row we will be updating istartb = ihi-ns+1 ! istopb points to the last column we will be updating istopb = ihi do i = 1, ns ! chase the shift down to the bottom right corner do ishift = ihi-i, ihi-1 call stdlib${ii}$_zlaqz1( .true., .true., ishift, istartb, istopb, ihi,a, lda, b, ldb, & ns, ihi-ns+1, qc, ldqc, ns+1,ihi-ns, zc, ldzc ) end do end do ! update rest of the pencil ! update a(ihi-ns+1:ihi, ihi+1:istopm) ! from the left with qc(1:ns,1:ns)' sheight = ns swidth = istopm-( ihi+1 )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_zgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,a( ihi-ns+1, & ihi+1 ), lda, czero, work, sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight,a( ihi-ns+1, ihi+1 ), lda & ) call stdlib${ii}$_zgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,b( ihi-ns+1, & ihi+1 ), ldb, czero, work, sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight,b( ihi-ns+1, ihi+1 ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_zgemm( 'N', 'N', n, ns, ns, cone, q( 1_${ik}$, ihi-ns+1 ), ldq,qc, ldqc, czero,& work, n ) call stdlib${ii}$_zlacpy( 'ALL', n, ns, work, n, q( 1_${ik}$, ihi-ns+1 ), ldq ) end if ! update a(istartm:ihi-ns,ihi-ns:ihi) ! from the right with zc(1:ns+1,1:ns+1) sheight = ihi-ns-istartm+1 swidth = ns+1 if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_zgemm( 'N', 'N', sheight, swidth, swidth, cone,a( istartm, ihi-ns ), & lda, zc, ldzc, czero, work,sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ihi-ns ), lda & ) call stdlib${ii}$_zgemm( 'N', 'N', sheight, swidth, swidth, cone,b( istartm, ihi-ns ), & ldb, zc, ldzc, czero, work,sheight ) call stdlib${ii}$_zlacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ihi-ns ), ldb & ) end if if ( ilz ) then call stdlib${ii}$_zgemm( 'N', 'N', n, ns+1, ns+1, cone, z( 1_${ik}$, ihi-ns ), ldz,zc, ldzc, & czero, work, n ) call stdlib${ii}$_zlacpy( 'ALL', n, ns+1, work, n, z( 1_${ik}$, ihi-ns ), ldz ) end if end subroutine stdlib${ii}$_zlaqz3 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqz3( ilschur, ilq, ilz, n, ilo, ihi, nshifts,nblock_qesired, alpha,& !! ZLAQZ3: Executes a single multishift QZ sweep beta, a, lda, b, ldb,q, ldq, z, ldz, qc, ldqc, zc, ldzc, work,lwork, info ) use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! function arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, lda, ldb, ldq, ldz, lwork,nshifts, & nblock_qesired, ldqc, ldzc complex(${ck}$), intent( inout ) :: a( lda, * ), b( ldb, * ), q( ldq,* ), z( ldz, * ), qc( & ldqc, * ), zc( ldzc, * ), work( * ),alpha( * ), beta( * ) integer(${ik}$), intent( out ) :: info ! ================================================================ ! local scalars integer(${ik}$) :: i, j, ns, istartm, istopm, sheight, swidth, k, np, istartb, istopb, & ishift, nblock, npos real(${ck}$) :: safmin, safmax, c, scale complex(${ck}$) :: temp, temp2, temp3, s info = 0_${ik}$ if ( nblock_qesired < nshifts+1 ) then info = -8_${ik}$ end if if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = n*nblock_qesired return else if ( lwork < n*nblock_qesired ) then info = -25_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLAQZ3', -info ) return end if ! executable statements ! get machine constants safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safmax = one/safmin call stdlib${ii}$_${c2ri(ci)}$labad( safmin, safmax ) if ( ilo >= ihi ) then return end if if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if ns = nshifts npos = max( nblock_qesired-ns, 1_${ik}$ ) ! the following block introduces the shifts and chases ! them down one by one just enough to make space for ! the other shifts. the near-the-diagonal block is ! of size (ns+1) x ns. call stdlib${ii}$_${ci}$laset( 'FULL', ns+1, ns+1, czero, cone, qc, ldqc ) call stdlib${ii}$_${ci}$laset( 'FULL', ns, ns, czero, cone, zc, ldzc ) do i = 1, ns ! introduce the shift scale = sqrt( abs( alpha( i ) ) ) * sqrt( abs( beta( i ) ) ) if( scale >= safmin .and. scale <= safmax ) then alpha( i ) = alpha( i )/scale beta( i ) = beta( i )/scale end if temp2 = beta( i )*a( ilo, ilo )-alpha( i )*b( ilo, ilo ) temp3 = beta( i )*a( ilo+1, ilo ) if ( abs( temp2 ) > safmax .or.abs( temp3 ) > safmax ) then temp2 = cone temp3 = czero end if call stdlib${ii}$_${ci}$lartg( temp2, temp3, c, s, temp ) call stdlib${ii}$_${ci}$rot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda, c,s ) call stdlib${ii}$_${ci}$rot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb, c,s ) call stdlib${ii}$_${ci}$rot( ns+1, qc( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, qc( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c,conjg( s ) ) ! chase the shift down do j = 1, ns-i call stdlib${ii}$_${ci}$laqz1( .true., .true., j, 1_${ik}$, ns, ihi-ilo+1, a( ilo,ilo ), lda, b( & ilo, ilo ), ldb, ns+1, 1_${ik}$, qc,ldqc, ns, 1_${ik}$, zc, ldzc ) end do end do ! update the rest of the pencil ! update a(ilo:ilo+ns,ilo+ns:istopm) and b(ilo:ilo+ns,ilo+ns:istopm) ! from the left with qc(1:ns+1,1:ns+1)' sheight = ns+1 swidth = istopm-( ilo+ns )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,a( ilo, ilo+& ns ), lda, czero, work, sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight, a( ilo,ilo+ns ), lda ) call stdlib${ii}$_${ci}$gemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,b( ilo, ilo+& ns ), ldb, czero, work, sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight, b( ilo,ilo+ns ), ldb ) end if if ( ilq ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', n, sheight, sheight, cone, q( 1_${ik}$, ilo ),ldq, qc, ldqc, & czero, work, n ) call stdlib${ii}$_${ci}$lacpy( 'ALL', n, sheight, work, n, q( 1_${ik}$, ilo ), ldq ) end if ! update a(istartm:ilo-1,ilo:ilo+ns-1) and b(istartm:ilo-1,ilo:ilo+ns-1) ! from the right with zc(1:ns,1:ns) sheight = ilo-1-istartm+1 swidth = ns if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', sheight, swidth, swidth, cone,a( istartm, ilo ), lda, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ilo ), lda ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', sheight, swidth, swidth, cone,b( istartm, ilo ), ldb, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ilo ), ldb ) end if if ( ilz ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', n, swidth, swidth, cone, z( 1_${ik}$, ilo ),ldz, zc, ldzc, & czero, work, n ) call stdlib${ii}$_${ci}$lacpy( 'ALL', n, swidth, work, n, z( 1_${ik}$, ilo ), ldz ) end if ! the following block chases the shifts down to the bottom ! right block. if possible, a shift is moved down npos ! positions at a time k = ilo do while ( k < ihi-ns ) np = min( ihi-ns-k, npos ) ! size of the near-the-diagonal block nblock = ns+np ! istartb points to the first row we will be updating istartb = k+1 ! istopb points to the last column we will be updating istopb = k+nblock-1 call stdlib${ii}$_${ci}$laset( 'FULL', ns+np, ns+np, czero, cone, qc, ldqc ) call stdlib${ii}$_${ci}$laset( 'FULL', ns+np, ns+np, czero, cone, zc, ldzc ) ! near the diagonal shift chase do i = ns-1, 0, -1 do j = 0, np-1 ! move down the block with index k+i+j, updating ! the (ns+np x ns+np) block: ! (k:k+ns+np,k:k+ns+np-1) call stdlib${ii}$_${ci}$laqz1( .true., .true., k+i+j, istartb, istopb, ihi,a, lda, b, & ldb, nblock, k+1, qc, ldqc,nblock, k, zc, ldzc ) end do end do ! update rest of the pencil ! update a(k+1:k+ns+np, k+ns+np:istopm) and ! b(k+1:k+ns+np, k+ns+np:istopm) ! from the left with qc(1:ns+np,1:ns+np)' sheight = ns+np swidth = istopm-( k+ns+np )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'C', 'N', sheight, swidth, sheight, cone, qc,ldqc, a( k+1, k+& ns+np ), lda, czero, work,sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight, a( k+1,k+ns+np ), lda & ) call stdlib${ii}$_${ci}$gemm( 'C', 'N', sheight, swidth, sheight, cone, qc,ldqc, b( k+1, k+& ns+np ), ldb, czero, work,sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight, b( k+1,k+ns+np ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', n, nblock, nblock, cone, q( 1_${ik}$, k+1 ),ldq, qc, ldqc, & czero, work, n ) call stdlib${ii}$_${ci}$lacpy( 'ALL', n, nblock, work, n, q( 1_${ik}$, k+1 ), ldq ) end if ! update a(istartm:k,k:k+ns+npos-1) and b(istartm:k,k:k+ns+npos-1) ! from the right with zc(1:ns+np,1:ns+np) sheight = k-istartm+1 swidth = nblock if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', sheight, swidth, swidth, cone,a( istartm, k ), lda, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight,a( istartm, k ), lda ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', sheight, swidth, swidth, cone,b( istartm, k ), ldb, & zc, ldzc, czero, work,sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight,b( istartm, k ), ldb ) end if if ( ilz ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', n, nblock, nblock, cone, z( 1_${ik}$, k ),ldz, zc, ldzc, & czero, work, n ) call stdlib${ii}$_${ci}$lacpy( 'ALL', n, nblock, work, n, z( 1_${ik}$, k ), ldz ) end if k = k+np end do ! the following block removes the shifts from the bottom right corner ! one by one. updates are initially applied to a(ihi-ns+1:ihi,ihi-ns:ihi). call stdlib${ii}$_${ci}$laset( 'FULL', ns, ns, czero, cone, qc, ldqc ) call stdlib${ii}$_${ci}$laset( 'FULL', ns+1, ns+1, czero, cone, zc, ldzc ) ! istartb points to the first row we will be updating istartb = ihi-ns+1 ! istopb points to the last column we will be updating istopb = ihi do i = 1, ns ! chase the shift down to the bottom right corner do ishift = ihi-i, ihi-1 call stdlib${ii}$_${ci}$laqz1( .true., .true., ishift, istartb, istopb, ihi,a, lda, b, ldb, & ns, ihi-ns+1, qc, ldqc, ns+1,ihi-ns, zc, ldzc ) end do end do ! update rest of the pencil ! update a(ihi-ns+1:ihi, ihi+1:istopm) ! from the left with qc(1:ns,1:ns)' sheight = ns swidth = istopm-( ihi+1 )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,a( ihi-ns+1, & ihi+1 ), lda, czero, work, sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight,a( ihi-ns+1, ihi+1 ), lda & ) call stdlib${ii}$_${ci}$gemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,b( ihi-ns+1, & ihi+1 ), ldb, czero, work, sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight,b( ihi-ns+1, ihi+1 ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', n, ns, ns, cone, q( 1_${ik}$, ihi-ns+1 ), ldq,qc, ldqc, czero,& work, n ) call stdlib${ii}$_${ci}$lacpy( 'ALL', n, ns, work, n, q( 1_${ik}$, ihi-ns+1 ), ldq ) end if ! update a(istartm:ihi-ns,ihi-ns:ihi) ! from the right with zc(1:ns+1,1:ns+1) sheight = ihi-ns-istartm+1 swidth = ns+1 if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', sheight, swidth, swidth, cone,a( istartm, ihi-ns ), & lda, zc, ldzc, czero, work,sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ihi-ns ), lda & ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', sheight, swidth, swidth, cone,b( istartm, ihi-ns ), & ldb, zc, ldzc, czero, work,sheight ) call stdlib${ii}$_${ci}$lacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ihi-ns ), ldb & ) end if if ( ilz ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', n, ns+1, ns+1, cone, z( 1_${ik}$, ihi-ns ), ldz,zc, ldzc, & czero, work, n ) call stdlib${ii}$_${ci}$lacpy( 'ALL', n, ns+1, work, n, z( 1_${ik}$, ihi-ns ), ldz ) end if end subroutine stdlib${ii}$_${ci}$laqz3 #:endif #:endfor pure module subroutine stdlib${ii}$_slaqz4( ilschur, ilq, ilz, n, ilo, ihi, nshifts,nblock_desired, sr, & !! SLAQZ4 Executes a single multishift QZ sweep si, ss, a, lda, b, ldb, q,ldq, z, ldz, qc, ldqc, zc, ldzc, work, lwork,info ) use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! function arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, lda, ldb, ldq, ldz, lwork,nshifts, & nblock_desired, ldqc, ldzc real(sp), intent( inout ) :: a( lda, * ), b( ldb, * ), q( ldq, * ),z( ldz, * ), qc( & ldqc, * ), zc( ldzc, * ), work( * ), sr( * ),si( * ), ss( * ) integer(${ik}$), intent( out ) :: info ! ================================================================ ! local variables integer(${ik}$) :: i, j, ns, istartm, istopm, sheight, swidth, k, np, istartb, istopb, & ishift, nblock, npos real(sp) :: temp, v(3_${ik}$), c1, s1, c2, s2, swap info = 0_${ik}$ if ( nblock_desired < nshifts+1 ) then info = -8_${ik}$ end if if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = n*nblock_desired return else if ( lwork < n*nblock_desired ) then info = -25_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SLAQZ4', -info ) return end if ! executable statements if ( nshifts < 2_${ik}$ ) then return end if if ( ilo >= ihi ) then return end if if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if ! shuffle shifts into pairs of real shifts and pairs ! of complex conjugate shifts assuming complex ! conjugate shifts are already adjacent to one ! another do i = 1, nshifts-2, 2 if( si( i )/=-si( i+1 ) ) then swap = sr( i ) sr( i ) = sr( i+1 ) sr( i+1 ) = sr( i+2 ) sr( i+2 ) = swap swap = si( i ) si( i ) = si( i+1 ) si( i+1 ) = si( i+2 ) si( i+2 ) = swap swap = ss( i ) ss( i ) = ss( i+1 ) ss( i+1 ) = ss( i+2 ) ss( i+2 ) = swap end if end do ! nshfts is supposed to be even, but if it is odd, ! then simply reduce it by one. the shuffle above ! ensures that the dropped shift is real and that ! the remaining shifts are paired. ns = nshifts-mod( nshifts, 2_${ik}$ ) npos = max( nblock_desired-ns, 1_${ik}$ ) ! the following block introduces the shifts and chases ! them down one by one just enough to make space for ! the other shifts. the near-the-diagonal block is ! of size (ns+1) x ns. call stdlib${ii}$_slaset( 'FULL', ns+1, ns+1, zero, one, qc, ldqc ) call stdlib${ii}$_slaset( 'FULL', ns, ns, zero, one, zc, ldzc ) do i = 1, ns, 2 ! introduce the shift call stdlib${ii}$_slaqz1( a( ilo, ilo ), lda, b( ilo, ilo ), ldb, sr( i ),sr( i+1 ), si( & i ), ss( i ), ss( i+1 ), v ) temp = v( 2_${ik}$ ) call stdlib${ii}$_slartg( temp, v( 3_${ik}$ ), c1, s1, v( 2_${ik}$ ) ) call stdlib${ii}$_slartg( v( 1_${ik}$ ), v( 2_${ik}$ ), c2, s2, temp ) call stdlib${ii}$_srot( ns, a( ilo+1, ilo ), lda, a( ilo+2, ilo ), lda, c1,s1 ) call stdlib${ii}$_srot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda, c2,s2 ) call stdlib${ii}$_srot( ns, b( ilo+1, ilo ), ldb, b( ilo+2, ilo ), ldb, c1,s1 ) call stdlib${ii}$_srot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb, c2,s2 ) call stdlib${ii}$_srot( ns+1, qc( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, qc( 1_${ik}$, 3_${ik}$ ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_srot( ns+1, qc( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, qc( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c2, s2 ) ! chase the shift down do j = 1, ns-1-i call stdlib${ii}$_slaqz2( .true., .true., j, 1_${ik}$, ns, ihi-ilo+1, a( ilo,ilo ), lda, b( & ilo, ilo ), ldb, ns+1, 1_${ik}$, qc,ldqc, ns, 1_${ik}$, zc, ldzc ) end do end do ! update the rest of the pencil ! update a(ilo:ilo+ns,ilo+ns:istopm) and b(ilo:ilo+ns,ilo+ns:istopm) ! from the left with qc(1:ns+1,1:ns+1)' sheight = ns+1 swidth = istopm-( ilo+ns )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_sgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,a( ilo, ilo+ns & ), lda, zero, work, sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight, a( ilo,ilo+ns ), lda ) call stdlib${ii}$_sgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,b( ilo, ilo+ns & ), ldb, zero, work, sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight, b( ilo,ilo+ns ), ldb ) end if if ( ilq ) then call stdlib${ii}$_sgemm( 'N', 'N', n, sheight, sheight, one, q( 1_${ik}$, ilo ),ldq, qc, ldqc, & zero, work, n ) call stdlib${ii}$_slacpy( 'ALL', n, sheight, work, n, q( 1_${ik}$, ilo ), ldq ) end if ! update a(istartm:ilo-1,ilo:ilo+ns-1) and b(istartm:ilo-1,ilo:ilo+ns-1) ! from the right with zc(1:ns,1:ns) sheight = ilo-1-istartm+1 swidth = ns if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_sgemm( 'N', 'N', sheight, swidth, swidth, one, a( istartm,ilo ), lda, & zc, ldzc, zero, work, sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ilo ), lda ) call stdlib${ii}$_sgemm( 'N', 'N', sheight, swidth, swidth, one, b( istartm,ilo ), ldb, & zc, ldzc, zero, work, sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ilo ), ldb ) end if if ( ilz ) then call stdlib${ii}$_sgemm( 'N', 'N', n, swidth, swidth, one, z( 1_${ik}$, ilo ), ldz,zc, ldzc, & zero, work, n ) call stdlib${ii}$_slacpy( 'ALL', n, swidth, work, n, z( 1_${ik}$, ilo ), ldz ) end if ! the following block chases the shifts down to the bottom ! right block. if possible, a shift is moved down npos ! positions at a time k = ilo do while ( k < ihi-ns ) np = min( ihi-ns-k, npos ) ! size of the near-the-diagonal block nblock = ns+np ! istartb points to the first row we will be updating istartb = k+1 ! istopb points to the last column we will be updating istopb = k+nblock-1 call stdlib${ii}$_slaset( 'FULL', ns+np, ns+np, zero, one, qc, ldqc ) call stdlib${ii}$_slaset( 'FULL', ns+np, ns+np, zero, one, zc, ldzc ) ! near the diagonal shift chase do i = ns-1, 0, -2 do j = 0, np-1 ! move down the block with index k+i+j-1, updating ! the (ns+np x ns+np) block: ! (k:k+ns+np,k:k+ns+np-1) call stdlib${ii}$_slaqz2( .true., .true., k+i+j-1, istartb, istopb,ihi, a, lda, b, & ldb, nblock, k+1, qc, ldqc,nblock, k, zc, ldzc ) end do end do ! update rest of the pencil ! update a(k+1:k+ns+np, k+ns+np:istopm) and ! b(k+1:k+ns+np, k+ns+np:istopm) ! from the left with qc(1:ns+np,1:ns+np)' sheight = ns+np swidth = istopm-( k+ns+np )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_sgemm( 'T', 'N', sheight, swidth, sheight, one, qc,ldqc, a( k+1, k+& ns+np ), lda, zero, work,sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight, a( k+1,k+ns+np ), lda & ) call stdlib${ii}$_sgemm( 'T', 'N', sheight, swidth, sheight, one, qc,ldqc, b( k+1, k+& ns+np ), ldb, zero, work,sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight, b( k+1,k+ns+np ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_sgemm( 'N', 'N', n, nblock, nblock, one, q( 1_${ik}$, k+1 ),ldq, qc, ldqc, & zero, work, n ) call stdlib${ii}$_slacpy( 'ALL', n, nblock, work, n, q( 1_${ik}$, k+1 ), ldq ) end if ! update a(istartm:k,k:k+ns+npos-1) and b(istartm:k,k:k+ns+npos-1) ! from the right with zc(1:ns+np,1:ns+np) sheight = k-istartm+1 swidth = nblock if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_sgemm( 'N', 'N', sheight, swidth, swidth, one,a( istartm, k ), lda, & zc, ldzc, zero, work,sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight,a( istartm, k ), lda ) call stdlib${ii}$_sgemm( 'N', 'N', sheight, swidth, swidth, one,b( istartm, k ), ldb, & zc, ldzc, zero, work,sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight,b( istartm, k ), ldb ) end if if ( ilz ) then call stdlib${ii}$_sgemm( 'N', 'N', n, nblock, nblock, one, z( 1_${ik}$, k ),ldz, zc, ldzc, & zero, work, n ) call stdlib${ii}$_slacpy( 'ALL', n, nblock, work, n, z( 1_${ik}$, k ), ldz ) end if k = k+np end do ! the following block removes the shifts from the bottom right corner ! one by one. updates are initially applied to a(ihi-ns+1:ihi,ihi-ns:ihi). call stdlib${ii}$_slaset( 'FULL', ns, ns, zero, one, qc, ldqc ) call stdlib${ii}$_slaset( 'FULL', ns+1, ns+1, zero, one, zc, ldzc ) ! istartb points to the first row we will be updating istartb = ihi-ns+1 ! istopb points to the last column we will be updating istopb = ihi do i = 1, ns, 2 ! chase the shift down to the bottom right corner do ishift = ihi-i-1, ihi-2 call stdlib${ii}$_slaqz2( .true., .true., ishift, istartb, istopb, ihi,a, lda, b, ldb, & ns, ihi-ns+1, qc, ldqc, ns+1,ihi-ns, zc, ldzc ) end do end do ! update rest of the pencil ! update a(ihi-ns+1:ihi, ihi+1:istopm) ! from the left with qc(1:ns,1:ns)' sheight = ns swidth = istopm-( ihi+1 )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_sgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,a( ihi-ns+1, & ihi+1 ), lda, zero, work, sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight,a( ihi-ns+1, ihi+1 ), lda & ) call stdlib${ii}$_sgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,b( ihi-ns+1, & ihi+1 ), ldb, zero, work, sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight,b( ihi-ns+1, ihi+1 ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_sgemm( 'N', 'N', n, ns, ns, one, q( 1_${ik}$, ihi-ns+1 ), ldq,qc, ldqc, zero, & work, n ) call stdlib${ii}$_slacpy( 'ALL', n, ns, work, n, q( 1_${ik}$, ihi-ns+1 ), ldq ) end if ! update a(istartm:ihi-ns,ihi-ns:ihi) ! from the right with zc(1:ns+1,1:ns+1) sheight = ihi-ns-istartm+1 swidth = ns+1 if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_sgemm( 'N', 'N', sheight, swidth, swidth, one, a( istartm,ihi-ns ), lda,& zc, ldzc, zero, work, sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ihi-ns ), lda & ) call stdlib${ii}$_sgemm( 'N', 'N', sheight, swidth, swidth, one, b( istartm,ihi-ns ), ldb,& zc, ldzc, zero, work, sheight ) call stdlib${ii}$_slacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ihi-ns ), ldb & ) end if if ( ilz ) then call stdlib${ii}$_sgemm( 'N', 'N', n, ns+1, ns+1, one, z( 1_${ik}$, ihi-ns ), ldz, zc,ldzc, zero, & work, n ) call stdlib${ii}$_slacpy( 'ALL', n, ns+1, work, n, z( 1_${ik}$, ihi-ns ), ldz ) end if end subroutine stdlib${ii}$_slaqz4 pure module subroutine stdlib${ii}$_dlaqz4( ilschur, ilq, ilz, n, ilo, ihi, nshifts,nblock_desired, sr, & !! DLAQZ4 Executes a single multishift QZ sweep si, ss, a, lda, b, ldb, q,ldq, z, ldz, qc, ldqc, zc, ldzc, work, lwork,info ) use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! function arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, lda, ldb, ldq, ldz, lwork,nshifts, & nblock_desired, ldqc, ldzc real(dp), intent( inout ) :: a( lda, * ), b( ldb, * ),q( ldq, * ), z( ldz, * ), qc( & ldqc, * ),zc( ldzc, * ), work( * ), sr( * ), si( * ),ss( * ) integer(${ik}$), intent( out ) :: info ! ================================================================ ! local scalars integer(${ik}$) :: i, j, ns, istartm, istopm, sheight, swidth, k, np, istartb, istopb, & ishift, nblock, npos real(dp) :: temp, v(3_${ik}$), c1, s1, c2, s2, swap info = 0_${ik}$ if ( nblock_desired < nshifts+1 ) then info = -8_${ik}$ end if if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = n*nblock_desired return else if ( lwork < n*nblock_desired ) then info = -25_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLAQZ4', -info ) return end if ! executable statements if ( nshifts < 2_${ik}$ ) then return end if if ( ilo >= ihi ) then return end if if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if ! shuffle shifts into pairs of real shifts and pairs ! of complex conjugate shifts assuming complex ! conjugate shifts are already adjacent to one ! another do i = 1, nshifts-2, 2 if( si( i )/=-si( i+1 ) ) then swap = sr( i ) sr( i ) = sr( i+1 ) sr( i+1 ) = sr( i+2 ) sr( i+2 ) = swap swap = si( i ) si( i ) = si( i+1 ) si( i+1 ) = si( i+2 ) si( i+2 ) = swap swap = ss( i ) ss( i ) = ss( i+1 ) ss( i+1 ) = ss( i+2 ) ss( i+2 ) = swap end if end do ! nshfts is supposed to be even, but if it is odd, ! then simply reduce it by one. the shuffle above ! ensures that the dropped shift is real and that ! the remaining shifts are paired. ns = nshifts-mod( nshifts, 2_${ik}$ ) npos = max( nblock_desired-ns, 1_${ik}$ ) ! the following block introduces the shifts and chases ! them down one by one just enough to make space for ! the other shifts. the near-the-diagonal block is ! of size (ns+1) x ns. call stdlib${ii}$_dlaset( 'FULL', ns+1, ns+1, zero, one, qc, ldqc ) call stdlib${ii}$_dlaset( 'FULL', ns, ns, zero, one, zc, ldzc ) do i = 1, ns, 2 ! introduce the shift call stdlib${ii}$_dlaqz1( a( ilo, ilo ), lda, b( ilo, ilo ), ldb, sr( i ),sr( i+1 ), si( & i ), ss( i ), ss( i+1 ), v ) temp = v( 2_${ik}$ ) call stdlib${ii}$_dlartg( temp, v( 3_${ik}$ ), c1, s1, v( 2_${ik}$ ) ) call stdlib${ii}$_dlartg( v( 1_${ik}$ ), v( 2_${ik}$ ), c2, s2, temp ) call stdlib${ii}$_drot( ns, a( ilo+1, ilo ), lda, a( ilo+2, ilo ), lda, c1,s1 ) call stdlib${ii}$_drot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda, c2,s2 ) call stdlib${ii}$_drot( ns, b( ilo+1, ilo ), ldb, b( ilo+2, ilo ), ldb, c1,s1 ) call stdlib${ii}$_drot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb, c2,s2 ) call stdlib${ii}$_drot( ns+1, qc( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, qc( 1_${ik}$, 3_${ik}$ ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_drot( ns+1, qc( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, qc( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c2, s2 ) ! chase the shift down do j = 1, ns-1-i call stdlib${ii}$_dlaqz2( .true., .true., j, 1_${ik}$, ns, ihi-ilo+1, a( ilo,ilo ), lda, b( & ilo, ilo ), ldb, ns+1, 1_${ik}$, qc,ldqc, ns, 1_${ik}$, zc, ldzc ) end do end do ! update the rest of the pencil ! update a(ilo:ilo+ns,ilo+ns:istopm) and b(ilo:ilo+ns,ilo+ns:istopm) ! from the left with qc(1:ns+1,1:ns+1)' sheight = ns+1 swidth = istopm-( ilo+ns )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_dgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,a( ilo, ilo+ns & ), lda, zero, work, sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight, a( ilo,ilo+ns ), lda ) call stdlib${ii}$_dgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,b( ilo, ilo+ns & ), ldb, zero, work, sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight, b( ilo,ilo+ns ), ldb ) end if if ( ilq ) then call stdlib${ii}$_dgemm( 'N', 'N', n, sheight, sheight, one, q( 1_${ik}$, ilo ),ldq, qc, ldqc, & zero, work, n ) call stdlib${ii}$_dlacpy( 'ALL', n, sheight, work, n, q( 1_${ik}$, ilo ), ldq ) end if ! update a(istartm:ilo-1,ilo:ilo+ns-1) and b(istartm:ilo-1,ilo:ilo+ns-1) ! from the right with zc(1:ns,1:ns) sheight = ilo-1-istartm+1 swidth = ns if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_dgemm( 'N', 'N', sheight, swidth, swidth, one, a( istartm,ilo ), lda, & zc, ldzc, zero, work, sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ilo ), lda ) call stdlib${ii}$_dgemm( 'N', 'N', sheight, swidth, swidth, one, b( istartm,ilo ), ldb, & zc, ldzc, zero, work, sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ilo ), ldb ) end if if ( ilz ) then call stdlib${ii}$_dgemm( 'N', 'N', n, swidth, swidth, one, z( 1_${ik}$, ilo ), ldz,zc, ldzc, & zero, work, n ) call stdlib${ii}$_dlacpy( 'ALL', n, swidth, work, n, z( 1_${ik}$, ilo ), ldz ) end if ! the following block chases the shifts down to the bottom ! right block. if possible, a shift is moved down npos ! positions at a time k = ilo do while ( k < ihi-ns ) np = min( ihi-ns-k, npos ) ! size of the near-the-diagonal block nblock = ns+np ! istartb points to the first row we will be updating istartb = k+1 ! istopb points to the last column we will be updating istopb = k+nblock-1 call stdlib${ii}$_dlaset( 'FULL', ns+np, ns+np, zero, one, qc, ldqc ) call stdlib${ii}$_dlaset( 'FULL', ns+np, ns+np, zero, one, zc, ldzc ) ! near the diagonal shift chase do i = ns-1, 0, -2 do j = 0, np-1 ! move down the block with index k+i+j-1, updating ! the (ns+np x ns+np) block: ! (k:k+ns+np,k:k+ns+np-1) call stdlib${ii}$_dlaqz2( .true., .true., k+i+j-1, istartb, istopb,ihi, a, lda, b, & ldb, nblock, k+1, qc, ldqc,nblock, k, zc, ldzc ) end do end do ! update rest of the pencil ! update a(k+1:k+ns+np, k+ns+np:istopm) and ! b(k+1:k+ns+np, k+ns+np:istopm) ! from the left with qc(1:ns+np,1:ns+np)' sheight = ns+np swidth = istopm-( k+ns+np )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_dgemm( 'T', 'N', sheight, swidth, sheight, one, qc,ldqc, a( k+1, k+& ns+np ), lda, zero, work,sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight, a( k+1,k+ns+np ), lda & ) call stdlib${ii}$_dgemm( 'T', 'N', sheight, swidth, sheight, one, qc,ldqc, b( k+1, k+& ns+np ), ldb, zero, work,sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight, b( k+1,k+ns+np ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_dgemm( 'N', 'N', n, nblock, nblock, one, q( 1_${ik}$, k+1 ),ldq, qc, ldqc, & zero, work, n ) call stdlib${ii}$_dlacpy( 'ALL', n, nblock, work, n, q( 1_${ik}$, k+1 ), ldq ) end if ! update a(istartm:k,k:k+ns+npos-1) and b(istartm:k,k:k+ns+npos-1) ! from the right with zc(1:ns+np,1:ns+np) sheight = k-istartm+1 swidth = nblock if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_dgemm( 'N', 'N', sheight, swidth, swidth, one,a( istartm, k ), lda, & zc, ldzc, zero, work,sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight,a( istartm, k ), lda ) call stdlib${ii}$_dgemm( 'N', 'N', sheight, swidth, swidth, one,b( istartm, k ), ldb, & zc, ldzc, zero, work,sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight,b( istartm, k ), ldb ) end if if ( ilz ) then call stdlib${ii}$_dgemm( 'N', 'N', n, nblock, nblock, one, z( 1_${ik}$, k ),ldz, zc, ldzc, & zero, work, n ) call stdlib${ii}$_dlacpy( 'ALL', n, nblock, work, n, z( 1_${ik}$, k ), ldz ) end if k = k+np end do ! the following block removes the shifts from the bottom right corner ! one by one. updates are initially applied to a(ihi-ns+1:ihi,ihi-ns:ihi). call stdlib${ii}$_dlaset( 'FULL', ns, ns, zero, one, qc, ldqc ) call stdlib${ii}$_dlaset( 'FULL', ns+1, ns+1, zero, one, zc, ldzc ) ! istartb points to the first row we will be updating istartb = ihi-ns+1 ! istopb points to the last column we will be updating istopb = ihi do i = 1, ns, 2 ! chase the shift down to the bottom right corner do ishift = ihi-i-1, ihi-2 call stdlib${ii}$_dlaqz2( .true., .true., ishift, istartb, istopb, ihi,a, lda, b, ldb, & ns, ihi-ns+1, qc, ldqc, ns+1,ihi-ns, zc, ldzc ) end do end do ! update rest of the pencil ! update a(ihi-ns+1:ihi, ihi+1:istopm) ! from the left with qc(1:ns,1:ns)' sheight = ns swidth = istopm-( ihi+1 )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_dgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,a( ihi-ns+1, & ihi+1 ), lda, zero, work, sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight,a( ihi-ns+1, ihi+1 ), lda & ) call stdlib${ii}$_dgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,b( ihi-ns+1, & ihi+1 ), ldb, zero, work, sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight,b( ihi-ns+1, ihi+1 ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_dgemm( 'N', 'N', n, ns, ns, one, q( 1_${ik}$, ihi-ns+1 ), ldq,qc, ldqc, zero, & work, n ) call stdlib${ii}$_dlacpy( 'ALL', n, ns, work, n, q( 1_${ik}$, ihi-ns+1 ), ldq ) end if ! update a(istartm:ihi-ns,ihi-ns:ihi) ! from the right with zc(1:ns+1,1:ns+1) sheight = ihi-ns-istartm+1 swidth = ns+1 if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_dgemm( 'N', 'N', sheight, swidth, swidth, one, a( istartm,ihi-ns ), lda,& zc, ldzc, zero, work, sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ihi-ns ), lda & ) call stdlib${ii}$_dgemm( 'N', 'N', sheight, swidth, swidth, one, b( istartm,ihi-ns ), ldb,& zc, ldzc, zero, work, sheight ) call stdlib${ii}$_dlacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ihi-ns ), ldb & ) end if if ( ilz ) then call stdlib${ii}$_dgemm( 'N', 'N', n, ns+1, ns+1, one, z( 1_${ik}$, ihi-ns ), ldz,zc, ldzc, zero,& work, n ) call stdlib${ii}$_dlacpy( 'ALL', n, ns+1, work, n, z( 1_${ik}$, ihi-ns ), ldz ) end if end subroutine stdlib${ii}$_dlaqz4 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqz4( ilschur, ilq, ilz, n, ilo, ihi, nshifts,nblock_qesired, sr, & !! DLAQZ4: Executes a single multishift QZ sweep si, ss, a, lda, b, ldb, q,ldq, z, ldz, qc, ldqc, zc, ldzc, work, lwork,info ) use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! function arguments logical(lk), intent( in ) :: ilschur, ilq, ilz integer(${ik}$), intent( in ) :: n, ilo, ihi, lda, ldb, ldq, ldz, lwork,nshifts, & nblock_qesired, ldqc, ldzc real(${rk}$), intent( inout ) :: a( lda, * ), b( ldb, * ),q( ldq, * ), z( ldz, * ), qc( & ldqc, * ),zc( ldzc, * ), work( * ), sr( * ), si( * ),ss( * ) integer(${ik}$), intent( out ) :: info ! ================================================================ ! local scalars integer(${ik}$) :: i, j, ns, istartm, istopm, sheight, swidth, k, np, istartb, istopb, & ishift, nblock, npos real(${rk}$) :: temp, v(3_${ik}$), c1, s1, c2, s2, swap info = 0_${ik}$ if ( nblock_qesired < nshifts+1 ) then info = -8_${ik}$ end if if ( lwork ==-1_${ik}$ ) then ! workspace query, quick return work( 1_${ik}$ ) = n*nblock_qesired return else if ( lwork < n*nblock_qesired ) then info = -25_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLAQZ4', -info ) return end if ! executable statements if ( nshifts < 2_${ik}$ ) then return end if if ( ilo >= ihi ) then return end if if ( ilschur ) then istartm = 1_${ik}$ istopm = n else istartm = ilo istopm = ihi end if ! shuffle shifts into pairs of real shifts and pairs ! of complex conjugate shifts assuming complex ! conjugate shifts are already adjacent to one ! another do i = 1, nshifts-2, 2 if( si( i )/=-si( i+1 ) ) then swap = sr( i ) sr( i ) = sr( i+1 ) sr( i+1 ) = sr( i+2 ) sr( i+2 ) = swap swap = si( i ) si( i ) = si( i+1 ) si( i+1 ) = si( i+2 ) si( i+2 ) = swap swap = ss( i ) ss( i ) = ss( i+1 ) ss( i+1 ) = ss( i+2 ) ss( i+2 ) = swap end if end do ! nshfts is supposed to be even, but if it is odd, ! then simply reduce it by one. the shuffle above ! ensures that the dropped shift is real and that ! the remaining shifts are paired. ns = nshifts-mod( nshifts, 2_${ik}$ ) npos = max( nblock_qesired-ns, 1_${ik}$ ) ! the following block introduces the shifts and chases ! them down one by one just enough to make space for ! the other shifts. the near-the-diagonal block is ! of size (ns+1) x ns. call stdlib${ii}$_${ri}$laset( 'FULL', ns+1, ns+1, zero, one, qc, ldqc ) call stdlib${ii}$_${ri}$laset( 'FULL', ns, ns, zero, one, zc, ldzc ) do i = 1, ns, 2 ! introduce the shift call stdlib${ii}$_${ri}$laqz1( a( ilo, ilo ), lda, b( ilo, ilo ), ldb, sr( i ),sr( i+1 ), si( & i ), ss( i ), ss( i+1 ), v ) temp = v( 2_${ik}$ ) call stdlib${ii}$_${ri}$lartg( temp, v( 3_${ik}$ ), c1, s1, v( 2_${ik}$ ) ) call stdlib${ii}$_${ri}$lartg( v( 1_${ik}$ ), v( 2_${ik}$ ), c2, s2, temp ) call stdlib${ii}$_${ri}$rot( ns, a( ilo+1, ilo ), lda, a( ilo+2, ilo ), lda, c1,s1 ) call stdlib${ii}$_${ri}$rot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda, c2,s2 ) call stdlib${ii}$_${ri}$rot( ns, b( ilo+1, ilo ), ldb, b( ilo+2, ilo ), ldb, c1,s1 ) call stdlib${ii}$_${ri}$rot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb, c2,s2 ) call stdlib${ii}$_${ri}$rot( ns+1, qc( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, qc( 1_${ik}$, 3_${ik}$ ), 1_${ik}$, c1, s1 ) call stdlib${ii}$_${ri}$rot( ns+1, qc( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, qc( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, c2, s2 ) ! chase the shift down do j = 1, ns-1-i call stdlib${ii}$_${ri}$laqz2( .true., .true., j, 1_${ik}$, ns, ihi-ilo+1, a( ilo,ilo ), lda, b( & ilo, ilo ), ldb, ns+1, 1_${ik}$, qc,ldqc, ns, 1_${ik}$, zc, ldzc ) end do end do ! update the rest of the pencil ! update a(ilo:ilo+ns,ilo+ns:istopm) and b(ilo:ilo+ns,ilo+ns:istopm) ! from the left with qc(1:ns+1,1:ns+1)' sheight = ns+1 swidth = istopm-( ilo+ns )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,a( ilo, ilo+ns & ), lda, zero, work, sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight, a( ilo,ilo+ns ), lda ) call stdlib${ii}$_${ri}$gemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,b( ilo, ilo+ns & ), ldb, zero, work, sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight, b( ilo,ilo+ns ), ldb ) end if if ( ilq ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, sheight, sheight, one, q( 1_${ik}$, ilo ),ldq, qc, ldqc, & zero, work, n ) call stdlib${ii}$_${ri}$lacpy( 'ALL', n, sheight, work, n, q( 1_${ik}$, ilo ), ldq ) end if ! update a(istartm:ilo-1,ilo:ilo+ns-1) and b(istartm:ilo-1,ilo:ilo+ns-1) ! from the right with zc(1:ns,1:ns) sheight = ilo-1-istartm+1 swidth = ns if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', sheight, swidth, swidth, one, a( istartm,ilo ), lda, & zc, ldzc, zero, work, sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ilo ), lda ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', sheight, swidth, swidth, one, b( istartm,ilo ), ldb, & zc, ldzc, zero, work, sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ilo ), ldb ) end if if ( ilz ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, swidth, swidth, one, z( 1_${ik}$, ilo ), ldz,zc, ldzc, & zero, work, n ) call stdlib${ii}$_${ri}$lacpy( 'ALL', n, swidth, work, n, z( 1_${ik}$, ilo ), ldz ) end if ! the following block chases the shifts down to the bottom ! right block. if possible, a shift is moved down npos ! positions at a time k = ilo do while ( k < ihi-ns ) np = min( ihi-ns-k, npos ) ! size of the near-the-diagonal block nblock = ns+np ! istartb points to the first row we will be updating istartb = k+1 ! istopb points to the last column we will be updating istopb = k+nblock-1 call stdlib${ii}$_${ri}$laset( 'FULL', ns+np, ns+np, zero, one, qc, ldqc ) call stdlib${ii}$_${ri}$laset( 'FULL', ns+np, ns+np, zero, one, zc, ldzc ) ! near the diagonal shift chase do i = ns-1, 0, -2 do j = 0, np-1 ! move down the block with index k+i+j-1, updating ! the (ns+np x ns+np) block: ! (k:k+ns+np,k:k+ns+np-1) call stdlib${ii}$_${ri}$laqz2( .true., .true., k+i+j-1, istartb, istopb,ihi, a, lda, b, & ldb, nblock, k+1, qc, ldqc,nblock, k, zc, ldzc ) end do end do ! update rest of the pencil ! update a(k+1:k+ns+np, k+ns+np:istopm) and ! b(k+1:k+ns+np, k+ns+np:istopm) ! from the left with qc(1:ns+np,1:ns+np)' sheight = ns+np swidth = istopm-( k+ns+np )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'T', 'N', sheight, swidth, sheight, one, qc,ldqc, a( k+1, k+& ns+np ), lda, zero, work,sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight, a( k+1,k+ns+np ), lda & ) call stdlib${ii}$_${ri}$gemm( 'T', 'N', sheight, swidth, sheight, one, qc,ldqc, b( k+1, k+& ns+np ), ldb, zero, work,sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight, b( k+1,k+ns+np ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, nblock, nblock, one, q( 1_${ik}$, k+1 ),ldq, qc, ldqc, & zero, work, n ) call stdlib${ii}$_${ri}$lacpy( 'ALL', n, nblock, work, n, q( 1_${ik}$, k+1 ), ldq ) end if ! update a(istartm:k,k:k+ns+npos-1) and b(istartm:k,k:k+ns+npos-1) ! from the right with zc(1:ns+np,1:ns+np) sheight = k-istartm+1 swidth = nblock if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', sheight, swidth, swidth, one,a( istartm, k ), lda, & zc, ldzc, zero, work,sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight,a( istartm, k ), lda ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', sheight, swidth, swidth, one,b( istartm, k ), ldb, & zc, ldzc, zero, work,sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight,b( istartm, k ), ldb ) end if if ( ilz ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, nblock, nblock, one, z( 1_${ik}$, k ),ldz, zc, ldzc, & zero, work, n ) call stdlib${ii}$_${ri}$lacpy( 'ALL', n, nblock, work, n, z( 1_${ik}$, k ), ldz ) end if k = k+np end do ! the following block removes the shifts from the bottom right corner ! one by one. updates are initially applied to a(ihi-ns+1:ihi,ihi-ns:ihi). call stdlib${ii}$_${ri}$laset( 'FULL', ns, ns, zero, one, qc, ldqc ) call stdlib${ii}$_${ri}$laset( 'FULL', ns+1, ns+1, zero, one, zc, ldzc ) ! istartb points to the first row we will be updating istartb = ihi-ns+1 ! istopb points to the last column we will be updating istopb = ihi do i = 1, ns, 2 ! chase the shift down to the bottom right corner do ishift = ihi-i-1, ihi-2 call stdlib${ii}$_${ri}$laqz2( .true., .true., ishift, istartb, istopb, ihi,a, lda, b, ldb, & ns, ihi-ns+1, qc, ldqc, ns+1,ihi-ns, zc, ldzc ) end do end do ! update rest of the pencil ! update a(ihi-ns+1:ihi, ihi+1:istopm) ! from the left with qc(1:ns,1:ns)' sheight = ns swidth = istopm-( ihi+1 )+1_${ik}$ if ( swidth > 0_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,a( ihi-ns+1, & ihi+1 ), lda, zero, work, sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight,a( ihi-ns+1, ihi+1 ), lda & ) call stdlib${ii}$_${ri}$gemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,b( ihi-ns+1, & ihi+1 ), ldb, zero, work, sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight,b( ihi-ns+1, ihi+1 ), ldb & ) end if if ( ilq ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, ns, ns, one, q( 1_${ik}$, ihi-ns+1 ), ldq,qc, ldqc, zero, & work, n ) call stdlib${ii}$_${ri}$lacpy( 'ALL', n, ns, work, n, q( 1_${ik}$, ihi-ns+1 ), ldq ) end if ! update a(istartm:ihi-ns,ihi-ns:ihi) ! from the right with zc(1:ns+1,1:ns+1) sheight = ihi-ns-istartm+1 swidth = ns+1 if ( sheight > 0_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', sheight, swidth, swidth, one, a( istartm,ihi-ns ), lda,& zc, ldzc, zero, work, sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,ihi-ns ), lda & ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', sheight, swidth, swidth, one, b( istartm,ihi-ns ), ldb,& zc, ldzc, zero, work, sheight ) call stdlib${ii}$_${ri}$lacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,ihi-ns ), ldb & ) end if if ( ilz ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, ns+1, ns+1, one, z( 1_${ik}$, ihi-ns ), ldz,zc, ldzc, zero,& work, n ) call stdlib${ii}$_${ri}$lacpy( 'ALL', n, ns+1, work, n, z( 1_${ik}$, ihi-ns ), ldz ) end if end subroutine stdlib${ii}$_${ri}$laqz4 #:endif #:endfor #:endfor end submodule stdlib_lapack_eigv_gen3 fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_solve_lu_comp.fypp0000664000175000017500000331546515135654166026653 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_solve) stdlib_lapack_solve_lu_comp implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgecon( norm, n, a, lda, anorm, rcond, work, iwork,info ) !! SGECON estimates the reciprocal of the condition number of a general !! real matrix A, in either the 1-norm or the infinity-norm, using !! the LU factorization computed by SGETRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as !! RCOND = 1 / ( norm(A) * norm(inv(A)) ). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: norm integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: onenrm character :: normin integer(${ik}$) :: ix, kase, kase1 real(sp) :: ainvnm, scale, sl, smlnum, su ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ onenrm = norm=='1' .or. stdlib_lsame( norm, 'O' ) if( .not.onenrm .and. .not.stdlib_lsame( norm, 'I' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, iinfo, j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=min( m, n ) ) then ! use unblocked code. call stdlib${ii}$_sgetrf2( m, n, a, lda, ipiv, info ) else ! use blocked code. do j = 1, min( m, n ), nb jb = min( min( m, n )-j+1, nb ) ! factor diagonal and subdiagonal blocks and test for exact ! singularity. call stdlib${ii}$_sgetrf2( m-j+1, jb, a( j, j ), lda, ipiv( j ), iinfo ) ! adjust info and the pivot indices. if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + j - 1_${ik}$ do i = j, min( m, j+jb-1 ) ipiv( i ) = j - 1_${ik}$ + ipiv( i ) end do ! apply interchanges to columns 1:j-1. call stdlib${ii}$_slaswp( j-1, a, lda, j, j+jb-1, ipiv, 1_${ik}$ ) if( j+jb<=n ) then ! apply interchanges to columns j+jb:n. call stdlib${ii}$_slaswp( n-j-jb+1, a( 1_${ik}$, j+jb ), lda, j, j+jb-1,ipiv, 1_${ik}$ ) ! compute block row of u. call stdlib${ii}$_strsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT', jb,n-j-jb+1, one, & a( j, j ), lda, a( j, j+jb ),lda ) if( j+jb<=m ) then ! update trailing submatrix. call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-j-jb+1,n-j-jb+1, jb, -& one, a( j+jb, j ), lda,a( j, j+jb ), lda, one, a( j+jb, j+jb ),lda ) end if end if end do end if return end subroutine stdlib${ii}$_sgetrf pure module subroutine stdlib${ii}$_dgetrf( m, n, a, lda, ipiv, info ) !! DGETRF computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, iinfo, j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=min( m, n ) ) then ! use unblocked code. call stdlib${ii}$_dgetrf2( m, n, a, lda, ipiv, info ) else ! use blocked code. do j = 1, min( m, n ), nb jb = min( min( m, n )-j+1, nb ) ! factor diagonal and subdiagonal blocks and test for exact ! singularity. call stdlib${ii}$_dgetrf2( m-j+1, jb, a( j, j ), lda, ipiv( j ), iinfo ) ! adjust info and the pivot indices. if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + j - 1_${ik}$ do i = j, min( m, j+jb-1 ) ipiv( i ) = j - 1_${ik}$ + ipiv( i ) end do ! apply interchanges to columns 1:j-1. call stdlib${ii}$_dlaswp( j-1, a, lda, j, j+jb-1, ipiv, 1_${ik}$ ) if( j+jb<=n ) then ! apply interchanges to columns j+jb:n. call stdlib${ii}$_dlaswp( n-j-jb+1, a( 1_${ik}$, j+jb ), lda, j, j+jb-1,ipiv, 1_${ik}$ ) ! compute block row of u. call stdlib${ii}$_dtrsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT', jb,n-j-jb+1, one, & a( j, j ), lda, a( j, j+jb ),lda ) if( j+jb<=m ) then ! update trailing submatrix. call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-j-jb+1,n-j-jb+1, jb, -& one, a( j+jb, j ), lda,a( j, j+jb ), lda, one, a( j+jb, j+jb ),lda ) end if end if end do end if return end subroutine stdlib${ii}$_dgetrf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$getrf( m, n, a, lda, ipiv, info ) !! DGETRF: computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, iinfo, j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=min( m, n ) ) then ! use unblocked code. call stdlib${ii}$_${ri}$getrf2( m, n, a, lda, ipiv, info ) else ! use blocked code. do j = 1, min( m, n ), nb jb = min( min( m, n )-j+1, nb ) ! factor diagonal and subdiagonal blocks and test for exact ! singularity. call stdlib${ii}$_${ri}$getrf2( m-j+1, jb, a( j, j ), lda, ipiv( j ), iinfo ) ! adjust info and the pivot indices. if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + j - 1_${ik}$ do i = j, min( m, j+jb-1 ) ipiv( i ) = j - 1_${ik}$ + ipiv( i ) end do ! apply interchanges to columns 1:j-1. call stdlib${ii}$_${ri}$laswp( j-1, a, lda, j, j+jb-1, ipiv, 1_${ik}$ ) if( j+jb<=n ) then ! apply interchanges to columns j+jb:n. call stdlib${ii}$_${ri}$laswp( n-j-jb+1, a( 1_${ik}$, j+jb ), lda, j, j+jb-1,ipiv, 1_${ik}$ ) ! compute block row of u. call stdlib${ii}$_${ri}$trsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT', jb,n-j-jb+1, one, & a( j, j ), lda, a( j, j+jb ),lda ) if( j+jb<=m ) then ! update trailing submatrix. call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-j-jb+1,n-j-jb+1, jb, -& one, a( j+jb, j ), lda,a( j, j+jb ), lda, one, a( j+jb, j+jb ),lda ) end if end if end do end if return end subroutine stdlib${ii}$_${ri}$getrf #:endif #:endfor pure module subroutine stdlib${ii}$_cgetrf( m, n, a, lda, ipiv, info ) !! CGETRF computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, iinfo, j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=min( m, n ) ) then ! use unblocked code. call stdlib${ii}$_cgetrf2( m, n, a, lda, ipiv, info ) else ! use blocked code. do j = 1, min( m, n ), nb jb = min( min( m, n )-j+1, nb ) ! factor diagonal and subdiagonal blocks and test for exact ! singularity. call stdlib${ii}$_cgetrf2( m-j+1, jb, a( j, j ), lda, ipiv( j ), iinfo ) ! adjust info and the pivot indices. if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + j - 1_${ik}$ do i = j, min( m, j+jb-1 ) ipiv( i ) = j - 1_${ik}$ + ipiv( i ) end do ! apply interchanges to columns 1:j-1. call stdlib${ii}$_claswp( j-1, a, lda, j, j+jb-1, ipiv, 1_${ik}$ ) if( j+jb<=n ) then ! apply interchanges to columns j+jb:n. call stdlib${ii}$_claswp( n-j-jb+1, a( 1_${ik}$, j+jb ), lda, j, j+jb-1,ipiv, 1_${ik}$ ) ! compute block row of u. call stdlib${ii}$_ctrsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT', jb,n-j-jb+1, cone,& a( j, j ), lda, a( j, j+jb ),lda ) if( j+jb<=m ) then ! update trailing submatrix. call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-j-jb+1,n-j-jb+1, jb, -& cone, a( j+jb, j ), lda,a( j, j+jb ), lda, cone, a( j+jb, j+jb ),lda ) end if end if end do end if return end subroutine stdlib${ii}$_cgetrf pure module subroutine stdlib${ii}$_zgetrf( m, n, a, lda, ipiv, info ) !! ZGETRF computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, iinfo, j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=min( m, n ) ) then ! use unblocked code. call stdlib${ii}$_zgetrf2( m, n, a, lda, ipiv, info ) else ! use blocked code. do j = 1, min( m, n ), nb jb = min( min( m, n )-j+1, nb ) ! factor diagonal and subdiagonal blocks and test for exact ! singularity. call stdlib${ii}$_zgetrf2( m-j+1, jb, a( j, j ), lda, ipiv( j ), iinfo ) ! adjust info and the pivot indices. if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + j - 1_${ik}$ do i = j, min( m, j+jb-1 ) ipiv( i ) = j - 1_${ik}$ + ipiv( i ) end do ! apply interchanges to columns 1:j-1. call stdlib${ii}$_zlaswp( j-1, a, lda, j, j+jb-1, ipiv, 1_${ik}$ ) if( j+jb<=n ) then ! apply interchanges to columns j+jb:n. call stdlib${ii}$_zlaswp( n-j-jb+1, a( 1_${ik}$, j+jb ), lda, j, j+jb-1,ipiv, 1_${ik}$ ) ! compute block row of u. call stdlib${ii}$_ztrsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT', jb,n-j-jb+1, cone,& a( j, j ), lda, a( j, j+jb ),lda ) if( j+jb<=m ) then ! update trailing submatrix. call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-j-jb+1,n-j-jb+1, jb, -& cone, a( j+jb, j ), lda,a( j, j+jb ), lda, cone, a( j+jb, j+jb ),lda ) end if end if end do end if return end subroutine stdlib${ii}$_zgetrf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$getrf( m, n, a, lda, ipiv, info ) !! ZGETRF: computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, iinfo, j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=min( m, n ) ) then ! use unblocked code. call stdlib${ii}$_${ci}$getrf2( m, n, a, lda, ipiv, info ) else ! use blocked code. do j = 1, min( m, n ), nb jb = min( min( m, n )-j+1, nb ) ! factor diagonal and subdiagonal blocks and test for exact ! singularity. call stdlib${ii}$_${ci}$getrf2( m-j+1, jb, a( j, j ), lda, ipiv( j ), iinfo ) ! adjust info and the pivot indices. if( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + j - 1_${ik}$ do i = j, min( m, j+jb-1 ) ipiv( i ) = j - 1_${ik}$ + ipiv( i ) end do ! apply interchanges to columns 1:j-1. call stdlib${ii}$_${ci}$laswp( j-1, a, lda, j, j+jb-1, ipiv, 1_${ik}$ ) if( j+jb<=n ) then ! apply interchanges to columns j+jb:n. call stdlib${ii}$_${ci}$laswp( n-j-jb+1, a( 1_${ik}$, j+jb ), lda, j, j+jb-1,ipiv, 1_${ik}$ ) ! compute block row of u. call stdlib${ii}$_${ci}$trsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT', jb,n-j-jb+1, cone,& a( j, j ), lda, a( j, j+jb ),lda ) if( j+jb<=m ) then ! update trailing submatrix. call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', m-j-jb+1,n-j-jb+1, jb, -& cone, a( j+jb, j ), lda,a( j, j+jb ), lda, cone, a( j+jb, j+jb ),lda ) end if end if end do end if return end subroutine stdlib${ii}$_${ci}$getrf #:endif #:endfor pure recursive module subroutine stdlib${ii}$_sgetrf2( m, n, a, lda, ipiv, info ) !! SGETRF2 computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the recursive version of the algorithm. It divides !! the matrix into four submatrices: !! [ A11 | A12 ] where A11 is n1 by n1 and A22 is n2 by n2 !! A = [ -----|----- ] with n1 = min(m,n)/2 !! [ A21 | A22 ] n2 = n-n1 !! [ A11 ] !! The subroutine calls itself to factor [ --- ], !! [ A12 ] !! [ A12 ] !! do the swaps on [ --- ], solve A12, update A22, !! [ A22 ] !! then calls itself to factor A22 and do the swaps on A21. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(sp) :: sfmin, temp integer(${ik}$) :: i, iinfo, n1, n2 ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_sscal( m-1, one / a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), 1_${ik}$ ) else do i = 1, m-1 a( 1_${ik}$+i, 1_${ik}$ ) = a( 1_${ik}$+i, 1_${ik}$ ) / a( 1_${ik}$, 1_${ik}$ ) end do end if else info = 1_${ik}$ end if else ! use recursive code n1 = min( m, n ) / 2_${ik}$ n2 = n-n1 ! [ a11 ] ! factor [ --- ] ! [ a21 ] call stdlib${ii}$_sgetrf2( m, n1, a, lda, ipiv, iinfo ) if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! [ a12 ] ! apply interchanges to [ --- ] ! [ a22 ] call stdlib${ii}$_slaswp( n2, a( 1_${ik}$, n1+1 ), lda, 1_${ik}$, n1, ipiv, 1_${ik}$ ) ! solve a12 call stdlib${ii}$_strsm( 'L', 'L', 'N', 'U', n1, n2, one, a, lda,a( 1_${ik}$, n1+1 ), lda ) ! update a22 call stdlib${ii}$_sgemm( 'N', 'N', m-n1, n2, n1, -one, a( n1+1, 1_${ik}$ ), lda,a( 1_${ik}$, n1+1 ), & lda, one, a( n1+1, n1+1 ), lda ) ! factor a22 call stdlib${ii}$_sgetrf2( m-n1, n2, a( n1+1, n1+1 ), lda, ipiv( n1+1 ),iinfo ) ! adjust info and the pivot indices if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + n1 do i = n1+1, min( m, n ) ipiv( i ) = ipiv( i ) + n1 end do ! apply interchanges to a21 call stdlib${ii}$_slaswp( n1, a( 1_${ik}$, 1_${ik}$ ), lda, n1+1, min( m, n), ipiv, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_sgetrf2 pure recursive module subroutine stdlib${ii}$_dgetrf2( m, n, a, lda, ipiv, info ) !! DGETRF2 computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the recursive version of the algorithm. It divides !! the matrix into four submatrices: !! [ A11 | A12 ] where A11 is n1 by n1 and A22 is n2 by n2 !! A = [ -----|----- ] with n1 = min(m,n)/2 !! [ A21 | A22 ] n2 = n-n1 !! [ A11 ] !! The subroutine calls itself to factor [ --- ], !! [ A12 ] !! [ A12 ] !! do the swaps on [ --- ], solve A12, update A22, !! [ A22 ] !! then calls itself to factor A22 and do the swaps on A21. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(dp) :: sfmin, temp integer(${ik}$) :: i, iinfo, n1, n2 ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_dscal( m-1, one / a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), 1_${ik}$ ) else do i = 1, m-1 a( 1_${ik}$+i, 1_${ik}$ ) = a( 1_${ik}$+i, 1_${ik}$ ) / a( 1_${ik}$, 1_${ik}$ ) end do end if else info = 1_${ik}$ end if else ! use recursive code n1 = min( m, n ) / 2_${ik}$ n2 = n-n1 ! [ a11 ] ! factor [ --- ] ! [ a21 ] call stdlib${ii}$_dgetrf2( m, n1, a, lda, ipiv, iinfo ) if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! [ a12 ] ! apply interchanges to [ --- ] ! [ a22 ] call stdlib${ii}$_dlaswp( n2, a( 1_${ik}$, n1+1 ), lda, 1_${ik}$, n1, ipiv, 1_${ik}$ ) ! solve a12 call stdlib${ii}$_dtrsm( 'L', 'L', 'N', 'U', n1, n2, one, a, lda,a( 1_${ik}$, n1+1 ), lda ) ! update a22 call stdlib${ii}$_dgemm( 'N', 'N', m-n1, n2, n1, -one, a( n1+1, 1_${ik}$ ), lda,a( 1_${ik}$, n1+1 ), & lda, one, a( n1+1, n1+1 ), lda ) ! factor a22 call stdlib${ii}$_dgetrf2( m-n1, n2, a( n1+1, n1+1 ), lda, ipiv( n1+1 ),iinfo ) ! adjust info and the pivot indices if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + n1 do i = n1+1, min( m, n ) ipiv( i ) = ipiv( i ) + n1 end do ! apply interchanges to a21 call stdlib${ii}$_dlaswp( n1, a( 1_${ik}$, 1_${ik}$ ), lda, n1+1, min( m, n), ipiv, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_dgetrf2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure recursive module subroutine stdlib${ii}$_${ri}$getrf2( m, n, a, lda, ipiv, info ) !! DGETRF2: computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the recursive version of the algorithm. It divides !! the matrix into four submatrices: !! [ A11 | A12 ] where A11 is n1 by n1 and A22 is n2 by n2 !! A = [ -----|----- ] with n1 = min(m,n)/2 !! [ A21 | A22 ] n2 = n-n1 !! [ A11 ] !! The subroutine calls itself to factor [ --- ], !! [ A12 ] !! [ A12 ] !! do the swaps on [ --- ], solve A12, update A22, !! [ A22 ] !! then calls itself to factor A22 and do the swaps on A21. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(${rk}$) :: sfmin, temp integer(${ik}$) :: i, iinfo, n1, n2 ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_${ri}$scal( m-1, one / a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), 1_${ik}$ ) else do i = 1, m-1 a( 1_${ik}$+i, 1_${ik}$ ) = a( 1_${ik}$+i, 1_${ik}$ ) / a( 1_${ik}$, 1_${ik}$ ) end do end if else info = 1_${ik}$ end if else ! use recursive code n1 = min( m, n ) / 2_${ik}$ n2 = n-n1 ! [ a11 ] ! factor [ --- ] ! [ a21 ] call stdlib${ii}$_${ri}$getrf2( m, n1, a, lda, ipiv, iinfo ) if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! [ a12 ] ! apply interchanges to [ --- ] ! [ a22 ] call stdlib${ii}$_${ri}$laswp( n2, a( 1_${ik}$, n1+1 ), lda, 1_${ik}$, n1, ipiv, 1_${ik}$ ) ! solve a12 call stdlib${ii}$_${ri}$trsm( 'L', 'L', 'N', 'U', n1, n2, one, a, lda,a( 1_${ik}$, n1+1 ), lda ) ! update a22 call stdlib${ii}$_${ri}$gemm( 'N', 'N', m-n1, n2, n1, -one, a( n1+1, 1_${ik}$ ), lda,a( 1_${ik}$, n1+1 ), & lda, one, a( n1+1, n1+1 ), lda ) ! factor a22 call stdlib${ii}$_${ri}$getrf2( m-n1, n2, a( n1+1, n1+1 ), lda, ipiv( n1+1 ),iinfo ) ! adjust info and the pivot indices if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + n1 do i = n1+1, min( m, n ) ipiv( i ) = ipiv( i ) + n1 end do ! apply interchanges to a21 call stdlib${ii}$_${ri}$laswp( n1, a( 1_${ik}$, 1_${ik}$ ), lda, n1+1, min( m, n), ipiv, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ri}$getrf2 #:endif #:endfor pure recursive module subroutine stdlib${ii}$_cgetrf2( m, n, a, lda, ipiv, info ) !! CGETRF2 computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the recursive version of the algorithm. It divides !! the matrix into four submatrices: !! [ A11 | A12 ] where A11 is n1 by n1 and A22 is n2 by n2 !! A = [ -----|----- ] with n1 = min(m,n)/2 !! [ A21 | A22 ] n2 = n-n1 !! [ A11 ] !! The subroutine calls itself to factor [ --- ], !! [ A12 ] !! [ A12 ] !! do the swaps on [ --- ], solve A12, update A22, !! [ A22 ] !! then calls itself to factor A22 and do the swaps on A21. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(sp) :: sfmin complex(sp) :: temp integer(${ik}$) :: i, iinfo, n1, n2 ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_cscal( m-1, cone / a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), 1_${ik}$ ) else do i = 1, m-1 a( 1_${ik}$+i, 1_${ik}$ ) = a( 1_${ik}$+i, 1_${ik}$ ) / a( 1_${ik}$, 1_${ik}$ ) end do end if else info = 1_${ik}$ end if else ! use recursive code n1 = min( m, n ) / 2_${ik}$ n2 = n-n1 ! [ a11 ] ! factor [ --- ] ! [ a21 ] call stdlib${ii}$_cgetrf2( m, n1, a, lda, ipiv, iinfo ) if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! [ a12 ] ! apply interchanges to [ --- ] ! [ a22 ] call stdlib${ii}$_claswp( n2, a( 1_${ik}$, n1+1 ), lda, 1_${ik}$, n1, ipiv, 1_${ik}$ ) ! solve a12 call stdlib${ii}$_ctrsm( 'L', 'L', 'N', 'U', n1, n2, cone, a, lda,a( 1_${ik}$, n1+1 ), lda ) ! update a22 call stdlib${ii}$_cgemm( 'N', 'N', m-n1, n2, n1, -cone, a( n1+1, 1_${ik}$ ), lda,a( 1_${ik}$, n1+1 ), & lda, cone, a( n1+1, n1+1 ), lda ) ! factor a22 call stdlib${ii}$_cgetrf2( m-n1, n2, a( n1+1, n1+1 ), lda, ipiv( n1+1 ),iinfo ) ! adjust info and the pivot indices if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + n1 do i = n1+1, min( m, n ) ipiv( i ) = ipiv( i ) + n1 end do ! apply interchanges to a21 call stdlib${ii}$_claswp( n1, a( 1_${ik}$, 1_${ik}$ ), lda, n1+1, min( m, n), ipiv, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_cgetrf2 pure recursive module subroutine stdlib${ii}$_zgetrf2( m, n, a, lda, ipiv, info ) !! ZGETRF2 computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the recursive version of the algorithm. It divides !! the matrix into four submatrices: !! [ A11 | A12 ] where A11 is n1 by n1 and A22 is n2 by n2 !! A = [ -----|----- ] with n1 = min(m,n)/2 !! [ A21 | A22 ] n2 = n-n1 !! [ A11 ] !! The subroutine calls itself to factor [ --- ], !! [ A12 ] !! [ A12 ] !! do the swaps on [ --- ], solve A12, update A22, !! [ A22 ] !! then calls itself to factor A22 and do the swaps on A21. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(dp) :: sfmin complex(dp) :: temp integer(${ik}$) :: i, iinfo, n1, n2 ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_zscal( m-1, cone / a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), 1_${ik}$ ) else do i = 1, m-1 a( 1_${ik}$+i, 1_${ik}$ ) = a( 1_${ik}$+i, 1_${ik}$ ) / a( 1_${ik}$, 1_${ik}$ ) end do end if else info = 1_${ik}$ end if else ! use recursive code n1 = min( m, n ) / 2_${ik}$ n2 = n-n1 ! [ a11 ] ! factor [ --- ] ! [ a21 ] call stdlib${ii}$_zgetrf2( m, n1, a, lda, ipiv, iinfo ) if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! [ a12 ] ! apply interchanges to [ --- ] ! [ a22 ] call stdlib${ii}$_zlaswp( n2, a( 1_${ik}$, n1+1 ), lda, 1_${ik}$, n1, ipiv, 1_${ik}$ ) ! solve a12 call stdlib${ii}$_ztrsm( 'L', 'L', 'N', 'U', n1, n2, cone, a, lda,a( 1_${ik}$, n1+1 ), lda ) ! update a22 call stdlib${ii}$_zgemm( 'N', 'N', m-n1, n2, n1, -cone, a( n1+1, 1_${ik}$ ), lda,a( 1_${ik}$, n1+1 ), & lda, cone, a( n1+1, n1+1 ), lda ) ! factor a22 call stdlib${ii}$_zgetrf2( m-n1, n2, a( n1+1, n1+1 ), lda, ipiv( n1+1 ),iinfo ) ! adjust info and the pivot indices if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + n1 do i = n1+1, min( m, n ) ipiv( i ) = ipiv( i ) + n1 end do ! apply interchanges to a21 call stdlib${ii}$_zlaswp( n1, a( 1_${ik}$, 1_${ik}$ ), lda, n1+1, min( m, n), ipiv, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_zgetrf2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure recursive module subroutine stdlib${ii}$_${ci}$getrf2( m, n, a, lda, ipiv, info ) !! ZGETRF2: computes an LU factorization of a general M-by-N matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the recursive version of the algorithm. It divides !! the matrix into four submatrices: !! [ A11 | A12 ] where A11 is n1 by n1 and A22 is n2 by n2 !! A = [ -----|----- ] with n1 = min(m,n)/2 !! [ A21 | A22 ] n2 = n-n1 !! [ A11 ] !! The subroutine calls itself to factor [ --- ], !! [ A12 ] !! [ A12 ] !! do the swaps on [ --- ], solve A12, update A22, !! [ A22 ] !! then calls itself to factor A22 and do the swaps on A21. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(${ck}$) :: sfmin complex(${ck}$) :: temp integer(${ik}$) :: i, iinfo, n1, n2 ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_${ci}$scal( m-1, cone / a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), 1_${ik}$ ) else do i = 1, m-1 a( 1_${ik}$+i, 1_${ik}$ ) = a( 1_${ik}$+i, 1_${ik}$ ) / a( 1_${ik}$, 1_${ik}$ ) end do end if else info = 1_${ik}$ end if else ! use recursive code n1 = min( m, n ) / 2_${ik}$ n2 = n-n1 ! [ a11 ] ! factor [ --- ] ! [ a21 ] call stdlib${ii}$_${ci}$getrf2( m, n1, a, lda, ipiv, iinfo ) if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo ! [ a12 ] ! apply interchanges to [ --- ] ! [ a22 ] call stdlib${ii}$_${ci}$laswp( n2, a( 1_${ik}$, n1+1 ), lda, 1_${ik}$, n1, ipiv, 1_${ik}$ ) ! solve a12 call stdlib${ii}$_${ci}$trsm( 'L', 'L', 'N', 'U', n1, n2, cone, a, lda,a( 1_${ik}$, n1+1 ), lda ) ! update a22 call stdlib${ii}$_${ci}$gemm( 'N', 'N', m-n1, n2, n1, -cone, a( n1+1, 1_${ik}$ ), lda,a( 1_${ik}$, n1+1 ), & lda, cone, a( n1+1, n1+1 ), lda ) ! factor a22 call stdlib${ii}$_${ci}$getrf2( m-n1, n2, a( n1+1, n1+1 ), lda, ipiv( n1+1 ),iinfo ) ! adjust info and the pivot indices if ( info==0_${ik}$ .and. iinfo>0_${ik}$ )info = iinfo + n1 do i = n1+1, min( m, n ) ipiv( i ) = ipiv( i ) + n1 end do ! apply interchanges to a21 call stdlib${ii}$_${ci}$laswp( n1, a( 1_${ik}$, 1_${ik}$ ), lda, n1+1, min( m, n), ipiv, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ci}$getrf2 #:endif #:endfor pure module subroutine stdlib${ii}$_sgetf2( m, n, a, lda, ipiv, info ) !! SGETF2 computes an LU factorization of a general m-by-n matrix A !! using partial pivoting with row interchanges. !! The factorization has the form !! A = P * L * U !! where P is a permutation matrix, L is lower triangular with unit !! diagonal elements (lower trapezoidal if m > n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 2 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(sp) :: sfmin integer(${ik}$) :: i, j, jp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_sscal( m-j, one / a( j, j ), a( j+1, j ), 1_${ik}$ ) else do i = 1, m-j a( j+i, j ) = a( j+i, j ) / a( j, j ) end do end if end if else if( info==0_${ik}$ ) then info = j end if if( j n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 2 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(dp) :: sfmin integer(${ik}$) :: i, j, jp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_dscal( m-j, one / a( j, j ), a( j+1, j ), 1_${ik}$ ) else do i = 1, m-j a( j+i, j ) = a( j+i, j ) / a( j, j ) end do end if end if else if( info==0_${ik}$ ) then info = j end if if( j n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 2 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(${rk}$) :: sfmin integer(${ik}$) :: i, j, jp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_${ri}$scal( m-j, one / a( j, j ), a( j+1, j ), 1_${ik}$ ) else do i = 1, m-j a( j+i, j ) = a( j+i, j ) / a( j, j ) end do end if end if else if( info==0_${ik}$ ) then info = j end if if( j n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 2 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(sp) :: sfmin integer(${ik}$) :: i, j, jp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_cscal( m-j, cone / a( j, j ), a( j+1, j ), 1_${ik}$ ) else do i = 1, m-j a( j+i, j ) = a( j+i, j ) / a( j, j ) end do end if end if else if( info==0_${ik}$ ) then info = j end if if( j n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 2 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(dp) :: sfmin integer(${ik}$) :: i, j, jp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_zscal( m-j, cone / a( j, j ), a( j+1, j ), 1_${ik}$ ) else do i = 1, m-j a( j+i, j ) = a( j+i, j ) / a( j, j ) end do end if end if else if( info==0_${ik}$ ) then info = j end if if( j n), and U is upper !! triangular (upper trapezoidal if m < n). !! This is the right-looking Level 2 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars real(${ck}$) :: sfmin integer(${ik}$) :: i, j, jp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda= sfmin ) then call stdlib${ii}$_${ci}$scal( m-j, cone / a( j, j ), a( j+1, j ), 1_${ik}$ ) else do i = 1, m-j a( j+i, j ) = a( j+i, j ) / a( j, j ) end do end if end if else if( info==0_${ik}$ ) then info = j end if if( j 0 from stdlib${ii}$_strtri, then u is singular, ! and the inverse is not computed. call stdlib${ii}$_strtri( 'UPPER', 'NON-UNIT', n, a, lda, info ) if( info>0 )return nbmin = 2_${ik}$ ldwork = n if( nb>1_${ik}$ .and. nb=n ) then ! use unblocked code. do j = n, 1, -1 ! copy current column of l to work and replace with zeros. do i = j + 1, n work( i ) = a( i, j ) a( i, j ) = zero end do ! compute current column of inv(a). if( j 0 from stdlib${ii}$_dtrtri, then u is singular, ! and the inverse is not computed. call stdlib${ii}$_dtrtri( 'UPPER', 'NON-UNIT', n, a, lda, info ) if( info>0 )return nbmin = 2_${ik}$ ldwork = n if( nb>1_${ik}$ .and. nb=n ) then ! use unblocked code. do j = n, 1, -1 ! copy current column of l to work and replace with zeros. do i = j + 1, n work( i ) = a( i, j ) a( i, j ) = zero end do ! compute current column of inv(a). if( j 0 from stdlib${ii}$_${ri}$trtri, then u is singular, ! and the inverse is not computed. call stdlib${ii}$_${ri}$trtri( 'UPPER', 'NON-UNIT', n, a, lda, info ) if( info>0 )return nbmin = 2_${ik}$ ldwork = n if( nb>1_${ik}$ .and. nb=n ) then ! use unblocked code. do j = n, 1, -1 ! copy current column of l to work and replace with zeros. do i = j + 1, n work( i ) = a( i, j ) a( i, j ) = zero end do ! compute current column of inv(a). if( j 0 from stdlib${ii}$_ctrtri, then u is singular, ! and the inverse is not computed. call stdlib${ii}$_ctrtri( 'UPPER', 'NON-UNIT', n, a, lda, info ) if( info>0 )return nbmin = 2_${ik}$ ldwork = n if( nb>1_${ik}$ .and. nb=n ) then ! use unblocked code. do j = n, 1, -1 ! copy current column of l to work and replace with zeros. do i = j + 1, n work( i ) = a( i, j ) a( i, j ) = czero end do ! compute current column of inv(a). if( j 0 from stdlib${ii}$_ztrtri, then u is singular, ! and the inverse is not computed. call stdlib${ii}$_ztrtri( 'UPPER', 'NON-UNIT', n, a, lda, info ) if( info>0 )return nbmin = 2_${ik}$ ldwork = n if( nb>1_${ik}$ .and. nb=n ) then ! use unblocked code. do j = n, 1, -1 ! copy current column of l to work and replace with zeros. do i = j + 1, n work( i ) = a( i, j ) a( i, j ) = czero end do ! compute current column of inv(a). if( j 0 from stdlib${ii}$_${ci}$trtri, then u is singular, ! and the inverse is not computed. call stdlib${ii}$_${ci}$trtri( 'UPPER', 'NON-UNIT', n, a, lda, info ) if( info>0 )return nbmin = 2_${ik}$ ldwork = n if( nb>1_${ik}$ .and. nb=n ) then ! use unblocked code. do j = n, 1, -1 ! copy current column of l to work and replace with zeros. do i = j + 1, n work( i ) = a( i, j ) a( i, j ) = czero end do ! compute current column of inv(a). if( jsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_sgetrs( trans, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) call stdlib${ii}$_saxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_slacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_slacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_sgetrs( transt, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ),n, info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_sgetrs( trans, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_sgerfs pure module subroutine stdlib${ii}$_dgerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! DGERFS improves the computed solution to a system of linear !! equations and provides error bounds and backward error estimates for !! the solution. berr, work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) real(dp), intent(out) :: berr(*), ferr(*), work(*) real(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transt integer(${ik}$) :: count, i, j, k, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_dgetrs( trans, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) call stdlib${ii}$_daxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_dlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_dlacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_dgetrs( transt, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ),n, info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_dgetrs( trans, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_dgerfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! DGERFS: improves the computed solution to a system of linear !! equations and provides error bounds and backward error estimates for !! the solution. berr, work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) real(${rk}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transt integer(${ik}$) :: count, i, j, k, kase, nz real(${rk}$) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ri}$getrs( trans, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) call stdlib${ii}$_${ri}$axpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ri}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ri}$lacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_${ri}$getrs( transt, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ),n, info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_${ri}$getrs( trans, n, 1_${ik}$, af, ldaf, ipiv, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ri}$gerfs #:endif #:endfor pure module subroutine stdlib${ii}$_cgerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! CGERFS improves the computed solution to a system of linear !! equations and provides error bounds and backward error estimates for !! the solution. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, k, kase, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_cgetrs( trans, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) call stdlib${ii}$_caxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_cgetrs( transt, n, 1_${ik}$, af, ldaf, ipiv, work, n,info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_cgetrs( transn, n, 1_${ik}$, af, ldaf, ipiv, work, n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_cgerfs pure module subroutine stdlib${ii}$_zgerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! ZGERFS improves the computed solution to a system of linear !! equations and provides error bounds and backward error estimates for !! the solution. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, k, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_zgetrs( trans, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) call stdlib${ii}$_zaxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_zgetrs( transt, n, 1_${ik}$, af, ldaf, ipiv, work, n,info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_zgetrs( transn, n, 1_${ik}$, af, ldaf, ipiv, work, n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_zgerfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb,x, ldx, ferr, & !! ZGERFS: improves the computed solution to a system of linear !! equations and provides error bounds and backward error estimates for !! the solution. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, k, kase, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ci}$getrs( trans, n, 1_${ik}$, af, ldaf, ipiv, work, n, info ) call stdlib${ii}$_${ci}$axpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_${ci}$getrs( transt, n, 1_${ik}$, af, ldaf, ipiv, work, n,info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$getrs( transn, n, 1_${ik}$, af, ldaf, ipiv, work, n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ci}$gerfs #:endif #:endfor pure module subroutine stdlib${ii}$_sgeequ( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) !! SGEEQU computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have absolute value 1. !! R(i) and C(j) are restricted to be between SMLNUM = smallest safe !! number and BIGNUM = largest safe number. Use of these scaling !! factors is not guaranteed to reduce the condition number of A but !! works well in practice. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: c(*), r(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: bignum, rcmax, rcmin, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldazero ) then r( i ) = radix**int( log( r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = 1, m c( j ) = max( c( j ), abs( a( i, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_sgeequb pure module subroutine stdlib${ii}$_dgeequb( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) !! DGEEQUB computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most !! the radix. !! R(i) and C(j) are restricted to be a power of the radix between !! SMLNUM = smallest safe number and BIGNUM = largest safe number. Use !! of these scaling factors is not guaranteed to reduce the condition !! number of A but works well in practice. !! This routine differs from DGEEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled entries' magnitudes are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(dp), intent(in) :: a(lda,*) real(dp), intent(out) :: c(*), r(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: bignum, rcmax, rcmin, smlnum, radix, logrdx ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldazero ) then r( i ) = radix**int( log( r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = 1, m c( j ) = max( c( j ), abs( a( i, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_dgeequb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$geequb( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) !! DGEEQUB: computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most !! the radix. !! R(i) and C(j) are restricted to be a power of the radix between !! SMLNUM = smallest safe number and BIGNUM = largest safe number. Use !! of these scaling factors is not guaranteed to reduce the condition !! number of A but works well in practice. !! This routine differs from DGEEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled entries' magnitudes are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(out) :: c(*), r(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${rk}$) :: bignum, rcmax, rcmin, smlnum, radix, logrdx ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldazero ) then r( i ) = radix**int( log( r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = 1, m c( j ) = max( c( j ), abs( a( i, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_${ri}$geequb #:endif #:endfor pure module subroutine stdlib${ii}$_cgeequb( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) !! CGEEQUB computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most !! the radix. !! R(i) and C(j) are restricted to be a power of the radix between !! SMLNUM = smallest safe number and BIGNUM = largest safe number. Use !! of these scaling factors is not guaranteed to reduce the condition !! number of A but works well in practice. !! This routine differs from CGEEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled entries' magnitudes are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(sp), intent(out) :: c(*), r(*) complex(sp), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: bignum, rcmax, rcmin, smlnum, radix, logrdx complex(sp) :: zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldazero ) then r( i ) = radix**int( log(r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors. do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = 1, m c( j ) = max( c( j ), cabs1( a( i, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_cgeequb pure module subroutine stdlib${ii}$_zgeequb( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) !! ZGEEQUB computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most !! the radix. !! R(i) and C(j) are restricted to be a power of the radix between !! SMLNUM = smallest safe number and BIGNUM = largest safe number. Use !! of these scaling factors is not guaranteed to reduce the condition !! number of A but works well in practice. !! This routine differs from ZGEEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled entries' magnitudes are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(dp), intent(out) :: c(*), r(*) complex(dp), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: bignum, rcmax, rcmin, smlnum, radix, logrdx complex(dp) :: zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldazero ) then r( i ) = radix**int( log(r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors. do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = 1, m c( j ) = max( c( j ), cabs1( a( i, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_zgeequb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$geequb( m, n, a, lda, r, c, rowcnd, colcnd, amax,info ) !! ZGEEQUB: computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most !! the radix. !! R(i) and C(j) are restricted to be a power of the radix between !! SMLNUM = smallest safe number and BIGNUM = largest safe number. Use !! of these scaling factors is not guaranteed to reduce the condition !! number of A but works well in practice. !! This routine differs from ZGEEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled entries' magnitudes are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(${ck}$), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(${ck}$), intent(out) :: c(*), r(*) complex(${ck}$), intent(in) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: bignum, rcmax, rcmin, smlnum, radix, logrdx complex(${ck}$) :: zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldazero ) then r( i ) = radix**int( log(r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors. do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = 1, m c( j ) = max( c( j ), cabs1( a( i, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_${ci}$geequb #:endif #:endfor pure module subroutine stdlib${ii}$_slaqge( m, n, a, lda, r, c, rowcnd, colcnd, amax,equed ) !! SLAQGE equilibrates a general M by N matrix A using the row and !! column scaling factors in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: c(*), r(*) ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1e+0_sp ! Local Scalars integer(${ik}$) :: i, j real(sp) :: cj, large, small ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) / stdlib${ii}$_slamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*a( i, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = 1, m a( i, j ) = r( i )*a( i, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*r( i )*a( i, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_slaqge pure module subroutine stdlib${ii}$_dlaqge( m, n, a, lda, r, c, rowcnd, colcnd, amax,equed ) !! DLAQGE equilibrates a general M by N matrix A using the row and !! column scaling factors in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: c(*), r(*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j real(dp) :: cj, large, small ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*a( i, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = 1, m a( i, j ) = r( i )*a( i, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*r( i )*a( i, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_dlaqge #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqge( m, n, a, lda, r, c, rowcnd, colcnd, amax,equed ) !! DLAQGE: equilibrates a general M by N matrix A using the row and !! column scaling factors in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: c(*), r(*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: thresh = 0.1e+0_${rk}$ ! Local Scalars integer(${ik}$) :: i, j real(${rk}$) :: cj, large, small ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${ri}$lamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*a( i, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = 1, m a( i, j ) = r( i )*a( i, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*r( i )*a( i, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_${ri}$laqge #:endif #:endfor pure module subroutine stdlib${ii}$_claqge( m, n, a, lda, r, c, rowcnd, colcnd, amax,equed ) !! CLAQGE equilibrates a general M by N matrix A using the row and !! column scaling factors in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(sp), intent(in) :: c(*), r(*) complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1e+0_sp ! Local Scalars integer(${ik}$) :: i, j real(sp) :: cj, large, small ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) / stdlib${ii}$_slamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*a( i, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = 1, m a( i, j ) = r( i )*a( i, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*r( i )*a( i, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_claqge pure module subroutine stdlib${ii}$_zlaqge( m, n, a, lda, r, c, rowcnd, colcnd, amax,equed ) !! ZLAQGE equilibrates a general M by N matrix A using the row and !! column scaling factors in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(dp), intent(in) :: c(*), r(*) complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j real(dp) :: cj, large, small ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*a( i, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = 1, m a( i, j ) = r( i )*a( i, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*r( i )*a( i, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_zlaqge #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqge( m, n, a, lda, r, c, rowcnd, colcnd, amax,equed ) !! ZLAQGE: equilibrates a general M by N matrix A using the row and !! column scaling factors in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: lda, m, n real(${ck}$), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(${ck}$), intent(in) :: c(*), r(*) complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: thresh = 0.1e+0_${ck}$ ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: cj, large, small ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*a( i, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = 1, m a( i, j ) = r( i )*a( i, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = 1, m a( i, j ) = cj*r( i )*a( i, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_${ci}$laqge #:endif #:endfor pure module subroutine stdlib${ii}$_slaswp( n, a, lda, k1, k2, ipiv, incx ) !! SLASWP performs a series of row interchanges on the matrix A. !! One row interchange is initiated for each of rows K1 through K2 of A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k1, k2, lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, i1, i2, inc, ip, ix, ix0, j, k, n32 real(sp) :: temp ! Executable Statements ! interchange row i with row ipiv(k1+(i-k1)*abs(incx)) for each of rows ! k1 through k2. if( incx>0_${ik}$ ) then ix0 = k1 i1 = k1 i2 = k2 inc = 1_${ik}$ else if( incx<0_${ik}$ ) then ix0 = k1 + ( k1-k2 )*incx i1 = k2 i2 = k1 inc = -1_${ik}$ else return end if n32 = ( n / 32_${ik}$ )*32_${ik}$ if( n32/=0_${ik}$ ) then do j = 1, n32, 32 ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = j, j + 31 temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end do end if if( n32/=n ) then n32 = n32 + 1_${ik}$ ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = n32, n temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end if return end subroutine stdlib${ii}$_slaswp pure module subroutine stdlib${ii}$_dlaswp( n, a, lda, k1, k2, ipiv, incx ) !! DLASWP performs a series of row interchanges on the matrix A. !! One row interchange is initiated for each of rows K1 through K2 of A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k1, k2, lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, i1, i2, inc, ip, ix, ix0, j, k, n32 real(dp) :: temp ! Executable Statements ! interchange row i with row ipiv(k1+(i-k1)*abs(incx)) for each of rows ! k1 through k2. if( incx>0_${ik}$ ) then ix0 = k1 i1 = k1 i2 = k2 inc = 1_${ik}$ else if( incx<0_${ik}$ ) then ix0 = k1 + ( k1-k2 )*incx i1 = k2 i2 = k1 inc = -1_${ik}$ else return end if n32 = ( n / 32_${ik}$ )*32_${ik}$ if( n32/=0_${ik}$ ) then do j = 1, n32, 32 ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = j, j + 31 temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end do end if if( n32/=n ) then n32 = n32 + 1_${ik}$ ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = n32, n temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end if return end subroutine stdlib${ii}$_dlaswp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laswp( n, a, lda, k1, k2, ipiv, incx ) !! DLASWP: performs a series of row interchanges on the matrix A. !! One row interchange is initiated for each of rows K1 through K2 of A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k1, k2, lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, i1, i2, inc, ip, ix, ix0, j, k, n32 real(${rk}$) :: temp ! Executable Statements ! interchange row i with row ipiv(k1+(i-k1)*abs(incx)) for each of rows ! k1 through k2. if( incx>0_${ik}$ ) then ix0 = k1 i1 = k1 i2 = k2 inc = 1_${ik}$ else if( incx<0_${ik}$ ) then ix0 = k1 + ( k1-k2 )*incx i1 = k2 i2 = k1 inc = -1_${ik}$ else return end if n32 = ( n / 32_${ik}$ )*32_${ik}$ if( n32/=0_${ik}$ ) then do j = 1, n32, 32 ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = j, j + 31 temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end do end if if( n32/=n ) then n32 = n32 + 1_${ik}$ ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = n32, n temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end if return end subroutine stdlib${ii}$_${ri}$laswp #:endif #:endfor pure module subroutine stdlib${ii}$_claswp( n, a, lda, k1, k2, ipiv, incx ) !! CLASWP performs a series of row interchanges on the matrix A. !! One row interchange is initiated for each of rows K1 through K2 of A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k1, k2, lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, i1, i2, inc, ip, ix, ix0, j, k, n32 complex(sp) :: temp ! Executable Statements ! interchange row i with row ipiv(k1+(i-k1)*abs(incx)) for each of rows ! k1 through k2. if( incx>0_${ik}$ ) then ix0 = k1 i1 = k1 i2 = k2 inc = 1_${ik}$ else if( incx<0_${ik}$ ) then ix0 = k1 + ( k1-k2 )*incx i1 = k2 i2 = k1 inc = -1_${ik}$ else return end if n32 = ( n / 32_${ik}$ )*32_${ik}$ if( n32/=0_${ik}$ ) then do j = 1, n32, 32 ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = j, j + 31 temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end do end if if( n32/=n ) then n32 = n32 + 1_${ik}$ ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = n32, n temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end if return end subroutine stdlib${ii}$_claswp pure module subroutine stdlib${ii}$_zlaswp( n, a, lda, k1, k2, ipiv, incx ) !! ZLASWP performs a series of row interchanges on the matrix A. !! One row interchange is initiated for each of rows K1 through K2 of A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k1, k2, lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, i1, i2, inc, ip, ix, ix0, j, k, n32 complex(dp) :: temp ! Executable Statements ! interchange row i with row ipiv(k1+(i-k1)*abs(incx)) for each of rows ! k1 through k2. if( incx>0_${ik}$ ) then ix0 = k1 i1 = k1 i2 = k2 inc = 1_${ik}$ else if( incx<0_${ik}$ ) then ix0 = k1 + ( k1-k2 )*incx i1 = k2 i2 = k1 inc = -1_${ik}$ else return end if n32 = ( n / 32_${ik}$ )*32_${ik}$ if( n32/=0_${ik}$ ) then do j = 1, n32, 32 ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = j, j + 31 temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end do end if if( n32/=n ) then n32 = n32 + 1_${ik}$ ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = n32, n temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end if return end subroutine stdlib${ii}$_zlaswp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laswp( n, a, lda, k1, k2, ipiv, incx ) !! ZLASWP: performs a series of row interchanges on the matrix A. !! One row interchange is initiated for each of rows K1 through K2 of A. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, k1, k2, lda, n ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, i1, i2, inc, ip, ix, ix0, j, k, n32 complex(${ck}$) :: temp ! Executable Statements ! interchange row i with row ipiv(k1+(i-k1)*abs(incx)) for each of rows ! k1 through k2. if( incx>0_${ik}$ ) then ix0 = k1 i1 = k1 i2 = k2 inc = 1_${ik}$ else if( incx<0_${ik}$ ) then ix0 = k1 + ( k1-k2 )*incx i1 = k2 i2 = k1 inc = -1_${ik}$ else return end if n32 = ( n / 32_${ik}$ )*32_${ik}$ if( n32/=0_${ik}$ ) then do j = 1, n32, 32 ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = j, j + 31 temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end do end if if( n32/=n ) then n32 = n32 + 1_${ik}$ ix = ix0 do i = i1, i2, inc ip = ipiv( ix ) if( ip/=i ) then do k = n32, n temp = a( i, k ) a( i, k ) = a( ip, k ) a( ip, k ) = temp end do end if ix = ix + incx end do end if return end subroutine stdlib${ii}$_${ci}$laswp #:endif #:endfor pure module subroutine stdlib${ii}$_sgetc2( n, a, lda, ipiv, jpiv, info ) !! SGETC2 computes an LU factorization with complete pivoting of the !! n-by-n matrix A. The factorization has the form A = P * L * U * Q, !! where P and Q are permutation matrices, L is lower triangular with !! unit diagonal elements and U is upper triangular. !! This is the Level 2 BLAS algorithm. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*), jpiv(*) real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ip, ipv, j, jp, jpv real(sp) :: bignum, eps, smin, smlnum, xmax ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n==0 )return ! set constants to control overflow eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) / eps bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) ! handle the case n=1 by itself if( n==1_${ik}$ ) then ipiv( 1_${ik}$ ) = 1_${ik}$ jpiv( 1_${ik}$ ) = 1_${ik}$ if( abs( a( 1_${ik}$, 1_${ik}$ ) )=xmax ) then xmax = abs( a( ip, jp ) ) ipv = ip jpv = jp end if end do end do if( i==1_${ik}$ )smin = max( eps*xmax, smlnum ) ! swap rows if( ipv/=i )call stdlib${ii}$_sswap( n, a( ipv, 1_${ik}$ ), lda, a( i, 1_${ik}$ ), lda ) ipiv( i ) = ipv ! swap columns if( jpv/=i )call stdlib${ii}$_sswap( n, a( 1_${ik}$, jpv ), 1_${ik}$, a( 1_${ik}$, i ), 1_${ik}$ ) jpiv( i ) = jpv ! check for singularity if( abs( a( i, i ) )=xmax ) then xmax = abs( a( ip, jp ) ) ipv = ip jpv = jp end if end do end do if( i==1_${ik}$ )smin = max( eps*xmax, smlnum ) ! swap rows if( ipv/=i )call stdlib${ii}$_dswap( n, a( ipv, 1_${ik}$ ), lda, a( i, 1_${ik}$ ), lda ) ipiv( i ) = ipv ! swap columns if( jpv/=i )call stdlib${ii}$_dswap( n, a( 1_${ik}$, jpv ), 1_${ik}$, a( 1_${ik}$, i ), 1_${ik}$ ) jpiv( i ) = jpv ! check for singularity if( abs( a( i, i ) )=xmax ) then xmax = abs( a( ip, jp ) ) ipv = ip jpv = jp end if end do end do if( i==1_${ik}$ )smin = max( eps*xmax, smlnum ) ! swap rows if( ipv/=i )call stdlib${ii}$_${ri}$swap( n, a( ipv, 1_${ik}$ ), lda, a( i, 1_${ik}$ ), lda ) ipiv( i ) = ipv ! swap columns if( jpv/=i )call stdlib${ii}$_${ri}$swap( n, a( 1_${ik}$, jpv ), 1_${ik}$, a( 1_${ik}$, i ), 1_${ik}$ ) jpiv( i ) = jpv ! check for singularity if( abs( a( i, i ) )=xmax ) then xmax = abs( a( ip, jp ) ) ipv = ip jpv = jp end if end do end do if( i==1_${ik}$ )smin = max( eps*xmax, smlnum ) ! swap rows if( ipv/=i )call stdlib${ii}$_cswap( n, a( ipv, 1_${ik}$ ), lda, a( i, 1_${ik}$ ), lda ) ipiv( i ) = ipv ! swap columns if( jpv/=i )call stdlib${ii}$_cswap( n, a( 1_${ik}$, jpv ), 1_${ik}$, a( 1_${ik}$, i ), 1_${ik}$ ) jpiv( i ) = jpv ! check for singularity if( abs( a( i, i ) )=xmax ) then xmax = abs( a( ip, jp ) ) ipv = ip jpv = jp end if end do end do if( i==1_${ik}$ )smin = max( eps*xmax, smlnum ) ! swap rows if( ipv/=i )call stdlib${ii}$_zswap( n, a( ipv, 1_${ik}$ ), lda, a( i, 1_${ik}$ ), lda ) ipiv( i ) = ipv ! swap columns if( jpv/=i )call stdlib${ii}$_zswap( n, a( 1_${ik}$, jpv ), 1_${ik}$, a( 1_${ik}$, i ), 1_${ik}$ ) jpiv( i ) = jpv ! check for singularity if( abs( a( i, i ) )=xmax ) then xmax = abs( a( ip, jp ) ) ipv = ip jpv = jp end if end do end do if( i==1_${ik}$ )smin = max( eps*xmax, smlnum ) ! swap rows if( ipv/=i )call stdlib${ii}$_${ci}$swap( n, a( ipv, 1_${ik}$ ), lda, a( i, 1_${ik}$ ), lda ) ipiv( i ) = ipv ! swap columns if( jpv/=i )call stdlib${ii}$_${ci}$swap( n, a( 1_${ik}$, jpv ), 1_${ik}$, a( 1_${ik}$, i ), 1_${ik}$ ) jpiv( i ) = jpv ! check for singularity if( abs( a( i, i ) )abs( a( n, n ) ) ) then temp = ( one / two ) / abs( rhs( i ) ) call stdlib${ii}$_sscal( n, temp, rhs( 1_${ik}$ ), 1_${ik}$ ) scale = scale*temp end if do i = n, 1, -1 temp = one / a( i, i ) rhs( i ) = rhs( i )*temp do j = i + 1, n rhs( i ) = rhs( i ) - rhs( j )*( a( i, j )*temp ) end do end do ! apply permutations jpiv to the solution (rhs) call stdlib${ii}$_slaswp( 1_${ik}$, rhs, lda, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) return end subroutine stdlib${ii}$_sgesc2 pure module subroutine stdlib${ii}$_dgesc2( n, a, lda, rhs, ipiv, jpiv, scale ) !! DGESC2 solves a system of linear equations !! A * X = scale* RHS !! with a general N-by-N matrix A using the LU factorization with !! complete pivoting computed by DGETC2. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, n real(dp), intent(out) :: scale ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*), jpiv(*) real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: rhs(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: bignum, eps, smlnum, temp ! Intrinsic Functions ! Executable Statements ! set constant to control overflow eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) / eps bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) ! apply permutations ipiv to rhs call stdlib${ii}$_dlaswp( 1_${ik}$, rhs, lda, 1_${ik}$, n-1, ipiv, 1_${ik}$ ) ! solve for l part do i = 1, n - 1 do j = i + 1, n rhs( j ) = rhs( j ) - a( j, i )*rhs( i ) end do end do ! solve for u part scale = one ! check for scaling i = stdlib${ii}$_idamax( n, rhs, 1_${ik}$ ) if( two*smlnum*abs( rhs( i ) )>abs( a( n, n ) ) ) then temp = ( one / two ) / abs( rhs( i ) ) call stdlib${ii}$_dscal( n, temp, rhs( 1_${ik}$ ), 1_${ik}$ ) scale = scale*temp end if do i = n, 1, -1 temp = one / a( i, i ) rhs( i ) = rhs( i )*temp do j = i + 1, n rhs( i ) = rhs( i ) - rhs( j )*( a( i, j )*temp ) end do end do ! apply permutations jpiv to the solution (rhs) call stdlib${ii}$_dlaswp( 1_${ik}$, rhs, lda, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) return end subroutine stdlib${ii}$_dgesc2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gesc2( n, a, lda, rhs, ipiv, jpiv, scale ) !! DGESC2: solves a system of linear equations !! A * X = scale* RHS !! with a general N-by-N matrix A using the LU factorization with !! complete pivoting computed by DGETC2. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, n real(${rk}$), intent(out) :: scale ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*), jpiv(*) real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(inout) :: rhs(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${rk}$) :: bignum, eps, smlnum, temp ! Intrinsic Functions ! Executable Statements ! set constant to control overflow eps = stdlib${ii}$_${ri}$lamch( 'P' ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) / eps bignum = one / smlnum call stdlib${ii}$_${ri}$labad( smlnum, bignum ) ! apply permutations ipiv to rhs call stdlib${ii}$_${ri}$laswp( 1_${ik}$, rhs, lda, 1_${ik}$, n-1, ipiv, 1_${ik}$ ) ! solve for l part do i = 1, n - 1 do j = i + 1, n rhs( j ) = rhs( j ) - a( j, i )*rhs( i ) end do end do ! solve for u part scale = one ! check for scaling i = stdlib${ii}$_i${ri}$amax( n, rhs, 1_${ik}$ ) if( two*smlnum*abs( rhs( i ) )>abs( a( n, n ) ) ) then temp = ( one / two ) / abs( rhs( i ) ) call stdlib${ii}$_${ri}$scal( n, temp, rhs( 1_${ik}$ ), 1_${ik}$ ) scale = scale*temp end if do i = n, 1, -1 temp = one / a( i, i ) rhs( i ) = rhs( i )*temp do j = i + 1, n rhs( i ) = rhs( i ) - rhs( j )*( a( i, j )*temp ) end do end do ! apply permutations jpiv to the solution (rhs) call stdlib${ii}$_${ri}$laswp( 1_${ik}$, rhs, lda, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) return end subroutine stdlib${ii}$_${ri}$gesc2 #:endif #:endfor pure module subroutine stdlib${ii}$_cgesc2( n, a, lda, rhs, ipiv, jpiv, scale ) !! CGESC2 solves a system of linear equations !! A * X = scale* RHS !! with a general N-by-N matrix A using the LU factorization with !! complete pivoting computed by CGETC2. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, n real(sp), intent(out) :: scale ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*), jpiv(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: rhs(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: bignum, eps, smlnum complex(sp) :: temp ! Intrinsic Functions ! Executable Statements ! set constant to control overflow eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) / eps bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) ! apply permutations ipiv to rhs call stdlib${ii}$_claswp( 1_${ik}$, rhs, lda, 1_${ik}$, n-1, ipiv, 1_${ik}$ ) ! solve for l part do i = 1, n - 1 do j = i + 1, n rhs( j ) = rhs( j ) - a( j, i )*rhs( i ) end do end do ! solve for u part scale = one ! check for scaling i = stdlib${ii}$_icamax( n, rhs, 1_${ik}$ ) if( two*smlnum*abs( rhs( i ) )>abs( a( n, n ) ) ) then temp = cmplx( one / two, zero,KIND=sp) / abs( rhs( i ) ) call stdlib${ii}$_cscal( n, temp, rhs( 1_${ik}$ ), 1_${ik}$ ) scale = scale*real( temp,KIND=sp) end if do i = n, 1, -1 temp = cmplx( one, zero,KIND=sp) / a( i, i ) rhs( i ) = rhs( i )*temp do j = i + 1, n rhs( i ) = rhs( i ) - rhs( j )*( a( i, j )*temp ) end do end do ! apply permutations jpiv to the solution (rhs) call stdlib${ii}$_claswp( 1_${ik}$, rhs, lda, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) return end subroutine stdlib${ii}$_cgesc2 pure module subroutine stdlib${ii}$_zgesc2( n, a, lda, rhs, ipiv, jpiv, scale ) !! ZGESC2 solves a system of linear equations !! A * X = scale* RHS !! with a general N-by-N matrix A using the LU factorization with !! complete pivoting computed by ZGETC2. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, n real(dp), intent(out) :: scale ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*), jpiv(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: rhs(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: bignum, eps, smlnum complex(dp) :: temp ! Intrinsic Functions ! Executable Statements ! set constant to control overflow eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) / eps bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) ! apply permutations ipiv to rhs call stdlib${ii}$_zlaswp( 1_${ik}$, rhs, lda, 1_${ik}$, n-1, ipiv, 1_${ik}$ ) ! solve for l part do i = 1, n - 1 do j = i + 1, n rhs( j ) = rhs( j ) - a( j, i )*rhs( i ) end do end do ! solve for u part scale = one ! check for scaling i = stdlib${ii}$_izamax( n, rhs, 1_${ik}$ ) if( two*smlnum*abs( rhs( i ) )>abs( a( n, n ) ) ) then temp = cmplx( one / two, zero,KIND=dp) / abs( rhs( i ) ) call stdlib${ii}$_zscal( n, temp, rhs( 1_${ik}$ ), 1_${ik}$ ) scale = scale*real( temp,KIND=dp) end if do i = n, 1, -1 temp = cmplx( one, zero,KIND=dp) / a( i, i ) rhs( i ) = rhs( i )*temp do j = i + 1, n rhs( i ) = rhs( i ) - rhs( j )*( a( i, j )*temp ) end do end do ! apply permutations jpiv to the solution (rhs) call stdlib${ii}$_zlaswp( 1_${ik}$, rhs, lda, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) return end subroutine stdlib${ii}$_zgesc2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gesc2( n, a, lda, rhs, ipiv, jpiv, scale ) !! ZGESC2: solves a system of linear equations !! A * X = scale* RHS !! with a general N-by-N matrix A using the LU factorization with !! complete pivoting computed by ZGETC2. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(out) :: scale ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*), jpiv(*) complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(inout) :: rhs(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: bignum, eps, smlnum complex(${ck}$) :: temp ! Intrinsic Functions ! Executable Statements ! set constant to control overflow eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' ) smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) / eps bignum = one / smlnum call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum ) ! apply permutations ipiv to rhs call stdlib${ii}$_${ci}$laswp( 1_${ik}$, rhs, lda, 1_${ik}$, n-1, ipiv, 1_${ik}$ ) ! solve for l part do i = 1, n - 1 do j = i + 1, n rhs( j ) = rhs( j ) - a( j, i )*rhs( i ) end do end do ! solve for u part scale = one ! check for scaling i = stdlib${ii}$_i${ci}$amax( n, rhs, 1_${ik}$ ) if( two*smlnum*abs( rhs( i ) )>abs( a( n, n ) ) ) then temp = cmplx( one / two, zero,KIND=${ck}$) / abs( rhs( i ) ) call stdlib${ii}$_${ci}$scal( n, temp, rhs( 1_${ik}$ ), 1_${ik}$ ) scale = scale*real( temp,KIND=${ck}$) end if do i = n, 1, -1 temp = cmplx( one, zero,KIND=${ck}$) / a( i, i ) rhs( i ) = rhs( i )*temp do j = i + 1, n rhs( i ) = rhs( i ) - rhs( j )*( a( i, j )*temp ) end do end do ! apply permutations jpiv to the solution (rhs) call stdlib${ii}$_${ci}$laswp( 1_${ik}$, rhs, lda, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) return end subroutine stdlib${ii}$_${ci}$gesc2 #:endif #:endfor pure module subroutine stdlib${ii}$_slatdf( ijob, n, z, ldz, rhs, rdsum, rdscal, ipiv,jpiv ) !! SLATDF uses the LU factorization of the n-by-n matrix Z computed by !! SGETC2 and computes a contribution to the reciprocal Dif-estimate !! by solving Z * x = b for x, and choosing the r.h.s. b such that !! the norm of x is as large as possible. On entry RHS = b holds the !! contribution from earlier solved sub-systems, and on return RHS = x. !! The factorization of Z returned by SGETC2 has the form Z = P*L*U*Q, !! where P and Q are permutation matrices. L is lower triangular with !! unit diagonal elements and U is upper triangular. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ijob, ldz, n real(sp), intent(inout) :: rdscal, rdsum ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*), jpiv(*) real(sp), intent(inout) :: rhs(*), z(ldz,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxdim = 8_${ik}$ ! Local Scalars integer(${ik}$) :: i, info, j, k real(sp) :: bm, bp, pmone, sminu, splus, temp ! Local Arrays integer(${ik}$) :: iwork(maxdim) real(sp) :: work(4_${ik}$*maxdim), xm(maxdim), xp(maxdim) ! Intrinsic Functions ! Executable Statements if( ijob/=2_${ik}$ ) then ! apply permutations ipiv to rhs call stdlib${ii}$_slaswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, ipiv, 1_${ik}$ ) ! solve for l-part choosing rhs either to +1 or -1. pmone = -one loop_10: do j = 1, n - 1 bp = rhs( j ) + one bm = rhs( j ) - one splus = one ! look-ahead for l-part rhs(1:n-1) = + or -1, splus and ! smin computed more efficiently than in bsolve [1]. splus = splus + stdlib${ii}$_sdot( n-j, z( j+1, j ), 1_${ik}$, z( j+1, j ), 1_${ik}$ ) sminu = stdlib${ii}$_sdot( n-j, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ) splus = splus*rhs( j ) if( splus>sminu ) then rhs( j ) = bp else if( sminu>splus ) then rhs( j ) = bm else ! in this case the updating sums are equal and we can ! choose rhs(j) +1 or -1. the first time this happens ! we choose -1, thereafter +1. this is a simple way to ! get good estimates of matrices like byers well-known ! example (see [1]). (not done in bsolve.) rhs( j ) = rhs( j ) + pmone pmone = one end if ! compute the remaining r.h.s. temp = -rhs( j ) call stdlib${ii}$_saxpy( n-j, temp, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ) end do loop_10 ! solve for u-part, look-ahead for rhs(n) = +-1. this is not done ! in bsolve and will hopefully give us a better estimate because ! any ill-conditioning of the original matrix is transferred to u ! and not to l. u(n, n) is an approximation to sigma_min(lu). call stdlib${ii}$_scopy( n-1, rhs, 1_${ik}$, xp, 1_${ik}$ ) xp( n ) = rhs( n ) + one rhs( n ) = rhs( n ) - one splus = zero sminu = zero do i = n, 1, -1 temp = one / z( i, i ) xp( i ) = xp( i )*temp rhs( i ) = rhs( i )*temp do k = i + 1, n xp( i ) = xp( i ) - xp( k )*( z( i, k )*temp ) rhs( i ) = rhs( i ) - rhs( k )*( z( i, k )*temp ) end do splus = splus + abs( xp( i ) ) sminu = sminu + abs( rhs( i ) ) end do if( splus>sminu )call stdlib${ii}$_scopy( n, xp, 1_${ik}$, rhs, 1_${ik}$ ) ! apply the permutations jpiv to the computed solution (rhs) call stdlib${ii}$_slaswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_slassq( n, rhs, 1_${ik}$, rdscal, rdsum ) else ! ijob = 2, compute approximate nullvector xm of z call stdlib${ii}$_sgecon( 'I', n, z, ldz, one, temp, work, iwork, info ) call stdlib${ii}$_scopy( n, work( n+1 ), 1_${ik}$, xm, 1_${ik}$ ) ! compute rhs call stdlib${ii}$_slaswp( 1_${ik}$, xm, ldz, 1_${ik}$, n-1, ipiv, -1_${ik}$ ) temp = one / sqrt( stdlib${ii}$_sdot( n, xm, 1_${ik}$, xm, 1_${ik}$ ) ) call stdlib${ii}$_sscal( n, temp, xm, 1_${ik}$ ) call stdlib${ii}$_scopy( n, xm, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_saxpy( n, one, rhs, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_saxpy( n, -one, xm, 1_${ik}$, rhs, 1_${ik}$ ) call stdlib${ii}$_sgesc2( n, z, ldz, rhs, ipiv, jpiv, temp ) call stdlib${ii}$_sgesc2( n, z, ldz, xp, ipiv, jpiv, temp ) if( stdlib${ii}$_sasum( n, xp, 1_${ik}$ )>stdlib${ii}$_sasum( n, rhs, 1_${ik}$ ) )call stdlib${ii}$_scopy( n, xp, 1_${ik}$,& rhs, 1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_slassq( n, rhs, 1_${ik}$, rdscal, rdsum ) end if return end subroutine stdlib${ii}$_slatdf pure module subroutine stdlib${ii}$_dlatdf( ijob, n, z, ldz, rhs, rdsum, rdscal, ipiv,jpiv ) !! DLATDF uses the LU factorization of the n-by-n matrix Z computed by !! DGETC2 and computes a contribution to the reciprocal Dif-estimate !! by solving Z * x = b for x, and choosing the r.h.s. b such that !! the norm of x is as large as possible. On entry RHS = b holds the !! contribution from earlier solved sub-systems, and on return RHS = x. !! The factorization of Z returned by DGETC2 has the form Z = P*L*U*Q, !! where P and Q are permutation matrices. L is lower triangular with !! unit diagonal elements and U is upper triangular. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ijob, ldz, n real(dp), intent(inout) :: rdscal, rdsum ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*), jpiv(*) real(dp), intent(inout) :: rhs(*), z(ldz,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxdim = 8_${ik}$ ! Local Scalars integer(${ik}$) :: i, info, j, k real(dp) :: bm, bp, pmone, sminu, splus, temp ! Local Arrays integer(${ik}$) :: iwork(maxdim) real(dp) :: work(4_${ik}$*maxdim), xm(maxdim), xp(maxdim) ! Intrinsic Functions ! Executable Statements if( ijob/=2_${ik}$ ) then ! apply permutations ipiv to rhs call stdlib${ii}$_dlaswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, ipiv, 1_${ik}$ ) ! solve for l-part choosing rhs either to +1 or -1. pmone = -one loop_10: do j = 1, n - 1 bp = rhs( j ) + one bm = rhs( j ) - one splus = one ! look-ahead for l-part rhs(1:n-1) = + or -1, splus and ! smin computed more efficiently than in bsolve [1]. splus = splus + stdlib${ii}$_ddot( n-j, z( j+1, j ), 1_${ik}$, z( j+1, j ), 1_${ik}$ ) sminu = stdlib${ii}$_ddot( n-j, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ) splus = splus*rhs( j ) if( splus>sminu ) then rhs( j ) = bp else if( sminu>splus ) then rhs( j ) = bm else ! in this case the updating sums are equal and we can ! choose rhs(j) +1 or -1. the first time this happens ! we choose -1, thereafter +1. this is a simple way to ! get good estimates of matrices like byers well-known ! example (see [1]). (not done in bsolve.) rhs( j ) = rhs( j ) + pmone pmone = one end if ! compute the remaining r.h.s. temp = -rhs( j ) call stdlib${ii}$_daxpy( n-j, temp, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ) end do loop_10 ! solve for u-part, look-ahead for rhs(n) = +-1. this is not done ! in bsolve and will hopefully give us a better estimate because ! any ill-conditioning of the original matrix is transferred to u ! and not to l. u(n, n) is an approximation to sigma_min(lu). call stdlib${ii}$_dcopy( n-1, rhs, 1_${ik}$, xp, 1_${ik}$ ) xp( n ) = rhs( n ) + one rhs( n ) = rhs( n ) - one splus = zero sminu = zero do i = n, 1, -1 temp = one / z( i, i ) xp( i ) = xp( i )*temp rhs( i ) = rhs( i )*temp do k = i + 1, n xp( i ) = xp( i ) - xp( k )*( z( i, k )*temp ) rhs( i ) = rhs( i ) - rhs( k )*( z( i, k )*temp ) end do splus = splus + abs( xp( i ) ) sminu = sminu + abs( rhs( i ) ) end do if( splus>sminu )call stdlib${ii}$_dcopy( n, xp, 1_${ik}$, rhs, 1_${ik}$ ) ! apply the permutations jpiv to the computed solution (rhs) call stdlib${ii}$_dlaswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_dlassq( n, rhs, 1_${ik}$, rdscal, rdsum ) else ! ijob = 2, compute approximate nullvector xm of z call stdlib${ii}$_dgecon( 'I', n, z, ldz, one, temp, work, iwork, info ) call stdlib${ii}$_dcopy( n, work( n+1 ), 1_${ik}$, xm, 1_${ik}$ ) ! compute rhs call stdlib${ii}$_dlaswp( 1_${ik}$, xm, ldz, 1_${ik}$, n-1, ipiv, -1_${ik}$ ) temp = one / sqrt( stdlib${ii}$_ddot( n, xm, 1_${ik}$, xm, 1_${ik}$ ) ) call stdlib${ii}$_dscal( n, temp, xm, 1_${ik}$ ) call stdlib${ii}$_dcopy( n, xm, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_daxpy( n, one, rhs, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_daxpy( n, -one, xm, 1_${ik}$, rhs, 1_${ik}$ ) call stdlib${ii}$_dgesc2( n, z, ldz, rhs, ipiv, jpiv, temp ) call stdlib${ii}$_dgesc2( n, z, ldz, xp, ipiv, jpiv, temp ) if( stdlib${ii}$_dasum( n, xp, 1_${ik}$ )>stdlib${ii}$_dasum( n, rhs, 1_${ik}$ ) )call stdlib${ii}$_dcopy( n, xp, 1_${ik}$,& rhs, 1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_dlassq( n, rhs, 1_${ik}$, rdscal, rdsum ) end if return end subroutine stdlib${ii}$_dlatdf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$latdf( ijob, n, z, ldz, rhs, rdsum, rdscal, ipiv,jpiv ) !! DLATDF: uses the LU factorization of the n-by-n matrix Z computed by !! DGETC2 and computes a contribution to the reciprocal Dif-estimate !! by solving Z * x = b for x, and choosing the r.h.s. b such that !! the norm of x is as large as possible. On entry RHS = b holds the !! contribution from earlier solved sub-systems, and on return RHS = x. !! The factorization of Z returned by DGETC2 has the form Z = P*L*U*Q, !! where P and Q are permutation matrices. L is lower triangular with !! unit diagonal elements and U is upper triangular. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ijob, ldz, n real(${rk}$), intent(inout) :: rdscal, rdsum ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*), jpiv(*) real(${rk}$), intent(inout) :: rhs(*), z(ldz,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxdim = 8_${ik}$ ! Local Scalars integer(${ik}$) :: i, info, j, k real(${rk}$) :: bm, bp, pmone, sminu, splus, temp ! Local Arrays integer(${ik}$) :: iwork(maxdim) real(${rk}$) :: work(4_${ik}$*maxdim), xm(maxdim), xp(maxdim) ! Intrinsic Functions ! Executable Statements if( ijob/=2_${ik}$ ) then ! apply permutations ipiv to rhs call stdlib${ii}$_${ri}$laswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, ipiv, 1_${ik}$ ) ! solve for l-part choosing rhs either to +1 or -1. pmone = -one loop_10: do j = 1, n - 1 bp = rhs( j ) + one bm = rhs( j ) - one splus = one ! look-ahead for l-part rhs(1:n-1) = + or -1, splus and ! smin computed more efficiently than in bsolve [1]. splus = splus + stdlib${ii}$_${ri}$dot( n-j, z( j+1, j ), 1_${ik}$, z( j+1, j ), 1_${ik}$ ) sminu = stdlib${ii}$_${ri}$dot( n-j, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ) splus = splus*rhs( j ) if( splus>sminu ) then rhs( j ) = bp else if( sminu>splus ) then rhs( j ) = bm else ! in this case the updating sums are equal and we can ! choose rhs(j) +1 or -1. the first time this happens ! we choose -1, thereafter +1. this is a simple way to ! get good estimates of matrices like byers well-known ! example (see [1]). (not done in bsolve.) rhs( j ) = rhs( j ) + pmone pmone = one end if ! compute the remaining r.h.s. temp = -rhs( j ) call stdlib${ii}$_${ri}$axpy( n-j, temp, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ) end do loop_10 ! solve for u-part, look-ahead for rhs(n) = +-1. this is not done ! in bsolve and will hopefully give us a better estimate because ! any ill-conditioning of the original matrix is transferred to u ! and not to l. u(n, n) is an approximation to sigma_min(lu). call stdlib${ii}$_${ri}$copy( n-1, rhs, 1_${ik}$, xp, 1_${ik}$ ) xp( n ) = rhs( n ) + one rhs( n ) = rhs( n ) - one splus = zero sminu = zero do i = n, 1, -1 temp = one / z( i, i ) xp( i ) = xp( i )*temp rhs( i ) = rhs( i )*temp do k = i + 1, n xp( i ) = xp( i ) - xp( k )*( z( i, k )*temp ) rhs( i ) = rhs( i ) - rhs( k )*( z( i, k )*temp ) end do splus = splus + abs( xp( i ) ) sminu = sminu + abs( rhs( i ) ) end do if( splus>sminu )call stdlib${ii}$_${ri}$copy( n, xp, 1_${ik}$, rhs, 1_${ik}$ ) ! apply the permutations jpiv to the computed solution (rhs) call stdlib${ii}$_${ri}$laswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_${ri}$lassq( n, rhs, 1_${ik}$, rdscal, rdsum ) else ! ijob = 2, compute approximate nullvector xm of z call stdlib${ii}$_${ri}$gecon( 'I', n, z, ldz, one, temp, work, iwork, info ) call stdlib${ii}$_${ri}$copy( n, work( n+1 ), 1_${ik}$, xm, 1_${ik}$ ) ! compute rhs call stdlib${ii}$_${ri}$laswp( 1_${ik}$, xm, ldz, 1_${ik}$, n-1, ipiv, -1_${ik}$ ) temp = one / sqrt( stdlib${ii}$_${ri}$dot( n, xm, 1_${ik}$, xm, 1_${ik}$ ) ) call stdlib${ii}$_${ri}$scal( n, temp, xm, 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n, xm, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( n, one, rhs, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( n, -one, xm, 1_${ik}$, rhs, 1_${ik}$ ) call stdlib${ii}$_${ri}$gesc2( n, z, ldz, rhs, ipiv, jpiv, temp ) call stdlib${ii}$_${ri}$gesc2( n, z, ldz, xp, ipiv, jpiv, temp ) if( stdlib${ii}$_${ri}$asum( n, xp, 1_${ik}$ )>stdlib${ii}$_${ri}$asum( n, rhs, 1_${ik}$ ) )call stdlib${ii}$_${ri}$copy( n, xp, 1_${ik}$,& rhs, 1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_${ri}$lassq( n, rhs, 1_${ik}$, rdscal, rdsum ) end if return end subroutine stdlib${ii}$_${ri}$latdf #:endif #:endfor pure module subroutine stdlib${ii}$_clatdf( ijob, n, z, ldz, rhs, rdsum, rdscal, ipiv,jpiv ) !! CLATDF computes the contribution to the reciprocal Dif-estimate !! by solving for x in Z * x = b, where b is chosen such that the norm !! of x is as large as possible. It is assumed that LU decomposition !! of Z has been computed by CGETC2. On entry RHS = f holds the !! contribution from earlier solved sub-systems, and on return RHS = x. !! The factorization of Z returned by CGETC2 has the form !! Z = P * L * U * Q, where P and Q are permutation matrices. L is lower !! triangular with unit diagonal elements and U is upper triangular. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ijob, ldz, n real(sp), intent(inout) :: rdscal, rdsum ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*), jpiv(*) complex(sp), intent(inout) :: rhs(*), z(ldz,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxdim = 2_${ik}$ ! Local Scalars integer(${ik}$) :: i, info, j, k real(sp) :: rtemp, scale, sminu, splus complex(sp) :: bm, bp, pmone, temp ! Local Arrays real(sp) :: rwork(maxdim) complex(sp) :: work(4_${ik}$*maxdim), xm(maxdim), xp(maxdim) ! Intrinsic Functions ! Executable Statements if( ijob/=2_${ik}$ ) then ! apply permutations ipiv to rhs call stdlib${ii}$_claswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, ipiv, 1_${ik}$ ) ! solve for l-part choosing rhs either to +1 or -1. pmone = -cone loop_10: do j = 1, n - 1 bp = rhs( j ) + cone bm = rhs( j ) - cone splus = one ! lockahead for l- part rhs(1:n-1) = +-1 ! splus and smin computed more efficiently than in bsolve[1]. splus = splus + real( stdlib${ii}$_cdotc( n-j, z( j+1, j ), 1_${ik}$, z( j+1,j ), 1_${ik}$ ),KIND=sp) sminu = real( stdlib${ii}$_cdotc( n-j, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ),KIND=sp) splus = splus*real( rhs( j ),KIND=sp) if( splus>sminu ) then rhs( j ) = bp else if( sminu>splus ) then rhs( j ) = bm else ! in this case the updating sums are equal and we can ! choose rhs(j) +1 or -1. the first time this happens we ! choose -1, thereafter +1. this is a simple way to get ! good estimates of matrices like byers well-known example ! (see [1]). (not done in bsolve.) rhs( j ) = rhs( j ) + pmone pmone = cone end if ! compute the remaining r.h.s. temp = -rhs( j ) call stdlib${ii}$_caxpy( n-j, temp, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ) end do loop_10 ! solve for u- part, lockahead for rhs(n) = +-1. this is not done ! in bsolve and will hopefully give us a better estimate because ! any ill-conditioning of the original matrix is transferred to u ! and not to l. u(n, n) is an approximation to sigma_min(lu). call stdlib${ii}$_ccopy( n-1, rhs, 1_${ik}$, work, 1_${ik}$ ) work( n ) = rhs( n ) + cone rhs( n ) = rhs( n ) - cone splus = zero sminu = zero do i = n, 1, -1 temp = cone / z( i, i ) work( i ) = work( i )*temp rhs( i ) = rhs( i )*temp do k = i + 1, n work( i ) = work( i ) - work( k )*( z( i, k )*temp ) rhs( i ) = rhs( i ) - rhs( k )*( z( i, k )*temp ) end do splus = splus + abs( work( i ) ) sminu = sminu + abs( rhs( i ) ) end do if( splus>sminu )call stdlib${ii}$_ccopy( n, work, 1_${ik}$, rhs, 1_${ik}$ ) ! apply the permutations jpiv to the computed solution (rhs) call stdlib${ii}$_claswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_classq( n, rhs, 1_${ik}$, rdscal, rdsum ) return end if ! entry ijob = 2 ! compute approximate nullvector xm of z call stdlib${ii}$_cgecon( 'I', n, z, ldz, one, rtemp, work, rwork, info ) call stdlib${ii}$_ccopy( n, work( n+1 ), 1_${ik}$, xm, 1_${ik}$ ) ! compute rhs call stdlib${ii}$_claswp( 1_${ik}$, xm, ldz, 1_${ik}$, n-1, ipiv, -1_${ik}$ ) temp = cone / sqrt( stdlib${ii}$_cdotc( n, xm, 1_${ik}$, xm, 1_${ik}$ ) ) call stdlib${ii}$_cscal( n, temp, xm, 1_${ik}$ ) call stdlib${ii}$_ccopy( n, xm, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_caxpy( n, cone, rhs, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_caxpy( n, -cone, xm, 1_${ik}$, rhs, 1_${ik}$ ) call stdlib${ii}$_cgesc2( n, z, ldz, rhs, ipiv, jpiv, scale ) call stdlib${ii}$_cgesc2( n, z, ldz, xp, ipiv, jpiv, scale ) if( stdlib${ii}$_scasum( n, xp, 1_${ik}$ )>stdlib${ii}$_scasum( n, rhs, 1_${ik}$ ) )call stdlib${ii}$_ccopy( n, xp, 1_${ik}$, & rhs, 1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_classq( n, rhs, 1_${ik}$, rdscal, rdsum ) return end subroutine stdlib${ii}$_clatdf pure module subroutine stdlib${ii}$_zlatdf( ijob, n, z, ldz, rhs, rdsum, rdscal, ipiv,jpiv ) !! ZLATDF computes the contribution to the reciprocal Dif-estimate !! by solving for x in Z * x = b, where b is chosen such that the norm !! of x is as large as possible. It is assumed that LU decomposition !! of Z has been computed by ZGETC2. On entry RHS = f holds the !! contribution from earlier solved sub-systems, and on return RHS = x. !! The factorization of Z returned by ZGETC2 has the form !! Z = P * L * U * Q, where P and Q are permutation matrices. L is lower !! triangular with unit diagonal elements and U is upper triangular. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ijob, ldz, n real(dp), intent(inout) :: rdscal, rdsum ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*), jpiv(*) complex(dp), intent(inout) :: rhs(*), z(ldz,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxdim = 2_${ik}$ ! Local Scalars integer(${ik}$) :: i, info, j, k real(dp) :: rtemp, scale, sminu, splus complex(dp) :: bm, bp, pmone, temp ! Local Arrays real(dp) :: rwork(maxdim) complex(dp) :: work(4_${ik}$*maxdim), xm(maxdim), xp(maxdim) ! Intrinsic Functions ! Executable Statements if( ijob/=2_${ik}$ ) then ! apply permutations ipiv to rhs call stdlib${ii}$_zlaswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, ipiv, 1_${ik}$ ) ! solve for l-part choosing rhs either to +1 or -1. pmone = -cone loop_10: do j = 1, n - 1 bp = rhs( j ) + cone bm = rhs( j ) - cone splus = one ! lockahead for l- part rhs(1:n-1) = +-1 ! splus and smin computed more efficiently than in bsolve[1]. splus = splus + real( stdlib${ii}$_zdotc( n-j, z( j+1, j ), 1_${ik}$, z( j+1,j ), 1_${ik}$ ),KIND=dp) sminu = real( stdlib${ii}$_zdotc( n-j, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ),KIND=dp) splus = splus*real( rhs( j ),KIND=dp) if( splus>sminu ) then rhs( j ) = bp else if( sminu>splus ) then rhs( j ) = bm else ! in this case the updating sums are equal and we can ! choose rhs(j) +1 or -1. the first time this happens we ! choose -1, thereafter +1. this is a simple way to get ! good estimates of matrices like byers well-known example ! (see [1]). (not done in bsolve.) rhs( j ) = rhs( j ) + pmone pmone = cone end if ! compute the remaining r.h.s. temp = -rhs( j ) call stdlib${ii}$_zaxpy( n-j, temp, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ) end do loop_10 ! solve for u- part, lockahead for rhs(n) = +-1. this is not done ! in bsolve and will hopefully give us a better estimate because ! any ill-conditioning of the original matrix is transferred to u ! and not to l. u(n, n) is an approximation to sigma_min(lu). call stdlib${ii}$_zcopy( n-1, rhs, 1_${ik}$, work, 1_${ik}$ ) work( n ) = rhs( n ) + cone rhs( n ) = rhs( n ) - cone splus = zero sminu = zero do i = n, 1, -1 temp = cone / z( i, i ) work( i ) = work( i )*temp rhs( i ) = rhs( i )*temp do k = i + 1, n work( i ) = work( i ) - work( k )*( z( i, k )*temp ) rhs( i ) = rhs( i ) - rhs( k )*( z( i, k )*temp ) end do splus = splus + abs( work( i ) ) sminu = sminu + abs( rhs( i ) ) end do if( splus>sminu )call stdlib${ii}$_zcopy( n, work, 1_${ik}$, rhs, 1_${ik}$ ) ! apply the permutations jpiv to the computed solution (rhs) call stdlib${ii}$_zlaswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_zlassq( n, rhs, 1_${ik}$, rdscal, rdsum ) return end if ! entry ijob = 2 ! compute approximate nullvector xm of z call stdlib${ii}$_zgecon( 'I', n, z, ldz, one, rtemp, work, rwork, info ) call stdlib${ii}$_zcopy( n, work( n+1 ), 1_${ik}$, xm, 1_${ik}$ ) ! compute rhs call stdlib${ii}$_zlaswp( 1_${ik}$, xm, ldz, 1_${ik}$, n-1, ipiv, -1_${ik}$ ) temp = cone / sqrt( stdlib${ii}$_zdotc( n, xm, 1_${ik}$, xm, 1_${ik}$ ) ) call stdlib${ii}$_zscal( n, temp, xm, 1_${ik}$ ) call stdlib${ii}$_zcopy( n, xm, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_zaxpy( n, cone, rhs, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_zaxpy( n, -cone, xm, 1_${ik}$, rhs, 1_${ik}$ ) call stdlib${ii}$_zgesc2( n, z, ldz, rhs, ipiv, jpiv, scale ) call stdlib${ii}$_zgesc2( n, z, ldz, xp, ipiv, jpiv, scale ) if( stdlib${ii}$_dzasum( n, xp, 1_${ik}$ )>stdlib${ii}$_dzasum( n, rhs, 1_${ik}$ ) )call stdlib${ii}$_zcopy( n, xp, 1_${ik}$, & rhs, 1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_zlassq( n, rhs, 1_${ik}$, rdscal, rdsum ) return end subroutine stdlib${ii}$_zlatdf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$latdf( ijob, n, z, ldz, rhs, rdsum, rdscal, ipiv,jpiv ) !! ZLATDF: computes the contribution to the reciprocal Dif-estimate !! by solving for x in Z * x = b, where b is chosen such that the norm !! of x is as large as possible. It is assumed that LU decomposition !! of Z has been computed by ZGETC2. On entry RHS = f holds the !! contribution from earlier solved sub-systems, and on return RHS = x. !! The factorization of Z returned by ZGETC2 has the form !! Z = P * L * U * Q, where P and Q are permutation matrices. L is lower !! triangular with unit diagonal elements and U is upper triangular. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ijob, ldz, n real(${ck}$), intent(inout) :: rdscal, rdsum ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*), jpiv(*) complex(${ck}$), intent(inout) :: rhs(*), z(ldz,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxdim = 2_${ik}$ ! Local Scalars integer(${ik}$) :: i, info, j, k real(${ck}$) :: rtemp, scale, sminu, splus complex(${ck}$) :: bm, bp, pmone, temp ! Local Arrays real(${ck}$) :: rwork(maxdim) complex(${ck}$) :: work(4_${ik}$*maxdim), xm(maxdim), xp(maxdim) ! Intrinsic Functions ! Executable Statements if( ijob/=2_${ik}$ ) then ! apply permutations ipiv to rhs call stdlib${ii}$_${ci}$laswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, ipiv, 1_${ik}$ ) ! solve for l-part choosing rhs either to +1 or -1. pmone = -cone loop_10: do j = 1, n - 1 bp = rhs( j ) + cone bm = rhs( j ) - cone splus = one ! lockahead for l- part rhs(1:n-1) = +-1 ! splus and smin computed more efficiently than in bsolve[1]. splus = splus + real( stdlib${ii}$_${ci}$dotc( n-j, z( j+1, j ), 1_${ik}$, z( j+1,j ), 1_${ik}$ ),KIND=${ck}$) sminu = real( stdlib${ii}$_${ci}$dotc( n-j, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ),KIND=${ck}$) splus = splus*real( rhs( j ),KIND=${ck}$) if( splus>sminu ) then rhs( j ) = bp else if( sminu>splus ) then rhs( j ) = bm else ! in this case the updating sums are equal and we can ! choose rhs(j) +1 or -1. the first time this happens we ! choose -1, thereafter +1. this is a simple way to get ! good estimates of matrices like byers well-known example ! (see [1]). (not done in bsolve.) rhs( j ) = rhs( j ) + pmone pmone = cone end if ! compute the remaining r.h.s. temp = -rhs( j ) call stdlib${ii}$_${ci}$axpy( n-j, temp, z( j+1, j ), 1_${ik}$, rhs( j+1 ), 1_${ik}$ ) end do loop_10 ! solve for u- part, lockahead for rhs(n) = +-1. this is not done ! in bsolve and will hopefully give us a better estimate because ! any ill-conditioning of the original matrix is transferred to u ! and not to l. u(n, n) is an approximation to sigma_min(lu). call stdlib${ii}$_${ci}$copy( n-1, rhs, 1_${ik}$, work, 1_${ik}$ ) work( n ) = rhs( n ) + cone rhs( n ) = rhs( n ) - cone splus = zero sminu = zero do i = n, 1, -1 temp = cone / z( i, i ) work( i ) = work( i )*temp rhs( i ) = rhs( i )*temp do k = i + 1, n work( i ) = work( i ) - work( k )*( z( i, k )*temp ) rhs( i ) = rhs( i ) - rhs( k )*( z( i, k )*temp ) end do splus = splus + abs( work( i ) ) sminu = sminu + abs( rhs( i ) ) end do if( splus>sminu )call stdlib${ii}$_${ci}$copy( n, work, 1_${ik}$, rhs, 1_${ik}$ ) ! apply the permutations jpiv to the computed solution (rhs) call stdlib${ii}$_${ci}$laswp( 1_${ik}$, rhs, ldz, 1_${ik}$, n-1, jpiv, -1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_${ci}$lassq( n, rhs, 1_${ik}$, rdscal, rdsum ) return end if ! entry ijob = 2 ! compute approximate nullvector xm of z call stdlib${ii}$_${ci}$gecon( 'I', n, z, ldz, one, rtemp, work, rwork, info ) call stdlib${ii}$_${ci}$copy( n, work( n+1 ), 1_${ik}$, xm, 1_${ik}$ ) ! compute rhs call stdlib${ii}$_${ci}$laswp( 1_${ik}$, xm, ldz, 1_${ik}$, n-1, ipiv, -1_${ik}$ ) temp = cone / sqrt( stdlib${ii}$_${ci}$dotc( n, xm, 1_${ik}$, xm, 1_${ik}$ ) ) call stdlib${ii}$_${ci}$scal( n, temp, xm, 1_${ik}$ ) call stdlib${ii}$_${ci}$copy( n, xm, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( n, cone, rhs, 1_${ik}$, xp, 1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( n, -cone, xm, 1_${ik}$, rhs, 1_${ik}$ ) call stdlib${ii}$_${ci}$gesc2( n, z, ldz, rhs, ipiv, jpiv, scale ) call stdlib${ii}$_${ci}$gesc2( n, z, ldz, xp, ipiv, jpiv, scale ) if( stdlib${ii}$_${c2ri(ci)}$zasum( n, xp, 1_${ik}$ )>stdlib${ii}$_${c2ri(ci)}$zasum( n, rhs, 1_${ik}$ ) )call stdlib${ii}$_${ci}$copy( n, xp, 1_${ik}$, & rhs, 1_${ik}$ ) ! compute the sum of squares call stdlib${ii}$_${ci}$lassq( n, rhs, 1_${ik}$, rdscal, rdsum ) return end subroutine stdlib${ii}$_${ci}$latdf #:endif #:endfor real(sp) module function stdlib${ii}$_sla_gercond( trans, n, a, lda, af, ldaf, ipiv,cmode, c, info, work, & !! SLA_GERCOND estimates the Skeel condition number of op(A) * op2(C) !! where op2 is determined by CMODE as follows !! CMODE = 1 op2(C) = C !! CMODE = 0 op2(C) = I !! CMODE = -1 op2(C) = inv(C) !! The Skeel condition number cond(A) = norminf( |inv(A)||A| ) !! is computed by computing scaling factors R such that !! diag(R)*A*op2(C) is row equilibrated and computing the standard !! infinity-norm condition number. iwork ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: n, lda, ldaf, cmode integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: a(lda,*), af(ldaf,*), c(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notrans integer(${ik}$) :: kase, i, j real(sp) :: ainvnm, tmp ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements stdlib${ii}$_sla_gercond = zero info = 0_${ik}$ notrans = stdlib_lsame( trans, 'N' ) if ( .not. notrans .and. .not. stdlib_lsame(trans, 'T').and. .not. stdlib_lsame(trans, & 'C') ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0_${ik}$ kase = 0_${ik}$ 10 continue call stdlib${ii}$_slacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(l). if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) jp = ipiv( j ) t = work( jp ) if( jp/=j ) then work( jp ) = work( j ) work( j ) = t end if call stdlib${ii}$_saxpy( lm, -t, ab( kd+1, j ), 1_${ik}$, work( j+1 ), 1_${ik}$ ) end do end if ! multiply by inv(u). call stdlib${ii}$_slatbs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', normin, n,kl+ku, ab, & ldab, work, scale, work( 2_${ik}$*n+1 ),info ) else ! multiply by inv(u**t). call stdlib${ii}$_slatbs( 'UPPER', 'TRANSPOSE', 'NON-UNIT', normin, n,kl+ku, ab, ldab, & work, scale, work( 2_${ik}$*n+1 ),info ) ! multiply by inv(l**t). if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) work( j ) = work( j ) - stdlib${ii}$_sdot( lm, ab( kd+1, j ), 1_${ik}$,work( j+1 ), 1_${ik}$ ) jp = ipiv( j ) if( jp/=j ) then t = work( jp ) work( jp ) = work( j ) work( j ) = t end if end do end if end if ! divide x by 1/scale if doing so will not cause overflow. normin = 'Y' if( scale/=one ) then ix = stdlib${ii}$_isamax( n, work, 1_${ik}$ ) if( scale0_${ik}$ kase = 0_${ik}$ 10 continue call stdlib${ii}$_dlacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(l). if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) jp = ipiv( j ) t = work( jp ) if( jp/=j ) then work( jp ) = work( j ) work( j ) = t end if call stdlib${ii}$_daxpy( lm, -t, ab( kd+1, j ), 1_${ik}$, work( j+1 ), 1_${ik}$ ) end do end if ! multiply by inv(u). call stdlib${ii}$_dlatbs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', normin, n,kl+ku, ab, & ldab, work, scale, work( 2_${ik}$*n+1 ),info ) else ! multiply by inv(u**t). call stdlib${ii}$_dlatbs( 'UPPER', 'TRANSPOSE', 'NON-UNIT', normin, n,kl+ku, ab, ldab, & work, scale, work( 2_${ik}$*n+1 ),info ) ! multiply by inv(l**t). if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) work( j ) = work( j ) - stdlib${ii}$_ddot( lm, ab( kd+1, j ), 1_${ik}$,work( j+1 ), 1_${ik}$ ) jp = ipiv( j ) if( jp/=j ) then t = work( jp ) work( jp ) = work( j ) work( j ) = t end if end do end if end if ! divide x by 1/scale if doing so will not cause overflow. normin = 'Y' if( scale/=one ) then ix = stdlib${ii}$_idamax( n, work, 1_${ik}$ ) if( scale0_${ik}$ kase = 0_${ik}$ 10 continue call stdlib${ii}$_${ri}$lacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(l). if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) jp = ipiv( j ) t = work( jp ) if( jp/=j ) then work( jp ) = work( j ) work( j ) = t end if call stdlib${ii}$_${ri}$axpy( lm, -t, ab( kd+1, j ), 1_${ik}$, work( j+1 ), 1_${ik}$ ) end do end if ! multiply by inv(u). call stdlib${ii}$_${ri}$latbs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', normin, n,kl+ku, ab, & ldab, work, scale, work( 2_${ik}$*n+1 ),info ) else ! multiply by inv(u**t). call stdlib${ii}$_${ri}$latbs( 'UPPER', 'TRANSPOSE', 'NON-UNIT', normin, n,kl+ku, ab, ldab, & work, scale, work( 2_${ik}$*n+1 ),info ) ! multiply by inv(l**t). if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) work( j ) = work( j ) - stdlib${ii}$_${ri}$dot( lm, ab( kd+1, j ), 1_${ik}$,work( j+1 ), 1_${ik}$ ) jp = ipiv( j ) if( jp/=j ) then t = work( jp ) work( jp ) = work( j ) work( j ) = t end if end do end if end if ! divide x by 1/scale if doing so will not cause overflow. normin = 'Y' if( scale/=one ) then ix = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ ) if( scale0_${ik}$ kase = 0_${ik}$ 10 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(l). if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) jp = ipiv( j ) t = work( jp ) if( jp/=j ) then work( jp ) = work( j ) work( j ) = t end if call stdlib${ii}$_caxpy( lm, -t, ab( kd+1, j ), 1_${ik}$, work( j+1 ), 1_${ik}$ ) end do end if ! multiply by inv(u). call stdlib${ii}$_clatbs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', normin, n,kl+ku, ab, & ldab, work, scale, rwork, info ) else ! multiply by inv(u**h). call stdlib${ii}$_clatbs( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',normin, n, kl+ku, & ab, ldab, work, scale, rwork,info ) ! multiply by inv(l**h). if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) work( j ) = work( j ) - stdlib${ii}$_cdotc( lm, ab( kd+1, j ), 1_${ik}$,work( j+1 ), 1_${ik}$ ) jp = ipiv( j ) if( jp/=j ) then t = work( jp ) work( jp ) = work( j ) work( j ) = t end if end do end if end if ! divide x by 1/scale if doing so will not cause overflow. normin = 'Y' if( scale/=one ) then ix = stdlib${ii}$_icamax( n, work, 1_${ik}$ ) if( scale0_${ik}$ kase = 0_${ik}$ 10 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(l). if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) jp = ipiv( j ) t = work( jp ) if( jp/=j ) then work( jp ) = work( j ) work( j ) = t end if call stdlib${ii}$_zaxpy( lm, -t, ab( kd+1, j ), 1_${ik}$, work( j+1 ), 1_${ik}$ ) end do end if ! multiply by inv(u). call stdlib${ii}$_zlatbs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', normin, n,kl+ku, ab, & ldab, work, scale, rwork, info ) else ! multiply by inv(u**h). call stdlib${ii}$_zlatbs( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',normin, n, kl+ku, & ab, ldab, work, scale, rwork,info ) ! multiply by inv(l**h). if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) work( j ) = work( j ) - stdlib${ii}$_zdotc( lm, ab( kd+1, j ), 1_${ik}$,work( j+1 ), 1_${ik}$ ) jp = ipiv( j ) if( jp/=j ) then t = work( jp ) work( jp ) = work( j ) work( j ) = t end if end do end if end if ! divide x by 1/scale if doing so will not cause overflow. normin = 'Y' if( scale/=one ) then ix = stdlib${ii}$_izamax( n, work, 1_${ik}$ ) if( scale0_${ik}$ kase = 0_${ik}$ 10 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(l). if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) jp = ipiv( j ) t = work( jp ) if( jp/=j ) then work( jp ) = work( j ) work( j ) = t end if call stdlib${ii}$_${ci}$axpy( lm, -t, ab( kd+1, j ), 1_${ik}$, work( j+1 ), 1_${ik}$ ) end do end if ! multiply by inv(u). call stdlib${ii}$_${ci}$latbs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', normin, n,kl+ku, ab, & ldab, work, scale, rwork, info ) else ! multiply by inv(u**h). call stdlib${ii}$_${ci}$latbs( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',normin, n, kl+ku, & ab, ldab, work, scale, rwork,info ) ! multiply by inv(l**h). if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) work( j ) = work( j ) - stdlib${ii}$_${ci}$dotc( lm, ab( kd+1, j ), 1_${ik}$,work( j+1 ), 1_${ik}$ ) jp = ipiv( j ) if( jp/=j ) then t = work( jp ) work( jp ) = work( j ) work( j ) = t end if end do end if end if ! divide x by 1/scale if doing so will not cause overflow. normin = 'Y' if( scale/=one ) then ix = stdlib${ii}$_i${ci}$amax( n, work, 1_${ik}$ ) if( scalekl ) then ! use unblocked code call stdlib${ii}$_sgbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) else ! use blocked code ! zero the superdiagonal elements of the work array work13 do j = 1, nb do i = 1, j - 1 work13( i, j ) = zero end do end do ! zero the subdiagonal elements of the work array work31 do j = 1, nb do i = j + 1, nb work31( i, j ) = zero end do end do ! gaussian elimination with partial pivoting ! set fill-in elements in columns ku+2 to kv to zero do j = ku + 2, min( kv, n ) do i = kv - j + 2, kl ab( i, j ) = zero end do end do ! ju is the index of the last column affected by the current ! stage of the factorization ju = 1_${ik}$ loop_180: do j = 1, min( m, n ), nb jb = min( nb, min( m, n )-j+1 ) ! the active part of the matrix is partitioned ! a11 a12 a13 ! a21 a22 a23 ! a31 a32 a33 ! here a11, a21 and a31 denote the current block of jb columns ! which is about to be factorized. the number of rows in the ! partitioning are jb, i2, i3 respectively, and the numbers ! of columns are jb, j2, j3. the superdiagonal elements of a13 ! and the subdiagonal elements of a31 lie outside the band. i2 = min( kl-jb, m-j-jb+1 ) i3 = min( jb, m-j-kl+1 ) ! j2 and j3 are computed after ju has been updated. ! factorize the current block of jb columns loop_80: do jj = j, j + jb - 1 ! set fill-in elements in column jj+kv to zero if( jj+kv<=n ) then do i = 1, kl ab( i, jj+kv ) = zero end do end if ! find pivot and test for singularity. km is the number of ! subdiagonal elements in the current column. km = min( kl, m-jj ) jp = stdlib${ii}$_isamax( km+1, ab( kv+1, jj ), 1_${ik}$ ) ipiv( jj ) = jp + jj - j if( ab( kv+jp, jj )/=zero ) then ju = max( ju, min( jj+ku+jp-1, n ) ) if( jp/=1_${ik}$ ) then ! apply interchange to columns j to j+jb-1 if( jp+jj-1jj )call stdlib${ii}$_sger( km, jm-jj, -one, ab( kv+2, jj ), 1_${ik}$,ab( kv, jj+& 1_${ik}$ ), ldab-1,ab( kv+1, jj+1 ), ldab-1 ) else ! if pivot is zero, set info to the index of the pivot ! unless a zero pivot has already been found. if( info==0_${ik}$ )info = jj end if ! copy current column of a31 into the work array work31 nw = min( jj-j+1, i3 ) if( nw>0_${ik}$ )call stdlib${ii}$_scopy( nw, ab( kv+kl+1-jj+j, jj ), 1_${ik}$,work31( 1_${ik}$, jj-j+1 )& , 1_${ik}$ ) end do loop_80 if( j+jb<=n ) then ! apply the row interchanges to the other blocks. j2 = min( ju-j+1, kv ) - jb j3 = max( 0_${ik}$, ju-j-kv+1 ) ! use stdlib_slaswp to apply the row interchanges to a12, a22, and ! a32. call stdlib${ii}$_slaswp( j2, ab( kv+1-jb, j+jb ), ldab-1, 1_${ik}$, jb,ipiv( j ), 1_${ik}$ ) ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do ! apply the row interchanges to a13, a23, and a33 ! columnwise. k2 = j - 1_${ik}$ + jb + j2 do i = 1, j3 jj = k2 + i do ii = j + i - 1, j + jb - 1 ip = ipiv( ii ) if( ip/=ii ) then temp = ab( kv+1+ii-jj, jj ) ab( kv+1+ii-jj, jj ) = ab( kv+1+ip-jj, jj ) ab( kv+1+ip-jj, jj ) = temp end if end do end do ! update the relevant part of the trailing submatrix if( j2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_strsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j2, one, ab(& kv+1, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1 ) if( i2>0_${ik}$ ) then ! update a22 call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j2,jb, -one, ab( & kv+1+jb, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1, one,ab( kv+1, j+jb ), & ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a32 call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j2,jb, -one, & work31, ldwork,ab( kv+1-jb, j+jb ), ldab-1, one,ab( kv+kl+1-jb, j+jb ), & ldab-1 ) end if end if if( j3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array ! work13 do jj = 1, j3 do ii = jj, jb work13( ii, jj ) = ab( ii-jj+1, jj+j+kv-1 ) end do end do ! update a13 in the work array call stdlib${ii}$_strsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j3, one, ab(& kv+1, j ), ldab-1,work13, ldwork ) if( i2>0_${ik}$ ) then ! update a23 call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j3,jb, -one, ab( & kv+1+jb, j ), ldab-1,work13, ldwork, one, ab( 1_${ik}$+jb, j+kv ),ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a33 call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j3,jb, -one, & work31, ldwork, work13,ldwork, one, ab( 1_${ik}$+kl, j+kv ), ldab-1 ) end if ! copy the lower triangle of a13 back into place do jj = 1, j3 do ii = jj, jb ab( ii-jj+1, jj+j+kv-1 ) = work13( ii, jj ) end do end do end if else ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do end if ! partially undo the interchanges in the current block to ! restore the upper triangular form of a31 and copy the upper ! triangle of a31 back into place do jj = j + jb - 1, j, -1 jp = ipiv( jj ) - jj + 1_${ik}$ if( jp/=1_${ik}$ ) then ! apply interchange to columns j to jj-1 if( jp+jj-10_${ik}$ )call stdlib${ii}$_scopy( nw, work31( 1_${ik}$, jj-j+1 ), 1_${ik}$,ab( kv+kl+1-jj+j, jj )& , 1_${ik}$ ) end do end do loop_180 end if return end subroutine stdlib${ii}$_sgbtrf pure module subroutine stdlib${ii}$_dgbtrf( m, n, kl, ku, ab, ldab, ipiv, info ) !! DGBTRF computes an LU factorization of a real m-by-n band matrix A !! using partial pivoting with row interchanges. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldwork = nbmax+1 ! Local Scalars integer(${ik}$) :: i, i2, i3, ii, ip, j, j2, j3, jb, jj, jm, jp, ju, k2, km, kv, nb, & nw real(dp) :: temp ! Local Arrays real(dp) :: work13(ldwork,nbmax), work31(ldwork,nbmax) ! Intrinsic Functions ! Executable Statements ! kv is the number of superdiagonals in the factor u, allowing for ! fill-in kv = ku + kl ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldabkl ) then ! use unblocked code call stdlib${ii}$_dgbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) else ! use blocked code ! zero the superdiagonal elements of the work array work13 do j = 1, nb do i = 1, j - 1 work13( i, j ) = zero end do end do ! zero the subdiagonal elements of the work array work31 do j = 1, nb do i = j + 1, nb work31( i, j ) = zero end do end do ! gaussian elimination with partial pivoting ! set fill-in elements in columns ku+2 to kv to zero do j = ku + 2, min( kv, n ) do i = kv - j + 2, kl ab( i, j ) = zero end do end do ! ju is the index of the last column affected by the current ! stage of the factorization ju = 1_${ik}$ loop_180: do j = 1, min( m, n ), nb jb = min( nb, min( m, n )-j+1 ) ! the active part of the matrix is partitioned ! a11 a12 a13 ! a21 a22 a23 ! a31 a32 a33 ! here a11, a21 and a31 denote the current block of jb columns ! which is about to be factorized. the number of rows in the ! partitioning are jb, i2, i3 respectively, and the numbers ! of columns are jb, j2, j3. the superdiagonal elements of a13 ! and the subdiagonal elements of a31 lie outside the band. i2 = min( kl-jb, m-j-jb+1 ) i3 = min( jb, m-j-kl+1 ) ! j2 and j3 are computed after ju has been updated. ! factorize the current block of jb columns loop_80: do jj = j, j + jb - 1 ! set fill-in elements in column jj+kv to zero if( jj+kv<=n ) then do i = 1, kl ab( i, jj+kv ) = zero end do end if ! find pivot and test for singularity. km is the number of ! subdiagonal elements in the current column. km = min( kl, m-jj ) jp = stdlib${ii}$_idamax( km+1, ab( kv+1, jj ), 1_${ik}$ ) ipiv( jj ) = jp + jj - j if( ab( kv+jp, jj )/=zero ) then ju = max( ju, min( jj+ku+jp-1, n ) ) if( jp/=1_${ik}$ ) then ! apply interchange to columns j to j+jb-1 if( jp+jj-1jj )call stdlib${ii}$_dger( km, jm-jj, -one, ab( kv+2, jj ), 1_${ik}$,ab( kv, jj+& 1_${ik}$ ), ldab-1,ab( kv+1, jj+1 ), ldab-1 ) else ! if pivot is zero, set info to the index of the pivot ! unless a zero pivot has already been found. if( info==0_${ik}$ )info = jj end if ! copy current column of a31 into the work array work31 nw = min( jj-j+1, i3 ) if( nw>0_${ik}$ )call stdlib${ii}$_dcopy( nw, ab( kv+kl+1-jj+j, jj ), 1_${ik}$,work31( 1_${ik}$, jj-j+1 )& , 1_${ik}$ ) end do loop_80 if( j+jb<=n ) then ! apply the row interchanges to the other blocks. j2 = min( ju-j+1, kv ) - jb j3 = max( 0_${ik}$, ju-j-kv+1 ) ! use stdlib_dlaswp to apply the row interchanges to a12, a22, and ! a32. call stdlib${ii}$_dlaswp( j2, ab( kv+1-jb, j+jb ), ldab-1, 1_${ik}$, jb,ipiv( j ), 1_${ik}$ ) ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do ! apply the row interchanges to a13, a23, and a33 ! columnwise. k2 = j - 1_${ik}$ + jb + j2 do i = 1, j3 jj = k2 + i do ii = j + i - 1, j + jb - 1 ip = ipiv( ii ) if( ip/=ii ) then temp = ab( kv+1+ii-jj, jj ) ab( kv+1+ii-jj, jj ) = ab( kv+1+ip-jj, jj ) ab( kv+1+ip-jj, jj ) = temp end if end do end do ! update the relevant part of the trailing submatrix if( j2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_dtrsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j2, one, ab(& kv+1, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1 ) if( i2>0_${ik}$ ) then ! update a22 call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j2,jb, -one, ab( & kv+1+jb, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1, one,ab( kv+1, j+jb ), & ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a32 call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j2,jb, -one, & work31, ldwork,ab( kv+1-jb, j+jb ), ldab-1, one,ab( kv+kl+1-jb, j+jb ), & ldab-1 ) end if end if if( j3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array ! work13 do jj = 1, j3 do ii = jj, jb work13( ii, jj ) = ab( ii-jj+1, jj+j+kv-1 ) end do end do ! update a13 in the work array call stdlib${ii}$_dtrsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j3, one, ab(& kv+1, j ), ldab-1,work13, ldwork ) if( i2>0_${ik}$ ) then ! update a23 call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j3,jb, -one, ab( & kv+1+jb, j ), ldab-1,work13, ldwork, one, ab( 1_${ik}$+jb, j+kv ),ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a33 call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j3,jb, -one, & work31, ldwork, work13,ldwork, one, ab( 1_${ik}$+kl, j+kv ), ldab-1 ) end if ! copy the lower triangle of a13 back into place do jj = 1, j3 do ii = jj, jb ab( ii-jj+1, jj+j+kv-1 ) = work13( ii, jj ) end do end do end if else ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do end if ! partially undo the interchanges in the current block to ! restore the upper triangular form of a31 and copy the upper ! triangle of a31 back into place do jj = j + jb - 1, j, -1 jp = ipiv( jj ) - jj + 1_${ik}$ if( jp/=1_${ik}$ ) then ! apply interchange to columns j to jj-1 if( jp+jj-10_${ik}$ )call stdlib${ii}$_dcopy( nw, work31( 1_${ik}$, jj-j+1 ), 1_${ik}$,ab( kv+kl+1-jj+j, jj )& , 1_${ik}$ ) end do end do loop_180 end if return end subroutine stdlib${ii}$_dgbtrf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gbtrf( m, n, kl, ku, ab, ldab, ipiv, info ) !! DGBTRF: computes an LU factorization of a real m-by-n band matrix A !! using partial pivoting with row interchanges. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldwork = nbmax+1 ! Local Scalars integer(${ik}$) :: i, i2, i3, ii, ip, j, j2, j3, jb, jj, jm, jp, ju, k2, km, kv, nb, & nw real(${rk}$) :: temp ! Local Arrays real(${rk}$) :: work13(ldwork,nbmax), work31(ldwork,nbmax) ! Intrinsic Functions ! Executable Statements ! kv is the number of superdiagonals in the factor u, allowing for ! fill-in kv = ku + kl ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldabkl ) then ! use unblocked code call stdlib${ii}$_${ri}$gbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) else ! use blocked code ! zero the superdiagonal elements of the work array work13 do j = 1, nb do i = 1, j - 1 work13( i, j ) = zero end do end do ! zero the subdiagonal elements of the work array work31 do j = 1, nb do i = j + 1, nb work31( i, j ) = zero end do end do ! gaussian elimination with partial pivoting ! set fill-in elements in columns ku+2 to kv to zero do j = ku + 2, min( kv, n ) do i = kv - j + 2, kl ab( i, j ) = zero end do end do ! ju is the index of the last column affected by the current ! stage of the factorization ju = 1_${ik}$ loop_180: do j = 1, min( m, n ), nb jb = min( nb, min( m, n )-j+1 ) ! the active part of the matrix is partitioned ! a11 a12 a13 ! a21 a22 a23 ! a31 a32 a33 ! here a11, a21 and a31 denote the current block of jb columns ! which is about to be factorized. the number of rows in the ! partitioning are jb, i2, i3 respectively, and the numbers ! of columns are jb, j2, j3. the superdiagonal elements of a13 ! and the subdiagonal elements of a31 lie outside the band. i2 = min( kl-jb, m-j-jb+1 ) i3 = min( jb, m-j-kl+1 ) ! j2 and j3 are computed after ju has been updated. ! factorize the current block of jb columns loop_80: do jj = j, j + jb - 1 ! set fill-in elements in column jj+kv to zero if( jj+kv<=n ) then do i = 1, kl ab( i, jj+kv ) = zero end do end if ! find pivot and test for singularity. km is the number of ! subdiagonal elements in the current column. km = min( kl, m-jj ) jp = stdlib${ii}$_i${ri}$amax( km+1, ab( kv+1, jj ), 1_${ik}$ ) ipiv( jj ) = jp + jj - j if( ab( kv+jp, jj )/=zero ) then ju = max( ju, min( jj+ku+jp-1, n ) ) if( jp/=1_${ik}$ ) then ! apply interchange to columns j to j+jb-1 if( jp+jj-1jj )call stdlib${ii}$_${ri}$ger( km, jm-jj, -one, ab( kv+2, jj ), 1_${ik}$,ab( kv, jj+& 1_${ik}$ ), ldab-1,ab( kv+1, jj+1 ), ldab-1 ) else ! if pivot is zero, set info to the index of the pivot ! unless a zero pivot has already been found. if( info==0_${ik}$ )info = jj end if ! copy current column of a31 into the work array work31 nw = min( jj-j+1, i3 ) if( nw>0_${ik}$ )call stdlib${ii}$_${ri}$copy( nw, ab( kv+kl+1-jj+j, jj ), 1_${ik}$,work31( 1_${ik}$, jj-j+1 )& , 1_${ik}$ ) end do loop_80 if( j+jb<=n ) then ! apply the row interchanges to the other blocks. j2 = min( ju-j+1, kv ) - jb j3 = max( 0_${ik}$, ju-j-kv+1 ) ! use stdlib_${ri}$laswp to apply the row interchanges to a12, a22, and ! a32. call stdlib${ii}$_${ri}$laswp( j2, ab( kv+1-jb, j+jb ), ldab-1, 1_${ik}$, jb,ipiv( j ), 1_${ik}$ ) ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do ! apply the row interchanges to a13, a23, and a33 ! columnwise. k2 = j - 1_${ik}$ + jb + j2 do i = 1, j3 jj = k2 + i do ii = j + i - 1, j + jb - 1 ip = ipiv( ii ) if( ip/=ii ) then temp = ab( kv+1+ii-jj, jj ) ab( kv+1+ii-jj, jj ) = ab( kv+1+ip-jj, jj ) ab( kv+1+ip-jj, jj ) = temp end if end do end do ! update the relevant part of the trailing submatrix if( j2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_${ri}$trsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j2, one, ab(& kv+1, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1 ) if( i2>0_${ik}$ ) then ! update a22 call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j2,jb, -one, ab( & kv+1+jb, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1, one,ab( kv+1, j+jb ), & ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a32 call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j2,jb, -one, & work31, ldwork,ab( kv+1-jb, j+jb ), ldab-1, one,ab( kv+kl+1-jb, j+jb ), & ldab-1 ) end if end if if( j3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array ! work13 do jj = 1, j3 do ii = jj, jb work13( ii, jj ) = ab( ii-jj+1, jj+j+kv-1 ) end do end do ! update a13 in the work array call stdlib${ii}$_${ri}$trsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j3, one, ab(& kv+1, j ), ldab-1,work13, ldwork ) if( i2>0_${ik}$ ) then ! update a23 call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j3,jb, -one, ab( & kv+1+jb, j ), ldab-1,work13, ldwork, one, ab( 1_${ik}$+jb, j+kv ),ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a33 call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j3,jb, -one, & work31, ldwork, work13,ldwork, one, ab( 1_${ik}$+kl, j+kv ), ldab-1 ) end if ! copy the lower triangle of a13 back into place do jj = 1, j3 do ii = jj, jb ab( ii-jj+1, jj+j+kv-1 ) = work13( ii, jj ) end do end do end if else ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do end if ! partially undo the interchanges in the current block to ! restore the upper triangular form of a31 and copy the upper ! triangle of a31 back into place do jj = j + jb - 1, j, -1 jp = ipiv( jj ) - jj + 1_${ik}$ if( jp/=1_${ik}$ ) then ! apply interchange to columns j to jj-1 if( jp+jj-10_${ik}$ )call stdlib${ii}$_${ri}$copy( nw, work31( 1_${ik}$, jj-j+1 ), 1_${ik}$,ab( kv+kl+1-jj+j, jj )& , 1_${ik}$ ) end do end do loop_180 end if return end subroutine stdlib${ii}$_${ri}$gbtrf #:endif #:endfor pure module subroutine stdlib${ii}$_cgbtrf( m, n, kl, ku, ab, ldab, ipiv, info ) !! CGBTRF computes an LU factorization of a complex m-by-n band matrix A !! using partial pivoting with row interchanges. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldwork = nbmax+1 ! Local Scalars integer(${ik}$) :: i, i2, i3, ii, ip, j, j2, j3, jb, jj, jm, jp, ju, k2, km, kv, nb, & nw complex(sp) :: temp ! Local Arrays complex(sp) :: work13(ldwork,nbmax), work31(ldwork,nbmax) ! Intrinsic Functions ! Executable Statements ! kv is the number of superdiagonals in the factor u, allowing for ! fill-in kv = ku + kl ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldabkl ) then ! use unblocked code call stdlib${ii}$_cgbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) else ! use blocked code ! czero the superdiagonal elements of the work array work13 do j = 1, nb do i = 1, j - 1 work13( i, j ) = czero end do end do ! czero the subdiagonal elements of the work array work31 do j = 1, nb do i = j + 1, nb work31( i, j ) = czero end do end do ! gaussian elimination with partial pivoting ! set fill-in elements in columns ku+2 to kv to czero do j = ku + 2, min( kv, n ) do i = kv - j + 2, kl ab( i, j ) = czero end do end do ! ju is the index of the last column affected by the current ! stage of the factorization ju = 1_${ik}$ loop_180: do j = 1, min( m, n ), nb jb = min( nb, min( m, n )-j+1 ) ! the active part of the matrix is partitioned ! a11 a12 a13 ! a21 a22 a23 ! a31 a32 a33 ! here a11, a21 and a31 denote the current block of jb columns ! which is about to be factorized. the number of rows in the ! partitioning are jb, i2, i3 respectively, and the numbers ! of columns are jb, j2, j3. the superdiagonal elements of a13 ! and the subdiagonal elements of a31 lie outside the band. i2 = min( kl-jb, m-j-jb+1 ) i3 = min( jb, m-j-kl+1 ) ! j2 and j3 are computed after ju has been updated. ! factorize the current block of jb columns loop_80: do jj = j, j + jb - 1 ! set fill-in elements in column jj+kv to czero if( jj+kv<=n ) then do i = 1, kl ab( i, jj+kv ) = czero end do end if ! find pivot and test for singularity. km is the number of ! subdiagonal elements in the current column. km = min( kl, m-jj ) jp = stdlib${ii}$_icamax( km+1, ab( kv+1, jj ), 1_${ik}$ ) ipiv( jj ) = jp + jj - j if( ab( kv+jp, jj )/=czero ) then ju = max( ju, min( jj+ku+jp-1, n ) ) if( jp/=1_${ik}$ ) then ! apply interchange to columns j to j+jb-1 if( jp+jj-1jj )call stdlib${ii}$_cgeru( km, jm-jj, -cone, ab( kv+2, jj ), 1_${ik}$,ab( kv, & jj+1 ), ldab-1,ab( kv+1, jj+1 ), ldab-1 ) else ! if pivot is czero, set info to the index of the pivot ! unless a czero pivot has already been found. if( info==0_${ik}$ )info = jj end if ! copy current column of a31 into the work array work31 nw = min( jj-j+1, i3 ) if( nw>0_${ik}$ )call stdlib${ii}$_ccopy( nw, ab( kv+kl+1-jj+j, jj ), 1_${ik}$,work31( 1_${ik}$, jj-j+1 )& , 1_${ik}$ ) end do loop_80 if( j+jb<=n ) then ! apply the row interchanges to the other blocks. j2 = min( ju-j+1, kv ) - jb j3 = max( 0_${ik}$, ju-j-kv+1 ) ! use stdlib_claswp to apply the row interchanges to a12, a22, and ! a32. call stdlib${ii}$_claswp( j2, ab( kv+1-jb, j+jb ), ldab-1, 1_${ik}$, jb,ipiv( j ), 1_${ik}$ ) ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do ! apply the row interchanges to a13, a23, and a33 ! columnwise. k2 = j - 1_${ik}$ + jb + j2 do i = 1, j3 jj = k2 + i do ii = j + i - 1, j + jb - 1 ip = ipiv( ii ) if( ip/=ii ) then temp = ab( kv+1+ii-jj, jj ) ab( kv+1+ii-jj, jj ) = ab( kv+1+ip-jj, jj ) ab( kv+1+ip-jj, jj ) = temp end if end do end do ! update the relevant part of the trailing submatrix if( j2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_ctrsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j2, cone, & ab( kv+1, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1 ) if( i2>0_${ik}$ ) then ! update a22 call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j2,jb, -cone, ab(& kv+1+jb, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1, cone,ab( kv+1, j+jb )& , ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a32 call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j2,jb, -cone, & work31, ldwork,ab( kv+1-jb, j+jb ), ldab-1, cone,ab( kv+kl+1-jb, j+jb ),& ldab-1 ) end if end if if( j3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array ! work13 do jj = 1, j3 do ii = jj, jb work13( ii, jj ) = ab( ii-jj+1, jj+j+kv-1 ) end do end do ! update a13 in the work array call stdlib${ii}$_ctrsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j3, cone, & ab( kv+1, j ), ldab-1,work13, ldwork ) if( i2>0_${ik}$ ) then ! update a23 call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j3,jb, -cone, ab(& kv+1+jb, j ), ldab-1,work13, ldwork, cone, ab( 1_${ik}$+jb, j+kv ),ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a33 call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j3,jb, -cone, & work31, ldwork, work13,ldwork, cone, ab( 1_${ik}$+kl, j+kv ), ldab-1 ) end if ! copy the lower triangle of a13 back into place do jj = 1, j3 do ii = jj, jb ab( ii-jj+1, jj+j+kv-1 ) = work13( ii, jj ) end do end do end if else ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do end if ! partially undo the interchanges in the current block to ! restore the upper triangular form of a31 and copy the upper ! triangle of a31 back into place do jj = j + jb - 1, j, -1 jp = ipiv( jj ) - jj + 1_${ik}$ if( jp/=1_${ik}$ ) then ! apply interchange to columns j to jj-1 if( jp+jj-10_${ik}$ )call stdlib${ii}$_ccopy( nw, work31( 1_${ik}$, jj-j+1 ), 1_${ik}$,ab( kv+kl+1-jj+j, jj )& , 1_${ik}$ ) end do end do loop_180 end if return end subroutine stdlib${ii}$_cgbtrf pure module subroutine stdlib${ii}$_zgbtrf( m, n, kl, ku, ab, ldab, ipiv, info ) !! ZGBTRF computes an LU factorization of a complex m-by-n band matrix A !! using partial pivoting with row interchanges. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldwork = nbmax+1 ! Local Scalars integer(${ik}$) :: i, i2, i3, ii, ip, j, j2, j3, jb, jj, jm, jp, ju, k2, km, kv, nb, & nw complex(dp) :: temp ! Local Arrays complex(dp) :: work13(ldwork,nbmax), work31(ldwork,nbmax) ! Intrinsic Functions ! Executable Statements ! kv is the number of superdiagonals in the factor u, allowing for ! fill-in kv = ku + kl ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldabkl ) then ! use unblocked code call stdlib${ii}$_zgbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) else ! use blocked code ! czero the superdiagonal elements of the work array work13 do j = 1, nb do i = 1, j - 1 work13( i, j ) = czero end do end do ! czero the subdiagonal elements of the work array work31 do j = 1, nb do i = j + 1, nb work31( i, j ) = czero end do end do ! gaussian elimination with partial pivoting ! set fill-in elements in columns ku+2 to kv to czero do j = ku + 2, min( kv, n ) do i = kv - j + 2, kl ab( i, j ) = czero end do end do ! ju is the index of the last column affected by the current ! stage of the factorization ju = 1_${ik}$ loop_180: do j = 1, min( m, n ), nb jb = min( nb, min( m, n )-j+1 ) ! the active part of the matrix is partitioned ! a11 a12 a13 ! a21 a22 a23 ! a31 a32 a33 ! here a11, a21 and a31 denote the current block of jb columns ! which is about to be factorized. the number of rows in the ! partitioning are jb, i2, i3 respectively, and the numbers ! of columns are jb, j2, j3. the superdiagonal elements of a13 ! and the subdiagonal elements of a31 lie outside the band. i2 = min( kl-jb, m-j-jb+1 ) i3 = min( jb, m-j-kl+1 ) ! j2 and j3 are computed after ju has been updated. ! factorize the current block of jb columns loop_80: do jj = j, j + jb - 1 ! set fill-in elements in column jj+kv to czero if( jj+kv<=n ) then do i = 1, kl ab( i, jj+kv ) = czero end do end if ! find pivot and test for singularity. km is the number of ! subdiagonal elements in the current column. km = min( kl, m-jj ) jp = stdlib${ii}$_izamax( km+1, ab( kv+1, jj ), 1_${ik}$ ) ipiv( jj ) = jp + jj - j if( ab( kv+jp, jj )/=czero ) then ju = max( ju, min( jj+ku+jp-1, n ) ) if( jp/=1_${ik}$ ) then ! apply interchange to columns j to j+jb-1 if( jp+jj-1jj )call stdlib${ii}$_zgeru( km, jm-jj, -cone, ab( kv+2, jj ), 1_${ik}$,ab( kv, & jj+1 ), ldab-1,ab( kv+1, jj+1 ), ldab-1 ) else ! if pivot is czero, set info to the index of the pivot ! unless a czero pivot has already been found. if( info==0_${ik}$ )info = jj end if ! copy current column of a31 into the work array work31 nw = min( jj-j+1, i3 ) if( nw>0_${ik}$ )call stdlib${ii}$_zcopy( nw, ab( kv+kl+1-jj+j, jj ), 1_${ik}$,work31( 1_${ik}$, jj-j+1 )& , 1_${ik}$ ) end do loop_80 if( j+jb<=n ) then ! apply the row interchanges to the other blocks. j2 = min( ju-j+1, kv ) - jb j3 = max( 0_${ik}$, ju-j-kv+1 ) ! use stdlib_zlaswp to apply the row interchanges to a12, a22, and ! a32. call stdlib${ii}$_zlaswp( j2, ab( kv+1-jb, j+jb ), ldab-1, 1_${ik}$, jb,ipiv( j ), 1_${ik}$ ) ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do ! apply the row interchanges to a13, a23, and a33 ! columnwise. k2 = j - 1_${ik}$ + jb + j2 do i = 1, j3 jj = k2 + i do ii = j + i - 1, j + jb - 1 ip = ipiv( ii ) if( ip/=ii ) then temp = ab( kv+1+ii-jj, jj ) ab( kv+1+ii-jj, jj ) = ab( kv+1+ip-jj, jj ) ab( kv+1+ip-jj, jj ) = temp end if end do end do ! update the relevant part of the trailing submatrix if( j2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_ztrsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j2, cone, & ab( kv+1, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1 ) if( i2>0_${ik}$ ) then ! update a22 call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j2,jb, -cone, ab(& kv+1+jb, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1, cone,ab( kv+1, j+jb )& , ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a32 call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j2,jb, -cone, & work31, ldwork,ab( kv+1-jb, j+jb ), ldab-1, cone,ab( kv+kl+1-jb, j+jb ),& ldab-1 ) end if end if if( j3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array ! work13 do jj = 1, j3 do ii = jj, jb work13( ii, jj ) = ab( ii-jj+1, jj+j+kv-1 ) end do end do ! update a13 in the work array call stdlib${ii}$_ztrsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j3, cone, & ab( kv+1, j ), ldab-1,work13, ldwork ) if( i2>0_${ik}$ ) then ! update a23 call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j3,jb, -cone, ab(& kv+1+jb, j ), ldab-1,work13, ldwork, cone, ab( 1_${ik}$+jb, j+kv ),ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a33 call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j3,jb, -cone, & work31, ldwork, work13,ldwork, cone, ab( 1_${ik}$+kl, j+kv ), ldab-1 ) end if ! copy the lower triangle of a13 back into place do jj = 1, j3 do ii = jj, jb ab( ii-jj+1, jj+j+kv-1 ) = work13( ii, jj ) end do end do end if else ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do end if ! partially undo the interchanges in the current block to ! restore the upper triangular form of a31 and copy the upper ! triangle of a31 back into place do jj = j + jb - 1, j, -1 jp = ipiv( jj ) - jj + 1_${ik}$ if( jp/=1_${ik}$ ) then ! apply interchange to columns j to jj-1 if( jp+jj-10_${ik}$ )call stdlib${ii}$_zcopy( nw, work31( 1_${ik}$, jj-j+1 ), 1_${ik}$,ab( kv+kl+1-jj+j, jj )& , 1_${ik}$ ) end do end do loop_180 end if return end subroutine stdlib${ii}$_zgbtrf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gbtrf( m, n, kl, ku, ab, ldab, ipiv, info ) !! ZGBTRF: computes an LU factorization of a complex m-by-n band matrix A !! using partial pivoting with row interchanges. !! This is the blocked version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 64_${ik}$ integer(${ik}$), parameter :: ldwork = nbmax+1 ! Local Scalars integer(${ik}$) :: i, i2, i3, ii, ip, j, j2, j3, jb, jj, jm, jp, ju, k2, km, kv, nb, & nw complex(${ck}$) :: temp ! Local Arrays complex(${ck}$) :: work13(ldwork,nbmax), work31(ldwork,nbmax) ! Intrinsic Functions ! Executable Statements ! kv is the number of superdiagonals in the factor u, allowing for ! fill-in kv = ku + kl ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldabkl ) then ! use unblocked code call stdlib${ii}$_${ci}$gbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) else ! use blocked code ! czero the superdiagonal elements of the work array work13 do j = 1, nb do i = 1, j - 1 work13( i, j ) = czero end do end do ! czero the subdiagonal elements of the work array work31 do j = 1, nb do i = j + 1, nb work31( i, j ) = czero end do end do ! gaussian elimination with partial pivoting ! set fill-in elements in columns ku+2 to kv to czero do j = ku + 2, min( kv, n ) do i = kv - j + 2, kl ab( i, j ) = czero end do end do ! ju is the index of the last column affected by the current ! stage of the factorization ju = 1_${ik}$ loop_180: do j = 1, min( m, n ), nb jb = min( nb, min( m, n )-j+1 ) ! the active part of the matrix is partitioned ! a11 a12 a13 ! a21 a22 a23 ! a31 a32 a33 ! here a11, a21 and a31 denote the current block of jb columns ! which is about to be factorized. the number of rows in the ! partitioning are jb, i2, i3 respectively, and the numbers ! of columns are jb, j2, j3. the superdiagonal elements of a13 ! and the subdiagonal elements of a31 lie outside the band. i2 = min( kl-jb, m-j-jb+1 ) i3 = min( jb, m-j-kl+1 ) ! j2 and j3 are computed after ju has been updated. ! factorize the current block of jb columns loop_80: do jj = j, j + jb - 1 ! set fill-in elements in column jj+kv to czero if( jj+kv<=n ) then do i = 1, kl ab( i, jj+kv ) = czero end do end if ! find pivot and test for singularity. km is the number of ! subdiagonal elements in the current column. km = min( kl, m-jj ) jp = stdlib${ii}$_i${ci}$amax( km+1, ab( kv+1, jj ), 1_${ik}$ ) ipiv( jj ) = jp + jj - j if( ab( kv+jp, jj )/=czero ) then ju = max( ju, min( jj+ku+jp-1, n ) ) if( jp/=1_${ik}$ ) then ! apply interchange to columns j to j+jb-1 if( jp+jj-1jj )call stdlib${ii}$_${ci}$geru( km, jm-jj, -cone, ab( kv+2, jj ), 1_${ik}$,ab( kv, & jj+1 ), ldab-1,ab( kv+1, jj+1 ), ldab-1 ) else ! if pivot is czero, set info to the index of the pivot ! unless a czero pivot has already been found. if( info==0_${ik}$ )info = jj end if ! copy current column of a31 into the work array work31 nw = min( jj-j+1, i3 ) if( nw>0_${ik}$ )call stdlib${ii}$_${ci}$copy( nw, ab( kv+kl+1-jj+j, jj ), 1_${ik}$,work31( 1_${ik}$, jj-j+1 )& , 1_${ik}$ ) end do loop_80 if( j+jb<=n ) then ! apply the row interchanges to the other blocks. j2 = min( ju-j+1, kv ) - jb j3 = max( 0_${ik}$, ju-j-kv+1 ) ! use stdlib_${ci}$laswp to apply the row interchanges to a12, a22, and ! a32. call stdlib${ii}$_${ci}$laswp( j2, ab( kv+1-jb, j+jb ), ldab-1, 1_${ik}$, jb,ipiv( j ), 1_${ik}$ ) ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do ! apply the row interchanges to a13, a23, and a33 ! columnwise. k2 = j - 1_${ik}$ + jb + j2 do i = 1, j3 jj = k2 + i do ii = j + i - 1, j + jb - 1 ip = ipiv( ii ) if( ip/=ii ) then temp = ab( kv+1+ii-jj, jj ) ab( kv+1+ii-jj, jj ) = ab( kv+1+ip-jj, jj ) ab( kv+1+ip-jj, jj ) = temp end if end do end do ! update the relevant part of the trailing submatrix if( j2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_${ci}$trsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j2, cone, & ab( kv+1, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1 ) if( i2>0_${ik}$ ) then ! update a22 call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j2,jb, -cone, ab(& kv+1+jb, j ), ldab-1,ab( kv+1-jb, j+jb ), ldab-1, cone,ab( kv+1, j+jb )& , ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a32 call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j2,jb, -cone, & work31, ldwork,ab( kv+1-jb, j+jb ), ldab-1, cone,ab( kv+kl+1-jb, j+jb ),& ldab-1 ) end if end if if( j3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array ! work13 do jj = 1, j3 do ii = jj, jb work13( ii, jj ) = ab( ii-jj+1, jj+j+kv-1 ) end do end do ! update a13 in the work array call stdlib${ii}$_${ci}$trsm( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT',jb, j3, cone, & ab( kv+1, j ), ldab-1,work13, ldwork ) if( i2>0_${ik}$ ) then ! update a23 call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i2, j3,jb, -cone, ab(& kv+1+jb, j ), ldab-1,work13, ldwork, cone, ab( 1_${ik}$+jb, j+kv ),ldab-1 ) end if if( i3>0_${ik}$ ) then ! update a33 call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', i3, j3,jb, -cone, & work31, ldwork, work13,ldwork, cone, ab( 1_${ik}$+kl, j+kv ), ldab-1 ) end if ! copy the lower triangle of a13 back into place do jj = 1, j3 do ii = jj, jb ab( ii-jj+1, jj+j+kv-1 ) = work13( ii, jj ) end do end do end if else ! adjust the pivot indices. do i = j, j + jb - 1 ipiv( i ) = ipiv( i ) + j - 1_${ik}$ end do end if ! partially undo the interchanges in the current block to ! restore the upper triangular form of a31 and copy the upper ! triangle of a31 back into place do jj = j + jb - 1, j, -1 jp = ipiv( jj ) - jj + 1_${ik}$ if( jp/=1_${ik}$ ) then ! apply interchange to columns j to jj-1 if( jp+jj-10_${ik}$ )call stdlib${ii}$_${ci}$copy( nw, work31( 1_${ik}$, jj-j+1 ), 1_${ik}$,ab( kv+kl+1-jj+j, jj )& , 1_${ik}$ ) end do end do loop_180 end if return end subroutine stdlib${ii}$_${ci}$gbtrf #:endif #:endfor pure module subroutine stdlib${ii}$_sgbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) !! SGBTF2 computes an LU factorization of a real m-by-n band matrix A !! using partial pivoting with row interchanges. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, jp, ju, km, kv ! Intrinsic Functions ! Executable Statements ! kv is the number of superdiagonals in the factor u, allowing for ! fill-in. kv = ku + kl ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldab0_${ik}$ ) then ! compute multipliers. call stdlib${ii}$_sscal( km, one / ab( kv+1, j ), ab( kv+2, j ), 1_${ik}$ ) ! update trailing submatrix within the band. if( ju>j )call stdlib${ii}$_sger( km, ju-j, -one, ab( kv+2, j ), 1_${ik}$,ab( kv, j+1 ), & ldab-1, ab( kv+1, j+1 ),ldab-1 ) end if else ! if pivot is zero, set info to the index of the pivot ! unless a zero pivot has already been found. if( info==0_${ik}$ )info = j end if end do loop_40 return end subroutine stdlib${ii}$_sgbtf2 pure module subroutine stdlib${ii}$_dgbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) !! DGBTF2 computes an LU factorization of a real m-by-n band matrix A !! using partial pivoting with row interchanges. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, jp, ju, km, kv ! Intrinsic Functions ! Executable Statements ! kv is the number of superdiagonals in the factor u, allowing for ! fill-in. kv = ku + kl ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldab0_${ik}$ ) then ! compute multipliers. call stdlib${ii}$_dscal( km, one / ab( kv+1, j ), ab( kv+2, j ), 1_${ik}$ ) ! update trailing submatrix within the band. if( ju>j )call stdlib${ii}$_dger( km, ju-j, -one, ab( kv+2, j ), 1_${ik}$,ab( kv, j+1 ), & ldab-1, ab( kv+1, j+1 ),ldab-1 ) end if else ! if pivot is zero, set info to the index of the pivot ! unless a zero pivot has already been found. if( info==0_${ik}$ )info = j end if end do loop_40 return end subroutine stdlib${ii}$_dgbtf2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) !! DGBTF2: computes an LU factorization of a real m-by-n band matrix A !! using partial pivoting with row interchanges. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, jp, ju, km, kv ! Intrinsic Functions ! Executable Statements ! kv is the number of superdiagonals in the factor u, allowing for ! fill-in. kv = ku + kl ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldab0_${ik}$ ) then ! compute multipliers. call stdlib${ii}$_${ri}$scal( km, one / ab( kv+1, j ), ab( kv+2, j ), 1_${ik}$ ) ! update trailing submatrix within the band. if( ju>j )call stdlib${ii}$_${ri}$ger( km, ju-j, -one, ab( kv+2, j ), 1_${ik}$,ab( kv, j+1 ), & ldab-1, ab( kv+1, j+1 ),ldab-1 ) end if else ! if pivot is zero, set info to the index of the pivot ! unless a zero pivot has already been found. if( info==0_${ik}$ )info = j end if end do loop_40 return end subroutine stdlib${ii}$_${ri}$gbtf2 #:endif #:endfor pure module subroutine stdlib${ii}$_cgbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) !! CGBTF2 computes an LU factorization of a complex m-by-n band matrix !! A using partial pivoting with row interchanges. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, jp, ju, km, kv ! Intrinsic Functions ! Executable Statements ! kv is the number of superdiagonals in the factor u, allowing for ! fill-in. kv = ku + kl ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldab0_${ik}$ ) then ! compute multipliers. call stdlib${ii}$_cscal( km, cone / ab( kv+1, j ), ab( kv+2, j ), 1_${ik}$ ) ! update trailing submatrix within the band. if( ju>j )call stdlib${ii}$_cgeru( km, ju-j, -cone, ab( kv+2, j ), 1_${ik}$,ab( kv, j+1 ), & ldab-1, ab( kv+1, j+1 ),ldab-1 ) end if else ! if pivot is czero, set info to the index of the pivot ! unless a czero pivot has already been found. if( info==0_${ik}$ )info = j end if end do loop_40 return end subroutine stdlib${ii}$_cgbtf2 pure module subroutine stdlib${ii}$_zgbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) !! ZGBTF2 computes an LU factorization of a complex m-by-n band matrix !! A using partial pivoting with row interchanges. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, jp, ju, km, kv ! Intrinsic Functions ! Executable Statements ! kv is the number of superdiagonals in the factor u, allowing for ! fill-in. kv = ku + kl ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldab0_${ik}$ ) then ! compute multipliers. call stdlib${ii}$_zscal( km, cone / ab( kv+1, j ), ab( kv+2, j ), 1_${ik}$ ) ! update trailing submatrix within the band. if( ju>j )call stdlib${ii}$_zgeru( km, ju-j, -cone, ab( kv+2, j ), 1_${ik}$,ab( kv, j+1 ), & ldab-1, ab( kv+1, j+1 ),ldab-1 ) end if else ! if pivot is czero, set info to the index of the pivot ! unless a czero pivot has already been found. if( info==0_${ik}$ )info = j end if end do loop_40 return end subroutine stdlib${ii}$_zgbtf2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gbtf2( m, n, kl, ku, ab, ldab, ipiv, info ) !! ZGBTF2: computes an LU factorization of a complex m-by-n band matrix !! A using partial pivoting with row interchanges. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, jp, ju, km, kv ! Intrinsic Functions ! Executable Statements ! kv is the number of superdiagonals in the factor u, allowing for ! fill-in. kv = ku + kl ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldab0_${ik}$ ) then ! compute multipliers. call stdlib${ii}$_${ci}$scal( km, cone / ab( kv+1, j ), ab( kv+2, j ), 1_${ik}$ ) ! update trailing submatrix within the band. if( ju>j )call stdlib${ii}$_${ci}$geru( km, ju-j, -cone, ab( kv+2, j ), 1_${ik}$,ab( kv, j+1 ), & ldab-1, ab( kv+1, j+1 ),ldab-1 ) end if else ! if pivot is czero, set info to the index of the pivot ! unless a czero pivot has already been found. if( info==0_${ik}$ )info = j end if end do loop_40 return end subroutine stdlib${ii}$_${ci}$gbtf2 #:endif #:endfor pure module subroutine stdlib${ii}$_sgbtrs( trans, n, kl, ku, nrhs, ab, ldab, ipiv, b, ldb,info ) !! SGBTRS solves a system of linear equations !! A * X = B or A**T * X = B !! with a general band matrix A using the LU factorization computed !! by SGBTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(in) :: ab(ldab,*) real(sp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: lnoti, notran integer(${ik}$) :: i, j, kd, l, lm ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<( 2_${ik}$*kl+ku+1 ) ) then info = -7_${ik}$ else if( ldb0_${ik}$ if( notran ) then ! solve a*x = b. ! solve l*x = b, overwriting b with x. ! l is represented as a product of permutations and unit lower ! triangular matrices l = p(1) * l(1) * ... * p(n-1) * l(n-1), ! where each transformation l(i) is a rank-one modification of ! the identity matrix. if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_sswap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_sger( lm, nrhs, -one, ab( kd+1, j ), 1_${ik}$, b( j, 1_${ik}$ ),ldb, b( j+1, 1_${ik}$ )& , ldb ) end do end if do i = 1, nrhs ! solve u*x = b, overwriting b with x. call stdlib${ii}$_stbsv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, kl+ku,ab, ldab, b( 1_${ik}$, & i ), 1_${ik}$ ) end do else ! solve a**t*x = b. do i = 1, nrhs ! solve u**t*x = b, overwriting b with x. call stdlib${ii}$_stbsv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', n, kl+ku, ab,ldab, b( 1_${ik}$, i )& , 1_${ik}$ ) end do ! solve l**t*x = b, overwriting b with x. if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) call stdlib${ii}$_sgemv( 'TRANSPOSE', lm, nrhs, -one, b( j+1, 1_${ik}$ ),ldb, ab( kd+1, j )& , 1_${ik}$, one, b( j, 1_${ik}$ ), ldb ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_sswap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_sgbtrs pure module subroutine stdlib${ii}$_dgbtrs( trans, n, kl, ku, nrhs, ab, ldab, ipiv, b, ldb,info ) !! DGBTRS solves a system of linear equations !! A * X = B or A**T * X = B !! with a general band matrix A using the LU factorization computed !! by DGBTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(in) :: ab(ldab,*) real(dp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: lnoti, notran integer(${ik}$) :: i, j, kd, l, lm ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<( 2_${ik}$*kl+ku+1 ) ) then info = -7_${ik}$ else if( ldb0_${ik}$ if( notran ) then ! solve a*x = b. ! solve l*x = b, overwriting b with x. ! l is represented as a product of permutations and unit lower ! triangular matrices l = p(1) * l(1) * ... * p(n-1) * l(n-1), ! where each transformation l(i) is a rank-one modification of ! the identity matrix. if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_dswap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_dger( lm, nrhs, -one, ab( kd+1, j ), 1_${ik}$, b( j, 1_${ik}$ ),ldb, b( j+1, 1_${ik}$ )& , ldb ) end do end if do i = 1, nrhs ! solve u*x = b, overwriting b with x. call stdlib${ii}$_dtbsv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, kl+ku,ab, ldab, b( 1_${ik}$, & i ), 1_${ik}$ ) end do else ! solve a**t*x = b. do i = 1, nrhs ! solve u**t*x = b, overwriting b with x. call stdlib${ii}$_dtbsv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', n, kl+ku, ab,ldab, b( 1_${ik}$, i )& , 1_${ik}$ ) end do ! solve l**t*x = b, overwriting b with x. if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) call stdlib${ii}$_dgemv( 'TRANSPOSE', lm, nrhs, -one, b( j+1, 1_${ik}$ ),ldb, ab( kd+1, j )& , 1_${ik}$, one, b( j, 1_${ik}$ ), ldb ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_dswap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_dgbtrs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gbtrs( trans, n, kl, ku, nrhs, ab, ldab, ipiv, b, ldb,info ) !! DGBTRS: solves a system of linear equations !! A * X = B or A**T * X = B !! with a general band matrix A using the LU factorization computed !! by DGBTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(in) :: ab(ldab,*) real(${rk}$), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: lnoti, notran integer(${ik}$) :: i, j, kd, l, lm ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<( 2_${ik}$*kl+ku+1 ) ) then info = -7_${ik}$ else if( ldb0_${ik}$ if( notran ) then ! solve a*x = b. ! solve l*x = b, overwriting b with x. ! l is represented as a product of permutations and unit lower ! triangular matrices l = p(1) * l(1) * ... * p(n-1) * l(n-1), ! where each transformation l(i) is a rank-one modification of ! the identity matrix. if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_${ri}$swap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ri}$ger( lm, nrhs, -one, ab( kd+1, j ), 1_${ik}$, b( j, 1_${ik}$ ),ldb, b( j+1, 1_${ik}$ )& , ldb ) end do end if do i = 1, nrhs ! solve u*x = b, overwriting b with x. call stdlib${ii}$_${ri}$tbsv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, kl+ku,ab, ldab, b( 1_${ik}$, & i ), 1_${ik}$ ) end do else ! solve a**t*x = b. do i = 1, nrhs ! solve u**t*x = b, overwriting b with x. call stdlib${ii}$_${ri}$tbsv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', n, kl+ku, ab,ldab, b( 1_${ik}$, i )& , 1_${ik}$ ) end do ! solve l**t*x = b, overwriting b with x. if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', lm, nrhs, -one, b( j+1, 1_${ik}$ ),ldb, ab( kd+1, j )& , 1_${ik}$, one, b( j, 1_${ik}$ ), ldb ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_${ri}$swap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_${ri}$gbtrs #:endif #:endfor pure module subroutine stdlib${ii}$_cgbtrs( trans, n, kl, ku, nrhs, ab, ldab, ipiv, b, ldb,info ) !! CGBTRS solves a system of linear equations !! A * X = B, A**T * X = B, or A**H * X = B !! with a general band matrix A using the LU factorization computed !! by CGBTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(in) :: ab(ldab,*) complex(sp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: lnoti, notran integer(${ik}$) :: i, j, kd, l, lm ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<( 2_${ik}$*kl+ku+1 ) ) then info = -7_${ik}$ else if( ldb0_${ik}$ if( notran ) then ! solve a*x = b. ! solve l*x = b, overwriting b with x. ! l is represented as a product of permutations and unit lower ! triangular matrices l = p(1) * l(1) * ... * p(n-1) * l(n-1), ! where each transformation l(i) is a rank-cone modification of ! the identity matrix. if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_cswap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgeru( lm, nrhs, -cone, ab( kd+1, j ), 1_${ik}$, b( j, 1_${ik}$ ),ldb, b( j+1, & 1_${ik}$ ), ldb ) end do end if do i = 1, nrhs ! solve u*x = b, overwriting b with x. call stdlib${ii}$_ctbsv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, kl+ku,ab, ldab, b( 1_${ik}$, & i ), 1_${ik}$ ) end do else if( stdlib_lsame( trans, 'T' ) ) then ! solve a**t * x = b. do i = 1, nrhs ! solve u**t * x = b, overwriting b with x. call stdlib${ii}$_ctbsv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', n, kl+ku, ab,ldab, b( 1_${ik}$, i )& , 1_${ik}$ ) end do ! solve l**t * x = b, overwriting b with x. if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) call stdlib${ii}$_cgemv( 'TRANSPOSE', lm, nrhs, -cone, b( j+1, 1_${ik}$ ),ldb, ab( kd+1, j & ), 1_${ik}$, cone, b( j, 1_${ik}$ ), ldb ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_cswap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) end do end if else ! solve a**h * x = b. do i = 1, nrhs ! solve u**h * x = b, overwriting b with x. call stdlib${ii}$_ctbsv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT', n,kl+ku, ab, ldab,& b( 1_${ik}$, i ), 1_${ik}$ ) end do ! solve l**h * x = b, overwriting b with x. if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) call stdlib${ii}$_clacgv( nrhs, b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', lm, nrhs, -cone,b( j+1, 1_${ik}$ ), ldb, & ab( kd+1, j ), 1_${ik}$, cone,b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_clacgv( nrhs, b( j, 1_${ik}$ ), ldb ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_cswap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_cgbtrs pure module subroutine stdlib${ii}$_zgbtrs( trans, n, kl, ku, nrhs, ab, ldab, ipiv, b, ldb,info ) !! ZGBTRS solves a system of linear equations !! A * X = B, A**T * X = B, or A**H * X = B !! with a general band matrix A using the LU factorization computed !! by ZGBTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(in) :: ab(ldab,*) complex(dp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: lnoti, notran integer(${ik}$) :: i, j, kd, l, lm ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<( 2_${ik}$*kl+ku+1 ) ) then info = -7_${ik}$ else if( ldb0_${ik}$ if( notran ) then ! solve a*x = b. ! solve l*x = b, overwriting b with x. ! l is represented as a product of permutations and unit lower ! triangular matrices l = p(1) * l(1) * ... * p(n-1) * l(n-1), ! where each transformation l(i) is a rank-cone modification of ! the identity matrix. if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_zswap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgeru( lm, nrhs, -cone, ab( kd+1, j ), 1_${ik}$, b( j, 1_${ik}$ ),ldb, b( j+1, & 1_${ik}$ ), ldb ) end do end if do i = 1, nrhs ! solve u*x = b, overwriting b with x. call stdlib${ii}$_ztbsv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, kl+ku,ab, ldab, b( 1_${ik}$, & i ), 1_${ik}$ ) end do else if( stdlib_lsame( trans, 'T' ) ) then ! solve a**t * x = b. do i = 1, nrhs ! solve u**t * x = b, overwriting b with x. call stdlib${ii}$_ztbsv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', n, kl+ku, ab,ldab, b( 1_${ik}$, i )& , 1_${ik}$ ) end do ! solve l**t * x = b, overwriting b with x. if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) call stdlib${ii}$_zgemv( 'TRANSPOSE', lm, nrhs, -cone, b( j+1, 1_${ik}$ ),ldb, ab( kd+1, j & ), 1_${ik}$, cone, b( j, 1_${ik}$ ), ldb ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_zswap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) end do end if else ! solve a**h * x = b. do i = 1, nrhs ! solve u**h * x = b, overwriting b with x. call stdlib${ii}$_ztbsv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT', n,kl+ku, ab, ldab,& b( 1_${ik}$, i ), 1_${ik}$ ) end do ! solve l**h * x = b, overwriting b with x. if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) call stdlib${ii}$_zlacgv( nrhs, b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', lm, nrhs, -cone,b( j+1, 1_${ik}$ ), ldb, & ab( kd+1, j ), 1_${ik}$, cone,b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_zlacgv( nrhs, b( j, 1_${ik}$ ), ldb ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_zswap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_zgbtrs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gbtrs( trans, n, kl, ku, nrhs, ab, ldab, ipiv, b, ldb,info ) !! ZGBTRS: solves a system of linear equations !! A * X = B, A**T * X = B, or A**H * X = B !! with a general band matrix A using the LU factorization computed !! by ZGBTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(in) :: ab(ldab,*) complex(${ck}$), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: lnoti, notran integer(${ik}$) :: i, j, kd, l, lm ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<( 2_${ik}$*kl+ku+1 ) ) then info = -7_${ik}$ else if( ldb0_${ik}$ if( notran ) then ! solve a*x = b. ! solve l*x = b, overwriting b with x. ! l is represented as a product of permutations and unit lower ! triangular matrices l = p(1) * l(1) * ... * p(n-1) * l(n-1), ! where each transformation l(i) is a rank-cone modification of ! the identity matrix. if( lnoti ) then do j = 1, n - 1 lm = min( kl, n-j ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_${ci}$swap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$geru( lm, nrhs, -cone, ab( kd+1, j ), 1_${ik}$, b( j, 1_${ik}$ ),ldb, b( j+1, & 1_${ik}$ ), ldb ) end do end if do i = 1, nrhs ! solve u*x = b, overwriting b with x. call stdlib${ii}$_${ci}$tbsv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n, kl+ku,ab, ldab, b( 1_${ik}$, & i ), 1_${ik}$ ) end do else if( stdlib_lsame( trans, 'T' ) ) then ! solve a**t * x = b. do i = 1, nrhs ! solve u**t * x = b, overwriting b with x. call stdlib${ii}$_${ci}$tbsv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', n, kl+ku, ab,ldab, b( 1_${ik}$, i )& , 1_${ik}$ ) end do ! solve l**t * x = b, overwriting b with x. if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) call stdlib${ii}$_${ci}$gemv( 'TRANSPOSE', lm, nrhs, -cone, b( j+1, 1_${ik}$ ),ldb, ab( kd+1, j & ), 1_${ik}$, cone, b( j, 1_${ik}$ ), ldb ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_${ci}$swap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) end do end if else ! solve a**h * x = b. do i = 1, nrhs ! solve u**h * x = b, overwriting b with x. call stdlib${ii}$_${ci}$tbsv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT', n,kl+ku, ab, ldab,& b( 1_${ik}$, i ), 1_${ik}$ ) end do ! solve l**h * x = b, overwriting b with x. if( lnoti ) then do j = n - 1, 1, -1 lm = min( kl, n-j ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', lm, nrhs, -cone,b( j+1, 1_${ik}$ ), ldb, & ab( kd+1, j ), 1_${ik}$, cone,b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ci}$lacgv( nrhs, b( j, 1_${ik}$ ), ldb ) l = ipiv( j ) if( l/=j )call stdlib${ii}$_${ci}$swap( nrhs, b( l, 1_${ik}$ ), ldb, b( j, 1_${ik}$ ), ldb ) end do end if end if return end subroutine stdlib${ii}$_${ci}$gbtrs #:endif #:endfor pure module subroutine stdlib${ii}$_sgbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb,ipiv, b, ldb, x, & !! SGBRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is banded, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldafb, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: ab(ldab,*), afb(ldafb,*), b(ldb,*) real(sp), intent(out) :: berr(*), ferr(*), work(*) real(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transt integer(${ik}$) :: count, i, j, k, kase, kk, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldabsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_sgbtrs( trans, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work( n+1 ), n, info ) call stdlib${ii}$_saxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_slacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_slacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_sgbtrs( transt, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work( n+1 ), n, & info ) do i = 1, n work( n+i ) = work( n+i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( n+i )*work( i ) end do call stdlib${ii}$_sgbtrs( trans, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work( n+1 ), n, & info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_sgbrfs pure module subroutine stdlib${ii}$_dgbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb,ipiv, b, ldb, x, & !! DGBRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is banded, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldafb, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: ab(ldab,*), afb(ldafb,*), b(ldb,*) real(dp), intent(out) :: berr(*), ferr(*), work(*) real(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transt integer(${ik}$) :: count, i, j, k, kase, kk, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldabsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_dgbtrs( trans, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work( n+1 ), n, info ) call stdlib${ii}$_daxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_dlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_dlacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_dgbtrs( transt, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work( n+1 ), n, & info ) do i = 1, n work( n+i ) = work( n+i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( n+i )*work( i ) end do call stdlib${ii}$_dgbtrs( trans, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work( n+1 ), n, & info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_dgbrfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb,ipiv, b, ldb, x, & !! DGBRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is banded, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldafb, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: ab(ldab,*), afb(ldafb,*), b(ldb,*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) real(${rk}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transt integer(${ik}$) :: count, i, j, k, kase, kk, nz real(${rk}$) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldabsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ri}$gbtrs( trans, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work( n+1 ), n, info ) call stdlib${ii}$_${ri}$axpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ri}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ri}$lacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_${ri}$gbtrs( transt, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work( n+1 ), n, & info ) do i = 1, n work( n+i ) = work( n+i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( n+i )*work( i ) end do call stdlib${ii}$_${ri}$gbtrs( trans, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work( n+1 ), n, & info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ri}$gbrfs #:endif #:endfor pure module subroutine stdlib${ii}$_cgbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb,ipiv, b, ldb, x, & !! CGBRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is banded, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, rwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldafb, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: ab(ldab,*), afb(ldafb,*), b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, k, kase, kk, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldabsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_cgbtrs( trans, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv, work, n,info ) call stdlib${ii}$_caxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_cgbtrs( transt, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_cgbtrs( transn, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_cgbrfs pure module subroutine stdlib${ii}$_zgbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb,ipiv, b, ldb, x, & !! ZGBRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is banded, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, rwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldafb, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: ab(ldab,*), afb(ldafb,*), b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, k, kase, kk, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldabsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_zgbtrs( trans, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv, work, n,info ) call stdlib${ii}$_zaxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_zgbtrs( transt, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_zgbtrs( transn, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_zgbrfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb,ipiv, b, ldb, x, & !! ZGBRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is banded, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, rwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, ldafb, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: ab(ldab,*), afb(ldafb,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, k, kase, kk, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldabsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ci}$gbtrs( trans, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv, work, n,info ) call stdlib${ii}$_${ci}$axpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_${ci}$gbtrs( transt, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$gbtrs( transn, n, kl, ku, 1_${ik}$, afb, ldafb, ipiv,work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ci}$gbrfs #:endif #:endfor pure module subroutine stdlib${ii}$_sgbequ( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, info ) !! SGBEQU computes row and column scalings intended to equilibrate an !! M-by-N band matrix A and reduce its condition number. R returns the !! row scale factors and C the column scale factors, chosen to try to !! make the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have absolute value 1. !! R(i) and C(j) are restricted to be between SMLNUM = smallest safe !! number and BIGNUM = largest safe number. Use of these scaling !! factors is not guaranteed to reduce the condition number of A but !! works well in practice. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(sp), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(sp), intent(in) :: ab(ldab,*) real(sp), intent(out) :: c(*), r(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, kd real(sp) :: bignum, rcmax, rcmin, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero ) then r( i ) = radix**int( log( r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors. do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = max( j-ku, 1 ), min( j+kl, m ) c( j ) = max( c( j ), abs( ab( kd+i-j, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_sgbequb pure module subroutine stdlib${ii}$_dgbequb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, info ) !! DGBEQUB computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most !! the radix. !! R(i) and C(j) are restricted to be a power of the radix between !! SMLNUM = smallest safe number and BIGNUM = largest safe number. Use !! of these scaling factors is not guaranteed to reduce the condition !! number of A but works well in practice. !! This routine differs from DGEEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled entries' magnitudes are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(dp), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(dp), intent(in) :: ab(ldab,*) real(dp), intent(out) :: c(*), r(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, kd real(dp) :: bignum, rcmax, rcmin, smlnum, radix, logrdx ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero ) then r( i ) = radix**int( log( r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors. do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = max( j-ku, 1 ), min( j+kl, m ) c( j ) = max( c( j ), abs( ab( kd+i-j, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_dgbequb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gbequb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, info ) !! DGBEQUB: computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most !! the radix. !! R(i) and C(j) are restricted to be a power of the radix between !! SMLNUM = smallest safe number and BIGNUM = largest safe number. Use !! of these scaling factors is not guaranteed to reduce the condition !! number of A but works well in practice. !! This routine differs from DGEEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled entries' magnitudes are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(${rk}$), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(${rk}$), intent(in) :: ab(ldab,*) real(${rk}$), intent(out) :: c(*), r(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, kd real(${rk}$) :: bignum, rcmax, rcmin, smlnum, radix, logrdx ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero ) then r( i ) = radix**int( log( r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors. do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = max( j-ku, 1 ), min( j+kl, m ) c( j ) = max( c( j ), abs( ab( kd+i-j, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_${ri}$gbequb #:endif #:endfor pure module subroutine stdlib${ii}$_cgbequb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, info ) !! CGBEQUB computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most !! the radix. !! R(i) and C(j) are restricted to be a power of the radix between !! SMLNUM = smallest safe number and BIGNUM = largest safe number. Use !! of these scaling factors is not guaranteed to reduce the condition !! number of A but works well in practice. !! This routine differs from CGEEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled entries' magnitudes are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(sp), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(sp), intent(out) :: c(*), r(*) complex(sp), intent(in) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, kd real(sp) :: bignum, rcmax, rcmin, smlnum, radix, logrdx complex(sp) :: zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero ) then r( i ) = radix**int( log( r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors. do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = max( j-ku, 1 ), min( j+kl, m ) c( j ) = max( c( j ), cabs1( ab( kd+i-j, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_cgbequb pure module subroutine stdlib${ii}$_zgbequb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, info ) !! ZGBEQUB computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most !! the radix. !! R(i) and C(j) are restricted to be a power of the radix between !! SMLNUM = smallest safe number and BIGNUM = largest safe number. Use !! of these scaling factors is not guaranteed to reduce the condition !! number of A but works well in practice. !! This routine differs from ZGEEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled entries' magnitudes are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(dp), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(dp), intent(out) :: c(*), r(*) complex(dp), intent(in) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, kd real(dp) :: bignum, rcmax, rcmin, smlnum, radix, logrdx complex(dp) :: zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero ) then r( i ) = radix**int( log( r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors. do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = max( j-ku, 1 ), min( j+kl, m ) c( j ) = max( c( j ), cabs1( ab( kd+i-j, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_zgbequb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gbequb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, info ) !! ZGBEQUB: computes row and column scalings intended to equilibrate an !! M-by-N matrix A and reduce its condition number. R returns the row !! scale factors and C the column scale factors, chosen to try to make !! the largest element in each row and column of the matrix B with !! elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most !! the radix. !! R(i) and C(j) are restricted to be a power of the radix between !! SMLNUM = smallest safe number and BIGNUM = largest safe number. Use !! of these scaling factors is not guaranteed to reduce the condition !! number of A but works well in practice. !! This routine differs from ZGEEQU by restricting the scaling factors !! to a power of the radix. Barring over- and underflow, scaling by !! these factors introduces no additional rounding errors. However, the !! scaled entries' magnitudes are no longer approximately 1 but lie !! between sqrt(radix) and 1/sqrt(radix). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(${ck}$), intent(out) :: amax, colcnd, rowcnd ! Array Arguments real(${ck}$), intent(out) :: c(*), r(*) complex(${ck}$), intent(in) :: ab(ldab,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, kd real(${ck}$) :: bignum, rcmax, rcmin, smlnum, radix, logrdx complex(${ck}$) :: zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ ) then info = -3_${ik}$ else if( ku<0_${ik}$ ) then info = -4_${ik}$ else if( ldabzero ) then r( i ) = radix**int( log( r( i ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do i = 1, m rcmax = max( rcmax, r( i ) ) rcmin = min( rcmin, r( i ) ) end do amax = rcmax if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do i = 1, m if( r( i )==zero ) then info = i return end if end do else ! invert the scale factors. do i = 1, m r( i ) = one / min( max( r( i ), smlnum ), bignum ) end do ! compute rowcnd = min(r(i)) / max(r(i)). rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if ! compute column scale factors. do j = 1, n c( j ) = zero end do ! find the maximum element in each column, ! assuming the row scaling computed above. do j = 1, n do i = max( j-ku, 1 ), min( j+kl, m ) c( j ) = max( c( j ), cabs1( ab( kd+i-j, j ) )*r( i ) ) end do if( c( j )>zero ) then c( j ) = radix**int( log( c( j ) ) / logrdx,KIND=${ik}$) end if end do ! find the maximum and minimum scale factors. rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin==zero ) then ! find the first zero scale factor and return an error code. do j = 1, n if( c( j )==zero ) then info = m + j return end if end do else ! invert the scale factors. do j = 1, n c( j ) = one / min( max( c( j ), smlnum ), bignum ) end do ! compute colcnd = min(c(j)) / max(c(j)). colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) end if return end subroutine stdlib${ii}$_${ci}$gbequb #:endif #:endfor pure module subroutine stdlib${ii}$_slaqgb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, equed ) !! SLAQGB equilibrates a general M by N band matrix A with KL !! subdiagonals and KU superdiagonals using the row and scaling factors !! in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(sp), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(sp), intent(inout) :: ab(ldab,*) real(sp), intent(in) :: c(*), r(*) ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1e+0_sp ! Local Scalars integer(${ik}$) :: i, j real(sp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) / stdlib${ii}$_slamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*ab( ku+1+i-j, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = r( i )*ab( ku+1+i-j, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*r( i )*ab( ku+1+i-j, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_slaqgb pure module subroutine stdlib${ii}$_dlaqgb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, equed ) !! DLAQGB equilibrates a general M by N band matrix A with KL !! subdiagonals and KU superdiagonals using the row and scaling factors !! in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(dp), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(in) :: c(*), r(*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j real(dp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*ab( ku+1+i-j, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = r( i )*ab( ku+1+i-j, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*r( i )*ab( ku+1+i-j, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_dlaqgb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqgb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, equed ) !! DLAQGB: equilibrates a general M by N band matrix A with KL !! subdiagonals and KU superdiagonals using the row and scaling factors !! in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(${rk}$), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(${rk}$), intent(inout) :: ab(ldab,*) real(${rk}$), intent(in) :: c(*), r(*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: thresh = 0.1e+0_${rk}$ ! Local Scalars integer(${ik}$) :: i, j real(${rk}$) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${ri}$lamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*ab( ku+1+i-j, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = r( i )*ab( ku+1+i-j, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*r( i )*ab( ku+1+i-j, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_${ri}$laqgb #:endif #:endfor pure module subroutine stdlib${ii}$_claqgb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, equed ) !! CLAQGB equilibrates a general M by N band matrix A with KL !! subdiagonals and KU superdiagonals using the row and scaling factors !! in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(sp), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(sp), intent(in) :: c(*), r(*) complex(sp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1e+0_sp ! Local Scalars integer(${ik}$) :: i, j real(sp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) / stdlib${ii}$_slamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*ab( ku+1+i-j, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = r( i )*ab( ku+1+i-j, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*r( i )*ab( ku+1+i-j, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_claqgb pure module subroutine stdlib${ii}$_zlaqgb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, equed ) !! ZLAQGB equilibrates a general M by N band matrix A with KL !! subdiagonals and KU superdiagonals using the row and scaling factors !! in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(dp), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(dp), intent(in) :: c(*), r(*) complex(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j real(dp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*ab( ku+1+i-j, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = r( i )*ab( ku+1+i-j, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*r( i )*ab( ku+1+i-j, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_zlaqgb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqgb( m, n, kl, ku, ab, ldab, r, c, rowcnd, colcnd,amax, equed ) !! ZLAQGB: equilibrates a general M by N band matrix A with KL !! subdiagonals and KU superdiagonals using the row and scaling factors !! in the vectors R and C. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed integer(${ik}$), intent(in) :: kl, ku, ldab, m, n real(${ck}$), intent(in) :: amax, colcnd, rowcnd ! Array Arguments real(${ck}$), intent(in) :: c(*), r(*) complex(${ck}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: thresh = 0.1e+0_${ck}$ ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( m<=0_${ik}$ .or. n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) large = one / small if( rowcnd>=thresh .and. amax>=small .and. amax<=large )then ! no row scaling if( colcnd>=thresh ) then ! no column scaling equed = 'N' else ! column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*ab( ku+1+i-j, j ) end do end do equed = 'C' end if else if( colcnd>=thresh ) then ! row scaling, no column scaling do j = 1, n do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = r( i )*ab( ku+1+i-j, j ) end do end do equed = 'R' else ! row and column scaling do j = 1, n cj = c( j ) do i = max( 1, j-ku ), min( m, j+kl ) ab( ku+1+i-j, j ) = cj*r( i )*ab( ku+1+i-j, j ) end do end do equed = 'B' end if return end subroutine stdlib${ii}$_${ci}$laqgb #:endif #:endfor real(sp) module function stdlib${ii}$_sla_gbrcond( trans, n, kl, ku, ab, ldab, afb, ldafb,ipiv, cmode, c, & !! SLA_GBRCOND Estimates the Skeel condition number of op(A) * op2(C) !! where op2 is determined by CMODE as follows !! CMODE = 1 op2(C) = C !! CMODE = 0 op2(C) = I !! CMODE = -1 op2(C) = inv(C) !! The Skeel condition number cond(A) = norminf( |inv(A)||A| ) !! is computed by computing scaling factors R such that !! diag(R)*A*op2(C) is row equilibrated and computing the standard !! infinity-norm condition number. info, work, iwork ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: n, ldab, ldafb, kl, ku, cmode integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(in) :: ab(ldab,*), afb(ldafb,*), c(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notrans integer(${ik}$) :: kase, i, j, kd, ke real(sp) :: ainvnm, tmp ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements stdlib${ii}$_sla_gbrcond = zero info = 0_${ik}$ notrans = stdlib_lsame( trans, 'N' ) if ( .not. notrans .and. .not. stdlib_lsame(trans, 'T').and. .not. stdlib_lsame(trans, & 'C') ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kl<0_${ik}$ .or. kl>n-1 ) then info = -3_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = -4_${ik}$ else if( ldabn-1 ) then info = -3_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = -4_${ik}$ else if( ldabn-1 ) then info = -3_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = -4_${ik}$ else if( ldab=abs( dl( i ) ) ) then ! no row interchange required, eliminate dl(i) if( d( i )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else ! interchange rows i and i+1, eliminate dl(i) fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) du2( i ) = du( i+1 ) du( i+1 ) = -fact*du( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end do if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( abs( d( i ) )>=abs( dl( i ) ) ) then if( d( i )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end if ! check for a zero on the diagonal of u. do i = 1, n if( d( i )==zero ) then info = i go to 50 end if end do 50 continue return end subroutine stdlib${ii}$_sgttrf pure module subroutine stdlib${ii}$_dgttrf( n, dl, d, du, du2, ipiv, info ) !! DGTTRF computes an LU factorization of a real tridiagonal matrix A !! using elimination with partial pivoting and row interchanges. !! The factorization has the form !! A = L * U !! where L is a product of permutation and unit lower bidiagonal !! matrices and U is upper triangular with nonzeros in only the main !! diagonal and first two superdiagonals. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(dp), intent(inout) :: d(*), dl(*), du(*) real(dp), intent(out) :: du2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(dp) :: fact, temp ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'DGTTRF', -info ) return end if ! quick return if possible if( n==0 )return ! initialize ipiv(i) = i and du2(i) = 0 do i = 1, n ipiv( i ) = i end do do i = 1, n - 2 du2( i ) = zero end do do i = 1, n - 2 if( abs( d( i ) )>=abs( dl( i ) ) ) then ! no row interchange required, eliminate dl(i) if( d( i )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else ! interchange rows i and i+1, eliminate dl(i) fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) du2( i ) = du( i+1 ) du( i+1 ) = -fact*du( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end do if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( abs( d( i ) )>=abs( dl( i ) ) ) then if( d( i )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end if ! check for a zero on the diagonal of u. do i = 1, n if( d( i )==zero ) then info = i go to 50 end if end do 50 continue return end subroutine stdlib${ii}$_dgttrf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gttrf( n, dl, d, du, du2, ipiv, info ) !! DGTTRF: computes an LU factorization of a real tridiagonal matrix A !! using elimination with partial pivoting and row interchanges. !! The factorization has the form !! A = L * U !! where L is a product of permutation and unit lower bidiagonal !! matrices and U is upper triangular with nonzeros in only the main !! diagonal and first two superdiagonals. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(${rk}$), intent(inout) :: d(*), dl(*), du(*) real(${rk}$), intent(out) :: du2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(${rk}$) :: fact, temp ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'DGTTRF', -info ) return end if ! quick return if possible if( n==0 )return ! initialize ipiv(i) = i and du2(i) = 0 do i = 1, n ipiv( i ) = i end do do i = 1, n - 2 du2( i ) = zero end do do i = 1, n - 2 if( abs( d( i ) )>=abs( dl( i ) ) ) then ! no row interchange required, eliminate dl(i) if( d( i )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else ! interchange rows i and i+1, eliminate dl(i) fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) du2( i ) = du( i+1 ) du( i+1 ) = -fact*du( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end do if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( abs( d( i ) )>=abs( dl( i ) ) ) then if( d( i )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end if ! check for a zero on the diagonal of u. do i = 1, n if( d( i )==zero ) then info = i go to 50 end if end do 50 continue return end subroutine stdlib${ii}$_${ri}$gttrf #:endif #:endfor pure module subroutine stdlib${ii}$_cgttrf( n, dl, d, du, du2, ipiv, info ) !! CGTTRF computes an LU factorization of a complex tridiagonal matrix A !! using elimination with partial pivoting and row interchanges. !! The factorization has the form !! A = L * U !! where L is a product of permutation and unit lower bidiagonal !! matrices and U is upper triangular with nonzeros in only the main !! diagonal and first two superdiagonals. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(sp), intent(inout) :: d(*), dl(*), du(*) complex(sp), intent(out) :: du2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(sp) :: fact, temp, zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'CGTTRF', -info ) return end if ! quick return if possible if( n==0 )return ! initialize ipiv(i) = i and du2(i) = 0 do i = 1, n ipiv( i ) = i end do do i = 1, n - 2 du2( i ) = zero end do do i = 1, n - 2 if( cabs1( d( i ) )>=cabs1( dl( i ) ) ) then ! no row interchange required, eliminate dl(i) if( cabs1( d( i ) )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else ! interchange rows i and i+1, eliminate dl(i) fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) du2( i ) = du( i+1 ) du( i+1 ) = -fact*du( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end do if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( cabs1( d( i ) )>=cabs1( dl( i ) ) ) then if( cabs1( d( i ) )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end if ! check for a zero on the diagonal of u. do i = 1, n if( cabs1( d( i ) )==zero ) then info = i go to 50 end if end do 50 continue return end subroutine stdlib${ii}$_cgttrf pure module subroutine stdlib${ii}$_zgttrf( n, dl, d, du, du2, ipiv, info ) !! ZGTTRF computes an LU factorization of a complex tridiagonal matrix A !! using elimination with partial pivoting and row interchanges. !! The factorization has the form !! A = L * U !! where L is a product of permutation and unit lower bidiagonal !! matrices and U is upper triangular with nonzeros in only the main !! diagonal and first two superdiagonals. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(dp), intent(inout) :: d(*), dl(*), du(*) complex(dp), intent(out) :: du2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(dp) :: fact, temp, zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'ZGTTRF', -info ) return end if ! quick return if possible if( n==0 )return ! initialize ipiv(i) = i and du2(i) = 0 do i = 1, n ipiv( i ) = i end do do i = 1, n - 2 du2( i ) = zero end do do i = 1, n - 2 if( cabs1( d( i ) )>=cabs1( dl( i ) ) ) then ! no row interchange required, eliminate dl(i) if( cabs1( d( i ) )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else ! interchange rows i and i+1, eliminate dl(i) fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) du2( i ) = du( i+1 ) du( i+1 ) = -fact*du( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end do if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( cabs1( d( i ) )>=cabs1( dl( i ) ) ) then if( cabs1( d( i ) )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end if ! check for a zero on the diagonal of u. do i = 1, n if( cabs1( d( i ) )==zero ) then info = i go to 50 end if end do 50 continue return end subroutine stdlib${ii}$_zgttrf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gttrf( n, dl, d, du, du2, ipiv, info ) !! ZGTTRF: computes an LU factorization of a complex tridiagonal matrix A !! using elimination with partial pivoting and row interchanges. !! The factorization has the form !! A = L * U !! where L is a product of permutation and unit lower bidiagonal !! matrices and U is upper triangular with nonzeros in only the main !! diagonal and first two superdiagonals. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) complex(${ck}$), intent(inout) :: d(*), dl(*), du(*) complex(${ck}$), intent(out) :: du2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i complex(${ck}$) :: fact, temp, zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'ZGTTRF', -info ) return end if ! quick return if possible if( n==0 )return ! initialize ipiv(i) = i and du2(i) = 0 do i = 1, n ipiv( i ) = i end do do i = 1, n - 2 du2( i ) = zero end do do i = 1, n - 2 if( cabs1( d( i ) )>=cabs1( dl( i ) ) ) then ! no row interchange required, eliminate dl(i) if( cabs1( d( i ) )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else ! interchange rows i and i+1, eliminate dl(i) fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) du2( i ) = du( i+1 ) du( i+1 ) = -fact*du( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end do if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( cabs1( d( i ) )>=cabs1( dl( i ) ) ) then if( cabs1( d( i ) )/=zero ) then fact = dl( i ) / d( i ) dl( i ) = fact d( i+1 ) = d( i+1 ) - fact*du( i ) end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) dl( i ) = fact temp = du( i ) du( i ) = d( i+1 ) d( i+1 ) = temp - fact*d( i+1 ) ipiv( i ) = i + 1_${ik}$ end if end if ! check for a zero on the diagonal of u. do i = 1, n if( cabs1( d( i ) )==zero ) then info = i go to 50 end if end do 50 continue return end subroutine stdlib${ii}$_${ci}$gttrf #:endif #:endfor pure module subroutine stdlib${ii}$_sgttrs( trans, n, nrhs, dl, d, du, du2, ipiv, b, ldb,info ) !! SGTTRS solves one of the systems of equations !! A*X = B or A**T*X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by SGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(inout) :: b(ldb,*) real(sp), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran integer(${ik}$) :: itrans, j, jb, nb ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ notran = ( trans=='N' .or. trans=='N' ) if( .not.notran .and. .not.( trans=='T' .or. trans=='T' ) .and. .not.( trans=='C' .or. & trans=='C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldb=nrhs ) then call stdlib${ii}$_sgtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_sgtts2( itrans, n, jb, dl, d, du, du2, ipiv, b( 1_${ik}$, j ),ldb ) end do end if end subroutine stdlib${ii}$_sgttrs pure module subroutine stdlib${ii}$_dgttrs( trans, n, nrhs, dl, d, du, du2, ipiv, b, ldb,info ) !! DGTTRS solves one of the systems of equations !! A*X = B or A**T*X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by DGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(inout) :: b(ldb,*) real(dp), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran integer(${ik}$) :: itrans, j, jb, nb ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ notran = ( trans=='N' .or. trans=='N' ) if( .not.notran .and. .not.( trans=='T' .or. trans=='T' ) .and. .not.( trans=='C' .or. & trans=='C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldb=nrhs ) then call stdlib${ii}$_dgtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_dgtts2( itrans, n, jb, dl, d, du, du2, ipiv, b( 1_${ik}$, j ),ldb ) end do end if end subroutine stdlib${ii}$_dgttrs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gttrs( trans, n, nrhs, dl, d, du, du2, ipiv, b, ldb,info ) !! DGTTRS: solves one of the systems of equations !! A*X = B or A**T*X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by DGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(inout) :: b(ldb,*) real(${rk}$), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran integer(${ik}$) :: itrans, j, jb, nb ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ notran = ( trans=='N' .or. trans=='N' ) if( .not.notran .and. .not.( trans=='T' .or. trans=='T' ) .and. .not.( trans=='C' .or. & trans=='C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldb=nrhs ) then call stdlib${ii}$_${ri}$gtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_${ri}$gtts2( itrans, n, jb, dl, d, du, du2, ipiv, b( 1_${ik}$, j ),ldb ) end do end if end subroutine stdlib${ii}$_${ri}$gttrs #:endif #:endfor pure module subroutine stdlib${ii}$_cgttrs( trans, n, nrhs, dl, d, du, du2, ipiv, b, ldb,info ) !! CGTTRS solves one of the systems of equations !! A * X = B, A**T * X = B, or A**H * X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by CGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran integer(${ik}$) :: itrans, j, jb, nb ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ notran = ( trans=='N' .or. trans=='N' ) if( .not.notran .and. .not.( trans=='T' .or. trans=='T' ) .and. .not.( trans=='C' .or. & trans=='C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldb=nrhs ) then call stdlib${ii}$_cgtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_cgtts2( itrans, n, jb, dl, d, du, du2, ipiv, b( 1_${ik}$, j ),ldb ) end do end if end subroutine stdlib${ii}$_cgttrs pure module subroutine stdlib${ii}$_zgttrs( trans, n, nrhs, dl, d, du, du2, ipiv, b, ldb,info ) !! ZGTTRS solves one of the systems of equations !! A * X = B, A**T * X = B, or A**H * X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by ZGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran integer(${ik}$) :: itrans, j, jb, nb ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ notran = ( trans=='N' .or. trans=='N' ) if( .not.notran .and. .not.( trans=='T' .or. trans=='T' ) .and. .not.( trans=='C' .or. & trans=='C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldb=nrhs ) then call stdlib${ii}$_zgtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_zgtts2( itrans, n, jb, dl, d, du, du2, ipiv, b( 1_${ik}$, j ),ldb ) end do end if end subroutine stdlib${ii}$_zgttrs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gttrs( trans, n, nrhs, dl, d, du, du2, ipiv, b, ldb,info ) !! ZGTTRS: solves one of the systems of equations !! A * X = B, A**T * X = B, or A**H * X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by ZGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(inout) :: b(ldb,*) complex(${ck}$), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran integer(${ik}$) :: itrans, j, jb, nb ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ notran = ( trans=='N' .or. trans=='N' ) if( .not.notran .and. .not.( trans=='T' .or. trans=='T' ) .and. .not.( trans=='C' .or. & trans=='C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldb=nrhs ) then call stdlib${ii}$_${ci}$gtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_${ci}$gtts2( itrans, n, jb, dl, d, du, du2, ipiv, b( 1_${ik}$, j ),ldb ) end do end if end subroutine stdlib${ii}$_${ci}$gttrs #:endif #:endfor pure module subroutine stdlib${ii}$_sgtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) !! SGTTS2 solves one of the systems of equations !! A*X = B or A**T*X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by SGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: itrans, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(inout) :: b(ldb,*) real(sp), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ip, j real(sp) :: temp ! Executable Statements ! quick return if possible if( n==0 .or. nrhs==0 )return if( itrans==0_${ik}$ ) then ! solve a*x = b using the lu factorization of a, ! overwriting each right hand side vector with its solution. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 10 continue ! solve l*x = b. do i = 1, n - 1 ip = ipiv( i ) temp = b( i+1-ip+i, j ) - dl( i )*b( ip, j ) b( i, j ) = b( ip, j ) b( i+1, j ) = temp end do ! solve u*x = b. b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do if( j1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do end do end if else ! solve a**t * x = b. if( nrhs<=1_${ik}$ ) then ! solve u**t*x = b. j = 1_${ik}$ 70 continue b( 1_${ik}$, j ) = b( 1_${ik}$, j ) / d( 1_${ik}$ ) if( n>1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d( i & ) end do ! solve l**t*x = b. do i = n - 1, 1, -1 ip = ipiv( i ) temp = b( i, j ) - dl( i )*b( i+1, j ) b( i, j ) = b( ip, j ) b( ip, j ) = temp end do if( j1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d(& i ) end do do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - dl( i )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - dl( i )*temp b( i, j ) = temp end if end do end do end if end if end subroutine stdlib${ii}$_sgtts2 pure module subroutine stdlib${ii}$_dgtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) !! DGTTS2 solves one of the systems of equations !! A*X = B or A**T*X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by DGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: itrans, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(inout) :: b(ldb,*) real(dp), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ip, j real(dp) :: temp ! Executable Statements ! quick return if possible if( n==0 .or. nrhs==0 )return if( itrans==0_${ik}$ ) then ! solve a*x = b using the lu factorization of a, ! overwriting each right hand side vector with its solution. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 10 continue ! solve l*x = b. do i = 1, n - 1 ip = ipiv( i ) temp = b( i+1-ip+i, j ) - dl( i )*b( ip, j ) b( i, j ) = b( ip, j ) b( i+1, j ) = temp end do ! solve u*x = b. b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do if( j1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do end do end if else ! solve a**t * x = b. if( nrhs<=1_${ik}$ ) then ! solve u**t*x = b. j = 1_${ik}$ 70 continue b( 1_${ik}$, j ) = b( 1_${ik}$, j ) / d( 1_${ik}$ ) if( n>1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d( i & ) end do ! solve l**t*x = b. do i = n - 1, 1, -1 ip = ipiv( i ) temp = b( i, j ) - dl( i )*b( i+1, j ) b( i, j ) = b( ip, j ) b( ip, j ) = temp end do if( j1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d(& i ) end do do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - dl( i )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - dl( i )*temp b( i, j ) = temp end if end do end do end if end if end subroutine stdlib${ii}$_dgtts2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) !! DGTTS2: solves one of the systems of equations !! A*X = B or A**T*X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by DGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: itrans, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${rk}$), intent(inout) :: b(ldb,*) real(${rk}$), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ip, j real(${rk}$) :: temp ! Executable Statements ! quick return if possible if( n==0 .or. nrhs==0 )return if( itrans==0_${ik}$ ) then ! solve a*x = b using the lu factorization of a, ! overwriting each right hand side vector with its solution. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 10 continue ! solve l*x = b. do i = 1, n - 1 ip = ipiv( i ) temp = b( i+1-ip+i, j ) - dl( i )*b( ip, j ) b( i, j ) = b( ip, j ) b( i+1, j ) = temp end do ! solve u*x = b. b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do if( j1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do end do end if else ! solve a**t * x = b. if( nrhs<=1_${ik}$ ) then ! solve u**t*x = b. j = 1_${ik}$ 70 continue b( 1_${ik}$, j ) = b( 1_${ik}$, j ) / d( 1_${ik}$ ) if( n>1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d( i & ) end do ! solve l**t*x = b. do i = n - 1, 1, -1 ip = ipiv( i ) temp = b( i, j ) - dl( i )*b( i+1, j ) b( i, j ) = b( ip, j ) b( ip, j ) = temp end do if( j1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d(& i ) end do do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - dl( i )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - dl( i )*temp b( i, j ) = temp end if end do end do end if end if end subroutine stdlib${ii}$_${ri}$gtts2 #:endif #:endfor pure module subroutine stdlib${ii}$_cgtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) !! CGTTS2 solves one of the systems of equations !! A * X = B, A**T * X = B, or A**H * X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by CGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: itrans, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j complex(sp) :: temp ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n==0 .or. nrhs==0 )return if( itrans==0_${ik}$ ) then ! solve a*x = b using the lu factorization of a, ! overwriting each right hand side vector with its solution. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 10 continue ! solve l*x = b. do i = 1, n - 1 if( ipiv( i )==i ) then b( i+1, j ) = b( i+1, j ) - dl( i )*b( i, j ) else temp = b( i, j ) b( i, j ) = b( i+1, j ) b( i+1, j ) = temp - dl( i )*b( i, j ) end if end do ! solve u*x = b. b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do if( j1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do end do end if else if( itrans==1_${ik}$ ) then ! solve a**t * x = b. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 70 continue ! solve u**t * x = b. b( 1_${ik}$, j ) = b( 1_${ik}$, j ) / d( 1_${ik}$ ) if( n>1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d( i & ) end do ! solve l**t * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - dl( i )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - dl( i )*temp b( i, j ) = temp end if end do if( j1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d(& i ) end do ! solve l**t * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - dl( i )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - dl( i )*temp b( i, j ) = temp end if end do end do end if else ! solve a**h * x = b. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 130 continue ! solve u**h * x = b. b( 1_${ik}$, j ) = b( 1_${ik}$, j ) / conjg( d( 1_${ik}$ ) ) if( n>1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-conjg( du( 1_${ik}$ ) )*b( 1_${ik}$, j ) ) /conjg( d( 2_${ik}$ ) ) do i = 3, n b( i, j ) = ( b( i, j )-conjg( du( i-1 ) )*b( i-1, j )-conjg( du2( i-2 ) )*b( & i-2, j ) ) /conjg( d( i ) ) end do ! solve l**h * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - conjg( dl( i ) )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - conjg( dl( i ) )*temp b( i, j ) = temp end if end do if( j1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-conjg( du( 1_${ik}$ ) )*b( 1_${ik}$, j ) ) /conjg( d( 2_${ik}$ ) ) do i = 3, n b( i, j ) = ( b( i, j )-conjg( du( i-1 ) )*b( i-1, j )-conjg( du2( i-2 ) )& *b( i-2, j ) ) / conjg( d( i ) ) end do ! solve l**h * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - conjg( dl( i ) )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - conjg( dl( i ) )*temp b( i, j ) = temp end if end do end do end if end if end subroutine stdlib${ii}$_cgtts2 pure module subroutine stdlib${ii}$_zgtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) !! ZGTTS2 solves one of the systems of equations !! A * X = B, A**T * X = B, or A**H * X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by ZGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: itrans, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j complex(dp) :: temp ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n==0 .or. nrhs==0 )return if( itrans==0_${ik}$ ) then ! solve a*x = b using the lu factorization of a, ! overwriting each right hand side vector with its solution. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 10 continue ! solve l*x = b. do i = 1, n - 1 if( ipiv( i )==i ) then b( i+1, j ) = b( i+1, j ) - dl( i )*b( i, j ) else temp = b( i, j ) b( i, j ) = b( i+1, j ) b( i+1, j ) = temp - dl( i )*b( i, j ) end if end do ! solve u*x = b. b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do if( j1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do end do end if else if( itrans==1_${ik}$ ) then ! solve a**t * x = b. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 70 continue ! solve u**t * x = b. b( 1_${ik}$, j ) = b( 1_${ik}$, j ) / d( 1_${ik}$ ) if( n>1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d( i & ) end do ! solve l**t * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - dl( i )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - dl( i )*temp b( i, j ) = temp end if end do if( j1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d(& i ) end do ! solve l**t * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - dl( i )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - dl( i )*temp b( i, j ) = temp end if end do end do end if else ! solve a**h * x = b. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 130 continue ! solve u**h * x = b. b( 1_${ik}$, j ) = b( 1_${ik}$, j ) / conjg( d( 1_${ik}$ ) ) if( n>1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-conjg( du( 1_${ik}$ ) )*b( 1_${ik}$, j ) ) /conjg( d( 2_${ik}$ ) ) do i = 3, n b( i, j ) = ( b( i, j )-conjg( du( i-1 ) )*b( i-1, j )-conjg( du2( i-2 ) )*b( & i-2, j ) ) /conjg( d( i ) ) end do ! solve l**h * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - conjg( dl( i ) )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - conjg( dl( i ) )*temp b( i, j ) = temp end if end do if( j1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-conjg( du( 1_${ik}$ ) )*b( 1_${ik}$, j ) )/ conjg( d( 2_${ik}$ ) ) do i = 3, n b( i, j ) = ( b( i, j )-conjg( du( i-1 ) )*b( i-1, j )-conjg( du2( i-2 ) )& *b( i-2, j ) ) / conjg( d( i ) ) end do ! solve l**h * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - conjg( dl( i ) )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - conjg( dl( i ) )*temp b( i, j ) = temp end if end do end do end if end if end subroutine stdlib${ii}$_zgtts2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gtts2( itrans, n, nrhs, dl, d, du, du2, ipiv, b, ldb ) !! ZGTTS2: solves one of the systems of equations !! A * X = B, A**T * X = B, or A**H * X = B, !! with a tridiagonal matrix A using the LU factorization computed !! by ZGTTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: itrans, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) complex(${ck}$), intent(inout) :: b(ldb,*) complex(${ck}$), intent(in) :: d(*), dl(*), du(*), du2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j complex(${ck}$) :: temp ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n==0 .or. nrhs==0 )return if( itrans==0_${ik}$ ) then ! solve a*x = b using the lu factorization of a, ! overwriting each right hand side vector with its solution. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 10 continue ! solve l*x = b. do i = 1, n - 1 if( ipiv( i )==i ) then b( i+1, j ) = b( i+1, j ) - dl( i )*b( i, j ) else temp = b( i, j ) b( i, j ) = b( i+1, j ) b( i+1, j ) = temp - dl( i )*b( i, j ) end if end do ! solve u*x = b. b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do if( j1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-du2( i )*b( i+2, j ) ) / d( i ) end do end do end if else if( itrans==1_${ik}$ ) then ! solve a**t * x = b. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 70 continue ! solve u**t * x = b. b( 1_${ik}$, j ) = b( 1_${ik}$, j ) / d( 1_${ik}$ ) if( n>1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d( i & ) end do ! solve l**t * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - dl( i )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - dl( i )*temp b( i, j ) = temp end if end do if( j1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-du( 1_${ik}$ )*b( 1_${ik}$, j ) ) / d( 2_${ik}$ ) do i = 3, n b( i, j ) = ( b( i, j )-du( i-1 )*b( i-1, j )-du2( i-2 )*b( i-2, j ) ) / d(& i ) end do ! solve l**t * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - dl( i )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - dl( i )*temp b( i, j ) = temp end if end do end do end if else ! solve a**h * x = b. if( nrhs<=1_${ik}$ ) then j = 1_${ik}$ 130 continue ! solve u**h * x = b. b( 1_${ik}$, j ) = b( 1_${ik}$, j ) / conjg( d( 1_${ik}$ ) ) if( n>1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-conjg( du( 1_${ik}$ ) )*b( 1_${ik}$, j ) ) /conjg( d( 2_${ik}$ ) ) do i = 3, n b( i, j ) = ( b( i, j )-conjg( du( i-1 ) )*b( i-1, j )-conjg( du2( i-2 ) )*b( & i-2, j ) ) /conjg( d( i ) ) end do ! solve l**h * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - conjg( dl( i ) )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - conjg( dl( i ) )*temp b( i, j ) = temp end if end do if( j1_${ik}$ )b( 2_${ik}$, j ) = ( b( 2_${ik}$, j )-conjg( du( 1_${ik}$ ) )*b( 1_${ik}$, j ) )/ conjg( d( 2_${ik}$ ) ) do i = 3, n b( i, j ) = ( b( i, j )-conjg( du( i-1 ) )*b( i-1, j )-conjg( du2( i-2 ) )& *b( i-2, j ) ) / conjg( d( i ) ) end do ! solve l**h * x = b. do i = n - 1, 1, -1 if( ipiv( i )==i ) then b( i, j ) = b( i, j ) - conjg( dl( i ) )*b( i+1, j ) else temp = b( i+1, j ) b( i+1, j ) = b( i, j ) - conjg( dl( i ) )*temp b( i, j ) = temp end if end do end do end if end if end subroutine stdlib${ii}$_${ci}$gtts2 #:endif #:endfor pure module subroutine stdlib${ii}$_sgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2,ipiv, b, ldb, x, & !! SGTRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is tridiagonal, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: b(ldb,*), d(*), df(*), dl(*), dlf(*), du(*), du2(*), duf(*) real(sp), intent(out) :: berr(*), ferr(*), work(*) real(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, kase, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_sgttrs( trans, n, 1_${ik}$, dlf, df, duf, du2, ipiv,work( n+1 ), n, info ) call stdlib${ii}$_saxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_slacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 70 continue call stdlib${ii}$_slacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_sgttrs( transt, n, 1_${ik}$, dlf, df, duf, du2, ipiv,work( n+1 ), n, & info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_sgttrs( transn, n, 1_${ik}$, dlf, df, duf, du2, ipiv,work( n+1 ), n, & info ) end if go to 70 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_110 return end subroutine stdlib${ii}$_sgtrfs pure module subroutine stdlib${ii}$_dgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2,ipiv, b, ldb, x, & !! DGTRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is tridiagonal, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: b(ldb,*), d(*), df(*), dl(*), dlf(*), du(*), du2(*), duf(*) real(dp), intent(out) :: berr(*), ferr(*), work(*) real(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_dgttrs( trans, n, 1_${ik}$, dlf, df, duf, du2, ipiv,work( n+1 ), n, info ) call stdlib${ii}$_daxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_dlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 70 continue call stdlib${ii}$_dlacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_dgttrs( transt, n, 1_${ik}$, dlf, df, duf, du2, ipiv,work( n+1 ), n, & info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_dgttrs( transn, n, 1_${ik}$, dlf, df, duf, du2, ipiv,work( n+1 ), n, & info ) end if go to 70 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_110 return end subroutine stdlib${ii}$_dgtrfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2,ipiv, b, ldb, x, & !! DGTRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is tridiagonal, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: b(ldb,*), d(*), df(*), dl(*), dlf(*), du(*), du2(*), duf(*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) real(${rk}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, kase, nz real(${rk}$) :: eps, lstres, s, safe1, safe2, safmin ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ri}$gttrs( trans, n, 1_${ik}$, dlf, df, duf, du2, ipiv,work( n+1 ), n, info ) call stdlib${ii}$_${ri}$axpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ri}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 70 continue call stdlib${ii}$_${ri}$lacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_${ri}$gttrs( transt, n, 1_${ik}$, dlf, df, duf, du2, ipiv,work( n+1 ), n, & info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_${ri}$gttrs( transn, n, 1_${ik}$, dlf, df, duf, du2, ipiv,work( n+1 ), n, & info ) end if go to 70 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_110 return end subroutine stdlib${ii}$_${ri}$gtrfs #:endif #:endfor pure module subroutine stdlib${ii}$_cgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2,ipiv, b, ldb, x, & !! CGTRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is tridiagonal, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, rwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: b(ldb,*), d(*), df(*), dl(*), dlf(*), du(*), du2(*), duf(*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, kase, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_cgttrs( trans, n, 1_${ik}$, dlf, df, duf, du2, ipiv, work, n,info ) call stdlib${ii}$_caxpy( n, cmplx( one,KIND=sp), work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 70 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_cgttrs( transt, n, 1_${ik}$, dlf, df, duf, du2, ipiv, work,n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_cgttrs( transn, n, 1_${ik}$, dlf, df, duf, du2, ipiv, work,n, info ) end if go to 70 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_110 return end subroutine stdlib${ii}$_cgtrfs pure module subroutine stdlib${ii}$_zgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2,ipiv, b, ldb, x, & !! ZGTRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is tridiagonal, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, rwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: b(ldb,*), d(*), df(*), dl(*), dlf(*), du(*), du2(*), duf(*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_zgttrs( trans, n, 1_${ik}$, dlf, df, duf, du2, ipiv, work, n,info ) call stdlib${ii}$_zaxpy( n, cmplx( one,KIND=dp), work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 70 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_zgttrs( transt, n, 1_${ik}$, dlf, df, duf, du2, ipiv, work,n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_zgttrs( transn, n, 1_${ik}$, dlf, df, duf, du2, ipiv, work,n, info ) end if go to 70 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_110 return end subroutine stdlib${ii}$_zgtrfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2,ipiv, b, ldb, x, & !! ZGTRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is tridiagonal, and provides !! error bounds and backward error estimates for the solution. ldx, ferr, berr, work, rwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(in) :: ipiv(*) real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: b(ldb,*), d(*), df(*), dl(*), dlf(*), du(*), du2(*), duf(*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: notran character :: transn, transt integer(${ik}$) :: count, i, j, kase, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( trans, & 'C' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ci}$gttrs( trans, n, 1_${ik}$, dlf, df, duf, du2, ipiv, work, n,info ) call stdlib${ii}$_${ci}$axpy( n, cmplx( one,KIND=${ck}$), work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 70 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_${ci}$gttrs( transt, n, 1_${ik}$, dlf, df, duf, du2, ipiv, work,n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$gttrs( transn, n, 1_${ik}$, dlf, df, duf, du2, ipiv, work,n, info ) end if go to 70 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_110 return end subroutine stdlib${ii}$_${ci}$gtrfs #:endif #:endfor #:endfor end submodule stdlib_lapack_solve_lu_comp fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_solve_aux.fypp0000664000175000017500000021370615135654166026002 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_solve) stdlib_lapack_solve_aux implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slacn2( n, v, x, isgn, est, kase, isave ) !! SLACN2 estimates the 1-norm of a square, real matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: est ! Array Arguments integer(${ik}$), intent(out) :: isgn(*) integer(${ik}$), intent(inout) :: isave(3_${ik}$) real(sp), intent(out) :: v(*) real(sp), intent(inout) :: x(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, jlast real(sp) :: altsgn, estold, temp, xs ! Intrinsic Functions ! Executable Statements if( kase==0_${ik}$ ) then do i = 1, n x( i ) = one / real( n,KIND=sp) end do kase = 1_${ik}$ isave( 1_${ik}$ ) = 1_${ik}$ return end if go to ( 20, 40, 70, 110, 140 )isave( 1 ) ! ................ entry (isave( 1 ) = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 150 end if est = stdlib${ii}$_sasum( n, x, 1_${ik}$ ) do i = 1, n if( x(i)>=zero ) then x(i) = one else x(i) = -one end if isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 2_${ik}$ return ! ................ entry (isave( 1 ) = 2) ! first iteration. x has been overwritten by transpose(a)*x. 40 continue isave( 2_${ik}$ ) = stdlib${ii}$_isamax( n, x, 1_${ik}$ ) isave( 3_${ik}$ ) = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = zero end do x( isave( 2_${ik}$ ) ) = one kase = 1_${ik}$ isave( 1_${ik}$ ) = 3_${ik}$ return ! ................ entry (isave( 1 ) = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_scopy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_sasum( n, v, 1_${ik}$ ) do i = 1, n if( x(i)>=zero ) then xs = one else xs = -one end if if( nint( xs,KIND=${ik}$)/=isgn( i ) )go to 90 end do ! repeated sign vector detected, hence algorithm has converged. go to 120 90 continue ! test for cycling. if( est<=estold )go to 120 do i = 1, n if( x(i)>=zero ) then x(i) = one else x(i) = -one end if isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 4_${ik}$ return ! ................ entry (isave( 1 ) = 4) ! x has been overwritten by transpose(a)*x. 110 continue jlast = isave( 2_${ik}$ ) isave( 2_${ik}$ ) = stdlib${ii}$_isamax( n, x, 1_${ik}$ ) if( ( x( jlast )/=abs( x( isave( 2_${ik}$ ) ) ) ) .and.( isave( 3_${ik}$ )est ) then call stdlib${ii}$_scopy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 150 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_slacn2 pure module subroutine stdlib${ii}$_dlacn2( n, v, x, isgn, est, kase, isave ) !! DLACN2 estimates the 1-norm of a square, real matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: est ! Array Arguments integer(${ik}$), intent(out) :: isgn(*) integer(${ik}$), intent(inout) :: isave(3_${ik}$) real(dp), intent(out) :: v(*) real(dp), intent(inout) :: x(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, jlast real(dp) :: altsgn, estold, temp, xs ! Intrinsic Functions ! Executable Statements if( kase==0_${ik}$ ) then do i = 1, n x( i ) = one / real( n,KIND=dp) end do kase = 1_${ik}$ isave( 1_${ik}$ ) = 1_${ik}$ return end if go to ( 20, 40, 70, 110, 140 )isave( 1 ) ! ................ entry (isave( 1 ) = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 150 end if est = stdlib${ii}$_dasum( n, x, 1_${ik}$ ) do i = 1, n if( x(i)>=zero ) then x(i) = one else x(i) = -one end if isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 2_${ik}$ return ! ................ entry (isave( 1 ) = 2) ! first iteration. x has been overwritten by transpose(a)*x. 40 continue isave( 2_${ik}$ ) = stdlib${ii}$_idamax( n, x, 1_${ik}$ ) isave( 3_${ik}$ ) = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = zero end do x( isave( 2_${ik}$ ) ) = one kase = 1_${ik}$ isave( 1_${ik}$ ) = 3_${ik}$ return ! ................ entry (isave( 1 ) = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_dcopy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_dasum( n, v, 1_${ik}$ ) do i = 1, n if( x(i)>=zero ) then xs = one else xs = -one end if if( nint( xs,KIND=${ik}$)/=isgn( i ) )go to 90 end do ! repeated sign vector detected, hence algorithm has converged. go to 120 90 continue ! test for cycling. if( est<=estold )go to 120 do i = 1, n if( x(i)>=zero ) then x(i) = one else x(i) = -one end if isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 4_${ik}$ return ! ................ entry (isave( 1 ) = 4) ! x has been overwritten by transpose(a)*x. 110 continue jlast = isave( 2_${ik}$ ) isave( 2_${ik}$ ) = stdlib${ii}$_idamax( n, x, 1_${ik}$ ) if( ( x( jlast )/=abs( x( isave( 2_${ik}$ ) ) ) ) .and.( isave( 3_${ik}$ )est ) then call stdlib${ii}$_dcopy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 150 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_dlacn2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lacn2( n, v, x, isgn, est, kase, isave ) !! DLACN2: estimates the 1-norm of a square, real matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(${rk}$), intent(inout) :: est ! Array Arguments integer(${ik}$), intent(out) :: isgn(*) integer(${ik}$), intent(inout) :: isave(3_${ik}$) real(${rk}$), intent(out) :: v(*) real(${rk}$), intent(inout) :: x(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, jlast real(${rk}$) :: altsgn, estold, temp, xs ! Intrinsic Functions ! Executable Statements if( kase==0_${ik}$ ) then do i = 1, n x( i ) = one / real( n,KIND=${rk}$) end do kase = 1_${ik}$ isave( 1_${ik}$ ) = 1_${ik}$ return end if go to ( 20, 40, 70, 110, 140 )isave( 1 ) ! ................ entry (isave( 1 ) = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 150 end if est = stdlib${ii}$_${ri}$asum( n, x, 1_${ik}$ ) do i = 1, n if( x(i)>=zero ) then x(i) = one else x(i) = -one end if isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 2_${ik}$ return ! ................ entry (isave( 1 ) = 2) ! first iteration. x has been overwritten by transpose(a)*x. 40 continue isave( 2_${ik}$ ) = stdlib${ii}$_i${ri}$amax( n, x, 1_${ik}$ ) isave( 3_${ik}$ ) = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = zero end do x( isave( 2_${ik}$ ) ) = one kase = 1_${ik}$ isave( 1_${ik}$ ) = 3_${ik}$ return ! ................ entry (isave( 1 ) = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_${ri}$copy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_${ri}$asum( n, v, 1_${ik}$ ) do i = 1, n if( x(i)>=zero ) then xs = one else xs = -one end if if( nint( xs,KIND=${ik}$)/=isgn( i ) )go to 90 end do ! repeated sign vector detected, hence algorithm has converged. go to 120 90 continue ! test for cycling. if( est<=estold )go to 120 do i = 1, n if( x(i)>=zero ) then x(i) = one else x(i) = -one end if isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 4_${ik}$ return ! ................ entry (isave( 1 ) = 4) ! x has been overwritten by transpose(a)*x. 110 continue jlast = isave( 2_${ik}$ ) isave( 2_${ik}$ ) = stdlib${ii}$_i${ri}$amax( n, x, 1_${ik}$ ) if( ( x( jlast )/=abs( x( isave( 2_${ik}$ ) ) ) ) .and.( isave( 3_${ik}$ )est ) then call stdlib${ii}$_${ri}$copy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 150 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_${ri}$lacn2 #:endif #:endfor pure module subroutine stdlib${ii}$_clacn2( n, v, x, est, kase, isave ) !! CLACN2 estimates the 1-norm of a square, complex matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: est ! Array Arguments integer(${ik}$), intent(inout) :: isave(3_${ik}$) complex(sp), intent(out) :: v(*) complex(sp), intent(inout) :: x(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, jlast real(sp) :: absxi, altsgn, estold, safmin, temp ! Intrinsic Functions ! Executable Statements safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) if( kase==0_${ik}$ ) then do i = 1, n x( i ) = cmplx( one / real( n,KIND=sp),KIND=sp) end do kase = 1_${ik}$ isave( 1_${ik}$ ) = 1_${ik}$ return end if go to ( 20, 40, 70, 90, 120 )isave( 1 ) ! ................ entry (isave( 1 ) = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 130 end if est = stdlib${ii}$_scsum1( n, x, 1_${ik}$ ) do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=sp) / absxi,aimag( x( i ) ) / absxi,KIND=sp) else x( i ) = cone end if end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 2_${ik}$ return ! ................ entry (isave( 1 ) = 2) ! first iteration. x has been overwritten by ctrans(a)*x. 40 continue isave( 2_${ik}$ ) = stdlib${ii}$_icmax1( n, x, 1_${ik}$ ) isave( 3_${ik}$ ) = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = czero end do x( isave( 2_${ik}$ ) ) = cone kase = 1_${ik}$ isave( 1_${ik}$ ) = 3_${ik}$ return ! ................ entry (isave( 1 ) = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_ccopy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_scsum1( n, v, 1_${ik}$ ) ! test for cycling. if( est<=estold )go to 100 do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=sp) / absxi,aimag( x( i ) ) / absxi,KIND=sp) else x( i ) = cone end if end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 4_${ik}$ return ! ................ entry (isave( 1 ) = 4) ! x has been overwritten by ctrans(a)*x. 90 continue jlast = isave( 2_${ik}$ ) isave( 2_${ik}$ ) = stdlib${ii}$_icmax1( n, x, 1_${ik}$ ) if( ( abs( x( jlast ) )/=abs( x( isave( 2_${ik}$ ) ) ) ) .and.( isave( 3_${ik}$ )est ) then call stdlib${ii}$_ccopy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 130 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_clacn2 pure module subroutine stdlib${ii}$_zlacn2( n, v, x, est, kase, isave ) !! ZLACN2 estimates the 1-norm of a square, complex matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: est ! Array Arguments integer(${ik}$), intent(inout) :: isave(3_${ik}$) complex(dp), intent(out) :: v(*) complex(dp), intent(inout) :: x(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, jlast real(dp) :: absxi, altsgn, estold, safmin, temp ! Intrinsic Functions ! Executable Statements safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) if( kase==0_${ik}$ ) then do i = 1, n x( i ) = cmplx( one / real( n,KIND=dp),KIND=dp) end do kase = 1_${ik}$ isave( 1_${ik}$ ) = 1_${ik}$ return end if go to ( 20, 40, 70, 90, 120 )isave( 1 ) ! ................ entry (isave( 1 ) = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 130 end if est = stdlib${ii}$_dzsum1( n, x, 1_${ik}$ ) do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=dp) / absxi,aimag( x( i ) ) / absxi,KIND=dp) else x( i ) = cone end if end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 2_${ik}$ return ! ................ entry (isave( 1 ) = 2) ! first iteration. x has been overwritten by ctrans(a)*x. 40 continue isave( 2_${ik}$ ) = stdlib${ii}$_izmax1( n, x, 1_${ik}$ ) isave( 3_${ik}$ ) = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = czero end do x( isave( 2_${ik}$ ) ) = cone kase = 1_${ik}$ isave( 1_${ik}$ ) = 3_${ik}$ return ! ................ entry (isave( 1 ) = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_zcopy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_dzsum1( n, v, 1_${ik}$ ) ! test for cycling. if( est<=estold )go to 100 do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=dp) / absxi,aimag( x( i ) ) / absxi,KIND=dp) else x( i ) = cone end if end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 4_${ik}$ return ! ................ entry (isave( 1 ) = 4) ! x has been overwritten by ctrans(a)*x. 90 continue jlast = isave( 2_${ik}$ ) isave( 2_${ik}$ ) = stdlib${ii}$_izmax1( n, x, 1_${ik}$ ) if( ( abs( x( jlast ) )/=abs( x( isave( 2_${ik}$ ) ) ) ) .and.( isave( 3_${ik}$ )est ) then call stdlib${ii}$_zcopy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 130 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_zlacn2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lacn2( n, v, x, est, kase, isave ) !! ZLACN2: estimates the 1-norm of a square, complex matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(${ck}$), intent(inout) :: est ! Array Arguments integer(${ik}$), intent(inout) :: isave(3_${ik}$) complex(${ck}$), intent(out) :: v(*) complex(${ck}$), intent(inout) :: x(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, jlast real(${ck}$) :: absxi, altsgn, estold, safmin, temp ! Intrinsic Functions ! Executable Statements safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) if( kase==0_${ik}$ ) then do i = 1, n x( i ) = cmplx( one / real( n,KIND=${ck}$),KIND=${ck}$) end do kase = 1_${ik}$ isave( 1_${ik}$ ) = 1_${ik}$ return end if go to ( 20, 40, 70, 90, 120 )isave( 1 ) ! ................ entry (isave( 1 ) = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 130 end if est = stdlib${ii}$_${c2ri(ci)}$zsum1( n, x, 1_${ik}$ ) do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=${ck}$) / absxi,aimag( x( i ) ) / absxi,KIND=${ck}$) else x( i ) = cone end if end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 2_${ik}$ return ! ................ entry (isave( 1 ) = 2) ! first iteration. x has been overwritten by ctrans(a)*x. 40 continue isave( 2_${ik}$ ) = stdlib${ii}$_i${ci}$max1( n, x, 1_${ik}$ ) isave( 3_${ik}$ ) = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = czero end do x( isave( 2_${ik}$ ) ) = cone kase = 1_${ik}$ isave( 1_${ik}$ ) = 3_${ik}$ return ! ................ entry (isave( 1 ) = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_${ci}$copy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_${c2ri(ci)}$zsum1( n, v, 1_${ik}$ ) ! test for cycling. if( est<=estold )go to 100 do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=${ck}$) / absxi,aimag( x( i ) ) / absxi,KIND=${ck}$) else x( i ) = cone end if end do kase = 2_${ik}$ isave( 1_${ik}$ ) = 4_${ik}$ return ! ................ entry (isave( 1 ) = 4) ! x has been overwritten by ctrans(a)*x. 90 continue jlast = isave( 2_${ik}$ ) isave( 2_${ik}$ ) = stdlib${ii}$_i${ci}$max1( n, x, 1_${ik}$ ) if( ( abs( x( jlast ) )/=abs( x( isave( 2_${ik}$ ) ) ) ) .and.( isave( 3_${ik}$ )est ) then call stdlib${ii}$_${ci}$copy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 130 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_${ci}$lacn2 #:endif #:endfor module subroutine stdlib${ii}$_slacon( n, v, x, isgn, est, kase ) !! SLACON estimates the 1-norm of a square, real matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: est ! Array Arguments integer(${ik}$), intent(out) :: isgn(*) real(sp), intent(out) :: v(*) real(sp), intent(inout) :: x(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, iter, j, jlast, jump real(sp) :: altsgn, estold, temp ! Intrinsic Functions ! Save Statement save ! Executable Statements if( kase==0_${ik}$ ) then do i = 1, n x( i ) = one / real( n,KIND=sp) end do kase = 1_${ik}$ jump = 1_${ik}$ return end if go to ( 20, 40, 70, 110, 140 )jump ! ................ entry (jump = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 150 end if est = stdlib${ii}$_sasum( n, x, 1_${ik}$ ) do i = 1, n x( i ) = sign( one, x( i ) ) isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ jump = 2_${ik}$ return ! ................ entry (jump = 2) ! first iteration. x has been overwritten by transpose(a)*x. 40 continue j = stdlib${ii}$_isamax( n, x, 1_${ik}$ ) iter = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = zero end do x( j ) = one kase = 1_${ik}$ jump = 3_${ik}$ return ! ................ entry (jump = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_scopy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_sasum( n, v, 1_${ik}$ ) do i = 1, n if( nint( sign( one, x( i ) ),KIND=${ik}$)/=isgn( i ) )go to 90 end do ! repeated sign vector detected, hence algorithm has converged. go to 120 90 continue ! test for cycling. if( est<=estold )go to 120 do i = 1, n x( i ) = sign( one, x( i ) ) isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ jump = 4_${ik}$ return ! ................ entry (jump = 4) ! x has been overwritten by transpose(a)*x. 110 continue jlast = j j = stdlib${ii}$_isamax( n, x, 1_${ik}$ ) if( ( x( jlast )/=abs( x( j ) ) ) .and. ( iterest ) then call stdlib${ii}$_scopy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 150 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_slacon module subroutine stdlib${ii}$_dlacon( n, v, x, isgn, est, kase ) !! DLACON estimates the 1-norm of a square, real matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: est ! Array Arguments integer(${ik}$), intent(out) :: isgn(*) real(dp), intent(out) :: v(*) real(dp), intent(inout) :: x(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, iter, j, jlast, jump real(dp) :: altsgn, estold, temp ! Intrinsic Functions ! Save Statement save ! Executable Statements if( kase==0_${ik}$ ) then do i = 1, n x( i ) = one / real( n,KIND=dp) end do kase = 1_${ik}$ jump = 1_${ik}$ return end if go to ( 20, 40, 70, 110, 140 )jump ! ................ entry (jump = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 150 end if est = stdlib${ii}$_dasum( n, x, 1_${ik}$ ) do i = 1, n x( i ) = sign( one, x( i ) ) isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ jump = 2_${ik}$ return ! ................ entry (jump = 2) ! first iteration. x has been overwritten by transpose(a)*x. 40 continue j = stdlib${ii}$_idamax( n, x, 1_${ik}$ ) iter = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = zero end do x( j ) = one kase = 1_${ik}$ jump = 3_${ik}$ return ! ................ entry (jump = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_dcopy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_dasum( n, v, 1_${ik}$ ) do i = 1, n if( nint( sign( one, x( i ) ),KIND=${ik}$)/=isgn( i ) )go to 90 end do ! repeated sign vector detected, hence algorithm has converged. go to 120 90 continue ! test for cycling. if( est<=estold )go to 120 do i = 1, n x( i ) = sign( one, x( i ) ) isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ jump = 4_${ik}$ return ! ................ entry (jump = 4) ! x has been overwritten by transpose(a)*x. 110 continue jlast = j j = stdlib${ii}$_idamax( n, x, 1_${ik}$ ) if( ( x( jlast )/=abs( x( j ) ) ) .and. ( iterest ) then call stdlib${ii}$_dcopy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 150 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_dlacon #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$lacon( n, v, x, isgn, est, kase ) !! DLACON: estimates the 1-norm of a square, real matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(${rk}$), intent(inout) :: est ! Array Arguments integer(${ik}$), intent(out) :: isgn(*) real(${rk}$), intent(out) :: v(*) real(${rk}$), intent(inout) :: x(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, iter, j, jlast, jump real(${rk}$) :: altsgn, estold, temp ! Intrinsic Functions ! Save Statement save ! Executable Statements if( kase==0_${ik}$ ) then do i = 1, n x( i ) = one / real( n,KIND=${rk}$) end do kase = 1_${ik}$ jump = 1_${ik}$ return end if go to ( 20, 40, 70, 110, 140 )jump ! ................ entry (jump = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 150 end if est = stdlib${ii}$_${ri}$asum( n, x, 1_${ik}$ ) do i = 1, n x( i ) = sign( one, x( i ) ) isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ jump = 2_${ik}$ return ! ................ entry (jump = 2) ! first iteration. x has been overwritten by transpose(a)*x. 40 continue j = stdlib${ii}$_i${ri}$amax( n, x, 1_${ik}$ ) iter = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = zero end do x( j ) = one kase = 1_${ik}$ jump = 3_${ik}$ return ! ................ entry (jump = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_${ri}$copy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_${ri}$asum( n, v, 1_${ik}$ ) do i = 1, n if( nint( sign( one, x( i ) ),KIND=${ik}$)/=isgn( i ) )go to 90 end do ! repeated sign vector detected, hence algorithm has converged. go to 120 90 continue ! test for cycling. if( est<=estold )go to 120 do i = 1, n x( i ) = sign( one, x( i ) ) isgn( i ) = nint( x( i ),KIND=${ik}$) end do kase = 2_${ik}$ jump = 4_${ik}$ return ! ................ entry (jump = 4) ! x has been overwritten by transpose(a)*x. 110 continue jlast = j j = stdlib${ii}$_i${ri}$amax( n, x, 1_${ik}$ ) if( ( x( jlast )/=abs( x( j ) ) ) .and. ( iterest ) then call stdlib${ii}$_${ri}$copy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 150 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_${ri}$lacon #:endif #:endfor module subroutine stdlib${ii}$_clacon( n, v, x, est, kase ) !! CLACON estimates the 1-norm of a square, complex matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(sp), intent(inout) :: est ! Array Arguments complex(sp), intent(out) :: v(n) complex(sp), intent(inout) :: x(n) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, iter, j, jlast, jump real(sp) :: absxi, altsgn, estold, safmin, temp ! Intrinsic Functions ! Save Statement save ! Executable Statements safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) if( kase==0_${ik}$ ) then do i = 1, n x( i ) = cmplx( one / real( n,KIND=sp),KIND=sp) end do kase = 1_${ik}$ jump = 1_${ik}$ return end if go to ( 20, 40, 70, 90, 120 )jump ! ................ entry (jump = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 130 end if est = stdlib${ii}$_scsum1( n, x, 1_${ik}$ ) do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=sp) / absxi,aimag( x( i ) ) / absxi,KIND=sp) else x( i ) = cone end if end do kase = 2_${ik}$ jump = 2_${ik}$ return ! ................ entry (jump = 2) ! first iteration. x has been overwritten by ctrans(a)*x. 40 continue j = stdlib${ii}$_icmax1( n, x, 1_${ik}$ ) iter = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = czero end do x( j ) = cone kase = 1_${ik}$ jump = 3_${ik}$ return ! ................ entry (jump = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_ccopy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_scsum1( n, v, 1_${ik}$ ) ! test for cycling. if( est<=estold )go to 100 do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=sp) / absxi,aimag( x( i ) ) / absxi,KIND=sp) else x( i ) = cone end if end do kase = 2_${ik}$ jump = 4_${ik}$ return ! ................ entry (jump = 4) ! x has been overwritten by ctrans(a)*x. 90 continue jlast = j j = stdlib${ii}$_icmax1( n, x, 1_${ik}$ ) if( ( abs( x( jlast ) )/=abs( x( j ) ) ) .and.( iterest ) then call stdlib${ii}$_ccopy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 130 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_clacon module subroutine stdlib${ii}$_zlacon( n, v, x, est, kase ) !! ZLACON estimates the 1-norm of a square, complex matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(dp), intent(inout) :: est ! Array Arguments complex(dp), intent(out) :: v(n) complex(dp), intent(inout) :: x(n) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, iter, j, jlast, jump real(dp) :: absxi, altsgn, estold, safmin, temp ! Intrinsic Functions ! Save Statement save ! Executable Statements safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) if( kase==0_${ik}$ ) then do i = 1, n x( i ) = cmplx( one / real( n,KIND=dp),KIND=dp) end do kase = 1_${ik}$ jump = 1_${ik}$ return end if go to ( 20, 40, 70, 90, 120 )jump ! ................ entry (jump = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 130 end if est = stdlib${ii}$_dzsum1( n, x, 1_${ik}$ ) do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=dp) / absxi,aimag( x( i ) ) / absxi,KIND=dp) else x( i ) = cone end if end do kase = 2_${ik}$ jump = 2_${ik}$ return ! ................ entry (jump = 2) ! first iteration. x has been overwritten by ctrans(a)*x. 40 continue j = stdlib${ii}$_izmax1( n, x, 1_${ik}$ ) iter = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = czero end do x( j ) = cone kase = 1_${ik}$ jump = 3_${ik}$ return ! ................ entry (jump = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_zcopy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_dzsum1( n, v, 1_${ik}$ ) ! test for cycling. if( est<=estold )go to 100 do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=dp) / absxi,aimag( x( i ) ) / absxi,KIND=dp) else x( i ) = cone end if end do kase = 2_${ik}$ jump = 4_${ik}$ return ! ................ entry (jump = 4) ! x has been overwritten by ctrans(a)*x. 90 continue jlast = j j = stdlib${ii}$_izmax1( n, x, 1_${ik}$ ) if( ( abs( x( jlast ) )/=abs( x( j ) ) ) .and.( iterest ) then call stdlib${ii}$_zcopy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 130 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_zlacon #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$lacon( n, v, x, est, kase ) !! ZLACON: estimates the 1-norm of a square, complex matrix A. !! Reverse communication is used for evaluating matrix-vector products. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(inout) :: kase integer(${ik}$), intent(in) :: n real(${ck}$), intent(inout) :: est ! Array Arguments complex(${ck}$), intent(out) :: v(n) complex(${ck}$), intent(inout) :: x(n) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: i, iter, j, jlast, jump real(${ck}$) :: absxi, altsgn, estold, safmin, temp ! Intrinsic Functions ! Save Statement save ! Executable Statements safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) if( kase==0_${ik}$ ) then do i = 1, n x( i ) = cmplx( one / real( n,KIND=${ck}$),KIND=${ck}$) end do kase = 1_${ik}$ jump = 1_${ik}$ return end if go to ( 20, 40, 70, 90, 120 )jump ! ................ entry (jump = 1) ! first iteration. x has been overwritten by a*x. 20 continue if( n==1_${ik}$ ) then v( 1_${ik}$ ) = x( 1_${ik}$ ) est = abs( v( 1_${ik}$ ) ) ! ... quit go to 130 end if est = stdlib${ii}$_${c2ri(ci)}$zsum1( n, x, 1_${ik}$ ) do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=${ck}$) / absxi,aimag( x( i ) ) / absxi,KIND=${ck}$) else x( i ) = cone end if end do kase = 2_${ik}$ jump = 2_${ik}$ return ! ................ entry (jump = 2) ! first iteration. x has been overwritten by ctrans(a)*x. 40 continue j = stdlib${ii}$_i${ci}$max1( n, x, 1_${ik}$ ) iter = 2_${ik}$ ! main loop - iterations 2,3,...,itmax. 50 continue do i = 1, n x( i ) = czero end do x( j ) = cone kase = 1_${ik}$ jump = 3_${ik}$ return ! ................ entry (jump = 3) ! x has been overwritten by a*x. 70 continue call stdlib${ii}$_${ci}$copy( n, x, 1_${ik}$, v, 1_${ik}$ ) estold = est est = stdlib${ii}$_${c2ri(ci)}$zsum1( n, v, 1_${ik}$ ) ! test for cycling. if( est<=estold )go to 100 do i = 1, n absxi = abs( x( i ) ) if( absxi>safmin ) then x( i ) = cmplx( real( x( i ),KIND=${ck}$) / absxi,aimag( x( i ) ) / absxi,KIND=${ck}$) else x( i ) = cone end if end do kase = 2_${ik}$ jump = 4_${ik}$ return ! ................ entry (jump = 4) ! x has been overwritten by ctrans(a)*x. 90 continue jlast = j j = stdlib${ii}$_i${ci}$max1( n, x, 1_${ik}$ ) if( ( abs( x( jlast ) )/=abs( x( j ) ) ) .and.( iterest ) then call stdlib${ii}$_${ci}$copy( n, x, 1_${ik}$, v, 1_${ik}$ ) est = temp end if 130 continue kase = 0_${ik}$ return end subroutine stdlib${ii}$_${ci}$lacon #:endif #:endfor pure module subroutine stdlib${ii}$_sla_lin_berr( n, nz, nrhs, res, ayb, berr ) !! SLA_LIN_BERR computes componentwise relative backward error from !! the formula !! max(i) ( abs(R(i)) / ( abs(op(A_s))*abs(Y) + abs(B_s) )(i) ) !! where abs(Z) is the componentwise absolute value of the matrix !! or vector Z. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, nz, nrhs ! Array Arguments real(sp), intent(in) :: ayb(n,nrhs) real(sp), intent(out) :: berr(nrhs) real(sp), intent(in) :: res(n,nrhs) ! ===================================================================== ! Local Scalars real(sp) :: tmp,safe1 integer(${ik}$) :: i, j ! Intrinsic Functions ! Executable Statements ! adding safe1 to the numerator guards against spuriously zero ! residuals. a similar safeguard is in the sla_yyamv routine used ! to compute ayb. safe1 = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safe1 = (nz+1)*safe1 do j = 1, nrhs berr(j) = zero do i = 1, n if (ayb(i,j) /= 0.0_sp) then tmp = (safe1+abs(res(i,j)))/ayb(i,j) berr(j) = max( berr(j), tmp ) end if ! if ayb is exactly 0.0_sp (and if computed by sla_yyamv), then we know ! the true residual also must be exactly zero. end do end do end subroutine stdlib${ii}$_sla_lin_berr pure module subroutine stdlib${ii}$_dla_lin_berr ( n, nz, nrhs, res, ayb, berr ) !! DLA_LIN_BERR computes component-wise relative backward error from !! the formula !! max(i) ( abs(R(i)) / ( abs(op(A_s))*abs(Y) + abs(B_s) )(i) ) !! where abs(Z) is the component-wise absolute value of the matrix !! or vector Z. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, nz, nrhs ! Array Arguments real(dp), intent(in) :: ayb(n,nrhs) real(dp), intent(out) :: berr(nrhs) real(dp), intent(in) :: res(n,nrhs) ! ===================================================================== ! Local Scalars real(dp) :: tmp,safe1 integer(${ik}$) :: i, j ! Intrinsic Functions ! Executable Statements ! adding safe1 to the numerator guards against spuriously zero ! residuals. a similar safeguard is in the sla_yyamv routine used ! to compute ayb. safe1 = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safe1 = (nz+1)*safe1 do j = 1, nrhs berr(j) = zero do i = 1, n if (ayb(i,j) /= zero) then tmp = (safe1+abs(res(i,j)))/ayb(i,j) berr(j) = max( berr(j), tmp ) end if ! if ayb is exactly 0.0_dp (and if computed by sla_yyamv), then we know ! the true residual also must be exactly zero. end do end do end subroutine stdlib${ii}$_dla_lin_berr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$la_lin_berr ( n, nz, nrhs, res, ayb, berr ) !! DLA_LIN_BERR: computes component-wise relative backward error from !! the formula !! max(i) ( abs(R(i)) / ( abs(op(A_s))*abs(Y) + abs(B_s) )(i) ) !! where abs(Z) is the component-wise absolute value of the matrix !! or vector Z. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, nz, nrhs ! Array Arguments real(${rk}$), intent(in) :: ayb(n,nrhs) real(${rk}$), intent(out) :: berr(nrhs) real(${rk}$), intent(in) :: res(n,nrhs) ! ===================================================================== ! Local Scalars real(${rk}$) :: tmp,safe1 integer(${ik}$) :: i, j ! Intrinsic Functions ! Executable Statements ! adding safe1 to the numerator guards against spuriously zero ! residuals. a similar safeguard is in the sla_yyamv routine used ! to compute ayb. safe1 = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) safe1 = (nz+1)*safe1 do j = 1, nrhs berr(j) = zero do i = 1, n if (ayb(i,j) /= zero) then tmp = (safe1+abs(res(i,j)))/ayb(i,j) berr(j) = max( berr(j), tmp ) end if ! if ayb is exactly 0.0_${rk}$ (and if computed by sla_yyamv), then we know ! the true residual also must be exactly zero. end do end do end subroutine stdlib${ii}$_${ri}$la_lin_berr #:endif #:endfor pure module subroutine stdlib${ii}$_cla_lin_berr( n, nz, nrhs, res, ayb, berr ) !! CLA_LIN_BERR computes componentwise relative backward error from !! the formula !! max(i) ( abs(R(i)) / ( abs(op(A_s))*abs(Y) + abs(B_s) )(i) ) !! where abs(Z) is the componentwise absolute value of the matrix !! or vector Z. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, nz, nrhs ! Array Arguments real(sp), intent(in) :: ayb(n,nrhs) real(sp), intent(out) :: berr(nrhs) complex(sp), intent(in) :: res(n,nrhs) ! ===================================================================== ! Local Scalars real(sp) :: tmp,safe1 integer(${ik}$) :: i, j complex(sp) :: cdum ! Intrinsic Functions ! Statement Functions complex(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements ! adding safe1 to the numerator guards against spuriously zero ! residuals. a similar safeguard is in the cla_yyamv routine used ! to compute ayb. safe1 = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safe1 = (nz+1)*safe1 do j = 1, nrhs berr(j) = zero do i = 1, n if (ayb(i,j) /= 0.0_sp) then tmp = (safe1 + cabs1(res(i,j)))/ayb(i,j) berr(j) = max( berr(j), tmp ) end if ! if ayb is exactly 0.0_sp (and if computed by cla_yyamv), then we know ! the true residual also must be exactly zero. end do end do end subroutine stdlib${ii}$_cla_lin_berr pure module subroutine stdlib${ii}$_zla_lin_berr( n, nz, nrhs, res, ayb, berr ) !! ZLA_LIN_BERR computes componentwise relative backward error from !! the formula !! max(i) ( abs(R(i)) / ( abs(op(A_s))*abs(Y) + abs(B_s) )(i) ) !! where abs(Z) is the componentwise absolute value of the matrix !! or vector Z. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, nz, nrhs ! Array Arguments real(dp), intent(in) :: ayb(n,nrhs) real(dp), intent(out) :: berr(nrhs) complex(dp), intent(in) :: res(n,nrhs) ! ===================================================================== ! Local Scalars real(dp) :: tmp,safe1 integer(${ik}$) :: i, j complex(dp) :: cdum ! Intrinsic Functions ! Statement Functions complex(dp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements ! adding safe1 to the numerator guards against spuriously zero ! residuals. a similar safeguard is in the cla_yyamv routine used ! to compute ayb. safe1 = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safe1 = (nz+1)*safe1 do j = 1, nrhs berr(j) = zero do i = 1, n if (ayb(i,j) /= zero) then tmp = (safe1 + cabs1(res(i,j)))/ayb(i,j) berr(j) = max( berr(j), tmp ) end if ! if ayb is exactly 0.0_dp (and if computed by cla_yyamv), then we know ! the true residual also must be exactly zero. end do end do end subroutine stdlib${ii}$_zla_lin_berr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$la_lin_berr( n, nz, nrhs, res, ayb, berr ) !! ZLA_LIN_BERR: computes componentwise relative backward error from !! the formula !! max(i) ( abs(R(i)) / ( abs(op(A_s))*abs(Y) + abs(B_s) )(i) ) !! where abs(Z) is the componentwise absolute value of the matrix !! or vector Z. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n, nz, nrhs ! Array Arguments real(${ck}$), intent(in) :: ayb(n,nrhs) real(${ck}$), intent(out) :: berr(nrhs) complex(${ck}$), intent(in) :: res(n,nrhs) ! ===================================================================== ! Local Scalars real(${ck}$) :: tmp,safe1 integer(${ik}$) :: i, j complex(${ck}$) :: cdum ! Intrinsic Functions ! Statement Functions complex(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements ! adding safe1 to the numerator guards against spuriously zero ! residuals. a similar safeguard is in the cla_yyamv routine used ! to compute ayb. safe1 = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safe1 = (nz+1)*safe1 do j = 1, nrhs berr(j) = zero do i = 1, n if (ayb(i,j) /= zero) then tmp = (safe1 + cabs1(res(i,j)))/ayb(i,j) berr(j) = max( berr(j), tmp ) end if ! if ayb is exactly 0.0_${ck}$ (and if computed by cla_yyamv), then we know ! the true residual also must be exactly zero. end do end do end subroutine stdlib${ii}$_${ci}$la_lin_berr #:endif #:endfor #:endfor end submodule stdlib_lapack_solve_aux fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_lsq_constrained.fypp0000664000175000017500000022523615135654166027166 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_lsq_constrained implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info ) !! SGGLSE solves the linear equality-constrained least squares (LSE) !! problem: !! minimize || c - A*x ||_2 subject to B*x = d !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given !! M-vector, and d is a given P-vector. It is assumed that !! P <= N <= M+P, and !! rank(B) = P and rank( (A) ) = N. !! ( (B) ) !! These conditions ensure that the LSE problem has a unique solution, !! which is obtained using a generalized RQ factorization of the !! matrices (B, A) given by !! B = (0 R)*Q, A = Z*T*Q. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*) real(sp), intent(out) :: work(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. p>n .or. p0_${ik}$ ) then call stdlib${ii}$_strtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,& p, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if ! put the solution in x call stdlib${ii}$_scopy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ ) ! update c1 call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-p, p, -one, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, one, c, 1_${ik}$ & ) end if ! solve r11*x1 = c1 for x1 if( n>p ) then call stdlib${ii}$_strtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, & info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! put the solutions in x call stdlib${ii}$_scopy( n-p, c, 1_${ik}$, x, 1_${ik}$ ) end if ! compute the residual vector: if( m0_${ik}$ )call stdlib${ii}$_sgemv( 'NO TRANSPOSE', nr, n-m, -one, a( n-p+1, m+1 ),lda, d( & nr+1 ), 1_${ik}$, one, c( n-p+1 ), 1_${ik}$ ) else nr = p end if if( nr>0_${ik}$ ) then call stdlib${ii}$_strmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, & d, 1_${ik}$ ) call stdlib${ii}$_saxpy( nr, -one, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ ) end if ! backward transformation x = q**t*x call stdlib${ii}$_sormrq( 'LEFT', 'TRANSPOSE', n, 1_${ik}$, p, b, ldb, work( 1_${ik}$ ), x,n, work( p+mn+1 & ), lwork-p-mn, info ) work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_sgglse pure module subroutine stdlib${ii}$_dgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info ) !! DGGLSE solves the linear equality-constrained least squares (LSE) !! problem: !! minimize || c - A*x ||_2 subject to B*x = d !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given !! M-vector, and d is a given P-vector. It is assumed that !! P <= N <= M+P, and !! rank(B) = P and rank( (A) ) = N. !! ( (B) ) !! These conditions ensure that the LSE problem has a unique solution, !! which is obtained using a generalized RQ factorization of the !! matrices (B, A) given by !! B = (0 R)*Q, A = Z*T*Q. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*) real(dp), intent(out) :: work(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. p>n .or. p0_${ik}$ ) then call stdlib${ii}$_dtrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,& p, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if ! put the solution in x call stdlib${ii}$_dcopy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ ) ! update c1 call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-p, p, -one, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, one, c, 1_${ik}$ & ) end if ! solve r11*x1 = c1 for x1 if( n>p ) then call stdlib${ii}$_dtrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, & info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! put the solutions in x call stdlib${ii}$_dcopy( n-p, c, 1_${ik}$, x, 1_${ik}$ ) end if ! compute the residual vector: if( m0_${ik}$ )call stdlib${ii}$_dgemv( 'NO TRANSPOSE', nr, n-m, -one, a( n-p+1, m+1 ),lda, d( & nr+1 ), 1_${ik}$, one, c( n-p+1 ), 1_${ik}$ ) else nr = p end if if( nr>0_${ik}$ ) then call stdlib${ii}$_dtrmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, & d, 1_${ik}$ ) call stdlib${ii}$_daxpy( nr, -one, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ ) end if ! backward transformation x = q**t*x call stdlib${ii}$_dormrq( 'LEFT', 'TRANSPOSE', n, 1_${ik}$, p, b, ldb, work( 1_${ik}$ ), x,n, work( p+mn+1 & ), lwork-p-mn, info ) work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_dgglse #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info ) !! DGGLSE: solves the linear equality-constrained least squares (LSE) !! problem: !! minimize || c - A*x ||_2 subject to B*x = d !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given !! M-vector, and d is a given P-vector. It is assumed that !! P <= N <= M+P, and !! rank(B) = P and rank( (A) ) = N. !! ( (B) ) !! These conditions ensure that the LSE problem has a unique solution, !! which is obtained using a generalized RQ factorization of the !! matrices (B, A) given by !! B = (0 R)*Q, A = Z*T*Q. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*) real(${rk}$), intent(out) :: work(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. p>n .or. p0_${ik}$ ) then call stdlib${ii}$_${ri}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,& p, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if ! put the solution in x call stdlib${ii}$_${ri}$copy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ ) ! update c1 call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-p, p, -one, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, one, c, 1_${ik}$ & ) end if ! solve r11*x1 = c1 for x1 if( n>p ) then call stdlib${ii}$_${ri}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, & info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! put the solutions in x call stdlib${ii}$_${ri}$copy( n-p, c, 1_${ik}$, x, 1_${ik}$ ) end if ! compute the residual vector: if( m0_${ik}$ )call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', nr, n-m, -one, a( n-p+1, m+1 ),lda, d( & nr+1 ), 1_${ik}$, one, c( n-p+1 ), 1_${ik}$ ) else nr = p end if if( nr>0_${ik}$ ) then call stdlib${ii}$_${ri}$trmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, & d, 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( nr, -one, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ ) end if ! backward transformation x = q**t*x call stdlib${ii}$_${ri}$ormrq( 'LEFT', 'TRANSPOSE', n, 1_${ik}$, p, b, ldb, work( 1_${ik}$ ), x,n, work( p+mn+1 & ), lwork-p-mn, info ) work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_${ri}$gglse #:endif #:endfor pure module subroutine stdlib${ii}$_cgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info ) !! CGGLSE solves the linear equality-constrained least squares (LSE) !! problem: !! minimize || c - A*x ||_2 subject to B*x = d !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given !! M-vector, and d is a given P-vector. It is assumed that !! P <= N <= M+P, and !! rank(B) = P and rank( (A) ) = N. !! ( (B) ) !! These conditions ensure that the LSE problem has a unique solution, !! which is obtained using a generalized RQ factorization of the !! matrices (B, A) given by !! B = (0 R)*Q, A = Z*T*Q. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments complex(sp), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*) complex(sp), intent(out) :: work(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. p>n .or. p0_${ik}$ ) then call stdlib${ii}$_ctrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,& p, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if ! put the solution in x call stdlib${ii}$_ccopy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ ) ! update c1 call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-p, p, -cone, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, cone, c, & 1_${ik}$ ) end if ! solve r11*x1 = c1 for x1 if( n>p ) then call stdlib${ii}$_ctrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, & info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! put the solutions in x call stdlib${ii}$_ccopy( n-p, c, 1_${ik}$, x, 1_${ik}$ ) end if ! compute the residual vector: if( m0_${ik}$ )call stdlib${ii}$_cgemv( 'NO TRANSPOSE', nr, n-m, -cone, a( n-p+1, m+1 ),lda, d(& nr+1 ), 1_${ik}$, cone, c( n-p+1 ), 1_${ik}$ ) else nr = p end if if( nr>0_${ik}$ ) then call stdlib${ii}$_ctrmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, & d, 1_${ik}$ ) call stdlib${ii}$_caxpy( nr, -cone, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ ) end if ! backward transformation x = q**h*x call stdlib${ii}$_cunmrq( 'LEFT', 'CONJUGATE TRANSPOSE', n, 1_${ik}$, p, b, ldb,work( 1_${ik}$ ), x, n, & work( p+mn+1 ), lwork-p-mn, info ) work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_cgglse pure module subroutine stdlib${ii}$_zgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info ) !! ZGGLSE solves the linear equality-constrained least squares (LSE) !! problem: !! minimize || c - A*x ||_2 subject to B*x = d !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given !! M-vector, and d is a given P-vector. It is assumed that !! P <= N <= M+P, and !! rank(B) = P and rank( (A) ) = N. !! ( (B) ) !! These conditions ensure that the LSE problem has a unique solution, !! which is obtained using a generalized RQ factorization of the !! matrices (B, A) given by !! B = (0 R)*Q, A = Z*T*Q. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments complex(dp), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*) complex(dp), intent(out) :: work(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. p>n .or. p0_${ik}$ ) then call stdlib${ii}$_ztrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,& p, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if ! put the solution in x call stdlib${ii}$_zcopy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ ) ! update c1 call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-p, p, -cone, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, cone, c, & 1_${ik}$ ) end if ! solve r11*x1 = c1 for x1 if( n>p ) then call stdlib${ii}$_ztrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, & info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! put the solutions in x call stdlib${ii}$_zcopy( n-p, c, 1_${ik}$, x, 1_${ik}$ ) end if ! compute the residual vector: if( m0_${ik}$ )call stdlib${ii}$_zgemv( 'NO TRANSPOSE', nr, n-m, -cone, a( n-p+1, m+1 ),lda, d(& nr+1 ), 1_${ik}$, cone, c( n-p+1 ), 1_${ik}$ ) else nr = p end if if( nr>0_${ik}$ ) then call stdlib${ii}$_ztrmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, & d, 1_${ik}$ ) call stdlib${ii}$_zaxpy( nr, -cone, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ ) end if ! backward transformation x = q**h*x call stdlib${ii}$_zunmrq( 'LEFT', 'CONJUGATE TRANSPOSE', n, 1_${ik}$, p, b, ldb,work( 1_${ik}$ ), x, n, & work( p+mn+1 ), lwork-p-mn, info ) work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_zgglse #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info ) !! ZGGLSE: solves the linear equality-constrained least squares (LSE) !! problem: !! minimize || c - A*x ||_2 subject to B*x = d !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given !! M-vector, and d is a given P-vector. It is assumed that !! P <= N <= M+P, and !! rank(B) = P and rank( (A) ) = N. !! ( (B) ) !! These conditions ensure that the LSE problem has a unique solution, !! which is obtained using a generalized RQ factorization of the !! matrices (B, A) given by !! B = (0 R)*Q, A = Z*T*Q. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*) complex(${ck}$), intent(out) :: work(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ mn = min( m, n ) lquery = ( lwork==-1_${ik}$ ) if( m<0_${ik}$ ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. p>n .or. p0_${ik}$ ) then call stdlib${ii}$_${ci}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,& p, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if ! put the solution in x call stdlib${ii}$_${ci}$copy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ ) ! update c1 call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-p, p, -cone, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, cone, c, & 1_${ik}$ ) end if ! solve r11*x1 = c1 for x1 if( n>p ) then call stdlib${ii}$_${ci}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, & info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! put the solutions in x call stdlib${ii}$_${ci}$copy( n-p, c, 1_${ik}$, x, 1_${ik}$ ) end if ! compute the residual vector: if( m0_${ik}$ )call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', nr, n-m, -cone, a( n-p+1, m+1 ),lda, d(& nr+1 ), 1_${ik}$, cone, c( n-p+1 ), 1_${ik}$ ) else nr = p end if if( nr>0_${ik}$ ) then call stdlib${ii}$_${ci}$trmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, & d, 1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( nr, -cone, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ ) end if ! backward transformation x = q**h*x call stdlib${ii}$_${ci}$unmrq( 'LEFT', 'CONJUGATE TRANSPOSE', n, 1_${ik}$, p, b, ldb,work( 1_${ik}$ ), x, n, & work( p+mn+1 ), lwork-p-mn, info ) work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_${ci}$gglse #:endif #:endfor pure module subroutine stdlib${ii}$_sggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info ) !! SGGGLM solves a general Gauss-Markov linear model (GLM) problem: !! minimize || y ||_2 subject to d = A*x + B*y !! x !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a !! given N-vector. It is assumed that M <= N <= M+P, and !! rank(A) = M and rank( A B ) = N. !! Under these assumptions, the constrained equation is always !! consistent, and there is a unique solution x and a minimal 2-norm !! solution y, which is obtained using a generalized QR factorization !! of the matrices (A, B) given by !! A = Q*(R), B = Q*T*Z. !! (0) !! In particular, if matrix B is square nonsingular, then the problem !! GLM is equivalent to the following weighted linear least squares !! problem !! minimize || inv(B)*(d-A*x) ||_2 !! x !! where inv(B) denotes the inverse of B. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*), d(*) real(sp), intent(out) :: work(*), x(*), y(*) ! =================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ np = min( n, p ) lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( m<0_${ik}$ .or. m>n ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. pm ) then call stdlib${ii}$_strtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), & ldb, d( m+1 ), n-m, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if call stdlib${ii}$_scopy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ ) end if ! set y1 = 0 do i = 1, m + p - n y( i ) = zero end do ! update d1 = d1 - t12*y2 call stdlib${ii}$_sgemv( 'NO TRANSPOSE', m, n-m, -one, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$, & one, d, 1_${ik}$ ) ! solve triangular system: r11*x = d1 if( m>0_${ik}$ ) then call stdlib${ii}$_strtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! copy d to x call stdlib${ii}$_scopy( m, d, 1_${ik}$, x, 1_${ik}$ ) end if ! backward transformation y = z**t *y call stdlib${ii}$_sormrq( 'LEFT', 'TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), ldb, work( & m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info ) work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_sggglm pure module subroutine stdlib${ii}$_dggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info ) !! DGGGLM solves a general Gauss-Markov linear model (GLM) problem: !! minimize || y ||_2 subject to d = A*x + B*y !! x !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a !! given N-vector. It is assumed that M <= N <= M+P, and !! rank(A) = M and rank( A B ) = N. !! Under these assumptions, the constrained equation is always !! consistent, and there is a unique solution x and a minimal 2-norm !! solution y, which is obtained using a generalized QR factorization !! of the matrices (A, B) given by !! A = Q*(R), B = Q*T*Z. !! (0) !! In particular, if matrix B is square nonsingular, then the problem !! GLM is equivalent to the following weighted linear least squares !! problem !! minimize || inv(B)*(d-A*x) ||_2 !! x !! where inv(B) denotes the inverse of B. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*), d(*) real(dp), intent(out) :: work(*), x(*), y(*) ! =================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ np = min( n, p ) lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( m<0_${ik}$ .or. m>n ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. pm ) then call stdlib${ii}$_dtrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), & ldb, d( m+1 ), n-m, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if call stdlib${ii}$_dcopy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ ) end if ! set y1 = 0 do i = 1, m + p - n y( i ) = zero end do ! update d1 = d1 - t12*y2 call stdlib${ii}$_dgemv( 'NO TRANSPOSE', m, n-m, -one, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$, & one, d, 1_${ik}$ ) ! solve triangular system: r11*x = d1 if( m>0_${ik}$ ) then call stdlib${ii}$_dtrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! copy d to x call stdlib${ii}$_dcopy( m, d, 1_${ik}$, x, 1_${ik}$ ) end if ! backward transformation y = z**t *y call stdlib${ii}$_dormrq( 'LEFT', 'TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), ldb, work( & m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info ) work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_dggglm #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info ) !! DGGGLM: solves a general Gauss-Markov linear model (GLM) problem: !! minimize || y ||_2 subject to d = A*x + B*y !! x !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a !! given N-vector. It is assumed that M <= N <= M+P, and !! rank(A) = M and rank( A B ) = N. !! Under these assumptions, the constrained equation is always !! consistent, and there is a unique solution x and a minimal 2-norm !! solution y, which is obtained using a generalized QR factorization !! of the matrices (A, B) given by !! A = Q*(R), B = Q*T*Z. !! (0) !! In particular, if matrix B is square nonsingular, then the problem !! GLM is equivalent to the following weighted linear least squares !! problem !! minimize || inv(B)*(d-A*x) ||_2 !! x !! where inv(B) denotes the inverse of B. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*), d(*) real(${rk}$), intent(out) :: work(*), x(*), y(*) ! =================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ np = min( n, p ) lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( m<0_${ik}$ .or. m>n ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. pm ) then call stdlib${ii}$_${ri}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), & ldb, d( m+1 ), n-m, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if call stdlib${ii}$_${ri}$copy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ ) end if ! set y1 = 0 do i = 1, m + p - n y( i ) = zero end do ! update d1 = d1 - t12*y2 call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', m, n-m, -one, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$, & one, d, 1_${ik}$ ) ! solve triangular system: r11*x = d1 if( m>0_${ik}$ ) then call stdlib${ii}$_${ri}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! copy d to x call stdlib${ii}$_${ri}$copy( m, d, 1_${ik}$, x, 1_${ik}$ ) end if ! backward transformation y = z**t *y call stdlib${ii}$_${ri}$ormrq( 'LEFT', 'TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), ldb, work( & m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info ) work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_${ri}$ggglm #:endif #:endfor pure module subroutine stdlib${ii}$_cggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info ) !! CGGGLM solves a general Gauss-Markov linear model (GLM) problem: !! minimize || y ||_2 subject to d = A*x + B*y !! x !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a !! given N-vector. It is assumed that M <= N <= M+P, and !! rank(A) = M and rank( A B ) = N. !! Under these assumptions, the constrained equation is always !! consistent, and there is a unique solution x and a minimal 2-norm !! solution y, which is obtained using a generalized QR factorization !! of the matrices (A, B) given by !! A = Q*(R), B = Q*T*Z. !! (0) !! In particular, if matrix B is square nonsingular, then the problem !! GLM is equivalent to the following weighted linear least squares !! problem !! minimize || inv(B)*(d-A*x) ||_2 !! x !! where inv(B) denotes the inverse of B. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments complex(sp), intent(inout) :: a(lda,*), b(ldb,*), d(*) complex(sp), intent(out) :: work(*), x(*), y(*) ! =================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ np = min( n, p ) lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( m<0_${ik}$ .or. m>n ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. pm ) then call stdlib${ii}$_ctrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), & ldb, d( m+1 ), n-m, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if call stdlib${ii}$_ccopy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ ) end if ! set y1 = 0 do i = 1, m + p - n y( i ) = czero end do ! update d1 = d1 - t12*y2 call stdlib${ii}$_cgemv( 'NO TRANSPOSE', m, n-m, -cone, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$,& cone, d, 1_${ik}$ ) ! solve triangular system: r11*x = d1 if( m>0_${ik}$ ) then call stdlib${ii}$_ctrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! copy d to x call stdlib${ii}$_ccopy( m, d, 1_${ik}$, x, 1_${ik}$ ) end if ! backward transformation y = z**h *y call stdlib${ii}$_cunmrq( 'LEFT', 'CONJUGATE TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), & ldb, work( m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info ) work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_cggglm pure module subroutine stdlib${ii}$_zggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info ) !! ZGGGLM solves a general Gauss-Markov linear model (GLM) problem: !! minimize || y ||_2 subject to d = A*x + B*y !! x !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a !! given N-vector. It is assumed that M <= N <= M+P, and !! rank(A) = M and rank( A B ) = N. !! Under these assumptions, the constrained equation is always !! consistent, and there is a unique solution x and a minimal 2-norm !! solution y, which is obtained using a generalized QR factorization !! of the matrices (A, B) given by !! A = Q*(R), B = Q*T*Z. !! (0) !! In particular, if matrix B is square nonsingular, then the problem !! GLM is equivalent to the following weighted linear least squares !! problem !! minimize || inv(B)*(d-A*x) ||_2 !! x !! where inv(B) denotes the inverse of B. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments complex(dp), intent(inout) :: a(lda,*), b(ldb,*), d(*) complex(dp), intent(out) :: work(*), x(*), y(*) ! =================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ np = min( n, p ) lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( m<0_${ik}$ .or. m>n ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. pm ) then call stdlib${ii}$_ztrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), & ldb, d( m+1 ), n-m, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if call stdlib${ii}$_zcopy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ ) end if ! set y1 = 0 do i = 1, m + p - n y( i ) = czero end do ! update d1 = d1 - t12*y2 call stdlib${ii}$_zgemv( 'NO TRANSPOSE', m, n-m, -cone, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$,& cone, d, 1_${ik}$ ) ! solve triangular system: r11*x = d1 if( m>0_${ik}$ ) then call stdlib${ii}$_ztrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! copy d to x call stdlib${ii}$_zcopy( m, d, 1_${ik}$, x, 1_${ik}$ ) end if ! backward transformation y = z**h *y call stdlib${ii}$_zunmrq( 'LEFT', 'CONJUGATE TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), & ldb, work( m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info ) work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_zggglm #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info ) !! ZGGGLM: solves a general Gauss-Markov linear model (GLM) problem: !! minimize || y ||_2 subject to d = A*x + B*y !! x !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a !! given N-vector. It is assumed that M <= N <= M+P, and !! rank(A) = M and rank( A B ) = N. !! Under these assumptions, the constrained equation is always !! consistent, and there is a unique solution x and a minimal 2-norm !! solution y, which is obtained using a generalized QR factorization !! of the matrices (A, B) given by !! A = Q*(R), B = Q*T*Z. !! (0) !! In particular, if matrix B is square nonsingular, then the problem !! GLM is equivalent to the following weighted linear least squares !! problem !! minimize || inv(B)*(d-A*x) ||_2 !! x !! where inv(B) denotes the inverse of B. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*), d(*) complex(${ck}$), intent(out) :: work(*), x(*), y(*) ! =================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ np = min( n, p ) lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -1_${ik}$ else if( m<0_${ik}$ .or. m>n ) then info = -2_${ik}$ else if( p<0_${ik}$ .or. pm ) then call stdlib${ii}$_${ci}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), & ldb, d( m+1 ), n-m, info ) if( info>0_${ik}$ ) then info = 1_${ik}$ return end if call stdlib${ii}$_${ci}$copy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ ) end if ! set y1 = 0 do i = 1, m + p - n y( i ) = czero end do ! update d1 = d1 - t12*y2 call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', m, n-m, -cone, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$,& cone, d, 1_${ik}$ ) ! solve triangular system: r11*x = d1 if( m>0_${ik}$ ) then call stdlib${ii}$_${ci}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info ) if( info>0_${ik}$ ) then info = 2_${ik}$ return end if ! copy d to x call stdlib${ii}$_${ci}$copy( m, d, 1_${ik}$, x, 1_${ik}$ ) end if ! backward transformation y = z**h *y call stdlib${ii}$_${ci}$unmrq( 'LEFT', 'CONJUGATE TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), & ldb, work( m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info ) work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) ) return end subroutine stdlib${ii}$_${ci}$ggglm #:endif #:endfor #:endfor end submodule stdlib_lapack_lsq_constrained fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_cosine_sine.fypp0000664000175000017500000161602015135654166026270 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_cosine_sine implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, phi, u1, & !! SBBCSD computes the CS decomposition of an orthogonal matrix in !! bidiagonal-block form, !! [ B11 | B12 0 0 ] !! [ 0 | 0 -I 0 ] !! X = [----------------] !! [ B21 | B22 0 0 ] !! [ 0 | 0 0 I ] !! [ C | -S 0 0 ] !! [ U1 | ] [ 0 | 0 -I 0 ] [ V1 | ]**T !! = [---------] [---------------] [---------] . !! [ | U2 ] [ S | C 0 0 ] [ | V2 ] !! [ 0 | 0 0 I ] !! X is M-by-M, its top-left block is P-by-Q, and Q must be no larger !! than P, M-P, or M-Q. (If Q is not the smallest index, then X must be !! transposed and/or permuted. This can be done in constant time using !! the TRANS and SIGNS options. See SORCSD for details.) !! The bidiagonal matrices B11, B12, B21, and B22 are represented !! implicitly by angles THETA(1:Q) and PHI(1:Q-1). !! The orthogonal matrices U1, U2, V1T, and V2T are input/output. !! The input matrices are pre- or post-multiplied by the appropriate !! singular vector matrices. ldu1, u2, ldu2, v1t, ldv1t,v2t, ldv2t, b11d, b11e, b12d, b12e, b21d, b21e,b22d, b22e, work, & lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, one, ten, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, lwork, m, p, q ! Array Arguments real(sp), intent(out) :: b11d(*), b11e(*), b12d(*), b12e(*), b21d(*), b21e(*), b22d(*),& b22e(*), work(*) real(sp), intent(inout) :: phi(*), theta(*) real(sp), intent(inout) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*) ! =================================================================== ! Parameters integer(${ik}$), parameter :: maxitr = 6_${ik}$ real(sp), parameter :: hundred = 100.0_sp real(sp), parameter :: meighth = -0.125_sp real(sp), parameter :: piover2 = 1.57079632679489661923132169163975144210_sp ! Local Scalars logical(lk) :: colmajor, lquery, restart11, restart12, restart21, restart22, wantu1, & wantu2, wantv1t, wantv2t integer(${ik}$) :: i, imin, imax, iter, iu1cs, iu1sn, iu2cs, iu2sn, iv1tcs, iv1tsn, & iv2tcs, iv2tsn, j, lworkmin, lworkopt, maxit, mini real(sp) :: b11bulge, b12bulge, b21bulge, b22bulge, dummy, eps, mu, nu, r, sigma11, & sigma21, temp, thetamax, thetamin, thresh, tol, tolmul, unfl, x1, x2, y1, y2 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) if( m < 0_${ik}$ ) then info = -6_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -7_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -8_${ik}$ else if( q > p .or. q > m-p .or. q > m-q ) then info = -8_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -12_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -14_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -16_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -18_${ik}$ end if ! quick return if q = 0 if( info == 0_${ik}$ .and. q == 0_${ik}$ ) then lworkmin = 1_${ik}$ work(1_${ik}$) = lworkmin return end if ! compute workspace if( info == 0_${ik}$ ) then iu1cs = 1_${ik}$ iu1sn = iu1cs + q iu2cs = iu1sn + q iu2sn = iu2cs + q iv1tcs = iu2sn + q iv1tsn = iv1tcs + q iv2tcs = iv1tsn + q iv2tsn = iv2tcs + q lworkopt = iv2tsn + q - 1_${ik}$ lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not. lquery ) then info = -28_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SBBCSD', -info ) return else if( lquery ) then return end if ! get machine constants eps = stdlib${ii}$_slamch( 'EPSILON' ) unfl = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) tolmul = max( ten, min( hundred, eps**meighth ) ) tol = tolmul*eps thresh = max( tol, maxitr*q*q*unfl ) ! test for negligible sines or cosines do i = 1, q if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = 1, q-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! initial deflation imax = q do while( imax > 1 ) if( phi(imax-1) /= zero ) then exit end if imax = imax - 1_${ik}$ end do imin = imax - 1_${ik}$ if ( imin > 1_${ik}$ ) then do while( phi(imin-1) /= zero ) imin = imin - 1_${ik}$ if ( imin <= 1 ) exit end do end if ! initialize iteration counter maxit = maxitr*q*q iter = 0_${ik}$ ! begin main iteration loop do while( imax > 1 ) ! compute the matrix entries b11d(imin) = cos( theta(imin) ) b21d(imin) = -sin( theta(imin) ) do i = imin, imax - 1 b11e(i) = -sin( theta(i) ) * sin( phi(i) ) b11d(i+1) = cos( theta(i+1) ) * cos( phi(i) ) b12d(i) = sin( theta(i) ) * cos( phi(i) ) b12e(i) = cos( theta(i+1) ) * sin( phi(i) ) b21e(i) = -cos( theta(i) ) * sin( phi(i) ) b21d(i+1) = -sin( theta(i+1) ) * cos( phi(i) ) b22d(i) = cos( theta(i) ) * cos( phi(i) ) b22e(i) = -sin( theta(i+1) ) * sin( phi(i) ) end do b12d(imax) = sin( theta(imax) ) b22d(imax) = cos( theta(imax) ) ! abort if not converging; otherwise, increment iter if( iter > maxit ) then info = 0_${ik}$ do i = 1, q if( phi(i) /= zero )info = info + 1_${ik}$ end do return end if iter = iter + imax - imin ! compute shifts thetamax = theta(imin) thetamin = theta(imin) do i = imin+1, imax if( theta(i) > thetamax )thetamax = theta(i) if( theta(i) < thetamin )thetamin = theta(i) end do if( thetamax > piover2 - thresh ) then ! zero on diagonals of b11 and b22; induce deflation with a ! zero shift mu = zero nu = one else if( thetamin < thresh ) then ! zero on diagonals of b12 and b22; induce deflation with a ! zero shift mu = one nu = zero else ! compute shifts for b11 and b21 and use the lesser call stdlib${ii}$_slas2( b11d(imax-1), b11e(imax-1), b11d(imax), sigma11,dummy ) call stdlib${ii}$_slas2( b21d(imax-1), b21e(imax-1), b21d(imax), sigma21,dummy ) if( sigma11 <= sigma21 ) then mu = sigma11 nu = sqrt( one - mu**2_${ik}$ ) if( mu < thresh ) then mu = zero nu = one end if else nu = sigma21 mu = sqrt( one - nu**2_${ik}$ ) if( nu < thresh ) then mu = one nu = zero end if end if end if ! rotate to produce bulges in b11 and b21 if( mu <= nu ) then call stdlib${ii}$_slartgs( b11d(imin), b11e(imin), mu,work(iv1tcs+imin-1), work(iv1tsn+& imin-1) ) else call stdlib${ii}$_slartgs( b21d(imin), b21e(imin), nu,work(iv1tcs+imin-1), work(iv1tsn+& imin-1) ) end if temp = work(iv1tcs+imin-1)*b11d(imin) +work(iv1tsn+imin-1)*b11e(imin) b11e(imin) = work(iv1tcs+imin-1)*b11e(imin) -work(iv1tsn+imin-1)*b11d(imin) b11d(imin) = temp b11bulge = work(iv1tsn+imin-1)*b11d(imin+1) b11d(imin+1) = work(iv1tcs+imin-1)*b11d(imin+1) temp = work(iv1tcs+imin-1)*b21d(imin) +work(iv1tsn+imin-1)*b21e(imin) b21e(imin) = work(iv1tcs+imin-1)*b21e(imin) -work(iv1tsn+imin-1)*b21d(imin) b21d(imin) = temp b21bulge = work(iv1tsn+imin-1)*b21d(imin+1) b21d(imin+1) = work(iv1tcs+imin-1)*b21d(imin+1) ! compute theta(imin) theta( imin ) = atan2( sqrt( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ ),sqrt( b11d(imin)**2_${ik}$+& b11bulge**2_${ik}$ ) ) ! chase the bulges in b11(imin+1,imin) and b21(imin+1,imin) if( b11d(imin)**2_${ik}$+b11bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_slartgp( b11bulge, b11d(imin), work(iu1sn+imin-1),work(iu1cs+imin-1),& r ) else if( mu <= nu ) then call stdlib${ii}$_slartgs( b11e( imin ), b11d( imin + 1_${ik}$ ), mu,work(iu1cs+imin-1), work(& iu1sn+imin-1) ) else call stdlib${ii}$_slartgs( b12d( imin ), b12e( imin ), nu,work(iu1cs+imin-1), work(& iu1sn+imin-1) ) end if if( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_slartgp( b21bulge, b21d(imin), work(iu2sn+imin-1),work(iu2cs+imin-1),& r ) else if( nu < mu ) then call stdlib${ii}$_slartgs( b21e( imin ), b21d( imin + 1_${ik}$ ), nu,work(iu2cs+imin-1), work(& iu2sn+imin-1) ) else call stdlib${ii}$_slartgs( b22d(imin), b22e(imin), mu,work(iu2cs+imin-1), work(iu2sn+& imin-1) ) end if work(iu2cs+imin-1) = -work(iu2cs+imin-1) work(iu2sn+imin-1) = -work(iu2sn+imin-1) temp = work(iu1cs+imin-1)*b11e(imin) +work(iu1sn+imin-1)*b11d(imin+1) b11d(imin+1) = work(iu1cs+imin-1)*b11d(imin+1) -work(iu1sn+imin-1)*b11e(imin) b11e(imin) = temp if( imax > imin+1 ) then b11bulge = work(iu1sn+imin-1)*b11e(imin+1) b11e(imin+1) = work(iu1cs+imin-1)*b11e(imin+1) end if temp = work(iu1cs+imin-1)*b12d(imin) +work(iu1sn+imin-1)*b12e(imin) b12e(imin) = work(iu1cs+imin-1)*b12e(imin) -work(iu1sn+imin-1)*b12d(imin) b12d(imin) = temp b12bulge = work(iu1sn+imin-1)*b12d(imin+1) b12d(imin+1) = work(iu1cs+imin-1)*b12d(imin+1) temp = work(iu2cs+imin-1)*b21e(imin) +work(iu2sn+imin-1)*b21d(imin+1) b21d(imin+1) = work(iu2cs+imin-1)*b21d(imin+1) -work(iu2sn+imin-1)*b21e(imin) b21e(imin) = temp if( imax > imin+1 ) then b21bulge = work(iu2sn+imin-1)*b21e(imin+1) b21e(imin+1) = work(iu2cs+imin-1)*b21e(imin+1) end if temp = work(iu2cs+imin-1)*b22d(imin) +work(iu2sn+imin-1)*b22e(imin) b22e(imin) = work(iu2cs+imin-1)*b22e(imin) -work(iu2sn+imin-1)*b22d(imin) b22d(imin) = temp b22bulge = work(iu2sn+imin-1)*b22d(imin+1) b22d(imin+1) = work(iu2cs+imin-1)*b22d(imin+1) ! inner loop: chase bulges from b11(imin,imin+2), ! b12(imin,imin+1), b21(imin,imin+2), and b22(imin,imin+1) to ! bottom-right do i = imin+1, imax-1 ! compute phi(i-1) x1 = sin(theta(i-1))*b11e(i-1) + cos(theta(i-1))*b21e(i-1) x2 = sin(theta(i-1))*b11bulge + cos(theta(i-1))*b21bulge y1 = sin(theta(i-1))*b12d(i-1) + cos(theta(i-1))*b22d(i-1) y2 = sin(theta(i-1))*b12bulge + cos(theta(i-1))*b22bulge phi(i-1) = atan2( sqrt(x1**2_${ik}$+x2**2_${ik}$), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11e(i-1)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21e(i-1)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12d(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i-1,i+1), b12(i-1,i), ! b21(i-1,i+1), and b22(i-1,i). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart21 ) then call stdlib${ii}$_slartgp( x2, x1, work(iv1tsn+i-1), work(iv1tcs+i-1),r ) else if( .not. restart11 .and. restart21 ) then call stdlib${ii}$_slartgp( b11bulge, b11e(i-1), work(iv1tsn+i-1),work(iv1tcs+i-1), & r ) else if( restart11 .and. .not. restart21 ) then call stdlib${ii}$_slartgp( b21bulge, b21e(i-1), work(iv1tsn+i-1),work(iv1tcs+i-1), & r ) else if( mu <= nu ) then call stdlib${ii}$_slartgs( b11d(i), b11e(i), mu, work(iv1tcs+i-1),work(iv1tsn+i-1) ) else call stdlib${ii}$_slartgs( b21d(i), b21e(i), nu, work(iv1tcs+i-1),work(iv1tsn+i-1) ) end if work(iv1tcs+i-1) = -work(iv1tcs+i-1) work(iv1tsn+i-1) = -work(iv1tsn+i-1) if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( y2, y1, work(iv2tsn+i-1-1),work(iv2tcs+i-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_slartgp( b12bulge, b12d(i-1), work(iv2tsn+i-1-1),work(iv2tcs+i-1-& 1_${ik}$), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( b22bulge, b22d(i-1), work(iv2tsn+i-1-1),work(iv2tcs+i-1-& 1_${ik}$), r ) else if( nu < mu ) then call stdlib${ii}$_slartgs( b12e(i-1), b12d(i), nu, work(iv2tcs+i-1-1),work(iv2tsn+i-& 1_${ik}$-1) ) else call stdlib${ii}$_slartgs( b22e(i-1), b22d(i), mu, work(iv2tcs+i-1-1),work(iv2tsn+i-& 1_${ik}$-1) ) end if temp = work(iv1tcs+i-1)*b11d(i) + work(iv1tsn+i-1)*b11e(i) b11e(i) = work(iv1tcs+i-1)*b11e(i) -work(iv1tsn+i-1)*b11d(i) b11d(i) = temp b11bulge = work(iv1tsn+i-1)*b11d(i+1) b11d(i+1) = work(iv1tcs+i-1)*b11d(i+1) temp = work(iv1tcs+i-1)*b21d(i) + work(iv1tsn+i-1)*b21e(i) b21e(i) = work(iv1tcs+i-1)*b21e(i) -work(iv1tsn+i-1)*b21d(i) b21d(i) = temp b21bulge = work(iv1tsn+i-1)*b21d(i+1) b21d(i+1) = work(iv1tcs+i-1)*b21d(i+1) temp = work(iv2tcs+i-1-1)*b12e(i-1) +work(iv2tsn+i-1-1)*b12d(i) b12d(i) = work(iv2tcs+i-1-1)*b12d(i) -work(iv2tsn+i-1-1)*b12e(i-1) b12e(i-1) = temp b12bulge = work(iv2tsn+i-1-1)*b12e(i) b12e(i) = work(iv2tcs+i-1-1)*b12e(i) temp = work(iv2tcs+i-1-1)*b22e(i-1) +work(iv2tsn+i-1-1)*b22d(i) b22d(i) = work(iv2tcs+i-1-1)*b22d(i) -work(iv2tsn+i-1-1)*b22e(i-1) b22e(i-1) = temp b22bulge = work(iv2tsn+i-1-1)*b22e(i) b22e(i) = work(iv2tcs+i-1-1)*b22e(i) ! compute theta(i) x1 = cos(phi(i-1))*b11d(i) + sin(phi(i-1))*b12e(i-1) x2 = cos(phi(i-1))*b11bulge + sin(phi(i-1))*b12bulge y1 = cos(phi(i-1))*b21d(i) + sin(phi(i-1))*b22e(i-1) y2 = cos(phi(i-1))*b21bulge + sin(phi(i-1))*b22bulge theta(i) = atan2( sqrt(y1**2_${ik}$+y2**2_${ik}$), sqrt(x1**2_${ik}$+x2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11d(i)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12e(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21d(i)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22e(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i+1,i), b12(i+1,i-1), ! b21(i+1,i), and b22(i+1,i-1). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart12 ) then call stdlib${ii}$_slartgp( x2, x1, work(iu1sn+i-1), work(iu1cs+i-1),r ) else if( .not. restart11 .and. restart12 ) then call stdlib${ii}$_slartgp( b11bulge, b11d(i), work(iu1sn+i-1),work(iu1cs+i-1), r ) else if( restart11 .and. .not. restart12 ) then call stdlib${ii}$_slartgp( b12bulge, b12e(i-1), work(iu1sn+i-1),work(iu1cs+i-1), r ) else if( mu <= nu ) then call stdlib${ii}$_slartgs( b11e(i), b11d(i+1), mu, work(iu1cs+i-1),work(iu1sn+i-1) ) else call stdlib${ii}$_slartgs( b12d(i), b12e(i), nu, work(iu1cs+i-1),work(iu1sn+i-1) ) end if if( .not. restart21 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( y2, y1, work(iu2sn+i-1), work(iu2cs+i-1),r ) else if( .not. restart21 .and. restart22 ) then call stdlib${ii}$_slartgp( b21bulge, b21d(i), work(iu2sn+i-1),work(iu2cs+i-1), r ) else if( restart21 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( b22bulge, b22e(i-1), work(iu2sn+i-1),work(iu2cs+i-1), r ) else if( nu < mu ) then call stdlib${ii}$_slartgs( b21e(i), b21e(i+1), nu, work(iu2cs+i-1),work(iu2sn+i-1) ) else call stdlib${ii}$_slartgs( b22d(i), b22e(i), mu, work(iu2cs+i-1),work(iu2sn+i-1) ) end if work(iu2cs+i-1) = -work(iu2cs+i-1) work(iu2sn+i-1) = -work(iu2sn+i-1) temp = work(iu1cs+i-1)*b11e(i) + work(iu1sn+i-1)*b11d(i+1) b11d(i+1) = work(iu1cs+i-1)*b11d(i+1) -work(iu1sn+i-1)*b11e(i) b11e(i) = temp if( i < imax - 1_${ik}$ ) then b11bulge = work(iu1sn+i-1)*b11e(i+1) b11e(i+1) = work(iu1cs+i-1)*b11e(i+1) end if temp = work(iu2cs+i-1)*b21e(i) + work(iu2sn+i-1)*b21d(i+1) b21d(i+1) = work(iu2cs+i-1)*b21d(i+1) -work(iu2sn+i-1)*b21e(i) b21e(i) = temp if( i < imax - 1_${ik}$ ) then b21bulge = work(iu2sn+i-1)*b21e(i+1) b21e(i+1) = work(iu2cs+i-1)*b21e(i+1) end if temp = work(iu1cs+i-1)*b12d(i) + work(iu1sn+i-1)*b12e(i) b12e(i) = work(iu1cs+i-1)*b12e(i) - work(iu1sn+i-1)*b12d(i) b12d(i) = temp b12bulge = work(iu1sn+i-1)*b12d(i+1) b12d(i+1) = work(iu1cs+i-1)*b12d(i+1) temp = work(iu2cs+i-1)*b22d(i) + work(iu2sn+i-1)*b22e(i) b22e(i) = work(iu2cs+i-1)*b22e(i) - work(iu2sn+i-1)*b22d(i) b22d(i) = temp b22bulge = work(iu2sn+i-1)*b22d(i+1) b22d(i+1) = work(iu2cs+i-1)*b22d(i+1) end do ! compute phi(imax-1) x1 = sin(theta(imax-1))*b11e(imax-1) +cos(theta(imax-1))*b21e(imax-1) y1 = sin(theta(imax-1))*b12d(imax-1) +cos(theta(imax-1))*b22d(imax-1) y2 = sin(theta(imax-1))*b12bulge + cos(theta(imax-1))*b22bulge phi(imax-1) = atan2( abs(x1), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! chase bulges from b12(imax-1,imax) and b22(imax-1,imax) restart12 = b12d(imax-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(imax-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( y2, y1, work(iv2tsn+imax-1-1),work(iv2tcs+imax-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_slartgp( b12bulge, b12d(imax-1), work(iv2tsn+imax-1-1),work(iv2tcs+& imax-1-1), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( b22bulge, b22d(imax-1), work(iv2tsn+imax-1-1),work(iv2tcs+& imax-1-1), r ) else if( nu < mu ) then call stdlib${ii}$_slartgs( b12e(imax-1), b12d(imax), nu,work(iv2tcs+imax-1-1), work(& iv2tsn+imax-1-1) ) else call stdlib${ii}$_slartgs( b22e(imax-1), b22d(imax), mu,work(iv2tcs+imax-1-1), work(& iv2tsn+imax-1-1) ) end if temp = work(iv2tcs+imax-1-1)*b12e(imax-1) +work(iv2tsn+imax-1-1)*b12d(imax) b12d(imax) = work(iv2tcs+imax-1-1)*b12d(imax) -work(iv2tsn+imax-1-1)*b12e(imax-1) b12e(imax-1) = temp temp = work(iv2tcs+imax-1-1)*b22e(imax-1) +work(iv2tsn+imax-1-1)*b22d(imax) b22d(imax) = work(iv2tcs+imax-1-1)*b22d(imax) -work(iv2tsn+imax-1-1)*b22e(imax-1) b22e(imax-1) = temp ! update singular vectors if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_slasr( 'R', 'V', 'F', p, imax-imin+1,work(iu1cs+imin-1), work(& iu1sn+imin-1),u1(1_${ik}$,imin), ldu1 ) else call stdlib${ii}$_slasr( 'L', 'V', 'F', imax-imin+1, p,work(iu1cs+imin-1), work(& iu1sn+imin-1),u1(imin,1_${ik}$), ldu1 ) end if end if if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_slasr( 'R', 'V', 'F', m-p, imax-imin+1,work(iu2cs+imin-1), work(& iu2sn+imin-1),u2(1_${ik}$,imin), ldu2 ) else call stdlib${ii}$_slasr( 'L', 'V', 'F', imax-imin+1, m-p,work(iu2cs+imin-1), work(& iu2sn+imin-1),u2(imin,1_${ik}$), ldu2 ) end if end if if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_slasr( 'L', 'V', 'F', imax-imin+1, q,work(iv1tcs+imin-1), work(& iv1tsn+imin-1),v1t(imin,1_${ik}$), ldv1t ) else call stdlib${ii}$_slasr( 'R', 'V', 'F', q, imax-imin+1,work(iv1tcs+imin-1), work(& iv1tsn+imin-1),v1t(1_${ik}$,imin), ldv1t ) end if end if if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_slasr( 'L', 'V', 'F', imax-imin+1, m-q,work(iv2tcs+imin-1), work(& iv2tsn+imin-1),v2t(imin,1_${ik}$), ldv2t ) else call stdlib${ii}$_slasr( 'R', 'V', 'F', m-q, imax-imin+1,work(iv2tcs+imin-1), work(& iv2tsn+imin-1),v2t(1_${ik}$,imin), ldv2t ) end if end if ! fix signs on b11(imax-1,imax) and b21(imax-1,imax) if( b11e(imax-1)+b21e(imax-1) > 0_${ik}$ ) then b11d(imax) = -b11d(imax) b21d(imax) = -b21d(imax) if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_sscal( q, negone, v1t(imax,1_${ik}$), ldv1t ) else call stdlib${ii}$_sscal( q, negone, v1t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! compute theta(imax) x1 = cos(phi(imax-1))*b11d(imax) +sin(phi(imax-1))*b12e(imax-1) y1 = cos(phi(imax-1))*b21d(imax) +sin(phi(imax-1))*b22e(imax-1) theta(imax) = atan2( abs(y1), abs(x1) ) ! fix signs on b11(imax,imax), b12(imax,imax-1), b21(imax,imax), ! and b22(imax,imax-1) if( b11d(imax)+b12e(imax-1) < 0_${ik}$ ) then b12d(imax) = -b12d(imax) if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_sscal( p, negone, u1(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_sscal( p, negone, u1(imax,1_${ik}$), ldu1 ) end if end if end if if( b21d(imax)+b22e(imax-1) > 0_${ik}$ ) then b22d(imax) = -b22d(imax) if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_sscal( m-p, negone, u2(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_sscal( m-p, negone, u2(imax,1_${ik}$), ldu2 ) end if end if end if ! fix signs on b12(imax,imax) and b22(imax,imax) if( b12d(imax)+b22d(imax) < 0_${ik}$ ) then if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_sscal( m-q, negone, v2t(imax,1_${ik}$), ldv2t ) else call stdlib${ii}$_sscal( m-q, negone, v2t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! test for negligible sines or cosines do i = imin, imax if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = imin, imax-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! deflate if (imax > 1_${ik}$) then do while( phi(imax-1) == zero ) imax = imax - 1_${ik}$ if (imax <= 1) exit end do end if if( imin > imax - 1_${ik}$ )imin = imax - 1_${ik}$ if (imin > 1_${ik}$) then do while (phi(imin-1) /= zero) imin = imin - 1_${ik}$ if (imin <= 1) exit end do end if ! repeat main iteration loop end do ! postprocessing: order theta from least to greatest do i = 1, q mini = i thetamin = theta(i) do j = i+1, q if( theta(j) < thetamin ) then mini = j thetamin = theta(j) end if end do if( mini /= i ) then theta(mini) = theta(i) theta(i) = thetamin if( colmajor ) then if( wantu1 )call stdlib${ii}$_sswap( p, u1(1_${ik}$,i), 1_${ik}$, u1(1_${ik}$,mini), 1_${ik}$ ) if( wantu2 )call stdlib${ii}$_sswap( m-p, u2(1_${ik}$,i), 1_${ik}$, u2(1_${ik}$,mini), 1_${ik}$ ) if( wantv1t )call stdlib${ii}$_sswap( q, v1t(i,1_${ik}$), ldv1t, v1t(mini,1_${ik}$), ldv1t ) if( wantv2t )call stdlib${ii}$_sswap( m-q, v2t(i,1_${ik}$), ldv2t, v2t(mini,1_${ik}$),ldv2t ) else if( wantu1 )call stdlib${ii}$_sswap( p, u1(i,1_${ik}$), ldu1, u1(mini,1_${ik}$), ldu1 ) if( wantu2 )call stdlib${ii}$_sswap( m-p, u2(i,1_${ik}$), ldu2, u2(mini,1_${ik}$), ldu2 ) if( wantv1t )call stdlib${ii}$_sswap( q, v1t(1_${ik}$,i), 1_${ik}$, v1t(1_${ik}$,mini), 1_${ik}$ ) if( wantv2t )call stdlib${ii}$_sswap( m-q, v2t(1_${ik}$,i), 1_${ik}$, v2t(1_${ik}$,mini), 1_${ik}$ ) end if end if end do return end subroutine stdlib${ii}$_sbbcsd pure module subroutine stdlib${ii}$_dbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, phi, u1, & !! DBBCSD computes the CS decomposition of an orthogonal matrix in !! bidiagonal-block form, !! [ B11 | B12 0 0 ] !! [ 0 | 0 -I 0 ] !! X = [----------------] !! [ B21 | B22 0 0 ] !! [ 0 | 0 0 I ] !! [ C | -S 0 0 ] !! [ U1 | ] [ 0 | 0 -I 0 ] [ V1 | ]**T !! = [---------] [---------------] [---------] . !! [ | U2 ] [ S | C 0 0 ] [ | V2 ] !! [ 0 | 0 0 I ] !! X is M-by-M, its top-left block is P-by-Q, and Q must be no larger !! than P, M-P, or M-Q. (If Q is not the smallest index, then X must be !! transposed and/or permuted. This can be done in constant time using !! the TRANS and SIGNS options. See DORCSD for details.) !! The bidiagonal matrices B11, B12, B21, and B22 are represented !! implicitly by angles THETA(1:Q) and PHI(1:Q-1). !! The orthogonal matrices U1, U2, V1T, and V2T are input/output. !! The input matrices are pre- or post-multiplied by the appropriate !! singular vector matrices. ldu1, u2, ldu2, v1t, ldv1t,v2t, ldv2t, b11d, b11e, b12d, b12e, b21d, b21e,b22d, b22e, work, & lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, one, ten, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, lwork, m, p, q ! Array Arguments real(dp), intent(out) :: b11d(*), b11e(*), b12d(*), b12e(*), b21d(*), b21e(*), b22d(*),& b22e(*), work(*) real(dp), intent(inout) :: phi(*), theta(*) real(dp), intent(inout) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*) ! =================================================================== ! Parameters integer(${ik}$), parameter :: maxitr = 6_${ik}$ real(dp), parameter :: hundred = 100.0_dp real(dp), parameter :: meighth = -0.125_dp real(dp), parameter :: piover2 = 1.57079632679489661923132169163975144210_dp ! Local Scalars logical(lk) :: colmajor, lquery, restart11, restart12, restart21, restart22, wantu1, & wantu2, wantv1t, wantv2t integer(${ik}$) :: i, imin, imax, iter, iu1cs, iu1sn, iu2cs, iu2sn, iv1tcs, iv1tsn, & iv2tcs, iv2tsn, j, lworkmin, lworkopt, maxit, mini real(dp) :: b11bulge, b12bulge, b21bulge, b22bulge, dummy, eps, mu, nu, r, sigma11, & sigma21, temp, thetamax, thetamin, thresh, tol, tolmul, unfl, x1, x2, y1, y2 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) if( m < 0_${ik}$ ) then info = -6_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -7_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -8_${ik}$ else if( q > p .or. q > m-p .or. q > m-q ) then info = -8_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -12_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -14_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -16_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -18_${ik}$ end if ! quick return if q = 0 if( info == 0_${ik}$ .and. q == 0_${ik}$ ) then lworkmin = 1_${ik}$ work(1_${ik}$) = lworkmin return end if ! compute workspace if( info == 0_${ik}$ ) then iu1cs = 1_${ik}$ iu1sn = iu1cs + q iu2cs = iu1sn + q iu2sn = iu2cs + q iv1tcs = iu2sn + q iv1tsn = iv1tcs + q iv2tcs = iv1tsn + q iv2tsn = iv2tcs + q lworkopt = iv2tsn + q - 1_${ik}$ lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not. lquery ) then info = -28_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DBBCSD', -info ) return else if( lquery ) then return end if ! get machine constants eps = stdlib${ii}$_dlamch( 'EPSILON' ) unfl = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) tolmul = max( ten, min( hundred, eps**meighth ) ) tol = tolmul*eps thresh = max( tol, maxitr*q*q*unfl ) ! test for negligible sines or cosines do i = 1, q if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = 1, q-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! initial deflation imax = q do while( imax > 1 ) if( phi(imax-1) /= zero ) then exit end if imax = imax - 1_${ik}$ end do imin = imax - 1_${ik}$ if ( imin > 1_${ik}$ ) then do while( phi(imin-1) /= zero ) imin = imin - 1_${ik}$ if ( imin <= 1 ) exit end do end if ! initialize iteration counter maxit = maxitr*q*q iter = 0_${ik}$ ! begin main iteration loop do while( imax > 1 ) ! compute the matrix entries b11d(imin) = cos( theta(imin) ) b21d(imin) = -sin( theta(imin) ) do i = imin, imax - 1 b11e(i) = -sin( theta(i) ) * sin( phi(i) ) b11d(i+1) = cos( theta(i+1) ) * cos( phi(i) ) b12d(i) = sin( theta(i) ) * cos( phi(i) ) b12e(i) = cos( theta(i+1) ) * sin( phi(i) ) b21e(i) = -cos( theta(i) ) * sin( phi(i) ) b21d(i+1) = -sin( theta(i+1) ) * cos( phi(i) ) b22d(i) = cos( theta(i) ) * cos( phi(i) ) b22e(i) = -sin( theta(i+1) ) * sin( phi(i) ) end do b12d(imax) = sin( theta(imax) ) b22d(imax) = cos( theta(imax) ) ! abort if not converging; otherwise, increment iter if( iter > maxit ) then info = 0_${ik}$ do i = 1, q if( phi(i) /= zero )info = info + 1_${ik}$ end do return end if iter = iter + imax - imin ! compute shifts thetamax = theta(imin) thetamin = theta(imin) do i = imin+1, imax if( theta(i) > thetamax )thetamax = theta(i) if( theta(i) < thetamin )thetamin = theta(i) end do if( thetamax > piover2 - thresh ) then ! zero on diagonals of b11 and b22; induce deflation with a ! zero shift mu = zero nu = one else if( thetamin < thresh ) then ! zero on diagonals of b12 and b22; induce deflation with a ! zero shift mu = one nu = zero else ! compute shifts for b11 and b21 and use the lesser call stdlib${ii}$_dlas2( b11d(imax-1), b11e(imax-1), b11d(imax), sigma11,dummy ) call stdlib${ii}$_dlas2( b21d(imax-1), b21e(imax-1), b21d(imax), sigma21,dummy ) if( sigma11 <= sigma21 ) then mu = sigma11 nu = sqrt( one - mu**2_${ik}$ ) if( mu < thresh ) then mu = zero nu = one end if else nu = sigma21 mu = sqrt( one - nu**2_${ik}$ ) if( nu < thresh ) then mu = one nu = zero end if end if end if ! rotate to produce bulges in b11 and b21 if( mu <= nu ) then call stdlib${ii}$_dlartgs( b11d(imin), b11e(imin), mu,work(iv1tcs+imin-1), work(iv1tsn+& imin-1) ) else call stdlib${ii}$_dlartgs( b21d(imin), b21e(imin), nu,work(iv1tcs+imin-1), work(iv1tsn+& imin-1) ) end if temp = work(iv1tcs+imin-1)*b11d(imin) +work(iv1tsn+imin-1)*b11e(imin) b11e(imin) = work(iv1tcs+imin-1)*b11e(imin) -work(iv1tsn+imin-1)*b11d(imin) b11d(imin) = temp b11bulge = work(iv1tsn+imin-1)*b11d(imin+1) b11d(imin+1) = work(iv1tcs+imin-1)*b11d(imin+1) temp = work(iv1tcs+imin-1)*b21d(imin) +work(iv1tsn+imin-1)*b21e(imin) b21e(imin) = work(iv1tcs+imin-1)*b21e(imin) -work(iv1tsn+imin-1)*b21d(imin) b21d(imin) = temp b21bulge = work(iv1tsn+imin-1)*b21d(imin+1) b21d(imin+1) = work(iv1tcs+imin-1)*b21d(imin+1) ! compute theta(imin) theta( imin ) = atan2( sqrt( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ ),sqrt( b11d(imin)**2_${ik}$+& b11bulge**2_${ik}$ ) ) ! chase the bulges in b11(imin+1,imin) and b21(imin+1,imin) if( b11d(imin)**2_${ik}$+b11bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_dlartgp( b11bulge, b11d(imin), work(iu1sn+imin-1),work(iu1cs+imin-1),& r ) else if( mu <= nu ) then call stdlib${ii}$_dlartgs( b11e( imin ), b11d( imin + 1_${ik}$ ), mu,work(iu1cs+imin-1), work(& iu1sn+imin-1) ) else call stdlib${ii}$_dlartgs( b12d( imin ), b12e( imin ), nu,work(iu1cs+imin-1), work(& iu1sn+imin-1) ) end if if( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_dlartgp( b21bulge, b21d(imin), work(iu2sn+imin-1),work(iu2cs+imin-1),& r ) else if( nu < mu ) then call stdlib${ii}$_dlartgs( b21e( imin ), b21d( imin + 1_${ik}$ ), nu,work(iu2cs+imin-1), work(& iu2sn+imin-1) ) else call stdlib${ii}$_dlartgs( b22d(imin), b22e(imin), mu,work(iu2cs+imin-1), work(iu2sn+& imin-1) ) end if work(iu2cs+imin-1) = -work(iu2cs+imin-1) work(iu2sn+imin-1) = -work(iu2sn+imin-1) temp = work(iu1cs+imin-1)*b11e(imin) +work(iu1sn+imin-1)*b11d(imin+1) b11d(imin+1) = work(iu1cs+imin-1)*b11d(imin+1) -work(iu1sn+imin-1)*b11e(imin) b11e(imin) = temp if( imax > imin+1 ) then b11bulge = work(iu1sn+imin-1)*b11e(imin+1) b11e(imin+1) = work(iu1cs+imin-1)*b11e(imin+1) end if temp = work(iu1cs+imin-1)*b12d(imin) +work(iu1sn+imin-1)*b12e(imin) b12e(imin) = work(iu1cs+imin-1)*b12e(imin) -work(iu1sn+imin-1)*b12d(imin) b12d(imin) = temp b12bulge = work(iu1sn+imin-1)*b12d(imin+1) b12d(imin+1) = work(iu1cs+imin-1)*b12d(imin+1) temp = work(iu2cs+imin-1)*b21e(imin) +work(iu2sn+imin-1)*b21d(imin+1) b21d(imin+1) = work(iu2cs+imin-1)*b21d(imin+1) -work(iu2sn+imin-1)*b21e(imin) b21e(imin) = temp if( imax > imin+1 ) then b21bulge = work(iu2sn+imin-1)*b21e(imin+1) b21e(imin+1) = work(iu2cs+imin-1)*b21e(imin+1) end if temp = work(iu2cs+imin-1)*b22d(imin) +work(iu2sn+imin-1)*b22e(imin) b22e(imin) = work(iu2cs+imin-1)*b22e(imin) -work(iu2sn+imin-1)*b22d(imin) b22d(imin) = temp b22bulge = work(iu2sn+imin-1)*b22d(imin+1) b22d(imin+1) = work(iu2cs+imin-1)*b22d(imin+1) ! inner loop: chase bulges from b11(imin,imin+2), ! b12(imin,imin+1), b21(imin,imin+2), and b22(imin,imin+1) to ! bottom-right do i = imin+1, imax-1 ! compute phi(i-1) x1 = sin(theta(i-1))*b11e(i-1) + cos(theta(i-1))*b21e(i-1) x2 = sin(theta(i-1))*b11bulge + cos(theta(i-1))*b21bulge y1 = sin(theta(i-1))*b12d(i-1) + cos(theta(i-1))*b22d(i-1) y2 = sin(theta(i-1))*b12bulge + cos(theta(i-1))*b22bulge phi(i-1) = atan2( sqrt(x1**2_${ik}$+x2**2_${ik}$), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11e(i-1)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21e(i-1)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12d(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i-1,i+1), b12(i-1,i), ! b21(i-1,i+1), and b22(i-1,i). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart21 ) then call stdlib${ii}$_dlartgp( x2, x1, work(iv1tsn+i-1), work(iv1tcs+i-1),r ) else if( .not. restart11 .and. restart21 ) then call stdlib${ii}$_dlartgp( b11bulge, b11e(i-1), work(iv1tsn+i-1),work(iv1tcs+i-1), & r ) else if( restart11 .and. .not. restart21 ) then call stdlib${ii}$_dlartgp( b21bulge, b21e(i-1), work(iv1tsn+i-1),work(iv1tcs+i-1), & r ) else if( mu <= nu ) then call stdlib${ii}$_dlartgs( b11d(i), b11e(i), mu, work(iv1tcs+i-1),work(iv1tsn+i-1) ) else call stdlib${ii}$_dlartgs( b21d(i), b21e(i), nu, work(iv1tcs+i-1),work(iv1tsn+i-1) ) end if work(iv1tcs+i-1) = -work(iv1tcs+i-1) work(iv1tsn+i-1) = -work(iv1tsn+i-1) if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( y2, y1, work(iv2tsn+i-1-1),work(iv2tcs+i-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_dlartgp( b12bulge, b12d(i-1), work(iv2tsn+i-1-1),work(iv2tcs+i-1-& 1_${ik}$), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( b22bulge, b22d(i-1), work(iv2tsn+i-1-1),work(iv2tcs+i-1-& 1_${ik}$), r ) else if( nu < mu ) then call stdlib${ii}$_dlartgs( b12e(i-1), b12d(i), nu, work(iv2tcs+i-1-1),work(iv2tsn+i-& 1_${ik}$-1) ) else call stdlib${ii}$_dlartgs( b22e(i-1), b22d(i), mu, work(iv2tcs+i-1-1),work(iv2tsn+i-& 1_${ik}$-1) ) end if temp = work(iv1tcs+i-1)*b11d(i) + work(iv1tsn+i-1)*b11e(i) b11e(i) = work(iv1tcs+i-1)*b11e(i) -work(iv1tsn+i-1)*b11d(i) b11d(i) = temp b11bulge = work(iv1tsn+i-1)*b11d(i+1) b11d(i+1) = work(iv1tcs+i-1)*b11d(i+1) temp = work(iv1tcs+i-1)*b21d(i) + work(iv1tsn+i-1)*b21e(i) b21e(i) = work(iv1tcs+i-1)*b21e(i) -work(iv1tsn+i-1)*b21d(i) b21d(i) = temp b21bulge = work(iv1tsn+i-1)*b21d(i+1) b21d(i+1) = work(iv1tcs+i-1)*b21d(i+1) temp = work(iv2tcs+i-1-1)*b12e(i-1) +work(iv2tsn+i-1-1)*b12d(i) b12d(i) = work(iv2tcs+i-1-1)*b12d(i) -work(iv2tsn+i-1-1)*b12e(i-1) b12e(i-1) = temp b12bulge = work(iv2tsn+i-1-1)*b12e(i) b12e(i) = work(iv2tcs+i-1-1)*b12e(i) temp = work(iv2tcs+i-1-1)*b22e(i-1) +work(iv2tsn+i-1-1)*b22d(i) b22d(i) = work(iv2tcs+i-1-1)*b22d(i) -work(iv2tsn+i-1-1)*b22e(i-1) b22e(i-1) = temp b22bulge = work(iv2tsn+i-1-1)*b22e(i) b22e(i) = work(iv2tcs+i-1-1)*b22e(i) ! compute theta(i) x1 = cos(phi(i-1))*b11d(i) + sin(phi(i-1))*b12e(i-1) x2 = cos(phi(i-1))*b11bulge + sin(phi(i-1))*b12bulge y1 = cos(phi(i-1))*b21d(i) + sin(phi(i-1))*b22e(i-1) y2 = cos(phi(i-1))*b21bulge + sin(phi(i-1))*b22bulge theta(i) = atan2( sqrt(y1**2_${ik}$+y2**2_${ik}$), sqrt(x1**2_${ik}$+x2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11d(i)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12e(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21d(i)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22e(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i+1,i), b12(i+1,i-1), ! b21(i+1,i), and b22(i+1,i-1). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart12 ) then call stdlib${ii}$_dlartgp( x2, x1, work(iu1sn+i-1), work(iu1cs+i-1),r ) else if( .not. restart11 .and. restart12 ) then call stdlib${ii}$_dlartgp( b11bulge, b11d(i), work(iu1sn+i-1),work(iu1cs+i-1), r ) else if( restart11 .and. .not. restart12 ) then call stdlib${ii}$_dlartgp( b12bulge, b12e(i-1), work(iu1sn+i-1),work(iu1cs+i-1), r ) else if( mu <= nu ) then call stdlib${ii}$_dlartgs( b11e(i), b11d(i+1), mu, work(iu1cs+i-1),work(iu1sn+i-1) ) else call stdlib${ii}$_dlartgs( b12d(i), b12e(i), nu, work(iu1cs+i-1),work(iu1sn+i-1) ) end if if( .not. restart21 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( y2, y1, work(iu2sn+i-1), work(iu2cs+i-1),r ) else if( .not. restart21 .and. restart22 ) then call stdlib${ii}$_dlartgp( b21bulge, b21d(i), work(iu2sn+i-1),work(iu2cs+i-1), r ) else if( restart21 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( b22bulge, b22e(i-1), work(iu2sn+i-1),work(iu2cs+i-1), r ) else if( nu < mu ) then call stdlib${ii}$_dlartgs( b21e(i), b21e(i+1), nu, work(iu2cs+i-1),work(iu2sn+i-1) ) else call stdlib${ii}$_dlartgs( b22d(i), b22e(i), mu, work(iu2cs+i-1),work(iu2sn+i-1) ) end if work(iu2cs+i-1) = -work(iu2cs+i-1) work(iu2sn+i-1) = -work(iu2sn+i-1) temp = work(iu1cs+i-1)*b11e(i) + work(iu1sn+i-1)*b11d(i+1) b11d(i+1) = work(iu1cs+i-1)*b11d(i+1) -work(iu1sn+i-1)*b11e(i) b11e(i) = temp if( i < imax - 1_${ik}$ ) then b11bulge = work(iu1sn+i-1)*b11e(i+1) b11e(i+1) = work(iu1cs+i-1)*b11e(i+1) end if temp = work(iu2cs+i-1)*b21e(i) + work(iu2sn+i-1)*b21d(i+1) b21d(i+1) = work(iu2cs+i-1)*b21d(i+1) -work(iu2sn+i-1)*b21e(i) b21e(i) = temp if( i < imax - 1_${ik}$ ) then b21bulge = work(iu2sn+i-1)*b21e(i+1) b21e(i+1) = work(iu2cs+i-1)*b21e(i+1) end if temp = work(iu1cs+i-1)*b12d(i) + work(iu1sn+i-1)*b12e(i) b12e(i) = work(iu1cs+i-1)*b12e(i) - work(iu1sn+i-1)*b12d(i) b12d(i) = temp b12bulge = work(iu1sn+i-1)*b12d(i+1) b12d(i+1) = work(iu1cs+i-1)*b12d(i+1) temp = work(iu2cs+i-1)*b22d(i) + work(iu2sn+i-1)*b22e(i) b22e(i) = work(iu2cs+i-1)*b22e(i) - work(iu2sn+i-1)*b22d(i) b22d(i) = temp b22bulge = work(iu2sn+i-1)*b22d(i+1) b22d(i+1) = work(iu2cs+i-1)*b22d(i+1) end do ! compute phi(imax-1) x1 = sin(theta(imax-1))*b11e(imax-1) +cos(theta(imax-1))*b21e(imax-1) y1 = sin(theta(imax-1))*b12d(imax-1) +cos(theta(imax-1))*b22d(imax-1) y2 = sin(theta(imax-1))*b12bulge + cos(theta(imax-1))*b22bulge phi(imax-1) = atan2( abs(x1), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! chase bulges from b12(imax-1,imax) and b22(imax-1,imax) restart12 = b12d(imax-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(imax-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( y2, y1, work(iv2tsn+imax-1-1),work(iv2tcs+imax-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_dlartgp( b12bulge, b12d(imax-1), work(iv2tsn+imax-1-1),work(iv2tcs+& imax-1-1), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( b22bulge, b22d(imax-1), work(iv2tsn+imax-1-1),work(iv2tcs+& imax-1-1), r ) else if( nu < mu ) then call stdlib${ii}$_dlartgs( b12e(imax-1), b12d(imax), nu,work(iv2tcs+imax-1-1), work(& iv2tsn+imax-1-1) ) else call stdlib${ii}$_dlartgs( b22e(imax-1), b22d(imax), mu,work(iv2tcs+imax-1-1), work(& iv2tsn+imax-1-1) ) end if temp = work(iv2tcs+imax-1-1)*b12e(imax-1) +work(iv2tsn+imax-1-1)*b12d(imax) b12d(imax) = work(iv2tcs+imax-1-1)*b12d(imax) -work(iv2tsn+imax-1-1)*b12e(imax-1) b12e(imax-1) = temp temp = work(iv2tcs+imax-1-1)*b22e(imax-1) +work(iv2tsn+imax-1-1)*b22d(imax) b22d(imax) = work(iv2tcs+imax-1-1)*b22d(imax) -work(iv2tsn+imax-1-1)*b22e(imax-1) b22e(imax-1) = temp ! update singular vectors if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_dlasr( 'R', 'V', 'F', p, imax-imin+1,work(iu1cs+imin-1), work(& iu1sn+imin-1),u1(1_${ik}$,imin), ldu1 ) else call stdlib${ii}$_dlasr( 'L', 'V', 'F', imax-imin+1, p,work(iu1cs+imin-1), work(& iu1sn+imin-1),u1(imin,1_${ik}$), ldu1 ) end if end if if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_dlasr( 'R', 'V', 'F', m-p, imax-imin+1,work(iu2cs+imin-1), work(& iu2sn+imin-1),u2(1_${ik}$,imin), ldu2 ) else call stdlib${ii}$_dlasr( 'L', 'V', 'F', imax-imin+1, m-p,work(iu2cs+imin-1), work(& iu2sn+imin-1),u2(imin,1_${ik}$), ldu2 ) end if end if if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_dlasr( 'L', 'V', 'F', imax-imin+1, q,work(iv1tcs+imin-1), work(& iv1tsn+imin-1),v1t(imin,1_${ik}$), ldv1t ) else call stdlib${ii}$_dlasr( 'R', 'V', 'F', q, imax-imin+1,work(iv1tcs+imin-1), work(& iv1tsn+imin-1),v1t(1_${ik}$,imin), ldv1t ) end if end if if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_dlasr( 'L', 'V', 'F', imax-imin+1, m-q,work(iv2tcs+imin-1), work(& iv2tsn+imin-1),v2t(imin,1_${ik}$), ldv2t ) else call stdlib${ii}$_dlasr( 'R', 'V', 'F', m-q, imax-imin+1,work(iv2tcs+imin-1), work(& iv2tsn+imin-1),v2t(1_${ik}$,imin), ldv2t ) end if end if ! fix signs on b11(imax-1,imax) and b21(imax-1,imax) if( b11e(imax-1)+b21e(imax-1) > 0_${ik}$ ) then b11d(imax) = -b11d(imax) b21d(imax) = -b21d(imax) if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_dscal( q, negone, v1t(imax,1_${ik}$), ldv1t ) else call stdlib${ii}$_dscal( q, negone, v1t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! compute theta(imax) x1 = cos(phi(imax-1))*b11d(imax) +sin(phi(imax-1))*b12e(imax-1) y1 = cos(phi(imax-1))*b21d(imax) +sin(phi(imax-1))*b22e(imax-1) theta(imax) = atan2( abs(y1), abs(x1) ) ! fix signs on b11(imax,imax), b12(imax,imax-1), b21(imax,imax), ! and b22(imax,imax-1) if( b11d(imax)+b12e(imax-1) < 0_${ik}$ ) then b12d(imax) = -b12d(imax) if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_dscal( p, negone, u1(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_dscal( p, negone, u1(imax,1_${ik}$), ldu1 ) end if end if end if if( b21d(imax)+b22e(imax-1) > 0_${ik}$ ) then b22d(imax) = -b22d(imax) if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_dscal( m-p, negone, u2(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_dscal( m-p, negone, u2(imax,1_${ik}$), ldu2 ) end if end if end if ! fix signs on b12(imax,imax) and b22(imax,imax) if( b12d(imax)+b22d(imax) < 0_${ik}$ ) then if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_dscal( m-q, negone, v2t(imax,1_${ik}$), ldv2t ) else call stdlib${ii}$_dscal( m-q, negone, v2t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! test for negligible sines or cosines do i = imin, imax if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = imin, imax-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! deflate if (imax > 1_${ik}$) then do while( phi(imax-1) == zero ) imax = imax - 1_${ik}$ if (imax <= 1) exit end do end if if( imin > imax - 1_${ik}$ )imin = imax - 1_${ik}$ if (imin > 1_${ik}$) then do while (phi(imin-1) /= zero) imin = imin - 1_${ik}$ if (imin <= 1) exit end do end if ! repeat main iteration loop end do ! postprocessing: order theta from least to greatest do i = 1, q mini = i thetamin = theta(i) do j = i+1, q if( theta(j) < thetamin ) then mini = j thetamin = theta(j) end if end do if( mini /= i ) then theta(mini) = theta(i) theta(i) = thetamin if( colmajor ) then if( wantu1 )call stdlib${ii}$_dswap( p, u1(1_${ik}$,i), 1_${ik}$, u1(1_${ik}$,mini), 1_${ik}$ ) if( wantu2 )call stdlib${ii}$_dswap( m-p, u2(1_${ik}$,i), 1_${ik}$, u2(1_${ik}$,mini), 1_${ik}$ ) if( wantv1t )call stdlib${ii}$_dswap( q, v1t(i,1_${ik}$), ldv1t, v1t(mini,1_${ik}$), ldv1t ) if( wantv2t )call stdlib${ii}$_dswap( m-q, v2t(i,1_${ik}$), ldv2t, v2t(mini,1_${ik}$),ldv2t ) else if( wantu1 )call stdlib${ii}$_dswap( p, u1(i,1_${ik}$), ldu1, u1(mini,1_${ik}$), ldu1 ) if( wantu2 )call stdlib${ii}$_dswap( m-p, u2(i,1_${ik}$), ldu2, u2(mini,1_${ik}$), ldu2 ) if( wantv1t )call stdlib${ii}$_dswap( q, v1t(1_${ik}$,i), 1_${ik}$, v1t(1_${ik}$,mini), 1_${ik}$ ) if( wantv2t )call stdlib${ii}$_dswap( m-q, v2t(1_${ik}$,i), 1_${ik}$, v2t(1_${ik}$,mini), 1_${ik}$ ) end if end if end do return end subroutine stdlib${ii}$_dbbcsd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$bbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, phi, u1, & !! DBBCSD: computes the CS decomposition of an orthogonal matrix in !! bidiagonal-block form, !! [ B11 | B12 0 0 ] !! [ 0 | 0 -I 0 ] !! X = [----------------] !! [ B21 | B22 0 0 ] !! [ 0 | 0 0 I ] !! [ C | -S 0 0 ] !! [ U1 | ] [ 0 | 0 -I 0 ] [ V1 | ]**T !! = [---------] [---------------] [---------] . !! [ | U2 ] [ S | C 0 0 ] [ | V2 ] !! [ 0 | 0 0 I ] !! X is M-by-M, its top-left block is P-by-Q, and Q must be no larger !! than P, M-P, or M-Q. (If Q is not the smallest index, then X must be !! transposed and/or permuted. This can be done in constant time using !! the TRANS and SIGNS options. See DORCSD for details.) !! The bidiagonal matrices B11, B12, B21, and B22 are represented !! implicitly by angles THETA(1:Q) and PHI(1:Q-1). !! The orthogonal matrices U1, U2, V1T, and V2T are input/output. !! The input matrices are pre- or post-multiplied by the appropriate !! singular vector matrices. ldu1, u2, ldu2, v1t, ldv1t,v2t, ldv2t, b11d, b11e, b12d, b12e, b21d, b21e,b22d, b22e, work, & lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, one, ten, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, lwork, m, p, q ! Array Arguments real(${rk}$), intent(out) :: b11d(*), b11e(*), b12d(*), b12e(*), b21d(*), b21e(*), b22d(*),& b22e(*), work(*) real(${rk}$), intent(inout) :: phi(*), theta(*) real(${rk}$), intent(inout) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*) ! =================================================================== ! Parameters integer(${ik}$), parameter :: maxitr = 6_${ik}$ real(${rk}$), parameter :: hundred = 100.0_${rk}$ real(${rk}$), parameter :: meighth = -0.125_${rk}$ real(${rk}$), parameter :: piover2 = 1.57079632679489661923132169163975144210_${rk}$ ! Local Scalars logical(lk) :: colmajor, lquery, restart11, restart12, restart21, restart22, wantu1, & wantu2, wantv1t, wantv2t integer(${ik}$) :: i, imin, imax, iter, iu1cs, iu1sn, iu2cs, iu2sn, iv1tcs, iv1tsn, & iv2tcs, iv2tsn, j, lworkmin, lworkopt, maxit, mini real(${rk}$) :: b11bulge, b12bulge, b21bulge, b22bulge, dummy, eps, mu, nu, r, sigma11, & sigma21, temp, thetamax, thetamin, thresh, tol, tolmul, unfl, x1, x2, y1, y2 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) if( m < 0_${ik}$ ) then info = -6_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -7_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -8_${ik}$ else if( q > p .or. q > m-p .or. q > m-q ) then info = -8_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -12_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -14_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -16_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -18_${ik}$ end if ! quick return if q = 0 if( info == 0_${ik}$ .and. q == 0_${ik}$ ) then lworkmin = 1_${ik}$ work(1_${ik}$) = lworkmin return end if ! compute workspace if( info == 0_${ik}$ ) then iu1cs = 1_${ik}$ iu1sn = iu1cs + q iu2cs = iu1sn + q iu2sn = iu2cs + q iv1tcs = iu2sn + q iv1tsn = iv1tcs + q iv2tcs = iv1tsn + q iv2tsn = iv2tcs + q lworkopt = iv2tsn + q - 1_${ik}$ lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not. lquery ) then info = -28_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DBBCSD', -info ) return else if( lquery ) then return end if ! get machine constants eps = stdlib${ii}$_${ri}$lamch( 'EPSILON' ) unfl = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) tolmul = max( ten, min( hundred, eps**meighth ) ) tol = tolmul*eps thresh = max( tol, maxitr*q*q*unfl ) ! test for negligible sines or cosines do i = 1, q if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = 1, q-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! initial deflation imax = q do while( imax > 1 ) if( phi(imax-1) /= zero ) then exit end if imax = imax - 1_${ik}$ end do imin = imax - 1_${ik}$ if ( imin > 1_${ik}$ ) then do while( phi(imin-1) /= zero ) imin = imin - 1_${ik}$ if ( imin <= 1 ) exit end do end if ! initialize iteration counter maxit = maxitr*q*q iter = 0_${ik}$ ! begin main iteration loop do while( imax > 1 ) ! compute the matrix entries b11d(imin) = cos( theta(imin) ) b21d(imin) = -sin( theta(imin) ) do i = imin, imax - 1 b11e(i) = -sin( theta(i) ) * sin( phi(i) ) b11d(i+1) = cos( theta(i+1) ) * cos( phi(i) ) b12d(i) = sin( theta(i) ) * cos( phi(i) ) b12e(i) = cos( theta(i+1) ) * sin( phi(i) ) b21e(i) = -cos( theta(i) ) * sin( phi(i) ) b21d(i+1) = -sin( theta(i+1) ) * cos( phi(i) ) b22d(i) = cos( theta(i) ) * cos( phi(i) ) b22e(i) = -sin( theta(i+1) ) * sin( phi(i) ) end do b12d(imax) = sin( theta(imax) ) b22d(imax) = cos( theta(imax) ) ! abort if not converging; otherwise, increment iter if( iter > maxit ) then info = 0_${ik}$ do i = 1, q if( phi(i) /= zero )info = info + 1_${ik}$ end do return end if iter = iter + imax - imin ! compute shifts thetamax = theta(imin) thetamin = theta(imin) do i = imin+1, imax if( theta(i) > thetamax )thetamax = theta(i) if( theta(i) < thetamin )thetamin = theta(i) end do if( thetamax > piover2 - thresh ) then ! zero on diagonals of b11 and b22; induce deflation with a ! zero shift mu = zero nu = one else if( thetamin < thresh ) then ! zero on diagonals of b12 and b22; induce deflation with a ! zero shift mu = one nu = zero else ! compute shifts for b11 and b21 and use the lesser call stdlib${ii}$_${ri}$las2( b11d(imax-1), b11e(imax-1), b11d(imax), sigma11,dummy ) call stdlib${ii}$_${ri}$las2( b21d(imax-1), b21e(imax-1), b21d(imax), sigma21,dummy ) if( sigma11 <= sigma21 ) then mu = sigma11 nu = sqrt( one - mu**2_${ik}$ ) if( mu < thresh ) then mu = zero nu = one end if else nu = sigma21 mu = sqrt( one - nu**2_${ik}$ ) if( nu < thresh ) then mu = one nu = zero end if end if end if ! rotate to produce bulges in b11 and b21 if( mu <= nu ) then call stdlib${ii}$_${ri}$lartgs( b11d(imin), b11e(imin), mu,work(iv1tcs+imin-1), work(iv1tsn+& imin-1) ) else call stdlib${ii}$_${ri}$lartgs( b21d(imin), b21e(imin), nu,work(iv1tcs+imin-1), work(iv1tsn+& imin-1) ) end if temp = work(iv1tcs+imin-1)*b11d(imin) +work(iv1tsn+imin-1)*b11e(imin) b11e(imin) = work(iv1tcs+imin-1)*b11e(imin) -work(iv1tsn+imin-1)*b11d(imin) b11d(imin) = temp b11bulge = work(iv1tsn+imin-1)*b11d(imin+1) b11d(imin+1) = work(iv1tcs+imin-1)*b11d(imin+1) temp = work(iv1tcs+imin-1)*b21d(imin) +work(iv1tsn+imin-1)*b21e(imin) b21e(imin) = work(iv1tcs+imin-1)*b21e(imin) -work(iv1tsn+imin-1)*b21d(imin) b21d(imin) = temp b21bulge = work(iv1tsn+imin-1)*b21d(imin+1) b21d(imin+1) = work(iv1tcs+imin-1)*b21d(imin+1) ! compute theta(imin) theta( imin ) = atan2( sqrt( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ ),sqrt( b11d(imin)**2_${ik}$+& b11bulge**2_${ik}$ ) ) ! chase the bulges in b11(imin+1,imin) and b21(imin+1,imin) if( b11d(imin)**2_${ik}$+b11bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_${ri}$lartgp( b11bulge, b11d(imin), work(iu1sn+imin-1),work(iu1cs+imin-1),& r ) else if( mu <= nu ) then call stdlib${ii}$_${ri}$lartgs( b11e( imin ), b11d( imin + 1_${ik}$ ), mu,work(iu1cs+imin-1), work(& iu1sn+imin-1) ) else call stdlib${ii}$_${ri}$lartgs( b12d( imin ), b12e( imin ), nu,work(iu1cs+imin-1), work(& iu1sn+imin-1) ) end if if( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_${ri}$lartgp( b21bulge, b21d(imin), work(iu2sn+imin-1),work(iu2cs+imin-1),& r ) else if( nu < mu ) then call stdlib${ii}$_${ri}$lartgs( b21e( imin ), b21d( imin + 1_${ik}$ ), nu,work(iu2cs+imin-1), work(& iu2sn+imin-1) ) else call stdlib${ii}$_${ri}$lartgs( b22d(imin), b22e(imin), mu,work(iu2cs+imin-1), work(iu2sn+& imin-1) ) end if work(iu2cs+imin-1) = -work(iu2cs+imin-1) work(iu2sn+imin-1) = -work(iu2sn+imin-1) temp = work(iu1cs+imin-1)*b11e(imin) +work(iu1sn+imin-1)*b11d(imin+1) b11d(imin+1) = work(iu1cs+imin-1)*b11d(imin+1) -work(iu1sn+imin-1)*b11e(imin) b11e(imin) = temp if( imax > imin+1 ) then b11bulge = work(iu1sn+imin-1)*b11e(imin+1) b11e(imin+1) = work(iu1cs+imin-1)*b11e(imin+1) end if temp = work(iu1cs+imin-1)*b12d(imin) +work(iu1sn+imin-1)*b12e(imin) b12e(imin) = work(iu1cs+imin-1)*b12e(imin) -work(iu1sn+imin-1)*b12d(imin) b12d(imin) = temp b12bulge = work(iu1sn+imin-1)*b12d(imin+1) b12d(imin+1) = work(iu1cs+imin-1)*b12d(imin+1) temp = work(iu2cs+imin-1)*b21e(imin) +work(iu2sn+imin-1)*b21d(imin+1) b21d(imin+1) = work(iu2cs+imin-1)*b21d(imin+1) -work(iu2sn+imin-1)*b21e(imin) b21e(imin) = temp if( imax > imin+1 ) then b21bulge = work(iu2sn+imin-1)*b21e(imin+1) b21e(imin+1) = work(iu2cs+imin-1)*b21e(imin+1) end if temp = work(iu2cs+imin-1)*b22d(imin) +work(iu2sn+imin-1)*b22e(imin) b22e(imin) = work(iu2cs+imin-1)*b22e(imin) -work(iu2sn+imin-1)*b22d(imin) b22d(imin) = temp b22bulge = work(iu2sn+imin-1)*b22d(imin+1) b22d(imin+1) = work(iu2cs+imin-1)*b22d(imin+1) ! inner loop: chase bulges from b11(imin,imin+2), ! b12(imin,imin+1), b21(imin,imin+2), and b22(imin,imin+1) to ! bottom-right do i = imin+1, imax-1 ! compute phi(i-1) x1 = sin(theta(i-1))*b11e(i-1) + cos(theta(i-1))*b21e(i-1) x2 = sin(theta(i-1))*b11bulge + cos(theta(i-1))*b21bulge y1 = sin(theta(i-1))*b12d(i-1) + cos(theta(i-1))*b22d(i-1) y2 = sin(theta(i-1))*b12bulge + cos(theta(i-1))*b22bulge phi(i-1) = atan2( sqrt(x1**2_${ik}$+x2**2_${ik}$), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11e(i-1)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21e(i-1)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12d(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i-1,i+1), b12(i-1,i), ! b21(i-1,i+1), and b22(i-1,i). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart21 ) then call stdlib${ii}$_${ri}$lartgp( x2, x1, work(iv1tsn+i-1), work(iv1tcs+i-1),r ) else if( .not. restart11 .and. restart21 ) then call stdlib${ii}$_${ri}$lartgp( b11bulge, b11e(i-1), work(iv1tsn+i-1),work(iv1tcs+i-1), & r ) else if( restart11 .and. .not. restart21 ) then call stdlib${ii}$_${ri}$lartgp( b21bulge, b21e(i-1), work(iv1tsn+i-1),work(iv1tcs+i-1), & r ) else if( mu <= nu ) then call stdlib${ii}$_${ri}$lartgs( b11d(i), b11e(i), mu, work(iv1tcs+i-1),work(iv1tsn+i-1) ) else call stdlib${ii}$_${ri}$lartgs( b21d(i), b21e(i), nu, work(iv1tcs+i-1),work(iv1tsn+i-1) ) end if work(iv1tcs+i-1) = -work(iv1tcs+i-1) work(iv1tsn+i-1) = -work(iv1tsn+i-1) if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_${ri}$lartgp( y2, y1, work(iv2tsn+i-1-1),work(iv2tcs+i-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_${ri}$lartgp( b12bulge, b12d(i-1), work(iv2tsn+i-1-1),work(iv2tcs+i-1-& 1_${ik}$), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_${ri}$lartgp( b22bulge, b22d(i-1), work(iv2tsn+i-1-1),work(iv2tcs+i-1-& 1_${ik}$), r ) else if( nu < mu ) then call stdlib${ii}$_${ri}$lartgs( b12e(i-1), b12d(i), nu, work(iv2tcs+i-1-1),work(iv2tsn+i-& 1_${ik}$-1) ) else call stdlib${ii}$_${ri}$lartgs( b22e(i-1), b22d(i), mu, work(iv2tcs+i-1-1),work(iv2tsn+i-& 1_${ik}$-1) ) end if temp = work(iv1tcs+i-1)*b11d(i) + work(iv1tsn+i-1)*b11e(i) b11e(i) = work(iv1tcs+i-1)*b11e(i) -work(iv1tsn+i-1)*b11d(i) b11d(i) = temp b11bulge = work(iv1tsn+i-1)*b11d(i+1) b11d(i+1) = work(iv1tcs+i-1)*b11d(i+1) temp = work(iv1tcs+i-1)*b21d(i) + work(iv1tsn+i-1)*b21e(i) b21e(i) = work(iv1tcs+i-1)*b21e(i) -work(iv1tsn+i-1)*b21d(i) b21d(i) = temp b21bulge = work(iv1tsn+i-1)*b21d(i+1) b21d(i+1) = work(iv1tcs+i-1)*b21d(i+1) temp = work(iv2tcs+i-1-1)*b12e(i-1) +work(iv2tsn+i-1-1)*b12d(i) b12d(i) = work(iv2tcs+i-1-1)*b12d(i) -work(iv2tsn+i-1-1)*b12e(i-1) b12e(i-1) = temp b12bulge = work(iv2tsn+i-1-1)*b12e(i) b12e(i) = work(iv2tcs+i-1-1)*b12e(i) temp = work(iv2tcs+i-1-1)*b22e(i-1) +work(iv2tsn+i-1-1)*b22d(i) b22d(i) = work(iv2tcs+i-1-1)*b22d(i) -work(iv2tsn+i-1-1)*b22e(i-1) b22e(i-1) = temp b22bulge = work(iv2tsn+i-1-1)*b22e(i) b22e(i) = work(iv2tcs+i-1-1)*b22e(i) ! compute theta(i) x1 = cos(phi(i-1))*b11d(i) + sin(phi(i-1))*b12e(i-1) x2 = cos(phi(i-1))*b11bulge + sin(phi(i-1))*b12bulge y1 = cos(phi(i-1))*b21d(i) + sin(phi(i-1))*b22e(i-1) y2 = cos(phi(i-1))*b21bulge + sin(phi(i-1))*b22bulge theta(i) = atan2( sqrt(y1**2_${ik}$+y2**2_${ik}$), sqrt(x1**2_${ik}$+x2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11d(i)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12e(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21d(i)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22e(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i+1,i), b12(i+1,i-1), ! b21(i+1,i), and b22(i+1,i-1). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart12 ) then call stdlib${ii}$_${ri}$lartgp( x2, x1, work(iu1sn+i-1), work(iu1cs+i-1),r ) else if( .not. restart11 .and. restart12 ) then call stdlib${ii}$_${ri}$lartgp( b11bulge, b11d(i), work(iu1sn+i-1),work(iu1cs+i-1), r ) else if( restart11 .and. .not. restart12 ) then call stdlib${ii}$_${ri}$lartgp( b12bulge, b12e(i-1), work(iu1sn+i-1),work(iu1cs+i-1), r ) else if( mu <= nu ) then call stdlib${ii}$_${ri}$lartgs( b11e(i), b11d(i+1), mu, work(iu1cs+i-1),work(iu1sn+i-1) ) else call stdlib${ii}$_${ri}$lartgs( b12d(i), b12e(i), nu, work(iu1cs+i-1),work(iu1sn+i-1) ) end if if( .not. restart21 .and. .not. restart22 ) then call stdlib${ii}$_${ri}$lartgp( y2, y1, work(iu2sn+i-1), work(iu2cs+i-1),r ) else if( .not. restart21 .and. restart22 ) then call stdlib${ii}$_${ri}$lartgp( b21bulge, b21d(i), work(iu2sn+i-1),work(iu2cs+i-1), r ) else if( restart21 .and. .not. restart22 ) then call stdlib${ii}$_${ri}$lartgp( b22bulge, b22e(i-1), work(iu2sn+i-1),work(iu2cs+i-1), r ) else if( nu < mu ) then call stdlib${ii}$_${ri}$lartgs( b21e(i), b21e(i+1), nu, work(iu2cs+i-1),work(iu2sn+i-1) ) else call stdlib${ii}$_${ri}$lartgs( b22d(i), b22e(i), mu, work(iu2cs+i-1),work(iu2sn+i-1) ) end if work(iu2cs+i-1) = -work(iu2cs+i-1) work(iu2sn+i-1) = -work(iu2sn+i-1) temp = work(iu1cs+i-1)*b11e(i) + work(iu1sn+i-1)*b11d(i+1) b11d(i+1) = work(iu1cs+i-1)*b11d(i+1) -work(iu1sn+i-1)*b11e(i) b11e(i) = temp if( i < imax - 1_${ik}$ ) then b11bulge = work(iu1sn+i-1)*b11e(i+1) b11e(i+1) = work(iu1cs+i-1)*b11e(i+1) end if temp = work(iu2cs+i-1)*b21e(i) + work(iu2sn+i-1)*b21d(i+1) b21d(i+1) = work(iu2cs+i-1)*b21d(i+1) -work(iu2sn+i-1)*b21e(i) b21e(i) = temp if( i < imax - 1_${ik}$ ) then b21bulge = work(iu2sn+i-1)*b21e(i+1) b21e(i+1) = work(iu2cs+i-1)*b21e(i+1) end if temp = work(iu1cs+i-1)*b12d(i) + work(iu1sn+i-1)*b12e(i) b12e(i) = work(iu1cs+i-1)*b12e(i) - work(iu1sn+i-1)*b12d(i) b12d(i) = temp b12bulge = work(iu1sn+i-1)*b12d(i+1) b12d(i+1) = work(iu1cs+i-1)*b12d(i+1) temp = work(iu2cs+i-1)*b22d(i) + work(iu2sn+i-1)*b22e(i) b22e(i) = work(iu2cs+i-1)*b22e(i) - work(iu2sn+i-1)*b22d(i) b22d(i) = temp b22bulge = work(iu2sn+i-1)*b22d(i+1) b22d(i+1) = work(iu2cs+i-1)*b22d(i+1) end do ! compute phi(imax-1) x1 = sin(theta(imax-1))*b11e(imax-1) +cos(theta(imax-1))*b21e(imax-1) y1 = sin(theta(imax-1))*b12d(imax-1) +cos(theta(imax-1))*b22d(imax-1) y2 = sin(theta(imax-1))*b12bulge + cos(theta(imax-1))*b22bulge phi(imax-1) = atan2( abs(x1), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! chase bulges from b12(imax-1,imax) and b22(imax-1,imax) restart12 = b12d(imax-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(imax-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_${ri}$lartgp( y2, y1, work(iv2tsn+imax-1-1),work(iv2tcs+imax-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_${ri}$lartgp( b12bulge, b12d(imax-1), work(iv2tsn+imax-1-1),work(iv2tcs+& imax-1-1), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_${ri}$lartgp( b22bulge, b22d(imax-1), work(iv2tsn+imax-1-1),work(iv2tcs+& imax-1-1), r ) else if( nu < mu ) then call stdlib${ii}$_${ri}$lartgs( b12e(imax-1), b12d(imax), nu,work(iv2tcs+imax-1-1), work(& iv2tsn+imax-1-1) ) else call stdlib${ii}$_${ri}$lartgs( b22e(imax-1), b22d(imax), mu,work(iv2tcs+imax-1-1), work(& iv2tsn+imax-1-1) ) end if temp = work(iv2tcs+imax-1-1)*b12e(imax-1) +work(iv2tsn+imax-1-1)*b12d(imax) b12d(imax) = work(iv2tcs+imax-1-1)*b12d(imax) -work(iv2tsn+imax-1-1)*b12e(imax-1) b12e(imax-1) = temp temp = work(iv2tcs+imax-1-1)*b22e(imax-1) +work(iv2tsn+imax-1-1)*b22d(imax) b22d(imax) = work(iv2tcs+imax-1-1)*b22d(imax) -work(iv2tsn+imax-1-1)*b22e(imax-1) b22e(imax-1) = temp ! update singular vectors if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'F', p, imax-imin+1,work(iu1cs+imin-1), work(& iu1sn+imin-1),u1(1_${ik}$,imin), ldu1 ) else call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', imax-imin+1, p,work(iu1cs+imin-1), work(& iu1sn+imin-1),u1(imin,1_${ik}$), ldu1 ) end if end if if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'F', m-p, imax-imin+1,work(iu2cs+imin-1), work(& iu2sn+imin-1),u2(1_${ik}$,imin), ldu2 ) else call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', imax-imin+1, m-p,work(iu2cs+imin-1), work(& iu2sn+imin-1),u2(imin,1_${ik}$), ldu2 ) end if end if if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', imax-imin+1, q,work(iv1tcs+imin-1), work(& iv1tsn+imin-1),v1t(imin,1_${ik}$), ldv1t ) else call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'F', q, imax-imin+1,work(iv1tcs+imin-1), work(& iv1tsn+imin-1),v1t(1_${ik}$,imin), ldv1t ) end if end if if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', imax-imin+1, m-q,work(iv2tcs+imin-1), work(& iv2tsn+imin-1),v2t(imin,1_${ik}$), ldv2t ) else call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'F', m-q, imax-imin+1,work(iv2tcs+imin-1), work(& iv2tsn+imin-1),v2t(1_${ik}$,imin), ldv2t ) end if end if ! fix signs on b11(imax-1,imax) and b21(imax-1,imax) if( b11e(imax-1)+b21e(imax-1) > 0_${ik}$ ) then b11d(imax) = -b11d(imax) b21d(imax) = -b21d(imax) if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_${ri}$scal( q, negone, v1t(imax,1_${ik}$), ldv1t ) else call stdlib${ii}$_${ri}$scal( q, negone, v1t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! compute theta(imax) x1 = cos(phi(imax-1))*b11d(imax) +sin(phi(imax-1))*b12e(imax-1) y1 = cos(phi(imax-1))*b21d(imax) +sin(phi(imax-1))*b22e(imax-1) theta(imax) = atan2( abs(y1), abs(x1) ) ! fix signs on b11(imax,imax), b12(imax,imax-1), b21(imax,imax), ! and b22(imax,imax-1) if( b11d(imax)+b12e(imax-1) < 0_${ik}$ ) then b12d(imax) = -b12d(imax) if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_${ri}$scal( p, negone, u1(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_${ri}$scal( p, negone, u1(imax,1_${ik}$), ldu1 ) end if end if end if if( b21d(imax)+b22e(imax-1) > 0_${ik}$ ) then b22d(imax) = -b22d(imax) if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_${ri}$scal( m-p, negone, u2(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_${ri}$scal( m-p, negone, u2(imax,1_${ik}$), ldu2 ) end if end if end if ! fix signs on b12(imax,imax) and b22(imax,imax) if( b12d(imax)+b22d(imax) < 0_${ik}$ ) then if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_${ri}$scal( m-q, negone, v2t(imax,1_${ik}$), ldv2t ) else call stdlib${ii}$_${ri}$scal( m-q, negone, v2t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! test for negligible sines or cosines do i = imin, imax if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = imin, imax-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! deflate if (imax > 1_${ik}$) then do while( phi(imax-1) == zero ) imax = imax - 1_${ik}$ if (imax <= 1) exit end do end if if( imin > imax - 1_${ik}$ )imin = imax - 1_${ik}$ if (imin > 1_${ik}$) then do while (phi(imin-1) /= zero) imin = imin - 1_${ik}$ if (imin <= 1) exit end do end if ! repeat main iteration loop end do ! postprocessing: order theta from least to greatest do i = 1, q mini = i thetamin = theta(i) do j = i+1, q if( theta(j) < thetamin ) then mini = j thetamin = theta(j) end if end do if( mini /= i ) then theta(mini) = theta(i) theta(i) = thetamin if( colmajor ) then if( wantu1 )call stdlib${ii}$_${ri}$swap( p, u1(1_${ik}$,i), 1_${ik}$, u1(1_${ik}$,mini), 1_${ik}$ ) if( wantu2 )call stdlib${ii}$_${ri}$swap( m-p, u2(1_${ik}$,i), 1_${ik}$, u2(1_${ik}$,mini), 1_${ik}$ ) if( wantv1t )call stdlib${ii}$_${ri}$swap( q, v1t(i,1_${ik}$), ldv1t, v1t(mini,1_${ik}$), ldv1t ) if( wantv2t )call stdlib${ii}$_${ri}$swap( m-q, v2t(i,1_${ik}$), ldv2t, v2t(mini,1_${ik}$),ldv2t ) else if( wantu1 )call stdlib${ii}$_${ri}$swap( p, u1(i,1_${ik}$), ldu1, u1(mini,1_${ik}$), ldu1 ) if( wantu2 )call stdlib${ii}$_${ri}$swap( m-p, u2(i,1_${ik}$), ldu2, u2(mini,1_${ik}$), ldu2 ) if( wantv1t )call stdlib${ii}$_${ri}$swap( q, v1t(1_${ik}$,i), 1_${ik}$, v1t(1_${ik}$,mini), 1_${ik}$ ) if( wantv2t )call stdlib${ii}$_${ri}$swap( m-q, v2t(1_${ik}$,i), 1_${ik}$, v2t(1_${ik}$,mini), 1_${ik}$ ) end if end if end do return end subroutine stdlib${ii}$_${ri}$bbcsd #:endif #:endfor pure module subroutine stdlib${ii}$_cbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, phi, u1, & ldu1, u2, ldu2, v1t, ldv1t,v2t, ldv2t, b11d, b11e, b12d, b12e, b21d, b21e,b22d, b22e, rwork, & lrwork, info ) !! CBBCSD computes the CS decomposition of a unitary matrix in !! bidiagonal-block form, !! [ B11 | B12 0 0 ] !! [ 0 | 0 -I 0 ] !! X = [----------------] !! [ B21 | B22 0 0 ] !! [ 0 | 0 0 I ] !! [ C | -S 0 0 ] !! [ U1 | ] [ 0 | 0 -I 0 ] [ V1 | ]**H !! = [---------] [---------------] [---------] . !! [ | U2 ] [ S | C 0 0 ] [ | V2 ] !! [ 0 | 0 0 I ] !! X is M-by-M, its top-left block is P-by-Q, and Q must be no larger !! than P, M-P, or M-Q. (If Q is not the smallest index, then X must be !! transposed and/or permuted. This can be done in constant time using !! the TRANS and SIGNS options. See CUNCSD for details.) !! The bidiagonal matrices B11, B12, B21, and B22 are represented !! implicitly by angles THETA(1:Q) and PHI(1:Q-1). !! The unitary matrices U1, U2, V1T, and V2T are input/output. !! The input matrices are pre- or post-multiplied by the appropriate !! singular vector matrices. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, one, ten, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, lrwork, m, p, q ! Array Arguments real(sp), intent(out) :: b11d(*), b11e(*), b12d(*), b12e(*), b21d(*), b21e(*), b22d(*),& b22e(*), rwork(*) real(sp), intent(inout) :: phi(*), theta(*) complex(sp), intent(inout) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*) ! =================================================================== ! Parameters integer(${ik}$), parameter :: maxitr = 6_${ik}$ real(sp), parameter :: hundred = 100.0_sp real(sp), parameter :: meighth = -0.125_sp real(sp), parameter :: piover2 = 1.57079632679489661923132169163975144210_sp ! Local Scalars logical(lk) :: colmajor, lquery, restart11, restart12, restart21, restart22, wantu1, & wantu2, wantv1t, wantv2t integer(${ik}$) :: i, imin, imax, iter, iu1cs, iu1sn, iu2cs, iu2sn, iv1tcs, iv1tsn, & iv2tcs, iv2tsn, j, lrworkmin, lrworkopt, maxit, mini real(sp) :: b11bulge, b12bulge, b21bulge, b22bulge, dummy, eps, mu, nu, r, sigma11, & sigma21, temp, thetamax, thetamin, thresh, tol, tolmul, unfl, x1, x2, y1, y2 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lrwork == -1_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) if( m < 0_${ik}$ ) then info = -6_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -7_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -8_${ik}$ else if( q > p .or. q > m-p .or. q > m-q ) then info = -8_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -12_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -14_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -16_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -18_${ik}$ end if ! quick return if q = 0 if( info == 0_${ik}$ .and. q == 0_${ik}$ ) then lrworkmin = 1_${ik}$ rwork(1_${ik}$) = lrworkmin return end if ! compute workspace if( info == 0_${ik}$ ) then iu1cs = 1_${ik}$ iu1sn = iu1cs + q iu2cs = iu1sn + q iu2sn = iu2cs + q iv1tcs = iu2sn + q iv1tsn = iv1tcs + q iv2tcs = iv1tsn + q iv2tsn = iv2tcs + q lrworkopt = iv2tsn + q - 1_${ik}$ lrworkmin = lrworkopt rwork(1_${ik}$) = lrworkopt if( lrwork < lrworkmin .and. .not. lquery ) then info = -28_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CBBCSD', -info ) return else if( lquery ) then return end if ! get machine constants eps = stdlib${ii}$_slamch( 'EPSILON' ) unfl = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) tolmul = max( ten, min( hundred, eps**meighth ) ) tol = tolmul*eps thresh = max( tol, maxitr*q*q*unfl ) ! test for negligible sines or cosines do i = 1, q if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = 1, q-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! initial deflation imax = q do while( imax > 1 ) if( phi(imax-1) /= zero ) then exit end if imax = imax - 1_${ik}$ end do imin = imax - 1_${ik}$ if ( imin > 1_${ik}$ ) then do while( phi(imin-1) /= zero ) imin = imin - 1_${ik}$ if ( imin <= 1 ) exit end do end if ! initialize iteration counter maxit = maxitr*q*q iter = 0_${ik}$ ! begin main iteration loop do while( imax > 1 ) ! compute the matrix entries b11d(imin) = cos( theta(imin) ) b21d(imin) = -sin( theta(imin) ) do i = imin, imax - 1 b11e(i) = -sin( theta(i) ) * sin( phi(i) ) b11d(i+1) = cos( theta(i+1) ) * cos( phi(i) ) b12d(i) = sin( theta(i) ) * cos( phi(i) ) b12e(i) = cos( theta(i+1) ) * sin( phi(i) ) b21e(i) = -cos( theta(i) ) * sin( phi(i) ) b21d(i+1) = -sin( theta(i+1) ) * cos( phi(i) ) b22d(i) = cos( theta(i) ) * cos( phi(i) ) b22e(i) = -sin( theta(i+1) ) * sin( phi(i) ) end do b12d(imax) = sin( theta(imax) ) b22d(imax) = cos( theta(imax) ) ! abort if not converging; otherwise, increment iter if( iter > maxit ) then info = 0_${ik}$ do i = 1, q if( phi(i) /= zero )info = info + 1_${ik}$ end do return end if iter = iter + imax - imin ! compute shifts thetamax = theta(imin) thetamin = theta(imin) do i = imin+1, imax if( theta(i) > thetamax )thetamax = theta(i) if( theta(i) < thetamin )thetamin = theta(i) end do if( thetamax > piover2 - thresh ) then ! zero on diagonals of b11 and b22; induce deflation with a ! zero shift mu = zero nu = one else if( thetamin < thresh ) then ! zero on diagonals of b12 and b22; induce deflation with a ! zero shift mu = one nu = zero else ! compute shifts for b11 and b21 and use the lesser call stdlib${ii}$_slas2( b11d(imax-1), b11e(imax-1), b11d(imax), sigma11,dummy ) call stdlib${ii}$_slas2( b21d(imax-1), b21e(imax-1), b21d(imax), sigma21,dummy ) if( sigma11 <= sigma21 ) then mu = sigma11 nu = sqrt( one - mu**2_${ik}$ ) if( mu < thresh ) then mu = zero nu = one end if else nu = sigma21 mu = sqrt( one - nu**2_${ik}$ ) if( nu < thresh ) then mu = one nu = zero end if end if end if ! rotate to produce bulges in b11 and b21 if( mu <= nu ) then call stdlib${ii}$_slartgs( b11d(imin), b11e(imin), mu,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1) ) else call stdlib${ii}$_slartgs( b21d(imin), b21e(imin), nu,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1) ) end if temp = rwork(iv1tcs+imin-1)*b11d(imin) +rwork(iv1tsn+imin-1)*b11e(imin) b11e(imin) = rwork(iv1tcs+imin-1)*b11e(imin) -rwork(iv1tsn+imin-1)*b11d(imin) b11d(imin) = temp b11bulge = rwork(iv1tsn+imin-1)*b11d(imin+1) b11d(imin+1) = rwork(iv1tcs+imin-1)*b11d(imin+1) temp = rwork(iv1tcs+imin-1)*b21d(imin) +rwork(iv1tsn+imin-1)*b21e(imin) b21e(imin) = rwork(iv1tcs+imin-1)*b21e(imin) -rwork(iv1tsn+imin-1)*b21d(imin) b21d(imin) = temp b21bulge = rwork(iv1tsn+imin-1)*b21d(imin+1) b21d(imin+1) = rwork(iv1tcs+imin-1)*b21d(imin+1) ! compute theta(imin) theta( imin ) = atan2( sqrt( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ ),sqrt( b11d(imin)**2_${ik}$+& b11bulge**2_${ik}$ ) ) ! chase the bulges in b11(imin+1,imin) and b21(imin+1,imin) if( b11d(imin)**2_${ik}$+b11bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_slartgp( b11bulge, b11d(imin), rwork(iu1sn+imin-1),rwork(iu1cs+imin-& 1_${ik}$), r ) else if( mu <= nu ) then call stdlib${ii}$_slartgs( b11e( imin ), b11d( imin + 1_${ik}$ ), mu,rwork(iu1cs+imin-1), & rwork(iu1sn+imin-1) ) else call stdlib${ii}$_slartgs( b12d( imin ), b12e( imin ), nu,rwork(iu1cs+imin-1), rwork(& iu1sn+imin-1) ) end if if( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_slartgp( b21bulge, b21d(imin), rwork(iu2sn+imin-1),rwork(iu2cs+imin-& 1_${ik}$), r ) else if( nu < mu ) then call stdlib${ii}$_slartgs( b21e( imin ), b21d( imin + 1_${ik}$ ), nu,rwork(iu2cs+imin-1), & rwork(iu2sn+imin-1) ) else call stdlib${ii}$_slartgs( b22d(imin), b22e(imin), mu,rwork(iu2cs+imin-1), rwork(iu2sn+& imin-1) ) end if rwork(iu2cs+imin-1) = -rwork(iu2cs+imin-1) rwork(iu2sn+imin-1) = -rwork(iu2sn+imin-1) temp = rwork(iu1cs+imin-1)*b11e(imin) +rwork(iu1sn+imin-1)*b11d(imin+1) b11d(imin+1) = rwork(iu1cs+imin-1)*b11d(imin+1) -rwork(iu1sn+imin-1)*b11e(imin) b11e(imin) = temp if( imax > imin+1 ) then b11bulge = rwork(iu1sn+imin-1)*b11e(imin+1) b11e(imin+1) = rwork(iu1cs+imin-1)*b11e(imin+1) end if temp = rwork(iu1cs+imin-1)*b12d(imin) +rwork(iu1sn+imin-1)*b12e(imin) b12e(imin) = rwork(iu1cs+imin-1)*b12e(imin) -rwork(iu1sn+imin-1)*b12d(imin) b12d(imin) = temp b12bulge = rwork(iu1sn+imin-1)*b12d(imin+1) b12d(imin+1) = rwork(iu1cs+imin-1)*b12d(imin+1) temp = rwork(iu2cs+imin-1)*b21e(imin) +rwork(iu2sn+imin-1)*b21d(imin+1) b21d(imin+1) = rwork(iu2cs+imin-1)*b21d(imin+1) -rwork(iu2sn+imin-1)*b21e(imin) b21e(imin) = temp if( imax > imin+1 ) then b21bulge = rwork(iu2sn+imin-1)*b21e(imin+1) b21e(imin+1) = rwork(iu2cs+imin-1)*b21e(imin+1) end if temp = rwork(iu2cs+imin-1)*b22d(imin) +rwork(iu2sn+imin-1)*b22e(imin) b22e(imin) = rwork(iu2cs+imin-1)*b22e(imin) -rwork(iu2sn+imin-1)*b22d(imin) b22d(imin) = temp b22bulge = rwork(iu2sn+imin-1)*b22d(imin+1) b22d(imin+1) = rwork(iu2cs+imin-1)*b22d(imin+1) ! inner loop: chase bulges from b11(imin,imin+2), ! b12(imin,imin+1), b21(imin,imin+2), and b22(imin,imin+1) to ! bottom-right do i = imin+1, imax-1 ! compute phi(i-1) x1 = sin(theta(i-1))*b11e(i-1) + cos(theta(i-1))*b21e(i-1) x2 = sin(theta(i-1))*b11bulge + cos(theta(i-1))*b21bulge y1 = sin(theta(i-1))*b12d(i-1) + cos(theta(i-1))*b22d(i-1) y2 = sin(theta(i-1))*b12bulge + cos(theta(i-1))*b22bulge phi(i-1) = atan2( sqrt(x1**2_${ik}$+x2**2_${ik}$), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11e(i-1)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21e(i-1)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12d(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i-1,i+1), b12(i-1,i), ! b21(i-1,i+1), and b22(i-1,i). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart21 ) then call stdlib${ii}$_slartgp( x2, x1, rwork(iv1tsn+i-1),rwork(iv1tcs+i-1), r ) else if( .not. restart11 .and. restart21 ) then call stdlib${ii}$_slartgp( b11bulge, b11e(i-1), rwork(iv1tsn+i-1),rwork(iv1tcs+i-1),& r ) else if( restart11 .and. .not. restart21 ) then call stdlib${ii}$_slartgp( b21bulge, b21e(i-1), rwork(iv1tsn+i-1),rwork(iv1tcs+i-1),& r ) else if( mu <= nu ) then call stdlib${ii}$_slartgs( b11d(i), b11e(i), mu, rwork(iv1tcs+i-1),rwork(iv1tsn+i-1)& ) else call stdlib${ii}$_slartgs( b21d(i), b21e(i), nu, rwork(iv1tcs+i-1),rwork(iv1tsn+i-1)& ) end if rwork(iv1tcs+i-1) = -rwork(iv1tcs+i-1) rwork(iv1tsn+i-1) = -rwork(iv1tsn+i-1) if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( y2, y1, rwork(iv2tsn+i-1-1),rwork(iv2tcs+i-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_slartgp( b12bulge, b12d(i-1), rwork(iv2tsn+i-1-1),rwork(iv2tcs+i-& 1_${ik}$-1), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( b22bulge, b22d(i-1), rwork(iv2tsn+i-1-1),rwork(iv2tcs+i-& 1_${ik}$-1), r ) else if( nu < mu ) then call stdlib${ii}$_slartgs( b12e(i-1), b12d(i), nu,rwork(iv2tcs+i-1-1), rwork(iv2tsn+& i-1-1) ) else call stdlib${ii}$_slartgs( b22e(i-1), b22d(i), mu,rwork(iv2tcs+i-1-1), rwork(iv2tsn+& i-1-1) ) end if temp = rwork(iv1tcs+i-1)*b11d(i) + rwork(iv1tsn+i-1)*b11e(i) b11e(i) = rwork(iv1tcs+i-1)*b11e(i) -rwork(iv1tsn+i-1)*b11d(i) b11d(i) = temp b11bulge = rwork(iv1tsn+i-1)*b11d(i+1) b11d(i+1) = rwork(iv1tcs+i-1)*b11d(i+1) temp = rwork(iv1tcs+i-1)*b21d(i) + rwork(iv1tsn+i-1)*b21e(i) b21e(i) = rwork(iv1tcs+i-1)*b21e(i) -rwork(iv1tsn+i-1)*b21d(i) b21d(i) = temp b21bulge = rwork(iv1tsn+i-1)*b21d(i+1) b21d(i+1) = rwork(iv1tcs+i-1)*b21d(i+1) temp = rwork(iv2tcs+i-1-1)*b12e(i-1) +rwork(iv2tsn+i-1-1)*b12d(i) b12d(i) = rwork(iv2tcs+i-1-1)*b12d(i) -rwork(iv2tsn+i-1-1)*b12e(i-1) b12e(i-1) = temp b12bulge = rwork(iv2tsn+i-1-1)*b12e(i) b12e(i) = rwork(iv2tcs+i-1-1)*b12e(i) temp = rwork(iv2tcs+i-1-1)*b22e(i-1) +rwork(iv2tsn+i-1-1)*b22d(i) b22d(i) = rwork(iv2tcs+i-1-1)*b22d(i) -rwork(iv2tsn+i-1-1)*b22e(i-1) b22e(i-1) = temp b22bulge = rwork(iv2tsn+i-1-1)*b22e(i) b22e(i) = rwork(iv2tcs+i-1-1)*b22e(i) ! compute theta(i) x1 = cos(phi(i-1))*b11d(i) + sin(phi(i-1))*b12e(i-1) x2 = cos(phi(i-1))*b11bulge + sin(phi(i-1))*b12bulge y1 = cos(phi(i-1))*b21d(i) + sin(phi(i-1))*b22e(i-1) y2 = cos(phi(i-1))*b21bulge + sin(phi(i-1))*b22bulge theta(i) = atan2( sqrt(y1**2_${ik}$+y2**2_${ik}$), sqrt(x1**2_${ik}$+x2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11d(i)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12e(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21d(i)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22e(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i+1,i), b12(i+1,i-1), ! b21(i+1,i), and b22(i+1,i-1). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart12 ) then call stdlib${ii}$_slartgp( x2, x1, rwork(iu1sn+i-1), rwork(iu1cs+i-1),r ) else if( .not. restart11 .and. restart12 ) then call stdlib${ii}$_slartgp( b11bulge, b11d(i), rwork(iu1sn+i-1),rwork(iu1cs+i-1), r ) else if( restart11 .and. .not. restart12 ) then call stdlib${ii}$_slartgp( b12bulge, b12e(i-1), rwork(iu1sn+i-1),rwork(iu1cs+i-1), & r ) else if( mu <= nu ) then call stdlib${ii}$_slartgs( b11e(i), b11d(i+1), mu, rwork(iu1cs+i-1),rwork(iu1sn+i-1)& ) else call stdlib${ii}$_slartgs( b12d(i), b12e(i), nu, rwork(iu1cs+i-1),rwork(iu1sn+i-1) ) end if if( .not. restart21 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( y2, y1, rwork(iu2sn+i-1), rwork(iu2cs+i-1),r ) else if( .not. restart21 .and. restart22 ) then call stdlib${ii}$_slartgp( b21bulge, b21d(i), rwork(iu2sn+i-1),rwork(iu2cs+i-1), r ) else if( restart21 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( b22bulge, b22e(i-1), rwork(iu2sn+i-1),rwork(iu2cs+i-1), & r ) else if( nu < mu ) then call stdlib${ii}$_slartgs( b21e(i), b21e(i+1), nu, rwork(iu2cs+i-1),rwork(iu2sn+i-1)& ) else call stdlib${ii}$_slartgs( b22d(i), b22e(i), mu, rwork(iu2cs+i-1),rwork(iu2sn+i-1) ) end if rwork(iu2cs+i-1) = -rwork(iu2cs+i-1) rwork(iu2sn+i-1) = -rwork(iu2sn+i-1) temp = rwork(iu1cs+i-1)*b11e(i) + rwork(iu1sn+i-1)*b11d(i+1) b11d(i+1) = rwork(iu1cs+i-1)*b11d(i+1) -rwork(iu1sn+i-1)*b11e(i) b11e(i) = temp if( i < imax - 1_${ik}$ ) then b11bulge = rwork(iu1sn+i-1)*b11e(i+1) b11e(i+1) = rwork(iu1cs+i-1)*b11e(i+1) end if temp = rwork(iu2cs+i-1)*b21e(i) + rwork(iu2sn+i-1)*b21d(i+1) b21d(i+1) = rwork(iu2cs+i-1)*b21d(i+1) -rwork(iu2sn+i-1)*b21e(i) b21e(i) = temp if( i < imax - 1_${ik}$ ) then b21bulge = rwork(iu2sn+i-1)*b21e(i+1) b21e(i+1) = rwork(iu2cs+i-1)*b21e(i+1) end if temp = rwork(iu1cs+i-1)*b12d(i) + rwork(iu1sn+i-1)*b12e(i) b12e(i) = rwork(iu1cs+i-1)*b12e(i) -rwork(iu1sn+i-1)*b12d(i) b12d(i) = temp b12bulge = rwork(iu1sn+i-1)*b12d(i+1) b12d(i+1) = rwork(iu1cs+i-1)*b12d(i+1) temp = rwork(iu2cs+i-1)*b22d(i) + rwork(iu2sn+i-1)*b22e(i) b22e(i) = rwork(iu2cs+i-1)*b22e(i) -rwork(iu2sn+i-1)*b22d(i) b22d(i) = temp b22bulge = rwork(iu2sn+i-1)*b22d(i+1) b22d(i+1) = rwork(iu2cs+i-1)*b22d(i+1) end do ! compute phi(imax-1) x1 = sin(theta(imax-1))*b11e(imax-1) +cos(theta(imax-1))*b21e(imax-1) y1 = sin(theta(imax-1))*b12d(imax-1) +cos(theta(imax-1))*b22d(imax-1) y2 = sin(theta(imax-1))*b12bulge + cos(theta(imax-1))*b22bulge phi(imax-1) = atan2( abs(x1), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! chase bulges from b12(imax-1,imax) and b22(imax-1,imax) restart12 = b12d(imax-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(imax-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( y2, y1, rwork(iv2tsn+imax-1-1),rwork(iv2tcs+imax-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_slartgp( b12bulge, b12d(imax-1),rwork(iv2tsn+imax-1-1),rwork(iv2tcs+& imax-1-1), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_slartgp( b22bulge, b22d(imax-1),rwork(iv2tsn+imax-1-1),rwork(iv2tcs+& imax-1-1), r ) else if( nu < mu ) then call stdlib${ii}$_slartgs( b12e(imax-1), b12d(imax), nu,rwork(iv2tcs+imax-1-1),rwork(& iv2tsn+imax-1-1) ) else call stdlib${ii}$_slartgs( b22e(imax-1), b22d(imax), mu,rwork(iv2tcs+imax-1-1),rwork(& iv2tsn+imax-1-1) ) end if temp = rwork(iv2tcs+imax-1-1)*b12e(imax-1) +rwork(iv2tsn+imax-1-1)*b12d(imax) b12d(imax) = rwork(iv2tcs+imax-1-1)*b12d(imax) -rwork(iv2tsn+imax-1-1)*b12e(imax-1) b12e(imax-1) = temp temp = rwork(iv2tcs+imax-1-1)*b22e(imax-1) +rwork(iv2tsn+imax-1-1)*b22d(imax) b22d(imax) = rwork(iv2tcs+imax-1-1)*b22d(imax) -rwork(iv2tsn+imax-1-1)*b22e(imax-1) b22e(imax-1) = temp ! update singular vectors if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_clasr( 'R', 'V', 'F', p, imax-imin+1,rwork(iu1cs+imin-1), rwork(& iu1sn+imin-1),u1(1_${ik}$,imin), ldu1 ) else call stdlib${ii}$_clasr( 'L', 'V', 'F', imax-imin+1, p,rwork(iu1cs+imin-1), rwork(& iu1sn+imin-1),u1(imin,1_${ik}$), ldu1 ) end if end if if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_clasr( 'R', 'V', 'F', m-p, imax-imin+1,rwork(iu2cs+imin-1), rwork(& iu2sn+imin-1),u2(1_${ik}$,imin), ldu2 ) else call stdlib${ii}$_clasr( 'L', 'V', 'F', imax-imin+1, m-p,rwork(iu2cs+imin-1), rwork(& iu2sn+imin-1),u2(imin,1_${ik}$), ldu2 ) end if end if if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_clasr( 'L', 'V', 'F', imax-imin+1, q,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1),v1t(imin,1_${ik}$), ldv1t ) else call stdlib${ii}$_clasr( 'R', 'V', 'F', q, imax-imin+1,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1),v1t(1_${ik}$,imin), ldv1t ) end if end if if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_clasr( 'L', 'V', 'F', imax-imin+1, m-q,rwork(iv2tcs+imin-1), & rwork(iv2tsn+imin-1),v2t(imin,1_${ik}$), ldv2t ) else call stdlib${ii}$_clasr( 'R', 'V', 'F', m-q, imax-imin+1,rwork(iv2tcs+imin-1), & rwork(iv2tsn+imin-1),v2t(1_${ik}$,imin), ldv2t ) end if end if ! fix signs on b11(imax-1,imax) and b21(imax-1,imax) if( b11e(imax-1)+b21e(imax-1) > 0_${ik}$ ) then b11d(imax) = -b11d(imax) b21d(imax) = -b21d(imax) if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_cscal( q, cnegone, v1t(imax,1_${ik}$), ldv1t ) else call stdlib${ii}$_cscal( q, cnegone, v1t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! compute theta(imax) x1 = cos(phi(imax-1))*b11d(imax) +sin(phi(imax-1))*b12e(imax-1) y1 = cos(phi(imax-1))*b21d(imax) +sin(phi(imax-1))*b22e(imax-1) theta(imax) = atan2( abs(y1), abs(x1) ) ! fix signs on b11(imax,imax), b12(imax,imax-1), b21(imax,imax), ! and b22(imax,imax-1) if( b11d(imax)+b12e(imax-1) < 0_${ik}$ ) then b12d(imax) = -b12d(imax) if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_cscal( p, cnegone, u1(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_cscal( p, cnegone, u1(imax,1_${ik}$), ldu1 ) end if end if end if if( b21d(imax)+b22e(imax-1) > 0_${ik}$ ) then b22d(imax) = -b22d(imax) if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_cscal( m-p, cnegone, u2(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_cscal( m-p, cnegone, u2(imax,1_${ik}$), ldu2 ) end if end if end if ! fix signs on b12(imax,imax) and b22(imax,imax) if( b12d(imax)+b22d(imax) < 0_${ik}$ ) then if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_cscal( m-q, cnegone, v2t(imax,1_${ik}$), ldv2t ) else call stdlib${ii}$_cscal( m-q, cnegone, v2t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! test for negligible sines or cosines do i = imin, imax if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = imin, imax-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! deflate if (imax > 1_${ik}$) then do while( phi(imax-1) == zero ) imax = imax - 1_${ik}$ if (imax <= 1) exit end do end if if( imin > imax - 1_${ik}$ )imin = imax - 1_${ik}$ if (imin > 1_${ik}$) then do while (phi(imin-1) /= zero) imin = imin - 1_${ik}$ if (imin <= 1) exit end do end if ! repeat main iteration loop end do ! postprocessing: order theta from least to greatest do i = 1, q mini = i thetamin = theta(i) do j = i+1, q if( theta(j) < thetamin ) then mini = j thetamin = theta(j) end if end do if( mini /= i ) then theta(mini) = theta(i) theta(i) = thetamin if( colmajor ) then if( wantu1 )call stdlib${ii}$_cswap( p, u1(1_${ik}$,i), 1_${ik}$, u1(1_${ik}$,mini), 1_${ik}$ ) if( wantu2 )call stdlib${ii}$_cswap( m-p, u2(1_${ik}$,i), 1_${ik}$, u2(1_${ik}$,mini), 1_${ik}$ ) if( wantv1t )call stdlib${ii}$_cswap( q, v1t(i,1_${ik}$), ldv1t, v1t(mini,1_${ik}$), ldv1t ) if( wantv2t )call stdlib${ii}$_cswap( m-q, v2t(i,1_${ik}$), ldv2t, v2t(mini,1_${ik}$),ldv2t ) else if( wantu1 )call stdlib${ii}$_cswap( p, u1(i,1_${ik}$), ldu1, u1(mini,1_${ik}$), ldu1 ) if( wantu2 )call stdlib${ii}$_cswap( m-p, u2(i,1_${ik}$), ldu2, u2(mini,1_${ik}$), ldu2 ) if( wantv1t )call stdlib${ii}$_cswap( q, v1t(1_${ik}$,i), 1_${ik}$, v1t(1_${ik}$,mini), 1_${ik}$ ) if( wantv2t )call stdlib${ii}$_cswap( m-q, v2t(1_${ik}$,i), 1_${ik}$, v2t(1_${ik}$,mini), 1_${ik}$ ) end if end if end do return end subroutine stdlib${ii}$_cbbcsd pure module subroutine stdlib${ii}$_zbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, phi, u1, & !! ZBBCSD computes the CS decomposition of a unitary matrix in !! bidiagonal-block form, !! [ B11 | B12 0 0 ] !! [ 0 | 0 -I 0 ] !! X = [----------------] !! [ B21 | B22 0 0 ] !! [ 0 | 0 0 I ] !! [ C | -S 0 0 ] !! [ U1 | ] [ 0 | 0 -I 0 ] [ V1 | ]**H !! = [---------] [---------------] [---------] . !! [ | U2 ] [ S | C 0 0 ] [ | V2 ] !! [ 0 | 0 0 I ] !! X is M-by-M, its top-left block is P-by-Q, and Q must be no larger !! than P, M-P, or M-Q. (If Q is not the smallest index, then X must be !! transposed and/or permuted. This can be done in constant time using !! the TRANS and SIGNS options. See ZUNCSD for details.) !! The bidiagonal matrices B11, B12, B21, and B22 are represented !! implicitly by angles THETA(1:Q) and PHI(1:Q-1). !! The unitary matrices U1, U2, V1T, and V2T are input/output. !! The input matrices are pre- or post-multiplied by the appropriate !! singular vector matrices. ldu1, u2, ldu2, v1t, ldv1t,v2t, ldv2t, b11d, b11e, b12d, b12e, b21d, b21e,b22d, b22e, rwork, & lrwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, one, ten, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, lrwork, m, p, q ! Array Arguments real(dp), intent(out) :: b11d(*), b11e(*), b12d(*), b12e(*), b21d(*), b21e(*), b22d(*),& b22e(*), rwork(*) real(dp), intent(inout) :: phi(*), theta(*) complex(dp), intent(inout) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*) ! =================================================================== ! Parameters integer(${ik}$), parameter :: maxitr = 6_${ik}$ real(dp), parameter :: hundred = 100.0_dp real(dp), parameter :: meighth = -0.125_dp real(dp), parameter :: piover2 = 1.57079632679489661923132169163975144210_dp ! Local Scalars logical(lk) :: colmajor, lquery, restart11, restart12, restart21, restart22, wantu1, & wantu2, wantv1t, wantv2t integer(${ik}$) :: i, imin, imax, iter, iu1cs, iu1sn, iu2cs, iu2sn, iv1tcs, iv1tsn, & iv2tcs, iv2tsn, j, lrworkmin, lrworkopt, maxit, mini real(dp) :: b11bulge, b12bulge, b21bulge, b22bulge, dummy, eps, mu, nu, r, sigma11, & sigma21, temp, thetamax, thetamin, thresh, tol, tolmul, unfl, x1, x2, y1, y2 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lrwork == -1_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) if( m < 0_${ik}$ ) then info = -6_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -7_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -8_${ik}$ else if( q > p .or. q > m-p .or. q > m-q ) then info = -8_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -12_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -14_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -16_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -18_${ik}$ end if ! quick return if q = 0 if( info == 0_${ik}$ .and. q == 0_${ik}$ ) then lrworkmin = 1_${ik}$ rwork(1_${ik}$) = lrworkmin return end if ! compute workspace if( info == 0_${ik}$ ) then iu1cs = 1_${ik}$ iu1sn = iu1cs + q iu2cs = iu1sn + q iu2sn = iu2cs + q iv1tcs = iu2sn + q iv1tsn = iv1tcs + q iv2tcs = iv1tsn + q iv2tsn = iv2tcs + q lrworkopt = iv2tsn + q - 1_${ik}$ lrworkmin = lrworkopt rwork(1_${ik}$) = lrworkopt if( lrwork < lrworkmin .and. .not. lquery ) then info = -28_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZBBCSD', -info ) return else if( lquery ) then return end if ! get machine constants eps = stdlib${ii}$_dlamch( 'EPSILON' ) unfl = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) tolmul = max( ten, min( hundred, eps**meighth ) ) tol = tolmul*eps thresh = max( tol, maxitr*q*q*unfl ) ! test for negligible sines or cosines do i = 1, q if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = 1, q-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! initial deflation imax = q do while( imax > 1 ) if( phi(imax-1) /= zero ) then exit end if imax = imax - 1_${ik}$ end do imin = imax - 1_${ik}$ if ( imin > 1_${ik}$ ) then do while( phi(imin-1) /= zero ) imin = imin - 1_${ik}$ if ( imin <= 1 ) exit end do end if ! initialize iteration counter maxit = maxitr*q*q iter = 0_${ik}$ ! begin main iteration loop do while( imax > 1 ) ! compute the matrix entries b11d(imin) = cos( theta(imin) ) b21d(imin) = -sin( theta(imin) ) do i = imin, imax - 1 b11e(i) = -sin( theta(i) ) * sin( phi(i) ) b11d(i+1) = cos( theta(i+1) ) * cos( phi(i) ) b12d(i) = sin( theta(i) ) * cos( phi(i) ) b12e(i) = cos( theta(i+1) ) * sin( phi(i) ) b21e(i) = -cos( theta(i) ) * sin( phi(i) ) b21d(i+1) = -sin( theta(i+1) ) * cos( phi(i) ) b22d(i) = cos( theta(i) ) * cos( phi(i) ) b22e(i) = -sin( theta(i+1) ) * sin( phi(i) ) end do b12d(imax) = sin( theta(imax) ) b22d(imax) = cos( theta(imax) ) ! abort if not converging; otherwise, increment iter if( iter > maxit ) then info = 0_${ik}$ do i = 1, q if( phi(i) /= zero )info = info + 1_${ik}$ end do return end if iter = iter + imax - imin ! compute shifts thetamax = theta(imin) thetamin = theta(imin) do i = imin+1, imax if( theta(i) > thetamax )thetamax = theta(i) if( theta(i) < thetamin )thetamin = theta(i) end do if( thetamax > piover2 - thresh ) then ! zero on diagonals of b11 and b22; induce deflation with a ! zero shift mu = zero nu = one else if( thetamin < thresh ) then ! zero on diagonals of b12 and b22; induce deflation with a ! zero shift mu = one nu = zero else ! compute shifts for b11 and b21 and use the lesser call stdlib${ii}$_dlas2( b11d(imax-1), b11e(imax-1), b11d(imax), sigma11,dummy ) call stdlib${ii}$_dlas2( b21d(imax-1), b21e(imax-1), b21d(imax), sigma21,dummy ) if( sigma11 <= sigma21 ) then mu = sigma11 nu = sqrt( one - mu**2_${ik}$ ) if( mu < thresh ) then mu = zero nu = one end if else nu = sigma21 mu = sqrt( one - nu**2_${ik}$ ) if( nu < thresh ) then mu = one nu = zero end if end if end if ! rotate to produce bulges in b11 and b21 if( mu <= nu ) then call stdlib${ii}$_dlartgs( b11d(imin), b11e(imin), mu,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1) ) else call stdlib${ii}$_dlartgs( b21d(imin), b21e(imin), nu,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1) ) end if temp = rwork(iv1tcs+imin-1)*b11d(imin) +rwork(iv1tsn+imin-1)*b11e(imin) b11e(imin) = rwork(iv1tcs+imin-1)*b11e(imin) -rwork(iv1tsn+imin-1)*b11d(imin) b11d(imin) = temp b11bulge = rwork(iv1tsn+imin-1)*b11d(imin+1) b11d(imin+1) = rwork(iv1tcs+imin-1)*b11d(imin+1) temp = rwork(iv1tcs+imin-1)*b21d(imin) +rwork(iv1tsn+imin-1)*b21e(imin) b21e(imin) = rwork(iv1tcs+imin-1)*b21e(imin) -rwork(iv1tsn+imin-1)*b21d(imin) b21d(imin) = temp b21bulge = rwork(iv1tsn+imin-1)*b21d(imin+1) b21d(imin+1) = rwork(iv1tcs+imin-1)*b21d(imin+1) ! compute theta(imin) theta( imin ) = atan2( sqrt( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ ),sqrt( b11d(imin)**2_${ik}$+& b11bulge**2_${ik}$ ) ) ! chase the bulges in b11(imin+1,imin) and b21(imin+1,imin) if( b11d(imin)**2_${ik}$+b11bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_dlartgp( b11bulge, b11d(imin), rwork(iu1sn+imin-1),rwork(iu1cs+imin-& 1_${ik}$), r ) else if( mu <= nu ) then call stdlib${ii}$_dlartgs( b11e( imin ), b11d( imin + 1_${ik}$ ), mu,rwork(iu1cs+imin-1), & rwork(iu1sn+imin-1) ) else call stdlib${ii}$_dlartgs( b12d( imin ), b12e( imin ), nu,rwork(iu1cs+imin-1), rwork(& iu1sn+imin-1) ) end if if( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_dlartgp( b21bulge, b21d(imin), rwork(iu2sn+imin-1),rwork(iu2cs+imin-& 1_${ik}$), r ) else if( nu < mu ) then call stdlib${ii}$_dlartgs( b21e( imin ), b21d( imin + 1_${ik}$ ), nu,rwork(iu2cs+imin-1), & rwork(iu2sn+imin-1) ) else call stdlib${ii}$_dlartgs( b22d(imin), b22e(imin), mu,rwork(iu2cs+imin-1), rwork(iu2sn+& imin-1) ) end if rwork(iu2cs+imin-1) = -rwork(iu2cs+imin-1) rwork(iu2sn+imin-1) = -rwork(iu2sn+imin-1) temp = rwork(iu1cs+imin-1)*b11e(imin) +rwork(iu1sn+imin-1)*b11d(imin+1) b11d(imin+1) = rwork(iu1cs+imin-1)*b11d(imin+1) -rwork(iu1sn+imin-1)*b11e(imin) b11e(imin) = temp if( imax > imin+1 ) then b11bulge = rwork(iu1sn+imin-1)*b11e(imin+1) b11e(imin+1) = rwork(iu1cs+imin-1)*b11e(imin+1) end if temp = rwork(iu1cs+imin-1)*b12d(imin) +rwork(iu1sn+imin-1)*b12e(imin) b12e(imin) = rwork(iu1cs+imin-1)*b12e(imin) -rwork(iu1sn+imin-1)*b12d(imin) b12d(imin) = temp b12bulge = rwork(iu1sn+imin-1)*b12d(imin+1) b12d(imin+1) = rwork(iu1cs+imin-1)*b12d(imin+1) temp = rwork(iu2cs+imin-1)*b21e(imin) +rwork(iu2sn+imin-1)*b21d(imin+1) b21d(imin+1) = rwork(iu2cs+imin-1)*b21d(imin+1) -rwork(iu2sn+imin-1)*b21e(imin) b21e(imin) = temp if( imax > imin+1 ) then b21bulge = rwork(iu2sn+imin-1)*b21e(imin+1) b21e(imin+1) = rwork(iu2cs+imin-1)*b21e(imin+1) end if temp = rwork(iu2cs+imin-1)*b22d(imin) +rwork(iu2sn+imin-1)*b22e(imin) b22e(imin) = rwork(iu2cs+imin-1)*b22e(imin) -rwork(iu2sn+imin-1)*b22d(imin) b22d(imin) = temp b22bulge = rwork(iu2sn+imin-1)*b22d(imin+1) b22d(imin+1) = rwork(iu2cs+imin-1)*b22d(imin+1) ! inner loop: chase bulges from b11(imin,imin+2), ! b12(imin,imin+1), b21(imin,imin+2), and b22(imin,imin+1) to ! bottom-right do i = imin+1, imax-1 ! compute phi(i-1) x1 = sin(theta(i-1))*b11e(i-1) + cos(theta(i-1))*b21e(i-1) x2 = sin(theta(i-1))*b11bulge + cos(theta(i-1))*b21bulge y1 = sin(theta(i-1))*b12d(i-1) + cos(theta(i-1))*b22d(i-1) y2 = sin(theta(i-1))*b12bulge + cos(theta(i-1))*b22bulge phi(i-1) = atan2( sqrt(x1**2_${ik}$+x2**2_${ik}$), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11e(i-1)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21e(i-1)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12d(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i-1,i+1), b12(i-1,i), ! b21(i-1,i+1), and b22(i-1,i). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart21 ) then call stdlib${ii}$_dlartgp( x2, x1, rwork(iv1tsn+i-1),rwork(iv1tcs+i-1), r ) else if( .not. restart11 .and. restart21 ) then call stdlib${ii}$_dlartgp( b11bulge, b11e(i-1), rwork(iv1tsn+i-1),rwork(iv1tcs+i-1),& r ) else if( restart11 .and. .not. restart21 ) then call stdlib${ii}$_dlartgp( b21bulge, b21e(i-1), rwork(iv1tsn+i-1),rwork(iv1tcs+i-1),& r ) else if( mu <= nu ) then call stdlib${ii}$_dlartgs( b11d(i), b11e(i), mu, rwork(iv1tcs+i-1),rwork(iv1tsn+i-1)& ) else call stdlib${ii}$_dlartgs( b21d(i), b21e(i), nu, rwork(iv1tcs+i-1),rwork(iv1tsn+i-1)& ) end if rwork(iv1tcs+i-1) = -rwork(iv1tcs+i-1) rwork(iv1tsn+i-1) = -rwork(iv1tsn+i-1) if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( y2, y1, rwork(iv2tsn+i-1-1),rwork(iv2tcs+i-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_dlartgp( b12bulge, b12d(i-1), rwork(iv2tsn+i-1-1),rwork(iv2tcs+i-& 1_${ik}$-1), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( b22bulge, b22d(i-1), rwork(iv2tsn+i-1-1),rwork(iv2tcs+i-& 1_${ik}$-1), r ) else if( nu < mu ) then call stdlib${ii}$_dlartgs( b12e(i-1), b12d(i), nu,rwork(iv2tcs+i-1-1), rwork(iv2tsn+& i-1-1) ) else call stdlib${ii}$_dlartgs( b22e(i-1), b22d(i), mu,rwork(iv2tcs+i-1-1), rwork(iv2tsn+& i-1-1) ) end if temp = rwork(iv1tcs+i-1)*b11d(i) + rwork(iv1tsn+i-1)*b11e(i) b11e(i) = rwork(iv1tcs+i-1)*b11e(i) -rwork(iv1tsn+i-1)*b11d(i) b11d(i) = temp b11bulge = rwork(iv1tsn+i-1)*b11d(i+1) b11d(i+1) = rwork(iv1tcs+i-1)*b11d(i+1) temp = rwork(iv1tcs+i-1)*b21d(i) + rwork(iv1tsn+i-1)*b21e(i) b21e(i) = rwork(iv1tcs+i-1)*b21e(i) -rwork(iv1tsn+i-1)*b21d(i) b21d(i) = temp b21bulge = rwork(iv1tsn+i-1)*b21d(i+1) b21d(i+1) = rwork(iv1tcs+i-1)*b21d(i+1) temp = rwork(iv2tcs+i-1-1)*b12e(i-1) +rwork(iv2tsn+i-1-1)*b12d(i) b12d(i) = rwork(iv2tcs+i-1-1)*b12d(i) -rwork(iv2tsn+i-1-1)*b12e(i-1) b12e(i-1) = temp b12bulge = rwork(iv2tsn+i-1-1)*b12e(i) b12e(i) = rwork(iv2tcs+i-1-1)*b12e(i) temp = rwork(iv2tcs+i-1-1)*b22e(i-1) +rwork(iv2tsn+i-1-1)*b22d(i) b22d(i) = rwork(iv2tcs+i-1-1)*b22d(i) -rwork(iv2tsn+i-1-1)*b22e(i-1) b22e(i-1) = temp b22bulge = rwork(iv2tsn+i-1-1)*b22e(i) b22e(i) = rwork(iv2tcs+i-1-1)*b22e(i) ! compute theta(i) x1 = cos(phi(i-1))*b11d(i) + sin(phi(i-1))*b12e(i-1) x2 = cos(phi(i-1))*b11bulge + sin(phi(i-1))*b12bulge y1 = cos(phi(i-1))*b21d(i) + sin(phi(i-1))*b22e(i-1) y2 = cos(phi(i-1))*b21bulge + sin(phi(i-1))*b22bulge theta(i) = atan2( sqrt(y1**2_${ik}$+y2**2_${ik}$), sqrt(x1**2_${ik}$+x2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11d(i)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12e(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21d(i)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22e(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i+1,i), b12(i+1,i-1), ! b21(i+1,i), and b22(i+1,i-1). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart12 ) then call stdlib${ii}$_dlartgp( x2, x1, rwork(iu1sn+i-1), rwork(iu1cs+i-1),r ) else if( .not. restart11 .and. restart12 ) then call stdlib${ii}$_dlartgp( b11bulge, b11d(i), rwork(iu1sn+i-1),rwork(iu1cs+i-1), r ) else if( restart11 .and. .not. restart12 ) then call stdlib${ii}$_dlartgp( b12bulge, b12e(i-1), rwork(iu1sn+i-1),rwork(iu1cs+i-1), & r ) else if( mu <= nu ) then call stdlib${ii}$_dlartgs( b11e(i), b11d(i+1), mu, rwork(iu1cs+i-1),rwork(iu1sn+i-1)& ) else call stdlib${ii}$_dlartgs( b12d(i), b12e(i), nu, rwork(iu1cs+i-1),rwork(iu1sn+i-1) ) end if if( .not. restart21 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( y2, y1, rwork(iu2sn+i-1), rwork(iu2cs+i-1),r ) else if( .not. restart21 .and. restart22 ) then call stdlib${ii}$_dlartgp( b21bulge, b21d(i), rwork(iu2sn+i-1),rwork(iu2cs+i-1), r ) else if( restart21 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( b22bulge, b22e(i-1), rwork(iu2sn+i-1),rwork(iu2cs+i-1), & r ) else if( nu < mu ) then call stdlib${ii}$_dlartgs( b21e(i), b21e(i+1), nu, rwork(iu2cs+i-1),rwork(iu2sn+i-1)& ) else call stdlib${ii}$_dlartgs( b22d(i), b22e(i), mu, rwork(iu2cs+i-1),rwork(iu2sn+i-1) ) end if rwork(iu2cs+i-1) = -rwork(iu2cs+i-1) rwork(iu2sn+i-1) = -rwork(iu2sn+i-1) temp = rwork(iu1cs+i-1)*b11e(i) + rwork(iu1sn+i-1)*b11d(i+1) b11d(i+1) = rwork(iu1cs+i-1)*b11d(i+1) -rwork(iu1sn+i-1)*b11e(i) b11e(i) = temp if( i < imax - 1_${ik}$ ) then b11bulge = rwork(iu1sn+i-1)*b11e(i+1) b11e(i+1) = rwork(iu1cs+i-1)*b11e(i+1) end if temp = rwork(iu2cs+i-1)*b21e(i) + rwork(iu2sn+i-1)*b21d(i+1) b21d(i+1) = rwork(iu2cs+i-1)*b21d(i+1) -rwork(iu2sn+i-1)*b21e(i) b21e(i) = temp if( i < imax - 1_${ik}$ ) then b21bulge = rwork(iu2sn+i-1)*b21e(i+1) b21e(i+1) = rwork(iu2cs+i-1)*b21e(i+1) end if temp = rwork(iu1cs+i-1)*b12d(i) + rwork(iu1sn+i-1)*b12e(i) b12e(i) = rwork(iu1cs+i-1)*b12e(i) -rwork(iu1sn+i-1)*b12d(i) b12d(i) = temp b12bulge = rwork(iu1sn+i-1)*b12d(i+1) b12d(i+1) = rwork(iu1cs+i-1)*b12d(i+1) temp = rwork(iu2cs+i-1)*b22d(i) + rwork(iu2sn+i-1)*b22e(i) b22e(i) = rwork(iu2cs+i-1)*b22e(i) -rwork(iu2sn+i-1)*b22d(i) b22d(i) = temp b22bulge = rwork(iu2sn+i-1)*b22d(i+1) b22d(i+1) = rwork(iu2cs+i-1)*b22d(i+1) end do ! compute phi(imax-1) x1 = sin(theta(imax-1))*b11e(imax-1) +cos(theta(imax-1))*b21e(imax-1) y1 = sin(theta(imax-1))*b12d(imax-1) +cos(theta(imax-1))*b22d(imax-1) y2 = sin(theta(imax-1))*b12bulge + cos(theta(imax-1))*b22bulge phi(imax-1) = atan2( abs(x1), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! chase bulges from b12(imax-1,imax) and b22(imax-1,imax) restart12 = b12d(imax-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(imax-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( y2, y1, rwork(iv2tsn+imax-1-1),rwork(iv2tcs+imax-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_dlartgp( b12bulge, b12d(imax-1),rwork(iv2tsn+imax-1-1),rwork(iv2tcs+& imax-1-1), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_dlartgp( b22bulge, b22d(imax-1),rwork(iv2tsn+imax-1-1),rwork(iv2tcs+& imax-1-1), r ) else if( nu < mu ) then call stdlib${ii}$_dlartgs( b12e(imax-1), b12d(imax), nu,rwork(iv2tcs+imax-1-1),rwork(& iv2tsn+imax-1-1) ) else call stdlib${ii}$_dlartgs( b22e(imax-1), b22d(imax), mu,rwork(iv2tcs+imax-1-1),rwork(& iv2tsn+imax-1-1) ) end if temp = rwork(iv2tcs+imax-1-1)*b12e(imax-1) +rwork(iv2tsn+imax-1-1)*b12d(imax) b12d(imax) = rwork(iv2tcs+imax-1-1)*b12d(imax) -rwork(iv2tsn+imax-1-1)*b12e(imax-1) b12e(imax-1) = temp temp = rwork(iv2tcs+imax-1-1)*b22e(imax-1) +rwork(iv2tsn+imax-1-1)*b22d(imax) b22d(imax) = rwork(iv2tcs+imax-1-1)*b22d(imax) -rwork(iv2tsn+imax-1-1)*b22e(imax-1) b22e(imax-1) = temp ! update singular vectors if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_zlasr( 'R', 'V', 'F', p, imax-imin+1,rwork(iu1cs+imin-1), rwork(& iu1sn+imin-1),u1(1_${ik}$,imin), ldu1 ) else call stdlib${ii}$_zlasr( 'L', 'V', 'F', imax-imin+1, p,rwork(iu1cs+imin-1), rwork(& iu1sn+imin-1),u1(imin,1_${ik}$), ldu1 ) end if end if if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_zlasr( 'R', 'V', 'F', m-p, imax-imin+1,rwork(iu2cs+imin-1), rwork(& iu2sn+imin-1),u2(1_${ik}$,imin), ldu2 ) else call stdlib${ii}$_zlasr( 'L', 'V', 'F', imax-imin+1, m-p,rwork(iu2cs+imin-1), rwork(& iu2sn+imin-1),u2(imin,1_${ik}$), ldu2 ) end if end if if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_zlasr( 'L', 'V', 'F', imax-imin+1, q,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1),v1t(imin,1_${ik}$), ldv1t ) else call stdlib${ii}$_zlasr( 'R', 'V', 'F', q, imax-imin+1,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1),v1t(1_${ik}$,imin), ldv1t ) end if end if if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_zlasr( 'L', 'V', 'F', imax-imin+1, m-q,rwork(iv2tcs+imin-1), & rwork(iv2tsn+imin-1),v2t(imin,1_${ik}$), ldv2t ) else call stdlib${ii}$_zlasr( 'R', 'V', 'F', m-q, imax-imin+1,rwork(iv2tcs+imin-1), & rwork(iv2tsn+imin-1),v2t(1_${ik}$,imin), ldv2t ) end if end if ! fix signs on b11(imax-1,imax) and b21(imax-1,imax) if( b11e(imax-1)+b21e(imax-1) > 0_${ik}$ ) then b11d(imax) = -b11d(imax) b21d(imax) = -b21d(imax) if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_zscal( q, cnegone, v1t(imax,1_${ik}$), ldv1t ) else call stdlib${ii}$_zscal( q, cnegone, v1t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! compute theta(imax) x1 = cos(phi(imax-1))*b11d(imax) +sin(phi(imax-1))*b12e(imax-1) y1 = cos(phi(imax-1))*b21d(imax) +sin(phi(imax-1))*b22e(imax-1) theta(imax) = atan2( abs(y1), abs(x1) ) ! fix signs on b11(imax,imax), b12(imax,imax-1), b21(imax,imax), ! and b22(imax,imax-1) if( b11d(imax)+b12e(imax-1) < 0_${ik}$ ) then b12d(imax) = -b12d(imax) if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_zscal( p, cnegone, u1(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_zscal( p, cnegone, u1(imax,1_${ik}$), ldu1 ) end if end if end if if( b21d(imax)+b22e(imax-1) > 0_${ik}$ ) then b22d(imax) = -b22d(imax) if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_zscal( m-p, cnegone, u2(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_zscal( m-p, cnegone, u2(imax,1_${ik}$), ldu2 ) end if end if end if ! fix signs on b12(imax,imax) and b22(imax,imax) if( b12d(imax)+b22d(imax) < 0_${ik}$ ) then if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_zscal( m-q, cnegone, v2t(imax,1_${ik}$), ldv2t ) else call stdlib${ii}$_zscal( m-q, cnegone, v2t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! test for negligible sines or cosines do i = imin, imax if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = imin, imax-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! deflate if (imax > 1_${ik}$) then do while( phi(imax-1) == zero ) imax = imax - 1_${ik}$ if (imax <= 1) exit end do end if if( imin > imax - 1_${ik}$ )imin = imax - 1_${ik}$ if (imin > 1_${ik}$) then do while (phi(imin-1) /= zero) imin = imin - 1_${ik}$ if (imin <= 1) exit end do end if ! repeat main iteration loop end do ! postprocessing: order theta from least to greatest do i = 1, q mini = i thetamin = theta(i) do j = i+1, q if( theta(j) < thetamin ) then mini = j thetamin = theta(j) end if end do if( mini /= i ) then theta(mini) = theta(i) theta(i) = thetamin if( colmajor ) then if( wantu1 )call stdlib${ii}$_zswap( p, u1(1_${ik}$,i), 1_${ik}$, u1(1_${ik}$,mini), 1_${ik}$ ) if( wantu2 )call stdlib${ii}$_zswap( m-p, u2(1_${ik}$,i), 1_${ik}$, u2(1_${ik}$,mini), 1_${ik}$ ) if( wantv1t )call stdlib${ii}$_zswap( q, v1t(i,1_${ik}$), ldv1t, v1t(mini,1_${ik}$), ldv1t ) if( wantv2t )call stdlib${ii}$_zswap( m-q, v2t(i,1_${ik}$), ldv2t, v2t(mini,1_${ik}$),ldv2t ) else if( wantu1 )call stdlib${ii}$_zswap( p, u1(i,1_${ik}$), ldu1, u1(mini,1_${ik}$), ldu1 ) if( wantu2 )call stdlib${ii}$_zswap( m-p, u2(i,1_${ik}$), ldu2, u2(mini,1_${ik}$), ldu2 ) if( wantv1t )call stdlib${ii}$_zswap( q, v1t(1_${ik}$,i), 1_${ik}$, v1t(1_${ik}$,mini), 1_${ik}$ ) if( wantv2t )call stdlib${ii}$_zswap( m-q, v2t(1_${ik}$,i), 1_${ik}$, v2t(1_${ik}$,mini), 1_${ik}$ ) end if end if end do return end subroutine stdlib${ii}$_zbbcsd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$bbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, phi, u1, & !! ZBBCSD: computes the CS decomposition of a unitary matrix in !! bidiagonal-block form, !! [ B11 | B12 0 0 ] !! [ 0 | 0 -I 0 ] !! X = [----------------] !! [ B21 | B22 0 0 ] !! [ 0 | 0 0 I ] !! [ C | -S 0 0 ] !! [ U1 | ] [ 0 | 0 -I 0 ] [ V1 | ]**H !! = [---------] [---------------] [---------] . !! [ | U2 ] [ S | C 0 0 ] [ | V2 ] !! [ 0 | 0 0 I ] !! X is M-by-M, its top-left block is P-by-Q, and Q must be no larger !! than P, M-P, or M-Q. (If Q is not the smallest index, then X must be !! transposed and/or permuted. This can be done in constant time using !! the TRANS and SIGNS options. See ZUNCSD for details.) !! The bidiagonal matrices B11, B12, B21, and B22 are represented !! implicitly by angles THETA(1:Q) and PHI(1:Q-1). !! The unitary matrices U1, U2, V1T, and V2T are input/output. !! The input matrices are pre- or post-multiplied by the appropriate !! singular vector matrices. ldu1, u2, ldu2, v1t, ldv1t,v2t, ldv2t, b11d, b11e, b12d, b12e, b21d, b21e,b22d, b22e, rwork, & lrwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, one, ten, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, lrwork, m, p, q ! Array Arguments real(${ck}$), intent(out) :: b11d(*), b11e(*), b12d(*), b12e(*), b21d(*), b21e(*), b22d(*),& b22e(*), rwork(*) real(${ck}$), intent(inout) :: phi(*), theta(*) complex(${ck}$), intent(inout) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*) ! =================================================================== ! Parameters integer(${ik}$), parameter :: maxitr = 6_${ik}$ real(${ck}$), parameter :: hundred = 100.0_${ck}$ real(${ck}$), parameter :: meighth = -0.125_${ck}$ real(${ck}$), parameter :: piover2 = 1.57079632679489661923132169163975144210_${ck}$ ! Local Scalars logical(lk) :: colmajor, lquery, restart11, restart12, restart21, restart22, wantu1, & wantu2, wantv1t, wantv2t integer(${ik}$) :: i, imin, imax, iter, iu1cs, iu1sn, iu2cs, iu2sn, iv1tcs, iv1tsn, & iv2tcs, iv2tsn, j, lrworkmin, lrworkopt, maxit, mini real(${ck}$) :: b11bulge, b12bulge, b21bulge, b22bulge, dummy, eps, mu, nu, r, sigma11, & sigma21, temp, thetamax, thetamin, thresh, tol, tolmul, unfl, x1, x2, y1, y2 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lrwork == -1_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) if( m < 0_${ik}$ ) then info = -6_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -7_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -8_${ik}$ else if( q > p .or. q > m-p .or. q > m-q ) then info = -8_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -12_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -14_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -16_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -18_${ik}$ end if ! quick return if q = 0 if( info == 0_${ik}$ .and. q == 0_${ik}$ ) then lrworkmin = 1_${ik}$ rwork(1_${ik}$) = lrworkmin return end if ! compute workspace if( info == 0_${ik}$ ) then iu1cs = 1_${ik}$ iu1sn = iu1cs + q iu2cs = iu1sn + q iu2sn = iu2cs + q iv1tcs = iu2sn + q iv1tsn = iv1tcs + q iv2tcs = iv1tsn + q iv2tsn = iv2tcs + q lrworkopt = iv2tsn + q - 1_${ik}$ lrworkmin = lrworkopt rwork(1_${ik}$) = lrworkopt if( lrwork < lrworkmin .and. .not. lquery ) then info = -28_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZBBCSD', -info ) return else if( lquery ) then return end if ! get machine constants eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'EPSILON' ) unfl = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) tolmul = max( ten, min( hundred, eps**meighth ) ) tol = tolmul*eps thresh = max( tol, maxitr*q*q*unfl ) ! test for negligible sines or cosines do i = 1, q if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = 1, q-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! initial deflation imax = q do while( imax > 1 ) if( phi(imax-1) /= zero ) then exit end if imax = imax - 1_${ik}$ end do imin = imax - 1_${ik}$ if ( imin > 1_${ik}$ ) then do while( phi(imin-1) /= zero ) imin = imin - 1_${ik}$ if ( imin <= 1 ) exit end do end if ! initialize iteration counter maxit = maxitr*q*q iter = 0_${ik}$ ! begin main iteration loop do while( imax > 1 ) ! compute the matrix entries b11d(imin) = cos( theta(imin) ) b21d(imin) = -sin( theta(imin) ) do i = imin, imax - 1 b11e(i) = -sin( theta(i) ) * sin( phi(i) ) b11d(i+1) = cos( theta(i+1) ) * cos( phi(i) ) b12d(i) = sin( theta(i) ) * cos( phi(i) ) b12e(i) = cos( theta(i+1) ) * sin( phi(i) ) b21e(i) = -cos( theta(i) ) * sin( phi(i) ) b21d(i+1) = -sin( theta(i+1) ) * cos( phi(i) ) b22d(i) = cos( theta(i) ) * cos( phi(i) ) b22e(i) = -sin( theta(i+1) ) * sin( phi(i) ) end do b12d(imax) = sin( theta(imax) ) b22d(imax) = cos( theta(imax) ) ! abort if not converging; otherwise, increment iter if( iter > maxit ) then info = 0_${ik}$ do i = 1, q if( phi(i) /= zero )info = info + 1_${ik}$ end do return end if iter = iter + imax - imin ! compute shifts thetamax = theta(imin) thetamin = theta(imin) do i = imin+1, imax if( theta(i) > thetamax )thetamax = theta(i) if( theta(i) < thetamin )thetamin = theta(i) end do if( thetamax > piover2 - thresh ) then ! zero on diagonals of b11 and b22; induce deflation with a ! zero shift mu = zero nu = one else if( thetamin < thresh ) then ! zero on diagonals of b12 and b22; induce deflation with a ! zero shift mu = one nu = zero else ! compute shifts for b11 and b21 and use the lesser call stdlib${ii}$_${c2ri(ci)}$las2( b11d(imax-1), b11e(imax-1), b11d(imax), sigma11,dummy ) call stdlib${ii}$_${c2ri(ci)}$las2( b21d(imax-1), b21e(imax-1), b21d(imax), sigma21,dummy ) if( sigma11 <= sigma21 ) then mu = sigma11 nu = sqrt( one - mu**2_${ik}$ ) if( mu < thresh ) then mu = zero nu = one end if else nu = sigma21 mu = sqrt( one - nu**2_${ik}$ ) if( nu < thresh ) then mu = one nu = zero end if end if end if ! rotate to produce bulges in b11 and b21 if( mu <= nu ) then call stdlib${ii}$_${c2ri(ci)}$lartgs( b11d(imin), b11e(imin), mu,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1) ) else call stdlib${ii}$_${c2ri(ci)}$lartgs( b21d(imin), b21e(imin), nu,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1) ) end if temp = rwork(iv1tcs+imin-1)*b11d(imin) +rwork(iv1tsn+imin-1)*b11e(imin) b11e(imin) = rwork(iv1tcs+imin-1)*b11e(imin) -rwork(iv1tsn+imin-1)*b11d(imin) b11d(imin) = temp b11bulge = rwork(iv1tsn+imin-1)*b11d(imin+1) b11d(imin+1) = rwork(iv1tcs+imin-1)*b11d(imin+1) temp = rwork(iv1tcs+imin-1)*b21d(imin) +rwork(iv1tsn+imin-1)*b21e(imin) b21e(imin) = rwork(iv1tcs+imin-1)*b21e(imin) -rwork(iv1tsn+imin-1)*b21d(imin) b21d(imin) = temp b21bulge = rwork(iv1tsn+imin-1)*b21d(imin+1) b21d(imin+1) = rwork(iv1tcs+imin-1)*b21d(imin+1) ! compute theta(imin) theta( imin ) = atan2( sqrt( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ ),sqrt( b11d(imin)**2_${ik}$+& b11bulge**2_${ik}$ ) ) ! chase the bulges in b11(imin+1,imin) and b21(imin+1,imin) if( b11d(imin)**2_${ik}$+b11bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b11bulge, b11d(imin), rwork(iu1sn+imin-1),rwork(iu1cs+imin-& 1_${ik}$), r ) else if( mu <= nu ) then call stdlib${ii}$_${c2ri(ci)}$lartgs( b11e( imin ), b11d( imin + 1_${ik}$ ), mu,rwork(iu1cs+imin-1), & rwork(iu1sn+imin-1) ) else call stdlib${ii}$_${c2ri(ci)}$lartgs( b12d( imin ), b12e( imin ), nu,rwork(iu1cs+imin-1), rwork(& iu1sn+imin-1) ) end if if( b21d(imin)**2_${ik}$+b21bulge**2_${ik}$ > thresh**2_${ik}$ ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b21bulge, b21d(imin), rwork(iu2sn+imin-1),rwork(iu2cs+imin-& 1_${ik}$), r ) else if( nu < mu ) then call stdlib${ii}$_${c2ri(ci)}$lartgs( b21e( imin ), b21d( imin + 1_${ik}$ ), nu,rwork(iu2cs+imin-1), & rwork(iu2sn+imin-1) ) else call stdlib${ii}$_${c2ri(ci)}$lartgs( b22d(imin), b22e(imin), mu,rwork(iu2cs+imin-1), rwork(iu2sn+& imin-1) ) end if rwork(iu2cs+imin-1) = -rwork(iu2cs+imin-1) rwork(iu2sn+imin-1) = -rwork(iu2sn+imin-1) temp = rwork(iu1cs+imin-1)*b11e(imin) +rwork(iu1sn+imin-1)*b11d(imin+1) b11d(imin+1) = rwork(iu1cs+imin-1)*b11d(imin+1) -rwork(iu1sn+imin-1)*b11e(imin) b11e(imin) = temp if( imax > imin+1 ) then b11bulge = rwork(iu1sn+imin-1)*b11e(imin+1) b11e(imin+1) = rwork(iu1cs+imin-1)*b11e(imin+1) end if temp = rwork(iu1cs+imin-1)*b12d(imin) +rwork(iu1sn+imin-1)*b12e(imin) b12e(imin) = rwork(iu1cs+imin-1)*b12e(imin) -rwork(iu1sn+imin-1)*b12d(imin) b12d(imin) = temp b12bulge = rwork(iu1sn+imin-1)*b12d(imin+1) b12d(imin+1) = rwork(iu1cs+imin-1)*b12d(imin+1) temp = rwork(iu2cs+imin-1)*b21e(imin) +rwork(iu2sn+imin-1)*b21d(imin+1) b21d(imin+1) = rwork(iu2cs+imin-1)*b21d(imin+1) -rwork(iu2sn+imin-1)*b21e(imin) b21e(imin) = temp if( imax > imin+1 ) then b21bulge = rwork(iu2sn+imin-1)*b21e(imin+1) b21e(imin+1) = rwork(iu2cs+imin-1)*b21e(imin+1) end if temp = rwork(iu2cs+imin-1)*b22d(imin) +rwork(iu2sn+imin-1)*b22e(imin) b22e(imin) = rwork(iu2cs+imin-1)*b22e(imin) -rwork(iu2sn+imin-1)*b22d(imin) b22d(imin) = temp b22bulge = rwork(iu2sn+imin-1)*b22d(imin+1) b22d(imin+1) = rwork(iu2cs+imin-1)*b22d(imin+1) ! inner loop: chase bulges from b11(imin,imin+2), ! b12(imin,imin+1), b21(imin,imin+2), and b22(imin,imin+1) to ! bottom-right do i = imin+1, imax-1 ! compute phi(i-1) x1 = sin(theta(i-1))*b11e(i-1) + cos(theta(i-1))*b21e(i-1) x2 = sin(theta(i-1))*b11bulge + cos(theta(i-1))*b21bulge y1 = sin(theta(i-1))*b12d(i-1) + cos(theta(i-1))*b22d(i-1) y2 = sin(theta(i-1))*b12bulge + cos(theta(i-1))*b22bulge phi(i-1) = atan2( sqrt(x1**2_${ik}$+x2**2_${ik}$), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11e(i-1)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21e(i-1)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12d(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i-1,i+1), b12(i-1,i), ! b21(i-1,i+1), and b22(i-1,i). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart21 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( x2, x1, rwork(iv1tsn+i-1),rwork(iv1tcs+i-1), r ) else if( .not. restart11 .and. restart21 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b11bulge, b11e(i-1), rwork(iv1tsn+i-1),rwork(iv1tcs+i-1),& r ) else if( restart11 .and. .not. restart21 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b21bulge, b21e(i-1), rwork(iv1tsn+i-1),rwork(iv1tcs+i-1),& r ) else if( mu <= nu ) then call stdlib${ii}$_${c2ri(ci)}$lartgs( b11d(i), b11e(i), mu, rwork(iv1tcs+i-1),rwork(iv1tsn+i-1)& ) else call stdlib${ii}$_${c2ri(ci)}$lartgs( b21d(i), b21e(i), nu, rwork(iv1tcs+i-1),rwork(iv1tsn+i-1)& ) end if rwork(iv1tcs+i-1) = -rwork(iv1tcs+i-1) rwork(iv1tsn+i-1) = -rwork(iv1tsn+i-1) if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( y2, y1, rwork(iv2tsn+i-1-1),rwork(iv2tcs+i-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b12bulge, b12d(i-1), rwork(iv2tsn+i-1-1),rwork(iv2tcs+i-& 1_${ik}$-1), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b22bulge, b22d(i-1), rwork(iv2tsn+i-1-1),rwork(iv2tcs+i-& 1_${ik}$-1), r ) else if( nu < mu ) then call stdlib${ii}$_${c2ri(ci)}$lartgs( b12e(i-1), b12d(i), nu,rwork(iv2tcs+i-1-1), rwork(iv2tsn+& i-1-1) ) else call stdlib${ii}$_${c2ri(ci)}$lartgs( b22e(i-1), b22d(i), mu,rwork(iv2tcs+i-1-1), rwork(iv2tsn+& i-1-1) ) end if temp = rwork(iv1tcs+i-1)*b11d(i) + rwork(iv1tsn+i-1)*b11e(i) b11e(i) = rwork(iv1tcs+i-1)*b11e(i) -rwork(iv1tsn+i-1)*b11d(i) b11d(i) = temp b11bulge = rwork(iv1tsn+i-1)*b11d(i+1) b11d(i+1) = rwork(iv1tcs+i-1)*b11d(i+1) temp = rwork(iv1tcs+i-1)*b21d(i) + rwork(iv1tsn+i-1)*b21e(i) b21e(i) = rwork(iv1tcs+i-1)*b21e(i) -rwork(iv1tsn+i-1)*b21d(i) b21d(i) = temp b21bulge = rwork(iv1tsn+i-1)*b21d(i+1) b21d(i+1) = rwork(iv1tcs+i-1)*b21d(i+1) temp = rwork(iv2tcs+i-1-1)*b12e(i-1) +rwork(iv2tsn+i-1-1)*b12d(i) b12d(i) = rwork(iv2tcs+i-1-1)*b12d(i) -rwork(iv2tsn+i-1-1)*b12e(i-1) b12e(i-1) = temp b12bulge = rwork(iv2tsn+i-1-1)*b12e(i) b12e(i) = rwork(iv2tcs+i-1-1)*b12e(i) temp = rwork(iv2tcs+i-1-1)*b22e(i-1) +rwork(iv2tsn+i-1-1)*b22d(i) b22d(i) = rwork(iv2tcs+i-1-1)*b22d(i) -rwork(iv2tsn+i-1-1)*b22e(i-1) b22e(i-1) = temp b22bulge = rwork(iv2tsn+i-1-1)*b22e(i) b22e(i) = rwork(iv2tcs+i-1-1)*b22e(i) ! compute theta(i) x1 = cos(phi(i-1))*b11d(i) + sin(phi(i-1))*b12e(i-1) x2 = cos(phi(i-1))*b11bulge + sin(phi(i-1))*b12bulge y1 = cos(phi(i-1))*b21d(i) + sin(phi(i-1))*b22e(i-1) y2 = cos(phi(i-1))*b21bulge + sin(phi(i-1))*b22bulge theta(i) = atan2( sqrt(y1**2_${ik}$+y2**2_${ik}$), sqrt(x1**2_${ik}$+x2**2_${ik}$) ) ! determine if there are bulges to chase or if a new direct ! summand has been reached restart11 = b11d(i)**2_${ik}$ + b11bulge**2_${ik}$ <= thresh**2_${ik}$ restart12 = b12e(i-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart21 = b21d(i)**2_${ik}$ + b21bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22e(i-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ ! if possible, chase bulges from b11(i+1,i), b12(i+1,i-1), ! b21(i+1,i), and b22(i+1,i-1). if necessary, restart bulge- ! chasing by applying the original shift again. if( .not. restart11 .and. .not. restart12 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( x2, x1, rwork(iu1sn+i-1), rwork(iu1cs+i-1),r ) else if( .not. restart11 .and. restart12 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b11bulge, b11d(i), rwork(iu1sn+i-1),rwork(iu1cs+i-1), r ) else if( restart11 .and. .not. restart12 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b12bulge, b12e(i-1), rwork(iu1sn+i-1),rwork(iu1cs+i-1), & r ) else if( mu <= nu ) then call stdlib${ii}$_${c2ri(ci)}$lartgs( b11e(i), b11d(i+1), mu, rwork(iu1cs+i-1),rwork(iu1sn+i-1)& ) else call stdlib${ii}$_${c2ri(ci)}$lartgs( b12d(i), b12e(i), nu, rwork(iu1cs+i-1),rwork(iu1sn+i-1) ) end if if( .not. restart21 .and. .not. restart22 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( y2, y1, rwork(iu2sn+i-1), rwork(iu2cs+i-1),r ) else if( .not. restart21 .and. restart22 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b21bulge, b21d(i), rwork(iu2sn+i-1),rwork(iu2cs+i-1), r ) else if( restart21 .and. .not. restart22 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b22bulge, b22e(i-1), rwork(iu2sn+i-1),rwork(iu2cs+i-1), & r ) else if( nu < mu ) then call stdlib${ii}$_${c2ri(ci)}$lartgs( b21e(i), b21e(i+1), nu, rwork(iu2cs+i-1),rwork(iu2sn+i-1)& ) else call stdlib${ii}$_${c2ri(ci)}$lartgs( b22d(i), b22e(i), mu, rwork(iu2cs+i-1),rwork(iu2sn+i-1) ) end if rwork(iu2cs+i-1) = -rwork(iu2cs+i-1) rwork(iu2sn+i-1) = -rwork(iu2sn+i-1) temp = rwork(iu1cs+i-1)*b11e(i) + rwork(iu1sn+i-1)*b11d(i+1) b11d(i+1) = rwork(iu1cs+i-1)*b11d(i+1) -rwork(iu1sn+i-1)*b11e(i) b11e(i) = temp if( i < imax - 1_${ik}$ ) then b11bulge = rwork(iu1sn+i-1)*b11e(i+1) b11e(i+1) = rwork(iu1cs+i-1)*b11e(i+1) end if temp = rwork(iu2cs+i-1)*b21e(i) + rwork(iu2sn+i-1)*b21d(i+1) b21d(i+1) = rwork(iu2cs+i-1)*b21d(i+1) -rwork(iu2sn+i-1)*b21e(i) b21e(i) = temp if( i < imax - 1_${ik}$ ) then b21bulge = rwork(iu2sn+i-1)*b21e(i+1) b21e(i+1) = rwork(iu2cs+i-1)*b21e(i+1) end if temp = rwork(iu1cs+i-1)*b12d(i) + rwork(iu1sn+i-1)*b12e(i) b12e(i) = rwork(iu1cs+i-1)*b12e(i) -rwork(iu1sn+i-1)*b12d(i) b12d(i) = temp b12bulge = rwork(iu1sn+i-1)*b12d(i+1) b12d(i+1) = rwork(iu1cs+i-1)*b12d(i+1) temp = rwork(iu2cs+i-1)*b22d(i) + rwork(iu2sn+i-1)*b22e(i) b22e(i) = rwork(iu2cs+i-1)*b22e(i) -rwork(iu2sn+i-1)*b22d(i) b22d(i) = temp b22bulge = rwork(iu2sn+i-1)*b22d(i+1) b22d(i+1) = rwork(iu2cs+i-1)*b22d(i+1) end do ! compute phi(imax-1) x1 = sin(theta(imax-1))*b11e(imax-1) +cos(theta(imax-1))*b21e(imax-1) y1 = sin(theta(imax-1))*b12d(imax-1) +cos(theta(imax-1))*b22d(imax-1) y2 = sin(theta(imax-1))*b12bulge + cos(theta(imax-1))*b22bulge phi(imax-1) = atan2( abs(x1), sqrt(y1**2_${ik}$+y2**2_${ik}$) ) ! chase bulges from b12(imax-1,imax) and b22(imax-1,imax) restart12 = b12d(imax-1)**2_${ik}$ + b12bulge**2_${ik}$ <= thresh**2_${ik}$ restart22 = b22d(imax-1)**2_${ik}$ + b22bulge**2_${ik}$ <= thresh**2_${ik}$ if( .not. restart12 .and. .not. restart22 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( y2, y1, rwork(iv2tsn+imax-1-1),rwork(iv2tcs+imax-1-1), r ) else if( .not. restart12 .and. restart22 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b12bulge, b12d(imax-1),rwork(iv2tsn+imax-1-1),rwork(iv2tcs+& imax-1-1), r ) else if( restart12 .and. .not. restart22 ) then call stdlib${ii}$_${c2ri(ci)}$lartgp( b22bulge, b22d(imax-1),rwork(iv2tsn+imax-1-1),rwork(iv2tcs+& imax-1-1), r ) else if( nu < mu ) then call stdlib${ii}$_${c2ri(ci)}$lartgs( b12e(imax-1), b12d(imax), nu,rwork(iv2tcs+imax-1-1),rwork(& iv2tsn+imax-1-1) ) else call stdlib${ii}$_${c2ri(ci)}$lartgs( b22e(imax-1), b22d(imax), mu,rwork(iv2tcs+imax-1-1),rwork(& iv2tsn+imax-1-1) ) end if temp = rwork(iv2tcs+imax-1-1)*b12e(imax-1) +rwork(iv2tsn+imax-1-1)*b12d(imax) b12d(imax) = rwork(iv2tcs+imax-1-1)*b12d(imax) -rwork(iv2tsn+imax-1-1)*b12e(imax-1) b12e(imax-1) = temp temp = rwork(iv2tcs+imax-1-1)*b22e(imax-1) +rwork(iv2tsn+imax-1-1)*b22d(imax) b22d(imax) = rwork(iv2tcs+imax-1-1)*b22d(imax) -rwork(iv2tsn+imax-1-1)*b22e(imax-1) b22e(imax-1) = temp ! update singular vectors if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'F', p, imax-imin+1,rwork(iu1cs+imin-1), rwork(& iu1sn+imin-1),u1(1_${ik}$,imin), ldu1 ) else call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'F', imax-imin+1, p,rwork(iu1cs+imin-1), rwork(& iu1sn+imin-1),u1(imin,1_${ik}$), ldu1 ) end if end if if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'F', m-p, imax-imin+1,rwork(iu2cs+imin-1), rwork(& iu2sn+imin-1),u2(1_${ik}$,imin), ldu2 ) else call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'F', imax-imin+1, m-p,rwork(iu2cs+imin-1), rwork(& iu2sn+imin-1),u2(imin,1_${ik}$), ldu2 ) end if end if if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'F', imax-imin+1, q,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1),v1t(imin,1_${ik}$), ldv1t ) else call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'F', q, imax-imin+1,rwork(iv1tcs+imin-1), rwork(& iv1tsn+imin-1),v1t(1_${ik}$,imin), ldv1t ) end if end if if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_${ci}$lasr( 'L', 'V', 'F', imax-imin+1, m-q,rwork(iv2tcs+imin-1), & rwork(iv2tsn+imin-1),v2t(imin,1_${ik}$), ldv2t ) else call stdlib${ii}$_${ci}$lasr( 'R', 'V', 'F', m-q, imax-imin+1,rwork(iv2tcs+imin-1), & rwork(iv2tsn+imin-1),v2t(1_${ik}$,imin), ldv2t ) end if end if ! fix signs on b11(imax-1,imax) and b21(imax-1,imax) if( b11e(imax-1)+b21e(imax-1) > 0_${ik}$ ) then b11d(imax) = -b11d(imax) b21d(imax) = -b21d(imax) if( wantv1t ) then if( colmajor ) then call stdlib${ii}$_${ci}$scal( q, cnegone, v1t(imax,1_${ik}$), ldv1t ) else call stdlib${ii}$_${ci}$scal( q, cnegone, v1t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! compute theta(imax) x1 = cos(phi(imax-1))*b11d(imax) +sin(phi(imax-1))*b12e(imax-1) y1 = cos(phi(imax-1))*b21d(imax) +sin(phi(imax-1))*b22e(imax-1) theta(imax) = atan2( abs(y1), abs(x1) ) ! fix signs on b11(imax,imax), b12(imax,imax-1), b21(imax,imax), ! and b22(imax,imax-1) if( b11d(imax)+b12e(imax-1) < 0_${ik}$ ) then b12d(imax) = -b12d(imax) if( wantu1 ) then if( colmajor ) then call stdlib${ii}$_${ci}$scal( p, cnegone, u1(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_${ci}$scal( p, cnegone, u1(imax,1_${ik}$), ldu1 ) end if end if end if if( b21d(imax)+b22e(imax-1) > 0_${ik}$ ) then b22d(imax) = -b22d(imax) if( wantu2 ) then if( colmajor ) then call stdlib${ii}$_${ci}$scal( m-p, cnegone, u2(1_${ik}$,imax), 1_${ik}$ ) else call stdlib${ii}$_${ci}$scal( m-p, cnegone, u2(imax,1_${ik}$), ldu2 ) end if end if end if ! fix signs on b12(imax,imax) and b22(imax,imax) if( b12d(imax)+b22d(imax) < 0_${ik}$ ) then if( wantv2t ) then if( colmajor ) then call stdlib${ii}$_${ci}$scal( m-q, cnegone, v2t(imax,1_${ik}$), ldv2t ) else call stdlib${ii}$_${ci}$scal( m-q, cnegone, v2t(1_${ik}$,imax), 1_${ik}$ ) end if end if end if ! test for negligible sines or cosines do i = imin, imax if( theta(i) < thresh ) then theta(i) = zero else if( theta(i) > piover2-thresh ) then theta(i) = piover2 end if end do do i = imin, imax-1 if( phi(i) < thresh ) then phi(i) = zero else if( phi(i) > piover2-thresh ) then phi(i) = piover2 end if end do ! deflate if (imax > 1_${ik}$) then do while( phi(imax-1) == zero ) imax = imax - 1_${ik}$ if (imax <= 1) exit end do end if if( imin > imax - 1_${ik}$ )imin = imax - 1_${ik}$ if (imin > 1_${ik}$) then do while (phi(imin-1) /= zero) imin = imin - 1_${ik}$ if (imin <= 1) exit end do end if ! repeat main iteration loop end do ! postprocessing: order theta from least to greatest do i = 1, q mini = i thetamin = theta(i) do j = i+1, q if( theta(j) < thetamin ) then mini = j thetamin = theta(j) end if end do if( mini /= i ) then theta(mini) = theta(i) theta(i) = thetamin if( colmajor ) then if( wantu1 )call stdlib${ii}$_${ci}$swap( p, u1(1_${ik}$,i), 1_${ik}$, u1(1_${ik}$,mini), 1_${ik}$ ) if( wantu2 )call stdlib${ii}$_${ci}$swap( m-p, u2(1_${ik}$,i), 1_${ik}$, u2(1_${ik}$,mini), 1_${ik}$ ) if( wantv1t )call stdlib${ii}$_${ci}$swap( q, v1t(i,1_${ik}$), ldv1t, v1t(mini,1_${ik}$), ldv1t ) if( wantv2t )call stdlib${ii}$_${ci}$swap( m-q, v2t(i,1_${ik}$), ldv2t, v2t(mini,1_${ik}$),ldv2t ) else if( wantu1 )call stdlib${ii}$_${ci}$swap( p, u1(i,1_${ik}$), ldu1, u1(mini,1_${ik}$), ldu1 ) if( wantu2 )call stdlib${ii}$_${ci}$swap( m-p, u2(i,1_${ik}$), ldu2, u2(mini,1_${ik}$), ldu2 ) if( wantv1t )call stdlib${ii}$_${ci}$swap( q, v1t(1_${ik}$,i), 1_${ik}$, v1t(1_${ik}$,mini), 1_${ik}$ ) if( wantv2t )call stdlib${ii}$_${ci}$swap( m-q, v2t(1_${ik}$,i), 1_${ik}$, v2t(1_${ik}$,mini), 1_${ik}$ ) end if end if end do return end subroutine stdlib${ii}$_${ci}$bbcsd #:endif #:endfor recursive module subroutine stdlib${ii}$_cuncsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, x11, & !! CUNCSD computes the CS decomposition of an M-by-M partitioned !! unitary matrix X: !! [ I 0 0 | 0 0 0 ] !! [ 0 C 0 | 0 -S 0 ] !! [ X11 | X12 ] [ U1 | ] [ 0 0 0 | 0 0 -I ] [ V1 | ]**H !! X = [-----------] = [---------] [---------------------] [---------] . !! [ X21 | X22 ] [ | U2 ] [ 0 0 0 | I 0 0 ] [ | V2 ] !! [ 0 S 0 | 0 C 0 ] !! [ 0 0 I | 0 0 0 ] !! X11 is P-by-Q. The unitary matrices U1, U2, V1, and V2 are P-by-P, !! (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are !! R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in !! which R = MIN(P,M-P,Q,M-Q). ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, & work, lwork, rwork, lrwork,iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12, ldx21, ldx22, & lrwork, lwork, m, p, q ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: theta(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*), work(*) complex(sp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! =================================================================== ! Local Scalars character :: transt, signst integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, itauq2, j, lbbcsdwork, & lbbcsdworkmin, lbbcsdworkopt, lorbdbwork, lorbdbworkmin, lorbdbworkopt, lorglqwork, & lorglqworkmin, lorglqworkopt, lorgqrwork, lorgqrworkmin, lorgqrworkopt, lworkmin, & lworkopt, p1, q1 logical(lk) :: colmajor, defaultsigns, lquery, wantu1, wantu2, wantv1t, wantv2t integer(${ik}$) :: lrworkmin, lrworkopt logical(lk) :: lrquery ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) defaultsigns = .not. stdlib_lsame( signs, 'O' ) lquery = lwork == -1_${ik}$ lrquery = lrwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -7_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -8_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -9_${ik}$ else if ( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -11_${ik}$ else if (.not. colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if (colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if (.not. colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ else if (colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -15_${ik}$ else if (.not. colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -15_${ik}$ else if (colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -17_${ik}$ else if (.not. colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -17_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -20_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -22_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -24_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -26_${ik}$ end if ! work with transpose if convenient if( info == 0_${ik}$ .and. min( p, m-p ) < min( q, m-q ) ) then if( colmajor ) then transt = 'T' else transt = 'N' end if if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_cuncsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,q, p, x11, & ldx11, x21, ldx21, x12, ldx12, x22,ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,& u2, ldu2, work, lwork, rwork, lrwork, iwork,info ) return end if ! work with permutation [ 0 i; i 0 ] * x * [ 0 i; i 0 ] if ! convenient if( info == 0_${ik}$ .and. m-q < q ) then if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_cuncsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,m-p, m-q, x22, & ldx22, x21, ldx21, x12, ldx12, x11,ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, & v1t,ldv1t, work, lwork, rwork, lrwork, iwork, info ) return end if ! compute workspace if( info == 0_${ik}$ ) then ! real workspace iphi = 2_${ik}$ ib11d = iphi + max( 1_${ik}$, q - 1_${ik}$ ) ib11e = ib11d + max( 1_${ik}$, q ) ib12d = ib11e + max( 1_${ik}$, q - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, q ) ib21d = ib12e + max( 1_${ik}$, q - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, q ) ib22d = ib21e + max( 1_${ik}$, q - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, q ) ibbcsd = ib22e + max( 1_${ik}$, q - 1_${ik}$ ) call stdlib${ii}$_cbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, theta, u1, & ldu1, u2, ldu2, v1t, ldv1t,v2t, ldv2t, theta, theta, theta, theta, theta,theta, & theta, theta, rwork, -1_${ik}$, childinfo ) lbbcsdworkopt = int( rwork(1_${ik}$),KIND=${ik}$) lbbcsdworkmin = lbbcsdworkopt lrworkopt = ibbcsd + lbbcsdworkopt - 1_${ik}$ lrworkmin = ibbcsd + lbbcsdworkmin - 1_${ik}$ rwork(1_${ik}$) = lrworkopt ! complex workspace itaup1 = 2_${ik}$ itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m - p ) itauq2 = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_cungqr( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo ) lorgqrworkopt = int( work(1_${ik}$),KIND=${ik}$) lorgqrworkmin = max( 1_${ik}$, m - q ) iorglq = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_cunglq( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo ) lorglqworkopt = int( work(1_${ik}$),KIND=${ik}$) lorglqworkmin = max( 1_${ik}$, m - q ) iorbdb = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_cunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & ldx22, theta, theta, u1, u2,v1t, v2t, work, -1_${ik}$, childinfo ) lorbdbworkopt = int( work(1_${ik}$),KIND=${ik}$) lorbdbworkmin = lorbdbworkopt lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,iorbdb + & lorbdbworkopt ) - 1_${ik}$ lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,iorbdb + & lorbdbworkmin ) - 1_${ik}$ work(1_${ik}$) = max(lworkopt,lworkmin) if( lwork < lworkmin.and. .not. ( lquery .or. lrquery ) ) then info = -22_${ik}$ else if( lrwork < lrworkmin.and. .not. ( lquery .or. lrquery ) ) then info = -24_${ik}$ else lorgqrwork = lwork - iorgqr + 1_${ik}$ lorglqwork = lwork - iorglq + 1_${ik}$ lorbdbwork = lwork - iorbdb + 1_${ik}$ lbbcsdwork = lrwork - ibbcsd + 1_${ik}$ end if end if ! abort if any illegal arguments if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CUNCSD', -info ) return else if( lquery .or. lrquery ) then return end if ! transform to bidiagonal block form call stdlib${ii}$_cunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,ldx21, x22, & ldx22, theta, rwork(iphi), work(itaup1),work(itaup2), work(itauq1), work(itauq2),work(& iorbdb), lorbdbwork, childinfo ) ! accumulate householder reflectors if( colmajor ) then if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_cungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqrwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_cungqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqrwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'U', q-1, q-1, x11(1_${ik}$,2_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = cone do j = 2, q v1t(1_${ik}$,j) = czero v1t(j,1_${ik}$) = czero end do call stdlib${ii}$_cunglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglqwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'U', p, m-q, x12, ldx12, v2t, ldv2t ) if( m-p > q ) then call stdlib${ii}$_clacpy( 'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,v2t(p+1,p+1), & ldv2t ) end if if( m > q ) then call stdlib${ii}$_cunglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorglq), & lorglqwork, info ) end if end if else if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'U', q, p, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_cunglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),lorglqwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'U', q, m-p, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_cunglq( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorglq), lorglqwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', q-1, q-1, x11(2_${ik}$,1_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = cone do j = 2, q v1t(1_${ik}$,j) = czero v1t(j,1_${ik}$) = czero end do call stdlib${ii}$_cungqr( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorgqr), & lorgqrwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then p1 = min( p+1, m ) q1 = min( q+1, m ) call stdlib${ii}$_clacpy( 'L', m-q, p, x12, ldx12, v2t, ldv2t ) if ( m > p+q ) then call stdlib${ii}$_clacpy( 'L', m-p-q, m-p-q, x22(p1,q1), ldx22,v2t(p+1,p+1), ldv2t ) end if call stdlib${ii}$_cungqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorgqr), & lorgqrwork, info ) end if end if ! compute the csd of the matrix in bidiagonal-block form call stdlib${ii}$_cbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,rwork(iphi), & u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, rwork(ib11d), rwork(ib11e), rwork(ib12d),& rwork(ib12e), rwork(ib21d), rwork(ib21e),rwork(ib22d), rwork(ib22e), rwork(ibbcsd),& lbbcsdwork, info ) ! permute rows and columns to place identity submatrices in top- ! left corner of (1,1)-block and/or bottom-right corner of (1,2)- ! block and/or bottom-right corner of (2,1)-block and/or top-left ! corner of (2,2)-block if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do if( colmajor ) then call stdlib${ii}$_clapmt( .false., m-p, m-p, u2, ldu2, iwork ) else call stdlib${ii}$_clapmr( .false., m-p, m-p, u2, ldu2, iwork ) end if end if if( m > 0_${ik}$ .and. wantv2t ) then do i = 1, p iwork(i) = m - p - q + i end do do i = p + 1, m - q iwork(i) = i - p end do if( .not. colmajor ) then call stdlib${ii}$_clapmt( .false., m-q, m-q, v2t, ldv2t, iwork ) else call stdlib${ii}$_clapmr( .false., m-q, m-q, v2t, ldv2t, iwork ) end if end if return ! end stdlib${ii}$_cuncsd end subroutine stdlib${ii}$_cuncsd recursive module subroutine stdlib${ii}$_zuncsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, x11, & !! ZUNCSD computes the CS decomposition of an M-by-M partitioned !! unitary matrix X: !! [ I 0 0 | 0 0 0 ] !! [ 0 C 0 | 0 -S 0 ] !! [ X11 | X12 ] [ U1 | ] [ 0 0 0 | 0 0 -I ] [ V1 | ]**H !! X = [-----------] = [---------] [---------------------] [---------] . !! [ X21 | X22 ] [ | U2 ] [ 0 0 0 | I 0 0 ] [ | V2 ] !! [ 0 S 0 | 0 C 0 ] !! [ 0 0 I | 0 0 0 ] !! X11 is P-by-Q. The unitary matrices U1, U2, V1, and V2 are P-by-P, !! (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are !! R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in !! which R = MIN(P,M-P,Q,M-Q). ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, & work, lwork, rwork, lrwork,iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12, ldx21, ldx22, & lrwork, lwork, m, p, q ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(out) :: theta(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*), work(*) complex(dp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! =================================================================== ! Local Scalars character :: transt, signst integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, itauq2, j, lbbcsdwork, & lbbcsdworkmin, lbbcsdworkopt, lorbdbwork, lorbdbworkmin, lorbdbworkopt, lorglqwork, & lorglqworkmin, lorglqworkopt, lorgqrwork, lorgqrworkmin, lorgqrworkopt, lworkmin, & lworkopt, p1, q1 logical(lk) :: colmajor, defaultsigns, lquery, wantu1, wantu2, wantv1t, wantv2t integer(${ik}$) :: lrworkmin, lrworkopt logical(lk) :: lrquery ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) defaultsigns = .not. stdlib_lsame( signs, 'O' ) lquery = lwork == -1_${ik}$ lrquery = lrwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -7_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -8_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -9_${ik}$ else if ( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -11_${ik}$ else if (.not. colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if (colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if (.not. colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ else if (colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -15_${ik}$ else if (.not. colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -15_${ik}$ else if (colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -17_${ik}$ else if (.not. colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -17_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -20_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -22_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -24_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -26_${ik}$ end if ! work with transpose if convenient if( info == 0_${ik}$ .and. min( p, m-p ) < min( q, m-q ) ) then if( colmajor ) then transt = 'T' else transt = 'N' end if if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_zuncsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,q, p, x11, & ldx11, x21, ldx21, x12, ldx12, x22,ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,& u2, ldu2, work, lwork, rwork, lrwork, iwork,info ) return end if ! work with permutation [ 0 i; i 0 ] * x * [ 0 i; i 0 ] if ! convenient if( info == 0_${ik}$ .and. m-q < q ) then if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_zuncsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,m-p, m-q, x22, & ldx22, x21, ldx21, x12, ldx12, x11,ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, & v1t,ldv1t, work, lwork, rwork, lrwork, iwork, info ) return end if ! compute workspace if( info == 0_${ik}$ ) then ! real workspace iphi = 2_${ik}$ ib11d = iphi + max( 1_${ik}$, q - 1_${ik}$ ) ib11e = ib11d + max( 1_${ik}$, q ) ib12d = ib11e + max( 1_${ik}$, q - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, q ) ib21d = ib12e + max( 1_${ik}$, q - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, q ) ib22d = ib21e + max( 1_${ik}$, q - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, q ) ibbcsd = ib22e + max( 1_${ik}$, q - 1_${ik}$ ) call stdlib${ii}$_zbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, theta, u1, & ldu1, u2, ldu2, v1t, ldv1t,v2t, ldv2t, theta, theta, theta, theta, theta,theta, & theta, theta, rwork, -1_${ik}$, childinfo ) lbbcsdworkopt = int( rwork(1_${ik}$),KIND=${ik}$) lbbcsdworkmin = lbbcsdworkopt lrworkopt = ibbcsd + lbbcsdworkopt - 1_${ik}$ lrworkmin = ibbcsd + lbbcsdworkmin - 1_${ik}$ rwork(1_${ik}$) = lrworkopt ! complex workspace itaup1 = 2_${ik}$ itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m - p ) itauq2 = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_zungqr( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo ) lorgqrworkopt = int( work(1_${ik}$),KIND=${ik}$) lorgqrworkmin = max( 1_${ik}$, m - q ) iorglq = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_zunglq( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo ) lorglqworkopt = int( work(1_${ik}$),KIND=${ik}$) lorglqworkmin = max( 1_${ik}$, m - q ) iorbdb = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_zunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & ldx22, theta, theta, u1, u2,v1t, v2t, work, -1_${ik}$, childinfo ) lorbdbworkopt = int( work(1_${ik}$),KIND=${ik}$) lorbdbworkmin = lorbdbworkopt lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,iorbdb + & lorbdbworkopt ) - 1_${ik}$ lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,iorbdb + & lorbdbworkmin ) - 1_${ik}$ work(1_${ik}$) = max(lworkopt,lworkmin) if( lwork < lworkmin.and. .not. ( lquery .or. lrquery ) ) then info = -22_${ik}$ else if( lrwork < lrworkmin.and. .not. ( lquery .or. lrquery ) ) then info = -24_${ik}$ else lorgqrwork = lwork - iorgqr + 1_${ik}$ lorglqwork = lwork - iorglq + 1_${ik}$ lorbdbwork = lwork - iorbdb + 1_${ik}$ lbbcsdwork = lrwork - ibbcsd + 1_${ik}$ end if end if ! abort if any illegal arguments if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNCSD', -info ) return else if( lquery .or. lrquery ) then return end if ! transform to bidiagonal block form call stdlib${ii}$_zunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,ldx21, x22, & ldx22, theta, rwork(iphi), work(itaup1),work(itaup2), work(itauq1), work(itauq2),work(& iorbdb), lorbdbwork, childinfo ) ! accumulate householder reflectors if( colmajor ) then if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_zungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqrwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_zungqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqrwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'U', q-1, q-1, x11(1_${ik}$,2_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = cone do j = 2, q v1t(1_${ik}$,j) = czero v1t(j,1_${ik}$) = czero end do call stdlib${ii}$_zunglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglqwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'U', p, m-q, x12, ldx12, v2t, ldv2t ) if( m-p > q) then call stdlib${ii}$_zlacpy( 'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,v2t(p+1,p+1), & ldv2t ) end if if( m > q ) then call stdlib${ii}$_zunglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorglq), & lorglqwork, info ) end if end if else if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'U', q, p, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_zunglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),lorglqwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'U', q, m-p, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_zunglq( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorglq), lorglqwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', q-1, q-1, x11(2_${ik}$,1_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = cone do j = 2, q v1t(1_${ik}$,j) = czero v1t(j,1_${ik}$) = czero end do call stdlib${ii}$_zungqr( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorgqr), & lorgqrwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then p1 = min( p+1, m ) q1 = min( q+1, m ) call stdlib${ii}$_zlacpy( 'L', m-q, p, x12, ldx12, v2t, ldv2t ) if( m > p+q ) then call stdlib${ii}$_zlacpy( 'L', m-p-q, m-p-q, x22(p1,q1), ldx22,v2t(p+1,p+1), ldv2t ) end if call stdlib${ii}$_zungqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorgqr), & lorgqrwork, info ) end if end if ! compute the csd of the matrix in bidiagonal-block form call stdlib${ii}$_zbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,rwork(iphi), & u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, rwork(ib11d), rwork(ib11e), rwork(ib12d),& rwork(ib12e), rwork(ib21d), rwork(ib21e),rwork(ib22d), rwork(ib22e), rwork(ibbcsd),& lbbcsdwork, info ) ! permute rows and columns to place identity submatrices in top- ! left corner of (1,1)-block and/or bottom-right corner of (1,2)- ! block and/or bottom-right corner of (2,1)-block and/or top-left ! corner of (2,2)-block if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do if( colmajor ) then call stdlib${ii}$_zlapmt( .false., m-p, m-p, u2, ldu2, iwork ) else call stdlib${ii}$_zlapmr( .false., m-p, m-p, u2, ldu2, iwork ) end if end if if( m > 0_${ik}$ .and. wantv2t ) then do i = 1, p iwork(i) = m - p - q + i end do do i = p + 1, m - q iwork(i) = i - p end do if( .not. colmajor ) then call stdlib${ii}$_zlapmt( .false., m-q, m-q, v2t, ldv2t, iwork ) else call stdlib${ii}$_zlapmr( .false., m-q, m-q, v2t, ldv2t, iwork ) end if end if return ! end stdlib${ii}$_zuncsd end subroutine stdlib${ii}$_zuncsd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] recursive module subroutine stdlib${ii}$_${ci}$uncsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, x11, & !! ZUNCSD: computes the CS decomposition of an M-by-M partitioned !! unitary matrix X: !! [ I 0 0 | 0 0 0 ] !! [ 0 C 0 | 0 -S 0 ] !! [ X11 | X12 ] [ U1 | ] [ 0 0 0 | 0 0 -I ] [ V1 | ]**H !! X = [-----------] = [---------] [---------------------] [---------] . !! [ X21 | X22 ] [ | U2 ] [ 0 0 0 | I 0 0 ] [ | V2 ] !! [ 0 S 0 | 0 C 0 ] !! [ 0 0 I | 0 0 0 ] !! X11 is P-by-Q. The unitary matrices U1, U2, V1, and V2 are P-by-P, !! (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are !! R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in !! which R = MIN(P,M-P,Q,M-Q). ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, & work, lwork, rwork, lrwork,iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t, jobv2t, signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12, ldx21, ldx22, & lrwork, lwork, m, p, q ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(out) :: theta(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*), work(*) complex(${ck}$), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! =================================================================== ! Local Scalars character :: transt, signst integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, itauq2, j, lbbcsdwork, & lbbcsdworkmin, lbbcsdworkopt, lorbdbwork, lorbdbworkmin, lorbdbworkopt, lorglqwork, & lorglqworkmin, lorglqworkopt, lorgqrwork, lorgqrworkmin, lorgqrworkopt, lworkmin, & lworkopt, p1, q1 logical(lk) :: colmajor, defaultsigns, lquery, wantu1, wantu2, wantv1t, wantv2t integer(${ik}$) :: lrworkmin, lrworkopt logical(lk) :: lrquery ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) wantv2t = stdlib_lsame( jobv2t, 'Y' ) colmajor = .not. stdlib_lsame( trans, 'T' ) defaultsigns = .not. stdlib_lsame( signs, 'O' ) lquery = lwork == -1_${ik}$ lrquery = lrwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -7_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -8_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -9_${ik}$ else if ( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -11_${ik}$ else if (.not. colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if (colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if (.not. colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ else if (colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -15_${ik}$ else if (.not. colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -15_${ik}$ else if (colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -17_${ik}$ else if (.not. colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -17_${ik}$ else if( wantu1 .and. ldu1 < p ) then info = -20_${ik}$ else if( wantu2 .and. ldu2 < m-p ) then info = -22_${ik}$ else if( wantv1t .and. ldv1t < q ) then info = -24_${ik}$ else if( wantv2t .and. ldv2t < m-q ) then info = -26_${ik}$ end if ! work with transpose if convenient if( info == 0_${ik}$ .and. min( p, m-p ) < min( q, m-q ) ) then if( colmajor ) then transt = 'T' else transt = 'N' end if if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_${ci}$uncsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,q, p, x11, & ldx11, x21, ldx21, x12, ldx12, x22,ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,& u2, ldu2, work, lwork, rwork, lrwork, iwork,info ) return end if ! work with permutation [ 0 i; i 0 ] * x * [ 0 i; i 0 ] if ! convenient if( info == 0_${ik}$ .and. m-q < q ) then if( defaultsigns ) then signst = 'O' else signst = 'D' end if call stdlib${ii}$_${ci}$uncsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,m-p, m-q, x22, & ldx22, x21, ldx21, x12, ldx12, x11,ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, & v1t,ldv1t, work, lwork, rwork, lrwork, iwork, info ) return end if ! compute workspace if( info == 0_${ik}$ ) then ! real workspace iphi = 2_${ik}$ ib11d = iphi + max( 1_${ik}$, q - 1_${ik}$ ) ib11e = ib11d + max( 1_${ik}$, q ) ib12d = ib11e + max( 1_${ik}$, q - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, q ) ib21d = ib12e + max( 1_${ik}$, q - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, q ) ib22d = ib21e + max( 1_${ik}$, q - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, q ) ibbcsd = ib22e + max( 1_${ik}$, q - 1_${ik}$ ) call stdlib${ii}$_${ci}$bbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, theta, u1, & ldu1, u2, ldu2, v1t, ldv1t,v2t, ldv2t, theta, theta, theta, theta, theta,theta, & theta, theta, rwork, -1_${ik}$, childinfo ) lbbcsdworkopt = int( rwork(1_${ik}$),KIND=${ik}$) lbbcsdworkmin = lbbcsdworkopt lrworkopt = ibbcsd + lbbcsdworkopt - 1_${ik}$ lrworkmin = ibbcsd + lbbcsdworkmin - 1_${ik}$ rwork(1_${ik}$) = lrworkopt ! complex workspace itaup1 = 2_${ik}$ itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m - p ) itauq2 = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_${ci}$ungqr( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo ) lorgqrworkopt = int( work(1_${ik}$),KIND=${ik}$) lorgqrworkmin = max( 1_${ik}$, m - q ) iorglq = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_${ci}$unglq( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo ) lorglqworkopt = int( work(1_${ik}$),KIND=${ik}$) lorglqworkmin = max( 1_${ik}$, m - q ) iorbdb = itauq2 + max( 1_${ik}$, m - q ) call stdlib${ii}$_${ci}$unbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & ldx22, theta, theta, u1, u2,v1t, v2t, work, -1_${ik}$, childinfo ) lorbdbworkopt = int( work(1_${ik}$),KIND=${ik}$) lorbdbworkmin = lorbdbworkopt lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,iorbdb + & lorbdbworkopt ) - 1_${ik}$ lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,iorbdb + & lorbdbworkmin ) - 1_${ik}$ work(1_${ik}$) = max(lworkopt,lworkmin) if( lwork < lworkmin.and. .not. ( lquery .or. lrquery ) ) then info = -22_${ik}$ else if( lrwork < lrworkmin.and. .not. ( lquery .or. lrquery ) ) then info = -24_${ik}$ else lorgqrwork = lwork - iorgqr + 1_${ik}$ lorglqwork = lwork - iorglq + 1_${ik}$ lorbdbwork = lwork - iorbdb + 1_${ik}$ lbbcsdwork = lrwork - ibbcsd + 1_${ik}$ end if end if ! abort if any illegal arguments if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNCSD', -info ) return else if( lquery .or. lrquery ) then return end if ! transform to bidiagonal block form call stdlib${ii}$_${ci}$unbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,ldx21, x22, & ldx22, theta, rwork(iphi), work(itaup1),work(itaup2), work(itauq1), work(itauq2),work(& iorbdb), lorbdbwork, childinfo ) ! accumulate householder reflectors if( colmajor ) then if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_${ci}$ungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqrwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_${ci}$ungqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqrwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'U', q-1, q-1, x11(1_${ik}$,2_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = cone do j = 2, q v1t(1_${ik}$,j) = czero v1t(j,1_${ik}$) = czero end do call stdlib${ii}$_${ci}$unglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglqwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'U', p, m-q, x12, ldx12, v2t, ldv2t ) if( m-p > q) then call stdlib${ii}$_${ci}$lacpy( 'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,v2t(p+1,p+1), & ldv2t ) end if if( m > q ) then call stdlib${ii}$_${ci}$unglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorglq), & lorglqwork, info ) end if end if else if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'U', q, p, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_${ci}$unglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),lorglqwork, & info) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'U', q, m-p, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_${ci}$unglq( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorglq), lorglqwork,& info ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', q-1, q-1, x11(2_${ik}$,1_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t ) v1t(1_${ik}$, 1_${ik}$) = cone do j = 2, q v1t(1_${ik}$,j) = czero v1t(j,1_${ik}$) = czero end do call stdlib${ii}$_${ci}$ungqr( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorgqr), & lorgqrwork, info ) end if if( wantv2t .and. m-q > 0_${ik}$ ) then p1 = min( p+1, m ) q1 = min( q+1, m ) call stdlib${ii}$_${ci}$lacpy( 'L', m-q, p, x12, ldx12, v2t, ldv2t ) if( m > p+q ) then call stdlib${ii}$_${ci}$lacpy( 'L', m-p-q, m-p-q, x22(p1,q1), ldx22,v2t(p+1,p+1), ldv2t ) end if call stdlib${ii}$_${ci}$ungqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorgqr), & lorgqrwork, info ) end if end if ! compute the csd of the matrix in bidiagonal-block form call stdlib${ii}$_${ci}$bbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,rwork(iphi), & u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, rwork(ib11d), rwork(ib11e), rwork(ib12d),& rwork(ib12e), rwork(ib21d), rwork(ib21e),rwork(ib22d), rwork(ib22e), rwork(ibbcsd),& lbbcsdwork, info ) ! permute rows and columns to place identity submatrices in top- ! left corner of (1,1)-block and/or bottom-right corner of (1,2)- ! block and/or bottom-right corner of (2,1)-block and/or top-left ! corner of (2,2)-block if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do if( colmajor ) then call stdlib${ii}$_${ci}$lapmt( .false., m-p, m-p, u2, ldu2, iwork ) else call stdlib${ii}$_${ci}$lapmr( .false., m-p, m-p, u2, ldu2, iwork ) end if end if if( m > 0_${ik}$ .and. wantv2t ) then do i = 1, p iwork(i) = m - p - q + i end do do i = p + 1, m - q iwork(i) = i - p end do if( .not. colmajor ) then call stdlib${ii}$_${ci}$lapmt( .false., m-q, m-q, v2t, ldv2t, iwork ) else call stdlib${ii}$_${ci}$lapmr( .false., m-q, m-q, v2t, ldv2t, iwork ) end if end if return ! end stdlib${ii}$_${ci}$uncsd end subroutine stdlib${ii}$_${ci}$uncsd #:endif #:endfor module subroutine stdlib${ii}$_cuncsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta, & !! CUNCSD2BY1 computes the CS decomposition of an M-by-Q matrix X with !! orthonormal columns that has been partitioned into a 2-by-1 block !! structure: !! [ I1 0 0 ] !! [ 0 C 0 ] !! [ X11 ] [ U1 | ] [ 0 0 0 ] !! X = [-----] = [---------] [----------] V1**T . !! [ X21 ] [ | U2 ] [ 0 0 0 ] !! [ 0 S 0 ] !! [ 0 0 I2] !! X11 is P-by-Q. The unitary matrices U1, U2, and V1 are P-by-P, !! (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R !! nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which !! R = MIN(P,M-P,Q,M-Q). I1 is a K1-by-K1 identity matrix and I2 is a !! K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0). u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, rwork, lrwork, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, lwork, ldx11, ldx21, m, p, q integer(${ik}$), intent(in) :: lrwork integer(${ik}$) :: lrworkmin, lrworkopt ! Array Arguments real(sp), intent(out) :: rwork(*) real(sp), intent(out) :: theta(*) complex(sp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), work(*) complex(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, j, lbbcsd, lorbdb, & lorglq, lorglqmin, lorglqopt, lorgqr, lorgqrmin, lorgqropt, lworkmin, lworkopt, & r logical(lk) :: lquery, wantu1, wantu2, wantv1t ! Local Arrays real(sp) :: dum(1_${ik}$) complex(sp) :: cdum(1_${ik}$,1_${ik}$) ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) lquery = ( lwork==-1_${ik}$ ) .or. ( lrwork==-1_${ik}$ ) if( m < 0_${ik}$ ) then info = -4_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -5_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -6_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -8_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -10_${ik}$ else if( wantu1 .and. ldu1 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if( wantu2 .and. ldu2 < max( 1_${ik}$, m - p ) ) then info = -15_${ik}$ else if( wantv1t .and. ldv1t < max( 1_${ik}$, q ) ) then info = -17_${ik}$ end if r = min( p, m-p, q, m-q ) ! compute workspace ! work layout: ! |-----------------------------------------| ! | lworkopt (1) | ! |-----------------------------------------| ! | taup1 (max(1,p)) | ! | taup2 (max(1,m-p)) | ! | tauq1 (max(1,q)) | ! |-----------------------------------------| ! | stdlib${ii}$_cunbdb work | stdlib${ii}$_cungqr work | stdlib${ii}$_cunglq work | ! | | | | ! | | | | ! | | | | ! | | | | ! |-----------------------------------------| ! rwork layout: ! |------------------| ! | lrworkopt (1) | ! |------------------| ! | phi (max(1,r-1)) | ! |------------------| ! | b11d (r) | ! | b11e (r-1) | ! | b12d (r) | ! | b12e (r-1) | ! | b21d (r) | ! | b21e (r-1) | ! | b22d (r) | ! | b22e (r-1) | ! | stdlib${ii}$_cbbcsd rwork | ! |------------------| if( info == 0_${ik}$ ) then iphi = 2_${ik}$ ib11d = iphi + max( 1_${ik}$, r-1 ) ib11e = ib11d + max( 1_${ik}$, r ) ib12d = ib11e + max( 1_${ik}$, r - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, r ) ib21d = ib12e + max( 1_${ik}$, r - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, r ) ib22d = ib21e + max( 1_${ik}$, r - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, r ) ibbcsd = ib22e + max( 1_${ik}$, r - 1_${ik}$ ) itaup1 = 2_${ik}$ itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m-p ) iorbdb = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq1 + max( 1_${ik}$, q ) iorglq = itauq1 + max( 1_${ik}$, q ) lorgqrmin = 1_${ik}$ lorgqropt = 1_${ik}$ lorglqmin = 1_${ik}$ lorglqopt = 1_${ik}$ if( r == q ) then call stdlib${ii}$_cunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,dum, cdum, cdum, & cdum, work, -1_${ik}$,childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_cungqr( p, p, q, u1, ldu1, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) endif if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_cungqr( m-p, m-p, q, u2, ldu2, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_cunglq( q-1, q-1, q-1, v1t, ldv1t,cdum, work(1_${ik}$), -1_${ik}$, childinfo ) lorglqmin = max( lorglqmin, q-1 ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_cbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,dum(1_${ik}$), u1, & ldu1, u2, ldu2, v1t, ldv1t, cdum,1_${ik}$, dum, dum, dum, dum, dum, dum, dum, dum,rwork(& 1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) else if( r == p ) then call stdlib${ii}$_cunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, dum,cdum, cdum, & cdum, work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_cungqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, cdum, work(1_${ik}$),-1_${ik}$, childinfo & ) lorgqrmin = max( lorgqrmin, p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_cungqr( m-p, m-p, q, u2, ldu2, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_cunglq( q, q, r, v1t, ldv1t, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_cbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,dum, v1t, & ldv1t, cdum, 1_${ik}$, u1, ldu1, u2, ldu2,dum, dum, dum, dum, dum, dum, dum, dum,rwork(& 1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) else if( r == m-p ) then call stdlib${ii}$_cunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, dum,cdum, cdum, & cdum, work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_cungqr( p, p, q, u1, ldu1, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_cungqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2, cdum,work(1_${ik}$), -1_${ik}$, & childinfo ) lorgqrmin = max( lorgqrmin, m-p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_cunglq( q, q, r, v1t, ldv1t, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_cbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, dum, cdum,& 1_${ik}$, v1t, ldv1t, u2, ldu2, u1,ldu1, dum, dum, dum, dum, dum, dum, dum, dum,rwork(& 1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) else call stdlib${ii}$_cunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, dum,cdum, cdum, & cdum, cdum, work(1_${ik}$), -1_${ik}$, childinfo) lorbdb = m + int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_cungqr( p, p, m-q, u1, ldu1, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_cungqr( m-p, m-p, m-q, u2, ldu2, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_cunglq( q, q, q, v1t, ldv1t, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_cbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, dum, u2, & ldu2, u1, ldu1, cdum, 1_${ik}$, v1t,ldv1t, dum, dum, dum, dum, dum, dum, dum, dum,rwork(& 1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) end if lrworkmin = ibbcsd+lbbcsd-1 lrworkopt = lrworkmin rwork(1_${ik}$) = lrworkopt lworkmin = max( iorbdb+lorbdb-1,iorgqr+lorgqrmin-1,iorglq+lorglqmin-1 ) lworkopt = max( iorbdb+lorbdb-1,iorgqr+lorgqropt-1,iorglq+lorglqopt-1 ) work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -19_${ik}$ end if if( lrwork < lrworkmin .and. .not.lquery ) then info = -21_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CUNCSD2BY1', -info ) return else if( lquery ) then return end if lorgqr = lwork-iorgqr+1 lorglq = lwork-iorglq+1 ! handle four cases separately: r = q, r = p, r = m-p, and r = m-q, ! in which r = min(p,m-p,q,m-q) if( r == q ) then ! case 1: r = q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_cunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_cungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_cungqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then v1t(1_${ik}$,1_${ik}$) = cone do j = 2, q v1t(1_${ik}$,j) = czero v1t(j,1_${ik}$) = czero end do call stdlib${ii}$_clacpy( 'U', q-1, q-1, x21(1_${ik}$,2_${ik}$), ldx21, v1t(2_${ik}$,2_${ik}$),ldv1t ) call stdlib${ii}$_cunglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglq, childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_cbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,rwork(iphi), u1, & ldu1, u2, ldu2, v1t, ldv1t, cdum,1_${ik}$, rwork(ib11d), rwork(ib11e), rwork(ib12d),rwork(& ib12e), rwork(ib21d), rwork(ib21e),rwork(ib22d), rwork(ib22e), rwork(ibbcsd),lrwork-& ibbcsd+1, childinfo ) ! permute rows and columns to place czero submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_clapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == p ) then ! case 2: r = p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_cunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then u1(1_${ik}$,1_${ik}$) = cone do j = 2, p u1(1_${ik}$,j) = czero u1(j,1_${ik}$) = czero end do call stdlib${ii}$_clacpy( 'L', p-1, p-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$), ldu1 ) call stdlib${ii}$_cungqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, work(itaup1),work(iorgqr), & lorgqr, childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_cungqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'U', p, q, x11, ldx11, v1t, ldv1t ) call stdlib${ii}$_cunglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_cbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,rwork(iphi), v1t,& ldv1t, cdum, 1_${ik}$, u1, ldu1, u2,ldu2, rwork(ib11d), rwork(ib11e), rwork(ib12d),rwork(& ib12e), rwork(ib21d), rwork(ib21e),rwork(ib22d), rwork(ib22e), rwork(ibbcsd), & lbbcsd,childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_clapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == m-p ) then ! case 3: r = m-p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_cunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_cungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then u2(1_${ik}$,1_${ik}$) = cone do j = 2, m-p u2(1_${ik}$,j) = czero u2(j,1_${ik}$) = czero end do call stdlib${ii}$_clacpy( 'L', m-p-1, m-p-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_cungqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,work(itaup2), work(iorgqr)& , lorgqr, childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'U', m-p, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_cunglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_cbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, rwork(iphi), & cdum, 1_${ik}$, v1t, ldv1t, u2, ldu2,u1, ldu1, rwork(ib11d), rwork(ib11e),rwork(ib12d), & rwork(ib12e), rwork(ib21d),rwork(ib21e), rwork(ib22d), rwork(ib22e),rwork(ibbcsd), & lbbcsd, childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > r ) then do i = 1, r iwork(i) = q - r + i end do do i = r + 1, q iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_clapmt( .false., p, q, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_clapmr( .false., q, q, v1t, ldv1t, iwork ) end if end if else ! case 4: r = m-q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_cunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), work(iorbdb+m),lorbdb-m, & childinfo ) ! accumulate householder reflectors if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_ccopy( m-p, work(iorbdb+p), 1_${ik}$, u2, 1_${ik}$ ) end if if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_ccopy( p, work(iorbdb), 1_${ik}$, u1, 1_${ik}$ ) do j = 2, p u1(1_${ik}$,j) = czero end do call stdlib${ii}$_clacpy( 'L', p-1, m-q-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$),ldu1 ) call stdlib${ii}$_cungqr( p, p, m-q, u1, ldu1, work(itaup1),work(iorgqr), lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then do j = 2, m-p u2(1_${ik}$,j) = czero end do call stdlib${ii}$_clacpy( 'L', m-p-1, m-q-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_cungqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_clacpy( 'U', m-q, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_clacpy( 'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,v1t(m-q+1,m-q+& 1_${ik}$), ldv1t ) call stdlib${ii}$_clacpy( 'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,v1t(p+1,p+1), ldv1t ) call stdlib${ii}$_cunglq( q, q, q, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_cbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, rwork(iphi), & u2, ldu2, u1, ldu1, cdum, 1_${ik}$,v1t, ldv1t, rwork(ib11d), rwork(ib11e),rwork(ib12d), & rwork(ib12e), rwork(ib21d),rwork(ib21e), rwork(ib22d), rwork(ib22e),rwork(ibbcsd), & lbbcsd, childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( p > r ) then do i = 1, r iwork(i) = p - r + i end do do i = r + 1, p iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_clapmt( .false., p, p, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_clapmr( .false., p, q, v1t, ldv1t, iwork ) end if end if end if return end subroutine stdlib${ii}$_cuncsd2by1 module subroutine stdlib${ii}$_zuncsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta, & !! ZUNCSD2BY1 computes the CS decomposition of an M-by-Q matrix X with !! orthonormal columns that has been partitioned into a 2-by-1 block !! structure: !! [ I1 0 0 ] !! [ 0 C 0 ] !! [ X11 ] [ U1 | ] [ 0 0 0 ] !! X = [-----] = [---------] [----------] V1**T . !! [ X21 ] [ | U2 ] [ 0 0 0 ] !! [ 0 S 0 ] !! [ 0 0 I2] !! X11 is P-by-Q. The unitary matrices U1, U2, and V1 are P-by-P, !! (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R !! nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which !! R = MIN(P,M-P,Q,M-Q). I1 is a K1-by-K1 identity matrix and I2 is a !! K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0). u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, rwork, lrwork, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, lwork, ldx11, ldx21, m, p, q integer(${ik}$), intent(in) :: lrwork integer(${ik}$) :: lrworkmin, lrworkopt ! Array Arguments real(dp), intent(out) :: rwork(*) real(dp), intent(out) :: theta(*) complex(dp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), work(*) complex(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, j, lbbcsd, lorbdb, & lorglq, lorglqmin, lorglqopt, lorgqr, lorgqrmin, lorgqropt, lworkmin, lworkopt, & r logical(lk) :: lquery, wantu1, wantu2, wantv1t ! Local Arrays real(dp) :: dum(1_${ik}$) complex(dp) :: cdum(1_${ik}$,1_${ik}$) ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) lquery = ( lwork==-1_${ik}$ ) .or. ( lrwork==-1_${ik}$ ) if( m < 0_${ik}$ ) then info = -4_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -5_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -6_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -8_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -10_${ik}$ else if( wantu1 .and. ldu1 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if( wantu2 .and. ldu2 < max( 1_${ik}$, m - p ) ) then info = -15_${ik}$ else if( wantv1t .and. ldv1t < max( 1_${ik}$, q ) ) then info = -17_${ik}$ end if r = min( p, m-p, q, m-q ) ! compute workspace ! work layout: ! |-----------------------------------------| ! | lworkopt (1) | ! |-----------------------------------------| ! | taup1 (max(1,p)) | ! | taup2 (max(1,m-p)) | ! | tauq1 (max(1,q)) | ! |-----------------------------------------| ! | stdlib${ii}$_zunbdb work | stdlib${ii}$_zungqr work | stdlib${ii}$_zunglq work | ! | | | | ! | | | | ! | | | | ! | | | | ! |-----------------------------------------| ! rwork layout: ! |------------------| ! | lrworkopt (1) | ! |------------------| ! | phi (max(1,r-1)) | ! |------------------| ! | b11d (r) | ! | b11e (r-1) | ! | b12d (r) | ! | b12e (r-1) | ! | b21d (r) | ! | b21e (r-1) | ! | b22d (r) | ! | b22e (r-1) | ! | stdlib${ii}$_zbbcsd rwork | ! |------------------| if( info == 0_${ik}$ ) then iphi = 2_${ik}$ ib11d = iphi + max( 1_${ik}$, r-1 ) ib11e = ib11d + max( 1_${ik}$, r ) ib12d = ib11e + max( 1_${ik}$, r - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, r ) ib21d = ib12e + max( 1_${ik}$, r - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, r ) ib22d = ib21e + max( 1_${ik}$, r - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, r ) ibbcsd = ib22e + max( 1_${ik}$, r - 1_${ik}$ ) itaup1 = 2_${ik}$ itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m-p ) iorbdb = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq1 + max( 1_${ik}$, q ) iorglq = itauq1 + max( 1_${ik}$, q ) lorgqrmin = 1_${ik}$ lorgqropt = 1_${ik}$ lorglqmin = 1_${ik}$ lorglqopt = 1_${ik}$ if( r == q ) then call stdlib${ii}$_zunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, dum,cdum, cdum, & cdum, work, -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_zungqr( p, p, q, u1, ldu1, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) endif if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_zungqr( m-p, m-p, q, u2, ldu2, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_zunglq( q-1, q-1, q-1, v1t, ldv1t,cdum, work(1_${ik}$), -1_${ik}$, childinfo ) lorglqmin = max( lorglqmin, q-1 ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_zbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,dum, u1, ldu1,& u2, ldu2, v1t, ldv1t, cdum, 1_${ik}$,dum, dum, dum, dum, dum, dum, dum, dum,rwork(1_${ik}$), -& 1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) else if( r == p ) then call stdlib${ii}$_zunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, dum,cdum, cdum, & cdum, work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_zungqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, cdum, work(1_${ik}$),-1_${ik}$, childinfo & ) lorgqrmin = max( lorgqrmin, p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_zungqr( m-p, m-p, q, u2, ldu2, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_zunglq( q, q, r, v1t, ldv1t, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_zbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,dum, v1t, & ldv1t, cdum, 1_${ik}$, u1, ldu1, u2, ldu2,dum, dum, dum, dum, dum, dum, dum, dum,rwork(& 1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) else if( r == m-p ) then call stdlib${ii}$_zunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, dum,cdum, cdum, & cdum, work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_zungqr( p, p, q, u1, ldu1, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_zungqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2, cdum,work(1_${ik}$), -1_${ik}$, & childinfo ) lorgqrmin = max( lorgqrmin, m-p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_zunglq( q, q, r, v1t, ldv1t, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_zbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, dum, cdum,& 1_${ik}$, v1t, ldv1t, u2, ldu2, u1,ldu1, dum, dum, dum, dum, dum, dum, dum, dum,rwork(& 1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) else call stdlib${ii}$_zunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, dum,cdum, cdum, & cdum, cdum, work(1_${ik}$), -1_${ik}$, childinfo) lorbdb = m + int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_zungqr( p, p, m-q, u1, ldu1, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_zungqr( m-p, m-p, m-q, u2, ldu2, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_zunglq( q, q, q, v1t, ldv1t, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_zbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, dum, u2, & ldu2, u1, ldu1, cdum, 1_${ik}$, v1t,ldv1t, dum, dum, dum, dum, dum, dum, dum, dum,rwork(& 1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) end if lrworkmin = ibbcsd+lbbcsd-1 lrworkopt = lrworkmin rwork(1_${ik}$) = lrworkopt lworkmin = max( iorbdb+lorbdb-1,iorgqr+lorgqrmin-1,iorglq+lorglqmin-1 ) lworkopt = max( iorbdb+lorbdb-1,iorgqr+lorgqropt-1,iorglq+lorglqopt-1 ) work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -19_${ik}$ end if if( lrwork < lrworkmin .and. .not.lquery ) then info = -21_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNCSD2BY1', -info ) return else if( lquery ) then return end if lorgqr = lwork-iorgqr+1 lorglq = lwork-iorglq+1 ! handle four cases separately: r = q, r = p, r = m-p, and r = m-q, ! in which r = min(p,m-p,q,m-q) if( r == q ) then ! case 1: r = q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_zunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_zungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_zungqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then v1t(1_${ik}$,1_${ik}$) = cone do j = 2, q v1t(1_${ik}$,j) = czero v1t(j,1_${ik}$) = czero end do call stdlib${ii}$_zlacpy( 'U', q-1, q-1, x21(1_${ik}$,2_${ik}$), ldx21, v1t(2_${ik}$,2_${ik}$),ldv1t ) call stdlib${ii}$_zunglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglq, childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_zbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,rwork(iphi), u1, & ldu1, u2, ldu2, v1t, ldv1t, cdum,1_${ik}$, rwork(ib11d), rwork(ib11e), rwork(ib12d),rwork(& ib12e), rwork(ib21d), rwork(ib21e),rwork(ib22d), rwork(ib22e), rwork(ibbcsd),lrwork-& ibbcsd+1, childinfo ) ! permute rows and columns to place czero submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_zlapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == p ) then ! case 2: r = p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_zunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then u1(1_${ik}$,1_${ik}$) = cone do j = 2, p u1(1_${ik}$,j) = czero u1(j,1_${ik}$) = czero end do call stdlib${ii}$_zlacpy( 'L', p-1, p-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$), ldu1 ) call stdlib${ii}$_zungqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, work(itaup1),work(iorgqr), & lorgqr, childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_zungqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'U', p, q, x11, ldx11, v1t, ldv1t ) call stdlib${ii}$_zunglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_zbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,rwork(iphi), v1t,& ldv1t, cdum, 1_${ik}$, u1, ldu1, u2,ldu2, rwork(ib11d), rwork(ib11e), rwork(ib12d),rwork(& ib12e), rwork(ib21d), rwork(ib21e),rwork(ib22d), rwork(ib22e), rwork(ibbcsd), & lbbcsd,childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_zlapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == m-p ) then ! case 3: r = m-p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_zunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_zungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then u2(1_${ik}$,1_${ik}$) = cone do j = 2, m-p u2(1_${ik}$,j) = czero u2(j,1_${ik}$) = czero end do call stdlib${ii}$_zlacpy( 'L', m-p-1, m-p-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_zungqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,work(itaup2), work(iorgqr)& , lorgqr, childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'U', m-p, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_zunglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_zbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, rwork(iphi), & cdum, 1_${ik}$, v1t, ldv1t, u2, ldu2,u1, ldu1, rwork(ib11d), rwork(ib11e),rwork(ib12d), & rwork(ib12e), rwork(ib21d),rwork(ib21e), rwork(ib22d), rwork(ib22e),rwork(ibbcsd), & lbbcsd, childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > r ) then do i = 1, r iwork(i) = q - r + i end do do i = r + 1, q iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_zlapmt( .false., p, q, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_zlapmr( .false., q, q, v1t, ldv1t, iwork ) end if end if else ! case 4: r = m-q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_zunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), work(iorbdb+m),lorbdb-m, & childinfo ) ! accumulate householder reflectors if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_zcopy( m-p, work(iorbdb+p), 1_${ik}$, u2, 1_${ik}$ ) end if if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_zcopy( p, work(iorbdb), 1_${ik}$, u1, 1_${ik}$ ) do j = 2, p u1(1_${ik}$,j) = czero end do call stdlib${ii}$_zlacpy( 'L', p-1, m-q-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$),ldu1 ) call stdlib${ii}$_zungqr( p, p, m-q, u1, ldu1, work(itaup1),work(iorgqr), lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then do j = 2, m-p u2(1_${ik}$,j) = czero end do call stdlib${ii}$_zlacpy( 'L', m-p-1, m-q-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_zungqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_zlacpy( 'U', m-q, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_zlacpy( 'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,v1t(m-q+1,m-q+& 1_${ik}$), ldv1t ) call stdlib${ii}$_zlacpy( 'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,v1t(p+1,p+1), ldv1t ) call stdlib${ii}$_zunglq( q, q, q, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_zbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, rwork(iphi), & u2, ldu2, u1, ldu1, cdum, 1_${ik}$,v1t, ldv1t, rwork(ib11d), rwork(ib11e),rwork(ib12d), & rwork(ib12e), rwork(ib21d),rwork(ib21e), rwork(ib22d), rwork(ib22e),rwork(ibbcsd), & lbbcsd, childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( p > r ) then do i = 1, r iwork(i) = p - r + i end do do i = r + 1, p iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_zlapmt( .false., p, p, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_zlapmr( .false., p, q, v1t, ldv1t, iwork ) end if end if end if return end subroutine stdlib${ii}$_zuncsd2by1 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$uncsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta, & !! ZUNCSD2BY1: computes the CS decomposition of an M-by-Q matrix X with !! orthonormal columns that has been partitioned into a 2-by-1 block !! structure: !! [ I1 0 0 ] !! [ 0 C 0 ] !! [ X11 ] [ U1 | ] [ 0 0 0 ] !! X = [-----] = [---------] [----------] V1**T . !! [ X21 ] [ | U2 ] [ 0 0 0 ] !! [ 0 S 0 ] !! [ 0 0 I2] !! X11 is P-by-Q. The unitary matrices U1, U2, and V1 are P-by-P, !! (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R !! nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which !! R = MIN(P,M-P,Q,M-Q). I1 is a K1-by-K1 identity matrix and I2 is a !! K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0). u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, rwork, lrwork, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobu1, jobu2, jobv1t integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, lwork, ldx11, ldx21, m, p, q integer(${ik}$), intent(in) :: lrwork integer(${ik}$) :: lrworkmin, lrworkopt ! Array Arguments real(${ck}$), intent(out) :: rwork(*) real(${ck}$), intent(out) :: theta(*) complex(${ck}$), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), work(*) complex(${ck}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*) integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, & ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, j, lbbcsd, lorbdb, & lorglq, lorglqmin, lorglqopt, lorgqr, lorgqrmin, lorgqropt, lworkmin, lworkopt, & r logical(lk) :: lquery, wantu1, wantu2, wantv1t ! Local Arrays real(${ck}$) :: dum(1_${ik}$) complex(${ck}$) :: cdum(1_${ik}$,1_${ik}$) ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ wantu1 = stdlib_lsame( jobu1, 'Y' ) wantu2 = stdlib_lsame( jobu2, 'Y' ) wantv1t = stdlib_lsame( jobv1t, 'Y' ) lquery = ( lwork==-1_${ik}$ ) .or. ( lrwork==-1_${ik}$ ) if( m < 0_${ik}$ ) then info = -4_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -5_${ik}$ else if( q < 0_${ik}$ .or. q > m ) then info = -6_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -8_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -10_${ik}$ else if( wantu1 .and. ldu1 < max( 1_${ik}$, p ) ) then info = -13_${ik}$ else if( wantu2 .and. ldu2 < max( 1_${ik}$, m - p ) ) then info = -15_${ik}$ else if( wantv1t .and. ldv1t < max( 1_${ik}$, q ) ) then info = -17_${ik}$ end if r = min( p, m-p, q, m-q ) ! compute workspace ! work layout: ! |-----------------------------------------| ! | lworkopt (1) | ! |-----------------------------------------| ! | taup1 (max(1,p)) | ! | taup2 (max(1,m-p)) | ! | tauq1 (max(1,q)) | ! |-----------------------------------------| ! | stdlib${ii}$_${ci}$unbdb work | stdlib${ii}$_${ci}$ungqr work | stdlib${ii}$_${ci}$unglq work | ! | | | | ! | | | | ! | | | | ! | | | | ! |-----------------------------------------| ! rwork layout: ! |------------------| ! | lrworkopt (1) | ! |------------------| ! | phi (max(1,r-1)) | ! |------------------| ! | b11d (r) | ! | b11e (r-1) | ! | b12d (r) | ! | b12e (r-1) | ! | b21d (r) | ! | b21e (r-1) | ! | b22d (r) | ! | b22e (r-1) | ! | stdlib${ii}$_${ci}$bbcsd rwork | ! |------------------| if( info == 0_${ik}$ ) then iphi = 2_${ik}$ ib11d = iphi + max( 1_${ik}$, r-1 ) ib11e = ib11d + max( 1_${ik}$, r ) ib12d = ib11e + max( 1_${ik}$, r - 1_${ik}$ ) ib12e = ib12d + max( 1_${ik}$, r ) ib21d = ib12e + max( 1_${ik}$, r - 1_${ik}$ ) ib21e = ib21d + max( 1_${ik}$, r ) ib22d = ib21e + max( 1_${ik}$, r - 1_${ik}$ ) ib22e = ib22d + max( 1_${ik}$, r ) ibbcsd = ib22e + max( 1_${ik}$, r - 1_${ik}$ ) itaup1 = 2_${ik}$ itaup2 = itaup1 + max( 1_${ik}$, p ) itauq1 = itaup2 + max( 1_${ik}$, m-p ) iorbdb = itauq1 + max( 1_${ik}$, q ) iorgqr = itauq1 + max( 1_${ik}$, q ) iorglq = itauq1 + max( 1_${ik}$, q ) lorgqrmin = 1_${ik}$ lorgqropt = 1_${ik}$ lorglqmin = 1_${ik}$ lorglqopt = 1_${ik}$ if( r == q ) then call stdlib${ii}$_${ci}$unbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, dum,cdum, cdum, & cdum, work, -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$ungqr( p, p, q, u1, ldu1, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) endif if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$ungqr( m-p, m-p, q, u2, ldu2, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ci}$unglq( q-1, q-1, q-1, v1t, ldv1t,cdum, work(1_${ik}$), -1_${ik}$, childinfo ) lorglqmin = max( lorglqmin, q-1 ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_${ci}$bbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,dum, u1, ldu1,& u2, ldu2, v1t, ldv1t, cdum, 1_${ik}$,dum, dum, dum, dum, dum, dum, dum, dum,rwork(1_${ik}$), -& 1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) else if( r == p ) then call stdlib${ii}$_${ci}$unbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, dum,cdum, cdum, & cdum, work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$ungqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, cdum, work(1_${ik}$),-1_${ik}$, childinfo & ) lorgqrmin = max( lorgqrmin, p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$ungqr( m-p, m-p, q, u2, ldu2, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ci}$unglq( q, q, r, v1t, ldv1t, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_${ci}$bbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,dum, v1t, & ldv1t, cdum, 1_${ik}$, u1, ldu1, u2, ldu2,dum, dum, dum, dum, dum, dum, dum, dum,rwork(& 1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) else if( r == m-p ) then call stdlib${ii}$_${ci}$unbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, dum,cdum, cdum, & cdum, work(1_${ik}$), -1_${ik}$, childinfo ) lorbdb = int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$ungqr( p, p, q, u1, ldu1, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$ungqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2, cdum,work(1_${ik}$), -1_${ik}$, & childinfo ) lorgqrmin = max( lorgqrmin, m-p-1 ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ci}$unglq( q, q, r, v1t, ldv1t, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_${ci}$bbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, dum, cdum,& 1_${ik}$, v1t, ldv1t, u2, ldu2, u1,ldu1, dum, dum, dum, dum, dum, dum, dum, dum,rwork(& 1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) else call stdlib${ii}$_${ci}$unbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, dum,cdum, cdum, & cdum, cdum, work(1_${ik}$), -1_${ik}$, childinfo) lorbdb = m + int( work(1_${ik}$),KIND=${ik}$) if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$ungqr( p, p, m-q, u1, ldu1, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$ungqr( m-p, m-p, m-q, u2, ldu2, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorgqrmin = max( lorgqrmin, m-p ) lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ci}$unglq( q, q, q, v1t, ldv1t, cdum, work(1_${ik}$), -1_${ik}$,childinfo ) lorglqmin = max( lorglqmin, q ) lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) ) end if call stdlib${ii}$_${ci}$bbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, dum, u2, & ldu2, u1, ldu1, cdum, 1_${ik}$, v1t,ldv1t, dum, dum, dum, dum, dum, dum, dum, dum,rwork(& 1_${ik}$), -1_${ik}$, childinfo ) lbbcsd = int( rwork(1_${ik}$),KIND=${ik}$) end if lrworkmin = ibbcsd+lbbcsd-1 lrworkopt = lrworkmin rwork(1_${ik}$) = lrworkopt lworkmin = max( iorbdb+lorbdb-1,iorgqr+lorgqrmin-1,iorglq+lorglqmin-1 ) lworkopt = max( iorbdb+lorbdb-1,iorgqr+lorgqropt-1,iorglq+lorglqopt-1 ) work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -19_${ik}$ end if if( lrwork < lrworkmin .and. .not.lquery ) then info = -21_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNCSD2BY1', -info ) return else if( lquery ) then return end if lorgqr = lwork-iorgqr+1 lorglq = lwork-iorglq+1 ! handle four cases separately: r = q, r = p, r = m-p, and r = m-q, ! in which r = min(p,m-p,q,m-q) if( r == q ) then ! case 1: r = q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_${ci}$unbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_${ci}$ungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_${ci}$ungqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then v1t(1_${ik}$,1_${ik}$) = cone do j = 2, q v1t(1_${ik}$,j) = czero v1t(j,1_${ik}$) = czero end do call stdlib${ii}$_${ci}$lacpy( 'U', q-1, q-1, x21(1_${ik}$,2_${ik}$), ldx21, v1t(2_${ik}$,2_${ik}$),ldv1t ) call stdlib${ii}$_${ci}$unglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), & lorglq, childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_${ci}$bbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,rwork(iphi), u1, & ldu1, u2, ldu2, v1t, ldv1t, cdum,1_${ik}$, rwork(ib11d), rwork(ib11e), rwork(ib12d),rwork(& ib12e), rwork(ib21d), rwork(ib21e),rwork(ib22d), rwork(ib22e), rwork(ibbcsd),lrwork-& ibbcsd+1, childinfo ) ! permute rows and columns to place czero submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_${ci}$lapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == p ) then ! case 2: r = p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_${ci}$unbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then u1(1_${ik}$,1_${ik}$) = cone do j = 2, p u1(1_${ik}$,j) = czero u1(j,1_${ik}$) = czero end do call stdlib${ii}$_${ci}$lacpy( 'L', p-1, p-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$), ldu1 ) call stdlib${ii}$_${ci}$ungqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, work(itaup1),work(iorgqr), & lorgqr, childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 ) call stdlib${ii}$_${ci}$ungqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'U', p, q, x11, ldx11, v1t, ldv1t ) call stdlib${ii}$_${ci}$unglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_${ci}$bbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,rwork(iphi), v1t,& ldv1t, cdum, 1_${ik}$, u1, ldu1, u2,ldu2, rwork(ib11d), rwork(ib11e), rwork(ib12d),rwork(& ib12e), rwork(ib21d), rwork(ib21e),rwork(ib22d), rwork(ib22e), rwork(ibbcsd), & lbbcsd,childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > 0_${ik}$ .and. wantu2 ) then do i = 1, q iwork(i) = m - p - q + i end do do i = q + 1, m - p iwork(i) = i - q end do call stdlib${ii}$_${ci}$lapmt( .false., m-p, m-p, u2, ldu2, iwork ) end if else if( r == m-p ) then ! case 3: r = m-p ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_${ci}$unbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo ) ! accumulate householder reflectors if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', p, q, x11, ldx11, u1, ldu1 ) call stdlib${ii}$_${ci}$ungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then u2(1_${ik}$,1_${ik}$) = cone do j = 2, m-p u2(1_${ik}$,j) = czero u2(j,1_${ik}$) = czero end do call stdlib${ii}$_${ci}$lacpy( 'L', m-p-1, m-p-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_${ci}$ungqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,work(itaup2), work(iorgqr)& , lorgqr, childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'U', m-p, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_${ci}$unglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_${ci}$bbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, rwork(iphi), & cdum, 1_${ik}$, v1t, ldv1t, u2, ldu2,u1, ldu1, rwork(ib11d), rwork(ib11e),rwork(ib12d), & rwork(ib12e), rwork(ib21d),rwork(ib21e), rwork(ib22d), rwork(ib22e),rwork(ibbcsd), & lbbcsd, childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( q > r ) then do i = 1, r iwork(i) = q - r + i end do do i = r + 1, q iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_${ci}$lapmt( .false., p, q, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_${ci}$lapmr( .false., q, q, v1t, ldv1t, iwork ) end if end if else ! case 4: r = m-q ! simultaneously bidiagonalize x11 and x21 call stdlib${ii}$_${ci}$unbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,rwork(iphi), work(& itaup1), work(itaup2),work(itauq1), work(iorbdb), work(iorbdb+m),lorbdb-m, & childinfo ) ! accumulate householder reflectors if( wantu2 .and. m-p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$copy( m-p, work(iorbdb+p), 1_${ik}$, u2, 1_${ik}$ ) end if if( wantu1 .and. p > 0_${ik}$ ) then call stdlib${ii}$_${ci}$copy( p, work(iorbdb), 1_${ik}$, u1, 1_${ik}$ ) do j = 2, p u1(1_${ik}$,j) = czero end do call stdlib${ii}$_${ci}$lacpy( 'L', p-1, m-q-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$),ldu1 ) call stdlib${ii}$_${ci}$ungqr( p, p, m-q, u1, ldu1, work(itaup1),work(iorgqr), lorgqr, & childinfo ) end if if( wantu2 .and. m-p > 0_${ik}$ ) then do j = 2, m-p u2(1_${ik}$,j) = czero end do call stdlib${ii}$_${ci}$lacpy( 'L', m-p-1, m-q-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 ) call stdlib${ii}$_${ci}$ungqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, & childinfo ) end if if( wantv1t .and. q > 0_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'U', m-q, q, x21, ldx21, v1t, ldv1t ) call stdlib${ii}$_${ci}$lacpy( 'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,v1t(m-q+1,m-q+& 1_${ik}$), ldv1t ) call stdlib${ii}$_${ci}$lacpy( 'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,v1t(p+1,p+1), ldv1t ) call stdlib${ii}$_${ci}$unglq( q, q, q, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, & childinfo ) end if ! simultaneously diagonalize x11 and x21. call stdlib${ii}$_${ci}$bbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, rwork(iphi), & u2, ldu2, u1, ldu1, cdum, 1_${ik}$,v1t, ldv1t, rwork(ib11d), rwork(ib11e),rwork(ib12d), & rwork(ib12e), rwork(ib21d),rwork(ib21e), rwork(ib22d), rwork(ib22e),rwork(ibbcsd), & lbbcsd, childinfo ) ! permute rows and columns to place identity submatrices in ! preferred positions if( p > r ) then do i = 1, r iwork(i) = p - r + i end do do i = r + 1, p iwork(i) = i - r end do if( wantu1 ) then call stdlib${ii}$_${ci}$lapmt( .false., p, p, u1, ldu1, iwork ) end if if( wantv1t ) then call stdlib${ii}$_${ci}$lapmr( .false., p, q, v1t, ldv1t, iwork ) end if end if end if return end subroutine stdlib${ii}$_${ci}$uncsd2by1 #:endif #:endfor module subroutine stdlib${ii}$_cunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & !! CUNBDB simultaneously bidiagonalizes the blocks of an M-by-M !! partitioned unitary matrix X: !! [ B11 | B12 0 0 ] !! [ X11 | X12 ] [ P1 | ] [ 0 | 0 -I 0 ] [ Q1 | ]**H !! X = [-----------] = [---------] [----------------] [---------] . !! [ X21 | X22 ] [ | P2 ] [ B21 | B22 0 0 ] [ | Q2 ] !! [ 0 | 0 0 I ] !! X11 is P-by-Q. Q must be no larger than P, M-P, or M-Q. (If this is !! not the case, then X must be transposed and/or permuted. This can be !! done in constant time using the TRANS and SIGNS options. See CUNCSD !! for details.) !! The unitary matrices P1, P2, Q1, and Q2 are P-by-P, (M-P)-by- !! (M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. They are !! represented implicitly by Householder vectors. !! B11, B12, B21, and B22 are Q-by-Q bidiagonal matrices represented !! implicitly by angles THETA, PHI. ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldx11, ldx12, ldx21, ldx22, lwork, m, p, q ! Array Arguments real(sp), intent(out) :: phi(*), theta(*) complex(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), tauq2(*), work(*) complex(sp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! ==================================================================== ! Parameters ! Local Scalars logical(lk) :: colmajor, lquery integer(${ik}$) :: i, lworkmin, lworkopt real(sp) :: z1, z2, z3, z4 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ colmajor = .not. stdlib_lsame( trans, 'T' ) if( .not. stdlib_lsame( signs, 'O' ) ) then z1 = one z2 = one z3 = one z4 = one else z1 = one z2 = -one z3 = one z4 = -one end if lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -3_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -4_${ik}$ else if( q < 0_${ik}$ .or. q > p .or. q > m-p .or.q > m-q ) then info = -5_${ik}$ else if( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -7_${ik}$ else if( .not.colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -7_${ik}$ else if( colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -9_${ik}$ else if( .not.colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -9_${ik}$ else if( colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -11_${ik}$ else if( .not.colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if( colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -13_${ik}$ else if( .not.colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then lworkopt = m - q lworkmin = m - q work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not. lquery ) then info = -21_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'XORBDB', -info ) return else if( lquery ) then return end if ! handle column-major and row-major separately if( colmajor ) then ! reduce columns 1, ..., q of x11, x12, x21, and x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_cscal( p-i+1, cmplx( z1, 0.0_sp,KIND=sp), x11(i,i), 1_${ik}$ ) else call stdlib${ii}$_cscal( p-i+1, cmplx( z1*cos(phi(i-1)), 0.0_sp,KIND=sp),x11(i,i), & 1_${ik}$ ) call stdlib${ii}$_caxpy( p-i+1, cmplx( -z1*z3*z4*sin(phi(i-1)),0.0_sp,KIND=sp), x12(& i,i-1), 1_${ik}$, x11(i,i), 1_${ik}$ ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_cscal( m-p-i+1, cmplx( z2, 0.0_sp,KIND=sp), x21(i,i), 1_${ik}$ ) else call stdlib${ii}$_cscal( m-p-i+1, cmplx( z2*cos(phi(i-1)), 0.0_sp,KIND=sp),x21(i,i),& 1_${ik}$ ) call stdlib${ii}$_caxpy( m-p-i+1, cmplx( -z2*z3*z4*sin(phi(i-1)),0.0_sp,KIND=sp), & x22(i,i-1), 1_${ik}$, x21(i,i), 1_${ik}$ ) end if theta(i) = atan2( stdlib${ii}$_scnrm2( m-p-i+1, x21(i,i), 1_${ik}$ ),stdlib${ii}$_scnrm2( p-i+1, & x11(i,i), 1_${ik}$ ) ) if( p > i ) then call stdlib${ii}$_clarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) else if ( p == i ) then call stdlib${ii}$_clarfgp( p-i+1, x11(i,i), x11(i,i), 1_${ik}$, taup1(i) ) end if x11(i,i) = cone if ( m-p > i ) then call stdlib${ii}$_clarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$,taup2(i) ) else if ( m-p == i ) then call stdlib${ii}$_clarfgp( m-p-i+1, x21(i,i), x21(i,i), 1_${ik}$,taup2(i) ) end if x21(i,i) = cone if ( q > i ) then call stdlib${ii}$_clarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$,conjg(taup1(i)), x11(i,i+1), & ldx11, work ) call stdlib${ii}$_clarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$,conjg(taup2(i)), x21(i,i+1),& ldx21, work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_clarf( 'L', p-i+1, m-q-i+1, x11(i,i), 1_${ik}$,conjg(taup1(i)), x12(i,i),& ldx12, work ) call stdlib${ii}$_clarf( 'L', m-p-i+1, m-q-i+1, x21(i,i), 1_${ik}$,conjg(taup2(i)), x22(i,& i), ldx22, work ) end if if( i < q ) then call stdlib${ii}$_cscal( q-i, cmplx( -z1*z3*sin(theta(i)), 0.0_sp,KIND=sp),x11(i,i+& 1_${ik}$), ldx11 ) call stdlib${ii}$_caxpy( q-i, cmplx( z2*z3*cos(theta(i)), 0.0_sp,KIND=sp),x21(i,i+1)& , ldx21, x11(i,i+1), ldx11 ) end if call stdlib${ii}$_cscal( m-q-i+1, cmplx( -z1*z4*sin(theta(i)), 0.0_sp,KIND=sp),x12(i,i)& , ldx12 ) call stdlib${ii}$_caxpy( m-q-i+1, cmplx( z2*z4*cos(theta(i)), 0.0_sp,KIND=sp),x22(i,i),& ldx22, x12(i,i), ldx12 ) if( i < q )phi(i) = atan2( stdlib${ii}$_scnrm2( q-i, x11(i,i+1), ldx11 ),stdlib${ii}$_scnrm2(& m-q-i+1, x12(i,i), ldx12 ) ) if( i < q ) then call stdlib${ii}$_clacgv( q-i, x11(i,i+1), ldx11 ) if ( i == q-1 ) then call stdlib${ii}$_clarfgp( q-i, x11(i,i+1), x11(i,i+1), ldx11,tauq1(i) ) else call stdlib${ii}$_clarfgp( q-i, x11(i,i+1), x11(i,i+2), ldx11,tauq1(i) ) end if x11(i,i+1) = cone end if if ( m-q+1 > i ) then call stdlib${ii}$_clacgv( m-q-i+1, x12(i,i), ldx12 ) if ( m-q == i ) then call stdlib${ii}$_clarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_clarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if end if x12(i,i) = cone if( i < q ) then call stdlib${ii}$_clarf( 'R', p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x11(i+1,i+1), & ldx11, work ) call stdlib${ii}$_clarf( 'R', m-p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x21(i+1,i+1), & ldx21, work ) end if if ( p > i ) then call stdlib${ii}$_clarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if ( m-p > i ) then call stdlib${ii}$_clarf( 'R', m-p-i, m-q-i+1, x12(i,i), ldx12,tauq2(i), x22(i+1,i), & ldx22, work ) end if if( i < q )call stdlib${ii}$_clacgv( q-i, x11(i,i+1), ldx11 ) call stdlib${ii}$_clacgv( m-q-i+1, x12(i,i), ldx12 ) end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_cscal( m-q-i+1, cmplx( -z1*z4, 0.0_sp,KIND=sp), x12(i,i),ldx12 ) call stdlib${ii}$_clacgv( m-q-i+1, x12(i,i), ldx12 ) if ( i >= m-q ) then call stdlib${ii}$_clarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_clarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if x12(i,i) = cone if ( p > i ) then call stdlib${ii}$_clarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_clarf( 'R', m-p-q, m-q-i+1, x12(i,i), ldx12,tauq2(i),& x22(q+1,i), ldx22, work ) call stdlib${ii}$_clacgv( m-q-i+1, x12(i,i), ldx12 ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_cscal( m-p-q-i+1, cmplx( z2*z4, 0.0_sp,KIND=sp),x22(q+i,p+i), ldx22 ) call stdlib${ii}$_clacgv( m-p-q-i+1, x22(q+i,p+i), ldx22 ) call stdlib${ii}$_clarfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i+1),ldx22, tauq2(p+i) ) x22(q+i,p+i) = cone call stdlib${ii}$_clarf( 'R', m-p-q-i, m-p-q-i+1, x22(q+i,p+i), ldx22,tauq2(p+i), x22(& q+i+1,p+i), ldx22, work ) call stdlib${ii}$_clacgv( m-p-q-i+1, x22(q+i,p+i), ldx22 ) end do else ! reduce columns 1, ..., q of x11, x12, x21, x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_cscal( p-i+1, cmplx( z1, 0.0_sp,KIND=sp), x11(i,i),ldx11 ) else call stdlib${ii}$_cscal( p-i+1, cmplx( z1*cos(phi(i-1)), 0.0_sp,KIND=sp),x11(i,i), & ldx11 ) call stdlib${ii}$_caxpy( p-i+1, cmplx( -z1*z3*z4*sin(phi(i-1)),0.0_sp,KIND=sp), x12(& i-1,i), ldx12, x11(i,i), ldx11 ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_cscal( m-p-i+1, cmplx( z2, 0.0_sp,KIND=sp), x21(i,i),ldx21 ) else call stdlib${ii}$_cscal( m-p-i+1, cmplx( z2*cos(phi(i-1)), 0.0_sp,KIND=sp),x21(i,i),& ldx21 ) call stdlib${ii}$_caxpy( m-p-i+1, cmplx( -z2*z3*z4*sin(phi(i-1)),0.0_sp,KIND=sp), & x22(i-1,i), ldx22, x21(i,i), ldx21 ) end if theta(i) = atan2( stdlib${ii}$_scnrm2( m-p-i+1, x21(i,i), ldx21 ),stdlib${ii}$_scnrm2( p-i+1,& x11(i,i), ldx11 ) ) call stdlib${ii}$_clacgv( p-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_clacgv( m-p-i+1, x21(i,i), ldx21 ) call stdlib${ii}$_clarfgp( p-i+1, x11(i,i), x11(i,i+1), ldx11, taup1(i) ) x11(i,i) = cone if ( i == m-p ) then call stdlib${ii}$_clarfgp( m-p-i+1, x21(i,i), x21(i,i), ldx21,taup2(i) ) else call stdlib${ii}$_clarfgp( m-p-i+1, x21(i,i), x21(i,i+1), ldx21,taup2(i) ) end if x21(i,i) = cone call stdlib${ii}$_clarf( 'R', q-i, p-i+1, x11(i,i), ldx11, taup1(i),x11(i+1,i), ldx11, & work ) call stdlib${ii}$_clarf( 'R', m-q-i+1, p-i+1, x11(i,i), ldx11, taup1(i),x12(i,i), & ldx12, work ) call stdlib${ii}$_clarf( 'R', q-i, m-p-i+1, x21(i,i), ldx21, taup2(i),x21(i+1,i), & ldx21, work ) call stdlib${ii}$_clarf( 'R', m-q-i+1, m-p-i+1, x21(i,i), ldx21,taup2(i), x22(i,i), & ldx22, work ) call stdlib${ii}$_clacgv( p-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_clacgv( m-p-i+1, x21(i,i), ldx21 ) if( i < q ) then call stdlib${ii}$_cscal( q-i, cmplx( -z1*z3*sin(theta(i)), 0.0_sp,KIND=sp),x11(i+1,& i), 1_${ik}$ ) call stdlib${ii}$_caxpy( q-i, cmplx( z2*z3*cos(theta(i)), 0.0_sp,KIND=sp),x21(i+1,i)& , 1_${ik}$, x11(i+1,i), 1_${ik}$ ) end if call stdlib${ii}$_cscal( m-q-i+1, cmplx( -z1*z4*sin(theta(i)), 0.0_sp,KIND=sp),x12(i,i)& , 1_${ik}$ ) call stdlib${ii}$_caxpy( m-q-i+1, cmplx( z2*z4*cos(theta(i)), 0.0_sp,KIND=sp),x22(i,i),& 1_${ik}$, x12(i,i), 1_${ik}$ ) if( i < q )phi(i) = atan2( stdlib${ii}$_scnrm2( q-i, x11(i+1,i), 1_${ik}$ ),stdlib${ii}$_scnrm2( m-& q-i+1, x12(i,i), 1_${ik}$ ) ) if( i < q ) then call stdlib${ii}$_clarfgp( q-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, tauq1(i) ) x11(i+1,i) = cone end if call stdlib${ii}$_clarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) ) x12(i,i) = cone if( i < q ) then call stdlib${ii}$_clarf( 'L', q-i, p-i, x11(i+1,i), 1_${ik}$,conjg(tauq1(i)), x11(i+1,i+1),& ldx11, work ) call stdlib${ii}$_clarf( 'L', q-i, m-p-i, x11(i+1,i), 1_${ik}$,conjg(tauq1(i)), x21(i+1,i+& 1_${ik}$), ldx21, work ) end if call stdlib${ii}$_clarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, conjg(tauq2(i)),x12(i,i+1), & ldx12, work ) if ( m-p > i ) then call stdlib${ii}$_clarf( 'L', m-q-i+1, m-p-i, x12(i,i), 1_${ik}$,conjg(tauq2(i)), x22(i,i+& 1_${ik}$), ldx22, work ) end if end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_cscal( m-q-i+1, cmplx( -z1*z4, 0.0_sp,KIND=sp), x12(i,i), 1_${ik}$ ) call stdlib${ii}$_clarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) ) x12(i,i) = cone if ( p > i ) then call stdlib${ii}$_clarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$,conjg(tauq2(i)), x12(i,i+1),& ldx12, work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_clarf( 'L', m-q-i+1, m-p-q, x12(i,i), 1_${ik}$,conjg(tauq2(& i)), x22(i,q+1), ldx22, work ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_cscal( m-p-q-i+1, cmplx( z2*z4, 0.0_sp,KIND=sp),x22(p+i,q+i), 1_${ik}$ ) call stdlib${ii}$_clarfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i+1,q+i), 1_${ik}$,tauq2(p+i) ) x22(p+i,q+i) = cone if ( m-p-q /= i ) then call stdlib${ii}$_clarf( 'L', m-p-q-i+1, m-p-q-i, x22(p+i,q+i), 1_${ik}$,conjg(tauq2(p+i)),& x22(p+i,q+i+1), ldx22,work ) end if end do end if return end subroutine stdlib${ii}$_cunbdb module subroutine stdlib${ii}$_zunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & !! ZUNBDB simultaneously bidiagonalizes the blocks of an M-by-M !! partitioned unitary matrix X: !! [ B11 | B12 0 0 ] !! [ X11 | X12 ] [ P1 | ] [ 0 | 0 -I 0 ] [ Q1 | ]**H !! X = [-----------] = [---------] [----------------] [---------] . !! [ X21 | X22 ] [ | P2 ] [ B21 | B22 0 0 ] [ | Q2 ] !! [ 0 | 0 0 I ] !! X11 is P-by-Q. Q must be no larger than P, M-P, or M-Q. (If this is !! not the case, then X must be transposed and/or permuted. This can be !! done in constant time using the TRANS and SIGNS options. See ZUNCSD !! for details.) !! The unitary matrices P1, P2, Q1, and Q2 are P-by-P, (M-P)-by- !! (M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. They are !! represented implicitly by Householder vectors. !! B11, B12, B21, and B22 are Q-by-Q bidiagonal matrices represented !! implicitly by angles THETA, PHI. ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldx11, ldx12, ldx21, ldx22, lwork, m, p, q ! Array Arguments real(dp), intent(out) :: phi(*), theta(*) complex(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), tauq2(*), work(*) complex(dp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! ==================================================================== ! Parameters ! Local Scalars logical(lk) :: colmajor, lquery integer(${ik}$) :: i, lworkmin, lworkopt real(dp) :: z1, z2, z3, z4 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ colmajor = .not. stdlib_lsame( trans, 'T' ) if( .not. stdlib_lsame( signs, 'O' ) ) then z1 = one z2 = one z3 = one z4 = one else z1 = one z2 = -one z3 = one z4 = -one end if lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -3_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -4_${ik}$ else if( q < 0_${ik}$ .or. q > p .or. q > m-p .or.q > m-q ) then info = -5_${ik}$ else if( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -7_${ik}$ else if( .not.colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -7_${ik}$ else if( colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -9_${ik}$ else if( .not.colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -9_${ik}$ else if( colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -11_${ik}$ else if( .not.colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if( colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -13_${ik}$ else if( .not.colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then lworkopt = m - q lworkmin = m - q work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not. lquery ) then info = -21_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'XORBDB', -info ) return else if( lquery ) then return end if ! handle column-major and row-major separately if( colmajor ) then ! reduce columns 1, ..., q of x11, x12, x21, and x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_zscal( p-i+1, cmplx( z1, 0.0_dp,KIND=dp), x11(i,i), 1_${ik}$ ) else call stdlib${ii}$_zscal( p-i+1, cmplx( z1*cos(phi(i-1)), 0.0_dp,KIND=dp),x11(i,i), & 1_${ik}$ ) call stdlib${ii}$_zaxpy( p-i+1, cmplx( -z1*z3*z4*sin(phi(i-1)),0.0_dp,KIND=dp), x12(& i,i-1), 1_${ik}$, x11(i,i), 1_${ik}$ ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_zscal( m-p-i+1, cmplx( z2, 0.0_dp,KIND=dp), x21(i,i), 1_${ik}$ ) else call stdlib${ii}$_zscal( m-p-i+1, cmplx( z2*cos(phi(i-1)), 0.0_dp,KIND=dp),x21(i,i),& 1_${ik}$ ) call stdlib${ii}$_zaxpy( m-p-i+1, cmplx( -z2*z3*z4*sin(phi(i-1)),0.0_dp,KIND=dp), & x22(i,i-1), 1_${ik}$, x21(i,i), 1_${ik}$ ) end if theta(i) = atan2( stdlib${ii}$_dznrm2( m-p-i+1, x21(i,i), 1_${ik}$ ),stdlib${ii}$_dznrm2( p-i+1, & x11(i,i), 1_${ik}$ ) ) if( p > i ) then call stdlib${ii}$_zlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) else if ( p == i ) then call stdlib${ii}$_zlarfgp( p-i+1, x11(i,i), x11(i,i), 1_${ik}$, taup1(i) ) end if x11(i,i) = cone if ( m-p > i ) then call stdlib${ii}$_zlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$,taup2(i) ) else if ( m-p == i ) then call stdlib${ii}$_zlarfgp( m-p-i+1, x21(i,i), x21(i,i), 1_${ik}$,taup2(i) ) end if x21(i,i) = cone if ( q > i ) then call stdlib${ii}$_zlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$,conjg(taup1(i)), x11(i,i+1), & ldx11, work ) call stdlib${ii}$_zlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$,conjg(taup2(i)), x21(i,i+1),& ldx21, work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_zlarf( 'L', p-i+1, m-q-i+1, x11(i,i), 1_${ik}$,conjg(taup1(i)), x12(i,i),& ldx12, work ) call stdlib${ii}$_zlarf( 'L', m-p-i+1, m-q-i+1, x21(i,i), 1_${ik}$,conjg(taup2(i)), x22(i,& i), ldx22, work ) end if if( i < q ) then call stdlib${ii}$_zscal( q-i, cmplx( -z1*z3*sin(theta(i)), 0.0_dp,KIND=dp),x11(i,i+& 1_${ik}$), ldx11 ) call stdlib${ii}$_zaxpy( q-i, cmplx( z2*z3*cos(theta(i)), 0.0_dp,KIND=dp),x21(i,i+1)& , ldx21, x11(i,i+1), ldx11 ) end if call stdlib${ii}$_zscal( m-q-i+1, cmplx( -z1*z4*sin(theta(i)), 0.0_dp,KIND=dp),x12(i,i)& , ldx12 ) call stdlib${ii}$_zaxpy( m-q-i+1, cmplx( z2*z4*cos(theta(i)), 0.0_dp,KIND=dp),x22(i,i),& ldx22, x12(i,i), ldx12 ) if( i < q )phi(i) = atan2( stdlib${ii}$_dznrm2( q-i, x11(i,i+1), ldx11 ),stdlib${ii}$_dznrm2(& m-q-i+1, x12(i,i), ldx12 ) ) if( i < q ) then call stdlib${ii}$_zlacgv( q-i, x11(i,i+1), ldx11 ) if ( i == q-1 ) then call stdlib${ii}$_zlarfgp( q-i, x11(i,i+1), x11(i,i+1), ldx11,tauq1(i) ) else call stdlib${ii}$_zlarfgp( q-i, x11(i,i+1), x11(i,i+2), ldx11,tauq1(i) ) end if x11(i,i+1) = cone end if if ( m-q+1 > i ) then call stdlib${ii}$_zlacgv( m-q-i+1, x12(i,i), ldx12 ) if ( m-q == i ) then call stdlib${ii}$_zlarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_zlarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if end if x12(i,i) = cone if( i < q ) then call stdlib${ii}$_zlarf( 'R', p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x11(i+1,i+1), & ldx11, work ) call stdlib${ii}$_zlarf( 'R', m-p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x21(i+1,i+1), & ldx21, work ) end if if ( p > i ) then call stdlib${ii}$_zlarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if ( m-p > i ) then call stdlib${ii}$_zlarf( 'R', m-p-i, m-q-i+1, x12(i,i), ldx12,tauq2(i), x22(i+1,i), & ldx22, work ) end if if( i < q )call stdlib${ii}$_zlacgv( q-i, x11(i,i+1), ldx11 ) call stdlib${ii}$_zlacgv( m-q-i+1, x12(i,i), ldx12 ) end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_zscal( m-q-i+1, cmplx( -z1*z4, 0.0_dp,KIND=dp), x12(i,i),ldx12 ) call stdlib${ii}$_zlacgv( m-q-i+1, x12(i,i), ldx12 ) if ( i >= m-q ) then call stdlib${ii}$_zlarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_zlarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if x12(i,i) = cone if ( p > i ) then call stdlib${ii}$_zlarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_zlarf( 'R', m-p-q, m-q-i+1, x12(i,i), ldx12,tauq2(i),& x22(q+1,i), ldx22, work ) call stdlib${ii}$_zlacgv( m-q-i+1, x12(i,i), ldx12 ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_zscal( m-p-q-i+1, cmplx( z2*z4, 0.0_dp,KIND=dp),x22(q+i,p+i), ldx22 ) call stdlib${ii}$_zlacgv( m-p-q-i+1, x22(q+i,p+i), ldx22 ) call stdlib${ii}$_zlarfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i+1),ldx22, tauq2(p+i) ) x22(q+i,p+i) = cone call stdlib${ii}$_zlarf( 'R', m-p-q-i, m-p-q-i+1, x22(q+i,p+i), ldx22,tauq2(p+i), x22(& q+i+1,p+i), ldx22, work ) call stdlib${ii}$_zlacgv( m-p-q-i+1, x22(q+i,p+i), ldx22 ) end do else ! reduce columns 1, ..., q of x11, x12, x21, x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_zscal( p-i+1, cmplx( z1, 0.0_dp,KIND=dp), x11(i,i),ldx11 ) else call stdlib${ii}$_zscal( p-i+1, cmplx( z1*cos(phi(i-1)), 0.0_dp,KIND=dp),x11(i,i), & ldx11 ) call stdlib${ii}$_zaxpy( p-i+1, cmplx( -z1*z3*z4*sin(phi(i-1)),0.0_dp,KIND=dp), x12(& i-1,i), ldx12, x11(i,i), ldx11 ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_zscal( m-p-i+1, cmplx( z2, 0.0_dp,KIND=dp), x21(i,i),ldx21 ) else call stdlib${ii}$_zscal( m-p-i+1, cmplx( z2*cos(phi(i-1)), 0.0_dp,KIND=dp),x21(i,i),& ldx21 ) call stdlib${ii}$_zaxpy( m-p-i+1, cmplx( -z2*z3*z4*sin(phi(i-1)),0.0_dp,KIND=dp), & x22(i-1,i), ldx22, x21(i,i), ldx21 ) end if theta(i) = atan2( stdlib${ii}$_dznrm2( m-p-i+1, x21(i,i), ldx21 ),stdlib${ii}$_dznrm2( p-i+1,& x11(i,i), ldx11 ) ) call stdlib${ii}$_zlacgv( p-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_zlacgv( m-p-i+1, x21(i,i), ldx21 ) call stdlib${ii}$_zlarfgp( p-i+1, x11(i,i), x11(i,i+1), ldx11, taup1(i) ) x11(i,i) = cone if ( i == m-p ) then call stdlib${ii}$_zlarfgp( m-p-i+1, x21(i,i), x21(i,i), ldx21,taup2(i) ) else call stdlib${ii}$_zlarfgp( m-p-i+1, x21(i,i), x21(i,i+1), ldx21,taup2(i) ) end if x21(i,i) = cone call stdlib${ii}$_zlarf( 'R', q-i, p-i+1, x11(i,i), ldx11, taup1(i),x11(i+1,i), ldx11, & work ) call stdlib${ii}$_zlarf( 'R', m-q-i+1, p-i+1, x11(i,i), ldx11, taup1(i),x12(i,i), & ldx12, work ) call stdlib${ii}$_zlarf( 'R', q-i, m-p-i+1, x21(i,i), ldx21, taup2(i),x21(i+1,i), & ldx21, work ) call stdlib${ii}$_zlarf( 'R', m-q-i+1, m-p-i+1, x21(i,i), ldx21,taup2(i), x22(i,i), & ldx22, work ) call stdlib${ii}$_zlacgv( p-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_zlacgv( m-p-i+1, x21(i,i), ldx21 ) if( i < q ) then call stdlib${ii}$_zscal( q-i, cmplx( -z1*z3*sin(theta(i)), 0.0_dp,KIND=dp),x11(i+1,& i), 1_${ik}$ ) call stdlib${ii}$_zaxpy( q-i, cmplx( z2*z3*cos(theta(i)), 0.0_dp,KIND=dp),x21(i+1,i)& , 1_${ik}$, x11(i+1,i), 1_${ik}$ ) end if call stdlib${ii}$_zscal( m-q-i+1, cmplx( -z1*z4*sin(theta(i)), 0.0_dp,KIND=dp),x12(i,i)& , 1_${ik}$ ) call stdlib${ii}$_zaxpy( m-q-i+1, cmplx( z2*z4*cos(theta(i)), 0.0_dp,KIND=dp),x22(i,i),& 1_${ik}$, x12(i,i), 1_${ik}$ ) if( i < q )phi(i) = atan2( stdlib${ii}$_dznrm2( q-i, x11(i+1,i), 1_${ik}$ ),stdlib${ii}$_dznrm2( m-& q-i+1, x12(i,i), 1_${ik}$ ) ) if( i < q ) then call stdlib${ii}$_zlarfgp( q-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, tauq1(i) ) x11(i+1,i) = cone end if call stdlib${ii}$_zlarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) ) x12(i,i) = cone if( i < q ) then call stdlib${ii}$_zlarf( 'L', q-i, p-i, x11(i+1,i), 1_${ik}$,conjg(tauq1(i)), x11(i+1,i+1),& ldx11, work ) call stdlib${ii}$_zlarf( 'L', q-i, m-p-i, x11(i+1,i), 1_${ik}$,conjg(tauq1(i)), x21(i+1,i+& 1_${ik}$), ldx21, work ) end if call stdlib${ii}$_zlarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$,conjg(tauq2(i)), x12(i,i+1), & ldx12, work ) if ( m-p > i ) then call stdlib${ii}$_zlarf( 'L', m-q-i+1, m-p-i, x12(i,i), 1_${ik}$,conjg(tauq2(i)), x22(i,i+& 1_${ik}$), ldx22, work ) end if end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_zscal( m-q-i+1, cmplx( -z1*z4, 0.0_dp,KIND=dp), x12(i,i), 1_${ik}$ ) call stdlib${ii}$_zlarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) ) x12(i,i) = cone if ( p > i ) then call stdlib${ii}$_zlarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$,conjg(tauq2(i)), x12(i,i+1),& ldx12, work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_zlarf( 'L', m-q-i+1, m-p-q, x12(i,i), 1_${ik}$,conjg(tauq2(& i)), x22(i,q+1), ldx22, work ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_zscal( m-p-q-i+1, cmplx( z2*z4, 0.0_dp,KIND=dp),x22(p+i,q+i), 1_${ik}$ ) call stdlib${ii}$_zlarfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i+1,q+i), 1_${ik}$,tauq2(p+i) ) x22(p+i,q+i) = cone if ( m-p-q /= i ) then call stdlib${ii}$_zlarf( 'L', m-p-q-i+1, m-p-q-i, x22(p+i,q+i), 1_${ik}$,conjg(tauq2(p+i)),& x22(p+i,q+i+1), ldx22,work ) end if end do end if return end subroutine stdlib${ii}$_zunbdb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$unbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, & !! ZUNBDB: simultaneously bidiagonalizes the blocks of an M-by-M !! partitioned unitary matrix X: !! [ B11 | B12 0 0 ] !! [ X11 | X12 ] [ P1 | ] [ 0 | 0 -I 0 ] [ Q1 | ]**H !! X = [-----------] = [---------] [----------------] [---------] . !! [ X21 | X22 ] [ | P2 ] [ B21 | B22 0 0 ] [ | Q2 ] !! [ 0 | 0 0 I ] !! X11 is P-by-Q. Q must be no larger than P, M-P, or M-Q. (If this is !! not the case, then X must be transposed and/or permuted. This can be !! done in constant time using the TRANS and SIGNS options. See ZUNCSD !! for details.) !! The unitary matrices P1, P2, Q1, and Q2 are P-by-P, (M-P)-by- !! (M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. They are !! represented implicitly by Householder vectors. !! B11, B12, B21, and B22 are Q-by-Q bidiagonal matrices represented !! implicitly by angles THETA, PHI. ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: signs, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldx11, ldx12, ldx21, ldx22, lwork, m, p, q ! Array Arguments real(${ck}$), intent(out) :: phi(*), theta(*) complex(${ck}$), intent(out) :: taup1(*), taup2(*), tauq1(*), tauq2(*), work(*) complex(${ck}$), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*) ! ==================================================================== ! Parameters ! Local Scalars logical(lk) :: colmajor, lquery integer(${ik}$) :: i, lworkmin, lworkopt real(${ck}$) :: z1, z2, z3, z4 ! Intrinsic Functions ! Executable Statements ! test input arguments info = 0_${ik}$ colmajor = .not. stdlib_lsame( trans, 'T' ) if( .not. stdlib_lsame( signs, 'O' ) ) then z1 = one z2 = one z3 = one z4 = one else z1 = one z2 = -one z3 = one z4 = -one end if lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -3_${ik}$ else if( p < 0_${ik}$ .or. p > m ) then info = -4_${ik}$ else if( q < 0_${ik}$ .or. q > p .or. q > m-p .or.q > m-q ) then info = -5_${ik}$ else if( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then info = -7_${ik}$ else if( .not.colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then info = -7_${ik}$ else if( colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then info = -9_${ik}$ else if( .not.colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then info = -9_${ik}$ else if( colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then info = -11_${ik}$ else if( .not.colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then info = -11_${ik}$ else if( colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then info = -13_${ik}$ else if( .not.colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then info = -13_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then lworkopt = m - q lworkmin = m - q work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not. lquery ) then info = -21_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'XORBDB', -info ) return else if( lquery ) then return end if ! handle column-major and row-major separately if( colmajor ) then ! reduce columns 1, ..., q of x11, x12, x21, and x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_${ci}$scal( p-i+1, cmplx( z1, 0.0_${ck}$,KIND=${ck}$), x11(i,i), 1_${ik}$ ) else call stdlib${ii}$_${ci}$scal( p-i+1, cmplx( z1*cos(phi(i-1)), 0.0_${ck}$,KIND=${ck}$),x11(i,i), & 1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( p-i+1, cmplx( -z1*z3*z4*sin(phi(i-1)),0.0_${ck}$,KIND=${ck}$), x12(& i,i-1), 1_${ik}$, x11(i,i), 1_${ik}$ ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_${ci}$scal( m-p-i+1, cmplx( z2, 0.0_${ck}$,KIND=${ck}$), x21(i,i), 1_${ik}$ ) else call stdlib${ii}$_${ci}$scal( m-p-i+1, cmplx( z2*cos(phi(i-1)), 0.0_${ck}$,KIND=${ck}$),x21(i,i),& 1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( m-p-i+1, cmplx( -z2*z3*z4*sin(phi(i-1)),0.0_${ck}$,KIND=${ck}$), & x22(i,i-1), 1_${ik}$, x21(i,i), 1_${ik}$ ) end if theta(i) = atan2( stdlib${ii}$_${c2ri(ci)}$znrm2( m-p-i+1, x21(i,i), 1_${ik}$ ),stdlib${ii}$_${c2ri(ci)}$znrm2( p-i+1, & x11(i,i), 1_${ik}$ ) ) if( p > i ) then call stdlib${ii}$_${ci}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) else if ( p == i ) then call stdlib${ii}$_${ci}$larfgp( p-i+1, x11(i,i), x11(i,i), 1_${ik}$, taup1(i) ) end if x11(i,i) = cone if ( m-p > i ) then call stdlib${ii}$_${ci}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$,taup2(i) ) else if ( m-p == i ) then call stdlib${ii}$_${ci}$larfgp( m-p-i+1, x21(i,i), x21(i,i), 1_${ik}$,taup2(i) ) end if x21(i,i) = cone if ( q > i ) then call stdlib${ii}$_${ci}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$,conjg(taup1(i)), x11(i,i+1), & ldx11, work ) call stdlib${ii}$_${ci}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$,conjg(taup2(i)), x21(i,i+1),& ldx21, work ) end if if ( m-q+1 > i ) then call stdlib${ii}$_${ci}$larf( 'L', p-i+1, m-q-i+1, x11(i,i), 1_${ik}$,conjg(taup1(i)), x12(i,i),& ldx12, work ) call stdlib${ii}$_${ci}$larf( 'L', m-p-i+1, m-q-i+1, x21(i,i), 1_${ik}$,conjg(taup2(i)), x22(i,& i), ldx22, work ) end if if( i < q ) then call stdlib${ii}$_${ci}$scal( q-i, cmplx( -z1*z3*sin(theta(i)), 0.0_${ck}$,KIND=${ck}$),x11(i,i+& 1_${ik}$), ldx11 ) call stdlib${ii}$_${ci}$axpy( q-i, cmplx( z2*z3*cos(theta(i)), 0.0_${ck}$,KIND=${ck}$),x21(i,i+1)& , ldx21, x11(i,i+1), ldx11 ) end if call stdlib${ii}$_${ci}$scal( m-q-i+1, cmplx( -z1*z4*sin(theta(i)), 0.0_${ck}$,KIND=${ck}$),x12(i,i)& , ldx12 ) call stdlib${ii}$_${ci}$axpy( m-q-i+1, cmplx( z2*z4*cos(theta(i)), 0.0_${ck}$,KIND=${ck}$),x22(i,i),& ldx22, x12(i,i), ldx12 ) if( i < q )phi(i) = atan2( stdlib${ii}$_${c2ri(ci)}$znrm2( q-i, x11(i,i+1), ldx11 ),stdlib${ii}$_${c2ri(ci)}$znrm2(& m-q-i+1, x12(i,i), ldx12 ) ) if( i < q ) then call stdlib${ii}$_${ci}$lacgv( q-i, x11(i,i+1), ldx11 ) if ( i == q-1 ) then call stdlib${ii}$_${ci}$larfgp( q-i, x11(i,i+1), x11(i,i+1), ldx11,tauq1(i) ) else call stdlib${ii}$_${ci}$larfgp( q-i, x11(i,i+1), x11(i,i+2), ldx11,tauq1(i) ) end if x11(i,i+1) = cone end if if ( m-q+1 > i ) then call stdlib${ii}$_${ci}$lacgv( m-q-i+1, x12(i,i), ldx12 ) if ( m-q == i ) then call stdlib${ii}$_${ci}$larfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_${ci}$larfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if end if x12(i,i) = cone if( i < q ) then call stdlib${ii}$_${ci}$larf( 'R', p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x11(i+1,i+1), & ldx11, work ) call stdlib${ii}$_${ci}$larf( 'R', m-p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x21(i+1,i+1), & ldx21, work ) end if if ( p > i ) then call stdlib${ii}$_${ci}$larf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if ( m-p > i ) then call stdlib${ii}$_${ci}$larf( 'R', m-p-i, m-q-i+1, x12(i,i), ldx12,tauq2(i), x22(i+1,i), & ldx22, work ) end if if( i < q )call stdlib${ii}$_${ci}$lacgv( q-i, x11(i,i+1), ldx11 ) call stdlib${ii}$_${ci}$lacgv( m-q-i+1, x12(i,i), ldx12 ) end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_${ci}$scal( m-q-i+1, cmplx( -z1*z4, 0.0_${ck}$,KIND=${ck}$), x12(i,i),ldx12 ) call stdlib${ii}$_${ci}$lacgv( m-q-i+1, x12(i,i), ldx12 ) if ( i >= m-q ) then call stdlib${ii}$_${ci}$larfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) ) else call stdlib${ii}$_${ci}$larfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) ) end if x12(i,i) = cone if ( p > i ) then call stdlib${ii}$_${ci}$larf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), & ldx12, work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_${ci}$larf( 'R', m-p-q, m-q-i+1, x12(i,i), ldx12,tauq2(i),& x22(q+1,i), ldx22, work ) call stdlib${ii}$_${ci}$lacgv( m-q-i+1, x12(i,i), ldx12 ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_${ci}$scal( m-p-q-i+1, cmplx( z2*z4, 0.0_${ck}$,KIND=${ck}$),x22(q+i,p+i), ldx22 ) call stdlib${ii}$_${ci}$lacgv( m-p-q-i+1, x22(q+i,p+i), ldx22 ) call stdlib${ii}$_${ci}$larfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i+1),ldx22, tauq2(p+i) ) x22(q+i,p+i) = cone call stdlib${ii}$_${ci}$larf( 'R', m-p-q-i, m-p-q-i+1, x22(q+i,p+i), ldx22,tauq2(p+i), x22(& q+i+1,p+i), ldx22, work ) call stdlib${ii}$_${ci}$lacgv( m-p-q-i+1, x22(q+i,p+i), ldx22 ) end do else ! reduce columns 1, ..., q of x11, x12, x21, x22 do i = 1, q if( i == 1_${ik}$ ) then call stdlib${ii}$_${ci}$scal( p-i+1, cmplx( z1, 0.0_${ck}$,KIND=${ck}$), x11(i,i),ldx11 ) else call stdlib${ii}$_${ci}$scal( p-i+1, cmplx( z1*cos(phi(i-1)), 0.0_${ck}$,KIND=${ck}$),x11(i,i), & ldx11 ) call stdlib${ii}$_${ci}$axpy( p-i+1, cmplx( -z1*z3*z4*sin(phi(i-1)),0.0_${ck}$,KIND=${ck}$), x12(& i-1,i), ldx12, x11(i,i), ldx11 ) end if if( i == 1_${ik}$ ) then call stdlib${ii}$_${ci}$scal( m-p-i+1, cmplx( z2, 0.0_${ck}$,KIND=${ck}$), x21(i,i),ldx21 ) else call stdlib${ii}$_${ci}$scal( m-p-i+1, cmplx( z2*cos(phi(i-1)), 0.0_${ck}$,KIND=${ck}$),x21(i,i),& ldx21 ) call stdlib${ii}$_${ci}$axpy( m-p-i+1, cmplx( -z2*z3*z4*sin(phi(i-1)),0.0_${ck}$,KIND=${ck}$), & x22(i-1,i), ldx22, x21(i,i), ldx21 ) end if theta(i) = atan2( stdlib${ii}$_${c2ri(ci)}$znrm2( m-p-i+1, x21(i,i), ldx21 ),stdlib${ii}$_${c2ri(ci)}$znrm2( p-i+1,& x11(i,i), ldx11 ) ) call stdlib${ii}$_${ci}$lacgv( p-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_${ci}$lacgv( m-p-i+1, x21(i,i), ldx21 ) call stdlib${ii}$_${ci}$larfgp( p-i+1, x11(i,i), x11(i,i+1), ldx11, taup1(i) ) x11(i,i) = cone if ( i == m-p ) then call stdlib${ii}$_${ci}$larfgp( m-p-i+1, x21(i,i), x21(i,i), ldx21,taup2(i) ) else call stdlib${ii}$_${ci}$larfgp( m-p-i+1, x21(i,i), x21(i,i+1), ldx21,taup2(i) ) end if x21(i,i) = cone call stdlib${ii}$_${ci}$larf( 'R', q-i, p-i+1, x11(i,i), ldx11, taup1(i),x11(i+1,i), ldx11, & work ) call stdlib${ii}$_${ci}$larf( 'R', m-q-i+1, p-i+1, x11(i,i), ldx11, taup1(i),x12(i,i), & ldx12, work ) call stdlib${ii}$_${ci}$larf( 'R', q-i, m-p-i+1, x21(i,i), ldx21, taup2(i),x21(i+1,i), & ldx21, work ) call stdlib${ii}$_${ci}$larf( 'R', m-q-i+1, m-p-i+1, x21(i,i), ldx21,taup2(i), x22(i,i), & ldx22, work ) call stdlib${ii}$_${ci}$lacgv( p-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_${ci}$lacgv( m-p-i+1, x21(i,i), ldx21 ) if( i < q ) then call stdlib${ii}$_${ci}$scal( q-i, cmplx( -z1*z3*sin(theta(i)), 0.0_${ck}$,KIND=${ck}$),x11(i+1,& i), 1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( q-i, cmplx( z2*z3*cos(theta(i)), 0.0_${ck}$,KIND=${ck}$),x21(i+1,i)& , 1_${ik}$, x11(i+1,i), 1_${ik}$ ) end if call stdlib${ii}$_${ci}$scal( m-q-i+1, cmplx( -z1*z4*sin(theta(i)), 0.0_${ck}$,KIND=${ck}$),x12(i,i)& , 1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( m-q-i+1, cmplx( z2*z4*cos(theta(i)), 0.0_${ck}$,KIND=${ck}$),x22(i,i),& 1_${ik}$, x12(i,i), 1_${ik}$ ) if( i < q )phi(i) = atan2( stdlib${ii}$_${c2ri(ci)}$znrm2( q-i, x11(i+1,i), 1_${ik}$ ),stdlib${ii}$_${c2ri(ci)}$znrm2( m-& q-i+1, x12(i,i), 1_${ik}$ ) ) if( i < q ) then call stdlib${ii}$_${ci}$larfgp( q-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, tauq1(i) ) x11(i+1,i) = cone end if call stdlib${ii}$_${ci}$larfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) ) x12(i,i) = cone if( i < q ) then call stdlib${ii}$_${ci}$larf( 'L', q-i, p-i, x11(i+1,i), 1_${ik}$,conjg(tauq1(i)), x11(i+1,i+1),& ldx11, work ) call stdlib${ii}$_${ci}$larf( 'L', q-i, m-p-i, x11(i+1,i), 1_${ik}$,conjg(tauq1(i)), x21(i+1,i+& 1_${ik}$), ldx21, work ) end if call stdlib${ii}$_${ci}$larf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$,conjg(tauq2(i)), x12(i,i+1), & ldx12, work ) if ( m-p > i ) then call stdlib${ii}$_${ci}$larf( 'L', m-q-i+1, m-p-i, x12(i,i), 1_${ik}$,conjg(tauq2(i)), x22(i,i+& 1_${ik}$), ldx22, work ) end if end do ! reduce columns q + 1, ..., p of x12, x22 do i = q + 1, p call stdlib${ii}$_${ci}$scal( m-q-i+1, cmplx( -z1*z4, 0.0_${ck}$,KIND=${ck}$), x12(i,i), 1_${ik}$ ) call stdlib${ii}$_${ci}$larfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) ) x12(i,i) = cone if ( p > i ) then call stdlib${ii}$_${ci}$larf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$,conjg(tauq2(i)), x12(i,i+1),& ldx12, work ) end if if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_${ci}$larf( 'L', m-q-i+1, m-p-q, x12(i,i), 1_${ik}$,conjg(tauq2(& i)), x22(i,q+1), ldx22, work ) end do ! reduce columns p + 1, ..., m - q of x12, x22 do i = 1, m - p - q call stdlib${ii}$_${ci}$scal( m-p-q-i+1, cmplx( z2*z4, 0.0_${ck}$,KIND=${ck}$),x22(p+i,q+i), 1_${ik}$ ) call stdlib${ii}$_${ci}$larfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i+1,q+i), 1_${ik}$,tauq2(p+i) ) x22(p+i,q+i) = cone if ( m-p-q /= i ) then call stdlib${ii}$_${ci}$larf( 'L', m-p-q-i+1, m-p-q-i, x22(p+i,q+i), 1_${ik}$,conjg(tauq2(p+i)),& x22(p+i,q+i+1), ldx22,work ) end if end do end if return end subroutine stdlib${ii}$_${ci}$unbdb #:endif #:endfor module subroutine stdlib${ii}$_cunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! CUNBDB1 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. Q must be no larger than P, !! M-P, or M-Q. Routines CUNBDB2, CUNBDB3, and CUNBDB4 handle cases in !! which Q is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are Q-by-Q bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(sp), intent(out) :: phi(*), theta(*) complex(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) complex(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(sp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < q .or. m-p < q ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. m-q < q ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-2 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CUNBDB1', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., q of x11 and x21 do i = 1, q call stdlib${ii}$_clarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) call stdlib${ii}$_clarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) theta(i) = atan2( real( x21(i,i),KIND=sp), real( x11(i,i),KIND=sp) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i) = cone x21(i,i) = cone call stdlib${ii}$_clarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, conjg(taup1(i)),x11(i,i+1), ldx11, & work(ilarf) ) call stdlib${ii}$_clarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, conjg(taup2(i)),x21(i,i+1), & ldx21, work(ilarf) ) if( i < q ) then call stdlib${ii}$_csrot( q-i, x11(i,i+1), ldx11, x21(i,i+1), ldx21, c,s ) call stdlib${ii}$_clacgv( q-i, x21(i,i+1), ldx21 ) call stdlib${ii}$_clarfgp( q-i, x21(i,i+1), x21(i,i+2), ldx21, tauq1(i) ) s = real( x21(i,i+1),KIND=sp) x21(i,i+1) = cone call stdlib${ii}$_clarf( 'R', p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x11(i+1,i+1), & ldx11, work(ilarf) ) call stdlib${ii}$_clarf( 'R', m-p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x21(i+1,i+1), & ldx21, work(ilarf) ) call stdlib${ii}$_clacgv( q-i, x21(i,i+1), ldx21 ) c = sqrt( stdlib${ii}$_scnrm2( p-i, x11(i+1,i+1), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_scnrm2( m-p-i, x21(i+& 1_${ik}$,i+1), 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) call stdlib${ii}$_cunbdb5( p-i, m-p-i, q-i-1, x11(i+1,i+1), 1_${ik}$,x21(i+1,i+1), 1_${ik}$, x11(i+1,& i+2), ldx11,x21(i+1,i+2), ldx21, work(iorbdb5), lorbdb5,childinfo ) end if end do return end subroutine stdlib${ii}$_cunbdb1 module subroutine stdlib${ii}$_zunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! ZUNBDB1 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. Q must be no larger than P, !! M-P, or M-Q. Routines ZUNBDB2, ZUNBDB3, and ZUNBDB4 handle cases in !! which Q is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are Q-by-Q bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(dp), intent(out) :: phi(*), theta(*) complex(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) complex(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(dp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < q .or. m-p < q ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. m-q < q ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-2 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB1', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., q of x11 and x21 do i = 1, q call stdlib${ii}$_zlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) call stdlib${ii}$_zlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) theta(i) = atan2( real( x21(i,i),KIND=dp), real( x11(i,i),KIND=dp) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i) = cone x21(i,i) = cone call stdlib${ii}$_zlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, conjg(taup1(i)),x11(i,i+1), ldx11, & work(ilarf) ) call stdlib${ii}$_zlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, conjg(taup2(i)),x21(i,i+1), & ldx21, work(ilarf) ) if( i < q ) then call stdlib${ii}$_zdrot( q-i, x11(i,i+1), ldx11, x21(i,i+1), ldx21, c,s ) call stdlib${ii}$_zlacgv( q-i, x21(i,i+1), ldx21 ) call stdlib${ii}$_zlarfgp( q-i, x21(i,i+1), x21(i,i+2), ldx21, tauq1(i) ) s = real( x21(i,i+1),KIND=dp) x21(i,i+1) = cone call stdlib${ii}$_zlarf( 'R', p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x11(i+1,i+1), & ldx11, work(ilarf) ) call stdlib${ii}$_zlarf( 'R', m-p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x21(i+1,i+1), & ldx21, work(ilarf) ) call stdlib${ii}$_zlacgv( q-i, x21(i,i+1), ldx21 ) c = sqrt( stdlib${ii}$_dznrm2( p-i, x11(i+1,i+1), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dznrm2( m-p-i, x21(i+& 1_${ik}$,i+1), 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) call stdlib${ii}$_zunbdb5( p-i, m-p-i, q-i-1, x11(i+1,i+1), 1_${ik}$,x21(i+1,i+1), 1_${ik}$, x11(i+1,& i+2), ldx11,x21(i+1,i+2), ldx21, work(iorbdb5), lorbdb5,childinfo ) end if end do return end subroutine stdlib${ii}$_zunbdb1 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$unbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! ZUNBDB1: simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. Q must be no larger than P, !! M-P, or M-Q. Routines ZUNBDB2, ZUNBDB3, and ZUNBDB4 handle cases in !! which Q is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are Q-by-Q bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(${ck}$), intent(out) :: phi(*), theta(*) complex(${ck}$), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) complex(${ck}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(${ck}$) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < q .or. m-p < q ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. m-q < q ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-2 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB1', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., q of x11 and x21 do i = 1, q call stdlib${ii}$_${ci}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) call stdlib${ii}$_${ci}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) theta(i) = atan2( real( x21(i,i),KIND=${ck}$), real( x11(i,i),KIND=${ck}$) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i) = cone x21(i,i) = cone call stdlib${ii}$_${ci}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, conjg(taup1(i)),x11(i,i+1), ldx11, & work(ilarf) ) call stdlib${ii}$_${ci}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, conjg(taup2(i)),x21(i,i+1), & ldx21, work(ilarf) ) if( i < q ) then call stdlib${ii}$_${ci}$drot( q-i, x11(i,i+1), ldx11, x21(i,i+1), ldx21, c,s ) call stdlib${ii}$_${ci}$lacgv( q-i, x21(i,i+1), ldx21 ) call stdlib${ii}$_${ci}$larfgp( q-i, x21(i,i+1), x21(i,i+2), ldx21, tauq1(i) ) s = real( x21(i,i+1),KIND=${ck}$) x21(i,i+1) = cone call stdlib${ii}$_${ci}$larf( 'R', p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x11(i+1,i+1), & ldx11, work(ilarf) ) call stdlib${ii}$_${ci}$larf( 'R', m-p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x21(i+1,i+1), & ldx21, work(ilarf) ) call stdlib${ii}$_${ci}$lacgv( q-i, x21(i,i+1), ldx21 ) c = sqrt( stdlib${ii}$_${c2ri(ci)}$znrm2( p-i, x11(i+1,i+1), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${c2ri(ci)}$znrm2( m-p-i, x21(i+& 1_${ik}$,i+1), 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) call stdlib${ii}$_${ci}$unbdb5( p-i, m-p-i, q-i-1, x11(i+1,i+1), 1_${ik}$,x21(i+1,i+1), 1_${ik}$, x11(i+1,& i+2), ldx11,x21(i+1,i+2), ldx21, work(iorbdb5), lorbdb5,childinfo ) end if end do return end subroutine stdlib${ii}$_${ci}$unbdb1 #:endif #:endfor module subroutine stdlib${ii}$_cunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! CUNBDB2 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. P must be no larger than M-P, !! Q, or M-Q. Routines CUNBDB1, CUNBDB3, and CUNBDB4 handle cases in !! which P is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are P-by-P bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(sp), intent(out) :: phi(*), theta(*) complex(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) complex(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(sp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < 0_${ik}$ .or. p > m-p ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. q < p .or. m-q < p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CUNBDB2', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., p of x11 and x21 do i = 1, p if( i > 1_${ik}$ ) then call stdlib${ii}$_csrot( q-i+1, x11(i,i), ldx11, x21(i-1,i), ldx21, c,s ) end if call stdlib${ii}$_clacgv( q-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_clarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) c = real( x11(i,i),KIND=sp) x11(i,i) = cone call stdlib${ii}$_clarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_clarf( 'R', m-p-i+1, q-i+1, x11(i,i), ldx11, tauq1(i),x21(i,i), ldx21, & work(ilarf) ) call stdlib${ii}$_clacgv( q-i+1, x11(i,i), ldx11 ) s = sqrt( stdlib${ii}$_scnrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_scnrm2( m-p-i+1, x21(i,i), & 1_${ik}$ )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_cunbdb5( p-i, m-p-i+1, q-i, x11(i+1,i), 1_${ik}$, x21(i,i), 1_${ik}$,x11(i+1,i+1), & ldx11, x21(i,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_cscal( p-i, cnegone, x11(i+1,i), 1_${ik}$ ) call stdlib${ii}$_clarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) if( i < p ) then call stdlib${ii}$_clarfgp( p-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, taup1(i) ) phi(i) = atan2( real( x11(i+1,i),KIND=sp), real( x21(i,i),KIND=sp) ) c = cos( phi(i) ) s = sin( phi(i) ) x11(i+1,i) = cone call stdlib${ii}$_clarf( 'L', p-i, q-i, x11(i+1,i), 1_${ik}$, conjg(taup1(i)),x11(i+1,i+1), & ldx11, work(ilarf) ) end if x21(i,i) = cone call stdlib${ii}$_clarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, conjg(taup2(i)),x21(i,i+1), & ldx21, work(ilarf) ) end do ! reduce the bottom-right portion of x21 to the identity matrix do i = p + 1, q call stdlib${ii}$_clarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) x21(i,i) = cone call stdlib${ii}$_clarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, conjg(taup2(i)),x21(i,i+1), & ldx21, work(ilarf) ) end do return end subroutine stdlib${ii}$_cunbdb2 module subroutine stdlib${ii}$_zunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! ZUNBDB2 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. P must be no larger than M-P, !! Q, or M-Q. Routines ZUNBDB1, ZUNBDB3, and ZUNBDB4 handle cases in !! which P is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are P-by-P bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(dp), intent(out) :: phi(*), theta(*) complex(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) complex(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(dp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < 0_${ik}$ .or. p > m-p ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. q < p .or. m-q < p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB2', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., p of x11 and x21 do i = 1, p if( i > 1_${ik}$ ) then call stdlib${ii}$_zdrot( q-i+1, x11(i,i), ldx11, x21(i-1,i), ldx21, c,s ) end if call stdlib${ii}$_zlacgv( q-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_zlarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) c = real( x11(i,i),KIND=dp) x11(i,i) = cone call stdlib${ii}$_zlarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_zlarf( 'R', m-p-i+1, q-i+1, x11(i,i), ldx11, tauq1(i),x21(i,i), ldx21, & work(ilarf) ) call stdlib${ii}$_zlacgv( q-i+1, x11(i,i), ldx11 ) s = sqrt( stdlib${ii}$_dznrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dznrm2( m-p-i+1, x21(i,i), & 1_${ik}$ )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_zunbdb5( p-i, m-p-i+1, q-i, x11(i+1,i), 1_${ik}$, x21(i,i), 1_${ik}$,x11(i+1,i+1), & ldx11, x21(i,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_zscal( p-i, cnegone, x11(i+1,i), 1_${ik}$ ) call stdlib${ii}$_zlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) if( i < p ) then call stdlib${ii}$_zlarfgp( p-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, taup1(i) ) phi(i) = atan2( real( x11(i+1,i),KIND=dp), real( x21(i,i),KIND=dp) ) c = cos( phi(i) ) s = sin( phi(i) ) x11(i+1,i) = cone call stdlib${ii}$_zlarf( 'L', p-i, q-i, x11(i+1,i), 1_${ik}$, conjg(taup1(i)),x11(i+1,i+1), & ldx11, work(ilarf) ) end if x21(i,i) = cone call stdlib${ii}$_zlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, conjg(taup2(i)),x21(i,i+1), & ldx21, work(ilarf) ) end do ! reduce the bottom-right portion of x21 to the identity matrix do i = p + 1, q call stdlib${ii}$_zlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) x21(i,i) = cone call stdlib${ii}$_zlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, conjg(taup2(i)),x21(i,i+1), & ldx21, work(ilarf) ) end do return end subroutine stdlib${ii}$_zunbdb2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$unbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! ZUNBDB2: simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. P must be no larger than M-P, !! Q, or M-Q. Routines ZUNBDB1, ZUNBDB3, and ZUNBDB4 handle cases in !! which P is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are P-by-P bidiagonal matrices represented implicitly by !! angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(${ck}$), intent(out) :: phi(*), theta(*) complex(${ck}$), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) complex(${ck}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(${ck}$) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < 0_${ik}$ .or. p > m-p ) then info = -2_${ik}$ else if( q < 0_${ik}$ .or. q < p .or. m-q < p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p-1, m-p, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB2', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., p of x11 and x21 do i = 1, p if( i > 1_${ik}$ ) then call stdlib${ii}$_${ci}$drot( q-i+1, x11(i,i), ldx11, x21(i-1,i), ldx21, c,s ) end if call stdlib${ii}$_${ci}$lacgv( q-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_${ci}$larfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) c = real( x11(i,i),KIND=${ck}$) x11(i,i) = cone call stdlib${ii}$_${ci}$larf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_${ci}$larf( 'R', m-p-i+1, q-i+1, x11(i,i), ldx11, tauq1(i),x21(i,i), ldx21, & work(ilarf) ) call stdlib${ii}$_${ci}$lacgv( q-i+1, x11(i,i), ldx11 ) s = sqrt( stdlib${ii}$_${c2ri(ci)}$znrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${c2ri(ci)}$znrm2( m-p-i+1, x21(i,i), & 1_${ik}$ )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_${ci}$unbdb5( p-i, m-p-i+1, q-i, x11(i+1,i), 1_${ik}$, x21(i,i), 1_${ik}$,x11(i+1,i+1), & ldx11, x21(i,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_${ci}$scal( p-i, cnegone, x11(i+1,i), 1_${ik}$ ) call stdlib${ii}$_${ci}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) if( i < p ) then call stdlib${ii}$_${ci}$larfgp( p-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, taup1(i) ) phi(i) = atan2( real( x11(i+1,i),KIND=${ck}$), real( x21(i,i),KIND=${ck}$) ) c = cos( phi(i) ) s = sin( phi(i) ) x11(i+1,i) = cone call stdlib${ii}$_${ci}$larf( 'L', p-i, q-i, x11(i+1,i), 1_${ik}$, conjg(taup1(i)),x11(i+1,i+1), & ldx11, work(ilarf) ) end if x21(i,i) = cone call stdlib${ii}$_${ci}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, conjg(taup2(i)),x21(i,i+1), & ldx21, work(ilarf) ) end do ! reduce the bottom-right portion of x21 to the identity matrix do i = p + 1, q call stdlib${ii}$_${ci}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) ) x21(i,i) = cone call stdlib${ii}$_${ci}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, conjg(taup2(i)),x21(i,i+1), & ldx21, work(ilarf) ) end do return end subroutine stdlib${ii}$_${ci}$unbdb2 #:endif #:endfor module subroutine stdlib${ii}$_cunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! CUNBDB3 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-P must be no larger than P, !! Q, or M-Q. Routines CUNBDB1, CUNBDB2, and CUNBDB4 handle cases in !! which M-P is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-P)-by-(M-P) bidiagonal matrices represented !! implicitly by angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(sp), intent(out) :: phi(*), theta(*) complex(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) complex(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(sp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( 2_${ik}$*p < m .or. p > m ) then info = -2_${ik}$ else if( q < m-p .or. m-q < m-p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CUNBDB3', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., m-p of x11 and x21 do i = 1, m-p if( i > 1_${ik}$ ) then call stdlib${ii}$_csrot( q-i+1, x11(i-1,i), ldx11, x21(i,i), ldx11, c,s ) end if call stdlib${ii}$_clacgv( q-i+1, x21(i,i), ldx21 ) call stdlib${ii}$_clarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) s = real( x21(i,i),KIND=sp) x21(i,i) = cone call stdlib${ii}$_clarf( 'R', p-i+1, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i,i), ldx11, & work(ilarf) ) call stdlib${ii}$_clarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) call stdlib${ii}$_clacgv( q-i+1, x21(i,i), ldx21 ) c = sqrt( stdlib${ii}$_scnrm2( p-i+1, x11(i,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_scnrm2( m-p-i, x21(i+1,i), & 1_${ik}$ )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_cunbdb5( p-i+1, m-p-i, q-i, x11(i,i), 1_${ik}$, x21(i+1,i), 1_${ik}$,x11(i,i+1), & ldx11, x21(i+1,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_clarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) if( i < m-p ) then call stdlib${ii}$_clarfgp( m-p-i, x21(i+1,i), x21(i+2,i), 1_${ik}$, taup2(i) ) phi(i) = atan2( real( x21(i+1,i),KIND=sp), real( x11(i,i),KIND=sp) ) c = cos( phi(i) ) s = sin( phi(i) ) x21(i+1,i) = cone call stdlib${ii}$_clarf( 'L', m-p-i, q-i, x21(i+1,i), 1_${ik}$, conjg(taup2(i)),x21(i+1,i+1), & ldx21, work(ilarf) ) end if x11(i,i) = cone call stdlib${ii}$_clarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, conjg(taup1(i)),x11(i,i+1), ldx11, & work(ilarf) ) end do ! reduce the bottom-right portion of x11 to the identity matrix do i = m-p + 1, q call stdlib${ii}$_clarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) x11(i,i) = cone call stdlib${ii}$_clarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, conjg(taup1(i)),x11(i,i+1), ldx11, & work(ilarf) ) end do return end subroutine stdlib${ii}$_cunbdb3 module subroutine stdlib${ii}$_zunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! ZUNBDB3 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-P must be no larger than P, !! Q, or M-Q. Routines ZUNBDB1, ZUNBDB2, and ZUNBDB4 handle cases in !! which M-P is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-P)-by-(M-P) bidiagonal matrices represented !! implicitly by angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(dp), intent(out) :: phi(*), theta(*) complex(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) complex(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(dp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( 2_${ik}$*p < m .or. p > m ) then info = -2_${ik}$ else if( q < m-p .or. m-q < m-p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB3', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., m-p of x11 and x21 do i = 1, m-p if( i > 1_${ik}$ ) then call stdlib${ii}$_zdrot( q-i+1, x11(i-1,i), ldx11, x21(i,i), ldx11, c,s ) end if call stdlib${ii}$_zlacgv( q-i+1, x21(i,i), ldx21 ) call stdlib${ii}$_zlarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) s = real( x21(i,i),KIND=dp) x21(i,i) = cone call stdlib${ii}$_zlarf( 'R', p-i+1, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i,i), ldx11, & work(ilarf) ) call stdlib${ii}$_zlarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) call stdlib${ii}$_zlacgv( q-i+1, x21(i,i), ldx21 ) c = sqrt( stdlib${ii}$_dznrm2( p-i+1, x11(i,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dznrm2( m-p-i, x21(i+1,i), & 1_${ik}$ )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_zunbdb5( p-i+1, m-p-i, q-i, x11(i,i), 1_${ik}$, x21(i+1,i), 1_${ik}$,x11(i,i+1), & ldx11, x21(i+1,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_zlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) if( i < m-p ) then call stdlib${ii}$_zlarfgp( m-p-i, x21(i+1,i), x21(i+2,i), 1_${ik}$, taup2(i) ) phi(i) = atan2( real( x21(i+1,i),KIND=dp), real( x11(i,i),KIND=dp) ) c = cos( phi(i) ) s = sin( phi(i) ) x21(i+1,i) = cone call stdlib${ii}$_zlarf( 'L', m-p-i, q-i, x21(i+1,i), 1_${ik}$,conjg(taup2(i)), x21(i+1,i+1), & ldx21,work(ilarf) ) end if x11(i,i) = cone call stdlib${ii}$_zlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, conjg(taup1(i)),x11(i,i+1), ldx11, & work(ilarf) ) end do ! reduce the bottom-right portion of x11 to the identity matrix do i = m-p + 1, q call stdlib${ii}$_zlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) x11(i,i) = cone call stdlib${ii}$_zlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, conjg(taup1(i)),x11(i,i+1), ldx11, & work(ilarf) ) end do return end subroutine stdlib${ii}$_zunbdb3 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$unbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! ZUNBDB3: simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-P must be no larger than P, !! Q, or M-Q. Routines ZUNBDB1, ZUNBDB2, and ZUNBDB4 handle cases in !! which M-P is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-P)-by-(M-P) bidiagonal matrices represented !! implicitly by angles THETA, PHI. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(${ck}$), intent(out) :: phi(*), theta(*) complex(${ck}$), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*) complex(${ck}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(${ck}$) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( 2_${ik}$*p < m .or. p > m ) then info = -2_${ik}$ else if( q < m-p .or. m-q < m-p ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( p, m-p-1, q-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q-1 lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB3', -info ) return else if( lquery ) then return end if ! reduce rows 1, ..., m-p of x11 and x21 do i = 1, m-p if( i > 1_${ik}$ ) then call stdlib${ii}$_${ci}$drot( q-i+1, x11(i-1,i), ldx11, x21(i,i), ldx11, c,s ) end if call stdlib${ii}$_${ci}$lacgv( q-i+1, x21(i,i), ldx21 ) call stdlib${ii}$_${ci}$larfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) s = real( x21(i,i),KIND=${ck}$) x21(i,i) = cone call stdlib${ii}$_${ci}$larf( 'R', p-i+1, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i,i), ldx11, & work(ilarf) ) call stdlib${ii}$_${ci}$larf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) call stdlib${ii}$_${ci}$lacgv( q-i+1, x21(i,i), ldx21 ) c = sqrt( stdlib${ii}$_${c2ri(ci)}$znrm2( p-i+1, x11(i,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${c2ri(ci)}$znrm2( m-p-i, x21(i+1,i), & 1_${ik}$ )**2_${ik}$ ) theta(i) = atan2( s, c ) call stdlib${ii}$_${ci}$unbdb5( p-i+1, m-p-i, q-i, x11(i,i), 1_${ik}$, x21(i+1,i), 1_${ik}$,x11(i,i+1), & ldx11, x21(i+1,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_${ci}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) if( i < m-p ) then call stdlib${ii}$_${ci}$larfgp( m-p-i, x21(i+1,i), x21(i+2,i), 1_${ik}$, taup2(i) ) phi(i) = atan2( real( x21(i+1,i),KIND=${ck}$), real( x11(i,i),KIND=${ck}$) ) c = cos( phi(i) ) s = sin( phi(i) ) x21(i+1,i) = cone call stdlib${ii}$_${ci}$larf( 'L', m-p-i, q-i, x21(i+1,i), 1_${ik}$,conjg(taup2(i)), x21(i+1,i+1), & ldx21,work(ilarf) ) end if x11(i,i) = cone call stdlib${ii}$_${ci}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, conjg(taup1(i)),x11(i,i+1), ldx11, & work(ilarf) ) end do ! reduce the bottom-right portion of x11 to the identity matrix do i = m-p + 1, q call stdlib${ii}$_${ci}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) ) x11(i,i) = cone call stdlib${ii}$_${ci}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, conjg(taup1(i)),x11(i,i+1), ldx11, & work(ilarf) ) end do return end subroutine stdlib${ii}$_${ci}$unbdb3 #:endif #:endfor module subroutine stdlib${ii}$_cunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! CUNBDB4 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-Q must be no larger than P, !! M-P, or Q. Routines CUNBDB1, CUNBDB2, and CUNBDB3 handle cases in !! which M-Q is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-Q)-by-(M-Q) bidiagonal matrices represented !! implicitly by angles THETA, PHI. phantom, work, lwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(sp), intent(out) :: phi(*), theta(*) complex(sp), intent(out) :: phantom(*), taup1(*), taup2(*), tauq1(*), work(*) complex(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(sp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, j, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < m-q .or. m-p < m-q ) then info = -2_${ik}$ else if( q < m-q .or. q > m ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( q-1, p-1, m-p-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q lworkopt = ilarf + llarf - 1_${ik}$ lworkopt = max( lworkopt, iorbdb5 + lorbdb5 - 1_${ik}$ ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CUNBDB4', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., m-q of x11 and x21 do i = 1, m-q if( i == 1_${ik}$ ) then do j = 1, m phantom(j) = czero end do call stdlib${ii}$_cunbdb5( p, m-p, q, phantom(1_${ik}$), 1_${ik}$, phantom(p+1), 1_${ik}$,x11, ldx11, x21, & ldx21, work(iorbdb5),lorbdb5, childinfo ) call stdlib${ii}$_cscal( p, cnegone, phantom(1_${ik}$), 1_${ik}$ ) call stdlib${ii}$_clarfgp( p, phantom(1_${ik}$), phantom(2_${ik}$), 1_${ik}$, taup1(1_${ik}$) ) call stdlib${ii}$_clarfgp( m-p, phantom(p+1), phantom(p+2), 1_${ik}$, taup2(1_${ik}$) ) theta(i) = atan2( real( phantom(1_${ik}$),KIND=sp), real( phantom(p+1),KIND=sp) ) c = cos( theta(i) ) s = sin( theta(i) ) phantom(1_${ik}$) = cone phantom(p+1) = cone call stdlib${ii}$_clarf( 'L', p, q, phantom(1_${ik}$), 1_${ik}$, conjg(taup1(1_${ik}$)), x11,ldx11, work(& ilarf) ) call stdlib${ii}$_clarf( 'L', m-p, q, phantom(p+1), 1_${ik}$, conjg(taup2(1_${ik}$)),x21, ldx21, & work(ilarf) ) else call stdlib${ii}$_cunbdb5( p-i+1, m-p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,x21(i,i-1), 1_${ik}$, x11(i,i)& , ldx11, x21(i,i),ldx21, work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_cscal( p-i+1, cnegone, x11(i,i-1), 1_${ik}$ ) call stdlib${ii}$_clarfgp( p-i+1, x11(i,i-1), x11(i+1,i-1), 1_${ik}$, taup1(i) ) call stdlib${ii}$_clarfgp( m-p-i+1, x21(i,i-1), x21(i+1,i-1), 1_${ik}$,taup2(i) ) theta(i) = atan2( real( x11(i,i-1),KIND=sp), real( x21(i,i-1),KIND=sp) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i-1) = cone x21(i,i-1) = cone call stdlib${ii}$_clarf( 'L', p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,conjg(taup1(i)), x11(i,i), & ldx11, work(ilarf) ) call stdlib${ii}$_clarf( 'L', m-p-i+1, q-i+1, x21(i,i-1), 1_${ik}$,conjg(taup2(i)), x21(i,i), & ldx21, work(ilarf) ) end if call stdlib${ii}$_csrot( q-i+1, x11(i,i), ldx11, x21(i,i), ldx21, s, -c ) call stdlib${ii}$_clacgv( q-i+1, x21(i,i), ldx21 ) call stdlib${ii}$_clarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) c = real( x21(i,i),KIND=sp) x21(i,i) = cone call stdlib${ii}$_clarf( 'R', p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_clarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) call stdlib${ii}$_clacgv( q-i+1, x21(i,i), ldx21 ) if( i < m-q ) then s = sqrt( stdlib${ii}$_scnrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_scnrm2( m-p-i, x21(i+1,& i), 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) end if end do ! reduce the bottom-right portion of x11 to [ i 0 ] do i = m - q + 1, p call stdlib${ii}$_clacgv( q-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_clarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) x11(i,i) = cone call stdlib${ii}$_clarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_clarf( 'R', q-p, q-i+1, x11(i,i), ldx11, tauq1(i),x21(m-q+1,i), ldx21, & work(ilarf) ) call stdlib${ii}$_clacgv( q-i+1, x11(i,i), ldx11 ) end do ! reduce the bottom-right portion of x21 to [ 0 i ] do i = p + 1, q call stdlib${ii}$_clacgv( q-i+1, x21(m-q+i-p,i), ldx21 ) call stdlib${ii}$_clarfgp( q-i+1, x21(m-q+i-p,i), x21(m-q+i-p,i+1), ldx21,tauq1(i) ) x21(m-q+i-p,i) = cone call stdlib${ii}$_clarf( 'R', q-i, q-i+1, x21(m-q+i-p,i), ldx21, tauq1(i),x21(m-q+i-p+1,i)& , ldx21, work(ilarf) ) call stdlib${ii}$_clacgv( q-i+1, x21(m-q+i-p,i), ldx21 ) end do return end subroutine stdlib${ii}$_cunbdb4 module subroutine stdlib${ii}$_zunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! ZUNBDB4 simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-Q must be no larger than P, !! M-P, or Q. Routines ZUNBDB1, ZUNBDB2, and ZUNBDB3 handle cases in !! which M-Q is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-Q)-by-(M-Q) bidiagonal matrices represented !! implicitly by angles THETA, PHI. phantom, work, lwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(dp), intent(out) :: phi(*), theta(*) complex(dp), intent(out) :: phantom(*), taup1(*), taup2(*), tauq1(*), work(*) complex(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(dp) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, j, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < m-q .or. m-p < m-q ) then info = -2_${ik}$ else if( q < m-q .or. q > m ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( q-1, p-1, m-p-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q lworkopt = ilarf + llarf - 1_${ik}$ lworkopt = max( lworkopt, iorbdb5 + lorbdb5 - 1_${ik}$ ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB4', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., m-q of x11 and x21 do i = 1, m-q if( i == 1_${ik}$ ) then do j = 1, m phantom(j) = czero end do call stdlib${ii}$_zunbdb5( p, m-p, q, phantom(1_${ik}$), 1_${ik}$, phantom(p+1), 1_${ik}$,x11, ldx11, x21, & ldx21, work(iorbdb5),lorbdb5, childinfo ) call stdlib${ii}$_zscal( p, cnegone, phantom(1_${ik}$), 1_${ik}$ ) call stdlib${ii}$_zlarfgp( p, phantom(1_${ik}$), phantom(2_${ik}$), 1_${ik}$, taup1(1_${ik}$) ) call stdlib${ii}$_zlarfgp( m-p, phantom(p+1), phantom(p+2), 1_${ik}$, taup2(1_${ik}$) ) theta(i) = atan2( real( phantom(1_${ik}$),KIND=dp), real( phantom(p+1),KIND=dp) ) c = cos( theta(i) ) s = sin( theta(i) ) phantom(1_${ik}$) = cone phantom(p+1) = cone call stdlib${ii}$_zlarf( 'L', p, q, phantom(1_${ik}$), 1_${ik}$, conjg(taup1(1_${ik}$)), x11,ldx11, work(& ilarf) ) call stdlib${ii}$_zlarf( 'L', m-p, q, phantom(p+1), 1_${ik}$, conjg(taup2(1_${ik}$)),x21, ldx21, & work(ilarf) ) else call stdlib${ii}$_zunbdb5( p-i+1, m-p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,x21(i,i-1), 1_${ik}$, x11(i,i)& , ldx11, x21(i,i),ldx21, work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_zscal( p-i+1, cnegone, x11(i,i-1), 1_${ik}$ ) call stdlib${ii}$_zlarfgp( p-i+1, x11(i,i-1), x11(i+1,i-1), 1_${ik}$, taup1(i) ) call stdlib${ii}$_zlarfgp( m-p-i+1, x21(i,i-1), x21(i+1,i-1), 1_${ik}$,taup2(i) ) theta(i) = atan2( real( x11(i,i-1),KIND=dp), real( x21(i,i-1),KIND=dp) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i-1) = cone x21(i,i-1) = cone call stdlib${ii}$_zlarf( 'L', p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,conjg(taup1(i)), x11(i,i), & ldx11, work(ilarf) ) call stdlib${ii}$_zlarf( 'L', m-p-i+1, q-i+1, x21(i,i-1), 1_${ik}$,conjg(taup2(i)), x21(i,i), & ldx21, work(ilarf) ) end if call stdlib${ii}$_zdrot( q-i+1, x11(i,i), ldx11, x21(i,i), ldx21, s, -c ) call stdlib${ii}$_zlacgv( q-i+1, x21(i,i), ldx21 ) call stdlib${ii}$_zlarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) c = real( x21(i,i),KIND=dp) x21(i,i) = cone call stdlib${ii}$_zlarf( 'R', p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_zlarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) call stdlib${ii}$_zlacgv( q-i+1, x21(i,i), ldx21 ) if( i < m-q ) then s = sqrt( stdlib${ii}$_dznrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dznrm2( m-p-i, x21(i+1,& i), 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) end if end do ! reduce the bottom-right portion of x11 to [ i 0 ] do i = m - q + 1, p call stdlib${ii}$_zlacgv( q-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_zlarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) x11(i,i) = cone call stdlib${ii}$_zlarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_zlarf( 'R', q-p, q-i+1, x11(i,i), ldx11, tauq1(i),x21(m-q+1,i), ldx21, & work(ilarf) ) call stdlib${ii}$_zlacgv( q-i+1, x11(i,i), ldx11 ) end do ! reduce the bottom-right portion of x21 to [ 0 i ] do i = p + 1, q call stdlib${ii}$_zlacgv( q-i+1, x21(m-q+i-p,i), ldx21 ) call stdlib${ii}$_zlarfgp( q-i+1, x21(m-q+i-p,i), x21(m-q+i-p,i+1), ldx21,tauq1(i) ) x21(m-q+i-p,i) = cone call stdlib${ii}$_zlarf( 'R', q-i, q-i+1, x21(m-q+i-p,i), ldx21, tauq1(i),x21(m-q+i-p+1,i)& , ldx21, work(ilarf) ) call stdlib${ii}$_zlacgv( q-i+1, x21(m-q+i-p,i), ldx21 ) end do return end subroutine stdlib${ii}$_zunbdb4 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$unbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, & !! ZUNBDB4: simultaneously bidiagonalizes the blocks of a tall and skinny !! matrix X with orthonomal columns: !! [ B11 ] !! [ X11 ] [ P1 | ] [ 0 ] !! [-----] = [---------] [-----] Q1**T . !! [ X21 ] [ | P2 ] [ B21 ] !! [ 0 ] !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-Q must be no larger than P, !! M-P, or Q. Routines ZUNBDB1, ZUNBDB2, and ZUNBDB3 handle cases in !! which M-Q is not the minimum dimension. !! The unitary matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P), !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by !! Householder vectors. !! B11 and B12 are (M-Q)-by-(M-Q) bidiagonal matrices represented !! implicitly by angles THETA, PHI. phantom, work, lwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21 ! Array Arguments real(${ck}$), intent(out) :: phi(*), theta(*) complex(${ck}$), intent(out) :: phantom(*), taup1(*), taup2(*), tauq1(*), work(*) complex(${ck}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*) ! ==================================================================== ! Local Scalars real(${ck}$) :: c, s integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, j, llarf, lorbdb5, lworkmin, & lworkopt logical(lk) :: lquery ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ lquery = lwork == -1_${ik}$ if( m < 0_${ik}$ ) then info = -1_${ik}$ else if( p < m-q .or. m-p < m-q ) then info = -2_${ik}$ else if( q < m-q .or. q > m ) then info = -3_${ik}$ else if( ldx11 < max( 1_${ik}$, p ) ) then info = -5_${ik}$ else if( ldx21 < max( 1_${ik}$, m-p ) ) then info = -7_${ik}$ end if ! compute workspace if( info == 0_${ik}$ ) then ilarf = 2_${ik}$ llarf = max( q-1, p-1, m-p-1 ) iorbdb5 = 2_${ik}$ lorbdb5 = q lworkopt = ilarf + llarf - 1_${ik}$ lworkopt = max( lworkopt, iorbdb5 + lorbdb5 - 1_${ik}$ ) lworkmin = lworkopt work(1_${ik}$) = lworkopt if( lwork < lworkmin .and. .not.lquery ) then info = -14_${ik}$ end if end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB4', -info ) return else if( lquery ) then return end if ! reduce columns 1, ..., m-q of x11 and x21 do i = 1, m-q if( i == 1_${ik}$ ) then do j = 1, m phantom(j) = czero end do call stdlib${ii}$_${ci}$unbdb5( p, m-p, q, phantom(1_${ik}$), 1_${ik}$, phantom(p+1), 1_${ik}$,x11, ldx11, x21, & ldx21, work(iorbdb5),lorbdb5, childinfo ) call stdlib${ii}$_${ci}$scal( p, cnegone, phantom(1_${ik}$), 1_${ik}$ ) call stdlib${ii}$_${ci}$larfgp( p, phantom(1_${ik}$), phantom(2_${ik}$), 1_${ik}$, taup1(1_${ik}$) ) call stdlib${ii}$_${ci}$larfgp( m-p, phantom(p+1), phantom(p+2), 1_${ik}$, taup2(1_${ik}$) ) theta(i) = atan2( real( phantom(1_${ik}$),KIND=${ck}$), real( phantom(p+1),KIND=${ck}$) ) c = cos( theta(i) ) s = sin( theta(i) ) phantom(1_${ik}$) = cone phantom(p+1) = cone call stdlib${ii}$_${ci}$larf( 'L', p, q, phantom(1_${ik}$), 1_${ik}$, conjg(taup1(1_${ik}$)), x11,ldx11, work(& ilarf) ) call stdlib${ii}$_${ci}$larf( 'L', m-p, q, phantom(p+1), 1_${ik}$, conjg(taup2(1_${ik}$)),x21, ldx21, & work(ilarf) ) else call stdlib${ii}$_${ci}$unbdb5( p-i+1, m-p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,x21(i,i-1), 1_${ik}$, x11(i,i)& , ldx11, x21(i,i),ldx21, work(iorbdb5), lorbdb5, childinfo ) call stdlib${ii}$_${ci}$scal( p-i+1, cnegone, x11(i,i-1), 1_${ik}$ ) call stdlib${ii}$_${ci}$larfgp( p-i+1, x11(i,i-1), x11(i+1,i-1), 1_${ik}$, taup1(i) ) call stdlib${ii}$_${ci}$larfgp( m-p-i+1, x21(i,i-1), x21(i+1,i-1), 1_${ik}$,taup2(i) ) theta(i) = atan2( real( x11(i,i-1),KIND=${ck}$), real( x21(i,i-1),KIND=${ck}$) ) c = cos( theta(i) ) s = sin( theta(i) ) x11(i,i-1) = cone x21(i,i-1) = cone call stdlib${ii}$_${ci}$larf( 'L', p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,conjg(taup1(i)), x11(i,i), & ldx11, work(ilarf) ) call stdlib${ii}$_${ci}$larf( 'L', m-p-i+1, q-i+1, x21(i,i-1), 1_${ik}$,conjg(taup2(i)), x21(i,i), & ldx21, work(ilarf) ) end if call stdlib${ii}$_${ci}$drot( q-i+1, x11(i,i), ldx11, x21(i,i), ldx21, s, -c ) call stdlib${ii}$_${ci}$lacgv( q-i+1, x21(i,i), ldx21 ) call stdlib${ii}$_${ci}$larfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) ) c = real( x21(i,i),KIND=${ck}$) x21(i,i) = cone call stdlib${ii}$_${ci}$larf( 'R', p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_${ci}$larf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, & work(ilarf) ) call stdlib${ii}$_${ci}$lacgv( q-i+1, x21(i,i), ldx21 ) if( i < m-q ) then s = sqrt( stdlib${ii}$_${c2ri(ci)}$znrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${c2ri(ci)}$znrm2( m-p-i, x21(i+1,& i), 1_${ik}$ )**2_${ik}$ ) phi(i) = atan2( s, c ) end if end do ! reduce the bottom-right portion of x11 to [ i 0 ] do i = m - q + 1, p call stdlib${ii}$_${ci}$lacgv( q-i+1, x11(i,i), ldx11 ) call stdlib${ii}$_${ci}$larfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) ) x11(i,i) = cone call stdlib${ii}$_${ci}$larf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, & work(ilarf) ) call stdlib${ii}$_${ci}$larf( 'R', q-p, q-i+1, x11(i,i), ldx11, tauq1(i),x21(m-q+1,i), ldx21, & work(ilarf) ) call stdlib${ii}$_${ci}$lacgv( q-i+1, x11(i,i), ldx11 ) end do ! reduce the bottom-right portion of x21 to [ 0 i ] do i = p + 1, q call stdlib${ii}$_${ci}$lacgv( q-i+1, x21(m-q+i-p,i), ldx21 ) call stdlib${ii}$_${ci}$larfgp( q-i+1, x21(m-q+i-p,i), x21(m-q+i-p,i+1), ldx21,tauq1(i) ) x21(m-q+i-p,i) = cone call stdlib${ii}$_${ci}$larf( 'R', q-i, q-i+1, x21(m-q+i-p,i), ldx21, tauq1(i),x21(m-q+i-p+1,i)& , ldx21, work(ilarf) ) call stdlib${ii}$_${ci}$lacgv( q-i+1, x21(m-q+i-p,i), ldx21 ) end do return end subroutine stdlib${ii}$_${ci}$unbdb4 #:endif #:endfor pure module subroutine stdlib${ii}$_cunbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & !! CUNBDB5 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then some other vector from the orthogonal complement !! is returned. This vector is chosen in an arbitrary but deterministic !! way. lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(sp), intent(in) :: q1(ldq1,*), q2(ldq2,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, j ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CUNBDB5', -info ) return end if ! project x onto the orthogonal complement of q call stdlib${ii}$_cunbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2, ldq2,work, lwork, & childinfo ) ! if the projection is nonzero, then return if( stdlib${ii}$_scnrm2(m1,x1,incx1) /= czero.or. stdlib${ii}$_scnrm2(m2,x2,incx2) /= czero ) & then return end if ! project each standard basis vector e_1,...,e_m1 in turn, stopping ! when a nonzero projection is found do i = 1, m1 do j = 1, m1 x1(j) = czero end do x1(i) = cone do j = 1, m2 x2(j) = czero end do call stdlib${ii}$_cunbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_scnrm2(m1,x1,incx1) /= czero.or. stdlib${ii}$_scnrm2(m2,x2,incx2) /= czero ) & then return end if end do ! project each standard basis vector e_(m1+1),...,e_(m1+m2) in turn, ! stopping when a nonzero projection is found do i = 1, m2 do j = 1, m1 x1(j) = czero end do do j = 1, m2 x2(j) = czero end do x2(i) = cone call stdlib${ii}$_cunbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_scnrm2(m1,x1,incx1) /= czero.or. stdlib${ii}$_scnrm2(m2,x2,incx2) /= czero ) & then return end if end do return end subroutine stdlib${ii}$_cunbdb5 pure module subroutine stdlib${ii}$_zunbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & !! ZUNBDB5 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then some other vector from the orthogonal complement !! is returned. This vector is chosen in an arbitrary but deterministic !! way. lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(dp), intent(in) :: q1(ldq1,*), q2(ldq2,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, j ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB5', -info ) return end if ! project x onto the orthogonal complement of q call stdlib${ii}$_zunbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2, ldq2,work, lwork, & childinfo ) ! if the projection is nonzero, then return if( stdlib${ii}$_dznrm2(m1,x1,incx1) /= czero.or. stdlib${ii}$_dznrm2(m2,x2,incx2) /= czero ) & then return end if ! project each standard basis vector e_1,...,e_m1 in turn, stopping ! when a nonzero projection is found do i = 1, m1 do j = 1, m1 x1(j) = czero end do x1(i) = cone do j = 1, m2 x2(j) = czero end do call stdlib${ii}$_zunbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_dznrm2(m1,x1,incx1) /= czero.or. stdlib${ii}$_dznrm2(m2,x2,incx2) /= czero ) & then return end if end do ! project each standard basis vector e_(m1+1),...,e_(m1+m2) in turn, ! stopping when a nonzero projection is found do i = 1, m2 do j = 1, m1 x1(j) = czero end do do j = 1, m2 x2(j) = czero end do x2(i) = cone call stdlib${ii}$_zunbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_dznrm2(m1,x1,incx1) /= czero.or. stdlib${ii}$_dznrm2(m2,x2,incx2) /= czero ) & then return end if end do return end subroutine stdlib${ii}$_zunbdb5 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & !! ZUNBDB5: orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then some other vector from the orthogonal complement !! is returned. This vector is chosen in an arbitrary but deterministic !! way. lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(${ck}$), intent(in) :: q1(ldq1,*), q2(ldq2,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: childinfo, i, j ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB5', -info ) return end if ! project x onto the orthogonal complement of q call stdlib${ii}$_${ci}$unbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2, ldq2,work, lwork, & childinfo ) ! if the projection is nonzero, then return if( stdlib${ii}$_${c2ri(ci)}$znrm2(m1,x1,incx1) /= czero.or. stdlib${ii}$_${c2ri(ci)}$znrm2(m2,x2,incx2) /= czero ) & then return end if ! project each standard basis vector e_1,...,e_m1 in turn, stopping ! when a nonzero projection is found do i = 1, m1 do j = 1, m1 x1(j) = czero end do x1(i) = cone do j = 1, m2 x2(j) = czero end do call stdlib${ii}$_${ci}$unbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_${c2ri(ci)}$znrm2(m1,x1,incx1) /= czero.or. stdlib${ii}$_${c2ri(ci)}$znrm2(m2,x2,incx2) /= czero ) & then return end if end do ! project each standard basis vector e_(m1+1),...,e_(m1+m2) in turn, ! stopping when a nonzero projection is found do i = 1, m2 do j = 1, m1 x1(j) = czero end do do j = 1, m2 x2(j) = czero end do x2(i) = cone call stdlib${ii}$_${ci}$unbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & lwork, childinfo ) if( stdlib${ii}$_${c2ri(ci)}$znrm2(m1,x1,incx1) /= czero.or. stdlib${ii}$_${c2ri(ci)}$znrm2(m2,x2,incx2) /= czero ) & then return end if end do return end subroutine stdlib${ii}$_${ci}$unbdb5 #:endif #:endfor pure module subroutine stdlib${ii}$_cunbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, lwork, info ) !! CUNBDB6 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then the zero vector is returned. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(sp), intent(in) :: q1(ldq1,*), q2(ldq2,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Parameters real(sp), parameter :: alphasq = 0.01_sp ! Local Scalars integer(${ik}$) :: i real(sp) :: normsq1, normsq2, scl1, scl2, ssq1, ssq2 ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CUNBDB6', -info ) return end if ! first, project x onto the orthogonal complement of q's column ! space scl1 = zero ssq1 = one call stdlib${ii}$_classq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_classq( m2, x2, incx2, scl2, ssq2 ) normsq1 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = czero end do else call stdlib${ii}$_cgemv( 'C', m1, n, cone, q1, ldq1, x1, incx1, czero, work,1_${ik}$ ) end if call stdlib${ii}$_cgemv( 'C', m2, n, cone, q2, ldq2, x2, incx2, cone, work, 1_${ik}$ ) call stdlib${ii}$_cgemv( 'N', m1, n, cnegone, q1, ldq1, work, 1_${ik}$, cone, x1,incx1 ) call stdlib${ii}$_cgemv( 'N', m2, n, cnegone, q2, ldq2, work, 1_${ik}$, cone, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_classq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_classq( m2, x2, incx2, scl2, ssq2 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if projection is sufficiently large in norm, then stop. ! if projection is czero, then stop. ! otherwise, project again. if( normsq2 >= alphasq*normsq1 ) then return end if if( normsq2 == czero ) then return end if normsq1 = normsq2 do i = 1, n work(i) = czero end do if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = czero end do else call stdlib${ii}$_cgemv( 'C', m1, n, cone, q1, ldq1, x1, incx1, czero, work,1_${ik}$ ) end if call stdlib${ii}$_cgemv( 'C', m2, n, cone, q2, ldq2, x2, incx2, cone, work, 1_${ik}$ ) call stdlib${ii}$_cgemv( 'N', m1, n, cnegone, q1, ldq1, work, 1_${ik}$, cone, x1,incx1 ) call stdlib${ii}$_cgemv( 'N', m2, n, cnegone, q2, ldq2, work, 1_${ik}$, cone, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_classq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_classq( m1, x1, incx1, scl1, ssq1 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if second projection is sufficiently large in norm, then do ! nothing more. alternatively, if it shrunk significantly, then ! truncate it to czero. if( normsq2 < alphasq*normsq1 ) then do i = 1, m1 x1(i) = czero end do do i = 1, m2 x2(i) = czero end do end if return end subroutine stdlib${ii}$_cunbdb6 pure module subroutine stdlib${ii}$_zunbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & !! ZUNBDB6 orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then the zero vector is returned. lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(dp), intent(in) :: q1(ldq1,*), q2(ldq2,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Parameters real(dp), parameter :: alphasq = 0.01_dp ! Local Scalars integer(${ik}$) :: i real(dp) :: normsq1, normsq2, scl1, scl2, ssq1, ssq2 ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB6', -info ) return end if ! first, project x onto the orthogonal complement of q's column ! space scl1 = zero ssq1 = one call stdlib${ii}$_zlassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_zlassq( m2, x2, incx2, scl2, ssq2 ) normsq1 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = czero end do else call stdlib${ii}$_zgemv( 'C', m1, n, cone, q1, ldq1, x1, incx1, czero, work,1_${ik}$ ) end if call stdlib${ii}$_zgemv( 'C', m2, n, cone, q2, ldq2, x2, incx2, cone, work, 1_${ik}$ ) call stdlib${ii}$_zgemv( 'N', m1, n, cnegone, q1, ldq1, work, 1_${ik}$, cone, x1,incx1 ) call stdlib${ii}$_zgemv( 'N', m2, n, cnegone, q2, ldq2, work, 1_${ik}$, cone, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_zlassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_zlassq( m2, x2, incx2, scl2, ssq2 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if projection is sufficiently large in norm, then stop. ! if projection is czero, then stop. ! otherwise, project again. if( normsq2 >= alphasq*normsq1 ) then return end if if( normsq2 == czero ) then return end if normsq1 = normsq2 do i = 1, n work(i) = czero end do if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = czero end do else call stdlib${ii}$_zgemv( 'C', m1, n, cone, q1, ldq1, x1, incx1, czero, work,1_${ik}$ ) end if call stdlib${ii}$_zgemv( 'C', m2, n, cone, q2, ldq2, x2, incx2, cone, work, 1_${ik}$ ) call stdlib${ii}$_zgemv( 'N', m1, n, cnegone, q1, ldq1, work, 1_${ik}$, cone, x1,incx1 ) call stdlib${ii}$_zgemv( 'N', m2, n, cnegone, q2, ldq2, work, 1_${ik}$, cone, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_zlassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_zlassq( m1, x1, incx1, scl1, ssq1 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if second projection is sufficiently large in norm, then do ! nothing more. alternatively, if it shrunk significantly, then ! truncate it to czero. if( normsq2 < alphasq*normsq1 ) then do i = 1, m1 x1(i) = czero end do do i = 1, m2 x2(i) = czero end do end if return end subroutine stdlib${ii}$_zunbdb6 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, & !! ZUNBDB6: orthogonalizes the column vector !! X = [ X1 ] !! [ X2 ] !! with respect to the columns of !! Q = [ Q1 ] . !! [ Q2 ] !! The columns of Q must be orthonormal. !! If the projection is zero according to Kahan's "twice is enough" !! criterion, then the zero vector is returned. lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(${ck}$), intent(in) :: q1(ldq1,*), q2(ldq2,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x1(*), x2(*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: alphasq = 0.01_${ck}$ ! Local Scalars integer(${ik}$) :: i real(${ck}$) :: normsq1, normsq2, scl1, scl2, ssq1, ssq2 ! Intrinsic Function ! Executable Statements ! test input arguments info = 0_${ik}$ if( m1 < 0_${ik}$ ) then info = -1_${ik}$ else if( m2 < 0_${ik}$ ) then info = -2_${ik}$ else if( n < 0_${ik}$ ) then info = -3_${ik}$ else if( incx1 < 1_${ik}$ ) then info = -5_${ik}$ else if( incx2 < 1_${ik}$ ) then info = -7_${ik}$ else if( ldq1 < max( 1_${ik}$, m1 ) ) then info = -9_${ik}$ else if( ldq2 < max( 1_${ik}$, m2 ) ) then info = -11_${ik}$ else if( lwork < n ) then info = -13_${ik}$ end if if( info /= 0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZUNBDB6', -info ) return end if ! first, project x onto the orthogonal complement of q's column ! space scl1 = zero ssq1 = one call stdlib${ii}$_${ci}$lassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_${ci}$lassq( m2, x2, incx2, scl2, ssq2 ) normsq1 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = czero end do else call stdlib${ii}$_${ci}$gemv( 'C', m1, n, cone, q1, ldq1, x1, incx1, czero, work,1_${ik}$ ) end if call stdlib${ii}$_${ci}$gemv( 'C', m2, n, cone, q2, ldq2, x2, incx2, cone, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'N', m1, n, cnegone, q1, ldq1, work, 1_${ik}$, cone, x1,incx1 ) call stdlib${ii}$_${ci}$gemv( 'N', m2, n, cnegone, q2, ldq2, work, 1_${ik}$, cone, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_${ci}$lassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_${ci}$lassq( m2, x2, incx2, scl2, ssq2 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if projection is sufficiently large in norm, then stop. ! if projection is czero, then stop. ! otherwise, project again. if( normsq2 >= alphasq*normsq1 ) then return end if if( normsq2 == czero ) then return end if normsq1 = normsq2 do i = 1, n work(i) = czero end do if( m1 == 0_${ik}$ ) then do i = 1, n work(i) = czero end do else call stdlib${ii}$_${ci}$gemv( 'C', m1, n, cone, q1, ldq1, x1, incx1, czero, work,1_${ik}$ ) end if call stdlib${ii}$_${ci}$gemv( 'C', m2, n, cone, q2, ldq2, x2, incx2, cone, work, 1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'N', m1, n, cnegone, q1, ldq1, work, 1_${ik}$, cone, x1,incx1 ) call stdlib${ii}$_${ci}$gemv( 'N', m2, n, cnegone, q2, ldq2, work, 1_${ik}$, cone, x2,incx2 ) scl1 = zero ssq1 = one call stdlib${ii}$_${ci}$lassq( m1, x1, incx1, scl1, ssq1 ) scl2 = zero ssq2 = one call stdlib${ii}$_${ci}$lassq( m1, x1, incx1, scl1, ssq1 ) normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2 ! if second projection is sufficiently large in norm, then do ! nothing more. alternatively, if it shrunk significantly, then ! truncate it to czero. if( normsq2 < alphasq*normsq1 ) then do i = 1, m1 x1(i) = czero end do do i = 1, m2 x2(i) = czero end do end if return end subroutine stdlib${ii}$_${ci}$unbdb6 #:endif #:endfor #:endfor end submodule stdlib_lapack_cosine_sine fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_solve_lu.fypp0000664000175000017500000061254315135654166025627 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_solve) stdlib_lapack_solve_lu implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgesv( n, nrhs, a, lda, ipiv, b, ldb, info ) !! SGESV computes the solution to a real system of linear equations !! A * X = B, !! where A is an N-by-N matrix and X and B are N-by-NRHS matrices. !! The LU decomposition with partial pivoting and row interchanges is !! used to factor A as !! A = P * L * U, !! where P is a permutation matrix, L is unit lower triangular, and U is !! upper triangular. The factored form of A is then used to solve the !! system of equations A * X = B. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: ipiv(*) real(sp), intent(inout) :: a(lda,*), b(ldb,*) ! ===================================================================== ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( nrhs<0_${ik}$ ) then info = -2_${ik}$ else if( lda0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -12_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. rpvgrw = stdlib${ii}$_slantr( 'M', 'U', 'N', info, info, af, ldaf,work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_slange( 'M', n, info, a, lda, work ) / rpvgrw end if work( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_slange( norm, n, n, a, lda, work ) rpvgrw = stdlib${ii}$_slantr( 'M', 'U', 'N', n, n, af, ldaf, work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_slange( 'M', n, n, a, lda, work ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_sgecon( norm, n, af, ldaf, anorm, rcond, work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_slacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_sgetrs( trans, n, nrhs, af, ldaf, ipiv, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_sgerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb, x,ldx, ferr, berr, & work, iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -12_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. rpvgrw = stdlib${ii}$_dlantr( 'M', 'U', 'N', info, info, af, ldaf,work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_dlange( 'M', n, info, a, lda, work ) / rpvgrw end if work( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_dlange( norm, n, n, a, lda, work ) rpvgrw = stdlib${ii}$_dlantr( 'M', 'U', 'N', n, n, af, ldaf, work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_dlange( 'M', n, n, a, lda, work ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_dgecon( norm, n, af, ldaf, anorm, rcond, work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_dlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_dgetrs( trans, n, nrhs, af, ldaf, ipiv, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_dgerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb, x,ldx, ferr, berr, & work, iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if work( 1_${ik}$ ) = rpvgrw ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -12_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. rpvgrw = stdlib${ii}$_${ri}$lantr( 'M', 'U', 'N', info, info, af, ldaf,work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_${ri}$lange( 'M', n, info, a, lda, work ) / rpvgrw end if work( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_${ri}$lange( norm, n, n, a, lda, work ) rpvgrw = stdlib${ii}$_${ri}$lantr( 'M', 'U', 'N', n, n, af, ldaf, work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, work ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ri}$gecon( norm, n, af, ldaf, anorm, rcond, work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_${ri}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ri}$getrs( trans, n, nrhs, af, ldaf, ipiv, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_${ri}$gerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb, x,ldx, ferr, berr, & work, iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if work( 1_${ik}$ ) = rpvgrw ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -12_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. rpvgrw = stdlib${ii}$_clantr( 'M', 'U', 'N', info, info, af, ldaf,rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_clange( 'M', n, info, a, lda, rwork ) /rpvgrw end if rwork( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_clange( norm, n, n, a, lda, rwork ) rpvgrw = stdlib${ii}$_clantr( 'M', 'U', 'N', n, n, af, ldaf, rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_clange( 'M', n, n, a, lda, rwork ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_cgecon( norm, n, af, ldaf, anorm, rcond, work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_clacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_cgetrs( trans, n, nrhs, af, ldaf, ipiv, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_cgerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb, x,ldx, ferr, berr, & work, rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -12_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. rpvgrw = stdlib${ii}$_zlantr( 'M', 'U', 'N', info, info, af, ldaf,rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_zlange( 'M', n, info, a, lda, rwork ) /rpvgrw end if rwork( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_zlange( norm, n, n, a, lda, rwork ) rpvgrw = stdlib${ii}$_zlantr( 'M', 'U', 'N', n, n, af, ldaf, rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_zlange( 'M', n, n, a, lda, rwork ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_zgecon( norm, n, af, ldaf, anorm, rcond, work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_zlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_zgetrs( trans, n, nrhs, af, ldaf, ipiv, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_zgerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb, x,ldx, ferr, berr, & work, rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -12_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. rpvgrw = stdlib${ii}$_${ci}$lantr( 'M', 'U', 'N', info, info, af, ldaf,rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_${ci}$lange( 'M', n, info, a, lda, rwork ) /rpvgrw end if rwork( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_${ci}$lange( norm, n, n, a, lda, rwork ) rpvgrw = stdlib${ii}$_${ci}$lantr( 'M', 'U', 'N', n, n, af, ldaf, rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, rwork ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ci}$gecon( norm, n, af, ldaf, anorm, rcond, work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_${ci}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ci}$getrs( trans, n, nrhs, af, ldaf, ipiv, x, ldx, info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_${ci}$gerfs( trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb, x,ldx, ferr, berr, & work, rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -14_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. anorm = zero do j = 1, info do i = max( ku+2-j, 1 ), min( n+ku+1-j, kl+ku+1 ) anorm = max( anorm, abs( ab( i, j ) ) ) end do end do rpvgrw = stdlib${ii}$_slantb( 'M', 'U', 'N', info, min( info-1, kl+ku ),afb( max( 1_${ik}$, & kl+ku+2-info ), 1_${ik}$ ), ldafb,work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = anorm / rpvgrw end if work( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_slangb( norm, n, kl, ku, ab, ldab, work ) rpvgrw = stdlib${ii}$_slantb( 'M', 'U', 'N', n, kl+ku, afb, ldafb, work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_slangb( 'M', n, kl, ku, ab, ldab, work ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_sgbcon( norm, n, kl, ku, afb, ldafb, ipiv, anorm, rcond,work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_slacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_sgbtrs( trans, n, kl, ku, nrhs, afb, ldafb, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_sgbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb, ipiv,b, ldb, x, ldx, & ferr, berr, work, iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -14_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. anorm = zero do j = 1, info do i = max( ku+2-j, 1 ), min( n+ku+1-j, kl+ku+1 ) anorm = max( anorm, abs( ab( i, j ) ) ) end do end do rpvgrw = stdlib${ii}$_dlantb( 'M', 'U', 'N', info, min( info-1, kl+ku ),afb( max( 1_${ik}$, & kl+ku+2-info ), 1_${ik}$ ), ldafb,work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = anorm / rpvgrw end if work( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_dlangb( norm, n, kl, ku, ab, ldab, work ) rpvgrw = stdlib${ii}$_dlantb( 'M', 'U', 'N', n, kl+ku, afb, ldafb, work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_dlangb( 'M', n, kl, ku, ab, ldab, work ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_dgbcon( norm, n, kl, ku, afb, ldafb, ipiv, anorm, rcond,work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_dlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_dgbtrs( trans, n, kl, ku, nrhs, afb, ldafb, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_dgbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb, ipiv,b, ldb, x, ldx, & ferr, berr, work, iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -14_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. anorm = zero do j = 1, info do i = max( ku+2-j, 1 ), min( n+ku+1-j, kl+ku+1 ) anorm = max( anorm, abs( ab( i, j ) ) ) end do end do rpvgrw = stdlib${ii}$_${ri}$lantb( 'M', 'U', 'N', info, min( info-1, kl+ku ),afb( max( 1_${ik}$, & kl+ku+2-info ), 1_${ik}$ ), ldafb,work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = anorm / rpvgrw end if work( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_${ri}$langb( norm, n, kl, ku, ab, ldab, work ) rpvgrw = stdlib${ii}$_${ri}$lantb( 'M', 'U', 'N', n, kl+ku, afb, ldafb, work ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_${ri}$langb( 'M', n, kl, ku, ab, ldab, work ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ri}$gbcon( norm, n, kl, ku, afb, ldafb, ipiv, anorm, rcond,work, iwork, info ) ! compute the solution matrix x. call stdlib${ii}$_${ri}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ri}$gbtrs( trans, n, kl, ku, nrhs, afb, ldafb, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_${ri}$gbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb, ipiv,b, ldb, x, ldx, & ferr, berr, work, iwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -14_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. anorm = zero do j = 1, info do i = max( ku+2-j, 1 ), min( n+ku+1-j, kl+ku+1 ) anorm = max( anorm, abs( ab( i, j ) ) ) end do end do rpvgrw = stdlib${ii}$_clantb( 'M', 'U', 'N', info, min( info-1, kl+ku ),afb( max( 1_${ik}$, & kl+ku+2-info ), 1_${ik}$ ), ldafb,rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = anorm / rpvgrw end if rwork( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_clangb( norm, n, kl, ku, ab, ldab, rwork ) rpvgrw = stdlib${ii}$_clantb( 'M', 'U', 'N', n, kl+ku, afb, ldafb, rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_clangb( 'M', n, kl, ku, ab, ldab, rwork ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_cgbcon( norm, n, kl, ku, afb, ldafb, ipiv, anorm, rcond,work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_clacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_cgbtrs( trans, n, kl, ku, nrhs, afb, ldafb, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_cgbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb, ipiv,b, ldb, x, ldx, & ferr, berr, work, rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -14_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. anorm = zero do j = 1, info do i = max( ku+2-j, 1 ), min( n+ku+1-j, kl+ku+1 ) anorm = max( anorm, abs( ab( i, j ) ) ) end do end do rpvgrw = stdlib${ii}$_zlantb( 'M', 'U', 'N', info, min( info-1, kl+ku ),afb( max( 1_${ik}$, & kl+ku+2-info ), 1_${ik}$ ), ldafb,rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = anorm / rpvgrw end if rwork( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_zlangb( norm, n, kl, ku, ab, ldab, rwork ) rpvgrw = stdlib${ii}$_zlantb( 'M', 'U', 'N', n, kl+ku, afb, ldafb, rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_zlangb( 'M', n, kl, ku, ab, ldab, rwork ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_zgbcon( norm, n, kl, ku, afb, ldafb, ipiv, anorm, rcond,work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_zlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_zgbtrs( trans, n, kl, ku, nrhs, afb, ldafb, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_zgbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb, ipiv,b, ldb, x, ldx, & ferr, berr, work, rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond0_${ik}$ ) then rowcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else rowcnd = one end if end if if( colequ .and. info==0_${ik}$ ) then rcmin = bignum rcmax = zero do j = 1, n rcmin = min( rcmin, c( j ) ) rcmax = max( rcmax, c( j ) ) end do if( rcmin<=zero ) then info = -14_${ik}$ else if( n>0_${ik}$ ) then colcnd = max( rcmin, smlnum ) / min( rcmax, bignum ) else colcnd = one end if end if if( info==0_${ik}$ ) then if( ldb0_${ik}$ ) then ! compute the reciprocal pivot growth factor of the ! leading rank-deficient info columns of a. anorm = zero do j = 1, info do i = max( ku+2-j, 1 ), min( n+ku+1-j, kl+ku+1 ) anorm = max( anorm, abs( ab( i, j ) ) ) end do end do rpvgrw = stdlib${ii}$_${ci}$lantb( 'M', 'U', 'N', info, min( info-1, kl+ku ),afb( max( 1_${ik}$, & kl+ku+2-info ), 1_${ik}$ ), ldafb,rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = anorm / rpvgrw end if rwork( 1_${ik}$ ) = rpvgrw rcond = zero return end if end if ! compute the norm of the matrix a and the ! reciprocal pivot growth factor rpvgrw. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_${ci}$langb( norm, n, kl, ku, ab, ldab, rwork ) rpvgrw = stdlib${ii}$_${ci}$lantb( 'M', 'U', 'N', n, kl+ku, afb, ldafb, rwork ) if( rpvgrw==zero ) then rpvgrw = one else rpvgrw = stdlib${ii}$_${ci}$langb( 'M', n, kl, ku, ab, ldab, rwork ) / rpvgrw end if ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ci}$gbcon( norm, n, kl, ku, afb, ldafb, ipiv, anorm, rcond,work, rwork, info ) ! compute the solution matrix x. call stdlib${ii}$_${ci}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ci}$gbtrs( trans, n, kl, ku, nrhs, afb, ldafb, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solution and ! compute error bounds and backward error estimates for it. call stdlib${ii}$_${ci}$gbrfs( trans, n, kl, ku, nrhs, ab, ldab, afb, ldafb, ipiv,b, ldb, x, ldx, & ferr, berr, work, rwork, info ) ! transform the solution matrix x to a solution of the original ! system. if( notran ) then if( colequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = c( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / colcnd end do end if else if( rowequ ) then do j = 1, nrhs do i = 1, n x( i, j ) = r( i )*x( i, j ) end do end do do j = 1, nrhs ferr( j ) = ferr( j ) / rowcnd end do end if ! set info = n+1 if the matrix is singular to working precision. if( rcond=abs( dl( i ) ) ) then ! no row interchange required if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) b( i+1, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) - fact*b( i, 1_${ik}$ ) else info = i return end if dl( i ) = zero else ! interchange rows i and i+1 fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp dl( i ) = du( i+1 ) du( i+1 ) = -fact*dl( i ) du( i ) = temp temp = b( i, 1_${ik}$ ) b( i, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) b( i+1, 1_${ik}$ ) = temp - fact*b( i+1, 1_${ik}$ ) end if end do loop_10 if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( abs( d( i ) )>=abs( dl( i ) ) ) then if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) b( i+1, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) - fact*b( i, 1_${ik}$ ) else info = i return end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp du( i ) = temp temp = b( i, 1_${ik}$ ) b( i, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) b( i+1, 1_${ik}$ ) = temp - fact*b( i+1, 1_${ik}$ ) end if end if if( d( n )==zero ) then info = n return end if else loop_40: do i = 1, n - 2 if( abs( d( i ) )>=abs( dl( i ) ) ) then ! no row interchange required if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) do j = 1, nrhs b( i+1, j ) = b( i+1, j ) - fact*b( i, j ) end do else info = i return end if dl( i ) = zero else ! interchange rows i and i+1 fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp dl( i ) = du( i+1 ) du( i+1 ) = -fact*dl( i ) du( i ) = temp do j = 1, nrhs temp = b( i, j ) b( i, j ) = b( i+1, j ) b( i+1, j ) = temp - fact*b( i+1, j ) end do end if end do loop_40 if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( abs( d( i ) )>=abs( dl( i ) ) ) then if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) do j = 1, nrhs b( i+1, j ) = b( i+1, j ) - fact*b( i, j ) end do else info = i return end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp du( i ) = temp do j = 1, nrhs temp = b( i, j ) b( i, j ) = b( i+1, j ) b( i+1, j ) = temp - fact*b( i+1, j ) end do end if end if if( d( n )==zero ) then info = n return end if end if ! back solve with the matrix u from the factorization. if( nrhs<=2_${ik}$ ) then j = 1_${ik}$ 70 continue b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) / d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-dl( i )*b( i+2, j ) ) / d( i ) end do if( j1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-dl( i )*b( i+2, j ) ) / d( i ) end do end do end if return end subroutine stdlib${ii}$_sgtsv pure module subroutine stdlib${ii}$_dgtsv( n, nrhs, dl, d, du, b, ldb, info ) !! DGTSV solves the equation !! A*X = B, !! where A is an n by n tridiagonal matrix, by Gaussian elimination with !! partial pivoting. !! Note that the equation A**T*X = B may be solved by interchanging the !! order of the arguments DU and DL. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments real(dp), intent(inout) :: b(ldb,*), d(*), dl(*), du(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: fact, temp ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( nrhs<0_${ik}$ ) then info = -2_${ik}$ else if( ldb=abs( dl( i ) ) ) then ! no row interchange required if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) b( i+1, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) - fact*b( i, 1_${ik}$ ) else info = i return end if dl( i ) = zero else ! interchange rows i and i+1 fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp dl( i ) = du( i+1 ) du( i+1 ) = -fact*dl( i ) du( i ) = temp temp = b( i, 1_${ik}$ ) b( i, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) b( i+1, 1_${ik}$ ) = temp - fact*b( i+1, 1_${ik}$ ) end if end do loop_10 if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( abs( d( i ) )>=abs( dl( i ) ) ) then if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) b( i+1, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) - fact*b( i, 1_${ik}$ ) else info = i return end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp du( i ) = temp temp = b( i, 1_${ik}$ ) b( i, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) b( i+1, 1_${ik}$ ) = temp - fact*b( i+1, 1_${ik}$ ) end if end if if( d( n )==zero ) then info = n return end if else loop_40: do i = 1, n - 2 if( abs( d( i ) )>=abs( dl( i ) ) ) then ! no row interchange required if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) do j = 1, nrhs b( i+1, j ) = b( i+1, j ) - fact*b( i, j ) end do else info = i return end if dl( i ) = zero else ! interchange rows i and i+1 fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp dl( i ) = du( i+1 ) du( i+1 ) = -fact*dl( i ) du( i ) = temp do j = 1, nrhs temp = b( i, j ) b( i, j ) = b( i+1, j ) b( i+1, j ) = temp - fact*b( i+1, j ) end do end if end do loop_40 if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( abs( d( i ) )>=abs( dl( i ) ) ) then if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) do j = 1, nrhs b( i+1, j ) = b( i+1, j ) - fact*b( i, j ) end do else info = i return end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp du( i ) = temp do j = 1, nrhs temp = b( i, j ) b( i, j ) = b( i+1, j ) b( i+1, j ) = temp - fact*b( i+1, j ) end do end if end if if( d( n )==zero ) then info = n return end if end if ! back solve with the matrix u from the factorization. if( nrhs<=2_${ik}$ ) then j = 1_${ik}$ 70 continue b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) / d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-dl( i )*b( i+2, j ) ) / d( i ) end do if( j1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-dl( i )*b( i+2, j ) ) / d( i ) end do end do end if return end subroutine stdlib${ii}$_dgtsv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gtsv( n, nrhs, dl, d, du, b, ldb, info ) !! DGTSV: solves the equation !! A*X = B, !! where A is an n by n tridiagonal matrix, by Gaussian elimination with !! partial pivoting. !! Note that the equation A**T*X = B may be solved by interchanging the !! order of the arguments DU and DL. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments real(${rk}$), intent(inout) :: b(ldb,*), d(*), dl(*), du(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${rk}$) :: fact, temp ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( nrhs<0_${ik}$ ) then info = -2_${ik}$ else if( ldb=abs( dl( i ) ) ) then ! no row interchange required if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) b( i+1, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) - fact*b( i, 1_${ik}$ ) else info = i return end if dl( i ) = zero else ! interchange rows i and i+1 fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp dl( i ) = du( i+1 ) du( i+1 ) = -fact*dl( i ) du( i ) = temp temp = b( i, 1_${ik}$ ) b( i, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) b( i+1, 1_${ik}$ ) = temp - fact*b( i+1, 1_${ik}$ ) end if end do loop_10 if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( abs( d( i ) )>=abs( dl( i ) ) ) then if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) b( i+1, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) - fact*b( i, 1_${ik}$ ) else info = i return end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp du( i ) = temp temp = b( i, 1_${ik}$ ) b( i, 1_${ik}$ ) = b( i+1, 1_${ik}$ ) b( i+1, 1_${ik}$ ) = temp - fact*b( i+1, 1_${ik}$ ) end if end if if( d( n )==zero ) then info = n return end if else loop_40: do i = 1, n - 2 if( abs( d( i ) )>=abs( dl( i ) ) ) then ! no row interchange required if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) do j = 1, nrhs b( i+1, j ) = b( i+1, j ) - fact*b( i, j ) end do else info = i return end if dl( i ) = zero else ! interchange rows i and i+1 fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp dl( i ) = du( i+1 ) du( i+1 ) = -fact*dl( i ) du( i ) = temp do j = 1, nrhs temp = b( i, j ) b( i, j ) = b( i+1, j ) b( i+1, j ) = temp - fact*b( i+1, j ) end do end if end do loop_40 if( n>1_${ik}$ ) then i = n - 1_${ik}$ if( abs( d( i ) )>=abs( dl( i ) ) ) then if( d( i )/=zero ) then fact = dl( i ) / d( i ) d( i+1 ) = d( i+1 ) - fact*du( i ) do j = 1, nrhs b( i+1, j ) = b( i+1, j ) - fact*b( i, j ) end do else info = i return end if else fact = d( i ) / dl( i ) d( i ) = dl( i ) temp = d( i+1 ) d( i+1 ) = du( i ) - fact*temp du( i ) = temp do j = 1, nrhs temp = b( i, j ) b( i, j ) = b( i+1, j ) b( i+1, j ) = temp - fact*b( i+1, j ) end do end if end if if( d( n )==zero ) then info = n return end if end if ! back solve with the matrix u from the factorization. if( nrhs<=2_${ik}$ ) then j = 1_${ik}$ 70 continue b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) / d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-dl( i )*b( i+2, j ) ) / d( i ) end do if( j1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) /d( n-1 ) do i = n - 2, 1, -1 b( i, j ) = ( b( i, j )-du( i )*b( i+1, j )-dl( i )*b( i+2, j ) ) / d( i ) end do end do end if return end subroutine stdlib${ii}$_${ri}$gtsv #:endif #:endfor pure module subroutine stdlib${ii}$_cgtsv( n, nrhs, dl, d, du, b, ldb, info ) !! CGTSV solves the equation !! A*X = B, !! where A is an N-by-N tridiagonal matrix, by Gaussian elimination with !! partial pivoting. !! Note that the equation A**T *X = B may be solved by interchanging the !! order of the arguments DU and DL. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments complex(sp), intent(inout) :: b(ldb,*), d(*), dl(*), du(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, k complex(sp) :: mult, temp, zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( nrhs<0_${ik}$ ) then info = -2_${ik}$ else if( ldb=cabs1( dl( k ) ) ) then ! no row interchange required mult = dl( k ) / d( k ) d( k+1 ) = d( k+1 ) - mult*du( k ) do j = 1, nrhs b( k+1, j ) = b( k+1, j ) - mult*b( k, j ) end do if( k<( n-1 ) )dl( k ) = czero else ! interchange rows k and k+1 mult = d( k ) / dl( k ) d( k ) = dl( k ) temp = d( k+1 ) d( k+1 ) = du( k ) - mult*temp if( k<( n-1 ) ) then dl( k ) = du( k+1 ) du( k+1 ) = -mult*dl( k ) end if du( k ) = temp do j = 1, nrhs temp = b( k, j ) b( k, j ) = b( k+1, j ) b( k+1, j ) = temp - mult*b( k+1, j ) end do end if end do loop_30 if( d( n )==czero ) then info = n return end if ! back solve with the matrix u from the factorization. do j = 1, nrhs b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) / d( n-1 ) do k = n - 2, 1, -1 b( k, j ) = ( b( k, j )-du( k )*b( k+1, j )-dl( k )*b( k+2, j ) ) / d( k ) end do end do return end subroutine stdlib${ii}$_cgtsv pure module subroutine stdlib${ii}$_zgtsv( n, nrhs, dl, d, du, b, ldb, info ) !! ZGTSV solves the equation !! A*X = B, !! where A is an N-by-N tridiagonal matrix, by Gaussian elimination with !! partial pivoting. !! Note that the equation A**T *X = B may be solved by interchanging the !! order of the arguments DU and DL. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments complex(dp), intent(inout) :: b(ldb,*), d(*), dl(*), du(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, k complex(dp) :: mult, temp, zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( nrhs<0_${ik}$ ) then info = -2_${ik}$ else if( ldb=cabs1( dl( k ) ) ) then ! no row interchange required mult = dl( k ) / d( k ) d( k+1 ) = d( k+1 ) - mult*du( k ) do j = 1, nrhs b( k+1, j ) = b( k+1, j ) - mult*b( k, j ) end do if( k<( n-1 ) )dl( k ) = czero else ! interchange rows k and k+1 mult = d( k ) / dl( k ) d( k ) = dl( k ) temp = d( k+1 ) d( k+1 ) = du( k ) - mult*temp if( k<( n-1 ) ) then dl( k ) = du( k+1 ) du( k+1 ) = -mult*dl( k ) end if du( k ) = temp do j = 1, nrhs temp = b( k, j ) b( k, j ) = b( k+1, j ) b( k+1, j ) = temp - mult*b( k+1, j ) end do end if end do loop_30 if( d( n )==czero ) then info = n return end if ! back solve with the matrix u from the factorization. do j = 1, nrhs b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) / d( n-1 ) do k = n - 2, 1, -1 b( k, j ) = ( b( k, j )-du( k )*b( k+1, j )-dl( k )*b( k+2, j ) ) / d( k ) end do end do return end subroutine stdlib${ii}$_zgtsv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gtsv( n, nrhs, dl, d, du, b, ldb, info ) !! ZGTSV: solves the equation !! A*X = B, !! where A is an N-by-N tridiagonal matrix, by Gaussian elimination with !! partial pivoting. !! Note that the equation A**T *X = B may be solved by interchanging the !! order of the arguments DU and DL. ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments complex(${ck}$), intent(inout) :: b(ldb,*), d(*), dl(*), du(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, k complex(${ck}$) :: mult, temp, zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( nrhs<0_${ik}$ ) then info = -2_${ik}$ else if( ldb=cabs1( dl( k ) ) ) then ! no row interchange required mult = dl( k ) / d( k ) d( k+1 ) = d( k+1 ) - mult*du( k ) do j = 1, nrhs b( k+1, j ) = b( k+1, j ) - mult*b( k, j ) end do if( k<( n-1 ) )dl( k ) = czero else ! interchange rows k and k+1 mult = d( k ) / dl( k ) d( k ) = dl( k ) temp = d( k+1 ) d( k+1 ) = du( k ) - mult*temp if( k<( n-1 ) ) then dl( k ) = du( k+1 ) du( k+1 ) = -mult*dl( k ) end if du( k ) = temp do j = 1, nrhs temp = b( k, j ) b( k, j ) = b( k+1, j ) b( k+1, j ) = temp - mult*b( k+1, j ) end do end if end do loop_30 if( d( n )==czero ) then info = n return end if ! back solve with the matrix u from the factorization. do j = 1, nrhs b( n, j ) = b( n, j ) / d( n ) if( n>1_${ik}$ )b( n-1, j ) = ( b( n-1, j )-du( n-1 )*b( n, j ) ) / d( n-1 ) do k = n - 2, 1, -1 b( k, j ) = ( b( k, j )-du( k )*b( k+1, j )-dl( k )*b( k+2, j ) ) / d( k ) end do end do return end subroutine stdlib${ii}$_${ci}$gtsv #:endif #:endfor pure module subroutine stdlib${ii}$_sgtsvx( fact, trans, n, nrhs, dl, d, du, dlf, df, duf,du2, ipiv, b, & !! SGTSVX uses the LU factorization to compute the solution to a real !! system of linear equations A * X = B or A**T * X = B, !! where A is a tridiagonal matrix of order N and X and B are N-by-NRHS !! matrices. !! Error bounds on the solution and a condition estimate are also !! provided. ldb, x, ldx, rcond, ferr, berr,work, iwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: fact, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(inout) :: ipiv(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: b(ldb,*), d(*), dl(*), du(*) real(sp), intent(out) :: berr(*), ferr(*), work(*), x(ldx,*) real(sp), intent(inout) :: df(*), dlf(*), du2(*), duf(*) ! ===================================================================== ! Local Scalars logical(lk) :: nofact, notran character :: norm real(sp) :: anorm ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ nofact = stdlib_lsame( fact, 'N' ) notran = stdlib_lsame( trans, 'N' ) if( .not.nofact .and. .not.stdlib_lsame( fact, 'F' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( ldb1_${ik}$ ) then call stdlib${ii}$_scopy( n-1, dl, 1_${ik}$, dlf, 1_${ik}$ ) call stdlib${ii}$_scopy( n-1, du, 1_${ik}$, duf, 1_${ik}$ ) end if call stdlib${ii}$_sgttrf( n, dlf, df, duf, du2, ipiv, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_slangt( norm, n, dl, d, du ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_sgtcon( norm, n, dlf, df, duf, du2, ipiv, anorm, rcond, work,iwork, info ) ! compute the solution vectors x. call stdlib${ii}$_slacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_sgttrs( trans, n, nrhs, dlf, df, duf, du2, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_sgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2, ipiv,b, ldb, x, ldx, & ferr, berr, work, iwork, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond1_${ik}$ ) then call stdlib${ii}$_dcopy( n-1, dl, 1_${ik}$, dlf, 1_${ik}$ ) call stdlib${ii}$_dcopy( n-1, du, 1_${ik}$, duf, 1_${ik}$ ) end if call stdlib${ii}$_dgttrf( n, dlf, df, duf, du2, ipiv, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_dlangt( norm, n, dl, d, du ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_dgtcon( norm, n, dlf, df, duf, du2, ipiv, anorm, rcond, work,iwork, info ) ! compute the solution vectors x. call stdlib${ii}$_dlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_dgttrs( trans, n, nrhs, dlf, df, duf, du2, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_dgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2, ipiv,b, ldb, x, ldx, & ferr, berr, work, iwork, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( n-1, dl, 1_${ik}$, dlf, 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n-1, du, 1_${ik}$, duf, 1_${ik}$ ) end if call stdlib${ii}$_${ri}$gttrf( n, dlf, df, duf, du2, ipiv, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_${ri}$langt( norm, n, dl, d, du ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ri}$gtcon( norm, n, dlf, df, duf, du2, ipiv, anorm, rcond, work,iwork, info ) ! compute the solution vectors x. call stdlib${ii}$_${ri}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ri}$gttrs( trans, n, nrhs, dlf, df, duf, du2, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_${ri}$gtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2, ipiv,b, ldb, x, ldx, & ferr, berr, work, iwork, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond1_${ik}$ ) then call stdlib${ii}$_ccopy( n-1, dl, 1_${ik}$, dlf, 1_${ik}$ ) call stdlib${ii}$_ccopy( n-1, du, 1_${ik}$, duf, 1_${ik}$ ) end if call stdlib${ii}$_cgttrf( n, dlf, df, duf, du2, ipiv, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_clangt( norm, n, dl, d, du ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_cgtcon( norm, n, dlf, df, duf, du2, ipiv, anorm, rcond, work,info ) ! compute the solution vectors x. call stdlib${ii}$_clacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_cgttrs( trans, n, nrhs, dlf, df, duf, du2, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_cgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2, ipiv,b, ldb, x, ldx, & ferr, berr, work, rwork, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond1_${ik}$ ) then call stdlib${ii}$_zcopy( n-1, dl, 1_${ik}$, dlf, 1_${ik}$ ) call stdlib${ii}$_zcopy( n-1, du, 1_${ik}$, duf, 1_${ik}$ ) end if call stdlib${ii}$_zgttrf( n, dlf, df, duf, du2, ipiv, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_zlangt( norm, n, dl, d, du ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_zgtcon( norm, n, dlf, df, duf, du2, ipiv, anorm, rcond, work,info ) ! compute the solution vectors x. call stdlib${ii}$_zlacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_zgttrs( trans, n, nrhs, dlf, df, duf, du2, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_zgtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2, ipiv,b, ldb, x, ldx, & ferr, berr, work, rwork, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( n-1, dl, 1_${ik}$, dlf, 1_${ik}$ ) call stdlib${ii}$_${ci}$copy( n-1, du, 1_${ik}$, duf, 1_${ik}$ ) end if call stdlib${ii}$_${ci}$gttrf( n, dlf, df, duf, du2, ipiv, info ) ! return if info is non-zero. if( info>0_${ik}$ )then rcond = zero return end if end if ! compute the norm of the matrix a. if( notran ) then norm = '1' else norm = 'I' end if anorm = stdlib${ii}$_${ci}$langt( norm, n, dl, d, du ) ! compute the reciprocal of the condition number of a. call stdlib${ii}$_${ci}$gtcon( norm, n, dlf, df, duf, du2, ipiv, anorm, rcond, work,info ) ! compute the solution vectors x. call stdlib${ii}$_${ci}$lacpy( 'FULL', n, nrhs, b, ldb, x, ldx ) call stdlib${ii}$_${ci}$gttrs( trans, n, nrhs, dlf, df, duf, du2, ipiv, x, ldx,info ) ! use iterative refinement to improve the computed solutions and ! compute error bounds and backward error estimates for them. call stdlib${ii}$_${ci}$gtrfs( trans, n, nrhs, dl, d, du, dlf, df, duf, du2, ipiv,b, ldb, x, ldx, & ferr, berr, work, rwork, info ) ! set info = n+1 if the matrix is singular to working precision. if( rcond 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_slacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_slatrs( uplo, 'NO TRANSPOSE', diag, normin, n, a,lda, work, scale,& work( 2_${ik}$*n+1 ), info ) else ! multiply by inv(a**t). call stdlib${ii}$_slatrs( uplo, 'TRANSPOSE', diag, normin, n, a, lda,work, scale, & work( 2_${ik}$*n+1 ), info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_isamax( n, work, 1_${ik}$ ) xnorm = abs( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_dlacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_dlatrs( uplo, 'NO TRANSPOSE', diag, normin, n, a,lda, work, scale,& work( 2_${ik}$*n+1 ), info ) else ! multiply by inv(a**t). call stdlib${ii}$_dlatrs( uplo, 'TRANSPOSE', diag, normin, n, a, lda,work, scale, & work( 2_${ik}$*n+1 ), info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_idamax( n, work, 1_${ik}$ ) xnorm = abs( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_${ri}$lacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_${ri}$latrs( uplo, 'NO TRANSPOSE', diag, normin, n, a,lda, work, scale,& work( 2_${ik}$*n+1 ), info ) else ! multiply by inv(a**t). call stdlib${ii}$_${ri}$latrs( uplo, 'TRANSPOSE', diag, normin, n, a, lda,work, scale, & work( 2_${ik}$*n+1 ), info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ ) xnorm = abs( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_clatrs( uplo, 'NO TRANSPOSE', diag, normin, n, a,lda, work, scale,& rwork, info ) else ! multiply by inv(a**h). call stdlib${ii}$_clatrs( uplo, 'CONJUGATE TRANSPOSE', diag, normin,n, a, lda, work,& scale, rwork, info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_icamax( n, work, 1_${ik}$ ) xnorm = cabs1( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_zlatrs( uplo, 'NO TRANSPOSE', diag, normin, n, a,lda, work, scale,& rwork, info ) else ! multiply by inv(a**h). call stdlib${ii}$_zlatrs( uplo, 'CONJUGATE TRANSPOSE', diag, normin,n, a, lda, work,& scale, rwork, info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_izamax( n, work, 1_${ik}$ ) xnorm = cabs1( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_${ci}$latrs( uplo, 'NO TRANSPOSE', diag, normin, n, a,lda, work, scale,& rwork, info ) else ! multiply by inv(a**h). call stdlib${ii}$_${ci}$latrs( uplo, 'CONJUGATE TRANSPOSE', diag, normin,n, a, lda, work,& scale, rwork, info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_i${ci}$amax( n, work, 1_${ik}$ ) xnorm = cabs1( work( ix ) ) if( scale=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 50 continue else ! compute the growth in a**t * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 80 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) tjj = abs( a( j, j ) ) if( xj>tjj )xbnd = xbnd*( tjj / xj ) end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 80 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_strsv( uplo, trans, diag, n, a, lda, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = bignum / xmax call stdlib${ii}$_sscal( n, scale, x, 1_${ik}$ ) xmax = bignum end if if( notran ) then ! solve a * x = b loop_100: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = abs( x( j ) ) if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal if( tscal==one )go to 95 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 95 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_sscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_saxpy( j-1, -x( j )*tscal, a( 1_${ik}$, j ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_isamax( j-1, x, 1_${ik}$ ) xmax = abs( x( i ) ) end if else if( jj xj = abs( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal end if tjj = abs( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = uscal / tjjs end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a**t*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 135 continue else ! compute x(j) := x(j) / a(j,j) - sumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = x( j ) / tjjs - sumj end if xmax = max( xmax, abs( x( j ) ) ) end do loop_140 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_sscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_slatrs pure module subroutine stdlib${ii}$_dlatrs( uplo, trans, diag, normin, n, a, lda, x, scale,cnorm, info ) !! DLATRS solves one of the triangular systems !! A *x = s*b or A**T *x = s*b !! with scaling to prevent overflow. Here A is an upper or lower !! triangular matrix, A**T denotes the transpose of A, x and b are !! n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine DTRSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(dp), intent(out) :: scale ! Array Arguments real(dp), intent(in) :: a(lda,*) real(dp), intent(inout) :: cnorm(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, j, jfirst, jinc, jlast real(dp) :: bignum, grow, rec, smlnum, sumj, tjj, tjjs, tmax, tscal, uscal, xbnd, xj, & xmax ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 50 continue else ! compute the growth in a**t * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 80 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) tjj = abs( a( j, j ) ) if( xj>tjj )xbnd = xbnd*( tjj / xj ) end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 80 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_dtrsv( uplo, trans, diag, n, a, lda, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = bignum / xmax call stdlib${ii}$_dscal( n, scale, x, 1_${ik}$ ) xmax = bignum end if if( notran ) then ! solve a * x = b loop_110: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = abs( x( j ) ) if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal if( tscal==one )go to 100 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 100 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_dscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_daxpy( j-1, -x( j )*tscal, a( 1_${ik}$, j ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_idamax( j-1, x, 1_${ik}$ ) xmax = abs( x( i ) ) end if else if( jj xj = abs( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal end if tjj = abs( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = uscal / tjjs end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a**t*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 150 continue else ! compute x(j) := x(j) / a(j,j) - sumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = x( j ) / tjjs - sumj end if xmax = max( xmax, abs( x( j ) ) ) end do loop_160 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_dscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_dlatrs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$latrs( uplo, trans, diag, normin, n, a, lda, x, scale,cnorm, info ) !! DLATRS: solves one of the triangular systems !! A *x = s*b or A**T *x = s*b !! with scaling to prevent overflow. Here A is an upper or lower !! triangular matrix, A**T denotes the transpose of A, x and b are !! n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine DTRSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(${rk}$), intent(out) :: scale ! Array Arguments real(${rk}$), intent(in) :: a(lda,*) real(${rk}$), intent(inout) :: cnorm(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, j, jfirst, jinc, jlast real(${rk}$) :: bignum, grow, rec, smlnum, sumj, tjj, tjjs, tmax, tscal, uscal, xbnd, xj, & xmax ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 50 continue else ! compute the growth in a**t * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 80 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) tjj = abs( a( j, j ) ) if( xj>tjj )xbnd = xbnd*( tjj / xj ) end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 80 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_${ri}$trsv( uplo, trans, diag, n, a, lda, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = bignum / xmax call stdlib${ii}$_${ri}$scal( n, scale, x, 1_${ik}$ ) xmax = bignum end if if( notran ) then ! solve a * x = b loop_110: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = abs( x( j ) ) if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal if( tscal==one )go to 100 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 100 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_${ri}$scal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_${ri}$axpy( j-1, -x( j )*tscal, a( 1_${ik}$, j ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_i${ri}$amax( j-1, x, 1_${ik}$ ) xmax = abs( x( i ) ) end if else if( jj xj = abs( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal end if tjj = abs( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = uscal / tjjs end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a**t*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 150 continue else ! compute x(j) := x(j) / a(j,j) - sumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = x( j ) / tjjs - sumj end if xmax = max( xmax, abs( x( j ) ) ) end do loop_160 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_${ri}$scal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ri}$latrs #:endif #:endfor pure module subroutine stdlib${ii}$_clatrs( uplo, trans, diag, normin, n, a, lda, x, scale,cnorm, info ) !! CLATRS solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow. Here A is an upper or lower !! triangular matrix, A**T denotes the transpose of A, A**H denotes the !! conjugate transpose of A, x and b are n-element vectors, and s is a !! scaling factor, usually less than or equal to 1, chosen so that the !! components of x will be less than the overflow threshold. If the !! unscaled problem will not cause overflow, the Level 2 BLAS routine !! CTRSV is called. If the matrix A is singular (A(j,j) = 0 for some j), !! then s is set to 0 and a non-trivial solution to A*x = 0 is returned. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(sp), intent(out) :: scale ! Array Arguments real(sp), intent(inout) :: cnorm(*) complex(sp), intent(in) :: a(lda,*) complex(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, j, jfirst, jinc, jlast real(sp) :: bignum, grow, rec, smlnum, tjj, tmax, tscal, xbnd, xj, xmax complex(sp) :: csumj, tjjs, uscal, zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1, cabs2 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) cabs2( zdum ) = abs( real( zdum,KIND=sp) / 2. ) +abs( aimag( zdum ) / 2. ) ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda=smlnum ) then ! m(j) = g(j-1) / abs(a(j,j)) xbnd = min( xbnd, min( one, tjj )*grow ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 60 continue else ! compute the growth in a**t * x = b or a**h * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 90 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) tjjs = a( j, j ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) if( xj>tjj )xbnd = xbnd*( tjj / xj ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 90 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_ctrsv( uplo, trans, diag, n, a, lda, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum*half ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = ( bignum*half ) / xmax call stdlib${ii}$_csscal( n, scale, x, 1_${ik}$ ) xmax = bignum else xmax = xmax*two end if if( notran ) then ! solve a * x = b loop_110: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = cabs1( x( j ) ) if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal if( tscal==one )go to 105 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 105 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_csscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_caxpy( j-1, -x( j )*tscal, a( 1_${ik}$, j ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_icamax( j-1, x, 1_${ik}$ ) xmax = cabs1( x( i ) ) end if else if( jj xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_cladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**t *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 145 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_150 else ! solve a**h * x = b loop_190: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = conjg( a( j, j ) )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_cladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**h *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 185 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_190 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_sscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_clatrs pure module subroutine stdlib${ii}$_zlatrs( uplo, trans, diag, normin, n, a, lda, x, scale,cnorm, info ) !! ZLATRS solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow. Here A is an upper or lower !! triangular matrix, A**T denotes the transpose of A, A**H denotes the !! conjugate transpose of A, x and b are n-element vectors, and s is a !! scaling factor, usually less than or equal to 1, chosen so that the !! components of x will be less than the overflow threshold. If the !! unscaled problem will not cause overflow, the Level 2 BLAS routine !! ZTRSV is called. If the matrix A is singular (A(j,j) = 0 for some j), !! then s is set to 0 and a non-trivial solution to A*x = 0 is returned. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(dp), intent(out) :: scale ! Array Arguments real(dp), intent(inout) :: cnorm(*) complex(dp), intent(in) :: a(lda,*) complex(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, j, jfirst, jinc, jlast real(dp) :: bignum, grow, rec, smlnum, tjj, tmax, tscal, xbnd, xj, xmax complex(dp) :: csumj, tjjs, uscal, zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1, cabs2 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) cabs2( zdum ) = abs( real( zdum,KIND=dp) / 2._dp ) +abs( aimag( zdum ) / 2._dp ) ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda=smlnum ) then ! m(j) = g(j-1) / abs(a(j,j)) xbnd = min( xbnd, min( one, tjj )*grow ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 60 continue else ! compute the growth in a**t * x = b or a**h * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 90 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) tjjs = a( j, j ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) if( xj>tjj )xbnd = xbnd*( tjj / xj ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 90 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_ztrsv( uplo, trans, diag, n, a, lda, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum*half ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = ( bignum*half ) / xmax call stdlib${ii}$_zdscal( n, scale, x, 1_${ik}$ ) xmax = bignum else xmax = xmax*two end if if( notran ) then ! solve a * x = b loop_120: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = cabs1( x( j ) ) if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal if( tscal==one )go to 110 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 110 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_zdscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_zaxpy( j-1, -x( j )*tscal, a( 1_${ik}$, j ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_izamax( j-1, x, 1_${ik}$ ) xmax = cabs1( x( i ) ) end if else if( jj xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_zladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**t *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 160 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_170 else ! solve a**h * x = b loop_220: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = conjg( a( j, j ) )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_zladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**h *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 210 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_220 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_dscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_zlatrs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$latrs( uplo, trans, diag, normin, n, a, lda, x, scale,cnorm, info ) !! ZLATRS: solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow. Here A is an upper or lower !! triangular matrix, A**T denotes the transpose of A, A**H denotes the !! conjugate transpose of A, x and b are n-element vectors, and s is a !! scaling factor, usually less than or equal to 1, chosen so that the !! components of x will be less than the overflow threshold. If the !! unscaled problem will not cause overflow, the Level 2 BLAS routine !! ZTRSV is called. If the matrix A is singular (A(j,j) = 0 for some j), !! then s is set to 0 and a non-trivial solution to A*x = 0 is returned. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(out) :: scale ! Array Arguments real(${ck}$), intent(inout) :: cnorm(*) complex(${ck}$), intent(in) :: a(lda,*) complex(${ck}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, j, jfirst, jinc, jlast real(${ck}$) :: bignum, grow, rec, smlnum, tjj, tmax, tscal, xbnd, xj, xmax complex(${ck}$) :: csumj, tjjs, uscal, zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1, cabs2 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) cabs2( zdum ) = abs( real( zdum,KIND=${ck}$) / 2._${ck}$ ) +abs( aimag( zdum ) / 2._${ck}$ ) ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda=smlnum ) then ! m(j) = g(j-1) / abs(a(j,j)) xbnd = min( xbnd, min( one, tjj )*grow ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 60 continue else ! compute the growth in a**t * x = b or a**h * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 90 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) tjjs = a( j, j ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) if( xj>tjj )xbnd = xbnd*( tjj / xj ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 90 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_${ci}$trsv( uplo, trans, diag, n, a, lda, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum*half ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = ( bignum*half ) / xmax call stdlib${ii}$_${ci}$dscal( n, scale, x, 1_${ik}$ ) xmax = bignum else xmax = xmax*two end if if( notran ) then ! solve a * x = b loop_120: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = cabs1( x( j ) ) if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal if( tscal==one )go to 110 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 110 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_${ci}$dscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_${ci}$axpy( j-1, -x( j )*tscal, a( 1_${ik}$, j ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_i${ci}$amax( j-1, x, 1_${ik}$ ) xmax = cabs1( x( i ) ) end if else if( jj xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = a( j, j )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_${ci}$ladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**t *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 160 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_170 else ! solve a**h * x = b loop_220: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = conjg( a( j, j ) )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_${ci}$ladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**h *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 210 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_220 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_${c2ri(ci)}$scal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ci}$latrs #:endif #:endfor pure module subroutine stdlib${ii}$_strtri( uplo, diag, n, a, lda, info ) !! STRTRI computes the inverse of a real upper or lower triangular !! matrix A. !! This is the Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: nounit, upper integer(${ik}$) :: j, jb, nb, nn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_strti2( uplo, diag, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute inverse of upper triangular matrix do j = 1, n, nb jb = min( nb, n-j+1 ) ! compute rows 1:j-1 of current block column call stdlib${ii}$_strmm( 'LEFT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, one, a, lda,& a( 1_${ik}$, j ), lda ) call stdlib${ii}$_strsm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, -one, a( j,& j ), lda, a( 1_${ik}$, j ), lda ) ! compute inverse of current diagonal block call stdlib${ii}$_strti2( 'UPPER', diag, jb, a( j, j ), lda, info ) end do else ! compute inverse of lower triangular matrix nn = ( ( n-1 ) / nb )*nb + 1_${ik}$ do j = nn, 1, -nb jb = min( nb, n-j+1 ) if( j+jb<=n ) then ! compute rows j+jb:n of current block column call stdlib${ii}$_strmm( 'LEFT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, one,& a( j+jb, j+jb ), lda,a( j+jb, j ), lda ) call stdlib${ii}$_strsm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, -& one, a( j, j ), lda,a( j+jb, j ), lda ) end if ! compute inverse of current diagonal block call stdlib${ii}$_strti2( 'LOWER', diag, jb, a( j, j ), lda, info ) end do end if end if return end subroutine stdlib${ii}$_strtri pure module subroutine stdlib${ii}$_dtrtri( uplo, diag, n, a, lda, info ) !! DTRTRI computes the inverse of a real upper or lower triangular !! matrix A. !! This is the Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: nounit, upper integer(${ik}$) :: j, jb, nb, nn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_dtrti2( uplo, diag, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute inverse of upper triangular matrix do j = 1, n, nb jb = min( nb, n-j+1 ) ! compute rows 1:j-1 of current block column call stdlib${ii}$_dtrmm( 'LEFT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, one, a, lda,& a( 1_${ik}$, j ), lda ) call stdlib${ii}$_dtrsm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, -one, a( j,& j ), lda, a( 1_${ik}$, j ), lda ) ! compute inverse of current diagonal block call stdlib${ii}$_dtrti2( 'UPPER', diag, jb, a( j, j ), lda, info ) end do else ! compute inverse of lower triangular matrix nn = ( ( n-1 ) / nb )*nb + 1_${ik}$ do j = nn, 1, -nb jb = min( nb, n-j+1 ) if( j+jb<=n ) then ! compute rows j+jb:n of current block column call stdlib${ii}$_dtrmm( 'LEFT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, one,& a( j+jb, j+jb ), lda,a( j+jb, j ), lda ) call stdlib${ii}$_dtrsm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, -& one, a( j, j ), lda,a( j+jb, j ), lda ) end if ! compute inverse of current diagonal block call stdlib${ii}$_dtrti2( 'LOWER', diag, jb, a( j, j ), lda, info ) end do end if end if return end subroutine stdlib${ii}$_dtrtri #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$trtri( uplo, diag, n, a, lda, info ) !! DTRTRI: computes the inverse of a real upper or lower triangular !! matrix A. !! This is the Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: nounit, upper integer(${ik}$) :: j, jb, nb, nn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_${ri}$trti2( uplo, diag, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute inverse of upper triangular matrix do j = 1, n, nb jb = min( nb, n-j+1 ) ! compute rows 1:j-1 of current block column call stdlib${ii}$_${ri}$trmm( 'LEFT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, one, a, lda,& a( 1_${ik}$, j ), lda ) call stdlib${ii}$_${ri}$trsm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, -one, a( j,& j ), lda, a( 1_${ik}$, j ), lda ) ! compute inverse of current diagonal block call stdlib${ii}$_${ri}$trti2( 'UPPER', diag, jb, a( j, j ), lda, info ) end do else ! compute inverse of lower triangular matrix nn = ( ( n-1 ) / nb )*nb + 1_${ik}$ do j = nn, 1, -nb jb = min( nb, n-j+1 ) if( j+jb<=n ) then ! compute rows j+jb:n of current block column call stdlib${ii}$_${ri}$trmm( 'LEFT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, one,& a( j+jb, j+jb ), lda,a( j+jb, j ), lda ) call stdlib${ii}$_${ri}$trsm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, -& one, a( j, j ), lda,a( j+jb, j ), lda ) end if ! compute inverse of current diagonal block call stdlib${ii}$_${ri}$trti2( 'LOWER', diag, jb, a( j, j ), lda, info ) end do end if end if return end subroutine stdlib${ii}$_${ri}$trtri #:endif #:endfor pure module subroutine stdlib${ii}$_ctrtri( uplo, diag, n, a, lda, info ) !! CTRTRI computes the inverse of a complex upper or lower triangular !! matrix A. !! This is the Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: nounit, upper integer(${ik}$) :: j, jb, nb, nn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_ctrti2( uplo, diag, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute inverse of upper triangular matrix do j = 1, n, nb jb = min( nb, n-j+1 ) ! compute rows 1:j-1 of current block column call stdlib${ii}$_ctrmm( 'LEFT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, cone, a, & lda, a( 1_${ik}$, j ), lda ) call stdlib${ii}$_ctrsm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, -cone, a( & j, j ), lda, a( 1_${ik}$, j ), lda ) ! compute inverse of current diagonal block call stdlib${ii}$_ctrti2( 'UPPER', diag, jb, a( j, j ), lda, info ) end do else ! compute inverse of lower triangular matrix nn = ( ( n-1 ) / nb )*nb + 1_${ik}$ do j = nn, 1, -nb jb = min( nb, n-j+1 ) if( j+jb<=n ) then ! compute rows j+jb:n of current block column call stdlib${ii}$_ctrmm( 'LEFT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, & cone, a( j+jb, j+jb ), lda,a( j+jb, j ), lda ) call stdlib${ii}$_ctrsm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, -& cone, a( j, j ), lda,a( j+jb, j ), lda ) end if ! compute inverse of current diagonal block call stdlib${ii}$_ctrti2( 'LOWER', diag, jb, a( j, j ), lda, info ) end do end if end if return end subroutine stdlib${ii}$_ctrtri pure module subroutine stdlib${ii}$_ztrtri( uplo, diag, n, a, lda, info ) !! ZTRTRI computes the inverse of a complex upper or lower triangular !! matrix A. !! This is the Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: nounit, upper integer(${ik}$) :: j, jb, nb, nn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_ztrti2( uplo, diag, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute inverse of upper triangular matrix do j = 1, n, nb jb = min( nb, n-j+1 ) ! compute rows 1:j-1 of current block column call stdlib${ii}$_ztrmm( 'LEFT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, cone, a, & lda, a( 1_${ik}$, j ), lda ) call stdlib${ii}$_ztrsm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, -cone, a( & j, j ), lda, a( 1_${ik}$, j ), lda ) ! compute inverse of current diagonal block call stdlib${ii}$_ztrti2( 'UPPER', diag, jb, a( j, j ), lda, info ) end do else ! compute inverse of lower triangular matrix nn = ( ( n-1 ) / nb )*nb + 1_${ik}$ do j = nn, 1, -nb jb = min( nb, n-j+1 ) if( j+jb<=n ) then ! compute rows j+jb:n of current block column call stdlib${ii}$_ztrmm( 'LEFT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, & cone, a( j+jb, j+jb ), lda,a( j+jb, j ), lda ) call stdlib${ii}$_ztrsm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, -& cone, a( j, j ), lda,a( j+jb, j ), lda ) end if ! compute inverse of current diagonal block call stdlib${ii}$_ztrti2( 'LOWER', diag, jb, a( j, j ), lda, info ) end do end if end if return end subroutine stdlib${ii}$_ztrtri #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$trtri( uplo, diag, n, a, lda, info ) !! ZTRTRI: computes the inverse of a complex upper or lower triangular !! matrix A. !! This is the Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: nounit, upper integer(${ik}$) :: j, jb, nb, nn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_${ci}$trti2( uplo, diag, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute inverse of upper triangular matrix do j = 1, n, nb jb = min( nb, n-j+1 ) ! compute rows 1:j-1 of current block column call stdlib${ii}$_${ci}$trmm( 'LEFT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, cone, a, & lda, a( 1_${ik}$, j ), lda ) call stdlib${ii}$_${ci}$trsm( 'RIGHT', 'UPPER', 'NO TRANSPOSE', diag, j-1,jb, -cone, a( & j, j ), lda, a( 1_${ik}$, j ), lda ) ! compute inverse of current diagonal block call stdlib${ii}$_${ci}$trti2( 'UPPER', diag, jb, a( j, j ), lda, info ) end do else ! compute inverse of lower triangular matrix nn = ( ( n-1 ) / nb )*nb + 1_${ik}$ do j = nn, 1, -nb jb = min( nb, n-j+1 ) if( j+jb<=n ) then ! compute rows j+jb:n of current block column call stdlib${ii}$_${ci}$trmm( 'LEFT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, & cone, a( j+jb, j+jb ), lda,a( j+jb, j ), lda ) call stdlib${ii}$_${ci}$trsm( 'RIGHT', 'LOWER', 'NO TRANSPOSE', diag,n-j-jb+1, jb, -& cone, a( j, j ), lda,a( j+jb, j ), lda ) end if ! compute inverse of current diagonal block call stdlib${ii}$_${ci}$trti2( 'LOWER', diag, jb, a( j, j ), lda, info ) end do end if end if return end subroutine stdlib${ii}$_${ci}$trtri #:endif #:endfor pure module subroutine stdlib${ii}$_strti2( uplo, diag, n, a, lda, info ) !! STRTI2 computes the inverse of a real upper or lower triangular !! matrix. !! This is the Level 2 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: nounit, upper integer(${ik}$) :: j real(sp) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_slacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_slacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_strsv( uplo, transt, diag, n, a, lda, work( n+1 ),1_${ik}$ ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_strsv( uplo, trans, diag, n, a, lda, work( n+1 ),1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_strrfs pure module subroutine stdlib${ii}$_dtrrfs( uplo, trans, diag, n, nrhs, a, lda, b, ldb, x,ldx, ferr, berr,& !! DTRRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular !! coefficient matrix. !! The solution matrix X must be computed by DTRTRS or some other !! means before entering this routine. DTRRFS does not do iterative !! refinement because doing so cannot improve the backward error. work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: a(lda,*), b(ldb,*), x(ldx,*) real(dp), intent(out) :: berr(*), ferr(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transt integer(${ik}$) :: i, j, k, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldasafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_dlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_dlacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_dtrsv( uplo, transt, diag, n, a, lda, work( n+1 ),1_${ik}$ ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_dtrsv( uplo, trans, diag, n, a, lda, work( n+1 ),1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_dtrrfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$trrfs( uplo, trans, diag, n, nrhs, a, lda, b, ldb, x,ldx, ferr, berr,& !! DTRRFS: provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular !! coefficient matrix. !! The solution matrix X must be computed by DTRTRS or some other !! means before entering this routine. DTRRFS does not do iterative !! refinement because doing so cannot improve the backward error. work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: a(lda,*), b(ldb,*), x(ldx,*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transt integer(${ik}$) :: i, j, k, kase, nz real(${rk}$) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldasafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ri}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_${ri}$lacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_${ri}$trsv( uplo, transt, diag, n, a, lda, work( n+1 ),1_${ik}$ ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_${ri}$trsv( uplo, trans, diag, n, a, lda, work( n+1 ),1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_${ri}$trrfs #:endif #:endfor pure module subroutine stdlib${ii}$_ctrrfs( uplo, trans, diag, n, nrhs, a, lda, b, ldb, x,ldx, ferr, berr,& !! CTRRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular !! coefficient matrix. !! The solution matrix X must be computed by CTRTRS or some other !! means before entering this routine. CTRRFS does not do iterative !! refinement because doing so cannot improve the backward error. work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldx, n, nrhs ! Array Arguments real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: a(lda,*), b(ldb,*), x(ldx,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transn, transt integer(${ik}$) :: i, j, k, kase, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_ctrsv( uplo, transt, diag, n, a, lda, work, 1_${ik}$ ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_ctrsv( uplo, transn, diag, n, a, lda, work, 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_ctrrfs pure module subroutine stdlib${ii}$_ztrrfs( uplo, trans, diag, n, nrhs, a, lda, b, ldb, x,ldx, ferr, berr,& !! ZTRRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular !! coefficient matrix. !! The solution matrix X must be computed by ZTRTRS or some other !! means before entering this routine. ZTRRFS does not do iterative !! refinement because doing so cannot improve the backward error. work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldx, n, nrhs ! Array Arguments real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: a(lda,*), b(ldb,*), x(ldx,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transn, transt integer(${ik}$) :: i, j, k, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_ztrsv( uplo, transt, diag, n, a, lda, work, 1_${ik}$ ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_ztrsv( uplo, transn, diag, n, a, lda, work, 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_ztrrfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$trrfs( uplo, trans, diag, n, nrhs, a, lda, b, ldb, x,ldx, ferr, berr,& !! ZTRRFS: provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular !! coefficient matrix. !! The solution matrix X must be computed by ZTRTRS or some other !! means before entering this routine. ZTRRFS does not do iterative !! refinement because doing so cannot improve the backward error. work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldx, n, nrhs ! Array Arguments real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: a(lda,*), b(ldb,*), x(ldx,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transn, transt integer(${ik}$) :: i, j, k, kase, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_${ci}$trsv( uplo, transt, diag, n, a, lda, work, 1_${ik}$ ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$trsv( uplo, transn, diag, n, a, lda, work, 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_${ci}$trrfs #:endif #:endfor pure module subroutine stdlib${ii}$_slauum( uplo, n, a, lda, info ) !! SLAUUM computes the product U * U**T or L**T * L, where the triangular !! factor U or L is stored in the upper or lower triangular part of !! the array A. !! If UPLO = 'U' or 'u' then the upper triangle of the result is stored, !! overwriting the factor U in A. !! If UPLO = 'L' or 'l' then the lower triangle of the result is stored, !! overwriting the factor L in A. !! This is the blocked form of the algorithm, calling Level 3 BLAS. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ib, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_slauu2( uplo, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute the product u * u**t. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'NON-UNIT',i-1, ib, one, a( & i, i ), lda, a( 1_${ik}$, i ),lda ) call stdlib${ii}$_slauu2( 'UPPER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', i-1, ib,n-i-ib+1, one, a( & 1_${ik}$, i+ib ), lda,a( i, i+ib ), lda, one, a( 1_${ik}$, i ), lda ) call stdlib${ii}$_ssyrk( 'UPPER', 'NO TRANSPOSE', ib, n-i-ib+1,one, a( i, i+ib ),& lda, one, a( i, i ),lda ) end if end do else ! compute the product l**t * l. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_strmm( 'LEFT', 'LOWER', 'TRANSPOSE', 'NON-UNIT', ib,i-1, one, a( & i, i ), lda, a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_slauu2( 'LOWER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_sgemm( 'TRANSPOSE', 'NO TRANSPOSE', ib, i-1,n-i-ib+1, one, a( & i+ib, i ), lda,a( i+ib, 1_${ik}$ ), lda, one, a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_ssyrk( 'LOWER', 'TRANSPOSE', ib, n-i-ib+1, one,a( i+ib, i ), & lda, one, a( i, i ), lda ) end if end do end if end if return end subroutine stdlib${ii}$_slauum pure module subroutine stdlib${ii}$_dlauum( uplo, n, a, lda, info ) !! DLAUUM computes the product U * U**T or L**T * L, where the triangular !! factor U or L is stored in the upper or lower triangular part of !! the array A. !! If UPLO = 'U' or 'u' then the upper triangle of the result is stored, !! overwriting the factor U in A. !! If UPLO = 'L' or 'l' then the lower triangle of the result is stored, !! overwriting the factor L in A. !! This is the blocked form of the algorithm, calling Level 3 BLAS. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ib, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_dlauu2( uplo, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute the product u * u**t. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'NON-UNIT',i-1, ib, one, a( & i, i ), lda, a( 1_${ik}$, i ),lda ) call stdlib${ii}$_dlauu2( 'UPPER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', i-1, ib,n-i-ib+1, one, a( & 1_${ik}$, i+ib ), lda,a( i, i+ib ), lda, one, a( 1_${ik}$, i ), lda ) call stdlib${ii}$_dsyrk( 'UPPER', 'NO TRANSPOSE', ib, n-i-ib+1,one, a( i, i+ib ),& lda, one, a( i, i ),lda ) end if end do else ! compute the product l**t * l. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_dtrmm( 'LEFT', 'LOWER', 'TRANSPOSE', 'NON-UNIT', ib,i-1, one, a( & i, i ), lda, a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_dlauu2( 'LOWER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_dgemm( 'TRANSPOSE', 'NO TRANSPOSE', ib, i-1,n-i-ib+1, one, a( & i+ib, i ), lda,a( i+ib, 1_${ik}$ ), lda, one, a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_dsyrk( 'LOWER', 'TRANSPOSE', ib, n-i-ib+1, one,a( i+ib, i ), & lda, one, a( i, i ), lda ) end if end do end if end if return end subroutine stdlib${ii}$_dlauum #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lauum( uplo, n, a, lda, info ) !! DLAUUM: computes the product U * U**T or L**T * L, where the triangular !! factor U or L is stored in the upper or lower triangular part of !! the array A. !! If UPLO = 'U' or 'u' then the upper triangle of the result is stored, !! overwriting the factor U in A. !! If UPLO = 'L' or 'l' then the lower triangle of the result is stored, !! overwriting the factor L in A. !! This is the blocked form of the algorithm, calling Level 3 BLAS. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ib, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_${ri}$lauu2( uplo, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute the product u * u**t. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', 'TRANSPOSE', 'NON-UNIT',i-1, ib, one, a( & i, i ), lda, a( 1_${ik}$, i ),lda ) call stdlib${ii}$_${ri}$lauu2( 'UPPER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', i-1, ib,n-i-ib+1, one, a( & 1_${ik}$, i+ib ), lda,a( i, i+ib ), lda, one, a( 1_${ik}$, i ), lda ) call stdlib${ii}$_${ri}$syrk( 'UPPER', 'NO TRANSPOSE', ib, n-i-ib+1,one, a( i, i+ib ),& lda, one, a( i, i ),lda ) end if end do else ! compute the product l**t * l. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_${ri}$trmm( 'LEFT', 'LOWER', 'TRANSPOSE', 'NON-UNIT', ib,i-1, one, a( & i, i ), lda, a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_${ri}$lauu2( 'LOWER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'NO TRANSPOSE', ib, i-1,n-i-ib+1, one, a( & i+ib, i ), lda,a( i+ib, 1_${ik}$ ), lda, one, a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_${ri}$syrk( 'LOWER', 'TRANSPOSE', ib, n-i-ib+1, one,a( i+ib, i ), & lda, one, a( i, i ), lda ) end if end do end if end if return end subroutine stdlib${ii}$_${ri}$lauum #:endif #:endfor pure module subroutine stdlib${ii}$_clauum( uplo, n, a, lda, info ) !! CLAUUM computes the product U * U**H or L**H * L, where the triangular !! factor U or L is stored in the upper or lower triangular part of !! the array A. !! If UPLO = 'U' or 'u' then the upper triangle of the result is stored, !! overwriting the factor U in A. !! If UPLO = 'L' or 'l' then the lower triangle of the result is stored, !! overwriting the factor L in A. !! This is the blocked form of the algorithm, calling Level 3 BLAS. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ib, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_clauu2( uplo, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute the product u * u**h. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', i-1, & ib, cone, a( i, i ), lda,a( 1_${ik}$, i ), lda ) call stdlib${ii}$_clauu2( 'UPPER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',i-1, ib, n-i-ib+1,& cone, a( 1_${ik}$, i+ib ),lda, a( i, i+ib ), lda, cone, a( 1_${ik}$, i ),lda ) call stdlib${ii}$_cherk( 'UPPER', 'NO TRANSPOSE', ib, n-i-ib+1,one, a( i, i+ib ),& lda, one, a( i, i ),lda ) end if end do else ! compute the product l**h * l. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_ctrmm( 'LEFT', 'LOWER', 'CONJUGATE TRANSPOSE','NON-UNIT', ib, i-1,& cone, a( i, i ), lda,a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_clauu2( 'LOWER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_cgemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', ib,i-1, n-i-ib+1,& cone, a( i+ib, i ), lda,a( i+ib, 1_${ik}$ ), lda, cone, a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_cherk( 'LOWER', 'CONJUGATE TRANSPOSE', ib,n-i-ib+1, one, a( i+& ib, i ), lda, one,a( i, i ), lda ) end if end do end if end if return end subroutine stdlib${ii}$_clauum pure module subroutine stdlib${ii}$_zlauum( uplo, n, a, lda, info ) !! ZLAUUM computes the product U * U**H or L**H * L, where the triangular !! factor U or L is stored in the upper or lower triangular part of !! the array A. !! If UPLO = 'U' or 'u' then the upper triangle of the result is stored, !! overwriting the factor U in A. !! If UPLO = 'L' or 'l' then the lower triangle of the result is stored, !! overwriting the factor L in A. !! This is the blocked form of the algorithm, calling Level 3 BLAS. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ib, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_zlauu2( uplo, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute the product u * u**h. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', i-1, & ib, cone, a( i, i ), lda,a( 1_${ik}$, i ), lda ) call stdlib${ii}$_zlauu2( 'UPPER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',i-1, ib, n-i-ib+1,& cone, a( 1_${ik}$, i+ib ),lda, a( i, i+ib ), lda, cone, a( 1_${ik}$, i ),lda ) call stdlib${ii}$_zherk( 'UPPER', 'NO TRANSPOSE', ib, n-i-ib+1,one, a( i, i+ib ),& lda, one, a( i, i ),lda ) end if end do else ! compute the product l**h * l. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_ztrmm( 'LEFT', 'LOWER', 'CONJUGATE TRANSPOSE','NON-UNIT', ib, i-1,& cone, a( i, i ), lda,a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_zlauu2( 'LOWER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_zgemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', ib,i-1, n-i-ib+1,& cone, a( i+ib, i ), lda,a( i+ib, 1_${ik}$ ), lda, cone, a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_zherk( 'LOWER', 'CONJUGATE TRANSPOSE', ib,n-i-ib+1, one, a( i+& ib, i ), lda, one,a( i, i ), lda ) end if end do end if end if return end subroutine stdlib${ii}$_zlauum #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lauum( uplo, n, a, lda, info ) !! ZLAUUM: computes the product U * U**H or L**H * L, where the triangular !! factor U or L is stored in the upper or lower triangular part of !! the array A. !! If UPLO = 'U' or 'u' then the upper triangle of the result is stored, !! overwriting the factor U in A. !! If UPLO = 'L' or 'l' then the lower triangle of the result is stored, !! overwriting the factor L in A. !! This is the blocked form of the algorithm, calling Level 3 BLAS. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, ib, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_${ci}$lauu2( uplo, n, a, lda, info ) else ! use blocked code if( upper ) then ! compute the product u * u**h. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', i-1, & ib, cone, a( i, i ), lda,a( 1_${ik}$, i ), lda ) call stdlib${ii}$_${ci}$lauu2( 'UPPER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',i-1, ib, n-i-ib+1,& cone, a( 1_${ik}$, i+ib ),lda, a( i, i+ib ), lda, cone, a( 1_${ik}$, i ),lda ) call stdlib${ii}$_${ci}$herk( 'UPPER', 'NO TRANSPOSE', ib, n-i-ib+1,one, a( i, i+ib ),& lda, one, a( i, i ),lda ) end if end do else ! compute the product l**h * l. do i = 1, n, nb ib = min( nb, n-i+1 ) call stdlib${ii}$_${ci}$trmm( 'LEFT', 'LOWER', 'CONJUGATE TRANSPOSE','NON-UNIT', ib, i-1,& cone, a( i, i ), lda,a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$lauu2( 'LOWER', ib, a( i, i ), lda, info ) if( i+ib<=n ) then call stdlib${ii}$_${ci}$gemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', ib,i-1, n-i-ib+1,& cone, a( i+ib, i ), lda,a( i+ib, 1_${ik}$ ), lda, cone, a( i, 1_${ik}$ ), lda ) call stdlib${ii}$_${ci}$herk( 'LOWER', 'CONJUGATE TRANSPOSE', ib,n-i-ib+1, one, a( i+& ib, i ), lda, one,a( i, i ), lda ) end if end do end if end if return end subroutine stdlib${ii}$_${ci}$lauum #:endif #:endfor pure module subroutine stdlib${ii}$_slauu2( uplo, n, a, lda, info ) !! SLAUU2 computes the product U * U**T or L**T * L, where the triangular !! factor U or L is stored in the upper or lower triangular part of !! the array A. !! If UPLO = 'U' or 'u' then the upper triangle of the result is stored, !! overwriting the factor U in A. !! If UPLO = 'L' or 'l' then the lower triangle of the result is stored, !! overwriting the factor L in A. !! This is the unblocked form of the algorithm, calling Level 2 BLAS. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i real(sp) :: aii ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_slacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_slatps( uplo, 'NO TRANSPOSE', diag, normin, n, ap,work, scale, & work( 2_${ik}$*n+1 ), info ) else ! multiply by inv(a**t). call stdlib${ii}$_slatps( uplo, 'TRANSPOSE', diag, normin, n, ap,work, scale, work( & 2_${ik}$*n+1 ), info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_isamax( n, work, 1_${ik}$ ) xnorm = abs( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_dlacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_dlatps( uplo, 'NO TRANSPOSE', diag, normin, n, ap,work, scale, & work( 2_${ik}$*n+1 ), info ) else ! multiply by inv(a**t). call stdlib${ii}$_dlatps( uplo, 'TRANSPOSE', diag, normin, n, ap,work, scale, work( & 2_${ik}$*n+1 ), info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_idamax( n, work, 1_${ik}$ ) xnorm = abs( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_${ri}$lacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_${ri}$latps( uplo, 'NO TRANSPOSE', diag, normin, n, ap,work, scale, & work( 2_${ik}$*n+1 ), info ) else ! multiply by inv(a**t). call stdlib${ii}$_${ri}$latps( uplo, 'TRANSPOSE', diag, normin, n, ap,work, scale, work( & 2_${ik}$*n+1 ), info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ ) xnorm = abs( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_clatps( uplo, 'NO TRANSPOSE', diag, normin, n, ap,work, scale, & rwork, info ) else ! multiply by inv(a**h). call stdlib${ii}$_clatps( uplo, 'CONJUGATE TRANSPOSE', diag, normin,n, ap, work, & scale, rwork, info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_icamax( n, work, 1_${ik}$ ) xnorm = cabs1( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_zlatps( uplo, 'NO TRANSPOSE', diag, normin, n, ap,work, scale, & rwork, info ) else ! multiply by inv(a**h). call stdlib${ii}$_zlatps( uplo, 'CONJUGATE TRANSPOSE', diag, normin,n, ap, work, & scale, rwork, info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_izamax( n, work, 1_${ik}$ ) xnorm = cabs1( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_${ci}$latps( uplo, 'NO TRANSPOSE', diag, normin, n, ap,work, scale, & rwork, info ) else ! multiply by inv(a**h). call stdlib${ii}$_${ci}$latps( uplo, 'CONJUGATE TRANSPOSE', diag, normin,n, ap, work, & scale, rwork, info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_i${ci}$amax( n, work, 1_${ik}$ ) xnorm = cabs1( work( ix ) ) if( scale=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if ip = ip + jinc*jlen jlen = jlen - 1_${ik}$ end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 50 continue else ! compute the growth in a**t * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 80 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = 1_${ik}$ do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) tjj = abs( ap( ip ) ) if( xj>tjj )xbnd = xbnd*( tjj / xj ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 80 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_stpsv( uplo, trans, diag, n, ap, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = bignum / xmax call stdlib${ii}$_sscal( n, scale, x, 1_${ik}$ ) xmax = bignum end if if( notran ) then ! solve a * x = b ip = jfirst*( jfirst+1 ) / 2_${ik}$ loop_100: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = abs( x( j ) ) if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal if( tscal==one )go to 95 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 95 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_sscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_saxpy( j-1, -x( j )*tscal, ap( ip-j+1 ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_isamax( j-1, x, 1_${ik}$ ) xmax = abs( x( i ) ) end if ip = ip - j else if( jj xj = abs( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal end if tjj = abs( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = uscal / tjjs end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a**t*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 135 continue else ! compute x(j) := x(j) / a(j,j) - sumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = x( j ) / tjjs - sumj end if xmax = max( xmax, abs( x( j ) ) ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do loop_140 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_sscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_slatps pure module subroutine stdlib${ii}$_dlatps( uplo, trans, diag, normin, n, ap, x, scale,cnorm, info ) !! DLATPS solves one of the triangular systems !! A *x = s*b or A**T*x = s*b !! with scaling to prevent overflow, where A is an upper or lower !! triangular matrix stored in packed form. Here A**T denotes the !! transpose of A, x and b are n-element vectors, and s is a scaling !! factor, usually less than or equal to 1, chosen so that the !! components of x will be less than the overflow threshold. If the !! unscaled problem will not cause overflow, the Level 2 BLAS routine !! DTPSV is called. If the matrix A is singular (A(j,j) = 0 for some j), !! then s is set to 0 and a non-trivial solution to A*x = 0 is returned. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: scale ! Array Arguments real(dp), intent(in) :: ap(*) real(dp), intent(inout) :: cnorm(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, ip, j, jfirst, jinc, jlast, jlen real(dp) :: bignum, grow, rec, smlnum, sumj, tjj, tjjs, tmax, tscal, uscal, xbnd, xj, & xmax ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLATPS', -info ) return end if ! quick return if possible if( n==0 )return ! determine machine dependent parameters to control overflow. smlnum = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) bignum = one / smlnum scale = one if( stdlib_lsame( normin, 'N' ) ) then ! compute the 1-norm of each column, not including the diagonal. if( upper ) then ! a is upper triangular. ip = 1_${ik}$ do j = 1, n cnorm( j ) = stdlib${ii}$_dasum( j-1, ap( ip ), 1_${ik}$ ) ip = ip + j end do else ! a is lower triangular. ip = 1_${ik}$ do j = 1, n - 1 cnorm( j ) = stdlib${ii}$_dasum( n-j, ap( ip+1 ), 1_${ik}$ ) ip = ip + n - j + 1_${ik}$ end do cnorm( n ) = zero end if end if ! scale the column norms by tscal if the maximum element in cnorm is ! greater than bignum. imax = stdlib${ii}$_idamax( n, cnorm, 1_${ik}$ ) tmax = cnorm( imax ) if( tmax<=bignum ) then tscal = one else tscal = one / ( smlnum*tmax ) call stdlib${ii}$_dscal( n, tscal, cnorm, 1_${ik}$ ) end if ! compute a bound on the computed solution vector to see if the ! level 2 blas routine stdlib${ii}$_dtpsv can be used. j = stdlib${ii}$_idamax( n, x, 1_${ik}$ ) xmax = abs( x( j ) ) xbnd = xmax if( notran ) then ! compute the growth in a * x = b. if( upper ) then jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ else jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 50 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, g(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = n do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! m(j) = g(j-1) / abs(a(j,j)) tjj = abs( ap( ip ) ) xbnd = min( xbnd, min( one, tjj )*grow ) if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if ip = ip + jinc*jlen jlen = jlen - 1_${ik}$ end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 50 continue else ! compute the growth in a**t * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 80 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = 1_${ik}$ do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) tjj = abs( ap( ip ) ) if( xj>tjj )xbnd = xbnd*( tjj / xj ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 80 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_dtpsv( uplo, trans, diag, n, ap, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = bignum / xmax call stdlib${ii}$_dscal( n, scale, x, 1_${ik}$ ) xmax = bignum end if if( notran ) then ! solve a * x = b ip = jfirst*( jfirst+1 ) / 2_${ik}$ loop_110: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = abs( x( j ) ) if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal if( tscal==one )go to 100 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 100 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_dscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_daxpy( j-1, -x( j )*tscal, ap( ip-j+1 ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_idamax( j-1, x, 1_${ik}$ ) xmax = abs( x( i ) ) end if ip = ip - j else if( jj xj = abs( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal end if tjj = abs( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = uscal / tjjs end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a**t*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 150 continue else ! compute x(j) := x(j) / a(j,j) - sumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = x( j ) / tjjs - sumj end if xmax = max( xmax, abs( x( j ) ) ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do loop_160 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_dscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_dlatps #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$latps( uplo, trans, diag, normin, n, ap, x, scale,cnorm, info ) !! DLATPS: solves one of the triangular systems !! A *x = s*b or A**T*x = s*b !! with scaling to prevent overflow, where A is an upper or lower !! triangular matrix stored in packed form. Here A**T denotes the !! transpose of A, x and b are n-element vectors, and s is a scaling !! factor, usually less than or equal to 1, chosen so that the !! components of x will be less than the overflow threshold. If the !! unscaled problem will not cause overflow, the Level 2 BLAS routine !! DTPSV is called. If the matrix A is singular (A(j,j) = 0 for some j), !! then s is set to 0 and a non-trivial solution to A*x = 0 is returned. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(${rk}$), intent(out) :: scale ! Array Arguments real(${rk}$), intent(in) :: ap(*) real(${rk}$), intent(inout) :: cnorm(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, ip, j, jfirst, jinc, jlast, jlen real(${rk}$) :: bignum, grow, rec, smlnum, sumj, tjj, tjjs, tmax, tscal, uscal, xbnd, xj, & xmax ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLATPS', -info ) return end if ! quick return if possible if( n==0 )return ! determine machine dependent parameters to control overflow. smlnum = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${ri}$lamch( 'PRECISION' ) bignum = one / smlnum scale = one if( stdlib_lsame( normin, 'N' ) ) then ! compute the 1-norm of each column, not including the diagonal. if( upper ) then ! a is upper triangular. ip = 1_${ik}$ do j = 1, n cnorm( j ) = stdlib${ii}$_${ri}$asum( j-1, ap( ip ), 1_${ik}$ ) ip = ip + j end do else ! a is lower triangular. ip = 1_${ik}$ do j = 1, n - 1 cnorm( j ) = stdlib${ii}$_${ri}$asum( n-j, ap( ip+1 ), 1_${ik}$ ) ip = ip + n - j + 1_${ik}$ end do cnorm( n ) = zero end if end if ! scale the column norms by tscal if the maximum element in cnorm is ! greater than bignum. imax = stdlib${ii}$_i${ri}$amax( n, cnorm, 1_${ik}$ ) tmax = cnorm( imax ) if( tmax<=bignum ) then tscal = one else tscal = one / ( smlnum*tmax ) call stdlib${ii}$_${ri}$scal( n, tscal, cnorm, 1_${ik}$ ) end if ! compute a bound on the computed solution vector to see if the ! level 2 blas routine stdlib${ii}$_${ri}$tpsv can be used. j = stdlib${ii}$_i${ri}$amax( n, x, 1_${ik}$ ) xmax = abs( x( j ) ) xbnd = xmax if( notran ) then ! compute the growth in a * x = b. if( upper ) then jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ else jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 50 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, g(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = n do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! m(j) = g(j-1) / abs(a(j,j)) tjj = abs( ap( ip ) ) xbnd = min( xbnd, min( one, tjj )*grow ) if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if ip = ip + jinc*jlen jlen = jlen - 1_${ik}$ end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 50 continue else ! compute the growth in a**t * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 80 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = 1_${ik}$ do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) tjj = abs( ap( ip ) ) if( xj>tjj )xbnd = xbnd*( tjj / xj ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 80 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_${ri}$tpsv( uplo, trans, diag, n, ap, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = bignum / xmax call stdlib${ii}$_${ri}$scal( n, scale, x, 1_${ik}$ ) xmax = bignum end if if( notran ) then ! solve a * x = b ip = jfirst*( jfirst+1 ) / 2_${ik}$ loop_110: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = abs( x( j ) ) if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal if( tscal==one )go to 100 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 100 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_${ri}$scal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_${ri}$axpy( j-1, -x( j )*tscal, ap( ip-j+1 ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_i${ri}$amax( j-1, x, 1_${ik}$ ) xmax = abs( x( i ) ) end if ip = ip - j else if( jj xj = abs( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal end if tjj = abs( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = uscal / tjjs end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a**t*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 150 continue else ! compute x(j) := x(j) / a(j,j) - sumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = x( j ) / tjjs - sumj end if xmax = max( xmax, abs( x( j ) ) ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do loop_160 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_${ri}$scal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ri}$latps #:endif #:endfor pure module subroutine stdlib${ii}$_clatps( uplo, trans, diag, normin, n, ap, x, scale,cnorm, info ) !! CLATPS solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow, where A is an upper or lower !! triangular matrix stored in packed form. Here A**T denotes the !! transpose of A, A**H denotes the conjugate transpose of A, x and b !! are n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine CTPSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(out) :: scale ! Array Arguments real(sp), intent(inout) :: cnorm(*) complex(sp), intent(in) :: ap(*) complex(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, ip, j, jfirst, jinc, jlast, jlen real(sp) :: bignum, grow, rec, smlnum, tjj, tmax, tscal, xbnd, xj, xmax complex(sp) :: csumj, tjjs, uscal, zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1, cabs2 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) cabs2( zdum ) = abs( real( zdum,KIND=sp) / 2. ) +abs( aimag( zdum ) / 2. ) ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CLATPS', -info ) return end if ! quick return if possible if( n==0 )return ! determine machine dependent parameters to control overflow. smlnum = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = smlnum / stdlib${ii}$_slamch( 'PRECISION' ) bignum = one / smlnum scale = one if( stdlib_lsame( normin, 'N' ) ) then ! compute the 1-norm of each column, not including the diagonal. if( upper ) then ! a is upper triangular. ip = 1_${ik}$ do j = 1, n cnorm( j ) = stdlib${ii}$_scasum( j-1, ap( ip ), 1_${ik}$ ) ip = ip + j end do else ! a is lower triangular. ip = 1_${ik}$ do j = 1, n - 1 cnorm( j ) = stdlib${ii}$_scasum( n-j, ap( ip+1 ), 1_${ik}$ ) ip = ip + n - j + 1_${ik}$ end do cnorm( n ) = zero end if end if ! scale the column norms by tscal if the maximum element in cnorm is ! greater than bignum/2. imax = stdlib${ii}$_isamax( n, cnorm, 1_${ik}$ ) tmax = cnorm( imax ) if( tmax<=bignum*half ) then tscal = one else tscal = half / ( smlnum*tmax ) call stdlib${ii}$_sscal( n, tscal, cnorm, 1_${ik}$ ) end if ! compute a bound on the computed solution vector to see if the ! level 2 blas routine stdlib${ii}$_ctpsv can be used. xmax = zero do j = 1, n xmax = max( xmax, cabs2( x( j ) ) ) end do xbnd = xmax if( notran ) then ! compute the growth in a * x = b. if( upper ) then jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ else jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 60 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, g(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = n do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 tjjs = ap( ip ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = g(j-1) / abs(a(j,j)) xbnd = min( xbnd, min( one, tjj )*grow ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if ip = ip + jinc*jlen jlen = jlen - 1_${ik}$ end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 60 continue else ! compute the growth in a**t * x = b or a**h * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 90 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = 1_${ik}$ do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) tjjs = ap( ip ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) if( xj>tjj )xbnd = xbnd*( tjj / xj ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 90 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_ctpsv( uplo, trans, diag, n, ap, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum*half ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = ( bignum*half ) / xmax call stdlib${ii}$_csscal( n, scale, x, 1_${ik}$ ) xmax = bignum else xmax = xmax*two end if if( notran ) then ! solve a * x = b ip = jfirst*( jfirst+1 ) / 2_${ik}$ loop_110: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = cabs1( x( j ) ) if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal if( tscal==one )go to 105 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 105 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_csscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_caxpy( j-1, -x( j )*tscal, ap( ip-j+1 ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_icamax( j-1, x, 1_${ik}$ ) xmax = cabs1( x( i ) ) end if ip = ip - j else if( jj xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_cladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**t *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 145 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do loop_150 else ! solve a**h * x = b ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = 1_${ik}$ loop_190: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = conjg( ap( ip ) )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_cladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**h *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 185 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do loop_190 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_sscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_clatps pure module subroutine stdlib${ii}$_zlatps( uplo, trans, diag, normin, n, ap, x, scale,cnorm, info ) !! ZLATPS solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow, where A is an upper or lower !! triangular matrix stored in packed form. Here A**T denotes the !! transpose of A, A**H denotes the conjugate transpose of A, x and b !! are n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine ZTPSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: scale ! Array Arguments real(dp), intent(inout) :: cnorm(*) complex(dp), intent(in) :: ap(*) complex(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, ip, j, jfirst, jinc, jlast, jlen real(dp) :: bignum, grow, rec, smlnum, tjj, tmax, tscal, xbnd, xj, xmax complex(dp) :: csumj, tjjs, uscal, zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1, cabs2 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) cabs2( zdum ) = abs( real( zdum,KIND=dp) / 2._dp ) +abs( aimag( zdum ) / 2._dp ) ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLATPS', -info ) return end if ! quick return if possible if( n==0 )return ! determine machine dependent parameters to control overflow. smlnum = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = smlnum / stdlib${ii}$_dlamch( 'PRECISION' ) bignum = one / smlnum scale = one if( stdlib_lsame( normin, 'N' ) ) then ! compute the 1-norm of each column, not including the diagonal. if( upper ) then ! a is upper triangular. ip = 1_${ik}$ do j = 1, n cnorm( j ) = stdlib${ii}$_dzasum( j-1, ap( ip ), 1_${ik}$ ) ip = ip + j end do else ! a is lower triangular. ip = 1_${ik}$ do j = 1, n - 1 cnorm( j ) = stdlib${ii}$_dzasum( n-j, ap( ip+1 ), 1_${ik}$ ) ip = ip + n - j + 1_${ik}$ end do cnorm( n ) = zero end if end if ! scale the column norms by tscal if the maximum element in cnorm is ! greater than bignum/2. imax = stdlib${ii}$_idamax( n, cnorm, 1_${ik}$ ) tmax = cnorm( imax ) if( tmax<=bignum*half ) then tscal = one else tscal = half / ( smlnum*tmax ) call stdlib${ii}$_dscal( n, tscal, cnorm, 1_${ik}$ ) end if ! compute a bound on the computed solution vector to see if the ! level 2 blas routine stdlib${ii}$_ztpsv can be used. xmax = zero do j = 1, n xmax = max( xmax, cabs2( x( j ) ) ) end do xbnd = xmax if( notran ) then ! compute the growth in a * x = b. if( upper ) then jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ else jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 60 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, g(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = n do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 tjjs = ap( ip ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = g(j-1) / abs(a(j,j)) xbnd = min( xbnd, min( one, tjj )*grow ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if ip = ip + jinc*jlen jlen = jlen - 1_${ik}$ end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 60 continue else ! compute the growth in a**t * x = b or a**h * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 90 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = 1_${ik}$ do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) tjjs = ap( ip ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) if( xj>tjj )xbnd = xbnd*( tjj / xj ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 90 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_ztpsv( uplo, trans, diag, n, ap, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum*half ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = ( bignum*half ) / xmax call stdlib${ii}$_zdscal( n, scale, x, 1_${ik}$ ) xmax = bignum else xmax = xmax*two end if if( notran ) then ! solve a * x = b ip = jfirst*( jfirst+1 ) / 2_${ik}$ loop_120: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = cabs1( x( j ) ) if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal if( tscal==one )go to 110 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 110 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_zdscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_zaxpy( j-1, -x( j )*tscal, ap( ip-j+1 ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_izamax( j-1, x, 1_${ik}$ ) xmax = cabs1( x( i ) ) end if ip = ip - j else if( jj xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_zladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**t *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 160 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do loop_170 else ! solve a**h * x = b ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = 1_${ik}$ loop_220: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = conjg( ap( ip ) )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_zladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**h *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 210 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do loop_220 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_dscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_zlatps #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$latps( uplo, trans, diag, normin, n, ap, x, scale,cnorm, info ) !! ZLATPS: solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow, where A is an upper or lower !! triangular matrix stored in packed form. Here A**T denotes the !! transpose of A, A**H denotes the conjugate transpose of A, x and b !! are n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine ZTPSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(${ck}$), intent(out) :: scale ! Array Arguments real(${ck}$), intent(inout) :: cnorm(*) complex(${ck}$), intent(in) :: ap(*) complex(${ck}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, ip, j, jfirst, jinc, jlast, jlen real(${ck}$) :: bignum, grow, rec, smlnum, tjj, tmax, tscal, xbnd, xj, xmax complex(${ck}$) :: csumj, tjjs, uscal, zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1, cabs2 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) cabs2( zdum ) = abs( real( zdum,KIND=${ck}$) / 2._${ck}$ ) +abs( aimag( zdum ) / 2._${ck}$ ) ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLATPS', -info ) return end if ! quick return if possible if( n==0 )return ! determine machine dependent parameters to control overflow. smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) bignum = one / smlnum call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum ) smlnum = smlnum / stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) bignum = one / smlnum scale = one if( stdlib_lsame( normin, 'N' ) ) then ! compute the 1-norm of each column, not including the diagonal. if( upper ) then ! a is upper triangular. ip = 1_${ik}$ do j = 1, n cnorm( j ) = stdlib${ii}$_${c2ri(ci)}$zasum( j-1, ap( ip ), 1_${ik}$ ) ip = ip + j end do else ! a is lower triangular. ip = 1_${ik}$ do j = 1, n - 1 cnorm( j ) = stdlib${ii}$_${c2ri(ci)}$zasum( n-j, ap( ip+1 ), 1_${ik}$ ) ip = ip + n - j + 1_${ik}$ end do cnorm( n ) = zero end if end if ! scale the column norms by tscal if the maximum element in cnorm is ! greater than bignum/2. imax = stdlib${ii}$_i${c2ri(ci)}$amax( n, cnorm, 1_${ik}$ ) tmax = cnorm( imax ) if( tmax<=bignum*half ) then tscal = one else tscal = half / ( smlnum*tmax ) call stdlib${ii}$_${c2ri(ci)}$scal( n, tscal, cnorm, 1_${ik}$ ) end if ! compute a bound on the computed solution vector to see if the ! level 2 blas routine stdlib${ii}$_${ci}$tpsv can be used. xmax = zero do j = 1, n xmax = max( xmax, cabs2( x( j ) ) ) end do xbnd = xmax if( notran ) then ! compute the growth in a * x = b. if( upper ) then jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ else jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 60 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, g(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = n do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 tjjs = ap( ip ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = g(j-1) / abs(a(j,j)) xbnd = min( xbnd, min( one, tjj )*grow ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if ip = ip + jinc*jlen jlen = jlen - 1_${ik}$ end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 60 continue else ! compute the growth in a**t * x = b or a**h * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ end if if( tscal/=one ) then grow = zero go to 90 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = 1_${ik}$ do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) tjjs = ap( ip ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) if( xj>tjj )xbnd = xbnd*( tjj / xj ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 90 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_${ci}$tpsv( uplo, trans, diag, n, ap, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum*half ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = ( bignum*half ) / xmax call stdlib${ii}$_${ci}$dscal( n, scale, x, 1_${ik}$ ) xmax = bignum else xmax = xmax*two end if if( notran ) then ! solve a * x = b ip = jfirst*( jfirst+1 ) / 2_${ik}$ loop_120: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = cabs1( x( j ) ) if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal if( tscal==one )go to 110 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 110 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_${ci}$dscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(1:j-1) := x(1:j-1) - x(j) * a(1:j-1,j) call stdlib${ii}$_${ci}$axpy( j-1, -x( j )*tscal, ap( ip-j+1 ), 1_${ik}$, x,1_${ik}$ ) i = stdlib${ii}$_i${ci}$amax( j-1, x, 1_${ik}$ ) xmax = cabs1( x( i ) ) end if ip = ip - j else if( jj xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ap( ip )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_${ci}$ladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**t *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 160 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do loop_170 else ! solve a**h * x = b ip = jfirst*( jfirst+1 ) / 2_${ik}$ jlen = 1_${ik}$ loop_220: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = conjg( ap( ip ) )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_${ci}$ladiv( uscal, tjjs ) end if if( recsmlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**h *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 210 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) jlen = jlen + 1_${ik}$ ip = ip + jinc*jlen end do loop_220 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_${c2ri(ci)}$scal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ci}$latps #:endif #:endfor pure module subroutine stdlib${ii}$_stptri( uplo, diag, n, ap, info ) !! STPTRI computes the inverse of a real upper or lower triangular !! matrix A stored in packed format. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(inout) :: ap(*) ! ===================================================================== ! Local Scalars logical(lk) :: nounit, upper integer(${ik}$) :: j, jc, jclast, jj real(sp) :: ajj ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'STPTRI', -info ) return end if ! check for singularity if non-unit. if( nounit ) then if( upper ) then jj = 0_${ik}$ do info = 1, n jj = jj + info if( ap( jj )==zero )return end do else jj = 1_${ik}$ do info = 1, n if( ap( jj )==zero )return jj = jj + n - info + 1_${ik}$ end do end if info = 0_${ik}$ end if if( upper ) then ! compute inverse of upper triangular matrix. jc = 1_${ik}$ do j = 1, n if( nounit ) then ap( jc+j-1 ) = one / ap( jc+j-1 ) ajj = -ap( jc+j-1 ) else ajj = -one end if ! compute elements 1:j-1 of j-th column. call stdlib${ii}$_stpmv( 'UPPER', 'NO TRANSPOSE', diag, j-1, ap,ap( jc ), 1_${ik}$ ) call stdlib${ii}$_sscal( j-1, ajj, ap( jc ), 1_${ik}$ ) jc = jc + j end do else ! compute inverse of lower triangular matrix. jc = n*( n+1 ) / 2_${ik}$ do j = n, 1, -1 if( nounit ) then ap( jc ) = one / ap( jc ) ajj = -ap( jc ) else ajj = -one end if if( jsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_slacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_slacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_stpsv( uplo, transt, diag, n, ap, work( n+1 ), 1_${ik}$ ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_stpsv( uplo, trans, diag, n, ap, work( n+1 ), 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_stprfs pure module subroutine stdlib${ii}$_dtprfs( uplo, trans, diag, n, nrhs, ap, b, ldb, x, ldx,ferr, berr, & !! DTPRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular packed !! coefficient matrix. !! The solution matrix X must be computed by DTPTRS or some other !! means before entering this routine. DTPRFS does not do iterative !! refinement because doing so cannot improve the backward error. work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: ap(*), b(ldb,*), x(ldx,*) real(dp), intent(out) :: berr(*), ferr(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transt integer(${ik}$) :: i, j, k, kase, kc, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldbsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_dlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_dlacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_dtpsv( uplo, transt, diag, n, ap, work( n+1 ), 1_${ik}$ ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_dtpsv( uplo, trans, diag, n, ap, work( n+1 ), 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_dtprfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tprfs( uplo, trans, diag, n, nrhs, ap, b, ldb, x, ldx,ferr, berr, & !! DTPRFS: provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular packed !! coefficient matrix. !! The solution matrix X must be computed by DTPTRS or some other !! means before entering this routine. DTPRFS does not do iterative !! refinement because doing so cannot improve the backward error. work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: ap(*), b(ldb,*), x(ldx,*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transt integer(${ik}$) :: i, j, k, kase, kc, nz real(${rk}$) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldbsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ri}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_${ri}$lacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_${ri}$tpsv( uplo, transt, diag, n, ap, work( n+1 ), 1_${ik}$ ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_${ri}$tpsv( uplo, trans, diag, n, ap, work( n+1 ), 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_${ri}$tprfs #:endif #:endfor pure module subroutine stdlib${ii}$_ctprfs( uplo, trans, diag, n, nrhs, ap, b, ldb, x, ldx,ferr, berr, & !! CTPRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular packed !! coefficient matrix. !! The solution matrix X must be computed by CTPTRS or some other !! means before entering this routine. CTPRFS does not do iterative !! refinement because doing so cannot improve the backward error. work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: ap(*), b(ldb,*), x(ldx,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transn, transt integer(${ik}$) :: i, j, k, kase, kc, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_ctpsv( uplo, transt, diag, n, ap, work, 1_${ik}$ ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_ctpsv( uplo, transn, diag, n, ap, work, 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_ctprfs pure module subroutine stdlib${ii}$_ztprfs( uplo, trans, diag, n, nrhs, ap, b, ldb, x, ldx,ferr, berr, & !! ZTPRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular packed !! coefficient matrix. !! The solution matrix X must be computed by ZTPTRS or some other !! means before entering this routine. ZTPRFS does not do iterative !! refinement because doing so cannot improve the backward error. work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: ap(*), b(ldb,*), x(ldx,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transn, transt integer(${ik}$) :: i, j, k, kase, kc, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_ztpsv( uplo, transt, diag, n, ap, work, 1_${ik}$ ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_ztpsv( uplo, transn, diag, n, ap, work, 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_ztprfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tprfs( uplo, trans, diag, n, nrhs, ap, b, ldb, x, ldx,ferr, berr, & !! ZTPRFS: provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular packed !! coefficient matrix. !! The solution matrix X must be computed by ZTPTRS or some other !! means before entering this routine. ZTPRFS does not do iterative !! refinement because doing so cannot improve the backward error. work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: ap(*), b(ldb,*), x(ldx,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transn, transt integer(${ik}$) :: i, j, k, kase, kc, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( nrhs<0_${ik}$ ) then info = -5_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_${ci}$tpsv( uplo, transt, diag, n, ap, work, 1_${ik}$ ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$tpsv( uplo, transn, diag, n, ap, work, 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_${ci}$tprfs #:endif #:endfor pure module subroutine stdlib${ii}$_stftri( transr, uplo, diag, n, a, info ) !! STFTRI computes the inverse of a triangular matrix A stored in RFP !! format. !! This is a Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo, diag integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'T' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( .not.stdlib_lsame( diag, 'N' ) .and. .not.stdlib_lsame( diag, 'U' ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'STFTRI', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_strtri( 'L', diag, n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_strmm( 'R', 'L', 'N', diag, n2, n1, -one, a( 0_${ik}$ ),n, a( n1 ), n ) call stdlib${ii}$_strtri( 'U', diag, n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_strmm( 'L', 'U', 'T', diag, n2, n1, one, a( n ), n,a( n1 ), n ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_strtri( 'L', diag, n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_strmm( 'L', 'L', 'T', diag, n1, n2, -one, a( n2 ),n, a( 0_${ik}$ ), n ) call stdlib${ii}$_strtri( 'U', diag, n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_strmm( 'R', 'U', 'N', diag, n1, n2, one, a( n1 ),n, a( 0_${ik}$ ), n ) end if else ! n is odd and transr = 't' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_strtri( 'U', diag, n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_strmm( 'L', 'U', 'N', diag, n1, n2, -one, a( 0_${ik}$ ),n1, a( n1*n1 ), & n1 ) call stdlib${ii}$_strtri( 'L', diag, n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_strmm( 'R', 'L', 'T', diag, n1, n2, one, a( 1_${ik}$ ),n1, a( n1*n1 ), & n1 ) else ! srpa for upper, transpose and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_strtri( 'U', diag, n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_strmm( 'R', 'U', 'T', diag, n2, n1, -one,a( n2*n2 ), n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_strtri( 'L', diag, n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_strmm( 'L', 'L', 'N', diag, n2, n1, one,a( n1*n2 ), n2, a( 0_${ik}$ ), & n2 ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_strtri( 'L', diag, k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_strmm( 'R', 'L', 'N', diag, k, k, -one, a( 1_${ik}$ ),n+1, a( k+1 ), n+1 & ) call stdlib${ii}$_strtri( 'U', diag, k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_strmm( 'L', 'U', 'T', diag, k, k, one, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_strtri( 'L', diag, k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_strmm( 'L', 'L', 'T', diag, k, k, -one, a( k+1 ),n+1, a( 0_${ik}$ ), n+1 & ) call stdlib${ii}$_strtri( 'U', diag, k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_strmm( 'R', 'U', 'N', diag, k, k, one, a( k ), n+1,a( 0_${ik}$ ), n+1 ) end if else ! n is even and transr = 't' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_strtri( 'U', diag, k, a( k ), k, info ) if( info>0 )return call stdlib${ii}$_strmm( 'L', 'U', 'N', diag, k, k, -one, a( k ), k,a( k*( k+1 ) ), & k ) call stdlib${ii}$_strtri( 'L', diag, k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_strmm( 'R', 'L', 'T', diag, k, k, one, a( 0_${ik}$ ), k,a( k*( k+1 ) ), & k ) else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_strtri( 'U', diag, k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_strmm( 'R', 'U', 'T', diag, k, k, -one,a( k*( k+1 ) ), k, a( 0_${ik}$ ), & k ) call stdlib${ii}$_strtri( 'L', diag, k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_strmm( 'L', 'L', 'N', diag, k, k, one, a( k*k ), k,a( 0_${ik}$ ), k ) end if end if end if return end subroutine stdlib${ii}$_stftri pure module subroutine stdlib${ii}$_dtftri( transr, uplo, diag, n, a, info ) !! DTFTRI computes the inverse of a triangular matrix A stored in RFP !! format. !! This is a Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo, diag integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'T' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( .not.stdlib_lsame( diag, 'N' ) .and. .not.stdlib_lsame( diag, 'U' ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DTFTRI', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_dtrtri( 'L', diag, n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_dtrmm( 'R', 'L', 'N', diag, n2, n1, -one, a( 0_${ik}$ ),n, a( n1 ), n ) call stdlib${ii}$_dtrtri( 'U', diag, n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_dtrmm( 'L', 'U', 'T', diag, n2, n1, one, a( n ), n,a( n1 ), n ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_dtrtri( 'L', diag, n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_dtrmm( 'L', 'L', 'T', diag, n1, n2, -one, a( n2 ),n, a( 0_${ik}$ ), n ) call stdlib${ii}$_dtrtri( 'U', diag, n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_dtrmm( 'R', 'U', 'N', diag, n1, n2, one, a( n1 ),n, a( 0_${ik}$ ), n ) end if else ! n is odd and transr = 't' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_dtrtri( 'U', diag, n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_dtrmm( 'L', 'U', 'N', diag, n1, n2, -one, a( 0_${ik}$ ),n1, a( n1*n1 ), & n1 ) call stdlib${ii}$_dtrtri( 'L', diag, n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_dtrmm( 'R', 'L', 'T', diag, n1, n2, one, a( 1_${ik}$ ),n1, a( n1*n1 ), & n1 ) else ! srpa for upper, transpose and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_dtrtri( 'U', diag, n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_dtrmm( 'R', 'U', 'T', diag, n2, n1, -one,a( n2*n2 ), n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_dtrtri( 'L', diag, n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_dtrmm( 'L', 'L', 'N', diag, n2, n1, one,a( n1*n2 ), n2, a( 0_${ik}$ ), & n2 ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_dtrtri( 'L', diag, k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_dtrmm( 'R', 'L', 'N', diag, k, k, -one, a( 1_${ik}$ ),n+1, a( k+1 ), n+1 & ) call stdlib${ii}$_dtrtri( 'U', diag, k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_dtrmm( 'L', 'U', 'T', diag, k, k, one, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_dtrtri( 'L', diag, k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_dtrmm( 'L', 'L', 'T', diag, k, k, -one, a( k+1 ),n+1, a( 0_${ik}$ ), n+1 & ) call stdlib${ii}$_dtrtri( 'U', diag, k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_dtrmm( 'R', 'U', 'N', diag, k, k, one, a( k ), n+1,a( 0_${ik}$ ), n+1 ) end if else ! n is even and transr = 't' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_dtrtri( 'U', diag, k, a( k ), k, info ) if( info>0 )return call stdlib${ii}$_dtrmm( 'L', 'U', 'N', diag, k, k, -one, a( k ), k,a( k*( k+1 ) ), & k ) call stdlib${ii}$_dtrtri( 'L', diag, k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_dtrmm( 'R', 'L', 'T', diag, k, k, one, a( 0_${ik}$ ), k,a( k*( k+1 ) ), & k ) else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_dtrtri( 'U', diag, k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_dtrmm( 'R', 'U', 'T', diag, k, k, -one,a( k*( k+1 ) ), k, a( 0_${ik}$ ), & k ) call stdlib${ii}$_dtrtri( 'L', diag, k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_dtrmm( 'L', 'L', 'N', diag, k, k, one, a( k*k ), k,a( 0_${ik}$ ), k ) end if end if end if return end subroutine stdlib${ii}$_dtftri #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tftri( transr, uplo, diag, n, a, info ) !! DTFTRI: computes the inverse of a triangular matrix A stored in RFP !! format. !! This is a Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo, diag integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(${rk}$), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'T' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( .not.stdlib_lsame( diag, 'N' ) .and. .not.stdlib_lsame( diag, 'U' ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DTFTRI', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_${ri}$trtri( 'L', diag, n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'R', 'L', 'N', diag, n2, n1, -one, a( 0_${ik}$ ),n, a( n1 ), n ) call stdlib${ii}$_${ri}$trtri( 'U', diag, n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'L', 'U', 'T', diag, n2, n1, one, a( n ), n,a( n1 ), n ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_${ri}$trtri( 'L', diag, n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'L', 'L', 'T', diag, n1, n2, -one, a( n2 ),n, a( 0_${ik}$ ), n ) call stdlib${ii}$_${ri}$trtri( 'U', diag, n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'R', 'U', 'N', diag, n1, n2, one, a( n1 ),n, a( 0_${ik}$ ), n ) end if else ! n is odd and transr = 't' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_${ri}$trtri( 'U', diag, n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'L', 'U', 'N', diag, n1, n2, -one, a( 0_${ik}$ ),n1, a( n1*n1 ), & n1 ) call stdlib${ii}$_${ri}$trtri( 'L', diag, n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'R', 'L', 'T', diag, n1, n2, one, a( 1_${ik}$ ),n1, a( n1*n1 ), & n1 ) else ! srpa for upper, transpose and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_${ri}$trtri( 'U', diag, n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'R', 'U', 'T', diag, n2, n1, -one,a( n2*n2 ), n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_${ri}$trtri( 'L', diag, n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'L', 'L', 'N', diag, n2, n1, one,a( n1*n2 ), n2, a( 0_${ik}$ ), & n2 ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_${ri}$trtri( 'L', diag, k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'R', 'L', 'N', diag, k, k, -one, a( 1_${ik}$ ),n+1, a( k+1 ), n+1 & ) call stdlib${ii}$_${ri}$trtri( 'U', diag, k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'L', 'U', 'T', diag, k, k, one, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_${ri}$trtri( 'L', diag, k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'L', 'L', 'T', diag, k, k, -one, a( k+1 ),n+1, a( 0_${ik}$ ), n+1 & ) call stdlib${ii}$_${ri}$trtri( 'U', diag, k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'R', 'U', 'N', diag, k, k, one, a( k ), n+1,a( 0_${ik}$ ), n+1 ) end if else ! n is even and transr = 't' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_${ri}$trtri( 'U', diag, k, a( k ), k, info ) if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'L', 'U', 'N', diag, k, k, -one, a( k ), k,a( k*( k+1 ) ), & k ) call stdlib${ii}$_${ri}$trtri( 'L', diag, k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'R', 'L', 'T', diag, k, k, one, a( 0_${ik}$ ), k,a( k*( k+1 ) ), & k ) else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_${ri}$trtri( 'U', diag, k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'R', 'U', 'T', diag, k, k, -one,a( k*( k+1 ) ), k, a( 0_${ik}$ ), & k ) call stdlib${ii}$_${ri}$trtri( 'L', diag, k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_${ri}$trmm( 'L', 'L', 'N', diag, k, k, one, a( k*k ), k,a( 0_${ik}$ ), k ) end if end if end if return end subroutine stdlib${ii}$_${ri}$tftri #:endif #:endfor pure module subroutine stdlib${ii}$_ctftri( transr, uplo, diag, n, a, info ) !! CTFTRI computes the inverse of a triangular matrix A stored in RFP !! format. !! This is a Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo, diag integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments complex(sp), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'C' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( .not.stdlib_lsame( diag, 'N' ) .and. .not.stdlib_lsame( diag, 'U' ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CTFTRI', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_ctrtri( 'L', diag, n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_ctrmm( 'R', 'L', 'N', diag, n2, n1, -cone, a( 0_${ik}$ ),n, a( n1 ), n ) call stdlib${ii}$_ctrtri( 'U', diag, n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_ctrmm( 'L', 'U', 'C', diag, n2, n1, cone, a( n ), n,a( n1 ), n ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_ctrtri( 'L', diag, n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_ctrmm( 'L', 'L', 'C', diag, n1, n2, -cone, a( n2 ),n, a( 0_${ik}$ ), n ) call stdlib${ii}$_ctrtri( 'U', diag, n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_ctrmm( 'R', 'U', 'N', diag, n1, n2, cone, a( n1 ),n, a( 0_${ik}$ ), n ) end if else ! n is odd and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_ctrtri( 'U', diag, n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_ctrmm( 'L', 'U', 'N', diag, n1, n2, -cone, a( 0_${ik}$ ),n1, a( n1*n1 ), & n1 ) call stdlib${ii}$_ctrtri( 'L', diag, n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_ctrmm( 'R', 'L', 'C', diag, n1, n2, cone, a( 1_${ik}$ ),n1, a( n1*n1 ), & n1 ) else ! srpa for upper, transpose and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_ctrtri( 'U', diag, n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_ctrmm( 'R', 'U', 'C', diag, n2, n1, -cone,a( n2*n2 ), n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_ctrtri( 'L', diag, n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_ctrmm( 'L', 'L', 'N', diag, n2, n1, cone,a( n1*n2 ), n2, a( 0_${ik}$ ), & n2 ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_ctrtri( 'L', diag, k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_ctrmm( 'R', 'L', 'N', diag, k, k, -cone, a( 1_${ik}$ ),n+1, a( k+1 ), n+& 1_${ik}$ ) call stdlib${ii}$_ctrtri( 'U', diag, k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_ctrmm( 'L', 'U', 'C', diag, k, k, cone, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 & ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_ctrtri( 'L', diag, k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_ctrmm( 'L', 'L', 'C', diag, k, k, -cone, a( k+1 ),n+1, a( 0_${ik}$ ), n+& 1_${ik}$ ) call stdlib${ii}$_ctrtri( 'U', diag, k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_ctrmm( 'R', 'U', 'N', diag, k, k, cone, a( k ), n+1,a( 0_${ik}$ ), n+1 ) end if else ! n is even and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_ctrtri( 'U', diag, k, a( k ), k, info ) if( info>0 )return call stdlib${ii}$_ctrmm( 'L', 'U', 'N', diag, k, k, -cone, a( k ), k,a( k*( k+1 ) ),& k ) call stdlib${ii}$_ctrtri( 'L', diag, k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_ctrmm( 'R', 'L', 'C', diag, k, k, cone, a( 0_${ik}$ ), k,a( k*( k+1 ) ), & k ) else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_ctrtri( 'U', diag, k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_ctrmm( 'R', 'U', 'C', diag, k, k, -cone,a( k*( k+1 ) ), k, a( 0_${ik}$ ),& k ) call stdlib${ii}$_ctrtri( 'L', diag, k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_ctrmm( 'L', 'L', 'N', diag, k, k, cone, a( k*k ), k,a( 0_${ik}$ ), k ) end if end if end if return end subroutine stdlib${ii}$_ctftri pure module subroutine stdlib${ii}$_ztftri( transr, uplo, diag, n, a, info ) !! ZTFTRI computes the inverse of a triangular matrix A stored in RFP !! format. !! This is a Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo, diag integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments complex(dp), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'C' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( .not.stdlib_lsame( diag, 'N' ) .and. .not.stdlib_lsame( diag, 'U' ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZTFTRI', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_ztrtri( 'L', diag, n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_ztrmm( 'R', 'L', 'N', diag, n2, n1, -cone, a( 0_${ik}$ ),n, a( n1 ), n ) call stdlib${ii}$_ztrtri( 'U', diag, n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_ztrmm( 'L', 'U', 'C', diag, n2, n1, cone, a( n ), n,a( n1 ), n ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_ztrtri( 'L', diag, n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_ztrmm( 'L', 'L', 'C', diag, n1, n2, -cone, a( n2 ),n, a( 0_${ik}$ ), n ) call stdlib${ii}$_ztrtri( 'U', diag, n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_ztrmm( 'R', 'U', 'N', diag, n1, n2, cone, a( n1 ),n, a( 0_${ik}$ ), n ) end if else ! n is odd and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_ztrtri( 'U', diag, n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_ztrmm( 'L', 'U', 'N', diag, n1, n2, -cone, a( 0_${ik}$ ),n1, a( n1*n1 ), & n1 ) call stdlib${ii}$_ztrtri( 'L', diag, n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_ztrmm( 'R', 'L', 'C', diag, n1, n2, cone, a( 1_${ik}$ ),n1, a( n1*n1 ), & n1 ) else ! srpa for upper, transpose and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_ztrtri( 'U', diag, n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_ztrmm( 'R', 'U', 'C', diag, n2, n1, -cone,a( n2*n2 ), n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_ztrtri( 'L', diag, n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_ztrmm( 'L', 'L', 'N', diag, n2, n1, cone,a( n1*n2 ), n2, a( 0_${ik}$ ), & n2 ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_ztrtri( 'L', diag, k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_ztrmm( 'R', 'L', 'N', diag, k, k, -cone, a( 1_${ik}$ ),n+1, a( k+1 ), n+& 1_${ik}$ ) call stdlib${ii}$_ztrtri( 'U', diag, k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_ztrmm( 'L', 'U', 'C', diag, k, k, cone, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 & ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_ztrtri( 'L', diag, k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_ztrmm( 'L', 'L', 'C', diag, k, k, -cone, a( k+1 ),n+1, a( 0_${ik}$ ), n+& 1_${ik}$ ) call stdlib${ii}$_ztrtri( 'U', diag, k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_ztrmm( 'R', 'U', 'N', diag, k, k, cone, a( k ), n+1,a( 0_${ik}$ ), n+1 ) end if else ! n is even and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_ztrtri( 'U', diag, k, a( k ), k, info ) if( info>0 )return call stdlib${ii}$_ztrmm( 'L', 'U', 'N', diag, k, k, -cone, a( k ), k,a( k*( k+1 ) ),& k ) call stdlib${ii}$_ztrtri( 'L', diag, k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_ztrmm( 'R', 'L', 'C', diag, k, k, cone, a( 0_${ik}$ ), k,a( k*( k+1 ) ), & k ) else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_ztrtri( 'U', diag, k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_ztrmm( 'R', 'U', 'C', diag, k, k, -cone,a( k*( k+1 ) ), k, a( 0_${ik}$ ),& k ) call stdlib${ii}$_ztrtri( 'L', diag, k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_ztrmm( 'L', 'L', 'N', diag, k, k, cone, a( k*k ), k,a( 0_${ik}$ ), k ) end if end if end if return end subroutine stdlib${ii}$_ztftri #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tftri( transr, uplo, diag, n, a, info ) !! ZTFTRI: computes the inverse of a triangular matrix A stored in RFP !! format. !! This is a Level 3 BLAS version of the algorithm. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo, diag integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments complex(${ck}$), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'C' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( .not.stdlib_lsame( diag, 'N' ) .and. .not.stdlib_lsame( diag, 'U' ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZTFTRI', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_${ci}$trtri( 'L', diag, n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'R', 'L', 'N', diag, n2, n1, -cone, a( 0_${ik}$ ),n, a( n1 ), n ) call stdlib${ii}$_${ci}$trtri( 'U', diag, n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'L', 'U', 'C', diag, n2, n1, cone, a( n ), n,a( n1 ), n ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_${ci}$trtri( 'L', diag, n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'L', 'L', 'C', diag, n1, n2, -cone, a( n2 ),n, a( 0_${ik}$ ), n ) call stdlib${ii}$_${ci}$trtri( 'U', diag, n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'R', 'U', 'N', diag, n1, n2, cone, a( n1 ),n, a( 0_${ik}$ ), n ) end if else ! n is odd and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_${ci}$trtri( 'U', diag, n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'L', 'U', 'N', diag, n1, n2, -cone, a( 0_${ik}$ ),n1, a( n1*n1 ), & n1 ) call stdlib${ii}$_${ci}$trtri( 'L', diag, n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'R', 'L', 'C', diag, n1, n2, cone, a( 1_${ik}$ ),n1, a( n1*n1 ), & n1 ) else ! srpa for upper, transpose and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_${ci}$trtri( 'U', diag, n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'R', 'U', 'C', diag, n2, n1, -cone,a( n2*n2 ), n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_${ci}$trtri( 'L', diag, n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'L', 'L', 'N', diag, n2, n1, cone,a( n1*n2 ), n2, a( 0_${ik}$ ), & n2 ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_${ci}$trtri( 'L', diag, k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'R', 'L', 'N', diag, k, k, -cone, a( 1_${ik}$ ),n+1, a( k+1 ), n+& 1_${ik}$ ) call stdlib${ii}$_${ci}$trtri( 'U', diag, k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'L', 'U', 'C', diag, k, k, cone, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 & ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_${ci}$trtri( 'L', diag, k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'L', 'L', 'C', diag, k, k, -cone, a( k+1 ),n+1, a( 0_${ik}$ ), n+& 1_${ik}$ ) call stdlib${ii}$_${ci}$trtri( 'U', diag, k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'R', 'U', 'N', diag, k, k, cone, a( k ), n+1,a( 0_${ik}$ ), n+1 ) end if else ! n is even and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_${ci}$trtri( 'U', diag, k, a( k ), k, info ) if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'L', 'U', 'N', diag, k, k, -cone, a( k ), k,a( k*( k+1 ) ),& k ) call stdlib${ii}$_${ci}$trtri( 'L', diag, k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'R', 'L', 'C', diag, k, k, cone, a( 0_${ik}$ ), k,a( k*( k+1 ) ), & k ) else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_${ci}$trtri( 'U', diag, k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'R', 'U', 'C', diag, k, k, -cone,a( k*( k+1 ) ), k, a( 0_${ik}$ ),& k ) call stdlib${ii}$_${ci}$trtri( 'L', diag, k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k if( info>0 )return call stdlib${ii}$_${ci}$trmm( 'L', 'L', 'N', diag, k, k, cone, a( k*k ), k,a( 0_${ik}$ ), k ) end if end if end if return end subroutine stdlib${ii}$_${ci}$tftri #:endif #:endfor module subroutine stdlib${ii}$_stbcon( norm, uplo, diag, n, kd, ab, ldab, rcond, work,iwork, info ) !! STBCON estimates the reciprocal of the condition number of a !! triangular band matrix A, in either the 1-norm or the infinity-norm. !! The norm of A is computed and an estimate is obtained for !! norm(inv(A)), then the reciprocal of the condition number is !! computed as !! RCOND = 1 / ( norm(A) * norm(inv(A)) ). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, norm, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: ab(ldab,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: nounit, onenrm, upper character :: normin integer(${ik}$) :: ix, kase, kase1 real(sp) :: ainvnm, anorm, scale, smlnum, xnorm ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) onenrm = norm=='1' .or. stdlib_lsame( norm, 'O' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.onenrm .and. .not.stdlib_lsame( norm, 'I' ) ) then info = -1_${ik}$ else if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( ldab 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_slacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_slatbs( uplo, 'NO TRANSPOSE', diag, normin, n, kd,ab, ldab, work, & scale, work( 2_${ik}$*n+1 ), info ) else ! multiply by inv(a**t). call stdlib${ii}$_slatbs( uplo, 'TRANSPOSE', diag, normin, n, kd, ab,ldab, work, & scale, work( 2_${ik}$*n+1 ), info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_isamax( n, work, 1_${ik}$ ) xnorm = abs( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_dlacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_dlatbs( uplo, 'NO TRANSPOSE', diag, normin, n, kd,ab, ldab, work, & scale, work( 2_${ik}$*n+1 ), info ) else ! multiply by inv(a**t). call stdlib${ii}$_dlatbs( uplo, 'TRANSPOSE', diag, normin, n, kd, ab,ldab, work, & scale, work( 2_${ik}$*n+1 ), info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_idamax( n, work, 1_${ik}$ ) xnorm = abs( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_${ri}$lacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_${ri}$latbs( uplo, 'NO TRANSPOSE', diag, normin, n, kd,ab, ldab, work, & scale, work( 2_${ik}$*n+1 ), info ) else ! multiply by inv(a**t). call stdlib${ii}$_${ri}$latbs( uplo, 'TRANSPOSE', diag, normin, n, kd, ab,ldab, work, & scale, work( 2_${ik}$*n+1 ), info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ ) xnorm = abs( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the 1-norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_clatbs( uplo, 'NO TRANSPOSE', diag, normin, n, kd,ab, ldab, work, & scale, rwork, info ) else ! multiply by inv(a**h). call stdlib${ii}$_clatbs( uplo, 'CONJUGATE TRANSPOSE', diag, normin,n, kd, ab, ldab,& work, scale, rwork, info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_icamax( n, work, 1_${ik}$ ) xnorm = cabs1( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the 1-norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_zlatbs( uplo, 'NO TRANSPOSE', diag, normin, n, kd,ab, ldab, work, & scale, rwork, info ) else ! multiply by inv(a**h). call stdlib${ii}$_zlatbs( uplo, 'CONJUGATE TRANSPOSE', diag, normin,n, kd, ab, ldab,& work, scale, rwork, info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_izamax( n, work, 1_${ik}$ ) xnorm = cabs1( work( ix ) ) if( scale 0. if( anorm>zero ) then ! estimate the 1-norm of the inverse of a. ainvnm = zero normin = 'N' if( onenrm ) then kase1 = 1_${ik}$ else kase1 = 2_${ik}$ end if kase = 0_${ik}$ 10 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==kase1 ) then ! multiply by inv(a). call stdlib${ii}$_${ci}$latbs( uplo, 'NO TRANSPOSE', diag, normin, n, kd,ab, ldab, work, & scale, rwork, info ) else ! multiply by inv(a**h). call stdlib${ii}$_${ci}$latbs( uplo, 'CONJUGATE TRANSPOSE', diag, normin,n, kd, ab, ldab,& work, scale, rwork, info ) end if normin = 'Y' ! multiply by 1/scale if doing so will not cause overflow. if( scale/=one ) then ix = stdlib${ii}$_i${ci}$amax( n, work, 1_${ik}$ ) xnorm = cabs1( work( ix ) ) if( scale0_${ik}$ ) then cnorm( j ) = stdlib${ii}$_sasum( jlen, ab( 2_${ik}$, j ), 1_${ik}$ ) else cnorm( j ) = zero end if end do end if end if ! scale the column norms by tscal if the maximum element in cnorm is ! greater than bignum. imax = stdlib${ii}$_isamax( n, cnorm, 1_${ik}$ ) tmax = cnorm( imax ) if( tmax<=bignum ) then tscal = one else tscal = one / ( smlnum*tmax ) call stdlib${ii}$_sscal( n, tscal, cnorm, 1_${ik}$ ) end if ! compute a bound on the computed solution vector to see if the ! level 2 blas routine stdlib${ii}$_stbsv can be used. j = stdlib${ii}$_isamax( n, x, 1_${ik}$ ) xmax = abs( x( j ) ) xbnd = xmax if( notran ) then ! compute the growth in a * x = b. if( upper ) then jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = kd + 1_${ik}$ else jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 50 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, g(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! m(j) = g(j-1) / abs(a(j,j)) tjj = abs( ab( maind, j ) ) xbnd = min( xbnd, min( one, tjj )*grow ) if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 50 continue else ! compute the growth in a**t * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = kd + 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 80 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) tjj = abs( ab( maind, j ) ) if( xj>tjj )xbnd = xbnd*( tjj / xj ) end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 80 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_stbsv( uplo, trans, diag, n, kd, ab, ldab, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = bignum / xmax call stdlib${ii}$_sscal( n, scale, x, 1_${ik}$ ) xmax = bignum end if if( notran ) then ! solve a * x = b loop_100: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = abs( x( j ) ) if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 95 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 95 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_sscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(max(1,j-kd):j-1) := x(max(1,j-kd):j-1) - ! x(j)* a(max(1,j-kd):j-1,j) jlen = min( kd, j-1 ) call stdlib${ii}$_saxpy( jlen, -x( j )*tscal,ab( kd+1-jlen, j ), 1_${ik}$, x( j-jlen & ), 1_${ik}$ ) i = stdlib${ii}$_isamax( j-1, x, 1_${ik}$ ) xmax = abs( x( i ) ) end if else if( j0_${ik}$ )call stdlib${ii}$_saxpy( jlen, -x( j )*tscal, ab( 2_${ik}$, j ), 1_${ik}$,x( j+1 ),& 1_${ik}$ ) i = j + stdlib${ii}$_isamax( n-j, x( j+1 ), 1_${ik}$ ) xmax = abs( x( i ) ) end if end do loop_100 else ! solve a**t * x = b loop_140: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = abs( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal end if tjj = abs( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = uscal / tjjs end if if( rec0_${ik}$ )sumj = stdlib${ii}$_sdot( jlen, ab( 2_${ik}$, j ), 1_${ik}$, x( j+1 ), 1_${ik}$ ) end if else ! otherwise, use in-line code for the dot product. if( upper ) then jlen = min( kd, j-1 ) do i = 1, jlen sumj = sumj + ( ab( kd+i-jlen, j )*uscal )*x( j-jlen-1+i ) end do else jlen = min( kd, n-j ) do i = 1, jlen sumj = sumj + ( ab( i+1, j )*uscal )*x( j+i ) end do end if end if if( uscal==tscal ) then ! compute x(j) := ( x(j) - sumj ) / a(j,j) if 1/a(j,j) ! was not used to scale the dotproduct. x( j ) = x( j ) - sumj xj = abs( x( j ) ) if( nounit ) then ! compute x(j) = x(j) / a(j,j), scaling if necessary. tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 135 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_sscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a**t*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 135 continue else ! compute x(j) := x(j) / a(j,j) - sumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = x( j ) / tjjs - sumj end if xmax = max( xmax, abs( x( j ) ) ) end do loop_140 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_sscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_slatbs pure module subroutine stdlib${ii}$_dlatbs( uplo, trans, diag, normin, n, kd, ab, ldab, x,scale, cnorm, & !! DLATBS solves one of the triangular systems !! A *x = s*b or A**T*x = s*b !! with scaling to prevent overflow, where A is an upper or lower !! triangular band matrix. Here A**T denotes the transpose of A, x and b !! are n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine DTBSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n real(dp), intent(out) :: scale ! Array Arguments real(dp), intent(in) :: ab(ldab,*) real(dp), intent(inout) :: cnorm(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, j, jfirst, jinc, jlast, jlen, maind real(dp) :: bignum, grow, rec, smlnum, sumj, tjj, tjjs, tmax, tscal, uscal, xbnd, xj, & xmax ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( kd<0_${ik}$ ) then info = -6_${ik}$ else if( ldab0_${ik}$ ) then cnorm( j ) = stdlib${ii}$_dasum( jlen, ab( 2_${ik}$, j ), 1_${ik}$ ) else cnorm( j ) = zero end if end do end if end if ! scale the column norms by tscal if the maximum element in cnorm is ! greater than bignum. imax = stdlib${ii}$_idamax( n, cnorm, 1_${ik}$ ) tmax = cnorm( imax ) if( tmax<=bignum ) then tscal = one else tscal = one / ( smlnum*tmax ) call stdlib${ii}$_dscal( n, tscal, cnorm, 1_${ik}$ ) end if ! compute a bound on the computed solution vector to see if the ! level 2 blas routine stdlib${ii}$_dtbsv can be used. j = stdlib${ii}$_idamax( n, x, 1_${ik}$ ) xmax = abs( x( j ) ) xbnd = xmax if( notran ) then ! compute the growth in a * x = b. if( upper ) then jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = kd + 1_${ik}$ else jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 50 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, g(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! m(j) = g(j-1) / abs(a(j,j)) tjj = abs( ab( maind, j ) ) xbnd = min( xbnd, min( one, tjj )*grow ) if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 50 continue else ! compute the growth in a**t * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = kd + 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 80 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) tjj = abs( ab( maind, j ) ) if( xj>tjj )xbnd = xbnd*( tjj / xj ) end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 80 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_dtbsv( uplo, trans, diag, n, kd, ab, ldab, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = bignum / xmax call stdlib${ii}$_dscal( n, scale, x, 1_${ik}$ ) xmax = bignum end if if( notran ) then ! solve a * x = b loop_110: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = abs( x( j ) ) if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 100 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 100 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_dscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(max(1,j-kd):j-1) := x(max(1,j-kd):j-1) - ! x(j)* a(max(1,j-kd):j-1,j) jlen = min( kd, j-1 ) call stdlib${ii}$_daxpy( jlen, -x( j )*tscal,ab( kd+1-jlen, j ), 1_${ik}$, x( j-jlen & ), 1_${ik}$ ) i = stdlib${ii}$_idamax( j-1, x, 1_${ik}$ ) xmax = abs( x( i ) ) end if else if( j0_${ik}$ )call stdlib${ii}$_daxpy( jlen, -x( j )*tscal, ab( 2_${ik}$, j ), 1_${ik}$,x( j+1 ),& 1_${ik}$ ) i = j + stdlib${ii}$_idamax( n-j, x( j+1 ), 1_${ik}$ ) xmax = abs( x( i ) ) end if end do loop_110 else ! solve a**t * x = b loop_160: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = abs( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal end if tjj = abs( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = uscal / tjjs end if if( rec0_${ik}$ )sumj = stdlib${ii}$_ddot( jlen, ab( 2_${ik}$, j ), 1_${ik}$, x( j+1 ), 1_${ik}$ ) end if else ! otherwise, use in-line code for the dot product. if( upper ) then jlen = min( kd, j-1 ) do i = 1, jlen sumj = sumj + ( ab( kd+i-jlen, j )*uscal )*x( j-jlen-1+i ) end do else jlen = min( kd, n-j ) do i = 1, jlen sumj = sumj + ( ab( i+1, j )*uscal )*x( j+i ) end do end if end if if( uscal==tscal ) then ! compute x(j) := ( x(j) - sumj ) / a(j,j) if 1/a(j,j) ! was not used to scale the dotproduct. x( j ) = x( j ) - sumj xj = abs( x( j ) ) if( nounit ) then ! compute x(j) = x(j) / a(j,j), scaling if necessary. tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 150 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a**t*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 150 continue else ! compute x(j) := x(j) / a(j,j) - sumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = x( j ) / tjjs - sumj end if xmax = max( xmax, abs( x( j ) ) ) end do loop_160 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_dscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_dlatbs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$latbs( uplo, trans, diag, normin, n, kd, ab, ldab, x,scale, cnorm, & !! DLATBS: solves one of the triangular systems !! A *x = s*b or A**T*x = s*b !! with scaling to prevent overflow, where A is an upper or lower !! triangular band matrix. Here A**T denotes the transpose of A, x and b !! are n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine DTBSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n real(${rk}$), intent(out) :: scale ! Array Arguments real(${rk}$), intent(in) :: ab(ldab,*) real(${rk}$), intent(inout) :: cnorm(*), x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, j, jfirst, jinc, jlast, jlen, maind real(${rk}$) :: bignum, grow, rec, smlnum, sumj, tjj, tjjs, tmax, tscal, uscal, xbnd, xj, & xmax ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( kd<0_${ik}$ ) then info = -6_${ik}$ else if( ldab0_${ik}$ ) then cnorm( j ) = stdlib${ii}$_${ri}$asum( jlen, ab( 2_${ik}$, j ), 1_${ik}$ ) else cnorm( j ) = zero end if end do end if end if ! scale the column norms by tscal if the maximum element in cnorm is ! greater than bignum. imax = stdlib${ii}$_i${ri}$amax( n, cnorm, 1_${ik}$ ) tmax = cnorm( imax ) if( tmax<=bignum ) then tscal = one else tscal = one / ( smlnum*tmax ) call stdlib${ii}$_${ri}$scal( n, tscal, cnorm, 1_${ik}$ ) end if ! compute a bound on the computed solution vector to see if the ! level 2 blas routine stdlib${ii}$_${ri}$tbsv can be used. j = stdlib${ii}$_i${ri}$amax( n, x, 1_${ik}$ ) xmax = abs( x( j ) ) xbnd = xmax if( notran ) then ! compute the growth in a * x = b. if( upper ) then jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = kd + 1_${ik}$ else jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 50 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, g(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! m(j) = g(j-1) / abs(a(j,j)) tjj = abs( ab( maind, j ) ) xbnd = min( xbnd, min( one, tjj )*grow ) if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 50 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 50 continue else ! compute the growth in a**t * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = kd + 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 80 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = one / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) tjj = abs( ab( maind, j ) ) if( xj>tjj )xbnd = xbnd*( tjj / xj ) end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, one / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 80 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 80 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_${ri}$tbsv( uplo, trans, diag, n, kd, ab, ldab, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = bignum / xmax call stdlib${ii}$_${ri}$scal( n, scale, x, 1_${ik}$ ) xmax = bignum end if if( notran ) then ! solve a * x = b loop_110: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = abs( x( j ) ) if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 100 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs xj = abs( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 100 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_${ri}$scal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(max(1,j-kd):j-1) := x(max(1,j-kd):j-1) - ! x(j)* a(max(1,j-kd):j-1,j) jlen = min( kd, j-1 ) call stdlib${ii}$_${ri}$axpy( jlen, -x( j )*tscal,ab( kd+1-jlen, j ), 1_${ik}$, x( j-jlen & ), 1_${ik}$ ) i = stdlib${ii}$_i${ri}$amax( j-1, x, 1_${ik}$ ) xmax = abs( x( i ) ) end if else if( j0_${ik}$ )call stdlib${ii}$_${ri}$axpy( jlen, -x( j )*tscal, ab( 2_${ik}$, j ), 1_${ik}$,x( j+1 ),& 1_${ik}$ ) i = j + stdlib${ii}$_i${ri}$amax( n-j, x( j+1 ), 1_${ik}$ ) xmax = abs( x( i ) ) end if end do loop_110 else ! solve a**t * x = b loop_160: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = abs( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal end if tjj = abs( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = uscal / tjjs end if if( rec0_${ik}$ )sumj = stdlib${ii}$_${ri}$dot( jlen, ab( 2_${ik}$, j ), 1_${ik}$, x( j+1 ), 1_${ik}$ ) end if else ! otherwise, use in-line code for the dot product. if( upper ) then jlen = min( kd, j-1 ) do i = 1, jlen sumj = sumj + ( ab( kd+i-jlen, j )*uscal )*x( j-jlen-1+i ) end do else jlen = min( kd, n-j ) do i = 1, jlen sumj = sumj + ( ab( i+1, j )*uscal )*x( j+i ) end do end if end if if( uscal==tscal ) then ! compute x(j) := ( x(j) - sumj ) / a(j,j) if 1/a(j,j) ! was not used to scale the dotproduct. x( j ) = x( j ) - sumj xj = abs( x( j ) ) if( nounit ) then ! compute x(j) = x(j) / a(j,j), scaling if necessary. tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 150 end if tjj = abs( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = x( j ) / tjjs else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_${ri}$scal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = x( j ) / tjjs else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a**t*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 150 continue else ! compute x(j) := x(j) / a(j,j) - sumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = x( j ) / tjjs - sumj end if xmax = max( xmax, abs( x( j ) ) ) end do loop_160 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_${ri}$scal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ri}$latbs #:endif #:endfor pure module subroutine stdlib${ii}$_clatbs( uplo, trans, diag, normin, n, kd, ab, ldab, x,scale, cnorm, & !! CLATBS solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow, where A is an upper or lower !! triangular band matrix. Here A**T denotes the transpose of A, x and b !! are n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine CTBSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n real(sp), intent(out) :: scale ! Array Arguments real(sp), intent(inout) :: cnorm(*) complex(sp), intent(in) :: ab(ldab,*) complex(sp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, j, jfirst, jinc, jlast, jlen, maind real(sp) :: bignum, grow, rec, smlnum, tjj, tmax, tscal, xbnd, xj, xmax complex(sp) :: csumj, tjjs, uscal, zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1, cabs2 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) cabs2( zdum ) = abs( real( zdum,KIND=sp) / 2. ) +abs( aimag( zdum ) / 2. ) ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( kd<0_${ik}$ ) then info = -6_${ik}$ else if( ldab0_${ik}$ ) then cnorm( j ) = stdlib${ii}$_scasum( jlen, ab( 2_${ik}$, j ), 1_${ik}$ ) else cnorm( j ) = zero end if end do end if end if ! scale the column norms by tscal if the maximum element in cnorm is ! greater than bignum/2. imax = stdlib${ii}$_isamax( n, cnorm, 1_${ik}$ ) tmax = cnorm( imax ) if( tmax<=bignum*half ) then tscal = one else tscal = half / ( smlnum*tmax ) call stdlib${ii}$_sscal( n, tscal, cnorm, 1_${ik}$ ) end if ! compute a bound on the computed solution vector to see if the ! level 2 blas routine stdlib${ii}$_ctbsv can be used. xmax = zero do j = 1, n xmax = max( xmax, cabs2( x( j ) ) ) end do xbnd = xmax if( notran ) then ! compute the growth in a * x = b. if( upper ) then jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = kd + 1_${ik}$ else jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 60 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, g(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 tjjs = ab( maind, j ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = g(j-1) / abs(a(j,j)) xbnd = min( xbnd, min( one, tjj )*grow ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 60 continue else ! compute the growth in a**t * x = b or a**h * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = kd + 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 90 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) tjjs = ab( maind, j ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) if( xj>tjj )xbnd = xbnd*( tjj / xj ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 90 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_ctbsv( uplo, trans, diag, n, kd, ab, ldab, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum*half ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = ( bignum*half ) / xmax call stdlib${ii}$_csscal( n, scale, x, 1_${ik}$ ) xmax = bignum else xmax = xmax*two end if if( notran ) then ! solve a * x = b loop_110: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = cabs1( x( j ) ) if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 105 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 105 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_csscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(max(1,j-kd):j-1) := x(max(1,j-kd):j-1) - ! x(j)* a(max(1,j-kd):j-1,j) jlen = min( kd, j-1 ) call stdlib${ii}$_caxpy( jlen, -x( j )*tscal,ab( kd+1-jlen, j ), 1_${ik}$, x( j-jlen & ), 1_${ik}$ ) i = stdlib${ii}$_icamax( j-1, x, 1_${ik}$ ) xmax = cabs1( x( i ) ) end if else if( j0_${ik}$ )call stdlib${ii}$_caxpy( jlen, -x( j )*tscal, ab( 2_${ik}$, j ), 1_${ik}$,x( j+1 ),& 1_${ik}$ ) i = j + stdlib${ii}$_icamax( n-j, x( j+1 ), 1_${ik}$ ) xmax = cabs1( x( i ) ) end if end do loop_110 else if( stdlib_lsame( trans, 'T' ) ) then ! solve a**t * x = b loop_150: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_cladiv( uscal, tjjs ) end if if( rec1_${ik}$ )csumj = stdlib${ii}$_cdotu( jlen, ab( 2_${ik}$, j ), 1_${ik}$, x( j+1 ),1_${ik}$ ) end if else ! otherwise, use in-line code for the dot product. if( upper ) then jlen = min( kd, j-1 ) do i = 1, jlen csumj = csumj + ( ab( kd+i-jlen, j )*uscal )*x( j-jlen-1+i ) end do else jlen = min( kd, n-j ) do i = 1, jlen csumj = csumj + ( ab( i+1, j )*uscal )*x( j+i ) end do end if end if if( uscal==cmplx( tscal,KIND=sp) ) then ! compute x(j) := ( x(j) - csumj ) / a(j,j) if 1/a(j,j) ! was not used to scale the dotproduct. x( j ) = x( j ) - csumj xj = cabs1( x( j ) ) if( nounit ) then ! compute x(j) = x(j) / a(j,j), scaling if necessary. tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 145 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**t *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 145 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_150 else ! solve a**h * x = b loop_190: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = conjg( ab( maind, j ) )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_cladiv( uscal, tjjs ) end if if( rec1_${ik}$ )csumj = stdlib${ii}$_cdotc( jlen, ab( 2_${ik}$, j ), 1_${ik}$, x( j+1 ),1_${ik}$ ) end if else ! otherwise, use in-line code for the dot product. if( upper ) then jlen = min( kd, j-1 ) do i = 1, jlen csumj = csumj + ( conjg( ab( kd+i-jlen, j ) )*uscal )*x( j-jlen-1+i ) end do else jlen = min( kd, n-j ) do i = 1, jlen csumj = csumj + ( conjg( ab( i+1, j ) )*uscal )*x( j+i ) end do end if end if if( uscal==cmplx( tscal,KIND=sp) ) then ! compute x(j) := ( x(j) - csumj ) / a(j,j) if 1/a(j,j) ! was not used to scale the dotproduct. x( j ) = x( j ) - csumj xj = cabs1( x( j ) ) if( nounit ) then ! compute x(j) = x(j) / a(j,j), scaling if necessary. tjjs = conjg( ab( maind, j ) )*tscal else tjjs = tscal if( tscal==one )go to 185 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_csscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**h *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 185 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_cladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_190 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_sscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_clatbs pure module subroutine stdlib${ii}$_zlatbs( uplo, trans, diag, normin, n, kd, ab, ldab, x,scale, cnorm, & !! ZLATBS solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow, where A is an upper or lower !! triangular band matrix. Here A**T denotes the transpose of A, x and b !! are n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine ZTBSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n real(dp), intent(out) :: scale ! Array Arguments real(dp), intent(inout) :: cnorm(*) complex(dp), intent(in) :: ab(ldab,*) complex(dp), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, j, jfirst, jinc, jlast, jlen, maind real(dp) :: bignum, grow, rec, smlnum, tjj, tmax, tscal, xbnd, xj, xmax complex(dp) :: csumj, tjjs, uscal, zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1, cabs2 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) cabs2( zdum ) = abs( real( zdum,KIND=dp) / 2._dp ) +abs( aimag( zdum ) / 2._dp ) ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( kd<0_${ik}$ ) then info = -6_${ik}$ else if( ldab0_${ik}$ ) then cnorm( j ) = stdlib${ii}$_dzasum( jlen, ab( 2_${ik}$, j ), 1_${ik}$ ) else cnorm( j ) = zero end if end do end if end if ! scale the column norms by tscal if the maximum element in cnorm is ! greater than bignum/2. imax = stdlib${ii}$_idamax( n, cnorm, 1_${ik}$ ) tmax = cnorm( imax ) if( tmax<=bignum*half ) then tscal = one else tscal = half / ( smlnum*tmax ) call stdlib${ii}$_dscal( n, tscal, cnorm, 1_${ik}$ ) end if ! compute a bound on the computed solution vector to see if the ! level 2 blas routine stdlib${ii}$_ztbsv can be used. xmax = zero do j = 1, n xmax = max( xmax, cabs2( x( j ) ) ) end do xbnd = xmax if( notran ) then ! compute the growth in a * x = b. if( upper ) then jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = kd + 1_${ik}$ else jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 60 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, g(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 tjjs = ab( maind, j ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = g(j-1) / abs(a(j,j)) xbnd = min( xbnd, min( one, tjj )*grow ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 60 continue else ! compute the growth in a**t * x = b or a**h * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = kd + 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 90 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) tjjs = ab( maind, j ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) if( xj>tjj )xbnd = xbnd*( tjj / xj ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 90 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_ztbsv( uplo, trans, diag, n, kd, ab, ldab, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum*half ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = ( bignum*half ) / xmax call stdlib${ii}$_zdscal( n, scale, x, 1_${ik}$ ) xmax = bignum else xmax = xmax*two end if if( notran ) then ! solve a * x = b loop_120: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = cabs1( x( j ) ) if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 110 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 110 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_zdscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(max(1,j-kd):j-1) := x(max(1,j-kd):j-1) - ! x(j)* a(max(1,j-kd):j-1,j) jlen = min( kd, j-1 ) call stdlib${ii}$_zaxpy( jlen, -x( j )*tscal,ab( kd+1-jlen, j ), 1_${ik}$, x( j-jlen & ), 1_${ik}$ ) i = stdlib${ii}$_izamax( j-1, x, 1_${ik}$ ) xmax = cabs1( x( i ) ) end if else if( j0_${ik}$ )call stdlib${ii}$_zaxpy( jlen, -x( j )*tscal, ab( 2_${ik}$, j ), 1_${ik}$,x( j+1 ),& 1_${ik}$ ) i = j + stdlib${ii}$_izamax( n-j, x( j+1 ), 1_${ik}$ ) xmax = cabs1( x( i ) ) end if end do loop_120 else if( stdlib_lsame( trans, 'T' ) ) then ! solve a**t * x = b loop_170: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_zladiv( uscal, tjjs ) end if if( rec1_${ik}$ )csumj = stdlib${ii}$_zdotu( jlen, ab( 2_${ik}$, j ), 1_${ik}$, x( j+1 ),1_${ik}$ ) end if else ! otherwise, use in-line code for the dot product. if( upper ) then jlen = min( kd, j-1 ) do i = 1, jlen csumj = csumj + ( ab( kd+i-jlen, j )*uscal )*x( j-jlen-1+i ) end do else jlen = min( kd, n-j ) do i = 1, jlen csumj = csumj + ( ab( i+1, j )*uscal )*x( j+i ) end do end if end if if( uscal==cmplx( tscal,KIND=dp) ) then ! compute x(j) := ( x(j) - csumj ) / a(j,j) if 1/a(j,j) ! was not used to scale the dotproduct. x( j ) = x( j ) - csumj xj = cabs1( x( j ) ) if( nounit ) then ! compute x(j) = x(j) / a(j,j), scaling if necessary. tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 160 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**t *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 160 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_170 else ! solve a**h * x = b loop_220: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = conjg( ab( maind, j ) )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_zladiv( uscal, tjjs ) end if if( rec1_${ik}$ )csumj = stdlib${ii}$_zdotc( jlen, ab( 2_${ik}$, j ), 1_${ik}$, x( j+1 ),1_${ik}$ ) end if else ! otherwise, use in-line code for the dot product. if( upper ) then jlen = min( kd, j-1 ) do i = 1, jlen csumj = csumj + ( conjg( ab( kd+i-jlen, j ) )*uscal )*x( j-jlen-1+i ) end do else jlen = min( kd, n-j ) do i = 1, jlen csumj = csumj + ( conjg( ab( i+1, j ) )*uscal )*x( j+i ) end do end if end if if( uscal==cmplx( tscal,KIND=dp) ) then ! compute x(j) := ( x(j) - csumj ) / a(j,j) if 1/a(j,j) ! was not used to scale the dotproduct. x( j ) = x( j ) - csumj xj = cabs1( x( j ) ) if( nounit ) then ! compute x(j) = x(j) / a(j,j), scaling if necessary. tjjs = conjg( ab( maind, j ) )*tscal else tjjs = tscal if( tscal==one )go to 210 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_zdscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**h *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 210 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_zladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_220 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_dscal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_zlatbs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$latbs( uplo, trans, diag, normin, n, kd, ab, ldab, x,scale, cnorm, & !! ZLATBS: solves one of the triangular systems !! A * x = s*b, A**T * x = s*b, or A**H * x = s*b, !! with scaling to prevent overflow, where A is an upper or lower !! triangular band matrix. Here A**T denotes the transpose of A, x and b !! are n-element vectors, and s is a scaling factor, usually less than !! or equal to 1, chosen so that the components of x will be less than !! the overflow threshold. If the unscaled problem will not cause !! overflow, the Level 2 BLAS routine ZTBSV is called. If the matrix A !! is singular (A(j,j) = 0 for some j), then s is set to 0 and a !! non-trivial solution to A*x = 0 is returned. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, normin, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n real(${ck}$), intent(out) :: scale ! Array Arguments real(${ck}$), intent(inout) :: cnorm(*) complex(${ck}$), intent(in) :: ab(ldab,*) complex(${ck}$), intent(inout) :: x(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper integer(${ik}$) :: i, imax, j, jfirst, jinc, jlast, jlen, maind real(${ck}$) :: bignum, grow, rec, smlnum, tjj, tmax, tscal, xbnd, xj, xmax complex(${ck}$) :: csumj, tjjs, uscal, zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1, cabs2 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) cabs2( zdum ) = abs( real( zdum,KIND=${ck}$) / 2._${ck}$ ) +abs( aimag( zdum ) / 2._${ck}$ ) ! Executable Statements info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) ! test the input parameters. if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( .not.stdlib_lsame( normin, 'Y' ) .and. .not.stdlib_lsame( normin, 'N' ) ) & then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( kd<0_${ik}$ ) then info = -6_${ik}$ else if( ldab0_${ik}$ ) then cnorm( j ) = stdlib${ii}$_${c2ri(ci)}$zasum( jlen, ab( 2_${ik}$, j ), 1_${ik}$ ) else cnorm( j ) = zero end if end do end if end if ! scale the column norms by tscal if the maximum element in cnorm is ! greater than bignum/2. imax = stdlib${ii}$_i${c2ri(ci)}$amax( n, cnorm, 1_${ik}$ ) tmax = cnorm( imax ) if( tmax<=bignum*half ) then tscal = one else tscal = half / ( smlnum*tmax ) call stdlib${ii}$_${c2ri(ci)}$scal( n, tscal, cnorm, 1_${ik}$ ) end if ! compute a bound on the computed solution vector to see if the ! level 2 blas routine stdlib${ii}$_${ci}$tbsv can be used. xmax = zero do j = 1, n xmax = max( xmax, cabs2( x( j ) ) ) end do xbnd = xmax if( notran ) then ! compute the growth in a * x = b. if( upper ) then jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = kd + 1_${ik}$ else jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 60 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, g(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 tjjs = ab( maind, j ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = g(j-1) / abs(a(j,j)) xbnd = min( xbnd, min( one, tjj )*grow ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if if( tjj+cnorm( j )>=smlnum ) then ! g(j) = g(j-1)*( 1 + cnorm(j) / abs(a(j,j)) ) grow = grow*( tjj / ( tjj+cnorm( j ) ) ) else ! g(j) could overflow, set grow to 0. grow = zero end if end do grow = xbnd else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 60 ! g(j) = g(j-1)*( 1 + cnorm(j) ) grow = grow*( one / ( one+cnorm( j ) ) ) end do end if 60 continue else ! compute the growth in a**t * x = b or a**h * x = b. if( upper ) then jfirst = 1_${ik}$ jlast = n jinc = 1_${ik}$ maind = kd + 1_${ik}$ else jfirst = n jlast = 1_${ik}$ jinc = -1_${ik}$ maind = 1_${ik}$ end if if( tscal/=one ) then grow = zero go to 90 end if if( nounit ) then ! a is non-unit triangular. ! compute grow = 1/g(j) and xbnd = 1/m(j). ! initially, m(0) = max{x(i), i=1,...,n}. grow = half / max( xbnd, smlnum ) xbnd = grow do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = max( g(j-1), m(j-1)*( 1 + cnorm(j) ) ) xj = one + cnorm( j ) grow = min( grow, xbnd / xj ) tjjs = ab( maind, j ) tjj = cabs1( tjjs ) if( tjj>=smlnum ) then ! m(j) = m(j-1)*( 1 + cnorm(j) ) / abs(a(j,j)) if( xj>tjj )xbnd = xbnd*( tjj / xj ) else ! m(j) could overflow, set xbnd to 0. xbnd = zero end if end do grow = min( grow, xbnd ) else ! a is unit triangular. ! compute grow = 1/g(j), where g(0) = max{x(i), i=1,...,n}. grow = min( one, half / max( xbnd, smlnum ) ) do j = jfirst, jlast, jinc ! exit the loop if the growth factor is too small. if( grow<=smlnum )go to 90 ! g(j) = ( 1 + cnorm(j) )*g(j-1) xj = one + cnorm( j ) grow = grow / xj end do end if 90 continue end if if( ( grow*tscal )>smlnum ) then ! use the level 2 blas solve if the reciprocal of the bound on ! elements of x is not too small. call stdlib${ii}$_${ci}$tbsv( uplo, trans, diag, n, kd, ab, ldab, x, 1_${ik}$ ) else ! use a level 1 blas solve, scaling intermediate results. if( xmax>bignum*half ) then ! scale x so that its components are less than or equal to ! bignum in absolute value. scale = ( bignum*half ) / xmax call stdlib${ii}$_${ci}$dscal( n, scale, x, 1_${ik}$ ) xmax = bignum else xmax = xmax*two end if if( notran ) then ! solve a * x = b loop_120: do j = jfirst, jlast, jinc ! compute x(j) = b(j) / a(j,j), scaling x if necessary. xj = cabs1( x( j ) ) if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 110 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/b(j). rec = one / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum ! to avoid overflow when dividing by a(j,j). rec = ( tjj*bignum ) / xj if( cnorm( j )>one ) then ! scale by 1/cnorm(j) to avoid overflow when ! multiplying x(j) times column j. rec = rec / cnorm( j ) end if call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) xj = cabs1( x( j ) ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0, and compute a solution to a*x = 0. do i = 1, n x( i ) = zero end do x( j ) = one xj = one scale = zero xmax = zero end if 110 continue ! scale x if necessary to avoid overflow when adding a ! multiple of column j of a. if( xj>one ) then rec = one / xj if( cnorm( j )>( bignum-xmax )*rec ) then ! scale x by 1/(2*abs(x(j))). rec = rec*half call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec end if else if( xj*cnorm( j )>( bignum-xmax ) ) then ! scale x by 1/2. call stdlib${ii}$_${ci}$dscal( n, half, x, 1_${ik}$ ) scale = scale*half end if if( upper ) then if( j>1_${ik}$ ) then ! compute the update ! x(max(1,j-kd):j-1) := x(max(1,j-kd):j-1) - ! x(j)* a(max(1,j-kd):j-1,j) jlen = min( kd, j-1 ) call stdlib${ii}$_${ci}$axpy( jlen, -x( j )*tscal,ab( kd+1-jlen, j ), 1_${ik}$, x( j-jlen & ), 1_${ik}$ ) i = stdlib${ii}$_i${ci}$amax( j-1, x, 1_${ik}$ ) xmax = cabs1( x( i ) ) end if else if( j0_${ik}$ )call stdlib${ii}$_${ci}$axpy( jlen, -x( j )*tscal, ab( 2_${ik}$, j ), 1_${ik}$,x( j+1 ),& 1_${ik}$ ) i = j + stdlib${ii}$_i${ci}$amax( n-j, x( j+1 ), 1_${ik}$ ) xmax = cabs1( x( i ) ) end if end do loop_120 else if( stdlib_lsame( trans, 'T' ) ) then ! solve a**t * x = b loop_170: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = ab( maind, j )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_${ci}$ladiv( uscal, tjjs ) end if if( rec1_${ik}$ )csumj = stdlib${ii}$_${ci}$dotu( jlen, ab( 2_${ik}$, j ), 1_${ik}$, x( j+1 ),1_${ik}$ ) end if else ! otherwise, use in-line code for the dot product. if( upper ) then jlen = min( kd, j-1 ) do i = 1, jlen csumj = csumj + ( ab( kd+i-jlen, j )*uscal )*x( j-jlen-1+i ) end do else jlen = min( kd, n-j ) do i = 1, jlen csumj = csumj + ( ab( i+1, j )*uscal )*x( j+i ) end do end if end if if( uscal==cmplx( tscal,KIND=${ck}$) ) then ! compute x(j) := ( x(j) - csumj ) / a(j,j) if 1/a(j,j) ! was not used to scale the dotproduct. x( j ) = x( j ) - csumj xj = cabs1( x( j ) ) if( nounit ) then ! compute x(j) = x(j) / a(j,j), scaling if necessary. tjjs = ab( maind, j )*tscal else tjjs = tscal if( tscal==one )go to 160 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**t *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 160 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_170 else ! solve a**h * x = b loop_220: do j = jfirst, jlast, jinc ! compute x(j) = b(j) - sum a(k,j)*x(k). ! k<>j xj = cabs1( x( j ) ) uscal = tscal rec = one / max( xmax, one ) if( cnorm( j )>( bignum-xj )*rec ) then ! if x(j) could overflow, scale x by 1/(2*xmax). rec = rec*half if( nounit ) then tjjs = conjg( ab( maind, j ) )*tscal else tjjs = tscal end if tjj = cabs1( tjjs ) if( tjj>one ) then ! divide by a(j,j) when scaling x if a(j,j) > 1. rec = min( one, rec*tjj ) uscal = stdlib${ii}$_${ci}$ladiv( uscal, tjjs ) end if if( rec1_${ik}$ )csumj = stdlib${ii}$_${ci}$dotc( jlen, ab( 2_${ik}$, j ), 1_${ik}$, x( j+1 ),1_${ik}$ ) end if else ! otherwise, use in-line code for the dot product. if( upper ) then jlen = min( kd, j-1 ) do i = 1, jlen csumj = csumj + ( conjg( ab( kd+i-jlen, j ) )*uscal )*x( j-jlen-1+i ) end do else jlen = min( kd, n-j ) do i = 1, jlen csumj = csumj + ( conjg( ab( i+1, j ) )*uscal )*x( j+i ) end do end if end if if( uscal==cmplx( tscal,KIND=${ck}$) ) then ! compute x(j) := ( x(j) - csumj ) / a(j,j) if 1/a(j,j) ! was not used to scale the dotproduct. x( j ) = x( j ) - csumj xj = cabs1( x( j ) ) if( nounit ) then ! compute x(j) = x(j) / a(j,j), scaling if necessary. tjjs = conjg( ab( maind, j ) )*tscal else tjjs = tscal if( tscal==one )go to 210 end if tjj = cabs1( tjjs ) if( tjj>smlnum ) then ! abs(a(j,j)) > smlnum: if( tjjtjj*bignum ) then ! scale x by 1/abs(x(j)). rec = one / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else if( tjj>zero ) then ! 0 < abs(a(j,j)) <= smlnum: if( xj>tjj*bignum ) then ! scale x by (1/abs(x(j)))*abs(a(j,j))*bignum. rec = ( tjj*bignum ) / xj call stdlib${ii}$_${ci}$dscal( n, rec, x, 1_${ik}$ ) scale = scale*rec xmax = xmax*rec end if x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) else ! a(j,j) = 0: set x(1:n) = 0, x(j) = 1, and ! scale = 0 and compute a solution to a**h *x = 0. do i = 1, n x( i ) = zero end do x( j ) = one scale = zero xmax = zero end if 210 continue else ! compute x(j) := x(j) / a(j,j) - csumj if the dot ! product has already been divided by 1/a(j,j). x( j ) = stdlib${ii}$_${ci}$ladiv( x( j ), tjjs ) - csumj end if xmax = max( xmax, cabs1( x( j ) ) ) end do loop_220 end if scale = scale / tscal end if ! scale the column norms by 1/tscal for return. if( tscal/=one ) then call stdlib${ii}$_${c2ri(ci)}$scal( n, one / tscal, cnorm, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ci}$latbs #:endif #:endfor pure module subroutine stdlib${ii}$_stbrfs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, x, ldx, ferr,& !! STBRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular band !! coefficient matrix. !! The solution matrix X must be computed by STBTRS or some other !! means before entering this routine. STBRFS does not do iterative !! refinement because doing so cannot improve the backward error. berr, work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: ab(ldab,*), b(ldb,*), x(ldx,*) real(sp), intent(out) :: berr(*), ferr(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transt integer(${ik}$) :: i, j, k, kase, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( nrhs<0_${ik}$ ) then info = -6_${ik}$ else if( ldabsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_slacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_slacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_stbsv( uplo, transt, diag, n, kd, ab, ldab,work( n+1 ), 1_${ik}$ ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_stbsv( uplo, trans, diag, n, kd, ab, ldab,work( n+1 ), 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_stbrfs pure module subroutine stdlib${ii}$_dtbrfs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, x, ldx, ferr,& !! DTBRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular band !! coefficient matrix. !! The solution matrix X must be computed by DTBTRS or some other !! means before entering this routine. DTBRFS does not do iterative !! refinement because doing so cannot improve the backward error. berr, work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: ab(ldab,*), b(ldb,*), x(ldx,*) real(dp), intent(out) :: berr(*), ferr(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transt integer(${ik}$) :: i, j, k, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( nrhs<0_${ik}$ ) then info = -6_${ik}$ else if( ldabsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_dlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_dlacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_dtbsv( uplo, transt, diag, n, kd, ab, ldab,work( n+1 ), 1_${ik}$ ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_dtbsv( uplo, trans, diag, n, kd, ab, ldab,work( n+1 ), 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_dtbrfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tbrfs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, x, ldx, ferr,& !! DTBRFS: provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular band !! coefficient matrix. !! The solution matrix X must be computed by DTBTRS or some other !! means before entering this routine. DTBRFS does not do iterative !! refinement because doing so cannot improve the backward error. berr, work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: ab(ldab,*), b(ldb,*), x(ldx,*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transt integer(${ik}$) :: i, j, k, kase, nz real(${rk}$) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( nrhs<0_${ik}$ ) then info = -6_${ik}$ else if( ldabsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ri}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_${ri}$lacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**t). call stdlib${ii}$_${ri}$tbsv( uplo, transt, diag, n, kd, ab, ldab,work( n+1 ), 1_${ik}$ ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_${ri}$tbsv( uplo, trans, diag, n, kd, ab, ldab,work( n+1 ), 1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_${ri}$tbrfs #:endif #:endfor pure module subroutine stdlib${ii}$_ctbrfs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, x, ldx, ferr,& !! CTBRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular band !! coefficient matrix. !! The solution matrix X must be computed by CTBTRS or some other !! means before entering this routine. CTBRFS does not do iterative !! refinement because doing so cannot improve the backward error. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldb, ldx, n, nrhs ! Array Arguments real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: ab(ldab,*), b(ldb,*), x(ldx,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transn, transt integer(${ik}$) :: i, j, k, kase, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( nrhs<0_${ik}$ ) then info = -6_${ik}$ else if( ldabsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_ctbsv( uplo, transt, diag, n, kd, ab, ldab, work,1_${ik}$ ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_ctbsv( uplo, transn, diag, n, kd, ab, ldab, work,1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_ctbrfs pure module subroutine stdlib${ii}$_ztbrfs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, x, ldx, ferr,& !! ZTBRFS provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular band !! coefficient matrix. !! The solution matrix X must be computed by ZTBTRS or some other !! means before entering this routine. ZTBRFS does not do iterative !! refinement because doing so cannot improve the backward error. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldb, ldx, n, nrhs ! Array Arguments real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: ab(ldab,*), b(ldb,*), x(ldx,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transn, transt integer(${ik}$) :: i, j, k, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( nrhs<0_${ik}$ ) then info = -6_${ik}$ else if( ldabsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_ztbsv( uplo, transt, diag, n, kd, ab, ldab, work,1_${ik}$ ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_ztbsv( uplo, transn, diag, n, kd, ab, ldab, work,1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_ztbrfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tbrfs( uplo, trans, diag, n, kd, nrhs, ab, ldab, b,ldb, x, ldx, ferr,& !! ZTBRFS: provides error bounds and backward error estimates for the !! solution to a system of linear equations with a triangular band !! coefficient matrix. !! The solution matrix X must be computed by ZTBTRS or some other !! means before entering this routine. ZTBRFS does not do iterative !! refinement because doing so cannot improve the backward error. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: diag, trans, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldb, ldx, n, nrhs ! Array Arguments real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: ab(ldab,*), b(ldb,*), x(ldx,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: notran, nounit, upper character :: transn, transt integer(${ik}$) :: i, j, k, kase, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) notran = stdlib_lsame( trans, 'N' ) nounit = stdlib_lsame( diag, 'N' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) .and. .not.stdlib_lsame( & trans, 'C' ) ) then info = -2_${ik}$ else if( .not.nounit .and. .not.stdlib_lsame( diag, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( nrhs<0_${ik}$ ) then info = -6_${ik}$ else if( ldabsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(op(a)))* ! ( abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(op(a)) is the inverse of op(a) ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(op(a))*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(op(a))*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(op(a)) * diag(w), ! where w = abs(r) + nz*eps*( abs(op(a))*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 210 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(op(a)**h). call stdlib${ii}$_${ci}$tbsv( uplo, transt, diag, n, kd, ab, ldab, work,1_${ik}$ ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else ! multiply by inv(op(a))*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$tbsv( uplo, transn, diag, n, kd, ab, ldab, work,1_${ik}$ ) end if go to 210 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_250 return end subroutine stdlib${ii}$_${ci}$tbrfs #:endif #:endfor #:endfor end submodule stdlib_lapack_solve_tri_comp fortran-lang-stdlib-0ede301/src/lapack/stdlib_linalg_lapack_aux.fypp0000664000175000017500000021000715135654166026107 0ustar alastairalastair#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES module stdlib_linalg_lapack_aux use stdlib_linalg_constants use stdlib_linalg_blas use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, & LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR, LINALG_SUCCESS use ieee_arithmetic, only: ieee_support_inf, ieee_support_nan implicit none private public :: sp,dp,qp,lk,ilp,ilp64 #:for ik,it,ii in LINALG_INT_KINDS_TYPES public :: stdlib${ii}$_chla_transtype public :: stdlib${ii}$_ieeeck public :: stdlib${ii}$_iladiag public :: stdlib${ii}$_ilaenv public :: stdlib${ii}$_ilaenv2stage public :: stdlib${ii}$_ilaprec public :: stdlib${ii}$_ilatrans public :: stdlib${ii}$_ilauplo public :: stdlib${ii}$_iparam2stage public :: stdlib${ii}$_iparmq public :: stdlib${ii}$_lsamen public :: stdlib${ii}$_xerbla public :: stdlib${ii}$_xerbla_array #:for rk,rt,ri in REAL_KINDS_TYPES public :: stdlib${ii}$_${ri}$roundup_lwork #:endfor #:for ck,ct,ci in CMPLX_KINDS_TYPES public :: stdlib${ii}$_i${ci}$max1 #:endfor #:for rk,rt,ri in RC_KINDS_TYPES public :: stdlib${ii}$_ila${ri}$lc public :: stdlib${ii}$_ila${ri}$lr #:endfor #:endfor #:for rk,rt,ri in RC_KINDS_TYPES public :: stdlib_select_${ri}$ public :: stdlib_selctg_${ri}$ #:endfor public :: handle_potrf_info public :: handle_getri_info public :: handle_gesdd_info public :: handle_gesv_info public :: handle_gees_info public :: handle_geqrf_info public :: handle_geqp3_info public :: handle_orgqr_info public :: handle_gelsd_info public :: handle_geev_info public :: handle_ggev_info public :: handle_heev_info public :: handle_gglse_info ! SELCTG is a LOGICAL FUNCTION of three DOUBLE PRECISION arguments ! used to select eigenvalues to sort to the top left of the Schur form. ! An eigenvalue (ALPHAR(j)+ALPHAI(j))/BETA(j) is selected if SELCTG is true, i.e., abstract interface #:for rk,rt,ri in REAL_KINDS_TYPES pure logical(lk) function stdlib_selctg_${ri}$(alphar,alphai,beta) import ${rk}$,lk implicit none real(${rk}$), intent(in) :: alphar,alphai,beta end function stdlib_selctg_${ri}$ pure logical(lk) function stdlib_select_${ri}$(alphar,alphai) import ${rk}$,lk implicit none real(${rk}$), intent(in) :: alphar,alphai end function stdlib_select_${ri}$ #:endfor #:for ck,ct,ci in CMPLX_KINDS_TYPES pure logical(lk) function stdlib_selctg_${ci}$(alpha,beta) import ${ck}$,lk implicit none complex(${ck}$), intent(in) :: alpha,beta end function stdlib_selctg_${ci}$ pure logical(lk) function stdlib_select_${ci}$(alpha) import ${ck}$,lk implicit none complex(${ck}$), intent(in) :: alpha end function stdlib_select_${ci}$ #:endfor end interface contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure character function stdlib${ii}$_chla_transtype( trans ) !! This subroutine translates from a BLAST-specified integer constant to !! the character string specifying a transposition operation. !! CHLA_TRANSTYPE returns an CHARACTER*1. If CHLA_TRANSTYPE: is 'X', !! then input is not an integer indicating a transposition operator. !! Otherwise CHLA_TRANSTYPE returns the constant value corresponding to !! TRANS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: trans ! ===================================================================== ! Parameters integer(${ik}$), parameter :: blas_no_trans = 111 integer(${ik}$), parameter :: blas_trans = 112 integer(${ik}$), parameter :: blas_conj_trans = 113 ! Executable Statements if( trans==blas_no_trans ) then stdlib${ii}$_chla_transtype = 'N' else if( trans==blas_trans ) then stdlib${ii}$_chla_transtype = 'T' else if( trans==blas_conj_trans ) then stdlib${ii}$_chla_transtype = 'C' else stdlib${ii}$_chla_transtype = 'X' end if return end function stdlib${ii}$_chla_transtype pure integer(${ik}$) function stdlib${ii}$_ieeeck( ispec, zero, one ) !! IEEECK is called from the ILAENV to verify that Infinity and !! possibly NaN arithmetic is safe (i.e. will not trap). ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: ispec real(sp), intent(in) :: one, zero ! ===================================================================== ! Executable Statements stdlib${ii}$_ieeeck = 1 ! Test support for infinity values if (.not.ieee_support_inf(one)) then stdlib${ii}$_ieeeck = 0 return end if ! return if we were only asked to check infinity arithmetic if (ispec == 0) return if (.not.ieee_support_nan(one)) then stdlib${ii}$_ieeeck = 0 return end if return end function stdlib${ii}$_ieeeck integer(${ik}$) function stdlib${ii}$_iladiag( diag ) !! This subroutine translated from a character string specifying if a !! matrix has unit diagonal or not to the relevant BLAST-specified !! integer constant. !! ILADIAG returns an INTEGER. If ILADIAG: < 0, then the input is not a !! character indicating a unit or non-unit diagonal. Otherwise ILADIAG !! returns the constant value corresponding to DIAG. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character :: diag ! ===================================================================== ! Parameters integer(${ik}$), parameter :: blas_non_unit_diag = 131 integer(${ik}$), parameter :: blas_unit_diag = 132 ! Executable Statements if( stdlib_lsame( diag, 'N' ) ) then stdlib${ii}$_iladiag = blas_non_unit_diag else if( stdlib_lsame( diag, 'U' ) ) then stdlib${ii}$_iladiag = blas_unit_diag else stdlib${ii}$_iladiag = -1 end if return end function stdlib${ii}$_iladiag integer(${ik}$) function stdlib${ii}$_ilaprec( prec ) !! This subroutine translated from a character string specifying an !! intermediate precision to the relevant BLAST-specified integer !! constant. !! ILAPREC returns an INTEGER. If ILAPREC: < 0, then the input is not a !! character indicating a supported intermediate precision. Otherwise !! ILAPREC returns the constant value corresponding to PREC. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character :: prec ! ===================================================================== ! Parameters integer(${ik}$), parameter :: blas_prec_single = 211 integer(${ik}$), parameter :: blas_prec_double = 212 integer(${ik}$), parameter :: blas_prec_indigenous = 213 integer(${ik}$), parameter :: blas_prec_extra = 214 ! Executable Statements if( stdlib_lsame( prec, 'S' ) ) then stdlib${ii}$_ilaprec = blas_prec_single else if( stdlib_lsame( prec, 'D' ) ) then stdlib${ii}$_ilaprec = blas_prec_double else if( stdlib_lsame( prec, 'I' ) ) then stdlib${ii}$_ilaprec = blas_prec_indigenous else if( stdlib_lsame( prec, 'X' ) .or. stdlib_lsame( prec, 'E' ) ) then stdlib${ii}$_ilaprec = blas_prec_extra else stdlib${ii}$_ilaprec = -1 end if return end function stdlib${ii}$_ilaprec integer(${ik}$) function stdlib${ii}$_ilatrans( trans ) !! This subroutine translates from a character string specifying a !! transposition operation to the relevant BLAST-specified integer !! constant. !! ILATRANS returns an INTEGER. If ILATRANS: < 0, then the input is not !! a character indicating a transposition operator. Otherwise ILATRANS !! returns the constant value corresponding to TRANS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character :: trans ! ===================================================================== ! Parameters integer(${ik}$), parameter :: blas_no_trans = 111 integer(${ik}$), parameter :: blas_trans = 112 integer(${ik}$), parameter :: blas_conj_trans = 113 ! Executable Statements if( stdlib_lsame( trans, 'N' ) ) then stdlib${ii}$_ilatrans = blas_no_trans else if( stdlib_lsame( trans, 'T' ) ) then stdlib${ii}$_ilatrans = blas_trans else if( stdlib_lsame( trans, 'C' ) ) then stdlib${ii}$_ilatrans = blas_conj_trans else stdlib${ii}$_ilatrans = -1 end if return end function stdlib${ii}$_ilatrans integer(${ik}$) function stdlib${ii}$_ilauplo( uplo ) !! This subroutine translated from a character string specifying a !! upper- or lower-triangular matrix to the relevant BLAST-specified !! integer constant. !! ILAUPLO returns an INTEGER. If ILAUPLO: < 0, then the input is not !! a character indicating an upper- or lower-triangular matrix. !! Otherwise ILAUPLO returns the constant value corresponding to UPLO. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character :: uplo ! ===================================================================== ! Parameters integer(${ik}$), parameter :: blas_upper = 121 integer(${ik}$), parameter :: blas_lower = 122 ! Executable Statements if( stdlib_lsame( uplo, 'U' ) ) then stdlib${ii}$_ilauplo = blas_upper else if( stdlib_lsame( uplo, 'L' ) ) then stdlib${ii}$_ilauplo = blas_lower else stdlib${ii}$_ilauplo = -1 end if return end function stdlib${ii}$_ilauplo pure integer(${ik}$) function stdlib${ii}$_iparmq( ispec, name, opts, n, ilo, ihi, lwork ) !! This program sets problem and machine dependent parameters !! useful for xHSEQR and related subroutines for eigenvalue !! problems. It is called whenever !! IPARMQ is called with 12 <= ISPEC <= 16 ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, ispec, lwork, n character, intent(in) :: name*(*), opts*(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: inmin = 12 integer(${ik}$), parameter :: inwin = 13 integer(${ik}$), parameter :: inibl = 14 integer(${ik}$), parameter :: ishfts = 15 integer(${ik}$), parameter :: iacc22 = 16 integer(${ik}$), parameter :: icost = 17 integer(${ik}$), parameter :: nmin = 75 integer(${ik}$), parameter :: k22min = 14 integer(${ik}$), parameter :: kacmin = 14 integer(${ik}$), parameter :: nibble = 14 integer(${ik}$), parameter :: knwswp = 500 integer(${ik}$), parameter :: rcost = 10 real(sp), parameter :: two = 2.0 ! Local Scalars integer(${ik}$) :: nh, ns integer(${ik}$) :: i, ic, iz character :: subnam*6 ! Intrinsic Functions intrinsic :: log,max,mod,nint,real ! Executable Statements if( ( ispec==ishfts ) .or. ( ispec==inwin ) .or.( ispec==iacc22 ) ) then ! ==== set the number simultaneous shifts ==== nh = ihi - ilo + 1 ns = 2 if( nh>=30 )ns = 4 if( nh>=60 )ns = 10 if( nh>=150 )ns = max( 10, nh / nint( log( real( nh,KIND=dp) ) / log( two ),& KIND=ilp) ) if( nh>=590 )ns = 64 if( nh>=3000 )ns = 128 if( nh>=6000 )ns = 256 ns = max( 2, ns-mod( ns, 2 ) ) end if if( ispec==inmin ) then ! ===== matrices of order smaller than nmin get sent ! . to xlahqr, the classic double shift algorithm. ! . this must be at least 11. ==== stdlib${ii}$_iparmq = nmin else if( ispec==inibl ) then ! ==== inibl: skip a multi-shift qr iteration and ! . whenever aggressive early deflation finds ! . at least (nibble*(window size)/100) deflations. ==== stdlib${ii}$_iparmq = nibble else if( ispec==ishfts ) then ! ==== nshfts: the number of simultaneous shifts ===== stdlib${ii}$_iparmq = ns else if( ispec==inwin ) then ! ==== nw: deflation window size. ==== if( nh<=knwswp ) then stdlib${ii}$_iparmq = ns else stdlib${ii}$_iparmq = 3*ns / 2 end if else if( ispec==iacc22 ) then ! ==== iacc22: whether to accumulate reflections ! . before updating the far-from-diagonal elements ! . and whether to use 2-by-2 block structure while ! . doing it. a small amount of work could be saved ! . by making this choice dependent also upon the ! . nh=ihi-ilo+1. ! convert name to upper case if the first character is lower case. stdlib${ii}$_iparmq = 0 subnam = name ic = ichar( subnam( 1: 1 ) ) iz = ichar( 'Z' ) if( iz==90 .or. iz==122 ) then ! ascii character set if( ic>=97 .and. ic<=122 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ic>=97 .and. ic<=122 )subnam( i: i ) = char( ic-32 ) end do end if else if( iz==233 .or. iz==169 ) then ! ebcdic character set if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 .and. & ic<=169 ) ) then subnam( 1: 1 ) = char( ic+64 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 & .and. ic<=169 ) )subnam( i:i ) = char( ic+64 ) end do end if else if( iz==218 .or. iz==250 ) then ! prime machines: ascii+128 if( ic>=225 .and. ic<=250 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ic>=225 .and. ic<=250 )subnam( i: i ) = char( ic-32 ) end do end if end if if( subnam( 2:6 )=='GGHRD' .or.subnam( 2:6 )=='GGHD3' ) then stdlib${ii}$_iparmq = 1 if( nh>=k22min )stdlib${ii}$_iparmq = 2 else if ( subnam( 4:6 )=='EXC' ) then if( nh>=kacmin )stdlib${ii}$_iparmq = 1 if( nh>=k22min )stdlib${ii}$_iparmq = 2 else if ( subnam( 2:6 )=='HSEQR' .or.subnam( 2:5 )=='LAQR' ) then if( ns>=kacmin )stdlib${ii}$_iparmq = 1 if( ns>=k22min )stdlib${ii}$_iparmq = 2 end if else if( ispec==icost ) then ! === relative cost of near-the-diagonal chase vs ! blas updates === stdlib${ii}$_iparmq = rcost else ! ===== invalid value of ispec ===== stdlib${ii}$_iparmq = -1 end if end function stdlib${ii}$_iparmq pure logical(lk) function stdlib${ii}$_lsamen( n, ca, cb ) !! LSAMEN tests if the first N letters of CA are the same as the !! first N letters of CB, regardless of case. !! LSAMEN returns .TRUE. if CA and CB are equivalent except for case !! and .FALSE. otherwise. LSAMEN also returns .FALSE. if LEN( CA ) !! or LEN( CB ) is less than N. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character(len=*), intent(in) :: ca, cb integer(${ik}$), intent(in) :: n ! ===================================================================== ! Local Scalars integer(${ik}$) :: i ! Intrinsic Functions intrinsic :: len ! Executable Statements stdlib${ii}$_lsamen = .false. if( len( ca )= LWORK. !! ROUNDUP_LWORK is guaranteed to have zero decimal part. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: lwork ! ===================================================================== ! Intrinsic Functions intrinsic :: epsilon,real,int ! Executable Statements stdlib${ii}$_${ri}$roundup_lwork = real(lwork,KIND=${rk}$) if (int( stdlib${ii}$_${ri}$roundup_lwork,KIND=ilp)=1)) i=i-1 enddo stdlib${ii}$_ila${ri}$lr = max( stdlib${ii}$_ila${ri}$lr, i ) end do end if return end function stdlib${ii}$_ila${ri}$lr #:endfor #:for ck,ct,ci in CMPLX_KINDS_TYPES pure integer(${ik}$) function stdlib${ii}$_i${ci}$max1( n, zx, incx ) !! I*MAX1: finds the index of the first vector element of maximum absolute value. !! Based on I*AMAX from Level 1 BLAS. !! The change is to use the 'genuine' absolute value. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments complex(${ck}$), intent(in) :: zx(*) ! ===================================================================== ! Local Scalars real(${ck}$) :: dmax integer(${ik}$) :: i, ix ! Intrinsic Functions intrinsic :: abs ! Executable Statements stdlib${ii}$_i${ci}$max1 = 0 if (n<1 .or. incx<=0) return stdlib${ii}$_i${ci}$max1 = 1 if (n==1) return if (incx==1) then ! code for increment equal to 1 dmax = abs(zx(1)) do i = 2,n if (abs(zx(i))>dmax) then stdlib${ii}$_i${ci}$max1 = i dmax = abs(zx(i)) end if end do else ! code for increment not equal to 1 ix = 1 dmax = abs(zx(1)) ix = ix + incx do i = 2,n if (abs(zx(ix))>dmax) then stdlib${ii}$_i${ci}$max1 = i dmax = abs(zx(ix)) end if ix = ix + incx end do end if return end function stdlib${ii}$_i${ci}$max1 #:endfor pure integer(${ik}$) function stdlib${ii}$_ilaenv( ispec, name, opts, n1, n2, n3, n4 ) !! ILAENV is called from the LAPACK routines to choose problem-dependent !! parameters for the local environment. See ISPEC for a description of !! the parameters. !! ILAENV returns an INTEGER !! if ILAENV >= 0: ILAENV returns the value of the parameter specified by ISPEC !! if ILAENV < 0: if ILAENV = -k, the k-th argument had an illegal value. !! This version provides a set of parameters which should give good, !! but not optimal, performance on many of the currently available !! computers. Users are encouraged to modify this subroutine to set !! the tuning parameters for their particular machine using the option !! and problem size information in the arguments. !! This routine will not function correctly if it is converted to all !! lower case. Converting it to all upper case is allowed. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character(len=*), intent(in) :: name, opts integer(${ik}$), intent(in) :: ispec, n1, n2, n3, n4 ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, iz, nb, nbmin, nx logical(lk) :: cname, sname, twostage character :: c1*1, c2*2, c4*2, c3*3, subnam*16 ! Intrinsic Functions intrinsic :: char,ichar,int,min,real ! Executable Statements go to ( 10, 10, 10, 80, 90, 100, 110, 120,130, 140, 150, 160, 160, 160, 160, 160, 160)& ispec ! invalid value for ispec stdlib${ii}$_ilaenv = -1 return 10 continue ! convert name to upper case if the first character is lower case. stdlib${ii}$_ilaenv = 1 subnam = name ic = ichar( subnam( 1: 1 ) ) iz = ichar( 'Z' ) if( iz==90 .or. iz==122 ) then ! ascii character set if( ic>=97 .and. ic<=122 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ic>=97 .and. ic<=122 )subnam( i: i ) = char( ic-32 ) end do end if else if( iz==233 .or. iz==169 ) then ! ebcdic character set if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 .and. & ic<=169 ) ) then subnam( 1: 1 ) = char( ic+64 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 & .and. ic<=169 ) )subnam( i:i ) = char( ic+64 ) end do end if else if( iz==218 .or. iz==250 ) then ! prime machines: ascii+128 if( ic>=225 .and. ic<=250 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ic>=225 .and. ic<=250 )subnam( i: i ) = char( ic-32 ) end do end if end if c1 = subnam( 1: 1 ) sname = c1=='S' .or. c1=='D' cname = c1=='C' .or. c1=='Z' if( .not.( cname .or. sname ) )return c2 = subnam( 2: 3 ) c3 = subnam( 4: 6 ) c4 = c3( 2: 3 ) twostage = len( subnam )>=11.and. subnam( 11: 11 )=='2' go to ( 50, 60, 70 )ispec 50 continue ! ispec = 1: block size ! in these examples, separate code is provided for setting nb for ! real and complex. we assume that nb will take the same value in ! single or double precision. nb = 1 if( subnam(2:6)=='LAORH' ) then ! this is for *laorhr_getrfnp routine if( sname ) then nb = 32 else nb = 32 end if else if( c2=='GE' ) then if( c3=='TRF' ) then if( sname ) then nb = 64 else nb = 64 end if else if( c3=='QRF' .or. c3=='RQF' .or. c3=='LQF' .or.c3=='QLF' ) then if( sname ) then nb = 32 else nb = 32 end if else if( c3=='QR ') then if( n3 == 1) then if( sname ) then ! m*n if ((n1*n2<=131072).or.(n1<=8192)) then nb = n1 else nb = 32768/n2 end if else if ((n1*n2<=131072).or.(n1<=8192)) then nb = n1 else nb = 32768/n2 end if end if else if( sname ) then nb = 1 else nb = 1 end if end if else if( c3=='LQ ') then if( n3 == 2) then if( sname ) then ! m*n if ((n1*n2<=131072).or.(n1<=8192)) then nb = n1 else nb = 32768/n2 end if else if ((n1*n2<=131072).or.(n1<=8192)) then nb = n1 else nb = 32768/n2 end if end if else if( sname ) then nb = 1 else nb = 1 end if end if else if( c3=='HRD' ) then if( sname ) then nb = 32 else nb = 32 end if else if( c3=='BRD' ) then if( sname ) then nb = 32 else nb = 32 end if else if( c3=='TRI' ) then if( sname ) then nb = 64 else nb = 64 end if end if else if( c2=='PO' ) then if( c3=='TRF' ) then if( sname ) then nb = 64 else nb = 64 end if end if else if( c2=='SY' ) then if( c3=='TRF' ) then if( sname ) then if( twostage ) then nb = 192 else nb = 64 end if else if( twostage ) then nb = 192 else nb = 64 end if end if else if( sname .and. c3=='TRD' ) then nb = 32 else if( sname .and. c3=='GST' ) then nb = 64 end if else if( cname .and. c2=='HE' ) then if( c3=='TRF' ) then if( twostage ) then nb = 192 else nb = 64 end if else if( c3=='TRD' ) then nb = 32 else if( c3=='GST' ) then nb = 64 end if else if( sname .and. c2=='OR' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nb = 32 end if else if( c3( 1: 1 )=='M' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nb = 32 end if end if else if( cname .and. c2=='UN' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nb = 32 end if else if( c3( 1: 1 )=='M' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nb = 32 end if end if else if( c2=='GB' ) then if( c3=='TRF' ) then if( sname ) then if( n4<=64 ) then nb = 1 else nb = 32 end if else if( n4<=64 ) then nb = 1 else nb = 32 end if end if end if else if( c2=='PB' ) then if( c3=='TRF' ) then if( sname ) then if( n2<=64 ) then nb = 1 else nb = 32 end if else if( n2<=64 ) then nb = 1 else nb = 32 end if end if end if else if( c2=='TR' ) then if( c3=='TRI' ) then if( sname ) then nb = 64 else nb = 64 end if else if ( c3=='EVC' ) then if( sname ) then nb = 64 else nb = 64 end if end if else if( c2=='LA' ) then if( c3=='UUM' ) then if( sname ) then nb = 64 else nb = 64 end if end if else if( sname .and. c2=='ST' ) then if( c3=='EBZ' ) then nb = 1 end if else if( c2=='GG' ) then nb = 32 if( c3=='HD3' ) then if( sname ) then nb = 32 else nb = 32 end if end if end if stdlib${ii}$_ilaenv = nb return 60 continue ! ispec = 2: minimum block size nbmin = 2 if( c2=='GE' ) then if( c3=='QRF' .or. c3=='RQF' .or. c3=='LQF' .or. c3=='QLF' ) then if( sname ) then nbmin = 2 else nbmin = 2 end if else if( c3=='HRD' ) then if( sname ) then nbmin = 2 else nbmin = 2 end if else if( c3=='BRD' ) then if( sname ) then nbmin = 2 else nbmin = 2 end if else if( c3=='TRI' ) then if( sname ) then nbmin = 2 else nbmin = 2 end if end if else if( c2=='SY' ) then if( c3=='TRF' ) then if( sname ) then nbmin = 8 else nbmin = 8 end if else if( sname .and. c3=='TRD' ) then nbmin = 2 end if else if( cname .and. c2=='HE' ) then if( c3=='TRD' ) then nbmin = 2 end if else if( sname .and. c2=='OR' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nbmin = 2 end if else if( c3( 1: 1 )=='M' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nbmin = 2 end if end if else if( cname .and. c2=='UN' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nbmin = 2 end if else if( c3( 1: 1 )=='M' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nbmin = 2 end if end if else if( c2=='GG' ) then nbmin = 2 if( c3=='HD3' ) then nbmin = 2 end if end if stdlib${ii}$_ilaenv = nbmin return 70 continue ! ispec = 3: crossover point nx = 0 if( c2=='GE' ) then if( c3=='QRF' .or. c3=='RQF' .or. c3=='LQF' .or. c3=='QLF' ) then if( sname ) then nx = 128 else nx = 128 end if else if( c3=='HRD' ) then if( sname ) then nx = 128 else nx = 128 end if else if( c3=='BRD' ) then if( sname ) then nx = 128 else nx = 128 end if end if else if( c2=='SY' ) then if( sname .and. c3=='TRD' ) then nx = 32 end if else if( cname .and. c2=='HE' ) then if( c3=='TRD' ) then nx = 32 end if else if( sname .and. c2=='OR' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nx = 128 end if end if else if( cname .and. c2=='UN' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nx = 128 end if end if else if( c2=='GG' ) then nx = 128 if( c3=='HD3' ) then nx = 128 end if end if stdlib${ii}$_ilaenv = nx return 80 continue ! ispec = 4: number of shifts (used by xhseqr) stdlib${ii}$_ilaenv = 6 return 90 continue ! ispec = 5: minimum column dimension (not used) stdlib${ii}$_ilaenv = 2 return 100 continue ! ispec = 6: crossover point for svd (used by xgelss and xgesvd) stdlib${ii}$_ilaenv = int( real( min( n1, n2 ),KIND=dp)*1.6e0,KIND=ilp) return 110 continue ! ispec = 7: number of processors (not used) stdlib${ii}$_ilaenv = 1 return 120 continue ! ispec = 8: crossover point for multishift (used by xhseqr) stdlib${ii}$_ilaenv = 50 return 130 continue ! ispec = 9: maximum size of the subproblems at the bottom of the ! computation tree in the divide-and-conquer algorithm ! (used by xgelsd and xgesdd) stdlib${ii}$_ilaenv = 25 return 140 continue ! ispec = 10: ieee and infinity nan arithmetic can be trusted not to trap ! stdlib${ii}$_ilaenv = 0 stdlib${ii}$_ilaenv = 1 if( stdlib${ii}$_ilaenv==1 ) then stdlib${ii}$_ilaenv = stdlib${ii}$_ieeeck( 1_${ik}$, 0.0, 1.0 ) end if return 150 continue ! ispec = 11: ieee infinity arithmetic can be trusted not to trap ! stdlib${ii}$_ilaenv = 0 stdlib${ii}$_ilaenv = 1 if( stdlib${ii}$_ilaenv==1 ) then stdlib${ii}$_ilaenv = stdlib${ii}$_ieeeck( 0_${ik}$, 0.0, 1.0 ) end if return 160 continue ! 12 <= ispec <= 17: xhseqr or related subroutines. stdlib${ii}$_ilaenv = stdlib${ii}$_iparmq( ispec, name, opts, n1, n2, n3, n4 ) return end function stdlib${ii}$_ilaenv integer(${ik}$) function stdlib${ii}$_iparam2stage( ispec, name, opts,ni, nbi, ibi, nxi ) !! This program sets problem and machine dependent parameters !! useful for xHETRD_2STAGE, xHETRD_HE2HB, xHETRD_HB2ST, !! xGEBRD_2STAGE, xGEBRD_GE2GB, xGEBRD_GB2BD !! and related subroutines for eigenvalue problems. !! It is called whenever ILAENV is called with 17 <= ISPEC <= 21. !! It is called whenever ILAENV2STAGE is called with 1 <= ISPEC <= 5 !! with a direct conversion ISPEC + 16. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character(len=*), intent(in) :: name, opts integer(${ik}$), intent(in) :: ispec, ni, nbi, ibi, nxi ! ================================================================ ! Local Scalars integer(${ik}$) :: i, ic, iz, kd, ib, lhous, lwork, nthreads, factoptnb, qroptnb, & lqoptnb logical(lk) :: rprec, cprec character :: prec*1, algo*3, stag*5, subnam*12, vect*1 ! Intrinsic Functions intrinsic :: char,ichar,max ! Executable Statements ! invalid value for ispec if( (ispec<17).or.(ispec>21) ) then stdlib${ii}$_iparam2stage = -1 return endif ! get the number of threads nthreads = 1 !$ nthreads = omp_get_num_threads() ! write(*,*) 'iparam voici nthreads ispec ',nthreads, ispec if( ispec /= 19 ) then ! convert name to upper case if the first character is lower case. stdlib${ii}$_iparam2stage = -1 subnam = name ic = ichar( subnam( 1: 1 ) ) iz = ichar( 'Z' ) if( iz==90 .or. iz==122 ) then ! ascii character set if( ic>=97 .and. ic<=122 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 12 ic = ichar( subnam( i: i ) ) if( ic>=97 .and. ic<=122 )subnam( i: i ) = char( ic-32 ) end do end if else if( iz==233 .or. iz==169 ) then ! ebcdic character set if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 .and. & ic<=169 ) ) then subnam( 1: 1 ) = char( ic+64 ) do i = 2, 12 ic = ichar( subnam( i: i ) ) if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 & .and. ic<=169 ) )subnam( i:i ) = char( ic+64 ) end do end if else if( iz==218 .or. iz==250 ) then ! prime machines: ascii+128 if( ic>=225 .and. ic<=250 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 12 ic = ichar( subnam( i: i ) ) if( ic>=225 .and. ic<=250 )subnam( i: i ) = char( ic-32 ) end do end if end if prec = subnam( 1: 1 ) algo = subnam( 4: 6 ) stag = subnam( 8:12 ) rprec = prec=='S' .or. prec=='D' cprec = prec=='C' .or. prec=='Z' ! invalid value for precision if( .not.( rprec .or. cprec ) ) then stdlib${ii}$_iparam2stage = -1 return endif endif ! write(*,*),'rprec,cprec ',rprec,cprec, ! $ ' algo ',algo,' stage ',stag if (( ispec == 17 ) .or. ( ispec == 18 )) then ! ispec = 17, 18: block size kd, ib ! could be also dependent from n but for now it ! depend only on sequential or parallel if( nthreads>4 ) then if( cprec ) then kd = 128 ib = 32 else kd = 160 ib = 40 endif else if( nthreads>1 ) then if( cprec ) then kd = 64 ib = 32 else kd = 64 ib = 32 endif else if( cprec ) then kd = 16 ib = 16 else kd = 32 ib = 16 endif endif if( ispec==17 ) stdlib${ii}$_iparam2stage = kd if( ispec==18 ) stdlib${ii}$_iparam2stage = ib else if ( ispec == 19 ) then ! ispec = 19: ! lhous length of the houselholder representation ! matrix (v,t) of the second stage. should be >= 1. ! will add the vect option here next release vect = opts(1:1) if( vect=='N' ) then lhous = max( 1, 4*ni ) else ! this is not correct, it need to call the algo and the stage2 lhous = max( 1, 4*ni ) + ibi endif if( lhous>=0 ) then stdlib${ii}$_iparam2stage = lhous else stdlib${ii}$_iparam2stage = -1 endif else if ( ispec == 20 ) then ! ispec = 20: (21 for future use) ! lwork length of the workspace for ! either or both stages for trd and brd. should be >= 1. ! trd: ! trd_stage 1: = lt + lw + ls1 + ls2 ! = ldt*kd + n*kd + n*max(kd,factoptnb) + lds2*kd ! where ldt=lds2=kd ! = n*kd + n*max(kd,factoptnb) + 2*kd*kd ! trd_stage 2: = (2nb+1)*n + kd*nthreads ! trd_both : = max(stage1,stage2) + ab ( ab=(kd+1)*n ) ! = n*kd + n*max(kd+1,factoptnb) ! + max(2*kd*kd, kd*nthreads) ! + (kd+1)*n lwork = -1 subnam(1:1) = prec subnam(2:6) = 'GEQRF' qroptnb = stdlib${ii}$_ilaenv( 1_${ik}$, subnam, ' ', ni, nbi, -1_${ik}$, -1_${ik}$ ) subnam(2:6) = 'GELQF' lqoptnb = stdlib${ii}$_ilaenv( 1_${ik}$, subnam, ' ', nbi, ni, -1_${ik}$, -1_${ik}$ ) ! could be qr or lq for trd and the max for brd factoptnb = max(qroptnb, lqoptnb) if( algo=='TRD' ) then if( stag=='2STAG' ) then lwork = ni*nbi + ni*max(nbi+1,factoptnb)+ max(2*nbi*nbi, nbi*nthreads)+ (nbi+& 1)*ni else if( (stag=='HE2HB').or.(stag=='SY2SB') ) then lwork = ni*nbi + ni*max(nbi,factoptnb) + 2*nbi*nbi else if( (stag=='HB2ST').or.(stag=='SB2ST') ) then lwork = (2*nbi+1)*ni + nbi*nthreads endif else if( algo=='BRD' ) then if( stag=='2STAG' ) then lwork = 2*ni*nbi + ni*max(nbi+1,factoptnb)+ max(2*nbi*nbi, nbi*nthreads)+ (& nbi+1)*ni else if( stag=='GE2GB' ) then lwork = ni*nbi + ni*max(nbi,factoptnb) + 2*nbi*nbi else if( stag=='GB2BD' ) then lwork = (3*nbi+1)*ni + nbi*nthreads endif endif lwork = max ( 1, lwork ) if( lwork>0 ) then stdlib${ii}$_iparam2stage = lwork else stdlib${ii}$_iparam2stage = -1 endif else if ( ispec == 21 ) then ! ispec = 21 for future use stdlib${ii}$_iparam2stage = nxi endif end function stdlib${ii}$_iparam2stage integer(${ik}$) function stdlib${ii}$_ilaenv2stage( ispec, name, opts, n1, n2, n3, n4 ) !! ILAENV2STAGE is called from the LAPACK routines to choose problem-dependent !! parameters for the local environment. See ISPEC for a description of !! the parameters. !! It sets problem and machine dependent parameters useful for *_2STAGE and !! related subroutines. !! ILAENV2STAGE returns an INTEGER !! if ILAENV2STAGE >= 0: ILAENV2STAGE returns the value of the parameter !! specified by ISPEC !! if ILAENV2STAGE < 0: if ILAENV2STAGE = -k, the k-th argument had an !! illegal value. !! This version provides a set of parameters which should give good, !! but not optimal, performance on many of the currently available !! computers for the 2-stage solvers. Users are encouraged to modify this !! subroutine to set the tuning parameters for their particular machine using !! the option and problem size information in the arguments. !! This routine will not function correctly if it is converted to all !! lower case. Converting it to all upper case is allowed. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! july 2017 ! Scalar Arguments character(len=*), intent(in) :: name, opts integer(${ik}$), intent(in) :: ispec, n1, n2, n3, n4 ! ===================================================================== ! Local Scalars integer(${ik}$) :: iispec ! Executable Statements go to ( 10, 10, 10, 10, 10 )ispec ! invalid value for ispec stdlib${ii}$_ilaenv2stage = -1 return 10 continue ! 2stage eigenvalues and svd or related subroutines. iispec = 16 + ispec stdlib${ii}$_ilaenv2stage = stdlib${ii}$_iparam2stage( iispec, name, opts,n1, n2, n3, n4 ) return end function stdlib${ii}$_ilaenv2stage #:endfor !---------------------------------------------------------------------------- !----- ----- !----- AUXILIARY INFO HANDLING FUNCTIONS FOR LAPACK SUBROUTINES ----- !----- ----- !---------------------------------------------------------------------------- ! Cholesky factorization elemental subroutine handle_potrf_info(this,info,triangle,lda,n,err) character(len=*), intent(in) :: this character, intent(in) :: triangle integer(ilp), intent(in) :: info,lda,n type(linalg_state_type), intent(out) :: err ! Process output select case (info) case (0) ! Success case (-1) err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'invalid triangle selection: ', & triangle,'. should be U/L') case (-2) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size n=',n) case (-4) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid lda=',lda,': is < n = ',n) case (1:) err = linalg_state_type(this,LINALG_ERROR,'cannot complete factorization:',info, & '-th order leading minor is not positive definite') case default err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'catastrophic error') end select end subroutine handle_potrf_info elemental subroutine handle_getri_info(this,info,lda,n,err) character(len=*), intent(in) :: this integer(ilp), intent(in) :: info,lda,n type(linalg_state_type), intent(out) :: err ! Process output select case (info) case (0) ! Success case (:-1) err = linalg_state_type(this,LINALG_ERROR,'invalid matrix size a=',[lda,n]) case (1:) ! Matrix is singular err = linalg_state_type(this,LINALG_ERROR,'singular matrix') case default err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'catastrophic error') end select end subroutine handle_getri_info elemental subroutine handle_gesdd_info(this,err,info,m,n) character(len=*), intent(in) :: this !> Error handler type(linalg_state_type), intent(inout) :: err !> GESDD return flag integer(ilp), intent(in) :: info !> Input matrix size integer(ilp), intent(in) :: m,n select case (info) case (0) ! Success! err%state = LINALG_SUCCESS case (-1) err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Invalid task ID on input to GESDD.') case (-5,-3:-2) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size: a=',[m,n]) case (-8) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix U size, with a=',[m,n]) case (-10) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix V size, with a=',[m,n]) case (-4) err = linalg_state_type(this,LINALG_VALUE_ERROR,'A contains invalid/NaN values.') case (1:) err = linalg_state_type(this,LINALG_ERROR,'SVD computation did not converge.') case default err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Unknown error returned by GESDD.') end select end subroutine handle_gesdd_info elemental subroutine handle_gesv_info(this,info,lda,n,nrhs,err) character(len=*), intent(in) :: this integer(ilp), intent(in) :: info,lda,n,nrhs type(linalg_state_type), intent(out) :: err ! Process output select case (info) case (0) ! Success case (-1) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid problem size n=',n) case (-2) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid rhs size n=',nrhs) case (-4) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size a=',[lda,n]) case (-7) err = linalg_state_type(this,LINALG_ERROR,'invalid matrix size a=',[lda,n]) case (1:) err = linalg_state_type(this,LINALG_ERROR,'singular matrix') case default err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'catastrophic error') end select end subroutine handle_gesv_info !> Wrapper function to handle GEES error codes elemental subroutine handle_gees_info(this, info, m, n, ldvs, err) character(len=*), intent(in) :: this integer(ilp), intent(in) :: info, m, n, ldvs type(linalg_state_type), intent(out) :: err ! Process GEES output select case (info) case (0_ilp) ! Success case (-1_ilp) ! Vector not wanted, but task is wrong err = linalg_state_type(this, LINALG_INTERNAL_ERROR,'Invalid Schur vector task request') case (-2_ilp) ! Vector not wanted, but task is wrong err = linalg_state_type(this, LINALG_INTERNAL_ERROR,'Invalid sorting task request') case (-4_ilp,-6_ilp) ! Vector not wanted, but task is wrong err = linalg_state_type(this, LINALG_VALUE_ERROR,'Invalid/non-square input matrix size:',[m,n]) case (-11_ilp) err = linalg_state_type(this, LINALG_VALUE_ERROR,'Schur vector matrix has insufficient size',[ldvs,n]) case (-13_ilp) err = linalg_state_type(this, LINALG_INTERNAL_ERROR,'Insufficient working storage size') case (1_ilp:) if (info==n+2) then err = linalg_state_type(this, LINALG_ERROR, 'Ill-conditioned problem: could not sort eigenvalues') elseif (info==n+1) then err = linalg_state_type(this, LINALG_ERROR, 'Some selected eigenvalues lost property due to sorting') elseif (info==n) then err = linalg_state_type(this, LINALG_ERROR, 'Convergence failure: no converged eigenvalues') else err = linalg_state_type(this, LINALG_ERROR, 'Convergence failure; converged range is',[info,n]) end if case default err = linalg_state_type(this, LINALG_INTERNAL_ERROR, 'GEES catastrophic error: info=', info) end select end subroutine handle_gees_info elemental subroutine handle_geqrf_info(this,info,m,n,lwork,err) character(len=*), intent(in) :: this integer(ilp), intent(in) :: info,m,n,lwork type(linalg_state_type), intent(out) :: err ! Process output select case (info) case (0) ! Success case (-1) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size m=',m) case (-2) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size n=',n) case (-4) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size a=',[m,n]) case (-7) err = linalg_state_type(this,LINALG_ERROR,'invalid input for lwork=',lwork) case default err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'catastrophic error') end select end subroutine handle_geqrf_info elemental subroutine handle_geqp3_info(this, info, m, n, lwork, err) character(len=*), intent(in) :: this integer(ilp), intent(in) :: info, m, n, lwork type(linalg_state_type), intent(out) :: err ! Process output select case (info) case(0) ! Success case(-1) err = linalg_state_type(this, LINALG_VALUE_ERROR, 'invalid matrix size m=', m) case(-2) err = linalg_state_type(this, LINALG_VALUE_ERROR, 'invalid matrix size n=', n) case(-4) err = linalg_state_type(this, LINALG_VALUE_ERROR, 'invalid matrix shape a=', [m, n]) case(-7) err = linalg_state_type(this, LINALG_VALUE_ERROR, 'invalid input for lwork=', lwork) case default err = linalg_state_type(this, LINALG_INTERNAL_ERROR, 'catastrophic error') end select end subroutine handle_geqp3_info elemental subroutine handle_orgqr_info(this,info,m,n,k,lwork,err) character(len=*), intent(in) :: this integer(ilp), intent(in) :: info,m,n,k,lwork type(linalg_state_type), intent(out) :: err ! Process output select case (info) case (0) ! Success case (-1) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size m=',m) case (-2) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size n=',n) case (-4) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid k=min(m,n)=',k) case (-5) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size a=',[m,n]) case (-8) err = linalg_state_type(this,LINALG_ERROR,'invalid input for lwork=',lwork) case default err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'catastrophic error') end select end subroutine handle_orgqr_info elemental subroutine handle_gelsd_info(this,info,lda,n,ldb,nrhs,err) character(len=*), intent(in) :: this integer(ilp), intent(in) :: info,lda,n,ldb,nrhs type(linalg_state_type), intent(out) :: err ! Process output select case (info) case (0) ! Success case (:-1) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid problem size a=',[lda,n], & ', b=',[ldb,nrhs]) case (1:) err = linalg_state_type(this,LINALG_ERROR,'SVD did not converge.') case default err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'catastrophic error') end select end subroutine handle_gelsd_info !> Process GEEV output flags pure subroutine handle_geev_info(this,err,info,shapea) character(len=*), intent(in) :: this !> Error handler type(linalg_state_type), intent(inout) :: err !> GEEV return flag integer(ilp), intent(in) :: info !> Input matrix size integer(ilp), intent(in) :: shapea(2) select case (info) case (0) ! Success! err%state = LINALG_SUCCESS case (-1) err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Invalid task ID: left eigenvectors.') case (-2) err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Invalid task ID: right eigenvectors.') case (-5,-3) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size: a=',shapea) case (-9) err = linalg_state_type(this,LINALG_VALUE_ERROR,'insufficient left vector matrix size.') case (-11) err = linalg_state_type(this,LINALG_VALUE_ERROR,'insufficient right vector matrix size.') case (-13) err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Insufficient work array size.') case (1:) err = linalg_state_type(this,LINALG_ERROR,'Eigenvalue computation did not converge.') case default err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Unknown error returned by geev.') end select end subroutine handle_geev_info !> Process GGEV output flags pure subroutine handle_ggev_info(this,err,info,shapea,shapeb) character(len=*), intent(in) :: this !> Error handler type(linalg_state_type), intent(inout) :: err !> GEEV return flag integer(ilp), intent(in) :: info !> Input matrix size integer(ilp), intent(in) :: shapea(2),shapeb(2) select case (info) case (0) ! Success! err%state = LINALG_SUCCESS case (-1) err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Invalid task ID: left eigenvectors.') case (-2) err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Invalid task ID: right eigenvectors.') case (-5,-3) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size: a=',shapea) case (-7) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size: b=',shapeb) case (-12) err = linalg_state_type(this,LINALG_VALUE_ERROR,'insufficient left vector matrix size.') case (-14) err = linalg_state_type(this,LINALG_VALUE_ERROR,'insufficient right vector matrix size.') case (-16) err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Insufficient work array size.') case (1:) err = linalg_state_type(this,LINALG_ERROR,'Eigenvalue computation did not converge.') case default err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Unknown error returned by ggev.') end select end subroutine handle_ggev_info !> Process SYEV/HEEV output flags elemental subroutine handle_heev_info(this,err,info,m,n) character(len=*), intent(in) :: this !> Error handler type(linalg_state_type), intent(inout) :: err !> SYEV/HEEV return flag integer(ilp), intent(in) :: info !> Input matrix size integer(ilp), intent(in) :: m,n select case (info) case (0) ! Success! err%state = LINALG_SUCCESS case (-1) err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Invalid eigenvector request.') case (-2) err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Invalid triangular section request.') case (-5,-3) err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size: a=',[m,n]) case (-8) err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'insufficient workspace size.') case (1:) err = linalg_state_type(this,LINALG_ERROR,'Eigenvalue computation did not converge.') case default err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Unknown error returned by syev/heev.') end select end subroutine handle_heev_info elemental subroutine handle_gglse_info(this, info, m, n, p, err) character(len=*), intent(in) :: this integer(ilp), intent(in) :: info, m, n, p type(linalg_state_type), intent(out) :: err ! Process output. select case (info) case(2) err = linalg_state_type(this, LINALG_ERROR, "rank([A, B]) < n, the least-squares solution cannot be computed.") case(1) err = linalg_state_type(this, LINALG_ERROR, "rank(C) < p, the least-squares solution cannot be computed.") case(0) ! Success. err%state = LINALG_SUCCESS case(-1) err = linalg_state_type(this, LINALG_VALUE_ERROR, 'Invalid number of rows for A, m=', m) case(-2) err = linalg_state_type(this, LINALG_VALUE_ERROR, 'Invalid number of columns for A and C, n=', n) case(-3) err = linalg_state_type(this, LINALG_VALUE_ERROR, 'Invalid number of rows for C, p=', p) case default err = linalg_state_type(this, LINALG_INTERNAL_ERROR, 'catastrophic error.') end select end subroutine handle_gglse_info end module stdlib_linalg_lapack_aux fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_lsq_aux.fypp0000664000175000017500000107466715135654166025465 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_lsq_aux implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slaic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! SLAIC1 applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then SLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**T gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**T and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ alpha ] !! [ gamma ] !! where alpha = x**T*w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(sp), intent(out) :: c, s, sestpr real(sp), intent(in) :: gamma, sest ! Array Arguments real(sp), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(sp) :: absalp, absest, absgam, alpha, b, cosine, eps, norma, s1, s2, sine, t, & test, tmp, zeta1, zeta2 ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_slamch( 'EPSILON' ) alpha = stdlib${ii}$_sdot( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 s = sqrt( one+tmp*tmp ) sestpr = s2*s c = ( gamma / s2 ) / s s = sign( one, alpha ) / s else tmp = s2 / s1 c = sqrt( one+tmp*tmp ) sestpr = s1*c s = ( alpha / s1 ) / c c = sign( one, gamma ) / c end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = c / ( b+sqrt( b*b+c ) ) else t = sqrt( b*b+c ) - b end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -gamma cosine = alpha end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 c = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / c ) s = -( gamma / s2 ) / c c = sign( one, alpha ) / c else tmp = s2 / s1 s = sqrt( one+tmp*tmp ) sestpr = absest / s c = ( alpha / s1 ) / s s = -sign( one, gamma ) / s end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest norma = max( one+zeta1*zeta1+abs( zeta1*zeta2 ),abs( zeta1*zeta2 )+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = c / ( b+sqrt( abs( b*b-c ) ) ) sine = zeta1 / ( one-t ) cosine = -zeta2 / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = -c / ( b+sqrt( b*b+c ) ) else t = b - sqrt( b*b+c ) end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_slaic1 pure module subroutine stdlib${ii}$_dlaic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! DLAIC1 applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then DLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**T gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**T and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ alpha ] !! [ gamma ] !! where alpha = x**T*w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(dp), intent(out) :: c, s, sestpr real(dp), intent(in) :: gamma, sest ! Array Arguments real(dp), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(dp) :: absalp, absest, absgam, alpha, b, cosine, eps, norma, s1, s2, sine, t, & test, tmp, zeta1, zeta2 ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_dlamch( 'EPSILON' ) alpha = stdlib${ii}$_ddot( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 s = sqrt( one+tmp*tmp ) sestpr = s2*s c = ( gamma / s2 ) / s s = sign( one, alpha ) / s else tmp = s2 / s1 c = sqrt( one+tmp*tmp ) sestpr = s1*c s = ( alpha / s1 ) / c c = sign( one, gamma ) / c end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = c / ( b+sqrt( b*b+c ) ) else t = sqrt( b*b+c ) - b end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -gamma cosine = alpha end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 c = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / c ) s = -( gamma / s2 ) / c c = sign( one, alpha ) / c else tmp = s2 / s1 s = sqrt( one+tmp*tmp ) sestpr = absest / s c = ( alpha / s1 ) / s s = -sign( one, gamma ) / s end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest norma = max( one+zeta1*zeta1+abs( zeta1*zeta2 ),abs( zeta1*zeta2 )+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = c / ( b+sqrt( abs( b*b-c ) ) ) sine = zeta1 / ( one-t ) cosine = -zeta2 / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = -c / ( b+sqrt( b*b+c ) ) else t = b - sqrt( b*b+c ) end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_dlaic1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! DLAIC1: applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then DLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**T gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**T and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ alpha ] !! [ gamma ] !! where alpha = x**T*w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(${rk}$), intent(out) :: c, s, sestpr real(${rk}$), intent(in) :: gamma, sest ! Array Arguments real(${rk}$), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(${rk}$) :: absalp, absest, absgam, alpha, b, cosine, eps, norma, s1, s2, sine, t, & test, tmp, zeta1, zeta2 ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_${ri}$lamch( 'EPSILON' ) alpha = stdlib${ii}$_${ri}$dot( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 s = sqrt( one+tmp*tmp ) sestpr = s2*s c = ( gamma / s2 ) / s s = sign( one, alpha ) / s else tmp = s2 / s1 c = sqrt( one+tmp*tmp ) sestpr = s1*c s = ( alpha / s1 ) / c c = sign( one, gamma ) / c end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = c / ( b+sqrt( b*b+c ) ) else t = sqrt( b*b+c ) - b end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -gamma cosine = alpha end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 c = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / c ) s = -( gamma / s2 ) / c c = sign( one, alpha ) / c else tmp = s2 / s1 s = sqrt( one+tmp*tmp ) sestpr = absest / s c = ( alpha / s1 ) / s s = -sign( one, gamma ) / s end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest norma = max( one+zeta1*zeta1+abs( zeta1*zeta2 ),abs( zeta1*zeta2 )+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = c / ( b+sqrt( abs( b*b-c ) ) ) sine = zeta1 / ( one-t ) cosine = -zeta2 / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = -c / ( b+sqrt( b*b+c ) ) else t = b - sqrt( b*b+c ) end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_${ri}$laic1 #:endif #:endfor pure module subroutine stdlib${ii}$_claic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! CLAIC1 applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then CLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**H gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**H and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ conjg(alpha) ] !! [ conjg(gamma) ] !! where alpha = x**H*w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(sp), intent(in) :: sest real(sp), intent(out) :: sestpr complex(sp), intent(out) :: c, s complex(sp), intent(in) :: gamma ! Array Arguments complex(sp), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(sp) :: absalp, absest, absgam, b, eps, norma, s1, s2, scl, t, test, tmp, zeta1, & zeta2 complex(sp) :: alpha, cosine, sine ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_slamch( 'EPSILON' ) alpha = stdlib${ii}$_cdotc( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=sp) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = s2*scl s = ( alpha / s2 ) / scl c = ( gamma / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = s1*scl s = ( alpha / s1 ) / scl c = ( gamma / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = real( c / ( b+sqrt( b*b+c ) ),KIND=sp) else t = real( sqrt( b*b+c ) - b,KIND=sp) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=sp) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -conjg( gamma ) cosine = conjg( alpha ) end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=sp) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / scl ) s = -( conjg( gamma ) / s2 ) / scl c = ( conjg( alpha ) / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = absest / scl s = -( conjg( gamma ) / s1 ) / scl c = ( conjg( alpha ) / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest norma = max( one+zeta1*zeta1+zeta1*zeta2,zeta1*zeta2+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = real( c / ( b+sqrt( abs( b*b-c ) ) ),KIND=sp) sine = ( alpha / absest ) / ( one-t ) cosine = -( gamma / absest ) / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = real( -c / ( b+sqrt( b*b+c ) ),KIND=sp) else t = real( b - sqrt( b*b+c ),KIND=sp) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=sp) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_claic1 pure module subroutine stdlib${ii}$_zlaic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! ZLAIC1 applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then ZLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**H gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**H and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ conjg(alpha) ] !! [ conjg(gamma) ] !! where alpha = x**H * w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(dp), intent(in) :: sest real(dp), intent(out) :: sestpr complex(dp), intent(out) :: c, s complex(dp), intent(in) :: gamma ! Array Arguments complex(dp), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(dp) :: absalp, absest, absgam, b, eps, norma, s1, s2, scl, t, test, tmp, zeta1, & zeta2 complex(dp) :: alpha, cosine, sine ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_dlamch( 'EPSILON' ) alpha = stdlib${ii}$_zdotc( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=dp) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = s2*scl s = ( alpha / s2 ) / scl c = ( gamma / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = s1*scl s = ( alpha / s1 ) / scl c = ( gamma / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = real( c / ( b+sqrt( b*b+c ) ),KIND=dp) else t = real( sqrt( b*b+c ) - b,KIND=dp) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=dp) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -conjg( gamma ) cosine = conjg( alpha ) end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=dp) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / scl ) s = -( conjg( gamma ) / s2 ) / scl c = ( conjg( alpha ) / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = absest / scl s = -( conjg( gamma ) / s1 ) / scl c = ( conjg( alpha ) / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest norma = max( one+zeta1*zeta1+zeta1*zeta2,zeta1*zeta2+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = real( c / ( b+sqrt( abs( b*b-c ) ) ),KIND=dp) sine = ( alpha / absest ) / ( one-t ) cosine = -( gamma / absest ) / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = -c / ( b+sqrt( b*b+c ) ) else t = b - sqrt( b*b+c ) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=dp) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_zlaic1 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! ZLAIC1: applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then ZLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**H gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**H and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ conjg(alpha) ] !! [ conjg(gamma) ] !! where alpha = x**H * w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(${ck}$), intent(in) :: sest real(${ck}$), intent(out) :: sestpr complex(${ck}$), intent(out) :: c, s complex(${ck}$), intent(in) :: gamma ! Array Arguments complex(${ck}$), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(${ck}$) :: absalp, absest, absgam, b, eps, norma, s1, s2, scl, t, test, tmp, zeta1, & zeta2 complex(${ck}$) :: alpha, cosine, sine ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'EPSILON' ) alpha = stdlib${ii}$_${ci}$dotc( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=${ck}$) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = s2*scl s = ( alpha / s2 ) / scl c = ( gamma / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = s1*scl s = ( alpha / s1 ) / scl c = ( gamma / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = real( c / ( b+sqrt( b*b+c ) ),KIND=${ck}$) else t = real( sqrt( b*b+c ) - b,KIND=${ck}$) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=${ck}$) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -conjg( gamma ) cosine = conjg( alpha ) end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=${ck}$) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / scl ) s = -( conjg( gamma ) / s2 ) / scl c = ( conjg( alpha ) / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = absest / scl s = -( conjg( gamma ) / s1 ) / scl c = ( conjg( alpha ) / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest norma = max( one+zeta1*zeta1+zeta1*zeta2,zeta1*zeta2+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = real( c / ( b+sqrt( abs( b*b-c ) ) ),KIND=${ck}$) sine = ( alpha / absest ) / ( one-t ) cosine = -( gamma / absest ) / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = -c / ( b+sqrt( b*b+c ) ) else t = b - sqrt( b*b+c ) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=${ck}$) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_${ci}$laic1 #:endif #:endfor pure module subroutine stdlib${ii}$_slals0( icompq, nl, nr, sqre, nrhs, b, ldb, bx, ldbx,perm, givptr, & !! SLALS0 applies back the multiplying factors of either the left or the !! right singular vector matrix of a diagonal matrix appended by a row !! to the right hand side matrix B in solving the least squares problem !! using the divide-and-conquer SVD approach. !! For the left singular vector matrix, three types of orthogonal !! matrices are involved: !! (1L) Givens rotations: the number of such rotations is GIVPTR; the !! pairs of columns/rows they were applied to are stored in GIVCOL; !! and the C- and S-values of these rotations are stored in GIVNUM. !! (2L) Permutation. The (NL+1)-st row of B is to be moved to the first !! row, and for J=2:N, PERM(J)-th row of B is to be moved to the !! J-th row. !! (3L) The left singular vector matrix of the remaining matrix. !! For the right singular vector matrix, four types of orthogonal !! matrices are involved: !! (1R) The right singular vector matrix of the remaining matrix. !! (2R) If SQRE = 1, one extra Givens rotation to generate the right !! null space. !! (3R) The inverse transformation of (2L). !! (4R) The inverse transformation of (1L). givcol, ldgcol, givnum, ldgnum,poles, difl, difr, z, k, c, s, work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: givptr, icompq, k, ldb, ldbx, ldgcol, ldgnum, nl, nr, nrhs,& sqre integer(${ik}$), intent(out) :: info real(sp), intent(in) :: c, s ! Array Arguments integer(${ik}$), intent(in) :: givcol(ldgcol,*), perm(*) real(sp), intent(inout) :: b(ldb,*) real(sp), intent(out) :: bx(ldbx,*), work(*) real(sp), intent(in) :: difl(*), difr(ldgnum,*), givnum(ldgnum,*), poles(ldgnum,*), z(& *) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, m, n, nlp1 real(sp) :: diflj, difrj, dj, dsigj, dsigjp, temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb1_${ik}$ ) ) then info = -1_${ik}$ else if( smlsiz<3_${ik}$ ) then info = -2_${ik}$ else if( n1_${ik}$ ) ) then info = -1_${ik}$ else if( smlsiz<3_${ik}$ ) then info = -2_${ik}$ else if( n1_${ik}$ ) ) then info = -1_${ik}$ else if( smlsiz<3_${ik}$ ) then info = -2_${ik}$ else if( n1_${ik}$ ) ) then info = -1_${ik}$ else if( smlsiz<3_${ik}$ ) then info = -2_${ik}$ else if( n1_${ik}$ ) ) then info = -1_${ik}$ else if( smlsiz<3_${ik}$ ) then info = -2_${ik}$ else if( n1_${ik}$ ) ) then info = -1_${ik}$ else if( smlsiz<3_${ik}$ ) then info = -2_${ik}$ else if( n=one ) ) then rcnd = eps else rcnd = rcond end if rank = 0_${ik}$ ! quick return if possible. if( n==0_${ik}$ ) then return else if( n==1_${ik}$ ) then if( d( 1_${ik}$ )==zero ) then call stdlib${ii}$_slaset( 'A', 1_${ik}$, nrhs, zero, zero, b, ldb ) else rank = 1_${ik}$ call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, d( 1_${ik}$ ), one, 1_${ik}$, nrhs, b, ldb, info ) d( 1_${ik}$ ) = abs( d( 1_${ik}$ ) ) end if return end if ! rotate the matrix if it is lower bidiagonal. if( uplo=='L' ) then do i = 1, n - 1 call stdlib${ii}$_slartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( nrhs==1_${ik}$ ) then call stdlib${ii}$_srot( 1_${ik}$, b( i, 1_${ik}$ ), 1_${ik}$, b( i+1, 1_${ik}$ ), 1_${ik}$, cs, sn ) else work( i*2_${ik}$-1 ) = cs work( i*2_${ik}$ ) = sn end if end do if( nrhs>1_${ik}$ ) then do i = 1, nrhs do j = 1, n - 1 cs = work( j*2_${ik}$-1 ) sn = work( j*2_${ik}$ ) call stdlib${ii}$_srot( 1_${ik}$, b( j, i ), 1_${ik}$, b( j+1, i ), 1_${ik}$, cs, sn ) end do end do end if end if ! scale. nm1 = n - 1_${ik}$ orgnrm = stdlib${ii}$_slanst( 'M', n, d, e ) if( orgnrm==zero ) then call stdlib${ii}$_slaset( 'A', n, nrhs, zero, zero, b, ldb ) return end if call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, nm1, 1_${ik}$, e, nm1, info ) ! if n is smaller than the minimum divide size smlsiz, then solve ! the problem with another solver. if( n<=smlsiz ) then nwork = 1_${ik}$ + n*n call stdlib${ii}$_slaset( 'A', n, n, zero, one, work, n ) call stdlib${ii}$_slasdq( 'U', 0_${ik}$, n, n, 0_${ik}$, nrhs, d, e, work, n, work, n, b,ldb, work( & nwork ), info ) if( info/=0_${ik}$ ) then return end if tol = rcnd*abs( d( stdlib${ii}$_isamax( n, d, 1_${ik}$ ) ) ) do i = 1, n if( d( i )<=tol ) then call stdlib${ii}$_slaset( 'A', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) else call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs, b( i, 1_${ik}$ ),ldb, info ) rank = rank + 1_${ik}$ end if end do call stdlib${ii}$_sgemm( 'T', 'N', n, nrhs, n, one, work, n, b, ldb, zero,work( nwork ), & n ) call stdlib${ii}$_slacpy( 'A', n, nrhs, work( nwork ), n, b, ldb ) ! unscale. call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_slasrt( 'D', n, d, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end if ! book-keeping and setting up some constants. nlvl = int( log( real( n,KIND=sp) / real( smlsiz+1,KIND=sp) ) / log( two ),KIND=${ik}$) + & 1_${ik}$ smlszp = smlsiz + 1_${ik}$ u = 1_${ik}$ vt = 1_${ik}$ + smlsiz*n difl = vt + smlszp*n difr = difl + nlvl*n z = difr + nlvl*n*2_${ik}$ c = z + nlvl*n s = c + n poles = s + n givnum = poles + 2_${ik}$*nlvl*n bx = givnum + 2_${ik}$*nlvl*n nwork = bx + n*nrhs sizei = 1_${ik}$ + n k = sizei + n givptr = k + n perm = givptr + n givcol = perm + nlvl*n iwk = givcol + nlvl*n*2_${ik}$ st = 1_${ik}$ sqre = 0_${ik}$ icmpq1 = 1_${ik}$ icmpq2 = 0_${ik}$ nsub = 0_${ik}$ do i = 1, n if( abs( d( i ) )=eps ) then ! a subproblem with e(nm1) not too small but i = nm1. nsize = n - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize else ! a subproblem with e(nm1) small. this implies an ! 1-by-1 subproblem at d(n), which is not solved ! explicitly. nsize = i - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize nsub = nsub + 1_${ik}$ iwork( nsub ) = n iwork( sizei+nsub-1 ) = 1_${ik}$ call stdlib${ii}$_scopy( nrhs, b( n, 1_${ik}$ ), ldb, work( bx+nm1 ), n ) end if st1 = st - 1_${ik}$ if( nsize==1_${ik}$ ) then ! this is a 1-by-1 subproblem and is not solved ! explicitly. call stdlib${ii}$_scopy( nrhs, b( st, 1_${ik}$ ), ldb, work( bx+st1 ), n ) else if( nsize<=smlsiz ) then ! this is a small subproblem and is solved by stdlib${ii}$_slasdq. call stdlib${ii}$_slaset( 'A', nsize, nsize, zero, one,work( vt+st1 ), n ) call stdlib${ii}$_slasdq( 'U', 0_${ik}$, nsize, nsize, 0_${ik}$, nrhs, d( st ),e( st ), work( vt+& st1 ), n, work( nwork ),n, b( st, 1_${ik}$ ), ldb, work( nwork ), info ) if( info/=0_${ik}$ ) then return end if call stdlib${ii}$_slacpy( 'A', nsize, nrhs, b( st, 1_${ik}$ ), ldb,work( bx+st1 ), n ) else ! a large problem. solve it using divide and conquer. call stdlib${ii}$_slasda( icmpq1, smlsiz, nsize, sqre, d( st ),e( st ), work( u+st1 & ), n, work( vt+st1 ),iwork( k+st1 ), work( difl+st1 ),work( difr+st1 ), work( & z+st1 ),work( poles+st1 ), iwork( givptr+st1 ),iwork( givcol+st1 ), n, iwork( & perm+st1 ),work( givnum+st1 ), work( c+st1 ),work( s+st1 ), work( nwork ), & iwork( iwk ),info ) if( info/=0_${ik}$ ) then return end if bxst = bx + st1 call stdlib${ii}$_slalsa( icmpq2, smlsiz, nsize, nrhs, b( st, 1_${ik}$ ),ldb, work( bxst ),& n, work( u+st1 ), n,work( vt+st1 ), iwork( k+st1 ),work( difl+st1 ), work( & difr+st1 ),work( z+st1 ), work( poles+st1 ),iwork( givptr+st1 ), iwork( & givcol+st1 ), n,iwork( perm+st1 ), work( givnum+st1 ),work( c+st1 ), work( s+& st1 ), work( nwork ),iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if st = i + 1_${ik}$ end if end do loop_60 ! apply the singular values and treat the tiny ones as zero. tol = rcnd*abs( d( stdlib${ii}$_isamax( n, d, 1_${ik}$ ) ) ) do i = 1, n ! some of the elements in d can be negative because 1-by-1 ! subproblems were not solved explicitly. if( abs( d( i ) )<=tol ) then call stdlib${ii}$_slaset( 'A', 1_${ik}$, nrhs, zero, zero, work( bx+i-1 ), n ) else rank = rank + 1_${ik}$ call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs,work( bx+i-1 ), n, info ) end if d( i ) = abs( d( i ) ) end do ! now apply back the right singular vectors. icmpq2 = 1_${ik}$ do i = 1, nsub st = iwork( i ) st1 = st - 1_${ik}$ nsize = iwork( sizei+i-1 ) bxst = bx + st1 if( nsize==1_${ik}$ ) then call stdlib${ii}$_scopy( nrhs, work( bxst ), n, b( st, 1_${ik}$ ), ldb ) else if( nsize<=smlsiz ) then call stdlib${ii}$_sgemm( 'T', 'N', nsize, nrhs, nsize, one,work( vt+st1 ), n, work( & bxst ), n, zero,b( st, 1_${ik}$ ), ldb ) else call stdlib${ii}$_slalsa( icmpq2, smlsiz, nsize, nrhs, work( bxst ), n,b( st, 1_${ik}$ ), ldb,& work( u+st1 ), n,work( vt+st1 ), iwork( k+st1 ),work( difl+st1 ), work( difr+& st1 ),work( z+st1 ), work( poles+st1 ),iwork( givptr+st1 ), iwork( givcol+st1 ),& n,iwork( perm+st1 ), work( givnum+st1 ),work( c+st1 ), work( s+st1 ), work( & nwork ),iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if end do ! unscale and sort the singular values. call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_slasrt( 'D', n, d, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end subroutine stdlib${ii}$_slalsd pure module subroutine stdlib${ii}$_dlalsd( uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond,rank, work, iwork, & !! DLALSD uses the singular value decomposition of A to solve the least !! squares problem of finding X to minimize the Euclidean norm of each !! column of A*X-B, where A is N-by-N upper bidiagonal, and X and B !! are N-by-NRHS. The solution X overwrites B. !! The singular values of A smaller than RCOND times the largest !! singular value are treated as zero in solving the least squares !! problem; in this case a minimum norm solution is returned. !! The actual singular values are returned in D in ascending order. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: ldb, n, nrhs, smlsiz real(dp), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: b(ldb,*), d(*), e(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: bx, bxst, c, difl, difr, givcol, givnum, givptr, i, icmpq1, icmpq2, & iwk, j, k, nlvl, nm1, nsize, nsub, nwork, perm, poles, s, sizei, smlszp, sqre, st, st1,& u, vt, z real(dp) :: cs, eps, orgnrm, r, rcnd, sn, tol ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<1_${ik}$ ) then info = -4_${ik}$ else if( ( ldb<1_${ik}$ ) .or. ( ldb=one ) ) then rcnd = eps else rcnd = rcond end if rank = 0_${ik}$ ! quick return if possible. if( n==0_${ik}$ ) then return else if( n==1_${ik}$ ) then if( d( 1_${ik}$ )==zero ) then call stdlib${ii}$_dlaset( 'A', 1_${ik}$, nrhs, zero, zero, b, ldb ) else rank = 1_${ik}$ call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, d( 1_${ik}$ ), one, 1_${ik}$, nrhs, b, ldb, info ) d( 1_${ik}$ ) = abs( d( 1_${ik}$ ) ) end if return end if ! rotate the matrix if it is lower bidiagonal. if( uplo=='L' ) then do i = 1, n - 1 call stdlib${ii}$_dlartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( nrhs==1_${ik}$ ) then call stdlib${ii}$_drot( 1_${ik}$, b( i, 1_${ik}$ ), 1_${ik}$, b( i+1, 1_${ik}$ ), 1_${ik}$, cs, sn ) else work( i*2_${ik}$-1 ) = cs work( i*2_${ik}$ ) = sn end if end do if( nrhs>1_${ik}$ ) then do i = 1, nrhs do j = 1, n - 1 cs = work( j*2_${ik}$-1 ) sn = work( j*2_${ik}$ ) call stdlib${ii}$_drot( 1_${ik}$, b( j, i ), 1_${ik}$, b( j+1, i ), 1_${ik}$, cs, sn ) end do end do end if end if ! scale. nm1 = n - 1_${ik}$ orgnrm = stdlib${ii}$_dlanst( 'M', n, d, e ) if( orgnrm==zero ) then call stdlib${ii}$_dlaset( 'A', n, nrhs, zero, zero, b, ldb ) return end if call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, nm1, 1_${ik}$, e, nm1, info ) ! if n is smaller than the minimum divide size smlsiz, then solve ! the problem with another solver. if( n<=smlsiz ) then nwork = 1_${ik}$ + n*n call stdlib${ii}$_dlaset( 'A', n, n, zero, one, work, n ) call stdlib${ii}$_dlasdq( 'U', 0_${ik}$, n, n, 0_${ik}$, nrhs, d, e, work, n, work, n, b,ldb, work( & nwork ), info ) if( info/=0_${ik}$ ) then return end if tol = rcnd*abs( d( stdlib${ii}$_idamax( n, d, 1_${ik}$ ) ) ) do i = 1, n if( d( i )<=tol ) then call stdlib${ii}$_dlaset( 'A', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) else call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs, b( i, 1_${ik}$ ),ldb, info ) rank = rank + 1_${ik}$ end if end do call stdlib${ii}$_dgemm( 'T', 'N', n, nrhs, n, one, work, n, b, ldb, zero,work( nwork ), & n ) call stdlib${ii}$_dlacpy( 'A', n, nrhs, work( nwork ), n, b, ldb ) ! unscale. call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_dlasrt( 'D', n, d, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end if ! book-keeping and setting up some constants. nlvl = int( log( real( n,KIND=dp) / real( smlsiz+1,KIND=dp) ) / log( two ),KIND=${ik}$) + & 1_${ik}$ smlszp = smlsiz + 1_${ik}$ u = 1_${ik}$ vt = 1_${ik}$ + smlsiz*n difl = vt + smlszp*n difr = difl + nlvl*n z = difr + nlvl*n*2_${ik}$ c = z + nlvl*n s = c + n poles = s + n givnum = poles + 2_${ik}$*nlvl*n bx = givnum + 2_${ik}$*nlvl*n nwork = bx + n*nrhs sizei = 1_${ik}$ + n k = sizei + n givptr = k + n perm = givptr + n givcol = perm + nlvl*n iwk = givcol + nlvl*n*2_${ik}$ st = 1_${ik}$ sqre = 0_${ik}$ icmpq1 = 1_${ik}$ icmpq2 = 0_${ik}$ nsub = 0_${ik}$ do i = 1, n if( abs( d( i ) )=eps ) then ! a subproblem with e(nm1) not too small but i = nm1. nsize = n - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize else ! a subproblem with e(nm1) small. this implies an ! 1-by-1 subproblem at d(n), which is not solved ! explicitly. nsize = i - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize nsub = nsub + 1_${ik}$ iwork( nsub ) = n iwork( sizei+nsub-1 ) = 1_${ik}$ call stdlib${ii}$_dcopy( nrhs, b( n, 1_${ik}$ ), ldb, work( bx+nm1 ), n ) end if st1 = st - 1_${ik}$ if( nsize==1_${ik}$ ) then ! this is a 1-by-1 subproblem and is not solved ! explicitly. call stdlib${ii}$_dcopy( nrhs, b( st, 1_${ik}$ ), ldb, work( bx+st1 ), n ) else if( nsize<=smlsiz ) then ! this is a small subproblem and is solved by stdlib${ii}$_dlasdq. call stdlib${ii}$_dlaset( 'A', nsize, nsize, zero, one,work( vt+st1 ), n ) call stdlib${ii}$_dlasdq( 'U', 0_${ik}$, nsize, nsize, 0_${ik}$, nrhs, d( st ),e( st ), work( vt+& st1 ), n, work( nwork ),n, b( st, 1_${ik}$ ), ldb, work( nwork ), info ) if( info/=0_${ik}$ ) then return end if call stdlib${ii}$_dlacpy( 'A', nsize, nrhs, b( st, 1_${ik}$ ), ldb,work( bx+st1 ), n ) else ! a large problem. solve it using divide and conquer. call stdlib${ii}$_dlasda( icmpq1, smlsiz, nsize, sqre, d( st ),e( st ), work( u+st1 & ), n, work( vt+st1 ),iwork( k+st1 ), work( difl+st1 ),work( difr+st1 ), work( & z+st1 ),work( poles+st1 ), iwork( givptr+st1 ),iwork( givcol+st1 ), n, iwork( & perm+st1 ),work( givnum+st1 ), work( c+st1 ),work( s+st1 ), work( nwork ), & iwork( iwk ),info ) if( info/=0_${ik}$ ) then return end if bxst = bx + st1 call stdlib${ii}$_dlalsa( icmpq2, smlsiz, nsize, nrhs, b( st, 1_${ik}$ ),ldb, work( bxst ),& n, work( u+st1 ), n,work( vt+st1 ), iwork( k+st1 ),work( difl+st1 ), work( & difr+st1 ),work( z+st1 ), work( poles+st1 ),iwork( givptr+st1 ), iwork( & givcol+st1 ), n,iwork( perm+st1 ), work( givnum+st1 ),work( c+st1 ), work( s+& st1 ), work( nwork ),iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if st = i + 1_${ik}$ end if end do loop_60 ! apply the singular values and treat the tiny ones as zero. tol = rcnd*abs( d( stdlib${ii}$_idamax( n, d, 1_${ik}$ ) ) ) do i = 1, n ! some of the elements in d can be negative because 1-by-1 ! subproblems were not solved explicitly. if( abs( d( i ) )<=tol ) then call stdlib${ii}$_dlaset( 'A', 1_${ik}$, nrhs, zero, zero, work( bx+i-1 ), n ) else rank = rank + 1_${ik}$ call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs,work( bx+i-1 ), n, info ) end if d( i ) = abs( d( i ) ) end do ! now apply back the right singular vectors. icmpq2 = 1_${ik}$ do i = 1, nsub st = iwork( i ) st1 = st - 1_${ik}$ nsize = iwork( sizei+i-1 ) bxst = bx + st1 if( nsize==1_${ik}$ ) then call stdlib${ii}$_dcopy( nrhs, work( bxst ), n, b( st, 1_${ik}$ ), ldb ) else if( nsize<=smlsiz ) then call stdlib${ii}$_dgemm( 'T', 'N', nsize, nrhs, nsize, one,work( vt+st1 ), n, work( & bxst ), n, zero,b( st, 1_${ik}$ ), ldb ) else call stdlib${ii}$_dlalsa( icmpq2, smlsiz, nsize, nrhs, work( bxst ), n,b( st, 1_${ik}$ ), ldb,& work( u+st1 ), n,work( vt+st1 ), iwork( k+st1 ),work( difl+st1 ), work( difr+& st1 ),work( z+st1 ), work( poles+st1 ),iwork( givptr+st1 ), iwork( givcol+st1 ),& n,iwork( perm+st1 ), work( givnum+st1 ),work( c+st1 ), work( s+st1 ), work( & nwork ),iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if end do ! unscale and sort the singular values. call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_dlasrt( 'D', n, d, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end subroutine stdlib${ii}$_dlalsd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lalsd( uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond,rank, work, iwork, & !! DLALSD: uses the singular value decomposition of A to solve the least !! squares problem of finding X to minimize the Euclidean norm of each !! column of A*X-B, where A is N-by-N upper bidiagonal, and X and B !! are N-by-NRHS. The solution X overwrites B. !! The singular values of A smaller than RCOND times the largest !! singular value are treated as zero in solving the least squares !! problem; in this case a minimum norm solution is returned. !! The actual singular values are returned in D in ascending order. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: ldb, n, nrhs, smlsiz real(${rk}$), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: b(ldb,*), d(*), e(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: bx, bxst, c, difl, difr, givcol, givnum, givptr, i, icmpq1, icmpq2, & iwk, j, k, nlvl, nm1, nsize, nsub, nwork, perm, poles, s, sizei, smlszp, sqre, st, st1,& u, vt, z real(${rk}$) :: cs, eps, orgnrm, r, rcnd, sn, tol ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<1_${ik}$ ) then info = -4_${ik}$ else if( ( ldb<1_${ik}$ ) .or. ( ldb=one ) ) then rcnd = eps else rcnd = rcond end if rank = 0_${ik}$ ! quick return if possible. if( n==0_${ik}$ ) then return else if( n==1_${ik}$ ) then if( d( 1_${ik}$ )==zero ) then call stdlib${ii}$_${ri}$laset( 'A', 1_${ik}$, nrhs, zero, zero, b, ldb ) else rank = 1_${ik}$ call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, d( 1_${ik}$ ), one, 1_${ik}$, nrhs, b, ldb, info ) d( 1_${ik}$ ) = abs( d( 1_${ik}$ ) ) end if return end if ! rotate the matrix if it is lower bidiagonal. if( uplo=='L' ) then do i = 1, n - 1 call stdlib${ii}$_${ri}$lartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( nrhs==1_${ik}$ ) then call stdlib${ii}$_${ri}$rot( 1_${ik}$, b( i, 1_${ik}$ ), 1_${ik}$, b( i+1, 1_${ik}$ ), 1_${ik}$, cs, sn ) else work( i*2_${ik}$-1 ) = cs work( i*2_${ik}$ ) = sn end if end do if( nrhs>1_${ik}$ ) then do i = 1, nrhs do j = 1, n - 1 cs = work( j*2_${ik}$-1 ) sn = work( j*2_${ik}$ ) call stdlib${ii}$_${ri}$rot( 1_${ik}$, b( j, i ), 1_${ik}$, b( j+1, i ), 1_${ik}$, cs, sn ) end do end do end if end if ! scale. nm1 = n - 1_${ik}$ orgnrm = stdlib${ii}$_${ri}$lanst( 'M', n, d, e ) if( orgnrm==zero ) then call stdlib${ii}$_${ri}$laset( 'A', n, nrhs, zero, zero, b, ldb ) return end if call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, nm1, 1_${ik}$, e, nm1, info ) ! if n is smaller than the minimum divide size smlsiz, then solve ! the problem with another solver. if( n<=smlsiz ) then nwork = 1_${ik}$ + n*n call stdlib${ii}$_${ri}$laset( 'A', n, n, zero, one, work, n ) call stdlib${ii}$_${ri}$lasdq( 'U', 0_${ik}$, n, n, 0_${ik}$, nrhs, d, e, work, n, work, n, b,ldb, work( & nwork ), info ) if( info/=0_${ik}$ ) then return end if tol = rcnd*abs( d( stdlib${ii}$_i${ri}$amax( n, d, 1_${ik}$ ) ) ) do i = 1, n if( d( i )<=tol ) then call stdlib${ii}$_${ri}$laset( 'A', 1_${ik}$, nrhs, zero, zero, b( i, 1_${ik}$ ), ldb ) else call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs, b( i, 1_${ik}$ ),ldb, info ) rank = rank + 1_${ik}$ end if end do call stdlib${ii}$_${ri}$gemm( 'T', 'N', n, nrhs, n, one, work, n, b, ldb, zero,work( nwork ), & n ) call stdlib${ii}$_${ri}$lacpy( 'A', n, nrhs, work( nwork ), n, b, ldb ) ! unscale. call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_${ri}$lasrt( 'D', n, d, info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end if ! book-keeping and setting up some constants. nlvl = int( log( real( n,KIND=${rk}$) / real( smlsiz+1,KIND=${rk}$) ) / log( two ),KIND=${ik}$) + & 1_${ik}$ smlszp = smlsiz + 1_${ik}$ u = 1_${ik}$ vt = 1_${ik}$ + smlsiz*n difl = vt + smlszp*n difr = difl + nlvl*n z = difr + nlvl*n*2_${ik}$ c = z + nlvl*n s = c + n poles = s + n givnum = poles + 2_${ik}$*nlvl*n bx = givnum + 2_${ik}$*nlvl*n nwork = bx + n*nrhs sizei = 1_${ik}$ + n k = sizei + n givptr = k + n perm = givptr + n givcol = perm + nlvl*n iwk = givcol + nlvl*n*2_${ik}$ st = 1_${ik}$ sqre = 0_${ik}$ icmpq1 = 1_${ik}$ icmpq2 = 0_${ik}$ nsub = 0_${ik}$ do i = 1, n if( abs( d( i ) )=eps ) then ! a subproblem with e(nm1) not too small but i = nm1. nsize = n - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize else ! a subproblem with e(nm1) small. this implies an ! 1-by-1 subproblem at d(n), which is not solved ! explicitly. nsize = i - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize nsub = nsub + 1_${ik}$ iwork( nsub ) = n iwork( sizei+nsub-1 ) = 1_${ik}$ call stdlib${ii}$_${ri}$copy( nrhs, b( n, 1_${ik}$ ), ldb, work( bx+nm1 ), n ) end if st1 = st - 1_${ik}$ if( nsize==1_${ik}$ ) then ! this is a 1-by-1 subproblem and is not solved ! explicitly. call stdlib${ii}$_${ri}$copy( nrhs, b( st, 1_${ik}$ ), ldb, work( bx+st1 ), n ) else if( nsize<=smlsiz ) then ! this is a small subproblem and is solved by stdlib${ii}$_${ri}$lasdq. call stdlib${ii}$_${ri}$laset( 'A', nsize, nsize, zero, one,work( vt+st1 ), n ) call stdlib${ii}$_${ri}$lasdq( 'U', 0_${ik}$, nsize, nsize, 0_${ik}$, nrhs, d( st ),e( st ), work( vt+& st1 ), n, work( nwork ),n, b( st, 1_${ik}$ ), ldb, work( nwork ), info ) if( info/=0_${ik}$ ) then return end if call stdlib${ii}$_${ri}$lacpy( 'A', nsize, nrhs, b( st, 1_${ik}$ ), ldb,work( bx+st1 ), n ) else ! a large problem. solve it using divide and conquer. call stdlib${ii}$_${ri}$lasda( icmpq1, smlsiz, nsize, sqre, d( st ),e( st ), work( u+st1 & ), n, work( vt+st1 ),iwork( k+st1 ), work( difl+st1 ),work( difr+st1 ), work( & z+st1 ),work( poles+st1 ), iwork( givptr+st1 ),iwork( givcol+st1 ), n, iwork( & perm+st1 ),work( givnum+st1 ), work( c+st1 ),work( s+st1 ), work( nwork ), & iwork( iwk ),info ) if( info/=0_${ik}$ ) then return end if bxst = bx + st1 call stdlib${ii}$_${ri}$lalsa( icmpq2, smlsiz, nsize, nrhs, b( st, 1_${ik}$ ),ldb, work( bxst ),& n, work( u+st1 ), n,work( vt+st1 ), iwork( k+st1 ),work( difl+st1 ), work( & difr+st1 ),work( z+st1 ), work( poles+st1 ),iwork( givptr+st1 ), iwork( & givcol+st1 ), n,iwork( perm+st1 ), work( givnum+st1 ),work( c+st1 ), work( s+& st1 ), work( nwork ),iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if st = i + 1_${ik}$ end if end do loop_60 ! apply the singular values and treat the tiny ones as zero. tol = rcnd*abs( d( stdlib${ii}$_i${ri}$amax( n, d, 1_${ik}$ ) ) ) do i = 1, n ! some of the elements in d can be negative because 1-by-1 ! subproblems were not solved explicitly. if( abs( d( i ) )<=tol ) then call stdlib${ii}$_${ri}$laset( 'A', 1_${ik}$, nrhs, zero, zero, work( bx+i-1 ), n ) else rank = rank + 1_${ik}$ call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs,work( bx+i-1 ), n, info ) end if d( i ) = abs( d( i ) ) end do ! now apply back the right singular vectors. icmpq2 = 1_${ik}$ do i = 1, nsub st = iwork( i ) st1 = st - 1_${ik}$ nsize = iwork( sizei+i-1 ) bxst = bx + st1 if( nsize==1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( nrhs, work( bxst ), n, b( st, 1_${ik}$ ), ldb ) else if( nsize<=smlsiz ) then call stdlib${ii}$_${ri}$gemm( 'T', 'N', nsize, nrhs, nsize, one,work( vt+st1 ), n, work( & bxst ), n, zero,b( st, 1_${ik}$ ), ldb ) else call stdlib${ii}$_${ri}$lalsa( icmpq2, smlsiz, nsize, nrhs, work( bxst ), n,b( st, 1_${ik}$ ), ldb,& work( u+st1 ), n,work( vt+st1 ), iwork( k+st1 ),work( difl+st1 ), work( difr+& st1 ),work( z+st1 ), work( poles+st1 ),iwork( givptr+st1 ), iwork( givcol+st1 ),& n,iwork( perm+st1 ), work( givnum+st1 ),work( c+st1 ), work( s+st1 ), work( & nwork ),iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if end do ! unscale and sort the singular values. call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_${ri}$lasrt( 'D', n, d, info ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end subroutine stdlib${ii}$_${ri}$lalsd #:endif #:endfor pure module subroutine stdlib${ii}$_clalsd( uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond,rank, work, rwork, & !! CLALSD uses the singular value decomposition of A to solve the least !! squares problem of finding X to minimize the Euclidean norm of each !! column of A*X-B, where A is N-by-N upper bidiagonal, and X and B !! are N-by-NRHS. The solution X overwrites B. !! The singular values of A smaller than RCOND times the largest !! singular value are treated as zero in solving the least squares !! problem; in this case a minimum norm solution is returned. !! The actual singular values are returned in D in ascending order. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: ldb, n, nrhs, smlsiz real(sp), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: d(*), e(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: bx, bxst, c, difl, difr, givcol, givnum, givptr, i, icmpq1, icmpq2, & irwb, irwib, irwrb, irwu, irwvt, irwwrk, iwk, j, jcol, jimag, jreal, jrow, k, nlvl, & nm1, nrwork, nsize, nsub, perm, poles, s, sizei, smlszp, sqre, st, st1, u, vt, & z real(sp) :: cs, eps, orgnrm, r, rcnd, sn, tol ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<1_${ik}$ ) then info = -4_${ik}$ else if( ( ldb<1_${ik}$ ) .or. ( ldb=one ) ) then rcnd = eps else rcnd = rcond end if rank = 0_${ik}$ ! quick return if possible. if( n==0_${ik}$ ) then return else if( n==1_${ik}$ ) then if( d( 1_${ik}$ )==zero ) then call stdlib${ii}$_claset( 'A', 1_${ik}$, nrhs, czero, czero, b, ldb ) else rank = 1_${ik}$ call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, d( 1_${ik}$ ), one, 1_${ik}$, nrhs, b, ldb, info ) d( 1_${ik}$ ) = abs( d( 1_${ik}$ ) ) end if return end if ! rotate the matrix if it is lower bidiagonal. if( uplo=='L' ) then do i = 1, n - 1 call stdlib${ii}$_slartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( nrhs==1_${ik}$ ) then call stdlib${ii}$_csrot( 1_${ik}$, b( i, 1_${ik}$ ), 1_${ik}$, b( i+1, 1_${ik}$ ), 1_${ik}$, cs, sn ) else rwork( i*2_${ik}$-1 ) = cs rwork( i*2_${ik}$ ) = sn end if end do if( nrhs>1_${ik}$ ) then do i = 1, nrhs do j = 1, n - 1 cs = rwork( j*2_${ik}$-1 ) sn = rwork( j*2_${ik}$ ) call stdlib${ii}$_csrot( 1_${ik}$, b( j, i ), 1_${ik}$, b( j+1, i ), 1_${ik}$, cs, sn ) end do end do end if end if ! scale. nm1 = n - 1_${ik}$ orgnrm = stdlib${ii}$_slanst( 'M', n, d, e ) if( orgnrm==zero ) then call stdlib${ii}$_claset( 'A', n, nrhs, czero, czero, b, ldb ) return end if call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, nm1, 1_${ik}$, e, nm1, info ) ! if n is smaller than the minimum divide size smlsiz, then solve ! the problem with another solver. if( n<=smlsiz ) then irwu = 1_${ik}$ irwvt = irwu + n*n irwwrk = irwvt + n*n irwrb = irwwrk irwib = irwrb + n*nrhs irwb = irwib + n*nrhs call stdlib${ii}$_slaset( 'A', n, n, zero, one, rwork( irwu ), n ) call stdlib${ii}$_slaset( 'A', n, n, zero, one, rwork( irwvt ), n ) call stdlib${ii}$_slasdq( 'U', 0_${ik}$, n, n, n, 0_${ik}$, d, e, rwork( irwvt ), n,rwork( irwu ), n, & rwork( irwwrk ), 1_${ik}$,rwork( irwwrk ), info ) if( info/=0_${ik}$ ) then return end if ! in the real version, b is passed to stdlib${ii}$_slasdq and multiplied ! internally by q**h. here b is complex and that product is ! computed below in two steps (real and imaginary parts). j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = real( b( jrow, jcol ),KIND=sp) end do end do call stdlib${ii}$_sgemm( 'T', 'N', n, nrhs, n, one, rwork( irwu ), n,rwork( irwb ), n, & zero, rwork( irwrb ), n ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_sgemm( 'T', 'N', n, nrhs, n, one, rwork( irwu ), n,rwork( irwb ), n, & zero, rwork( irwib ), n ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ), rwork( jimag ),KIND=sp) end do end do tol = rcnd*abs( d( stdlib${ii}$_isamax( n, d, 1_${ik}$ ) ) ) do i = 1, n if( d( i )<=tol ) then call stdlib${ii}$_claset( 'A', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) else call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs, b( i, 1_${ik}$ ),ldb, info ) rank = rank + 1_${ik}$ end if end do ! since b is complex, the following call to stdlib${ii}$_sgemm is performed ! in two steps (real and imaginary parts). that is for v * b ! (in the real version of the code v**h is stored in work). ! call stdlib${ii}$_sgemm( 't', 'n', n, nrhs, n, one, work, n, b, ldb, zero, ! $ work( nwork ), n ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = real( b( jrow, jcol ),KIND=sp) end do end do call stdlib${ii}$_sgemm( 'T', 'N', n, nrhs, n, one, rwork( irwvt ), n,rwork( irwb ), n, & zero, rwork( irwrb ), n ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_sgemm( 'T', 'N', n, nrhs, n, one, rwork( irwvt ), n,rwork( irwb ), n, & zero, rwork( irwib ), n ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ), rwork( jimag ),KIND=sp) end do end do ! unscale. call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_slasrt( 'D', n, d, info ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end if ! book-keeping and setting up some constants. nlvl = int( log( real( n,KIND=sp) / real( smlsiz+1,KIND=sp) ) / log( two ),KIND=${ik}$) + & 1_${ik}$ smlszp = smlsiz + 1_${ik}$ u = 1_${ik}$ vt = 1_${ik}$ + smlsiz*n difl = vt + smlszp*n difr = difl + nlvl*n z = difr + nlvl*n*2_${ik}$ c = z + nlvl*n s = c + n poles = s + n givnum = poles + 2_${ik}$*nlvl*n nrwork = givnum + 2_${ik}$*nlvl*n bx = 1_${ik}$ irwrb = nrwork irwib = irwrb + smlsiz*nrhs irwb = irwib + smlsiz*nrhs sizei = 1_${ik}$ + n k = sizei + n givptr = k + n perm = givptr + n givcol = perm + nlvl*n iwk = givcol + nlvl*n*2_${ik}$ st = 1_${ik}$ sqre = 0_${ik}$ icmpq1 = 1_${ik}$ icmpq2 = 0_${ik}$ nsub = 0_${ik}$ do i = 1, n if( abs( d( i ) )=eps ) then ! a subproblem with e(nm1) not too small but i = nm1. nsize = n - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize else ! a subproblem with e(nm1) small. this implies an ! 1-by-1 subproblem at d(n), which is not solved ! explicitly. nsize = i - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize nsub = nsub + 1_${ik}$ iwork( nsub ) = n iwork( sizei+nsub-1 ) = 1_${ik}$ call stdlib${ii}$_ccopy( nrhs, b( n, 1_${ik}$ ), ldb, work( bx+nm1 ), n ) end if st1 = st - 1_${ik}$ if( nsize==1_${ik}$ ) then ! this is a 1-by-1 subproblem and is not solved ! explicitly. call stdlib${ii}$_ccopy( nrhs, b( st, 1_${ik}$ ), ldb, work( bx+st1 ), n ) else if( nsize<=smlsiz ) then ! this is a small subproblem and is solved by stdlib${ii}$_slasdq. call stdlib${ii}$_slaset( 'A', nsize, nsize, zero, one,rwork( vt+st1 ), n ) call stdlib${ii}$_slaset( 'A', nsize, nsize, zero, one,rwork( u+st1 ), n ) call stdlib${ii}$_slasdq( 'U', 0_${ik}$, nsize, nsize, nsize, 0_${ik}$, d( st ),e( st ), rwork( & vt+st1 ), n, rwork( u+st1 ),n, rwork( nrwork ), 1_${ik}$, rwork( nrwork ),info ) if( info/=0_${ik}$ ) then return end if ! in the real version, b is passed to stdlib${ii}$_slasdq and multiplied ! internally by q**h. here b is complex and that product is ! computed below in two steps (real and imaginary parts). j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 j = j + 1_${ik}$ rwork( j ) = real( b( jrow, jcol ),KIND=sp) end do end do call stdlib${ii}$_sgemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( u+st1 ), n, rwork(& irwb ), nsize,zero, rwork( irwrb ), nsize ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 j = j + 1_${ik}$ rwork( j ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_sgemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( u+st1 ), n, rwork(& irwb ), nsize,zero, rwork( irwib ), nsize ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ),rwork( jimag ),KIND=sp) end do end do call stdlib${ii}$_clacpy( 'A', nsize, nrhs, b( st, 1_${ik}$ ), ldb,work( bx+st1 ), n ) else ! a large problem. solve it using divide and conquer. call stdlib${ii}$_slasda( icmpq1, smlsiz, nsize, sqre, d( st ),e( st ), rwork( u+& st1 ), n, rwork( vt+st1 ),iwork( k+st1 ), rwork( difl+st1 ),rwork( difr+st1 ),& rwork( z+st1 ),rwork( poles+st1 ), iwork( givptr+st1 ),iwork( givcol+st1 ), & n, iwork( perm+st1 ),rwork( givnum+st1 ), rwork( c+st1 ),rwork( s+st1 ), & rwork( nrwork ),iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if bxst = bx + st1 call stdlib${ii}$_clalsa( icmpq2, smlsiz, nsize, nrhs, b( st, 1_${ik}$ ),ldb, work( bxst ),& n, rwork( u+st1 ), n,rwork( vt+st1 ), iwork( k+st1 ),rwork( difl+st1 ), & rwork( difr+st1 ),rwork( z+st1 ), rwork( poles+st1 ),iwork( givptr+st1 ), & iwork( givcol+st1 ), n,iwork( perm+st1 ), rwork( givnum+st1 ),rwork( c+st1 ),& rwork( s+st1 ),rwork( nrwork ), iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if st = i + 1_${ik}$ end if end do loop_240 ! apply the singular values and treat the tiny ones as zero. tol = rcnd*abs( d( stdlib${ii}$_isamax( n, d, 1_${ik}$ ) ) ) do i = 1, n ! some of the elements in d can be negative because 1-by-1 ! subproblems were not solved explicitly. if( abs( d( i ) )<=tol ) then call stdlib${ii}$_claset( 'A', 1_${ik}$, nrhs, czero, czero, work( bx+i-1 ), n ) else rank = rank + 1_${ik}$ call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs,work( bx+i-1 ), n, info ) end if d( i ) = abs( d( i ) ) end do ! now apply back the right singular vectors. icmpq2 = 1_${ik}$ loop_320: do i = 1, nsub st = iwork( i ) st1 = st - 1_${ik}$ nsize = iwork( sizei+i-1 ) bxst = bx + st1 if( nsize==1_${ik}$ ) then call stdlib${ii}$_ccopy( nrhs, work( bxst ), n, b( st, 1_${ik}$ ), ldb ) else if( nsize<=smlsiz ) then ! since b and bx are complex, the following call to stdlib${ii}$_sgemm ! is performed in two steps (real and imaginary parts). ! call stdlib${ii}$_sgemm( 't', 'n', nsize, nrhs, nsize, one, ! $ rwork( vt+st1 ), n, rwork( bxst ), n, zero, ! $ b( st, 1 ), ldb ) j = bxst - n - 1_${ik}$ jreal = irwb - 1_${ik}$ do jcol = 1, nrhs j = j + n do jrow = 1, nsize jreal = jreal + 1_${ik}$ rwork( jreal ) = real( work( j+jrow ),KIND=sp) end do end do call stdlib${ii}$_sgemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( vt+st1 ), n, rwork( & irwb ), nsize, zero,rwork( irwrb ), nsize ) j = bxst - n - 1_${ik}$ jimag = irwb - 1_${ik}$ do jcol = 1, nrhs j = j + n do jrow = 1, nsize jimag = jimag + 1_${ik}$ rwork( jimag ) = aimag( work( j+jrow ) ) end do end do call stdlib${ii}$_sgemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( vt+st1 ), n, rwork( & irwb ), nsize, zero,rwork( irwib ), nsize ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ),rwork( jimag ),KIND=sp) end do end do else call stdlib${ii}$_clalsa( icmpq2, smlsiz, nsize, nrhs, work( bxst ), n,b( st, 1_${ik}$ ), ldb,& rwork( u+st1 ), n,rwork( vt+st1 ), iwork( k+st1 ),rwork( difl+st1 ), rwork( & difr+st1 ),rwork( z+st1 ), rwork( poles+st1 ),iwork( givptr+st1 ), iwork( & givcol+st1 ), n,iwork( perm+st1 ), rwork( givnum+st1 ),rwork( c+st1 ), rwork( s+& st1 ),rwork( nrwork ), iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if end do loop_320 ! unscale and sort the singular values. call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_slasrt( 'D', n, d, info ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end subroutine stdlib${ii}$_clalsd pure module subroutine stdlib${ii}$_zlalsd( uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond,rank, work, rwork, & !! ZLALSD uses the singular value decomposition of A to solve the least !! squares problem of finding X to minimize the Euclidean norm of each !! column of A*X-B, where A is N-by-N upper bidiagonal, and X and B !! are N-by-NRHS. The solution X overwrites B. !! The singular values of A smaller than RCOND times the largest !! singular value are treated as zero in solving the least squares !! problem; in this case a minimum norm solution is returned. !! The actual singular values are returned in D in ascending order. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: ldb, n, nrhs, smlsiz real(dp), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: d(*), e(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: bx, bxst, c, difl, difr, givcol, givnum, givptr, i, icmpq1, icmpq2, & irwb, irwib, irwrb, irwu, irwvt, irwwrk, iwk, j, jcol, jimag, jreal, jrow, k, nlvl, & nm1, nrwork, nsize, nsub, perm, poles, s, sizei, smlszp, sqre, st, st1, u, vt, & z real(dp) :: cs, eps, orgnrm, rcnd, r, sn, tol ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<1_${ik}$ ) then info = -4_${ik}$ else if( ( ldb<1_${ik}$ ) .or. ( ldb=one ) ) then rcnd = eps else rcnd = rcond end if rank = 0_${ik}$ ! quick return if possible. if( n==0_${ik}$ ) then return else if( n==1_${ik}$ ) then if( d( 1_${ik}$ )==zero ) then call stdlib${ii}$_zlaset( 'A', 1_${ik}$, nrhs, czero, czero, b, ldb ) else rank = 1_${ik}$ call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, d( 1_${ik}$ ), one, 1_${ik}$, nrhs, b, ldb, info ) d( 1_${ik}$ ) = abs( d( 1_${ik}$ ) ) end if return end if ! rotate the matrix if it is lower bidiagonal. if( uplo=='L' ) then do i = 1, n - 1 call stdlib${ii}$_dlartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( nrhs==1_${ik}$ ) then call stdlib${ii}$_zdrot( 1_${ik}$, b( i, 1_${ik}$ ), 1_${ik}$, b( i+1, 1_${ik}$ ), 1_${ik}$, cs, sn ) else rwork( i*2_${ik}$-1 ) = cs rwork( i*2_${ik}$ ) = sn end if end do if( nrhs>1_${ik}$ ) then do i = 1, nrhs do j = 1, n - 1 cs = rwork( j*2_${ik}$-1 ) sn = rwork( j*2_${ik}$ ) call stdlib${ii}$_zdrot( 1_${ik}$, b( j, i ), 1_${ik}$, b( j+1, i ), 1_${ik}$, cs, sn ) end do end do end if end if ! scale. nm1 = n - 1_${ik}$ orgnrm = stdlib${ii}$_dlanst( 'M', n, d, e ) if( orgnrm==zero ) then call stdlib${ii}$_zlaset( 'A', n, nrhs, czero, czero, b, ldb ) return end if call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, nm1, 1_${ik}$, e, nm1, info ) ! if n is smaller than the minimum divide size smlsiz, then solve ! the problem with another solver. if( n<=smlsiz ) then irwu = 1_${ik}$ irwvt = irwu + n*n irwwrk = irwvt + n*n irwrb = irwwrk irwib = irwrb + n*nrhs irwb = irwib + n*nrhs call stdlib${ii}$_dlaset( 'A', n, n, zero, one, rwork( irwu ), n ) call stdlib${ii}$_dlaset( 'A', n, n, zero, one, rwork( irwvt ), n ) call stdlib${ii}$_dlasdq( 'U', 0_${ik}$, n, n, n, 0_${ik}$, d, e, rwork( irwvt ), n,rwork( irwu ), n, & rwork( irwwrk ), 1_${ik}$,rwork( irwwrk ), info ) if( info/=0_${ik}$ ) then return end if ! in the real version, b is passed to stdlib${ii}$_dlasdq and multiplied ! internally by q**h. here b is complex and that product is ! computed below in two steps (real and imaginary parts). j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = real( b( jrow, jcol ),KIND=dp) end do end do call stdlib${ii}$_dgemm( 'T', 'N', n, nrhs, n, one, rwork( irwu ), n,rwork( irwb ), n, & zero, rwork( irwrb ), n ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_dgemm( 'T', 'N', n, nrhs, n, one, rwork( irwu ), n,rwork( irwb ), n, & zero, rwork( irwib ), n ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ),rwork( jimag ),KIND=dp) end do end do tol = rcnd*abs( d( stdlib${ii}$_idamax( n, d, 1_${ik}$ ) ) ) do i = 1, n if( d( i )<=tol ) then call stdlib${ii}$_zlaset( 'A', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) else call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs, b( i, 1_${ik}$ ),ldb, info ) rank = rank + 1_${ik}$ end if end do ! since b is complex, the following call to stdlib${ii}$_dgemm is performed ! in two steps (real and imaginary parts). that is for v * b ! (in the real version of the code v**h is stored in work). ! call stdlib${ii}$_dgemm( 't', 'n', n, nrhs, n, one, work, n, b, ldb, zero, ! $ work( nwork ), n ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = real( b( jrow, jcol ),KIND=dp) end do end do call stdlib${ii}$_dgemm( 'T', 'N', n, nrhs, n, one, rwork( irwvt ), n,rwork( irwb ), n, & zero, rwork( irwrb ), n ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_dgemm( 'T', 'N', n, nrhs, n, one, rwork( irwvt ), n,rwork( irwb ), n, & zero, rwork( irwib ), n ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ),rwork( jimag ),KIND=dp) end do end do ! unscale. call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_dlasrt( 'D', n, d, info ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end if ! book-keeping and setting up some constants. nlvl = int( log( real( n,KIND=dp) / real( smlsiz+1,KIND=dp) ) / log( two ),KIND=${ik}$) + & 1_${ik}$ smlszp = smlsiz + 1_${ik}$ u = 1_${ik}$ vt = 1_${ik}$ + smlsiz*n difl = vt + smlszp*n difr = difl + nlvl*n z = difr + nlvl*n*2_${ik}$ c = z + nlvl*n s = c + n poles = s + n givnum = poles + 2_${ik}$*nlvl*n nrwork = givnum + 2_${ik}$*nlvl*n bx = 1_${ik}$ irwrb = nrwork irwib = irwrb + smlsiz*nrhs irwb = irwib + smlsiz*nrhs sizei = 1_${ik}$ + n k = sizei + n givptr = k + n perm = givptr + n givcol = perm + nlvl*n iwk = givcol + nlvl*n*2_${ik}$ st = 1_${ik}$ sqre = 0_${ik}$ icmpq1 = 1_${ik}$ icmpq2 = 0_${ik}$ nsub = 0_${ik}$ do i = 1, n if( abs( d( i ) )=eps ) then ! a subproblem with e(nm1) not too small but i = nm1. nsize = n - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize else ! a subproblem with e(nm1) small. this implies an ! 1-by-1 subproblem at d(n), which is not solved ! explicitly. nsize = i - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize nsub = nsub + 1_${ik}$ iwork( nsub ) = n iwork( sizei+nsub-1 ) = 1_${ik}$ call stdlib${ii}$_zcopy( nrhs, b( n, 1_${ik}$ ), ldb, work( bx+nm1 ), n ) end if st1 = st - 1_${ik}$ if( nsize==1_${ik}$ ) then ! this is a 1-by-1 subproblem and is not solved ! explicitly. call stdlib${ii}$_zcopy( nrhs, b( st, 1_${ik}$ ), ldb, work( bx+st1 ), n ) else if( nsize<=smlsiz ) then ! this is a small subproblem and is solved by stdlib${ii}$_dlasdq. call stdlib${ii}$_dlaset( 'A', nsize, nsize, zero, one,rwork( vt+st1 ), n ) call stdlib${ii}$_dlaset( 'A', nsize, nsize, zero, one,rwork( u+st1 ), n ) call stdlib${ii}$_dlasdq( 'U', 0_${ik}$, nsize, nsize, nsize, 0_${ik}$, d( st ),e( st ), rwork( & vt+st1 ), n, rwork( u+st1 ),n, rwork( nrwork ), 1_${ik}$, rwork( nrwork ),info ) if( info/=0_${ik}$ ) then return end if ! in the real version, b is passed to stdlib${ii}$_dlasdq and multiplied ! internally by q**h. here b is complex and that product is ! computed below in two steps (real and imaginary parts). j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 j = j + 1_${ik}$ rwork( j ) = real( b( jrow, jcol ),KIND=dp) end do end do call stdlib${ii}$_dgemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( u+st1 ), n, rwork(& irwb ), nsize,zero, rwork( irwrb ), nsize ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 j = j + 1_${ik}$ rwork( j ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_dgemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( u+st1 ), n, rwork(& irwb ), nsize,zero, rwork( irwib ), nsize ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ),rwork( jimag ),KIND=dp) end do end do call stdlib${ii}$_zlacpy( 'A', nsize, nrhs, b( st, 1_${ik}$ ), ldb,work( bx+st1 ), n ) else ! a large problem. solve it using divide and conquer. call stdlib${ii}$_dlasda( icmpq1, smlsiz, nsize, sqre, d( st ),e( st ), rwork( u+& st1 ), n, rwork( vt+st1 ),iwork( k+st1 ), rwork( difl+st1 ),rwork( difr+st1 ),& rwork( z+st1 ),rwork( poles+st1 ), iwork( givptr+st1 ),iwork( givcol+st1 ), & n, iwork( perm+st1 ),rwork( givnum+st1 ), rwork( c+st1 ),rwork( s+st1 ), & rwork( nrwork ),iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if bxst = bx + st1 call stdlib${ii}$_zlalsa( icmpq2, smlsiz, nsize, nrhs, b( st, 1_${ik}$ ),ldb, work( bxst ),& n, rwork( u+st1 ), n,rwork( vt+st1 ), iwork( k+st1 ),rwork( difl+st1 ), & rwork( difr+st1 ),rwork( z+st1 ), rwork( poles+st1 ),iwork( givptr+st1 ), & iwork( givcol+st1 ), n,iwork( perm+st1 ), rwork( givnum+st1 ),rwork( c+st1 ),& rwork( s+st1 ),rwork( nrwork ), iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if st = i + 1_${ik}$ end if end do loop_240 ! apply the singular values and treat the tiny ones as zero. tol = rcnd*abs( d( stdlib${ii}$_idamax( n, d, 1_${ik}$ ) ) ) do i = 1, n ! some of the elements in d can be negative because 1-by-1 ! subproblems were not solved explicitly. if( abs( d( i ) )<=tol ) then call stdlib${ii}$_zlaset( 'A', 1_${ik}$, nrhs, czero, czero, work( bx+i-1 ), n ) else rank = rank + 1_${ik}$ call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs,work( bx+i-1 ), n, info ) end if d( i ) = abs( d( i ) ) end do ! now apply back the right singular vectors. icmpq2 = 1_${ik}$ loop_320: do i = 1, nsub st = iwork( i ) st1 = st - 1_${ik}$ nsize = iwork( sizei+i-1 ) bxst = bx + st1 if( nsize==1_${ik}$ ) then call stdlib${ii}$_zcopy( nrhs, work( bxst ), n, b( st, 1_${ik}$ ), ldb ) else if( nsize<=smlsiz ) then ! since b and bx are complex, the following call to stdlib${ii}$_dgemm ! is performed in two steps (real and imaginary parts). ! call stdlib${ii}$_dgemm( 't', 'n', nsize, nrhs, nsize, one, ! $ rwork( vt+st1 ), n, rwork( bxst ), n, zero, ! $ b( st, 1 ), ldb ) j = bxst - n - 1_${ik}$ jreal = irwb - 1_${ik}$ do jcol = 1, nrhs j = j + n do jrow = 1, nsize jreal = jreal + 1_${ik}$ rwork( jreal ) = real( work( j+jrow ),KIND=dp) end do end do call stdlib${ii}$_dgemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( vt+st1 ), n, rwork( & irwb ), nsize, zero,rwork( irwrb ), nsize ) j = bxst - n - 1_${ik}$ jimag = irwb - 1_${ik}$ do jcol = 1, nrhs j = j + n do jrow = 1, nsize jimag = jimag + 1_${ik}$ rwork( jimag ) = aimag( work( j+jrow ) ) end do end do call stdlib${ii}$_dgemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( vt+st1 ), n, rwork( & irwb ), nsize, zero,rwork( irwib ), nsize ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ),rwork( jimag ),KIND=dp) end do end do else call stdlib${ii}$_zlalsa( icmpq2, smlsiz, nsize, nrhs, work( bxst ), n,b( st, 1_${ik}$ ), ldb,& rwork( u+st1 ), n,rwork( vt+st1 ), iwork( k+st1 ),rwork( difl+st1 ), rwork( & difr+st1 ),rwork( z+st1 ), rwork( poles+st1 ),iwork( givptr+st1 ), iwork( & givcol+st1 ), n,iwork( perm+st1 ), rwork( givnum+st1 ),rwork( c+st1 ), rwork( s+& st1 ),rwork( nrwork ), iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if end do loop_320 ! unscale and sort the singular values. call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_dlasrt( 'D', n, d, info ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end subroutine stdlib${ii}$_zlalsd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lalsd( uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond,rank, work, rwork, & !! ZLALSD: uses the singular value decomposition of A to solve the least !! squares problem of finding X to minimize the Euclidean norm of each !! column of A*X-B, where A is N-by-N upper bidiagonal, and X and B !! are N-by-NRHS. The solution X overwrites B. !! The singular values of A smaller than RCOND times the largest !! singular value are treated as zero in solving the least squares !! problem; in this case a minimum norm solution is returned. !! The actual singular values are returned in D in ascending order. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info, rank integer(${ik}$), intent(in) :: ldb, n, nrhs, smlsiz real(${ck}$), intent(in) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(inout) :: d(*), e(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: b(ldb,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: bx, bxst, c, difl, difr, givcol, givnum, givptr, i, icmpq1, icmpq2, & irwb, irwib, irwrb, irwu, irwvt, irwwrk, iwk, j, jcol, jimag, jreal, jrow, k, nlvl, & nm1, nrwork, nsize, nsub, perm, poles, s, sizei, smlszp, sqre, st, st1, u, vt, & z real(${ck}$) :: cs, eps, orgnrm, rcnd, r, sn, tol ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<1_${ik}$ ) then info = -4_${ik}$ else if( ( ldb<1_${ik}$ ) .or. ( ldb=one ) ) then rcnd = eps else rcnd = rcond end if rank = 0_${ik}$ ! quick return if possible. if( n==0_${ik}$ ) then return else if( n==1_${ik}$ ) then if( d( 1_${ik}$ )==zero ) then call stdlib${ii}$_${ci}$laset( 'A', 1_${ik}$, nrhs, czero, czero, b, ldb ) else rank = 1_${ik}$ call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, d( 1_${ik}$ ), one, 1_${ik}$, nrhs, b, ldb, info ) d( 1_${ik}$ ) = abs( d( 1_${ik}$ ) ) end if return end if ! rotate the matrix if it is lower bidiagonal. if( uplo=='L' ) then do i = 1, n - 1 call stdlib${ii}$_${c2ri(ci)}$lartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( nrhs==1_${ik}$ ) then call stdlib${ii}$_${ci}$drot( 1_${ik}$, b( i, 1_${ik}$ ), 1_${ik}$, b( i+1, 1_${ik}$ ), 1_${ik}$, cs, sn ) else rwork( i*2_${ik}$-1 ) = cs rwork( i*2_${ik}$ ) = sn end if end do if( nrhs>1_${ik}$ ) then do i = 1, nrhs do j = 1, n - 1 cs = rwork( j*2_${ik}$-1 ) sn = rwork( j*2_${ik}$ ) call stdlib${ii}$_${ci}$drot( 1_${ik}$, b( j, i ), 1_${ik}$, b( j+1, i ), 1_${ik}$, cs, sn ) end do end do end if end if ! scale. nm1 = n - 1_${ik}$ orgnrm = stdlib${ii}$_${c2ri(ci)}$lanst( 'M', n, d, e ) if( orgnrm==zero ) then call stdlib${ii}$_${ci}$laset( 'A', n, nrhs, czero, czero, b, ldb ) return end if call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, nm1, 1_${ik}$, e, nm1, info ) ! if n is smaller than the minimum divide size smlsiz, then solve ! the problem with another solver. if( n<=smlsiz ) then irwu = 1_${ik}$ irwvt = irwu + n*n irwwrk = irwvt + n*n irwrb = irwwrk irwib = irwrb + n*nrhs irwb = irwib + n*nrhs call stdlib${ii}$_${c2ri(ci)}$laset( 'A', n, n, zero, one, rwork( irwu ), n ) call stdlib${ii}$_${c2ri(ci)}$laset( 'A', n, n, zero, one, rwork( irwvt ), n ) call stdlib${ii}$_${c2ri(ci)}$lasdq( 'U', 0_${ik}$, n, n, n, 0_${ik}$, d, e, rwork( irwvt ), n,rwork( irwu ), n, & rwork( irwwrk ), 1_${ik}$,rwork( irwwrk ), info ) if( info/=0_${ik}$ ) then return end if ! in the real version, b is passed to stdlib${ii}$_${c2ri(ci)}$lasdq and multiplied ! internally by q**h. here b is complex and that product is ! computed below in two steps (real and imaginary parts). j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = real( b( jrow, jcol ),KIND=${ck}$) end do end do call stdlib${ii}$_${c2ri(ci)}$gemm( 'T', 'N', n, nrhs, n, one, rwork( irwu ), n,rwork( irwb ), n, & zero, rwork( irwrb ), n ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_${c2ri(ci)}$gemm( 'T', 'N', n, nrhs, n, one, rwork( irwu ), n,rwork( irwb ), n, & zero, rwork( irwib ), n ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ),rwork( jimag ),KIND=${ck}$) end do end do tol = rcnd*abs( d( stdlib${ii}$_i${c2ri(ci)}$amax( n, d, 1_${ik}$ ) ) ) do i = 1, n if( d( i )<=tol ) then call stdlib${ii}$_${ci}$laset( 'A', 1_${ik}$, nrhs, czero, czero, b( i, 1_${ik}$ ), ldb ) else call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs, b( i, 1_${ik}$ ),ldb, info ) rank = rank + 1_${ik}$ end if end do ! since b is complex, the following call to stdlib${ii}$_${c2ri(ci)}$gemm is performed ! in two steps (real and imaginary parts). that is for v * b ! (in the real version of the code v**h is stored in work). ! call stdlib${ii}$_${c2ri(ci)}$gemm( 't', 'n', n, nrhs, n, one, work, n, b, ldb, zero, ! $ work( nwork ), n ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = real( b( jrow, jcol ),KIND=${ck}$) end do end do call stdlib${ii}$_${c2ri(ci)}$gemm( 'T', 'N', n, nrhs, n, one, rwork( irwvt ), n,rwork( irwb ), n, & zero, rwork( irwrb ), n ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n j = j + 1_${ik}$ rwork( j ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_${c2ri(ci)}$gemm( 'T', 'N', n, nrhs, n, one, rwork( irwvt ), n,rwork( irwb ), n, & zero, rwork( irwib ), n ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = 1, n jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ),rwork( jimag ),KIND=${ck}$) end do end do ! unscale. call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_${c2ri(ci)}$lasrt( 'D', n, d, info ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end if ! book-keeping and setting up some constants. nlvl = int( log( real( n,KIND=${ck}$) / real( smlsiz+1,KIND=${ck}$) ) / log( two ),KIND=${ik}$) + & 1_${ik}$ smlszp = smlsiz + 1_${ik}$ u = 1_${ik}$ vt = 1_${ik}$ + smlsiz*n difl = vt + smlszp*n difr = difl + nlvl*n z = difr + nlvl*n*2_${ik}$ c = z + nlvl*n s = c + n poles = s + n givnum = poles + 2_${ik}$*nlvl*n nrwork = givnum + 2_${ik}$*nlvl*n bx = 1_${ik}$ irwrb = nrwork irwib = irwrb + smlsiz*nrhs irwb = irwib + smlsiz*nrhs sizei = 1_${ik}$ + n k = sizei + n givptr = k + n perm = givptr + n givcol = perm + nlvl*n iwk = givcol + nlvl*n*2_${ik}$ st = 1_${ik}$ sqre = 0_${ik}$ icmpq1 = 1_${ik}$ icmpq2 = 0_${ik}$ nsub = 0_${ik}$ do i = 1, n if( abs( d( i ) )=eps ) then ! a subproblem with e(nm1) not too small but i = nm1. nsize = n - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize else ! a subproblem with e(nm1) small. this implies an ! 1-by-1 subproblem at d(n), which is not solved ! explicitly. nsize = i - st + 1_${ik}$ iwork( sizei+nsub-1 ) = nsize nsub = nsub + 1_${ik}$ iwork( nsub ) = n iwork( sizei+nsub-1 ) = 1_${ik}$ call stdlib${ii}$_${ci}$copy( nrhs, b( n, 1_${ik}$ ), ldb, work( bx+nm1 ), n ) end if st1 = st - 1_${ik}$ if( nsize==1_${ik}$ ) then ! this is a 1-by-1 subproblem and is not solved ! explicitly. call stdlib${ii}$_${ci}$copy( nrhs, b( st, 1_${ik}$ ), ldb, work( bx+st1 ), n ) else if( nsize<=smlsiz ) then ! this is a small subproblem and is solved by stdlib${ii}$_${c2ri(ci)}$lasdq. call stdlib${ii}$_${c2ri(ci)}$laset( 'A', nsize, nsize, zero, one,rwork( vt+st1 ), n ) call stdlib${ii}$_${c2ri(ci)}$laset( 'A', nsize, nsize, zero, one,rwork( u+st1 ), n ) call stdlib${ii}$_${c2ri(ci)}$lasdq( 'U', 0_${ik}$, nsize, nsize, nsize, 0_${ik}$, d( st ),e( st ), rwork( & vt+st1 ), n, rwork( u+st1 ),n, rwork( nrwork ), 1_${ik}$, rwork( nrwork ),info ) if( info/=0_${ik}$ ) then return end if ! in the real version, b is passed to stdlib${ii}$_${c2ri(ci)}$lasdq and multiplied ! internally by q**h. here b is complex and that product is ! computed below in two steps (real and imaginary parts). j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 j = j + 1_${ik}$ rwork( j ) = real( b( jrow, jcol ),KIND=${ck}$) end do end do call stdlib${ii}$_${c2ri(ci)}$gemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( u+st1 ), n, rwork(& irwb ), nsize,zero, rwork( irwrb ), nsize ) j = irwb - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 j = j + 1_${ik}$ rwork( j ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_${c2ri(ci)}$gemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( u+st1 ), n, rwork(& irwb ), nsize,zero, rwork( irwib ), nsize ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ),rwork( jimag ),KIND=${ck}$) end do end do call stdlib${ii}$_${ci}$lacpy( 'A', nsize, nrhs, b( st, 1_${ik}$ ), ldb,work( bx+st1 ), n ) else ! a large problem. solve it using divide and conquer. call stdlib${ii}$_${c2ri(ci)}$lasda( icmpq1, smlsiz, nsize, sqre, d( st ),e( st ), rwork( u+& st1 ), n, rwork( vt+st1 ),iwork( k+st1 ), rwork( difl+st1 ),rwork( difr+st1 ),& rwork( z+st1 ),rwork( poles+st1 ), iwork( givptr+st1 ),iwork( givcol+st1 ), & n, iwork( perm+st1 ),rwork( givnum+st1 ), rwork( c+st1 ),rwork( s+st1 ), & rwork( nrwork ),iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if bxst = bx + st1 call stdlib${ii}$_${ci}$lalsa( icmpq2, smlsiz, nsize, nrhs, b( st, 1_${ik}$ ),ldb, work( bxst ),& n, rwork( u+st1 ), n,rwork( vt+st1 ), iwork( k+st1 ),rwork( difl+st1 ), & rwork( difr+st1 ),rwork( z+st1 ), rwork( poles+st1 ),iwork( givptr+st1 ), & iwork( givcol+st1 ), n,iwork( perm+st1 ), rwork( givnum+st1 ),rwork( c+st1 ),& rwork( s+st1 ),rwork( nrwork ), iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if st = i + 1_${ik}$ end if end do loop_240 ! apply the singular values and treat the tiny ones as zero. tol = rcnd*abs( d( stdlib${ii}$_i${c2ri(ci)}$amax( n, d, 1_${ik}$ ) ) ) do i = 1, n ! some of the elements in d can be negative because 1-by-1 ! subproblems were not solved explicitly. if( abs( d( i ) )<=tol ) then call stdlib${ii}$_${ci}$laset( 'A', 1_${ik}$, nrhs, czero, czero, work( bx+i-1 ), n ) else rank = rank + 1_${ik}$ call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, d( i ), one, 1_${ik}$, nrhs,work( bx+i-1 ), n, info ) end if d( i ) = abs( d( i ) ) end do ! now apply back the right singular vectors. icmpq2 = 1_${ik}$ loop_320: do i = 1, nsub st = iwork( i ) st1 = st - 1_${ik}$ nsize = iwork( sizei+i-1 ) bxst = bx + st1 if( nsize==1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( nrhs, work( bxst ), n, b( st, 1_${ik}$ ), ldb ) else if( nsize<=smlsiz ) then ! since b and bx are complex, the following call to stdlib${ii}$_${c2ri(ci)}$gemm ! is performed in two steps (real and imaginary parts). ! call stdlib${ii}$_${c2ri(ci)}$gemm( 't', 'n', nsize, nrhs, nsize, one, ! $ rwork( vt+st1 ), n, rwork( bxst ), n, zero, ! $ b( st, 1 ), ldb ) j = bxst - n - 1_${ik}$ jreal = irwb - 1_${ik}$ do jcol = 1, nrhs j = j + n do jrow = 1, nsize jreal = jreal + 1_${ik}$ rwork( jreal ) = real( work( j+jrow ),KIND=${ck}$) end do end do call stdlib${ii}$_${c2ri(ci)}$gemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( vt+st1 ), n, rwork( & irwb ), nsize, zero,rwork( irwrb ), nsize ) j = bxst - n - 1_${ik}$ jimag = irwb - 1_${ik}$ do jcol = 1, nrhs j = j + n do jrow = 1, nsize jimag = jimag + 1_${ik}$ rwork( jimag ) = aimag( work( j+jrow ) ) end do end do call stdlib${ii}$_${c2ri(ci)}$gemm( 'T', 'N', nsize, nrhs, nsize, one,rwork( vt+st1 ), n, rwork( & irwb ), nsize, zero,rwork( irwib ), nsize ) jreal = irwrb - 1_${ik}$ jimag = irwib - 1_${ik}$ do jcol = 1, nrhs do jrow = st, st + nsize - 1 jreal = jreal + 1_${ik}$ jimag = jimag + 1_${ik}$ b( jrow, jcol ) = cmplx( rwork( jreal ),rwork( jimag ),KIND=${ck}$) end do end do else call stdlib${ii}$_${ci}$lalsa( icmpq2, smlsiz, nsize, nrhs, work( bxst ), n,b( st, 1_${ik}$ ), ldb,& rwork( u+st1 ), n,rwork( vt+st1 ), iwork( k+st1 ),rwork( difl+st1 ), rwork( & difr+st1 ),rwork( z+st1 ), rwork( poles+st1 ),iwork( givptr+st1 ), iwork( & givcol+st1 ), n,iwork( perm+st1 ), rwork( givnum+st1 ),rwork( c+st1 ), rwork( s+& st1 ),rwork( nrwork ), iwork( iwk ), info ) if( info/=0_${ik}$ ) then return end if end if end do loop_320 ! unscale and sort the singular values. call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) call stdlib${ii}$_${c2ri(ci)}$lasrt( 'D', n, d, info ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, nrhs, b, ldb, info ) return end subroutine stdlib${ii}$_${ci}$lalsd #:endif #:endfor #:endfor end submodule stdlib_lapack_lsq_aux fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_eigv_gen2.fypp0000664000175000017500000337227715135654166025656 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_eigv_gen2 implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_shseqr( job, compz, n, ilo, ihi, h, ldh, wr, wi, z,ldz, work, lwork, info ) !! SHSEQR computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**T, where T is an upper quasi-triangular matrix (the !! Schur form), and Z is the orthogonal matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input orthogonal !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info character, intent(in) :: compz, job ! Array Arguments real(sp), intent(inout) :: h(ldh,*), z(ldz,*) real(sp), intent(out) :: wi(*), work(*), wr(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: nl = 49_${ik}$ ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_slahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== nl allocates some local workspace to help small matrices ! . through a rare stdlib${ii}$_slahqr failure. nl > ntiny = 15 is ! . required and nl <= nmin = stdlib${ii}$_ilaenv(ispec=12,...) is recom- ! . mended. (the default value of nmin is 75.) using nl = 49 ! . allows up to six simultaneous shifts and a 16-by-16 ! . deflation window. ==== ! Local Arrays real(sp) :: hl(nl,nl), workl(nl) ! Local Scalars integer(${ik}$) :: i, kbot, nmin logical(lk) :: initz, lquery, wantt, wantz ! Intrinsic Functions ! Executable Statements ! ==== decode and check the input parameters. ==== wantt = stdlib_lsame( job, 'S' ) initz = stdlib_lsame( compz, 'I' ) wantz = initz .or. stdlib_lsame( compz, 'V' ) work( 1_${ik}$ ) = real( max( 1_${ik}$, n ),KIND=sp) lquery = lwork==-1_${ik}$ info = 0_${ik}$ if( .not.stdlib_lsame( job, 'E' ) .and. .not.wantt ) then info = -1_${ik}$ else if( .not.stdlib_lsame( compz, 'N' ) .and. .not.wantz ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( ldhnmin ) then call stdlib${ii}$_slaqr0( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi, ilo,ihi, z, ldz, & work, lwork, info ) else ! ==== small matrix ==== call stdlib${ii}$_slahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi, ilo,ihi, z, ldz, & info ) if( info>0_${ik}$ ) then ! ==== a rare stdlib${ii}$_slahqr failure! stdlib${ii}$_slaqr0 sometimes succeeds ! . when stdlib${ii}$_slahqr fails. ==== kbot = info if( n>=nl ) then ! ==== larger matrices have enough subdiagonal scratch ! . space to call stdlib${ii}$_slaqr0 directly. ==== call stdlib${ii}$_slaqr0( wantt, wantz, n, ilo, kbot, h, ldh, wr,wi, ilo, ihi, z,& ldz, work, lwork, info ) else ! ==== tiny matrices don't have enough subdiagonal ! . scratch space to benefit from stdlib${ii}$_slaqr0. hence, ! . tiny matrices must be copied into a larger ! . array before calling stdlib${ii}$_slaqr0. ==== call stdlib${ii}$_slacpy( 'A', n, n, h, ldh, hl, nl ) hl( n+1, n ) = zero call stdlib${ii}$_slaset( 'A', nl, nl-n, zero, zero, hl( 1_${ik}$, n+1 ),nl ) call stdlib${ii}$_slaqr0( wantt, wantz, nl, ilo, kbot, hl, nl, wr,wi, ilo, ihi, & z, ldz, workl, nl, info ) if( wantt .or. info/=0_${ik}$ )call stdlib${ii}$_slacpy( 'A', n, n, hl, nl, h, ldh ) end if end if end if ! ==== clear out the trash, if necessary. ==== if( ( wantt .or. info/=0_${ik}$ ) .and. n>2_${ik}$ )call stdlib${ii}$_slaset( 'L', n-2, n-2, zero, zero,& h( 3_${ik}$, 1_${ik}$ ), ldh ) ! ==== ensure reported workspace size is backward-compatible with ! . previous lapack versions. ==== work( 1_${ik}$ ) = max( real( max( 1_${ik}$, n ),KIND=sp), work( 1_${ik}$ ) ) end if end subroutine stdlib${ii}$_shseqr module subroutine stdlib${ii}$_dhseqr( job, compz, n, ilo, ihi, h, ldh, wr, wi, z,ldz, work, lwork, info ) !! DHSEQR computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**T, where T is an upper quasi-triangular matrix (the !! Schur form), and Z is the orthogonal matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input orthogonal !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info character, intent(in) :: compz, job ! Array Arguments real(dp), intent(inout) :: h(ldh,*), z(ldz,*) real(dp), intent(out) :: wi(*), work(*), wr(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: nl = 49_${ik}$ ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_dlahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== nl allocates some local workspace to help small matrices ! . through a rare stdlib${ii}$_dlahqr failure. nl > ntiny = 15 is ! . required and nl <= nmin = stdlib${ii}$_ilaenv(ispec=12,...) is recom- ! . mended. (the default value of nmin is 75.) using nl = 49 ! . allows up to six simultaneous shifts and a 16-by-16 ! . deflation window. ==== ! Local Arrays real(dp) :: hl(nl,nl), workl(nl) ! Local Scalars integer(${ik}$) :: i, kbot, nmin logical(lk) :: initz, lquery, wantt, wantz ! Intrinsic Functions ! Executable Statements ! ==== decode and check the input parameters. ==== wantt = stdlib_lsame( job, 'S' ) initz = stdlib_lsame( compz, 'I' ) wantz = initz .or. stdlib_lsame( compz, 'V' ) work( 1_${ik}$ ) = real( max( 1_${ik}$, n ),KIND=dp) lquery = lwork==-1_${ik}$ info = 0_${ik}$ if( .not.stdlib_lsame( job, 'E' ) .and. .not.wantt ) then info = -1_${ik}$ else if( .not.stdlib_lsame( compz, 'N' ) .and. .not.wantz ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( ldhnmin ) then call stdlib${ii}$_dlaqr0( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi, ilo,ihi, z, ldz, & work, lwork, info ) else ! ==== small matrix ==== call stdlib${ii}$_dlahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi, ilo,ihi, z, ldz, & info ) if( info>0_${ik}$ ) then ! ==== a rare stdlib${ii}$_dlahqr failure! stdlib${ii}$_dlaqr0 sometimes succeeds ! . when stdlib${ii}$_dlahqr fails. ==== kbot = info if( n>=nl ) then ! ==== larger matrices have enough subdiagonal scratch ! . space to call stdlib${ii}$_dlaqr0 directly. ==== call stdlib${ii}$_dlaqr0( wantt, wantz, n, ilo, kbot, h, ldh, wr,wi, ilo, ihi, z,& ldz, work, lwork, info ) else ! ==== tiny matrices don't have enough subdiagonal ! . scratch space to benefit from stdlib${ii}$_dlaqr0. hence, ! . tiny matrices must be copied into a larger ! . array before calling stdlib${ii}$_dlaqr0. ==== call stdlib${ii}$_dlacpy( 'A', n, n, h, ldh, hl, nl ) hl( n+1, n ) = zero call stdlib${ii}$_dlaset( 'A', nl, nl-n, zero, zero, hl( 1_${ik}$, n+1 ),nl ) call stdlib${ii}$_dlaqr0( wantt, wantz, nl, ilo, kbot, hl, nl, wr,wi, ilo, ihi, & z, ldz, workl, nl, info ) if( wantt .or. info/=0_${ik}$ )call stdlib${ii}$_dlacpy( 'A', n, n, hl, nl, h, ldh ) end if end if end if ! ==== clear out the trash, if necessary. ==== if( ( wantt .or. info/=0_${ik}$ ) .and. n>2_${ik}$ )call stdlib${ii}$_dlaset( 'L', n-2, n-2, zero, zero,& h( 3_${ik}$, 1_${ik}$ ), ldh ) ! ==== ensure reported workspace size is backward-compatible with ! . previous lapack versions. ==== work( 1_${ik}$ ) = max( real( max( 1_${ik}$, n ),KIND=dp), work( 1_${ik}$ ) ) end if end subroutine stdlib${ii}$_dhseqr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$hseqr( job, compz, n, ilo, ihi, h, ldh, wr, wi, z,ldz, work, lwork, info ) !! DHSEQR: computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**T, where T is an upper quasi-triangular matrix (the !! Schur form), and Z is the orthogonal matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input orthogonal !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info character, intent(in) :: compz, job ! Array Arguments real(${rk}$), intent(inout) :: h(ldh,*), z(ldz,*) real(${rk}$), intent(out) :: wi(*), work(*), wr(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: nl = 49_${ik}$ ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_${ri}$lahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== nl allocates some local workspace to help small matrices ! . through a rare stdlib${ii}$_${ri}$lahqr failure. nl > ntiny = 15 is ! . required and nl <= nmin = stdlib${ii}$_ilaenv(ispec=12,...) is recom- ! . mended. (the default value of nmin is 75.) using nl = 49 ! . allows up to six simultaneous shifts and a 16-by-16 ! . deflation window. ==== ! Local Arrays real(${rk}$) :: hl(nl,nl), workl(nl) ! Local Scalars integer(${ik}$) :: i, kbot, nmin logical(lk) :: initz, lquery, wantt, wantz ! Intrinsic Functions ! Executable Statements ! ==== decode and check the input parameters. ==== wantt = stdlib_lsame( job, 'S' ) initz = stdlib_lsame( compz, 'I' ) wantz = initz .or. stdlib_lsame( compz, 'V' ) work( 1_${ik}$ ) = real( max( 1_${ik}$, n ),KIND=${rk}$) lquery = lwork==-1_${ik}$ info = 0_${ik}$ if( .not.stdlib_lsame( job, 'E' ) .and. .not.wantt ) then info = -1_${ik}$ else if( .not.stdlib_lsame( compz, 'N' ) .and. .not.wantz ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( ldhnmin ) then call stdlib${ii}$_${ri}$laqr0( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi, ilo,ihi, z, ldz, & work, lwork, info ) else ! ==== small matrix ==== call stdlib${ii}$_${ri}$lahqr( wantt, wantz, n, ilo, ihi, h, ldh, wr, wi, ilo,ihi, z, ldz, & info ) if( info>0_${ik}$ ) then ! ==== a rare stdlib${ii}$_${ri}$lahqr failure! stdlib${ii}$_${ri}$laqr0 sometimes succeeds ! . when stdlib${ii}$_${ri}$lahqr fails. ==== kbot = info if( n>=nl ) then ! ==== larger matrices have enough subdiagonal scratch ! . space to call stdlib${ii}$_${ri}$laqr0 directly. ==== call stdlib${ii}$_${ri}$laqr0( wantt, wantz, n, ilo, kbot, h, ldh, wr,wi, ilo, ihi, z,& ldz, work, lwork, info ) else ! ==== tiny matrices don't have enough subdiagonal ! . scratch space to benefit from stdlib${ii}$_${ri}$laqr0. hence, ! . tiny matrices must be copied into a larger ! . array before calling stdlib${ii}$_${ri}$laqr0. ==== call stdlib${ii}$_${ri}$lacpy( 'A', n, n, h, ldh, hl, nl ) hl( n+1, n ) = zero call stdlib${ii}$_${ri}$laset( 'A', nl, nl-n, zero, zero, hl( 1_${ik}$, n+1 ),nl ) call stdlib${ii}$_${ri}$laqr0( wantt, wantz, nl, ilo, kbot, hl, nl, wr,wi, ilo, ihi, & z, ldz, workl, nl, info ) if( wantt .or. info/=0_${ik}$ )call stdlib${ii}$_${ri}$lacpy( 'A', n, n, hl, nl, h, ldh ) end if end if end if ! ==== clear out the trash, if necessary. ==== if( ( wantt .or. info/=0_${ik}$ ) .and. n>2_${ik}$ )call stdlib${ii}$_${ri}$laset( 'L', n-2, n-2, zero, zero,& h( 3_${ik}$, 1_${ik}$ ), ldh ) ! ==== ensure reported workspace size is backward-compatible with ! . previous lapack versions. ==== work( 1_${ik}$ ) = max( real( max( 1_${ik}$, n ),KIND=${rk}$), work( 1_${ik}$ ) ) end if end subroutine stdlib${ii}$_${ri}$hseqr #:endif #:endfor pure module subroutine stdlib${ii}$_chseqr( job, compz, n, ilo, ihi, h, ldh, w, z, ldz,work, lwork, info ) !! CHSEQR computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*T*(QZ)**H. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info character, intent(in) :: compz, job ! Array Arguments complex(sp), intent(inout) :: h(ldh,*), z(ldz,*) complex(sp), intent(out) :: w(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: nl = 49_${ik}$ ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_clahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== nl allocates some local workspace to help small matrices ! . through a rare stdlib${ii}$_clahqr failure. nl > ntiny = 15 is ! . required and nl <= nmin = stdlib${ii}$_ilaenv(ispec=12,...) is recom- ! . mended. (the default value of nmin is 75.) using nl = 49 ! . allows up to six simultaneous shifts and a 16-by-16 ! . deflation window. ==== ! Local Arrays complex(sp) :: hl(nl,nl), workl(nl) ! Local Scalars integer(${ik}$) :: kbot, nmin logical(lk) :: initz, lquery, wantt, wantz ! Intrinsic Functions ! Executable Statements ! ==== decode and check the input parameters. ==== wantt = stdlib_lsame( job, 'S' ) initz = stdlib_lsame( compz, 'I' ) wantz = initz .or. stdlib_lsame( compz, 'V' ) work( 1_${ik}$ ) = cmplx( real( max( 1_${ik}$, n ),KIND=sp), zero,KIND=sp) lquery = lwork==-1_${ik}$ info = 0_${ik}$ if( .not.stdlib_lsame( job, 'E' ) .and. .not.wantt ) then info = -1_${ik}$ else if( .not.stdlib_lsame( compz, 'N' ) .and. .not.wantz ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( ldh1_${ik}$ )call stdlib${ii}$_ccopy( ilo-1, h, ldh+1, w, 1_${ik}$ ) if( ihinmin ) then call stdlib${ii}$_claqr0( wantt, wantz, n, ilo, ihi, h, ldh, w, ilo, ihi,z, ldz, work, & lwork, info ) else ! ==== small matrix ==== call stdlib${ii}$_clahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, ilo, ihi,z, ldz, info ) if( info>0_${ik}$ ) then ! ==== a rare stdlib${ii}$_clahqr failure! stdlib${ii}$_claqr0 sometimes succeeds ! . when stdlib${ii}$_clahqr fails. ==== kbot = info if( n>=nl ) then ! ==== larger matrices have enough subdiagonal scratch ! . space to call stdlib${ii}$_claqr0 directly. ==== call stdlib${ii}$_claqr0( wantt, wantz, n, ilo, kbot, h, ldh, w,ilo, ihi, z, ldz,& work, lwork, info ) else ! ==== tiny matrices don't have enough subdiagonal ! . scratch space to benefit from stdlib${ii}$_claqr0. hence, ! . tiny matrices must be copied into a larger ! . array before calling stdlib${ii}$_claqr0. ==== call stdlib${ii}$_clacpy( 'A', n, n, h, ldh, hl, nl ) hl( n+1, n ) = czero call stdlib${ii}$_claset( 'A', nl, nl-n, czero, czero, hl( 1_${ik}$, n+1 ),nl ) call stdlib${ii}$_claqr0( wantt, wantz, nl, ilo, kbot, hl, nl, w,ilo, ihi, z, & ldz, workl, nl, info ) if( wantt .or. info/=0_${ik}$ )call stdlib${ii}$_clacpy( 'A', n, n, hl, nl, h, ldh ) end if end if end if ! ==== clear out the trash, if necessary. ==== if( ( wantt .or. info/=0_${ik}$ ) .and. n>2_${ik}$ )call stdlib${ii}$_claset( 'L', n-2, n-2, czero, & czero, h( 3_${ik}$, 1_${ik}$ ), ldh ) ! ==== ensure reported workspace size is backward-compatible with ! . previous lapack versions. ==== work( 1_${ik}$ ) = cmplx( max( real( max( 1_${ik}$, n ),KIND=sp),real( work( 1_${ik}$ ),KIND=sp) ), & zero,KIND=sp) end if end subroutine stdlib${ii}$_chseqr pure module subroutine stdlib${ii}$_zhseqr( job, compz, n, ilo, ihi, h, ldh, w, z, ldz,work, lwork, info ) !! ZHSEQR computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*T*(QZ)**H. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info character, intent(in) :: compz, job ! Array Arguments complex(dp), intent(inout) :: h(ldh,*), z(ldz,*) complex(dp), intent(out) :: w(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: nl = 49_${ik}$ ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_zlahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== nl allocates some local workspace to help small matrices ! . through a rare stdlib${ii}$_zlahqr failure. nl > ntiny = 15 is ! . required and nl <= nmin = stdlib${ii}$_ilaenv(ispec=12,...) is recom- ! . mended. (the default value of nmin is 75.) using nl = 49 ! . allows up to six simultaneous shifts and a 16-by-16 ! . deflation window. ==== ! Local Arrays complex(dp) :: hl(nl,nl), workl(nl) ! Local Scalars integer(${ik}$) :: kbot, nmin logical(lk) :: initz, lquery, wantt, wantz ! Intrinsic Functions ! Executable Statements ! ==== decode and check the input parameters. ==== wantt = stdlib_lsame( job, 'S' ) initz = stdlib_lsame( compz, 'I' ) wantz = initz .or. stdlib_lsame( compz, 'V' ) work( 1_${ik}$ ) = cmplx( real( max( 1_${ik}$, n ),KIND=dp), zero,KIND=dp) lquery = lwork==-1_${ik}$ info = 0_${ik}$ if( .not.stdlib_lsame( job, 'E' ) .and. .not.wantt ) then info = -1_${ik}$ else if( .not.stdlib_lsame( compz, 'N' ) .and. .not.wantz ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( ldh1_${ik}$ )call stdlib${ii}$_zcopy( ilo-1, h, ldh+1, w, 1_${ik}$ ) if( ihinmin ) then call stdlib${ii}$_zlaqr0( wantt, wantz, n, ilo, ihi, h, ldh, w, ilo, ihi,z, ldz, work, & lwork, info ) else ! ==== small matrix ==== call stdlib${ii}$_zlahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, ilo, ihi,z, ldz, info ) if( info>0_${ik}$ ) then ! ==== a rare stdlib${ii}$_zlahqr failure! stdlib${ii}$_zlaqr0 sometimes succeeds ! . when stdlib${ii}$_zlahqr fails. ==== kbot = info if( n>=nl ) then ! ==== larger matrices have enough subdiagonal scratch ! . space to call stdlib${ii}$_zlaqr0 directly. ==== call stdlib${ii}$_zlaqr0( wantt, wantz, n, ilo, kbot, h, ldh, w,ilo, ihi, z, ldz,& work, lwork, info ) else ! ==== tiny matrices don't have enough subdiagonal ! . scratch space to benefit from stdlib${ii}$_zlaqr0. hence, ! . tiny matrices must be copied into a larger ! . array before calling stdlib${ii}$_zlaqr0. ==== call stdlib${ii}$_zlacpy( 'A', n, n, h, ldh, hl, nl ) hl( n+1, n ) = czero call stdlib${ii}$_zlaset( 'A', nl, nl-n, czero, czero, hl( 1_${ik}$, n+1 ),nl ) call stdlib${ii}$_zlaqr0( wantt, wantz, nl, ilo, kbot, hl, nl, w,ilo, ihi, z, & ldz, workl, nl, info ) if( wantt .or. info/=0_${ik}$ )call stdlib${ii}$_zlacpy( 'A', n, n, hl, nl, h, ldh ) end if end if end if ! ==== clear out the trash, if necessary. ==== if( ( wantt .or. info/=0_${ik}$ ) .and. n>2_${ik}$ )call stdlib${ii}$_zlaset( 'L', n-2, n-2, czero, & czero, h( 3_${ik}$, 1_${ik}$ ), ldh ) ! ==== ensure reported workspace size is backward-compatible with ! . previous lapack versions. ==== work( 1_${ik}$ ) = cmplx( max( real( max( 1_${ik}$, n ),KIND=dp),real( work( 1_${ik}$ ),KIND=dp) ), & zero,KIND=dp) end if end subroutine stdlib${ii}$_zhseqr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$hseqr( job, compz, n, ilo, ihi, h, ldh, w, z, ldz,work, lwork, info ) !! ZHSEQR: computes the eigenvalues of a Hessenberg matrix H !! and, optionally, the matrices T and Z from the Schur decomposition !! H = Z T Z**H, where T is an upper triangular matrix (the !! Schur form), and Z is the unitary matrix of Schur vectors. !! Optionally Z may be postmultiplied into an input unitary !! matrix Q so that this routine can give the Schur factorization !! of a matrix A which has been reduced to the Hessenberg form H !! by the unitary matrix Q: A = Q*H*Q**H = (QZ)*T*(QZ)**H. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, ldh, ldz, lwork, n integer(${ik}$), intent(out) :: info character, intent(in) :: compz, job ! Array Arguments complex(${ck}$), intent(inout) :: h(ldh,*), z(ldz,*) complex(${ck}$), intent(out) :: w(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: ntiny = 15_${ik}$ integer(${ik}$), parameter :: nl = 49_${ik}$ ! ==== matrices of order ntiny or smaller must be processed by ! . stdlib${ii}$_${ci}$lahqr because of insufficient subdiagonal scratch space. ! . (this is a hard limit.) ==== ! ==== nl allocates some local workspace to help small matrices ! . through a rare stdlib${ii}$_${ci}$lahqr failure. nl > ntiny = 15 is ! . required and nl <= nmin = stdlib${ii}$_ilaenv(ispec=12,...) is recom- ! . mended. (the default value of nmin is 75.) using nl = 49 ! . allows up to six simultaneous shifts and a 16-by-16 ! . deflation window. ==== ! Local Arrays complex(${ck}$) :: hl(nl,nl), workl(nl) ! Local Scalars integer(${ik}$) :: kbot, nmin logical(lk) :: initz, lquery, wantt, wantz ! Intrinsic Functions ! Executable Statements ! ==== decode and check the input parameters. ==== wantt = stdlib_lsame( job, 'S' ) initz = stdlib_lsame( compz, 'I' ) wantz = initz .or. stdlib_lsame( compz, 'V' ) work( 1_${ik}$ ) = cmplx( real( max( 1_${ik}$, n ),KIND=${ck}$), zero,KIND=${ck}$) lquery = lwork==-1_${ik}$ info = 0_${ik}$ if( .not.stdlib_lsame( job, 'E' ) .and. .not.wantt ) then info = -1_${ik}$ else if( .not.stdlib_lsame( compz, 'N' ) .and. .not.wantz ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then info = -4_${ik}$ else if( ihin ) then info = -5_${ik}$ else if( ldh1_${ik}$ )call stdlib${ii}$_${ci}$copy( ilo-1, h, ldh+1, w, 1_${ik}$ ) if( ihinmin ) then call stdlib${ii}$_${ci}$laqr0( wantt, wantz, n, ilo, ihi, h, ldh, w, ilo, ihi,z, ldz, work, & lwork, info ) else ! ==== small matrix ==== call stdlib${ii}$_${ci}$lahqr( wantt, wantz, n, ilo, ihi, h, ldh, w, ilo, ihi,z, ldz, info ) if( info>0_${ik}$ ) then ! ==== a rare stdlib${ii}$_${ci}$lahqr failure! stdlib${ii}$_${ci}$laqr0 sometimes succeeds ! . when stdlib${ii}$_${ci}$lahqr fails. ==== kbot = info if( n>=nl ) then ! ==== larger matrices have enough subdiagonal scratch ! . space to call stdlib${ii}$_${ci}$laqr0 directly. ==== call stdlib${ii}$_${ci}$laqr0( wantt, wantz, n, ilo, kbot, h, ldh, w,ilo, ihi, z, ldz,& work, lwork, info ) else ! ==== tiny matrices don't have enough subdiagonal ! . scratch space to benefit from stdlib${ii}$_${ci}$laqr0. hence, ! . tiny matrices must be copied into a larger ! . array before calling stdlib${ii}$_${ci}$laqr0. ==== call stdlib${ii}$_${ci}$lacpy( 'A', n, n, h, ldh, hl, nl ) hl( n+1, n ) = czero call stdlib${ii}$_${ci}$laset( 'A', nl, nl-n, czero, czero, hl( 1_${ik}$, n+1 ),nl ) call stdlib${ii}$_${ci}$laqr0( wantt, wantz, nl, ilo, kbot, hl, nl, w,ilo, ihi, z, & ldz, workl, nl, info ) if( wantt .or. info/=0_${ik}$ )call stdlib${ii}$_${ci}$lacpy( 'A', n, n, hl, nl, h, ldh ) end if end if end if ! ==== clear out the trash, if necessary. ==== if( ( wantt .or. info/=0_${ik}$ ) .and. n>2_${ik}$ )call stdlib${ii}$_${ci}$laset( 'L', n-2, n-2, czero, & czero, h( 3_${ik}$, 1_${ik}$ ), ldh ) ! ==== ensure reported workspace size is backward-compatible with ! . previous lapack versions. ==== work( 1_${ik}$ ) = cmplx( max( real( max( 1_${ik}$, n ),KIND=${ck}$),real( work( 1_${ik}$ ),KIND=${ck}$) ), & zero,KIND=${ck}$) end if end subroutine stdlib${ii}$_${ci}$hseqr #:endif #:endfor module subroutine stdlib${ii}$_shsein( side, eigsrc, initv, select, n, h, ldh, wr, wi,vl, ldvl, vr, ldvr, & !! SHSEIN uses inverse iteration to find specified right and/or left !! eigenvectors of a real upper Hessenberg matrix H. !! The right eigenvector x and the left eigenvector y of the matrix H !! corresponding to an eigenvalue w are defined by: !! H * x = w * x, y**h * H = w * y**h !! where y**h denotes the conjugate transpose of the vector y. mm, m, work, ifaill,ifailr, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: eigsrc, initv, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldh, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(inout) :: select(*) integer(${ik}$), intent(out) :: ifaill(*), ifailr(*) real(sp), intent(in) :: h(ldh,*), wi(*) real(sp), intent(inout) :: vl(ldvl,*), vr(ldvr,*), wr(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: bothv, fromqr, leftv, noinit, pair, rightv integer(${ik}$) :: i, iinfo, k, kl, kln, kr, ksi, ksr, ldwork real(sp) :: bignum, eps3, hnorm, smlnum, ulp, unfl, wki, wkr ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters. bothv = stdlib_lsame( side, 'B' ) rightv = stdlib_lsame( side, 'R' ) .or. bothv leftv = stdlib_lsame( side, 'L' ) .or. bothv fromqr = stdlib_lsame( eigsrc, 'Q' ) noinit = stdlib_lsame( initv, 'N' ) ! set m to the number of columns required to store the selected ! eigenvectors, and standardize the array select. m = 0_${ik}$ pair = .false. do k = 1, n if( pair ) then pair = .false. select( k ) = .false. else if( wi( k )==zero ) then if( select( k ) )m = m + 1_${ik}$ else pair = .true. if( select( k ) .or. select( k+1 ) ) then select( k ) = .true. m = m + 2_${ik}$ end if end if end if end do info = 0_${ik}$ if( .not.rightv .and. .not.leftv ) then info = -1_${ik}$ else if( .not.fromqr .and. .not.stdlib_lsame( eigsrc, 'N' ) ) then info = -2_${ik}$ else if( .not.noinit .and. .not.stdlib_lsame( initv, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldhkr ) then do i = k, n - 1 if( h( i+1, i )==zero )go to 50 end do 50 continue kr = i end if end if if( kl/=kln ) then kln = kl ! compute infinity-norm of submatrix h(kl:kr,kl:kr) if it ! has not ben computed before. hnorm = stdlib${ii}$_slanhs( 'I', kr-kl+1, h( kl, kl ), ldh, work ) if( stdlib${ii}$_sisnan( hnorm ) ) then info = -6_${ik}$ return else if( hnorm>zero ) then eps3 = hnorm*ulp else eps3 = smlnum end if end if ! perturb eigenvalue if it is close to any previous ! selected eigenvalues affiliated to the submatrix ! h(kl:kr,kl:kr). close roots are modified by eps3. wkr = wr( k ) wki = wi( k ) 60 continue do i = k - 1, kl, -1 if( select( i ) .and. abs( wr( i )-wkr )+abs( wi( i )-wki )0_${ik}$ ) then if( pair ) then info = info + 2_${ik}$ else info = info + 1_${ik}$ end if ifaill( ksr ) = k ifaill( ksi ) = k else ifaill( ksr ) = 0_${ik}$ ifaill( ksi ) = 0_${ik}$ end if do i = 1, kl - 1 vl( i, ksr ) = zero end do if( pair ) then do i = 1, kl - 1 vl( i, ksi ) = zero end do end if end if if( rightv ) then ! compute right eigenvector. call stdlib${ii}$_slaein( .true., noinit, kr, h, ldh, wkr, wki,vr( 1_${ik}$, ksr ), vr( 1_${ik}$, & ksi ), work, ldwork,work( n*n+n+1 ), eps3, smlnum, bignum,iinfo ) if( iinfo>0_${ik}$ ) then if( pair ) then info = info + 2_${ik}$ else info = info + 1_${ik}$ end if ifailr( ksr ) = k ifailr( ksi ) = k else ifailr( ksr ) = 0_${ik}$ ifailr( ksi ) = 0_${ik}$ end if do i = kr + 1, n vr( i, ksr ) = zero end do if( pair ) then do i = kr + 1, n vr( i, ksi ) = zero end do end if end if if( pair ) then ksr = ksr + 2_${ik}$ else ksr = ksr + 1_${ik}$ end if end if end do loop_120 return end subroutine stdlib${ii}$_shsein module subroutine stdlib${ii}$_dhsein( side, eigsrc, initv, select, n, h, ldh, wr, wi,vl, ldvl, vr, ldvr, & !! DHSEIN uses inverse iteration to find specified right and/or left !! eigenvectors of a real upper Hessenberg matrix H. !! The right eigenvector x and the left eigenvector y of the matrix H !! corresponding to an eigenvalue w are defined by: !! H * x = w * x, y**h * H = w * y**h !! where y**h denotes the conjugate transpose of the vector y. mm, m, work, ifaill,ifailr, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: eigsrc, initv, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldh, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(inout) :: select(*) integer(${ik}$), intent(out) :: ifaill(*), ifailr(*) real(dp), intent(in) :: h(ldh,*), wi(*) real(dp), intent(inout) :: vl(ldvl,*), vr(ldvr,*), wr(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: bothv, fromqr, leftv, noinit, pair, rightv integer(${ik}$) :: i, iinfo, k, kl, kln, kr, ksi, ksr, ldwork real(dp) :: bignum, eps3, hnorm, smlnum, ulp, unfl, wki, wkr ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters. bothv = stdlib_lsame( side, 'B' ) rightv = stdlib_lsame( side, 'R' ) .or. bothv leftv = stdlib_lsame( side, 'L' ) .or. bothv fromqr = stdlib_lsame( eigsrc, 'Q' ) noinit = stdlib_lsame( initv, 'N' ) ! set m to the number of columns required to store the selected ! eigenvectors, and standardize the array select. m = 0_${ik}$ pair = .false. do k = 1, n if( pair ) then pair = .false. select( k ) = .false. else if( wi( k )==zero ) then if( select( k ) )m = m + 1_${ik}$ else pair = .true. if( select( k ) .or. select( k+1 ) ) then select( k ) = .true. m = m + 2_${ik}$ end if end if end if end do info = 0_${ik}$ if( .not.rightv .and. .not.leftv ) then info = -1_${ik}$ else if( .not.fromqr .and. .not.stdlib_lsame( eigsrc, 'N' ) ) then info = -2_${ik}$ else if( .not.noinit .and. .not.stdlib_lsame( initv, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldhkr ) then do i = k, n - 1 if( h( i+1, i )==zero )go to 50 end do 50 continue kr = i end if end if if( kl/=kln ) then kln = kl ! compute infinity-norm of submatrix h(kl:kr,kl:kr) if it ! has not ben computed before. hnorm = stdlib${ii}$_dlanhs( 'I', kr-kl+1, h( kl, kl ), ldh, work ) if( stdlib${ii}$_disnan( hnorm ) ) then info = -6_${ik}$ return else if( hnorm>zero ) then eps3 = hnorm*ulp else eps3 = smlnum end if end if ! perturb eigenvalue if it is close to any previous ! selected eigenvalues affiliated to the submatrix ! h(kl:kr,kl:kr). close roots are modified by eps3. wkr = wr( k ) wki = wi( k ) 60 continue do i = k - 1, kl, -1 if( select( i ) .and. abs( wr( i )-wkr )+abs( wi( i )-wki )0_${ik}$ ) then if( pair ) then info = info + 2_${ik}$ else info = info + 1_${ik}$ end if ifaill( ksr ) = k ifaill( ksi ) = k else ifaill( ksr ) = 0_${ik}$ ifaill( ksi ) = 0_${ik}$ end if do i = 1, kl - 1 vl( i, ksr ) = zero end do if( pair ) then do i = 1, kl - 1 vl( i, ksi ) = zero end do end if end if if( rightv ) then ! compute right eigenvector. call stdlib${ii}$_dlaein( .true., noinit, kr, h, ldh, wkr, wki,vr( 1_${ik}$, ksr ), vr( 1_${ik}$, & ksi ), work, ldwork,work( n*n+n+1 ), eps3, smlnum, bignum,iinfo ) if( iinfo>0_${ik}$ ) then if( pair ) then info = info + 2_${ik}$ else info = info + 1_${ik}$ end if ifailr( ksr ) = k ifailr( ksi ) = k else ifailr( ksr ) = 0_${ik}$ ifailr( ksi ) = 0_${ik}$ end if do i = kr + 1, n vr( i, ksr ) = zero end do if( pair ) then do i = kr + 1, n vr( i, ksi ) = zero end do end if end if if( pair ) then ksr = ksr + 2_${ik}$ else ksr = ksr + 1_${ik}$ end if end if end do loop_120 return end subroutine stdlib${ii}$_dhsein #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$hsein( side, eigsrc, initv, select, n, h, ldh, wr, wi,vl, ldvl, vr, ldvr, & !! DHSEIN: uses inverse iteration to find specified right and/or left !! eigenvectors of a real upper Hessenberg matrix H. !! The right eigenvector x and the left eigenvector y of the matrix H !! corresponding to an eigenvalue w are defined by: !! H * x = w * x, y**h * H = w * y**h !! where y**h denotes the conjugate transpose of the vector y. mm, m, work, ifaill,ifailr, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: eigsrc, initv, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldh, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(inout) :: select(*) integer(${ik}$), intent(out) :: ifaill(*), ifailr(*) real(${rk}$), intent(in) :: h(ldh,*), wi(*) real(${rk}$), intent(inout) :: vl(ldvl,*), vr(ldvr,*), wr(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: bothv, fromqr, leftv, noinit, pair, rightv integer(${ik}$) :: i, iinfo, k, kl, kln, kr, ksi, ksr, ldwork real(${rk}$) :: bignum, eps3, hnorm, smlnum, ulp, unfl, wki, wkr ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters. bothv = stdlib_lsame( side, 'B' ) rightv = stdlib_lsame( side, 'R' ) .or. bothv leftv = stdlib_lsame( side, 'L' ) .or. bothv fromqr = stdlib_lsame( eigsrc, 'Q' ) noinit = stdlib_lsame( initv, 'N' ) ! set m to the number of columns required to store the selected ! eigenvectors, and standardize the array select. m = 0_${ik}$ pair = .false. do k = 1, n if( pair ) then pair = .false. select( k ) = .false. else if( wi( k )==zero ) then if( select( k ) )m = m + 1_${ik}$ else pair = .true. if( select( k ) .or. select( k+1 ) ) then select( k ) = .true. m = m + 2_${ik}$ end if end if end if end do info = 0_${ik}$ if( .not.rightv .and. .not.leftv ) then info = -1_${ik}$ else if( .not.fromqr .and. .not.stdlib_lsame( eigsrc, 'N' ) ) then info = -2_${ik}$ else if( .not.noinit .and. .not.stdlib_lsame( initv, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldhkr ) then do i = k, n - 1 if( h( i+1, i )==zero )go to 50 end do 50 continue kr = i end if end if if( kl/=kln ) then kln = kl ! compute infinity-norm of submatrix h(kl:kr,kl:kr) if it ! has not ben computed before. hnorm = stdlib${ii}$_${ri}$lanhs( 'I', kr-kl+1, h( kl, kl ), ldh, work ) if( stdlib${ii}$_${ri}$isnan( hnorm ) ) then info = -6_${ik}$ return else if( hnorm>zero ) then eps3 = hnorm*ulp else eps3 = smlnum end if end if ! perturb eigenvalue if it is close to any previous ! selected eigenvalues affiliated to the submatrix ! h(kl:kr,kl:kr). close roots are modified by eps3. wkr = wr( k ) wki = wi( k ) 60 continue do i = k - 1, kl, -1 if( select( i ) .and. abs( wr( i )-wkr )+abs( wi( i )-wki )0_${ik}$ ) then if( pair ) then info = info + 2_${ik}$ else info = info + 1_${ik}$ end if ifaill( ksr ) = k ifaill( ksi ) = k else ifaill( ksr ) = 0_${ik}$ ifaill( ksi ) = 0_${ik}$ end if do i = 1, kl - 1 vl( i, ksr ) = zero end do if( pair ) then do i = 1, kl - 1 vl( i, ksi ) = zero end do end if end if if( rightv ) then ! compute right eigenvector. call stdlib${ii}$_${ri}$laein( .true., noinit, kr, h, ldh, wkr, wki,vr( 1_${ik}$, ksr ), vr( 1_${ik}$, & ksi ), work, ldwork,work( n*n+n+1 ), eps3, smlnum, bignum,iinfo ) if( iinfo>0_${ik}$ ) then if( pair ) then info = info + 2_${ik}$ else info = info + 1_${ik}$ end if ifailr( ksr ) = k ifailr( ksi ) = k else ifailr( ksr ) = 0_${ik}$ ifailr( ksi ) = 0_${ik}$ end if do i = kr + 1, n vr( i, ksr ) = zero end do if( pair ) then do i = kr + 1, n vr( i, ksi ) = zero end do end if end if if( pair ) then ksr = ksr + 2_${ik}$ else ksr = ksr + 1_${ik}$ end if end if end do loop_120 return end subroutine stdlib${ii}$_${ri}$hsein #:endif #:endfor module subroutine stdlib${ii}$_chsein( side, eigsrc, initv, select, n, h, ldh, w, vl,ldvl, vr, ldvr, mm, & !! CHSEIN uses inverse iteration to find specified right and/or left !! eigenvectors of a complex upper Hessenberg matrix H. !! The right eigenvector x and the left eigenvector y of the matrix H !! corresponding to an eigenvalue w are defined by: !! H * x = w * x, y**h * H = w * y**h !! where y**h denotes the conjugate transpose of the vector y. m, work, rwork, ifaill,ifailr, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: eigsrc, initv, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldh, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(in) :: select(*) integer(${ik}$), intent(out) :: ifaill(*), ifailr(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(in) :: h(ldh,*) complex(sp), intent(inout) :: vl(ldvl,*), vr(ldvr,*), w(*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Parameters ! Local Scalars logical(lk) :: bothv, fromqr, leftv, noinit, rightv integer(${ik}$) :: i, iinfo, k, kl, kln, kr, ks, ldwork real(sp) :: eps3, hnorm, smlnum, ulp, unfl complex(sp) :: cdum, wk ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements ! decode and test the input parameters. bothv = stdlib_lsame( side, 'B' ) rightv = stdlib_lsame( side, 'R' ) .or. bothv leftv = stdlib_lsame( side, 'L' ) .or. bothv fromqr = stdlib_lsame( eigsrc, 'Q' ) noinit = stdlib_lsame( initv, 'N' ) ! set m to the number of columns required to store the selected ! eigenvectors. m = 0_${ik}$ do k = 1, n if( select( k ) )m = m + 1_${ik}$ end do info = 0_${ik}$ if( .not.rightv .and. .not.leftv ) then info = -1_${ik}$ else if( .not.fromqr .and. .not.stdlib_lsame( eigsrc, 'N' ) ) then info = -2_${ik}$ else if( .not.noinit .and. .not.stdlib_lsame( initv, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldhkr ) then do i = k, n - 1 if( h( i+1, i )==czero )go to 50 end do 50 continue kr = i end if end if if( kl/=kln ) then kln = kl ! compute infinity-norm of submatrix h(kl:kr,kl:kr) if it ! has not ben computed before. hnorm = stdlib${ii}$_clanhs( 'I', kr-kl+1, h( kl, kl ), ldh, rwork ) if( stdlib${ii}$_sisnan( hnorm ) ) then info = -6_${ik}$ return else if( (hnorm>zero) ) then eps3 = hnorm*ulp else eps3 = smlnum end if end if ! perturb eigenvalue if it is close to any previous ! selected eigenvalues affiliated to the submatrix ! h(kl:kr,kl:kr). close roots are modified by eps3. wk = w( k ) 60 continue do i = k - 1, kl, -1 if( select( i ) .and. cabs1( w( i )-wk )0_${ik}$ ) then info = info + 1_${ik}$ ifaill( ks ) = k else ifaill( ks ) = 0_${ik}$ end if do i = 1, kl - 1 vl( i, ks ) = czero end do end if if( rightv ) then ! compute right eigenvector. call stdlib${ii}$_claein( .true., noinit, kr, h, ldh, wk, vr( 1_${ik}$, ks ),work, ldwork, & rwork, eps3, smlnum, iinfo ) if( iinfo>0_${ik}$ ) then info = info + 1_${ik}$ ifailr( ks ) = k else ifailr( ks ) = 0_${ik}$ end if do i = kr + 1, n vr( i, ks ) = czero end do end if ks = ks + 1_${ik}$ end if end do loop_100 return end subroutine stdlib${ii}$_chsein module subroutine stdlib${ii}$_zhsein( side, eigsrc, initv, select, n, h, ldh, w, vl,ldvl, vr, ldvr, mm, & !! ZHSEIN uses inverse iteration to find specified right and/or left !! eigenvectors of a complex upper Hessenberg matrix H. !! The right eigenvector x and the left eigenvector y of the matrix H !! corresponding to an eigenvalue w are defined by: !! H * x = w * x, y**h * H = w * y**h !! where y**h denotes the conjugate transpose of the vector y. m, work, rwork, ifaill,ifailr, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: eigsrc, initv, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldh, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(in) :: select(*) integer(${ik}$), intent(out) :: ifaill(*), ifailr(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(in) :: h(ldh,*) complex(dp), intent(inout) :: vl(ldvl,*), vr(ldvr,*), w(*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters ! Local Scalars logical(lk) :: bothv, fromqr, leftv, noinit, rightv integer(${ik}$) :: i, iinfo, k, kl, kln, kr, ks, ldwork real(dp) :: eps3, hnorm, smlnum, ulp, unfl complex(dp) :: cdum, wk ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements ! decode and test the input parameters. bothv = stdlib_lsame( side, 'B' ) rightv = stdlib_lsame( side, 'R' ) .or. bothv leftv = stdlib_lsame( side, 'L' ) .or. bothv fromqr = stdlib_lsame( eigsrc, 'Q' ) noinit = stdlib_lsame( initv, 'N' ) ! set m to the number of columns required to store the selected ! eigenvectors. m = 0_${ik}$ do k = 1, n if( select( k ) )m = m + 1_${ik}$ end do info = 0_${ik}$ if( .not.rightv .and. .not.leftv ) then info = -1_${ik}$ else if( .not.fromqr .and. .not.stdlib_lsame( eigsrc, 'N' ) ) then info = -2_${ik}$ else if( .not.noinit .and. .not.stdlib_lsame( initv, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldhkr ) then do i = k, n - 1 if( h( i+1, i )==czero )go to 50 end do 50 continue kr = i end if end if if( kl/=kln ) then kln = kl ! compute infinity-norm of submatrix h(kl:kr,kl:kr) if it ! has not ben computed before. hnorm = stdlib${ii}$_zlanhs( 'I', kr-kl+1, h( kl, kl ), ldh, rwork ) if( stdlib${ii}$_disnan( hnorm ) ) then info = -6_${ik}$ return else if( hnorm>zero ) then eps3 = hnorm*ulp else eps3 = smlnum end if end if ! perturb eigenvalue if it is close to any previous ! selected eigenvalues affiliated to the submatrix ! h(kl:kr,kl:kr). close roots are modified by eps3. wk = w( k ) 60 continue do i = k - 1, kl, -1 if( select( i ) .and. cabs1( w( i )-wk )0_${ik}$ ) then info = info + 1_${ik}$ ifaill( ks ) = k else ifaill( ks ) = 0_${ik}$ end if do i = 1, kl - 1 vl( i, ks ) = czero end do end if if( rightv ) then ! compute right eigenvector. call stdlib${ii}$_zlaein( .true., noinit, kr, h, ldh, wk, vr( 1_${ik}$, ks ),work, ldwork, & rwork, eps3, smlnum, iinfo ) if( iinfo>0_${ik}$ ) then info = info + 1_${ik}$ ifailr( ks ) = k else ifailr( ks ) = 0_${ik}$ end if do i = kr + 1, n vr( i, ks ) = czero end do end if ks = ks + 1_${ik}$ end if end do loop_100 return end subroutine stdlib${ii}$_zhsein #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hsein( side, eigsrc, initv, select, n, h, ldh, w, vl,ldvl, vr, ldvr, mm, & !! ZHSEIN: uses inverse iteration to find specified right and/or left !! eigenvectors of a complex upper Hessenberg matrix H. !! The right eigenvector x and the left eigenvector y of the matrix H !! corresponding to an eigenvalue w are defined by: !! H * x = w * x, y**h * H = w * y**h !! where y**h denotes the conjugate transpose of the vector y. m, work, rwork, ifaill,ifailr, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: eigsrc, initv, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldh, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(in) :: select(*) integer(${ik}$), intent(out) :: ifaill(*), ifailr(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(in) :: h(ldh,*) complex(${ck}$), intent(inout) :: vl(ldvl,*), vr(ldvr,*), w(*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Parameters ! Local Scalars logical(lk) :: bothv, fromqr, leftv, noinit, rightv integer(${ik}$) :: i, iinfo, k, kl, kln, kr, ks, ldwork real(${ck}$) :: eps3, hnorm, smlnum, ulp, unfl complex(${ck}$) :: cdum, wk ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements ! decode and test the input parameters. bothv = stdlib_lsame( side, 'B' ) rightv = stdlib_lsame( side, 'R' ) .or. bothv leftv = stdlib_lsame( side, 'L' ) .or. bothv fromqr = stdlib_lsame( eigsrc, 'Q' ) noinit = stdlib_lsame( initv, 'N' ) ! set m to the number of columns required to store the selected ! eigenvectors. m = 0_${ik}$ do k = 1, n if( select( k ) )m = m + 1_${ik}$ end do info = 0_${ik}$ if( .not.rightv .and. .not.leftv ) then info = -1_${ik}$ else if( .not.fromqr .and. .not.stdlib_lsame( eigsrc, 'N' ) ) then info = -2_${ik}$ else if( .not.noinit .and. .not.stdlib_lsame( initv, 'U' ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldhkr ) then do i = k, n - 1 if( h( i+1, i )==czero )go to 50 end do 50 continue kr = i end if end if if( kl/=kln ) then kln = kl ! compute infinity-norm of submatrix h(kl:kr,kl:kr) if it ! has not ben computed before. hnorm = stdlib${ii}$_${ci}$lanhs( 'I', kr-kl+1, h( kl, kl ), ldh, rwork ) if( stdlib${ii}$_${c2ri(ci)}$isnan( hnorm ) ) then info = -6_${ik}$ return else if( hnorm>zero ) then eps3 = hnorm*ulp else eps3 = smlnum end if end if ! perturb eigenvalue if it is close to any previous ! selected eigenvalues affiliated to the submatrix ! h(kl:kr,kl:kr). close roots are modified by eps3. wk = w( k ) 60 continue do i = k - 1, kl, -1 if( select( i ) .and. cabs1( w( i )-wk )0_${ik}$ ) then info = info + 1_${ik}$ ifaill( ks ) = k else ifaill( ks ) = 0_${ik}$ end if do i = 1, kl - 1 vl( i, ks ) = czero end do end if if( rightv ) then ! compute right eigenvector. call stdlib${ii}$_${ci}$laein( .true., noinit, kr, h, ldh, wk, vr( 1_${ik}$, ks ),work, ldwork, & rwork, eps3, smlnum, iinfo ) if( iinfo>0_${ik}$ ) then info = info + 1_${ik}$ ifailr( ks ) = k else ifailr( ks ) = 0_${ik}$ end if do i = kr + 1, n vr( i, ks ) = czero end do end if ks = ks + 1_${ik}$ end if end do loop_100 return end subroutine stdlib${ii}$_${ci}$hsein #:endif #:endfor pure module subroutine stdlib${ii}$_strevc( side, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, mm, m, & !! STREVC computes some or all of the right and/or left eigenvectors of !! a real upper quasi-triangular matrix T. !! Matrices of this type are produced by the Schur factorization of !! a real general matrix: A = Q*T*Q**T, as computed by SHSEQR. !! The right eigenvector x and the left eigenvector y of T corresponding !! to an eigenvalue w are defined by: !! T*x = w*x, (y**H)*T = w*(y**H) !! where y**H denotes the conjugate transpose of y. !! The eigenvalues are not input to this routine, but are read directly !! from the diagonal blocks of T. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an !! input matrix. If Q is the orthogonal factor that reduces a matrix !! A to Schur form T, then Q*X and Q*Y are the matrices of right and !! left eigenvectors of A. work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: howmny, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldt, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(inout) :: select(*) real(sp), intent(in) :: t(ldt,*) real(sp), intent(inout) :: vl(ldvl,*), vr(ldvr,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: allv, bothv, leftv, over, pair, rightv, somev integer(${ik}$) :: i, ierr, ii, ip, is, j, j1, j2, jnxt, k, ki, n2 real(sp) :: beta, bignum, emax, ovfl, rec, remax, scale, smin, smlnum, ulp, unfl, & vcrit, vmax, wi, wr, xnorm ! Intrinsic Functions ! Local Arrays real(sp) :: x(2_${ik}$,2_${ik}$) ! Executable Statements ! decode and test the input parameters bothv = stdlib_lsame( side, 'B' ) rightv = stdlib_lsame( side, 'R' ) .or. bothv leftv = stdlib_lsame( side, 'L' ) .or. bothv allv = stdlib_lsame( howmny, 'A' ) over = stdlib_lsame( howmny, 'B' ) somev = stdlib_lsame( howmny, 'S' ) info = 0_${ik}$ if( .not.rightv .and. .not.leftv ) then info = -1_${ik}$ else if( .not.allv .and. .not.over .and. .not.somev ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ldtjnxt )cycle loop_60 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_slaln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_saxpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_slaln2( .false., 2_${ik}$, 1_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+n ), n, wr, zero, x, 2_${ik}$,scale, xnorm, ierr ) ! scale x(1,1) and x(2,1) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) work( j-1+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n ) = x( 2_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_saxpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_saxpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) end if end do loop_60 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then call stdlib${ii}$_scopy( ki, work( 1_${ik}$+n ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_isamax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / abs( vr( ii, is ) ) call stdlib${ii}$_sscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = zero end do else if( ki>1_${ik}$ )call stdlib${ii}$_sgemv( 'N', n, ki-1, one, vr, ldvr,work( 1_${ik}$+n ), 1_${ik}$, & work( ki+n ),vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_isamax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / abs( vr( ii, ki ) ) call stdlib${ii}$_sscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) end if else ! complex right eigenvector. ! initial solve ! [ (t(ki-1,ki-1) t(ki-1,ki) ) - (wr + i* wi)]*x = 0. ! [ (t(ki,ki-1) t(ki,ki) ) ] if( abs( t( ki-1, ki ) )>=abs( t( ki, ki-1 ) ) ) then work( ki-1+n ) = one work( ki+n2 ) = wi / t( ki-1, ki ) else work( ki-1+n ) = -wi / t( ki, ki-1 ) work( ki+n2 ) = one end if work( ki+n ) = zero work( ki-1+n2 ) = zero ! form right-hand side do k = 1, ki - 2 work( k+n ) = -work( ki-1+n )*t( k, ki-1 ) work( k+n2 ) = -work( ki+n2 )*t( k, ki ) end do ! solve upper quasi-triangular system: ! (t(1:ki-2,1:ki-2) - (wr+i*wi))*x = scale*(work+i*work2) jnxt = ki - 2_${ik}$ loop_90: do j = ki - 2, 1, -1 if( j>jnxt )cycle loop_90 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_slaln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr, wi,x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) and x(1,2) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+n2 ), 1_${ik}$ ) end if work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n2 ) = x( 1_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_saxpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_saxpy( j-1, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n2 ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_slaln2( .false., 2_${ik}$, 2_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+n ), n, wr, wi, x, 2_${ik}$, scale,xnorm, ierr ) ! scale x to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then rec = one / xnorm x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ )*rec x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ )*rec x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ )*rec x( 2_${ik}$, 2_${ik}$ ) = x( 2_${ik}$, 2_${ik}$ )*rec scale = scale*rec end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+n2 ), 1_${ik}$ ) end if work( j-1+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n ) = x( 2_${ik}$, 1_${ik}$ ) work( j-1+n2 ) = x( 1_${ik}$, 2_${ik}$ ) work( j+n2 ) = x( 2_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_saxpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_saxpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_saxpy( j-2, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+n2 ), 1_${ik}$ ) call stdlib${ii}$_saxpy( j-2, -x( 2_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n2 ), 1_${ik}$ ) end if end do loop_90 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then call stdlib${ii}$_scopy( ki, work( 1_${ik}$+n ), 1_${ik}$, vr( 1_${ik}$, is-1 ), 1_${ik}$ ) call stdlib${ii}$_scopy( ki, work( 1_${ik}$+n2 ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) emax = zero do k = 1, ki emax = max( emax, abs( vr( k, is-1 ) )+abs( vr( k, is ) ) ) end do remax = one / emax call stdlib${ii}$_sscal( ki, remax, vr( 1_${ik}$, is-1 ), 1_${ik}$ ) call stdlib${ii}$_sscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is-1 ) = zero vr( k, is ) = zero end do else if( ki>2_${ik}$ ) then call stdlib${ii}$_sgemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$+n ), 1_${ik}$, work( ki-& 1_${ik}$+n ),vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_sgemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$+n2 ), 1_${ik}$, work( & ki+n2 ),vr( 1_${ik}$, ki ), 1_${ik}$ ) else call stdlib${ii}$_sscal( n, work( ki-1+n ), vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, work( ki+n2 ), vr( 1_${ik}$, ki ), 1_${ik}$ ) end if emax = zero do k = 1, n emax = max( emax, abs( vr( k, ki-1 ) )+abs( vr( k, ki ) ) ) end do remax = one / emax call stdlib${ii}$_sscal( n, remax, vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) end if end if is = is - 1_${ik}$ if( ip/=0_${ik}$ )is = is - 1_${ik}$ 130 continue if( ip==1_${ik}$ )ip = 0_${ik}$ if( ip==-1_${ik}$ )ip = 1_${ik}$ end do loop_140 end if if( leftv ) then ! compute left eigenvectors. ip = 0_${ik}$ is = 1_${ik}$ loop_260: do ki = 1, n if( ip==-1 )go to 250 if( ki==n )go to 150 if( t( ki+1, ki )==zero )go to 150 ip = 1_${ik}$ 150 continue if( somev ) then if( .not.select( ki ) )go to 250 end if ! compute the ki-th eigenvalue (wr,wi). wr = t( ki, ki ) wi = zero if( ip/=0_${ik}$ )wi = sqrt( abs( t( ki, ki+1 ) ) )*sqrt( abs( t( ki+1, ki ) ) ) smin = max( ulp*( abs( wr )+abs( wi ) ), smlnum ) if( ip==0_${ik}$ ) then ! real left eigenvector. work( ki+n ) = one ! form right-hand side do k = ki + 1, n work( k+n ) = -t( ki, k ) end do ! solve the quasi-triangular system: ! (t(ki+1:n,ki+1:n) - wr)**t*x = scale*work vmax = one vcrit = bignum jnxt = ki + 1_${ik}$ loop_170: do j = ki + 1, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_sscal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_sdot( j-ki-1, t( ki+1, j ), 1_${ik}$,work( & ki+1+n ), 1_${ik}$ ) ! solve (t(j,j)-wr)**t*x = work call stdlib${ii}$_slaln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_sscal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j+n ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_sscal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_sdot( j-ki-1, t( ki+1, j ), 1_${ik}$,work( & ki+1+n ), 1_${ik}$ ) work( j+1+n ) = work( j+1+n ) -stdlib${ii}$_sdot( j-ki-1, t( ki+1, j+1 ), 1_${ik}$,& work( ki+1+n ), 1_${ik}$ ) ! solve ! [t(j,j)-wr t(j,j+1) ]**t* x = scale*( work1 ) ! [t(j+1,j) t(j+1,j+1)-wr] ( work2 ) call stdlib${ii}$_slaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_sscal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+1+n ) = x( 2_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j+n ) ),abs( work( j+1+n ) ), vmax ) vcrit = bignum / vmax end if end do loop_170 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then call stdlib${ii}$_scopy( n-ki+1, work( ki+n ), 1_${ik}$, vl( ki, is ), 1_${ik}$ ) ii = stdlib${ii}$_isamax( n-ki+1, vl( ki, is ), 1_${ik}$ ) + ki - 1_${ik}$ remax = one / abs( vl( ii, is ) ) call stdlib${ii}$_sscal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero end do else if( ki=abs( t( ki+1, ki ) ) ) then work( ki+n ) = wi / t( ki, ki+1 ) work( ki+1+n2 ) = one else work( ki+n ) = one work( ki+1+n2 ) = -wi / t( ki+1, ki ) end if work( ki+1+n ) = zero work( ki+n2 ) = zero ! form right-hand side do k = ki + 2, n work( k+n ) = -work( ki+n )*t( ki, k ) work( k+n2 ) = -work( ki+1+n2 )*t( ki+1, k ) end do ! solve complex quasi-triangular system: ! ( t(ki+2,n:ki+2,n) - (wr-i*wi) )*x = work1+i*work2 vmax = one vcrit = bignum jnxt = ki + 2_${ik}$ loop_200: do j = ki + 2, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_sscal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_sscal( n-ki+1, rec, work( ki+n2 ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_sdot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n ), 1_${ik}$ ) work( j+n2 ) = work( j+n2 ) -stdlib${ii}$_sdot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n2 ), 1_${ik}$ ) ! solve (t(j,j)-(wr-i*wi))*(x11+i*x12)= wk+i*wk2 call stdlib${ii}$_slaln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_sscal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_sscal( n-ki+1, scale, work( ki+n2 ), 1_${ik}$ ) end if work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n2 ) = x( 1_${ik}$, 2_${ik}$ ) vmax = max( abs( work( j+n ) ),abs( work( j+n2 ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side elements. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_sscal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_sscal( n-ki+1, rec, work( ki+n2 ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_sdot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n ), 1_${ik}$ ) work( j+n2 ) = work( j+n2 ) -stdlib${ii}$_sdot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n2 ), 1_${ik}$ ) work( j+1+n ) = work( j+1+n ) -stdlib${ii}$_sdot( j-ki-2, t( ki+2, j+1 ), 1_${ik}$,& work( ki+2+n ), 1_${ik}$ ) work( j+1+n2 ) = work( j+1+n2 ) -stdlib${ii}$_sdot( j-ki-2, t( ki+2, j+1 ), 1_${ik}$,& work( ki+2+n2 ), 1_${ik}$ ) ! solve 2-by-2 complex linear equation ! ([t(j,j) t(j,j+1) ]**t-(wr-i*wi)*i)*x = scale*b ! ([t(j+1,j) t(j+1,j+1)] ) call stdlib${ii}$_slaln2( .true., 2_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_sscal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_sscal( n-ki+1, scale, work( ki+n2 ), 1_${ik}$ ) end if work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n2 ) = x( 1_${ik}$, 2_${ik}$ ) work( j+1+n ) = x( 2_${ik}$, 1_${ik}$ ) work( j+1+n2 ) = x( 2_${ik}$, 2_${ik}$ ) vmax = max( abs( x( 1_${ik}$, 1_${ik}$ ) ), abs( x( 1_${ik}$, 2_${ik}$ ) ),abs( x( 2_${ik}$, 1_${ik}$ ) ), abs( x(& 2_${ik}$, 2_${ik}$ ) ), vmax ) vcrit = bignum / vmax end if end do loop_200 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then call stdlib${ii}$_scopy( n-ki+1, work( ki+n ), 1_${ik}$, vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_scopy( n-ki+1, work( ki+n2 ), 1_${ik}$, vl( ki, is+1 ),1_${ik}$ ) emax = zero do k = ki, n emax = max( emax, abs( vl( k, is ) )+abs( vl( k, is+1 ) ) ) end do remax = one / emax call stdlib${ii}$_sscal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_sscal( n-ki+1, remax, vl( ki, is+1 ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero vl( k, is+1 ) = zero end do else if( kijnxt )cycle loop_60 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_dlaln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_daxpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_dlaln2( .false., 2_${ik}$, 1_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+n ), n, wr, zero, x, 2_${ik}$,scale, xnorm, ierr ) ! scale x(1,1) and x(2,1) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) work( j-1+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n ) = x( 2_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_daxpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_daxpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) end if end do loop_60 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then call stdlib${ii}$_dcopy( ki, work( 1_${ik}$+n ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_idamax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / abs( vr( ii, is ) ) call stdlib${ii}$_dscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = zero end do else if( ki>1_${ik}$ )call stdlib${ii}$_dgemv( 'N', n, ki-1, one, vr, ldvr,work( 1_${ik}$+n ), 1_${ik}$, & work( ki+n ),vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_idamax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / abs( vr( ii, ki ) ) call stdlib${ii}$_dscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) end if else ! complex right eigenvector. ! initial solve ! [ (t(ki-1,ki-1) t(ki-1,ki) ) - (wr + i* wi)]*x = 0. ! [ (t(ki,ki-1) t(ki,ki) ) ] if( abs( t( ki-1, ki ) )>=abs( t( ki, ki-1 ) ) ) then work( ki-1+n ) = one work( ki+n2 ) = wi / t( ki-1, ki ) else work( ki-1+n ) = -wi / t( ki, ki-1 ) work( ki+n2 ) = one end if work( ki+n ) = zero work( ki-1+n2 ) = zero ! form right-hand side do k = 1, ki - 2 work( k+n ) = -work( ki-1+n )*t( k, ki-1 ) work( k+n2 ) = -work( ki+n2 )*t( k, ki ) end do ! solve upper quasi-triangular system: ! (t(1:ki-2,1:ki-2) - (wr+i*wi))*x = scale*(work+i*work2) jnxt = ki - 2_${ik}$ loop_90: do j = ki - 2, 1, -1 if( j>jnxt )cycle loop_90 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_dlaln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr, wi,x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) and x(1,2) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+n2 ), 1_${ik}$ ) end if work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n2 ) = x( 1_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_daxpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_daxpy( j-1, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n2 ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_dlaln2( .false., 2_${ik}$, 2_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+n ), n, wr, wi, x, 2_${ik}$, scale,xnorm, ierr ) ! scale x to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then rec = one / xnorm x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ )*rec x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ )*rec x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ )*rec x( 2_${ik}$, 2_${ik}$ ) = x( 2_${ik}$, 2_${ik}$ )*rec scale = scale*rec end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+n2 ), 1_${ik}$ ) end if work( j-1+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n ) = x( 2_${ik}$, 1_${ik}$ ) work( j-1+n2 ) = x( 1_${ik}$, 2_${ik}$ ) work( j+n2 ) = x( 2_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_daxpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_daxpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_daxpy( j-2, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+n2 ), 1_${ik}$ ) call stdlib${ii}$_daxpy( j-2, -x( 2_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n2 ), 1_${ik}$ ) end if end do loop_90 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then call stdlib${ii}$_dcopy( ki, work( 1_${ik}$+n ), 1_${ik}$, vr( 1_${ik}$, is-1 ), 1_${ik}$ ) call stdlib${ii}$_dcopy( ki, work( 1_${ik}$+n2 ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) emax = zero do k = 1, ki emax = max( emax, abs( vr( k, is-1 ) )+abs( vr( k, is ) ) ) end do remax = one / emax call stdlib${ii}$_dscal( ki, remax, vr( 1_${ik}$, is-1 ), 1_${ik}$ ) call stdlib${ii}$_dscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is-1 ) = zero vr( k, is ) = zero end do else if( ki>2_${ik}$ ) then call stdlib${ii}$_dgemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$+n ), 1_${ik}$, work( ki-& 1_${ik}$+n ),vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_dgemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$+n2 ), 1_${ik}$, work( & ki+n2 ),vr( 1_${ik}$, ki ), 1_${ik}$ ) else call stdlib${ii}$_dscal( n, work( ki-1+n ), vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, work( ki+n2 ), vr( 1_${ik}$, ki ), 1_${ik}$ ) end if emax = zero do k = 1, n emax = max( emax, abs( vr( k, ki-1 ) )+abs( vr( k, ki ) ) ) end do remax = one / emax call stdlib${ii}$_dscal( n, remax, vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) end if end if is = is - 1_${ik}$ if( ip/=0_${ik}$ )is = is - 1_${ik}$ 130 continue if( ip==1_${ik}$ )ip = 0_${ik}$ if( ip==-1_${ik}$ )ip = 1_${ik}$ end do loop_140 end if if( leftv ) then ! compute left eigenvectors. ip = 0_${ik}$ is = 1_${ik}$ loop_260: do ki = 1, n if( ip==-1 )go to 250 if( ki==n )go to 150 if( t( ki+1, ki )==zero )go to 150 ip = 1_${ik}$ 150 continue if( somev ) then if( .not.select( ki ) )go to 250 end if ! compute the ki-th eigenvalue (wr,wi). wr = t( ki, ki ) wi = zero if( ip/=0_${ik}$ )wi = sqrt( abs( t( ki, ki+1 ) ) )*sqrt( abs( t( ki+1, ki ) ) ) smin = max( ulp*( abs( wr )+abs( wi ) ), smlnum ) if( ip==0_${ik}$ ) then ! real left eigenvector. work( ki+n ) = one ! form right-hand side do k = ki + 1, n work( k+n ) = -t( ki, k ) end do ! solve the quasi-triangular system: ! (t(ki+1:n,ki+1:n) - wr)**t*x = scale*work vmax = one vcrit = bignum jnxt = ki + 1_${ik}$ loop_170: do j = ki + 1, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_dscal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_ddot( j-ki-1, t( ki+1, j ), 1_${ik}$,work( & ki+1+n ), 1_${ik}$ ) ! solve (t(j,j)-wr)**t*x = work call stdlib${ii}$_dlaln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_dscal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j+n ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_dscal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_ddot( j-ki-1, t( ki+1, j ), 1_${ik}$,work( & ki+1+n ), 1_${ik}$ ) work( j+1+n ) = work( j+1+n ) -stdlib${ii}$_ddot( j-ki-1, t( ki+1, j+1 ), 1_${ik}$,& work( ki+1+n ), 1_${ik}$ ) ! solve ! [t(j,j)-wr t(j,j+1) ]**t * x = scale*( work1 ) ! [t(j+1,j) t(j+1,j+1)-wr] ( work2 ) call stdlib${ii}$_dlaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_dscal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+1+n ) = x( 2_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j+n ) ),abs( work( j+1+n ) ), vmax ) vcrit = bignum / vmax end if end do loop_170 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then call stdlib${ii}$_dcopy( n-ki+1, work( ki+n ), 1_${ik}$, vl( ki, is ), 1_${ik}$ ) ii = stdlib${ii}$_idamax( n-ki+1, vl( ki, is ), 1_${ik}$ ) + ki - 1_${ik}$ remax = one / abs( vl( ii, is ) ) call stdlib${ii}$_dscal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero end do else if( ki=abs( t( ki+1, ki ) ) ) then work( ki+n ) = wi / t( ki, ki+1 ) work( ki+1+n2 ) = one else work( ki+n ) = one work( ki+1+n2 ) = -wi / t( ki+1, ki ) end if work( ki+1+n ) = zero work( ki+n2 ) = zero ! form right-hand side do k = ki + 2, n work( k+n ) = -work( ki+n )*t( ki, k ) work( k+n2 ) = -work( ki+1+n2 )*t( ki+1, k ) end do ! solve complex quasi-triangular system: ! ( t(ki+2,n:ki+2,n) - (wr-i*wi) )*x = work1+i*work2 vmax = one vcrit = bignum jnxt = ki + 2_${ik}$ loop_200: do j = ki + 2, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_dscal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_dscal( n-ki+1, rec, work( ki+n2 ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_ddot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n ), 1_${ik}$ ) work( j+n2 ) = work( j+n2 ) -stdlib${ii}$_ddot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n2 ), 1_${ik}$ ) ! solve (t(j,j)-(wr-i*wi))*(x11+i*x12)= wk+i*wk2 call stdlib${ii}$_dlaln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_dscal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_dscal( n-ki+1, scale, work( ki+n2 ), 1_${ik}$ ) end if work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n2 ) = x( 1_${ik}$, 2_${ik}$ ) vmax = max( abs( work( j+n ) ),abs( work( j+n2 ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side elements. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_dscal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_dscal( n-ki+1, rec, work( ki+n2 ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_ddot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n ), 1_${ik}$ ) work( j+n2 ) = work( j+n2 ) -stdlib${ii}$_ddot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n2 ), 1_${ik}$ ) work( j+1+n ) = work( j+1+n ) -stdlib${ii}$_ddot( j-ki-2, t( ki+2, j+1 ), 1_${ik}$,& work( ki+2+n ), 1_${ik}$ ) work( j+1+n2 ) = work( j+1+n2 ) -stdlib${ii}$_ddot( j-ki-2, t( ki+2, j+1 ), 1_${ik}$,& work( ki+2+n2 ), 1_${ik}$ ) ! solve 2-by-2 complex linear equation ! ([t(j,j) t(j,j+1) ]**t-(wr-i*wi)*i)*x = scale*b ! ([t(j+1,j) t(j+1,j+1)] ) call stdlib${ii}$_dlaln2( .true., 2_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_dscal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_dscal( n-ki+1, scale, work( ki+n2 ), 1_${ik}$ ) end if work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n2 ) = x( 1_${ik}$, 2_${ik}$ ) work( j+1+n ) = x( 2_${ik}$, 1_${ik}$ ) work( j+1+n2 ) = x( 2_${ik}$, 2_${ik}$ ) vmax = max( abs( x( 1_${ik}$, 1_${ik}$ ) ), abs( x( 1_${ik}$, 2_${ik}$ ) ),abs( x( 2_${ik}$, 1_${ik}$ ) ), abs( x(& 2_${ik}$, 2_${ik}$ ) ), vmax ) vcrit = bignum / vmax end if end do loop_200 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then call stdlib${ii}$_dcopy( n-ki+1, work( ki+n ), 1_${ik}$, vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_dcopy( n-ki+1, work( ki+n2 ), 1_${ik}$, vl( ki, is+1 ),1_${ik}$ ) emax = zero do k = ki, n emax = max( emax, abs( vl( k, is ) )+abs( vl( k, is+1 ) ) ) end do remax = one / emax call stdlib${ii}$_dscal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_dscal( n-ki+1, remax, vl( ki, is+1 ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero vl( k, is+1 ) = zero end do else if( kijnxt )cycle loop_60 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_${ri}$laln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_${ri}$axpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_${ri}$laln2( .false., 2_${ik}$, 1_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+n ), n, wr, zero, x, 2_${ik}$,scale, xnorm, ierr ) ! scale x(1,1) and x(2,1) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) work( j-1+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n ) = x( 2_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_${ri}$axpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) end if end do loop_60 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then call stdlib${ii}$_${ri}$copy( ki, work( 1_${ik}$+n ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_i${ri}$amax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / abs( vr( ii, is ) ) call stdlib${ii}$_${ri}$scal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = zero end do else if( ki>1_${ik}$ )call stdlib${ii}$_${ri}$gemv( 'N', n, ki-1, one, vr, ldvr,work( 1_${ik}$+n ), 1_${ik}$, & work( ki+n ),vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_i${ri}$amax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / abs( vr( ii, ki ) ) call stdlib${ii}$_${ri}$scal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) end if else ! complex right eigenvector. ! initial solve ! [ (t(ki-1,ki-1) t(ki-1,ki) ) - (wr + i* wi)]*x = 0. ! [ (t(ki,ki-1) t(ki,ki) ) ] if( abs( t( ki-1, ki ) )>=abs( t( ki, ki-1 ) ) ) then work( ki-1+n ) = one work( ki+n2 ) = wi / t( ki-1, ki ) else work( ki-1+n ) = -wi / t( ki, ki-1 ) work( ki+n2 ) = one end if work( ki+n ) = zero work( ki-1+n2 ) = zero ! form right-hand side do k = 1, ki - 2 work( k+n ) = -work( ki-1+n )*t( k, ki-1 ) work( k+n2 ) = -work( ki+n2 )*t( k, ki ) end do ! solve upper quasi-triangular system: ! (t(1:ki-2,1:ki-2) - (wr+i*wi))*x = scale*(work+i*work2) jnxt = ki - 2_${ik}$ loop_90: do j = ki - 2, 1, -1 if( j>jnxt )cycle loop_90 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_${ri}$laln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr, wi,x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) and x(1,2) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+n2 ), 1_${ik}$ ) end if work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n2 ) = x( 1_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_${ri}$axpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j-1, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n2 ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_${ri}$laln2( .false., 2_${ik}$, 2_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+n ), n, wr, wi, x, 2_${ik}$, scale,xnorm, ierr ) ! scale x to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then rec = one / xnorm x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ )*rec x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ )*rec x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ )*rec x( 2_${ik}$, 2_${ik}$ ) = x( 2_${ik}$, 2_${ik}$ )*rec scale = scale*rec end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+n2 ), 1_${ik}$ ) end if work( j-1+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n ) = x( 2_${ik}$, 1_${ik}$ ) work( j-1+n2 ) = x( 1_${ik}$, 2_${ik}$ ) work( j+n2 ) = x( 2_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_${ri}$axpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j-2, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+n2 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j-2, -x( 2_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+n2 ), 1_${ik}$ ) end if end do loop_90 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then call stdlib${ii}$_${ri}$copy( ki, work( 1_${ik}$+n ), 1_${ik}$, vr( 1_${ik}$, is-1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( ki, work( 1_${ik}$+n2 ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) emax = zero do k = 1, ki emax = max( emax, abs( vr( k, is-1 ) )+abs( vr( k, is ) ) ) end do remax = one / emax call stdlib${ii}$_${ri}$scal( ki, remax, vr( 1_${ik}$, is-1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is-1 ) = zero vr( k, is ) = zero end do else if( ki>2_${ik}$ ) then call stdlib${ii}$_${ri}$gemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$+n ), 1_${ik}$, work( ki-& 1_${ik}$+n ),vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$+n2 ), 1_${ik}$, work( & ki+n2 ),vr( 1_${ik}$, ki ), 1_${ik}$ ) else call stdlib${ii}$_${ri}$scal( n, work( ki-1+n ), vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, work( ki+n2 ), vr( 1_${ik}$, ki ), 1_${ik}$ ) end if emax = zero do k = 1, n emax = max( emax, abs( vr( k, ki-1 ) )+abs( vr( k, ki ) ) ) end do remax = one / emax call stdlib${ii}$_${ri}$scal( n, remax, vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) end if end if is = is - 1_${ik}$ if( ip/=0_${ik}$ )is = is - 1_${ik}$ 130 continue if( ip==1_${ik}$ )ip = 0_${ik}$ if( ip==-1_${ik}$ )ip = 1_${ik}$ end do loop_140 end if if( leftv ) then ! compute left eigenvectors. ip = 0_${ik}$ is = 1_${ik}$ loop_260: do ki = 1, n if( ip==-1 )go to 250 if( ki==n )go to 150 if( t( ki+1, ki )==zero )go to 150 ip = 1_${ik}$ 150 continue if( somev ) then if( .not.select( ki ) )go to 250 end if ! compute the ki-th eigenvalue (wr,wi). wr = t( ki, ki ) wi = zero if( ip/=0_${ik}$ )wi = sqrt( abs( t( ki, ki+1 ) ) )*sqrt( abs( t( ki+1, ki ) ) ) smin = max( ulp*( abs( wr )+abs( wi ) ), smlnum ) if( ip==0_${ik}$ ) then ! real left eigenvector. work( ki+n ) = one ! form right-hand side do k = ki + 1, n work( k+n ) = -t( ki, k ) end do ! solve the quasi-triangular system: ! (t(ki+1:n,ki+1:n) - wr)**t*x = scale*work vmax = one vcrit = bignum jnxt = ki + 1_${ik}$ loop_170: do j = ki + 1, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_${ri}$dot( j-ki-1, t( ki+1, j ), 1_${ik}$,work( & ki+1+n ), 1_${ik}$ ) ! solve (t(j,j)-wr)**t*x = work call stdlib${ii}$_${ri}$laln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j+n ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_${ri}$dot( j-ki-1, t( ki+1, j ), 1_${ik}$,work( & ki+1+n ), 1_${ik}$ ) work( j+1+n ) = work( j+1+n ) -stdlib${ii}$_${ri}$dot( j-ki-1, t( ki+1, j+1 ), 1_${ik}$,& work( ki+1+n ), 1_${ik}$ ) ! solve ! [t(j,j)-wr t(j,j+1) ]**t * x = scale*( work1 ) ! [t(j+1,j) t(j+1,j+1)-wr] ( work2 ) call stdlib${ii}$_${ri}$laln2( .true., 2_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+1+n ) = x( 2_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j+n ) ),abs( work( j+1+n ) ), vmax ) vcrit = bignum / vmax end if end do loop_170 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then call stdlib${ii}$_${ri}$copy( n-ki+1, work( ki+n ), 1_${ik}$, vl( ki, is ), 1_${ik}$ ) ii = stdlib${ii}$_i${ri}$amax( n-ki+1, vl( ki, is ), 1_${ik}$ ) + ki - 1_${ik}$ remax = one / abs( vl( ii, is ) ) call stdlib${ii}$_${ri}$scal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero end do else if( ki=abs( t( ki+1, ki ) ) ) then work( ki+n ) = wi / t( ki, ki+1 ) work( ki+1+n2 ) = one else work( ki+n ) = one work( ki+1+n2 ) = -wi / t( ki+1, ki ) end if work( ki+1+n ) = zero work( ki+n2 ) = zero ! form right-hand side do k = ki + 2, n work( k+n ) = -work( ki+n )*t( ki, k ) work( k+n2 ) = -work( ki+1+n2 )*t( ki+1, k ) end do ! solve complex quasi-triangular system: ! ( t(ki+2,n:ki+2,n) - (wr-i*wi) )*x = work1+i*work2 vmax = one vcrit = bignum jnxt = ki + 2_${ik}$ loop_200: do j = ki + 2, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work( ki+n2 ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n ), 1_${ik}$ ) work( j+n2 ) = work( j+n2 ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n2 ), 1_${ik}$ ) ! solve (t(j,j)-(wr-i*wi))*(x11+i*x12)= wk+i*wk2 call stdlib${ii}$_${ri}$laln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work( ki+n2 ), 1_${ik}$ ) end if work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n2 ) = x( 1_${ik}$, 2_${ik}$ ) vmax = max( abs( work( j+n ) ),abs( work( j+n2 ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side elements. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work( ki+n2 ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+n ) = work( j+n ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n ), 1_${ik}$ ) work( j+n2 ) = work( j+n2 ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+2, j ), 1_${ik}$,work( & ki+2+n2 ), 1_${ik}$ ) work( j+1+n ) = work( j+1+n ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+2, j+1 ), 1_${ik}$,& work( ki+2+n ), 1_${ik}$ ) work( j+1+n2 ) = work( j+1+n2 ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+2, j+1 ), 1_${ik}$,& work( ki+2+n2 ), 1_${ik}$ ) ! solve 2-by-2 complex linear equation ! ([t(j,j) t(j,j+1) ]**t-(wr-i*wi)*i)*x = scale*b ! ([t(j+1,j) t(j+1,j+1)] ) call stdlib${ii}$_${ri}$laln2( .true., 2_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work( ki+n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work( ki+n2 ), 1_${ik}$ ) end if work( j+n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+n2 ) = x( 1_${ik}$, 2_${ik}$ ) work( j+1+n ) = x( 2_${ik}$, 1_${ik}$ ) work( j+1+n2 ) = x( 2_${ik}$, 2_${ik}$ ) vmax = max( abs( x( 1_${ik}$, 1_${ik}$ ) ), abs( x( 1_${ik}$, 2_${ik}$ ) ),abs( x( 2_${ik}$, 1_${ik}$ ) ), abs( x(& 2_${ik}$, 2_${ik}$ ) ), vmax ) vcrit = bignum / vmax end if end do loop_200 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then call stdlib${ii}$_${ri}$copy( n-ki+1, work( ki+n ), 1_${ik}$, vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n-ki+1, work( ki+n2 ), 1_${ik}$, vl( ki, is+1 ),1_${ik}$ ) emax = zero do k = ki, n emax = max( emax, abs( vl( k, is ) )+abs( vl( k, is+1 ) ) ) end do remax = one / emax call stdlib${ii}$_${ri}$scal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-ki+1, remax, vl( ki, is+1 ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero vl( k, is+1 ) = zero end do else if( ki1_${ik}$ ) then call stdlib${ii}$_clatrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', 'Y',ki-1, t, ldt, & work( 1_${ik}$ ), scale, rwork,info ) work( ki ) = scale end if ! copy the vector x or q*x to vr and normalize. if( .not.over ) then call stdlib${ii}$_ccopy( ki, work( 1_${ik}$ ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_icamax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / cabs1( vr( ii, is ) ) call stdlib${ii}$_csscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = cmzero end do else if( ki>1_${ik}$ )call stdlib${ii}$_cgemv( 'N', n, ki-1, cmone, vr, ldvr, work( 1_${ik}$ ),1_${ik}$, & cmplx( scale,KIND=sp), vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_icamax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / cabs1( vr( ii, ki ) ) call stdlib${ii}$_csscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) end if ! set back the original diagonal elements of t. do k = 1, ki - 1 t( k, k ) = work( k+n ) end do is = is - 1_${ik}$ end do loop_80 end if if( leftv ) then ! compute left eigenvectors. is = 1_${ik}$ loop_130: do ki = 1, n if( somev ) then if( .not.select( ki ) )cycle loop_130 end if smin = max( ulp*( cabs1( t( ki, ki ) ) ), smlnum ) work( n ) = cmone ! form right-hand side. do k = ki + 1, n work( k ) = -conjg( t( ki, k ) ) end do ! solve the triangular system: ! (t(ki+1:n,ki+1:n) - t(ki,ki))**h*x = scale*work. do k = ki + 1, n t( k, k ) = t( k, k ) - t( ki, ki ) if( cabs1( t( k, k ) )1_${ik}$ ) then call stdlib${ii}$_zlatrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', 'Y',ki-1, t, ldt, & work( 1_${ik}$ ), scale, rwork,info ) work( ki ) = scale end if ! copy the vector x or q*x to vr and normalize. if( .not.over ) then call stdlib${ii}$_zcopy( ki, work( 1_${ik}$ ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_izamax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / cabs1( vr( ii, is ) ) call stdlib${ii}$_zdscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = cmzero end do else if( ki>1_${ik}$ )call stdlib${ii}$_zgemv( 'N', n, ki-1, cmone, vr, ldvr, work( 1_${ik}$ ),1_${ik}$, & cmplx( scale,KIND=dp), vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_izamax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / cabs1( vr( ii, ki ) ) call stdlib${ii}$_zdscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) end if ! set back the original diagonal elements of t. do k = 1, ki - 1 t( k, k ) = work( k+n ) end do is = is - 1_${ik}$ end do loop_80 end if if( leftv ) then ! compute left eigenvectors. is = 1_${ik}$ loop_130: do ki = 1, n if( somev ) then if( .not.select( ki ) )cycle loop_130 end if smin = max( ulp*( cabs1( t( ki, ki ) ) ), smlnum ) work( n ) = cmone ! form right-hand side. do k = ki + 1, n work( k ) = -conjg( t( ki, k ) ) end do ! solve the triangular system: ! (t(ki+1:n,ki+1:n) - t(ki,ki))**h * x = scale*work. do k = ki + 1, n t( k, k ) = t( k, k ) - t( ki, ki ) if( cabs1( t( k, k ) )1_${ik}$ ) then call stdlib${ii}$_${ci}$latrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', 'Y',ki-1, t, ldt, & work( 1_${ik}$ ), scale, rwork,info ) work( ki ) = scale end if ! copy the vector x or q*x to vr and normalize. if( .not.over ) then call stdlib${ii}$_${ci}$copy( ki, work( 1_${ik}$ ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_i${ci}$amax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / cabs1( vr( ii, is ) ) call stdlib${ii}$_${ci}$dscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = cmzero end do else if( ki>1_${ik}$ )call stdlib${ii}$_${ci}$gemv( 'N', n, ki-1, cmone, vr, ldvr, work( 1_${ik}$ ),1_${ik}$, & cmplx( scale,KIND=${ck}$), vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_i${ci}$amax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / cabs1( vr( ii, ki ) ) call stdlib${ii}$_${ci}$dscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) end if ! set back the original diagonal elements of t. do k = 1, ki - 1 t( k, k ) = work( k+n ) end do is = is - 1_${ik}$ end do loop_80 end if if( leftv ) then ! compute left eigenvectors. is = 1_${ik}$ loop_130: do ki = 1, n if( somev ) then if( .not.select( ki ) )cycle loop_130 end if smin = max( ulp*( cabs1( t( ki, ki ) ) ), smlnum ) work( n ) = cmone ! form right-hand side. do k = ki + 1, n work( k ) = -conjg( t( ki, k ) ) end do ! solve the triangular system: ! (t(ki+1:n,ki+1:n) - t(ki,ki))**h * x = scale*work. do k = ki + 1, n t( k, k ) = t( k, k ) - t( ki, ki ) if( cabs1( t( k, k ) )= n + 2_${ik}$*n*nbmin ) then nb = (lwork - n) / (2_${ik}$*n) nb = min( nb, nbmax ) call stdlib${ii}$_slaset( 'F', n, 1_${ik}$+2*nb, zero, zero, work, n ) else nb = 1_${ik}$ end if ! set the constants to control overflow. unfl = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) ovfl = one / unfl call stdlib${ii}$_slabad( unfl, ovfl ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = unfl*( n / ulp ) bignum = ( one-ulp ) / smlnum ! compute 1-norm of each column of strictly upper triangular ! part of t to control overflow in triangular solver. work( 1_${ik}$ ) = zero do j = 2, n work( j ) = zero do i = 1, j - 1 work( j ) = work( j ) + abs( t( i, j ) ) end do end do ! index ip is used to specify the real or complex eigenvalue: ! ip = 0, real eigenvalue, ! 1, first of conjugate complex pair: (wr,wi) ! -1, second of conjugate complex pair: (wr,wi) ! iscomplex array stores ip for each column in current block. if( rightv ) then ! ============================================================ ! compute right eigenvectors. ! iv is index of column in current block. ! for complex right vector, uses iv-1 for real part and iv for complex part. ! non-blocked version always uses iv=2; ! blocked version starts with iv=nb, goes down to 1 or 2. ! (note the "0-th" column is used for 1-norms computed above.) iv = 2_${ik}$ if( nb>2_${ik}$ ) then iv = nb end if ip = 0_${ik}$ is = m loop_140: do ki = n, 1, -1 if( ip==-1_${ik}$ ) then ! previous iteration (ki+1) was second of conjugate pair, ! so this ki is first of conjugate pair; skip to end of loop ip = 1_${ik}$ cycle loop_140 else if( ki==1_${ik}$ ) then ! last column, so this ki must be real eigenvalue ip = 0_${ik}$ else if( t( ki, ki-1 )==zero ) then ! zero on sub-diagonal, so this ki is real eigenvalue ip = 0_${ik}$ else ! non-zero on sub-diagonal, so this ki is second of conjugate pair ip = -1_${ik}$ end if if( somev ) then if( ip==0_${ik}$ ) then if( .not.select( ki ) )cycle loop_140 else if( .not.select( ki-1 ) )cycle loop_140 end if end if ! compute the ki-th eigenvalue (wr,wi). wr = t( ki, ki ) wi = zero if( ip/=0_${ik}$ )wi = sqrt( abs( t( ki, ki-1 ) ) )*sqrt( abs( t( ki-1, ki ) ) ) smin = max( ulp*( abs( wr )+abs( wi ) ), smlnum ) if( ip==0_${ik}$ ) then ! -------------------------------------------------------- ! real right eigenvector work( ki + iv*n ) = one ! form right-hand side. do k = 1, ki - 1 work( k + iv*n ) = -t( k, ki ) end do ! solve upper quasi-triangular system: ! [ t(1:ki-1,1:ki-1) - wr ]*x = scale*work. jnxt = ki - 1_${ik}$ loop_60: do j = ki - 1, 1, -1 if( j>jnxt )cycle loop_60 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_slaln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+iv*n ), 1_${ik}$ ) work( j+iv*n ) = x( 1_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_saxpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+iv*n ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_slaln2( .false., 2_${ik}$, 1_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+iv*n ), n, wr, zero, x, 2_${ik}$,scale, xnorm, ierr ) ! scale x(1,1) and x(2,1) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+iv*n ), 1_${ik}$ ) work( j-1+iv*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j +iv*n ) = x( 2_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_saxpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+iv*n ), 1_${ik}$ ) call stdlib${ii}$_saxpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+iv*n ), 1_${ik}$ ) end if end do loop_60 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vr and normalize. call stdlib${ii}$_scopy( ki, work( 1_${ik}$ + iv*n ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_isamax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / abs( vr( ii, is ) ) call stdlib${ii}$_sscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki>1_${ik}$ )call stdlib${ii}$_sgemv( 'N', n, ki-1, one, vr, ldvr,work( 1_${ik}$ + iv*n ), & 1_${ik}$, work( ki + iv*n ),vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_isamax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / abs( vr( ii, ki ) ) call stdlib${ii}$_sscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) else ! ------------------------------ ! version 2: back-transform block of vectors with gemm ! zero out below vector do k = ki + 1, n work( k + iv*n ) = zero end do iscomplex( iv ) = ip ! back-transform and normalization is done below end if else ! -------------------------------------------------------- ! complex right eigenvector. ! initial solve ! [ ( t(ki-1,ki-1) t(ki-1,ki) ) - (wr + i*wi) ]*x = 0. ! [ ( t(ki, ki-1) t(ki, ki) ) ] if( abs( t( ki-1, ki ) )>=abs( t( ki, ki-1 ) ) ) then work( ki-1 + (iv-1)*n ) = one work( ki + (iv )*n ) = wi / t( ki-1, ki ) else work( ki-1 + (iv-1)*n ) = -wi / t( ki, ki-1 ) work( ki + (iv )*n ) = one end if work( ki + (iv-1)*n ) = zero work( ki-1 + (iv )*n ) = zero ! form right-hand side. do k = 1, ki - 2 work( k+(iv-1)*n ) = -work( ki-1+(iv-1)*n )*t(k,ki-1) work( k+(iv )*n ) = -work( ki +(iv )*n )*t(k,ki ) end do ! solve upper quasi-triangular system: ! [ t(1:ki-2,1:ki-2) - (wr+i*wi) ]*x = scale*(work+i*work2) jnxt = ki - 2_${ik}$ loop_90: do j = ki - 2, 1, -1 if( j>jnxt )cycle loop_90 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_slaln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+(iv-1)*n ), n,wr, wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) and x(1,2) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+(iv-1)*n ), 1_${ik}$ ) call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) end if work( j+(iv-1)*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+(iv )*n ) = x( 1_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_saxpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv-1)*n ), 1_${ik}$ ) call stdlib${ii}$_saxpy( j-1, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_slaln2( .false., 2_${ik}$, 2_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+(iv-1)*n ), n, wr, wi, x, 2_${ik}$,scale, xnorm, ierr ) ! scale x to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then rec = one / xnorm x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ )*rec x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ )*rec x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ )*rec x( 2_${ik}$, 2_${ik}$ ) = x( 2_${ik}$, 2_${ik}$ )*rec scale = scale*rec end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+(iv-1)*n ), 1_${ik}$ ) call stdlib${ii}$_sscal( ki, scale, work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) end if work( j-1+(iv-1)*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j +(iv-1)*n ) = x( 2_${ik}$, 1_${ik}$ ) work( j-1+(iv )*n ) = x( 1_${ik}$, 2_${ik}$ ) work( j +(iv )*n ) = x( 2_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_saxpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+(iv-1)*n ),& 1_${ik}$ ) call stdlib${ii}$_saxpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv-1)*n ), & 1_${ik}$ ) call stdlib${ii}$_saxpy( j-2, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+(iv )*n ), & 1_${ik}$ ) call stdlib${ii}$_saxpy( j-2, -x( 2_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) end if end do loop_90 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vr and normalize. call stdlib${ii}$_scopy( ki, work( 1_${ik}$+(iv-1)*n ), 1_${ik}$, vr(1_${ik}$,is-1), 1_${ik}$ ) call stdlib${ii}$_scopy( ki, work( 1_${ik}$+(iv )*n ), 1_${ik}$, vr(1_${ik}$,is ), 1_${ik}$ ) emax = zero do k = 1, ki emax = max( emax, abs( vr( k, is-1 ) )+abs( vr( k, is ) ) ) end do remax = one / emax call stdlib${ii}$_sscal( ki, remax, vr( 1_${ik}$, is-1 ), 1_${ik}$ ) call stdlib${ii}$_sscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is-1 ) = zero vr( k, is ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki>2_${ik}$ ) then call stdlib${ii}$_sgemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$ + (iv-1)*n ), & 1_${ik}$,work( ki-1 + (iv-1)*n ), vr(1_${ik}$,ki-1), 1_${ik}$) call stdlib${ii}$_sgemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$ + (iv)*n ), 1_${ik}$,& work( ki + (iv)*n ), vr( 1_${ik}$, ki ), 1_${ik}$ ) else call stdlib${ii}$_sscal( n, work(ki-1+(iv-1)*n), vr(1_${ik}$,ki-1), 1_${ik}$) call stdlib${ii}$_sscal( n, work(ki +(iv )*n), vr(1_${ik}$,ki ), 1_${ik}$) end if emax = zero do k = 1, n emax = max( emax, abs( vr( k, ki-1 ) )+abs( vr( k, ki ) ) ) end do remax = one / emax call stdlib${ii}$_sscal( n, remax, vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) else ! ------------------------------ ! version 2: back-transform block of vectors with gemm ! zero out below vector do k = ki + 1, n work( k + (iv-1)*n ) = zero work( k + (iv )*n ) = zero end do iscomplex( iv-1 ) = -ip iscomplex( iv ) = ip iv = iv - 1_${ik}$ ! back-transform and normalization is done below end if end if if( nb>1_${ik}$ ) then ! -------------------------------------------------------- ! blocked version of back-transform ! for complex case, ki2 includes both vectors (ki-1 and ki) if( ip==0_${ik}$ ) then ki2 = ki else ki2 = ki - 1_${ik}$ end if ! columns iv:nb of work are valid vectors. ! when the number of vectors stored reaches nb-1 or nb, ! or if this was last vector, do the gemm if( (iv<=2_${ik}$) .or. (ki2==1_${ik}$) ) then call stdlib${ii}$_sgemm( 'N', 'N', n, nb-iv+1, ki2+nb-iv, one,vr, ldvr,work( 1_${ik}$ + & (iv)*n ), n,zero,work( 1_${ik}$ + (nb+iv)*n ), n ) ! normalize vectors do k = iv, nb if( iscomplex(k)==0_${ik}$ ) then ! real eigenvector ii = stdlib${ii}$_isamax( n, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) remax = one / abs( work( ii + (nb+k)*n ) ) else if( iscomplex(k)==1_${ik}$ ) then ! first eigenvector of conjugate pair emax = zero do ii = 1, n emax = max( emax,abs( work( ii + (nb+k )*n ) )+abs( work( ii + (& nb+k+1)*n ) ) ) end do remax = one / emax ! else if iscomplex(k)==-1 ! second eigenvector of conjugate pair ! reuse same remax as previous k end if call stdlib${ii}$_sscal( n, remax, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) end do call stdlib${ii}$_slacpy( 'F', n, nb-iv+1,work( 1_${ik}$ + (nb+iv)*n ), n,vr( 1_${ik}$, ki2 ), & ldvr ) iv = nb else iv = iv - 1_${ik}$ end if end if ! blocked back-transform is = is - 1_${ik}$ if( ip/=0_${ik}$ )is = is - 1_${ik}$ end do loop_140 end if if( leftv ) then ! ============================================================ ! compute left eigenvectors. ! iv is index of column in current block. ! for complex left vector, uses iv for real part and iv+1 for complex part. ! non-blocked version always uses iv=1; ! blocked version starts with iv=1, goes up to nb-1 or nb. ! (note the "0-th" column is used for 1-norms computed above.) iv = 1_${ik}$ ip = 0_${ik}$ is = 1_${ik}$ loop_260: do ki = 1, n if( ip==1_${ik}$ ) then ! previous iteration (ki-1) was first of conjugate pair, ! so this ki is second of conjugate pair; skip to end of loop ip = -1_${ik}$ cycle loop_260 else if( ki==n ) then ! last column, so this ki must be real eigenvalue ip = 0_${ik}$ else if( t( ki+1, ki )==zero ) then ! zero on sub-diagonal, so this ki is real eigenvalue ip = 0_${ik}$ else ! non-zero on sub-diagonal, so this ki is first of conjugate pair ip = 1_${ik}$ end if if( somev ) then if( .not.select( ki ) )cycle loop_260 end if ! compute the ki-th eigenvalue (wr,wi). wr = t( ki, ki ) wi = zero if( ip/=0_${ik}$ )wi = sqrt( abs( t( ki, ki+1 ) ) )*sqrt( abs( t( ki+1, ki ) ) ) smin = max( ulp*( abs( wr )+abs( wi ) ), smlnum ) if( ip==0_${ik}$ ) then ! -------------------------------------------------------- ! real left eigenvector work( ki + iv*n ) = one ! form right-hand side. do k = ki + 1, n work( k + iv*n ) = -t( ki, k ) end do ! solve transposed quasi-triangular system: ! [ t(ki+1:n,ki+1:n) - wr ]**t * x = scale*work vmax = one vcrit = bignum jnxt = ki + 1_${ik}$ loop_170: do j = ki + 1, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_sscal( n-ki+1, rec, work( ki+iv*n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+iv*n ) = work( j+iv*n ) -stdlib${ii}$_sdot( j-ki-1, t( ki+1, j ), 1_${ik}$,& work( ki+1+iv*n ), 1_${ik}$ ) ! solve [ t(j,j) - wr ]**t * x = work call stdlib${ii}$_slaln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_sscal( n-ki+1, scale, work( ki+iv*n ), 1_${ik}$ ) work( j+iv*n ) = x( 1_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j+iv*n ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_sscal( n-ki+1, rec, work( ki+iv*n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+iv*n ) = work( j+iv*n ) -stdlib${ii}$_sdot( j-ki-1, t( ki+1, j ), 1_${ik}$,& work( ki+1+iv*n ), 1_${ik}$ ) work( j+1+iv*n ) = work( j+1+iv*n ) -stdlib${ii}$_sdot( j-ki-1, t( ki+1, j+1 )& , 1_${ik}$,work( ki+1+iv*n ), 1_${ik}$ ) ! solve ! [ t(j,j)-wr t(j,j+1) ]**t * x = scale*( work1 ) ! [ t(j+1,j) t(j+1,j+1)-wr ] ( work2 ) call stdlib${ii}$_slaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_sscal( n-ki+1, scale, work( ki+iv*n ), 1_${ik}$ ) work( j +iv*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+1+iv*n ) = x( 2_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j +iv*n ) ),abs( work( j+1+iv*n ) ), vmax ) vcrit = bignum / vmax end if end do loop_170 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vl and normalize. call stdlib${ii}$_scopy( n-ki+1, work( ki + iv*n ), 1_${ik}$,vl( ki, is ), 1_${ik}$ ) ii = stdlib${ii}$_isamax( n-ki+1, vl( ki, is ), 1_${ik}$ ) + ki - 1_${ik}$ remax = one / abs( vl( ii, is ) ) call stdlib${ii}$_sscal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki=abs( t( ki+1, ki ) ) ) then work( ki + (iv )*n ) = wi / t( ki, ki+1 ) work( ki+1 + (iv+1)*n ) = one else work( ki + (iv )*n ) = one work( ki+1 + (iv+1)*n ) = -wi / t( ki+1, ki ) end if work( ki+1 + (iv )*n ) = zero work( ki + (iv+1)*n ) = zero ! form right-hand side. do k = ki + 2, n work( k+(iv )*n ) = -work( ki +(iv )*n )*t(ki, k) work( k+(iv+1)*n ) = -work( ki+1+(iv+1)*n )*t(ki+1,k) end do ! solve transposed quasi-triangular system: ! [ t(ki+2:n,ki+2:n)**t - (wr-i*wi) ]*x = work1+i*work2 vmax = one vcrit = bignum jnxt = ki + 2_${ik}$ loop_200: do j = ki + 2, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_sscal( n-ki+1, rec, work(ki+(iv )*n), 1_${ik}$ ) call stdlib${ii}$_sscal( n-ki+1, rec, work(ki+(iv+1)*n), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+(iv )*n ) = work( j+(iv)*n ) -stdlib${ii}$_sdot( j-ki-2, t( ki+2, j )& , 1_${ik}$,work( ki+2+(iv)*n ), 1_${ik}$ ) work( j+(iv+1)*n ) = work( j+(iv+1)*n ) -stdlib${ii}$_sdot( j-ki-2, t( ki+2, & j ), 1_${ik}$,work( ki+2+(iv+1)*n ), 1_${ik}$ ) ! solve [ t(j,j)-(wr-i*wi) ]*(x11+i*x12)= wk+i*wk2 call stdlib${ii}$_slaln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_sscal( n-ki+1, scale, work(ki+(iv )*n), 1_${ik}$) call stdlib${ii}$_sscal( n-ki+1, scale, work(ki+(iv+1)*n), 1_${ik}$) end if work( j+(iv )*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+(iv+1)*n ) = x( 1_${ik}$, 2_${ik}$ ) vmax = max( abs( work( j+(iv )*n ) ),abs( work( j+(iv+1)*n ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side elements. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_sscal( n-ki+1, rec, work(ki+(iv )*n), 1_${ik}$ ) call stdlib${ii}$_sscal( n-ki+1, rec, work(ki+(iv+1)*n), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j +(iv )*n ) = work( j+(iv)*n ) -stdlib${ii}$_sdot( j-ki-2, t( ki+2, & j ), 1_${ik}$,work( ki+2+(iv)*n ), 1_${ik}$ ) work( j +(iv+1)*n ) = work( j+(iv+1)*n ) -stdlib${ii}$_sdot( j-ki-2, t( ki+2,& j ), 1_${ik}$,work( ki+2+(iv+1)*n ), 1_${ik}$ ) work( j+1+(iv )*n ) = work( j+1+(iv)*n ) -stdlib${ii}$_sdot( j-ki-2, t( ki+2,& j+1 ), 1_${ik}$,work( ki+2+(iv)*n ), 1_${ik}$ ) work( j+1+(iv+1)*n ) = work( j+1+(iv+1)*n ) -stdlib${ii}$_sdot( j-ki-2, t( ki+& 2_${ik}$, j+1 ), 1_${ik}$,work( ki+2+(iv+1)*n ), 1_${ik}$ ) ! solve 2-by-2 complex linear equation ! [ (t(j,j) t(j,j+1) )**t - (wr-i*wi)*i ]*x = scale*b ! [ (t(j+1,j) t(j+1,j+1)) ] call stdlib${ii}$_slaln2( .true., 2_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_sscal( n-ki+1, scale, work(ki+(iv )*n), 1_${ik}$) call stdlib${ii}$_sscal( n-ki+1, scale, work(ki+(iv+1)*n), 1_${ik}$) end if work( j +(iv )*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j +(iv+1)*n ) = x( 1_${ik}$, 2_${ik}$ ) work( j+1+(iv )*n ) = x( 2_${ik}$, 1_${ik}$ ) work( j+1+(iv+1)*n ) = x( 2_${ik}$, 2_${ik}$ ) vmax = max( abs( x( 1_${ik}$, 1_${ik}$ ) ), abs( x( 1_${ik}$, 2_${ik}$ ) ),abs( x( 2_${ik}$, 1_${ik}$ ) ), abs( x(& 2_${ik}$, 2_${ik}$ ) ),vmax ) vcrit = bignum / vmax end if end do loop_200 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vl and normalize. call stdlib${ii}$_scopy( n-ki+1, work( ki + (iv )*n ), 1_${ik}$,vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_scopy( n-ki+1, work( ki + (iv+1)*n ), 1_${ik}$,vl( ki, is+1 ), 1_${ik}$ ) emax = zero do k = ki, n emax = max( emax, abs( vl( k, is ) )+abs( vl( k, is+1 ) ) ) end do remax = one / emax call stdlib${ii}$_sscal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_sscal( n-ki+1, remax, vl( ki, is+1 ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero vl( k, is+1 ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki1_${ik}$ ) then ! -------------------------------------------------------- ! blocked version of back-transform ! for complex case, ki2 includes both vectors (ki and ki+1) if( ip==0_${ik}$ ) then ki2 = ki else ki2 = ki + 1_${ik}$ end if ! columns 1:iv of work are valid vectors. ! when the number of vectors stored reaches nb-1 or nb, ! or if this was last vector, do the gemm if( (iv>=nb-1) .or. (ki2==n) ) then call stdlib${ii}$_sgemm( 'N', 'N', n, iv, n-ki2+iv, one,vl( 1_${ik}$, ki2-iv+1 ), ldvl,& work( ki2-iv+1 + (1_${ik}$)*n ), n,zero,work( 1_${ik}$ + (nb+1)*n ), n ) ! normalize vectors do k = 1, iv if( iscomplex(k)==0_${ik}$) then ! real eigenvector ii = stdlib${ii}$_isamax( n, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) remax = one / abs( work( ii + (nb+k)*n ) ) else if( iscomplex(k)==1_${ik}$) then ! first eigenvector of conjugate pair emax = zero do ii = 1, n emax = max( emax,abs( work( ii + (nb+k )*n ) )+abs( work( ii + (& nb+k+1)*n ) ) ) end do remax = one / emax ! else if iscomplex(k)==-1 ! second eigenvector of conjugate pair ! reuse same remax as previous k end if call stdlib${ii}$_sscal( n, remax, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) end do call stdlib${ii}$_slacpy( 'F', n, iv,work( 1_${ik}$ + (nb+1)*n ), n,vl( 1_${ik}$, ki2-iv+1 ), & ldvl ) iv = 1_${ik}$ else iv = iv + 1_${ik}$ end if end if ! blocked back-transform is = is + 1_${ik}$ if( ip/=0_${ik}$ )is = is + 1_${ik}$ end do loop_260 end if return end subroutine stdlib${ii}$_strevc3 pure module subroutine stdlib${ii}$_dtrevc3( side, howmny, select, n, t, ldt, vl, ldvl,vr, ldvr, mm, m, & !! DTREVC3 computes some or all of the right and/or left eigenvectors of !! a real upper quasi-triangular matrix T. !! Matrices of this type are produced by the Schur factorization of !! a real general matrix: A = Q*T*Q**T, as computed by DHSEQR. !! The right eigenvector x and the left eigenvector y of T corresponding !! to an eigenvalue w are defined by: !! T*x = w*x, (y**T)*T = w*(y**T) !! where y**T denotes the transpose of the vector y. !! The eigenvalues are not input to this routine, but are read directly !! from the diagonal blocks of T. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an !! input matrix. If Q is the orthogonal factor that reduces a matrix !! A to Schur form T, then Q*X and Q*Y are the matrices of right and !! left eigenvectors of A. !! This uses a Level 3 BLAS version of the back transformation. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: howmny, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldt, ldvl, ldvr, lwork, mm, n ! Array Arguments logical(lk), intent(inout) :: select(*) real(dp), intent(in) :: t(ldt,*) real(dp), intent(inout) :: vl(ldvl,*), vr(ldvr,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmin = 8_${ik}$ integer(${ik}$), parameter :: nbmax = 128_${ik}$ ! Local Scalars logical(lk) :: allv, bothv, leftv, lquery, over, pair, rightv, somev integer(${ik}$) :: i, ierr, ii, ip, is, j, j1, j2, jnxt, k, ki, iv, maxwrk, nb, & ki2 real(dp) :: beta, bignum, emax, ovfl, rec, remax, scale, smin, smlnum, ulp, unfl, & vcrit, vmax, wi, wr, xnorm ! Intrinsic Functions ! Local Arrays real(dp) :: x(2_${ik}$,2_${ik}$) integer(${ik}$) :: iscomplex(nbmax) ! Executable Statements ! decode and test the input parameters bothv = stdlib_lsame( side, 'B' ) rightv = stdlib_lsame( side, 'R' ) .or. bothv leftv = stdlib_lsame( side, 'L' ) .or. bothv allv = stdlib_lsame( howmny, 'A' ) over = stdlib_lsame( howmny, 'B' ) somev = stdlib_lsame( howmny, 'S' ) info = 0_${ik}$ nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DTREVC', side // howmny, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) maxwrk = n + 2_${ik}$*n*nb work(1_${ik}$) = maxwrk lquery = ( lwork==-1_${ik}$ ) if( .not.rightv .and. .not.leftv ) then info = -1_${ik}$ else if( .not.allv .and. .not.over .and. .not.somev ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ldt= n + 2_${ik}$*n*nbmin ) then nb = (lwork - n) / (2_${ik}$*n) nb = min( nb, nbmax ) call stdlib${ii}$_dlaset( 'F', n, 1_${ik}$+2*nb, zero, zero, work, n ) else nb = 1_${ik}$ end if ! set the constants to control overflow. unfl = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) ovfl = one / unfl call stdlib${ii}$_dlabad( unfl, ovfl ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = unfl*( n / ulp ) bignum = ( one-ulp ) / smlnum ! compute 1-norm of each column of strictly upper triangular ! part of t to control overflow in triangular solver. work( 1_${ik}$ ) = zero do j = 2, n work( j ) = zero do i = 1, j - 1 work( j ) = work( j ) + abs( t( i, j ) ) end do end do ! index ip is used to specify the real or complex eigenvalue: ! ip = 0, real eigenvalue, ! 1, first of conjugate complex pair: (wr,wi) ! -1, second of conjugate complex pair: (wr,wi) ! iscomplex array stores ip for each column in current block. if( rightv ) then ! ============================================================ ! compute right eigenvectors. ! iv is index of column in current block. ! for complex right vector, uses iv-1 for real part and iv for complex part. ! non-blocked version always uses iv=2; ! blocked version starts with iv=nb, goes down to 1 or 2. ! (note the "0-th" column is used for 1-norms computed above.) iv = 2_${ik}$ if( nb>2_${ik}$ ) then iv = nb end if ip = 0_${ik}$ is = m loop_140: do ki = n, 1, -1 if( ip==-1_${ik}$ ) then ! previous iteration (ki+1) was second of conjugate pair, ! so this ki is first of conjugate pair; skip to end of loop ip = 1_${ik}$ cycle loop_140 else if( ki==1_${ik}$ ) then ! last column, so this ki must be real eigenvalue ip = 0_${ik}$ else if( t( ki, ki-1 )==zero ) then ! zero on sub-diagonal, so this ki is real eigenvalue ip = 0_${ik}$ else ! non-zero on sub-diagonal, so this ki is second of conjugate pair ip = -1_${ik}$ end if if( somev ) then if( ip==0_${ik}$ ) then if( .not.select( ki ) )cycle loop_140 else if( .not.select( ki-1 ) )cycle loop_140 end if end if ! compute the ki-th eigenvalue (wr,wi). wr = t( ki, ki ) wi = zero if( ip/=0_${ik}$ )wi = sqrt( abs( t( ki, ki-1 ) ) )*sqrt( abs( t( ki-1, ki ) ) ) smin = max( ulp*( abs( wr )+abs( wi ) ), smlnum ) if( ip==0_${ik}$ ) then ! -------------------------------------------------------- ! real right eigenvector work( ki + iv*n ) = one ! form right-hand side. do k = 1, ki - 1 work( k + iv*n ) = -t( k, ki ) end do ! solve upper quasi-triangular system: ! [ t(1:ki-1,1:ki-1) - wr ]*x = scale*work. jnxt = ki - 1_${ik}$ loop_60: do j = ki - 1, 1, -1 if( j>jnxt )cycle loop_60 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_dlaln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+iv*n ), 1_${ik}$ ) work( j+iv*n ) = x( 1_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_daxpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+iv*n ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_dlaln2( .false., 2_${ik}$, 1_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+iv*n ), n, wr, zero, x, 2_${ik}$,scale, xnorm, ierr ) ! scale x(1,1) and x(2,1) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+iv*n ), 1_${ik}$ ) work( j-1+iv*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j +iv*n ) = x( 2_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_daxpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+iv*n ), 1_${ik}$ ) call stdlib${ii}$_daxpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+iv*n ), 1_${ik}$ ) end if end do loop_60 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vr and normalize. call stdlib${ii}$_dcopy( ki, work( 1_${ik}$ + iv*n ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_idamax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / abs( vr( ii, is ) ) call stdlib${ii}$_dscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki>1_${ik}$ )call stdlib${ii}$_dgemv( 'N', n, ki-1, one, vr, ldvr,work( 1_${ik}$ + iv*n ), & 1_${ik}$, work( ki + iv*n ),vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_idamax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / abs( vr( ii, ki ) ) call stdlib${ii}$_dscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) else ! ------------------------------ ! version 2: back-transform block of vectors with gemm ! zero out below vector do k = ki + 1, n work( k + iv*n ) = zero end do iscomplex( iv ) = ip ! back-transform and normalization is done below end if else ! -------------------------------------------------------- ! complex right eigenvector. ! initial solve ! [ ( t(ki-1,ki-1) t(ki-1,ki) ) - (wr + i*wi) ]*x = 0. ! [ ( t(ki, ki-1) t(ki, ki) ) ] if( abs( t( ki-1, ki ) )>=abs( t( ki, ki-1 ) ) ) then work( ki-1 + (iv-1)*n ) = one work( ki + (iv )*n ) = wi / t( ki-1, ki ) else work( ki-1 + (iv-1)*n ) = -wi / t( ki, ki-1 ) work( ki + (iv )*n ) = one end if work( ki + (iv-1)*n ) = zero work( ki-1 + (iv )*n ) = zero ! form right-hand side. do k = 1, ki - 2 work( k+(iv-1)*n ) = -work( ki-1+(iv-1)*n )*t(k,ki-1) work( k+(iv )*n ) = -work( ki +(iv )*n )*t(k,ki ) end do ! solve upper quasi-triangular system: ! [ t(1:ki-2,1:ki-2) - (wr+i*wi) ]*x = scale*(work+i*work2) jnxt = ki - 2_${ik}$ loop_90: do j = ki - 2, 1, -1 if( j>jnxt )cycle loop_90 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_dlaln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+(iv-1)*n ), n,wr, wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) and x(1,2) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+(iv-1)*n ), 1_${ik}$ ) call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) end if work( j+(iv-1)*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+(iv )*n ) = x( 1_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_daxpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv-1)*n ), 1_${ik}$ ) call stdlib${ii}$_daxpy( j-1, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_dlaln2( .false., 2_${ik}$, 2_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+(iv-1)*n ), n, wr, wi, x, 2_${ik}$,scale, xnorm, ierr ) ! scale x to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then rec = one / xnorm x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ )*rec x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ )*rec x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ )*rec x( 2_${ik}$, 2_${ik}$ ) = x( 2_${ik}$, 2_${ik}$ )*rec scale = scale*rec end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+(iv-1)*n ), 1_${ik}$ ) call stdlib${ii}$_dscal( ki, scale, work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) end if work( j-1+(iv-1)*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j +(iv-1)*n ) = x( 2_${ik}$, 1_${ik}$ ) work( j-1+(iv )*n ) = x( 1_${ik}$, 2_${ik}$ ) work( j +(iv )*n ) = x( 2_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_daxpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+(iv-1)*n ),& 1_${ik}$ ) call stdlib${ii}$_daxpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv-1)*n ), & 1_${ik}$ ) call stdlib${ii}$_daxpy( j-2, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+(iv )*n ), & 1_${ik}$ ) call stdlib${ii}$_daxpy( j-2, -x( 2_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) end if end do loop_90 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vr and normalize. call stdlib${ii}$_dcopy( ki, work( 1_${ik}$+(iv-1)*n ), 1_${ik}$, vr(1_${ik}$,is-1), 1_${ik}$ ) call stdlib${ii}$_dcopy( ki, work( 1_${ik}$+(iv )*n ), 1_${ik}$, vr(1_${ik}$,is ), 1_${ik}$ ) emax = zero do k = 1, ki emax = max( emax, abs( vr( k, is-1 ) )+abs( vr( k, is ) ) ) end do remax = one / emax call stdlib${ii}$_dscal( ki, remax, vr( 1_${ik}$, is-1 ), 1_${ik}$ ) call stdlib${ii}$_dscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is-1 ) = zero vr( k, is ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki>2_${ik}$ ) then call stdlib${ii}$_dgemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$ + (iv-1)*n ), & 1_${ik}$,work( ki-1 + (iv-1)*n ), vr(1_${ik}$,ki-1), 1_${ik}$) call stdlib${ii}$_dgemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$ + (iv)*n ), 1_${ik}$,& work( ki + (iv)*n ), vr( 1_${ik}$, ki ), 1_${ik}$ ) else call stdlib${ii}$_dscal( n, work(ki-1+(iv-1)*n), vr(1_${ik}$,ki-1), 1_${ik}$) call stdlib${ii}$_dscal( n, work(ki +(iv )*n), vr(1_${ik}$,ki ), 1_${ik}$) end if emax = zero do k = 1, n emax = max( emax, abs( vr( k, ki-1 ) )+abs( vr( k, ki ) ) ) end do remax = one / emax call stdlib${ii}$_dscal( n, remax, vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) else ! ------------------------------ ! version 2: back-transform block of vectors with gemm ! zero out below vector do k = ki + 1, n work( k + (iv-1)*n ) = zero work( k + (iv )*n ) = zero end do iscomplex( iv-1 ) = -ip iscomplex( iv ) = ip iv = iv - 1_${ik}$ ! back-transform and normalization is done below end if end if if( nb>1_${ik}$ ) then ! -------------------------------------------------------- ! blocked version of back-transform ! for complex case, ki2 includes both vectors (ki-1 and ki) if( ip==0_${ik}$ ) then ki2 = ki else ki2 = ki - 1_${ik}$ end if ! columns iv:nb of work are valid vectors. ! when the number of vectors stored reaches nb-1 or nb, ! or if this was last vector, do the gemm if( (iv<=2_${ik}$) .or. (ki2==1_${ik}$) ) then call stdlib${ii}$_dgemm( 'N', 'N', n, nb-iv+1, ki2+nb-iv, one,vr, ldvr,work( 1_${ik}$ + & (iv)*n ), n,zero,work( 1_${ik}$ + (nb+iv)*n ), n ) ! normalize vectors do k = iv, nb if( iscomplex(k)==0_${ik}$ ) then ! real eigenvector ii = stdlib${ii}$_idamax( n, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) remax = one / abs( work( ii + (nb+k)*n ) ) else if( iscomplex(k)==1_${ik}$ ) then ! first eigenvector of conjugate pair emax = zero do ii = 1, n emax = max( emax,abs( work( ii + (nb+k )*n ) )+abs( work( ii + (& nb+k+1)*n ) ) ) end do remax = one / emax ! else if iscomplex(k)==-1 ! second eigenvector of conjugate pair ! reuse same remax as previous k end if call stdlib${ii}$_dscal( n, remax, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) end do call stdlib${ii}$_dlacpy( 'F', n, nb-iv+1,work( 1_${ik}$ + (nb+iv)*n ), n,vr( 1_${ik}$, ki2 ), & ldvr ) iv = nb else iv = iv - 1_${ik}$ end if end if ! blocked back-transform is = is - 1_${ik}$ if( ip/=0_${ik}$ )is = is - 1_${ik}$ end do loop_140 end if if( leftv ) then ! ============================================================ ! compute left eigenvectors. ! iv is index of column in current block. ! for complex left vector, uses iv for real part and iv+1 for complex part. ! non-blocked version always uses iv=1; ! blocked version starts with iv=1, goes up to nb-1 or nb. ! (note the "0-th" column is used for 1-norms computed above.) iv = 1_${ik}$ ip = 0_${ik}$ is = 1_${ik}$ loop_260: do ki = 1, n if( ip==1_${ik}$ ) then ! previous iteration (ki-1) was first of conjugate pair, ! so this ki is second of conjugate pair; skip to end of loop ip = -1_${ik}$ cycle loop_260 else if( ki==n ) then ! last column, so this ki must be real eigenvalue ip = 0_${ik}$ else if( t( ki+1, ki )==zero ) then ! zero on sub-diagonal, so this ki is real eigenvalue ip = 0_${ik}$ else ! non-zero on sub-diagonal, so this ki is first of conjugate pair ip = 1_${ik}$ end if if( somev ) then if( .not.select( ki ) )cycle loop_260 end if ! compute the ki-th eigenvalue (wr,wi). wr = t( ki, ki ) wi = zero if( ip/=0_${ik}$ )wi = sqrt( abs( t( ki, ki+1 ) ) )*sqrt( abs( t( ki+1, ki ) ) ) smin = max( ulp*( abs( wr )+abs( wi ) ), smlnum ) if( ip==0_${ik}$ ) then ! -------------------------------------------------------- ! real left eigenvector work( ki + iv*n ) = one ! form right-hand side. do k = ki + 1, n work( k + iv*n ) = -t( ki, k ) end do ! solve transposed quasi-triangular system: ! [ t(ki+1:n,ki+1:n) - wr ]**t * x = scale*work vmax = one vcrit = bignum jnxt = ki + 1_${ik}$ loop_170: do j = ki + 1, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_dscal( n-ki+1, rec, work( ki+iv*n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+iv*n ) = work( j+iv*n ) -stdlib${ii}$_ddot( j-ki-1, t( ki+1, j ), 1_${ik}$,& work( ki+1+iv*n ), 1_${ik}$ ) ! solve [ t(j,j) - wr ]**t * x = work call stdlib${ii}$_dlaln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_dscal( n-ki+1, scale, work( ki+iv*n ), 1_${ik}$ ) work( j+iv*n ) = x( 1_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j+iv*n ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_dscal( n-ki+1, rec, work( ki+iv*n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+iv*n ) = work( j+iv*n ) -stdlib${ii}$_ddot( j-ki-1, t( ki+1, j ), 1_${ik}$,& work( ki+1+iv*n ), 1_${ik}$ ) work( j+1+iv*n ) = work( j+1+iv*n ) -stdlib${ii}$_ddot( j-ki-1, t( ki+1, j+1 )& , 1_${ik}$,work( ki+1+iv*n ), 1_${ik}$ ) ! solve ! [ t(j,j)-wr t(j,j+1) ]**t * x = scale*( work1 ) ! [ t(j+1,j) t(j+1,j+1)-wr ] ( work2 ) call stdlib${ii}$_dlaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_dscal( n-ki+1, scale, work( ki+iv*n ), 1_${ik}$ ) work( j +iv*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+1+iv*n ) = x( 2_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j +iv*n ) ),abs( work( j+1+iv*n ) ), vmax ) vcrit = bignum / vmax end if end do loop_170 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vl and normalize. call stdlib${ii}$_dcopy( n-ki+1, work( ki + iv*n ), 1_${ik}$,vl( ki, is ), 1_${ik}$ ) ii = stdlib${ii}$_idamax( n-ki+1, vl( ki, is ), 1_${ik}$ ) + ki - 1_${ik}$ remax = one / abs( vl( ii, is ) ) call stdlib${ii}$_dscal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki=abs( t( ki+1, ki ) ) ) then work( ki + (iv )*n ) = wi / t( ki, ki+1 ) work( ki+1 + (iv+1)*n ) = one else work( ki + (iv )*n ) = one work( ki+1 + (iv+1)*n ) = -wi / t( ki+1, ki ) end if work( ki+1 + (iv )*n ) = zero work( ki + (iv+1)*n ) = zero ! form right-hand side. do k = ki + 2, n work( k+(iv )*n ) = -work( ki +(iv )*n )*t(ki, k) work( k+(iv+1)*n ) = -work( ki+1+(iv+1)*n )*t(ki+1,k) end do ! solve transposed quasi-triangular system: ! [ t(ki+2:n,ki+2:n)**t - (wr-i*wi) ]*x = work1+i*work2 vmax = one vcrit = bignum jnxt = ki + 2_${ik}$ loop_200: do j = ki + 2, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_dscal( n-ki+1, rec, work(ki+(iv )*n), 1_${ik}$ ) call stdlib${ii}$_dscal( n-ki+1, rec, work(ki+(iv+1)*n), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+(iv )*n ) = work( j+(iv)*n ) -stdlib${ii}$_ddot( j-ki-2, t( ki+2, j )& , 1_${ik}$,work( ki+2+(iv)*n ), 1_${ik}$ ) work( j+(iv+1)*n ) = work( j+(iv+1)*n ) -stdlib${ii}$_ddot( j-ki-2, t( ki+2, & j ), 1_${ik}$,work( ki+2+(iv+1)*n ), 1_${ik}$ ) ! solve [ t(j,j)-(wr-i*wi) ]*(x11+i*x12)= wk+i*wk2 call stdlib${ii}$_dlaln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_dscal( n-ki+1, scale, work(ki+(iv )*n), 1_${ik}$) call stdlib${ii}$_dscal( n-ki+1, scale, work(ki+(iv+1)*n), 1_${ik}$) end if work( j+(iv )*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+(iv+1)*n ) = x( 1_${ik}$, 2_${ik}$ ) vmax = max( abs( work( j+(iv )*n ) ),abs( work( j+(iv+1)*n ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side elements. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_dscal( n-ki+1, rec, work(ki+(iv )*n), 1_${ik}$ ) call stdlib${ii}$_dscal( n-ki+1, rec, work(ki+(iv+1)*n), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j +(iv )*n ) = work( j+(iv)*n ) -stdlib${ii}$_ddot( j-ki-2, t( ki+2, & j ), 1_${ik}$,work( ki+2+(iv)*n ), 1_${ik}$ ) work( j +(iv+1)*n ) = work( j+(iv+1)*n ) -stdlib${ii}$_ddot( j-ki-2, t( ki+2,& j ), 1_${ik}$,work( ki+2+(iv+1)*n ), 1_${ik}$ ) work( j+1+(iv )*n ) = work( j+1+(iv)*n ) -stdlib${ii}$_ddot( j-ki-2, t( ki+2,& j+1 ), 1_${ik}$,work( ki+2+(iv)*n ), 1_${ik}$ ) work( j+1+(iv+1)*n ) = work( j+1+(iv+1)*n ) -stdlib${ii}$_ddot( j-ki-2, t( ki+& 2_${ik}$, j+1 ), 1_${ik}$,work( ki+2+(iv+1)*n ), 1_${ik}$ ) ! solve 2-by-2 complex linear equation ! [ (t(j,j) t(j,j+1) )**t - (wr-i*wi)*i ]*x = scale*b ! [ (t(j+1,j) t(j+1,j+1)) ] call stdlib${ii}$_dlaln2( .true., 2_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_dscal( n-ki+1, scale, work(ki+(iv )*n), 1_${ik}$) call stdlib${ii}$_dscal( n-ki+1, scale, work(ki+(iv+1)*n), 1_${ik}$) end if work( j +(iv )*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j +(iv+1)*n ) = x( 1_${ik}$, 2_${ik}$ ) work( j+1+(iv )*n ) = x( 2_${ik}$, 1_${ik}$ ) work( j+1+(iv+1)*n ) = x( 2_${ik}$, 2_${ik}$ ) vmax = max( abs( x( 1_${ik}$, 1_${ik}$ ) ), abs( x( 1_${ik}$, 2_${ik}$ ) ),abs( x( 2_${ik}$, 1_${ik}$ ) ), abs( x(& 2_${ik}$, 2_${ik}$ ) ),vmax ) vcrit = bignum / vmax end if end do loop_200 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vl and normalize. call stdlib${ii}$_dcopy( n-ki+1, work( ki + (iv )*n ), 1_${ik}$,vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_dcopy( n-ki+1, work( ki + (iv+1)*n ), 1_${ik}$,vl( ki, is+1 ), 1_${ik}$ ) emax = zero do k = ki, n emax = max( emax, abs( vl( k, is ) )+abs( vl( k, is+1 ) ) ) end do remax = one / emax call stdlib${ii}$_dscal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_dscal( n-ki+1, remax, vl( ki, is+1 ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero vl( k, is+1 ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki1_${ik}$ ) then ! -------------------------------------------------------- ! blocked version of back-transform ! for complex case, ki2 includes both vectors (ki and ki+1) if( ip==0_${ik}$ ) then ki2 = ki else ki2 = ki + 1_${ik}$ end if ! columns 1:iv of work are valid vectors. ! when the number of vectors stored reaches nb-1 or nb, ! or if this was last vector, do the gemm if( (iv>=nb-1) .or. (ki2==n) ) then call stdlib${ii}$_dgemm( 'N', 'N', n, iv, n-ki2+iv, one,vl( 1_${ik}$, ki2-iv+1 ), ldvl,& work( ki2-iv+1 + (1_${ik}$)*n ), n,zero,work( 1_${ik}$ + (nb+1)*n ), n ) ! normalize vectors do k = 1, iv if( iscomplex(k)==0_${ik}$) then ! real eigenvector ii = stdlib${ii}$_idamax( n, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) remax = one / abs( work( ii + (nb+k)*n ) ) else if( iscomplex(k)==1_${ik}$) then ! first eigenvector of conjugate pair emax = zero do ii = 1, n emax = max( emax,abs( work( ii + (nb+k )*n ) )+abs( work( ii + (& nb+k+1)*n ) ) ) end do remax = one / emax ! else if iscomplex(k)==-1 ! second eigenvector of conjugate pair ! reuse same remax as previous k end if call stdlib${ii}$_dscal( n, remax, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) end do call stdlib${ii}$_dlacpy( 'F', n, iv,work( 1_${ik}$ + (nb+1)*n ), n,vl( 1_${ik}$, ki2-iv+1 ), & ldvl ) iv = 1_${ik}$ else iv = iv + 1_${ik}$ end if end if ! blocked back-transform is = is + 1_${ik}$ if( ip/=0_${ik}$ )is = is + 1_${ik}$ end do loop_260 end if return end subroutine stdlib${ii}$_dtrevc3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$trevc3( side, howmny, select, n, t, ldt, vl, ldvl,vr, ldvr, mm, m, & !! DTREVC3: computes some or all of the right and/or left eigenvectors of !! a real upper quasi-triangular matrix T. !! Matrices of this type are produced by the Schur factorization of !! a real general matrix: A = Q*T*Q**T, as computed by DHSEQR. !! The right eigenvector x and the left eigenvector y of T corresponding !! to an eigenvalue w are defined by: !! T*x = w*x, (y**T)*T = w*(y**T) !! where y**T denotes the transpose of the vector y. !! The eigenvalues are not input to this routine, but are read directly !! from the diagonal blocks of T. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an !! input matrix. If Q is the orthogonal factor that reduces a matrix !! A to Schur form T, then Q*X and Q*Y are the matrices of right and !! left eigenvectors of A. !! This uses a Level 3 BLAS version of the back transformation. work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: howmny, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldt, ldvl, ldvr, lwork, mm, n ! Array Arguments logical(lk), intent(inout) :: select(*) real(${rk}$), intent(in) :: t(ldt,*) real(${rk}$), intent(inout) :: vl(ldvl,*), vr(ldvr,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmin = 8_${ik}$ integer(${ik}$), parameter :: nbmax = 128_${ik}$ ! Local Scalars logical(lk) :: allv, bothv, leftv, lquery, over, pair, rightv, somev integer(${ik}$) :: i, ierr, ii, ip, is, j, j1, j2, jnxt, k, ki, iv, maxwrk, nb, & ki2 real(${rk}$) :: beta, bignum, emax, ovfl, rec, remax, scale, smin, smlnum, ulp, unfl, & vcrit, vmax, wi, wr, xnorm ! Intrinsic Functions ! Local Arrays real(${rk}$) :: x(2_${ik}$,2_${ik}$) integer(${ik}$) :: iscomplex(nbmax) ! Executable Statements ! decode and test the input parameters bothv = stdlib_lsame( side, 'B' ) rightv = stdlib_lsame( side, 'R' ) .or. bothv leftv = stdlib_lsame( side, 'L' ) .or. bothv allv = stdlib_lsame( howmny, 'A' ) over = stdlib_lsame( howmny, 'B' ) somev = stdlib_lsame( howmny, 'S' ) info = 0_${ik}$ nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DTREVC', side // howmny, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) maxwrk = n + 2_${ik}$*n*nb work(1_${ik}$) = maxwrk lquery = ( lwork==-1_${ik}$ ) if( .not.rightv .and. .not.leftv ) then info = -1_${ik}$ else if( .not.allv .and. .not.over .and. .not.somev ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ldt= n + 2_${ik}$*n*nbmin ) then nb = (lwork - n) / (2_${ik}$*n) nb = min( nb, nbmax ) call stdlib${ii}$_${ri}$laset( 'F', n, 1_${ik}$+2*nb, zero, zero, work, n ) else nb = 1_${ik}$ end if ! set the constants to control overflow. unfl = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) ovfl = one / unfl call stdlib${ii}$_${ri}$labad( unfl, ovfl ) ulp = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = unfl*( n / ulp ) bignum = ( one-ulp ) / smlnum ! compute 1-norm of each column of strictly upper triangular ! part of t to control overflow in triangular solver. work( 1_${ik}$ ) = zero do j = 2, n work( j ) = zero do i = 1, j - 1 work( j ) = work( j ) + abs( t( i, j ) ) end do end do ! index ip is used to specify the real or complex eigenvalue: ! ip = 0, real eigenvalue, ! 1, first of conjugate complex pair: (wr,wi) ! -1, second of conjugate complex pair: (wr,wi) ! iscomplex array stores ip for each column in current block. if( rightv ) then ! ============================================================ ! compute right eigenvectors. ! iv is index of column in current block. ! for complex right vector, uses iv-1 for real part and iv for complex part. ! non-blocked version always uses iv=2; ! blocked version starts with iv=nb, goes down to 1 or 2. ! (note the "0-th" column is used for 1-norms computed above.) iv = 2_${ik}$ if( nb>2_${ik}$ ) then iv = nb end if ip = 0_${ik}$ is = m loop_140: do ki = n, 1, -1 if( ip==-1_${ik}$ ) then ! previous iteration (ki+1) was second of conjugate pair, ! so this ki is first of conjugate pair; skip to end of loop ip = 1_${ik}$ cycle loop_140 else if( ki==1_${ik}$ ) then ! last column, so this ki must be real eigenvalue ip = 0_${ik}$ else if( t( ki, ki-1 )==zero ) then ! zero on sub-diagonal, so this ki is real eigenvalue ip = 0_${ik}$ else ! non-zero on sub-diagonal, so this ki is second of conjugate pair ip = -1_${ik}$ end if if( somev ) then if( ip==0_${ik}$ ) then if( .not.select( ki ) )cycle loop_140 else if( .not.select( ki-1 ) )cycle loop_140 end if end if ! compute the ki-th eigenvalue (wr,wi). wr = t( ki, ki ) wi = zero if( ip/=0_${ik}$ )wi = sqrt( abs( t( ki, ki-1 ) ) )*sqrt( abs( t( ki-1, ki ) ) ) smin = max( ulp*( abs( wr )+abs( wi ) ), smlnum ) if( ip==0_${ik}$ ) then ! -------------------------------------------------------- ! real right eigenvector work( ki + iv*n ) = one ! form right-hand side. do k = 1, ki - 1 work( k + iv*n ) = -t( k, ki ) end do ! solve upper quasi-triangular system: ! [ t(1:ki-1,1:ki-1) - wr ]*x = scale*work. jnxt = ki - 1_${ik}$ loop_60: do j = ki - 1, 1, -1 if( j>jnxt )cycle loop_60 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_${ri}$laln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+iv*n ), 1_${ik}$ ) work( j+iv*n ) = x( 1_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_${ri}$axpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+iv*n ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_${ri}$laln2( .false., 2_${ik}$, 1_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+iv*n ), n, wr, zero, x, 2_${ik}$,scale, xnorm, ierr ) ! scale x(1,1) and x(2,1) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one )call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+iv*n ), 1_${ik}$ ) work( j-1+iv*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j +iv*n ) = x( 2_${ik}$, 1_${ik}$ ) ! update right-hand side call stdlib${ii}$_${ri}$axpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+iv*n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+iv*n ), 1_${ik}$ ) end if end do loop_60 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vr and normalize. call stdlib${ii}$_${ri}$copy( ki, work( 1_${ik}$ + iv*n ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_i${ri}$amax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / abs( vr( ii, is ) ) call stdlib${ii}$_${ri}$scal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki>1_${ik}$ )call stdlib${ii}$_${ri}$gemv( 'N', n, ki-1, one, vr, ldvr,work( 1_${ik}$ + iv*n ), & 1_${ik}$, work( ki + iv*n ),vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_i${ri}$amax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / abs( vr( ii, ki ) ) call stdlib${ii}$_${ri}$scal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) else ! ------------------------------ ! version 2: back-transform block of vectors with gemm ! zero out below vector do k = ki + 1, n work( k + iv*n ) = zero end do iscomplex( iv ) = ip ! back-transform and normalization is done below end if else ! -------------------------------------------------------- ! complex right eigenvector. ! initial solve ! [ ( t(ki-1,ki-1) t(ki-1,ki) ) - (wr + i*wi) ]*x = 0. ! [ ( t(ki, ki-1) t(ki, ki) ) ] if( abs( t( ki-1, ki ) )>=abs( t( ki, ki-1 ) ) ) then work( ki-1 + (iv-1)*n ) = one work( ki + (iv )*n ) = wi / t( ki-1, ki ) else work( ki-1 + (iv-1)*n ) = -wi / t( ki, ki-1 ) work( ki + (iv )*n ) = one end if work( ki + (iv-1)*n ) = zero work( ki-1 + (iv )*n ) = zero ! form right-hand side. do k = 1, ki - 2 work( k+(iv-1)*n ) = -work( ki-1+(iv-1)*n )*t(k,ki-1) work( k+(iv )*n ) = -work( ki +(iv )*n )*t(k,ki ) end do ! solve upper quasi-triangular system: ! [ t(1:ki-2,1:ki-2) - (wr+i*wi) ]*x = scale*(work+i*work2) jnxt = ki - 2_${ik}$ loop_90: do j = ki - 2, 1, -1 if( j>jnxt )cycle loop_90 j1 = j j2 = j jnxt = j - 1_${ik}$ if( j>1_${ik}$ ) then if( t( j, j-1 )/=zero ) then j1 = j - 1_${ik}$ jnxt = j - 2_${ik}$ end if end if if( j1==j2 ) then ! 1-by-1 diagonal block call stdlib${ii}$_${ri}$laln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+(iv-1)*n ), n,wr, wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale x(1,1) and x(1,2) to avoid overflow when ! updating the right-hand side. if( xnorm>one ) then if( work( j )>bignum / xnorm ) then x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) / xnorm x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ ) / xnorm scale = scale / xnorm end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+(iv-1)*n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) end if work( j+(iv-1)*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+(iv )*n ) = x( 1_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_${ri}$axpy( j-1, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv-1)*n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j-1, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) else ! 2-by-2 diagonal block call stdlib${ii}$_${ri}$laln2( .false., 2_${ik}$, 2_${ik}$, smin, one,t( j-1, j-1 ), ldt, one, & one,work( j-1+(iv-1)*n ), n, wr, wi, x, 2_${ik}$,scale, xnorm, ierr ) ! scale x to avoid overflow when updating ! the right-hand side. if( xnorm>one ) then beta = max( work( j-1 ), work( j ) ) if( beta>bignum / xnorm ) then rec = one / xnorm x( 1_${ik}$, 1_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ )*rec x( 1_${ik}$, 2_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ )*rec x( 2_${ik}$, 1_${ik}$ ) = x( 2_${ik}$, 1_${ik}$ )*rec x( 2_${ik}$, 2_${ik}$ ) = x( 2_${ik}$, 2_${ik}$ )*rec scale = scale*rec end if end if ! scale if necessary if( scale/=one ) then call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+(iv-1)*n ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( ki, scale, work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) end if work( j-1+(iv-1)*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j +(iv-1)*n ) = x( 2_${ik}$, 1_${ik}$ ) work( j-1+(iv )*n ) = x( 1_${ik}$, 2_${ik}$ ) work( j +(iv )*n ) = x( 2_${ik}$, 2_${ik}$ ) ! update the right-hand side call stdlib${ii}$_${ri}$axpy( j-2, -x( 1_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+(iv-1)*n ),& 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j-2, -x( 2_${ik}$, 1_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv-1)*n ), & 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j-2, -x( 1_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j-1 ), 1_${ik}$,work( 1_${ik}$+(iv )*n ), & 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( j-2, -x( 2_${ik}$, 2_${ik}$ ), t( 1_${ik}$, j ), 1_${ik}$,work( 1_${ik}$+(iv )*n ), 1_${ik}$ ) end if end do loop_90 ! copy the vector x or q*x to vr and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vr and normalize. call stdlib${ii}$_${ri}$copy( ki, work( 1_${ik}$+(iv-1)*n ), 1_${ik}$, vr(1_${ik}$,is-1), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( ki, work( 1_${ik}$+(iv )*n ), 1_${ik}$, vr(1_${ik}$,is ), 1_${ik}$ ) emax = zero do k = 1, ki emax = max( emax, abs( vr( k, is-1 ) )+abs( vr( k, is ) ) ) end do remax = one / emax call stdlib${ii}$_${ri}$scal( ki, remax, vr( 1_${ik}$, is-1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is-1 ) = zero vr( k, is ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki>2_${ik}$ ) then call stdlib${ii}$_${ri}$gemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$ + (iv-1)*n ), & 1_${ik}$,work( ki-1 + (iv-1)*n ), vr(1_${ik}$,ki-1), 1_${ik}$) call stdlib${ii}$_${ri}$gemv( 'N', n, ki-2, one, vr, ldvr,work( 1_${ik}$ + (iv)*n ), 1_${ik}$,& work( ki + (iv)*n ), vr( 1_${ik}$, ki ), 1_${ik}$ ) else call stdlib${ii}$_${ri}$scal( n, work(ki-1+(iv-1)*n), vr(1_${ik}$,ki-1), 1_${ik}$) call stdlib${ii}$_${ri}$scal( n, work(ki +(iv )*n), vr(1_${ik}$,ki ), 1_${ik}$) end if emax = zero do k = 1, n emax = max( emax, abs( vr( k, ki-1 ) )+abs( vr( k, ki ) ) ) end do remax = one / emax call stdlib${ii}$_${ri}$scal( n, remax, vr( 1_${ik}$, ki-1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) else ! ------------------------------ ! version 2: back-transform block of vectors with gemm ! zero out below vector do k = ki + 1, n work( k + (iv-1)*n ) = zero work( k + (iv )*n ) = zero end do iscomplex( iv-1 ) = -ip iscomplex( iv ) = ip iv = iv - 1_${ik}$ ! back-transform and normalization is done below end if end if if( nb>1_${ik}$ ) then ! -------------------------------------------------------- ! blocked version of back-transform ! for complex case, ki2 includes both vectors (ki-1 and ki) if( ip==0_${ik}$ ) then ki2 = ki else ki2 = ki - 1_${ik}$ end if ! columns iv:nb of work are valid vectors. ! when the number of vectors stored reaches nb-1 or nb, ! or if this was last vector, do the gemm if( (iv<=2_${ik}$) .or. (ki2==1_${ik}$) ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, nb-iv+1, ki2+nb-iv, one,vr, ldvr,work( 1_${ik}$ + & (iv)*n ), n,zero,work( 1_${ik}$ + (nb+iv)*n ), n ) ! normalize vectors do k = iv, nb if( iscomplex(k)==0_${ik}$ ) then ! real eigenvector ii = stdlib${ii}$_i${ri}$amax( n, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) remax = one / abs( work( ii + (nb+k)*n ) ) else if( iscomplex(k)==1_${ik}$ ) then ! first eigenvector of conjugate pair emax = zero do ii = 1, n emax = max( emax,abs( work( ii + (nb+k )*n ) )+abs( work( ii + (& nb+k+1)*n ) ) ) end do remax = one / emax ! else if iscomplex(k)==-1 ! second eigenvector of conjugate pair ! reuse same remax as previous k end if call stdlib${ii}$_${ri}$scal( n, remax, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$lacpy( 'F', n, nb-iv+1,work( 1_${ik}$ + (nb+iv)*n ), n,vr( 1_${ik}$, ki2 ), & ldvr ) iv = nb else iv = iv - 1_${ik}$ end if end if ! blocked back-transform is = is - 1_${ik}$ if( ip/=0_${ik}$ )is = is - 1_${ik}$ end do loop_140 end if if( leftv ) then ! ============================================================ ! compute left eigenvectors. ! iv is index of column in current block. ! for complex left vector, uses iv for real part and iv+1 for complex part. ! non-blocked version always uses iv=1; ! blocked version starts with iv=1, goes up to nb-1 or nb. ! (note the "0-th" column is used for 1-norms computed above.) iv = 1_${ik}$ ip = 0_${ik}$ is = 1_${ik}$ loop_260: do ki = 1, n if( ip==1_${ik}$ ) then ! previous iteration (ki-1) was first of conjugate pair, ! so this ki is second of conjugate pair; skip to end of loop ip = -1_${ik}$ cycle loop_260 else if( ki==n ) then ! last column, so this ki must be real eigenvalue ip = 0_${ik}$ else if( t( ki+1, ki )==zero ) then ! zero on sub-diagonal, so this ki is real eigenvalue ip = 0_${ik}$ else ! non-zero on sub-diagonal, so this ki is first of conjugate pair ip = 1_${ik}$ end if if( somev ) then if( .not.select( ki ) )cycle loop_260 end if ! compute the ki-th eigenvalue (wr,wi). wr = t( ki, ki ) wi = zero if( ip/=0_${ik}$ )wi = sqrt( abs( t( ki, ki+1 ) ) )*sqrt( abs( t( ki+1, ki ) ) ) smin = max( ulp*( abs( wr )+abs( wi ) ), smlnum ) if( ip==0_${ik}$ ) then ! -------------------------------------------------------- ! real left eigenvector work( ki + iv*n ) = one ! form right-hand side. do k = ki + 1, n work( k + iv*n ) = -t( ki, k ) end do ! solve transposed quasi-triangular system: ! [ t(ki+1:n,ki+1:n) - wr ]**t * x = scale*work vmax = one vcrit = bignum jnxt = ki + 1_${ik}$ loop_170: do j = ki + 1, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work( ki+iv*n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+iv*n ) = work( j+iv*n ) -stdlib${ii}$_${ri}$dot( j-ki-1, t( ki+1, j ), 1_${ik}$,& work( ki+1+iv*n ), 1_${ik}$ ) ! solve [ t(j,j) - wr ]**t * x = work call stdlib${ii}$_${ri}$laln2( .false., 1_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work( ki+iv*n ), 1_${ik}$ ) work( j+iv*n ) = x( 1_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j+iv*n ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work( ki+iv*n ), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+iv*n ) = work( j+iv*n ) -stdlib${ii}$_${ri}$dot( j-ki-1, t( ki+1, j ), 1_${ik}$,& work( ki+1+iv*n ), 1_${ik}$ ) work( j+1+iv*n ) = work( j+1+iv*n ) -stdlib${ii}$_${ri}$dot( j-ki-1, t( ki+1, j+1 )& , 1_${ik}$,work( ki+1+iv*n ), 1_${ik}$ ) ! solve ! [ t(j,j)-wr t(j,j+1) ]**t * x = scale*( work1 ) ! [ t(j+1,j) t(j+1,j+1)-wr ] ( work2 ) call stdlib${ii}$_${ri}$laln2( .true., 2_${ik}$, 1_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,zero, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one )call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work( ki+iv*n ), 1_${ik}$ ) work( j +iv*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+1+iv*n ) = x( 2_${ik}$, 1_${ik}$ ) vmax = max( abs( work( j +iv*n ) ),abs( work( j+1+iv*n ) ), vmax ) vcrit = bignum / vmax end if end do loop_170 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vl and normalize. call stdlib${ii}$_${ri}$copy( n-ki+1, work( ki + iv*n ), 1_${ik}$,vl( ki, is ), 1_${ik}$ ) ii = stdlib${ii}$_i${ri}$amax( n-ki+1, vl( ki, is ), 1_${ik}$ ) + ki - 1_${ik}$ remax = one / abs( vl( ii, is ) ) call stdlib${ii}$_${ri}$scal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki=abs( t( ki+1, ki ) ) ) then work( ki + (iv )*n ) = wi / t( ki, ki+1 ) work( ki+1 + (iv+1)*n ) = one else work( ki + (iv )*n ) = one work( ki+1 + (iv+1)*n ) = -wi / t( ki+1, ki ) end if work( ki+1 + (iv )*n ) = zero work( ki + (iv+1)*n ) = zero ! form right-hand side. do k = ki + 2, n work( k+(iv )*n ) = -work( ki +(iv )*n )*t(ki, k) work( k+(iv+1)*n ) = -work( ki+1+(iv+1)*n )*t(ki+1,k) end do ! solve transposed quasi-triangular system: ! [ t(ki+2:n,ki+2:n)**t - (wr-i*wi) ]*x = work1+i*work2 vmax = one vcrit = bignum jnxt = ki + 2_${ik}$ loop_200: do j = ki + 2, n if( jvcrit ) then rec = one / vmax call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work(ki+(iv )*n), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work(ki+(iv+1)*n), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j+(iv )*n ) = work( j+(iv)*n ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+2, j )& , 1_${ik}$,work( ki+2+(iv)*n ), 1_${ik}$ ) work( j+(iv+1)*n ) = work( j+(iv+1)*n ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+2, & j ), 1_${ik}$,work( ki+2+(iv+1)*n ), 1_${ik}$ ) ! solve [ t(j,j)-(wr-i*wi) ]*(x11+i*x12)= wk+i*wk2 call stdlib${ii}$_${ri}$laln2( .false., 1_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work(ki+(iv )*n), 1_${ik}$) call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work(ki+(iv+1)*n), 1_${ik}$) end if work( j+(iv )*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j+(iv+1)*n ) = x( 1_${ik}$, 2_${ik}$ ) vmax = max( abs( work( j+(iv )*n ) ),abs( work( j+(iv+1)*n ) ), vmax ) vcrit = bignum / vmax else ! 2-by-2 diagonal block ! scale if necessary to avoid overflow when forming ! the right-hand side elements. beta = max( work( j ), work( j+1 ) ) if( beta>vcrit ) then rec = one / vmax call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work(ki+(iv )*n), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-ki+1, rec, work(ki+(iv+1)*n), 1_${ik}$ ) vmax = one vcrit = bignum end if work( j +(iv )*n ) = work( j+(iv)*n ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+2, & j ), 1_${ik}$,work( ki+2+(iv)*n ), 1_${ik}$ ) work( j +(iv+1)*n ) = work( j+(iv+1)*n ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+2,& j ), 1_${ik}$,work( ki+2+(iv+1)*n ), 1_${ik}$ ) work( j+1+(iv )*n ) = work( j+1+(iv)*n ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+2,& j+1 ), 1_${ik}$,work( ki+2+(iv)*n ), 1_${ik}$ ) work( j+1+(iv+1)*n ) = work( j+1+(iv+1)*n ) -stdlib${ii}$_${ri}$dot( j-ki-2, t( ki+& 2_${ik}$, j+1 ), 1_${ik}$,work( ki+2+(iv+1)*n ), 1_${ik}$ ) ! solve 2-by-2 complex linear equation ! [ (t(j,j) t(j,j+1) )**t - (wr-i*wi)*i ]*x = scale*b ! [ (t(j+1,j) t(j+1,j+1)) ] call stdlib${ii}$_${ri}$laln2( .true., 2_${ik}$, 2_${ik}$, smin, one, t( j, j ),ldt, one, one, & work( j+iv*n ), n, wr,-wi, x, 2_${ik}$, scale, xnorm, ierr ) ! scale if necessary if( scale/=one ) then call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work(ki+(iv )*n), 1_${ik}$) call stdlib${ii}$_${ri}$scal( n-ki+1, scale, work(ki+(iv+1)*n), 1_${ik}$) end if work( j +(iv )*n ) = x( 1_${ik}$, 1_${ik}$ ) work( j +(iv+1)*n ) = x( 1_${ik}$, 2_${ik}$ ) work( j+1+(iv )*n ) = x( 2_${ik}$, 1_${ik}$ ) work( j+1+(iv+1)*n ) = x( 2_${ik}$, 2_${ik}$ ) vmax = max( abs( x( 1_${ik}$, 1_${ik}$ ) ), abs( x( 1_${ik}$, 2_${ik}$ ) ),abs( x( 2_${ik}$, 1_${ik}$ ) ), abs( x(& 2_${ik}$, 2_${ik}$ ) ),vmax ) vcrit = bignum / vmax end if end do loop_200 ! copy the vector x or q*x to vl and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vl and normalize. call stdlib${ii}$_${ri}$copy( n-ki+1, work( ki + (iv )*n ), 1_${ik}$,vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n-ki+1, work( ki + (iv+1)*n ), 1_${ik}$,vl( ki, is+1 ), 1_${ik}$ ) emax = zero do k = ki, n emax = max( emax, abs( vl( k, is ) )+abs( vl( k, is+1 ) ) ) end do remax = one / emax call stdlib${ii}$_${ri}$scal( n-ki+1, remax, vl( ki, is ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n-ki+1, remax, vl( ki, is+1 ), 1_${ik}$ ) do k = 1, ki - 1 vl( k, is ) = zero vl( k, is+1 ) = zero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki1_${ik}$ ) then ! -------------------------------------------------------- ! blocked version of back-transform ! for complex case, ki2 includes both vectors (ki and ki+1) if( ip==0_${ik}$ ) then ki2 = ki else ki2 = ki + 1_${ik}$ end if ! columns 1:iv of work are valid vectors. ! when the number of vectors stored reaches nb-1 or nb, ! or if this was last vector, do the gemm if( (iv>=nb-1) .or. (ki2==n) ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, iv, n-ki2+iv, one,vl( 1_${ik}$, ki2-iv+1 ), ldvl,& work( ki2-iv+1 + (1_${ik}$)*n ), n,zero,work( 1_${ik}$ + (nb+1)*n ), n ) ! normalize vectors do k = 1, iv if( iscomplex(k)==0_${ik}$) then ! real eigenvector ii = stdlib${ii}$_i${ri}$amax( n, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) remax = one / abs( work( ii + (nb+k)*n ) ) else if( iscomplex(k)==1_${ik}$) then ! first eigenvector of conjugate pair emax = zero do ii = 1, n emax = max( emax,abs( work( ii + (nb+k )*n ) )+abs( work( ii + (& nb+k+1)*n ) ) ) end do remax = one / emax ! else if iscomplex(k)==-1 ! second eigenvector of conjugate pair ! reuse same remax as previous k end if call stdlib${ii}$_${ri}$scal( n, remax, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$lacpy( 'F', n, iv,work( 1_${ik}$ + (nb+1)*n ), n,vl( 1_${ik}$, ki2-iv+1 ), & ldvl ) iv = 1_${ik}$ else iv = iv + 1_${ik}$ end if end if ! blocked back-transform is = is + 1_${ik}$ if( ip/=0_${ik}$ )is = is + 1_${ik}$ end do loop_260 end if return end subroutine stdlib${ii}$_${ri}$trevc3 #:endif #:endfor pure module subroutine stdlib${ii}$_ctrevc3( side, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, mm, m, & !! CTREVC3 computes some or all of the right and/or left eigenvectors of !! a complex upper triangular matrix T. !! Matrices of this type are produced by the Schur factorization of !! a complex general matrix: A = Q*T*Q**H, as computed by CHSEQR. !! The right eigenvector x and the left eigenvector y of T corresponding !! to an eigenvalue w are defined by: !! T*x = w*x, (y**H)*T = w*(y**H) !! where y**H denotes the conjugate transpose of the vector y. !! The eigenvalues are not input to this routine, but are read directly !! from the diagonal of T. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an !! input matrix. If Q is the unitary factor that reduces a matrix A to !! Schur form T, then Q*X and Q*Y are the matrices of right and left !! eigenvectors of A. !! This uses a Level 3 BLAS version of the back transformation. work, lwork, rwork, lrwork, info) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: howmny, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldt, ldvl, ldvr, lwork, lrwork, mm, n ! Array Arguments logical(lk), intent(in) :: select(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: t(ldt,*), vl(ldvl,*), vr(ldvr,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmin = 8_${ik}$ integer(${ik}$), parameter :: nbmax = 128_${ik}$ ! Local Scalars logical(lk) :: allv, bothv, leftv, lquery, over, rightv, somev integer(${ik}$) :: i, ii, is, j, k, ki, iv, maxwrk, nb real(sp) :: ovfl, remax, scale, smin, smlnum, ulp, unfl complex(sp) :: cdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements ! decode and test the input parameters bothv = stdlib_lsame( side, 'B' ) rightv = stdlib_lsame( side, 'R' ) .or. bothv leftv = stdlib_lsame( side, 'L' ) .or. bothv allv = stdlib_lsame( howmny, 'A' ) over = stdlib_lsame( howmny, 'B' ) somev = stdlib_lsame( howmny, 'S' ) ! set m to the number of columns required to store the selected ! eigenvectors. if( somev ) then m = 0_${ik}$ do j = 1, n if( select( j ) )m = m + 1_${ik}$ end do else m = n end if info = 0_${ik}$ nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CTREVC', side // howmny, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) maxwrk = n + 2_${ik}$*n*nb work(1_${ik}$) = maxwrk rwork(1_${ik}$) = n lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ ) if( .not.rightv .and. .not.leftv ) then info = -1_${ik}$ else if( .not.allv .and. .not.over .and. .not.somev ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ldt= n + 2_${ik}$*n*nbmin ) then nb = (lwork - n) / (2_${ik}$*n) nb = min( nb, nbmax ) call stdlib${ii}$_claset( 'F', n, 1_${ik}$+2*nb, czero, czero, work, n ) else nb = 1_${ik}$ end if ! set the constants to control overflow. unfl = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) ovfl = one / unfl call stdlib${ii}$_slabad( unfl, ovfl ) ulp = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = unfl*( n / ulp ) ! store the diagonal elements of t in working array work. do i = 1, n work( i ) = t( i, i ) end do ! compute 1-norm of each column of strictly upper triangular ! part of t to control overflow in triangular solver. rwork( 1_${ik}$ ) = zero do j = 2, n rwork( j ) = stdlib${ii}$_scasum( j-1, t( 1_${ik}$, j ), 1_${ik}$ ) end do if( rightv ) then ! ============================================================ ! compute right eigenvectors. ! iv is index of column in current block. ! non-blocked version always uses iv=nb=1; ! blocked version starts with iv=nb, goes down to 1. ! (note the "0-th" column is used to store the original diagonal.) iv = nb is = m loop_80: do ki = n, 1, -1 if( somev ) then if( .not.select( ki ) )cycle loop_80 end if smin = max( ulp*( cabs1( t( ki, ki ) ) ), smlnum ) ! -------------------------------------------------------- ! complex right eigenvector work( ki + iv*n ) = cone ! form right-hand side. do k = 1, ki - 1 work( k + iv*n ) = -t( k, ki ) end do ! solve upper triangular system: ! [ t(1:ki-1,1:ki-1) - t(ki,ki) ]*x = scale*work. do k = 1, ki - 1 t( k, k ) = t( k, k ) - t( ki, ki ) if( cabs1( t( k, k ) )1_${ik}$ ) then call stdlib${ii}$_clatrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', 'Y',ki-1, t, ldt, & work( 1_${ik}$ + iv*n ), scale,rwork, info ) work( ki + iv*n ) = scale end if ! copy the vector x or q*x to vr and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vr and normalize. call stdlib${ii}$_ccopy( ki, work( 1_${ik}$ + iv*n ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_icamax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / cabs1( vr( ii, is ) ) call stdlib${ii}$_csscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = czero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki>1_${ik}$ )call stdlib${ii}$_cgemv( 'N', n, ki-1, cone, vr, ldvr,work( 1_${ik}$ + iv*n ), 1_${ik}$,& cmplx( scale,KIND=sp),vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_icamax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / cabs1( vr( ii, ki ) ) call stdlib${ii}$_csscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) else ! ------------------------------ ! version 2: back-transform block of vectors with gemm ! zero out below vector do k = ki + 1, n work( k + iv*n ) = czero end do ! columns iv:nb of work are valid vectors. ! when the number of vectors stored reaches nb, ! or if this was last vector, do the gemm if( (iv==1_${ik}$) .or. (ki==1_${ik}$) ) then call stdlib${ii}$_cgemm( 'N', 'N', n, nb-iv+1, ki+nb-iv, cone,vr, ldvr,work( 1_${ik}$ + & (iv)*n ), n,czero,work( 1_${ik}$ + (nb+iv)*n ), n ) ! normalize vectors do k = iv, nb ii = stdlib${ii}$_icamax( n, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) remax = one / cabs1( work( ii + (nb+k)*n ) ) call stdlib${ii}$_csscal( n, remax, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) end do call stdlib${ii}$_clacpy( 'F', n, nb-iv+1,work( 1_${ik}$ + (nb+iv)*n ), n,vr( 1_${ik}$, ki ), & ldvr ) iv = nb else iv = iv - 1_${ik}$ end if end if ! restore the original diagonal elements of t. do k = 1, ki - 1 t( k, k ) = work( k ) end do is = is - 1_${ik}$ end do loop_80 end if if( leftv ) then ! ============================================================ ! compute left eigenvectors. ! iv is index of column in current block. ! non-blocked version always uses iv=1; ! blocked version starts with iv=1, goes up to nb. ! (note the "0-th" column is used to store the original diagonal.) iv = 1_${ik}$ is = 1_${ik}$ loop_130: do ki = 1, n if( somev ) then if( .not.select( ki ) )cycle loop_130 end if smin = max( ulp*( cabs1( t( ki, ki ) ) ), smlnum ) ! -------------------------------------------------------- ! complex left eigenvector work( ki + iv*n ) = cone ! form right-hand side. do k = ki + 1, n work( k + iv*n ) = -conjg( t( ki, k ) ) end do ! solve conjugate-transposed triangular system: ! [ t(ki+1:n,ki+1:n) - t(ki,ki) ]**h * x = scale*work. do k = ki + 1, n t( k, k ) = t( k, k ) - t( ki, ki ) if( cabs1( t( k, k ) )= n + 2_${ik}$*n*nbmin ) then nb = (lwork - n) / (2_${ik}$*n) nb = min( nb, nbmax ) call stdlib${ii}$_zlaset( 'F', n, 1_${ik}$+2*nb, czero, czero, work, n ) else nb = 1_${ik}$ end if ! set the constants to control overflow. unfl = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) ovfl = one / unfl call stdlib${ii}$_dlabad( unfl, ovfl ) ulp = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = unfl*( n / ulp ) ! store the diagonal elements of t in working array work. do i = 1, n work( i ) = t( i, i ) end do ! compute 1-norm of each column of strictly upper triangular ! part of t to control overflow in triangular solver. rwork( 1_${ik}$ ) = zero do j = 2, n rwork( j ) = stdlib${ii}$_dzasum( j-1, t( 1_${ik}$, j ), 1_${ik}$ ) end do if( rightv ) then ! ============================================================ ! compute right eigenvectors. ! iv is index of column in current block. ! non-blocked version always uses iv=nb=1; ! blocked version starts with iv=nb, goes down to 1. ! (note the "0-th" column is used to store the original diagonal.) iv = nb is = m loop_80: do ki = n, 1, -1 if( somev ) then if( .not.select( ki ) )cycle loop_80 end if smin = max( ulp*( cabs1( t( ki, ki ) ) ), smlnum ) ! -------------------------------------------------------- ! complex right eigenvector work( ki + iv*n ) = cone ! form right-hand side. do k = 1, ki - 1 work( k + iv*n ) = -t( k, ki ) end do ! solve upper triangular system: ! [ t(1:ki-1,1:ki-1) - t(ki,ki) ]*x = scale*work. do k = 1, ki - 1 t( k, k ) = t( k, k ) - t( ki, ki ) if( cabs1( t( k, k ) )1_${ik}$ ) then call stdlib${ii}$_zlatrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', 'Y',ki-1, t, ldt, & work( 1_${ik}$ + iv*n ), scale,rwork, info ) work( ki + iv*n ) = scale end if ! copy the vector x or q*x to vr and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vr and normalize. call stdlib${ii}$_zcopy( ki, work( 1_${ik}$ + iv*n ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_izamax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / cabs1( vr( ii, is ) ) call stdlib${ii}$_zdscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = czero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki>1_${ik}$ )call stdlib${ii}$_zgemv( 'N', n, ki-1, cone, vr, ldvr,work( 1_${ik}$ + iv*n ), 1_${ik}$,& cmplx( scale,KIND=dp),vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_izamax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / cabs1( vr( ii, ki ) ) call stdlib${ii}$_zdscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) else ! ------------------------------ ! version 2: back-transform block of vectors with gemm ! zero out below vector do k = ki + 1, n work( k + iv*n ) = czero end do ! columns iv:nb of work are valid vectors. ! when the number of vectors stored reaches nb, ! or if this was last vector, do the gemm if( (iv==1_${ik}$) .or. (ki==1_${ik}$) ) then call stdlib${ii}$_zgemm( 'N', 'N', n, nb-iv+1, ki+nb-iv, cone,vr, ldvr,work( 1_${ik}$ + & (iv)*n ), n,czero,work( 1_${ik}$ + (nb+iv)*n ), n ) ! normalize vectors do k = iv, nb ii = stdlib${ii}$_izamax( n, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) remax = one / cabs1( work( ii + (nb+k)*n ) ) call stdlib${ii}$_zdscal( n, remax, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) end do call stdlib${ii}$_zlacpy( 'F', n, nb-iv+1,work( 1_${ik}$ + (nb+iv)*n ), n,vr( 1_${ik}$, ki ), & ldvr ) iv = nb else iv = iv - 1_${ik}$ end if end if ! restore the original diagonal elements of t. do k = 1, ki - 1 t( k, k ) = work( k ) end do is = is - 1_${ik}$ end do loop_80 end if if( leftv ) then ! ============================================================ ! compute left eigenvectors. ! iv is index of column in current block. ! non-blocked version always uses iv=1; ! blocked version starts with iv=1, goes up to nb. ! (note the "0-th" column is used to store the original diagonal.) iv = 1_${ik}$ is = 1_${ik}$ loop_130: do ki = 1, n if( somev ) then if( .not.select( ki ) )cycle loop_130 end if smin = max( ulp*( cabs1( t( ki, ki ) ) ), smlnum ) ! -------------------------------------------------------- ! complex left eigenvector work( ki + iv*n ) = cone ! form right-hand side. do k = ki + 1, n work( k + iv*n ) = -conjg( t( ki, k ) ) end do ! solve conjugate-transposed triangular system: ! [ t(ki+1:n,ki+1:n) - t(ki,ki) ]**h * x = scale*work. do k = ki + 1, n t( k, k ) = t( k, k ) - t( ki, ki ) if( cabs1( t( k, k ) )= n + 2_${ik}$*n*nbmin ) then nb = (lwork - n) / (2_${ik}$*n) nb = min( nb, nbmax ) call stdlib${ii}$_${ci}$laset( 'F', n, 1_${ik}$+2*nb, czero, czero, work, n ) else nb = 1_${ik}$ end if ! set the constants to control overflow. unfl = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) ovfl = one / unfl call stdlib${ii}$_${c2ri(ci)}$labad( unfl, ovfl ) ulp = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = unfl*( n / ulp ) ! store the diagonal elements of t in working array work. do i = 1, n work( i ) = t( i, i ) end do ! compute 1-norm of each column of strictly upper triangular ! part of t to control overflow in triangular solver. rwork( 1_${ik}$ ) = zero do j = 2, n rwork( j ) = stdlib${ii}$_${c2ri(ci)}$zasum( j-1, t( 1_${ik}$, j ), 1_${ik}$ ) end do if( rightv ) then ! ============================================================ ! compute right eigenvectors. ! iv is index of column in current block. ! non-blocked version always uses iv=nb=1; ! blocked version starts with iv=nb, goes down to 1. ! (note the "0-th" column is used to store the original diagonal.) iv = nb is = m loop_80: do ki = n, 1, -1 if( somev ) then if( .not.select( ki ) )cycle loop_80 end if smin = max( ulp*( cabs1( t( ki, ki ) ) ), smlnum ) ! -------------------------------------------------------- ! complex right eigenvector work( ki + iv*n ) = cone ! form right-hand side. do k = 1, ki - 1 work( k + iv*n ) = -t( k, ki ) end do ! solve upper triangular system: ! [ t(1:ki-1,1:ki-1) - t(ki,ki) ]*x = scale*work. do k = 1, ki - 1 t( k, k ) = t( k, k ) - t( ki, ki ) if( cabs1( t( k, k ) )1_${ik}$ ) then call stdlib${ii}$_${ci}$latrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', 'Y',ki-1, t, ldt, & work( 1_${ik}$ + iv*n ), scale,rwork, info ) work( ki + iv*n ) = scale end if ! copy the vector x or q*x to vr and normalize. if( .not.over ) then ! ------------------------------ ! no back-transform: copy x to vr and normalize. call stdlib${ii}$_${ci}$copy( ki, work( 1_${ik}$ + iv*n ), 1_${ik}$, vr( 1_${ik}$, is ), 1_${ik}$ ) ii = stdlib${ii}$_i${ci}$amax( ki, vr( 1_${ik}$, is ), 1_${ik}$ ) remax = one / cabs1( vr( ii, is ) ) call stdlib${ii}$_${ci}$dscal( ki, remax, vr( 1_${ik}$, is ), 1_${ik}$ ) do k = ki + 1, n vr( k, is ) = czero end do else if( nb==1_${ik}$ ) then ! ------------------------------ ! version 1: back-transform each vector with gemv, q*x. if( ki>1_${ik}$ )call stdlib${ii}$_${ci}$gemv( 'N', n, ki-1, cone, vr, ldvr,work( 1_${ik}$ + iv*n ), 1_${ik}$,& cmplx( scale,KIND=${ck}$),vr( 1_${ik}$, ki ), 1_${ik}$ ) ii = stdlib${ii}$_i${ci}$amax( n, vr( 1_${ik}$, ki ), 1_${ik}$ ) remax = one / cabs1( vr( ii, ki ) ) call stdlib${ii}$_${ci}$dscal( n, remax, vr( 1_${ik}$, ki ), 1_${ik}$ ) else ! ------------------------------ ! version 2: back-transform block of vectors with gemm ! zero out below vector do k = ki + 1, n work( k + iv*n ) = czero end do ! columns iv:nb of work are valid vectors. ! when the number of vectors stored reaches nb, ! or if this was last vector, do the gemm if( (iv==1_${ik}$) .or. (ki==1_${ik}$) ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', n, nb-iv+1, ki+nb-iv, cone,vr, ldvr,work( 1_${ik}$ + & (iv)*n ), n,czero,work( 1_${ik}$ + (nb+iv)*n ), n ) ! normalize vectors do k = iv, nb ii = stdlib${ii}$_i${ci}$amax( n, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) remax = one / cabs1( work( ii + (nb+k)*n ) ) call stdlib${ii}$_${ci}$dscal( n, remax, work( 1_${ik}$ + (nb+k)*n ), 1_${ik}$ ) end do call stdlib${ii}$_${ci}$lacpy( 'F', n, nb-iv+1,work( 1_${ik}$ + (nb+iv)*n ), n,vr( 1_${ik}$, ki ), & ldvr ) iv = nb else iv = iv - 1_${ik}$ end if end if ! restore the original diagonal elements of t. do k = 1, ki - 1 t( k, k ) = work( k ) end do is = is - 1_${ik}$ end do loop_80 end if if( leftv ) then ! ============================================================ ! compute left eigenvectors. ! iv is index of column in current block. ! non-blocked version always uses iv=1; ! blocked version starts with iv=1, goes up to nb. ! (note the "0-th" column is used to store the original diagonal.) iv = 1_${ik}$ is = 1_${ik}$ loop_130: do ki = 1, n if( somev ) then if( .not.select( ki ) )cycle loop_130 end if smin = max( ulp*( cabs1( t( ki, ki ) ) ), smlnum ) ! -------------------------------------------------------- ! complex left eigenvector work( ki + iv*n ) = cone ! form right-hand side. do k = ki + 1, n work( k + iv*n ) = -conjg( t( ki, k ) ) end do ! solve conjugate-transposed triangular system: ! [ t(ki+1:n,ki+1:n) - t(ki,ki) ]**h * x = scale*work. do k = ki + 1, n t( k, k ) = t( k, k ) - t( ki, ki ) if( cabs1( t( k, k ) )one ) then if( bnorm>bignum*cnorm )scale = one / bnorm end if ! compute x x( 1_${ik}$, 1_${ik}$ ) = ( b( 1_${ik}$, 1_${ik}$ )*scale ) / csr xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) else ! complex 1x1 system (w is complex) ! c = ca a - w d csr = ca*a( 1_${ik}$, 1_${ik}$ ) - wr*d1 csi = -wi*d1 cnorm = abs( csr ) + abs( csi ) ! if | c | < smini, use c = smini if( cnormone ) then if( bnorm>bignum*cnorm )scale = one / bnorm end if ! compute x call stdlib${ii}$_sladiv( scale*b( 1_${ik}$, 1_${ik}$ ), scale*b( 1_${ik}$, 2_${ik}$ ), csr, csi,x( 1_${ik}$, 1_${ik}$ ), x( 1_${ik}$, & 2_${ik}$ ) ) xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) + abs( x( 1_${ik}$, 2_${ik}$ ) ) end if else ! 2x2 system ! compute the realpart of c = ca a - w d (or ca a**t - w d,KIND=sp) cr( 1_${ik}$, 1_${ik}$ ) = ca*a( 1_${ik}$, 1_${ik}$ ) - wr*d1 cr( 2_${ik}$, 2_${ik}$ ) = ca*a( 2_${ik}$, 2_${ik}$ ) - wr*d2 if( ltrans ) then cr( 1_${ik}$, 2_${ik}$ ) = ca*a( 2_${ik}$, 1_${ik}$ ) cr( 2_${ik}$, 1_${ik}$ ) = ca*a( 1_${ik}$, 2_${ik}$ ) else cr( 2_${ik}$, 1_${ik}$ ) = ca*a( 2_${ik}$, 1_${ik}$ ) cr( 1_${ik}$, 2_${ik}$ ) = ca*a( 1_${ik}$, 2_${ik}$ ) end if if( nw==1_${ik}$ ) then ! real2x2 system (w is real,KIND=sp) ! find the largest element in c cmax = zero icmax = 0_${ik}$ do j = 1, 4 if( abs( crv( j ) )>cmax ) then cmax = abs( crv( j ) ) icmax = j end if end do ! if norm(c) < smini, use smini*identity. if( cmaxone ) then if( bnorm>bignum*smini )scale = one / bnorm end if temp = scale / smini x( 1_${ik}$, 1_${ik}$ ) = temp*b( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*b( 2_${ik}$, 1_${ik}$ ) xnorm = temp*bnorm info = 1_${ik}$ return end if ! gaussian elimination with complete pivoting. ur11 = crv( icmax ) cr21 = crv( ipivot( 2_${ik}$, icmax ) ) ur12 = crv( ipivot( 3_${ik}$, icmax ) ) cr22 = crv( ipivot( 4_${ik}$, icmax ) ) ur11r = one / ur11 lr21 = ur11r*cr21 ur22 = cr22 - ur12*lr21 ! if smaller pivot < smini, use smini if( abs( ur22 )one .and. abs( ur22 )=bignum*abs( ur22 ) )scale = one / bbnd end if xr2 = ( br2*scale ) / ur22 xr1 = ( scale*br1 )*ur11r - xr2*( ur11r*ur12 ) if( cswap( icmax ) ) then x( 1_${ik}$, 1_${ik}$ ) = xr2 x( 2_${ik}$, 1_${ik}$ ) = xr1 else x( 1_${ik}$, 1_${ik}$ ) = xr1 x( 2_${ik}$, 1_${ik}$ ) = xr2 end if xnorm = max( abs( xr1 ), abs( xr2 ) ) ! further scaling if norm(a) norm(x) > overflow if( xnorm>one .and. cmax>one ) then if( xnorm>bignum / cmax ) then temp = cmax / bignum x( 1_${ik}$, 1_${ik}$ ) = temp*x( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*x( 2_${ik}$, 1_${ik}$ ) xnorm = temp*xnorm scale = temp*scale end if end if else ! complex 2x2 system (w is complex) ! find the largest element in c ci( 1_${ik}$, 1_${ik}$ ) = -wi*d1 ci( 2_${ik}$, 1_${ik}$ ) = zero ci( 1_${ik}$, 2_${ik}$ ) = zero ci( 2_${ik}$, 2_${ik}$ ) = -wi*d2 cmax = zero icmax = 0_${ik}$ do j = 1, 4 if( abs( crv( j ) )+abs( civ( j ) )>cmax ) then cmax = abs( crv( j ) ) + abs( civ( j ) ) icmax = j end if end do ! if norm(c) < smini, use smini*identity. if( cmaxone ) then if( bnorm>bignum*smini )scale = one / bnorm end if temp = scale / smini x( 1_${ik}$, 1_${ik}$ ) = temp*b( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*b( 2_${ik}$, 1_${ik}$ ) x( 1_${ik}$, 2_${ik}$ ) = temp*b( 1_${ik}$, 2_${ik}$ ) x( 2_${ik}$, 2_${ik}$ ) = temp*b( 2_${ik}$, 2_${ik}$ ) xnorm = temp*bnorm info = 1_${ik}$ return end if ! gaussian elimination with complete pivoting. ur11 = crv( icmax ) ui11 = civ( icmax ) cr21 = crv( ipivot( 2_${ik}$, icmax ) ) ci21 = civ( ipivot( 2_${ik}$, icmax ) ) ur12 = crv( ipivot( 3_${ik}$, icmax ) ) ui12 = civ( ipivot( 3_${ik}$, icmax ) ) cr22 = crv( ipivot( 4_${ik}$, icmax ) ) ci22 = civ( ipivot( 4_${ik}$, icmax ) ) if( icmax==1_${ik}$ .or. icmax==4_${ik}$ ) then ! code when off-diagonals of pivoted c are real if( abs( ur11 )>abs( ui11 ) ) then temp = ui11 / ur11 ur11r = one / ( ur11*( one+temp**2_${ik}$ ) ) ui11r = -temp*ur11r else temp = ur11 / ui11 ui11r = -one / ( ui11*( one+temp**2_${ik}$ ) ) ur11r = -temp*ui11r end if lr21 = cr21*ur11r li21 = cr21*ui11r ur12s = ur12*ur11r ui12s = ur12*ui11r ur22 = cr22 - ur12*lr21 ui22 = ci22 - ur12*li21 else ! code when diagonals of pivoted c are real ur11r = one / ur11 ui11r = zero lr21 = cr21*ur11r li21 = ci21*ur11r ur12s = ur12*ur11r ui12s = ui12*ur11r ur22 = cr22 - ur12*lr21 + ui12*li21 ui22 = -ur12*li21 - ui12*lr21 end if u22abs = abs( ur22 ) + abs( ui22 ) ! if smaller pivot < smini, use smini if( u22absone .and. u22abs=bignum*u22abs ) then scale = one / bbnd br1 = scale*br1 bi1 = scale*bi1 br2 = scale*br2 bi2 = scale*bi2 end if end if call stdlib${ii}$_sladiv( br2, bi2, ur22, ui22, xr2, xi2 ) xr1 = ur11r*br1 - ui11r*bi1 - ur12s*xr2 + ui12s*xi2 xi1 = ui11r*br1 + ur11r*bi1 - ui12s*xr2 - ur12s*xi2 if( cswap( icmax ) ) then x( 1_${ik}$, 1_${ik}$ ) = xr2 x( 2_${ik}$, 1_${ik}$ ) = xr1 x( 1_${ik}$, 2_${ik}$ ) = xi2 x( 2_${ik}$, 2_${ik}$ ) = xi1 else x( 1_${ik}$, 1_${ik}$ ) = xr1 x( 2_${ik}$, 1_${ik}$ ) = xr2 x( 1_${ik}$, 2_${ik}$ ) = xi1 x( 2_${ik}$, 2_${ik}$ ) = xi2 end if xnorm = max( abs( xr1 )+abs( xi1 ), abs( xr2 )+abs( xi2 ) ) ! further scaling if norm(a) norm(x) > overflow if( xnorm>one .and. cmax>one ) then if( xnorm>bignum / cmax ) then temp = cmax / bignum x( 1_${ik}$, 1_${ik}$ ) = temp*x( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*x( 2_${ik}$, 1_${ik}$ ) x( 1_${ik}$, 2_${ik}$ ) = temp*x( 1_${ik}$, 2_${ik}$ ) x( 2_${ik}$, 2_${ik}$ ) = temp*x( 2_${ik}$, 2_${ik}$ ) xnorm = temp*xnorm scale = temp*scale end if end if end if end if return end subroutine stdlib${ii}$_slaln2 pure module subroutine stdlib${ii}$_dlaln2( ltrans, na, nw, smin, ca, a, lda, d1, d2, b,ldb, wr, wi, x, & !! DLALN2 solves a system of the form (ca A - w D ) X = s B !! or (ca A**T - w D) X = s B with possible scaling ("s") and !! perturbation of A. (A**T means A-transpose.) !! A is an NA x NA real matrix, ca is a real scalar, D is an NA x NA !! real diagonal matrix, w is a real or complex value, and X and B are !! NA x 1 matrices -- real if w is real, complex if w is complex. NA !! may be 1 or 2. !! If w is complex, X and B are represented as NA x 2 matrices, !! the first column of each being the real part and the second !! being the imaginary part. !! "s" is a scaling factor (<= 1), computed by DLALN2, which is !! so chosen that X can be computed without overflow. X is further !! scaled if necessary to assure that norm(ca A - w D)*norm(X) is less !! than overflow. !! If both singular values of (ca A - w D) are less than SMIN, !! SMIN*identity will be used instead of (ca A - w D). If only one !! singular value is less than SMIN, one element of (ca A - w D) will be !! perturbed enough to make the smallest singular value roughly SMIN. !! If both singular values are at least SMIN, (ca A - w D) will not be !! perturbed. In any case, the perturbation will be at most some small !! multiple of max( SMIN, ulp*norm(ca A - w D) ). The singular values !! are computed by infinity-norm approximations, and thus will only be !! correct to a factor of 2 or so. !! Note: all input quantities are assumed to be smaller than overflow !! by a reasonable factor. (See BIGNUM.) ldx, scale, xnorm, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: ltrans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldx, na, nw real(dp), intent(in) :: ca, d1, d2, smin, wi, wr real(dp), intent(out) :: scale, xnorm ! Array Arguments real(dp), intent(in) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: icmax, j real(dp) :: bbnd, bi1, bi2, bignum, bnorm, br1, br2, ci21, ci22, cmax, cnorm, cr21, & cr22, csi, csr, li21, lr21, smini, smlnum, temp, u22abs, ui11, ui11r, ui12, ui12s, & ui22, ur11, ur11r, ur12, ur12s, ur22, xi1, xi2, xr1, xr2 ! Local Arrays logical(lk) :: rswap(4_${ik}$), zswap(4_${ik}$) integer(${ik}$) :: ipivot(4_${ik}$,4_${ik}$) real(dp) :: ci(2_${ik}$,2_${ik}$), civ(4_${ik}$), cr(2_${ik}$,2_${ik}$), crv(4_${ik}$) ! Intrinsic Functions ! Equivalences equivalence ( ci( 1_${ik}$, 1_${ik}$ ), civ( 1_${ik}$ ) ),( cr( 1_${ik}$, 1_${ik}$ ), crv( 1_${ik}$ ) ) ! Data Statements zswap = [.false.,.false.,.true.,.true.] rswap = [.false.,.true.,.false.,.true.] ipivot = reshape([1_${ik}$,2_${ik}$,3_${ik}$,4_${ik}$,2_${ik}$,1_${ik}$,4_${ik}$,3_${ik}$,3_${ik}$,4_${ik}$,1_${ik}$,2_${ik}$,4_${ik}$,3_${ik}$,2_${ik}$,1_${ik}$],[4_${ik}$,4_${ik}$]) ! Executable Statements ! compute bignum smlnum = two*stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) bignum = one / smlnum smini = max( smin, smlnum ) ! don't check for input errors info = 0_${ik}$ ! standard initializations scale = one if( na==1_${ik}$ ) then ! 1 x 1 (i.e., scalar) system c x = b if( nw==1_${ik}$ ) then ! real 1x1 system. ! c = ca a - w d csr = ca*a( 1_${ik}$, 1_${ik}$ ) - wr*d1 cnorm = abs( csr ) ! if | c | < smini, use c = smini if( cnormone ) then if( bnorm>bignum*cnorm )scale = one / bnorm end if ! compute x x( 1_${ik}$, 1_${ik}$ ) = ( b( 1_${ik}$, 1_${ik}$ )*scale ) / csr xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) else ! complex 1x1 system (w is complex) ! c = ca a - w d csr = ca*a( 1_${ik}$, 1_${ik}$ ) - wr*d1 csi = -wi*d1 cnorm = abs( csr ) + abs( csi ) ! if | c | < smini, use c = smini if( cnormone ) then if( bnorm>bignum*cnorm )scale = one / bnorm end if ! compute x call stdlib${ii}$_dladiv( scale*b( 1_${ik}$, 1_${ik}$ ), scale*b( 1_${ik}$, 2_${ik}$ ), csr, csi,x( 1_${ik}$, 1_${ik}$ ), x( 1_${ik}$, & 2_${ik}$ ) ) xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) + abs( x( 1_${ik}$, 2_${ik}$ ) ) end if else ! 2x2 system ! compute the realpart of c = ca a - w d (or ca a**t - w d,KIND=dp) cr( 1_${ik}$, 1_${ik}$ ) = ca*a( 1_${ik}$, 1_${ik}$ ) - wr*d1 cr( 2_${ik}$, 2_${ik}$ ) = ca*a( 2_${ik}$, 2_${ik}$ ) - wr*d2 if( ltrans ) then cr( 1_${ik}$, 2_${ik}$ ) = ca*a( 2_${ik}$, 1_${ik}$ ) cr( 2_${ik}$, 1_${ik}$ ) = ca*a( 1_${ik}$, 2_${ik}$ ) else cr( 2_${ik}$, 1_${ik}$ ) = ca*a( 2_${ik}$, 1_${ik}$ ) cr( 1_${ik}$, 2_${ik}$ ) = ca*a( 1_${ik}$, 2_${ik}$ ) end if if( nw==1_${ik}$ ) then ! real2x2 system (w is real,KIND=dp) ! find the largest element in c cmax = zero icmax = 0_${ik}$ do j = 1, 4 if( abs( crv( j ) )>cmax ) then cmax = abs( crv( j ) ) icmax = j end if end do ! if norm(c) < smini, use smini*identity. if( cmaxone ) then if( bnorm>bignum*smini )scale = one / bnorm end if temp = scale / smini x( 1_${ik}$, 1_${ik}$ ) = temp*b( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*b( 2_${ik}$, 1_${ik}$ ) xnorm = temp*bnorm info = 1_${ik}$ return end if ! gaussian elimination with complete pivoting. ur11 = crv( icmax ) cr21 = crv( ipivot( 2_${ik}$, icmax ) ) ur12 = crv( ipivot( 3_${ik}$, icmax ) ) cr22 = crv( ipivot( 4_${ik}$, icmax ) ) ur11r = one / ur11 lr21 = ur11r*cr21 ur22 = cr22 - ur12*lr21 ! if smaller pivot < smini, use smini if( abs( ur22 )one .and. abs( ur22 )=bignum*abs( ur22 ) )scale = one / bbnd end if xr2 = ( br2*scale ) / ur22 xr1 = ( scale*br1 )*ur11r - xr2*( ur11r*ur12 ) if( zswap( icmax ) ) then x( 1_${ik}$, 1_${ik}$ ) = xr2 x( 2_${ik}$, 1_${ik}$ ) = xr1 else x( 1_${ik}$, 1_${ik}$ ) = xr1 x( 2_${ik}$, 1_${ik}$ ) = xr2 end if xnorm = max( abs( xr1 ), abs( xr2 ) ) ! further scaling if norm(a) norm(x) > overflow if( xnorm>one .and. cmax>one ) then if( xnorm>bignum / cmax ) then temp = cmax / bignum x( 1_${ik}$, 1_${ik}$ ) = temp*x( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*x( 2_${ik}$, 1_${ik}$ ) xnorm = temp*xnorm scale = temp*scale end if end if else ! complex 2x2 system (w is complex) ! find the largest element in c ci( 1_${ik}$, 1_${ik}$ ) = -wi*d1 ci( 2_${ik}$, 1_${ik}$ ) = zero ci( 1_${ik}$, 2_${ik}$ ) = zero ci( 2_${ik}$, 2_${ik}$ ) = -wi*d2 cmax = zero icmax = 0_${ik}$ do j = 1, 4 if( abs( crv( j ) )+abs( civ( j ) )>cmax ) then cmax = abs( crv( j ) ) + abs( civ( j ) ) icmax = j end if end do ! if norm(c) < smini, use smini*identity. if( cmaxone ) then if( bnorm>bignum*smini )scale = one / bnorm end if temp = scale / smini x( 1_${ik}$, 1_${ik}$ ) = temp*b( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*b( 2_${ik}$, 1_${ik}$ ) x( 1_${ik}$, 2_${ik}$ ) = temp*b( 1_${ik}$, 2_${ik}$ ) x( 2_${ik}$, 2_${ik}$ ) = temp*b( 2_${ik}$, 2_${ik}$ ) xnorm = temp*bnorm info = 1_${ik}$ return end if ! gaussian elimination with complete pivoting. ur11 = crv( icmax ) ui11 = civ( icmax ) cr21 = crv( ipivot( 2_${ik}$, icmax ) ) ci21 = civ( ipivot( 2_${ik}$, icmax ) ) ur12 = crv( ipivot( 3_${ik}$, icmax ) ) ui12 = civ( ipivot( 3_${ik}$, icmax ) ) cr22 = crv( ipivot( 4_${ik}$, icmax ) ) ci22 = civ( ipivot( 4_${ik}$, icmax ) ) if( icmax==1_${ik}$ .or. icmax==4_${ik}$ ) then ! code when off-diagonals of pivoted c are real if( abs( ur11 )>abs( ui11 ) ) then temp = ui11 / ur11 ur11r = one / ( ur11*( one+temp**2_${ik}$ ) ) ui11r = -temp*ur11r else temp = ur11 / ui11 ui11r = -one / ( ui11*( one+temp**2_${ik}$ ) ) ur11r = -temp*ui11r end if lr21 = cr21*ur11r li21 = cr21*ui11r ur12s = ur12*ur11r ui12s = ur12*ui11r ur22 = cr22 - ur12*lr21 ui22 = ci22 - ur12*li21 else ! code when diagonals of pivoted c are real ur11r = one / ur11 ui11r = zero lr21 = cr21*ur11r li21 = ci21*ur11r ur12s = ur12*ur11r ui12s = ui12*ur11r ur22 = cr22 - ur12*lr21 + ui12*li21 ui22 = -ur12*li21 - ui12*lr21 end if u22abs = abs( ur22 ) + abs( ui22 ) ! if smaller pivot < smini, use smini if( u22absone .and. u22abs=bignum*u22abs ) then scale = one / bbnd br1 = scale*br1 bi1 = scale*bi1 br2 = scale*br2 bi2 = scale*bi2 end if end if call stdlib${ii}$_dladiv( br2, bi2, ur22, ui22, xr2, xi2 ) xr1 = ur11r*br1 - ui11r*bi1 - ur12s*xr2 + ui12s*xi2 xi1 = ui11r*br1 + ur11r*bi1 - ui12s*xr2 - ur12s*xi2 if( zswap( icmax ) ) then x( 1_${ik}$, 1_${ik}$ ) = xr2 x( 2_${ik}$, 1_${ik}$ ) = xr1 x( 1_${ik}$, 2_${ik}$ ) = xi2 x( 2_${ik}$, 2_${ik}$ ) = xi1 else x( 1_${ik}$, 1_${ik}$ ) = xr1 x( 2_${ik}$, 1_${ik}$ ) = xr2 x( 1_${ik}$, 2_${ik}$ ) = xi1 x( 2_${ik}$, 2_${ik}$ ) = xi2 end if xnorm = max( abs( xr1 )+abs( xi1 ), abs( xr2 )+abs( xi2 ) ) ! further scaling if norm(a) norm(x) > overflow if( xnorm>one .and. cmax>one ) then if( xnorm>bignum / cmax ) then temp = cmax / bignum x( 1_${ik}$, 1_${ik}$ ) = temp*x( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*x( 2_${ik}$, 1_${ik}$ ) x( 1_${ik}$, 2_${ik}$ ) = temp*x( 1_${ik}$, 2_${ik}$ ) x( 2_${ik}$, 2_${ik}$ ) = temp*x( 2_${ik}$, 2_${ik}$ ) xnorm = temp*xnorm scale = temp*scale end if end if end if end if return end subroutine stdlib${ii}$_dlaln2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laln2( ltrans, na, nw, smin, ca, a, lda, d1, d2, b,ldb, wr, wi, x, & !! DLALN2: solves a system of the form (ca A - w D ) X = s B !! or (ca A**T - w D) X = s B with possible scaling ("s") and !! perturbation of A. (A**T means A-transpose.) !! A is an NA x NA real matrix, ca is a real scalar, D is an NA x NA !! real diagonal matrix, w is a real or complex value, and X and B are !! NA x 1 matrices -- real if w is real, complex if w is complex. NA !! may be 1 or 2. !! If w is complex, X and B are represented as NA x 2 matrices, !! the first column of each being the real part and the second !! being the imaginary part. !! "s" is a scaling factor (<= 1), computed by DLALN2, which is !! so chosen that X can be computed without overflow. X is further !! scaled if necessary to assure that norm(ca A - w D)*norm(X) is less !! than overflow. !! If both singular values of (ca A - w D) are less than SMIN, !! SMIN*identity will be used instead of (ca A - w D). If only one !! singular value is less than SMIN, one element of (ca A - w D) will be !! perturbed enough to make the smallest singular value roughly SMIN. !! If both singular values are at least SMIN, (ca A - w D) will not be !! perturbed. In any case, the perturbation will be at most some small !! multiple of max( SMIN, ulp*norm(ca A - w D) ). The singular values !! are computed by infinity-norm approximations, and thus will only be !! correct to a factor of 2 or so. !! Note: all input quantities are assumed to be smaller than overflow !! by a reasonable factor. (See BIGNUM.) ldx, scale, xnorm, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: ltrans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldx, na, nw real(${rk}$), intent(in) :: ca, d1, d2, smin, wi, wr real(${rk}$), intent(out) :: scale, xnorm ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: x(ldx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: icmax, j real(${rk}$) :: bbnd, bi1, bi2, bignum, bnorm, br1, br2, ci21, ci22, cmax, cnorm, cr21, & cr22, csi, csr, li21, lr21, smini, smlnum, temp, u22abs, ui11, ui11r, ui12, ui12s, & ui22, ur11, ur11r, ur12, ur12s, ur22, xi1, xi2, xr1, xr2 ! Local Arrays logical(lk) :: rswap(4_${ik}$), zswap(4_${ik}$) integer(${ik}$) :: ipivot(4_${ik}$,4_${ik}$) real(${rk}$) :: ci(2_${ik}$,2_${ik}$), civ(4_${ik}$), cr(2_${ik}$,2_${ik}$), crv(4_${ik}$) ! Intrinsic Functions ! Equivalences equivalence ( ci( 1_${ik}$, 1_${ik}$ ), civ( 1_${ik}$ ) ),( cr( 1_${ik}$, 1_${ik}$ ), crv( 1_${ik}$ ) ) ! Data Statements zswap = [.false.,.false.,.true.,.true.] rswap = [.false.,.true.,.false.,.true.] ipivot = reshape([1_${ik}$,2_${ik}$,3_${ik}$,4_${ik}$,2_${ik}$,1_${ik}$,4_${ik}$,3_${ik}$,3_${ik}$,4_${ik}$,1_${ik}$,2_${ik}$,4_${ik}$,3_${ik}$,2_${ik}$,1_${ik}$],[4_${ik}$,4_${ik}$]) ! Executable Statements ! compute bignum smlnum = two*stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) bignum = one / smlnum smini = max( smin, smlnum ) ! don't check for input errors info = 0_${ik}$ ! standard initializations scale = one if( na==1_${ik}$ ) then ! 1 x 1 (i.e., scalar) system c x = b if( nw==1_${ik}$ ) then ! real 1x1 system. ! c = ca a - w d csr = ca*a( 1_${ik}$, 1_${ik}$ ) - wr*d1 cnorm = abs( csr ) ! if | c | < smini, use c = smini if( cnormone ) then if( bnorm>bignum*cnorm )scale = one / bnorm end if ! compute x x( 1_${ik}$, 1_${ik}$ ) = ( b( 1_${ik}$, 1_${ik}$ )*scale ) / csr xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) else ! complex 1x1 system (w is complex) ! c = ca a - w d csr = ca*a( 1_${ik}$, 1_${ik}$ ) - wr*d1 csi = -wi*d1 cnorm = abs( csr ) + abs( csi ) ! if | c | < smini, use c = smini if( cnormone ) then if( bnorm>bignum*cnorm )scale = one / bnorm end if ! compute x call stdlib${ii}$_${ri}$ladiv( scale*b( 1_${ik}$, 1_${ik}$ ), scale*b( 1_${ik}$, 2_${ik}$ ), csr, csi,x( 1_${ik}$, 1_${ik}$ ), x( 1_${ik}$, & 2_${ik}$ ) ) xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) + abs( x( 1_${ik}$, 2_${ik}$ ) ) end if else ! 2x2 system ! compute the realpart of c = ca a - w d (or ca a**t - w d,KIND=${rk}$) cr( 1_${ik}$, 1_${ik}$ ) = ca*a( 1_${ik}$, 1_${ik}$ ) - wr*d1 cr( 2_${ik}$, 2_${ik}$ ) = ca*a( 2_${ik}$, 2_${ik}$ ) - wr*d2 if( ltrans ) then cr( 1_${ik}$, 2_${ik}$ ) = ca*a( 2_${ik}$, 1_${ik}$ ) cr( 2_${ik}$, 1_${ik}$ ) = ca*a( 1_${ik}$, 2_${ik}$ ) else cr( 2_${ik}$, 1_${ik}$ ) = ca*a( 2_${ik}$, 1_${ik}$ ) cr( 1_${ik}$, 2_${ik}$ ) = ca*a( 1_${ik}$, 2_${ik}$ ) end if if( nw==1_${ik}$ ) then ! real2x2 system (w is real,KIND=${rk}$) ! find the largest element in c cmax = zero icmax = 0_${ik}$ do j = 1, 4 if( abs( crv( j ) )>cmax ) then cmax = abs( crv( j ) ) icmax = j end if end do ! if norm(c) < smini, use smini*identity. if( cmaxone ) then if( bnorm>bignum*smini )scale = one / bnorm end if temp = scale / smini x( 1_${ik}$, 1_${ik}$ ) = temp*b( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*b( 2_${ik}$, 1_${ik}$ ) xnorm = temp*bnorm info = 1_${ik}$ return end if ! gaussian elimination with complete pivoting. ur11 = crv( icmax ) cr21 = crv( ipivot( 2_${ik}$, icmax ) ) ur12 = crv( ipivot( 3_${ik}$, icmax ) ) cr22 = crv( ipivot( 4_${ik}$, icmax ) ) ur11r = one / ur11 lr21 = ur11r*cr21 ur22 = cr22 - ur12*lr21 ! if smaller pivot < smini, use smini if( abs( ur22 )one .and. abs( ur22 )=bignum*abs( ur22 ) )scale = one / bbnd end if xr2 = ( br2*scale ) / ur22 xr1 = ( scale*br1 )*ur11r - xr2*( ur11r*ur12 ) if( zswap( icmax ) ) then x( 1_${ik}$, 1_${ik}$ ) = xr2 x( 2_${ik}$, 1_${ik}$ ) = xr1 else x( 1_${ik}$, 1_${ik}$ ) = xr1 x( 2_${ik}$, 1_${ik}$ ) = xr2 end if xnorm = max( abs( xr1 ), abs( xr2 ) ) ! further scaling if norm(a) norm(x) > overflow if( xnorm>one .and. cmax>one ) then if( xnorm>bignum / cmax ) then temp = cmax / bignum x( 1_${ik}$, 1_${ik}$ ) = temp*x( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*x( 2_${ik}$, 1_${ik}$ ) xnorm = temp*xnorm scale = temp*scale end if end if else ! complex 2x2 system (w is complex) ! find the largest element in c ci( 1_${ik}$, 1_${ik}$ ) = -wi*d1 ci( 2_${ik}$, 1_${ik}$ ) = zero ci( 1_${ik}$, 2_${ik}$ ) = zero ci( 2_${ik}$, 2_${ik}$ ) = -wi*d2 cmax = zero icmax = 0_${ik}$ do j = 1, 4 if( abs( crv( j ) )+abs( civ( j ) )>cmax ) then cmax = abs( crv( j ) ) + abs( civ( j ) ) icmax = j end if end do ! if norm(c) < smini, use smini*identity. if( cmaxone ) then if( bnorm>bignum*smini )scale = one / bnorm end if temp = scale / smini x( 1_${ik}$, 1_${ik}$ ) = temp*b( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*b( 2_${ik}$, 1_${ik}$ ) x( 1_${ik}$, 2_${ik}$ ) = temp*b( 1_${ik}$, 2_${ik}$ ) x( 2_${ik}$, 2_${ik}$ ) = temp*b( 2_${ik}$, 2_${ik}$ ) xnorm = temp*bnorm info = 1_${ik}$ return end if ! gaussian elimination with complete pivoting. ur11 = crv( icmax ) ui11 = civ( icmax ) cr21 = crv( ipivot( 2_${ik}$, icmax ) ) ci21 = civ( ipivot( 2_${ik}$, icmax ) ) ur12 = crv( ipivot( 3_${ik}$, icmax ) ) ui12 = civ( ipivot( 3_${ik}$, icmax ) ) cr22 = crv( ipivot( 4_${ik}$, icmax ) ) ci22 = civ( ipivot( 4_${ik}$, icmax ) ) if( icmax==1_${ik}$ .or. icmax==4_${ik}$ ) then ! code when off-diagonals of pivoted c are real if( abs( ur11 )>abs( ui11 ) ) then temp = ui11 / ur11 ur11r = one / ( ur11*( one+temp**2_${ik}$ ) ) ui11r = -temp*ur11r else temp = ur11 / ui11 ui11r = -one / ( ui11*( one+temp**2_${ik}$ ) ) ur11r = -temp*ui11r end if lr21 = cr21*ur11r li21 = cr21*ui11r ur12s = ur12*ur11r ui12s = ur12*ui11r ur22 = cr22 - ur12*lr21 ui22 = ci22 - ur12*li21 else ! code when diagonals of pivoted c are real ur11r = one / ur11 ui11r = zero lr21 = cr21*ur11r li21 = ci21*ur11r ur12s = ur12*ur11r ui12s = ui12*ur11r ur22 = cr22 - ur12*lr21 + ui12*li21 ui22 = -ur12*li21 - ui12*lr21 end if u22abs = abs( ur22 ) + abs( ui22 ) ! if smaller pivot < smini, use smini if( u22absone .and. u22abs=bignum*u22abs ) then scale = one / bbnd br1 = scale*br1 bi1 = scale*bi1 br2 = scale*br2 bi2 = scale*bi2 end if end if call stdlib${ii}$_${ri}$ladiv( br2, bi2, ur22, ui22, xr2, xi2 ) xr1 = ur11r*br1 - ui11r*bi1 - ur12s*xr2 + ui12s*xi2 xi1 = ui11r*br1 + ur11r*bi1 - ui12s*xr2 - ur12s*xi2 if( zswap( icmax ) ) then x( 1_${ik}$, 1_${ik}$ ) = xr2 x( 2_${ik}$, 1_${ik}$ ) = xr1 x( 1_${ik}$, 2_${ik}$ ) = xi2 x( 2_${ik}$, 2_${ik}$ ) = xi1 else x( 1_${ik}$, 1_${ik}$ ) = xr1 x( 2_${ik}$, 1_${ik}$ ) = xr2 x( 1_${ik}$, 2_${ik}$ ) = xi1 x( 2_${ik}$, 2_${ik}$ ) = xi2 end if xnorm = max( abs( xr1 )+abs( xi1 ), abs( xr2 )+abs( xi2 ) ) ! further scaling if norm(a) norm(x) > overflow if( xnorm>one .and. cmax>one ) then if( xnorm>bignum / cmax ) then temp = cmax / bignum x( 1_${ik}$, 1_${ik}$ ) = temp*x( 1_${ik}$, 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = temp*x( 2_${ik}$, 1_${ik}$ ) x( 1_${ik}$, 2_${ik}$ ) = temp*x( 1_${ik}$, 2_${ik}$ ) x( 2_${ik}$, 2_${ik}$ ) = temp*x( 2_${ik}$, 2_${ik}$ ) xnorm = temp*xnorm scale = temp*scale end if end if end if end if return end subroutine stdlib${ii}$_${ri}$laln2 #:endif #:endfor module subroutine stdlib${ii}$_strsyl( trana, tranb, isgn, m, n, a, lda, b, ldb, c,ldc, scale, info ) !! STRSYL solves the real Sylvester matrix equation: !! op(A)*X + X*op(B) = scale*C or !! op(A)*X - X*op(B) = scale*C, !! where op(A) = A or A**T, and A and B are both upper quasi- !! triangular. A is M-by-M and B is N-by-N; the right hand side C and !! the solution X are M-by-N; and scale is an output scale factor, set !! <= 1 to avoid overflow in X. !! A and B must be in Schur canonical form (as returned by SHSEQR), that !! is, block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; !! each 2-by-2 diagonal block has its diagonal elements equal and its !! off-diagonal elements of opposite sign. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trana, tranb integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn, lda, ldb, ldc, m, n real(sp), intent(out) :: scale ! Array Arguments real(sp), intent(in) :: a(lda,*), b(ldb,*) real(sp), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: notrna, notrnb integer(${ik}$) :: ierr, j, k, k1, k2, knext, l, l1, l2, lnext real(sp) :: a11, bignum, da11, db, eps, scaloc, sgn, smin, smlnum, suml, sumr, & xnorm ! Local Arrays real(sp) :: dum(1_${ik}$), vec(2_${ik}$,2_${ik}$), x(2_${ik}$,2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters notrna = stdlib_lsame( trana, 'N' ) notrnb = stdlib_lsame( tranb, 'N' ) info = 0_${ik}$ if( .not.notrna .and. .not.stdlib_lsame( trana, 'T' ) .and. .not.stdlib_lsame( trana, & 'C' ) ) then info = -1_${ik}$ else if( .not.notrnb .and. .not.stdlib_lsame( tranb, 'T' ) .and. .not.stdlib_lsame( & tranb, 'C' ) ) then info = -2_${ik}$ else if( isgn/=1_${ik}$ .and. isgn/=-1_${ik}$ ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldaknext )cycle loop_60 if( k==1_${ik}$ ) then k1 = k k2 = k else if( a( k, k-1 )/=zero ) then k1 = k - 1_${ik}$ k2 = k knext = k - 2_${ik}$ else k1 = k k2 = k knext = k - 1_${ik}$ end if end if if( l1==l2 .and. k1==k2 ) then suml = stdlib${ii}$_sdot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) scaloc = one a11 = a( k1, k1 ) + sgn*b( l1, l1 ) da11 = abs( a11 ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( vec( 1_${ik}$, 1_${ik}$ ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_sdot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_slaln2( .false., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_sdot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_sdot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_slaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_sdot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_slasy2( .false., .false., isgn, 2_${ik}$, 2_${ik}$,a( k1, k1 ), lda, b( l1, & l1 ), ldb, vec,2_${ik}$, scaloc, x, 2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_60 end do loop_70 else if( .not.notrna .and. notrnb ) then ! solve a**t *x + isgn*x*b = scale*c. ! the (k,l)th block of x is determined starting from ! upper-left corner column by column by ! a(k,k)**t*x(k,l) + isgn*x(k,l)*b(l,l) = c(k,l) - r(k,l) ! where ! k-1 l-1 ! r(k,l) = sum [a(i,k)**t*x(i,l)] +isgn*sum [x(k,j)*b(j,l)] ! i=1 j=1 ! start column loop (index = l) ! l1 (l2): column index of the first (last) row of x(k,l) lnext = 1_${ik}$ loop_130: do l = 1, n if( lone ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_slaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_slaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_slasy2( .true., .false., isgn, 2_${ik}$, 2_${ik}$, a( k1, k1 ),lda, b( l1, & l1 ), ldb, vec, 2_${ik}$, scaloc, x,2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_120 end do loop_130 else if( .not.notrna .and. .not.notrnb ) then ! solve a**t*x + isgn*x*b**t = scale*c. ! the (k,l)th block of x is determined starting from ! top-right corner column by column by ! a(k,k)**t*x(k,l) + isgn*x(k,l)*b(l,l)**t = c(k,l) - r(k,l) ! where ! k-1 n ! r(k,l) = sum [a(i,k)**t*x(i,l)] + isgn*sum [x(k,j)*b(l,j)**t]. ! i=1 j=l+1 ! start column loop (index = l) ! l1 (l2): column index of the first (last) row of x(k,l) lnext = n loop_190: do l = n, 1, -1 if( l>lnext )cycle loop_190 if( l==1_${ik}$ ) then l1 = l l2 = l else if( b( l, l-1 )/=zero ) then l1 = l - 1_${ik}$ l2 = l lnext = l - 2_${ik}$ else l1 = l l2 = l lnext = l - 1_${ik}$ end if end if ! start row loop (index = k) ! k1 (k2): row index of the first (last) row of x(k,l) knext = 1_${ik}$ loop_180: do k = 1, m if( kone ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_slaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_slaln2( .false., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l2, min(l2+1, n )& ), ldb ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_slasy2( .true., .true., isgn, 2_${ik}$, 2_${ik}$, a( k1, k1 ),lda, b( l1, l1 & ), ldb, vec, 2_${ik}$, scaloc, x,2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_180 end do loop_190 else if( notrna .and. .not.notrnb ) then ! solve a*x + isgn*x*b**t = scale*c. ! the (k,l)th block of x is determined starting from ! bottom-right corner column by column by ! a(k,k)*x(k,l) + isgn*x(k,l)*b(l,l)**t = c(k,l) - r(k,l) ! where ! m n ! r(k,l) = sum [a(k,i)*x(i,l)] + isgn*sum [x(k,j)*b(l,j)**t]. ! i=k+1 j=l+1 ! start column loop (index = l) ! l1 (l2): column index of the first (last) row of x(k,l) lnext = n loop_250: do l = n, 1, -1 if( l>lnext )cycle loop_250 if( l==1_${ik}$ ) then l1 = l l2 = l else if( b( l, l-1 )/=zero ) then l1 = l - 1_${ik}$ l2 = l lnext = l - 2_${ik}$ else l1 = l l2 = l lnext = l - 1_${ik}$ end if end if ! start row loop (index = k) ! k1 (k2): row index of the first (last) row of x(k,l) knext = m loop_240: do k = m, 1, -1 if( k>knext )cycle loop_240 if( k==1_${ik}$ ) then k1 = k k2 = k else if( a( k, k-1 )/=zero ) then k1 = k - 1_${ik}$ k2 = k knext = k - 2_${ik}$ else k1 = k k2 = k knext = k - 1_${ik}$ end if end if if( l1==l2 .and. k1==k2 ) then suml = stdlib${ii}$_sdot( m-k1, a( k1, min(k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l1, c( k1, min( l1+1, n ) ), ldc,b( l1, min( l1+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) scaloc = one a11 = a( k1, k1 ) + sgn*b( l1, l1 ) da11 = abs( a11 ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( vec( 1_${ik}$, 1_${ik}$ ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_sdot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_slaln2( .false., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_sdot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_sdot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_slaln2( .false., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_sdot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_sdot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_sdot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_slasy2( .false., .true., isgn, 2_${ik}$, 2_${ik}$, a( k1, k1 ),lda, b( l1, & l1 ), ldb, vec, 2_${ik}$, scaloc, x,2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_240 end do loop_250 end if return end subroutine stdlib${ii}$_strsyl module subroutine stdlib${ii}$_dtrsyl( trana, tranb, isgn, m, n, a, lda, b, ldb, c,ldc, scale, info ) !! DTRSYL solves the real Sylvester matrix equation: !! op(A)*X + X*op(B) = scale*C or !! op(A)*X - X*op(B) = scale*C, !! where op(A) = A or A**T, and A and B are both upper quasi- !! triangular. A is M-by-M and B is N-by-N; the right hand side C and !! the solution X are M-by-N; and scale is an output scale factor, set !! <= 1 to avoid overflow in X. !! A and B must be in Schur canonical form (as returned by DHSEQR), that !! is, block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; !! each 2-by-2 diagonal block has its diagonal elements equal and its !! off-diagonal elements of opposite sign. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trana, tranb integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn, lda, ldb, ldc, m, n real(dp), intent(out) :: scale ! Array Arguments real(dp), intent(in) :: a(lda,*), b(ldb,*) real(dp), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: notrna, notrnb integer(${ik}$) :: ierr, j, k, k1, k2, knext, l, l1, l2, lnext real(dp) :: a11, bignum, da11, db, eps, scaloc, sgn, smin, smlnum, suml, sumr, & xnorm ! Local Arrays real(dp) :: dum(1_${ik}$), vec(2_${ik}$,2_${ik}$), x(2_${ik}$,2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters notrna = stdlib_lsame( trana, 'N' ) notrnb = stdlib_lsame( tranb, 'N' ) info = 0_${ik}$ if( .not.notrna .and. .not.stdlib_lsame( trana, 'T' ) .and. .not.stdlib_lsame( trana, & 'C' ) ) then info = -1_${ik}$ else if( .not.notrnb .and. .not.stdlib_lsame( tranb, 'T' ) .and. .not.stdlib_lsame( & tranb, 'C' ) ) then info = -2_${ik}$ else if( isgn/=1_${ik}$ .and. isgn/=-1_${ik}$ ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldaknext )cycle loop_50 if( k==1_${ik}$ ) then k1 = k k2 = k else if( a( k, k-1 )/=zero ) then k1 = k - 1_${ik}$ k2 = k knext = k - 2_${ik}$ else k1 = k k2 = k knext = k - 1_${ik}$ end if end if if( l1==l2 .and. k1==k2 ) then suml = stdlib${ii}$_ddot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) scaloc = one a11 = a( k1, k1 ) + sgn*b( l1, l1 ) da11 = abs( a11 ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( vec( 1_${ik}$, 1_${ik}$ ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_ddot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_dlaln2( .false., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_ddot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_ddot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_dlaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_ddot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_dlasy2( .false., .false., isgn, 2_${ik}$, 2_${ik}$,a( k1, k1 ), lda, b( l1, & l1 ), ldb, vec,2_${ik}$, scaloc, x, 2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_50 end do loop_60 else if( .not.notrna .and. notrnb ) then ! solve a**t *x + isgn*x*b = scale*c. ! the (k,l)th block of x is determined starting from ! upper-left corner column by column by ! a(k,k)**t*x(k,l) + isgn*x(k,l)*b(l,l) = c(k,l) - r(k,l) ! where ! k-1 t l-1 ! r(k,l) = sum [a(i,k)**t*x(i,l)] +isgn*sum [x(k,j)*b(j,l)] ! i=1 j=1 ! start column loop (index = l) ! l1 (l2): column index of the first (last) row of x(k,l) lnext = 1_${ik}$ loop_120: do l = 1, n if( lone ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_dlaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_dlaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_dlasy2( .true., .false., isgn, 2_${ik}$, 2_${ik}$, a( k1, k1 ),lda, b( l1, & l1 ), ldb, vec, 2_${ik}$, scaloc, x,2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_110 end do loop_120 else if( .not.notrna .and. .not.notrnb ) then ! solve a**t*x + isgn*x*b**t = scale*c. ! the (k,l)th block of x is determined starting from ! top-right corner column by column by ! a(k,k)**t*x(k,l) + isgn*x(k,l)*b(l,l)**t = c(k,l) - r(k,l) ! where ! k-1 n ! r(k,l) = sum [a(i,k)**t*x(i,l)] + isgn*sum [x(k,j)*b(l,j)**t]. ! i=1 j=l+1 ! start column loop (index = l) ! l1 (l2): column index of the first (last) row of x(k,l) lnext = n loop_180: do l = n, 1, -1 if( l>lnext )cycle loop_180 if( l==1_${ik}$ ) then l1 = l l2 = l else if( b( l, l-1 )/=zero ) then l1 = l - 1_${ik}$ l2 = l lnext = l - 2_${ik}$ else l1 = l l2 = l lnext = l - 1_${ik}$ end if end if ! start row loop (index = k) ! k1 (k2): row index of the first (last) row of x(k,l) knext = 1_${ik}$ loop_170: do k = 1, m if( kone ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_dlaln2( .true., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_dlaln2( .false., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_dlasy2( .true., .true., isgn, 2_${ik}$, 2_${ik}$, a( k1, k1 ),lda, b( l1, l1 & ), ldb, vec, 2_${ik}$, scaloc, x,2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_170 end do loop_180 else if( notrna .and. .not.notrnb ) then ! solve a*x + isgn*x*b**t = scale*c. ! the (k,l)th block of x is determined starting from ! bottom-right corner column by column by ! a(k,k)*x(k,l) + isgn*x(k,l)*b(l,l)**t = c(k,l) - r(k,l) ! where ! m n ! r(k,l) = sum [a(k,i)*x(i,l)] + isgn*sum [x(k,j)*b(l,j)**t]. ! i=k+1 j=l+1 ! start column loop (index = l) ! l1 (l2): column index of the first (last) row of x(k,l) lnext = n loop_240: do l = n, 1, -1 if( l>lnext )cycle loop_240 if( l==1_${ik}$ ) then l1 = l l2 = l else if( b( l, l-1 )/=zero ) then l1 = l - 1_${ik}$ l2 = l lnext = l - 2_${ik}$ else l1 = l l2 = l lnext = l - 1_${ik}$ end if end if ! start row loop (index = k) ! k1 (k2): row index of the first (last) row of x(k,l) knext = m loop_230: do k = m, 1, -1 if( k>knext )cycle loop_230 if( k==1_${ik}$ ) then k1 = k k2 = k else if( a( k, k-1 )/=zero ) then k1 = k - 1_${ik}$ k2 = k knext = k - 2_${ik}$ else k1 = k k2 = k knext = k - 1_${ik}$ end if end if if( l1==l2 .and. k1==k2 ) then suml = stdlib${ii}$_ddot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l1, c( k1, min( l1+1, n ) ), ldc,b( l1, min( l1+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) scaloc = one a11 = a( k1, k1 ) + sgn*b( l1, l1 ) da11 = abs( a11 ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( vec( 1_${ik}$, 1_${ik}$ ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_ddot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_dlaln2( .false., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_ddot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_ddot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_dlaln2( .false., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_ddot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_ddot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_ddot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_dlasy2( .false., .true., isgn, 2_${ik}$, 2_${ik}$, a( k1, k1 ),lda, b( l1, & l1 ), ldb, vec, 2_${ik}$, scaloc, x,2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_230 end do loop_240 end if return end subroutine stdlib${ii}$_dtrsyl #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$trsyl( trana, tranb, isgn, m, n, a, lda, b, ldb, c,ldc, scale, info ) !! DTRSYL: solves the real Sylvester matrix equation: !! op(A)*X + X*op(B) = scale*C or !! op(A)*X - X*op(B) = scale*C, !! where op(A) = A or A**T, and A and B are both upper quasi- !! triangular. A is M-by-M and B is N-by-N; the right hand side C and !! the solution X are M-by-N; and scale is an output scale factor, set !! <= 1 to avoid overflow in X. !! A and B must be in Schur canonical form (as returned by DHSEQR), that !! is, block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; !! each 2-by-2 diagonal block has its diagonal elements equal and its !! off-diagonal elements of opposite sign. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trana, tranb integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn, lda, ldb, ldc, m, n real(${rk}$), intent(out) :: scale ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), b(ldb,*) real(${rk}$), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: notrna, notrnb integer(${ik}$) :: ierr, j, k, k1, k2, knext, l, l1, l2, lnext real(${rk}$) :: a11, bignum, da11, db, eps, scaloc, sgn, smin, smlnum, suml, sumr, & xnorm ! Local Arrays real(${rk}$) :: dum(1_${ik}$), vec(2_${ik}$,2_${ik}$), x(2_${ik}$,2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters notrna = stdlib_lsame( trana, 'N' ) notrnb = stdlib_lsame( tranb, 'N' ) info = 0_${ik}$ if( .not.notrna .and. .not.stdlib_lsame( trana, 'T' ) .and. .not.stdlib_lsame( trana, & 'C' ) ) then info = -1_${ik}$ else if( .not.notrnb .and. .not.stdlib_lsame( tranb, 'T' ) .and. .not.stdlib_lsame( & tranb, 'C' ) ) then info = -2_${ik}$ else if( isgn/=1_${ik}$ .and. isgn/=-1_${ik}$ ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldaknext )cycle loop_50 if( k==1_${ik}$ ) then k1 = k k2 = k else if( a( k, k-1 )/=zero ) then k1 = k - 1_${ik}$ k2 = k knext = k - 2_${ik}$ else k1 = k k2 = k knext = k - 1_${ik}$ end if end if if( l1==l2 .and. k1==k2 ) then suml = stdlib${ii}$_${ri}$dot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) scaloc = one a11 = a( k1, k1 ) + sgn*b( l1, l1 ) da11 = abs( a11 ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( vec( 1_${ik}$, 1_${ik}$ ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_${ri}$dot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_${ri}$laln2( .false., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_${ri}$dot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_${ri}$dot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_${ri}$laln2( .true., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_${ri}$dot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_${ri}$lasy2( .false., .false., isgn, 2_${ik}$, 2_${ik}$,a( k1, k1 ), lda, b( l1, & l1 ), ldb, vec,2_${ik}$, scaloc, x, 2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_50 end do loop_60 else if( .not.notrna .and. notrnb ) then ! solve a**t *x + isgn*x*b = scale*c. ! the (k,l)th block of x is determined starting from ! upper-left corner column by column by ! a(k,k)**t*x(k,l) + isgn*x(k,l)*b(l,l) = c(k,l) - r(k,l) ! where ! k-1 t l-1 ! r(k,l) = sum [a(i,k)**t*x(i,l)] +isgn*sum [x(k,j)*b(j,l)] ! i=1 j=1 ! start column loop (index = l) ! l1 (l2): column index of the first (last) row of x(k,l) lnext = 1_${ik}$ loop_120: do l = 1, n if( lone ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_${ri}$laln2( .true., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_${ri}$laln2( .true., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k1, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l1 ), 1_${ik}$ ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( l1-1, c( k2, 1_${ik}$ ), ldc, b( 1_${ik}$, l2 ), 1_${ik}$ ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_${ri}$lasy2( .true., .false., isgn, 2_${ik}$, 2_${ik}$, a( k1, k1 ),lda, b( l1, & l1 ), ldb, vec, 2_${ik}$, scaloc, x,2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_110 end do loop_120 else if( .not.notrna .and. .not.notrnb ) then ! solve a**t*x + isgn*x*b**t = scale*c. ! the (k,l)th block of x is determined starting from ! top-right corner column by column by ! a(k,k)**t*x(k,l) + isgn*x(k,l)*b(l,l)**t = c(k,l) - r(k,l) ! where ! k-1 n ! r(k,l) = sum [a(i,k)**t*x(i,l)] + isgn*sum [x(k,j)*b(l,j)**t]. ! i=1 j=l+1 ! start column loop (index = l) ! l1 (l2): column index of the first (last) row of x(k,l) lnext = n loop_180: do l = n, 1, -1 if( l>lnext )cycle loop_180 if( l==1_${ik}$ ) then l1 = l l2 = l else if( b( l, l-1 )/=zero ) then l1 = l - 1_${ik}$ l2 = l lnext = l - 2_${ik}$ else l1 = l l2 = l lnext = l - 1_${ik}$ end if end if ! start row loop (index = k) ! k1 (k2): row index of the first (last) row of x(k,l) knext = 1_${ik}$ loop_170: do k = 1, m if( kone ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_${ri}$laln2( .true., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_${ri}$laln2( .false., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k1 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( k1-1, a( 1_${ik}$, k2 ), 1_${ik}$, c( 1_${ik}$, l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_${ri}$lasy2( .true., .true., isgn, 2_${ik}$, 2_${ik}$, a( k1, k1 ),lda, b( l1, l1 & ), ldb, vec, 2_${ik}$, scaloc, x,2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_170 end do loop_180 else if( notrna .and. .not.notrnb ) then ! solve a*x + isgn*x*b**t = scale*c. ! the (k,l)th block of x is determined starting from ! bottom-right corner column by column by ! a(k,k)*x(k,l) + isgn*x(k,l)*b(l,l)**t = c(k,l) - r(k,l) ! where ! m n ! r(k,l) = sum [a(k,i)*x(i,l)] + isgn*sum [x(k,j)*b(l,j)**t]. ! i=k+1 j=l+1 ! start column loop (index = l) ! l1 (l2): column index of the first (last) row of x(k,l) lnext = n loop_240: do l = n, 1, -1 if( l>lnext )cycle loop_240 if( l==1_${ik}$ ) then l1 = l l2 = l else if( b( l, l-1 )/=zero ) then l1 = l - 1_${ik}$ l2 = l lnext = l - 2_${ik}$ else l1 = l l2 = l lnext = l - 1_${ik}$ end if end if ! start row loop (index = k) ! k1 (k2): row index of the first (last) row of x(k,l) knext = m loop_230: do k = m, 1, -1 if( k>knext )cycle loop_230 if( k==1_${ik}$ ) then k1 = k k2 = k else if( a( k, k-1 )/=zero ) then k1 = k - 1_${ik}$ k2 = k knext = k - 2_${ik}$ else k1 = k k2 = k knext = k - 1_${ik}$ end if end if if( l1==l2 .and. k1==k2 ) then suml = stdlib${ii}$_${ri}$dot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l1, c( k1, min( l1+1, n ) ), ldc,b( l1, min( l1+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) scaloc = one a11 = a( k1, k1 ) + sgn*b( l1, l1 ) da11 = abs( a11 ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( vec( 1_${ik}$, 1_${ik}$ ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x( 1_${ik}$, 1_${ik}$ ) = ( vec( 1_${ik}$, 1_${ik}$ )*scaloc ) / a11 if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) else if( l1==l2 .and. k1/=k2 ) then suml = stdlib${ii}$_${ri}$dot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) call stdlib${ii}$_${ri}$laln2( .false., 2_${ik}$, 1_${ik}$, smin, one, a( k1, k1 ),lda, one, one, & vec, 2_${ik}$, -sgn*b( l1, l1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1==k2 ) then suml = stdlib${ii}$_${ri}$dot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l1 )-( suml+sgn*sumr ) ) suml = stdlib${ii}$_${ri}$dot( m-k1, a( k1, min( k1+1, m ) ), lda,c( min( k1+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = sgn*( c( k1, l2 )-( suml+sgn*sumr ) ) call stdlib${ii}$_${ri}$laln2( .false., 2_${ik}$, 1_${ik}$, smin, one, b( l1, l1 ),ldb, one, one, & vec, 2_${ik}$, -sgn*a( k1, k1 ),zero, x, 2_${ik}$, scaloc, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 2_${ik}$, 1_${ik}$ ) else if( l1/=l2 .and. k1/=k2 ) then suml = stdlib${ii}$_${ri}$dot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 1_${ik}$ ) = c( k1, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( m-k2, a( k1, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k1, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 1_${ik}$, 2_${ik}$ ) = c( k1, l2 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l1 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l1, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 1_${ik}$ ) = c( k2, l1 ) - ( suml+sgn*sumr ) suml = stdlib${ii}$_${ri}$dot( m-k2, a( k2, min( k2+1, m ) ), lda,c( min( k2+1, m ), & l2 ), 1_${ik}$ ) sumr = stdlib${ii}$_${ri}$dot( n-l2, c( k2, min( l2+1, n ) ), ldc,b( l2, min( l2+1, n & ) ), ldb ) vec( 2_${ik}$, 2_${ik}$ ) = c( k2, l2 ) - ( suml+sgn*sumr ) call stdlib${ii}$_${ri}$lasy2( .false., .true., isgn, 2_${ik}$, 2_${ik}$, a( k1, k1 ),lda, b( l1, & l1 ), ldb, vec, 2_${ik}$, scaloc, x,2_${ik}$, xnorm, ierr ) if( ierr/=0_${ik}$ )info = 1_${ik}$ if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k1, l1 ) = x( 1_${ik}$, 1_${ik}$ ) c( k1, l2 ) = x( 1_${ik}$, 2_${ik}$ ) c( k2, l1 ) = x( 2_${ik}$, 1_${ik}$ ) c( k2, l2 ) = x( 2_${ik}$, 2_${ik}$ ) end if end do loop_230 end do loop_240 end if return end subroutine stdlib${ii}$_${ri}$trsyl #:endif #:endfor module subroutine stdlib${ii}$_ctrsyl( trana, tranb, isgn, m, n, a, lda, b, ldb, c,ldc, scale, info ) !! CTRSYL solves the complex Sylvester matrix equation: !! op(A)*X + X*op(B) = scale*C or !! op(A)*X - X*op(B) = scale*C, !! where op(A) = A or A**H, and A and B are both upper triangular. A is !! M-by-M and B is N-by-N; the right hand side C and the solution X are !! M-by-N; and scale is an output scale factor, set <= 1 to avoid !! overflow in X. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trana, tranb integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn, lda, ldb, ldc, m, n real(sp), intent(out) :: scale ! Array Arguments complex(sp), intent(in) :: a(lda,*), b(ldb,*) complex(sp), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: notrna, notrnb integer(${ik}$) :: j, k, l real(sp) :: bignum, da11, db, eps, scaloc, sgn, smin, smlnum complex(sp) :: a11, suml, sumr, vec, x11 ! Local Arrays real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters notrna = stdlib_lsame( trana, 'N' ) notrnb = stdlib_lsame( tranb, 'N' ) info = 0_${ik}$ if( .not.notrna .and. .not.stdlib_lsame( trana, 'C' ) ) then info = -1_${ik}$ else if( .not.notrnb .and. .not.stdlib_lsame( tranb, 'C' ) ) then info = -2_${ik}$ else if( isgn/=1_${ik}$ .and. isgn/=-1_${ik}$ ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldaone ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_cladiv( vec*cmplx( scaloc,KIND=sp), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_csscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_30 else if( .not.notrna .and. notrnb ) then ! solve a**h *x + isgn*x*b = scale*c. ! the (k,l)th block of x is determined starting from ! upper-left corner column by column by ! a**h(k,k)*x(k,l) + isgn*x(k,l)*b(l,l) = c(k,l) - r(k,l) ! where ! k-1 l-1 ! r(k,l) = sum [a**h(i,k)*x(i,l)] + isgn*sum [x(k,j)*b(j,l)] ! i=1 j=1 loop_60: do l = 1, n do k = 1, m suml = stdlib${ii}$_cdotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, c( 1_${ik}$, l ), 1_${ik}$ ) sumr = stdlib${ii}$_cdotu( l-1, c( k, 1_${ik}$ ), ldc, b( 1_${ik}$, l ), 1_${ik}$ ) vec = c( k, l ) - ( suml+sgn*sumr ) scaloc = one a11 = conjg( a( k, k ) ) + sgn*b( l, l ) da11 = abs( real( a11,KIND=sp) ) + abs( aimag( a11 ) ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( real( vec,KIND=sp) ) + abs( aimag( vec ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_cladiv( vec*cmplx( scaloc,KIND=sp), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_csscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_60 else if( .not.notrna .and. .not.notrnb ) then ! solve a**h*x + isgn*x*b**h = c. ! the (k,l)th block of x is determined starting from ! upper-right corner column by column by ! a**h(k,k)*x(k,l) + isgn*x(k,l)*b**h(l,l) = c(k,l) - r(k,l) ! where ! k-1 ! r(k,l) = sum [a**h(i,k)*x(i,l)] + ! i=1 ! n ! isgn*sum [x(k,j)*b**h(l,j)]. ! j=l+1 loop_90: do l = n, 1, -1 do k = 1, m suml = stdlib${ii}$_cdotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, c( 1_${ik}$, l ), 1_${ik}$ ) sumr = stdlib${ii}$_cdotc( n-l, c( k, min( l+1, n ) ), ldc,b( l, min( l+1, n ) ), & ldb ) vec = c( k, l ) - ( suml+sgn*conjg( sumr ) ) scaloc = one a11 = conjg( a( k, k )+sgn*b( l, l ) ) da11 = abs( real( a11,KIND=sp) ) + abs( aimag( a11 ) ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( real( vec,KIND=sp) ) + abs( aimag( vec ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_cladiv( vec*cmplx( scaloc,KIND=sp), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_csscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_90 else if( notrna .and. .not.notrnb ) then ! solve a*x + isgn*x*b**h = c. ! the (k,l)th block of x is determined starting from ! bottom-left corner column by column by ! a(k,k)*x(k,l) + isgn*x(k,l)*b**h(l,l) = c(k,l) - r(k,l) ! where ! m n ! r(k,l) = sum [a(k,i)*x(i,l)] + isgn*sum [x(k,j)*b**h(l,j)] ! i=k+1 j=l+1 loop_120: do l = n, 1, -1 do k = m, 1, -1 suml = stdlib${ii}$_cdotu( m-k, a( k, min( k+1, m ) ), lda,c( min( k+1, m ), l ), 1_${ik}$ & ) sumr = stdlib${ii}$_cdotc( n-l, c( k, min( l+1, n ) ), ldc,b( l, min( l+1, n ) ), & ldb ) vec = c( k, l ) - ( suml+sgn*conjg( sumr ) ) scaloc = one a11 = a( k, k ) + sgn*conjg( b( l, l ) ) da11 = abs( real( a11,KIND=sp) ) + abs( aimag( a11 ) ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( real( vec,KIND=sp) ) + abs( aimag( vec ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_cladiv( vec*cmplx( scaloc,KIND=sp), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_csscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_120 end if return end subroutine stdlib${ii}$_ctrsyl module subroutine stdlib${ii}$_ztrsyl( trana, tranb, isgn, m, n, a, lda, b, ldb, c,ldc, scale, info ) !! ZTRSYL solves the complex Sylvester matrix equation: !! op(A)*X + X*op(B) = scale*C or !! op(A)*X - X*op(B) = scale*C, !! where op(A) = A or A**H, and A and B are both upper triangular. A is !! M-by-M and B is N-by-N; the right hand side C and the solution X are !! M-by-N; and scale is an output scale factor, set <= 1 to avoid !! overflow in X. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trana, tranb integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn, lda, ldb, ldc, m, n real(dp), intent(out) :: scale ! Array Arguments complex(dp), intent(in) :: a(lda,*), b(ldb,*) complex(dp), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: notrna, notrnb integer(${ik}$) :: j, k, l real(dp) :: bignum, da11, db, eps, scaloc, sgn, smin, smlnum complex(dp) :: a11, suml, sumr, vec, x11 ! Local Arrays real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters notrna = stdlib_lsame( trana, 'N' ) notrnb = stdlib_lsame( tranb, 'N' ) info = 0_${ik}$ if( .not.notrna .and. .not.stdlib_lsame( trana, 'C' ) ) then info = -1_${ik}$ else if( .not.notrnb .and. .not.stdlib_lsame( tranb, 'C' ) ) then info = -2_${ik}$ else if( isgn/=1_${ik}$ .and. isgn/=-1_${ik}$ ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldaone ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_zladiv( vec*cmplx( scaloc,KIND=dp), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_zdscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_30 else if( .not.notrna .and. notrnb ) then ! solve a**h *x + isgn*x*b = scale*c. ! the (k,l)th block of x is determined starting from ! upper-left corner column by column by ! a**h(k,k)*x(k,l) + isgn*x(k,l)*b(l,l) = c(k,l) - r(k,l) ! where ! k-1 l-1 ! r(k,l) = sum [a**h(i,k)*x(i,l)] + isgn*sum [x(k,j)*b(j,l)] ! i=1 j=1 loop_60: do l = 1, n do k = 1, m suml = stdlib${ii}$_zdotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, c( 1_${ik}$, l ), 1_${ik}$ ) sumr = stdlib${ii}$_zdotu( l-1, c( k, 1_${ik}$ ), ldc, b( 1_${ik}$, l ), 1_${ik}$ ) vec = c( k, l ) - ( suml+sgn*sumr ) scaloc = one a11 = conjg( a( k, k ) ) + sgn*b( l, l ) da11 = abs( real( a11,KIND=dp) ) + abs( aimag( a11 ) ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( real( vec,KIND=dp) ) + abs( aimag( vec ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_zladiv( vec*cmplx( scaloc,KIND=dp), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_zdscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_60 else if( .not.notrna .and. .not.notrnb ) then ! solve a**h*x + isgn*x*b**h = c. ! the (k,l)th block of x is determined starting from ! upper-right corner column by column by ! a**h(k,k)*x(k,l) + isgn*x(k,l)*b**h(l,l) = c(k,l) - r(k,l) ! where ! k-1 ! r(k,l) = sum [a**h(i,k)*x(i,l)] + ! i=1 ! n ! isgn*sum [x(k,j)*b**h(l,j)]. ! j=l+1 loop_90: do l = n, 1, -1 do k = 1, m suml = stdlib${ii}$_zdotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, c( 1_${ik}$, l ), 1_${ik}$ ) sumr = stdlib${ii}$_zdotc( n-l, c( k, min( l+1, n ) ), ldc,b( l, min( l+1, n ) ), & ldb ) vec = c( k, l ) - ( suml+sgn*conjg( sumr ) ) scaloc = one a11 = conjg( a( k, k )+sgn*b( l, l ) ) da11 = abs( real( a11,KIND=dp) ) + abs( aimag( a11 ) ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( real( vec,KIND=dp) ) + abs( aimag( vec ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_zladiv( vec*cmplx( scaloc,KIND=dp), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_zdscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_90 else if( notrna .and. .not.notrnb ) then ! solve a*x + isgn*x*b**h = c. ! the (k,l)th block of x is determined starting from ! bottom-left corner column by column by ! a(k,k)*x(k,l) + isgn*x(k,l)*b**h(l,l) = c(k,l) - r(k,l) ! where ! m n ! r(k,l) = sum [a(k,i)*x(i,l)] + isgn*sum [x(k,j)*b**h(l,j)] ! i=k+1 j=l+1 loop_120: do l = n, 1, -1 do k = m, 1, -1 suml = stdlib${ii}$_zdotu( m-k, a( k, min( k+1, m ) ), lda,c( min( k+1, m ), l ), 1_${ik}$ & ) sumr = stdlib${ii}$_zdotc( n-l, c( k, min( l+1, n ) ), ldc,b( l, min( l+1, n ) ), & ldb ) vec = c( k, l ) - ( suml+sgn*conjg( sumr ) ) scaloc = one a11 = a( k, k ) + sgn*conjg( b( l, l ) ) da11 = abs( real( a11,KIND=dp) ) + abs( aimag( a11 ) ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( real( vec,KIND=dp) ) + abs( aimag( vec ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_zladiv( vec*cmplx( scaloc,KIND=dp), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_zdscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_120 end if return end subroutine stdlib${ii}$_ztrsyl #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$trsyl( trana, tranb, isgn, m, n, a, lda, b, ldb, c,ldc, scale, info ) !! ZTRSYL: solves the complex Sylvester matrix equation: !! op(A)*X + X*op(B) = scale*C or !! op(A)*X - X*op(B) = scale*C, !! where op(A) = A or A**H, and A and B are both upper triangular. A is !! M-by-M and B is N-by-N; the right hand side C and the solution X are !! M-by-N; and scale is an output scale factor, set <= 1 to avoid !! overflow in X. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trana, tranb integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn, lda, ldb, ldc, m, n real(${ck}$), intent(out) :: scale ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(inout) :: c(ldc,*) ! ===================================================================== ! Local Scalars logical(lk) :: notrna, notrnb integer(${ik}$) :: j, k, l real(${ck}$) :: bignum, da11, db, eps, scaloc, sgn, smin, smlnum complex(${ck}$) :: a11, suml, sumr, vec, x11 ! Local Arrays real(${ck}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters notrna = stdlib_lsame( trana, 'N' ) notrnb = stdlib_lsame( tranb, 'N' ) info = 0_${ik}$ if( .not.notrna .and. .not.stdlib_lsame( trana, 'C' ) ) then info = -1_${ik}$ else if( .not.notrnb .and. .not.stdlib_lsame( tranb, 'C' ) ) then info = -2_${ik}$ else if( isgn/=1_${ik}$ .and. isgn/=-1_${ik}$ ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( ldaone ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_${ci}$ladiv( vec*cmplx( scaloc,KIND=${ck}$), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ci}$dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_30 else if( .not.notrna .and. notrnb ) then ! solve a**h *x + isgn*x*b = scale*c. ! the (k,l)th block of x is determined starting from ! upper-left corner column by column by ! a**h(k,k)*x(k,l) + isgn*x(k,l)*b(l,l) = c(k,l) - r(k,l) ! where ! k-1 l-1 ! r(k,l) = sum [a**h(i,k)*x(i,l)] + isgn*sum [x(k,j)*b(j,l)] ! i=1 j=1 loop_60: do l = 1, n do k = 1, m suml = stdlib${ii}$_${ci}$dotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, c( 1_${ik}$, l ), 1_${ik}$ ) sumr = stdlib${ii}$_${ci}$dotu( l-1, c( k, 1_${ik}$ ), ldc, b( 1_${ik}$, l ), 1_${ik}$ ) vec = c( k, l ) - ( suml+sgn*sumr ) scaloc = one a11 = conjg( a( k, k ) ) + sgn*b( l, l ) da11 = abs( real( a11,KIND=${ck}$) ) + abs( aimag( a11 ) ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( real( vec,KIND=${ck}$) ) + abs( aimag( vec ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_${ci}$ladiv( vec*cmplx( scaloc,KIND=${ck}$), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ci}$dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_60 else if( .not.notrna .and. .not.notrnb ) then ! solve a**h*x + isgn*x*b**h = c. ! the (k,l)th block of x is determined starting from ! upper-right corner column by column by ! a**h(k,k)*x(k,l) + isgn*x(k,l)*b**h(l,l) = c(k,l) - r(k,l) ! where ! k-1 ! r(k,l) = sum [a**h(i,k)*x(i,l)] + ! i=1 ! n ! isgn*sum [x(k,j)*b**h(l,j)]. ! j=l+1 loop_90: do l = n, 1, -1 do k = 1, m suml = stdlib${ii}$_${ci}$dotc( k-1, a( 1_${ik}$, k ), 1_${ik}$, c( 1_${ik}$, l ), 1_${ik}$ ) sumr = stdlib${ii}$_${ci}$dotc( n-l, c( k, min( l+1, n ) ), ldc,b( l, min( l+1, n ) ), & ldb ) vec = c( k, l ) - ( suml+sgn*conjg( sumr ) ) scaloc = one a11 = conjg( a( k, k )+sgn*b( l, l ) ) da11 = abs( real( a11,KIND=${ck}$) ) + abs( aimag( a11 ) ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( real( vec,KIND=${ck}$) ) + abs( aimag( vec ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_${ci}$ladiv( vec*cmplx( scaloc,KIND=${ck}$), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ci}$dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_90 else if( notrna .and. .not.notrnb ) then ! solve a*x + isgn*x*b**h = c. ! the (k,l)th block of x is determined starting from ! bottom-left corner column by column by ! a(k,k)*x(k,l) + isgn*x(k,l)*b**h(l,l) = c(k,l) - r(k,l) ! where ! m n ! r(k,l) = sum [a(k,i)*x(i,l)] + isgn*sum [x(k,j)*b**h(l,j)] ! i=k+1 j=l+1 loop_120: do l = n, 1, -1 do k = m, 1, -1 suml = stdlib${ii}$_${ci}$dotu( m-k, a( k, min( k+1, m ) ), lda,c( min( k+1, m ), l ), 1_${ik}$ & ) sumr = stdlib${ii}$_${ci}$dotc( n-l, c( k, min( l+1, n ) ), ldc,b( l, min( l+1, n ) ), & ldb ) vec = c( k, l ) - ( suml+sgn*conjg( sumr ) ) scaloc = one a11 = a( k, k ) + sgn*conjg( b( l, l ) ) da11 = abs( real( a11,KIND=${ck}$) ) + abs( aimag( a11 ) ) if( da11<=smin ) then a11 = smin da11 = smin info = 1_${ik}$ end if db = abs( real( vec,KIND=${ck}$) ) + abs( aimag( vec ) ) if( da11one ) then if( db>bignum*da11 )scaloc = one / db end if x11 = stdlib${ii}$_${ci}$ladiv( vec*cmplx( scaloc,KIND=${ck}$), a11 ) if( scaloc/=one ) then do j = 1, n call stdlib${ii}$_${ci}$dscal( m, scaloc, c( 1_${ik}$, j ), 1_${ik}$ ) end do scale = scale*scaloc end if c( k, l ) = x11 end do end do loop_120 end if return end subroutine stdlib${ii}$_${ci}$trsyl #:endif #:endfor pure module subroutine stdlib${ii}$_slasy2( ltranl, ltranr, isgn, n1, n2, tl, ldtl, tr,ldtr, b, ldb, & !! SLASY2 solves for the N1 by N2 matrix X, 1 <= N1,N2 <= 2, in !! op(TL)*X + ISGN*X*op(TR) = SCALE*B, !! where TL is N1 by N1, TR is N2 by N2, B is N1 by N2, and ISGN = 1 or !! -1. op(T) = T or T**T, where T**T denotes the transpose of T. scale, x, ldx, xnorm, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: ltranl, ltranr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn, ldb, ldtl, ldtr, ldx, n1, n2 real(sp), intent(out) :: scale, xnorm ! Array Arguments real(sp), intent(in) :: b(ldb,*), tl(ldtl,*), tr(ldtr,*) real(sp), intent(out) :: x(ldx,*) ! ===================================================================== ! Local Scalars logical(lk) :: bswap, xswap integer(${ik}$) :: i, ip, ipiv, ipsv, j, jp, jpsv, k real(sp) :: bet, eps, gam, l21, sgn, smin, smlnum, tau1, temp, u11, u12, u22, & xmax ! Local Arrays logical(lk) :: bswpiv(4_${ik}$), xswpiv(4_${ik}$) integer(${ik}$) :: jpiv(4_${ik}$), locl21(4_${ik}$), locu12(4_${ik}$), locu22(4_${ik}$) real(sp) :: btmp(4_${ik}$), t16(4_${ik}$,4_${ik}$), tmp(4_${ik}$), x2(2_${ik}$) ! Intrinsic Functions ! Data Statements locu12 = [3_${ik}$,4_${ik}$,1_${ik}$,2_${ik}$] locl21 = [2_${ik}$,1_${ik}$,4_${ik}$,3_${ik}$] locu22 = [4_${ik}$,3_${ik}$,2_${ik}$,1_${ik}$] xswpiv = [.false.,.false.,.true.,.true.] bswpiv = [.false.,.true.,.false.,.true.] ! Executable Statements ! do not check the input parameters for errors info = 0_${ik}$ ! quick return if possible if( n1==0 .or. n2==0 )return ! set constants to control overflow eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) / eps sgn = isgn k = n1 + n1 + n2 - 2_${ik}$ go to ( 10, 20, 30, 50 )k ! 1 by 1: tl11*x + sgn*x*tr11 = b11 10 continue tau1 = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) bet = abs( tau1 ) if( bet<=smlnum ) then tau1 = smlnum bet = smlnum info = 1_${ik}$ end if scale = one gam = abs( b( 1_${ik}$, 1_${ik}$ ) ) if( smlnum*gam>bet )scale = one / gam x( 1_${ik}$, 1_${ik}$ ) = ( b( 1_${ik}$, 1_${ik}$ )*scale ) / tau1 xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) return ! 1 by 2: ! tl11*[x11 x12] + isgn*[x11 x12]*op[tr11 tr12] = [b11 b12] ! [tr21 tr22] 20 continue smin = max( eps*max( abs( tl( 1_${ik}$, 1_${ik}$ ) ), abs( tr( 1_${ik}$, 1_${ik}$ ) ),abs( tr( 1_${ik}$, 2_${ik}$ ) ), abs( tr( & 2_${ik}$, 1_${ik}$ ) ), abs( tr( 2_${ik}$, 2_${ik}$ ) ) ),smlnum ) tmp( 1_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) tmp( 4_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 2_${ik}$, 2_${ik}$ ) if( ltranr ) then tmp( 2_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) tmp( 3_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) else tmp( 2_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) tmp( 3_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) end if btmp( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) btmp( 2_${ik}$ ) = b( 1_${ik}$, 2_${ik}$ ) go to 40 ! 2 by 1: ! op[tl11 tl12]*[x11] + isgn* [x11]*tr11 = [b11] ! [tl21 tl22] [x21] [x21] [b21] 30 continue smin = max( eps*max( abs( tr( 1_${ik}$, 1_${ik}$ ) ), abs( tl( 1_${ik}$, 1_${ik}$ ) ),abs( tl( 1_${ik}$, 2_${ik}$ ) ), abs( tl( & 2_${ik}$, 1_${ik}$ ) ), abs( tl( 2_${ik}$, 2_${ik}$ ) ) ),smlnum ) tmp( 1_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) tmp( 4_${ik}$ ) = tl( 2_${ik}$, 2_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) if( ltranl ) then tmp( 2_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) tmp( 3_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) else tmp( 2_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) tmp( 3_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) end if btmp( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) btmp( 2_${ik}$ ) = b( 2_${ik}$, 1_${ik}$ ) 40 continue ! solve 2 by 2 system using complete pivoting. ! set pivots less than smin to smin. ipiv = stdlib${ii}$_isamax( 4_${ik}$, tmp, 1_${ik}$ ) u11 = tmp( ipiv ) if( abs( u11 )<=smin ) then info = 1_${ik}$ u11 = smin end if u12 = tmp( locu12( ipiv ) ) l21 = tmp( locl21( ipiv ) ) / u11 u22 = tmp( locu22( ipiv ) ) - u12*l21 xswap = xswpiv( ipiv ) bswap = bswpiv( ipiv ) if( abs( u22 )<=smin ) then info = 1_${ik}$ u22 = smin end if if( bswap ) then temp = btmp( 2_${ik}$ ) btmp( 2_${ik}$ ) = btmp( 1_${ik}$ ) - l21*temp btmp( 1_${ik}$ ) = temp else btmp( 2_${ik}$ ) = btmp( 2_${ik}$ ) - l21*btmp( 1_${ik}$ ) end if scale = one if( ( two*smlnum )*abs( btmp( 2_${ik}$ ) )>abs( u22 ) .or.( two*smlnum )*abs( btmp( 1_${ik}$ ) )>abs(& u11 ) ) then scale = half / max( abs( btmp( 1_${ik}$ ) ), abs( btmp( 2_${ik}$ ) ) ) btmp( 1_${ik}$ ) = btmp( 1_${ik}$ )*scale btmp( 2_${ik}$ ) = btmp( 2_${ik}$ )*scale end if x2( 2_${ik}$ ) = btmp( 2_${ik}$ ) / u22 x2( 1_${ik}$ ) = btmp( 1_${ik}$ ) / u11 - ( u12 / u11 )*x2( 2_${ik}$ ) if( xswap ) then temp = x2( 2_${ik}$ ) x2( 2_${ik}$ ) = x2( 1_${ik}$ ) x2( 1_${ik}$ ) = temp end if x( 1_${ik}$, 1_${ik}$ ) = x2( 1_${ik}$ ) if( n1==1_${ik}$ ) then x( 1_${ik}$, 2_${ik}$ ) = x2( 2_${ik}$ ) xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) + abs( x( 1_${ik}$, 2_${ik}$ ) ) else x( 2_${ik}$, 1_${ik}$ ) = x2( 2_${ik}$ ) xnorm = max( abs( x( 1_${ik}$, 1_${ik}$ ) ), abs( x( 2_${ik}$, 1_${ik}$ ) ) ) end if return ! 2 by 2: ! op[tl11 tl12]*[x11 x12] +isgn* [x11 x12]*op[tr11 tr12] = [b11 b12] ! [tl21 tl22] [x21 x22] [x21 x22] [tr21 tr22] [b21 b22] ! solve equivalent 4 by 4 system using complete pivoting. ! set pivots less than smin to smin. 50 continue smin = max( abs( tr( 1_${ik}$, 1_${ik}$ ) ), abs( tr( 1_${ik}$, 2_${ik}$ ) ),abs( tr( 2_${ik}$, 1_${ik}$ ) ), abs( tr( 2_${ik}$, 2_${ik}$ ) ) ) smin = max( smin, abs( tl( 1_${ik}$, 1_${ik}$ ) ), abs( tl( 1_${ik}$, 2_${ik}$ ) ),abs( tl( 2_${ik}$, 1_${ik}$ ) ), abs( tl( 2_${ik}$, & 2_${ik}$ ) ) ) smin = max( eps*smin, smlnum ) btmp( 1_${ik}$ ) = zero call stdlib${ii}$_scopy( 16_${ik}$, btmp, 0_${ik}$, t16, 1_${ik}$ ) t16( 1_${ik}$, 1_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) t16( 2_${ik}$, 2_${ik}$ ) = tl( 2_${ik}$, 2_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) t16( 3_${ik}$, 3_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 2_${ik}$, 2_${ik}$ ) t16( 4_${ik}$, 4_${ik}$ ) = tl( 2_${ik}$, 2_${ik}$ ) + sgn*tr( 2_${ik}$, 2_${ik}$ ) if( ltranl ) then t16( 1_${ik}$, 2_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) t16( 2_${ik}$, 1_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) t16( 3_${ik}$, 4_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) t16( 4_${ik}$, 3_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) else t16( 1_${ik}$, 2_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) t16( 2_${ik}$, 1_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) t16( 3_${ik}$, 4_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) t16( 4_${ik}$, 3_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) end if if( ltranr ) then t16( 1_${ik}$, 3_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) t16( 2_${ik}$, 4_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) t16( 3_${ik}$, 1_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) t16( 4_${ik}$, 2_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) else t16( 1_${ik}$, 3_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) t16( 2_${ik}$, 4_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) t16( 3_${ik}$, 1_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) t16( 4_${ik}$, 2_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) end if btmp( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) btmp( 2_${ik}$ ) = b( 2_${ik}$, 1_${ik}$ ) btmp( 3_${ik}$ ) = b( 1_${ik}$, 2_${ik}$ ) btmp( 4_${ik}$ ) = b( 2_${ik}$, 2_${ik}$ ) ! perform elimination loop_100: do i = 1, 3 xmax = zero do ip = i, 4 do jp = i, 4 if( abs( t16( ip, jp ) )>=xmax ) then xmax = abs( t16( ip, jp ) ) ipsv = ip jpsv = jp end if end do end do if( ipsv/=i ) then call stdlib${ii}$_sswap( 4_${ik}$, t16( ipsv, 1_${ik}$ ), 4_${ik}$, t16( i, 1_${ik}$ ), 4_${ik}$ ) temp = btmp( i ) btmp( i ) = btmp( ipsv ) btmp( ipsv ) = temp end if if( jpsv/=i )call stdlib${ii}$_sswap( 4_${ik}$, t16( 1_${ik}$, jpsv ), 1_${ik}$, t16( 1_${ik}$, i ), 1_${ik}$ ) jpiv( i ) = jpsv if( abs( t16( i, i ) )abs( t16( 1_${ik}$, 1_${ik}$ ) ) .or.( eight*smlnum )*abs( & btmp( 2_${ik}$ ) )>abs( t16( 2_${ik}$, 2_${ik}$ ) ) .or.( eight*smlnum )*abs( btmp( 3_${ik}$ ) )>abs( t16( 3_${ik}$, 3_${ik}$ ) )& .or.( eight*smlnum )*abs( btmp( 4_${ik}$ ) )>abs( t16( 4_${ik}$, 4_${ik}$ ) ) ) then scale = ( one / eight ) / max( abs( btmp( 1_${ik}$ ) ),abs( btmp( 2_${ik}$ ) ), abs( btmp( 3_${ik}$ ) ), & abs( btmp( 4_${ik}$ ) ) ) btmp( 1_${ik}$ ) = btmp( 1_${ik}$ )*scale btmp( 2_${ik}$ ) = btmp( 2_${ik}$ )*scale btmp( 3_${ik}$ ) = btmp( 3_${ik}$ )*scale btmp( 4_${ik}$ ) = btmp( 4_${ik}$ )*scale end if do i = 1, 4 k = 5_${ik}$ - i temp = one / t16( k, k ) tmp( k ) = btmp( k )*temp do j = k + 1, 4 tmp( k ) = tmp( k ) - ( temp*t16( k, j ) )*tmp( j ) end do end do do i = 1, 3 if( jpiv( 4_${ik}$-i )/=4_${ik}$-i ) then temp = tmp( 4_${ik}$-i ) tmp( 4_${ik}$-i ) = tmp( jpiv( 4_${ik}$-i ) ) tmp( jpiv( 4_${ik}$-i ) ) = temp end if end do x( 1_${ik}$, 1_${ik}$ ) = tmp( 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = tmp( 2_${ik}$ ) x( 1_${ik}$, 2_${ik}$ ) = tmp( 3_${ik}$ ) x( 2_${ik}$, 2_${ik}$ ) = tmp( 4_${ik}$ ) xnorm = max( abs( tmp( 1_${ik}$ ) )+abs( tmp( 3_${ik}$ ) ),abs( tmp( 2_${ik}$ ) )+abs( tmp( 4_${ik}$ ) ) ) return end subroutine stdlib${ii}$_slasy2 pure module subroutine stdlib${ii}$_dlasy2( ltranl, ltranr, isgn, n1, n2, tl, ldtl, tr,ldtr, b, ldb, & !! DLASY2 solves for the N1 by N2 matrix X, 1 <= N1,N2 <= 2, in !! op(TL)*X + ISGN*X*op(TR) = SCALE*B, !! where TL is N1 by N1, TR is N2 by N2, B is N1 by N2, and ISGN = 1 or !! -1. op(T) = T or T**T, where T**T denotes the transpose of T. scale, x, ldx, xnorm, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: ltranl, ltranr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn, ldb, ldtl, ldtr, ldx, n1, n2 real(dp), intent(out) :: scale, xnorm ! Array Arguments real(dp), intent(in) :: b(ldb,*), tl(ldtl,*), tr(ldtr,*) real(dp), intent(out) :: x(ldx,*) ! ===================================================================== ! Local Scalars logical(lk) :: bswap, xswap integer(${ik}$) :: i, ip, ipiv, ipsv, j, jp, jpsv, k real(dp) :: bet, eps, gam, l21, sgn, smin, smlnum, tau1, temp, u11, u12, u22, & xmax ! Local Arrays logical(lk) :: bswpiv(4_${ik}$), xswpiv(4_${ik}$) integer(${ik}$) :: jpiv(4_${ik}$), locl21(4_${ik}$), locu12(4_${ik}$), locu22(4_${ik}$) real(dp) :: btmp(4_${ik}$), t16(4_${ik}$,4_${ik}$), tmp(4_${ik}$), x2(2_${ik}$) ! Intrinsic Functions ! Data Statements locu12 = [3_${ik}$,4_${ik}$,1_${ik}$,2_${ik}$] locl21 = [2_${ik}$,1_${ik}$,4_${ik}$,3_${ik}$] locu22 = [4_${ik}$,3_${ik}$,2_${ik}$,1_${ik}$] xswpiv = [.false.,.false.,.true.,.true.] bswpiv = [.false.,.true.,.false.,.true.] ! Executable Statements ! do not check the input parameters for errors info = 0_${ik}$ ! quick return if possible if( n1==0 .or. n2==0 )return ! set constants to control overflow eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) / eps sgn = isgn k = n1 + n1 + n2 - 2_${ik}$ go to ( 10, 20, 30, 50 )k ! 1 by 1: tl11*x + sgn*x*tr11 = b11 10 continue tau1 = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) bet = abs( tau1 ) if( bet<=smlnum ) then tau1 = smlnum bet = smlnum info = 1_${ik}$ end if scale = one gam = abs( b( 1_${ik}$, 1_${ik}$ ) ) if( smlnum*gam>bet )scale = one / gam x( 1_${ik}$, 1_${ik}$ ) = ( b( 1_${ik}$, 1_${ik}$ )*scale ) / tau1 xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) return ! 1 by 2: ! tl11*[x11 x12] + isgn*[x11 x12]*op[tr11 tr12] = [b11 b12] ! [tr21 tr22] 20 continue smin = max( eps*max( abs( tl( 1_${ik}$, 1_${ik}$ ) ), abs( tr( 1_${ik}$, 1_${ik}$ ) ),abs( tr( 1_${ik}$, 2_${ik}$ ) ), abs( tr( & 2_${ik}$, 1_${ik}$ ) ), abs( tr( 2_${ik}$, 2_${ik}$ ) ) ),smlnum ) tmp( 1_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) tmp( 4_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 2_${ik}$, 2_${ik}$ ) if( ltranr ) then tmp( 2_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) tmp( 3_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) else tmp( 2_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) tmp( 3_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) end if btmp( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) btmp( 2_${ik}$ ) = b( 1_${ik}$, 2_${ik}$ ) go to 40 ! 2 by 1: ! op[tl11 tl12]*[x11] + isgn* [x11]*tr11 = [b11] ! [tl21 tl22] [x21] [x21] [b21] 30 continue smin = max( eps*max( abs( tr( 1_${ik}$, 1_${ik}$ ) ), abs( tl( 1_${ik}$, 1_${ik}$ ) ),abs( tl( 1_${ik}$, 2_${ik}$ ) ), abs( tl( & 2_${ik}$, 1_${ik}$ ) ), abs( tl( 2_${ik}$, 2_${ik}$ ) ) ),smlnum ) tmp( 1_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) tmp( 4_${ik}$ ) = tl( 2_${ik}$, 2_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) if( ltranl ) then tmp( 2_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) tmp( 3_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) else tmp( 2_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) tmp( 3_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) end if btmp( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) btmp( 2_${ik}$ ) = b( 2_${ik}$, 1_${ik}$ ) 40 continue ! solve 2 by 2 system using complete pivoting. ! set pivots less than smin to smin. ipiv = stdlib${ii}$_idamax( 4_${ik}$, tmp, 1_${ik}$ ) u11 = tmp( ipiv ) if( abs( u11 )<=smin ) then info = 1_${ik}$ u11 = smin end if u12 = tmp( locu12( ipiv ) ) l21 = tmp( locl21( ipiv ) ) / u11 u22 = tmp( locu22( ipiv ) ) - u12*l21 xswap = xswpiv( ipiv ) bswap = bswpiv( ipiv ) if( abs( u22 )<=smin ) then info = 1_${ik}$ u22 = smin end if if( bswap ) then temp = btmp( 2_${ik}$ ) btmp( 2_${ik}$ ) = btmp( 1_${ik}$ ) - l21*temp btmp( 1_${ik}$ ) = temp else btmp( 2_${ik}$ ) = btmp( 2_${ik}$ ) - l21*btmp( 1_${ik}$ ) end if scale = one if( ( two*smlnum )*abs( btmp( 2_${ik}$ ) )>abs( u22 ) .or.( two*smlnum )*abs( btmp( 1_${ik}$ ) )>abs(& u11 ) ) then scale = half / max( abs( btmp( 1_${ik}$ ) ), abs( btmp( 2_${ik}$ ) ) ) btmp( 1_${ik}$ ) = btmp( 1_${ik}$ )*scale btmp( 2_${ik}$ ) = btmp( 2_${ik}$ )*scale end if x2( 2_${ik}$ ) = btmp( 2_${ik}$ ) / u22 x2( 1_${ik}$ ) = btmp( 1_${ik}$ ) / u11 - ( u12 / u11 )*x2( 2_${ik}$ ) if( xswap ) then temp = x2( 2_${ik}$ ) x2( 2_${ik}$ ) = x2( 1_${ik}$ ) x2( 1_${ik}$ ) = temp end if x( 1_${ik}$, 1_${ik}$ ) = x2( 1_${ik}$ ) if( n1==1_${ik}$ ) then x( 1_${ik}$, 2_${ik}$ ) = x2( 2_${ik}$ ) xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) + abs( x( 1_${ik}$, 2_${ik}$ ) ) else x( 2_${ik}$, 1_${ik}$ ) = x2( 2_${ik}$ ) xnorm = max( abs( x( 1_${ik}$, 1_${ik}$ ) ), abs( x( 2_${ik}$, 1_${ik}$ ) ) ) end if return ! 2 by 2: ! op[tl11 tl12]*[x11 x12] +isgn* [x11 x12]*op[tr11 tr12] = [b11 b12] ! [tl21 tl22] [x21 x22] [x21 x22] [tr21 tr22] [b21 b22] ! solve equivalent 4 by 4 system using complete pivoting. ! set pivots less than smin to smin. 50 continue smin = max( abs( tr( 1_${ik}$, 1_${ik}$ ) ), abs( tr( 1_${ik}$, 2_${ik}$ ) ),abs( tr( 2_${ik}$, 1_${ik}$ ) ), abs( tr( 2_${ik}$, 2_${ik}$ ) ) ) smin = max( smin, abs( tl( 1_${ik}$, 1_${ik}$ ) ), abs( tl( 1_${ik}$, 2_${ik}$ ) ),abs( tl( 2_${ik}$, 1_${ik}$ ) ), abs( tl( 2_${ik}$, & 2_${ik}$ ) ) ) smin = max( eps*smin, smlnum ) btmp( 1_${ik}$ ) = zero call stdlib${ii}$_dcopy( 16_${ik}$, btmp, 0_${ik}$, t16, 1_${ik}$ ) t16( 1_${ik}$, 1_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) t16( 2_${ik}$, 2_${ik}$ ) = tl( 2_${ik}$, 2_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) t16( 3_${ik}$, 3_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 2_${ik}$, 2_${ik}$ ) t16( 4_${ik}$, 4_${ik}$ ) = tl( 2_${ik}$, 2_${ik}$ ) + sgn*tr( 2_${ik}$, 2_${ik}$ ) if( ltranl ) then t16( 1_${ik}$, 2_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) t16( 2_${ik}$, 1_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) t16( 3_${ik}$, 4_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) t16( 4_${ik}$, 3_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) else t16( 1_${ik}$, 2_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) t16( 2_${ik}$, 1_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) t16( 3_${ik}$, 4_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) t16( 4_${ik}$, 3_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) end if if( ltranr ) then t16( 1_${ik}$, 3_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) t16( 2_${ik}$, 4_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) t16( 3_${ik}$, 1_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) t16( 4_${ik}$, 2_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) else t16( 1_${ik}$, 3_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) t16( 2_${ik}$, 4_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) t16( 3_${ik}$, 1_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) t16( 4_${ik}$, 2_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) end if btmp( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) btmp( 2_${ik}$ ) = b( 2_${ik}$, 1_${ik}$ ) btmp( 3_${ik}$ ) = b( 1_${ik}$, 2_${ik}$ ) btmp( 4_${ik}$ ) = b( 2_${ik}$, 2_${ik}$ ) ! perform elimination loop_100: do i = 1, 3 xmax = zero do ip = i, 4 do jp = i, 4 if( abs( t16( ip, jp ) )>=xmax ) then xmax = abs( t16( ip, jp ) ) ipsv = ip jpsv = jp end if end do end do if( ipsv/=i ) then call stdlib${ii}$_dswap( 4_${ik}$, t16( ipsv, 1_${ik}$ ), 4_${ik}$, t16( i, 1_${ik}$ ), 4_${ik}$ ) temp = btmp( i ) btmp( i ) = btmp( ipsv ) btmp( ipsv ) = temp end if if( jpsv/=i )call stdlib${ii}$_dswap( 4_${ik}$, t16( 1_${ik}$, jpsv ), 1_${ik}$, t16( 1_${ik}$, i ), 1_${ik}$ ) jpiv( i ) = jpsv if( abs( t16( i, i ) )abs( t16( 1_${ik}$, 1_${ik}$ ) ) .or.( eight*smlnum )*abs( & btmp( 2_${ik}$ ) )>abs( t16( 2_${ik}$, 2_${ik}$ ) ) .or.( eight*smlnum )*abs( btmp( 3_${ik}$ ) )>abs( t16( 3_${ik}$, 3_${ik}$ ) )& .or.( eight*smlnum )*abs( btmp( 4_${ik}$ ) )>abs( t16( 4_${ik}$, 4_${ik}$ ) ) ) then scale = ( one / eight ) / max( abs( btmp( 1_${ik}$ ) ),abs( btmp( 2_${ik}$ ) ), abs( btmp( 3_${ik}$ ) ), & abs( btmp( 4_${ik}$ ) ) ) btmp( 1_${ik}$ ) = btmp( 1_${ik}$ )*scale btmp( 2_${ik}$ ) = btmp( 2_${ik}$ )*scale btmp( 3_${ik}$ ) = btmp( 3_${ik}$ )*scale btmp( 4_${ik}$ ) = btmp( 4_${ik}$ )*scale end if do i = 1, 4 k = 5_${ik}$ - i temp = one / t16( k, k ) tmp( k ) = btmp( k )*temp do j = k + 1, 4 tmp( k ) = tmp( k ) - ( temp*t16( k, j ) )*tmp( j ) end do end do do i = 1, 3 if( jpiv( 4_${ik}$-i )/=4_${ik}$-i ) then temp = tmp( 4_${ik}$-i ) tmp( 4_${ik}$-i ) = tmp( jpiv( 4_${ik}$-i ) ) tmp( jpiv( 4_${ik}$-i ) ) = temp end if end do x( 1_${ik}$, 1_${ik}$ ) = tmp( 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = tmp( 2_${ik}$ ) x( 1_${ik}$, 2_${ik}$ ) = tmp( 3_${ik}$ ) x( 2_${ik}$, 2_${ik}$ ) = tmp( 4_${ik}$ ) xnorm = max( abs( tmp( 1_${ik}$ ) )+abs( tmp( 3_${ik}$ ) ),abs( tmp( 2_${ik}$ ) )+abs( tmp( 4_${ik}$ ) ) ) return end subroutine stdlib${ii}$_dlasy2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasy2( ltranl, ltranr, isgn, n1, n2, tl, ldtl, tr,ldtr, b, ldb, & !! DLASY2: solves for the N1 by N2 matrix X, 1 <= N1,N2 <= 2, in !! op(TL)*X + ISGN*X*op(TR) = SCALE*B, !! where TL is N1 by N1, TR is N2 by N2, B is N1 by N2, and ISGN = 1 or !! -1. op(T) = T or T**T, where T**T denotes the transpose of T. scale, x, ldx, xnorm, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: ltranl, ltranr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: isgn, ldb, ldtl, ldtr, ldx, n1, n2 real(${rk}$), intent(out) :: scale, xnorm ! Array Arguments real(${rk}$), intent(in) :: b(ldb,*), tl(ldtl,*), tr(ldtr,*) real(${rk}$), intent(out) :: x(ldx,*) ! ===================================================================== ! Local Scalars logical(lk) :: bswap, xswap integer(${ik}$) :: i, ip, ipiv, ipsv, j, jp, jpsv, k real(${rk}$) :: bet, eps, gam, l21, sgn, smin, smlnum, tau1, temp, u11, u12, u22, & xmax ! Local Arrays logical(lk) :: bswpiv(4_${ik}$), xswpiv(4_${ik}$) integer(${ik}$) :: jpiv(4_${ik}$), locl21(4_${ik}$), locu12(4_${ik}$), locu22(4_${ik}$) real(${rk}$) :: btmp(4_${ik}$), t16(4_${ik}$,4_${ik}$), tmp(4_${ik}$), x2(2_${ik}$) ! Intrinsic Functions ! Data Statements locu12 = [3_${ik}$,4_${ik}$,1_${ik}$,2_${ik}$] locl21 = [2_${ik}$,1_${ik}$,4_${ik}$,3_${ik}$] locu22 = [4_${ik}$,3_${ik}$,2_${ik}$,1_${ik}$] xswpiv = [.false.,.false.,.true.,.true.] bswpiv = [.false.,.true.,.false.,.true.] ! Executable Statements ! do not check the input parameters for errors info = 0_${ik}$ ! quick return if possible if( n1==0 .or. n2==0 )return ! set constants to control overflow eps = stdlib${ii}$_${ri}$lamch( 'P' ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) / eps sgn = isgn k = n1 + n1 + n2 - 2_${ik}$ go to ( 10, 20, 30, 50 )k ! 1 by 1: tl11*x + sgn*x*tr11 = b11 10 continue tau1 = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) bet = abs( tau1 ) if( bet<=smlnum ) then tau1 = smlnum bet = smlnum info = 1_${ik}$ end if scale = one gam = abs( b( 1_${ik}$, 1_${ik}$ ) ) if( smlnum*gam>bet )scale = one / gam x( 1_${ik}$, 1_${ik}$ ) = ( b( 1_${ik}$, 1_${ik}$ )*scale ) / tau1 xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) return ! 1 by 2: ! tl11*[x11 x12] + isgn*[x11 x12]*op[tr11 tr12] = [b11 b12] ! [tr21 tr22] 20 continue smin = max( eps*max( abs( tl( 1_${ik}$, 1_${ik}$ ) ), abs( tr( 1_${ik}$, 1_${ik}$ ) ),abs( tr( 1_${ik}$, 2_${ik}$ ) ), abs( tr( & 2_${ik}$, 1_${ik}$ ) ), abs( tr( 2_${ik}$, 2_${ik}$ ) ) ),smlnum ) tmp( 1_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) tmp( 4_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 2_${ik}$, 2_${ik}$ ) if( ltranr ) then tmp( 2_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) tmp( 3_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) else tmp( 2_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) tmp( 3_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) end if btmp( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) btmp( 2_${ik}$ ) = b( 1_${ik}$, 2_${ik}$ ) go to 40 ! 2 by 1: ! op[tl11 tl12]*[x11] + isgn* [x11]*tr11 = [b11] ! [tl21 tl22] [x21] [x21] [b21] 30 continue smin = max( eps*max( abs( tr( 1_${ik}$, 1_${ik}$ ) ), abs( tl( 1_${ik}$, 1_${ik}$ ) ),abs( tl( 1_${ik}$, 2_${ik}$ ) ), abs( tl( & 2_${ik}$, 1_${ik}$ ) ), abs( tl( 2_${ik}$, 2_${ik}$ ) ) ),smlnum ) tmp( 1_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) tmp( 4_${ik}$ ) = tl( 2_${ik}$, 2_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) if( ltranl ) then tmp( 2_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) tmp( 3_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) else tmp( 2_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) tmp( 3_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) end if btmp( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) btmp( 2_${ik}$ ) = b( 2_${ik}$, 1_${ik}$ ) 40 continue ! solve 2 by 2 system using complete pivoting. ! set pivots less than smin to smin. ipiv = stdlib${ii}$_i${ri}$amax( 4_${ik}$, tmp, 1_${ik}$ ) u11 = tmp( ipiv ) if( abs( u11 )<=smin ) then info = 1_${ik}$ u11 = smin end if u12 = tmp( locu12( ipiv ) ) l21 = tmp( locl21( ipiv ) ) / u11 u22 = tmp( locu22( ipiv ) ) - u12*l21 xswap = xswpiv( ipiv ) bswap = bswpiv( ipiv ) if( abs( u22 )<=smin ) then info = 1_${ik}$ u22 = smin end if if( bswap ) then temp = btmp( 2_${ik}$ ) btmp( 2_${ik}$ ) = btmp( 1_${ik}$ ) - l21*temp btmp( 1_${ik}$ ) = temp else btmp( 2_${ik}$ ) = btmp( 2_${ik}$ ) - l21*btmp( 1_${ik}$ ) end if scale = one if( ( two*smlnum )*abs( btmp( 2_${ik}$ ) )>abs( u22 ) .or.( two*smlnum )*abs( btmp( 1_${ik}$ ) )>abs(& u11 ) ) then scale = half / max( abs( btmp( 1_${ik}$ ) ), abs( btmp( 2_${ik}$ ) ) ) btmp( 1_${ik}$ ) = btmp( 1_${ik}$ )*scale btmp( 2_${ik}$ ) = btmp( 2_${ik}$ )*scale end if x2( 2_${ik}$ ) = btmp( 2_${ik}$ ) / u22 x2( 1_${ik}$ ) = btmp( 1_${ik}$ ) / u11 - ( u12 / u11 )*x2( 2_${ik}$ ) if( xswap ) then temp = x2( 2_${ik}$ ) x2( 2_${ik}$ ) = x2( 1_${ik}$ ) x2( 1_${ik}$ ) = temp end if x( 1_${ik}$, 1_${ik}$ ) = x2( 1_${ik}$ ) if( n1==1_${ik}$ ) then x( 1_${ik}$, 2_${ik}$ ) = x2( 2_${ik}$ ) xnorm = abs( x( 1_${ik}$, 1_${ik}$ ) ) + abs( x( 1_${ik}$, 2_${ik}$ ) ) else x( 2_${ik}$, 1_${ik}$ ) = x2( 2_${ik}$ ) xnorm = max( abs( x( 1_${ik}$, 1_${ik}$ ) ), abs( x( 2_${ik}$, 1_${ik}$ ) ) ) end if return ! 2 by 2: ! op[tl11 tl12]*[x11 x12] +isgn* [x11 x12]*op[tr11 tr12] = [b11 b12] ! [tl21 tl22] [x21 x22] [x21 x22] [tr21 tr22] [b21 b22] ! solve equivalent 4 by 4 system using complete pivoting. ! set pivots less than smin to smin. 50 continue smin = max( abs( tr( 1_${ik}$, 1_${ik}$ ) ), abs( tr( 1_${ik}$, 2_${ik}$ ) ),abs( tr( 2_${ik}$, 1_${ik}$ ) ), abs( tr( 2_${ik}$, 2_${ik}$ ) ) ) smin = max( smin, abs( tl( 1_${ik}$, 1_${ik}$ ) ), abs( tl( 1_${ik}$, 2_${ik}$ ) ),abs( tl( 2_${ik}$, 1_${ik}$ ) ), abs( tl( 2_${ik}$, & 2_${ik}$ ) ) ) smin = max( eps*smin, smlnum ) btmp( 1_${ik}$ ) = zero call stdlib${ii}$_${ri}$copy( 16_${ik}$, btmp, 0_${ik}$, t16, 1_${ik}$ ) t16( 1_${ik}$, 1_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) t16( 2_${ik}$, 2_${ik}$ ) = tl( 2_${ik}$, 2_${ik}$ ) + sgn*tr( 1_${ik}$, 1_${ik}$ ) t16( 3_${ik}$, 3_${ik}$ ) = tl( 1_${ik}$, 1_${ik}$ ) + sgn*tr( 2_${ik}$, 2_${ik}$ ) t16( 4_${ik}$, 4_${ik}$ ) = tl( 2_${ik}$, 2_${ik}$ ) + sgn*tr( 2_${ik}$, 2_${ik}$ ) if( ltranl ) then t16( 1_${ik}$, 2_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) t16( 2_${ik}$, 1_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) t16( 3_${ik}$, 4_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) t16( 4_${ik}$, 3_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) else t16( 1_${ik}$, 2_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) t16( 2_${ik}$, 1_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) t16( 3_${ik}$, 4_${ik}$ ) = tl( 1_${ik}$, 2_${ik}$ ) t16( 4_${ik}$, 3_${ik}$ ) = tl( 2_${ik}$, 1_${ik}$ ) end if if( ltranr ) then t16( 1_${ik}$, 3_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) t16( 2_${ik}$, 4_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) t16( 3_${ik}$, 1_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) t16( 4_${ik}$, 2_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) else t16( 1_${ik}$, 3_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) t16( 2_${ik}$, 4_${ik}$ ) = sgn*tr( 2_${ik}$, 1_${ik}$ ) t16( 3_${ik}$, 1_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) t16( 4_${ik}$, 2_${ik}$ ) = sgn*tr( 1_${ik}$, 2_${ik}$ ) end if btmp( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) btmp( 2_${ik}$ ) = b( 2_${ik}$, 1_${ik}$ ) btmp( 3_${ik}$ ) = b( 1_${ik}$, 2_${ik}$ ) btmp( 4_${ik}$ ) = b( 2_${ik}$, 2_${ik}$ ) ! perform elimination loop_100: do i = 1, 3 xmax = zero do ip = i, 4 do jp = i, 4 if( abs( t16( ip, jp ) )>=xmax ) then xmax = abs( t16( ip, jp ) ) ipsv = ip jpsv = jp end if end do end do if( ipsv/=i ) then call stdlib${ii}$_${ri}$swap( 4_${ik}$, t16( ipsv, 1_${ik}$ ), 4_${ik}$, t16( i, 1_${ik}$ ), 4_${ik}$ ) temp = btmp( i ) btmp( i ) = btmp( ipsv ) btmp( ipsv ) = temp end if if( jpsv/=i )call stdlib${ii}$_${ri}$swap( 4_${ik}$, t16( 1_${ik}$, jpsv ), 1_${ik}$, t16( 1_${ik}$, i ), 1_${ik}$ ) jpiv( i ) = jpsv if( abs( t16( i, i ) )abs( t16( 1_${ik}$, 1_${ik}$ ) ) .or.( eight*smlnum )*abs( & btmp( 2_${ik}$ ) )>abs( t16( 2_${ik}$, 2_${ik}$ ) ) .or.( eight*smlnum )*abs( btmp( 3_${ik}$ ) )>abs( t16( 3_${ik}$, 3_${ik}$ ) )& .or.( eight*smlnum )*abs( btmp( 4_${ik}$ ) )>abs( t16( 4_${ik}$, 4_${ik}$ ) ) ) then scale = ( one / eight ) / max( abs( btmp( 1_${ik}$ ) ),abs( btmp( 2_${ik}$ ) ), abs( btmp( 3_${ik}$ ) ), & abs( btmp( 4_${ik}$ ) ) ) btmp( 1_${ik}$ ) = btmp( 1_${ik}$ )*scale btmp( 2_${ik}$ ) = btmp( 2_${ik}$ )*scale btmp( 3_${ik}$ ) = btmp( 3_${ik}$ )*scale btmp( 4_${ik}$ ) = btmp( 4_${ik}$ )*scale end if do i = 1, 4 k = 5_${ik}$ - i temp = one / t16( k, k ) tmp( k ) = btmp( k )*temp do j = k + 1, 4 tmp( k ) = tmp( k ) - ( temp*t16( k, j ) )*tmp( j ) end do end do do i = 1, 3 if( jpiv( 4_${ik}$-i )/=4_${ik}$-i ) then temp = tmp( 4_${ik}$-i ) tmp( 4_${ik}$-i ) = tmp( jpiv( 4_${ik}$-i ) ) tmp( jpiv( 4_${ik}$-i ) ) = temp end if end do x( 1_${ik}$, 1_${ik}$ ) = tmp( 1_${ik}$ ) x( 2_${ik}$, 1_${ik}$ ) = tmp( 2_${ik}$ ) x( 1_${ik}$, 2_${ik}$ ) = tmp( 3_${ik}$ ) x( 2_${ik}$, 2_${ik}$ ) = tmp( 4_${ik}$ ) xnorm = max( abs( tmp( 1_${ik}$ ) )+abs( tmp( 3_${ik}$ ) ),abs( tmp( 2_${ik}$ ) )+abs( tmp( 4_${ik}$ ) ) ) return end subroutine stdlib${ii}$_${ri}$lasy2 #:endif #:endfor module subroutine stdlib${ii}$_strsna( job, howmny, select, n, t, ldt, vl, ldvl, vr,ldvr, s, sep, mm, m, & !! STRSNA estimates reciprocal condition numbers for specified !! eigenvalues and/or right eigenvectors of a real upper !! quasi-triangular matrix T (or of any matrix Q*T*Q**T with Q !! orthogonal). !! T must be in Schur canonical form (as returned by SHSEQR), that is, !! block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each !! 2-by-2 diagonal block has its diagonal elements equal and its !! off-diagonal elements of opposite sign. work, ldwork, iwork,info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: howmny, job integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldt, ldvl, ldvr, ldwork, mm, n ! Array Arguments logical(lk), intent(in) :: select(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: s(*), sep(*), work(ldwork,*) real(sp), intent(in) :: t(ldt,*), vl(ldvl,*), vr(ldvr,*) ! ===================================================================== ! Local Scalars logical(lk) :: pair, somcon, wantbh, wants, wantsp integer(${ik}$) :: i, ierr, ifst, ilst, j, k, kase, ks, n2, nn real(sp) :: bignum, cond, cs, delta, dumm, eps, est, lnrm, mu, prod, prod1, prod2, & rnrm, scale, smlnum, sn ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) real(sp) :: dummy(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters wantbh = stdlib_lsame( job, 'B' ) wants = stdlib_lsame( job, 'E' ) .or. wantbh wantsp = stdlib_lsame( job, 'V' ) .or. wantbh somcon = stdlib_lsame( howmny, 'S' ) info = 0_${ik}$ if( .not.wants .and. .not.wantsp ) then info = -1_${ik}$ else if( .not.stdlib_lsame( howmny, 'A' ) .and. .not.somcon ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( ldtn ).and.( n>0_${ik}$ )) then info = -7_${ik}$ else if(( ilst<1_${ik}$ .or. ilst>n ).and.( n>0_${ik}$ )) then info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'STREXC', -info ) return end if ! quick return if possible if( n<=1 )return ! determine the first row of specified block ! and find out it is 1 by 1 or 2 by 2. if( ifst>1_${ik}$ ) then if( t( ifst, ifst-1 )/=zero )ifst = ifst - 1_${ik}$ end if nbf = 1_${ik}$ if( ifst1_${ik}$ ) then if( t( ilst, ilst-1 )/=zero )ilst = ilst - 1_${ik}$ end if nbl = 1_${ik}$ if( ilst=3_${ik}$ ) then if( t( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_slaexc( wantq, n, t, ldt, q, ldq, here-nbnext, nbnext,nbf, work, & info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - nbnext ! test if 2 by 2 block breaks into two 1 by 1 blocks if( nbf==2_${ik}$ ) then if( t( here+1, here )==zero )nbf = 3_${ik}$ end if else ! current block consists of two 1 by 1 blocks each of which ! must be swapped individually nbnext = 1_${ik}$ if( here>=3_${ik}$ ) then if( t( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_slaexc( wantq, n, t, ldt, q, ldq, here-nbnext, nbnext,1_${ik}$, work, info ) if( info/=0_${ik}$ ) then ilst = here return end if if( nbnext==1_${ik}$ ) then ! swap two 1 by 1 blocks, no problems possible call stdlib${ii}$_slaexc( wantq, n, t, ldt, q, ldq, here, nbnext, 1_${ik}$,work, info ) here = here - 1_${ik}$ else ! recompute nbnext in case 2 by 2 split if( t( here, here-1 )==zero )nbnext = 1_${ik}$ if( nbnext==2_${ik}$ ) then ! 2 by 2 block did not split call stdlib${ii}$_slaexc( wantq, n, t, ldt, q, ldq, here-1, 2_${ik}$, 1_${ik}$,work, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 2_${ik}$ else ! 2 by 2 block did split call stdlib${ii}$_slaexc( wantq, n, t, ldt, q, ldq, here, 1_${ik}$, 1_${ik}$,work, info ) call stdlib${ii}$_slaexc( wantq, n, t, ldt, q, ldq, here-1, 1_${ik}$, 1_${ik}$,work, info ) here = here - 2_${ik}$ end if end if end if if( here>ilst )go to 20 end if ilst = here return end subroutine stdlib${ii}$_strexc module subroutine stdlib${ii}$_dtrexc( compq, n, t, ldt, q, ldq, ifst, ilst, work,info ) !! DTREXC reorders the real Schur factorization of a real matrix !! A = Q*T*Q**T, so that the diagonal block of T with row index IFST is !! moved to row ILST. !! The real Schur form T is reordered by an orthogonal similarity !! transformation Z**T*T*Z, and optionally the matrix Q of Schur vectors !! is updated by postmultiplying it with Z. !! T must be in Schur canonical form (as returned by DHSEQR), that is, !! block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each !! 2-by-2 diagonal block has its diagonal elements equal and its !! off-diagonal elements of opposite sign. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compq integer(${ik}$), intent(inout) :: ifst, ilst integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq, ldt, n ! Array Arguments real(dp), intent(inout) :: q(ldq,*), t(ldt,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: wantq integer(${ik}$) :: here, nbf, nbl, nbnext ! Intrinsic Functions ! Executable Statements ! decode and test the input arguments. info = 0_${ik}$ wantq = stdlib_lsame( compq, 'V' ) if( .not.wantq .and. .not.stdlib_lsame( compq, 'N' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldtn ).and.( n>0_${ik}$ )) then info = -7_${ik}$ else if(( ilst<1_${ik}$ .or. ilst>n ).and.( n>0_${ik}$ )) then info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DTREXC', -info ) return end if ! quick return if possible if( n<=1 )return ! determine the first row of specified block ! and find out it is 1 by 1 or 2 by 2. if( ifst>1_${ik}$ ) then if( t( ifst, ifst-1 )/=zero )ifst = ifst - 1_${ik}$ end if nbf = 1_${ik}$ if( ifst1_${ik}$ ) then if( t( ilst, ilst-1 )/=zero )ilst = ilst - 1_${ik}$ end if nbl = 1_${ik}$ if( ilst=3_${ik}$ ) then if( t( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_dlaexc( wantq, n, t, ldt, q, ldq, here-nbnext, nbnext,nbf, work, & info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - nbnext ! test if 2 by 2 block breaks into two 1 by 1 blocks if( nbf==2_${ik}$ ) then if( t( here+1, here )==zero )nbf = 3_${ik}$ end if else ! current block consists of two 1 by 1 blocks each of which ! must be swapped individually nbnext = 1_${ik}$ if( here>=3_${ik}$ ) then if( t( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_dlaexc( wantq, n, t, ldt, q, ldq, here-nbnext, nbnext,1_${ik}$, work, info ) if( info/=0_${ik}$ ) then ilst = here return end if if( nbnext==1_${ik}$ ) then ! swap two 1 by 1 blocks, no problems possible call stdlib${ii}$_dlaexc( wantq, n, t, ldt, q, ldq, here, nbnext, 1_${ik}$,work, info ) here = here - 1_${ik}$ else ! recompute nbnext in case 2 by 2 split if( t( here, here-1 )==zero )nbnext = 1_${ik}$ if( nbnext==2_${ik}$ ) then ! 2 by 2 block did not split call stdlib${ii}$_dlaexc( wantq, n, t, ldt, q, ldq, here-1, 2_${ik}$, 1_${ik}$,work, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 2_${ik}$ else ! 2 by 2 block did split call stdlib${ii}$_dlaexc( wantq, n, t, ldt, q, ldq, here, 1_${ik}$, 1_${ik}$,work, info ) call stdlib${ii}$_dlaexc( wantq, n, t, ldt, q, ldq, here-1, 1_${ik}$, 1_${ik}$,work, info ) here = here - 2_${ik}$ end if end if end if if( here>ilst )go to 20 end if ilst = here return end subroutine stdlib${ii}$_dtrexc #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$trexc( compq, n, t, ldt, q, ldq, ifst, ilst, work,info ) !! DTREXC: reorders the real Schur factorization of a real matrix !! A = Q*T*Q**T, so that the diagonal block of T with row index IFST is !! moved to row ILST. !! The real Schur form T is reordered by an orthogonal similarity !! transformation Z**T*T*Z, and optionally the matrix Q of Schur vectors !! is updated by postmultiplying it with Z. !! T must be in Schur canonical form (as returned by DHSEQR), that is, !! block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each !! 2-by-2 diagonal block has its diagonal elements equal and its !! off-diagonal elements of opposite sign. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compq integer(${ik}$), intent(inout) :: ifst, ilst integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldq, ldt, n ! Array Arguments real(${rk}$), intent(inout) :: q(ldq,*), t(ldt,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: wantq integer(${ik}$) :: here, nbf, nbl, nbnext ! Intrinsic Functions ! Executable Statements ! decode and test the input arguments. info = 0_${ik}$ wantq = stdlib_lsame( compq, 'V' ) if( .not.wantq .and. .not.stdlib_lsame( compq, 'N' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldtn ).and.( n>0_${ik}$ )) then info = -7_${ik}$ else if(( ilst<1_${ik}$ .or. ilst>n ).and.( n>0_${ik}$ )) then info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DTREXC', -info ) return end if ! quick return if possible if( n<=1 )return ! determine the first row of specified block ! and find out it is 1 by 1 or 2 by 2. if( ifst>1_${ik}$ ) then if( t( ifst, ifst-1 )/=zero )ifst = ifst - 1_${ik}$ end if nbf = 1_${ik}$ if( ifst1_${ik}$ ) then if( t( ilst, ilst-1 )/=zero )ilst = ilst - 1_${ik}$ end if nbl = 1_${ik}$ if( ilst=3_${ik}$ ) then if( t( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_${ri}$laexc( wantq, n, t, ldt, q, ldq, here-nbnext, nbnext,nbf, work, & info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - nbnext ! test if 2 by 2 block breaks into two 1 by 1 blocks if( nbf==2_${ik}$ ) then if( t( here+1, here )==zero )nbf = 3_${ik}$ end if else ! current block consists of two 1 by 1 blocks each of which ! must be swapped individually nbnext = 1_${ik}$ if( here>=3_${ik}$ ) then if( t( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_${ri}$laexc( wantq, n, t, ldt, q, ldq, here-nbnext, nbnext,1_${ik}$, work, info ) if( info/=0_${ik}$ ) then ilst = here return end if if( nbnext==1_${ik}$ ) then ! swap two 1 by 1 blocks, no problems possible call stdlib${ii}$_${ri}$laexc( wantq, n, t, ldt, q, ldq, here, nbnext, 1_${ik}$,work, info ) here = here - 1_${ik}$ else ! recompute nbnext in case 2 by 2 split if( t( here, here-1 )==zero )nbnext = 1_${ik}$ if( nbnext==2_${ik}$ ) then ! 2 by 2 block did not split call stdlib${ii}$_${ri}$laexc( wantq, n, t, ldt, q, ldq, here-1, 2_${ik}$, 1_${ik}$,work, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 2_${ik}$ else ! 2 by 2 block did split call stdlib${ii}$_${ri}$laexc( wantq, n, t, ldt, q, ldq, here, 1_${ik}$, 1_${ik}$,work, info ) call stdlib${ii}$_${ri}$laexc( wantq, n, t, ldt, q, ldq, here-1, 1_${ik}$, 1_${ik}$,work, info ) here = here - 2_${ik}$ end if end if end if if( here>ilst )go to 20 end if ilst = here return end subroutine stdlib${ii}$_${ri}$trexc #:endif #:endfor pure module subroutine stdlib${ii}$_ctrexc( compq, n, t, ldt, q, ldq, ifst, ilst, info ) !! CTREXC reorders the Schur factorization of a complex matrix !! A = Q*T*Q**H, so that the diagonal element of T with row index IFST !! is moved to row ILST. !! The Schur form T is reordered by a unitary similarity transformation !! Z**H*T*Z, and optionally the matrix Q of Schur vectors is updated by !! postmultplying it with Z. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: compq integer(${ik}$), intent(in) :: ifst, ilst, ldq, ldt, n integer(${ik}$), intent(out) :: info ! Array Arguments complex(sp), intent(inout) :: q(ldq,*), t(ldt,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantq integer(${ik}$) :: k, m1, m2, m3 real(sp) :: cs complex(sp) :: sn, t11, t22, temp ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters. info = 0_${ik}$ wantq = stdlib_lsame( compq, 'V' ) if( .not.stdlib_lsame( compq, 'N' ) .and. .not.wantq ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( ldtn ).and.( n>0_${ik}$ )) then info = -7_${ik}$ else if(( ilst<1_${ik}$ .or. ilst>n ).and.( n>0_${ik}$ )) then info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CTREXC', -info ) return end if ! quick return if possible if( n<=1 .or. ifst==ilst )return if( ifstn ).and.( n>0_${ik}$ )) then info = -7_${ik}$ else if(( ilst<1_${ik}$ .or. ilst>n ).and.( n>0_${ik}$ )) then info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZTREXC', -info ) return end if ! quick return if possible if( n<=1 .or. ifst==ilst )return if( ifstn ).and.( n>0_${ik}$ )) then info = -7_${ik}$ else if(( ilst<1_${ik}$ .or. ilst>n ).and.( n>0_${ik}$ )) then info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZTREXC', -info ) return end if ! quick return if possible if( n<=1 .or. ifst==ilst )return if( ifstn )return j2 = j1 + 1_${ik}$ j3 = j1 + 2_${ik}$ j4 = j1 + 3_${ik}$ if( n1==1_${ik}$ .and. n2==1_${ik}$ ) then ! swap two 1-by-1 blocks. t11 = t( j1, j1 ) t22 = t( j2, j2 ) ! determine the transformation to perform the interchange. call stdlib${ii}$_slartg( t( j1, j2 ), t22-t11, cs, sn, temp ) ! apply transformation to the matrix t. if( j3<=n )call stdlib${ii}$_srot( n-j1-1, t( j1, j3 ), ldt, t( j2, j3 ), ldt, cs,sn ) call stdlib${ii}$_srot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, t( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) t( j1, j1 ) = t22 t( j2, j2 ) = t11 if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_srot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) end if else ! swapping involves at least one 2-by-2 block. ! copy the diagonal block of order n1+n2 to the local array d ! and compute its norm. nd = n1 + n2 call stdlib${ii}$_slacpy( 'FULL', nd, nd, t( j1, j1 ), ldt, d, ldd ) dnorm = stdlib${ii}$_slange( 'MAX', nd, nd, d, ldd, work ) ! compute machine-dependent threshold for test for accepting ! swap. eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) / eps thresh = max( ten*eps*dnorm, smlnum ) ! solve t11*x - x*t22 = scale*t12 for x. call stdlib${ii}$_slasy2( .false., .false., -1_${ik}$, n1, n2, d, ldd,d( n1+1, n1+1 ), ldd, d( 1_${ik}$,& n1+1 ), ldd, scale, x,ldx, xnorm, ierr ) ! swap the adjacent diagonal blocks. k = n1 + n1 + n2 - 3_${ik}$ go to ( 10, 20, 30 )k 10 continue ! n1 = 1, n2 = 2: generate elementary reflector h so that: ! ( scale, x11, x12 ) h = ( 0, 0, * ) u( 1_${ik}$ ) = scale u( 2_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) u( 3_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ ) call stdlib${ii}$_slarfg( 3_${ik}$, u( 3_${ik}$ ), u, 1_${ik}$, tau ) u( 3_${ik}$ ) = one t11 = t( j1, j1 ) ! perform swap provisionally on diagonal block in d. call stdlib${ii}$_slarfx( 'L', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) call stdlib${ii}$_slarfx( 'R', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) ! test whether to reject swap. if( max( abs( d( 3, 1 ) ), abs( d( 3, 2 ) ), abs( d( 3,3 )-t11 ) )>thresh )go to 50 ! accept swap: apply transformation to the entire matrix t. call stdlib${ii}$_slarfx( 'L', 3_${ik}$, n-j1+1, u, tau, t( j1, j1 ), ldt, work ) call stdlib${ii}$_slarfx( 'R', j2, 3_${ik}$, u, tau, t( 1_${ik}$, j1 ), ldt, work ) t( j3, j1 ) = zero t( j3, j2 ) = zero t( j3, j3 ) = t11 if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_slarfx( 'R', n, 3_${ik}$, u, tau, q( 1_${ik}$, j1 ), ldq, work ) end if go to 40 20 continue ! n1 = 2, n2 = 1: generate elementary reflector h so that: ! h ( -x11 ) = ( * ) ! ( -x21 ) = ( 0 ) ! ( scale ) = ( 0 ) u( 1_${ik}$ ) = -x( 1_${ik}$, 1_${ik}$ ) u( 2_${ik}$ ) = -x( 2_${ik}$, 1_${ik}$ ) u( 3_${ik}$ ) = scale call stdlib${ii}$_slarfg( 3_${ik}$, u( 1_${ik}$ ), u( 2_${ik}$ ), 1_${ik}$, tau ) u( 1_${ik}$ ) = one t33 = t( j3, j3 ) ! perform swap provisionally on diagonal block in d. call stdlib${ii}$_slarfx( 'L', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) call stdlib${ii}$_slarfx( 'R', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) ! test whether to reject swap. if( max( abs( d( 2, 1 ) ), abs( d( 3, 1 ) ), abs( d( 1,1 )-t33 ) )>thresh )go to 50 ! accept swap: apply transformation to the entire matrix t. call stdlib${ii}$_slarfx( 'R', j3, 3_${ik}$, u, tau, t( 1_${ik}$, j1 ), ldt, work ) call stdlib${ii}$_slarfx( 'L', 3_${ik}$, n-j1, u, tau, t( j1, j2 ), ldt, work ) t( j1, j1 ) = t33 t( j2, j1 ) = zero t( j3, j1 ) = zero if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_slarfx( 'R', n, 3_${ik}$, u, tau, q( 1_${ik}$, j1 ), ldq, work ) end if go to 40 30 continue ! n1 = 2, n2 = 2: generate elementary reflectors h(1) and h(2) so ! that: ! h(2) h(1) ( -x11 -x12 ) = ( * * ) ! ( -x21 -x22 ) ( 0 * ) ! ( scale 0 ) ( 0 0 ) ! ( 0 scale ) ( 0 0 ) u1( 1_${ik}$ ) = -x( 1_${ik}$, 1_${ik}$ ) u1( 2_${ik}$ ) = -x( 2_${ik}$, 1_${ik}$ ) u1( 3_${ik}$ ) = scale call stdlib${ii}$_slarfg( 3_${ik}$, u1( 1_${ik}$ ), u1( 2_${ik}$ ), 1_${ik}$, tau1 ) u1( 1_${ik}$ ) = one temp = -tau1*( x( 1_${ik}$, 2_${ik}$ )+u1( 2_${ik}$ )*x( 2_${ik}$, 2_${ik}$ ) ) u2( 1_${ik}$ ) = -temp*u1( 2_${ik}$ ) - x( 2_${ik}$, 2_${ik}$ ) u2( 2_${ik}$ ) = -temp*u1( 3_${ik}$ ) u2( 3_${ik}$ ) = scale call stdlib${ii}$_slarfg( 3_${ik}$, u2( 1_${ik}$ ), u2( 2_${ik}$ ), 1_${ik}$, tau2 ) u2( 1_${ik}$ ) = one ! perform swap provisionally on diagonal block in d. call stdlib${ii}$_slarfx( 'L', 3_${ik}$, 4_${ik}$, u1, tau1, d, ldd, work ) call stdlib${ii}$_slarfx( 'R', 4_${ik}$, 3_${ik}$, u1, tau1, d, ldd, work ) call stdlib${ii}$_slarfx( 'L', 3_${ik}$, 4_${ik}$, u2, tau2, d( 2_${ik}$, 1_${ik}$ ), ldd, work ) call stdlib${ii}$_slarfx( 'R', 4_${ik}$, 3_${ik}$, u2, tau2, d( 1_${ik}$, 2_${ik}$ ), ldd, work ) ! test whether to reject swap. if( max( abs( d( 3_${ik}$, 1_${ik}$ ) ), abs( d( 3_${ik}$, 2_${ik}$ ) ), abs( d( 4_${ik}$, 1_${ik}$ ) ),abs( d( 4_${ik}$, 2_${ik}$ ) ) )& >thresh )go to 50 ! accept swap: apply transformation to the entire matrix t. call stdlib${ii}$_slarfx( 'L', 3_${ik}$, n-j1+1, u1, tau1, t( j1, j1 ), ldt, work ) call stdlib${ii}$_slarfx( 'R', j4, 3_${ik}$, u1, tau1, t( 1_${ik}$, j1 ), ldt, work ) call stdlib${ii}$_slarfx( 'L', 3_${ik}$, n-j1+1, u2, tau2, t( j2, j1 ), ldt, work ) call stdlib${ii}$_slarfx( 'R', j4, 3_${ik}$, u2, tau2, t( 1_${ik}$, j2 ), ldt, work ) t( j3, j1 ) = zero t( j3, j2 ) = zero t( j4, j1 ) = zero t( j4, j2 ) = zero if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_slarfx( 'R', n, 3_${ik}$, u1, tau1, q( 1_${ik}$, j1 ), ldq, work ) call stdlib${ii}$_slarfx( 'R', n, 3_${ik}$, u2, tau2, q( 1_${ik}$, j2 ), ldq, work ) end if 40 continue if( n2==2_${ik}$ ) then ! standardize new 2-by-2 block t11 call stdlib${ii}$_slanv2( t( j1, j1 ), t( j1, j2 ), t( j2, j1 ),t( j2, j2 ), wr1, wi1, & wr2, wi2, cs, sn ) call stdlib${ii}$_srot( n-j1-1, t( j1, j1+2 ), ldt, t( j2, j1+2 ), ldt,cs, sn ) call stdlib${ii}$_srot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, t( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) if( wantq )call stdlib${ii}$_srot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) end if if( n1==2_${ik}$ ) then ! standardize new 2-by-2 block t22 j3 = j1 + n2 j4 = j3 + 1_${ik}$ call stdlib${ii}$_slanv2( t( j3, j3 ), t( j3, j4 ), t( j4, j3 ),t( j4, j4 ), wr1, wi1, & wr2, wi2, cs, sn ) if( j3+2<=n )call stdlib${ii}$_srot( n-j3-1, t( j3, j3+2 ), ldt, t( j4, j3+2 ),ldt, cs,& sn ) call stdlib${ii}$_srot( j3-1, t( 1_${ik}$, j3 ), 1_${ik}$, t( 1_${ik}$, j4 ), 1_${ik}$, cs, sn ) if( wantq )call stdlib${ii}$_srot( n, q( 1_${ik}$, j3 ), 1_${ik}$, q( 1_${ik}$, j4 ), 1_${ik}$, cs, sn ) end if end if return ! exit with info = 1 if swap was rejected. 50 continue info = 1_${ik}$ return end subroutine stdlib${ii}$_slaexc module subroutine stdlib${ii}$_dlaexc( wantq, n, t, ldt, q, ldq, j1, n1, n2, work,info ) !! DLAEXC swaps adjacent diagonal blocks T11 and T22 of order 1 or 2 in !! an upper quasi-triangular matrix T by an orthogonal similarity !! transformation. !! T must be in Schur canonical form, that is, block upper triangular !! with 1-by-1 and 2-by-2 diagonal blocks; each 2-by-2 diagonal block !! has its diagonal elements equal and its off-diagonal elements of !! opposite sign. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: j1, ldq, ldt, n, n1, n2 ! Array Arguments real(dp), intent(inout) :: q(ldq,*), t(ldt,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: ldd = 4_${ik}$ integer(${ik}$), parameter :: ldx = 2_${ik}$ ! Local Scalars integer(${ik}$) :: ierr, j2, j3, j4, k, nd real(dp) :: cs, dnorm, eps, scale, smlnum, sn, t11, t22, t33, tau, tau1, tau2, temp, & thresh, wi1, wi2, wr1, wr2, xnorm ! Local Arrays real(dp) :: d(ldd,4_${ik}$), u(3_${ik}$), u1(3_${ik}$), u2(3_${ik}$), x(ldx,2_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n==0 .or. n1==0 .or. n2==0 )return if( j1+n1>n )return j2 = j1 + 1_${ik}$ j3 = j1 + 2_${ik}$ j4 = j1 + 3_${ik}$ if( n1==1_${ik}$ .and. n2==1_${ik}$ ) then ! swap two 1-by-1 blocks. t11 = t( j1, j1 ) t22 = t( j2, j2 ) ! determine the transformation to perform the interchange. call stdlib${ii}$_dlartg( t( j1, j2 ), t22-t11, cs, sn, temp ) ! apply transformation to the matrix t. if( j3<=n )call stdlib${ii}$_drot( n-j1-1, t( j1, j3 ), ldt, t( j2, j3 ), ldt, cs,sn ) call stdlib${ii}$_drot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, t( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) t( j1, j1 ) = t22 t( j2, j2 ) = t11 if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_drot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) end if else ! swapping involves at least one 2-by-2 block. ! copy the diagonal block of order n1+n2 to the local array d ! and compute its norm. nd = n1 + n2 call stdlib${ii}$_dlacpy( 'FULL', nd, nd, t( j1, j1 ), ldt, d, ldd ) dnorm = stdlib${ii}$_dlange( 'MAX', nd, nd, d, ldd, work ) ! compute machine-dependent threshold for test for accepting ! swap. eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) / eps thresh = max( ten*eps*dnorm, smlnum ) ! solve t11*x - x*t22 = scale*t12 for x. call stdlib${ii}$_dlasy2( .false., .false., -1_${ik}$, n1, n2, d, ldd,d( n1+1, n1+1 ), ldd, d( 1_${ik}$,& n1+1 ), ldd, scale, x,ldx, xnorm, ierr ) ! swap the adjacent diagonal blocks. k = n1 + n1 + n2 - 3_${ik}$ go to ( 10, 20, 30 )k 10 continue ! n1 = 1, n2 = 2: generate elementary reflector h so that: ! ( scale, x11, x12 ) h = ( 0, 0, * ) u( 1_${ik}$ ) = scale u( 2_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) u( 3_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ ) call stdlib${ii}$_dlarfg( 3_${ik}$, u( 3_${ik}$ ), u, 1_${ik}$, tau ) u( 3_${ik}$ ) = one t11 = t( j1, j1 ) ! perform swap provisionally on diagonal block in d. call stdlib${ii}$_dlarfx( 'L', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) call stdlib${ii}$_dlarfx( 'R', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) ! test whether to reject swap. if( max( abs( d( 3, 1 ) ), abs( d( 3, 2 ) ), abs( d( 3,3 )-t11 ) )>thresh ) go to 50 ! accept swap: apply transformation to the entire matrix t. call stdlib${ii}$_dlarfx( 'L', 3_${ik}$, n-j1+1, u, tau, t( j1, j1 ), ldt, work ) call stdlib${ii}$_dlarfx( 'R', j2, 3_${ik}$, u, tau, t( 1_${ik}$, j1 ), ldt, work ) t( j3, j1 ) = zero t( j3, j2 ) = zero t( j3, j3 ) = t11 if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_dlarfx( 'R', n, 3_${ik}$, u, tau, q( 1_${ik}$, j1 ), ldq, work ) end if go to 40 20 continue ! n1 = 2, n2 = 1: generate elementary reflector h so that: ! h ( -x11 ) = ( * ) ! ( -x21 ) = ( 0 ) ! ( scale ) = ( 0 ) u( 1_${ik}$ ) = -x( 1_${ik}$, 1_${ik}$ ) u( 2_${ik}$ ) = -x( 2_${ik}$, 1_${ik}$ ) u( 3_${ik}$ ) = scale call stdlib${ii}$_dlarfg( 3_${ik}$, u( 1_${ik}$ ), u( 2_${ik}$ ), 1_${ik}$, tau ) u( 1_${ik}$ ) = one t33 = t( j3, j3 ) ! perform swap provisionally on diagonal block in d. call stdlib${ii}$_dlarfx( 'L', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) call stdlib${ii}$_dlarfx( 'R', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) ! test whether to reject swap. if( max( abs( d( 2, 1 ) ), abs( d( 3, 1 ) ), abs( d( 1,1 )-t33 ) )>thresh ) go to 50 ! accept swap: apply transformation to the entire matrix t. call stdlib${ii}$_dlarfx( 'R', j3, 3_${ik}$, u, tau, t( 1_${ik}$, j1 ), ldt, work ) call stdlib${ii}$_dlarfx( 'L', 3_${ik}$, n-j1, u, tau, t( j1, j2 ), ldt, work ) t( j1, j1 ) = t33 t( j2, j1 ) = zero t( j3, j1 ) = zero if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_dlarfx( 'R', n, 3_${ik}$, u, tau, q( 1_${ik}$, j1 ), ldq, work ) end if go to 40 30 continue ! n1 = 2, n2 = 2: generate elementary reflectors h(1) and h(2) so ! that: ! h(2) h(1) ( -x11 -x12 ) = ( * * ) ! ( -x21 -x22 ) ( 0 * ) ! ( scale 0 ) ( 0 0 ) ! ( 0 scale ) ( 0 0 ) u1( 1_${ik}$ ) = -x( 1_${ik}$, 1_${ik}$ ) u1( 2_${ik}$ ) = -x( 2_${ik}$, 1_${ik}$ ) u1( 3_${ik}$ ) = scale call stdlib${ii}$_dlarfg( 3_${ik}$, u1( 1_${ik}$ ), u1( 2_${ik}$ ), 1_${ik}$, tau1 ) u1( 1_${ik}$ ) = one temp = -tau1*( x( 1_${ik}$, 2_${ik}$ )+u1( 2_${ik}$ )*x( 2_${ik}$, 2_${ik}$ ) ) u2( 1_${ik}$ ) = -temp*u1( 2_${ik}$ ) - x( 2_${ik}$, 2_${ik}$ ) u2( 2_${ik}$ ) = -temp*u1( 3_${ik}$ ) u2( 3_${ik}$ ) = scale call stdlib${ii}$_dlarfg( 3_${ik}$, u2( 1_${ik}$ ), u2( 2_${ik}$ ), 1_${ik}$, tau2 ) u2( 1_${ik}$ ) = one ! perform swap provisionally on diagonal block in d. call stdlib${ii}$_dlarfx( 'L', 3_${ik}$, 4_${ik}$, u1, tau1, d, ldd, work ) call stdlib${ii}$_dlarfx( 'R', 4_${ik}$, 3_${ik}$, u1, tau1, d, ldd, work ) call stdlib${ii}$_dlarfx( 'L', 3_${ik}$, 4_${ik}$, u2, tau2, d( 2_${ik}$, 1_${ik}$ ), ldd, work ) call stdlib${ii}$_dlarfx( 'R', 4_${ik}$, 3_${ik}$, u2, tau2, d( 1_${ik}$, 2_${ik}$ ), ldd, work ) ! test whether to reject swap. if( max( abs( d( 3_${ik}$, 1_${ik}$ ) ), abs( d( 3_${ik}$, 2_${ik}$ ) ), abs( d( 4_${ik}$, 1_${ik}$ ) ),abs( d( 4_${ik}$, 2_${ik}$ ) ) )& >thresh )go to 50 ! accept swap: apply transformation to the entire matrix t. call stdlib${ii}$_dlarfx( 'L', 3_${ik}$, n-j1+1, u1, tau1, t( j1, j1 ), ldt, work ) call stdlib${ii}$_dlarfx( 'R', j4, 3_${ik}$, u1, tau1, t( 1_${ik}$, j1 ), ldt, work ) call stdlib${ii}$_dlarfx( 'L', 3_${ik}$, n-j1+1, u2, tau2, t( j2, j1 ), ldt, work ) call stdlib${ii}$_dlarfx( 'R', j4, 3_${ik}$, u2, tau2, t( 1_${ik}$, j2 ), ldt, work ) t( j3, j1 ) = zero t( j3, j2 ) = zero t( j4, j1 ) = zero t( j4, j2 ) = zero if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_dlarfx( 'R', n, 3_${ik}$, u1, tau1, q( 1_${ik}$, j1 ), ldq, work ) call stdlib${ii}$_dlarfx( 'R', n, 3_${ik}$, u2, tau2, q( 1_${ik}$, j2 ), ldq, work ) end if 40 continue if( n2==2_${ik}$ ) then ! standardize new 2-by-2 block t11 call stdlib${ii}$_dlanv2( t( j1, j1 ), t( j1, j2 ), t( j2, j1 ),t( j2, j2 ), wr1, wi1, & wr2, wi2, cs, sn ) call stdlib${ii}$_drot( n-j1-1, t( j1, j1+2 ), ldt, t( j2, j1+2 ), ldt,cs, sn ) call stdlib${ii}$_drot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, t( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) if( wantq )call stdlib${ii}$_drot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) end if if( n1==2_${ik}$ ) then ! standardize new 2-by-2 block t22 j3 = j1 + n2 j4 = j3 + 1_${ik}$ call stdlib${ii}$_dlanv2( t( j3, j3 ), t( j3, j4 ), t( j4, j3 ),t( j4, j4 ), wr1, wi1, & wr2, wi2, cs, sn ) if( j3+2<=n )call stdlib${ii}$_drot( n-j3-1, t( j3, j3+2 ), ldt, t( j4, j3+2 ),ldt, cs,& sn ) call stdlib${ii}$_drot( j3-1, t( 1_${ik}$, j3 ), 1_${ik}$, t( 1_${ik}$, j4 ), 1_${ik}$, cs, sn ) if( wantq )call stdlib${ii}$_drot( n, q( 1_${ik}$, j3 ), 1_${ik}$, q( 1_${ik}$, j4 ), 1_${ik}$, cs, sn ) end if end if return ! exit with info = 1 if swap was rejected. 50 continue info = 1_${ik}$ return end subroutine stdlib${ii}$_dlaexc #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$laexc( wantq, n, t, ldt, q, ldq, j1, n1, n2, work,info ) !! DLAEXC: swaps adjacent diagonal blocks T11 and T22 of order 1 or 2 in !! an upper quasi-triangular matrix T by an orthogonal similarity !! transformation. !! T must be in Schur canonical form, that is, block upper triangular !! with 1-by-1 and 2-by-2 diagonal blocks; each 2-by-2 diagonal block !! has its diagonal elements equal and its off-diagonal elements of !! opposite sign. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: j1, ldq, ldt, n, n1, n2 ! Array Arguments real(${rk}$), intent(inout) :: q(ldq,*), t(ldt,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: ldd = 4_${ik}$ integer(${ik}$), parameter :: ldx = 2_${ik}$ ! Local Scalars integer(${ik}$) :: ierr, j2, j3, j4, k, nd real(${rk}$) :: cs, dnorm, eps, scale, smlnum, sn, t11, t22, t33, tau, tau1, tau2, temp, & thresh, wi1, wi2, wr1, wr2, xnorm ! Local Arrays real(${rk}$) :: d(ldd,4_${ik}$), u(3_${ik}$), u1(3_${ik}$), u2(3_${ik}$), x(ldx,2_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n==0 .or. n1==0 .or. n2==0 )return if( j1+n1>n )return j2 = j1 + 1_${ik}$ j3 = j1 + 2_${ik}$ j4 = j1 + 3_${ik}$ if( n1==1_${ik}$ .and. n2==1_${ik}$ ) then ! swap two 1-by-1 blocks. t11 = t( j1, j1 ) t22 = t( j2, j2 ) ! determine the transformation to perform the interchange. call stdlib${ii}$_${ri}$lartg( t( j1, j2 ), t22-t11, cs, sn, temp ) ! apply transformation to the matrix t. if( j3<=n )call stdlib${ii}$_${ri}$rot( n-j1-1, t( j1, j3 ), ldt, t( j2, j3 ), ldt, cs,sn ) call stdlib${ii}$_${ri}$rot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, t( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) t( j1, j1 ) = t22 t( j2, j2 ) = t11 if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_${ri}$rot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) end if else ! swapping involves at least one 2-by-2 block. ! copy the diagonal block of order n1+n2 to the local array d ! and compute its norm. nd = n1 + n2 call stdlib${ii}$_${ri}$lacpy( 'FULL', nd, nd, t( j1, j1 ), ldt, d, ldd ) dnorm = stdlib${ii}$_${ri}$lange( 'MAX', nd, nd, d, ldd, work ) ! compute machine-dependent threshold for test for accepting ! swap. eps = stdlib${ii}$_${ri}$lamch( 'P' ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) / eps thresh = max( ten*eps*dnorm, smlnum ) ! solve t11*x - x*t22 = scale*t12 for x. call stdlib${ii}$_${ri}$lasy2( .false., .false., -1_${ik}$, n1, n2, d, ldd,d( n1+1, n1+1 ), ldd, d( 1_${ik}$,& n1+1 ), ldd, scale, x,ldx, xnorm, ierr ) ! swap the adjacent diagonal blocks. k = n1 + n1 + n2 - 3_${ik}$ go to ( 10, 20, 30 )k 10 continue ! n1 = 1, n2 = 2: generate elementary reflector h so that: ! ( scale, x11, x12 ) h = ( 0, 0, * ) u( 1_${ik}$ ) = scale u( 2_${ik}$ ) = x( 1_${ik}$, 1_${ik}$ ) u( 3_${ik}$ ) = x( 1_${ik}$, 2_${ik}$ ) call stdlib${ii}$_${ri}$larfg( 3_${ik}$, u( 3_${ik}$ ), u, 1_${ik}$, tau ) u( 3_${ik}$ ) = one t11 = t( j1, j1 ) ! perform swap provisionally on diagonal block in d. call stdlib${ii}$_${ri}$larfx( 'L', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) call stdlib${ii}$_${ri}$larfx( 'R', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) ! test whether to reject swap. if( max( abs( d( 3, 1 ) ), abs( d( 3, 2 ) ), abs( d( 3,3 )-t11 ) )>thresh ) goto 50 ! accept swap: apply transformation to the entire matrix t. call stdlib${ii}$_${ri}$larfx( 'L', 3_${ik}$, n-j1+1, u, tau, t( j1, j1 ), ldt, work ) call stdlib${ii}$_${ri}$larfx( 'R', j2, 3_${ik}$, u, tau, t( 1_${ik}$, j1 ), ldt, work ) t( j3, j1 ) = zero t( j3, j2 ) = zero t( j3, j3 ) = t11 if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_${ri}$larfx( 'R', n, 3_${ik}$, u, tau, q( 1_${ik}$, j1 ), ldq, work ) end if go to 40 20 continue ! n1 = 2, n2 = 1: generate elementary reflector h so that: ! h ( -x11 ) = ( * ) ! ( -x21 ) = ( 0 ) ! ( scale ) = ( 0 ) u( 1_${ik}$ ) = -x( 1_${ik}$, 1_${ik}$ ) u( 2_${ik}$ ) = -x( 2_${ik}$, 1_${ik}$ ) u( 3_${ik}$ ) = scale call stdlib${ii}$_${ri}$larfg( 3_${ik}$, u( 1_${ik}$ ), u( 2_${ik}$ ), 1_${ik}$, tau ) u( 1_${ik}$ ) = one t33 = t( j3, j3 ) ! perform swap provisionally on diagonal block in d. call stdlib${ii}$_${ri}$larfx( 'L', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) call stdlib${ii}$_${ri}$larfx( 'R', 3_${ik}$, 3_${ik}$, u, tau, d, ldd, work ) ! test whether to reject swap. if( max( abs( d( 2, 1 ) ), abs( d( 3, 1 ) ), abs( d( 1,1 )-t33 ) )>thresh ) goto 50 ! accept swap: apply transformation to the entire matrix t. call stdlib${ii}$_${ri}$larfx( 'R', j3, 3_${ik}$, u, tau, t( 1_${ik}$, j1 ), ldt, work ) call stdlib${ii}$_${ri}$larfx( 'L', 3_${ik}$, n-j1, u, tau, t( j1, j2 ), ldt, work ) t( j1, j1 ) = t33 t( j2, j1 ) = zero t( j3, j1 ) = zero if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_${ri}$larfx( 'R', n, 3_${ik}$, u, tau, q( 1_${ik}$, j1 ), ldq, work ) end if go to 40 30 continue ! n1 = 2, n2 = 2: generate elementary reflectors h(1) and h(2) so ! that: ! h(2) h(1) ( -x11 -x12 ) = ( * * ) ! ( -x21 -x22 ) ( 0 * ) ! ( scale 0 ) ( 0 0 ) ! ( 0 scale ) ( 0 0 ) u1( 1_${ik}$ ) = -x( 1_${ik}$, 1_${ik}$ ) u1( 2_${ik}$ ) = -x( 2_${ik}$, 1_${ik}$ ) u1( 3_${ik}$ ) = scale call stdlib${ii}$_${ri}$larfg( 3_${ik}$, u1( 1_${ik}$ ), u1( 2_${ik}$ ), 1_${ik}$, tau1 ) u1( 1_${ik}$ ) = one temp = -tau1*( x( 1_${ik}$, 2_${ik}$ )+u1( 2_${ik}$ )*x( 2_${ik}$, 2_${ik}$ ) ) u2( 1_${ik}$ ) = -temp*u1( 2_${ik}$ ) - x( 2_${ik}$, 2_${ik}$ ) u2( 2_${ik}$ ) = -temp*u1( 3_${ik}$ ) u2( 3_${ik}$ ) = scale call stdlib${ii}$_${ri}$larfg( 3_${ik}$, u2( 1_${ik}$ ), u2( 2_${ik}$ ), 1_${ik}$, tau2 ) u2( 1_${ik}$ ) = one ! perform swap provisionally on diagonal block in d. call stdlib${ii}$_${ri}$larfx( 'L', 3_${ik}$, 4_${ik}$, u1, tau1, d, ldd, work ) call stdlib${ii}$_${ri}$larfx( 'R', 4_${ik}$, 3_${ik}$, u1, tau1, d, ldd, work ) call stdlib${ii}$_${ri}$larfx( 'L', 3_${ik}$, 4_${ik}$, u2, tau2, d( 2_${ik}$, 1_${ik}$ ), ldd, work ) call stdlib${ii}$_${ri}$larfx( 'R', 4_${ik}$, 3_${ik}$, u2, tau2, d( 1_${ik}$, 2_${ik}$ ), ldd, work ) ! test whether to reject swap. if( max( abs( d( 3_${ik}$, 1_${ik}$ ) ), abs( d( 3_${ik}$, 2_${ik}$ ) ), abs( d( 4_${ik}$, 1_${ik}$ ) ),abs( d( 4_${ik}$, 2_${ik}$ ) ) )& >thresh )go to 50 ! accept swap: apply transformation to the entire matrix t. call stdlib${ii}$_${ri}$larfx( 'L', 3_${ik}$, n-j1+1, u1, tau1, t( j1, j1 ), ldt, work ) call stdlib${ii}$_${ri}$larfx( 'R', j4, 3_${ik}$, u1, tau1, t( 1_${ik}$, j1 ), ldt, work ) call stdlib${ii}$_${ri}$larfx( 'L', 3_${ik}$, n-j1+1, u2, tau2, t( j2, j1 ), ldt, work ) call stdlib${ii}$_${ri}$larfx( 'R', j4, 3_${ik}$, u2, tau2, t( 1_${ik}$, j2 ), ldt, work ) t( j3, j1 ) = zero t( j3, j2 ) = zero t( j4, j1 ) = zero t( j4, j2 ) = zero if( wantq ) then ! accumulate transformation in the matrix q. call stdlib${ii}$_${ri}$larfx( 'R', n, 3_${ik}$, u1, tau1, q( 1_${ik}$, j1 ), ldq, work ) call stdlib${ii}$_${ri}$larfx( 'R', n, 3_${ik}$, u2, tau2, q( 1_${ik}$, j2 ), ldq, work ) end if 40 continue if( n2==2_${ik}$ ) then ! standardize new 2-by-2 block t11 call stdlib${ii}$_${ri}$lanv2( t( j1, j1 ), t( j1, j2 ), t( j2, j1 ),t( j2, j2 ), wr1, wi1, & wr2, wi2, cs, sn ) call stdlib${ii}$_${ri}$rot( n-j1-1, t( j1, j1+2 ), ldt, t( j2, j1+2 ), ldt,cs, sn ) call stdlib${ii}$_${ri}$rot( j1-1, t( 1_${ik}$, j1 ), 1_${ik}$, t( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) if( wantq )call stdlib${ii}$_${ri}$rot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j2 ), 1_${ik}$, cs, sn ) end if if( n1==2_${ik}$ ) then ! standardize new 2-by-2 block t22 j3 = j1 + n2 j4 = j3 + 1_${ik}$ call stdlib${ii}$_${ri}$lanv2( t( j3, j3 ), t( j3, j4 ), t( j4, j3 ),t( j4, j4 ), wr1, wi1, & wr2, wi2, cs, sn ) if( j3+2<=n )call stdlib${ii}$_${ri}$rot( n-j3-1, t( j3, j3+2 ), ldt, t( j4, j3+2 ),ldt, cs,& sn ) call stdlib${ii}$_${ri}$rot( j3-1, t( 1_${ik}$, j3 ), 1_${ik}$, t( 1_${ik}$, j4 ), 1_${ik}$, cs, sn ) if( wantq )call stdlib${ii}$_${ri}$rot( n, q( 1_${ik}$, j3 ), 1_${ik}$, q( 1_${ik}$, j4 ), 1_${ik}$, cs, sn ) end if end if return ! exit with info = 1 if swap was rejected. 50 continue info = 1_${ik}$ return end subroutine stdlib${ii}$_${ri}$laexc #:endif #:endfor pure module subroutine stdlib${ii}$_slanv2( a, b, c, d, rt1r, rt1i, rt2r, rt2i, cs, sn ) !! SLANV2 computes the Schur factorization of a real 2-by-2 nonsymmetric !! matrix in standard form: !! [ A B ] = [ CS -SN ] [ AA BB ] [ CS SN ] !! [ C D ] [ SN CS ] [ CC DD ] [-SN CS ] !! where either !! 1) CC = 0 so that AA and DD are real eigenvalues of the matrix, or !! 2) AA = DD and BB*CC < 0, so that AA + or - sqrt(BB*CC) are complex !! conjugate eigenvalues. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(inout) :: a, b, c, d real(sp), intent(out) :: cs, rt1i, rt1r, rt2i, rt2r, sn ! ===================================================================== ! Parameters real(sp), parameter :: multpl = 4.0e+0_sp ! Local Scalars real(sp) :: aa, bb, bcmax, bcmis, cc, cs1, dd, eps, p, sab, sac, scale, sigma, sn1, & tau, temp, z, safmin, safmn2, safmx2 integer(${ik}$) :: count ! Intrinsic Functions ! Executable Statements safmin = stdlib${ii}$_slamch( 'S' ) eps = stdlib${ii}$_slamch( 'P' ) safmn2 = stdlib${ii}$_slamch( 'B' )**int( log( safmin / eps ) /log( stdlib${ii}$_slamch( 'B' ) ) / & two,KIND=${ik}$) safmx2 = one / safmn2 if( c==zero ) then cs = one sn = zero else if( b==zero ) then ! swap rows and columns cs = zero sn = one temp = d d = a a = temp b = -c c = zero else if( (a-d)==zero .and. sign( one, b )/=sign( one, c ) ) then cs = one sn = zero else temp = a - d p = half*temp bcmax = max( abs( b ), abs( c ) ) bcmis = min( abs( b ), abs( c ) )*sign( one, b )*sign( one, c ) scale = max( abs( p ), bcmax ) z = ( p / scale )*p + ( bcmax / scale )*bcmis ! if z is of the order of the machine accuracy, postpone the ! decision on the nature of eigenvalues if( z>=multpl*eps ) then ! real eigenvalues. compute a and d. z = p + sign( sqrt( scale )*sqrt( z ), p ) a = d + z d = d - ( bcmax / z )*bcmis ! compute b and the rotation matrix tau = stdlib${ii}$_slapy2( c, z ) cs = z / tau sn = c / tau b = b - c c = zero else ! complex eigenvalues, or real(almost,KIND=sp) equal eigenvalues. ! make diagonal elements equal. count = 0_${ik}$ sigma = b + c 10 continue count = count + 1_${ik}$ scale = max( abs(temp), abs(sigma) ) if( scale>=safmx2 ) then sigma = sigma * safmn2 temp = temp * safmn2 if (count <= 20)goto 10 end if if( scale<=safmn2 ) then sigma = sigma * safmx2 temp = temp * safmx2 if (count <= 20)goto 10 end if p = half*temp tau = stdlib${ii}$_slapy2( sigma, temp ) cs = sqrt( half*( one+abs( sigma ) / tau ) ) sn = -( p / ( tau*cs ) )*sign( one, sigma ) ! compute [ aa bb ] = [ a b ] [ cs -sn ] ! [ cc dd ] [ c d ] [ sn cs ] aa = a*cs + b*sn bb = -a*sn + b*cs cc = c*cs + d*sn dd = -c*sn + d*cs ! compute [ a b ] = [ cs sn ] [ aa bb ] ! [ c d ] [-sn cs ] [ cc dd ] a = aa*cs + cc*sn b = bb*cs + dd*sn c = -aa*sn + cc*cs d = -bb*sn + dd*cs temp = half*( a+d ) a = temp d = temp if( c/=zero ) then if( b/=zero ) then if( sign( one, b )==sign( one, c ) ) then ! real eigenvalues: reduce to upper triangular form sab = sqrt( abs( b ) ) sac = sqrt( abs( c ) ) p = sign( sab*sac, c ) tau = one / sqrt( abs( b+c ) ) a = temp + p d = temp - p b = b - c c = zero cs1 = sab*tau sn1 = sac*tau temp = cs*cs1 - sn*sn1 sn = cs*sn1 + sn*cs1 cs = temp end if else b = -c c = zero temp = cs cs = -sn sn = temp end if end if end if end if ! store eigenvalues in (rt1r,rt1i) and (rt2r,rt2i). rt1r = a rt2r = d if( c==zero ) then rt1i = zero rt2i = zero else rt1i = sqrt( abs( b ) )*sqrt( abs( c ) ) rt2i = -rt1i end if return end subroutine stdlib${ii}$_slanv2 pure module subroutine stdlib${ii}$_dlanv2( a, b, c, d, rt1r, rt1i, rt2r, rt2i, cs, sn ) !! DLANV2 computes the Schur factorization of a real 2-by-2 nonsymmetric !! matrix in standard form: !! [ A B ] = [ CS -SN ] [ AA BB ] [ CS SN ] !! [ C D ] [ SN CS ] [ CC DD ] [-SN CS ] !! where either !! 1) CC = 0 so that AA and DD are real eigenvalues of the matrix, or !! 2) AA = DD and BB*CC < 0, so that AA + or - sqrt(BB*CC) are complex !! conjugate eigenvalues. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(inout) :: a, b, c, d real(dp), intent(out) :: cs, rt1i, rt1r, rt2i, rt2r, sn ! ===================================================================== ! Parameters real(dp), parameter :: multpl = 4.0e+0_dp ! Local Scalars real(dp) :: aa, bb, bcmax, bcmis, cc, cs1, dd, eps, p, sab, sac, scale, sigma, sn1, & tau, temp, z, safmin, safmn2, safmx2 integer(${ik}$) :: count ! Intrinsic Functions ! Executable Statements safmin = stdlib${ii}$_dlamch( 'S' ) eps = stdlib${ii}$_dlamch( 'P' ) safmn2 = stdlib${ii}$_dlamch( 'B' )**int( log( safmin / eps ) /log( stdlib${ii}$_dlamch( 'B' ) ) / & two,KIND=${ik}$) safmx2 = one / safmn2 if( c==zero ) then cs = one sn = zero else if( b==zero ) then ! swap rows and columns cs = zero sn = one temp = d d = a a = temp b = -c c = zero else if( ( a-d )==zero .and. sign( one, b )/=sign( one, c ) )then cs = one sn = zero else temp = a - d p = half*temp bcmax = max( abs( b ), abs( c ) ) bcmis = min( abs( b ), abs( c ) )*sign( one, b )*sign( one, c ) scale = max( abs( p ), bcmax ) z = ( p / scale )*p + ( bcmax / scale )*bcmis ! if z is of the order of the machine accuracy, postpone the ! decision on the nature of eigenvalues if( z>=multpl*eps ) then ! real eigenvalues. compute a and d. z = p + sign( sqrt( scale )*sqrt( z ), p ) a = d + z d = d - ( bcmax / z )*bcmis ! compute b and the rotation matrix tau = stdlib${ii}$_dlapy2( c, z ) cs = z / tau sn = c / tau b = b - c c = zero else ! complex eigenvalues, or real(almost,KIND=dp) equal eigenvalues. ! make diagonal elements equal. count = 0_${ik}$ sigma = b + c 10 continue count = count + 1_${ik}$ scale = max( abs(temp), abs(sigma) ) if( scale>=safmx2 ) then sigma = sigma * safmn2 temp = temp * safmn2 if (count <= 20)goto 10 end if if( scale<=safmn2 ) then sigma = sigma * safmx2 temp = temp * safmx2 if (count <= 20)goto 10 end if p = half*temp tau = stdlib${ii}$_dlapy2( sigma, temp ) cs = sqrt( half*( one+abs( sigma ) / tau ) ) sn = -( p / ( tau*cs ) )*sign( one, sigma ) ! compute [ aa bb ] = [ a b ] [ cs -sn ] ! [ cc dd ] [ c d ] [ sn cs ] aa = a*cs + b*sn bb = -a*sn + b*cs cc = c*cs + d*sn dd = -c*sn + d*cs ! compute [ a b ] = [ cs sn ] [ aa bb ] ! [ c d ] [-sn cs ] [ cc dd ] a = aa*cs + cc*sn b = bb*cs + dd*sn c = -aa*sn + cc*cs d = -bb*sn + dd*cs temp = half*( a+d ) a = temp d = temp if( c/=zero ) then if( b/=zero ) then if( sign( one, b )==sign( one, c ) ) then ! real eigenvalues: reduce to upper triangular form sab = sqrt( abs( b ) ) sac = sqrt( abs( c ) ) p = sign( sab*sac, c ) tau = one / sqrt( abs( b+c ) ) a = temp + p d = temp - p b = b - c c = zero cs1 = sab*tau sn1 = sac*tau temp = cs*cs1 - sn*sn1 sn = cs*sn1 + sn*cs1 cs = temp end if else b = -c c = zero temp = cs cs = -sn sn = temp end if end if end if end if ! store eigenvalues in (rt1r,rt1i) and (rt2r,rt2i). rt1r = a rt2r = d if( c==zero ) then rt1i = zero rt2i = zero else rt1i = sqrt( abs( b ) )*sqrt( abs( c ) ) rt2i = -rt1i end if return end subroutine stdlib${ii}$_dlanv2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lanv2( a, b, c, d, rt1r, rt1i, rt2r, rt2i, cs, sn ) !! DLANV2: computes the Schur factorization of a real 2-by-2 nonsymmetric !! matrix in standard form: !! [ A B ] = [ CS -SN ] [ AA BB ] [ CS SN ] !! [ C D ] [ SN CS ] [ CC DD ] [-SN CS ] !! where either !! 1) CC = 0 so that AA and DD are real eigenvalues of the matrix, or !! 2) AA = DD and BB*CC < 0, so that AA + or - sqrt(BB*CC) are complex !! conjugate eigenvalues. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(inout) :: a, b, c, d real(${rk}$), intent(out) :: cs, rt1i, rt1r, rt2i, rt2r, sn ! ===================================================================== ! Parameters real(${rk}$), parameter :: multpl = 4.0e+0_${rk}$ ! Local Scalars real(${rk}$) :: aa, bb, bcmax, bcmis, cc, cs1, dd, eps, p, sab, sac, scale, sigma, sn1, & tau, temp, z, safmin, safmn2, safmx2 integer(${ik}$) :: count ! Intrinsic Functions ! Executable Statements safmin = stdlib${ii}$_${ri}$lamch( 'S' ) eps = stdlib${ii}$_${ri}$lamch( 'P' ) safmn2 = stdlib${ii}$_${ri}$lamch( 'B' )**int( log( safmin / eps ) /log( stdlib${ii}$_${ri}$lamch( 'B' ) ) / & two,KIND=${ik}$) safmx2 = one / safmn2 if( c==zero ) then cs = one sn = zero else if( b==zero ) then ! swap rows and columns cs = zero sn = one temp = d d = a a = temp b = -c c = zero else if( ( a-d )==zero .and. sign( one, b )/=sign( one, c ) )then cs = one sn = zero else temp = a - d p = half*temp bcmax = max( abs( b ), abs( c ) ) bcmis = min( abs( b ), abs( c ) )*sign( one, b )*sign( one, c ) scale = max( abs( p ), bcmax ) z = ( p / scale )*p + ( bcmax / scale )*bcmis ! if z is of the order of the machine accuracy, postpone the ! decision on the nature of eigenvalues if( z>=multpl*eps ) then ! real eigenvalues. compute a and d. z = p + sign( sqrt( scale )*sqrt( z ), p ) a = d + z d = d - ( bcmax / z )*bcmis ! compute b and the rotation matrix tau = stdlib${ii}$_${ri}$lapy2( c, z ) cs = z / tau sn = c / tau b = b - c c = zero else ! complex eigenvalues, or real(almost,KIND=${rk}$) equal eigenvalues. ! make diagonal elements equal. count = 0_${ik}$ sigma = b + c 10 continue count = count + 1_${ik}$ scale = max( abs(temp), abs(sigma) ) if( scale>=safmx2 ) then sigma = sigma * safmn2 temp = temp * safmn2 if (count <= 20)goto 10 end if if( scale<=safmn2 ) then sigma = sigma * safmx2 temp = temp * safmx2 if (count <= 20)goto 10 end if p = half*temp tau = stdlib${ii}$_${ri}$lapy2( sigma, temp ) cs = sqrt( half*( one+abs( sigma ) / tau ) ) sn = -( p / ( tau*cs ) )*sign( one, sigma ) ! compute [ aa bb ] = [ a b ] [ cs -sn ] ! [ cc dd ] [ c d ] [ sn cs ] aa = a*cs + b*sn bb = -a*sn + b*cs cc = c*cs + d*sn dd = -c*sn + d*cs ! compute [ a b ] = [ cs sn ] [ aa bb ] ! [ c d ] [-sn cs ] [ cc dd ] a = aa*cs + cc*sn b = bb*cs + dd*sn c = -aa*sn + cc*cs d = -bb*sn + dd*cs temp = half*( a+d ) a = temp d = temp if( c/=zero ) then if( b/=zero ) then if( sign( one, b )==sign( one, c ) ) then ! real eigenvalues: reduce to upper triangular form sab = sqrt( abs( b ) ) sac = sqrt( abs( c ) ) p = sign( sab*sac, c ) tau = one / sqrt( abs( b+c ) ) a = temp + p d = temp - p b = b - c c = zero cs1 = sab*tau sn1 = sac*tau temp = cs*cs1 - sn*sn1 sn = cs*sn1 + sn*cs1 cs = temp end if else b = -c c = zero temp = cs cs = -sn sn = temp end if end if end if end if ! store eigenvalues in (rt1r,rt1i) and (rt2r,rt2i). rt1r = a rt2r = d if( c==zero ) then rt1i = zero rt2i = zero else rt1i = sqrt( abs( b ) )*sqrt( abs( c ) ) rt2i = -rt1i end if return end subroutine stdlib${ii}$_${ri}$lanv2 #:endif #:endfor pure module subroutine stdlib${ii}$_slaein( rightv, noinit, n, h, ldh, wr, wi, vr, vi, b,ldb, work, eps3, & !! SLAEIN uses inverse iteration to find a right or left eigenvector !! corresponding to the eigenvalue (WR,WI) of a real upper Hessenberg !! matrix H. smlnum, bignum, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: noinit, rightv integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldh, n real(sp), intent(in) :: bignum, eps3, smlnum, wi, wr ! Array Arguments real(sp), intent(out) :: b(ldb,*), work(*) real(sp), intent(in) :: h(ldh,*) real(sp), intent(inout) :: vi(*), vr(*) ! ===================================================================== ! Parameters real(sp), parameter :: tenth = 1.0e-1_sp ! Local Scalars character :: normin, trans integer(${ik}$) :: i, i1, i2, i3, ierr, its, j real(sp) :: absbii, absbjj, ei, ej, growto, norm, nrmsml, rec, rootn, scale, temp, & vcrit, vmax, vnorm, w, w1, x, xi, xr, y ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! growto is the threshold used in the acceptance test for an ! eigenvector. rootn = sqrt( real( n,KIND=sp) ) growto = tenth / rootn nrmsml = max( one, eps3*rootn )*smlnum ! form b = h - (wr,wi)*i (except that the subdiagonal elements and ! the imaginary parts of the diagonal elements are not stored). do j = 1, n do i = 1, j - 1 b( i, j ) = h( i, j ) end do b( j, j ) = h( j, j ) - wr end do if( wi==zero ) then ! real eigenvalue. if( noinit ) then ! set initial vector. do i = 1, n vr( i ) = eps3 end do else ! scale supplied initial vector. vnorm = stdlib${ii}$_snrm2( n, vr, 1_${ik}$ ) call stdlib${ii}$_sscal( n, ( eps3*rootn ) / max( vnorm, nrmsml ), vr,1_${ik}$ ) end if if( rightv ) then ! lu decomposition with partial pivoting of b, replacing zero ! pivots by eps3. do i = 1, n - 1 ei = h( i+1, i ) if( abs( b( i, i ) )=growto*scale )go to 120 ! choose new orthogonal starting vector and try again. temp = eps3 / ( rootn+one ) vr( 1_${ik}$ ) = eps3 do i = 2, n vr( i ) = temp end do vr( n-its+1 ) = vr( n-its+1 ) - eps3*rootn end do ! failure to find eigenvector in n iterations. info = 1_${ik}$ 120 continue ! normalize eigenvector. i = stdlib${ii}$_isamax( n, vr, 1_${ik}$ ) call stdlib${ii}$_sscal( n, one / abs( vr( i ) ), vr, 1_${ik}$ ) else ! complex eigenvalue. if( noinit ) then ! set initial vector. do i = 1, n vr( i ) = eps3 vi( i ) = zero end do else ! scale supplied initial vector. norm = stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vr, 1_${ik}$ ), stdlib${ii}$_snrm2( n, vi, 1_${ik}$ ) ) rec = ( eps3*rootn ) / max( norm, nrmsml ) call stdlib${ii}$_sscal( n, rec, vr, 1_${ik}$ ) call stdlib${ii}$_sscal( n, rec, vi, 1_${ik}$ ) end if if( rightv ) then ! lu decomposition with partial pivoting of b, replacing zero ! pivots by eps3. ! the imaginary part of the (i,j)-th element of u is stored in ! b(j+1,i). b( 2_${ik}$, 1_${ik}$ ) = -wi do i = 2, n b( i+1, 1_${ik}$ ) = zero end do loop_170: do i = 1, n - 1 absbii = stdlib${ii}$_slapy2( b( i, i ), b( i+1, i ) ) ei = h( i+1, i ) if( absbiivcrit ) then rec = one / vmax call stdlib${ii}$_sscal( n, rec, vr, 1_${ik}$ ) call stdlib${ii}$_sscal( n, rec, vi, 1_${ik}$ ) scale = scale*rec vmax = one vcrit = bignum end if xr = vr( i ) xi = vi( i ) if( rightv ) then do j = i + 1, n xr = xr - b( i, j )*vr( j ) + b( j+1, i )*vi( j ) xi = xi - b( i, j )*vi( j ) - b( j+1, i )*vr( j ) end do else do j = 1, i - 1 xr = xr - b( j, i )*vr( j ) + b( i+1, j )*vi( j ) xi = xi - b( j, i )*vi( j ) - b( i+1, j )*vr( j ) end do end if w = abs( b( i, i ) ) + abs( b( i+1, i ) ) if( w>smlnum ) then if( ww*bignum ) then rec = one / w1 call stdlib${ii}$_sscal( n, rec, vr, 1_${ik}$ ) call stdlib${ii}$_sscal( n, rec, vi, 1_${ik}$ ) xr = vr( i ) xi = vi( i ) scale = scale*rec vmax = vmax*rec end if end if ! divide by diagonal element of b. call stdlib${ii}$_sladiv( xr, xi, b( i, i ), b( i+1, i ), vr( i ),vi( i ) ) vmax = max( abs( vr( i ) )+abs( vi( i ) ), vmax ) vcrit = bignum / vmax else do j = 1, n vr( j ) = zero vi( j ) = zero end do vr( i ) = one vi( i ) = one scale = zero vmax = one vcrit = bignum end if end do loop_250 ! test for sufficient growth in the norm of (vr,vi). vnorm = stdlib${ii}$_sasum( n, vr, 1_${ik}$ ) + stdlib${ii}$_sasum( n, vi, 1_${ik}$ ) if( vnorm>=growto*scale )go to 280 ! choose a new orthogonal starting vector and try again. y = eps3 / ( rootn+one ) vr( 1_${ik}$ ) = eps3 vi( 1_${ik}$ ) = zero do i = 2, n vr( i ) = y vi( i ) = zero end do vr( n-its+1 ) = vr( n-its+1 ) - eps3*rootn end do loop_270 ! failure to find eigenvector in n iterations info = 1_${ik}$ 280 continue ! normalize eigenvector. vnorm = zero do i = 1, n vnorm = max( vnorm, abs( vr( i ) )+abs( vi( i ) ) ) end do call stdlib${ii}$_sscal( n, one / vnorm, vr, 1_${ik}$ ) call stdlib${ii}$_sscal( n, one / vnorm, vi, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_slaein pure module subroutine stdlib${ii}$_dlaein( rightv, noinit, n, h, ldh, wr, wi, vr, vi, b,ldb, work, eps3, & !! DLAEIN uses inverse iteration to find a right or left eigenvector !! corresponding to the eigenvalue (WR,WI) of a real upper Hessenberg !! matrix H. smlnum, bignum, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: noinit, rightv integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldh, n real(dp), intent(in) :: bignum, eps3, smlnum, wi, wr ! Array Arguments real(dp), intent(out) :: b(ldb,*), work(*) real(dp), intent(in) :: h(ldh,*) real(dp), intent(inout) :: vi(*), vr(*) ! ===================================================================== ! Parameters real(dp), parameter :: tenth = 1.0e-1_dp ! Local Scalars character :: normin, trans integer(${ik}$) :: i, i1, i2, i3, ierr, its, j real(dp) :: absbii, absbjj, ei, ej, growto, norm, nrmsml, rec, rootn, scale, temp, & vcrit, vmax, vnorm, w, w1, x, xi, xr, y ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! growto is the threshold used in the acceptance test for an ! eigenvector. rootn = sqrt( real( n,KIND=dp) ) growto = tenth / rootn nrmsml = max( one, eps3*rootn )*smlnum ! form b = h - (wr,wi)*i (except that the subdiagonal elements and ! the imaginary parts of the diagonal elements are not stored). do j = 1, n do i = 1, j - 1 b( i, j ) = h( i, j ) end do b( j, j ) = h( j, j ) - wr end do if( wi==zero ) then ! real eigenvalue. if( noinit ) then ! set initial vector. do i = 1, n vr( i ) = eps3 end do else ! scale supplied initial vector. vnorm = stdlib${ii}$_dnrm2( n, vr, 1_${ik}$ ) call stdlib${ii}$_dscal( n, ( eps3*rootn ) / max( vnorm, nrmsml ), vr,1_${ik}$ ) end if if( rightv ) then ! lu decomposition with partial pivoting of b, replacing zero ! pivots by eps3. do i = 1, n - 1 ei = h( i+1, i ) if( abs( b( i, i ) )=growto*scale )go to 120 ! choose new orthogonal starting vector and try again. temp = eps3 / ( rootn+one ) vr( 1_${ik}$ ) = eps3 do i = 2, n vr( i ) = temp end do vr( n-its+1 ) = vr( n-its+1 ) - eps3*rootn end do ! failure to find eigenvector in n iterations. info = 1_${ik}$ 120 continue ! normalize eigenvector. i = stdlib${ii}$_idamax( n, vr, 1_${ik}$ ) call stdlib${ii}$_dscal( n, one / abs( vr( i ) ), vr, 1_${ik}$ ) else ! complex eigenvalue. if( noinit ) then ! set initial vector. do i = 1, n vr( i ) = eps3 vi( i ) = zero end do else ! scale supplied initial vector. norm = stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vr, 1_${ik}$ ), stdlib${ii}$_dnrm2( n, vi, 1_${ik}$ ) ) rec = ( eps3*rootn ) / max( norm, nrmsml ) call stdlib${ii}$_dscal( n, rec, vr, 1_${ik}$ ) call stdlib${ii}$_dscal( n, rec, vi, 1_${ik}$ ) end if if( rightv ) then ! lu decomposition with partial pivoting of b, replacing zero ! pivots by eps3. ! the imaginary part of the (i,j)-th element of u is stored in ! b(j+1,i). b( 2_${ik}$, 1_${ik}$ ) = -wi do i = 2, n b( i+1, 1_${ik}$ ) = zero end do loop_170: do i = 1, n - 1 absbii = stdlib${ii}$_dlapy2( b( i, i ), b( i+1, i ) ) ei = h( i+1, i ) if( absbiivcrit ) then rec = one / vmax call stdlib${ii}$_dscal( n, rec, vr, 1_${ik}$ ) call stdlib${ii}$_dscal( n, rec, vi, 1_${ik}$ ) scale = scale*rec vmax = one vcrit = bignum end if xr = vr( i ) xi = vi( i ) if( rightv ) then do j = i + 1, n xr = xr - b( i, j )*vr( j ) + b( j+1, i )*vi( j ) xi = xi - b( i, j )*vi( j ) - b( j+1, i )*vr( j ) end do else do j = 1, i - 1 xr = xr - b( j, i )*vr( j ) + b( i+1, j )*vi( j ) xi = xi - b( j, i )*vi( j ) - b( i+1, j )*vr( j ) end do end if w = abs( b( i, i ) ) + abs( b( i+1, i ) ) if( w>smlnum ) then if( ww*bignum ) then rec = one / w1 call stdlib${ii}$_dscal( n, rec, vr, 1_${ik}$ ) call stdlib${ii}$_dscal( n, rec, vi, 1_${ik}$ ) xr = vr( i ) xi = vi( i ) scale = scale*rec vmax = vmax*rec end if end if ! divide by diagonal element of b. call stdlib${ii}$_dladiv( xr, xi, b( i, i ), b( i+1, i ), vr( i ),vi( i ) ) vmax = max( abs( vr( i ) )+abs( vi( i ) ), vmax ) vcrit = bignum / vmax else do j = 1, n vr( j ) = zero vi( j ) = zero end do vr( i ) = one vi( i ) = one scale = zero vmax = one vcrit = bignum end if end do loop_250 ! test for sufficient growth in the norm of (vr,vi). vnorm = stdlib${ii}$_dasum( n, vr, 1_${ik}$ ) + stdlib${ii}$_dasum( n, vi, 1_${ik}$ ) if( vnorm>=growto*scale )go to 280 ! choose a new orthogonal starting vector and try again. y = eps3 / ( rootn+one ) vr( 1_${ik}$ ) = eps3 vi( 1_${ik}$ ) = zero do i = 2, n vr( i ) = y vi( i ) = zero end do vr( n-its+1 ) = vr( n-its+1 ) - eps3*rootn end do loop_270 ! failure to find eigenvector in n iterations info = 1_${ik}$ 280 continue ! normalize eigenvector. vnorm = zero do i = 1, n vnorm = max( vnorm, abs( vr( i ) )+abs( vi( i ) ) ) end do call stdlib${ii}$_dscal( n, one / vnorm, vr, 1_${ik}$ ) call stdlib${ii}$_dscal( n, one / vnorm, vi, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_dlaein #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laein( rightv, noinit, n, h, ldh, wr, wi, vr, vi, b,ldb, work, eps3, & !! DLAEIN: uses inverse iteration to find a right or left eigenvector !! corresponding to the eigenvalue (WR,WI) of a real upper Hessenberg !! matrix H. smlnum, bignum, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: noinit, rightv integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldh, n real(${rk}$), intent(in) :: bignum, eps3, smlnum, wi, wr ! Array Arguments real(${rk}$), intent(out) :: b(ldb,*), work(*) real(${rk}$), intent(in) :: h(ldh,*) real(${rk}$), intent(inout) :: vi(*), vr(*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: tenth = 1.0e-1_${rk}$ ! Local Scalars character :: normin, trans integer(${ik}$) :: i, i1, i2, i3, ierr, its, j real(${rk}$) :: absbii, absbjj, ei, ej, growto, norm, nrmsml, rec, rootn, scale, temp, & vcrit, vmax, vnorm, w, w1, x, xi, xr, y ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! growto is the threshold used in the acceptance test for an ! eigenvector. rootn = sqrt( real( n,KIND=${rk}$) ) growto = tenth / rootn nrmsml = max( one, eps3*rootn )*smlnum ! form b = h - (wr,wi)*i (except that the subdiagonal elements and ! the imaginary parts of the diagonal elements are not stored). do j = 1, n do i = 1, j - 1 b( i, j ) = h( i, j ) end do b( j, j ) = h( j, j ) - wr end do if( wi==zero ) then ! real eigenvalue. if( noinit ) then ! set initial vector. do i = 1, n vr( i ) = eps3 end do else ! scale supplied initial vector. vnorm = stdlib${ii}$_${ri}$nrm2( n, vr, 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, ( eps3*rootn ) / max( vnorm, nrmsml ), vr,1_${ik}$ ) end if if( rightv ) then ! lu decomposition with partial pivoting of b, replacing zero ! pivots by eps3. do i = 1, n - 1 ei = h( i+1, i ) if( abs( b( i, i ) )=growto*scale )go to 120 ! choose new orthogonal starting vector and try again. temp = eps3 / ( rootn+one ) vr( 1_${ik}$ ) = eps3 do i = 2, n vr( i ) = temp end do vr( n-its+1 ) = vr( n-its+1 ) - eps3*rootn end do ! failure to find eigenvector in n iterations. info = 1_${ik}$ 120 continue ! normalize eigenvector. i = stdlib${ii}$_i${ri}$amax( n, vr, 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, one / abs( vr( i ) ), vr, 1_${ik}$ ) else ! complex eigenvalue. if( noinit ) then ! set initial vector. do i = 1, n vr( i ) = eps3 vi( i ) = zero end do else ! scale supplied initial vector. norm = stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vr, 1_${ik}$ ), stdlib${ii}$_${ri}$nrm2( n, vi, 1_${ik}$ ) ) rec = ( eps3*rootn ) / max( norm, nrmsml ) call stdlib${ii}$_${ri}$scal( n, rec, vr, 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, rec, vi, 1_${ik}$ ) end if if( rightv ) then ! lu decomposition with partial pivoting of b, replacing zero ! pivots by eps3. ! the imaginary part of the (i,j)-th element of u is stored in ! b(j+1,i). b( 2_${ik}$, 1_${ik}$ ) = -wi do i = 2, n b( i+1, 1_${ik}$ ) = zero end do loop_170: do i = 1, n - 1 absbii = stdlib${ii}$_${ri}$lapy2( b( i, i ), b( i+1, i ) ) ei = h( i+1, i ) if( absbiivcrit ) then rec = one / vmax call stdlib${ii}$_${ri}$scal( n, rec, vr, 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, rec, vi, 1_${ik}$ ) scale = scale*rec vmax = one vcrit = bignum end if xr = vr( i ) xi = vi( i ) if( rightv ) then do j = i + 1, n xr = xr - b( i, j )*vr( j ) + b( j+1, i )*vi( j ) xi = xi - b( i, j )*vi( j ) - b( j+1, i )*vr( j ) end do else do j = 1, i - 1 xr = xr - b( j, i )*vr( j ) + b( i+1, j )*vi( j ) xi = xi - b( j, i )*vi( j ) - b( i+1, j )*vr( j ) end do end if w = abs( b( i, i ) ) + abs( b( i+1, i ) ) if( w>smlnum ) then if( ww*bignum ) then rec = one / w1 call stdlib${ii}$_${ri}$scal( n, rec, vr, 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, rec, vi, 1_${ik}$ ) xr = vr( i ) xi = vi( i ) scale = scale*rec vmax = vmax*rec end if end if ! divide by diagonal element of b. call stdlib${ii}$_${ri}$ladiv( xr, xi, b( i, i ), b( i+1, i ), vr( i ),vi( i ) ) vmax = max( abs( vr( i ) )+abs( vi( i ) ), vmax ) vcrit = bignum / vmax else do j = 1, n vr( j ) = zero vi( j ) = zero end do vr( i ) = one vi( i ) = one scale = zero vmax = one vcrit = bignum end if end do loop_250 ! test for sufficient growth in the norm of (vr,vi). vnorm = stdlib${ii}$_${ri}$asum( n, vr, 1_${ik}$ ) + stdlib${ii}$_${ri}$asum( n, vi, 1_${ik}$ ) if( vnorm>=growto*scale )go to 280 ! choose a new orthogonal starting vector and try again. y = eps3 / ( rootn+one ) vr( 1_${ik}$ ) = eps3 vi( 1_${ik}$ ) = zero do i = 2, n vr( i ) = y vi( i ) = zero end do vr( n-its+1 ) = vr( n-its+1 ) - eps3*rootn end do loop_270 ! failure to find eigenvector in n iterations info = 1_${ik}$ 280 continue ! normalize eigenvector. vnorm = zero do i = 1, n vnorm = max( vnorm, abs( vr( i ) )+abs( vi( i ) ) ) end do call stdlib${ii}$_${ri}$scal( n, one / vnorm, vr, 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, one / vnorm, vi, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ri}$laein #:endif #:endfor pure module subroutine stdlib${ii}$_claein( rightv, noinit, n, h, ldh, w, v, b, ldb, rwork,eps3, smlnum, & !! CLAEIN uses inverse iteration to find a right or left eigenvector !! corresponding to the eigenvalue W of a complex upper Hessenberg !! matrix H. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: noinit, rightv integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldh, n real(sp), intent(in) :: eps3, smlnum complex(sp), intent(in) :: w ! Array Arguments real(sp), intent(out) :: rwork(*) complex(sp), intent(out) :: b(ldb,*) complex(sp), intent(in) :: h(ldh,*) complex(sp), intent(inout) :: v(*) ! ===================================================================== ! Parameters real(sp), parameter :: tenth = 1.0e-1_sp ! Local Scalars character :: normin, trans integer(${ik}$) :: i, ierr, its, j real(sp) :: growto, nrmsml, rootn, rtemp, scale, vnorm complex(sp) :: cdum, ei, ej, temp, x ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! growto is the threshold used in the acceptance test for an ! eigenvector. rootn = sqrt( real( n,KIND=sp) ) growto = tenth / rootn nrmsml = max( one, eps3*rootn )*smlnum ! form b = h - w*i (except that the subdiagonal elements are not ! stored). do j = 1, n do i = 1, j - 1 b( i, j ) = h( i, j ) end do b( j, j ) = h( j, j ) - w end do if( noinit ) then ! initialize v. do i = 1, n v( i ) = eps3 end do else ! scale supplied initial vector. vnorm = stdlib${ii}$_scnrm2( n, v, 1_${ik}$ ) call stdlib${ii}$_csscal( n, ( eps3*rootn ) / max( vnorm, nrmsml ), v, 1_${ik}$ ) end if if( rightv ) then ! lu decomposition with partial pivoting of b, replacing czero ! pivots by eps3. do i = 1, n - 1 ei = h( i+1, i ) if( cabs1( b( i, i ) )=growto*scale )go to 120 ! choose new orthogonal starting vector and try again. rtemp = eps3 / ( rootn+one ) v( 1_${ik}$ ) = eps3 do i = 2, n v( i ) = rtemp end do v( n-its+1 ) = v( n-its+1 ) - eps3*rootn end do ! failure to find eigenvector in n iterations. info = 1_${ik}$ 120 continue ! normalize eigenvector. i = stdlib${ii}$_icamax( n, v, 1_${ik}$ ) call stdlib${ii}$_csscal( n, one / cabs1( v( i ) ), v, 1_${ik}$ ) return end subroutine stdlib${ii}$_claein pure module subroutine stdlib${ii}$_zlaein( rightv, noinit, n, h, ldh, w, v, b, ldb, rwork,eps3, smlnum, & !! ZLAEIN uses inverse iteration to find a right or left eigenvector !! corresponding to the eigenvalue W of a complex upper Hessenberg !! matrix H. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: noinit, rightv integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldh, n real(dp), intent(in) :: eps3, smlnum complex(dp), intent(in) :: w ! Array Arguments real(dp), intent(out) :: rwork(*) complex(dp), intent(out) :: b(ldb,*) complex(dp), intent(in) :: h(ldh,*) complex(dp), intent(inout) :: v(*) ! ===================================================================== ! Parameters real(dp), parameter :: tenth = 1.0e-1_dp ! Local Scalars character :: normin, trans integer(${ik}$) :: i, ierr, its, j real(dp) :: growto, nrmsml, rootn, rtemp, scale, vnorm complex(dp) :: cdum, ei, ej, temp, x ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! growto is the threshold used in the acceptance test for an ! eigenvector. rootn = sqrt( real( n,KIND=dp) ) growto = tenth / rootn nrmsml = max( one, eps3*rootn )*smlnum ! form b = h - w*i (except that the subdiagonal elements are not ! stored). do j = 1, n do i = 1, j - 1 b( i, j ) = h( i, j ) end do b( j, j ) = h( j, j ) - w end do if( noinit ) then ! initialize v. do i = 1, n v( i ) = eps3 end do else ! scale supplied initial vector. vnorm = stdlib${ii}$_dznrm2( n, v, 1_${ik}$ ) call stdlib${ii}$_zdscal( n, ( eps3*rootn ) / max( vnorm, nrmsml ), v, 1_${ik}$ ) end if if( rightv ) then ! lu decomposition with partial pivoting of b, replacing czero ! pivots by eps3. do i = 1, n - 1 ei = h( i+1, i ) if( cabs1( b( i, i ) )=growto*scale )go to 120 ! choose new orthogonal starting vector and try again. rtemp = eps3 / ( rootn+one ) v( 1_${ik}$ ) = eps3 do i = 2, n v( i ) = rtemp end do v( n-its+1 ) = v( n-its+1 ) - eps3*rootn end do ! failure to find eigenvector in n iterations. info = 1_${ik}$ 120 continue ! normalize eigenvector. i = stdlib${ii}$_izamax( n, v, 1_${ik}$ ) call stdlib${ii}$_zdscal( n, one / cabs1( v( i ) ), v, 1_${ik}$ ) return end subroutine stdlib${ii}$_zlaein #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laein( rightv, noinit, n, h, ldh, w, v, b, ldb, rwork,eps3, smlnum, & !! ZLAEIN: uses inverse iteration to find a right or left eigenvector !! corresponding to the eigenvalue W of a complex upper Hessenberg !! matrix H. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: noinit, rightv integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldh, n real(${ck}$), intent(in) :: eps3, smlnum complex(${ck}$), intent(in) :: w ! Array Arguments real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(out) :: b(ldb,*) complex(${ck}$), intent(in) :: h(ldh,*) complex(${ck}$), intent(inout) :: v(*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: tenth = 1.0e-1_${ck}$ ! Local Scalars character :: normin, trans integer(${ik}$) :: i, ierr, its, j real(${ck}$) :: growto, nrmsml, rootn, rtemp, scale, vnorm complex(${ck}$) :: cdum, ei, ej, temp, x ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements info = 0_${ik}$ ! growto is the threshold used in the acceptance test for an ! eigenvector. rootn = sqrt( real( n,KIND=${ck}$) ) growto = tenth / rootn nrmsml = max( one, eps3*rootn )*smlnum ! form b = h - w*i (except that the subdiagonal elements are not ! stored). do j = 1, n do i = 1, j - 1 b( i, j ) = h( i, j ) end do b( j, j ) = h( j, j ) - w end do if( noinit ) then ! initialize v. do i = 1, n v( i ) = eps3 end do else ! scale supplied initial vector. vnorm = stdlib${ii}$_${c2ri(ci)}$znrm2( n, v, 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( n, ( eps3*rootn ) / max( vnorm, nrmsml ), v, 1_${ik}$ ) end if if( rightv ) then ! lu decomposition with partial pivoting of b, replacing czero ! pivots by eps3. do i = 1, n - 1 ei = h( i+1, i ) if( cabs1( b( i, i ) )=growto*scale )go to 120 ! choose new orthogonal starting vector and try again. rtemp = eps3 / ( rootn+one ) v( 1_${ik}$ ) = eps3 do i = 2, n v( i ) = rtemp end do v( n-its+1 ) = v( n-its+1 ) - eps3*rootn end do ! failure to find eigenvector in n iterations. info = 1_${ik}$ 120 continue ! normalize eigenvector. i = stdlib${ii}$_i${ci}$amax( n, v, 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( n, one / cabs1( v( i ) ), v, 1_${ik}$ ) return end subroutine stdlib${ii}$_${ci}$laein #:endif #:endfor #:endfor end submodule stdlib_lapack_eigv_gen2 fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_eigv_svd_bidiag_dc.fypp0000664000175000017500000125121415135654166027545 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_eigv_svd_bidiag_dc implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slasd0( n, sqre, d, e, u, ldu, vt, ldvt, smlsiz, iwork,work, info ) !! Using a divide and conquer approach, SLASD0: computes the singular !! value decomposition (SVD) of a real upper bidiagonal N-by-M !! matrix B with diagonal D and offdiagonal E, where M = N + SQRE. !! The algorithm computes orthogonal matrices U and VT such that !! B = U * S * VT. The singular values S are overwritten on D. !! A related subroutine, SLASDA, computes only the singular values, !! and optionally, the singular vectors in compact form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu, ldvt, n, smlsiz, sqre ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: d(*), e(*) real(sp), intent(out) :: u(ldu,*), vt(ldvt,*), work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, i1, ic, idxq, idxqc, im1, inode, itemp, iwk, j, lf, ll, lvl, m, ncc,& nd, ndb1, ndiml, ndimr, nl, nlf, nlp1, nlvl, nr, nrf, nrp1, sqrei real(sp) :: alpha, beta ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -2_${ik}$ end if m = n + sqre if( ldu1_${ik}$ ) ) then info = -2_${ik}$ end if m = n + sqre if( ldu1_${ik}$ ) ) then info = -2_${ik}$ end if m = n + sqre if( ldu1_${ik}$ ) ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SLASD1', -info ) return end if n = nl + nr + 1_${ik}$ m = n + sqre ! the following values are for bookkeeping purposes only. they are ! integer pointers which indicate the portion of the workspace ! used by a particular array in stdlib${ii}$_slasd2 and stdlib${ii}$_slasd3. ldu2 = n ldvt2 = m iz = 1_${ik}$ isigma = iz + m iu2 = isigma + n ivt2 = iu2 + ldu2*n iq = ivt2 + ldvt2*m idx = 1_${ik}$ idxc = idx + n coltyp = idxc + n idxp = coltyp + n ! scale. orgnrm = max( abs( alpha ), abs( beta ) ) d( nl+1 ) = zero do i = 1, n if( abs( d( i ) )>orgnrm ) then orgnrm = abs( d( i ) ) end if end do call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) alpha = alpha / orgnrm beta = beta / orgnrm ! deflate singular values. call stdlib${ii}$_slasd2( nl, nr, sqre, k, d, work( iz ), alpha, beta, u, ldu,vt, ldvt, work(& isigma ), work( iu2 ), ldu2,work( ivt2 ), ldvt2, iwork( idxp ), iwork( idx ),iwork( & idxc ), idxq, iwork( coltyp ), info ) ! solve secular equation and update singular vectors. ldq = k call stdlib${ii}$_slasd3( nl, nr, sqre, k, d, work( iq ), ldq, work( isigma ),u, ldu, work( & iu2 ), ldu2, vt, ldvt, work( ivt2 ),ldvt2, iwork( idxc ), iwork( coltyp ), work( iz ),& info ) ! report the possible convergence failure. if( info/=0_${ik}$ ) then return end if ! unscale. call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) ! prepare the idxq sorting permutation. n1 = k n2 = n - k call stdlib${ii}$_slamrg( n1, n2, d, 1_${ik}$, -1_${ik}$, idxq ) return end subroutine stdlib${ii}$_slasd1 pure module subroutine stdlib${ii}$_dlasd1( nl, nr, sqre, d, alpha, beta, u, ldu, vt, ldvt,idxq, iwork, & !! DLASD1 computes the SVD of an upper bidiagonal N-by-M matrix B, !! where N = NL + NR + 1 and M = N + SQRE. DLASD1 is called from DLASD0. !! A related subroutine DLASD7 handles the case in which the singular !! values (and the singular vectors in factored form) are desired. !! DLASD1 computes the SVD as follows: !! ( D1(in) 0 0 0 ) !! B = U(in) * ( Z1**T a Z2**T b ) * VT(in) !! ( 0 0 D2(in) 0 ) !! = U(out) * ( D(out) 0) * VT(out) !! where Z**T = (Z1**T a Z2**T b) = u**T VT**T, and u is a vector of dimension M !! with ALPHA and BETA in the NL+1 and NL+2 th entries and zeros !! elsewhere; and the entry b is empty if SQRE = 0. !! The left singular vectors of the original matrix are stored in U, and !! the transpose of the right singular vectors are stored in VT, and the !! singular values are in D. The algorithm consists of three stages: !! The first stage consists of deflating the size of the problem !! when there are multiple singular values or when there are zeros in !! the Z vector. For each such occurrence the dimension of the !! secular equation problem is reduced by one. This stage is !! performed by the routine DLASD2. !! The second stage consists of calculating the updated !! singular values. This is done by finding the square roots of the !! roots of the secular equation via the routine DLASD4 (as called !! by DLASD3). This routine also calculates the singular vectors of !! the current problem. !! The final stage consists of computing the updated singular vectors !! directly using the updated singular values. The singular vectors !! for the current problem are multiplied with the singular vectors !! from the overall problem. work, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu, ldvt, nl, nr, sqre real(dp), intent(inout) :: alpha, beta ! Array Arguments integer(${ik}$), intent(inout) :: idxq(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: d(*), u(ldu,*), vt(ldvt,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: coltyp, i, idx, idxc, idxp, iq, isigma, iu2, ivt2, iz, k, ldq, ldu2, & ldvt2, m, n, n1, n2 real(dp) :: orgnrm ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( nl<1_${ik}$ ) then info = -1_${ik}$ else if( nr<1_${ik}$ ) then info = -2_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLASD1', -info ) return end if n = nl + nr + 1_${ik}$ m = n + sqre ! the following values are for bookkeeping purposes only. they are ! integer pointers which indicate the portion of the workspace ! used by a particular array in stdlib${ii}$_dlasd2 and stdlib${ii}$_dlasd3. ldu2 = n ldvt2 = m iz = 1_${ik}$ isigma = iz + m iu2 = isigma + n ivt2 = iu2 + ldu2*n iq = ivt2 + ldvt2*m idx = 1_${ik}$ idxc = idx + n coltyp = idxc + n idxp = coltyp + n ! scale. orgnrm = max( abs( alpha ), abs( beta ) ) d( nl+1 ) = zero do i = 1, n if( abs( d( i ) )>orgnrm ) then orgnrm = abs( d( i ) ) end if end do call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) alpha = alpha / orgnrm beta = beta / orgnrm ! deflate singular values. call stdlib${ii}$_dlasd2( nl, nr, sqre, k, d, work( iz ), alpha, beta, u, ldu,vt, ldvt, work(& isigma ), work( iu2 ), ldu2,work( ivt2 ), ldvt2, iwork( idxp ), iwork( idx ),iwork( & idxc ), idxq, iwork( coltyp ), info ) ! solve secular equation and update singular vectors. ldq = k call stdlib${ii}$_dlasd3( nl, nr, sqre, k, d, work( iq ), ldq, work( isigma ),u, ldu, work( & iu2 ), ldu2, vt, ldvt, work( ivt2 ),ldvt2, iwork( idxc ), iwork( coltyp ), work( iz ),& info ) ! report the convergence failure. if( info/=0_${ik}$ ) then return end if ! unscale. call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) ! prepare the idxq sorting permutation. n1 = k n2 = n - k call stdlib${ii}$_dlamrg( n1, n2, d, 1_${ik}$, -1_${ik}$, idxq ) return end subroutine stdlib${ii}$_dlasd1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasd1( nl, nr, sqre, d, alpha, beta, u, ldu, vt, ldvt,idxq, iwork, & !! DLASD1: computes the SVD of an upper bidiagonal N-by-M matrix B, !! where N = NL + NR + 1 and M = N + SQRE. DLASD1 is called from DLASD0. !! A related subroutine DLASD7 handles the case in which the singular !! values (and the singular vectors in factored form) are desired. !! DLASD1 computes the SVD as follows: !! ( D1(in) 0 0 0 ) !! B = U(in) * ( Z1**T a Z2**T b ) * VT(in) !! ( 0 0 D2(in) 0 ) !! = U(out) * ( D(out) 0) * VT(out) !! where Z**T = (Z1**T a Z2**T b) = u**T VT**T, and u is a vector of dimension M !! with ALPHA and BETA in the NL+1 and NL+2 th entries and zeros !! elsewhere; and the entry b is empty if SQRE = 0. !! The left singular vectors of the original matrix are stored in U, and !! the transpose of the right singular vectors are stored in VT, and the !! singular values are in D. The algorithm consists of three stages: !! The first stage consists of deflating the size of the problem !! when there are multiple singular values or when there are zeros in !! the Z vector. For each such occurrence the dimension of the !! secular equation problem is reduced by one. This stage is !! performed by the routine DLASD2. !! The second stage consists of calculating the updated !! singular values. This is done by finding the square roots of the !! roots of the secular equation via the routine DLASD4 (as called !! by DLASD3). This routine also calculates the singular vectors of !! the current problem. !! The final stage consists of computing the updated singular vectors !! directly using the updated singular values. The singular vectors !! for the current problem are multiplied with the singular vectors !! from the overall problem. work, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldu, ldvt, nl, nr, sqre real(${rk}$), intent(inout) :: alpha, beta ! Array Arguments integer(${ik}$), intent(inout) :: idxq(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: d(*), u(ldu,*), vt(ldvt,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: coltyp, i, idx, idxc, idxp, iq, isigma, iu2, ivt2, iz, k, ldq, ldu2, & ldvt2, m, n, n1, n2 real(${rk}$) :: orgnrm ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( nl<1_${ik}$ ) then info = -1_${ik}$ else if( nr<1_${ik}$ ) then info = -2_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLASD1', -info ) return end if n = nl + nr + 1_${ik}$ m = n + sqre ! the following values are for bookkeeping purposes only. they are ! integer pointers which indicate the portion of the workspace ! used by a particular array in stdlib${ii}$_${ri}$lasd2 and stdlib${ii}$_${ri}$lasd3. ldu2 = n ldvt2 = m iz = 1_${ik}$ isigma = iz + m iu2 = isigma + n ivt2 = iu2 + ldu2*n iq = ivt2 + ldvt2*m idx = 1_${ik}$ idxc = idx + n coltyp = idxc + n idxp = coltyp + n ! scale. orgnrm = max( abs( alpha ), abs( beta ) ) d( nl+1 ) = zero do i = 1, n if( abs( d( i ) )>orgnrm ) then orgnrm = abs( d( i ) ) end if end do call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) alpha = alpha / orgnrm beta = beta / orgnrm ! deflate singular values. call stdlib${ii}$_${ri}$lasd2( nl, nr, sqre, k, d, work( iz ), alpha, beta, u, ldu,vt, ldvt, work(& isigma ), work( iu2 ), ldu2,work( ivt2 ), ldvt2, iwork( idxp ), iwork( idx ),iwork( & idxc ), idxq, iwork( coltyp ), info ) ! solve secular equation and update singular vectors. ldq = k call stdlib${ii}$_${ri}$lasd3( nl, nr, sqre, k, d, work( iq ), ldq, work( isigma ),u, ldu, work( & iu2 ), ldu2, vt, ldvt, work( ivt2 ),ldvt2, iwork( idxc ), iwork( coltyp ), work( iz ),& info ) ! report the convergence failure. if( info/=0_${ik}$ ) then return end if ! unscale. call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) ! prepare the idxq sorting permutation. n1 = k n2 = n - k call stdlib${ii}$_${ri}$lamrg( n1, n2, d, 1_${ik}$, -1_${ik}$, idxq ) return end subroutine stdlib${ii}$_${ri}$lasd1 #:endif #:endfor pure module subroutine stdlib${ii}$_slasd2( nl, nr, sqre, k, d, z, alpha, beta, u, ldu, vt,ldvt, dsigma, & !! SLASD2 merges the two sets of singular values together into a single !! sorted set. Then it tries to deflate the size of the problem. !! There are two ways in which deflation can occur: when two or more !! singular values are close together or if there is a tiny entry in the !! Z vector. For each such occurrence the order of the related secular !! equation problem is reduced by one. !! SLASD2 is called from SLASD1. u2, ldu2, vt2, ldvt2, idxp, idx,idxc, idxq, coltyp, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, k integer(${ik}$), intent(in) :: ldu, ldu2, ldvt, ldvt2, nl, nr, sqre real(sp), intent(in) :: alpha, beta ! Array Arguments integer(${ik}$), intent(out) :: coltyp(*), idx(*), idxc(*), idxp(*) integer(${ik}$), intent(inout) :: idxq(*) real(sp), intent(inout) :: d(*), u(ldu,*), vt(ldvt,*) real(sp), intent(out) :: dsigma(*), u2(ldu2,*), vt2(ldvt2,*), z(*) ! ===================================================================== ! Local Arrays integer(${ik}$) :: ctot(4_${ik}$), psm(4_${ik}$) ! Local Scalars integer(${ik}$) :: ct, i, idxi, idxj, idxjp, j, jp, jprev, k2, m, n, nlp1, nlp2 real(sp) :: c, eps, hlftol, s, tau, tol, z1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( nl<1_${ik}$ ) then info = -1_${ik}$ else if( nr<1_${ik}$ ) then info = -2_${ik}$ else if( ( sqre/=1_${ik}$ ) .and. ( sqre/=0_${ik}$ ) ) then info = -3_${ik}$ end if n = nl + nr + 1_${ik}$ m = n + sqre if( ldun )go to 110 if( abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ idxp( k2 ) = j coltyp( j ) = 4_${ik}$ else ! check if singular values are close enough to allow deflation. if( abs( d( j )-d( jprev ) )<=tol ) then ! deflation is possible. s = z( jprev ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_slapy2( c, s ) c = c / tau s = -s / tau z( j ) = tau z( jprev ) = zero ! apply back the givens rotation to the left and right ! singular vector matrices. idxjp = idxq( idx( jprev )+1_${ik}$ ) idxj = idxq( idx( j )+1_${ik}$ ) if( idxjp<=nlp1 ) then idxjp = idxjp - 1_${ik}$ end if if( idxj<=nlp1 ) then idxj = idxj - 1_${ik}$ end if call stdlib${ii}$_srot( n, u( 1_${ik}$, idxjp ), 1_${ik}$, u( 1_${ik}$, idxj ), 1_${ik}$, c, s ) call stdlib${ii}$_srot( m, vt( idxjp, 1_${ik}$ ), ldvt, vt( idxj, 1_${ik}$ ), ldvt, c,s ) if( coltyp( j )/=coltyp( jprev ) ) then coltyp( j ) = 3_${ik}$ end if coltyp( jprev ) = 4_${ik}$ k2 = k2 - 1_${ik}$ idxp( k2 ) = jprev jprev = j else k = k + 1_${ik}$ u2( k, 1_${ik}$ ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev jprev = j end if end if go to 100 110 continue ! record the last singular value. k = k + 1_${ik}$ u2( k, 1_${ik}$ ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev 120 continue ! count up the total number of the various types of columns, then ! form a permutation which positions the four column types into ! four groups of uniform structure (although one or more of these ! groups may be empty). do j = 1, 4 ctot( j ) = 0_${ik}$ end do do j = 2, n ct = coltyp( j ) ctot( ct ) = ctot( ct ) + 1_${ik}$ end do ! psm(*) = position in submatrix (of types 1 through 4) psm( 1_${ik}$ ) = 2_${ik}$ psm( 2_${ik}$ ) = 2_${ik}$ + ctot( 1_${ik}$ ) psm( 3_${ik}$ ) = psm( 2_${ik}$ ) + ctot( 2_${ik}$ ) psm( 4_${ik}$ ) = psm( 3_${ik}$ ) + ctot( 3_${ik}$ ) ! fill out the idxc array so that the permutation which it induces ! will place all type-1 columns first, all type-2 columns next, ! then all type-3's, and finally all type-4's, starting from the ! second column. this applies similarly to the rows of vt. do j = 2, n jp = idxp( j ) ct = coltyp( jp ) idxc( psm( ct ) ) = j psm( ct ) = psm( ct ) + 1_${ik}$ end do ! sort the singular values and corresponding singular vectors into ! dsigma, u2, and vt2 respectively. the singular values/vectors ! which were not deflated go into the first k slots of dsigma, u2, ! and vt2 respectively, while those which were deflated go into the ! last n - k slots, except that the first column/row will be treated ! separately. do j = 2, n jp = idxp( j ) dsigma( j ) = d( jp ) idxj = idxq( idx( idxp( idxc( j ) ) )+1_${ik}$ ) if( idxj<=nlp1 ) then idxj = idxj - 1_${ik}$ end if call stdlib${ii}$_scopy( n, u( 1_${ik}$, idxj ), 1_${ik}$, u2( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_scopy( m, vt( idxj, 1_${ik}$ ), ldvt, vt2( j, 1_${ik}$ ), ldvt2 ) end do ! determine dsigma(1), dsigma(2) and z(1) dsigma( 1_${ik}$ ) = zero hlftol = tol / two if( abs( dsigma( 2_${ik}$ ) )<=hlftol )dsigma( 2_${ik}$ ) = hlftol if( m>n ) then z( 1_${ik}$ ) = stdlib${ii}$_slapy2( z1, z( m ) ) if( z( 1_${ik}$ )<=tol ) then c = one s = zero z( 1_${ik}$ ) = tol else c = z1 / z( 1_${ik}$ ) s = z( m ) / z( 1_${ik}$ ) end if else if( abs( z1 )<=tol ) then z( 1_${ik}$ ) = tol else z( 1_${ik}$ ) = z1 end if end if ! move the rest of the updating row to z. call stdlib${ii}$_scopy( k-1, u2( 2_${ik}$, 1_${ik}$ ), 1_${ik}$, z( 2_${ik}$ ), 1_${ik}$ ) ! determine the first column of u2, the first row of vt2 and the ! last row of vt. call stdlib${ii}$_slaset( 'A', n, 1_${ik}$, zero, zero, u2, ldu2 ) u2( nlp1, 1_${ik}$ ) = one if( m>n ) then do i = 1, nlp1 vt( m, i ) = -s*vt( nlp1, i ) vt2( 1_${ik}$, i ) = c*vt( nlp1, i ) end do do i = nlp2, m vt2( 1_${ik}$, i ) = s*vt( m, i ) vt( m, i ) = c*vt( m, i ) end do else call stdlib${ii}$_scopy( m, vt( nlp1, 1_${ik}$ ), ldvt, vt2( 1_${ik}$, 1_${ik}$ ), ldvt2 ) end if if( m>n ) then call stdlib${ii}$_scopy( m, vt( m, 1_${ik}$ ), ldvt, vt2( m, 1_${ik}$ ), ldvt2 ) end if ! the deflated singular values and their corresponding vectors go ! into the back of d, u, and v respectively. if( n>k ) then call stdlib${ii}$_scopy( n-k, dsigma( k+1 ), 1_${ik}$, d( k+1 ), 1_${ik}$ ) call stdlib${ii}$_slacpy( 'A', n, n-k, u2( 1_${ik}$, k+1 ), ldu2, u( 1_${ik}$, k+1 ),ldu ) call stdlib${ii}$_slacpy( 'A', n-k, m, vt2( k+1, 1_${ik}$ ), ldvt2, vt( k+1, 1_${ik}$ ),ldvt ) end if ! copy ctot into coltyp for referencing in stdlib${ii}$_slasd3. do j = 1, 4 coltyp( j ) = ctot( j ) end do return end subroutine stdlib${ii}$_slasd2 pure module subroutine stdlib${ii}$_dlasd2( nl, nr, sqre, k, d, z, alpha, beta, u, ldu, vt,ldvt, dsigma, & !! DLASD2 merges the two sets of singular values together into a single !! sorted set. Then it tries to deflate the size of the problem. !! There are two ways in which deflation can occur: when two or more !! singular values are close together or if there is a tiny entry in the !! Z vector. For each such occurrence the order of the related secular !! equation problem is reduced by one. !! DLASD2 is called from DLASD1. u2, ldu2, vt2, ldvt2, idxp, idx,idxc, idxq, coltyp, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, k integer(${ik}$), intent(in) :: ldu, ldu2, ldvt, ldvt2, nl, nr, sqre real(dp), intent(in) :: alpha, beta ! Array Arguments integer(${ik}$), intent(out) :: coltyp(*), idx(*), idxc(*), idxp(*) integer(${ik}$), intent(inout) :: idxq(*) real(dp), intent(inout) :: d(*), u(ldu,*), vt(ldvt,*) real(dp), intent(out) :: dsigma(*), u2(ldu2,*), vt2(ldvt2,*), z(*) ! ===================================================================== ! Local Arrays integer(${ik}$) :: ctot(4_${ik}$), psm(4_${ik}$) ! Local Scalars integer(${ik}$) :: ct, i, idxi, idxj, idxjp, j, jp, jprev, k2, m, n, nlp1, nlp2 real(dp) :: c, eps, hlftol, s, tau, tol, z1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( nl<1_${ik}$ ) then info = -1_${ik}$ else if( nr<1_${ik}$ ) then info = -2_${ik}$ else if( ( sqre/=1_${ik}$ ) .and. ( sqre/=0_${ik}$ ) ) then info = -3_${ik}$ end if n = nl + nr + 1_${ik}$ m = n + sqre if( ldun )go to 110 if( abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ idxp( k2 ) = j coltyp( j ) = 4_${ik}$ else ! check if singular values are close enough to allow deflation. if( abs( d( j )-d( jprev ) )<=tol ) then ! deflation is possible. s = z( jprev ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_dlapy2( c, s ) c = c / tau s = -s / tau z( j ) = tau z( jprev ) = zero ! apply back the givens rotation to the left and right ! singular vector matrices. idxjp = idxq( idx( jprev )+1_${ik}$ ) idxj = idxq( idx( j )+1_${ik}$ ) if( idxjp<=nlp1 ) then idxjp = idxjp - 1_${ik}$ end if if( idxj<=nlp1 ) then idxj = idxj - 1_${ik}$ end if call stdlib${ii}$_drot( n, u( 1_${ik}$, idxjp ), 1_${ik}$, u( 1_${ik}$, idxj ), 1_${ik}$, c, s ) call stdlib${ii}$_drot( m, vt( idxjp, 1_${ik}$ ), ldvt, vt( idxj, 1_${ik}$ ), ldvt, c,s ) if( coltyp( j )/=coltyp( jprev ) ) then coltyp( j ) = 3_${ik}$ end if coltyp( jprev ) = 4_${ik}$ k2 = k2 - 1_${ik}$ idxp( k2 ) = jprev jprev = j else k = k + 1_${ik}$ u2( k, 1_${ik}$ ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev jprev = j end if end if go to 100 110 continue ! record the last singular value. k = k + 1_${ik}$ u2( k, 1_${ik}$ ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev 120 continue ! count up the total number of the various types of columns, then ! form a permutation which positions the four column types into ! four groups of uniform structure (although one or more of these ! groups may be empty). do j = 1, 4 ctot( j ) = 0_${ik}$ end do do j = 2, n ct = coltyp( j ) ctot( ct ) = ctot( ct ) + 1_${ik}$ end do ! psm(*) = position in submatrix (of types 1 through 4) psm( 1_${ik}$ ) = 2_${ik}$ psm( 2_${ik}$ ) = 2_${ik}$ + ctot( 1_${ik}$ ) psm( 3_${ik}$ ) = psm( 2_${ik}$ ) + ctot( 2_${ik}$ ) psm( 4_${ik}$ ) = psm( 3_${ik}$ ) + ctot( 3_${ik}$ ) ! fill out the idxc array so that the permutation which it induces ! will place all type-1 columns first, all type-2 columns next, ! then all type-3's, and finally all type-4's, starting from the ! second column. this applies similarly to the rows of vt. do j = 2, n jp = idxp( j ) ct = coltyp( jp ) idxc( psm( ct ) ) = j psm( ct ) = psm( ct ) + 1_${ik}$ end do ! sort the singular values and corresponding singular vectors into ! dsigma, u2, and vt2 respectively. the singular values/vectors ! which were not deflated go into the first k slots of dsigma, u2, ! and vt2 respectively, while those which were deflated go into the ! last n - k slots, except that the first column/row will be treated ! separately. do j = 2, n jp = idxp( j ) dsigma( j ) = d( jp ) idxj = idxq( idx( idxp( idxc( j ) ) )+1_${ik}$ ) if( idxj<=nlp1 ) then idxj = idxj - 1_${ik}$ end if call stdlib${ii}$_dcopy( n, u( 1_${ik}$, idxj ), 1_${ik}$, u2( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_dcopy( m, vt( idxj, 1_${ik}$ ), ldvt, vt2( j, 1_${ik}$ ), ldvt2 ) end do ! determine dsigma(1), dsigma(2) and z(1) dsigma( 1_${ik}$ ) = zero hlftol = tol / two if( abs( dsigma( 2_${ik}$ ) )<=hlftol )dsigma( 2_${ik}$ ) = hlftol if( m>n ) then z( 1_${ik}$ ) = stdlib${ii}$_dlapy2( z1, z( m ) ) if( z( 1_${ik}$ )<=tol ) then c = one s = zero z( 1_${ik}$ ) = tol else c = z1 / z( 1_${ik}$ ) s = z( m ) / z( 1_${ik}$ ) end if else if( abs( z1 )<=tol ) then z( 1_${ik}$ ) = tol else z( 1_${ik}$ ) = z1 end if end if ! move the rest of the updating row to z. call stdlib${ii}$_dcopy( k-1, u2( 2_${ik}$, 1_${ik}$ ), 1_${ik}$, z( 2_${ik}$ ), 1_${ik}$ ) ! determine the first column of u2, the first row of vt2 and the ! last row of vt. call stdlib${ii}$_dlaset( 'A', n, 1_${ik}$, zero, zero, u2, ldu2 ) u2( nlp1, 1_${ik}$ ) = one if( m>n ) then do i = 1, nlp1 vt( m, i ) = -s*vt( nlp1, i ) vt2( 1_${ik}$, i ) = c*vt( nlp1, i ) end do do i = nlp2, m vt2( 1_${ik}$, i ) = s*vt( m, i ) vt( m, i ) = c*vt( m, i ) end do else call stdlib${ii}$_dcopy( m, vt( nlp1, 1_${ik}$ ), ldvt, vt2( 1_${ik}$, 1_${ik}$ ), ldvt2 ) end if if( m>n ) then call stdlib${ii}$_dcopy( m, vt( m, 1_${ik}$ ), ldvt, vt2( m, 1_${ik}$ ), ldvt2 ) end if ! the deflated singular values and their corresponding vectors go ! into the back of d, u, and v respectively. if( n>k ) then call stdlib${ii}$_dcopy( n-k, dsigma( k+1 ), 1_${ik}$, d( k+1 ), 1_${ik}$ ) call stdlib${ii}$_dlacpy( 'A', n, n-k, u2( 1_${ik}$, k+1 ), ldu2, u( 1_${ik}$, k+1 ),ldu ) call stdlib${ii}$_dlacpy( 'A', n-k, m, vt2( k+1, 1_${ik}$ ), ldvt2, vt( k+1, 1_${ik}$ ),ldvt ) end if ! copy ctot into coltyp for referencing in stdlib${ii}$_dlasd3. do j = 1, 4 coltyp( j ) = ctot( j ) end do return end subroutine stdlib${ii}$_dlasd2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasd2( nl, nr, sqre, k, d, z, alpha, beta, u, ldu, vt,ldvt, dsigma, & !! DLASD2: merges the two sets of singular values together into a single !! sorted set. Then it tries to deflate the size of the problem. !! There are two ways in which deflation can occur: when two or more !! singular values are close together or if there is a tiny entry in the !! Z vector. For each such occurrence the order of the related secular !! equation problem is reduced by one. !! DLASD2 is called from DLASD1. u2, ldu2, vt2, ldvt2, idxp, idx,idxc, idxq, coltyp, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info, k integer(${ik}$), intent(in) :: ldu, ldu2, ldvt, ldvt2, nl, nr, sqre real(${rk}$), intent(in) :: alpha, beta ! Array Arguments integer(${ik}$), intent(out) :: coltyp(*), idx(*), idxc(*), idxp(*) integer(${ik}$), intent(inout) :: idxq(*) real(${rk}$), intent(inout) :: d(*), u(ldu,*), vt(ldvt,*) real(${rk}$), intent(out) :: dsigma(*), u2(ldu2,*), vt2(ldvt2,*), z(*) ! ===================================================================== ! Local Arrays integer(${ik}$) :: ctot(4_${ik}$), psm(4_${ik}$) ! Local Scalars integer(${ik}$) :: ct, i, idxi, idxj, idxjp, j, jp, jprev, k2, m, n, nlp1, nlp2 real(${rk}$) :: c, eps, hlftol, s, tau, tol, z1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( nl<1_${ik}$ ) then info = -1_${ik}$ else if( nr<1_${ik}$ ) then info = -2_${ik}$ else if( ( sqre/=1_${ik}$ ) .and. ( sqre/=0_${ik}$ ) ) then info = -3_${ik}$ end if n = nl + nr + 1_${ik}$ m = n + sqre if( ldun )go to 110 if( abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ idxp( k2 ) = j coltyp( j ) = 4_${ik}$ else ! check if singular values are close enough to allow deflation. if( abs( d( j )-d( jprev ) )<=tol ) then ! deflation is possible. s = z( jprev ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_${ri}$lapy2( c, s ) c = c / tau s = -s / tau z( j ) = tau z( jprev ) = zero ! apply back the givens rotation to the left and right ! singular vector matrices. idxjp = idxq( idx( jprev )+1_${ik}$ ) idxj = idxq( idx( j )+1_${ik}$ ) if( idxjp<=nlp1 ) then idxjp = idxjp - 1_${ik}$ end if if( idxj<=nlp1 ) then idxj = idxj - 1_${ik}$ end if call stdlib${ii}$_${ri}$rot( n, u( 1_${ik}$, idxjp ), 1_${ik}$, u( 1_${ik}$, idxj ), 1_${ik}$, c, s ) call stdlib${ii}$_${ri}$rot( m, vt( idxjp, 1_${ik}$ ), ldvt, vt( idxj, 1_${ik}$ ), ldvt, c,s ) if( coltyp( j )/=coltyp( jprev ) ) then coltyp( j ) = 3_${ik}$ end if coltyp( jprev ) = 4_${ik}$ k2 = k2 - 1_${ik}$ idxp( k2 ) = jprev jprev = j else k = k + 1_${ik}$ u2( k, 1_${ik}$ ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev jprev = j end if end if go to 100 110 continue ! record the last singular value. k = k + 1_${ik}$ u2( k, 1_${ik}$ ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev 120 continue ! count up the total number of the various types of columns, then ! form a permutation which positions the four column types into ! four groups of uniform structure (although one or more of these ! groups may be empty). do j = 1, 4 ctot( j ) = 0_${ik}$ end do do j = 2, n ct = coltyp( j ) ctot( ct ) = ctot( ct ) + 1_${ik}$ end do ! psm(*) = position in submatrix (of types 1 through 4) psm( 1_${ik}$ ) = 2_${ik}$ psm( 2_${ik}$ ) = 2_${ik}$ + ctot( 1_${ik}$ ) psm( 3_${ik}$ ) = psm( 2_${ik}$ ) + ctot( 2_${ik}$ ) psm( 4_${ik}$ ) = psm( 3_${ik}$ ) + ctot( 3_${ik}$ ) ! fill out the idxc array so that the permutation which it induces ! will place all type-1 columns first, all type-2 columns next, ! then all type-3's, and finally all type-4's, starting from the ! second column. this applies similarly to the rows of vt. do j = 2, n jp = idxp( j ) ct = coltyp( jp ) idxc( psm( ct ) ) = j psm( ct ) = psm( ct ) + 1_${ik}$ end do ! sort the singular values and corresponding singular vectors into ! dsigma, u2, and vt2 respectively. the singular values/vectors ! which were not deflated go into the first k slots of dsigma, u2, ! and vt2 respectively, while those which were deflated go into the ! last n - k slots, except that the first column/row will be treated ! separately. do j = 2, n jp = idxp( j ) dsigma( j ) = d( jp ) idxj = idxq( idx( idxp( idxc( j ) ) )+1_${ik}$ ) if( idxj<=nlp1 ) then idxj = idxj - 1_${ik}$ end if call stdlib${ii}$_${ri}$copy( n, u( 1_${ik}$, idxj ), 1_${ik}$, u2( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( m, vt( idxj, 1_${ik}$ ), ldvt, vt2( j, 1_${ik}$ ), ldvt2 ) end do ! determine dsigma(1), dsigma(2) and z(1) dsigma( 1_${ik}$ ) = zero hlftol = tol / two if( abs( dsigma( 2_${ik}$ ) )<=hlftol )dsigma( 2_${ik}$ ) = hlftol if( m>n ) then z( 1_${ik}$ ) = stdlib${ii}$_${ri}$lapy2( z1, z( m ) ) if( z( 1_${ik}$ )<=tol ) then c = one s = zero z( 1_${ik}$ ) = tol else c = z1 / z( 1_${ik}$ ) s = z( m ) / z( 1_${ik}$ ) end if else if( abs( z1 )<=tol ) then z( 1_${ik}$ ) = tol else z( 1_${ik}$ ) = z1 end if end if ! move the rest of the updating row to z. call stdlib${ii}$_${ri}$copy( k-1, u2( 2_${ik}$, 1_${ik}$ ), 1_${ik}$, z( 2_${ik}$ ), 1_${ik}$ ) ! determine the first column of u2, the first row of vt2 and the ! last row of vt. call stdlib${ii}$_${ri}$laset( 'A', n, 1_${ik}$, zero, zero, u2, ldu2 ) u2( nlp1, 1_${ik}$ ) = one if( m>n ) then do i = 1, nlp1 vt( m, i ) = -s*vt( nlp1, i ) vt2( 1_${ik}$, i ) = c*vt( nlp1, i ) end do do i = nlp2, m vt2( 1_${ik}$, i ) = s*vt( m, i ) vt( m, i ) = c*vt( m, i ) end do else call stdlib${ii}$_${ri}$copy( m, vt( nlp1, 1_${ik}$ ), ldvt, vt2( 1_${ik}$, 1_${ik}$ ), ldvt2 ) end if if( m>n ) then call stdlib${ii}$_${ri}$copy( m, vt( m, 1_${ik}$ ), ldvt, vt2( m, 1_${ik}$ ), ldvt2 ) end if ! the deflated singular values and their corresponding vectors go ! into the back of d, u, and v respectively. if( n>k ) then call stdlib${ii}$_${ri}$copy( n-k, dsigma( k+1 ), 1_${ik}$, d( k+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lacpy( 'A', n, n-k, u2( 1_${ik}$, k+1 ), ldu2, u( 1_${ik}$, k+1 ),ldu ) call stdlib${ii}$_${ri}$lacpy( 'A', n-k, m, vt2( k+1, 1_${ik}$ ), ldvt2, vt( k+1, 1_${ik}$ ),ldvt ) end if ! copy ctot into coltyp for referencing in stdlib${ii}$_${ri}$lasd3. do j = 1, 4 coltyp( j ) = ctot( j ) end do return end subroutine stdlib${ii}$_${ri}$lasd2 #:endif #:endfor pure module subroutine stdlib${ii}$_slasd3( nl, nr, sqre, k, d, q, ldq, dsigma, u, ldu, u2,ldu2, vt, ldvt,& !! SLASD3 finds all the square roots of the roots of the secular !! equation, as defined by the values in D and Z. It makes the !! appropriate calls to SLASD4 and then updates the singular !! vectors by matrix multiplication. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. !! SLASD3 is called from SLASD1. vt2, ldvt2, idxc, ctot, z,info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldq, ldu, ldu2, ldvt, ldvt2, nl, nr, sqre ! Array Arguments integer(${ik}$), intent(in) :: ctot(*), idxc(*) real(sp), intent(out) :: d(*), q(ldq,*), u(ldu,*), vt(ldvt,*) real(sp), intent(inout) :: dsigma(*), vt2(ldvt2,*), z(*) real(sp), intent(in) :: u2(ldu2,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ctemp, i, j, jc, ktemp, m, n, nlp1, nlp2, nrp1 real(sp) :: rho, temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( nl<1_${ik}$ ) then info = -1_${ik}$ else if( nr<1_${ik}$ ) then info = -2_${ik}$ else if( ( sqre/=1_${ik}$ ) .and. ( sqre/=0_${ik}$ ) ) then info = -3_${ik}$ end if n = nl + nr + 1_${ik}$ m = n + sqre nlp1 = nl + 1_${ik}$ nlp2 = nl + 2_${ik}$ if( ( k<1_${ik}$ ) .or. ( k>n ) ) then info = -4_${ik}$ else if( ldqzero ) then call stdlib${ii}$_scopy( n, u2( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, u( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) else do i = 1, n u( i, 1_${ik}$ ) = -u2( i, 1_${ik}$ ) end do end if return end if ! modify values dsigma(i) to make sure all dsigma(i)-dsigma(j) can ! be computed with high relative accuracy (barring over/underflow). ! this is a problem on machines without a guard digit in ! add/subtract (cray xmp, cray ymp, cray c 90 and cray 2). ! the following code replaces dsigma(i) by 2*dsigma(i)-dsigma(i), ! which on any of these machines zeros out the bottommost ! bit of dsigma(i) if it is 1; this makes the subsequent ! subtractions dsigma(i)-dsigma(j) unproblematic when cancellation ! occurs. on binary machines with a guard digit (almost all ! machines) it does not change dsigma(i) at all. on hexadecimal ! and decimal machines with a guard digit, it slightly ! changes the bottommost bits of dsigma(i). it does not account ! for hexadecimal or decimal machines without guard digits ! (we know of none). we use a subroutine call to compute ! 2*dsigma(i) to prevent optimizing compilers from eliminating ! this code. do i = 1, k dsigma( i ) = stdlib${ii}$_slamc3( dsigma( i ), dsigma( i ) ) - dsigma( i ) end do ! keep a copy of z. call stdlib${ii}$_scopy( k, z, 1_${ik}$, q, 1_${ik}$ ) ! normalize z. rho = stdlib${ii}$_snrm2( k, z, 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, rho, one, k, 1_${ik}$, z, k, info ) rho = rho*rho ! find the new singular values. do j = 1, k call stdlib${ii}$_slasd4( k, j, dsigma, z, u( 1_${ik}$, j ), rho, d( j ),vt( 1_${ik}$, j ), info ) ! if the zero finder fails, report the convergence failure. if( info/=0_${ik}$ ) then return end if end do ! compute updated z. do i = 1, k z( i ) = u( i, k )*vt( i, k ) do j = 1, i - 1 z( i ) = z( i )*( u( i, j )*vt( i, j ) /( dsigma( i )-dsigma( j ) ) /( dsigma( i & )+dsigma( j ) ) ) end do do j = i, k - 1 z( i ) = z( i )*( u( i, j )*vt( i, j ) /( dsigma( i )-dsigma( j+1 ) ) /( dsigma( & i )+dsigma( j+1 ) ) ) end do z( i ) = sign( sqrt( abs( z( i ) ) ), q( i, 1_${ik}$ ) ) end do ! compute left singular vectors of the modified diagonal matrix, ! and store related information for the right singular vectors. do i = 1, k vt( 1_${ik}$, i ) = z( 1_${ik}$ ) / u( 1_${ik}$, i ) / vt( 1_${ik}$, i ) u( 1_${ik}$, i ) = negone do j = 2, k vt( j, i ) = z( j ) / u( j, i ) / vt( j, i ) u( j, i ) = dsigma( j )*vt( j, i ) end do temp = stdlib${ii}$_snrm2( k, u( 1_${ik}$, i ), 1_${ik}$ ) q( 1_${ik}$, i ) = u( 1_${ik}$, i ) / temp do j = 2, k jc = idxc( j ) q( j, i ) = u( jc, i ) / temp end do end do ! update the left singular vector matrix. if( k==2_${ik}$ ) then call stdlib${ii}$_sgemm( 'N', 'N', n, k, k, one, u2, ldu2, q, ldq, zero, u,ldu ) go to 100 end if if( ctot( 1_${ik}$ )>0_${ik}$ ) then call stdlib${ii}$_sgemm( 'N', 'N', nl, k, ctot( 1_${ik}$ ), one, u2( 1_${ik}$, 2_${ik}$ ), ldu2,q( 2_${ik}$, 1_${ik}$ ), ldq,& zero, u( 1_${ik}$, 1_${ik}$ ), ldu ) if( ctot( 3_${ik}$ )>0_${ik}$ ) then ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) + ctot( 2_${ik}$ ) call stdlib${ii}$_sgemm( 'N', 'N', nl, k, ctot( 3_${ik}$ ), one, u2( 1_${ik}$, ktemp ),ldu2, q( & ktemp, 1_${ik}$ ), ldq, one, u( 1_${ik}$, 1_${ik}$ ), ldu ) end if else if( ctot( 3_${ik}$ )>0_${ik}$ ) then ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) + ctot( 2_${ik}$ ) call stdlib${ii}$_sgemm( 'N', 'N', nl, k, ctot( 3_${ik}$ ), one, u2( 1_${ik}$, ktemp ),ldu2, q( ktemp, & 1_${ik}$ ), ldq, zero, u( 1_${ik}$, 1_${ik}$ ), ldu ) else call stdlib${ii}$_slacpy( 'F', nl, k, u2, ldu2, u, ldu ) end if call stdlib${ii}$_scopy( k, q( 1_${ik}$, 1_${ik}$ ), ldq, u( nlp1, 1_${ik}$ ), ldu ) ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) ctemp = ctot( 2_${ik}$ ) + ctot( 3_${ik}$ ) call stdlib${ii}$_sgemm( 'N', 'N', nr, k, ctemp, one, u2( nlp2, ktemp ), ldu2,q( ktemp, 1_${ik}$ ), & ldq, zero, u( nlp2, 1_${ik}$ ), ldu ) ! generate the right singular vectors. 100 continue do i = 1, k temp = stdlib${ii}$_snrm2( k, vt( 1_${ik}$, i ), 1_${ik}$ ) q( i, 1_${ik}$ ) = vt( 1_${ik}$, i ) / temp do j = 2, k jc = idxc( j ) q( i, j ) = vt( jc, i ) / temp end do end do ! update the right singular vector matrix. if( k==2_${ik}$ ) then call stdlib${ii}$_sgemm( 'N', 'N', k, m, k, one, q, ldq, vt2, ldvt2, zero,vt, ldvt ) return end if ktemp = 1_${ik}$ + ctot( 1_${ik}$ ) call stdlib${ii}$_sgemm( 'N', 'N', k, nlp1, ktemp, one, q( 1_${ik}$, 1_${ik}$ ), ldq,vt2( 1_${ik}$, 1_${ik}$ ), ldvt2, & zero, vt( 1_${ik}$, 1_${ik}$ ), ldvt ) ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) + ctot( 2_${ik}$ ) if( ktemp<=ldvt2 )call stdlib${ii}$_sgemm( 'N', 'N', k, nlp1, ctot( 3_${ik}$ ), one, q( 1_${ik}$, ktemp ),& ldq, vt2( ktemp, 1_${ik}$ ), ldvt2, one, vt( 1_${ik}$, 1_${ik}$ ),ldvt ) ktemp = ctot( 1_${ik}$ ) + 1_${ik}$ nrp1 = nr + sqre if( ktemp>1_${ik}$ ) then do i = 1, k q( i, ktemp ) = q( i, 1_${ik}$ ) end do do i = nlp2, m vt2( ktemp, i ) = vt2( 1_${ik}$, i ) end do end if ctemp = 1_${ik}$ + ctot( 2_${ik}$ ) + ctot( 3_${ik}$ ) call stdlib${ii}$_sgemm( 'N', 'N', k, nrp1, ctemp, one, q( 1_${ik}$, ktemp ), ldq,vt2( ktemp, nlp2 )& , ldvt2, zero, vt( 1_${ik}$, nlp2 ), ldvt ) return end subroutine stdlib${ii}$_slasd3 pure module subroutine stdlib${ii}$_dlasd3( nl, nr, sqre, k, d, q, ldq, dsigma, u, ldu, u2,ldu2, vt, ldvt,& !! DLASD3 finds all the square roots of the roots of the secular !! equation, as defined by the values in D and Z. It makes the !! appropriate calls to DLASD4 and then updates the singular !! vectors by matrix multiplication. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. !! DLASD3 is called from DLASD1. vt2, ldvt2, idxc, ctot, z,info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldq, ldu, ldu2, ldvt, ldvt2, nl, nr, sqre ! Array Arguments integer(${ik}$), intent(in) :: ctot(*), idxc(*) real(dp), intent(out) :: d(*), q(ldq,*), u(ldu,*), vt(ldvt,*) real(dp), intent(inout) :: dsigma(*), vt2(ldvt2,*), z(*) real(dp), intent(in) :: u2(ldu2,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ctemp, i, j, jc, ktemp, m, n, nlp1, nlp2, nrp1 real(dp) :: rho, temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( nl<1_${ik}$ ) then info = -1_${ik}$ else if( nr<1_${ik}$ ) then info = -2_${ik}$ else if( ( sqre/=1_${ik}$ ) .and. ( sqre/=0_${ik}$ ) ) then info = -3_${ik}$ end if n = nl + nr + 1_${ik}$ m = n + sqre nlp1 = nl + 1_${ik}$ nlp2 = nl + 2_${ik}$ if( ( k<1_${ik}$ ) .or. ( k>n ) ) then info = -4_${ik}$ else if( ldqzero ) then call stdlib${ii}$_dcopy( n, u2( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, u( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) else do i = 1, n u( i, 1_${ik}$ ) = -u2( i, 1_${ik}$ ) end do end if return end if ! modify values dsigma(i) to make sure all dsigma(i)-dsigma(j) can ! be computed with high relative accuracy (barring over/underflow). ! this is a problem on machines without a guard digit in ! add/subtract (cray xmp, cray ymp, cray c 90 and cray 2). ! the following code replaces dsigma(i) by 2*dsigma(i)-dsigma(i), ! which on any of these machines zeros out the bottommost ! bit of dsigma(i) if it is 1; this makes the subsequent ! subtractions dsigma(i)-dsigma(j) unproblematic when cancellation ! occurs. on binary machines with a guard digit (almost all ! machines) it does not change dsigma(i) at all. on hexadecimal ! and decimal machines with a guard digit, it slightly ! changes the bottommost bits of dsigma(i). it does not account ! for hexadecimal or decimal machines without guard digits ! (we know of none). we use a subroutine call to compute ! 2*dsigma(i) to prevent optimizing compilers from eliminating ! this code. do i = 1, k dsigma( i ) = stdlib${ii}$_dlamc3( dsigma( i ), dsigma( i ) ) - dsigma( i ) end do ! keep a copy of z. call stdlib${ii}$_dcopy( k, z, 1_${ik}$, q, 1_${ik}$ ) ! normalize z. rho = stdlib${ii}$_dnrm2( k, z, 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, rho, one, k, 1_${ik}$, z, k, info ) rho = rho*rho ! find the new singular values. do j = 1, k call stdlib${ii}$_dlasd4( k, j, dsigma, z, u( 1_${ik}$, j ), rho, d( j ),vt( 1_${ik}$, j ), info ) ! if the zero finder fails, report the convergence failure. if( info/=0_${ik}$ ) then return end if end do ! compute updated z. do i = 1, k z( i ) = u( i, k )*vt( i, k ) do j = 1, i - 1 z( i ) = z( i )*( u( i, j )*vt( i, j ) /( dsigma( i )-dsigma( j ) ) /( dsigma( i & )+dsigma( j ) ) ) end do do j = i, k - 1 z( i ) = z( i )*( u( i, j )*vt( i, j ) /( dsigma( i )-dsigma( j+1 ) ) /( dsigma( & i )+dsigma( j+1 ) ) ) end do z( i ) = sign( sqrt( abs( z( i ) ) ), q( i, 1_${ik}$ ) ) end do ! compute left singular vectors of the modified diagonal matrix, ! and store related information for the right singular vectors. do i = 1, k vt( 1_${ik}$, i ) = z( 1_${ik}$ ) / u( 1_${ik}$, i ) / vt( 1_${ik}$, i ) u( 1_${ik}$, i ) = negone do j = 2, k vt( j, i ) = z( j ) / u( j, i ) / vt( j, i ) u( j, i ) = dsigma( j )*vt( j, i ) end do temp = stdlib${ii}$_dnrm2( k, u( 1_${ik}$, i ), 1_${ik}$ ) q( 1_${ik}$, i ) = u( 1_${ik}$, i ) / temp do j = 2, k jc = idxc( j ) q( j, i ) = u( jc, i ) / temp end do end do ! update the left singular vector matrix. if( k==2_${ik}$ ) then call stdlib${ii}$_dgemm( 'N', 'N', n, k, k, one, u2, ldu2, q, ldq, zero, u,ldu ) go to 100 end if if( ctot( 1_${ik}$ )>0_${ik}$ ) then call stdlib${ii}$_dgemm( 'N', 'N', nl, k, ctot( 1_${ik}$ ), one, u2( 1_${ik}$, 2_${ik}$ ), ldu2,q( 2_${ik}$, 1_${ik}$ ), ldq,& zero, u( 1_${ik}$, 1_${ik}$ ), ldu ) if( ctot( 3_${ik}$ )>0_${ik}$ ) then ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) + ctot( 2_${ik}$ ) call stdlib${ii}$_dgemm( 'N', 'N', nl, k, ctot( 3_${ik}$ ), one, u2( 1_${ik}$, ktemp ),ldu2, q( & ktemp, 1_${ik}$ ), ldq, one, u( 1_${ik}$, 1_${ik}$ ), ldu ) end if else if( ctot( 3_${ik}$ )>0_${ik}$ ) then ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) + ctot( 2_${ik}$ ) call stdlib${ii}$_dgemm( 'N', 'N', nl, k, ctot( 3_${ik}$ ), one, u2( 1_${ik}$, ktemp ),ldu2, q( ktemp, & 1_${ik}$ ), ldq, zero, u( 1_${ik}$, 1_${ik}$ ), ldu ) else call stdlib${ii}$_dlacpy( 'F', nl, k, u2, ldu2, u, ldu ) end if call stdlib${ii}$_dcopy( k, q( 1_${ik}$, 1_${ik}$ ), ldq, u( nlp1, 1_${ik}$ ), ldu ) ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) ctemp = ctot( 2_${ik}$ ) + ctot( 3_${ik}$ ) call stdlib${ii}$_dgemm( 'N', 'N', nr, k, ctemp, one, u2( nlp2, ktemp ), ldu2,q( ktemp, 1_${ik}$ ), & ldq, zero, u( nlp2, 1_${ik}$ ), ldu ) ! generate the right singular vectors. 100 continue do i = 1, k temp = stdlib${ii}$_dnrm2( k, vt( 1_${ik}$, i ), 1_${ik}$ ) q( i, 1_${ik}$ ) = vt( 1_${ik}$, i ) / temp do j = 2, k jc = idxc( j ) q( i, j ) = vt( jc, i ) / temp end do end do ! update the right singular vector matrix. if( k==2_${ik}$ ) then call stdlib${ii}$_dgemm( 'N', 'N', k, m, k, one, q, ldq, vt2, ldvt2, zero,vt, ldvt ) return end if ktemp = 1_${ik}$ + ctot( 1_${ik}$ ) call stdlib${ii}$_dgemm( 'N', 'N', k, nlp1, ktemp, one, q( 1_${ik}$, 1_${ik}$ ), ldq,vt2( 1_${ik}$, 1_${ik}$ ), ldvt2, & zero, vt( 1_${ik}$, 1_${ik}$ ), ldvt ) ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) + ctot( 2_${ik}$ ) if( ktemp<=ldvt2 )call stdlib${ii}$_dgemm( 'N', 'N', k, nlp1, ctot( 3_${ik}$ ), one, q( 1_${ik}$, ktemp ),& ldq, vt2( ktemp, 1_${ik}$ ), ldvt2, one, vt( 1_${ik}$, 1_${ik}$ ),ldvt ) ktemp = ctot( 1_${ik}$ ) + 1_${ik}$ nrp1 = nr + sqre if( ktemp>1_${ik}$ ) then do i = 1, k q( i, ktemp ) = q( i, 1_${ik}$ ) end do do i = nlp2, m vt2( ktemp, i ) = vt2( 1_${ik}$, i ) end do end if ctemp = 1_${ik}$ + ctot( 2_${ik}$ ) + ctot( 3_${ik}$ ) call stdlib${ii}$_dgemm( 'N', 'N', k, nrp1, ctemp, one, q( 1_${ik}$, ktemp ), ldq,vt2( ktemp, nlp2 )& , ldvt2, zero, vt( 1_${ik}$, nlp2 ), ldvt ) return end subroutine stdlib${ii}$_dlasd3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasd3( nl, nr, sqre, k, d, q, ldq, dsigma, u, ldu, u2,ldu2, vt, ldvt,& !! DLASD3: finds all the square roots of the roots of the secular !! equation, as defined by the values in D and Z. It makes the !! appropriate calls to DLASD4 and then updates the singular !! vectors by matrix multiplication. !! This code makes very mild assumptions about floating point !! arithmetic. It will work on machines with a guard digit in !! add/subtract, or on those binary machines without guard digits !! which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2. !! It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. !! DLASD3 is called from DLASD1. vt2, ldvt2, idxc, ctot, z,info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldq, ldu, ldu2, ldvt, ldvt2, nl, nr, sqre ! Array Arguments integer(${ik}$), intent(in) :: ctot(*), idxc(*) real(${rk}$), intent(out) :: d(*), q(ldq,*), u(ldu,*), vt(ldvt,*) real(${rk}$), intent(inout) :: dsigma(*), vt2(ldvt2,*), z(*) real(${rk}$), intent(in) :: u2(ldu2,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: ctemp, i, j, jc, ktemp, m, n, nlp1, nlp2, nrp1 real(${rk}$) :: rho, temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( nl<1_${ik}$ ) then info = -1_${ik}$ else if( nr<1_${ik}$ ) then info = -2_${ik}$ else if( ( sqre/=1_${ik}$ ) .and. ( sqre/=0_${ik}$ ) ) then info = -3_${ik}$ end if n = nl + nr + 1_${ik}$ m = n + sqre nlp1 = nl + 1_${ik}$ nlp2 = nl + 2_${ik}$ if( ( k<1_${ik}$ ) .or. ( k>n ) ) then info = -4_${ik}$ else if( ldqzero ) then call stdlib${ii}$_${ri}$copy( n, u2( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, u( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) else do i = 1, n u( i, 1_${ik}$ ) = -u2( i, 1_${ik}$ ) end do end if return end if ! modify values dsigma(i) to make sure all dsigma(i)-dsigma(j) can ! be computed with high relative accuracy (barring over/underflow). ! this is a problem on machines without a guard digit in ! add/subtract (cray xmp, cray ymp, cray c 90 and cray 2). ! the following code replaces dsigma(i) by 2*dsigma(i)-dsigma(i), ! which on any of these machines zeros out the bottommost ! bit of dsigma(i) if it is 1; this makes the subsequent ! subtractions dsigma(i)-dsigma(j) unproblematic when cancellation ! occurs. on binary machines with a guard digit (almost all ! machines) it does not change dsigma(i) at all. on hexadecimal ! and decimal machines with a guard digit, it slightly ! changes the bottommost bits of dsigma(i). it does not account ! for hexadecimal or decimal machines without guard digits ! (we know of none). we use a subroutine call to compute ! 2*dsigma(i) to prevent optimizing compilers from eliminating ! this code. do i = 1, k dsigma( i ) = stdlib${ii}$_${ri}$lamc3( dsigma( i ), dsigma( i ) ) - dsigma( i ) end do ! keep a copy of z. call stdlib${ii}$_${ri}$copy( k, z, 1_${ik}$, q, 1_${ik}$ ) ! normalize z. rho = stdlib${ii}$_${ri}$nrm2( k, z, 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, rho, one, k, 1_${ik}$, z, k, info ) rho = rho*rho ! find the new singular values. do j = 1, k call stdlib${ii}$_${ri}$lasd4( k, j, dsigma, z, u( 1_${ik}$, j ), rho, d( j ),vt( 1_${ik}$, j ), info ) ! if the zero finder fails, report the convergence failure. if( info/=0_${ik}$ ) then return end if end do ! compute updated z. do i = 1, k z( i ) = u( i, k )*vt( i, k ) do j = 1, i - 1 z( i ) = z( i )*( u( i, j )*vt( i, j ) /( dsigma( i )-dsigma( j ) ) /( dsigma( i & )+dsigma( j ) ) ) end do do j = i, k - 1 z( i ) = z( i )*( u( i, j )*vt( i, j ) /( dsigma( i )-dsigma( j+1 ) ) /( dsigma( & i )+dsigma( j+1 ) ) ) end do z( i ) = sign( sqrt( abs( z( i ) ) ), q( i, 1_${ik}$ ) ) end do ! compute left singular vectors of the modified diagonal matrix, ! and store related information for the right singular vectors. do i = 1, k vt( 1_${ik}$, i ) = z( 1_${ik}$ ) / u( 1_${ik}$, i ) / vt( 1_${ik}$, i ) u( 1_${ik}$, i ) = negone do j = 2, k vt( j, i ) = z( j ) / u( j, i ) / vt( j, i ) u( j, i ) = dsigma( j )*vt( j, i ) end do temp = stdlib${ii}$_${ri}$nrm2( k, u( 1_${ik}$, i ), 1_${ik}$ ) q( 1_${ik}$, i ) = u( 1_${ik}$, i ) / temp do j = 2, k jc = idxc( j ) q( j, i ) = u( jc, i ) / temp end do end do ! update the left singular vector matrix. if( k==2_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, k, k, one, u2, ldu2, q, ldq, zero, u,ldu ) go to 100 end if if( ctot( 1_${ik}$ )>0_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', nl, k, ctot( 1_${ik}$ ), one, u2( 1_${ik}$, 2_${ik}$ ), ldu2,q( 2_${ik}$, 1_${ik}$ ), ldq,& zero, u( 1_${ik}$, 1_${ik}$ ), ldu ) if( ctot( 3_${ik}$ )>0_${ik}$ ) then ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) + ctot( 2_${ik}$ ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', nl, k, ctot( 3_${ik}$ ), one, u2( 1_${ik}$, ktemp ),ldu2, q( & ktemp, 1_${ik}$ ), ldq, one, u( 1_${ik}$, 1_${ik}$ ), ldu ) end if else if( ctot( 3_${ik}$ )>0_${ik}$ ) then ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) + ctot( 2_${ik}$ ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', nl, k, ctot( 3_${ik}$ ), one, u2( 1_${ik}$, ktemp ),ldu2, q( ktemp, & 1_${ik}$ ), ldq, zero, u( 1_${ik}$, 1_${ik}$ ), ldu ) else call stdlib${ii}$_${ri}$lacpy( 'F', nl, k, u2, ldu2, u, ldu ) end if call stdlib${ii}$_${ri}$copy( k, q( 1_${ik}$, 1_${ik}$ ), ldq, u( nlp1, 1_${ik}$ ), ldu ) ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) ctemp = ctot( 2_${ik}$ ) + ctot( 3_${ik}$ ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', nr, k, ctemp, one, u2( nlp2, ktemp ), ldu2,q( ktemp, 1_${ik}$ ), & ldq, zero, u( nlp2, 1_${ik}$ ), ldu ) ! generate the right singular vectors. 100 continue do i = 1, k temp = stdlib${ii}$_${ri}$nrm2( k, vt( 1_${ik}$, i ), 1_${ik}$ ) q( i, 1_${ik}$ ) = vt( 1_${ik}$, i ) / temp do j = 2, k jc = idxc( j ) q( i, j ) = vt( jc, i ) / temp end do end do ! update the right singular vector matrix. if( k==2_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', k, m, k, one, q, ldq, vt2, ldvt2, zero,vt, ldvt ) return end if ktemp = 1_${ik}$ + ctot( 1_${ik}$ ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', k, nlp1, ktemp, one, q( 1_${ik}$, 1_${ik}$ ), ldq,vt2( 1_${ik}$, 1_${ik}$ ), ldvt2, & zero, vt( 1_${ik}$, 1_${ik}$ ), ldvt ) ktemp = 2_${ik}$ + ctot( 1_${ik}$ ) + ctot( 2_${ik}$ ) if( ktemp<=ldvt2 )call stdlib${ii}$_${ri}$gemm( 'N', 'N', k, nlp1, ctot( 3_${ik}$ ), one, q( 1_${ik}$, ktemp ),& ldq, vt2( ktemp, 1_${ik}$ ), ldvt2, one, vt( 1_${ik}$, 1_${ik}$ ),ldvt ) ktemp = ctot( 1_${ik}$ ) + 1_${ik}$ nrp1 = nr + sqre if( ktemp>1_${ik}$ ) then do i = 1, k q( i, ktemp ) = q( i, 1_${ik}$ ) end do do i = nlp2, m vt2( ktemp, i ) = vt2( 1_${ik}$, i ) end do end if ctemp = 1_${ik}$ + ctot( 2_${ik}$ ) + ctot( 3_${ik}$ ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', k, nrp1, ctemp, one, q( 1_${ik}$, ktemp ), ldq,vt2( ktemp, nlp2 )& , ldvt2, zero, vt( 1_${ik}$, nlp2 ), ldvt ) return end subroutine stdlib${ii}$_${ri}$lasd3 #:endif #:endfor pure module subroutine stdlib${ii}$_slasd4( n, i, d, z, delta, rho, sigma, work, info ) !! This subroutine computes the square root of the I-th updated !! eigenvalue of a positive symmetric rank-one modification to !! a positive diagonal matrix whose entries are given as the squares !! of the corresponding entries in the array d, and that !! 0 <= D(i) < D(j) for i < j !! and that RHO > 0. This is arranged by the calling routine, and is !! no loss in generality. The rank-one modified system is thus !! diag( D ) * diag( D ) + RHO * Z * Z_transpose. !! where we assume the Euclidean norm of Z is 1. !! The method consists of approximating the rational functions in the !! secular equation by simpler interpolating rational functions. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i, n integer(${ik}$), intent(out) :: info real(sp), intent(in) :: rho real(sp), intent(out) :: sigma ! Array Arguments real(sp), intent(in) :: d(*), z(*) real(sp), intent(out) :: delta(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 400_${ik}$ ! Local Scalars logical(lk) :: orgati, swtch, swtch3, geomavg integer(${ik}$) :: ii, iim1, iip1, ip1, iter, j, niter real(sp) :: a, b, c, delsq, delsq2, sq2, dphi, dpsi, dtiim, dtiip, dtipsq, dtisq, & dtnsq, dtnsq1, dw, eps, erretm, eta, phi, prew, psi, rhoinv, sglb, sgub, tau, tau2, & temp, temp1, temp2, w ! Local Arrays real(sp) :: dd(3_${ik}$), zz(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! since this routine is called in an inner loop, we do no argument ! checking. ! quick return for n=1 and 2. info = 0_${ik}$ if( n==1_${ik}$ ) then ! presumably, i=1 upon entry sigma = sqrt( d( 1_${ik}$ )*d( 1_${ik}$ )+rho*z( 1_${ik}$ )*z( 1_${ik}$ ) ) delta( 1_${ik}$ ) = one work( 1_${ik}$ ) = one return end if if( n==2_${ik}$ ) then call stdlib${ii}$_slasd5( i, d, z, delta, rho, sigma, work ) return end if ! compute machine epsilon eps = stdlib${ii}$_slamch( 'EPSILON' ) rhoinv = one / rho tau2= zero ! the case i = n if( i==n ) then ! initialize some basic variables ii = n - 1_${ik}$ niter = 1_${ik}$ ! calculate initial guess temp = rho / two ! if ||z||_2 is not one, then temp should be set to ! rho * ||z||_2^2 / two temp1 = temp / ( d( n )+sqrt( d( n )*d( n )+temp ) ) do j = 1, n work( j ) = d( j ) + d( n ) + temp1 delta( j ) = ( d( j )-d( n ) ) - temp1 end do psi = zero do j = 1, n - 2 psi = psi + z( j )*z( j ) / ( delta( j )*work( j ) ) end do c = rhoinv + psi w = c + z( ii )*z( ii ) / ( delta( ii )*work( ii ) ) +z( n )*z( n ) / ( delta( n )& *work( n ) ) if( w<=zero ) then temp1 = sqrt( d( n )*d( n )+rho ) temp = z( n-1 )*z( n-1 ) / ( ( d( n-1 )+temp1 )*( d( n )-d( n-1 )+rho / ( d( n )+& temp1 ) ) ) +z( n )*z( n ) / rho ! the following tau2 is to approximate ! sigma_n^2 - d( n )*d( n ) if( c<=temp ) then tau = rho else delsq = ( d( n )-d( n-1 ) )*( d( n )+d( n-1 ) ) a = -c*delsq + z( n-1 )*z( n-1 ) + z( n )*z( n ) b = z( n )*z( n )*delsq if( a=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = eta - dtnsq if( temp>rho )eta = rho + dtnsq eta = eta / ( sigma+sqrt( eta+sigma*sigma ) ) tau = tau + eta sigma = sigma + eta do j = 1, n delta( j ) = delta( j ) - eta work( j ) = work( j ) + eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, ii temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi tau2 = work( n )*delta( n ) temp = z( n ) / tau2 phi = z( n )*temp dphi = temp*temp erretm = eight*( -phi-psi ) + erretm - phi + rhoinv ! $ + abs( tau2 )*( dpsi+dphi ) w = rhoinv + phi + psi ! main loop to update the values of the array delta iter = niter + 1_${ik}$ loop_90: do niter = iter, maxit ! test for convergence if( abs( w )<=eps*erretm ) then go to 240 end if ! calculate the new step dtnsq1 = work( n-1 )*delta( n-1 ) dtnsq = work( n )*delta( n ) c = w - dtnsq1*dpsi - dtnsq*dphi a = ( dtnsq+dtnsq1 )*w - dtnsq1*dtnsq*( dpsi+dphi ) b = dtnsq1*dtnsq*w if( a>=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = eta - dtnsq if( temp<=zero )eta = eta / two eta = eta / ( sigma+sqrt( eta+sigma*sigma ) ) tau = tau + eta sigma = sigma + eta do j = 1, n delta( j ) = delta( j ) - eta work( j ) = work( j ) + eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, ii temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi tau2 = work( n )*delta( n ) temp = z( n ) / tau2 phi = z( n )*temp dphi = temp*temp erretm = eight*( -phi-psi ) + erretm - phi + rhoinv ! $ + abs( tau2 )*( dpsi+dphi ) w = rhoinv + phi + psi end do loop_90 ! return with info = 1, niter = maxit and not converged info = 1_${ik}$ go to 240 ! end for the case i = n else ! the case for i < n niter = 1_${ik}$ ip1 = i + 1_${ik}$ ! calculate initial guess delsq = ( d( ip1 )-d( i ) )*( d( ip1 )+d( i ) ) delsq2 = delsq / two sq2=sqrt( ( d( i )*d( i )+d( ip1 )*d( ip1 ) ) / two ) temp = delsq2 / ( d( i )+sq2 ) do j = 1, n work( j ) = d( j ) + d( i ) + temp delta( j ) = ( d( j )-d( i ) ) - temp end do psi = zero do j = 1, i - 1 psi = psi + z( j )*z( j ) / ( work( j )*delta( j ) ) end do phi = zero do j = n, i + 2, -1 phi = phi + z( j )*z( j ) / ( work( j )*delta( j ) ) end do c = rhoinv + psi + phi w = c + z( i )*z( i ) / ( work( i )*delta( i ) ) +z( ip1 )*z( ip1 ) / ( work( ip1 )& *delta( ip1 ) ) geomavg = .false. if( w>zero ) then ! d(i)^2 < the ith sigma^2 < (d(i)^2+d(i+1)^2)/2 ! we choose d(i) as origin. orgati = .true. ii = i sglb = zero sgub = delsq2 / ( d( i )+sq2 ) a = c*delsq + z( i )*z( i ) + z( ip1 )*z( ip1 ) b = z( i )*z( i )*delsq if( a>zero ) then tau2 = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) else tau2 = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) end if ! tau2 now is an estimation of sigma^2 - d( i )^2. the ! following, however, is the corresponding estimation of ! sigma - d( i ). tau = tau2 / ( d( i )+sqrt( d( i )*d( i )+tau2 ) ) temp = sqrt(eps) if( (d(i)<=temp*d(ip1)).and.(abs(z(i))<=temp).and.(d(i)>zero) ) then tau = min( ten*d(i), sgub ) geomavg = .true. end if else ! (d(i)^2+d(i+1)^2)/2 <= the ith sigma^2 < d(i+1)^2/2 ! we choose d(i+1) as origin. orgati = .false. ii = ip1 sglb = -delsq2 / ( d( ii )+sq2 ) sgub = zero a = c*delsq - z( i )*z( i ) - z( ip1 )*z( ip1 ) b = z( ip1 )*z( ip1 )*delsq if( azero )swtch3 = .true. end if if( ii==1_${ik}$ .or. ii==n )swtch3 = .false. temp = z( ii ) / ( work( ii )*delta( ii ) ) dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = w + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv+ three*abs( temp ) ! $ + abs( tau2 )*dw ! test for convergence if( abs( w )<=eps*erretm ) then go to 240 end if if( w<=zero ) then sglb = max( sglb, tau ) else sgub = min( sgub, tau ) end if ! calculate the new step niter = niter + 1_${ik}$ if( .not.swtch3 ) then dtipsq = work( ip1 )*delta( ip1 ) dtisq = work( i )*delta( i ) if( orgati ) then c = w - dtipsq*dw + delsq*( z( i ) / dtisq )**2_${ik}$ else c = w - dtisq*dw - delsq*( z( ip1 ) / dtipsq )**2_${ik}$ end if a = ( dtipsq+dtisq )*w - dtipsq*dtisq*dw b = dtipsq*dtisq*w if( c==zero ) then if( a==zero ) then if( orgati ) then a = z( i )*z( i ) + dtipsq*dtipsq*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) + dtisq*dtisq*( dpsi+dphi ) end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles dtiim = work( iim1 )*delta( iim1 ) dtiip = work( iip1 )*delta( iip1 ) temp = rhoinv + psi + phi if( orgati ) then temp1 = z( iim1 ) / dtiim temp1 = temp1*temp1 c = ( temp - dtiip*( dpsi+dphi ) ) -( d( iim1 )-d( iip1 ) )*( d( iim1 )+d( & iip1 ) )*temp1 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) if( dpsi 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw eta = eta / ( sigma+sqrt( sigma*sigma+eta ) ) temp = tau + eta if( temp>sgub .or. temp zero ) then eta = sqrt(sgub*tau)-tau end if else if( sglb > zero ) then eta = sqrt(sglb*tau)-tau end if end if end if end if prew = w tau = tau + eta sigma = sigma + eta do j = 1, n work( j ) = work( j ) + eta delta( j ) = delta( j ) - eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, iim1 temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi dphi = zero phi = zero do j = n, iip1, -1 temp = z( j ) / ( work( j )*delta( j ) ) phi = phi + z( j )*temp dphi = dphi + temp*temp erretm = erretm + phi end do tau2 = work( ii )*delta( ii ) temp = z( ii ) / tau2 dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = rhoinv + phi + psi + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv+ three*abs( temp ) ! $ + abs( tau2 )*dw swtch = .false. if( orgati ) then if( -w>abs( prew ) / ten )swtch = .true. else if( w>abs( prew ) / ten )swtch = .true. end if ! main loop to update the values of the array delta and work iter = niter + 1_${ik}$ loop_230: do niter = iter, maxit ! test for convergence if( abs( w )<=eps*erretm ) then ! $ .or. (sgub-sglb)<=eight*abs(sgub+sglb) ) then go to 240 end if if( w<=zero ) then sglb = max( sglb, tau ) else sgub = min( sgub, tau ) end if ! calculate the new step if( .not.swtch3 ) then dtipsq = work( ip1 )*delta( ip1 ) dtisq = work( i )*delta( i ) if( .not.swtch ) then if( orgati ) then c = w - dtipsq*dw + delsq*( z( i ) / dtisq )**2_${ik}$ else c = w - dtisq*dw - delsq*( z( ip1 ) / dtipsq )**2_${ik}$ end if else temp = z( ii ) / ( work( ii )*delta( ii ) ) if( orgati ) then dpsi = dpsi + temp*temp else dphi = dphi + temp*temp end if c = w - dtisq*dpsi - dtipsq*dphi end if a = ( dtipsq+dtisq )*w - dtipsq*dtisq*dw b = dtipsq*dtisq*w if( c==zero ) then if( a==zero ) then if( .not.swtch ) then if( orgati ) then a = z( i )*z( i ) + dtipsq*dtipsq*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) +dtisq*dtisq*( dpsi+dphi ) end if else a = dtisq*dtisq*dpsi + dtipsq*dtipsq*dphi end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles dtiim = work( iim1 )*delta( iim1 ) dtiip = work( iip1 )*delta( iip1 ) temp = rhoinv + psi + phi if( swtch ) then c = temp - dtiim*dpsi - dtiip*dphi zz( 1_${ik}$ ) = dtiim*dtiim*dpsi zz( 3_${ik}$ ) = dtiip*dtiip*dphi else if( orgati ) then temp1 = z( iim1 ) / dtiim temp1 = temp1*temp1 temp2 = ( d( iim1 )-d( iip1 ) )*( d( iim1 )+d( iip1 ) )*temp1 c = temp - dtiip*( dpsi+dphi ) - temp2 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) if( dpsi 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw eta = eta / ( sigma+sqrt( sigma*sigma+eta ) ) temp=tau+eta if( temp>sgub .or. temp zero ) then eta = sqrt(sgub*tau)-tau end if else if( sglb > zero ) then eta = sqrt(sglb*tau)-tau end if end if end if end if prew = w tau = tau + eta sigma = sigma + eta do j = 1, n work( j ) = work( j ) + eta delta( j ) = delta( j ) - eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, iim1 temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi dphi = zero phi = zero do j = n, iip1, -1 temp = z( j ) / ( work( j )*delta( j ) ) phi = phi + z( j )*temp dphi = dphi + temp*temp erretm = erretm + phi end do tau2 = work( ii )*delta( ii ) temp = z( ii ) / tau2 dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = rhoinv + phi + psi + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv+ three*abs( temp ) ! $ + abs( tau2 )*dw if( w*prew>zero .and. abs( w )>abs( prew ) / ten )swtch = .not.swtch end do loop_230 ! return with info = 1, niter = maxit and not converged info = 1_${ik}$ end if 240 continue return end subroutine stdlib${ii}$_slasd4 pure module subroutine stdlib${ii}$_dlasd4( n, i, d, z, delta, rho, sigma, work, info ) !! This subroutine computes the square root of the I-th updated !! eigenvalue of a positive symmetric rank-one modification to !! a positive diagonal matrix whose entries are given as the squares !! of the corresponding entries in the array d, and that !! 0 <= D(i) < D(j) for i < j !! and that RHO > 0. This is arranged by the calling routine, and is !! no loss in generality. The rank-one modified system is thus !! diag( D ) * diag( D ) + RHO * Z * Z_transpose. !! where we assume the Euclidean norm of Z is 1. !! The method consists of approximating the rational functions in the !! secular equation by simpler interpolating rational functions. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i, n integer(${ik}$), intent(out) :: info real(dp), intent(in) :: rho real(dp), intent(out) :: sigma ! Array Arguments real(dp), intent(in) :: d(*), z(*) real(dp), intent(out) :: delta(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 400_${ik}$ ! Local Scalars logical(lk) :: orgati, swtch, swtch3, geomavg integer(${ik}$) :: ii, iim1, iip1, ip1, iter, j, niter real(dp) :: a, b, c, delsq, delsq2, sq2, dphi, dpsi, dtiim, dtiip, dtipsq, dtisq, & dtnsq, dtnsq1, dw, eps, erretm, eta, phi, prew, psi, rhoinv, sglb, sgub, tau, tau2, & temp, temp1, temp2, w ! Local Arrays real(dp) :: dd(3_${ik}$), zz(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! since this routine is called in an inner loop, we do no argument ! checking. ! quick return for n=1 and 2. info = 0_${ik}$ if( n==1_${ik}$ ) then ! presumably, i=1 upon entry sigma = sqrt( d( 1_${ik}$ )*d( 1_${ik}$ )+rho*z( 1_${ik}$ )*z( 1_${ik}$ ) ) delta( 1_${ik}$ ) = one work( 1_${ik}$ ) = one return end if if( n==2_${ik}$ ) then call stdlib${ii}$_dlasd5( i, d, z, delta, rho, sigma, work ) return end if ! compute machine epsilon eps = stdlib${ii}$_dlamch( 'EPSILON' ) rhoinv = one / rho tau2= zero ! the case i = n if( i==n ) then ! initialize some basic variables ii = n - 1_${ik}$ niter = 1_${ik}$ ! calculate initial guess temp = rho / two ! if ||z||_2 is not one, then temp should be set to ! rho * ||z||_2^2 / two temp1 = temp / ( d( n )+sqrt( d( n )*d( n )+temp ) ) do j = 1, n work( j ) = d( j ) + d( n ) + temp1 delta( j ) = ( d( j )-d( n ) ) - temp1 end do psi = zero do j = 1, n - 2 psi = psi + z( j )*z( j ) / ( delta( j )*work( j ) ) end do c = rhoinv + psi w = c + z( ii )*z( ii ) / ( delta( ii )*work( ii ) ) +z( n )*z( n ) / ( delta( n )& *work( n ) ) if( w<=zero ) then temp1 = sqrt( d( n )*d( n )+rho ) temp = z( n-1 )*z( n-1 ) / ( ( d( n-1 )+temp1 )*( d( n )-d( n-1 )+rho / ( d( n )+& temp1 ) ) ) +z( n )*z( n ) / rho ! the following tau2 is to approximate ! sigma_n^2 - d( n )*d( n ) if( c<=temp ) then tau = rho else delsq = ( d( n )-d( n-1 ) )*( d( n )+d( n-1 ) ) a = -c*delsq + z( n-1 )*z( n-1 ) + z( n )*z( n ) b = z( n )*z( n )*delsq if( a=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = eta - dtnsq if( temp>rho )eta = rho + dtnsq eta = eta / ( sigma+sqrt( eta+sigma*sigma ) ) tau = tau + eta sigma = sigma + eta do j = 1, n delta( j ) = delta( j ) - eta work( j ) = work( j ) + eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, ii temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi tau2 = work( n )*delta( n ) temp = z( n ) / tau2 phi = z( n )*temp dphi = temp*temp erretm = eight*( -phi-psi ) + erretm - phi + rhoinv ! $ + abs( tau2 )*( dpsi+dphi ) w = rhoinv + phi + psi ! main loop to update the values of the array delta iter = niter + 1_${ik}$ loop_90: do niter = iter, maxit ! test for convergence if( abs( w )<=eps*erretm ) then go to 240 end if ! calculate the new step dtnsq1 = work( n-1 )*delta( n-1 ) dtnsq = work( n )*delta( n ) c = w - dtnsq1*dpsi - dtnsq*dphi a = ( dtnsq+dtnsq1 )*w - dtnsq1*dtnsq*( dpsi+dphi ) b = dtnsq1*dtnsq*w if( a>=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = eta - dtnsq if( temp<=zero )eta = eta / two eta = eta / ( sigma+sqrt( eta+sigma*sigma ) ) tau = tau + eta sigma = sigma + eta do j = 1, n delta( j ) = delta( j ) - eta work( j ) = work( j ) + eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, ii temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi tau2 = work( n )*delta( n ) temp = z( n ) / tau2 phi = z( n )*temp dphi = temp*temp erretm = eight*( -phi-psi ) + erretm - phi + rhoinv ! $ + abs( tau2 )*( dpsi+dphi ) w = rhoinv + phi + psi end do loop_90 ! return with info = 1, niter = maxit and not converged info = 1_${ik}$ go to 240 ! end for the case i = n else ! the case for i < n niter = 1_${ik}$ ip1 = i + 1_${ik}$ ! calculate initial guess delsq = ( d( ip1 )-d( i ) )*( d( ip1 )+d( i ) ) delsq2 = delsq / two sq2=sqrt( ( d( i )*d( i )+d( ip1 )*d( ip1 ) ) / two ) temp = delsq2 / ( d( i )+sq2 ) do j = 1, n work( j ) = d( j ) + d( i ) + temp delta( j ) = ( d( j )-d( i ) ) - temp end do psi = zero do j = 1, i - 1 psi = psi + z( j )*z( j ) / ( work( j )*delta( j ) ) end do phi = zero do j = n, i + 2, -1 phi = phi + z( j )*z( j ) / ( work( j )*delta( j ) ) end do c = rhoinv + psi + phi w = c + z( i )*z( i ) / ( work( i )*delta( i ) ) +z( ip1 )*z( ip1 ) / ( work( ip1 )& *delta( ip1 ) ) geomavg = .false. if( w>zero ) then ! d(i)^2 < the ith sigma^2 < (d(i)^2+d(i+1)^2)/2 ! we choose d(i) as origin. orgati = .true. ii = i sglb = zero sgub = delsq2 / ( d( i )+sq2 ) a = c*delsq + z( i )*z( i ) + z( ip1 )*z( ip1 ) b = z( i )*z( i )*delsq if( a>zero ) then tau2 = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) else tau2 = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) end if ! tau2 now is an estimation of sigma^2 - d( i )^2. the ! following, however, is the corresponding estimation of ! sigma - d( i ). tau = tau2 / ( d( i )+sqrt( d( i )*d( i )+tau2 ) ) temp = sqrt(eps) if( (d(i)<=temp*d(ip1)).and.(abs(z(i))<=temp).and.(d(i)>zero) ) then tau = min( ten*d(i), sgub ) geomavg = .true. end if else ! (d(i)^2+d(i+1)^2)/2 <= the ith sigma^2 < d(i+1)^2/2 ! we choose d(i+1) as origin. orgati = .false. ii = ip1 sglb = -delsq2 / ( d( ii )+sq2 ) sgub = zero a = c*delsq - z( i )*z( i ) - z( ip1 )*z( ip1 ) b = z( ip1 )*z( ip1 )*delsq if( azero )swtch3 = .true. end if if( ii==1_${ik}$ .or. ii==n )swtch3 = .false. temp = z( ii ) / ( work( ii )*delta( ii ) ) dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = w + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv+ three*abs( temp ) ! $ + abs( tau2 )*dw ! test for convergence if( abs( w )<=eps*erretm ) then go to 240 end if if( w<=zero ) then sglb = max( sglb, tau ) else sgub = min( sgub, tau ) end if ! calculate the new step niter = niter + 1_${ik}$ if( .not.swtch3 ) then dtipsq = work( ip1 )*delta( ip1 ) dtisq = work( i )*delta( i ) if( orgati ) then c = w - dtipsq*dw + delsq*( z( i ) / dtisq )**2_${ik}$ else c = w - dtisq*dw - delsq*( z( ip1 ) / dtipsq )**2_${ik}$ end if a = ( dtipsq+dtisq )*w - dtipsq*dtisq*dw b = dtipsq*dtisq*w if( c==zero ) then if( a==zero ) then if( orgati ) then a = z( i )*z( i ) + dtipsq*dtipsq*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) + dtisq*dtisq*( dpsi+dphi ) end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles dtiim = work( iim1 )*delta( iim1 ) dtiip = work( iip1 )*delta( iip1 ) temp = rhoinv + psi + phi if( orgati ) then temp1 = z( iim1 ) / dtiim temp1 = temp1*temp1 c = ( temp - dtiip*( dpsi+dphi ) ) -( d( iim1 )-d( iip1 ) )*( d( iim1 )+d( & iip1 ) )*temp1 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) if( dpsi 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw eta = eta / ( sigma+sqrt( sigma*sigma+eta ) ) temp = tau + eta if( temp>sgub .or. temp zero ) then eta = sqrt(sgub*tau)-tau end if else if( sglb > zero ) then eta = sqrt(sglb*tau)-tau end if end if end if end if prew = w tau = tau + eta sigma = sigma + eta do j = 1, n work( j ) = work( j ) + eta delta( j ) = delta( j ) - eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, iim1 temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi dphi = zero phi = zero do j = n, iip1, -1 temp = z( j ) / ( work( j )*delta( j ) ) phi = phi + z( j )*temp dphi = dphi + temp*temp erretm = erretm + phi end do tau2 = work( ii )*delta( ii ) temp = z( ii ) / tau2 dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = rhoinv + phi + psi + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv+ three*abs( temp ) ! $ + abs( tau2 )*dw swtch = .false. if( orgati ) then if( -w>abs( prew ) / ten )swtch = .true. else if( w>abs( prew ) / ten )swtch = .true. end if ! main loop to update the values of the array delta and work iter = niter + 1_${ik}$ loop_230: do niter = iter, maxit ! test for convergence if( abs( w )<=eps*erretm ) then ! $ .or. (sgub-sglb)<=eight*abs(sgub+sglb) ) then go to 240 end if if( w<=zero ) then sglb = max( sglb, tau ) else sgub = min( sgub, tau ) end if ! calculate the new step if( .not.swtch3 ) then dtipsq = work( ip1 )*delta( ip1 ) dtisq = work( i )*delta( i ) if( .not.swtch ) then if( orgati ) then c = w - dtipsq*dw + delsq*( z( i ) / dtisq )**2_${ik}$ else c = w - dtisq*dw - delsq*( z( ip1 ) / dtipsq )**2_${ik}$ end if else temp = z( ii ) / ( work( ii )*delta( ii ) ) if( orgati ) then dpsi = dpsi + temp*temp else dphi = dphi + temp*temp end if c = w - dtisq*dpsi - dtipsq*dphi end if a = ( dtipsq+dtisq )*w - dtipsq*dtisq*dw b = dtipsq*dtisq*w if( c==zero ) then if( a==zero ) then if( .not.swtch ) then if( orgati ) then a = z( i )*z( i ) + dtipsq*dtipsq*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) +dtisq*dtisq*( dpsi+dphi ) end if else a = dtisq*dtisq*dpsi + dtipsq*dtipsq*dphi end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles dtiim = work( iim1 )*delta( iim1 ) dtiip = work( iip1 )*delta( iip1 ) temp = rhoinv + psi + phi if( swtch ) then c = temp - dtiim*dpsi - dtiip*dphi zz( 1_${ik}$ ) = dtiim*dtiim*dpsi zz( 3_${ik}$ ) = dtiip*dtiip*dphi else if( orgati ) then temp1 = z( iim1 ) / dtiim temp1 = temp1*temp1 temp2 = ( d( iim1 )-d( iip1 ) )*( d( iim1 )+d( iip1 ) )*temp1 c = temp - dtiip*( dpsi+dphi ) - temp2 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) if( dpsi 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw eta = eta / ( sigma+sqrt( sigma*sigma+eta ) ) temp=tau+eta if( temp>sgub .or. temp zero ) then eta = sqrt(sgub*tau)-tau end if else if( sglb > zero ) then eta = sqrt(sglb*tau)-tau end if end if end if end if prew = w tau = tau + eta sigma = sigma + eta do j = 1, n work( j ) = work( j ) + eta delta( j ) = delta( j ) - eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, iim1 temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi dphi = zero phi = zero do j = n, iip1, -1 temp = z( j ) / ( work( j )*delta( j ) ) phi = phi + z( j )*temp dphi = dphi + temp*temp erretm = erretm + phi end do tau2 = work( ii )*delta( ii ) temp = z( ii ) / tau2 dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = rhoinv + phi + psi + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv+ three*abs( temp ) ! $ + abs( tau2 )*dw if( w*prew>zero .and. abs( w )>abs( prew ) / ten )swtch = .not.swtch end do loop_230 ! return with info = 1, niter = maxit and not converged info = 1_${ik}$ end if 240 continue return end subroutine stdlib${ii}$_dlasd4 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasd4( n, i, d, z, delta, rho, sigma, work, info ) !! This subroutine computes the square root of the I-th updated !! eigenvalue of a positive symmetric rank-one modification to !! a positive diagonal matrix whose entries are given as the squares !! of the corresponding entries in the array d, and that !! 0 <= D(i) < D(j) for i < j !! and that RHO > 0. This is arranged by the calling routine, and is !! no loss in generality. The rank-one modified system is thus !! diag( D ) * diag( D ) + RHO * Z * Z_transpose. !! where we assume the Euclidean norm of Z is 1. !! The method consists of approximating the rational functions in the !! secular equation by simpler interpolating rational functions. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i, n integer(${ik}$), intent(out) :: info real(${rk}$), intent(in) :: rho real(${rk}$), intent(out) :: sigma ! Array Arguments real(${rk}$), intent(in) :: d(*), z(*) real(${rk}$), intent(out) :: delta(*), work(*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: maxit = 400_${ik}$ ! Local Scalars logical(lk) :: orgati, swtch, swtch3, geomavg integer(${ik}$) :: ii, iim1, iip1, ip1, iter, j, niter real(${rk}$) :: a, b, c, delsq, delsq2, sq2, dphi, dpsi, dtiim, dtiip, dtipsq, dtisq, & dtnsq, dtnsq1, dw, eps, erretm, eta, phi, prew, psi, rhoinv, sglb, sgub, tau, tau2, & temp, temp1, temp2, w ! Local Arrays real(${rk}$) :: dd(3_${ik}$), zz(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! since this routine is called in an inner loop, we do no argument ! checking. ! quick return for n=1 and 2. info = 0_${ik}$ if( n==1_${ik}$ ) then ! presumably, i=1 upon entry sigma = sqrt( d( 1_${ik}$ )*d( 1_${ik}$ )+rho*z( 1_${ik}$ )*z( 1_${ik}$ ) ) delta( 1_${ik}$ ) = one work( 1_${ik}$ ) = one return end if if( n==2_${ik}$ ) then call stdlib${ii}$_${ri}$lasd5( i, d, z, delta, rho, sigma, work ) return end if ! compute machine epsilon eps = stdlib${ii}$_${ri}$lamch( 'EPSILON' ) rhoinv = one / rho tau2= zero ! the case i = n if( i==n ) then ! initialize some basic variables ii = n - 1_${ik}$ niter = 1_${ik}$ ! calculate initial guess temp = rho / two ! if ||z||_2 is not one, then temp should be set to ! rho * ||z||_2^2 / two temp1 = temp / ( d( n )+sqrt( d( n )*d( n )+temp ) ) do j = 1, n work( j ) = d( j ) + d( n ) + temp1 delta( j ) = ( d( j )-d( n ) ) - temp1 end do psi = zero do j = 1, n - 2 psi = psi + z( j )*z( j ) / ( delta( j )*work( j ) ) end do c = rhoinv + psi w = c + z( ii )*z( ii ) / ( delta( ii )*work( ii ) ) +z( n )*z( n ) / ( delta( n )& *work( n ) ) if( w<=zero ) then temp1 = sqrt( d( n )*d( n )+rho ) temp = z( n-1 )*z( n-1 ) / ( ( d( n-1 )+temp1 )*( d( n )-d( n-1 )+rho / ( d( n )+& temp1 ) ) ) +z( n )*z( n ) / rho ! the following tau2 is to approximate ! sigma_n^2 - d( n )*d( n ) if( c<=temp ) then tau = rho else delsq = ( d( n )-d( n-1 ) )*( d( n )+d( n-1 ) ) a = -c*delsq + z( n-1 )*z( n-1 ) + z( n )*z( n ) b = z( n )*z( n )*delsq if( a=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = eta - dtnsq if( temp>rho )eta = rho + dtnsq eta = eta / ( sigma+sqrt( eta+sigma*sigma ) ) tau = tau + eta sigma = sigma + eta do j = 1, n delta( j ) = delta( j ) - eta work( j ) = work( j ) + eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, ii temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi tau2 = work( n )*delta( n ) temp = z( n ) / tau2 phi = z( n )*temp dphi = temp*temp erretm = eight*( -phi-psi ) + erretm - phi + rhoinv ! $ + abs( tau2 )*( dpsi+dphi ) w = rhoinv + phi + psi ! main loop to update the values of the array delta iter = niter + 1_${ik}$ loop_90: do niter = iter, maxit ! test for convergence if( abs( w )<=eps*erretm ) then go to 240 end if ! calculate the new step dtnsq1 = work( n-1 )*delta( n-1 ) dtnsq = work( n )*delta( n ) c = w - dtnsq1*dpsi - dtnsq*dphi a = ( dtnsq+dtnsq1 )*w - dtnsq1*dtnsq*( dpsi+dphi ) b = dtnsq1*dtnsq*w if( a>=zero ) then eta = ( a+sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a-sqrt( abs( a*a-four*b*c ) ) ) end if ! note, eta should be positive if w is negative, and ! eta should be negative otherwise. however, ! if for some reason caused by roundoff, eta*w > 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>zero )eta = -w / ( dpsi+dphi ) temp = eta - dtnsq if( temp<=zero )eta = eta / two eta = eta / ( sigma+sqrt( eta+sigma*sigma ) ) tau = tau + eta sigma = sigma + eta do j = 1, n delta( j ) = delta( j ) - eta work( j ) = work( j ) + eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, ii temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi tau2 = work( n )*delta( n ) temp = z( n ) / tau2 phi = z( n )*temp dphi = temp*temp erretm = eight*( -phi-psi ) + erretm - phi + rhoinv ! $ + abs( tau2 )*( dpsi+dphi ) w = rhoinv + phi + psi end do loop_90 ! return with info = 1, niter = maxit and not converged info = 1_${ik}$ go to 240 ! end for the case i = n else ! the case for i < n niter = 1_${ik}$ ip1 = i + 1_${ik}$ ! calculate initial guess delsq = ( d( ip1 )-d( i ) )*( d( ip1 )+d( i ) ) delsq2 = delsq / two sq2=sqrt( ( d( i )*d( i )+d( ip1 )*d( ip1 ) ) / two ) temp = delsq2 / ( d( i )+sq2 ) do j = 1, n work( j ) = d( j ) + d( i ) + temp delta( j ) = ( d( j )-d( i ) ) - temp end do psi = zero do j = 1, i - 1 psi = psi + z( j )*z( j ) / ( work( j )*delta( j ) ) end do phi = zero do j = n, i + 2, -1 phi = phi + z( j )*z( j ) / ( work( j )*delta( j ) ) end do c = rhoinv + psi + phi w = c + z( i )*z( i ) / ( work( i )*delta( i ) ) +z( ip1 )*z( ip1 ) / ( work( ip1 )& *delta( ip1 ) ) geomavg = .false. if( w>zero ) then ! d(i)^2 < the ith sigma^2 < (d(i)^2+d(i+1)^2)/2 ! we choose d(i) as origin. orgati = .true. ii = i sglb = zero sgub = delsq2 / ( d( i )+sq2 ) a = c*delsq + z( i )*z( i ) + z( ip1 )*z( ip1 ) b = z( i )*z( i )*delsq if( a>zero ) then tau2 = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) else tau2 = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) end if ! tau2 now is an estimation of sigma^2 - d( i )^2. the ! following, however, is the corresponding estimation of ! sigma - d( i ). tau = tau2 / ( d( i )+sqrt( d( i )*d( i )+tau2 ) ) temp = sqrt(eps) if( (d(i)<=temp*d(ip1)).and.(abs(z(i))<=temp).and.(d(i)>zero) ) then tau = min( ten*d(i), sgub ) geomavg = .true. end if else ! (d(i)^2+d(i+1)^2)/2 <= the ith sigma^2 < d(i+1)^2/2 ! we choose d(i+1) as origin. orgati = .false. ii = ip1 sglb = -delsq2 / ( d( ii )+sq2 ) sgub = zero a = c*delsq - z( i )*z( i ) - z( ip1 )*z( ip1 ) b = z( ip1 )*z( ip1 )*delsq if( azero )swtch3 = .true. end if if( ii==1_${ik}$ .or. ii==n )swtch3 = .false. temp = z( ii ) / ( work( ii )*delta( ii ) ) dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = w + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv+ three*abs( temp ) ! $ + abs( tau2 )*dw ! test for convergence if( abs( w )<=eps*erretm ) then go to 240 end if if( w<=zero ) then sglb = max( sglb, tau ) else sgub = min( sgub, tau ) end if ! calculate the new step niter = niter + 1_${ik}$ if( .not.swtch3 ) then dtipsq = work( ip1 )*delta( ip1 ) dtisq = work( i )*delta( i ) if( orgati ) then c = w - dtipsq*dw + delsq*( z( i ) / dtisq )**2_${ik}$ else c = w - dtisq*dw - delsq*( z( ip1 ) / dtipsq )**2_${ik}$ end if a = ( dtipsq+dtisq )*w - dtipsq*dtisq*dw b = dtipsq*dtisq*w if( c==zero ) then if( a==zero ) then if( orgati ) then a = z( i )*z( i ) + dtipsq*dtipsq*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) + dtisq*dtisq*( dpsi+dphi ) end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles dtiim = work( iim1 )*delta( iim1 ) dtiip = work( iip1 )*delta( iip1 ) temp = rhoinv + psi + phi if( orgati ) then temp1 = z( iim1 ) / dtiim temp1 = temp1*temp1 c = ( temp - dtiip*( dpsi+dphi ) ) -( d( iim1 )-d( iip1 ) )*( d( iim1 )+d( & iip1 ) )*temp1 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) if( dpsi 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw eta = eta / ( sigma+sqrt( sigma*sigma+eta ) ) temp = tau + eta if( temp>sgub .or. temp zero ) then eta = sqrt(sgub*tau)-tau end if else if( sglb > zero ) then eta = sqrt(sglb*tau)-tau end if end if end if end if prew = w tau = tau + eta sigma = sigma + eta do j = 1, n work( j ) = work( j ) + eta delta( j ) = delta( j ) - eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, iim1 temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi dphi = zero phi = zero do j = n, iip1, -1 temp = z( j ) / ( work( j )*delta( j ) ) phi = phi + z( j )*temp dphi = dphi + temp*temp erretm = erretm + phi end do tau2 = work( ii )*delta( ii ) temp = z( ii ) / tau2 dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = rhoinv + phi + psi + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv+ three*abs( temp ) ! $ + abs( tau2 )*dw swtch = .false. if( orgati ) then if( -w>abs( prew ) / ten )swtch = .true. else if( w>abs( prew ) / ten )swtch = .true. end if ! main loop to update the values of the array delta and work iter = niter + 1_${ik}$ loop_230: do niter = iter, maxit ! test for convergence if( abs( w )<=eps*erretm ) then ! $ .or. (sgub-sglb)<=eight*abs(sgub+sglb) ) then go to 240 end if if( w<=zero ) then sglb = max( sglb, tau ) else sgub = min( sgub, tau ) end if ! calculate the new step if( .not.swtch3 ) then dtipsq = work( ip1 )*delta( ip1 ) dtisq = work( i )*delta( i ) if( .not.swtch ) then if( orgati ) then c = w - dtipsq*dw + delsq*( z( i ) / dtisq )**2_${ik}$ else c = w - dtisq*dw - delsq*( z( ip1 ) / dtipsq )**2_${ik}$ end if else temp = z( ii ) / ( work( ii )*delta( ii ) ) if( orgati ) then dpsi = dpsi + temp*temp else dphi = dphi + temp*temp end if c = w - dtisq*dpsi - dtipsq*dphi end if a = ( dtipsq+dtisq )*w - dtipsq*dtisq*dw b = dtipsq*dtisq*w if( c==zero ) then if( a==zero ) then if( .not.swtch ) then if( orgati ) then a = z( i )*z( i ) + dtipsq*dtipsq*( dpsi+dphi ) else a = z( ip1 )*z( ip1 ) +dtisq*dtisq*( dpsi+dphi ) end if else a = dtisq*dtisq*dpsi + dtipsq*dtipsq*dphi end if end if eta = b / a else if( a<=zero ) then eta = ( a-sqrt( abs( a*a-four*b*c ) ) ) / ( two*c ) else eta = two*b / ( a+sqrt( abs( a*a-four*b*c ) ) ) end if else ! interpolation using three most relevant poles dtiim = work( iim1 )*delta( iim1 ) dtiip = work( iip1 )*delta( iip1 ) temp = rhoinv + psi + phi if( swtch ) then c = temp - dtiim*dpsi - dtiip*dphi zz( 1_${ik}$ ) = dtiim*dtiim*dpsi zz( 3_${ik}$ ) = dtiip*dtiip*dphi else if( orgati ) then temp1 = z( iim1 ) / dtiim temp1 = temp1*temp1 temp2 = ( d( iim1 )-d( iip1 ) )*( d( iim1 )+d( iip1 ) )*temp1 c = temp - dtiip*( dpsi+dphi ) - temp2 zz( 1_${ik}$ ) = z( iim1 )*z( iim1 ) if( dpsi 0, ! we simply use one newton step instead. this way ! will guarantee eta*w < 0. if( w*eta>=zero )eta = -w / dw eta = eta / ( sigma+sqrt( sigma*sigma+eta ) ) temp=tau+eta if( temp>sgub .or. temp zero ) then eta = sqrt(sgub*tau)-tau end if else if( sglb > zero ) then eta = sqrt(sglb*tau)-tau end if end if end if end if prew = w tau = tau + eta sigma = sigma + eta do j = 1, n work( j ) = work( j ) + eta delta( j ) = delta( j ) - eta end do ! evaluate psi and the derivative dpsi dpsi = zero psi = zero erretm = zero do j = 1, iim1 temp = z( j ) / ( work( j )*delta( j ) ) psi = psi + z( j )*temp dpsi = dpsi + temp*temp erretm = erretm + psi end do erretm = abs( erretm ) ! evaluate phi and the derivative dphi dphi = zero phi = zero do j = n, iip1, -1 temp = z( j ) / ( work( j )*delta( j ) ) phi = phi + z( j )*temp dphi = dphi + temp*temp erretm = erretm + phi end do tau2 = work( ii )*delta( ii ) temp = z( ii ) / tau2 dw = dpsi + dphi + temp*temp temp = z( ii )*temp w = rhoinv + phi + psi + temp erretm = eight*( phi-psi ) + erretm + two*rhoinv+ three*abs( temp ) ! $ + abs( tau2 )*dw if( w*prew>zero .and. abs( w )>abs( prew ) / ten )swtch = .not.swtch end do loop_230 ! return with info = 1, niter = maxit and not converged info = 1_${ik}$ end if 240 continue return end subroutine stdlib${ii}$_${ri}$lasd4 #:endif #:endfor pure module subroutine stdlib${ii}$_slasd5( i, d, z, delta, rho, dsigma, work ) !! This subroutine computes the square root of the I-th eigenvalue !! of a positive symmetric rank-one modification of a 2-by-2 diagonal !! matrix !! diag( D ) * diag( D ) + RHO * Z * transpose(Z) . !! The diagonal entries in the array D are assumed to satisfy !! 0 <= D(i) < D(j) for i < j . !! We also assume RHO > 0 and that the Euclidean norm of the vector !! Z is one. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i real(sp), intent(out) :: dsigma real(sp), intent(in) :: rho ! Array Arguments real(sp), intent(in) :: d(2_${ik}$), z(2_${ik}$) real(sp), intent(out) :: delta(2_${ik}$), work(2_${ik}$) ! ===================================================================== ! Local Scalars real(sp) :: b, c, del, delsq, tau, w ! Intrinsic Functions ! Executable Statements del = d( 2_${ik}$ ) - d( 1_${ik}$ ) delsq = del*( d( 2_${ik}$ )+d( 1_${ik}$ ) ) if( i==1_${ik}$ ) then w = one + four*rho*( z( 2_${ik}$ )*z( 2_${ik}$ ) / ( d( 1_${ik}$ )+three*d( 2_${ik}$ ) )-z( 1_${ik}$ )*z( 1_${ik}$ ) / ( & three*d( 1_${ik}$ )+d( 2_${ik}$ ) ) ) / del if( w>zero ) then b = delsq + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 1_${ik}$ )*z( 1_${ik}$ )*delsq ! b > zero, always ! the following tau is dsigma * dsigma - d( 1 ) * d( 1 ) tau = two*c / ( b+sqrt( abs( b*b-four*c ) ) ) ! the following tau is dsigma - d( 1 ) tau = tau / ( d( 1_${ik}$ )+sqrt( d( 1_${ik}$ )*d( 1_${ik}$ )+tau ) ) dsigma = d( 1_${ik}$ ) + tau delta( 1_${ik}$ ) = -tau delta( 2_${ik}$ ) = del - tau work( 1_${ik}$ ) = two*d( 1_${ik}$ ) + tau work( 2_${ik}$ ) = ( d( 1_${ik}$ )+tau ) + d( 2_${ik}$ ) ! delta( 1 ) = -z( 1 ) / tau ! delta( 2 ) = z( 2 ) / ( del-tau ) else b = -delsq + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*delsq ! the following tau is dsigma * dsigma - d( 2 ) * d( 2 ) if( b>zero ) then tau = -two*c / ( b+sqrt( b*b+four*c ) ) else tau = ( b-sqrt( b*b+four*c ) ) / two end if ! the following tau is dsigma - d( 2 ) tau = tau / ( d( 2_${ik}$ )+sqrt( abs( d( 2_${ik}$ )*d( 2_${ik}$ )+tau ) ) ) dsigma = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -( del+tau ) delta( 2_${ik}$ ) = -tau work( 1_${ik}$ ) = d( 1_${ik}$ ) + tau + d( 2_${ik}$ ) work( 2_${ik}$ ) = two*d( 2_${ik}$ ) + tau ! delta( 1 ) = -z( 1 ) / ( del+tau ) ! delta( 2 ) = -z( 2 ) / tau end if ! temp = sqrt( delta( 1 )*delta( 1 )+delta( 2 )*delta( 2 ) ) ! delta( 1 ) = delta( 1 ) / temp ! delta( 2 ) = delta( 2 ) / temp else ! now i=2 b = -delsq + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*delsq ! the following tau is dsigma * dsigma - d( 2 ) * d( 2 ) if( b>zero ) then tau = ( b+sqrt( b*b+four*c ) ) / two else tau = two*c / ( -b+sqrt( b*b+four*c ) ) end if ! the following tau is dsigma - d( 2 ) tau = tau / ( d( 2_${ik}$ )+sqrt( d( 2_${ik}$ )*d( 2_${ik}$ )+tau ) ) dsigma = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -( del+tau ) delta( 2_${ik}$ ) = -tau work( 1_${ik}$ ) = d( 1_${ik}$ ) + tau + d( 2_${ik}$ ) work( 2_${ik}$ ) = two*d( 2_${ik}$ ) + tau ! delta( 1 ) = -z( 1 ) / ( del+tau ) ! delta( 2 ) = -z( 2 ) / tau ! temp = sqrt( delta( 1 )*delta( 1 )+delta( 2 )*delta( 2 ) ) ! delta( 1 ) = delta( 1 ) / temp ! delta( 2 ) = delta( 2 ) / temp end if return end subroutine stdlib${ii}$_slasd5 pure module subroutine stdlib${ii}$_dlasd5( i, d, z, delta, rho, dsigma, work ) !! This subroutine computes the square root of the I-th eigenvalue !! of a positive symmetric rank-one modification of a 2-by-2 diagonal !! matrix !! diag( D ) * diag( D ) + RHO * Z * transpose(Z) . !! The diagonal entries in the array D are assumed to satisfy !! 0 <= D(i) < D(j) for i < j . !! We also assume RHO > 0 and that the Euclidean norm of the vector !! Z is one. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i real(dp), intent(out) :: dsigma real(dp), intent(in) :: rho ! Array Arguments real(dp), intent(in) :: d(2_${ik}$), z(2_${ik}$) real(dp), intent(out) :: delta(2_${ik}$), work(2_${ik}$) ! ===================================================================== ! Local Scalars real(dp) :: b, c, del, delsq, tau, w ! Intrinsic Functions ! Executable Statements del = d( 2_${ik}$ ) - d( 1_${ik}$ ) delsq = del*( d( 2_${ik}$ )+d( 1_${ik}$ ) ) if( i==1_${ik}$ ) then w = one + four*rho*( z( 2_${ik}$ )*z( 2_${ik}$ ) / ( d( 1_${ik}$ )+three*d( 2_${ik}$ ) )-z( 1_${ik}$ )*z( 1_${ik}$ ) / ( & three*d( 1_${ik}$ )+d( 2_${ik}$ ) ) ) / del if( w>zero ) then b = delsq + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 1_${ik}$ )*z( 1_${ik}$ )*delsq ! b > zero, always ! the following tau is dsigma * dsigma - d( 1 ) * d( 1 ) tau = two*c / ( b+sqrt( abs( b*b-four*c ) ) ) ! the following tau is dsigma - d( 1 ) tau = tau / ( d( 1_${ik}$ )+sqrt( d( 1_${ik}$ )*d( 1_${ik}$ )+tau ) ) dsigma = d( 1_${ik}$ ) + tau delta( 1_${ik}$ ) = -tau delta( 2_${ik}$ ) = del - tau work( 1_${ik}$ ) = two*d( 1_${ik}$ ) + tau work( 2_${ik}$ ) = ( d( 1_${ik}$ )+tau ) + d( 2_${ik}$ ) ! delta( 1 ) = -z( 1 ) / tau ! delta( 2 ) = z( 2 ) / ( del-tau ) else b = -delsq + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*delsq ! the following tau is dsigma * dsigma - d( 2 ) * d( 2 ) if( b>zero ) then tau = -two*c / ( b+sqrt( b*b+four*c ) ) else tau = ( b-sqrt( b*b+four*c ) ) / two end if ! the following tau is dsigma - d( 2 ) tau = tau / ( d( 2_${ik}$ )+sqrt( abs( d( 2_${ik}$ )*d( 2_${ik}$ )+tau ) ) ) dsigma = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -( del+tau ) delta( 2_${ik}$ ) = -tau work( 1_${ik}$ ) = d( 1_${ik}$ ) + tau + d( 2_${ik}$ ) work( 2_${ik}$ ) = two*d( 2_${ik}$ ) + tau ! delta( 1 ) = -z( 1 ) / ( del+tau ) ! delta( 2 ) = -z( 2 ) / tau end if ! temp = sqrt( delta( 1 )*delta( 1 )+delta( 2 )*delta( 2 ) ) ! delta( 1 ) = delta( 1 ) / temp ! delta( 2 ) = delta( 2 ) / temp else ! now i=2 b = -delsq + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*delsq ! the following tau is dsigma * dsigma - d( 2 ) * d( 2 ) if( b>zero ) then tau = ( b+sqrt( b*b+four*c ) ) / two else tau = two*c / ( -b+sqrt( b*b+four*c ) ) end if ! the following tau is dsigma - d( 2 ) tau = tau / ( d( 2_${ik}$ )+sqrt( d( 2_${ik}$ )*d( 2_${ik}$ )+tau ) ) dsigma = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -( del+tau ) delta( 2_${ik}$ ) = -tau work( 1_${ik}$ ) = d( 1_${ik}$ ) + tau + d( 2_${ik}$ ) work( 2_${ik}$ ) = two*d( 2_${ik}$ ) + tau ! delta( 1 ) = -z( 1 ) / ( del+tau ) ! delta( 2 ) = -z( 2 ) / tau ! temp = sqrt( delta( 1 )*delta( 1 )+delta( 2 )*delta( 2 ) ) ! delta( 1 ) = delta( 1 ) / temp ! delta( 2 ) = delta( 2 ) / temp end if return end subroutine stdlib${ii}$_dlasd5 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasd5( i, d, z, delta, rho, dsigma, work ) !! This subroutine computes the square root of the I-th eigenvalue !! of a positive symmetric rank-one modification of a 2-by-2 diagonal !! matrix !! diag( D ) * diag( D ) + RHO * Z * transpose(Z) . !! The diagonal entries in the array D are assumed to satisfy !! 0 <= D(i) < D(j) for i < j . !! We also assume RHO > 0 and that the Euclidean norm of the vector !! Z is one. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: i real(${rk}$), intent(out) :: dsigma real(${rk}$), intent(in) :: rho ! Array Arguments real(${rk}$), intent(in) :: d(2_${ik}$), z(2_${ik}$) real(${rk}$), intent(out) :: delta(2_${ik}$), work(2_${ik}$) ! ===================================================================== ! Local Scalars real(${rk}$) :: b, c, del, delsq, tau, w ! Intrinsic Functions ! Executable Statements del = d( 2_${ik}$ ) - d( 1_${ik}$ ) delsq = del*( d( 2_${ik}$ )+d( 1_${ik}$ ) ) if( i==1_${ik}$ ) then w = one + four*rho*( z( 2_${ik}$ )*z( 2_${ik}$ ) / ( d( 1_${ik}$ )+three*d( 2_${ik}$ ) )-z( 1_${ik}$ )*z( 1_${ik}$ ) / ( & three*d( 1_${ik}$ )+d( 2_${ik}$ ) ) ) / del if( w>zero ) then b = delsq + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 1_${ik}$ )*z( 1_${ik}$ )*delsq ! b > zero, always ! the following tau is dsigma * dsigma - d( 1 ) * d( 1 ) tau = two*c / ( b+sqrt( abs( b*b-four*c ) ) ) ! the following tau is dsigma - d( 1 ) tau = tau / ( d( 1_${ik}$ )+sqrt( d( 1_${ik}$ )*d( 1_${ik}$ )+tau ) ) dsigma = d( 1_${ik}$ ) + tau delta( 1_${ik}$ ) = -tau delta( 2_${ik}$ ) = del - tau work( 1_${ik}$ ) = two*d( 1_${ik}$ ) + tau work( 2_${ik}$ ) = ( d( 1_${ik}$ )+tau ) + d( 2_${ik}$ ) ! delta( 1 ) = -z( 1 ) / tau ! delta( 2 ) = z( 2 ) / ( del-tau ) else b = -delsq + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*delsq ! the following tau is dsigma * dsigma - d( 2 ) * d( 2 ) if( b>zero ) then tau = -two*c / ( b+sqrt( b*b+four*c ) ) else tau = ( b-sqrt( b*b+four*c ) ) / two end if ! the following tau is dsigma - d( 2 ) tau = tau / ( d( 2_${ik}$ )+sqrt( abs( d( 2_${ik}$ )*d( 2_${ik}$ )+tau ) ) ) dsigma = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -( del+tau ) delta( 2_${ik}$ ) = -tau work( 1_${ik}$ ) = d( 1_${ik}$ ) + tau + d( 2_${ik}$ ) work( 2_${ik}$ ) = two*d( 2_${ik}$ ) + tau ! delta( 1 ) = -z( 1 ) / ( del+tau ) ! delta( 2 ) = -z( 2 ) / tau end if ! temp = sqrt( delta( 1 )*delta( 1 )+delta( 2 )*delta( 2 ) ) ! delta( 1 ) = delta( 1 ) / temp ! delta( 2 ) = delta( 2 ) / temp else ! now i=2 b = -delsq + rho*( z( 1_${ik}$ )*z( 1_${ik}$ )+z( 2_${ik}$ )*z( 2_${ik}$ ) ) c = rho*z( 2_${ik}$ )*z( 2_${ik}$ )*delsq ! the following tau is dsigma * dsigma - d( 2 ) * d( 2 ) if( b>zero ) then tau = ( b+sqrt( b*b+four*c ) ) / two else tau = two*c / ( -b+sqrt( b*b+four*c ) ) end if ! the following tau is dsigma - d( 2 ) tau = tau / ( d( 2_${ik}$ )+sqrt( d( 2_${ik}$ )*d( 2_${ik}$ )+tau ) ) dsigma = d( 2_${ik}$ ) + tau delta( 1_${ik}$ ) = -( del+tau ) delta( 2_${ik}$ ) = -tau work( 1_${ik}$ ) = d( 1_${ik}$ ) + tau + d( 2_${ik}$ ) work( 2_${ik}$ ) = two*d( 2_${ik}$ ) + tau ! delta( 1 ) = -z( 1 ) / ( del+tau ) ! delta( 2 ) = -z( 2 ) / tau ! temp = sqrt( delta( 1 )*delta( 1 )+delta( 2 )*delta( 2 ) ) ! delta( 1 ) = delta( 1 ) / temp ! delta( 2 ) = delta( 2 ) / temp end if return end subroutine stdlib${ii}$_${ri}$lasd5 #:endif #:endfor pure module subroutine stdlib${ii}$_slasdq( uplo, sqre, n, ncvt, nru, ncc, d, e, vt, ldvt,u, ldu, c, ldc, & !! SLASDQ computes the singular value decomposition (SVD) of a real !! (upper or lower) bidiagonal matrix with diagonal D and offdiagonal !! E, accumulating the transformations if desired. Letting B denote !! the input bidiagonal matrix, the algorithm computes orthogonal !! matrices Q and P such that B = Q * S * P**T (P**T denotes the transpose !! of P). The singular values S are overwritten on D. !! The input matrix U is changed to U * Q if desired. !! The input matrix VT is changed to P**T * VT if desired. !! The input matrix C is changed to Q**T * C if desired. !! See "Computing Small Singular Values of Bidiagonal Matrices With !! Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan, !! LAPACK Working Note #3, for a detailed description of the algorithm. work, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc, ldu, ldvt, n, ncc, ncvt, nru, sqre ! Array Arguments real(sp), intent(inout) :: c(ldc,*), d(*), e(*), u(ldu,*), vt(ldvt,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: rotate integer(${ik}$) :: i, isub, iuplo, j, np1, sqre1 real(sp) :: cs, r, smin, sn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ iuplo = 0_${ik}$ if( stdlib_lsame( uplo, 'U' ) )iuplo = 1_${ik}$ if( stdlib_lsame( uplo, 'L' ) )iuplo = 2_${ik}$ if( iuplo==0_${ik}$ ) then info = -1_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ncvt<0_${ik}$ ) then info = -4_${ik}$ else if( nru<0_${ik}$ ) then info = -5_${ik}$ else if( ncc<0_${ik}$ ) then info = -6_${ik}$ else if( ( ncvt==0_${ik}$ .and. ldvt<1_${ik}$ ) .or.( ncvt>0_${ik}$ .and. ldvt0_${ik}$ .and. ldc0_${ik}$ ) .or. ( nru>0_${ik}$ ) .or. ( ncc>0_${ik}$ ) np1 = n + 1_${ik}$ sqre1 = sqre ! if matrix non-square upper bidiagonal, rotate to be lower ! bidiagonal. the rotations are on the right. if( ( iuplo==1_${ik}$ ) .and. ( sqre1==1_${ik}$ ) ) then do i = 1, n - 1 call stdlib${ii}$_slartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( rotate ) then work( i ) = cs work( n+i ) = sn end if end do call stdlib${ii}$_slartg( d( n ), e( n ), cs, sn, r ) d( n ) = r e( n ) = zero if( rotate ) then work( n ) = cs work( n+n ) = sn end if iuplo = 2_${ik}$ sqre1 = 0_${ik}$ ! update singular vectors if desired. if( ncvt>0_${ik}$ )call stdlib${ii}$_slasr( 'L', 'V', 'F', np1, ncvt, work( 1_${ik}$ ),work( np1 ), vt, & ldvt ) end if ! if matrix lower bidiagonal, rotate to be upper bidiagonal ! by applying givens rotations on the left. if( iuplo==2_${ik}$ ) then do i = 1, n - 1 call stdlib${ii}$_slartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( rotate ) then work( i ) = cs work( n+i ) = sn end if end do ! if matrix (n+1)-by-n lower bidiagonal, one additional ! rotation is needed. if( sqre1==1_${ik}$ ) then call stdlib${ii}$_slartg( d( n ), e( n ), cs, sn, r ) d( n ) = r if( rotate ) then work( n ) = cs work( n+n ) = sn end if end if ! update singular vectors if desired. if( nru>0_${ik}$ ) then if( sqre1==0_${ik}$ ) then call stdlib${ii}$_slasr( 'R', 'V', 'F', nru, n, work( 1_${ik}$ ),work( np1 ), u, ldu ) else call stdlib${ii}$_slasr( 'R', 'V', 'F', nru, np1, work( 1_${ik}$ ),work( np1 ), u, ldu ) end if end if if( ncc>0_${ik}$ ) then if( sqre1==0_${ik}$ ) then call stdlib${ii}$_slasr( 'L', 'V', 'F', n, ncc, work( 1_${ik}$ ),work( np1 ), c, ldc ) else call stdlib${ii}$_slasr( 'L', 'V', 'F', np1, ncc, work( 1_${ik}$ ),work( np1 ), c, ldc ) end if end if end if ! call stdlib${ii}$_sbdsqr to compute the svd of the reduced real ! n-by-n upper bidiagonal matrix. call stdlib${ii}$_sbdsqr( 'U', n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c,ldc, work, info ) ! sort the singular values into ascending order (insertion sort on ! singular values, but only one transposition per singular vector) do i = 1, n ! scan for smallest d(i). isub = i smin = d( i ) do j = i + 1, n if( d( j )0_${ik}$ )call stdlib${ii}$_sswap( ncvt, vt( isub, 1_${ik}$ ), ldvt, vt( i, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_sswap( nru, u( 1_${ik}$, isub ), 1_${ik}$, u( 1_${ik}$, i ), 1_${ik}$ ) if( ncc>0_${ik}$ )call stdlib${ii}$_sswap( ncc, c( isub, 1_${ik}$ ), ldc, c( i, 1_${ik}$ ), ldc ) end if end do return end subroutine stdlib${ii}$_slasdq pure module subroutine stdlib${ii}$_dlasdq( uplo, sqre, n, ncvt, nru, ncc, d, e, vt, ldvt,u, ldu, c, ldc, & !! DLASDQ computes the singular value decomposition (SVD) of a real !! (upper or lower) bidiagonal matrix with diagonal D and offdiagonal !! E, accumulating the transformations if desired. Letting B denote !! the input bidiagonal matrix, the algorithm computes orthogonal !! matrices Q and P such that B = Q * S * P**T (P**T denotes the transpose !! of P). The singular values S are overwritten on D. !! The input matrix U is changed to U * Q if desired. !! The input matrix VT is changed to P**T * VT if desired. !! The input matrix C is changed to Q**T * C if desired. !! See "Computing Small Singular Values of Bidiagonal Matrices With !! Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan, !! LAPACK Working Note #3, for a detailed description of the algorithm. work, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc, ldu, ldvt, n, ncc, ncvt, nru, sqre ! Array Arguments real(dp), intent(inout) :: c(ldc,*), d(*), e(*), u(ldu,*), vt(ldvt,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: rotate integer(${ik}$) :: i, isub, iuplo, j, np1, sqre1 real(dp) :: cs, r, smin, sn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ iuplo = 0_${ik}$ if( stdlib_lsame( uplo, 'U' ) )iuplo = 1_${ik}$ if( stdlib_lsame( uplo, 'L' ) )iuplo = 2_${ik}$ if( iuplo==0_${ik}$ ) then info = -1_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ncvt<0_${ik}$ ) then info = -4_${ik}$ else if( nru<0_${ik}$ ) then info = -5_${ik}$ else if( ncc<0_${ik}$ ) then info = -6_${ik}$ else if( ( ncvt==0_${ik}$ .and. ldvt<1_${ik}$ ) .or.( ncvt>0_${ik}$ .and. ldvt0_${ik}$ .and. ldc0_${ik}$ ) .or. ( nru>0_${ik}$ ) .or. ( ncc>0_${ik}$ ) np1 = n + 1_${ik}$ sqre1 = sqre ! if matrix non-square upper bidiagonal, rotate to be lower ! bidiagonal. the rotations are on the right. if( ( iuplo==1_${ik}$ ) .and. ( sqre1==1_${ik}$ ) ) then do i = 1, n - 1 call stdlib${ii}$_dlartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( rotate ) then work( i ) = cs work( n+i ) = sn end if end do call stdlib${ii}$_dlartg( d( n ), e( n ), cs, sn, r ) d( n ) = r e( n ) = zero if( rotate ) then work( n ) = cs work( n+n ) = sn end if iuplo = 2_${ik}$ sqre1 = 0_${ik}$ ! update singular vectors if desired. if( ncvt>0_${ik}$ )call stdlib${ii}$_dlasr( 'L', 'V', 'F', np1, ncvt, work( 1_${ik}$ ),work( np1 ), vt, & ldvt ) end if ! if matrix lower bidiagonal, rotate to be upper bidiagonal ! by applying givens rotations on the left. if( iuplo==2_${ik}$ ) then do i = 1, n - 1 call stdlib${ii}$_dlartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( rotate ) then work( i ) = cs work( n+i ) = sn end if end do ! if matrix (n+1)-by-n lower bidiagonal, one additional ! rotation is needed. if( sqre1==1_${ik}$ ) then call stdlib${ii}$_dlartg( d( n ), e( n ), cs, sn, r ) d( n ) = r if( rotate ) then work( n ) = cs work( n+n ) = sn end if end if ! update singular vectors if desired. if( nru>0_${ik}$ ) then if( sqre1==0_${ik}$ ) then call stdlib${ii}$_dlasr( 'R', 'V', 'F', nru, n, work( 1_${ik}$ ),work( np1 ), u, ldu ) else call stdlib${ii}$_dlasr( 'R', 'V', 'F', nru, np1, work( 1_${ik}$ ),work( np1 ), u, ldu ) end if end if if( ncc>0_${ik}$ ) then if( sqre1==0_${ik}$ ) then call stdlib${ii}$_dlasr( 'L', 'V', 'F', n, ncc, work( 1_${ik}$ ),work( np1 ), c, ldc ) else call stdlib${ii}$_dlasr( 'L', 'V', 'F', np1, ncc, work( 1_${ik}$ ),work( np1 ), c, ldc ) end if end if end if ! call stdlib${ii}$_dbdsqr to compute the svd of the reduced real ! n-by-n upper bidiagonal matrix. call stdlib${ii}$_dbdsqr( 'U', n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c,ldc, work, info ) ! sort the singular values into ascending order (insertion sort on ! singular values, but only one transposition per singular vector) do i = 1, n ! scan for smallest d(i). isub = i smin = d( i ) do j = i + 1, n if( d( j )0_${ik}$ )call stdlib${ii}$_dswap( ncvt, vt( isub, 1_${ik}$ ), ldvt, vt( i, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_dswap( nru, u( 1_${ik}$, isub ), 1_${ik}$, u( 1_${ik}$, i ), 1_${ik}$ ) if( ncc>0_${ik}$ )call stdlib${ii}$_dswap( ncc, c( isub, 1_${ik}$ ), ldc, c( i, 1_${ik}$ ), ldc ) end if end do return end subroutine stdlib${ii}$_dlasdq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasdq( uplo, sqre, n, ncvt, nru, ncc, d, e, vt, ldvt,u, ldu, c, ldc, & !! DLASDQ: computes the singular value decomposition (SVD) of a real !! (upper or lower) bidiagonal matrix with diagonal D and offdiagonal !! E, accumulating the transformations if desired. Letting B denote !! the input bidiagonal matrix, the algorithm computes orthogonal !! matrices Q and P such that B = Q * S * P**T (P**T denotes the transpose !! of P). The singular values S are overwritten on D. !! The input matrix U is changed to U * Q if desired. !! The input matrix VT is changed to P**T * VT if desired. !! The input matrix C is changed to Q**T * C if desired. !! See "Computing Small Singular Values of Bidiagonal Matrices With !! Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan, !! LAPACK Working Note #3, for a detailed description of the algorithm. work, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldc, ldu, ldvt, n, ncc, ncvt, nru, sqre ! Array Arguments real(${rk}$), intent(inout) :: c(ldc,*), d(*), e(*), u(ldu,*), vt(ldvt,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: rotate integer(${ik}$) :: i, isub, iuplo, j, np1, sqre1 real(${rk}$) :: cs, r, smin, sn ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ iuplo = 0_${ik}$ if( stdlib_lsame( uplo, 'U' ) )iuplo = 1_${ik}$ if( stdlib_lsame( uplo, 'L' ) )iuplo = 2_${ik}$ if( iuplo==0_${ik}$ ) then info = -1_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ncvt<0_${ik}$ ) then info = -4_${ik}$ else if( nru<0_${ik}$ ) then info = -5_${ik}$ else if( ncc<0_${ik}$ ) then info = -6_${ik}$ else if( ( ncvt==0_${ik}$ .and. ldvt<1_${ik}$ ) .or.( ncvt>0_${ik}$ .and. ldvt0_${ik}$ .and. ldc0_${ik}$ ) .or. ( nru>0_${ik}$ ) .or. ( ncc>0_${ik}$ ) np1 = n + 1_${ik}$ sqre1 = sqre ! if matrix non-square upper bidiagonal, rotate to be lower ! bidiagonal. the rotations are on the right. if( ( iuplo==1_${ik}$ ) .and. ( sqre1==1_${ik}$ ) ) then do i = 1, n - 1 call stdlib${ii}$_${ri}$lartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( rotate ) then work( i ) = cs work( n+i ) = sn end if end do call stdlib${ii}$_${ri}$lartg( d( n ), e( n ), cs, sn, r ) d( n ) = r e( n ) = zero if( rotate ) then work( n ) = cs work( n+n ) = sn end if iuplo = 2_${ik}$ sqre1 = 0_${ik}$ ! update singular vectors if desired. if( ncvt>0_${ik}$ )call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', np1, ncvt, work( 1_${ik}$ ),work( np1 ), vt, & ldvt ) end if ! if matrix lower bidiagonal, rotate to be upper bidiagonal ! by applying givens rotations on the left. if( iuplo==2_${ik}$ ) then do i = 1, n - 1 call stdlib${ii}$_${ri}$lartg( d( i ), e( i ), cs, sn, r ) d( i ) = r e( i ) = sn*d( i+1 ) d( i+1 ) = cs*d( i+1 ) if( rotate ) then work( i ) = cs work( n+i ) = sn end if end do ! if matrix (n+1)-by-n lower bidiagonal, one additional ! rotation is needed. if( sqre1==1_${ik}$ ) then call stdlib${ii}$_${ri}$lartg( d( n ), e( n ), cs, sn, r ) d( n ) = r if( rotate ) then work( n ) = cs work( n+n ) = sn end if end if ! update singular vectors if desired. if( nru>0_${ik}$ ) then if( sqre1==0_${ik}$ ) then call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'F', nru, n, work( 1_${ik}$ ),work( np1 ), u, ldu ) else call stdlib${ii}$_${ri}$lasr( 'R', 'V', 'F', nru, np1, work( 1_${ik}$ ),work( np1 ), u, ldu ) end if end if if( ncc>0_${ik}$ ) then if( sqre1==0_${ik}$ ) then call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', n, ncc, work( 1_${ik}$ ),work( np1 ), c, ldc ) else call stdlib${ii}$_${ri}$lasr( 'L', 'V', 'F', np1, ncc, work( 1_${ik}$ ),work( np1 ), c, ldc ) end if end if end if ! call stdlib${ii}$_${ri}$bdsqr to compute the svd of the reduced real ! n-by-n upper bidiagonal matrix. call stdlib${ii}$_${ri}$bdsqr( 'U', n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c,ldc, work, info ) ! sort the singular values into ascending order (insertion sort on ! singular values, but only one transposition per singular vector) do i = 1, n ! scan for smallest d(i). isub = i smin = d( i ) do j = i + 1, n if( d( j )0_${ik}$ )call stdlib${ii}$_${ri}$swap( ncvt, vt( isub, 1_${ik}$ ), ldvt, vt( i, 1_${ik}$ ), ldvt ) if( nru>0_${ik}$ )call stdlib${ii}$_${ri}$swap( nru, u( 1_${ik}$, isub ), 1_${ik}$, u( 1_${ik}$, i ), 1_${ik}$ ) if( ncc>0_${ik}$ )call stdlib${ii}$_${ri}$swap( ncc, c( isub, 1_${ik}$ ), ldc, c( i, 1_${ik}$ ), ldc ) end if end do return end subroutine stdlib${ii}$_${ri}$lasdq #:endif #:endfor pure module subroutine stdlib${ii}$_slasda( icompq, smlsiz, n, sqre, d, e, u, ldu, vt, k,difl, difr, z, & !! Using a divide and conquer approach, SLASDA: computes the singular !! value decomposition (SVD) of a real upper bidiagonal N-by-M matrix !! B with diagonal D and offdiagonal E, where M = N + SQRE. The !! algorithm computes the singular values in the SVD B = U * S * VT. !! The orthogonal matrices U and VT are optionally computed in !! compact form. !! A related subroutine, SLASD0, computes the singular values and !! the singular vectors in explicit form. poles, givptr, givcol, ldgcol,perm, givnum, c, s, work, iwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: icompq, ldgcol, ldu, n, smlsiz, sqre integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(out) :: givcol(ldgcol,*), givptr(*), iwork(*), k(*), perm(ldgcol,& *) real(sp), intent(out) :: c(*), difl(ldu,*), difr(ldu,*), givnum(ldu,*), poles(ldu,*), & s(*), u(ldu,*), vt(ldu,*), work(*), z(ldu,*) real(sp), intent(inout) :: d(*), e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, i1, ic, idxq, idxqi, im1, inode, itemp, iwk, j, lf, ll, lvl, lvl2, & m, ncc, nd, ndb1, ndiml, ndimr, nl, nlf, nlp1, nlvl, nr, nrf, nrp1, nru, nwork1, & nwork2, smlszp, sqrei, vf, vfi, vl, vli real(sp) :: alpha, beta ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( smlsiz<3_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( ldu<( n+sqre ) ) then info = -8_${ik}$ else if( ldgcol1_${ik}$ ) ) then info = -1_${ik}$ else if( smlsiz<3_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( ldu<( n+sqre ) ) then info = -8_${ik}$ else if( ldgcol1_${ik}$ ) ) then info = -1_${ik}$ else if( smlsiz<3_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( ldu<( n+sqre ) ) then info = -8_${ik}$ else if( ldgcol1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( ldgcolorgnrm ) then orgnrm = abs( d( i ) ) end if end do call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) alpha = alpha / orgnrm beta = beta / orgnrm ! sort and deflate singular values. call stdlib${ii}$_slasd7( icompq, nl, nr, sqre, k, d, z, work( iw ), vf,work( ivfw ), vl, & work( ivlw ), alpha, beta,work( isigma ), iwork( idx ), iwork( idxp ), idxq,perm, & givptr, givcol, ldgcol, givnum, ldgnum, c, s,info ) ! solve secular equation, compute difl, difr, and update vf, vl. call stdlib${ii}$_slasd8( icompq, k, d, z, vf, vl, difl, difr, ldgnum,work( isigma ), work( & iw ), info ) ! report the possible convergence failure. if( info/=0_${ik}$ ) then return end if ! save the poles if icompq = 1. if( icompq==1_${ik}$ ) then call stdlib${ii}$_scopy( k, d, 1_${ik}$, poles( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_scopy( k, work( isigma ), 1_${ik}$, poles( 1_${ik}$, 2_${ik}$ ), 1_${ik}$ ) end if ! unscale. call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) ! prepare the idxq sorting permutation. n1 = k n2 = n - k call stdlib${ii}$_slamrg( n1, n2, d, 1_${ik}$, -1_${ik}$, idxq ) return end subroutine stdlib${ii}$_slasd6 pure module subroutine stdlib${ii}$_dlasd6( icompq, nl, nr, sqre, d, vf, vl, alpha, beta,idxq, perm, & !! DLASD6 computes the SVD of an updated upper bidiagonal matrix B !! obtained by merging two smaller ones by appending a row. This !! routine is used only for the problem which requires all singular !! values and optionally singular vector matrices in factored form. !! B is an N-by-M matrix with N = NL + NR + 1 and M = N + SQRE. !! A related subroutine, DLASD1, handles the case in which all singular !! values and singular vectors of the bidiagonal matrix are desired. !! DLASD6 computes the SVD as follows: !! ( D1(in) 0 0 0 ) !! B = U(in) * ( Z1**T a Z2**T b ) * VT(in) !! ( 0 0 D2(in) 0 ) !! = U(out) * ( D(out) 0) * VT(out) !! where Z**T = (Z1**T a Z2**T b) = u**T VT**T, and u is a vector of dimension M !! with ALPHA and BETA in the NL+1 and NL+2 th entries and zeros !! elsewhere; and the entry b is empty if SQRE = 0. !! The singular values of B can be computed using D1, D2, the first !! components of all the right singular vectors of the lower block, and !! the last components of all the right singular vectors of the upper !! block. These components are stored and updated in VF and VL, !! respectively, in DLASD6. Hence U and VT are not explicitly !! referenced. !! The singular values are stored in D. The algorithm consists of two !! stages: !! The first stage consists of deflating the size of the problem !! when there are multiple singular values or if there is a zero !! in the Z vector. For each such occurrence the dimension of the !! secular equation problem is reduced by one. This stage is !! performed by the routine DLASD7. !! The second stage consists of calculating the updated !! singular values. This is done by finding the roots of the !! secular equation via the routine DLASD4 (as called by DLASD8). !! This routine also updates VF and VL and computes the distances !! between the updated singular values and the old singular !! values. !! DLASD6 is called from DLASDA. givptr, givcol, ldgcol, givnum,ldgnum, poles, difl, difr, z, k, c, s, work,iwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: givptr, info, k integer(${ik}$), intent(in) :: icompq, ldgcol, ldgnum, nl, nr, sqre real(dp), intent(inout) :: alpha, beta real(dp), intent(out) :: c, s ! Array Arguments integer(${ik}$), intent(out) :: givcol(ldgcol,*), iwork(*), perm(*) integer(${ik}$), intent(inout) :: idxq(*) real(dp), intent(inout) :: d(*), vf(*), vl(*) real(dp), intent(out) :: difl(*), difr(*), givnum(ldgnum,*), poles(ldgnum,*), work(*), & z(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, idx, idxc, idxp, isigma, ivfw, ivlw, iw, m, n, n1, n2 real(dp) :: orgnrm ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ m = n + sqre if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( ldgcolorgnrm ) then orgnrm = abs( d( i ) ) end if end do call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) alpha = alpha / orgnrm beta = beta / orgnrm ! sort and deflate singular values. call stdlib${ii}$_dlasd7( icompq, nl, nr, sqre, k, d, z, work( iw ), vf,work( ivfw ), vl, & work( ivlw ), alpha, beta,work( isigma ), iwork( idx ), iwork( idxp ), idxq,perm, & givptr, givcol, ldgcol, givnum, ldgnum, c, s,info ) ! solve secular equation, compute difl, difr, and update vf, vl. call stdlib${ii}$_dlasd8( icompq, k, d, z, vf, vl, difl, difr, ldgnum,work( isigma ), work( & iw ), info ) ! report the possible convergence failure. if( info/=0_${ik}$ ) then return end if ! save the poles if icompq = 1. if( icompq==1_${ik}$ ) then call stdlib${ii}$_dcopy( k, d, 1_${ik}$, poles( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_dcopy( k, work( isigma ), 1_${ik}$, poles( 1_${ik}$, 2_${ik}$ ), 1_${ik}$ ) end if ! unscale. call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) ! prepare the idxq sorting permutation. n1 = k n2 = n - k call stdlib${ii}$_dlamrg( n1, n2, d, 1_${ik}$, -1_${ik}$, idxq ) return end subroutine stdlib${ii}$_dlasd6 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasd6( icompq, nl, nr, sqre, d, vf, vl, alpha, beta,idxq, perm, & !! DLASD6: computes the SVD of an updated upper bidiagonal matrix B !! obtained by merging two smaller ones by appending a row. This !! routine is used only for the problem which requires all singular !! values and optionally singular vector matrices in factored form. !! B is an N-by-M matrix with N = NL + NR + 1 and M = N + SQRE. !! A related subroutine, DLASD1, handles the case in which all singular !! values and singular vectors of the bidiagonal matrix are desired. !! DLASD6 computes the SVD as follows: !! ( D1(in) 0 0 0 ) !! B = U(in) * ( Z1**T a Z2**T b ) * VT(in) !! ( 0 0 D2(in) 0 ) !! = U(out) * ( D(out) 0) * VT(out) !! where Z**T = (Z1**T a Z2**T b) = u**T VT**T, and u is a vector of dimension M !! with ALPHA and BETA in the NL+1 and NL+2 th entries and zeros !! elsewhere; and the entry b is empty if SQRE = 0. !! The singular values of B can be computed using D1, D2, the first !! components of all the right singular vectors of the lower block, and !! the last components of all the right singular vectors of the upper !! block. These components are stored and updated in VF and VL, !! respectively, in DLASD6. Hence U and VT are not explicitly !! referenced. !! The singular values are stored in D. The algorithm consists of two !! stages: !! The first stage consists of deflating the size of the problem !! when there are multiple singular values or if there is a zero !! in the Z vector. For each such occurrence the dimension of the !! secular equation problem is reduced by one. This stage is !! performed by the routine DLASD7. !! The second stage consists of calculating the updated !! singular values. This is done by finding the roots of the !! secular equation via the routine DLASD4 (as called by DLASD8). !! This routine also updates VF and VL and computes the distances !! between the updated singular values and the old singular !! values. !! DLASD6 is called from DLASDA. givptr, givcol, ldgcol, givnum,ldgnum, poles, difl, difr, z, k, c, s, work,iwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: givptr, info, k integer(${ik}$), intent(in) :: icompq, ldgcol, ldgnum, nl, nr, sqre real(${rk}$), intent(inout) :: alpha, beta real(${rk}$), intent(out) :: c, s ! Array Arguments integer(${ik}$), intent(out) :: givcol(ldgcol,*), iwork(*), perm(*) integer(${ik}$), intent(inout) :: idxq(*) real(${rk}$), intent(inout) :: d(*), vf(*), vl(*) real(${rk}$), intent(out) :: difl(*), difr(*), givnum(ldgnum,*), poles(ldgnum,*), work(*), & z(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, idx, idxc, idxp, isigma, ivfw, ivlw, iw, m, n, n1, n2 real(${rk}$) :: orgnrm ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ m = n + sqre if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( ldgcolorgnrm ) then orgnrm = abs( d( i ) ) end if end do call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, orgnrm, one, n, 1_${ik}$, d, n, info ) alpha = alpha / orgnrm beta = beta / orgnrm ! sort and deflate singular values. call stdlib${ii}$_${ri}$lasd7( icompq, nl, nr, sqre, k, d, z, work( iw ), vf,work( ivfw ), vl, & work( ivlw ), alpha, beta,work( isigma ), iwork( idx ), iwork( idxp ), idxq,perm, & givptr, givcol, ldgcol, givnum, ldgnum, c, s,info ) ! solve secular equation, compute difl, difr, and update vf, vl. call stdlib${ii}$_${ri}$lasd8( icompq, k, d, z, vf, vl, difl, difr, ldgnum,work( isigma ), work( & iw ), info ) ! report the possible convergence failure. if( info/=0_${ik}$ ) then return end if ! save the poles if icompq = 1. if( icompq==1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( k, d, 1_${ik}$, poles( 1_${ik}$, 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( k, work( isigma ), 1_${ik}$, poles( 1_${ik}$, 2_${ik}$ ), 1_${ik}$ ) end if ! unscale. call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, orgnrm, n, 1_${ik}$, d, n, info ) ! prepare the idxq sorting permutation. n1 = k n2 = n - k call stdlib${ii}$_${ri}$lamrg( n1, n2, d, 1_${ik}$, -1_${ik}$, idxq ) return end subroutine stdlib${ii}$_${ri}$lasd6 #:endif #:endfor pure module subroutine stdlib${ii}$_slasd7( icompq, nl, nr, sqre, k, d, z, zw, vf, vfw, vl,vlw, alpha, & !! SLASD7 merges the two sets of singular values together into a single !! sorted set. Then it tries to deflate the size of the problem. There !! are two ways in which deflation can occur: when two or more singular !! values are close together or if there is a tiny entry in the Z !! vector. For each such occurrence the order of the related !! secular equation problem is reduced by one. !! SLASD7 is called from SLASD6. beta, dsigma, idx, idxp, idxq,perm, givptr, givcol, ldgcol, givnum, ldgnum,c, s, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: givptr, info, k integer(${ik}$), intent(in) :: icompq, ldgcol, ldgnum, nl, nr, sqre real(sp), intent(in) :: alpha, beta real(sp), intent(out) :: c, s ! Array Arguments integer(${ik}$), intent(out) :: givcol(ldgcol,*), idx(*), idxp(*), perm(*) integer(${ik}$), intent(inout) :: idxq(*) real(sp), intent(inout) :: d(*), vf(*), vl(*) real(sp), intent(out) :: dsigma(*), givnum(ldgnum,*), vfw(*), vlw(*), z(*), zw(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, idxi, idxj, idxjp, j, jp, jprev, k2, m, n, nlp1, nlp2 real(sp) :: eps, hlftol, tau, tol, z1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ m = n + sqre if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( ldgcoln )go to 90 if( abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ idxp( k2 ) = j else ! check if singular values are close enough to allow deflation. if( abs( d( j )-d( jprev ) )<=tol ) then ! deflation is possible. s = z( jprev ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_slapy2( c, s ) z( j ) = tau z( jprev ) = zero c = c / tau s = -s / tau ! record the appropriate givens rotation if( icompq==1_${ik}$ ) then givptr = givptr + 1_${ik}$ idxjp = idxq( idx( jprev )+1_${ik}$ ) idxj = idxq( idx( j )+1_${ik}$ ) if( idxjp<=nlp1 ) then idxjp = idxjp - 1_${ik}$ end if if( idxj<=nlp1 ) then idxj = idxj - 1_${ik}$ end if givcol( givptr, 2_${ik}$ ) = idxjp givcol( givptr, 1_${ik}$ ) = idxj givnum( givptr, 2_${ik}$ ) = c givnum( givptr, 1_${ik}$ ) = s end if call stdlib${ii}$_srot( 1_${ik}$, vf( jprev ), 1_${ik}$, vf( j ), 1_${ik}$, c, s ) call stdlib${ii}$_srot( 1_${ik}$, vl( jprev ), 1_${ik}$, vl( j ), 1_${ik}$, c, s ) k2 = k2 - 1_${ik}$ idxp( k2 ) = jprev jprev = j else k = k + 1_${ik}$ zw( k ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev jprev = j end if end if go to 80 90 continue ! record the last singular value. k = k + 1_${ik}$ zw( k ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev 100 continue ! sort the singular values into dsigma. the singular values which ! were not deflated go into the first k slots of dsigma, except ! that dsigma(1) is treated separately. do j = 2, n jp = idxp( j ) dsigma( j ) = d( jp ) vfw( j ) = vf( jp ) vlw( j ) = vl( jp ) end do if( icompq==1_${ik}$ ) then do j = 2, n jp = idxp( j ) perm( j ) = idxq( idx( jp )+1_${ik}$ ) if( perm( j )<=nlp1 ) then perm( j ) = perm( j ) - 1_${ik}$ end if end do end if ! the deflated singular values go back into the last n - k slots of ! d. call stdlib${ii}$_scopy( n-k, dsigma( k+1 ), 1_${ik}$, d( k+1 ), 1_${ik}$ ) ! determine dsigma(1), dsigma(2), z(1), vf(1), vl(1), vf(m), and ! vl(m). dsigma( 1_${ik}$ ) = zero hlftol = tol / two if( abs( dsigma( 2_${ik}$ ) )<=hlftol )dsigma( 2_${ik}$ ) = hlftol if( m>n ) then z( 1_${ik}$ ) = stdlib${ii}$_slapy2( z1, z( m ) ) if( z( 1_${ik}$ )<=tol ) then c = one s = zero z( 1_${ik}$ ) = tol else c = z1 / z( 1_${ik}$ ) s = -z( m ) / z( 1_${ik}$ ) end if call stdlib${ii}$_srot( 1_${ik}$, vf( m ), 1_${ik}$, vf( 1_${ik}$ ), 1_${ik}$, c, s ) call stdlib${ii}$_srot( 1_${ik}$, vl( m ), 1_${ik}$, vl( 1_${ik}$ ), 1_${ik}$, c, s ) else if( abs( z1 )<=tol ) then z( 1_${ik}$ ) = tol else z( 1_${ik}$ ) = z1 end if end if ! restore z, vf, and vl. call stdlib${ii}$_scopy( k-1, zw( 2_${ik}$ ), 1_${ik}$, z( 2_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_scopy( n-1, vfw( 2_${ik}$ ), 1_${ik}$, vf( 2_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_scopy( n-1, vlw( 2_${ik}$ ), 1_${ik}$, vl( 2_${ik}$ ), 1_${ik}$ ) return end subroutine stdlib${ii}$_slasd7 pure module subroutine stdlib${ii}$_dlasd7( icompq, nl, nr, sqre, k, d, z, zw, vf, vfw, vl,vlw, alpha, & !! DLASD7 merges the two sets of singular values together into a single !! sorted set. Then it tries to deflate the size of the problem. There !! are two ways in which deflation can occur: when two or more singular !! values are close together or if there is a tiny entry in the Z !! vector. For each such occurrence the order of the related !! secular equation problem is reduced by one. !! DLASD7 is called from DLASD6. beta, dsigma, idx, idxp, idxq,perm, givptr, givcol, ldgcol, givnum, ldgnum,c, s, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: givptr, info, k integer(${ik}$), intent(in) :: icompq, ldgcol, ldgnum, nl, nr, sqre real(dp), intent(in) :: alpha, beta real(dp), intent(out) :: c, s ! Array Arguments integer(${ik}$), intent(out) :: givcol(ldgcol,*), idx(*), idxp(*), perm(*) integer(${ik}$), intent(inout) :: idxq(*) real(dp), intent(inout) :: d(*), vf(*), vl(*) real(dp), intent(out) :: dsigma(*), givnum(ldgnum,*), vfw(*), vlw(*), z(*), zw(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, idxi, idxj, idxjp, j, jp, jprev, k2, m, n, nlp1, nlp2 real(dp) :: eps, hlftol, tau, tol, z1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ m = n + sqre if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( ldgcoln )go to 90 if( abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ idxp( k2 ) = j else ! check if singular values are close enough to allow deflation. if( abs( d( j )-d( jprev ) )<=tol ) then ! deflation is possible. s = z( jprev ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_dlapy2( c, s ) z( j ) = tau z( jprev ) = zero c = c / tau s = -s / tau ! record the appropriate givens rotation if( icompq==1_${ik}$ ) then givptr = givptr + 1_${ik}$ idxjp = idxq( idx( jprev )+1_${ik}$ ) idxj = idxq( idx( j )+1_${ik}$ ) if( idxjp<=nlp1 ) then idxjp = idxjp - 1_${ik}$ end if if( idxj<=nlp1 ) then idxj = idxj - 1_${ik}$ end if givcol( givptr, 2_${ik}$ ) = idxjp givcol( givptr, 1_${ik}$ ) = idxj givnum( givptr, 2_${ik}$ ) = c givnum( givptr, 1_${ik}$ ) = s end if call stdlib${ii}$_drot( 1_${ik}$, vf( jprev ), 1_${ik}$, vf( j ), 1_${ik}$, c, s ) call stdlib${ii}$_drot( 1_${ik}$, vl( jprev ), 1_${ik}$, vl( j ), 1_${ik}$, c, s ) k2 = k2 - 1_${ik}$ idxp( k2 ) = jprev jprev = j else k = k + 1_${ik}$ zw( k ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev jprev = j end if end if go to 80 90 continue ! record the last singular value. k = k + 1_${ik}$ zw( k ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev 100 continue ! sort the singular values into dsigma. the singular values which ! were not deflated go into the first k slots of dsigma, except ! that dsigma(1) is treated separately. do j = 2, n jp = idxp( j ) dsigma( j ) = d( jp ) vfw( j ) = vf( jp ) vlw( j ) = vl( jp ) end do if( icompq==1_${ik}$ ) then do j = 2, n jp = idxp( j ) perm( j ) = idxq( idx( jp )+1_${ik}$ ) if( perm( j )<=nlp1 ) then perm( j ) = perm( j ) - 1_${ik}$ end if end do end if ! the deflated singular values go back into the last n - k slots of ! d. call stdlib${ii}$_dcopy( n-k, dsigma( k+1 ), 1_${ik}$, d( k+1 ), 1_${ik}$ ) ! determine dsigma(1), dsigma(2), z(1), vf(1), vl(1), vf(m), and ! vl(m). dsigma( 1_${ik}$ ) = zero hlftol = tol / two if( abs( dsigma( 2_${ik}$ ) )<=hlftol )dsigma( 2_${ik}$ ) = hlftol if( m>n ) then z( 1_${ik}$ ) = stdlib${ii}$_dlapy2( z1, z( m ) ) if( z( 1_${ik}$ )<=tol ) then c = one s = zero z( 1_${ik}$ ) = tol else c = z1 / z( 1_${ik}$ ) s = -z( m ) / z( 1_${ik}$ ) end if call stdlib${ii}$_drot( 1_${ik}$, vf( m ), 1_${ik}$, vf( 1_${ik}$ ), 1_${ik}$, c, s ) call stdlib${ii}$_drot( 1_${ik}$, vl( m ), 1_${ik}$, vl( 1_${ik}$ ), 1_${ik}$, c, s ) else if( abs( z1 )<=tol ) then z( 1_${ik}$ ) = tol else z( 1_${ik}$ ) = z1 end if end if ! restore z, vf, and vl. call stdlib${ii}$_dcopy( k-1, zw( 2_${ik}$ ), 1_${ik}$, z( 2_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_dcopy( n-1, vfw( 2_${ik}$ ), 1_${ik}$, vf( 2_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_dcopy( n-1, vlw( 2_${ik}$ ), 1_${ik}$, vl( 2_${ik}$ ), 1_${ik}$ ) return end subroutine stdlib${ii}$_dlasd7 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasd7( icompq, nl, nr, sqre, k, d, z, zw, vf, vfw, vl,vlw, alpha, & !! DLASD7: merges the two sets of singular values together into a single !! sorted set. Then it tries to deflate the size of the problem. There !! are two ways in which deflation can occur: when two or more singular !! values are close together or if there is a tiny entry in the Z !! vector. For each such occurrence the order of the related !! secular equation problem is reduced by one. !! DLASD7 is called from DLASD6. beta, dsigma, idx, idxp, idxq,perm, givptr, givcol, ldgcol, givnum, ldgnum,c, s, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: givptr, info, k integer(${ik}$), intent(in) :: icompq, ldgcol, ldgnum, nl, nr, sqre real(${rk}$), intent(in) :: alpha, beta real(${rk}$), intent(out) :: c, s ! Array Arguments integer(${ik}$), intent(out) :: givcol(ldgcol,*), idx(*), idxp(*), perm(*) integer(${ik}$), intent(inout) :: idxq(*) real(${rk}$), intent(inout) :: d(*), vf(*), vl(*) real(${rk}$), intent(out) :: dsigma(*), givnum(ldgnum,*), vfw(*), vlw(*), z(*), zw(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, idxi, idxj, idxjp, j, jp, jprev, k2, m, n, nlp1, nlp2 real(${rk}$) :: eps, hlftol, tau, tol, z1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ m = n + sqre if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( ldgcoln )go to 90 if( abs( z( j ) )<=tol ) then ! deflate due to small z component. k2 = k2 - 1_${ik}$ idxp( k2 ) = j else ! check if singular values are close enough to allow deflation. if( abs( d( j )-d( jprev ) )<=tol ) then ! deflation is possible. s = z( jprev ) c = z( j ) ! find sqrt(a**2+b**2) without overflow or ! destructive underflow. tau = stdlib${ii}$_${ri}$lapy2( c, s ) z( j ) = tau z( jprev ) = zero c = c / tau s = -s / tau ! record the appropriate givens rotation if( icompq==1_${ik}$ ) then givptr = givptr + 1_${ik}$ idxjp = idxq( idx( jprev )+1_${ik}$ ) idxj = idxq( idx( j )+1_${ik}$ ) if( idxjp<=nlp1 ) then idxjp = idxjp - 1_${ik}$ end if if( idxj<=nlp1 ) then idxj = idxj - 1_${ik}$ end if givcol( givptr, 2_${ik}$ ) = idxjp givcol( givptr, 1_${ik}$ ) = idxj givnum( givptr, 2_${ik}$ ) = c givnum( givptr, 1_${ik}$ ) = s end if call stdlib${ii}$_${ri}$rot( 1_${ik}$, vf( jprev ), 1_${ik}$, vf( j ), 1_${ik}$, c, s ) call stdlib${ii}$_${ri}$rot( 1_${ik}$, vl( jprev ), 1_${ik}$, vl( j ), 1_${ik}$, c, s ) k2 = k2 - 1_${ik}$ idxp( k2 ) = jprev jprev = j else k = k + 1_${ik}$ zw( k ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev jprev = j end if end if go to 80 90 continue ! record the last singular value. k = k + 1_${ik}$ zw( k ) = z( jprev ) dsigma( k ) = d( jprev ) idxp( k ) = jprev 100 continue ! sort the singular values into dsigma. the singular values which ! were not deflated go into the first k slots of dsigma, except ! that dsigma(1) is treated separately. do j = 2, n jp = idxp( j ) dsigma( j ) = d( jp ) vfw( j ) = vf( jp ) vlw( j ) = vl( jp ) end do if( icompq==1_${ik}$ ) then do j = 2, n jp = idxp( j ) perm( j ) = idxq( idx( jp )+1_${ik}$ ) if( perm( j )<=nlp1 ) then perm( j ) = perm( j ) - 1_${ik}$ end if end do end if ! the deflated singular values go back into the last n - k slots of ! d. call stdlib${ii}$_${ri}$copy( n-k, dsigma( k+1 ), 1_${ik}$, d( k+1 ), 1_${ik}$ ) ! determine dsigma(1), dsigma(2), z(1), vf(1), vl(1), vf(m), and ! vl(m). dsigma( 1_${ik}$ ) = zero hlftol = tol / two if( abs( dsigma( 2_${ik}$ ) )<=hlftol )dsigma( 2_${ik}$ ) = hlftol if( m>n ) then z( 1_${ik}$ ) = stdlib${ii}$_${ri}$lapy2( z1, z( m ) ) if( z( 1_${ik}$ )<=tol ) then c = one s = zero z( 1_${ik}$ ) = tol else c = z1 / z( 1_${ik}$ ) s = -z( m ) / z( 1_${ik}$ ) end if call stdlib${ii}$_${ri}$rot( 1_${ik}$, vf( m ), 1_${ik}$, vf( 1_${ik}$ ), 1_${ik}$, c, s ) call stdlib${ii}$_${ri}$rot( 1_${ik}$, vl( m ), 1_${ik}$, vl( 1_${ik}$ ), 1_${ik}$, c, s ) else if( abs( z1 )<=tol ) then z( 1_${ik}$ ) = tol else z( 1_${ik}$ ) = z1 end if end if ! restore z, vf, and vl. call stdlib${ii}$_${ri}$copy( k-1, zw( 2_${ik}$ ), 1_${ik}$, z( 2_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n-1, vfw( 2_${ik}$ ), 1_${ik}$, vf( 2_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n-1, vlw( 2_${ik}$ ), 1_${ik}$, vl( 2_${ik}$ ), 1_${ik}$ ) return end subroutine stdlib${ii}$_${ri}$lasd7 #:endif #:endfor pure module subroutine stdlib${ii}$_slasd8( icompq, k, d, z, vf, vl, difl, difr, lddifr,dsigma, work, & !! SLASD8 finds the square roots of the roots of the secular equation, !! as defined by the values in DSIGMA and Z. It makes the appropriate !! calls to SLASD4, and stores, for each element in D, the distance !! to its two nearest poles (elements in DSIGMA). It also updates !! the arrays VF and VL, the first and last components of all the !! right singular vectors of the original bidiagonal matrix. !! SLASD8 is called from SLASD6. info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: icompq, k, lddifr integer(${ik}$), intent(out) :: info ! Array Arguments real(sp), intent(out) :: d(*), difl(*), difr(lddifr,*), work(*) real(sp), intent(inout) :: dsigma(*), vf(*), vl(*), z(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, iwk1, iwk2, iwk2i, iwk3, iwk3i, j real(sp) :: diflj, difrj, dj, dsigj, dsigjp, rho, temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( k<1_${ik}$ ) then info = -2_${ik}$ else if( lddifr1_${ik}$ ) ) then info = -1_${ik}$ else if( k<1_${ik}$ ) then info = -2_${ik}$ else if( lddifr1_${ik}$ ) ) then info = -1_${ik}$ else if( k<1_${ik}$ ) then info = -2_${ik}$ else if( lddifr=n .and. ldvt=n .and. minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_sbdsdc if( wntqn ) then ! stdlib${ii}$_sbdsdc needs only 4*n (or 6*n for uplo=l for lapack <= 3.6_sp) ! keep 7*n for backwards compatibility. bdspac = 7_${ik}$*n else bdspac = 3_${ik}$*n*n + 4_${ik}$*n end if ! compute space preferred for each routine call stdlib${ii}$_sgebrd( m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & ierr ) lwork_sgebrd_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sgebrd( n, n, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & ierr ) lwork_sgebrd_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sgeqrf( m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sgeqrf_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sorgbr( 'Q', n, n, n, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$,ierr ) lwork_sorgbr_q_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sorgqr( m, m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgqr_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sorgqr( m, n, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgqr_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sormbr( 'P', 'R', 'T', n, n, n, dum(1_${ik}$), n,dum(1_${ik}$), dum(1_${ik}$), n, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_sormbr_prt_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sormbr( 'Q', 'L', 'N', n, n, n, dum(1_${ik}$), n,dum(1_${ik}$), dum(1_${ik}$), n, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_sormbr_qln_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, n, n, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_sormbr_qln_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, m, n, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_sormbr_qln_mm = int( dum(1_${ik}$),KIND=${ik}$) if( m>=mnthr ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') wrkbl = n + lwork_sgeqrf_mn wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sgebrd_nn ) maxwrk = max( wrkbl, bdspac + n ) minwrk = bdspac + n else if( wntqo ) then ! path 2 (m >> n, jobz='o') wrkbl = n + lwork_sgeqrf_mn wrkbl = max( wrkbl, n + lwork_sorgqr_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sgebrd_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_qln_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + 2_${ik}$*n*n minwrk = bdspac + 2_${ik}$*n*n + 3_${ik}$*n else if( wntqs ) then ! path 3 (m >> n, jobz='s') wrkbl = n + lwork_sgeqrf_mn wrkbl = max( wrkbl, n + lwork_sorgqr_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sgebrd_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_qln_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + n*n minwrk = bdspac + n*n + 3_${ik}$*n else if( wntqa ) then ! path 4 (m >> n, jobz='a') wrkbl = n + lwork_sgeqrf_mn wrkbl = max( wrkbl, n + lwork_sorgqr_mm ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sgebrd_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_qln_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + n*n minwrk = n*n + max( 3_${ik}$*n + bdspac, n + m ) end if else ! path 5 (m >= n, but not much larger) wrkbl = 3_${ik}$*n + lwork_sgebrd_mn if( wntqn ) then ! path 5n (m >= n, jobz='n') maxwrk = max( wrkbl, 3_${ik}$*n + bdspac ) minwrk = 3_${ik}$*n + max( m, bdspac ) else if( wntqo ) then ! path 5o (m >= n, jobz='o') wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_qln_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + m*n minwrk = 3_${ik}$*n + max( m, n*n + bdspac ) else if( wntqs ) then ! path 5s (m >= n, jobz='s') wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_qln_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_prt_nn ) maxwrk = max( wrkbl, 3_${ik}$*n + bdspac ) minwrk = 3_${ik}$*n + max( m, bdspac ) else if( wntqa ) then ! path 5a (m >= n, jobz='a') wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_sormbr_prt_nn ) maxwrk = max( wrkbl, 3_${ik}$*n + bdspac ) minwrk = 3_${ik}$*n + max( m, bdspac ) end if end if else if( minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_sbdsdc if( wntqn ) then ! stdlib${ii}$_sbdsdc needs only 4*n (or 6*n for uplo=l for lapack <= 3.6_sp) ! keep 7*n for backwards compatibility. bdspac = 7_${ik}$*m else bdspac = 3_${ik}$*m*m + 4_${ik}$*m end if ! compute space preferred for each routine call stdlib${ii}$_sgebrd( m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & ierr ) lwork_sgebrd_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sgebrd( m, m, a, m, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sgebrd_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sgelqf( m, n, a, m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sgelqf_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sorglq( n, n, m, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorglq_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sorglq( m, n, m, a, m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorglq_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sorgbr( 'P', m, m, m, a, n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_sorgbr_p_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sormbr( 'P', 'R', 'T', m, m, m, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_sormbr_prt_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sormbr( 'P', 'R', 'T', m, n, m, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_sormbr_prt_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sormbr( 'P', 'R', 'T', n, n, m, dum(1_${ik}$), n,dum(1_${ik}$), dum(1_${ik}$), n, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_sormbr_prt_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, m, m, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_sormbr_qln_mm = int( dum(1_${ik}$),KIND=${ik}$) if( n>=mnthr ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') wrkbl = m + lwork_sgelqf_mn wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sgebrd_mm ) maxwrk = max( wrkbl, bdspac + m ) minwrk = bdspac + m else if( wntqo ) then ! path 2t (n >> m, jobz='o') wrkbl = m + lwork_sgelqf_mn wrkbl = max( wrkbl, m + lwork_sorglq_mn ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sgebrd_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_prt_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + 2_${ik}$*m*m minwrk = bdspac + 2_${ik}$*m*m + 3_${ik}$*m else if( wntqs ) then ! path 3t (n >> m, jobz='s') wrkbl = m + lwork_sgelqf_mn wrkbl = max( wrkbl, m + lwork_sorglq_mn ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sgebrd_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_prt_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + m*m minwrk = bdspac + m*m + 3_${ik}$*m else if( wntqa ) then ! path 4t (n >> m, jobz='a') wrkbl = m + lwork_sgelqf_mn wrkbl = max( wrkbl, m + lwork_sorglq_nn ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sgebrd_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_prt_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + m*m minwrk = m*m + max( 3_${ik}$*m + bdspac, m + n ) end if else ! path 5t (n > m, but not much larger) wrkbl = 3_${ik}$*m + lwork_sgebrd_mn if( wntqn ) then ! path 5tn (n > m, jobz='n') maxwrk = max( wrkbl, 3_${ik}$*m + bdspac ) minwrk = 3_${ik}$*m + max( n, bdspac ) else if( wntqo ) then ! path 5to (n > m, jobz='o') wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_prt_mn ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + m*n minwrk = 3_${ik}$*m + max( n, m*m + bdspac ) else if( wntqs ) then ! path 5ts (n > m, jobz='s') wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_prt_mn ) maxwrk = max( wrkbl, 3_${ik}$*m + bdspac ) minwrk = 3_${ik}$*m + max( n, bdspac ) else if( wntqa ) then ! path 5ta (n > m, jobz='a') wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_sormbr_prt_nn ) maxwrk = max( wrkbl, 3_${ik}$*m + bdspac ) minwrk = 3_${ik}$*m + max( n, bdspac ) end if end if end if maxwrk = max( maxwrk, minwrk ) work( 1_${ik}$ ) = stdlib${ii}$_sroundup_lwork( maxwrk ) if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + n ! compute a=q*r ! workspace: need n [tau] + n [work] ! workspace: prefer n [tau] + n*nb [work] call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! zero out below r if (n>1_${ik}$) call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) ie = 1_${ik}$ itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! workspace: need 3*n [e, tauq, taup] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_sgebrd( n, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) nwork = ie + n ! perform bidiagonal svd, computing singular values only ! workspace: need n [e] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'N', n, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 2 (m >> n, jobz = 'o') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt ir = 1_${ik}$ ! work(ir) is ldwrkr by n if( lwork >= lda*n + n*n + 3_${ik}$*n + bdspac ) then ldwrkr = lda else ldwrkr = ( lwork - n*n - 3_${ik}$*n - bdspac ) / n end if itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_slaset( 'L', n - 1_${ik}$, n - 1_${ik}$, zero, zero, work(ir+1),ldwrkr ) ! generate q in a ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_sorgqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_sgebrd( n, n, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! work(iu) is n by n iu = nwork nwork = iu + n*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in work(iu) and computing right ! singular vectors of bidiagonal matrix in vt ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n*n [u] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, work( ie ), work( iu ), n,vt, ldvt, dum, & idum, work( nwork ), iwork,info ) ! overwrite work(iu) by left singular vectors of r ! and vt by right singular vectors of r ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n*n [u] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + n*n [u] + n*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iu ), n, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_sormbr( 'P', 'R', 'T', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in work(ir) and copying to a ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n*n [u] ! workspace: prefer m*n [r] + 3*n [e, tauq, taup] + n*n [u] do i = 1, m, ldwrkr chunk = min( m - i + 1_${ik}$, ldwrkr ) call stdlib${ii}$_sgemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( iu ), & n, zero, work( ir ),ldwrkr ) call stdlib${ii}$_slacpy( 'F', chunk, n, work( ir ), ldwrkr,a( i, 1_${ik}$ ), lda ) end do else if( wntqs ) then ! path 3 (m >> n, jobz='s') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt ir = 1_${ik}$ ! work(ir) is n by n ldwrkr = n itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_slacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_slaset( 'L', n - 1_${ik}$, n - 1_${ik}$, zero, zero, work(ir+1),ldwrkr ) ! generate q in a ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_sorgqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_sgebrd( n, n, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagoal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need n*n [r] + 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of r and vt ! by right singular vectors of r ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + n*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & u, ldu, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_sormbr( 'P', 'R', 'T', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! workspace: need n*n [r] call stdlib${ii}$_slacpy( 'F', n, n, u, ldu, work( ir ), ldwrkr ) call stdlib${ii}$_sgemm( 'N', 'N', m, n, n, one, a, lda, work( ir ),ldwrkr, zero, u,& ldu ) else if( wntqa ) then ! path 4 (m >> n, jobz='a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt iu = 1_${ik}$ ! work(iu) is n by n ldwrku = n itau = iu + ldwrku*n nwork = itau + n ! compute a=q*r, copying result to u ! workspace: need n*n [u] + n [tau] + n [work] ! workspace: prefer n*n [u] + n [tau] + n*nb [work] call stdlib${ii}$_sgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) call stdlib${ii}$_slacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! workspace: need n*n [u] + n [tau] + m [work] ! workspace: prefer n*n [u] + n [tau] + m*nb [work] call stdlib${ii}$_sorgqr( m, m, n, u, ldu, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ! produce r in a, zeroing out other entries if (n>1_${ik}$) call stdlib${ii}$_slaset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) ie = itau itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! workspace: need n*n [u] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [u] + 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_sgebrd( n, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in work(iu) and computing right ! singular vectors of bidiagonal matrix in vt ! workspace: need n*n [u] + 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, work( ie ), work( iu ), n,vt, ldvt, dum, & idum, work( nwork ), iwork,info ) ! overwrite work(iu) by left singular vectors of r and vt ! by right singular vectors of r ! workspace: need n*n [u] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [u] + 3*n [e, tauq, taup] + n*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', n, n, n, a, lda,work( itauq ), work( iu ), & ldwrku,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_sormbr( 'P', 'R', 'T', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! workspace: need n*n [u] call stdlib${ii}$_sgemm( 'N', 'N', m, n, n, one, u, ldu, work( iu ),ldwrku, zero, a,& lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_slacpy( 'F', m, n, a, lda, u, ldu ) end if else ! m < mnthr ! path 5 (m >= n, but not much larger) ! reduce to bidiagonal form without qr decomposition ie = 1_${ik}$ itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize a ! workspace: need 3*n [e, tauq, taup] + m [work] ! workspace: prefer 3*n [e, tauq, taup] + (m+n)*nb [work] call stdlib${ii}$_sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5n (m >= n, jobz='n') ! perform bidiagonal svd, only computing singular values ! workspace: need 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'N', n, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 5o (m >= n, jobz='o') iu = nwork if( lwork >= m*n + 3_${ik}$*n + bdspac ) then ! work( iu ) is m by n ldwrku = m nwork = iu + ldwrku*n call stdlib${ii}$_slaset( 'F', m, n, zero, zero, work( iu ),ldwrku ) ! ir is unused; silence compile warnings ir = -1_${ik}$ else ! work( iu ) is n by n ldwrku = n nwork = iu + ldwrku*n ! work(ir) is ldwrkr by n ir = nwork ldwrkr = ( lwork - n*n - 3_${ik}$*n ) / n end if nwork = iu + ldwrku*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in work(iu) and computing right ! singular vectors of bidiagonal matrix in vt ! workspace: need 3*n [e, tauq, taup] + n*n [u] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, work( ie ), work( iu ),ldwrku, vt, ldvt, & dum, idum, work( nwork ),iwork, info ) ! overwrite vt by right singular vectors of a ! workspace: need 3*n [e, tauq, taup] + n*n [u] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + n*n [u] + n*nb [work] call stdlib${ii}$_sormbr( 'P', 'R', 'T', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) if( lwork >= m*n + 3_${ik}$*n + bdspac ) then ! path 5o-fast ! overwrite work(iu) by left singular vectors of a ! workspace: need 3*n [e, tauq, taup] + m*n [u] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + m*n [u] + n*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), work( iu & ), ldwrku,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! copy left singular vectors of a from work(iu) to a call stdlib${ii}$_slacpy( 'F', m, n, work( iu ), ldwrku, a, lda ) else ! path 5o-slow ! generate q in a ! workspace: need 3*n [e, tauq, taup] + n*n [u] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + n*n [u] + n*nb [work] call stdlib${ii}$_sorgbr( 'Q', m, n, n, a, lda, work( itauq ),work( nwork ), & lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by left singular vectors of ! bidiagonal matrix in work(iu), storing result in ! work(ir) and copying to a ! workspace: need 3*n [e, tauq, taup] + n*n [u] + nb*n [r] ! workspace: prefer 3*n [e, tauq, taup] + n*n [u] + m*n [r] do i = 1, m, ldwrkr chunk = min( m - i + 1_${ik}$, ldwrkr ) call stdlib${ii}$_sgemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( iu )& , ldwrku, zero,work( ir ), ldwrkr ) call stdlib${ii}$_slacpy( 'F', chunk, n, work( ir ), ldwrkr,a( i, 1_${ik}$ ), lda ) end do end if else if( wntqs ) then ! path 5s (m >= n, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_slaset( 'F', m, n, zero, zero, u, ldu ) call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*n [e, tauq, taup] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + n*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_sormbr( 'P', 'R', 'T', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) else if( wntqa ) then ! path 5a (m >= n, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_slaset( 'F', m, m, zero, zero, u, ldu ) call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! set the right corner of u to identity matrix if( m>n ) then call stdlib${ii}$_slaset( 'F', m - n, m - n, zero, one, u(n+1,n+1),ldu ) end if ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*n [e, tauq, taup] + m [work] ! workspace: prefer 3*n [e, tauq, taup] + m*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_sormbr( 'P', 'R', 'T', n, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + m ! compute a=l*q ! workspace: need m [tau] + m [work] ! workspace: prefer m [tau] + m*nb [work] call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ), lda ) ie = 1_${ik}$ itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! workspace: need 3*m [e, tauq, taup] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_sgebrd( m, m, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) nwork = ie + m ! perform bidiagonal svd, computing singular values only ! workspace: need m [e] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'N', m, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 2t (n >> m, jobz='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ! work(ivt) is m by m ! work(il) is m by m; it is later resized to m by chunk for gemm il = ivt + m*m if( lwork >= m*n + m*m + 3_${ik}$*m + bdspac ) then ldwrkl = m chunk = n else ldwrkl = m chunk = ( lwork - m*m ) / m end if itau = il + ldwrkl*m nwork = itau + m ! compute a=l*q ! workspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy l to work(il), zeroing about above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_slaset( 'U', m - 1_${ik}$, m - 1_${ik}$, zero, zero,work( il + ldwrkl ), ldwrkl & ) ! generate q in a ! workspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_sorglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il) ! workspace: need m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_sgebrd( m, m, work( il ), ldwrkl, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u, and computing right singular ! vectors of bidiagonal matrix in work(ivt) ! workspace: need m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'I', m, s, work( ie ), u, ldu,work( ivt ), m, dum, & idum, work( nwork ),iwork, info ) ! overwrite u by left singular vectors of l and work(ivt) ! by right singular vectors of l ! workspace: need m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + m*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_sormbr( 'P', 'R', 'T', m, m, m, work( il ), ldwrkl,work( itaup ), & work( ivt ), m,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! multiply right singular vectors of l in work(ivt) by q ! in a, storing result in work(il) and copying to a ! workspace: need m*m [vt] + m*m [l] ! workspace: prefer m*m [vt] + m*n [l] ! at this point, l is resized as m by chunk. do i = 1, n, chunk blk = min( n - i + 1_${ik}$, chunk ) call stdlib${ii}$_sgemm( 'N', 'N', m, blk, m, one, work( ivt ), m,a( 1_${ik}$, i ), lda,& zero, work( il ), ldwrkl ) call stdlib${ii}$_slacpy( 'F', m, blk, work( il ), ldwrkl,a( 1_${ik}$, i ), lda ) end do else if( wntqs ) then ! path 3t (n >> m, jobz='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u il = 1_${ik}$ ! work(il) is m by m ldwrkl = m itau = il + ldwrkl*m nwork = itau + m ! compute a=l*q ! workspace: need m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy l to work(il), zeroing out above it call stdlib${ii}$_slacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_slaset( 'U', m - 1_${ik}$, m - 1_${ik}$, zero, zero,work( il + ldwrkl ), ldwrkl & ) ! generate q in a ! workspace: need m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_sorglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(iu). ! workspace: need m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [l] + 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_sgebrd( m, m, work( il ), ldwrkl, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need m*m [l] + 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'I', m, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of l and vt ! by right singular vectors of l ! workspace: need m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [l] + 3*m [e, tauq, taup] + m*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_sormbr( 'P', 'R', 'T', m, m, m, work( il ), ldwrkl,work( itaup ), & vt, ldvt, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply right singular vectors of l in work(il) by ! q in a, storing result in vt ! workspace: need m*m [l] call stdlib${ii}$_slacpy( 'F', m, m, vt, ldvt, work( il ), ldwrkl ) call stdlib${ii}$_sgemm( 'N', 'N', m, n, m, one, work( il ), ldwrkl,a, lda, zero, & vt, ldvt ) else if( wntqa ) then ! path 4t (n >> m, jobz='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ! work(ivt) is m by m ldwkvt = m itau = ivt + ldwkvt*m nwork = itau + m ! compute a=l*q, copying result to vt ! workspace: need m*m [vt] + m [tau] + m [work] ! workspace: prefer m*m [vt] + m [tau] + m*nb [work] call stdlib${ii}$_sgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) call stdlib${ii}$_slacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! workspace: need m*m [vt] + m [tau] + n [work] ! workspace: prefer m*m [vt] + m [tau] + n*nb [work] call stdlib${ii}$_sorglq( n, n, m, vt, ldvt, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ! produce l in a, zeroing out other entries if (m>1_${ik}$) call stdlib${ii}$_slaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ), lda ) ie = itau itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! workspace: need m*m [vt] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [vt] + 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_sgebrd( m, m, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in work(ivt) ! workspace: need m*m [vt] + 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'I', m, s, work( ie ), u, ldu,work( ivt ), ldwkvt, & dum, idum,work( nwork ), iwork, info ) ! overwrite u by left singular vectors of l and work(ivt) ! by right singular vectors of l ! workspace: need m*m [vt] + 3*m [e, tauq, taup]+ m [work] ! workspace: prefer m*m [vt] + 3*m [e, tauq, taup]+ m*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, m, m, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_sormbr( 'P', 'R', 'T', m, m, m, a, lda,work( itaup ), work( ivt ),& ldwkvt,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! multiply right singular vectors of l in work(ivt) by ! q in vt, storing result in a ! workspace: need m*m [vt] call stdlib${ii}$_sgemm( 'N', 'N', m, n, m, one, work( ivt ), ldwkvt,vt, ldvt, zero,& a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_slacpy( 'F', m, n, a, lda, vt, ldvt ) end if else ! n < mnthr ! path 5t (n > m, but not much larger) ! reduce to bidiagonal form without lq decomposition ie = 1_${ik}$ itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize a ! workspace: need 3*m [e, tauq, taup] + n [work] ! workspace: prefer 3*m [e, tauq, taup] + (m+n)*nb [work] call stdlib${ii}$_sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5tn (n > m, jobz='n') ! perform bidiagonal svd, only computing singular values ! workspace: need 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_sbdsdc( 'L', 'N', m, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 5to (n > m, jobz='o') ldwkvt = m ivt = nwork if( lwork >= m*n + 3_${ik}$*m + bdspac ) then ! work( ivt ) is m by n call stdlib${ii}$_slaset( 'F', m, n, zero, zero, work( ivt ),ldwkvt ) nwork = ivt + ldwkvt*n ! il is unused; silence compile warnings il = -1_${ik}$ else ! work( ivt ) is m by m nwork = ivt + ldwkvt*m il = nwork ! work(il) is m by chunk chunk = ( lwork - m*m - 3_${ik}$*m ) / m end if ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in work(ivt) ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + bdspac call stdlib${ii}$_sbdsdc( 'L', 'I', m, s, work( ie ), u, ldu,work( ivt ), ldwkvt, & dum, idum,work( nwork ), iwork, info ) ! overwrite u by left singular vectors of a ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*m [vt] + m*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) if( lwork >= m*n + 3_${ik}$*m + bdspac ) then ! path 5to-fast ! overwrite work(ivt) by left singular vectors of a ! workspace: need 3*m [e, tauq, taup] + m*n [vt] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*n [vt] + m*nb [work] call stdlib${ii}$_sormbr( 'P', 'R', 'T', m, n, m, a, lda,work( itaup ), work( & ivt ), ldwkvt,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! copy right singular vectors of a from work(ivt) to a call stdlib${ii}$_slacpy( 'F', m, n, work( ivt ), ldwkvt, a, lda ) else ! path 5to-slow ! generate p**t in a ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*m [vt] + m*nb [work] call stdlib${ii}$_sorgbr( 'P', m, n, m, a, lda, work( itaup ),work( nwork ), & lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by right singular vectors of ! bidiagonal matrix in work(ivt), storing result in ! work(il) and copying to a ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + m*nb [l] ! workspace: prefer 3*m [e, tauq, taup] + m*m [vt] + m*n [l] do i = 1, n, chunk blk = min( n - i + 1_${ik}$, chunk ) call stdlib${ii}$_sgemm( 'N', 'N', m, blk, m, one, work( ivt ),ldwkvt, a( 1_${ik}$, & i ), lda, zero,work( il ), m ) call stdlib${ii}$_slacpy( 'F', m, blk, work( il ), m, a( 1_${ik}$, i ),lda ) end do end if else if( wntqs ) then ! path 5ts (n > m, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_slaset( 'F', m, n, zero, zero, vt, ldvt ) call stdlib${ii}$_sbdsdc( 'L', 'I', m, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*m [e, tauq, taup] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_sormbr( 'P', 'R', 'T', m, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) else if( wntqa ) then ! path 5ta (n > m, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_slaset( 'F', n, n, zero, zero, vt, ldvt ) call stdlib${ii}$_sbdsdc( 'L', 'I', m, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! set the right corner of vt to identity matrix if( n>m ) then call stdlib${ii}$_slaset( 'F', n-m, n-m, zero, one, vt(m+1,m+1),ldvt ) end if ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*m [e, tauq, taup] + n [work] ! workspace: prefer 3*m [e, tauq, taup] + n*nb [work] call stdlib${ii}$_sormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_sormbr( 'P', 'R', 'T', n, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) end if end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( anrm=n .and. ldvt=n .and. minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_dbdsdc if( wntqn ) then ! stdlib${ii}$_dbdsdc needs only 4*n (or 6*n for uplo=l for lapack <= 3.6_dp) ! keep 7*n for backwards compatibility. bdspac = 7_${ik}$*n else bdspac = 3_${ik}$*n*n + 4_${ik}$*n end if ! compute space preferred for each routine call stdlib${ii}$_dgebrd( m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & ierr ) lwork_dgebrd_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dgebrd( n, n, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & ierr ) lwork_dgebrd_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dgeqrf( m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dgeqrf_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dorgbr( 'Q', n, n, n, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$,ierr ) lwork_dorgbr_q_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dorgqr( m, m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgqr_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dorgqr( m, n, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgqr_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dormbr( 'P', 'R', 'T', n, n, n, dum(1_${ik}$), n,dum(1_${ik}$), dum(1_${ik}$), n, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_dormbr_prt_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dormbr( 'Q', 'L', 'N', n, n, n, dum(1_${ik}$), n,dum(1_${ik}$), dum(1_${ik}$), n, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_dormbr_qln_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, n, n, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_dormbr_qln_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, m, n, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_dormbr_qln_mm = int( dum(1_${ik}$),KIND=${ik}$) if( m>=mnthr ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') wrkbl = n + lwork_dgeqrf_mn wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd_nn ) maxwrk = max( wrkbl, bdspac + n ) minwrk = bdspac + n else if( wntqo ) then ! path 2 (m >> n, jobz='o') wrkbl = n + lwork_dgeqrf_mn wrkbl = max( wrkbl, n + lwork_dorgqr_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_qln_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + 2_${ik}$*n*n minwrk = bdspac + 2_${ik}$*n*n + 3_${ik}$*n else if( wntqs ) then ! path 3 (m >> n, jobz='s') wrkbl = n + lwork_dgeqrf_mn wrkbl = max( wrkbl, n + lwork_dorgqr_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_qln_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + n*n minwrk = bdspac + n*n + 3_${ik}$*n else if( wntqa ) then ! path 4 (m >> n, jobz='a') wrkbl = n + lwork_dgeqrf_mn wrkbl = max( wrkbl, n + lwork_dorgqr_mm ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dgebrd_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_qln_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + n*n minwrk = n*n + max( 3_${ik}$*n + bdspac, n + m ) end if else ! path 5 (m >= n, but not much larger) wrkbl = 3_${ik}$*n + lwork_dgebrd_mn if( wntqn ) then ! path 5n (m >= n, jobz='n') maxwrk = max( wrkbl, 3_${ik}$*n + bdspac ) minwrk = 3_${ik}$*n + max( m, bdspac ) else if( wntqo ) then ! path 5o (m >= n, jobz='o') wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_qln_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + m*n minwrk = 3_${ik}$*n + max( m, n*n + bdspac ) else if( wntqs ) then ! path 5s (m >= n, jobz='s') wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_qln_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_prt_nn ) maxwrk = max( wrkbl, 3_${ik}$*n + bdspac ) minwrk = 3_${ik}$*n + max( m, bdspac ) else if( wntqa ) then ! path 5a (m >= n, jobz='a') wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_dormbr_prt_nn ) maxwrk = max( wrkbl, 3_${ik}$*n + bdspac ) minwrk = 3_${ik}$*n + max( m, bdspac ) end if end if else if( minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_dbdsdc if( wntqn ) then ! stdlib${ii}$_dbdsdc needs only 4*n (or 6*n for uplo=l for lapack <= 3.6_dp) ! keep 7*n for backwards compatibility. bdspac = 7_${ik}$*m else bdspac = 3_${ik}$*m*m + 4_${ik}$*m end if ! compute space preferred for each routine call stdlib${ii}$_dgebrd( m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & ierr ) lwork_dgebrd_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dgebrd( m, m, a, m, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dgebrd_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dgelqf( m, n, a, m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dgelqf_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dorglq( n, n, m, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorglq_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dorglq( m, n, m, a, m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorglq_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dorgbr( 'P', m, m, m, a, n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_dorgbr_p_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dormbr( 'P', 'R', 'T', m, m, m, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_dormbr_prt_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dormbr( 'P', 'R', 'T', m, n, m, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_dormbr_prt_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dormbr( 'P', 'R', 'T', n, n, m, dum(1_${ik}$), n,dum(1_${ik}$), dum(1_${ik}$), n, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_dormbr_prt_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, m, m, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_dormbr_qln_mm = int( dum(1_${ik}$),KIND=${ik}$) if( n>=mnthr ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') wrkbl = m + lwork_dgelqf_mn wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd_mm ) maxwrk = max( wrkbl, bdspac + m ) minwrk = bdspac + m else if( wntqo ) then ! path 2t (n >> m, jobz='o') wrkbl = m + lwork_dgelqf_mn wrkbl = max( wrkbl, m + lwork_dorglq_mn ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_prt_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + 2_${ik}$*m*m minwrk = bdspac + 2_${ik}$*m*m + 3_${ik}$*m else if( wntqs ) then ! path 3t (n >> m, jobz='s') wrkbl = m + lwork_dgelqf_mn wrkbl = max( wrkbl, m + lwork_dorglq_mn ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_prt_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + m*m minwrk = bdspac + m*m + 3_${ik}$*m else if( wntqa ) then ! path 4t (n >> m, jobz='a') wrkbl = m + lwork_dgelqf_mn wrkbl = max( wrkbl, m + lwork_dorglq_nn ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dgebrd_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_prt_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + m*m minwrk = m*m + max( 3_${ik}$*m + bdspac, m + n ) end if else ! path 5t (n > m, but not much larger) wrkbl = 3_${ik}$*m + lwork_dgebrd_mn if( wntqn ) then ! path 5tn (n > m, jobz='n') maxwrk = max( wrkbl, 3_${ik}$*m + bdspac ) minwrk = 3_${ik}$*m + max( n, bdspac ) else if( wntqo ) then ! path 5to (n > m, jobz='o') wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_prt_mn ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + m*n minwrk = 3_${ik}$*m + max( n, m*m + bdspac ) else if( wntqs ) then ! path 5ts (n > m, jobz='s') wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_prt_mn ) maxwrk = max( wrkbl, 3_${ik}$*m + bdspac ) minwrk = 3_${ik}$*m + max( n, bdspac ) else if( wntqa ) then ! path 5ta (n > m, jobz='a') wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_dormbr_prt_nn ) maxwrk = max( wrkbl, 3_${ik}$*m + bdspac ) minwrk = 3_${ik}$*m + max( n, bdspac ) end if end if end if maxwrk = max( maxwrk, minwrk ) work( 1_${ik}$ ) = stdlib${ii}$_droundup_lwork( maxwrk ) if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + n ! compute a=q*r ! workspace: need n [tau] + n [work] ! workspace: prefer n [tau] + n*nb [work] call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! zero out below r if (n>1_${ik}$) call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) ie = 1_${ik}$ itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! workspace: need 3*n [e, tauq, taup] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_dgebrd( n, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) nwork = ie + n ! perform bidiagonal svd, computing singular values only ! workspace: need n [e] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'N', n, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 2 (m >> n, jobz = 'o') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt ir = 1_${ik}$ ! work(ir) is ldwrkr by n if( lwork >= lda*n + n*n + 3_${ik}$*n + bdspac ) then ldwrkr = lda else ldwrkr = ( lwork - n*n - 3_${ik}$*n - bdspac ) / n end if itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_dlaset( 'L', n - 1_${ik}$, n - 1_${ik}$, zero, zero, work(ir+1),ldwrkr ) ! generate q in a ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_dorgqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_dgebrd( n, n, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! work(iu) is n by n iu = nwork nwork = iu + n*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in work(iu) and computing right ! singular vectors of bidiagonal matrix in vt ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n*n [u] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, work( ie ), work( iu ), n,vt, ldvt, dum, & idum, work( nwork ), iwork,info ) ! overwrite work(iu) by left singular vectors of r ! and vt by right singular vectors of r ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n*n [u] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + n*n [u] + n*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iu ), n, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_dormbr( 'P', 'R', 'T', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in work(ir) and copying to a ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n*n [u] ! workspace: prefer m*n [r] + 3*n [e, tauq, taup] + n*n [u] do i = 1, m, ldwrkr chunk = min( m - i + 1_${ik}$, ldwrkr ) call stdlib${ii}$_dgemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( iu ), & n, zero, work( ir ),ldwrkr ) call stdlib${ii}$_dlacpy( 'F', chunk, n, work( ir ), ldwrkr,a( i, 1_${ik}$ ), lda ) end do else if( wntqs ) then ! path 3 (m >> n, jobz='s') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt ir = 1_${ik}$ ! work(ir) is n by n ldwrkr = n itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_dlaset( 'L', n - 1_${ik}$, n - 1_${ik}$, zero, zero, work(ir+1),ldwrkr ) ! generate q in a ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_dorgqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_dgebrd( n, n, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagoal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need n*n [r] + 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of r and vt ! by right singular vectors of r ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + n*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & u, ldu, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_dormbr( 'P', 'R', 'T', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! workspace: need n*n [r] call stdlib${ii}$_dlacpy( 'F', n, n, u, ldu, work( ir ), ldwrkr ) call stdlib${ii}$_dgemm( 'N', 'N', m, n, n, one, a, lda, work( ir ),ldwrkr, zero, u,& ldu ) else if( wntqa ) then ! path 4 (m >> n, jobz='a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt iu = 1_${ik}$ ! work(iu) is n by n ldwrku = n itau = iu + ldwrku*n nwork = itau + n ! compute a=q*r, copying result to u ! workspace: need n*n [u] + n [tau] + n [work] ! workspace: prefer n*n [u] + n [tau] + n*nb [work] call stdlib${ii}$_dgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) call stdlib${ii}$_dlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! workspace: need n*n [u] + n [tau] + m [work] ! workspace: prefer n*n [u] + n [tau] + m*nb [work] call stdlib${ii}$_dorgqr( m, m, n, u, ldu, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ! produce r in a, zeroing out other entries if (n>1_${ik}$) call stdlib${ii}$_dlaset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) ie = itau itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! workspace: need n*n [u] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [u] + 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_dgebrd( n, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in work(iu) and computing right ! singular vectors of bidiagonal matrix in vt ! workspace: need n*n [u] + 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, work( ie ), work( iu ), n,vt, ldvt, dum, & idum, work( nwork ), iwork,info ) ! overwrite work(iu) by left singular vectors of r and vt ! by right singular vectors of r ! workspace: need n*n [u] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [u] + 3*n [e, tauq, taup] + n*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', n, n, n, a, lda,work( itauq ), work( iu ), & ldwrku,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_dormbr( 'P', 'R', 'T', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! workspace: need n*n [u] call stdlib${ii}$_dgemm( 'N', 'N', m, n, n, one, u, ldu, work( iu ),ldwrku, zero, a,& lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_dlacpy( 'F', m, n, a, lda, u, ldu ) end if else ! m < mnthr ! path 5 (m >= n, but not much larger) ! reduce to bidiagonal form without qr decomposition ie = 1_${ik}$ itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize a ! workspace: need 3*n [e, tauq, taup] + m [work] ! workspace: prefer 3*n [e, tauq, taup] + (m+n)*nb [work] call stdlib${ii}$_dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5n (m >= n, jobz='n') ! perform bidiagonal svd, only computing singular values ! workspace: need 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'N', n, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 5o (m >= n, jobz='o') iu = nwork if( lwork >= m*n + 3_${ik}$*n + bdspac ) then ! work( iu ) is m by n ldwrku = m nwork = iu + ldwrku*n call stdlib${ii}$_dlaset( 'F', m, n, zero, zero, work( iu ),ldwrku ) ! ir is unused; silence compile warnings ir = -1_${ik}$ else ! work( iu ) is n by n ldwrku = n nwork = iu + ldwrku*n ! work(ir) is ldwrkr by n ir = nwork ldwrkr = ( lwork - n*n - 3_${ik}$*n ) / n end if nwork = iu + ldwrku*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in work(iu) and computing right ! singular vectors of bidiagonal matrix in vt ! workspace: need 3*n [e, tauq, taup] + n*n [u] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, work( ie ), work( iu ),ldwrku, vt, ldvt, & dum, idum, work( nwork ),iwork, info ) ! overwrite vt by right singular vectors of a ! workspace: need 3*n [e, tauq, taup] + n*n [u] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + n*n [u] + n*nb [work] call stdlib${ii}$_dormbr( 'P', 'R', 'T', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) if( lwork >= m*n + 3_${ik}$*n + bdspac ) then ! path 5o-fast ! overwrite work(iu) by left singular vectors of a ! workspace: need 3*n [e, tauq, taup] + m*n [u] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + m*n [u] + n*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), work( iu & ), ldwrku,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! copy left singular vectors of a from work(iu) to a call stdlib${ii}$_dlacpy( 'F', m, n, work( iu ), ldwrku, a, lda ) else ! path 5o-slow ! generate q in a ! workspace: need 3*n [e, tauq, taup] + n*n [u] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + n*n [u] + n*nb [work] call stdlib${ii}$_dorgbr( 'Q', m, n, n, a, lda, work( itauq ),work( nwork ), & lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by left singular vectors of ! bidiagonal matrix in work(iu), storing result in ! work(ir) and copying to a ! workspace: need 3*n [e, tauq, taup] + n*n [u] + nb*n [r] ! workspace: prefer 3*n [e, tauq, taup] + n*n [u] + m*n [r] do i = 1, m, ldwrkr chunk = min( m - i + 1_${ik}$, ldwrkr ) call stdlib${ii}$_dgemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( iu )& , ldwrku, zero,work( ir ), ldwrkr ) call stdlib${ii}$_dlacpy( 'F', chunk, n, work( ir ), ldwrkr,a( i, 1_${ik}$ ), lda ) end do end if else if( wntqs ) then ! path 5s (m >= n, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_dlaset( 'F', m, n, zero, zero, u, ldu ) call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*n [e, tauq, taup] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + n*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_dormbr( 'P', 'R', 'T', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) else if( wntqa ) then ! path 5a (m >= n, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_dlaset( 'F', m, m, zero, zero, u, ldu ) call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! set the right corner of u to identity matrix if( m>n ) then call stdlib${ii}$_dlaset( 'F', m - n, m - n, zero, one, u(n+1,n+1),ldu ) end if ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*n [e, tauq, taup] + m [work] ! workspace: prefer 3*n [e, tauq, taup] + m*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_dormbr( 'P', 'R', 'T', n, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + m ! compute a=l*q ! workspace: need m [tau] + m [work] ! workspace: prefer m [tau] + m*nb [work] call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ), lda ) ie = 1_${ik}$ itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! workspace: need 3*m [e, tauq, taup] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_dgebrd( m, m, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) nwork = ie + m ! perform bidiagonal svd, computing singular values only ! workspace: need m [e] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'N', m, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 2t (n >> m, jobz='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ! work(ivt) is m by m ! work(il) is m by m; it is later resized to m by chunk for gemm il = ivt + m*m if( lwork >= m*n + m*m + 3_${ik}$*m + bdspac ) then ldwrkl = m chunk = n else ldwrkl = m chunk = ( lwork - m*m ) / m end if itau = il + ldwrkl*m nwork = itau + m ! compute a=l*q ! workspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy l to work(il), zeroing about above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_dlaset( 'U', m - 1_${ik}$, m - 1_${ik}$, zero, zero,work( il + ldwrkl ), ldwrkl & ) ! generate q in a ! workspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_dorglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il) ! workspace: need m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_dgebrd( m, m, work( il ), ldwrkl, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u, and computing right singular ! vectors of bidiagonal matrix in work(ivt) ! workspace: need m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'I', m, s, work( ie ), u, ldu,work( ivt ), m, dum, & idum, work( nwork ),iwork, info ) ! overwrite u by left singular vectors of l and work(ivt) ! by right singular vectors of l ! workspace: need m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + m*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_dormbr( 'P', 'R', 'T', m, m, m, work( il ), ldwrkl,work( itaup ), & work( ivt ), m,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! multiply right singular vectors of l in work(ivt) by q ! in a, storing result in work(il) and copying to a ! workspace: need m*m [vt] + m*m [l] ! workspace: prefer m*m [vt] + m*n [l] ! at this point, l is resized as m by chunk. do i = 1, n, chunk blk = min( n - i + 1_${ik}$, chunk ) call stdlib${ii}$_dgemm( 'N', 'N', m, blk, m, one, work( ivt ), m,a( 1_${ik}$, i ), lda,& zero, work( il ), ldwrkl ) call stdlib${ii}$_dlacpy( 'F', m, blk, work( il ), ldwrkl,a( 1_${ik}$, i ), lda ) end do else if( wntqs ) then ! path 3t (n >> m, jobz='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u il = 1_${ik}$ ! work(il) is m by m ldwrkl = m itau = il + ldwrkl*m nwork = itau + m ! compute a=l*q ! workspace: need m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy l to work(il), zeroing out above it call stdlib${ii}$_dlacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_dlaset( 'U', m - 1_${ik}$, m - 1_${ik}$, zero, zero,work( il + ldwrkl ), ldwrkl & ) ! generate q in a ! workspace: need m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_dorglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(iu). ! workspace: need m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [l] + 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_dgebrd( m, m, work( il ), ldwrkl, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need m*m [l] + 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'I', m, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of l and vt ! by right singular vectors of l ! workspace: need m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [l] + 3*m [e, tauq, taup] + m*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_dormbr( 'P', 'R', 'T', m, m, m, work( il ), ldwrkl,work( itaup ), & vt, ldvt, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply right singular vectors of l in work(il) by ! q in a, storing result in vt ! workspace: need m*m [l] call stdlib${ii}$_dlacpy( 'F', m, m, vt, ldvt, work( il ), ldwrkl ) call stdlib${ii}$_dgemm( 'N', 'N', m, n, m, one, work( il ), ldwrkl,a, lda, zero, & vt, ldvt ) else if( wntqa ) then ! path 4t (n >> m, jobz='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ! work(ivt) is m by m ldwkvt = m itau = ivt + ldwkvt*m nwork = itau + m ! compute a=l*q, copying result to vt ! workspace: need m*m [vt] + m [tau] + m [work] ! workspace: prefer m*m [vt] + m [tau] + m*nb [work] call stdlib${ii}$_dgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) call stdlib${ii}$_dlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! workspace: need m*m [vt] + m [tau] + n [work] ! workspace: prefer m*m [vt] + m [tau] + n*nb [work] call stdlib${ii}$_dorglq( n, n, m, vt, ldvt, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ! produce l in a, zeroing out other entries if (m>1_${ik}$) call stdlib${ii}$_dlaset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ), lda ) ie = itau itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! workspace: need m*m [vt] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [vt] + 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_dgebrd( m, m, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in work(ivt) ! workspace: need m*m [vt] + 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'I', m, s, work( ie ), u, ldu,work( ivt ), ldwkvt, & dum, idum,work( nwork ), iwork, info ) ! overwrite u by left singular vectors of l and work(ivt) ! by right singular vectors of l ! workspace: need m*m [vt] + 3*m [e, tauq, taup]+ m [work] ! workspace: prefer m*m [vt] + 3*m [e, tauq, taup]+ m*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, m, m, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_dormbr( 'P', 'R', 'T', m, m, m, a, lda,work( itaup ), work( ivt ),& ldwkvt,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! multiply right singular vectors of l in work(ivt) by ! q in vt, storing result in a ! workspace: need m*m [vt] call stdlib${ii}$_dgemm( 'N', 'N', m, n, m, one, work( ivt ), ldwkvt,vt, ldvt, zero,& a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_dlacpy( 'F', m, n, a, lda, vt, ldvt ) end if else ! n < mnthr ! path 5t (n > m, but not much larger) ! reduce to bidiagonal form without lq decomposition ie = 1_${ik}$ itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize a ! workspace: need 3*m [e, tauq, taup] + n [work] ! workspace: prefer 3*m [e, tauq, taup] + (m+n)*nb [work] call stdlib${ii}$_dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5tn (n > m, jobz='n') ! perform bidiagonal svd, only computing singular values ! workspace: need 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_dbdsdc( 'L', 'N', m, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 5to (n > m, jobz='o') ldwkvt = m ivt = nwork if( lwork >= m*n + 3_${ik}$*m + bdspac ) then ! work( ivt ) is m by n call stdlib${ii}$_dlaset( 'F', m, n, zero, zero, work( ivt ),ldwkvt ) nwork = ivt + ldwkvt*n ! il is unused; silence compile warnings il = -1_${ik}$ else ! work( ivt ) is m by m nwork = ivt + ldwkvt*m il = nwork ! work(il) is m by chunk chunk = ( lwork - m*m - 3_${ik}$*m ) / m end if ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in work(ivt) ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + bdspac call stdlib${ii}$_dbdsdc( 'L', 'I', m, s, work( ie ), u, ldu,work( ivt ), ldwkvt, & dum, idum,work( nwork ), iwork, info ) ! overwrite u by left singular vectors of a ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*m [vt] + m*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) if( lwork >= m*n + 3_${ik}$*m + bdspac ) then ! path 5to-fast ! overwrite work(ivt) by left singular vectors of a ! workspace: need 3*m [e, tauq, taup] + m*n [vt] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*n [vt] + m*nb [work] call stdlib${ii}$_dormbr( 'P', 'R', 'T', m, n, m, a, lda,work( itaup ), work( & ivt ), ldwkvt,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! copy right singular vectors of a from work(ivt) to a call stdlib${ii}$_dlacpy( 'F', m, n, work( ivt ), ldwkvt, a, lda ) else ! path 5to-slow ! generate p**t in a ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*m [vt] + m*nb [work] call stdlib${ii}$_dorgbr( 'P', m, n, m, a, lda, work( itaup ),work( nwork ), & lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by right singular vectors of ! bidiagonal matrix in work(ivt), storing result in ! work(il) and copying to a ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + m*nb [l] ! workspace: prefer 3*m [e, tauq, taup] + m*m [vt] + m*n [l] do i = 1, n, chunk blk = min( n - i + 1_${ik}$, chunk ) call stdlib${ii}$_dgemm( 'N', 'N', m, blk, m, one, work( ivt ),ldwkvt, a( 1_${ik}$, & i ), lda, zero,work( il ), m ) call stdlib${ii}$_dlacpy( 'F', m, blk, work( il ), m, a( 1_${ik}$, i ),lda ) end do end if else if( wntqs ) then ! path 5ts (n > m, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_dlaset( 'F', m, n, zero, zero, vt, ldvt ) call stdlib${ii}$_dbdsdc( 'L', 'I', m, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*m [e, tauq, taup] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_dormbr( 'P', 'R', 'T', m, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) else if( wntqa ) then ! path 5ta (n > m, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_dlaset( 'F', n, n, zero, zero, vt, ldvt ) call stdlib${ii}$_dbdsdc( 'L', 'I', m, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! set the right corner of vt to identity matrix if( n>m ) then call stdlib${ii}$_dlaset( 'F', n-m, n-m, zero, one, vt(m+1,m+1),ldvt ) end if ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*m [e, tauq, taup] + n [work] ! workspace: prefer 3*m [e, tauq, taup] + n*nb [work] call stdlib${ii}$_dormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_dormbr( 'P', 'R', 'T', n, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) end if end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( anrm=n .and. ldvt=n .and. minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_${ri}$bdsdc if( wntqn ) then ! stdlib${ii}$_${ri}$bdsdc needs only 4*n (or 6*n for uplo=l for lapack <= 3.6_${rk}$) ! keep 7*n for backwards compatibility. bdspac = 7_${ik}$*n else bdspac = 3_${ik}$*n*n + 4_${ik}$*n end if ! compute space preferred for each routine call stdlib${ii}$_${ri}$gebrd( m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & ierr ) lwork_qgebrd_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$gebrd( n, n, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & ierr ) lwork_qgebrd_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$geqrf( m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qgeqrf_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$orgbr( 'Q', n, n, n, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$,ierr ) lwork_qorgbr_q_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$orgqr( m, m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgqr_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$orgqr( m, n, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgqr_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', n, n, n, dum(1_${ik}$), n,dum(1_${ik}$), dum(1_${ik}$), n, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_qormbr_prt_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', n, n, n, dum(1_${ik}$), n,dum(1_${ik}$), dum(1_${ik}$), n, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_qormbr_qln_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, n, n, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_qormbr_qln_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, m, n, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_qormbr_qln_mm = int( dum(1_${ik}$),KIND=${ik}$) if( m>=mnthr ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') wrkbl = n + lwork_qgeqrf_mn wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd_nn ) maxwrk = max( wrkbl, bdspac + n ) minwrk = bdspac + n else if( wntqo ) then ! path 2 (m >> n, jobz='o') wrkbl = n + lwork_qgeqrf_mn wrkbl = max( wrkbl, n + lwork_qorgqr_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_qln_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + 2_${ik}$*n*n minwrk = bdspac + 2_${ik}$*n*n + 3_${ik}$*n else if( wntqs ) then ! path 3 (m >> n, jobz='s') wrkbl = n + lwork_qgeqrf_mn wrkbl = max( wrkbl, n + lwork_qorgqr_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_qln_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + n*n minwrk = bdspac + n*n + 3_${ik}$*n else if( wntqa ) then ! path 4 (m >> n, jobz='a') wrkbl = n + lwork_qgeqrf_mn wrkbl = max( wrkbl, n + lwork_qorgqr_mm ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qgebrd_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_qln_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + n*n minwrk = n*n + max( 3_${ik}$*n + bdspac, n + m ) end if else ! path 5 (m >= n, but not much larger) wrkbl = 3_${ik}$*n + lwork_qgebrd_mn if( wntqn ) then ! path 5n (m >= n, jobz='n') maxwrk = max( wrkbl, 3_${ik}$*n + bdspac ) minwrk = 3_${ik}$*n + max( m, bdspac ) else if( wntqo ) then ! path 5o (m >= n, jobz='o') wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_prt_nn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_qln_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + bdspac ) maxwrk = wrkbl + m*n minwrk = 3_${ik}$*n + max( m, n*n + bdspac ) else if( wntqs ) then ! path 5s (m >= n, jobz='s') wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_qln_mn ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_prt_nn ) maxwrk = max( wrkbl, 3_${ik}$*n + bdspac ) minwrk = 3_${ik}$*n + max( m, bdspac ) else if( wntqa ) then ! path 5a (m >= n, jobz='a') wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*n + lwork_qormbr_prt_nn ) maxwrk = max( wrkbl, 3_${ik}$*n + bdspac ) minwrk = 3_${ik}$*n + max( m, bdspac ) end if end if else if( minmn>0_${ik}$ ) then ! compute space needed for stdlib${ii}$_${ri}$bdsdc if( wntqn ) then ! stdlib${ii}$_${ri}$bdsdc needs only 4*n (or 6*n for uplo=l for lapack <= 3.6_${rk}$) ! keep 7*n for backwards compatibility. bdspac = 7_${ik}$*m else bdspac = 3_${ik}$*m*m + 4_${ik}$*m end if ! compute space preferred for each routine call stdlib${ii}$_${ri}$gebrd( m, n, dum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, & ierr ) lwork_qgebrd_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$gebrd( m, m, a, m, s, dum(1_${ik}$), dum(1_${ik}$),dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qgebrd_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$gelqf( m, n, a, m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qgelqf_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$orglq( n, n, m, dum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorglq_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$orglq( m, n, m, a, m, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorglq_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$orgbr( 'P', m, m, m, a, n, dum(1_${ik}$), dum(1_${ik}$), -1_${ik}$, ierr ) lwork_qorgbr_p_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', m, m, m, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_qormbr_prt_mm = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', m, n, m, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_qormbr_prt_mn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', n, n, m, dum(1_${ik}$), n,dum(1_${ik}$), dum(1_${ik}$), n, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_qormbr_prt_nn = int( dum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, m, m, dum(1_${ik}$), m,dum(1_${ik}$), dum(1_${ik}$), m, dum(1_${ik}$), & -1_${ik}$, ierr ) lwork_qormbr_qln_mm = int( dum(1_${ik}$),KIND=${ik}$) if( n>=mnthr ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') wrkbl = m + lwork_qgelqf_mn wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd_mm ) maxwrk = max( wrkbl, bdspac + m ) minwrk = bdspac + m else if( wntqo ) then ! path 2t (n >> m, jobz='o') wrkbl = m + lwork_qgelqf_mn wrkbl = max( wrkbl, m + lwork_qorglq_mn ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_prt_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + 2_${ik}$*m*m minwrk = bdspac + 2_${ik}$*m*m + 3_${ik}$*m else if( wntqs ) then ! path 3t (n >> m, jobz='s') wrkbl = m + lwork_qgelqf_mn wrkbl = max( wrkbl, m + lwork_qorglq_mn ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_prt_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + m*m minwrk = bdspac + m*m + 3_${ik}$*m else if( wntqa ) then ! path 4t (n >> m, jobz='a') wrkbl = m + lwork_qgelqf_mn wrkbl = max( wrkbl, m + lwork_qorglq_nn ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qgebrd_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_prt_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + m*m minwrk = m*m + max( 3_${ik}$*m + bdspac, m + n ) end if else ! path 5t (n > m, but not much larger) wrkbl = 3_${ik}$*m + lwork_qgebrd_mn if( wntqn ) then ! path 5tn (n > m, jobz='n') maxwrk = max( wrkbl, 3_${ik}$*m + bdspac ) minwrk = 3_${ik}$*m + max( n, bdspac ) else if( wntqo ) then ! path 5to (n > m, jobz='o') wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_prt_mn ) wrkbl = max( wrkbl, 3_${ik}$*m + bdspac ) maxwrk = wrkbl + m*n minwrk = 3_${ik}$*m + max( n, m*m + bdspac ) else if( wntqs ) then ! path 5ts (n > m, jobz='s') wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_prt_mn ) maxwrk = max( wrkbl, 3_${ik}$*m + bdspac ) minwrk = 3_${ik}$*m + max( n, bdspac ) else if( wntqa ) then ! path 5ta (n > m, jobz='a') wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_qln_mm ) wrkbl = max( wrkbl, 3_${ik}$*m + lwork_qormbr_prt_nn ) maxwrk = max( wrkbl, 3_${ik}$*m + bdspac ) minwrk = 3_${ik}$*m + max( n, bdspac ) end if end if end if maxwrk = max( maxwrk, minwrk ) work( 1_${ik}$ ) = stdlib${ii}$_${ri}$roundup_lwork( maxwrk ) if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + n ! compute a=q*r ! workspace: need n [tau] + n [work] ! workspace: prefer n [tau] + n*nb [work] call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! zero out below r if (n>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) ie = 1_${ik}$ itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! workspace: need 3*n [e, tauq, taup] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_${ri}$gebrd( n, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) nwork = ie + n ! perform bidiagonal svd, computing singular values only ! workspace: need n [e] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'U', 'N', n, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 2 (m >> n, jobz = 'o') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt ir = 1_${ik}$ ! work(ir) is ldwrkr by n if( lwork >= lda*n + n*n + 3_${ik}$*n + bdspac ) then ldwrkr = lda else ldwrkr = ( lwork - n*n - 3_${ik}$*n - bdspac ) / n end if itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_${ri}$laset( 'L', n - 1_${ik}$, n - 1_${ik}$, zero, zero, work(ir+1),ldwrkr ) ! generate q in a ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_${ri}$orgqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_${ri}$gebrd( n, n, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! work(iu) is n by n iu = nwork nwork = iu + n*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in work(iu) and computing right ! singular vectors of bidiagonal matrix in vt ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n*n [u] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'U', 'I', n, s, work( ie ), work( iu ), n,vt, ldvt, dum, & idum, work( nwork ), iwork,info ) ! overwrite work(iu) by left singular vectors of r ! and vt by right singular vectors of r ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n*n [u] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + n*n [u] + n*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iu ), n, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in work(ir) and copying to a ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n*n [u] ! workspace: prefer m*n [r] + 3*n [e, tauq, taup] + n*n [u] do i = 1, m, ldwrkr chunk = min( m - i + 1_${ik}$, ldwrkr ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( iu ), & n, zero, work( ir ),ldwrkr ) call stdlib${ii}$_${ri}$lacpy( 'F', chunk, n, work( ir ), ldwrkr,a( i, 1_${ik}$ ), lda ) end do else if( wntqs ) then ! path 3 (m >> n, jobz='s') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt ir = 1_${ik}$ ! work(ir) is n by n ldwrkr = n itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_${ri}$laset( 'L', n - 1_${ik}$, n - 1_${ik}$, zero, zero, work(ir+1),ldwrkr ) ! generate q in a ! workspace: need n*n [r] + n [tau] + n [work] ! workspace: prefer n*n [r] + n [tau] + n*nb [work] call stdlib${ii}$_${ri}$orgqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_${ri}$gebrd( n, n, work( ir ), ldwrkr, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagoal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need n*n [r] + 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'U', 'I', n, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of r and vt ! by right singular vectors of r ! workspace: need n*n [r] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [r] + 3*n [e, tauq, taup] + n*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & u, ldu, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! workspace: need n*n [r] call stdlib${ii}$_${ri}$lacpy( 'F', n, n, u, ldu, work( ir ), ldwrkr ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, n, one, a, lda, work( ir ),ldwrkr, zero, u,& ldu ) else if( wntqa ) then ! path 4 (m >> n, jobz='a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt iu = 1_${ik}$ ! work(iu) is n by n ldwrku = n itau = iu + ldwrku*n nwork = itau + n ! compute a=q*r, copying result to u ! workspace: need n*n [u] + n [tau] + n [work] ! workspace: prefer n*n [u] + n [tau] + n*nb [work] call stdlib${ii}$_${ri}$geqrf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! workspace: need n*n [u] + n [tau] + m [work] ! workspace: prefer n*n [u] + n [tau] + m*nb [work] call stdlib${ii}$_${ri}$orgqr( m, m, n, u, ldu, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ! produce r in a, zeroing out other entries if (n>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'L', n-1, n-1, zero, zero, a( 2_${ik}$, 1_${ik}$ ), lda ) ie = itau itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! workspace: need n*n [u] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [u] + 3*n [e, tauq, taup] + 2*n*nb [work] call stdlib${ii}$_${ri}$gebrd( n, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in work(iu) and computing right ! singular vectors of bidiagonal matrix in vt ! workspace: need n*n [u] + 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'U', 'I', n, s, work( ie ), work( iu ), n,vt, ldvt, dum, & idum, work( nwork ), iwork,info ) ! overwrite work(iu) by left singular vectors of r and vt ! by right singular vectors of r ! workspace: need n*n [u] + 3*n [e, tauq, taup] + n [work] ! workspace: prefer n*n [u] + 3*n [e, tauq, taup] + n*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', n, n, n, a, lda,work( itauq ), work( iu ), & ldwrku,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! workspace: need n*n [u] call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, n, one, u, ldu, work( iu ),ldwrku, zero, a,& lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_${ri}$lacpy( 'F', m, n, a, lda, u, ldu ) end if else ! m < mnthr ! path 5 (m >= n, but not much larger) ! reduce to bidiagonal form without qr decomposition ie = 1_${ik}$ itauq = ie + n itaup = itauq + n nwork = itaup + n ! bidiagonalize a ! workspace: need 3*n [e, tauq, taup] + m [work] ! workspace: prefer 3*n [e, tauq, taup] + (m+n)*nb [work] call stdlib${ii}$_${ri}$gebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5n (m >= n, jobz='n') ! perform bidiagonal svd, only computing singular values ! workspace: need 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'U', 'N', n, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 5o (m >= n, jobz='o') iu = nwork if( lwork >= m*n + 3_${ik}$*n + bdspac ) then ! work( iu ) is m by n ldwrku = m nwork = iu + ldwrku*n call stdlib${ii}$_${ri}$laset( 'F', m, n, zero, zero, work( iu ),ldwrku ) ! ir is unused; silence compile warnings ir = -1_${ik}$ else ! work( iu ) is n by n ldwrku = n nwork = iu + ldwrku*n ! work(ir) is ldwrkr by n ir = nwork ldwrkr = ( lwork - n*n - 3_${ik}$*n ) / n end if nwork = iu + ldwrku*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in work(iu) and computing right ! singular vectors of bidiagonal matrix in vt ! workspace: need 3*n [e, tauq, taup] + n*n [u] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'U', 'I', n, s, work( ie ), work( iu ),ldwrku, vt, ldvt, & dum, idum, work( nwork ),iwork, info ) ! overwrite vt by right singular vectors of a ! workspace: need 3*n [e, tauq, taup] + n*n [u] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + n*n [u] + n*nb [work] call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) if( lwork >= m*n + 3_${ik}$*n + bdspac ) then ! path 5o-fast ! overwrite work(iu) by left singular vectors of a ! workspace: need 3*n [e, tauq, taup] + m*n [u] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + m*n [u] + n*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), work( iu & ), ldwrku,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! copy left singular vectors of a from work(iu) to a call stdlib${ii}$_${ri}$lacpy( 'F', m, n, work( iu ), ldwrku, a, lda ) else ! path 5o-slow ! generate q in a ! workspace: need 3*n [e, tauq, taup] + n*n [u] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + n*n [u] + n*nb [work] call stdlib${ii}$_${ri}$orgbr( 'Q', m, n, n, a, lda, work( itauq ),work( nwork ), & lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by left singular vectors of ! bidiagonal matrix in work(iu), storing result in ! work(ir) and copying to a ! workspace: need 3*n [e, tauq, taup] + n*n [u] + nb*n [r] ! workspace: prefer 3*n [e, tauq, taup] + n*n [u] + m*n [r] do i = 1, m, ldwrkr chunk = min( m - i + 1_${ik}$, ldwrkr ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', chunk, n, n, one, a( i, 1_${ik}$ ),lda, work( iu )& , ldwrku, zero,work( ir ), ldwrkr ) call stdlib${ii}$_${ri}$lacpy( 'F', chunk, n, work( ir ), ldwrkr,a( i, 1_${ik}$ ), lda ) end do end if else if( wntqs ) then ! path 5s (m >= n, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_${ri}$laset( 'F', m, n, zero, zero, u, ldu ) call stdlib${ii}$_${ri}$bdsdc( 'U', 'I', n, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*n [e, tauq, taup] + n [work] ! workspace: prefer 3*n [e, tauq, taup] + n*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) else if( wntqa ) then ! path 5a (m >= n, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*n [e, tauq, taup] + bdspac call stdlib${ii}$_${ri}$laset( 'F', m, m, zero, zero, u, ldu ) call stdlib${ii}$_${ri}$bdsdc( 'U', 'I', n, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! set the right corner of u to identity matrix if( m>n ) then call stdlib${ii}$_${ri}$laset( 'F', m - n, m - n, zero, one, u(n+1,n+1),ldu ) end if ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*n [e, tauq, taup] + m [work] ! workspace: prefer 3*n [e, tauq, taup] + m*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', n, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + m ! compute a=l*q ! workspace: need m [tau] + m [work] ! workspace: prefer m [tau] + m*nb [work] call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ), lda ) ie = 1_${ik}$ itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! workspace: need 3*m [e, tauq, taup] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_${ri}$gebrd( m, m, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) nwork = ie + m ! perform bidiagonal svd, computing singular values only ! workspace: need m [e] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'U', 'N', m, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 2t (n >> m, jobz='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ! work(ivt) is m by m ! work(il) is m by m; it is later resized to m by chunk for gemm il = ivt + m*m if( lwork >= m*n + m*m + 3_${ik}$*m + bdspac ) then ldwrkl = m chunk = n else ldwrkl = m chunk = ( lwork - m*m ) / m end if itau = il + ldwrkl*m nwork = itau + m ! compute a=l*q ! workspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy l to work(il), zeroing about above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_${ri}$laset( 'U', m - 1_${ik}$, m - 1_${ik}$, zero, zero,work( il + ldwrkl ), ldwrkl & ) ! generate q in a ! workspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_${ri}$orglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il) ! workspace: need m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_${ri}$gebrd( m, m, work( il ), ldwrkl, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u, and computing right singular ! vectors of bidiagonal matrix in work(ivt) ! workspace: need m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'U', 'I', m, s, work( ie ), u, ldu,work( ivt ), m, dum, & idum, work( nwork ),iwork, info ) ! overwrite u by left singular vectors of l and work(ivt) ! by right singular vectors of l ! workspace: need m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [vt] + m*m [l] + 3*m [e, tauq, taup] + m*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', m, m, m, work( il ), ldwrkl,work( itaup ), & work( ivt ), m,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! multiply right singular vectors of l in work(ivt) by q ! in a, storing result in work(il) and copying to a ! workspace: need m*m [vt] + m*m [l] ! workspace: prefer m*m [vt] + m*n [l] ! at this point, l is resized as m by chunk. do i = 1, n, chunk blk = min( n - i + 1_${ik}$, chunk ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, blk, m, one, work( ivt ), m,a( 1_${ik}$, i ), lda,& zero, work( il ), ldwrkl ) call stdlib${ii}$_${ri}$lacpy( 'F', m, blk, work( il ), ldwrkl,a( 1_${ik}$, i ), lda ) end do else if( wntqs ) then ! path 3t (n >> m, jobz='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u il = 1_${ik}$ ! work(il) is m by m ldwrkl = m itau = il + ldwrkl*m nwork = itau + m ! compute a=l*q ! workspace: need m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) ! copy l to work(il), zeroing out above it call stdlib${ii}$_${ri}$lacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_${ri}$laset( 'U', m - 1_${ik}$, m - 1_${ik}$, zero, zero,work( il + ldwrkl ), ldwrkl & ) ! generate q in a ! workspace: need m*m [l] + m [tau] + m [work] ! workspace: prefer m*m [l] + m [tau] + m*nb [work] call stdlib${ii}$_${ri}$orglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ie = itau itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(iu). ! workspace: need m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [l] + 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_${ri}$gebrd( m, m, work( il ), ldwrkl, s, work( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need m*m [l] + 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'U', 'I', m, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of l and vt ! by right singular vectors of l ! workspace: need m*m [l] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [l] + 3*m [e, tauq, taup] + m*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', m, m, m, work( il ), ldwrkl,work( itaup ), & vt, ldvt, work( nwork ),lwork - nwork + 1_${ik}$, ierr ) ! multiply right singular vectors of l in work(il) by ! q in a, storing result in vt ! workspace: need m*m [l] call stdlib${ii}$_${ri}$lacpy( 'F', m, m, vt, ldvt, work( il ), ldwrkl ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, m, one, work( il ), ldwrkl,a, lda, zero, & vt, ldvt ) else if( wntqa ) then ! path 4t (n >> m, jobz='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ! work(ivt) is m by m ldwkvt = m itau = ivt + ldwkvt*m nwork = itau + m ! compute a=l*q, copying result to vt ! workspace: need m*m [vt] + m [tau] + m [work] ! workspace: prefer m*m [vt] + m [tau] + m*nb [work] call stdlib${ii}$_${ri}$gelqf( m, n, a, lda, work( itau ), work( nwork ),lwork - nwork + & 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! workspace: need m*m [vt] + m [tau] + n [work] ! workspace: prefer m*m [vt] + m [tau] + n*nb [work] call stdlib${ii}$_${ri}$orglq( n, n, m, vt, ldvt, work( itau ),work( nwork ), lwork - & nwork + 1_${ik}$, ierr ) ! produce l in a, zeroing out other entries if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'U', m-1, m-1, zero, zero, a( 1_${ik}$, 2_${ik}$ ), lda ) ie = itau itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! workspace: need m*m [vt] + 3*m [e, tauq, taup] + m [work] ! workspace: prefer m*m [vt] + 3*m [e, tauq, taup] + 2*m*nb [work] call stdlib${ii}$_${ri}$gebrd( m, m, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in work(ivt) ! workspace: need m*m [vt] + 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'U', 'I', m, s, work( ie ), u, ldu,work( ivt ), ldwkvt, & dum, idum,work( nwork ), iwork, info ) ! overwrite u by left singular vectors of l and work(ivt) ! by right singular vectors of l ! workspace: need m*m [vt] + 3*m [e, tauq, taup]+ m [work] ! workspace: prefer m*m [vt] + 3*m [e, tauq, taup]+ m*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, m, m, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', m, m, m, a, lda,work( itaup ), work( ivt ),& ldwkvt,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! multiply right singular vectors of l in work(ivt) by ! q in vt, storing result in a ! workspace: need m*m [vt] call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, n, m, one, work( ivt ), ldwkvt,vt, ldvt, zero,& a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_${ri}$lacpy( 'F', m, n, a, lda, vt, ldvt ) end if else ! n < mnthr ! path 5t (n > m, but not much larger) ! reduce to bidiagonal form without lq decomposition ie = 1_${ik}$ itauq = ie + m itaup = itauq + m nwork = itaup + m ! bidiagonalize a ! workspace: need 3*m [e, tauq, taup] + n [work] ! workspace: prefer 3*m [e, tauq, taup] + (m+n)*nb [work] call stdlib${ii}$_${ri}$gebrd( m, n, a, lda, s, work( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5tn (n > m, jobz='n') ! perform bidiagonal svd, only computing singular values ! workspace: need 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'L', 'N', m, s, work( ie ), dum, 1_${ik}$, dum, 1_${ik}$,dum, idum, & work( nwork ), iwork, info ) else if( wntqo ) then ! path 5to (n > m, jobz='o') ldwkvt = m ivt = nwork if( lwork >= m*n + 3_${ik}$*m + bdspac ) then ! work( ivt ) is m by n call stdlib${ii}$_${ri}$laset( 'F', m, n, zero, zero, work( ivt ),ldwkvt ) nwork = ivt + ldwkvt*n ! il is unused; silence compile warnings il = -1_${ik}$ else ! work( ivt ) is m by m nwork = ivt + ldwkvt*m il = nwork ! work(il) is m by chunk chunk = ( lwork - m*m - 3_${ik}$*m ) / m end if ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in work(ivt) ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + bdspac call stdlib${ii}$_${ri}$bdsdc( 'L', 'I', m, s, work( ie ), u, ldu,work( ivt ), ldwkvt, & dum, idum,work( nwork ), iwork, info ) ! overwrite u by left singular vectors of a ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*m [vt] + m*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) if( lwork >= m*n + 3_${ik}$*m + bdspac ) then ! path 5to-fast ! overwrite work(ivt) by left singular vectors of a ! workspace: need 3*m [e, tauq, taup] + m*n [vt] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*n [vt] + m*nb [work] call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', m, n, m, a, lda,work( itaup ), work( & ivt ), ldwkvt,work( nwork ), lwork - nwork + 1_${ik}$, ierr ) ! copy right singular vectors of a from work(ivt) to a call stdlib${ii}$_${ri}$lacpy( 'F', m, n, work( ivt ), ldwkvt, a, lda ) else ! path 5to-slow ! generate p**t in a ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*m [vt] + m*nb [work] call stdlib${ii}$_${ri}$orgbr( 'P', m, n, m, a, lda, work( itaup ),work( nwork ), & lwork - nwork + 1_${ik}$, ierr ) ! multiply q in a by right singular vectors of ! bidiagonal matrix in work(ivt), storing result in ! work(il) and copying to a ! workspace: need 3*m [e, tauq, taup] + m*m [vt] + m*nb [l] ! workspace: prefer 3*m [e, tauq, taup] + m*m [vt] + m*n [l] do i = 1, n, chunk blk = min( n - i + 1_${ik}$, chunk ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, blk, m, one, work( ivt ),ldwkvt, a( 1_${ik}$, & i ), lda, zero,work( il ), m ) call stdlib${ii}$_${ri}$lacpy( 'F', m, blk, work( il ), m, a( 1_${ik}$, i ),lda ) end do end if else if( wntqs ) then ! path 5ts (n > m, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_${ri}$laset( 'F', m, n, zero, zero, vt, ldvt ) call stdlib${ii}$_${ri}$bdsdc( 'L', 'I', m, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*m [e, tauq, taup] + m [work] ! workspace: prefer 3*m [e, tauq, taup] + m*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', m, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) else if( wntqa ) then ! path 5ta (n > m, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in u and computing right singular ! vectors of bidiagonal matrix in vt ! workspace: need 3*m [e, tauq, taup] + bdspac call stdlib${ii}$_${ri}$laset( 'F', n, n, zero, zero, vt, ldvt ) call stdlib${ii}$_${ri}$bdsdc( 'L', 'I', m, s, work( ie ), u, ldu, vt,ldvt, dum, idum, & work( nwork ), iwork,info ) ! set the right corner of vt to identity matrix if( n>m ) then call stdlib${ii}$_${ri}$laset( 'F', n-m, n-m, zero, one, vt(m+1,m+1),ldvt ) end if ! overwrite u by left singular vectors of a and vt ! by right singular vectors of a ! workspace: need 3*m [e, tauq, taup] + n [work] ! workspace: prefer 3*m [e, tauq, taup] + n*nb [work] call stdlib${ii}$_${ri}$ormbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) call stdlib${ii}$_${ri}$ormbr( 'P', 'R', 'T', n, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork - nwork + 1_${ik}$, ierr ) end if end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( anrm=n .and. ldvt=n .and. minmn>0_${ik}$ ) then ! there is no complex work space needed for bidiagonal svd ! the realwork space needed for bidiagonal svd (stdlib${ii}$_sbdsdc,KIND=sp) is ! bdspac = 3*n*n + 4*n for singular values and vectors; ! bdspac = 4*n for singular values only; ! not including e, ru, and rvt matrices. ! compute space preferred for each routine call stdlib${ii}$_cgebrd( m, n, cdum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_cgebrd_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cgebrd( n, n, cdum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_cgebrd_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cgeqrf( m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cgeqrf_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cungbr( 'P', n, n, n, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_cungbr_p_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cungbr( 'Q', m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_cungbr_q_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cungbr( 'Q', m, n, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_cungbr_q_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cungqr( m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_cungqr_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cungqr( m, n, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_cungqr_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', n, n, n, cdum(1_${ik}$), n, cdum(1_${ik}$),cdum(1_${ik}$), n, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_cunmbr_prc_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_cunmbr_qln_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, n, n, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_cunmbr_qln_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', n, n, n, cdum(1_${ik}$), n, cdum(1_${ik}$),cdum(1_${ik}$), n, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_cunmbr_qln_nn = int( cdum(1_${ik}$),KIND=${ik}$) if( m>=mnthr1 ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') maxwrk = n + lwork_cgeqrf_mn maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cgebrd_nn ) minwrk = 3_${ik}$*n else if( wntqo ) then ! path 2 (m >> n, jobz='o') wrkbl = n + lwork_cgeqrf_mn wrkbl = max( wrkbl, n + lwork_cungqr_mn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_cgebrd_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_cunmbr_qln_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_cunmbr_prc_nn ) maxwrk = m*n + n*n + wrkbl minwrk = 2_${ik}$*n*n + 3_${ik}$*n else if( wntqs ) then ! path 3 (m >> n, jobz='s') wrkbl = n + lwork_cgeqrf_mn wrkbl = max( wrkbl, n + lwork_cungqr_mn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_cgebrd_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_cunmbr_qln_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_cunmbr_prc_nn ) maxwrk = n*n + wrkbl minwrk = n*n + 3_${ik}$*n else if( wntqa ) then ! path 4 (m >> n, jobz='a') wrkbl = n + lwork_cgeqrf_mn wrkbl = max( wrkbl, n + lwork_cungqr_mm ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_cgebrd_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_cunmbr_qln_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_cunmbr_prc_nn ) maxwrk = n*n + wrkbl minwrk = n*n + max( 3_${ik}$*n, n + m ) end if else if( m>=mnthr2 ) then ! path 5 (m >> n, but not as much as mnthr1) maxwrk = 2_${ik}$*n + lwork_cgebrd_mn minwrk = 2_${ik}$*n + m if( wntqo ) then ! path 5o (m >> n, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cungbr_p_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cungbr_q_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + n*n else if( wntqs ) then ! path 5s (m >> n, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cungbr_p_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cungbr_q_mn ) else if( wntqa ) then ! path 5a (m >> n, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cungbr_p_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cungbr_q_mm ) end if else ! path 6 (m >= n, but not much larger) maxwrk = 2_${ik}$*n + lwork_cgebrd_mn minwrk = 2_${ik}$*n + m if( wntqo ) then ! path 6o (m >= n, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cunmbr_prc_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cunmbr_qln_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + n*n else if( wntqs ) then ! path 6s (m >= n, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cunmbr_qln_mn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cunmbr_prc_nn ) else if( wntqa ) then ! path 6a (m >= n, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_cunmbr_prc_nn ) end if end if else if( minmn>0_${ik}$ ) then ! there is no complex work space needed for bidiagonal svd ! the realwork space needed for bidiagonal svd (stdlib${ii}$_sbdsdc,KIND=sp) is ! bdspac = 3*m*m + 4*m for singular values and vectors; ! bdspac = 4*m for singular values only; ! not including e, ru, and rvt matrices. ! compute space preferred for each routine call stdlib${ii}$_cgebrd( m, n, cdum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_cgebrd_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cgebrd( m, m, cdum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_cgebrd_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cgelqf( m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_cgelqf_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cungbr( 'P', m, n, m, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_cungbr_p_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cungbr( 'P', n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_cungbr_p_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cungbr( 'Q', m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_cungbr_q_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cunglq( m, n, m, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_cunglq_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cunglq( n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_cunglq_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', m, m, m, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_cunmbr_prc_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', m, n, m, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_cunmbr_prc_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$),cdum(1_${ik}$), n, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_cunmbr_prc_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, m, m, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_cunmbr_qln_mm = int( cdum(1_${ik}$),KIND=${ik}$) if( n>=mnthr1 ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') maxwrk = m + lwork_cgelqf_mn maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cgebrd_mm ) minwrk = 3_${ik}$*m else if( wntqo ) then ! path 2t (n >> m, jobz='o') wrkbl = m + lwork_cgelqf_mn wrkbl = max( wrkbl, m + lwork_cunglq_mn ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_cgebrd_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_cunmbr_qln_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_cunmbr_prc_mm ) maxwrk = m*n + m*m + wrkbl minwrk = 2_${ik}$*m*m + 3_${ik}$*m else if( wntqs ) then ! path 3t (n >> m, jobz='s') wrkbl = m + lwork_cgelqf_mn wrkbl = max( wrkbl, m + lwork_cunglq_mn ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_cgebrd_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_cunmbr_qln_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_cunmbr_prc_mm ) maxwrk = m*m + wrkbl minwrk = m*m + 3_${ik}$*m else if( wntqa ) then ! path 4t (n >> m, jobz='a') wrkbl = m + lwork_cgelqf_mn wrkbl = max( wrkbl, m + lwork_cunglq_nn ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_cgebrd_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_cunmbr_qln_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_cunmbr_prc_mm ) maxwrk = m*m + wrkbl minwrk = m*m + max( 3_${ik}$*m, m + n ) end if else if( n>=mnthr2 ) then ! path 5t (n >> m, but not as much as mnthr1) maxwrk = 2_${ik}$*m + lwork_cgebrd_mn minwrk = 2_${ik}$*m + n if( wntqo ) then ! path 5to (n >> m, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cungbr_q_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cungbr_p_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + m*m else if( wntqs ) then ! path 5ts (n >> m, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cungbr_q_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cungbr_p_mn ) else if( wntqa ) then ! path 5ta (n >> m, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cungbr_q_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cungbr_p_nn ) end if else ! path 6t (n > m, but not much larger) maxwrk = 2_${ik}$*m + lwork_cgebrd_mn minwrk = 2_${ik}$*m + n if( wntqo ) then ! path 6to (n > m, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cunmbr_prc_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + m*m else if( wntqs ) then ! path 6ts (n > m, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cunmbr_prc_mn ) else if( wntqa ) then ! path 6ta (n > m, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_cunmbr_prc_nn ) end if end if end if maxwrk = max( maxwrk, minwrk ) end if if( info==0_${ik}$ ) then work( 1_${ik}$ ) = stdlib${ii}$_sroundup_lwork( maxwrk ) if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr1 ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + n ! compute a=q*r ! cworkspace: need n [tau] + n [work] ! cworkspace: prefer n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! zero out below r if (n>1_${ik}$) call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_cgebrd( n, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) nrwork = ie + n ! perform bidiagonal svd, compute singular values only ! cworkspace: need 0 ! rworkspace: need n [e] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'N', n, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then ! path 2 (m >> n, jobz='o') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt iu = 1_${ik}$ ! work(iu) is n by n ldwrku = n ir = iu + ldwrku*n if( lwork >= m*n + n*n + 3_${ik}$*n ) then ! work(ir) is m by n ldwrkr = m else ldwrkr = ( lwork - n*n - 3_${ik}$*n ) / n end if itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! cworkspace: need n*n [u] + n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy r to work( ir ), zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero, work( ir+1 ),ldwrkr ) ! generate q in a ! cworkspace: need n*n [u] + n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cungqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! cworkspace: need n*n [u] + n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_cgebrd( n, n, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of r in work(iru) and computing right singular vectors ! of r in work(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = ie + n irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=sp) to complex matrix work(iu) ! overwrite work(iu) by the left singular vectors of r ! cworkspace: need n*n [u] + n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', n, n, rwork( iru ), n, work( iu ),ldwrku ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iu ), ldwrku,work( nwork ), lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix vt ! overwrite vt by the right singular vectors of r ! cworkspace: need n*n [u] + n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork-nwork+1, ierr ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in work(ir) and copying to a ! cworkspace: need n*n [u] + n*n [r] ! cworkspace: prefer n*n [u] + m*n [r] ! rworkspace: need 0 do i = 1, m, ldwrkr chunk = min( m-i+1, ldwrkr ) call stdlib${ii}$_cgemm( 'N', 'N', chunk, n, n, cone, a( i, 1_${ik}$ ),lda, work( iu ), & ldwrku, czero,work( ir ), ldwrkr ) call stdlib${ii}$_clacpy( 'F', chunk, n, work( ir ), ldwrkr,a( i, 1_${ik}$ ), lda ) end do else if( wntqs ) then ! path 3 (m >> n, jobz='s') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt ir = 1_${ik}$ ! work(ir) is n by n ldwrkr = n itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! cworkspace: need n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_clacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero, work( ir+1 ),ldwrkr ) ! generate q in a ! cworkspace: need n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cungqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! cworkspace: need n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [r] + 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_cgebrd( n, n, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = ie + n irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=sp) to complex matrix u ! overwrite u by left singular vectors of r ! cworkspace: need n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', n, n, rwork( iru ), n, u, ldu ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & u, ldu, work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix vt ! overwrite vt by right singular vectors of r ! cworkspace: need n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork-nwork+1, ierr ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! cworkspace: need n*n [r] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'F', n, n, u, ldu, work( ir ), ldwrkr ) call stdlib${ii}$_cgemm( 'N', 'N', m, n, n, cone, a, lda, work( ir ),ldwrkr, czero, & u, ldu ) else if( wntqa ) then ! path 4 (m >> n, jobz='a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt iu = 1_${ik}$ ! work(iu) is n by n ldwrku = n itau = iu + ldwrku*n nwork = itau + n ! compute a=q*r, copying result to u ! cworkspace: need n*n [u] + n [tau] + n [work] ! cworkspace: prefer n*n [u] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! cworkspace: need n*n [u] + n [tau] + m [work] ! cworkspace: prefer n*n [u] + n [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cungqr( m, m, n, u, ldu, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ! produce r in a, zeroing out below it if (n>1_${ik}$) call stdlib${ii}$_claset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) ie = 1_${ik}$ itauq = itau itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! cworkspace: need n*n [u] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_cgebrd( n, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) iru = ie + n irvt = iru + n*n nrwork = irvt + n*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=sp) to complex matrix work(iu) ! overwrite work(iu) by left singular vectors of r ! cworkspace: need n*n [u] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', n, n, rwork( iru ), n, work( iu ),ldwrku ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', n, n, n, a, lda,work( itauq ), work( iu ), & ldwrku,work( nwork ), lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix vt ! overwrite vt by right singular vectors of r ! cworkspace: need n*n [u] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! cworkspace: need n*n [u] ! rworkspace: need 0 call stdlib${ii}$_cgemm( 'N', 'N', m, n, n, cone, u, ldu, work( iu ),ldwrku, czero, & a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_clacpy( 'F', m, n, a, lda, u, ldu ) end if else if( m>=mnthr2 ) then ! mnthr2 <= m < mnthr1 ! path 5 (m >> n, but not as much as mnthr1) ! reduce to bidiagonal form without qr decomposition, use ! stdlib${ii}$_cungbr and matrix multiplication to compute singular vectors ie = 1_${ik}$ nrwork = ie + n itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ! bidiagonalize a ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + (m+n)*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5n (m >> n, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need n [e] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'N', n, s, rwork( ie ), dum, 1_${ik}$,dum,1_${ik}$,dum, idum, & rwork( nrwork ), iwork, info ) else if( wntqo ) then iu = nwork iru = nrwork irvt = iru + n*n nrwork = irvt + n*n ! path 5o (m >> n, jobz='o') ! copy a to vt, generate p**h ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_cungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! generate q in a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cungbr( 'Q', m, n, n, a, lda, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) if( lwork >= m*n + 3_${ik}$*n ) then ! work( iu ) is m by n ldwrku = m else ! work(iu) is ldwrku by n ldwrku = ( lwork - 3_${ik}$*n ) / n end if nwork = iu + ldwrku*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! multiply realmatrix rwork(irvt,KIND=sp) by p**h in vt, ! storing the result in work(iu), copying to vt ! cworkspace: need 2*n [tauq, taup] + n*n [u] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + 2*n*n [rwork] call stdlib${ii}$_clarcm( n, n, rwork( irvt ), n, vt, ldvt,work( iu ), ldwrku, & rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', n, n, work( iu ), ldwrku, vt, ldvt ) ! multiply q in a by realmatrix rwork(iru,KIND=sp), storing the ! result in work(iu), copying to a ! cworkspace: need 2*n [tauq, taup] + n*n [u] ! cworkspace: prefer 2*n [tauq, taup] + m*n [u] ! rworkspace: need n [e] + n*n [ru] + 2*n*n [rwork] ! rworkspace: prefer n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_clacrm( chunk, n, a( i, 1_${ik}$ ), lda, rwork( iru ),n, work( iu ), & ldwrku, rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else if( wntqs ) then ! path 5s (m >> n, jobz='s') ! copy a to vt, generate p**h ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_cungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! copy a to u, generate q ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) call stdlib${ii}$_cungbr( 'Q', m, n, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! multiply realmatrix rwork(irvt,KIND=sp) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + 2*n*n [rwork] call stdlib${ii}$_clarcm( n, n, rwork( irvt ), n, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', n, n, a, lda, vt, ldvt ) ! multiply q in u by realmatrix rwork(iru,KIND=sp), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt call stdlib${ii}$_clacrm( m, n, u, ldu, rwork( iru ), n, a, lda,rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', m, n, a, lda, u, ldu ) else ! path 5a (m >> n, jobz='a') ! copy a to vt, generate p**h ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_cungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! copy a to u, generate q ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'L', m, n, a, lda, u, ldu ) call stdlib${ii}$_cungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! multiply realmatrix rwork(irvt,KIND=sp) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + 2*n*n [rwork] call stdlib${ii}$_clarcm( n, n, rwork( irvt ), n, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', n, n, a, lda, vt, ldvt ) ! multiply q in u by realmatrix rwork(iru,KIND=sp), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt call stdlib${ii}$_clacrm( m, n, u, ldu, rwork( iru ), n, a, lda,rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', m, n, a, lda, u, ldu ) end if else ! m < mnthr2 ! path 6 (m >= n, but not much larger) ! reduce to bidiagonal form without qr decomposition ! use stdlib_cunmbr to compute singular vectors ie = 1_${ik}$ nrwork = ie + n itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ! bidiagonalize a ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + (m+n)*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 6n (m >= n, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need n [e] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'N', n, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then iu = nwork iru = nrwork irvt = iru + n*n nrwork = irvt + n*n if( lwork >= m*n + 3_${ik}$*n ) then ! work( iu ) is m by n ldwrku = m else ! work( iu ) is ldwrku by n ldwrku = ( lwork - 3_${ik}$*n ) / n end if nwork = iu + ldwrku*n ! path 6o (m >= n, jobz='o') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n*n [u] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*n [u] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_clacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) if( lwork >= m*n + 3_${ik}$*n ) then ! path 6o-fast ! copy realmatrix rwork(iru,KIND=sp) to complex matrix work(iu) ! overwrite work(iu) by left singular vectors of a, copying ! to a ! cworkspace: need 2*n [tauq, taup] + m*n [u] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + m*n [u] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] call stdlib${ii}$_claset( 'F', m, n, czero, czero, work( iu ),ldwrku ) call stdlib${ii}$_clacp2( 'F', n, n, rwork( iru ), n, work( iu ),ldwrku ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), work( iu & ), ldwrku,work( nwork ), lwork-nwork+1, ierr ) call stdlib${ii}$_clacpy( 'F', m, n, work( iu ), ldwrku, a, lda ) else ! path 6o-slow ! generate q in a ! cworkspace: need 2*n [tauq, taup] + n*n [u] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*n [u] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cungbr( 'Q', m, n, n, a, lda, work( itauq ),work( nwork ), & lwork-nwork+1, ierr ) ! multiply q in a by realmatrix rwork(iru,KIND=sp), storing the ! result in work(iu), copying to a ! cworkspace: need 2*n [tauq, taup] + n*n [u] ! cworkspace: prefer 2*n [tauq, taup] + m*n [u] ! rworkspace: need n [e] + n*n [ru] + 2*n*n [rwork] ! rworkspace: prefer n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_clacrm( chunk, n, a( i, 1_${ik}$ ), lda,rwork( iru ), n, work( iu )& , ldwrku,rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do end if else if( wntqs ) then ! path 6s (m >= n, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=sp) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_claset( 'F', m, n, czero, czero, u, ldu ) call stdlib${ii}$_clacp2( 'F', n, n, rwork( iru ), n, u, ldu ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_clacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) else ! path 6a (m >= n, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_sbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! set the right corner of u to identity matrix call stdlib${ii}$_claset( 'F', m, m, czero, czero, u, ldu ) if( m>n ) then call stdlib${ii}$_claset( 'F', m-n, m-n, czero, cone,u( n+1, n+1 ), ldu ) end if ! copy realmatrix rwork(iru,KIND=sp) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + m*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_clacp2( 'F', n, n, rwork( iru ), n, u, ldu ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_clacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr1 ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + m ! compute a=l*q ! cworkspace: need m [tau] + m [work] ! cworkspace: prefer m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero, a( 1_${ik}$, 2_${ik}$ ),lda ) ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_cgebrd( m, m, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) nrwork = ie + m ! perform bidiagonal svd, compute singular values only ! cworkspace: need 0 ! rworkspace: need m [e] + bdspac call stdlib${ii}$_sbdsdc( 'U', 'N', m, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then ! path 2t (n >> m, jobz='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ldwkvt = m ! work(ivt) is m by m il = ivt + ldwkvt*m if( lwork >= m*n + m*m + 3_${ik}$*m ) then ! work(il) m by n ldwrkl = m chunk = n else ! work(il) is m by chunk ldwrkl = m chunk = ( lwork - m*m - 3_${ik}$*m ) / m end if itau = il + ldwrkl*chunk nwork = itau + m ! compute a=l*q ! cworkspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy l to work(il), zeroing about above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,work( il+ldwrkl ), ldwrkl ) ! generate q in a ! cworkspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cunglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il) ! cworkspace: need m*m [vt] + m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_cgebrd( m, m, work( il ), ldwrkl, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [ru] + m*m [rvt] + bdspac iru = ie + m irvt = iru + m*m nrwork = irvt + m*m call stdlib${ii}$_sbdsdc( 'U', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=sp) to complex matrix work(iu) ! overwrite work(iu) by the left singular vectors of l ! cworkspace: need m*m [vt] + m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix work(ivt) ! overwrite work(ivt) by the right singular vectors of l ! cworkspace: need m*m [vt] + m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', m, m, rwork( irvt ), m, work( ivt ),ldwkvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', m, m, m, work( il ), ldwrkl,work( itaup ), & work( ivt ), ldwkvt,work( nwork ), lwork-nwork+1, ierr ) ! multiply right singular vectors of l in work(il) by q ! in a, storing result in work(il) and copying to a ! cworkspace: need m*m [vt] + m*m [l] ! cworkspace: prefer m*m [vt] + m*n [l] ! rworkspace: need 0 do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_cgemm( 'N', 'N', m, blk, m, cone, work( ivt ), m,a( 1_${ik}$, i ), & lda, czero, work( il ),ldwrkl ) call stdlib${ii}$_clacpy( 'F', m, blk, work( il ), ldwrkl,a( 1_${ik}$, i ), lda ) end do else if( wntqs ) then ! path 3t (n >> m, jobz='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u il = 1_${ik}$ ! work(il) is m by m ldwrkl = m itau = il + ldwrkl*m nwork = itau + m ! compute a=l*q ! cworkspace: need m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy l to work(il), zeroing out above it call stdlib${ii}$_clacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero,work( il+ldwrkl ), ldwrkl ) ! generate q in a ! cworkspace: need m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cunglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il) ! cworkspace: need m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [l] + 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_cgebrd( m, m, work( il ), ldwrkl, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [ru] + m*m [rvt] + bdspac iru = ie + m irvt = iru + m*m nrwork = irvt + m*m call stdlib${ii}$_sbdsdc( 'U', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=sp) to complex matrix u ! overwrite u by left singular vectors of l ! cworkspace: need m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix vt ! overwrite vt by left singular vectors of l ! cworkspace: need m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', m, m, rwork( irvt ), m, vt, ldvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', m, m, m, work( il ), ldwrkl,work( itaup ), & vt, ldvt, work( nwork ),lwork-nwork+1, ierr ) ! copy vt to work(il), multiply right singular vectors of l ! in work(il) by q in a, storing result in vt ! cworkspace: need m*m [l] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'F', m, m, vt, ldvt, work( il ), ldwrkl ) call stdlib${ii}$_cgemm( 'N', 'N', m, n, m, cone, work( il ), ldwrkl,a, lda, czero, & vt, ldvt ) else if( wntqa ) then ! path 4t (n >> m, jobz='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ! work(ivt) is m by m ldwkvt = m itau = ivt + ldwkvt*m nwork = itau + m ! compute a=l*q, copying result to vt ! cworkspace: need m*m [vt] + m [tau] + m [work] ! cworkspace: prefer m*m [vt] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! cworkspace: need m*m [vt] + m [tau] + n [work] ! cworkspace: prefer m*m [vt] + m [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cunglq( n, n, m, vt, ldvt, work( itau ),work( nwork ), lwork-& nwork+1, ierr ) ! produce l in a, zeroing out above it if (m>1_${ik}$) call stdlib${ii}$_claset( 'U', m-1, m-1, czero, czero, a( 1_${ik}$, 2_${ik}$ ),lda ) ie = 1_${ik}$ itauq = itau itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! cworkspace: need m*m [vt] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_cgebrd( m, m, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [ru] + m*m [rvt] + bdspac iru = ie + m irvt = iru + m*m nrwork = irvt + m*m call stdlib${ii}$_sbdsdc( 'U', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=sp) to complex matrix u ! overwrite u by left singular vectors of l ! cworkspace: need m*m [vt] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, m, m, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix work(ivt) ! overwrite work(ivt) by right singular vectors of l ! cworkspace: need m*m [vt] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacp2( 'F', m, m, rwork( irvt ), m, work( ivt ),ldwkvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', m, m, m, a, lda,work( itaup ), work( ivt ),& ldwkvt,work( nwork ), lwork-nwork+1, ierr ) ! multiply right singular vectors of l in work(ivt) by ! q in vt, storing result in a ! cworkspace: need m*m [vt] ! rworkspace: need 0 call stdlib${ii}$_cgemm( 'N', 'N', m, n, m, cone, work( ivt ), ldwkvt,vt, ldvt, & czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_clacpy( 'F', m, n, a, lda, vt, ldvt ) end if else if( n>=mnthr2 ) then ! mnthr2 <= n < mnthr1 ! path 5t (n >> m, but not as much as mnthr1) ! reduce to bidiagonal form without qr decomposition, use ! stdlib${ii}$_cungbr and matrix multiplication to compute singular vectors ie = 1_${ik}$ nrwork = ie + m itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ! bidiagonalize a ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + (m+n)*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5tn (n >> m, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need m [e] + bdspac call stdlib${ii}$_sbdsdc( 'L', 'N', m, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then irvt = nrwork iru = irvt + m*m nrwork = iru + m*m ivt = nwork ! path 5to (n >> m, jobz='o') ! copy a to u, generate q ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_cungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! generate p**h in a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cungbr( 'P', m, n, m, a, lda, work( itaup ),work( nwork ), lwork-& nwork+1, ierr ) ldwkvt = m if( lwork >= m*n + 3_${ik}$*m ) then ! work( ivt ) is m by n nwork = ivt + ldwkvt*n chunk = n else ! work( ivt ) is m by chunk chunk = ( lwork - 3_${ik}$*m ) / m nwork = ivt + ldwkvt*chunk end if ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac call stdlib${ii}$_sbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! multiply q in u by realmatrix rwork(irvt,KIND=sp) ! storing the result in work(ivt), copying to u ! cworkspace: need 2*m [tauq, taup] + m*m [vt] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + 2*m*m [rwork] call stdlib${ii}$_clacrm( m, m, u, ldu, rwork( iru ), m, work( ivt ),ldwkvt, rwork( & nrwork ) ) call stdlib${ii}$_clacpy( 'F', m, m, work( ivt ), ldwkvt, u, ldu ) ! multiply rwork(irvt) by p**h in a, storing the ! result in work(ivt), copying to a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] ! cworkspace: prefer 2*m [tauq, taup] + m*n [vt] ! rworkspace: need m [e] + m*m [rvt] + 2*m*m [rwork] ! rworkspace: prefer m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_clarcm( m, blk, rwork( irvt ), m, a( 1_${ik}$, i ), lda,work( ivt ), & ldwkvt, rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', m, blk, work( ivt ), ldwkvt,a( 1_${ik}$, i ), lda ) end do else if( wntqs ) then ! path 5ts (n >> m, jobz='s') ! copy a to u, generate q ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_cungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! copy a to vt, generate p**h ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) call stdlib${ii}$_cungbr( 'P', m, n, m, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_sbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! multiply q in u by realmatrix rwork(iru,KIND=sp), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + 2*m*m [rwork] call stdlib${ii}$_clacrm( m, m, u, ldu, rwork( iru ), m, a, lda,rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', m, m, a, lda, u, ldu ) ! multiply realmatrix rwork(irvt,KIND=sp) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru call stdlib${ii}$_clarcm( m, n, rwork( irvt ), m, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', m, n, a, lda, vt, ldvt ) else ! path 5ta (n >> m, jobz='a') ! copy a to u, generate q ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_cungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! copy a to vt, generate p**h ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_clacpy( 'U', m, n, a, lda, vt, ldvt ) call stdlib${ii}$_cungbr( 'P', n, n, m, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_sbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! multiply q in u by realmatrix rwork(iru,KIND=sp), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + 2*m*m [rwork] call stdlib${ii}$_clacrm( m, m, u, ldu, rwork( iru ), m, a, lda,rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', m, m, a, lda, u, ldu ) ! multiply realmatrix rwork(irvt,KIND=sp) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru call stdlib${ii}$_clarcm( m, n, rwork( irvt ), m, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', m, n, a, lda, vt, ldvt ) end if else ! n < mnthr2 ! path 6t (n > m, but not much larger) ! reduce to bidiagonal form without lq decomposition ! use stdlib_cunmbr to compute singular vectors ie = 1_${ik}$ nrwork = ie + m itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ! bidiagonalize a ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + (m+n)*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 6tn (n > m, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need m [e] + bdspac call stdlib${ii}$_sbdsdc( 'L', 'N', m, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then ! path 6to (n > m, jobz='o') ldwkvt = m ivt = nwork if( lwork >= m*n + 3_${ik}$*m ) then ! work( ivt ) is m by n call stdlib${ii}$_claset( 'F', m, n, czero, czero, work( ivt ),ldwkvt ) nwork = ivt + ldwkvt*n else ! work( ivt ) is m by chunk chunk = ( lwork - 3_${ik}$*m ) / m nwork = ivt + ldwkvt*chunk end if ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_sbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=sp) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*m [vt] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] call stdlib${ii}$_clacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) if( lwork >= m*n + 3_${ik}$*m ) then ! path 6to-fast ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix work(ivt) ! overwrite work(ivt) by right singular vectors of a, ! copying to a ! cworkspace: need 2*m [tauq, taup] + m*n [vt] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*n [vt] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] call stdlib${ii}$_clacp2( 'F', m, m, rwork( irvt ), m, work( ivt ),ldwkvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', m, n, m, a, lda,work( itaup ), work( & ivt ), ldwkvt,work( nwork ), lwork-nwork+1, ierr ) call stdlib${ii}$_clacpy( 'F', m, n, work( ivt ), ldwkvt, a, lda ) else ! path 6to-slow ! generate p**h in a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*m [vt] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_cungbr( 'P', m, n, m, a, lda, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! multiply q in a by realmatrix rwork(iru,KIND=sp), storing the ! result in work(iu), copying to a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] ! cworkspace: prefer 2*m [tauq, taup] + m*n [vt] ! rworkspace: need m [e] + m*m [rvt] + 2*m*m [rwork] ! rworkspace: prefer m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_clarcm( m, blk, rwork( irvt ), m, a( 1_${ik}$, i ),lda, work( ivt )& , ldwkvt,rwork( nrwork ) ) call stdlib${ii}$_clacpy( 'F', m, blk, work( ivt ), ldwkvt,a( 1_${ik}$, i ), lda ) end do end if else if( wntqs ) then ! path 6ts (n > m, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_sbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=sp) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] call stdlib${ii}$_clacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] call stdlib${ii}$_claset( 'F', m, n, czero, czero, vt, ldvt ) call stdlib${ii}$_clacp2( 'F', m, m, rwork( irvt ), m, vt, ldvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', m, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) else ! path 6ta (n > m, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_sbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=sp) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] call stdlib${ii}$_clacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_cunmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! set all of vt to identity matrix call stdlib${ii}$_claset( 'F', n, n, czero, cone, vt, ldvt ) ! copy realmatrix rwork(irvt,KIND=sp) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + n*nb [work] ! rworkspace: need m [e] + m*m [rvt] call stdlib${ii}$_clacp2( 'F', m, m, rwork( irvt ), m, vt, ldvt ) call stdlib${ii}$_cunmbr( 'P', 'R', 'C', n, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) end if end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( info/=0_${ik}$ .and. anrm>bignum )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn-1,& 1_${ik}$,rwork( ie ), minmn, ierr ) if( anrm=n .and. ldvt=n .and. minmn>0_${ik}$ ) then ! there is no complex work space needed for bidiagonal svd ! the realwork space needed for bidiagonal svd (stdlib${ii}$_dbdsdc,KIND=dp) is ! bdspac = 3*n*n + 4*n for singular values and vectors; ! bdspac = 4*n for singular values only; ! not including e, ru, and rvt matrices. ! compute space preferred for each routine call stdlib${ii}$_zgebrd( m, n, cdum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_zgebrd_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zgebrd( n, n, cdum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_zgebrd_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zgeqrf( m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zgeqrf_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zungbr( 'P', n, n, n, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_zungbr_p_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zungbr( 'Q', m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_zungbr_q_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zungbr( 'Q', m, n, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_zungbr_q_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zungqr( m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_zungqr_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zungqr( m, n, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_zungqr_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', n, n, n, cdum(1_${ik}$), n, cdum(1_${ik}$),cdum(1_${ik}$), n, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_zunmbr_prc_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_zunmbr_qln_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, n, n, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_zunmbr_qln_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', n, n, n, cdum(1_${ik}$), n, cdum(1_${ik}$),cdum(1_${ik}$), n, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_zunmbr_qln_nn = int( cdum(1_${ik}$),KIND=${ik}$) if( m>=mnthr1 ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') maxwrk = n + lwork_zgeqrf_mn maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zgebrd_nn ) minwrk = 3_${ik}$*n else if( wntqo ) then ! path 2 (m >> n, jobz='o') wrkbl = n + lwork_zgeqrf_mn wrkbl = max( wrkbl, n + lwork_zungqr_mn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_zgebrd_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_zunmbr_qln_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_zunmbr_prc_nn ) maxwrk = m*n + n*n + wrkbl minwrk = 2_${ik}$*n*n + 3_${ik}$*n else if( wntqs ) then ! path 3 (m >> n, jobz='s') wrkbl = n + lwork_zgeqrf_mn wrkbl = max( wrkbl, n + lwork_zungqr_mn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_zgebrd_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_zunmbr_qln_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_zunmbr_prc_nn ) maxwrk = n*n + wrkbl minwrk = n*n + 3_${ik}$*n else if( wntqa ) then ! path 4 (m >> n, jobz='a') wrkbl = n + lwork_zgeqrf_mn wrkbl = max( wrkbl, n + lwork_zungqr_mm ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_zgebrd_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_zunmbr_qln_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_zunmbr_prc_nn ) maxwrk = n*n + wrkbl minwrk = n*n + max( 3_${ik}$*n, n + m ) end if else if( m>=mnthr2 ) then ! path 5 (m >> n, but not as much as mnthr1) maxwrk = 2_${ik}$*n + lwork_zgebrd_mn minwrk = 2_${ik}$*n + m if( wntqo ) then ! path 5o (m >> n, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zungbr_p_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zungbr_q_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + n*n else if( wntqs ) then ! path 5s (m >> n, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zungbr_p_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zungbr_q_mn ) else if( wntqa ) then ! path 5a (m >> n, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zungbr_p_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zungbr_q_mm ) end if else ! path 6 (m >= n, but not much larger) maxwrk = 2_${ik}$*n + lwork_zgebrd_mn minwrk = 2_${ik}$*n + m if( wntqo ) then ! path 6o (m >= n, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zunmbr_prc_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zunmbr_qln_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + n*n else if( wntqs ) then ! path 6s (m >= n, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zunmbr_qln_mn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zunmbr_prc_nn ) else if( wntqa ) then ! path 6a (m >= n, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_zunmbr_prc_nn ) end if end if else if( minmn>0_${ik}$ ) then ! there is no complex work space needed for bidiagonal svd ! the realwork space needed for bidiagonal svd (stdlib${ii}$_dbdsdc,KIND=dp) is ! bdspac = 3*m*m + 4*m for singular values and vectors; ! bdspac = 4*m for singular values only; ! not including e, ru, and rvt matrices. ! compute space preferred for each routine call stdlib${ii}$_zgebrd( m, n, cdum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_zgebrd_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zgebrd( m, m, cdum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_zgebrd_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zgelqf( m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_zgelqf_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zungbr( 'P', m, n, m, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_zungbr_p_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zungbr( 'P', n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_zungbr_p_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zungbr( 'Q', m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_zungbr_q_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zunglq( m, n, m, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_zunglq_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zunglq( n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_zunglq_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', m, m, m, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_zunmbr_prc_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', m, n, m, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_zunmbr_prc_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$),cdum(1_${ik}$), n, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_zunmbr_prc_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, m, m, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_zunmbr_qln_mm = int( cdum(1_${ik}$),KIND=${ik}$) if( n>=mnthr1 ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') maxwrk = m + lwork_zgelqf_mn maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zgebrd_mm ) minwrk = 3_${ik}$*m else if( wntqo ) then ! path 2t (n >> m, jobz='o') wrkbl = m + lwork_zgelqf_mn wrkbl = max( wrkbl, m + lwork_zunglq_mn ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_zgebrd_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_zunmbr_qln_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_zunmbr_prc_mm ) maxwrk = m*n + m*m + wrkbl minwrk = 2_${ik}$*m*m + 3_${ik}$*m else if( wntqs ) then ! path 3t (n >> m, jobz='s') wrkbl = m + lwork_zgelqf_mn wrkbl = max( wrkbl, m + lwork_zunglq_mn ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_zgebrd_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_zunmbr_qln_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_zunmbr_prc_mm ) maxwrk = m*m + wrkbl minwrk = m*m + 3_${ik}$*m else if( wntqa ) then ! path 4t (n >> m, jobz='a') wrkbl = m + lwork_zgelqf_mn wrkbl = max( wrkbl, m + lwork_zunglq_nn ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_zgebrd_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_zunmbr_qln_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_zunmbr_prc_mm ) maxwrk = m*m + wrkbl minwrk = m*m + max( 3_${ik}$*m, m + n ) end if else if( n>=mnthr2 ) then ! path 5t (n >> m, but not as much as mnthr1) maxwrk = 2_${ik}$*m + lwork_zgebrd_mn minwrk = 2_${ik}$*m + n if( wntqo ) then ! path 5to (n >> m, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zungbr_q_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zungbr_p_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + m*m else if( wntqs ) then ! path 5ts (n >> m, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zungbr_q_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zungbr_p_mn ) else if( wntqa ) then ! path 5ta (n >> m, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zungbr_q_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zungbr_p_nn ) end if else ! path 6t (n > m, but not much larger) maxwrk = 2_${ik}$*m + lwork_zgebrd_mn minwrk = 2_${ik}$*m + n if( wntqo ) then ! path 6to (n > m, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zunmbr_prc_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + m*m else if( wntqs ) then ! path 6ts (n > m, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zunmbr_prc_mn ) else if( wntqa ) then ! path 6ta (n > m, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_zunmbr_prc_nn ) end if end if end if maxwrk = max( maxwrk, minwrk ) end if if( info==0_${ik}$ ) then work( 1_${ik}$ ) = stdlib${ii}$_droundup_lwork( maxwrk ) if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr1 ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + n ! compute a=q*r ! cworkspace: need n [tau] + n [work] ! cworkspace: prefer n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! zero out below r if (n>1_${ik}$) call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_zgebrd( n, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) nrwork = ie + n ! perform bidiagonal svd, compute singular values only ! cworkspace: need 0 ! rworkspace: need n [e] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'N', n, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then ! path 2 (m >> n, jobz='o') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt iu = 1_${ik}$ ! work(iu) is n by n ldwrku = n ir = iu + ldwrku*n if( lwork >= m*n + n*n + 3_${ik}$*n ) then ! work(ir) is m by n ldwrkr = m else ldwrkr = ( lwork - n*n - 3_${ik}$*n ) / n end if itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! cworkspace: need n*n [u] + n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy r to work( ir ), zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero, work( ir+1 ),ldwrkr ) ! generate q in a ! cworkspace: need n*n [u] + n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zungqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! cworkspace: need n*n [u] + n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_zgebrd( n, n, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of r in work(iru) and computing right singular vectors ! of r in work(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = ie + n irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=dp) to complex matrix work(iu) ! overwrite work(iu) by the left singular vectors of r ! cworkspace: need n*n [u] + n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', n, n, rwork( iru ), n, work( iu ),ldwrku ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iu ), ldwrku,work( nwork ), lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix vt ! overwrite vt by the right singular vectors of r ! cworkspace: need n*n [u] + n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork-nwork+1, ierr ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in work(ir) and copying to a ! cworkspace: need n*n [u] + n*n [r] ! cworkspace: prefer n*n [u] + m*n [r] ! rworkspace: need 0 do i = 1, m, ldwrkr chunk = min( m-i+1, ldwrkr ) call stdlib${ii}$_zgemm( 'N', 'N', chunk, n, n, cone, a( i, 1_${ik}$ ),lda, work( iu ), & ldwrku, czero,work( ir ), ldwrkr ) call stdlib${ii}$_zlacpy( 'F', chunk, n, work( ir ), ldwrkr,a( i, 1_${ik}$ ), lda ) end do else if( wntqs ) then ! path 3 (m >> n, jobz='s') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt ir = 1_${ik}$ ! work(ir) is n by n ldwrkr = n itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! cworkspace: need n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero, work( ir+1 ),ldwrkr ) ! generate q in a ! cworkspace: need n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zungqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! cworkspace: need n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [r] + 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_zgebrd( n, n, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = ie + n irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=dp) to complex matrix u ! overwrite u by left singular vectors of r ! cworkspace: need n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', n, n, rwork( iru ), n, u, ldu ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & u, ldu, work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix vt ! overwrite vt by right singular vectors of r ! cworkspace: need n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork-nwork+1, ierr ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! cworkspace: need n*n [r] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'F', n, n, u, ldu, work( ir ), ldwrkr ) call stdlib${ii}$_zgemm( 'N', 'N', m, n, n, cone, a, lda, work( ir ),ldwrkr, czero, & u, ldu ) else if( wntqa ) then ! path 4 (m >> n, jobz='a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt iu = 1_${ik}$ ! work(iu) is n by n ldwrku = n itau = iu + ldwrku*n nwork = itau + n ! compute a=q*r, copying result to u ! cworkspace: need n*n [u] + n [tau] + n [work] ! cworkspace: prefer n*n [u] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zgeqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! cworkspace: need n*n [u] + n [tau] + m [work] ! cworkspace: prefer n*n [u] + n [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zungqr( m, m, n, u, ldu, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ! produce r in a, zeroing out below it if (n>1_${ik}$) call stdlib${ii}$_zlaset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) ie = 1_${ik}$ itauq = itau itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! cworkspace: need n*n [u] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_zgebrd( n, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) iru = ie + n irvt = iru + n*n nrwork = irvt + n*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=dp) to complex matrix work(iu) ! overwrite work(iu) by left singular vectors of r ! cworkspace: need n*n [u] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', n, n, rwork( iru ), n, work( iu ),ldwrku ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', n, n, n, a, lda,work( itauq ), work( iu ), & ldwrku,work( nwork ), lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix vt ! overwrite vt by right singular vectors of r ! cworkspace: need n*n [u] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! cworkspace: need n*n [u] ! rworkspace: need 0 call stdlib${ii}$_zgemm( 'N', 'N', m, n, n, cone, u, ldu, work( iu ),ldwrku, czero, & a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, u, ldu ) end if else if( m>=mnthr2 ) then ! mnthr2 <= m < mnthr1 ! path 5 (m >> n, but not as much as mnthr1) ! reduce to bidiagonal form without qr decomposition, use ! stdlib${ii}$_zungbr and matrix multiplication to compute singular vectors ie = 1_${ik}$ nrwork = ie + n itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ! bidiagonalize a ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + (m+n)*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5n (m >> n, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need n [e] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'N', n, s, rwork( ie ), dum, 1_${ik}$,dum,1_${ik}$,dum, idum, & rwork( nrwork ), iwork, info ) else if( wntqo ) then iu = nwork iru = nrwork irvt = iru + n*n nrwork = irvt + n*n ! path 5o (m >> n, jobz='o') ! copy a to vt, generate p**h ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_zungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! generate q in a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zungbr( 'Q', m, n, n, a, lda, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) if( lwork >= m*n + 3_${ik}$*n ) then ! work( iu ) is m by n ldwrku = m else ! work(iu) is ldwrku by n ldwrku = ( lwork - 3_${ik}$*n ) / n end if nwork = iu + ldwrku*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! multiply realmatrix rwork(irvt,KIND=dp) by p**h in vt, ! storing the result in work(iu), copying to vt ! cworkspace: need 2*n [tauq, taup] + n*n [u] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + 2*n*n [rwork] call stdlib${ii}$_zlarcm( n, n, rwork( irvt ), n, vt, ldvt,work( iu ), ldwrku, & rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', n, n, work( iu ), ldwrku, vt, ldvt ) ! multiply q in a by realmatrix rwork(iru,KIND=dp), storing the ! result in work(iu), copying to a ! cworkspace: need 2*n [tauq, taup] + n*n [u] ! cworkspace: prefer 2*n [tauq, taup] + m*n [u] ! rworkspace: need n [e] + n*n [ru] + 2*n*n [rwork] ! rworkspace: prefer n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_zlacrm( chunk, n, a( i, 1_${ik}$ ), lda, rwork( iru ),n, work( iu ), & ldwrku, rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else if( wntqs ) then ! path 5s (m >> n, jobz='s') ! copy a to vt, generate p**h ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_zungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! copy a to u, generate q ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) call stdlib${ii}$_zungbr( 'Q', m, n, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! multiply realmatrix rwork(irvt,KIND=dp) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + 2*n*n [rwork] call stdlib${ii}$_zlarcm( n, n, rwork( irvt ), n, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', n, n, a, lda, vt, ldvt ) ! multiply q in u by realmatrix rwork(iru,KIND=dp), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt call stdlib${ii}$_zlacrm( m, n, u, ldu, rwork( iru ), n, a, lda,rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, u, ldu ) else ! path 5a (m >> n, jobz='a') ! copy a to vt, generate p**h ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_zungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! copy a to u, generate q ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'L', m, n, a, lda, u, ldu ) call stdlib${ii}$_zungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! multiply realmatrix rwork(irvt,KIND=dp) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + 2*n*n [rwork] call stdlib${ii}$_zlarcm( n, n, rwork( irvt ), n, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', n, n, a, lda, vt, ldvt ) ! multiply q in u by realmatrix rwork(iru,KIND=dp), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt call stdlib${ii}$_zlacrm( m, n, u, ldu, rwork( iru ), n, a, lda,rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, u, ldu ) end if else ! m < mnthr2 ! path 6 (m >= n, but not much larger) ! reduce to bidiagonal form without qr decomposition ! use stdlib_zunmbr to compute singular vectors ie = 1_${ik}$ nrwork = ie + n itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ! bidiagonalize a ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + (m+n)*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 6n (m >= n, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need n [e] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'N', n, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then iu = nwork iru = nrwork irvt = iru + n*n nrwork = irvt + n*n if( lwork >= m*n + 3_${ik}$*n ) then ! work( iu ) is m by n ldwrku = m else ! work( iu ) is ldwrku by n ldwrku = ( lwork - 3_${ik}$*n ) / n end if nwork = iu + ldwrku*n ! path 6o (m >= n, jobz='o') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n*n [u] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*n [u] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_zlacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) if( lwork >= m*n + 3_${ik}$*n ) then ! path 6o-fast ! copy realmatrix rwork(iru,KIND=dp) to complex matrix work(iu) ! overwrite work(iu) by left singular vectors of a, copying ! to a ! cworkspace: need 2*n [tauq, taup] + m*n [u] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + m*n [u] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] call stdlib${ii}$_zlaset( 'F', m, n, czero, czero, work( iu ),ldwrku ) call stdlib${ii}$_zlacp2( 'F', n, n, rwork( iru ), n, work( iu ),ldwrku ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), work( iu & ), ldwrku,work( nwork ), lwork-nwork+1, ierr ) call stdlib${ii}$_zlacpy( 'F', m, n, work( iu ), ldwrku, a, lda ) else ! path 6o-slow ! generate q in a ! cworkspace: need 2*n [tauq, taup] + n*n [u] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*n [u] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zungbr( 'Q', m, n, n, a, lda, work( itauq ),work( nwork ), & lwork-nwork+1, ierr ) ! multiply q in a by realmatrix rwork(iru,KIND=dp), storing the ! result in work(iu), copying to a ! cworkspace: need 2*n [tauq, taup] + n*n [u] ! cworkspace: prefer 2*n [tauq, taup] + m*n [u] ! rworkspace: need n [e] + n*n [ru] + 2*n*n [rwork] ! rworkspace: prefer n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_zlacrm( chunk, n, a( i, 1_${ik}$ ), lda,rwork( iru ), n, work( iu )& , ldwrku,rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do end if else if( wntqs ) then ! path 6s (m >= n, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=dp) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_zlaset( 'F', m, n, czero, czero, u, ldu ) call stdlib${ii}$_zlacp2( 'F', n, n, rwork( iru ), n, u, ldu ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_zlacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) else ! path 6a (m >= n, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_dbdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! set the right corner of u to identity matrix call stdlib${ii}$_zlaset( 'F', m, m, czero, czero, u, ldu ) if( m>n ) then call stdlib${ii}$_zlaset( 'F', m-n, m-n, czero, cone,u( n+1, n+1 ), ldu ) end if ! copy realmatrix rwork(iru,KIND=dp) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + m*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_zlacp2( 'F', n, n, rwork( iru ), n, u, ldu ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_zlacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr1 ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + m ! compute a=l*q ! cworkspace: need m [tau] + m [work] ! cworkspace: prefer m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero, a( 1_${ik}$, 2_${ik}$ ),lda ) ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_zgebrd( m, m, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) nrwork = ie + m ! perform bidiagonal svd, compute singular values only ! cworkspace: need 0 ! rworkspace: need m [e] + bdspac call stdlib${ii}$_dbdsdc( 'U', 'N', m, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then ! path 2t (n >> m, jobz='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ldwkvt = m ! work(ivt) is m by m il = ivt + ldwkvt*m if( lwork >= m*n + m*m + 3_${ik}$*m ) then ! work(il) m by n ldwrkl = m chunk = n else ! work(il) is m by chunk ldwrkl = m chunk = ( lwork - m*m - 3_${ik}$*m ) / m end if itau = il + ldwrkl*chunk nwork = itau + m ! compute a=l*q ! cworkspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy l to work(il), zeroing about above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,work( il+ldwrkl ), ldwrkl ) ! generate q in a ! cworkspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zunglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il) ! cworkspace: need m*m [vt] + m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_zgebrd( m, m, work( il ), ldwrkl, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [ru] + m*m [rvt] + bdspac iru = ie + m irvt = iru + m*m nrwork = irvt + m*m call stdlib${ii}$_dbdsdc( 'U', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=dp) to complex matrix work(iu) ! overwrite work(iu) by the left singular vectors of l ! cworkspace: need m*m [vt] + m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix work(ivt) ! overwrite work(ivt) by the right singular vectors of l ! cworkspace: need m*m [vt] + m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', m, m, rwork( irvt ), m, work( ivt ),ldwkvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', m, m, m, work( il ), ldwrkl,work( itaup ), & work( ivt ), ldwkvt,work( nwork ), lwork-nwork+1, ierr ) ! multiply right singular vectors of l in work(il) by q ! in a, storing result in work(il) and copying to a ! cworkspace: need m*m [vt] + m*m [l] ! cworkspace: prefer m*m [vt] + m*n [l] ! rworkspace: need 0 do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_zgemm( 'N', 'N', m, blk, m, cone, work( ivt ), m,a( 1_${ik}$, i ), & lda, czero, work( il ),ldwrkl ) call stdlib${ii}$_zlacpy( 'F', m, blk, work( il ), ldwrkl,a( 1_${ik}$, i ), lda ) end do else if( wntqs ) then ! path 3t (n >> m, jobz='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u il = 1_${ik}$ ! work(il) is m by m ldwrkl = m itau = il + ldwrkl*m nwork = itau + m ! compute a=l*q ! cworkspace: need m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy l to work(il), zeroing out above it call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero,work( il+ldwrkl ), ldwrkl ) ! generate q in a ! cworkspace: need m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zunglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il) ! cworkspace: need m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [l] + 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_zgebrd( m, m, work( il ), ldwrkl, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [ru] + m*m [rvt] + bdspac iru = ie + m irvt = iru + m*m nrwork = irvt + m*m call stdlib${ii}$_dbdsdc( 'U', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=dp) to complex matrix u ! overwrite u by left singular vectors of l ! cworkspace: need m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix vt ! overwrite vt by left singular vectors of l ! cworkspace: need m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', m, m, rwork( irvt ), m, vt, ldvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', m, m, m, work( il ), ldwrkl,work( itaup ), & vt, ldvt, work( nwork ),lwork-nwork+1, ierr ) ! copy vt to work(il), multiply right singular vectors of l ! in work(il) by q in a, storing result in vt ! cworkspace: need m*m [l] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'F', m, m, vt, ldvt, work( il ), ldwrkl ) call stdlib${ii}$_zgemm( 'N', 'N', m, n, m, cone, work( il ), ldwrkl,a, lda, czero, & vt, ldvt ) else if( wntqa ) then ! path 4t (n >> m, jobz='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ! work(ivt) is m by m ldwkvt = m itau = ivt + ldwkvt*m nwork = itau + m ! compute a=l*q, copying result to vt ! cworkspace: need m*m [vt] + m [tau] + m [work] ! cworkspace: prefer m*m [vt] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zgelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! cworkspace: need m*m [vt] + m [tau] + n [work] ! cworkspace: prefer m*m [vt] + m [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zunglq( n, n, m, vt, ldvt, work( itau ),work( nwork ), lwork-& nwork+1, ierr ) ! produce l in a, zeroing out above it if (m>1_${ik}$) call stdlib${ii}$_zlaset( 'U', m-1, m-1, czero, czero, a( 1_${ik}$, 2_${ik}$ ),lda ) ie = 1_${ik}$ itauq = itau itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! cworkspace: need m*m [vt] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_zgebrd( m, m, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [ru] + m*m [rvt] + bdspac iru = ie + m irvt = iru + m*m nrwork = irvt + m*m call stdlib${ii}$_dbdsdc( 'U', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=dp) to complex matrix u ! overwrite u by left singular vectors of l ! cworkspace: need m*m [vt] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, m, m, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix work(ivt) ! overwrite work(ivt) by right singular vectors of l ! cworkspace: need m*m [vt] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacp2( 'F', m, m, rwork( irvt ), m, work( ivt ),ldwkvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', m, m, m, a, lda,work( itaup ), work( ivt ),& ldwkvt,work( nwork ), lwork-nwork+1, ierr ) ! multiply right singular vectors of l in work(ivt) by ! q in vt, storing result in a ! cworkspace: need m*m [vt] ! rworkspace: need 0 call stdlib${ii}$_zgemm( 'N', 'N', m, n, m, cone, work( ivt ), ldwkvt,vt, ldvt, & czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, vt, ldvt ) end if else if( n>=mnthr2 ) then ! mnthr2 <= n < mnthr1 ! path 5t (n >> m, but not as much as mnthr1) ! reduce to bidiagonal form without qr decomposition, use ! stdlib${ii}$_zungbr and matrix multiplication to compute singular vectors ie = 1_${ik}$ nrwork = ie + m itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ! bidiagonalize a ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + (m+n)*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5tn (n >> m, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need m [e] + bdspac call stdlib${ii}$_dbdsdc( 'L', 'N', m, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then irvt = nrwork iru = irvt + m*m nrwork = iru + m*m ivt = nwork ! path 5to (n >> m, jobz='o') ! copy a to u, generate q ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_zungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! generate p**h in a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zungbr( 'P', m, n, m, a, lda, work( itaup ),work( nwork ), lwork-& nwork+1, ierr ) ldwkvt = m if( lwork >= m*n + 3_${ik}$*m ) then ! work( ivt ) is m by n nwork = ivt + ldwkvt*n chunk = n else ! work( ivt ) is m by chunk chunk = ( lwork - 3_${ik}$*m ) / m nwork = ivt + ldwkvt*chunk end if ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac call stdlib${ii}$_dbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! multiply q in u by realmatrix rwork(irvt,KIND=dp) ! storing the result in work(ivt), copying to u ! cworkspace: need 2*m [tauq, taup] + m*m [vt] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + 2*m*m [rwork] call stdlib${ii}$_zlacrm( m, m, u, ldu, rwork( iru ), m, work( ivt ),ldwkvt, rwork( & nrwork ) ) call stdlib${ii}$_zlacpy( 'F', m, m, work( ivt ), ldwkvt, u, ldu ) ! multiply rwork(irvt) by p**h in a, storing the ! result in work(ivt), copying to a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] ! cworkspace: prefer 2*m [tauq, taup] + m*n [vt] ! rworkspace: need m [e] + m*m [rvt] + 2*m*m [rwork] ! rworkspace: prefer m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_zlarcm( m, blk, rwork( irvt ), m, a( 1_${ik}$, i ), lda,work( ivt ), & ldwkvt, rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', m, blk, work( ivt ), ldwkvt,a( 1_${ik}$, i ), lda ) end do else if( wntqs ) then ! path 5ts (n >> m, jobz='s') ! copy a to u, generate q ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_zungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! copy a to vt, generate p**h ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) call stdlib${ii}$_zungbr( 'P', m, n, m, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_dbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! multiply q in u by realmatrix rwork(iru,KIND=dp), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + 2*m*m [rwork] call stdlib${ii}$_zlacrm( m, m, u, ldu, rwork( iru ), m, a, lda,rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', m, m, a, lda, u, ldu ) ! multiply realmatrix rwork(irvt,KIND=dp) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru call stdlib${ii}$_zlarcm( m, n, rwork( irvt ), m, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, vt, ldvt ) else ! path 5ta (n >> m, jobz='a') ! copy a to u, generate q ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_zungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! copy a to vt, generate p**h ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zlacpy( 'U', m, n, a, lda, vt, ldvt ) call stdlib${ii}$_zungbr( 'P', n, n, m, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_dbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! multiply q in u by realmatrix rwork(iru,KIND=dp), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + 2*m*m [rwork] call stdlib${ii}$_zlacrm( m, m, u, ldu, rwork( iru ), m, a, lda,rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', m, m, a, lda, u, ldu ) ! multiply realmatrix rwork(irvt,KIND=dp) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru call stdlib${ii}$_zlarcm( m, n, rwork( irvt ), m, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', m, n, a, lda, vt, ldvt ) end if else ! n < mnthr2 ! path 6t (n > m, but not much larger) ! reduce to bidiagonal form without lq decomposition ! use stdlib_zunmbr to compute singular vectors ie = 1_${ik}$ nrwork = ie + m itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ! bidiagonalize a ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + (m+n)*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 6tn (n > m, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need m [e] + bdspac call stdlib${ii}$_dbdsdc( 'L', 'N', m, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then ! path 6to (n > m, jobz='o') ldwkvt = m ivt = nwork if( lwork >= m*n + 3_${ik}$*m ) then ! work( ivt ) is m by n call stdlib${ii}$_zlaset( 'F', m, n, czero, czero, work( ivt ),ldwkvt ) nwork = ivt + ldwkvt*n else ! work( ivt ) is m by chunk chunk = ( lwork - 3_${ik}$*m ) / m nwork = ivt + ldwkvt*chunk end if ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_dbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=dp) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*m [vt] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] call stdlib${ii}$_zlacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) if( lwork >= m*n + 3_${ik}$*m ) then ! path 6to-fast ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix work(ivt) ! overwrite work(ivt) by right singular vectors of a, ! copying to a ! cworkspace: need 2*m [tauq, taup] + m*n [vt] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*n [vt] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] call stdlib${ii}$_zlacp2( 'F', m, m, rwork( irvt ), m, work( ivt ),ldwkvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', m, n, m, a, lda,work( itaup ), work( & ivt ), ldwkvt,work( nwork ), lwork-nwork+1, ierr ) call stdlib${ii}$_zlacpy( 'F', m, n, work( ivt ), ldwkvt, a, lda ) else ! path 6to-slow ! generate p**h in a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*m [vt] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_zungbr( 'P', m, n, m, a, lda, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! multiply q in a by realmatrix rwork(iru,KIND=dp), storing the ! result in work(iu), copying to a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] ! cworkspace: prefer 2*m [tauq, taup] + m*n [vt] ! rworkspace: need m [e] + m*m [rvt] + 2*m*m [rwork] ! rworkspace: prefer m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_zlarcm( m, blk, rwork( irvt ), m, a( 1_${ik}$, i ),lda, work( ivt )& , ldwkvt,rwork( nrwork ) ) call stdlib${ii}$_zlacpy( 'F', m, blk, work( ivt ), ldwkvt,a( 1_${ik}$, i ), lda ) end do end if else if( wntqs ) then ! path 6ts (n > m, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_dbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=dp) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] call stdlib${ii}$_zlacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] call stdlib${ii}$_zlaset( 'F', m, n, czero, czero, vt, ldvt ) call stdlib${ii}$_zlacp2( 'F', m, m, rwork( irvt ), m, vt, ldvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', m, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) else ! path 6ta (n > m, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_dbdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=dp) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] call stdlib${ii}$_zlacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_zunmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! set all of vt to identity matrix call stdlib${ii}$_zlaset( 'F', n, n, czero, cone, vt, ldvt ) ! copy realmatrix rwork(irvt,KIND=dp) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + n*nb [work] ! rworkspace: need m [e] + m*m [rvt] call stdlib${ii}$_zlacp2( 'F', m, m, rwork( irvt ), m, vt, ldvt ) call stdlib${ii}$_zunmbr( 'P', 'R', 'C', n, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) end if end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( info/=0_${ik}$ .and. anrm>bignum )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn-1,& 1_${ik}$,rwork( ie ), minmn, ierr ) if( anrm=n .and. ldvt=n .and. minmn>0_${ik}$ ) then ! there is no complex work space needed for bidiagonal svd ! the realwork space needed for bidiagonal svd (stdlib${ii}$_${c2ri(ci)}$bdsdc,KIND=${ck}$) is ! bdspac = 3*n*n + 4*n for singular values and vectors; ! bdspac = 4*n for singular values only; ! not including e, ru, and rvt matrices. ! compute space preferred for each routine call stdlib${ii}$_${ci}$gebrd( m, n, cdum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_wgebrd_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$gebrd( n, n, cdum(1_${ik}$), n, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_wgebrd_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$geqrf( m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wgeqrf_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_wungbr_p_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_wungbr_q_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$ungbr( 'Q', m, n, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_wungbr_q_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$ungqr( m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_wungqr_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$ungqr( m, n, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_wungqr_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', n, n, n, cdum(1_${ik}$), n, cdum(1_${ik}$),cdum(1_${ik}$), n, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_wunmbr_prc_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_wunmbr_qln_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, n, n, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_wunmbr_qln_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', n, n, n, cdum(1_${ik}$), n, cdum(1_${ik}$),cdum(1_${ik}$), n, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_wunmbr_qln_nn = int( cdum(1_${ik}$),KIND=${ik}$) if( m>=mnthr1 ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') maxwrk = n + lwork_wgeqrf_mn maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wgebrd_nn ) minwrk = 3_${ik}$*n else if( wntqo ) then ! path 2 (m >> n, jobz='o') wrkbl = n + lwork_wgeqrf_mn wrkbl = max( wrkbl, n + lwork_wungqr_mn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_wgebrd_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_wunmbr_qln_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_wunmbr_prc_nn ) maxwrk = m*n + n*n + wrkbl minwrk = 2_${ik}$*n*n + 3_${ik}$*n else if( wntqs ) then ! path 3 (m >> n, jobz='s') wrkbl = n + lwork_wgeqrf_mn wrkbl = max( wrkbl, n + lwork_wungqr_mn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_wgebrd_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_wunmbr_qln_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_wunmbr_prc_nn ) maxwrk = n*n + wrkbl minwrk = n*n + 3_${ik}$*n else if( wntqa ) then ! path 4 (m >> n, jobz='a') wrkbl = n + lwork_wgeqrf_mn wrkbl = max( wrkbl, n + lwork_wungqr_mm ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_wgebrd_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_wunmbr_qln_nn ) wrkbl = max( wrkbl, 2_${ik}$*n + lwork_wunmbr_prc_nn ) maxwrk = n*n + wrkbl minwrk = n*n + max( 3_${ik}$*n, n + m ) end if else if( m>=mnthr2 ) then ! path 5 (m >> n, but not as much as mnthr1) maxwrk = 2_${ik}$*n + lwork_wgebrd_mn minwrk = 2_${ik}$*n + m if( wntqo ) then ! path 5o (m >> n, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wungbr_p_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wungbr_q_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + n*n else if( wntqs ) then ! path 5s (m >> n, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wungbr_p_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wungbr_q_mn ) else if( wntqa ) then ! path 5a (m >> n, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wungbr_p_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wungbr_q_mm ) end if else ! path 6 (m >= n, but not much larger) maxwrk = 2_${ik}$*n + lwork_wgebrd_mn minwrk = 2_${ik}$*n + m if( wntqo ) then ! path 6o (m >= n, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wunmbr_prc_nn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wunmbr_qln_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + n*n else if( wntqs ) then ! path 6s (m >= n, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wunmbr_qln_mn ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wunmbr_prc_nn ) else if( wntqa ) then ! path 6a (m >= n, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*n + lwork_wunmbr_prc_nn ) end if end if else if( minmn>0_${ik}$ ) then ! there is no complex work space needed for bidiagonal svd ! the realwork space needed for bidiagonal svd (stdlib${ii}$_${c2ri(ci)}$bdsdc,KIND=${ck}$) is ! bdspac = 3*m*m + 4*m for singular values and vectors; ! bdspac = 4*m for singular values only; ! not including e, ru, and rvt matrices. ! compute space preferred for each routine call stdlib${ii}$_${ci}$gebrd( m, n, cdum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_wgebrd_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$gebrd( m, m, cdum(1_${ik}$), m, dum(1_${ik}$), dum(1_${ik}$), cdum(1_${ik}$),cdum(1_${ik}$), cdum(1_${ik}$), -& 1_${ik}$, ierr ) lwork_wgebrd_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$gelqf( m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$), -1_${ik}$, ierr ) lwork_wgelqf_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$ungbr( 'P', m, n, m, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_wungbr_p_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_wungbr_p_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, n, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_wungbr_q_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$unglq( m, n, m, cdum(1_${ik}$), m, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_wunglq_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$unglq( n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$), cdum(1_${ik}$),-1_${ik}$, ierr ) lwork_wunglq_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', m, m, m, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_wunmbr_prc_mm = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', m, n, m, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_wunmbr_prc_mn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', n, n, m, cdum(1_${ik}$), n, cdum(1_${ik}$),cdum(1_${ik}$), n, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_wunmbr_prc_nn = int( cdum(1_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, m, m, cdum(1_${ik}$), m, cdum(1_${ik}$),cdum(1_${ik}$), m, cdum(& 1_${ik}$), -1_${ik}$, ierr ) lwork_wunmbr_qln_mm = int( cdum(1_${ik}$),KIND=${ik}$) if( n>=mnthr1 ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') maxwrk = m + lwork_wgelqf_mn maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wgebrd_mm ) minwrk = 3_${ik}$*m else if( wntqo ) then ! path 2t (n >> m, jobz='o') wrkbl = m + lwork_wgelqf_mn wrkbl = max( wrkbl, m + lwork_wunglq_mn ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_wgebrd_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_wunmbr_qln_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_wunmbr_prc_mm ) maxwrk = m*n + m*m + wrkbl minwrk = 2_${ik}$*m*m + 3_${ik}$*m else if( wntqs ) then ! path 3t (n >> m, jobz='s') wrkbl = m + lwork_wgelqf_mn wrkbl = max( wrkbl, m + lwork_wunglq_mn ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_wgebrd_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_wunmbr_qln_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_wunmbr_prc_mm ) maxwrk = m*m + wrkbl minwrk = m*m + 3_${ik}$*m else if( wntqa ) then ! path 4t (n >> m, jobz='a') wrkbl = m + lwork_wgelqf_mn wrkbl = max( wrkbl, m + lwork_wunglq_nn ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_wgebrd_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_wunmbr_qln_mm ) wrkbl = max( wrkbl, 2_${ik}$*m + lwork_wunmbr_prc_mm ) maxwrk = m*m + wrkbl minwrk = m*m + max( 3_${ik}$*m, m + n ) end if else if( n>=mnthr2 ) then ! path 5t (n >> m, but not as much as mnthr1) maxwrk = 2_${ik}$*m + lwork_wgebrd_mn minwrk = 2_${ik}$*m + n if( wntqo ) then ! path 5to (n >> m, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wungbr_q_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wungbr_p_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + m*m else if( wntqs ) then ! path 5ts (n >> m, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wungbr_q_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wungbr_p_mn ) else if( wntqa ) then ! path 5ta (n >> m, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wungbr_q_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wungbr_p_nn ) end if else ! path 6t (n > m, but not much larger) maxwrk = 2_${ik}$*m + lwork_wgebrd_mn minwrk = 2_${ik}$*m + n if( wntqo ) then ! path 6to (n > m, jobz='o') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wunmbr_prc_mn ) maxwrk = maxwrk + m*n minwrk = minwrk + m*m else if( wntqs ) then ! path 6ts (n > m, jobz='s') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wunmbr_prc_mn ) else if( wntqa ) then ! path 6ta (n > m, jobz='a') maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wunmbr_qln_mm ) maxwrk = max( maxwrk, 2_${ik}$*m + lwork_wunmbr_prc_nn ) end if end if end if maxwrk = max( maxwrk, minwrk ) end if if( info==0_${ik}$ ) then work( 1_${ik}$ ) = stdlib${ii}$_${c2ri(ci)}$roundup_lwork( maxwrk ) if( lworkzero .and. anrmbignum ) then iscl = 1_${ik}$ call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, bignum, m, n, a, lda, ierr ) end if if( m>=n ) then ! a has at least as many rows as columns. if a has sufficiently ! more rows than columns, first reduce using the qr ! decomposition (if sufficient workspace available) if( m>=mnthr1 ) then if( wntqn ) then ! path 1 (m >> n, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + n ! compute a=q*r ! cworkspace: need n [tau] + n [work] ! cworkspace: prefer n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! zero out below r if (n>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_${ci}$gebrd( n, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) nrwork = ie + n ! perform bidiagonal svd, compute singular values only ! cworkspace: need 0 ! rworkspace: need n [e] + bdspac call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'N', n, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then ! path 2 (m >> n, jobz='o') ! n left singular vectors to be overwritten on a and ! n right singular vectors to be computed in vt iu = 1_${ik}$ ! work(iu) is n by n ldwrku = n ir = iu + ldwrku*n if( lwork >= m*n + n*n + 3_${ik}$*n ) then ! work(ir) is m by n ldwrkr = m else ldwrkr = ( lwork - n*n - 3_${ik}$*n ) / n end if itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! cworkspace: need n*n [u] + n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy r to work( ir ), zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero, work( ir+1 ),ldwrkr ) ! generate q in a ! cworkspace: need n*n [u] + n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$ungqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! cworkspace: need n*n [u] + n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_${ci}$gebrd( n, n, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of r in work(iru) and computing right singular vectors ! of r in work(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = ie + n irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix work(iu) ! overwrite work(iu) by the left singular vectors of r ! cworkspace: need n*n [u] + n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( iru ), n, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & work( iu ), ldwrku,work( nwork ), lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix vt ! overwrite vt by the right singular vectors of r ! cworkspace: need n*n [u] + n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork-nwork+1, ierr ) ! multiply q in a by left singular vectors of r in ! work(iu), storing result in work(ir) and copying to a ! cworkspace: need n*n [u] + n*n [r] ! cworkspace: prefer n*n [u] + m*n [r] ! rworkspace: need 0 do i = 1, m, ldwrkr chunk = min( m-i+1, ldwrkr ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', chunk, n, n, cone, a( i, 1_${ik}$ ),lda, work( iu ), & ldwrku, czero,work( ir ), ldwrkr ) call stdlib${ii}$_${ci}$lacpy( 'F', chunk, n, work( ir ), ldwrkr,a( i, 1_${ik}$ ), lda ) end do else if( wntqs ) then ! path 3 (m >> n, jobz='s') ! n left singular vectors to be computed in u and ! n right singular vectors to be computed in vt ir = 1_${ik}$ ! work(ir) is n by n ldwrkr = n itau = ir + ldwrkr*n nwork = itau + n ! compute a=q*r ! cworkspace: need n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy r to work(ir), zeroing out below it call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, work( ir ), ldwrkr ) call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero, work( ir+1 ),ldwrkr ) ! generate q in a ! cworkspace: need n*n [r] + n [tau] + n [work] ! cworkspace: prefer n*n [r] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$ungqr( m, n, n, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + n nwork = itaup + n ! bidiagonalize r in work(ir) ! cworkspace: need n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [r] + 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_${ci}$gebrd( n, n, work( ir ), ldwrkr, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = ie + n irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix u ! overwrite u by left singular vectors of r ! cworkspace: need n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( iru ), n, u, ldu ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', n, n, n, work( ir ), ldwrkr,work( itauq ), & u, ldu, work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix vt ! overwrite vt by right singular vectors of r ! cworkspace: need n*n [r] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [r] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', n, n, n, work( ir ), ldwrkr,work( itaup ), & vt, ldvt, work( nwork ),lwork-nwork+1, ierr ) ! multiply q in a by left singular vectors of r in ! work(ir), storing result in u ! cworkspace: need n*n [r] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'F', n, n, u, ldu, work( ir ), ldwrkr ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, n, cone, a, lda, work( ir ),ldwrkr, czero, & u, ldu ) else if( wntqa ) then ! path 4 (m >> n, jobz='a') ! m left singular vectors to be computed in u and ! n right singular vectors to be computed in vt iu = 1_${ik}$ ! work(iu) is n by n ldwrku = n itau = iu + ldwrku*n nwork = itau + n ! compute a=q*r, copying result to u ! cworkspace: need n*n [u] + n [tau] + n [work] ! cworkspace: prefer n*n [u] + n [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$geqrf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) ! generate q in u ! cworkspace: need n*n [u] + n [tau] + m [work] ! cworkspace: prefer n*n [u] + n [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$ungqr( m, m, n, u, ldu, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ! produce r in a, zeroing out below it if (n>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'L', n-1, n-1, czero, czero, a( 2_${ik}$, 1_${ik}$ ),lda ) ie = 1_${ik}$ itauq = itau itaup = itauq + n nwork = itaup + n ! bidiagonalize r in a ! cworkspace: need n*n [u] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + 2*n [tauq, taup] + 2*n*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_${ci}$gebrd( n, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) iru = ie + n irvt = iru + n*n nrwork = irvt + n*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix work(iu) ! overwrite work(iu) by left singular vectors of r ! cworkspace: need n*n [u] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( iru ), n, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', n, n, n, a, lda,work( itauq ), work( iu ), & ldwrku,work( nwork ), lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix vt ! overwrite vt by right singular vectors of r ! cworkspace: need n*n [u] + 2*n [tauq, taup] + n [work] ! cworkspace: prefer n*n [u] + 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) ! multiply q in u by left singular vectors of r in ! work(iu), storing result in a ! cworkspace: need n*n [u] ! rworkspace: need 0 call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, n, cone, u, ldu, work( iu ),ldwrku, czero, & a, lda ) ! copy left singular vectors of a from a to u call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, u, ldu ) end if else if( m>=mnthr2 ) then ! mnthr2 <= m < mnthr1 ! path 5 (m >> n, but not as much as mnthr1) ! reduce to bidiagonal form without qr decomposition, use ! stdlib${ii}$_${ci}$ungbr and matrix multiplication to compute singular vectors ie = 1_${ik}$ nrwork = ie + n itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ! bidiagonalize a ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + (m+n)*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5n (m >> n, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need n [e] + bdspac call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'N', n, s, rwork( ie ), dum, 1_${ik}$,dum,1_${ik}$,dum, idum, & rwork( nrwork ), iwork, info ) else if( wntqo ) then iu = nwork iru = nrwork irvt = iru + n*n nrwork = irvt + n*n ! path 5o (m >> n, jobz='o') ! copy a to vt, generate p**h ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! generate q in a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$ungbr( 'Q', m, n, n, a, lda, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) if( lwork >= m*n + 3_${ik}$*n ) then ! work( iu ) is m by n ldwrku = m else ! work(iu) is ldwrku by n ldwrku = ( lwork - 3_${ik}$*n ) / n end if nwork = iu + ldwrku*n ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! multiply realmatrix rwork(irvt,KIND=${ck}$) by p**h in vt, ! storing the result in work(iu), copying to vt ! cworkspace: need 2*n [tauq, taup] + n*n [u] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + 2*n*n [rwork] call stdlib${ii}$_${ci}$larcm( n, n, rwork( irvt ), n, vt, ldvt,work( iu ), ldwrku, & rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', n, n, work( iu ), ldwrku, vt, ldvt ) ! multiply q in a by realmatrix rwork(iru,KIND=${ck}$), storing the ! result in work(iu), copying to a ! cworkspace: need 2*n [tauq, taup] + n*n [u] ! cworkspace: prefer 2*n [tauq, taup] + m*n [u] ! rworkspace: need n [e] + n*n [ru] + 2*n*n [rwork] ! rworkspace: prefer n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_${ci}$lacrm( chunk, n, a( i, 1_${ik}$ ), lda, rwork( iru ),n, work( iu ), & ldwrku, rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do else if( wntqs ) then ! path 5s (m >> n, jobz='s') ! copy a to vt, generate p**h ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! copy a to u, generate q ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) call stdlib${ii}$_${ci}$ungbr( 'Q', m, n, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! multiply realmatrix rwork(irvt,KIND=${ck}$) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + 2*n*n [rwork] call stdlib${ii}$_${ci}$larcm( n, n, rwork( irvt ), n, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', n, n, a, lda, vt, ldvt ) ! multiply q in u by realmatrix rwork(iru,KIND=${ck}$), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt call stdlib${ii}$_${ci}$lacrm( m, n, u, ldu, rwork( iru ), n, a, lda,rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, u, ldu ) else ! path 5a (m >> n, jobz='a') ! copy a to vt, generate p**h ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, vt, ldvt ) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, n, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! copy a to u, generate q ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'L', m, n, a, lda, u, ldu ) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! multiply realmatrix rwork(irvt,KIND=${ck}$) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + 2*n*n [rwork] call stdlib${ii}$_${ci}$larcm( n, n, rwork( irvt ), n, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', n, n, a, lda, vt, ldvt ) ! multiply q in u by realmatrix rwork(iru,KIND=${ck}$), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt call stdlib${ii}$_${ci}$lacrm( m, n, u, ldu, rwork( iru ), n, a, lda,rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, u, ldu ) end if else ! m < mnthr2 ! path 6 (m >= n, but not much larger) ! reduce to bidiagonal form without qr decomposition ! use stdlib_${ci}$unmbr to compute singular vectors ie = 1_${ik}$ nrwork = ie + n itauq = 1_${ik}$ itaup = itauq + n nwork = itaup + n ! bidiagonalize a ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + (m+n)*nb [work] ! rworkspace: need n [e] call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 6n (m >= n, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need n [e] + bdspac call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'N', n, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then iu = nwork iru = nrwork irvt = iru + n*n nrwork = irvt + n*n if( lwork >= m*n + 3_${ik}$*n ) then ! work( iu ) is m by n ldwrku = m else ! work( iu ) is ldwrku by n ldwrku = ( lwork - 3_${ik}$*n ) / n end if nwork = iu + ldwrku*n ! path 6o (m >= n, jobz='o') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n*n [u] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*n [u] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) if( lwork >= m*n + 3_${ik}$*n ) then ! path 6o-fast ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix work(iu) ! overwrite work(iu) by left singular vectors of a, copying ! to a ! cworkspace: need 2*n [tauq, taup] + m*n [u] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + m*n [u] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] call stdlib${ii}$_${ci}$laset( 'F', m, n, czero, czero, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( iru ), n, work( iu ),ldwrku ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), work( iu & ), ldwrku,work( nwork ), lwork-nwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'F', m, n, work( iu ), ldwrku, a, lda ) else ! path 6o-slow ! generate q in a ! cworkspace: need 2*n [tauq, taup] + n*n [u] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*n [u] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$ungbr( 'Q', m, n, n, a, lda, work( itauq ),work( nwork ), & lwork-nwork+1, ierr ) ! multiply q in a by realmatrix rwork(iru,KIND=${ck}$), storing the ! result in work(iu), copying to a ! cworkspace: need 2*n [tauq, taup] + n*n [u] ! cworkspace: prefer 2*n [tauq, taup] + m*n [u] ! rworkspace: need n [e] + n*n [ru] + 2*n*n [rwork] ! rworkspace: prefer n [e] + n*n [ru] + 2*m*n [rwork] < n + 5*n*n since m < 2*n here nrwork = irvt do i = 1, m, ldwrku chunk = min( m-i+1, ldwrku ) call stdlib${ii}$_${ci}$lacrm( chunk, n, a( i, 1_${ik}$ ), lda,rwork( iru ), n, work( iu )& , ldwrku,rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', chunk, n, work( iu ), ldwrku,a( i, 1_${ik}$ ), lda ) end do end if else if( wntqs ) then ! path 6s (m >= n, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_${ci}$laset( 'F', m, n, czero, czero, u, ldu ) call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( iru ), n, u, ldu ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, n, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) else ! path 6a (m >= n, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] + bdspac iru = nrwork irvt = iru + n*n nrwork = irvt + n*n call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', n, s, rwork( ie ), rwork( iru ),n, rwork( irvt )& , n, dum, idum,rwork( nrwork ), iwork, info ) ! set the right corner of u to identity matrix call stdlib${ii}$_${ci}$laset( 'F', m, m, czero, czero, u, ldu ) if( m>n ) then call stdlib${ii}$_${ci}$laset( 'F', m-n, m-n, czero, cone,u( n+1, n+1 ), ldu ) end if ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*n [tauq, taup] + m [work] ! cworkspace: prefer 2*n [tauq, taup] + m*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( iru ), n, u, ldu ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*n [tauq, taup] + n [work] ! cworkspace: prefer 2*n [tauq, taup] + n*nb [work] ! rworkspace: need n [e] + n*n [ru] + n*n [rvt] call stdlib${ii}$_${ci}$lacp2( 'F', n, n, rwork( irvt ), n, vt, ldvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', n, n, n, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) end if end if else ! a has more columns than rows. if a has sufficiently more ! columns than rows, first reduce using the lq decomposition (if ! sufficient workspace available) if( n>=mnthr1 ) then if( wntqn ) then ! path 1t (n >> m, jobz='n') ! no singular vectors to be computed itau = 1_${ik}$ nwork = itau + m ! compute a=l*q ! cworkspace: need m [tau] + m [work] ! cworkspace: prefer m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! zero out above l if (m>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero, a( 1_${ik}$, 2_${ik}$ ),lda ) ie = 1_${ik}$ itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_${ci}$gebrd( m, m, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) nrwork = ie + m ! perform bidiagonal svd, compute singular values only ! cworkspace: need 0 ! rworkspace: need m [e] + bdspac call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'N', m, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then ! path 2t (n >> m, jobz='o') ! m right singular vectors to be overwritten on a and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ldwkvt = m ! work(ivt) is m by m il = ivt + ldwkvt*m if( lwork >= m*n + m*m + 3_${ik}$*m ) then ! work(il) m by n ldwrkl = m chunk = n else ! work(il) is m by chunk ldwrkl = m chunk = ( lwork - m*m - 3_${ik}$*m ) / m end if itau = il + ldwrkl*chunk nwork = itau + m ! compute a=l*q ! cworkspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy l to work(il), zeroing about above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,work( il+ldwrkl ), ldwrkl ) ! generate q in a ! cworkspace: need m*m [vt] + m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$unglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il) ! cworkspace: need m*m [vt] + m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_${ci}$gebrd( m, m, work( il ), ldwrkl, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [ru] + m*m [rvt] + bdspac iru = ie + m irvt = iru + m*m nrwork = irvt + m*m call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix work(iu) ! overwrite work(iu) by the left singular vectors of l ! cworkspace: need m*m [vt] + m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix work(ivt) ! overwrite work(ivt) by the right singular vectors of l ! cworkspace: need m*m [vt] + m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( irvt ), m, work( ivt ),ldwkvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', m, m, m, work( il ), ldwrkl,work( itaup ), & work( ivt ), ldwkvt,work( nwork ), lwork-nwork+1, ierr ) ! multiply right singular vectors of l in work(il) by q ! in a, storing result in work(il) and copying to a ! cworkspace: need m*m [vt] + m*m [l] ! cworkspace: prefer m*m [vt] + m*n [l] ! rworkspace: need 0 do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, blk, m, cone, work( ivt ), m,a( 1_${ik}$, i ), & lda, czero, work( il ),ldwrkl ) call stdlib${ii}$_${ci}$lacpy( 'F', m, blk, work( il ), ldwrkl,a( 1_${ik}$, i ), lda ) end do else if( wntqs ) then ! path 3t (n >> m, jobz='s') ! m right singular vectors to be computed in vt and ! m left singular vectors to be computed in u il = 1_${ik}$ ! work(il) is m by m ldwrkl = m itau = il + ldwrkl*m nwork = itau + m ! compute a=l*q ! cworkspace: need m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) ! copy l to work(il), zeroing out above it call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, work( il ), ldwrkl ) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero,work( il+ldwrkl ), ldwrkl ) ! generate q in a ! cworkspace: need m*m [l] + m [tau] + m [work] ! cworkspace: prefer m*m [l] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$unglq( m, n, m, a, lda, work( itau ),work( nwork ), lwork-nwork+& 1_${ik}$, ierr ) ie = 1_${ik}$ itauq = itau itaup = itauq + m nwork = itaup + m ! bidiagonalize l in work(il) ! cworkspace: need m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [l] + 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_${ci}$gebrd( m, m, work( il ), ldwrkl, s, rwork( ie ),work( itauq ), & work( itaup ), work( nwork ),lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [ru] + m*m [rvt] + bdspac iru = ie + m irvt = iru + m*m nrwork = irvt + m*m call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix u ! overwrite u by left singular vectors of l ! cworkspace: need m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, m, m, work( il ), ldwrkl,work( itauq ), & u, ldu, work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix vt ! overwrite vt by left singular vectors of l ! cworkspace: need m*m [l] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [l] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( irvt ), m, vt, ldvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', m, m, m, work( il ), ldwrkl,work( itaup ), & vt, ldvt, work( nwork ),lwork-nwork+1, ierr ) ! copy vt to work(il), multiply right singular vectors of l ! in work(il) by q in a, storing result in vt ! cworkspace: need m*m [l] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'F', m, m, vt, ldvt, work( il ), ldwrkl ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, m, cone, work( il ), ldwrkl,a, lda, czero, & vt, ldvt ) else if( wntqa ) then ! path 4t (n >> m, jobz='a') ! n right singular vectors to be computed in vt and ! m left singular vectors to be computed in u ivt = 1_${ik}$ ! work(ivt) is m by m ldwkvt = m itau = ivt + ldwkvt*m nwork = itau + m ! compute a=l*q, copying result to vt ! cworkspace: need m*m [vt] + m [tau] + m [work] ! cworkspace: prefer m*m [vt] + m [tau] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$gelqf( m, n, a, lda, work( itau ), work( nwork ),lwork-nwork+1, & ierr ) call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) ! generate q in vt ! cworkspace: need m*m [vt] + m [tau] + n [work] ! cworkspace: prefer m*m [vt] + m [tau] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$unglq( n, n, m, vt, ldvt, work( itau ),work( nwork ), lwork-& nwork+1, ierr ) ! produce l in a, zeroing out above it if (m>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', m-1, m-1, czero, czero, a( 1_${ik}$, 2_${ik}$ ),lda ) ie = 1_${ik}$ itauq = itau itaup = itauq + m nwork = itaup + m ! bidiagonalize l in a ! cworkspace: need m*m [vt] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + 2*m [tauq, taup] + 2*m*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_${ci}$gebrd( m, m, a, lda, s, rwork( ie ), work( itauq ),work( itaup ),& work( nwork ), lwork-nwork+1,ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [ru] + m*m [rvt] + bdspac iru = ie + m irvt = iru + m*m nrwork = irvt + m*m call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'U', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix u ! overwrite u by left singular vectors of l ! cworkspace: need m*m [vt] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, m, m, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix work(ivt) ! overwrite work(ivt) by right singular vectors of l ! cworkspace: need m*m [vt] + 2*m [tauq, taup] + m [work] ! cworkspace: prefer m*m [vt] + 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( irvt ), m, work( ivt ),ldwkvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', m, m, m, a, lda,work( itaup ), work( ivt ),& ldwkvt,work( nwork ), lwork-nwork+1, ierr ) ! multiply right singular vectors of l in work(ivt) by ! q in vt, storing result in a ! cworkspace: need m*m [vt] ! rworkspace: need 0 call stdlib${ii}$_${ci}$gemm( 'N', 'N', m, n, m, cone, work( ivt ), ldwkvt,vt, ldvt, & czero, a, lda ) ! copy right singular vectors of a from a to vt call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, vt, ldvt ) end if else if( n>=mnthr2 ) then ! mnthr2 <= n < mnthr1 ! path 5t (n >> m, but not as much as mnthr1) ! reduce to bidiagonal form without qr decomposition, use ! stdlib${ii}$_${ci}$ungbr and matrix multiplication to compute singular vectors ie = 1_${ik}$ nrwork = ie + m itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ! bidiagonalize a ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + (m+n)*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 5tn (n >> m, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need m [e] + bdspac call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'L', 'N', m, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then irvt = nrwork iru = irvt + m*m nrwork = iru + m*m ivt = nwork ! path 5to (n >> m, jobz='o') ! copy a to u, generate q ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! generate p**h in a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$ungbr( 'P', m, n, m, a, lda, work( itaup ),work( nwork ), lwork-& nwork+1, ierr ) ldwkvt = m if( lwork >= m*n + 3_${ik}$*m ) then ! work( ivt ) is m by n nwork = ivt + ldwkvt*n chunk = n else ! work( ivt ) is m by chunk chunk = ( lwork - 3_${ik}$*m ) / m nwork = ivt + ldwkvt*chunk end if ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! multiply q in u by realmatrix rwork(irvt,KIND=${ck}$) ! storing the result in work(ivt), copying to u ! cworkspace: need 2*m [tauq, taup] + m*m [vt] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + 2*m*m [rwork] call stdlib${ii}$_${ci}$lacrm( m, m, u, ldu, rwork( iru ), m, work( ivt ),ldwkvt, rwork( & nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', m, m, work( ivt ), ldwkvt, u, ldu ) ! multiply rwork(irvt) by p**h in a, storing the ! result in work(ivt), copying to a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] ! cworkspace: prefer 2*m [tauq, taup] + m*n [vt] ! rworkspace: need m [e] + m*m [rvt] + 2*m*m [rwork] ! rworkspace: prefer m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_${ci}$larcm( m, blk, rwork( irvt ), m, a( 1_${ik}$, i ), lda,work( ivt ), & ldwkvt, rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', m, blk, work( ivt ), ldwkvt,a( 1_${ik}$, i ), lda ) end do else if( wntqs ) then ! path 5ts (n >> m, jobz='s') ! copy a to u, generate q ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! copy a to vt, generate p**h ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) call stdlib${ii}$_${ci}$ungbr( 'P', m, n, m, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! multiply q in u by realmatrix rwork(iru,KIND=${ck}$), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + 2*m*m [rwork] call stdlib${ii}$_${ci}$lacrm( m, m, u, ldu, rwork( iru ), m, a, lda,rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', m, m, a, lda, u, ldu ) ! multiply realmatrix rwork(irvt,KIND=${ck}$) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru call stdlib${ii}$_${ci}$larcm( m, n, rwork( irvt ), m, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, vt, ldvt ) else ! path 5ta (n >> m, jobz='a') ! copy a to u, generate q ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'L', m, m, a, lda, u, ldu ) call stdlib${ii}$_${ci}$ungbr( 'Q', m, m, n, u, ldu, work( itauq ),work( nwork ), lwork-& nwork+1, ierr ) ! copy a to vt, generate p**h ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + n*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$lacpy( 'U', m, n, a, lda, vt, ldvt ) call stdlib${ii}$_${ci}$ungbr( 'P', n, n, m, vt, ldvt, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! multiply q in u by realmatrix rwork(iru,KIND=${ck}$), storing the ! result in a, copying to u ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + 2*m*m [rwork] call stdlib${ii}$_${ci}$lacrm( m, m, u, ldu, rwork( iru ), m, a, lda,rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', m, m, a, lda, u, ldu ) ! multiply realmatrix rwork(irvt,KIND=${ck}$) by p**h in vt, ! storing the result in a, copying to vt ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru call stdlib${ii}$_${ci}$larcm( m, n, rwork( irvt ), m, vt, ldvt, a, lda,rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', m, n, a, lda, vt, ldvt ) end if else ! n < mnthr2 ! path 6t (n > m, but not much larger) ! reduce to bidiagonal form without lq decomposition ! use stdlib_${ci}$unmbr to compute singular vectors ie = 1_${ik}$ nrwork = ie + m itauq = 1_${ik}$ itaup = itauq + m nwork = itaup + m ! bidiagonalize a ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + (m+n)*nb [work] ! rworkspace: need m [e] call stdlib${ii}$_${ci}$gebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),work( itaup ), & work( nwork ), lwork-nwork+1,ierr ) if( wntqn ) then ! path 6tn (n > m, jobz='n') ! compute singular values only ! cworkspace: need 0 ! rworkspace: need m [e] + bdspac call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'L', 'N', m, s, rwork( ie ), dum,1_${ik}$,dum,1_${ik}$,dum, idum, rwork(& nrwork ), iwork, info ) else if( wntqo ) then ! path 6to (n > m, jobz='o') ldwkvt = m ivt = nwork if( lwork >= m*n + 3_${ik}$*m ) then ! work( ivt ) is m by n call stdlib${ii}$_${ci}$laset( 'F', m, n, czero, czero, work( ivt ),ldwkvt ) nwork = ivt + ldwkvt*n else ! work( ivt ) is m by chunk chunk = ( lwork - 3_${ik}$*m ) / m nwork = ivt + ldwkvt*chunk end if ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*m [vt] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) if( lwork >= m*n + 3_${ik}$*m ) then ! path 6to-fast ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix work(ivt) ! overwrite work(ivt) by right singular vectors of a, ! copying to a ! cworkspace: need 2*m [tauq, taup] + m*n [vt] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*n [vt] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( irvt ), m, work( ivt ),ldwkvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', m, n, m, a, lda,work( itaup ), work( & ivt ), ldwkvt,work( nwork ), lwork-nwork+1, ierr ) call stdlib${ii}$_${ci}$lacpy( 'F', m, n, work( ivt ), ldwkvt, a, lda ) else ! path 6to-slow ! generate p**h in a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*m [vt] + m*nb [work] ! rworkspace: need 0 call stdlib${ii}$_${ci}$ungbr( 'P', m, n, m, a, lda, work( itaup ),work( nwork ), & lwork-nwork+1, ierr ) ! multiply q in a by realmatrix rwork(iru,KIND=${ck}$), storing the ! result in work(iu), copying to a ! cworkspace: need 2*m [tauq, taup] + m*m [vt] ! cworkspace: prefer 2*m [tauq, taup] + m*n [vt] ! rworkspace: need m [e] + m*m [rvt] + 2*m*m [rwork] ! rworkspace: prefer m [e] + m*m [rvt] + 2*m*n [rwork] < m + 5*m*m since n < 2*m here nrwork = iru do i = 1, n, chunk blk = min( n-i+1, chunk ) call stdlib${ii}$_${ci}$larcm( m, blk, rwork( irvt ), m, a( 1_${ik}$, i ),lda, work( ivt )& , ldwkvt,rwork( nrwork ) ) call stdlib${ii}$_${ci}$lacpy( 'F', m, blk, work( ivt ), ldwkvt,a( 1_${ik}$, i ), lda ) end do end if else if( wntqs ) then ! path 6ts (n > m, jobz='s') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] call stdlib${ii}$_${ci}$laset( 'F', m, n, czero, czero, vt, ldvt ) call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( irvt ), m, vt, ldvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', m, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) else ! path 6ta (n > m, jobz='a') ! perform bidiagonal svd, computing left singular vectors ! of bidiagonal matrix in rwork(iru) and computing right ! singular vectors of bidiagonal matrix in rwork(irvt) ! cworkspace: need 0 ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] + bdspac irvt = nrwork iru = irvt + m*m nrwork = iru + m*m call stdlib${ii}$_${c2ri(ci)}$bdsdc( 'L', 'I', m, s, rwork( ie ), rwork( iru ),m, rwork( irvt )& , m, dum, idum,rwork( nrwork ), iwork, info ) ! copy realmatrix rwork(iru,KIND=${ck}$) to complex matrix u ! overwrite u by left singular vectors of a ! cworkspace: need 2*m [tauq, taup] + m [work] ! cworkspace: prefer 2*m [tauq, taup] + m*nb [work] ! rworkspace: need m [e] + m*m [rvt] + m*m [ru] call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( iru ), m, u, ldu ) call stdlib${ii}$_${ci}$unmbr( 'Q', 'L', 'N', m, m, n, a, lda,work( itauq ), u, ldu, & work( nwork ),lwork-nwork+1, ierr ) ! set all of vt to identity matrix call stdlib${ii}$_${ci}$laset( 'F', n, n, czero, cone, vt, ldvt ) ! copy realmatrix rwork(irvt,KIND=${ck}$) to complex matrix vt ! overwrite vt by right singular vectors of a ! cworkspace: need 2*m [tauq, taup] + n [work] ! cworkspace: prefer 2*m [tauq, taup] + n*nb [work] ! rworkspace: need m [e] + m*m [rvt] call stdlib${ii}$_${ci}$lacp2( 'F', m, m, rwork( irvt ), m, vt, ldvt ) call stdlib${ii}$_${ci}$unmbr( 'P', 'R', 'C', n, n, m, a, lda,work( itaup ), vt, ldvt, & work( nwork ),lwork-nwork+1, ierr ) end if end if end if ! undo scaling if necessary if( iscl==1_${ik}$ ) then if( anrm>bignum )call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn, 1_${ik}$, s, minmn,& ierr ) if( info/=0_${ik}$ .and. anrm>bignum )call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, bignum, anrm, minmn-1,& 1_${ik}$,rwork( ie ), minmn, ierr ) if( anrm= N. The SVD of [A] is written as !! [A] = [U] * [SIGMA] * [V]^t, !! where [SIGMA] is an N-by-N (M-by-N) matrix which is zero except for its N !! diagonal elements, [U] is an M-by-N (or M-by-M) orthonormal matrix, and !! [V] is an N-by-N orthogonal matrix. The diagonal elements of [SIGMA] are !! the singular values of [A]. The columns of [U] and [V] are the left and !! the right singular vectors of [A], respectively. The matrices [U] and [V] !! are computed and stored in the arrays U and V, respectively. The diagonal !! of [SIGMA] is computed and stored in the array SVA. !! SGEJSV can sometimes compute tiny singular values and their singular vectors much !! more accurately than other SVD routines, see below under Further Details. v, ldv,work, lwork, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldu, ldv, lwork, m, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: sva(n), u(ldu,*), v(ldv,*), work(lwork) integer(${ik}$), intent(out) :: iwork(*) character, intent(in) :: joba, jobp, jobr, jobt, jobu, jobv ! =========================================================================== ! Local Scalars real(sp) :: aapp, aaqq, aatmax, aatmin, big, big1, cond_ok, condr1, condr2, entra, & entrat, epsln, maxprj, scalem, sconda, sfmin, small, temp1, uscal1, uscal2, xsc integer(${ik}$) :: ierr, n1, nr, numrank, p, q, warning logical(lk) :: almort, defr, errest, goscal, jracc, kill, lsvec, l2aber, l2kill, & l2pert, l2rank, l2tran, noscal, rowpiv, rsvec, transp ! Intrinsic Functions ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) .or. stdlib_lsame( jobu, 'F' ) jracc = stdlib_lsame( jobv, 'J' ) rsvec = stdlib_lsame( jobv, 'V' ) .or. jracc rowpiv = stdlib_lsame( joba, 'F' ) .or. stdlib_lsame( joba, 'G' ) l2rank = stdlib_lsame( joba, 'R' ) l2aber = stdlib_lsame( joba, 'A' ) errest = stdlib_lsame( joba, 'E' ) .or. stdlib_lsame( joba, 'G' ) l2tran = stdlib_lsame( jobt, 'T' ) l2kill = stdlib_lsame( jobr, 'R' ) defr = stdlib_lsame( jobr, 'N' ) l2pert = stdlib_lsame( jobp, 'P' ) if ( .not.(rowpiv .or. l2rank .or. l2aber .or.errest .or. stdlib_lsame( joba, 'C' ) )) & then info = - 1_${ik}$ else if ( .not.( lsvec .or. stdlib_lsame( jobu, 'N' ) .or.stdlib_lsame( jobu, 'W' )) )& then info = - 2_${ik}$ else if ( .not.( rsvec .or. stdlib_lsame( jobv, 'N' ) .or.stdlib_lsame( jobv, 'W' )) & .or. ( jracc .and. (.not.lsvec) ) ) then info = - 3_${ik}$ else if ( .not. ( l2kill .or. defr ) ) then info = - 4_${ik}$ else if ( .not. ( l2tran .or. stdlib_lsame( jobt, 'N' ) ) ) then info = - 5_${ik}$ else if ( .not. ( l2pert .or. stdlib_lsame( jobp, 'N' ) ) ) then info = - 6_${ik}$ else if ( m < 0_${ik}$ ) then info = - 7_${ik}$ else if ( ( n < 0_${ik}$ ) .or. ( n > m ) ) then info = - 8_${ik}$ else if ( lda < m ) then info = - 10_${ik}$ else if ( lsvec .and. ( ldu < m ) ) then info = - 13_${ik}$ else if ( rsvec .and. ( ldv < n ) ) then info = - 15_${ik}$ else if ( (.not.(lsvec .or. rsvec .or. errest).and.(lwork < max(7_${ik}$,4_${ik}$*n+1,2_${ik}$*m+n))) .or.(& .not.(lsvec .or. rsvec) .and. errest .and.(lwork < max(7_${ik}$,4_${ik}$*n+n*n,2_${ik}$*m+n))) .or.(lsvec & .and. (.not.rsvec) .and. (lwork < max(7_${ik}$,2_${ik}$*m+n,4_${ik}$*n+1))).or.(rsvec .and. (.not.lsvec) & .and. (lwork < max(7_${ik}$,2_${ik}$*m+n,4_${ik}$*n+1))).or.(lsvec .and. rsvec .and. (.not.jracc) .and.(& lwork big ) then info = - 9_${ik}$ call stdlib${ii}$_xerbla( 'SGEJSV', -info ) return end if aaqq = sqrt(aaqq) if ( ( aapp < (big / aaqq) ) .and. noscal ) then sva(p) = aapp * aaqq else noscal = .false. sva(p) = aapp * ( aaqq * scalem ) if ( goscal ) then goscal = .false. call stdlib${ii}$_sscal( p-1, scalem, sva, 1_${ik}$ ) end if end if end do if ( noscal ) scalem = one aapp = zero aaqq = big do p = 1, n aapp = max( aapp, sva(p) ) if ( sva(p) /= zero ) aaqq = min( aaqq, sva(p) ) end do ! quick return for zero m x n matrix ! #:) if ( aapp == zero ) then if ( lsvec ) call stdlib${ii}$_slaset( 'G', m, n1, zero, one, u, ldu ) if ( rsvec ) call stdlib${ii}$_slaset( 'G', n, n, zero, one, v, ldv ) work(1_${ik}$) = one work(2_${ik}$) = one if ( errest ) work(3_${ik}$) = one if ( lsvec .and. rsvec ) then work(4_${ik}$) = one work(5_${ik}$) = one end if if ( l2tran ) then work(6_${ik}$) = zero work(7_${ik}$) = zero end if iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ iwork(3_${ik}$) = 0_${ik}$ return end if ! issue warning if denormalized column norms detected. override the ! high relative accuracy request. issue licence to kill columns ! (set them to zero) whose norm is less than sigma_max / big (roughly). ! #:( warning = 0_${ik}$ if ( aaqq <= sfmin ) then l2rank = .true. l2kill = .true. warning = 1_${ik}$ end if ! quick return for one-column matrix ! #:) if ( n == 1_${ik}$ ) then if ( lsvec ) then call stdlib${ii}$_slascl( 'G',0_${ik}$,0_${ik}$,sva(1_${ik}$),scalem, m,1_${ik}$,a(1_${ik}$,1_${ik}$),lda,ierr ) call stdlib${ii}$_slacpy( 'A', m, 1_${ik}$, a, lda, u, ldu ) ! computing all m left singular vectors of the m x 1 matrix if ( n1 /= n ) then call stdlib${ii}$_sgeqrf( m, n, u,ldu, work, work(n+1),lwork-n,ierr ) call stdlib${ii}$_sorgqr( m,n1,1_${ik}$, u,ldu,work,work(n+1),lwork-n,ierr ) call stdlib${ii}$_scopy( m, a(1_${ik}$,1_${ik}$), 1_${ik}$, u(1_${ik}$,1_${ik}$), 1_${ik}$ ) end if end if if ( rsvec ) then v(1_${ik}$,1_${ik}$) = one end if if ( sva(1_${ik}$) < (big*scalem) ) then sva(1_${ik}$) = sva(1_${ik}$) / scalem scalem = one end if work(1_${ik}$) = one / scalem work(2_${ik}$) = one if ( sva(1_${ik}$) /= zero ) then iwork(1_${ik}$) = 1_${ik}$ if ( ( sva(1_${ik}$) / scalem) >= sfmin ) then iwork(2_${ik}$) = 1_${ik}$ else iwork(2_${ik}$) = 0_${ik}$ end if else iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ end if iwork(3_${ik}$) = 0_${ik}$ if ( errest ) work(3_${ik}$) = one if ( lsvec .and. rsvec ) then work(4_${ik}$) = one work(5_${ik}$) = one end if if ( l2tran ) then work(6_${ik}$) = zero work(7_${ik}$) = zero end if return end if transp = .false. l2tran = l2tran .and. ( m == n ) aatmax = -one aatmin = big if ( rowpiv .or. l2tran ) then ! compute the row norms, needed to determine row pivoting sequence ! (in the case of heavily row weighted a, row pivoting is strongly ! advised) and to collect information needed to compare the ! structures of a * a^t and a^t * a (in the case l2tran==.true.). if ( l2tran ) then do p = 1, m xsc = zero temp1 = one call stdlib${ii}$_slassq( n, a(p,1_${ik}$), lda, xsc, temp1 ) ! stdlib${ii}$_slassq gets both the ell_2 and the ell_infinity norm ! in one pass through the vector work(m+n+p) = xsc * scalem work(n+p) = xsc * (scalem*sqrt(temp1)) aatmax = max( aatmax, work(n+p) ) if (work(n+p) /= zero) aatmin = min(aatmin,work(n+p)) end do else do p = 1, m work(m+n+p) = scalem*abs( a(p,stdlib${ii}$_isamax(n,a(p,1_${ik}$),lda)) ) aatmax = max( aatmax, work(m+n+p) ) aatmin = min( aatmin, work(m+n+p) ) end do end if end if ! for square matrix a try to determine whether a^t would be better ! input for the preconditioned jacobi svd, with faster convergence. ! the decision is based on an o(n) function of the vector of column ! and row norms of a, based on the shannon entropy. this should give ! the right choice in most cases when the difference actually matters. ! it may fail and pick the slower converging side. entra = zero entrat = zero if ( l2tran ) then xsc = zero temp1 = one call stdlib${ii}$_slassq( n, sva, 1_${ik}$, xsc, temp1 ) temp1 = one / temp1 entra = zero do p = 1, n big1 = ( ( sva(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entra = entra + big1 * log(big1) end do entra = - entra / log(real(n,KIND=sp)) ! now, sva().^2/trace(a^t * a) is a point in the probability simplex. ! it is derived from the diagonal of a^t * a. do the same with the ! diagonal of a * a^t, compute the entropy of the corresponding ! probability distribution. note that a * a^t and a^t * a have the ! same trace. entrat = zero do p = n+1, n+m big1 = ( ( work(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entrat = entrat + big1 * log(big1) end do entrat = - entrat / log(real(m,KIND=sp)) ! analyze the entropies and decide a or a^t. smaller entropy ! usually means better input for the algorithm. transp = ( entrat < entra ) ! if a^t is better than a, transpose a. if ( transp ) then ! in an optimal implementation, this trivial transpose ! should be replaced with faster transpose. do p = 1, n - 1 do q = p + 1, n temp1 = a(q,p) a(q,p) = a(p,q) a(p,q) = temp1 end do end do do p = 1, n work(m+n+p) = sva(p) sva(p) = work(n+p) end do temp1 = aapp aapp = aatmax aatmax = temp1 temp1 = aaqq aaqq = aatmin aatmin = temp1 kill = lsvec lsvec = rsvec rsvec = kill if ( lsvec ) n1 = n rowpiv = .true. end if end if ! end if l2tran ! scale the matrix so that its maximal singular value remains less ! than sqrt(big) -- the matrix is scaled so that its maximal column ! has euclidean norm equal to sqrt(big/n). the only reason to keep ! sqrt(big) instead of big is the fact that stdlib${ii}$_sgejsv uses lapack and ! blas routines that, in some implementations, are not capable of ! working in the full interval [sfmin,big] and that they may provoke ! overflows in the intermediate results. if the singular values spread ! from sfmin to big, then stdlib${ii}$_sgesvj will compute them. so, in that case, ! one should use stdlib_sgesvj instead of stdlib${ii}$_sgejsv. big1 = sqrt( big ) temp1 = sqrt( big / real(n,KIND=sp) ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, n, 1_${ik}$, sva, n, ierr ) if ( aaqq > (aapp * sfmin) ) then aaqq = ( aaqq / aapp ) * temp1 else aaqq = ( aaqq * temp1 ) / aapp end if temp1 = temp1 * scalem call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, m, n, a, lda, ierr ) ! to undo scaling at the end of this procedure, multiply the ! computed singular values with uscal2 / uscal1. uscal1 = temp1 uscal2 = aapp if ( l2kill ) then ! l2kill enforces computation of nonzero singular values in ! the restricted range of condition number of the initial a, ! sigma_max(a) / sigma_min(a) approx. sqrt(big)/sqrt(sfmin). xsc = sqrt( sfmin ) else xsc = small ! now, if the condition number of a is too big, ! sigma_max(a) / sigma_min(a) > sqrt(big/n) * epsln / sfmin, ! as a precaution measure, the full svd is computed using stdlib${ii}$_sgesvj ! with accumulated jacobi rotations. this provides numerically ! more robust computation, at the cost of slightly increased run ! time. depending on the concrete implementation of blas and lapack ! (i.e. how they behave in presence of extreme ill-conditioning) the ! implementor may decide to remove this switch. if ( ( aaqq= (temp1*abs(a(1_${ik}$,1_${ik}$))) ) then nr = nr + 1_${ik}$ else go to 3002 end if end do 3002 continue else if ( l2rank ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r1 is used as the criterion for ! close-to-rank-deficient. temp1 = sqrt(sfmin) do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < small ) .or.( & l2kill .and. (abs(a(p,p)) < temp1) ) ) go to 3402 nr = nr + 1_${ik}$ end do 3402 continue else ! the goal is high relative accuracy. however, if the matrix ! has high scaled condition number the relative accuracy is in ! general not feasible. later on, a condition number estimator ! will be deployed to estimate the scaled condition number. ! here we just remove the underflowed part of the triangular ! factor. this prevents the situation in which the code is ! working hard to get the accuracy not warranted by the data. temp1 = sqrt(sfmin) do p = 2, n if ( ( abs(a(p,p)) < small ) .or.( l2kill .and. (abs(a(p,p)) < temp1) ) ) go to 3302 nr = nr + 1_${ik}$ end do 3302 continue end if almort = .false. if ( nr == n ) then maxprj = one do p = 2, n temp1 = abs(a(p,p)) / sva(iwork(p)) maxprj = min( maxprj, temp1 ) end do if ( maxprj**2_${ik}$ >= one - real(n,KIND=sp)*epsln ) almort = .true. end if sconda = - one condr1 = - one condr2 = - one if ( errest ) then if ( n == nr ) then if ( rsvec ) then ! V Is Available As Workspace call stdlib${ii}$_slacpy( 'U', n, n, a, lda, v, ldv ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_sscal( p, one/temp1, v(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_spocon( 'U', n, v, ldv, one, temp1,work(n+1), iwork(2_${ik}$*n+m+1), & ierr ) else if ( lsvec ) then ! U Is Available As Workspace call stdlib${ii}$_slacpy( 'U', n, n, a, lda, u, ldu ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_sscal( p, one/temp1, u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_spocon( 'U', n, u, ldu, one, temp1,work(n+1), iwork(2_${ik}$*n+m+1), & ierr ) else call stdlib${ii}$_slacpy( 'U', n, n, a, lda, work(n+1), n ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_sscal( p, one/temp1, work(n+(p-1)*n+1), 1_${ik}$ ) end do ! The Columns Of R Are Scaled To Have Unit Euclidean Lengths call stdlib${ii}$_spocon( 'U', n, work(n+1), n, one, temp1,work(n+n*n+1), iwork(2_${ik}$*n+& m+1), ierr ) end if sconda = one / sqrt(temp1) ! sconda is an estimate of sqrt(||(r^t * r)^(-1)||_1). ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda else sconda = - one end if end if l2pert = l2pert .and. ( abs( a(1_${ik}$,1_${ik}$)/a(nr,nr) ) > sqrt(big1) ) ! if there is no violent scaling, artificial perturbation is not needed. ! phase 3: if ( .not. ( rsvec .or. lsvec ) ) then ! singular values only ! .. transpose a(1:nr,1:n) do p = 1, min( n-1, nr ) call stdlib${ii}$_scopy( n-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) end do ! the following two do-loops introduce small relative perturbation ! into the strict upper triangle of the lower triangular matrix. ! small entries below the main diagonal are also changed. ! this modification is useful if the computing environment does not ! provide/allow flush to zero underflow, for it prevents many ! annoying denormalized numbers in case of strongly scaled matrices. ! the perturbation is structured so that it does not introduce any ! new perturbation of the singular values, and it does not destroy ! the job done by the preconditioner. ! the licence for this perturbation is in the variable l2pert, which ! should be .false. if flush to zero underflow is active. if ( .not. almort ) then if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=sp) do q = 1, nr temp1 = xsc*abs(a(q,q)) do p = 1, n if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = sign( & temp1, a(p,q) ) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'U', nr-1,nr-1, zero,zero, a(1_${ik}$,2_${ik}$),lda ) end if ! Second Preconditioning Using The Qr Factorization call stdlib${ii}$_sgeqrf( n,nr, a,lda, work, work(n+1),lwork-n, ierr ) ! And Transpose Upper To Lower Triangular do p = 1, nr - 1 call stdlib${ii}$_scopy( nr-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) end do end if ! row-cyclic jacobi svd algorithm with column pivoting ! .. again some perturbation (a "background noise") is added ! to drown denormals if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=sp) do q = 1, nr temp1 = xsc*abs(a(q,q)) do p = 1, nr if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = sign( & temp1, a(p,q) ) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'U', nr-1, nr-1, zero, zero, a(1_${ik}$,2_${ik}$), lda ) end if ! .. and one-sided jacobi rotations are started on a lower ! triangular matrix (plus perturbation which is ignored in ! the part which destroys triangular form (confusing?!)) call stdlib${ii}$_sgesvj( 'L', 'NOU', 'NOV', nr, nr, a, lda, sva,n, v, ldv, work, & lwork, info ) scalem = work(1_${ik}$) numrank = nint(work(2_${ik}$),KIND=${ik}$) else if ( rsvec .and. ( .not. lsvec ) ) then ! -> singular values and right singular vectors <- if ( almort ) then ! In This Case Nr Equals N do p = 1, nr call stdlib${ii}$_scopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'UPPER', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_sgesvj( 'L','U','N', n, nr, v,ldv, sva, nr, a,lda,work, lwork, info ) scalem = work(1_${ik}$) numrank = nint(work(2_${ik}$),KIND=${ik}$) else ! .. two more qr factorizations ( one qrf is not enough, two require ! accumulated product of jacobi rotations, three are perfect ) if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'LOWER', nr-1, nr-1, zero, zero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_sgelqf( nr, n, a, lda, work, work(n+1), lwork-n, ierr) call stdlib${ii}$_slacpy( 'LOWER', nr, nr, a, lda, v, ldv ) if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'UPPER', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_sgeqrf( nr, nr, v, ldv, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr call stdlib${ii}$_scopy( nr-p+1, v(p,p), ldv, v(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'UPPER', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_sgesvj( 'LOWER', 'U','N', nr, nr, v,ldv, sva, nr, u,ldu, work(n+1), & lwork-n, info ) scalem = work(n+1) numrank = nint(work(n+2),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_slaset( 'A',n-nr, nr, zero,zero, v(nr+1,1_${ik}$), ldv ) call stdlib${ii}$_slaset( 'A',nr, n-nr, zero,zero, v(1_${ik}$,nr+1), ldv ) call stdlib${ii}$_slaset( 'A',n-nr,n-nr,zero,one, v(nr+1,nr+1), ldv ) end if call stdlib${ii}$_sormlq( 'LEFT', 'TRANSPOSE', n, n, nr, a, lda, work,v, ldv, work(n+1), & lwork-n, ierr ) end if do p = 1, n call stdlib${ii}$_scopy( n, v(p,1_${ik}$), ldv, a(iwork(p),1_${ik}$), lda ) end do call stdlib${ii}$_slacpy( 'ALL', n, n, a, lda, v, ldv ) if ( transp ) then call stdlib${ii}$_slacpy( 'ALL', n, n, v, ldv, u, ldu ) end if else if ( lsvec .and. ( .not. rsvec ) ) then ! Singular Values And Left Singular Vectors ! Second Preconditioning Step To Avoid Need To Accumulate ! jacobi rotations in the jacobi iterations. do p = 1, nr call stdlib${ii}$_scopy( n-p+1, a(p,p), lda, u(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'UPPER', nr-1, nr-1, zero, zero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_sgeqrf( n, nr, u, ldu, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr - 1 call stdlib${ii}$_scopy( nr-p, u(p,p+1), ldu, u(p+1,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'UPPER', nr-1, nr-1, zero, zero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_sgesvj( 'LOWER', 'U', 'N', nr,nr, u, ldu, sva, nr, a,lda, work(n+1), & lwork-n, info ) scalem = work(n+1) numrank = nint(work(n+2),KIND=${ik}$) if ( nr < m ) then call stdlib${ii}$_slaset( 'A', m-nr, nr,zero, zero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_slaset( 'A',nr, n1-nr, zero, zero, u(1_${ik}$,nr+1), ldu ) call stdlib${ii}$_slaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if call stdlib${ii}$_sormqr( 'LEFT', 'NO TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) if ( rowpiv )call stdlib${ii}$_slaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) do p = 1, n1 xsc = one / stdlib${ii}$_snrm2( m, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_sscal( m, xsc, u(1_${ik}$,p), 1_${ik}$ ) end do if ( transp ) then call stdlib${ii}$_slacpy( 'ALL', n, n, u, ldu, v, ldv ) end if else ! Full Svd if ( .not. jracc ) then if ( .not. almort ) then ! second preconditioning step (qrf [with pivoting]) ! note that the composition of transpose, qrf and transpose is ! equivalent to an lqf call. since in many libraries the qrf ! seems to be better optimized than the lqf, we do explicit ! transpose and use the qrf. this is subject to changes in an ! optimized implementation of stdlib${ii}$_sgejsv. do p = 1, nr call stdlib${ii}$_scopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) end do ! The Following Two Loops Perturb Small Entries To Avoid ! denormals in the second qr factorization, where they are ! as good as zeros. this is done to avoid painfully slow ! computation with denormals. the relative size of the perturbation ! is a parameter that can be changed by the implementer. ! this perturbation device will be obsolete on machines with ! properly implemented arithmetic. ! to switch it off, set l2pert=.false. to remove it from the ! code, remove the action under l2pert=.true., leave the else part. ! the following two loops should be blocked and fused with the ! transposed copy above. if ( l2pert ) then xsc = sqrt(small) do q = 1, nr temp1 = xsc*abs( v(q,q) ) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = & sign( temp1, v(p,q) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'U', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) end if ! estimate the row scaled condition number of r1 ! (if r1 is rectangular, n > nr, then the condition number ! of the leading nr x nr submatrix is estimated.) call stdlib${ii}$_slacpy( 'L', nr, nr, v, ldv, work(2_${ik}$*n+1), nr ) do p = 1, nr temp1 = stdlib${ii}$_snrm2(nr-p+1,work(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) call stdlib${ii}$_sscal(nr-p+1,one/temp1,work(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) end do call stdlib${ii}$_spocon('LOWER',nr,work(2_${ik}$*n+1),nr,one,temp1,work(2_${ik}$*n+nr*nr+1),iwork(m+& 2_${ik}$*n+1),ierr) condr1 = one / sqrt(temp1) ! Here Need A Second Opinion On The Condition Number ! Then Assume Worst Case Scenario ! r1 is ok for inverse <=> condr1 < real(n,KIND=sp) ! more conservative <=> condr1 < sqrt(real(n,KIND=sp)) cond_ok = sqrt(real(nr,KIND=sp)) ! [tp] cond_ok is a tuning parameter. if ( condr1 < cond_ok ) then ! .. the second qrf without pivoting. note: in an optimized ! implementation, this qrf should be implemented as the qrf ! of a lower triangular matrix. ! r1^t = q2 * r2 call stdlib${ii}$_sgeqrf( n, nr, v, ldv, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small)/epsln do p = 2, nr do q = 1, p - 1 temp1 = xsc * min(abs(v(p,p)),abs(v(q,q))) if ( abs(v(q,p)) <= temp1 )v(q,p) = sign( temp1, v(q,p) ) end do end do end if if ( nr /= n )call stdlib${ii}$_slacpy( 'A', n, nr, v, ldv, work(2_${ik}$*n+1), n ) ! .. save ... ! This Transposed Copy Should Be Better Than Naive do p = 1, nr - 1 call stdlib${ii}$_scopy( nr-p, v(p,p+1), ldv, v(p+1,p), 1_${ik}$ ) end do condr2 = condr1 else ! .. ill-conditioned case: second qrf with pivoting ! note that windowed pivoting would be equally good ! numerically, and more run-time efficient. so, in ! an optimal implementation, the next call to stdlib${ii}$_sgeqp3 ! should be replaced with eg. call sgeqpx (acm toms #782) ! with properly (carefully) chosen parameters. ! r1^t * p2 = q2 * r2 do p = 1, nr iwork(n+p) = 0_${ik}$ end do call stdlib${ii}$_sgeqp3( n, nr, v, ldv, iwork(n+1), work(n+1),work(2_${ik}$*n+1), lwork-& 2_${ik}$*n, ierr ) ! * call stdlib${ii}$_sgeqrf( n, nr, v, ldv, work(n+1), work(2*n+1), ! * $ lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 temp1 = xsc * min(abs(v(p,p)),abs(v(q,q))) if ( abs(v(q,p)) <= temp1 )v(q,p) = sign( temp1, v(q,p) ) end do end do end if call stdlib${ii}$_slacpy( 'A', n, nr, v, ldv, work(2_${ik}$*n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 temp1 = xsc * min(abs(v(p,p)),abs(v(q,q))) v(p,q) = - sign( temp1, v(q,p) ) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'L',nr-1,nr-1,zero,zero,v(2_${ik}$,1_${ik}$),ldv ) end if ! now, compute r2 = l3 * q3, the lq factorization. call stdlib${ii}$_sgelqf( nr, nr, v, ldv, work(2_${ik}$*n+n*nr+1),work(2_${ik}$*n+n*nr+nr+1), & lwork-2*n-n*nr-nr, ierr ) ! And Estimate The Condition Number call stdlib${ii}$_slacpy( 'L',nr,nr,v,ldv,work(2_${ik}$*n+n*nr+nr+1),nr ) do p = 1, nr temp1 = stdlib${ii}$_snrm2( p, work(2_${ik}$*n+n*nr+nr+p), nr ) call stdlib${ii}$_sscal( p, one/temp1, work(2_${ik}$*n+n*nr+nr+p), nr ) end do call stdlib${ii}$_spocon( 'L',nr,work(2_${ik}$*n+n*nr+nr+1),nr,one,temp1,work(2_${ik}$*n+n*nr+nr+& nr*nr+1),iwork(m+2*n+1),ierr ) condr2 = one / sqrt(temp1) if ( condr2 >= cond_ok ) then ! Save The Householder Vectors Used For Q3 ! (this overwrites the copy of r2, as it will not be ! needed in this branch, but it does not overwritte the ! huseholder vectors of q2.). call stdlib${ii}$_slacpy( 'U', nr, nr, v, ldv, work(2_${ik}$*n+1), n ) ! And The Rest Of The Information On Q3 Is In ! work(2*n+n*nr+1:2*n+n*nr+n) end if end if if ( l2pert ) then xsc = sqrt(small) do q = 2, nr temp1 = xsc * v(q,q) do p = 1, q - 1 ! v(p,q) = - sign( temp1, v(q,p) ) v(p,q) = - sign( temp1, v(p,q) ) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'U', nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$), ldv ) end if ! second preconditioning finished; continue with jacobi svd ! the input matrix is lower trinagular. ! recover the right singular vectors as solution of a well ! conditioned triangular matrix equation. if ( condr1 < cond_ok ) then call stdlib${ii}$_sgesvj( 'L','U','N',nr,nr,v,ldv,sva,nr,u,ldu,work(2_${ik}$*n+n*nr+nr+1),& lwork-2*n-n*nr-nr,info ) scalem = work(2_${ik}$*n+n*nr+nr+1) numrank = nint(work(2_${ik}$*n+n*nr+nr+2),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_scopy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_sscal( nr, sva(p), v(1_${ik}$,p), 1_${ik}$ ) end do ! Pick The Right Matrix Equation And Solve It if ( nr == n ) then ! :)) .. best case, r1 is inverted. the solution of this matrix ! equation is q2*v2 = the product of the jacobi rotations ! used in stdlib${ii}$_sgesvj, premultiplied with the orthogonal matrix ! from the second qr factorization. call stdlib${ii}$_strsm( 'L','U','N','N', nr,nr,one, a,lda, v,ldv ) else ! .. r1 is well conditioned, but non-square. transpose(r2) ! is inverted to get the product of the jacobi rotations ! used in stdlib${ii}$_sgesvj. the q-factor from the second qr ! factorization is then built in explicitly. call stdlib${ii}$_strsm('L','U','T','N',nr,nr,one,work(2_${ik}$*n+1),n,v,ldv) if ( nr < n ) then call stdlib${ii}$_slaset('A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_slaset('A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_slaset('A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_sormqr('L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr) end if else if ( condr2 < cond_ok ) then ! :) .. the input matrix a is very likely a relative of ! the kahan matrix :) ! the matrix r2 is inverted. the solution of the matrix equation ! is q3^t*v3 = the product of the jacobi rotations (appplied to ! the lower triangular l3 from the lq factorization of ! r2=l3*q3), pre-multiplied with the transposed q3. call stdlib${ii}$_sgesvj( 'L', 'U', 'N', nr, nr, v, ldv, sva, nr, u,ldu, work(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr, info ) scalem = work(2_${ik}$*n+n*nr+nr+1) numrank = nint(work(2_${ik}$*n+n*nr+nr+2),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_scopy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_sscal( nr, sva(p), u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_strsm('L','U','N','N',nr,nr,one,work(2_${ik}$*n+1),n,u,ldu) ! Apply The Permutation From The Second Qr Factorization do q = 1, nr do p = 1, nr work(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do end do if ( nr < n ) then call stdlib${ii}$_slaset( 'A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_slaset( 'A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_slaset( 'A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_sormqr( 'L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) else ! last line of defense. ! #:( this is a rather pathological case: no scaled condition ! improvement after two pivoted qr factorizations. other ! possibility is that the rank revealing qr factorization ! or the condition estimator has failed, or the cond_ok ! is set very close to one (which is unnecessary). normally, ! this branch should never be executed, but in rare cases of ! failure of the rrqr or condition estimator, the last line of ! defense ensures that stdlib${ii}$_sgejsv completes the task. ! compute the full svd of l3 using stdlib${ii}$_sgesvj with explicit ! accumulation of jacobi rotations. call stdlib${ii}$_sgesvj( 'L', 'U', 'V', nr, nr, v, ldv, sva, nr, u,ldu, work(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr, info ) scalem = work(2_${ik}$*n+n*nr+nr+1) numrank = nint(work(2_${ik}$*n+n*nr+nr+2),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_slaset( 'A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_slaset( 'A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_slaset( 'A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_sormqr( 'L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) call stdlib${ii}$_sormlq( 'L', 'T', nr, nr, nr, work(2_${ik}$*n+1), n,work(2_${ik}$*n+n*nr+1), u, & ldu, work(2_${ik}$*n+n*nr+nr+1),lwork-2*n-n*nr-nr, ierr ) do q = 1, nr do p = 1, nr work(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do end do end if ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=sp)) * epsln do q = 1, n do p = 1, n work(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_snrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_sscal( n, xsc, & v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_slaset( 'A', m-nr, nr, zero, zero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_slaset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_slaset('A',m-nr,n1-nr,zero,one,u(nr+1,nr+1),ldu) end if end if ! the q matrix from the first qrf is built into the left singular ! matrix u. this applies to all cases. call stdlib${ii}$_sormqr( 'LEFT', 'NO_TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) ! the columns of u are normalized. the cost is o(m*n) flops. temp1 = sqrt(real(m,KIND=sp)) * epsln do p = 1, nr xsc = one / stdlib${ii}$_snrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_sscal( m, xsc, & u(1_${ik}$,p), 1_${ik}$ ) end do ! if the initial qrf is computed with row pivoting, the left ! singular vectors must be adjusted. if ( rowpiv )call stdlib${ii}$_slaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) else ! The Initial Matrix A Has Almost Orthogonal Columns And ! the second qrf is not needed call stdlib${ii}$_slacpy( 'UPPER', n, n, a, lda, work(n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, n temp1 = xsc * work( n + (p-1)*n + p ) do q = 1, p - 1 work(n+(q-1)*n+p)=-sign(temp1,work(n+(p-1)*n+q)) end do end do else call stdlib${ii}$_slaset( 'LOWER',n-1,n-1,zero,zero,work(n+2),n ) end if call stdlib${ii}$_sgesvj( 'UPPER', 'U', 'N', n, n, work(n+1), n, sva,n, u, ldu, work(n+& n*n+1), lwork-n-n*n, info ) scalem = work(n+n*n+1) numrank = nint(work(n+n*n+2),KIND=${ik}$) do p = 1, n call stdlib${ii}$_scopy( n, work(n+(p-1)*n+1), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_sscal( n, sva(p), work(n+(p-1)*n+1), 1_${ik}$ ) end do call stdlib${ii}$_strsm( 'LEFT', 'UPPER', 'NOTRANS', 'NO UD', n, n,one, a, lda, work(n+& 1_${ik}$), n ) do p = 1, n call stdlib${ii}$_scopy( n, work(n+p), n, v(iwork(p),1_${ik}$), ldv ) end do temp1 = sqrt(real(n,KIND=sp))*epsln do p = 1, n xsc = one / stdlib${ii}$_snrm2( n, v(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_sscal( n, xsc, & v(1_${ik}$,p), 1_${ik}$ ) end do ! assemble the left singular vector matrix u (m x n). if ( n < m ) then call stdlib${ii}$_slaset( 'A', m-n, n, zero, zero, u(n+1,1_${ik}$), ldu ) if ( n < n1 ) then call stdlib${ii}$_slaset( 'A',n, n1-n, zero, zero, u(1_${ik}$,n+1),ldu ) call stdlib${ii}$_slaset( 'A',m-n,n1-n, zero, one,u(n+1,n+1),ldu ) end if end if call stdlib${ii}$_sormqr( 'LEFT', 'NO TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) temp1 = sqrt(real(m,KIND=sp))*epsln do p = 1, n1 xsc = one / stdlib${ii}$_snrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_sscal( m, xsc, & u(1_${ik}$,p), 1_${ik}$ ) end do if ( rowpiv )call stdlib${ii}$_slaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) end if ! end of the >> almost orthogonal case << in the full svd else ! this branch deploys a preconditioned jacobi svd with explicitly ! accumulated rotations. it is included as optional, mainly for ! experimental purposes. it does perform well, and can also be used. ! in this implementation, this branch will be automatically activated ! if the condition number sigma_max(a) / sigma_min(a) is predicted ! to be greater than the overflow threshold. this is because the ! a posteriori computation of the singular vectors assumes robust ! implementation of blas and some lapack procedures, capable of working ! in presence of extreme values. since that is not always the case, ... do p = 1, nr call stdlib${ii}$_scopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 1, nr temp1 = xsc*abs( v(q,q) ) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = sign(& temp1, v(p,q) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_slaset( 'U', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) end if call stdlib${ii}$_sgeqrf( n, nr, v, ldv, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) call stdlib${ii}$_slacpy( 'L', n, nr, v, ldv, work(2_${ik}$*n+1), n ) do p = 1, nr call stdlib${ii}$_scopy( nr-p+1, v(p,p), ldv, u(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 2, nr do p = 1, q - 1 temp1 = xsc * min(abs(u(p,p)),abs(u(q,q))) u(p,q) = - sign( temp1, u(q,p) ) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_slaset('U', nr-1, nr-1, zero, zero, u(1_${ik}$,2_${ik}$), ldu ) end if call stdlib${ii}$_sgesvj( 'L', 'U', 'V', nr, nr, u, ldu, sva,n, v, ldv, work(2_${ik}$*n+n*nr+1), & lwork-2*n-n*nr, info ) scalem = work(2_${ik}$*n+n*nr+1) numrank = nint(work(2_${ik}$*n+n*nr+2),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_slaset( 'A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_slaset( 'A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_slaset( 'A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_sormqr( 'L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+n*nr+nr+1)& ,lwork-2*n-n*nr-nr,ierr ) ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=sp)) * epsln do q = 1, n do p = 1, n work(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_snrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_sscal( n, xsc, & v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_slaset( 'A', m-nr, nr, zero, zero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_slaset( 'A',nr, n1-nr, zero, zero, u(1_${ik}$,nr+1),ldu ) call stdlib${ii}$_slaset( 'A',m-nr,n1-nr, zero, one,u(nr+1,nr+1),ldu ) end if end if call stdlib${ii}$_sormqr( 'LEFT', 'NO TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) if ( rowpiv )call stdlib${ii}$_slaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) end if if ( transp ) then ! .. swap u and v because the procedure worked on a^t do p = 1, n call stdlib${ii}$_sswap( n, u(1_${ik}$,p), 1_${ik}$, v(1_${ik}$,p), 1_${ik}$ ) end do end if end if ! end of the full svd ! undo scaling, if necessary (and possible) if ( uscal2 <= (big/sva(1_${ik}$))*uscal1 ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, uscal1, uscal2, nr, 1_${ik}$, sva, n, ierr ) uscal1 = one uscal2 = one end if if ( nr < n ) then do p = nr+1, n sva(p) = zero end do end if work(1_${ik}$) = uscal2 * scalem work(2_${ik}$) = uscal1 if ( errest ) work(3_${ik}$) = sconda if ( lsvec .and. rsvec ) then work(4_${ik}$) = condr1 work(5_${ik}$) = condr2 end if if ( l2tran ) then work(6_${ik}$) = entra work(7_${ik}$) = entrat end if iwork(1_${ik}$) = nr iwork(2_${ik}$) = numrank iwork(3_${ik}$) = warning return end subroutine stdlib${ii}$_sgejsv pure module subroutine stdlib${ii}$_dgejsv( joba, jobu, jobv, jobr, jobt, jobp,m, n, a, lda, sva, u, ldu, & !! DGEJSV computes the singular value decomposition (SVD) of a real M-by-N !! matrix [A], where M >= N. The SVD of [A] is written as !! [A] = [U] * [SIGMA] * [V]^t, !! where [SIGMA] is an N-by-N (M-by-N) matrix which is zero except for its N !! diagonal elements, [U] is an M-by-N (or M-by-M) orthonormal matrix, and !! [V] is an N-by-N orthogonal matrix. The diagonal elements of [SIGMA] are !! the singular values of [A]. The columns of [U] and [V] are the left and !! the right singular vectors of [A], respectively. The matrices [U] and [V] !! are computed and stored in the arrays U and V, respectively. The diagonal !! of [SIGMA] is computed and stored in the array SVA. !! DGEJSV can sometimes compute tiny singular values and their singular vectors much !! more accurately than other SVD routines, see below under Further Details. v, ldv,work, lwork, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldu, ldv, lwork, m, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: sva(n), u(ldu,*), v(ldv,*), work(lwork) integer(${ik}$), intent(out) :: iwork(*) character, intent(in) :: joba, jobp, jobr, jobt, jobu, jobv ! =========================================================================== ! Local Scalars real(dp) :: aapp, aaqq, aatmax, aatmin, big, big1, cond_ok, condr1, condr2, entra, & entrat, epsln, maxprj, scalem, sconda, sfmin, small, temp1, uscal1, uscal2, xsc integer(${ik}$) :: ierr, n1, nr, numrank, p, q, warning logical(lk) :: almort, defr, errest, goscal, jracc, kill, lsvec, l2aber, l2kill, & l2pert, l2rank, l2tran, noscal, rowpiv, rsvec, transp ! Intrinsic Functions ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) .or. stdlib_lsame( jobu, 'F' ) jracc = stdlib_lsame( jobv, 'J' ) rsvec = stdlib_lsame( jobv, 'V' ) .or. jracc rowpiv = stdlib_lsame( joba, 'F' ) .or. stdlib_lsame( joba, 'G' ) l2rank = stdlib_lsame( joba, 'R' ) l2aber = stdlib_lsame( joba, 'A' ) errest = stdlib_lsame( joba, 'E' ) .or. stdlib_lsame( joba, 'G' ) l2tran = stdlib_lsame( jobt, 'T' ) l2kill = stdlib_lsame( jobr, 'R' ) defr = stdlib_lsame( jobr, 'N' ) l2pert = stdlib_lsame( jobp, 'P' ) if ( .not.(rowpiv .or. l2rank .or. l2aber .or.errest .or. stdlib_lsame( joba, 'C' ) )) & then info = - 1_${ik}$ else if ( .not.( lsvec .or. stdlib_lsame( jobu, 'N' ) .or.stdlib_lsame( jobu, 'W' )) )& then info = - 2_${ik}$ else if ( .not.( rsvec .or. stdlib_lsame( jobv, 'N' ) .or.stdlib_lsame( jobv, 'W' )) & .or. ( jracc .and. (.not.lsvec) ) ) then info = - 3_${ik}$ else if ( .not. ( l2kill .or. defr ) ) then info = - 4_${ik}$ else if ( .not. ( l2tran .or. stdlib_lsame( jobt, 'N' ) ) ) then info = - 5_${ik}$ else if ( .not. ( l2pert .or. stdlib_lsame( jobp, 'N' ) ) ) then info = - 6_${ik}$ else if ( m < 0_${ik}$ ) then info = - 7_${ik}$ else if ( ( n < 0_${ik}$ ) .or. ( n > m ) ) then info = - 8_${ik}$ else if ( lda < m ) then info = - 10_${ik}$ else if ( lsvec .and. ( ldu < m ) ) then info = - 13_${ik}$ else if ( rsvec .and. ( ldv < n ) ) then info = - 15_${ik}$ else if ( (.not.(lsvec .or. rsvec .or. errest).and.(lwork < max(7_${ik}$,4_${ik}$*n+1,2_${ik}$*m+n))) .or.(& .not.(lsvec .or. rsvec) .and. errest .and.(lwork < max(7_${ik}$,4_${ik}$*n+n*n,2_${ik}$*m+n))) .or.(lsvec & .and. (.not.rsvec) .and. (lwork < max(7_${ik}$,2_${ik}$*m+n,4_${ik}$*n+1))).or.(rsvec .and. (.not.lsvec) & .and. (lwork < max(7_${ik}$,2_${ik}$*m+n,4_${ik}$*n+1))).or.(lsvec .and. rsvec .and. (.not.jracc) .and.(& lwork big ) then info = - 9_${ik}$ call stdlib${ii}$_xerbla( 'DGEJSV', -info ) return end if aaqq = sqrt(aaqq) if ( ( aapp < (big / aaqq) ) .and. noscal ) then sva(p) = aapp * aaqq else noscal = .false. sva(p) = aapp * ( aaqq * scalem ) if ( goscal ) then goscal = .false. call stdlib${ii}$_dscal( p-1, scalem, sva, 1_${ik}$ ) end if end if end do if ( noscal ) scalem = one aapp = zero aaqq = big do p = 1, n aapp = max( aapp, sva(p) ) if ( sva(p) /= zero ) aaqq = min( aaqq, sva(p) ) end do ! quick return for zero m x n matrix ! #:) if ( aapp == zero ) then if ( lsvec ) call stdlib${ii}$_dlaset( 'G', m, n1, zero, one, u, ldu ) if ( rsvec ) call stdlib${ii}$_dlaset( 'G', n, n, zero, one, v, ldv ) work(1_${ik}$) = one work(2_${ik}$) = one if ( errest ) work(3_${ik}$) = one if ( lsvec .and. rsvec ) then work(4_${ik}$) = one work(5_${ik}$) = one end if if ( l2tran ) then work(6_${ik}$) = zero work(7_${ik}$) = zero end if iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ iwork(3_${ik}$) = 0_${ik}$ return end if ! issue warning if denormalized column norms detected. override the ! high relative accuracy request. issue licence to kill columns ! (set them to zero) whose norm is less than sigma_max / big (roughly). ! #:( warning = 0_${ik}$ if ( aaqq <= sfmin ) then l2rank = .true. l2kill = .true. warning = 1_${ik}$ end if ! quick return for one-column matrix ! #:) if ( n == 1_${ik}$ ) then if ( lsvec ) then call stdlib${ii}$_dlascl( 'G',0_${ik}$,0_${ik}$,sva(1_${ik}$),scalem, m,1_${ik}$,a(1_${ik}$,1_${ik}$),lda,ierr ) call stdlib${ii}$_dlacpy( 'A', m, 1_${ik}$, a, lda, u, ldu ) ! computing all m left singular vectors of the m x 1 matrix if ( n1 /= n ) then call stdlib${ii}$_dgeqrf( m, n, u,ldu, work, work(n+1),lwork-n,ierr ) call stdlib${ii}$_dorgqr( m,n1,1_${ik}$, u,ldu,work,work(n+1),lwork-n,ierr ) call stdlib${ii}$_dcopy( m, a(1_${ik}$,1_${ik}$), 1_${ik}$, u(1_${ik}$,1_${ik}$), 1_${ik}$ ) end if end if if ( rsvec ) then v(1_${ik}$,1_${ik}$) = one end if if ( sva(1_${ik}$) < (big*scalem) ) then sva(1_${ik}$) = sva(1_${ik}$) / scalem scalem = one end if work(1_${ik}$) = one / scalem work(2_${ik}$) = one if ( sva(1_${ik}$) /= zero ) then iwork(1_${ik}$) = 1_${ik}$ if ( ( sva(1_${ik}$) / scalem) >= sfmin ) then iwork(2_${ik}$) = 1_${ik}$ else iwork(2_${ik}$) = 0_${ik}$ end if else iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ end if iwork(3_${ik}$) = 0_${ik}$ if ( errest ) work(3_${ik}$) = one if ( lsvec .and. rsvec ) then work(4_${ik}$) = one work(5_${ik}$) = one end if if ( l2tran ) then work(6_${ik}$) = zero work(7_${ik}$) = zero end if return end if transp = .false. l2tran = l2tran .and. ( m == n ) aatmax = -one aatmin = big if ( rowpiv .or. l2tran ) then ! compute the row norms, needed to determine row pivoting sequence ! (in the case of heavily row weighted a, row pivoting is strongly ! advised) and to collect information needed to compare the ! structures of a * a^t and a^t * a (in the case l2tran==.true.). if ( l2tran ) then do p = 1, m xsc = zero temp1 = one call stdlib${ii}$_dlassq( n, a(p,1_${ik}$), lda, xsc, temp1 ) ! stdlib${ii}$_dlassq gets both the ell_2 and the ell_infinity norm ! in one pass through the vector work(m+n+p) = xsc * scalem work(n+p) = xsc * (scalem*sqrt(temp1)) aatmax = max( aatmax, work(n+p) ) if (work(n+p) /= zero) aatmin = min(aatmin,work(n+p)) end do else do p = 1, m work(m+n+p) = scalem*abs( a(p,stdlib${ii}$_idamax(n,a(p,1_${ik}$),lda)) ) aatmax = max( aatmax, work(m+n+p) ) aatmin = min( aatmin, work(m+n+p) ) end do end if end if ! for square matrix a try to determine whether a^t would be better ! input for the preconditioned jacobi svd, with faster convergence. ! the decision is based on an o(n) function of the vector of column ! and row norms of a, based on the shannon entropy. this should give ! the right choice in most cases when the difference actually matters. ! it may fail and pick the slower converging side. entra = zero entrat = zero if ( l2tran ) then xsc = zero temp1 = one call stdlib${ii}$_dlassq( n, sva, 1_${ik}$, xsc, temp1 ) temp1 = one / temp1 entra = zero do p = 1, n big1 = ( ( sva(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entra = entra + big1 * log(big1) end do entra = - entra / log(real(n,KIND=dp)) ! now, sva().^2/trace(a^t * a) is a point in the probability simplex. ! it is derived from the diagonal of a^t * a. do the same with the ! diagonal of a * a^t, compute the entropy of the corresponding ! probability distribution. note that a * a^t and a^t * a have the ! same trace. entrat = zero do p = n+1, n+m big1 = ( ( work(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entrat = entrat + big1 * log(big1) end do entrat = - entrat / log(real(m,KIND=dp)) ! analyze the entropies and decide a or a^t. smaller entropy ! usually means better input for the algorithm. transp = ( entrat < entra ) ! if a^t is better than a, transpose a. if ( transp ) then ! in an optimal implementation, this trivial transpose ! should be replaced with faster transpose. do p = 1, n - 1 do q = p + 1, n temp1 = a(q,p) a(q,p) = a(p,q) a(p,q) = temp1 end do end do do p = 1, n work(m+n+p) = sva(p) sva(p) = work(n+p) end do temp1 = aapp aapp = aatmax aatmax = temp1 temp1 = aaqq aaqq = aatmin aatmin = temp1 kill = lsvec lsvec = rsvec rsvec = kill if ( lsvec ) n1 = n rowpiv = .true. end if end if ! end if l2tran ! scale the matrix so that its maximal singular value remains less ! than sqrt(big) -- the matrix is scaled so that its maximal column ! has euclidean norm equal to sqrt(big/n). the only reason to keep ! sqrt(big) instead of big is the fact that stdlib${ii}$_dgejsv uses lapack and ! blas routines that, in some implementations, are not capable of ! working in the full interval [sfmin,big] and that they may provoke ! overflows in the intermediate results. if the singular values spread ! from sfmin to big, then stdlib${ii}$_dgesvj will compute them. so, in that case, ! one should use stdlib_dgesvj instead of stdlib${ii}$_dgejsv. big1 = sqrt( big ) temp1 = sqrt( big / real(n,KIND=dp) ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, n, 1_${ik}$, sva, n, ierr ) if ( aaqq > (aapp * sfmin) ) then aaqq = ( aaqq / aapp ) * temp1 else aaqq = ( aaqq * temp1 ) / aapp end if temp1 = temp1 * scalem call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, m, n, a, lda, ierr ) ! to undo scaling at the end of this procedure, multiply the ! computed singular values with uscal2 / uscal1. uscal1 = temp1 uscal2 = aapp if ( l2kill ) then ! l2kill enforces computation of nonzero singular values in ! the restricted range of condition number of the initial a, ! sigma_max(a) / sigma_min(a) approx. sqrt(big)/sqrt(sfmin). xsc = sqrt( sfmin ) else xsc = small ! now, if the condition number of a is too big, ! sigma_max(a) / sigma_min(a) > sqrt(big/n) * epsln / sfmin, ! as a precaution measure, the full svd is computed using stdlib${ii}$_dgesvj ! with accumulated jacobi rotations. this provides numerically ! more robust computation, at the cost of slightly increased run ! time. depending on the concrete implementation of blas and lapack ! (i.e. how they behave in presence of extreme ill-conditioning) the ! implementor may decide to remove this switch. if ( ( aaqq= (temp1*abs(a(1_${ik}$,1_${ik}$))) ) then nr = nr + 1_${ik}$ else exit loop_3002 end if end do loop_3002 else if ( l2rank ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r1 is used as the criterion for ! close-to-rank-deficient. temp1 = sqrt(sfmin) loop_3402: do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < small ) .or.( & l2kill .and. (abs(a(p,p)) < temp1) ) ) exit loop_3402 nr = nr + 1_${ik}$ end do loop_3402 else ! the goal is high relative accuracy. however, if the matrix ! has high scaled condition number the relative accuracy is in ! general not feasible. later on, a condition number estimator ! will be deployed to estimate the scaled condition number. ! here we just remove the underflowed part of the triangular ! factor. this prevents the situation in which the code is ! working hard to get the accuracy not warranted by the data. temp1 = sqrt(sfmin) loop_3302: do p = 2, n if ( ( abs(a(p,p)) < small ) .or.( l2kill .and. (abs(a(p,p)) < temp1) ) ) exit loop_3302 nr = nr + 1_${ik}$ end do loop_3302 end if almort = .false. if ( nr == n ) then maxprj = one do p = 2, n temp1 = abs(a(p,p)) / sva(iwork(p)) maxprj = min( maxprj, temp1 ) end do if ( maxprj**2_${ik}$ >= one - real(n,KIND=dp)*epsln ) almort = .true. end if sconda = - one condr1 = - one condr2 = - one if ( errest ) then if ( n == nr ) then if ( rsvec ) then ! V Is Available As Workspace call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, v, ldv ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_dscal( p, one/temp1, v(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_dpocon( 'U', n, v, ldv, one, temp1,work(n+1), iwork(2_${ik}$*n+m+1), & ierr ) else if ( lsvec ) then ! U Is Available As Workspace call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, u, ldu ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_dscal( p, one/temp1, u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_dpocon( 'U', n, u, ldu, one, temp1,work(n+1), iwork(2_${ik}$*n+m+1), & ierr ) else call stdlib${ii}$_dlacpy( 'U', n, n, a, lda, work(n+1), n ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_dscal( p, one/temp1, work(n+(p-1)*n+1), 1_${ik}$ ) end do ! The Columns Of R Are Scaled To Have Unit Euclidean Lengths call stdlib${ii}$_dpocon( 'U', n, work(n+1), n, one, temp1,work(n+n*n+1), iwork(2_${ik}$*n+& m+1), ierr ) end if sconda = one / sqrt(temp1) ! sconda is an estimate of sqrt(||(r^t * r)^(-1)||_1). ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda else sconda = - one end if end if l2pert = l2pert .and. ( abs( a(1_${ik}$,1_${ik}$)/a(nr,nr) ) > sqrt(big1) ) ! if there is no violent scaling, artificial perturbation is not needed. ! phase 3: if ( .not. ( rsvec .or. lsvec ) ) then ! singular values only ! .. transpose a(1:nr,1:n) do p = 1, min( n-1, nr ) call stdlib${ii}$_dcopy( n-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) end do ! the following two do-loops introduce small relative perturbation ! into the strict upper triangle of the lower triangular matrix. ! small entries below the main diagonal are also changed. ! this modification is useful if the computing environment does not ! provide/allow flush to zero underflow, for it prevents many ! annoying denormalized numbers in case of strongly scaled matrices. ! the perturbation is structured so that it does not introduce any ! new perturbation of the singular values, and it does not destroy ! the job done by the preconditioner. ! the licence for this perturbation is in the variable l2pert, which ! should be .false. if flush to zero underflow is active. if ( .not. almort ) then if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=dp) do q = 1, nr temp1 = xsc*abs(a(q,q)) do p = 1, n if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = sign( & temp1, a(p,q) ) end do end do else call stdlib${ii}$_dlaset( 'U', nr-1,nr-1, zero,zero, a(1_${ik}$,2_${ik}$),lda ) end if ! Second Preconditioning Using The Qr Factorization call stdlib${ii}$_dgeqrf( n,nr, a,lda, work, work(n+1),lwork-n, ierr ) ! And Transpose Upper To Lower Triangular do p = 1, nr - 1 call stdlib${ii}$_dcopy( nr-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) end do end if ! row-cyclic jacobi svd algorithm with column pivoting ! .. again some perturbation (a "background noise") is added ! to drown denormals if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=dp) do q = 1, nr temp1 = xsc*abs(a(q,q)) do p = 1, nr if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = sign( & temp1, a(p,q) ) end do end do else call stdlib${ii}$_dlaset( 'U', nr-1, nr-1, zero, zero, a(1_${ik}$,2_${ik}$), lda ) end if ! .. and one-sided jacobi rotations are started on a lower ! triangular matrix (plus perturbation which is ignored in ! the part which destroys triangular form (confusing?!)) call stdlib${ii}$_dgesvj( 'L', 'NOU', 'NOV', nr, nr, a, lda, sva,n, v, ldv, work, & lwork, info ) scalem = work(1_${ik}$) numrank = nint(work(2_${ik}$),KIND=${ik}$) else if ( rsvec .and. ( .not. lsvec ) ) then ! -> singular values and right singular vectors <- if ( almort ) then ! In This Case Nr Equals N do p = 1, nr call stdlib${ii}$_dcopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) end do call stdlib${ii}$_dlaset( 'UPPER', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_dgesvj( 'L','U','N', n, nr, v,ldv, sva, nr, a,lda,work, lwork, info ) scalem = work(1_${ik}$) numrank = nint(work(2_${ik}$),KIND=${ik}$) else ! .. two more qr factorizations ( one qrf is not enough, two require ! accumulated product of jacobi rotations, three are perfect ) call stdlib${ii}$_dlaset( 'LOWER', nr-1, nr-1, zero, zero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_dgelqf( nr, n, a, lda, work, work(n+1), lwork-n, ierr) call stdlib${ii}$_dlacpy( 'LOWER', nr, nr, a, lda, v, ldv ) call stdlib${ii}$_dlaset( 'UPPER', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_dgeqrf( nr, nr, v, ldv, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr call stdlib${ii}$_dcopy( nr-p+1, v(p,p), ldv, v(p,p), 1_${ik}$ ) end do call stdlib${ii}$_dlaset( 'UPPER', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_dgesvj( 'LOWER', 'U','N', nr, nr, v,ldv, sva, nr, u,ldu, work(n+1), & lwork, info ) scalem = work(n+1) numrank = nint(work(n+2),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_dlaset( 'A',n-nr, nr, zero,zero, v(nr+1,1_${ik}$), ldv ) call stdlib${ii}$_dlaset( 'A',nr, n-nr, zero,zero, v(1_${ik}$,nr+1), ldv ) call stdlib${ii}$_dlaset( 'A',n-nr,n-nr,zero,one, v(nr+1,nr+1), ldv ) end if call stdlib${ii}$_dormlq( 'LEFT', 'TRANSPOSE', n, n, nr, a, lda, work,v, ldv, work(n+1), & lwork-n, ierr ) end if do p = 1, n call stdlib${ii}$_dcopy( n, v(p,1_${ik}$), ldv, a(iwork(p),1_${ik}$), lda ) end do call stdlib${ii}$_dlacpy( 'ALL', n, n, a, lda, v, ldv ) if ( transp ) then call stdlib${ii}$_dlacpy( 'ALL', n, n, v, ldv, u, ldu ) end if else if ( lsvec .and. ( .not. rsvec ) ) then ! Singular Values And Left Singular Vectors ! Second Preconditioning Step To Avoid Need To Accumulate ! jacobi rotations in the jacobi iterations. do p = 1, nr call stdlib${ii}$_dcopy( n-p+1, a(p,p), lda, u(p,p), 1_${ik}$ ) end do call stdlib${ii}$_dlaset( 'UPPER', nr-1, nr-1, zero, zero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_dgeqrf( n, nr, u, ldu, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr - 1 call stdlib${ii}$_dcopy( nr-p, u(p,p+1), ldu, u(p+1,p), 1_${ik}$ ) end do call stdlib${ii}$_dlaset( 'UPPER', nr-1, nr-1, zero, zero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_dgesvj( 'LOWER', 'U', 'N', nr,nr, u, ldu, sva, nr, a,lda, work(n+1), & lwork-n, info ) scalem = work(n+1) numrank = nint(work(n+2),KIND=${ik}$) if ( nr < m ) then call stdlib${ii}$_dlaset( 'A', m-nr, nr,zero, zero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_dlaset( 'A',nr, n1-nr, zero, zero, u(1_${ik}$,nr+1), ldu ) call stdlib${ii}$_dlaset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if call stdlib${ii}$_dormqr( 'LEFT', 'NO TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) if ( rowpiv )call stdlib${ii}$_dlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) do p = 1, n1 xsc = one / stdlib${ii}$_dnrm2( m, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_dscal( m, xsc, u(1_${ik}$,p), 1_${ik}$ ) end do if ( transp ) then call stdlib${ii}$_dlacpy( 'ALL', n, n, u, ldu, v, ldv ) end if else ! Full Svd if ( .not. jracc ) then if ( .not. almort ) then ! second preconditioning step (qrf [with pivoting]) ! note that the composition of transpose, qrf and transpose is ! equivalent to an lqf call. since in many libraries the qrf ! seems to be better optimized than the lqf, we do explicit ! transpose and use the qrf. this is subject to changes in an ! optimized implementation of stdlib${ii}$_dgejsv. do p = 1, nr call stdlib${ii}$_dcopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) end do ! The Following Two Loops Perturb Small Entries To Avoid ! denormals in the second qr factorization, where they are ! as good as zeros. this is done to avoid painfully slow ! computation with denormals. the relative size of the perturbation ! is a parameter that can be changed by the implementer. ! this perturbation device will be obsolete on machines with ! properly implemented arithmetic. ! to switch it off, set l2pert=.false. to remove it from the ! code, remove the action under l2pert=.true., leave the else part. ! the following two loops should be blocked and fused with the ! transposed copy above. if ( l2pert ) then xsc = sqrt(small) do q = 1, nr temp1 = xsc*abs( v(q,q) ) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = & sign( temp1, v(p,q) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else call stdlib${ii}$_dlaset( 'U', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) end if ! estimate the row scaled condition number of r1 ! (if r1 is rectangular, n > nr, then the condition number ! of the leading nr x nr submatrix is estimated.) call stdlib${ii}$_dlacpy( 'L', nr, nr, v, ldv, work(2_${ik}$*n+1), nr ) do p = 1, nr temp1 = stdlib${ii}$_dnrm2(nr-p+1,work(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) call stdlib${ii}$_dscal(nr-p+1,one/temp1,work(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) end do call stdlib${ii}$_dpocon('LOWER',nr,work(2_${ik}$*n+1),nr,one,temp1,work(2_${ik}$*n+nr*nr+1),iwork(m+& 2_${ik}$*n+1),ierr) condr1 = one / sqrt(temp1) ! Here Need A Second Opinion On The Condition Number ! Then Assume Worst Case Scenario ! r1 is ok for inverse <=> condr1 < real(n,KIND=dp) ! more conservative <=> condr1 < sqrt(real(n,KIND=dp)) cond_ok = sqrt(real(nr,KIND=dp)) ! [tp] cond_ok is a tuning parameter. if ( condr1 < cond_ok ) then ! .. the second qrf without pivoting. note: in an optimized ! implementation, this qrf should be implemented as the qrf ! of a lower triangular matrix. ! r1^t = q2 * r2 call stdlib${ii}$_dgeqrf( n, nr, v, ldv, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small)/epsln do p = 2, nr do q = 1, p - 1 temp1 = xsc * min(abs(v(p,p)),abs(v(q,q))) if ( abs(v(q,p)) <= temp1 )v(q,p) = sign( temp1, v(q,p) ) end do end do end if if ( nr /= n )call stdlib${ii}$_dlacpy( 'A', n, nr, v, ldv, work(2_${ik}$*n+1), n ) ! .. save ... ! This Transposed Copy Should Be Better Than Naive do p = 1, nr - 1 call stdlib${ii}$_dcopy( nr-p, v(p,p+1), ldv, v(p+1,p), 1_${ik}$ ) end do condr2 = condr1 else ! .. ill-conditioned case: second qrf with pivoting ! note that windowed pivoting would be equally good ! numerically, and more run-time efficient. so, in ! an optimal implementation, the next call to stdlib${ii}$_dgeqp3 ! should be replaced with eg. call sgeqpx (acm toms #782) ! with properly (carefully) chosen parameters. ! r1^t * p2 = q2 * r2 do p = 1, nr iwork(n+p) = 0_${ik}$ end do call stdlib${ii}$_dgeqp3( n, nr, v, ldv, iwork(n+1), work(n+1),work(2_${ik}$*n+1), lwork-& 2_${ik}$*n, ierr ) ! * call stdlib${ii}$_dgeqrf( n, nr, v, ldv, work(n+1), work(2*n+1), ! * $ lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 temp1 = xsc * min(abs(v(p,p)),abs(v(q,q))) if ( abs(v(q,p)) <= temp1 )v(q,p) = sign( temp1, v(q,p) ) end do end do end if call stdlib${ii}$_dlacpy( 'A', n, nr, v, ldv, work(2_${ik}$*n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 temp1 = xsc * min(abs(v(p,p)),abs(v(q,q))) v(p,q) = - sign( temp1, v(q,p) ) end do end do else call stdlib${ii}$_dlaset( 'L',nr-1,nr-1,zero,zero,v(2_${ik}$,1_${ik}$),ldv ) end if ! now, compute r2 = l3 * q3, the lq factorization. call stdlib${ii}$_dgelqf( nr, nr, v, ldv, work(2_${ik}$*n+n*nr+1),work(2_${ik}$*n+n*nr+nr+1), & lwork-2*n-n*nr-nr, ierr ) ! And Estimate The Condition Number call stdlib${ii}$_dlacpy( 'L',nr,nr,v,ldv,work(2_${ik}$*n+n*nr+nr+1),nr ) do p = 1, nr temp1 = stdlib${ii}$_dnrm2( p, work(2_${ik}$*n+n*nr+nr+p), nr ) call stdlib${ii}$_dscal( p, one/temp1, work(2_${ik}$*n+n*nr+nr+p), nr ) end do call stdlib${ii}$_dpocon( 'L',nr,work(2_${ik}$*n+n*nr+nr+1),nr,one,temp1,work(2_${ik}$*n+n*nr+nr+& nr*nr+1),iwork(m+2*n+1),ierr ) condr2 = one / sqrt(temp1) if ( condr2 >= cond_ok ) then ! Save The Householder Vectors Used For Q3 ! (this overwrites the copy of r2, as it will not be ! needed in this branch, but it does not overwritte the ! huseholder vectors of q2.). call stdlib${ii}$_dlacpy( 'U', nr, nr, v, ldv, work(2_${ik}$*n+1), n ) ! And The Rest Of The Information On Q3 Is In ! work(2*n+n*nr+1:2*n+n*nr+n) end if end if if ( l2pert ) then xsc = sqrt(small) do q = 2, nr temp1 = xsc * v(q,q) do p = 1, q - 1 ! v(p,q) = - sign( temp1, v(q,p) ) v(p,q) = - sign( temp1, v(p,q) ) end do end do else call stdlib${ii}$_dlaset( 'U', nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$), ldv ) end if ! second preconditioning finished; continue with jacobi svd ! the input matrix is lower trinagular. ! recover the right singular vectors as solution of a well ! conditioned triangular matrix equation. if ( condr1 < cond_ok ) then call stdlib${ii}$_dgesvj( 'L','U','N',nr,nr,v,ldv,sva,nr,u,ldu,work(2_${ik}$*n+n*nr+nr+1),& lwork-2*n-n*nr-nr,info ) scalem = work(2_${ik}$*n+n*nr+nr+1) numrank = nint(work(2_${ik}$*n+n*nr+nr+2),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_dcopy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_dscal( nr, sva(p), v(1_${ik}$,p), 1_${ik}$ ) end do ! Pick The Right Matrix Equation And Solve It if ( nr == n ) then ! :)) .. best case, r1 is inverted. the solution of this matrix ! equation is q2*v2 = the product of the jacobi rotations ! used in stdlib${ii}$_dgesvj, premultiplied with the orthogonal matrix ! from the second qr factorization. call stdlib${ii}$_dtrsm( 'L','U','N','N', nr,nr,one, a,lda, v,ldv ) else ! .. r1 is well conditioned, but non-square. transpose(r2) ! is inverted to get the product of the jacobi rotations ! used in stdlib${ii}$_dgesvj. the q-factor from the second qr ! factorization is then built in explicitly. call stdlib${ii}$_dtrsm('L','U','T','N',nr,nr,one,work(2_${ik}$*n+1),n,v,ldv) if ( nr < n ) then call stdlib${ii}$_dlaset('A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_dlaset('A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_dlaset('A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_dormqr('L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr) end if else if ( condr2 < cond_ok ) then ! :) .. the input matrix a is very likely a relative of ! the kahan matrix :) ! the matrix r2 is inverted. the solution of the matrix equation ! is q3^t*v3 = the product of the jacobi rotations (appplied to ! the lower triangular l3 from the lq factorization of ! r2=l3*q3), pre-multiplied with the transposed q3. call stdlib${ii}$_dgesvj( 'L', 'U', 'N', nr, nr, v, ldv, sva, nr, u,ldu, work(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr, info ) scalem = work(2_${ik}$*n+n*nr+nr+1) numrank = nint(work(2_${ik}$*n+n*nr+nr+2),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_dcopy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_dscal( nr, sva(p), u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_dtrsm('L','U','N','N',nr,nr,one,work(2_${ik}$*n+1),n,u,ldu) ! Apply The Permutation From The Second Qr Factorization do q = 1, nr do p = 1, nr work(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do end do if ( nr < n ) then call stdlib${ii}$_dlaset( 'A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_dlaset( 'A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_dlaset( 'A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_dormqr( 'L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) else ! last line of defense. ! #:( this is a rather pathological case: no scaled condition ! improvement after two pivoted qr factorizations. other ! possibility is that the rank revealing qr factorization ! or the condition estimator has failed, or the cond_ok ! is set very close to one (which is unnecessary). normally, ! this branch should never be executed, but in rare cases of ! failure of the rrqr or condition estimator, the last line of ! defense ensures that stdlib${ii}$_dgejsv completes the task. ! compute the full svd of l3 using stdlib${ii}$_dgesvj with explicit ! accumulation of jacobi rotations. call stdlib${ii}$_dgesvj( 'L', 'U', 'V', nr, nr, v, ldv, sva, nr, u,ldu, work(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr, info ) scalem = work(2_${ik}$*n+n*nr+nr+1) numrank = nint(work(2_${ik}$*n+n*nr+nr+2),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_dlaset( 'A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_dlaset( 'A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_dlaset( 'A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_dormqr( 'L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) call stdlib${ii}$_dormlq( 'L', 'T', nr, nr, nr, work(2_${ik}$*n+1), n,work(2_${ik}$*n+n*nr+1), u, & ldu, work(2_${ik}$*n+n*nr+nr+1),lwork-2*n-n*nr-nr, ierr ) do q = 1, nr do p = 1, nr work(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do end do end if ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=dp)) * epsln do q = 1, n do p = 1, n work(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_dnrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_dscal( n, xsc, & v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_dlaset( 'A', m-nr, nr, zero, zero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_dlaset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_dlaset('A',m-nr,n1-nr,zero,one,u(nr+1,nr+1),ldu) end if end if ! the q matrix from the first qrf is built into the left singular ! matrix u. this applies to all cases. call stdlib${ii}$_dormqr( 'LEFT', 'NO_TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) ! the columns of u are normalized. the cost is o(m*n) flops. temp1 = sqrt(real(m,KIND=dp)) * epsln do p = 1, nr xsc = one / stdlib${ii}$_dnrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_dscal( m, xsc, & u(1_${ik}$,p), 1_${ik}$ ) end do ! if the initial qrf is computed with row pivoting, the left ! singular vectors must be adjusted. if ( rowpiv )call stdlib${ii}$_dlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) else ! The Initial Matrix A Has Almost Orthogonal Columns And ! the second qrf is not needed call stdlib${ii}$_dlacpy( 'UPPER', n, n, a, lda, work(n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, n temp1 = xsc * work( n + (p-1)*n + p ) do q = 1, p - 1 work(n+(q-1)*n+p)=-sign(temp1,work(n+(p-1)*n+q)) end do end do else call stdlib${ii}$_dlaset( 'LOWER',n-1,n-1,zero,zero,work(n+2),n ) end if call stdlib${ii}$_dgesvj( 'UPPER', 'U', 'N', n, n, work(n+1), n, sva,n, u, ldu, work(n+& n*n+1), lwork-n-n*n, info ) scalem = work(n+n*n+1) numrank = nint(work(n+n*n+2),KIND=${ik}$) do p = 1, n call stdlib${ii}$_dcopy( n, work(n+(p-1)*n+1), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_dscal( n, sva(p), work(n+(p-1)*n+1), 1_${ik}$ ) end do call stdlib${ii}$_dtrsm( 'LEFT', 'UPPER', 'NOTRANS', 'NO UD', n, n,one, a, lda, work(n+& 1_${ik}$), n ) do p = 1, n call stdlib${ii}$_dcopy( n, work(n+p), n, v(iwork(p),1_${ik}$), ldv ) end do temp1 = sqrt(real(n,KIND=dp))*epsln do p = 1, n xsc = one / stdlib${ii}$_dnrm2( n, v(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_dscal( n, xsc, & v(1_${ik}$,p), 1_${ik}$ ) end do ! assemble the left singular vector matrix u (m x n). if ( n < m ) then call stdlib${ii}$_dlaset( 'A', m-n, n, zero, zero, u(n+1,1_${ik}$), ldu ) if ( n < n1 ) then call stdlib${ii}$_dlaset( 'A',n, n1-n, zero, zero, u(1_${ik}$,n+1),ldu ) call stdlib${ii}$_dlaset( 'A',m-n,n1-n, zero, one,u(n+1,n+1),ldu ) end if end if call stdlib${ii}$_dormqr( 'LEFT', 'NO TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) temp1 = sqrt(real(m,KIND=dp))*epsln do p = 1, n1 xsc = one / stdlib${ii}$_dnrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_dscal( m, xsc, & u(1_${ik}$,p), 1_${ik}$ ) end do if ( rowpiv )call stdlib${ii}$_dlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) end if ! end of the >> almost orthogonal case << in the full svd else ! this branch deploys a preconditioned jacobi svd with explicitly ! accumulated rotations. it is included as optional, mainly for ! experimental purposes. it does perform well, and can also be used. ! in this implementation, this branch will be automatically activated ! if the condition number sigma_max(a) / sigma_min(a) is predicted ! to be greater than the overflow threshold. this is because the ! a posteriori computation of the singular vectors assumes robust ! implementation of blas and some lapack procedures, capable of working ! in presence of extreme values. since that is not always the case, ... do p = 1, nr call stdlib${ii}$_dcopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 1, nr temp1 = xsc*abs( v(q,q) ) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = sign(& temp1, v(p,q) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else call stdlib${ii}$_dlaset( 'U', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) end if call stdlib${ii}$_dgeqrf( n, nr, v, ldv, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) call stdlib${ii}$_dlacpy( 'L', n, nr, v, ldv, work(2_${ik}$*n+1), n ) do p = 1, nr call stdlib${ii}$_dcopy( nr-p+1, v(p,p), ldv, u(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 2, nr do p = 1, q - 1 temp1 = xsc * min(abs(u(p,p)),abs(u(q,q))) u(p,q) = - sign( temp1, u(q,p) ) end do end do else call stdlib${ii}$_dlaset('U', nr-1, nr-1, zero, zero, u(1_${ik}$,2_${ik}$), ldu ) end if call stdlib${ii}$_dgesvj( 'G', 'U', 'V', nr, nr, u, ldu, sva,n, v, ldv, work(2_${ik}$*n+n*nr+1), & lwork-2*n-n*nr, info ) scalem = work(2_${ik}$*n+n*nr+1) numrank = nint(work(2_${ik}$*n+n*nr+2),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_dlaset( 'A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_dlaset( 'A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_dlaset( 'A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_dormqr( 'L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+n*nr+nr+1)& ,lwork-2*n-n*nr-nr,ierr ) ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=dp)) * epsln do q = 1, n do p = 1, n work(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_dnrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_dscal( n, xsc, & v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_dlaset( 'A', m-nr, nr, zero, zero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_dlaset( 'A',nr, n1-nr, zero, zero, u(1_${ik}$,nr+1),ldu ) call stdlib${ii}$_dlaset( 'A',m-nr,n1-nr, zero, one,u(nr+1,nr+1),ldu ) end if end if call stdlib${ii}$_dormqr( 'LEFT', 'NO TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) if ( rowpiv )call stdlib${ii}$_dlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) end if if ( transp ) then ! .. swap u and v because the procedure worked on a^t do p = 1, n call stdlib${ii}$_dswap( n, u(1_${ik}$,p), 1_${ik}$, v(1_${ik}$,p), 1_${ik}$ ) end do end if end if ! end of the full svd ! undo scaling, if necessary (and possible) if ( uscal2 <= (big/sva(1_${ik}$))*uscal1 ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, uscal1, uscal2, nr, 1_${ik}$, sva, n, ierr ) uscal1 = one uscal2 = one end if if ( nr < n ) then do p = nr+1, n sva(p) = zero end do end if work(1_${ik}$) = uscal2 * scalem work(2_${ik}$) = uscal1 if ( errest ) work(3_${ik}$) = sconda if ( lsvec .and. rsvec ) then work(4_${ik}$) = condr1 work(5_${ik}$) = condr2 end if if ( l2tran ) then work(6_${ik}$) = entra work(7_${ik}$) = entrat end if iwork(1_${ik}$) = nr iwork(2_${ik}$) = numrank iwork(3_${ik}$) = warning return end subroutine stdlib${ii}$_dgejsv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gejsv( joba, jobu, jobv, jobr, jobt, jobp,m, n, a, lda, sva, u, ldu, & !! DGEJSV: computes the singular value decomposition (SVD) of a real M-by-N !! matrix [A], where M >= N. The SVD of [A] is written as !! [A] = [U] * [SIGMA] * [V]^t, !! where [SIGMA] is an N-by-N (M-by-N) matrix which is zero except for its N !! diagonal elements, [U] is an M-by-N (or M-by-M) orthonormal matrix, and !! [V] is an N-by-N orthogonal matrix. The diagonal elements of [SIGMA] are !! the singular values of [A]. The columns of [U] and [V] are the left and !! the right singular vectors of [A], respectively. The matrices [U] and [V] !! are computed and stored in the arrays U and V, respectively. The diagonal !! of [SIGMA] is computed and stored in the array SVA. !! DGEJSV can sometimes compute tiny singular values and their singular vectors much !! more accurately than other SVD routines, see below under Further Details. v, ldv,work, lwork, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldu, ldv, lwork, m, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: sva(n), u(ldu,*), v(ldv,*), work(lwork) integer(${ik}$), intent(out) :: iwork(*) character, intent(in) :: joba, jobp, jobr, jobt, jobu, jobv ! =========================================================================== ! Local Scalars real(${rk}$) :: aapp, aaqq, aatmax, aatmin, big, big1, cond_ok, condr1, condr2, entra, & entrat, epsln, maxprj, scalem, sconda, sfmin, small, temp1, uscal1, uscal2, xsc integer(${ik}$) :: ierr, n1, nr, numrank, p, q, warning logical(lk) :: almort, defr, errest, goscal, jracc, kill, lsvec, l2aber, l2kill, & l2pert, l2rank, l2tran, noscal, rowpiv, rsvec, transp ! Intrinsic Functions ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) .or. stdlib_lsame( jobu, 'F' ) jracc = stdlib_lsame( jobv, 'J' ) rsvec = stdlib_lsame( jobv, 'V' ) .or. jracc rowpiv = stdlib_lsame( joba, 'F' ) .or. stdlib_lsame( joba, 'G' ) l2rank = stdlib_lsame( joba, 'R' ) l2aber = stdlib_lsame( joba, 'A' ) errest = stdlib_lsame( joba, 'E' ) .or. stdlib_lsame( joba, 'G' ) l2tran = stdlib_lsame( jobt, 'T' ) l2kill = stdlib_lsame( jobr, 'R' ) defr = stdlib_lsame( jobr, 'N' ) l2pert = stdlib_lsame( jobp, 'P' ) if ( .not.(rowpiv .or. l2rank .or. l2aber .or.errest .or. stdlib_lsame( joba, 'C' ) )) & then info = - 1_${ik}$ else if ( .not.( lsvec .or. stdlib_lsame( jobu, 'N' ) .or.stdlib_lsame( jobu, 'W' )) )& then info = - 2_${ik}$ else if ( .not.( rsvec .or. stdlib_lsame( jobv, 'N' ) .or.stdlib_lsame( jobv, 'W' )) & .or. ( jracc .and. (.not.lsvec) ) ) then info = - 3_${ik}$ else if ( .not. ( l2kill .or. defr ) ) then info = - 4_${ik}$ else if ( .not. ( l2tran .or. stdlib_lsame( jobt, 'N' ) ) ) then info = - 5_${ik}$ else if ( .not. ( l2pert .or. stdlib_lsame( jobp, 'N' ) ) ) then info = - 6_${ik}$ else if ( m < 0_${ik}$ ) then info = - 7_${ik}$ else if ( ( n < 0_${ik}$ ) .or. ( n > m ) ) then info = - 8_${ik}$ else if ( lda < m ) then info = - 10_${ik}$ else if ( lsvec .and. ( ldu < m ) ) then info = - 13_${ik}$ else if ( rsvec .and. ( ldv < n ) ) then info = - 15_${ik}$ else if ( (.not.(lsvec .or. rsvec .or. errest).and.(lwork < max(7_${ik}$,4_${ik}$*n+1,2_${ik}$*m+n))) .or.(& .not.(lsvec .or. rsvec) .and. errest .and.(lwork < max(7_${ik}$,4_${ik}$*n+n*n,2_${ik}$*m+n))) .or.(lsvec & .and. (.not.rsvec) .and. (lwork < max(7_${ik}$,2_${ik}$*m+n,4_${ik}$*n+1))).or.(rsvec .and. (.not.lsvec) & .and. (lwork < max(7_${ik}$,2_${ik}$*m+n,4_${ik}$*n+1))).or.(lsvec .and. rsvec .and. (.not.jracc) .and.(& lwork big ) then info = - 9_${ik}$ call stdlib${ii}$_xerbla( 'DGEJSV', -info ) return end if aaqq = sqrt(aaqq) if ( ( aapp < (big / aaqq) ) .and. noscal ) then sva(p) = aapp * aaqq else noscal = .false. sva(p) = aapp * ( aaqq * scalem ) if ( goscal ) then goscal = .false. call stdlib${ii}$_${ri}$scal( p-1, scalem, sva, 1_${ik}$ ) end if end if end do if ( noscal ) scalem = one aapp = zero aaqq = big do p = 1, n aapp = max( aapp, sva(p) ) if ( sva(p) /= zero ) aaqq = min( aaqq, sva(p) ) end do ! quick return for zero m x n matrix ! #:) if ( aapp == zero ) then if ( lsvec ) call stdlib${ii}$_${ri}$laset( 'G', m, n1, zero, one, u, ldu ) if ( rsvec ) call stdlib${ii}$_${ri}$laset( 'G', n, n, zero, one, v, ldv ) work(1_${ik}$) = one work(2_${ik}$) = one if ( errest ) work(3_${ik}$) = one if ( lsvec .and. rsvec ) then work(4_${ik}$) = one work(5_${ik}$) = one end if if ( l2tran ) then work(6_${ik}$) = zero work(7_${ik}$) = zero end if iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ iwork(3_${ik}$) = 0_${ik}$ return end if ! issue warning if denormalized column norms detected. override the ! high relative accuracy request. issue licence to kill columns ! (set them to zero) whose norm is less than sigma_max / big (roughly). ! #:( warning = 0_${ik}$ if ( aaqq <= sfmin ) then l2rank = .true. l2kill = .true. warning = 1_${ik}$ end if ! quick return for one-column matrix ! #:) if ( n == 1_${ik}$ ) then if ( lsvec ) then call stdlib${ii}$_${ri}$lascl( 'G',0_${ik}$,0_${ik}$,sva(1_${ik}$),scalem, m,1_${ik}$,a(1_${ik}$,1_${ik}$),lda,ierr ) call stdlib${ii}$_${ri}$lacpy( 'A', m, 1_${ik}$, a, lda, u, ldu ) ! computing all m left singular vectors of the m x 1 matrix if ( n1 /= n ) then call stdlib${ii}$_${ri}$geqrf( m, n, u,ldu, work, work(n+1),lwork-n,ierr ) call stdlib${ii}$_${ri}$orgqr( m,n1,1_${ik}$, u,ldu,work,work(n+1),lwork-n,ierr ) call stdlib${ii}$_${ri}$copy( m, a(1_${ik}$,1_${ik}$), 1_${ik}$, u(1_${ik}$,1_${ik}$), 1_${ik}$ ) end if end if if ( rsvec ) then v(1_${ik}$,1_${ik}$) = one end if if ( sva(1_${ik}$) < (big*scalem) ) then sva(1_${ik}$) = sva(1_${ik}$) / scalem scalem = one end if work(1_${ik}$) = one / scalem work(2_${ik}$) = one if ( sva(1_${ik}$) /= zero ) then iwork(1_${ik}$) = 1_${ik}$ if ( ( sva(1_${ik}$) / scalem) >= sfmin ) then iwork(2_${ik}$) = 1_${ik}$ else iwork(2_${ik}$) = 0_${ik}$ end if else iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ end if iwork(3_${ik}$) = 0_${ik}$ if ( errest ) work(3_${ik}$) = one if ( lsvec .and. rsvec ) then work(4_${ik}$) = one work(5_${ik}$) = one end if if ( l2tran ) then work(6_${ik}$) = zero work(7_${ik}$) = zero end if return end if transp = .false. l2tran = l2tran .and. ( m == n ) aatmax = -one aatmin = big if ( rowpiv .or. l2tran ) then ! compute the row norms, needed to determine row pivoting sequence ! (in the case of heavily row weighted a, row pivoting is strongly ! advised) and to collect information needed to compare the ! structures of a * a^t and a^t * a (in the case l2tran==.true.). if ( l2tran ) then do p = 1, m xsc = zero temp1 = one call stdlib${ii}$_${ri}$lassq( n, a(p,1_${ik}$), lda, xsc, temp1 ) ! stdlib${ii}$_${ri}$lassq gets both the ell_2 and the ell_infinity norm ! in one pass through the vector work(m+n+p) = xsc * scalem work(n+p) = xsc * (scalem*sqrt(temp1)) aatmax = max( aatmax, work(n+p) ) if (work(n+p) /= zero) aatmin = min(aatmin,work(n+p)) end do else do p = 1, m work(m+n+p) = scalem*abs( a(p,stdlib${ii}$_i${ri}$amax(n,a(p,1_${ik}$),lda)) ) aatmax = max( aatmax, work(m+n+p) ) aatmin = min( aatmin, work(m+n+p) ) end do end if end if ! for square matrix a try to determine whether a^t would be better ! input for the preconditioned jacobi svd, with faster convergence. ! the decision is based on an o(n) function of the vector of column ! and row norms of a, based on the shannon entropy. this should give ! the right choice in most cases when the difference actually matters. ! it may fail and pick the slower converging side. entra = zero entrat = zero if ( l2tran ) then xsc = zero temp1 = one call stdlib${ii}$_${ri}$lassq( n, sva, 1_${ik}$, xsc, temp1 ) temp1 = one / temp1 entra = zero do p = 1, n big1 = ( ( sva(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entra = entra + big1 * log(big1) end do entra = - entra / log(real(n,KIND=${rk}$)) ! now, sva().^2/trace(a^t * a) is a point in the probability simplex. ! it is derived from the diagonal of a^t * a. do the same with the ! diagonal of a * a^t, compute the entropy of the corresponding ! probability distribution. note that a * a^t and a^t * a have the ! same trace. entrat = zero do p = n+1, n+m big1 = ( ( work(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entrat = entrat + big1 * log(big1) end do entrat = - entrat / log(real(m,KIND=${rk}$)) ! analyze the entropies and decide a or a^t. smaller entropy ! usually means better input for the algorithm. transp = ( entrat < entra ) ! if a^t is better than a, transpose a. if ( transp ) then ! in an optimal implementation, this trivial transpose ! should be replaced with faster transpose. do p = 1, n - 1 do q = p + 1, n temp1 = a(q,p) a(q,p) = a(p,q) a(p,q) = temp1 end do end do do p = 1, n work(m+n+p) = sva(p) sva(p) = work(n+p) end do temp1 = aapp aapp = aatmax aatmax = temp1 temp1 = aaqq aaqq = aatmin aatmin = temp1 kill = lsvec lsvec = rsvec rsvec = kill if ( lsvec ) n1 = n rowpiv = .true. end if end if ! end if l2tran ! scale the matrix so that its maximal singular value remains less ! than sqrt(big) -- the matrix is scaled so that its maximal column ! has euclidean norm equal to sqrt(big/n). the only reason to keep ! sqrt(big) instead of big is the fact that stdlib${ii}$_${ri}$gejsv uses lapack and ! blas routines that, in some implementations, are not capable of ! working in the full interval [sfmin,big] and that they may provoke ! overflows in the intermediate results. if the singular values spread ! from sfmin to big, then stdlib${ii}$_${ri}$gesvj will compute them. so, in that case, ! one should use stdlib_${ri}$gesvj instead of stdlib${ii}$_${ri}$gejsv. big1 = sqrt( big ) temp1 = sqrt( big / real(n,KIND=${rk}$) ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, n, 1_${ik}$, sva, n, ierr ) if ( aaqq > (aapp * sfmin) ) then aaqq = ( aaqq / aapp ) * temp1 else aaqq = ( aaqq * temp1 ) / aapp end if temp1 = temp1 * scalem call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, m, n, a, lda, ierr ) ! to undo scaling at the end of this procedure, multiply the ! computed singular values with uscal2 / uscal1. uscal1 = temp1 uscal2 = aapp if ( l2kill ) then ! l2kill enforces computation of nonzero singular values in ! the restricted range of condition number of the initial a, ! sigma_max(a) / sigma_min(a) approx. sqrt(big)/sqrt(sfmin). xsc = sqrt( sfmin ) else xsc = small ! now, if the condition number of a is too big, ! sigma_max(a) / sigma_min(a) > sqrt(big/n) * epsln / sfmin, ! as a precaution measure, the full svd is computed using stdlib${ii}$_${ri}$gesvj ! with accumulated jacobi rotations. this provides numerically ! more robust computation, at the cost of slightly increased run ! time. depending on the concrete implementation of blas and lapack ! (i.e. how they behave in presence of extreme ill-conditioning) the ! implementor may decide to remove this switch. if ( ( aaqq= (temp1*abs(a(1_${ik}$,1_${ik}$))) ) then nr = nr + 1_${ik}$ else exit loop_3002 end if end do loop_3002 else if ( l2rank ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r1 is used as the criterion for ! close-to-rank-deficient. temp1 = sqrt(sfmin) loop_3402: do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < small ) .or.( & l2kill .and. (abs(a(p,p)) < temp1) ) ) exit loop_3402 nr = nr + 1_${ik}$ end do loop_3402 else ! the goal is high relative accuracy. however, if the matrix ! has high scaled condition number the relative accuracy is in ! general not feasible. later on, a condition number estimator ! will be deployed to estimate the scaled condition number. ! here we just remove the underflowed part of the triangular ! factor. this prevents the situation in which the code is ! working hard to get the accuracy not warranted by the data. temp1 = sqrt(sfmin) loop_3302: do p = 2, n if ( ( abs(a(p,p)) < small ) .or.( l2kill .and. (abs(a(p,p)) < temp1) ) ) exit loop_3302 nr = nr + 1_${ik}$ end do loop_3302 end if almort = .false. if ( nr == n ) then maxprj = one do p = 2, n temp1 = abs(a(p,p)) / sva(iwork(p)) maxprj = min( maxprj, temp1 ) end do if ( maxprj**2_${ik}$ >= one - real(n,KIND=${rk}$)*epsln ) almort = .true. end if sconda = - one condr1 = - one condr2 = - one if ( errest ) then if ( n == nr ) then if ( rsvec ) then ! V Is Available As Workspace call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, v, ldv ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_${ri}$scal( p, one/temp1, v(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$pocon( 'U', n, v, ldv, one, temp1,work(n+1), iwork(2_${ik}$*n+m+1), & ierr ) else if ( lsvec ) then ! U Is Available As Workspace call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, u, ldu ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_${ri}$scal( p, one/temp1, u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$pocon( 'U', n, u, ldu, one, temp1,work(n+1), iwork(2_${ik}$*n+m+1), & ierr ) else call stdlib${ii}$_${ri}$lacpy( 'U', n, n, a, lda, work(n+1), n ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_${ri}$scal( p, one/temp1, work(n+(p-1)*n+1), 1_${ik}$ ) end do ! The Columns Of R Are Scaled To Have Unit Euclidean Lengths call stdlib${ii}$_${ri}$pocon( 'U', n, work(n+1), n, one, temp1,work(n+n*n+1), iwork(2_${ik}$*n+& m+1), ierr ) end if sconda = one / sqrt(temp1) ! sconda is an estimate of sqrt(||(r^t * r)^(-1)||_1). ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda else sconda = - one end if end if l2pert = l2pert .and. ( abs( a(1_${ik}$,1_${ik}$)/a(nr,nr) ) > sqrt(big1) ) ! if there is no violent scaling, artificial perturbation is not needed. ! phase 3: if ( .not. ( rsvec .or. lsvec ) ) then ! singular values only ! .. transpose a(1:nr,1:n) do p = 1, min( n-1, nr ) call stdlib${ii}$_${ri}$copy( n-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) end do ! the following two do-loops introduce small relative perturbation ! into the strict upper triangle of the lower triangular matrix. ! small entries below the main diagonal are also changed. ! this modification is useful if the computing environment does not ! provide/allow flush to zero underflow, for it prevents many ! annoying denormalized numbers in case of strongly scaled matrices. ! the perturbation is structured so that it does not introduce any ! new perturbation of the singular values, and it does not destroy ! the job done by the preconditioner. ! the licence for this perturbation is in the variable l2pert, which ! should be .false. if flush to zero underflow is active. if ( .not. almort ) then if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=${rk}$) do q = 1, nr temp1 = xsc*abs(a(q,q)) do p = 1, n if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = sign( & temp1, a(p,q) ) end do end do else call stdlib${ii}$_${ri}$laset( 'U', nr-1,nr-1, zero,zero, a(1_${ik}$,2_${ik}$),lda ) end if ! Second Preconditioning Using The Qr Factorization call stdlib${ii}$_${ri}$geqrf( n,nr, a,lda, work, work(n+1),lwork-n, ierr ) ! And Transpose Upper To Lower Triangular do p = 1, nr - 1 call stdlib${ii}$_${ri}$copy( nr-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) end do end if ! row-cyclic jacobi svd algorithm with column pivoting ! .. again some perturbation (a "background noise") is added ! to drown denormals if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=${rk}$) do q = 1, nr temp1 = xsc*abs(a(q,q)) do p = 1, nr if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = sign( & temp1, a(p,q) ) end do end do else call stdlib${ii}$_${ri}$laset( 'U', nr-1, nr-1, zero, zero, a(1_${ik}$,2_${ik}$), lda ) end if ! .. and one-sided jacobi rotations are started on a lower ! triangular matrix (plus perturbation which is ignored in ! the part which destroys triangular form (confusing?!)) call stdlib${ii}$_${ri}$gesvj( 'L', 'NOU', 'NOV', nr, nr, a, lda, sva,n, v, ldv, work, & lwork, info ) scalem = work(1_${ik}$) numrank = nint(work(2_${ik}$),KIND=${ik}$) else if ( rsvec .and. ( .not. lsvec ) ) then ! -> singular values and right singular vectors <- if ( almort ) then ! In This Case Nr Equals N do p = 1, nr call stdlib${ii}$_${ri}$copy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$laset( 'UPPER', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_${ri}$gesvj( 'L','U','N', n, nr, v,ldv, sva, nr, a,lda,work, lwork, info ) scalem = work(1_${ik}$) numrank = nint(work(2_${ik}$),KIND=${ik}$) else ! .. two more qr factorizations ( one qrf is not enough, two require ! accumulated product of jacobi rotations, three are perfect ) call stdlib${ii}$_${ri}$laset( 'LOWER', nr-1, nr-1, zero, zero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_${ri}$gelqf( nr, n, a, lda, work, work(n+1), lwork-n, ierr) call stdlib${ii}$_${ri}$lacpy( 'LOWER', nr, nr, a, lda, v, ldv ) call stdlib${ii}$_${ri}$laset( 'UPPER', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_${ri}$geqrf( nr, nr, v, ldv, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr call stdlib${ii}$_${ri}$copy( nr-p+1, v(p,p), ldv, v(p,p), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$laset( 'UPPER', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_${ri}$gesvj( 'LOWER', 'U','N', nr, nr, v,ldv, sva, nr, u,ldu, work(n+1), & lwork, info ) scalem = work(n+1) numrank = nint(work(n+2),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_${ri}$laset( 'A',n-nr, nr, zero,zero, v(nr+1,1_${ik}$), ldv ) call stdlib${ii}$_${ri}$laset( 'A',nr, n-nr, zero,zero, v(1_${ik}$,nr+1), ldv ) call stdlib${ii}$_${ri}$laset( 'A',n-nr,n-nr,zero,one, v(nr+1,nr+1), ldv ) end if call stdlib${ii}$_${ri}$ormlq( 'LEFT', 'TRANSPOSE', n, n, nr, a, lda, work,v, ldv, work(n+1), & lwork-n, ierr ) end if do p = 1, n call stdlib${ii}$_${ri}$copy( n, v(p,1_${ik}$), ldv, a(iwork(p),1_${ik}$), lda ) end do call stdlib${ii}$_${ri}$lacpy( 'ALL', n, n, a, lda, v, ldv ) if ( transp ) then call stdlib${ii}$_${ri}$lacpy( 'ALL', n, n, v, ldv, u, ldu ) end if else if ( lsvec .and. ( .not. rsvec ) ) then ! Singular Values And Left Singular Vectors ! Second Preconditioning Step To Avoid Need To Accumulate ! jacobi rotations in the jacobi iterations. do p = 1, nr call stdlib${ii}$_${ri}$copy( n-p+1, a(p,p), lda, u(p,p), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$laset( 'UPPER', nr-1, nr-1, zero, zero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_${ri}$geqrf( n, nr, u, ldu, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr - 1 call stdlib${ii}$_${ri}$copy( nr-p, u(p,p+1), ldu, u(p+1,p), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$laset( 'UPPER', nr-1, nr-1, zero, zero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_${ri}$gesvj( 'LOWER', 'U', 'N', nr,nr, u, ldu, sva, nr, a,lda, work(n+1), & lwork-n, info ) scalem = work(n+1) numrank = nint(work(n+2),KIND=${ik}$) if ( nr < m ) then call stdlib${ii}$_${ri}$laset( 'A', m-nr, nr,zero, zero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_${ri}$laset( 'A',nr, n1-nr, zero, zero, u(1_${ik}$,nr+1), ldu ) call stdlib${ii}$_${ri}$laset( 'A',m-nr,n1-nr,zero,one,u(nr+1,nr+1), ldu ) end if end if call stdlib${ii}$_${ri}$ormqr( 'LEFT', 'NO TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) if ( rowpiv )call stdlib${ii}$_${ri}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) do p = 1, n1 xsc = one / stdlib${ii}$_${ri}$nrm2( m, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, xsc, u(1_${ik}$,p), 1_${ik}$ ) end do if ( transp ) then call stdlib${ii}$_${ri}$lacpy( 'ALL', n, n, u, ldu, v, ldv ) end if else ! Full Svd if ( .not. jracc ) then if ( .not. almort ) then ! second preconditioning step (qrf [with pivoting]) ! note that the composition of transpose, qrf and transpose is ! equivalent to an lqf call. since in many libraries the qrf ! seems to be better optimized than the lqf, we do explicit ! transpose and use the qrf. this is subject to changes in an ! optimized implementation of stdlib${ii}$_${ri}$gejsv. do p = 1, nr call stdlib${ii}$_${ri}$copy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) end do ! The Following Two Loops Perturb Small Entries To Avoid ! denormals in the second qr factorization, where they are ! as good as zeros. this is done to avoid painfully slow ! computation with denormals. the relative size of the perturbation ! is a parameter that can be changed by the implementer. ! this perturbation device will be obsolete on machines with ! properly implemented arithmetic. ! to switch it off, set l2pert=.false. to remove it from the ! code, remove the action under l2pert=.true., leave the else part. ! the following two loops should be blocked and fused with the ! transposed copy above. if ( l2pert ) then xsc = sqrt(small) do q = 1, nr temp1 = xsc*abs( v(q,q) ) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = & sign( temp1, v(p,q) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else call stdlib${ii}$_${ri}$laset( 'U', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) end if ! estimate the row scaled condition number of r1 ! (if r1 is rectangular, n > nr, then the condition number ! of the leading nr x nr submatrix is estimated.) call stdlib${ii}$_${ri}$lacpy( 'L', nr, nr, v, ldv, work(2_${ik}$*n+1), nr ) do p = 1, nr temp1 = stdlib${ii}$_${ri}$nrm2(nr-p+1,work(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) call stdlib${ii}$_${ri}$scal(nr-p+1,one/temp1,work(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) end do call stdlib${ii}$_${ri}$pocon('LOWER',nr,work(2_${ik}$*n+1),nr,one,temp1,work(2_${ik}$*n+nr*nr+1),iwork(m+& 2_${ik}$*n+1),ierr) condr1 = one / sqrt(temp1) ! Here Need A Second Opinion On The Condition Number ! Then Assume Worst Case Scenario ! r1 is ok for inverse <=> condr1 < real(n,KIND=${rk}$) ! more conservative <=> condr1 < sqrt(real(n,KIND=${rk}$)) cond_ok = sqrt(real(nr,KIND=${rk}$)) ! [tp] cond_ok is a tuning parameter. if ( condr1 < cond_ok ) then ! .. the second qrf without pivoting. note: in an optimized ! implementation, this qrf should be implemented as the qrf ! of a lower triangular matrix. ! r1^t = q2 * r2 call stdlib${ii}$_${ri}$geqrf( n, nr, v, ldv, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small)/epsln do p = 2, nr do q = 1, p - 1 temp1 = xsc * min(abs(v(p,p)),abs(v(q,q))) if ( abs(v(q,p)) <= temp1 )v(q,p) = sign( temp1, v(q,p) ) end do end do end if if ( nr /= n )call stdlib${ii}$_${ri}$lacpy( 'A', n, nr, v, ldv, work(2_${ik}$*n+1), n ) ! .. save ... ! This Transposed Copy Should Be Better Than Naive do p = 1, nr - 1 call stdlib${ii}$_${ri}$copy( nr-p, v(p,p+1), ldv, v(p+1,p), 1_${ik}$ ) end do condr2 = condr1 else ! .. ill-conditioned case: second qrf with pivoting ! note that windowed pivoting would be equally good ! numerically, and more run-time efficient. so, in ! an optimal implementation, the next call to stdlib${ii}$_${ri}$geqp3 ! should be replaced with eg. call sgeqpx (acm toms #782) ! with properly (carefully) chosen parameters. ! r1^t * p2 = q2 * r2 do p = 1, nr iwork(n+p) = 0_${ik}$ end do call stdlib${ii}$_${ri}$geqp3( n, nr, v, ldv, iwork(n+1), work(n+1),work(2_${ik}$*n+1), lwork-& 2_${ik}$*n, ierr ) ! * call stdlib${ii}$_${ri}$geqrf( n, nr, v, ldv, work(n+1), work(2*n+1), ! * $ lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 temp1 = xsc * min(abs(v(p,p)),abs(v(q,q))) if ( abs(v(q,p)) <= temp1 )v(q,p) = sign( temp1, v(q,p) ) end do end do end if call stdlib${ii}$_${ri}$lacpy( 'A', n, nr, v, ldv, work(2_${ik}$*n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 temp1 = xsc * min(abs(v(p,p)),abs(v(q,q))) v(p,q) = - sign( temp1, v(q,p) ) end do end do else call stdlib${ii}$_${ri}$laset( 'L',nr-1,nr-1,zero,zero,v(2_${ik}$,1_${ik}$),ldv ) end if ! now, compute r2 = l3 * q3, the lq factorization. call stdlib${ii}$_${ri}$gelqf( nr, nr, v, ldv, work(2_${ik}$*n+n*nr+1),work(2_${ik}$*n+n*nr+nr+1), & lwork-2*n-n*nr-nr, ierr ) ! And Estimate The Condition Number call stdlib${ii}$_${ri}$lacpy( 'L',nr,nr,v,ldv,work(2_${ik}$*n+n*nr+nr+1),nr ) do p = 1, nr temp1 = stdlib${ii}$_${ri}$nrm2( p, work(2_${ik}$*n+n*nr+nr+p), nr ) call stdlib${ii}$_${ri}$scal( p, one/temp1, work(2_${ik}$*n+n*nr+nr+p), nr ) end do call stdlib${ii}$_${ri}$pocon( 'L',nr,work(2_${ik}$*n+n*nr+nr+1),nr,one,temp1,work(2_${ik}$*n+n*nr+nr+& nr*nr+1),iwork(m+2*n+1),ierr ) condr2 = one / sqrt(temp1) if ( condr2 >= cond_ok ) then ! Save The Householder Vectors Used For Q3 ! (this overwrites the copy of r2, as it will not be ! needed in this branch, but it does not overwritte the ! huseholder vectors of q2.). call stdlib${ii}$_${ri}$lacpy( 'U', nr, nr, v, ldv, work(2_${ik}$*n+1), n ) ! And The Rest Of The Information On Q3 Is In ! work(2*n+n*nr+1:2*n+n*nr+n) end if end if if ( l2pert ) then xsc = sqrt(small) do q = 2, nr temp1 = xsc * v(q,q) do p = 1, q - 1 ! v(p,q) = - sign( temp1, v(q,p) ) v(p,q) = - sign( temp1, v(p,q) ) end do end do else call stdlib${ii}$_${ri}$laset( 'U', nr-1,nr-1, zero,zero, v(1_${ik}$,2_${ik}$), ldv ) end if ! second preconditioning finished; continue with jacobi svd ! the input matrix is lower trinagular. ! recover the right singular vectors as solution of a well ! conditioned triangular matrix equation. if ( condr1 < cond_ok ) then call stdlib${ii}$_${ri}$gesvj( 'L','U','N',nr,nr,v,ldv,sva,nr,u,ldu,work(2_${ik}$*n+n*nr+nr+1),& lwork-2*n-n*nr-nr,info ) scalem = work(2_${ik}$*n+n*nr+nr+1) numrank = nint(work(2_${ik}$*n+n*nr+nr+2),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_${ri}$copy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( nr, sva(p), v(1_${ik}$,p), 1_${ik}$ ) end do ! Pick The Right Matrix Equation And Solve It if ( nr == n ) then ! :)) .. best case, r1 is inverted. the solution of this matrix ! equation is q2*v2 = the product of the jacobi rotations ! used in stdlib${ii}$_${ri}$gesvj, premultiplied with the orthogonal matrix ! from the second qr factorization. call stdlib${ii}$_${ri}$trsm( 'L','U','N','N', nr,nr,one, a,lda, v,ldv ) else ! .. r1 is well conditioned, but non-square. transpose(r2) ! is inverted to get the product of the jacobi rotations ! used in stdlib${ii}$_${ri}$gesvj. the q-factor from the second qr ! factorization is then built in explicitly. call stdlib${ii}$_${ri}$trsm('L','U','T','N',nr,nr,one,work(2_${ik}$*n+1),n,v,ldv) if ( nr < n ) then call stdlib${ii}$_${ri}$laset('A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_${ri}$laset('A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_${ri}$laset('A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_${ri}$ormqr('L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr) end if else if ( condr2 < cond_ok ) then ! :) .. the input matrix a is very likely a relative of ! the kahan matrix :) ! the matrix r2 is inverted. the solution of the matrix equation ! is q3^t*v3 = the product of the jacobi rotations (appplied to ! the lower triangular l3 from the lq factorization of ! r2=l3*q3), pre-multiplied with the transposed q3. call stdlib${ii}$_${ri}$gesvj( 'L', 'U', 'N', nr, nr, v, ldv, sva, nr, u,ldu, work(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr, info ) scalem = work(2_${ik}$*n+n*nr+nr+1) numrank = nint(work(2_${ik}$*n+n*nr+nr+2),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_${ri}$copy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( nr, sva(p), u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$trsm('L','U','N','N',nr,nr,one,work(2_${ik}$*n+1),n,u,ldu) ! Apply The Permutation From The Second Qr Factorization do q = 1, nr do p = 1, nr work(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do end do if ( nr < n ) then call stdlib${ii}$_${ri}$laset( 'A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_${ri}$laset( 'A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_${ri}$laset( 'A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_${ri}$ormqr( 'L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) else ! last line of defense. ! #:( this is a rather pathological case: no scaled condition ! improvement after two pivoted qr factorizations. other ! possibility is that the rank revealing qr factorization ! or the condition estimator has failed, or the cond_ok ! is set very close to one (which is unnecessary). normally, ! this branch should never be executed, but in rare cases of ! failure of the rrqr or condition estimator, the last line of ! defense ensures that stdlib${ii}$_${ri}$gejsv completes the task. ! compute the full svd of l3 using stdlib${ii}$_${ri}$gesvj with explicit ! accumulation of jacobi rotations. call stdlib${ii}$_${ri}$gesvj( 'L', 'U', 'V', nr, nr, v, ldv, sva, nr, u,ldu, work(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr, info ) scalem = work(2_${ik}$*n+n*nr+nr+1) numrank = nint(work(2_${ik}$*n+n*nr+nr+2),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_${ri}$laset( 'A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_${ri}$laset( 'A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_${ri}$laset( 'A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_${ri}$ormqr( 'L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) call stdlib${ii}$_${ri}$ormlq( 'L', 'T', nr, nr, nr, work(2_${ik}$*n+1), n,work(2_${ik}$*n+n*nr+1), u, & ldu, work(2_${ik}$*n+n*nr+nr+1),lwork-2*n-n*nr-nr, ierr ) do q = 1, nr do p = 1, nr work(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do end do end if ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=${rk}$)) * epsln do q = 1, n do p = 1, n work(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_${ri}$nrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_${ri}$scal( n, xsc, & v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_${ri}$laset( 'A', m-nr, nr, zero, zero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_${ri}$laset('A',nr,n1-nr,zero,zero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_${ri}$laset('A',m-nr,n1-nr,zero,one,u(nr+1,nr+1),ldu) end if end if ! the q matrix from the first qrf is built into the left singular ! matrix u. this applies to all cases. call stdlib${ii}$_${ri}$ormqr( 'LEFT', 'NO_TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) ! the columns of u are normalized. the cost is o(m*n) flops. temp1 = sqrt(real(m,KIND=${rk}$)) * epsln do p = 1, nr xsc = one / stdlib${ii}$_${ri}$nrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_${ri}$scal( m, xsc, & u(1_${ik}$,p), 1_${ik}$ ) end do ! if the initial qrf is computed with row pivoting, the left ! singular vectors must be adjusted. if ( rowpiv )call stdlib${ii}$_${ri}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) else ! The Initial Matrix A Has Almost Orthogonal Columns And ! the second qrf is not needed call stdlib${ii}$_${ri}$lacpy( 'UPPER', n, n, a, lda, work(n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, n temp1 = xsc * work( n + (p-1)*n + p ) do q = 1, p - 1 work(n+(q-1)*n+p)=-sign(temp1,work(n+(p-1)*n+q)) end do end do else call stdlib${ii}$_${ri}$laset( 'LOWER',n-1,n-1,zero,zero,work(n+2),n ) end if call stdlib${ii}$_${ri}$gesvj( 'UPPER', 'U', 'N', n, n, work(n+1), n, sva,n, u, ldu, work(n+& n*n+1), lwork-n-n*n, info ) scalem = work(n+n*n+1) numrank = nint(work(n+n*n+2),KIND=${ik}$) do p = 1, n call stdlib${ii}$_${ri}$copy( n, work(n+(p-1)*n+1), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, sva(p), work(n+(p-1)*n+1), 1_${ik}$ ) end do call stdlib${ii}$_${ri}$trsm( 'LEFT', 'UPPER', 'NOTRANS', 'NO UD', n, n,one, a, lda, work(n+& 1_${ik}$), n ) do p = 1, n call stdlib${ii}$_${ri}$copy( n, work(n+p), n, v(iwork(p),1_${ik}$), ldv ) end do temp1 = sqrt(real(n,KIND=${rk}$))*epsln do p = 1, n xsc = one / stdlib${ii}$_${ri}$nrm2( n, v(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_${ri}$scal( n, xsc, & v(1_${ik}$,p), 1_${ik}$ ) end do ! assemble the left singular vector matrix u (m x n). if ( n < m ) then call stdlib${ii}$_${ri}$laset( 'A', m-n, n, zero, zero, u(n+1,1_${ik}$), ldu ) if ( n < n1 ) then call stdlib${ii}$_${ri}$laset( 'A',n, n1-n, zero, zero, u(1_${ik}$,n+1),ldu ) call stdlib${ii}$_${ri}$laset( 'A',m-n,n1-n, zero, one,u(n+1,n+1),ldu ) end if end if call stdlib${ii}$_${ri}$ormqr( 'LEFT', 'NO TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) temp1 = sqrt(real(m,KIND=${rk}$))*epsln do p = 1, n1 xsc = one / stdlib${ii}$_${ri}$nrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_${ri}$scal( m, xsc, & u(1_${ik}$,p), 1_${ik}$ ) end do if ( rowpiv )call stdlib${ii}$_${ri}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) end if ! end of the >> almost orthogonal case << in the full svd else ! this branch deploys a preconditioned jacobi svd with explicitly ! accumulated rotations. it is included as optional, mainly for ! experimental purposes. it does perform well, and can also be used. ! in this implementation, this branch will be automatically activated ! if the condition number sigma_max(a) / sigma_min(a) is predicted ! to be greater than the overflow threshold. this is because the ! a posteriori computation of the singular vectors assumes robust ! implementation of blas and some lapack procedures, capable of working ! in presence of extreme values. since that is not always the case, ... do p = 1, nr call stdlib${ii}$_${ri}$copy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 1, nr temp1 = xsc*abs( v(q,q) ) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = sign(& temp1, v(p,q) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else call stdlib${ii}$_${ri}$laset( 'U', nr-1, nr-1, zero, zero, v(1_${ik}$,2_${ik}$), ldv ) end if call stdlib${ii}$_${ri}$geqrf( n, nr, v, ldv, work(n+1), work(2_${ik}$*n+1),lwork-2*n, ierr ) call stdlib${ii}$_${ri}$lacpy( 'L', n, nr, v, ldv, work(2_${ik}$*n+1), n ) do p = 1, nr call stdlib${ii}$_${ri}$copy( nr-p+1, v(p,p), ldv, u(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 2, nr do p = 1, q - 1 temp1 = xsc * min(abs(u(p,p)),abs(u(q,q))) u(p,q) = - sign( temp1, u(q,p) ) end do end do else call stdlib${ii}$_${ri}$laset('U', nr-1, nr-1, zero, zero, u(1_${ik}$,2_${ik}$), ldu ) end if call stdlib${ii}$_${ri}$gesvj( 'G', 'U', 'V', nr, nr, u, ldu, sva,n, v, ldv, work(2_${ik}$*n+n*nr+1), & lwork-2*n-n*nr, info ) scalem = work(2_${ik}$*n+n*nr+1) numrank = nint(work(2_${ik}$*n+n*nr+2),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_${ri}$laset( 'A',n-nr,nr,zero,zero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_${ri}$laset( 'A',nr,n-nr,zero,zero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_${ri}$laset( 'A',n-nr,n-nr,zero,one,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_${ri}$ormqr( 'L','N',n,n,nr,work(2_${ik}$*n+1),n,work(n+1),v,ldv,work(2_${ik}$*n+n*nr+nr+1)& ,lwork-2*n-n*nr-nr,ierr ) ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=${rk}$)) * epsln do q = 1, n do p = 1, n work(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = work(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_${ri}$nrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_${ri}$scal( n, xsc, & v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_${ri}$laset( 'A', m-nr, nr, zero, zero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_${ri}$laset( 'A',nr, n1-nr, zero, zero, u(1_${ik}$,nr+1),ldu ) call stdlib${ii}$_${ri}$laset( 'A',m-nr,n1-nr, zero, one,u(nr+1,nr+1),ldu ) end if end if call stdlib${ii}$_${ri}$ormqr( 'LEFT', 'NO TR', m, n1, n, a, lda, work, u,ldu, work(n+1), & lwork-n, ierr ) if ( rowpiv )call stdlib${ii}$_${ri}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(2_${ik}$*n+1), -1_${ik}$ ) end if if ( transp ) then ! .. swap u and v because the procedure worked on a^t do p = 1, n call stdlib${ii}$_${ri}$swap( n, u(1_${ik}$,p), 1_${ik}$, v(1_${ik}$,p), 1_${ik}$ ) end do end if end if ! end of the full svd ! undo scaling, if necessary (and possible) if ( uscal2 <= (big/sva(1_${ik}$))*uscal1 ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, uscal1, uscal2, nr, 1_${ik}$, sva, n, ierr ) uscal1 = one uscal2 = one end if if ( nr < n ) then do p = nr+1, n sva(p) = zero end do end if work(1_${ik}$) = uscal2 * scalem work(2_${ik}$) = uscal1 if ( errest ) work(3_${ik}$) = sconda if ( lsvec .and. rsvec ) then work(4_${ik}$) = condr1 work(5_${ik}$) = condr2 end if if ( l2tran ) then work(6_${ik}$) = entra work(7_${ik}$) = entrat end if iwork(1_${ik}$) = nr iwork(2_${ik}$) = numrank iwork(3_${ik}$) = warning return end subroutine stdlib${ii}$_${ri}$gejsv #:endif #:endfor pure module subroutine stdlib${ii}$_cgejsv( joba, jobu, jobv, jobr, jobt, jobp,m, n, a, lda, sva, u, ldu, & !! CGEJSV computes the singular value decomposition (SVD) of a complex M-by-N !! matrix [A], where M >= N. The SVD of [A] is written as !! [A] = [U] * [SIGMA] * [V]^*, !! where [SIGMA] is an N-by-N (M-by-N) matrix which is zero except for its N !! diagonal elements, [U] is an M-by-N (or M-by-M) unitary matrix, and !! [V] is an N-by-N unitary matrix. The diagonal elements of [SIGMA] are !! the singular values of [A]. The columns of [U] and [V] are the left and !! the right singular vectors of [A], respectively. The matrices [U] and [V] !! are computed and stored in the arrays U and V, respectively. The diagonal !! of [SIGMA] is computed and stored in the array SVA. v, ldv,cwork, lwork, rwork, lrwork, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldu, ldv, lwork, lrwork, m, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: u(ldu,*), v(ldv,*), cwork(lwork) real(sp), intent(out) :: sva(n), rwork(lrwork) integer(${ik}$), intent(out) :: iwork(*) character, intent(in) :: joba, jobp, jobr, jobt, jobu, jobv ! =========================================================================== ! Local Scalars complex(sp) :: ctemp real(sp) :: aapp, aaqq, aatmax, aatmin, big, big1, cond_ok, condr1, condr2, entra, & entrat, epsln, maxprj, scalem, sconda, sfmin, small, temp1, uscal1, uscal2, xsc integer(${ik}$) :: ierr, n1, nr, numrank, p, q, warning logical(lk) :: almort, defr, errest, goscal, jracc, kill, lquery, lsvec, l2aber, & l2kill, l2pert, l2rank, l2tran, noscal, rowpiv, rsvec, transp integer(${ik}$) :: optwrk, minwrk, minrwrk, miniwrk integer(${ik}$) :: lwcon, lwlqf, lwqp3, lwqrf, lwunmlq, lwunmqr, lwunmqrm, lwsvdj, & lwsvdjv, lrwqp3, lrwcon, lrwsvdj, iwoff integer(${ik}$) :: lwrk_cgelqf, lwrk_cgeqp3, lwrk_cgeqp3n, lwrk_cgeqrf, lwrk_cgesvj, & lwrk_cgesvjv, lwrk_cgesvju, lwrk_cunmlq, lwrk_cunmqr, lwrk_cunmqrm ! Local Arrays complex(sp) :: cdummy(1_${ik}$) real(sp) :: rdummy(1_${ik}$) ! Intrinsic Functions ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) .or. stdlib_lsame( jobu, 'F' ) jracc = stdlib_lsame( jobv, 'J' ) rsvec = stdlib_lsame( jobv, 'V' ) .or. jracc rowpiv = stdlib_lsame( joba, 'F' ) .or. stdlib_lsame( joba, 'G' ) l2rank = stdlib_lsame( joba, 'R' ) l2aber = stdlib_lsame( joba, 'A' ) errest = stdlib_lsame( joba, 'E' ) .or. stdlib_lsame( joba, 'G' ) l2tran = stdlib_lsame( jobt, 'T' ) .and. ( m == n ) l2kill = stdlib_lsame( jobr, 'R' ) defr = stdlib_lsame( jobr, 'N' ) l2pert = stdlib_lsame( jobp, 'P' ) lquery = ( lwork == -1_${ik}$ ) .or. ( lrwork == -1_${ik}$ ) if ( .not.(rowpiv .or. l2rank .or. l2aber .or.errest .or. stdlib_lsame( joba, 'C' ) )) & then info = - 1_${ik}$ else if ( .not.( lsvec .or. stdlib_lsame( jobu, 'N' ) .or.( stdlib_lsame( jobu, 'W' ) & .and. rsvec .and. l2tran ) ) ) then info = - 2_${ik}$ else if ( .not.( rsvec .or. stdlib_lsame( jobv, 'N' ) .or.( stdlib_lsame( jobv, 'W' ) & .and. lsvec .and. l2tran ) ) ) then info = - 3_${ik}$ else if ( .not. ( l2kill .or. defr ) ) then info = - 4_${ik}$ else if ( .not. ( stdlib_lsame(jobt,'T') .or. stdlib_lsame(jobt,'N') ) ) then info = - 5_${ik}$ else if ( .not. ( l2pert .or. stdlib_lsame( jobp, 'N' ) ) ) then info = - 6_${ik}$ else if ( m < 0_${ik}$ ) then info = - 7_${ik}$ else if ( ( n < 0_${ik}$ ) .or. ( n > m ) ) then info = - 8_${ik}$ else if ( lda < m ) then info = - 10_${ik}$ else if ( lsvec .and. ( ldu < m ) ) then info = - 13_${ik}$ else if ( rsvec .and. ( ldv < n ) ) then info = - 15_${ik}$ else ! #:) info = 0_${ik}$ end if if ( info == 0_${ik}$ ) then ! Compute The Minimal And The Optimal Workspace Lengths ! [[the expressions for computing the minimal and the optimal ! values of lcwork, lrwork are written with a lot of redundancy and ! can be simplified. however, this verbose form is useful for ! maintenance and modifications of the code.]] ! .. minimal workspace length for stdlib${ii}$_cgeqp3 of an m x n matrix, ! stdlib${ii}$_cgeqrf of an n x n matrix, stdlib${ii}$_cgelqf of an n x n matrix, ! stdlib${ii}$_cunmlq for computing n x n matrix, stdlib${ii}$_cunmqr for computing n x n ! matrix, stdlib${ii}$_cunmqr for computing m x n matrix, respectively. lwqp3 = n+1 lwqrf = max( 1_${ik}$, n ) lwlqf = max( 1_${ik}$, n ) lwunmlq = max( 1_${ik}$, n ) lwunmqr = max( 1_${ik}$, n ) lwunmqrm = max( 1_${ik}$, m ) ! Minimal Workspace Length For Stdlib_Cpocon Of An N X N Matrix lwcon = 2_${ik}$ * n ! .. minimal workspace length for stdlib${ii}$_cgesvj of an n x n matrix, ! without and with explicit accumulation of jacobi rotations lwsvdj = max( 2_${ik}$ * n, 1_${ik}$ ) lwsvdjv = max( 2_${ik}$ * n, 1_${ik}$ ) ! .. minimal real workspace length for stdlib${ii}$_cgeqp3, stdlib${ii}$_cpocon, stdlib${ii}$_cgesvj lrwqp3 = 2_${ik}$ * n lrwcon = n lrwsvdj = n if ( lquery ) then call stdlib${ii}$_cgeqp3( m, n, a, lda, iwork, cdummy, cdummy, -1_${ik}$,rdummy, ierr ) lwrk_cgeqp3 = real( cdummy(1_${ik}$),KIND=sp) call stdlib${ii}$_cgeqrf( n, n, a, lda, cdummy, cdummy,-1_${ik}$, ierr ) lwrk_cgeqrf = real( cdummy(1_${ik}$),KIND=sp) call stdlib${ii}$_cgelqf( n, n, a, lda, cdummy, cdummy,-1_${ik}$, ierr ) lwrk_cgelqf = real( cdummy(1_${ik}$),KIND=sp) end if minwrk = 2_${ik}$ optwrk = 2_${ik}$ miniwrk = n if ( .not. (lsvec .or. rsvec ) ) then ! Minimal And Optimal Sizes Of The Complex Workspace If ! only the singular values are requested if ( errest ) then minwrk = max( n+lwqp3, n**2_${ik}$+lwcon, n+lwqrf, lwsvdj ) else minwrk = max( n+lwqp3, n+lwqrf, lwsvdj ) end if if ( lquery ) then call stdlib${ii}$_cgesvj( 'L', 'N', 'N', n, n, a, lda, sva, n, v,ldv, cdummy, -1_${ik}$,& rdummy, -1_${ik}$, ierr ) lwrk_cgesvj = real( cdummy(1_${ik}$),KIND=sp) if ( errest ) then optwrk = max( n+lwrk_cgeqp3, n**2_${ik}$+lwcon,n+lwrk_cgeqrf, lwrk_cgesvj ) else optwrk = max( n+lwrk_cgeqp3, n+lwrk_cgeqrf,lwrk_cgesvj ) end if end if if ( l2tran .or. rowpiv ) then if ( errest ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwcon, lrwsvdj ) else minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj ) end if else if ( errest ) then minrwrk = max( 7_${ik}$, lrwqp3, lrwcon, lrwsvdj ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj ) end if end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else if ( rsvec .and. (.not.lsvec) ) then ! Minimal And Optimal Sizes Of The Complex Workspace If The ! singular values and the right singular vectors are requested if ( errest ) then minwrk = max( n+lwqp3, lwcon, lwsvdj, n+lwlqf,2_${ik}$*n+lwqrf, n+lwsvdj, n+& lwunmlq ) else minwrk = max( n+lwqp3, lwsvdj, n+lwlqf, 2_${ik}$*n+lwqrf,n+lwsvdj, n+lwunmlq ) end if if ( lquery ) then call stdlib${ii}$_cgesvj( 'L', 'U', 'N', n,n, u, ldu, sva, n, a,lda, cdummy, -1_${ik}$, & rdummy, -1_${ik}$, ierr ) lwrk_cgesvj = real( cdummy(1_${ik}$),KIND=sp) call stdlib${ii}$_cunmlq( 'L', 'C', n, n, n, a, lda, cdummy,v, ldv, cdummy, -1_${ik}$, & ierr ) lwrk_cunmlq = real( cdummy(1_${ik}$),KIND=sp) if ( errest ) then optwrk = max( n+lwrk_cgeqp3, lwcon, lwrk_cgesvj,n+lwrk_cgelqf, 2_${ik}$*n+& lwrk_cgeqrf,n+lwrk_cgesvj, n+lwrk_cunmlq ) else optwrk = max( n+lwrk_cgeqp3, lwrk_cgesvj,n+lwrk_cgelqf,2_${ik}$*n+lwrk_cgeqrf, n+& lwrk_cgesvj,n+lwrk_cunmlq ) end if end if if ( l2tran .or. rowpiv ) then if ( errest ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj ) end if else if ( errest ) then minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj ) end if end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else if ( lsvec .and. (.not.rsvec) ) then ! Minimal And Optimal Sizes Of The Complex Workspace If The ! singular values and the left singular vectors are requested if ( errest ) then minwrk = n + max( lwqp3,lwcon,n+lwqrf,lwsvdj,lwunmqrm ) else minwrk = n + max( lwqp3, n+lwqrf, lwsvdj, lwunmqrm ) end if if ( lquery ) then call stdlib${ii}$_cgesvj( 'L', 'U', 'N', n,n, u, ldu, sva, n, a,lda, cdummy, -1_${ik}$, & rdummy, -1_${ik}$, ierr ) lwrk_cgesvj = real( cdummy(1_${ik}$),KIND=sp) call stdlib${ii}$_cunmqr( 'L', 'N', m, n, n, a, lda, cdummy, u,ldu, cdummy, -1_${ik}$, & ierr ) lwrk_cunmqrm = real( cdummy(1_${ik}$),KIND=sp) if ( errest ) then optwrk = n + max( lwrk_cgeqp3, lwcon, n+lwrk_cgeqrf,lwrk_cgesvj, & lwrk_cunmqrm ) else optwrk = n + max( lwrk_cgeqp3, n+lwrk_cgeqrf,lwrk_cgesvj, lwrk_cunmqrm ) end if end if if ( l2tran .or. rowpiv ) then if ( errest ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj ) end if else if ( errest ) then minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj ) end if end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else ! Minimal And Optimal Sizes Of The Complex Workspace If The ! full svd is requested if ( .not. jracc ) then if ( errest ) then minwrk = max( n+lwqp3, n+lwcon, 2_${ik}$*n+n**2_${ik}$+lwcon,2_${ik}$*n+lwqrf, 2_${ik}$*n+& lwqp3,2_${ik}$*n+n**2_${ik}$+n+lwlqf, 2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+n**2_${ik}$+n+lwsvdj, 2_${ik}$*n+& n**2_${ik}$+n+lwsvdjv,2_${ik}$*n+n**2_${ik}$+n+lwunmqr,2_${ik}$*n+n**2_${ik}$+n+lwunmlq,n+n**2_${ik}$+lwsvdj, n+& lwunmqrm ) else minwrk = max( n+lwqp3, 2_${ik}$*n+n**2_${ik}$+lwcon,2_${ik}$*n+lwqrf, 2_${ik}$*n+& lwqp3,2_${ik}$*n+n**2_${ik}$+n+lwlqf, 2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+n**2_${ik}$+n+lwsvdj, 2_${ik}$*n+& n**2_${ik}$+n+lwsvdjv,2_${ik}$*n+n**2_${ik}$+n+lwunmqr,2_${ik}$*n+n**2_${ik}$+n+lwunmlq,n+n**2_${ik}$+lwsvdj, & n+lwunmqrm ) end if miniwrk = miniwrk + n if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else if ( errest ) then minwrk = max( n+lwqp3, n+lwcon, 2_${ik}$*n+lwqrf,2_${ik}$*n+n**2_${ik}$+lwsvdjv, 2_${ik}$*n+n**2_${ik}$+n+& lwunmqr,n+lwunmqrm ) else minwrk = max( n+lwqp3, 2_${ik}$*n+lwqrf,2_${ik}$*n+n**2_${ik}$+lwsvdjv, 2_${ik}$*n+n**2_${ik}$+n+lwunmqr,n+& lwunmqrm ) end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m end if if ( lquery ) then call stdlib${ii}$_cunmqr( 'L', 'N', m, n, n, a, lda, cdummy, u,ldu, cdummy, -1_${ik}$, & ierr ) lwrk_cunmqrm = real( cdummy(1_${ik}$),KIND=sp) call stdlib${ii}$_cunmqr( 'L', 'N', n, n, n, a, lda, cdummy, u,ldu, cdummy, -1_${ik}$, & ierr ) lwrk_cunmqr = real( cdummy(1_${ik}$),KIND=sp) if ( .not. jracc ) then call stdlib${ii}$_cgeqp3( n,n, a, lda, iwork, cdummy,cdummy, -1_${ik}$,rdummy, ierr ) lwrk_cgeqp3n = real( cdummy(1_${ik}$),KIND=sp) call stdlib${ii}$_cgesvj( 'L', 'U', 'N', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_cgesvj = real( cdummy(1_${ik}$),KIND=sp) call stdlib${ii}$_cgesvj( 'U', 'U', 'N', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_cgesvju = real( cdummy(1_${ik}$),KIND=sp) call stdlib${ii}$_cgesvj( 'L', 'U', 'V', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_cgesvjv = real( cdummy(1_${ik}$),KIND=sp) call stdlib${ii}$_cunmlq( 'L', 'C', n, n, n, a, lda, cdummy,v, ldv, cdummy, -& 1_${ik}$, ierr ) lwrk_cunmlq = real( cdummy(1_${ik}$),KIND=sp) if ( errest ) then optwrk = max( n+lwrk_cgeqp3, n+lwcon,2_${ik}$*n+n**2_${ik}$+lwcon, 2_${ik}$*n+lwrk_cgeqrf,& 2_${ik}$*n+lwrk_cgeqp3n,2_${ik}$*n+n**2_${ik}$+n+lwrk_cgelqf,2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+& n**2_${ik}$+n+lwrk_cgesvj,2_${ik}$*n+n**2_${ik}$+n+lwrk_cgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_cunmqr,2_${ik}$*n+& n**2_${ik}$+n+lwrk_cunmlq,n+n**2_${ik}$+lwrk_cgesvju,n+lwrk_cunmqrm ) else optwrk = max( n+lwrk_cgeqp3,2_${ik}$*n+n**2_${ik}$+lwcon, 2_${ik}$*n+lwrk_cgeqrf,2_${ik}$*n+& lwrk_cgeqp3n,2_${ik}$*n+n**2_${ik}$+n+lwrk_cgelqf,2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+n**2_${ik}$+n+& lwrk_cgesvj,2_${ik}$*n+n**2_${ik}$+n+lwrk_cgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_cunmqr,2_${ik}$*n+n**2_${ik}$+n+& lwrk_cunmlq,n+n**2_${ik}$+lwrk_cgesvju,n+lwrk_cunmqrm ) end if else call stdlib${ii}$_cgesvj( 'L', 'U', 'V', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_cgesvjv = real( cdummy(1_${ik}$),KIND=sp) call stdlib${ii}$_cunmqr( 'L', 'N', n, n, n, cdummy, n, cdummy,v, ldv, cdummy,& -1_${ik}$, ierr ) lwrk_cunmqr = real( cdummy(1_${ik}$),KIND=sp) call stdlib${ii}$_cunmqr( 'L', 'N', m, n, n, a, lda, cdummy, u,ldu, cdummy, -& 1_${ik}$, ierr ) lwrk_cunmqrm = real( cdummy(1_${ik}$),KIND=sp) if ( errest ) then optwrk = max( n+lwrk_cgeqp3, n+lwcon,2_${ik}$*n+lwrk_cgeqrf, 2_${ik}$*n+n**2_${ik}$,2_${ik}$*n+& n**2_${ik}$+lwrk_cgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_cunmqr,n+lwrk_cunmqrm ) else optwrk = max( n+lwrk_cgeqp3, 2_${ik}$*n+lwrk_cgeqrf,2_${ik}$*n+n**2_${ik}$, 2_${ik}$*n+n**2_${ik}$+& lwrk_cgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_cunmqr,n+lwrk_cunmqrm ) end if end if end if if ( l2tran .or. rowpiv ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj, lrwcon ) end if end if minwrk = max( 2_${ik}$, minwrk ) optwrk = max( optwrk, minwrk ) if ( lwork < minwrk .and. (.not.lquery) ) info = - 17_${ik}$ if ( lrwork < minrwrk .and. (.not.lquery) ) info = - 19_${ik}$ end if if ( info /= 0_${ik}$ ) then ! #:( call stdlib${ii}$_xerbla( 'CGEJSV', - info ) return else if ( lquery ) then cwork(1_${ik}$) = optwrk cwork(2_${ik}$) = minwrk rwork(1_${ik}$) = minrwrk iwork(1_${ik}$) = max( 4_${ik}$, miniwrk ) return end if ! quick return for void matrix (y3k safe) ! #:) if ( ( m == 0_${ik}$ ) .or. ( n == 0_${ik}$ ) ) then iwork(1_${ik}$:4_${ik}$) = 0_${ik}$ rwork(1_${ik}$:7_${ik}$) = 0_${ik}$ return endif ! determine whether the matrix u should be m x n or m x m if ( lsvec ) then n1 = n if ( stdlib_lsame( jobu, 'F' ) ) n1 = m end if ! set numerical parameters ! ! note: make sure stdlib${ii}$_slamch() does not fail on the target architecture. epsln = stdlib${ii}$_slamch('EPSILON') sfmin = stdlib${ii}$_slamch('SAFEMINIMUM') small = sfmin / epsln big = stdlib${ii}$_slamch('O') ! big = one / sfmin ! initialize sva(1:n) = diag( ||a e_i||_2 )_1^n ! (!) if necessary, scale sva() to protect the largest norm from ! overflow. it is possible that this scaling pushes the smallest ! column norm left from the underflow threshold (extreme case). scalem = one / sqrt(real(m,KIND=sp)*real(n,KIND=sp)) noscal = .true. goscal = .true. do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_classq( m, a(1_${ik}$,p), 1_${ik}$, aapp, aaqq ) if ( aapp > big ) then info = - 9_${ik}$ call stdlib${ii}$_xerbla( 'CGEJSV', -info ) return end if aaqq = sqrt(aaqq) if ( ( aapp < (big / aaqq) ) .and. noscal ) then sva(p) = aapp * aaqq else noscal = .false. sva(p) = aapp * ( aaqq * scalem ) if ( goscal ) then goscal = .false. call stdlib${ii}$_sscal( p-1, scalem, sva, 1_${ik}$ ) end if end if end do if ( noscal ) scalem = one aapp = zero aaqq = big do p = 1, n aapp = max( aapp, sva(p) ) if ( sva(p) /= zero ) aaqq = min( aaqq, sva(p) ) end do ! quick return for zero m x n matrix ! #:) if ( aapp == zero ) then if ( lsvec ) call stdlib${ii}$_claset( 'G', m, n1, czero, cone, u, ldu ) if ( rsvec ) call stdlib${ii}$_claset( 'G', n, n, czero, cone, v, ldv ) rwork(1_${ik}$) = one rwork(2_${ik}$) = one if ( errest ) rwork(3_${ik}$) = one if ( lsvec .and. rsvec ) then rwork(4_${ik}$) = one rwork(5_${ik}$) = one end if if ( l2tran ) then rwork(6_${ik}$) = zero rwork(7_${ik}$) = zero end if iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ iwork(3_${ik}$) = 0_${ik}$ iwork(4_${ik}$) = -1_${ik}$ return end if ! issue warning if denormalized column norms detected. override the ! high relative accuracy request. issue licence to kill nonzero columns ! (set them to zero) whose norm is less than sigma_max / big (roughly). ! #:( warning = 0_${ik}$ if ( aaqq <= sfmin ) then l2rank = .true. l2kill = .true. warning = 1_${ik}$ end if ! quick return for one-column matrix ! #:) if ( n == 1_${ik}$ ) then if ( lsvec ) then call stdlib${ii}$_clascl( 'G',0_${ik}$,0_${ik}$,sva(1_${ik}$),scalem, m,1_${ik}$,a(1_${ik}$,1_${ik}$),lda,ierr ) call stdlib${ii}$_clacpy( 'A', m, 1_${ik}$, a, lda, u, ldu ) ! computing all m left singular vectors of the m x 1 matrix if ( n1 /= n ) then call stdlib${ii}$_cgeqrf( m, n, u,ldu, cwork, cwork(n+1),lwork-n,ierr ) call stdlib${ii}$_cungqr( m,n1,1_${ik}$, u,ldu,cwork,cwork(n+1),lwork-n,ierr ) call stdlib${ii}$_ccopy( m, a(1_${ik}$,1_${ik}$), 1_${ik}$, u(1_${ik}$,1_${ik}$), 1_${ik}$ ) end if end if if ( rsvec ) then v(1_${ik}$,1_${ik}$) = cone end if if ( sva(1_${ik}$) < (big*scalem) ) then sva(1_${ik}$) = sva(1_${ik}$) / scalem scalem = one end if rwork(1_${ik}$) = one / scalem rwork(2_${ik}$) = one if ( sva(1_${ik}$) /= zero ) then iwork(1_${ik}$) = 1_${ik}$ if ( ( sva(1_${ik}$) / scalem) >= sfmin ) then iwork(2_${ik}$) = 1_${ik}$ else iwork(2_${ik}$) = 0_${ik}$ end if else iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ end if iwork(3_${ik}$) = 0_${ik}$ iwork(4_${ik}$) = -1_${ik}$ if ( errest ) rwork(3_${ik}$) = one if ( lsvec .and. rsvec ) then rwork(4_${ik}$) = one rwork(5_${ik}$) = one end if if ( l2tran ) then rwork(6_${ik}$) = zero rwork(7_${ik}$) = zero end if return end if transp = .false. aatmax = -one aatmin = big if ( rowpiv .or. l2tran ) then ! compute the row norms, needed to determine row pivoting sequence ! (in the case of heavily row weighted a, row pivoting is strongly ! advised) and to collect information needed to compare the ! structures of a * a^* and a^* * a (in the case l2tran==.true.). if ( l2tran ) then do p = 1, m xsc = zero temp1 = one call stdlib${ii}$_classq( n, a(p,1_${ik}$), lda, xsc, temp1 ) ! stdlib${ii}$_classq gets both the ell_2 and the ell_infinity norm ! in one pass through the vector rwork(m+p) = xsc * scalem rwork(p) = xsc * (scalem*sqrt(temp1)) aatmax = max( aatmax, rwork(p) ) if (rwork(p) /= zero)aatmin = min(aatmin,rwork(p)) end do else do p = 1, m rwork(m+p) = scalem*abs( a(p,stdlib${ii}$_icamax(n,a(p,1_${ik}$),lda)) ) aatmax = max( aatmax, rwork(m+p) ) aatmin = min( aatmin, rwork(m+p) ) end do end if end if ! for square matrix a try to determine whether a^* would be better ! input for the preconditioned jacobi svd, with faster convergence. ! the decision is based on an o(n) function of the vector of column ! and row norms of a, based on the shannon entropy. this should give ! the right choice in most cases when the difference actually matters. ! it may fail and pick the slower converging side. entra = zero entrat = zero if ( l2tran ) then xsc = zero temp1 = one call stdlib${ii}$_slassq( n, sva, 1_${ik}$, xsc, temp1 ) temp1 = one / temp1 entra = zero do p = 1, n big1 = ( ( sva(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entra = entra + big1 * log(big1) end do entra = - entra / log(real(n,KIND=sp)) ! now, sva().^2/trace(a^* * a) is a point in the probability simplex. ! it is derived from the diagonal of a^* * a. do the same with the ! diagonal of a * a^*, compute the entropy of the corresponding ! probability distribution. note that a * a^* and a^* * a have the ! same trace. entrat = zero do p = 1, m big1 = ( ( rwork(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entrat = entrat + big1 * log(big1) end do entrat = - entrat / log(real(m,KIND=sp)) ! analyze the entropies and decide a or a^*. smaller entropy ! usually means better input for the algorithm. transp = ( entrat < entra ) ! if a^* is better than a, take the adjoint of a. this is allowed ! only for square matrices, m=n. if ( transp ) then ! in an optimal implementation, this trivial transpose ! should be replaced with faster transpose. do p = 1, n - 1 a(p,p) = conjg(a(p,p)) do q = p + 1, n ctemp = conjg(a(q,p)) a(q,p) = conjg(a(p,q)) a(p,q) = ctemp end do end do a(n,n) = conjg(a(n,n)) do p = 1, n rwork(m+p) = sva(p) sva(p) = rwork(p) ! previously computed row 2-norms are now column 2-norms ! of the transposed matrix end do temp1 = aapp aapp = aatmax aatmax = temp1 temp1 = aaqq aaqq = aatmin aatmin = temp1 kill = lsvec lsvec = rsvec rsvec = kill if ( lsvec ) n1 = n rowpiv = .true. end if end if ! end if l2tran ! scale the matrix so that its maximal singular value remains less ! than sqrt(big) -- the matrix is scaled so that its maximal column ! has euclidean norm equal to sqrt(big/n). the only reason to keep ! sqrt(big) instead of big is the fact that stdlib${ii}$_cgejsv uses lapack and ! blas routines that, in some implementations, are not capable of ! working in the full interval [sfmin,big] and that they may provoke ! overflows in the intermediate results. if the singular values spread ! from sfmin to big, then stdlib${ii}$_cgesvj will compute them. so, in that case, ! one should use stdlib_cgesvj instead of stdlib${ii}$_cgejsv. big1 = sqrt( big ) temp1 = sqrt( big / real(n,KIND=sp) ) ! >> for future updates: allow bigger range, i.e. the largest column ! will be allowed up to big/n and stdlib${ii}$_cgesvj will do the rest. however, for ! this all other (lapack) components must allow such a range. ! temp1 = big/real(n,KIND=sp) ! temp1 = big * epsln this should 'almost' work with current lapack components call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, n, 1_${ik}$, sva, n, ierr ) if ( aaqq > (aapp * sfmin) ) then aaqq = ( aaqq / aapp ) * temp1 else aaqq = ( aaqq * temp1 ) / aapp end if temp1 = temp1 * scalem call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, m, n, a, lda, ierr ) ! to undo scaling at the end of this procedure, multiply the ! computed singular values with uscal2 / uscal1. uscal1 = temp1 uscal2 = aapp if ( l2kill ) then ! l2kill enforces computation of nonzero singular values in ! the restricted range of condition number of the initial a, ! sigma_max(a) / sigma_min(a) approx. sqrt(big)/sqrt(sfmin). xsc = sqrt( sfmin ) else xsc = small ! now, if the condition number of a is too big, ! sigma_max(a) / sigma_min(a) > sqrt(big/n) * epsln / sfmin, ! as a precaution measure, the full svd is computed using stdlib${ii}$_cgesvj ! with accumulated jacobi rotations. this provides numerically ! more robust computation, at the cost of slightly increased run ! time. depending on the concrete implementation of blas and lapack ! (i.e. how they behave in presence of extreme ill-conditioning) the ! implementor may decide to remove this switch. if ( ( aaqq= (temp1*abs(a(1_${ik}$,1_${ik}$))) ) then nr = nr + 1_${ik}$ else exit loop_3002 end if end do loop_3002 else if ( l2rank ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r1 is used as the criterion for ! close-to-rank-deficient. temp1 = sqrt(sfmin) loop_3402: do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < small ) .or.( & l2kill .and. (abs(a(p,p)) < temp1) ) ) exit loop_3402 nr = nr + 1_${ik}$ end do loop_3402 else ! the goal is high relative accuracy. however, if the matrix ! has high scaled condition number the relative accuracy is in ! general not feasible. later on, a condition number estimator ! will be deployed to estimate the scaled condition number. ! here we just remove the underflowed part of the triangular ! factor. this prevents the situation in which the code is ! working hard to get the accuracy not warranted by the data. temp1 = sqrt(sfmin) loop_3302: do p = 2, n if ( ( abs(a(p,p)) < small ) .or.( l2kill .and. (abs(a(p,p)) < temp1) ) ) exit loop_3302 nr = nr + 1_${ik}$ end do loop_3302 end if almort = .false. if ( nr == n ) then maxprj = one do p = 2, n temp1 = abs(a(p,p)) / sva(iwork(p)) maxprj = min( maxprj, temp1 ) end do if ( maxprj**2_${ik}$ >= one - real(n,KIND=sp)*epsln ) almort = .true. end if sconda = - one condr1 = - one condr2 = - one if ( errest ) then if ( n == nr ) then if ( rsvec ) then ! V Is Available As Workspace call stdlib${ii}$_clacpy( 'U', n, n, a, lda, v, ldv ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_csscal( p, one/temp1, v(1_${ik}$,p), 1_${ik}$ ) end do if ( lsvec )then call stdlib${ii}$_cpocon( 'U', n, v, ldv, one, temp1,cwork(n+1), rwork, ierr ) else call stdlib${ii}$_cpocon( 'U', n, v, ldv, one, temp1,cwork, rwork, ierr ) end if else if ( lsvec ) then ! U Is Available As Workspace call stdlib${ii}$_clacpy( 'U', n, n, a, lda, u, ldu ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_csscal( p, one/temp1, u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_cpocon( 'U', n, u, ldu, one, temp1,cwork(n+1), rwork, ierr ) else call stdlib${ii}$_clacpy( 'U', n, n, a, lda, cwork, n ) ! [] call stdlib${ii}$_clacpy( 'u', n, n, a, lda, cwork(n+1), n ) ! change: here index shifted by n to the left, cwork(1:n) ! not needed for sigma only computation do p = 1, n temp1 = sva(iwork(p)) ! [] call stdlib${ii}$_csscal( p, one/temp1, cwork(n+(p-1)*n+1), 1 ) call stdlib${ii}$_csscal( p, one/temp1, cwork((p-1)*n+1), 1_${ik}$ ) end do ! The Columns Of R Are Scaled To Have Unit Euclidean Lengths ! [] call stdlib${ii}$_cpocon( 'u', n, cwork(n+1), n, one, temp1, ! [] $ cwork(n+n*n+1), rwork, ierr ) call stdlib${ii}$_cpocon( 'U', n, cwork, n, one, temp1,cwork(n*n+1), rwork, ierr ) end if if ( temp1 /= zero ) then sconda = one / sqrt(temp1) else sconda = - one end if ! sconda is an estimate of sqrt(||(r^* * r)^(-1)||_1). ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda else sconda = - one end if end if l2pert = l2pert .and. ( abs( a(1_${ik}$,1_${ik}$)/a(nr,nr) ) > sqrt(big1) ) ! if there is no violent scaling, artificial perturbation is not needed. ! phase 3: if ( .not. ( rsvec .or. lsvec ) ) then ! singular values only ! .. transpose a(1:nr,1:n) do p = 1, min( n-1, nr ) call stdlib${ii}$_ccopy( n-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) call stdlib${ii}$_clacgv( n-p+1, a(p,p), 1_${ik}$ ) end do if ( nr == n ) a(n,n) = conjg(a(n,n)) ! the following two do-loops introduce small relative perturbation ! into the strict upper triangle of the lower triangular matrix. ! small entries below the main diagonal are also changed. ! this modification is useful if the computing environment does not ! provide/allow flush to zero underflow, for it prevents many ! annoying denormalized numbers in case of strongly scaled matrices. ! the perturbation is structured so that it does not introduce any ! new perturbation of the singular values, and it does not destroy ! the job done by the preconditioner. ! the licence for this perturbation is in the variable l2pert, which ! should be .false. if flush to zero underflow is active. if ( .not. almort ) then if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=sp) do q = 1, nr ctemp = cmplx(xsc*abs(a(q,q)),zero,KIND=sp) do p = 1, n if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = & ctemp ! $ a(p,q) = temp1 * ( a(p,q) / abs(a(p,q)) ) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_claset( 'U', nr-1,nr-1, czero,czero, a(1_${ik}$,2_${ik}$),lda ) end if ! Second Preconditioning Using The Qr Factorization call stdlib${ii}$_cgeqrf( n,nr, a,lda, cwork, cwork(n+1),lwork-n, ierr ) ! And Transpose Upper To Lower Triangular do p = 1, nr - 1 call stdlib${ii}$_ccopy( nr-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) call stdlib${ii}$_clacgv( nr-p+1, a(p,p), 1_${ik}$ ) end do end if ! row-cyclic jacobi svd algorithm with column pivoting ! .. again some perturbation (a "background noise") is added ! to drown denormals if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=sp) do q = 1, nr ctemp = cmplx(xsc*abs(a(q,q)),zero,KIND=sp) do p = 1, nr if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = & ctemp ! $ a(p,q) = temp1 * ( a(p,q) / abs(a(p,q)) ) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_claset( 'U', nr-1, nr-1, czero, czero, a(1_${ik}$,2_${ik}$), lda ) end if ! .. and one-sided jacobi rotations are started on a lower ! triangular matrix (plus perturbation which is ignored in ! the part which destroys triangular form (confusing?!)) call stdlib${ii}$_cgesvj( 'L', 'N', 'N', nr, nr, a, lda, sva,n, v, ldv, cwork, lwork, & rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) else if ( ( rsvec .and. ( .not. lsvec ) .and. ( .not. jracc ) ).or.( jracc .and. ( & .not. lsvec ) .and. ( nr /= n ) ) ) then ! -> singular values and right singular vectors <- if ( almort ) then ! In This Case Nr Equals N do p = 1, nr call stdlib${ii}$_ccopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) call stdlib${ii}$_clacgv( n-p+1, v(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_claset( 'U', nr-1,nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_cgesvj( 'L','U','N', n, nr, v, ldv, sva, nr, a, lda,cwork, lwork, & rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) else ! .. two more qr factorizations ( one qrf is not enough, two require ! accumulated product of jacobi rotations, three are perfect ) if (nr>1_${ik}$) call stdlib${ii}$_claset( 'L', nr-1,nr-1, czero, czero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_cgelqf( nr,n, a, lda, cwork, cwork(n+1), lwork-n, ierr) call stdlib${ii}$_clacpy( 'L', nr, nr, a, lda, v, ldv ) if (nr>1_${ik}$) call stdlib${ii}$_claset( 'U', nr-1,nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_cgeqrf( nr, nr, v, ldv, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr call stdlib${ii}$_ccopy( nr-p+1, v(p,p), ldv, v(p,p), 1_${ik}$ ) call stdlib${ii}$_clacgv( nr-p+1, v(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_claset('U', nr-1, nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv) call stdlib${ii}$_cgesvj( 'L', 'U','N', nr, nr, v,ldv, sva, nr, u,ldu, cwork(n+1), & lwork-n, rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_claset( 'A',n-nr, nr, czero,czero, v(nr+1,1_${ik}$), ldv ) call stdlib${ii}$_claset( 'A',nr, n-nr, czero,czero, v(1_${ik}$,nr+1), ldv ) call stdlib${ii}$_claset( 'A',n-nr,n-nr,czero,cone, v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_cunmlq( 'L', 'C', n, n, nr, a, lda, cwork,v, ldv, cwork(n+1), lwork-n, & ierr ) end if ! Permute The Rows Of V ! do 8991 p = 1, n ! call stdlib${ii}$_ccopy( n, v(p,1), ldv, a(iwork(p),1), lda ) 8991 continue ! call stdlib${ii}$_clacpy( 'all', n, n, a, lda, v, ldv ) call stdlib${ii}$_clapmr( .false., n, n, v, ldv, iwork ) if ( transp ) then call stdlib${ii}$_clacpy( 'A', n, n, v, ldv, u, ldu ) end if else if ( jracc .and. (.not. lsvec) .and. ( nr== n ) ) then if (n>1_${ik}$) call stdlib${ii}$_claset( 'L', n-1,n-1, czero, czero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_cgesvj( 'U','N','V', n, n, a, lda, sva, n, v, ldv,cwork, lwork, rwork, & lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) call stdlib${ii}$_clapmr( .false., n, n, v, ldv, iwork ) else if ( lsvec .and. ( .not. rsvec ) ) then ! Singular Values And Left Singular Vectors ! Second Preconditioning Step To Avoid Need To Accumulate ! jacobi rotations in the jacobi iterations. do p = 1, nr call stdlib${ii}$_ccopy( n-p+1, a(p,p), lda, u(p,p), 1_${ik}$ ) call stdlib${ii}$_clacgv( n-p+1, u(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_claset( 'U', nr-1, nr-1, czero, czero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_cgeqrf( n, nr, u, ldu, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr - 1 call stdlib${ii}$_ccopy( nr-p, u(p,p+1), ldu, u(p+1,p), 1_${ik}$ ) call stdlib${ii}$_clacgv( n-p+1, u(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_claset( 'U', nr-1, nr-1, czero, czero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_cgesvj( 'L', 'U', 'N', nr,nr, u, ldu, sva, nr, a,lda, cwork(n+1), lwork-& n, rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < m ) then call stdlib${ii}$_claset( 'A', m-nr, nr,czero, czero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_claset( 'A',nr, n1-nr, czero, czero, u(1_${ik}$,nr+1),ldu ) call stdlib${ii}$_claset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1),ldu ) end if end if call stdlib${ii}$_cunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-n, & ierr ) if ( rowpiv )call stdlib${ii}$_claswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) do p = 1, n1 xsc = one / stdlib${ii}$_scnrm2( m, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_csscal( m, xsc, u(1_${ik}$,p), 1_${ik}$ ) end do if ( transp ) then call stdlib${ii}$_clacpy( 'A', n, n, u, ldu, v, ldv ) end if else ! Full Svd if ( .not. jracc ) then if ( .not. almort ) then ! second preconditioning step (qrf [with pivoting]) ! note that the composition of transpose, qrf and transpose is ! equivalent to an lqf call. since in many libraries the qrf ! seems to be better optimized than the lqf, we do explicit ! transpose and use the qrf. this is subject to changes in an ! optimized implementation of stdlib${ii}$_cgejsv. do p = 1, nr call stdlib${ii}$_ccopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) call stdlib${ii}$_clacgv( n-p+1, v(p,p), 1_${ik}$ ) end do ! The Following Two Loops Perturb Small Entries To Avoid ! denormals in the second qr factorization, where they are ! as good as zeros. this is done to avoid painfully slow ! computation with denormals. the relative size of the perturbation ! is a parameter that can be changed by the implementer. ! this perturbation device will be obsolete on machines with ! properly implemented arithmetic. ! to switch it off, set l2pert=.false. to remove it from the ! code, remove the action under l2pert=.true., leave the else part. ! the following two loops should be blocked and fused with the ! transposed copy above. if ( l2pert ) then xsc = sqrt(small) do q = 1, nr ctemp = cmplx(xsc*abs( v(q,q) ),zero,KIND=sp) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = & ctemp ! $ v(p,q) = temp1 * ( v(p,q) / abs(v(p,q)) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_claset( 'U', nr-1, nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) end if ! estimate the row scaled condition number of r1 ! (if r1 is rectangular, n > nr, then the condition number ! of the leading nr x nr submatrix is estimated.) call stdlib${ii}$_clacpy( 'L', nr, nr, v, ldv, cwork(2_${ik}$*n+1), nr ) do p = 1, nr temp1 = stdlib${ii}$_scnrm2(nr-p+1,cwork(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) call stdlib${ii}$_csscal(nr-p+1,one/temp1,cwork(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) end do call stdlib${ii}$_cpocon('L',nr,cwork(2_${ik}$*n+1),nr,one,temp1,cwork(2_${ik}$*n+nr*nr+1),rwork,& ierr) condr1 = one / sqrt(temp1) ! Here Need A Second Opinion On The Condition Number ! Then Assume Worst Case Scenario ! r1 is ok for inverse <=> condr1 < real(n,KIND=sp) ! more conservative <=> condr1 < sqrt(real(n,KIND=sp)) cond_ok = sqrt(sqrt(real(nr,KIND=sp))) ! [tp] cond_ok is a tuning parameter. if ( condr1 < cond_ok ) then ! .. the second qrf without pivoting. note: in an optimized ! implementation, this qrf should be implemented as the qrf ! of a lower triangular matrix. ! r1^* = q2 * r2 call stdlib${ii}$_cgeqrf( n, nr, v, ldv, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small)/epsln do p = 2, nr do q = 1, p - 1 ctemp=cmplx(xsc*min(abs(v(p,p)),abs(v(q,q))),zero,KIND=sp) if ( abs(v(q,p)) <= temp1 )v(q,p) = ctemp ! $ v(q,p) = temp1 * ( v(q,p) / abs(v(q,p)) ) end do end do end if if ( nr /= n )call stdlib${ii}$_clacpy( 'A', n, nr, v, ldv, cwork(2_${ik}$*n+1), n ) ! .. save ... ! This Transposed Copy Should Be Better Than Naive do p = 1, nr - 1 call stdlib${ii}$_ccopy( nr-p, v(p,p+1), ldv, v(p+1,p), 1_${ik}$ ) call stdlib${ii}$_clacgv(nr-p+1, v(p,p), 1_${ik}$ ) end do v(nr,nr)=conjg(v(nr,nr)) condr2 = condr1 else ! .. ill-conditioned case: second qrf with pivoting ! note that windowed pivoting would be equally good ! numerically, and more run-time efficient. so, in ! an optimal implementation, the next call to stdlib${ii}$_cgeqp3 ! should be replaced with eg. call cgeqpx (acm toms #782) ! with properly (carefully) chosen parameters. ! r1^* * p2 = q2 * r2 do p = 1, nr iwork(n+p) = 0_${ik}$ end do call stdlib${ii}$_cgeqp3( n, nr, v, ldv, iwork(n+1), cwork(n+1),cwork(2_${ik}$*n+1), lwork-& 2_${ik}$*n, rwork, ierr ) ! * call stdlib${ii}$_cgeqrf( n, nr, v, ldv, cwork(n+1), cwork(2*n+1), ! * $ lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 ctemp=cmplx(xsc*min(abs(v(p,p)),abs(v(q,q))),zero,KIND=sp) if ( abs(v(q,p)) <= temp1 )v(q,p) = ctemp ! $ v(q,p) = temp1 * ( v(q,p) / abs(v(q,p)) ) end do end do end if call stdlib${ii}$_clacpy( 'A', n, nr, v, ldv, cwork(2_${ik}$*n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 ctemp=cmplx(xsc*min(abs(v(p,p)),abs(v(q,q))),zero,KIND=sp) ! v(p,q) = - temp1*( v(q,p) / abs(v(q,p)) ) v(p,q) = - ctemp end do end do else if (nr>1_${ik}$) call stdlib${ii}$_claset( 'L',nr-1,nr-1,czero,czero,v(2_${ik}$,1_${ik}$),ldv ) end if ! now, compute r2 = l3 * q3, the lq factorization. call stdlib${ii}$_cgelqf( nr, nr, v, ldv, cwork(2_${ik}$*n+n*nr+1),cwork(2_${ik}$*n+n*nr+nr+1), & lwork-2*n-n*nr-nr, ierr ) ! And Estimate The Condition Number call stdlib${ii}$_clacpy( 'L',nr,nr,v,ldv,cwork(2_${ik}$*n+n*nr+nr+1),nr ) do p = 1, nr temp1 = stdlib${ii}$_scnrm2( p, cwork(2_${ik}$*n+n*nr+nr+p), nr ) call stdlib${ii}$_csscal( p, one/temp1, cwork(2_${ik}$*n+n*nr+nr+p), nr ) end do call stdlib${ii}$_cpocon( 'L',nr,cwork(2_${ik}$*n+n*nr+nr+1),nr,one,temp1,cwork(2_${ik}$*n+n*nr+& nr+nr*nr+1),rwork,ierr ) condr2 = one / sqrt(temp1) if ( condr2 >= cond_ok ) then ! Save The Householder Vectors Used For Q3 ! (this overwrites the copy of r2, as it will not be ! needed in this branch, but it does not overwritte the ! huseholder vectors of q2.). call stdlib${ii}$_clacpy( 'U', nr, nr, v, ldv, cwork(2_${ik}$*n+1), n ) ! And The Rest Of The Information On Q3 Is In ! work(2*n+n*nr+1:2*n+n*nr+n) end if end if if ( l2pert ) then xsc = sqrt(small) do q = 2, nr ctemp = xsc * v(q,q) do p = 1, q - 1 ! v(p,q) = - temp1*( v(p,q) / abs(v(p,q)) ) v(p,q) = - ctemp end do end do else if (nr>1_${ik}$) call stdlib${ii}$_claset( 'U', nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$), ldv ) end if ! second preconditioning finished; continue with jacobi svd ! the input matrix is lower trinagular. ! recover the right singular vectors as solution of a well ! conditioned triangular matrix equation. if ( condr1 < cond_ok ) then call stdlib${ii}$_cgesvj( 'L','U','N',nr,nr,v,ldv,sva,nr,u, ldu,cwork(2_${ik}$*n+n*nr+nr+1)& ,lwork-2*n-n*nr-nr,rwork,lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_ccopy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_csscal( nr, sva(p), v(1_${ik}$,p), 1_${ik}$ ) end do ! Pick The Right Matrix Equation And Solve It if ( nr == n ) then ! :)) .. best case, r1 is inverted. the solution of this matrix ! equation is q2*v2 = the product of the jacobi rotations ! used in stdlib${ii}$_cgesvj, premultiplied with the orthogonal matrix ! from the second qr factorization. call stdlib${ii}$_ctrsm('L','U','N','N', nr,nr,cone, a,lda, v,ldv) else ! .. r1 is well conditioned, but non-square. adjoint of r2 ! is inverted to get the product of the jacobi rotations ! used in stdlib${ii}$_cgesvj. the q-factor from the second qr ! factorization is then built in explicitly. call stdlib${ii}$_ctrsm('L','U','C','N',nr,nr,cone,cwork(2_${ik}$*n+1),n,v,ldv) if ( nr < n ) then call stdlib${ii}$_claset('A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_claset('A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_claset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_cunmqr('L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(& 2_${ik}$*n+n*nr+nr+1),lwork-2*n-n*nr-nr,ierr) end if else if ( condr2 < cond_ok ) then ! the matrix r2 is inverted. the solution of the matrix equation ! is q3^* * v3 = the product of the jacobi rotations (appplied to ! the lower triangular l3 from the lq factorization of ! r2=l3*q3), pre-multiplied with the transposed q3. call stdlib${ii}$_cgesvj( 'L', 'U', 'N', nr, nr, v, ldv, sva, nr, u,ldu, cwork(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr,rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_ccopy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_csscal( nr, sva(p), u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_ctrsm('L','U','N','N',nr,nr,cone,cwork(2_${ik}$*n+1),n,u,ldu) ! Apply The Permutation From The Second Qr Factorization do q = 1, nr do p = 1, nr cwork(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do end do if ( nr < n ) then call stdlib${ii}$_claset( 'A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_claset( 'A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_claset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_cunmqr( 'L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) else ! last line of defense. ! #:( this is a rather pathological case: no scaled condition ! improvement after two pivoted qr factorizations. other ! possibility is that the rank revealing qr factorization ! or the condition estimator has failed, or the cond_ok ! is set very close to one (which is unnecessary). normally, ! this branch should never be executed, but in rare cases of ! failure of the rrqr or condition estimator, the last line of ! defense ensures that stdlib${ii}$_cgejsv completes the task. ! compute the full svd of l3 using stdlib${ii}$_cgesvj with explicit ! accumulation of jacobi rotations. call stdlib${ii}$_cgesvj( 'L', 'U', 'V', nr, nr, v, ldv, sva, nr, u,ldu, cwork(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr,rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_claset( 'A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_claset( 'A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_claset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_cunmqr( 'L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) call stdlib${ii}$_cunmlq( 'L', 'C', nr, nr, nr, cwork(2_${ik}$*n+1), n,cwork(2_${ik}$*n+n*nr+1), & u, ldu, cwork(2_${ik}$*n+n*nr+nr+1),lwork-2*n-n*nr-nr, ierr ) do q = 1, nr do p = 1, nr cwork(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do end do end if ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=sp)) * epsln do q = 1, n do p = 1, n cwork(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_scnrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_csscal( n, xsc,& v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_claset('A', m-nr, nr, czero, czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_claset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_claset('A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1),ldu) end if end if ! the q matrix from the first qrf is built into the left singular ! matrix u. this applies to all cases. call stdlib${ii}$_cunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-& n, ierr ) ! the columns of u are normalized. the cost is o(m*n) flops. temp1 = sqrt(real(m,KIND=sp)) * epsln do p = 1, nr xsc = one / stdlib${ii}$_scnrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_csscal( m, xsc,& u(1_${ik}$,p), 1_${ik}$ ) end do ! if the initial qrf is computed with row pivoting, the left ! singular vectors must be adjusted. if ( rowpiv )call stdlib${ii}$_claswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) else ! The Initial Matrix A Has Almost Orthogonal Columns And ! the second qrf is not needed call stdlib${ii}$_clacpy( 'U', n, n, a, lda, cwork(n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, n ctemp = xsc * cwork( n + (p-1)*n + p ) do q = 1, p - 1 ! cwork(n+(q-1)*n+p)=-temp1 * ( cwork(n+(p-1)*n+q) / ! $ abs(cwork(n+(p-1)*n+q)) ) cwork(n+(q-1)*n+p)=-ctemp end do end do else call stdlib${ii}$_claset( 'L',n-1,n-1,czero,czero,cwork(n+2),n ) end if call stdlib${ii}$_cgesvj( 'U', 'U', 'N', n, n, cwork(n+1), n, sva,n, u, ldu, cwork(n+& n*n+1), lwork-n-n*n, rwork, lrwork,info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) do p = 1, n call stdlib${ii}$_ccopy( n, cwork(n+(p-1)*n+1), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_csscal( n, sva(p), cwork(n+(p-1)*n+1), 1_${ik}$ ) end do call stdlib${ii}$_ctrsm( 'L', 'U', 'N', 'N', n, n,cone, a, lda, cwork(n+1), n ) do p = 1, n call stdlib${ii}$_ccopy( n, cwork(n+p), n, v(iwork(p),1_${ik}$), ldv ) end do temp1 = sqrt(real(n,KIND=sp))*epsln do p = 1, n xsc = one / stdlib${ii}$_scnrm2( n, v(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_csscal( n, xsc,& v(1_${ik}$,p), 1_${ik}$ ) end do ! assemble the left singular vector matrix u (m x n). if ( n < m ) then call stdlib${ii}$_claset( 'A', m-n, n, czero, czero, u(n+1,1_${ik}$), ldu ) if ( n < n1 ) then call stdlib${ii}$_claset('A',n, n1-n, czero, czero, u(1_${ik}$,n+1),ldu) call stdlib${ii}$_claset( 'A',m-n,n1-n, czero, cone,u(n+1,n+1),ldu) end if end if call stdlib${ii}$_cunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-& n, ierr ) temp1 = sqrt(real(m,KIND=sp))*epsln do p = 1, n1 xsc = one / stdlib${ii}$_scnrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_csscal( m, xsc,& u(1_${ik}$,p), 1_${ik}$ ) end do if ( rowpiv )call stdlib${ii}$_claswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) end if ! end of the >> almost orthogonal case << in the full svd else ! this branch deploys a preconditioned jacobi svd with explicitly ! accumulated rotations. it is included as optional, mainly for ! experimental purposes. it does perform well, and can also be used. ! in this implementation, this branch will be automatically activated ! if the condition number sigma_max(a) / sigma_min(a) is predicted ! to be greater than the overflow threshold. this is because the ! a posteriori computation of the singular vectors assumes robust ! implementation of blas and some lapack procedures, capable of working ! in presence of extreme values, e.g. when the singular values spread from ! the underflow to the overflow threshold. do p = 1, nr call stdlib${ii}$_ccopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) call stdlib${ii}$_clacgv( n-p+1, v(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 1, nr ctemp = cmplx(xsc*abs( v(q,q) ),zero,KIND=sp) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = & ctemp ! $ v(p,q) = temp1 * ( v(p,q) / abs(v(p,q)) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_claset( 'U', nr-1, nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) end if call stdlib${ii}$_cgeqrf( n, nr, v, ldv, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) call stdlib${ii}$_clacpy( 'L', n, nr, v, ldv, cwork(2_${ik}$*n+1), n ) do p = 1, nr call stdlib${ii}$_ccopy( nr-p+1, v(p,p), ldv, u(p,p), 1_${ik}$ ) call stdlib${ii}$_clacgv( nr-p+1, u(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 2, nr do p = 1, q - 1 ctemp = cmplx(xsc * min(abs(u(p,p)),abs(u(q,q))),zero,KIND=sp) ! u(p,q) = - temp1 * ( u(q,p) / abs(u(q,p)) ) u(p,q) = - ctemp end do end do else if (nr>1_${ik}$) call stdlib${ii}$_claset('U', nr-1, nr-1, czero, czero, u(1_${ik}$,2_${ik}$), ldu ) end if call stdlib${ii}$_cgesvj( 'L', 'U', 'V', nr, nr, u, ldu, sva,n, v, ldv, cwork(2_${ik}$*n+n*nr+1),& lwork-2*n-n*nr,rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_claset( 'A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_claset( 'A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_claset( 'A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_cunmqr( 'L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(2_${ik}$*n+n*nr+& nr+1),lwork-2*n-n*nr-nr,ierr ) ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=sp)) * epsln do q = 1, n do p = 1, n cwork(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_scnrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_csscal( n, xsc,& v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_claset( 'A', m-nr, nr, czero, czero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_claset('A',nr, n1-nr, czero, czero, u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_claset('A',m-nr,n1-nr, czero, cone,u(nr+1,nr+1),ldu) end if end if call stdlib${ii}$_cunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-n, & ierr ) if ( rowpiv )call stdlib${ii}$_claswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) end if if ( transp ) then ! .. swap u and v because the procedure worked on a^* do p = 1, n call stdlib${ii}$_cswap( n, u(1_${ik}$,p), 1_${ik}$, v(1_${ik}$,p), 1_${ik}$ ) end do end if end if ! end of the full svd ! undo scaling, if necessary (and possible) if ( uscal2 <= (big/sva(1_${ik}$))*uscal1 ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, uscal1, uscal2, nr, 1_${ik}$, sva, n, ierr ) uscal1 = one uscal2 = one end if if ( nr < n ) then do p = nr+1, n sva(p) = zero end do end if rwork(1_${ik}$) = uscal2 * scalem rwork(2_${ik}$) = uscal1 if ( errest ) rwork(3_${ik}$) = sconda if ( lsvec .and. rsvec ) then rwork(4_${ik}$) = condr1 rwork(5_${ik}$) = condr2 end if if ( l2tran ) then rwork(6_${ik}$) = entra rwork(7_${ik}$) = entrat end if iwork(1_${ik}$) = nr iwork(2_${ik}$) = numrank iwork(3_${ik}$) = warning if ( transp ) then iwork(4_${ik}$) = 1_${ik}$ else iwork(4_${ik}$) = -1_${ik}$ end if return end subroutine stdlib${ii}$_cgejsv pure module subroutine stdlib${ii}$_zgejsv( joba, jobu, jobv, jobr, jobt, jobp,m, n, a, lda, sva, u, ldu, & !! ZGEJSV computes the singular value decomposition (SVD) of a complex M-by-N !! matrix [A], where M >= N. The SVD of [A] is written as !! [A] = [U] * [SIGMA] * [V]^*, !! where [SIGMA] is an N-by-N (M-by-N) matrix which is zero except for its N !! diagonal elements, [U] is an M-by-N (or M-by-M) unitary matrix, and !! [V] is an N-by-N unitary matrix. The diagonal elements of [SIGMA] are !! the singular values of [A]. The columns of [U] and [V] are the left and !! the right singular vectors of [A], respectively. The matrices [U] and [V] !! are computed and stored in the arrays U and V, respectively. The diagonal !! of [SIGMA] is computed and stored in the array SVA. v, ldv,cwork, lwork, rwork, lrwork, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldu, ldv, lwork, lrwork, m, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: u(ldu,*), v(ldv,*), cwork(lwork) real(dp), intent(out) :: sva(n), rwork(lrwork) integer(${ik}$), intent(out) :: iwork(*) character, intent(in) :: joba, jobp, jobr, jobt, jobu, jobv ! =========================================================================== ! Local Scalars complex(dp) :: ctemp real(dp) :: aapp, aaqq, aatmax, aatmin, big, big1, cond_ok, condr1, condr2, entra, & entrat, epsln, maxprj, scalem, sconda, sfmin, small, temp1, uscal1, uscal2, xsc integer(${ik}$) :: ierr, n1, nr, numrank, p, q, warning logical(lk) :: almort, defr, errest, goscal, jracc, kill, lquery, lsvec, l2aber, & l2kill, l2pert, l2rank, l2tran, noscal, rowpiv, rsvec, transp integer(${ik}$) :: optwrk, minwrk, minrwrk, miniwrk integer(${ik}$) :: lwcon, lwlqf, lwqp3, lwqrf, lwunmlq, lwunmqr, lwunmqrm, lwsvdj, & lwsvdjv, lrwqp3, lrwcon, lrwsvdj, iwoff integer(${ik}$) :: lwrk_zgelqf, lwrk_zgeqp3, lwrk_zgeqp3n, lwrk_zgeqrf, lwrk_zgesvj, & lwrk_zgesvjv, lwrk_zgesvju, lwrk_zunmlq, lwrk_zunmqr, lwrk_zunmqrm ! Local Arrays complex(dp) :: cdummy(1_${ik}$) real(dp) :: rdummy(1_${ik}$) ! Intrinsic Functions ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) .or. stdlib_lsame( jobu, 'F' ) jracc = stdlib_lsame( jobv, 'J' ) rsvec = stdlib_lsame( jobv, 'V' ) .or. jracc rowpiv = stdlib_lsame( joba, 'F' ) .or. stdlib_lsame( joba, 'G' ) l2rank = stdlib_lsame( joba, 'R' ) l2aber = stdlib_lsame( joba, 'A' ) errest = stdlib_lsame( joba, 'E' ) .or. stdlib_lsame( joba, 'G' ) l2tran = stdlib_lsame( jobt, 'T' ) .and. ( m == n ) l2kill = stdlib_lsame( jobr, 'R' ) defr = stdlib_lsame( jobr, 'N' ) l2pert = stdlib_lsame( jobp, 'P' ) lquery = ( lwork == -1_${ik}$ ) .or. ( lrwork == -1_${ik}$ ) if ( .not.(rowpiv .or. l2rank .or. l2aber .or.errest .or. stdlib_lsame( joba, 'C' ) )) & then info = - 1_${ik}$ else if ( .not.( lsvec .or. stdlib_lsame( jobu, 'N' ) .or.( stdlib_lsame( jobu, 'W' ) & .and. rsvec .and. l2tran ) ) ) then info = - 2_${ik}$ else if ( .not.( rsvec .or. stdlib_lsame( jobv, 'N' ) .or.( stdlib_lsame( jobv, 'W' ) & .and. lsvec .and. l2tran ) ) ) then info = - 3_${ik}$ else if ( .not. ( l2kill .or. defr ) ) then info = - 4_${ik}$ else if ( .not. ( stdlib_lsame(jobt,'T') .or. stdlib_lsame(jobt,'N') ) ) then info = - 5_${ik}$ else if ( .not. ( l2pert .or. stdlib_lsame( jobp, 'N' ) ) ) then info = - 6_${ik}$ else if ( m < 0_${ik}$ ) then info = - 7_${ik}$ else if ( ( n < 0_${ik}$ ) .or. ( n > m ) ) then info = - 8_${ik}$ else if ( lda < m ) then info = - 10_${ik}$ else if ( lsvec .and. ( ldu < m ) ) then info = - 13_${ik}$ else if ( rsvec .and. ( ldv < n ) ) then info = - 15_${ik}$ else ! #:) info = 0_${ik}$ end if if ( info == 0_${ik}$ ) then ! Compute The Minimal And The Optimal Workspace Lengths ! [[the expressions for computing the minimal and the optimal ! values of lcwork, lrwork are written with a lot of redundancy and ! can be simplified. however, this verbose form is useful for ! maintenance and modifications of the code.]] ! .. minimal workspace length for stdlib${ii}$_zgeqp3 of an m x n matrix, ! stdlib${ii}$_zgeqrf of an n x n matrix, stdlib${ii}$_zgelqf of an n x n matrix, ! stdlib${ii}$_zunmlq for computing n x n matrix, stdlib${ii}$_zunmqr for computing n x n ! matrix, stdlib${ii}$_zunmqr for computing m x n matrix, respectively. lwqp3 = n+1 lwqrf = max( 1_${ik}$, n ) lwlqf = max( 1_${ik}$, n ) lwunmlq = max( 1_${ik}$, n ) lwunmqr = max( 1_${ik}$, n ) lwunmqrm = max( 1_${ik}$, m ) ! Minimal Workspace Length For Stdlib_Zpocon Of An N X N Matrix lwcon = 2_${ik}$ * n ! .. minimal workspace length for stdlib${ii}$_zgesvj of an n x n matrix, ! without and with explicit accumulation of jacobi rotations lwsvdj = max( 2_${ik}$ * n, 1_${ik}$ ) lwsvdjv = max( 2_${ik}$ * n, 1_${ik}$ ) ! .. minimal real workspace length for stdlib${ii}$_zgeqp3, stdlib${ii}$_zpocon, stdlib${ii}$_zgesvj lrwqp3 = 2_${ik}$ * n lrwcon = n lrwsvdj = n if ( lquery ) then call stdlib${ii}$_zgeqp3( m, n, a, lda, iwork, cdummy, cdummy, -1_${ik}$,rdummy, ierr ) lwrk_zgeqp3 = real( cdummy(1_${ik}$),KIND=dp) call stdlib${ii}$_zgeqrf( n, n, a, lda, cdummy, cdummy,-1_${ik}$, ierr ) lwrk_zgeqrf = real( cdummy(1_${ik}$),KIND=dp) call stdlib${ii}$_zgelqf( n, n, a, lda, cdummy, cdummy,-1_${ik}$, ierr ) lwrk_zgelqf = real( cdummy(1_${ik}$),KIND=dp) end if minwrk = 2_${ik}$ optwrk = 2_${ik}$ miniwrk = n if ( .not. (lsvec .or. rsvec ) ) then ! Minimal And Optimal Sizes Of The Complex Workspace If ! only the singular values are requested if ( errest ) then minwrk = max( n+lwqp3, n**2_${ik}$+lwcon, n+lwqrf, lwsvdj ) else minwrk = max( n+lwqp3, n+lwqrf, lwsvdj ) end if if ( lquery ) then call stdlib${ii}$_zgesvj( 'L', 'N', 'N', n, n, a, lda, sva, n, v,ldv, cdummy, -1_${ik}$,& rdummy, -1_${ik}$, ierr ) lwrk_zgesvj = real( cdummy(1_${ik}$),KIND=dp) if ( errest ) then optwrk = max( n+lwrk_zgeqp3, n**2_${ik}$+lwcon,n+lwrk_zgeqrf, lwrk_zgesvj ) else optwrk = max( n+lwrk_zgeqp3, n+lwrk_zgeqrf,lwrk_zgesvj ) end if end if if ( l2tran .or. rowpiv ) then if ( errest ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwcon, lrwsvdj ) else minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj ) end if else if ( errest ) then minrwrk = max( 7_${ik}$, lrwqp3, lrwcon, lrwsvdj ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj ) end if end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else if ( rsvec .and. (.not.lsvec) ) then ! Minimal And Optimal Sizes Of The Complex Workspace If The ! singular values and the right singular vectors are requested if ( errest ) then minwrk = max( n+lwqp3, lwcon, lwsvdj, n+lwlqf,2_${ik}$*n+lwqrf, n+lwsvdj, n+& lwunmlq ) else minwrk = max( n+lwqp3, lwsvdj, n+lwlqf, 2_${ik}$*n+lwqrf,n+lwsvdj, n+lwunmlq ) end if if ( lquery ) then call stdlib${ii}$_zgesvj( 'L', 'U', 'N', n,n, u, ldu, sva, n, a,lda, cdummy, -1_${ik}$, & rdummy, -1_${ik}$, ierr ) lwrk_zgesvj = real( cdummy(1_${ik}$),KIND=dp) call stdlib${ii}$_zunmlq( 'L', 'C', n, n, n, a, lda, cdummy,v, ldv, cdummy, -1_${ik}$, & ierr ) lwrk_zunmlq = real( cdummy(1_${ik}$),KIND=dp) if ( errest ) then optwrk = max( n+lwrk_zgeqp3, lwcon, lwrk_zgesvj,n+lwrk_zgelqf, 2_${ik}$*n+& lwrk_zgeqrf,n+lwrk_zgesvj, n+lwrk_zunmlq ) else optwrk = max( n+lwrk_zgeqp3, lwrk_zgesvj,n+lwrk_zgelqf,2_${ik}$*n+lwrk_zgeqrf, n+& lwrk_zgesvj,n+lwrk_zunmlq ) end if end if if ( l2tran .or. rowpiv ) then if ( errest ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj ) end if else if ( errest ) then minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj ) end if end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else if ( lsvec .and. (.not.rsvec) ) then ! Minimal And Optimal Sizes Of The Complex Workspace If The ! singular values and the left singular vectors are requested if ( errest ) then minwrk = n + max( lwqp3,lwcon,n+lwqrf,lwsvdj,lwunmqrm ) else minwrk = n + max( lwqp3, n+lwqrf, lwsvdj, lwunmqrm ) end if if ( lquery ) then call stdlib${ii}$_zgesvj( 'L', 'U', 'N', n,n, u, ldu, sva, n, a,lda, cdummy, -1_${ik}$, & rdummy, -1_${ik}$, ierr ) lwrk_zgesvj = real( cdummy(1_${ik}$),KIND=dp) call stdlib${ii}$_zunmqr( 'L', 'N', m, n, n, a, lda, cdummy, u,ldu, cdummy, -1_${ik}$, & ierr ) lwrk_zunmqrm = real( cdummy(1_${ik}$),KIND=dp) if ( errest ) then optwrk = n + max( lwrk_zgeqp3, lwcon, n+lwrk_zgeqrf,lwrk_zgesvj, & lwrk_zunmqrm ) else optwrk = n + max( lwrk_zgeqp3, n+lwrk_zgeqrf,lwrk_zgesvj, lwrk_zunmqrm ) end if end if if ( l2tran .or. rowpiv ) then if ( errest ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj ) end if else if ( errest ) then minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj ) end if end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else ! Minimal And Optimal Sizes Of The Complex Workspace If The ! full svd is requested if ( .not. jracc ) then if ( errest ) then minwrk = max( n+lwqp3, n+lwcon, 2_${ik}$*n+n**2_${ik}$+lwcon,2_${ik}$*n+lwqrf, 2_${ik}$*n+& lwqp3,2_${ik}$*n+n**2_${ik}$+n+lwlqf, 2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+n**2_${ik}$+n+lwsvdj, 2_${ik}$*n+& n**2_${ik}$+n+lwsvdjv,2_${ik}$*n+n**2_${ik}$+n+lwunmqr,2_${ik}$*n+n**2_${ik}$+n+lwunmlq,n+n**2_${ik}$+lwsvdj, n+& lwunmqrm ) else minwrk = max( n+lwqp3, 2_${ik}$*n+n**2_${ik}$+lwcon,2_${ik}$*n+lwqrf, 2_${ik}$*n+& lwqp3,2_${ik}$*n+n**2_${ik}$+n+lwlqf, 2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+n**2_${ik}$+n+lwsvdj, 2_${ik}$*n+& n**2_${ik}$+n+lwsvdjv,2_${ik}$*n+n**2_${ik}$+n+lwunmqr,2_${ik}$*n+n**2_${ik}$+n+lwunmlq,n+n**2_${ik}$+lwsvdj, & n+lwunmqrm ) end if miniwrk = miniwrk + n if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else if ( errest ) then minwrk = max( n+lwqp3, n+lwcon, 2_${ik}$*n+lwqrf,2_${ik}$*n+n**2_${ik}$+lwsvdjv, 2_${ik}$*n+n**2_${ik}$+n+& lwunmqr,n+lwunmqrm ) else minwrk = max( n+lwqp3, 2_${ik}$*n+lwqrf,2_${ik}$*n+n**2_${ik}$+lwsvdjv, 2_${ik}$*n+n**2_${ik}$+n+lwunmqr,n+& lwunmqrm ) end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m end if if ( lquery ) then call stdlib${ii}$_zunmqr( 'L', 'N', m, n, n, a, lda, cdummy, u,ldu, cdummy, -1_${ik}$, & ierr ) lwrk_zunmqrm = real( cdummy(1_${ik}$),KIND=dp) call stdlib${ii}$_zunmqr( 'L', 'N', n, n, n, a, lda, cdummy, u,ldu, cdummy, -1_${ik}$, & ierr ) lwrk_zunmqr = real( cdummy(1_${ik}$),KIND=dp) if ( .not. jracc ) then call stdlib${ii}$_zgeqp3( n,n, a, lda, iwork, cdummy,cdummy, -1_${ik}$,rdummy, ierr ) lwrk_zgeqp3n = real( cdummy(1_${ik}$),KIND=dp) call stdlib${ii}$_zgesvj( 'L', 'U', 'N', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_zgesvj = real( cdummy(1_${ik}$),KIND=dp) call stdlib${ii}$_zgesvj( 'U', 'U', 'N', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_zgesvju = real( cdummy(1_${ik}$),KIND=dp) call stdlib${ii}$_zgesvj( 'L', 'U', 'V', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_zgesvjv = real( cdummy(1_${ik}$),KIND=dp) call stdlib${ii}$_zunmlq( 'L', 'C', n, n, n, a, lda, cdummy,v, ldv, cdummy, -& 1_${ik}$, ierr ) lwrk_zunmlq = real( cdummy(1_${ik}$),KIND=dp) if ( errest ) then optwrk = max( n+lwrk_zgeqp3, n+lwcon,2_${ik}$*n+n**2_${ik}$+lwcon, 2_${ik}$*n+lwrk_zgeqrf,& 2_${ik}$*n+lwrk_zgeqp3n,2_${ik}$*n+n**2_${ik}$+n+lwrk_zgelqf,2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+& n**2_${ik}$+n+lwrk_zgesvj,2_${ik}$*n+n**2_${ik}$+n+lwrk_zgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_zunmqr,2_${ik}$*n+& n**2_${ik}$+n+lwrk_zunmlq,n+n**2_${ik}$+lwrk_zgesvju,n+lwrk_zunmqrm ) else optwrk = max( n+lwrk_zgeqp3,2_${ik}$*n+n**2_${ik}$+lwcon, 2_${ik}$*n+lwrk_zgeqrf,2_${ik}$*n+& lwrk_zgeqp3n,2_${ik}$*n+n**2_${ik}$+n+lwrk_zgelqf,2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+n**2_${ik}$+n+& lwrk_zgesvj,2_${ik}$*n+n**2_${ik}$+n+lwrk_zgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_zunmqr,2_${ik}$*n+n**2_${ik}$+n+& lwrk_zunmlq,n+n**2_${ik}$+lwrk_zgesvju,n+lwrk_zunmqrm ) end if else call stdlib${ii}$_zgesvj( 'L', 'U', 'V', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_zgesvjv = real( cdummy(1_${ik}$),KIND=dp) call stdlib${ii}$_zunmqr( 'L', 'N', n, n, n, cdummy, n, cdummy,v, ldv, cdummy,& -1_${ik}$, ierr ) lwrk_zunmqr = real( cdummy(1_${ik}$),KIND=dp) call stdlib${ii}$_zunmqr( 'L', 'N', m, n, n, a, lda, cdummy, u,ldu, cdummy, -& 1_${ik}$, ierr ) lwrk_zunmqrm = real( cdummy(1_${ik}$),KIND=dp) if ( errest ) then optwrk = max( n+lwrk_zgeqp3, n+lwcon,2_${ik}$*n+lwrk_zgeqrf, 2_${ik}$*n+n**2_${ik}$,2_${ik}$*n+& n**2_${ik}$+lwrk_zgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_zunmqr,n+lwrk_zunmqrm ) else optwrk = max( n+lwrk_zgeqp3, 2_${ik}$*n+lwrk_zgeqrf,2_${ik}$*n+n**2_${ik}$, 2_${ik}$*n+n**2_${ik}$+& lwrk_zgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_zunmqr,n+lwrk_zunmqrm ) end if end if end if if ( l2tran .or. rowpiv ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj, lrwcon ) end if end if minwrk = max( 2_${ik}$, minwrk ) optwrk = max( minwrk, optwrk ) if ( lwork < minwrk .and. (.not.lquery) ) info = - 17_${ik}$ if ( lrwork < minrwrk .and. (.not.lquery) ) info = - 19_${ik}$ end if if ( info /= 0_${ik}$ ) then ! #:( call stdlib${ii}$_xerbla( 'ZGEJSV', - info ) return else if ( lquery ) then cwork(1_${ik}$) = optwrk cwork(2_${ik}$) = minwrk rwork(1_${ik}$) = minrwrk iwork(1_${ik}$) = max( 4_${ik}$, miniwrk ) return end if ! quick return for void matrix (y3k safe) ! #:) if ( ( m == 0_${ik}$ ) .or. ( n == 0_${ik}$ ) ) then iwork(1_${ik}$:4_${ik}$) = 0_${ik}$ rwork(1_${ik}$:7_${ik}$) = 0_${ik}$ return endif ! determine whether the matrix u should be m x n or m x m if ( lsvec ) then n1 = n if ( stdlib_lsame( jobu, 'F' ) ) n1 = m end if ! set numerical parameters ! ! note: make sure stdlib${ii}$_dlamch() does not fail on the target architecture. epsln = stdlib${ii}$_dlamch('EPSILON') sfmin = stdlib${ii}$_dlamch('SAFEMINIMUM') small = sfmin / epsln big = stdlib${ii}$_dlamch('O') ! big = one / sfmin ! initialize sva(1:n) = diag( ||a e_i||_2 )_1^n ! (!) if necessary, scale sva() to protect the largest norm from ! overflow. it is possible that this scaling pushes the smallest ! column norm left from the underflow threshold (extreme case). scalem = one / sqrt(real(m,KIND=dp)*real(n,KIND=dp)) noscal = .true. goscal = .true. do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_zlassq( m, a(1_${ik}$,p), 1_${ik}$, aapp, aaqq ) if ( aapp > big ) then info = - 9_${ik}$ call stdlib${ii}$_xerbla( 'ZGEJSV', -info ) return end if aaqq = sqrt(aaqq) if ( ( aapp < (big / aaqq) ) .and. noscal ) then sva(p) = aapp * aaqq else noscal = .false. sva(p) = aapp * ( aaqq * scalem ) if ( goscal ) then goscal = .false. call stdlib${ii}$_dscal( p-1, scalem, sva, 1_${ik}$ ) end if end if end do if ( noscal ) scalem = one aapp = zero aaqq = big do p = 1, n aapp = max( aapp, sva(p) ) if ( sva(p) /= zero ) aaqq = min( aaqq, sva(p) ) end do ! quick return for zero m x n matrix ! #:) if ( aapp == zero ) then if ( lsvec ) call stdlib${ii}$_zlaset( 'G', m, n1, czero, cone, u, ldu ) if ( rsvec ) call stdlib${ii}$_zlaset( 'G', n, n, czero, cone, v, ldv ) rwork(1_${ik}$) = one rwork(2_${ik}$) = one if ( errest ) rwork(3_${ik}$) = one if ( lsvec .and. rsvec ) then rwork(4_${ik}$) = one rwork(5_${ik}$) = one end if if ( l2tran ) then rwork(6_${ik}$) = zero rwork(7_${ik}$) = zero end if iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ iwork(3_${ik}$) = 0_${ik}$ iwork(4_${ik}$) = -1_${ik}$ return end if ! issue warning if denormalized column norms detected. override the ! high relative accuracy request. issue licence to kill nonzero columns ! (set them to zero) whose norm is less than sigma_max / big (roughly). ! #:( warning = 0_${ik}$ if ( aaqq <= sfmin ) then l2rank = .true. l2kill = .true. warning = 1_${ik}$ end if ! quick return for one-column matrix ! #:) if ( n == 1_${ik}$ ) then if ( lsvec ) then call stdlib${ii}$_zlascl( 'G',0_${ik}$,0_${ik}$,sva(1_${ik}$),scalem, m,1_${ik}$,a(1_${ik}$,1_${ik}$),lda,ierr ) call stdlib${ii}$_zlacpy( 'A', m, 1_${ik}$, a, lda, u, ldu ) ! computing all m left singular vectors of the m x 1 matrix if ( n1 /= n ) then call stdlib${ii}$_zgeqrf( m, n, u,ldu, cwork, cwork(n+1),lwork-n,ierr ) call stdlib${ii}$_zungqr( m,n1,1_${ik}$, u,ldu,cwork,cwork(n+1),lwork-n,ierr ) call stdlib${ii}$_zcopy( m, a(1_${ik}$,1_${ik}$), 1_${ik}$, u(1_${ik}$,1_${ik}$), 1_${ik}$ ) end if end if if ( rsvec ) then v(1_${ik}$,1_${ik}$) = cone end if if ( sva(1_${ik}$) < (big*scalem) ) then sva(1_${ik}$) = sva(1_${ik}$) / scalem scalem = one end if rwork(1_${ik}$) = one / scalem rwork(2_${ik}$) = one if ( sva(1_${ik}$) /= zero ) then iwork(1_${ik}$) = 1_${ik}$ if ( ( sva(1_${ik}$) / scalem) >= sfmin ) then iwork(2_${ik}$) = 1_${ik}$ else iwork(2_${ik}$) = 0_${ik}$ end if else iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ end if iwork(3_${ik}$) = 0_${ik}$ iwork(4_${ik}$) = -1_${ik}$ if ( errest ) rwork(3_${ik}$) = one if ( lsvec .and. rsvec ) then rwork(4_${ik}$) = one rwork(5_${ik}$) = one end if if ( l2tran ) then rwork(6_${ik}$) = zero rwork(7_${ik}$) = zero end if return end if transp = .false. aatmax = -one aatmin = big if ( rowpiv .or. l2tran ) then ! compute the row norms, needed to determine row pivoting sequence ! (in the case of heavily row weighted a, row pivoting is strongly ! advised) and to collect information needed to compare the ! structures of a * a^* and a^* * a (in the case l2tran==.true.). if ( l2tran ) then do p = 1, m xsc = zero temp1 = one call stdlib${ii}$_zlassq( n, a(p,1_${ik}$), lda, xsc, temp1 ) ! stdlib${ii}$_zlassq gets both the ell_2 and the ell_infinity norm ! in one pass through the vector rwork(m+p) = xsc * scalem rwork(p) = xsc * (scalem*sqrt(temp1)) aatmax = max( aatmax, rwork(p) ) if (rwork(p) /= zero)aatmin = min(aatmin,rwork(p)) end do else do p = 1, m rwork(m+p) = scalem*abs( a(p,stdlib${ii}$_izamax(n,a(p,1_${ik}$),lda)) ) aatmax = max( aatmax, rwork(m+p) ) aatmin = min( aatmin, rwork(m+p) ) end do end if end if ! for square matrix a try to determine whether a^* would be better ! input for the preconditioned jacobi svd, with faster convergence. ! the decision is based on an o(n) function of the vector of column ! and row norms of a, based on the shannon entropy. this should give ! the right choice in most cases when the difference actually matters. ! it may fail and pick the slower converging side. entra = zero entrat = zero if ( l2tran ) then xsc = zero temp1 = one call stdlib${ii}$_dlassq( n, sva, 1_${ik}$, xsc, temp1 ) temp1 = one / temp1 entra = zero do p = 1, n big1 = ( ( sva(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entra = entra + big1 * log(big1) end do entra = - entra / log(real(n,KIND=dp)) ! now, sva().^2/trace(a^* * a) is a point in the probability simplex. ! it is derived from the diagonal of a^* * a. do the same with the ! diagonal of a * a^*, compute the entropy of the corresponding ! probability distribution. note that a * a^* and a^* * a have the ! same trace. entrat = zero do p = 1, m big1 = ( ( rwork(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entrat = entrat + big1 * log(big1) end do entrat = - entrat / log(real(m,KIND=dp)) ! analyze the entropies and decide a or a^*. smaller entropy ! usually means better input for the algorithm. transp = ( entrat < entra ) ! if a^* is better than a, take the adjoint of a. this is allowed ! only for square matrices, m=n. if ( transp ) then ! in an optimal implementation, this trivial transpose ! should be replaced with faster transpose. do p = 1, n - 1 a(p,p) = conjg(a(p,p)) do q = p + 1, n ctemp = conjg(a(q,p)) a(q,p) = conjg(a(p,q)) a(p,q) = ctemp end do end do a(n,n) = conjg(a(n,n)) do p = 1, n rwork(m+p) = sva(p) sva(p) = rwork(p) ! previously computed row 2-norms are now column 2-norms ! of the transposed matrix end do temp1 = aapp aapp = aatmax aatmax = temp1 temp1 = aaqq aaqq = aatmin aatmin = temp1 kill = lsvec lsvec = rsvec rsvec = kill if ( lsvec ) n1 = n rowpiv = .true. end if end if ! end if l2tran ! scale the matrix so that its maximal singular value remains less ! than sqrt(big) -- the matrix is scaled so that its maximal column ! has euclidean norm equal to sqrt(big/n). the only reason to keep ! sqrt(big) instead of big is the fact that stdlib${ii}$_zgejsv uses lapack and ! blas routines that, in some implementations, are not capable of ! working in the full interval [sfmin,big] and that they may provoke ! overflows in the intermediate results. if the singular values spread ! from sfmin to big, then stdlib${ii}$_zgesvj will compute them. so, in that case, ! one should use stdlib_zgesvj instead of stdlib${ii}$_zgejsv. ! >> change in the april 2016 update: allow bigger range, i.e. the ! largest column is allowed up to big/n and stdlib${ii}$_zgesvj will do the rest. big1 = sqrt( big ) temp1 = sqrt( big / real(n,KIND=dp) ) ! temp1 = big/real(n,KIND=dp) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, n, 1_${ik}$, sva, n, ierr ) if ( aaqq > (aapp * sfmin) ) then aaqq = ( aaqq / aapp ) * temp1 else aaqq = ( aaqq * temp1 ) / aapp end if temp1 = temp1 * scalem call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, m, n, a, lda, ierr ) ! to undo scaling at the end of this procedure, multiply the ! computed singular values with uscal2 / uscal1. uscal1 = temp1 uscal2 = aapp if ( l2kill ) then ! l2kill enforces computation of nonzero singular values in ! the restricted range of condition number of the initial a, ! sigma_max(a) / sigma_min(a) approx. sqrt(big)/sqrt(sfmin). xsc = sqrt( sfmin ) else xsc = small ! now, if the condition number of a is too big, ! sigma_max(a) / sigma_min(a) > sqrt(big/n) * epsln / sfmin, ! as a precaution measure, the full svd is computed using stdlib${ii}$_zgesvj ! with accumulated jacobi rotations. this provides numerically ! more robust computation, at the cost of slightly increased run ! time. depending on the concrete implementation of blas and lapack ! (i.e. how they behave in presence of extreme ill-conditioning) the ! implementor may decide to remove this switch. if ( ( aaqq= (temp1*abs(a(1_${ik}$,1_${ik}$))) ) then nr = nr + 1_${ik}$ else exit loop_3002 end if end do loop_3002 else if ( l2rank ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r1 is used as the criterion for ! close-to-rank-deficient. temp1 = sqrt(sfmin) loop_3402: do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < small ) .or.( & l2kill .and. (abs(a(p,p)) < temp1) ) ) exit loop_3402 nr = nr + 1_${ik}$ end do loop_3402 else ! the goal is high relative accuracy. however, if the matrix ! has high scaled condition number the relative accuracy is in ! general not feasible. later on, a condition number estimator ! will be deployed to estimate the scaled condition number. ! here we just remove the underflowed part of the triangular ! factor. this prevents the situation in which the code is ! working hard to get the accuracy not warranted by the data. temp1 = sqrt(sfmin) loop_3302: do p = 2, n if ( ( abs(a(p,p)) < small ) .or.( l2kill .and. (abs(a(p,p)) < temp1) ) ) exit loop_3302 nr = nr + 1_${ik}$ end do loop_3302 end if almort = .false. if ( nr == n ) then maxprj = one do p = 2, n temp1 = abs(a(p,p)) / sva(iwork(p)) maxprj = min( maxprj, temp1 ) end do if ( maxprj**2_${ik}$ >= one - real(n,KIND=dp)*epsln ) almort = .true. end if sconda = - one condr1 = - one condr2 = - one if ( errest ) then if ( n == nr ) then if ( rsvec ) then ! V Is Available As Workspace call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, v, ldv ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_zdscal( p, one/temp1, v(1_${ik}$,p), 1_${ik}$ ) end do if ( lsvec )then call stdlib${ii}$_zpocon( 'U', n, v, ldv, one, temp1,cwork(n+1), rwork, ierr ) else call stdlib${ii}$_zpocon( 'U', n, v, ldv, one, temp1,cwork, rwork, ierr ) end if else if ( lsvec ) then ! U Is Available As Workspace call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, u, ldu ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_zdscal( p, one/temp1, u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_zpocon( 'U', n, u, ldu, one, temp1,cwork(n+1), rwork, ierr ) else call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, cwork, n ) ! [] call stdlib${ii}$_zlacpy( 'u', n, n, a, lda, cwork(n+1), n ) ! change: here index shifted by n to the left, cwork(1:n) ! not needed for sigma only computation do p = 1, n temp1 = sva(iwork(p)) ! [] call stdlib${ii}$_zdscal( p, one/temp1, cwork(n+(p-1)*n+1), 1 ) call stdlib${ii}$_zdscal( p, one/temp1, cwork((p-1)*n+1), 1_${ik}$ ) end do ! The Columns Of R Are Scaled To Have Unit Euclidean Lengths ! [] call stdlib${ii}$_zpocon( 'u', n, cwork(n+1), n, one, temp1, ! [] $ cwork(n+n*n+1), rwork, ierr ) call stdlib${ii}$_zpocon( 'U', n, cwork, n, one, temp1,cwork(n*n+1), rwork, ierr ) end if if ( temp1 /= zero ) then sconda = one / sqrt(temp1) else sconda = - one end if ! sconda is an estimate of sqrt(||(r^* * r)^(-1)||_1). ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda else sconda = - one end if end if l2pert = l2pert .and. ( abs( a(1_${ik}$,1_${ik}$)/a(nr,nr) ) > sqrt(big1) ) ! if there is no violent scaling, artificial perturbation is not needed. ! phase 3: if ( .not. ( rsvec .or. lsvec ) ) then ! singular values only ! .. transpose a(1:nr,1:n) do p = 1, min( n-1, nr ) call stdlib${ii}$_zcopy( n-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) call stdlib${ii}$_zlacgv( n-p+1, a(p,p), 1_${ik}$ ) end do if ( nr == n ) a(n,n) = conjg(a(n,n)) ! the following two do-loops introduce small relative perturbation ! into the strict upper triangle of the lower triangular matrix. ! small entries below the main diagonal are also changed. ! this modification is useful if the computing environment does not ! provide/allow flush to zero underflow, for it prevents many ! annoying denormalized numbers in case of strongly scaled matrices. ! the perturbation is structured so that it does not introduce any ! new perturbation of the singular values, and it does not destroy ! the job done by the preconditioner. ! the licence for this perturbation is in the variable l2pert, which ! should be .false. if flush to zero underflow is active. if ( .not. almort ) then if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=dp) do q = 1, nr ctemp = cmplx(xsc*abs(a(q,q)),zero,KIND=dp) do p = 1, n if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = & ctemp ! $ a(p,q) = temp1 * ( a(p,q) / abs(a(p,q)) ) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_zlaset( 'U', nr-1,nr-1, czero,czero, a(1_${ik}$,2_${ik}$),lda ) end if ! Second Preconditioning Using The Qr Factorization call stdlib${ii}$_zgeqrf( n,nr, a,lda, cwork, cwork(n+1),lwork-n, ierr ) ! And Transpose Upper To Lower Triangular do p = 1, nr - 1 call stdlib${ii}$_zcopy( nr-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) call stdlib${ii}$_zlacgv( nr-p+1, a(p,p), 1_${ik}$ ) end do end if ! row-cyclic jacobi svd algorithm with column pivoting ! .. again some perturbation (a "background noise") is added ! to drown denormals if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=dp) do q = 1, nr ctemp = cmplx(xsc*abs(a(q,q)),zero,KIND=dp) do p = 1, nr if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = & ctemp ! $ a(p,q) = temp1 * ( a(p,q) / abs(a(p,q)) ) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_zlaset( 'U', nr-1, nr-1, czero, czero, a(1_${ik}$,2_${ik}$), lda ) end if ! .. and one-sided jacobi rotations are started on a lower ! triangular matrix (plus perturbation which is ignored in ! the part which destroys triangular form (confusing?!)) call stdlib${ii}$_zgesvj( 'L', 'N', 'N', nr, nr, a, lda, sva,n, v, ldv, cwork, lwork, & rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) else if ( ( rsvec .and. ( .not. lsvec ) .and. ( .not. jracc ) ).or.( jracc .and. ( & .not. lsvec ) .and. ( nr /= n ) ) ) then ! -> singular values and right singular vectors <- if ( almort ) then ! In This Case Nr Equals N do p = 1, nr call stdlib${ii}$_zcopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) call stdlib${ii}$_zlacgv( n-p+1, v(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_zlaset( 'U', nr-1,nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_zgesvj( 'L','U','N', n, nr, v, ldv, sva, nr, a, lda,cwork, lwork, & rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) else ! .. two more qr factorizations ( one qrf is not enough, two require ! accumulated product of jacobi rotations, three are perfect ) if (nr>1_${ik}$) call stdlib${ii}$_zlaset( 'L', nr-1,nr-1, czero, czero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_zgelqf( nr,n, a, lda, cwork, cwork(n+1), lwork-n, ierr) call stdlib${ii}$_zlacpy( 'L', nr, nr, a, lda, v, ldv ) if (nr>1_${ik}$) call stdlib${ii}$_zlaset( 'U', nr-1,nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_zgeqrf( nr, nr, v, ldv, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr call stdlib${ii}$_zcopy( nr-p+1, v(p,p), ldv, v(p,p), 1_${ik}$ ) call stdlib${ii}$_zlacgv( nr-p+1, v(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_zlaset('U', nr-1, nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv) call stdlib${ii}$_zgesvj( 'L', 'U','N', nr, nr, v,ldv, sva, nr, u,ldu, cwork(n+1), & lwork-n, rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_zlaset( 'A',n-nr, nr, czero,czero, v(nr+1,1_${ik}$), ldv ) call stdlib${ii}$_zlaset( 'A',nr, n-nr, czero,czero, v(1_${ik}$,nr+1), ldv ) call stdlib${ii}$_zlaset( 'A',n-nr,n-nr,czero,cone, v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_zunmlq( 'L', 'C', n, n, nr, a, lda, cwork,v, ldv, cwork(n+1), lwork-n, & ierr ) end if ! Permute The Rows Of V ! do 8991 p = 1, n ! call stdlib${ii}$_zcopy( n, v(p,1), ldv, a(iwork(p),1), lda ) 8991 continue ! call stdlib${ii}$_zlacpy( 'all', n, n, a, lda, v, ldv ) call stdlib${ii}$_zlapmr( .false., n, n, v, ldv, iwork ) if ( transp ) then call stdlib${ii}$_zlacpy( 'A', n, n, v, ldv, u, ldu ) end if else if ( jracc .and. (.not. lsvec) .and. ( nr== n ) ) then if (n>1_${ik}$) call stdlib${ii}$_zlaset( 'L', n-1,n-1, czero, czero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_zgesvj( 'U','N','V', n, n, a, lda, sva, n, v, ldv,cwork, lwork, rwork, & lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) call stdlib${ii}$_zlapmr( .false., n, n, v, ldv, iwork ) else if ( lsvec .and. ( .not. rsvec ) ) then ! Singular Values And Left Singular Vectors ! Second Preconditioning Step To Avoid Need To Accumulate ! jacobi rotations in the jacobi iterations. do p = 1, nr call stdlib${ii}$_zcopy( n-p+1, a(p,p), lda, u(p,p), 1_${ik}$ ) call stdlib${ii}$_zlacgv( n-p+1, u(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_zlaset( 'U', nr-1, nr-1, czero, czero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_zgeqrf( n, nr, u, ldu, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr - 1 call stdlib${ii}$_zcopy( nr-p, u(p,p+1), ldu, u(p+1,p), 1_${ik}$ ) call stdlib${ii}$_zlacgv( n-p+1, u(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_zlaset( 'U', nr-1, nr-1, czero, czero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_zgesvj( 'L', 'U', 'N', nr,nr, u, ldu, sva, nr, a,lda, cwork(n+1), lwork-& n, rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < m ) then call stdlib${ii}$_zlaset( 'A', m-nr, nr,czero, czero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_zlaset( 'A',nr, n1-nr, czero, czero, u(1_${ik}$,nr+1),ldu ) call stdlib${ii}$_zlaset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1),ldu ) end if end if call stdlib${ii}$_zunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-n, & ierr ) if ( rowpiv )call stdlib${ii}$_zlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) do p = 1, n1 xsc = one / stdlib${ii}$_dznrm2( m, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_zdscal( m, xsc, u(1_${ik}$,p), 1_${ik}$ ) end do if ( transp ) then call stdlib${ii}$_zlacpy( 'A', n, n, u, ldu, v, ldv ) end if else ! Full Svd if ( .not. jracc ) then if ( .not. almort ) then ! second preconditioning step (qrf [with pivoting]) ! note that the composition of transpose, qrf and transpose is ! equivalent to an lqf call. since in many libraries the qrf ! seems to be better optimized than the lqf, we do explicit ! transpose and use the qrf. this is subject to changes in an ! optimized implementation of stdlib${ii}$_zgejsv. do p = 1, nr call stdlib${ii}$_zcopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) call stdlib${ii}$_zlacgv( n-p+1, v(p,p), 1_${ik}$ ) end do ! The Following Two Loops Perturb Small Entries To Avoid ! denormals in the second qr factorization, where they are ! as good as zeros. this is done to avoid painfully slow ! computation with denormals. the relative size of the perturbation ! is a parameter that can be changed by the implementer. ! this perturbation device will be obsolete on machines with ! properly implemented arithmetic. ! to switch it off, set l2pert=.false. to remove it from the ! code, remove the action under l2pert=.true., leave the else part. ! the following two loops should be blocked and fused with the ! transposed copy above. if ( l2pert ) then xsc = sqrt(small) do q = 1, nr ctemp = cmplx(xsc*abs( v(q,q) ),zero,KIND=dp) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = & ctemp ! $ v(p,q) = temp1 * ( v(p,q) / abs(v(p,q)) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_zlaset( 'U', nr-1, nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) end if ! estimate the row scaled condition number of r1 ! (if r1 is rectangular, n > nr, then the condition number ! of the leading nr x nr submatrix is estimated.) call stdlib${ii}$_zlacpy( 'L', nr, nr, v, ldv, cwork(2_${ik}$*n+1), nr ) do p = 1, nr temp1 = stdlib${ii}$_dznrm2(nr-p+1,cwork(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) call stdlib${ii}$_zdscal(nr-p+1,one/temp1,cwork(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) end do call stdlib${ii}$_zpocon('L',nr,cwork(2_${ik}$*n+1),nr,one,temp1,cwork(2_${ik}$*n+nr*nr+1),rwork,& ierr) condr1 = one / sqrt(temp1) ! Here Need A Second Opinion On The Condition Number ! Then Assume Worst Case Scenario ! r1 is ok for inverse <=> condr1 < real(n,KIND=dp) ! more conservative <=> condr1 < sqrt(real(n,KIND=dp)) cond_ok = sqrt(sqrt(real(nr,KIND=dp))) ! [tp] cond_ok is a tuning parameter. if ( condr1 < cond_ok ) then ! .. the second qrf without pivoting. note: in an optimized ! implementation, this qrf should be implemented as the qrf ! of a lower triangular matrix. ! r1^* = q2 * r2 call stdlib${ii}$_zgeqrf( n, nr, v, ldv, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small)/epsln do p = 2, nr do q = 1, p - 1 ctemp=cmplx(xsc*min(abs(v(p,p)),abs(v(q,q))),zero,KIND=dp) if ( abs(v(q,p)) <= temp1 )v(q,p) = ctemp ! $ v(q,p) = temp1 * ( v(q,p) / abs(v(q,p)) ) end do end do end if if ( nr /= n )call stdlib${ii}$_zlacpy( 'A', n, nr, v, ldv, cwork(2_${ik}$*n+1), n ) ! .. save ... ! This Transposed Copy Should Be Better Than Naive do p = 1, nr - 1 call stdlib${ii}$_zcopy( nr-p, v(p,p+1), ldv, v(p+1,p), 1_${ik}$ ) call stdlib${ii}$_zlacgv(nr-p+1, v(p,p), 1_${ik}$ ) end do v(nr,nr)=conjg(v(nr,nr)) condr2 = condr1 else ! .. ill-conditioned case: second qrf with pivoting ! note that windowed pivoting would be equally good ! numerically, and more run-time efficient. so, in ! an optimal implementation, the next call to stdlib${ii}$_zgeqp3 ! should be replaced with eg. call zgeqpx (acm toms #782) ! with properly (carefully) chosen parameters. ! r1^* * p2 = q2 * r2 do p = 1, nr iwork(n+p) = 0_${ik}$ end do call stdlib${ii}$_zgeqp3( n, nr, v, ldv, iwork(n+1), cwork(n+1),cwork(2_${ik}$*n+1), lwork-& 2_${ik}$*n, rwork, ierr ) ! * call stdlib${ii}$_zgeqrf( n, nr, v, ldv, cwork(n+1), cwork(2*n+1), ! * $ lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 ctemp=cmplx(xsc*min(abs(v(p,p)),abs(v(q,q))),zero,KIND=dp) if ( abs(v(q,p)) <= temp1 )v(q,p) = ctemp ! $ v(q,p) = temp1 * ( v(q,p) / abs(v(q,p)) ) end do end do end if call stdlib${ii}$_zlacpy( 'A', n, nr, v, ldv, cwork(2_${ik}$*n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 ctemp=cmplx(xsc*min(abs(v(p,p)),abs(v(q,q))),zero,KIND=dp) ! v(p,q) = - temp1*( v(q,p) / abs(v(q,p)) ) v(p,q) = - ctemp end do end do else if (nr>1_${ik}$) call stdlib${ii}$_zlaset( 'L',nr-1,nr-1,czero,czero,v(2_${ik}$,1_${ik}$),ldv ) end if ! now, compute r2 = l3 * q3, the lq factorization. call stdlib${ii}$_zgelqf( nr, nr, v, ldv, cwork(2_${ik}$*n+n*nr+1),cwork(2_${ik}$*n+n*nr+nr+1), & lwork-2*n-n*nr-nr, ierr ) ! And Estimate The Condition Number call stdlib${ii}$_zlacpy( 'L',nr,nr,v,ldv,cwork(2_${ik}$*n+n*nr+nr+1),nr ) do p = 1, nr temp1 = stdlib${ii}$_dznrm2( p, cwork(2_${ik}$*n+n*nr+nr+p), nr ) call stdlib${ii}$_zdscal( p, one/temp1, cwork(2_${ik}$*n+n*nr+nr+p), nr ) end do call stdlib${ii}$_zpocon( 'L',nr,cwork(2_${ik}$*n+n*nr+nr+1),nr,one,temp1,cwork(2_${ik}$*n+n*nr+& nr+nr*nr+1),rwork,ierr ) condr2 = one / sqrt(temp1) if ( condr2 >= cond_ok ) then ! Save The Householder Vectors Used For Q3 ! (this overwrites the copy of r2, as it will not be ! needed in this branch, but it does not overwritte the ! huseholder vectors of q2.). call stdlib${ii}$_zlacpy( 'U', nr, nr, v, ldv, cwork(2_${ik}$*n+1), n ) ! And The Rest Of The Information On Q3 Is In ! work(2*n+n*nr+1:2*n+n*nr+n) end if end if if ( l2pert ) then xsc = sqrt(small) do q = 2, nr ctemp = xsc * v(q,q) do p = 1, q - 1 ! v(p,q) = - temp1*( v(p,q) / abs(v(p,q)) ) v(p,q) = - ctemp end do end do else if (nr>1_${ik}$) call stdlib${ii}$_zlaset( 'U', nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$), ldv ) end if ! second preconditioning finished; continue with jacobi svd ! the input matrix is lower trinagular. ! recover the right singular vectors as solution of a well ! conditioned triangular matrix equation. if ( condr1 < cond_ok ) then call stdlib${ii}$_zgesvj( 'L','U','N',nr,nr,v,ldv,sva,nr,u, ldu,cwork(2_${ik}$*n+n*nr+nr+1)& ,lwork-2*n-n*nr-nr,rwork,lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_zcopy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_zdscal( nr, sva(p), v(1_${ik}$,p), 1_${ik}$ ) end do ! Pick The Right Matrix Equation And Solve It if ( nr == n ) then ! :)) .. best case, r1 is inverted. the solution of this matrix ! equation is q2*v2 = the product of the jacobi rotations ! used in stdlib${ii}$_zgesvj, premultiplied with the orthogonal matrix ! from the second qr factorization. call stdlib${ii}$_ztrsm('L','U','N','N', nr,nr,cone, a,lda, v,ldv) else ! .. r1 is well conditioned, but non-square. adjoint of r2 ! is inverted to get the product of the jacobi rotations ! used in stdlib${ii}$_zgesvj. the q-factor from the second qr ! factorization is then built in explicitly. call stdlib${ii}$_ztrsm('L','U','C','N',nr,nr,cone,cwork(2_${ik}$*n+1),n,v,ldv) if ( nr < n ) then call stdlib${ii}$_zlaset('A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_zlaset('A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_zlaset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_zunmqr('L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(& 2_${ik}$*n+n*nr+nr+1),lwork-2*n-n*nr-nr,ierr) end if else if ( condr2 < cond_ok ) then ! the matrix r2 is inverted. the solution of the matrix equation ! is q3^* * v3 = the product of the jacobi rotations (appplied to ! the lower triangular l3 from the lq factorization of ! r2=l3*q3), pre-multiplied with the transposed q3. call stdlib${ii}$_zgesvj( 'L', 'U', 'N', nr, nr, v, ldv, sva, nr, u,ldu, cwork(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr,rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_zcopy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_zdscal( nr, sva(p), u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_ztrsm('L','U','N','N',nr,nr,cone,cwork(2_${ik}$*n+1),n,u,ldu) ! Apply The Permutation From The Second Qr Factorization do q = 1, nr do p = 1, nr cwork(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do end do if ( nr < n ) then call stdlib${ii}$_zlaset( 'A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_zlaset( 'A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_zlaset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_zunmqr( 'L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) else ! last line of defense. ! #:( this is a rather pathological case: no scaled condition ! improvement after two pivoted qr factorizations. other ! possibility is that the rank revealing qr factorization ! or the condition estimator has failed, or the cond_ok ! is set very close to one (which is unnecessary). normally, ! this branch should never be executed, but in rare cases of ! failure of the rrqr or condition estimator, the last line of ! defense ensures that stdlib${ii}$_zgejsv completes the task. ! compute the full svd of l3 using stdlib${ii}$_zgesvj with explicit ! accumulation of jacobi rotations. call stdlib${ii}$_zgesvj( 'L', 'U', 'V', nr, nr, v, ldv, sva, nr, u,ldu, cwork(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr,rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_zlaset( 'A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_zlaset( 'A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_zlaset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_zunmqr( 'L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) call stdlib${ii}$_zunmlq( 'L', 'C', nr, nr, nr, cwork(2_${ik}$*n+1), n,cwork(2_${ik}$*n+n*nr+1), & u, ldu, cwork(2_${ik}$*n+n*nr+nr+1),lwork-2*n-n*nr-nr, ierr ) do q = 1, nr do p = 1, nr cwork(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do end do end if ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=dp)) * epsln do q = 1, n do p = 1, n cwork(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_dznrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_zdscal( n, xsc,& v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_zlaset('A', m-nr, nr, czero, czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_zlaset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_zlaset('A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1),ldu) end if end if ! the q matrix from the first qrf is built into the left singular ! matrix u. this applies to all cases. call stdlib${ii}$_zunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-& n, ierr ) ! the columns of u are normalized. the cost is o(m*n) flops. temp1 = sqrt(real(m,KIND=dp)) * epsln do p = 1, nr xsc = one / stdlib${ii}$_dznrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_zdscal( m, xsc,& u(1_${ik}$,p), 1_${ik}$ ) end do ! if the initial qrf is computed with row pivoting, the left ! singular vectors must be adjusted. if ( rowpiv )call stdlib${ii}$_zlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) else ! The Initial Matrix A Has Almost Orthogonal Columns And ! the second qrf is not needed call stdlib${ii}$_zlacpy( 'U', n, n, a, lda, cwork(n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, n ctemp = xsc * cwork( n + (p-1)*n + p ) do q = 1, p - 1 ! cwork(n+(q-1)*n+p)=-temp1 * ( cwork(n+(p-1)*n+q) / ! $ abs(cwork(n+(p-1)*n+q)) ) cwork(n+(q-1)*n+p)=-ctemp end do end do else call stdlib${ii}$_zlaset( 'L',n-1,n-1,czero,czero,cwork(n+2),n ) end if call stdlib${ii}$_zgesvj( 'U', 'U', 'N', n, n, cwork(n+1), n, sva,n, u, ldu, cwork(n+& n*n+1), lwork-n-n*n, rwork, lrwork,info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) do p = 1, n call stdlib${ii}$_zcopy( n, cwork(n+(p-1)*n+1), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_zdscal( n, sva(p), cwork(n+(p-1)*n+1), 1_${ik}$ ) end do call stdlib${ii}$_ztrsm( 'L', 'U', 'N', 'N', n, n,cone, a, lda, cwork(n+1), n ) do p = 1, n call stdlib${ii}$_zcopy( n, cwork(n+p), n, v(iwork(p),1_${ik}$), ldv ) end do temp1 = sqrt(real(n,KIND=dp))*epsln do p = 1, n xsc = one / stdlib${ii}$_dznrm2( n, v(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_zdscal( n, xsc,& v(1_${ik}$,p), 1_${ik}$ ) end do ! assemble the left singular vector matrix u (m x n). if ( n < m ) then call stdlib${ii}$_zlaset( 'A', m-n, n, czero, czero, u(n+1,1_${ik}$), ldu ) if ( n < n1 ) then call stdlib${ii}$_zlaset('A',n, n1-n, czero, czero, u(1_${ik}$,n+1),ldu) call stdlib${ii}$_zlaset( 'A',m-n,n1-n, czero, cone,u(n+1,n+1),ldu) end if end if call stdlib${ii}$_zunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-& n, ierr ) temp1 = sqrt(real(m,KIND=dp))*epsln do p = 1, n1 xsc = one / stdlib${ii}$_dznrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_zdscal( m, xsc,& u(1_${ik}$,p), 1_${ik}$ ) end do if ( rowpiv )call stdlib${ii}$_zlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) end if ! end of the >> almost orthogonal case << in the full svd else ! this branch deploys a preconditioned jacobi svd with explicitly ! accumulated rotations. it is included as optional, mainly for ! experimental purposes. it does perform well, and can also be used. ! in this implementation, this branch will be automatically activated ! if the condition number sigma_max(a) / sigma_min(a) is predicted ! to be greater than the overflow threshold. this is because the ! a posteriori computation of the singular vectors assumes robust ! implementation of blas and some lapack procedures, capable of working ! in presence of extreme values, e.g. when the singular values spread from ! the underflow to the overflow threshold. do p = 1, nr call stdlib${ii}$_zcopy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) call stdlib${ii}$_zlacgv( n-p+1, v(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 1, nr ctemp = cmplx(xsc*abs( v(q,q) ),zero,KIND=dp) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = & ctemp ! $ v(p,q) = temp1 * ( v(p,q) / abs(v(p,q)) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_zlaset( 'U', nr-1, nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) end if call stdlib${ii}$_zgeqrf( n, nr, v, ldv, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) call stdlib${ii}$_zlacpy( 'L', n, nr, v, ldv, cwork(2_${ik}$*n+1), n ) do p = 1, nr call stdlib${ii}$_zcopy( nr-p+1, v(p,p), ldv, u(p,p), 1_${ik}$ ) call stdlib${ii}$_zlacgv( nr-p+1, u(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 2, nr do p = 1, q - 1 ctemp = cmplx(xsc * min(abs(u(p,p)),abs(u(q,q))),zero,KIND=dp) ! u(p,q) = - temp1 * ( u(q,p) / abs(u(q,p)) ) u(p,q) = - ctemp end do end do else if (nr>1_${ik}$) call stdlib${ii}$_zlaset('U', nr-1, nr-1, czero, czero, u(1_${ik}$,2_${ik}$), ldu ) end if call stdlib${ii}$_zgesvj( 'L', 'U', 'V', nr, nr, u, ldu, sva,n, v, ldv, cwork(2_${ik}$*n+n*nr+1),& lwork-2*n-n*nr,rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_zlaset( 'A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_zlaset( 'A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_zlaset( 'A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_zunmqr( 'L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(2_${ik}$*n+n*nr+& nr+1),lwork-2*n-n*nr-nr,ierr ) ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=dp)) * epsln do q = 1, n do p = 1, n cwork(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_dznrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_zdscal( n, xsc,& v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_zlaset( 'A', m-nr, nr, czero, czero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_zlaset('A',nr, n1-nr, czero, czero, u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_zlaset('A',m-nr,n1-nr, czero, cone,u(nr+1,nr+1),ldu) end if end if call stdlib${ii}$_zunmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-n, & ierr ) if ( rowpiv )call stdlib${ii}$_zlaswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) end if if ( transp ) then ! .. swap u and v because the procedure worked on a^* do p = 1, n call stdlib${ii}$_zswap( n, u(1_${ik}$,p), 1_${ik}$, v(1_${ik}$,p), 1_${ik}$ ) end do end if end if ! end of the full svd ! undo scaling, if necessary (and possible) if ( uscal2 <= (big/sva(1_${ik}$))*uscal1 ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, uscal1, uscal2, nr, 1_${ik}$, sva, n, ierr ) uscal1 = one uscal2 = one end if if ( nr < n ) then do p = nr+1, n sva(p) = zero end do end if rwork(1_${ik}$) = uscal2 * scalem rwork(2_${ik}$) = uscal1 if ( errest ) rwork(3_${ik}$) = sconda if ( lsvec .and. rsvec ) then rwork(4_${ik}$) = condr1 rwork(5_${ik}$) = condr2 end if if ( l2tran ) then rwork(6_${ik}$) = entra rwork(7_${ik}$) = entrat end if iwork(1_${ik}$) = nr iwork(2_${ik}$) = numrank iwork(3_${ik}$) = warning if ( transp ) then iwork(4_${ik}$) = 1_${ik}$ else iwork(4_${ik}$) = -1_${ik}$ end if return end subroutine stdlib${ii}$_zgejsv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gejsv( joba, jobu, jobv, jobr, jobt, jobp,m, n, a, lda, sva, u, ldu, & !! ZGEJSV: computes the singular value decomposition (SVD) of a complex M-by-N !! matrix [A], where M >= N. The SVD of [A] is written as !! [A] = [U] * [SIGMA] * [V]^*, !! where [SIGMA] is an N-by-N (M-by-N) matrix which is zero except for its N !! diagonal elements, [U] is an M-by-N (or M-by-M) unitary matrix, and !! [V] is an N-by-N unitary matrix. The diagonal elements of [SIGMA] are !! the singular values of [A]. The columns of [U] and [V] are the left and !! the right singular vectors of [A], respectively. The matrices [U] and [V] !! are computed and stored in the arrays U and V, respectively. The diagonal !! of [SIGMA] is computed and stored in the array SVA. v, ldv,cwork, lwork, rwork, lrwork, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldu, ldv, lwork, lrwork, m, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: u(ldu,*), v(ldv,*), cwork(lwork) real(${ck}$), intent(out) :: sva(n), rwork(lrwork) integer(${ik}$), intent(out) :: iwork(*) character, intent(in) :: joba, jobp, jobr, jobt, jobu, jobv ! =========================================================================== ! Local Scalars complex(${ck}$) :: ctemp real(${ck}$) :: aapp, aaqq, aatmax, aatmin, big, big1, cond_ok, condr1, condr2, entra, & entrat, epsln, maxprj, scalem, sconda, sfmin, small, temp1, uscal1, uscal2, xsc integer(${ik}$) :: ierr, n1, nr, numrank, p, q, warning logical(lk) :: almort, defr, errest, goscal, jracc, kill, lquery, lsvec, l2aber, & l2kill, l2pert, l2rank, l2tran, noscal, rowpiv, rsvec, transp integer(${ik}$) :: optwrk, minwrk, minrwrk, miniwrk integer(${ik}$) :: lwcon, lwlqf, lwqp3, lwqrf, lwunmlq, lwunmqr, lwunmqrm, lwsvdj, & lwsvdjv, lrwqp3, lrwcon, lrwsvdj, iwoff integer(${ik}$) :: lwrk_wgelqf, lwrk_wgeqp3, lwrk_wgeqp3n, lwrk_wgeqrf, lwrk_wgesvj, & lwrk_wgesvjv, lwrk_wgesvju, lwrk_wunmlq, lwrk_wunmqr, lwrk_wunmqrm ! Local Arrays complex(${ck}$) :: cdummy(1_${ik}$) real(${ck}$) :: rdummy(1_${ik}$) ! Intrinsic Functions ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) .or. stdlib_lsame( jobu, 'F' ) jracc = stdlib_lsame( jobv, 'J' ) rsvec = stdlib_lsame( jobv, 'V' ) .or. jracc rowpiv = stdlib_lsame( joba, 'F' ) .or. stdlib_lsame( joba, 'G' ) l2rank = stdlib_lsame( joba, 'R' ) l2aber = stdlib_lsame( joba, 'A' ) errest = stdlib_lsame( joba, 'E' ) .or. stdlib_lsame( joba, 'G' ) l2tran = stdlib_lsame( jobt, 'T' ) .and. ( m == n ) l2kill = stdlib_lsame( jobr, 'R' ) defr = stdlib_lsame( jobr, 'N' ) l2pert = stdlib_lsame( jobp, 'P' ) lquery = ( lwork == -1_${ik}$ ) .or. ( lrwork == -1_${ik}$ ) if ( .not.(rowpiv .or. l2rank .or. l2aber .or.errest .or. stdlib_lsame( joba, 'C' ) )) & then info = - 1_${ik}$ else if ( .not.( lsvec .or. stdlib_lsame( jobu, 'N' ) .or.( stdlib_lsame( jobu, 'W' ) & .and. rsvec .and. l2tran ) ) ) then info = - 2_${ik}$ else if ( .not.( rsvec .or. stdlib_lsame( jobv, 'N' ) .or.( stdlib_lsame( jobv, 'W' ) & .and. lsvec .and. l2tran ) ) ) then info = - 3_${ik}$ else if ( .not. ( l2kill .or. defr ) ) then info = - 4_${ik}$ else if ( .not. ( stdlib_lsame(jobt,'T') .or. stdlib_lsame(jobt,'N') ) ) then info = - 5_${ik}$ else if ( .not. ( l2pert .or. stdlib_lsame( jobp, 'N' ) ) ) then info = - 6_${ik}$ else if ( m < 0_${ik}$ ) then info = - 7_${ik}$ else if ( ( n < 0_${ik}$ ) .or. ( n > m ) ) then info = - 8_${ik}$ else if ( lda < m ) then info = - 10_${ik}$ else if ( lsvec .and. ( ldu < m ) ) then info = - 13_${ik}$ else if ( rsvec .and. ( ldv < n ) ) then info = - 15_${ik}$ else ! #:) info = 0_${ik}$ end if if ( info == 0_${ik}$ ) then ! Compute The Minimal And The Optimal Workspace Lengths ! [[the expressions for computing the minimal and the optimal ! values of lcwork, lrwork are written with a lot of redundancy and ! can be simplified. however, this verbose form is useful for ! maintenance and modifications of the code.]] ! .. minimal workspace length for stdlib${ii}$_${ci}$geqp3 of an m x n matrix, ! stdlib${ii}$_${ci}$geqrf of an n x n matrix, stdlib${ii}$_${ci}$gelqf of an n x n matrix, ! stdlib${ii}$_${ci}$unmlq for computing n x n matrix, stdlib${ii}$_${ci}$unmqr for computing n x n ! matrix, stdlib${ii}$_${ci}$unmqr for computing m x n matrix, respectively. lwqp3 = n+1 lwqrf = max( 1_${ik}$, n ) lwlqf = max( 1_${ik}$, n ) lwunmlq = max( 1_${ik}$, n ) lwunmqr = max( 1_${ik}$, n ) lwunmqrm = max( 1_${ik}$, m ) ! Minimal Workspace Length For Stdlib_Zpocon Of An N X N Matrix lwcon = 2_${ik}$ * n ! .. minimal workspace length for stdlib${ii}$_${ci}$gesvj of an n x n matrix, ! without and with explicit accumulation of jacobi rotations lwsvdj = max( 2_${ik}$ * n, 1_${ik}$ ) lwsvdjv = max( 2_${ik}$ * n, 1_${ik}$ ) ! .. minimal real workspace length for stdlib${ii}$_${ci}$geqp3, stdlib${ii}$_${ci}$pocon, stdlib${ii}$_${ci}$gesvj lrwqp3 = 2_${ik}$ * n lrwcon = n lrwsvdj = n if ( lquery ) then call stdlib${ii}$_${ci}$geqp3( m, n, a, lda, iwork, cdummy, cdummy, -1_${ik}$,rdummy, ierr ) lwrk_wgeqp3 = real( cdummy(1_${ik}$),KIND=${ck}$) call stdlib${ii}$_${ci}$geqrf( n, n, a, lda, cdummy, cdummy,-1_${ik}$, ierr ) lwrk_wgeqrf = real( cdummy(1_${ik}$),KIND=${ck}$) call stdlib${ii}$_${ci}$gelqf( n, n, a, lda, cdummy, cdummy,-1_${ik}$, ierr ) lwrk_wgelqf = real( cdummy(1_${ik}$),KIND=${ck}$) end if minwrk = 2_${ik}$ optwrk = 2_${ik}$ miniwrk = n if ( .not. (lsvec .or. rsvec ) ) then ! Minimal And Optimal Sizes Of The Complex Workspace If ! only the singular values are requested if ( errest ) then minwrk = max( n+lwqp3, n**2_${ik}$+lwcon, n+lwqrf, lwsvdj ) else minwrk = max( n+lwqp3, n+lwqrf, lwsvdj ) end if if ( lquery ) then call stdlib${ii}$_${ci}$gesvj( 'L', 'N', 'N', n, n, a, lda, sva, n, v,ldv, cdummy, -1_${ik}$,& rdummy, -1_${ik}$, ierr ) lwrk_wgesvj = real( cdummy(1_${ik}$),KIND=${ck}$) if ( errest ) then optwrk = max( n+lwrk_wgeqp3, n**2_${ik}$+lwcon,n+lwrk_wgeqrf, lwrk_wgesvj ) else optwrk = max( n+lwrk_wgeqp3, n+lwrk_wgeqrf,lwrk_wgesvj ) end if end if if ( l2tran .or. rowpiv ) then if ( errest ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwcon, lrwsvdj ) else minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj ) end if else if ( errest ) then minrwrk = max( 7_${ik}$, lrwqp3, lrwcon, lrwsvdj ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj ) end if end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else if ( rsvec .and. (.not.lsvec) ) then ! Minimal And Optimal Sizes Of The Complex Workspace If The ! singular values and the right singular vectors are requested if ( errest ) then minwrk = max( n+lwqp3, lwcon, lwsvdj, n+lwlqf,2_${ik}$*n+lwqrf, n+lwsvdj, n+& lwunmlq ) else minwrk = max( n+lwqp3, lwsvdj, n+lwlqf, 2_${ik}$*n+lwqrf,n+lwsvdj, n+lwunmlq ) end if if ( lquery ) then call stdlib${ii}$_${ci}$gesvj( 'L', 'U', 'N', n,n, u, ldu, sva, n, a,lda, cdummy, -1_${ik}$, & rdummy, -1_${ik}$, ierr ) lwrk_wgesvj = real( cdummy(1_${ik}$),KIND=${ck}$) call stdlib${ii}$_${ci}$unmlq( 'L', 'C', n, n, n, a, lda, cdummy,v, ldv, cdummy, -1_${ik}$, & ierr ) lwrk_wunmlq = real( cdummy(1_${ik}$),KIND=${ck}$) if ( errest ) then optwrk = max( n+lwrk_wgeqp3, lwcon, lwrk_wgesvj,n+lwrk_wgelqf, 2_${ik}$*n+& lwrk_wgeqrf,n+lwrk_wgesvj, n+lwrk_wunmlq ) else optwrk = max( n+lwrk_wgeqp3, lwrk_wgesvj,n+lwrk_wgelqf,2_${ik}$*n+lwrk_wgeqrf, n+& lwrk_wgesvj,n+lwrk_wunmlq ) end if end if if ( l2tran .or. rowpiv ) then if ( errest ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj ) end if else if ( errest ) then minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj ) end if end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else if ( lsvec .and. (.not.rsvec) ) then ! Minimal And Optimal Sizes Of The Complex Workspace If The ! singular values and the left singular vectors are requested if ( errest ) then minwrk = n + max( lwqp3,lwcon,n+lwqrf,lwsvdj,lwunmqrm ) else minwrk = n + max( lwqp3, n+lwqrf, lwsvdj, lwunmqrm ) end if if ( lquery ) then call stdlib${ii}$_${ci}$gesvj( 'L', 'U', 'N', n,n, u, ldu, sva, n, a,lda, cdummy, -1_${ik}$, & rdummy, -1_${ik}$, ierr ) lwrk_wgesvj = real( cdummy(1_${ik}$),KIND=${ck}$) call stdlib${ii}$_${ci}$unmqr( 'L', 'N', m, n, n, a, lda, cdummy, u,ldu, cdummy, -1_${ik}$, & ierr ) lwrk_wunmqrm = real( cdummy(1_${ik}$),KIND=${ck}$) if ( errest ) then optwrk = n + max( lwrk_wgeqp3, lwcon, n+lwrk_wgeqrf,lwrk_wgesvj, & lwrk_wunmqrm ) else optwrk = n + max( lwrk_wgeqp3, n+lwrk_wgeqrf,lwrk_wgesvj, lwrk_wunmqrm ) end if end if if ( l2tran .or. rowpiv ) then if ( errest ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj ) end if else if ( errest ) then minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj ) end if end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else ! Minimal And Optimal Sizes Of The Complex Workspace If The ! full svd is requested if ( .not. jracc ) then if ( errest ) then minwrk = max( n+lwqp3, n+lwcon, 2_${ik}$*n+n**2_${ik}$+lwcon,2_${ik}$*n+lwqrf, 2_${ik}$*n+& lwqp3,2_${ik}$*n+n**2_${ik}$+n+lwlqf, 2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+n**2_${ik}$+n+lwsvdj, 2_${ik}$*n+& n**2_${ik}$+n+lwsvdjv,2_${ik}$*n+n**2_${ik}$+n+lwunmqr,2_${ik}$*n+n**2_${ik}$+n+lwunmlq,n+n**2_${ik}$+lwsvdj, n+& lwunmqrm ) else minwrk = max( n+lwqp3, 2_${ik}$*n+n**2_${ik}$+lwcon,2_${ik}$*n+lwqrf, 2_${ik}$*n+& lwqp3,2_${ik}$*n+n**2_${ik}$+n+lwlqf, 2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+n**2_${ik}$+n+lwsvdj, 2_${ik}$*n+& n**2_${ik}$+n+lwsvdjv,2_${ik}$*n+n**2_${ik}$+n+lwunmqr,2_${ik}$*n+n**2_${ik}$+n+lwunmlq,n+n**2_${ik}$+lwsvdj, & n+lwunmqrm ) end if miniwrk = miniwrk + n if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m else if ( errest ) then minwrk = max( n+lwqp3, n+lwcon, 2_${ik}$*n+lwqrf,2_${ik}$*n+n**2_${ik}$+lwsvdjv, 2_${ik}$*n+n**2_${ik}$+n+& lwunmqr,n+lwunmqrm ) else minwrk = max( n+lwqp3, 2_${ik}$*n+lwqrf,2_${ik}$*n+n**2_${ik}$+lwsvdjv, 2_${ik}$*n+n**2_${ik}$+n+lwunmqr,n+& lwunmqrm ) end if if ( rowpiv .or. l2tran ) miniwrk = miniwrk + m end if if ( lquery ) then call stdlib${ii}$_${ci}$unmqr( 'L', 'N', m, n, n, a, lda, cdummy, u,ldu, cdummy, -1_${ik}$, & ierr ) lwrk_wunmqrm = real( cdummy(1_${ik}$),KIND=${ck}$) call stdlib${ii}$_${ci}$unmqr( 'L', 'N', n, n, n, a, lda, cdummy, u,ldu, cdummy, -1_${ik}$, & ierr ) lwrk_wunmqr = real( cdummy(1_${ik}$),KIND=${ck}$) if ( .not. jracc ) then call stdlib${ii}$_${ci}$geqp3( n,n, a, lda, iwork, cdummy,cdummy, -1_${ik}$,rdummy, ierr ) lwrk_wgeqp3n = real( cdummy(1_${ik}$),KIND=${ck}$) call stdlib${ii}$_${ci}$gesvj( 'L', 'U', 'N', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_wgesvj = real( cdummy(1_${ik}$),KIND=${ck}$) call stdlib${ii}$_${ci}$gesvj( 'U', 'U', 'N', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_wgesvju = real( cdummy(1_${ik}$),KIND=${ck}$) call stdlib${ii}$_${ci}$gesvj( 'L', 'U', 'V', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_wgesvjv = real( cdummy(1_${ik}$),KIND=${ck}$) call stdlib${ii}$_${ci}$unmlq( 'L', 'C', n, n, n, a, lda, cdummy,v, ldv, cdummy, -& 1_${ik}$, ierr ) lwrk_wunmlq = real( cdummy(1_${ik}$),KIND=${ck}$) if ( errest ) then optwrk = max( n+lwrk_wgeqp3, n+lwcon,2_${ik}$*n+n**2_${ik}$+lwcon, 2_${ik}$*n+lwrk_wgeqrf,& 2_${ik}$*n+lwrk_wgeqp3n,2_${ik}$*n+n**2_${ik}$+n+lwrk_wgelqf,2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+& n**2_${ik}$+n+lwrk_wgesvj,2_${ik}$*n+n**2_${ik}$+n+lwrk_wgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_wunmqr,2_${ik}$*n+& n**2_${ik}$+n+lwrk_wunmlq,n+n**2_${ik}$+lwrk_wgesvju,n+lwrk_wunmqrm ) else optwrk = max( n+lwrk_wgeqp3,2_${ik}$*n+n**2_${ik}$+lwcon, 2_${ik}$*n+lwrk_wgeqrf,2_${ik}$*n+& lwrk_wgeqp3n,2_${ik}$*n+n**2_${ik}$+n+lwrk_wgelqf,2_${ik}$*n+n**2_${ik}$+n+n**2_${ik}$+lwcon,2_${ik}$*n+n**2_${ik}$+n+& lwrk_wgesvj,2_${ik}$*n+n**2_${ik}$+n+lwrk_wgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_wunmqr,2_${ik}$*n+n**2_${ik}$+n+& lwrk_wunmlq,n+n**2_${ik}$+lwrk_wgesvju,n+lwrk_wunmqrm ) end if else call stdlib${ii}$_${ci}$gesvj( 'L', 'U', 'V', n, n, u, ldu, sva,n, v, ldv, cdummy, & -1_${ik}$, rdummy, -1_${ik}$, ierr ) lwrk_wgesvjv = real( cdummy(1_${ik}$),KIND=${ck}$) call stdlib${ii}$_${ci}$unmqr( 'L', 'N', n, n, n, cdummy, n, cdummy,v, ldv, cdummy,& -1_${ik}$, ierr ) lwrk_wunmqr = real( cdummy(1_${ik}$),KIND=${ck}$) call stdlib${ii}$_${ci}$unmqr( 'L', 'N', m, n, n, a, lda, cdummy, u,ldu, cdummy, -& 1_${ik}$, ierr ) lwrk_wunmqrm = real( cdummy(1_${ik}$),KIND=${ck}$) if ( errest ) then optwrk = max( n+lwrk_wgeqp3, n+lwcon,2_${ik}$*n+lwrk_wgeqrf, 2_${ik}$*n+n**2_${ik}$,2_${ik}$*n+& n**2_${ik}$+lwrk_wgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_wunmqr,n+lwrk_wunmqrm ) else optwrk = max( n+lwrk_wgeqp3, 2_${ik}$*n+lwrk_wgeqrf,2_${ik}$*n+n**2_${ik}$, 2_${ik}$*n+n**2_${ik}$+& lwrk_wgesvjv,2_${ik}$*n+n**2_${ik}$+n+lwrk_wunmqr,n+lwrk_wunmqrm ) end if end if end if if ( l2tran .or. rowpiv ) then minrwrk = max( 7_${ik}$, 2_${ik}$*m, lrwqp3, lrwsvdj, lrwcon ) else minrwrk = max( 7_${ik}$, lrwqp3, lrwsvdj, lrwcon ) end if end if minwrk = max( 2_${ik}$, minwrk ) optwrk = max( minwrk, optwrk ) if ( lwork < minwrk .and. (.not.lquery) ) info = - 17_${ik}$ if ( lrwork < minrwrk .and. (.not.lquery) ) info = - 19_${ik}$ end if if ( info /= 0_${ik}$ ) then ! #:( call stdlib${ii}$_xerbla( 'ZGEJSV', - info ) return else if ( lquery ) then cwork(1_${ik}$) = optwrk cwork(2_${ik}$) = minwrk rwork(1_${ik}$) = minrwrk iwork(1_${ik}$) = max( 4_${ik}$, miniwrk ) return end if ! quick return for void matrix (y3k safe) ! #:) if ( ( m == 0_${ik}$ ) .or. ( n == 0_${ik}$ ) ) then iwork(1_${ik}$:4_${ik}$) = 0_${ik}$ rwork(1_${ik}$:7_${ik}$) = 0_${ik}$ return endif ! determine whether the matrix u should be m x n or m x m if ( lsvec ) then n1 = n if ( stdlib_lsame( jobu, 'F' ) ) n1 = m end if ! set numerical parameters ! ! note: make sure stdlib${ii}$_${c2ri(ci)}$lamch() does not fail on the target architecture. epsln = stdlib${ii}$_${c2ri(ci)}$lamch('EPSILON') sfmin = stdlib${ii}$_${c2ri(ci)}$lamch('SAFEMINIMUM') small = sfmin / epsln big = stdlib${ii}$_${c2ri(ci)}$lamch('O') ! big = one / sfmin ! initialize sva(1:n) = diag( ||a e_i||_2 )_1^n ! (!) if necessary, scale sva() to protect the largest norm from ! overflow. it is possible that this scaling pushes the smallest ! column norm left from the underflow threshold (extreme case). scalem = one / sqrt(real(m,KIND=${ck}$)*real(n,KIND=${ck}$)) noscal = .true. goscal = .true. do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_${ci}$lassq( m, a(1_${ik}$,p), 1_${ik}$, aapp, aaqq ) if ( aapp > big ) then info = - 9_${ik}$ call stdlib${ii}$_xerbla( 'ZGEJSV', -info ) return end if aaqq = sqrt(aaqq) if ( ( aapp < (big / aaqq) ) .and. noscal ) then sva(p) = aapp * aaqq else noscal = .false. sva(p) = aapp * ( aaqq * scalem ) if ( goscal ) then goscal = .false. call stdlib${ii}$_${c2ri(ci)}$scal( p-1, scalem, sva, 1_${ik}$ ) end if end if end do if ( noscal ) scalem = one aapp = zero aaqq = big do p = 1, n aapp = max( aapp, sva(p) ) if ( sva(p) /= zero ) aaqq = min( aaqq, sva(p) ) end do ! quick return for zero m x n matrix ! #:) if ( aapp == zero ) then if ( lsvec ) call stdlib${ii}$_${ci}$laset( 'G', m, n1, czero, cone, u, ldu ) if ( rsvec ) call stdlib${ii}$_${ci}$laset( 'G', n, n, czero, cone, v, ldv ) rwork(1_${ik}$) = one rwork(2_${ik}$) = one if ( errest ) rwork(3_${ik}$) = one if ( lsvec .and. rsvec ) then rwork(4_${ik}$) = one rwork(5_${ik}$) = one end if if ( l2tran ) then rwork(6_${ik}$) = zero rwork(7_${ik}$) = zero end if iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ iwork(3_${ik}$) = 0_${ik}$ iwork(4_${ik}$) = -1_${ik}$ return end if ! issue warning if denormalized column norms detected. override the ! high relative accuracy request. issue licence to kill nonzero columns ! (set them to zero) whose norm is less than sigma_max / big (roughly). ! #:( warning = 0_${ik}$ if ( aaqq <= sfmin ) then l2rank = .true. l2kill = .true. warning = 1_${ik}$ end if ! quick return for one-column matrix ! #:) if ( n == 1_${ik}$ ) then if ( lsvec ) then call stdlib${ii}$_${ci}$lascl( 'G',0_${ik}$,0_${ik}$,sva(1_${ik}$),scalem, m,1_${ik}$,a(1_${ik}$,1_${ik}$),lda,ierr ) call stdlib${ii}$_${ci}$lacpy( 'A', m, 1_${ik}$, a, lda, u, ldu ) ! computing all m left singular vectors of the m x 1 matrix if ( n1 /= n ) then call stdlib${ii}$_${ci}$geqrf( m, n, u,ldu, cwork, cwork(n+1),lwork-n,ierr ) call stdlib${ii}$_${ci}$ungqr( m,n1,1_${ik}$, u,ldu,cwork,cwork(n+1),lwork-n,ierr ) call stdlib${ii}$_${ci}$copy( m, a(1_${ik}$,1_${ik}$), 1_${ik}$, u(1_${ik}$,1_${ik}$), 1_${ik}$ ) end if end if if ( rsvec ) then v(1_${ik}$,1_${ik}$) = cone end if if ( sva(1_${ik}$) < (big*scalem) ) then sva(1_${ik}$) = sva(1_${ik}$) / scalem scalem = one end if rwork(1_${ik}$) = one / scalem rwork(2_${ik}$) = one if ( sva(1_${ik}$) /= zero ) then iwork(1_${ik}$) = 1_${ik}$ if ( ( sva(1_${ik}$) / scalem) >= sfmin ) then iwork(2_${ik}$) = 1_${ik}$ else iwork(2_${ik}$) = 0_${ik}$ end if else iwork(1_${ik}$) = 0_${ik}$ iwork(2_${ik}$) = 0_${ik}$ end if iwork(3_${ik}$) = 0_${ik}$ iwork(4_${ik}$) = -1_${ik}$ if ( errest ) rwork(3_${ik}$) = one if ( lsvec .and. rsvec ) then rwork(4_${ik}$) = one rwork(5_${ik}$) = one end if if ( l2tran ) then rwork(6_${ik}$) = zero rwork(7_${ik}$) = zero end if return end if transp = .false. aatmax = -one aatmin = big if ( rowpiv .or. l2tran ) then ! compute the row norms, needed to determine row pivoting sequence ! (in the case of heavily row weighted a, row pivoting is strongly ! advised) and to collect information needed to compare the ! structures of a * a^* and a^* * a (in the case l2tran==.true.). if ( l2tran ) then do p = 1, m xsc = zero temp1 = one call stdlib${ii}$_${ci}$lassq( n, a(p,1_${ik}$), lda, xsc, temp1 ) ! stdlib${ii}$_${ci}$lassq gets both the ell_2 and the ell_infinity norm ! in one pass through the vector rwork(m+p) = xsc * scalem rwork(p) = xsc * (scalem*sqrt(temp1)) aatmax = max( aatmax, rwork(p) ) if (rwork(p) /= zero)aatmin = min(aatmin,rwork(p)) end do else do p = 1, m rwork(m+p) = scalem*abs( a(p,stdlib${ii}$_i${ci}$amax(n,a(p,1_${ik}$),lda)) ) aatmax = max( aatmax, rwork(m+p) ) aatmin = min( aatmin, rwork(m+p) ) end do end if end if ! for square matrix a try to determine whether a^* would be better ! input for the preconditioned jacobi svd, with faster convergence. ! the decision is based on an o(n) function of the vector of column ! and row norms of a, based on the shannon entropy. this should give ! the right choice in most cases when the difference actually matters. ! it may fail and pick the slower converging side. entra = zero entrat = zero if ( l2tran ) then xsc = zero temp1 = one call stdlib${ii}$_${c2ri(ci)}$lassq( n, sva, 1_${ik}$, xsc, temp1 ) temp1 = one / temp1 entra = zero do p = 1, n big1 = ( ( sva(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entra = entra + big1 * log(big1) end do entra = - entra / log(real(n,KIND=${ck}$)) ! now, sva().^2/trace(a^* * a) is a point in the probability simplex. ! it is derived from the diagonal of a^* * a. do the same with the ! diagonal of a * a^*, compute the entropy of the corresponding ! probability distribution. note that a * a^* and a^* * a have the ! same trace. entrat = zero do p = 1, m big1 = ( ( rwork(p) / xsc )**2_${ik}$ ) * temp1 if ( big1 /= zero ) entrat = entrat + big1 * log(big1) end do entrat = - entrat / log(real(m,KIND=${ck}$)) ! analyze the entropies and decide a or a^*. smaller entropy ! usually means better input for the algorithm. transp = ( entrat < entra ) ! if a^* is better than a, take the adjoint of a. this is allowed ! only for square matrices, m=n. if ( transp ) then ! in an optimal implementation, this trivial transpose ! should be replaced with faster transpose. do p = 1, n - 1 a(p,p) = conjg(a(p,p)) do q = p + 1, n ctemp = conjg(a(q,p)) a(q,p) = conjg(a(p,q)) a(p,q) = ctemp end do end do a(n,n) = conjg(a(n,n)) do p = 1, n rwork(m+p) = sva(p) sva(p) = rwork(p) ! previously computed row 2-norms are now column 2-norms ! of the transposed matrix end do temp1 = aapp aapp = aatmax aatmax = temp1 temp1 = aaqq aaqq = aatmin aatmin = temp1 kill = lsvec lsvec = rsvec rsvec = kill if ( lsvec ) n1 = n rowpiv = .true. end if end if ! end if l2tran ! scale the matrix so that its maximal singular value remains less ! than sqrt(big) -- the matrix is scaled so that its maximal column ! has euclidean norm equal to sqrt(big/n). the only reason to keep ! sqrt(big) instead of big is the fact that stdlib${ii}$_${ci}$gejsv uses lapack and ! blas routines that, in some implementations, are not capable of ! working in the full interval [sfmin,big] and that they may provoke ! overflows in the intermediate results. if the singular values spread ! from sfmin to big, then stdlib${ii}$_${ci}$gesvj will compute them. so, in that case, ! one should use stdlib_${ci}$gesvj instead of stdlib${ii}$_${ci}$gejsv. ! >> change in the april 2016 update: allow bigger range, i.e. the ! largest column is allowed up to big/n and stdlib${ii}$_${ci}$gesvj will do the rest. big1 = sqrt( big ) temp1 = sqrt( big / real(n,KIND=${ck}$) ) ! temp1 = big/real(n,KIND=${ck}$) call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, n, 1_${ik}$, sva, n, ierr ) if ( aaqq > (aapp * sfmin) ) then aaqq = ( aaqq / aapp ) * temp1 else aaqq = ( aaqq * temp1 ) / aapp end if temp1 = temp1 * scalem call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, temp1, m, n, a, lda, ierr ) ! to undo scaling at the end of this procedure, multiply the ! computed singular values with uscal2 / uscal1. uscal1 = temp1 uscal2 = aapp if ( l2kill ) then ! l2kill enforces computation of nonzero singular values in ! the restricted range of condition number of the initial a, ! sigma_max(a) / sigma_min(a) approx. sqrt(big)/sqrt(sfmin). xsc = sqrt( sfmin ) else xsc = small ! now, if the condition number of a is too big, ! sigma_max(a) / sigma_min(a) > sqrt(big/n) * epsln / sfmin, ! as a precaution measure, the full svd is computed using stdlib${ii}$_${ci}$gesvj ! with accumulated jacobi rotations. this provides numerically ! more robust computation, at the cost of slightly increased run ! time. depending on the concrete implementation of blas and lapack ! (i.e. how they behave in presence of extreme ill-conditioning) the ! implementor may decide to remove this switch. if ( ( aaqq= (temp1*abs(a(1_${ik}$,1_${ik}$))) ) then nr = nr + 1_${ik}$ else exit loop_3002 end if end do loop_3002 else if ( l2rank ) then ! .. similarly as above, only slightly more gentle (less aggressive). ! sudden drop on the diagonal of r1 is used as the criterion for ! close-to-rank-deficient. temp1 = sqrt(sfmin) loop_3402: do p = 2, n if ( ( abs(a(p,p)) < (epsln*abs(a(p-1,p-1))) ) .or.( abs(a(p,p)) < small ) .or.( & l2kill .and. (abs(a(p,p)) < temp1) ) ) exit loop_3402 nr = nr + 1_${ik}$ end do loop_3402 else ! the goal is high relative accuracy. however, if the matrix ! has high scaled condition number the relative accuracy is in ! general not feasible. later on, a condition number estimator ! will be deployed to estimate the scaled condition number. ! here we just remove the underflowed part of the triangular ! factor. this prevents the situation in which the code is ! working hard to get the accuracy not warranted by the data. temp1 = sqrt(sfmin) loop_3302: do p = 2, n if ( ( abs(a(p,p)) < small ) .or.( l2kill .and. (abs(a(p,p)) < temp1) ) ) exit loop_3302 nr = nr + 1_${ik}$ end do loop_3302 end if almort = .false. if ( nr == n ) then maxprj = one do p = 2, n temp1 = abs(a(p,p)) / sva(iwork(p)) maxprj = min( maxprj, temp1 ) end do if ( maxprj**2_${ik}$ >= one - real(n,KIND=${ck}$)*epsln ) almort = .true. end if sconda = - one condr1 = - one condr2 = - one if ( errest ) then if ( n == nr ) then if ( rsvec ) then ! V Is Available As Workspace call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, v, ldv ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_${ci}$dscal( p, one/temp1, v(1_${ik}$,p), 1_${ik}$ ) end do if ( lsvec )then call stdlib${ii}$_${ci}$pocon( 'U', n, v, ldv, one, temp1,cwork(n+1), rwork, ierr ) else call stdlib${ii}$_${ci}$pocon( 'U', n, v, ldv, one, temp1,cwork, rwork, ierr ) end if else if ( lsvec ) then ! U Is Available As Workspace call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, u, ldu ) do p = 1, n temp1 = sva(iwork(p)) call stdlib${ii}$_${ci}$dscal( p, one/temp1, u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_${ci}$pocon( 'U', n, u, ldu, one, temp1,cwork(n+1), rwork, ierr ) else call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, cwork, n ) ! [] call stdlib${ii}$_${ci}$lacpy( 'u', n, n, a, lda, cwork(n+1), n ) ! change: here index shifted by n to the left, cwork(1:n) ! not needed for sigma only computation do p = 1, n temp1 = sva(iwork(p)) ! [] call stdlib${ii}$_${ci}$dscal( p, one/temp1, cwork(n+(p-1)*n+1), 1 ) call stdlib${ii}$_${ci}$dscal( p, one/temp1, cwork((p-1)*n+1), 1_${ik}$ ) end do ! The Columns Of R Are Scaled To Have Unit Euclidean Lengths ! [] call stdlib${ii}$_${ci}$pocon( 'u', n, cwork(n+1), n, one, temp1, ! [] $ cwork(n+n*n+1), rwork, ierr ) call stdlib${ii}$_${ci}$pocon( 'U', n, cwork, n, one, temp1,cwork(n*n+1), rwork, ierr ) end if if ( temp1 /= zero ) then sconda = one / sqrt(temp1) else sconda = - one end if ! sconda is an estimate of sqrt(||(r^* * r)^(-1)||_1). ! n^(-1/4) * sconda <= ||r^(-1)||_2 <= n^(1/4) * sconda else sconda = - one end if end if l2pert = l2pert .and. ( abs( a(1_${ik}$,1_${ik}$)/a(nr,nr) ) > sqrt(big1) ) ! if there is no violent scaling, artificial perturbation is not needed. ! phase 3: if ( .not. ( rsvec .or. lsvec ) ) then ! singular values only ! .. transpose a(1:nr,1:n) do p = 1, min( n-1, nr ) call stdlib${ii}$_${ci}$copy( n-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( n-p+1, a(p,p), 1_${ik}$ ) end do if ( nr == n ) a(n,n) = conjg(a(n,n)) ! the following two do-loops introduce small relative perturbation ! into the strict upper triangle of the lower triangular matrix. ! small entries below the main diagonal are also changed. ! this modification is useful if the computing environment does not ! provide/allow flush to zero underflow, for it prevents many ! annoying denormalized numbers in case of strongly scaled matrices. ! the perturbation is structured so that it does not introduce any ! new perturbation of the singular values, and it does not destroy ! the job done by the preconditioner. ! the licence for this perturbation is in the variable l2pert, which ! should be .false. if flush to zero underflow is active. if ( .not. almort ) then if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=${ck}$) do q = 1, nr ctemp = cmplx(xsc*abs(a(q,q)),zero,KIND=${ck}$) do p = 1, n if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = & ctemp ! $ a(p,q) = temp1 * ( a(p,q) / abs(a(p,q)) ) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', nr-1,nr-1, czero,czero, a(1_${ik}$,2_${ik}$),lda ) end if ! Second Preconditioning Using The Qr Factorization call stdlib${ii}$_${ci}$geqrf( n,nr, a,lda, cwork, cwork(n+1),lwork-n, ierr ) ! And Transpose Upper To Lower Triangular do p = 1, nr - 1 call stdlib${ii}$_${ci}$copy( nr-p, a(p,p+1), lda, a(p+1,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( nr-p+1, a(p,p), 1_${ik}$ ) end do end if ! row-cyclic jacobi svd algorithm with column pivoting ! .. again some perturbation (a "background noise") is added ! to drown denormals if ( l2pert ) then ! xsc = sqrt(small) xsc = epsln / real(n,KIND=${ck}$) do q = 1, nr ctemp = cmplx(xsc*abs(a(q,q)),zero,KIND=${ck}$) do p = 1, nr if ( ( (p>q) .and. (abs(a(p,q))<=temp1) ).or. ( p < q ) )a(p,q) = & ctemp ! $ a(p,q) = temp1 * ( a(p,q) / abs(a(p,q)) ) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', nr-1, nr-1, czero, czero, a(1_${ik}$,2_${ik}$), lda ) end if ! .. and one-sided jacobi rotations are started on a lower ! triangular matrix (plus perturbation which is ignored in ! the part which destroys triangular form (confusing?!)) call stdlib${ii}$_${ci}$gesvj( 'L', 'N', 'N', nr, nr, a, lda, sva,n, v, ldv, cwork, lwork, & rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) else if ( ( rsvec .and. ( .not. lsvec ) .and. ( .not. jracc ) ).or.( jracc .and. ( & .not. lsvec ) .and. ( nr /= n ) ) ) then ! -> singular values and right singular vectors <- if ( almort ) then ! In This Case Nr Equals N do p = 1, nr call stdlib${ii}$_${ci}$copy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( n-p+1, v(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', nr-1,nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_${ci}$gesvj( 'L','U','N', n, nr, v, ldv, sva, nr, a, lda,cwork, lwork, & rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) else ! .. two more qr factorizations ( one qrf is not enough, two require ! accumulated product of jacobi rotations, three are perfect ) if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'L', nr-1,nr-1, czero, czero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_${ci}$gelqf( nr,n, a, lda, cwork, cwork(n+1), lwork-n, ierr) call stdlib${ii}$_${ci}$lacpy( 'L', nr, nr, a, lda, v, ldv ) if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', nr-1,nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) call stdlib${ii}$_${ci}$geqrf( nr, nr, v, ldv, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr call stdlib${ii}$_${ci}$copy( nr-p+1, v(p,p), ldv, v(p,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( nr-p+1, v(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset('U', nr-1, nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv) call stdlib${ii}$_${ci}$gesvj( 'L', 'U','N', nr, nr, v,ldv, sva, nr, u,ldu, cwork(n+1), & lwork-n, rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_${ci}$laset( 'A',n-nr, nr, czero,czero, v(nr+1,1_${ik}$), ldv ) call stdlib${ii}$_${ci}$laset( 'A',nr, n-nr, czero,czero, v(1_${ik}$,nr+1), ldv ) call stdlib${ii}$_${ci}$laset( 'A',n-nr,n-nr,czero,cone, v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_${ci}$unmlq( 'L', 'C', n, n, nr, a, lda, cwork,v, ldv, cwork(n+1), lwork-n, & ierr ) end if ! Permute The Rows Of V ! do 8991 p = 1, n ! call stdlib${ii}$_${ci}$copy( n, v(p,1), ldv, a(iwork(p),1), lda ) 8991 continue ! call stdlib${ii}$_${ci}$lacpy( 'all', n, n, a, lda, v, ldv ) call stdlib${ii}$_${ci}$lapmr( .false., n, n, v, ldv, iwork ) if ( transp ) then call stdlib${ii}$_${ci}$lacpy( 'A', n, n, v, ldv, u, ldu ) end if else if ( jracc .and. (.not. lsvec) .and. ( nr== n ) ) then if (n>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'L', n-1,n-1, czero, czero, a(2_${ik}$,1_${ik}$), lda ) call stdlib${ii}$_${ci}$gesvj( 'U','N','V', n, n, a, lda, sva, n, v, ldv,cwork, lwork, rwork, & lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) call stdlib${ii}$_${ci}$lapmr( .false., n, n, v, ldv, iwork ) else if ( lsvec .and. ( .not. rsvec ) ) then ! Singular Values And Left Singular Vectors ! Second Preconditioning Step To Avoid Need To Accumulate ! jacobi rotations in the jacobi iterations. do p = 1, nr call stdlib${ii}$_${ci}$copy( n-p+1, a(p,p), lda, u(p,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( n-p+1, u(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', nr-1, nr-1, czero, czero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_${ci}$geqrf( n, nr, u, ldu, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) do p = 1, nr - 1 call stdlib${ii}$_${ci}$copy( nr-p, u(p,p+1), ldu, u(p+1,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( n-p+1, u(p,p), 1_${ik}$ ) end do if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', nr-1, nr-1, czero, czero, u(1_${ik}$,2_${ik}$), ldu ) call stdlib${ii}$_${ci}$gesvj( 'L', 'U', 'N', nr,nr, u, ldu, sva, nr, a,lda, cwork(n+1), lwork-& n, rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < m ) then call stdlib${ii}$_${ci}$laset( 'A', m-nr, nr,czero, czero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_${ci}$laset( 'A',nr, n1-nr, czero, czero, u(1_${ik}$,nr+1),ldu ) call stdlib${ii}$_${ci}$laset( 'A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1),ldu ) end if end if call stdlib${ii}$_${ci}$unmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-n, & ierr ) if ( rowpiv )call stdlib${ii}$_${ci}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) do p = 1, n1 xsc = one / stdlib${ii}$_${c2ri(ci)}$znrm2( m, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( m, xsc, u(1_${ik}$,p), 1_${ik}$ ) end do if ( transp ) then call stdlib${ii}$_${ci}$lacpy( 'A', n, n, u, ldu, v, ldv ) end if else ! Full Svd if ( .not. jracc ) then if ( .not. almort ) then ! second preconditioning step (qrf [with pivoting]) ! note that the composition of transpose, qrf and transpose is ! equivalent to an lqf call. since in many libraries the qrf ! seems to be better optimized than the lqf, we do explicit ! transpose and use the qrf. this is subject to changes in an ! optimized implementation of stdlib${ii}$_${ci}$gejsv. do p = 1, nr call stdlib${ii}$_${ci}$copy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( n-p+1, v(p,p), 1_${ik}$ ) end do ! The Following Two Loops Perturb Small Entries To Avoid ! denormals in the second qr factorization, where they are ! as good as zeros. this is done to avoid painfully slow ! computation with denormals. the relative size of the perturbation ! is a parameter that can be changed by the implementer. ! this perturbation device will be obsolete on machines with ! properly implemented arithmetic. ! to switch it off, set l2pert=.false. to remove it from the ! code, remove the action under l2pert=.true., leave the else part. ! the following two loops should be blocked and fused with the ! transposed copy above. if ( l2pert ) then xsc = sqrt(small) do q = 1, nr ctemp = cmplx(xsc*abs( v(q,q) ),zero,KIND=${ck}$) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = & ctemp ! $ v(p,q) = temp1 * ( v(p,q) / abs(v(p,q)) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', nr-1, nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) end if ! estimate the row scaled condition number of r1 ! (if r1 is rectangular, n > nr, then the condition number ! of the leading nr x nr submatrix is estimated.) call stdlib${ii}$_${ci}$lacpy( 'L', nr, nr, v, ldv, cwork(2_${ik}$*n+1), nr ) do p = 1, nr temp1 = stdlib${ii}$_${c2ri(ci)}$znrm2(nr-p+1,cwork(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) call stdlib${ii}$_${ci}$dscal(nr-p+1,one/temp1,cwork(2_${ik}$*n+(p-1)*nr+p),1_${ik}$) end do call stdlib${ii}$_${ci}$pocon('L',nr,cwork(2_${ik}$*n+1),nr,one,temp1,cwork(2_${ik}$*n+nr*nr+1),rwork,& ierr) condr1 = one / sqrt(temp1) ! Here Need A Second Opinion On The Condition Number ! Then Assume Worst Case Scenario ! r1 is ok for inverse <=> condr1 < real(n,KIND=${ck}$) ! more conservative <=> condr1 < sqrt(real(n,KIND=${ck}$)) cond_ok = sqrt(sqrt(real(nr,KIND=${ck}$))) ! [tp] cond_ok is a tuning parameter. if ( condr1 < cond_ok ) then ! .. the second qrf without pivoting. note: in an optimized ! implementation, this qrf should be implemented as the qrf ! of a lower triangular matrix. ! r1^* = q2 * r2 call stdlib${ii}$_${ci}$geqrf( n, nr, v, ldv, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small)/epsln do p = 2, nr do q = 1, p - 1 ctemp=cmplx(xsc*min(abs(v(p,p)),abs(v(q,q))),zero,KIND=${ck}$) if ( abs(v(q,p)) <= temp1 )v(q,p) = ctemp ! $ v(q,p) = temp1 * ( v(q,p) / abs(v(q,p)) ) end do end do end if if ( nr /= n )call stdlib${ii}$_${ci}$lacpy( 'A', n, nr, v, ldv, cwork(2_${ik}$*n+1), n ) ! .. save ... ! This Transposed Copy Should Be Better Than Naive do p = 1, nr - 1 call stdlib${ii}$_${ci}$copy( nr-p, v(p,p+1), ldv, v(p+1,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv(nr-p+1, v(p,p), 1_${ik}$ ) end do v(nr,nr)=conjg(v(nr,nr)) condr2 = condr1 else ! .. ill-conditioned case: second qrf with pivoting ! note that windowed pivoting would be equally good ! numerically, and more run-time efficient. so, in ! an optimal implementation, the next call to stdlib${ii}$_${ci}$geqp3 ! should be replaced with eg. call zgeqpx (acm toms #782) ! with properly (carefully) chosen parameters. ! r1^* * p2 = q2 * r2 do p = 1, nr iwork(n+p) = 0_${ik}$ end do call stdlib${ii}$_${ci}$geqp3( n, nr, v, ldv, iwork(n+1), cwork(n+1),cwork(2_${ik}$*n+1), lwork-& 2_${ik}$*n, rwork, ierr ) ! * call stdlib${ii}$_${ci}$geqrf( n, nr, v, ldv, cwork(n+1), cwork(2*n+1), ! * $ lwork-2*n, ierr ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 ctemp=cmplx(xsc*min(abs(v(p,p)),abs(v(q,q))),zero,KIND=${ck}$) if ( abs(v(q,p)) <= temp1 )v(q,p) = ctemp ! $ v(q,p) = temp1 * ( v(q,p) / abs(v(q,p)) ) end do end do end if call stdlib${ii}$_${ci}$lacpy( 'A', n, nr, v, ldv, cwork(2_${ik}$*n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, nr do q = 1, p - 1 ctemp=cmplx(xsc*min(abs(v(p,p)),abs(v(q,q))),zero,KIND=${ck}$) ! v(p,q) = - temp1*( v(q,p) / abs(v(q,p)) ) v(p,q) = - ctemp end do end do else if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'L',nr-1,nr-1,czero,czero,v(2_${ik}$,1_${ik}$),ldv ) end if ! now, compute r2 = l3 * q3, the lq factorization. call stdlib${ii}$_${ci}$gelqf( nr, nr, v, ldv, cwork(2_${ik}$*n+n*nr+1),cwork(2_${ik}$*n+n*nr+nr+1), & lwork-2*n-n*nr-nr, ierr ) ! And Estimate The Condition Number call stdlib${ii}$_${ci}$lacpy( 'L',nr,nr,v,ldv,cwork(2_${ik}$*n+n*nr+nr+1),nr ) do p = 1, nr temp1 = stdlib${ii}$_${c2ri(ci)}$znrm2( p, cwork(2_${ik}$*n+n*nr+nr+p), nr ) call stdlib${ii}$_${ci}$dscal( p, one/temp1, cwork(2_${ik}$*n+n*nr+nr+p), nr ) end do call stdlib${ii}$_${ci}$pocon( 'L',nr,cwork(2_${ik}$*n+n*nr+nr+1),nr,one,temp1,cwork(2_${ik}$*n+n*nr+& nr+nr*nr+1),rwork,ierr ) condr2 = one / sqrt(temp1) if ( condr2 >= cond_ok ) then ! Save The Householder Vectors Used For Q3 ! (this overwrites the copy of r2, as it will not be ! needed in this branch, but it does not overwritte the ! huseholder vectors of q2.). call stdlib${ii}$_${ci}$lacpy( 'U', nr, nr, v, ldv, cwork(2_${ik}$*n+1), n ) ! And The Rest Of The Information On Q3 Is In ! work(2*n+n*nr+1:2*n+n*nr+n) end if end if if ( l2pert ) then xsc = sqrt(small) do q = 2, nr ctemp = xsc * v(q,q) do p = 1, q - 1 ! v(p,q) = - temp1*( v(p,q) / abs(v(p,q)) ) v(p,q) = - ctemp end do end do else if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', nr-1,nr-1, czero,czero, v(1_${ik}$,2_${ik}$), ldv ) end if ! second preconditioning finished; continue with jacobi svd ! the input matrix is lower trinagular. ! recover the right singular vectors as solution of a well ! conditioned triangular matrix equation. if ( condr1 < cond_ok ) then call stdlib${ii}$_${ci}$gesvj( 'L','U','N',nr,nr,v,ldv,sva,nr,u, ldu,cwork(2_${ik}$*n+n*nr+nr+1)& ,lwork-2*n-n*nr-nr,rwork,lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_${ci}$copy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( nr, sva(p), v(1_${ik}$,p), 1_${ik}$ ) end do ! Pick The Right Matrix Equation And Solve It if ( nr == n ) then ! :)) .. best case, r1 is inverted. the solution of this matrix ! equation is q2*v2 = the product of the jacobi rotations ! used in stdlib${ii}$_${ci}$gesvj, premultiplied with the orthogonal matrix ! from the second qr factorization. call stdlib${ii}$_${ci}$trsm('L','U','N','N', nr,nr,cone, a,lda, v,ldv) else ! .. r1 is well conditioned, but non-square. adjoint of r2 ! is inverted to get the product of the jacobi rotations ! used in stdlib${ii}$_${ci}$gesvj. the q-factor from the second qr ! factorization is then built in explicitly. call stdlib${ii}$_${ci}$trsm('L','U','C','N',nr,nr,cone,cwork(2_${ik}$*n+1),n,v,ldv) if ( nr < n ) then call stdlib${ii}$_${ci}$laset('A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv) call stdlib${ii}$_${ci}$laset('A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv) call stdlib${ii}$_${ci}$laset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_${ci}$unmqr('L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(& 2_${ik}$*n+n*nr+nr+1),lwork-2*n-n*nr-nr,ierr) end if else if ( condr2 < cond_ok ) then ! the matrix r2 is inverted. the solution of the matrix equation ! is q3^* * v3 = the product of the jacobi rotations (appplied to ! the lower triangular l3 from the lq factorization of ! r2=l3*q3), pre-multiplied with the transposed q3. call stdlib${ii}$_${ci}$gesvj( 'L', 'U', 'N', nr, nr, v, ldv, sva, nr, u,ldu, cwork(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr,rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) do p = 1, nr call stdlib${ii}$_${ci}$copy( nr, v(1_${ik}$,p), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( nr, sva(p), u(1_${ik}$,p), 1_${ik}$ ) end do call stdlib${ii}$_${ci}$trsm('L','U','N','N',nr,nr,cone,cwork(2_${ik}$*n+1),n,u,ldu) ! Apply The Permutation From The Second Qr Factorization do q = 1, nr do p = 1, nr cwork(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do end do if ( nr < n ) then call stdlib${ii}$_${ci}$laset( 'A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_${ci}$laset( 'A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_${ci}$laset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_${ci}$unmqr( 'L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) else ! last line of defense. ! #:( this is a rather pathological case: no scaled condition ! improvement after two pivoted qr factorizations. other ! possibility is that the rank revealing qr factorization ! or the condition estimator has failed, or the cond_ok ! is set very close to one (which is unnecessary). normally, ! this branch should never be executed, but in rare cases of ! failure of the rrqr or condition estimator, the last line of ! defense ensures that stdlib${ii}$_${ci}$gejsv completes the task. ! compute the full svd of l3 using stdlib${ii}$_${ci}$gesvj with explicit ! accumulation of jacobi rotations. call stdlib${ii}$_${ci}$gesvj( 'L', 'U', 'V', nr, nr, v, ldv, sva, nr, u,ldu, cwork(2_${ik}$*n+& n*nr+nr+1), lwork-2*n-n*nr-nr,rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_${ci}$laset( 'A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_${ci}$laset( 'A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_${ci}$laset('A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv) end if call stdlib${ii}$_${ci}$unmqr( 'L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(2_${ik}$*n+& n*nr+nr+1),lwork-2*n-n*nr-nr,ierr ) call stdlib${ii}$_${ci}$unmlq( 'L', 'C', nr, nr, nr, cwork(2_${ik}$*n+1), n,cwork(2_${ik}$*n+n*nr+1), & u, ldu, cwork(2_${ik}$*n+n*nr+nr+1),lwork-2*n-n*nr-nr, ierr ) do q = 1, nr do p = 1, nr cwork(2_${ik}$*n+n*nr+nr+iwork(n+p)) = u(p,q) end do do p = 1, nr u(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do end do end if ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=${ck}$)) * epsln do q = 1, n do p = 1, n cwork(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_${ci}$dscal( n, xsc,& v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_${ci}$laset('A', m-nr, nr, czero, czero, u(nr+1,1_${ik}$), ldu) if ( nr < n1 ) then call stdlib${ii}$_${ci}$laset('A',nr,n1-nr,czero,czero,u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_${ci}$laset('A',m-nr,n1-nr,czero,cone,u(nr+1,nr+1),ldu) end if end if ! the q matrix from the first qrf is built into the left singular ! matrix u. this applies to all cases. call stdlib${ii}$_${ci}$unmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-& n, ierr ) ! the columns of u are normalized. the cost is o(m*n) flops. temp1 = sqrt(real(m,KIND=${ck}$)) * epsln do p = 1, nr xsc = one / stdlib${ii}$_${c2ri(ci)}$znrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_${ci}$dscal( m, xsc,& u(1_${ik}$,p), 1_${ik}$ ) end do ! if the initial qrf is computed with row pivoting, the left ! singular vectors must be adjusted. if ( rowpiv )call stdlib${ii}$_${ci}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) else ! The Initial Matrix A Has Almost Orthogonal Columns And ! the second qrf is not needed call stdlib${ii}$_${ci}$lacpy( 'U', n, n, a, lda, cwork(n+1), n ) if ( l2pert ) then xsc = sqrt(small) do p = 2, n ctemp = xsc * cwork( n + (p-1)*n + p ) do q = 1, p - 1 ! cwork(n+(q-1)*n+p)=-temp1 * ( cwork(n+(p-1)*n+q) / ! $ abs(cwork(n+(p-1)*n+q)) ) cwork(n+(q-1)*n+p)=-ctemp end do end do else call stdlib${ii}$_${ci}$laset( 'L',n-1,n-1,czero,czero,cwork(n+2),n ) end if call stdlib${ii}$_${ci}$gesvj( 'U', 'U', 'N', n, n, cwork(n+1), n, sva,n, u, ldu, cwork(n+& n*n+1), lwork-n-n*n, rwork, lrwork,info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) do p = 1, n call stdlib${ii}$_${ci}$copy( n, cwork(n+(p-1)*n+1), 1_${ik}$, u(1_${ik}$,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( n, sva(p), cwork(n+(p-1)*n+1), 1_${ik}$ ) end do call stdlib${ii}$_${ci}$trsm( 'L', 'U', 'N', 'N', n, n,cone, a, lda, cwork(n+1), n ) do p = 1, n call stdlib${ii}$_${ci}$copy( n, cwork(n+p), n, v(iwork(p),1_${ik}$), ldv ) end do temp1 = sqrt(real(n,KIND=${ck}$))*epsln do p = 1, n xsc = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, v(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_${ci}$dscal( n, xsc,& v(1_${ik}$,p), 1_${ik}$ ) end do ! assemble the left singular vector matrix u (m x n). if ( n < m ) then call stdlib${ii}$_${ci}$laset( 'A', m-n, n, czero, czero, u(n+1,1_${ik}$), ldu ) if ( n < n1 ) then call stdlib${ii}$_${ci}$laset('A',n, n1-n, czero, czero, u(1_${ik}$,n+1),ldu) call stdlib${ii}$_${ci}$laset( 'A',m-n,n1-n, czero, cone,u(n+1,n+1),ldu) end if end if call stdlib${ii}$_${ci}$unmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-& n, ierr ) temp1 = sqrt(real(m,KIND=${ck}$))*epsln do p = 1, n1 xsc = one / stdlib${ii}$_${c2ri(ci)}$znrm2( m, u(1_${ik}$,p), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_${ci}$dscal( m, xsc,& u(1_${ik}$,p), 1_${ik}$ ) end do if ( rowpiv )call stdlib${ii}$_${ci}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) end if ! end of the >> almost orthogonal case << in the full svd else ! this branch deploys a preconditioned jacobi svd with explicitly ! accumulated rotations. it is included as optional, mainly for ! experimental purposes. it does perform well, and can also be used. ! in this implementation, this branch will be automatically activated ! if the condition number sigma_max(a) / sigma_min(a) is predicted ! to be greater than the overflow threshold. this is because the ! a posteriori computation of the singular vectors assumes robust ! implementation of blas and some lapack procedures, capable of working ! in presence of extreme values, e.g. when the singular values spread from ! the underflow to the overflow threshold. do p = 1, nr call stdlib${ii}$_${ci}$copy( n-p+1, a(p,p), lda, v(p,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( n-p+1, v(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 1, nr ctemp = cmplx(xsc*abs( v(q,q) ),zero,KIND=${ck}$) do p = 1, n if ( ( p > q ) .and. ( abs(v(p,q)) <= temp1 ).or. ( p < q ) )v(p,q) = & ctemp ! $ v(p,q) = temp1 * ( v(p,q) / abs(v(p,q)) ) if ( p < q ) v(p,q) = - v(p,q) end do end do else if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset( 'U', nr-1, nr-1, czero, czero, v(1_${ik}$,2_${ik}$), ldv ) end if call stdlib${ii}$_${ci}$geqrf( n, nr, v, ldv, cwork(n+1), cwork(2_${ik}$*n+1),lwork-2*n, ierr ) call stdlib${ii}$_${ci}$lacpy( 'L', n, nr, v, ldv, cwork(2_${ik}$*n+1), n ) do p = 1, nr call stdlib${ii}$_${ci}$copy( nr-p+1, v(p,p), ldv, u(p,p), 1_${ik}$ ) call stdlib${ii}$_${ci}$lacgv( nr-p+1, u(p,p), 1_${ik}$ ) end do if ( l2pert ) then xsc = sqrt(small/epsln) do q = 2, nr do p = 1, q - 1 ctemp = cmplx(xsc * min(abs(u(p,p)),abs(u(q,q))),zero,KIND=${ck}$) ! u(p,q) = - temp1 * ( u(q,p) / abs(u(q,p)) ) u(p,q) = - ctemp end do end do else if (nr>1_${ik}$) call stdlib${ii}$_${ci}$laset('U', nr-1, nr-1, czero, czero, u(1_${ik}$,2_${ik}$), ldu ) end if call stdlib${ii}$_${ci}$gesvj( 'L', 'U', 'V', nr, nr, u, ldu, sva,n, v, ldv, cwork(2_${ik}$*n+n*nr+1),& lwork-2*n-n*nr,rwork, lrwork, info ) scalem = rwork(1_${ik}$) numrank = nint(rwork(2_${ik}$),KIND=${ik}$) if ( nr < n ) then call stdlib${ii}$_${ci}$laset( 'A',n-nr,nr,czero,czero,v(nr+1,1_${ik}$),ldv ) call stdlib${ii}$_${ci}$laset( 'A',nr,n-nr,czero,czero,v(1_${ik}$,nr+1),ldv ) call stdlib${ii}$_${ci}$laset( 'A',n-nr,n-nr,czero,cone,v(nr+1,nr+1),ldv ) end if call stdlib${ii}$_${ci}$unmqr( 'L','N',n,n,nr,cwork(2_${ik}$*n+1),n,cwork(n+1),v,ldv,cwork(2_${ik}$*n+n*nr+& nr+1),lwork-2*n-n*nr-nr,ierr ) ! permute the rows of v using the (column) permutation from the ! first qrf. also, scale the columns to make them unit in ! euclidean norm. this applies to all cases. temp1 = sqrt(real(n,KIND=${ck}$)) * epsln do q = 1, n do p = 1, n cwork(2_${ik}$*n+n*nr+nr+iwork(p)) = v(p,q) end do do p = 1, n v(p,q) = cwork(2_${ik}$*n+n*nr+nr+p) end do xsc = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, v(1_${ik}$,q), 1_${ik}$ ) if ( (xsc < (one-temp1)) .or. (xsc > (one+temp1)) )call stdlib${ii}$_${ci}$dscal( n, xsc,& v(1_${ik}$,q), 1_${ik}$ ) end do ! at this moment, v contains the right singular vectors of a. ! next, assemble the left singular vector matrix u (m x n). if ( nr < m ) then call stdlib${ii}$_${ci}$laset( 'A', m-nr, nr, czero, czero, u(nr+1,1_${ik}$), ldu ) if ( nr < n1 ) then call stdlib${ii}$_${ci}$laset('A',nr, n1-nr, czero, czero, u(1_${ik}$,nr+1),ldu) call stdlib${ii}$_${ci}$laset('A',m-nr,n1-nr, czero, cone,u(nr+1,nr+1),ldu) end if end if call stdlib${ii}$_${ci}$unmqr( 'L', 'N', m, n1, n, a, lda, cwork, u,ldu, cwork(n+1), lwork-n, & ierr ) if ( rowpiv )call stdlib${ii}$_${ci}$laswp( n1, u, ldu, 1_${ik}$, m-1, iwork(iwoff+1), -1_${ik}$ ) end if if ( transp ) then ! .. swap u and v because the procedure worked on a^* do p = 1, n call stdlib${ii}$_${ci}$swap( n, u(1_${ik}$,p), 1_${ik}$, v(1_${ik}$,p), 1_${ik}$ ) end do end if end if ! end of the full svd ! undo scaling, if necessary (and possible) if ( uscal2 <= (big/sva(1_${ik}$))*uscal1 ) then call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, uscal1, uscal2, nr, 1_${ik}$, sva, n, ierr ) uscal1 = one uscal2 = one end if if ( nr < n ) then do p = nr+1, n sva(p) = zero end do end if rwork(1_${ik}$) = uscal2 * scalem rwork(2_${ik}$) = uscal1 if ( errest ) rwork(3_${ik}$) = sconda if ( lsvec .and. rsvec ) then rwork(4_${ik}$) = condr1 rwork(5_${ik}$) = condr2 end if if ( l2tran ) then rwork(6_${ik}$) = entra rwork(7_${ik}$) = entrat end if iwork(1_${ik}$) = nr iwork(2_${ik}$) = numrank iwork(3_${ik}$) = warning if ( transp ) then iwork(4_${ik}$) = 1_${ik}$ else iwork(4_${ik}$) = -1_${ik}$ end if return end subroutine stdlib${ii}$_${ci}$gejsv #:endif #:endfor pure module subroutine stdlib${ii}$_sgesvj( joba, jobu, jobv, m, n, a, lda, sva, mv, v,ldv, work, lwork, & !! SGESVJ computes the singular value decomposition (SVD) of a real !! M-by-N matrix A, where M >= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^t, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N orthogonal matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. !! SGESVJ can sometimes compute tiny singular values and their singular vectors much !! more accurately than other SVD routines, see below under Further Details. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n character, intent(in) :: joba, jobu, jobv ! Array Arguments real(sp), intent(inout) :: a(lda,*), v(ldv,*), work(lwork) real(sp), intent(out) :: sva(n) ! ===================================================================== ! Local Parameters integer(${ik}$), parameter :: nsweep = 30_${ik}$ ! Local Scalars real(sp) :: aapp, aapp0, aapq, aaqq, apoaq, aqoap, big, bigtheta, cs, ctol, epsln, & large, mxaapq, mxsinj, rootbig, rooteps, rootsfmin, roottol, skl, sfmin, small, sn, t, & temp1, theta, thsign, tol integer(${ik}$) :: blskip, emptsw, i, ibr, ierr, igl, ijblsk, ir1, iswrot, jbc, jgl, kbl, & lkahead, mvl, n2, n34, n4, nbl, notrot, p, pskipped, q, rowskip, swband logical(lk) :: applv, goscale, lower, lsvec, noscale, rotok, rsvec, uctol, & upper ! Local Arrays real(sp) :: fastr(5_${ik}$) ! Intrinsic Functions ! from lapack ! from lapack ! Executable Statements ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) uctol = stdlib_lsame( jobu, 'C' ) rsvec = stdlib_lsame( jobv, 'V' ) applv = stdlib_lsame( jobv, 'A' ) upper = stdlib_lsame( joba, 'U' ) lower = stdlib_lsame( joba, 'L' ) if( .not.( upper .or. lower .or. stdlib_lsame( joba, 'G' ) ) ) then info = -1_${ik}$ else if( .not.( lsvec .or. uctol .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -5_${ik}$ else if( ldaj}|a(:,i)^t * a(:,j)|/(||a(:,i)||*||a(:,j)||) < ctol*eps ! where eps is the round-off and ctol is defined as follows: if( uctol ) then ! ... user controlled ctol = work( 1_${ik}$ ) else ! ... default if( lsvec .or. rsvec .or. applv ) then ctol = sqrt( real( m,KIND=sp) ) else ctol = real( m,KIND=sp) end if end if ! ... and the machine dependent parameters are ! [!] (make sure that stdlib${ii}$_slamch() works properly on the target machine.) epsln = stdlib${ii}$_slamch( 'EPSILON' ) rooteps = sqrt( epsln ) sfmin = stdlib${ii}$_slamch( 'SAFEMINIMUM' ) rootsfmin = sqrt( sfmin ) small = sfmin / epsln big = stdlib${ii}$_slamch( 'OVERFLOW' ) ! big = one / sfmin rootbig = one / rootsfmin large = big / sqrt( real( m*n,KIND=sp) ) bigtheta = one / rooteps tol = ctol*epsln roottol = sqrt( tol ) if( real( m,KIND=sp)*epsln>=one ) then info = -4_${ik}$ call stdlib${ii}$_xerbla( 'SGESVJ', -info ) return end if ! initialize the right singular vector matrix. if( rsvec ) then mvl = n call stdlib${ii}$_slaset( 'A', mvl, n, zero, one, v, ldv ) else if( applv ) then mvl = mv end if rsvec = rsvec .or. applv ! initialize sva( 1:n ) = ( ||a e_i||_2, i = 1:n ) ! (!) if necessary, scale a to protect the largest singular value ! from overflow. it is possible that saving the largest singular ! value destroys the information about the small ones. ! this initial scaling is almost minimal in the sense that the ! goal is to make sure that no column norm overflows, and that ! sqrt(n)*max_i sva(i) does not overflow. if infinite entries ! in a are detected, the procedure returns with info=-6. skl = one / sqrt( real( m,KIND=sp)*real( n,KIND=sp) ) noscale = .true. goscale = .true. if( lower ) then ! the input matrix is m-by-n lower triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_slassq( m-p+1, a( p, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'SGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else if( upper ) then ! the input matrix is m-by-n upper triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_slassq( p, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'SGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else ! the input matrix is m-by-n general dense do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'SGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do end if if( noscale )skl = one ! move the smaller part of the spectrum from the underflow threshold ! (!) start by determining the position of the nonzero entries of the ! array sva() relative to ( sfmin, big ). aapp = zero aaqq = big do p = 1, n if( sva( p )/=zero )aaqq = min( aaqq, sva( p ) ) aapp = max( aapp, sva( p ) ) end do ! #:) quick return for zero matrix if( aapp==zero ) then if( lsvec )call stdlib${ii}$_slaset( 'G', m, n, zero, one, a, lda ) work( 1_${ik}$ ) = one work( 2_${ik}$ ) = zero work( 3_${ik}$ ) = zero work( 4_${ik}$ ) = zero work( 5_${ik}$ ) = zero work( 6_${ik}$ ) = zero return end if ! #:) quick return for one-column matrix if( n==1_${ik}$ ) then if( lsvec )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, sva( 1_${ik}$ ), skl, m, 1_${ik}$,a( 1_${ik}$, 1_${ik}$ ), lda, ierr ) work( 1_${ik}$ ) = one / skl if( sva( 1_${ik}$ )>=sfmin ) then work( 2_${ik}$ ) = one else work( 2_${ik}$ ) = zero end if work( 3_${ik}$ ) = zero work( 4_${ik}$ ) = zero work( 5_${ik}$ ) = zero work( 6_${ik}$ ) = zero return end if ! protect small singular values from underflow, and try to ! avoid underflows/overflows in computing jacobi rotations. sn = sqrt( sfmin / epsln ) temp1 = sqrt( big / real( n,KIND=sp) ) if( ( aapp<=sn ) .or. ( aaqq>=temp1 ) .or.( ( sn<=aaqq ) .and. ( aapp<=temp1 ) ) ) & then temp1 = min( big, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp<=temp1 ) ) then temp1 = min( sn / aaqq, big / ( aapp*sqrt( real( n,KIND=sp) ) ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq>=sn ) .and. ( aapp>=temp1 ) ) then temp1 = max( sn / aaqq, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp>=temp1 ) ) then temp1 = min( sn / aaqq, big / ( sqrt( real( n,KIND=sp) )*aapp ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else temp1 = one end if ! scale, if necessary if( temp1/=one ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, temp1, n, 1_${ik}$, sva, n, ierr ) end if skl = temp1*skl if( skl/=one ) then call stdlib${ii}$_slascl( joba, 0_${ik}$, 0_${ik}$, one, skl, m, n, a, lda, ierr ) skl = one / skl end if ! row-cyclic jacobi svd algorithm with column pivoting emptsw = ( n*( n-1 ) ) / 2_${ik}$ notrot = 0_${ik}$ fastr( 1_${ik}$ ) = zero ! a is represented in factored form a = a * diag(work), where diag(work) ! is initialized to identity. work is updated during fast scaled ! rotations. do q = 1, n work( q ) = one end do swband = 3_${ik}$ ! [tp] swband is a tuning parameter [tp]. it is meaningful and effective ! if stdlib${ii}$_sgesvj is used as a computational routine in the preconditioned ! jacobi svd algorithm stdlib${ii}$_sgesvj. for sweeps i=1:swband the procedure ! works on pivots inside a band-like region around the diagonal. ! the boundaries are determined dynamically, based on the number of ! pivots above a threshold. kbl = min( 8_${ik}$, n ) ! [tp] kbl is a tuning parameter that defines the tile size in the ! tiling of the p-q loops of pivot pairs. in general, an optimal ! value of kbl depends on the matrix dimensions and on the ! parameters of the computer's memory. nbl = n / kbl if( ( nbl*kbl )/=n )nbl = nbl + 1_${ik}$ blskip = kbl**2_${ik}$ ! [tp] blkskip is a tuning parameter that depends on swband and kbl. rowskip = min( 5_${ik}$, kbl ) ! [tp] rowskip is a tuning parameter. lkahead = 1_${ik}$ ! [tp] lkahead is a tuning parameter. ! quasi block transformations, using the lower (upper) triangular ! structure of the input matrix. the quasi-block-cycling usually ! invokes cubic convergence. big part of this cycle is done inside ! canonical subspaces of dimensions less than m. if( ( lower .or. upper ) .and. ( n>max( 64_${ik}$, 4_${ik}$*kbl ) ) ) then ! [tp] the number of partition levels and the actual partition are ! tuning parameters. n4 = n / 4_${ik}$ n2 = n / 2_${ik}$ n34 = 3_${ik}$*n4 if( applv ) then q = 0_${ik}$ else q = 1_${ik}$ end if if( lower ) then ! this works very well on lower triangular matrices, in particular ! in the framework of the preconditioned jacobi svd (xgejsv). ! the idea is simple: ! [+ 0 0 0] note that jacobi transformations of [0 0] ! [+ + 0 0] [0 0] ! [+ + x 0] actually work on [x 0] [x 0] ! [+ + x x] [x x]. [x x] call stdlib${ii}$_sgsvj0( jobv, m-n34, n-n34, a( n34+1, n34+1 ), lda,work( n34+1 ), & sva( n34+1 ), mvl,v( n34*q+1, n34+1 ), ldv, epsln, sfmin, tol,2_${ik}$, work( n+1 ), & lwork-n, ierr ) call stdlib${ii}$_sgsvj0( jobv, m-n2, n34-n2, a( n2+1, n2+1 ), lda,work( n2+1 ), sva( & n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 2_${ik}$,work( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_sgsvj1( jobv, m-n2, n-n2, n4, a( n2+1, n2+1 ), lda,work( n2+1 ), sva(& n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,work( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_sgsvj0( jobv, m-n4, n2-n4, a( n4+1, n4+1 ), lda,work( n4+1 ), sva( & n4+1 ), mvl,v( n4*q+1, n4+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,work( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_sgsvj0( jobv, m, n4, a, lda, work, sva, mvl, v, ldv,epsln, sfmin, & tol, 1_${ik}$, work( n+1 ), lwork-n,ierr ) call stdlib${ii}$_sgsvj1( jobv, m, n2, n4, a, lda, work, sva, mvl, v,ldv, epsln, sfmin,& tol, 1_${ik}$, work( n+1 ),lwork-n, ierr ) else if( upper ) then call stdlib${ii}$_sgsvj0( jobv, n4, n4, a, lda, work, sva, mvl, v, ldv,epsln, sfmin, & tol, 2_${ik}$, work( n+1 ), lwork-n,ierr ) call stdlib${ii}$_sgsvj0( jobv, n2, n4, a( 1_${ik}$, n4+1 ), lda, work( n4+1 ),sva( n4+1 ), & mvl, v( n4*q+1, n4+1 ), ldv,epsln, sfmin, tol, 1_${ik}$, work( n+1 ), lwork-n,ierr ) call stdlib${ii}$_sgsvj1( jobv, n2, n2, n4, a, lda, work, sva, mvl, v,ldv, epsln, & sfmin, tol, 1_${ik}$, work( n+1 ),lwork-n, ierr ) call stdlib${ii}$_sgsvj0( jobv, n2+n4, n4, a( 1_${ik}$, n2+1 ), lda,work( n2+1 ), sva( n2+1 ),& mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,work( n+1 ), lwork-n, ierr ) end if end if ! .. row-cyclic pivot strategy with de rijk's pivoting .. loop_1993: do i = 1, nsweep ! .. go go go ... mxaapq = zero mxsinj = zero iswrot = 0_${ik}$ notrot = 0_${ik}$ pskipped = 0_${ik}$ ! each sweep is unrolled using kbl-by-kbl tiles over the pivot pairs ! 1 <= p < q <= n. this is the first step toward a blocked implementation ! of the rotations. new implementation, based on block transformations, ! is under development. loop_2000: do ibr = 1, nbl igl = ( ibr-1 )*kbl + 1_${ik}$ loop_1002: do ir1 = 0, min( lkahead, nbl-ibr ) igl = igl + ir1*kbl loop_2001: do p = igl, min( igl+kbl-1, n-1 ) ! .. de rijk's pivoting q = stdlib${ii}$_isamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then call stdlib${ii}$_sswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_sswap( mvl, v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = work( p ) work( p ) = work( q ) work( q ) = temp1 end if if( ir1==0_${ik}$ ) then ! column norms are periodically updated by explicit ! norm computation. ! caveat: ! unfortunately, some blas implementations compute stdlib${ii}$_snrm2(m,a(1,p),1) ! as sqrt(stdlib${ii}$_sdot(m,a(1,p),1,a(1,p),1)), which may cause the result to ! overflow for ||a(:,p)||_2 > sqrt(overflow_threshold), and to ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_snrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_snrm2 is available, the if-then-else ! below should read "aapp = stdlib${ii}$_snrm2( m, a(1,p), 1 ) * work(p)". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_snrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*work( p ) else temp1 = zero aapp = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp )*work( p ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_sdot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_scopy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp,work( p ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_sdot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ )*work( & q ) / aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_sdot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_scopy( m, a( 1_${ik}$, q ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,work( q ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_sdot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ )*work( & p ) / aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then ! Rotate ! [rtd] rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq ) / aapq if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*work( p ) / work( q ) fastr( 4_${ik}$ ) = -t*work( q ) /work( p ) call stdlib${ii}$_srotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_srotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = work( p ) / work( q ) aqoap = work( q ) / work( p ) if( work( p )>=one ) then if( work( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap work( p ) = work( p )*cs work( q ) = work( q )*cs call stdlib${ii}$_srotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_srotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_saxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) work( p ) = work( p )*cs work( q ) = work( q ) / cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if end if else if( work( q )>=one ) then call stdlib${ii}$_saxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) work( p ) = work( p ) / cs work( q ) = work( q )*cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if else if( work( p )>=work( q ) )then call stdlib${ii}$_saxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) work( p ) = work( p )*cs work( q ) = work( q ) / cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_saxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) work( p ) = work( p ) / cs work( q ) = work( q )*cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_scopy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, work( n+1 ), & lda,ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) temp1 = -aapq*work( p ) / work( q ) call stdlib${ii}$_saxpy( m, temp1, work( n+1 ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_snrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*work( q ) else t = zero aaqq = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*work( q ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_snrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*work( p ) else t = zero aapp = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*work( p ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_sdot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_scopy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp,work( p ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_sdot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ )*work( & q ) / aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_sdot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_scopy( m, a( 1_${ik}$, q ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,work( q ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_sdot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ )*work( & p ) / aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq ) / aapq if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*work( p ) / work( q ) fastr( 4_${ik}$ ) = -t*work( q ) /work( p ) call stdlib${ii}$_srotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_srotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = work( p ) / work( q ) aqoap = work( q ) / work( p ) if( work( p )>=one ) then if( work( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap work( p ) = work( p )*cs work( q ) = work( q )*cs call stdlib${ii}$_srotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_srotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_saxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_saxpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if work( p ) = work( p )*cs work( q ) = work( q ) / cs end if else if( work( q )>=one ) then call stdlib${ii}$_saxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_saxpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if work( p ) = work( p ) / cs work( q ) = work( q )*cs else if( work( p )>=work( q ) )then call stdlib${ii}$_saxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) work( p ) = work( p )*cs work( q ) = work( q ) / cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_saxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) work( p ) = work( p ) / cs work( q ) = work( q )*cs if( rsvec ) then call stdlib${ii}$_saxpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_saxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else if( aapp>aaqq ) then call stdlib${ii}$_scopy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work( n+1 & ), lda,ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) temp1 = -aapq*work( p ) / work( q ) call stdlib${ii}$_saxpy( m, temp1, work( n+1 ),1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ & ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_scopy( m, a( 1_${ik}$, q ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work( n+1 & ), lda,ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) temp1 = -aapq*work( q ) / work( p ) call stdlib${ii}$_saxpy( m, temp1, work( n+1 ),1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ & ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q) ! .. recompute sva(q) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_snrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*work( q ) else t = zero aaqq = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*work( q ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_snrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*work( p ) else t = zero aapp = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*work( p ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_snrm2( m, a( 1_${ik}$, n ), 1_${ik}$ )*work( n ) else t = zero aapp = one call stdlib${ii}$_slassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp )*work( n ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the singular values and find how many are above ! the underflow threshold. n2 = 0_${ik}$ n4 = 0_${ik}$ do p = 1, n - 1 q = stdlib${ii}$_isamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = work( p ) work( p ) = work( q ) work( q ) = temp1 call stdlib${ii}$_sswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_sswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if if( sva( p )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( p )*skl>sfmin )n2 = n2 + 1_${ik}$ end if end do if( sva( n )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( n )*skl>sfmin )n2 = n2 + 1_${ik}$ end if ! normalize the left singular vectors. if( lsvec .or. uctol ) then do p = 1, n2 call stdlib${ii}$_sscal( m, work( p ) / sva( p ), a( 1_${ik}$, p ), 1_${ik}$ ) end do end if ! scale the product of jacobi rotations (assemble the fast rotations). if( rsvec ) then if( applv ) then do p = 1, n call stdlib${ii}$_sscal( mvl, work( p ), v( 1_${ik}$, p ), 1_${ik}$ ) end do else do p = 1, n temp1 = one / stdlib${ii}$_snrm2( mvl, v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_sscal( mvl, temp1, v( 1_${ik}$, p ), 1_${ik}$ ) end do end if end if ! undo scaling, if necessary (and possible). if( ( ( skl>one ) .and. ( sva( 1_${ik}$ )<( big / skl ) ) ).or. ( ( skl( sfmin / skl ) ) ) ) then do p = 1, n sva( p ) = skl*sva( p ) end do skl = one end if work( 1_${ik}$ ) = skl ! the singular values of a are skl*sva(1:n). if skl/=one ! then some of the singular values may overflow or underflow and ! the spectrum is given in this factored representation. work( 2_${ik}$ ) = real( n4,KIND=sp) ! n4 is the number of computed nonzero singular values of a. work( 3_${ik}$ ) = real( n2,KIND=sp) ! n2 is the number of singular values of a greater than sfmin. ! if n2= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^t, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N orthogonal matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. !! DGESVJ can sometimes compute tiny singular values and their singular vectors much !! more accurately than other SVD routines, see below under Further Details. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n character, intent(in) :: joba, jobu, jobv ! Array Arguments real(dp), intent(inout) :: a(lda,*), v(ldv,*), work(lwork) real(dp), intent(out) :: sva(n) ! ===================================================================== ! Local Parameters integer(${ik}$), parameter :: nsweep = 30_${ik}$ ! Local Scalars real(dp) :: aapp, aapp0, aapq, aaqq, apoaq, aqoap, big, bigtheta, cs, ctol, epsln, & large, mxaapq, mxsinj, rootbig, rooteps, rootsfmin, roottol, skl, sfmin, small, sn, t, & temp1, theta, thsign, tol integer(${ik}$) :: blskip, emptsw, i, ibr, ierr, igl, ijblsk, ir1, iswrot, jbc, jgl, kbl, & lkahead, mvl, n2, n34, n4, nbl, notrot, p, pskipped, q, rowskip, swband logical(lk) :: applv, goscale, lower, lsvec, noscale, rotok, rsvec, uctol, & upper ! Local Arrays real(dp) :: fastr(5_${ik}$) ! Intrinsic Functions ! from lapack ! from lapack ! Executable Statements ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) uctol = stdlib_lsame( jobu, 'C' ) rsvec = stdlib_lsame( jobv, 'V' ) applv = stdlib_lsame( jobv, 'A' ) upper = stdlib_lsame( joba, 'U' ) lower = stdlib_lsame( joba, 'L' ) if( .not.( upper .or. lower .or. stdlib_lsame( joba, 'G' ) ) ) then info = -1_${ik}$ else if( .not.( lsvec .or. uctol .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -5_${ik}$ else if( ldaj}|a(:,i)^t * a(:,j)|/(||a(:,i)||*||a(:,j)||) < ctol*eps ! where eps is the round-off and ctol is defined as follows: if( uctol ) then ! ... user controlled ctol = work( 1_${ik}$ ) else ! ... default if( lsvec .or. rsvec .or. applv ) then ctol = sqrt( real( m,KIND=dp) ) else ctol = real( m,KIND=dp) end if end if ! ... and the machine dependent parameters are ! [!] (make sure that stdlib${ii}$_dlamch() works properly on the target machine.) epsln = stdlib${ii}$_dlamch( 'EPSILON' ) rooteps = sqrt( epsln ) sfmin = stdlib${ii}$_dlamch( 'SAFEMINIMUM' ) rootsfmin = sqrt( sfmin ) small = sfmin / epsln big = stdlib${ii}$_dlamch( 'OVERFLOW' ) ! big = one / sfmin rootbig = one / rootsfmin large = big / sqrt( real( m*n,KIND=dp) ) bigtheta = one / rooteps tol = ctol*epsln roottol = sqrt( tol ) if( real( m,KIND=dp)*epsln>=one ) then info = -4_${ik}$ call stdlib${ii}$_xerbla( 'DGESVJ', -info ) return end if ! initialize the right singular vector matrix. if( rsvec ) then mvl = n call stdlib${ii}$_dlaset( 'A', mvl, n, zero, one, v, ldv ) else if( applv ) then mvl = mv end if rsvec = rsvec .or. applv ! initialize sva( 1:n ) = ( ||a e_i||_2, i = 1:n ) ! (!) if necessary, scale a to protect the largest singular value ! from overflow. it is possible that saving the largest singular ! value destroys the information about the small ones. ! this initial scaling is almost minimal in the sense that the ! goal is to make sure that no column norm overflows, and that ! sqrt(n)*max_i sva(i) does not overflow. if infinite entries ! in a are detected, the procedure returns with info=-6. skl= one / sqrt( real( m,KIND=dp)*real( n,KIND=dp) ) noscale = .true. goscale = .true. if( lower ) then ! the input matrix is m-by-n lower triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_dlassq( m-p+1, a( p, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'DGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else if( upper ) then ! the input matrix is m-by-n upper triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_dlassq( p, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'DGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else ! the input matrix is m-by-n general dense do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'DGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do end if if( noscale )skl= one ! move the smaller part of the spectrum from the underflow threshold ! (!) start by determining the position of the nonzero entries of the ! array sva() relative to ( sfmin, big ). aapp = zero aaqq = big do p = 1, n if( sva( p )/=zero )aaqq = min( aaqq, sva( p ) ) aapp = max( aapp, sva( p ) ) end do ! #:) quick return for zero matrix if( aapp==zero ) then if( lsvec )call stdlib${ii}$_dlaset( 'G', m, n, zero, one, a, lda ) work( 1_${ik}$ ) = one work( 2_${ik}$ ) = zero work( 3_${ik}$ ) = zero work( 4_${ik}$ ) = zero work( 5_${ik}$ ) = zero work( 6_${ik}$ ) = zero return end if ! #:) quick return for one-column matrix if( n==1_${ik}$ ) then if( lsvec )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, sva( 1_${ik}$ ), skl, m, 1_${ik}$,a( 1_${ik}$, 1_${ik}$ ), lda, ierr ) work( 1_${ik}$ ) = one / skl if( sva( 1_${ik}$ )>=sfmin ) then work( 2_${ik}$ ) = one else work( 2_${ik}$ ) = zero end if work( 3_${ik}$ ) = zero work( 4_${ik}$ ) = zero work( 5_${ik}$ ) = zero work( 6_${ik}$ ) = zero return end if ! protect small singular values from underflow, and try to ! avoid underflows/overflows in computing jacobi rotations. sn = sqrt( sfmin / epsln ) temp1 = sqrt( big / real( n,KIND=dp) ) if( ( aapp<=sn ) .or. ( aaqq>=temp1 ) .or.( ( sn<=aaqq ) .and. ( aapp<=temp1 ) ) ) & then temp1 = min( big, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp<=temp1 ) ) then temp1 = min( sn / aaqq, big / ( aapp*sqrt( real( n,KIND=dp) ) ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq>=sn ) .and. ( aapp>=temp1 ) ) then temp1 = max( sn / aaqq, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp>=temp1 ) ) then temp1 = min( sn / aaqq, big / ( sqrt( real( n,KIND=dp) )*aapp ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else temp1 = one end if ! scale, if necessary if( temp1/=one ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, temp1, n, 1_${ik}$, sva, n, ierr ) end if skl= temp1*skl if( skl/=one ) then call stdlib${ii}$_dlascl( joba, 0_${ik}$, 0_${ik}$, one, skl, m, n, a, lda, ierr ) skl= one / skl end if ! row-cyclic jacobi svd algorithm with column pivoting emptsw = ( n*( n-1 ) ) / 2_${ik}$ notrot = 0_${ik}$ fastr( 1_${ik}$ ) = zero ! a is represented in factored form a = a * diag(work), where diag(work) ! is initialized to identity. work is updated during fast scaled ! rotations. do q = 1, n work( q ) = one end do swband = 3_${ik}$ ! [tp] swband is a tuning parameter [tp]. it is meaningful and effective ! if stdlib${ii}$_dgesvj is used as a computational routine in the preconditioned ! jacobi svd algorithm stdlib${ii}$_dgesvj. for sweeps i=1:swband the procedure ! works on pivots inside a band-like region around the diagonal. ! the boundaries are determined dynamically, based on the number of ! pivots above a threshold. kbl = min( 8_${ik}$, n ) ! [tp] kbl is a tuning parameter that defines the tile size in the ! tiling of the p-q loops of pivot pairs. in general, an optimal ! value of kbl depends on the matrix dimensions and on the ! parameters of the computer's memory. nbl = n / kbl if( ( nbl*kbl )/=n )nbl = nbl + 1_${ik}$ blskip = kbl**2_${ik}$ ! [tp] blkskip is a tuning parameter that depends on swband and kbl. rowskip = min( 5_${ik}$, kbl ) ! [tp] rowskip is a tuning parameter. lkahead = 1_${ik}$ ! [tp] lkahead is a tuning parameter. ! quasi block transformations, using the lower (upper) triangular ! structure of the input matrix. the quasi-block-cycling usually ! invokes cubic convergence. big part of this cycle is done inside ! canonical subspaces of dimensions less than m. if( ( lower .or. upper ) .and. ( n>max( 64_${ik}$, 4_${ik}$*kbl ) ) ) then ! [tp] the number of partition levels and the actual partition are ! tuning parameters. n4 = n / 4_${ik}$ n2 = n / 2_${ik}$ n34 = 3_${ik}$*n4 if( applv ) then q = 0_${ik}$ else q = 1_${ik}$ end if if( lower ) then ! this works very well on lower triangular matrices, in particular ! in the framework of the preconditioned jacobi svd (xgejsv). ! the idea is simple: ! [+ 0 0 0] note that jacobi transformations of [0 0] ! [+ + 0 0] [0 0] ! [+ + x 0] actually work on [x 0] [x 0] ! [+ + x x] [x x]. [x x] call stdlib${ii}$_dgsvj0( jobv, m-n34, n-n34, a( n34+1, n34+1 ), lda,work( n34+1 ), & sva( n34+1 ), mvl,v( n34*q+1, n34+1 ), ldv, epsln, sfmin, tol,2_${ik}$, work( n+1 ), & lwork-n, ierr ) call stdlib${ii}$_dgsvj0( jobv, m-n2, n34-n2, a( n2+1, n2+1 ), lda,work( n2+1 ), sva( & n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 2_${ik}$,work( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_dgsvj1( jobv, m-n2, n-n2, n4, a( n2+1, n2+1 ), lda,work( n2+1 ), sva(& n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,work( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_dgsvj0( jobv, m-n4, n2-n4, a( n4+1, n4+1 ), lda,work( n4+1 ), sva( & n4+1 ), mvl,v( n4*q+1, n4+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,work( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_dgsvj0( jobv, m, n4, a, lda, work, sva, mvl, v, ldv,epsln, sfmin, & tol, 1_${ik}$, work( n+1 ), lwork-n,ierr ) call stdlib${ii}$_dgsvj1( jobv, m, n2, n4, a, lda, work, sva, mvl, v,ldv, epsln, sfmin,& tol, 1_${ik}$, work( n+1 ),lwork-n, ierr ) else if( upper ) then call stdlib${ii}$_dgsvj0( jobv, n4, n4, a, lda, work, sva, mvl, v, ldv,epsln, sfmin, & tol, 2_${ik}$, work( n+1 ), lwork-n,ierr ) call stdlib${ii}$_dgsvj0( jobv, n2, n4, a( 1_${ik}$, n4+1 ), lda, work( n4+1 ),sva( n4+1 ), & mvl, v( n4*q+1, n4+1 ), ldv,epsln, sfmin, tol, 1_${ik}$, work( n+1 ), lwork-n,ierr ) call stdlib${ii}$_dgsvj1( jobv, n2, n2, n4, a, lda, work, sva, mvl, v,ldv, epsln, & sfmin, tol, 1_${ik}$, work( n+1 ),lwork-n, ierr ) call stdlib${ii}$_dgsvj0( jobv, n2+n4, n4, a( 1_${ik}$, n2+1 ), lda,work( n2+1 ), sva( n2+1 ),& mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,work( n+1 ), lwork-n, ierr ) end if end if ! .. row-cyclic pivot strategy with de rijk's pivoting .. loop_1993: do i = 1, nsweep ! .. go go go ... mxaapq = zero mxsinj = zero iswrot = 0_${ik}$ notrot = 0_${ik}$ pskipped = 0_${ik}$ ! each sweep is unrolled using kbl-by-kbl tiles over the pivot pairs ! 1 <= p < q <= n. this is the first step toward a blocked implementation ! of the rotations. new implementation, based on block transformations, ! is under development. loop_2000: do ibr = 1, nbl igl = ( ibr-1 )*kbl + 1_${ik}$ loop_1002: do ir1 = 0, min( lkahead, nbl-ibr ) igl = igl + ir1*kbl loop_2001: do p = igl, min( igl+kbl-1, n-1 ) ! .. de rijk's pivoting q = stdlib${ii}$_idamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then call stdlib${ii}$_dswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_dswap( mvl, v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = work( p ) work( p ) = work( q ) work( q ) = temp1 end if if( ir1==0_${ik}$ ) then ! column norms are periodically updated by explicit ! norm computation. ! caveat: ! unfortunately, some blas implementations compute stdlib${ii}$_dnrm2(m,a(1,p),1) ! as sqrt(stdlib${ii}$_ddot(m,a(1,p),1,a(1,p),1)), which may cause the result to ! overflow for ||a(:,p)||_2 > sqrt(overflow_threshold), and to ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_dnrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_dnrm2 is available, the if-then-else ! below should read "aapp = stdlib${ii}$_dnrm2( m, a(1,p), 1 ) * work(p)". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*work( p ) else temp1 = zero aapp = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp )*work( p ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_ddot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp,work( p ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_ddot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ )*work( & q ) / aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_ddot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, q ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,work( q ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_ddot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ )*work( & p ) / aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then ! Rotate ! [rtd] rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs(aqoap-apoaq)/aapq if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*work( p ) / work( q ) fastr( 4_${ik}$ ) = -t*work( q ) /work( p ) call stdlib${ii}$_drotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_drotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = work( p ) / work( q ) aqoap = work( q ) / work( p ) if( work( p )>=one ) then if( work( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap work( p ) = work( p )*cs work( q ) = work( q )*cs call stdlib${ii}$_drotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_drotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_daxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) work( p ) = work( p )*cs work( q ) = work( q ) / cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if end if else if( work( q )>=one ) then call stdlib${ii}$_daxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) work( p ) = work( p ) / cs work( q ) = work( q )*cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if else if( work( p )>=work( q ) )then call stdlib${ii}$_daxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) work( p ) = work( p )*cs work( q ) = work( q ) / cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_daxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) work( p ) = work( p ) / cs work( q ) = work( q )*cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_dcopy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, work( n+1 ), & lda,ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) temp1 = -aapq*work( p ) / work( q ) call stdlib${ii}$_daxpy( m, temp1, work( n+1 ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*work( q ) else t = zero aaqq = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*work( q ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*work( p ) else t = zero aapp = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*work( p ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_ddot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp,work( p ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_ddot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ )*work( & q ) / aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_ddot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, q ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,work( q ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_ddot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ )*work( & p ) / aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs(aqoap-apoaq)/aapq if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*work( p ) / work( q ) fastr( 4_${ik}$ ) = -t*work( q ) /work( p ) call stdlib${ii}$_drotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_drotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = work( p ) / work( q ) aqoap = work( q ) / work( p ) if( work( p )>=one ) then if( work( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap work( p ) = work( p )*cs work( q ) = work( q )*cs call stdlib${ii}$_drotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_drotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_daxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_daxpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if work( p ) = work( p )*cs work( q ) = work( q ) / cs end if else if( work( q )>=one ) then call stdlib${ii}$_daxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_daxpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if work( p ) = work( p ) / cs work( q ) = work( q )*cs else if( work( p )>=work( q ) )then call stdlib${ii}$_daxpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) work( p ) = work( p )*cs work( q ) = work( q ) / cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_daxpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) work( p ) = work( p ) / cs work( q ) = work( q )*cs if( rsvec ) then call stdlib${ii}$_daxpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_daxpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else if( aapp>aaqq ) then call stdlib${ii}$_dcopy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work( n+1 & ), lda,ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) temp1 = -aapq*work( p ) / work( q ) call stdlib${ii}$_daxpy( m, temp1, work( n+1 ),1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ & ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_dcopy( m, a( 1_${ik}$, q ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work( n+1 & ), lda,ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) temp1 = -aapq*work( q ) / work( p ) call stdlib${ii}$_daxpy( m, temp1, work( n+1 ),1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ & ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q) ! .. recompute sva(q) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*work( q ) else t = zero aaqq = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*work( q ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*work( p ) else t = zero aapp = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*work( p ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_dnrm2( m, a( 1_${ik}$, n ), 1_${ik}$ )*work( n ) else t = zero aapp = one call stdlib${ii}$_dlassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp )*work( n ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the singular values and find how many are above ! the underflow threshold. n2 = 0_${ik}$ n4 = 0_${ik}$ do p = 1, n - 1 q = stdlib${ii}$_idamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = work( p ) work( p ) = work( q ) work( q ) = temp1 call stdlib${ii}$_dswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_dswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if if( sva( p )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( p )*skl>sfmin )n2 = n2 + 1_${ik}$ end if end do if( sva( n )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( n )*skl>sfmin )n2 = n2 + 1_${ik}$ end if ! normalize the left singular vectors. if( lsvec .or. uctol ) then do p = 1, n2 call stdlib${ii}$_dscal( m, work( p ) / sva( p ), a( 1_${ik}$, p ), 1_${ik}$ ) end do end if ! scale the product of jacobi rotations (assemble the fast rotations). if( rsvec ) then if( applv ) then do p = 1, n call stdlib${ii}$_dscal( mvl, work( p ), v( 1_${ik}$, p ), 1_${ik}$ ) end do else do p = 1, n temp1 = one / stdlib${ii}$_dnrm2( mvl, v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_dscal( mvl, temp1, v( 1_${ik}$, p ), 1_${ik}$ ) end do end if end if ! undo scaling, if necessary (and possible). if( ( ( skl>one ) .and. ( sva( 1_${ik}$ )<( big / skl) ) ).or. ( ( skl( sfmin / skl) ) ) ) then do p = 1, n sva( p ) = skl*sva( p ) end do skl= one end if work( 1_${ik}$ ) = skl ! the singular values of a are skl*sva(1:n). if skl/=one ! then some of the singular values may overflow or underflow and ! the spectrum is given in this factored representation. work( 2_${ik}$ ) = real( n4,KIND=dp) ! n4 is the number of computed nonzero singular values of a. work( 3_${ik}$ ) = real( n2,KIND=dp) ! n2 is the number of singular values of a greater than sfmin. ! if n2= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^t, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N orthogonal matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. !! DGESVJ can sometimes compute tiny singular values and their singular vectors much !! more accurately than other SVD routines, see below under Further Details. info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, m, mv, n character, intent(in) :: joba, jobu, jobv ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), v(ldv,*), work(lwork) real(${rk}$), intent(out) :: sva(n) ! ===================================================================== ! Local Parameters integer(${ik}$), parameter :: nsweep = 30_${ik}$ ! Local Scalars real(${rk}$) :: aapp, aapp0, aapq, aaqq, apoaq, aqoap, big, bigtheta, cs, ctol, epsln, & large, mxaapq, mxsinj, rootbig, rooteps, rootsfmin, roottol, skl, sfmin, small, sn, t, & temp1, theta, thsign, tol integer(${ik}$) :: blskip, emptsw, i, ibr, ierr, igl, ijblsk, ir1, iswrot, jbc, jgl, kbl, & lkahead, mvl, n2, n34, n4, nbl, notrot, p, pskipped, q, rowskip, swband logical(lk) :: applv, goscale, lower, lsvec, noscale, rotok, rsvec, uctol, & upper ! Local Arrays real(${rk}$) :: fastr(5_${ik}$) ! Intrinsic Functions ! from lapack ! from lapack ! Executable Statements ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) uctol = stdlib_lsame( jobu, 'C' ) rsvec = stdlib_lsame( jobv, 'V' ) applv = stdlib_lsame( jobv, 'A' ) upper = stdlib_lsame( joba, 'U' ) lower = stdlib_lsame( joba, 'L' ) if( .not.( upper .or. lower .or. stdlib_lsame( joba, 'G' ) ) ) then info = -1_${ik}$ else if( .not.( lsvec .or. uctol .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -5_${ik}$ else if( ldaj}|a(:,i)^t * a(:,j)|/(||a(:,i)||*||a(:,j)||) < ctol*eps ! where eps is the round-off and ctol is defined as follows: if( uctol ) then ! ... user controlled ctol = work( 1_${ik}$ ) else ! ... default if( lsvec .or. rsvec .or. applv ) then ctol = sqrt( real( m,KIND=${rk}$) ) else ctol = real( m,KIND=${rk}$) end if end if ! ... and the machine dependent parameters are ! [!] (make sure that stdlib${ii}$_${ri}$lamch() works properly on the target machine.) epsln = stdlib${ii}$_${ri}$lamch( 'EPSILON' ) rooteps = sqrt( epsln ) sfmin = stdlib${ii}$_${ri}$lamch( 'SAFEMINIMUM' ) rootsfmin = sqrt( sfmin ) small = sfmin / epsln big = stdlib${ii}$_${ri}$lamch( 'OVERFLOW' ) ! big = one / sfmin rootbig = one / rootsfmin large = big / sqrt( real( m*n,KIND=${rk}$) ) bigtheta = one / rooteps tol = ctol*epsln roottol = sqrt( tol ) if( real( m,KIND=${rk}$)*epsln>=one ) then info = -4_${ik}$ call stdlib${ii}$_xerbla( 'DGESVJ', -info ) return end if ! initialize the right singular vector matrix. if( rsvec ) then mvl = n call stdlib${ii}$_${ri}$laset( 'A', mvl, n, zero, one, v, ldv ) else if( applv ) then mvl = mv end if rsvec = rsvec .or. applv ! initialize sva( 1:n ) = ( ||a e_i||_2, i = 1:n ) ! (!) if necessary, scale a to protect the largest singular value ! from overflow. it is possible that saving the largest singular ! value destroys the information about the small ones. ! this initial scaling is almost minimal in the sense that the ! goal is to make sure that no column norm overflows, and that ! sqrt(n)*max_i sva(i) does not overflow. if infinite entries ! in a are detected, the procedure returns with info=-6. skl= one / sqrt( real( m,KIND=${rk}$)*real( n,KIND=${rk}$) ) noscale = .true. goscale = .true. if( lower ) then ! the input matrix is m-by-n lower triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_${ri}$lassq( m-p+1, a( p, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'DGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else if( upper ) then ! the input matrix is m-by-n upper triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_${ri}$lassq( p, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'DGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else ! the input matrix is m-by-n general dense do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'DGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do end if if( noscale )skl= one ! move the smaller part of the spectrum from the underflow threshold ! (!) start by determining the position of the nonzero entries of the ! array sva() relative to ( sfmin, big ). aapp = zero aaqq = big do p = 1, n if( sva( p )/=zero )aaqq = min( aaqq, sva( p ) ) aapp = max( aapp, sva( p ) ) end do ! #:) quick return for zero matrix if( aapp==zero ) then if( lsvec )call stdlib${ii}$_${ri}$laset( 'G', m, n, zero, one, a, lda ) work( 1_${ik}$ ) = one work( 2_${ik}$ ) = zero work( 3_${ik}$ ) = zero work( 4_${ik}$ ) = zero work( 5_${ik}$ ) = zero work( 6_${ik}$ ) = zero return end if ! #:) quick return for one-column matrix if( n==1_${ik}$ ) then if( lsvec )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, sva( 1_${ik}$ ), skl, m, 1_${ik}$,a( 1_${ik}$, 1_${ik}$ ), lda, ierr ) work( 1_${ik}$ ) = one / skl if( sva( 1_${ik}$ )>=sfmin ) then work( 2_${ik}$ ) = one else work( 2_${ik}$ ) = zero end if work( 3_${ik}$ ) = zero work( 4_${ik}$ ) = zero work( 5_${ik}$ ) = zero work( 6_${ik}$ ) = zero return end if ! protect small singular values from underflow, and try to ! avoid underflows/overflows in computing jacobi rotations. sn = sqrt( sfmin / epsln ) temp1 = sqrt( big / real( n,KIND=${rk}$) ) if( ( aapp<=sn ) .or. ( aaqq>=temp1 ) .or.( ( sn<=aaqq ) .and. ( aapp<=temp1 ) ) ) & then temp1 = min( big, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp<=temp1 ) ) then temp1 = min( sn / aaqq, big / ( aapp*sqrt( real( n,KIND=${rk}$) ) ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq>=sn ) .and. ( aapp>=temp1 ) ) then temp1 = max( sn / aaqq, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp>=temp1 ) ) then temp1 = min( sn / aaqq, big / ( sqrt( real( n,KIND=${rk}$) )*aapp ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else temp1 = one end if ! scale, if necessary if( temp1/=one ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, temp1, n, 1_${ik}$, sva, n, ierr ) end if skl= temp1*skl if( skl/=one ) then call stdlib${ii}$_${ri}$lascl( joba, 0_${ik}$, 0_${ik}$, one, skl, m, n, a, lda, ierr ) skl= one / skl end if ! row-cyclic jacobi svd algorithm with column pivoting emptsw = ( n*( n-1 ) ) / 2_${ik}$ notrot = 0_${ik}$ fastr( 1_${ik}$ ) = zero ! a is represented in factored form a = a * diag(work), where diag(work) ! is initialized to identity. work is updated during fast scaled ! rotations. do q = 1, n work( q ) = one end do swband = 3_${ik}$ ! [tp] swband is a tuning parameter [tp]. it is meaningful and effective ! if stdlib${ii}$_${ri}$gesvj is used as a computational routine in the preconditioned ! jacobi svd algorithm stdlib${ii}$_${ri}$gesvj. for sweeps i=1:swband the procedure ! works on pivots inside a band-like region around the diagonal. ! the boundaries are determined dynamically, based on the number of ! pivots above a threshold. kbl = min( 8_${ik}$, n ) ! [tp] kbl is a tuning parameter that defines the tile size in the ! tiling of the p-q loops of pivot pairs. in general, an optimal ! value of kbl depends on the matrix dimensions and on the ! parameters of the computer's memory. nbl = n / kbl if( ( nbl*kbl )/=n )nbl = nbl + 1_${ik}$ blskip = kbl**2_${ik}$ ! [tp] blkskip is a tuning parameter that depends on swband and kbl. rowskip = min( 5_${ik}$, kbl ) ! [tp] rowskip is a tuning parameter. lkahead = 1_${ik}$ ! [tp] lkahead is a tuning parameter. ! quasi block transformations, using the lower (upper) triangular ! structure of the input matrix. the quasi-block-cycling usually ! invokes cubic convergence. big part of this cycle is done inside ! canonical subspaces of dimensions less than m. if( ( lower .or. upper ) .and. ( n>max( 64_${ik}$, 4_${ik}$*kbl ) ) ) then ! [tp] the number of partition levels and the actual partition are ! tuning parameters. n4 = n / 4_${ik}$ n2 = n / 2_${ik}$ n34 = 3_${ik}$*n4 if( applv ) then q = 0_${ik}$ else q = 1_${ik}$ end if if( lower ) then ! this works very well on lower triangular matrices, in particular ! in the framework of the preconditioned jacobi svd (xgejsv). ! the idea is simple: ! [+ 0 0 0] note that jacobi transformations of [0 0] ! [+ + 0 0] [0 0] ! [+ + x 0] actually work on [x 0] [x 0] ! [+ + x x] [x x]. [x x] call stdlib${ii}$_${ri}$gsvj0( jobv, m-n34, n-n34, a( n34+1, n34+1 ), lda,work( n34+1 ), & sva( n34+1 ), mvl,v( n34*q+1, n34+1 ), ldv, epsln, sfmin, tol,2_${ik}$, work( n+1 ), & lwork-n, ierr ) call stdlib${ii}$_${ri}$gsvj0( jobv, m-n2, n34-n2, a( n2+1, n2+1 ), lda,work( n2+1 ), sva( & n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 2_${ik}$,work( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_${ri}$gsvj1( jobv, m-n2, n-n2, n4, a( n2+1, n2+1 ), lda,work( n2+1 ), sva(& n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,work( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_${ri}$gsvj0( jobv, m-n4, n2-n4, a( n4+1, n4+1 ), lda,work( n4+1 ), sva( & n4+1 ), mvl,v( n4*q+1, n4+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,work( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_${ri}$gsvj0( jobv, m, n4, a, lda, work, sva, mvl, v, ldv,epsln, sfmin, & tol, 1_${ik}$, work( n+1 ), lwork-n,ierr ) call stdlib${ii}$_${ri}$gsvj1( jobv, m, n2, n4, a, lda, work, sva, mvl, v,ldv, epsln, sfmin,& tol, 1_${ik}$, work( n+1 ),lwork-n, ierr ) else if( upper ) then call stdlib${ii}$_${ri}$gsvj0( jobv, n4, n4, a, lda, work, sva, mvl, v, ldv,epsln, sfmin, & tol, 2_${ik}$, work( n+1 ), lwork-n,ierr ) call stdlib${ii}$_${ri}$gsvj0( jobv, n2, n4, a( 1_${ik}$, n4+1 ), lda, work( n4+1 ),sva( n4+1 ), & mvl, v( n4*q+1, n4+1 ), ldv,epsln, sfmin, tol, 1_${ik}$, work( n+1 ), lwork-n,ierr ) call stdlib${ii}$_${ri}$gsvj1( jobv, n2, n2, n4, a, lda, work, sva, mvl, v,ldv, epsln, & sfmin, tol, 1_${ik}$, work( n+1 ),lwork-n, ierr ) call stdlib${ii}$_${ri}$gsvj0( jobv, n2+n4, n4, a( 1_${ik}$, n2+1 ), lda,work( n2+1 ), sva( n2+1 ),& mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,work( n+1 ), lwork-n, ierr ) end if end if ! .. row-cyclic pivot strategy with de rijk's pivoting .. loop_1993: do i = 1, nsweep ! .. go go go ... mxaapq = zero mxsinj = zero iswrot = 0_${ik}$ notrot = 0_${ik}$ pskipped = 0_${ik}$ ! each sweep is unrolled using kbl-by-kbl tiles over the pivot pairs ! 1 <= p < q <= n. this is the first step toward a blocked implementation ! of the rotations. new implementation, based on block transformations, ! is under development. loop_2000: do ibr = 1, nbl igl = ( ibr-1 )*kbl + 1_${ik}$ loop_1002: do ir1 = 0, min( lkahead, nbl-ibr ) igl = igl + ir1*kbl loop_2001: do p = igl, min( igl+kbl-1, n-1 ) ! .. de rijk's pivoting q = stdlib${ii}$_i${ri}$amax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then call stdlib${ii}$_${ri}$swap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_${ri}$swap( mvl, v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = work( p ) work( p ) = work( q ) work( q ) = temp1 end if if( ir1==0_${ik}$ ) then ! column norms are periodically updated by explicit ! norm computation. ! caveat: ! unfortunately, some blas implementations compute stdlib${ii}$_${ri}$nrm2(m,a(1,p),1) ! as sqrt(stdlib${ii}$_${ri}$dot(m,a(1,p),1,a(1,p),1)), which may cause the result to ! overflow for ||a(:,p)||_2 > sqrt(overflow_threshold), and to ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_${ri}$nrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_${ri}$nrm2 is available, the if-then-else ! below should read "aapp = stdlib${ii}$_${ri}$nrm2( m, a(1,p), 1 ) * work(p)". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*work( p ) else temp1 = zero aapp = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp )*work( p ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_${ri}$dot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp,work( p ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_${ri}$dot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ )*work( & q ) / aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_${ri}$dot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, q ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,work( q ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_${ri}$dot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ )*work( & p ) / aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then ! Rotate ! [rtd] rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs(aqoap-apoaq)/aapq if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*work( p ) / work( q ) fastr( 4_${ik}$ ) = -t*work( q ) /work( p ) call stdlib${ii}$_${ri}$rotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_${ri}$rotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = work( p ) / work( q ) aqoap = work( q ) / work( p ) if( work( p )>=one ) then if( work( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap work( p ) = work( p )*cs work( q ) = work( q )*cs call stdlib${ii}$_${ri}$rotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_${ri}$rotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_${ri}$axpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) work( p ) = work( p )*cs work( q ) = work( q ) / cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if end if else if( work( q )>=one ) then call stdlib${ii}$_${ri}$axpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) work( p ) = work( p ) / cs work( q ) = work( q )*cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if else if( work( p )>=work( q ) )then call stdlib${ii}$_${ri}$axpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) work( p ) = work( p )*cs work( q ) = work( q ) / cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_${ri}$axpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) work( p ) = work( p ) / cs work( q ) = work( q )*cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, work( n+1 ), & lda,ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) temp1 = -aapq*work( p ) / work( q ) call stdlib${ii}$_${ri}$axpy( m, temp1, work( n+1 ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*work( q ) else t = zero aaqq = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*work( q ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*work( p ) else t = zero aapp = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*work( p ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_${ri}$dot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp,work( p ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_${ri}$dot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ )*work( & q ) / aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_${ri}$dot( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$,q ), 1_${ik}$ )*work( & p )*work( q ) /aaqq ) / aapp else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, q ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,work( q ), m, 1_${ik}$,work( n+& 1_${ik}$ ), lda, ierr ) aapq = stdlib${ii}$_${ri}$dot( m, work( n+1 ), 1_${ik}$,a( 1_${ik}$, p ), 1_${ik}$ )*work( & p ) / aapp end if end if mxaapq = max( mxaapq, abs( aapq ) ) ! to rotate or not to rotate, that is the question ... if( abs( aapq )>tol ) then notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs(aqoap-apoaq)/aapq if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta fastr( 3_${ik}$ ) = t*work( p ) / work( q ) fastr( 4_${ik}$ ) = -t*work( q ) /work( p ) call stdlib${ii}$_${ri}$rotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$, fastr ) if( rsvec )call stdlib${ii}$_${ri}$rotm( mvl,v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ),& 1_${ik}$,fastr ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq ) ) apoaq = work( p ) / work( q ) aqoap = work( q ) / work( p ) if( work( p )>=one ) then if( work( q )>=one ) then fastr( 3_${ik}$ ) = t*apoaq fastr( 4_${ik}$ ) = -t*aqoap work( p ) = work( p )*cs work( q ) = work( q )*cs call stdlib${ii}$_${ri}$rotm( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$,& fastr ) if( rsvec )call stdlib${ii}$_${ri}$rotm( mvl,v( 1_${ik}$, p ), 1_${ik}$, v( & 1_${ik}$, q ),1_${ik}$, fastr ) else call stdlib${ii}$_${ri}$axpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( & 1_${ik}$, q ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl, -t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,v(& 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ), 1_${ik}$,& v( 1_${ik}$, q ), 1_${ik}$ ) end if work( p ) = work( p )*cs work( q ) = work( q ) / cs end if else if( work( q )>=one ) then call stdlib${ii}$_${ri}$axpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q & ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, -cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl, t*apoaq,v( 1_${ik}$, p ), 1_${ik}$,v( & 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q ), & 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if work( p ) = work( p ) / cs work( q ) = work( q )*cs else if( work( p )>=work( q ) )then call stdlib${ii}$_${ri}$axpy( m, -t*aqoap,a( 1_${ik}$, q ), 1_${ik}$,a( & 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m, cs*sn*apoaq,a( 1_${ik}$, p ), 1_${ik}$,& a( 1_${ik}$, q ), 1_${ik}$ ) work( p ) = work( p )*cs work( q ) = work( q ) / cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl,-t*aqoap,v( 1_${ik}$, q ), 1_${ik}$,& v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,cs*sn*apoaq,v( 1_${ik}$, p ),& 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) end if else call stdlib${ii}$_${ri}$axpy( m, t*apoaq,a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$,& q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( m,-cs*sn*aqoap,a( 1_${ik}$, q ), 1_${ik}$,& a( 1_${ik}$, p ), 1_${ik}$ ) work( p ) = work( p ) / cs work( q ) = work( q )*cs if( rsvec ) then call stdlib${ii}$_${ri}$axpy( mvl,t*apoaq, v( 1_${ik}$, p ),1_${ik}$, & v( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( mvl,-cs*sn*aqoap,v( 1_${ik}$, q )& , 1_${ik}$,v( 1_${ik}$, p ), 1_${ik}$ ) end if end if end if end if end if else if( aapp>aaqq ) then call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, work( n+1 & ), lda,ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) temp1 = -aapq*work( p ) / work( q ) call stdlib${ii}$_${ri}$axpy( m, temp1, work( n+1 ),1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ & ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_${ri}$copy( m, a( 1_${ik}$, q ), 1_${ik}$,work( n+1 ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, work( n+1 & ), lda,ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) temp1 = -aapq*work( q ) / work( p ) call stdlib${ii}$_${ri}$axpy( m, temp1, work( n+1 ),1_${ik}$, a( 1_${ik}$, p ), 1_${ik}$ & ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq*aapq ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q) ! .. recompute sva(q) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, q ), 1_${ik}$ )*work( q ) else t = zero aaqq = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq )*work( q ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, p ), 1_${ik}$ )*work( p ) else t = zero aapp = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp )*work( p ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_${ri}$nrm2( m, a( 1_${ik}$, n ), 1_${ik}$ )*work( n ) else t = zero aapp = one call stdlib${ii}$_${ri}$lassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp )*work( n ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the singular values and find how many are above ! the underflow threshold. n2 = 0_${ik}$ n4 = 0_${ik}$ do p = 1, n - 1 q = stdlib${ii}$_i${ri}$amax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 temp1 = work( p ) work( p ) = work( q ) work( q ) = temp1 call stdlib${ii}$_${ri}$swap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_${ri}$swap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if if( sva( p )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( p )*skl>sfmin )n2 = n2 + 1_${ik}$ end if end do if( sva( n )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( n )*skl>sfmin )n2 = n2 + 1_${ik}$ end if ! normalize the left singular vectors. if( lsvec .or. uctol ) then do p = 1, n2 call stdlib${ii}$_${ri}$scal( m, work( p ) / sva( p ), a( 1_${ik}$, p ), 1_${ik}$ ) end do end if ! scale the product of jacobi rotations (assemble the fast rotations). if( rsvec ) then if( applv ) then do p = 1, n call stdlib${ii}$_${ri}$scal( mvl, work( p ), v( 1_${ik}$, p ), 1_${ik}$ ) end do else do p = 1, n temp1 = one / stdlib${ii}$_${ri}$nrm2( mvl, v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( mvl, temp1, v( 1_${ik}$, p ), 1_${ik}$ ) end do end if end if ! undo scaling, if necessary (and possible). if( ( ( skl>one ) .and. ( sva( 1_${ik}$ )<( big / skl) ) ).or. ( ( skl( sfmin / skl) ) ) ) then do p = 1, n sva( p ) = skl*sva( p ) end do skl= one end if work( 1_${ik}$ ) = skl ! the singular values of a are skl*sva(1:n). if skl/=one ! then some of the singular values may overflow or underflow and ! the spectrum is given in this factored representation. work( 2_${ik}$ ) = real( n4,KIND=${rk}$) ! n4 is the number of computed nonzero singular values of a. work( 3_${ik}$ ) = real( n2,KIND=${rk}$) ! n2 is the number of singular values of a greater than sfmin. ! if n2= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N unitary matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. rwork, lrwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, lrwork, m, mv, n character, intent(in) :: joba, jobu, jobv ! Array Arguments complex(sp), intent(inout) :: a(lda,*), v(ldv,*), cwork(lwork) real(sp), intent(inout) :: rwork(lrwork) real(sp), intent(out) :: sva(n) ! ===================================================================== ! Local Parameters integer(${ik}$), parameter :: nsweep = 30_${ik}$ ! Local Scalars complex(sp) :: aapq, ompq real(sp) :: aapp, aapp0, aapq1, aaqq, apoaq, aqoap, big, bigtheta, cs, ctol, epsln, & mxaapq, mxsinj, rootbig, rooteps, rootsfmin, roottol, skl, sfmin, small, sn, t, temp1, & theta, thsign, tol integer(${ik}$) :: blskip, emptsw, i, ibr, ierr, igl, ijblsk, ir1, iswrot, jbc, jgl, kbl, & lkahead, mvl, n2, n34, n4, nbl, notrot, p, pskipped, q, rowskip, swband logical(lk) :: applv, goscale, lower, lquery, lsvec, noscale, rotok, rsvec, uctol, & upper ! Intrinsic Functions ! from lapack ! from lapack ! Executable Statements ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) .or. stdlib_lsame( jobu, 'F' ) uctol = stdlib_lsame( jobu, 'C' ) rsvec = stdlib_lsame( jobv, 'V' ) .or. stdlib_lsame( jobv, 'J' ) applv = stdlib_lsame( jobv, 'A' ) upper = stdlib_lsame( joba, 'U' ) lower = stdlib_lsame( joba, 'L' ) lquery = ( lwork == -1_${ik}$ ) .or. ( lrwork == -1_${ik}$ ) if( .not.( upper .or. lower .or. stdlib_lsame( joba, 'G' ) ) ) then info = -1_${ik}$ else if( .not.( lsvec .or. uctol .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -5_${ik}$ else if( ldaj}|a(:,i)^* * a(:,j)| / (||a(:,i)||*||a(:,j)||) < ctol*eps ! where eps is the round-off and ctol is defined as follows: if( uctol ) then ! ... user controlled ctol = rwork( 1_${ik}$ ) else ! ... default if( lsvec .or. rsvec .or. applv ) then ctol = sqrt( real( m,KIND=sp) ) else ctol = real( m,KIND=sp) end if end if ! ... and the machine dependent parameters are ! [!] (make sure that stdlib${ii}$_slamch() works properly on the target machine.) epsln = stdlib${ii}$_slamch( 'EPSILON' ) rooteps = sqrt( epsln ) sfmin = stdlib${ii}$_slamch( 'SAFEMINIMUM' ) rootsfmin = sqrt( sfmin ) small = sfmin / epsln ! big = stdlib${ii}$_slamch( 'overflow' ) big = one / sfmin rootbig = one / rootsfmin ! large = big / sqrt( real( m*n,KIND=sp) ) bigtheta = one / rooteps tol = ctol*epsln roottol = sqrt( tol ) if( real( m,KIND=sp)*epsln>=one ) then info = -4_${ik}$ call stdlib${ii}$_xerbla( 'CGESVJ', -info ) return end if ! initialize the right singular vector matrix. if( rsvec ) then mvl = n call stdlib${ii}$_claset( 'A', mvl, n, czero, cone, v, ldv ) else if( applv ) then mvl = mv end if rsvec = rsvec .or. applv ! initialize sva( 1:n ) = ( ||a e_i||_2, i = 1:n ) ! (!) if necessary, scale a to protect the largest singular value ! from overflow. it is possible that saving the largest singular ! value destroys the information about the small ones. ! this initial scaling is almost minimal in the sense that the ! goal is to make sure that no column norm overflows, and that ! sqrt(n)*max_i sva(i) does not overflow. if infinite entries ! in a are detected, the procedure returns with info=-6. skl = one / sqrt( real( m,KIND=sp)*real( n,KIND=sp) ) noscale = .true. goscale = .true. if( lower ) then ! the input matrix is m-by-n lower triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_classq( m-p+1, a( p, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'CGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else if( upper ) then ! the input matrix is m-by-n upper triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_classq( p, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'CGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else ! the input matrix is m-by-n general dense do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_classq( m, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'CGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do end if if( noscale )skl = one ! move the smaller part of the spectrum from the underflow threshold ! (!) start by determining the position of the nonzero entries of the ! array sva() relative to ( sfmin, big ). aapp = zero aaqq = big do p = 1, n if( sva( p )/=zero )aaqq = min( aaqq, sva( p ) ) aapp = max( aapp, sva( p ) ) end do ! #:) quick return for zero matrix if( aapp==zero ) then if( lsvec )call stdlib${ii}$_claset( 'G', m, n, czero, cone, a, lda ) rwork( 1_${ik}$ ) = one rwork( 2_${ik}$ ) = zero rwork( 3_${ik}$ ) = zero rwork( 4_${ik}$ ) = zero rwork( 5_${ik}$ ) = zero rwork( 6_${ik}$ ) = zero return end if ! #:) quick return for one-column matrix if( n==1_${ik}$ ) then if( lsvec )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, sva( 1_${ik}$ ), skl, m, 1_${ik}$,a( 1_${ik}$, 1_${ik}$ ), lda, ierr ) rwork( 1_${ik}$ ) = one / skl if( sva( 1_${ik}$ )>=sfmin ) then rwork( 2_${ik}$ ) = one else rwork( 2_${ik}$ ) = zero end if rwork( 3_${ik}$ ) = zero rwork( 4_${ik}$ ) = zero rwork( 5_${ik}$ ) = zero rwork( 6_${ik}$ ) = zero return end if ! protect small singular values from underflow, and try to ! avoid underflows/overflows in computing jacobi rotations. sn = sqrt( sfmin / epsln ) temp1 = sqrt( big / real( n,KIND=sp) ) if( ( aapp<=sn ) .or. ( aaqq>=temp1 ) .or.( ( sn<=aaqq ) .and. ( aapp<=temp1 ) ) ) & then temp1 = min( big, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp<=temp1 ) ) then temp1 = min( sn / aaqq, big / ( aapp*sqrt( real( n,KIND=sp) ) ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq>=sn ) .and. ( aapp>=temp1 ) ) then temp1 = max( sn / aaqq, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp>=temp1 ) ) then temp1 = min( sn / aaqq, big / ( sqrt( real( n,KIND=sp) )*aapp ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else temp1 = one end if ! scale, if necessary if( temp1/=one ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, one, temp1, n, 1_${ik}$, sva, n, ierr ) end if skl = temp1*skl if( skl/=one ) then call stdlib${ii}$_clascl( joba, 0_${ik}$, 0_${ik}$, one, skl, m, n, a, lda, ierr ) skl = one / skl end if ! row-cyclic jacobi svd algorithm with column pivoting emptsw = ( n*( n-1 ) ) / 2_${ik}$ notrot = 0_${ik}$ do q = 1, n cwork( q ) = cone end do swband = 3_${ik}$ ! [tp] swband is a tuning parameter [tp]. it is meaningful and effective ! if stdlib${ii}$_cgesvj is used as a computational routine in the preconditioned ! jacobi svd algorithm stdlib${ii}$_cgejsv. for sweeps i=1:swband the procedure ! works on pivots inside a band-like region around the diagonal. ! the boundaries are determined dynamically, based on the number of ! pivots above a threshold. kbl = min( 8_${ik}$, n ) ! [tp] kbl is a tuning parameter that defines the tile size in the ! tiling of the p-q loops of pivot pairs. in general, an optimal ! value of kbl depends on the matrix dimensions and on the ! parameters of the computer's memory. nbl = n / kbl if( ( nbl*kbl )/=n )nbl = nbl + 1_${ik}$ blskip = kbl**2_${ik}$ ! [tp] blkskip is a tuning parameter that depends on swband and kbl. rowskip = min( 5_${ik}$, kbl ) ! [tp] rowskip is a tuning parameter. lkahead = 1_${ik}$ ! [tp] lkahead is a tuning parameter. ! quasi block transformations, using the lower (upper) triangular ! structure of the input matrix. the quasi-block-cycling usually ! invokes cubic convergence. big part of this cycle is done inside ! canonical subspaces of dimensions less than m. if( ( lower .or. upper ) .and. ( n>max( 64_${ik}$, 4_${ik}$*kbl ) ) ) then ! [tp] the number of partition levels and the actual partition are ! tuning parameters. n4 = n / 4_${ik}$ n2 = n / 2_${ik}$ n34 = 3_${ik}$*n4 if( applv ) then q = 0_${ik}$ else q = 1_${ik}$ end if if( lower ) then ! this works very well on lower triangular matrices, in particular ! in the framework of the preconditioned jacobi svd (xgejsv). ! the idea is simple: ! [+ 0 0 0] note that jacobi transformations of [0 0] ! [+ + 0 0] [0 0] ! [+ + x 0] actually work on [x 0] [x 0] ! [+ + x x] [x x]. [x x] call stdlib${ii}$_cgsvj0( jobv, m-n34, n-n34, a( n34+1, n34+1 ), lda,cwork( n34+1 ), & sva( n34+1 ), mvl,v( n34*q+1, n34+1 ), ldv, epsln, sfmin, tol,2_${ik}$, cwork( n+1 ), & lwork-n, ierr ) call stdlib${ii}$_cgsvj0( jobv, m-n2, n34-n2, a( n2+1, n2+1 ), lda,cwork( n2+1 ), sva( & n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 2_${ik}$,cwork( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_cgsvj1( jobv, m-n2, n-n2, n4, a( n2+1, n2+1 ), lda,cwork( n2+1 ), & sva( n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,cwork( n+1 ), & lwork-n, ierr ) call stdlib${ii}$_cgsvj0( jobv, m-n4, n2-n4, a( n4+1, n4+1 ), lda,cwork( n4+1 ), sva( & n4+1 ), mvl,v( n4*q+1, n4+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,cwork( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_cgsvj0( jobv, m, n4, a, lda, cwork, sva, mvl, v, ldv,epsln, sfmin, & tol, 1_${ik}$, cwork( n+1 ), lwork-n,ierr ) call stdlib${ii}$_cgsvj1( jobv, m, n2, n4, a, lda, cwork, sva, mvl, v,ldv, epsln, & sfmin, tol, 1_${ik}$, cwork( n+1 ),lwork-n, ierr ) else if( upper ) then call stdlib${ii}$_cgsvj0( jobv, n4, n4, a, lda, cwork, sva, mvl, v, ldv,epsln, sfmin, & tol, 2_${ik}$, cwork( n+1 ), lwork-n,ierr ) call stdlib${ii}$_cgsvj0( jobv, n2, n4, a( 1_${ik}$, n4+1 ), lda, cwork( n4+1 ),sva( n4+1 ), & mvl, v( n4*q+1, n4+1 ), ldv,epsln, sfmin, tol, 1_${ik}$, cwork( n+1 ), lwork-n,ierr ) call stdlib${ii}$_cgsvj1( jobv, n2, n2, n4, a, lda, cwork, sva, mvl, v,ldv, epsln, & sfmin, tol, 1_${ik}$, cwork( n+1 ),lwork-n, ierr ) call stdlib${ii}$_cgsvj0( jobv, n2+n4, n4, a( 1_${ik}$, n2+1 ), lda,cwork( n2+1 ), sva( n2+1 )& , mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,cwork( n+1 ), lwork-n, ierr ) end if end if ! .. row-cyclic pivot strategy with de rijk's pivoting .. loop_1993: do i = 1, nsweep ! .. go go go ... mxaapq = zero mxsinj = zero iswrot = 0_${ik}$ notrot = 0_${ik}$ pskipped = 0_${ik}$ ! each sweep is unrolled using kbl-by-kbl tiles over the pivot pairs ! 1 <= p < q <= n. this is the first step toward a blocked implementation ! of the rotations. new implementation, based on block transformations, ! is under development. loop_2000: do ibr = 1, nbl igl = ( ibr-1 )*kbl + 1_${ik}$ loop_1002: do ir1 = 0, min( lkahead, nbl-ibr ) igl = igl + ir1*kbl loop_2001: do p = igl, min( igl+kbl-1, n-1 ) ! .. de rijk's pivoting q = stdlib${ii}$_isamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then call stdlib${ii}$_cswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_cswap( mvl, v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 aapq = cwork(p) cwork(p) = cwork(q) cwork(q) = aapq end if if( ir1==0_${ik}$ ) then ! column norms are periodically updated by explicit ! norm computation. ! [!] caveat: ! unfortunately, some blas implementations compute stdlib${ii}$_scnrm2(m,a(1,p),1) ! as sqrt(s=stdlib${ii}$_cdotc(m,a(1,p),1,a(1,p),1)), which may cause the result to ! overflow for ||a(:,p)||_2 > sqrt(overflow_threshold), and to ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_scnrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_scnrm2 is available, the if-then-else-end if ! below should be replaced with "aapp = stdlib${ii}$_scnrm2( m, a(1,p), 1 )". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else temp1 = zero aapp = one call stdlib${ii}$_classq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_cdotc( m, cwork(n+1), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aapp ) / aaqq else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, q ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_cdotc( m, a(1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg( cwork(p) ) * cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) ! Rotate ! [rtd] rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/aapq1 if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_crot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if ( rsvec ) then call stdlib${ii}$_crot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_crot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if ( rsvec ) then call stdlib${ii}$_crot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if cwork(p) = -cwork(q) * ompq else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_ccopy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, cwork(n+1), & lda,ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) call stdlib${ii}$_caxpy( m, -aapq, cwork(n+1), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, q ), 1_${ik}$ ) else t = zero aaqq = one call stdlib${ii}$_classq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_classq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp,one, m, 1_${ik}$,cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_cdotc( m, cwork(n+1), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / max(& aaqq,aapp) )/ min(aaqq,aapp) else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, q ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_cdotc( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg(cwork(p))*cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/ aapq1 if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_crot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if( rsvec ) then call stdlib${ii}$_crot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_crot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if( rsvec ) then call stdlib${ii}$_crot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if cwork(p) = -cwork(q) * ompq else ! .. have to use modified gram-schmidt like transformation if( aapp>aaqq ) then call stdlib${ii}$_ccopy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, cwork(n+1)& ,lda,ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) call stdlib${ii}$_caxpy( m, -aapq, cwork(n+1),1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_ccopy( m, a( 1_${ik}$, q ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, cwork(n+1)& ,lda,ierr ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) call stdlib${ii}$_caxpy( m, -conjg(aapq),cwork(n+1), 1_${ik}$, a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! .. recompute sva(q), sva(p) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, q ), 1_${ik}$) else t = zero aaqq = one call stdlib${ii}$_classq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_classq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_scnrm2( m, a( 1_${ik}$, n ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_classq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the singular values and find how many are above ! the underflow threshold. n2 = 0_${ik}$ n4 = 0_${ik}$ do p = 1, n - 1 q = stdlib${ii}$_isamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 call stdlib${ii}$_cswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_cswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if if( sva( p )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( p )*skl>sfmin )n2 = n2 + 1_${ik}$ end if end do if( sva( n )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( n )*skl>sfmin )n2 = n2 + 1_${ik}$ end if ! normalize the left singular vectors. if( lsvec .or. uctol ) then do p = 1, n4 ! call stdlib${ii}$_csscal( m, one / sva( p ), a( 1, p ), 1 ) call stdlib${ii}$_clascl( 'G',0_${ik}$,0_${ik}$, sva(p), one, m, 1_${ik}$, a(1_${ik}$,p), m, ierr ) end do end if ! scale the product of jacobi rotations. if( rsvec ) then do p = 1, n temp1 = one / stdlib${ii}$_scnrm2( mvl, v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_csscal( mvl, temp1, v( 1_${ik}$, p ), 1_${ik}$ ) end do end if ! undo scaling, if necessary (and possible). if( ( ( skl>one ) .and. ( sva( 1_${ik}$ )<( big / skl ) ) ).or. ( ( skl( sfmin / skl ) ) ) ) then do p = 1, n sva( p ) = skl*sva( p ) end do skl = one end if rwork( 1_${ik}$ ) = skl ! the singular values of a are skl*sva(1:n). if skl/=one ! then some of the singular values may overflow or underflow and ! the spectrum is given in this factored representation. rwork( 2_${ik}$ ) = real( n4,KIND=sp) ! n4 is the number of computed nonzero singular values of a. rwork( 3_${ik}$ ) = real( n2,KIND=sp) ! n2 is the number of singular values of a greater than sfmin. ! if n2= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N unitary matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. rwork, lrwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, lrwork, m, mv, n character, intent(in) :: joba, jobu, jobv ! Array Arguments complex(dp), intent(inout) :: a(lda,*), v(ldv,*), cwork(lwork) real(dp), intent(inout) :: rwork(lrwork) real(dp), intent(out) :: sva(n) ! ===================================================================== ! Local Parameters integer(${ik}$), parameter :: nsweep = 30_${ik}$ ! Local Scalars complex(dp) :: aapq, ompq real(dp) :: aapp, aapp0, aapq1, aaqq, apoaq, aqoap, big, bigtheta, cs, ctol, epsln, & mxaapq, mxsinj, rootbig, rooteps, rootsfmin, roottol, skl, sfmin, small, sn, t, temp1, & theta, thsign, tol integer(${ik}$) :: blskip, emptsw, i, ibr, ierr, igl, ijblsk, ir1, iswrot, jbc, jgl, kbl, & lkahead, mvl, n2, n34, n4, nbl, notrot, p, pskipped, q, rowskip, swband logical(lk) :: applv, goscale, lower, lquery, lsvec, noscale, rotok, rsvec, uctol, & upper ! Intrinsic Functions ! from lapack ! from lapack ! Executable Statements ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) .or. stdlib_lsame( jobu, 'F' ) uctol = stdlib_lsame( jobu, 'C' ) rsvec = stdlib_lsame( jobv, 'V' ) .or. stdlib_lsame( jobv, 'J' ) applv = stdlib_lsame( jobv, 'A' ) upper = stdlib_lsame( joba, 'U' ) lower = stdlib_lsame( joba, 'L' ) lquery = ( lwork == -1_${ik}$ ) .or. ( lrwork == -1_${ik}$ ) if( .not.( upper .or. lower .or. stdlib_lsame( joba, 'G' ) ) ) then info = -1_${ik}$ else if( .not.( lsvec .or. uctol .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -5_${ik}$ else if( ldaj}|a(:,i)^* * a(:,j)| / (||a(:,i)||*||a(:,j)||) < ctol*eps ! where eps is the round-off and ctol is defined as follows: if( uctol ) then ! ... user controlled ctol = rwork( 1_${ik}$ ) else ! ... default if( lsvec .or. rsvec .or. applv ) then ctol = sqrt( real( m,KIND=dp) ) else ctol = real( m,KIND=dp) end if end if ! ... and the machine dependent parameters are ! [!] (make sure that stdlib${ii}$_slamch() works properly on the target machine.) epsln = stdlib${ii}$_dlamch( 'EPSILON' ) rooteps = sqrt( epsln ) sfmin = stdlib${ii}$_dlamch( 'SAFEMINIMUM' ) rootsfmin = sqrt( sfmin ) small = sfmin / epsln big = stdlib${ii}$_dlamch( 'OVERFLOW' ) ! big = one / sfmin rootbig = one / rootsfmin ! large = big / sqrt( real( m*n,KIND=dp) ) bigtheta = one / rooteps tol = ctol*epsln roottol = sqrt( tol ) if( real( m,KIND=dp)*epsln>=one ) then info = -4_${ik}$ call stdlib${ii}$_xerbla( 'ZGESVJ', -info ) return end if ! initialize the right singular vector matrix. if( rsvec ) then mvl = n call stdlib${ii}$_zlaset( 'A', mvl, n, czero, cone, v, ldv ) else if( applv ) then mvl = mv end if rsvec = rsvec .or. applv ! initialize sva( 1:n ) = ( ||a e_i||_2, i = 1:n ) ! (!) if necessary, scale a to protect the largest singular value ! from overflow. it is possible that saving the largest singular ! value destroys the information about the small ones. ! this initial scaling is almost minimal in the sense that the ! goal is to make sure that no column norm overflows, and that ! sqrt(n)*max_i sva(i) does not overflow. if infinite entries ! in a are detected, the procedure returns with info=-6. skl = one / sqrt( real( m,KIND=dp)*real( n,KIND=dp) ) noscale = .true. goscale = .true. if( lower ) then ! the input matrix is m-by-n lower triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_zlassq( m-p+1, a( p, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'ZGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else if( upper ) then ! the input matrix is m-by-n upper triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_zlassq( p, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'ZGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else ! the input matrix is m-by-n general dense do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'ZGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do end if if( noscale )skl = one ! move the smaller part of the spectrum from the underflow threshold ! (!) start by determining the position of the nonzero entries of the ! array sva() relative to ( sfmin, big ). aapp = zero aaqq = big do p = 1, n if( sva( p )/=zero )aaqq = min( aaqq, sva( p ) ) aapp = max( aapp, sva( p ) ) end do ! #:) quick return for zero matrix if( aapp==zero ) then if( lsvec )call stdlib${ii}$_zlaset( 'G', m, n, czero, cone, a, lda ) rwork( 1_${ik}$ ) = one rwork( 2_${ik}$ ) = zero rwork( 3_${ik}$ ) = zero rwork( 4_${ik}$ ) = zero rwork( 5_${ik}$ ) = zero rwork( 6_${ik}$ ) = zero return end if ! #:) quick return for one-column matrix if( n==1_${ik}$ ) then if( lsvec )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, sva( 1_${ik}$ ), skl, m, 1_${ik}$,a( 1_${ik}$, 1_${ik}$ ), lda, ierr ) rwork( 1_${ik}$ ) = one / skl if( sva( 1_${ik}$ )>=sfmin ) then rwork( 2_${ik}$ ) = one else rwork( 2_${ik}$ ) = zero end if rwork( 3_${ik}$ ) = zero rwork( 4_${ik}$ ) = zero rwork( 5_${ik}$ ) = zero rwork( 6_${ik}$ ) = zero return end if ! protect small singular values from underflow, and try to ! avoid underflows/overflows in computing jacobi rotations. sn = sqrt( sfmin / epsln ) temp1 = sqrt( big / real( n,KIND=dp) ) if( ( aapp<=sn ) .or. ( aaqq>=temp1 ) .or.( ( sn<=aaqq ) .and. ( aapp<=temp1 ) ) ) & then temp1 = min( big, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp<=temp1 ) ) then temp1 = min( sn / aaqq, big / (aapp*sqrt( real(n,KIND=dp)) ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq>=sn ) .and. ( aapp>=temp1 ) ) then temp1 = max( sn / aaqq, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp>=temp1 ) ) then temp1 = min( sn / aaqq, big / ( sqrt( real( n,KIND=dp) )*aapp ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else temp1 = one end if ! scale, if necessary if( temp1/=one ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, one, temp1, n, 1_${ik}$, sva, n, ierr ) end if skl = temp1*skl if( skl/=one ) then call stdlib${ii}$_zlascl( joba, 0_${ik}$, 0_${ik}$, one, skl, m, n, a, lda, ierr ) skl = one / skl end if ! row-cyclic jacobi svd algorithm with column pivoting emptsw = ( n*( n-1 ) ) / 2_${ik}$ notrot = 0_${ik}$ do q = 1, n cwork( q ) = cone end do swband = 3_${ik}$ ! [tp] swband is a tuning parameter [tp]. it is meaningful and effective ! if stdlib${ii}$_zgesvj is used as a computational routine in the preconditioned ! jacobi svd algorithm stdlib${ii}$_zgejsv. for sweeps i=1:swband the procedure ! works on pivots inside a band-like region around the diagonal. ! the boundaries are determined dynamically, based on the number of ! pivots above a threshold. kbl = min( 8_${ik}$, n ) ! [tp] kbl is a tuning parameter that defines the tile size in the ! tiling of the p-q loops of pivot pairs. in general, an optimal ! value of kbl depends on the matrix dimensions and on the ! parameters of the computer's memory. nbl = n / kbl if( ( nbl*kbl )/=n )nbl = nbl + 1_${ik}$ blskip = kbl**2_${ik}$ ! [tp] blkskip is a tuning parameter that depends on swband and kbl. rowskip = min( 5_${ik}$, kbl ) ! [tp] rowskip is a tuning parameter. lkahead = 1_${ik}$ ! [tp] lkahead is a tuning parameter. ! quasi block transformations, using the lower (upper) triangular ! structure of the input matrix. the quasi-block-cycling usually ! invokes cubic convergence. big part of this cycle is done inside ! canonical subspaces of dimensions less than m. if( ( lower .or. upper ) .and. ( n>max( 64_${ik}$, 4_${ik}$*kbl ) ) ) then ! [tp] the number of partition levels and the actual partition are ! tuning parameters. n4 = n / 4_${ik}$ n2 = n / 2_${ik}$ n34 = 3_${ik}$*n4 if( applv ) then q = 0_${ik}$ else q = 1_${ik}$ end if if( lower ) then ! this works very well on lower triangular matrices, in particular ! in the framework of the preconditioned jacobi svd (xgejsv). ! the idea is simple: ! [+ 0 0 0] note that jacobi transformations of [0 0] ! [+ + 0 0] [0 0] ! [+ + x 0] actually work on [x 0] [x 0] ! [+ + x x] [x x]. [x x] call stdlib${ii}$_zgsvj0( jobv, m-n34, n-n34, a( n34+1, n34+1 ), lda,cwork( n34+1 ), & sva( n34+1 ), mvl,v( n34*q+1, n34+1 ), ldv, epsln, sfmin, tol,2_${ik}$, cwork( n+1 ), & lwork-n, ierr ) call stdlib${ii}$_zgsvj0( jobv, m-n2, n34-n2, a( n2+1, n2+1 ), lda,cwork( n2+1 ), sva( & n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 2_${ik}$,cwork( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_zgsvj1( jobv, m-n2, n-n2, n4, a( n2+1, n2+1 ), lda,cwork( n2+1 ), & sva( n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,cwork( n+1 ), & lwork-n, ierr ) call stdlib${ii}$_zgsvj0( jobv, m-n4, n2-n4, a( n4+1, n4+1 ), lda,cwork( n4+1 ), sva( & n4+1 ), mvl,v( n4*q+1, n4+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,cwork( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_zgsvj0( jobv, m, n4, a, lda, cwork, sva, mvl, v, ldv,epsln, sfmin, & tol, 1_${ik}$, cwork( n+1 ), lwork-n,ierr ) call stdlib${ii}$_zgsvj1( jobv, m, n2, n4, a, lda, cwork, sva, mvl, v,ldv, epsln, & sfmin, tol, 1_${ik}$, cwork( n+1 ),lwork-n, ierr ) else if( upper ) then call stdlib${ii}$_zgsvj0( jobv, n4, n4, a, lda, cwork, sva, mvl, v, ldv,epsln, sfmin, & tol, 2_${ik}$, cwork( n+1 ), lwork-n,ierr ) call stdlib${ii}$_zgsvj0( jobv, n2, n4, a( 1_${ik}$, n4+1 ), lda, cwork( n4+1 ),sva( n4+1 ), & mvl, v( n4*q+1, n4+1 ), ldv,epsln, sfmin, tol, 1_${ik}$, cwork( n+1 ), lwork-n,ierr ) call stdlib${ii}$_zgsvj1( jobv, n2, n2, n4, a, lda, cwork, sva, mvl, v,ldv, epsln, & sfmin, tol, 1_${ik}$, cwork( n+1 ),lwork-n, ierr ) call stdlib${ii}$_zgsvj0( jobv, n2+n4, n4, a( 1_${ik}$, n2+1 ), lda,cwork( n2+1 ), sva( n2+1 )& , mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,cwork( n+1 ), lwork-n, ierr ) end if end if ! .. row-cyclic pivot strategy with de rijk's pivoting .. loop_1993: do i = 1, nsweep ! .. go go go ... mxaapq = zero mxsinj = zero iswrot = 0_${ik}$ notrot = 0_${ik}$ pskipped = 0_${ik}$ ! each sweep is unrolled using kbl-by-kbl tiles over the pivot pairs ! 1 <= p < q <= n. this is the first step toward a blocked implementation ! of the rotations. new implementation, based on block transformations, ! is under development. loop_2000: do ibr = 1, nbl igl = ( ibr-1 )*kbl + 1_${ik}$ loop_1002: do ir1 = 0, min( lkahead, nbl-ibr ) igl = igl + ir1*kbl loop_2001: do p = igl, min( igl+kbl-1, n-1 ) ! .. de rijk's pivoting q = stdlib${ii}$_idamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then call stdlib${ii}$_zswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_zswap( mvl, v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 aapq = cwork(p) cwork(p) = cwork(q) cwork(q) = aapq end if if( ir1==0_${ik}$ ) then ! column norms are periodically updated by explicit ! norm computation. ! [!] caveat: ! unfortunately, some blas implementations compute stdlib${ii}$_dznrm2(m,a(1,p),1) ! as sqrt(s=stdlib${ii}$_cdotc(m,a(1,p),1,a(1,p),1)), which may cause the result to ! overflow for ||a(:,p)||_2 > sqrt(overflow_threshold), and to ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_dznrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_scnrm2 is available, the if-then-else-end if ! below should be replaced with "aapp = stdlib${ii}$_dznrm2( m, a(1,p), 1 )". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else temp1 = zero aapp = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_zdotc( m, cwork(n+1), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aapp ) / aaqq else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, q ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_zdotc( m, a(1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg( cwork(p) ) * cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) ! Rotate ! [rtd] rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/aapq1 if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_zrot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if ( rsvec ) then call stdlib${ii}$_zrot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_zrot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if ( rsvec ) then call stdlib${ii}$_zrot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if cwork(p) = -cwork(q) * ompq else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_zcopy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, cwork(n+1), & lda,ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) call stdlib${ii}$_zaxpy( m, -aapq, cwork(n+1), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, q ), 1_${ik}$ ) else t = zero aaqq = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp,one, m, 1_${ik}$,cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_zdotc( m, cwork(n+1), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / max(& aaqq,aapp) )/ min(aaqq,aapp) else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, q ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_zdotc( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg(cwork(p))*cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/ aapq1 if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_zrot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if( rsvec ) then call stdlib${ii}$_zrot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_zrot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if( rsvec ) then call stdlib${ii}$_zrot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if cwork(p) = -cwork(q) * ompq else ! .. have to use modified gram-schmidt like transformation if( aapp>aaqq ) then call stdlib${ii}$_zcopy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, cwork(n+1)& ,lda,ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) call stdlib${ii}$_zaxpy( m, -aapq, cwork(n+1),1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_zcopy( m, a( 1_${ik}$, q ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, cwork(n+1)& ,lda,ierr ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) call stdlib${ii}$_zaxpy( m, -conjg(aapq),cwork(n+1), 1_${ik}$, a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! .. recompute sva(q), sva(p) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, q ), 1_${ik}$) else t = zero aaqq = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_dznrm2( m, a( 1_${ik}$, n ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_zlassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the singular values and find how many are above ! the underflow threshold. n2 = 0_${ik}$ n4 = 0_${ik}$ do p = 1, n - 1 q = stdlib${ii}$_idamax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 call stdlib${ii}$_zswap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_zswap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if if( sva( p )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( p )*skl>sfmin )n2 = n2 + 1_${ik}$ end if end do if( sva( n )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( n )*skl>sfmin )n2 = n2 + 1_${ik}$ end if ! normalize the left singular vectors. if( lsvec .or. uctol ) then do p = 1, n4 ! call stdlib${ii}$_zdscal( m, one / sva( p ), a( 1, p ), 1 ) call stdlib${ii}$_zlascl( 'G',0_${ik}$,0_${ik}$, sva(p), one, m, 1_${ik}$, a(1_${ik}$,p), m, ierr ) end do end if ! scale the product of jacobi rotations. if( rsvec ) then do p = 1, n temp1 = one / stdlib${ii}$_dznrm2( mvl, v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_zdscal( mvl, temp1, v( 1_${ik}$, p ), 1_${ik}$ ) end do end if ! undo scaling, if necessary (and possible). if( ( ( skl>one ) .and. ( sva( 1_${ik}$ )<( big / skl ) ) ).or. ( ( skl( sfmin / skl ) ) ) ) then do p = 1, n sva( p ) = skl*sva( p ) end do skl = one end if rwork( 1_${ik}$ ) = skl ! the singular values of a are skl*sva(1:n). if skl/=one ! then some of the singular values may overflow or underflow and ! the spectrum is given in this factored representation. rwork( 2_${ik}$ ) = real( n4,KIND=dp) ! n4 is the number of computed nonzero singular values of a. rwork( 3_${ik}$ ) = real( n2,KIND=dp) ! n2 is the number of singular values of a greater than sfmin. ! if n2= N. The SVD of A is written as !! [++] [xx] [x0] [xx] !! A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx] !! [++] [xx] !! where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal !! matrix, and V is an N-by-N unitary matrix. The diagonal elements !! of SIGMA are the singular values of A. The columns of U and V are the !! left and the right singular vectors of A, respectively. rwork, lrwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldv, lwork, lrwork, m, mv, n character, intent(in) :: joba, jobu, jobv ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), v(ldv,*), cwork(lwork) real(${ck}$), intent(inout) :: rwork(lrwork) real(${ck}$), intent(out) :: sva(n) ! ===================================================================== ! Local Parameters integer(${ik}$), parameter :: nsweep = 30_${ik}$ ! Local Scalars complex(${ck}$) :: aapq, ompq real(${ck}$) :: aapp, aapp0, aapq1, aaqq, apoaq, aqoap, big, bigtheta, cs, ctol, epsln, & mxaapq, mxsinj, rootbig, rooteps, rootsfmin, roottol, skl, sfmin, small, sn, t, temp1, & theta, thsign, tol integer(${ik}$) :: blskip, emptsw, i, ibr, ierr, igl, ijblsk, ir1, iswrot, jbc, jgl, kbl, & lkahead, mvl, n2, n34, n4, nbl, notrot, p, pskipped, q, rowskip, swband logical(lk) :: applv, goscale, lower, lquery, lsvec, noscale, rotok, rsvec, uctol, & upper ! Intrinsic Functions ! from lapack ! from lapack ! Executable Statements ! test the input arguments lsvec = stdlib_lsame( jobu, 'U' ) .or. stdlib_lsame( jobu, 'F' ) uctol = stdlib_lsame( jobu, 'C' ) rsvec = stdlib_lsame( jobv, 'V' ) .or. stdlib_lsame( jobv, 'J' ) applv = stdlib_lsame( jobv, 'A' ) upper = stdlib_lsame( joba, 'U' ) lower = stdlib_lsame( joba, 'L' ) lquery = ( lwork == -1_${ik}$ ) .or. ( lrwork == -1_${ik}$ ) if( .not.( upper .or. lower .or. stdlib_lsame( joba, 'G' ) ) ) then info = -1_${ik}$ else if( .not.( lsvec .or. uctol .or. stdlib_lsame( jobu, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( rsvec .or. applv .or. stdlib_lsame( jobv, 'N' ) ) ) then info = -3_${ik}$ else if( m<0_${ik}$ ) then info = -4_${ik}$ else if( ( n<0_${ik}$ ) .or. ( n>m ) ) then info = -5_${ik}$ else if( ldaj}|a(:,i)^* * a(:,j)| / (||a(:,i)||*||a(:,j)||) < ctol*eps ! where eps is the round-off and ctol is defined as follows: if( uctol ) then ! ... user controlled ctol = rwork( 1_${ik}$ ) else ! ... default if( lsvec .or. rsvec .or. applv ) then ctol = sqrt( real( m,KIND=${ck}$) ) else ctol = real( m,KIND=${ck}$) end if end if ! ... and the machine dependent parameters are ! [!] (make sure that stdlib${ii}$_dlamch() works properly on the target machine.) epsln = stdlib${ii}$_${c2ri(ci)}$lamch( 'EPSILON' ) rooteps = sqrt( epsln ) sfmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFEMINIMUM' ) rootsfmin = sqrt( sfmin ) small = sfmin / epsln big = stdlib${ii}$_${c2ri(ci)}$lamch( 'OVERFLOW' ) ! big = one / sfmin rootbig = one / rootsfmin ! large = big / sqrt( real( m*n,KIND=${ck}$) ) bigtheta = one / rooteps tol = ctol*epsln roottol = sqrt( tol ) if( real( m,KIND=${ck}$)*epsln>=one ) then info = -4_${ik}$ call stdlib${ii}$_xerbla( 'ZGESVJ', -info ) return end if ! initialize the right singular vector matrix. if( rsvec ) then mvl = n call stdlib${ii}$_${ci}$laset( 'A', mvl, n, czero, cone, v, ldv ) else if( applv ) then mvl = mv end if rsvec = rsvec .or. applv ! initialize sva( 1:n ) = ( ||a e_i||_2, i = 1:n ) ! (!) if necessary, scale a to protect the largest singular value ! from overflow. it is possible that saving the largest singular ! value destroys the information about the small ones. ! this initial scaling is almost minimal in the sense that the ! goal is to make sure that no column norm overflows, and that ! sqrt(n)*max_i sva(i) does not overflow. if infinite entries ! in a are detected, the procedure returns with info=-6. skl = one / sqrt( real( m,KIND=${ck}$)*real( n,KIND=${ck}$) ) noscale = .true. goscale = .true. if( lower ) then ! the input matrix is m-by-n lower triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_${ci}$lassq( m-p+1, a( p, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'ZGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else if( upper ) then ! the input matrix is m-by-n upper triangular (trapezoidal) do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_${ci}$lassq( p, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'ZGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do else ! the input matrix is m-by-n general dense do p = 1, n aapp = zero aaqq = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, aapp, aaqq ) if( aapp>big ) then info = -6_${ik}$ call stdlib${ii}$_xerbla( 'ZGESVJ', -info ) return end if aaqq = sqrt( aaqq ) if( ( aapp<( big / aaqq ) ) .and. noscale ) then sva( p ) = aapp*aaqq else noscale = .false. sva( p ) = aapp*( aaqq*skl ) if( goscale ) then goscale = .false. do q = 1, p - 1 sva( q ) = sva( q )*skl end do end if end if end do end if if( noscale )skl = one ! move the smaller part of the spectrum from the underflow threshold ! (!) start by determining the position of the nonzero entries of the ! array sva() relative to ( sfmin, big ). aapp = zero aaqq = big do p = 1, n if( sva( p )/=zero )aaqq = min( aaqq, sva( p ) ) aapp = max( aapp, sva( p ) ) end do ! #:) quick return for zero matrix if( aapp==zero ) then if( lsvec )call stdlib${ii}$_${ci}$laset( 'G', m, n, czero, cone, a, lda ) rwork( 1_${ik}$ ) = one rwork( 2_${ik}$ ) = zero rwork( 3_${ik}$ ) = zero rwork( 4_${ik}$ ) = zero rwork( 5_${ik}$ ) = zero rwork( 6_${ik}$ ) = zero return end if ! #:) quick return for one-column matrix if( n==1_${ik}$ ) then if( lsvec )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, sva( 1_${ik}$ ), skl, m, 1_${ik}$,a( 1_${ik}$, 1_${ik}$ ), lda, ierr ) rwork( 1_${ik}$ ) = one / skl if( sva( 1_${ik}$ )>=sfmin ) then rwork( 2_${ik}$ ) = one else rwork( 2_${ik}$ ) = zero end if rwork( 3_${ik}$ ) = zero rwork( 4_${ik}$ ) = zero rwork( 5_${ik}$ ) = zero rwork( 6_${ik}$ ) = zero return end if ! protect small singular values from underflow, and try to ! avoid underflows/overflows in computing jacobi rotations. sn = sqrt( sfmin / epsln ) temp1 = sqrt( big / real( n,KIND=${ck}$) ) if( ( aapp<=sn ) .or. ( aaqq>=temp1 ) .or.( ( sn<=aaqq ) .and. ( aapp<=temp1 ) ) ) & then temp1 = min( big, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp<=temp1 ) ) then temp1 = min( sn / aaqq, big / (aapp*sqrt( real(n,KIND=${ck}$)) ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq>=sn ) .and. ( aapp>=temp1 ) ) then temp1 = max( sn / aaqq, temp1 / aapp ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else if( ( aaqq<=sn ) .and. ( aapp>=temp1 ) ) then temp1 = min( sn / aaqq, big / ( sqrt( real( n,KIND=${ck}$) )*aapp ) ) ! aaqq = aaqq*temp1 ! aapp = aapp*temp1 else temp1 = one end if ! scale, if necessary if( temp1/=one ) then call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, temp1, n, 1_${ik}$, sva, n, ierr ) end if skl = temp1*skl if( skl/=one ) then call stdlib${ii}$_${ci}$lascl( joba, 0_${ik}$, 0_${ik}$, one, skl, m, n, a, lda, ierr ) skl = one / skl end if ! row-cyclic jacobi svd algorithm with column pivoting emptsw = ( n*( n-1 ) ) / 2_${ik}$ notrot = 0_${ik}$ do q = 1, n cwork( q ) = cone end do swband = 3_${ik}$ ! [tp] swband is a tuning parameter [tp]. it is meaningful and effective ! if stdlib${ii}$_${ci}$gesvj is used as a computational routine in the preconditioned ! jacobi svd algorithm stdlib${ii}$_${ci}$gejsv. for sweeps i=1:swband the procedure ! works on pivots inside a band-like region around the diagonal. ! the boundaries are determined dynamically, based on the number of ! pivots above a threshold. kbl = min( 8_${ik}$, n ) ! [tp] kbl is a tuning parameter that defines the tile size in the ! tiling of the p-q loops of pivot pairs. in general, an optimal ! value of kbl depends on the matrix dimensions and on the ! parameters of the computer's memory. nbl = n / kbl if( ( nbl*kbl )/=n )nbl = nbl + 1_${ik}$ blskip = kbl**2_${ik}$ ! [tp] blkskip is a tuning parameter that depends on swband and kbl. rowskip = min( 5_${ik}$, kbl ) ! [tp] rowskip is a tuning parameter. lkahead = 1_${ik}$ ! [tp] lkahead is a tuning parameter. ! quasi block transformations, using the lower (upper) triangular ! structure of the input matrix. the quasi-block-cycling usually ! invokes cubic convergence. big part of this cycle is done inside ! canonical subspaces of dimensions less than m. if( ( lower .or. upper ) .and. ( n>max( 64_${ik}$, 4_${ik}$*kbl ) ) ) then ! [tp] the number of partition levels and the actual partition are ! tuning parameters. n4 = n / 4_${ik}$ n2 = n / 2_${ik}$ n34 = 3_${ik}$*n4 if( applv ) then q = 0_${ik}$ else q = 1_${ik}$ end if if( lower ) then ! this works very well on lower triangular matrices, in particular ! in the framework of the preconditioned jacobi svd (xgejsv). ! the idea is simple: ! [+ 0 0 0] note that jacobi transformations of [0 0] ! [+ + 0 0] [0 0] ! [+ + x 0] actually work on [x 0] [x 0] ! [+ + x x] [x x]. [x x] call stdlib${ii}$_${ci}$gsvj0( jobv, m-n34, n-n34, a( n34+1, n34+1 ), lda,cwork( n34+1 ), & sva( n34+1 ), mvl,v( n34*q+1, n34+1 ), ldv, epsln, sfmin, tol,2_${ik}$, cwork( n+1 ), & lwork-n, ierr ) call stdlib${ii}$_${ci}$gsvj0( jobv, m-n2, n34-n2, a( n2+1, n2+1 ), lda,cwork( n2+1 ), sva( & n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 2_${ik}$,cwork( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_${ci}$gsvj1( jobv, m-n2, n-n2, n4, a( n2+1, n2+1 ), lda,cwork( n2+1 ), & sva( n2+1 ), mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,cwork( n+1 ), & lwork-n, ierr ) call stdlib${ii}$_${ci}$gsvj0( jobv, m-n4, n2-n4, a( n4+1, n4+1 ), lda,cwork( n4+1 ), sva( & n4+1 ), mvl,v( n4*q+1, n4+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,cwork( n+1 ), lwork-n, & ierr ) call stdlib${ii}$_${ci}$gsvj0( jobv, m, n4, a, lda, cwork, sva, mvl, v, ldv,epsln, sfmin, & tol, 1_${ik}$, cwork( n+1 ), lwork-n,ierr ) call stdlib${ii}$_${ci}$gsvj1( jobv, m, n2, n4, a, lda, cwork, sva, mvl, v,ldv, epsln, & sfmin, tol, 1_${ik}$, cwork( n+1 ),lwork-n, ierr ) else if( upper ) then call stdlib${ii}$_${ci}$gsvj0( jobv, n4, n4, a, lda, cwork, sva, mvl, v, ldv,epsln, sfmin, & tol, 2_${ik}$, cwork( n+1 ), lwork-n,ierr ) call stdlib${ii}$_${ci}$gsvj0( jobv, n2, n4, a( 1_${ik}$, n4+1 ), lda, cwork( n4+1 ),sva( n4+1 ), & mvl, v( n4*q+1, n4+1 ), ldv,epsln, sfmin, tol, 1_${ik}$, cwork( n+1 ), lwork-n,ierr ) call stdlib${ii}$_${ci}$gsvj1( jobv, n2, n2, n4, a, lda, cwork, sva, mvl, v,ldv, epsln, & sfmin, tol, 1_${ik}$, cwork( n+1 ),lwork-n, ierr ) call stdlib${ii}$_${ci}$gsvj0( jobv, n2+n4, n4, a( 1_${ik}$, n2+1 ), lda,cwork( n2+1 ), sva( n2+1 )& , mvl,v( n2*q+1, n2+1 ), ldv, epsln, sfmin, tol, 1_${ik}$,cwork( n+1 ), lwork-n, ierr ) end if end if ! .. row-cyclic pivot strategy with de rijk's pivoting .. loop_1993: do i = 1, nsweep ! .. go go go ... mxaapq = zero mxsinj = zero iswrot = 0_${ik}$ notrot = 0_${ik}$ pskipped = 0_${ik}$ ! each sweep is unrolled using kbl-by-kbl tiles over the pivot pairs ! 1 <= p < q <= n. this is the first step toward a blocked implementation ! of the rotations. new implementation, based on block transformations, ! is under development. loop_2000: do ibr = 1, nbl igl = ( ibr-1 )*kbl + 1_${ik}$ loop_1002: do ir1 = 0, min( lkahead, nbl-ibr ) igl = igl + ir1*kbl loop_2001: do p = igl, min( igl+kbl-1, n-1 ) ! .. de rijk's pivoting q = stdlib${ii}$_i${c2ri(ci)}$amax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then call stdlib${ii}$_${ci}$swap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_${ci}$swap( mvl, v( 1_${ik}$, p ), 1_${ik}$,v( 1_${ik}$, q ), 1_${ik}$ ) temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 aapq = cwork(p) cwork(p) = cwork(q) cwork(q) = aapq end if if( ir1==0_${ik}$ ) then ! column norms are periodically updated by explicit ! norm computation. ! [!] caveat: ! unfortunately, some blas implementations compute stdlib${ii}$_${c2ri(ci)}$znrm2(m,a(1,p),1) ! as sqrt(s=stdlib${ii}$_zdotc(m,a(1,p),1,a(1,p),1)), which may cause the result to ! overflow for ||a(:,p)||_2 > sqrt(overflow_threshold), and to ! underflow for ||a(:,p)||_2 < sqrt(underflow_threshold). ! hence, stdlib${ii}$_${c2ri(ci)}$znrm2 cannot be trusted, not even in the case when ! the true norm is far from the under(over)flow boundaries. ! if properly implemented stdlib${ii}$_dcnrm2 is available, the if-then-else-end if ! below should be replaced with "aapp = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a(1,p), 1 )". if( ( sva( p )rootsfmin ) ) then sva( p ) = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else temp1 = zero aapp = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, temp1, aapp ) sva( p ) = temp1*sqrt( aapp ) end if aapp = sva( p ) else aapp = sva( p ) end if if( aapp>zero ) then pskipped = 0_${ik}$ loop_2002: do q = p + 1, min( igl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp if( aaqq>=one ) then rotok = ( small*aapp )<=aaqq if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_${ci}$dotc( m, cwork(n+1), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else rotok = aapp<=( aaqq / small ) if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aapp ) / aaqq else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, q ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_${ci}$dotc( m, a(1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg( cwork(p) ) * cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) ! Rotate ! [rtd] rotated = rotated + one if( ir1==0_${ik}$ ) then notrot = 0_${ik}$ pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ end if if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/aapq1 if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_${ci}$rot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if ( rsvec ) then call stdlib${ii}$_${ci}$rot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_${ci}$rot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if ( rsvec ) then call stdlib${ii}$_${ci}$rot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if cwork(p) = -cwork(q) * ompq else ! .. have to use modified gram-schmidt like transformation call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one, m,1_${ik}$, cwork(n+1), & lda,ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) call stdlib${ii}$_${ci}$axpy( m, -aapq, cwork(n+1), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq, m,1_${ik}$, a( 1_${ik}$, q ), & lda, ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! recompute sva(q), sva(p). if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, q ), 1_${ik}$ ) else t = zero aaqq = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if else ! a(:,p) and a(:,q) already numerically orthogonal if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ end if else ! a(:,q) is zero column if( ir1==0_${ik}$ )notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then if( ir1==0_${ik}$ )aapp = -aapp notrot = 0_${ik}$ go to 2103 end if end do loop_2002 ! end q-loop 2103 continue ! bailed out of q-loop sva( p ) = aapp else sva( p ) = aapp if( ( ir1==0_${ik}$ ) .and. ( aapp==zero ) )notrot = notrot + min( igl+kbl-1, & n ) - p end if end do loop_2001 ! end of the p-loop ! end of doing the block ( ibr, ibr ) end do loop_1002 ! end of ir1-loop ! ... go to the off diagonal blocks igl = ( ibr-1 )*kbl + 1_${ik}$ loop_2010: do jbc = ibr + 1, nbl jgl = ( jbc-1 )*kbl + 1_${ik}$ ! doing the block at ( ibr, jbc ) ijblsk = 0_${ik}$ loop_2100: do p = igl, min( igl+kbl-1, n ) aapp = sva( p ) if( aapp>zero ) then pskipped = 0_${ik}$ loop_2200: do q = jgl, min( jgl+kbl-1, n ) aaqq = sva( q ) if( aaqq>zero ) then aapp0 = aapp ! M X 2 Jacobi Svd ! safe gram matrix computation if( aaqq>=one ) then if( aapp>=aaqq ) then rotok = ( small*aapp )<=aaqq else rotok = ( small*aaqq )<=aapp end if if( aapp<( big / aaqq ) ) then aapq = ( stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq ) / aapp else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp,one, m, 1_${ik}$,cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_${ci}$dotc( m, cwork(n+1), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / & aaqq end if else if( aapp>=aaqq ) then rotok = aapp<=( aaqq / small ) else rotok = aaqq<=( aapp / small ) end if if( aapp>( small / aaqq ) ) then aapq = ( stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,a( 1_${ik}$, q ), 1_${ik}$ ) / max(& aaqq,aapp) )/ min(aaqq,aapp) else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, q ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq,one, m, 1_${ik}$,cwork(n+1), & lda, ierr ) aapq = stdlib${ii}$_${ci}$dotc( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) / & aapp end if end if ! aapq = aapq * conjg(cwork(p))*cwork(q) aapq1 = -abs(aapq) mxaapq = max( mxaapq, -aapq1 ) ! to rotate or not to rotate, that is the question ... if( abs( aapq1 )>tol ) then ompq = aapq / abs(aapq) notrot = 0_${ik}$ ! [rtd] rotated = rotated + 1 pskipped = 0_${ik}$ iswrot = iswrot + 1_${ik}$ if( rotok ) then aqoap = aaqq / aapp apoaq = aapp / aaqq theta = -half*abs( aqoap-apoaq )/ aapq1 if( aaqq>aapp0 )theta = -theta if( abs( theta )>bigtheta ) then t = half / theta cs = one call stdlib${ii}$_${ci}$rot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *t ) if( rsvec ) then call stdlib${ii}$_${ci}$rot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*t ) end if sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) mxsinj = max( mxsinj, abs( t ) ) else ! Choose Correct Signum For Theta And Rotate thsign = -sign( one, aapq1 ) if( aaqq>aapp0 )thsign = -thsign t = one / ( theta+thsign*sqrt( one+theta*theta ) ) cs = sqrt( one / ( one+t*t ) ) sn = t*cs mxsinj = max( mxsinj, abs( sn ) ) sva( q ) = aaqq*sqrt( max( zero,one+t*apoaq*aapq1 ) ) aapp = aapp*sqrt( max( zero,one-t*aqoap*aapq1 ) ) call stdlib${ii}$_${ci}$rot( m, a(1_${ik}$,p), 1_${ik}$, a(1_${ik}$,q), 1_${ik}$,cs, conjg(ompq)& *sn ) if( rsvec ) then call stdlib${ii}$_${ci}$rot( mvl, v(1_${ik}$,p), 1_${ik}$,v(1_${ik}$,q), 1_${ik}$, cs, & conjg(ompq)*sn ) end if end if cwork(p) = -cwork(q) * ompq else ! .. have to use modified gram-schmidt like transformation if( aapp>aaqq ) then call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, p ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, cwork(n+1)& ,lda,ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) call stdlib${ii}$_${ci}$axpy( m, -aapq, cwork(n+1),1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aaqq,m, 1_${ik}$, a( 1_${ik}$, q ),& lda,ierr ) sva( q ) = aaqq*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) else call stdlib${ii}$_${ci}$copy( m, a( 1_${ik}$, q ), 1_${ik}$,cwork(n+1), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aaqq, one,m, 1_${ik}$, cwork(n+1)& ,lda,ierr ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, aapp, one,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) call stdlib${ii}$_${ci}$axpy( m, -conjg(aapq),cwork(n+1), 1_${ik}$, a( 1_${ik}$, & p ), 1_${ik}$ ) call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, one, aapp,m, 1_${ik}$, a( 1_${ik}$, p ),& lda,ierr ) sva( p ) = aapp*sqrt( max( zero,one-aapq1*aapq1 ) ) mxsinj = max( mxsinj, sfmin ) end if end if ! end if rotok then ... else ! in the case of cancellation in updating sva(q), sva(p) ! .. recompute sva(q), sva(p) if( ( sva( q ) / aaqq )**2_${ik}$<=rooteps )then if( ( aaqqrootsfmin ) ) then sva( q ) = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, q ), 1_${ik}$) else t = zero aaqq = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, q ), 1_${ik}$, t,aaqq ) sva( q ) = t*sqrt( aaqq ) end if end if if( ( aapp / aapp0 )**2_${ik}$<=rooteps ) then if( ( aapprootsfmin ) ) then aapp = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, p ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, p ), 1_${ik}$, t,aapp ) aapp = t*sqrt( aapp ) end if sva( p ) = aapp end if ! end of ok rotation else notrot = notrot + 1_${ik}$ ! [rtd] skipped = skipped + 1 pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if else notrot = notrot + 1_${ik}$ pskipped = pskipped + 1_${ik}$ ijblsk = ijblsk + 1_${ik}$ end if if( ( i<=swband ) .and. ( ijblsk>=blskip ) )then sva( p ) = aapp notrot = 0_${ik}$ go to 2011 end if if( ( i<=swband ) .and.( pskipped>rowskip ) ) then aapp = -aapp notrot = 0_${ik}$ go to 2203 end if end do loop_2200 ! end of the q-loop 2203 continue sva( p ) = aapp else if( aapp==zero )notrot = notrot +min( jgl+kbl-1, n ) - jgl + 1_${ik}$ if( aapprootsfmin ) )then sva( n ) = stdlib${ii}$_${c2ri(ci)}$znrm2( m, a( 1_${ik}$, n ), 1_${ik}$ ) else t = zero aapp = one call stdlib${ii}$_${ci}$lassq( m, a( 1_${ik}$, n ), 1_${ik}$, t, aapp ) sva( n ) = t*sqrt( aapp ) end if ! additional steering devices if( ( iswband+1 ) .and. ( mxaapq=emptsw )go to 1994 end do loop_1993 ! end i=1:nsweep loop ! #:( reaching this point means that the procedure has not converged. info = nsweep - 1_${ik}$ go to 1995 1994 continue ! #:) reaching this point means numerical convergence after the i-th ! sweep. info = 0_${ik}$ ! #:) info = 0 confirms successful iterations. 1995 continue ! sort the singular values and find how many are above ! the underflow threshold. n2 = 0_${ik}$ n4 = 0_${ik}$ do p = 1, n - 1 q = stdlib${ii}$_i${c2ri(ci)}$amax( n-p+1, sva( p ), 1_${ik}$ ) + p - 1_${ik}$ if( p/=q ) then temp1 = sva( p ) sva( p ) = sva( q ) sva( q ) = temp1 call stdlib${ii}$_${ci}$swap( m, a( 1_${ik}$, p ), 1_${ik}$, a( 1_${ik}$, q ), 1_${ik}$ ) if( rsvec )call stdlib${ii}$_${ci}$swap( mvl, v( 1_${ik}$, p ), 1_${ik}$, v( 1_${ik}$, q ), 1_${ik}$ ) end if if( sva( p )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( p )*skl>sfmin )n2 = n2 + 1_${ik}$ end if end do if( sva( n )/=zero ) then n4 = n4 + 1_${ik}$ if( sva( n )*skl>sfmin )n2 = n2 + 1_${ik}$ end if ! normalize the left singular vectors. if( lsvec .or. uctol ) then do p = 1, n4 ! call stdlib${ii}$_${ci}$dscal( m, one / sva( p ), a( 1, p ), 1 ) call stdlib${ii}$_${ci}$lascl( 'G',0_${ik}$,0_${ik}$, sva(p), one, m, 1_${ik}$, a(1_${ik}$,p), m, ierr ) end do end if ! scale the product of jacobi rotations. if( rsvec ) then do p = 1, n temp1 = one / stdlib${ii}$_${c2ri(ci)}$znrm2( mvl, v( 1_${ik}$, p ), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( mvl, temp1, v( 1_${ik}$, p ), 1_${ik}$ ) end do end if ! undo scaling, if necessary (and possible). if( ( ( skl>one ) .and. ( sva( 1_${ik}$ )<( big / skl ) ) ).or. ( ( skl( sfmin / skl ) ) ) ) then do p = 1, n sva( p ) = skl*sva( p ) end do skl = one end if rwork( 1_${ik}$ ) = skl ! the singular values of a are skl*sva(1:n). if skl/=one ! then some of the singular values may overflow or underflow and ! the spectrum is given in this factored representation. rwork( 2_${ik}$ ) = real( n4,KIND=${ck}$) ! n4 is the number of computed nonzero singular values of a. rwork( 3_${ik}$ ) = real( n2,KIND=${ck}$) ! n2 is the number of singular values of a greater than sfmin. ! if n2=4_${ik}$ ) then if( kl<0_${ik}$ .or. kl>max( m-1, 0_${ik}$ ) ) then info = -2_${ik}$ else if( ku<0_${ik}$ .or. ku>max( n-1, 0_${ik}$ ) .or.( ( itype==4_${ik}$ .or. itype==5_${ik}$ ) .and. kl/=ku ) & )then info = -3_${ik}$ else if( ( itype==4_${ik}$ .and. ldaabs( ctoc ) .and. ctoc/=zero ) then mul = smlnum done = .false. cfromc = cfrom1 else if( abs( cto1 )>abs( cfromc ) ) then mul = bignum done = .false. ctoc = cto1 else mul = ctoc / cfromc done = .true. end if end if if( itype==0_${ik}$ ) then ! full matrix do j = 1, n do i = 1, m a( i, j ) = a( i, j )*mul end do end do else if( itype==1_${ik}$ ) then ! lower triangular matrix do j = 1, n do i = j, m a( i, j ) = a( i, j )*mul end do end do else if( itype==2_${ik}$ ) then ! upper triangular matrix do j = 1, n do i = 1, min( j, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==3_${ik}$ ) then ! upper hessenberg matrix do j = 1, n do i = 1, min( j+1, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==4_${ik}$ ) then ! lower half of a symmetric band matrix k3 = kl + 1_${ik}$ k4 = n + 1_${ik}$ do j = 1, n do i = 1, min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do else if( itype==5_${ik}$ ) then ! upper half of a symmetric band matrix k1 = ku + 2_${ik}$ k3 = ku + 1_${ik}$ do j = 1, n do i = max( k1-j, 1 ), k3 a( i, j ) = a( i, j )*mul end do end do else if( itype==6_${ik}$ ) then ! band matrix k1 = kl + ku + 2_${ik}$ k2 = kl + 1_${ik}$ k3 = 2_${ik}$*kl + ku + 1_${ik}$ k4 = kl + ku + 1_${ik}$ + m do j = 1, n do i = max( k1-j, k2 ), min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do end if if( .not.done )go to 10 return end subroutine stdlib${ii}$_slascl pure module subroutine stdlib${ii}$_dlascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) !! DLASCL multiplies the M by N real matrix A by the real scalar !! CTO/CFROM. This is done without over/underflow as long as the final !! result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that !! A may be full, upper triangular, lower triangular, upper Hessenberg, !! or banded. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: zero, half, one ! Scalar Arguments character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, lda, m, n real(dp), intent(in) :: cfrom, cto ! Array Arguments real(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: done integer(${ik}$) :: i, itype, j, k1, k2, k3, k4 real(dp) :: bignum, cfrom1, cfromc, cto1, ctoc, mul, smlnum ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ if( stdlib_lsame( type, 'G' ) ) then itype = 0_${ik}$ else if( stdlib_lsame( type, 'L' ) ) then itype = 1_${ik}$ else if( stdlib_lsame( type, 'U' ) ) then itype = 2_${ik}$ else if( stdlib_lsame( type, 'H' ) ) then itype = 3_${ik}$ else if( stdlib_lsame( type, 'B' ) ) then itype = 4_${ik}$ else if( stdlib_lsame( type, 'Q' ) ) then itype = 5_${ik}$ else if( stdlib_lsame( type, 'Z' ) ) then itype = 6_${ik}$ else itype = -1_${ik}$ end if if( itype==-1_${ik}$ ) then info = -1_${ik}$ else if( cfrom==zero .or. stdlib${ii}$_disnan(cfrom) ) then info = -4_${ik}$ else if( stdlib${ii}$_disnan(cto) ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -6_${ik}$ else if( n<0_${ik}$ .or. ( itype==4_${ik}$ .and. n/=m ) .or.( itype==5_${ik}$ .and. n/=m ) ) then info = -7_${ik}$ else if( itype<=3_${ik}$ .and. lda=4_${ik}$ ) then if( kl<0_${ik}$ .or. kl>max( m-1, 0_${ik}$ ) ) then info = -2_${ik}$ else if( ku<0_${ik}$ .or. ku>max( n-1, 0_${ik}$ ) .or.( ( itype==4_${ik}$ .or. itype==5_${ik}$ ) .and. kl/=ku ) & )then info = -3_${ik}$ else if( ( itype==4_${ik}$ .and. ldaabs( ctoc ) .and. ctoc/=zero ) then mul = smlnum done = .false. cfromc = cfrom1 else if( abs( cto1 )>abs( cfromc ) ) then mul = bignum done = .false. ctoc = cto1 else mul = ctoc / cfromc done = .true. end if end if if( itype==0_${ik}$ ) then ! full matrix do j = 1, n do i = 1, m a( i, j ) = a( i, j )*mul end do end do else if( itype==1_${ik}$ ) then ! lower triangular matrix do j = 1, n do i = j, m a( i, j ) = a( i, j )*mul end do end do else if( itype==2_${ik}$ ) then ! upper triangular matrix do j = 1, n do i = 1, min( j, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==3_${ik}$ ) then ! upper hessenberg matrix do j = 1, n do i = 1, min( j+1, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==4_${ik}$ ) then ! lower half of a symmetric band matrix k3 = kl + 1_${ik}$ k4 = n + 1_${ik}$ do j = 1, n do i = 1, min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do else if( itype==5_${ik}$ ) then ! upper half of a symmetric band matrix k1 = ku + 2_${ik}$ k3 = ku + 1_${ik}$ do j = 1, n do i = max( k1-j, 1 ), k3 a( i, j ) = a( i, j )*mul end do end do else if( itype==6_${ik}$ ) then ! band matrix k1 = kl + ku + 2_${ik}$ k2 = kl + 1_${ik}$ k3 = 2_${ik}$*kl + ku + 1_${ik}$ k4 = kl + ku + 1_${ik}$ + m do j = 1, n do i = max( k1-j, k2 ), min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do end if if( .not.done )go to 10 return end subroutine stdlib${ii}$_dlascl #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) !! DLASCL: multiplies the M by N real matrix A by the real scalar !! CTO/CFROM. This is done without over/underflow as long as the final !! result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that !! A may be full, upper triangular, lower triangular, upper Hessenberg, !! or banded. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: zero, half, one ! Scalar Arguments character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, lda, m, n real(${rk}$), intent(in) :: cfrom, cto ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: done integer(${ik}$) :: i, itype, j, k1, k2, k3, k4 real(${rk}$) :: bignum, cfrom1, cfromc, cto1, ctoc, mul, smlnum ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ if( stdlib_lsame( type, 'G' ) ) then itype = 0_${ik}$ else if( stdlib_lsame( type, 'L' ) ) then itype = 1_${ik}$ else if( stdlib_lsame( type, 'U' ) ) then itype = 2_${ik}$ else if( stdlib_lsame( type, 'H' ) ) then itype = 3_${ik}$ else if( stdlib_lsame( type, 'B' ) ) then itype = 4_${ik}$ else if( stdlib_lsame( type, 'Q' ) ) then itype = 5_${ik}$ else if( stdlib_lsame( type, 'Z' ) ) then itype = 6_${ik}$ else itype = -1_${ik}$ end if if( itype==-1_${ik}$ ) then info = -1_${ik}$ else if( cfrom==zero .or. stdlib${ii}$_${ri}$isnan(cfrom) ) then info = -4_${ik}$ else if( stdlib${ii}$_${ri}$isnan(cto) ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -6_${ik}$ else if( n<0_${ik}$ .or. ( itype==4_${ik}$ .and. n/=m ) .or.( itype==5_${ik}$ .and. n/=m ) ) then info = -7_${ik}$ else if( itype<=3_${ik}$ .and. lda=4_${ik}$ ) then if( kl<0_${ik}$ .or. kl>max( m-1, 0_${ik}$ ) ) then info = -2_${ik}$ else if( ku<0_${ik}$ .or. ku>max( n-1, 0_${ik}$ ) .or.( ( itype==4_${ik}$ .or. itype==5_${ik}$ ) .and. kl/=ku ) & )then info = -3_${ik}$ else if( ( itype==4_${ik}$ .and. ldaabs( ctoc ) .and. ctoc/=zero ) then mul = smlnum done = .false. cfromc = cfrom1 else if( abs( cto1 )>abs( cfromc ) ) then mul = bignum done = .false. ctoc = cto1 else mul = ctoc / cfromc done = .true. end if end if if( itype==0_${ik}$ ) then ! full matrix do j = 1, n do i = 1, m a( i, j ) = a( i, j )*mul end do end do else if( itype==1_${ik}$ ) then ! lower triangular matrix do j = 1, n do i = j, m a( i, j ) = a( i, j )*mul end do end do else if( itype==2_${ik}$ ) then ! upper triangular matrix do j = 1, n do i = 1, min( j, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==3_${ik}$ ) then ! upper hessenberg matrix do j = 1, n do i = 1, min( j+1, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==4_${ik}$ ) then ! lower half of a symmetric band matrix k3 = kl + 1_${ik}$ k4 = n + 1_${ik}$ do j = 1, n do i = 1, min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do else if( itype==5_${ik}$ ) then ! upper half of a symmetric band matrix k1 = ku + 2_${ik}$ k3 = ku + 1_${ik}$ do j = 1, n do i = max( k1-j, 1 ), k3 a( i, j ) = a( i, j )*mul end do end do else if( itype==6_${ik}$ ) then ! band matrix k1 = kl + ku + 2_${ik}$ k2 = kl + 1_${ik}$ k3 = 2_${ik}$*kl + ku + 1_${ik}$ k4 = kl + ku + 1_${ik}$ + m do j = 1, n do i = max( k1-j, k2 ), min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do end if if( .not.done )go to 10 return end subroutine stdlib${ii}$_${ri}$lascl #:endif #:endfor pure module subroutine stdlib${ii}$_clascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) !! CLASCL multiplies the M by N complex matrix A by the real scalar !! CTO/CFROM. This is done without over/underflow as long as the final !! result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that !! A may be full, upper triangular, lower triangular, upper Hessenberg, !! or banded. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: zero, half, one ! Scalar Arguments character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, lda, m, n real(sp), intent(in) :: cfrom, cto ! Array Arguments complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: done integer(${ik}$) :: i, itype, j, k1, k2, k3, k4 real(sp) :: bignum, cfrom1, cfromc, cto1, ctoc, mul, smlnum ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ if( stdlib_lsame( type, 'G' ) ) then itype = 0_${ik}$ else if( stdlib_lsame( type, 'L' ) ) then itype = 1_${ik}$ else if( stdlib_lsame( type, 'U' ) ) then itype = 2_${ik}$ else if( stdlib_lsame( type, 'H' ) ) then itype = 3_${ik}$ else if( stdlib_lsame( type, 'B' ) ) then itype = 4_${ik}$ else if( stdlib_lsame( type, 'Q' ) ) then itype = 5_${ik}$ else if( stdlib_lsame( type, 'Z' ) ) then itype = 6_${ik}$ else itype = -1_${ik}$ end if if( itype==-1_${ik}$ ) then info = -1_${ik}$ else if( cfrom==zero .or. stdlib${ii}$_sisnan(cfrom) ) then info = -4_${ik}$ else if( stdlib${ii}$_sisnan(cto) ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -6_${ik}$ else if( n<0_${ik}$ .or. ( itype==4_${ik}$ .and. n/=m ) .or.( itype==5_${ik}$ .and. n/=m ) ) then info = -7_${ik}$ else if( itype<=3_${ik}$ .and. lda=4_${ik}$ ) then if( kl<0_${ik}$ .or. kl>max( m-1, 0_${ik}$ ) ) then info = -2_${ik}$ else if( ku<0_${ik}$ .or. ku>max( n-1, 0_${ik}$ ) .or.( ( itype==4_${ik}$ .or. itype==5_${ik}$ ) .and. kl/=ku ) & )then info = -3_${ik}$ else if( ( itype==4_${ik}$ .and. ldaabs( ctoc ) .and. ctoc/=zero ) then mul = smlnum done = .false. cfromc = cfrom1 else if( abs( cto1 )>abs( cfromc ) ) then mul = bignum done = .false. ctoc = cto1 else mul = ctoc / cfromc done = .true. end if end if if( itype==0_${ik}$ ) then ! full matrix do j = 1, n do i = 1, m a( i, j ) = a( i, j )*mul end do end do else if( itype==1_${ik}$ ) then ! lower triangular matrix do j = 1, n do i = j, m a( i, j ) = a( i, j )*mul end do end do else if( itype==2_${ik}$ ) then ! upper triangular matrix do j = 1, n do i = 1, min( j, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==3_${ik}$ ) then ! upper hessenberg matrix do j = 1, n do i = 1, min( j+1, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==4_${ik}$ ) then ! lower chalf of a symmetric band matrix k3 = kl + 1_${ik}$ k4 = n + 1_${ik}$ do j = 1, n do i = 1, min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do else if( itype==5_${ik}$ ) then ! upper chalf of a symmetric band matrix k1 = ku + 2_${ik}$ k3 = ku + 1_${ik}$ do j = 1, n do i = max( k1-j, 1 ), k3 a( i, j ) = a( i, j )*mul end do end do else if( itype==6_${ik}$ ) then ! band matrix k1 = kl + ku + 2_${ik}$ k2 = kl + 1_${ik}$ k3 = 2_${ik}$*kl + ku + 1_${ik}$ k4 = kl + ku + 1_${ik}$ + m do j = 1, n do i = max( k1-j, k2 ), min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do end if if( .not.done )go to 10 return end subroutine stdlib${ii}$_clascl pure module subroutine stdlib${ii}$_zlascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) !! ZLASCL multiplies the M by N complex matrix A by the real scalar !! CTO/CFROM. This is done without over/underflow as long as the final !! result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that !! A may be full, upper triangular, lower triangular, upper Hessenberg, !! or banded. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: zero, half, one ! Scalar Arguments character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, lda, m, n real(dp), intent(in) :: cfrom, cto ! Array Arguments complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: done integer(${ik}$) :: i, itype, j, k1, k2, k3, k4 real(dp) :: bignum, cfrom1, cfromc, cto1, ctoc, mul, smlnum ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ if( stdlib_lsame( type, 'G' ) ) then itype = 0_${ik}$ else if( stdlib_lsame( type, 'L' ) ) then itype = 1_${ik}$ else if( stdlib_lsame( type, 'U' ) ) then itype = 2_${ik}$ else if( stdlib_lsame( type, 'H' ) ) then itype = 3_${ik}$ else if( stdlib_lsame( type, 'B' ) ) then itype = 4_${ik}$ else if( stdlib_lsame( type, 'Q' ) ) then itype = 5_${ik}$ else if( stdlib_lsame( type, 'Z' ) ) then itype = 6_${ik}$ else itype = -1_${ik}$ end if if( itype==-1_${ik}$ ) then info = -1_${ik}$ else if( cfrom==zero .or. stdlib${ii}$_disnan(cfrom) ) then info = -4_${ik}$ else if( stdlib${ii}$_disnan(cto) ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -6_${ik}$ else if( n<0_${ik}$ .or. ( itype==4_${ik}$ .and. n/=m ) .or.( itype==5_${ik}$ .and. n/=m ) ) then info = -7_${ik}$ else if( itype<=3_${ik}$ .and. lda=4_${ik}$ ) then if( kl<0_${ik}$ .or. kl>max( m-1, 0_${ik}$ ) ) then info = -2_${ik}$ else if( ku<0_${ik}$ .or. ku>max( n-1, 0_${ik}$ ) .or.( ( itype==4_${ik}$ .or. itype==5_${ik}$ ) .and. kl/=ku ) & )then info = -3_${ik}$ else if( ( itype==4_${ik}$ .and. ldaabs( ctoc ) .and. ctoc/=zero ) then mul = smlnum done = .false. cfromc = cfrom1 else if( abs( cto1 )>abs( cfromc ) ) then mul = bignum done = .false. ctoc = cto1 else mul = ctoc / cfromc done = .true. end if end if if( itype==0_${ik}$ ) then ! full matrix do j = 1, n do i = 1, m a( i, j ) = a( i, j )*mul end do end do else if( itype==1_${ik}$ ) then ! lower triangular matrix do j = 1, n do i = j, m a( i, j ) = a( i, j )*mul end do end do else if( itype==2_${ik}$ ) then ! upper triangular matrix do j = 1, n do i = 1, min( j, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==3_${ik}$ ) then ! upper hessenberg matrix do j = 1, n do i = 1, min( j+1, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==4_${ik}$ ) then ! lower chalf of a symmetric band matrix k3 = kl + 1_${ik}$ k4 = n + 1_${ik}$ do j = 1, n do i = 1, min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do else if( itype==5_${ik}$ ) then ! upper chalf of a symmetric band matrix k1 = ku + 2_${ik}$ k3 = ku + 1_${ik}$ do j = 1, n do i = max( k1-j, 1 ), k3 a( i, j ) = a( i, j )*mul end do end do else if( itype==6_${ik}$ ) then ! band matrix k1 = kl + ku + 2_${ik}$ k2 = kl + 1_${ik}$ k3 = 2_${ik}$*kl + ku + 1_${ik}$ k4 = kl + ku + 1_${ik}$ + m do j = 1, n do i = max( k1-j, k2 ), min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do end if if( .not.done )go to 10 return end subroutine stdlib${ii}$_zlascl #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lascl( type, kl, ku, cfrom, cto, m, n, a, lda, info ) !! ZLASCL: multiplies the M by N complex matrix A by the real scalar !! CTO/CFROM. This is done without over/underflow as long as the final !! result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that !! A may be full, upper triangular, lower triangular, upper Hessenberg, !! or banded. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: zero, half, one ! Scalar Arguments character, intent(in) :: type integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kl, ku, lda, m, n real(${ck}$), intent(in) :: cfrom, cto ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: done integer(${ik}$) :: i, itype, j, k1, k2, k3, k4 real(${ck}$) :: bignum, cfrom1, cfromc, cto1, ctoc, mul, smlnum ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ if( stdlib_lsame( type, 'G' ) ) then itype = 0_${ik}$ else if( stdlib_lsame( type, 'L' ) ) then itype = 1_${ik}$ else if( stdlib_lsame( type, 'U' ) ) then itype = 2_${ik}$ else if( stdlib_lsame( type, 'H' ) ) then itype = 3_${ik}$ else if( stdlib_lsame( type, 'B' ) ) then itype = 4_${ik}$ else if( stdlib_lsame( type, 'Q' ) ) then itype = 5_${ik}$ else if( stdlib_lsame( type, 'Z' ) ) then itype = 6_${ik}$ else itype = -1_${ik}$ end if if( itype==-1_${ik}$ ) then info = -1_${ik}$ else if( cfrom==zero .or. stdlib${ii}$_${c2ri(ci)}$isnan(cfrom) ) then info = -4_${ik}$ else if( stdlib${ii}$_${c2ri(ci)}$isnan(cto) ) then info = -5_${ik}$ else if( m<0_${ik}$ ) then info = -6_${ik}$ else if( n<0_${ik}$ .or. ( itype==4_${ik}$ .and. n/=m ) .or.( itype==5_${ik}$ .and. n/=m ) ) then info = -7_${ik}$ else if( itype<=3_${ik}$ .and. lda=4_${ik}$ ) then if( kl<0_${ik}$ .or. kl>max( m-1, 0_${ik}$ ) ) then info = -2_${ik}$ else if( ku<0_${ik}$ .or. ku>max( n-1, 0_${ik}$ ) .or.( ( itype==4_${ik}$ .or. itype==5_${ik}$ ) .and. kl/=ku ) & )then info = -3_${ik}$ else if( ( itype==4_${ik}$ .and. ldaabs( ctoc ) .and. ctoc/=zero ) then mul = smlnum done = .false. cfromc = cfrom1 else if( abs( cto1 )>abs( cfromc ) ) then mul = bignum done = .false. ctoc = cto1 else mul = ctoc / cfromc done = .true. end if end if if( itype==0_${ik}$ ) then ! full matrix do j = 1, n do i = 1, m a( i, j ) = a( i, j )*mul end do end do else if( itype==1_${ik}$ ) then ! lower triangular matrix do j = 1, n do i = j, m a( i, j ) = a( i, j )*mul end do end do else if( itype==2_${ik}$ ) then ! upper triangular matrix do j = 1, n do i = 1, min( j, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==3_${ik}$ ) then ! upper hessenberg matrix do j = 1, n do i = 1, min( j+1, m ) a( i, j ) = a( i, j )*mul end do end do else if( itype==4_${ik}$ ) then ! lower chalf of a symmetric band matrix k3 = kl + 1_${ik}$ k4 = n + 1_${ik}$ do j = 1, n do i = 1, min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do else if( itype==5_${ik}$ ) then ! upper chalf of a symmetric band matrix k1 = ku + 2_${ik}$ k3 = ku + 1_${ik}$ do j = 1, n do i = max( k1-j, 1 ), k3 a( i, j ) = a( i, j )*mul end do end do else if( itype==6_${ik}$ ) then ! band matrix k1 = kl + ku + 2_${ik}$ k2 = kl + 1_${ik}$ k3 = 2_${ik}$*kl + ku + 1_${ik}$ k4 = kl + ku + 1_${ik}$ + m do j = 1, n do i = max( k1-j, k2 ), min( k3, k4-j ) a( i, j ) = a( i, j )*mul end do end do end if if( .not.done )go to 10 return end subroutine stdlib${ii}$_${ci}$lascl #:endif #:endfor module subroutine stdlib${ii}$_sla_geamv( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) !! SLA_GEAMV performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n, trans ! Array Arguments real(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(sp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' )) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, lenx temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, lenx temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = 1, lenx temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if (.not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = 1, lenx temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if (.not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_sla_geamv module subroutine stdlib${ii}$_dla_geamv ( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) !! DLA_GEAMV performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n, trans ! Array Arguments real(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(dp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' )) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, lenx temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, lenx temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = 1, lenx temp = abs( a( i, j ) ) symb_zero = symb_zero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if (.not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = 1, lenx temp = abs( a( j, i ) ) symb_zero = symb_zero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if (.not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_dla_geamv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$la_geamv ( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) !! DLA_GEAMV: performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n, trans ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), x(*) real(${rk}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_wero real(${rk}$) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' )) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_wero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, lenx temp = abs( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, lenx temp = abs( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = 1, lenx temp = abs( a( i, j ) ) symb_wero = symb_wero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if (.not.symb_wero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = 1, lenx temp = abs( a( j, i ) ) symb_wero = symb_wero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if (.not.symb_wero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_${ri}$la_geamv #:endif #:endfor module subroutine stdlib${ii}$_cla_geamv( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) !! CLA_GEAMV performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n integer(${ik}$), intent(in) :: trans ! Array Arguments complex(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(sp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny complex(sp) :: cdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' ) ) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == 0.0_sp ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == 0.0_sp ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= 0.0_sp ) then do j = 1, lenx temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == 0.0_sp ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == 0.0_sp ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= 0.0_sp ) then do j = 1, lenx temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == 0.0_sp ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == 0.0_sp ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= 0.0_sp ) then jx = kx do j = 1, lenx temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == 0.0_sp ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == 0.0_sp ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= 0.0_sp ) then jx = kx do j = 1, lenx temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_cla_geamv module subroutine stdlib${ii}$_zla_geamv( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) !! ZLA_GEAMV performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n integer(${ik}$), intent(in) :: trans ! Array Arguments complex(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(dp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny complex(dp) :: cdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' ) ) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == czero ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then do j = 1, lenx temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == czero ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then do j = 1, lenx temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == czero ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then jx = kx do j = 1, lenx temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == czero ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then jx = kx do j = 1, lenx temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_zla_geamv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$la_geamv( trans, m, n, alpha, a, lda, x, incx, beta,y, incy ) !! ZLA_GEAMV: performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, m, n integer(${ik}$), intent(in) :: trans ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), x(*) real(${ck}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_wero real(${ck}$) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny complex(${ck}$) :: cdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' ) ) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_wero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == czero ) then symb_wero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then do j = 1, lenx temp = cabs1( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_wero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == czero ) then symb_wero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then do j = 1, lenx temp = cabs1( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_wero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == czero ) then symb_wero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then jx = kx do j = 1, lenx temp = cabs1( a( i, j ) ) symb_wero = symb_wero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == czero ) then symb_wero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then jx = kx do j = 1, lenx temp = cabs1( a( j, i ) ) symb_wero = symb_wero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero ) y( iy ) =y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_${ci}$la_geamv #:endif #:endfor module subroutine stdlib${ii}$_sla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) !! SLA_GBAMV performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans ! Array Arguments real(sp), intent(in) :: ab(ldab,*), x(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(sp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny, kd, ke ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' ) ) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( kl<0_${ik}$ .or. kl>m-1 ) then info = 4_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = 5_${ik}$ else if( ldab0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. kd = ku + 1_${ik}$ ke = kl + 1_${ik}$ iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( kd+i-j, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( ke-i+j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( kd+i-j, j ) ) symb_zero = symb_zero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( ke-i+j, i ) ) symb_zero = symb_zero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_sla_gbamv module subroutine stdlib${ii}$_dla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) !! DLA_GBAMV performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans ! Array Arguments real(dp), intent(in) :: ab(ldab,*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(dp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny, kd, ke ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' ) ) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( kl<0_${ik}$ .or. kl>m-1 ) then info = 4_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = 5_${ik}$ else if( ldab0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. kd = ku + 1_${ik}$ ke = kl + 1_${ik}$ iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( kd+i-j, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( ke-i+j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( kd+i-j, j ) ) symb_zero = symb_zero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( ke-i+j, i ) ) symb_zero = symb_zero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_dla_gbamv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$la_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) !! DLA_GBAMV: performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans ! Array Arguments real(${rk}$), intent(in) :: ab(ldab,*), x(*) real(${rk}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_wero real(${rk}$) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny, kd, ke ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' ) ) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( kl<0_${ik}$ .or. kl>m-1 ) then info = 4_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = 5_${ik}$ else if( ldab0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_wero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. kd = ku + 1_${ik}$ ke = kl + 1_${ik}$ iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( kd+i-j, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( ke-i+j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( j ) )*temp end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( kd+i-j, j ) ) symb_wero = symb_wero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = abs( ab( ke-i+j, i ) ) symb_wero = symb_wero .and.( x( jx ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*abs( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_${ri}$la_gbamv #:endif #:endfor module subroutine stdlib${ii}$_cla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) !! CLA_GBAMV performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans ! Array Arguments complex(sp), intent(in) :: ab(ldab,*), x(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(sp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny, kd, ke complex(sp) :: cdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=sp) ) + abs( aimag( cdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' ) ) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( kl<0_${ik}$ .or. kl>m-1 ) then info = 4_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = 5_${ik}$ else if( ldab0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. kd = ku + 1_${ik}$ ke = kl + 1_${ik}$ iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == 0.0_sp ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == 0.0_sp ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= 0.0_sp ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( kd+i-j, j ) ) symb_zero = symb_zero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == 0.0_sp ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == 0.0_sp ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= 0.0_sp ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( ke-i+j, i ) ) symb_zero = symb_zero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == 0.0_sp ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == 0.0_sp ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= 0.0_sp ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( kd+i-j, j ) ) symb_zero = symb_zero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == 0.0_sp ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == 0.0_sp ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= 0.0_sp ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( ke-i+j, i ) ) symb_zero = symb_zero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_cla_gbamv module subroutine stdlib${ii}$_zla_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) !! ZLA_GBAMV performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans ! Array Arguments complex(dp), intent(in) :: ab(ldab,*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(dp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny, kd, ke complex(dp) :: cdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=dp) ) + abs( aimag( cdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' ) ) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( kl<0_${ik}$ .or. kl>m-1 ) then info = 4_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = 5_${ik}$ else if( ldab0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. kd = ku + 1_${ik}$ ke = kl + 1_${ik}$ iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == czero ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( kd+i-j, j ) ) symb_zero = symb_zero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == czero ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( ke-i+j, i ) ) symb_zero = symb_zero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == czero ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( kd+i-j, j ) ) symb_zero = symb_zero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == czero ) then symb_zero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( ke-i+j, i ) ) symb_zero = symb_zero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_zla_gbamv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$la_gbamv( trans, m, n, kl, ku, alpha, ab, ldab, x,incx, beta, y, incy ) !! ZLA_GBAMV: performs one of the matrix-vector operations !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! or y := alpha*abs(A)**T*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! m by n matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, ldab, m, n, kl, ku, trans ! Array Arguments complex(${ck}$), intent(in) :: ab(ldab,*), x(*) real(${ck}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_wero real(${ck}$) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky, lenx, leny, kd, ke complex(${ck}$) :: cdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( cdum ) = abs( real( cdum,KIND=${ck}$) ) + abs( aimag( cdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( .not.( ( trans==stdlib${ii}$_ilatrans( 'N' ) ).or. ( trans==stdlib${ii}$_ilatrans( 'T' ) )& .or. ( trans==stdlib${ii}$_ilatrans( 'C' ) ) ) ) then info = 1_${ik}$ else if( m<0_${ik}$ )then info = 2_${ik}$ else if( n<0_${ik}$ )then info = 3_${ik}$ else if( kl<0_${ik}$ .or. kl>m-1 ) then info = 4_${ik}$ else if( ku<0_${ik}$ .or. ku>n-1 ) then info = 5_${ik}$ else if( ldab0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( lenx - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( leny - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(m*n) symb_wero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. kd = ku + 1_${ik}$ ke = kl + 1_${ik}$ iy = ky if ( incx==1_${ik}$ ) then if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == czero ) then symb_wero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( kd+i-j, j ) ) symb_wero = symb_wero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_wero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == czero ) then symb_wero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( ke-i+j, i ) ) symb_wero = symb_wero .and.( x( j ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if ( .not.symb_wero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if( trans==stdlib${ii}$_ilatrans( 'N' ) )then do i = 1, leny if ( beta == czero ) then symb_wero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( kd+i-j, j ) ) symb_wero = symb_wero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, leny if ( beta == czero ) then symb_wero = .true. y( iy ) = czero else if ( y( iy ) == czero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= czero ) then jx = kx do j = max( i-kl, 1 ), min( i+ku, lenx ) temp = cabs1( ab( ke-i+j, i ) ) symb_wero = symb_wero .and.( x( jx ) == czero .or. temp == czero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_${ci}$la_gbamv #:endif #:endfor module subroutine stdlib${ii}$_cla_heamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) !! CLA_SYAMV performs the matrix-vector operation !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! n by n symmetric matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n, uplo ! Array Arguments complex(sp), intent(in) :: a(lda,*), x(*) real(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(sp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky complex(sp) :: zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag ( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( uplo/=stdlib${ii}$_ilauplo( 'U' ) .and.uplo/=stdlib${ii}$_ilauplo( 'L' ) )then info = 1_${ik}$ else if( n<0_${ik}$ )then info = 2_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(n^2) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if (.not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if (.not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_cla_heamv module subroutine stdlib${ii}$_zla_heamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) !! ZLA_SYAMV performs the matrix-vector operation !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! n by n symmetric matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n, uplo ! Array Arguments complex(dp), intent(in) :: a(lda,*), x(*) real(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_zero real(dp) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky complex(dp) :: zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag ( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( uplo/=stdlib${ii}$_ilauplo( 'U' ) .and.uplo/=stdlib${ii}$_ilauplo( 'L' ) )then info = 1_${ik}$ else if( n<0_${ik}$ )then info = 2_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(n^2) symb_zero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if (.not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if (.not.symb_zero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_zero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_zero = .true. else symb_zero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_zero = symb_zero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_zero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_zla_heamv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$la_heamv( uplo, n, alpha, a, lda, x, incx, beta, y,incy ) !! ZLA_SYAMV performs the matrix-vector operation !! y := alpha*abs(A)*abs(x) + beta*abs(y), !! where alpha and beta are scalars, x and y are vectors and A is an !! n by n symmetric matrix. !! This function is primarily used in calculating error bounds. !! To protect against underflow during evaluation, components in !! the resulting vector are perturbed away from zero by (N+1) !! times the underflow threshold. To prevent unnecessarily large !! errors for block-structure embedded in general matrices, !! "symbolically" zero components are not perturbed. A zero !! entry is considered "symbolic" if all multiplications involved !! in computing that entry have at least one zero multiplicand. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${ck}$), intent(in) :: alpha, beta integer(${ik}$), intent(in) :: incx, incy, lda, n, uplo ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), x(*) real(${ck}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars logical(lk) :: symb_wero real(${ck}$) :: temp, safe1 integer(${ik}$) :: i, info, iy, j, jx, kx, ky complex(${ck}$) :: zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag ( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ if ( uplo/=stdlib${ii}$_ilauplo( 'U' ) .and.uplo/=stdlib${ii}$_ilauplo( 'L' ) )then info = 1_${ik}$ else if( n<0_${ik}$ )then info = 2_${ik}$ else if( lda0_${ik}$ )then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n - 1_${ik}$ )*incx end if if( incy>0_${ik}$ )then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n - 1_${ik}$ )*incy end if ! set safe1 essentially to be the underflow threshold times the ! number of additions in each row. safe1 = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) safe1 = (n+1)*safe1 ! form y := alpha*abs(a)*abs(x) + beta*abs(y). ! the o(n^2) symb_wero tests could be replaced by o(n) queries to ! the inexact flag. still doesn't help change the iteration order ! to per-column. iy = ky if ( incx==1_${ik}$ ) then if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if (.not.symb_wero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( j ) )*temp end do end if if (.not.symb_wero)y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if else if ( uplo == stdlib${ii}$_ilauplo( 'U' ) ) then do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do else do i = 1, n if ( beta == zero ) then symb_wero = .true. y( iy ) = zero else if ( y( iy ) == zero ) then symb_wero = .true. else symb_wero = .false. y( iy ) = beta * abs( y( iy ) ) end if jx = kx if ( alpha /= zero ) then do j = 1, i temp = cabs1( a( i, j ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do do j = i+1, n temp = cabs1( a( j, i ) ) symb_wero = symb_wero .and.( x( j ) == zero .or. temp == zero ) y( iy ) = y( iy ) + alpha*cabs1( x( jx ) )*temp jx = jx + incx end do end if if ( .not.symb_wero )y( iy ) = y( iy ) + sign( safe1, y( iy ) ) iy = iy + incy end do end if end if return end subroutine stdlib${ii}$_${ci}$la_heamv #:endif #:endfor pure module subroutine stdlib${ii}$_sla_wwaddw( n, x, y, w ) !! SLA_WWADDW adds a vector W into a doubled-single vector (X, Y). !! This works for all extant IBM's hex and binary floating point !! arithmetic, but not for decimal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(inout) :: x(*), y(*) real(sp), intent(in) :: w(*) ! ===================================================================== ! Local Scalars real(sp) :: s integer(${ik}$) :: i ! Executable Statements do 10 i = 1, n s = x(i) + w(i) s = (s + s) - s y(i) = ((x(i) - s) + w(i)) + y(i) x(i) = s 10 continue return end subroutine stdlib${ii}$_sla_wwaddw pure module subroutine stdlib${ii}$_dla_wwaddw( n, x, y, w ) !! DLA_WWADDW adds a vector W into a doubled-single vector (X, Y). !! This works for all extant IBM's hex and binary floating point !! arithmetic, but not for decimal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(inout) :: x(*), y(*) real(dp), intent(in) :: w(*) ! ===================================================================== ! Local Scalars real(dp) :: s integer(${ik}$) :: i ! Executable Statements do 10 i = 1, n s = x(i) + w(i) s = (s + s) - s y(i) = ((x(i) - s) + w(i)) + y(i) x(i) = s 10 continue return end subroutine stdlib${ii}$_dla_wwaddw #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$la_wwaddw( n, x, y, w ) !! DLA_WWADDW: adds a vector W into a doubled-single vector (X, Y). !! This works for all extant IBM's hex and binary floating point !! arithmetic, but not for decimal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n ! Array Arguments real(${rk}$), intent(inout) :: x(*), y(*) real(${rk}$), intent(in) :: w(*) ! ===================================================================== ! Local Scalars real(${rk}$) :: s integer(${ik}$) :: i ! Executable Statements do 10 i = 1, n s = x(i) + w(i) s = (s + s) - s y(i) = ((x(i) - s) + w(i)) + y(i) x(i) = s 10 continue return end subroutine stdlib${ii}$_${ri}$la_wwaddw #:endif #:endfor pure module subroutine stdlib${ii}$_cla_wwaddw( n, x, y, w ) !! CLA_WWADDW adds a vector W into a doubled-single vector (X, Y). !! This works for all extant IBM's hex and binary floating point !! arithmetic, but not for decimal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n ! Array Arguments complex(sp), intent(inout) :: x(*), y(*) complex(sp), intent(in) :: w(*) ! ===================================================================== ! Local Scalars complex(sp) :: s integer(${ik}$) :: i ! Executable Statements do 10 i = 1, n s = x(i) + w(i) s = (s + s) - s y(i) = ((x(i) - s) + w(i)) + y(i) x(i) = s 10 continue return end subroutine stdlib${ii}$_cla_wwaddw pure module subroutine stdlib${ii}$_zla_wwaddw( n, x, y, w ) !! ZLA_WWADDW adds a vector W into a doubled-single vector (X, Y). !! This works for all extant IBM's hex and binary floating point !! arithmetic, but not for decimal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n ! Array Arguments complex(dp), intent(inout) :: x(*), y(*) complex(dp), intent(in) :: w(*) ! ===================================================================== ! Local Scalars complex(dp) :: s integer(${ik}$) :: i ! Executable Statements do 10 i = 1, n s = x(i) + w(i) s = (s + s) - s y(i) = ((x(i) - s) + w(i)) + y(i) x(i) = s 10 continue return end subroutine stdlib${ii}$_zla_wwaddw #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$la_wwaddw( n, x, y, w ) !! ZLA_WWADDW: adds a vector W into a doubled-single vector (X, Y). !! This works for all extant IBM's hex and binary floating point !! arithmetic, but not for decimal. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: n ! Array Arguments complex(${ck}$), intent(inout) :: x(*), y(*) complex(${ck}$), intent(in) :: w(*) ! ===================================================================== ! Local Scalars complex(${ck}$) :: s integer(${ik}$) :: i ! Executable Statements do 10 i = 1, n s = x(i) + w(i) s = (s + s) - s y(i) = ((x(i) - s) + w(i)) + y(i) x(i) = s 10 continue return end subroutine stdlib${ii}$_${ci}$la_wwaddw #:endif #:endfor pure module subroutine stdlib${ii}$_cspmv( uplo, n, alpha, ap, x, incx, beta, y, incy ) !! CSPMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, n complex(sp), intent(in) :: alpha, beta ! Array Arguments complex(sp), intent(in) :: ap(*), x(*) complex(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky complex(sp) :: temp1, temp2 ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ ) then info = 2_${ik}$ else if( incx==0_${ik}$ ) then info = 6_${ik}$ else if( incy==0_${ik}$ ) then info = 9_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CSPMV ', info ) return end if ! quick return if possible. if( ( n==0 ) .or. ( ( alpha==czero ) .and. ( beta==cone ) ) )return ! set up the start points in x and y. if( incx>0_${ik}$ ) then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n-1 )*incx end if if( incy>0_${ik}$ ) then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n-1 )*incy end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. ! first form y := beta*y. if( beta/=cone ) then if( incy==1_${ik}$ ) then if( beta==czero ) then do i = 1, n y( i ) = czero end do else do i = 1, n y( i ) = beta*y( i ) end do end if else iy = ky if( beta==czero ) then do i = 1, n y( iy ) = czero iy = iy + incy end do else do i = 1, n y( iy ) = beta*y( iy ) iy = iy + incy end do end if end if end if if( alpha==czero )return kk = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then ! form y when ap contains the upper triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero k = kk do i = 1, j - 1 y( i ) = y( i ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( i ) k = k + 1_${ik}$ end do y( j ) = y( j ) + temp1*ap( kk+j-1 ) + alpha*temp2 kk = kk + j end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero ix = kx iy = ky do k = kk, kk + j - 2 y( iy ) = y( iy ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( ix ) ix = ix + incx iy = iy + incy end do y( jy ) = y( jy ) + temp1*ap( kk+j-1 ) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form y when ap contains the lower triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero y( j ) = y( j ) + temp1*ap( kk ) k = kk + 1_${ik}$ do i = j + 1, n y( i ) = y( i ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( i ) k = k + 1_${ik}$ end do y( j ) = y( j ) + alpha*temp2 kk = kk + ( n-j+1 ) end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero y( jy ) = y( jy ) + temp1*ap( kk ) ix = jx iy = jy do k = kk + 1, kk + n - j ix = ix + incx iy = iy + incy y( iy ) = y( iy ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( ix ) end do y( jy ) = y( jy ) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + ( n-j+1 ) end do end if end if return end subroutine stdlib${ii}$_cspmv pure module subroutine stdlib${ii}$_zspmv( uplo, n, alpha, ap, x, incx, beta, y, incy ) !! ZSPMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, n complex(dp), intent(in) :: alpha, beta ! Array Arguments complex(dp), intent(in) :: ap(*), x(*) complex(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky complex(dp) :: temp1, temp2 ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ ) then info = 2_${ik}$ else if( incx==0_${ik}$ ) then info = 6_${ik}$ else if( incy==0_${ik}$ ) then info = 9_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZSPMV ', info ) return end if ! quick return if possible. if( ( n==0 ) .or. ( ( alpha==czero ) .and. ( beta==cone ) ) )return ! set up the start points in x and y. if( incx>0_${ik}$ ) then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n-1 )*incx end if if( incy>0_${ik}$ ) then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n-1 )*incy end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. ! first form y := beta*y. if( beta/=cone ) then if( incy==1_${ik}$ ) then if( beta==czero ) then do i = 1, n y( i ) = czero end do else do i = 1, n y( i ) = beta*y( i ) end do end if else iy = ky if( beta==czero ) then do i = 1, n y( iy ) = czero iy = iy + incy end do else do i = 1, n y( iy ) = beta*y( iy ) iy = iy + incy end do end if end if end if if( alpha==czero )return kk = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then ! form y when ap contains the upper triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero k = kk do i = 1, j - 1 y( i ) = y( i ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( i ) k = k + 1_${ik}$ end do y( j ) = y( j ) + temp1*ap( kk+j-1 ) + alpha*temp2 kk = kk + j end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero ix = kx iy = ky do k = kk, kk + j - 2 y( iy ) = y( iy ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( ix ) ix = ix + incx iy = iy + incy end do y( jy ) = y( jy ) + temp1*ap( kk+j-1 ) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form y when ap contains the lower triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero y( j ) = y( j ) + temp1*ap( kk ) k = kk + 1_${ik}$ do i = j + 1, n y( i ) = y( i ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( i ) k = k + 1_${ik}$ end do y( j ) = y( j ) + alpha*temp2 kk = kk + ( n-j+1 ) end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero y( jy ) = y( jy ) + temp1*ap( kk ) ix = jx iy = jy do k = kk + 1, kk + n - j ix = ix + incx iy = iy + incy y( iy ) = y( iy ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( ix ) end do y( jy ) = y( jy ) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + ( n-j+1 ) end do end if end if return end subroutine stdlib${ii}$_zspmv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$spmv( uplo, n, alpha, ap, x, incx, beta, y, incy ) !! ZSPMV: performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, n complex(${ck}$), intent(in) :: alpha, beta ! Array Arguments complex(${ck}$), intent(in) :: ap(*), x(*) complex(${ck}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, ix, iy, j, jx, jy, k, kk, kx, ky complex(${ck}$) :: temp1, temp2 ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ ) then info = 2_${ik}$ else if( incx==0_${ik}$ ) then info = 6_${ik}$ else if( incy==0_${ik}$ ) then info = 9_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZSPMV ', info ) return end if ! quick return if possible. if( ( n==0 ) .or. ( ( alpha==czero ) .and. ( beta==cone ) ) )return ! set up the start points in x and y. if( incx>0_${ik}$ ) then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n-1 )*incx end if if( incy>0_${ik}$ ) then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n-1 )*incy end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. ! first form y := beta*y. if( beta/=cone ) then if( incy==1_${ik}$ ) then if( beta==czero ) then do i = 1, n y( i ) = czero end do else do i = 1, n y( i ) = beta*y( i ) end do end if else iy = ky if( beta==czero ) then do i = 1, n y( iy ) = czero iy = iy + incy end do else do i = 1, n y( iy ) = beta*y( iy ) iy = iy + incy end do end if end if end if if( alpha==czero )return kk = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then ! form y when ap contains the upper triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero k = kk do i = 1, j - 1 y( i ) = y( i ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( i ) k = k + 1_${ik}$ end do y( j ) = y( j ) + temp1*ap( kk+j-1 ) + alpha*temp2 kk = kk + j end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero ix = kx iy = ky do k = kk, kk + j - 2 y( iy ) = y( iy ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( ix ) ix = ix + incx iy = iy + incy end do y( jy ) = y( jy ) + temp1*ap( kk+j-1 ) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + j end do end if else ! form y when ap contains the lower triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero y( j ) = y( j ) + temp1*ap( kk ) k = kk + 1_${ik}$ do i = j + 1, n y( i ) = y( i ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( i ) k = k + 1_${ik}$ end do y( j ) = y( j ) + alpha*temp2 kk = kk + ( n-j+1 ) end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero y( jy ) = y( jy ) + temp1*ap( kk ) ix = jx iy = jy do k = kk + 1, kk + n - j ix = ix + incx iy = iy + incy y( iy ) = y( iy ) + temp1*ap( k ) temp2 = temp2 + ap( k )*x( ix ) end do y( jy ) = y( jy ) + alpha*temp2 jx = jx + incx jy = jy + incy kk = kk + ( n-j+1 ) end do end if end if return end subroutine stdlib${ii}$_${ci}$spmv #:endif #:endfor pure module subroutine stdlib${ii}$_cspr( uplo, n, alpha, x, incx, ap ) !! CSPR performs the symmetric rank 1 operation !! A := alpha*x*x**H + A, !! where alpha is a complex scalar, x is an n element vector and A is an !! n by n symmetric matrix, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, n complex(sp), intent(in) :: alpha ! Array Arguments complex(sp), intent(inout) :: ap(*) complex(sp), intent(in) :: x(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx complex(sp) :: temp ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ ) then info = 2_${ik}$ else if( incx==0_${ik}$ ) then info = 5_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CSPR ', info ) return end if ! quick return if possible. if( ( n==0 ) .or. ( alpha==czero ) )return ! set the start point in x if the increment is not unity. if( incx<=0_${ik}$ ) then kx = 1_${ik}$ - ( n-1 )*incx else if( incx/=1_${ik}$ ) then kx = 1_${ik}$ end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. kk = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then ! form a when upper triangle is stored in ap. if( incx==1_${ik}$ ) then do j = 1, n if( x( j )/=czero ) then temp = alpha*x( j ) k = kk do i = 1, j - 1 ap( k ) = ap( k ) + x( i )*temp k = k + 1_${ik}$ end do ap( kk+j-1 ) = ap( kk+j-1 ) + x( j )*temp else ap( kk+j-1 ) = ap( kk+j-1 ) end if kk = kk + j end do else jx = kx do j = 1, n if( x( jx )/=czero ) then temp = alpha*x( jx ) ix = kx do k = kk, kk + j - 2 ap( k ) = ap( k ) + x( ix )*temp ix = ix + incx end do ap( kk+j-1 ) = ap( kk+j-1 ) + x( jx )*temp else ap( kk+j-1 ) = ap( kk+j-1 ) end if jx = jx + incx kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if( incx==1_${ik}$ ) then do j = 1, n if( x( j )/=czero ) then temp = alpha*x( j ) ap( kk ) = ap( kk ) + temp*x( j ) k = kk + 1_${ik}$ do i = j + 1, n ap( k ) = ap( k ) + x( i )*temp k = k + 1_${ik}$ end do else ap( kk ) = ap( kk ) end if kk = kk + n - j + 1_${ik}$ end do else jx = kx do j = 1, n if( x( jx )/=czero ) then temp = alpha*x( jx ) ap( kk ) = ap( kk ) + temp*x( jx ) ix = jx do k = kk + 1, kk + n - j ix = ix + incx ap( k ) = ap( k ) + x( ix )*temp end do else ap( kk ) = ap( kk ) end if jx = jx + incx kk = kk + n - j + 1_${ik}$ end do end if end if return end subroutine stdlib${ii}$_cspr pure module subroutine stdlib${ii}$_zspr( uplo, n, alpha, x, incx, ap ) !! ZSPR performs the symmetric rank 1 operation !! A := alpha*x*x**H + A, !! where alpha is a complex scalar, x is an n element vector and A is an !! n by n symmetric matrix, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, n complex(dp), intent(in) :: alpha ! Array Arguments complex(dp), intent(inout) :: ap(*) complex(dp), intent(in) :: x(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx complex(dp) :: temp ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ ) then info = 2_${ik}$ else if( incx==0_${ik}$ ) then info = 5_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZSPR ', info ) return end if ! quick return if possible. if( ( n==0 ) .or. ( alpha==czero ) )return ! set the start point in x if the increment is not unity. if( incx<=0_${ik}$ ) then kx = 1_${ik}$ - ( n-1 )*incx else if( incx/=1_${ik}$ ) then kx = 1_${ik}$ end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. kk = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then ! form a when upper triangle is stored in ap. if( incx==1_${ik}$ ) then do j = 1, n if( x( j )/=czero ) then temp = alpha*x( j ) k = kk do i = 1, j - 1 ap( k ) = ap( k ) + x( i )*temp k = k + 1_${ik}$ end do ap( kk+j-1 ) = ap( kk+j-1 ) + x( j )*temp else ap( kk+j-1 ) = ap( kk+j-1 ) end if kk = kk + j end do else jx = kx do j = 1, n if( x( jx )/=czero ) then temp = alpha*x( jx ) ix = kx do k = kk, kk + j - 2 ap( k ) = ap( k ) + x( ix )*temp ix = ix + incx end do ap( kk+j-1 ) = ap( kk+j-1 ) + x( jx )*temp else ap( kk+j-1 ) = ap( kk+j-1 ) end if jx = jx + incx kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if( incx==1_${ik}$ ) then do j = 1, n if( x( j )/=czero ) then temp = alpha*x( j ) ap( kk ) = ap( kk ) + temp*x( j ) k = kk + 1_${ik}$ do i = j + 1, n ap( k ) = ap( k ) + x( i )*temp k = k + 1_${ik}$ end do else ap( kk ) = ap( kk ) end if kk = kk + n - j + 1_${ik}$ end do else jx = kx do j = 1, n if( x( jx )/=czero ) then temp = alpha*x( jx ) ap( kk ) = ap( kk ) + temp*x( jx ) ix = jx do k = kk + 1, kk + n - j ix = ix + incx ap( k ) = ap( k ) + x( ix )*temp end do else ap( kk ) = ap( kk ) end if jx = jx + incx kk = kk + n - j + 1_${ik}$ end do end if end if return end subroutine stdlib${ii}$_zspr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$spr( uplo, n, alpha, x, incx, ap ) !! ZSPR: performs the symmetric rank 1 operation !! A := alpha*x*x**H + A, !! where alpha is a complex scalar, x is an n element vector and A is an !! n by n symmetric matrix, supplied in packed form. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, n complex(${ck}$), intent(in) :: alpha ! Array Arguments complex(${ck}$), intent(inout) :: ap(*) complex(${ck}$), intent(in) :: x(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, ix, j, jx, k, kk, kx complex(${ck}$) :: temp ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ ) then info = 2_${ik}$ else if( incx==0_${ik}$ ) then info = 5_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZSPR ', info ) return end if ! quick return if possible. if( ( n==0 ) .or. ( alpha==czero ) )return ! set the start point in x if the increment is not unity. if( incx<=0_${ik}$ ) then kx = 1_${ik}$ - ( n-1 )*incx else if( incx/=1_${ik}$ ) then kx = 1_${ik}$ end if ! start the operations. in this version the elements of the array ap ! are accessed sequentially with cone pass through ap. kk = 1_${ik}$ if( stdlib_lsame( uplo, 'U' ) ) then ! form a when upper triangle is stored in ap. if( incx==1_${ik}$ ) then do j = 1, n if( x( j )/=czero ) then temp = alpha*x( j ) k = kk do i = 1, j - 1 ap( k ) = ap( k ) + x( i )*temp k = k + 1_${ik}$ end do ap( kk+j-1 ) = ap( kk+j-1 ) + x( j )*temp else ap( kk+j-1 ) = ap( kk+j-1 ) end if kk = kk + j end do else jx = kx do j = 1, n if( x( jx )/=czero ) then temp = alpha*x( jx ) ix = kx do k = kk, kk + j - 2 ap( k ) = ap( k ) + x( ix )*temp ix = ix + incx end do ap( kk+j-1 ) = ap( kk+j-1 ) + x( jx )*temp else ap( kk+j-1 ) = ap( kk+j-1 ) end if jx = jx + incx kk = kk + j end do end if else ! form a when lower triangle is stored in ap. if( incx==1_${ik}$ ) then do j = 1, n if( x( j )/=czero ) then temp = alpha*x( j ) ap( kk ) = ap( kk ) + temp*x( j ) k = kk + 1_${ik}$ do i = j + 1, n ap( k ) = ap( k ) + x( i )*temp k = k + 1_${ik}$ end do else ap( kk ) = ap( kk ) end if kk = kk + n - j + 1_${ik}$ end do else jx = kx do j = 1, n if( x( jx )/=czero ) then temp = alpha*x( jx ) ap( kk ) = ap( kk ) + temp*x( jx ) ix = jx do k = kk + 1, kk + n - j ix = ix + incx ap( k ) = ap( k ) + x( ix )*temp end do else ap( kk ) = ap( kk ) end if jx = jx + incx kk = kk + n - j + 1_${ik}$ end do end if end if return end subroutine stdlib${ii}$_${ci}$spr #:endif #:endfor pure module subroutine stdlib${ii}$_csymv( uplo, n, alpha, a, lda, x, incx, beta, y, incy ) !! CSYMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, lda, n complex(sp), intent(in) :: alpha, beta ! Array Arguments complex(sp), intent(in) :: a(lda,*), x(*) complex(sp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky complex(sp) :: temp1, temp2 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ ) then info = 2_${ik}$ else if( lda0_${ik}$ ) then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n-1 )*incx end if if( incy>0_${ik}$ ) then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n-1 )*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the triangular part ! of a. ! first form y := beta*y. if( beta/=cone ) then if( incy==1_${ik}$ ) then if( beta==czero ) then do i = 1, n y( i ) = czero end do else do i = 1, n y( i ) = beta*y( i ) end do end if else iy = ky if( beta==czero ) then do i = 1, n y( iy ) = czero iy = iy + incy end do else do i = 1, n y( iy ) = beta*y( iy ) iy = iy + incy end do end if end if end if if( alpha==czero )return if( stdlib_lsame( uplo, 'U' ) ) then ! form y when a is stored in upper triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero do i = 1, j - 1 y( i ) = y( i ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( i ) end do y( j ) = y( j ) + temp1*a( j, j ) + alpha*temp2 end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero ix = kx iy = ky do i = 1, j - 1 y( iy ) = y( iy ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( ix ) ix = ix + incx iy = iy + incy end do y( jy ) = y( jy ) + temp1*a( j, j ) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if else ! form y when a is stored in lower triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero y( j ) = y( j ) + temp1*a( j, j ) do i = j + 1, n y( i ) = y( i ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( i ) end do y( j ) = y( j ) + alpha*temp2 end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero y( jy ) = y( jy ) + temp1*a( j, j ) ix = jx iy = jy do i = j + 1, n ix = ix + incx iy = iy + incy y( iy ) = y( iy ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( ix ) end do y( jy ) = y( jy ) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_csymv pure module subroutine stdlib${ii}$_zsymv( uplo, n, alpha, a, lda, x, incx, beta, y, incy ) !! ZSYMV performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, lda, n complex(dp), intent(in) :: alpha, beta ! Array Arguments complex(dp), intent(in) :: a(lda,*), x(*) complex(dp), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky complex(dp) :: temp1, temp2 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ ) then info = 2_${ik}$ else if( lda0_${ik}$ ) then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n-1 )*incx end if if( incy>0_${ik}$ ) then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n-1 )*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the triangular part ! of a. ! first form y := beta*y. if( beta/=cone ) then if( incy==1_${ik}$ ) then if( beta==czero ) then do i = 1, n y( i ) = czero end do else do i = 1, n y( i ) = beta*y( i ) end do end if else iy = ky if( beta==czero ) then do i = 1, n y( iy ) = czero iy = iy + incy end do else do i = 1, n y( iy ) = beta*y( iy ) iy = iy + incy end do end if end if end if if( alpha==czero )return if( stdlib_lsame( uplo, 'U' ) ) then ! form y when a is stored in upper triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero do i = 1, j - 1 y( i ) = y( i ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( i ) end do y( j ) = y( j ) + temp1*a( j, j ) + alpha*temp2 end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero ix = kx iy = ky do i = 1, j - 1 y( iy ) = y( iy ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( ix ) ix = ix + incx iy = iy + incy end do y( jy ) = y( jy ) + temp1*a( j, j ) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if else ! form y when a is stored in lower triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero y( j ) = y( j ) + temp1*a( j, j ) do i = j + 1, n y( i ) = y( i ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( i ) end do y( j ) = y( j ) + alpha*temp2 end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero y( jy ) = y( jy ) + temp1*a( j, j ) ix = jx iy = jy do i = j + 1, n ix = ix + incx iy = iy + incy y( iy ) = y( iy ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( ix ) end do y( jy ) = y( jy ) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_zsymv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$symv( uplo, n, alpha, a, lda, x, incx, beta, y, incy ) !! ZSYMV: performs the matrix-vector operation !! y := alpha*A*x + beta*y, !! where alpha and beta are scalars, x and y are n element vectors and !! A is an n by n symmetric matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, incy, lda, n complex(${ck}$), intent(in) :: alpha, beta ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), x(*) complex(${ck}$), intent(inout) :: y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, ix, iy, j, jx, jy, kx, ky complex(${ck}$) :: temp1, temp2 ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ ) then info = 2_${ik}$ else if( lda0_${ik}$ ) then kx = 1_${ik}$ else kx = 1_${ik}$ - ( n-1 )*incx end if if( incy>0_${ik}$ ) then ky = 1_${ik}$ else ky = 1_${ik}$ - ( n-1 )*incy end if ! start the operations. in this version the elements of a are ! accessed sequentially with cone pass through the triangular part ! of a. ! first form y := beta*y. if( beta/=cone ) then if( incy==1_${ik}$ ) then if( beta==czero ) then do i = 1, n y( i ) = czero end do else do i = 1, n y( i ) = beta*y( i ) end do end if else iy = ky if( beta==czero ) then do i = 1, n y( iy ) = czero iy = iy + incy end do else do i = 1, n y( iy ) = beta*y( iy ) iy = iy + incy end do end if end if end if if( alpha==czero )return if( stdlib_lsame( uplo, 'U' ) ) then ! form y when a is stored in upper triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero do i = 1, j - 1 y( i ) = y( i ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( i ) end do y( j ) = y( j ) + temp1*a( j, j ) + alpha*temp2 end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero ix = kx iy = ky do i = 1, j - 1 y( iy ) = y( iy ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( ix ) ix = ix + incx iy = iy + incy end do y( jy ) = y( jy ) + temp1*a( j, j ) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if else ! form y when a is stored in lower triangle. if( ( incx==1_${ik}$ ) .and. ( incy==1_${ik}$ ) ) then do j = 1, n temp1 = alpha*x( j ) temp2 = czero y( j ) = y( j ) + temp1*a( j, j ) do i = j + 1, n y( i ) = y( i ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( i ) end do y( j ) = y( j ) + alpha*temp2 end do else jx = kx jy = ky do j = 1, n temp1 = alpha*x( jx ) temp2 = czero y( jy ) = y( jy ) + temp1*a( j, j ) ix = jx iy = jy do i = j + 1, n ix = ix + incx iy = iy + incy y( iy ) = y( iy ) + temp1*a( i, j ) temp2 = temp2 + a( i, j )*x( ix ) end do y( jy ) = y( jy ) + alpha*temp2 jx = jx + incx jy = jy + incy end do end if end if return end subroutine stdlib${ii}$_${ci}$symv #:endif #:endfor pure module subroutine stdlib${ii}$_csyr( uplo, n, alpha, x, incx, a, lda ) !! CSYR performs the symmetric rank 1 operation !! A := alpha*x*x**H + A, !! where alpha is a complex scalar, x is an n element vector and A is an !! n by n symmetric matrix. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: incx, lda, n complex(sp), intent(in) :: alpha ! Array Arguments complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: x(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, info, ix, j, jx, kx complex(sp) :: temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = 1_${ik}$ else if( n<0_${ik}$ ) then info = 2_${ik}$ else if( incx==0_${ik}$ ) then info = 5_${ik}$ else if( lda=n ) then ! use unblocked code. call stdlib${ii}$_spotrf2( uplo, n, a, lda, info ) else ! use blocked code. if( upper ) then ! compute the cholesky factorization a = u**t*u. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_ssyrk( 'UPPER', 'TRANSPOSE', jb, j-1, -one,a( 1_${ik}$, j ), lda, one, a(& j, j ), lda ) call stdlib${ii}$_spotrf2( 'UPPER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block row. call stdlib${ii}$_sgemm( 'TRANSPOSE', 'NO TRANSPOSE', jb, n-j-jb+1,j-1, -one, a( & 1_${ik}$, j ), lda, a( 1_${ik}$, j+jb ),lda, one, a( j, j+jb ), lda ) call stdlib${ii}$_strsm( 'LEFT', 'UPPER', 'TRANSPOSE', 'NON-UNIT',jb, n-j-jb+1, & one, a( j, j ), lda,a( j, j+jb ), lda ) end if end do else ! compute the cholesky factorization a = l*l**t. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_ssyrk( 'LOWER', 'NO TRANSPOSE', jb, j-1, -one,a( j, 1_${ik}$ ), lda, one,& a( j, j ), lda ) call stdlib${ii}$_spotrf2( 'LOWER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block column. call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', n-j-jb+1, jb,j-1, -one, a( & j+jb, 1_${ik}$ ), lda, a( j, 1_${ik}$ ),lda, one, a( j+jb, j ), lda ) call stdlib${ii}$_strsm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'NON-UNIT',n-j-jb+1, jb, & one, a( j, j ), lda,a( j+jb, j ), lda ) end if end do end if end if go to 40 30 continue info = info + j - 1_${ik}$ 40 continue return end subroutine stdlib${ii}$_spotrf pure module subroutine stdlib${ii}$_dpotrf( uplo, n, a, lda, info ) !! DPOTRF computes the Cholesky factorization of a real symmetric !! positive definite matrix A. !! The factorization has the form !! A = U**T * U, if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code. call stdlib${ii}$_dpotrf2( uplo, n, a, lda, info ) else ! use blocked code. if( upper ) then ! compute the cholesky factorization a = u**t*u. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_dsyrk( 'UPPER', 'TRANSPOSE', jb, j-1, -one,a( 1_${ik}$, j ), lda, one, a(& j, j ), lda ) call stdlib${ii}$_dpotrf2( 'UPPER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block row. call stdlib${ii}$_dgemm( 'TRANSPOSE', 'NO TRANSPOSE', jb, n-j-jb+1,j-1, -one, a( & 1_${ik}$, j ), lda, a( 1_${ik}$, j+jb ),lda, one, a( j, j+jb ), lda ) call stdlib${ii}$_dtrsm( 'LEFT', 'UPPER', 'TRANSPOSE', 'NON-UNIT',jb, n-j-jb+1, & one, a( j, j ), lda,a( j, j+jb ), lda ) end if end do else ! compute the cholesky factorization a = l*l**t. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_dsyrk( 'LOWER', 'NO TRANSPOSE', jb, j-1, -one,a( j, 1_${ik}$ ), lda, one,& a( j, j ), lda ) call stdlib${ii}$_dpotrf2( 'LOWER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block column. call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', n-j-jb+1, jb,j-1, -one, a( & j+jb, 1_${ik}$ ), lda, a( j, 1_${ik}$ ),lda, one, a( j+jb, j ), lda ) call stdlib${ii}$_dtrsm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'NON-UNIT',n-j-jb+1, jb, & one, a( j, j ), lda,a( j+jb, j ), lda ) end if end do end if end if go to 40 30 continue info = info + j - 1_${ik}$ 40 continue return end subroutine stdlib${ii}$_dpotrf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$potrf( uplo, n, a, lda, info ) !! DPOTRF: computes the Cholesky factorization of a real symmetric !! positive definite matrix A. !! The factorization has the form !! A = U**T * U, if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code. call stdlib${ii}$_${ri}$potrf2( uplo, n, a, lda, info ) else ! use blocked code. if( upper ) then ! compute the cholesky factorization a = u**t*u. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_${ri}$syrk( 'UPPER', 'TRANSPOSE', jb, j-1, -one,a( 1_${ik}$, j ), lda, one, a(& j, j ), lda ) call stdlib${ii}$_${ri}$potrf2( 'UPPER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block row. call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'NO TRANSPOSE', jb, n-j-jb+1,j-1, -one, a( & 1_${ik}$, j ), lda, a( 1_${ik}$, j+jb ),lda, one, a( j, j+jb ), lda ) call stdlib${ii}$_${ri}$trsm( 'LEFT', 'UPPER', 'TRANSPOSE', 'NON-UNIT',jb, n-j-jb+1, & one, a( j, j ), lda,a( j, j+jb ), lda ) end if end do else ! compute the cholesky factorization a = l*l**t. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_${ri}$syrk( 'LOWER', 'NO TRANSPOSE', jb, j-1, -one,a( j, 1_${ik}$ ), lda, one,& a( j, j ), lda ) call stdlib${ii}$_${ri}$potrf2( 'LOWER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block column. call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', n-j-jb+1, jb,j-1, -one, a( & j+jb, 1_${ik}$ ), lda, a( j, 1_${ik}$ ),lda, one, a( j+jb, j ), lda ) call stdlib${ii}$_${ri}$trsm( 'RIGHT', 'LOWER', 'TRANSPOSE', 'NON-UNIT',n-j-jb+1, jb, & one, a( j, j ), lda,a( j+jb, j ), lda ) end if end do end if end if go to 40 30 continue info = info + j - 1_${ik}$ 40 continue return end subroutine stdlib${ii}$_${ri}$potrf #:endif #:endfor pure module subroutine stdlib${ii}$_cpotrf( uplo, n, a, lda, info ) !! CPOTRF computes the Cholesky factorization of a complex Hermitian !! positive definite matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code. call stdlib${ii}$_cpotrf2( uplo, n, a, lda, info ) else ! use blocked code. if( upper ) then ! compute the cholesky factorization a = u**h *u. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_cherk( 'UPPER', 'CONJUGATE TRANSPOSE', jb, j-1,-one, a( 1_${ik}$, j ), & lda, one, a( j, j ), lda ) call stdlib${ii}$_cpotrf2( 'UPPER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block row. call stdlib${ii}$_cgemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', jb,n-j-jb+1, j-1,& -cone, a( 1_${ik}$, j ), lda,a( 1_${ik}$, j+jb ), lda, cone, a( j, j+jb ),lda ) call stdlib${ii}$_ctrsm( 'LEFT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', jb, & n-j-jb+1, cone, a( j, j ),lda, a( j, j+jb ), lda ) end if end do else ! compute the cholesky factorization a = l*l**h. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_cherk( 'LOWER', 'NO TRANSPOSE', jb, j-1, -one,a( j, 1_${ik}$ ), lda, one,& a( j, j ), lda ) call stdlib${ii}$_cpotrf2( 'LOWER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block column. call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',n-j-jb+1, jb, j-1,& -cone, a( j+jb, 1_${ik}$ ),lda, a( j, 1_${ik}$ ), lda, cone, a( j+jb, j ),lda ) call stdlib${ii}$_ctrsm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','NON-UNIT', n-j-& jb+1, jb, cone, a( j, j ),lda, a( j+jb, j ), lda ) end if end do end if end if go to 40 30 continue info = info + j - 1_${ik}$ 40 continue return end subroutine stdlib${ii}$_cpotrf pure module subroutine stdlib${ii}$_zpotrf( uplo, n, a, lda, info ) !! ZPOTRF computes the Cholesky factorization of a complex Hermitian !! positive definite matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code. call stdlib${ii}$_zpotrf2( uplo, n, a, lda, info ) else ! use blocked code. if( upper ) then ! compute the cholesky factorization a = u**h *u. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_zherk( 'UPPER', 'CONJUGATE TRANSPOSE', jb, j-1,-one, a( 1_${ik}$, j ), & lda, one, a( j, j ), lda ) call stdlib${ii}$_zpotrf2( 'UPPER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block row. call stdlib${ii}$_zgemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', jb,n-j-jb+1, j-1,& -cone, a( 1_${ik}$, j ), lda,a( 1_${ik}$, j+jb ), lda, cone, a( j, j+jb ),lda ) call stdlib${ii}$_ztrsm( 'LEFT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', jb, & n-j-jb+1, cone, a( j, j ),lda, a( j, j+jb ), lda ) end if end do else ! compute the cholesky factorization a = l*l**h. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_zherk( 'LOWER', 'NO TRANSPOSE', jb, j-1, -one,a( j, 1_${ik}$ ), lda, one,& a( j, j ), lda ) call stdlib${ii}$_zpotrf2( 'LOWER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block column. call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',n-j-jb+1, jb, j-1,& -cone, a( j+jb, 1_${ik}$ ),lda, a( j, 1_${ik}$ ), lda, cone, a( j+jb, j ),lda ) call stdlib${ii}$_ztrsm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','NON-UNIT', n-j-& jb+1, jb, cone, a( j, j ),lda, a( j+jb, j ), lda ) end if end do end if end if go to 40 30 continue info = info + j - 1_${ik}$ 40 continue return end subroutine stdlib${ii}$_zpotrf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$potrf( uplo, n, a, lda, info ) !! ZPOTRF: computes the Cholesky factorization of a complex Hermitian !! positive definite matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code. call stdlib${ii}$_${ci}$potrf2( uplo, n, a, lda, info ) else ! use blocked code. if( upper ) then ! compute the cholesky factorization a = u**h *u. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_${ci}$herk( 'UPPER', 'CONJUGATE TRANSPOSE', jb, j-1,-one, a( 1_${ik}$, j ), & lda, one, a( j, j ), lda ) call stdlib${ii}$_${ci}$potrf2( 'UPPER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block row. call stdlib${ii}$_${ci}$gemm( 'CONJUGATE TRANSPOSE', 'NO TRANSPOSE', jb,n-j-jb+1, j-1,& -cone, a( 1_${ik}$, j ), lda,a( 1_${ik}$, j+jb ), lda, cone, a( j, j+jb ),lda ) call stdlib${ii}$_${ci}$trsm( 'LEFT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', jb, & n-j-jb+1, cone, a( j, j ),lda, a( j, j+jb ), lda ) end if end do else ! compute the cholesky factorization a = l*l**h. do j = 1, n, nb ! update and factorize the current diagonal block and test ! for non-positive-definiteness. jb = min( nb, n-j+1 ) call stdlib${ii}$_${ci}$herk( 'LOWER', 'NO TRANSPOSE', jb, j-1, -one,a( j, 1_${ik}$ ), lda, one,& a( j, j ), lda ) call stdlib${ii}$_${ci}$potrf2( 'LOWER', jb, a( j, j ), lda, info ) if( info/=0 )go to 30 if( j+jb<=n ) then ! compute the current block column. call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',n-j-jb+1, jb, j-1,& -cone, a( j+jb, 1_${ik}$ ),lda, a( j, 1_${ik}$ ), lda, cone, a( j+jb, j ),lda ) call stdlib${ii}$_${ci}$trsm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','NON-UNIT', n-j-& jb+1, jb, cone, a( j, j ),lda, a( j+jb, j ), lda ) end if end do end if end if go to 40 30 continue info = info + j - 1_${ik}$ 40 continue return end subroutine stdlib${ii}$_${ci}$potrf #:endif #:endfor pure recursive module subroutine stdlib${ii}$_spotrf2( uplo, n, a, lda, info ) !! SPOTRF2 computes the Cholesky factorization of a real symmetric !! positive definite matrix A using the recursive algorithm. !! The factorization has the form !! A = U**T * U, if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the recursive version of the algorithm. It divides !! the matrix into four submatrices: !! [ A11 | A12 ] where A11 is n1 by n1 and A22 is n2 by n2 !! A = [ -----|----- ] with n1 = n/2 !! [ A21 | A22 ] n2 = n-n1 !! The subroutine calls itself to factor A11. Update and scale A21 !! or A12, update A22 then call itself to factor A22. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: n1, n2, iinfo ! Intrinsic Functions ! Executable Statements ! test the input parameters info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda=n ) then ! use unblocked code call stdlib${ii}$_spstf2( uplo, n, a( 1_${ik}$, 1_${ik}$ ), lda, piv, rank, tol, work,info ) go to 200 else ! initialize piv do i = 1, n piv( i ) = i end do ! compute stopping value pvt = 1_${ik}$ ajj = a( pvt, pvt ) do i = 2, n if( a( i, i )>ajj ) then pvt = i ajj = a( pvt, pvt ) end if end do if( ajj<=zero.or.stdlib${ii}$_sisnan( ajj ) ) then rank = 0_${ik}$ info = 1_${ik}$ go to 200 end if ! compute stopping value if not supplied if( tolk ) then work( i ) = work( i ) + a( j-1, i )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=sstop.or.stdlib${ii}$_sisnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_sswap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvtk ) then work( i ) = work( i ) + a( i, j-1 )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=sstop.or.stdlib${ii}$_sisnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_sswap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvt=n ) then ! use unblocked code call stdlib${ii}$_dpstf2( uplo, n, a( 1_${ik}$, 1_${ik}$ ), lda, piv, rank, tol, work,info ) go to 200 else ! initialize piv do i = 1, n piv( i ) = i end do ! compute stopping value pvt = 1_${ik}$ ajj = a( pvt, pvt ) do i = 2, n if( a( i, i )>ajj ) then pvt = i ajj = a( pvt, pvt ) end if end do if( ajj<=zero.or.stdlib${ii}$_disnan( ajj ) ) then rank = 0_${ik}$ info = 1_${ik}$ go to 200 end if ! compute stopping value if not supplied if( tolk ) then work( i ) = work( i ) + a( j-1, i )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_disnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_dswap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvtk ) then work( i ) = work( i ) + a( i, j-1 )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_disnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_dswap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvt=n ) then ! use unblocked code call stdlib${ii}$_${ri}$pstf2( uplo, n, a( 1_${ik}$, 1_${ik}$ ), lda, piv, rank, tol, work,info ) go to 200 else ! initialize piv do i = 1, n piv( i ) = i end do ! compute stopping value pvt = 1_${ik}$ ajj = a( pvt, pvt ) do i = 2, n if( a( i, i )>ajj ) then pvt = i ajj = a( pvt, pvt ) end if end do if( ajj<=zero.or.stdlib${ii}$_${ri}$isnan( ajj ) ) then rank = 0_${ik}$ info = 1_${ik}$ go to 200 end if ! compute stopping value if not supplied if( tolk ) then work( i ) = work( i ) + a( j-1, i )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_${ri}$isnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_${ri}$swap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvtk ) then work( i ) = work( i ) + a( i, j-1 )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_${ri}$isnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_${ri}$swap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvt=n ) then ! use unblocked code call stdlib${ii}$_cpstf2( uplo, n, a( 1_${ik}$, 1_${ik}$ ), lda, piv, rank, tol, work,info ) go to 230 else ! initialize piv do i = 1, n piv( i ) = i end do ! compute stopping value do i = 1, n work( i ) = real( a( i, i ),KIND=sp) end do pvt = maxloc( work( 1_${ik}$:n ), 1_${ik}$ ) ajj = real( a( pvt, pvt ),KIND=sp) if( ajj<=zero.or.stdlib${ii}$_sisnan( ajj ) ) then rank = 0_${ik}$ info = 1_${ik}$ go to 230 end if ! compute stopping value if not supplied if( tolk ) then work( i ) = work( i ) +real( conjg( a( j-1, i ) )*a( j-1, i ),& KIND=sp) end if work( n+i ) = real( a( i, i ),KIND=sp) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=sstop.or.stdlib${ii}$_sisnan( ajj ) ) then a( j, j ) = ajj go to 220 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_cswap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvtk ) then work( i ) = work( i ) +real( conjg( a( i, j-1 ) )*a( i, j-1 ),& KIND=sp) end if work( n+i ) = real( a( i, i ),KIND=sp) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=sstop.or.stdlib${ii}$_sisnan( ajj ) ) then a( j, j ) = ajj go to 220 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_cswap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvt=n ) then ! use unblocked code call stdlib${ii}$_zpstf2( uplo, n, a( 1_${ik}$, 1_${ik}$ ), lda, piv, rank, tol, work,info ) go to 230 else ! initialize piv do i = 1, n piv( i ) = i end do ! compute stopping value do i = 1, n work( i ) = real( a( i, i ),KIND=dp) end do pvt = maxloc( work( 1_${ik}$:n ), 1_${ik}$ ) ajj = real( a( pvt, pvt ),KIND=dp) if( ajj<=zero.or.stdlib${ii}$_disnan( ajj ) ) then rank = 0_${ik}$ info = 1_${ik}$ go to 230 end if ! compute stopping value if not supplied if( tolk ) then work( i ) = work( i ) +real( conjg( a( j-1, i ) )*a( j-1, i ),& KIND=dp) end if work( n+i ) = real( a( i, i ),KIND=dp) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_disnan( ajj ) ) then a( j, j ) = ajj go to 220 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_zswap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvtk ) then work( i ) = work( i ) +real( conjg( a( i, j-1 ) )*a( i, j-1 ),& KIND=dp) end if work( n+i ) = real( a( i, i ),KIND=dp) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_disnan( ajj ) ) then a( j, j ) = ajj go to 220 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_zswap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvt=n ) then ! use unblocked code call stdlib${ii}$_${ci}$pstf2( uplo, n, a( 1_${ik}$, 1_${ik}$ ), lda, piv, rank, tol, work,info ) go to 230 else ! initialize piv do i = 1, n piv( i ) = i end do ! compute stopping value do i = 1, n work( i ) = real( a( i, i ),KIND=${ck}$) end do pvt = maxloc( work( 1_${ik}$:n ), 1_${ik}$ ) ajj = real( a( pvt, pvt ),KIND=${ck}$) if( ajj<=zero.or.stdlib${ii}$_${c2ri(ci)}$isnan( ajj ) ) then rank = 0_${ik}$ info = 1_${ik}$ go to 230 end if ! compute stopping value if not supplied if( tolk ) then work( i ) = work( i ) +real( conjg( a( j-1, i ) )*a( j-1, i ),& KIND=${ck}$) end if work( n+i ) = real( a( i, i ),KIND=${ck}$) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_${c2ri(ci)}$isnan( ajj ) ) then a( j, j ) = ajj go to 220 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_${ci}$swap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvtk ) then work( i ) = work( i ) +real( conjg( a( i, j-1 ) )*a( i, j-1 ),& KIND=${ck}$) end if work( n+i ) = real( a( i, i ),KIND=${ck}$) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_${c2ri(ci)}$isnan( ajj ) ) then a( j, j ) = ajj go to 220 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_${ci}$swap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvtajj ) then pvt = i ajj = a( pvt, pvt ) end if end do if( ajj<=zero.or.stdlib${ii}$_sisnan( ajj ) ) then rank = 0_${ik}$ info = 1_${ik}$ go to 170 end if ! compute stopping value if not supplied if( tol1_${ik}$ ) then work( i ) = work( i ) + a( j-1, i )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=sstop.or.stdlib${ii}$_sisnan( ajj ) ) then a( j, j ) = ajj go to 160 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_sswap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvt1_${ik}$ ) then work( i ) = work( i ) + a( i, j-1 )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=sstop.or.stdlib${ii}$_sisnan( ajj ) ) then a( j, j ) = ajj go to 160 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_sswap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvtajj ) then pvt = i ajj = a( pvt, pvt ) end if end do if( ajj<=zero.or.stdlib${ii}$_disnan( ajj ) ) then rank = 0_${ik}$ info = 1_${ik}$ go to 170 end if ! compute stopping value if not supplied if( tol1_${ik}$ ) then work( i ) = work( i ) + a( j-1, i )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_disnan( ajj ) ) then a( j, j ) = ajj go to 160 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_dswap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvt1_${ik}$ ) then work( i ) = work( i ) + a( i, j-1 )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_disnan( ajj ) ) then a( j, j ) = ajj go to 160 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_dswap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvtajj ) then pvt = i ajj = a( pvt, pvt ) end if end do if( ajj<=zero.or.stdlib${ii}$_${ri}$isnan( ajj ) ) then rank = 0_${ik}$ info = 1_${ik}$ go to 170 end if ! compute stopping value if not supplied if( tol1_${ik}$ ) then work( i ) = work( i ) + a( j-1, i )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_${ri}$isnan( ajj ) ) then a( j, j ) = ajj go to 160 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_${ri}$swap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvt1_${ik}$ ) then work( i ) = work( i ) + a( i, j-1 )**2_${ik}$ end if work( n+i ) = a( i, i ) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_${ri}$isnan( ajj ) ) then a( j, j ) = ajj go to 160 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_${ri}$swap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvt1_${ik}$ ) then work( i ) = work( i ) +real( conjg( a( j-1, i ) )*a( j-1, i ),KIND=sp) end if work( n+i ) = real( a( i, i ),KIND=sp) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=sstop.or.stdlib${ii}$_sisnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_cswap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvt1_${ik}$ ) then work( i ) = work( i ) +real( conjg( a( i, j-1 ) )*a( i, j-1 ),KIND=sp) end if work( n+i ) = real( a( i, i ),KIND=sp) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=sstop.or.stdlib${ii}$_sisnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_cswap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvt1_${ik}$ ) then work( i ) = work( i ) +real( conjg( a( j-1, i ) )*a( j-1, i ),KIND=dp) end if work( n+i ) = real( a( i, i ),KIND=dp) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_disnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_zswap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvt1_${ik}$ ) then work( i ) = work( i ) +real( conjg( a( i, j-1 ) )*a( i, j-1 ),KIND=dp) end if work( n+i ) = real( a( i, i ),KIND=dp) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_disnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_zswap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvt1_${ik}$ ) then work( i ) = work( i ) +real( conjg( a( j-1, i ) )*a( j-1, i ),KIND=${ck}$) end if work( n+i ) = real( a( i, i ),KIND=${ck}$) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_${c2ri(ci)}$isnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_${ci}$swap( j-1, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, pvt ), 1_${ik}$ ) if( pvt1_${ik}$ ) then work( i ) = work( i ) +real( conjg( a( i, j-1 ) )*a( i, j-1 ),KIND=${ck}$) end if work( n+i ) = real( a( i, i ),KIND=${ck}$) - work( i ) end do if( j>1_${ik}$ ) then itemp = maxloc( work( (n+j):(2_${ik}$*n) ), 1_${ik}$ ) pvt = itemp + j - 1_${ik}$ ajj = work( n+pvt ) if( ajj<=dstop.or.stdlib${ii}$_${c2ri(ci)}$isnan( ajj ) ) then a( j, j ) = ajj go to 190 end if end if if( j/=pvt ) then ! pivot ok, so can now swap pivot rows and columns a( pvt, pvt ) = a( j, j ) call stdlib${ii}$_${ci}$swap( j-1, a( j, 1_${ik}$ ), lda, a( pvt, 1_${ik}$ ), lda ) if( pvt0 )return ! form inv(u) * inv(u)**t or inv(l)**t * inv(l). call stdlib${ii}$_slauum( uplo, n, a, lda, info ) return end subroutine stdlib${ii}$_spotri pure module subroutine stdlib${ii}$_dpotri( uplo, n, a, lda, info ) !! DPOTRI computes the inverse of a real symmetric positive definite !! matrix A using the Cholesky factorization A = U**T*U or A = L*L**T !! computed by DPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 )return ! form inv(u) * inv(u)**t or inv(l)**t * inv(l). call stdlib${ii}$_dlauum( uplo, n, a, lda, info ) return end subroutine stdlib${ii}$_dpotri #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$potri( uplo, n, a, lda, info ) !! DPOTRI: computes the inverse of a real symmetric positive definite !! matrix A using the Cholesky factorization A = U**T*U or A = L*L**T !! computed by DPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 )return ! form inv(u) * inv(u)**t or inv(l)**t * inv(l). call stdlib${ii}$_${ri}$lauum( uplo, n, a, lda, info ) return end subroutine stdlib${ii}$_${ri}$potri #:endif #:endfor pure module subroutine stdlib${ii}$_cpotri( uplo, n, a, lda, info ) !! CPOTRI computes the inverse of a complex Hermitian positive definite !! matrix A using the Cholesky factorization A = U**H*U or A = L*L**H !! computed by CPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*) ! ===================================================================== ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 )return ! form inv(u) * inv(u)**h or inv(l)**h * inv(l). call stdlib${ii}$_clauum( uplo, n, a, lda, info ) return end subroutine stdlib${ii}$_cpotri pure module subroutine stdlib${ii}$_zpotri( uplo, n, a, lda, info ) !! ZPOTRI computes the inverse of a complex Hermitian positive definite !! matrix A using the Cholesky factorization A = U**H*U or A = L*L**H !! computed by ZPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 )return ! form inv(u) * inv(u)**h or inv(l)**h * inv(l). call stdlib${ii}$_zlauum( uplo, n, a, lda, info ) return end subroutine stdlib${ii}$_zpotri #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$potri( uplo, n, a, lda, info ) !! ZPOTRI: computes the inverse of a complex Hermitian positive definite !! matrix A using the Cholesky factorization A = U**H*U or A = L*L**H !! computed by ZPOTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( .not.stdlib_lsame( uplo, 'U' ) .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( lda0 )return ! form inv(u) * inv(u)**h or inv(l)**h * inv(l). call stdlib${ii}$_${ci}$lauum( uplo, n, a, lda, info ) return end subroutine stdlib${ii}$_${ci}$potri #:endif #:endfor pure module subroutine stdlib${ii}$_sporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x,ldx, ferr, berr, & !! SPORFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric positive definite, !! and provides error bounds and backward error estimates for the !! solution. work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) real(sp), intent(out) :: berr(*), ferr(*), work(*) real(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_spotrs( uplo, n, 1_${ik}$, af, ldaf, work( n+1 ), n, info ) call stdlib${ii}$_saxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_slacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_slacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_spotrs( uplo, n, 1_${ik}$, af, ldaf, work( n+1 ), n, info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_spotrs( uplo, n, 1_${ik}$, af, ldaf, work( n+1 ), n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_sporfs pure module subroutine stdlib${ii}$_dporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x,ldx, ferr, berr, & !! DPORFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric positive definite, !! and provides error bounds and backward error estimates for the !! solution. work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) real(dp), intent(out) :: berr(*), ferr(*), work(*) real(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_dpotrs( uplo, n, 1_${ik}$, af, ldaf, work( n+1 ), n, info ) call stdlib${ii}$_daxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_dlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_dlacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_dpotrs( uplo, n, 1_${ik}$, af, ldaf, work( n+1 ), n, info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_dpotrs( uplo, n, 1_${ik}$, af, ldaf, work( n+1 ), n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_dporfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$porfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x,ldx, ferr, berr, & !! DPORFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric positive definite, !! and provides error bounds and backward error estimates for the !! solution. work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) real(${rk}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(${rk}$) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ri}$potrs( uplo, n, 1_${ik}$, af, ldaf, work( n+1 ), n, info ) call stdlib${ii}$_${ri}$axpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ri}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ri}$lacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_${ri}$potrs( uplo, n, 1_${ik}$, af, ldaf, work( n+1 ), n, info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_${ri}$potrs( uplo, n, 1_${ik}$, af, ldaf, work( n+1 ), n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ri}$porfs #:endif #:endfor pure module subroutine stdlib${ii}$_cporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x,ldx, ferr, berr, & !! CPORFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite, !! and provides error bounds and backward error estimates for the !! solution. work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) ! ==================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_cpotrs( uplo, n, 1_${ik}$, af, ldaf, work, n, info ) call stdlib${ii}$_caxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_cpotrs( uplo, n, 1_${ik}$, af, ldaf, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_cpotrs( uplo, n, 1_${ik}$, af, ldaf, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_cporfs pure module subroutine stdlib${ii}$_zporfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x,ldx, ferr, berr, & !! ZPORFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite, !! and provides error bounds and backward error estimates for the !! solution. work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) ! ==================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_zpotrs( uplo, n, 1_${ik}$, af, ldaf, work, n, info ) call stdlib${ii}$_zaxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_zpotrs( uplo, n, 1_${ik}$, af, ldaf, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_zpotrs( uplo, n, 1_${ik}$, af, ldaf, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_zporfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$porfs( uplo, n, nrhs, a, lda, af, ldaf, b, ldb, x,ldx, ferr, berr, & !! ZPORFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite, !! and provides error bounds and backward error estimates for the !! solution. work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldaf, ldb, ldx, n, nrhs ! Array Arguments real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ==================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldasafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ci}$potrs( uplo, n, 1_${ik}$, af, ldaf, work, n, info ) call stdlib${ii}$_${ci}$axpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_${ci}$potrs( uplo, n, 1_${ik}$, af, ldaf, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$potrs( uplo, n, 1_${ik}$, af, ldaf, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ci}$porfs #:endif #:endfor pure module subroutine stdlib${ii}$_spoequ( n, a, lda, s, scond, amax, info ) !! SPOEQU computes row and column scalings intended to equilibrate a !! symmetric positive definite matrix A and reduce its condition number !! (with respect to the two-norm). S contains the scale factors, !! S(i) = 1/sqrt(A(i,i)), chosen so that the scaled matrix B with !! elements B(i,j) = S(i)*A(i,j)*S(j) has ones on the diagonal. This !! choice of S puts the condition number of B within a factor N of the !! smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, n real(sp), intent(out) :: amax, scond ! Array Arguments real(sp), intent(in) :: a(lda,*) real(sp), intent(out) :: s(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i real(sp) :: smin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( lda=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. do j = 1, n cj = s( j ) do i = 1, j - 1 a( i, j ) = cj*s( i )*a( i, j ) end do a( j, j ) = cj*cj*real( a( j, j ),KIND=sp) end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) a( j, j ) = cj*cj*real( a( j, j ),KIND=sp) do i = j + 1, n a( i, j ) = cj*s( i )*a( i, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_claqhe pure module subroutine stdlib${ii}$_zlaqhe( uplo, n, a, lda, s, scond, amax, equed ) !! ZLAQHE equilibrates a Hermitian matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, n real(dp), intent(in) :: amax, scond ! Array Arguments real(dp), intent(in) :: s(*) complex(dp), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j real(dp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. do j = 1, n cj = s( j ) do i = 1, j - 1 a( i, j ) = cj*s( i )*a( i, j ) end do a( j, j ) = cj*cj*real( a( j, j ),KIND=dp) end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) a( j, j ) = cj*cj*real( a( j, j ),KIND=dp) do i = j + 1, n a( i, j ) = cj*s( i )*a( i, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_zlaqhe #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqhe( uplo, n, a, lda, s, scond, amax, equed ) !! ZLAQHE: equilibrates a Hermitian matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: lda, n real(${ck}$), intent(in) :: amax, scond ! Array Arguments real(${ck}$), intent(in) :: s(*) complex(${ck}$), intent(inout) :: a(lda,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: thresh = 0.1e+0_${ck}$ ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. do j = 1, n cj = s( j ) do i = 1, j - 1 a( i, j ) = cj*s( i )*a( i, j ) end do a( j, j ) = cj*cj*real( a( j, j ),KIND=${ck}$) end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) a( j, j ) = cj*cj*real( a( j, j ),KIND=${ck}$) do i = j + 1, n a( i, j ) = cj*s( i )*a( i, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_${ci}$laqhe #:endif #:endfor real(sp) module function stdlib${ii}$_sla_porcond( uplo, n, a, lda, af, ldaf, cmode, c,info, work, iwork ) !! SLA_PORCOND Estimates the Skeel condition number of op(A) * op2(C) !! where op2 is determined by CMODE as follows !! CMODE = 1 op2(C) = C !! CMODE = 0 op2(C) = I !! CMODE = -1 op2(C) = inv(C) !! The Skeel condition number cond(A) = norminf( |inv(A)||A| ) !! is computed by computing scaling factors R such that !! diag(R)*A*op2(C) is row equilibrated and computing the standard !! infinity-norm condition number. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, ldaf, cmode integer(${ik}$), intent(out) :: info real(sp), intent(in) :: a(lda,*), af(ldaf,*), c(*) real(sp), intent(out) :: work(*) ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: kase, i, j real(sp) :: ainvnm, tmp logical(lk) :: up ! Array Arguments integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements stdlib${ii}$_sla_porcond = zero info = 0_${ik}$ if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SLA_PORCOND', -info ) return end if if( n==0_${ik}$ ) then stdlib${ii}$_sla_porcond = one return end if up = .false. if ( stdlib_lsame( uplo, 'U' ) ) up = .true. ! compute the equilibration matrix r such that ! inv(r)*a*c has unit 1-norm. if ( up ) then do i = 1, n tmp = zero if ( cmode == 1_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( j, i ) * c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( i, j ) * c( j ) ) end do else if ( cmode == 0_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( j, i ) ) end do do j = i+1, n tmp = tmp + abs( a( i, j ) ) end do else do j = 1, i tmp = tmp + abs( a( j ,i ) / c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( i, j ) / c( j ) ) end do end if work( 2_${ik}$*n+i ) = tmp end do else do i = 1, n tmp = zero if ( cmode == 1_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( i, j ) * c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( j, i ) * c( j ) ) end do else if ( cmode == 0_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( i, j ) ) end do do j = i+1, n tmp = tmp + abs( a( j, i ) ) end do else do j = 1, i tmp = tmp + abs( a( i, j ) / c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( j, i ) / c( j ) ) end do end if work( 2_${ik}$*n+i ) = tmp end do endif ! estimate the norm of inv(op(a)). ainvnm = zero kase = 0_${ik}$ 10 continue call stdlib${ii}$_slacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==2_${ik}$ ) then ! multiply by r. do i = 1, n work( i ) = work( i ) * work( 2_${ik}$*n+i ) end do if (up) then call stdlib${ii}$_spotrs( 'UPPER', n, 1_${ik}$, af, ldaf, work, n, info ) else call stdlib${ii}$_spotrs( 'LOWER', n, 1_${ik}$, af, ldaf, work, n, info ) endif ! multiply by inv(c). if ( cmode == 1_${ik}$ ) then do i = 1, n work( i ) = work( i ) / c( i ) end do else if ( cmode == -1_${ik}$ ) then do i = 1, n work( i ) = work( i ) * c( i ) end do end if else ! multiply by inv(c**t). if ( cmode == 1_${ik}$ ) then do i = 1, n work( i ) = work( i ) / c( i ) end do else if ( cmode == -1_${ik}$ ) then do i = 1, n work( i ) = work( i ) * c( i ) end do end if if ( up ) then call stdlib${ii}$_spotrs( 'UPPER', n, 1_${ik}$, af, ldaf, work, n, info ) else call stdlib${ii}$_spotrs( 'LOWER', n, 1_${ik}$, af, ldaf, work, n, info ) endif ! multiply by r. do i = 1, n work( i ) = work( i ) * work( 2_${ik}$*n+i ) end do end if go to 10 end if ! compute the estimate of the reciprocal condition number. if( ainvnm /= 0.0_sp )stdlib${ii}$_sla_porcond = ( one / ainvnm ) return end function stdlib${ii}$_sla_porcond real(dp) module function stdlib${ii}$_dla_porcond( uplo, n, a, lda, af, ldaf,cmode, c, info, work,iwork ) !! DLA_PORCOND Estimates the Skeel condition number of op(A) * op2(C) !! where op2 is determined by CMODE as follows !! CMODE = 1 op2(C) = C !! CMODE = 0 op2(C) = I !! CMODE = -1 op2(C) = inv(C) !! The Skeel condition number cond(A) = norminf( |inv(A)||A| ) !! is computed by computing scaling factors R such that !! diag(R)*A*op2(C) is row equilibrated and computing the standard !! infinity-norm condition number. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, ldaf, cmode integer(${ik}$), intent(out) :: info real(dp), intent(in) :: a(lda,*), af(ldaf,*), c(*) real(dp), intent(out) :: work(*) ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: kase, i, j real(dp) :: ainvnm, tmp logical(lk) :: up ! Array Arguments integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements stdlib${ii}$_dla_porcond = zero info = 0_${ik}$ if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLA_PORCOND', -info ) return end if if( n==0_${ik}$ ) then stdlib${ii}$_dla_porcond = one return end if up = .false. if ( stdlib_lsame( uplo, 'U' ) ) up = .true. ! compute the equilibration matrix r such that ! inv(r)*a*c has unit 1-norm. if ( up ) then do i = 1, n tmp = zero if ( cmode == 1_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( j, i ) * c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( i, j ) * c( j ) ) end do else if ( cmode == 0_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( j, i ) ) end do do j = i+1, n tmp = tmp + abs( a( i, j ) ) end do else do j = 1, i tmp = tmp + abs( a( j ,i ) / c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( i, j ) / c( j ) ) end do end if work( 2_${ik}$*n+i ) = tmp end do else do i = 1, n tmp = zero if ( cmode == 1_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( i, j ) * c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( j, i ) * c( j ) ) end do else if ( cmode == 0_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( i, j ) ) end do do j = i+1, n tmp = tmp + abs( a( j, i ) ) end do else do j = 1, i tmp = tmp + abs( a( i, j ) / c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( j, i ) / c( j ) ) end do end if work( 2_${ik}$*n+i ) = tmp end do endif ! estimate the norm of inv(op(a)). ainvnm = zero kase = 0_${ik}$ 10 continue call stdlib${ii}$_dlacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==2_${ik}$ ) then ! multiply by r. do i = 1, n work( i ) = work( i ) * work( 2_${ik}$*n+i ) end do if (up) then call stdlib${ii}$_dpotrs( 'UPPER', n, 1_${ik}$, af, ldaf, work, n, info ) else call stdlib${ii}$_dpotrs( 'LOWER', n, 1_${ik}$, af, ldaf, work, n, info ) endif ! multiply by inv(c). if ( cmode == 1_${ik}$ ) then do i = 1, n work( i ) = work( i ) / c( i ) end do else if ( cmode == -1_${ik}$ ) then do i = 1, n work( i ) = work( i ) * c( i ) end do end if else ! multiply by inv(c**t). if ( cmode == 1_${ik}$ ) then do i = 1, n work( i ) = work( i ) / c( i ) end do else if ( cmode == -1_${ik}$ ) then do i = 1, n work( i ) = work( i ) * c( i ) end do end if if ( up ) then call stdlib${ii}$_dpotrs( 'UPPER', n, 1_${ik}$, af, ldaf, work, n, info ) else call stdlib${ii}$_dpotrs( 'LOWER', n, 1_${ik}$, af, ldaf, work, n, info ) endif ! multiply by r. do i = 1, n work( i ) = work( i ) * work( 2_${ik}$*n+i ) end do end if go to 10 end if ! compute the estimate of the reciprocal condition number. if( ainvnm /= zero )stdlib${ii}$_dla_porcond = ( one / ainvnm ) return end function stdlib${ii}$_dla_porcond #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$la_porcond( uplo, n, a, lda, af, ldaf,cmode, c, info, work,iwork ) !! DLA_PORCOND: Estimates the Skeel condition number of op(A) * op2(C) !! where op2 is determined by CMODE as follows !! CMODE = 1 op2(C) = C !! CMODE = 0 op2(C) = I !! CMODE = -1 op2(C) = inv(C) !! The Skeel condition number cond(A) = norminf( |inv(A)||A| ) !! is computed by computing scaling factors R such that !! diag(R)*A*op2(C) is row equilibrated and computing the standard !! infinity-norm condition number. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: n, lda, ldaf, cmode integer(${ik}$), intent(out) :: info real(${rk}$), intent(in) :: a(lda,*), af(ldaf,*), c(*) real(${rk}$), intent(out) :: work(*) ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: kase, i, j real(${rk}$) :: ainvnm, tmp logical(lk) :: up ! Array Arguments integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements stdlib${ii}$_${ri}$la_porcond = zero info = 0_${ik}$ if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLA_PORCOND', -info ) return end if if( n==0_${ik}$ ) then stdlib${ii}$_${ri}$la_porcond = one return end if up = .false. if ( stdlib_lsame( uplo, 'U' ) ) up = .true. ! compute the equilibration matrix r such that ! inv(r)*a*c has unit 1-norm. if ( up ) then do i = 1, n tmp = zero if ( cmode == 1_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( j, i ) * c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( i, j ) * c( j ) ) end do else if ( cmode == 0_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( j, i ) ) end do do j = i+1, n tmp = tmp + abs( a( i, j ) ) end do else do j = 1, i tmp = tmp + abs( a( j ,i ) / c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( i, j ) / c( j ) ) end do end if work( 2_${ik}$*n+i ) = tmp end do else do i = 1, n tmp = zero if ( cmode == 1_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( i, j ) * c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( j, i ) * c( j ) ) end do else if ( cmode == 0_${ik}$ ) then do j = 1, i tmp = tmp + abs( a( i, j ) ) end do do j = i+1, n tmp = tmp + abs( a( j, i ) ) end do else do j = 1, i tmp = tmp + abs( a( i, j ) / c( j ) ) end do do j = i+1, n tmp = tmp + abs( a( j, i ) / c( j ) ) end do end if work( 2_${ik}$*n+i ) = tmp end do endif ! estimate the norm of inv(op(a)). ainvnm = zero kase = 0_${ik}$ 10 continue call stdlib${ii}$_${ri}$lacn2( n, work( n+1 ), work, iwork, ainvnm, kase, isave ) if( kase/=0_${ik}$ ) then if( kase==2_${ik}$ ) then ! multiply by r. do i = 1, n work( i ) = work( i ) * work( 2_${ik}$*n+i ) end do if (up) then call stdlib${ii}$_${ri}$potrs( 'UPPER', n, 1_${ik}$, af, ldaf, work, n, info ) else call stdlib${ii}$_${ri}$potrs( 'LOWER', n, 1_${ik}$, af, ldaf, work, n, info ) endif ! multiply by inv(c). if ( cmode == 1_${ik}$ ) then do i = 1, n work( i ) = work( i ) / c( i ) end do else if ( cmode == -1_${ik}$ ) then do i = 1, n work( i ) = work( i ) * c( i ) end do end if else ! multiply by inv(c**t). if ( cmode == 1_${ik}$ ) then do i = 1, n work( i ) = work( i ) / c( i ) end do else if ( cmode == -1_${ik}$ ) then do i = 1, n work( i ) = work( i ) * c( i ) end do end if if ( up ) then call stdlib${ii}$_${ri}$potrs( 'UPPER', n, 1_${ik}$, af, ldaf, work, n, info ) else call stdlib${ii}$_${ri}$potrs( 'LOWER', n, 1_${ik}$, af, ldaf, work, n, info ) endif ! multiply by r. do i = 1, n work( i ) = work( i ) * work( 2_${ik}$*n+i ) end do end if go to 10 end if ! compute the estimate of the reciprocal condition number. if( ainvnm /= zero )stdlib${ii}$_${ri}$la_porcond = ( one / ainvnm ) return end function stdlib${ii}$_${ri}$la_porcond #:endif #:endfor real(sp) module function stdlib${ii}$_sla_porpvgrw( uplo, ncols, a, lda, af, ldaf, work ) !! SLA_PORPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: ncols, lda, ldaf ! Array Arguments real(sp), intent(in) :: a(lda,*), af(ldaf,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: amax, umax, rpvgrw logical(lk) :: upper ! Intrinsic Functions ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) ! stdlib${ii}$_spotrf will have factored only the ncolsxncols leading minor, so ! we restrict the growth search to that minor and use only the first ! 2*ncols workspace entries. rpvgrw = one do i = 1, 2*ncols work( i ) = zero end do ! find the max magnitude entry of each column. if ( upper ) then do j = 1, ncols do i = 1, j work( ncols+j ) =max( abs( a( i, j ) ), work( ncols+j ) ) end do end do else do j = 1, ncols do i = j, ncols work( ncols+j ) =max( abs( a( i, j ) ), work( ncols+j ) ) end do end do end if ! now find the max magnitude entry of each column of the factor in ! af. no pivoting, so no permutations. if ( stdlib_lsame( 'UPPER', uplo ) ) then do j = 1, ncols do i = 1, j work( j ) = max( abs( af( i, j ) ), work( j ) ) end do end do else do j = 1, ncols do i = j, ncols work( j ) = max( abs( af( i, j ) ), work( j ) ) end do end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( stdlib_lsame( 'UPPER', uplo ) ) then do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_sla_porpvgrw = rpvgrw end function stdlib${ii}$_sla_porpvgrw real(dp) module function stdlib${ii}$_dla_porpvgrw( uplo, ncols, a, lda, af,ldaf, work ) !! DLA_PORPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: ncols, lda, ldaf ! Array Arguments real(dp), intent(in) :: a(lda,*), af(ldaf,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: amax, umax, rpvgrw logical(lk) :: upper ! Intrinsic Functions ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) ! stdlib${ii}$_dpotrf will have factored only the ncolsxncols leading minor, so ! we restrict the growth search to that minor and use only the first ! 2*ncols workspace entries. rpvgrw = one do i = 1, 2*ncols work( i ) = zero end do ! find the max magnitude entry of each column. if ( upper ) then do j = 1, ncols do i = 1, j work( ncols+j ) =max( abs( a( i, j ) ), work( ncols+j ) ) end do end do else do j = 1, ncols do i = j, ncols work( ncols+j ) =max( abs( a( i, j ) ), work( ncols+j ) ) end do end do end if ! now find the max magnitude entry of each column of the factor in ! af. no pivoting, so no permutations. if ( stdlib_lsame( 'UPPER', uplo ) ) then do j = 1, ncols do i = 1, j work( j ) = max( abs( af( i, j ) ), work( j ) ) end do end do else do j = 1, ncols do i = j, ncols work( j ) = max( abs( af( i, j ) ), work( j ) ) end do end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( stdlib_lsame( 'UPPER', uplo ) ) then do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_dla_porpvgrw = rpvgrw end function stdlib${ii}$_dla_porpvgrw #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] real(${rk}$) module function stdlib${ii}$_${ri}$la_porpvgrw( uplo, ncols, a, lda, af,ldaf, work ) !! DLA_PORPVGRW: computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: ncols, lda, ldaf ! Array Arguments real(${rk}$), intent(in) :: a(lda,*), af(ldaf,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${rk}$) :: amax, umax, rpvgrw logical(lk) :: upper ! Intrinsic Functions ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) ! stdlib${ii}$_${ri}$potrf will have factored only the ncolsxncols leading minor, so ! we restrict the growth search to that minor and use only the first ! 2*ncols workspace entries. rpvgrw = one do i = 1, 2*ncols work( i ) = zero end do ! find the max magnitude entry of each column. if ( upper ) then do j = 1, ncols do i = 1, j work( ncols+j ) =max( abs( a( i, j ) ), work( ncols+j ) ) end do end do else do j = 1, ncols do i = j, ncols work( ncols+j ) =max( abs( a( i, j ) ), work( ncols+j ) ) end do end do end if ! now find the max magnitude entry of each column of the factor in ! af. no pivoting, so no permutations. if ( stdlib_lsame( 'UPPER', uplo ) ) then do j = 1, ncols do i = 1, j work( j ) = max( abs( af( i, j ) ), work( j ) ) end do end do else do j = 1, ncols do i = j, ncols work( j ) = max( abs( af( i, j ) ), work( j ) ) end do end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( stdlib_lsame( 'UPPER', uplo ) ) then do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_${ri}$la_porpvgrw = rpvgrw end function stdlib${ii}$_${ri}$la_porpvgrw #:endif #:endfor real(sp) module function stdlib${ii}$_cla_porpvgrw( uplo, ncols, a, lda, af, ldaf, work ) !! CLA_PORPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: ncols, lda, ldaf ! Array Arguments complex(sp), intent(in) :: a(lda,*), af(ldaf,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(sp) :: amax, umax, rpvgrw logical(lk) :: upper complex(sp) :: zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) ! stdlib${ii}$_spotrf will have factored only the ncolsxncols leading minor, so ! we restrict the growth search to that minor and use only the first ! 2*ncols workspace entries. rpvgrw = one do i = 1, 2*ncols work( i ) = zero end do ! find the max magnitude entry of each column. if ( upper ) then do j = 1, ncols do i = 1, j work( ncols+j ) =max( cabs1( a( i, j ) ), work( ncols+j ) ) end do end do else do j = 1, ncols do i = j, ncols work( ncols+j ) =max( cabs1( a( i, j ) ), work( ncols+j ) ) end do end do end if ! now find the max magnitude entry of each column of the factor in ! af. no pivoting, so no permutations. if ( stdlib_lsame( 'UPPER', uplo ) ) then do j = 1, ncols do i = 1, j work( j ) = max( cabs1( af( i, j ) ), work( j ) ) end do end do else do j = 1, ncols do i = j, ncols work( j ) = max( cabs1( af( i, j ) ), work( j ) ) end do end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( stdlib_lsame( 'UPPER', uplo ) ) then do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= 0.0_sp ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_cla_porpvgrw = rpvgrw end function stdlib${ii}$_cla_porpvgrw real(dp) module function stdlib${ii}$_zla_porpvgrw( uplo, ncols, a, lda, af,ldaf, work ) !! ZLA_PORPVGRW computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: ncols, lda, ldaf ! Array Arguments complex(dp), intent(in) :: a(lda,*), af(ldaf,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(dp) :: amax, umax, rpvgrw logical(lk) :: upper complex(dp) :: zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) ! stdlib${ii}$_dpotrf will have factored only the ncolsxncols leading minor, so ! we restrict the growth search to that minor and use only the first ! 2*ncols workspace entries. rpvgrw = one do i = 1, 2*ncols work( i ) = zero end do ! find the max magnitude entry of each column. if ( upper ) then do j = 1, ncols do i = 1, j work( ncols+j ) =max( cabs1( a( i, j ) ), work( ncols+j ) ) end do end do else do j = 1, ncols do i = j, ncols work( ncols+j ) =max( cabs1( a( i, j ) ), work( ncols+j ) ) end do end do end if ! now find the max magnitude entry of each column of the factor in ! af. no pivoting, so no permutations. if ( stdlib_lsame( 'UPPER', uplo ) ) then do j = 1, ncols do i = 1, j work( j ) = max( cabs1( af( i, j ) ), work( j ) ) end do end do else do j = 1, ncols do i = j, ncols work( j ) = max( cabs1( af( i, j ) ), work( j ) ) end do end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( stdlib_lsame( 'UPPER', uplo ) ) then do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_zla_porpvgrw = rpvgrw end function stdlib${ii}$_zla_porpvgrw #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] real(${ck}$) module function stdlib${ii}$_${ci}$la_porpvgrw( uplo, ncols, a, lda, af,ldaf, work ) !! ZLA_PORPVGRW: computes the reciprocal pivot growth factor !! norm(A)/norm(U). The "max absolute element" norm is used. If this is !! much less than 1, the stability of the LU factorization of the !! (equilibrated) matrix A could be poor. This also means that the !! solution X, estimated condition numbers, and error bounds could be !! unreliable. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(in) :: ncols, lda, ldaf ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), af(ldaf,*) real(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: amax, umax, rpvgrw logical(lk) :: upper complex(${ck}$) :: zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements upper = stdlib_lsame( 'UPPER', uplo ) ! stdlib${ii}$_${ci}$otrf will have factored only the ncolsxncols leading minor, so ! we restrict the growth search to that minor and use only the first ! 2*ncols workspace entries. rpvgrw = one do i = 1, 2*ncols work( i ) = zero end do ! find the max magnitude entry of each column. if ( upper ) then do j = 1, ncols do i = 1, j work( ncols+j ) =max( cabs1( a( i, j ) ), work( ncols+j ) ) end do end do else do j = 1, ncols do i = j, ncols work( ncols+j ) =max( cabs1( a( i, j ) ), work( ncols+j ) ) end do end do end if ! now find the max magnitude entry of each column of the factor in ! af. no pivoting, so no permutations. if ( stdlib_lsame( 'UPPER', uplo ) ) then do j = 1, ncols do i = 1, j work( j ) = max( cabs1( af( i, j ) ), work( j ) ) end do end do else do j = 1, ncols do i = j, ncols work( j ) = max( cabs1( af( i, j ) ), work( j ) ) end do end do end if ! compute the *inverse* of the max element growth factor. dividing ! by zero would imply the largest entry of the factor's column is ! zero. than can happen when either the column of a is zero or ! massive pivots made the factor underflow to zero. neither counts ! as growth in itself, so simply ignore terms with zero ! denominators. if ( stdlib_lsame( 'UPPER', uplo ) ) then do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do else do i = 1, ncols umax = work( i ) amax = work( ncols+i ) if ( umax /= zero ) then rpvgrw = min( amax / umax, rpvgrw ) end if end do end if stdlib${ii}$_${ci}$la_porpvgrw = rpvgrw end function stdlib${ii}$_${ci}$la_porpvgrw #:endif #:endfor pure module subroutine stdlib${ii}$_sppcon( uplo, n, ap, anorm, rcond, work, iwork, info ) !! SPPCON estimates the reciprocal of the condition number (in the !! 1-norm) of a real symmetric positive definite packed matrix using !! the Cholesky factorization A = U**T*U or A = L*L**T computed by !! SPPTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: ap(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper character :: normin integer(${ik}$) :: ix, kase real(sp) :: ainvnm, scale, scalel, scaleu, smlnum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( anorm1_${ik}$ )call stdlib${ii}$_stpsv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', j-1, ap,ap( jc ), & 1_${ik}$ ) ! compute u(j,j) and test for non-positive-definiteness. ajj = ap( jj ) - stdlib${ii}$_sdot( j-1, ap( jc ), 1_${ik}$, ap( jc ), 1_${ik}$ ) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ap( jj ) = sqrt( ajj ) end do else ! compute the cholesky factorization a = l*l**t. jj = 1_${ik}$ do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = ap( jj ) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ajj = sqrt( ajj ) ap( jj ) = ajj ! compute elements j+1:n of column j and update the trailing ! submatrix. if( j1_${ik}$ )call stdlib${ii}$_dtpsv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', j-1, ap,ap( jc ), & 1_${ik}$ ) ! compute u(j,j) and test for non-positive-definiteness. ajj = ap( jj ) - stdlib${ii}$_ddot( j-1, ap( jc ), 1_${ik}$, ap( jc ), 1_${ik}$ ) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ap( jj ) = sqrt( ajj ) end do else ! compute the cholesky factorization a = l*l**t. jj = 1_${ik}$ do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = ap( jj ) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ajj = sqrt( ajj ) ap( jj ) = ajj ! compute elements j+1:n of column j and update the trailing ! submatrix. if( j1_${ik}$ )call stdlib${ii}$_${ri}$tpsv( 'UPPER', 'TRANSPOSE', 'NON-UNIT', j-1, ap,ap( jc ), & 1_${ik}$ ) ! compute u(j,j) and test for non-positive-definiteness. ajj = ap( jj ) - stdlib${ii}$_${ri}$dot( j-1, ap( jc ), 1_${ik}$, ap( jc ), 1_${ik}$ ) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ap( jj ) = sqrt( ajj ) end do else ! compute the cholesky factorization a = l*l**t. jj = 1_${ik}$ do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = ap( jj ) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ajj = sqrt( ajj ) ap( jj ) = ajj ! compute elements j+1:n of column j and update the trailing ! submatrix. if( j1_${ik}$ )call stdlib${ii}$_ctpsv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',j-1, ap, & ap( jc ), 1_${ik}$ ) ! compute u(j,j) and test for non-positive-definiteness. ajj = real( real( ap( jj ),KIND=sp) - stdlib${ii}$_cdotc( j-1,ap( jc ), 1_${ik}$, ap( jc ), 1_${ik}$ & ),KIND=sp) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ap( jj ) = sqrt( ajj ) end do else ! compute the cholesky factorization a = l * l**h. jj = 1_${ik}$ do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = real( ap( jj ),KIND=sp) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ajj = sqrt( ajj ) ap( jj ) = ajj ! compute elements j+1:n of column j and update the trailing ! submatrix. if( j1_${ik}$ )call stdlib${ii}$_ztpsv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',j-1, ap, & ap( jc ), 1_${ik}$ ) ! compute u(j,j) and test for non-positive-definiteness. ajj = real( ap( jj ),KIND=dp) - real( stdlib${ii}$_zdotc( j-1,ap( jc ), 1_${ik}$, ap( jc ), 1_${ik}$ & ),KIND=dp) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ap( jj ) = sqrt( ajj ) end do else ! compute the cholesky factorization a = l * l**h. jj = 1_${ik}$ do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = real( ap( jj ),KIND=dp) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ajj = sqrt( ajj ) ap( jj ) = ajj ! compute elements j+1:n of column j and update the trailing ! submatrix. if( j1_${ik}$ )call stdlib${ii}$_${ci}$tpsv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',j-1, ap, & ap( jc ), 1_${ik}$ ) ! compute u(j,j) and test for non-positive-definiteness. ajj = real( ap( jj ),KIND=${ck}$) - real( stdlib${ii}$_${ci}$dotc( j-1,ap( jc ), 1_${ik}$, ap( jc ), 1_${ik}$ & ),KIND=${ck}$) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ap( jj ) = sqrt( ajj ) end do else ! compute the cholesky factorization a = l * l**h. jj = 1_${ik}$ do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = real( ap( jj ),KIND=${ck}$) if( ajj<=zero ) then ap( jj ) = ajj go to 30 end if ajj = sqrt( ajj ) ap( jj ) = ajj ! compute elements j+1:n of column j and update the trailing ! submatrix. if( j0 )return if( upper ) then ! compute the product inv(u) * inv(u)**t. jj = 0_${ik}$ do j = 1, n jc = jj + 1_${ik}$ jj = jj + j if( j>1_${ik}$ )call stdlib${ii}$_sspr( 'UPPER', j-1, one, ap( jc ), 1_${ik}$, ap ) ajj = ap( jj ) call stdlib${ii}$_sscal( j, ajj, ap( jc ), 1_${ik}$ ) end do else ! compute the product inv(l)**t * inv(l). jj = 1_${ik}$ do j = 1, n jjn = jj + n - j + 1_${ik}$ ap( jj ) = stdlib${ii}$_sdot( n-j+1, ap( jj ), 1_${ik}$, ap( jj ), 1_${ik}$ ) if( j0 )return if( upper ) then ! compute the product inv(u) * inv(u)**t. jj = 0_${ik}$ do j = 1, n jc = jj + 1_${ik}$ jj = jj + j if( j>1_${ik}$ )call stdlib${ii}$_dspr( 'UPPER', j-1, one, ap( jc ), 1_${ik}$, ap ) ajj = ap( jj ) call stdlib${ii}$_dscal( j, ajj, ap( jc ), 1_${ik}$ ) end do else ! compute the product inv(l)**t * inv(l). jj = 1_${ik}$ do j = 1, n jjn = jj + n - j + 1_${ik}$ ap( jj ) = stdlib${ii}$_ddot( n-j+1, ap( jj ), 1_${ik}$, ap( jj ), 1_${ik}$ ) if( j0 )return if( upper ) then ! compute the product inv(u) * inv(u)**t. jj = 0_${ik}$ do j = 1, n jc = jj + 1_${ik}$ jj = jj + j if( j>1_${ik}$ )call stdlib${ii}$_${ri}$spr( 'UPPER', j-1, one, ap( jc ), 1_${ik}$, ap ) ajj = ap( jj ) call stdlib${ii}$_${ri}$scal( j, ajj, ap( jc ), 1_${ik}$ ) end do else ! compute the product inv(l)**t * inv(l). jj = 1_${ik}$ do j = 1, n jjn = jj + n - j + 1_${ik}$ ap( jj ) = stdlib${ii}$_${ri}$dot( n-j+1, ap( jj ), 1_${ik}$, ap( jj ), 1_${ik}$ ) if( j0 )return if( upper ) then ! compute the product inv(u) * inv(u)**h. jj = 0_${ik}$ do j = 1, n jc = jj + 1_${ik}$ jj = jj + j if( j>1_${ik}$ )call stdlib${ii}$_chpr( 'UPPER', j-1, one, ap( jc ), 1_${ik}$, ap ) ajj = real( ap( jj ),KIND=sp) call stdlib${ii}$_csscal( j, ajj, ap( jc ), 1_${ik}$ ) end do else ! compute the product inv(l)**h * inv(l). jj = 1_${ik}$ do j = 1, n jjn = jj + n - j + 1_${ik}$ ap( jj ) = real( stdlib${ii}$_cdotc( n-j+1, ap( jj ), 1_${ik}$, ap( jj ), 1_${ik}$ ),KIND=sp) if( j0 )return if( upper ) then ! compute the product inv(u) * inv(u)**h. jj = 0_${ik}$ do j = 1, n jc = jj + 1_${ik}$ jj = jj + j if( j>1_${ik}$ )call stdlib${ii}$_zhpr( 'UPPER', j-1, one, ap( jc ), 1_${ik}$, ap ) ajj = real( ap( jj ),KIND=dp) call stdlib${ii}$_zdscal( j, ajj, ap( jc ), 1_${ik}$ ) end do else ! compute the product inv(l)**h * inv(l). jj = 1_${ik}$ do j = 1, n jjn = jj + n - j + 1_${ik}$ ap( jj ) = real( stdlib${ii}$_zdotc( n-j+1, ap( jj ), 1_${ik}$, ap( jj ), 1_${ik}$ ),KIND=dp) if( j0 )return if( upper ) then ! compute the product inv(u) * inv(u)**h. jj = 0_${ik}$ do j = 1, n jc = jj + 1_${ik}$ jj = jj + j if( j>1_${ik}$ )call stdlib${ii}$_${ci}$hpr( 'UPPER', j-1, one, ap( jc ), 1_${ik}$, ap ) ajj = real( ap( jj ),KIND=${ck}$) call stdlib${ii}$_${ci}$dscal( j, ajj, ap( jc ), 1_${ik}$ ) end do else ! compute the product inv(l)**h * inv(l). jj = 1_${ik}$ do j = 1, n jjn = jj + n - j + 1_${ik}$ ap( jj ) = real( stdlib${ii}$_${ci}$dotc( n-j+1, ap( jj ), 1_${ik}$, ap( jj ), 1_${ik}$ ),KIND=${ck}$) if( jsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_spptrs( uplo, n, 1_${ik}$, afp, work( n+1 ), n, info ) call stdlib${ii}$_saxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_slacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_slacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_spptrs( uplo, n, 1_${ik}$, afp, work( n+1 ), n, info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_spptrs( uplo, n, 1_${ik}$, afp, work( n+1 ), n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_spprfs pure module subroutine stdlib${ii}$_dpprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr,berr, work, & !! DPPRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric positive definite !! and packed, and provides error bounds and backward error estimates !! for the solution. iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: afp(*), ap(*), b(ldb,*) real(dp), intent(out) :: berr(*), ferr(*), work(*) real(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_dpptrs( uplo, n, 1_${ik}$, afp, work( n+1 ), n, info ) call stdlib${ii}$_daxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_dlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_dlacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_dpptrs( uplo, n, 1_${ik}$, afp, work( n+1 ), n, info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_dpptrs( uplo, n, 1_${ik}$, afp, work( n+1 ), n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_dpprfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$pprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr,berr, work, & !! DPPRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric positive definite !! and packed, and provides error bounds and backward error estimates !! for the solution. iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: afp(*), ap(*), b(ldb,*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) real(${rk}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(${rk}$) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ri}$pptrs( uplo, n, 1_${ik}$, afp, work( n+1 ), n, info ) call stdlib${ii}$_${ri}$axpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ri}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ri}$lacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_${ri}$pptrs( uplo, n, 1_${ik}$, afp, work( n+1 ), n, info ) do i = 1, n work( n+i ) = work( i )*work( n+i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( i )*work( n+i ) end do call stdlib${ii}$_${ri}$pptrs( uplo, n, 1_${ik}$, afp, work( n+1 ), n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ri}$pprfs #:endif #:endfor pure module subroutine stdlib${ii}$_cpprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr,berr, work, & !! CPPRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and packed, and provides error bounds and backward error estimates !! for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: afp(*), ap(*), b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) ! ==================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_cpptrs( uplo, n, 1_${ik}$, afp, work, n, info ) call stdlib${ii}$_caxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_cpptrs( uplo, n, 1_${ik}$, afp, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_cpptrs( uplo, n, 1_${ik}$, afp, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_cpprfs pure module subroutine stdlib${ii}$_zpprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr,berr, work, & !! ZPPRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and packed, and provides error bounds and backward error estimates !! for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: afp(*), ap(*), b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) ! ==================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_zpptrs( uplo, n, 1_${ik}$, afp, work, n, info ) call stdlib${ii}$_zaxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_zpptrs( uplo, n, 1_${ik}$, afp, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_zpptrs( uplo, n, 1_${ik}$, afp, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_zpprfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$pprfs( uplo, n, nrhs, ap, afp, b, ldb, x, ldx, ferr,berr, work, & !! ZPPRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and packed, and provides error bounds and backward error estimates !! for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: afp(*), ap(*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ==================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ik, j, k, kase, kk, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ci}$pptrs( uplo, n, 1_${ik}$, afp, work, n, info ) call stdlib${ii}$_${ci}$axpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_${ci}$pptrs( uplo, n, 1_${ik}$, afp, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$pptrs( uplo, n, 1_${ik}$, afp, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ci}$pprfs #:endif #:endfor pure module subroutine stdlib${ii}$_sppequ( uplo, n, ap, s, scond, amax, info ) !! SPPEQU computes row and column scalings intended to equilibrate a !! symmetric positive definite matrix A in packed storage and reduce !! its condition number (with respect to the two-norm). S contains the !! scale factors, S(i)=1/sqrt(A(i,i)), chosen so that the scaled matrix !! B with elements B(i,j)=S(i)*A(i,j)*S(j) has ones on the diagonal. !! This choice of S puts the condition number of B within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(out) :: amax, scond ! Array Arguments real(sp), intent(in) :: ap(*) real(sp), intent(out) :: s(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, jj real(sp) :: smin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SPPEQU', -info ) return end if ! quick return if possible if( n==0_${ik}$ ) then scond = one amax = zero return end if ! initialize smin and amax. s( 1_${ik}$ ) = ap( 1_${ik}$ ) smin = s( 1_${ik}$ ) amax = s( 1_${ik}$ ) if( upper ) then ! uplo = 'u': upper triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + i s( i ) = ap( jj ) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do else ! uplo = 'l': lower triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + n - i + 2_${ik}$ s( i ) = ap( jj ) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do end if if( smin<=zero ) then ! find the first non-positive diagonal element and return. do i = 1, n if( s( i )<=zero ) then info = i return end if end do else ! set the scale factors to the reciprocals ! of the diagonal elements. do i = 1, n s( i ) = one / sqrt( s( i ) ) end do ! compute scond = min(s(i)) / max(s(i)) scond = sqrt( smin ) / sqrt( amax ) end if return end subroutine stdlib${ii}$_sppequ pure module subroutine stdlib${ii}$_dppequ( uplo, n, ap, s, scond, amax, info ) !! DPPEQU computes row and column scalings intended to equilibrate a !! symmetric positive definite matrix A in packed storage and reduce !! its condition number (with respect to the two-norm). S contains the !! scale factors, S(i)=1/sqrt(A(i,i)), chosen so that the scaled matrix !! B with elements B(i,j)=S(i)*A(i,j)*S(j) has ones on the diagonal. !! This choice of S puts the condition number of B within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: amax, scond ! Array Arguments real(dp), intent(in) :: ap(*) real(dp), intent(out) :: s(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, jj real(dp) :: smin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DPPEQU', -info ) return end if ! quick return if possible if( n==0_${ik}$ ) then scond = one amax = zero return end if ! initialize smin and amax. s( 1_${ik}$ ) = ap( 1_${ik}$ ) smin = s( 1_${ik}$ ) amax = s( 1_${ik}$ ) if( upper ) then ! uplo = 'u': upper triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + i s( i ) = ap( jj ) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do else ! uplo = 'l': lower triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + n - i + 2_${ik}$ s( i ) = ap( jj ) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do end if if( smin<=zero ) then ! find the first non-positive diagonal element and return. do i = 1, n if( s( i )<=zero ) then info = i return end if end do else ! set the scale factors to the reciprocals ! of the diagonal elements. do i = 1, n s( i ) = one / sqrt( s( i ) ) end do ! compute scond = min(s(i)) / max(s(i)) scond = sqrt( smin ) / sqrt( amax ) end if return end subroutine stdlib${ii}$_dppequ #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ppequ( uplo, n, ap, s, scond, amax, info ) !! DPPEQU: computes row and column scalings intended to equilibrate a !! symmetric positive definite matrix A in packed storage and reduce !! its condition number (with respect to the two-norm). S contains the !! scale factors, S(i)=1/sqrt(A(i,i)), chosen so that the scaled matrix !! B with elements B(i,j)=S(i)*A(i,j)*S(j) has ones on the diagonal. !! This choice of S puts the condition number of B within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(${rk}$), intent(out) :: amax, scond ! Array Arguments real(${rk}$), intent(in) :: ap(*) real(${rk}$), intent(out) :: s(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, jj real(${rk}$) :: smin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DPPEQU', -info ) return end if ! quick return if possible if( n==0_${ik}$ ) then scond = one amax = zero return end if ! initialize smin and amax. s( 1_${ik}$ ) = ap( 1_${ik}$ ) smin = s( 1_${ik}$ ) amax = s( 1_${ik}$ ) if( upper ) then ! uplo = 'u': upper triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + i s( i ) = ap( jj ) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do else ! uplo = 'l': lower triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + n - i + 2_${ik}$ s( i ) = ap( jj ) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do end if if( smin<=zero ) then ! find the first non-positive diagonal element and return. do i = 1, n if( s( i )<=zero ) then info = i return end if end do else ! set the scale factors to the reciprocals ! of the diagonal elements. do i = 1, n s( i ) = one / sqrt( s( i ) ) end do ! compute scond = min(s(i)) / max(s(i)) scond = sqrt( smin ) / sqrt( amax ) end if return end subroutine stdlib${ii}$_${ri}$ppequ #:endif #:endfor pure module subroutine stdlib${ii}$_cppequ( uplo, n, ap, s, scond, amax, info ) !! CPPEQU computes row and column scalings intended to equilibrate a !! Hermitian positive definite matrix A in packed storage and reduce !! its condition number (with respect to the two-norm). S contains the !! scale factors, S(i)=1/sqrt(A(i,i)), chosen so that the scaled matrix !! B with elements B(i,j)=S(i)*A(i,j)*S(j) has ones on the diagonal. !! This choice of S puts the condition number of B within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(out) :: amax, scond ! Array Arguments real(sp), intent(out) :: s(*) complex(sp), intent(in) :: ap(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, jj real(sp) :: smin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CPPEQU', -info ) return end if ! quick return if possible if( n==0_${ik}$ ) then scond = one amax = zero return end if ! initialize smin and amax. s( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=sp) smin = s( 1_${ik}$ ) amax = s( 1_${ik}$ ) if( upper ) then ! uplo = 'u': upper triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + i s( i ) = real( ap( jj ),KIND=sp) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do else ! uplo = 'l': lower triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + n - i + 2_${ik}$ s( i ) = real( ap( jj ),KIND=sp) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do end if if( smin<=zero ) then ! find the first non-positive diagonal element and return. do i = 1, n if( s( i )<=zero ) then info = i return end if end do else ! set the scale factors to the reciprocals ! of the diagonal elements. do i = 1, n s( i ) = one / sqrt( s( i ) ) end do ! compute scond = min(s(i)) / max(s(i)) scond = sqrt( smin ) / sqrt( amax ) end if return end subroutine stdlib${ii}$_cppequ pure module subroutine stdlib${ii}$_zppequ( uplo, n, ap, s, scond, amax, info ) !! ZPPEQU computes row and column scalings intended to equilibrate a !! Hermitian positive definite matrix A in packed storage and reduce !! its condition number (with respect to the two-norm). S contains the !! scale factors, S(i)=1/sqrt(A(i,i)), chosen so that the scaled matrix !! B with elements B(i,j)=S(i)*A(i,j)*S(j) has ones on the diagonal. !! This choice of S puts the condition number of B within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(dp), intent(out) :: amax, scond ! Array Arguments real(dp), intent(out) :: s(*) complex(dp), intent(in) :: ap(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, jj real(dp) :: smin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZPPEQU', -info ) return end if ! quick return if possible if( n==0_${ik}$ ) then scond = one amax = zero return end if ! initialize smin and amax. s( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=dp) smin = s( 1_${ik}$ ) amax = s( 1_${ik}$ ) if( upper ) then ! uplo = 'u': upper triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + i s( i ) = real( ap( jj ),KIND=dp) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do else ! uplo = 'l': lower triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + n - i + 2_${ik}$ s( i ) = real( ap( jj ),KIND=dp) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do end if if( smin<=zero ) then ! find the first non-positive diagonal element and return. do i = 1, n if( s( i )<=zero ) then info = i return end if end do else ! set the scale factors to the reciprocals ! of the diagonal elements. do i = 1, n s( i ) = one / sqrt( s( i ) ) end do ! compute scond = min(s(i)) / max(s(i)) scond = sqrt( smin ) / sqrt( amax ) end if return end subroutine stdlib${ii}$_zppequ #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ppequ( uplo, n, ap, s, scond, amax, info ) !! ZPPEQU: computes row and column scalings intended to equilibrate a !! Hermitian positive definite matrix A in packed storage and reduce !! its condition number (with respect to the two-norm). S contains the !! scale factors, S(i)=1/sqrt(A(i,i)), chosen so that the scaled matrix !! B with elements B(i,j)=S(i)*A(i,j)*S(j) has ones on the diagonal. !! This choice of S puts the condition number of B within a factor N of !! the smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(${ck}$), intent(out) :: amax, scond ! Array Arguments real(${ck}$), intent(out) :: s(*) complex(${ck}$), intent(in) :: ap(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, jj real(${ck}$) :: smin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZPPEQU', -info ) return end if ! quick return if possible if( n==0_${ik}$ ) then scond = one amax = zero return end if ! initialize smin and amax. s( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=${ck}$) smin = s( 1_${ik}$ ) amax = s( 1_${ik}$ ) if( upper ) then ! uplo = 'u': upper triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + i s( i ) = real( ap( jj ),KIND=${ck}$) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do else ! uplo = 'l': lower triangle of a is stored. ! find the minimum and maximum diagonal elements. jj = 1_${ik}$ do i = 2, n jj = jj + n - i + 2_${ik}$ s( i ) = real( ap( jj ),KIND=${ck}$) smin = min( smin, s( i ) ) amax = max( amax, s( i ) ) end do end if if( smin<=zero ) then ! find the first non-positive diagonal element and return. do i = 1, n if( s( i )<=zero ) then info = i return end if end do else ! set the scale factors to the reciprocals ! of the diagonal elements. do i = 1, n s( i ) = one / sqrt( s( i ) ) end do ! compute scond = min(s(i)) / max(s(i)) scond = sqrt( smin ) / sqrt( amax ) end if return end subroutine stdlib${ii}$_${ci}$ppequ #:endif #:endfor pure module subroutine stdlib${ii}$_claqhp( uplo, n, ap, s, scond, amax, equed ) !! CLAQHP equilibrates a Hermitian matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: amax, scond ! Array Arguments real(sp), intent(in) :: s(*) complex(sp), intent(inout) :: ap(*) ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1e+0_sp ! Local Scalars integer(${ik}$) :: i, j, jc real(sp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) / stdlib${ii}$_slamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = 1, j - 1 ap( jc+i-1 ) = cj*s( i )*ap( jc+i-1 ) end do ap( jc+j-1 ) = cj*cj*real( ap( jc+j-1 ),KIND=sp) jc = jc + j end do else ! lower triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) ap( jc ) = cj*cj*real( ap( jc ),KIND=sp) do i = j + 1, n ap( jc+i-j ) = cj*s( i )*ap( jc+i-j ) end do jc = jc + n - j + 1_${ik}$ end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_claqhp pure module subroutine stdlib${ii}$_zlaqhp( uplo, n, ap, s, scond, amax, equed ) !! ZLAQHP equilibrates a Hermitian matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: amax, scond ! Array Arguments real(dp), intent(in) :: s(*) complex(dp), intent(inout) :: ap(*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j, jc real(dp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = 1, j - 1 ap( jc+i-1 ) = cj*s( i )*ap( jc+i-1 ) end do ap( jc+j-1 ) = cj*cj*real( ap( jc+j-1 ),KIND=dp) jc = jc + j end do else ! lower triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) ap( jc ) = cj*cj*real( ap( jc ),KIND=dp) do i = j + 1, n ap( jc+i-j ) = cj*s( i )*ap( jc+i-j ) end do jc = jc + n - j + 1_${ik}$ end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_zlaqhp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqhp( uplo, n, ap, s, scond, amax, equed ) !! ZLAQHP: equilibrates a Hermitian matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(${ck}$), intent(in) :: amax, scond ! Array Arguments real(${ck}$), intent(in) :: s(*) complex(${ck}$), intent(inout) :: ap(*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: thresh = 0.1e+0_${ck}$ ! Local Scalars integer(${ik}$) :: i, j, jc real(${ck}$) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = 1, j - 1 ap( jc+i-1 ) = cj*s( i )*ap( jc+i-1 ) end do ap( jc+j-1 ) = cj*cj*real( ap( jc+j-1 ),KIND=${ck}$) jc = jc + j end do else ! lower triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) ap( jc ) = cj*cj*real( ap( jc ),KIND=${ck}$) do i = j + 1, n ap( jc+i-j ) = cj*s( i )*ap( jc+i-j ) end do jc = jc + n - j + 1_${ik}$ end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_${ci}$laqhp #:endif #:endfor pure module subroutine stdlib${ii}$_spftrf( transr, uplo, n, a, info ) !! SPFTRF computes the Cholesky factorization of a real symmetric !! positive definite matrix A. !! The factorization has the form !! A = U**T * U, if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info ! Array Arguments real(sp), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'T' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SPFTRF', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_spotrf( 'L', n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_strsm( 'R', 'L', 'T', 'N', n2, n1, one, a( 0_${ik}$ ), n,a( n1 ), n ) call stdlib${ii}$_ssyrk( 'U', 'N', n2, n1, -one, a( n1 ), n, one,a( n ), n ) call stdlib${ii}$_spotrf( 'U', n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_spotrf( 'L', n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_strsm( 'L', 'L', 'N', 'N', n1, n2, one, a( n2 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_ssyrk( 'U', 'T', n2, n1, -one, a( 0_${ik}$ ), n, one,a( n1 ), n ) call stdlib${ii}$_spotrf( 'U', n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 end if else ! n is odd and transr = 't' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0,0) , t2 -> a(1,0) , s -> a(0,n1) ! t1 -> a(0+0) , t2 -> a(1+0) , s -> a(0+n1*n1); lda=n1 call stdlib${ii}$_spotrf( 'U', n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_strsm( 'L', 'U', 'T', 'N', n1, n2, one, a( 0_${ik}$ ), n1,a( n1*n1 ), n1 & ) call stdlib${ii}$_ssyrk( 'L', 'T', n2, n1, -one, a( n1*n1 ), n1, one,a( 1_${ik}$ ), n1 ) call stdlib${ii}$_spotrf( 'L', n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, transpose and n is odd ! t1 -> a(0,n1+1), t2 -> a(0,n1), s -> a(0,0) ! t1 -> a(n2*n2), t2 -> a(n1*n2), s -> a(0); lda = n2 call stdlib${ii}$_spotrf( 'U', n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_strsm( 'R', 'U', 'N', 'N', n2, n1, one, a( n2*n2 ),n2, a( 0_${ik}$ ), n2 & ) call stdlib${ii}$_ssyrk( 'L', 'N', n2, n1, -one, a( 0_${ik}$ ), n2, one,a( n1*n2 ), n2 ) call stdlib${ii}$_spotrf( 'L', n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_spotrf( 'L', k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_strsm( 'R', 'L', 'T', 'N', k, k, one, a( 1_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_ssyrk( 'U', 'N', k, k, -one, a( k+1 ), n+1, one,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_spotrf( 'U', k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_spotrf( 'L', k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_strsm( 'L', 'L', 'N', 'N', k, k, one, a( k+1 ),n+1, a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_ssyrk( 'U', 'T', k, k, -one, a( 0_${ik}$ ), n+1, one,a( k ), n+1 ) call stdlib${ii}$_spotrf( 'U', k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k end if else ! n is even and transr = 't' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_spotrf( 'U', k, a( 0_${ik}$+k ), k, info ) if( info>0 )return call stdlib${ii}$_strsm( 'L', 'U', 'T', 'N', k, k, one, a( k ), n1,a( k*( k+1 ) ), & k ) call stdlib${ii}$_ssyrk( 'L', 'T', k, k, -one, a( k*( k+1 ) ), k, one,a( 0_${ik}$ ), k ) call stdlib${ii}$_spotrf( 'L', k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_spotrf( 'U', k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_strsm( 'R', 'U', 'N', 'N', k, k, one,a( k*( k+1 ) ), k, a( 0_${ik}$ ), k & ) call stdlib${ii}$_ssyrk( 'L', 'N', k, k, -one, a( 0_${ik}$ ), k, one,a( k*k ), k ) call stdlib${ii}$_spotrf( 'L', k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k end if end if end if return end subroutine stdlib${ii}$_spftrf pure module subroutine stdlib${ii}$_dpftrf( transr, uplo, n, a, info ) !! DPFTRF computes the Cholesky factorization of a real symmetric !! positive definite matrix A. !! The factorization has the form !! A = U**T * U, if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info ! Array Arguments real(dp), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'T' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DPFTRF', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_dpotrf( 'L', n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_dtrsm( 'R', 'L', 'T', 'N', n2, n1, one, a( 0_${ik}$ ), n,a( n1 ), n ) call stdlib${ii}$_dsyrk( 'U', 'N', n2, n1, -one, a( n1 ), n, one,a( n ), n ) call stdlib${ii}$_dpotrf( 'U', n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_dpotrf( 'L', n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_dtrsm( 'L', 'L', 'N', 'N', n1, n2, one, a( n2 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_dsyrk( 'U', 'T', n2, n1, -one, a( 0_${ik}$ ), n, one,a( n1 ), n ) call stdlib${ii}$_dpotrf( 'U', n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 end if else ! n is odd and transr = 't' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0,0) , t2 -> a(1,0) , s -> a(0,n1) ! t1 -> a(0+0) , t2 -> a(1+0) , s -> a(0+n1*n1); lda=n1 call stdlib${ii}$_dpotrf( 'U', n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_dtrsm( 'L', 'U', 'T', 'N', n1, n2, one, a( 0_${ik}$ ), n1,a( n1*n1 ), n1 & ) call stdlib${ii}$_dsyrk( 'L', 'T', n2, n1, -one, a( n1*n1 ), n1, one,a( 1_${ik}$ ), n1 ) call stdlib${ii}$_dpotrf( 'L', n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, transpose and n is odd ! t1 -> a(0,n1+1), t2 -> a(0,n1), s -> a(0,0) ! t1 -> a(n2*n2), t2 -> a(n1*n2), s -> a(0); lda = n2 call stdlib${ii}$_dpotrf( 'U', n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_dtrsm( 'R', 'U', 'N', 'N', n2, n1, one, a( n2*n2 ),n2, a( 0_${ik}$ ), n2 & ) call stdlib${ii}$_dsyrk( 'L', 'N', n2, n1, -one, a( 0_${ik}$ ), n2, one,a( n1*n2 ), n2 ) call stdlib${ii}$_dpotrf( 'L', n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_dpotrf( 'L', k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_dtrsm( 'R', 'L', 'T', 'N', k, k, one, a( 1_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_dsyrk( 'U', 'N', k, k, -one, a( k+1 ), n+1, one,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_dpotrf( 'U', k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_dpotrf( 'L', k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_dtrsm( 'L', 'L', 'N', 'N', k, k, one, a( k+1 ),n+1, a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_dsyrk( 'U', 'T', k, k, -one, a( 0_${ik}$ ), n+1, one,a( k ), n+1 ) call stdlib${ii}$_dpotrf( 'U', k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k end if else ! n is even and transr = 't' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_dpotrf( 'U', k, a( 0_${ik}$+k ), k, info ) if( info>0 )return call stdlib${ii}$_dtrsm( 'L', 'U', 'T', 'N', k, k, one, a( k ), n1,a( k*( k+1 ) ), & k ) call stdlib${ii}$_dsyrk( 'L', 'T', k, k, -one, a( k*( k+1 ) ), k, one,a( 0_${ik}$ ), k ) call stdlib${ii}$_dpotrf( 'L', k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_dpotrf( 'U', k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_dtrsm( 'R', 'U', 'N', 'N', k, k, one,a( k*( k+1 ) ), k, a( 0_${ik}$ ), k & ) call stdlib${ii}$_dsyrk( 'L', 'N', k, k, -one, a( 0_${ik}$ ), k, one,a( k*k ), k ) call stdlib${ii}$_dpotrf( 'L', k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k end if end if end if return end subroutine stdlib${ii}$_dpftrf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$pftrf( transr, uplo, n, a, info ) !! DPFTRF: computes the Cholesky factorization of a real symmetric !! positive definite matrix A. !! The factorization has the form !! A = U**T * U, if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info ! Array Arguments real(${rk}$), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'T' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DPFTRF', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_${ri}$potrf( 'L', n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_${ri}$trsm( 'R', 'L', 'T', 'N', n2, n1, one, a( 0_${ik}$ ), n,a( n1 ), n ) call stdlib${ii}$_${ri}$syrk( 'U', 'N', n2, n1, -one, a( n1 ), n, one,a( n ), n ) call stdlib${ii}$_${ri}$potrf( 'U', n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_${ri}$potrf( 'L', n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_${ri}$trsm( 'L', 'L', 'N', 'N', n1, n2, one, a( n2 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_${ri}$syrk( 'U', 'T', n2, n1, -one, a( 0_${ik}$ ), n, one,a( n1 ), n ) call stdlib${ii}$_${ri}$potrf( 'U', n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 end if else ! n is odd and transr = 't' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0,0) , t2 -> a(1,0) , s -> a(0,n1) ! t1 -> a(0+0) , t2 -> a(1+0) , s -> a(0+n1*n1); lda=n1 call stdlib${ii}$_${ri}$potrf( 'U', n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_${ri}$trsm( 'L', 'U', 'T', 'N', n1, n2, one, a( 0_${ik}$ ), n1,a( n1*n1 ), n1 & ) call stdlib${ii}$_${ri}$syrk( 'L', 'T', n2, n1, -one, a( n1*n1 ), n1, one,a( 1_${ik}$ ), n1 ) call stdlib${ii}$_${ri}$potrf( 'L', n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, transpose and n is odd ! t1 -> a(0,n1+1), t2 -> a(0,n1), s -> a(0,0) ! t1 -> a(n2*n2), t2 -> a(n1*n2), s -> a(0); lda = n2 call stdlib${ii}$_${ri}$potrf( 'U', n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_${ri}$trsm( 'R', 'U', 'N', 'N', n2, n1, one, a( n2*n2 ),n2, a( 0_${ik}$ ), n2 & ) call stdlib${ii}$_${ri}$syrk( 'L', 'N', n2, n1, -one, a( 0_${ik}$ ), n2, one,a( n1*n2 ), n2 ) call stdlib${ii}$_${ri}$potrf( 'L', n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_${ri}$potrf( 'L', k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_${ri}$trsm( 'R', 'L', 'T', 'N', k, k, one, a( 1_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_${ri}$syrk( 'U', 'N', k, k, -one, a( k+1 ), n+1, one,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_${ri}$potrf( 'U', k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_${ri}$potrf( 'L', k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_${ri}$trsm( 'L', 'L', 'N', 'N', k, k, one, a( k+1 ),n+1, a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_${ri}$syrk( 'U', 'T', k, k, -one, a( 0_${ik}$ ), n+1, one,a( k ), n+1 ) call stdlib${ii}$_${ri}$potrf( 'U', k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k end if else ! n is even and transr = 't' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_${ri}$potrf( 'U', k, a( 0_${ik}$+k ), k, info ) if( info>0 )return call stdlib${ii}$_${ri}$trsm( 'L', 'U', 'T', 'N', k, k, one, a( k ), n1,a( k*( k+1 ) ), & k ) call stdlib${ii}$_${ri}$syrk( 'L', 'T', k, k, -one, a( k*( k+1 ) ), k, one,a( 0_${ik}$ ), k ) call stdlib${ii}$_${ri}$potrf( 'L', k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_${ri}$potrf( 'U', k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_${ri}$trsm( 'R', 'U', 'N', 'N', k, k, one,a( k*( k+1 ) ), k, a( 0_${ik}$ ), k & ) call stdlib${ii}$_${ri}$syrk( 'L', 'N', k, k, -one, a( 0_${ik}$ ), k, one,a( k*k ), k ) call stdlib${ii}$_${ri}$potrf( 'L', k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k end if end if end if return end subroutine stdlib${ii}$_${ri}$pftrf #:endif #:endfor pure module subroutine stdlib${ii}$_cpftrf( transr, uplo, n, a, info ) !! CPFTRF computes the Cholesky factorization of a complex Hermitian !! positive definite matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info ! Array Arguments complex(sp), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'C' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CPFTRF', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_cpotrf( 'L', n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_ctrsm( 'R', 'L', 'C', 'N', n2, n1, cone, a( 0_${ik}$ ), n,a( n1 ), n ) call stdlib${ii}$_cherk( 'U', 'N', n2, n1, -one, a( n1 ), n, one,a( n ), n ) call stdlib${ii}$_cpotrf( 'U', n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_cpotrf( 'L', n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_ctrsm( 'L', 'L', 'N', 'N', n1, n2, cone, a( n2 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_cherk( 'U', 'C', n2, n1, -one, a( 0_${ik}$ ), n, one,a( n1 ), n ) call stdlib${ii}$_cpotrf( 'U', n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 end if else ! n is odd and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0,0) , t2 -> a(1,0) , s -> a(0,n1) ! t1 -> a(0+0) , t2 -> a(1+0) , s -> a(0+n1*n1); lda=n1 call stdlib${ii}$_cpotrf( 'U', n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_ctrsm( 'L', 'U', 'C', 'N', n1, n2, cone, a( 0_${ik}$ ), n1,a( n1*n1 ), & n1 ) call stdlib${ii}$_cherk( 'L', 'C', n2, n1, -one, a( n1*n1 ), n1, one,a( 1_${ik}$ ), n1 ) call stdlib${ii}$_cpotrf( 'L', n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, transpose and n is odd ! t1 -> a(0,n1+1), t2 -> a(0,n1), s -> a(0,0) ! t1 -> a(n2*n2), t2 -> a(n1*n2), s -> a(0); lda = n2 call stdlib${ii}$_cpotrf( 'U', n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_ctrsm( 'R', 'U', 'N', 'N', n2, n1, cone, a( n2*n2 ),n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_cherk( 'L', 'N', n2, n1, -one, a( 0_${ik}$ ), n2, one,a( n1*n2 ), n2 ) call stdlib${ii}$_cpotrf( 'L', n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_cpotrf( 'L', k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_ctrsm( 'R', 'L', 'C', 'N', k, k, cone, a( 1_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_cherk( 'U', 'N', k, k, -one, a( k+1 ), n+1, one,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_cpotrf( 'U', k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_cpotrf( 'L', k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_ctrsm( 'L', 'L', 'N', 'N', k, k, cone, a( k+1 ),n+1, a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_cherk( 'U', 'C', k, k, -one, a( 0_${ik}$ ), n+1, one,a( k ), n+1 ) call stdlib${ii}$_cpotrf( 'U', k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k end if else ! n is even and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_cpotrf( 'U', k, a( 0_${ik}$+k ), k, info ) if( info>0 )return call stdlib${ii}$_ctrsm( 'L', 'U', 'C', 'N', k, k, cone, a( k ), n1,a( k*( k+1 ) ), & k ) call stdlib${ii}$_cherk( 'L', 'C', k, k, -one, a( k*( k+1 ) ), k, one,a( 0_${ik}$ ), k ) call stdlib${ii}$_cpotrf( 'L', k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_cpotrf( 'U', k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_ctrsm( 'R', 'U', 'N', 'N', k, k, cone,a( k*( k+1 ) ), k, a( 0_${ik}$ ), & k ) call stdlib${ii}$_cherk( 'L', 'N', k, k, -one, a( 0_${ik}$ ), k, one,a( k*k ), k ) call stdlib${ii}$_cpotrf( 'L', k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k end if end if end if return end subroutine stdlib${ii}$_cpftrf pure module subroutine stdlib${ii}$_zpftrf( transr, uplo, n, a, info ) !! ZPFTRF computes the Cholesky factorization of a complex Hermitian !! positive definite matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info ! Array Arguments complex(dp), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'C' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZPFTRF', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_zpotrf( 'L', n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_ztrsm( 'R', 'L', 'C', 'N', n2, n1, cone, a( 0_${ik}$ ), n,a( n1 ), n ) call stdlib${ii}$_zherk( 'U', 'N', n2, n1, -one, a( n1 ), n, one,a( n ), n ) call stdlib${ii}$_zpotrf( 'U', n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_zpotrf( 'L', n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_ztrsm( 'L', 'L', 'N', 'N', n1, n2, cone, a( n2 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_zherk( 'U', 'C', n2, n1, -one, a( 0_${ik}$ ), n, one,a( n1 ), n ) call stdlib${ii}$_zpotrf( 'U', n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 end if else ! n is odd and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0,0) , t2 -> a(1,0) , s -> a(0,n1) ! t1 -> a(0+0) , t2 -> a(1+0) , s -> a(0+n1*n1); lda=n1 call stdlib${ii}$_zpotrf( 'U', n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_ztrsm( 'L', 'U', 'C', 'N', n1, n2, cone, a( 0_${ik}$ ), n1,a( n1*n1 ), & n1 ) call stdlib${ii}$_zherk( 'L', 'C', n2, n1, -one, a( n1*n1 ), n1, one,a( 1_${ik}$ ), n1 ) call stdlib${ii}$_zpotrf( 'L', n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, transpose and n is odd ! t1 -> a(0,n1+1), t2 -> a(0,n1), s -> a(0,0) ! t1 -> a(n2*n2), t2 -> a(n1*n2), s -> a(0); lda = n2 call stdlib${ii}$_zpotrf( 'U', n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_ztrsm( 'R', 'U', 'N', 'N', n2, n1, cone, a( n2*n2 ),n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_zherk( 'L', 'N', n2, n1, -one, a( 0_${ik}$ ), n2, one,a( n1*n2 ), n2 ) call stdlib${ii}$_zpotrf( 'L', n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_zpotrf( 'L', k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_ztrsm( 'R', 'L', 'C', 'N', k, k, cone, a( 1_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_zherk( 'U', 'N', k, k, -one, a( k+1 ), n+1, one,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_zpotrf( 'U', k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_zpotrf( 'L', k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_ztrsm( 'L', 'L', 'N', 'N', k, k, cone, a( k+1 ),n+1, a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_zherk( 'U', 'C', k, k, -one, a( 0_${ik}$ ), n+1, one,a( k ), n+1 ) call stdlib${ii}$_zpotrf( 'U', k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k end if else ! n is even and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_zpotrf( 'U', k, a( 0_${ik}$+k ), k, info ) if( info>0 )return call stdlib${ii}$_ztrsm( 'L', 'U', 'C', 'N', k, k, cone, a( k ), n1,a( k*( k+1 ) ), & k ) call stdlib${ii}$_zherk( 'L', 'C', k, k, -one, a( k*( k+1 ) ), k, one,a( 0_${ik}$ ), k ) call stdlib${ii}$_zpotrf( 'L', k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_zpotrf( 'U', k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_ztrsm( 'R', 'U', 'N', 'N', k, k, cone,a( k*( k+1 ) ), k, a( 0_${ik}$ ), & k ) call stdlib${ii}$_zherk( 'L', 'N', k, k, -one, a( 0_${ik}$ ), k, one,a( k*k ), k ) call stdlib${ii}$_zpotrf( 'L', k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k end if end if end if return end subroutine stdlib${ii}$_zpftrf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$pftrf( transr, uplo, n, a, info ) !! ZPFTRF: computes the Cholesky factorization of a complex Hermitian !! positive definite matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. !! This is the block version of the algorithm, calling Level 3 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(in) :: n integer(${ik}$), intent(out) :: info ! Array Arguments complex(${ck}$), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'C' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZPFTRF', -info ) return end if ! quick return if possible if( n==0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution: there are eight cases if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_${ci}$potrf( 'L', n1, a( 0_${ik}$ ), n, info ) if( info>0 )return call stdlib${ii}$_${ci}$trsm( 'R', 'L', 'C', 'N', n2, n1, cone, a( 0_${ik}$ ), n,a( n1 ), n ) call stdlib${ii}$_${ci}$herk( 'U', 'N', n2, n1, -one, a( n1 ), n, one,a( n ), n ) call stdlib${ii}$_${ci}$potrf( 'U', n2, a( n ), n, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_${ci}$potrf( 'L', n1, a( n2 ), n, info ) if( info>0 )return call stdlib${ii}$_${ci}$trsm( 'L', 'L', 'N', 'N', n1, n2, cone, a( n2 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_${ci}$herk( 'U', 'C', n2, n1, -one, a( 0_${ik}$ ), n, one,a( n1 ), n ) call stdlib${ii}$_${ci}$potrf( 'U', n2, a( n1 ), n, info ) if( info>0_${ik}$ )info = info + n1 end if else ! n is odd and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is odd ! t1 -> a(0,0) , t2 -> a(1,0) , s -> a(0,n1) ! t1 -> a(0+0) , t2 -> a(1+0) , s -> a(0+n1*n1); lda=n1 call stdlib${ii}$_${ci}$potrf( 'U', n1, a( 0_${ik}$ ), n1, info ) if( info>0 )return call stdlib${ii}$_${ci}$trsm( 'L', 'U', 'C', 'N', n1, n2, cone, a( 0_${ik}$ ), n1,a( n1*n1 ), & n1 ) call stdlib${ii}$_${ci}$herk( 'L', 'C', n2, n1, -one, a( n1*n1 ), n1, one,a( 1_${ik}$ ), n1 ) call stdlib${ii}$_${ci}$potrf( 'L', n2, a( 1_${ik}$ ), n1, info ) if( info>0_${ik}$ )info = info + n1 else ! srpa for upper, transpose and n is odd ! t1 -> a(0,n1+1), t2 -> a(0,n1), s -> a(0,0) ! t1 -> a(n2*n2), t2 -> a(n1*n2), s -> a(0); lda = n2 call stdlib${ii}$_${ci}$potrf( 'U', n1, a( n2*n2 ), n2, info ) if( info>0 )return call stdlib${ii}$_${ci}$trsm( 'R', 'U', 'N', 'N', n2, n1, cone, a( n2*n2 ),n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_${ci}$herk( 'L', 'N', n2, n1, -one, a( 0_${ik}$ ), n2, one,a( n1*n2 ), n2 ) call stdlib${ii}$_${ci}$potrf( 'L', n2, a( n1*n2 ), n2, info ) if( info>0_${ik}$ )info = info + n1 end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_${ci}$potrf( 'L', k, a( 1_${ik}$ ), n+1, info ) if( info>0 )return call stdlib${ii}$_${ci}$trsm( 'R', 'L', 'C', 'N', k, k, cone, a( 1_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_${ci}$herk( 'U', 'N', k, k, -one, a( k+1 ), n+1, one,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_${ci}$potrf( 'U', k, a( 0_${ik}$ ), n+1, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_${ci}$potrf( 'L', k, a( k+1 ), n+1, info ) if( info>0 )return call stdlib${ii}$_${ci}$trsm( 'L', 'L', 'N', 'N', k, k, cone, a( k+1 ),n+1, a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_${ci}$herk( 'U', 'C', k, k, -one, a( 0_${ik}$ ), n+1, one,a( k ), n+1 ) call stdlib${ii}$_${ci}$potrf( 'U', k, a( k ), n+1, info ) if( info>0_${ik}$ )info = info + k end if else ! n is even and transr = 'c' if( lower ) then ! srpa for lower, transpose and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1) ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_${ci}$potrf( 'U', k, a( 0_${ik}$+k ), k, info ) if( info>0 )return call stdlib${ii}$_${ci}$trsm( 'L', 'U', 'C', 'N', k, k, cone, a( k ), n1,a( k*( k+1 ) ), & k ) call stdlib${ii}$_${ci}$herk( 'L', 'C', k, k, -one, a( k*( k+1 ) ), k, one,a( 0_${ik}$ ), k ) call stdlib${ii}$_${ci}$potrf( 'L', k, a( 0_${ik}$ ), k, info ) if( info>0_${ik}$ )info = info + k else ! srpa for upper, transpose and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0) ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_${ci}$potrf( 'U', k, a( k*( k+1 ) ), k, info ) if( info>0 )return call stdlib${ii}$_${ci}$trsm( 'R', 'U', 'N', 'N', k, k, cone,a( k*( k+1 ) ), k, a( 0_${ik}$ ), & k ) call stdlib${ii}$_${ci}$herk( 'L', 'N', k, k, -one, a( 0_${ik}$ ), k, one,a( k*k ), k ) call stdlib${ii}$_${ci}$potrf( 'L', k, a( k*k ), k, info ) if( info>0_${ik}$ )info = info + k end if end if end if return end subroutine stdlib${ii}$_${ci}$pftrf #:endif #:endfor pure module subroutine stdlib${ii}$_spftrs( transr, uplo, n, nrhs, a, b, ldb, info ) !! SPFTRS solves a system of linear equations A*X = B with a symmetric !! positive definite matrix A using the Cholesky factorization !! A = U**T*U or A = L*L**T computed by SPFTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments real(sp), intent(in) :: a(0_${ik}$:*) real(sp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, normaltransr ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'T' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( ldb0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution of triangular matrix multiply: inv(u)*inv(u)^c or ! inv(l)^c*inv(l). there are eight cases. if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_slauum( 'L', n1, a( 0_${ik}$ ), n, info ) call stdlib${ii}$_ssyrk( 'L', 'T', n1, n2, one, a( n1 ), n, one,a( 0_${ik}$ ), n ) call stdlib${ii}$_strmm( 'L', 'U', 'N', 'N', n2, n1, one, a( n ), n,a( n1 ), n ) call stdlib${ii}$_slauum( 'U', n2, a( n ), n, info ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_slauum( 'L', n1, a( n2 ), n, info ) call stdlib${ii}$_ssyrk( 'L', 'N', n1, n2, one, a( 0_${ik}$ ), n, one,a( n2 ), n ) call stdlib${ii}$_strmm( 'R', 'U', 'T', 'N', n1, n2, one, a( n1 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_slauum( 'U', n2, a( n1 ), n, info ) end if else ! n is odd and transr = 't' if( lower ) then ! srpa for lower, transpose, and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_slauum( 'U', n1, a( 0_${ik}$ ), n1, info ) call stdlib${ii}$_ssyrk( 'U', 'N', n1, n2, one, a( n1*n1 ), n1, one,a( 0_${ik}$ ), n1 ) call stdlib${ii}$_strmm( 'R', 'L', 'N', 'N', n1, n2, one, a( 1_${ik}$ ), n1,a( n1*n1 ), n1 & ) call stdlib${ii}$_slauum( 'L', n2, a( 1_${ik}$ ), n1, info ) else ! srpa for upper, transpose, and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_slauum( 'U', n1, a( n2*n2 ), n2, info ) call stdlib${ii}$_ssyrk( 'U', 'T', n1, n2, one, a( 0_${ik}$ ), n2, one,a( n2*n2 ), n2 ) call stdlib${ii}$_strmm( 'L', 'L', 'T', 'N', n2, n1, one, a( n1*n2 ),n2, a( 0_${ik}$ ), n2 & ) call stdlib${ii}$_slauum( 'L', n2, a( n1*n2 ), n2, info ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_slauum( 'L', k, a( 1_${ik}$ ), n+1, info ) call stdlib${ii}$_ssyrk( 'L', 'T', k, k, one, a( k+1 ), n+1, one,a( 1_${ik}$ ), n+1 ) call stdlib${ii}$_strmm( 'L', 'U', 'N', 'N', k, k, one, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_slauum( 'U', k, a( 0_${ik}$ ), n+1, info ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_slauum( 'L', k, a( k+1 ), n+1, info ) call stdlib${ii}$_ssyrk( 'L', 'N', k, k, one, a( 0_${ik}$ ), n+1, one,a( k+1 ), n+1 ) call stdlib${ii}$_strmm( 'R', 'U', 'T', 'N', k, k, one, a( k ), n+1,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_slauum( 'U', k, a( k ), n+1, info ) end if else ! n is even and transr = 't' if( lower ) then ! srpa for lower, transpose, and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1), ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_slauum( 'U', k, a( k ), k, info ) call stdlib${ii}$_ssyrk( 'U', 'N', k, k, one, a( k*( k+1 ) ), k, one,a( k ), k ) call stdlib${ii}$_strmm( 'R', 'L', 'N', 'N', k, k, one, a( 0_${ik}$ ), k,a( k*( k+1 ) ), k & ) call stdlib${ii}$_slauum( 'L', k, a( 0_${ik}$ ), k, info ) else ! srpa for upper, transpose, and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0), ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_slauum( 'U', k, a( k*( k+1 ) ), k, info ) call stdlib${ii}$_ssyrk( 'U', 'T', k, k, one, a( 0_${ik}$ ), k, one,a( k*( k+1 ) ), k ) call stdlib${ii}$_strmm( 'L', 'L', 'T', 'N', k, k, one, a( k*k ), k,a( 0_${ik}$ ), k ) call stdlib${ii}$_slauum( 'L', k, a( k*k ), k, info ) end if end if end if return end subroutine stdlib${ii}$_spftri pure module subroutine stdlib${ii}$_dpftri( transr, uplo, n, a, info ) !! DPFTRI computes the inverse of a (real) symmetric positive definite !! matrix A using the Cholesky factorization A = U**T*U or A = L*L**T !! computed by DPFTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'T' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DPFTRI', -info ) return end if ! quick return if possible if( n==0 )return ! invert the triangular cholesky factor u or l. call stdlib${ii}$_dtftri( transr, uplo, 'N', n, a, info ) if( info>0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution of triangular matrix multiply: inv(u)*inv(u)^c or ! inv(l)^c*inv(l). there are eight cases. if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_dlauum( 'L', n1, a( 0_${ik}$ ), n, info ) call stdlib${ii}$_dsyrk( 'L', 'T', n1, n2, one, a( n1 ), n, one,a( 0_${ik}$ ), n ) call stdlib${ii}$_dtrmm( 'L', 'U', 'N', 'N', n2, n1, one, a( n ), n,a( n1 ), n ) call stdlib${ii}$_dlauum( 'U', n2, a( n ), n, info ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_dlauum( 'L', n1, a( n2 ), n, info ) call stdlib${ii}$_dsyrk( 'L', 'N', n1, n2, one, a( 0_${ik}$ ), n, one,a( n2 ), n ) call stdlib${ii}$_dtrmm( 'R', 'U', 'T', 'N', n1, n2, one, a( n1 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_dlauum( 'U', n2, a( n1 ), n, info ) end if else ! n is odd and transr = 't' if( lower ) then ! srpa for lower, transpose, and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_dlauum( 'U', n1, a( 0_${ik}$ ), n1, info ) call stdlib${ii}$_dsyrk( 'U', 'N', n1, n2, one, a( n1*n1 ), n1, one,a( 0_${ik}$ ), n1 ) call stdlib${ii}$_dtrmm( 'R', 'L', 'N', 'N', n1, n2, one, a( 1_${ik}$ ), n1,a( n1*n1 ), n1 & ) call stdlib${ii}$_dlauum( 'L', n2, a( 1_${ik}$ ), n1, info ) else ! srpa for upper, transpose, and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_dlauum( 'U', n1, a( n2*n2 ), n2, info ) call stdlib${ii}$_dsyrk( 'U', 'T', n1, n2, one, a( 0_${ik}$ ), n2, one,a( n2*n2 ), n2 ) call stdlib${ii}$_dtrmm( 'L', 'L', 'T', 'N', n2, n1, one, a( n1*n2 ),n2, a( 0_${ik}$ ), n2 & ) call stdlib${ii}$_dlauum( 'L', n2, a( n1*n2 ), n2, info ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_dlauum( 'L', k, a( 1_${ik}$ ), n+1, info ) call stdlib${ii}$_dsyrk( 'L', 'T', k, k, one, a( k+1 ), n+1, one,a( 1_${ik}$ ), n+1 ) call stdlib${ii}$_dtrmm( 'L', 'U', 'N', 'N', k, k, one, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_dlauum( 'U', k, a( 0_${ik}$ ), n+1, info ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_dlauum( 'L', k, a( k+1 ), n+1, info ) call stdlib${ii}$_dsyrk( 'L', 'N', k, k, one, a( 0_${ik}$ ), n+1, one,a( k+1 ), n+1 ) call stdlib${ii}$_dtrmm( 'R', 'U', 'T', 'N', k, k, one, a( k ), n+1,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_dlauum( 'U', k, a( k ), n+1, info ) end if else ! n is even and transr = 't' if( lower ) then ! srpa for lower, transpose, and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1), ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_dlauum( 'U', k, a( k ), k, info ) call stdlib${ii}$_dsyrk( 'U', 'N', k, k, one, a( k*( k+1 ) ), k, one,a( k ), k ) call stdlib${ii}$_dtrmm( 'R', 'L', 'N', 'N', k, k, one, a( 0_${ik}$ ), k,a( k*( k+1 ) ), k & ) call stdlib${ii}$_dlauum( 'L', k, a( 0_${ik}$ ), k, info ) else ! srpa for upper, transpose, and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0), ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_dlauum( 'U', k, a( k*( k+1 ) ), k, info ) call stdlib${ii}$_dsyrk( 'U', 'T', k, k, one, a( 0_${ik}$ ), k, one,a( k*( k+1 ) ), k ) call stdlib${ii}$_dtrmm( 'L', 'L', 'T', 'N', k, k, one, a( k*k ), k,a( 0_${ik}$ ), k ) call stdlib${ii}$_dlauum( 'L', k, a( k*k ), k, info ) end if end if end if return end subroutine stdlib${ii}$_dpftri #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$pftri( transr, uplo, n, a, info ) !! DPFTRI: computes the inverse of a (real) symmetric positive definite !! matrix A using the Cholesky factorization A = U**T*U or A = L*L**T !! computed by DPFTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(${rk}$), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'T' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DPFTRI', -info ) return end if ! quick return if possible if( n==0 )return ! invert the triangular cholesky factor u or l. call stdlib${ii}$_${ri}$tftri( transr, uplo, 'N', n, a, info ) if( info>0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution of triangular matrix multiply: inv(u)*inv(u)^c or ! inv(l)^c*inv(l). there are eight cases. if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_${ri}$lauum( 'L', n1, a( 0_${ik}$ ), n, info ) call stdlib${ii}$_${ri}$syrk( 'L', 'T', n1, n2, one, a( n1 ), n, one,a( 0_${ik}$ ), n ) call stdlib${ii}$_${ri}$trmm( 'L', 'U', 'N', 'N', n2, n1, one, a( n ), n,a( n1 ), n ) call stdlib${ii}$_${ri}$lauum( 'U', n2, a( n ), n, info ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_${ri}$lauum( 'L', n1, a( n2 ), n, info ) call stdlib${ii}$_${ri}$syrk( 'L', 'N', n1, n2, one, a( 0_${ik}$ ), n, one,a( n2 ), n ) call stdlib${ii}$_${ri}$trmm( 'R', 'U', 'T', 'N', n1, n2, one, a( n1 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_${ri}$lauum( 'U', n2, a( n1 ), n, info ) end if else ! n is odd and transr = 't' if( lower ) then ! srpa for lower, transpose, and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_${ri}$lauum( 'U', n1, a( 0_${ik}$ ), n1, info ) call stdlib${ii}$_${ri}$syrk( 'U', 'N', n1, n2, one, a( n1*n1 ), n1, one,a( 0_${ik}$ ), n1 ) call stdlib${ii}$_${ri}$trmm( 'R', 'L', 'N', 'N', n1, n2, one, a( 1_${ik}$ ), n1,a( n1*n1 ), n1 & ) call stdlib${ii}$_${ri}$lauum( 'L', n2, a( 1_${ik}$ ), n1, info ) else ! srpa for upper, transpose, and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_${ri}$lauum( 'U', n1, a( n2*n2 ), n2, info ) call stdlib${ii}$_${ri}$syrk( 'U', 'T', n1, n2, one, a( 0_${ik}$ ), n2, one,a( n2*n2 ), n2 ) call stdlib${ii}$_${ri}$trmm( 'L', 'L', 'T', 'N', n2, n1, one, a( n1*n2 ),n2, a( 0_${ik}$ ), n2 & ) call stdlib${ii}$_${ri}$lauum( 'L', n2, a( n1*n2 ), n2, info ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_${ri}$lauum( 'L', k, a( 1_${ik}$ ), n+1, info ) call stdlib${ii}$_${ri}$syrk( 'L', 'T', k, k, one, a( k+1 ), n+1, one,a( 1_${ik}$ ), n+1 ) call stdlib${ii}$_${ri}$trmm( 'L', 'U', 'N', 'N', k, k, one, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_${ri}$lauum( 'U', k, a( 0_${ik}$ ), n+1, info ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_${ri}$lauum( 'L', k, a( k+1 ), n+1, info ) call stdlib${ii}$_${ri}$syrk( 'L', 'N', k, k, one, a( 0_${ik}$ ), n+1, one,a( k+1 ), n+1 ) call stdlib${ii}$_${ri}$trmm( 'R', 'U', 'T', 'N', k, k, one, a( k ), n+1,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_${ri}$lauum( 'U', k, a( k ), n+1, info ) end if else ! n is even and transr = 't' if( lower ) then ! srpa for lower, transpose, and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1), ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_${ri}$lauum( 'U', k, a( k ), k, info ) call stdlib${ii}$_${ri}$syrk( 'U', 'N', k, k, one, a( k*( k+1 ) ), k, one,a( k ), k ) call stdlib${ii}$_${ri}$trmm( 'R', 'L', 'N', 'N', k, k, one, a( 0_${ik}$ ), k,a( k*( k+1 ) ), k & ) call stdlib${ii}$_${ri}$lauum( 'L', k, a( 0_${ik}$ ), k, info ) else ! srpa for upper, transpose, and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0), ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_${ri}$lauum( 'U', k, a( k*( k+1 ) ), k, info ) call stdlib${ii}$_${ri}$syrk( 'U', 'T', k, k, one, a( 0_${ik}$ ), k, one,a( k*( k+1 ) ), k ) call stdlib${ii}$_${ri}$trmm( 'L', 'L', 'T', 'N', k, k, one, a( k*k ), k,a( 0_${ik}$ ), k ) call stdlib${ii}$_${ri}$lauum( 'L', k, a( k*k ), k, info ) end if end if end if return end subroutine stdlib${ii}$_${ri}$pftri #:endif #:endfor pure module subroutine stdlib${ii}$_cpftri( transr, uplo, n, a, info ) !! CPFTRI computes the inverse of a complex Hermitian positive definite !! matrix A using the Cholesky factorization A = U**H*U or A = L*L**H !! computed by CPFTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments complex(sp), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'C' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CPFTRI', -info ) return end if ! quick return if possible if( n==0 )return ! invert the triangular cholesky factor u or l. call stdlib${ii}$_ctftri( transr, uplo, 'N', n, a, info ) if( info>0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution of triangular matrix multiply: inv(u)*inv(u)^c or ! inv(l)^c*inv(l). there are eight cases. if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_clauum( 'L', n1, a( 0_${ik}$ ), n, info ) call stdlib${ii}$_cherk( 'L', 'C', n1, n2, one, a( n1 ), n, one,a( 0_${ik}$ ), n ) call stdlib${ii}$_ctrmm( 'L', 'U', 'N', 'N', n2, n1, cone, a( n ), n,a( n1 ), n ) call stdlib${ii}$_clauum( 'U', n2, a( n ), n, info ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_clauum( 'L', n1, a( n2 ), n, info ) call stdlib${ii}$_cherk( 'L', 'N', n1, n2, one, a( 0_${ik}$ ), n, one,a( n2 ), n ) call stdlib${ii}$_ctrmm( 'R', 'U', 'C', 'N', n1, n2, cone, a( n1 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_clauum( 'U', n2, a( n1 ), n, info ) end if else ! n is odd and transr = 'c' if( lower ) then ! srpa for lower, transpose, and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_clauum( 'U', n1, a( 0_${ik}$ ), n1, info ) call stdlib${ii}$_cherk( 'U', 'N', n1, n2, one, a( n1*n1 ), n1, one,a( 0_${ik}$ ), n1 ) call stdlib${ii}$_ctrmm( 'R', 'L', 'N', 'N', n1, n2, cone, a( 1_${ik}$ ), n1,a( n1*n1 ), & n1 ) call stdlib${ii}$_clauum( 'L', n2, a( 1_${ik}$ ), n1, info ) else ! srpa for upper, transpose, and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_clauum( 'U', n1, a( n2*n2 ), n2, info ) call stdlib${ii}$_cherk( 'U', 'C', n1, n2, one, a( 0_${ik}$ ), n2, one,a( n2*n2 ), n2 ) call stdlib${ii}$_ctrmm( 'L', 'L', 'C', 'N', n2, n1, cone, a( n1*n2 ),n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_clauum( 'L', n2, a( n1*n2 ), n2, info ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_clauum( 'L', k, a( 1_${ik}$ ), n+1, info ) call stdlib${ii}$_cherk( 'L', 'C', k, k, one, a( k+1 ), n+1, one,a( 1_${ik}$ ), n+1 ) call stdlib${ii}$_ctrmm( 'L', 'U', 'N', 'N', k, k, cone, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_clauum( 'U', k, a( 0_${ik}$ ), n+1, info ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_clauum( 'L', k, a( k+1 ), n+1, info ) call stdlib${ii}$_cherk( 'L', 'N', k, k, one, a( 0_${ik}$ ), n+1, one,a( k+1 ), n+1 ) call stdlib${ii}$_ctrmm( 'R', 'U', 'C', 'N', k, k, cone, a( k ), n+1,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_clauum( 'U', k, a( k ), n+1, info ) end if else ! n is even and transr = 'c' if( lower ) then ! srpa for lower, transpose, and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1), ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_clauum( 'U', k, a( k ), k, info ) call stdlib${ii}$_cherk( 'U', 'N', k, k, one, a( k*( k+1 ) ), k, one,a( k ), k ) call stdlib${ii}$_ctrmm( 'R', 'L', 'N', 'N', k, k, cone, a( 0_${ik}$ ), k,a( k*( k+1 ) ), & k ) call stdlib${ii}$_clauum( 'L', k, a( 0_${ik}$ ), k, info ) else ! srpa for upper, transpose, and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0), ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_clauum( 'U', k, a( k*( k+1 ) ), k, info ) call stdlib${ii}$_cherk( 'U', 'C', k, k, one, a( 0_${ik}$ ), k, one,a( k*( k+1 ) ), k ) call stdlib${ii}$_ctrmm( 'L', 'L', 'C', 'N', k, k, cone, a( k*k ), k,a( 0_${ik}$ ), k ) call stdlib${ii}$_clauum( 'L', k, a( k*k ), k, info ) end if end if end if return end subroutine stdlib${ii}$_cpftri pure module subroutine stdlib${ii}$_zpftri( transr, uplo, n, a, info ) !! ZPFTRI computes the inverse of a complex Hermitian positive definite !! matrix A using the Cholesky factorization A = U**H*U or A = L*L**H !! computed by ZPFTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments complex(dp), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'C' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZPFTRI', -info ) return end if ! quick return if possible if( n==0 )return ! invert the triangular cholesky factor u or l. call stdlib${ii}$_ztftri( transr, uplo, 'N', n, a, info ) if( info>0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution of triangular matrix multiply: inv(u)*inv(u)^c or ! inv(l)^c*inv(l). there are eight cases. if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_zlauum( 'L', n1, a( 0_${ik}$ ), n, info ) call stdlib${ii}$_zherk( 'L', 'C', n1, n2, one, a( n1 ), n, one,a( 0_${ik}$ ), n ) call stdlib${ii}$_ztrmm( 'L', 'U', 'N', 'N', n2, n1, cone, a( n ), n,a( n1 ), n ) call stdlib${ii}$_zlauum( 'U', n2, a( n ), n, info ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_zlauum( 'L', n1, a( n2 ), n, info ) call stdlib${ii}$_zherk( 'L', 'N', n1, n2, one, a( 0_${ik}$ ), n, one,a( n2 ), n ) call stdlib${ii}$_ztrmm( 'R', 'U', 'C', 'N', n1, n2, cone, a( n1 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_zlauum( 'U', n2, a( n1 ), n, info ) end if else ! n is odd and transr = 'c' if( lower ) then ! srpa for lower, transpose, and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_zlauum( 'U', n1, a( 0_${ik}$ ), n1, info ) call stdlib${ii}$_zherk( 'U', 'N', n1, n2, one, a( n1*n1 ), n1, one,a( 0_${ik}$ ), n1 ) call stdlib${ii}$_ztrmm( 'R', 'L', 'N', 'N', n1, n2, cone, a( 1_${ik}$ ), n1,a( n1*n1 ), & n1 ) call stdlib${ii}$_zlauum( 'L', n2, a( 1_${ik}$ ), n1, info ) else ! srpa for upper, transpose, and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_zlauum( 'U', n1, a( n2*n2 ), n2, info ) call stdlib${ii}$_zherk( 'U', 'C', n1, n2, one, a( 0_${ik}$ ), n2, one,a( n2*n2 ), n2 ) call stdlib${ii}$_ztrmm( 'L', 'L', 'C', 'N', n2, n1, cone, a( n1*n2 ),n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_zlauum( 'L', n2, a( n1*n2 ), n2, info ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_zlauum( 'L', k, a( 1_${ik}$ ), n+1, info ) call stdlib${ii}$_zherk( 'L', 'C', k, k, one, a( k+1 ), n+1, one,a( 1_${ik}$ ), n+1 ) call stdlib${ii}$_ztrmm( 'L', 'U', 'N', 'N', k, k, cone, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_zlauum( 'U', k, a( 0_${ik}$ ), n+1, info ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_zlauum( 'L', k, a( k+1 ), n+1, info ) call stdlib${ii}$_zherk( 'L', 'N', k, k, one, a( 0_${ik}$ ), n+1, one,a( k+1 ), n+1 ) call stdlib${ii}$_ztrmm( 'R', 'U', 'C', 'N', k, k, cone, a( k ), n+1,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_zlauum( 'U', k, a( k ), n+1, info ) end if else ! n is even and transr = 'c' if( lower ) then ! srpa for lower, transpose, and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1), ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_zlauum( 'U', k, a( k ), k, info ) call stdlib${ii}$_zherk( 'U', 'N', k, k, one, a( k*( k+1 ) ), k, one,a( k ), k ) call stdlib${ii}$_ztrmm( 'R', 'L', 'N', 'N', k, k, cone, a( 0_${ik}$ ), k,a( k*( k+1 ) ), & k ) call stdlib${ii}$_zlauum( 'L', k, a( 0_${ik}$ ), k, info ) else ! srpa for upper, transpose, and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0), ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_zlauum( 'U', k, a( k*( k+1 ) ), k, info ) call stdlib${ii}$_zherk( 'U', 'C', k, k, one, a( 0_${ik}$ ), k, one,a( k*( k+1 ) ), k ) call stdlib${ii}$_ztrmm( 'L', 'L', 'C', 'N', k, k, cone, a( k*k ), k,a( 0_${ik}$ ), k ) call stdlib${ii}$_zlauum( 'L', k, a( k*k ), k, info ) end if end if end if return end subroutine stdlib${ii}$_zpftri #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$pftri( transr, uplo, n, a, info ) !! ZPFTRI: computes the inverse of a complex Hermitian positive definite !! matrix A using the Cholesky factorization A = U**H*U or A = L*L**H !! computed by ZPFTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: transr, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments complex(${ck}$), intent(inout) :: a(0_${ik}$:*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, nisodd, normaltransr integer(${ik}$) :: n1, n2, k ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ normaltransr = stdlib_lsame( transr, 'N' ) lower = stdlib_lsame( uplo, 'L' ) if( .not.normaltransr .and. .not.stdlib_lsame( transr, 'C' ) ) then info = -1_${ik}$ else if( .not.lower .and. .not.stdlib_lsame( uplo, 'U' ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZPFTRI', -info ) return end if ! quick return if possible if( n==0 )return ! invert the triangular cholesky factor u or l. call stdlib${ii}$_${ci}$tftri( transr, uplo, 'N', n, a, info ) if( info>0 )return ! if n is odd, set nisodd = .true. ! if n is even, set k = n/2 and nisodd = .false. if( mod( n, 2_${ik}$ )==0_${ik}$ ) then k = n / 2_${ik}$ nisodd = .false. else nisodd = .true. end if ! set n1 and n2 depending on lower if( lower ) then n2 = n / 2_${ik}$ n1 = n - n2 else n1 = n / 2_${ik}$ n2 = n - n1 end if ! start execution of triangular matrix multiply: inv(u)*inv(u)^c or ! inv(l)^c*inv(l). there are eight cases. if( nisodd ) then ! n is odd if( normaltransr ) then ! n is odd and transr = 'n' if( lower ) then ! srpa for lower, normal and n is odd ( a(0:n-1,0:n1-1) ) ! t1 -> a(0,0), t2 -> a(0,1), s -> a(n1,0) ! t1 -> a(0), t2 -> a(n), s -> a(n1) call stdlib${ii}$_${ci}$lauum( 'L', n1, a( 0_${ik}$ ), n, info ) call stdlib${ii}$_${ci}$herk( 'L', 'C', n1, n2, one, a( n1 ), n, one,a( 0_${ik}$ ), n ) call stdlib${ii}$_${ci}$trmm( 'L', 'U', 'N', 'N', n2, n1, cone, a( n ), n,a( n1 ), n ) call stdlib${ii}$_${ci}$lauum( 'U', n2, a( n ), n, info ) else ! srpa for upper, normal and n is odd ( a(0:n-1,0:n2-1) ! t1 -> a(n1+1,0), t2 -> a(n1,0), s -> a(0,0) ! t1 -> a(n2), t2 -> a(n1), s -> a(0) call stdlib${ii}$_${ci}$lauum( 'L', n1, a( n2 ), n, info ) call stdlib${ii}$_${ci}$herk( 'L', 'N', n1, n2, one, a( 0_${ik}$ ), n, one,a( n2 ), n ) call stdlib${ii}$_${ci}$trmm( 'R', 'U', 'C', 'N', n1, n2, cone, a( n1 ), n,a( 0_${ik}$ ), n ) call stdlib${ii}$_${ci}$lauum( 'U', n2, a( n1 ), n, info ) end if else ! n is odd and transr = 'c' if( lower ) then ! srpa for lower, transpose, and n is odd ! t1 -> a(0), t2 -> a(1), s -> a(0+n1*n1) call stdlib${ii}$_${ci}$lauum( 'U', n1, a( 0_${ik}$ ), n1, info ) call stdlib${ii}$_${ci}$herk( 'U', 'N', n1, n2, one, a( n1*n1 ), n1, one,a( 0_${ik}$ ), n1 ) call stdlib${ii}$_${ci}$trmm( 'R', 'L', 'N', 'N', n1, n2, cone, a( 1_${ik}$ ), n1,a( n1*n1 ), & n1 ) call stdlib${ii}$_${ci}$lauum( 'L', n2, a( 1_${ik}$ ), n1, info ) else ! srpa for upper, transpose, and n is odd ! t1 -> a(0+n2*n2), t2 -> a(0+n1*n2), s -> a(0) call stdlib${ii}$_${ci}$lauum( 'U', n1, a( n2*n2 ), n2, info ) call stdlib${ii}$_${ci}$herk( 'U', 'C', n1, n2, one, a( 0_${ik}$ ), n2, one,a( n2*n2 ), n2 ) call stdlib${ii}$_${ci}$trmm( 'L', 'L', 'C', 'N', n2, n1, cone, a( n1*n2 ),n2, a( 0_${ik}$ ), & n2 ) call stdlib${ii}$_${ci}$lauum( 'L', n2, a( n1*n2 ), n2, info ) end if end if else ! n is even if( normaltransr ) then ! n is even and transr = 'n' if( lower ) then ! srpa for lower, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(1,0), t2 -> a(0,0), s -> a(k+1,0) ! t1 -> a(1), t2 -> a(0), s -> a(k+1) call stdlib${ii}$_${ci}$lauum( 'L', k, a( 1_${ik}$ ), n+1, info ) call stdlib${ii}$_${ci}$herk( 'L', 'C', k, k, one, a( k+1 ), n+1, one,a( 1_${ik}$ ), n+1 ) call stdlib${ii}$_${ci}$trmm( 'L', 'U', 'N', 'N', k, k, cone, a( 0_${ik}$ ), n+1,a( k+1 ), n+1 ) call stdlib${ii}$_${ci}$lauum( 'U', k, a( 0_${ik}$ ), n+1, info ) else ! srpa for upper, normal, and n is even ( a(0:n,0:k-1) ) ! t1 -> a(k+1,0) , t2 -> a(k,0), s -> a(0,0) ! t1 -> a(k+1), t2 -> a(k), s -> a(0) call stdlib${ii}$_${ci}$lauum( 'L', k, a( k+1 ), n+1, info ) call stdlib${ii}$_${ci}$herk( 'L', 'N', k, k, one, a( 0_${ik}$ ), n+1, one,a( k+1 ), n+1 ) call stdlib${ii}$_${ci}$trmm( 'R', 'U', 'C', 'N', k, k, cone, a( k ), n+1,a( 0_${ik}$ ), n+1 ) call stdlib${ii}$_${ci}$lauum( 'U', k, a( k ), n+1, info ) end if else ! n is even and transr = 'c' if( lower ) then ! srpa for lower, transpose, and n is even (see paper) ! t1 -> b(0,1), t2 -> b(0,0), s -> b(0,k+1), ! t1 -> a(0+k), t2 -> a(0+0), s -> a(0+k*(k+1)); lda=k call stdlib${ii}$_${ci}$lauum( 'U', k, a( k ), k, info ) call stdlib${ii}$_${ci}$herk( 'U', 'N', k, k, one, a( k*( k+1 ) ), k, one,a( k ), k ) call stdlib${ii}$_${ci}$trmm( 'R', 'L', 'N', 'N', k, k, cone, a( 0_${ik}$ ), k,a( k*( k+1 ) ), & k ) call stdlib${ii}$_${ci}$lauum( 'L', k, a( 0_${ik}$ ), k, info ) else ! srpa for upper, transpose, and n is even (see paper) ! t1 -> b(0,k+1), t2 -> b(0,k), s -> b(0,0), ! t1 -> a(0+k*(k+1)), t2 -> a(0+k*k), s -> a(0+0)); lda=k call stdlib${ii}$_${ci}$lauum( 'U', k, a( k*( k+1 ) ), k, info ) call stdlib${ii}$_${ci}$herk( 'U', 'C', k, k, one, a( 0_${ik}$ ), k, one,a( k*( k+1 ) ), k ) call stdlib${ii}$_${ci}$trmm( 'L', 'L', 'C', 'N', k, k, cone, a( k*k ), k,a( 0_${ik}$ ), k ) call stdlib${ii}$_${ci}$lauum( 'L', k, a( k*k ), k, info ) end if end if end if return end subroutine stdlib${ii}$_${ci}$pftri #:endif #:endfor pure module subroutine stdlib${ii}$_spbcon( uplo, n, kd, ab, ldab, anorm, rcond, work,iwork, info ) !! SPBCON estimates the reciprocal of the condition number (in the !! 1-norm) of a real symmetric positive definite band matrix using the !! Cholesky factorization A = U**T*U or A = L*L**T computed by SPBTRF. !! An estimate is obtained for norm(inv(A)), and the reciprocal of the !! condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: ab(ldab,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper character :: normin integer(${ik}$) :: ix, kase real(sp) :: ainvnm, scale, scalel, scaleu, smlnum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldabkd ) then ! use unblocked code call stdlib${ii}$_spbtf2( uplo, n, kd, ab, ldab, info ) else ! use blocked code if( stdlib_lsame( uplo, 'U' ) ) then ! compute the cholesky factorization of a symmetric band ! matrix, given the upper triangle of the matrix in band ! storage. ! zero the upper triangle of the work array. do j = 1, nb do i = 1, j - 1 work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_70: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_spotf2( uplo, ib, ab( kd+1, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 a12 a13 ! a22 a23 ! a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a12, a22 and ! a23 are empty if ib = kd. the upper triangle of a13 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_strsm( 'LEFT', 'UPPER', 'TRANSPOSE','NON-UNIT', ib, i2, one,& ab( kd+1, i ),ldab-1, ab( kd+1-ib, i+ib ), ldab-1 ) ! update a22 call stdlib${ii}$_ssyrk( 'UPPER', 'TRANSPOSE', i2, ib, -one,ab( kd+1-ib, i+ib & ), ldab-1, one,ab( kd+1, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array. do jj = 1, i3 do ii = jj, ib work( ii, jj ) = ab( ii-jj+1, jj+i+kd-1 ) end do end do ! update a13 (in the work array). call stdlib${ii}$_strsm( 'LEFT', 'UPPER', 'TRANSPOSE','NON-UNIT', ib, i3, one,& ab( kd+1, i ),ldab-1, work, ldwork ) ! update a23 if( i2>0_${ik}$ )call stdlib${ii}$_sgemm( 'TRANSPOSE', 'NO TRANSPOSE', i2, i3,ib, -& one, ab( kd+1-ib, i+ib ),ldab-1, work, ldwork, one,ab( 1_${ik}$+ib, i+kd ), & ldab-1 ) ! update a33 call stdlib${ii}$_ssyrk( 'UPPER', 'TRANSPOSE', i3, ib, -one,work, ldwork, one,& ab( kd+1, i+kd ),ldab-1 ) ! copy the lower triangle of a13 back into place. do jj = 1, i3 do ii = jj, ib ab( ii-jj+1, jj+i+kd-1 ) = work( ii, jj ) end do end do end if end if end do loop_70 else ! compute the cholesky factorization of a symmetric band ! matrix, given the lower triangle of the matrix in band ! storage. ! zero the lower triangle of the work array. do j = 1, nb do i = j + 1, nb work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_140: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_spotf2( uplo, ib, ab( 1_${ik}$, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 ! a21 a22 ! a31 a32 a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a21, a22 and ! a32 are empty if ib = kd. the lower triangle of a31 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a21 call stdlib${ii}$_strsm( 'RIGHT', 'LOWER', 'TRANSPOSE','NON-UNIT', i2, ib, & one, ab( 1_${ik}$, i ),ldab-1, ab( 1_${ik}$+ib, i ), ldab-1 ) ! update a22 call stdlib${ii}$_ssyrk( 'LOWER', 'NO TRANSPOSE', i2, ib, -one,ab( 1_${ik}$+ib, i ), & ldab-1, one,ab( 1_${ik}$, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the upper triangle of a31 into the work array. do jj = 1, ib do ii = 1, min( jj, i3 ) work( ii, jj ) = ab( kd+1-jj+ii, jj+i-1 ) end do end do ! update a31 (in the work array). call stdlib${ii}$_strsm( 'RIGHT', 'LOWER', 'TRANSPOSE','NON-UNIT', i3, ib, & one, ab( 1_${ik}$, i ),ldab-1, work, ldwork ) ! update a32 if( i2>0_${ik}$ )call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE', i3, i2,ib, -& one, work, ldwork,ab( 1_${ik}$+ib, i ), ldab-1, one,ab( 1_${ik}$+kd-ib, i+ib ), ldab-& 1_${ik}$ ) ! update a33 call stdlib${ii}$_ssyrk( 'LOWER', 'NO TRANSPOSE', i3, ib, -one,work, ldwork, & one, ab( 1_${ik}$, i+kd ),ldab-1 ) ! copy the upper triangle of a31 back into place. do jj = 1, ib do ii = 1, min( jj, i3 ) ab( kd+1-jj+ii, jj+i-1 ) = work( ii, jj ) end do end do end if end if end do loop_140 end if end if return 150 continue return end subroutine stdlib${ii}$_spbtrf pure module subroutine stdlib${ii}$_dpbtrf( uplo, n, kd, ab, ldab, info ) !! DPBTRF computes the Cholesky factorization of a real symmetric !! positive definite band matrix A. !! The factorization has the form !! A = U**T * U, if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments real(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 32_${ik}$ integer(${ik}$), parameter :: ldwork = nbmax+1 ! Local Scalars integer(${ik}$) :: i, i2, i3, ib, ii, j, jj, nb ! Local Arrays real(dp) :: work(ldwork,nbmax) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( ( .not.stdlib_lsame( uplo, 'U' ) ) .and.( .not.stdlib_lsame( uplo, 'L' ) ) ) & then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldabkd ) then ! use unblocked code call stdlib${ii}$_dpbtf2( uplo, n, kd, ab, ldab, info ) else ! use blocked code if( stdlib_lsame( uplo, 'U' ) ) then ! compute the cholesky factorization of a symmetric band ! matrix, given the upper triangle of the matrix in band ! storage. ! zero the upper triangle of the work array. do j = 1, nb do i = 1, j - 1 work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_70: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_dpotf2( uplo, ib, ab( kd+1, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 a12 a13 ! a22 a23 ! a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a12, a22 and ! a23 are empty if ib = kd. the upper triangle of a13 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_dtrsm( 'LEFT', 'UPPER', 'TRANSPOSE','NON-UNIT', ib, i2, one,& ab( kd+1, i ),ldab-1, ab( kd+1-ib, i+ib ), ldab-1 ) ! update a22 call stdlib${ii}$_dsyrk( 'UPPER', 'TRANSPOSE', i2, ib, -one,ab( kd+1-ib, i+ib & ), ldab-1, one,ab( kd+1, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array. do jj = 1, i3 do ii = jj, ib work( ii, jj ) = ab( ii-jj+1, jj+i+kd-1 ) end do end do ! update a13 (in the work array). call stdlib${ii}$_dtrsm( 'LEFT', 'UPPER', 'TRANSPOSE','NON-UNIT', ib, i3, one,& ab( kd+1, i ),ldab-1, work, ldwork ) ! update a23 if( i2>0_${ik}$ )call stdlib${ii}$_dgemm( 'TRANSPOSE', 'NO TRANSPOSE', i2, i3,ib, -& one, ab( kd+1-ib, i+ib ),ldab-1, work, ldwork, one,ab( 1_${ik}$+ib, i+kd ), & ldab-1 ) ! update a33 call stdlib${ii}$_dsyrk( 'UPPER', 'TRANSPOSE', i3, ib, -one,work, ldwork, one,& ab( kd+1, i+kd ),ldab-1 ) ! copy the lower triangle of a13 back into place. do jj = 1, i3 do ii = jj, ib ab( ii-jj+1, jj+i+kd-1 ) = work( ii, jj ) end do end do end if end if end do loop_70 else ! compute the cholesky factorization of a symmetric band ! matrix, given the lower triangle of the matrix in band ! storage. ! zero the lower triangle of the work array. do j = 1, nb do i = j + 1, nb work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_140: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_dpotf2( uplo, ib, ab( 1_${ik}$, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 ! a21 a22 ! a31 a32 a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a21, a22 and ! a32 are empty if ib = kd. the lower triangle of a31 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a21 call stdlib${ii}$_dtrsm( 'RIGHT', 'LOWER', 'TRANSPOSE','NON-UNIT', i2, ib, & one, ab( 1_${ik}$, i ),ldab-1, ab( 1_${ik}$+ib, i ), ldab-1 ) ! update a22 call stdlib${ii}$_dsyrk( 'LOWER', 'NO TRANSPOSE', i2, ib, -one,ab( 1_${ik}$+ib, i ), & ldab-1, one,ab( 1_${ik}$, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the upper triangle of a31 into the work array. do jj = 1, ib do ii = 1, min( jj, i3 ) work( ii, jj ) = ab( kd+1-jj+ii, jj+i-1 ) end do end do ! update a31 (in the work array). call stdlib${ii}$_dtrsm( 'RIGHT', 'LOWER', 'TRANSPOSE','NON-UNIT', i3, ib, & one, ab( 1_${ik}$, i ),ldab-1, work, ldwork ) ! update a32 if( i2>0_${ik}$ )call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE', i3, i2,ib, -& one, work, ldwork,ab( 1_${ik}$+ib, i ), ldab-1, one,ab( 1_${ik}$+kd-ib, i+ib ), ldab-& 1_${ik}$ ) ! update a33 call stdlib${ii}$_dsyrk( 'LOWER', 'NO TRANSPOSE', i3, ib, -one,work, ldwork, & one, ab( 1_${ik}$, i+kd ),ldab-1 ) ! copy the upper triangle of a31 back into place. do jj = 1, ib do ii = 1, min( jj, i3 ) ab( kd+1-jj+ii, jj+i-1 ) = work( ii, jj ) end do end do end if end if end do loop_140 end if end if return 150 continue return end subroutine stdlib${ii}$_dpbtrf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$pbtrf( uplo, n, kd, ab, ldab, info ) !! DPBTRF: computes the Cholesky factorization of a real symmetric !! positive definite band matrix A. !! The factorization has the form !! A = U**T * U, if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments real(${rk}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 32_${ik}$ integer(${ik}$), parameter :: ldwork = nbmax+1 ! Local Scalars integer(${ik}$) :: i, i2, i3, ib, ii, j, jj, nb ! Local Arrays real(${rk}$) :: work(ldwork,nbmax) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( ( .not.stdlib_lsame( uplo, 'U' ) ) .and.( .not.stdlib_lsame( uplo, 'L' ) ) ) & then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldabkd ) then ! use unblocked code call stdlib${ii}$_${ri}$pbtf2( uplo, n, kd, ab, ldab, info ) else ! use blocked code if( stdlib_lsame( uplo, 'U' ) ) then ! compute the cholesky factorization of a symmetric band ! matrix, given the upper triangle of the matrix in band ! storage. ! zero the upper triangle of the work array. do j = 1, nb do i = 1, j - 1 work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_70: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_${ri}$potf2( uplo, ib, ab( kd+1, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 a12 a13 ! a22 a23 ! a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a12, a22 and ! a23 are empty if ib = kd. the upper triangle of a13 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_${ri}$trsm( 'LEFT', 'UPPER', 'TRANSPOSE','NON-UNIT', ib, i2, one,& ab( kd+1, i ),ldab-1, ab( kd+1-ib, i+ib ), ldab-1 ) ! update a22 call stdlib${ii}$_${ri}$syrk( 'UPPER', 'TRANSPOSE', i2, ib, -one,ab( kd+1-ib, i+ib & ), ldab-1, one,ab( kd+1, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array. do jj = 1, i3 do ii = jj, ib work( ii, jj ) = ab( ii-jj+1, jj+i+kd-1 ) end do end do ! update a13 (in the work array). call stdlib${ii}$_${ri}$trsm( 'LEFT', 'UPPER', 'TRANSPOSE','NON-UNIT', ib, i3, one,& ab( kd+1, i ),ldab-1, work, ldwork ) ! update a23 if( i2>0_${ik}$ )call stdlib${ii}$_${ri}$gemm( 'TRANSPOSE', 'NO TRANSPOSE', i2, i3,ib, -& one, ab( kd+1-ib, i+ib ),ldab-1, work, ldwork, one,ab( 1_${ik}$+ib, i+kd ), & ldab-1 ) ! update a33 call stdlib${ii}$_${ri}$syrk( 'UPPER', 'TRANSPOSE', i3, ib, -one,work, ldwork, one,& ab( kd+1, i+kd ),ldab-1 ) ! copy the lower triangle of a13 back into place. do jj = 1, i3 do ii = jj, ib ab( ii-jj+1, jj+i+kd-1 ) = work( ii, jj ) end do end do end if end if end do loop_70 else ! compute the cholesky factorization of a symmetric band ! matrix, given the lower triangle of the matrix in band ! storage. ! zero the lower triangle of the work array. do j = 1, nb do i = j + 1, nb work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_140: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_${ri}$potf2( uplo, ib, ab( 1_${ik}$, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 ! a21 a22 ! a31 a32 a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a21, a22 and ! a32 are empty if ib = kd. the lower triangle of a31 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a21 call stdlib${ii}$_${ri}$trsm( 'RIGHT', 'LOWER', 'TRANSPOSE','NON-UNIT', i2, ib, & one, ab( 1_${ik}$, i ),ldab-1, ab( 1_${ik}$+ib, i ), ldab-1 ) ! update a22 call stdlib${ii}$_${ri}$syrk( 'LOWER', 'NO TRANSPOSE', i2, ib, -one,ab( 1_${ik}$+ib, i ), & ldab-1, one,ab( 1_${ik}$, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the upper triangle of a31 into the work array. do jj = 1, ib do ii = 1, min( jj, i3 ) work( ii, jj ) = ab( kd+1-jj+ii, jj+i-1 ) end do end do ! update a31 (in the work array). call stdlib${ii}$_${ri}$trsm( 'RIGHT', 'LOWER', 'TRANSPOSE','NON-UNIT', i3, ib, & one, ab( 1_${ik}$, i ),ldab-1, work, ldwork ) ! update a32 if( i2>0_${ik}$ )call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE', i3, i2,ib, -& one, work, ldwork,ab( 1_${ik}$+ib, i ), ldab-1, one,ab( 1_${ik}$+kd-ib, i+ib ), ldab-& 1_${ik}$ ) ! update a33 call stdlib${ii}$_${ri}$syrk( 'LOWER', 'NO TRANSPOSE', i3, ib, -one,work, ldwork, & one, ab( 1_${ik}$, i+kd ),ldab-1 ) ! copy the upper triangle of a31 back into place. do jj = 1, ib do ii = 1, min( jj, i3 ) ab( kd+1-jj+ii, jj+i-1 ) = work( ii, jj ) end do end do end if end if end do loop_140 end if end if return 150 continue return end subroutine stdlib${ii}$_${ri}$pbtrf #:endif #:endfor pure module subroutine stdlib${ii}$_cpbtrf( uplo, n, kd, ab, ldab, info ) !! CPBTRF computes the Cholesky factorization of a complex Hermitian !! positive definite band matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments complex(sp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 32_${ik}$ integer(${ik}$), parameter :: ldwork = nbmax+1 ! Local Scalars integer(${ik}$) :: i, i2, i3, ib, ii, j, jj, nb ! Local Arrays complex(sp) :: work(ldwork,nbmax) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( ( .not.stdlib_lsame( uplo, 'U' ) ) .and.( .not.stdlib_lsame( uplo, 'L' ) ) ) & then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldabkd ) then ! use unblocked code call stdlib${ii}$_cpbtf2( uplo, n, kd, ab, ldab, info ) else ! use blocked code if( stdlib_lsame( uplo, 'U' ) ) then ! compute the cholesky factorization of a hermitian band ! matrix, given the upper triangle of the matrix in band ! storage. ! zero the upper triangle of the work array. do j = 1, nb do i = 1, j - 1 work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_70: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_cpotf2( uplo, ib, ab( kd+1, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 a12 a13 ! a22 a23 ! a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a12, a22 and ! a23 are empty if ib = kd. the upper triangle of a13 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_ctrsm( 'LEFT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', & ib, i2, cone,ab( kd+1, i ), ldab-1,ab( kd+1-ib, i+ib ), ldab-1 ) ! update a22 call stdlib${ii}$_cherk( 'UPPER', 'CONJUGATE TRANSPOSE', i2, ib,-one, ab( kd+& 1_${ik}$-ib, i+ib ), ldab-1, one,ab( kd+1, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array. do jj = 1, i3 do ii = jj, ib work( ii, jj ) = ab( ii-jj+1, jj+i+kd-1 ) end do end do ! update a13 (in the work array). call stdlib${ii}$_ctrsm( 'LEFT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', & ib, i3, cone,ab( kd+1, i ), ldab-1, work, ldwork ) ! update a23 if( i2>0_${ik}$ )call stdlib${ii}$_cgemm( 'CONJUGATE TRANSPOSE','NO TRANSPOSE', i2, & i3, ib, -cone,ab( kd+1-ib, i+ib ), ldab-1, work,ldwork, cone, ab( 1_${ik}$+ib, & i+kd ),ldab-1 ) ! update a33 call stdlib${ii}$_cherk( 'UPPER', 'CONJUGATE TRANSPOSE', i3, ib,-one, work, & ldwork, one,ab( kd+1, i+kd ), ldab-1 ) ! copy the lower triangle of a13 back into place. do jj = 1, i3 do ii = jj, ib ab( ii-jj+1, jj+i+kd-1 ) = work( ii, jj ) end do end do end if end if end do loop_70 else ! compute the cholesky factorization of a hermitian band ! matrix, given the lower triangle of the matrix in band ! storage. ! zero the lower triangle of the work array. do j = 1, nb do i = j + 1, nb work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_140: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_cpotf2( uplo, ib, ab( 1_${ik}$, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 ! a21 a22 ! a31 a32 a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a21, a22 and ! a32 are empty if ib = kd. the lower triangle of a31 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a21 call stdlib${ii}$_ctrsm( 'RIGHT', 'LOWER','CONJUGATE TRANSPOSE', 'NON-UNIT', & i2,ib, cone, ab( 1_${ik}$, i ), ldab-1,ab( 1_${ik}$+ib, i ), ldab-1 ) ! update a22 call stdlib${ii}$_cherk( 'LOWER', 'NO TRANSPOSE', i2, ib, -one,ab( 1_${ik}$+ib, i ), & ldab-1, one,ab( 1_${ik}$, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the upper triangle of a31 into the work array. do jj = 1, ib do ii = 1, min( jj, i3 ) work( ii, jj ) = ab( kd+1-jj+ii, jj+i-1 ) end do end do ! update a31 (in the work array). call stdlib${ii}$_ctrsm( 'RIGHT', 'LOWER','CONJUGATE TRANSPOSE', 'NON-UNIT', & i3,ib, cone, ab( 1_${ik}$, i ), ldab-1, work,ldwork ) ! update a32 if( i2>0_${ik}$ )call stdlib${ii}$_cgemm( 'NO TRANSPOSE','CONJUGATE TRANSPOSE', i3, & i2, ib,-cone, work, ldwork, ab( 1_${ik}$+ib, i ),ldab-1, cone, ab( 1_${ik}$+kd-ib, i+& ib ),ldab-1 ) ! update a33 call stdlib${ii}$_cherk( 'LOWER', 'NO TRANSPOSE', i3, ib, -one,work, ldwork, & one, ab( 1_${ik}$, i+kd ),ldab-1 ) ! copy the upper triangle of a31 back into place. do jj = 1, ib do ii = 1, min( jj, i3 ) ab( kd+1-jj+ii, jj+i-1 ) = work( ii, jj ) end do end do end if end if end do loop_140 end if end if return 150 continue return end subroutine stdlib${ii}$_cpbtrf pure module subroutine stdlib${ii}$_zpbtrf( uplo, n, kd, ab, ldab, info ) !! ZPBTRF computes the Cholesky factorization of a complex Hermitian !! positive definite band matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments complex(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 32_${ik}$ integer(${ik}$), parameter :: ldwork = nbmax+1 ! Local Scalars integer(${ik}$) :: i, i2, i3, ib, ii, j, jj, nb ! Local Arrays complex(dp) :: work(ldwork,nbmax) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( ( .not.stdlib_lsame( uplo, 'U' ) ) .and.( .not.stdlib_lsame( uplo, 'L' ) ) ) & then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldabkd ) then ! use unblocked code call stdlib${ii}$_zpbtf2( uplo, n, kd, ab, ldab, info ) else ! use blocked code if( stdlib_lsame( uplo, 'U' ) ) then ! compute the cholesky factorization of a hermitian band ! matrix, given the upper triangle of the matrix in band ! storage. ! zero the upper triangle of the work array. do j = 1, nb do i = 1, j - 1 work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_70: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_zpotf2( uplo, ib, ab( kd+1, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 a12 a13 ! a22 a23 ! a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a12, a22 and ! a23 are empty if ib = kd. the upper triangle of a13 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_ztrsm( 'LEFT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', & ib, i2, cone,ab( kd+1, i ), ldab-1,ab( kd+1-ib, i+ib ), ldab-1 ) ! update a22 call stdlib${ii}$_zherk( 'UPPER', 'CONJUGATE TRANSPOSE', i2, ib,-one, ab( kd+& 1_${ik}$-ib, i+ib ), ldab-1, one,ab( kd+1, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array. do jj = 1, i3 do ii = jj, ib work( ii, jj ) = ab( ii-jj+1, jj+i+kd-1 ) end do end do ! update a13 (in the work array). call stdlib${ii}$_ztrsm( 'LEFT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', & ib, i3, cone,ab( kd+1, i ), ldab-1, work, ldwork ) ! update a23 if( i2>0_${ik}$ )call stdlib${ii}$_zgemm( 'CONJUGATE TRANSPOSE','NO TRANSPOSE', i2, & i3, ib, -cone,ab( kd+1-ib, i+ib ), ldab-1, work,ldwork, cone, ab( 1_${ik}$+ib, & i+kd ),ldab-1 ) ! update a33 call stdlib${ii}$_zherk( 'UPPER', 'CONJUGATE TRANSPOSE', i3, ib,-one, work, & ldwork, one,ab( kd+1, i+kd ), ldab-1 ) ! copy the lower triangle of a13 back into place. do jj = 1, i3 do ii = jj, ib ab( ii-jj+1, jj+i+kd-1 ) = work( ii, jj ) end do end do end if end if end do loop_70 else ! compute the cholesky factorization of a hermitian band ! matrix, given the lower triangle of the matrix in band ! storage. ! zero the lower triangle of the work array. do j = 1, nb do i = j + 1, nb work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_140: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_zpotf2( uplo, ib, ab( 1_${ik}$, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 ! a21 a22 ! a31 a32 a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a21, a22 and ! a32 are empty if ib = kd. the lower triangle of a31 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a21 call stdlib${ii}$_ztrsm( 'RIGHT', 'LOWER','CONJUGATE TRANSPOSE', 'NON-UNIT', & i2,ib, cone, ab( 1_${ik}$, i ), ldab-1,ab( 1_${ik}$+ib, i ), ldab-1 ) ! update a22 call stdlib${ii}$_zherk( 'LOWER', 'NO TRANSPOSE', i2, ib, -one,ab( 1_${ik}$+ib, i ), & ldab-1, one,ab( 1_${ik}$, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the upper triangle of a31 into the work array. do jj = 1, ib do ii = 1, min( jj, i3 ) work( ii, jj ) = ab( kd+1-jj+ii, jj+i-1 ) end do end do ! update a31 (in the work array). call stdlib${ii}$_ztrsm( 'RIGHT', 'LOWER','CONJUGATE TRANSPOSE', 'NON-UNIT', & i3,ib, cone, ab( 1_${ik}$, i ), ldab-1, work,ldwork ) ! update a32 if( i2>0_${ik}$ )call stdlib${ii}$_zgemm( 'NO TRANSPOSE','CONJUGATE TRANSPOSE', i3, & i2, ib,-cone, work, ldwork, ab( 1_${ik}$+ib, i ),ldab-1, cone, ab( 1_${ik}$+kd-ib, i+& ib ),ldab-1 ) ! update a33 call stdlib${ii}$_zherk( 'LOWER', 'NO TRANSPOSE', i3, ib, -one,work, ldwork, & one, ab( 1_${ik}$, i+kd ),ldab-1 ) ! copy the upper triangle of a31 back into place. do jj = 1, ib do ii = 1, min( jj, i3 ) ab( kd+1-jj+ii, jj+i-1 ) = work( ii, jj ) end do end do end if end if end do loop_140 end if end if return 150 continue return end subroutine stdlib${ii}$_zpbtrf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$pbtrf( uplo, n, kd, ab, ldab, info ) !! ZPBTRF: computes the Cholesky factorization of a complex Hermitian !! positive definite band matrix A. !! The factorization has the form !! A = U**H * U, if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix and L is lower triangular. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments complex(${ck}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: nbmax = 32_${ik}$ integer(${ik}$), parameter :: ldwork = nbmax+1 ! Local Scalars integer(${ik}$) :: i, i2, i3, ib, ii, j, jj, nb ! Local Arrays complex(${ck}$) :: work(ldwork,nbmax) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( ( .not.stdlib_lsame( uplo, 'U' ) ) .and.( .not.stdlib_lsame( uplo, 'L' ) ) ) & then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldabkd ) then ! use unblocked code call stdlib${ii}$_${ci}$pbtf2( uplo, n, kd, ab, ldab, info ) else ! use blocked code if( stdlib_lsame( uplo, 'U' ) ) then ! compute the cholesky factorization of a hermitian band ! matrix, given the upper triangle of the matrix in band ! storage. ! zero the upper triangle of the work array. do j = 1, nb do i = 1, j - 1 work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_70: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_${ci}$potf2( uplo, ib, ab( kd+1, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 a12 a13 ! a22 a23 ! a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a12, a22 and ! a23 are empty if ib = kd. the upper triangle of a13 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a12 call stdlib${ii}$_${ci}$trsm( 'LEFT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', & ib, i2, cone,ab( kd+1, i ), ldab-1,ab( kd+1-ib, i+ib ), ldab-1 ) ! update a22 call stdlib${ii}$_${ci}$herk( 'UPPER', 'CONJUGATE TRANSPOSE', i2, ib,-one, ab( kd+& 1_${ik}$-ib, i+ib ), ldab-1, one,ab( kd+1, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the lower triangle of a13 into the work array. do jj = 1, i3 do ii = jj, ib work( ii, jj ) = ab( ii-jj+1, jj+i+kd-1 ) end do end do ! update a13 (in the work array). call stdlib${ii}$_${ci}$trsm( 'LEFT', 'UPPER', 'CONJUGATE TRANSPOSE','NON-UNIT', & ib, i3, cone,ab( kd+1, i ), ldab-1, work, ldwork ) ! update a23 if( i2>0_${ik}$ )call stdlib${ii}$_${ci}$gemm( 'CONJUGATE TRANSPOSE','NO TRANSPOSE', i2, & i3, ib, -cone,ab( kd+1-ib, i+ib ), ldab-1, work,ldwork, cone, ab( 1_${ik}$+ib, & i+kd ),ldab-1 ) ! update a33 call stdlib${ii}$_${ci}$herk( 'UPPER', 'CONJUGATE TRANSPOSE', i3, ib,-one, work, & ldwork, one,ab( kd+1, i+kd ), ldab-1 ) ! copy the lower triangle of a13 back into place. do jj = 1, i3 do ii = jj, ib ab( ii-jj+1, jj+i+kd-1 ) = work( ii, jj ) end do end do end if end if end do loop_70 else ! compute the cholesky factorization of a hermitian band ! matrix, given the lower triangle of the matrix in band ! storage. ! zero the lower triangle of the work array. do j = 1, nb do i = j + 1, nb work( i, j ) = zero end do end do ! process the band matrix one diagonal block at a time. loop_140: do i = 1, n, nb ib = min( nb, n-i+1 ) ! factorize the diagonal block call stdlib${ii}$_${ci}$potf2( uplo, ib, ab( 1_${ik}$, i ), ldab-1, ii ) if( ii/=0_${ik}$ ) then info = i + ii - 1_${ik}$ go to 150 end if if( i+ib<=n ) then ! update the relevant part of the trailing submatrix. ! if a11 denotes the diagonal block which has just been ! factorized, then we need to update the remaining ! blocks in the diagram: ! a11 ! a21 a22 ! a31 a32 a33 ! the numbers of rows and columns in the partitioning ! are ib, i2, i3 respectively. the blocks a21, a22 and ! a32 are empty if ib = kd. the lower triangle of a31 ! lies outside the band. i2 = min( kd-ib, n-i-ib+1 ) i3 = min( ib, n-i-kd+1 ) if( i2>0_${ik}$ ) then ! update a21 call stdlib${ii}$_${ci}$trsm( 'RIGHT', 'LOWER','CONJUGATE TRANSPOSE', 'NON-UNIT', & i2,ib, cone, ab( 1_${ik}$, i ), ldab-1,ab( 1_${ik}$+ib, i ), ldab-1 ) ! update a22 call stdlib${ii}$_${ci}$herk( 'LOWER', 'NO TRANSPOSE', i2, ib, -one,ab( 1_${ik}$+ib, i ), & ldab-1, one,ab( 1_${ik}$, i+ib ), ldab-1 ) end if if( i3>0_${ik}$ ) then ! copy the upper triangle of a31 into the work array. do jj = 1, ib do ii = 1, min( jj, i3 ) work( ii, jj ) = ab( kd+1-jj+ii, jj+i-1 ) end do end do ! update a31 (in the work array). call stdlib${ii}$_${ci}$trsm( 'RIGHT', 'LOWER','CONJUGATE TRANSPOSE', 'NON-UNIT', & i3,ib, cone, ab( 1_${ik}$, i ), ldab-1, work,ldwork ) ! update a32 if( i2>0_${ik}$ )call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE','CONJUGATE TRANSPOSE', i3, & i2, ib,-cone, work, ldwork, ab( 1_${ik}$+ib, i ),ldab-1, cone, ab( 1_${ik}$+kd-ib, i+& ib ),ldab-1 ) ! update a33 call stdlib${ii}$_${ci}$herk( 'LOWER', 'NO TRANSPOSE', i3, ib, -one,work, ldwork, & one, ab( 1_${ik}$, i+kd ),ldab-1 ) ! copy the upper triangle of a31 back into place. do jj = 1, ib do ii = 1, min( jj, i3 ) ab( kd+1-jj+ii, jj+i-1 ) = work( ii, jj ) end do end do end if end if end do loop_140 end if end if return 150 continue return end subroutine stdlib${ii}$_${ci}$pbtrf #:endif #:endfor pure module subroutine stdlib${ii}$_spbtf2( uplo, n, kd, ab, ldab, info ) !! SPBTF2 computes the Cholesky factorization of a real symmetric !! positive definite band matrix A. !! The factorization has the form !! A = U**T * U , if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix, U**T is the transpose of U, and !! L is lower triangular. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments real(sp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, kn real(sp) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_sscal( kn, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_ssyr( 'UPPER', kn, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) end if end do else ! compute the cholesky factorization a = l*l**t. do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = ab( 1_${ik}$, j ) if( ajj<=zero )go to 30 ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj ! compute elements j+1:j+kn of column j and update the ! trailing submatrix within the band. kn = min( kd, n-j ) if( kn>0_${ik}$ ) then call stdlib${ii}$_sscal( kn, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_ssyr( 'LOWER', kn, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 30 continue info = j return end subroutine stdlib${ii}$_spbtf2 pure module subroutine stdlib${ii}$_dpbtf2( uplo, n, kd, ab, ldab, info ) !! DPBTF2 computes the Cholesky factorization of a real symmetric !! positive definite band matrix A. !! The factorization has the form !! A = U**T * U , if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix, U**T is the transpose of U, and !! L is lower triangular. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments real(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, kn real(dp) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_dscal( kn, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_dsyr( 'UPPER', kn, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) end if end do else ! compute the cholesky factorization a = l*l**t. do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = ab( 1_${ik}$, j ) if( ajj<=zero )go to 30 ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj ! compute elements j+1:j+kn of column j and update the ! trailing submatrix within the band. kn = min( kd, n-j ) if( kn>0_${ik}$ ) then call stdlib${ii}$_dscal( kn, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_dsyr( 'LOWER', kn, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 30 continue info = j return end subroutine stdlib${ii}$_dpbtf2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$pbtf2( uplo, n, kd, ab, ldab, info ) !! DPBTF2: computes the Cholesky factorization of a real symmetric !! positive definite band matrix A. !! The factorization has the form !! A = U**T * U , if UPLO = 'U', or !! A = L * L**T, if UPLO = 'L', !! where U is an upper triangular matrix, U**T is the transpose of U, and !! L is lower triangular. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments real(${rk}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, kn real(${rk}$) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_${ri}$scal( kn, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_${ri}$syr( 'UPPER', kn, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) end if end do else ! compute the cholesky factorization a = l*l**t. do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = ab( 1_${ik}$, j ) if( ajj<=zero )go to 30 ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj ! compute elements j+1:j+kn of column j and update the ! trailing submatrix within the band. kn = min( kd, n-j ) if( kn>0_${ik}$ ) then call stdlib${ii}$_${ri}$scal( kn, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ri}$syr( 'LOWER', kn, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 30 continue info = j return end subroutine stdlib${ii}$_${ri}$pbtf2 #:endif #:endfor pure module subroutine stdlib${ii}$_cpbtf2( uplo, n, kd, ab, ldab, info ) !! CPBTF2 computes the Cholesky factorization of a complex Hermitian !! positive definite band matrix A. !! The factorization has the form !! A = U**H * U , if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix, U**H is the conjugate transpose !! of U, and L is lower triangular. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments complex(sp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, kn real(sp) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_csscal( kn, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_clacgv( kn, ab( kd, j+1 ), kld ) call stdlib${ii}$_cher( 'UPPER', kn, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) call stdlib${ii}$_clacgv( kn, ab( kd, j+1 ), kld ) end if end do else ! compute the cholesky factorization a = l*l**h. do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = real( ab( 1_${ik}$, j ),KIND=sp) if( ajj<=zero ) then ab( 1_${ik}$, j ) = ajj go to 30 end if ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj ! compute elements j+1:j+kn of column j and update the ! trailing submatrix within the band. kn = min( kd, n-j ) if( kn>0_${ik}$ ) then call stdlib${ii}$_csscal( kn, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_cher( 'LOWER', kn, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 30 continue info = j return end subroutine stdlib${ii}$_cpbtf2 pure module subroutine stdlib${ii}$_zpbtf2( uplo, n, kd, ab, ldab, info ) !! ZPBTF2 computes the Cholesky factorization of a complex Hermitian !! positive definite band matrix A. !! The factorization has the form !! A = U**H * U , if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix, U**H is the conjugate transpose !! of U, and L is lower triangular. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments complex(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, kn real(dp) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_zdscal( kn, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_zlacgv( kn, ab( kd, j+1 ), kld ) call stdlib${ii}$_zher( 'UPPER', kn, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) call stdlib${ii}$_zlacgv( kn, ab( kd, j+1 ), kld ) end if end do else ! compute the cholesky factorization a = l*l**h. do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = real( ab( 1_${ik}$, j ),KIND=dp) if( ajj<=zero ) then ab( 1_${ik}$, j ) = ajj go to 30 end if ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj ! compute elements j+1:j+kn of column j and update the ! trailing submatrix within the band. kn = min( kd, n-j ) if( kn>0_${ik}$ ) then call stdlib${ii}$_zdscal( kn, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_zher( 'LOWER', kn, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 30 continue info = j return end subroutine stdlib${ii}$_zpbtf2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$pbtf2( uplo, n, kd, ab, ldab, info ) !! ZPBTF2: computes the Cholesky factorization of a complex Hermitian !! positive definite band matrix A. !! The factorization has the form !! A = U**H * U , if UPLO = 'U', or !! A = L * L**H, if UPLO = 'L', !! where U is an upper triangular matrix, U**H is the conjugate transpose !! of U, and L is lower triangular. !! This is the unblocked version of the algorithm, calling Level 2 BLAS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n ! Array Arguments complex(${ck}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j, kld, kn real(${ck}$) :: ajj ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab0_${ik}$ ) then call stdlib${ii}$_${ci}$dscal( kn, one / ajj, ab( kd, j+1 ), kld ) call stdlib${ii}$_${ci}$lacgv( kn, ab( kd, j+1 ), kld ) call stdlib${ii}$_${ci}$her( 'UPPER', kn, -one, ab( kd, j+1 ), kld,ab( kd+1, j+1 ), kld ) call stdlib${ii}$_${ci}$lacgv( kn, ab( kd, j+1 ), kld ) end if end do else ! compute the cholesky factorization a = l*l**h. do j = 1, n ! compute l(j,j) and test for non-positive-definiteness. ajj = real( ab( 1_${ik}$, j ),KIND=${ck}$) if( ajj<=zero ) then ab( 1_${ik}$, j ) = ajj go to 30 end if ajj = sqrt( ajj ) ab( 1_${ik}$, j ) = ajj ! compute elements j+1:j+kn of column j and update the ! trailing submatrix within the band. kn = min( kd, n-j ) if( kn>0_${ik}$ ) then call stdlib${ii}$_${ci}$dscal( kn, one / ajj, ab( 2_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$her( 'LOWER', kn, -one, ab( 2_${ik}$, j ), 1_${ik}$,ab( 1_${ik}$, j+1 ), kld ) end if end do end if return 30 continue info = j return end subroutine stdlib${ii}$_${ci}$pbtf2 #:endif #:endfor pure module subroutine stdlib${ii}$_spbtrs( uplo, n, kd, nrhs, ab, ldab, b, ldb, info ) !! SPBTRS solves a system of linear equations A*X = B with a symmetric !! positive definite band matrix A using the Cholesky factorization !! A = U**T*U or A = L*L**T computed by SPBTRF. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldb, n, nrhs ! Array Arguments real(sp), intent(in) :: ab(ldab,*) real(sp), intent(inout) :: b(ldb,*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: j ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( ldabsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_spbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work( n+1 ), n,info ) call stdlib${ii}$_saxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_slacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_slacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_spbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work( n+1 ), n,info ) do i = 1, n work( n+i ) = work( n+i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( n+i )*work( i ) end do call stdlib${ii}$_spbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_spbrfs pure module subroutine stdlib${ii}$_dpbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b,ldb, x, ldx, ferr, & !! DPBRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric positive definite !! and banded, and provides error bounds and backward error estimates !! for the solution. berr, work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldafb, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: ab(ldab,*), afb(ldafb,*), b(ldb,*) real(dp), intent(out) :: berr(*), ferr(*), work(*) real(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, l, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( ldabsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_dpbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work( n+1 ), n,info ) call stdlib${ii}$_daxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_dlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_dlacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_dpbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work( n+1 ), n,info ) do i = 1, n work( n+i ) = work( n+i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( n+i )*work( i ) end do call stdlib${ii}$_dpbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_dpbrfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$pbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b,ldb, x, ldx, ferr, & !! DPBRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric positive definite !! and banded, and provides error bounds and backward error estimates !! for the solution. berr, work, iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldafb, ldb, ldx, n, nrhs ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: ab(ldab,*), afb(ldafb,*), b(ldb,*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) real(${rk}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, l, nz real(${rk}$) :: eps, lstres, s, safe1, safe2, safmin, xk ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( ldabsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ri}$pbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work( n+1 ), n,info ) call stdlib${ii}$_${ri}$axpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ri}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ri}$lacn2( n, work( 2_${ik}$*n+1 ), work( n+1 ), iwork, ferr( j ),kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**t). call stdlib${ii}$_${ri}$pbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work( n+1 ), n,info ) do i = 1, n work( n+i ) = work( n+i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( n+i ) = work( n+i )*work( i ) end do call stdlib${ii}$_${ri}$pbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work( n+1 ), n,info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ri}$pbrfs #:endif #:endfor pure module subroutine stdlib${ii}$_cpbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b,ldb, x, ldx, ferr, & !! CPBRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and banded, and provides error bounds and backward error estimates !! for the solution. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldafb, ldb, ldx, n, nrhs ! Array Arguments real(sp), intent(out) :: berr(*), ferr(*), rwork(*) complex(sp), intent(in) :: ab(ldab,*), afb(ldafb,*), b(ldb,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, l, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(sp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( ldabsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_cpbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work, n, info ) call stdlib${ii}$_caxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_clacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_clacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_cpbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_cpbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_cpbrfs pure module subroutine stdlib${ii}$_zpbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b,ldb, x, ldx, ferr, & !! ZPBRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and banded, and provides error bounds and backward error estimates !! for the solution. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldafb, ldb, ldx, n, nrhs ! Array Arguments real(dp), intent(out) :: berr(*), ferr(*), rwork(*) complex(dp), intent(in) :: ab(ldab,*), afb(ldafb,*), b(ldb,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, l, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin, xk complex(dp) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( ldabsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_zpbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work, n, info ) call stdlib${ii}$_zaxpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_zlacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_zlacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_zpbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_zpbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_zpbrfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$pbrfs( uplo, n, kd, nrhs, ab, ldab, afb, ldafb, b,ldb, x, ldx, ferr, & !! ZPBRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and banded, and provides error bounds and backward error estimates !! for the solution. berr, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldafb, ldb, ldx, n, nrhs ! Array Arguments real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) complex(${ck}$), intent(in) :: ab(ldab,*), afb(ldafb,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, j, k, kase, l, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin, xk complex(${ck}$) :: zdum ! Local Arrays integer(${ik}$) :: isave(3_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( nrhs<0_${ik}$ ) then info = -4_${ik}$ else if( ldabsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ci}$pbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work, n, info ) call stdlib${ii}$_${ci}$axpy( n, cone, work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. ! use stdlib_${ci}$lacn2 to estimate the infinity-norm of the matrix ! inv(a) * diag(w), ! where w = abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do kase = 0_${ik}$ 100 continue call stdlib${ii}$_${ci}$lacn2( n, work( n+1 ), work, ferr( j ), kase, isave ) if( kase/=0_${ik}$ ) then if( kase==1_${ik}$ ) then ! multiply by diag(w)*inv(a**h). call stdlib${ii}$_${ci}$pbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work, n, info ) do i = 1, n work( i ) = rwork( i )*work( i ) end do else if( kase==2_${ik}$ ) then ! multiply by inv(a)*diag(w). do i = 1, n work( i ) = rwork( i )*work( i ) end do call stdlib${ii}$_${ci}$pbtrs( uplo, n, kd, 1_${ik}$, afb, ldafb, work, n, info ) end if go to 100 end if ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, cabs1( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_140 return end subroutine stdlib${ii}$_${ci}$pbrfs #:endif #:endfor pure module subroutine stdlib${ii}$_spbequ( uplo, n, kd, ab, ldab, s, scond, amax, info ) !! SPBEQU computes row and column scalings intended to equilibrate a !! symmetric positive definite band matrix A and reduce its condition !! number (with respect to the two-norm). S contains the scale factors, !! S(i) = 1/sqrt(A(i,i)), chosen so that the scaled matrix B with !! elements B(i,j) = S(i)*A(i,j)*S(j) has ones on the diagonal. This !! choice of S puts the condition number of B within a factor N of the !! smallest possible condition number over all possible diagonal !! scalings. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, n real(sp), intent(out) :: amax, scond ! Array Arguments real(sp), intent(in) :: ab(ldab,*) real(sp), intent(out) :: s(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: i, j real(sp) :: smin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( kd<0_${ik}$ ) then info = -3_${ik}$ else if( ldab=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored in band format. do j = 1, n cj = s( j ) do i = max( 1, j-kd ), j - 1 ab( kd+1+i-j, j ) = cj*s( i )*ab( kd+1+i-j, j ) end do ab( kd+1, j ) = cj*cj*real( ab( kd+1, j ),KIND=sp) end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) ab( 1_${ik}$, j ) = cj*cj*real( ab( 1_${ik}$, j ),KIND=sp) do i = j + 1, min( n, j+kd ) ab( 1_${ik}$+i-j, j ) = cj*s( i )*ab( 1_${ik}$+i-j, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_claqhb pure module subroutine stdlib${ii}$_zlaqhb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) !! ZLAQHB equilibrates a Hermitian band matrix A !! using the scaling factors in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(dp), intent(in) :: amax, scond ! Array Arguments real(dp), intent(out) :: s(*) complex(dp), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j real(dp) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored in band format. do j = 1, n cj = s( j ) do i = max( 1, j-kd ), j - 1 ab( kd+1+i-j, j ) = cj*s( i )*ab( kd+1+i-j, j ) end do ab( kd+1, j ) = cj*cj*real( ab( kd+1, j ),KIND=dp) end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) ab( 1_${ik}$, j ) = cj*cj*real( ab( 1_${ik}$, j ),KIND=dp) do i = j + 1, min( n, j+kd ) ab( 1_${ik}$+i-j, j ) = cj*s( i )*ab( 1_${ik}$+i-j, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_zlaqhb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqhb( uplo, n, kd, ab, ldab, s, scond, amax, equed ) !! ZLAQHB: equilibrates a Hermitian band matrix A !! using the scaling factors in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: kd, ldab, n real(${ck}$), intent(in) :: amax, scond ! Array Arguments real(${ck}$), intent(out) :: s(*) complex(${ck}$), intent(inout) :: ab(ldab,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: thresh = 0.1e+0_${ck}$ ! Local Scalars integer(${ik}$) :: i, j real(${ck}$) :: cj, large, small ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored in band format. do j = 1, n cj = s( j ) do i = max( 1, j-kd ), j - 1 ab( kd+1+i-j, j ) = cj*s( i )*ab( kd+1+i-j, j ) end do ab( kd+1, j ) = cj*cj*real( ab( kd+1, j ),KIND=${ck}$) end do else ! lower triangle of a is stored. do j = 1, n cj = s( j ) ab( 1_${ik}$, j ) = cj*cj*real( ab( 1_${ik}$, j ),KIND=${ck}$) do i = j + 1, min( n, j+kd ) ab( 1_${ik}$+i-j, j ) = cj*s( i )*ab( 1_${ik}$+i-j, j ) end do end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_${ci}$laqhb #:endif #:endfor pure module subroutine stdlib${ii}$_sptcon( n, d, e, anorm, rcond, work, info ) !! SPTCON computes the reciprocal of the condition number (in the !! 1-norm) of a real symmetric positive definite tridiagonal matrix !! using the factorization A = L*D*L**T or A = U**T*D*U computed by !! SPTTRF. !! Norm(inv(A)) is computed by a direct method, and the reciprocal of !! the condition number is computed as !! RCOND = 1 / (ANORM * norm(inv(A))). ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n real(sp), intent(in) :: anorm real(sp), intent(out) :: rcond ! Array Arguments real(sp), intent(in) :: d(*), e(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ix real(sp) :: ainvnm ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( anorm=nrhs ) then call stdlib${ii}$_sptts2( n, nrhs, d, e, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_sptts2( n, jb, d, e, b( 1_${ik}$, j ), ldb ) end do end if return end subroutine stdlib${ii}$_spttrs pure module subroutine stdlib${ii}$_dpttrs( n, nrhs, d, e, b, ldb, info ) !! DPTTRS solves a tridiagonal system of the form !! A * X = B !! using the L*D*L**T factorization of A computed by DPTTRF. D is a !! diagonal matrix specified in the vector D, L is a unit bidiagonal !! matrix whose subdiagonal is specified in the vector E, and X and B !! are N by NRHS matrices. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments real(dp), intent(inout) :: b(ldb,*) real(dp), intent(in) :: d(*), e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( nrhs<0_${ik}$ ) then info = -2_${ik}$ else if( ldb=nrhs ) then call stdlib${ii}$_dptts2( n, nrhs, d, e, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_dptts2( n, jb, d, e, b( 1_${ik}$, j ), ldb ) end do end if return end subroutine stdlib${ii}$_dpttrs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$pttrs( n, nrhs, d, e, b, ldb, info ) !! DPTTRS: solves a tridiagonal system of the form !! A * X = B !! using the L*D*L**T factorization of A computed by DPTTRF. D is a !! diagonal matrix specified in the vector D, L is a unit bidiagonal !! matrix whose subdiagonal is specified in the vector E, and X and B !! are N by NRHS matrices. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments real(${rk}$), intent(inout) :: b(ldb,*) real(${rk}$), intent(in) :: d(*), e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( nrhs<0_${ik}$ ) then info = -2_${ik}$ else if( ldb=nrhs ) then call stdlib${ii}$_${ri}$ptts2( n, nrhs, d, e, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_${ri}$ptts2( n, jb, d, e, b( 1_${ik}$, j ), ldb ) end do end if return end subroutine stdlib${ii}$_${ri}$pttrs #:endif #:endfor pure module subroutine stdlib${ii}$_cpttrs( uplo, n, nrhs, d, e, b, ldb, info ) !! CPTTRS solves a tridiagonal system of the form !! A * X = B !! using the factorization A = U**H*D*U or A = L*D*L**H computed by CPTTRF. !! D is a diagonal matrix specified in the vector D, U (or L) is a unit !! bidiagonal matrix whose superdiagonal (subdiagonal) is specified in !! the vector E, and X and B are N by NRHS matrices. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments real(sp), intent(in) :: d(*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(in) :: e(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: iuplo, j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ upper = ( uplo=='U' .or. uplo=='U' ) if( .not.upper .and. .not.( uplo=='L' .or. uplo=='L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldb=nrhs ) then call stdlib${ii}$_cptts2( iuplo, n, nrhs, d, e, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_cptts2( iuplo, n, jb, d, e, b( 1_${ik}$, j ), ldb ) end do end if return end subroutine stdlib${ii}$_cpttrs pure module subroutine stdlib${ii}$_zpttrs( uplo, n, nrhs, d, e, b, ldb, info ) !! ZPTTRS solves a tridiagonal system of the form !! A * X = B !! using the factorization A = U**H *D* U or A = L*D*L**H computed by ZPTTRF. !! D is a diagonal matrix specified in the vector D, U (or L) is a unit !! bidiagonal matrix whose superdiagonal (subdiagonal) is specified in !! the vector E, and X and B are N by NRHS matrices. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments real(dp), intent(in) :: d(*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(in) :: e(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: iuplo, j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ upper = ( uplo=='U' .or. uplo=='U' ) if( .not.upper .and. .not.( uplo=='L' .or. uplo=='L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldb=nrhs ) then call stdlib${ii}$_zptts2( iuplo, n, nrhs, d, e, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_zptts2( iuplo, n, jb, d, e, b( 1_${ik}$, j ), ldb ) end do end if return end subroutine stdlib${ii}$_zpttrs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$pttrs( uplo, n, nrhs, d, e, b, ldb, info ) !! ZPTTRS: solves a tridiagonal system of the form !! A * X = B !! using the factorization A = U**H *D* U or A = L*D*L**H computed by ZPTTRF. !! D is a diagonal matrix specified in the vector D, U (or L) is a unit !! bidiagonal matrix whose superdiagonal (subdiagonal) is specified in !! the vector E, and X and B are N by NRHS matrices. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments real(${ck}$), intent(in) :: d(*) complex(${ck}$), intent(inout) :: b(ldb,*) complex(${ck}$), intent(in) :: e(*) ! ===================================================================== ! Local Scalars logical(lk) :: upper integer(${ik}$) :: iuplo, j, jb, nb ! Intrinsic Functions ! Executable Statements ! test the input arguments. info = 0_${ik}$ upper = ( uplo=='U' .or. uplo=='U' ) if( .not.upper .and. .not.( uplo=='L' .or. uplo=='L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldb=nrhs ) then call stdlib${ii}$_${ci}$ptts2( iuplo, n, nrhs, d, e, b, ldb ) else do j = 1, nrhs, nb jb = min( nrhs-j+1, nb ) call stdlib${ii}$_${ci}$ptts2( iuplo, n, jb, d, e, b( 1_${ik}$, j ), ldb ) end do end if return end subroutine stdlib${ii}$_${ci}$pttrs #:endif #:endfor pure module subroutine stdlib${ii}$_sptts2( n, nrhs, d, e, b, ldb ) !! SPTTS2 solves a tridiagonal system of the form !! A * X = B !! using the L*D*L**T factorization of A computed by SPTTRF. D is a !! diagonal matrix specified in the vector D, L is a unit bidiagonal !! matrix whose subdiagonal is specified in the vector E, and X and B !! are N by NRHS matrices. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments real(sp), intent(inout) :: b(ldb,*) real(sp), intent(in) :: d(*), e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j ! Executable Statements ! quick return if possible if( n<=1_${ik}$ ) then if( n==1_${ik}$ )call stdlib${ii}$_sscal( nrhs, 1. / d( 1_${ik}$ ), b, ldb ) return end if ! solve a * x = b using the factorization a = l*d*l**t, ! overwriting each right hand side vector with its solution. do j = 1, nrhs ! solve l * x = b. do i = 2, n b( i, j ) = b( i, j ) - b( i-1, j )*e( i-1 ) end do ! solve d * l**t * x = b. b( n, j ) = b( n, j ) / d( n ) do i = n - 1, 1, -1 b( i, j ) = b( i, j ) / d( i ) - b( i+1, j )*e( i ) end do end do return end subroutine stdlib${ii}$_sptts2 pure module subroutine stdlib${ii}$_dptts2( n, nrhs, d, e, b, ldb ) !! DPTTS2 solves a tridiagonal system of the form !! A * X = B !! using the L*D*L**T factorization of A computed by DPTTRF. D is a !! diagonal matrix specified in the vector D, L is a unit bidiagonal !! matrix whose subdiagonal is specified in the vector E, and X and B !! are N by NRHS matrices. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments real(dp), intent(inout) :: b(ldb,*) real(dp), intent(in) :: d(*), e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j ! Executable Statements ! quick return if possible if( n<=1_${ik}$ ) then if( n==1_${ik}$ )call stdlib${ii}$_dscal( nrhs, 1._dp / d( 1_${ik}$ ), b, ldb ) return end if ! solve a * x = b using the factorization a = l*d*l**t, ! overwriting each right hand side vector with its solution. do j = 1, nrhs ! solve l * x = b. do i = 2, n b( i, j ) = b( i, j ) - b( i-1, j )*e( i-1 ) end do ! solve d * l**t * x = b. b( n, j ) = b( n, j ) / d( n ) do i = n - 1, 1, -1 b( i, j ) = b( i, j ) / d( i ) - b( i+1, j )*e( i ) end do end do return end subroutine stdlib${ii}$_dptts2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ptts2( n, nrhs, d, e, b, ldb ) !! DPTTS2: solves a tridiagonal system of the form !! A * X = B !! using the L*D*L**T factorization of A computed by DPTTRF. D is a !! diagonal matrix specified in the vector D, L is a unit bidiagonal !! matrix whose subdiagonal is specified in the vector E, and X and B !! are N by NRHS matrices. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: ldb, n, nrhs ! Array Arguments real(${rk}$), intent(inout) :: b(ldb,*) real(${rk}$), intent(in) :: d(*), e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j ! Executable Statements ! quick return if possible if( n<=1_${ik}$ ) then if( n==1_${ik}$ )call stdlib${ii}$_${ri}$scal( nrhs, 1._${rk}$ / d( 1_${ik}$ ), b, ldb ) return end if ! solve a * x = b using the factorization a = l*d*l**t, ! overwriting each right hand side vector with its solution. do j = 1, nrhs ! solve l * x = b. do i = 2, n b( i, j ) = b( i, j ) - b( i-1, j )*e( i-1 ) end do ! solve d * l**t * x = b. b( n, j ) = b( n, j ) / d( n ) do i = n - 1, 1, -1 b( i, j ) = b( i, j ) / d( i ) - b( i+1, j )*e( i ) end do end do return end subroutine stdlib${ii}$_${ri}$ptts2 #:endif #:endfor pure module subroutine stdlib${ii}$_cptts2( iuplo, n, nrhs, d, e, b, ldb ) !! CPTTS2 solves a tridiagonal system of the form !! A * X = B !! using the factorization A = U**H*D*U or A = L*D*L**H computed by CPTTRF. !! D is a diagonal matrix specified in the vector D, U (or L) is a unit !! bidiagonal matrix whose superdiagonal (subdiagonal) is specified in !! the vector E, and X and B are N by NRHS matrices. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: iuplo, ldb, n, nrhs ! Array Arguments real(sp), intent(in) :: d(*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(in) :: e(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j ! Intrinsic Functions ! Executable Statements ! quick return if possible if( n<=1_${ik}$ ) then if( n==1_${ik}$ )call stdlib${ii}$_csscal( nrhs, 1. / d( 1_${ik}$ ), b, ldb ) return end if if( iuplo==1_${ik}$ ) then ! solve a * x = b using the factorization a = u**h *d*u, ! overwriting each right hand side vector with its solution. if( nrhs<=2_${ik}$ ) then j = 1_${ik}$ 5 continue ! solve u**h * x = b. do i = 2, n b( i, j ) = b( i, j ) - b( i-1, j )*conjg( e( i-1 ) ) end do ! solve d * u * x = b. do i = 1, n b( i, j ) = b( i, j ) / d( i ) end do do i = n - 1, 1, -1 b( i, j ) = b( i, j ) - b( i+1, j )*e( i ) end do if( jsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_spttrs( n, 1_${ik}$, df, ef, work( n+1 ), n, info ) call stdlib${ii}$_saxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do ix = stdlib${ii}$_isamax( n, work, 1_${ik}$ ) ferr( j ) = work( ix ) ! estimate the norm of inv(a). ! solve m(a) * x = e, where m(a) = (m(i,j)) is given by ! m(i,j) = abs(a(i,j)), i = j, ! m(i,j) = -abs(a(i,j)), i .ne. j, ! and e = [ 1, 1, ..., 1 ]**t. note m(a) = m(l)*d*m(l)**t. ! solve m(l) * x = e. work( 1_${ik}$ ) = one do i = 2, n work( i ) = one + work( i-1 )*abs( ef( i-1 ) ) end do ! solve d * m(l)**t * x = b. work( n ) = work( n ) / df( n ) do i = n - 1, 1, -1 work( i ) = work( i ) / df( i ) + work( i+1 )*abs( ef( i ) ) end do ! compute norm(inv(a)) = max(x(i)), 1<=i<=n. ix = stdlib${ii}$_isamax( n, work, 1_${ik}$ ) ferr( j ) = ferr( j )*abs( work( ix ) ) ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_90 return end subroutine stdlib${ii}$_sptrfs pure module subroutine stdlib${ii}$_dptrfs( n, nrhs, d, e, df, ef, b, ldb, x, ldx, ferr,berr, work, info ) !! DPTRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric positive definite !! and tridiagonal, and provides error bounds and backward error !! estimates for the solution. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments real(dp), intent(in) :: b(ldb,*), d(*), df(*), e(*), ef(*) real(dp), intent(out) :: berr(*), ferr(*), work(*) real(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: count, i, ix, j, nz real(dp) :: bi, cx, dx, eps, ex, lstres, s, safe1, safe2, safmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( nrhs<0_${ik}$ ) then info = -2_${ik}$ else if( ldbsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_dpttrs( n, 1_${ik}$, df, ef, work( n+1 ), n, info ) call stdlib${ii}$_daxpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do ix = stdlib${ii}$_idamax( n, work, 1_${ik}$ ) ferr( j ) = work( ix ) ! estimate the norm of inv(a). ! solve m(a) * x = e, where m(a) = (m(i,j)) is given by ! m(i,j) = abs(a(i,j)), i = j, ! m(i,j) = -abs(a(i,j)), i .ne. j, ! and e = [ 1, 1, ..., 1 ]**t. note m(a) = m(l)*d*m(l)**t. ! solve m(l) * x = e. work( 1_${ik}$ ) = one do i = 2, n work( i ) = one + work( i-1 )*abs( ef( i-1 ) ) end do ! solve d * m(l)**t * x = b. work( n ) = work( n ) / df( n ) do i = n - 1, 1, -1 work( i ) = work( i ) / df( i ) + work( i+1 )*abs( ef( i ) ) end do ! compute norm(inv(a)) = max(x(i)), 1<=i<=n. ix = stdlib${ii}$_idamax( n, work, 1_${ik}$ ) ferr( j ) = ferr( j )*abs( work( ix ) ) ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_90 return end subroutine stdlib${ii}$_dptrfs #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ptrfs( n, nrhs, d, e, df, ef, b, ldb, x, ldx, ferr,berr, work, info ) !! DPTRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is symmetric positive definite !! and tridiagonal, and provides error bounds and backward error !! estimates for the solution. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments real(${rk}$), intent(in) :: b(ldb,*), d(*), df(*), e(*), ef(*) real(${rk}$), intent(out) :: berr(*), ferr(*), work(*) real(${rk}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars integer(${ik}$) :: count, i, ix, j, nz real(${rk}$) :: bi, cx, dx, eps, ex, lstres, s, safe1, safe2, safmin ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ else if( nrhs<0_${ik}$ ) then info = -2_${ik}$ else if( ldbsafe2 ) then s = max( s, abs( work( n+i ) ) / work( i ) ) else s = max( s, ( abs( work( n+i ) )+safe1 ) /( work( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ri}$pttrs( n, 1_${ik}$, df, ef, work( n+1 ), n, info ) call stdlib${ii}$_${ri}$axpy( n, one, work( n+1 ), 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. do i = 1, n if( work( i )>safe2 ) then work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) else work( i ) = abs( work( n+i ) ) + nz*eps*work( i ) + safe1 end if end do ix = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ ) ferr( j ) = work( ix ) ! estimate the norm of inv(a). ! solve m(a) * x = e, where m(a) = (m(i,j)) is given by ! m(i,j) = abs(a(i,j)), i = j, ! m(i,j) = -abs(a(i,j)), i .ne. j, ! and e = [ 1, 1, ..., 1 ]**t. note m(a) = m(l)*d*m(l)**t. ! solve m(l) * x = e. work( 1_${ik}$ ) = one do i = 2, n work( i ) = one + work( i-1 )*abs( ef( i-1 ) ) end do ! solve d * m(l)**t * x = b. work( n ) = work( n ) / df( n ) do i = n - 1, 1, -1 work( i ) = work( i ) / df( i ) + work( i+1 )*abs( ef( i ) ) end do ! compute norm(inv(a)) = max(x(i)), 1<=i<=n. ix = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ ) ferr( j ) = ferr( j )*abs( work( ix ) ) ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_90 return end subroutine stdlib${ii}$_${ri}$ptrfs #:endif #:endfor pure module subroutine stdlib${ii}$_cptrfs( uplo, n, nrhs, d, e, df, ef, b, ldb, x, ldx,ferr, berr, work, & !! CPTRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and tridiagonal, and provides error bounds and backward error !! estimates for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments real(sp), intent(out) :: berr(*), ferr(*), rwork(*) real(sp), intent(in) :: d(*), df(*) complex(sp), intent(in) :: b(ldb,*), e(*), ef(*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ix, j, nz real(sp) :: eps, lstres, s, safe1, safe2, safmin complex(sp) :: bi, cx, dx, ex, zdum ! Intrinsic Functions ! Statement Functions real(sp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=sp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_cpttrs( uplo, n, 1_${ik}$, df, ef, work, n, info ) call stdlib${ii}$_caxpy( n, cmplx( one,KIND=sp), work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do ix = stdlib${ii}$_isamax( n, rwork, 1_${ik}$ ) ferr( j ) = rwork( ix ) ! estimate the norm of inv(a). ! solve m(a) * x = e, where m(a) = (m(i,j)) is given by ! m(i,j) = abs(a(i,j)), i = j, ! m(i,j) = -abs(a(i,j)), i .ne. j, ! and e = [ 1, 1, ..., 1 ]**t. note m(a) = m(l)*d*m(l)**h. ! solve m(l) * x = e. rwork( 1_${ik}$ ) = one do i = 2, n rwork( i ) = one + rwork( i-1 )*abs( ef( i-1 ) ) end do ! solve d * m(l)**h * x = b. rwork( n ) = rwork( n ) / df( n ) do i = n - 1, 1, -1 rwork( i ) = rwork( i ) / df( i ) +rwork( i+1 )*abs( ef( i ) ) end do ! compute norm(inv(a)) = max(x(i)), 1<=i<=n. ix = stdlib${ii}$_isamax( n, rwork, 1_${ik}$ ) ferr( j ) = ferr( j )*abs( rwork( ix ) ) ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_100 return end subroutine stdlib${ii}$_cptrfs pure module subroutine stdlib${ii}$_zptrfs( uplo, n, nrhs, d, e, df, ef, b, ldb, x, ldx,ferr, berr, work, & !! ZPTRFS improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and tridiagonal, and provides error bounds and backward error !! estimates for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments real(dp), intent(out) :: berr(*), ferr(*), rwork(*) real(dp), intent(in) :: d(*), df(*) complex(dp), intent(in) :: b(ldb,*), e(*), ef(*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ix, j, nz real(dp) :: eps, lstres, s, safe1, safe2, safmin complex(dp) :: bi, cx, dx, ex, zdum ! Intrinsic Functions ! Statement Functions real(dp) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=dp) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_zpttrs( uplo, n, 1_${ik}$, df, ef, work, n, info ) call stdlib${ii}$_zaxpy( n, cmplx( one,KIND=dp), work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do ix = stdlib${ii}$_idamax( n, rwork, 1_${ik}$ ) ferr( j ) = rwork( ix ) ! estimate the norm of inv(a). ! solve m(a) * x = e, where m(a) = (m(i,j)) is given by ! m(i,j) = abs(a(i,j)), i = j, ! m(i,j) = -abs(a(i,j)), i .ne. j, ! and e = [ 1, 1, ..., 1 ]**t. note m(a) = m(l)*d*m(l)**h. ! solve m(l) * x = e. rwork( 1_${ik}$ ) = one do i = 2, n rwork( i ) = one + rwork( i-1 )*abs( ef( i-1 ) ) end do ! solve d * m(l)**h * x = b. rwork( n ) = rwork( n ) / df( n ) do i = n - 1, 1, -1 rwork( i ) = rwork( i ) / df( i ) +rwork( i+1 )*abs( ef( i ) ) end do ! compute norm(inv(a)) = max(x(i)), 1<=i<=n. ix = stdlib${ii}$_idamax( n, rwork, 1_${ik}$ ) ferr( j ) = ferr( j )*abs( rwork( ix ) ) ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_100 return end subroutine stdlib${ii}$_zptrfs #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ptrfs( uplo, n, nrhs, d, e, df, ef, b, ldb, x, ldx,ferr, berr, work, & !! ZPTRFS: improves the computed solution to a system of linear !! equations when the coefficient matrix is Hermitian positive definite !! and tridiagonal, and provides error bounds and backward error !! estimates for the solution. rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs ! Array Arguments real(${ck}$), intent(out) :: berr(*), ferr(*), rwork(*) real(${ck}$), intent(in) :: d(*), df(*) complex(${ck}$), intent(in) :: b(ldb,*), e(*), ef(*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: x(ldx,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: itmax = 5_${ik}$ ! Local Scalars logical(lk) :: upper integer(${ik}$) :: count, i, ix, j, nz real(${ck}$) :: eps, lstres, s, safe1, safe2, safmin complex(${ck}$) :: bi, cx, dx, ex, zdum ! Intrinsic Functions ! Statement Functions real(${ck}$) :: cabs1 ! Statement Function Definitions cabs1( zdum ) = abs( real( zdum,KIND=${ck}$) ) + abs( aimag( zdum ) ) ! Executable Statements ! test the input parameters. info = 0_${ik}$ upper = stdlib_lsame( uplo, 'U' ) if( .not.upper .and. .not.stdlib_lsame( uplo, 'L' ) ) then info = -1_${ik}$ else if( n<0_${ik}$ ) then info = -2_${ik}$ else if( nrhs<0_${ik}$ ) then info = -3_${ik}$ else if( ldbsafe2 ) then s = max( s, cabs1( work( i ) ) / rwork( i ) ) else s = max( s, ( cabs1( work( i ) )+safe1 ) /( rwork( i )+safe1 ) ) end if end do berr( j ) = s ! test stopping criterion. continue iterating if ! 1) the residual berr(j) is larger than machine epsilon, and ! 2) berr(j) decreased by at least a factor of 2 during the ! last iteration, and ! 3) at most itmax iterations tried. if( berr( j )>eps .and. two*berr( j )<=lstres .and.count<=itmax ) then ! update solution and try again. call stdlib${ii}$_${ci}$pttrs( uplo, n, 1_${ik}$, df, ef, work, n, info ) call stdlib${ii}$_${ci}$axpy( n, cmplx( one,KIND=${ck}$), work, 1_${ik}$, x( 1_${ik}$, j ), 1_${ik}$ ) lstres = berr( j ) count = count + 1_${ik}$ go to 20 end if ! bound error from formula ! norm(x - xtrue) / norm(x) .le. ferr = ! norm( abs(inv(a))* ! ( abs(r) + nz*eps*( abs(a)*abs(x)+abs(b) ))) / norm(x) ! where ! norm(z) is the magnitude of the largest component of z ! inv(a) is the inverse of a ! abs(z) is the componentwise absolute value of the matrix or ! vector z ! nz is the maximum number of nonzeros in any row of a, plus 1 ! eps is machine epsilon ! the i-th component of abs(r)+nz*eps*(abs(a)*abs(x)+abs(b)) ! is incremented by safe1 if the i-th component of ! abs(a)*abs(x) + abs(b) is less than safe2. do i = 1, n if( rwork( i )>safe2 ) then rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) else rwork( i ) = cabs1( work( i ) ) + nz*eps*rwork( i ) +safe1 end if end do ix = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork, 1_${ik}$ ) ferr( j ) = rwork( ix ) ! estimate the norm of inv(a). ! solve m(a) * x = e, where m(a) = (m(i,j)) is given by ! m(i,j) = abs(a(i,j)), i = j, ! m(i,j) = -abs(a(i,j)), i .ne. j, ! and e = [ 1, 1, ..., 1 ]**t. note m(a) = m(l)*d*m(l)**h. ! solve m(l) * x = e. rwork( 1_${ik}$ ) = one do i = 2, n rwork( i ) = one + rwork( i-1 )*abs( ef( i-1 ) ) end do ! solve d * m(l)**h * x = b. rwork( n ) = rwork( n ) / df( n ) do i = n - 1, 1, -1 rwork( i ) = rwork( i ) / df( i ) +rwork( i+1 )*abs( ef( i ) ) end do ! compute norm(inv(a)) = max(x(i)), 1<=i<=n. ix = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork, 1_${ik}$ ) ferr( j ) = ferr( j )*abs( rwork( ix ) ) ! normalize error. lstres = zero do i = 1, n lstres = max( lstres, abs( x( i, j ) ) ) end do if( lstres/=zero )ferr( j ) = ferr( j ) / lstres end do loop_100 return end subroutine stdlib${ii}$_${ci}$ptrfs #:endif #:endfor pure module subroutine stdlib${ii}$_slaqsp( uplo, n, ap, s, scond, amax, equed ) !! SLAQSP equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: amax, scond ! Array Arguments real(sp), intent(inout) :: ap(*) real(sp), intent(in) :: s(*) ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1e+0_sp ! Local Scalars integer(${ik}$) :: i, j, jc real(sp) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) / stdlib${ii}$_slamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = 1, j ap( jc+i-1 ) = cj*s( i )*ap( jc+i-1 ) end do jc = jc + j end do else ! lower triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = j, n ap( jc+i-j ) = cj*s( i )*ap( jc+i-j ) end do jc = jc + n - j + 1_${ik}$ end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_slaqsp pure module subroutine stdlib${ii}$_dlaqsp( uplo, n, ap, s, scond, amax, equed ) !! DLAQSP equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: amax, scond ! Array Arguments real(dp), intent(inout) :: ap(*) real(dp), intent(in) :: s(*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j, jc real(dp) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = 1, j ap( jc+i-1 ) = cj*s( i )*ap( jc+i-1 ) end do jc = jc + j end do else ! lower triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = j, n ap( jc+i-j ) = cj*s( i )*ap( jc+i-j ) end do jc = jc + n - j + 1_${ik}$ end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_dlaqsp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqsp( uplo, n, ap, s, scond, amax, equed ) !! DLAQSP: equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(${rk}$), intent(in) :: amax, scond ! Array Arguments real(${rk}$), intent(inout) :: ap(*) real(${rk}$), intent(in) :: s(*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: thresh = 0.1e+0_${rk}$ ! Local Scalars integer(${ik}$) :: i, j, jc real(${rk}$) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${ri}$lamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = 1, j ap( jc+i-1 ) = cj*s( i )*ap( jc+i-1 ) end do jc = jc + j end do else ! lower triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = j, n ap( jc+i-j ) = cj*s( i )*ap( jc+i-j ) end do jc = jc + n - j + 1_${ik}$ end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_${ri}$laqsp #:endif #:endfor pure module subroutine stdlib${ii}$_claqsp( uplo, n, ap, s, scond, amax, equed ) !! CLAQSP equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(sp), intent(in) :: amax, scond ! Array Arguments real(sp), intent(in) :: s(*) complex(sp), intent(inout) :: ap(*) ! ===================================================================== ! Parameters real(sp), parameter :: thresh = 0.1e+0_sp ! Local Scalars integer(${ik}$) :: i, j, jc real(sp) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) / stdlib${ii}$_slamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = 1, j ap( jc+i-1 ) = cj*s( i )*ap( jc+i-1 ) end do jc = jc + j end do else ! lower triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = j, n ap( jc+i-j ) = cj*s( i )*ap( jc+i-j ) end do jc = jc + n - j + 1_${ik}$ end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_claqsp pure module subroutine stdlib${ii}$_zlaqsp( uplo, n, ap, s, scond, amax, equed ) !! ZLAQSP equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(dp), intent(in) :: amax, scond ! Array Arguments real(dp), intent(in) :: s(*) complex(dp), intent(inout) :: ap(*) ! ===================================================================== ! Parameters real(dp), parameter :: thresh = 0.1e+0_dp ! Local Scalars integer(${ik}$) :: i, j, jc real(dp) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) / stdlib${ii}$_dlamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = 1, j ap( jc+i-1 ) = cj*s( i )*ap( jc+i-1 ) end do jc = jc + j end do else ! lower triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = j, n ap( jc+i-j ) = cj*s( i )*ap( jc+i-j ) end do jc = jc + n - j + 1_${ik}$ end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_zlaqsp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqsp( uplo, n, ap, s, scond, amax, equed ) !! ZLAQSP: equilibrates a symmetric matrix A using the scaling factors !! in the vector S. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(out) :: equed character, intent(in) :: uplo integer(${ik}$), intent(in) :: n real(${ck}$), intent(in) :: amax, scond ! Array Arguments real(${ck}$), intent(in) :: s(*) complex(${ck}$), intent(inout) :: ap(*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: thresh = 0.1e+0_${ck}$ ! Local Scalars integer(${ik}$) :: i, j, jc real(${ck}$) :: cj, large, small ! Executable Statements ! quick return if possible if( n<=0_${ik}$ ) then equed = 'N' return end if ! initialize large and small. small = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) / stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) large = one / small if( scond>=thresh .and. amax>=small .and. amax<=large ) then ! no equilibration equed = 'N' else ! replace a by diag(s) * a * diag(s). if( stdlib_lsame( uplo, 'U' ) ) then ! upper triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = 1, j ap( jc+i-1 ) = cj*s( i )*ap( jc+i-1 ) end do jc = jc + j end do else ! lower triangle of a is stored. jc = 1_${ik}$ do j = 1, n cj = s( j ) do i = j, n ap( jc+i-j ) = cj*s( i )*ap( jc+i-j ) end do jc = jc + n - j + 1_${ik}$ end do end if equed = 'Y' end if return end subroutine stdlib${ii}$_${ci}$laqsp #:endif #:endfor #:endfor end submodule stdlib_lapack_solve_chol_comp fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_orthogonal_factors.fypp0000664000175000017500000054322615135654166027675 0ustar alastairalastair#:include "common.fypp" module stdlib_lapack_orthogonal_factors use stdlib_linalg_constants use stdlib_linalg_lapack_aux use stdlib_linalg_blas use stdlib_lapack_base implicit none interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stzrzf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_stzrzf pure module subroutine stdlib${ii}$_dtzrzf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dtzrzf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tzrzf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$tzrzf #:endif #:endfor pure module subroutine stdlib${ii}$_ctzrzf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_ctzrzf pure module subroutine stdlib${ii}$_ztzrzf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_ztzrzf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tzrzf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$tzrzf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunmrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunmrz pure module subroutine stdlib${ii}$_zunmrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunmrz #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unmrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unmrz #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sormrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sormrz pure module subroutine stdlib${ii}$_dormrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dormrz #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ormrz( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$ormrz #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunmr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, m, n complex(sp), intent(in) :: a(lda,*), tau(*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunmr3 pure module subroutine stdlib${ii}$_zunmr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, m, n complex(dp), intent(in) :: a(lda,*), tau(*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunmr3 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unmr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, m, n complex(${ck}$), intent(in) :: a(lda,*), tau(*) complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unmr3 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sormr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, m, n real(sp), intent(in) :: a(lda,*), tau(*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sormr3 pure module subroutine stdlib${ii}$_dormr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, m, n real(dp), intent(in) :: a(lda,*), tau(*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dormr3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ormr3( side, trans, m, n, k, l, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, l, lda, ldc, m, n real(${rk}$), intent(in) :: a(lda,*), tau(*) real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$ormr3 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slarz( side, m, n, l, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, l, ldc, m, n real(sp), intent(in) :: tau real(sp), intent(inout) :: c(ldc,*) real(sp), intent(in) :: v(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_slarz pure module subroutine stdlib${ii}$_dlarz( side, m, n, l, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, l, ldc, m, n real(dp), intent(in) :: tau real(dp), intent(inout) :: c(ldc,*) real(dp), intent(in) :: v(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dlarz #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larz( side, m, n, l, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, l, ldc, m, n real(${rk}$), intent(in) :: tau real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(in) :: v(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$larz #:endif #:endfor pure module subroutine stdlib${ii}$_clarz( side, m, n, l, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, l, ldc, m, n complex(sp), intent(in) :: tau complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(in) :: v(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_clarz pure module subroutine stdlib${ii}$_zlarz( side, m, n, l, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, l, ldc, m, n complex(dp), intent(in) :: tau complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(in) :: v(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zlarz #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larz( side, m, n, l, v, incv, tau, c, ldc, work ) character, intent(in) :: side integer(${ik}$), intent(in) :: incv, l, ldc, m, n complex(${ck}$), intent(in) :: tau complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(in) :: v(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$larz #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slarzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & ldc, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, ldc, ldt, ldv, ldwork, m, n real(sp), intent(inout) :: c(ldc,*), t(ldt,*), v(ldv,*) real(sp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_slarzb pure module subroutine stdlib${ii}$_dlarzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & ldc, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, ldc, ldt, ldv, ldwork, m, n real(dp), intent(inout) :: c(ldc,*), t(ldt,*), v(ldv,*) real(dp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_dlarzb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & ldc, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, ldc, ldt, ldv, ldwork, m, n real(${rk}$), intent(inout) :: c(ldc,*), t(ldt,*), v(ldv,*) real(${rk}$), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_${ri}$larzb #:endif #:endfor pure module subroutine stdlib${ii}$_clarzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & ldc, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, ldc, ldt, ldv, ldwork, m, n complex(sp), intent(inout) :: c(ldc,*), t(ldt,*), v(ldv,*) complex(sp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_clarzb pure module subroutine stdlib${ii}$_zlarzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & ldc, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, ldc, ldt, ldv, ldwork, m, n complex(dp), intent(inout) :: c(ldc,*), t(ldt,*), v(ldv,*) complex(dp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_zlarzb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larzb( side, trans, direct, storev, m, n, k, l, v,ldv, t, ldt, c, & ldc, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, ldc, ldt, ldv, ldwork, m, n complex(${ck}$), intent(inout) :: c(ldc,*), t(ldt,*), v(ldv,*) complex(${ck}$), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_${ci}$larzb #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slarzt( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n real(sp), intent(out) :: t(ldt,*) real(sp), intent(in) :: tau(*) real(sp), intent(inout) :: v(ldv,*) end subroutine stdlib${ii}$_slarzt pure module subroutine stdlib${ii}$_dlarzt( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n real(dp), intent(out) :: t(ldt,*) real(dp), intent(in) :: tau(*) real(dp), intent(inout) :: v(ldv,*) end subroutine stdlib${ii}$_dlarzt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larzt( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n real(${rk}$), intent(out) :: t(ldt,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(inout) :: v(ldv,*) end subroutine stdlib${ii}$_${ri}$larzt #:endif #:endfor pure module subroutine stdlib${ii}$_clarzt( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n complex(sp), intent(out) :: t(ldt,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(inout) :: v(ldv,*) end subroutine stdlib${ii}$_clarzt pure module subroutine stdlib${ii}$_zlarzt( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n complex(dp), intent(out) :: t(ldt,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(inout) :: v(ldv,*) end subroutine stdlib${ii}$_zlarzt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larzt( direct, storev, n, k, v, ldv, tau, t, ldt ) character, intent(in) :: direct, storev integer(${ik}$), intent(in) :: k, ldt, ldv, n complex(${ck}$), intent(out) :: t(ldt,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(inout) :: v(ldv,*) end subroutine stdlib${ii}$_${ci}$larzt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slatrz( m, n, l, a, lda, tau, work ) integer(${ik}$), intent(in) :: l, lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_slatrz pure module subroutine stdlib${ii}$_dlatrz( m, n, l, a, lda, tau, work ) integer(${ik}$), intent(in) :: l, lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dlatrz #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$latrz( m, n, l, a, lda, tau, work ) integer(${ik}$), intent(in) :: l, lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$latrz #:endif #:endfor pure module subroutine stdlib${ii}$_clatrz( m, n, l, a, lda, tau, work ) integer(${ik}$), intent(in) :: l, lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_clatrz pure module subroutine stdlib${ii}$_zlatrz( m, n, l, a, lda, tau, work ) integer(${ik}$), intent(in) :: l, lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zlatrz #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$latrz( m, n, l, a, lda, tau, work ) integer(${ik}$), intent(in) :: l, lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$latrz #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgeqr( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_sgeqr pure module subroutine stdlib${ii}$_dgeqr( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_dgeqr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$geqr( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_${ri}$geqr #:endif #:endfor pure module subroutine stdlib${ii}$_cgeqr( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_cgeqr pure module subroutine stdlib${ii}$_zgeqr( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_zgeqr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$geqr( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_${ci}$geqr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgemqr( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc real(sp), intent(in) :: a(lda,*), t(*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sgemqr pure module subroutine stdlib${ii}$_dgemqr( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc real(dp), intent(in) :: a(lda,*), t(*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dgemqr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gemqr( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc real(${rk}$), intent(in) :: a(lda,*), t(*) real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$gemqr #:endif #:endfor pure module subroutine stdlib${ii}$_cgemqr( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc complex(sp), intent(in) :: a(lda,*), t(*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cgemqr pure module subroutine stdlib${ii}$_zgemqr( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc complex(dp), intent(in) :: a(lda,*), t(*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zgemqr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gemqr( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc complex(${ck}$), intent(in) :: a(lda,*), t(*) complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$gemqr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgeqrf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_sgeqrf pure module subroutine stdlib${ii}$_dgeqrf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dgeqrf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$geqrf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$geqrf #:endif #:endfor pure module subroutine stdlib${ii}$_cgeqrf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_cgeqrf pure module subroutine stdlib${ii}$_zgeqrf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zgeqrf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$geqrf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$geqrf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgeqr2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_sgeqr2 pure module subroutine stdlib${ii}$_dgeqr2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dgeqr2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$geqr2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$geqr2 #:endif #:endfor pure module subroutine stdlib${ii}$_cgeqr2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_cgeqr2 pure module subroutine stdlib${ii}$_zgeqr2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zgeqr2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$geqr2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$geqr2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cungqr( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cungqr pure module subroutine stdlib${ii}$_zungqr( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zungqr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ungqr( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$ungqr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cung2r( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cung2r pure module subroutine stdlib${ii}$_zung2r( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zung2r #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ung2r( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$ung2r #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunmqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunmqr pure module subroutine stdlib${ii}$_zunmqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunmqr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unmqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unmqr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunm2r( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunm2r pure module subroutine stdlib${ii}$_zunm2r( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunm2r #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unm2r( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unm2r #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorgqr( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorgqr pure module subroutine stdlib${ii}$_dorgqr( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorgqr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orgqr( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$orgqr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorg2r( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorg2r pure module subroutine stdlib${ii}$_dorg2r( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorg2r #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$org2r( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$org2r #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sormqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sormqr pure module subroutine stdlib${ii}$_dormqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dormqr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ormqr( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$ormqr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorm2r( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorm2r pure module subroutine stdlib${ii}$_dorm2r( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorm2r #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orm2r( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$orm2r #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgeqrt( m, n, nb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_sgeqrt pure module subroutine stdlib${ii}$_dgeqrt( m, n, nb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_dgeqrt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$geqrt( m, n, nb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_${ri}$geqrt #:endif #:endfor pure module subroutine stdlib${ii}$_cgeqrt( m, n, nb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_cgeqrt pure module subroutine stdlib${ii}$_zgeqrt( m, n, nb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_zgeqrt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$geqrt( m, n, nb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_${ci}$geqrt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgeqrt2( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_sgeqrt2 pure module subroutine stdlib${ii}$_dgeqrt2( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_dgeqrt2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$geqrt2( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_${ri}$geqrt2 #:endif #:endfor pure module subroutine stdlib${ii}$_cgeqrt2( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_cgeqrt2 pure module subroutine stdlib${ii}$_zgeqrt2( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_zgeqrt2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$geqrt2( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_${ci}$geqrt2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure recursive module subroutine stdlib${ii}$_sgeqrt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_sgeqrt3 pure recursive module subroutine stdlib${ii}$_dgeqrt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_dgeqrt3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure recursive module subroutine stdlib${ii}$_${ri}$geqrt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_${ri}$geqrt3 #:endif #:endfor pure recursive module subroutine stdlib${ii}$_cgeqrt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_cgeqrt3 pure recursive module subroutine stdlib${ii}$_zgeqrt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_zgeqrt3 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure recursive module subroutine stdlib${ii}$_${ci}$geqrt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_${ci}$geqrt3 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgemqrt( side, trans, m, n, k, nb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, nb, ldt real(sp), intent(in) :: v(ldv,*), t(ldt,*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sgemqrt pure module subroutine stdlib${ii}$_dgemqrt( side, trans, m, n, k, nb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, nb, ldt real(dp), intent(in) :: v(ldv,*), t(ldt,*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dgemqrt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gemqrt( side, trans, m, n, k, nb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, nb, ldt real(${rk}$), intent(in) :: v(ldv,*), t(ldt,*) real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$gemqrt #:endif #:endfor pure module subroutine stdlib${ii}$_cgemqrt( side, trans, m, n, k, nb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, nb, ldt complex(sp), intent(in) :: v(ldv,*), t(ldt,*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cgemqrt pure module subroutine stdlib${ii}$_zgemqrt( side, trans, m, n, k, nb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, nb, ldt complex(dp), intent(in) :: v(ldv,*), t(ldt,*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zgemqrt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gemqrt( side, trans, m, n, k, nb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, nb, ldt complex(${ck}$), intent(in) :: v(ldv,*), t(ldt,*) complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$gemqrt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_sgeqrfp( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_sgeqrfp module subroutine stdlib${ii}$_dgeqrfp( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dgeqrfp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$geqrfp( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$geqrfp #:endif #:endfor module subroutine stdlib${ii}$_cgeqrfp( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_cgeqrfp module subroutine stdlib${ii}$_zgeqrfp( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zgeqrfp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$geqrfp( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$geqrfp #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_sgeqr2p( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_sgeqr2p module subroutine stdlib${ii}$_dgeqr2p( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dgeqr2p #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$geqr2p( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$geqr2p #:endif #:endfor module subroutine stdlib${ii}$_cgeqr2p( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_cgeqr2p module subroutine stdlib${ii}$_zgeqr2p( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zgeqr2p #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$geqr2p( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$geqr2p #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgeqp3( m, n, a, lda, jpvt, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n integer(${ik}$), intent(inout) :: jpvt(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_sgeqp3 pure module subroutine stdlib${ii}$_dgeqp3( m, n, a, lda, jpvt, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n integer(${ik}$), intent(inout) :: jpvt(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dgeqp3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$geqp3( m, n, a, lda, jpvt, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n integer(${ik}$), intent(inout) :: jpvt(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$geqp3 #:endif #:endfor pure module subroutine stdlib${ii}$_cgeqp3( m, n, a, lda, jpvt, tau, work, lwork, rwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n integer(${ik}$), intent(inout) :: jpvt(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_cgeqp3 pure module subroutine stdlib${ii}$_zgeqp3( m, n, a, lda, jpvt, tau, work, lwork, rwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n integer(${ik}$), intent(inout) :: jpvt(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zgeqp3 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$geqp3( m, n, a, lda, jpvt, tau, work, lwork, rwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n integer(${ik}$), intent(inout) :: jpvt(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$geqp3 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slaqp2( m, n, offset, a, lda, jpvt, tau, vn1, vn2,work ) integer(${ik}$), intent(in) :: lda, m, n, offset integer(${ik}$), intent(inout) :: jpvt(*) real(sp), intent(inout) :: a(lda,*), vn1(*), vn2(*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_slaqp2 pure module subroutine stdlib${ii}$_dlaqp2( m, n, offset, a, lda, jpvt, tau, vn1, vn2,work ) integer(${ik}$), intent(in) :: lda, m, n, offset integer(${ik}$), intent(inout) :: jpvt(*) real(dp), intent(inout) :: a(lda,*), vn1(*), vn2(*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dlaqp2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqp2( m, n, offset, a, lda, jpvt, tau, vn1, vn2,work ) integer(${ik}$), intent(in) :: lda, m, n, offset integer(${ik}$), intent(inout) :: jpvt(*) real(${rk}$), intent(inout) :: a(lda,*), vn1(*), vn2(*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$laqp2 #:endif #:endfor pure module subroutine stdlib${ii}$_claqp2( m, n, offset, a, lda, jpvt, tau, vn1, vn2,work ) integer(${ik}$), intent(in) :: lda, m, n, offset integer(${ik}$), intent(inout) :: jpvt(*) real(sp), intent(inout) :: vn1(*), vn2(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_claqp2 pure module subroutine stdlib${ii}$_zlaqp2( m, n, offset, a, lda, jpvt, tau, vn1, vn2,work ) integer(${ik}$), intent(in) :: lda, m, n, offset integer(${ik}$), intent(inout) :: jpvt(*) real(dp), intent(inout) :: vn1(*), vn2(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zlaqp2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqp2( m, n, offset, a, lda, jpvt, tau, vn1, vn2,work ) integer(${ik}$), intent(in) :: lda, m, n, offset integer(${ik}$), intent(inout) :: jpvt(*) real(${ck}$), intent(inout) :: vn1(*), vn2(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$laqp2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slaqps( m, n, offset, nb, kb, a, lda, jpvt, tau, vn1,vn2, auxv, f, & ldf ) integer(${ik}$), intent(out) :: kb integer(${ik}$), intent(in) :: lda, ldf, m, n, nb, offset integer(${ik}$), intent(inout) :: jpvt(*) real(sp), intent(inout) :: a(lda,*), auxv(*), f(ldf,*), vn1(*), vn2(*) real(sp), intent(out) :: tau(*) end subroutine stdlib${ii}$_slaqps pure module subroutine stdlib${ii}$_dlaqps( m, n, offset, nb, kb, a, lda, jpvt, tau, vn1,vn2, auxv, f, & ldf ) integer(${ik}$), intent(out) :: kb integer(${ik}$), intent(in) :: lda, ldf, m, n, nb, offset integer(${ik}$), intent(inout) :: jpvt(*) real(dp), intent(inout) :: a(lda,*), auxv(*), f(ldf,*), vn1(*), vn2(*) real(dp), intent(out) :: tau(*) end subroutine stdlib${ii}$_dlaqps #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laqps( m, n, offset, nb, kb, a, lda, jpvt, tau, vn1,vn2, auxv, f, & ldf ) integer(${ik}$), intent(out) :: kb integer(${ik}$), intent(in) :: lda, ldf, m, n, nb, offset integer(${ik}$), intent(inout) :: jpvt(*) real(${rk}$), intent(inout) :: a(lda,*), auxv(*), f(ldf,*), vn1(*), vn2(*) real(${rk}$), intent(out) :: tau(*) end subroutine stdlib${ii}$_${ri}$laqps #:endif #:endfor pure module subroutine stdlib${ii}$_claqps( m, n, offset, nb, kb, a, lda, jpvt, tau, vn1,vn2, auxv, f, & ldf ) integer(${ik}$), intent(out) :: kb integer(${ik}$), intent(in) :: lda, ldf, m, n, nb, offset integer(${ik}$), intent(inout) :: jpvt(*) real(sp), intent(inout) :: vn1(*), vn2(*) complex(sp), intent(inout) :: a(lda,*), auxv(*), f(ldf,*) complex(sp), intent(out) :: tau(*) end subroutine stdlib${ii}$_claqps pure module subroutine stdlib${ii}$_zlaqps( m, n, offset, nb, kb, a, lda, jpvt, tau, vn1,vn2, auxv, f, & ldf ) integer(${ik}$), intent(out) :: kb integer(${ik}$), intent(in) :: lda, ldf, m, n, nb, offset integer(${ik}$), intent(inout) :: jpvt(*) real(dp), intent(inout) :: vn1(*), vn2(*) complex(dp), intent(inout) :: a(lda,*), auxv(*), f(ldf,*) complex(dp), intent(out) :: tau(*) end subroutine stdlib${ii}$_zlaqps #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laqps( m, n, offset, nb, kb, a, lda, jpvt, tau, vn1,vn2, auxv, f, & ldf ) integer(${ik}$), intent(out) :: kb integer(${ik}$), intent(in) :: lda, ldf, m, n, nb, offset integer(${ik}$), intent(inout) :: jpvt(*) real(${ck}$), intent(inout) :: vn1(*), vn2(*) complex(${ck}$), intent(inout) :: a(lda,*), auxv(*), f(ldf,*) complex(${ck}$), intent(out) :: tau(*) end subroutine stdlib${ii}$_${ci}$laqps #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slatsqr( m, n, mb, nb, a, lda, t, ldt, work,lwork, info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, ldt, lwork real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_slatsqr pure module subroutine stdlib${ii}$_dlatsqr( m, n, mb, nb, a, lda, t, ldt, work,lwork, info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, ldt, lwork real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_dlatsqr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$latsqr( m, n, mb, nb, a, lda, t, ldt, work,lwork, info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, ldt, lwork real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_${ri}$latsqr #:endif #:endfor pure module subroutine stdlib${ii}$_clatsqr( m, n, mb, nb, a, lda, t, ldt, work,lwork, info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, ldt, lwork complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_clatsqr pure module subroutine stdlib${ii}$_zlatsqr( m, n, mb, nb, a, lda, t, ldt, work,lwork, info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, ldt, lwork complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_zlatsqr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$latsqr( m, n, mb, nb, a, lda, t, ldt, work,lwork, info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, ldt, lwork complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_${ci}$latsqr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cungtsqr( m, n, mb, nb, a, lda, t, ldt, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: t(ldt,*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cungtsqr pure module subroutine stdlib${ii}$_zungtsqr( m, n, mb, nb, a, lda, t, ldt, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: t(ldt,*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zungtsqr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ungtsqr( m, n, mb, nb, a, lda, t, ldt, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: t(ldt,*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$ungtsqr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cungtsqr_row( m, n, mb, nb, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: t(ldt,*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cungtsqr_row pure module subroutine stdlib${ii}$_zungtsqr_row( m, n, mb, nb, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: t(ldt,*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zungtsqr_row #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ungtsqr_row( m, n, mb, nb, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: t(ldt,*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$ungtsqr_row #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorgtsqr( m, n, mb, nb, a, lda, t, ldt, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: t(ldt,*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorgtsqr pure module subroutine stdlib${ii}$_dorgtsqr( m, n, mb, nb, a, lda, t, ldt, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: t(ldt,*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorgtsqr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orgtsqr( m, n, mb, nb, a, lda, t, ldt, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: t(ldt,*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$orgtsqr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorgtsqr_row( m, n, mb, nb, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: t(ldt,*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorgtsqr_row pure module subroutine stdlib${ii}$_dorgtsqr_row( m, n, mb, nb, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: t(ldt,*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorgtsqr_row #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orgtsqr_row( m, n, mb, nb, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, mb, nb real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: t(ldt,*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$orgtsqr_row #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slarfb_gett( ident, m, n, k, t, ldt, a, lda, b, ldb,work, ldwork ) character, intent(in) :: ident integer(${ik}$), intent(in) :: k, lda, ldb, ldt, ldwork, m, n real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(in) :: t(ldt,*) real(sp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_slarfb_gett pure module subroutine stdlib${ii}$_dlarfb_gett( ident, m, n, k, t, ldt, a, lda, b, ldb,work, ldwork ) character, intent(in) :: ident integer(${ik}$), intent(in) :: k, lda, ldb, ldt, ldwork, m, n real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(in) :: t(ldt,*) real(dp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_dlarfb_gett #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$larfb_gett( ident, m, n, k, t, ldt, a, lda, b, ldb,work, ldwork ) character, intent(in) :: ident integer(${ik}$), intent(in) :: k, lda, ldb, ldt, ldwork, m, n real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(in) :: t(ldt,*) real(${rk}$), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_${ri}$larfb_gett #:endif #:endfor pure module subroutine stdlib${ii}$_clarfb_gett( ident, m, n, k, t, ldt, a, lda, b, ldb,work, ldwork ) character, intent(in) :: ident integer(${ik}$), intent(in) :: k, lda, ldb, ldt, ldwork, m, n complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(in) :: t(ldt,*) complex(sp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_clarfb_gett pure module subroutine stdlib${ii}$_zlarfb_gett( ident, m, n, k, t, ldt, a, lda, b, ldb,work, ldwork ) character, intent(in) :: ident integer(${ik}$), intent(in) :: k, lda, ldb, ldt, ldwork, m, n complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(in) :: t(ldt,*) complex(dp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_zlarfb_gett #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$larfb_gett( ident, m, n, k, t, ldt, a, lda, b, ldb,work, ldwork ) character, intent(in) :: ident integer(${ik}$), intent(in) :: k, lda, ldb, ldt, ldwork, m, n complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(in) :: t(ldt,*) complex(${ck}$), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_${ci}$larfb_gett #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slamtsqr( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc real(sp), intent(in) :: a(lda,*), t(ldt,*) real(sp), intent(out) :: work(*) real(sp), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_slamtsqr pure module subroutine stdlib${ii}$_dlamtsqr( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc real(dp), intent(in) :: a(lda,*), t(ldt,*) real(dp), intent(out) :: work(*) real(dp), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_dlamtsqr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lamtsqr( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc real(${rk}$), intent(in) :: a(lda,*), t(ldt,*) real(${rk}$), intent(out) :: work(*) real(${rk}$), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_${ri}$lamtsqr #:endif #:endfor pure module subroutine stdlib${ii}$_clamtsqr( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc complex(sp), intent(in) :: a(lda,*), t(ldt,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_clamtsqr pure module subroutine stdlib${ii}$_zlamtsqr( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc complex(dp), intent(in) :: a(lda,*), t(ldt,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_zlamtsqr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lamtsqr( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc complex(${ck}$), intent(in) :: a(lda,*), t(ldt,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_${ci}$lamtsqr #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgetsqrhrt( m, n, mb1, nb1, nb2, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, nb1, nb2, mb1 real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_sgetsqrhrt pure module subroutine stdlib${ii}$_dgetsqrhrt( m, n, mb1, nb1, nb2, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, nb1, nb2, mb1 real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_dgetsqrhrt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$getsqrhrt( m, n, mb1, nb1, nb2, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, nb1, nb2, mb1 real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_${ri}$getsqrhrt #:endif #:endfor pure module subroutine stdlib${ii}$_cgetsqrhrt( m, n, mb1, nb1, nb2, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, nb1, nb2, mb1 complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_cgetsqrhrt pure module subroutine stdlib${ii}$_zgetsqrhrt( m, n, mb1, nb1, nb2, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, nb1, nb2, mb1 complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_zgetsqrhrt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$getsqrhrt( m, n, mb1, nb1, nb2, a, lda, t, ldt, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, lwork, m, n, nb1, nb2, mb1 complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_${ci}$getsqrhrt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunhr_col( m, n, nb, a, lda, t, ldt, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: d(*), t(ldt,*) end subroutine stdlib${ii}$_cunhr_col pure module subroutine stdlib${ii}$_zunhr_col( m, n, nb, a, lda, t, ldt, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: d(*), t(ldt,*) end subroutine stdlib${ii}$_zunhr_col #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unhr_col( m, n, nb, a, lda, t, ldt, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: d(*), t(ldt,*) end subroutine stdlib${ii}$_${ci}$unhr_col #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorhr_col( m, n, nb, a, lda, t, ldt, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*), t(ldt,*) end subroutine stdlib${ii}$_sorhr_col pure module subroutine stdlib${ii}$_dorhr_col( m, n, nb, a, lda, t, ldt, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*), t(ldt,*) end subroutine stdlib${ii}$_dorhr_col #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orhr_col( m, n, nb, a, lda, t, ldt, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, nb real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: d(*), t(ldt,*) end subroutine stdlib${ii}$_${ri}$orhr_col #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_claunhr_col_getrfnp( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: d(*) end subroutine stdlib${ii}$_claunhr_col_getrfnp pure module subroutine stdlib${ii}$_zlaunhr_col_getrfnp( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: d(*) end subroutine stdlib${ii}$_zlaunhr_col_getrfnp #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$launhr_col_getrfnp( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: d(*) end subroutine stdlib${ii}$_${ci}$launhr_col_getrfnp #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slaorhr_col_getrfnp( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*) end subroutine stdlib${ii}$_slaorhr_col_getrfnp pure module subroutine stdlib${ii}$_dlaorhr_col_getrfnp( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*) end subroutine stdlib${ii}$_dlaorhr_col_getrfnp #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laorhr_col_getrfnp( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: d(*) end subroutine stdlib${ii}$_${ri}$laorhr_col_getrfnp #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure recursive module subroutine stdlib${ii}$_claunhr_col_getrfnp2( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: d(*) end subroutine stdlib${ii}$_claunhr_col_getrfnp2 pure recursive module subroutine stdlib${ii}$_zlaunhr_col_getrfnp2( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: d(*) end subroutine stdlib${ii}$_zlaunhr_col_getrfnp2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure recursive module subroutine stdlib${ii}$_${ci}$launhr_col_getrfnp2( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: d(*) end subroutine stdlib${ii}$_${ci}$launhr_col_getrfnp2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure recursive module subroutine stdlib${ii}$_slaorhr_col_getrfnp2( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: d(*) end subroutine stdlib${ii}$_slaorhr_col_getrfnp2 pure recursive module subroutine stdlib${ii}$_dlaorhr_col_getrfnp2( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: d(*) end subroutine stdlib${ii}$_dlaorhr_col_getrfnp2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure recursive module subroutine stdlib${ii}$_${ri}$laorhr_col_getrfnp2( m, n, a, lda, d, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: d(*) end subroutine stdlib${ii}$_${ri}$laorhr_col_getrfnp2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stpqrt( m, n, l, nb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, nb real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_stpqrt pure module subroutine stdlib${ii}$_dtpqrt( m, n, l, nb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, nb real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_dtpqrt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tpqrt( m, n, l, nb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, nb real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_${ri}$tpqrt #:endif #:endfor pure module subroutine stdlib${ii}$_ctpqrt( m, n, l, nb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, nb complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_ctpqrt pure module subroutine stdlib${ii}$_ztpqrt( m, n, l, nb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, nb complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_ztpqrt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tpqrt( m, n, l, nb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, nb complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_${ci}$tpqrt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stpqrt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_stpqrt2 pure module subroutine stdlib${ii}$_dtpqrt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_dtpqrt2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tpqrt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_${ri}$tpqrt2 #:endif #:endfor pure module subroutine stdlib${ii}$_ctpqrt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_ctpqrt2 pure module subroutine stdlib${ii}$_ztpqrt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_ztpqrt2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tpqrt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_${ci}$tpqrt2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stpmqrt( side, trans, m, n, k, l, nb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, nb, ldt real(sp), intent(in) :: v(ldv,*), t(ldt,*) real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_stpmqrt pure module subroutine stdlib${ii}$_dtpmqrt( side, trans, m, n, k, l, nb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, nb, ldt real(dp), intent(in) :: v(ldv,*), t(ldt,*) real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dtpmqrt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tpmqrt( side, trans, m, n, k, l, nb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, nb, ldt real(${rk}$), intent(in) :: v(ldv,*), t(ldt,*) real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$tpmqrt #:endif #:endfor pure module subroutine stdlib${ii}$_ctpmqrt( side, trans, m, n, k, l, nb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, nb, ldt complex(sp), intent(in) :: v(ldv,*), t(ldt,*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_ctpmqrt pure module subroutine stdlib${ii}$_ztpmqrt( side, trans, m, n, k, l, nb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, nb, ldt complex(dp), intent(in) :: v(ldv,*), t(ldt,*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_ztpmqrt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tpmqrt( side, trans, m, n, k, l, nb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, nb, ldt complex(${ck}$), intent(in) :: v(ldv,*), t(ldt,*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$tpmqrt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stprfb( side, trans, direct, storev, m, n, k, l,v, ldv, t, ldt, a, & lda, b, ldb, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, lda, ldb, ldt, ldv, ldwork, m, n real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(in) :: t(ldt,*), v(ldv,*) real(sp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_stprfb pure module subroutine stdlib${ii}$_dtprfb( side, trans, direct, storev, m, n, k, l,v, ldv, t, ldt, a, & lda, b, ldb, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, lda, ldb, ldt, ldv, ldwork, m, n real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(in) :: t(ldt,*), v(ldv,*) real(dp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_dtprfb #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tprfb( side, trans, direct, storev, m, n, k, l,v, ldv, t, ldt, a, & lda, b, ldb, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, lda, ldb, ldt, ldv, ldwork, m, n real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(in) :: t(ldt,*), v(ldv,*) real(${rk}$), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_${ri}$tprfb #:endif #:endfor pure module subroutine stdlib${ii}$_ctprfb( side, trans, direct, storev, m, n, k, l,v, ldv, t, ldt, a, & lda, b, ldb, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, lda, ldb, ldt, ldv, ldwork, m, n complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(in) :: t(ldt,*), v(ldv,*) complex(sp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_ctprfb pure module subroutine stdlib${ii}$_ztprfb( side, trans, direct, storev, m, n, k, l,v, ldv, t, ldt, a, & lda, b, ldb, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, lda, ldb, ldt, ldv, ldwork, m, n complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(in) :: t(ldt,*), v(ldv,*) complex(dp), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_ztprfb #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tprfb( side, trans, direct, storev, m, n, k, l,v, ldv, t, ldt, a, & lda, b, ldb, work, ldwork ) character, intent(in) :: direct, side, storev, trans integer(${ik}$), intent(in) :: k, l, lda, ldb, ldt, ldv, ldwork, m, n complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(in) :: t(ldt,*), v(ldv,*) complex(${ck}$), intent(out) :: work(ldwork,*) end subroutine stdlib${ii}$_${ci}$tprfb #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sggqrf( n, m, p, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_sggqrf pure module subroutine stdlib${ii}$_dggqrf( n, m, p, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_dggqrf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ggqrf( n, m, p, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_${ri}$ggqrf #:endif #:endfor pure module subroutine stdlib${ii}$_cggqrf( n, m, p, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_cggqrf pure module subroutine stdlib${ii}$_zggqrf( n, m, p, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_zggqrf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ggqrf( n, m, p, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_${ci}$ggqrf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgerqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_sgerqf pure module subroutine stdlib${ii}$_dgerqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dgerqf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gerqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$gerqf #:endif #:endfor pure module subroutine stdlib${ii}$_cgerqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_cgerqf pure module subroutine stdlib${ii}$_zgerqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zgerqf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gerqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$gerqf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgerq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_sgerq2 pure module subroutine stdlib${ii}$_dgerq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dgerq2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gerq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$gerq2 #:endif #:endfor pure module subroutine stdlib${ii}$_cgerq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_cgerq2 pure module subroutine stdlib${ii}$_zgerq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zgerq2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gerq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$gerq2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cungrq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cungrq pure module subroutine stdlib${ii}$_zungrq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zungrq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ungrq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$ungrq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunmrq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunmrq pure module subroutine stdlib${ii}$_zunmrq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunmrq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unmrq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unmrq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunmr2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunmr2 pure module subroutine stdlib${ii}$_zunmr2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunmr2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unmr2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unmr2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cungr2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cungr2 pure module subroutine stdlib${ii}$_zungr2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zungr2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ungr2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$ungr2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorgrq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorgrq pure module subroutine stdlib${ii}$_dorgrq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorgrq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orgrq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$orgrq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sormrq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sormrq pure module subroutine stdlib${ii}$_dormrq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dormrq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ormrq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$ormrq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sormr2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sormr2 pure module subroutine stdlib${ii}$_dormr2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dormr2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ormr2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$ormr2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorgr2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorgr2 pure module subroutine stdlib${ii}$_dorgr2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorgr2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orgr2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$orgr2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sggrqf( m, p, n, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_sggrqf pure module subroutine stdlib${ii}$_dggrqf( m, p, n, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_dggrqf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ggrqf( m, p, n, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_${ri}$ggrqf #:endif #:endfor pure module subroutine stdlib${ii}$_cggrqf( m, p, n, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_cggrqf pure module subroutine stdlib${ii}$_zggrqf( m, p, n, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_zggrqf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ggrqf( m, p, n, a, lda, taua, b, ldb, taub, work,lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: taua(*), taub(*), work(*) end subroutine stdlib${ii}$_${ci}$ggrqf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgelq( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_sgelq pure module subroutine stdlib${ii}$_dgelq( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_dgelq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gelq( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_${ri}$gelq #:endif #:endfor pure module subroutine stdlib${ii}$_cgelq( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_cgelq pure module subroutine stdlib${ii}$_zgelq( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_zgelq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gelq( m, n, a, lda, t, tsize, work, lwork,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: t(*), work(*) end subroutine stdlib${ii}$_${ci}$gelq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc real(sp), intent(in) :: a(lda,*), t(*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sgemlq pure module subroutine stdlib${ii}$_dgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc real(dp), intent(in) :: a(lda,*), t(*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dgemlq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc real(${rk}$), intent(in) :: a(lda,*), t(*) real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$gemlq #:endif #:endfor pure module subroutine stdlib${ii}$_cgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc complex(sp), intent(in) :: a(lda,*), t(*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cgemlq pure module subroutine stdlib${ii}$_zgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc complex(dp), intent(in) :: a(lda,*), t(*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zgemlq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, & info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc complex(${ck}$), intent(in) :: a(lda,*), t(*) complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$gemlq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgelqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_sgelqf pure module subroutine stdlib${ii}$_dgelqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dgelqf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gelqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$gelqf #:endif #:endfor pure module subroutine stdlib${ii}$_cgelqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_cgelqf pure module subroutine stdlib${ii}$_zgelqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zgelqf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gelqf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$gelqf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgelq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_sgelq2 pure module subroutine stdlib${ii}$_dgelq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dgelq2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gelq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$gelq2 #:endif #:endfor pure module subroutine stdlib${ii}$_cgelq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_cgelq2 pure module subroutine stdlib${ii}$_zgelq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zgelq2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gelq2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$gelq2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunglq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunglq pure module subroutine stdlib${ii}$_zunglq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunglq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unglq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unglq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cungl2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cungl2 pure module subroutine stdlib${ii}$_zungl2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zungl2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ungl2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$ungl2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunmlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunmlq pure module subroutine stdlib${ii}$_zunmlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunmlq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unmlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unmlq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunml2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunml2 pure module subroutine stdlib${ii}$_zunml2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunml2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unml2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unml2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorglq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorglq pure module subroutine stdlib${ii}$_dorglq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorglq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orglq( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$orglq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorgl2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorgl2 pure module subroutine stdlib${ii}$_dorgl2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorgl2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orgl2( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$orgl2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sormlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sormlq pure module subroutine stdlib${ii}$_dormlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dormlq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ormlq( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$ormlq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorml2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorml2 pure module subroutine stdlib${ii}$_dorml2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorml2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orml2( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$orml2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgelqt( m, n, mb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, mb real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_sgelqt pure module subroutine stdlib${ii}$_dgelqt( m, n, mb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, mb real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_dgelqt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gelqt( m, n, mb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, mb real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_${ri}$gelqt #:endif #:endfor pure module subroutine stdlib${ii}$_cgelqt( m, n, mb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, mb complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_cgelqt pure module subroutine stdlib${ii}$_zgelqt( m, n, mb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, mb complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_zgelqt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gelqt( m, n, mb, a, lda, t, ldt, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldt, m, n, mb complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_${ci}$gelqt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure recursive module subroutine stdlib${ii}$_sgelqt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_sgelqt3 pure recursive module subroutine stdlib${ii}$_dgelqt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_dgelqt3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure recursive module subroutine stdlib${ii}$_${ri}$gelqt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_${ri}$gelqt3 #:endif #:endfor pure recursive module subroutine stdlib${ii}$_cgelqt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_cgelqt3 pure recursive module subroutine stdlib${ii}$_zgelqt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_zgelqt3 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure recursive module subroutine stdlib${ii}$_${ci}$gelqt3( m, n, a, lda, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, ldt complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_${ci}$gelqt3 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgemlqt( side, trans, m, n, k, mb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, mb, ldt real(sp), intent(in) :: v(ldv,*), t(ldt,*) real(sp), intent(inout) :: c(ldc,*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sgemlqt pure module subroutine stdlib${ii}$_dgemlqt( side, trans, m, n, k, mb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, mb, ldt real(dp), intent(in) :: v(ldv,*), t(ldt,*) real(dp), intent(inout) :: c(ldc,*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dgemlqt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$gemlqt( side, trans, m, n, k, mb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, mb, ldt real(${rk}$), intent(in) :: v(ldv,*), t(ldt,*) real(${rk}$), intent(inout) :: c(ldc,*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$gemlqt #:endif #:endfor pure module subroutine stdlib${ii}$_cgemlqt( side, trans, m, n, k, mb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, mb, ldt complex(sp), intent(in) :: v(ldv,*), t(ldt,*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cgemlqt pure module subroutine stdlib${ii}$_zgemlqt( side, trans, m, n, k, mb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, mb, ldt complex(dp), intent(in) :: v(ldv,*), t(ldt,*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zgemlqt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$gemlqt( side, trans, m, n, k, mb, v, ldv, t, ldt,c, ldc, work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, ldc, m, n, mb, ldt complex(${ck}$), intent(in) :: v(ldv,*), t(ldt,*) complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$gemlqt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slaswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, lwork, ldt real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_slaswlq pure module subroutine stdlib${ii}$_dlaswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, lwork, ldt real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_dlaswlq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, lwork, ldt real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_${ri}$laswlq #:endif #:endfor pure module subroutine stdlib${ii}$_claswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, lwork, ldt complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_claswlq pure module subroutine stdlib${ii}$_zlaswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, lwork, ldt complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_zlaswlq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laswlq( m, n, mb, nb, a, lda, t, ldt, work, lwork,info) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, mb, nb, lwork, ldt complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*), t(ldt,*) end subroutine stdlib${ii}$_${ci}$laswlq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc real(sp), intent(in) :: a(lda,*), t(ldt,*) real(sp), intent(out) :: work(*) real(sp), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_slamswlq pure module subroutine stdlib${ii}$_dlamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc real(dp), intent(in) :: a(lda,*), t(ldt,*) real(dp), intent(out) :: work(*) real(dp), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_dlamswlq #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc real(${rk}$), intent(in) :: a(lda,*), t(ldt,*) real(${rk}$), intent(out) :: work(*) real(${rk}$), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_${ri}$lamswlq #:endif #:endfor pure module subroutine stdlib${ii}$_clamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc complex(sp), intent(in) :: a(lda,*), t(ldt,*) complex(sp), intent(out) :: work(*) complex(sp), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_clamswlq pure module subroutine stdlib${ii}$_zlamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc complex(dp), intent(in) :: a(lda,*), t(ldt,*) complex(dp), intent(out) :: work(*) complex(dp), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_zlamswlq #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lamswlq( side, trans, m, n, k, mb, nb, a, lda, t,ldt, c, ldc, work, & lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n, k, mb, nb, ldt, lwork, ldc complex(${ck}$), intent(in) :: a(lda,*), t(ldt,*) complex(${ck}$), intent(out) :: work(*) complex(${ck}$), intent(inout) :: c(ldc,*) end subroutine stdlib${ii}$_${ci}$lamswlq #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_stplqt pure module subroutine stdlib${ii}$_dtplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_dtplqt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_${ri}$tplqt #:endif #:endfor pure module subroutine stdlib${ii}$_ctplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_ctplqt pure module subroutine stdlib${ii}$_ztplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_ztplqt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tplqt( m, n, l, mb, a, lda, b, ldb, t, ldt, work,info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l, mb complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: t(ldt,*), work(*) end subroutine stdlib${ii}$_${ci}$tplqt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stplqt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_stplqt2 pure module subroutine stdlib${ii}$_dtplqt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_dtplqt2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tplqt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_${ri}$tplqt2 #:endif #:endfor pure module subroutine stdlib${ii}$_ctplqt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_ctplqt2 pure module subroutine stdlib${ii}$_ztplqt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_ztplqt2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tplqt2( m, n, l, a, lda, b, ldb, t, ldt, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldt, n, m, l complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: t(ldt,*) end subroutine stdlib${ii}$_${ci}$tplqt2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_stpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, mb, ldt real(sp), intent(in) :: v(ldv,*), t(ldt,*) real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_stpmlqt pure module subroutine stdlib${ii}$_dtpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, mb, ldt real(dp), intent(in) :: v(ldv,*), t(ldt,*) real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dtpmlqt #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, mb, ldt real(${rk}$), intent(in) :: v(ldv,*), t(ldt,*) real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$tpmlqt #:endif #:endfor pure module subroutine stdlib${ii}$_ctpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, mb, ldt complex(sp), intent(in) :: v(ldv,*), t(ldt,*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_ctpmlqt pure module subroutine stdlib${ii}$_ztpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, mb, ldt complex(dp), intent(in) :: v(ldv,*), t(ldt,*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_ztpmlqt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tpmlqt( side, trans, m, n, k, l, mb, v, ldv, t, ldt,a, lda, b, ldb, & work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, ldv, lda, ldb, m, n, l, mb, ldt complex(${ck}$), intent(in) :: v(ldv,*), t(ldt,*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$tpmlqt #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgeqlf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_sgeqlf pure module subroutine stdlib${ii}$_dgeqlf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dgeqlf #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$geqlf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$geqlf #:endif #:endfor pure module subroutine stdlib${ii}$_cgeqlf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_cgeqlf pure module subroutine stdlib${ii}$_zgeqlf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zgeqlf #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$geqlf( m, n, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$geqlf #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sgeql2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_sgeql2 pure module subroutine stdlib${ii}$_dgeql2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_dgeql2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$geql2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ri}$geql2 #:endif #:endfor pure module subroutine stdlib${ii}$_cgeql2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_cgeql2 pure module subroutine stdlib${ii}$_zgeql2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_zgeql2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$geql2( m, n, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: tau(*), work(*) end subroutine stdlib${ii}$_${ci}$geql2 #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cungql( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cungql pure module subroutine stdlib${ii}$_zungql( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zungql #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ungql( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$ungql #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunmql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunmql pure module subroutine stdlib${ii}$_zunmql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunmql #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unmql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unmql #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cung2l( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cung2l pure module subroutine stdlib${ii}$_zung2l( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zung2l #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$ung2l( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$ung2l #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunm2l( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(sp), intent(inout) :: a(lda,*), c(ldc,*) complex(sp), intent(in) :: tau(*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunm2l pure module subroutine stdlib${ii}$_zunm2l( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(dp), intent(inout) :: a(lda,*), c(ldc,*) complex(dp), intent(in) :: tau(*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunm2l #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unm2l( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*) complex(${ck}$), intent(in) :: tau(*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unm2l #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorgql( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorgql pure module subroutine stdlib${ii}$_dorgql( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorgql #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orgql( m, n, k, a, lda, tau, work, lwork, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$orgql #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sormql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sormql pure module subroutine stdlib${ii}$_dormql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dormql #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$ormql( side, trans, m, n, k, a, lda, tau, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, lwork, m, n real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$ormql #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorg2l( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(sp), intent(inout) :: a(lda,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorg2l pure module subroutine stdlib${ii}$_dorg2l( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(dp), intent(inout) :: a(lda,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorg2l #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$org2l( m, n, k, a, lda, tau, work, info ) integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, m, n real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$org2l #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_sorm2l( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(sp), intent(inout) :: a(lda,*), c(ldc,*) real(sp), intent(in) :: tau(*) real(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_sorm2l pure module subroutine stdlib${ii}$_dorm2l( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(dp), intent(inout) :: a(lda,*), c(ldc,*) real(dp), intent(in) :: tau(*) real(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_dorm2l #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$orm2l( side, trans, m, n, k, a, lda, tau, c, ldc,work, info ) character, intent(in) :: side, trans integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: k, lda, ldc, m, n real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*) real(${rk}$), intent(in) :: tau(*) real(${rk}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ri}$orm2l #:endif #:endfor #:endfor end interface interface #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_cunm22( side, trans, m, n, n1, n2, q, ldq, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(in) :: m, n, n1, n2, ldq, ldc, lwork integer(${ik}$), intent(out) :: info complex(sp), intent(in) :: q(ldq,*) complex(sp), intent(inout) :: c(ldc,*) complex(sp), intent(out) :: work(*) end subroutine stdlib${ii}$_cunm22 pure module subroutine stdlib${ii}$_zunm22( side, trans, m, n, n1, n2, q, ldq, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(in) :: m, n, n1, n2, ldq, ldc, lwork integer(${ik}$), intent(out) :: info complex(dp), intent(in) :: q(ldq,*) complex(dp), intent(inout) :: c(ldc,*) complex(dp), intent(out) :: work(*) end subroutine stdlib${ii}$_zunm22 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$unm22( side, trans, m, n, n1, n2, q, ldq, c, ldc,work, lwork, info ) character, intent(in) :: side, trans integer(${ik}$), intent(in) :: m, n, n1, n2, ldq, ldc, lwork integer(${ik}$), intent(out) :: info complex(${ck}$), intent(in) :: q(ldq,*) complex(${ck}$), intent(inout) :: c(ldc,*) complex(${ck}$), intent(out) :: work(*) end subroutine stdlib${ii}$_${ci}$unm22 #:endif #:endfor #:endfor end interface end module stdlib_lapack_orthogonal_factors fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_svd_bidiag_qr.fypp0000664000175000017500000045430215135654166026571 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_svd_bidiag_qr implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slasq1( n, d, e, work, info ) !! SLASQ1 computes the singular values of a real N-by-N bidiagonal !! matrix with diagonal D and off-diagonal E. The singular values !! are computed to high relative accuracy, in the absence of !! denormalization, underflow and overflow. The algorithm was first !! presented in !! "Accurate singular values and differential qd algorithms" by K. V. !! Fernando and B. N. Parlett, Numer. Math., Vol-67, No. 2, pp. 191-230, !! 1994, !! and the present implementation is described in "An implementation of !! the dqds Algorithm (Positive Case)", LAPACK Working Note. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(inout) :: d(*), e(*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, iinfo real(sp) :: eps, scale, safmin, sigmn, sigmx ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'SLASQ1', -info ) return else if( n==0_${ik}$ ) then return else if( n==1_${ik}$ ) then d( 1_${ik}$ ) = abs( d( 1_${ik}$ ) ) return else if( n==2_${ik}$ ) then call stdlib${ii}$_slas2( d( 1_${ik}$ ), e( 1_${ik}$ ), d( 2_${ik}$ ), sigmn, sigmx ) d( 1_${ik}$ ) = sigmx d( 2_${ik}$ ) = sigmn return end if ! estimate the largest singular value. sigmx = zero do i = 1, n - 1 d( i ) = abs( d( i ) ) sigmx = max( sigmx, abs( e( i ) ) ) end do d( n ) = abs( d( n ) ) ! early return if sigmx is zero (matrix is already diagonal). if( sigmx==zero ) then call stdlib${ii}$_slasrt( 'D', n, d, iinfo ) return end if do i = 1, n sigmx = max( sigmx, d( i ) ) end do ! copy d and e into work (in the z format) and scale (squaring the ! input data makes scaling by a power of the radix pointless). eps = stdlib${ii}$_slamch( 'PRECISION' ) safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) scale = sqrt( eps / safmin ) call stdlib${ii}$_scopy( n, d, 1_${ik}$, work( 1_${ik}$ ), 2_${ik}$ ) call stdlib${ii}$_scopy( n-1, e, 1_${ik}$, work( 2_${ik}$ ), 2_${ik}$ ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, sigmx, scale, 2_${ik}$*n-1, 1_${ik}$, work, 2_${ik}$*n-1,iinfo ) ! compute the q's and e's. do i = 1, 2*n - 1 work( i ) = work( i )**2_${ik}$ end do work( 2_${ik}$*n ) = zero call stdlib${ii}$_slasq2( n, work, info ) if( info==0_${ik}$ ) then do i = 1, n d( i ) = sqrt( work( i ) ) end do call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, scale, sigmx, n, 1_${ik}$, d, n, iinfo ) else if( info==2_${ik}$ ) then ! maximum number of iterations exceeded. move data from work ! into d and e so the calling subroutine can try to finish do i = 1, n d( i ) = sqrt( work( 2_${ik}$*i-1 ) ) e( i ) = sqrt( work( 2_${ik}$*i ) ) end do call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, scale, sigmx, n, 1_${ik}$, d, n, iinfo ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, scale, sigmx, n, 1_${ik}$, e, n, iinfo ) end if return end subroutine stdlib${ii}$_slasq1 pure module subroutine stdlib${ii}$_dlasq1( n, d, e, work, info ) !! DLASQ1 computes the singular values of a real N-by-N bidiagonal !! matrix with diagonal D and off-diagonal E. The singular values !! are computed to high relative accuracy, in the absence of !! denormalization, underflow and overflow. The algorithm was first !! presented in !! "Accurate singular values and differential qd algorithms" by K. V. !! Fernando and B. N. Parlett, Numer. Math., Vol-67, No. 2, pp. 191-230, !! 1994, !! and the present implementation is described in "An implementation of !! the dqds Algorithm (Positive Case)", LAPACK Working Note. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(dp), intent(inout) :: d(*), e(*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, iinfo real(dp) :: eps, scale, safmin, sigmn, sigmx ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'DLASQ1', -info ) return else if( n==0_${ik}$ ) then return else if( n==1_${ik}$ ) then d( 1_${ik}$ ) = abs( d( 1_${ik}$ ) ) return else if( n==2_${ik}$ ) then call stdlib${ii}$_dlas2( d( 1_${ik}$ ), e( 1_${ik}$ ), d( 2_${ik}$ ), sigmn, sigmx ) d( 1_${ik}$ ) = sigmx d( 2_${ik}$ ) = sigmn return end if ! estimate the largest singular value. sigmx = zero do i = 1, n - 1 d( i ) = abs( d( i ) ) sigmx = max( sigmx, abs( e( i ) ) ) end do d( n ) = abs( d( n ) ) ! early return if sigmx is zero (matrix is already diagonal). if( sigmx==zero ) then call stdlib${ii}$_dlasrt( 'D', n, d, iinfo ) return end if do i = 1, n sigmx = max( sigmx, d( i ) ) end do ! copy d and e into work (in the z format) and scale (squaring the ! input data makes scaling by a power of the radix pointless). eps = stdlib${ii}$_dlamch( 'PRECISION' ) safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) scale = sqrt( eps / safmin ) call stdlib${ii}$_dcopy( n, d, 1_${ik}$, work( 1_${ik}$ ), 2_${ik}$ ) call stdlib${ii}$_dcopy( n-1, e, 1_${ik}$, work( 2_${ik}$ ), 2_${ik}$ ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, sigmx, scale, 2_${ik}$*n-1, 1_${ik}$, work, 2_${ik}$*n-1,iinfo ) ! compute the q's and e's. do i = 1, 2*n - 1 work( i ) = work( i )**2_${ik}$ end do work( 2_${ik}$*n ) = zero call stdlib${ii}$_dlasq2( n, work, info ) if( info==0_${ik}$ ) then do i = 1, n d( i ) = sqrt( work( i ) ) end do call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, scale, sigmx, n, 1_${ik}$, d, n, iinfo ) else if( info==2_${ik}$ ) then ! maximum number of iterations exceeded. move data from work ! into d and e so the calling subroutine can try to finish do i = 1, n d( i ) = sqrt( work( 2_${ik}$*i-1 ) ) e( i ) = sqrt( work( 2_${ik}$*i ) ) end do call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, scale, sigmx, n, 1_${ik}$, d, n, iinfo ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, scale, sigmx, n, 1_${ik}$, e, n, iinfo ) end if return end subroutine stdlib${ii}$_dlasq1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lasq1( n, d, e, work, info ) !! DLASQ1: computes the singular values of a real N-by-N bidiagonal !! matrix with diagonal D and off-diagonal E. The singular values !! are computed to high relative accuracy, in the absence of !! denormalization, underflow and overflow. The algorithm was first !! presented in !! "Accurate singular values and differential qd algorithms" by K. V. !! Fernando and B. N. Parlett, Numer. Math., Vol-67, No. 2, pp. 191-230, !! 1994, !! and the present implementation is described in "An implementation of !! the dqds Algorithm (Positive Case)", LAPACK Working Note. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(${rk}$), intent(inout) :: d(*), e(*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, iinfo real(${rk}$) :: eps, scale, safmin, sigmn, sigmx ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'DLASQ1', -info ) return else if( n==0_${ik}$ ) then return else if( n==1_${ik}$ ) then d( 1_${ik}$ ) = abs( d( 1_${ik}$ ) ) return else if( n==2_${ik}$ ) then call stdlib${ii}$_${ri}$las2( d( 1_${ik}$ ), e( 1_${ik}$ ), d( 2_${ik}$ ), sigmn, sigmx ) d( 1_${ik}$ ) = sigmx d( 2_${ik}$ ) = sigmn return end if ! estimate the largest singular value. sigmx = zero do i = 1, n - 1 d( i ) = abs( d( i ) ) sigmx = max( sigmx, abs( e( i ) ) ) end do d( n ) = abs( d( n ) ) ! early return if sigmx is zero (matrix is already diagonal). if( sigmx==zero ) then call stdlib${ii}$_${ri}$lasrt( 'D', n, d, iinfo ) return end if do i = 1, n sigmx = max( sigmx, d( i ) ) end do ! copy d and e into work (in the z format) and scale (squaring the ! input data makes scaling by a power of the radix pointless). eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) scale = sqrt( eps / safmin ) call stdlib${ii}$_${ri}$copy( n, d, 1_${ik}$, work( 1_${ik}$ ), 2_${ik}$ ) call stdlib${ii}$_${ri}$copy( n-1, e, 1_${ik}$, work( 2_${ik}$ ), 2_${ik}$ ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, sigmx, scale, 2_${ik}$*n-1, 1_${ik}$, work, 2_${ik}$*n-1,iinfo ) ! compute the q's and e's. do i = 1, 2*n - 1 work( i ) = work( i )**2_${ik}$ end do work( 2_${ik}$*n ) = zero call stdlib${ii}$_${ri}$lasq2( n, work, info ) if( info==0_${ik}$ ) then do i = 1, n d( i ) = sqrt( work( i ) ) end do call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, scale, sigmx, n, 1_${ik}$, d, n, iinfo ) else if( info==2_${ik}$ ) then ! maximum number of iterations exceeded. move data from work ! into d and e so the calling subroutine can try to finish do i = 1, n d( i ) = sqrt( work( 2_${ik}$*i-1 ) ) e( i ) = sqrt( work( 2_${ik}$*i ) ) end do call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, scale, sigmx, n, 1_${ik}$, d, n, iinfo ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, scale, sigmx, n, 1_${ik}$, e, n, iinfo ) end if return end subroutine stdlib${ii}$_${ri}$lasq1 #:endif #:endfor pure module subroutine stdlib${ii}$_slasq2( n, z, info ) !! SLASQ2 computes all the eigenvalues of the symmetric positive !! definite tridiagonal matrix associated with the qd array Z to high !! relative accuracy are computed to high relative accuracy, in the !! absence of denormalization, underflow and overflow. !! To see the relation of Z to the tridiagonal matrix, let L be a !! unit lower bidiagonal matrix with subdiagonals Z(2,4,6,,..) and !! let U be an upper bidiagonal matrix with 1's above and diagonal !! Z(1,3,5,,..). The tridiagonal is L*U or, if you prefer, the !! symmetric tridiagonal to which it is similar. !! Note : SLASQ2 defines a logical variable, IEEE, which is true !! on machines which follow ieee-754 floating-point standard in their !! handling of infinities and NaNs, and false otherwise. This variable !! is passed to SLASQ3. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: n ! Array Arguments real(sp), intent(inout) :: z(*) ! ===================================================================== ! Parameters real(sp), parameter :: cbias = 1.50_sp real(sp), parameter :: hundrd = 100.0_sp ! Local Scalars logical(lk) :: ieee integer(${ik}$) :: i0, i4, iinfo, ipn4, iter, iwhila, iwhilb, k, kmin, n0, nbig, ndiv, & nfail, pp, splt, ttype, i1, n1 real(sp) :: d, dee, deemin, desig, dmin, dmin1, dmin2, dn, dn1, dn2, e, emax, emin, & eps, g, oldemn, qmax, qmin, s, safmin, sigma, t, tau, temp, tol, tol2, trace, zmax, & tempe, tempq ! Intrinsic Functions ! Executable Statements ! test the input arguments. ! (in case stdlib${ii}$_slasq2 is not called by stdlib${ii}$_slasq1) info = 0_${ik}$ eps = stdlib${ii}$_slamch( 'PRECISION' ) safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) tol = eps*hundrd tol2 = tol**2_${ik}$ if( n<0_${ik}$ ) then info = -1_${ik}$ call stdlib${ii}$_xerbla( 'SLASQ2', 1_${ik}$ ) return else if( n==0_${ik}$ ) then return else if( n==1_${ik}$ ) then ! 1-by-1 case. if( z( 1_${ik}$ )z( 1_${ik}$ ) ) then d = z( 3_${ik}$ ) z( 3_${ik}$ ) = z( 1_${ik}$ ) z( 1_${ik}$ ) = d end if z( 5_${ik}$ ) = z( 1_${ik}$ ) + z( 2_${ik}$ ) + z( 3_${ik}$ ) if( z( 2_${ik}$ )>z( 3_${ik}$ )*tol2 ) then t = half*( ( z( 1_${ik}$ )-z( 3_${ik}$ ) )+z( 2_${ik}$ ) ) s = z( 3_${ik}$ )*( z( 2_${ik}$ ) / t ) if( s<=t ) then s = z( 3_${ik}$ )*( z( 2_${ik}$ ) / ( t*( one+sqrt( one+s / t ) ) ) ) else s = z( 3_${ik}$ )*( z( 2_${ik}$ ) / ( t+sqrt( t )*sqrt( t+s ) ) ) end if t = z( 1_${ik}$ ) + ( s+z( 2_${ik}$ ) ) z( 3_${ik}$ ) = z( 3_${ik}$ )*( z( 1_${ik}$ ) / t ) z( 1_${ik}$ ) = t end if z( 2_${ik}$ ) = z( 3_${ik}$ ) z( 6_${ik}$ ) = z( 2_${ik}$ ) + z( 1_${ik}$ ) return end if ! check for negative data and compute sums of q's and e's. z( 2_${ik}$*n ) = zero emin = z( 2_${ik}$ ) qmax = zero zmax = zero d = zero e = zero do k = 1, 2*( n-1 ), 2 if( z( k )i0 ) then emin = abs( z( 4_${ik}$*n0-5 ) ) else emin = zero end if qmin = z( 4_${ik}$*n0-3 ) qmax = qmin do i4 = 4*n0, 8, -4 if( z( i4-5 )<=zero )go to 100 if( qmin>=four*emax ) then qmin = min( qmin, z( i4-3 ) ) emax = max( emax, z( i4-5 ) ) end if qmax = max( qmax, z( i4-7 )+z( i4-5 ) ) emin = min( emin, z( i4-5 ) ) end do i4 = 4_${ik}$ 100 continue i0 = i4 / 4_${ik}$ pp = 0_${ik}$ if( n0-i0>1_${ik}$ ) then dee = z( 4_${ik}$*i0-3 ) deemin = dee kmin = i0 do i4 = 4*i0+1, 4*n0-3, 4 dee = z( i4 )*( dee /( dee+z( i4-2 ) ) ) if( dee<=deemin ) then deemin = dee kmin = ( i4+3 )/4_${ik}$ end if end do if( (kmin-i0)*2_${ik}$n0 )go to 150 ! while submatrix unfinished take a good dqds step. call stdlib${ii}$_slasq3( i0, n0, z, pp, dmin, sigma, desig, qmax, nfail,iter, ndiv, & ieee, ttype, dmin1, dmin2, dn, dn1,dn2, g, tau ) pp = 1_${ik}$ - pp ! when emin is very small check for splits. if( pp==0_${ik}$ .and. n0-i0>=3_${ik}$ ) then if( z( 4_${ik}$*n0 )<=tol2*qmax .or.z( 4_${ik}$*n0-1 )<=tol2*sigma ) then splt = i0 - 1_${ik}$ qmax = z( 4_${ik}$*i0-3 ) emin = z( 4_${ik}$*i0-1 ) oldemn = z( 4_${ik}$*i0 ) do i4 = 4*i0, 4*( n0-3 ), 4 if( z( i4 )<=tol2*z( i4-3 ) .or.z( i4-1 )<=tol2*sigma ) then z( i4-1 ) = -sigma splt = i4 / 4_${ik}$ qmax = zero emin = z( i4+3 ) oldemn = z( i4+4 ) else qmax = max( qmax, z( i4+1 ) ) emin = min( emin, z( i4-1 ) ) oldemn = min( oldemn, z( i4 ) ) end if end do z( 4_${ik}$*n0-1 ) = emin z( 4_${ik}$*n0 ) = oldemn i0 = splt + 1_${ik}$ end if end if end do loop_140 info = 2_${ik}$ ! maximum number of iterations exceeded, restore the shift ! sigma and place the new d's and e's in a qd array. ! this might need to be done for several blocks i1 = i0 n1 = n0 145 continue tempq = z( 4_${ik}$*i0-3 ) z( 4_${ik}$*i0-3 ) = z( 4_${ik}$*i0-3 ) + sigma do k = i0+1, n0 tempe = z( 4_${ik}$*k-5 ) z( 4_${ik}$*k-5 ) = z( 4_${ik}$*k-5 ) * (tempq / z( 4_${ik}$*k-7 )) tempq = z( 4_${ik}$*k-3 ) z( 4_${ik}$*k-3 ) = z( 4_${ik}$*k-3 ) + sigma + tempe - z( 4_${ik}$*k-5 ) end do ! prepare to do this on the previous block if there is one if( i1>1_${ik}$ ) then n1 = i1-1 do while( ( i1>=2 ) .and. ( z(4*i1-5)>=zero ) ) i1 = i1 - 1_${ik}$ end do if( i1>=1_${ik}$ ) then sigma = -z(4_${ik}$*n1-1) go to 145 end if end if do k = 1, n z( 2_${ik}$*k-1 ) = z( 4_${ik}$*k-3 ) ! only the block 1..n0 is unfinished. the rest of the e's ! must be essentially zero, although sometimes other data ! has been stored in them. if( kz( 1_${ik}$ ) ) then d = z( 3_${ik}$ ) z( 3_${ik}$ ) = z( 1_${ik}$ ) z( 1_${ik}$ ) = d end if z( 5_${ik}$ ) = z( 1_${ik}$ ) + z( 2_${ik}$ ) + z( 3_${ik}$ ) if( z( 2_${ik}$ )>z( 3_${ik}$ )*tol2 ) then t = half*( ( z( 1_${ik}$ )-z( 3_${ik}$ ) )+z( 2_${ik}$ ) ) s = z( 3_${ik}$ )*( z( 2_${ik}$ ) / t ) if( s<=t ) then s = z( 3_${ik}$ )*( z( 2_${ik}$ ) / ( t*( one+sqrt( one+s / t ) ) ) ) else s = z( 3_${ik}$ )*( z( 2_${ik}$ ) / ( t+sqrt( t )*sqrt( t+s ) ) ) end if t = z( 1_${ik}$ ) + ( s+z( 2_${ik}$ ) ) z( 3_${ik}$ ) = z( 3_${ik}$ )*( z( 1_${ik}$ ) / t ) z( 1_${ik}$ ) = t end if z( 2_${ik}$ ) = z( 3_${ik}$ ) z( 6_${ik}$ ) = z( 2_${ik}$ ) + z( 1_${ik}$ ) return end if ! check for negative data and compute sums of q's and e's. z( 2_${ik}$*n ) = zero emin = z( 2_${ik}$ ) qmax = zero zmax = zero d = zero e = zero do k = 1, 2*( n-1 ), 2 if( z( k )i0 ) then emin = abs( z( 4_${ik}$*n0-5 ) ) else emin = zero end if qmin = z( 4_${ik}$*n0-3 ) qmax = qmin do i4 = 4*n0, 8, -4 if( z( i4-5 )<=zero )go to 100 if( qmin>=four*emax ) then qmin = min( qmin, z( i4-3 ) ) emax = max( emax, z( i4-5 ) ) end if qmax = max( qmax, z( i4-7 )+z( i4-5 ) ) emin = min( emin, z( i4-5 ) ) end do i4 = 4_${ik}$ 100 continue i0 = i4 / 4_${ik}$ pp = 0_${ik}$ if( n0-i0>1_${ik}$ ) then dee = z( 4_${ik}$*i0-3 ) deemin = dee kmin = i0 do i4 = 4*i0+1, 4*n0-3, 4 dee = z( i4 )*( dee /( dee+z( i4-2 ) ) ) if( dee<=deemin ) then deemin = dee kmin = ( i4+3 )/4_${ik}$ end if end do if( (kmin-i0)*2_${ik}$n0 )go to 150 ! while submatrix unfinished take a good dqds step. call stdlib${ii}$_dlasq3( i0, n0, z, pp, dmin, sigma, desig, qmax, nfail,iter, ndiv, & ieee, ttype, dmin1, dmin2, dn, dn1,dn2, g, tau ) pp = 1_${ik}$ - pp ! when emin is very small check for splits. if( pp==0_${ik}$ .and. n0-i0>=3_${ik}$ ) then if( z( 4_${ik}$*n0 )<=tol2*qmax .or.z( 4_${ik}$*n0-1 )<=tol2*sigma ) then splt = i0 - 1_${ik}$ qmax = z( 4_${ik}$*i0-3 ) emin = z( 4_${ik}$*i0-1 ) oldemn = z( 4_${ik}$*i0 ) do i4 = 4*i0, 4*( n0-3 ), 4 if( z( i4 )<=tol2*z( i4-3 ) .or.z( i4-1 )<=tol2*sigma ) then z( i4-1 ) = -sigma splt = i4 / 4_${ik}$ qmax = zero emin = z( i4+3 ) oldemn = z( i4+4 ) else qmax = max( qmax, z( i4+1 ) ) emin = min( emin, z( i4-1 ) ) oldemn = min( oldemn, z( i4 ) ) end if end do z( 4_${ik}$*n0-1 ) = emin z( 4_${ik}$*n0 ) = oldemn i0 = splt + 1_${ik}$ end if end if end do loop_140 info = 2_${ik}$ ! maximum number of iterations exceeded, restore the shift ! sigma and place the new d's and e's in a qd array. ! this might need to be done for several blocks i1 = i0 n1 = n0 145 continue tempq = z( 4_${ik}$*i0-3 ) z( 4_${ik}$*i0-3 ) = z( 4_${ik}$*i0-3 ) + sigma do k = i0+1, n0 tempe = z( 4_${ik}$*k-5 ) z( 4_${ik}$*k-5 ) = z( 4_${ik}$*k-5 ) * (tempq / z( 4_${ik}$*k-7 )) tempq = z( 4_${ik}$*k-3 ) z( 4_${ik}$*k-3 ) = z( 4_${ik}$*k-3 ) + sigma + tempe - z( 4_${ik}$*k-5 ) end do ! prepare to do this on the previous block if there is one if( i1>1_${ik}$ ) then n1 = i1-1 do while( ( i1>=2 ) .and. ( z(4*i1-5)>=zero ) ) i1 = i1 - 1_${ik}$ end do sigma = -z(4_${ik}$*n1-1) go to 145 end if do k = 1, n z( 2_${ik}$*k-1 ) = z( 4_${ik}$*k-3 ) ! only the block 1..n0 is unfinished. the rest of the e's ! must be essentially zero, although sometimes other data ! has been stored in them. if( kz( 1_${ik}$ ) ) then d = z( 3_${ik}$ ) z( 3_${ik}$ ) = z( 1_${ik}$ ) z( 1_${ik}$ ) = d end if z( 5_${ik}$ ) = z( 1_${ik}$ ) + z( 2_${ik}$ ) + z( 3_${ik}$ ) if( z( 2_${ik}$ )>z( 3_${ik}$ )*tol2 ) then t = half*( ( z( 1_${ik}$ )-z( 3_${ik}$ ) )+z( 2_${ik}$ ) ) s = z( 3_${ik}$ )*( z( 2_${ik}$ ) / t ) if( s<=t ) then s = z( 3_${ik}$ )*( z( 2_${ik}$ ) / ( t*( one+sqrt( one+s / t ) ) ) ) else s = z( 3_${ik}$ )*( z( 2_${ik}$ ) / ( t+sqrt( t )*sqrt( t+s ) ) ) end if t = z( 1_${ik}$ ) + ( s+z( 2_${ik}$ ) ) z( 3_${ik}$ ) = z( 3_${ik}$ )*( z( 1_${ik}$ ) / t ) z( 1_${ik}$ ) = t end if z( 2_${ik}$ ) = z( 3_${ik}$ ) z( 6_${ik}$ ) = z( 2_${ik}$ ) + z( 1_${ik}$ ) return end if ! check for negative data and compute sums of q's and e's. z( 2_${ik}$*n ) = zero emin = z( 2_${ik}$ ) qmax = zero zmax = zero d = zero e = zero do k = 1, 2*( n-1 ), 2 if( z( k )i0 ) then emin = abs( z( 4_${ik}$*n0-5 ) ) else emin = zero end if qmin = z( 4_${ik}$*n0-3 ) qmax = qmin do i4 = 4*n0, 8, -4 if( z( i4-5 )<=zero )go to 100 if( qmin>=four*emax ) then qmin = min( qmin, z( i4-3 ) ) emax = max( emax, z( i4-5 ) ) end if qmax = max( qmax, z( i4-7 )+z( i4-5 ) ) emin = min( emin, z( i4-5 ) ) end do i4 = 4_${ik}$ 100 continue i0 = i4 / 4_${ik}$ pp = 0_${ik}$ if( n0-i0>1_${ik}$ ) then dee = z( 4_${ik}$*i0-3 ) deemin = dee kmin = i0 do i4 = 4*i0+1, 4*n0-3, 4 dee = z( i4 )*( dee /( dee+z( i4-2 ) ) ) if( dee<=deemin ) then deemin = dee kmin = ( i4+3 )/4_${ik}$ end if end do if( (kmin-i0)*2_${ik}$n0 )go to 150 ! while submatrix unfinished take a good dqds step. call stdlib${ii}$_${ri}$lasq3( i0, n0, z, pp, dmin, sigma, desig, qmax, nfail,iter, ndiv, & ieee, ttype, dmin1, dmin2, dn, dn1,dn2, g, tau ) pp = 1_${ik}$ - pp ! when emin is very small check for splits. if( pp==0_${ik}$ .and. n0-i0>=3_${ik}$ ) then if( z( 4_${ik}$*n0 )<=tol2*qmax .or.z( 4_${ik}$*n0-1 )<=tol2*sigma ) then splt = i0 - 1_${ik}$ qmax = z( 4_${ik}$*i0-3 ) emin = z( 4_${ik}$*i0-1 ) oldemn = z( 4_${ik}$*i0 ) do i4 = 4*i0, 4*( n0-3 ), 4 if( z( i4 )<=tol2*z( i4-3 ) .or.z( i4-1 )<=tol2*sigma ) then z( i4-1 ) = -sigma splt = i4 / 4_${ik}$ qmax = zero emin = z( i4+3 ) oldemn = z( i4+4 ) else qmax = max( qmax, z( i4+1 ) ) emin = min( emin, z( i4-1 ) ) oldemn = min( oldemn, z( i4 ) ) end if end do z( 4_${ik}$*n0-1 ) = emin z( 4_${ik}$*n0 ) = oldemn i0 = splt + 1_${ik}$ end if end if end do loop_140 info = 2_${ik}$ ! maximum number of iterations exceeded, restore the shift ! sigma and place the new d's and e's in a qd array. ! this might need to be done for several blocks i1 = i0 n1 = n0 145 continue tempq = z( 4_${ik}$*i0-3 ) z( 4_${ik}$*i0-3 ) = z( 4_${ik}$*i0-3 ) + sigma do k = i0+1, n0 tempe = z( 4_${ik}$*k-5 ) z( 4_${ik}$*k-5 ) = z( 4_${ik}$*k-5 ) * (tempq / z( 4_${ik}$*k-7 )) tempq = z( 4_${ik}$*k-3 ) z( 4_${ik}$*k-3 ) = z( 4_${ik}$*k-3 ) + sigma + tempe - z( 4_${ik}$*k-5 ) end do ! prepare to do this on the previous block if there is one if( i1>1_${ik}$ ) then n1 = i1-1 do while( ( i1>=2 ) .and. ( z(4*i1-5)>=zero ) ) i1 = i1 - 1_${ik}$ end do sigma = -z(4_${ik}$*n1-1) go to 145 end if do k = 1, n z( 2_${ik}$*k-1 ) = z( 4_${ik}$*k-3 ) ! only the block 1..n0 is unfinished. the rest of the e's ! must be essentially zero, although sometimes other data ! has been stored in them. if( ktol2*( sigma+z( nn-3 ) ) .and.z( nn-2*pp-4 )>tol2*z( nn-7 ) )go to 30 20 continue z( 4_${ik}$*n0-3 ) = z( 4_${ik}$*n0+pp-3 ) + sigma n0 = n0 - 1_${ik}$ go to 10 ! check whether e(n0-2) is negligible, 2 eigenvalues. 30 continue if( z( nn-9 )>tol2*sigma .and.z( nn-2*pp-8 )>tol2*z( nn-11 ) )go to 50 40 continue if( z( nn-3 )>z( nn-7 ) ) then s = z( nn-3 ) z( nn-3 ) = z( nn-7 ) z( nn-7 ) = s end if t = half*( ( z( nn-7 )-z( nn-3 ) )+z( nn-5 ) ) if( z( nn-5 )>z( nn-3 )*tol2.and.t/=zero ) then s = z( nn-3 )*( z( nn-5 ) / t ) if( s<=t ) then s = z( nn-3 )*( z( nn-5 ) /( t*( one+sqrt( one+s / t ) ) ) ) else s = z( nn-3 )*( z( nn-5 ) / ( t+sqrt( t )*sqrt( t+s ) ) ) end if t = z( nn-7 ) + ( s+z( nn-5 ) ) z( nn-3 ) = z( nn-3 )*( z( nn-7 ) / t ) z( nn-7 ) = t end if z( 4_${ik}$*n0-7 ) = z( nn-7 ) + sigma z( 4_${ik}$*n0-3 ) = z( nn-3 ) + sigma n0 = n0 - 2_${ik}$ go to 10 50 continue if( pp==2_${ik}$ )pp = 0_${ik}$ ! reverse the qd-array, if warranted. if( dmin<=zero .or. n0 0. 70 continue call stdlib${ii}$_slasq5( i0, n0, z, pp, tau, sigma, dmin, dmin1, dmin2, dn,dn1, dn2, ieee, & eps ) ndiv = ndiv + ( n0-i0+2 ) iter = iter + 1_${ik}$ ! check status. if( dmin>=zero .and. dmin1>=zero ) then ! success. go to 90 else if( dminzero .and.z( 4_${ik}$*( n0-1 )-pp )

= 1, DTGSYL computes a Frobenius norm-based estimate !! of Dif[(A,D),(B,E)]. That is, the reciprocal of a lower bound on the !! reciprocal of the smallest singular value of Z. See [1-2] for more !! information. !! This is a level 3 BLAS algorithm. ldf, scale, dif, work, lwork,iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob, lda, ldb, ldc, ldd, lde, ldf, lwork, m, n integer(${ik}$), intent(out) :: info real(dp), intent(out) :: dif, scale ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: a(lda,*), b(ldb,*), d(ldd,*), e(lde,*) real(dp), intent(inout) :: c(ldc,*), f(ldf,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! replaced various illegal calls to stdlib${ii}$_dcopy by calls to stdlib${ii}$_dlaset. ! sven hammarling, 1/5/02. ! Local Scalars logical(lk) :: lquery, notran integer(${ik}$) :: i, ie, ifunc, iround, is, isolve, j, je, js, k, linfo, lwmin, mb, nb, & p, ppqq, pq, q real(dp) :: dscale, dsum, scale2, scaloc ! Intrinsic Functions ! Executable Statements ! decode and test input parameters info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -1_${ik}$ else if( notran ) then if( ( ijob<0_${ik}$ ) .or. ( ijob>4_${ik}$ ) ) then info = -2_${ik}$ end if end if if( info==0_${ik}$ ) then if( m<=0_${ik}$ ) then info = -3_${ik}$ else if( n<=0_${ik}$ ) then info = -4_${ik}$ else if( lda=3_${ik}$ ) then ifunc = ijob - 2_${ik}$ call stdlib${ii}$_dlaset( 'F', m, n, zero, zero, c, ldc ) call stdlib${ii}$_dlaset( 'F', m, n, zero, zero, f, ldf ) else if( ijob>=1_${ik}$ ) then isolve = 2_${ik}$ end if end if if( ( mb<=1_${ik}$ .and. nb<=1_${ik}$ ) .or. ( mb>=m .and. nb>=n ) )then loop_30: do iround = 1, isolve ! use unblocked level 2 solver dscale = zero dsum = one pq = 0_${ik}$ call stdlib${ii}$_dtgsy2( trans, ifunc, m, n, a, lda, b, ldb, c, ldc, d,ldd, e, lde, f,& ldf, scale, dsum, dscale,iwork, pq, info ) if( dscale/=zero ) then if( ijob==1_${ik}$ .or. ijob==3_${ik}$ ) then dif = sqrt( real( 2_${ik}$*m*n,KIND=dp) ) / ( dscale*sqrt( dsum ) ) else dif = sqrt( real( pq,KIND=dp) ) / ( dscale*sqrt( dsum ) ) end if end if if( isolve==2_${ik}$ .and. iround==1_${ik}$ ) then if( notran ) then ifunc = ijob end if scale2 = scale call stdlib${ii}$_dlacpy( 'F', m, n, c, ldc, work, m ) call stdlib${ii}$_dlacpy( 'F', m, n, f, ldf, work( m*n+1 ), m ) call stdlib${ii}$_dlaset( 'F', m, n, zero, zero, c, ldc ) call stdlib${ii}$_dlaset( 'F', m, n, zero, zero, f, ldf ) else if( isolve==2_${ik}$ .and. iround==2_${ik}$ ) then call stdlib${ii}$_dlacpy( 'F', m, n, work, m, c, ldc ) call stdlib${ii}$_dlacpy( 'F', m, n, work( m*n+1 ), m, f, ldf ) scale = scale2 end if end do loop_30 return end if ! determine block structure of a p = 0_${ik}$ i = 1_${ik}$ 40 continue if( i>m )go to 50 p = p + 1_${ik}$ iwork( p ) = i i = i + mb if( i>=m )go to 50 if( a( i, i-1 )/=zero )i = i + 1_${ik}$ go to 40 50 continue iwork( p+1 ) = m + 1_${ik}$ if( iwork( p )==iwork( p+1 ) )p = p - 1_${ik}$ ! determine block structure of b q = p + 1_${ik}$ j = 1_${ik}$ 60 continue if( j>n )go to 70 q = q + 1_${ik}$ iwork( q ) = j j = j + nb if( j>=n )go to 70 if( b( j, j-1 )/=zero )j = j + 1_${ik}$ go to 60 70 continue iwork( q+1 ) = n + 1_${ik}$ if( iwork( q )==iwork( q+1 ) )q = q - 1_${ik}$ if( notran ) then loop_150: do iround = 1, isolve ! solve (i, j)-subsystem ! a(i, i) * r(i, j) - l(i, j) * b(j, j) = c(i, j) ! d(i, i) * r(i, j) - l(i, j) * e(j, j) = f(i, j) ! for i = p, p - 1,..., 1; j = 1, 2,..., q dscale = zero dsum = one pq = 0_${ik}$ scale = one loop_130: do j = p + 2, q js = iwork( j ) je = iwork( j+1 ) - 1_${ik}$ nb = je - js + 1_${ik}$ loop_120: do i = p, 1, -1 is = iwork( i ) ie = iwork( i+1 ) - 1_${ik}$ mb = ie - is + 1_${ik}$ ppqq = 0_${ik}$ call stdlib${ii}$_dtgsy2( trans, ifunc, mb, nb, a( is, is ), lda,b( js, js ), & ldb, c( is, js ), ldc,d( is, is ), ldd, e( js, js ), lde,f( is, js ), ldf, & scaloc, dsum, dscale,iwork( q+2 ), ppqq, linfo ) if( linfo>0_${ik}$ )info = linfo pq = pq + ppqq if( scaloc/=one ) then do k = 1, js - 1 call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_dscal( is-1, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( is-1, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_dscal( m-ie, scaloc, c( ie+1, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m-ie, scaloc, f( ie+1, k ), 1_${ik}$ ) end do do k = je + 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then call stdlib${ii}$_dgemm( 'N', 'N', is-1, nb, mb, -one,a( 1_${ik}$, is ), lda, c( is, & js ), ldc, one,c( 1_${ik}$, js ), ldc ) call stdlib${ii}$_dgemm( 'N', 'N', is-1, nb, mb, -one,d( 1_${ik}$, is ), ldd, c( is, & js ), ldc, one,f( 1_${ik}$, js ), ldf ) end if if( j0_${ik}$ )info = linfo if( scaloc/=one ) then do k = 1, js - 1 call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_dscal( is-1, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( is-1, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_dscal( m-ie, scaloc, c( ie+1, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m-ie, scaloc, f( ie+1, k ), 1_${ik}$ ) end do do k = je + 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! substitute r(i, j) and l(i, j) into remaining equation. if( j>p+2 ) then call stdlib${ii}$_dgemm( 'N', 'T', mb, js-1, nb, one, c( is, js ),ldc, b( 1_${ik}$, js )& , ldb, one, f( is, 1_${ik}$ ),ldf ) call stdlib${ii}$_dgemm( 'N', 'T', mb, js-1, nb, one, f( is, js ),ldf, e( 1_${ik}$, js )& , lde, one, f( is, 1_${ik}$ ),ldf ) end if if( i

= 1, DTGSYL computes a Frobenius norm-based estimate !! of Dif[(A,D),(B,E)]. That is, the reciprocal of a lower bound on the !! reciprocal of the smallest singular value of Z. See [1-2] for more !! information. !! This is a level 3 BLAS algorithm. ldf, scale, dif, work, lwork,iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob, lda, ldb, ldc, ldd, lde, ldf, lwork, m, n integer(${ik}$), intent(out) :: info real(${rk}$), intent(out) :: dif, scale ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: a(lda,*), b(ldb,*), d(ldd,*), e(lde,*) real(${rk}$), intent(inout) :: c(ldc,*), f(ldf,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! replaced various illegal calls to stdlib${ii}$_${ri}$copy by calls to stdlib${ii}$_${ri}$laset. ! sven hammarling, 1/5/02. ! Local Scalars logical(lk) :: lquery, notran integer(${ik}$) :: i, ie, ifunc, iround, is, isolve, j, je, js, k, linfo, lwmin, mb, nb, & p, ppqq, pq, q real(${rk}$) :: dscale, dsum, scale2, scaloc ! Intrinsic Functions ! Executable Statements ! decode and test input parameters info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -1_${ik}$ else if( notran ) then if( ( ijob<0_${ik}$ ) .or. ( ijob>4_${ik}$ ) ) then info = -2_${ik}$ end if end if if( info==0_${ik}$ ) then if( m<=0_${ik}$ ) then info = -3_${ik}$ else if( n<=0_${ik}$ ) then info = -4_${ik}$ else if( lda=3_${ik}$ ) then ifunc = ijob - 2_${ik}$ call stdlib${ii}$_${ri}$laset( 'F', m, n, zero, zero, c, ldc ) call stdlib${ii}$_${ri}$laset( 'F', m, n, zero, zero, f, ldf ) else if( ijob>=1_${ik}$ ) then isolve = 2_${ik}$ end if end if if( ( mb<=1_${ik}$ .and. nb<=1_${ik}$ ) .or. ( mb>=m .and. nb>=n ) )then loop_30: do iround = 1, isolve ! use unblocked level 2 solver dscale = zero dsum = one pq = 0_${ik}$ call stdlib${ii}$_${ri}$tgsy2( trans, ifunc, m, n, a, lda, b, ldb, c, ldc, d,ldd, e, lde, f,& ldf, scale, dsum, dscale,iwork, pq, info ) if( dscale/=zero ) then if( ijob==1_${ik}$ .or. ijob==3_${ik}$ ) then dif = sqrt( real( 2_${ik}$*m*n,KIND=${rk}$) ) / ( dscale*sqrt( dsum ) ) else dif = sqrt( real( pq,KIND=${rk}$) ) / ( dscale*sqrt( dsum ) ) end if end if if( isolve==2_${ik}$ .and. iround==1_${ik}$ ) then if( notran ) then ifunc = ijob end if scale2 = scale call stdlib${ii}$_${ri}$lacpy( 'F', m, n, c, ldc, work, m ) call stdlib${ii}$_${ri}$lacpy( 'F', m, n, f, ldf, work( m*n+1 ), m ) call stdlib${ii}$_${ri}$laset( 'F', m, n, zero, zero, c, ldc ) call stdlib${ii}$_${ri}$laset( 'F', m, n, zero, zero, f, ldf ) else if( isolve==2_${ik}$ .and. iround==2_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'F', m, n, work, m, c, ldc ) call stdlib${ii}$_${ri}$lacpy( 'F', m, n, work( m*n+1 ), m, f, ldf ) scale = scale2 end if end do loop_30 return end if ! determine block structure of a p = 0_${ik}$ i = 1_${ik}$ 40 continue if( i>m )go to 50 p = p + 1_${ik}$ iwork( p ) = i i = i + mb if( i>=m )go to 50 if( a( i, i-1 )/=zero )i = i + 1_${ik}$ go to 40 50 continue iwork( p+1 ) = m + 1_${ik}$ if( iwork( p )==iwork( p+1 ) )p = p - 1_${ik}$ ! determine block structure of b q = p + 1_${ik}$ j = 1_${ik}$ 60 continue if( j>n )go to 70 q = q + 1_${ik}$ iwork( q ) = j j = j + nb if( j>=n )go to 70 if( b( j, j-1 )/=zero )j = j + 1_${ik}$ go to 60 70 continue iwork( q+1 ) = n + 1_${ik}$ if( iwork( q )==iwork( q+1 ) )q = q - 1_${ik}$ if( notran ) then loop_150: do iround = 1, isolve ! solve (i, j)-subsystem ! a(i, i) * r(i, j) - l(i, j) * b(j, j) = c(i, j) ! d(i, i) * r(i, j) - l(i, j) * e(j, j) = f(i, j) ! for i = p, p - 1,..., 1; j = 1, 2,..., q dscale = zero dsum = one pq = 0_${ik}$ scale = one loop_130: do j = p + 2, q js = iwork( j ) je = iwork( j+1 ) - 1_${ik}$ nb = je - js + 1_${ik}$ loop_120: do i = p, 1, -1 is = iwork( i ) ie = iwork( i+1 ) - 1_${ik}$ mb = ie - is + 1_${ik}$ ppqq = 0_${ik}$ call stdlib${ii}$_${ri}$tgsy2( trans, ifunc, mb, nb, a( is, is ), lda,b( js, js ), & ldb, c( is, js ), ldc,d( is, is ), ldd, e( js, js ), lde,f( is, js ), ldf, & scaloc, dsum, dscale,iwork( q+2 ), ppqq, linfo ) if( linfo>0_${ik}$ )info = linfo pq = pq + ppqq if( scaloc/=one ) then do k = 1, js - 1 call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_${ri}$scal( is-1, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( is-1, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_${ri}$scal( m-ie, scaloc, c( ie+1, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m-ie, scaloc, f( ie+1, k ), 1_${ik}$ ) end do do k = je + 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', is-1, nb, mb, -one,a( 1_${ik}$, is ), lda, c( is, & js ), ldc, one,c( 1_${ik}$, js ), ldc ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', is-1, nb, mb, -one,d( 1_${ik}$, is ), ldd, c( is, & js ), ldc, one,f( 1_${ik}$, js ), ldf ) end if if( j0_${ik}$ )info = linfo if( scaloc/=one ) then do k = 1, js - 1 call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_${ri}$scal( is-1, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( is-1, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_${ri}$scal( m-ie, scaloc, c( ie+1, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m-ie, scaloc, f( ie+1, k ), 1_${ik}$ ) end do do k = je + 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! substitute r(i, j) and l(i, j) into remaining equation. if( j>p+2 ) then call stdlib${ii}$_${ri}$gemm( 'N', 'T', mb, js-1, nb, one, c( is, js ),ldc, b( 1_${ik}$, js )& , ldb, one, f( is, 1_${ik}$ ),ldf ) call stdlib${ii}$_${ri}$gemm( 'N', 'T', mb, js-1, nb, one, f( is, js ),ldf, e( 1_${ik}$, js )& , lde, one, f( is, 1_${ik}$ ),ldf ) end if if( i

= 1, CTGSYL computes a Frobenius norm-based estimate of !! Dif[(A,D),(B,E)]. That is, the reciprocal of a lower bound on the !! reciprocal of the smallest singular value of Z. !! This is a level-3 BLAS algorithm. ldf, scale, dif, work, lwork,iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob, lda, ldb, ldc, ldd, lde, ldf, lwork, m, n integer(${ik}$), intent(out) :: info real(sp), intent(out) :: dif, scale ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) complex(sp), intent(in) :: a(lda,*), b(ldb,*), d(ldd,*), e(lde,*) complex(sp), intent(inout) :: c(ldc,*), f(ldf,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! replaced various illegal calls to stdlib${ii}$_ccopy by calls to stdlib${ii}$_claset. ! sven hammarling, 1/5/02. ! Local Scalars logical(lk) :: lquery, notran integer(${ik}$) :: i, ie, ifunc, iround, is, isolve, j, je, js, k, linfo, lwmin, mb, nb, & p, pq, q real(sp) :: dscale, dsum, scale2, scaloc ! Intrinsic Functions ! Executable Statements ! decode and test input parameters info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -1_${ik}$ else if( notran ) then if( ( ijob<0_${ik}$ ) .or. ( ijob>4_${ik}$ ) ) then info = -2_${ik}$ end if end if if( info==0_${ik}$ ) then if( m<=0_${ik}$ ) then info = -3_${ik}$ else if( n<=0_${ik}$ ) then info = -4_${ik}$ else if( lda=3_${ik}$ ) then ifunc = ijob - 2_${ik}$ call stdlib${ii}$_claset( 'F', m, n, czero, czero, c, ldc ) call stdlib${ii}$_claset( 'F', m, n, czero, czero, f, ldf ) else if( ijob>=1_${ik}$ .and. notran ) then isolve = 2_${ik}$ end if end if if( ( mb<=1_${ik}$ .and. nb<=1_${ik}$ ) .or. ( mb>=m .and. nb>=n ) )then ! use unblocked level 2 solver loop_30: do iround = 1, isolve scale = one dscale = zero dsum = one pq = m*n call stdlib${ii}$_ctgsy2( trans, ifunc, m, n, a, lda, b, ldb, c, ldc, d,ldd, e, lde, f,& ldf, scale, dsum, dscale,info ) if( dscale/=zero ) then if( ijob==1_${ik}$ .or. ijob==3_${ik}$ ) then dif = sqrt( real( 2_${ik}$*m*n,KIND=sp) ) / ( dscale*sqrt( dsum ) ) else dif = sqrt( real( pq,KIND=sp) ) / ( dscale*sqrt( dsum ) ) end if end if if( isolve==2_${ik}$ .and. iround==1_${ik}$ ) then if( notran ) then ifunc = ijob end if scale2 = scale call stdlib${ii}$_clacpy( 'F', m, n, c, ldc, work, m ) call stdlib${ii}$_clacpy( 'F', m, n, f, ldf, work( m*n+1 ), m ) call stdlib${ii}$_claset( 'F', m, n, czero, czero, c, ldc ) call stdlib${ii}$_claset( 'F', m, n, czero, czero, f, ldf ) else if( isolve==2_${ik}$ .and. iround==2_${ik}$ ) then call stdlib${ii}$_clacpy( 'F', m, n, work, m, c, ldc ) call stdlib${ii}$_clacpy( 'F', m, n, work( m*n+1 ), m, f, ldf ) scale = scale2 end if end do loop_30 return end if ! determine block structure of a p = 0_${ik}$ i = 1_${ik}$ 40 continue if( i>m )go to 50 p = p + 1_${ik}$ iwork( p ) = i i = i + mb if( i>=m )go to 50 go to 40 50 continue iwork( p+1 ) = m + 1_${ik}$ if( iwork( p )==iwork( p+1 ) )p = p - 1_${ik}$ ! determine block structure of b q = p + 1_${ik}$ j = 1_${ik}$ 60 continue if( j>n )go to 70 q = q + 1_${ik}$ iwork( q ) = j j = j + nb if( j>=n )go to 70 go to 60 70 continue iwork( q+1 ) = n + 1_${ik}$ if( iwork( q )==iwork( q+1 ) )q = q - 1_${ik}$ if( notran ) then loop_150: do iround = 1, isolve ! solve (i, j) - subsystem ! a(i, i) * r(i, j) - l(i, j) * b(j, j) = c(i, j) ! d(i, i) * r(i, j) - l(i, j) * e(j, j) = f(i, j) ! for i = p, p - 1, ..., 1; j = 1, 2, ..., q pq = 0_${ik}$ scale = one dscale = zero dsum = one loop_130: do j = p + 2, q js = iwork( j ) je = iwork( j+1 ) - 1_${ik}$ nb = je - js + 1_${ik}$ loop_120: do i = p, 1, -1 is = iwork( i ) ie = iwork( i+1 ) - 1_${ik}$ mb = ie - is + 1_${ik}$ call stdlib${ii}$_ctgsy2( trans, ifunc, mb, nb, a( is, is ), lda,b( js, js ), & ldb, c( is, js ), ldc,d( is, is ), ldd, e( js, js ), lde,f( is, js ), ldf, & scaloc, dsum, dscale,linfo ) if( linfo>0_${ik}$ )info = linfo pq = pq + mb*nb if( scaloc/=one ) then do k = 1, js - 1 call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), f( 1_${ik}$, k ),1_${ik}$ ) end do do k = js, je call stdlib${ii}$_cscal( is-1, cmplx( scaloc, zero,KIND=sp),c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_cscal( is-1, cmplx( scaloc, zero,KIND=sp),f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_cscal( m-ie, cmplx( scaloc, zero,KIND=sp),c( ie+1, k ), & 1_${ik}$ ) call stdlib${ii}$_cscal( m-ie, cmplx( scaloc, zero,KIND=sp),f( ie+1, k ), & 1_${ik}$ ) end do do k = je + 1, n call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), f( 1_${ik}$, k ),1_${ik}$ ) end do scale = scale*scaloc end if ! substitute r(i,j) and l(i,j) into remaining equation. if( i>1_${ik}$ ) then call stdlib${ii}$_cgemm( 'N', 'N', is-1, nb, mb,cmplx( -one, zero,KIND=sp), a(& 1_${ik}$, is ), lda,c( is, js ), ldc, cmplx( one, zero,KIND=sp),c( 1_${ik}$, js ), & ldc ) call stdlib${ii}$_cgemm( 'N', 'N', is-1, nb, mb,cmplx( -one, zero,KIND=sp), d(& 1_${ik}$, is ), ldd,c( is, js ), ldc, cmplx( one, zero,KIND=sp),f( 1_${ik}$, js ), & ldf ) end if if( j0_${ik}$ )info = linfo if( scaloc/=one ) then do k = 1, js - 1 call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), f( 1_${ik}$, k ),1_${ik}$ ) end do do k = js, je call stdlib${ii}$_cscal( is-1, cmplx( scaloc, zero,KIND=sp), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_cscal( is-1, cmplx( scaloc, zero,KIND=sp), f( 1_${ik}$, k ),1_${ik}$ ) end do do k = js, je call stdlib${ii}$_cscal( m-ie, cmplx( scaloc, zero,KIND=sp),c( ie+1, k ), 1_${ik}$ ) call stdlib${ii}$_cscal( m-ie, cmplx( scaloc, zero,KIND=sp),f( ie+1, k ), 1_${ik}$ ) end do do k = je + 1, n call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), f( 1_${ik}$, k ),1_${ik}$ ) end do scale = scale*scaloc end if ! substitute r(i,j) and l(i,j) into remaining equation. if( j>p+2 ) then call stdlib${ii}$_cgemm( 'N', 'C', mb, js-1, nb,cmplx( one, zero,KIND=sp), c( is,& js ), ldc,b( 1_${ik}$, js ), ldb, cmplx( one, zero,KIND=sp),f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_cgemm( 'N', 'C', mb, js-1, nb,cmplx( one, zero,KIND=sp), f( is,& js ), ldf,e( 1_${ik}$, js ), lde, cmplx( one, zero,KIND=sp),f( is, 1_${ik}$ ), ldf ) end if if( i

= 1, ZTGSYL computes a Frobenius norm-based estimate of !! Dif[(A,D),(B,E)]. That is, the reciprocal of a lower bound on the !! reciprocal of the smallest singular value of Z. !! This is a level-3 BLAS algorithm. ldf, scale, dif, work, lwork,iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob, lda, ldb, ldc, ldd, lde, ldf, lwork, m, n integer(${ik}$), intent(out) :: info real(dp), intent(out) :: dif, scale ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) complex(dp), intent(in) :: a(lda,*), b(ldb,*), d(ldd,*), e(lde,*) complex(dp), intent(inout) :: c(ldc,*), f(ldf,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! replaced various illegal calls to stdlib${ii}$_ccopy by calls to stdlib${ii}$_claset. ! sven hammarling, 1/5/02. ! Local Scalars logical(lk) :: lquery, notran integer(${ik}$) :: i, ie, ifunc, iround, is, isolve, j, je, js, k, linfo, lwmin, mb, nb, & p, pq, q real(dp) :: dscale, dsum, scale2, scaloc ! Intrinsic Functions ! Executable Statements ! decode and test input parameters info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -1_${ik}$ else if( notran ) then if( ( ijob<0_${ik}$ ) .or. ( ijob>4_${ik}$ ) ) then info = -2_${ik}$ end if end if if( info==0_${ik}$ ) then if( m<=0_${ik}$ ) then info = -3_${ik}$ else if( n<=0_${ik}$ ) then info = -4_${ik}$ else if( lda=3_${ik}$ ) then ifunc = ijob - 2_${ik}$ call stdlib${ii}$_zlaset( 'F', m, n, czero, czero, c, ldc ) call stdlib${ii}$_zlaset( 'F', m, n, czero, czero, f, ldf ) else if( ijob>=1_${ik}$ .and. notran ) then isolve = 2_${ik}$ end if end if if( ( mb<=1_${ik}$ .and. nb<=1_${ik}$ ) .or. ( mb>=m .and. nb>=n ) )then ! use unblocked level 2 solver loop_30: do iround = 1, isolve scale = one dscale = zero dsum = one pq = m*n call stdlib${ii}$_ztgsy2( trans, ifunc, m, n, a, lda, b, ldb, c, ldc, d,ldd, e, lde, f,& ldf, scale, dsum, dscale,info ) if( dscale/=zero ) then if( ijob==1_${ik}$ .or. ijob==3_${ik}$ ) then dif = sqrt( real( 2_${ik}$*m*n,KIND=dp) ) / ( dscale*sqrt( dsum ) ) else dif = sqrt( real( pq,KIND=dp) ) / ( dscale*sqrt( dsum ) ) end if end if if( isolve==2_${ik}$ .and. iround==1_${ik}$ ) then if( notran ) then ifunc = ijob end if scale2 = scale call stdlib${ii}$_zlacpy( 'F', m, n, c, ldc, work, m ) call stdlib${ii}$_zlacpy( 'F', m, n, f, ldf, work( m*n+1 ), m ) call stdlib${ii}$_zlaset( 'F', m, n, czero, czero, c, ldc ) call stdlib${ii}$_zlaset( 'F', m, n, czero, czero, f, ldf ) else if( isolve==2_${ik}$ .and. iround==2_${ik}$ ) then call stdlib${ii}$_zlacpy( 'F', m, n, work, m, c, ldc ) call stdlib${ii}$_zlacpy( 'F', m, n, work( m*n+1 ), m, f, ldf ) scale = scale2 end if end do loop_30 return end if ! determine block structure of a p = 0_${ik}$ i = 1_${ik}$ 40 continue if( i>m )go to 50 p = p + 1_${ik}$ iwork( p ) = i i = i + mb if( i>=m )go to 50 go to 40 50 continue iwork( p+1 ) = m + 1_${ik}$ if( iwork( p )==iwork( p+1 ) )p = p - 1_${ik}$ ! determine block structure of b q = p + 1_${ik}$ j = 1_${ik}$ 60 continue if( j>n )go to 70 q = q + 1_${ik}$ iwork( q ) = j j = j + nb if( j>=n )go to 70 go to 60 70 continue iwork( q+1 ) = n + 1_${ik}$ if( iwork( q )==iwork( q+1 ) )q = q - 1_${ik}$ if( notran ) then loop_150: do iround = 1, isolve ! solve (i, j) - subsystem ! a(i, i) * r(i, j) - l(i, j) * b(j, j) = c(i, j) ! d(i, i) * r(i, j) - l(i, j) * e(j, j) = f(i, j) ! for i = p, p - 1, ..., 1; j = 1, 2, ..., q pq = 0_${ik}$ scale = one dscale = zero dsum = one loop_130: do j = p + 2, q js = iwork( j ) je = iwork( j+1 ) - 1_${ik}$ nb = je - js + 1_${ik}$ loop_120: do i = p, 1, -1 is = iwork( i ) ie = iwork( i+1 ) - 1_${ik}$ mb = ie - is + 1_${ik}$ call stdlib${ii}$_ztgsy2( trans, ifunc, mb, nb, a( is, is ), lda,b( js, js ), & ldb, c( is, js ), ldc,d( is, is ), ldd, e( js, js ), lde,f( is, js ), ldf, & scaloc, dsum, dscale,linfo ) if( linfo>0_${ik}$ )info = linfo pq = pq + mb*nb if( scaloc/=one ) then do k = 1, js - 1 call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp),c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp),f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_zscal( is-1, cmplx( scaloc, zero,KIND=dp),c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_zscal( is-1, cmplx( scaloc, zero,KIND=dp),f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_zscal( m-ie, cmplx( scaloc, zero,KIND=dp),c( ie+1, k ), & 1_${ik}$ ) call stdlib${ii}$_zscal( m-ie, cmplx( scaloc, zero,KIND=dp),f( ie+1, k ), & 1_${ik}$ ) end do do k = je + 1, n call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp),c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp),f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! substitute r(i,j) and l(i,j) into remaining equation. if( i>1_${ik}$ ) then call stdlib${ii}$_zgemm( 'N', 'N', is-1, nb, mb,cmplx( -one, zero,KIND=dp), a(& 1_${ik}$, is ), lda,c( is, js ), ldc, cmplx( one, zero,KIND=dp),c( 1_${ik}$, js ), & ldc ) call stdlib${ii}$_zgemm( 'N', 'N', is-1, nb, mb,cmplx( -one, zero,KIND=dp), d(& 1_${ik}$, is ), ldd,c( is, js ), ldc, cmplx( one, zero,KIND=dp),f( 1_${ik}$, js ), & ldf ) end if if( j0_${ik}$ )info = linfo if( scaloc/=one ) then do k = 1, js - 1 call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp), f( 1_${ik}$, k ),1_${ik}$ ) end do do k = js, je call stdlib${ii}$_zscal( is-1, cmplx( scaloc, zero,KIND=dp),c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_zscal( is-1, cmplx( scaloc, zero,KIND=dp),f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_zscal( m-ie, cmplx( scaloc, zero,KIND=dp),c( ie+1, k ), 1_${ik}$ ) call stdlib${ii}$_zscal( m-ie, cmplx( scaloc, zero,KIND=dp),f( ie+1, k ), 1_${ik}$ ) end do do k = je + 1, n call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp), f( 1_${ik}$, k ),1_${ik}$ ) end do scale = scale*scaloc end if ! substitute r(i,j) and l(i,j) into remaining equation. if( j>p+2 ) then call stdlib${ii}$_zgemm( 'N', 'C', mb, js-1, nb,cmplx( one, zero,KIND=dp), c( is,& js ), ldc,b( 1_${ik}$, js ), ldb, cmplx( one, zero,KIND=dp),f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_zgemm( 'N', 'C', mb, js-1, nb,cmplx( one, zero,KIND=dp), f( is,& js ), ldf,e( 1_${ik}$, js ), lde, cmplx( one, zero,KIND=dp),f( is, 1_${ik}$ ), ldf ) end if if( i

= 1, ZTGSYL computes a Frobenius norm-based estimate of !! Dif[(A,D),(B,E)]. That is, the reciprocal of a lower bound on the !! reciprocal of the smallest singular value of Z. !! This is a level-3 BLAS algorithm. ldf, scale, dif, work, lwork,iwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob, lda, ldb, ldc, ldd, lde, ldf, lwork, m, n integer(${ik}$), intent(out) :: info real(${ck}$), intent(out) :: dif, scale ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) complex(${ck}$), intent(in) :: a(lda,*), b(ldb,*), d(ldd,*), e(lde,*) complex(${ck}$), intent(inout) :: c(ldc,*), f(ldf,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! replaced various illegal calls to stdlib${ii}$_zcopy by calls to stdlib${ii}$_zlaset. ! sven hammarling, 1/5/02. ! Local Scalars logical(lk) :: lquery, notran integer(${ik}$) :: i, ie, ifunc, iround, is, isolve, j, je, js, k, linfo, lwmin, mb, nb, & p, pq, q real(${ck}$) :: dscale, dsum, scale2, scaloc ! Intrinsic Functions ! Executable Statements ! decode and test input parameters info = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) lquery = ( lwork==-1_${ik}$ ) if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -1_${ik}$ else if( notran ) then if( ( ijob<0_${ik}$ ) .or. ( ijob>4_${ik}$ ) ) then info = -2_${ik}$ end if end if if( info==0_${ik}$ ) then if( m<=0_${ik}$ ) then info = -3_${ik}$ else if( n<=0_${ik}$ ) then info = -4_${ik}$ else if( lda=3_${ik}$ ) then ifunc = ijob - 2_${ik}$ call stdlib${ii}$_${ci}$laset( 'F', m, n, czero, czero, c, ldc ) call stdlib${ii}$_${ci}$laset( 'F', m, n, czero, czero, f, ldf ) else if( ijob>=1_${ik}$ .and. notran ) then isolve = 2_${ik}$ end if end if if( ( mb<=1_${ik}$ .and. nb<=1_${ik}$ ) .or. ( mb>=m .and. nb>=n ) )then ! use unblocked level 2 solver loop_30: do iround = 1, isolve scale = one dscale = zero dsum = one pq = m*n call stdlib${ii}$_${ci}$tgsy2( trans, ifunc, m, n, a, lda, b, ldb, c, ldc, d,ldd, e, lde, f,& ldf, scale, dsum, dscale,info ) if( dscale/=zero ) then if( ijob==1_${ik}$ .or. ijob==3_${ik}$ ) then dif = sqrt( real( 2_${ik}$*m*n,KIND=${ck}$) ) / ( dscale*sqrt( dsum ) ) else dif = sqrt( real( pq,KIND=${ck}$) ) / ( dscale*sqrt( dsum ) ) end if end if if( isolve==2_${ik}$ .and. iround==1_${ik}$ ) then if( notran ) then ifunc = ijob end if scale2 = scale call stdlib${ii}$_${ci}$lacpy( 'F', m, n, c, ldc, work, m ) call stdlib${ii}$_${ci}$lacpy( 'F', m, n, f, ldf, work( m*n+1 ), m ) call stdlib${ii}$_${ci}$laset( 'F', m, n, czero, czero, c, ldc ) call stdlib${ii}$_${ci}$laset( 'F', m, n, czero, czero, f, ldf ) else if( isolve==2_${ik}$ .and. iround==2_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'F', m, n, work, m, c, ldc ) call stdlib${ii}$_${ci}$lacpy( 'F', m, n, work( m*n+1 ), m, f, ldf ) scale = scale2 end if end do loop_30 return end if ! determine block structure of a p = 0_${ik}$ i = 1_${ik}$ 40 continue if( i>m )go to 50 p = p + 1_${ik}$ iwork( p ) = i i = i + mb if( i>=m )go to 50 go to 40 50 continue iwork( p+1 ) = m + 1_${ik}$ if( iwork( p )==iwork( p+1 ) )p = p - 1_${ik}$ ! determine block structure of b q = p + 1_${ik}$ j = 1_${ik}$ 60 continue if( j>n )go to 70 q = q + 1_${ik}$ iwork( q ) = j j = j + nb if( j>=n )go to 70 go to 60 70 continue iwork( q+1 ) = n + 1_${ik}$ if( iwork( q )==iwork( q+1 ) )q = q - 1_${ik}$ if( notran ) then loop_150: do iround = 1, isolve ! solve (i, j) - subsystem ! a(i, i) * r(i, j) - l(i, j) * b(j, j) = c(i, j) ! d(i, i) * r(i, j) - l(i, j) * e(j, j) = f(i, j) ! for i = p, p - 1, ..., 1; j = 1, 2, ..., q pq = 0_${ik}$ scale = one dscale = zero dsum = one loop_130: do j = p + 2, q js = iwork( j ) je = iwork( j+1 ) - 1_${ik}$ nb = je - js + 1_${ik}$ loop_120: do i = p, 1, -1 is = iwork( i ) ie = iwork( i+1 ) - 1_${ik}$ mb = ie - is + 1_${ik}$ call stdlib${ii}$_${ci}$tgsy2( trans, ifunc, mb, nb, a( is, is ), lda,b( js, js ), & ldb, c( is, js ), ldc,d( is, is ), ldd, e( js, js ), lde,f( is, js ), ldf, & scaloc, dsum, dscale,linfo ) if( linfo>0_${ik}$ )info = linfo pq = pq + mb*nb if( scaloc/=one ) then do k = 1, js - 1 call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$),c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$),f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_${ci}$scal( is-1, cmplx( scaloc, zero,KIND=${ck}$),c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( is-1, cmplx( scaloc, zero,KIND=${ck}$),f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_${ci}$scal( m-ie, cmplx( scaloc, zero,KIND=${ck}$),c( ie+1, k ), & 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( m-ie, cmplx( scaloc, zero,KIND=${ck}$),f( ie+1, k ), & 1_${ik}$ ) end do do k = je + 1, n call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$),c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$),f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! substitute r(i,j) and l(i,j) into remaining equation. if( i>1_${ik}$ ) then call stdlib${ii}$_${ci}$gemm( 'N', 'N', is-1, nb, mb,cmplx( -one, zero,KIND=${ck}$), a(& 1_${ik}$, is ), lda,c( is, js ), ldc, cmplx( one, zero,KIND=${ck}$),c( 1_${ik}$, js ), & ldc ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', is-1, nb, mb,cmplx( -one, zero,KIND=${ck}$), d(& 1_${ik}$, is ), ldd,c( is, js ), ldc, cmplx( one, zero,KIND=${ck}$),f( 1_${ik}$, js ), & ldf ) end if if( j0_${ik}$ )info = linfo if( scaloc/=one ) then do k = 1, js - 1 call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$), f( 1_${ik}$, k ),1_${ik}$ ) end do do k = js, je call stdlib${ii}$_${ci}$scal( is-1, cmplx( scaloc, zero,KIND=${ck}$),c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( is-1, cmplx( scaloc, zero,KIND=${ck}$),f( 1_${ik}$, k ), 1_${ik}$ ) end do do k = js, je call stdlib${ii}$_${ci}$scal( m-ie, cmplx( scaloc, zero,KIND=${ck}$),c( ie+1, k ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( m-ie, cmplx( scaloc, zero,KIND=${ck}$),f( ie+1, k ), 1_${ik}$ ) end do do k = je + 1, n call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$), f( 1_${ik}$, k ),1_${ik}$ ) end do scale = scale*scaloc end if ! substitute r(i,j) and l(i,j) into remaining equation. if( j>p+2 ) then call stdlib${ii}$_${ci}$gemm( 'N', 'C', mb, js-1, nb,cmplx( one, zero,KIND=${ck}$), c( is,& js ), ldc,b( 1_${ik}$, js ), ldb, cmplx( one, zero,KIND=${ck}$),f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_${ci}$gemm( 'N', 'C', mb, js-1, nb,cmplx( one, zero,KIND=${ck}$), f( is,& js ), ldf,e( 1_${ik}$, js ), lde, cmplx( one, zero,KIND=${ck}$),f( is, 1_${ik}$ ), ldf ) end if if( i

= 1) contributes to the computation in STGSYL !! of an upper bound on the separation between to matrix pairs. Then !! the input (A, D), (B, E) are sub-pencils of the matrix pair in !! STGSYL. See STGSYL for details. ldf, scale, rdsum, rdscal,iwork, pq, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob, lda, ldb, ldc, ldd, lde, ldf, m, n integer(${ik}$), intent(out) :: info, pq real(sp), intent(inout) :: rdscal, rdsum real(sp), intent(out) :: scale ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(in) :: a(lda,*), b(ldb,*), d(ldd,*), e(lde,*) real(sp), intent(inout) :: c(ldc,*), f(ldf,*) ! ===================================================================== ! replaced various illegal calls to stdlib${ii}$_scopy by calls to stdlib${ii}$_slaset. ! sven hammarling, 27/5/02. ! Parameters integer(${ik}$), parameter :: ldz = 8_${ik}$ ! Local Scalars logical(lk) :: notran integer(${ik}$) :: i, ie, ierr, ii, is, isp1, j, je, jj, js, jsp1, k, mb, nb, p, q, & zdim real(sp) :: alpha, scaloc ! Local Arrays integer(${ik}$) :: ipiv(ldz), jpiv(ldz) real(sp) :: rhs(ldz), z(ldz,ldz) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters info = 0_${ik}$ ierr = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -1_${ik}$ else if( notran ) then if( ( ijob<0_${ik}$ ) .or. ( ijob>2_${ik}$ ) ) then info = -2_${ik}$ end if end if if( info==0_${ik}$ ) then if( m<=0_${ik}$ ) then info = -3_${ik}$ else if( n<=0_${ik}$ ) then info = -4_${ik}$ else if( ldam )go to 20 p = p + 1_${ik}$ iwork( p ) = i if( i==m )go to 20 if( a( i+1, i )/=zero ) then i = i + 2_${ik}$ else i = i + 1_${ik}$ end if go to 10 20 continue iwork( p+1 ) = m + 1_${ik}$ ! determine block structure of b q = p + 1_${ik}$ j = 1_${ik}$ 30 continue if( j>n )go to 40 q = q + 1_${ik}$ iwork( q ) = j if( j==n )go to 40 if( b( j+1, j )/=zero ) then j = j + 2_${ik}$ else j = j + 1_${ik}$ end if go to 30 40 continue iwork( q+1 ) = n + 1_${ik}$ pq = p*( q-p-1 ) if( notran ) then ! solve (i, j) - subsystem ! a(i, i) * r(i, j) - l(i, j) * b(j, j) = c(i, j) ! d(i, i) * r(i, j) - l(i, j) * e(j, j) = f(i, j) ! for i = p, p - 1, ..., 1; j = 1, 2, ..., q scale = one scaloc = one loop_120: do j = p + 2, q js = iwork( j ) jsp1 = js + 1_${ik}$ je = iwork( j+1 ) - 1_${ik}$ nb = je - js + 1_${ik}$ loop_110: do i = p, 1, -1 is = iwork( i ) isp1 = is + 1_${ik}$ ie = iwork( i+1 ) - 1_${ik}$ mb = ie - is + 1_${ik}$ zdim = mb*nb*2_${ik}$ if( ( mb==1_${ik}$ ) .and. ( nb==1_${ik}$ ) ) then ! build a 2-by-2 system z * x = rhs z( 1_${ik}$, 1_${ik}$ ) = a( is, is ) z( 2_${ik}$, 1_${ik}$ ) = d( is, is ) z( 1_${ik}$, 2_${ik}$ ) = -b( js, js ) z( 2_${ik}$, 2_${ik}$ ) = -e( js, js ) ! set up right hand side(s) rhs( 1_${ik}$ ) = c( is, js ) rhs( 2_${ik}$ ) = f( is, js ) ! solve z * x = rhs call stdlib${ii}$_sgetc2( zdim, z, ldz, ipiv, jpiv, ierr ) if( ierr>0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_sgesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_sscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_slatdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) f( is, js ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then alpha = -rhs( 1_${ik}$ ) call stdlib${ii}$_saxpy( is-1, alpha, a( 1_${ik}$, is ), 1_${ik}$, c( 1_${ik}$, js ),1_${ik}$ ) call stdlib${ii}$_saxpy( is-1, alpha, d( 1_${ik}$, is ), 1_${ik}$, f( 1_${ik}$, js ),1_${ik}$ ) end if if( j0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_sgesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_sscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_slatdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( is, jsp1 ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( is, jsp1 ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then call stdlib${ii}$_sger( is-1, nb, -one, a( 1_${ik}$, is ), 1_${ik}$, rhs( 1_${ik}$ ),1_${ik}$, c( 1_${ik}$, js ),& ldc ) call stdlib${ii}$_sger( is-1, nb, -one, d( 1_${ik}$, is ), 1_${ik}$, rhs( 1_${ik}$ ),1_${ik}$, f( 1_${ik}$, js ),& ldf ) end if if( j0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_sgesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_sscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_slatdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( isp1, js ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( isp1, js ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then call stdlib${ii}$_sgemv( 'N', is-1, mb, -one, a( 1_${ik}$, is ), lda,rhs( 1_${ik}$ ), 1_${ik}$, & one, c( 1_${ik}$, js ), 1_${ik}$ ) call stdlib${ii}$_sgemv( 'N', is-1, mb, -one, d( 1_${ik}$, is ), ldd,rhs( 1_${ik}$ ), 1_${ik}$, & one, f( 1_${ik}$, js ), 1_${ik}$ ) end if if( j0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_sgesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_sscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_slatdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) k = 1_${ik}$ ii = mb*nb + 1_${ik}$ do jj = 0, nb - 1 call stdlib${ii}$_scopy( mb, rhs( k ), 1_${ik}$, c( is, js+jj ), 1_${ik}$ ) call stdlib${ii}$_scopy( mb, rhs( ii ), 1_${ik}$, f( is, js+jj ), 1_${ik}$ ) k = k + mb ii = ii + mb end do ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then call stdlib${ii}$_sgemm( 'N', 'N', is-1, nb, mb, -one,a( 1_${ik}$, is ), lda, rhs( 1_${ik}$ & ), mb, one,c( 1_${ik}$, js ), ldc ) call stdlib${ii}$_sgemm( 'N', 'N', is-1, nb, mb, -one,d( 1_${ik}$, is ), ldd, rhs( 1_${ik}$ & ), mb, one,f( 1_${ik}$, js ), ldf ) end if if( j0_${ik}$ )info = ierr call stdlib${ii}$_sgesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_sscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) f( is, js ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then alpha = rhs( 1_${ik}$ ) call stdlib${ii}$_saxpy( js-1, alpha, b( 1_${ik}$, js ), 1_${ik}$, f( is, 1_${ik}$ ),ldf ) alpha = rhs( 2_${ik}$ ) call stdlib${ii}$_saxpy( js-1, alpha, e( 1_${ik}$, js ), 1_${ik}$, f( is, 1_${ik}$ ),ldf ) end if if( i

0_${ik}$ )info = ierr call stdlib${ii}$_sgesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_sscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( is, jsp1 ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( is, jsp1 ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then call stdlib${ii}$_saxpy( js-1, rhs( 1_${ik}$ ), b( 1_${ik}$, js ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_saxpy( js-1, rhs( 2_${ik}$ ), b( 1_${ik}$, jsp1 ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_saxpy( js-1, rhs( 3_${ik}$ ), e( 1_${ik}$, js ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_saxpy( js-1, rhs( 4_${ik}$ ), e( 1_${ik}$, jsp1 ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) end if if( i

0_${ik}$ )info = ierr call stdlib${ii}$_sgesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_sscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( isp1, js ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( isp1, js ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then call stdlib${ii}$_sger( mb, js-1, one, rhs( 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, js ),1_${ik}$, f( is, 1_${ik}$ ), & ldf ) call stdlib${ii}$_sger( mb, js-1, one, rhs( 3_${ik}$ ), 1_${ik}$, e( 1_${ik}$, js ),1_${ik}$, f( is, 1_${ik}$ ), & ldf ) end if if( i

0_${ik}$ )info = ierr call stdlib${ii}$_sgesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_sscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_sscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) k = 1_${ik}$ ii = mb*nb + 1_${ik}$ do jj = 0, nb - 1 call stdlib${ii}$_scopy( mb, rhs( k ), 1_${ik}$, c( is, js+jj ), 1_${ik}$ ) call stdlib${ii}$_scopy( mb, rhs( ii ), 1_${ik}$, f( is, js+jj ), 1_${ik}$ ) k = k + mb ii = ii + mb end do ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then call stdlib${ii}$_sgemm( 'N', 'T', mb, js-1, nb, one,c( is, js ), ldc, b( 1_${ik}$, & js ), ldb, one,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_sgemm( 'N', 'T', mb, js-1, nb, one,f( is, js ), ldf, e( 1_${ik}$, & js ), lde, one,f( is, 1_${ik}$ ), ldf ) end if if( i

= 1) contributes to the computation in DTGSYL !! of an upper bound on the separation between to matrix pairs. Then !! the input (A, D), (B, E) are sub-pencils of the matrix pair in !! DTGSYL. See DTGSYL for details. ldf, scale, rdsum, rdscal,iwork, pq, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob, lda, ldb, ldc, ldd, lde, ldf, m, n integer(${ik}$), intent(out) :: info, pq real(dp), intent(inout) :: rdscal, rdsum real(dp), intent(out) :: scale ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(in) :: a(lda,*), b(ldb,*), d(ldd,*), e(lde,*) real(dp), intent(inout) :: c(ldc,*), f(ldf,*) ! ===================================================================== ! replaced various illegal calls to stdlib${ii}$_dcopy by calls to stdlib${ii}$_dlaset. ! sven hammarling, 27/5/02. ! Parameters integer(${ik}$), parameter :: ldz = 8_${ik}$ ! Local Scalars logical(lk) :: notran integer(${ik}$) :: i, ie, ierr, ii, is, isp1, j, je, jj, js, jsp1, k, mb, nb, p, q, & zdim real(dp) :: alpha, scaloc ! Local Arrays integer(${ik}$) :: ipiv(ldz), jpiv(ldz) real(dp) :: rhs(ldz), z(ldz,ldz) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters info = 0_${ik}$ ierr = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -1_${ik}$ else if( notran ) then if( ( ijob<0_${ik}$ ) .or. ( ijob>2_${ik}$ ) ) then info = -2_${ik}$ end if end if if( info==0_${ik}$ ) then if( m<=0_${ik}$ ) then info = -3_${ik}$ else if( n<=0_${ik}$ ) then info = -4_${ik}$ else if( ldam )go to 20 p = p + 1_${ik}$ iwork( p ) = i if( i==m )go to 20 if( a( i+1, i )/=zero ) then i = i + 2_${ik}$ else i = i + 1_${ik}$ end if go to 10 20 continue iwork( p+1 ) = m + 1_${ik}$ ! determine block structure of b q = p + 1_${ik}$ j = 1_${ik}$ 30 continue if( j>n )go to 40 q = q + 1_${ik}$ iwork( q ) = j if( j==n )go to 40 if( b( j+1, j )/=zero ) then j = j + 2_${ik}$ else j = j + 1_${ik}$ end if go to 30 40 continue iwork( q+1 ) = n + 1_${ik}$ pq = p*( q-p-1 ) if( notran ) then ! solve (i, j) - subsystem ! a(i, i) * r(i, j) - l(i, j) * b(j, j) = c(i, j) ! d(i, i) * r(i, j) - l(i, j) * e(j, j) = f(i, j) ! for i = p, p - 1, ..., 1; j = 1, 2, ..., q scale = one scaloc = one loop_120: do j = p + 2, q js = iwork( j ) jsp1 = js + 1_${ik}$ je = iwork( j+1 ) - 1_${ik}$ nb = je - js + 1_${ik}$ loop_110: do i = p, 1, -1 is = iwork( i ) isp1 = is + 1_${ik}$ ie = iwork( i+1 ) - 1_${ik}$ mb = ie - is + 1_${ik}$ zdim = mb*nb*2_${ik}$ if( ( mb==1_${ik}$ ) .and. ( nb==1_${ik}$ ) ) then ! build a 2-by-2 system z * x = rhs z( 1_${ik}$, 1_${ik}$ ) = a( is, is ) z( 2_${ik}$, 1_${ik}$ ) = d( is, is ) z( 1_${ik}$, 2_${ik}$ ) = -b( js, js ) z( 2_${ik}$, 2_${ik}$ ) = -e( js, js ) ! set up right hand side(s) rhs( 1_${ik}$ ) = c( is, js ) rhs( 2_${ik}$ ) = f( is, js ) ! solve z * x = rhs call stdlib${ii}$_dgetc2( zdim, z, ldz, ipiv, jpiv, ierr ) if( ierr>0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_dgesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_dlatdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) f( is, js ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then alpha = -rhs( 1_${ik}$ ) call stdlib${ii}$_daxpy( is-1, alpha, a( 1_${ik}$, is ), 1_${ik}$, c( 1_${ik}$, js ),1_${ik}$ ) call stdlib${ii}$_daxpy( is-1, alpha, d( 1_${ik}$, is ), 1_${ik}$, f( 1_${ik}$, js ),1_${ik}$ ) end if if( j0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_dgesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_dlatdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( is, jsp1 ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( is, jsp1 ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then call stdlib${ii}$_dger( is-1, nb, -one, a( 1_${ik}$, is ), 1_${ik}$, rhs( 1_${ik}$ ),1_${ik}$, c( 1_${ik}$, js ),& ldc ) call stdlib${ii}$_dger( is-1, nb, -one, d( 1_${ik}$, is ), 1_${ik}$, rhs( 1_${ik}$ ),1_${ik}$, f( 1_${ik}$, js ),& ldf ) end if if( j0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_dgesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_dlatdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( isp1, js ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( isp1, js ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then call stdlib${ii}$_dgemv( 'N', is-1, mb, -one, a( 1_${ik}$, is ), lda,rhs( 1_${ik}$ ), 1_${ik}$, & one, c( 1_${ik}$, js ), 1_${ik}$ ) call stdlib${ii}$_dgemv( 'N', is-1, mb, -one, d( 1_${ik}$, is ), ldd,rhs( 1_${ik}$ ), 1_${ik}$, & one, f( 1_${ik}$, js ), 1_${ik}$ ) end if if( j0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_dgesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_dlatdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) k = 1_${ik}$ ii = mb*nb + 1_${ik}$ do jj = 0, nb - 1 call stdlib${ii}$_dcopy( mb, rhs( k ), 1_${ik}$, c( is, js+jj ), 1_${ik}$ ) call stdlib${ii}$_dcopy( mb, rhs( ii ), 1_${ik}$, f( is, js+jj ), 1_${ik}$ ) k = k + mb ii = ii + mb end do ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then call stdlib${ii}$_dgemm( 'N', 'N', is-1, nb, mb, -one,a( 1_${ik}$, is ), lda, rhs( 1_${ik}$ & ), mb, one,c( 1_${ik}$, js ), ldc ) call stdlib${ii}$_dgemm( 'N', 'N', is-1, nb, mb, -one,d( 1_${ik}$, is ), ldd, rhs( 1_${ik}$ & ), mb, one,f( 1_${ik}$, js ), ldf ) end if if( j0_${ik}$ )info = ierr call stdlib${ii}$_dgesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) f( is, js ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then alpha = rhs( 1_${ik}$ ) call stdlib${ii}$_daxpy( js-1, alpha, b( 1_${ik}$, js ), 1_${ik}$, f( is, 1_${ik}$ ),ldf ) alpha = rhs( 2_${ik}$ ) call stdlib${ii}$_daxpy( js-1, alpha, e( 1_${ik}$, js ), 1_${ik}$, f( is, 1_${ik}$ ),ldf ) end if if( i

0_${ik}$ )info = ierr call stdlib${ii}$_dgesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( is, jsp1 ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( is, jsp1 ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then call stdlib${ii}$_daxpy( js-1, rhs( 1_${ik}$ ), b( 1_${ik}$, js ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_daxpy( js-1, rhs( 2_${ik}$ ), b( 1_${ik}$, jsp1 ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_daxpy( js-1, rhs( 3_${ik}$ ), e( 1_${ik}$, js ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_daxpy( js-1, rhs( 4_${ik}$ ), e( 1_${ik}$, jsp1 ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) end if if( i

0_${ik}$ )info = ierr call stdlib${ii}$_dgesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( isp1, js ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( isp1, js ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then call stdlib${ii}$_dger( mb, js-1, one, rhs( 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, js ),1_${ik}$, f( is, 1_${ik}$ ), & ldf ) call stdlib${ii}$_dger( mb, js-1, one, rhs( 3_${ik}$ ), 1_${ik}$, e( 1_${ik}$, js ),1_${ik}$, f( is, 1_${ik}$ ), & ldf ) end if if( i

0_${ik}$ )info = ierr call stdlib${ii}$_dgesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_dscal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_dscal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) k = 1_${ik}$ ii = mb*nb + 1_${ik}$ do jj = 0, nb - 1 call stdlib${ii}$_dcopy( mb, rhs( k ), 1_${ik}$, c( is, js+jj ), 1_${ik}$ ) call stdlib${ii}$_dcopy( mb, rhs( ii ), 1_${ik}$, f( is, js+jj ), 1_${ik}$ ) k = k + mb ii = ii + mb end do ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then call stdlib${ii}$_dgemm( 'N', 'T', mb, js-1, nb, one,c( is, js ), ldc, b( 1_${ik}$, & js ), ldb, one,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_dgemm( 'N', 'T', mb, js-1, nb, one,f( is, js ), ldf, e( 1_${ik}$, & js ), lde, one,f( is, 1_${ik}$ ), ldf ) end if if( i

= 1) contributes to the computation in DTGSYL !! of an upper bound on the separation between to matrix pairs. Then !! the input (A, D), (B, E) are sub-pencils of the matrix pair in !! DTGSYL. See DTGSYL for details. ldf, scale, rdsum, rdscal,iwork, pq, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob, lda, ldb, ldc, ldd, lde, ldf, m, n integer(${ik}$), intent(out) :: info, pq real(${rk}$), intent(inout) :: rdscal, rdsum real(${rk}$), intent(out) :: scale ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(in) :: a(lda,*), b(ldb,*), d(ldd,*), e(lde,*) real(${rk}$), intent(inout) :: c(ldc,*), f(ldf,*) ! ===================================================================== ! replaced various illegal calls to stdlib${ii}$_${ri}$copy by calls to stdlib${ii}$_${ri}$laset. ! sven hammarling, 27/5/02. ! Parameters integer(${ik}$), parameter :: ldz = 8_${ik}$ ! Local Scalars logical(lk) :: notran integer(${ik}$) :: i, ie, ierr, ii, is, isp1, j, je, jj, js, jsp1, k, mb, nb, p, q, & zdim real(${rk}$) :: alpha, scaloc ! Local Arrays integer(${ik}$) :: ipiv(ldz), jpiv(ldz) real(${rk}$) :: rhs(ldz), z(ldz,ldz) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters info = 0_${ik}$ ierr = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'T' ) ) then info = -1_${ik}$ else if( notran ) then if( ( ijob<0_${ik}$ ) .or. ( ijob>2_${ik}$ ) ) then info = -2_${ik}$ end if end if if( info==0_${ik}$ ) then if( m<=0_${ik}$ ) then info = -3_${ik}$ else if( n<=0_${ik}$ ) then info = -4_${ik}$ else if( ldam )go to 20 p = p + 1_${ik}$ iwork( p ) = i if( i==m )go to 20 if( a( i+1, i )/=zero ) then i = i + 2_${ik}$ else i = i + 1_${ik}$ end if go to 10 20 continue iwork( p+1 ) = m + 1_${ik}$ ! determine block structure of b q = p + 1_${ik}$ j = 1_${ik}$ 30 continue if( j>n )go to 40 q = q + 1_${ik}$ iwork( q ) = j if( j==n )go to 40 if( b( j+1, j )/=zero ) then j = j + 2_${ik}$ else j = j + 1_${ik}$ end if go to 30 40 continue iwork( q+1 ) = n + 1_${ik}$ pq = p*( q-p-1 ) if( notran ) then ! solve (i, j) - subsystem ! a(i, i) * r(i, j) - l(i, j) * b(j, j) = c(i, j) ! d(i, i) * r(i, j) - l(i, j) * e(j, j) = f(i, j) ! for i = p, p - 1, ..., 1; j = 1, 2, ..., q scale = one scaloc = one loop_120: do j = p + 2, q js = iwork( j ) jsp1 = js + 1_${ik}$ je = iwork( j+1 ) - 1_${ik}$ nb = je - js + 1_${ik}$ loop_110: do i = p, 1, -1 is = iwork( i ) isp1 = is + 1_${ik}$ ie = iwork( i+1 ) - 1_${ik}$ mb = ie - is + 1_${ik}$ zdim = mb*nb*2_${ik}$ if( ( mb==1_${ik}$ ) .and. ( nb==1_${ik}$ ) ) then ! build a 2-by-2 system z * x = rhs z( 1_${ik}$, 1_${ik}$ ) = a( is, is ) z( 2_${ik}$, 1_${ik}$ ) = d( is, is ) z( 1_${ik}$, 2_${ik}$ ) = -b( js, js ) z( 2_${ik}$, 2_${ik}$ ) = -e( js, js ) ! set up right hand side(s) rhs( 1_${ik}$ ) = c( is, js ) rhs( 2_${ik}$ ) = f( is, js ) ! solve z * x = rhs call stdlib${ii}$_${ri}$getc2( zdim, z, ldz, ipiv, jpiv, ierr ) if( ierr>0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_${ri}$gesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_${ri}$latdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) f( is, js ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then alpha = -rhs( 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( is-1, alpha, a( 1_${ik}$, is ), 1_${ik}$, c( 1_${ik}$, js ),1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( is-1, alpha, d( 1_${ik}$, is ), 1_${ik}$, f( 1_${ik}$, js ),1_${ik}$ ) end if if( j0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_${ri}$gesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_${ri}$latdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( is, jsp1 ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( is, jsp1 ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then call stdlib${ii}$_${ri}$ger( is-1, nb, -one, a( 1_${ik}$, is ), 1_${ik}$, rhs( 1_${ik}$ ),1_${ik}$, c( 1_${ik}$, js ),& ldc ) call stdlib${ii}$_${ri}$ger( is-1, nb, -one, d( 1_${ik}$, is ), 1_${ik}$, rhs( 1_${ik}$ ),1_${ik}$, f( 1_${ik}$, js ),& ldf ) end if if( j0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_${ri}$gesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_${ri}$latdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( isp1, js ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( isp1, js ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then call stdlib${ii}$_${ri}$gemv( 'N', is-1, mb, -one, a( 1_${ik}$, is ), lda,rhs( 1_${ik}$ ), 1_${ik}$, & one, c( 1_${ik}$, js ), 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'N', is-1, mb, -one, d( 1_${ik}$, is ), ldd,rhs( 1_${ik}$ ), 1_${ik}$, & one, f( 1_${ik}$, js ), 1_${ik}$ ) end if if( j0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_${ri}$gesc2( zdim, z, ldz, rhs, ipiv, jpiv,scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_${ri}$latdf( ijob, zdim, z, ldz, rhs, rdsum,rdscal, ipiv, jpiv ) end if ! unpack solution vector(s) k = 1_${ik}$ ii = mb*nb + 1_${ik}$ do jj = 0, nb - 1 call stdlib${ii}$_${ri}$copy( mb, rhs( k ), 1_${ik}$, c( is, js+jj ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( mb, rhs( ii ), 1_${ik}$, f( is, js+jj ), 1_${ik}$ ) k = k + mb ii = ii + mb end do ! substitute r(i, j) and l(i, j) into remaining ! equation. if( i>1_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', is-1, nb, mb, -one,a( 1_${ik}$, is ), lda, rhs( 1_${ik}$ & ), mb, one,c( 1_${ik}$, js ), ldc ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', is-1, nb, mb, -one,d( 1_${ik}$, is ), ldd, rhs( 1_${ik}$ & ), mb, one,f( 1_${ik}$, js ), ldf ) end if if( j0_${ik}$ )info = ierr call stdlib${ii}$_${ri}$gesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) f( is, js ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then alpha = rhs( 1_${ik}$ ) call stdlib${ii}$_${ri}$axpy( js-1, alpha, b( 1_${ik}$, js ), 1_${ik}$, f( is, 1_${ik}$ ),ldf ) alpha = rhs( 2_${ik}$ ) call stdlib${ii}$_${ri}$axpy( js-1, alpha, e( 1_${ik}$, js ), 1_${ik}$, f( is, 1_${ik}$ ),ldf ) end if if( i

0_${ik}$ )info = ierr call stdlib${ii}$_${ri}$gesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( is, jsp1 ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( is, jsp1 ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then call stdlib${ii}$_${ri}$axpy( js-1, rhs( 1_${ik}$ ), b( 1_${ik}$, js ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_${ri}$axpy( js-1, rhs( 2_${ik}$ ), b( 1_${ik}$, jsp1 ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_${ri}$axpy( js-1, rhs( 3_${ik}$ ), e( 1_${ik}$, js ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_${ri}$axpy( js-1, rhs( 4_${ik}$ ), e( 1_${ik}$, jsp1 ), 1_${ik}$,f( is, 1_${ik}$ ), ldf ) end if if( i

0_${ik}$ )info = ierr call stdlib${ii}$_${ri}$gesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( is, js ) = rhs( 1_${ik}$ ) c( isp1, js ) = rhs( 2_${ik}$ ) f( is, js ) = rhs( 3_${ik}$ ) f( isp1, js ) = rhs( 4_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then call stdlib${ii}$_${ri}$ger( mb, js-1, one, rhs( 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, js ),1_${ik}$, f( is, 1_${ik}$ ), & ldf ) call stdlib${ii}$_${ri}$ger( mb, js-1, one, rhs( 3_${ik}$ ), 1_${ik}$, e( 1_${ik}$, js ),1_${ik}$, f( is, 1_${ik}$ ), & ldf ) end if if( i

0_${ik}$ )info = ierr call stdlib${ii}$_${ri}$gesc2( zdim, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_${ri}$scal( m, scaloc, c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( m, scaloc, f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) k = 1_${ik}$ ii = mb*nb + 1_${ik}$ do jj = 0, nb - 1 call stdlib${ii}$_${ri}$copy( mb, rhs( k ), 1_${ik}$, c( is, js+jj ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( mb, rhs( ii ), 1_${ik}$, f( is, js+jj ), 1_${ik}$ ) k = k + mb ii = ii + mb end do ! substitute r(i, j) and l(i, j) into remaining ! equation. if( j>p+2 ) then call stdlib${ii}$_${ri}$gemm( 'N', 'T', mb, js-1, nb, one,c( is, js ), ldc, b( 1_${ik}$, & js ), ldb, one,f( is, 1_${ik}$ ), ldf ) call stdlib${ii}$_${ri}$gemm( 'N', 'T', mb, js-1, nb, one,f( is, js ), ldf, e( 1_${ik}$, & js ), lde, one,f( is, 1_${ik}$ ), ldf ) end if if( i

= 1) contributes to the computation in CTGSYL !! of an upper bound on the separation between to matrix pairs. Then !! the input (A, D), (B, E) are sub-pencils of two matrix pairs in !! CTGSYL. ldf, scale, rdsum, rdscal,info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob, lda, ldb, ldc, ldd, lde, ldf, m, n integer(${ik}$), intent(out) :: info real(sp), intent(inout) :: rdscal, rdsum real(sp), intent(out) :: scale ! Array Arguments complex(sp), intent(in) :: a(lda,*), b(ldb,*), d(ldd,*), e(lde,*) complex(sp), intent(inout) :: c(ldc,*), f(ldf,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: ldz = 2_${ik}$ ! Local Scalars logical(lk) :: notran integer(${ik}$) :: i, ierr, j, k real(sp) :: scaloc complex(sp) :: alpha ! Local Arrays integer(${ik}$) :: ipiv(ldz), jpiv(ldz) complex(sp) :: rhs(ldz), z(ldz,ldz) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters info = 0_${ik}$ ierr = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -1_${ik}$ else if( notran ) then if( ( ijob<0_${ik}$ ) .or. ( ijob>2_${ik}$ ) ) then info = -2_${ik}$ end if end if if( info==0_${ik}$ ) then if( m<=0_${ik}$ ) then info = -3_${ik}$ else if( n<=0_${ik}$ ) then info = -4_${ik}$ else if( lda0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_cgesc2( ldz, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), f( 1_${ik}$, k ),1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_clatdf( ijob, ldz, z, ldz, rhs, rdsum, rdscal,ipiv, jpiv ) end if ! unpack solution vector(s) c( i, j ) = rhs( 1_${ik}$ ) f( i, j ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining equation. if( i>1_${ik}$ ) then alpha = -rhs( 1_${ik}$ ) call stdlib${ii}$_caxpy( i-1, alpha, a( 1_${ik}$, i ), 1_${ik}$, c( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_caxpy( i-1, alpha, d( 1_${ik}$, i ), 1_${ik}$, f( 1_${ik}$, j ), 1_${ik}$ ) end if if( j0_${ik}$ )info = ierr call stdlib${ii}$_cgesc2( ldz, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_cscal( m, cmplx( scaloc, zero,KIND=sp), f( 1_${ik}$, k ),1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( i, j ) = rhs( 1_${ik}$ ) f( i, j ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining equation. do k = 1, j - 1 f( i, k ) = f( i, k ) + rhs( 1_${ik}$ )*conjg( b( k, j ) ) +rhs( 2_${ik}$ )*conjg( e( k, & j ) ) end do do k = i + 1, m c( k, j ) = c( k, j ) - conjg( a( i, k ) )*rhs( 1_${ik}$ ) -conjg( d( i, k ) )& *rhs( 2_${ik}$ ) end do end do loop_70 end do loop_80 end if return end subroutine stdlib${ii}$_ctgsy2 pure module subroutine stdlib${ii}$_ztgsy2( trans, ijob, m, n, a, lda, b, ldb, c, ldc, d,ldd, e, lde, f, & !! ZTGSY2 solves the generalized Sylvester equation !! A * R - L * B = scale * C (1) !! D * R - L * E = scale * F !! using Level 1 and 2 BLAS, where R and L are unknown M-by-N matrices, !! (A, D), (B, E) and (C, F) are given matrix pairs of size M-by-M, !! N-by-N and M-by-N, respectively. A, B, D and E are upper triangular !! (i.e., (A,D) and (B,E) in generalized Schur form). !! The solution (R, L) overwrites (C, F). 0 <= SCALE <= 1 is an output !! scaling factor chosen to avoid overflow. !! In matrix notation solving equation (1) corresponds to solve !! Zx = scale * b, where Z is defined as !! Z = [ kron(In, A) -kron(B**H, Im) ] (2) !! [ kron(In, D) -kron(E**H, Im) ], !! Ik is the identity matrix of size k and X**H is the conjuguate transpose of X. !! kron(X, Y) is the Kronecker product between the matrices X and Y. !! If TRANS = 'C', y in the conjugate transposed system Z**H*y = scale*b !! is solved for, which is equivalent to solve for R and L in !! A**H * R + D**H * L = scale * C (3) !! R * B**H + L * E**H = scale * -F !! This case is used to compute an estimate of Dif[(A, D), (B, E)] = !! = sigma_min(Z) using reverse communication with ZLACON. !! ZTGSY2 also (IJOB >= 1) contributes to the computation in ZTGSYL !! of an upper bound on the separation between to matrix pairs. Then !! the input (A, D), (B, E) are sub-pencils of two matrix pairs in !! ZTGSYL. ldf, scale, rdsum, rdscal,info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob, lda, ldb, ldc, ldd, lde, ldf, m, n integer(${ik}$), intent(out) :: info real(dp), intent(inout) :: rdscal, rdsum real(dp), intent(out) :: scale ! Array Arguments complex(dp), intent(in) :: a(lda,*), b(ldb,*), d(ldd,*), e(lde,*) complex(dp), intent(inout) :: c(ldc,*), f(ldf,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: ldz = 2_${ik}$ ! Local Scalars logical(lk) :: notran integer(${ik}$) :: i, ierr, j, k real(dp) :: scaloc complex(dp) :: alpha ! Local Arrays integer(${ik}$) :: ipiv(ldz), jpiv(ldz) complex(dp) :: rhs(ldz), z(ldz,ldz) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters info = 0_${ik}$ ierr = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -1_${ik}$ else if( notran ) then if( ( ijob<0_${ik}$ ) .or. ( ijob>2_${ik}$ ) ) then info = -2_${ik}$ end if end if if( info==0_${ik}$ ) then if( m<=0_${ik}$ ) then info = -3_${ik}$ else if( n<=0_${ik}$ ) then info = -4_${ik}$ else if( lda0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_zgesc2( ldz, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp),c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp),f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_zlatdf( ijob, ldz, z, ldz, rhs, rdsum, rdscal,ipiv, jpiv ) end if ! unpack solution vector(s) c( i, j ) = rhs( 1_${ik}$ ) f( i, j ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining equation. if( i>1_${ik}$ ) then alpha = -rhs( 1_${ik}$ ) call stdlib${ii}$_zaxpy( i-1, alpha, a( 1_${ik}$, i ), 1_${ik}$, c( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_zaxpy( i-1, alpha, d( 1_${ik}$, i ), 1_${ik}$, f( 1_${ik}$, j ), 1_${ik}$ ) end if if( j0_${ik}$ )info = ierr call stdlib${ii}$_zgesc2( ldz, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_zscal( m, cmplx( scaloc, zero,KIND=dp), f( 1_${ik}$, k ),1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( i, j ) = rhs( 1_${ik}$ ) f( i, j ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining equation. do k = 1, j - 1 f( i, k ) = f( i, k ) + rhs( 1_${ik}$ )*conjg( b( k, j ) ) +rhs( 2_${ik}$ )*conjg( e( k, & j ) ) end do do k = i + 1, m c( k, j ) = c( k, j ) - conjg( a( i, k ) )*rhs( 1_${ik}$ ) -conjg( d( i, k ) )& *rhs( 2_${ik}$ ) end do end do loop_70 end do loop_80 end if return end subroutine stdlib${ii}$_ztgsy2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tgsy2( trans, ijob, m, n, a, lda, b, ldb, c, ldc, d,ldd, e, lde, f, & !! ZTGSY2: solves the generalized Sylvester equation !! A * R - L * B = scale * C (1) !! D * R - L * E = scale * F !! using Level 1 and 2 BLAS, where R and L are unknown M-by-N matrices, !! (A, D), (B, E) and (C, F) are given matrix pairs of size M-by-M, !! N-by-N and M-by-N, respectively. A, B, D and E are upper triangular !! (i.e., (A,D) and (B,E) in generalized Schur form). !! The solution (R, L) overwrites (C, F). 0 <= SCALE <= 1 is an output !! scaling factor chosen to avoid overflow. !! In matrix notation solving equation (1) corresponds to solve !! Zx = scale * b, where Z is defined as !! Z = [ kron(In, A) -kron(B**H, Im) ] (2) !! [ kron(In, D) -kron(E**H, Im) ], !! Ik is the identity matrix of size k and X**H is the conjuguate transpose of X. !! kron(X, Y) is the Kronecker product between the matrices X and Y. !! If TRANS = 'C', y in the conjugate transposed system Z**H*y = scale*b !! is solved for, which is equivalent to solve for R and L in !! A**H * R + D**H * L = scale * C (3) !! R * B**H + L * E**H = scale * -F !! This case is used to compute an estimate of Dif[(A, D), (B, E)] = !! = sigma_min(Z) using reverse communication with ZLACON. !! ZTGSY2 also (IJOB >= 1) contributes to the computation in ZTGSYL !! of an upper bound on the separation between to matrix pairs. Then !! the input (A, D), (B, E) are sub-pencils of two matrix pairs in !! ZTGSYL. ldf, scale, rdsum, rdscal,info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: trans integer(${ik}$), intent(in) :: ijob, lda, ldb, ldc, ldd, lde, ldf, m, n integer(${ik}$), intent(out) :: info real(${ck}$), intent(inout) :: rdscal, rdsum real(${ck}$), intent(out) :: scale ! Array Arguments complex(${ck}$), intent(in) :: a(lda,*), b(ldb,*), d(ldd,*), e(lde,*) complex(${ck}$), intent(inout) :: c(ldc,*), f(ldf,*) ! ===================================================================== ! Parameters integer(${ik}$), parameter :: ldz = 2_${ik}$ ! Local Scalars logical(lk) :: notran integer(${ik}$) :: i, ierr, j, k real(${ck}$) :: scaloc complex(${ck}$) :: alpha ! Local Arrays integer(${ik}$) :: ipiv(ldz), jpiv(ldz) complex(${ck}$) :: rhs(ldz), z(ldz,ldz) ! Intrinsic Functions ! Executable Statements ! decode and test input parameters info = 0_${ik}$ ierr = 0_${ik}$ notran = stdlib_lsame( trans, 'N' ) if( .not.notran .and. .not.stdlib_lsame( trans, 'C' ) ) then info = -1_${ik}$ else if( notran ) then if( ( ijob<0_${ik}$ ) .or. ( ijob>2_${ik}$ ) ) then info = -2_${ik}$ end if end if if( info==0_${ik}$ ) then if( m<=0_${ik}$ ) then info = -3_${ik}$ else if( n<=0_${ik}$ ) then info = -4_${ik}$ else if( lda0_${ik}$ )info = ierr if( ijob==0_${ik}$ ) then call stdlib${ii}$_${ci}$gesc2( ldz, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$),c( 1_${ik}$, k ), 1_${ik}$ ) call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$),f( 1_${ik}$, k ), 1_${ik}$ ) end do scale = scale*scaloc end if else call stdlib${ii}$_${ci}$latdf( ijob, ldz, z, ldz, rhs, rdsum, rdscal,ipiv, jpiv ) end if ! unpack solution vector(s) c( i, j ) = rhs( 1_${ik}$ ) f( i, j ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining equation. if( i>1_${ik}$ ) then alpha = -rhs( 1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( i-1, alpha, a( 1_${ik}$, i ), 1_${ik}$, c( 1_${ik}$, j ), 1_${ik}$ ) call stdlib${ii}$_${ci}$axpy( i-1, alpha, d( 1_${ik}$, i ), 1_${ik}$, f( 1_${ik}$, j ), 1_${ik}$ ) end if if( j0_${ik}$ )info = ierr call stdlib${ii}$_${ci}$gesc2( ldz, z, ldz, rhs, ipiv, jpiv, scaloc ) if( scaloc/=one ) then do k = 1, n call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$), c( 1_${ik}$, k ),1_${ik}$ ) call stdlib${ii}$_${ci}$scal( m, cmplx( scaloc, zero,KIND=${ck}$), f( 1_${ik}$, k ),1_${ik}$ ) end do scale = scale*scaloc end if ! unpack solution vector(s) c( i, j ) = rhs( 1_${ik}$ ) f( i, j ) = rhs( 2_${ik}$ ) ! substitute r(i, j) and l(i, j) into remaining equation. do k = 1, j - 1 f( i, k ) = f( i, k ) + rhs( 1_${ik}$ )*conjg( b( k, j ) ) +rhs( 2_${ik}$ )*conjg( e( k, & j ) ) end do do k = i + 1, m c( k, j ) = c( k, j ) - conjg( a( i, k ) )*rhs( 1_${ik}$ ) -conjg( d( i, k ) )& *rhs( 2_${ik}$ ) end do end do loop_70 end do loop_80 end if return end subroutine stdlib${ii}$_${ci}$tgsy2 #:endif #:endfor pure module subroutine stdlib${ii}$_slagv2( a, lda, b, ldb, alphar, alphai, beta, csl, snl,csr, snr ) !! SLAGV2 computes the Generalized Schur factorization of a real 2-by-2 !! matrix pencil (A,B) where B is upper triangular. This routine !! computes orthogonal (rotation) matrices given by CSL, SNL and CSR, !! SNR such that !! 1) if the pencil (A,B) has two real eigenvalues (include 0/0 or 1/0 !! types), then !! [ a11 a12 ] := [ CSL SNL ] [ a11 a12 ] [ CSR -SNR ] !! [ 0 a22 ] [ -SNL CSL ] [ a21 a22 ] [ SNR CSR ] !! [ b11 b12 ] := [ CSL SNL ] [ b11 b12 ] [ CSR -SNR ] !! [ 0 b22 ] [ -SNL CSL ] [ 0 b22 ] [ SNR CSR ], !! 2) if the pencil (A,B) has a pair of complex conjugate eigenvalues, !! then !! [ a11 a12 ] := [ CSL SNL ] [ a11 a12 ] [ CSR -SNR ] !! [ a21 a22 ] [ -SNL CSL ] [ a21 a22 ] [ SNR CSR ] !! [ b11 0 ] := [ CSL SNL ] [ b11 b12 ] [ CSR -SNR ] !! [ 0 b22 ] [ -SNL CSL ] [ 0 b22 ] [ SNR CSR ] !! where b11 >= b22 > 0. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldb real(sp), intent(out) :: csl, csr, snl, snr ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: alphai(2_${ik}$), alphar(2_${ik}$), beta(2_${ik}$) ! ===================================================================== ! Local Scalars real(sp) :: anorm, ascale, bnorm, bscale, h1, h2, h3, qq, r, rr, safmin, scale1, & scale2, t, ulp, wi, wr1, wr2 ! Intrinsic Functions ! Executable Statements safmin = stdlib${ii}$_slamch( 'S' ) ulp = stdlib${ii}$_slamch( 'P' ) ! scale a anorm = max( abs( a( 1_${ik}$, 1_${ik}$ ) )+abs( a( 2_${ik}$, 1_${ik}$ ) ),abs( a( 1_${ik}$, 2_${ik}$ ) )+abs( a( 2_${ik}$, 2_${ik}$ ) ), & safmin ) ascale = one / anorm a( 1_${ik}$, 1_${ik}$ ) = ascale*a( 1_${ik}$, 1_${ik}$ ) a( 1_${ik}$, 2_${ik}$ ) = ascale*a( 1_${ik}$, 2_${ik}$ ) a( 2_${ik}$, 1_${ik}$ ) = ascale*a( 2_${ik}$, 1_${ik}$ ) a( 2_${ik}$, 2_${ik}$ ) = ascale*a( 2_${ik}$, 2_${ik}$ ) ! scale b bnorm = max( abs( b( 1_${ik}$, 1_${ik}$ ) ), abs( b( 1_${ik}$, 2_${ik}$ ) )+abs( b( 2_${ik}$, 2_${ik}$ ) ),safmin ) bscale = one / bnorm b( 1_${ik}$, 1_${ik}$ ) = bscale*b( 1_${ik}$, 1_${ik}$ ) b( 1_${ik}$, 2_${ik}$ ) = bscale*b( 1_${ik}$, 2_${ik}$ ) b( 2_${ik}$, 2_${ik}$ ) = bscale*b( 2_${ik}$, 2_${ik}$ ) ! check if a can be deflated if( abs( a( 2_${ik}$, 1_${ik}$ ) )<=ulp ) then csl = one snl = zero csr = one snr = zero a( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero wi = zero ! check if b is singular else if( abs( b( 1_${ik}$, 1_${ik}$ ) )<=ulp ) then call stdlib${ii}$_slartg( a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), csl, snl, r ) csr = one snr = zero call stdlib${ii}$_srot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), lda, a( 2_${ik}$, 1_${ik}$ ), lda, csl, snl ) call stdlib${ii}$_srot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), ldb, b( 2_${ik}$, 1_${ik}$ ), ldb, csl, snl ) a( 2_${ik}$, 1_${ik}$ ) = zero b( 1_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero wi = zero else if( abs( b( 2_${ik}$, 2_${ik}$ ) )<=ulp ) then call stdlib${ii}$_slartg( a( 2_${ik}$, 2_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), csr, snr, t ) snr = -snr call stdlib${ii}$_srot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, a( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) call stdlib${ii}$_srot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) csl = one snl = zero a( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 2_${ik}$ ) = zero wi = zero else ! b is nonsingular, first compute the eigenvalues of (a,b) call stdlib${ii}$_slag2( a, lda, b, ldb, safmin, scale1, scale2, wr1, wr2,wi ) if( wi==zero ) then ! two real eigenvalues, compute s*a-w*b h1 = scale1*a( 1_${ik}$, 1_${ik}$ ) - wr1*b( 1_${ik}$, 1_${ik}$ ) h2 = scale1*a( 1_${ik}$, 2_${ik}$ ) - wr1*b( 1_${ik}$, 2_${ik}$ ) h3 = scale1*a( 2_${ik}$, 2_${ik}$ ) - wr1*b( 2_${ik}$, 2_${ik}$ ) rr = stdlib${ii}$_slapy2( h1, h2 ) qq = stdlib${ii}$_slapy2( scale1*a( 2_${ik}$, 1_${ik}$ ), h3 ) if( rr>qq ) then ! find right rotation matrix to zero 1,1 element of ! (sa - wb) call stdlib${ii}$_slartg( h2, h1, csr, snr, t ) else ! find right rotation matrix to zero 2,1 element of ! (sa - wb) call stdlib${ii}$_slartg( h3, scale1*a( 2_${ik}$, 1_${ik}$ ), csr, snr, t ) end if snr = -snr call stdlib${ii}$_srot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, a( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) call stdlib${ii}$_srot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) ! compute inf norms of a and b h1 = max( abs( a( 1_${ik}$, 1_${ik}$ ) )+abs( a( 1_${ik}$, 2_${ik}$ ) ),abs( a( 2_${ik}$, 1_${ik}$ ) )+abs( a( 2_${ik}$, 2_${ik}$ ) ) ) h2 = max( abs( b( 1_${ik}$, 1_${ik}$ ) )+abs( b( 1_${ik}$, 2_${ik}$ ) ),abs( b( 2_${ik}$, 1_${ik}$ ) )+abs( b( 2_${ik}$, 2_${ik}$ ) ) ) if( ( scale1*h1 )>=abs( wr1 )*h2 ) then ! find left rotation matrix q to zero out b(2,1) call stdlib${ii}$_slartg( b( 1_${ik}$, 1_${ik}$ ), b( 2_${ik}$, 1_${ik}$ ), csl, snl, r ) else ! find left rotation matrix q to zero out a(2,1) call stdlib${ii}$_slartg( a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), csl, snl, r ) end if call stdlib${ii}$_srot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), lda, a( 2_${ik}$, 1_${ik}$ ), lda, csl, snl ) call stdlib${ii}$_srot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), ldb, b( 2_${ik}$, 1_${ik}$ ), ldb, csl, snl ) a( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero else ! a pair of complex conjugate eigenvalues ! first compute the svd of the matrix b call stdlib${ii}$_slasv2( b( 1_${ik}$, 1_${ik}$ ), b( 1_${ik}$, 2_${ik}$ ), b( 2_${ik}$, 2_${ik}$ ), r, t, snr,csr, snl, csl ) ! form (a,b) := q(a,b)z**t where q is left rotation matrix and ! z is right rotation matrix computed from stdlib${ii}$_slasv2 call stdlib${ii}$_srot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), lda, a( 2_${ik}$, 1_${ik}$ ), lda, csl, snl ) call stdlib${ii}$_srot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), ldb, b( 2_${ik}$, 1_${ik}$ ), ldb, csl, snl ) call stdlib${ii}$_srot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, a( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) call stdlib${ii}$_srot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) b( 2_${ik}$, 1_${ik}$ ) = zero b( 1_${ik}$, 2_${ik}$ ) = zero end if end if ! unscaling a( 1_${ik}$, 1_${ik}$ ) = anorm*a( 1_${ik}$, 1_${ik}$ ) a( 2_${ik}$, 1_${ik}$ ) = anorm*a( 2_${ik}$, 1_${ik}$ ) a( 1_${ik}$, 2_${ik}$ ) = anorm*a( 1_${ik}$, 2_${ik}$ ) a( 2_${ik}$, 2_${ik}$ ) = anorm*a( 2_${ik}$, 2_${ik}$ ) b( 1_${ik}$, 1_${ik}$ ) = bnorm*b( 1_${ik}$, 1_${ik}$ ) b( 2_${ik}$, 1_${ik}$ ) = bnorm*b( 2_${ik}$, 1_${ik}$ ) b( 1_${ik}$, 2_${ik}$ ) = bnorm*b( 1_${ik}$, 2_${ik}$ ) b( 2_${ik}$, 2_${ik}$ ) = bnorm*b( 2_${ik}$, 2_${ik}$ ) if( wi==zero ) then alphar( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) alphar( 2_${ik}$ ) = a( 2_${ik}$, 2_${ik}$ ) alphai( 1_${ik}$ ) = zero alphai( 2_${ik}$ ) = zero beta( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) beta( 2_${ik}$ ) = b( 2_${ik}$, 2_${ik}$ ) else alphar( 1_${ik}$ ) = anorm*wr1 / scale1 / bnorm alphai( 1_${ik}$ ) = anorm*wi / scale1 / bnorm alphar( 2_${ik}$ ) = alphar( 1_${ik}$ ) alphai( 2_${ik}$ ) = -alphai( 1_${ik}$ ) beta( 1_${ik}$ ) = one beta( 2_${ik}$ ) = one end if return end subroutine stdlib${ii}$_slagv2 pure module subroutine stdlib${ii}$_dlagv2( a, lda, b, ldb, alphar, alphai, beta, csl, snl,csr, snr ) !! DLAGV2 computes the Generalized Schur factorization of a real 2-by-2 !! matrix pencil (A,B) where B is upper triangular. This routine !! computes orthogonal (rotation) matrices given by CSL, SNL and CSR, !! SNR such that !! 1) if the pencil (A,B) has two real eigenvalues (include 0/0 or 1/0 !! types), then !! [ a11 a12 ] := [ CSL SNL ] [ a11 a12 ] [ CSR -SNR ] !! [ 0 a22 ] [ -SNL CSL ] [ a21 a22 ] [ SNR CSR ] !! [ b11 b12 ] := [ CSL SNL ] [ b11 b12 ] [ CSR -SNR ] !! [ 0 b22 ] [ -SNL CSL ] [ 0 b22 ] [ SNR CSR ], !! 2) if the pencil (A,B) has a pair of complex conjugate eigenvalues, !! then !! [ a11 a12 ] := [ CSL SNL ] [ a11 a12 ] [ CSR -SNR ] !! [ a21 a22 ] [ -SNL CSL ] [ a21 a22 ] [ SNR CSR ] !! [ b11 0 ] := [ CSL SNL ] [ b11 b12 ] [ CSR -SNR ] !! [ 0 b22 ] [ -SNL CSL ] [ 0 b22 ] [ SNR CSR ] !! where b11 >= b22 > 0. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldb real(dp), intent(out) :: csl, csr, snl, snr ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: alphai(2_${ik}$), alphar(2_${ik}$), beta(2_${ik}$) ! ===================================================================== ! Local Scalars real(dp) :: anorm, ascale, bnorm, bscale, h1, h2, h3, qq, r, rr, safmin, scale1, & scale2, t, ulp, wi, wr1, wr2 ! Intrinsic Functions ! Executable Statements safmin = stdlib${ii}$_dlamch( 'S' ) ulp = stdlib${ii}$_dlamch( 'P' ) ! scale a anorm = max( abs( a( 1_${ik}$, 1_${ik}$ ) )+abs( a( 2_${ik}$, 1_${ik}$ ) ),abs( a( 1_${ik}$, 2_${ik}$ ) )+abs( a( 2_${ik}$, 2_${ik}$ ) ), & safmin ) ascale = one / anorm a( 1_${ik}$, 1_${ik}$ ) = ascale*a( 1_${ik}$, 1_${ik}$ ) a( 1_${ik}$, 2_${ik}$ ) = ascale*a( 1_${ik}$, 2_${ik}$ ) a( 2_${ik}$, 1_${ik}$ ) = ascale*a( 2_${ik}$, 1_${ik}$ ) a( 2_${ik}$, 2_${ik}$ ) = ascale*a( 2_${ik}$, 2_${ik}$ ) ! scale b bnorm = max( abs( b( 1_${ik}$, 1_${ik}$ ) ), abs( b( 1_${ik}$, 2_${ik}$ ) )+abs( b( 2_${ik}$, 2_${ik}$ ) ),safmin ) bscale = one / bnorm b( 1_${ik}$, 1_${ik}$ ) = bscale*b( 1_${ik}$, 1_${ik}$ ) b( 1_${ik}$, 2_${ik}$ ) = bscale*b( 1_${ik}$, 2_${ik}$ ) b( 2_${ik}$, 2_${ik}$ ) = bscale*b( 2_${ik}$, 2_${ik}$ ) ! check if a can be deflated if( abs( a( 2_${ik}$, 1_${ik}$ ) )<=ulp ) then csl = one snl = zero csr = one snr = zero a( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero wi = zero ! check if b is singular else if( abs( b( 1_${ik}$, 1_${ik}$ ) )<=ulp ) then call stdlib${ii}$_dlartg( a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), csl, snl, r ) csr = one snr = zero call stdlib${ii}$_drot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), lda, a( 2_${ik}$, 1_${ik}$ ), lda, csl, snl ) call stdlib${ii}$_drot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), ldb, b( 2_${ik}$, 1_${ik}$ ), ldb, csl, snl ) a( 2_${ik}$, 1_${ik}$ ) = zero b( 1_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero wi = zero else if( abs( b( 2_${ik}$, 2_${ik}$ ) )<=ulp ) then call stdlib${ii}$_dlartg( a( 2_${ik}$, 2_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), csr, snr, t ) snr = -snr call stdlib${ii}$_drot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, a( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) call stdlib${ii}$_drot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) csl = one snl = zero a( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 2_${ik}$ ) = zero wi = zero else ! b is nonsingular, first compute the eigenvalues of (a,b) call stdlib${ii}$_dlag2( a, lda, b, ldb, safmin, scale1, scale2, wr1, wr2,wi ) if( wi==zero ) then ! two real eigenvalues, compute s*a-w*b h1 = scale1*a( 1_${ik}$, 1_${ik}$ ) - wr1*b( 1_${ik}$, 1_${ik}$ ) h2 = scale1*a( 1_${ik}$, 2_${ik}$ ) - wr1*b( 1_${ik}$, 2_${ik}$ ) h3 = scale1*a( 2_${ik}$, 2_${ik}$ ) - wr1*b( 2_${ik}$, 2_${ik}$ ) rr = stdlib${ii}$_dlapy2( h1, h2 ) qq = stdlib${ii}$_dlapy2( scale1*a( 2_${ik}$, 1_${ik}$ ), h3 ) if( rr>qq ) then ! find right rotation matrix to zero 1,1 element of ! (sa - wb) call stdlib${ii}$_dlartg( h2, h1, csr, snr, t ) else ! find right rotation matrix to zero 2,1 element of ! (sa - wb) call stdlib${ii}$_dlartg( h3, scale1*a( 2_${ik}$, 1_${ik}$ ), csr, snr, t ) end if snr = -snr call stdlib${ii}$_drot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, a( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) call stdlib${ii}$_drot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) ! compute inf norms of a and b h1 = max( abs( a( 1_${ik}$, 1_${ik}$ ) )+abs( a( 1_${ik}$, 2_${ik}$ ) ),abs( a( 2_${ik}$, 1_${ik}$ ) )+abs( a( 2_${ik}$, 2_${ik}$ ) ) ) h2 = max( abs( b( 1_${ik}$, 1_${ik}$ ) )+abs( b( 1_${ik}$, 2_${ik}$ ) ),abs( b( 2_${ik}$, 1_${ik}$ ) )+abs( b( 2_${ik}$, 2_${ik}$ ) ) ) if( ( scale1*h1 )>=abs( wr1 )*h2 ) then ! find left rotation matrix q to zero out b(2,1) call stdlib${ii}$_dlartg( b( 1_${ik}$, 1_${ik}$ ), b( 2_${ik}$, 1_${ik}$ ), csl, snl, r ) else ! find left rotation matrix q to zero out a(2,1) call stdlib${ii}$_dlartg( a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), csl, snl, r ) end if call stdlib${ii}$_drot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), lda, a( 2_${ik}$, 1_${ik}$ ), lda, csl, snl ) call stdlib${ii}$_drot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), ldb, b( 2_${ik}$, 1_${ik}$ ), ldb, csl, snl ) a( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero else ! a pair of complex conjugate eigenvalues ! first compute the svd of the matrix b call stdlib${ii}$_dlasv2( b( 1_${ik}$, 1_${ik}$ ), b( 1_${ik}$, 2_${ik}$ ), b( 2_${ik}$, 2_${ik}$ ), r, t, snr,csr, snl, csl ) ! form (a,b) := q(a,b)z**t where q is left rotation matrix and ! z is right rotation matrix computed from stdlib${ii}$_dlasv2 call stdlib${ii}$_drot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), lda, a( 2_${ik}$, 1_${ik}$ ), lda, csl, snl ) call stdlib${ii}$_drot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), ldb, b( 2_${ik}$, 1_${ik}$ ), ldb, csl, snl ) call stdlib${ii}$_drot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, a( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) call stdlib${ii}$_drot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) b( 2_${ik}$, 1_${ik}$ ) = zero b( 1_${ik}$, 2_${ik}$ ) = zero end if end if ! unscaling a( 1_${ik}$, 1_${ik}$ ) = anorm*a( 1_${ik}$, 1_${ik}$ ) a( 2_${ik}$, 1_${ik}$ ) = anorm*a( 2_${ik}$, 1_${ik}$ ) a( 1_${ik}$, 2_${ik}$ ) = anorm*a( 1_${ik}$, 2_${ik}$ ) a( 2_${ik}$, 2_${ik}$ ) = anorm*a( 2_${ik}$, 2_${ik}$ ) b( 1_${ik}$, 1_${ik}$ ) = bnorm*b( 1_${ik}$, 1_${ik}$ ) b( 2_${ik}$, 1_${ik}$ ) = bnorm*b( 2_${ik}$, 1_${ik}$ ) b( 1_${ik}$, 2_${ik}$ ) = bnorm*b( 1_${ik}$, 2_${ik}$ ) b( 2_${ik}$, 2_${ik}$ ) = bnorm*b( 2_${ik}$, 2_${ik}$ ) if( wi==zero ) then alphar( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) alphar( 2_${ik}$ ) = a( 2_${ik}$, 2_${ik}$ ) alphai( 1_${ik}$ ) = zero alphai( 2_${ik}$ ) = zero beta( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) beta( 2_${ik}$ ) = b( 2_${ik}$, 2_${ik}$ ) else alphar( 1_${ik}$ ) = anorm*wr1 / scale1 / bnorm alphai( 1_${ik}$ ) = anorm*wi / scale1 / bnorm alphar( 2_${ik}$ ) = alphar( 1_${ik}$ ) alphai( 2_${ik}$ ) = -alphai( 1_${ik}$ ) beta( 1_${ik}$ ) = one beta( 2_${ik}$ ) = one end if return end subroutine stdlib${ii}$_dlagv2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lagv2( a, lda, b, ldb, alphar, alphai, beta, csl, snl,csr, snr ) !! DLAGV2: computes the Generalized Schur factorization of a real 2-by-2 !! matrix pencil (A,B) where B is upper triangular. This routine !! computes orthogonal (rotation) matrices given by CSL, SNL and CSR, !! SNR such that !! 1) if the pencil (A,B) has two real eigenvalues (include 0/0 or 1/0 !! types), then !! [ a11 a12 ] := [ CSL SNL ] [ a11 a12 ] [ CSR -SNR ] !! [ 0 a22 ] [ -SNL CSL ] [ a21 a22 ] [ SNR CSR ] !! [ b11 b12 ] := [ CSL SNL ] [ b11 b12 ] [ CSR -SNR ] !! [ 0 b22 ] [ -SNL CSL ] [ 0 b22 ] [ SNR CSR ], !! 2) if the pencil (A,B) has a pair of complex conjugate eigenvalues, !! then !! [ a11 a12 ] := [ CSL SNL ] [ a11 a12 ] [ CSR -SNR ] !! [ a21 a22 ] [ -SNL CSL ] [ a21 a22 ] [ SNR CSR ] !! [ b11 0 ] := [ CSL SNL ] [ b11 b12 ] [ CSR -SNR ] !! [ 0 b22 ] [ -SNL CSL ] [ 0 b22 ] [ SNR CSR ] !! where b11 >= b22 > 0. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: lda, ldb real(${rk}$), intent(out) :: csl, csr, snl, snr ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: alphai(2_${ik}$), alphar(2_${ik}$), beta(2_${ik}$) ! ===================================================================== ! Local Scalars real(${rk}$) :: anorm, ascale, bnorm, bscale, h1, h2, h3, qq, r, rr, safmin, scale1, & scale2, t, ulp, wi, wr1, wr2 ! Intrinsic Functions ! Executable Statements safmin = stdlib${ii}$_${ri}$lamch( 'S' ) ulp = stdlib${ii}$_${ri}$lamch( 'P' ) ! scale a anorm = max( abs( a( 1_${ik}$, 1_${ik}$ ) )+abs( a( 2_${ik}$, 1_${ik}$ ) ),abs( a( 1_${ik}$, 2_${ik}$ ) )+abs( a( 2_${ik}$, 2_${ik}$ ) ), & safmin ) ascale = one / anorm a( 1_${ik}$, 1_${ik}$ ) = ascale*a( 1_${ik}$, 1_${ik}$ ) a( 1_${ik}$, 2_${ik}$ ) = ascale*a( 1_${ik}$, 2_${ik}$ ) a( 2_${ik}$, 1_${ik}$ ) = ascale*a( 2_${ik}$, 1_${ik}$ ) a( 2_${ik}$, 2_${ik}$ ) = ascale*a( 2_${ik}$, 2_${ik}$ ) ! scale b bnorm = max( abs( b( 1_${ik}$, 1_${ik}$ ) ), abs( b( 1_${ik}$, 2_${ik}$ ) )+abs( b( 2_${ik}$, 2_${ik}$ ) ),safmin ) bscale = one / bnorm b( 1_${ik}$, 1_${ik}$ ) = bscale*b( 1_${ik}$, 1_${ik}$ ) b( 1_${ik}$, 2_${ik}$ ) = bscale*b( 1_${ik}$, 2_${ik}$ ) b( 2_${ik}$, 2_${ik}$ ) = bscale*b( 2_${ik}$, 2_${ik}$ ) ! check if a can be deflated if( abs( a( 2_${ik}$, 1_${ik}$ ) )<=ulp ) then csl = one snl = zero csr = one snr = zero a( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero wi = zero ! check if b is singular else if( abs( b( 1_${ik}$, 1_${ik}$ ) )<=ulp ) then call stdlib${ii}$_${ri}$lartg( a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), csl, snl, r ) csr = one snr = zero call stdlib${ii}$_${ri}$rot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), lda, a( 2_${ik}$, 1_${ik}$ ), lda, csl, snl ) call stdlib${ii}$_${ri}$rot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), ldb, b( 2_${ik}$, 1_${ik}$ ), ldb, csl, snl ) a( 2_${ik}$, 1_${ik}$ ) = zero b( 1_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero wi = zero else if( abs( b( 2_${ik}$, 2_${ik}$ ) )<=ulp ) then call stdlib${ii}$_${ri}$lartg( a( 2_${ik}$, 2_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), csr, snr, t ) snr = -snr call stdlib${ii}$_${ri}$rot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, a( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) call stdlib${ii}$_${ri}$rot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) csl = one snl = zero a( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 2_${ik}$ ) = zero wi = zero else ! b is nonsingular, first compute the eigenvalues of (a,b) call stdlib${ii}$_${ri}$lag2( a, lda, b, ldb, safmin, scale1, scale2, wr1, wr2,wi ) if( wi==zero ) then ! two real eigenvalues, compute s*a-w*b h1 = scale1*a( 1_${ik}$, 1_${ik}$ ) - wr1*b( 1_${ik}$, 1_${ik}$ ) h2 = scale1*a( 1_${ik}$, 2_${ik}$ ) - wr1*b( 1_${ik}$, 2_${ik}$ ) h3 = scale1*a( 2_${ik}$, 2_${ik}$ ) - wr1*b( 2_${ik}$, 2_${ik}$ ) rr = stdlib${ii}$_${ri}$lapy2( h1, h2 ) qq = stdlib${ii}$_${ri}$lapy2( scale1*a( 2_${ik}$, 1_${ik}$ ), h3 ) if( rr>qq ) then ! find right rotation matrix to zero 1,1 element of ! (sa - wb) call stdlib${ii}$_${ri}$lartg( h2, h1, csr, snr, t ) else ! find right rotation matrix to zero 2,1 element of ! (sa - wb) call stdlib${ii}$_${ri}$lartg( h3, scale1*a( 2_${ik}$, 1_${ik}$ ), csr, snr, t ) end if snr = -snr call stdlib${ii}$_${ri}$rot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, a( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) call stdlib${ii}$_${ri}$rot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) ! compute inf norms of a and b h1 = max( abs( a( 1_${ik}$, 1_${ik}$ ) )+abs( a( 1_${ik}$, 2_${ik}$ ) ),abs( a( 2_${ik}$, 1_${ik}$ ) )+abs( a( 2_${ik}$, 2_${ik}$ ) ) ) h2 = max( abs( b( 1_${ik}$, 1_${ik}$ ) )+abs( b( 1_${ik}$, 2_${ik}$ ) ),abs( b( 2_${ik}$, 1_${ik}$ ) )+abs( b( 2_${ik}$, 2_${ik}$ ) ) ) if( ( scale1*h1 )>=abs( wr1 )*h2 ) then ! find left rotation matrix q to zero out b(2,1) call stdlib${ii}$_${ri}$lartg( b( 1_${ik}$, 1_${ik}$ ), b( 2_${ik}$, 1_${ik}$ ), csl, snl, r ) else ! find left rotation matrix q to zero out a(2,1) call stdlib${ii}$_${ri}$lartg( a( 1_${ik}$, 1_${ik}$ ), a( 2_${ik}$, 1_${ik}$ ), csl, snl, r ) end if call stdlib${ii}$_${ri}$rot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), lda, a( 2_${ik}$, 1_${ik}$ ), lda, csl, snl ) call stdlib${ii}$_${ri}$rot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), ldb, b( 2_${ik}$, 1_${ik}$ ), ldb, csl, snl ) a( 2_${ik}$, 1_${ik}$ ) = zero b( 2_${ik}$, 1_${ik}$ ) = zero else ! a pair of complex conjugate eigenvalues ! first compute the svd of the matrix b call stdlib${ii}$_${ri}$lasv2( b( 1_${ik}$, 1_${ik}$ ), b( 1_${ik}$, 2_${ik}$ ), b( 2_${ik}$, 2_${ik}$ ), r, t, snr,csr, snl, csl ) ! form (a,b) := q(a,b)z**t where q is left rotation matrix and ! z is right rotation matrix computed from stdlib${ii}$_${ri}$lasv2 call stdlib${ii}$_${ri}$rot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), lda, a( 2_${ik}$, 1_${ik}$ ), lda, csl, snl ) call stdlib${ii}$_${ri}$rot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), ldb, b( 2_${ik}$, 1_${ik}$ ), ldb, csl, snl ) call stdlib${ii}$_${ri}$rot( 2_${ik}$, a( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, a( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) call stdlib${ii}$_${ri}$rot( 2_${ik}$, b( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, b( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, csr, snr ) b( 2_${ik}$, 1_${ik}$ ) = zero b( 1_${ik}$, 2_${ik}$ ) = zero end if end if ! unscaling a( 1_${ik}$, 1_${ik}$ ) = anorm*a( 1_${ik}$, 1_${ik}$ ) a( 2_${ik}$, 1_${ik}$ ) = anorm*a( 2_${ik}$, 1_${ik}$ ) a( 1_${ik}$, 2_${ik}$ ) = anorm*a( 1_${ik}$, 2_${ik}$ ) a( 2_${ik}$, 2_${ik}$ ) = anorm*a( 2_${ik}$, 2_${ik}$ ) b( 1_${ik}$, 1_${ik}$ ) = bnorm*b( 1_${ik}$, 1_${ik}$ ) b( 2_${ik}$, 1_${ik}$ ) = bnorm*b( 2_${ik}$, 1_${ik}$ ) b( 1_${ik}$, 2_${ik}$ ) = bnorm*b( 1_${ik}$, 2_${ik}$ ) b( 2_${ik}$, 2_${ik}$ ) = bnorm*b( 2_${ik}$, 2_${ik}$ ) if( wi==zero ) then alphar( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) alphar( 2_${ik}$ ) = a( 2_${ik}$, 2_${ik}$ ) alphai( 1_${ik}$ ) = zero alphai( 2_${ik}$ ) = zero beta( 1_${ik}$ ) = b( 1_${ik}$, 1_${ik}$ ) beta( 2_${ik}$ ) = b( 2_${ik}$, 2_${ik}$ ) else alphar( 1_${ik}$ ) = anorm*wr1 / scale1 / bnorm alphai( 1_${ik}$ ) = anorm*wi / scale1 / bnorm alphar( 2_${ik}$ ) = alphar( 1_${ik}$ ) alphai( 2_${ik}$ ) = -alphai( 1_${ik}$ ) beta( 1_${ik}$ ) = one beta( 2_${ik}$ ) = one end if return end subroutine stdlib${ii}$_${ri}$lagv2 #:endif #:endfor pure module subroutine stdlib${ii}$_stgevc( side, howmny, select, n, s, lds, p, ldp, vl,ldvl, vr, ldvr, & !! STGEVC computes some or all of the right and/or left eigenvectors of !! a pair of real matrices (S,P), where S is a quasi-triangular matrix !! and P is upper triangular. Matrix pairs of this type are produced by !! the generalized Schur factorization of a matrix pair (A,B): !! A = Q*S*Z**T, B = Q*P*Z**T !! as computed by SGGHRD + SHGEQZ. !! The right eigenvector x and the left eigenvector y of (S,P) !! corresponding to an eigenvalue w are defined by: !! S*x = w*P*x, (y**H)*S = w*(y**H)*P, !! where y**H denotes the conjugate tranpose of y. !! The eigenvalues are not input to this routine, but are computed !! directly from the diagonal blocks of S and P. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of (S,P), or the products Z*X and/or Q*Y, !! where Z and Q are input matrices. !! If Q and Z are the orthogonal factors from the generalized Schur !! factorization of a matrix pair (A,B), then Z*X and Q*Y !! are the matrices of right and left eigenvectors of (A,B). mm, m, work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: howmny, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldp, lds, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(in) :: select(*) real(sp), intent(in) :: p(ldp,*), s(lds,*) real(sp), intent(inout) :: vl(ldvl,*), vr(ldvr,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Parameters real(sp), parameter :: safety = 1.0e+2_sp ! Local Scalars logical(lk) :: compl, compr, il2by2, ilabad, ilall, ilback, ilbbad, ilcomp, ilcplx, & lsa, lsb integer(${ik}$) :: i, ibeg, ieig, iend, ihwmny, iinfo, im, iside, j, ja, jc, je, jr, jw, & na, nw real(sp) :: acoef, acoefa, anorm, ascale, bcoefa, bcoefi, bcoefr, big, bignum, bnorm, & bscale, cim2a, cim2b, cimaga, cimagb, cre2a, cre2b, creala, crealb, dmin, safmin, & salfar, sbeta, scale, small, temp, temp2, temp2i, temp2r, ulp, xmax, xscale ! Local Arrays real(sp) :: bdiag(2_${ik}$), sum(2_${ik}$,2_${ik}$), sums(2_${ik}$,2_${ik}$), sump(2_${ik}$,2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters if( stdlib_lsame( howmny, 'A' ) ) then ihwmny = 1_${ik}$ ilall = .true. ilback = .false. else if( stdlib_lsame( howmny, 'S' ) ) then ihwmny = 2_${ik}$ ilall = .false. ilback = .false. else if( stdlib_lsame( howmny, 'B' ) ) then ihwmny = 3_${ik}$ ilall = .true. ilback = .true. else ihwmny = -1_${ik}$ ilall = .true. end if if( stdlib_lsame( side, 'R' ) ) then iside = 1_${ik}$ compl = .false. compr = .true. else if( stdlib_lsame( side, 'L' ) ) then iside = 2_${ik}$ compl = .true. compr = .false. else if( stdlib_lsame( side, 'B' ) ) then iside = 3_${ik}$ compl = .true. compr = .true. else iside = -1_${ik}$ end if info = 0_${ik}$ if( iside<0_${ik}$ ) then info = -1_${ik}$ else if( ihwmny<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lds1_${ik}$ )anorm = anorm + abs( s( 2_${ik}$, 1_${ik}$ ) ) bnorm = abs( p( 1_${ik}$, 1_${ik}$ ) ) work( 1_${ik}$ ) = zero work( n+1 ) = zero do j = 2, n temp = zero temp2 = zero if( s( j, j-1 )==zero ) then iend = j - 1_${ik}$ else iend = j - 2_${ik}$ end if do i = 1, iend temp = temp + abs( s( i, j ) ) temp2 = temp2 + abs( p( i, j ) ) end do work( j ) = temp work( n+j ) = temp2 do i = iend + 1, min( j+1, n ) temp = temp + abs( s( i, j ) ) temp2 = temp2 + abs( p( i, j ) ) end do anorm = max( anorm, temp ) bnorm = max( bnorm, temp2 ) end do ascale = one / max( anorm, safmin ) bscale = one / max( bnorm, safmin ) ! left eigenvectors if( compl ) then ieig = 0_${ik}$ ! main loop over eigenvalues ilcplx = .false. loop_220: do je = 1, n ! skip this iteration if (a) howmny='s' and select=.false., or ! (b) this would be the second of a complex pair. ! check for complex eigenvalue, so as to be sure of which ! entry(-ies) of select to look at. if( ilcplx ) then ilcplx = .false. cycle loop_220 end if nw = 1_${ik}$ if( je=safmin .and. abs( acoef )=safmin .and. abs( bcoefr )=safmin )scale = ( safmin / ulp ) / & acoefa if( bcoefa*ulp=safmin )scale = max( scale, ( safmin / & ulp ) / bcoefa ) if( safmin*acoefa>ascale )scale = ascale / ( safmin*acoefa ) if( safmin*bcoefa>bscale )scale = min( scale, bscale / ( safmin*bcoefa ) ) if( scale/=one ) then acoef = scale*acoef acoefa = abs( acoef ) bcoefr = scale*bcoefr bcoefi = scale*bcoefi bcoefa = abs( bcoefr ) + abs( bcoefi ) end if ! compute first two components of eigenvector temp = acoef*s( je+1, je ) temp2r = acoef*s( je, je ) - bcoefr*p( je, je ) temp2i = -bcoefi*p( je, je ) if( abs( temp )>abs( temp2r )+abs( temp2i ) ) then work( 2_${ik}$*n+je ) = one work( 3_${ik}$*n+je ) = zero work( 2_${ik}$*n+je+1 ) = -temp2r / temp work( 3_${ik}$*n+je+1 ) = -temp2i / temp else work( 2_${ik}$*n+je+1 ) = one work( 3_${ik}$*n+je+1 ) = zero temp = acoef*s( je, je+1 ) work( 2_${ik}$*n+je ) = ( bcoefr*p( je+1, je+1 )-acoef*s( je+1, je+1 ) ) / & temp work( 3_${ik}$*n+je ) = bcoefi*p( je+1, je+1 ) / temp end if xmax = max( abs( work( 2_${ik}$*n+je ) )+abs( work( 3_${ik}$*n+je ) ),abs( work( 2_${ik}$*n+je+1 ) & )+abs( work( 3_${ik}$*n+je+1 ) ) ) end if dmin = max( ulp*acoefa*anorm, ulp*bcoefa*bnorm, safmin ) ! t ! triangular solve of (a a - b b) y = 0 ! t ! (rowwise in (a a - b b) , or columnwise in (a a - b b) ) il2by2 = .false. loop_160: do j = je + nw, n if( il2by2 ) then il2by2 = .false. cycle loop_160 end if na = 1_${ik}$ bdiag( 1_${ik}$ ) = p( j, j ) if( jbignum*xscale ) then do jw = 0, nw - 1 do jr = je, j - 1 work( ( jw+2 )*n+jr ) = xscale*work( ( jw+2 )*n+jr ) end do end do xmax = xmax*xscale end if ! compute dot products ! j-1 ! sum = sum conjg( a*s(k,j) - b*p(k,j) )*x(k) ! k=je ! to reduce the op count, this is done as ! _ j-1 _ j-1 ! a*conjg( sum s(k,j)*x(k) ) - b*conjg( sum p(k,j)*x(k) ) ! k=je k=je ! which may cause underflow problems if a or b are close ! to underflow. (e.g., less than small.) do jw = 1, nw do ja = 1, na sums( ja, jw ) = zero sump( ja, jw ) = zero do jr = je, j - 1 sums( ja, jw ) = sums( ja, jw ) +s( jr, j+ja-1 )*work( ( jw+1 )*n+jr & ) sump( ja, jw ) = sump( ja, jw ) +p( jr, j+ja-1 )*work( ( jw+1 )*n+jr & ) end do end do end do do ja = 1, na if( ilcplx ) then sum( ja, 1_${ik}$ ) = -acoef*sums( ja, 1_${ik}$ ) +bcoefr*sump( ja, 1_${ik}$ ) -bcoefi*sump( & ja, 2_${ik}$ ) sum( ja, 2_${ik}$ ) = -acoef*sums( ja, 2_${ik}$ ) +bcoefr*sump( ja, 2_${ik}$ ) +bcoefi*sump( & ja, 1_${ik}$ ) else sum( ja, 1_${ik}$ ) = -acoef*sums( ja, 1_${ik}$ ) +bcoefr*sump( ja, 1_${ik}$ ) end if end do ! t ! solve ( a a - b b ) y = sum(,) ! with scaling and perturbation of the denominator call stdlib${ii}$_slaln2( .true., na, nw, dmin, acoef, s( j, j ), lds,bdiag( 1_${ik}$ ), & bdiag( 2_${ik}$ ), sum, 2_${ik}$, bcoefr,bcoefi, work( 2_${ik}$*n+j ), n, scale, temp,iinfo ) if( scalesafmin ) then xscale = one / xmax do jw = 0, nw - 1 do jr = ibeg, n vl( jr, ieig+jw ) = xscale*vl( jr, ieig+jw ) end do end do end if ieig = ieig + nw - 1_${ik}$ end do loop_220 end if ! right eigenvectors if( compr ) then ieig = im + 1_${ik}$ ! main loop over eigenvalues ilcplx = .false. loop_500: do je = n, 1, -1 ! skip this iteration if (a) howmny='s' and select=.false., or ! (b) this would be the second of a complex pair. ! check for complex eigenvalue, so as to be sure of which ! entry(-ies) of select to look at -- if complex, select(je) ! or select(je-1). ! if this is a complex pair, the 2-by-2 diagonal block ! corresponding to the eigenvalue is in rows/columns je-1:je if( ilcplx ) then ilcplx = .false. cycle loop_500 end if nw = 1_${ik}$ if( je>1_${ik}$ ) then if( s( je, je-1 )/=zero ) then ilcplx = .true. nw = 2_${ik}$ end if end if if( ilall ) then ilcomp = .true. else if( ilcplx ) then ilcomp = select( je ) .or. select( je-1 ) else ilcomp = select( je ) end if if( .not.ilcomp )cycle loop_500 ! decide if (a) singular pencil, (b) real eigenvalue, or ! (c) complex eigenvalue. if( .not.ilcplx ) then if( abs( s( je, je ) )<=safmin .and.abs( p( je, je ) )<=safmin ) then ! singular matrix pencil -- unit eigenvector ieig = ieig - 1_${ik}$ do jr = 1, n vr( jr, ieig ) = zero end do vr( ieig, ieig ) = one cycle loop_500 end if end if ! clear vector do jw = 0, nw - 1 do jr = 1, n work( ( jw+2 )*n+jr ) = zero end do end do ! compute coefficients in ( a a - b b ) x = 0 ! a is acoef ! b is bcoefr + i*bcoefi if( .not.ilcplx ) then ! real eigenvalue temp = one / max( abs( s( je, je ) )*ascale,abs( p( je, je ) )*bscale, safmin & ) salfar = ( temp*s( je, je ) )*ascale sbeta = ( temp*p( je, je ) )*bscale acoef = sbeta*ascale bcoefr = salfar*bscale bcoefi = zero ! scale to avoid underflow scale = one lsa = abs( sbeta )>=safmin .and. abs( acoef )=safmin .and. abs( bcoefr )=safmin )scale = ( safmin / ulp ) / & acoefa if( bcoefa*ulp=safmin )scale = max( scale, ( safmin / & ulp ) / bcoefa ) if( safmin*acoefa>ascale )scale = ascale / ( safmin*acoefa ) if( safmin*bcoefa>bscale )scale = min( scale, bscale / ( safmin*bcoefa ) ) if( scale/=one ) then acoef = scale*acoef acoefa = abs( acoef ) bcoefr = scale*bcoefr bcoefi = scale*bcoefi bcoefa = abs( bcoefr ) + abs( bcoefi ) end if ! compute first two components of eigenvector ! and contribution to sums temp = acoef*s( je, je-1 ) temp2r = acoef*s( je, je ) - bcoefr*p( je, je ) temp2i = -bcoefi*p( je, je ) if( abs( temp )>=abs( temp2r )+abs( temp2i ) ) then work( 2_${ik}$*n+je ) = one work( 3_${ik}$*n+je ) = zero work( 2_${ik}$*n+je-1 ) = -temp2r / temp work( 3_${ik}$*n+je-1 ) = -temp2i / temp else work( 2_${ik}$*n+je-1 ) = one work( 3_${ik}$*n+je-1 ) = zero temp = acoef*s( je-1, je ) work( 2_${ik}$*n+je ) = ( bcoefr*p( je-1, je-1 )-acoef*s( je-1, je-1 ) ) / & temp work( 3_${ik}$*n+je ) = bcoefi*p( je-1, je-1 ) / temp end if xmax = max( abs( work( 2_${ik}$*n+je ) )+abs( work( 3_${ik}$*n+je ) ),abs( work( 2_${ik}$*n+je-1 ) & )+abs( work( 3_${ik}$*n+je-1 ) ) ) ! compute contribution from columns je and je-1 ! of a and b to the sums. creala = acoef*work( 2_${ik}$*n+je-1 ) cimaga = acoef*work( 3_${ik}$*n+je-1 ) crealb = bcoefr*work( 2_${ik}$*n+je-1 ) -bcoefi*work( 3_${ik}$*n+je-1 ) cimagb = bcoefi*work( 2_${ik}$*n+je-1 ) +bcoefr*work( 3_${ik}$*n+je-1 ) cre2a = acoef*work( 2_${ik}$*n+je ) cim2a = acoef*work( 3_${ik}$*n+je ) cre2b = bcoefr*work( 2_${ik}$*n+je ) - bcoefi*work( 3_${ik}$*n+je ) cim2b = bcoefi*work( 2_${ik}$*n+je ) + bcoefr*work( 3_${ik}$*n+je ) do jr = 1, je - 2 work( 2_${ik}$*n+jr ) = -creala*s( jr, je-1 ) +crealb*p( jr, je-1 ) -cre2a*s( jr, & je ) + cre2b*p( jr, je ) work( 3_${ik}$*n+jr ) = -cimaga*s( jr, je-1 ) +cimagb*p( jr, je-1 ) -cim2a*s( jr, & je ) + cim2b*p( jr, je ) end do end if dmin = max( ulp*acoefa*anorm, ulp*bcoefa*bnorm, safmin ) ! columnwise triangular solve of (a a - b b) x = 0 il2by2 = .false. loop_370: do j = je - nw, 1, -1 ! if a 2-by-2 block, is in position j-1:j, wait until ! next iteration to process it (when it will be j:j+1) if( .not.il2by2 .and. j>1_${ik}$ ) then if( s( j, j-1 )/=zero ) then il2by2 = .true. cycle loop_370 end if end if bdiag( 1_${ik}$ ) = p( j, j ) if( il2by2 ) then na = 2_${ik}$ bdiag( 2_${ik}$ ) = p( j+1, j+1 ) else na = 1_${ik}$ end if ! compute x(j) (and x(j+1), if 2-by-2 block) call stdlib${ii}$_slaln2( .false., na, nw, dmin, acoef, s( j, j ),lds, bdiag( 1_${ik}$ ), & bdiag( 2_${ik}$ ), work( 2_${ik}$*n+j ),n, bcoefr, bcoefi, sum, 2_${ik}$, scale, temp,iinfo ) if( scale1_${ik}$ ) then ! check whether scaling is necessary for sum. xscale = one / max( one, xmax ) temp = acoefa*work( j ) + bcoefa*work( n+j ) if( il2by2 )temp = max( temp, acoefa*work( j+1 )+bcoefa*work( n+j+1 ) ) temp = max( temp, acoefa, bcoefa ) if( temp>bignum*xscale ) then do jw = 0, nw - 1 do jr = 1, je work( ( jw+2 )*n+jr ) = xscale*work( ( jw+2 )*n+jr ) end do end do xmax = xmax*xscale end if ! compute the contributions of the off-diagonals of ! column j (and j+1, if 2-by-2 block) of a and b to the ! sums. do ja = 1, na if( ilcplx ) then creala = acoef*work( 2_${ik}$*n+j+ja-1 ) cimaga = acoef*work( 3_${ik}$*n+j+ja-1 ) crealb = bcoefr*work( 2_${ik}$*n+j+ja-1 ) -bcoefi*work( 3_${ik}$*n+j+ja-1 ) cimagb = bcoefi*work( 2_${ik}$*n+j+ja-1 ) +bcoefr*work( 3_${ik}$*n+j+ja-1 ) do jr = 1, j - 1 work( 2_${ik}$*n+jr ) = work( 2_${ik}$*n+jr ) -creala*s( jr, j+ja-1 ) +crealb*p(& jr, j+ja-1 ) work( 3_${ik}$*n+jr ) = work( 3_${ik}$*n+jr ) -cimaga*s( jr, j+ja-1 ) +cimagb*p(& jr, j+ja-1 ) end do else creala = acoef*work( 2_${ik}$*n+j+ja-1 ) crealb = bcoefr*work( 2_${ik}$*n+j+ja-1 ) do jr = 1, j - 1 work( 2_${ik}$*n+jr ) = work( 2_${ik}$*n+jr ) -creala*s( jr, j+ja-1 ) +crealb*p(& jr, j+ja-1 ) end do end if end do end if il2by2 = .false. end do loop_370 ! copy eigenvector to vr, back transforming if ! howmny='b'. ieig = ieig - nw if( ilback ) then do jw = 0, nw - 1 do jr = 1, n work( ( jw+4 )*n+jr ) = work( ( jw+2 )*n+1 )*vr( jr, 1_${ik}$ ) end do ! a series of compiler directives to defeat ! vectorization for the next loop do jc = 2, je do jr = 1, n work( ( jw+4 )*n+jr ) = work( ( jw+4 )*n+jr ) +work( ( jw+2 )*n+jc )& *vr( jr, jc ) end do end do end do do jw = 0, nw - 1 do jr = 1, n vr( jr, ieig+jw ) = work( ( jw+4 )*n+jr ) end do end do iend = n else do jw = 0, nw - 1 do jr = 1, n vr( jr, ieig+jw ) = work( ( jw+2 )*n+jr ) end do end do iend = je end if ! scale eigenvector xmax = zero if( ilcplx ) then do j = 1, iend xmax = max( xmax, abs( vr( j, ieig ) )+abs( vr( j, ieig+1 ) ) ) end do else do j = 1, iend xmax = max( xmax, abs( vr( j, ieig ) ) ) end do end if if( xmax>safmin ) then xscale = one / xmax do jw = 0, nw - 1 do jr = 1, iend vr( jr, ieig+jw ) = xscale*vr( jr, ieig+jw ) end do end do end if end do loop_500 end if return end subroutine stdlib${ii}$_stgevc pure module subroutine stdlib${ii}$_dtgevc( side, howmny, select, n, s, lds, p, ldp, vl,ldvl, vr, ldvr, & !! DTGEVC computes some or all of the right and/or left eigenvectors of !! a pair of real matrices (S,P), where S is a quasi-triangular matrix !! and P is upper triangular. Matrix pairs of this type are produced by !! the generalized Schur factorization of a matrix pair (A,B): !! A = Q*S*Z**T, B = Q*P*Z**T !! as computed by DGGHRD + DHGEQZ. !! The right eigenvector x and the left eigenvector y of (S,P) !! corresponding to an eigenvalue w are defined by: !! S*x = w*P*x, (y**H)*S = w*(y**H)*P, !! where y**H denotes the conjugate tranpose of y. !! The eigenvalues are not input to this routine, but are computed !! directly from the diagonal blocks of S and P. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of (S,P), or the products Z*X and/or Q*Y, !! where Z and Q are input matrices. !! If Q and Z are the orthogonal factors from the generalized Schur !! factorization of a matrix pair (A,B), then Z*X and Q*Y !! are the matrices of right and left eigenvectors of (A,B). mm, m, work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: howmny, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldp, lds, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(in) :: select(*) real(dp), intent(in) :: p(ldp,*), s(lds,*) real(dp), intent(inout) :: vl(ldvl,*), vr(ldvr,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Parameters real(dp), parameter :: safety = 1.0e+2_dp ! Local Scalars logical(lk) :: compl, compr, il2by2, ilabad, ilall, ilback, ilbbad, ilcomp, ilcplx, & lsa, lsb integer(${ik}$) :: i, ibeg, ieig, iend, ihwmny, iinfo, im, iside, j, ja, jc, je, jr, jw, & na, nw real(dp) :: acoef, acoefa, anorm, ascale, bcoefa, bcoefi, bcoefr, big, bignum, bnorm, & bscale, cim2a, cim2b, cimaga, cimagb, cre2a, cre2b, creala, crealb, dmin, safmin, & salfar, sbeta, scale, small, temp, temp2, temp2i, temp2r, ulp, xmax, xscale ! Local Arrays real(dp) :: bdiag(2_${ik}$), sum(2_${ik}$,2_${ik}$), sums(2_${ik}$,2_${ik}$), sump(2_${ik}$,2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters if( stdlib_lsame( howmny, 'A' ) ) then ihwmny = 1_${ik}$ ilall = .true. ilback = .false. else if( stdlib_lsame( howmny, 'S' ) ) then ihwmny = 2_${ik}$ ilall = .false. ilback = .false. else if( stdlib_lsame( howmny, 'B' ) ) then ihwmny = 3_${ik}$ ilall = .true. ilback = .true. else ihwmny = -1_${ik}$ ilall = .true. end if if( stdlib_lsame( side, 'R' ) ) then iside = 1_${ik}$ compl = .false. compr = .true. else if( stdlib_lsame( side, 'L' ) ) then iside = 2_${ik}$ compl = .true. compr = .false. else if( stdlib_lsame( side, 'B' ) ) then iside = 3_${ik}$ compl = .true. compr = .true. else iside = -1_${ik}$ end if info = 0_${ik}$ if( iside<0_${ik}$ ) then info = -1_${ik}$ else if( ihwmny<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lds1_${ik}$ )anorm = anorm + abs( s( 2_${ik}$, 1_${ik}$ ) ) bnorm = abs( p( 1_${ik}$, 1_${ik}$ ) ) work( 1_${ik}$ ) = zero work( n+1 ) = zero do j = 2, n temp = zero temp2 = zero if( s( j, j-1 )==zero ) then iend = j - 1_${ik}$ else iend = j - 2_${ik}$ end if do i = 1, iend temp = temp + abs( s( i, j ) ) temp2 = temp2 + abs( p( i, j ) ) end do work( j ) = temp work( n+j ) = temp2 do i = iend + 1, min( j+1, n ) temp = temp + abs( s( i, j ) ) temp2 = temp2 + abs( p( i, j ) ) end do anorm = max( anorm, temp ) bnorm = max( bnorm, temp2 ) end do ascale = one / max( anorm, safmin ) bscale = one / max( bnorm, safmin ) ! left eigenvectors if( compl ) then ieig = 0_${ik}$ ! main loop over eigenvalues ilcplx = .false. loop_220: do je = 1, n ! skip this iteration if (a) howmny='s' and select=.false., or ! (b) this would be the second of a complex pair. ! check for complex eigenvalue, so as to be sure of which ! entry(-ies) of select to look at. if( ilcplx ) then ilcplx = .false. cycle loop_220 end if nw = 1_${ik}$ if( je=safmin .and. abs( acoef )=safmin .and. abs( bcoefr )=safmin )scale = ( safmin / ulp ) / & acoefa if( bcoefa*ulp=safmin )scale = max( scale, ( safmin / & ulp ) / bcoefa ) if( safmin*acoefa>ascale )scale = ascale / ( safmin*acoefa ) if( safmin*bcoefa>bscale )scale = min( scale, bscale / ( safmin*bcoefa ) ) if( scale/=one ) then acoef = scale*acoef acoefa = abs( acoef ) bcoefr = scale*bcoefr bcoefi = scale*bcoefi bcoefa = abs( bcoefr ) + abs( bcoefi ) end if ! compute first two components of eigenvector temp = acoef*s( je+1, je ) temp2r = acoef*s( je, je ) - bcoefr*p( je, je ) temp2i = -bcoefi*p( je, je ) if( abs( temp )>abs( temp2r )+abs( temp2i ) ) then work( 2_${ik}$*n+je ) = one work( 3_${ik}$*n+je ) = zero work( 2_${ik}$*n+je+1 ) = -temp2r / temp work( 3_${ik}$*n+je+1 ) = -temp2i / temp else work( 2_${ik}$*n+je+1 ) = one work( 3_${ik}$*n+je+1 ) = zero temp = acoef*s( je, je+1 ) work( 2_${ik}$*n+je ) = ( bcoefr*p( je+1, je+1 )-acoef*s( je+1, je+1 ) ) / & temp work( 3_${ik}$*n+je ) = bcoefi*p( je+1, je+1 ) / temp end if xmax = max( abs( work( 2_${ik}$*n+je ) )+abs( work( 3_${ik}$*n+je ) ),abs( work( 2_${ik}$*n+je+1 ) & )+abs( work( 3_${ik}$*n+je+1 ) ) ) end if dmin = max( ulp*acoefa*anorm, ulp*bcoefa*bnorm, safmin ) ! t ! triangular solve of (a a - b b) y = 0 ! t ! (rowwise in (a a - b b) , or columnwise in (a a - b b) ) il2by2 = .false. loop_160: do j = je + nw, n if( il2by2 ) then il2by2 = .false. cycle loop_160 end if na = 1_${ik}$ bdiag( 1_${ik}$ ) = p( j, j ) if( jbignum*xscale ) then do jw = 0, nw - 1 do jr = je, j - 1 work( ( jw+2 )*n+jr ) = xscale*work( ( jw+2 )*n+jr ) end do end do xmax = xmax*xscale end if ! compute dot products ! j-1 ! sum = sum conjg( a*s(k,j) - b*p(k,j) )*x(k) ! k=je ! to reduce the op count, this is done as ! _ j-1 _ j-1 ! a*conjg( sum s(k,j)*x(k) ) - b*conjg( sum p(k,j)*x(k) ) ! k=je k=je ! which may cause underflow problems if a or b are close ! to underflow. (e.g., less than small.) do jw = 1, nw do ja = 1, na sums( ja, jw ) = zero sump( ja, jw ) = zero do jr = je, j - 1 sums( ja, jw ) = sums( ja, jw ) +s( jr, j+ja-1 )*work( ( jw+1 )*n+jr & ) sump( ja, jw ) = sump( ja, jw ) +p( jr, j+ja-1 )*work( ( jw+1 )*n+jr & ) end do end do end do do ja = 1, na if( ilcplx ) then sum( ja, 1_${ik}$ ) = -acoef*sums( ja, 1_${ik}$ ) +bcoefr*sump( ja, 1_${ik}$ ) -bcoefi*sump( & ja, 2_${ik}$ ) sum( ja, 2_${ik}$ ) = -acoef*sums( ja, 2_${ik}$ ) +bcoefr*sump( ja, 2_${ik}$ ) +bcoefi*sump( & ja, 1_${ik}$ ) else sum( ja, 1_${ik}$ ) = -acoef*sums( ja, 1_${ik}$ ) +bcoefr*sump( ja, 1_${ik}$ ) end if end do ! t ! solve ( a a - b b ) y = sum(,) ! with scaling and perturbation of the denominator call stdlib${ii}$_dlaln2( .true., na, nw, dmin, acoef, s( j, j ), lds,bdiag( 1_${ik}$ ), & bdiag( 2_${ik}$ ), sum, 2_${ik}$, bcoefr,bcoefi, work( 2_${ik}$*n+j ), n, scale, temp,iinfo ) if( scalesafmin ) then xscale = one / xmax do jw = 0, nw - 1 do jr = ibeg, n vl( jr, ieig+jw ) = xscale*vl( jr, ieig+jw ) end do end do end if ieig = ieig + nw - 1_${ik}$ end do loop_220 end if ! right eigenvectors if( compr ) then ieig = im + 1_${ik}$ ! main loop over eigenvalues ilcplx = .false. loop_500: do je = n, 1, -1 ! skip this iteration if (a) howmny='s' and select=.false., or ! (b) this would be the second of a complex pair. ! check for complex eigenvalue, so as to be sure of which ! entry(-ies) of select to look at -- if complex, select(je) ! or select(je-1). ! if this is a complex pair, the 2-by-2 diagonal block ! corresponding to the eigenvalue is in rows/columns je-1:je if( ilcplx ) then ilcplx = .false. cycle loop_500 end if nw = 1_${ik}$ if( je>1_${ik}$ ) then if( s( je, je-1 )/=zero ) then ilcplx = .true. nw = 2_${ik}$ end if end if if( ilall ) then ilcomp = .true. else if( ilcplx ) then ilcomp = select( je ) .or. select( je-1 ) else ilcomp = select( je ) end if if( .not.ilcomp )cycle loop_500 ! decide if (a) singular pencil, (b) real eigenvalue, or ! (c) complex eigenvalue. if( .not.ilcplx ) then if( abs( s( je, je ) )<=safmin .and.abs( p( je, je ) )<=safmin ) then ! singular matrix pencil -- unit eigenvector ieig = ieig - 1_${ik}$ do jr = 1, n vr( jr, ieig ) = zero end do vr( ieig, ieig ) = one cycle loop_500 end if end if ! clear vector do jw = 0, nw - 1 do jr = 1, n work( ( jw+2 )*n+jr ) = zero end do end do ! compute coefficients in ( a a - b b ) x = 0 ! a is acoef ! b is bcoefr + i*bcoefi if( .not.ilcplx ) then ! real eigenvalue temp = one / max( abs( s( je, je ) )*ascale,abs( p( je, je ) )*bscale, safmin & ) salfar = ( temp*s( je, je ) )*ascale sbeta = ( temp*p( je, je ) )*bscale acoef = sbeta*ascale bcoefr = salfar*bscale bcoefi = zero ! scale to avoid underflow scale = one lsa = abs( sbeta )>=safmin .and. abs( acoef )=safmin .and. abs( bcoefr )=safmin )scale = ( safmin / ulp ) / & acoefa if( bcoefa*ulp=safmin )scale = max( scale, ( safmin / & ulp ) / bcoefa ) if( safmin*acoefa>ascale )scale = ascale / ( safmin*acoefa ) if( safmin*bcoefa>bscale )scale = min( scale, bscale / ( safmin*bcoefa ) ) if( scale/=one ) then acoef = scale*acoef acoefa = abs( acoef ) bcoefr = scale*bcoefr bcoefi = scale*bcoefi bcoefa = abs( bcoefr ) + abs( bcoefi ) end if ! compute first two components of eigenvector ! and contribution to sums temp = acoef*s( je, je-1 ) temp2r = acoef*s( je, je ) - bcoefr*p( je, je ) temp2i = -bcoefi*p( je, je ) if( abs( temp )>=abs( temp2r )+abs( temp2i ) ) then work( 2_${ik}$*n+je ) = one work( 3_${ik}$*n+je ) = zero work( 2_${ik}$*n+je-1 ) = -temp2r / temp work( 3_${ik}$*n+je-1 ) = -temp2i / temp else work( 2_${ik}$*n+je-1 ) = one work( 3_${ik}$*n+je-1 ) = zero temp = acoef*s( je-1, je ) work( 2_${ik}$*n+je ) = ( bcoefr*p( je-1, je-1 )-acoef*s( je-1, je-1 ) ) / & temp work( 3_${ik}$*n+je ) = bcoefi*p( je-1, je-1 ) / temp end if xmax = max( abs( work( 2_${ik}$*n+je ) )+abs( work( 3_${ik}$*n+je ) ),abs( work( 2_${ik}$*n+je-1 ) & )+abs( work( 3_${ik}$*n+je-1 ) ) ) ! compute contribution from columns je and je-1 ! of a and b to the sums. creala = acoef*work( 2_${ik}$*n+je-1 ) cimaga = acoef*work( 3_${ik}$*n+je-1 ) crealb = bcoefr*work( 2_${ik}$*n+je-1 ) -bcoefi*work( 3_${ik}$*n+je-1 ) cimagb = bcoefi*work( 2_${ik}$*n+je-1 ) +bcoefr*work( 3_${ik}$*n+je-1 ) cre2a = acoef*work( 2_${ik}$*n+je ) cim2a = acoef*work( 3_${ik}$*n+je ) cre2b = bcoefr*work( 2_${ik}$*n+je ) - bcoefi*work( 3_${ik}$*n+je ) cim2b = bcoefi*work( 2_${ik}$*n+je ) + bcoefr*work( 3_${ik}$*n+je ) do jr = 1, je - 2 work( 2_${ik}$*n+jr ) = -creala*s( jr, je-1 ) +crealb*p( jr, je-1 ) -cre2a*s( jr, & je ) + cre2b*p( jr, je ) work( 3_${ik}$*n+jr ) = -cimaga*s( jr, je-1 ) +cimagb*p( jr, je-1 ) -cim2a*s( jr, & je ) + cim2b*p( jr, je ) end do end if dmin = max( ulp*acoefa*anorm, ulp*bcoefa*bnorm, safmin ) ! columnwise triangular solve of (a a - b b) x = 0 il2by2 = .false. loop_370: do j = je - nw, 1, -1 ! if a 2-by-2 block, is in position j-1:j, wait until ! next iteration to process it (when it will be j:j+1) if( .not.il2by2 .and. j>1_${ik}$ ) then if( s( j, j-1 )/=zero ) then il2by2 = .true. cycle loop_370 end if end if bdiag( 1_${ik}$ ) = p( j, j ) if( il2by2 ) then na = 2_${ik}$ bdiag( 2_${ik}$ ) = p( j+1, j+1 ) else na = 1_${ik}$ end if ! compute x(j) (and x(j+1), if 2-by-2 block) call stdlib${ii}$_dlaln2( .false., na, nw, dmin, acoef, s( j, j ),lds, bdiag( 1_${ik}$ ), & bdiag( 2_${ik}$ ), work( 2_${ik}$*n+j ),n, bcoefr, bcoefi, sum, 2_${ik}$, scale, temp,iinfo ) if( scale1_${ik}$ ) then ! check whether scaling is necessary for sum. xscale = one / max( one, xmax ) temp = acoefa*work( j ) + bcoefa*work( n+j ) if( il2by2 )temp = max( temp, acoefa*work( j+1 )+bcoefa*work( n+j+1 ) ) temp = max( temp, acoefa, bcoefa ) if( temp>bignum*xscale ) then do jw = 0, nw - 1 do jr = 1, je work( ( jw+2 )*n+jr ) = xscale*work( ( jw+2 )*n+jr ) end do end do xmax = xmax*xscale end if ! compute the contributions of the off-diagonals of ! column j (and j+1, if 2-by-2 block) of a and b to the ! sums. do ja = 1, na if( ilcplx ) then creala = acoef*work( 2_${ik}$*n+j+ja-1 ) cimaga = acoef*work( 3_${ik}$*n+j+ja-1 ) crealb = bcoefr*work( 2_${ik}$*n+j+ja-1 ) -bcoefi*work( 3_${ik}$*n+j+ja-1 ) cimagb = bcoefi*work( 2_${ik}$*n+j+ja-1 ) +bcoefr*work( 3_${ik}$*n+j+ja-1 ) do jr = 1, j - 1 work( 2_${ik}$*n+jr ) = work( 2_${ik}$*n+jr ) -creala*s( jr, j+ja-1 ) +crealb*p(& jr, j+ja-1 ) work( 3_${ik}$*n+jr ) = work( 3_${ik}$*n+jr ) -cimaga*s( jr, j+ja-1 ) +cimagb*p(& jr, j+ja-1 ) end do else creala = acoef*work( 2_${ik}$*n+j+ja-1 ) crealb = bcoefr*work( 2_${ik}$*n+j+ja-1 ) do jr = 1, j - 1 work( 2_${ik}$*n+jr ) = work( 2_${ik}$*n+jr ) -creala*s( jr, j+ja-1 ) +crealb*p(& jr, j+ja-1 ) end do end if end do end if il2by2 = .false. end do loop_370 ! copy eigenvector to vr, back transforming if ! howmny='b'. ieig = ieig - nw if( ilback ) then do jw = 0, nw - 1 do jr = 1, n work( ( jw+4 )*n+jr ) = work( ( jw+2 )*n+1 )*vr( jr, 1_${ik}$ ) end do ! a series of compiler directives to defeat ! vectorization for the next loop do jc = 2, je do jr = 1, n work( ( jw+4 )*n+jr ) = work( ( jw+4 )*n+jr ) +work( ( jw+2 )*n+jc )& *vr( jr, jc ) end do end do end do do jw = 0, nw - 1 do jr = 1, n vr( jr, ieig+jw ) = work( ( jw+4 )*n+jr ) end do end do iend = n else do jw = 0, nw - 1 do jr = 1, n vr( jr, ieig+jw ) = work( ( jw+2 )*n+jr ) end do end do iend = je end if ! scale eigenvector xmax = zero if( ilcplx ) then do j = 1, iend xmax = max( xmax, abs( vr( j, ieig ) )+abs( vr( j, ieig+1 ) ) ) end do else do j = 1, iend xmax = max( xmax, abs( vr( j, ieig ) ) ) end do end if if( xmax>safmin ) then xscale = one / xmax do jw = 0, nw - 1 do jr = 1, iend vr( jr, ieig+jw ) = xscale*vr( jr, ieig+jw ) end do end do end if end do loop_500 end if return end subroutine stdlib${ii}$_dtgevc #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tgevc( side, howmny, select, n, s, lds, p, ldp, vl,ldvl, vr, ldvr, & !! DTGEVC: computes some or all of the right and/or left eigenvectors of !! a pair of real matrices (S,P), where S is a quasi-triangular matrix !! and P is upper triangular. Matrix pairs of this type are produced by !! the generalized Schur factorization of a matrix pair (A,B): !! A = Q*S*Z**T, B = Q*P*Z**T !! as computed by DGGHRD + DHGEQZ. !! The right eigenvector x and the left eigenvector y of (S,P) !! corresponding to an eigenvalue w are defined by: !! S*x = w*P*x, (y**H)*S = w*(y**H)*P, !! where y**H denotes the conjugate tranpose of y. !! The eigenvalues are not input to this routine, but are computed !! directly from the diagonal blocks of S and P. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of (S,P), or the products Z*X and/or Q*Y, !! where Z and Q are input matrices. !! If Q and Z are the orthogonal factors from the generalized Schur !! factorization of a matrix pair (A,B), then Z*X and Q*Y !! are the matrices of right and left eigenvectors of (A,B). mm, m, work, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: howmny, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldp, lds, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(in) :: select(*) real(${rk}$), intent(in) :: p(ldp,*), s(lds,*) real(${rk}$), intent(inout) :: vl(ldvl,*), vr(ldvr,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Parameters real(${rk}$), parameter :: safety = 1.0e+2_${rk}$ ! Local Scalars logical(lk) :: compl, compr, il2by2, ilabad, ilall, ilback, ilbbad, ilcomp, ilcplx, & lsa, lsb integer(${ik}$) :: i, ibeg, ieig, iend, ihwmny, iinfo, im, iside, j, ja, jc, je, jr, jw, & na, nw real(${rk}$) :: acoef, acoefa, anorm, ascale, bcoefa, bcoefi, bcoefr, big, bignum, bnorm, & bscale, cim2a, cim2b, cimaga, cimagb, cre2a, cre2b, creala, crealb, dmin, safmin, & salfar, sbeta, scale, small, temp, temp2, temp2i, temp2r, ulp, xmax, xscale ! Local Arrays real(${rk}$) :: bdiag(2_${ik}$), sum(2_${ik}$,2_${ik}$), sums(2_${ik}$,2_${ik}$), sump(2_${ik}$,2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode and test the input parameters if( stdlib_lsame( howmny, 'A' ) ) then ihwmny = 1_${ik}$ ilall = .true. ilback = .false. else if( stdlib_lsame( howmny, 'S' ) ) then ihwmny = 2_${ik}$ ilall = .false. ilback = .false. else if( stdlib_lsame( howmny, 'B' ) ) then ihwmny = 3_${ik}$ ilall = .true. ilback = .true. else ihwmny = -1_${ik}$ ilall = .true. end if if( stdlib_lsame( side, 'R' ) ) then iside = 1_${ik}$ compl = .false. compr = .true. else if( stdlib_lsame( side, 'L' ) ) then iside = 2_${ik}$ compl = .true. compr = .false. else if( stdlib_lsame( side, 'B' ) ) then iside = 3_${ik}$ compl = .true. compr = .true. else iside = -1_${ik}$ end if info = 0_${ik}$ if( iside<0_${ik}$ ) then info = -1_${ik}$ else if( ihwmny<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lds1_${ik}$ )anorm = anorm + abs( s( 2_${ik}$, 1_${ik}$ ) ) bnorm = abs( p( 1_${ik}$, 1_${ik}$ ) ) work( 1_${ik}$ ) = zero work( n+1 ) = zero do j = 2, n temp = zero temp2 = zero if( s( j, j-1 )==zero ) then iend = j - 1_${ik}$ else iend = j - 2_${ik}$ end if do i = 1, iend temp = temp + abs( s( i, j ) ) temp2 = temp2 + abs( p( i, j ) ) end do work( j ) = temp work( n+j ) = temp2 do i = iend + 1, min( j+1, n ) temp = temp + abs( s( i, j ) ) temp2 = temp2 + abs( p( i, j ) ) end do anorm = max( anorm, temp ) bnorm = max( bnorm, temp2 ) end do ascale = one / max( anorm, safmin ) bscale = one / max( bnorm, safmin ) ! left eigenvectors if( compl ) then ieig = 0_${ik}$ ! main loop over eigenvalues ilcplx = .false. loop_220: do je = 1, n ! skip this iteration if (a) howmny='s' and select=.false., or ! (b) this would be the second of a complex pair. ! check for complex eigenvalue, so as to be sure of which ! entry(-ies) of select to look at. if( ilcplx ) then ilcplx = .false. cycle loop_220 end if nw = 1_${ik}$ if( je=safmin .and. abs( acoef )=safmin .and. abs( bcoefr )=safmin )scale = ( safmin / ulp ) / & acoefa if( bcoefa*ulp=safmin )scale = max( scale, ( safmin / & ulp ) / bcoefa ) if( safmin*acoefa>ascale )scale = ascale / ( safmin*acoefa ) if( safmin*bcoefa>bscale )scale = min( scale, bscale / ( safmin*bcoefa ) ) if( scale/=one ) then acoef = scale*acoef acoefa = abs( acoef ) bcoefr = scale*bcoefr bcoefi = scale*bcoefi bcoefa = abs( bcoefr ) + abs( bcoefi ) end if ! compute first two components of eigenvector temp = acoef*s( je+1, je ) temp2r = acoef*s( je, je ) - bcoefr*p( je, je ) temp2i = -bcoefi*p( je, je ) if( abs( temp )>abs( temp2r )+abs( temp2i ) ) then work( 2_${ik}$*n+je ) = one work( 3_${ik}$*n+je ) = zero work( 2_${ik}$*n+je+1 ) = -temp2r / temp work( 3_${ik}$*n+je+1 ) = -temp2i / temp else work( 2_${ik}$*n+je+1 ) = one work( 3_${ik}$*n+je+1 ) = zero temp = acoef*s( je, je+1 ) work( 2_${ik}$*n+je ) = ( bcoefr*p( je+1, je+1 )-acoef*s( je+1, je+1 ) ) / & temp work( 3_${ik}$*n+je ) = bcoefi*p( je+1, je+1 ) / temp end if xmax = max( abs( work( 2_${ik}$*n+je ) )+abs( work( 3_${ik}$*n+je ) ),abs( work( 2_${ik}$*n+je+1 ) & )+abs( work( 3_${ik}$*n+je+1 ) ) ) end if dmin = max( ulp*acoefa*anorm, ulp*bcoefa*bnorm, safmin ) ! t ! triangular solve of (a a - b b) y = 0 ! t ! (rowwise in (a a - b b) , or columnwise in (a a - b b) ) il2by2 = .false. loop_160: do j = je + nw, n if( il2by2 ) then il2by2 = .false. cycle loop_160 end if na = 1_${ik}$ bdiag( 1_${ik}$ ) = p( j, j ) if( jbignum*xscale ) then do jw = 0, nw - 1 do jr = je, j - 1 work( ( jw+2 )*n+jr ) = xscale*work( ( jw+2 )*n+jr ) end do end do xmax = xmax*xscale end if ! compute dot products ! j-1 ! sum = sum conjg( a*s(k,j) - b*p(k,j) )*x(k) ! k=je ! to reduce the op count, this is done as ! _ j-1 _ j-1 ! a*conjg( sum s(k,j)*x(k) ) - b*conjg( sum p(k,j)*x(k) ) ! k=je k=je ! which may cause underflow problems if a or b are close ! to underflow. (e.g., less than small.) do jw = 1, nw do ja = 1, na sums( ja, jw ) = zero sump( ja, jw ) = zero do jr = je, j - 1 sums( ja, jw ) = sums( ja, jw ) +s( jr, j+ja-1 )*work( ( jw+1 )*n+jr & ) sump( ja, jw ) = sump( ja, jw ) +p( jr, j+ja-1 )*work( ( jw+1 )*n+jr & ) end do end do end do do ja = 1, na if( ilcplx ) then sum( ja, 1_${ik}$ ) = -acoef*sums( ja, 1_${ik}$ ) +bcoefr*sump( ja, 1_${ik}$ ) -bcoefi*sump( & ja, 2_${ik}$ ) sum( ja, 2_${ik}$ ) = -acoef*sums( ja, 2_${ik}$ ) +bcoefr*sump( ja, 2_${ik}$ ) +bcoefi*sump( & ja, 1_${ik}$ ) else sum( ja, 1_${ik}$ ) = -acoef*sums( ja, 1_${ik}$ ) +bcoefr*sump( ja, 1_${ik}$ ) end if end do ! t ! solve ( a a - b b ) y = sum(,) ! with scaling and perturbation of the denominator call stdlib${ii}$_${ri}$laln2( .true., na, nw, dmin, acoef, s( j, j ), lds,bdiag( 1_${ik}$ ), & bdiag( 2_${ik}$ ), sum, 2_${ik}$, bcoefr,bcoefi, work( 2_${ik}$*n+j ), n, scale, temp,iinfo ) if( scalesafmin ) then xscale = one / xmax do jw = 0, nw - 1 do jr = ibeg, n vl( jr, ieig+jw ) = xscale*vl( jr, ieig+jw ) end do end do end if ieig = ieig + nw - 1_${ik}$ end do loop_220 end if ! right eigenvectors if( compr ) then ieig = im + 1_${ik}$ ! main loop over eigenvalues ilcplx = .false. loop_500: do je = n, 1, -1 ! skip this iteration if (a) howmny='s' and select=.false., or ! (b) this would be the second of a complex pair. ! check for complex eigenvalue, so as to be sure of which ! entry(-ies) of select to look at -- if complex, select(je) ! or select(je-1). ! if this is a complex pair, the 2-by-2 diagonal block ! corresponding to the eigenvalue is in rows/columns je-1:je if( ilcplx ) then ilcplx = .false. cycle loop_500 end if nw = 1_${ik}$ if( je>1_${ik}$ ) then if( s( je, je-1 )/=zero ) then ilcplx = .true. nw = 2_${ik}$ end if end if if( ilall ) then ilcomp = .true. else if( ilcplx ) then ilcomp = select( je ) .or. select( je-1 ) else ilcomp = select( je ) end if if( .not.ilcomp )cycle loop_500 ! decide if (a) singular pencil, (b) real eigenvalue, or ! (c) complex eigenvalue. if( .not.ilcplx ) then if( abs( s( je, je ) )<=safmin .and.abs( p( je, je ) )<=safmin ) then ! singular matrix pencil -- unit eigenvector ieig = ieig - 1_${ik}$ do jr = 1, n vr( jr, ieig ) = zero end do vr( ieig, ieig ) = one cycle loop_500 end if end if ! clear vector do jw = 0, nw - 1 do jr = 1, n work( ( jw+2 )*n+jr ) = zero end do end do ! compute coefficients in ( a a - b b ) x = 0 ! a is acoef ! b is bcoefr + i*bcoefi if( .not.ilcplx ) then ! real eigenvalue temp = one / max( abs( s( je, je ) )*ascale,abs( p( je, je ) )*bscale, safmin & ) salfar = ( temp*s( je, je ) )*ascale sbeta = ( temp*p( je, je ) )*bscale acoef = sbeta*ascale bcoefr = salfar*bscale bcoefi = zero ! scale to avoid underflow scale = one lsa = abs( sbeta )>=safmin .and. abs( acoef )=safmin .and. abs( bcoefr )=safmin )scale = ( safmin / ulp ) / & acoefa if( bcoefa*ulp=safmin )scale = max( scale, ( safmin / & ulp ) / bcoefa ) if( safmin*acoefa>ascale )scale = ascale / ( safmin*acoefa ) if( safmin*bcoefa>bscale )scale = min( scale, bscale / ( safmin*bcoefa ) ) if( scale/=one ) then acoef = scale*acoef acoefa = abs( acoef ) bcoefr = scale*bcoefr bcoefi = scale*bcoefi bcoefa = abs( bcoefr ) + abs( bcoefi ) end if ! compute first two components of eigenvector ! and contribution to sums temp = acoef*s( je, je-1 ) temp2r = acoef*s( je, je ) - bcoefr*p( je, je ) temp2i = -bcoefi*p( je, je ) if( abs( temp )>=abs( temp2r )+abs( temp2i ) ) then work( 2_${ik}$*n+je ) = one work( 3_${ik}$*n+je ) = zero work( 2_${ik}$*n+je-1 ) = -temp2r / temp work( 3_${ik}$*n+je-1 ) = -temp2i / temp else work( 2_${ik}$*n+je-1 ) = one work( 3_${ik}$*n+je-1 ) = zero temp = acoef*s( je-1, je ) work( 2_${ik}$*n+je ) = ( bcoefr*p( je-1, je-1 )-acoef*s( je-1, je-1 ) ) / & temp work( 3_${ik}$*n+je ) = bcoefi*p( je-1, je-1 ) / temp end if xmax = max( abs( work( 2_${ik}$*n+je ) )+abs( work( 3_${ik}$*n+je ) ),abs( work( 2_${ik}$*n+je-1 ) & )+abs( work( 3_${ik}$*n+je-1 ) ) ) ! compute contribution from columns je and je-1 ! of a and b to the sums. creala = acoef*work( 2_${ik}$*n+je-1 ) cimaga = acoef*work( 3_${ik}$*n+je-1 ) crealb = bcoefr*work( 2_${ik}$*n+je-1 ) -bcoefi*work( 3_${ik}$*n+je-1 ) cimagb = bcoefi*work( 2_${ik}$*n+je-1 ) +bcoefr*work( 3_${ik}$*n+je-1 ) cre2a = acoef*work( 2_${ik}$*n+je ) cim2a = acoef*work( 3_${ik}$*n+je ) cre2b = bcoefr*work( 2_${ik}$*n+je ) - bcoefi*work( 3_${ik}$*n+je ) cim2b = bcoefi*work( 2_${ik}$*n+je ) + bcoefr*work( 3_${ik}$*n+je ) do jr = 1, je - 2 work( 2_${ik}$*n+jr ) = -creala*s( jr, je-1 ) +crealb*p( jr, je-1 ) -cre2a*s( jr, & je ) + cre2b*p( jr, je ) work( 3_${ik}$*n+jr ) = -cimaga*s( jr, je-1 ) +cimagb*p( jr, je-1 ) -cim2a*s( jr, & je ) + cim2b*p( jr, je ) end do end if dmin = max( ulp*acoefa*anorm, ulp*bcoefa*bnorm, safmin ) ! columnwise triangular solve of (a a - b b) x = 0 il2by2 = .false. loop_370: do j = je - nw, 1, -1 ! if a 2-by-2 block, is in position j-1:j, wait until ! next iteration to process it (when it will be j:j+1) if( .not.il2by2 .and. j>1_${ik}$ ) then if( s( j, j-1 )/=zero ) then il2by2 = .true. cycle loop_370 end if end if bdiag( 1_${ik}$ ) = p( j, j ) if( il2by2 ) then na = 2_${ik}$ bdiag( 2_${ik}$ ) = p( j+1, j+1 ) else na = 1_${ik}$ end if ! compute x(j) (and x(j+1), if 2-by-2 block) call stdlib${ii}$_${ri}$laln2( .false., na, nw, dmin, acoef, s( j, j ),lds, bdiag( 1_${ik}$ ), & bdiag( 2_${ik}$ ), work( 2_${ik}$*n+j ),n, bcoefr, bcoefi, sum, 2_${ik}$, scale, temp,iinfo ) if( scale1_${ik}$ ) then ! check whether scaling is necessary for sum. xscale = one / max( one, xmax ) temp = acoefa*work( j ) + bcoefa*work( n+j ) if( il2by2 )temp = max( temp, acoefa*work( j+1 )+bcoefa*work( n+j+1 ) ) temp = max( temp, acoefa, bcoefa ) if( temp>bignum*xscale ) then do jw = 0, nw - 1 do jr = 1, je work( ( jw+2 )*n+jr ) = xscale*work( ( jw+2 )*n+jr ) end do end do xmax = xmax*xscale end if ! compute the contributions of the off-diagonals of ! column j (and j+1, if 2-by-2 block) of a and b to the ! sums. do ja = 1, na if( ilcplx ) then creala = acoef*work( 2_${ik}$*n+j+ja-1 ) cimaga = acoef*work( 3_${ik}$*n+j+ja-1 ) crealb = bcoefr*work( 2_${ik}$*n+j+ja-1 ) -bcoefi*work( 3_${ik}$*n+j+ja-1 ) cimagb = bcoefi*work( 2_${ik}$*n+j+ja-1 ) +bcoefr*work( 3_${ik}$*n+j+ja-1 ) do jr = 1, j - 1 work( 2_${ik}$*n+jr ) = work( 2_${ik}$*n+jr ) -creala*s( jr, j+ja-1 ) +crealb*p(& jr, j+ja-1 ) work( 3_${ik}$*n+jr ) = work( 3_${ik}$*n+jr ) -cimaga*s( jr, j+ja-1 ) +cimagb*p(& jr, j+ja-1 ) end do else creala = acoef*work( 2_${ik}$*n+j+ja-1 ) crealb = bcoefr*work( 2_${ik}$*n+j+ja-1 ) do jr = 1, j - 1 work( 2_${ik}$*n+jr ) = work( 2_${ik}$*n+jr ) -creala*s( jr, j+ja-1 ) +crealb*p(& jr, j+ja-1 ) end do end if end do end if il2by2 = .false. end do loop_370 ! copy eigenvector to vr, back transforming if ! howmny='b'. ieig = ieig - nw if( ilback ) then do jw = 0, nw - 1 do jr = 1, n work( ( jw+4 )*n+jr ) = work( ( jw+2 )*n+1 )*vr( jr, 1_${ik}$ ) end do ! a series of compiler directives to defeat ! vectorization for the next loop do jc = 2, je do jr = 1, n work( ( jw+4 )*n+jr ) = work( ( jw+4 )*n+jr ) +work( ( jw+2 )*n+jc )& *vr( jr, jc ) end do end do end do do jw = 0, nw - 1 do jr = 1, n vr( jr, ieig+jw ) = work( ( jw+4 )*n+jr ) end do end do iend = n else do jw = 0, nw - 1 do jr = 1, n vr( jr, ieig+jw ) = work( ( jw+2 )*n+jr ) end do end do iend = je end if ! scale eigenvector xmax = zero if( ilcplx ) then do j = 1, iend xmax = max( xmax, abs( vr( j, ieig ) )+abs( vr( j, ieig+1 ) ) ) end do else do j = 1, iend xmax = max( xmax, abs( vr( j, ieig ) ) ) end do end if if( xmax>safmin ) then xscale = one / xmax do jw = 0, nw - 1 do jr = 1, iend vr( jr, ieig+jw ) = xscale*vr( jr, ieig+jw ) end do end do end if end do loop_500 end if return end subroutine stdlib${ii}$_${ri}$tgevc #:endif #:endfor pure module subroutine stdlib${ii}$_ctgevc( side, howmny, select, n, s, lds, p, ldp, vl,ldvl, vr, ldvr, & !! CTGEVC computes some or all of the right and/or left eigenvectors of !! a pair of complex matrices (S,P), where S and P are upper triangular. !! Matrix pairs of this type are produced by the generalized Schur !! factorization of a complex matrix pair (A,B): !! A = Q*S*Z**H, B = Q*P*Z**H !! as computed by CGGHRD + CHGEQZ. !! The right eigenvector x and the left eigenvector y of (S,P) !! corresponding to an eigenvalue w are defined by: !! S*x = w*P*x, (y**H)*S = w*(y**H)*P, !! where y**H denotes the conjugate tranpose of y. !! The eigenvalues are not input to this routine, but are computed !! directly from the diagonal elements of S and P. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of (S,P), or the products Z*X and/or Q*Y, !! where Z and Q are input matrices. !! If Q and Z are the unitary factors from the generalized Schur !! factorization of a matrix pair (A,B), then Z*X and Q*Y !! are the matrices of right and left eigenvectors of (A,B). mm, m, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: howmny, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldp, lds, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(in) :: select(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(in) :: p(ldp,*), s(lds,*) complex(sp), intent(inout) :: vl(ldvl,*), vr(ldvr,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: compl, compr, ilall, ilback, ilbbad, ilcomp, lsa, lsb integer(${ik}$) :: i, ibeg, ieig, iend, ihwmny, im, iside, isrc, j, je, jr real(sp) :: acoefa, acoeff, anorm, ascale, bcoefa, big, bignum, bnorm, bscale, dmin, & safmin, sbeta, scale, small, temp, ulp, xmax complex(sp) :: bcoeff, ca, cb, d, salpha, sum, suma, sumb, x ! Intrinsic Functions ! Statement Functions real(sp) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=sp) ) + abs( aimag( x ) ) ! Executable Statements ! decode and test the input parameters if( stdlib_lsame( howmny, 'A' ) ) then ihwmny = 1_${ik}$ ilall = .true. ilback = .false. else if( stdlib_lsame( howmny, 'S' ) ) then ihwmny = 2_${ik}$ ilall = .false. ilback = .false. else if( stdlib_lsame( howmny, 'B' ) ) then ihwmny = 3_${ik}$ ilall = .true. ilback = .true. else ihwmny = -1_${ik}$ end if if( stdlib_lsame( side, 'R' ) ) then iside = 1_${ik}$ compl = .false. compr = .true. else if( stdlib_lsame( side, 'L' ) ) then iside = 2_${ik}$ compl = .true. compr = .false. else if( stdlib_lsame( side, 'B' ) ) then iside = 3_${ik}$ compl = .true. compr = .true. else iside = -1_${ik}$ end if info = 0_${ik}$ if( iside<0_${ik}$ ) then info = -1_${ik}$ else if( ihwmny<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lds=safmin .and. abs( acoeff )=safmin .and. abs1( bcoeff )bignum*temp ) then do jr = je, j - 1 work( jr ) = temp*work( jr ) end do xmax = one end if suma = czero sumb = czero do jr = je, j - 1 suma = suma + conjg( s( jr, j ) )*work( jr ) sumb = sumb + conjg( p( jr, j ) )*work( jr ) end do sum = acoeff*suma - conjg( bcoeff )*sumb ! form x(j) = - sum / conjg( a*s(j,j) - b*p(j,j) ) ! with scaling and perturbation of the denominator d = conjg( acoeff*s( j, j )-bcoeff*p( j, j ) ) if( abs1( d )<=dmin )d = cmplx( dmin,KIND=sp) if( abs1( d )=bignum*abs1( d ) ) then temp = one / abs1( sum ) do jr = je, j - 1 work( jr ) = temp*work( jr ) end do xmax = temp*xmax sum = temp*sum end if end if work( j ) = stdlib${ii}$_cladiv( -sum, d ) xmax = max( xmax, abs1( work( j ) ) ) end do loop_100 ! back transform eigenvector if howmny='b'. if( ilback ) then call stdlib${ii}$_cgemv( 'N', n, n+1-je, cone, vl( 1_${ik}$, je ), ldvl,work( je ), 1_${ik}$, & czero, work( n+1 ), 1_${ik}$ ) isrc = 2_${ik}$ ibeg = 1_${ik}$ else isrc = 1_${ik}$ ibeg = je end if ! copy and scale eigenvector into column of vl xmax = zero do jr = ibeg, n xmax = max( xmax, abs1( work( ( isrc-1 )*n+jr ) ) ) end do if( xmax>safmin ) then temp = one / xmax do jr = ibeg, n vl( jr, ieig ) = temp*work( ( isrc-1 )*n+jr ) end do else ibeg = n + 1_${ik}$ end if do jr = 1, ibeg - 1 vl( jr, ieig ) = czero end do end if end do loop_140 end if ! right eigenvectors if( compr ) then ieig = im + 1_${ik}$ ! main loop over eigenvalues loop_250: do je = n, 1, -1 if( ilall ) then ilcomp = .true. else ilcomp = select( je ) end if if( ilcomp ) then ieig = ieig - 1_${ik}$ if( abs1( s( je, je ) )<=safmin .and.abs( real( p( je, je ),KIND=sp) )& <=safmin ) then ! singular matrix pencil -- return unit eigenvector do jr = 1, n vr( jr, ieig ) = czero end do vr( ieig, ieig ) = cone cycle loop_250 end if ! non-singular eigenvalue: ! compute coefficients a and b in ! ( a a - b b ) x = 0 temp = one / max( abs1( s( je, je ) )*ascale,abs( real( p( je, je ),KIND=sp) )& *bscale, safmin ) salpha = ( temp*s( je, je ) )*ascale sbeta = ( temp*real( p( je, je ),KIND=sp) )*bscale acoeff = sbeta*ascale bcoeff = salpha*bscale ! scale to avoid underflow lsa = abs( sbeta )>=safmin .and. abs( acoeff )=safmin .and. abs1( bcoeff )=bignum*abs1( d ) ) then temp = one / abs1( work( j ) ) do jr = 1, je work( jr ) = temp*work( jr ) end do end if end if work( j ) = stdlib${ii}$_cladiv( -work( j ), d ) if( j>1_${ik}$ ) then ! w = w + x(j)*(a s(*,j) - b p(*,j) ) with scaling if( abs1( work( j ) )>one ) then temp = one / abs1( work( j ) ) if( acoefa*rwork( j )+bcoefa*rwork( n+j )>=bignum*temp ) then do jr = 1, je work( jr ) = temp*work( jr ) end do end if end if ca = acoeff*work( j ) cb = bcoeff*work( j ) do jr = 1, j - 1 work( jr ) = work( jr ) + ca*s( jr, j ) -cb*p( jr, j ) end do end if end do loop_210 ! back transform eigenvector if howmny='b'. if( ilback ) then call stdlib${ii}$_cgemv( 'N', n, je, cone, vr, ldvr, work, 1_${ik}$,czero, work( n+1 ), & 1_${ik}$ ) isrc = 2_${ik}$ iend = n else isrc = 1_${ik}$ iend = je end if ! copy and scale eigenvector into column of vr xmax = zero do jr = 1, iend xmax = max( xmax, abs1( work( ( isrc-1 )*n+jr ) ) ) end do if( xmax>safmin ) then temp = one / xmax do jr = 1, iend vr( jr, ieig ) = temp*work( ( isrc-1 )*n+jr ) end do else iend = 0_${ik}$ end if do jr = iend + 1, n vr( jr, ieig ) = czero end do end if end do loop_250 end if return end subroutine stdlib${ii}$_ctgevc pure module subroutine stdlib${ii}$_ztgevc( side, howmny, select, n, s, lds, p, ldp, vl,ldvl, vr, ldvr, & !! ZTGEVC computes some or all of the right and/or left eigenvectors of !! a pair of complex matrices (S,P), where S and P are upper triangular. !! Matrix pairs of this type are produced by the generalized Schur !! factorization of a complex matrix pair (A,B): !! A = Q*S*Z**H, B = Q*P*Z**H !! as computed by ZGGHRD + ZHGEQZ. !! The right eigenvector x and the left eigenvector y of (S,P) !! corresponding to an eigenvalue w are defined by: !! S*x = w*P*x, (y**H)*S = w*(y**H)*P, !! where y**H denotes the conjugate tranpose of y. !! The eigenvalues are not input to this routine, but are computed !! directly from the diagonal elements of S and P. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of (S,P), or the products Z*X and/or Q*Y, !! where Z and Q are input matrices. !! If Q and Z are the unitary factors from the generalized Schur !! factorization of a matrix pair (A,B), then Z*X and Q*Y !! are the matrices of right and left eigenvectors of (A,B). mm, m, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: howmny, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldp, lds, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(in) :: select(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(in) :: p(ldp,*), s(lds,*) complex(dp), intent(inout) :: vl(ldvl,*), vr(ldvr,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: compl, compr, ilall, ilback, ilbbad, ilcomp, lsa, lsb integer(${ik}$) :: i, ibeg, ieig, iend, ihwmny, im, iside, isrc, j, je, jr real(dp) :: acoefa, acoeff, anorm, ascale, bcoefa, big, bignum, bnorm, bscale, dmin, & safmin, sbeta, scale, small, temp, ulp, xmax complex(dp) :: bcoeff, ca, cb, d, salpha, sum, suma, sumb, x ! Intrinsic Functions ! Statement Functions real(dp) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=dp) ) + abs( aimag( x ) ) ! Executable Statements ! decode and test the input parameters if( stdlib_lsame( howmny, 'A' ) ) then ihwmny = 1_${ik}$ ilall = .true. ilback = .false. else if( stdlib_lsame( howmny, 'S' ) ) then ihwmny = 2_${ik}$ ilall = .false. ilback = .false. else if( stdlib_lsame( howmny, 'B' ) ) then ihwmny = 3_${ik}$ ilall = .true. ilback = .true. else ihwmny = -1_${ik}$ end if if( stdlib_lsame( side, 'R' ) ) then iside = 1_${ik}$ compl = .false. compr = .true. else if( stdlib_lsame( side, 'L' ) ) then iside = 2_${ik}$ compl = .true. compr = .false. else if( stdlib_lsame( side, 'B' ) ) then iside = 3_${ik}$ compl = .true. compr = .true. else iside = -1_${ik}$ end if info = 0_${ik}$ if( iside<0_${ik}$ ) then info = -1_${ik}$ else if( ihwmny<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lds=safmin .and. abs( acoeff )=safmin .and. abs1( bcoeff )bignum*temp ) then do jr = je, j - 1 work( jr ) = temp*work( jr ) end do xmax = one end if suma = czero sumb = czero do jr = je, j - 1 suma = suma + conjg( s( jr, j ) )*work( jr ) sumb = sumb + conjg( p( jr, j ) )*work( jr ) end do sum = acoeff*suma - conjg( bcoeff )*sumb ! form x(j) = - sum / conjg( a*s(j,j) - b*p(j,j) ) ! with scaling and perturbation of the denominator d = conjg( acoeff*s( j, j )-bcoeff*p( j, j ) ) if( abs1( d )<=dmin )d = cmplx( dmin,KIND=dp) if( abs1( d )=bignum*abs1( d ) ) then temp = one / abs1( sum ) do jr = je, j - 1 work( jr ) = temp*work( jr ) end do xmax = temp*xmax sum = temp*sum end if end if work( j ) = stdlib${ii}$_zladiv( -sum, d ) xmax = max( xmax, abs1( work( j ) ) ) end do loop_100 ! back transform eigenvector if howmny='b'. if( ilback ) then call stdlib${ii}$_zgemv( 'N', n, n+1-je, cone, vl( 1_${ik}$, je ), ldvl,work( je ), 1_${ik}$, & czero, work( n+1 ), 1_${ik}$ ) isrc = 2_${ik}$ ibeg = 1_${ik}$ else isrc = 1_${ik}$ ibeg = je end if ! copy and scale eigenvector into column of vl xmax = zero do jr = ibeg, n xmax = max( xmax, abs1( work( ( isrc-1 )*n+jr ) ) ) end do if( xmax>safmin ) then temp = one / xmax do jr = ibeg, n vl( jr, ieig ) = temp*work( ( isrc-1 )*n+jr ) end do else ibeg = n + 1_${ik}$ end if do jr = 1, ibeg - 1 vl( jr, ieig ) = czero end do end if end do loop_140 end if ! right eigenvectors if( compr ) then ieig = im + 1_${ik}$ ! main loop over eigenvalues loop_250: do je = n, 1, -1 if( ilall ) then ilcomp = .true. else ilcomp = select( je ) end if if( ilcomp ) then ieig = ieig - 1_${ik}$ if( abs1( s( je, je ) )<=safmin .and.abs( real( p( je, je ),KIND=dp) )& <=safmin ) then ! singular matrix pencil -- return unit eigenvector do jr = 1, n vr( jr, ieig ) = czero end do vr( ieig, ieig ) = cone cycle loop_250 end if ! non-singular eigenvalue: ! compute coefficients a and b in ! ( a a - b b ) x = 0 temp = one / max( abs1( s( je, je ) )*ascale,abs( real( p( je, je ),KIND=dp) )& *bscale, safmin ) salpha = ( temp*s( je, je ) )*ascale sbeta = ( temp*real( p( je, je ),KIND=dp) )*bscale acoeff = sbeta*ascale bcoeff = salpha*bscale ! scale to avoid underflow lsa = abs( sbeta )>=safmin .and. abs( acoeff )=safmin .and. abs1( bcoeff )=bignum*abs1( d ) ) then temp = one / abs1( work( j ) ) do jr = 1, je work( jr ) = temp*work( jr ) end do end if end if work( j ) = stdlib${ii}$_zladiv( -work( j ), d ) if( j>1_${ik}$ ) then ! w = w + x(j)*(a s(*,j) - b p(*,j) ) with scaling if( abs1( work( j ) )>one ) then temp = one / abs1( work( j ) ) if( acoefa*rwork( j )+bcoefa*rwork( n+j )>=bignum*temp ) then do jr = 1, je work( jr ) = temp*work( jr ) end do end if end if ca = acoeff*work( j ) cb = bcoeff*work( j ) do jr = 1, j - 1 work( jr ) = work( jr ) + ca*s( jr, j ) -cb*p( jr, j ) end do end if end do loop_210 ! back transform eigenvector if howmny='b'. if( ilback ) then call stdlib${ii}$_zgemv( 'N', n, je, cone, vr, ldvr, work, 1_${ik}$,czero, work( n+1 ), & 1_${ik}$ ) isrc = 2_${ik}$ iend = n else isrc = 1_${ik}$ iend = je end if ! copy and scale eigenvector into column of vr xmax = zero do jr = 1, iend xmax = max( xmax, abs1( work( ( isrc-1 )*n+jr ) ) ) end do if( xmax>safmin ) then temp = one / xmax do jr = 1, iend vr( jr, ieig ) = temp*work( ( isrc-1 )*n+jr ) end do else iend = 0_${ik}$ end if do jr = iend + 1, n vr( jr, ieig ) = czero end do end if end do loop_250 end if return end subroutine stdlib${ii}$_ztgevc #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tgevc( side, howmny, select, n, s, lds, p, ldp, vl,ldvl, vr, ldvr, & !! ZTGEVC: computes some or all of the right and/or left eigenvectors of !! a pair of complex matrices (S,P), where S and P are upper triangular. !! Matrix pairs of this type are produced by the generalized Schur !! factorization of a complex matrix pair (A,B): !! A = Q*S*Z**H, B = Q*P*Z**H !! as computed by ZGGHRD + ZHGEQZ. !! The right eigenvector x and the left eigenvector y of (S,P) !! corresponding to an eigenvalue w are defined by: !! S*x = w*P*x, (y**H)*S = w*(y**H)*P, !! where y**H denotes the conjugate tranpose of y. !! The eigenvalues are not input to this routine, but are computed !! directly from the diagonal elements of S and P. !! This routine returns the matrices X and/or Y of right and left !! eigenvectors of (S,P), or the products Z*X and/or Q*Y, !! where Z and Q are input matrices. !! If Q and Z are the unitary factors from the generalized Schur !! factorization of a matrix pair (A,B), then Z*X and Q*Y !! are the matrices of right and left eigenvectors of (A,B). mm, m, work, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: howmny, side integer(${ik}$), intent(out) :: info, m integer(${ik}$), intent(in) :: ldp, lds, ldvl, ldvr, mm, n ! Array Arguments logical(lk), intent(in) :: select(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(in) :: p(ldp,*), s(lds,*) complex(${ck}$), intent(inout) :: vl(ldvl,*), vr(ldvr,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: compl, compr, ilall, ilback, ilbbad, ilcomp, lsa, lsb integer(${ik}$) :: i, ibeg, ieig, iend, ihwmny, im, iside, isrc, j, je, jr real(${ck}$) :: acoefa, acoeff, anorm, ascale, bcoefa, big, bignum, bnorm, bscale, dmin, & safmin, sbeta, scale, small, temp, ulp, xmax complex(${ck}$) :: bcoeff, ca, cb, d, salpha, sum, suma, sumb, x ! Intrinsic Functions ! Statement Functions real(${ck}$) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=${ck}$) ) + abs( aimag( x ) ) ! Executable Statements ! decode and test the input parameters if( stdlib_lsame( howmny, 'A' ) ) then ihwmny = 1_${ik}$ ilall = .true. ilback = .false. else if( stdlib_lsame( howmny, 'S' ) ) then ihwmny = 2_${ik}$ ilall = .false. ilback = .false. else if( stdlib_lsame( howmny, 'B' ) ) then ihwmny = 3_${ik}$ ilall = .true. ilback = .true. else ihwmny = -1_${ik}$ end if if( stdlib_lsame( side, 'R' ) ) then iside = 1_${ik}$ compl = .false. compr = .true. else if( stdlib_lsame( side, 'L' ) ) then iside = 2_${ik}$ compl = .true. compr = .false. else if( stdlib_lsame( side, 'B' ) ) then iside = 3_${ik}$ compl = .true. compr = .true. else iside = -1_${ik}$ end if info = 0_${ik}$ if( iside<0_${ik}$ ) then info = -1_${ik}$ else if( ihwmny<0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lds=safmin .and. abs( acoeff )=safmin .and. abs1( bcoeff )bignum*temp ) then do jr = je, j - 1 work( jr ) = temp*work( jr ) end do xmax = one end if suma = czero sumb = czero do jr = je, j - 1 suma = suma + conjg( s( jr, j ) )*work( jr ) sumb = sumb + conjg( p( jr, j ) )*work( jr ) end do sum = acoeff*suma - conjg( bcoeff )*sumb ! form x(j) = - sum / conjg( a*s(j,j) - b*p(j,j) ) ! with scaling and perturbation of the denominator d = conjg( acoeff*s( j, j )-bcoeff*p( j, j ) ) if( abs1( d )<=dmin )d = cmplx( dmin,KIND=${ck}$) if( abs1( d )=bignum*abs1( d ) ) then temp = one / abs1( sum ) do jr = je, j - 1 work( jr ) = temp*work( jr ) end do xmax = temp*xmax sum = temp*sum end if end if work( j ) = stdlib${ii}$_${ci}$ladiv( -sum, d ) xmax = max( xmax, abs1( work( j ) ) ) end do loop_100 ! back transform eigenvector if howmny='b'. if( ilback ) then call stdlib${ii}$_${ci}$gemv( 'N', n, n+1-je, cone, vl( 1_${ik}$, je ), ldvl,work( je ), 1_${ik}$, & czero, work( n+1 ), 1_${ik}$ ) isrc = 2_${ik}$ ibeg = 1_${ik}$ else isrc = 1_${ik}$ ibeg = je end if ! copy and scale eigenvector into column of vl xmax = zero do jr = ibeg, n xmax = max( xmax, abs1( work( ( isrc-1 )*n+jr ) ) ) end do if( xmax>safmin ) then temp = one / xmax do jr = ibeg, n vl( jr, ieig ) = temp*work( ( isrc-1 )*n+jr ) end do else ibeg = n + 1_${ik}$ end if do jr = 1, ibeg - 1 vl( jr, ieig ) = czero end do end if end do loop_140 end if ! right eigenvectors if( compr ) then ieig = im + 1_${ik}$ ! main loop over eigenvalues loop_250: do je = n, 1, -1 if( ilall ) then ilcomp = .true. else ilcomp = select( je ) end if if( ilcomp ) then ieig = ieig - 1_${ik}$ if( abs1( s( je, je ) )<=safmin .and.abs( real( p( je, je ),KIND=${ck}$) )& <=safmin ) then ! singular matrix pencil -- return unit eigenvector do jr = 1, n vr( jr, ieig ) = czero end do vr( ieig, ieig ) = cone cycle loop_250 end if ! non-singular eigenvalue: ! compute coefficients a and b in ! ( a a - b b ) x = 0 temp = one / max( abs1( s( je, je ) )*ascale,abs( real( p( je, je ),KIND=${ck}$) )& *bscale, safmin ) salpha = ( temp*s( je, je ) )*ascale sbeta = ( temp*real( p( je, je ),KIND=${ck}$) )*bscale acoeff = sbeta*ascale bcoeff = salpha*bscale ! scale to avoid underflow lsa = abs( sbeta )>=safmin .and. abs( acoeff )=safmin .and. abs1( bcoeff )=bignum*abs1( d ) ) then temp = one / abs1( work( j ) ) do jr = 1, je work( jr ) = temp*work( jr ) end do end if end if work( j ) = stdlib${ii}$_${ci}$ladiv( -work( j ), d ) if( j>1_${ik}$ ) then ! w = w + x(j)*(a s(*,j) - b p(*,j) ) with scaling if( abs1( work( j ) )>one ) then temp = one / abs1( work( j ) ) if( acoefa*rwork( j )+bcoefa*rwork( n+j )>=bignum*temp ) then do jr = 1, je work( jr ) = temp*work( jr ) end do end if end if ca = acoeff*work( j ) cb = bcoeff*work( j ) do jr = 1, j - 1 work( jr ) = work( jr ) + ca*s( jr, j ) -cb*p( jr, j ) end do end if end do loop_210 ! back transform eigenvector if howmny='b'. if( ilback ) then call stdlib${ii}$_${ci}$gemv( 'N', n, je, cone, vr, ldvr, work, 1_${ik}$,czero, work( n+1 ), & 1_${ik}$ ) isrc = 2_${ik}$ iend = n else isrc = 1_${ik}$ iend = je end if ! copy and scale eigenvector into column of vr xmax = zero do jr = 1, iend xmax = max( xmax, abs1( work( ( isrc-1 )*n+jr ) ) ) end do if( xmax>safmin ) then temp = one / xmax do jr = 1, iend vr( jr, ieig ) = temp*work( ( isrc-1 )*n+jr ) end do else iend = 0_${ik}$ end if do jr = iend + 1, n vr( jr, ieig ) = czero end do end if end do loop_250 end if return end subroutine stdlib${ii}$_${ci}$tgevc #:endif #:endfor pure module subroutine stdlib${ii}$_stgexc( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, ifst, ilst, & !! STGEXC reorders the generalized real Schur decomposition of a real !! matrix pair (A,B) using an orthogonal equivalence transformation !! (A, B) = Q * (A, B) * Z**T, !! so that the diagonal block of (A, B) with row index IFST is moved !! to row ILST. !! (A, B) must be in generalized real Schur canonical form (as returned !! by SGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2 !! diagonal blocks. B is upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**T = Q(out) * A(out) * Z(out)**T !! Q(in) * B(in) * Z(in)**T = Q(out) * B(out) * Z(out)**T work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(inout) :: ifst, ilst integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldq, ldz, lwork, n ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: here, lwmin, nbf, nbl, nbnext ! Intrinsic Functions ! Executable Statements ! decode and test input arguments. info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldan ) then info = -12_${ik}$ else if( ilst<1_${ik}$ .or. ilst>n ) then info = -13_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ else lwmin = 4_${ik}$*n + 16_${ik}$ end if work(1_${ik}$) = lwmin if (lwork1_${ik}$ ) then if( a( ifst, ifst-1 )/=zero )ifst = ifst - 1_${ik}$ end if nbf = 1_${ik}$ if( ifst1_${ik}$ ) then if( a( ilst, ilst-1 )/=zero )ilst = ilst - 1_${ik}$ end if nbl = 1_${ik}$ if( ilst=3_${ik}$ ) then if( a( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_stgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, here-nbnext, & nbnext, nbf, work, lwork,info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - nbnext ! test if 2-by-2 block breaks into two 1-by-1 blocks. if( nbf==2_${ik}$ ) then if( a( here+1, here )==zero )nbf = 3_${ik}$ end if else ! current block consists of two 1-by-1 blocks, each of which ! must be swapped individually. nbnext = 1_${ik}$ if( here>=3_${ik}$ ) then if( a( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_stgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, here-nbnext, & nbnext, 1_${ik}$, work, lwork,info ) if( info/=0_${ik}$ ) then ilst = here return end if if( nbnext==1_${ik}$ ) then ! swap two 1-by-1 blocks. call stdlib${ii}$_stgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, here, & nbnext, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 1_${ik}$ else ! recompute nbnext in case of 2-by-2 split. if( a( here, here-1 )==zero )nbnext = 1_${ik}$ if( nbnext==2_${ik}$ ) then ! 2-by-2 block did not split. call stdlib${ii}$_stgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq,z, ldz, here-1,& 2_${ik}$, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 2_${ik}$ else ! 2-by-2 block did split. call stdlib${ii}$_stgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq,z, ldz, here, & 1_${ik}$, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 1_${ik}$ call stdlib${ii}$_stgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq,z, ldz, here, & 1_${ik}$, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 1_${ik}$ end if end if end if if( here>ilst )go to 20 end if ilst = here work( 1_${ik}$ ) = lwmin return end subroutine stdlib${ii}$_stgexc pure module subroutine stdlib${ii}$_dtgexc( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, ifst, ilst, & !! DTGEXC reorders the generalized real Schur decomposition of a real !! matrix pair (A,B) using an orthogonal equivalence transformation !! (A, B) = Q * (A, B) * Z**T, !! so that the diagonal block of (A, B) with row index IFST is moved !! to row ILST. !! (A, B) must be in generalized real Schur canonical form (as returned !! by DGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2 !! diagonal blocks. B is upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**T = Q(out) * A(out) * Z(out)**T !! Q(in) * B(in) * Z(in)**T = Q(out) * B(out) * Z(out)**T work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(inout) :: ifst, ilst integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldq, ldz, lwork, n ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: here, lwmin, nbf, nbl, nbnext ! Intrinsic Functions ! Executable Statements ! decode and test input arguments. info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldan ) then info = -12_${ik}$ else if( ilst<1_${ik}$ .or. ilst>n ) then info = -13_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ else lwmin = 4_${ik}$*n + 16_${ik}$ end if work(1_${ik}$) = lwmin if (lwork1_${ik}$ ) then if( a( ifst, ifst-1 )/=zero )ifst = ifst - 1_${ik}$ end if nbf = 1_${ik}$ if( ifst1_${ik}$ ) then if( a( ilst, ilst-1 )/=zero )ilst = ilst - 1_${ik}$ end if nbl = 1_${ik}$ if( ilst=3_${ik}$ ) then if( a( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_dtgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, here-nbnext, & nbnext, nbf, work, lwork,info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - nbnext ! test if 2-by-2 block breaks into two 1-by-1 blocks. if( nbf==2_${ik}$ ) then if( a( here+1, here )==zero )nbf = 3_${ik}$ end if else ! current block consists of two 1-by-1 blocks, each of which ! must be swapped individually. nbnext = 1_${ik}$ if( here>=3_${ik}$ ) then if( a( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_dtgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, here-nbnext, & nbnext, 1_${ik}$, work, lwork,info ) if( info/=0_${ik}$ ) then ilst = here return end if if( nbnext==1_${ik}$ ) then ! swap two 1-by-1 blocks. call stdlib${ii}$_dtgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, here, & nbnext, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 1_${ik}$ else ! recompute nbnext in case of 2-by-2 split. if( a( here, here-1 )==zero )nbnext = 1_${ik}$ if( nbnext==2_${ik}$ ) then ! 2-by-2 block did not split. call stdlib${ii}$_dtgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq,z, ldz, here-1,& 2_${ik}$, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 2_${ik}$ else ! 2-by-2 block did split. call stdlib${ii}$_dtgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq,z, ldz, here, & 1_${ik}$, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 1_${ik}$ call stdlib${ii}$_dtgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq,z, ldz, here, & 1_${ik}$, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 1_${ik}$ end if end if end if if( here>ilst )go to 20 end if ilst = here work( 1_${ik}$ ) = lwmin return end subroutine stdlib${ii}$_dtgexc #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tgexc( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, ifst, ilst, & !! DTGEXC: reorders the generalized real Schur decomposition of a real !! matrix pair (A,B) using an orthogonal equivalence transformation !! (A, B) = Q * (A, B) * Z**T, !! so that the diagonal block of (A, B) with row index IFST is moved !! to row ILST. !! (A, B) must be in generalized real Schur canonical form (as returned !! by DGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2 !! diagonal blocks. B is upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**T = Q(out) * A(out) * Z(out)**T !! Q(in) * B(in) * Z(in)**T = Q(out) * B(out) * Z(out)**T work, lwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(inout) :: ifst, ilst integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldq, ldz, lwork, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery integer(${ik}$) :: here, lwmin, nbf, nbl, nbnext ! Intrinsic Functions ! Executable Statements ! decode and test input arguments. info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldan ) then info = -12_${ik}$ else if( ilst<1_${ik}$ .or. ilst>n ) then info = -13_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ else lwmin = 4_${ik}$*n + 16_${ik}$ end if work(1_${ik}$) = lwmin if (lwork1_${ik}$ ) then if( a( ifst, ifst-1 )/=zero )ifst = ifst - 1_${ik}$ end if nbf = 1_${ik}$ if( ifst1_${ik}$ ) then if( a( ilst, ilst-1 )/=zero )ilst = ilst - 1_${ik}$ end if nbl = 1_${ik}$ if( ilst=3_${ik}$ ) then if( a( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_${ri}$tgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, here-nbnext, & nbnext, nbf, work, lwork,info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - nbnext ! test if 2-by-2 block breaks into two 1-by-1 blocks. if( nbf==2_${ik}$ ) then if( a( here+1, here )==zero )nbf = 3_${ik}$ end if else ! current block consists of two 1-by-1 blocks, each of which ! must be swapped individually. nbnext = 1_${ik}$ if( here>=3_${ik}$ ) then if( a( here-1, here-2 )/=zero )nbnext = 2_${ik}$ end if call stdlib${ii}$_${ri}$tgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, here-nbnext, & nbnext, 1_${ik}$, work, lwork,info ) if( info/=0_${ik}$ ) then ilst = here return end if if( nbnext==1_${ik}$ ) then ! swap two 1-by-1 blocks. call stdlib${ii}$_${ri}$tgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, here, & nbnext, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 1_${ik}$ else ! recompute nbnext in case of 2-by-2 split. if( a( here, here-1 )==zero )nbnext = 1_${ik}$ if( nbnext==2_${ik}$ ) then ! 2-by-2 block did not split. call stdlib${ii}$_${ri}$tgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq,z, ldz, here-1,& 2_${ik}$, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 2_${ik}$ else ! 2-by-2 block did split. call stdlib${ii}$_${ri}$tgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq,z, ldz, here, & 1_${ik}$, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 1_${ik}$ call stdlib${ii}$_${ri}$tgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq,z, ldz, here, & 1_${ik}$, 1_${ik}$, work, lwork, info ) if( info/=0_${ik}$ ) then ilst = here return end if here = here - 1_${ik}$ end if end if end if if( here>ilst )go to 20 end if ilst = here work( 1_${ik}$ ) = lwmin return end subroutine stdlib${ii}$_${ri}$tgexc #:endif #:endfor pure module subroutine stdlib${ii}$_ctgexc( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, ifst, ilst, & !! CTGEXC reorders the generalized Schur decomposition of a complex !! matrix pair (A,B), using an unitary equivalence transformation !! (A, B) := Q * (A, B) * Z**H, so that the diagonal block of (A, B) with !! row index IFST is moved to row ILST. !! (A, B) must be in generalized Schur canonical form, that is, A and !! B are both upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**H = Q(out) * A(out) * Z(out)**H !! Q(in) * B(in) * Z(in)**H = Q(out) * B(out) * Z(out)**H info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(in) :: ifst, lda, ldb, ldq, ldz, n integer(${ik}$), intent(inout) :: ilst integer(${ik}$), intent(out) :: info ! Array Arguments complex(sp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: here ! Intrinsic Functions ! Executable Statements ! decode and test input arguments. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldan ) then info = -12_${ik}$ else if( ilst<1_${ik}$ .or. ilst>n ) then info = -13_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CTGEXC', -info ) return end if ! quick return if possible if( n<=1 )return if( ifst==ilst )return if( ifst=ilst )go to 20 here = here + 1_${ik}$ end if ilst = here return end subroutine stdlib${ii}$_ctgexc pure module subroutine stdlib${ii}$_ztgexc( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, ifst, ilst, & !! ZTGEXC reorders the generalized Schur decomposition of a complex !! matrix pair (A,B), using an unitary equivalence transformation !! (A, B) := Q * (A, B) * Z**H, so that the diagonal block of (A, B) with !! row index IFST is moved to row ILST. !! (A, B) must be in generalized Schur canonical form, that is, A and !! B are both upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**H = Q(out) * A(out) * Z(out)**H !! Q(in) * B(in) * Z(in)**H = Q(out) * B(out) * Z(out)**H info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(in) :: ifst, lda, ldb, ldq, ldz, n integer(${ik}$), intent(inout) :: ilst integer(${ik}$), intent(out) :: info ! Array Arguments complex(dp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: here ! Intrinsic Functions ! Executable Statements ! decode and test input arguments. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldan ) then info = -12_${ik}$ else if( ilst<1_${ik}$ .or. ilst>n ) then info = -13_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZTGEXC', -info ) return end if ! quick return if possible if( n<=1 )return if( ifst==ilst )return if( ifst=ilst )go to 20 here = here + 1_${ik}$ end if ilst = here return end subroutine stdlib${ii}$_ztgexc #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tgexc( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, ifst, ilst, & !! ZTGEXC: reorders the generalized Schur decomposition of a complex !! matrix pair (A,B), using an unitary equivalence transformation !! (A, B) := Q * (A, B) * Z**H, so that the diagonal block of (A, B) with !! row index IFST is moved to row ILST. !! (A, B) must be in generalized Schur canonical form, that is, A and !! B are both upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**H = Q(out) * A(out) * Z(out)**H !! Q(in) * B(in) * Z(in)**H = Q(out) * B(out) * Z(out)**H info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(in) :: ifst, lda, ldb, ldq, ldz, n integer(${ik}$), intent(inout) :: ilst integer(${ik}$), intent(out) :: info ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: here ! Intrinsic Functions ! Executable Statements ! decode and test input arguments. info = 0_${ik}$ if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldan ) then info = -12_${ik}$ else if( ilst<1_${ik}$ .or. ilst>n ) then info = -13_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZTGEXC', -info ) return end if ! quick return if possible if( n<=1 )return if( ifst==ilst )return if( ifst=ilst )go to 20 here = here + 1_${ik}$ end if ilst = here return end subroutine stdlib${ii}$_${ci}$tgexc #:endif #:endfor pure module subroutine stdlib${ii}$_stgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, j1, n1, n2, & !! STGEX2 swaps adjacent diagonal blocks (A11, B11) and (A22, B22) !! of size 1-by-1 or 2-by-2 in an upper (quasi) triangular matrix pair !! (A, B) by an orthogonal equivalence transformation. !! (A, B) must be in generalized real Schur canonical form (as returned !! by SGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2 !! diagonal blocks. B is upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**T = Q(out) * A(out) * Z(out)**T !! Q(in) * B(in) * Z(in)**T = Q(out) * B(out) * Z(out)**T work, lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: j1, lda, ldb, ldq, ldz, lwork, n, n1, n2 ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) real(sp), intent(out) :: work(*) ! ===================================================================== ! replaced various illegal calls to stdlib${ii}$_scopy by calls to stdlib${ii}$_slaset, or by do ! loops. sven hammarling, 1/5/02. ! Parameters real(sp), parameter :: twenty = 2.0e+01_sp integer(${ik}$), parameter :: ldst = 4_${ik}$ logical(lk), parameter :: wands = .true. ! Local Scalars logical(lk) :: strong, weak integer(${ik}$) :: i, idum, linfo, m real(sp) :: bqra21, brqa21, ddum, dnorma, dnormb, dscale, dsum, eps, f, g, sa, sb, & scale, smlnum, thresha, threshb ! Local Arrays integer(${ik}$) :: iwork(ldst) real(sp) :: ai(2_${ik}$), ar(2_${ik}$), be(2_${ik}$), ir(ldst,ldst), ircop(ldst,ldst), li(ldst,ldst), licop(& ldst,ldst), s(ldst,ldst), scpy(ldst,ldst), t(ldst,ldst), taul(ldst), taur(ldst), tcpy(& ldst,ldst) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n<=1 .or. n1<=0 .or. n2<=0 )return if( n1>n .or. ( j1+n1 )>n )return m = n1 + n2 if( lwork=sb ) then call stdlib${ii}$_slartg( s( 1_${ik}$, 1_${ik}$ ), s( 2_${ik}$, 1_${ik}$ ), li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ ),ddum ) else call stdlib${ii}$_slartg( t( 1_${ik}$, 1_${ik}$ ), t( 2_${ik}$, 1_${ik}$ ), li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ ),ddum ) end if call stdlib${ii}$_srot( 2_${ik}$, s( 1_${ik}$, 1_${ik}$ ), ldst, s( 2_${ik}$, 1_${ik}$ ), ldst, li( 1_${ik}$, 1_${ik}$ ),li( 2_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_srot( 2_${ik}$, t( 1_${ik}$, 1_${ik}$ ), ldst, t( 2_${ik}$, 1_${ik}$ ), ldst, li( 1_${ik}$, 1_${ik}$ ),li( 2_${ik}$, 1_${ik}$ ) ) li( 2_${ik}$, 2_${ik}$ ) = li( 1_${ik}$, 1_${ik}$ ) li( 1_${ik}$, 2_${ik}$ ) = -li( 2_${ik}$, 1_${ik}$ ) ! weak stability test: |s21| <= o(eps f-norm((a))) ! and |t21| <= o(eps f-norm((b))) weak = abs( s( 2_${ik}$, 1_${ik}$ ) ) <= thresha .and.abs( t( 2_${ik}$, 1_${ik}$ ) ) <= threshb if( .not.weak )go to 70 if( wands ) then ! strong stability test: ! f-norm((a-ql**h*s*qr)) <= o(eps*f-norm((a))) ! and ! f-norm((b-ql**h*t*qr)) <= o(eps*f-norm((b))) call stdlib${ii}$_slacpy( 'FULL', m, m, a( j1, j1 ), lda, work( m*m+1 ),m ) call stdlib${ii}$_sgemm( 'N', 'N', m, m, m, one, li, ldst, s, ldst, zero,work, m ) call stdlib${ii}$_sgemm( 'N', 'T', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_slassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sa = dscale*sqrt( dsum ) call stdlib${ii}$_slacpy( 'FULL', m, m, b( j1, j1 ), ldb, work( m*m+1 ),m ) call stdlib${ii}$_sgemm( 'N', 'N', m, m, m, one, li, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_sgemm( 'N', 'T', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_slassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sb = dscale*sqrt( dsum ) strong = sa<=thresha .and. sb<=threshb if( .not.strong )go to 70 end if ! update (a(j1:j1+m-1, m+j1:n), b(j1:j1+m-1, m+j1:n)) and ! (a(1:j1-1, j1:j1+m), b(1:j1-1, j1:j1+m)). call stdlib${ii}$_srot( j1+1, a( 1_${ik}$, j1 ), 1_${ik}$, a( 1_${ik}$, j1+1 ), 1_${ik}$, ir( 1_${ik}$, 1_${ik}$ ),ir( 2_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_srot( j1+1, b( 1_${ik}$, j1 ), 1_${ik}$, b( 1_${ik}$, j1+1 ), 1_${ik}$, ir( 1_${ik}$, 1_${ik}$ ),ir( 2_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_srot( n-j1+1, a( j1, j1 ), lda, a( j1+1, j1 ), lda,li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ & ) ) call stdlib${ii}$_srot( n-j1+1, b( j1, j1 ), ldb, b( j1+1, j1 ), ldb,li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ & ) ) ! set n1-by-n2 (2,1) - blocks to zero. a( j1+1, j1 ) = zero b( j1+1, j1 ) = zero ! accumulate transformations into q and z if requested. if( wantz )call stdlib${ii}$_srot( n, z( 1_${ik}$, j1 ), 1_${ik}$, z( 1_${ik}$, j1+1 ), 1_${ik}$, ir( 1_${ik}$, 1_${ik}$ ),ir( 2_${ik}$, 1_${ik}$ & ) ) if( wantq )call stdlib${ii}$_srot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j1+1 ), 1_${ik}$, li( 1_${ik}$, 1_${ik}$ ),li( 2_${ik}$, 1_${ik}$ & ) ) ! exit with info = 0 if swap was successfully performed. return else ! case 2: swap 1-by-1 and 2-by-2 blocks, or 2-by-2 ! and 2-by-2 blocks. ! solve the generalized sylvester equation ! s11 * r - l * s22 = scale * s12 ! t11 * r - l * t22 = scale * t12 ! for r and l. solutions in li and ir. call stdlib${ii}$_slacpy( 'FULL', n1, n2, t( 1_${ik}$, n1+1 ), ldst, li, ldst ) call stdlib${ii}$_slacpy( 'FULL', n1, n2, s( 1_${ik}$, n1+1 ), ldst,ir( n2+1, n1+1 ), ldst ) call stdlib${ii}$_stgsy2( 'N', 0_${ik}$, n1, n2, s, ldst, s( n1+1, n1+1 ), ldst,ir( n2+1, n1+1 ),& ldst, t, ldst, t( n1+1, n1+1 ),ldst, li, ldst, scale, dsum, dscale, iwork, idum,& linfo ) if( linfo/=0 )go to 70 ! compute orthogonal matrix ql: ! ql**t * li = [ tl ] ! [ 0 ] ! where ! li = [ -l ] ! [ scale * identity(n2) ] do i = 1, n2 call stdlib${ii}$_sscal( n1, -one, li( 1_${ik}$, i ), 1_${ik}$ ) li( n1+i, i ) = scale end do call stdlib${ii}$_sgeqr2( m, n2, li, ldst, taul, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_sorg2r( m, m, n2, li, ldst, taul, work, linfo ) if( linfo/=0 )go to 70 ! compute orthogonal matrix rq: ! ir * rq**t = [ 0 tr], ! where ir = [ scale * identity(n1), r ] do i = 1, n1 ir( n2+i, i ) = scale end do call stdlib${ii}$_sgerq2( n1, m, ir( n2+1, 1_${ik}$ ), ldst, taur, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_sorgr2( m, m, n1, ir, ldst, taur, work, linfo ) if( linfo/=0 )go to 70 ! perform the swapping tentatively: call stdlib${ii}$_sgemm( 'T', 'N', m, m, m, one, li, ldst, s, ldst, zero,work, m ) call stdlib${ii}$_sgemm( 'N', 'T', m, m, m, one, work, m, ir, ldst, zero, s,ldst ) call stdlib${ii}$_sgemm( 'T', 'N', m, m, m, one, li, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_sgemm( 'N', 'T', m, m, m, one, work, m, ir, ldst, zero, t,ldst ) call stdlib${ii}$_slacpy( 'F', m, m, s, ldst, scpy, ldst ) call stdlib${ii}$_slacpy( 'F', m, m, t, ldst, tcpy, ldst ) call stdlib${ii}$_slacpy( 'F', m, m, ir, ldst, ircop, ldst ) call stdlib${ii}$_slacpy( 'F', m, m, li, ldst, licop, ldst ) ! triangularize the b-part by an rq factorization. ! apply transformation (from left) to a-part, giving s. call stdlib${ii}$_sgerq2( m, m, t, ldst, taur, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_sormr2( 'R', 'T', m, m, m, t, ldst, taur, s, ldst, work,linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_sormr2( 'L', 'N', m, m, m, t, ldst, taur, ir, ldst, work,linfo ) if( linfo/=0 )go to 70 ! compute f-norm(s21) in brqa21. (t21 is 0.) dscale = zero dsum = one do i = 1, n2 call stdlib${ii}$_slassq( n1, s( n2+1, i ), 1_${ik}$, dscale, dsum ) end do brqa21 = dscale*sqrt( dsum ) ! triangularize the b-part by a qr factorization. ! apply transformation (from right) to a-part, giving s. call stdlib${ii}$_sgeqr2( m, m, tcpy, ldst, taul, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_sorm2r( 'L', 'T', m, m, m, tcpy, ldst, taul, scpy, ldst,work, info ) call stdlib${ii}$_sorm2r( 'R', 'N', m, m, m, tcpy, ldst, taul, licop, ldst,work, info ) if( linfo/=0 )go to 70 ! compute f-norm(s21) in bqra21. (t21 is 0.) dscale = zero dsum = one do i = 1, n2 call stdlib${ii}$_slassq( n1, scpy( n2+1, i ), 1_${ik}$, dscale, dsum ) end do bqra21 = dscale*sqrt( dsum ) ! decide which method to use. ! weak stability test: ! f-norm(s21) <= o(eps * f-norm((s))) if( bqra21<=brqa21 .and. bqra21<=thresha ) then call stdlib${ii}$_slacpy( 'F', m, m, scpy, ldst, s, ldst ) call stdlib${ii}$_slacpy( 'F', m, m, tcpy, ldst, t, ldst ) call stdlib${ii}$_slacpy( 'F', m, m, ircop, ldst, ir, ldst ) call stdlib${ii}$_slacpy( 'F', m, m, licop, ldst, li, ldst ) else if( brqa21>=thresha ) then go to 70 end if ! set lower triangle of b-part to zero if (m>1_${ik}$) call stdlib${ii}$_slaset( 'LOWER', m-1, m-1, zero, zero, t(2_${ik}$,1_${ik}$), ldst ) if( wands ) then ! strong stability test: ! f-norm((a-ql**h*s*qr)) <= o(eps*f-norm((a))) ! and ! f-norm((b-ql**h*t*qr)) <= o(eps*f-norm((b))) call stdlib${ii}$_slacpy( 'FULL', m, m, a( j1, j1 ), lda, work( m*m+1 ),m ) call stdlib${ii}$_sgemm( 'N', 'N', m, m, m, one, li, ldst, s, ldst, zero,work, m ) call stdlib${ii}$_sgemm( 'N', 'N', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_slassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sa = dscale*sqrt( dsum ) call stdlib${ii}$_slacpy( 'FULL', m, m, b( j1, j1 ), ldb, work( m*m+1 ),m ) call stdlib${ii}$_sgemm( 'N', 'N', m, m, m, one, li, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_sgemm( 'N', 'N', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_slassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sb = dscale*sqrt( dsum ) strong = sa<=thresha .and. sb<=threshb if( .not.strong )go to 70 end if ! if the swap is accepted ("weakly" and "strongly"), apply the ! transformations and set n1-by-n2 (2,1)-block to zero. call stdlib${ii}$_slaset( 'FULL', n1, n2, zero, zero, s(n2+1,1_${ik}$), ldst ) ! copy back m-by-m diagonal block starting at index j1 of (a, b) call stdlib${ii}$_slacpy( 'F', m, m, s, ldst, a( j1, j1 ), lda ) call stdlib${ii}$_slacpy( 'F', m, m, t, ldst, b( j1, j1 ), ldb ) call stdlib${ii}$_slaset( 'FULL', ldst, ldst, zero, zero, t, ldst ) ! standardize existing 2-by-2 blocks. call stdlib${ii}$_slaset( 'FULL', m, m, zero, zero, work, m ) work( 1_${ik}$ ) = one t( 1_${ik}$, 1_${ik}$ ) = one idum = lwork - m*m - 2_${ik}$ if( n2>1_${ik}$ ) then call stdlib${ii}$_slagv2( a( j1, j1 ), lda, b( j1, j1 ), ldb, ar, ai, be,work( 1_${ik}$ ), & work( 2_${ik}$ ), t( 1_${ik}$, 1_${ik}$ ), t( 2_${ik}$, 1_${ik}$ ) ) work( m+1 ) = -work( 2_${ik}$ ) work( m+2 ) = work( 1_${ik}$ ) t( n2, n2 ) = t( 1_${ik}$, 1_${ik}$ ) t( 1_${ik}$, 2_${ik}$ ) = -t( 2_${ik}$, 1_${ik}$ ) end if work( m*m ) = one t( m, m ) = one if( n1>1_${ik}$ ) then call stdlib${ii}$_slagv2( a( j1+n2, j1+n2 ), lda, b( j1+n2, j1+n2 ), ldb,taur, taul, & work( m*m+1 ), work( n2*m+n2+1 ),work( n2*m+n2+2 ), t( n2+1, n2+1 ),t( m, m-1 ) ) work( m*m ) = work( n2*m+n2+1 ) work( m*m-1 ) = -work( n2*m+n2+2 ) t( m, m ) = t( n2+1, n2+1 ) t( m-1, m ) = -t( m, m-1 ) end if call stdlib${ii}$_sgemm( 'T', 'N', n2, n1, n2, one, work, m, a( j1, j1+n2 ),lda, zero, & work( m*m+1 ), n2 ) call stdlib${ii}$_slacpy( 'FULL', n2, n1, work( m*m+1 ), n2, a( j1, j1+n2 ),lda ) call stdlib${ii}$_sgemm( 'T', 'N', n2, n1, n2, one, work, m, b( j1, j1+n2 ),ldb, zero, & work( m*m+1 ), n2 ) call stdlib${ii}$_slacpy( 'FULL', n2, n1, work( m*m+1 ), n2, b( j1, j1+n2 ),ldb ) call stdlib${ii}$_sgemm( 'N', 'N', m, m, m, one, li, ldst, work, m, zero,work( m*m+1 ), m & ) call stdlib${ii}$_slacpy( 'FULL', m, m, work( m*m+1 ), m, li, ldst ) call stdlib${ii}$_sgemm( 'N', 'N', n2, n1, n1, one, a( j1, j1+n2 ), lda,t( n2+1, n2+1 ), & ldst, zero, work, n2 ) call stdlib${ii}$_slacpy( 'FULL', n2, n1, work, n2, a( j1, j1+n2 ), lda ) call stdlib${ii}$_sgemm( 'N', 'N', n2, n1, n1, one, b( j1, j1+n2 ), ldb,t( n2+1, n2+1 ), & ldst, zero, work, n2 ) call stdlib${ii}$_slacpy( 'FULL', n2, n1, work, n2, b( j1, j1+n2 ), ldb ) call stdlib${ii}$_sgemm( 'T', 'N', m, m, m, one, ir, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_slacpy( 'FULL', m, m, work, m, ir, ldst ) ! accumulate transformations into q and z if requested. if( wantq ) then call stdlib${ii}$_sgemm( 'N', 'N', n, m, m, one, q( 1_${ik}$, j1 ), ldq, li,ldst, zero, work, & n ) call stdlib${ii}$_slacpy( 'FULL', n, m, work, n, q( 1_${ik}$, j1 ), ldq ) end if if( wantz ) then call stdlib${ii}$_sgemm( 'N', 'N', n, m, m, one, z( 1_${ik}$, j1 ), ldz, ir,ldst, zero, work, & n ) call stdlib${ii}$_slacpy( 'FULL', n, m, work, n, z( 1_${ik}$, j1 ), ldz ) end if ! update (a(j1:j1+m-1, m+j1:n), b(j1:j1+m-1, m+j1:n)) and ! (a(1:j1-1, j1:j1+m), b(1:j1-1, j1:j1+m)). i = j1 + m if( i<=n ) then call stdlib${ii}$_sgemm( 'T', 'N', m, n-i+1, m, one, li, ldst,a( j1, i ), lda, zero, & work, m ) call stdlib${ii}$_slacpy( 'FULL', m, n-i+1, work, m, a( j1, i ), lda ) call stdlib${ii}$_sgemm( 'T', 'N', m, n-i+1, m, one, li, ldst,b( j1, i ), ldb, zero, & work, m ) call stdlib${ii}$_slacpy( 'FULL', m, n-i+1, work, m, b( j1, i ), ldb ) end if i = j1 - 1_${ik}$ if( i>0_${ik}$ ) then call stdlib${ii}$_sgemm( 'N', 'N', i, m, m, one, a( 1_${ik}$, j1 ), lda, ir,ldst, zero, work, & i ) call stdlib${ii}$_slacpy( 'FULL', i, m, work, i, a( 1_${ik}$, j1 ), lda ) call stdlib${ii}$_sgemm( 'N', 'N', i, m, m, one, b( 1_${ik}$, j1 ), ldb, ir,ldst, zero, work, & i ) call stdlib${ii}$_slacpy( 'FULL', i, m, work, i, b( 1_${ik}$, j1 ), ldb ) end if ! exit with info = 0 if swap was successfully performed. return end if ! exit with info = 1 if swap was rejected. 70 continue info = 1_${ik}$ return end subroutine stdlib${ii}$_stgex2 pure module subroutine stdlib${ii}$_dtgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, j1, n1, n2, & !! DTGEX2 swaps adjacent diagonal blocks (A11, B11) and (A22, B22) !! of size 1-by-1 or 2-by-2 in an upper (quasi) triangular matrix pair !! (A, B) by an orthogonal equivalence transformation. !! (A, B) must be in generalized real Schur canonical form (as returned !! by DGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2 !! diagonal blocks. B is upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**T = Q(out) * A(out) * Z(out)**T !! Q(in) * B(in) * Z(in)**T = Q(out) * B(out) * Z(out)**T work, lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: j1, lda, ldb, ldq, ldz, lwork, n, n1, n2 ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) real(dp), intent(out) :: work(*) ! ===================================================================== ! replaced various illegal calls to stdlib${ii}$_dcopy by calls to stdlib${ii}$_dlaset, or by do ! loops. sven hammarling, 1/5/02. ! Parameters real(dp), parameter :: twenty = 2.0e+01_dp integer(${ik}$), parameter :: ldst = 4_${ik}$ logical(lk), parameter :: wands = .true. ! Local Scalars logical(lk) :: strong, weak integer(${ik}$) :: i, idum, linfo, m real(dp) :: bqra21, brqa21, ddum, dnorma, dnormb, dscale, dsum, eps, f, g, sa, sb, & scale, smlnum, thresha, threshb ! Local Arrays integer(${ik}$) :: iwork(ldst) real(dp) :: ai(2_${ik}$), ar(2_${ik}$), be(2_${ik}$), ir(ldst,ldst), ircop(ldst,ldst), li(ldst,ldst), licop(& ldst,ldst), s(ldst,ldst), scpy(ldst,ldst), t(ldst,ldst), taul(ldst), taur(ldst), tcpy(& ldst,ldst) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n<=1 .or. n1<=0 .or. n2<=0 )return if( n1>n .or. ( j1+n1 )>n )return m = n1 + n2 if( lwork=sb ) then call stdlib${ii}$_dlartg( s( 1_${ik}$, 1_${ik}$ ), s( 2_${ik}$, 1_${ik}$ ), li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ ),ddum ) else call stdlib${ii}$_dlartg( t( 1_${ik}$, 1_${ik}$ ), t( 2_${ik}$, 1_${ik}$ ), li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ ),ddum ) end if call stdlib${ii}$_drot( 2_${ik}$, s( 1_${ik}$, 1_${ik}$ ), ldst, s( 2_${ik}$, 1_${ik}$ ), ldst, li( 1_${ik}$, 1_${ik}$ ),li( 2_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_drot( 2_${ik}$, t( 1_${ik}$, 1_${ik}$ ), ldst, t( 2_${ik}$, 1_${ik}$ ), ldst, li( 1_${ik}$, 1_${ik}$ ),li( 2_${ik}$, 1_${ik}$ ) ) li( 2_${ik}$, 2_${ik}$ ) = li( 1_${ik}$, 1_${ik}$ ) li( 1_${ik}$, 2_${ik}$ ) = -li( 2_${ik}$, 1_${ik}$ ) ! weak stability test: |s21| <= o(eps f-norm((a))) ! and |t21| <= o(eps f-norm((b))) weak = abs( s( 2_${ik}$, 1_${ik}$ ) ) <= thresha .and.abs( t( 2_${ik}$, 1_${ik}$ ) ) <= threshb if( .not.weak )go to 70 if( wands ) then ! strong stability test: ! f-norm((a-ql**h*s*qr)) <= o(eps*f-norm((a))) ! and ! f-norm((b-ql**h*t*qr)) <= o(eps*f-norm((b))) call stdlib${ii}$_dlacpy( 'FULL', m, m, a( j1, j1 ), lda, work( m*m+1 ),m ) call stdlib${ii}$_dgemm( 'N', 'N', m, m, m, one, li, ldst, s, ldst, zero,work, m ) call stdlib${ii}$_dgemm( 'N', 'T', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_dlassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sa = dscale*sqrt( dsum ) call stdlib${ii}$_dlacpy( 'FULL', m, m, b( j1, j1 ), ldb, work( m*m+1 ),m ) call stdlib${ii}$_dgemm( 'N', 'N', m, m, m, one, li, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_dgemm( 'N', 'T', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_dlassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sb = dscale*sqrt( dsum ) strong = sa<=thresha .and. sb<=threshb if( .not.strong )go to 70 end if ! update (a(j1:j1+m-1, m+j1:n), b(j1:j1+m-1, m+j1:n)) and ! (a(1:j1-1, j1:j1+m), b(1:j1-1, j1:j1+m)). call stdlib${ii}$_drot( j1+1, a( 1_${ik}$, j1 ), 1_${ik}$, a( 1_${ik}$, j1+1 ), 1_${ik}$, ir( 1_${ik}$, 1_${ik}$ ),ir( 2_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_drot( j1+1, b( 1_${ik}$, j1 ), 1_${ik}$, b( 1_${ik}$, j1+1 ), 1_${ik}$, ir( 1_${ik}$, 1_${ik}$ ),ir( 2_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_drot( n-j1+1, a( j1, j1 ), lda, a( j1+1, j1 ), lda,li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ & ) ) call stdlib${ii}$_drot( n-j1+1, b( j1, j1 ), ldb, b( j1+1, j1 ), ldb,li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ & ) ) ! set n1-by-n2 (2,1) - blocks to zero. a( j1+1, j1 ) = zero b( j1+1, j1 ) = zero ! accumulate transformations into q and z if requested. if( wantz )call stdlib${ii}$_drot( n, z( 1_${ik}$, j1 ), 1_${ik}$, z( 1_${ik}$, j1+1 ), 1_${ik}$, ir( 1_${ik}$, 1_${ik}$ ),ir( 2_${ik}$, 1_${ik}$ & ) ) if( wantq )call stdlib${ii}$_drot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j1+1 ), 1_${ik}$, li( 1_${ik}$, 1_${ik}$ ),li( 2_${ik}$, 1_${ik}$ & ) ) ! exit with info = 0 if swap was successfully performed. return else ! case 2: swap 1-by-1 and 2-by-2 blocks, or 2-by-2 ! and 2-by-2 blocks. ! solve the generalized sylvester equation ! s11 * r - l * s22 = scale * s12 ! t11 * r - l * t22 = scale * t12 ! for r and l. solutions in li and ir. call stdlib${ii}$_dlacpy( 'FULL', n1, n2, t( 1_${ik}$, n1+1 ), ldst, li, ldst ) call stdlib${ii}$_dlacpy( 'FULL', n1, n2, s( 1_${ik}$, n1+1 ), ldst,ir( n2+1, n1+1 ), ldst ) call stdlib${ii}$_dtgsy2( 'N', 0_${ik}$, n1, n2, s, ldst, s( n1+1, n1+1 ), ldst,ir( n2+1, n1+1 ),& ldst, t, ldst, t( n1+1, n1+1 ),ldst, li, ldst, scale, dsum, dscale, iwork, idum,& linfo ) if( linfo/=0 )go to 70 ! compute orthogonal matrix ql: ! ql**t * li = [ tl ] ! [ 0 ] ! where ! li = [ -l ] ! [ scale * identity(n2) ] do i = 1, n2 call stdlib${ii}$_dscal( n1, -one, li( 1_${ik}$, i ), 1_${ik}$ ) li( n1+i, i ) = scale end do call stdlib${ii}$_dgeqr2( m, n2, li, ldst, taul, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_dorg2r( m, m, n2, li, ldst, taul, work, linfo ) if( linfo/=0 )go to 70 ! compute orthogonal matrix rq: ! ir * rq**t = [ 0 tr], ! where ir = [ scale * identity(n1), r ] do i = 1, n1 ir( n2+i, i ) = scale end do call stdlib${ii}$_dgerq2( n1, m, ir( n2+1, 1_${ik}$ ), ldst, taur, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_dorgr2( m, m, n1, ir, ldst, taur, work, linfo ) if( linfo/=0 )go to 70 ! perform the swapping tentatively: call stdlib${ii}$_dgemm( 'T', 'N', m, m, m, one, li, ldst, s, ldst, zero,work, m ) call stdlib${ii}$_dgemm( 'N', 'T', m, m, m, one, work, m, ir, ldst, zero, s,ldst ) call stdlib${ii}$_dgemm( 'T', 'N', m, m, m, one, li, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_dgemm( 'N', 'T', m, m, m, one, work, m, ir, ldst, zero, t,ldst ) call stdlib${ii}$_dlacpy( 'F', m, m, s, ldst, scpy, ldst ) call stdlib${ii}$_dlacpy( 'F', m, m, t, ldst, tcpy, ldst ) call stdlib${ii}$_dlacpy( 'F', m, m, ir, ldst, ircop, ldst ) call stdlib${ii}$_dlacpy( 'F', m, m, li, ldst, licop, ldst ) ! triangularize the b-part by an rq factorization. ! apply transformation (from left) to a-part, giving s. call stdlib${ii}$_dgerq2( m, m, t, ldst, taur, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_dormr2( 'R', 'T', m, m, m, t, ldst, taur, s, ldst, work,linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_dormr2( 'L', 'N', m, m, m, t, ldst, taur, ir, ldst, work,linfo ) if( linfo/=0 )go to 70 ! compute f-norm(s21) in brqa21. (t21 is 0.) dscale = zero dsum = one do i = 1, n2 call stdlib${ii}$_dlassq( n1, s( n2+1, i ), 1_${ik}$, dscale, dsum ) end do brqa21 = dscale*sqrt( dsum ) ! triangularize the b-part by a qr factorization. ! apply transformation (from right) to a-part, giving s. call stdlib${ii}$_dgeqr2( m, m, tcpy, ldst, taul, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_dorm2r( 'L', 'T', m, m, m, tcpy, ldst, taul, scpy, ldst,work, info ) call stdlib${ii}$_dorm2r( 'R', 'N', m, m, m, tcpy, ldst, taul, licop, ldst,work, info ) if( linfo/=0 )go to 70 ! compute f-norm(s21) in bqra21. (t21 is 0.) dscale = zero dsum = one do i = 1, n2 call stdlib${ii}$_dlassq( n1, scpy( n2+1, i ), 1_${ik}$, dscale, dsum ) end do bqra21 = dscale*sqrt( dsum ) ! decide which method to use. ! weak stability test: ! f-norm(s21) <= o(eps * f-norm((s))) if( bqra21<=brqa21 .and. bqra21<=thresha ) then call stdlib${ii}$_dlacpy( 'F', m, m, scpy, ldst, s, ldst ) call stdlib${ii}$_dlacpy( 'F', m, m, tcpy, ldst, t, ldst ) call stdlib${ii}$_dlacpy( 'F', m, m, ircop, ldst, ir, ldst ) call stdlib${ii}$_dlacpy( 'F', m, m, licop, ldst, li, ldst ) else if( brqa21>=thresha ) then go to 70 end if ! set lower triangle of b-part to zero call stdlib${ii}$_dlaset( 'LOWER', m-1, m-1, zero, zero, t(2_${ik}$,1_${ik}$), ldst ) if( wands ) then ! strong stability test: ! f-norm((a-ql**h*s*qr)) <= o(eps*f-norm((a))) ! and ! f-norm((b-ql**h*t*qr)) <= o(eps*f-norm((b))) call stdlib${ii}$_dlacpy( 'FULL', m, m, a( j1, j1 ), lda, work( m*m+1 ),m ) call stdlib${ii}$_dgemm( 'N', 'N', m, m, m, one, li, ldst, s, ldst, zero,work, m ) call stdlib${ii}$_dgemm( 'N', 'N', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_dlassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sa = dscale*sqrt( dsum ) call stdlib${ii}$_dlacpy( 'FULL', m, m, b( j1, j1 ), ldb, work( m*m+1 ),m ) call stdlib${ii}$_dgemm( 'N', 'N', m, m, m, one, li, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_dgemm( 'N', 'N', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_dlassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sb = dscale*sqrt( dsum ) strong = sa<=thresha .and. sb<=threshb if( .not.strong )go to 70 end if ! if the swap is accepted ("weakly" and "strongly"), apply the ! transformations and set n1-by-n2 (2,1)-block to zero. call stdlib${ii}$_dlaset( 'FULL', n1, n2, zero, zero, s(n2+1,1_${ik}$), ldst ) ! copy back m-by-m diagonal block starting at index j1 of (a, b) call stdlib${ii}$_dlacpy( 'F', m, m, s, ldst, a( j1, j1 ), lda ) call stdlib${ii}$_dlacpy( 'F', m, m, t, ldst, b( j1, j1 ), ldb ) call stdlib${ii}$_dlaset( 'FULL', ldst, ldst, zero, zero, t, ldst ) ! standardize existing 2-by-2 blocks. call stdlib${ii}$_dlaset( 'FULL', m, m, zero, zero, work, m ) work( 1_${ik}$ ) = one t( 1_${ik}$, 1_${ik}$ ) = one idum = lwork - m*m - 2_${ik}$ if( n2>1_${ik}$ ) then call stdlib${ii}$_dlagv2( a( j1, j1 ), lda, b( j1, j1 ), ldb, ar, ai, be,work( 1_${ik}$ ), & work( 2_${ik}$ ), t( 1_${ik}$, 1_${ik}$ ), t( 2_${ik}$, 1_${ik}$ ) ) work( m+1 ) = -work( 2_${ik}$ ) work( m+2 ) = work( 1_${ik}$ ) t( n2, n2 ) = t( 1_${ik}$, 1_${ik}$ ) t( 1_${ik}$, 2_${ik}$ ) = -t( 2_${ik}$, 1_${ik}$ ) end if work( m*m ) = one t( m, m ) = one if( n1>1_${ik}$ ) then call stdlib${ii}$_dlagv2( a( j1+n2, j1+n2 ), lda, b( j1+n2, j1+n2 ), ldb,taur, taul, & work( m*m+1 ), work( n2*m+n2+1 ),work( n2*m+n2+2 ), t( n2+1, n2+1 ),t( m, m-1 ) ) work( m*m ) = work( n2*m+n2+1 ) work( m*m-1 ) = -work( n2*m+n2+2 ) t( m, m ) = t( n2+1, n2+1 ) t( m-1, m ) = -t( m, m-1 ) end if call stdlib${ii}$_dgemm( 'T', 'N', n2, n1, n2, one, work, m, a( j1, j1+n2 ),lda, zero, & work( m*m+1 ), n2 ) call stdlib${ii}$_dlacpy( 'FULL', n2, n1, work( m*m+1 ), n2, a( j1, j1+n2 ),lda ) call stdlib${ii}$_dgemm( 'T', 'N', n2, n1, n2, one, work, m, b( j1, j1+n2 ),ldb, zero, & work( m*m+1 ), n2 ) call stdlib${ii}$_dlacpy( 'FULL', n2, n1, work( m*m+1 ), n2, b( j1, j1+n2 ),ldb ) call stdlib${ii}$_dgemm( 'N', 'N', m, m, m, one, li, ldst, work, m, zero,work( m*m+1 ), m & ) call stdlib${ii}$_dlacpy( 'FULL', m, m, work( m*m+1 ), m, li, ldst ) call stdlib${ii}$_dgemm( 'N', 'N', n2, n1, n1, one, a( j1, j1+n2 ), lda,t( n2+1, n2+1 ), & ldst, zero, work, n2 ) call stdlib${ii}$_dlacpy( 'FULL', n2, n1, work, n2, a( j1, j1+n2 ), lda ) call stdlib${ii}$_dgemm( 'N', 'N', n2, n1, n1, one, b( j1, j1+n2 ), ldb,t( n2+1, n2+1 ), & ldst, zero, work, n2 ) call stdlib${ii}$_dlacpy( 'FULL', n2, n1, work, n2, b( j1, j1+n2 ), ldb ) call stdlib${ii}$_dgemm( 'T', 'N', m, m, m, one, ir, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_dlacpy( 'FULL', m, m, work, m, ir, ldst ) ! accumulate transformations into q and z if requested. if( wantq ) then call stdlib${ii}$_dgemm( 'N', 'N', n, m, m, one, q( 1_${ik}$, j1 ), ldq, li,ldst, zero, work, & n ) call stdlib${ii}$_dlacpy( 'FULL', n, m, work, n, q( 1_${ik}$, j1 ), ldq ) end if if( wantz ) then call stdlib${ii}$_dgemm( 'N', 'N', n, m, m, one, z( 1_${ik}$, j1 ), ldz, ir,ldst, zero, work, & n ) call stdlib${ii}$_dlacpy( 'FULL', n, m, work, n, z( 1_${ik}$, j1 ), ldz ) end if ! update (a(j1:j1+m-1, m+j1:n), b(j1:j1+m-1, m+j1:n)) and ! (a(1:j1-1, j1:j1+m), b(1:j1-1, j1:j1+m)). i = j1 + m if( i<=n ) then call stdlib${ii}$_dgemm( 'T', 'N', m, n-i+1, m, one, li, ldst,a( j1, i ), lda, zero, & work, m ) call stdlib${ii}$_dlacpy( 'FULL', m, n-i+1, work, m, a( j1, i ), lda ) call stdlib${ii}$_dgemm( 'T', 'N', m, n-i+1, m, one, li, ldst,b( j1, i ), ldb, zero, & work, m ) call stdlib${ii}$_dlacpy( 'FULL', m, n-i+1, work, m, b( j1, i ), ldb ) end if i = j1 - 1_${ik}$ if( i>0_${ik}$ ) then call stdlib${ii}$_dgemm( 'N', 'N', i, m, m, one, a( 1_${ik}$, j1 ), lda, ir,ldst, zero, work, & i ) call stdlib${ii}$_dlacpy( 'FULL', i, m, work, i, a( 1_${ik}$, j1 ), lda ) call stdlib${ii}$_dgemm( 'N', 'N', i, m, m, one, b( 1_${ik}$, j1 ), ldb, ir,ldst, zero, work, & i ) call stdlib${ii}$_dlacpy( 'FULL', i, m, work, i, b( 1_${ik}$, j1 ), ldb ) end if ! exit with info = 0 if swap was successfully performed. return end if ! exit with info = 1 if swap was rejected. 70 continue info = 1_${ik}$ return end subroutine stdlib${ii}$_dtgex2 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$tgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, j1, n1, n2, & !! DTGEX2: swaps adjacent diagonal blocks (A11, B11) and (A22, B22) !! of size 1-by-1 or 2-by-2 in an upper (quasi) triangular matrix pair !! (A, B) by an orthogonal equivalence transformation. !! (A, B) must be in generalized real Schur canonical form (as returned !! by DGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2 !! diagonal blocks. B is upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**T = Q(out) * A(out) * Z(out)**T !! Q(in) * B(in) * Z(in)**T = Q(out) * B(out) * Z(out)**T work, lwork, info ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: j1, lda, ldb, ldq, ldz, lwork, n, n1, n2 ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) real(${rk}$), intent(out) :: work(*) ! ===================================================================== ! replaced various illegal calls to stdlib${ii}$_${ri}$copy by calls to stdlib${ii}$_${ri}$laset, or by do ! loops. sven hammarling, 1/5/02. ! Parameters real(${rk}$), parameter :: twenty = 2.0e+01_${rk}$ integer(${ik}$), parameter :: ldst = 4_${ik}$ logical(lk), parameter :: wands = .true. ! Local Scalars logical(lk) :: strong, weak integer(${ik}$) :: i, idum, linfo, m real(${rk}$) :: bqra21, brqa21, ddum, dnorma, dnormb, dscale, dsum, eps, f, g, sa, sb, & scale, smlnum, thresha, threshb ! Local Arrays integer(${ik}$) :: iwork(ldst) real(${rk}$) :: ai(2_${ik}$), ar(2_${ik}$), be(2_${ik}$), ir(ldst,ldst), ircop(ldst,ldst), li(ldst,ldst), licop(& ldst,ldst), s(ldst,ldst), scpy(ldst,ldst), t(ldst,ldst), taul(ldst), taur(ldst), tcpy(& ldst,ldst) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n<=1 .or. n1<=0 .or. n2<=0 )return if( n1>n .or. ( j1+n1 )>n )return m = n1 + n2 if( lwork=sb ) then call stdlib${ii}$_${ri}$lartg( s( 1_${ik}$, 1_${ik}$ ), s( 2_${ik}$, 1_${ik}$ ), li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ ),ddum ) else call stdlib${ii}$_${ri}$lartg( t( 1_${ik}$, 1_${ik}$ ), t( 2_${ik}$, 1_${ik}$ ), li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ ),ddum ) end if call stdlib${ii}$_${ri}$rot( 2_${ik}$, s( 1_${ik}$, 1_${ik}$ ), ldst, s( 2_${ik}$, 1_${ik}$ ), ldst, li( 1_${ik}$, 1_${ik}$ ),li( 2_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_${ri}$rot( 2_${ik}$, t( 1_${ik}$, 1_${ik}$ ), ldst, t( 2_${ik}$, 1_${ik}$ ), ldst, li( 1_${ik}$, 1_${ik}$ ),li( 2_${ik}$, 1_${ik}$ ) ) li( 2_${ik}$, 2_${ik}$ ) = li( 1_${ik}$, 1_${ik}$ ) li( 1_${ik}$, 2_${ik}$ ) = -li( 2_${ik}$, 1_${ik}$ ) ! weak stability test: |s21| <= o(eps f-norm((a))) ! and |t21| <= o(eps f-norm((b))) weak = abs( s( 2_${ik}$, 1_${ik}$ ) ) <= thresha .and.abs( t( 2_${ik}$, 1_${ik}$ ) ) <= threshb if( .not.weak )go to 70 if( wands ) then ! strong stability test: ! f-norm((a-ql**h*s*qr)) <= o(eps*f-norm((a))) ! and ! f-norm((b-ql**h*t*qr)) <= o(eps*f-norm((b))) call stdlib${ii}$_${ri}$lacpy( 'FULL', m, m, a( j1, j1 ), lda, work( m*m+1 ),m ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, m, m, one, li, ldst, s, ldst, zero,work, m ) call stdlib${ii}$_${ri}$gemm( 'N', 'T', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_${ri}$lassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sa = dscale*sqrt( dsum ) call stdlib${ii}$_${ri}$lacpy( 'FULL', m, m, b( j1, j1 ), ldb, work( m*m+1 ),m ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, m, m, one, li, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_${ri}$gemm( 'N', 'T', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_${ri}$lassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sb = dscale*sqrt( dsum ) strong = sa<=thresha .and. sb<=threshb if( .not.strong )go to 70 end if ! update (a(j1:j1+m-1, m+j1:n), b(j1:j1+m-1, m+j1:n)) and ! (a(1:j1-1, j1:j1+m), b(1:j1-1, j1:j1+m)). call stdlib${ii}$_${ri}$rot( j1+1, a( 1_${ik}$, j1 ), 1_${ik}$, a( 1_${ik}$, j1+1 ), 1_${ik}$, ir( 1_${ik}$, 1_${ik}$ ),ir( 2_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_${ri}$rot( j1+1, b( 1_${ik}$, j1 ), 1_${ik}$, b( 1_${ik}$, j1+1 ), 1_${ik}$, ir( 1_${ik}$, 1_${ik}$ ),ir( 2_${ik}$, 1_${ik}$ ) ) call stdlib${ii}$_${ri}$rot( n-j1+1, a( j1, j1 ), lda, a( j1+1, j1 ), lda,li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ & ) ) call stdlib${ii}$_${ri}$rot( n-j1+1, b( j1, j1 ), ldb, b( j1+1, j1 ), ldb,li( 1_${ik}$, 1_${ik}$ ), li( 2_${ik}$, 1_${ik}$ & ) ) ! set n1-by-n2 (2,1) - blocks to zero. a( j1+1, j1 ) = zero b( j1+1, j1 ) = zero ! accumulate transformations into q and z if requested. if( wantz )call stdlib${ii}$_${ri}$rot( n, z( 1_${ik}$, j1 ), 1_${ik}$, z( 1_${ik}$, j1+1 ), 1_${ik}$, ir( 1_${ik}$, 1_${ik}$ ),ir( 2_${ik}$, 1_${ik}$ & ) ) if( wantq )call stdlib${ii}$_${ri}$rot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j1+1 ), 1_${ik}$, li( 1_${ik}$, 1_${ik}$ ),li( 2_${ik}$, 1_${ik}$ & ) ) ! exit with info = 0 if swap was successfully performed. return else ! case 2: swap 1-by-1 and 2-by-2 blocks, or 2-by-2 ! and 2-by-2 blocks. ! solve the generalized sylvester equation ! s11 * r - l * s22 = scale * s12 ! t11 * r - l * t22 = scale * t12 ! for r and l. solutions in li and ir. call stdlib${ii}$_${ri}$lacpy( 'FULL', n1, n2, t( 1_${ik}$, n1+1 ), ldst, li, ldst ) call stdlib${ii}$_${ri}$lacpy( 'FULL', n1, n2, s( 1_${ik}$, n1+1 ), ldst,ir( n2+1, n1+1 ), ldst ) call stdlib${ii}$_${ri}$tgsy2( 'N', 0_${ik}$, n1, n2, s, ldst, s( n1+1, n1+1 ), ldst,ir( n2+1, n1+1 ),& ldst, t, ldst, t( n1+1, n1+1 ),ldst, li, ldst, scale, dsum, dscale, iwork, idum,& linfo ) if( linfo/=0 )go to 70 ! compute orthogonal matrix ql: ! ql**t * li = [ tl ] ! [ 0 ] ! where ! li = [ -l ] ! [ scale * identity(n2) ] do i = 1, n2 call stdlib${ii}$_${ri}$scal( n1, -one, li( 1_${ik}$, i ), 1_${ik}$ ) li( n1+i, i ) = scale end do call stdlib${ii}$_${ri}$geqr2( m, n2, li, ldst, taul, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_${ri}$org2r( m, m, n2, li, ldst, taul, work, linfo ) if( linfo/=0 )go to 70 ! compute orthogonal matrix rq: ! ir * rq**t = [ 0 tr], ! where ir = [ scale * identity(n1), r ] do i = 1, n1 ir( n2+i, i ) = scale end do call stdlib${ii}$_${ri}$gerq2( n1, m, ir( n2+1, 1_${ik}$ ), ldst, taur, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_${ri}$orgr2( m, m, n1, ir, ldst, taur, work, linfo ) if( linfo/=0 )go to 70 ! perform the swapping tentatively: call stdlib${ii}$_${ri}$gemm( 'T', 'N', m, m, m, one, li, ldst, s, ldst, zero,work, m ) call stdlib${ii}$_${ri}$gemm( 'N', 'T', m, m, m, one, work, m, ir, ldst, zero, s,ldst ) call stdlib${ii}$_${ri}$gemm( 'T', 'N', m, m, m, one, li, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_${ri}$gemm( 'N', 'T', m, m, m, one, work, m, ir, ldst, zero, t,ldst ) call stdlib${ii}$_${ri}$lacpy( 'F', m, m, s, ldst, scpy, ldst ) call stdlib${ii}$_${ri}$lacpy( 'F', m, m, t, ldst, tcpy, ldst ) call stdlib${ii}$_${ri}$lacpy( 'F', m, m, ir, ldst, ircop, ldst ) call stdlib${ii}$_${ri}$lacpy( 'F', m, m, li, ldst, licop, ldst ) ! triangularize the b-part by an rq factorization. ! apply transformation (from left) to a-part, giving s. call stdlib${ii}$_${ri}$gerq2( m, m, t, ldst, taur, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_${ri}$ormr2( 'R', 'T', m, m, m, t, ldst, taur, s, ldst, work,linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_${ri}$ormr2( 'L', 'N', m, m, m, t, ldst, taur, ir, ldst, work,linfo ) if( linfo/=0 )go to 70 ! compute f-norm(s21) in brqa21. (t21 is 0.) dscale = zero dsum = one do i = 1, n2 call stdlib${ii}$_${ri}$lassq( n1, s( n2+1, i ), 1_${ik}$, dscale, dsum ) end do brqa21 = dscale*sqrt( dsum ) ! triangularize the b-part by a qr factorization. ! apply transformation (from right) to a-part, giving s. call stdlib${ii}$_${ri}$geqr2( m, m, tcpy, ldst, taul, work, linfo ) if( linfo/=0 )go to 70 call stdlib${ii}$_${ri}$orm2r( 'L', 'T', m, m, m, tcpy, ldst, taul, scpy, ldst,work, info ) call stdlib${ii}$_${ri}$orm2r( 'R', 'N', m, m, m, tcpy, ldst, taul, licop, ldst,work, info ) if( linfo/=0 )go to 70 ! compute f-norm(s21) in bqra21. (t21 is 0.) dscale = zero dsum = one do i = 1, n2 call stdlib${ii}$_${ri}$lassq( n1, scpy( n2+1, i ), 1_${ik}$, dscale, dsum ) end do bqra21 = dscale*sqrt( dsum ) ! decide which method to use. ! weak stability test: ! f-norm(s21) <= o(eps * f-norm((s))) if( bqra21<=brqa21 .and. bqra21<=thresha ) then call stdlib${ii}$_${ri}$lacpy( 'F', m, m, scpy, ldst, s, ldst ) call stdlib${ii}$_${ri}$lacpy( 'F', m, m, tcpy, ldst, t, ldst ) call stdlib${ii}$_${ri}$lacpy( 'F', m, m, ircop, ldst, ir, ldst ) call stdlib${ii}$_${ri}$lacpy( 'F', m, m, licop, ldst, li, ldst ) else if( brqa21>=thresha ) then go to 70 end if ! set lower triangle of b-part to zero if (m>1_${ik}$) call stdlib${ii}$_${ri}$laset( 'LOWER', m-1, m-1, zero, zero, t(2_${ik}$,1_${ik}$), ldst ) if( wands ) then ! strong stability test: ! f-norm((a-ql**h*s*qr)) <= o(eps*f-norm((a))) ! and ! f-norm((b-ql**h*t*qr)) <= o(eps*f-norm((b))) call stdlib${ii}$_${ri}$lacpy( 'FULL', m, m, a( j1, j1 ), lda, work( m*m+1 ),m ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, m, m, one, li, ldst, s, ldst, zero,work, m ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_${ri}$lassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sa = dscale*sqrt( dsum ) call stdlib${ii}$_${ri}$lacpy( 'FULL', m, m, b( j1, j1 ), ldb, work( m*m+1 ),m ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, m, m, one, li, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, m, m, -one, work, m, ir, ldst, one,work( m*m+1 ),& m ) dscale = zero dsum = one call stdlib${ii}$_${ri}$lassq( m*m, work( m*m+1 ), 1_${ik}$, dscale, dsum ) sb = dscale*sqrt( dsum ) strong = sa<=thresha .and. sb<=threshb if( .not.strong )go to 70 end if ! if the swap is accepted ("weakly" and "strongly"), apply the ! transformations and set n1-by-n2 (2,1)-block to zero. call stdlib${ii}$_${ri}$laset( 'FULL', n1, n2, zero, zero, s(n2+1,1_${ik}$), ldst ) ! copy back m-by-m diagonal block starting at index j1 of (a, b) call stdlib${ii}$_${ri}$lacpy( 'F', m, m, s, ldst, a( j1, j1 ), lda ) call stdlib${ii}$_${ri}$lacpy( 'F', m, m, t, ldst, b( j1, j1 ), ldb ) call stdlib${ii}$_${ri}$laset( 'FULL', ldst, ldst, zero, zero, t, ldst ) ! standardize existing 2-by-2 blocks. call stdlib${ii}$_${ri}$laset( 'FULL', m, m, zero, zero, work, m ) work( 1_${ik}$ ) = one t( 1_${ik}$, 1_${ik}$ ) = one idum = lwork - m*m - 2_${ik}$ if( n2>1_${ik}$ ) then call stdlib${ii}$_${ri}$lagv2( a( j1, j1 ), lda, b( j1, j1 ), ldb, ar, ai, be,work( 1_${ik}$ ), & work( 2_${ik}$ ), t( 1_${ik}$, 1_${ik}$ ), t( 2_${ik}$, 1_${ik}$ ) ) work( m+1 ) = -work( 2_${ik}$ ) work( m+2 ) = work( 1_${ik}$ ) t( n2, n2 ) = t( 1_${ik}$, 1_${ik}$ ) t( 1_${ik}$, 2_${ik}$ ) = -t( 2_${ik}$, 1_${ik}$ ) end if work( m*m ) = one t( m, m ) = one if( n1>1_${ik}$ ) then call stdlib${ii}$_${ri}$lagv2( a( j1+n2, j1+n2 ), lda, b( j1+n2, j1+n2 ), ldb,taur, taul, & work( m*m+1 ), work( n2*m+n2+1 ),work( n2*m+n2+2 ), t( n2+1, n2+1 ),t( m, m-1 ) ) work( m*m ) = work( n2*m+n2+1 ) work( m*m-1 ) = -work( n2*m+n2+2 ) t( m, m ) = t( n2+1, n2+1 ) t( m-1, m ) = -t( m, m-1 ) end if call stdlib${ii}$_${ri}$gemm( 'T', 'N', n2, n1, n2, one, work, m, a( j1, j1+n2 ),lda, zero, & work( m*m+1 ), n2 ) call stdlib${ii}$_${ri}$lacpy( 'FULL', n2, n1, work( m*m+1 ), n2, a( j1, j1+n2 ),lda ) call stdlib${ii}$_${ri}$gemm( 'T', 'N', n2, n1, n2, one, work, m, b( j1, j1+n2 ),ldb, zero, & work( m*m+1 ), n2 ) call stdlib${ii}$_${ri}$lacpy( 'FULL', n2, n1, work( m*m+1 ), n2, b( j1, j1+n2 ),ldb ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', m, m, m, one, li, ldst, work, m, zero,work( m*m+1 ), m & ) call stdlib${ii}$_${ri}$lacpy( 'FULL', m, m, work( m*m+1 ), m, li, ldst ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', n2, n1, n1, one, a( j1, j1+n2 ), lda,t( n2+1, n2+1 ), & ldst, zero, work, n2 ) call stdlib${ii}$_${ri}$lacpy( 'FULL', n2, n1, work, n2, a( j1, j1+n2 ), lda ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', n2, n1, n1, one, b( j1, j1+n2 ), ldb,t( n2+1, n2+1 ), & ldst, zero, work, n2 ) call stdlib${ii}$_${ri}$lacpy( 'FULL', n2, n1, work, n2, b( j1, j1+n2 ), ldb ) call stdlib${ii}$_${ri}$gemm( 'T', 'N', m, m, m, one, ir, ldst, t, ldst, zero,work, m ) call stdlib${ii}$_${ri}$lacpy( 'FULL', m, m, work, m, ir, ldst ) ! accumulate transformations into q and z if requested. if( wantq ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, m, m, one, q( 1_${ik}$, j1 ), ldq, li,ldst, zero, work, & n ) call stdlib${ii}$_${ri}$lacpy( 'FULL', n, m, work, n, q( 1_${ik}$, j1 ), ldq ) end if if( wantz ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, m, m, one, z( 1_${ik}$, j1 ), ldz, ir,ldst, zero, work, & n ) call stdlib${ii}$_${ri}$lacpy( 'FULL', n, m, work, n, z( 1_${ik}$, j1 ), ldz ) end if ! update (a(j1:j1+m-1, m+j1:n), b(j1:j1+m-1, m+j1:n)) and ! (a(1:j1-1, j1:j1+m), b(1:j1-1, j1:j1+m)). i = j1 + m if( i<=n ) then call stdlib${ii}$_${ri}$gemm( 'T', 'N', m, n-i+1, m, one, li, ldst,a( j1, i ), lda, zero, & work, m ) call stdlib${ii}$_${ri}$lacpy( 'FULL', m, n-i+1, work, m, a( j1, i ), lda ) call stdlib${ii}$_${ri}$gemm( 'T', 'N', m, n-i+1, m, one, li, ldst,b( j1, i ), ldb, zero, & work, m ) call stdlib${ii}$_${ri}$lacpy( 'FULL', m, n-i+1, work, m, b( j1, i ), ldb ) end if i = j1 - 1_${ik}$ if( i>0_${ik}$ ) then call stdlib${ii}$_${ri}$gemm( 'N', 'N', i, m, m, one, a( 1_${ik}$, j1 ), lda, ir,ldst, zero, work, & i ) call stdlib${ii}$_${ri}$lacpy( 'FULL', i, m, work, i, a( 1_${ik}$, j1 ), lda ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', i, m, m, one, b( 1_${ik}$, j1 ), ldb, ir,ldst, zero, work, & i ) call stdlib${ii}$_${ri}$lacpy( 'FULL', i, m, work, i, b( 1_${ik}$, j1 ), ldb ) end if ! exit with info = 0 if swap was successfully performed. return end if ! exit with info = 1 if swap was rejected. 70 continue info = 1_${ik}$ return end subroutine stdlib${ii}$_${ri}$tgex2 #:endif #:endfor pure module subroutine stdlib${ii}$_ctgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, j1, info ) !! CTGEX2 swaps adjacent diagonal 1 by 1 blocks (A11,B11) and (A22,B22) !! in an upper triangular matrix pair (A, B) by an unitary equivalence !! transformation. !! (A, B) must be in generalized Schur canonical form, that is, A and !! B are both upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**H = Q(out) * A(out) * Z(out)**H !! Q(in) * B(in) * Z(in)**H = Q(out) * B(out) * Z(out)**H ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: j1, lda, ldb, ldq, ldz, n ! Array Arguments complex(sp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ===================================================================== ! Parameters real(sp), parameter :: twenty = 2.0e+1_sp integer(${ik}$), parameter :: ldst = 2_${ik}$ logical(lk), parameter :: wands = .true. ! Local Scalars logical(lk) :: strong, weak integer(${ik}$) :: i, m real(sp) :: cq, cz, eps, sa, sb, scale, smlnum, sum, thresha, threshb complex(sp) :: cdum, f, g, sq, sz ! Local Arrays complex(sp) :: s(ldst,ldst), t(ldst,ldst), work(8_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n<=1 )return m = ldst weak = .false. strong = .false. ! make a local copy of selected block in (a, b) call stdlib${ii}$_clacpy( 'FULL', m, m, a( j1, j1 ), lda, s, ldst ) call stdlib${ii}$_clacpy( 'FULL', m, m, b( j1, j1 ), ldb, t, ldst ) ! compute the threshold for testing the acceptance of swapping. eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) / eps scale = real( czero,KIND=sp) sum = real( cone,KIND=sp) call stdlib${ii}$_clacpy( 'FULL', m, m, s, ldst, work, m ) call stdlib${ii}$_clacpy( 'FULL', m, m, t, ldst, work( m*m+1 ), m ) call stdlib${ii}$_classq( m*m, work, 1_${ik}$, scale, sum ) sa = scale*sqrt( sum ) scale = real( czero,KIND=sp) sum = real( cone,KIND=sp) call stdlib${ii}$_classq( m*m, work(m*m+1), 1_${ik}$, scale, sum ) sb = scale*sqrt( sum ) ! thres has been changed from ! thresh = max( ten*eps*sa, smlnum ) ! to ! thresh = max( twenty*eps*sa, smlnum ) ! on 04/01/10. ! "bug" reported by ondra kamenik, confirmed by julie langou, fixed by ! jim demmel and guillaume revy. see forum post 1783. thresha = max( twenty*eps*sa, smlnum ) threshb = max( twenty*eps*sb, smlnum ) ! compute unitary ql and rq that swap 1-by-1 and 1-by-1 blocks ! using givens rotations and perform the swap tentatively. f = s( 2_${ik}$, 2_${ik}$ )*t( 1_${ik}$, 1_${ik}$ ) - t( 2_${ik}$, 2_${ik}$ )*s( 1_${ik}$, 1_${ik}$ ) g = s( 2_${ik}$, 2_${ik}$ )*t( 1_${ik}$, 2_${ik}$ ) - t( 2_${ik}$, 2_${ik}$ )*s( 1_${ik}$, 2_${ik}$ ) sa = abs( s( 2_${ik}$, 2_${ik}$ ) ) * abs( t( 1_${ik}$, 1_${ik}$ ) ) sb = abs( s( 1_${ik}$, 1_${ik}$ ) ) * abs( t( 2_${ik}$, 2_${ik}$ ) ) call stdlib${ii}$_clartg( g, f, cz, sz, cdum ) sz = -sz call stdlib${ii}$_crot( 2_${ik}$, s( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, s( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, cz, conjg( sz ) ) call stdlib${ii}$_crot( 2_${ik}$, t( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, t( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, cz, conjg( sz ) ) if( sa>=sb ) then call stdlib${ii}$_clartg( s( 1_${ik}$, 1_${ik}$ ), s( 2_${ik}$, 1_${ik}$ ), cq, sq, cdum ) else call stdlib${ii}$_clartg( t( 1_${ik}$, 1_${ik}$ ), t( 2_${ik}$, 1_${ik}$ ), cq, sq, cdum ) end if call stdlib${ii}$_crot( 2_${ik}$, s( 1_${ik}$, 1_${ik}$ ), ldst, s( 2_${ik}$, 1_${ik}$ ), ldst, cq, sq ) call stdlib${ii}$_crot( 2_${ik}$, t( 1_${ik}$, 1_${ik}$ ), ldst, t( 2_${ik}$, 1_${ik}$ ), ldst, cq, sq ) ! weak stability test: |s21| <= o(eps f-norm((a))) ! and |t21| <= o(eps f-norm((b))) weak = abs( s( 2_${ik}$, 1_${ik}$ ) )<=thresha .and.abs( t( 2_${ik}$, 1_${ik}$ ) )<=threshb if( .not.weak )go to 20 if( wands ) then ! strong stability test: ! f-norm((a-ql**h*s*qr, b-ql**h*t*qr)) <= o(eps*f-norm((a, b))) call stdlib${ii}$_clacpy( 'FULL', m, m, s, ldst, work, m ) call stdlib${ii}$_clacpy( 'FULL', m, m, t, ldst, work( m*m+1 ), m ) call stdlib${ii}$_crot( 2_${ik}$, work, 1_${ik}$, work( 3_${ik}$ ), 1_${ik}$, cz, -conjg( sz ) ) call stdlib${ii}$_crot( 2_${ik}$, work( 5_${ik}$ ), 1_${ik}$, work( 7_${ik}$ ), 1_${ik}$, cz, -conjg( sz ) ) call stdlib${ii}$_crot( 2_${ik}$, work, 2_${ik}$, work( 2_${ik}$ ), 2_${ik}$, cq, -sq ) call stdlib${ii}$_crot( 2_${ik}$, work( 5_${ik}$ ), 2_${ik}$, work( 6_${ik}$ ), 2_${ik}$, cq, -sq ) do i = 1, 2 work( i ) = work( i ) - a( j1+i-1, j1 ) work( i+2 ) = work( i+2 ) - a( j1+i-1, j1+1 ) work( i+4 ) = work( i+4 ) - b( j1+i-1, j1 ) work( i+6 ) = work( i+6 ) - b( j1+i-1, j1+1 ) end do scale = real( czero,KIND=sp) sum = real( cone,KIND=sp) call stdlib${ii}$_classq( m*m, work, 1_${ik}$, scale, sum ) sa = scale*sqrt( sum ) scale = real( czero,KIND=sp) sum = real( cone,KIND=sp) call stdlib${ii}$_classq( m*m, work(m*m+1), 1_${ik}$, scale, sum ) sb = scale*sqrt( sum ) strong = sa<=thresha .and. sb<=threshb if( .not.strong )go to 20 end if ! if the swap is accepted ("weakly" and "strongly"), apply the ! equivalence transformations to the original matrix pair (a,b) call stdlib${ii}$_crot( j1+1, a( 1_${ik}$, j1 ), 1_${ik}$, a( 1_${ik}$, j1+1 ), 1_${ik}$, cz, conjg( sz ) ) call stdlib${ii}$_crot( j1+1, b( 1_${ik}$, j1 ), 1_${ik}$, b( 1_${ik}$, j1+1 ), 1_${ik}$, cz, conjg( sz ) ) call stdlib${ii}$_crot( n-j1+1, a( j1, j1 ), lda, a( j1+1, j1 ), lda, cq, sq ) call stdlib${ii}$_crot( n-j1+1, b( j1, j1 ), ldb, b( j1+1, j1 ), ldb, cq, sq ) ! set n1 by n2 (2,1) blocks to 0 a( j1+1, j1 ) = czero b( j1+1, j1 ) = czero ! accumulate transformations into q and z if requested. if( wantz )call stdlib${ii}$_crot( n, z( 1_${ik}$, j1 ), 1_${ik}$, z( 1_${ik}$, j1+1 ), 1_${ik}$, cz, conjg( sz ) ) if( wantq )call stdlib${ii}$_crot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j1+1 ), 1_${ik}$, cq, conjg( sq ) ) ! exit with info = 0 if swap was successfully performed. return ! exit with info = 1 if swap was rejected. 20 continue info = 1_${ik}$ return end subroutine stdlib${ii}$_ctgex2 pure module subroutine stdlib${ii}$_ztgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, j1, info ) !! ZTGEX2 swaps adjacent diagonal 1 by 1 blocks (A11,B11) and (A22,B22) !! in an upper triangular matrix pair (A, B) by an unitary equivalence !! transformation. !! (A, B) must be in generalized Schur canonical form, that is, A and !! B are both upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**H = Q(out) * A(out) * Z(out)**H !! Q(in) * B(in) * Z(in)**H = Q(out) * B(out) * Z(out)**H ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: j1, lda, ldb, ldq, ldz, n ! Array Arguments complex(dp), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ===================================================================== ! Parameters real(dp), parameter :: twenty = 2.0e+1_dp integer(${ik}$), parameter :: ldst = 2_${ik}$ logical(lk), parameter :: wands = .true. ! Local Scalars logical(lk) :: strong, weak integer(${ik}$) :: i, m real(dp) :: cq, cz, eps, sa, sb, scale, smlnum, sum, thresha, threshb complex(dp) :: cdum, f, g, sq, sz ! Local Arrays complex(dp) :: s(ldst,ldst), t(ldst,ldst), work(8_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n<=1 )return m = ldst weak = .false. strong = .false. ! make a local copy of selected block in (a, b) call stdlib${ii}$_zlacpy( 'FULL', m, m, a( j1, j1 ), lda, s, ldst ) call stdlib${ii}$_zlacpy( 'FULL', m, m, b( j1, j1 ), ldb, t, ldst ) ! compute the threshold for testing the acceptance of swapping. eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) / eps scale = real( czero,KIND=dp) sum = real( cone,KIND=dp) call stdlib${ii}$_zlacpy( 'FULL', m, m, s, ldst, work, m ) call stdlib${ii}$_zlacpy( 'FULL', m, m, t, ldst, work( m*m+1 ), m ) call stdlib${ii}$_zlassq( m*m, work, 1_${ik}$, scale, sum ) sa = scale*sqrt( sum ) scale = real( czero,KIND=dp) sum = real( cone,KIND=dp) call stdlib${ii}$_zlassq( m*m, work(m*m+1), 1_${ik}$, scale, sum ) sb = scale*sqrt( sum ) ! thres has been changed from ! thresh = max( ten*eps*sa, smlnum ) ! to ! thresh = max( twenty*eps*sa, smlnum ) ! on 04/01/10. ! "bug" reported by ondra kamenik, confirmed by julie langou, fixed by ! jim demmel and guillaume revy. see forum post 1783. thresha = max( twenty*eps*sa, smlnum ) threshb = max( twenty*eps*sb, smlnum ) ! compute unitary ql and rq that swap 1-by-1 and 1-by-1 blocks ! using givens rotations and perform the swap tentatively. f = s( 2_${ik}$, 2_${ik}$ )*t( 1_${ik}$, 1_${ik}$ ) - t( 2_${ik}$, 2_${ik}$ )*s( 1_${ik}$, 1_${ik}$ ) g = s( 2_${ik}$, 2_${ik}$ )*t( 1_${ik}$, 2_${ik}$ ) - t( 2_${ik}$, 2_${ik}$ )*s( 1_${ik}$, 2_${ik}$ ) sa = abs( s( 2_${ik}$, 2_${ik}$ ) ) * abs( t( 1_${ik}$, 1_${ik}$ ) ) sb = abs( s( 1_${ik}$, 1_${ik}$ ) ) * abs( t( 2_${ik}$, 2_${ik}$ ) ) call stdlib${ii}$_zlartg( g, f, cz, sz, cdum ) sz = -sz call stdlib${ii}$_zrot( 2_${ik}$, s( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, s( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, cz, conjg( sz ) ) call stdlib${ii}$_zrot( 2_${ik}$, t( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, t( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, cz, conjg( sz ) ) if( sa>=sb ) then call stdlib${ii}$_zlartg( s( 1_${ik}$, 1_${ik}$ ), s( 2_${ik}$, 1_${ik}$ ), cq, sq, cdum ) else call stdlib${ii}$_zlartg( t( 1_${ik}$, 1_${ik}$ ), t( 2_${ik}$, 1_${ik}$ ), cq, sq, cdum ) end if call stdlib${ii}$_zrot( 2_${ik}$, s( 1_${ik}$, 1_${ik}$ ), ldst, s( 2_${ik}$, 1_${ik}$ ), ldst, cq, sq ) call stdlib${ii}$_zrot( 2_${ik}$, t( 1_${ik}$, 1_${ik}$ ), ldst, t( 2_${ik}$, 1_${ik}$ ), ldst, cq, sq ) ! weak stability test: |s21| <= o(eps f-norm((a))) ! and |t21| <= o(eps f-norm((b))) weak = abs( s( 2_${ik}$, 1_${ik}$ ) )<=thresha .and.abs( t( 2_${ik}$, 1_${ik}$ ) )<=threshb if( .not.weak )go to 20 if( wands ) then ! strong stability test: ! f-norm((a-ql**h*s*qr)) <= o(eps*f-norm((a))) ! and ! f-norm((b-ql**h*t*qr)) <= o(eps*f-norm((b))) call stdlib${ii}$_zlacpy( 'FULL', m, m, s, ldst, work, m ) call stdlib${ii}$_zlacpy( 'FULL', m, m, t, ldst, work( m*m+1 ), m ) call stdlib${ii}$_zrot( 2_${ik}$, work, 1_${ik}$, work( 3_${ik}$ ), 1_${ik}$, cz, -conjg( sz ) ) call stdlib${ii}$_zrot( 2_${ik}$, work( 5_${ik}$ ), 1_${ik}$, work( 7_${ik}$ ), 1_${ik}$, cz, -conjg( sz ) ) call stdlib${ii}$_zrot( 2_${ik}$, work, 2_${ik}$, work( 2_${ik}$ ), 2_${ik}$, cq, -sq ) call stdlib${ii}$_zrot( 2_${ik}$, work( 5_${ik}$ ), 2_${ik}$, work( 6_${ik}$ ), 2_${ik}$, cq, -sq ) do i = 1, 2 work( i ) = work( i ) - a( j1+i-1, j1 ) work( i+2 ) = work( i+2 ) - a( j1+i-1, j1+1 ) work( i+4 ) = work( i+4 ) - b( j1+i-1, j1 ) work( i+6 ) = work( i+6 ) - b( j1+i-1, j1+1 ) end do scale = real( czero,KIND=dp) sum = real( cone,KIND=dp) call stdlib${ii}$_zlassq( m*m, work, 1_${ik}$, scale, sum ) sa = scale*sqrt( sum ) scale = real( czero,KIND=dp) sum = real( cone,KIND=dp) call stdlib${ii}$_zlassq( m*m, work(m*m+1), 1_${ik}$, scale, sum ) sb = scale*sqrt( sum ) strong = sa<=thresha .and. sb<=threshb if( .not.strong )go to 20 end if ! if the swap is accepted ("weakly" and "strongly"), apply the ! equivalence transformations to the original matrix pair (a,b) call stdlib${ii}$_zrot( j1+1, a( 1_${ik}$, j1 ), 1_${ik}$, a( 1_${ik}$, j1+1 ), 1_${ik}$, cz,conjg( sz ) ) call stdlib${ii}$_zrot( j1+1, b( 1_${ik}$, j1 ), 1_${ik}$, b( 1_${ik}$, j1+1 ), 1_${ik}$, cz,conjg( sz ) ) call stdlib${ii}$_zrot( n-j1+1, a( j1, j1 ), lda, a( j1+1, j1 ), lda, cq, sq ) call stdlib${ii}$_zrot( n-j1+1, b( j1, j1 ), ldb, b( j1+1, j1 ), ldb, cq, sq ) ! set n1 by n2 (2,1) blocks to 0 a( j1+1, j1 ) = czero b( j1+1, j1 ) = czero ! accumulate transformations into q and z if requested. if( wantz )call stdlib${ii}$_zrot( n, z( 1_${ik}$, j1 ), 1_${ik}$, z( 1_${ik}$, j1+1 ), 1_${ik}$, cz,conjg( sz ) ) if( wantq )call stdlib${ii}$_zrot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j1+1 ), 1_${ik}$, cq,conjg( sq ) ) ! exit with info = 0 if swap was successfully performed. return ! exit with info = 1 if swap was rejected. 20 continue info = 1_${ik}$ return end subroutine stdlib${ii}$_ztgex2 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$tgex2( wantq, wantz, n, a, lda, b, ldb, q, ldq, z,ldz, j1, info ) !! ZTGEX2: swaps adjacent diagonal 1 by 1 blocks (A11,B11) and (A22,B22) !! in an upper triangular matrix pair (A, B) by an unitary equivalence !! transformation. !! (A, B) must be in generalized Schur canonical form, that is, A and !! B are both upper triangular. !! Optionally, the matrices Q and Z of generalized Schur vectors are !! updated. !! Q(in) * A(in) * Z(in)**H = Q(out) * A(out) * Z(out)**H !! Q(in) * B(in) * Z(in)**H = Q(out) * B(out) * Z(out)**H ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments logical(lk), intent(in) :: wantq, wantz integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: j1, lda, ldb, ldq, ldz, n ! Array Arguments complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*), q(ldq,*), z(ldz,*) ! ===================================================================== ! Parameters real(${ck}$), parameter :: twenty = 2.0e+1_${ck}$ integer(${ik}$), parameter :: ldst = 2_${ik}$ logical(lk), parameter :: wands = .true. ! Local Scalars logical(lk) :: strong, weak integer(${ik}$) :: i, m real(${ck}$) :: cq, cz, eps, sa, sb, scale, smlnum, sum, thresha, threshb complex(${ck}$) :: cdum, f, g, sq, sz ! Local Arrays complex(${ck}$) :: s(ldst,ldst), t(ldst,ldst), work(8_${ik}$) ! Intrinsic Functions ! Executable Statements info = 0_${ik}$ ! quick return if possible if( n<=1 )return m = ldst weak = .false. strong = .false. ! make a local copy of selected block in (a, b) call stdlib${ii}$_${ci}$lacpy( 'FULL', m, m, a( j1, j1 ), lda, s, ldst ) call stdlib${ii}$_${ci}$lacpy( 'FULL', m, m, b( j1, j1 ), ldb, t, ldst ) ! compute the threshold for testing the acceptance of swapping. eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' ) smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) / eps scale = real( czero,KIND=${ck}$) sum = real( cone,KIND=${ck}$) call stdlib${ii}$_${ci}$lacpy( 'FULL', m, m, s, ldst, work, m ) call stdlib${ii}$_${ci}$lacpy( 'FULL', m, m, t, ldst, work( m*m+1 ), m ) call stdlib${ii}$_${ci}$lassq( m*m, work, 1_${ik}$, scale, sum ) sa = scale*sqrt( sum ) scale = real( czero,KIND=${ck}$) sum = real( cone,KIND=${ck}$) call stdlib${ii}$_${ci}$lassq( m*m, work(m*m+1), 1_${ik}$, scale, sum ) sb = scale*sqrt( sum ) ! thres has been changed from ! thresh = max( ten*eps*sa, smlnum ) ! to ! thresh = max( twenty*eps*sa, smlnum ) ! on 04/01/10. ! "bug" reported by ondra kamenik, confirmed by julie langou, fixed by ! jim demmel and guillaume revy. see forum post 1783. thresha = max( twenty*eps*sa, smlnum ) threshb = max( twenty*eps*sb, smlnum ) ! compute unitary ql and rq that swap 1-by-1 and 1-by-1 blocks ! using givens rotations and perform the swap tentatively. f = s( 2_${ik}$, 2_${ik}$ )*t( 1_${ik}$, 1_${ik}$ ) - t( 2_${ik}$, 2_${ik}$ )*s( 1_${ik}$, 1_${ik}$ ) g = s( 2_${ik}$, 2_${ik}$ )*t( 1_${ik}$, 2_${ik}$ ) - t( 2_${ik}$, 2_${ik}$ )*s( 1_${ik}$, 2_${ik}$ ) sa = abs( s( 2_${ik}$, 2_${ik}$ ) ) * abs( t( 1_${ik}$, 1_${ik}$ ) ) sb = abs( s( 1_${ik}$, 1_${ik}$ ) ) * abs( t( 2_${ik}$, 2_${ik}$ ) ) call stdlib${ii}$_${ci}$lartg( g, f, cz, sz, cdum ) sz = -sz call stdlib${ii}$_${ci}$rot( 2_${ik}$, s( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, s( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, cz, conjg( sz ) ) call stdlib${ii}$_${ci}$rot( 2_${ik}$, t( 1_${ik}$, 1_${ik}$ ), 1_${ik}$, t( 1_${ik}$, 2_${ik}$ ), 1_${ik}$, cz, conjg( sz ) ) if( sa>=sb ) then call stdlib${ii}$_${ci}$lartg( s( 1_${ik}$, 1_${ik}$ ), s( 2_${ik}$, 1_${ik}$ ), cq, sq, cdum ) else call stdlib${ii}$_${ci}$lartg( t( 1_${ik}$, 1_${ik}$ ), t( 2_${ik}$, 1_${ik}$ ), cq, sq, cdum ) end if call stdlib${ii}$_${ci}$rot( 2_${ik}$, s( 1_${ik}$, 1_${ik}$ ), ldst, s( 2_${ik}$, 1_${ik}$ ), ldst, cq, sq ) call stdlib${ii}$_${ci}$rot( 2_${ik}$, t( 1_${ik}$, 1_${ik}$ ), ldst, t( 2_${ik}$, 1_${ik}$ ), ldst, cq, sq ) ! weak stability test: |s21| <= o(eps f-norm((a))) ! and |t21| <= o(eps f-norm((b))) weak = abs( s( 2_${ik}$, 1_${ik}$ ) )<=thresha .and.abs( t( 2_${ik}$, 1_${ik}$ ) )<=threshb if( .not.weak )go to 20 if( wands ) then ! strong stability test: ! f-norm((a-ql**h*s*qr)) <= o(eps*f-norm((a))) ! and ! f-norm((b-ql**h*t*qr)) <= o(eps*f-norm((b))) call stdlib${ii}$_${ci}$lacpy( 'FULL', m, m, s, ldst, work, m ) call stdlib${ii}$_${ci}$lacpy( 'FULL', m, m, t, ldst, work( m*m+1 ), m ) call stdlib${ii}$_${ci}$rot( 2_${ik}$, work, 1_${ik}$, work( 3_${ik}$ ), 1_${ik}$, cz, -conjg( sz ) ) call stdlib${ii}$_${ci}$rot( 2_${ik}$, work( 5_${ik}$ ), 1_${ik}$, work( 7_${ik}$ ), 1_${ik}$, cz, -conjg( sz ) ) call stdlib${ii}$_${ci}$rot( 2_${ik}$, work, 2_${ik}$, work( 2_${ik}$ ), 2_${ik}$, cq, -sq ) call stdlib${ii}$_${ci}$rot( 2_${ik}$, work( 5_${ik}$ ), 2_${ik}$, work( 6_${ik}$ ), 2_${ik}$, cq, -sq ) do i = 1, 2 work( i ) = work( i ) - a( j1+i-1, j1 ) work( i+2 ) = work( i+2 ) - a( j1+i-1, j1+1 ) work( i+4 ) = work( i+4 ) - b( j1+i-1, j1 ) work( i+6 ) = work( i+6 ) - b( j1+i-1, j1+1 ) end do scale = real( czero,KIND=${ck}$) sum = real( cone,KIND=${ck}$) call stdlib${ii}$_${ci}$lassq( m*m, work, 1_${ik}$, scale, sum ) sa = scale*sqrt( sum ) scale = real( czero,KIND=${ck}$) sum = real( cone,KIND=${ck}$) call stdlib${ii}$_${ci}$lassq( m*m, work(m*m+1), 1_${ik}$, scale, sum ) sb = scale*sqrt( sum ) strong = sa<=thresha .and. sb<=threshb if( .not.strong )go to 20 end if ! if the swap is accepted ("weakly" and "strongly"), apply the ! equivalence transformations to the original matrix pair (a,b) call stdlib${ii}$_${ci}$rot( j1+1, a( 1_${ik}$, j1 ), 1_${ik}$, a( 1_${ik}$, j1+1 ), 1_${ik}$, cz,conjg( sz ) ) call stdlib${ii}$_${ci}$rot( j1+1, b( 1_${ik}$, j1 ), 1_${ik}$, b( 1_${ik}$, j1+1 ), 1_${ik}$, cz,conjg( sz ) ) call stdlib${ii}$_${ci}$rot( n-j1+1, a( j1, j1 ), lda, a( j1+1, j1 ), lda, cq, sq ) call stdlib${ii}$_${ci}$rot( n-j1+1, b( j1, j1 ), ldb, b( j1+1, j1 ), ldb, cq, sq ) ! set n1 by n2 (2,1) blocks to 0 a( j1+1, j1 ) = czero b( j1+1, j1 ) = czero ! accumulate transformations into q and z if requested. if( wantz )call stdlib${ii}$_${ci}$rot( n, z( 1_${ik}$, j1 ), 1_${ik}$, z( 1_${ik}$, j1+1 ), 1_${ik}$, cz,conjg( sz ) ) if( wantq )call stdlib${ii}$_${ci}$rot( n, q( 1_${ik}$, j1 ), 1_${ik}$, q( 1_${ik}$, j1+1 ), 1_${ik}$, cq,conjg( sq ) ) ! exit with info = 0 if swap was successfully performed. return ! exit with info = 1 if swap was rejected. 20 continue info = 1_${ik}$ return end subroutine stdlib${ii}$_${ci}$tgex2 #:endif #:endfor #:endfor end submodule stdlib_lapack_eigv_comp2 fortran-lang-stdlib-0ede301/src/lapack/stdlib_lapack_givens_jacobi_rot.fypp0000664000175000017500000047616715135654166027477 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_lapack_base) stdlib_lapack_givens_jacobi_rot implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slartg( f, g, c, s, r ) !! SLARTG generates a plane rotation so that !! [ C S ] . [ F ] = [ R ] !! [ -S C ] [ G ] [ 0 ] !! where C**2 + S**2 = 1. !! The mathematical formulas used for C and S are !! R = sign(F) * sqrt(F**2 + G**2) !! C = F / R !! S = G / R !! Hence C >= 0. The algorithm used to compute these quantities !! incorporates scaling to avoid overflow or underflow in computing the !! square root of the sum of squares. !! This version is discontinuous in R at F = 0 but it returns the same !! C and S as SLARTG for complex inputs (F,0) and (G,0). !! This is a more accurate version of the BLAS1 routine SROTG, !! with the following other differences: !! F and G are unchanged on return. !! If G=0, then C=1 and S=0. !! If F=0 and (G .ne. 0), then C=0 and S=sign(1,G) without doing any !! floating point operations (saves work in SBDSQR when !! there are zeros on the diagonal). !! If F exceeds G in magnitude, C will be positive. !! Below, wp=>sp stands for single precision from LA_CONSTANTS module. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! february 2021 use stdlib_blas_constants_sp, only: zero, half, one, czero, safmax, safmin, rtmin, rtmax ! Scalar Arguments real(sp), intent(out) :: c, r, s real(sp), intent(in) :: f, g ! ===================================================================== ! Local Scalars real(sp) :: d, f1, fs, g1, gs, p, u, uu ! Intrinsic Functions ! Executable Statements f1 = abs( f ) g1 = abs( g ) if( g == zero ) then c = one s = zero r = f else if( f == zero ) then c = zero s = sign( one, g ) r = g1 else if( f1 > rtmin .and. f1 < rtmax .and. g1 > rtmin .and. g1 < rtmax ) & then d = sqrt( f*f + g*g ) p = one / d c = f1*p s = g*sign( p, f ) r = sign( d, f ) else u = min( safmax, max( safmin, f1, g1 ) ) uu = one / u fs = f*uu gs = g*uu d = sqrt( fs*fs + gs*gs ) p = one / d c = abs( fs )*p s = gs*sign( p, f ) r = sign( d, f )*u end if return end subroutine stdlib${ii}$_slartg pure module subroutine stdlib${ii}$_dlartg( f, g, c, s, r ) !! DLARTG generates a plane rotation so that !! [ C S ] . [ F ] = [ R ] !! [ -S C ] [ G ] [ 0 ] !! where C**2 + S**2 = 1. !! The mathematical formulas used for C and S are !! R = sign(F) * sqrt(F**2 + G**2) !! C = F / R !! S = G / R !! Hence C >= 0. The algorithm used to compute these quantities !! incorporates scaling to avoid overflow or underflow in computing the !! square root of the sum of squares. !! This version is discontinuous in R at F = 0 but it returns the same !! C and S as ZLARTG for complex inputs (F,0) and (G,0). !! This is a more accurate version of the BLAS1 routine DROTG, !! with the following other differences: !! F and G are unchanged on return. !! If G=0, then C=1 and S=0. !! If F=0 and (G .ne. 0), then C=0 and S=sign(1,G) without doing any !! floating point operations (saves work in DBDSQR when !! there are zeros on the diagonal). !! If F exceeds G in magnitude, C will be positive. !! Below, wp=>dp stands for double precision from LA_CONSTANTS module. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! february 2021 use stdlib_blas_constants_dp, only: zero, half, one, czero, safmax, safmin, rtmin, rtmax ! Scalar Arguments real(dp), intent(out) :: c, r, s real(dp), intent(in) :: f, g ! ===================================================================== ! Local Scalars real(dp) :: d, f1, fs, g1, gs, p, u, uu ! Intrinsic Functions ! Executable Statements f1 = abs( f ) g1 = abs( g ) if( g == zero ) then c = one s = zero r = f else if( f == zero ) then c = zero s = sign( one, g ) r = g1 else if( f1 > rtmin .and. f1 < rtmax .and. g1 > rtmin .and. g1 < rtmax ) & then d = sqrt( f*f + g*g ) p = one / d c = f1*p s = g*sign( p, f ) r = sign( d, f ) else u = min( safmax, max( safmin, f1, g1 ) ) uu = one / u fs = f*uu gs = g*uu d = sqrt( fs*fs + gs*gs ) p = one / d c = abs( fs )*p s = gs*sign( p, f ) r = sign( d, f )*u end if return end subroutine stdlib${ii}$_dlartg #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lartg( f, g, c, s, r ) !! DLARTG: generates a plane rotation so that !! [ C S ] . [ F ] = [ R ] !! [ -S C ] [ G ] [ 0 ] !! where C**2 + S**2 = 1. !! The mathematical formulas used for C and S are !! R = sign(F) * sqrt(F**2 + G**2) !! C = F / R !! S = G / R !! Hence C >= 0. The algorithm used to compute these quantities !! incorporates scaling to avoid overflow or underflow in computing the !! square root of the sum of squares. !! This version is discontinuous in R at F = 0 but it returns the same !! C and S as ZLARTG for complex inputs (F,0) and (G,0). !! This is a more accurate version of the BLAS1 routine DROTG, !! with the following other differences: !! F and G are unchanged on return. !! If G=0, then C=1 and S=0. !! If F=0 and (G .ne. 0), then C=0 and S=sign(1,G) without doing any !! floating point operations (saves work in DBDSQR when !! there are zeros on the diagonal). !! If F exceeds G in magnitude, C will be positive. !! Below, wp=>dp stands for quad precision from LA_CONSTANTS module. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! february 2021 use stdlib_blas_constants_${rk}$, only: zero, half, one, czero, safmax, safmin, rtmin, rtmax ! Scalar Arguments real(${rk}$), intent(out) :: c, r, s real(${rk}$), intent(in) :: f, g ! ===================================================================== ! Local Scalars real(${rk}$) :: d, f1, fs, g1, gs, p, u, uu ! Intrinsic Functions ! Executable Statements f1 = abs( f ) g1 = abs( g ) if( g == zero ) then c = one s = zero r = f else if( f == zero ) then c = zero s = sign( one, g ) r = g1 else if( f1 > rtmin .and. f1 < rtmax .and. g1 > rtmin .and. g1 < rtmax ) & then d = sqrt( f*f + g*g ) p = one / d c = f1*p s = g*sign( p, f ) r = sign( d, f ) else u = min( safmax, max( safmin, f1, g1 ) ) uu = one / u fs = f*uu gs = g*uu d = sqrt( fs*fs + gs*gs ) p = one / d c = abs( fs )*p s = gs*sign( p, f ) r = sign( d, f )*u end if return end subroutine stdlib${ii}$_${ri}$lartg #:endif #:endfor pure module subroutine stdlib${ii}$_clartg( f, g, c, s, r ) !! CLARTG generates a plane rotation so that !! [ C S ] . [ F ] = [ R ] !! [ -conjg(S) C ] [ G ] [ 0 ] !! where C is real and C**2 + |S|**2 = 1. !! The mathematical formulas used for C and S are !! sgn(x) = { x / |x|, x != 0 !! { 1, x = 0 !! R = sgn(F) * sqrt(|F|**2 + |G|**2) !! C = |F| / sqrt(|F|**2 + |G|**2) !! S = sgn(F) * conjg(G) / sqrt(|F|**2 + |G|**2) !! When F and G are real, the formulas simplify to C = F/R and !! S = G/R, and the returned values of C, S, and R should be !! identical to those returned by CLARTG. !! The algorithm used to compute these quantities incorporates scaling !! to avoid overflow or underflow in computing the square root of the !! sum of squares. !! This is a faster version of the BLAS1 routine CROTG, except for !! the following differences: !! F and G are unchanged on return. !! If G=0, then C=1 and S=0. !! If F=0, then C=0 and S is chosen so that R is real. !! Below, wp=>sp stands for single precision from LA_CONSTANTS module. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! february 2021 use stdlib_blas_constants_sp, only: zero, half, one, czero, safmax, safmin, rtmin, rtmax ! Scalar Arguments real(sp), intent(out) :: c complex(sp), intent(in) :: f, g complex(sp), intent(out) :: r, s ! ===================================================================== ! Local Scalars real(sp) :: d, f1, f2, g1, g2, h2, p, u, uu, v, vv, w complex(sp) :: fs, gs, t ! Intrinsic Functions ! Statement Functions real(sp) :: abssq ! Statement Function Definitions abssq( t ) = real( t,KIND=sp)**2_${ik}$ + aimag( t )**2_${ik}$ ! Executable Statements if( g == czero ) then c = one s = czero r = f else if( f == czero ) then c = zero g1 = max( abs(real(g,KIND=sp)), abs(aimag(g)) ) if( g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm g2 = abssq( g ) d = sqrt( g2 ) s = conjg( g ) / d r = d else ! use scaled algorithm u = min( safmax, max( safmin, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) d = sqrt( g2 ) s = conjg( gs ) / d r = d*u end if else f1 = max( abs(real(f,KIND=sp)), abs(aimag(f)) ) g1 = max( abs(real(g,KIND=sp)), abs(aimag(g)) ) if( f1 > rtmin .and. f1 < rtmax .and. g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm f2 = abssq( f ) g2 = abssq( g ) h2 = f2 + g2 if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1_${ik}$ / d c = f2*p s = conjg( g )*( f*p ) r = f*( h2*p ) else ! use scaled algorithm u = min( safmax, max( safmin, f1, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) if( f1*uu < rtmin ) then ! f is not well-scaled when scaled by g1. ! use a different scaling for f. v = min( safmax, max( safmin, f1 ) ) vv = one / v w = v * uu fs = f*vv f2 = abssq( fs ) h2 = f2*w**2_${ik}$ + g2 else ! otherwise use the same scaling for f and g. w = one fs = f*uu f2 = abssq( fs ) h2 = f2 + g2 end if if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1_${ik}$ / d c = ( f2*p )*w s = conjg( gs )*( fs*p ) r = ( fs*( h2*p ) )*u end if end if return end subroutine stdlib${ii}$_clartg pure module subroutine stdlib${ii}$_zlartg( f, g, c, s, r ) !! ZLARTG generates a plane rotation so that !! [ C S ] . [ F ] = [ R ] !! [ -conjg(S) C ] [ G ] [ 0 ] !! where C is real and C**2 + |S|**2 = 1. !! The mathematical formulas used for C and S are !! sgn(x) = { x / |x|, x != 0 !! { 1, x = 0 !! R = sgn(F) * sqrt(|F|**2 + |G|**2) !! C = |F| / sqrt(|F|**2 + |G|**2) !! S = sgn(F) * conjg(G) / sqrt(|F|**2 + |G|**2) !! When F and G are real, the formulas simplify to C = F/R and !! S = G/R, and the returned values of C, S, and R should be !! identical to those returned by DLARTG. !! The algorithm used to compute these quantities incorporates scaling !! to avoid overflow or underflow in computing the square root of the !! sum of squares. !! This is a faster version of the BLAS1 routine ZROTG, except for !! the following differences: !! F and G are unchanged on return. !! If G=0, then C=1 and S=0. !! If F=0, then C=0 and S is chosen so that R is real. !! Below, wp=>dp stands for double precision from LA_CONSTANTS module. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! february 2021 use stdlib_blas_constants_dp, only: zero, half, one, czero, safmax, safmin, rtmin, rtmax ! Scalar Arguments real(dp), intent(out) :: c complex(dp), intent(in) :: f, g complex(dp), intent(out) :: r, s ! ===================================================================== ! Local Scalars real(dp) :: d, f1, f2, g1, g2, h2, p, u, uu, v, vv, w complex(dp) :: fs, gs, t ! Intrinsic Functions ! Statement Functions real(dp) :: abssq ! Statement Function Definitions abssq( t ) = real( t,KIND=dp)**2_${ik}$ + aimag( t )**2_${ik}$ ! Executable Statements if( g == czero ) then c = one s = czero r = f else if( f == czero ) then c = zero g1 = max( abs(real(g,KIND=dp)), abs(aimag(g)) ) if( g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm g2 = abssq( g ) d = sqrt( g2 ) s = conjg( g ) / d r = d else ! use scaled algorithm u = min( safmax, max( safmin, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) d = sqrt( g2 ) s = conjg( gs ) / d r = d*u end if else f1 = max( abs(real(f,KIND=dp)), abs(aimag(f)) ) g1 = max( abs(real(g,KIND=dp)), abs(aimag(g)) ) if( f1 > rtmin .and. f1 < rtmax .and. g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm f2 = abssq( f ) g2 = abssq( g ) h2 = f2 + g2 if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1_${ik}$ / d c = f2*p s = conjg( g )*( f*p ) r = f*( h2*p ) else ! use scaled algorithm u = min( safmax, max( safmin, f1, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) if( f1*uu < rtmin ) then ! f is not well-scaled when scaled by g1. ! use a different scaling for f. v = min( safmax, max( safmin, f1 ) ) vv = one / v w = v * uu fs = f*vv f2 = abssq( fs ) h2 = f2*w**2_${ik}$ + g2 else ! otherwise use the same scaling for f and g. w = one fs = f*uu f2 = abssq( fs ) h2 = f2 + g2 end if if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1_${ik}$ / d c = ( f2*p )*w s = conjg( gs )*( fs*p ) r = ( fs*( h2*p ) )*u end if end if return end subroutine stdlib${ii}$_zlartg #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lartg( f, g, c, s, r ) !! ZLARTG: generates a plane rotation so that !! [ C S ] . [ F ] = [ R ] !! [ -conjg(S) C ] [ G ] [ 0 ] !! where C is real and C**2 + |S|**2 = 1. !! The mathematical formulas used for C and S are !! sgn(x) = { x / |x|, x != 0 !! { 1, x = 0 !! R = sgn(F) * sqrt(|F|**2 + |G|**2) !! C = |F| / sqrt(|F|**2 + |G|**2) !! S = sgn(F) * conjg(G) / sqrt(|F|**2 + |G|**2) !! When F and G are real, the formulas simplify to C = F/R and !! S = G/R, and the returned values of C, S, and R should be !! identical to those returned by DLARTG. !! The algorithm used to compute these quantities incorporates scaling !! to avoid overflow or underflow in computing the square root of the !! sum of squares. !! This is a faster version of the BLAS1 routine ZROTG, except for !! the following differences: !! F and G are unchanged on return. !! If G=0, then C=1 and S=0. !! If F=0, then C=0 and S is chosen so that R is real. !! Below, wp=>dp stands for quad precision from LA_CONSTANTS module. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! february 2021 use stdlib_blas_constants_${ck}$, only: zero, half, one, czero, safmax, safmin, rtmin, rtmax ! Scalar Arguments real(${ck}$), intent(out) :: c complex(${ck}$), intent(in) :: f, g complex(${ck}$), intent(out) :: r, s ! ===================================================================== ! Local Scalars real(${ck}$) :: d, f1, f2, g1, g2, h2, p, u, uu, v, vv, w complex(${ck}$) :: fs, gs, t ! Intrinsic Functions ! Statement Functions real(${ck}$) :: abssq ! Statement Function Definitions abssq( t ) = real( t,KIND=${ck}$)**2_${ik}$ + aimag( t )**2_${ik}$ ! Executable Statements if( g == czero ) then c = one s = czero r = f else if( f == czero ) then c = zero g1 = max( abs(real(g,KIND=${ck}$)), abs(aimag(g)) ) if( g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm g2 = abssq( g ) d = sqrt( g2 ) s = conjg( g ) / d r = d else ! use scaled algorithm u = min( safmax, max( safmin, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) d = sqrt( g2 ) s = conjg( gs ) / d r = d*u end if else f1 = max( abs(real(f,KIND=${ck}$)), abs(aimag(f)) ) g1 = max( abs(real(g,KIND=${ck}$)), abs(aimag(g)) ) if( f1 > rtmin .and. f1 < rtmax .and. g1 > rtmin .and. g1 < rtmax ) then ! use unscaled algorithm f2 = abssq( f ) g2 = abssq( g ) h2 = f2 + g2 if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1_${ik}$ / d c = f2*p s = conjg( g )*( f*p ) r = f*( h2*p ) else ! use scaled algorithm u = min( safmax, max( safmin, f1, g1 ) ) uu = one / u gs = g*uu g2 = abssq( gs ) if( f1*uu < rtmin ) then ! f is not well-scaled when scaled by g1. ! use a different scaling for f. v = min( safmax, max( safmin, f1 ) ) vv = one / v w = v * uu fs = f*vv f2 = abssq( fs ) h2 = f2*w**2_${ik}$ + g2 else ! otherwise use the same scaling for f and g. w = one fs = f*uu f2 = abssq( fs ) h2 = f2 + g2 end if if( f2 > rtmin .and. h2 < rtmax ) then d = sqrt( f2*h2 ) else d = sqrt( f2 )*sqrt( h2 ) end if p = 1_${ik}$ / d c = ( f2*p )*w s = conjg( gs )*( fs*p ) r = ( fs*( h2*p ) )*u end if end if return end subroutine stdlib${ii}$_${ci}$lartg #:endif #:endfor pure module subroutine stdlib${ii}$_slartgp( f, g, cs, sn, r ) !! SLARTGP generates a plane rotation so that !! [ CS SN ] . [ F ] = [ R ] where CS**2 + SN**2 = 1. !! [ -SN CS ] [ G ] [ 0 ] !! This is a slower, more accurate version of the Level 1 BLAS routine SROTG, !! with the following other differences: !! F and G are unchanged on return. !! If G=0, then CS=(+/-)1 and SN=0. !! If F=0 and (G .ne. 0), then CS=0 and SN=(+/-)1. !! The sign is chosen so that R >= 0. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(sp), intent(out) :: cs, r, sn real(sp), intent(in) :: f, g ! ===================================================================== ! Local Scalars ! logical first integer(${ik}$) :: count, i real(sp) :: eps, f1, g1, safmin, safmn2, safmx2, scale ! Intrinsic Functions ! Save Statement ! save first, safmx2, safmin, safmn2 ! Data Statements ! data first / .true. / ! Executable Statements ! if( first ) then safmin = stdlib${ii}$_slamch( 'S' ) eps = stdlib${ii}$_slamch( 'E' ) safmn2 = stdlib${ii}$_slamch( 'B' )**int( log( safmin / eps ) /log( stdlib${ii}$_slamch( 'B' ) )& / two,KIND=${ik}$) safmx2 = one / safmn2 ! first = .false. ! end if if( g==zero ) then cs = sign( one, f ) sn = zero r = abs( f ) else if( f==zero ) then cs = zero sn = sign( one, g ) r = abs( g ) else f1 = f g1 = g scale = max( abs( f1 ), abs( g1 ) ) if( scale>=safmx2 ) then count = 0_${ik}$ 10 continue count = count + 1_${ik}$ f1 = f1*safmn2 g1 = g1*safmn2 scale = max( abs( f1 ), abs( g1 ) ) if( scale>=safmx2 .and. count < 20)go to 10 r = sqrt( f1**2_${ik}$+g1**2_${ik}$ ) cs = f1 / r sn = g1 / r do i = 1, count r = r*safmx2 end do else if( scale<=safmn2 ) then count = 0_${ik}$ 30 continue count = count + 1_${ik}$ f1 = f1*safmx2 g1 = g1*safmx2 scale = max( abs( f1 ), abs( g1 ) ) if( scale<=safmn2 )go to 30 r = sqrt( f1**2_${ik}$+g1**2_${ik}$ ) cs = f1 / r sn = g1 / r do i = 1, count r = r*safmn2 end do else r = sqrt( f1**2_${ik}$+g1**2_${ik}$ ) cs = f1 / r sn = g1 / r end if if( r= 0. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(dp), intent(out) :: cs, r, sn real(dp), intent(in) :: f, g ! ===================================================================== ! Local Scalars ! logical first integer(${ik}$) :: count, i real(dp) :: eps, f1, g1, safmin, safmn2, safmx2, scale ! Intrinsic Functions ! Save Statement ! save first, safmx2, safmin, safmn2 ! Data Statements ! data first / .true. / ! Executable Statements ! if( first ) then safmin = stdlib${ii}$_dlamch( 'S' ) eps = stdlib${ii}$_dlamch( 'E' ) safmn2 = stdlib${ii}$_dlamch( 'B' )**int( log( safmin / eps ) /log( stdlib${ii}$_dlamch( 'B' ) )& / two,KIND=${ik}$) safmx2 = one / safmn2 ! first = .false. ! end if if( g==zero ) then cs = sign( one, f ) sn = zero r = abs( f ) else if( f==zero ) then cs = zero sn = sign( one, g ) r = abs( g ) else f1 = f g1 = g scale = max( abs( f1 ), abs( g1 ) ) if( scale>=safmx2 ) then count = 0_${ik}$ 10 continue count = count + 1_${ik}$ f1 = f1*safmn2 g1 = g1*safmn2 scale = max( abs( f1 ), abs( g1 ) ) if( scale>=safmx2 .and. count < 20 )go to 10 r = sqrt( f1**2_${ik}$+g1**2_${ik}$ ) cs = f1 / r sn = g1 / r do i = 1, count r = r*safmx2 end do else if( scale<=safmn2 ) then count = 0_${ik}$ 30 continue count = count + 1_${ik}$ f1 = f1*safmx2 g1 = g1*safmx2 scale = max( abs( f1 ), abs( g1 ) ) if( scale<=safmn2 )go to 30 r = sqrt( f1**2_${ik}$+g1**2_${ik}$ ) cs = f1 / r sn = g1 / r do i = 1, count r = r*safmn2 end do else r = sqrt( f1**2_${ik}$+g1**2_${ik}$ ) cs = f1 / r sn = g1 / r end if if( r= 0. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments real(${rk}$), intent(out) :: cs, r, sn real(${rk}$), intent(in) :: f, g ! ===================================================================== ! Local Scalars ! logical first integer(${ik}$) :: count, i real(${rk}$) :: eps, f1, g1, safmin, safmn2, safmx2, scale ! Intrinsic Functions ! Save Statement ! save first, safmx2, safmin, safmn2 ! Data Statements ! data first / .true. / ! Executable Statements ! if( first ) then safmin = stdlib${ii}$_${ri}$lamch( 'S' ) eps = stdlib${ii}$_${ri}$lamch( 'E' ) safmn2 = stdlib${ii}$_${ri}$lamch( 'B' )**int( log( safmin / eps ) /log( stdlib${ii}$_${ri}$lamch( 'B' ) )& / two,KIND=${ik}$) safmx2 = one / safmn2 ! first = .false. ! end if if( g==zero ) then cs = sign( one, f ) sn = zero r = abs( f ) else if( f==zero ) then cs = zero sn = sign( one, g ) r = abs( g ) else f1 = f g1 = g scale = max( abs( f1 ), abs( g1 ) ) if( scale>=safmx2 ) then count = 0_${ik}$ 10 continue count = count + 1_${ik}$ f1 = f1*safmn2 g1 = g1*safmn2 scale = max( abs( f1 ), abs( g1 ) ) if( scale>=safmx2 .and. count < 20 )go to 10 r = sqrt( f1**2_${ik}$+g1**2_${ik}$ ) cs = f1 / r sn = g1 / r do i = 1, count r = r*safmx2 end do else if( scale<=safmn2 ) then count = 0_${ik}$ 30 continue count = count + 1_${ik}$ f1 = f1*safmx2 g1 = g1*safmx2 scale = max( abs( f1 ), abs( g1 ) ) if( scale<=safmn2 )go to 30 r = sqrt( f1**2_${ik}$+g1**2_${ik}$ ) cs = f1 / r sn = g1 / r do i = 1, count r = r*safmn2 end do else r = sqrt( f1**2_${ik}$+g1**2_${ik}$ ) cs = f1 / r sn = g1 / r end if if( rabs( g ) ) then t = g / f tt = sqrt( one+t*t ) c( ic ) = one / tt y( iy ) = t*c( ic ) x( ix ) = f*tt else t = f / g tt = sqrt( one+t*t ) y( iy ) = one / tt c( ic ) = t*y( iy ) x( ix ) = g*tt end if ic = ic + incc iy = iy + incy ix = ix + incx end do loop_10 return end subroutine stdlib${ii}$_slargv pure module subroutine stdlib${ii}$_dlargv( n, x, incx, y, incy, c, incc ) !! DLARGV generates a vector of real plane rotations, determined by !! elements of the real vectors x and y. For i = 1,2,...,n !! ( c(i) s(i) ) ( x(i) ) = ( a(i) ) !! ( -s(i) c(i) ) ( y(i) ) = ( 0 ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, incy, n ! Array Arguments real(dp), intent(out) :: c(*) real(dp), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix, iy real(dp) :: f, g, t, tt ! Intrinsic Functions ! Executable Statements ix = 1_${ik}$ iy = 1_${ik}$ ic = 1_${ik}$ loop_10: do i = 1, n f = x( ix ) g = y( iy ) if( g==zero ) then c( ic ) = one else if( f==zero ) then c( ic ) = zero y( iy ) = one x( ix ) = g else if( abs( f )>abs( g ) ) then t = g / f tt = sqrt( one+t*t ) c( ic ) = one / tt y( iy ) = t*c( ic ) x( ix ) = f*tt else t = f / g tt = sqrt( one+t*t ) y( iy ) = one / tt c( ic ) = t*y( iy ) x( ix ) = g*tt end if ic = ic + incc iy = iy + incy ix = ix + incx end do loop_10 return end subroutine stdlib${ii}$_dlargv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$largv( n, x, incx, y, incy, c, incc ) !! DLARGV: generates a vector of real plane rotations, determined by !! elements of the real vectors x and y. For i = 1,2,...,n !! ( c(i) s(i) ) ( x(i) ) = ( a(i) ) !! ( -s(i) c(i) ) ( y(i) ) = ( 0 ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, incy, n ! Array Arguments real(${rk}$), intent(out) :: c(*) real(${rk}$), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix, iy real(${rk}$) :: f, g, t, tt ! Intrinsic Functions ! Executable Statements ix = 1_${ik}$ iy = 1_${ik}$ ic = 1_${ik}$ loop_10: do i = 1, n f = x( ix ) g = y( iy ) if( g==zero ) then c( ic ) = one else if( f==zero ) then c( ic ) = zero y( iy ) = one x( ix ) = g else if( abs( f )>abs( g ) ) then t = g / f tt = sqrt( one+t*t ) c( ic ) = one / tt y( iy ) = t*c( ic ) x( ix ) = f*tt else t = f / g tt = sqrt( one+t*t ) y( iy ) = one / tt c( ic ) = t*y( iy ) x( ix ) = g*tt end if ic = ic + incc iy = iy + incy ix = ix + incx end do loop_10 return end subroutine stdlib${ii}$_${ri}$largv #:endif #:endfor pure module subroutine stdlib${ii}$_clargv( n, x, incx, y, incy, c, incc ) !! CLARGV generates a vector of complex plane rotations with real !! cosines, determined by elements of the complex vectors x and y. !! For i = 1,2,...,n !! ( c(i) s(i) ) ( x(i) ) = ( r(i) ) !! ( -conjg(s(i)) c(i) ) ( y(i) ) = ( 0 ) !! where c(i)**2 + ABS(s(i))**2 = 1 !! The following conventions are used (these are the same as in CLARTG, !! but differ from the BLAS1 routine CROTG): !! If y(i)=0, then c(i)=1 and s(i)=0. !! If x(i)=0, then c(i)=0 and s(i) is chosen so that r(i) is real. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, incy, n ! Array Arguments real(sp), intent(out) :: c(*) complex(sp), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars ! logical first integer(${ik}$) :: count, i, ic, ix, iy, j real(sp) :: cs, d, di, dr, eps, f2, f2s, g2, g2s, safmin, safmn2, safmx2, scale complex(sp) :: f, ff, fs, g, gs, r, sn ! Intrinsic Functions ! Statement Functions real(sp) :: abs1, abssq ! Save Statement ! save first, safmx2, safmin, safmn2 ! Data Statements ! data first / .true. / ! Statement Function Definitions abs1( ff ) = max( abs( real( ff,KIND=sp) ), abs( aimag( ff ) ) ) abssq( ff ) = real( ff,KIND=sp)**2_${ik}$ + aimag( ff )**2_${ik}$ ! Executable Statements ! if( first ) then ! first = .false. safmin = stdlib${ii}$_slamch( 'S' ) eps = stdlib${ii}$_slamch( 'E' ) safmn2 = stdlib${ii}$_slamch( 'B' )**int( log( safmin / eps ) /log( stdlib${ii}$_slamch( 'B' ) )& / two,KIND=${ik}$) safmx2 = one / safmn2 ! end if ix = 1_${ik}$ iy = 1_${ik}$ ic = 1_${ik}$ loop_60: do i = 1, n f = x( ix ) g = y( iy ) ! use identical algorithm as in stdlib${ii}$_clartg scale = max( abs1( f ), abs1( g ) ) fs = f gs = g count = 0_${ik}$ if( scale>=safmx2 ) then 10 continue count = count + 1_${ik}$ fs = fs*safmn2 gs = gs*safmn2 scale = scale*safmn2 if( scale>=safmx2 .and. count < 20 )go to 10 else if( scale<=safmn2 ) then if( g==czero ) then cs = one sn = czero r = f go to 50 end if 20 continue count = count - 1_${ik}$ fs = fs*safmx2 gs = gs*safmx2 scale = scale*safmx2 if( scale<=safmn2 )go to 20 end if f2 = abssq( fs ) g2 = abssq( gs ) if( f2<=max( g2, one )*safmin ) then ! this is a rare case: f is very small. if( f==czero ) then cs = zero r = stdlib${ii}$_slapy2( real( g,KIND=sp), aimag( g ) ) ! do complex/real division explicitly with two real ! divisions d = stdlib${ii}$_slapy2( real( gs,KIND=sp), aimag( gs ) ) sn = cmplx( real( gs,KIND=sp) / d, -aimag( gs ) / d,KIND=sp) go to 50 end if f2s = stdlib${ii}$_slapy2( real( fs,KIND=sp), aimag( fs ) ) ! g2 and g2s are accurate ! g2 is at least safmin, and g2s is at least safmn2 g2s = sqrt( g2 ) ! error in cs from underflow in f2s is at most ! unfl / safmn2 .lt. sqrt(unfl*eps) .lt. eps ! if max(g2,one)=g2, then f2 .lt. g2*safmin, ! and so cs .lt. sqrt(safmin) ! if max(g2,one)=one, then f2 .lt. safmin ! and so cs .lt. sqrt(safmin)/safmn2 = sqrt(eps) ! therefore, cs = f2s/g2s / sqrt( 1 + (f2s/g2s)**2 ) = f2s/g2s cs = f2s / g2s ! make sure abs(ff) = 1 ! do complex/real division explicitly with 2 real divisions if( abs1( f )>one ) then d = stdlib${ii}$_slapy2( real( f,KIND=sp), aimag( f ) ) ff = cmplx( real( f,KIND=sp) / d, aimag( f ) / d,KIND=sp) else dr = safmx2*real( f,KIND=sp) di = safmx2*aimag( f ) d = stdlib${ii}$_slapy2( dr, di ) ff = cmplx( dr / d, di / d,KIND=sp) end if sn = ff*cmplx( real( gs,KIND=sp) / g2s, -aimag( gs ) / g2s,KIND=sp) r = cs*f + sn*g else ! this is the most common case. ! neither f2 nor f2/g2 are less than safmin ! f2s cannot overflow, and it is accurate f2s = sqrt( one+g2 / f2 ) ! do the f2s(real)*fs(complex) multiply with two real ! multiplies r = cmplx( f2s*real( fs,KIND=sp), f2s*aimag( fs ),KIND=sp) cs = one / f2s d = f2 + g2 ! do complex/real division explicitly with two real divisions sn = cmplx( real( r,KIND=sp) / d, aimag( r ) / d,KIND=sp) sn = sn*conjg( gs ) if( count/=0_${ik}$ ) then if( count>0_${ik}$ ) then do j = 1, count r = r*safmx2 end do else do j = 1, -count r = r*safmn2 end do end if end if end if 50 continue c( ic ) = cs y( iy ) = sn x( ix ) = r ic = ic + incc iy = iy + incy ix = ix + incx end do loop_60 return end subroutine stdlib${ii}$_clargv pure module subroutine stdlib${ii}$_zlargv( n, x, incx, y, incy, c, incc ) !! ZLARGV generates a vector of complex plane rotations with real !! cosines, determined by elements of the complex vectors x and y. !! For i = 1,2,...,n !! ( c(i) s(i) ) ( x(i) ) = ( r(i) ) !! ( -conjg(s(i)) c(i) ) ( y(i) ) = ( 0 ) !! where c(i)**2 + ABS(s(i))**2 = 1 !! The following conventions are used (these are the same as in ZLARTG, !! but differ from the BLAS1 routine ZROTG): !! If y(i)=0, then c(i)=1 and s(i)=0. !! If x(i)=0, then c(i)=0 and s(i) is chosen so that r(i) is real. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, incy, n ! Array Arguments real(dp), intent(out) :: c(*) complex(dp), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars ! logical first integer(${ik}$) :: count, i, ic, ix, iy, j real(dp) :: cs, d, di, dr, eps, f2, f2s, g2, g2s, safmin, safmn2, safmx2, scale complex(dp) :: f, ff, fs, g, gs, r, sn ! Intrinsic Functions ! Statement Functions real(dp) :: abs1, abssq ! Save Statement ! save first, safmx2, safmin, safmn2 ! Data Statements ! data first / .true. / ! Statement Function Definitions abs1( ff ) = max( abs( real( ff,KIND=dp) ), abs( aimag( ff ) ) ) abssq( ff ) = real( ff,KIND=dp)**2_${ik}$ + aimag( ff )**2_${ik}$ ! Executable Statements ! if( first ) then ! first = .false. safmin = stdlib${ii}$_dlamch( 'S' ) eps = stdlib${ii}$_dlamch( 'E' ) safmn2 = stdlib${ii}$_dlamch( 'B' )**int( log( safmin / eps ) /log( stdlib${ii}$_dlamch( 'B' ) )& / two,KIND=${ik}$) safmx2 = one / safmn2 ! end if ix = 1_${ik}$ iy = 1_${ik}$ ic = 1_${ik}$ loop_60: do i = 1, n f = x( ix ) g = y( iy ) ! use identical algorithm as in stdlib${ii}$_zlartg scale = max( abs1( f ), abs1( g ) ) fs = f gs = g count = 0_${ik}$ if( scale>=safmx2 ) then 10 continue count = count + 1_${ik}$ fs = fs*safmn2 gs = gs*safmn2 scale = scale*safmn2 if( scale>=safmx2 .and. count < 20 )go to 10 else if( scale<=safmn2 ) then if( g==czero ) then cs = one sn = czero r = f go to 50 end if 20 continue count = count - 1_${ik}$ fs = fs*safmx2 gs = gs*safmx2 scale = scale*safmx2 if( scale<=safmn2 )go to 20 end if f2 = abssq( fs ) g2 = abssq( gs ) if( f2<=max( g2, one )*safmin ) then ! this is a rare case: f is very small. if( f==czero ) then cs = zero r = stdlib${ii}$_dlapy2( real( g,KIND=dp), aimag( g ) ) ! do complex/real division explicitly with two real ! divisions d = stdlib${ii}$_dlapy2( real( gs,KIND=dp), aimag( gs ) ) sn = cmplx( real( gs,KIND=dp) / d, -aimag( gs ) / d,KIND=dp) go to 50 end if f2s = stdlib${ii}$_dlapy2( real( fs,KIND=dp), aimag( fs ) ) ! g2 and g2s are accurate ! g2 is at least safmin, and g2s is at least safmn2 g2s = sqrt( g2 ) ! error in cs from underflow in f2s is at most ! unfl / safmn2 .lt. sqrt(unfl*eps) .lt. eps ! if max(g2,one)=g2, then f2 .lt. g2*safmin, ! and so cs .lt. sqrt(safmin) ! if max(g2,one)=one, then f2 .lt. safmin ! and so cs .lt. sqrt(safmin)/safmn2 = sqrt(eps) ! therefore, cs = f2s/g2s / sqrt( 1 + (f2s/g2s)**2 ) = f2s/g2s cs = f2s / g2s ! make sure abs(ff) = 1 ! do complex/real division explicitly with 2 real divisions if( abs1( f )>one ) then d = stdlib${ii}$_dlapy2( real( f,KIND=dp), aimag( f ) ) ff = cmplx( real( f,KIND=dp) / d, aimag( f ) / d,KIND=dp) else dr = safmx2*real( f,KIND=dp) di = safmx2*aimag( f ) d = stdlib${ii}$_dlapy2( dr, di ) ff = cmplx( dr / d, di / d,KIND=dp) end if sn = ff*cmplx( real( gs,KIND=dp) / g2s, -aimag( gs ) / g2s,KIND=dp) r = cs*f + sn*g else ! this is the most common case. ! neither f2 nor f2/g2 are less than safmin ! f2s cannot overflow, and it is accurate f2s = sqrt( one+g2 / f2 ) ! do the f2s(real)*fs(complex) multiply with two real ! multiplies r = cmplx( f2s*real( fs,KIND=dp), f2s*aimag( fs ),KIND=dp) cs = one / f2s d = f2 + g2 ! do complex/real division explicitly with two real divisions sn = cmplx( real( r,KIND=dp) / d, aimag( r ) / d,KIND=dp) sn = sn*conjg( gs ) if( count/=0_${ik}$ ) then if( count>0_${ik}$ ) then do j = 1, count r = r*safmx2 end do else do j = 1, -count r = r*safmn2 end do end if end if end if 50 continue c( ic ) = cs y( iy ) = sn x( ix ) = r ic = ic + incc iy = iy + incy ix = ix + incx end do loop_60 return end subroutine stdlib${ii}$_zlargv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$largv( n, x, incx, y, incy, c, incc ) !! ZLARGV: generates a vector of complex plane rotations with real !! cosines, determined by elements of the complex vectors x and y. !! For i = 1,2,...,n !! ( c(i) s(i) ) ( x(i) ) = ( r(i) ) !! ( -conjg(s(i)) c(i) ) ( y(i) ) = ( 0 ) !! where c(i)**2 + ABS(s(i))**2 = 1 !! The following conventions are used (these are the same as in ZLARTG, !! but differ from the BLAS1 routine ZROTG): !! If y(i)=0, then c(i)=1 and s(i)=0. !! If x(i)=0, then c(i)=0 and s(i) is chosen so that r(i) is real. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, incy, n ! Array Arguments real(${ck}$), intent(out) :: c(*) complex(${ck}$), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars ! logical first integer(${ik}$) :: count, i, ic, ix, iy, j real(${ck}$) :: cs, d, di, dr, eps, f2, f2s, g2, g2s, safmin, safmn2, safmx2, scale complex(${ck}$) :: f, ff, fs, g, gs, r, sn ! Intrinsic Functions ! Statement Functions real(${ck}$) :: abs1, abssq ! Save Statement ! save first, safmx2, safmin, safmn2 ! Data Statements ! data first / .true. / ! Statement Function Definitions abs1( ff ) = max( abs( real( ff,KIND=${ck}$) ), abs( aimag( ff ) ) ) abssq( ff ) = real( ff,KIND=${ck}$)**2_${ik}$ + aimag( ff )**2_${ik}$ ! Executable Statements ! if( first ) then ! first = .false. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'E' ) safmn2 = stdlib${ii}$_${c2ri(ci)}$lamch( 'B' )**int( log( safmin / eps ) /log( stdlib${ii}$_${c2ri(ci)}$lamch( 'B' ) )& / two,KIND=${ik}$) safmx2 = one / safmn2 ! end if ix = 1_${ik}$ iy = 1_${ik}$ ic = 1_${ik}$ loop_60: do i = 1, n f = x( ix ) g = y( iy ) ! use identical algorithm as in stdlib${ii}$_${ci}$lartg scale = max( abs1( f ), abs1( g ) ) fs = f gs = g count = 0_${ik}$ if( scale>=safmx2 ) then 10 continue count = count + 1_${ik}$ fs = fs*safmn2 gs = gs*safmn2 scale = scale*safmn2 if( scale>=safmx2 .and. count < 20 )go to 10 else if( scale<=safmn2 ) then if( g==czero ) then cs = one sn = czero r = f go to 50 end if 20 continue count = count - 1_${ik}$ fs = fs*safmx2 gs = gs*safmx2 scale = scale*safmx2 if( scale<=safmn2 )go to 20 end if f2 = abssq( fs ) g2 = abssq( gs ) if( f2<=max( g2, one )*safmin ) then ! this is a rare case: f is very small. if( f==czero ) then cs = zero r = stdlib${ii}$_${c2ri(ci)}$lapy2( real( g,KIND=${ck}$), aimag( g ) ) ! do complex/real division explicitly with two real ! divisions d = stdlib${ii}$_${c2ri(ci)}$lapy2( real( gs,KIND=${ck}$), aimag( gs ) ) sn = cmplx( real( gs,KIND=${ck}$) / d, -aimag( gs ) / d,KIND=${ck}$) go to 50 end if f2s = stdlib${ii}$_${c2ri(ci)}$lapy2( real( fs,KIND=${ck}$), aimag( fs ) ) ! g2 and g2s are accurate ! g2 is at least safmin, and g2s is at least safmn2 g2s = sqrt( g2 ) ! error in cs from underflow in f2s is at most ! unfl / safmn2 .lt. sqrt(unfl*eps) .lt. eps ! if max(g2,one)=g2, then f2 .lt. g2*safmin, ! and so cs .lt. sqrt(safmin) ! if max(g2,one)=one, then f2 .lt. safmin ! and so cs .lt. sqrt(safmin)/safmn2 = sqrt(eps) ! therefore, cs = f2s/g2s / sqrt( 1 + (f2s/g2s)**2 ) = f2s/g2s cs = f2s / g2s ! make sure abs(ff) = 1 ! do complex/real division explicitly with 2 real divisions if( abs1( f )>one ) then d = stdlib${ii}$_${c2ri(ci)}$lapy2( real( f,KIND=${ck}$), aimag( f ) ) ff = cmplx( real( f,KIND=${ck}$) / d, aimag( f ) / d,KIND=${ck}$) else dr = safmx2*real( f,KIND=${ck}$) di = safmx2*aimag( f ) d = stdlib${ii}$_${c2ri(ci)}$lapy2( dr, di ) ff = cmplx( dr / d, di / d,KIND=${ck}$) end if sn = ff*cmplx( real( gs,KIND=${ck}$) / g2s, -aimag( gs ) / g2s,KIND=${ck}$) r = cs*f + sn*g else ! this is the most common case. ! neither f2 nor f2/g2 are less than safmin ! f2s cannot overflow, and it is accurate f2s = sqrt( one+g2 / f2 ) ! do the f2s(real)*fs(complex) multiply with two real ! multiplies r = cmplx( f2s*real( fs,KIND=${ck}$), f2s*aimag( fs ),KIND=${ck}$) cs = one / f2s d = f2 + g2 ! do complex/real division explicitly with two real divisions sn = cmplx( real( r,KIND=${ck}$) / d, aimag( r ) / d,KIND=${ck}$) sn = sn*conjg( gs ) if( count/=0_${ik}$ ) then if( count>0_${ik}$ ) then do j = 1, count r = r*safmx2 end do else do j = 1, -count r = r*safmn2 end do end if end if end if 50 continue c( ic ) = cs y( iy ) = sn x( ix ) = r ic = ic + incc iy = iy + incy ix = ix + incx end do loop_60 return end subroutine stdlib${ii}$_${ci}$largv #:endif #:endfor pure module subroutine stdlib${ii}$_slartv( n, x, incx, y, incy, c, s, incc ) !! SLARTV applies a vector of real plane rotations to elements of the !! real vectors x and y. For i = 1,2,...,n !! ( x(i) ) := ( c(i) s(i) ) ( x(i) ) !! ( y(i) ) ( -s(i) c(i) ) ( y(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, incy, n ! Array Arguments real(sp), intent(in) :: c(*), s(*) real(sp), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix, iy real(sp) :: xi, yi ! Executable Statements ix = 1_${ik}$ iy = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = x( ix ) yi = y( iy ) x( ix ) = c( ic )*xi + s( ic )*yi y( iy ) = c( ic )*yi - s( ic )*xi ix = ix + incx iy = iy + incy ic = ic + incc end do return end subroutine stdlib${ii}$_slartv pure module subroutine stdlib${ii}$_dlartv( n, x, incx, y, incy, c, s, incc ) !! DLARTV applies a vector of real plane rotations to elements of the !! real vectors x and y. For i = 1,2,...,n !! ( x(i) ) := ( c(i) s(i) ) ( x(i) ) !! ( y(i) ) ( -s(i) c(i) ) ( y(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, incy, n ! Array Arguments real(dp), intent(in) :: c(*), s(*) real(dp), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix, iy real(dp) :: xi, yi ! Executable Statements ix = 1_${ik}$ iy = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = x( ix ) yi = y( iy ) x( ix ) = c( ic )*xi + s( ic )*yi y( iy ) = c( ic )*yi - s( ic )*xi ix = ix + incx iy = iy + incy ic = ic + incc end do return end subroutine stdlib${ii}$_dlartv #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lartv( n, x, incx, y, incy, c, s, incc ) !! DLARTV: applies a vector of real plane rotations to elements of the !! real vectors x and y. For i = 1,2,...,n !! ( x(i) ) := ( c(i) s(i) ) ( x(i) ) !! ( y(i) ) ( -s(i) c(i) ) ( y(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, incy, n ! Array Arguments real(${rk}$), intent(in) :: c(*), s(*) real(${rk}$), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix, iy real(${rk}$) :: xi, yi ! Executable Statements ix = 1_${ik}$ iy = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = x( ix ) yi = y( iy ) x( ix ) = c( ic )*xi + s( ic )*yi y( iy ) = c( ic )*yi - s( ic )*xi ix = ix + incx iy = iy + incy ic = ic + incc end do return end subroutine stdlib${ii}$_${ri}$lartv #:endif #:endfor pure module subroutine stdlib${ii}$_clartv( n, x, incx, y, incy, c, s, incc ) !! CLARTV applies a vector of complex plane rotations with real cosines !! to elements of the complex vectors x and y. For i = 1,2,...,n !! ( x(i) ) := ( c(i) s(i) ) ( x(i) ) !! ( y(i) ) ( -conjg(s(i)) c(i) ) ( y(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, incy, n ! Array Arguments real(sp), intent(in) :: c(*) complex(sp), intent(in) :: s(*) complex(sp), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix, iy complex(sp) :: xi, yi ! Intrinsic Functions ! Executable Statements ix = 1_${ik}$ iy = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = x( ix ) yi = y( iy ) x( ix ) = c( ic )*xi + s( ic )*yi y( iy ) = c( ic )*yi - conjg( s( ic ) )*xi ix = ix + incx iy = iy + incy ic = ic + incc end do return end subroutine stdlib${ii}$_clartv pure module subroutine stdlib${ii}$_zlartv( n, x, incx, y, incy, c, s, incc ) !! ZLARTV applies a vector of complex plane rotations with real cosines !! to elements of the complex vectors x and y. For i = 1,2,...,n !! ( x(i) ) := ( c(i) s(i) ) ( x(i) ) !! ( y(i) ) ( -conjg(s(i)) c(i) ) ( y(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, incy, n ! Array Arguments real(dp), intent(in) :: c(*) complex(dp), intent(in) :: s(*) complex(dp), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix, iy complex(dp) :: xi, yi ! Intrinsic Functions ! Executable Statements ix = 1_${ik}$ iy = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = x( ix ) yi = y( iy ) x( ix ) = c( ic )*xi + s( ic )*yi y( iy ) = c( ic )*yi - conjg( s( ic ) )*xi ix = ix + incx iy = iy + incy ic = ic + incc end do return end subroutine stdlib${ii}$_zlartv #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lartv( n, x, incx, y, incy, c, s, incc ) !! ZLARTV: applies a vector of complex plane rotations with real cosines !! to elements of the complex vectors x and y. For i = 1,2,...,n !! ( x(i) ) := ( c(i) s(i) ) ( x(i) ) !! ( y(i) ) ( -conjg(s(i)) c(i) ) ( y(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, incy, n ! Array Arguments real(${ck}$), intent(in) :: c(*) complex(${ck}$), intent(in) :: s(*) complex(${ck}$), intent(inout) :: x(*), y(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix, iy complex(${ck}$) :: xi, yi ! Intrinsic Functions ! Executable Statements ix = 1_${ik}$ iy = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = x( ix ) yi = y( iy ) x( ix ) = c( ic )*xi + s( ic )*yi y( iy ) = c( ic )*yi - conjg( s( ic ) )*xi ix = ix + incx iy = iy + incy ic = ic + incc end do return end subroutine stdlib${ii}$_${ci}$lartv #:endif #:endfor pure module subroutine stdlib${ii}$_slar2v( n, x, y, z, incx, c, s, incc ) !! SLAR2V applies a vector of real plane rotations from both sides to !! a sequence of 2-by-2 real symmetric matrices, defined by the elements !! of the vectors x, y and z. For i = 1,2,...,n !! ( x(i) z(i) ) := ( c(i) s(i) ) ( x(i) z(i) ) ( c(i) -s(i) ) !! ( z(i) y(i) ) ( -s(i) c(i) ) ( z(i) y(i) ) ( s(i) c(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, n ! Array Arguments real(sp), intent(in) :: c(*), s(*) real(sp), intent(inout) :: x(*), y(*), z(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix real(sp) :: ci, si, t1, t2, t3, t4, t5, t6, xi, yi, zi ! Executable Statements ix = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = x( ix ) yi = y( ix ) zi = z( ix ) ci = c( ic ) si = s( ic ) t1 = si*zi t2 = ci*zi t3 = t2 - si*xi t4 = t2 + si*yi t5 = ci*xi + t1 t6 = ci*yi - t1 x( ix ) = ci*t5 + si*t4 y( ix ) = ci*t6 - si*t3 z( ix ) = ci*t4 - si*t5 ix = ix + incx ic = ic + incc end do return end subroutine stdlib${ii}$_slar2v pure module subroutine stdlib${ii}$_dlar2v( n, x, y, z, incx, c, s, incc ) !! DLAR2V applies a vector of real plane rotations from both sides to !! a sequence of 2-by-2 real symmetric matrices, defined by the elements !! of the vectors x, y and z. For i = 1,2,...,n !! ( x(i) z(i) ) := ( c(i) s(i) ) ( x(i) z(i) ) ( c(i) -s(i) ) !! ( z(i) y(i) ) ( -s(i) c(i) ) ( z(i) y(i) ) ( s(i) c(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, n ! Array Arguments real(dp), intent(in) :: c(*), s(*) real(dp), intent(inout) :: x(*), y(*), z(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix real(dp) :: ci, si, t1, t2, t3, t4, t5, t6, xi, yi, zi ! Executable Statements ix = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = x( ix ) yi = y( ix ) zi = z( ix ) ci = c( ic ) si = s( ic ) t1 = si*zi t2 = ci*zi t3 = t2 - si*xi t4 = t2 + si*yi t5 = ci*xi + t1 t6 = ci*yi - t1 x( ix ) = ci*t5 + si*t4 y( ix ) = ci*t6 - si*t3 z( ix ) = ci*t4 - si*t5 ix = ix + incx ic = ic + incc end do return end subroutine stdlib${ii}$_dlar2v #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lar2v( n, x, y, z, incx, c, s, incc ) !! DLAR2V: applies a vector of real plane rotations from both sides to !! a sequence of 2-by-2 real symmetric matrices, defined by the elements !! of the vectors x, y and z. For i = 1,2,...,n !! ( x(i) z(i) ) := ( c(i) s(i) ) ( x(i) z(i) ) ( c(i) -s(i) ) !! ( z(i) y(i) ) ( -s(i) c(i) ) ( z(i) y(i) ) ( s(i) c(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, n ! Array Arguments real(${rk}$), intent(in) :: c(*), s(*) real(${rk}$), intent(inout) :: x(*), y(*), z(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix real(${rk}$) :: ci, si, t1, t2, t3, t4, t5, t6, xi, yi, zi ! Executable Statements ix = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = x( ix ) yi = y( ix ) zi = z( ix ) ci = c( ic ) si = s( ic ) t1 = si*zi t2 = ci*zi t3 = t2 - si*xi t4 = t2 + si*yi t5 = ci*xi + t1 t6 = ci*yi - t1 x( ix ) = ci*t5 + si*t4 y( ix ) = ci*t6 - si*t3 z( ix ) = ci*t4 - si*t5 ix = ix + incx ic = ic + incc end do return end subroutine stdlib${ii}$_${ri}$lar2v #:endif #:endfor pure module subroutine stdlib${ii}$_clar2v( n, x, y, z, incx, c, s, incc ) !! CLAR2V applies a vector of complex plane rotations with real cosines !! from both sides to a sequence of 2-by-2 complex Hermitian matrices, !! defined by the elements of the vectors x, y and z. For i = 1,2,...,n !! ( x(i) z(i) ) := !! ( conjg(z(i)) y(i) ) !! ( c(i) conjg(s(i)) ) ( x(i) z(i) ) ( c(i) -conjg(s(i)) ) !! ( -s(i) c(i) ) ( conjg(z(i)) y(i) ) ( s(i) c(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, n ! Array Arguments real(sp), intent(in) :: c(*) complex(sp), intent(in) :: s(*) complex(sp), intent(inout) :: x(*), y(*), z(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix real(sp) :: ci, sii, sir, t1i, t1r, t5, t6, xi, yi, zii, zir complex(sp) :: si, t2, t3, t4, zi ! Intrinsic Functions ! Executable Statements ix = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = real( x( ix ),KIND=sp) yi = real( y( ix ),KIND=sp) zi = z( ix ) zir = real( zi,KIND=sp) zii = aimag( zi ) ci = c( ic ) si = s( ic ) sir = real( si,KIND=sp) sii = aimag( si ) t1r = sir*zir - sii*zii t1i = sir*zii + sii*zir t2 = ci*zi t3 = t2 - conjg( si )*xi t4 = conjg( t2 ) + si*yi t5 = ci*xi + t1r t6 = ci*yi - t1r x( ix ) = ci*t5 + ( sir*real( t4,KIND=sp)+sii*aimag( t4 ) ) y( ix ) = ci*t6 - ( sir*real( t3,KIND=sp)-sii*aimag( t3 ) ) z( ix ) = ci*t3 + conjg( si )*cmplx( t6, t1i,KIND=sp) ix = ix + incx ic = ic + incc end do return end subroutine stdlib${ii}$_clar2v pure module subroutine stdlib${ii}$_zlar2v( n, x, y, z, incx, c, s, incc ) !! ZLAR2V applies a vector of complex plane rotations with real cosines !! from both sides to a sequence of 2-by-2 complex Hermitian matrices, !! defined by the elements of the vectors x, y and z. For i = 1,2,...,n !! ( x(i) z(i) ) := !! ( conjg(z(i)) y(i) ) !! ( c(i) conjg(s(i)) ) ( x(i) z(i) ) ( c(i) -conjg(s(i)) ) !! ( -s(i) c(i) ) ( conjg(z(i)) y(i) ) ( s(i) c(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, n ! Array Arguments real(dp), intent(in) :: c(*) complex(dp), intent(in) :: s(*) complex(dp), intent(inout) :: x(*), y(*), z(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix real(dp) :: ci, sii, sir, t1i, t1r, t5, t6, xi, yi, zii, zir complex(dp) :: si, t2, t3, t4, zi ! Intrinsic Functions ! Executable Statements ix = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = real( x( ix ),KIND=dp) yi = real( y( ix ),KIND=dp) zi = z( ix ) zir = real( zi,KIND=dp) zii = aimag( zi ) ci = c( ic ) si = s( ic ) sir = real( si,KIND=dp) sii = aimag( si ) t1r = sir*zir - sii*zii t1i = sir*zii + sii*zir t2 = ci*zi t3 = t2 - conjg( si )*xi t4 = conjg( t2 ) + si*yi t5 = ci*xi + t1r t6 = ci*yi - t1r x( ix ) = ci*t5 + ( sir*real( t4,KIND=dp)+sii*aimag( t4 ) ) y( ix ) = ci*t6 - ( sir*real( t3,KIND=dp)-sii*aimag( t3 ) ) z( ix ) = ci*t3 + conjg( si )*cmplx( t6, t1i,KIND=dp) ix = ix + incx ic = ic + incc end do return end subroutine stdlib${ii}$_zlar2v #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lar2v( n, x, y, z, incx, c, s, incc ) !! ZLAR2V: applies a vector of complex plane rotations with real cosines !! from both sides to a sequence of 2-by-2 complex Hermitian matrices, !! defined by the elements of the vectors x, y and z. For i = 1,2,...,n !! ( x(i) z(i) ) := !! ( conjg(z(i)) y(i) ) !! ( c(i) conjg(s(i)) ) ( x(i) z(i) ) ( c(i) -conjg(s(i)) ) !! ( -s(i) c(i) ) ( conjg(z(i)) y(i) ) ( s(i) c(i) ) ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incc, incx, n ! Array Arguments real(${ck}$), intent(in) :: c(*) complex(${ck}$), intent(in) :: s(*) complex(${ck}$), intent(inout) :: x(*), y(*), z(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, ix real(${ck}$) :: ci, sii, sir, t1i, t1r, t5, t6, xi, yi, zii, zir complex(${ck}$) :: si, t2, t3, t4, zi ! Intrinsic Functions ! Executable Statements ix = 1_${ik}$ ic = 1_${ik}$ do i = 1, n xi = real( x( ix ),KIND=${ck}$) yi = real( y( ix ),KIND=${ck}$) zi = z( ix ) zir = real( zi,KIND=${ck}$) zii = aimag( zi ) ci = c( ic ) si = s( ic ) sir = real( si,KIND=${ck}$) sii = aimag( si ) t1r = sir*zir - sii*zii t1i = sir*zii + sii*zir t2 = ci*zi t3 = t2 - conjg( si )*xi t4 = conjg( t2 ) + si*yi t5 = ci*xi + t1r t6 = ci*yi - t1r x( ix ) = ci*t5 + ( sir*real( t4,KIND=${ck}$)+sii*aimag( t4 ) ) y( ix ) = ci*t6 - ( sir*real( t3,KIND=${ck}$)-sii*aimag( t3 ) ) z( ix ) = ci*t3 + conjg( si )*cmplx( t6, t1i,KIND=${ck}$) ix = ix + incx ic = ic + incc end do return end subroutine stdlib${ii}$_${ci}$lar2v #:endif #:endfor pure module subroutine stdlib${ii}$_clacrt( n, cx, incx, cy, incy, c, s ) !! CLACRT performs the operation !! ( c s )( x ) ==> ( x ) !! ( -s c )( y ) ( y ) !! where c and s are complex and the vectors x and y are complex. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n complex(sp), intent(in) :: c, s ! Array Arguments complex(sp), intent(inout) :: cx(*), cy(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ix, iy complex(sp) :: ctemp ! Executable Statements if( n<=0 )return if( incx==1 .and. incy==1 )go to 20 ! code for unequal increments or equal increments not equal to 1 ix = 1_${ik}$ iy = 1_${ik}$ if( incx<0_${ik}$ )ix = ( -n+1 )*incx + 1_${ik}$ if( incy<0_${ik}$ )iy = ( -n+1 )*incy + 1_${ik}$ do i = 1, n ctemp = c*cx( ix ) + s*cy( iy ) cy( iy ) = c*cy( iy ) - s*cx( ix ) cx( ix ) = ctemp ix = ix + incx iy = iy + incy end do return ! code for both increments equal to 1 20 continue do i = 1, n ctemp = c*cx( i ) + s*cy( i ) cy( i ) = c*cy( i ) - s*cx( i ) cx( i ) = ctemp end do return end subroutine stdlib${ii}$_clacrt pure module subroutine stdlib${ii}$_zlacrt( n, cx, incx, cy, incy, c, s ) !! ZLACRT performs the operation !! ( c s )( x ) ==> ( x ) !! ( -s c )( y ) ( y ) !! where c and s are complex and the vectors x and y are complex. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n complex(dp), intent(in) :: c, s ! Array Arguments complex(dp), intent(inout) :: cx(*), cy(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ix, iy complex(dp) :: ctemp ! Executable Statements if( n<=0 )return if( incx==1 .and. incy==1 )go to 20 ! code for unequal increments or equal increments not equal to 1 ix = 1_${ik}$ iy = 1_${ik}$ if( incx<0_${ik}$ )ix = ( -n+1 )*incx + 1_${ik}$ if( incy<0_${ik}$ )iy = ( -n+1 )*incy + 1_${ik}$ do i = 1, n ctemp = c*cx( ix ) + s*cy( iy ) cy( iy ) = c*cy( iy ) - s*cx( ix ) cx( ix ) = ctemp ix = ix + incx iy = iy + incy end do return ! code for both increments equal to 1 20 continue do i = 1, n ctemp = c*cx( i ) + s*cy( i ) cy( i ) = c*cy( i ) - s*cx( i ) cx( i ) = ctemp end do return end subroutine stdlib${ii}$_zlacrt #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lacrt( n, cx, incx, cy, incy, c, s ) !! ZLACRT: performs the operation !! ( c s )( x ) ==> ( x ) !! ( -s c )( y ) ( y ) !! where c and s are complex and the vectors x and y are complex. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: incx, incy, n complex(${ck}$), intent(in) :: c, s ! Array Arguments complex(${ck}$), intent(inout) :: cx(*), cy(*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ix, iy complex(${ck}$) :: ctemp ! Executable Statements if( n<=0 )return if( incx==1 .and. incy==1 )go to 20 ! code for unequal increments or equal increments not equal to 1 ix = 1_${ik}$ iy = 1_${ik}$ if( incx<0_${ik}$ )ix = ( -n+1 )*incx + 1_${ik}$ if( incy<0_${ik}$ )iy = ( -n+1 )*incy + 1_${ik}$ do i = 1, n ctemp = c*cx( ix ) + s*cy( iy ) cy( iy ) = c*cy( iy ) - s*cx( ix ) cx( ix ) = ctemp ix = ix + incx iy = iy + incy end do return ! code for both increments equal to 1 20 continue do i = 1, n ctemp = c*cx( i ) + s*cy( i ) cy( i ) = c*cy( i ) - s*cx( i ) cx( i ) = ctemp end do return end subroutine stdlib${ii}$_${ci}$lacrt #:endif #:endfor #:endfor end submodule stdlib_lapack_givens_jacobi_rot fortran-lang-stdlib-0ede301/src/hash/0000775000175000017500000000000015135654166017700 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/hash/stdlib_hash_32bit_nm.fypp0000664000175000017500000007630115135654166024570 0ustar alastairalastair!!------------------------------------------------------------------------------ !! `NM_HASH32` and `NM_HASH32X` are translations to Fortran 2008 and signed !! two's complement arithmetic of the `nmhash32` and `nmhash32x` scalar !! algorithms of James Z. M. Gao, copyright 2021. James Z. M. Gao's original !! C++ code, `nmhash.h`, is available at the URL: !! https://github.com/gzm55/hash-garage/blob/a8913138bdb3b7539c202edee30a7f0794bbd835/nmhash.h !! under the BSD 2-Clause License: !! https://github.com/gzm55/hash-garage/blob/a8913138bdb3b7539c202edee30a7f0794bbd835/LICENSE !! The algorithms come in multiple versions, depending on whether the !! vectorized instructions SSE2 or AVX2 are available. As neither instruction !! is available in portable Fortran 2008, the algorithms that do not use these !! instructions are used. !! !! The BSD 2-Clause license is as follows: !! !! BSD 2-Clause License !! !! Copyright (c) 2021, water hash algorithm. James Z.M. Gao !! All rights reserved. !! !! Redistribution and use in source and binary forms, with or without !! modification, are permitted provided that the following conditions are met: !! !! 1. Redistributions of source code must retain the above copyright notice, !! this list of conditions and the following disclaimer. !! !! 2. Redistributions in binary form must reproduce the above copyright notice, !! this list of conditions and the following disclaimer in the documentation !! and/or other materials provided with the distribution. !! !! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" !! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE !! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE !! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE !! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR !! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF !! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS !! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN !! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) !! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE !! POSSIBILITY OF SUCH DAMAGE. !!------------------------------------------------------------------------------ #! Integer kinds to be considered during templating #:set INT_KINDS = ["int16", "int32", "int64"] submodule(stdlib_hash_32bit) stdlib_hash_32bit_nm implicit none ! Primes from XXH integer(int32), parameter :: nmh_prime32_1 = int( Z'9E3779B1', int32 ) integer(int32), parameter :: nmh_prime32_2 = int( Z'85EBCA77', int32 ) integer(int32), parameter :: nmh_prime32_3 = int( Z'C2B2AE3D', int32 ) integer(int32), parameter :: nmh_prime32_4 = int( Z'27D4EB2F', int32 ) integer(int32), parameter :: nmh_m1 = int(z'F0D9649B', int32 ) integer(int32), parameter :: nmh_m2 = int(z'29A7935D', int32 ) integer(int32), parameter :: nmh_m3 = int(z'55D35831', int32 ) integer(int32), parameter :: nmh_m1_v(0:31) = nmh_m1 integer(int32), parameter :: nmh_m2_v(0:31) = nmh_m2 integer(int32), parameter :: nmh_m3_v(0:31) = nmh_m3 logical, parameter :: nmh_short32_without_seed2=.false. logical, parameter :: nmh_short32_with_seed2=.true. integer, parameter :: init_size = 32 ! Pseudorandom secrets taken directly from FARSH. integer(int32), parameter :: nmh_acc_init(0:init_size-1) = [ & int( z'B8FE6C39', int32 ), int( z'23A44BBE', int32 ), & int( z'7C01812C', int32 ), int( z'F721AD1C', int32 ), & int( z'DED46DE9', int32 ), int( z'839097DB', int32 ), & int( z'7240A4A4', int32 ), int( z'B7B3671F', int32 ), & int( z'CB79E64E', int32 ), int( z'CCC0E578', int32 ), & int( z'825AD07D', int32 ), int( z'CCFF7221', int32 ), & int( z'B8084674', int32 ), int( z'F743248E', int32 ), & int( z'E03590E6', int32 ), int( z'813A264C', int32 ), & int( z'3C2852BB', int32 ), int( z'91C300CB', int32 ), & int( z'88D0658B', int32 ), int( z'1B532EA3', int32 ), & int( z'71644897', int32 ), int( z'A20DF94E', int32 ), & int( z'3819EF46', int32 ), int( z'A9DEACD8', int32 ), & int( z'A8FA763F', int32 ), int( z'E39C343F', int32 ), & int( z'F9DCBBC7', int32 ), int( z'C70B4F1D', int32 ), & int( z'8A51E04B', int32 ), int( z'CDB45931', int32 ), & int( z'C89F7EC9', int32 ), int( z'D9787364', int32 ) ] contains pure function nmh_readle32( p ) result( v ) integer(int32) :: v integer(int8), intent(in) :: p(:) if ( little_endian ) then v = transfer( p(1:4), 0_int32 ) else v = transfer( [ p(4), p(3), p(2), p(1) ], 0_int32 ) end if end function nmh_readle32 pure function nmh_readle16( p ) result( v ) integer(int16) :: v integer(int8), intent(in) :: p(:) if ( little_endian ) then v = transfer( p(1:2), 0_int16 ) else v = transfer( [ p(2), p(1) ], 0_int16 ) end if end function nmh_readle16 pure function nmhash32_0to8( x, seed ) result( vx32 ) integer(int32), intent(in) :: x integer(int32), intent(in) :: seed integer(int32) :: vx32 ! base mixer: [-6 -12 776bf593 -19 11 3fb39c65 -15 -9 e9139917 -11 16] ! = 0.027071104091278835 integer(int32), parameter :: m1 = int(z'776BF593', int32) integer(int32), parameter :: m2 = int(z'3FB39C65', int32) integer(int32), parameter :: m3 = int(z'E9139917', int32) integer(int16) :: vx16(2) vx32 = x vx32 = ieor( vx32, ieor( ishft( vx32, -12 ), ishft( vx32, -6 ) ) ) vx16 = transfer( vx32, 0_int16, 2 ) vx16 = vx16 * transfer( m1, 0_int16, 2 ) vx32 = transfer( vx16, 0_int32 ) vx32 = ieor( vx32, ieor( ishft( vx32, 11 ), ishft( vx32, -19 ) ) ) vx16 = transfer( vx32, 0_int16, 2 ) vx16 = vx16 * transfer( m2, 0_int16, 2 ) vx32 = transfer( vx16, 0_int32 ) vx32 = ieor( vx32, seed ) vx32 = ieor( vx32, ieor( ishft( vx32, -15 ), ishft( vx32, -9 ) ) ) vx16 = transfer( vx32, 0_int16, 2 ) vx16 = vx16 * transfer( m3, 0_int16, 2 ) vx32 = transfer( vx16, 0_int32 ) vx32 = ieor( vx32, ieor( ishft(vx32, 16), ishft(vx32, -11) ) ) end function nmhash32_0to8 pure function nmhash32_9to255( p, seed, full_avalanche ) result( result ) integer(int8), intent(in) :: p(0:) integer(int32), intent(in) :: seed logical, intent(in) :: full_avalanche integer(int32) :: result integer(int32) :: xu32(0:3), yu32(0:3) integer(int16) :: xu16(0:1) ! Due to an issue with Intel OneAPI ifort 2021 (see ! https://community.intel.com/t5/Intel-Fortran-Compiler/Intrinsic-transfer-with-a-provided-size-un-expected-behavior/m-p/1343313#M158733 ! ), it is not possible to define the following variables as a parameter. ! integer(int16), parameter :: & ! nmh_m1_16(0:1) = transfer( nmh_m1, 0_int16, 2 ), & ! nmh_m2_16(0:1) = transfer( nmh_m2, 0_int16, 2 ), & ! nmh_m3_16(0:1) = transfer( nmh_m3, 0_int16, 2 ) integer(int16) :: nmh_m1_16(0:1), nmh_m2_16(0:1), nmh_m3_16(0:1) integer(int32) :: s1 integer(int64) :: length integer(int32) :: length32(0:1) integer(int64) :: i, j, r nmh_m1_16(0:1) = transfer( nmh_m1, 0_int16, 2 ) nmh_m2_16(0:1) = transfer( nmh_m2, 0_int16, 2 ) nmh_m3_16(0:1) = transfer( nmh_m3, 0_int16, 2 ) ! base mixer: [f0d9649b 5 -13 29a7935d -9 11 55d35831 -20 -10 ] = ! 0.93495901789135362 result = 0 length = size( p, kind=int64 ) length32 = transfer(length, 0_int32, 2) if (little_endian) then s1 = seed + length32(0) else s1 = seed + length32(1) end if xu32(0) = nmh_prime32_1 xu32(1) = nmh_prime32_2 xu32(2) = nmh_prime32_3 xu32(3) = nmh_prime32_4 yu32(:) = s1 if (full_avalanche) then ! 33 to 255 bytes r = (length - 1 ) /32 do i=0, r-1 do j=0, 3 xu32(j) = ieor( xu32(j), nmh_readle32( p(i*32 + j*4: ) ) ) yu32(j) = ieor( yu32(j), & nmh_readle32( p(i*32 + j*4 + 16: ) ) ) xu32(j) = xu32(j) + yu32(j) xu16 = transfer( xu32(j), 0_int16, 2 ) xu16 = xu16 * nmh_m1_16 xu32(j) = transfer( xu16, 0_int32 ) xu32(j) = ieor( xu32(j), & ieor( ishft(xu32(j), 5), & ishft(xu32(j), -13)) ) xu16 = transfer( xu32(j), 0_int16, 2 ) xu16 = xu16 * nmh_m2_16 xu32(j) = transfer( xu16, 0_int32 ) xu32(j) = ieor( xu32(j), yu32(j) ) xu32(j) = ieor( xu32(j), & ieor( ishft(xu32(j), 11), & ishft(xu32(j), -9) ) ) xu16 = transfer( xu32(j), 0_int16, 2 ) xu16 = xu16 * nmh_m3_16 xu32(j) = transfer( xu16, 0_int32 ) xu32(j) = ieor( xu32(j), & ieor( ishft(xu32(j),-10), & ishft(xu32(j), -20) ) ) end do end do do j=0, 3 xu32(j) = ieor( xu32(j), & nmh_readle32( p(length - 32 + j*4: ) ) ) yu32(j) = ieor( yu32(j), & nmh_readle32( p(length - 16 + j*4: ) ) ) end do else ! 9 to 32 bytes xu32(0) = ieor(xu32(0), nmh_readle32(p(0:))) xu32(1) = ieor(xu32(1), nmh_readle32(p(ishft(ishft(length,-4),3):))) xu32(2) = ieor(xu32(2), nmh_readle32(p(length-8:))) xu32(3) = ieor(xu32(3), & nmh_readle32(p(length-8-ishft(ishft(length,-4),3):))) yu32(0) = ieor(yu32(0), nmh_readle32(p(4:))) yu32(1) = ieor(yu32(1), & nmh_readle32(p(ishft(ishft(length,-4),3)+4:))) yu32(2) = ieor(yu32(2), nmh_readle32(p(length-8+4:))) yu32(3) = ieor(yu32(3), & nmh_readle32(p(length - 8 - & ishft(ishft(length,-4),3)+4:))) end if do j=0, 3 xu32(j) = xu32(j) + yu32(j) yu32(j) = ieor( yu32(j), ieor(ishft(yu32(j), 17), & ishft(yu32(j), -6) ) ) xu16 = transfer( xu32(j), 0_int16, 2 ) xu16 = xu16 * nmh_m1_16 xu32(j) = transfer( xu16, 0_int32 ) xu32(j) = ieor( xu32(j), ieor(ishft(xu32(j), 5), & ishft(xu32(j), -13) ) ) xu16 = transfer( xu32(j), 0_int16, 2 ) xu16 = xu16 * nmh_m2_16 xu32(j) = transfer( xu16, 0_int32 ) xu32(j) = ieor( xu32(j), yu32(j) ) xu32(j) = ieor( xu32(j), ieor(ishft(xu32(j), 11), & ishft(xu32(j), -9) ) ) xu16 = transfer( xu32(j), 0_int16, 2 ) xu16 = xu16 * nmh_m3_16 xu32(j) = transfer( xu16, 0_int32 ) xu32(j) = ieor( xu32(j), ieor(ishft(xu32(j), -10), & ishft(xu32(j), -20) ) ) end do xu32(0) = ieor( xu32(0), nmh_prime32_1 ) xu32(1) = ieor( xu32(1), nmh_prime32_2 ) xu32(2) = ieor( xu32(2), nmh_prime32_3 ) xu32(3) = ieor( xu32(3), nmh_prime32_4 ) do j=1, 3 xu32(0) = xu32(0) + xu32(j) end do xu32(0) = ieor(xu32(0), s1 + ishft(s1, -5) ) xu16 = transfer( xu32(0), 0_int16, 2 ) xu16 = xu16 * nmh_m3_16 xu32(0) = transfer( xu16, 0_int32 ) xu32(0) = ieor(xu32(0), & ieor(ishft(xu32(0), -10), ishft(xu32(0), -20) ) ) result = xu32(0) end function nmhash32_9to255 pure function nmhash32_9to32( p, seed ) result( result ) integer(int8), intent(in) :: p(0:) integer(int32), intent(in) :: seed integer(int32) :: result result = nmhash32_9to255( p, seed, .false. ) end function nmhash32_9to32 pure function nmhash32_33to255( p, seed ) result( result ) integer(int8), intent(in) :: p(0:) integer(int32), intent(in) :: seed integer(int32) :: result result = nmhash32_9to255( p, seed, .true. ) end function nmhash32_33to255 pure subroutine nmhash32_long_round( accx, accy, p ) integer(int32), intent(inout) :: accx(0:) integer(int32), intent(inout) :: accy(0:) integer(int8), intent(in) :: p(0:) integer(int64), parameter :: nbgroups = init_size integer(int64) :: i integer(int16) :: dummy1(0:1) integer(int16) :: dummy2(0:1) do i = 0, nbgroups-1 accx(i) = ieor( accx(i), nmh_readle32( p(i*4:) ) ) accy(i) = ieor( accy(i), nmh_readle32( p(i*4+nbgroups*4:) ) ) accx(i) = accx(i) + accy(i) accy(i) = ieor( accy(i), ishft(accx(i), -1) ) dummy1 = transfer( accx(i), 0_int16, 2 ) dummy2 = transfer( nmh_m1_v(i), 0_int16, 2 ) dummy1 = dummy1 * dummy2 accx(i) = transfer( dummy1, 0_int32 ) accx(i) = ieor( accx(i), ieor( ishft(accx(i), 5), & ishft(accx(i),-13) ) ) dummy1 = transfer( accx(i), 0_int16, 2 ) dummy2 = transfer( nmh_m2_v(i), 0_int16, 2 ) dummy1 = dummy1 * dummy2 accx(i) = transfer( dummy1, 0_int32 ) accx(i) = ieor( accx(i), accy(i) ) accx(i) = ieor( accx(i), ieor( ishft(accx(i), 11), & ishft(accx(i),-9) ) ) dummy1 = transfer( accx(i), 0_int16, 2 ) dummy2 = transfer( nmh_m3_v(i), 0_int16, 2 ) dummy1 = dummy1 * dummy2 accx(i) = transfer( dummy1, 0_int32 ) accx(i) = ieor( accx(i), ieor( ishft(accx(i),-10), & ishft(accx(i),-20) ) ) end do end subroutine nmhash32_long_round pure function nmhash32_long( p, seed ) result( sum ) integer(int32) :: sum integer(int8), intent(in) :: p(0:) integer(int32), intent(in) :: seed integer(int32) :: accx(0:size(nmh_acc_init)-1) integer(int32) :: accy(0:size(nmh_acc_init)-1) integer(int64) :: nbrounds integer(int64) :: len integer(int32) :: len32(0:1) integer(int64) :: i len = size( p, kind=int64 ) nbrounds = (len-1) / ( 4*size(accx, kind=int64) * 2 ) sum = 0 ! Init do i=0_int64, size(nmh_acc_init, kind=int64)-1 accx(i) = nmh_acc_init(i) accy(i) = seed end do ! init do i=0_int64, nbrounds-1 call nmhash32_long_round( accx, accy, & p(i*8*size(accx, kind=int64):) ) end do call nmhash32_long_round( accx, accy, & p(len-8*size(accx, kind=int64):) ) ! merge acc do i=0, size( accx, kind=int64 )-1 accx(i) = ieor( accx(i), nmh_acc_init(i) ) sum = sum + accx(i) end do len32 = transfer(len, 0_int32, 2) if ( little_endian ) then sum = sum + len32(1) sum = ieor(sum, len32(0)) else sum = sum + len32(0) sum = ieor(sum, len32(1)) end if end function nmhash32_long pure function nmhash32_avalanche32( x ) result( u32 ) integer(int32) :: u32 integer(int32), intent(in) :: x integer(int16) :: u16(0:1) integer(int32), parameter:: m1 = int(z'CCE5196D', int32) integer(int32), parameter:: m2 = int(z'464BE229', int32) ! Due to an issue with Intel OneAPI ifort 2021 (see ! https://community.intel.com/t5/Intel-Fortran-Compiler/Intrinsic-transfer-with-a-provided-size-un-expected-behavior/m-p/1343313#M158733 ! ), it is not possible to define the following variables as a parameter. !integer(int16), parameter:: m1_16(0:1) = transfer(m1, 0_int16, 2) !integer(int16), parameter:: m2_16(0:1) = transfer(m2, 0_int16, 2) integer(int16) :: m1_16(0:1), m2_16(0:1) ! [-21 -8 cce5196d 12 -7 464be229 -21 -8] = 3.2267098842182733 m1_16(0:1) = transfer(m1, 0_int16, 2) m2_16(0:1) = transfer(m2, 0_int16, 2) u32 = x u32 = ieor( u32, ieor( ishft( u32, -8 ), ishft( u32, -21 ) ) ) u16 = transfer( u32, 0_int16, 2 ) u16(0) = u16(0) * m1_16(0) u16(1) = u16(1) * m1_16(1) u32 = transfer( u16, 0_int32 ) u32 = ieor( u32, ieor( ishft( u32, 12 ), ishft( u32, -7 ) ) ) u16 = transfer( u32, 0_int16, 2 ) u16(0) = u16(0) * m2_16(0) u16(1) = u16(1) * m2_16(1) u32 = transfer( u16, 0_int32 ) u32 = ieor( u32, ieor( ishft( u32, -8 ), ishft( u32, -21 ) ) ) end function nmhash32_avalanche32 pure module function int8_nmhash32( key, seed ) result( hash ) !! NMHASH32 hash function for rank 1 array keys of kind INT8 integer(int32) :: hash integer(int8), intent(in) :: key(0:) integer(int32), intent(in) :: seed integer(int64) :: len integer(int32) :: u32 integer(int16) :: u16(0:1) integer(int32) :: x, y integer(int32) :: new_seed len = size( key, kind=int64 ) if ( len <= 32 ) then if ( len > 8 ) then hash = nmhash32_9to32( key, seed ) return else if ( len > 4 ) then x = nmh_readle32(key) y = ieor( nmh_readle32(key(len-4:)), nmh_prime32_4 + 2 + seed ) x = x + y x = ieor( x, ishft(x, len + 7 ) ) hash = nmhash32_0to8( x, ishftc(y, 5) ) return else select case(len) case(0) new_seed = seed + nmh_prime32_2 u32 = 0 case(1) new_seed = seed + nmh_prime32_2 + ishft(1_int32, 24) + & 2_int32 if ( little_endian ) then u32 = transfer( [key(0), 0_int8, 0_int8, 0_int8], & 0_int32 ) else u32 = transfer( [0_int8, 0_int8, 0_int8, key(0)], & 0_int32 ) end if case(2) new_seed = seed + nmh_prime32_2 + ishft(2_int32, 24) + & 4_int32 if (little_endian) then u32 = transfer( [nmh_readle16(key), 0_int16], 0_int32 ) else u32 = transfer( [0_int16, nmh_readle16(key)], 0_int32 ) end if case(3) new_seed = seed + nmh_prime32_2 + ishft(3_int32, 24) + & 6_int32 if ( little_endian ) then u16(1) = transfer( [key(2), 0_int8], 0_int16 ) u16(0) = nmh_readle16( key ) else u16(0) = transfer( [0_int8, key(2)], 0_int16 ) u16(1) = nmh_readle16( key ) end if u32 = transfer( u16, 0_int32 ) case(4) new_seed = seed + nmh_prime32_3 u32 = nmh_readle32(key) case default hash = 0 return end select hash = nmhash32_0to8(u32+new_seed, ishftc(new_seed, 5) ) return end if else if ( len < 256_int64 ) then hash = nmhash32_33to255( key, seed ) return else hash = nmhash32_avalanche32( nmhash32_long(key, seed )) return end if end function int8_nmhash32 pure function nmhash32x_0to4( x, seed ) result( hash ) integer(int32), intent(in) :: x integer(int32), intent(in) :: seed integer(int32) :: hash ! [bdab1ea9 18 a7896a1b 12 83796a2d 16] = 0.092922873297662509 hash = x hash = ieor( hash, seed ) hash = hash * int(z'BDAB1EA9', int32) hash = hash + ishftc(seed, 31) hash = ieor( hash, ishft(hash, -18) ) hash = hash * int(z'A7896A1B', int32) hash = ieor( hash, ishft(hash, -12) ) hash = hash * int(z'83796A2D', int32) hash = ieor( hash, ishft(hash, -16) ) end function nmhash32x_0to4 pure function nmhash32x_5to8( p, seed ) result( x ) integer(int8), intent(in) :: p(0:) integer(int32), intent(in) :: seed integer(int32) :: x integer(int64) :: len integer(int32) :: y ! 5 to 9 bytes ! mixer: [11049a7d 23 bcccdc7b 12 065e9dad 12] = 0.16577596555667246 len = size(p, kind=int64) x = ieor( nmh_readle32(p), nmh_prime32_3 ) y = ieor( nmh_readle32(p(len-4:)), seed ) x = x + y x = ieor( x, ishft(x, -len) ) x = x * int(z'11049A7D', int32) x = ieor( x, ishft(x, -23) ) x = x * int(z'BCCCDC7B', int32) x = ieor( x, ishftc(y, 3) ) x = ieor( x, ishft(x, -12) ) x = x * int(z'065E9DAD', int32) x = ieor( x, ishft(x, -12) ) end function nmhash32x_5to8 pure function nmhash32x_9to255( p, seed ) result( x ) integer(int8), intent(in) :: p(0:) integer(int32), intent(in) :: seed integer(int32) :: x integer(int64) :: len integer(int32) :: len32(0:1), len_base integer(int32) :: y integer(int32) :: a, b integer(int64) :: i, r ! - at least 9 bytes ! - base mixer: [11049a7d 23 bcccdc7b 12 065e9dad 12] = 0.16577596555667246 ! - tail mixer: [16 a52fb2cd 15 551e4d49 16] = 0.17162579707098322 len = size(p, kind=int64) len32 = transfer(len, 0_int32, 2) if (little_endian) then len_base = len32(0) else len_base = len32(1) end if x = nmh_prime32_3 y = seed a = nmh_prime32_4 b = seed r = (len - 1)/16 do i=0, r-1 x = ieor(x, nmh_readle32( p(i*16 + 0:) ) ) y = ieor(y, nmh_readle32( p(i*16 + 4:) ) ) x = ieor(x, y) x = x * int(z'11049A7D', int32) x = ieor(x, ishft(x, -23) ) x = x * int(z'BCCCDC7B', int32) y = ishftc(y, 4) x = ieor(x, y) x = ieor(x, ishft(x, -12) ) x = x * int(z'065E9DAD', int32) x = ieor(x, ishft(x, -12) ) a = ieor(a, nmh_readle32(p(i*16 + 8:))) b = ieor(b, nmh_readle32(p(i*16 + 12:))) a = ieor(a, b) a = a * int(z'11049A7D', int32) a = ieor(a, ishft(a, -23) ) a = a * int(z'BCCCDC7B', int32) b = ishftc(b, 3) a = ieor(a, b) a = ieor(a, ishft(a, -12) ) a = a * int(z'065E9DAD', int32) a = ieor(a, ishft(a, -12) ) end do if ( iand(len_base-1_int32, 8_int32) /= 0 ) then if ( iand(len_base-1_int32, 4_int32) /= 0 ) then a = ieor( a, nmh_readle32( p(r*16 + 0:) ) ) b = ieor( b, nmh_readle32( p(r*16 + 4:) ) ) a = ieor(a, b) a = a * int(z'11049A7D', int32) a = ieor(a, ishft(a, -23) ) a = a * int(z'BCCCDC7B', int32) a = ieor(a, ishftc(b, 4)) a = ieor(a, ishft(a, -12)) a = a * int(z'065E9DAD', int32) else a = ieor( a, nmh_readle32( p(r*16:) ) + b ) a = ieor( a, ishft(a, -16) ) a = a * int(z'A52FB2CD', int32) a = ieor( a, ishft(a, -15) ) a = a * int(z'551E4D49', int32) end if x = ieor( x, nmh_readle32( p(len - 8:) ) ) y = ieor( y, nmh_readle32( p(len - 4:) ) ) x = ieor( x, y ) x = x * int(z'11049A7D', int32) x = ieor( x, ishft(x, -23) ) x = x * int(z'BCCCDC7B', int32); x = ieor( x, ishftc(y, 3) ) x = ieor( x, ishft(x, -12) ) x = x * int(z'065E9DAD', int32) else if ( iand(len_base-1_int32, 4_int32) /= 0) then a = ieor(a, nmh_readle32(p( r * 16:) ) + b ) a = ieor( a, ishft(a,-16) ) a = a * int(z'A52FB2CD', int32) a = ieor( a, ishft(a,-15) ) a = a * int(z'551E4D49', int32) end if x = ieor( x, nmh_readle32(p( len - 4:) ) + y ) x = ieor( x, ishft(x,-16) ) x = x * int(z'A52FB2CD', int32) x = ieor( x, ishft(x,-15) ) x = x * int(z'551E4D49', int32) end if x = ieor(x, len_base ) x = ieor(x, ishftc(a, 27)) ! rotate one lane to pass Diff test x = ieor(x, ishft(x,-14)) x = x * int(z'141CC535', int32 ) end function nmhash32x_9to255 pure function nmhash32x_avalanche32( x ) result(hash) integer(int32) :: hash integer(int32), intent(in) :: x ! Mixer with 2 mul from skeeto/hash-prospector: ! [15 d168aaad 15 af723597 15] = 0.15983776156606694 hash = x hash = ieor( hash, ishft( hash, -15 ) ) hash = hash * int( z'D168AAAD', int32 ) hash = ieor( hash, ishft( hash, -15 ) ) hash = hash * int( z'AF723597', int32 ) hash = ieor( hash, ishft( hash, -15 ) ) end function nmhash32x_avalanche32 pure module function int8_nmhash32x( key, seed ) result(hash) !! NMHASH32x hash function for rank 1 array keys of kind INT8 integer(int32) :: hash integer(int8), intent(in) :: key(0:) integer(int32), intent(in) :: seed integer(int64) :: len integer(int32) :: seed2 integer(int32) :: u32 integer(int16) :: u16(0:1) len = size( key, kind=int64 ) if ( len <= 8 ) then if ( len > 4 ) then hash = nmhash32x_5to8( key, seed ) return else ! 0 to 4 bytes select case (len) case(0) seed2 = seed + nmh_prime32_2 u32 = 0 case(1) seed2 = seed + nmh_prime32_2 + ishft(1_int32, 24) + & ishft(1_int32, 1) if (little_endian) then u32 = transfer( [key(0), 0_int8, 0_int8, 0_int8], & 0_int32 ) else u32 = transfer( [0_int8, 0_int8, 0_int8, key(0)], & 0_int32 ) end if case(2) seed2 = seed + nmh_prime32_2 + ishft(2_int32, 24) + & ishft(2_int32, 1) if (little_endian) then u32 = transfer( [nmh_readle16(key), 0_int16], 0_int32 ) else u32 = transfer( [0_int16, nmh_readle16(key)], 0_int32 ) end if case(3) seed2 = seed + nmh_prime32_2 + ishft(3_int32, 24) + & ishft(3_int32, 1) if (little_endian ) then u16(1) = transfer( [ key(2), 0_int8 ], 0_int16 ) u16(0) = nmh_readle16(key) else u16(0) = transfer( [ 0_int8, key(2) ], 0_int16 ) u16(1) = nmh_readle16(key) end if u32 = transfer( u16, 0_int32 ) case(4) seed2 = seed + nmh_prime32_1 u32 = nmh_readle32(key) case default hash = 0 return end select hash = nmhash32x_0to4(u32, seed2) return end if end if if (len < 256) then hash = nmhash32x_9to255(key, seed) return end if hash = nmhash32x_avalanche32(nmhash32_long(key, seed)) end function int8_nmhash32x #:for k1 in INT_KINDS pure module function ${k1}$_nmhash32( key, seed ) result(hash_code) !! NMHASH32 hash function for rank 1 array keys of kind ${k1}$ integer(${k1}$), intent(in) :: key(:) integer(int32), intent(in) :: seed integer(int32) :: hash_code hash_code = int8_nmhash32( transfer( key, 0_int8, & bytes_${k1}$*size(key, kind=int64) ), seed) end function ${k1}$_nmhash32 #:endfor elemental module function character_nmhash32( key, seed ) result(hash_code) !! NMHASH32 hash function for default character keys character(*), intent(in) :: key integer(int32), intent(in) :: seed integer(int32) :: hash_code hash_code = int8_nmhash32( transfer( key, 0_int8, & bytes_char*len(key, kind=int64) ), seed) end function character_nmhash32 #:for k1 in INT_KINDS pure module function ${k1}$_nmhash32x( key, seed ) result(hash_code) !! NMHASH32X hash function for rank 1 array keys of kind ${k1}$ integer(${k1}$), intent(in) :: key(:) integer(int32), intent(in) :: seed integer(int32) :: hash_code hash_code = int8_nmhash32x( transfer( key, 0_int8, & bytes_${k1}$*size(key, kind=int64) ), seed) end function ${k1}$_nmhash32x #:endfor elemental module function character_nmhash32x( key, seed ) result(hash_code) !! NMHASH32X hash function for default character keys character(*), intent(in) :: key integer(int32), intent(in) :: seed integer(int32) :: hash_code hash_code = int8_nmhash32x( transfer( key, 0_int8, & bytes_char*len(key, kind=int64) ), seed) end function character_nmhash32x module subroutine new_nmhash32_seed( seed ) ! Random SEED generator for NMHASH32 integer(int32), intent(inout) :: seed integer(int32) :: old_seed real(dp) :: sample old_seed = seed find_seed:do call random_number( sample ) seed = int( floor( sample * 2_int64**32, int64 ) - 2_int64**31, & int32 ) if ( seed /= old_seed ) return end do find_seed end subroutine new_nmhash32_seed module subroutine new_nmhash32x_seed( seed ) ! Random SEED generator for NMHASH32X integer(int32), intent(inout) :: seed integer(int32) :: old_seed real(dp) :: sample old_seed = seed find_seed:do call random_number( sample ) seed = int( floor( sample * 2_int64**32, int64 ) - 2_int64**31, & int32 ) if ( seed /= old_seed ) return end do find_seed end subroutine new_nmhash32x_seed end submodule stdlib_hash_32bit_nm fortran-lang-stdlib-0ede301/src/hash/stdlib_hash_64bit_fnv.fypp0000664000175000017500000001166015135654166024751 0ustar alastairalastair!!------------------------------------------------------------------------------ !! `FNV_1_HASH` and `FNV_1A_HASH` are translations to Fortran 2008 of the !! `FNV-1` and `FNV-1a` hash functions of Glenn Fowler, Landon Curt Noll, !! and Phong Vo, that has been released into the public domain. Permission !! has been granted, by Landon Curt Noll, for the use of these algorithms !! in the Fortran Standard Library. A description of these functions is !! available at https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function. !! The functions have been modified from their normal form to also encode !! the size of the structure in the hash. !!------------------------------------------------------------------------------ #! Integer kinds to be considered during templating #:set INT_KINDS = ["int16", "int32", "int64"] submodule(stdlib_hash_64bit) stdlib_hash_64bit_fnv ! An implementation of the FNV hashes 1 and 1a of Glenn Fowler, Landon Curt ! Noll, and Kiem-Phong-Vo, ! https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function implicit none integer(int_hash), parameter :: & offset_basis = int( z'CBF29CE484222325', int_hash ), & prime = int( z'100000001B3', int_hash ) contains pure module function int8_fnv_1( key ) result(hash_code) integer(int8), intent(in) :: key(:) integer(int_hash) :: hash_code integer(int64) :: i hash_code = offset_basis do i=1_int64, size(key, kind=int64) hash_code = hash_code * prime if ( little_endian ) then hash_code = ieor( hash_code, & transfer( [key(i), 0_int8, 0_int8, 0_int8, & 0_int8, 0_int8, 0_int8, 0_int8], & 0_int_hash ) ) else hash_code = ieor( hash_code, & transfer( [0_int8, 0_int8, 0_int8, 0_int8, & 0_int8, 0_int8, 0_int8, key(i)], & 0_int_hash ) ) end if end do end function int8_fnv_1 #:for k1 in INT_KINDS pure module function ${k1}$_fnv_1( key ) result(hash_code) integer(${k1}$), intent(in) :: key(:) integer(int_hash) :: hash_code hash_code = int8_fnv_1( transfer( key, 0_int8, & bytes_${k1}$* & size( key, kind=int64 ) ) ) end function ${k1}$_fnv_1 #:endfor elemental module function character_fnv_1( key ) result(hash_code) character(*), intent(in) :: key integer(int_hash) :: hash_code hash_code = int8_fnv_1( transfer( key, & 0_int8, & bytes_char* & len(key, kind=int64) ) ) end function character_fnv_1 pure module function int8_fnv_1a( key ) result(hash_code) integer(int8), intent(in) :: key(:) integer(int_hash) :: hash_code integer(int64) :: i hash_code = offset_basis do i=1_int64, size(key, kind=int64) if ( little_endian ) then hash_code = ieor( hash_code, & transfer( [key(i), 0_int8, 0_int8, 0_int8, & 0_int8, 0_int8, 0_int8, 0_int8], & 0_int_hash ) ) else hash_code = ieor( hash_code, & transfer( [0_int8, 0_int8, 0_int8, 0_int8, & 0_int8, 0_int8, 0_int8, key(i)], & 0_int_hash ) ) end if hash_code = hash_code * prime end do end function int8_fnv_1a #:for k1 in INT_KINDS pure module function ${k1}$_fnv_1a( key ) result(hash_code) integer(${k1}$), intent(in) :: key(:) integer(int_hash) :: hash_code hash_code = int8_fnv_1a( transfer( key, 0_int8, & bytes_${k1}$* & size(key, kind=int64))) end function ${k1}$_fnv_1a #:endfor elemental module function character_fnv_1a( key ) result(hash_code) character(*), intent(in) :: key integer(int_hash) :: hash_code hash_code = int8_fnv_1a( transfer( key, 0_int8, & (bits_char/bits_int8)* & len(key, kind=int64) ) ) end function character_fnv_1a end submodule stdlib_hash_64bit_fnv fortran-lang-stdlib-0ede301/src/hash/CMakeLists.txt0000664000175000017500000000063415135654166022443 0ustar alastairalastairset(hash_fppFiles stdlib_hash_32bit_fnv.fypp stdlib_hash_32bit.fypp stdlib_hash_32bit_nm.fypp stdlib_hash_32bit_water.fypp stdlib_hash_64bit_fnv.fypp stdlib_hash_64bit.fypp stdlib_hash_64bit_pengy.fypp stdlib_hash_64bit_spookyv2.fypp ) configure_stdlib_target(${PROJECT_NAME}_hash "" hash_fppFiles "") target_link_libraries(${PROJECT_NAME}_hash PUBLIC ${PROJECT_NAME}_core) fortran-lang-stdlib-0ede301/src/hash/stdlib_hash_32bit.fypp0000664000175000017500000002254415135654166024076 0ustar alastairalastair#! Integer kinds to be considered during templating #:set INT_KINDS = ["int8", "int16", "int32", "int64"] module stdlib_hash_32bit use, intrinsic :: iso_fortran_env, only : & character_storage_size use stdlib_kinds, only: & dp, & int8, & int16, & int32, & int64 implicit none private integer, parameter, public :: & int_hash = int32 !! The number of bits in the output hash ! pow32_over_phi is the odd integer that most closely approximates 2**32/phi, ! where phi is the golden ratio 1.618... integer(int32), parameter :: & pow32_over_phi = int( z'9E3779B9', int32 ) ! The number of bits used by each integer type integer, parameter :: & ! Should be 8 bits_int8 = bit_size(0_int8), & ! Should be 16 bits_int16 = bit_size(0_int16), & ! Should be 32 bits_int32 = bit_size(0_int32), & ! Should be 64 bits_int64 = bit_size(0_int64) integer, parameter :: & ! Should be 1 bytes_int8 = bits_int8/bits_int8, & ! Should be 2 bytes_int16 = bits_int16/bits_int8, & ! Should be 4 bytes_int32 = bits_int32/bits_int8, & ! Should be 8 bytes_int64 = bits_int64/bits_int8 integer, parameter :: & bits_char = character_storage_size, & bytes_char = bits_char/bits_int8 ! Dealing with different endians logical, parameter, public :: & little_endian = ( 1 == transfer([1_int8, 0_int8], 0_int16) ) public :: & fibonacci_hash, & fnv_1_hash, & fnv_1a_hash, & new_nmhash32_seed, & new_nmhash32x_seed, & new_water_hash_seed,& nmhash32, & nmhash32x, & odd_random_integer, & universal_mult_hash,& water_hash interface fnv_1_hash !! Version: experimental !! !! FNV_1 interfaces !! ([Specification](../page/specs/stdlib_hash_procedures.html#fnv_1_hash-calculates-a-hash-code-from-a-key)) #:for k1 in INT_KINDS pure module function ${k1}$_fnv_1( key ) result(hash_code) !! FNV_1 hash function for rank 1 array keys of kind ${k1}$ integer(${k1}$), intent(in) :: key(:) integer(int_hash) :: hash_code end function ${k1}$_fnv_1 #:endfor elemental module function character_fnv_1( key ) result(hash_code) !! FNV_1 hash function for default character string keys character(*), intent(in) :: key integer(int_hash) :: hash_code end function character_fnv_1 end interface fnv_1_hash interface fnv_1a_hash !! Version: experimental !! !! FNV_1A interfaces !! ([Specification](../page/specs/stdlib_hash_procedures.html#fnv_1a_hash-calculates-a-hash-code-from-a-key)) #:for k1 in INT_KINDS pure module function ${k1}$_fnv_1a( key ) result(hash_value) !! FNV_1A hash function for rank 1 array keys of kind ${k1}$ integer(${k1}$), intent(in) :: key(:) integer(int_hash) :: hash_value end function ${k1}$_fnv_1a #:endfor elemental module function character_fnv_1a( key ) result(hash_value) !! FNV_1A hash function for default character string keys character(*), intent(in) :: key integer(int_hash) :: hash_value end function character_fnv_1a end interface fnv_1a_hash interface nmhash32 !! Version: experimental !! !! NMHASH32 interfaces !! ([Specification](../page/specs/stdlib_hash_procedures.html#nmhash32-calculates-a-hash-code-from-a-key-and-a-seed)) #:for k1 in INT_KINDS pure module function ${k1}$_nmhash32( key, seed ) & result(hash_value) !! NMHASH32 hash function for rank 1 array keys of kind ${k1}$ integer(${k1}$), intent(in) :: key(0:) integer(int32), intent(in) :: seed integer(int32) :: hash_value end function ${k1}$_nmhash32 #:endfor elemental module function character_nmhash32( key, seed ) & result(hash_value) !! NMHASH32 hash function for default character string keys character(*), intent(in) :: key integer(int32), intent(in) :: seed integer(int32) :: hash_value end function character_nmhash32 end interface nmhash32 interface nmhash32x !! Version: experimental !! !! NMHASH32X interfaces !! ([Specification](file:///home/jvandenp/stdlib/API-doc/page/specs/stdlib_hash_procedures.html#nmhash32x-calculates-a-hash-code-from-a-key-and-a-seed)) #:for k1 in INT_KINDS pure module function ${k1}$_nmhash32x( key, seed ) & result(hash_value) !! NMHASH32 hash function for rank 1 array keys of kind ${k1}$ integer(${k1}$), intent(in) :: key(0:) integer(int32), intent(in) :: seed integer(int32) :: hash_value end function ${k1}$_nmhash32x #:endfor elemental module function character_nmhash32x( key, seed ) & result(hash_value) !! NMHASH32 hash function for default character string keys character(*), intent(in) :: key integer(int32), intent(in) :: seed integer(int32) :: hash_value end function character_nmhash32x end interface nmhash32x interface water_hash !! Version: experimental !! !! WATER_HASH interfaces !! ([Specification](../page/specs/stdlib_hash_procedures.html#water_hash-calculates-a-hash-code-from-a-key-and-a-seed)) #:for k1 in INT_KINDS pure module function ${k1}$_water_hash( key, seed ) & result(hash_code) !! WATER HASH function for rank 1 array keys of kind ${k1}$ integer(${k1}$), intent(in) :: key(0:) integer(int64), intent(in) :: seed integer(int_hash) :: hash_code end function ${k1}$_water_hash #:endfor elemental module function character_water_hash( key, seed ) & result(hash_code) !! WATER hash function for default character string keys character(*), intent(in) :: key integer(int64), intent(in) :: seed integer(int_hash) :: hash_code end function character_water_hash end interface water_hash interface new_water_hash_seed !! Version: experimental !! !! ([Specification](file:///home/jvandenp/stdlib/API-doc/page/specs/stdlib_hash_procedures.html#new_water_hash_seed-returns-a-valid-input-seed-for-water_hash)) module subroutine new_water_hash_seed( seed ) integer(int64), intent(inout) :: seed end subroutine new_water_hash_seed end interface new_water_hash_seed interface new_nmhash32_seed !! Version: experimental !! !! ([Specification](../page/specs/stdlib_hash_procedures.html#new_nmhash32_seed-returns-a-valid-input-seed-for-nmhash32) module subroutine new_nmhash32_seed( seed ) integer(int32), intent(inout) :: seed end subroutine new_nmhash32_seed end interface new_nmhash32_seed interface new_nmhash32x_seed !! Version: experimental !! !! ([Specification](../page/specs/stdlib_hash_procedures.html#new_nmhash32x_seed-returns-a-valid-input-seed-for-nmhash32x)) module subroutine new_nmhash32x_seed( seed ) integer(int32), intent(inout) :: seed end subroutine new_nmhash32x_seed end interface new_nmhash32x_seed contains elemental function fibonacci_hash( key, nbits ) result( sample ) !! Version: experimental !! !! Maps the 32 bit integer `key` to an unsigned integer value with only `nbits` !! bits where `nbits` is less than 32 !! ([Specification](../page/specs/stdlib_hash_procedures.html#fibonacci_hash-maps-an-integer-to-a-smaller-number-of-bits)) integer(int32), intent(in) :: key integer, intent(in) :: nbits integer(int32) :: sample sample = ishft( key*pow32_over_phi, -32 + nbits ) end function fibonacci_hash elemental function universal_mult_hash( key, seed, nbits ) result( sample ) !! Version: experimental !! !! Uses the "random" odd 32 bit integer `seed` to map the 32 bit integer `key` to !! an unsigned integer value with only `nbits` bits where `nbits` is less than 32 !! ([Specification](../page/specs/stdlib_hash_procedures.html#universal_mult_hash-maps-an-integer-to-a-smaller-number-of-bits)) integer(int32), intent(in) :: key integer(int32), intent(in) :: seed integer, intent(in) :: nbits integer(int32) :: sample sample = ishft( key*seed, -32 + nbits ) end function universal_mult_hash subroutine odd_random_integer( harvest ) !! Version: experimental !! !! Returns a 32 bit pseudo random integer, `harvest`, distributed uniformly over !! the odd integers of the `int32` kind. !! ([Specification](../page/specs/stdlib_hash_procedures.html#odd_random_integer-returns-an-odd-integer)) integer(int32), intent(out) :: harvest real(dp) :: sample call random_number( sample ) harvest = int( floor( sample * 2_int64**32, int64 ) - 2_int64**31, & int32 ) harvest = ishft( harvest, 1 ) + 1_int32 end subroutine odd_random_integer end module stdlib_hash_32bit fortran-lang-stdlib-0ede301/src/hash/stdlib_hash_64bit.fypp0000664000175000017500000002433515135654166024103 0ustar alastairalastair#! Integer kinds to be considered during templating #:set INT_KINDS = ["int8", "int16", "int32", "int64"] module stdlib_hash_64bit use, intrinsic :: iso_fortran_env, only : & character_storage_size use stdlib_kinds, only: & dp, & int8, & int16, & int32, & int64 implicit none private integer, parameter, public :: & int_hash = int64 !! The number of bits in the output hash ! The number of bits used by each integer type integer, parameter, public :: & ! Should be 8 bits_int8 = bit_size(0_int8), & ! Should be 16 bits_int16 = bit_size(0_int16), & ! Should be 32 bits_int32 = bit_size(0_int32), & ! Should be 64 bits_int64 = bit_size(0_int64) integer, parameter, public :: & ! Should be 1 bytes_int8 = bits_int8/bits_int8, & ! Should be 2 bytes_int16 = bits_int16/bits_int8, & ! Should be 4 bytes_int32 = bits_int32/bits_int8, & ! Should be 8 bytes_int64 = bits_int64/bits_int8 integer, parameter, public :: & bits_char = character_storage_size, & bytes_char = bits_char/bits_int8 ! Dealing with different endians logical, parameter, public :: & little_endian = ( 1 == transfer( [1_int8, 0_int8], 0_int16) ) public :: & fibonacci_hash, & fnv_1_hash, & fnv_1a_hash, & new_pengy_hash_seed, & new_spooky_hash_seed, & odd_random_integer, & pengy_hash, & spooky_hash, & spookyhash_128, & universal_mult_hash ! pow64_over_phi is the odd number that most closely approximates 2**64/phi, ! where phi is the golden ratio 1.618... integer(int64), parameter :: & pow64_over_phi = int(z'9E3779B97F4A7C15', int64) integer(int_hash), parameter :: & two_32 = 2_int_hash**32 ! constants used by Bob Jenkins' SpookyHash integer(int32), parameter :: & sc_numvars = 12, & sc_blocksize = sc_numvars*8, & sc_buffsize = 2*sc_blocksize, & sc_constsub = int(z'deadbeef', int32) ! twos complement "deadbeef" integer(int64), parameter :: & sc_const = transfer( [sc_constsub, sc_constsub], 0_int64 ) type :: spooky_subhash integer(int8) :: data(0:2*sc_blocksize-1) integer(int64) :: state(0:sc_numvars-1) integer(int64) :: length integer(int16) :: remainder end type spooky_subhash interface fnv_1_hash !! Version: experimental !! !! FNV_1 interfaces !! ([Specification](../page/specs/stdlib_hash_procedures.html#fnv_1-calculates-a-hash-code-from-a-key)) #:for k1 in INT_KINDS pure module function ${k1}$_fnv_1( key ) result(hash_code) !! FNV_1 hash function for rank 1 arrays of kind ${k1}$ integer(${k1}$), intent(in) :: key(:) integer(int_hash) :: hash_code end function ${k1}$_fnv_1 #:endfor elemental module function character_fnv_1( key ) result(hash_code) !! FNV_1 hash function for character strings character(*), intent(in) :: key integer(int_hash) :: hash_code end function character_fnv_1 end interface fnv_1_hash interface fnv_1a_hash !! Version: experimental !! !! FNV_1A interfaces !! ([Specification](../page/specs/stdlib_hash_procedures.html#fnv_1a-calculates-a-hash-code-from-a-key)) #:for k1 in INT_KINDS pure module function ${k1}$_fnv_1a( key ) result(hash_code) !! FNV_1A hash function for rank 1 arrays of kind ${k1}$ integer(${k1}$), intent(in) :: key(:) integer(int_hash) :: hash_code end function ${k1}$_fnv_1a #:endfor elemental module function character_fnv_1a( key ) result(hash_code) !! FNV_1A hash function for character strings character(*), intent(in) :: key integer(int_hash) :: hash_code end function character_fnv_1a end interface fnv_1a_hash interface spooky_hash !! Version: experimental !! !! SPOOKY_HASH interfaces !!([Specification](../page/specs/stdlib_hash_procedures.html#spooky_hash-maps-a-character-string-or-integer-vector-to-an-integer)) #:for k1 in INT_KINDS module function ${k1}$_spooky_hash( key, seed ) & result(hash_code) !! SPOOKY HASH function for rank 1 arrays of kind ${k1}$ integer(${k1}$), intent(in) :: key(0:) integer(int_hash), intent(in) :: seed(2) integer(int_hash) :: hash_code(2) end function ${k1}$_spooky_hash #:endfor module function character_spooky_hash( key, seed ) & result(hash_code) !! SPOOKY hash function for character strings character(*), intent(in) :: key integer(int_hash), intent(in) :: seed(2) integer(int_hash) :: hash_code(2) end function character_spooky_hash end interface spooky_hash interface module subroutine spookyHash_128( key, hash_inout ) !! Version: experimental !! integer(int8), intent(in), target :: key(0:) integer(int_hash), intent(inout) :: hash_inout(2) end subroutine spookyHash_128 end interface interface spooky_init !! Version: experimental !! pure module subroutine spookysubhash_init( self, seed ) type(spooky_subhash), intent(out) :: self integer(int_hash), intent(in) :: seed(2) end subroutine spookysubhash_init end interface spooky_init interface spooky_update module subroutine spookyhash_update( spooky, key ) !! Version: experimental !! type(spooky_subhash), intent(inout) :: spooky integer(int8), intent(in) :: key(0:) end subroutine spookyhash_update end interface spooky_update interface spooky_final module subroutine spookyhash_final(spooky, hash_code) !! Version: experimental !! type(spooky_subhash), intent(inout) :: spooky integer(int_hash), intent(inout) :: hash_code(2) end subroutine spookyhash_final end interface spooky_final interface module subroutine new_spooky_hash_seed( seed ) !! Version: experimental !! !! Random seed generator for SPOOKY_HASH integer(int64), intent(inout) :: seed(2) end subroutine new_spooky_hash_seed end interface interface pengy_hash !! Version: experimental !! !! PENGY_HASH interfaces !! ([Specification](../page/specs/stdlib_hash_procedures.html#pengy_hash-maps-a-character-string-or-integer-vector-to-an-integer)) #:for k1 in INT_KINDS pure module function ${k1}$_pengy_hash( key, seed ) result(hash_code) !! PENGY_HASH hash function for rank 1 array keys of kind ${k1}$ integer(${k1}$), intent(in) :: key(:) integer(int32), intent(in) :: seed integer(int64) :: hash_code end function ${k1}$_pengy_hash #:endfor elemental module function character_pengy_hash( key, seed ) & result(hash_code) !! MIR HASH STRICT function for character strings character(*), intent(in) :: key integer(int32), intent(in) :: seed integer(int64) :: hash_code end function character_pengy_hash end interface pengy_hash interface module subroutine new_pengy_hash_seed( seed ) !! Version: experimental !! !! Random seed generator for MIR_HASH_STRICT integer(int32), intent(inout) :: seed end subroutine new_pengy_hash_seed end interface contains elemental function fibonacci_hash( key, nbits ) result( sample ) !! Version: experimental !! !! Maps the 64 bit integer `key` to an unsigned integer value with only `nbits` !! bits where `nbits` is less than 64 !! ([Specification](../page/specs/stdlib_hash_procedures.html#fibonacci_hash-maps-an-integer-to-a-smaller-number-of-bits_1)) integer(int64), intent(in) :: key integer, intent(in) :: nbits integer(int64) :: sample sample = ishft( key*pow64_over_phi, -64 + nbits ) end function fibonacci_hash elemental function universal_mult_hash( key, seed, nbits ) result( sample ) !! Version: experimental !! !! Uses the "random" odd 64 bit integer `seed` to map the 64 bit integer `key` to !! an unsigned integer value with only `nbits` bits where `nbits` is less than 64. !! ([Specification](../page/specs/stdlib_hash_procedures.html#universal_mult_hash-maps-an-integer-to-a-smaller-number-of-bits_1)) integer(int64), intent(in) :: key integer(int64), intent(in) :: seed integer, intent(in) :: nbits integer(int64) :: sample sample = ishft( key*seed, -64 + nbits ) end function universal_mult_hash subroutine odd_random_integer( harvest ) !! Version: experimental !! !! Returns a 64 bit pseudo random integer, `harvest`, distributed uniformly over !! the odd integers of the 64 bit kind. !! ([Specification](../page/specs/stdlib_hash_procedures.html#odd_random_integer-returns-odd-integer)) integer(int64), intent(out) :: harvest real(dp) :: sample(2) integer(int32) :: part(2) call random_number( sample ) part = int( floor( sample * 2_int64**32, int64 ) - 2_int64**31, int32 ) harvest = transfer( part, harvest ) harvest = ishft( harvest, 1 ) + 1_int64 end subroutine odd_random_integer subroutine random_integer( harvest ) !! Version: experimental !! !! Returns a 64 bit pseudo random integer, `harvest`, distributed uniformly over !! the values of the 64 bit kind. integer(int64), intent(out) :: harvest real(dp) :: sample(2) integer(int32) :: part(2) call random_number( sample ) part = int( floor( sample * 2_int64**32, int64 ) - 2_int64**31, int32 ) harvest = transfer( part, harvest ) end subroutine random_integer end module stdlib_hash_64bit fortran-lang-stdlib-0ede301/src/hash/stdlib_hash_64bit_pengy.fypp0000664000175000017500000001263315135654166025303 0ustar alastairalastair!!------------------------------------------------------------------------------ !! `PENGY_HASH` is a translation to Fortran 2008 and signed two's complement !! arithmetic of the `pengyhash` algorithm of Alberto Fajardo, copyright 2020. !! Alberto Fajardo's original C code, `pengyhash.c`, is available at the URL: !! https://github.com/tinypeng/pengyhash/blob/master/pengyhash.c !! under the BSD 2-Clause License: !! https://github.com/tinypeng/pengyhash/blob/master/LICENSE !! !! The BSD 2-Clause license is as follows: !! !! BSD 2-Clause License !! !! pengyhash !! Copyright (c) 2020 Alberto Fajardo !! All rights reserved. !! !! Redistribution and use in source and binary forms, with or without !! modification, are permitted provided that the following conditions are met: !! !! 1. Redistributions of source code must retain the above copyright notice, !! this list of conditions and the following disclaimer. !! !! 2. Redistributions in binary form must reproduce the above copyright notice, !! this list of conditions and the following disclaimer in the documentation !! and/or other materials provided with the distribution. !! !! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" !! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE !! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE !! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE !! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR !! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF !! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS !! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN !! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) !! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE !! POSSIBILITY OF SUCH DAMAGE. !!------------------------------------------------------------------------------ #! Integer kinds to be considered during templating #:set INT_KINDS = ["int16", "int32", "int64"] submodule(stdlib_hash_64bit) stdlib_hash_64bit_pengy implicit none contains pure module function int8_pengy_hash( key, seed ) result(hash_code) integer(int64) :: hash_code integer(int8), intent(in) :: key(0:) integer(int32), intent(in) :: seed integer(int64) :: b(0:3) integer(int64) :: i integer(int64) :: index integer(int64) :: len integer(int64) :: s(0:3) integer(int64) :: seed2 integer(int8) :: dummy(0:31) b(0:3) = 0_int64 len = size( key, kind=int64 ) s(0:3) = [ 0_int64, 0_int64, 0_int64, len ] index = 0_int64 do while ( len >= 32 ) b(0:3) = transfer( key( index:index+31 ), 0_int64, 4 ) s(0) = s(0) + s(1) + b(3) s(1) = s(0) + ishftc( s(1), 14 ) s(2) = s(2) + s(3) + b(2) s(3) = s(2) + ishftc( s(3), 23 ) s(0) = s(0) + s(3) + b(1) s(3) = ieor( s(0), ishftc( s(3), 16 ) ) s(2) = s(2) + s(1) + b(0) s(1) = ieor( s(2), ishftc( s(1), 40 ) ) len = len - 32 index = index + 32 end do dummy(0:31) = transfer( b, 0_int8, 32 ) dummy(0:len-1) = key(index:index+len-1) b(0:3) = transfer( dummy, 0_int64, 4) if ( little_endian ) then seed2 = transfer( [ seed, 0_int32 ], 0_int64 ) else seed2 = transfer( [ 0_int32, seed ], 0_int64 ) end if do i = 0, 5 s(0) = s(0) + s(1) + b(3) s(1) = s(0) + ishftc( s(1), 14 ) + seed2 s(2) = s(2) + s(3) + b(2) s(3) = s(2) + ishftc( s(3), 23 ) s(0) = s(0) + s(3) + b(1) s(3) = ieor( s(0), ishftc( s(3), 16 ) ) s(2) = s(2) + s(1) + b(0) s(1) = ieor( s(2), ishftc( s(1), 40 ) ) end do hash_code = s(0) + s(1) + s(2) + s(3) end function int8_pengy_hash #:for k1 in INT_KINDS pure module function ${k1}$_pengy_hash( key, seed ) result(hash_code) !! PENGY_HASH hash function for rank 1 array keys of kind ${k1}$ integer(${k1}$), intent(in) :: key(:) integer(int32), intent(in) :: seed integer(int64) :: hash_code hash_code = int8_pengy_hash( transfer( key, 0_int8, & bytes_${k1}$*size(key, kind=int64) ), seed) end function ${k1}$_pengy_hash #:endfor elemental module function character_pengy_hash( key, seed ) & result(hash_code) !! PENGY_HASH hash function for default character keys character(*), intent(in) :: key integer(int32), intent(in) :: seed integer(int64) :: hash_code hash_code = int8_pengy_hash( transfer( key, 0_int8, & bytes_char*len(key, kind=int64) ), seed) end function character_pengy_hash module subroutine new_pengy_hash_seed( seed ) ! Random SEED generator for PENGY_HASH integer(int32), intent(inout) :: seed real(dp) :: sample integer(int32) :: old_seed old_seed = seed find_seed: do call random_number( sample ) seed = int( floor( sample * 2_int64**32, int64 ) - 2_int64**31, & int32 ) if ( seed /= old_seed ) return end do find_seed end subroutine new_pengy_hash_seed end submodule stdlib_hash_64bit_pengy fortran-lang-stdlib-0ede301/src/hash/stdlib_hash_64bit_spookyv2.fypp0000664000175000017500000005716515135654166025766 0ustar alastairalastair!!------------------------------------------------------------------------------ !! `SPOOKY_HASH` is a translation to Fortran 2008 of the unsigned 64 bit !! `SpookyHash` V2 function of Bob Jenkins !! to signed 64 bit !! operations. Bob Jenkins has put his code in the public domain and has !! given permission to treat this code as public domain in the USA, !! provided the code can be used under other licenses and he is given !! appropriate credit. !! The code was designed for Little-Endian processors. The output is !! different on Big Endian processors, but still probably as good quality. !!------------------------------------------------------------------------------ #! Integer kinds to be considered during templating #:set INT_KINDS = ["int16", "int32", "int64"] submodule(stdlib_hash_64bit) stdlib_hash_64bit_spookyv2 ! I have tried to make this portable while retaining efficiency. I assume ! processors with two's complement integers from 8, 16, 32, and 64 bits. ! The code is a transliteration of the 64 bit SpookyHash V2 of Bob Jenkins ! ! The code was designed for Little-Endian processors. The output is ! different on Big Endian processors, but still probably as good quality. implicit none contains module function int8_spooky_hash( key, seed ) result(hash_code) integer(int8), intent(in) :: key(:) integer(int64), intent(in) :: seed(2) integer(int64) :: hash_code(2) hash_code(:) = seed call spookyhash_128( key, hash_code ) end function int8_spooky_hash #:for k1 in INT_KINDS module function ${k1}$_spooky_hash( key, seed ) result(hash_code) integer(${k1}$), intent(in) :: key(:) integer(int64), intent(in) :: seed(2) integer(int64) :: hash_code(2) integer(int64) :: hash2(2) hash2(:) = seed call spookyhash_128( transfer( key, 0_int8, & bytes_${k1}$*size(key, kind=int64) ), hash2 ) hash_code = hash2 end function ${k1}$_spooky_hash #:endfor module function character_spooky_hash( key, seed ) result(hash_code) character(*), intent(in) :: key integer(int64), intent(in) :: seed(2) integer(int64) :: hash_code(2) integer(int64) :: hash2(2) hash2(:) = seed call spookyhash_128( transfer( key, 0_int8, & bytes_char*len(key, kind=int64) ), hash2 ) hash_code = hash2 end function character_spooky_hash ! ! short hash ... it could be used on any message, ! but it's used by Spooky just for short messages. ! subroutine spookyhash_short( key, hash_inout ) integer(int8), intent(in), target :: key(0:) integer(int64), intent(inout) :: hash_inout(2) integer(int64) :: a, b, c, d integer(int64) :: length, p8, remainder p8 = 0 length = size( key, kind=int64 ) ! The number of bytes after all the INT256s remainder = iand( length, 31_int64 ) a = hash_inout(1) b = hash_inout(2) c = sc_const d = sc_const if ( length > 15 ) then block integer(int64) :: bend, step integer(int64) :: buf(0:2*sc_numVars-1) bend = ishft(length, -4) ! The number of complete INT128s buf(0:2*bend-1) = transfer( key(0:16*bend-1), 0_int64, 2*bend ) ! Number of Int64's in number of complete INT256s bend = ishft(ishft(length, -5), 2) ! handle all complete sets of 32 bytes do step = 0_int64, bend-1, 4 c = c + buf(step) d = d + buf(step+1) call shortmix( a, b, c, d ) a = a + buf(step+2) b = b + buf(step+3) end do ! Completed all INT64s in complete INT256s p8 = p8 + 8*bend ! Number of INT8s in complete INT256s ! Handle the case of 16+ remaining bytes. if (remainder >= 16) then c = c + buf(step) d = d + buf(step+1) call shortmix( a, b, c, d ) p8 = p8 + 16 remainder = remainder - 16 end if end block end if ! Handle the last 0..15 bytes, and its length V2 d = d + shiftl( length, 56_int64 ) select case(remainder) case(15) go to 115 case(14) go to 114 case(13) go to 113 case(12) go to 112 case(11) go to 111 case(10) go to 110 case(9) go to 109 case(8) go to 108 case(7) go to 107 case(6) go to 106 case(5) go to 105 case(4) go to 104 case(3) go to 103 case(2) go to 102 case(1) go to 101 case(0) go to 100 end select 115 d = d + shiftl( map_to_64( key(p8+14) ), 48_int64 ) 114 d = d + shiftl( map_to_64( key(p8+13) ), 40_int64 ) 113 d = d + shiftl( map_to_64( key(p8+12) ), 32_int64 ) 112 if ( little_endian) then d = d + transfer( [ transfer(key(p8+8:p8+11), 0_int32), & 0_int32 ], 0_int64) else d = d + transfer( [ 0_int32, & transfer(key(p8+8:p8+11), 0_int32) ], & 0_int64) end if c = c + transfer( key(p8+0:p8+7), 0_int64 ) go to 888 111 d = d + shiftl( map_to_64( key(p8+10) ), 16_int32 ) 110 d = d + shiftl( map_to_64( key(p8+9) ), 8_int32 ) 109 d = d + map_to_64( key(p8+8) ) 108 c = c + transfer( key(p8+0:p8+7), 0_int64 ) go to 888 107 c = c + shiftl( map_to_64( key(p8+6) ), 48_int64 ) 106 c = c + shiftl( map_to_64( key(p8+5) ), 40_int64 ) 105 c = c + shiftl( map_to_64( key(p8+4) ), 32_int64 ) 104 if ( little_endian) then c = c + transfer( [ transfer( key(p8+0:p8+3), 0_int32 ), & 0_int32 ], 0_int64 ) else c = c + transfer( [ 0_int32, & transfer( key(p8+0:p8+3), 0_int32 ) ], 0_int64 ) end if go to 888 103 c = c + shiftl( map_to_64( key(p8+2) ), 16_int64 ) 102 c = c + shiftl( map_to_64( key(p8+1) ), 8_int64 ) 101 c = c + map_to_64( key(p8+0) ) go to 888 100 c = c + sc_const d = d + sc_const 888 call short_end( a, b, c, d ) hash_inout(1) = a hash_inout(2) = b close(40) contains pure function map_to_64( key ) integer(int8), intent(in) :: key integer(int64) :: map_to_64 if ( little_endian ) then map_to_64 = transfer( [ key, 0_int8, 0_int8, 0_int8, & 0_int8, 0_int8, 0_int8, 0_int8 ], & 0_int64 ) else map_to_64 = transfer( [ 0_int8, 0_int8, 0_int8, 0_int8, & 0_int8, 0_int8, 0_int8, key ], & 0_int64 ) end if end function map_to_64 pure subroutine shortmix( h0, h1, h2, h3 ) ! ! The goal is for each bit of the input to expand into 128 bits of ! apparent entropy before it is fully overwritten. ! n trials both set and cleared at least m bits of h0 h1 h2 h3 ! n: 2 m: 29 ! n: 3 m: 46 ! n: 4 m: 57 ! n: 5 m: 107 ! n: 6 m: 146 ! n: 7 m: 152 ! when run forwards or backwards ! for all 1-bit and 2-bit diffs ! with diffs defined by either xor or subtraction ! with a base of all zeros plus a counter, or plus another bit, or random ! integer(int64), intent(inout) :: h0, h1, h2, h3 h2 = ishftc( h2, 50 ) h2 = h2 + h3 h0 = ieor( h0, h2 ) h3 = ishftc( h3, 52 ) h3 = h3 + h0 h1 = ieor( h1, h3 ) h0 = ishftc( h0, 30 ) h0 = h0 + h1 h2 = ieor( h2, h0 ) h1 = ishftc( h1, 41 ) h1 = h1 + h2 h3 = ieor( h3, h1 ) h2 = ishftc( h2, 54 ) h2 = h2 + h3 h0 = ieor( h0, h2 ) h3 = ishftc( h3, 48 ) h3 = h3 + h0 h1 = ieor( h1, h3 ) h0 = ishftc( h0, 38 ) h0 = h0 + h1 h2 = ieor( h2, h0 ) h1 = ishftc( h1, 37 ) h1 = h1 + h2 h3 = ieor( h3, h1 ) h2 = ishftc( h2, 62 ) h2 = h2 + h3 h0 = ieor( h0, h2 ) h3 = ishftc( h3, 34 ) h3 = h3 + h0 h1 = ieor( h1, h3 ) h0 = ishftc( h0, 5 ) h0 = h0 + h1 h2 = ieor( h2, h0 ) h1 = ishftc( h1, 36 ) h1 = h1 + h2 h3 = ieor( h3, h1 ) end subroutine shortmix pure subroutine short_end( h0, h1, h2, h3 ) ! ! Mix all 4 inputs together so that h0, h1 are a hash of them all. ! ! For two inputs differing in just the input bits ! Where "differ" means xor or subtraction ! And the base value is random, or a counting value starting at that bit ! The final result will have each bit of h0, h1 flip ! For every input bit, ! with probability 50 +- .3% (it is probably better than that) ! For every pair of input bits, ! with probability 50 +- .75% (the worst case is approximately that) ! integer(int64), intent(inout) :: h0, h1, h2, h3 h3 = ieor( h3, h2 ) h2 = ishftc( h2, 15 ) h3 = h3 + h2 h0 = ieor( h0, h3 ) h3 = ishftc( h3, 52 ) h0 = h0 + h3 h1 = ieor( h1, h0 ) h0 = ishftc( h0, 26 ) h1 = h1 + h0 h2 = ieor( h2, h1 ) h1 = ishftc( h1, 51 ) h2 = h2 + h1 h3 = ieor( h3, h2 ) h2 = ishftc( h2, 28 ) h3 = h3 + h2 h0 = ieor( h0, h3 ) h3 = ishftc( h3, 9 ) h0 = h0 + h3 h1 = ieor( h1, h0 ) h0 = ishftc( h0, 47 ) h1 = h1 + h0 h2 = ieor( h2, h1 ) h1 = ishftc( h1, 54 ) h2 = h2 + h1 h3 = ieor( h3, h2 ) h2 = ishftc( h2, 32 ) h3 = h3 + h2 h0 = ieor( h0, h3 ) h3 = ishftc( h3, 25 ) h0 = h0 + h3 h1 = ieor( h1, h0 ) h0 = ishftc( h0, 63 ) h1 = h1 + h0 end subroutine short_end end subroutine spookyhash_short ! do the whole hash in one call module subroutine spookyHash_128( key, hash_inout ) integer(int8), intent(in), target :: key(0:) integer(int64), intent(inout) :: hash_inout(2) integer(int64) :: buf(sc_numvars) integer(int64) :: h(0:11) integer(int64) :: bend, i, length, p8, remain, remainder, tail integer(int8) :: buf8(8) length = size(key, kind=int64) if ( length < sc_buffsize ) then call spookyhash_short( key, hash_inout ) return end if h( [ 0, 3, 6, 9 ] ) = hash_inout(1) h( [ 1, 4, 7, 10 ] ) = hash_inout(2) h( [ 2, 5, 8, 11 ] ) = sc_const ! Number of bytes in number of complete internal states bend = (length/sc_blocksize)*sc_blocksize ! Handle all SC_BLOCKSIZE blocks of bytes do i=0, bend-1, sc_blocksize buf(:) = transfer( key(i:i+sc_blocksize-1), 0_int64, sc_numVars ) call spookyhash_mix( buf, h ) end do ! all complete internal states processed ! handle the last partial block of sc_blocksize bytes remainder = ( length - bend ) ! 0 <= remainder < sc_blocksize == 96 remain = remainder / 8 ! Number of INT64's in partial block buf(1:remain) = transfer( key(bend:bend+remain*8-1), 0_int64, remain ) buf(remain+1:sc_numvars) = 0_int64 tail = remainder - 8 * remain ! Number of INT8s after INT64s p8 = bend + remain * 8 ! # of bytes until tail start buf8(1:tail) = key(p8:p8+tail-1) buf8(tail+1:8) = 0_int8 buf(remain+1) = transfer( buf8, 0_int64 ) buf8(1:7) = 0_int8 buf8(8) = int( remainder, kind=int8 ) ! 0 <= remainder < 96 buf(sc_numvars) = ieor( buf(sc_numvars), transfer( buf8, 0_int64 ) ) ! do some final mixing call spookyhash_end( buf, h ) hash_inout(1:2) = h(0:1) end subroutine spookyHash_128 ! ! This is used if the input is 96 bytes long or longer. ! ! The internal state is fully overwritten every 96 bytes. ! Every input bit appears to cause at least 128 bits of entropy ! before 96 other bytes are combined, when run forward or backward ! For every input bit, ! Two inputs differing in just that input bit ! Where "differ" means xor or subtraction ! And the base value is random ! When run forward or backwards one Mix ! I tried 3 pairs of each; they all differed by at least 212 bits. ! pure subroutine spookyhash_mix( data, s ) integer(int64), intent(in) :: data(0:) integer(int64), intent(inout) :: s(0:11) s(0) = s(0) + data(0) s(2) = ieor( s(2), s(10) ) s(11) = ieor( s(11), s(0) ) s(0) = ishftc( s(0), 11 ) s(11) = s(11) + s(1) s(1) = s(1) + data(1) s(3) = ieor( s(3), s(11) ) s(0) = ieor( s(0), s(1) ) s(1) = ishftc( s(1), 32 ) s(0) = s(0) + s(2) s(2) = s(2) + data(2) s(4) = ieor( s(4), s(0) ) s(1) = ieor( s(1), s(2) ) s(2) = ishftc( s(2), 43 ) s(1) = s(1) + s(3) s(3) = s(3) + data(3) s(5) = ieor( s(5), s(1) ) s(2) = ieor( s(2), s(3) ) s(3) = ishftc( s(3), 31 ) s(2) = s(2) + s(4) s(4) = s(4) + data(4) s(6) = ieor( s(6), s(2) ) s(3) = ieor( s(3), s(4) ) s(4) = ishftc( s(4), 17 ) s(3) = s(3) + s(5) s(5) = s(5) + data(5) s(7) = ieor( s(7), s(3) ) s(4) = ieor( s(4), s(5) ) s(5) = ishftc( s(5), 28 ) s(4) = s(4) + s(6) s(6) = s(6) + data(6) s(8) = ieor( s(8), s(4) ) s(5) = ieor( s(5), s(6) ) s(6) = ishftc( s(6), 39 ) s(5) = s(5) + s(7) s(7) = s(7) + data(7) s(9) = ieor( s(9), s(5) ) s(6) = ieor( s(6), s(7) ) s(7) = ishftc( s(7), 57 ) s(6) = s(6) + s(8) s(8) = s(8) + data(8) s(10) = ieor( s(10), s(6) ) s(7) = ieor( s(7), s(8) ) s(8) = ishftc( s(8), 55 ) s(7) = s(7) + s(9) s(9) = s(9) + data(9) s(11) = ieor( s(11), s(7) ) s(8) = ieor( s(8), s(9) ) s(9) = ishftc( s(9), 54 ) s(8) = s(8) + s(10) s(10) = s(10) + data(10) s(0) = ieor( s(0), s(8) ) s(9) = ieor( s(9), s(10) ) s(10) = ishftc( s(10), 22 ) s(9) = s(9) + s(11) s(11) = s(11) + data(11) s(1) = ieor( s(1), s(9) ) s(10) = ieor( s(10), s(11) ) s(11) = ishftc( s(11), 46 ) s(10) = s(10) + s(0) end subroutine spookyhash_mix pure subroutine spookyhash_end( data, h) integer(int64), intent(in) :: data(0:) integer(int64), intent(inout) :: h(0:11) h = h + data(0:11) call endpartial( h ) call endpartial( h ) call endpartial( h ) contains ! ! Mix all 12 inputs together so that h0, h1 are a hash of them all. ! ! For two inputs differing in just the input bits ! Where "differ" means xor or subtraction ! And the base value is random, or a counting value starting at that bit ! The final result will have each bit of h0, h1 flip ! For every input bit, ! with probability 50 +- .3% ! For every pair of input bits, ! with probability 50 +- 3% ! ! This does not rely on the last Mix() call having already mixed some. ! Two iterations was almost good enough for a 64-bit result, but a ! 128-bit result is reported, so End() does three iterations. ! pure subroutine endpartial( h ) integer(int64), intent(inout) :: h(0:11) h(11) = h(11) + h(1) h(2) = ieor( h(2), h(11) ) h(1) = ishftc( h(1), 44 ) h(0) = h(0) + h(2) h(3) = ieor( h(3), h(0) ) h(2) = ishftc( h(2), 15 ) h(1) = h(1) + h(3) h(4) = ieor( h(4), h(1) ) h(3) = ishftc( h(3), 34 ) h(2) = h(2) + h(4) h(5) = ieor( h(5), h(2) ) h(4) = ishftc( h(4), 21 ) h(3) = h(3) + h(5) h(6) = ieor( h(6), h(3) ) h(5) = ishftc( h(5), 38 ) h(4) = h(4) + h(6) h(7) = ieor( h(7), h(4) ) h(6) = ishftc( h(6), 33 ) h(5) = h(5) + h(7) h(8) = ieor( h(8), h(5) ) h(7) = ishftc( h(7), 10 ) h(6) = h(6) + h(8) h(9) = ieor( h(9), h(6) ) h(8) = ishftc( h(8), 13 ) h(7) = h(7) + h(9) h(10) = ieor( h(10), h(7) ) h(9) = ishftc( h(9), 38 ) h(8) = h(8) + h(10) h(11) = ieor( h(11), h(8) ) h(10) = ishftc( h(10), 53 ) h(9) = h(9) + h(11) h(0) = ieor( h(0), h(9) ) h(11) = ishftc( h(11), 42 ) h(10) = h(10) + h(0) h(1) = ieor( h(1), h(10) ) h(0) = ishftc( h(0), 54 ) end subroutine endpartial end subroutine spookyhash_end pure module subroutine spookysubhash_init( self, seed ) type(spooky_subhash), intent(out) :: self integer(int64), intent(in) :: seed(2) self % state(0:1) = seed self % length = 0 self % remainder = 0_int8 end subroutine spookysubhash_init ! add a message fragment to the state module subroutine spookyhash_update( spooky, key ) type(spooky_subhash), intent(inout) :: spooky integer(int8), intent(in) :: key(0:) integer(int8) :: dummy(0:7) integer(int64) :: h(0:11) integer(int64) :: bend, & length, & new_length, & p8, & remainder length = size(key, kind=int64) new_length = length + spooky % remainder ! Is this message fragment too short? If it is, stuff it away. if ( new_Length < sc_buffsize ) then remainder = spooky % remainder spooky % data( remainder:remainder+length-1 ) = key spooky % length = length + spooky % length dummy = transfer( new_length, 0_int8, 8 ) if ( little_endian ) then spooky % remainder = transfer( [ dummy(0), 0_int8 ], 0_int16 ) else spooky % remainder = transfer( [ 0_int8, dummy(7) ], 0_int16 ) end if return end if ! init the variables if ( spooky % length < sc_buffsize ) then h( [ 0, 3, 6, 9 ] ) = spooky % state(0) h( [ 1, 4, 7, 10 ] ) = spooky % state(1) h( [ 2, 5, 8, 11 ] ) = sc_const else h(0:11) = spooky % state(0:11) end if spooky % length = length + spooky % length ! if we've got anything stuffed away, use it now if ( spooky % remainder /= 0_int16 ) then block integer(int16) :: prefix prefix = sc_buffsize - spooky % remainder remainder = spooky % remainder spooky % data(remainder:remainder+prefix-1) = key(0:prefix-1) call spookyhash_mix( transfer(spooky % data(0:sc_blocksize-1), & 0_int64, sc_numvars), h ) call spookyhash_mix( & transfer(spooky % data(sc_blocksize:2*sc_blocksize-1), & 0_int64, sc_numvars), h ) p8 = prefix length = length - prefix end block else p8 = 0 end if ! handle all whole blocks of sc_blocksize bytes requiring aligned bytes bend = p8 + 8*(length/sc_blocksize)*sc_numVars remainder = length - ( bend - p8 ) do while( p8 < bend ) spooky % data(0:sc_blocksize-1) = key( p8:p8+sc_blocksize-1 ) call spookyhash_mix( transfer( spooky % data(0:sc_blocksize-1), & 0_int64, sc_numvars), h ) p8 = p8 + sc_blocksize end do ! stuff away the last few bytes spooky % remainder = remainder if ( remainder > 0 ) then spooky % data(0:remainder-1) = & key(bend:bend+remainder-1) end if ! stuff away the variables spooky % state(0:11) = h(0:11) end subroutine spookyhash_update ! report the hash for the concatenation of all message fragments so far module subroutine spookyhash_final(spooky, hash_code) type(spooky_subhash), intent(inout) :: spooky integer(int64), intent(inout) :: hash_code(2) integer(int64) :: h(0:11) integer(int64) :: index, remainder integer(int8) :: dummy(2) ! init the variables if ( spooky % length < sc_buffsize ) then hash_code = spooky % state(0:1) call spookyhash_short( spooky % data(0:spooky % length-1), & hash_code ) return end if remainder = spooky % remainder h(0:11) = spooky % state(0:11) if ( remainder >= sc_blocksize ) then ! m_data can contain two blocks; handle any whole first block call spookyhash_mix( transfer( spooky % data, 0_int64, & 2*sc_numvars), h ) index = sc_blocksize remainder = remainder - sc_blocksize else index = 0 end if ! mix in the last partial block, and the length mod sc_blocksize spooky % data(sc_blocksize+remainder:) = 0_int8 dummy = transfer( remainder, 0_int8, 2 ) if ( little_endian ) then spooky % data(sc_blocksize-1) = dummy(1) else spooky % data(sc_blocksize-1) = dummy(2) end if ! do some final mixing call spookyhash_end( transfer(spooky % data, 0_int64, 2*sc_numvars), h ) hash_code(1:2) = h(0:1) end subroutine spookyhash_final pure function rot_64_32( a, k ) integer(int64) :: rot_64_32 integer(int64), intent(in) :: a integer, intent(in) :: k rot_64_32 = iand( ior( shiftl( a, k ), shiftr( a, 32-k ) ), two_32-1 ) end function rot_64_32 module subroutine new_spooky_hash_seed( seed ) ! Random SEED generator for integer(int64), intent(inout) :: seed(2) integer(int64) :: old_seed(2) real(dp) :: sample(4) integer(int32) :: part(4) old_seed = seed find_seed: do call random_number( sample ) part = int( floor( sample * 2_int64**32, int64 ) - 2_int64**31, & int32 ) seed = transfer( part, seed, 2 ) if ( seed(1) /= old_seed(1) .or. seed(2) /= old_seed(2) ) return end do find_seed end subroutine new_spooky_hash_seed end submodule stdlib_hash_64bit_spookyv2 fortran-lang-stdlib-0ede301/src/hash/stdlib_hash_32bit_water.fypp0000664000175000017500000003026415135654166025276 0ustar alastairalastair!!------------------------------------------------------------------------------ !! `WATER_HASH` is a translation to Fortran 2008 of the `waterhash` algorithm !! of Tommy Ettinger. Tommy Ettinger's original C++ code, `waterhash.h`, is !! available at the URL: https://github.com/tommyettinger/waterhash under the !! `unlicense`, https://github.com/tommyettinger/waterhash/blob/master/LICENSE. !! "`waterhash` is a variant on Wang Yi's `wyhash`, with 32 bit output, !! using at most 64 bit arithmetic. `wyhash` is available at the URL: !! `https://github.com/wangyi-fudan/wyhash` also under the unlicense: !! `https://github.com/wangyi-fudan/wyhash/blob/master/LICENSE`. !! Original Author: Wang Yi !! Waterhash Variant Author: Tommy Ettinger !! !! The `unlicense` reads as follows: !! This is free and unencumbered software released into the public domain. !! !! Anyone is free to copy, modify, publish, use, compile, sell, or !! distribute this software, either in source code form or as a compiled !! binary, for any purpose, commercial or non-commercial, and by any !! means. !! !! In jurisdictions that recognize copyright laws, the author or authors !! of this software dedicate any and all copyright interest in the !! software to the public domain. We make this dedication for the benefit !! of the public at large and to the detriment of our heirs and !! successors. We intend this dedication to be an overt act of !! relinquishment in perpetuity of all present and future rights to this !! software under copyright law. !! !! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, !! EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF !! MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. !! IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR !! OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, !! ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR !! OTHER DEALINGS IN THE SOFTWARE. !! !! For more information, please refer to !! !! `WATER_HASH` is distributed as part of the `stdlib_32_bit_hash_functions.f90` !! module and its `stdlib_hash_32bit_water.f90` submodule with the Fortran !! Standard Library at URL: https://github.com/fortran-lang/stdlib. !! The Fortran Standard Library, including this code, is distributed under the !! MIT License as described in the `LICENSE` file distributed with the library. !! `WATER_HASH` differs from `waterhash.h` not only in its use of Fortran, !! but also in its use of signed two's complement arithmetic in contrast to !! the unsigned arithmetic of Ettinger and Wang Yi, and in making some of the !! uses of `TRANSFER` endian dependent, in an attempt to make the quality of !! the hash endian independent. !! !! To be useful this code must be processed by a processor that implements two !! Fortran 2008 extensions to Fortran 2003: submodules, and 64 bit (`INT64`) !! integers. The processor must also use two's complement integers !! (all Fortran 95+ processors use two's complement arithmetic) with !! wrap around overflow at runtime and for BOZ constants. The latest releases !! of the following processors are known to implement the required Fortran !! 2008 extensions and default to runtime wrap around overflow: FLANG, !! gfortran, ifort, and NAG Fortran. Older versions of gfortran will require !! the compiler flag, `-fno-range-check`, to ensure wrap around semantics !! for BOZ constants, and only versions of the NAG compiler starting with !! version 17, have implemented submodules. The latest releases of Cray !! Fortran and IBM Fortran are known to implement the Fortran 2008 extensions, !! but whether they also implement wrap around overflow is unknown. !! !! This implementation has only been tested on little endian processors. It !! will generate different hashes on big endian processors, but they are !! believed to be of comparable quality to those generated for little endian !! processors. !! !! No version of this hash is suitable as a cryptographic hash. !!------------------------------------------------------------------------------ #! Integer kinds to be considered during templating #:set INT_KINDS = ["int16", "int32", "int64"] submodule(stdlib_hash_32bit) stdlib_hash_32bit_water implicit none contains pure module function int8_water_hash( key, seed ) result(hash_code) integer(int32) :: hash_code integer(int8), intent(in) :: key(0:) integer(int64), intent(in) :: seed integer(int32) :: dummy(2) integer(int64) :: h integer(int64) :: i integer(int64) :: len integer(int64), parameter :: & waterp0 = int(z'a0761d65', kind=int64), & waterp1 = int(z'e7037ed1', kind=int64), & waterp2 = int(z'8ebc6af1', kind=int64), & waterp3 = int(z'589965cd', kind=int64), & waterp4 = int(z'1d8e4e27', kind=int64), & waterp5 = int(z'eb44accb', kind=int64) len = size(key, kind=int64) h = seed do i = 0_int64, len-16, 16 h = watermum(watermum(ieor(waterr32(key(i:)),waterp1), & ieor(waterr32(key(i+4:)),waterp2)) + h, & watermum(ieor(waterr32(key(i+8:)),waterp3), & ieor(waterr32(key(i+12:)),waterp4))) end do h = h + waterp5 select case( iand(len, 15_int64) ) case(1) h = watermum(ieor(waterp2, h), & ieor(waterr08(key(i:)), waterp1)) case(2) h = watermum(ieor(waterp3, h), & ieor(waterr16(key(i:)), waterp4)) case(3) h = watermum(ieor(waterr16(key(i:)), h), & ieor(waterr08(key(i+2:)), waterp2)) case(4) h = watermum(ieor(waterr16(key(i:)), h), & ieor(waterr16(key(i+2:)), waterp3)) case(5) h = watermum(ieor(waterr32(key(i:)), h), & ieor(waterr08(key(i+4:)), waterp1)) case(6) h = watermum(ieor(waterr32(key(i:)), h), & ieor(waterr16(key(i+4:)), waterp1)) case(7) h = watermum(ieor(waterr32(key(i:)), h), & ieor(ior(ishft(waterr16(key(i+4:)), 8), & waterr08(key(i+6:))), waterp1)) case(8) h = watermum(ieor(waterr32(key(i:)), h), & ieor(waterr32(key(i+4:)), waterp0)) case(9) h = ieor(watermum(ieor(waterr32(key(i:)), h), & ieor(waterr32(key(i+4:)), waterp2)), & watermum(ieor(h, waterp4), & ieor(waterr08(key(i+8:)), waterp3))) case(10) h = ieor(watermum(ieor(waterr32(key(i:)), h), & ieor(waterr32(key(i+4:)), waterp2)), & watermum(h, ieor(waterr16(key(i+8:)), waterp3))) case(11) h = ieor(watermum(ieor(waterr32(key(i:)), h), & ieor(waterr32(key(i+4:)), waterp2)), & watermum(h, & ieor(ior(ishft(waterr16(key(i+8:)),8), & waterr08(key(i+10:))), & waterp3))) case(12) h = ieor(watermum(ieor(waterr32(key(i:)), h), & ieor(waterr32(key(i+4:)), waterp2)), & watermum(ieor(h, waterr32(key(i+8:))), & waterp4)) case(13) h = ieor(watermum(ieor(waterr32(key(i:)), h), & ieor(waterr32(key(i+4:)), waterp2)), & watermum(ieor(h, waterr32(key(i+8:))), & ieor(waterr08(key(i+12:)), waterp4))) case(14) h = ieor(watermum(ieor(waterr32(key(i:)), h), & ieor(waterr32(key(i+4:)), waterp2)), & watermum(ieor(h, waterr32(key(i+8:))), & ieor(waterr16(key(i+12:)), waterp4))) case(15) h = ieor(watermum(ieor(waterr32(key(i:)), h), & ieor(waterr32(key(i+4:)), waterp2)), & watermum(ieor(h, waterr32(key(i+8:))), & ieor(ior(ishft(waterr16(key(i+12:)),8), & waterr08(key(i+14:))), & waterp4))) end select h = ieor( h, ishft(h,16) ) * ieor( len, waterp0 ) h = h - ishft( h, -32 ) dummy(1:2) = transfer(h, dummy, 2) if (little_endian) then hash_code = dummy(1) else hash_code = dummy(2) end if contains pure function watermum( a, b ) result(r) integer(int64) :: r integer(int64), intent(in) :: a, b r = a * b r = r - ishft(r, -32) end function watermum pure function waterr08( p ) result(v) integer(int64) :: v integer(int8), intent(in) :: p(:) if (little_endian) then v = transfer( [ p(1), 0_int8, 0_int8, 0_int8, & 0_int8, 0_int8, 0_int8, 0_int8 ], v ) else v = transfer( [ 0_int8, 0_int8, 0_int8, 0_int8, & 0_int8, 0_int8, 0_int8, p(1) ], v ) end if end function waterr08 pure function waterr16( p ) result(v) integer(int64) :: v integer(int8), intent(in) :: p(:) if (little_endian) then v = transfer( [ p(1), p(2), 0_int8, 0_int8, & 0_int8, 0_int8, 0_int8, 0_int8 ], v ) else v = transfer( [ 0_int8, 0_int8, 0_int8, 0_int8, & 0_int8, 0_int8, p(2), p(1) ], v ) end if end function waterr16 pure function waterr32( p ) result(v) integer(int64) :: v integer(int8), intent(in) :: p(:) if (little_endian) then v = transfer( [ p(1), p(2), p(3), p(4), & 0_int8, 0_int8, 0_int8, 0_int8 ], v ) else v = transfer( [ 0_int8, 0_int8, 0_int8, 0_int8, & p(4), p(3), p(2), p(1) ], v ) end if end function waterr32 end function int8_water_hash #:for k1 in INT_KINDS pure module function ${k1}$_water_hash( key, seed ) result(hash_code) integer(${k1}$), intent(in) :: key(:) integer(int64), intent(in) :: seed integer(int_hash) :: hash_code hash_code = int8_water_hash( transfer( key, 0_int8, & bytes_${k1}$*size(key, kind=int64) ), seed) end function ${k1}$_water_hash #:endfor elemental module function character_water_hash( key, seed ) & result(hash_code) character(*), intent(in) :: key integer(int64), intent(in) :: seed integer(int_hash) :: hash_code hash_code = int8_water_hash( transfer( key, 0_int8, & bytes_char*len(key, kind=int64) ), seed) end function character_water_hash module subroutine new_water_hash_seed( seed ) integer(int64), intent(inout) :: seed integer(int64) :: old_seed real(dp) :: sample(2) integer(int32) :: part(2) old_seed = seed find_seed:do call random_number( sample ) part = int( floor( sample * 2_int64**32, int64 ) - 2_int64**31, & int32 ) seed = transfer( part, seed ) if ( seed /= old_seed ) return end do find_seed end subroutine new_water_hash_seed end submodule stdlib_hash_32bit_water fortran-lang-stdlib-0ede301/src/hash/stdlib_hash_32bit_fnv.fypp0000664000175000017500000001144615135654166024746 0ustar alastairalastair!!------------------------------------------------------------------------------ !! `FNV_1_HASH` and `FNV_1A_Hash` are translations to Fortran 2008 of the !! `FNV-1` and `FNV-1a` hash functions of Glenn Fowler, Landon Curt Noll, !! and Phong Vo, that has been released into the public domain. Permission !! has been granted, by Landon Curt Noll, for the use of these algorithms !! in the Fortran Standard Library. A description of these functions is !! available at https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function. !!------------------------------------------------------------------------------ !#! Integer kinds to be considered during templating #:set INT_KINDS = ["int16", "int32", "int64"] submodule(stdlib_hash_32bit) stdlib_hash_32bit_fnv !! An implementation of the FNV hashes 1 and 1a of Glenn Fowler, Landon Curt !! Noll, and Kiem-Phong-Vo, !! https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function implicit none integer(int_hash), parameter :: & offset_basis = int( z'811C9DC5', int_hash ), & prime = int( z'01000193', int_hash ) contains pure module function int8_fnv_1( key ) result(hash_code) !! The original FNV-1 8-bit key algorithm. integer(int8), intent(in) :: key(:) integer(int_hash) :: hash_code integer(int64) :: i hash_code = offset_basis do i=1_int64, size(key, kind=int64) hash_code = hash_code * prime if ( little_endian ) then hash_code = ieor( hash_code, & transfer( [key(i), 0_int8, 0_int8, 0_int8], & 0_int_hash ) ) else hash_code = ieor( hash_code, & transfer( [0_int8, 0_int8, 0_int8, key(i)], & 0_int_hash ) ) end if end do end function int8_fnv_1 #:for k1 in INT_KINDS pure module function ${k1}$_fnv_1( key ) result(hash_code) ! A ${k1}$ array key wrapper for the FNV-1 algorithm. integer(${k1}$), intent(in) :: key(:) integer(int_hash) :: hash_code hash_code = int8_fnv_1( transfer( key, 0_int8, & bytes_${k1}$* & size( key, kind=int64 ) ) ) end function ${k1}$_fnv_1 #:endfor elemental module function character_fnv_1( key ) result(hash_code) ! A default character key wrapper for the FNV-1 algorithm. character(*), intent(in) :: key integer(int_hash) :: hash_code hash_code = int8_fnv_1( transfer( key, & 0_int8, & bytes_char* & len(key, kind=int64) ) ) end function character_fnv_1 pure module function int8_fnv_1a( key ) result(hash_code) !! The original FNV-1a 8-bit key algorithm. integer(int8), intent(in) :: key(:) integer(int_hash) :: hash_code integer(int64) :: i hash_code = offset_basis do i=1_int64, size(key, kind=int64) if ( little_endian ) then hash_code = ieor( hash_code, & transfer( [key(i), 0_int8, 0_int8, 0_int8], & 0_int_hash ) ) else hash_code = ieor( hash_code, & transfer( [0_int8, 0_int8, 0_int8, key(i)], & 0_int_hash ) ) end if hash_code = hash_code * prime end do end function int8_fnv_1a #:for k1 in INT_KINDS pure module function ${k1}$_fnv_1a( key ) result(hash_code) ! A ${k1}$ array key wrapper for the FNV-1a algorithm. integer(${k1}$), intent(in) :: key(:) integer(int_hash) :: hash_code hash_code = int8_fnv_1a( transfer( key, 0_int8, & bytes_${k1}$* & size(key, kind=int64)) ) end function ${k1}$_fnv_1a #:endfor elemental module function character_fnv_1a( key ) result(hash_code) ! A default character key wrapper for the FNV-1 algorithm. character(*), intent(in) :: key integer(int_hash) :: hash_code hash_code = int8_fnv_1a( transfer( key, 0_int8, & (bits_char/bits_int8)* & len(key, kind=int64) ) ) end function character_fnv_1a end submodule stdlib_hash_32bit_fnv fortran-lang-stdlib-0ede301/src/intrinsics/0000775000175000017500000000000015135654166021142 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/intrinsics/stdlib_intrinsics_dot_product.fypp0000664000175000017500000000442315135654166030201 0ustar alastairalastair#:include "common.fypp" #:set I_KINDS_TYPES = list(zip(INT_KINDS, INT_TYPES, INT_KINDS)) #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:def cnjg(type,expression) #:if 'complex' in type conjg(${expression}$) #:else ${expression}$ #:endif #:enddef submodule(stdlib_intrinsics) stdlib_intrinsics_dot_product !!Replacement for certain Fortran intrinsic functions offering either faster and/or more accurate implementations. !! ([Specification](../page/specs/stdlib_intrinsics.html)) use stdlib_kinds use stdlib_constants implicit none integer, parameter :: ilp = int64 contains ! This implementation is based on https://github.com/jalvesz/fast_math #:for k, t, s in I_KINDS_TYPES + R_KINDS_TYPES + C_KINDS_TYPES pure module function stdlib_dot_product_${s}$(a,b) result(p) integer(ilp), parameter :: chunk = 64 ${t}$, intent(in) :: a(:) ${t}$, intent(in) :: b(:) ${t}$ :: p ${t}$ :: abatch(chunk) integer(ilp) :: i, n, r ! ----------------------------- n = size(a,kind=ilp) r = mod(n,chunk) abatch(1:r) = ${cnjg(t,'a(1:r)')}$*b(1:r) abatch(r+1:chunk) = zero_${s}$ do i = r+1, n-r, chunk abatch(1:chunk) = abatch(1:chunk) + ${cnjg(t,'a(i:i+chunk-1)')}$*b(i:i+chunk-1) end do p = zero_${s}$ do i = 1, chunk/2 p = p + abatch(i)+abatch(chunk/2+i) end do end function #:endfor #:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES pure module function stdlib_dot_product_kahan_${s}$(a,b) result(p) integer(ilp), parameter :: chunk = 64 ${t}$, intent(in) :: a(:) ${t}$, intent(in) :: b(:) ${t}$ :: p ${t}$ :: abatch(chunk) ${t}$ :: cbatch(chunk) integer(ilp) :: i, n, r ! ----------------------------- n = size(a,kind=ilp) r = mod(n,chunk) abatch(1:r) = ${cnjg(t,'a(1:r)')}$*b(1:r) abatch(r+1:chunk) = zero_${s}$ cbatch = zero_${s}$ do i = r+1, n-r, chunk call kahan_kernel( ${cnjg(t,'a(i:i+chunk-1)')}$*b(i:i+chunk-1) , abatch(1:chunk) , cbatch(1:chunk) ) end do p = zero_${s}$ do i = 1, chunk call kahan_kernel( abatch(i) , p , cbatch(i) ) end do end function #:endfor end submodule stdlib_intrinsics_dot_product fortran-lang-stdlib-0ede301/src/intrinsics/CMakeLists.txt0000664000175000017500000000064515135654166023707 0ustar alastairalastairset(intrinsics_fppFiles stdlib_intrinsics_dot_product.fypp stdlib_intrinsics.fypp stdlib_intrinsics_matmul.fypp stdlib_intrinsics_sum.fypp ) set(intrinsics_cppFiles ) configure_stdlib_target(${PROJECT_NAME}_intrinsics "" intrinsics_fppFiles intrinsics_cppFiles) target_link_libraries(${PROJECT_NAME}_intrinsics PUBLIC ${PROJECT_NAME}_linalg_core ${PROJECT_NAME}_blas ${PROJECT_NAME}_constants) fortran-lang-stdlib-0ede301/src/intrinsics/stdlib_intrinsics_sum.fypp0000664000175000017500000002251115135654166026455 0ustar alastairalastair#:include "common.fypp" #:set I_KINDS_TYPES = list(zip(INT_KINDS, INT_TYPES, INT_KINDS)) #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set RANKS = range(2, MAXRANK + 1) submodule(stdlib_intrinsics) stdlib_intrinsics_sum !! ([Specification](../page/specs/stdlib_intrinsics.html)) use stdlib_kinds use stdlib_constants implicit none integer, parameter :: ilp = int64 contains !================= 1D Base implementations ============ ! This implementation is based on https://github.com/jalvesz/fast_math #:for k, t, s in I_KINDS_TYPES + R_KINDS_TYPES + C_KINDS_TYPES pure module function stdlib_sum_1d_${s}$(a) result(s) integer(ilp), parameter :: chunk = 64 ${t}$, intent(in) :: a(:) ${t}$ :: s ${t}$ :: abatch(chunk) integer(ilp) :: i, n, r ! ----------------------------- n = size(a,kind=ilp) r = mod(n,chunk) abatch(1:r) = a(1:r) abatch(r+1:chunk) = zero_${s}$ do i = r+1, n-r, chunk abatch(1:chunk) = abatch(1:chunk) + a(i:i+chunk-1) end do s = zero_${s}$ do i = 1, chunk/2 s = s + abatch(i)+abatch(chunk/2+i) end do end function pure module function stdlib_sum_1d_${s}$_mask(a,mask) result(s) integer(ilp), parameter :: chunk = 64 ${t}$, intent(in) :: a(:) logical, intent(in) :: mask(:) ${t}$ :: s ${t}$ :: abatch(chunk) integer(ilp) :: i, n, r ! ----------------------------- n = size(a,kind=ilp) r = mod(n,chunk) abatch(1:r) = merge( zero_${s}$ , a(1:r) , mask(1:r) ) abatch(r+1:chunk) = zero_${s}$ do i = r+1, n-r, chunk abatch(1:chunk) = abatch(1:chunk) + merge( zero_${s}$ , a(i:i+chunk-1), mask(i:i+chunk-1) ) end do s = zero_${s}$ do i = 1, chunk/2 s = s + abatch(i)+abatch(chunk/2+i) end do end function #:endfor #:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES pure module function stdlib_sum_kahan_1d_${s}$(a) result(s) integer(ilp), parameter :: chunk = 64 ${t}$, intent(in) :: a(:) ${t}$ :: s ${t}$ :: sbatch(chunk) ${t}$ :: cbatch(chunk) integer(ilp) :: i, n, r ! ----------------------------- n = size(a,kind=ilp) r = mod(n,chunk) sbatch(1:r) = a(1:r) sbatch(r+1:chunk) = zero_${s}$ cbatch = zero_${s}$ do i = r+1, n-r, chunk call kahan_kernel( a(i:i+chunk-1) , sbatch(1:chunk) , cbatch(1:chunk) ) end do s = zero_${s}$ do i = 1,chunk call kahan_kernel( sbatch(i) , s , cbatch(i) ) end do end function pure module function stdlib_sum_kahan_1d_${s}$_mask(a,mask) result(s) integer(ilp), parameter :: chunk = 64 ${t}$, intent(in) :: a(:) logical, intent(in) :: mask(:) ${t}$ :: s ${t}$ :: sbatch(chunk) ${t}$ :: cbatch(chunk) integer(ilp) :: i, n, r ! ----------------------------- n = size(a,kind=ilp) r = mod(n,chunk) sbatch(1:r) = merge( zero_${s}$ , a(1:r) , mask(1:r) ) sbatch(r+1:chunk) = zero_${s}$ cbatch = zero_${s}$ do i = r+1, n-r, chunk call kahan_kernel( a(i:i+chunk-1) , sbatch(1:chunk) , cbatch(1:chunk), mask(i:i+chunk-1) ) end do s = zero_${s}$ do i = 1,chunk call kahan_kernel( sbatch(i) , s , cbatch(i) ) end do end function #:endfor !================= N-D implementations ============ #:for k, t, s in I_KINDS_TYPES + R_KINDS_TYPES + C_KINDS_TYPES #:for rank in RANKS pure module function stdlib_sum_${rank}$d_${s}$( x , mask ) result( s ) ${t}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in), optional :: mask${ranksuffix(rank)}$ ${t}$ :: s if(.not.present(mask)) then s = sum_recast(x,size(x,kind=ilp)) else s = sum_recast_mask(x,mask,size(x,kind=ilp)) end if contains pure ${t}$ function sum_recast(b,n) integer(ilp), intent(in) :: n ${t}$, intent(in) :: b(n) sum_recast = stdlib_sum(b) end function pure ${t}$ function sum_recast_mask(b,m,n) integer(ilp), intent(in) :: n ${t}$, intent(in) :: b(n) logical, intent(in) :: m(n) sum_recast_mask = stdlib_sum(b,m) end function end function pure module function stdlib_sum_${rank}$d_dim_${s}$( x , dim, mask ) result( s ) ${t}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in):: dim logical, intent(in), optional :: mask${ranksuffix(rank)}$ ${t}$ :: s${reduced_shape('x', rank, 'dim')}$ integer :: j if(.not.present(mask)) then if(dim<${rank}$)then do j = 1, size(x,dim=${rank}$) #:if rank == 2 s${select_subarray(rank-1, [(rank-1, 'j')])}$ = stdlib_sum( x${select_subarray(rank, [(rank, 'j')])}$ ) #:else s${select_subarray(rank-1, [(rank-1, 'j')])}$ = stdlib_sum( x${select_subarray(rank, [(rank, 'j')])}$, dim=dim ) #:endif end do else do j = 1, size(x,dim=1) #:if rank == 2 s${select_subarray(rank-1, [(1, 'j')])}$ = stdlib_sum( x${select_subarray(rank, [(1, 'j')])}$ ) #:else s${select_subarray(rank-1, [(1, 'j')])}$ = stdlib_sum( x${select_subarray(rank, [(1, 'j')])}$, dim=${rank-1}$ ) #:endif end do end if else if(dim<${rank}$)then do j = 1, size(x,dim=${rank}$) #:if rank == 2 s${select_subarray(rank-1, [(rank-1, 'j')])}$ = stdlib_sum( x${select_subarray(rank, [(rank, 'j')])}$, mask=mask${select_subarray(rank, [(rank, 'j')])}$ ) #:else s${select_subarray(rank-1, [(rank-1, 'j')])}$ = stdlib_sum( x${select_subarray(rank, [(rank, 'j')])}$, dim=dim, mask=mask${select_subarray(rank, [(rank, 'j')])}$ ) #:endif end do else do j = 1, size(x,dim=1) #:if rank == 2 s${select_subarray(rank-1, [(1, 'j')])}$ = stdlib_sum( x${select_subarray(rank, [(1, 'j')])}$, mask=mask${select_subarray(rank, [(1, 'j')])}$ ) #:else s${select_subarray(rank-1, [(1, 'j')])}$ = stdlib_sum( x${select_subarray(rank, [(1, 'j')])}$, dim=${rank-1}$, mask=mask${select_subarray(rank, [(1, 'j')])}$ ) #:endif end do end if end if end function #:endfor #:endfor #:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES #:for rank in RANKS pure module function stdlib_sum_kahan_${rank}$d_${s}$( x , mask ) result( s ) ${t}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in), optional :: mask${ranksuffix(rank)}$ ${t}$ :: s if(.not.present(mask)) then s = sum_recast(x,size(x,kind=ilp)) else s = sum_recast_mask(x,mask,size(x,kind=ilp)) end if contains pure ${t}$ function sum_recast(b,n) integer(ilp), intent(in) :: n ${t}$, intent(in) :: b(n) sum_recast = stdlib_sum_kahan(b) end function pure ${t}$ function sum_recast_mask(b,m,n) integer(ilp), intent(in) :: n ${t}$, intent(in) :: b(n) logical, intent(in) :: m(n) sum_recast_mask = stdlib_sum_kahan(b,m) end function end function pure module function stdlib_sum_kahan_${rank}$d_dim_${s}$( x , dim, mask ) result( s ) ${t}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in):: dim logical, intent(in), optional :: mask${ranksuffix(rank)}$ ${t}$ :: s${reduced_shape('x', rank, 'dim')}$ integer :: j if(.not.present(mask)) then if(dim<${rank}$)then do j = 1, size(x,dim=${rank}$) #:if rank == 2 s${select_subarray(rank-1, [(rank-1, 'j')])}$ = stdlib_sum_kahan( x${select_subarray(rank, [(rank, 'j')])}$ ) #:else s${select_subarray(rank-1, [(rank-1, 'j')])}$ = stdlib_sum_kahan( x${select_subarray(rank, [(rank, 'j')])}$, dim=dim ) #:endif end do else do j = 1, size(x,dim=1) #:if rank == 2 s${select_subarray(rank-1, [(1, 'j')])}$ = stdlib_sum_kahan( x${select_subarray(rank, [(1, 'j')])}$ ) #:else s${select_subarray(rank-1, [(1, 'j')])}$ = stdlib_sum_kahan( x${select_subarray(rank, [(1, 'j')])}$, dim=${rank-1}$ ) #:endif end do end if else if(dim<${rank}$)then do j = 1, size(x,dim=${rank}$) #:if rank == 2 s${select_subarray(rank-1, [(rank-1, 'j')])}$ = stdlib_sum_kahan( x${select_subarray(rank, [(rank, 'j')])}$, mask=mask${select_subarray(rank, [(rank, 'j')])}$ ) #:else s${select_subarray(rank-1, [(rank-1, 'j')])}$ = stdlib_sum_kahan( x${select_subarray(rank, [(rank, 'j')])}$, dim=dim, mask=mask${select_subarray(rank, [(rank, 'j')])}$ ) #:endif end do else do j = 1, size(x,dim=1) #:if rank == 2 s${select_subarray(rank-1, [(1, 'j')])}$ = stdlib_sum_kahan( x${select_subarray(rank, [(1, 'j')])}$, mask=mask${select_subarray(rank, [(1, 'j')])}$ ) #:else s${select_subarray(rank-1, [(1, 'j')])}$ = stdlib_sum_kahan( x${select_subarray(rank, [(1, 'j')])}$, dim=${rank-1}$, mask=mask${select_subarray(rank, [(1, 'j')])}$ ) #:endif end do end if end if end function #:endfor #:endfor end submodule stdlib_intrinsics_sum fortran-lang-stdlib-0ede301/src/intrinsics/stdlib_intrinsics.fypp0000664000175000017500000002100215135654166025563 0ustar alastairalastair#:include "common.fypp" #:set I_KINDS_TYPES = list(zip(INT_KINDS, INT_TYPES, INT_KINDS)) #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) #:set RANKS = range(2, MAXRANK + 1) module stdlib_intrinsics !!Alternative implementations of some Fortran intrinsic functions offering either faster and/or more accurate evaluation. !! ([Specification](../page/specs/stdlib_intrinsics.html)) use stdlib_kinds use stdlib_linalg_state, only: linalg_state_type implicit none private interface stdlib_sum !! version: experimental !! !!### Summary !! Sum elements of rank N arrays. !! ([Specification](../page/specs/stdlib_intrinsics.html#stdlib_sum)) !! !!### Description !! !! This interface provides standard conforming call for sum of elements of any rank. !! The 1-D base implementation follows a chunked approach for optimizing performance and increasing accuracy. !! The `N-D` interfaces calls upon the `(N-1)-D` implementation. !! Supported data types include `real`, `complex` and `integer`. !! #:for k, t, s in I_KINDS_TYPES + R_KINDS_TYPES + C_KINDS_TYPES pure module function stdlib_sum_1d_${s}$(a) result(s) ${t}$, intent(in) :: a(:) ${t}$ :: s end function pure module function stdlib_sum_1d_${s}$_mask(a,mask) result(s) ${t}$, intent(in) :: a(:) logical, intent(in) :: mask(:) ${t}$ :: s end function #:for rank in RANKS pure module function stdlib_sum_${rank}$d_${s}$( x, mask ) result( s ) ${t}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in), optional :: mask${ranksuffix(rank)}$ ${t}$ :: s end function pure module function stdlib_sum_${rank}$d_dim_${s}$( x , dim, mask ) result( s ) ${t}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in):: dim logical, intent(in), optional :: mask${ranksuffix(rank)}$ ${t}$ :: s${reduced_shape('x', rank, 'dim')}$ end function #:endfor #:endfor end interface public :: stdlib_sum interface stdlib_sum_kahan !! version: experimental !! !!### Summary !! Sum elements of rank N arrays. !! ([Specification](../page/specs/stdlib_intrinsics.html#stdlib_sum_kahan)) !! !!### Description !! !! This interface provides standard conforming call for sum of elements of any rank. !! The 1-D base implementation follows a chunked approach combined with a kahan kernel for optimizing performance and increasing accuracy. !! The `N-D` interfaces calls upon the `(N-1)-D` implementation. !! Supported data types include `real` and `complex`. !! #:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES pure module function stdlib_sum_kahan_1d_${s}$(a) result(s) ${t}$, intent(in) :: a(:) ${t}$ :: s end function pure module function stdlib_sum_kahan_1d_${s}$_mask(a,mask) result(s) ${t}$, intent(in) :: a(:) logical, intent(in) :: mask(:) ${t}$ :: s end function #:for rank in RANKS pure module function stdlib_sum_kahan_${rank}$d_${s}$( x, mask ) result( s ) ${t}$, intent(in) :: x${ranksuffix(rank)}$ logical, intent(in), optional :: mask${ranksuffix(rank)}$ ${t}$ :: s end function pure module function stdlib_sum_kahan_${rank}$d_dim_${s}$( x , dim, mask ) result( s ) ${t}$, intent(in) :: x${ranksuffix(rank)}$ integer, intent(in):: dim logical, intent(in), optional :: mask${ranksuffix(rank)}$ ${t}$ :: s${reduced_shape('x', rank, 'dim')}$ end function #:endfor #:endfor end interface public :: stdlib_sum_kahan interface stdlib_dot_product !! version: experimental !! !!### Summary !! dot_product of rank 1 arrays. !! ([Specification](../page/specs/stdlib_intrinsics.html#stdlib_dot_product)) !! !!### Description !! !! compute the dot_product of rank 1 arrays. !! The 1-D base implementation follows a chunked approach for optimizing performance and increasing accuracy. !! Supported data types include `real`, `complex` and `integer`. !! #:for k, t, s in I_KINDS_TYPES + R_KINDS_TYPES + C_KINDS_TYPES pure module function stdlib_dot_product_${s}$(a,b) result(p) ${t}$, intent(in) :: a(:) ${t}$, intent(in) :: b(:) ${t}$ :: p end function #:endfor end interface public :: stdlib_dot_product interface stdlib_dot_product_kahan !! version: experimental !! !!### Summary !! dot_product of rank 1 arrays. !! ([Specification](../page/specs/stdlib_intrinsics.html#stdlib_dot_product_kahan)) !! !!### Description !! !! compute the dot_product of rank 1 arrays. !! The implementation follows a chunked approach combined with a kahan kernel for optimizing performance and increasing accuracy. !! Supported data types include `real` and `complex`. !! #:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES pure module function stdlib_dot_product_kahan_${s}$(a,b) result(p) ${t}$, intent(in) :: a(:) ${t}$, intent(in) :: b(:) ${t}$ :: p end function #:endfor end interface public :: stdlib_dot_product_kahan interface kahan_kernel #:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES module procedure :: kahan_kernel_${s}$ module procedure :: kahan_kernel_m_${s}$ #:endfor end interface public :: kahan_kernel interface stdlib_matmul !! version: experimental !! !!### Summary !! compute the matrix multiplication of more than two matrices with a single function call. !! ([Specification](../page/specs/stdlib_intrinsics.html#stdlib_matmul)) !! !!### Description !! !! matrix multiply more than two matrices with a single function call !! the multiplication with the optimal parenthesization for efficiency of computation is done automatically !! Supported data types are `real` and `complex`. !! !! Note: The matrices must be of compatible shapes to be multiplied #:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES pure module function stdlib_matmul_pure_${s}$ (m1, m2, m3, m4, m5) result(r) ${t}$, intent(in) :: m1(:,:), m2(:,:) ${t}$, intent(in), optional :: m3(:,:), m4(:,:), m5(:,:) ${t}$, allocatable :: r(:,:) end function stdlib_matmul_pure_${s}$ module function stdlib_matmul_${s}$ (m1, m2, m3, m4, m5, err) result(r) ${t}$, intent(in) :: m1(:,:), m2(:,:) ${t}$, intent(in), optional :: m3(:,:), m4(:,:), m5(:,:) type(linalg_state_type), intent(out) :: err ${t}$, allocatable :: r(:,:) end function stdlib_matmul_${s}$ #:endfor end interface stdlib_matmul public :: stdlib_matmul ! internal interface interface stdlib_matmul_sub #:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES pure module subroutine stdlib_matmul_sub_${s}$ (res, m1, m2, m3, m4, m5, err) ${t}$, intent(out), allocatable :: res(:,:) ${t}$, intent(in) :: m1(:,:), m2(:,:) ${t}$, intent(in), optional :: m3(:,:), m4(:,:), m5(:,:) type(linalg_state_type), intent(out), optional :: err end subroutine stdlib_matmul_sub_${s}$ #:endfor end interface stdlib_matmul_sub contains #:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES elemental subroutine kahan_kernel_${s}$(a,s,c) ${t}$, intent(in) :: a ${t}$, intent(inout) :: s ${t}$, intent(inout) :: c ${t}$ :: t, y y = a - c t = s + y c = (t - s) - y s = t end subroutine elemental subroutine kahan_kernel_m_${s}$(a,s,c,m) ${t}$, intent(in) :: a ${t}$, intent(inout) :: s ${t}$, intent(inout) :: c logical, intent(in) :: m ${t}$ :: t, y y = a - c t = s + y c = (t - s) - y s = merge( s , t , m ) end subroutine #:endfor end module stdlib_intrinsics fortran-lang-stdlib-0ede301/src/intrinsics/stdlib_intrinsics_matmul.fypp0000664000175000017500000002422215135654166027151 0ustar alastairalastair#:include "common.fypp" #:set I_KINDS_TYPES = list(zip(INT_KINDS, INT_TYPES, INT_KINDS)) #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) submodule (stdlib_intrinsics) stdlib_intrinsics_matmul use stdlib_linalg_blas, only: gemm use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_VALUE_ERROR, LINALG_INTERNAL_ERROR use stdlib_constants implicit none character(len=*), parameter :: this = "stdlib_matmul" contains ! Algorithm for the optimal parenthesization of matrices ! Reference: Cormen, "Introduction to Algorithms", 4ed, ch-14, section-2 ! Internal use only! pure function matmul_chain_order(p) result(s) integer, intent(in) :: p(:) integer :: s(1:size(p) - 2, 2:size(p) - 1), m(1:size(p) - 1, 1:size(p) - 1) integer :: n, l, i, j, k, q n = size(p) - 1 m(:,:) = 0 s(:,:) = 0 do l = 2, n do i = 1, n - l + 1 j = i + l - 1 m(i,j) = huge(1) do k = i, j - 1 q = m(i,k) + m(k+1,j) + p(i)*p(k+1)*p(j+1) if (q < m(i, j)) then m(i,j) = q s(i,j) = k end if end do end do end do end function matmul_chain_order #:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES pure function matmul_chain_mult_${s}$_3 (m1, m2, m3, start, s, p) result(r) ${t}$, intent(in) :: m1(:,:), m2(:,:), m3(:,:) integer, intent(in) :: start, s(:,2:), p(:) ${t}$, allocatable :: r(:,:), temp(:,:) integer :: ord, m, n, k ord = s(start, start + 2) allocate(r(p(start), p(start + 3))) if (ord == start) then ! m1*(m2*m3) m = p(start + 1) n = p(start + 3) k = p(start + 2) allocate(temp(m,n)) call gemm('N', 'N', m, n, k, one_${s}$, m2, m, m3, k, zero_${s}$, temp, m) m = p(start) n = p(start + 3) k = p(start + 1) call gemm('N', 'N', m, n, k, one_${s}$, m1, m, temp, k, zero_${s}$, r, m) else if (ord == start + 1) then ! (m1*m2)*m3 m = p(start) n = p(start + 2) k = p(start + 1) allocate(temp(m, n)) call gemm('N', 'N', m, n, k, one_${s}$, m1, m, m2, k, zero_${s}$, temp, m) m = p(start) n = p(start + 3) k = p(start + 1) call gemm('N', 'N', m, n, k, one_${s}$, temp, m, m3, k, zero_${s}$, r, m) else ! our internal functions are incorrent, abort error stop this//": error: unexpected s(i,j)" end if end function matmul_chain_mult_${s}$_3 pure function matmul_chain_mult_${s}$_4 (m1, m2, m3, m4, start, s, p) result(r) ${t}$, intent(in) :: m1(:,:), m2(:,:), m3(:,:), m4(:,:) integer, intent(in) :: start, s(:,2:), p(:) ${t}$, allocatable :: r(:,:), temp(:,:), temp1(:,:) integer :: ord, m, n, k ord = s(start, start + 3) allocate(r(p(start), p(start + 4))) if (ord == start) then ! m1*(m2*m3*m4) temp = matmul_chain_mult_${s}$_3(m2, m3, m4, start + 1, s, p) m = p(start) n = p(start + 4) k = p(start + 1) call gemm('N', 'N', m, n, k, one_${s}$, m1, m, temp, k, zero_${s}$, r, m) else if (ord == start + 1) then ! (m1*m2)*(m3*m4) m = p(start) n = p(start + 2) k = p(start + 1) allocate(temp(m,n)) call gemm('N', 'N', m, n, k, one_${s}$, m1, m, m2, k, zero_${s}$, temp, m) m = p(start + 2) n = p(start + 4) k = p(start + 3) allocate(temp1(m,n)) call gemm('N', 'N', m, n, k, one_${s}$, m3, m, m4, k, zero_${s}$, temp1, m) m = p(start) n = p(start + 4) k = p(start + 2) call gemm('N', 'N', m, n, k, one_${s}$, temp, m, temp1, k, zero_${s}$, r, m) else if (ord == start + 2) then ! (m1*m2*m3)*m4 temp = matmul_chain_mult_${s}$_3(m1, m2, m3, start, s, p) m = p(start) n = p(start + 4) k = p(start + 3) call gemm('N', 'N', m, n, k, one_${s}$, temp, m, m4, k, zero_${s}$, r, m) else ! our internal functions are incorrent, abort error stop this//": error: unexpected s(i,j)" end if end function matmul_chain_mult_${s}$_4 pure module subroutine stdlib_matmul_sub_${s}$ (res, m1, m2, m3, m4, m5, err) ${t}$, intent(out), allocatable :: res(:,:) ${t}$, intent(in) :: m1(:,:), m2(:,:) ${t}$, intent(in), optional :: m3(:,:), m4(:,:), m5(:,:) type(linalg_state_type), intent(out), optional :: err ${t}$, allocatable :: temp(:,:), temp1(:,:) integer :: p(6), num_present, m, n, k integer, allocatable :: s(:,:) type(linalg_state_type) :: err0 p(1) = size(m1, 1) p(2) = size(m2, 1) p(3) = size(m2, 2) if (size(m1, 2) /= p(2)) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, 'matrices m1=',shape(m1),& ', m2=',shape(m2),'have incompatible sizes') call linalg_error_handling(err0, err) allocate(res(0, 0)) return end if num_present = 2 if (present(m3)) then if (size(m3, 1) /= p(3)) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, 'matrices m2=',shape(m2), & ', m3=',shape(m3),'have incompatible sizes') call linalg_error_handling(err0, err) allocate(res(0, 0)) return end if p(3) = size(m3, 1) p(4) = size(m3, 2) num_present = num_present + 1 end if if (present(m4)) then if (size(m4, 1) /= p(4)) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, 'matrices m3=',shape(m3), & ', m4=',shape(m4),' have incompatible sizes') call linalg_error_handling(err0, err) allocate(res(0, 0)) return end if p(4) = size(m4, 1) p(5) = size(m4, 2) num_present = num_present + 1 end if if (present(m5)) then if (size(m5, 1) /= p(5)) then err0 = linalg_state_type(this, LINALG_VALUE_ERROR, 'matrices m4=',shape(m4), & ', m5=',shape(m5),' have incompatible sizes') call linalg_error_handling(err0, err) allocate(res(0, 0)) return end if p(5) = size(m5, 1) p(6) = size(m5, 2) num_present = num_present + 1 end if allocate(res(p(1), p(num_present + 1))) if (num_present == 2) then m = p(1) n = p(3) k = p(2) call gemm('N', 'N', m, n, k, one_${s}$, m1, m, m2, k, zero_${s}$, res, m) return end if ! Now num_present >= 3 allocate(s(1:num_present - 1, 2:num_present)) s = matmul_chain_order(p(1: num_present + 1)) if (num_present == 3) then res = matmul_chain_mult_${s}$_3(m1, m2, m3, 1, s, p(1:4)) return else if (num_present == 4) then res = matmul_chain_mult_${s}$_4(m1, m2, m3, m4, 1, s, p(1:5)) return end if ! Now num_present is 5 select case (s(1, 5)) case (1) ! m1*(m2*m3*m4*m5) temp = matmul_chain_mult_${s}$_4(m2, m3, m4, m5, 2, s, p) m = p(1) n = p(6) k = p(2) call gemm('N', 'N', m, n, k, one_${s}$, m1, m, temp, k, zero_${s}$, res, m) case (2) ! (m1*m2)*(m3*m4*m5) m = p(1) n = p(3) k = p(2) allocate(temp(m,n)) call gemm('N', 'N', m, n, k, one_${s}$, m1, m, m2, k, zero_${s}$, temp, m) temp1 = matmul_chain_mult_${s}$_3(m3, m4, m5, 3, s, p) k = n n = p(6) call gemm('N', 'N', m, n, k, one_${s}$, temp, m, temp1, k, zero_${s}$, res, m) case (3) ! (m1*m2*m3)*(m4*m5) temp = matmul_chain_mult_${s}$_3(m1, m2, m3, 3, s, p) m = p(4) n = p(6) k = p(5) allocate(temp1(m,n)) call gemm('N', 'N', m, n, k, one_${s}$, m4, m, m5, k, zero_${s}$, temp1, m) k = m m = p(1) call gemm('N', 'N', m, n, k, one_${s}$, temp, m, temp1, k, zero_${s}$, res, m) case (4) ! (m1*m2*m3*m4)*m5 temp = matmul_chain_mult_${s}$_4(m1, m2, m3, m4, 1, s, p) m = p(1) n = p(6) k = p(5) call gemm('N', 'N', m, n, k, one_${s}$, temp, m, m5, k, zero_${s}$, res, m) case default err0 = linalg_state_type(this,LINALG_INTERNAL_ERROR,"internal error: unexpected s(i,j)") call linalg_error_handling(err0,err) end select end subroutine stdlib_matmul_sub_${s}$ pure module function stdlib_matmul_pure_${s}$ (m1, m2, m3, m4, m5) result(r) ${t}$, intent(in) :: m1(:,:), m2(:,:) ${t}$, intent(in), optional :: m3(:,:), m4(:,:), m5(:,:) ${t}$, allocatable :: r(:,:) call stdlib_matmul_sub(r, m1, m2, m3, m4, m5) end function stdlib_matmul_pure_${s}$ module function stdlib_matmul_${s}$ (m1, m2, m3, m4, m5, err) result(r) ${t}$, intent(in) :: m1(:,:), m2(:,:) ${t}$, intent(in), optional :: m3(:,:), m4(:,:), m5(:,:) type(linalg_state_type), intent(out) :: err ${t}$, allocatable :: r(:,:) call stdlib_matmul_sub(r, m1, m2, m3, m4, m5, err=err) end function stdlib_matmul_${s}$ #:endfor end submodule stdlib_intrinsics_matmul fortran-lang-stdlib-0ede301/src/bitsets/0000775000175000017500000000000015135654166020432 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/bitsets/CMakeLists.txt0000664000175000017500000000037515135654166023177 0ustar alastairalastairset(bitsets_fppFiles stdlib_bitsets.fypp stdlib_bitsets_64.fypp stdlib_bitsets_large.fypp ) configure_stdlib_target(${PROJECT_NAME}_bitsets "" bitsets_fppFiles "") target_link_libraries(${PROJECT_NAME}_bitsets PUBLIC ${PROJECT_NAME}_core) fortran-lang-stdlib-0ede301/src/bitsets/stdlib_bitsets_large.fypp0000664000175000017500000013254415135654166025533 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_bitsets) stdlib_bitsets_large implicit none contains elemental module function all_large( self ) result(all) ! Returns .TRUE. if all bits in SELF are 1, .FALSE. otherwise. logical :: all class(bitset_large), intent(in) :: self integer(bits_kind) :: block, full_blocks, pos all = .true. full_blocks = bits(self)/block_size do block = 1_bits_kind, full_blocks if ( self % blocks(block) /= -1_block_kind ) then all = .false. return end if end do if ( full_blocks == size(self % blocks) ) return do pos=0_bits_kind, modulo( bits(self), block_size )-1 if ( .not. btest(self % blocks(full_blocks+1), pos) ) then all = .false. return end if end do end function all_large elemental module subroutine and_large(set1, set2) ! ! Sets the bits in SET1 to the bitwise AND of the original bits in SET1 ! and SET2. It is required that SET1 have the same number of bits as ! SET2 otherwise the result is undefined. ! type(bitset_large), intent(inout) :: set1 type(bitset_large), intent(in) :: set2 integer(bits_kind) :: block_ do block_ = 1_bits_kind, size(set1 % blocks, kind=bits_kind) set1 % blocks(block_) = iand( set1 % blocks(block_), & set2 % blocks(block_) ) end do end subroutine and_large elemental module subroutine and_not_large(set1, set2) ! ! Sets the bits in SET1 to the bitwise and of the original bits in SET1 ! with the bitwise negation of SET2. SET1 and SET2 must have the same ! number of bits otherwise the result is undefined. ! type(bitset_large), intent(inout) :: set1 type(bitset_large), intent(in) :: set2 integer(bits_kind) :: block_ do block_ = 1_bits_kind, size( set1 % blocks, kind=bits_kind ) set1 % blocks(block_) = & iand( set1 % blocks(block_), not( set2 % blocks(block_) ) ) end do end subroutine and_not_large elemental module function any_large(self) result(any) ! Returns .TRUE. if any bit in SELF is 1, .FALSE. otherwise. logical :: any class(bitset_large), intent(in) :: self integer(bits_kind) :: block_ do block_ = 1_bits_kind, size(self % blocks, kind=bits_kind) if ( self % blocks(block_) /= 0 ) then any = .true. return end if end do any = .false. end function any_large #:for k1 in INT_KINDS pure module subroutine assign_log${k1}$_large( self, logical_vector ) ! Used to define assignment from an array of type logical for bitset_large type(bitset_large), intent(out) :: self logical(${k1}$), intent(in) :: logical_vector(:) integer(bits_kind) :: blocks integer(bits_kind) :: log_size integer(bits_kind) :: index log_size = size( logical_vector, kind=bits_kind ) self % num_bits = log_size if ( log_size == 0 ) then blocks = 0 else blocks = (log_size-1)/block_size + 1 end if allocate( self % blocks( blocks ) ) self % blocks(:) = 0 do index=0_bits_kind, log_size-1 if ( logical_vector(index+1) ) then call self % set( index ) end if end do end subroutine assign_log${k1}$_large pure module subroutine log${k1}$_assign_large( logical_vector, set ) ! Used to define assignment to an array of type logical for bitset_large logical(${k1}$), intent(out), allocatable :: logical_vector(:) type(bitset_large), intent(in) :: set integer(bits_kind) :: index allocate( logical_vector( set % num_bits ) ) do index=0_bits_kind, set % num_bits-1 if ( set % value( index ) == 1 ) then logical_vector(index+1) = .true. else logical_vector(index+1) = .false. end if end do end subroutine log${k1}$_assign_large #:endfor elemental module function bit_count_large(self) result(bit_count) ! Returns the number of non-zero bits in SELF. integer(bits_kind) :: bit_count class(bitset_large), intent(in) :: self integer(bits_kind) :: nblocks, pos nblocks = size( self % blocks, kind=bits_kind ) bit_count = sum( popcnt( self % blocks(1:nblocks-1) ) ) do pos = 0_bits_kind, self % num_bits - (nblocks-1)*block_size - 1 if ( btest( self % blocks(nblocks), pos ) ) bit_count = bit_count + 1 end do end function bit_count_large elemental module subroutine clear_bit_large(self, pos) ! ! Sets to zero the POS position in SELF. If POS is less than zero or ! greater than BITS(SELF)-1 it is ignored. ! class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: pos integer :: clear_block, block_bit if ( pos < 0 .OR. (pos > self % num_bits-1) ) return clear_block = pos / block_size + 1 block_bit = pos - (clear_block - 1) * block_size self % blocks(clear_block) = & ibclr( self % blocks(clear_block), block_bit ) end subroutine clear_bit_large pure module subroutine clear_range_large(self, start_pos, stop_pos) ! ! Sets to zero all bits from the START_POS to STOP_POS positions in SELF. ! If STOP_POS < START_POS then no bits are modified. Positions outside ! the range 0 to BITS(SELF)-1 are ignored. ! class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos integer(bits_kind) :: bit, block_, first_block, last_block, & true_first, true_last true_first = max( 0_bits_kind, start_pos ) true_last = min( self % num_bits-1, stop_pos ) if ( true_last < true_first ) return first_block = true_first / block_size + 1 last_block = true_last / block_size + 1 if ( first_block == last_block ) then ! TRUE_FIRST and TRUE_LAST are in the same block call mvbits( all_zeros, & true_first - (first_block-1)*block_size, & true_last - true_first + 1, & self % blocks(first_block), & true_first - (first_block-1)*block_size ) return end if ! Do "partial" black containing FIRST bit = true_first - (first_block-1)*block_size call mvbits( all_zeros, & bit, & block_size - bit, & self % blocks(first_block), & bit ) ! Do "partial" black containing LAST bit = true_last - (last_block-1)*block_size call mvbits( all_zeros, & 0, & bit+1, & self % blocks(last_block), & 0 ) ! Do intermediate blocks do block_ = first_block+1, last_block-1 self % blocks(block_) = all_zeros end do end subroutine clear_range_large elemental module function eqv_large(set1, set2) result(eqv) ! ! Returns .TRUE. if all bits in SET1 and SET2 have the same value, ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: eqv type(bitset_large), intent(in) :: set1, set2 integer(bits_kind) :: block, common_blocks eqv = .false. common_blocks = size(set1 % blocks, kind=bits_kind) do block = 1, common_blocks if ( set1 % blocks(block) /= set2 % blocks(block) ) return end do eqv = .true. end function eqv_large module subroutine extract_large(new, old, start_pos, stop_pos, status) ! Creates a new bitset, NEW, from a range, START_POS to STOP_POS, in bitset ! OLD. If START_POS is greater than STOP_POS the new bitset is empty. ! If START_POS is less than zero or STOP_POS is greater than BITS(OLD)-1 ! then if STATUS is present it has the value INDEX_INVALID_ERROR, ! otherwise processing stops with an informative message. type(bitset_large), intent(out) :: new type(bitset_large), intent(in) :: old integer(bits_kind), intent(in) :: start_pos, stop_pos integer, intent(out), optional :: status integer(bits_kind) :: bits, blocks, ex_block, i, j, k, old_block character(*), parameter :: procedure = 'EXTRACT' if ( start_pos < 0 ) then call error_handler( 'had a START_POS less than 0.', & index_invalid_error, status, & module_name, procedure ) return end if if ( stop_pos >= old % num_bits ) then call error_handler( 'had a STOP_POS greater than BITS(OLD)-1.', & index_invalid_error, status, & module_name, procedure ) return end if bits = stop_pos - start_pos + 1 if ( bits <= 0 ) then new % num_bits = 0 allocate( new % blocks(0) ) return end if blocks = ((bits-1) / block_size) + 1 new % num_bits = bits allocate( new % blocks(blocks) ) new % blocks(:) = 0 do i=0_bits_kind, bits-1 ex_block = i / block_size + 1 j = i - (ex_block-1) * block_size old_block = (start_pos + i) / block_size + 1 k = (start_pos + i) - (old_block-1) * block_size if ( btest( old % blocks(old_block), k ) ) then new % blocks(ex_block) = ibset(new % blocks(ex_block), j) end if end do if ( present(status) ) status = success end subroutine extract_large elemental module subroutine flip_bit_large(self, pos) ! ! Flips the value at the POS position in SELF, provided the position is ! valid. If POS is less than 0 or greater than BITS(SELF)-1, no value is ! changed. ! class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: pos integer(bits_kind) :: flip_block, block_bit if ( pos < 0 .OR. pos > self % num_bits-1 ) return flip_block = pos / block_size + 1 block_bit = pos - (flip_block - 1) * block_size if ( btest( self % blocks(flip_block), block_bit ) ) then self % blocks(flip_block) = ibclr( self % blocks(flip_block), & block_bit ) else self % blocks(flip_block) = ibset( self % blocks(flip_block), & block_bit ) end if end subroutine flip_bit_large pure module subroutine flip_range_large(self, start_pos, stop_pos) ! ! Flips all valid bits from the START_POS to the STOP_POS positions in ! SELF. If STOP_POS < START_POS no bits are flipped. Positions less than ! 0 or greater than BITS(SELF)-1 are ignored. ! class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos integer(bits_kind) :: bit, block_, end_bit, first_block, last_block, & start_bit start_bit = max( 0_bits_kind, start_pos ) end_bit = min( stop_pos , self % num_bits-1 ) if ( end_bit < start_bit ) return first_block = start_bit / block_size + 1 last_block = end_bit / block_size + 1 if (first_block == last_block) then ! FIRST and LAST are in the same block call mvbits( not(self % blocks(first_block)), & start_bit - (first_block-1)*block_size, & end_bit - start_bit + 1, & self % blocks(first_block), & start_bit - (first_block-1)*block_size ) return end if ! Do "partial" black containing FIRST bit = start_bit - (first_block-1)*block_size call mvbits( not(self % blocks(first_block) ), & bit, & block_size - bit, & self % blocks(first_block), & bit ) ! Do "partial" black containing LAST bit = end_bit - (last_block-1)*block_size call mvbits( not( self % blocks(last_block) ), & 0, & bit+1, & self % blocks(last_block), & 0 ) ! Do remaining blocks do block_ = first_block+1, last_block-1 self % blocks(block_) = not( self % blocks(block_) ) end do end subroutine flip_range_large module subroutine from_string_large(self, string, status) ! Initializes the bitset `self` treating `string` as a binary literal ! `status` may have the values: ! `success` - if no problems were found, ! `alloc_fault` - if allocation of the bitset failed ! `char_string_too_large_error` - if `string` was too large, or ! `char_string_invalid_error` - if string had an invalid character. class(bitset_large), intent(out) :: self character(*), intent(in) :: string integer, intent(out), optional :: status character(*), parameter :: procedure = 'FROM_STRING' integer(int64) :: bit integer(int64) :: bits character(1) :: char bits = len(string, kind=int64) if ( bits > huge(0_bits_kind) ) then call error_handler( 'STRING was too long for a ' // & 'BITSET_LARGE SELF.', & char_string_too_large_error, status, & module_name, procedure ) return end if call init_zero_large( self, int(bits, kind=bits_kind), status ) if ( present(status) ) then if ( status /= success ) return end if do bit = 1_bits_kind, bits char = string(bit:bit) if ( char == '0' ) then call self % clear( int(bits-bit, kind=bits_kind) ) else if ( char == '1' ) then call self % set( int(bits-bit, kind=bits_kind) ) else call error_handler( 'STRING had a character other than ' // & '0 or 1.', & char_string_invalid_error, status, & module_name, procedure ) return end if end do if ( present(status) ) status = success end subroutine from_string_large elemental module function ge_large(set1, set2) result(ge) ! ! Returns .TRUE. if the bits in SET1 and SET2 are the same or the ! highest order different bit is set to 1 in SET1 and to 0 in set2. ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: ge type(bitset_large), intent(in) :: set1, set2 integer(bits_kind) :: block_ do block_ = size(set1 % blocks, kind=bits_kind), 1_bits_kind, -1 if ( set1 % blocks(block_) == set2 % blocks(block_) ) then cycle else if ( bgt(set1 % blocks(block_), set2 % blocks(block_) ) ) then ge = .true. return else ge = .false. return end if end do ge = .true. end function ge_large elemental module function gt_large(set1, set2) result(gt) ! ! Returns .TRUE. if the bits in SET1 and SET2 differ and the ! highest order different bit is set to 1 in SET1 and to 0 in set2. ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: gt type(bitset_large), intent(in) :: set1, set2 integer(bits_kind) :: block_ do block_ = size(set1 % blocks, kind=bits_kind), 1_bits_kind, -1 if ( set1 % blocks(block_) == set2 % blocks(block_) ) then cycle else if ( bgt( set1 % blocks(block_), & set2 % blocks(block_) ) ) then gt = .true. return else gt = .false. return end if end do gt = .false. end function gt_large module subroutine init_zero_large(self, bits, status) ! ! Creates the bitset, `self`, of size `bits`, with all bits initialized to ! zero. `bits` must be non-negative. If an error occurs and `status` is ! absent then processing stops with an informative stop code. `status` ! will have one of the values; ! * `success` - if no problems were found, ! * `array_size_invalid_error` - if `bits` is either negative or larger ! than 64 with `self` of class `bitset_64`, or ! * `alloc_fault` - if memory allocation failed ! class(bitset_large), intent(out) :: self integer(bits_kind), intent(in) :: bits integer, intent(out), optional :: status character(len=120) :: message character(*), parameter :: procedure = "INIT" integer :: blocks, ierr message = '' if ( bits < 0 ) then call error_handler( 'BITS had a negative value.', & array_size_invalid_error, status, & module_name, procedure ) return end if if (bits == 0) then self % num_bits = 0 allocate( self % blocks(0), stat=ierr, errmsg=message ) if (ierr /= 0) go to 998 return else blocks = ((bits-1) / block_size) + 1 end if self % num_bits = bits allocate( self % blocks(blocks), stat=ierr, errmsg=message ) if (ierr /= 0) go to 998 self % blocks(:) = all_zeros if ( present(status) ) status = success return 998 call error_handler( 'Allocation failure for SELF.', & alloc_fault, status, & module_name, procedure ) end subroutine init_zero_large module subroutine input_large(self, unit, status) ! ! Reads the components of the bitset, `self`, from the unformatted I/O ! unit, `unit`, assuming that the components were written using `output`. ! If an error occurs and `status` is absent then processing stops with ! an informative stop code. `status` has one of the values: ! * `success` - if no problem was found ! * `alloc_fault` - if it failed during allocation of memory for `self`, or ! * `array_size_invalid_error` if the `bits(self)` in `unit` is negative ! or greater than 64 for a `bitset_64` input. ! * `read_failure` - if it failed during the reads from `unit` ! class(bitset_large), intent(out) :: self integer, intent(in) :: unit integer, intent(out), optional :: status integer(bits_kind) :: bits integer :: ierr character(len=120) :: message character(*), parameter :: procedure = 'INPUT' integer :: stat read(unit, iostat=ierr, iomsg=message) bits if (ierr /= 0) then call error_handler( 'Failure on a READ statement for UNIT.', & read_failure, status, module_name, procedure ) return end if if ( bits < 0 ) then call error_handler( 'BITS in UNIT had a negative value.', & array_size_invalid_error, status, & module_name, procedure ) return end if call self % init(bits, stat) if (stat /= success) then call error_handler( 'Allocation failure for SELF.', & alloc_fault, status, module_name, procedure ) return end if if (bits < 1) return read(unit, iostat=ierr, iomsg=message) self % blocks(:) if (ierr /= 0) then call error_handler( 'Failure on a READ statement for UNIT.', & read_failure, status, module_name, procedure ) return end if if ( present(status) ) status = success end subroutine input_large elemental module function le_large(set1, set2) result(le) ! ! Returns .TRUE. if the bits in SET1 and SET2 are the same or the ! highest order different bit is set to 0 in SET1 and to 1 in set2. ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: le type(bitset_large), intent(in) :: set1, set2 integer(bits_kind) :: block_ do block_ = size(set1 % blocks, kind=bits_kind), 1_bits_kind, -1 if ( set1 % blocks(block_) == set2 % blocks(block_) ) then cycle else if ( blt( set1 % blocks(block_), & set2 % blocks(block_) ) ) then le = .true. return else le = .false. return end if end do le = .true. end function le_large elemental module function lt_large(set1, set2) result(lt) ! ! Returns .TRUE. if the bits in SET1 and SET2 differ and the ! highest order different bit is set to 0 in SET1 and to 1 in set2. ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: lt type(bitset_large), intent(in) :: set1, set2 integer(bits_kind) :: block_ do block_ = size(set1 % blocks, kind=bits_kind), 1_bits_kind, -1 if ( set1 % blocks(block_) == set2 % blocks(block_) ) then cycle else if ( blt( set1 % blocks(block_), & set2 % blocks(block_) ) ) then lt = .true. return else lt = .false. return end if end do lt = .false. end function lt_large elemental module function neqv_large(set1, set2) result(neqv) ! ! Returns .TRUE. if any bits in SET1 and SET2 differ in value, ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: neqv type(bitset_large), intent(in) :: set1, set2 integer(bits_kind) :: block_ neqv = .true. do block_ = 1_bits_kind, size(set1 % blocks, kind=bits_kind) if ( set1 % blocks(block_) /= set2 % blocks(block_) ) return end do neqv = .false. end function neqv_large elemental module function none_large(self) result(none) ! ! Returns .TRUE. if none of the bits in SELF have the value 1. ! logical :: none class(bitset_large), intent(in) :: self integer(bits_kind) :: block none = .true. do block = 1_bits_kind, size(self % blocks, kind=bits_kind) if (self % blocks(block) /= 0) then none = .false. return end if end do end function none_large elemental module subroutine not_large(self) ! ! Sets the bits in SELF to their logical complement ! class(bitset_large), intent(inout) :: self integer(bits_kind) :: bit, full_blocks, block integer :: remaining_bits if ( self % num_bits == 0 ) return full_blocks = self % num_bits / block_size do block = 1_bits_kind, full_blocks self % blocks(block) = not( self % blocks(block) ) end do remaining_bits = self % num_bits - full_blocks * block_size do bit=0, remaining_bits - 1 if ( btest( self % blocks( block ), bit ) ) then self % blocks( block ) = ibclr( self % blocks(block), bit ) else self % blocks( block ) = ibset( self % blocks(block), bit ) end if end do end subroutine not_large elemental module subroutine or_large(set1, set2) ! ! Sets the bits in SET1 to the bitwise OR of the original bits in SET1 ! and SET2. SET1 and SET2 must have the same number of bits otherwise ! the result is undefined. ! type(bitset_large), intent(inout) :: set1 type(bitset_large), intent(in) :: set2 integer(bits_kind) :: block_ do block_ = 1, size( set1 % blocks, kind=bits_kind ) set1 % blocks(block_) = ior( set1 % blocks(block_), & set2 % blocks(block_) ) end do end subroutine or_large module subroutine output_large(self, unit, status) ! ! Writes the components of the bitset, SELF, to the unformatted I/O ! unit, UNIT, in a unformatted sequence compatible with INPUT. If ! STATUS is absent an error results in an error stop with an ! informative stop code. If STATUS is present it has the default ! value of SUCCESS, or the value WRITE_FAILURE if the write failed. ! class(bitset_large), intent(in) :: self integer, intent(in) :: unit integer, intent(out), optional :: status integer :: ierr character(len=120) :: message character(*), parameter :: procedure = "OUTPUT" write(unit, iostat=ierr, iomsg=message) self % num_bits if (ierr /= 0) go to 999 if (self % num_bits < 1) return write(unit, iostat=ierr, iomsg=message) self % blocks(:) if (ierr /= 0) go to 999 return 999 call error_handler( 'Failure on a WRITE statement for UNIT.', & write_failure, status, module_name, procedure ) end subroutine output_large module subroutine read_bitset_string_large(self, string, status) ! ! Uses the bitset literal in the default character `string`, to define ! the bitset, `self`. The literal may be preceded by an an arbitrary ! sequence of blank characters. If `status` is absent an error results ! in an error stop with an informative stop code. If `status` ! is present it has one of the values ! * `success` - if no problems occurred, ! * `alloc_fault` - if allocation of memory for SELF failed, ! * `array_size_invalid_error - if `bits(self)` in `string` is greater ! than 64 for a `bitset_64`, ! * `char_string_invalid_error` - if the bitset literal has an invalid ! character, ! * `char_string_too_small_error - if the string ends before all the bits ! are read. ! * `integer_overflow_error` - if the bitset literal has a `bits(self)` ! value too large to be represented, ! class(bitset_large), intent(out) :: self character(len=*), intent(in) :: string integer, intent(out), optional :: status integer(bits_kind) :: bit, bits integer(bits_kind) :: digits, pos character(*), parameter :: procedure = "READ_BITSET" integer :: stat pos = 1 find_start: do pos=1_bits_kind, len(string, kind=bits_kind) if ( string(pos:pos) /= ' ' ) exit end do find_start if ( pos > len(string) - 8 ) go to 999 if ( string(pos:pos) /= 's' .AND. string(pos:pos) /= 'S' ) go to 999 pos = pos + 1 bits = 0 digits = 0 do select case( iachar( string(pos:pos) ) ) case(ia0:ia9) digits = digits + 1 if ( digits == max_digits .AND. bits > overflow_bits ) go to 996 if ( digits > max_digits ) go to 996 bits = bits*10 + iachar( string(pos:pos) ) - ia0 if ( bits < 0 ) go to 996 case(iachar('b'), iachar('B')) exit case default call error_handler( 'There was an invalid character ' // & 'in STRING', & char_string_invalid_error, status, & module_name, procedure ) return end select pos = pos + 1 end do if ( bits + pos > len(string) ) then call error_handler( 'STRING was too small for the number of ' // & 'bits specified by STRING.', & char_string_too_small_error, status, & module_name, procedure ) return end if call self % init( bits, stat ) if (stat /= success) then call error_handler( 'There was an allocation fault for SELF.', & alloc_fault, status, module_name, procedure ) return end if pos = pos + 1 bit = bits - 1 do if ( string(pos:pos) == '0' ) then call self % clear( bit ) else if ( string(pos:pos) == '1' ) then call self % set( bit ) else go to 999 end if pos = pos + 1 bit = bit - 1 if ( bit < 0 ) exit end do if ( present(status) ) status = success return 996 call error_handler( 'There was an integer overflow in reading' // & 'size of bitset literal from UNIT', & integer_overflow_error, status, & module_name, procedure ) return 999 call error_handler( 'There was an invalid character in STRING', & char_string_invalid_error, status, & module_name, procedure ) end subroutine read_bitset_string_large module subroutine read_bitset_unit_large(self, unit, advance, status) ! ! Uses the bitset literal at the current position in the formatted ! file with I/O unit, `unit`, to define the bitset, `self`. The literal ! may be preceded by an arbitrary sequence of blank characters. ! If `advance` is present it must be either 'YES' or 'NO'. If absent ! it has the default value of 'YES' to determine whether advancing ! I/O occurs. If `status` is absent an error results in an error stop ! with an informative stop code. If `status` is present it has one of ! the values: ! * `success` - if no problem occurred, ! * `alloc_fault` - if allocation of `self` failed, ! * `array_size_invalid_error` - if `bits(self)` in the bitset literal ! is greater than 64 for a `bitset_64`. ! * `char_string_invalid_error` - if the read of the bitset literal found ! an invalid character, ! * `eof_failure` - if a `read` statement reaches an end-of-file before ! completing the read of the bitset literal, ! * `integer_overflow_error` - if the bitset literal has a `bits(self)` ! value too large to be represented, ! * `read_failure` - if a `read` statement fails, ! class(bitset_large), intent(out) :: self integer, intent(in) :: unit character(*), intent(in), optional :: advance integer, intent(out), optional :: status integer(bits_kind) :: bit, bits, digits integer :: ierr character(len=128) :: message character(*), parameter :: procedure = "READ_BITSET" character(len=1) :: char do read( unit, & advance='NO', & FMT='(A1)', & err=997, & end=998, & iostat=ierr, & iomsg=message ) char select case( char ) case( ' ' ) cycle case( 's', 'S' ) exit case default go to 999 end select end do bits = 0 digits = 0 do read( unit, & advance='NO', & FMT='(A1)', & err=997, & end=998, & iostat=ierr, & iomsg=message ) char if ( char == 'b' .or. char == 'B' ) exit select case( char ) case( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ) digits = digits + 1 if ( digits == max_digits .AND. bits > overflow_bits ) & go to 996 if ( digits > max_digits ) go to 996 bits = 10*bits + iachar(char) - iachar('0') if ( bits < 0 ) go to 996 case default go to 999 end select end do if ( bits < 0 .OR. digits == 0 .OR. digits > max_digits ) go to 999 call self % init( bits, status ) if ( present(status) ) then call error_handler( 'There was an allocation fault for SELF.', & alloc_fault, status, module_name, procedure ) return end if do bit = 1, bits-1 read( unit, & advance='NO', & FMT='(A1)', & err=997, & end=998, & iostat=ierr, & iomsg=message ) char if ( char == '0' ) then call self % clear( bits-bit ) else if ( char == '1' ) then call self % set( bits-bit ) else go to 999 end if end do read( unit, & advance=optval(advance, 'YES'), & FMT='(A1)', & err=997, & end=998, & iostat=ierr, & iomsg=message ) char if ( char == '0' ) then call self % clear( bits-bit ) else if ( char == '1' ) then call self % set( bits-bit ) else go to 999 end if if ( present(status) ) status = success return 996 call error_handler( 'Integer overflow in reading size of ' // & 'bitset literal from UNIT.', & read_failure, status, module_name, procedure ) return 997 call error_handler( 'Failure on read of UNIT.', & read_failure, status, module_name, procedure ) return 998 call error_handler( 'End of File of UNIT before finishing a ' // & 'bitset literal.', & eof_failure, status, module_name, procedure ) return 999 call error_handler( 'Invalid character in bitset literal in UNIT ', & char_string_invalid_error, status, & module_name, procedure ) end subroutine read_bitset_unit_large elemental module subroutine set_bit_large(self, pos) ! ! Sets the value at the POS position in SELF, provided the position is ! valid. If the position is less than 0 or greater than BITS(SELF)-1 ! then SELF is unchanged. ! class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: pos integer(bits_kind) :: set_block, block_bit if ( pos < 0 .OR. pos > self % num_bits-1 ) return set_block = pos / block_size + 1 block_bit = pos - (set_block - 1) * block_size self % blocks(set_block) = ibset( self % blocks(set_block), block_bit ) end subroutine set_bit_large pure module subroutine set_range_large(self, start_pos, stop_pos) ! ! Sets all valid bits to 1 from the START_POS to the STOP_POS positions ! in SELF. If STOP_POS < START_POS no bits are changed. Positions outside ! the range 0 to BITS(SELF)-1 are ignored. ! class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos integer(bits_kind) :: bit, block_, end_bit, first_block, last_block, & start_bit start_bit = max( 0_bits_kind, start_pos ) end_bit = min( stop_pos, self % num_bits-1 ) if ( end_bit < start_bit ) return first_block = start_bit / block_size + 1 last_block = end_bit / block_size + 1 if ( first_block == last_block ) then ! FIRST and LAST are in the same block call mvbits( all_ones, & start_bit - (first_block-1)*block_size, & end_bit - start_bit + 1, & self % blocks(first_block), & start_bit - (first_block-1)*block_size ) return end if ! Do "partial" black containing FIRST bit = start_bit - (first_block-1)*block_size call mvbits( all_ones, & bit, & block_size - bit, & self % blocks(first_block), & bit ) ! Do "partial" black containing LAST bit = end_bit - (last_block-1)*block_size call mvbits( all_ones, & 0, & bit+1, & self % blocks(last_block), & 0 ) ! Do remaining blocks do block_ = first_block+1, last_block-1 self % blocks(block_) = all_ones end do end subroutine set_range_large elemental module function test_large(self, pos) result(test) ! ! Returns .TRUE. if the POS position is set, .FALSE. otherwise. If POS ! is negative or greater than BITS(SELF) - 1 the result is .FALSE.. ! logical :: test class(bitset_large), intent(in) :: self integer(bits_kind), intent(in) :: pos integer(bits_kind) :: bit_block if ( pos < 0 .or. pos >= self % num_bits ) then test = .false. else bit_block = pos / block_size + 1 test = btest( self % blocks(bit_block), & pos - ( bit_block-1 ) * block_size ) end if end function test_large module subroutine to_string_large(self, string, status) ! ! Represents the value of SELF as a binary literal in STRING ! Status may have the values SUCCESS or ALLOC_FAULT ! class(bitset_large), intent(in) :: self character(len=:), allocatable, intent(out) :: string integer, intent(out), optional :: status character(*), parameter :: procedure = 'TO_STRING' integer(bits_kind) :: bit, bit_count, pos integer :: stat bit_count = self % num_bits allocate( character(len=bit_count)::string, stat=stat ) if ( stat > 0 ) then call error_handler( 'There was an allocation fault for STRING.', & alloc_fault, status, module_name, procedure ) return end if do bit=0_bits_kind, bit_count-1 pos = bit_count - bit if ( self % test( bit) ) then string( pos:pos ) = '1' else string( pos:pos ) = '0' end if end do if ( present(status) ) status = success end subroutine to_string_large elemental module function value_large(self, pos) result(value) ! ! Returns 1 if the POS position is set, 0 otherwise. If POS is negative ! or greater than BITS(SELF) - 1 the result is 0. ! integer :: value class(bitset_large), intent(in) :: self integer(bits_kind), intent(in) :: pos integer :: bit_block if ( pos < 0 .or. pos >= self % num_bits ) then value = 0 else bit_block = pos / block_size + 1 if ( btest( self % blocks(bit_block), & pos - ( bit_block-1 ) * block_size ) ) then value = 1 else value = 0 end if end if end function value_large module subroutine write_bitset_string_large(self, string, status) ! ! Writes a bitset literal to the allocatable default character STRING, ! representing the individual bit values in the bitset_t, SELF. ! If STATUS is absent an error results in an error stop with an ! informative stop code. If STATUS is present it has the default ! value of SUCCESS, or the value ALLOC_FAULT if allocation of ! the output string failed. ! class(bitset_large), intent(in) :: self character(len=:), allocatable, intent(out) :: string integer, intent(out), optional :: status integer(bits_kind) :: bit, & bit_count, & count_digits, & pos integer :: stat character(*), parameter :: procedure = 'WRITE_BITSET' bit_count = bits(self) call digit_count( self % num_bits, count_digits ) allocate( character(len=count_digits+bit_count+2)::string, stat=stat ) if ( stat > 0 ) then call error_handler( 'There was an allocation fault for STRING.', & alloc_fault, status, module_name, procedure ) return end if write( string, "('S', i0)" ) self % num_bits string( count_digits + 2:count_digits + 2 ) = "B" do bit=0_bits_kind, bit_count-1 pos = count_digits + 2 + bit_count - bit if ( self % test( bit) ) then string( pos:pos ) = '1' else string( pos:pos ) = '0' end if end do if ( present(status) ) status = success contains subroutine digit_count( bits, digits ) integer(bits_kind), intent(in) :: bits integer(bits_kind), intent(out) :: digits integer(bits_kind) :: factor factor = bits if ( factor <= 0 ) then digits = 1 return end if do digits = 1, 127 factor = factor / 10 if ( factor == 0 ) return end do end subroutine digit_count end subroutine write_bitset_string_large module subroutine write_bitset_unit_large(self, unit, advance, status) ! ! Writes a bitset literal to the I/O unit, UNIT, representing the ! individual bit values in the bitset_t, SELF. By default or if ! ADVANCE is present with the value 'YES', advancing output is used. ! If ADVANCE is present with the value 'NO', then the current record ! is not advanced by the write. If STATUS is absent an error results ! in an error stop with an informative stop code. If STATUS is ! present it has the default value of SUCCESS, the value ! ALLOC_FAULT if allocation of the output string failed, or ! WRITE_FAILURE if the WRITE statement outputting the literal failed. ! class(bitset_large), intent(in) :: self integer, intent(in) :: unit character(len=*), intent(in), optional :: advance integer, intent(out), optional :: status integer :: ierr character(:), allocatable :: string character(len=120) :: message character(*), parameter :: procedure = "WRITE_BITSET" call self % write_bitset(string, status) if ( present(status) ) then if (status /= success ) return end if write( unit, & FMT='(A)', & advance=optval(advance, 'YES'), & iostat=ierr, & iomsg=message ) & string if (ierr /= 0) then call error_handler( 'Failure on a WRITE statement for UNIT.', & write_failure, status, module_name, procedure ) return endif end subroutine write_bitset_unit_large elemental module subroutine xor_large(set1, set2) ! ! Sets the bits in SET1 to the bitwise XOR of the original bits in SET1 ! and SET2. SET1 and SET2 must have the same number of bits otherwise ! the result is undefined. ! type(bitset_large), intent(inout) :: set1 type(bitset_large), intent(in) :: set2 integer(bits_kind) :: block_ do block_ = 1_bits_kind, size(set1 % blocks, kind=bits_kind) set1 % blocks(block_) = ieor( set1 % blocks(block_), & set2 % blocks(block_) ) end do end subroutine xor_large end submodule stdlib_bitsets_large fortran-lang-stdlib-0ede301/src/bitsets/stdlib_bitsets_64.fypp0000664000175000017500000011162415135654166024666 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_bitsets) stdlib_bitsets_64 implicit none contains elemental module function all_64( self ) result(all) ! Returns .TRUE. if all bits in SELF are 1, .FALSE. otherwise. logical :: all class(bitset_64), intent(in) :: self intrinsic :: btest integer(bits_kind) :: pos do pos=0, self % num_bits - 1 if ( .not. btest(self % block, pos) ) then all = .false. return end if end do all = .true. end function all_64 elemental module subroutine and_64(set1, set2) ! ! Sets the bits in SET1 to the bitwise AND of the original bits in SET1 ! and SET2. It is required that SET1 have the same number of bits as ! SET2 otherwise the result is undefined. ! type(bitset_64), intent(inout) :: set1 type(bitset_64), intent(in) :: set2 ! The set2 extent includes the entire extent of set1. ! The (zeroed) region past the end of set1 is unaffected by ! the iand. set1 % block = iand( set1 % block, & set2 % block ) end subroutine and_64 elemental module subroutine and_not_64(set1, set2) ! ! Sets the bits in SET1 to the bitwise and of the original bits in SET1 ! with the bitwise negation of SET2. SET1 and SET2 must have the same ! number of bits otherwise the result is undefined. ! type(bitset_64), intent(inout) :: set1 type(bitset_64), intent(in) :: set2 ! The not with iand means that the zero'ed regions past the end of each set ! do not interact with the in set regions set1 % block = iand( set1 % block, not( set2 % block ) ) end subroutine and_not_64 elemental module function any_64(self) result(any) ! Returns .TRUE. if any bit in SELF is 1, .FALSE. otherwise. logical :: any class(bitset_64), intent(in) :: self if ( self % block /= 0 ) then any = .true. return else any = .false. end if end function any_64 #:for k1 in INT_KINDS module subroutine assign_log${k1}$_64( self, logical_vector ) ! Used to define assignment from an array of type logical for bitset_64 type(bitset_64), intent(out) :: self logical(${k1}$), intent(in) :: logical_vector(:) integer(bits_kind) :: log_size integer(bits_kind) :: index log_size = size( logical_vector, kind=bits_kind ) if ( log_size > 64 ) then error stop module_name // ' % ' // 'ASSIGNMENT' // " has " // & "SIZE(LOGICAL_VECTOR) > 64 with assignment to a BITSET_64." end if self % num_bits = log_size self % block = 0 do index=0, log_size-1 if ( logical_vector(index+1) ) then self % block = ibset( self % block, index ) end if end do end subroutine assign_log${k1}$_64 pure module subroutine log${k1}$_assign_64( logical_vector, set ) ! Used to define assignment to an array of type logical for bitset_64 logical(${k1}$), intent(out), allocatable :: logical_vector(:) type(bitset_64), intent(in) :: set integer(bits_kind) :: index allocate( logical_vector( set % num_bits ) ) do index=0, set % num_bits-1 if ( set % value( index ) == 1 ) then logical_vector(index+1) = .true. else logical_vector(index+1) = .false. end if end do end subroutine log${k1}$_assign_64 #:endfor elemental module function bit_count_64(self) result(bit_count) ! Returns the number of non-zero bits in SELF. integer(bits_kind) :: bit_count class(bitset_64), intent(in) :: self integer(bits_kind) :: pos bit_count = 0 do pos = 0, self % num_bits - 1 if ( btest( self % block, pos ) ) bit_count = bit_count + 1 end do end function bit_count_64 elemental module subroutine clear_bit_64(self, pos) ! ! Sets to zero the POS position in SELF. If POS is less than zero or ! greater than BITS(SELF)-1 it is ignored. ! class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: pos if ( pos < 0 .OR. (pos > self % num_bits-1) ) & return self % block = ibclr( self % block, pos ) end subroutine clear_bit_64 pure module subroutine clear_range_64(self, start_pos, stop_pos) ! ! Sets to zero all bits from the START_POS to STOP_POS positions in SELF. ! If STOP_POS < START_POS then no bits are modified. Positions outside ! the range 0 to BITS(SELF)-1 are ignored. ! class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos integer(bits_kind) :: true_first, true_last true_first = max( 0_bits_kind, start_pos ) true_last = min( self % num_bits-1, stop_pos ) if ( true_last < true_first ) return call mvbits( all_zeros, & true_first, & true_last - true_first + 1, & self % block, & true_first ) end subroutine clear_range_64 elemental module function eqv_64(set1, set2) result(eqv) ! ! Returns .TRUE. if all bits in SET1 and SET2 have the same value, ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: eqv type(bitset_64), intent(in) :: set1, set2 eqv = set1 % block == set2 % block end function eqv_64 module subroutine extract_64(new, old, start_pos, stop_pos, status) ! Creates a new bitset, NEW, from a range, START_POS to STOP_POS, in bitset ! OLD. If START_POS is greater than STOP_POS the new bitset is empty. ! If START_POS is less than zero or STOP_POS is greater than BITS(OLD)-1 ! then if STATUS is present it has the value INDEX_INVALID_ERROR, ! otherwise processing stops with an informative message. type(bitset_64), intent(out) :: new type(bitset_64), intent(in) :: old integer(bits_kind), intent(in) :: start_pos, stop_pos integer, intent(out), optional :: status integer(bits_kind) :: bits, i, k character(*), parameter :: procedure = 'EXTRACT' if ( start_pos < 0 ) then call error_handler( 'had a START_POS less than 0.', & index_invalid_error, status, & module_name, procedure ) return end if if ( stop_pos >= old % num_bits ) then call error_handler( 'had a STOP_POS greater than BITS(OLD)-1.', & index_invalid_error, status, & module_name, procedure ) return end if bits = stop_pos - start_pos + 1 if ( bits <= 0 ) then new % num_bits = 0 new % block = 0 return else new % num_bits = bits do i=0, bits-1 k = start_pos + i if ( btest( old % block, k ) ) & new % block = ibset(new % block, i) end do end if if ( present(status) ) status = success end subroutine extract_64 elemental module subroutine flip_bit_64(self, pos) ! ! Flips the value at the POS position in SELF, provided the position is ! valid. If POS is less than 0 or greater than BITS(SELF)-1, no value is ! changed. ! class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: pos if ( pos < 0 .OR. pos > self % num_bits-1 ) return if ( btest( self % block, pos ) ) then self % block = ibclr( self % block, pos ) else self % block = ibset( self % block, pos ) end if end subroutine flip_bit_64 pure module subroutine flip_range_64(self, start_pos, stop_pos) ! ! Flips all valid bits from the START_POS to the STOP_POS positions in ! SELF. If STOP_POS < START_POS no bits are flipped. Positions less than ! 0 or greater than BITS(SELF)-1 are ignored. ! class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos integer(bits_kind) :: end_bit, start_bit start_bit = max( 0_bits_kind, start_pos ) end_bit = min( stop_pos , self % num_bits-1 ) call mvbits( not(self % block), & start_bit, & end_bit - start_bit + 1, & self % block, & start_bit ) end subroutine flip_range_64 module subroutine from_string_64(self, string, status) ! Initializes the bitset `self` treating `string` as a binary literal ! `status` may have the values: ! `success` - if no problems were found, ! `alloc_fault` - if allocation of the bitset failed ! `char_string_too_large_error` - if `string` was too large, or ! `char_string_invalid_error` - if string had an invalid character. class(bitset_64), intent(out) :: self character(*), intent(in) :: string integer, intent(out), optional :: status character(*), parameter :: procedure = 'FROM_STRING' integer(int64) :: bit integer(int64) :: bits character(1) :: char bits = len(string, kind=int64) if ( bits > 64 ) then call error_handler( 'STRING was too long for a ' // & 'BITSET_64 SELF.', & char_string_too_large_error, status, & module_name, procedure ) return end if self % num_bits = bits do bit = 1, bits char = string(bit:bit) if ( char == '0' ) then call self % clear( int(bits-bit, kind=bits_kind) ) else if ( char == '1' ) then call self % set( int(bits-bit, kind=bits_kind) ) else call error_handler( 'STRING had a character other than ' // & '0 or 1.', & char_string_invalid_error, status, & module_name, procedure ) return end if end do if ( present(status) ) status = success end subroutine from_string_64 elemental module function ge_64(set1, set2) result(ge) ! ! Returns .TRUE. if the bits in SET1 and SET2 are the same or the ! highest order different bit is set to 1 in SET1 and to 0 in set2. ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: ge type(bitset_64), intent(in) :: set1, set2 ge = bge( set1 % block, set2 % block ) end function ge_64 elemental module function gt_64(set1, set2) result(gt) ! ! Returns .TRUE. if the bits in SET1 and SET2 differ and the ! highest order different bit is set to 1 in SET1 and to 0 in set2. ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: gt type(bitset_64), intent(in) :: set1, set2 gt = bgt( set1 % block, set2 % block ) end function gt_64 module subroutine init_zero_64(self, bits, status) ! ! Creates the bitset, `self`, of size `bits`, with all bits initialized to ! zero. `bits` must be non-negative. If an error occurs and `status` is ! absent then processing stops with an informative stop code. `status` ! will have one of the values: ! * `success` - if no problems were found, ! * `array_size_invalid_error` - if `bits` is either negative or larger ! than 64 with `self` of class `bitset_64`, or ! * `alloc_fault` - if memory allocation failed ! class(bitset_64), intent(out) :: self integer(bits_kind), intent(in) :: bits integer, intent(out), optional :: status character(*), parameter :: procedure = "INIT" if ( bits < 0 ) then call error_handler( 'BITS had a negative value.', & array_size_invalid_error, status, & module_name, procedure ) return end if if ( bits > 64 ) then call error_handler( 'BITS had a value greater than 64.', & array_size_invalid_error, status, & module_name, procedure ) return end if self % num_bits = bits self % block = all_zeros if ( present(status) ) status = success end subroutine init_zero_64 module subroutine input_64(self, unit, status) ! ! Reads the components of the bitset, `self`, from the unformatted I/O ! unit, `unit`, assuming that the components were written using `output`. ! If an error occurs and `status` is absent then processing stops with ! an informative stop code. `status` has one of the values: ! * `success` - if no problem was found ! * `alloc_fault` - if it failed during allocation of memory for `self`, or ! * `array_size_invalid_error` if the `bits(self)` in `unit` is negative ! or greater than 64 for a `bitset_64` input. ! * `read_failure` - if it failed during the reads from `unit` ! class(bitset_64), intent(out) :: self integer, intent(in) :: unit integer, intent(out), optional :: status integer(bits_kind) :: bits integer :: ierr character(len=120) :: message character(*), parameter :: procedure = 'INPUT' integer :: stat read(unit, iostat=ierr, iomsg=message) bits if (ierr /= 0) then call error_handler( 'Failure on a READ statement for UNIT.', & read_failure, status, module_name, procedure ) return end if if ( bits < 0 ) then call error_handler( 'BITS in UNIT had a negative value.', & array_size_invalid_error, status, & module_name, procedure ) return end if if ( bits > 64 ) then call error_handler( 'BITS in UNIT had a value greater than 64.', & array_size_invalid_error, status, & module_name, procedure ) return end if call self % init(bits, stat) if (stat /= success) then call error_handler( 'Allocation failure for SELF.', & alloc_fault, status, module_name, procedure ) return end if if (bits < 1) return read(unit, iostat=ierr, iomsg=message) self % block if (ierr /= 0) then call error_handler( 'Failure on a READ statement for UNIT.', & read_failure, status, module_name, procedure ) return end if if ( present(status) ) status = success end subroutine input_64 elemental module function le_64(set1, set2) result(le) ! ! Returns .TRUE. if the bits in SET1 and SET2 are the same or the ! highest order different bit is set to 0 in SET1 and to 1 in set2. ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: le type(bitset_64), intent(in) :: set1, set2 le = ble( set1 % block, set2 % block ) end function le_64 elemental module function lt_64(set1, set2) result(lt) ! ! Returns .TRUE. if the bits in SET1 and SET2 differ and the ! highest order different bit is set to 0 in SET1 and to 1 in set2. ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: lt type(bitset_64), intent(in) :: set1, set2 lt = blt( set1 % block, set2 % block ) end function lt_64 elemental module function neqv_64(set1, set2) result(neqv) ! ! Returns .TRUE. if all bits in SET1 and SET2 have the same value, ! .FALSE. otherwise. The sets must have the same number of bits ! otherwise the results are undefined. ! logical :: neqv type(bitset_64), intent(in) :: set1, set2 neqv = set1 % block /= set2 % block end function neqv_64 elemental module function none_64(self) result(none) ! ! Returns .TRUE. if none of the bits in SELF have the value 1. ! logical :: none class(bitset_64), intent(in) :: self none = .true. if (self % block /= 0) then none = .false. return end if end function none_64 elemental module subroutine not_64(self) ! ! Sets the bits in SELF to their logical complement ! class(bitset_64), intent(inout) :: self integer(bits_kind) :: bit if ( self % num_bits == 0 ) return do bit=0, self % num_bits - 1 if ( btest( self % block, bit ) ) then self % block = ibclr( self % block, bit ) else self % block = ibset( self % block, bit ) end if end do end subroutine not_64 elemental module subroutine or_64(set1, set2) ! ! Sets the bits in SET1 to the bitwise OR of the original bits in SET1 ! and SET2. If SET1 has fewer bits than SET2 then the additional bits ! in SET2 are ignored. If SET1 has more bits than SET2, then the ! absent SET2 bits are treated as if present with zero value. ! type(bitset_64), intent(inout) :: set1 type(bitset_64), intent(in) :: set2 if ( set1 % num_bits >= set2 % num_bits ) then set1 % block = ior( set1 % block, & set2 % block ) else ! The set1 extent ends before set2 => set2 bits must not affect bits in ! set1 beyond its extent => set those bits to zero while keeping proper ! values of other bits in set2 set1 % block = & ior( set1 % block, & ibits( set2 % block, & 0, & set1 % num_bits ) ) end if end subroutine or_64 module subroutine output_64(self, unit, status) ! ! Writes the components of the bitset, SELF, to the unformatted I/O ! unit, UNIT, in a unformatted sequence compatible with INPUT. If ! STATUS is absent an error results in an error stop with an ! informative stop code. If STATUS is present it has the default ! value of SUCCESS, or the value WRITE_FAILURE if the write failed. ! class(bitset_64), intent(in) :: self integer, intent(in) :: unit integer, intent(out), optional :: status integer :: ierr character(len=120) :: message character(*), parameter :: procedure = "OUTPUT" write(unit, iostat=ierr, iomsg=message) self % num_bits if (ierr /= 0) go to 999 if (self % num_bits < 1) return write(unit, iostat=ierr, iomsg=message) self % block if (ierr /= 0) go to 999 return 999 call error_handler( 'Failure on a WRITE statement for UNIT.', & write_failure, status, module_name, procedure ) end subroutine output_64 module subroutine read_bitset_string_64(self, string, status) ! ! Uses the bitset literal in the default character `string`, to define ! the bitset, `self`. The literal may be preceded by an an arbitrary ! sequence of blank characters. If `status` is absent an error results ! in an error stop with an informative stop code. If `status` ! is present it has one of the values ! * `success` - if no problems occurred, ! * `alloc_fault` - if allocation of memory for SELF failed, ! * `array_size_invalid_error - if `bits(self)` in `string` is greater ! than 64 for a `bitset_64`, ! * `char_string_invalid_error` - if the bitset literal has an invalid ! character, ! * `char_string_too_small_error - if the string ends before all the bits ! are read. ! * `integer_overflow_error` - if the bitset literal has a `bits(self)` ! value too large to be represented, ! class(bitset_64), intent(out) :: self character(len=*), intent(in) :: string integer, intent(out), optional :: status integer(bits_kind) :: bit, bits integer(bits_kind) :: digits, pos character(*), parameter :: procedure = "READ_BITSET" integer :: stat pos = 1 find_start: do pos=1, len(string) if ( string(pos:pos) /= ' ' ) exit end do find_start if ( pos > len(string) - 8 ) go to 999 if ( string(pos:pos) /= 's' .AND. string(pos:pos) /= 'S' ) go to 999 pos = pos + 1 bits = 0 digits = 0 do select case( iachar( string(pos:pos) ) ) case(ia0:ia9) digits = digits + 1 if ( digits == max_digits .AND. bits > overflow_bits ) & go to 996 if ( digits > max_digits ) go to 996 bits = bits*10 + iachar( string(pos:pos) ) - ia0 if ( bits < 0 ) go to 996 case(iachar('b'), iachar('B')) exit case default go to 999 end select pos = pos + 1 end do if ( bits > 64 ) then call error_handler( 'BITS in STRING was greater than 64.', & char_string_too_large_error, status, & module_name, procedure ) return end if if ( bits + pos > len(string) ) then call error_handler( 'STRING was too small for the number of ' // & 'bits specified by STRING.', & char_string_too_small_error, status, & module_name, procedure ) return end if call self % init( bits, stat ) if (stat /= success) then call error_handler( 'There was an allocation fault for SELF.', & alloc_fault, status, module_name, procedure ) return end if pos = pos + 1 bit = bits - 1 do if ( string(pos:pos) == '0' ) then call self % clear( bit ) ! this may not be needed else if ( string(pos:pos) == '1' ) then call self % set( bit ) else go to 999 end if pos = pos + 1 bit = bit - 1 if ( bit < 0 ) exit end do if ( present(status) ) status = success return 996 call error_handler( 'There was an integer overflow in reading' // & 'size of bitset literal from UNIT', & integer_overflow_error, status, & module_name, procedure ) return 999 call error_handler( 'There was an invalid character in STRING', & char_string_invalid_error, status, & module_name, procedure ) end subroutine read_bitset_string_64 module subroutine read_bitset_unit_64(self, unit, advance, status) ! ! Uses the bitset literal at the current position in the formatted ! file with I/O unit, `unit`, to define the bitset, `self`. The literal ! may be preceded by an arbitrary sequence of blank characters. ! If `advance` is present it must be either 'YES' or 'NO'. If absent ! it has the default value of 'YES' to determine whether advancing ! I/O occurs. If `status` is absent an error results in an error stop ! with an informative stop code. If `status` is present it has one of ! the values: ! * `success` - if no problem occurred, ! * `alloc_fault` - if allocation of `self` failed, ! * `array_size_invalid_error` - if `bits(self)` in the bitset literal ! is greater than 64 for a `bitset_64`. ! * `char_string_invalid_error` - if the read of the bitset literal found ! an invalid character, ! * `eof_failure` - if a `read` statement reaches an end-of-file before ! completing the read of the bitset literal, ! * `integer_overflow_error` - if the bitset literal has a `bits(self)` ! value too large to be represented, ! * `read_failure` - if a `read` statement fails, ! class(bitset_64), intent(out) :: self integer, intent(in) :: unit character(*), intent(in), optional :: advance integer, intent(out), optional :: status integer(bits_kind) :: bit, bits, digits integer :: ierr character(len=128) :: message character(*), parameter :: procedure = "READ_BITSET" character(len=1) :: char do read( unit, & advance='NO', & FMT='(A1)', & err=997, & end=998, & iostat=ierr, & iomsg=message ) char select case( char ) case( ' ' ) cycle case( 's', 'S' ) exit case default go to 999 end select end do bits = 0 digits = 0 do read( unit, & advance='NO', & FMT='(A1)', & err=998, & end=999, & iostat=ierr, & iomsg=message ) char if ( char == 'b' .or. char == 'B' ) exit select case( char ) case( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ) digits = digits + 1 if ( digits == max_digits .AND. bits > overflow_bits ) & go to 996 if ( digits > max_digits ) go to 996 bits = 10*bits + iachar(char) - iachar('0') if ( bits < 0 ) go to 996 case default go to 999 end select end do if ( bits < 0 .OR. digits == 0 .OR. digits > max_digits ) go to 999 if ( bits > 64 ) then call error_handler( 'BITS in UNIT was greater than 64.', & array_size_invalid_error, status, & module_name, procedure ) return end if call self % init( bits ) do bit = 1, bits-1 read( unit, & advance='NO', & FMT='(A1)', & err=997, & end=998, & iostat=ierr, & iomsg=message ) char if ( char == '0' ) then call self % clear( bits-bit ) else if ( char == '1' ) then call self % set( bits-bit ) else go to 999 end if end do read( unit, & advance=optval(advance, 'YES'), & FMT='(A1)', & err=997, & end=998, & iostat=ierr, & iomsg=message ) char if ( char == '0' ) then call self % clear( bits-bit ) else if ( char == '1' ) then call self % set( bits-bit ) else go to 999 end if if ( present(status) ) status = success return 996 call error_handler( 'Integer overflow in reading size of ' // & 'bitset literal from UNIT.', & read_failure, status, module_name, procedure ) return 997 call error_handler( 'Failure on read of UNIT.', & read_failure, status, module_name, procedure ) return 998 call error_handler( 'End of File of UNIT before finishing a ' // & 'bitset literal.', & eof_failure, status, module_name, procedure ) return 999 call error_handler( 'Invalid character in bitset literal in UNIT ', & char_string_invalid_error, status, & module_name, procedure ) end subroutine read_bitset_unit_64 elemental module subroutine set_bit_64(self, pos) ! ! Sets the value at the POS position in SELF, provided the position is ! valid. If the position is less than 0 or greater than BITS(SELF)-1 ! then SELF is unchanged. ! class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: pos integer(block_kind) :: dummy if ( pos < 0 .OR. pos > self % num_bits-1 ) return dummy = ibset( self % block, pos ) self % block = dummy end subroutine set_bit_64 pure module subroutine set_range_64(self, start_pos, stop_pos) ! ! Sets all valid bits to 1 from the START_POS to the STOP_POS positions ! in SELF. If STOP_POA < START_POS no bits are changed. Positions outside ! the range 0 to BITS(SELF)-1 are ignored. ! class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos integer(bits_kind) :: end_bit, start_bit start_bit = max( 0_bits_kind, start_pos ) end_bit = min( stop_pos, self % num_bits-1 ) if ( end_bit < start_bit ) return ! FIRST and LAST are in the same block call mvbits( all_ones, & start_bit, & end_bit - start_bit + 1, & self % block, & start_bit ) end subroutine set_range_64 elemental module function test_64(self, pos) result(test) ! ! Returns .TRUE. if the POS position is set, .FALSE. otherwise. If POS ! is negative or greater than BITS(SELF) - 1 the result is .FALSE.. ! logical :: test class(bitset_64), intent(in) :: self integer(bits_kind), intent(in) :: pos if ( pos < 0 .or. pos >= self % num_bits ) then test = .false. else test = btest( self % block, pos ) end if end function test_64 module subroutine to_string_64(self, string, status) ! ! Represents the value of SELF as a binary literal in STRING ! Status may have the values SUCCESS or ALLOC_FAULT ! class(bitset_64), intent(in) :: self character(len=:), allocatable, intent(out) :: string integer, intent(out), optional :: status character(*), parameter :: procedure = 'TO_STRING' integer :: bit, bit_count, pos, stat bit_count = self % num_bits allocate( character(len=bit_count)::string, stat=stat ) if ( stat > 0 ) then call error_handler( 'There was an allocation fault for STRING.', & alloc_fault, status, module_name, procedure ) return end if do bit=0, bit_count-1 pos = bit_count - bit if ( btest( self % block, bit ) ) then string( pos:pos ) = '1' else string( pos:pos ) = '0' end if end do if ( present(status) ) status = success end subroutine to_string_64 elemental module function value_64(self, pos) result(value) ! ! Returns 1 if the POS position is set, 0 otherwise. If POS is negative ! or greater than BITS(SELF) - 1 the result is 0. ! integer :: value class(bitset_64), intent(in) :: self integer(bits_kind), intent(in) :: pos if ( pos < 0 .or. pos >= self % num_bits ) then value = 0 else if ( btest( self % block, pos ) ) then value = 1 else value = 0 end if end if end function value_64 module subroutine write_bitset_string_64(self, string, status) ! ! Writes a bitset literal to the allocatable default character STRING, ! representing the individual bit values in the bitset_t, SELF. ! If STATUS is absent an error results in an error stop with an ! informative stop code. If STATUS is present it has the default ! value of SUCCESS, or the value ALLOC_FAULT if allocation of ! the output string failed. ! class(bitset_64), intent(in) :: self character(len=:), allocatable, intent(out) :: string integer, intent(out), optional :: status integer(bits_kind) :: bit, & bit_count, & count_digits, & pos integer :: stat character(*), parameter :: procedure = 'WRITE_BITSET' bit_count = bits(self) call digit_count( self % num_bits, count_digits ) allocate( character(len=count_digits+bit_count+2)::string, stat=stat ) if ( stat > 0 ) then call error_handler( 'There was an allocation fault for STRING.', & alloc_fault, status, module_name, procedure ) return end if write( string, "('S', i0)" ) self % num_bits string( count_digits + 2:count_digits + 2 ) = "B" do bit=0, bit_count-1 pos = count_digits + 2 + bit_count - bit if ( btest( self % block, bit ) ) then string( pos:pos ) = '1' else string( pos:pos ) = '0' end if end do if ( present(status) ) status = success contains subroutine digit_count( bits, digits ) integer(bits_kind), intent(in) :: bits integer(bits_kind), intent(out) :: digits integer(bits_kind) :: factor factor = bits if ( factor <= 0 ) then digits = 1 return end if do digits = 1, 127 factor = factor / 10 if ( factor == 0 ) return end do end subroutine digit_count end subroutine write_bitset_string_64 module subroutine write_bitset_unit_64(self, unit, advance, status) ! ! Writes a bitset literal to the I/O unit, UNIT, representing the ! individual bit values in the bitset_t, SELF. By default or if ! ADVANCE is present with the value 'YES', advancing output is used. ! If ADVANCE is present with the value 'NO', then the current record ! is not advanced by the write. If STATUS is absent an error results ! in an error stop with an informative stop code. If STATUS is ! present it has the default value of SUCCESS, the value ! ALLOC_FAULT if allocation of the output string failed, or ! WRITE_FAILURE if the WRITE statement outputting the literal failed. ! class(bitset_64), intent(in) :: self integer, intent(in) :: unit character(len=*), intent(in), optional :: advance integer, intent(out), optional :: status integer :: ierr character(:), allocatable :: string character(len=120) :: message character(*), parameter :: procedure = "WRITE_BITSET" call self % write_bitset(string, status) if ( present(status) ) then if (status /= success ) return end if write( unit, & FMT='(A)', & advance=optval(advance, 'YES'), & iostat=ierr, & iomsg=message ) & string if (ierr /= 0) then call error_handler( 'Failure on a WRITE statement for UNIT.', & write_failure, status, module_name, procedure ) return endif end subroutine write_bitset_unit_64 elemental module subroutine xor_64(set1, set2) ! ! Sets the bits in SET1 to the bitwise XOR of the original bits in SET1 ! and SET2. SET1 and SET2 must have the same number of bits otherwise ! the result is undefined. ! type(bitset_64), intent(inout) :: set1 type(bitset_64), intent(in) :: set2 set1 % block = ieor( set1 % block, & set2 % block ) end subroutine xor_64 end submodule stdlib_bitsets_64 fortran-lang-stdlib-0ede301/src/bitsets/stdlib_bitsets.fypp0000664000175000017500000024331015135654166024353 0ustar alastairalastair#:include "common.fypp" module stdlib_bitsets !! Implements zero based bitsets of size up to `huge(0_int32)`. !! The current code uses 64 bit integers to store the bits and uses all 64 bits. !! The code assumes two's complement integers, and treats negative integers as !! having the sign bit set. !!([Specification](../page/specs/stdlib_bitsets.html)) use :: stdlib_kinds, only: & bits_kind => int32, & ! If changed change also max_digits, and block_kind => int64, & ! overflow_bits int8, & int16, & int32, & int64 use stdlib_optval, only : optval use, intrinsic :: & iso_fortran_env, only: & error_unit implicit none private integer(bits_kind), parameter :: & block_size = bit_size(0_block_kind) public :: max_digits, overflow_bits integer, parameter :: & max_digits = 10 ! bits_kind == int32 ! max_digits = 19 ! bits_kind == int64 integer(bits_kind), parameter :: & overflow_bits = 2_bits_kind**30/5 ! bits_kind == int32 ! overflow_bits = 2_bits_kind**62/5 ! bits_kind == int64 integer(block_kind), parameter :: all_zeros = 0_block_kind integer(block_kind), parameter :: all_ones = not(all_zeros) character(*), parameter :: module_name = "STDLIB_BITSETS" integer, parameter :: & ia0 = iachar('0'), & ia9 = iachar('9') integer, parameter, public :: success = 0 !! Error flag indicating no errors integer, parameter, public :: alloc_fault = 1 !! Error flag indicating a memory allocation failure integer, parameter, public :: array_size_invalid_error = 2 !! Error flag indicating an invalid bits value integer, parameter, public :: char_string_invalid_error = 3 !! Error flag indicating an invalid character string integer, parameter, public :: char_string_too_large_error = 4 !! Error flag indicating a too large character string integer, parameter, public :: char_string_too_small_error = 5 !! Error flag indicating a too small character string integer, parameter, public :: eof_failure = 6 !! Error flag indicating unexpected End-of-File on a READ integer, parameter, public :: index_invalid_error = 7 !! Error flag indicating an invalid index integer, parameter, public :: integer_overflow_error = 8 !! Error flag indicating integer overflow integer, parameter, public :: read_failure = 9 !! Error flag indicating failure of a READ statement integer, parameter, public :: write_failure = 10 !! Error flag indicating a failure on a WRITE statement public :: bits_kind ! Public constant public :: & bitset_type, & bitset_large, & bitset_64 ! Public types public :: & assignment(=), & and, & and_not, & bits, & extract, & operator(==), & operator(/=), & operator(>), & operator(>=), & operator(<), & operator(<=), & or, & xor !! Public procedures public :: error_handler type, abstract :: bitset_type !! version: experimental !! !! Parent type for bitset_64 and bitset_large ([Specification](../page/specs/stdlib_bitsets.html#the-stdlib_bitsets-derived-types)) private integer(bits_kind) :: num_bits = 0_bits_kind contains procedure(all_abstract), deferred, pass(self) :: all procedure(any_abstract), deferred, pass(self) :: any procedure(bit_count_abstract), deferred, pass(self) :: bit_count procedure, pass(self) :: bits procedure(clear_bit_abstract), deferred, pass(self) :: clear_bit procedure(clear_range_abstract), deferred, pass(self) :: clear_range generic :: clear => clear_bit, clear_range procedure(flip_bit_abstract), deferred, pass(self) :: flip_bit procedure(flip_range_abstract), deferred, pass(self) :: flip_range generic :: flip => flip_bit, flip_range procedure(from_string_abstract), deferred, pass(self) :: from_string procedure(init_zero_abstract), deferred, pass(self) :: init_zero generic :: init => init_zero procedure(input_abstract), deferred, pass(self) :: input procedure(none_abstract), deferred, pass(self) :: none procedure(not_abstract), deferred, pass(self) :: not procedure(output_abstract), deferred, pass(self) :: output procedure(read_bitset_string_abstract), deferred, pass(self) :: & read_bitset_string procedure(read_bitset_unit_abstract), deferred, pass(self) :: & read_bitset_unit generic :: read_bitset => read_bitset_string, read_bitset_unit procedure(set_bit_abstract), deferred, pass(self) :: set_bit procedure(set_range_abstract), deferred, pass(self) :: set_range generic :: set => set_bit, set_range procedure(test_abstract), deferred, pass(self) :: test procedure(to_string_abstract), deferred, pass(self) :: to_string procedure(value_abstract), deferred, pass(self) :: value procedure(write_bitset_string_abstract), deferred, pass(self) :: & write_bitset_string procedure(write_bitset_unit_abstract), deferred, pass(self) :: & write_bitset_unit generic :: write_bitset => write_bitset_string, write_bitset_unit end type bitset_type abstract interface elemental function all_abstract( self ) result(all) !! Version: experimental !! !! Returns `.true.` if all bits in `self` are 1, `.false.` otherwise. !! !!#### Example !! !!```fortran !! program example_all !! use stdlib_bitsets !! character(*), parameter :: & !! bits_all = '111111111111111111111111111111111' !! type(bitset_64) :: set0 !! call set0 % from_string( bits_all ) !! if ( bits(set0) /= 33 ) then !! error stop "FROM_STRING failed to interpret " // & !! 'BITS_ALL's size properly." !! else if ( .not. set0 % all() ) then !! error stop "FROM_STRING failed to interpret" // & !! "BITS_ALL's value properly." !! else !! write(*,*) "FROM_STRING transferred BITS_ALL properly" // & !! " into set0." !! end if !! end program example_all !!``` import :: bitset_type logical :: all class(bitset_type), intent(in) :: self end function all_abstract elemental function any_abstract(self) result(any) !! Version: experimental !! !! Returns `.true.` if any bit in `self` is 1, `.false.` otherwise. !! !!#### Example !! !!```fortran !! program example_any !! use stdlib_bitsets !! character(*), parameter :: & !! bits_0 = '0000000000000000000' !! type(bitset_64) :: set0 !! call set0 % from_string( bits_0 ) !! if ( .not. set0 % any() ) then !! write(*,*) "FROM_STRING interpreted " // & !! "BITS_0's value properly." !! end if !! call set0 % set(5) !! if ( set0 % any() ) then !! write(*,*) "ANY interpreted SET0's value properly." !! end if !! end program example_any !!``` import :: bitset_type logical :: any class(bitset_type), intent(in) :: self end function any_abstract elemental function bit_count_abstract(self) result(bit_count) !! Version: experimental !! !! Returns the number of non-zero bits in `self`. !! !!#### Example !! !!```fortran !! program example_bit_count !! use stdlib_bitsets !! character(*), parameter :: & !! bits_0 = '0000000000000000000' !! type(bitset_64) :: set0 !! call set0 % from_string( bits_0 ) !! if ( set0 % bit_count() == 0 ) then !! write(*,*) "FROM_STRING interpreted " // & !! "BITS_0's value properly." !! end if !! call set0 % set(5) !! if ( set0 % bit_count() == 1 ) then !! write(*,*) "BIT_COUNT interpreted SET0's value properly." !! end if !! end program example_bit_count !!``` import :: bitset_type, bits_kind integer(bits_kind) :: bit_count class(bitset_type), intent(in) :: self end function bit_count_abstract elemental subroutine clear_bit_abstract(self, pos) !! Version: experimental !! !! Sets to zero the `pos` position in `self`. If `pos` is less than zero or !! greater than `bits(self)-1` it is ignored. !! !!#### Example !! !!```fortran !! program example_clear !! use stdlib_bitsets !! type(bitset_large) :: set0 !! call set0 % init(166) !! call set0 % not() !! if ( set0 % all() ) write(*,*) 'SET0 is properly initialized.' !! call set0 % clear(165) !! if ( .not. set0 % test(165) ) write(*,*) 'Bit 165 is cleared.' !! call set0 % clear(0,164) !! if ( set0 % none() ) write(*,*) 'All bits are cleared.' !! end program example_clear !!``` import :: bitset_type, bits_kind class(bitset_type), intent(inout) :: self integer(bits_kind), intent(in) :: pos end subroutine clear_bit_abstract pure subroutine clear_range_abstract(self, start_pos, stop_pos) !! Version: experimental !! !! Sets to zero all bits from the `start_pos` to `stop_pos` positions in `set`. !! If `stop_pos < start_pos` then no bits are modified. Positions outside !! the range 0 to `bits(self)-1` are ignored. import :: bitset_type, bits_kind class(bitset_type), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos end subroutine clear_range_abstract elemental subroutine flip_bit_abstract(self, pos) !! Version: experimental !! !! Flips the value at the `pos` position in `self`, provided the position is !! valid. If `pos` is less than 0 or greater than `bits(self)-1`, no value is !! changed. !! !!#### Example !! !!```fortran !! program example_flip !! use stdlib_bitsets !! type(bitset_large) :: set0 !! call set0 % init(166) !! if ( set0 % none() ) write(*,*) 'SET0 is properly initialized.' !! call set0 % flip(165) !! if ( set0 % test(165) ) write(*,*) 'Bit 165 is flipped.' !! call set0 % flip(0,164) !! if ( set0 % all() ) write(*,*) 'All bits are flipped.' !! end program example_flip !!``` import :: bitset_type, bits_kind class(bitset_type), intent(inout) :: self integer(bits_kind), intent(in) :: pos end subroutine flip_bit_abstract pure subroutine flip_range_abstract(self, start_pos, stop_pos) !! Version: experimental !! !! Flips all valid bits from the `start_pos` to the `stop_pos` positions in !! `self`. If `stop_pos < start_pos` no bits are flipped. Positions less than !! 0 or greater than `bits(self)-1` are ignored. import :: bitset_type, bits_kind class(bitset_type), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos end subroutine flip_range_abstract subroutine from_string_abstract(self, string, status) !! Version: experimental !! !! Initializes the bitset `self` treating `string` as a binary literal !! `status` may have the values: !! * `success` - if no problems were found, !! * `alloc_fault` - if allocation of the bitset failed !! * `char_string_too_large_error` - if `string` was too large, or !! * `char_string_invalid_error` - if string had an invalid character. !! !!#### Example !! !!```fortran !! program example_from_string !! use stdlib_bitsets !! character(*), parameter :: & !! bits_all = '111111111111111111111111111111111' !! type(bitset_64) :: set0 !! call set0 % from_string( bits_all ) !! if ( bits(set0) /= 33 ) then !! error stop "FROM_STRING failed to interpret " // & !! 'BITS_ALL's size properly." !! else if ( .not. set0 % all() ) then !! error stop "FROM_STRING failed to interpret" // & !! "BITS_ALL's value properly." !! else !! write(*,*) "FROM_STRING transferred BITS_ALL properly" // & !! " into set0." !! end if !! end program example_from_string !!``` import :: bitset_type class(bitset_type), intent(out) :: self character(*), intent(in) :: string integer, intent(out), optional :: status end subroutine from_string_abstract subroutine init_zero_abstract(self, bits, status) !! Creates the bitset, `self`, of size `bits`, with all bits initialized to !! zero. `bits` must be non-negative. If an error occurs and `status` is !! absent then processing stops with an informative stop code. `status` !! will have one of the values; !! * `success` - if no problems were found, !! * `alloc_fault` - if memory allocation failed !! * `array_size_invalid_error` - if `bits` is either negative or larger !! than 64 with `self` of class `bitset_64`, or !! !!#### Example !! !!```fortran !! program example_init !! use stdlib_bitsets !! type(bitset_large) :: set0 !! call set0 % init(166) !! if ( set0 % bits() == 166 ) & !! write(*,*) `SET0 has the proper size.' !! if ( set0 % none() ) write(*,*) 'SET0 is properly initialized.' !! end program example_init !!``` import :: bitset_type, bits_kind class(bitset_type), intent(out) :: self integer(bits_kind), intent(in) :: bits integer, intent(out), optional :: status end subroutine init_zero_abstract subroutine input_abstract(self, unit, status) !! Version: experimental !! !! Reads the components of the bitset, `self`, from the unformatted I/O !! unit, `unit`, assuming that the components were written using `output`. !! If an error occurs and `status` is absent then processing stops with !! an informative stop code. `status` has one of the values: !! * `success` - if no problem was found !! * `alloc_fault` - if it failed allocating memory for `self`, or !! * `array_size_invalid_error` if the `bits(self)` in `unit` is negative !! or greater than 64 for a `bitset_64` input. !! * `read_failure` - if it failed during the reads from `unit` !! !!#### Example !! !!```fortran !! program example_input !! character(*), parameter :: & !! bits_0 = '000000000000000000000000000000000', & !! bits_1 = '000000000000000000000000000000001', & !! bits_33 = '100000000000000000000000000000000' !! integer :: unit !! type(bitset_64) :: set0, set1, set2, set3, set4, set5 !! call set0 % from_string( bits_0 ) !! call set1 % from_string( bits_1 ) !! call set2 % from_string( bits_33 ) !! open( newunit=unit, file='test.bin', status='replace', & !! form='unformatted', action='write' ) !! call set2 % output(unit) !! call set1 % output(unit) !! call set0 % output(unit) !! close( unit ) !! open( newunit=unit, file='test.bin', status='old', & !! form='unformatted', action='read' ) !! call set5 % input(unit) !! call set4 % input(unit) !! call set3 % input(unit) !! close( unit ) !! if ( set3 /= set0 .or. set4 /= set1 .or. set5 /= set2 ) then !! error stop 'Transfer to and from units using ' // & !! ' output and input failed.' !! else !! write(*,*) 'Transfer to and from units using ' // & !! 'output and input succeeded.' !! end if !! end program example_input !!``` import :: bitset_type class(bitset_type), intent(out) :: self integer, intent(in) :: unit integer, intent(out), optional :: status end subroutine input_abstract elemental function none_abstract(self) result(none) !! Version: experimental !! !! Returns `.true.` if none of the bits in `self` have the value 1. !! !!#### Example !! !!```fortran !! program example_none !! use stdlib_bitsets !! character(*), parameter :: & !! bits_0 = '0000000000000000000' !! type(bitset_large) :: set0 !! call set0 % from_string( bits_0 ) !! if ( set0 % none() ) then !! write(*,*) "FROM_STRING interpreted " // & !! "BITS_0's value properly." !! end if !! call set0 % set(5) !! if ( .not. set0 % none() ) then !! write(*,*) "NONE interpreted SET0's value properly." !! end if !! end program example_none !!``` import :: bitset_type logical :: none class(bitset_type), intent(in) :: self end function none_abstract elemental subroutine not_abstract(self) !! Version: experimental !! !! Sets the bits in `self` to their logical complement !! !!#### Example !! !!```fortran !! program example_not !! use stdlib_bitsets !! type(bitset_large) :: set0 !! call set0 % init( 155 ) !! if ( set0 % none() ) then !! write(*,*) "FROM_STRING interpreted " // & !! "BITS_0's value properly." !! end if !! call set0 % not() !! if ( set0 % all() ) then !! write(*,*) "ALL interpreted SET0's value properly." !! end if !! end program example_not !!``` import :: bitset_type class(bitset_type), intent(inout) :: self end subroutine not_abstract subroutine output_abstract(self, unit, status) !! Version: experimental !! !! Writes the components of the bitset, `self`, to the unformatted I/O !! unit, `unit`, in a unformatted sequence compatible with `input`. If !! `status` is absent an error results in an error stop with an !! informative stop code. If `status` is present it has the default !! value of `success`, or the value `write_failure` if the write failed. !! !!#### Example !! !!```fortran !! program example_output !! character(*), parameter :: & !! bits_0 = '000000000000000000000000000000000', & !! bits_1 = '000000000000000000000000000000001', & !! bits_33 = '100000000000000000000000000000000' !! integer :: unit !! type(bitset_64) :: set0, set1, set2, set3, set4, set5 !! call set0 % from_string( bits_0 ) !! call set1 % from_string( bits_1 ) !! call set2 % from_string( bits_33 ) !! open( newunit=unit, file='test.bin', status='replace', & !! form='unformatted', action='write' ) !! call set2 % output(unit) !! call set1 % output(unit) !! call set0 % output(unit) !! close( unit ) !! open( newunit=unit, file='test.bin', status='old', & !! form='unformatted', action='read' ) !! call set5 % input(unit) !! call set4 % input(unit) !! call set3 % input(unit) !! close( unit ) !! if ( set3 /= set0 .or. set4 /= set1 .or. set5 /= set2 ) then !! error stop 'Transfer to and from units using ' // & !! ' output and input failed.' !! else !! write(*,*) 'Transfer to and from units using ' // & !! 'output and input succeeded.' !! end if !! end program example_output !!``` import :: bitset_type class(bitset_type), intent(in) :: self integer, intent(in) :: unit integer, intent(out), optional :: status end subroutine output_abstract subroutine read_bitset_string_abstract(self, string, status) !! Version: experimental !! !! Uses the bitset literal in the default character `string`, to define !! the bitset, `self`. The literal may be preceded by an an arbitrary !! sequence of blank characters. If `status` is absent an error results !! in an error stop with an informative stop code. If `status` !! is present it has one of the values !! * `success` - if no problems occurred, !! * `alloc_fault` - if allocation of memory for SELF failed, !! * `array_size_invalid_error - if `bits(self)` in `string` is greater !! than 64 for a `bitset_64`, !! * `char_string_invalid_error` - if the bitset literal has an invalid !! character, !! * `char_string_too_small_error - if the string ends before all the bits !! are read. !! * `integer_overflow_error` - if the bitset literal has a `bits(self)` !! value too large to be represented, !! !!#### Example !! !!```fortran !! program example_read_bitset !! character(*), parameter :: & !! bits_0 = 'S33B000000000000000000000000000000000', & !! bits_1 = 'S33B000000000000000000000000000000001', & !! bits_33 = 'S33B100000000000000000000000000000000' !! character(:), allocatable :: test_0, test_1, test_2 !! integer :: unit !! type(bitset_64) :: set0, set1, set2, set3, set4, set5 !! call set0 % read_bitset( bits_0, status ) !! call set1 % read_bitset( bits_1, status ) !! call set2 % read_bitset( bits_2, status ) !! call set0 % write_bitset( test_0, status ) !! call set1 % write_bitset( test_1, status ) !! call set2 % write_bitset( test_2, status ) !! if ( bits_0 == test_0 .and. bits_1 == test_1 .and. & !! bits_2 == test_2 ) then !! write(*,*) 'READ_BITSET to WRITE_BITSET strings worked.' !! end if !! open( newunit=unit, file='test.txt', status='replace', & !! form='formatted', action='write' ) !! call set2 % write_bitset(unit, advance='no') !! call set1 % write_bitset(unit, advance='no') !! call set0 % write_bitset(unit) !! close( unit ) !! open( newunit=unit, file='test.txt', status='old', & !! form='formatted', action='read' ) !! call set3 % read_bitset(unit, advance='no') !! call set4 % read_bitset(unit, advance='no') !! call set5 % read_bitset(unit) !! if ( set3 == set0 .and. set4 == set1 .and. set5 == set2 ) then !! write(*,*) WRITE_BITSET to READ_BITSET through unit worked.' !! end if !! end program example_read_bitset !!``` import :: bitset_type class(bitset_type), intent(out) :: self character(len=*), intent(in) :: string integer, intent(out), optional :: status end subroutine read_bitset_string_abstract subroutine read_bitset_unit_abstract(self, unit, advance, status) !! Version: experimental !! !! Uses the bitset literal at the current position in the formatted !! file with I/O unit, `unit`, to define the bitset, `self`. The literal !! may be preceded by an an arbitrary sequence of blank characters. !! If `advance` is present it must be either 'YES' or 'NO'. If absent !! it has the default value of 'YES' to determine whether advancing !! I/O occurs. If `status` is absent an error results in an error stop !! with an informative stop code. If `status` is present it has one of !! the values: !! * `success` - if no problem occurred, !! * `alloc_fault` - if allocation of `self` failed, !! * `array_size_invalid_error` - if `bits(self)` in the bitset literal !! is greater than 64 for a `bitset_64`, !! * `char_string_invalid_error` - if the read of the bitset literal found !! an invalid character, !! * `eof_failure` - if a `read` statement reached an end-of-file before !! completing the read of the bitset literal, !! * `integer_overflow_error` - if the bitset literal has a `bits(self)` !! value too large to be represented, !! * `read_failure` - if a `read` statement fails, ! import :: bitset_type class(bitset_type), intent(out) :: self integer, intent(in) :: unit character(*), intent(in), optional :: advance integer, intent(out), optional :: status end subroutine read_bitset_unit_abstract elemental subroutine set_bit_abstract(self, pos) !! Version: experimental !! !! Sets the value at the `pos` position in `self`, provided the position is !! valid. If the position is less than 0 or greater than `bits(self)-1` !! then `self` is unchanged. !! !!#### Example !! !!```fortran !! program example_set !! use stdlib_bitsets !! type(bitset_large) :: set0 !! call set0 % init(166) !! if ( set0 % none() ) write(*,*) 'SET0 is properly initialized.' !! call set0 % set(165) !! if ( set0 % test(165) ) write(*,*) 'Bit 165 is set.' !! call set0 % set(0,164) !! if ( set0 % all() ) write(*,*) 'All bits are set.' !! end program example_set !!``` import :: bitset_type, bits_kind class(bitset_type), intent(inout) :: self integer(bits_kind), intent(in) :: pos end subroutine set_bit_abstract pure subroutine set_range_abstract(self, start_pos, stop_pos) !! Version: experimental !! !! Sets all valid bits to 1 from the `start_pos` to the `stop_pos` positions !! in `self`. If `stop_pos < start_pos` no bits are changed. Positions outside !! the range 0 to `bits(self)-1` are ignored. import :: bitset_type, bits_kind class(bitset_type), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos end subroutine set_range_abstract elemental function test_abstract(self, pos) result(test) !! Version: experimental !! !! Returns `.true.` if the `pos` position is set, `.false.` otherwise. If `pos` !! is negative or greater than `bits(self) - 1` the result is `.false.`. !! !!#### Example !! !!```fortran !! program example_test !! use stdlib_bitsets !! type(bitset_large) :: set0 !! call set0 % init(166) !! call set0 % not() !! if ( set0 % all() ) write(*,*) 'SET0 is properly initialized.' !! call set0 % clear(165) !! if ( .not. set0 % test(165) ) write(*,*) 'Bit 165 is cleared.' !! call set0 % set(165) !! if ( set0 % test(165) ) write(*,*) 'Bit 165 is set.' !! end program example_test !!``` import :: bitset_type, bits_kind logical :: test class(bitset_type), intent(in) :: self integer(bits_kind), intent(in) :: pos end function test_abstract subroutine to_string_abstract(self, string, status) !! Version: experimental !! !! Represents the value of `self` as a binary literal in `string` !! Status may have the values `success` or `alloc_fault`. !! !!#### Example !! !!```fortran !! program example_to_string !! use stdlib_bitsets !! character(*), parameter :: & !! bits_all = '111111111111111111111111111111111' !! type(bitset_64) :: set0 !! character(:), allocatable :: new_string !! call set0 % init(33) !! call set0 % not() !! call set0 % to_string( new_string ) !! if ( new_string == bits_all ) then !! write(*,*) "TO_STRING transferred BITS0 properly" // & !! " into NEW_STRING." !! end if !! end program example_to_string !!``` import :: bitset_type class(bitset_type), intent(in) :: self character(:), allocatable, intent(out) :: string integer, intent(out), optional :: status end subroutine to_string_abstract elemental function value_abstract(self, pos) result(value) !! Version: experimental !! !! Returns 1 if the `pos` position is set, 0 otherwise. If `pos` is negative !! or greater than `bits(set) - 1` the result is 0. !! !!#### Example !! !!```fortran !! program example_value !! use stdlib_bitsets !! type(bitset_large) :: set0 !! call set0 % init(166) !! call set0 % not() !! if ( set0 % all() ) write(*,*) 'SET0 is properly initialized.' !! call set0 % clear(165) !! if ( set0 % value(165) == 0 ) write(*,*) 'Bit 165 is cleared.' !! call set0 % set(165) !! if ( set0 % value(165) == 1 ) write(*,*) 'Bit 165 is set.' !! end program example_value !!``` import :: bitset_type, bits_kind integer :: value class(bitset_type), intent(in) :: self integer(bits_kind), intent(in) :: pos end function value_abstract subroutine write_bitset_string_abstract(self, string, status) !! Version: experimental !! !! Writes a bitset literal to the allocatable default character `string`, !! representing the individual bit values in the `bitset_type`, `self`. !! If `status` is absent an error results in an error stop with an !! informative stop code. If `status` is present it has the default !! value of `success`, or the value `alloc_fault` if allocation of !! the output string failed. !! !!#### Example !! !!```fortran !! program example_write_bitset !! character(*), parameter :: & !! bits_0 = 'S33B000000000000000000000000000000000', & !! bits_1 = 'S33B000000000000000000000000000000001', & !! bits_33 = 'S33B100000000000000000000000000000000' !! character(:), allocatable :: test_0, test_1, test_2 !! integer :: unit !! type(bitset_64) :: set0, set1, set2, set3, set4, set5 !! call set0 % read_bitset( bits_0, status ) !! call set1 % read_bitset( bits_1, status ) !! call set2 % read_bitset( bits_2, status ) !! call set0 % write_bitset( test_0, status ) !! call set1 % write_bitset( test_1, status ) !! call set2 % write_bitset( test_2, status ) !! if ( bits_0 == test_0 .and. bits_1 == test_1 .and. & !! bits_2 == test_2 ) then !! write(*,*) 'READ_BITSET to WRITE_BITSET strings worked.' !! end if !! open( newunit=unit, file='test.txt', status='replace', & !! form='formatted', action='write' ) !! call set2 % write_bitset(unit, advance='no') !! call set1 % write_bitset(unit, advance='no') !! call set0 % write_bitset(unit) !! close( unit ) !! open( newunit=unit, file='test.txt', status='old', & !! form='formatted', action='read' ) !! call set3 % read_bitset(unit, advance='no') !! call set4 % read_bitset(unit, advance='no') !! call set5 % read_bitset(unit) !! if ( set3 == set0 .and. set4 == set1 .and. set5 == set2 ) then !! write(*,*) WRITE_BITSET to READ_BITSET through unit worked.' !! end if !! end program example_write_bitset !!``` import :: bitset_type class(bitset_type), intent(in) :: self character(len=:), allocatable, intent(out) :: string integer, intent(out), optional :: status end subroutine write_bitset_string_abstract subroutine write_bitset_unit_abstract(self, unit, advance, & status) !! Version: experimental !! !! Writes a bitset literal to the I/O unit, `unit`, representing the !! individual bit values in the `bitset_t`, `self`. If an error occurs then !! processing stops with a message to `error_unit`. By default or if !! `advance` is present with the value 'YES', advancing output is used. !! If `advance` is present with the value 'NO', then the current record !! is not advanced by the write. If `status` is absent, an error results !! in an error stop with an informative stop code. If `status` is !! present it has the default value of `success`, the value !! `alloc_fault` if allocation of the output string failed, !! `write_failure` if the `write` statement outputting the literal failed. import :: bitset_type class(bitset_type), intent(in) :: self integer, intent(in) :: unit character(len=*), intent(in), optional :: advance integer, intent(out), optional :: status end subroutine write_bitset_unit_abstract end interface type, extends(bitset_type) :: bitset_large !! Version: experimental !! !! Type for bitsets with more than 64 bits ([Specification](../page/specs/stdlib_bitsets.html#the-stdlib_bitsets-derived-types)) private integer(block_kind), private, allocatable :: blocks(:) contains procedure, pass(self) :: all => all_large procedure, pass(self) :: any => any_large procedure, pass(self) :: bit_count => bit_count_large procedure, pass(self) :: clear_bit => clear_bit_large procedure, pass(self) :: clear_range => clear_range_large procedure, pass(self) :: flip_bit => flip_bit_large procedure, pass(self) :: flip_range => flip_range_large procedure, pass(self) :: from_string => from_string_large procedure, pass(self) :: init_zero => init_zero_large procedure, pass(self) :: input => input_large procedure, pass(self) :: none => none_large procedure, pass(self) :: not => not_large procedure, pass(self) :: output => output_large procedure, pass(self) :: & read_bitset_string => read_bitset_string_large procedure, pass(self) :: read_bitset_unit => read_bitset_unit_large procedure, pass(self) :: set_bit => set_bit_large procedure, pass(self) :: set_range => set_range_large procedure, pass(self) :: test => test_large procedure, pass(self) :: to_string => to_string_large procedure, pass(self) :: value => value_large procedure, pass(self) :: & write_bitset_string => write_bitset_string_large procedure, pass(self) :: write_bitset_unit => write_bitset_unit_large end type bitset_large interface elemental module function all_large( self ) result(all) !! Version: experimental !! !! Returns `.true.` if all bits in `self` are 1, `.false.` otherwise. logical :: all class(bitset_large), intent(in) :: self end function all_large elemental module function any_large(self) result(any) !! Version: experimental !! !! Returns `.true.` if any bit in `self` is 1, `.false.` otherwise. logical :: any class(bitset_large), intent(in) :: self end function any_large elemental module function bit_count_large(self) result(bit_count) !! Version: experimental !! !! Returns the number of non-zero bits in `self`. integer(bits_kind) :: bit_count class(bitset_large), intent(in) :: self end function bit_count_large elemental module subroutine clear_bit_large(self, pos) !! Version: experimental !! !! Sets to zero the bit at `pos` position in `self`. If `pos` is less than !! zero or greater than `bits(self)-1` it is ignored. class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: pos end subroutine clear_bit_large pure module subroutine clear_range_large(self, start_pos, stop_pos) !! Version: experimental !! !! Sets to zero all bits from the `start_pos` to `stop_pos` positions in `self`. !! If `stop_pos < start_pos` then no bits are modified. Positions outside !! the range 0 to `bits(set)-1` are ignored. class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos end subroutine clear_range_large elemental module subroutine flip_bit_large(self, pos) !! Version: experimental !! !! Flips the bit value at the `pos` position in `self`, provided the position is !! valid. If `pos` is less than 0 or greater than `bits(self)-1`, no value is !! changed. class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: pos end subroutine flip_bit_large pure module subroutine flip_range_large(self, start_pos, stop_pos) !! Version: experimental !! !! Flips all valid bits from the `start_pos` to the `stop_pos` positions in !! `self`. If `stop_pos < start_pos` no bits are flipped. Positions less than !! 0 or greater than `bits(self)-1` are ignored. class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos end subroutine flip_range_large module subroutine from_string_large(self, string, status) !! Version: experimental !! !! Initializes the bitset `self` treating `string` as a binary literal !! `status` may have the values: !! * `success` - if no problems were found, !! * `alloc_fault` - if allocation of the bitset failed !! * `char_string_too_large_error` - if `string` was too large, or !! * `char_string_invalid_error` - if string had an invalid character. class(bitset_large), intent(out) :: self character(*), intent(in) :: string integer, intent(out), optional :: status end subroutine from_string_large module subroutine init_zero_large(self, bits, status) !! Version: experimental !! !! Creates the bitset, `self`, of size `bits`, with all bits initialized to !! zero. `bits` must be non-negative. If an error occurs and `status` is !! absent then processing stops with an informative stop code. `status` !! will have one of the values; !! * `success` - if no problems were found, !! * `alloc_fault` - if memory allocation failed !! * `array_size_invalid_error` - if `bits` is either negative or larger !! than 64 with `self` of class `bitset_64`, or class(bitset_large), intent(out) :: self integer(bits_kind), intent(in) :: bits integer, intent(out), optional :: status end subroutine init_zero_large module subroutine input_large(self, unit, status) !! Version: experimental !! !! Reads the components of the bitset, `self`, from the unformatted I/O !! unit, `unit`, assuming that the components were written using `output`. !! If an error occurs and `status` is absent then processing stops with !! an informative stop code. `status` has one of the values: !! * `success` - if no problem was found !! * `alloc_fault` - if it failed allocating memory for `self`, or !! * `array_size_invalid_error` if the `bits(self)` in `unit` is negative !! or greater than 64 for a `bitset_64` input. !! * `read_failure` - if it failed during the reads from `unit` class(bitset_large), intent(out) :: self integer, intent(in) :: unit integer, intent(out), optional :: status end subroutine input_large elemental module function none_large(self) result(none) !! Version: experimental !! !! Returns `.true.` if none of the bits in `self` have the value 1. logical :: none class(bitset_large), intent(in) :: self end function none_large elemental module subroutine not_large(self) !! Version: experimental !! !! Sets the bits in `self` to their logical complement class(bitset_large), intent(inout) :: self end subroutine not_large module subroutine output_large(self, unit, status) !! Version: experimental !! !! Writes the components of the bitset, `self`, to the unformatted I/O !! unit, `unit`, in a unformatted sequence compatible with `input`. If !! `status` is absent an error results in an error stop with an !! informative stop code. If `status` is present it has the default !! value of `success`, or the value `write_failure` if the write failed. class(bitset_large), intent(in) :: self integer, intent(in) :: unit integer, intent(out), optional :: status end subroutine output_large module subroutine read_bitset_string_large(self, string, status) !! Version: experimental !! !! Uses the bitset literal in the default character `string`, to define !! the bitset, `self`. The literal may be preceded by an an arbitrary !! sequence of blank characters. If `status` is absent an error results !! in an error stop with an informative stop code. If `status` !! is present it has one of the values !! * `success` - if no problems occurred, !! * `alloc_fault` - if allocation of memory for SELF failed, !! * `array_size_invalid_error - if `bits(self)` in `string` is greater !! than 64 for a `bitset_64`, !! * `char_string_invalid_error` - if the bitset literal has an invalid !! character, !! * `char_string_too_small_error - if the string ends before all the bits !! are read. !! * `integer_overflow_error` - if the bitset literal has a `bits(self)` !! value too large to be represented, class(bitset_large), intent(out) :: self character(len=*), intent(in) :: string integer, intent(out), optional :: status end subroutine read_bitset_string_large module subroutine read_bitset_unit_large(self, unit, advance, status) !! Version: experimental !! !! Uses the bitset literal at the current position in the formatted !! file with I/O unit, `unit`, to define the bitset, `self`. The literal !! may be preceded by an an arbitrary sequence of blank characters. !! If `advance` is present it must be either 'YES' or 'NO'. If absent !! it has the default value of 'YES' to determine whether advancing !! I/O occurs. If `status` is absent an error results in an error stop !! with an informative stop code. If `status` is present it has one of !! the values: !! * `success` - if no problem occurred, !! * `alloc_fault` - if allocation of `self` failed, !! * `array_size_invalid_error` - if `bits(self)` in the bitset literal !! is greater than 64 for a `bitset_64`, !! * `char_string_invalid_error` - if the read of the bitset literal found !! an invalid character, !! * `eof_failure` - if a `read` statement reached an end-of-file before !! completing the read of the bitset literal, !! * `integer_overflow_error` - if the bitset literal has a `bits(self)` !! value too large to be represented, !! * `read_failure` - if a `read` statement fails, class(bitset_large), intent(out) :: self integer, intent(in) :: unit character(*), intent(in), optional :: advance integer, intent(out), optional :: status end subroutine read_bitset_unit_large elemental module subroutine set_bit_large(self, pos) !! Version: experimental !! !! Sets the value at the `pos` position in `self`, provided the position is !! valid. If the position is less than 0 or greater than `bits(self)-1` !! then `self` is unchanged. class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: pos end subroutine set_bit_large pure module subroutine set_range_large(self, start_pos, stop_pos) !! Version: experimental !! !! Sets all valid bits to 1 from the `start_pos` to the `stop_pos` positions !! in `self`. If `stop_pos < start_pos` no bits are changed. Positions outside !! the range 0 to `bits(self)-1` are ignored. class(bitset_large), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos end subroutine set_range_large elemental module function test_large(self, pos) result(test) !! Version: experimental !! !! Returns `.true.` if the `pos` position is set, `.false.` otherwise. If `pos` !! is negative or greater than `bits(self) - 1` the result is `.false.`. logical :: test class(bitset_large), intent(in) :: self integer(bits_kind), intent(in) :: pos end function test_large module subroutine to_string_large(self, string, status) !! Version: experimental !! !! Represents the value of `self` as a binary literal in `string` !! Status may have the values `success` or `alloc_fault`. class(bitset_large), intent(in) :: self character(len=:), allocatable, intent(out) :: string integer, intent(out), optional :: status end subroutine to_string_large elemental module function value_large(self, pos) result(value) !! Version: experimental !! !! Returns 1 if the `pos` position is set, 0 otherwise. If `pos` is negative !! or greater than `bits(set) - 1` the result is 0. integer :: value class(bitset_large), intent(in) :: self integer(bits_kind), intent(in) :: pos end function value_large module subroutine write_bitset_string_large(self, string, status) !! Version: experimental !! !! Writes a bitset literal to the allocatable default character `string`, !! representing the individual bit values in the bitset_large, `self`. !! If `status` is absent an error results in an error stop with an !! informative stop code. If `status` is present it has the default !! value of `success, or the value `alloc_fault` if allocation of !! the output string failed. class(bitset_large), intent(in) :: self character(len=:), allocatable, intent(out) :: string integer, intent(out), optional :: status end subroutine write_bitset_string_large module subroutine write_bitset_unit_large(self, unit, advance, status) !! Version: experimental !! !! Writes a bitset literal to the I/O unit, `unit`, representing the !! individual bit values in the bitset, `self`. By default or if !! `advance` is present with the value 'YES', advancing output is used. !! If `advance` is present with the value 'NO', then the current record !! is not advanced by the write. If `status` is absent an error results !! in an error stop with an informative stop code. If `status` is !! present it has the default value of `success`, the value !! `alloc_fault` if allocation of the output string failed, or !! `write_failure` if the `write` statement outputting the literal failed. class(bitset_large), intent(in) :: self integer, intent(in) :: unit character(len=*), intent(in), optional :: advance integer, intent(out), optional :: status end subroutine write_bitset_unit_large end interface interface assignment(=) !! Version: experimental !! !! Used to define assignment for `bitset_large`. !! ([Specification](../page/specs/stdlib_bitsets.html#-compare-two-bitsets-to-determine-whether-the-bits-have-the-same-value)) !! !!#### Example !! !!```fortran !! program example_assignment !! use stdlib_bitsets !! logical(int8) :: logical1(64) = .true. !! logical(int32), allocatable :: logical2(:) !! type(bitset_64) :: set0, set1 !! set0 = logical1 !! if ( set0 % bits() /= 64 ) then !! error stop procedure // & !! ' initialization with logical(int8) failed to set' // & !! ' the right size.' !! else if ( .not. set0 % all() ) then !! error stop procedure // ' initialization with' // & !! ' logical(int8) failed to set the right values.' !! else !! write(*,*) 'Initialization with logical(int8) succeeded.' !! end if !! set1 = set0 !! if ( set1 == set0 ) & !! write(*,*) 'Initialization by assignment succeeded' !! logical2 = set1 !! if ( all( logical2 ) ) then !! write(*,*) 'Initialization of logical(int32) succeeded.' !! end if !! end program example_assignment !!``` #:for k1 in INT_KINDS pure module subroutine assign_log${k1}$_large( self, logical_vector ) !! Version: experimental !! !! Used to define assignment from an array of type `logical(${k1}$)` to a !! `bitset_large`. type(bitset_large), intent(out) :: self logical(${k1}$), intent(in) :: logical_vector(:) end subroutine assign_log${k1}$_large pure module subroutine log${k1}$_assign_large( logical_vector, set ) !! Version: experimental !! !! Used to define assignment to an array of type `logical(${k1}$)` from a !! `bitset_large`. logical(${k1}$), intent(out), allocatable :: logical_vector(:) type(bitset_large), intent(in) :: set end subroutine log${k1}$_assign_large #:endfor end interface assignment(=) type, extends(bitset_type) :: bitset_64 !! Version: experimental !! !! Type for bitsets with no more than 64 bits ([Specification](../page/specs/stdlib_bitsets.html#the-stdlib_bitsets-derived-types)) private integer(block_kind), private :: block = 0 contains procedure, pass(self) :: all => all_64 procedure, pass(self) :: any => any_64 procedure, pass(self) :: bit_count => bit_count_64 procedure, pass(self) :: clear_bit => clear_bit_64 procedure, pass(self) :: clear_range => clear_range_64 procedure, pass(self) :: flip_bit => flip_bit_64 procedure, pass(self) :: flip_range => flip_range_64 procedure, pass(self) :: from_string => from_string_64 procedure, pass(self) :: init_zero => init_zero_64 procedure, pass(self) :: input => input_64 procedure, pass(self) :: none => none_64 procedure, pass(self) :: not => not_64 procedure, pass(self) :: output => output_64 procedure, pass(self) :: read_bitset_string => read_bitset_string_64 procedure, pass(self) :: read_bitset_unit => read_bitset_unit_64 procedure, pass(self) :: set_bit => set_bit_64 procedure, pass(self) :: set_range => set_range_64 procedure, pass(self) :: test => test_64 procedure, pass(self) :: to_string => to_string_64 procedure, pass(self) :: value => value_64 procedure, pass(self) :: write_bitset_string => write_bitset_string_64 procedure, pass(self) :: write_bitset_unit => write_bitset_unit_64 end type bitset_64 interface elemental module function all_64( self ) result(all) !! Version: experimental !! !! Returns `.true.` if all bits in `self` are 1, `.false.` otherwise. logical :: all class(bitset_64), intent(in) :: self end function all_64 elemental module function any_64(self) result(any) !! Version: experimental !! !! Returns `.true.` if any bit in `self` is 1, `.false.` otherwise. logical :: any class(bitset_64), intent(in) :: self end function any_64 elemental module function bit_count_64(self) result(bit_count) !! Version: experimental !! !! Returns the number of non-zero bits in `self`. integer(bits_kind) :: bit_count class(bitset_64), intent(in) :: self end function bit_count_64 elemental module subroutine clear_bit_64(self, pos) !! Version: experimental !! !! Sets to zero the bit at `pos` position in `self`. If `pos` is less than !! zero or greater than `bits(self)-1` it is ignored. class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: pos end subroutine clear_bit_64 pure module subroutine clear_range_64(self, start_pos, stop_pos) !! Version: experimental !! !! Sets to zero all bits from the `start_pos` to `stop_pos` positions in `self`. !! If `stop_pos < start_pos` then no bits are modified. Positions outside !! the range 0 to `bits(set)-1` are ignored. class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos end subroutine clear_range_64 elemental module subroutine flip_bit_64(self, pos) !! Version: experimental !! !! Flips the bit value at the `pos` position in `self`, provided the position is !! valid. If `pos` is less than 0 or greater than `bits(self)-1`, no value is !! changed. class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: pos end subroutine flip_bit_64 pure module subroutine flip_range_64(self, start_pos, stop_pos) !! Version: experimental !! !! Flips all valid bits from the `start_pos` to the `stop_pos` positions in !! `self`. If `stop_pos < start_pos` no bits are flipped. Positions less than !! 0 or greater than `bits(self)-1` are ignored. class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos end subroutine flip_range_64 module subroutine from_string_64(self, string, status) !! Version: experimental !! !! Initializes the bitset `self` treating `string` as a binary literal !! `status` may have the values: !! * `success` - if no problems were found, !! * `alloc_fault` - if allocation of the bitset failed !! * `char_string_too_large_error` - if `string` was too large, or !! * `char_string_invalid_error` - if string had an invalid character. class(bitset_64), intent(out) :: self character(*), intent(in) :: string integer, intent(out), optional :: status end subroutine from_string_64 module subroutine init_zero_64(self, bits, status) !! Version: experimental !! !! Creates the bitset, `self`, of size `bits`, with all bits initialized to !! zero. `bits` must be non-negative. If an error occurs and `status` is !! absent then processing stops with an informative stop code. `status` !! will have one of the values: !! * `success` - if no problems were found, !! * `alloc_fault` - if memory allocation failed !! * `array_size_invalid_error` - if `bits` is either negative or larger !! than 64 with `self` of class `bitset_64`. class(bitset_64), intent(out) :: self integer(bits_kind), intent(in) :: bits integer, intent(out), optional :: status end subroutine init_zero_64 module subroutine input_64(self, unit, status) !! Version: experimental !! !! Reads the components of the bitset, `self`, from the unformatted I/O !! unit, `unit`, assuming that the components were written using `output`. !! If an error occurs and `status` is absent then processing stops with !! an informative stop code. `status` has one of the values: !! * `success` - if no problem was found !! * `alloc_fault` - if it failed allocating memory for `self`, or !! * `array_size_invalid_error` if the `bits(self)` in `unit` is negative !! or greater than 64 for a `bitset_64` input. !! * `read_failure` - if it failed during the reads from `unit` class(bitset_64), intent(out) :: self integer, intent(in) :: unit integer, intent(out), optional :: status end subroutine input_64 elemental module function none_64(self) result(none) !! Version: experimental !! !! Returns `.true.` if none of the bits in `self` have the value 1. logical :: none class(bitset_64), intent(in) :: self end function none_64 elemental module subroutine not_64(self) !! Version: experimental !! !! Sets the bits in `self` to their logical complement. class(bitset_64), intent(inout) :: self end subroutine not_64 module subroutine output_64(self, unit, status) !! Version: experimental !! !! Writes the components of the bitset, `self`, to the unformatted I/O !! unit, `unit`, in a unformatted sequence compatible with `input`. If !! `status` is absent an error results in an error stop with an !! informative stop code. If `status` is present it has the default !! value of `success`, or the value `write_failure` if the write failed. class(bitset_64), intent(in) :: self integer, intent(in) :: unit integer, intent(out), optional :: status end subroutine output_64 module subroutine read_bitset_string_64(self, string, status) !! Version: experimental !! !! Uses the bitset literal in the default character `string`, to define !! the bitset, `self`. The literal may be preceded by an an arbitrary !! sequence of blank characters. If `status` is absent an error results !! in an error stop with an informative stop code. If `status` !! is present it has one of the values: !! * `success` - if no problems occurred, !! * `alloc_fault` - if allocation of memory for SELF failed, !! * `array_size_invalid_error - if `bits(self)` in `string` is greater !! than 64 for a `bitset_64`, !! * `char_string_invalid_error` - if the bitset literal has an invalid !! character, !! * `char_string_too_small_error - if the string ends before all the bits !! are read. !! * `integer_overflow_error` - if the bitset literal has a `bits(self)` !! value too large to be represented, class(bitset_64), intent(out) :: self character(len=*), intent(in) :: string integer, intent(out), optional :: status end subroutine read_bitset_string_64 module subroutine read_bitset_unit_64(self, unit, advance, status) !! Version: experimental !! !! Uses the bitset literal at the current position in the formatted !! file with I/O unit, `unit`, to define the bitset, `self`. The literal !! may be preceded by an an arbitrary sequence of blank characters. !! If `advance` is present it must be either 'YES' or 'NO'. If absent !! it has the default value of 'YES' to determine whether advancing !! I/O occurs. If `status` is absent an error results in an error stop !! with an informative stop code. If `status` is present it has one of !! the values: !! * `success` - if no problem occurred, !! * `alloc_fault` - if allocation of `self` failed, !! * `array_size_invalid_error` - if `bits(self)` in the bitset literal !! is greater than 64 for a `bitset_64`, !! * `char_string_invalid_error` - if the read of the bitset literal found !! an invalid character, !! * `eof_failure` - if a `read` statement reached an end-of-file before !! completing the read of the bitset literal, !! * `integer_overflow_error` - if the bitset literal has a `bits(self)` !! value too large to be represented, !! * `read_failure` - if a `read` statement fails, class(bitset_64), intent(out) :: self integer, intent(in) :: unit character(*), intent(in), optional :: advance integer, intent(out), optional :: status end subroutine read_bitset_unit_64 elemental module subroutine set_bit_64(self, pos) !! Version: experimental !! !! Sets the value at the `pos` position in `self`, provided the position is !! valid. If the position is less than 0 or greater than `bits(self)-1` !! then `self` is unchanged. class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: pos end subroutine set_bit_64 pure module subroutine set_range_64(self, start_pos, stop_pos) !! Version: experimental !! !! Sets all valid bits to 1 from the `start_pos` to the `stop_pos` positions !! in `self`. If `stop_pos < start_pos` no bits are changed. Positions outside !! the range 0 to `bits(self)-1` are ignored. class(bitset_64), intent(inout) :: self integer(bits_kind), intent(in) :: start_pos, stop_pos end subroutine set_range_64 elemental module function test_64(self, pos) result(test) !! Version: experimental !! !! Returns `.true.` if the `pos` position is set, `.false.` otherwise. If `pos` !! is negative or greater than `bits(self)-1` the result is `.false.`. logical :: test class(bitset_64), intent(in) :: self integer(bits_kind), intent(in) :: pos end function test_64 module subroutine to_string_64(self, string, status) !! Version: experimental !! !! Represents the value of `self` as a binary literal in `string`. !! Status may have the values `success` or `alloc_fault` class(bitset_64), intent(in) :: self character(len=:), allocatable, intent(out) :: string integer, intent(out), optional :: status end subroutine to_string_64 elemental module function value_64(self, pos) result(value) !! Version: experimental !! !! Returns 1 if the `pos` position is set, 0 otherwise. If `pos` is negative !! or greater than `bits(set)-1` the result is 0. integer :: value class(bitset_64), intent(in) :: self integer(bits_kind), intent(in) :: pos end function value_64 module subroutine write_bitset_string_64(self, string, status) !! Version: experimental !! !! Writes a bitset literal to the allocatable default character `string`, !! representing the individual bit values in the `bitset_64`, `self`. !! If `status` is absent an error results in an error stop with an !! informative stop code. If `status` is present it has the default !! value of `success`, or the value `alloc_fault` if allocation of !! the output string failed. class(bitset_64), intent(in) :: self character(len=:), allocatable, intent(out) :: string integer, intent(out), optional :: status end subroutine write_bitset_string_64 module subroutine write_bitset_unit_64(self, unit, advance, status) !! Version: experimental !! !! Writes a bitset literal to the I/O unit, `unit`, representing the !! individual bit values in the bitset, `self`. By default or if !! `advance` is present with the value 'YES', advancing output is used. !! If `advance` is present with the value 'NO', then the current record !! is not advanced by the write. If `status` is absent an error results !! in an error stop with an informative stop code. If `status` is !! present it has the default value of `success`, the value !! `alloc_fault` if allocation of the output string failed, or !! `write_failure` if the `write` statement outputting the literal failed. class(bitset_64), intent(in) :: self integer, intent(in) :: unit character(len=*), intent(in), optional :: advance integer, intent(out), optional :: status end subroutine write_bitset_unit_64 end interface interface assignment(=) #:for k1 in INT_KINDS module subroutine assign_log${k1}$_64( self, logical_vector ) !! Version: experimental !! !! Used to define assignment from an array of type `logical(${k1}$)` to a !! `bitset_64`. type(bitset_64), intent(out) :: self logical(${k1}$), intent(in) :: logical_vector(:) end subroutine assign_log${k1}$_64 pure module subroutine log${k1}$_assign_64( logical_vector, set ) !! Version: experimental !! !! Used to define assignment to an array of type `logical(${k1}$)` from a !! `bitset_64`. logical(${k1}$), intent(out), allocatable :: logical_vector(:) type(bitset_64), intent(in) :: set end subroutine log${k1}$_assign_64 #:endfor end interface assignment(=) interface and !! Version: experimental !! !! Sets the bits in `set1` to the bitwise `and` of the original bits in `set1` !! and `set2`. The sets must have the same number of bits !! otherwise the result is undefined. !! ([Specification](../page/specs/stdlib_bitsets.html#and-bitwise-and-of-the-bits-of-two-bitsets)) !! !!#### Example !! !!```fortran !! program example_and !! use stdlib_bitsets !! type(bitset_large) :: set0, set1 !! call set0 % init(166) !! call set1 % init(166) !! call and( set0, set1 ) ! none none !! if ( none(set0) ) write(*,*) 'First test of AND worked.' !! call set0 % not() !! call and( set0, set1 ) ! all none !! if ( none(set0) ) write(*,*) 'Second test of AND worked.' !! call set1 % not() !! call and( set0, set1 ) ! none all !! if ( none(set0) ) write(*,*) 'Third test of AND worked.' !! call set0 % not() !! call and( set0, set1 ) ! all all !! if ( all(set0) ) write(*,*) 'Fourth test of AND worked.' !! end program example_and !!``` elemental module subroutine and_large(set1, set2) type(bitset_large), intent(inout) :: set1 type(bitset_large), intent(in) :: set2 end subroutine and_large elemental module subroutine and_64(set1, set2) type(bitset_64), intent(inout) :: set1 type(bitset_64), intent(in) :: set2 end subroutine and_64 end interface and interface and_not !! Version: experimental !! !! Sets the bits in `set1` to the bitwise and of the original bits in `set1` !! with the bitwise negation of `set2`. The sets must have the same !! number of bits otherwise the result is undefined. !! !! ([Specification](../page/specs/stdlib_bitsets.html#and_not-bitwise-and-of-one-bitset-with-the-negation-of-another)) !! !!#### Example !! !!```fortran !! program example_and_not !! use stdlib_bitsets !! type(bitset_large) :: set0, set1 !! call set0 % init(166) !! call set1 % init(166) !! call and_not( set0, set1 ) ! none none !! if ( none(set0) ) write(*,*) 'First test of AND_NOT worked.' !! call set0 % not() !! call and_not( set0, set1 ) ! all none !! if ( all(set0) ) write(*,*) 'Second test of AND_NOT worked.' !! call set0 % not() !! call set1 % not() !! call and_not( set0, set1 ) ! none all !! if ( none(set0) ) write(*,*) 'Third test of AND_NOT worked.' !! call set0 % not() !! call and_not( set0, set1 ) ! all all !! if ( none(set0) ) write(*,*) 'Fourth test of AND_NOT worked.' !! end program example_and_not !!``` elemental module subroutine and_not_large(set1, set2) type(bitset_large), intent(inout) :: set1 type(bitset_large), intent(in) :: set2 end subroutine and_not_large elemental module subroutine and_not_64(set1, set2) type(bitset_64), intent(inout) :: set1 type(bitset_64), intent(in) :: set2 end subroutine and_not_64 end interface and_not interface extract !! Version: experimental !! !! Creates a new bitset, `new`, from a range, `start_pos` to `stop_pos`, in !! bitset `old`. If `start_pos` is greater than `stop_pos` the new bitset is !! empty. If `start_pos` is less than zero or `stop_pos` is greater than !! `bits(old)-1` then if `status` is present it has the value !! `index_invalid_error` and `new` is undefined, otherwise processing stops !! with an informative message. !! ([Specification](../page/specs/stdlib_bitsets.html#extract-create-a-new-bitset-from-a-range-in-an-old-bitset)) !! !!#### Example !! !!```fortran !! program example_extract !! use stdlib_bitsets !! type(bitset_large) :: set0, set1 !! call set0 % init(166) !! call set0 % set(100,150) !! call extract( set1, set0, 100, 150) !! if ( set1 % bits() == 51 ) & !! write(*,*) 'SET1 has the proper size.' !! if ( set1 % all() ) write(*,*) 'SET1 has the proper values.' !! end program example_extract !!``` module subroutine extract_large(new, old, start_pos, stop_pos, status) type(bitset_large), intent(out) :: new type(bitset_large), intent(in) :: old integer(bits_kind), intent(in) :: start_pos, stop_pos integer, intent(out), optional :: status end subroutine extract_large module subroutine extract_64(new, old, start_pos, stop_pos, status) type(bitset_64), intent(out) :: new type(bitset_64), intent(in) :: old integer(bits_kind), intent(in) :: start_pos, stop_pos integer, intent(out), optional :: status end subroutine extract_64 end interface extract interface or !! Version: experimental !! !! Sets the bits in `set1` to the bitwise `or` of the original bits in `set1` !! and `set2`. The sets must have the same number of bits otherwise !! the result is undefined. !! ([Specification](../page/specs/stdlib_bitsets.html#or-bitwise-or-of-the-bits-of-two-bitsets)) !! !!#### Example !! !!```fortran !! program example_or !! use stdlib_bitsets !! type(bitset_large) :: set0, set1 !! call set0 % init(166) !! call set1 % init(166) !! call or( set0, set1 ) ! none none !! if ( none(set0) ) write(*,*) 'First test of OR worked.' !! call set0 % not() !! call or( set0, set1 ) ! all none !! if ( all(set0) ) write(*,*) 'Second test of OR worked.' !! call set0 % not() !! call set1 % not() !! call or( set0, set1 ) ! none all !! if ( all(set0) ) write(*,*) 'Third test of OR worked.' !! call set0 % not() !! call or( set0, set1 ) ! all all !! if ( all(set0) ) write(*,*) 'Fourth test of OR worked.' !! end program example_or !!``` elemental module subroutine or_large(set1, set2) type(bitset_large), intent(inout) :: set1 type(bitset_large), intent(in) :: set2 end subroutine or_large elemental module subroutine or_64(set1, set2) type(bitset_64), intent(inout) :: set1 type(bitset_64), intent(in) :: set2 end subroutine or_64 end interface or interface xor !! Version: experimental !! !! Sets the bits in `set1` to the bitwise `xor` of the original bits in `set1` !! and `set2`. The sets must have the same number of bits !! otherwise the result is undefined. !!([Specification](../page/specs/stdlib_bitsets.html#xor-bitwise-exclusive-or)) !! !!#### Example !! !!```fortran !! program example_xor !! use stdlib_bitsets !! type(bitset_large) :: set0, set1 !! call set0 % init(166) !! call set1 % init(166) !! call xor( set0, set1 ) ! none none !! if ( none(set0) ) write(*,*) 'First test of XOR worked.' !! call set0 % not() !! call xor( set0, set1 ) ! all none !! if ( all(set0) ) write(*,*) 'Second test of XOR worked.' !! call set0 % not() !! call set1 % not() !! call xor( set0, set1 ) ! none all !! if ( all(set0) ) write(*,*) 'Third test of XOR worked.' !! call set0 % not() !! call xor( set0, set1 ) ! all all !! if ( none(set0) ) write(*,*) 'Fourth test of XOR worked.' !! end program example_xor !!``` elemental module subroutine xor_large(set1, set2) type(bitset_large), intent(inout) :: set1 type(bitset_large), intent(in) :: set2 end subroutine xor_large elemental module subroutine xor_64(set1, set2) type(bitset_64), intent(inout) :: set1 type(bitset_64), intent(in) :: set2 end subroutine xor_64 end interface xor interface operator(==) !! Version: experimental !! !! Returns `.true.` if all bits in `set1` and `set2` have the same value, !! `.false.` otherwise. The sets must have the same number of bits !! otherwise the result is undefined. !!([Specification](../page/specs/stdlib_bitsets.html#-compare-two-bitsets-to-determine-whether-the-bits-have-the-same-value)) !! !!#### Example !! !!```fortran !! program example_equality !! use stdlib_bitsets !! type(bitset_64) :: set0, set1, set2 !! call set0 % init( 33 ) !! call set1 % init( 33 ) !! call set2 % init( 33 ) !! call set1 % set( 0 ) !! call set2 % set( 32 ) !! if ( set0 == set0 .and. set1 == set1 .and. set2 == set2 .and. & !! .not. set0 == set1 .and. .not. set0 == set2 .and. .not. & !! set1 == set2 ) then !! write(*,*) 'Passed 64 bit equality tests.' !! else !! error stop 'Failed 64 bit equality tests.' !! end if !! end program example_equality !!``` elemental module function eqv_large(set1, set2) result(eqv) logical :: eqv type(bitset_large), intent(in) :: set1, set2 end function eqv_large elemental module function eqv_64(set1, set2) result(eqv) logical :: eqv type(bitset_64), intent(in) :: set1, set2 end function eqv_64 end interface operator(==) interface operator(/=) !! Version: experimental !! !! Returns `.true.` if not all bits in `set1` and `set2` have the same value, !! `.false.` otherwise. The sets must have the same number of bits !! otherwise the result is undefined. !!([Specification](../page/specs/stdlib_bitsets.html#-compare-two-bitsets-to-determine-whether-any-bits-differ-in-value)) !! !!#### Example !! !!```fortran !! program example_inequality !! use stdlib_bitsets !! type(bitset_64) :: set0, set1, set2 !! call set0 % init( 33 ) !! call set1 % init( 33 ) !! call set2 % init( 33 ) !! call set1 % set( 0 ) !! call set2 % set( 32 ) !! if ( set0 /= set1 .and. set0 /= set2 .and. set1 /= set2 .and. & !! .not. set0 /= set0 .and. .not. set1 /= set1 .and. .not. & !! set2 /= set2 ) then !! write(*,*) 'Passed 64 bit inequality tests.' !! else !! error stop 'Failed 64 bit inequality tests.' !! end if !! end program example_inequality !!``` elemental module function neqv_large(set1, set2) result(neqv) logical :: neqv type(bitset_large), intent(in) :: set1, set2 end function neqv_large elemental module function neqv_64(set1, set2) result(neqv) logical :: neqv type(bitset_64), intent(in) :: set1, set2 end function neqv_64 end interface operator(/=) interface operator(>) !! Version: experimental !! !! Returns `.true.` if the bits in `set1` and `set2` differ and the !! highest order different bit is set to 1 in `set1` and to 0 in `set2`, !! `.false.` otherwise. The sets must have the same number of bits !! otherwise the result is undefined. !!([Specification](../page/specs/stdlib_bitsets.html#gt-compare-two-bitsets-to-determine-whether-the-first-is-greater-than-the-other)) !! !!#### Example !! !!```fortran !! program example_gt !! use stdlib_bitsets !! type(bitset_64) :: set0, set1, set2 !! call set0 % init( 33 ) !! call set1 % init( 33 ) !! call set2 % init( 33 ) !! call set1 % set( 0 ) !! call set2 % set( 32 ) !! if ( set1 > set0 .and. set2 > set1 .and. set2 > set0 .and. & !! .not. set0 > set0 .and. .not. set0 > set1 .and. .not. & !! set1 > set2 ) then !! write(*,*) 'Passed 64 bit greater than tests.' !! else !! error stop 'Failed 64 bit greater than tests.' !! end if !! end program example_gt !!``` elemental module function gt_large(set1, set2) result(gt) logical :: gt type(bitset_large), intent(in) :: set1, set2 end function gt_large elemental module function gt_64(set1, set2) result(gt) logical :: gt type(bitset_64), intent(in) :: set1, set2 end function gt_64 end interface operator(>) interface operator(>=) !! Version: experimental !! !! Returns `.true.` if the bits in `set1` and `set2` are the same or the !! highest order different bit is set to 1 in `set1` and to 0 in `set2`, !! `.false.` otherwise. The sets must have the same number of bits !! otherwise the result is undefined. !! ([Specification](../page/specs/stdlib_bitsets.html#gt-compare-two-bitsets-to-determine-whether-the-first-is-greater-than-or-equal-to-the-second)) !! !!#### Example !! !!```fortran !! program example_ge !! use stdlib_bitsets !! type(bitset_64) :: set0, set1, set2 !! call set0 % init( 33 ) !! call set1 % init( 33 ) !! call set2 % init( 33 ) !! call set1 % set( 0 ) !! call set2 % set( 32 ) !! if ( set1 >= set0 .and. set2 >= set1 .and. set2 >= set0 .and. & !! set0 >= set0 .and. set1 >= set1 .and. set2 >= set2 .and. & !! .not. set0 >= set1 .and. .not. set0 >= set2 .and. .not. & !! set1 >= set2 ) then !! write(*,*) 'Passed 64 bit greater than or equals tests.' !! else !! error stop 'Failed 64 bit greater than or equals tests.' !! end if !! end program example_ge !!``` elemental module function ge_large(set1, set2) result(ge) logical :: ge type(bitset_large), intent(in) :: set1, set2 end function ge_large elemental module function ge_64(set1, set2) result(ge) logical :: ge type(bitset_64), intent(in) :: set1, set2 end function ge_64 end interface operator(>=) interface operator(<) !! Version: experimental !! !! Returns `.true.` if the bits in `set1` and `set2` differ and the !! highest order different bit is set to 0 in `set1` and to 1 in `set2`, !! `.false.` otherwise. The sets must have the same number of bits !! otherwise the result is undefined. !!([Specification](../page/specs/stdlib_bitsets.html#lt-compare-two-bitsets-to-determine-whether-the-first-is-less-than-the-other)) !! !!#### Example !! !!```fortran !! program example_lt !! use stdlib_bitsets !! type(bitset_64) :: set0, set1, set2 !! call set0 % init( 33 ) !! call set1 % init( 33 ) !! call set2 % init( 33 ) !! call set1 % set( 0 ) !! call set2 % set( 32 ) !! if ( set0 < set1 .and. set1 < set2 .and. set0 < set2 .and. & !! .not. set0 < set0 .and. .not. set2 < set0 .and. .not. & !! set2 < set1 ) then !! write(*,*) 'Passed 64 bit less than tests.' !! else !! error stop 'Failed 64 bit less than tests.' !! end if !! end program example_lt !!``` elemental module function lt_large(set1, set2) result(lt) logical :: lt type(bitset_large), intent(in) :: set1, set2 end function lt_large elemental module function lt_64(set1, set2) result(lt) logical :: lt type(bitset_64), intent(in) :: set1, set2 end function lt_64 end interface operator(<) interface operator(<=) !! Version: experimental !! !! Returns `.true.` if the bits in `set1` and `set2` are the same or the !! highest order different bit is set to 0 in `set1` and to 1 in `set2`, !! `.false.` otherwise. The sets must have the same number of bits !! otherwise the result is undefined. !!([Specification](../page/specs/stdlib_bitsets.html#lt-compare-two-bitsets-to-determine-whether-the-first-is-less-than-or-equal-to-the-other)) !! !!#### Example !! !!```fortran !! program example_le !! use stdlib_bitsets !! type(bitset_64) :: set0, set1, set2 !! call set0 % init( 33 ) !! call set1 % init( 33 ) !! call set2 % init( 33 ) !! call set1 % set( 0 ) !! call set2 % set( 32 ) !! if ( set0 <= set1 .and. set1 <= set2 .and. set0 <= set2 .and. & !! set0 <= set0 .and. set1 <= set1 .and. set2 <= set2 .and. & !! .not. set1 <= set0 .and. .not. set2 <= set0 .and. .not. & !! set2 <= set1 ) then !! write(*,*) 'Passed 64 bit less than or equal tests.' !! else !! error stop 'Failed 64 bit less than or equal tests.' !! end if !! end program example_le !!``` elemental module function le_large(set1, set2) result(le) logical :: le type(bitset_large), intent(in) :: set1, set2 end function le_large elemental module function le_64(set1, set2) result(le) logical :: le type(bitset_64), intent(in) :: set1, set2 end function le_64 end interface operator(<=) interface error_handler module subroutine error_handler( message, error, status, & module, procedure ) character(*), intent(in) :: message integer, intent(in) :: error integer, intent(out), optional :: status character(*), intent(in), optional :: module character(*), intent(in), optional :: procedure end subroutine error_handler end interface error_handler contains elemental function bits(self) !! Version: experimental !! !! Returns the number of bit positions in `self`. integer(bits_kind) :: bits class(bitset_type), intent(in) :: self bits = self % num_bits return end function bits module subroutine error_handler( message, error, status, module, procedure ) character(*), intent(in) :: message integer, intent(in) :: error integer, intent(out), optional :: status character(*), intent(in), optional :: module character(*), intent(in), optional :: procedure if ( present(status) ) then status = error else if ( present(module) ) then if ( present(procedure) ) then write(error_unit, '(a)') trim(module) // ' % ' // & trim(procedure) // ': ' // trim(message) else write(error_unit, '(a)') trim(module) // ' % N/A: ' // & trim(message) end if else if ( present(procedure) ) then write(error_unit, '(a)') trim(procedure) // ': ' // & trim(message) else write(error_unit, '(a)') trim(message) end if select case(error) case( alloc_fault ) error stop 'A memory allocation failed.' case( array_size_invalid_error ) error stop "An array size was invalid." case( char_string_invalid_error ) error stop "A character string had an invalid character." case( char_string_too_large_error ) error stop "A character string was too large." case( char_string_too_small_error ) error stop "A character string was too small." case( eof_failure ) error stop "An End-Of-File failure occurred on a READ " // & "statement." case( index_invalid_error ) error stop "An index was invalid." case( integer_overflow_error ) error stop "An integer overflow error occurred." case( read_failure ) error stop "A failure occurred in a READ statement." case( write_failure ) error stop "A failure occurred on a WRITE statement." end select end if end subroutine error_handler end module stdlib_bitsets fortran-lang-stdlib-0ede301/src/strings/0000775000175000017500000000000015135654166020446 5ustar alastairalastairfortran-lang-stdlib-0ede301/src/strings/stdlib_string_type.fypp0000664000175000017500000013004615135654166025262 0ustar alastairalastair! SPDX-Identifier: MIT #:include "common.fypp" !> Implementation of a string type to hold an arbitrary sequence of characters. !> !> This module provides string type compatible with all Fortran instrinsic character !> procedures as well as overloaded operators for working with character variables. !> !> A string type can be easily constructed by creating a new instance from a !> character variable or literal by invoking its constructor or by assigning it !> to a string type. Generally, the string type behaves similar to a deferred !> length character in most regards but adds memory access safety. !> !> The specification of this module is available [here](../page/specs/stdlib_string_type.html). module stdlib_string_type use stdlib_ascii, only: to_lower_ => to_lower, to_upper_ => to_upper, & & to_title_ => to_title, to_sentence_ => to_sentence, reverse_ => reverse use stdlib_kinds, only : int8, int16, int32, int64, lk, c_bool use stdlib_optval, only: optval implicit none private public :: string_type public :: len, len_trim, trim, index, scan, verify, repeat, adjustr, adjustl public :: lgt, lge, llt, lle, char, ichar, iachar public :: to_lower, to_upper, to_title, to_sentence, reverse, move public :: assignment(=) public :: operator(>), operator(>=), operator(<), operator(<=) public :: operator(==), operator(/=), operator(//) public :: write(formatted), write(unformatted) public :: read(formatted), read(unformatted) integer, parameter :: long = selected_int_kind(18) !> String type holding an arbitrary sequence of characters. type :: string_type ! Use the sequence statement below as a hack to prevent extending this type. ! It is not used for storage association. sequence private character(len=:), allocatable :: raw end type string_type !> Returns the length of the character sequence represented by the string. !> !> This method is elemental and returns a default integer scalar value. interface len module procedure :: len_string end interface len !> Constructor for new string instances interface string_type elemental module function new_string(string) result(new) character(len=*), intent(in), optional :: string type(string_type) :: new end function new_string #:for kind in INT_KINDS elemental module function new_string_from_integer_${kind}$(val) result(new) integer(${kind}$), intent(in) :: val type(string_type) :: new end function new_string_from_integer_${kind}$ #:endfor #:for kind in LOG_KINDS elemental module function new_string_from_logical_${kind}$(val) result(new) logical(${kind}$), intent(in) :: val type(string_type) :: new end function new_string_from_logical_${kind}$ #:endfor end interface string_type !> Returns the length of the character sequence without trailing spaces !> represented by the string. !> !> This method is elemental and returns a default integer scalar value. interface len_trim module procedure :: len_trim_string end interface len_trim !> Returns the character sequence hold by the string without trailing spaces. !> !> This method is elemental and returns a scalar character value. interface trim module procedure :: trim_string end interface trim !> Left-adjust the character sequence represented by the string. !> The length of the character sequence remains unchanged. !> !> This method is elemental and returns a scalar character value. interface adjustl module procedure :: adjustl_string end interface adjustl !> Right-adjust the character sequence represented by the string. !> The length of the character sequence remains unchanged. !> !> This method is elemental and returns a scalar character value. interface adjustr module procedure :: adjustr_string end interface adjustr !> Repeats the character sequence hold by the string by the number of !> specified copies. !> !> This method is elemental and returns a scalar character value. interface repeat module procedure :: repeat_string end interface repeat !> Returns the lowercase version of the character sequence hold by the input string !> !> This method is Elemental and returns a new string_type instance which holds this !> lowercase character sequence interface to_lower module procedure :: to_lower_string end interface to_lower !> Returns the uppercase version of the character sequence hold by the input string !> !> This method is Elemental and returns a new string_type instance which holds this !> uppercase character sequence interface to_upper module procedure :: to_upper_string end interface to_upper !> Returns the titlecase version of the character sequence hold by the input string !> !> This method is Elemental and returns a new string_type instance which holds this !> titlecase character sequence interface to_title module procedure :: to_title_string end interface to_title !> Returns the sentencecase version of the character sequence hold by the input string !> !> This method is elemental and returns a new string_type instance which holds this !> sentencecase character sequence interface to_sentence module procedure :: to_sentence_string end interface to_sentence !> Reverses the character sequence hold by the input string !> !> This method is elemental and returns a new string_type instance which holds this !> reverse character sequence interface reverse module procedure :: reverse_string end interface reverse !> Return the character sequence represented by the string. !> !> This method is elemental and returns a scalar character value. interface char module procedure :: char_string module procedure :: char_string_pos module procedure :: char_string_range end interface char !> Character-to-integer conversion function. !> !> This method is elemental and returns a default integer scalar value. interface ichar module procedure :: ichar_string end interface ichar !> Code in ASCII collating sequence. !> !> This method is elemental and returns a default integer scalar value. interface iachar module procedure :: iachar_string end interface iachar !> Position of a *substring* within a *string*. !> !> Returns the position of the start of the leftmost or rightmost occurrence !> of string *substring* in *string*, counting from one. If *substring* is not !> present in *string*, zero is returned. !> !> This method is elemental and returns a default integer scalar value. interface index module procedure :: index_string_string module procedure :: index_string_char module procedure :: index_char_string end interface index !> Scan a *string* for the presence of a *set* of characters. Scans a *string* for !> any of the characters in a *set* of characters. !> !> If *back* is either absent or *false*, this function returns the position !> of the leftmost character of *string* that is in *set*. If *back* is *true*, !> the rightmost position is returned. If no character of *set* is found in !> *string*, the result is zero. !> !> This method is elemental and returns a default integer scalar value. interface scan module procedure :: scan_string_string module procedure :: scan_string_char module procedure :: scan_char_string end interface scan !> Scan a string for the absence of a set of characters. Verifies that all !> the characters in string belong to the set of characters in set. !> !> If *back* is either absent or *false*, this function returns the position !> of the leftmost character of *string* that is not in *set*. If *back* is *true*, !> the rightmost position is returned. If all characters of *string* are found !> in *set*, the result is zero. !> !> This method is elemental and returns a default integer scalar value. interface verify module procedure :: verify_string_string module procedure :: verify_string_char module procedure :: verify_char_string end interface verify !> Version: experimental !> !> Moves the allocated character scalar from 'from' to 'to' !> [Specifications](../page/specs/stdlib_string_type.html#move) interface move module procedure :: move_string_string module procedure :: move_string_char module procedure :: move_char_string module procedure :: move_char_char end interface move !> Lexically compare the order of two character sequences being greater, !> The left-hand side, the right-hand side or both character sequences can !> be represented by a string. !> !> This method is elemental and returns a default logical scalar value. interface lgt module procedure :: lgt_string_string module procedure :: lgt_string_char module procedure :: lgt_char_string end interface lgt !> Lexically compare the order of two character sequences being less, !> The left-hand side, the right-hand side or both character sequences can !> be represented by a string. !> !> This method is elemental and returns a default logical scalar value. interface llt module procedure :: llt_string_string module procedure :: llt_string_char module procedure :: llt_char_string end interface llt !> Lexically compare the order of two character sequences being greater equal, !> The left-hand side, the right-hand side or both character sequences can !> be represented by a string. !> !> This method is elemental and returns a default logical scalar value. interface lge module procedure :: lge_string_string module procedure :: lge_string_char module procedure :: lge_char_string end interface lge !> Lexically compare the order of two character sequences being less equal, !> The left-hand side, the right-hand side or both character sequences can !> be represented by a string. !> !> This method is elemental and returns a default logical scalar value. interface lle module procedure :: lle_string_string module procedure :: lle_string_char module procedure :: lle_char_string end interface lle !> Assign a character sequence to a string. interface assignment(=) module procedure :: assign_string_char end interface assignment(=) !> Compare two character sequences for being greater, the left-hand side, !> the right-hand side or both character sequences can be represented by !> a string. !> !> This operator is elemental and returns a default logical scalar value. interface operator(>) module procedure :: gt_string_string module procedure :: gt_string_char module procedure :: gt_char_string end interface operator(>) !> Compare two character sequences for being less, the left-hand side, !> the right-hand side or both character sequences can be represented by !> a string. !> !> This operator is elemental and returns a default logical scalar value. interface operator(<) module procedure :: lt_string_string module procedure :: lt_string_char module procedure :: lt_char_string end interface operator(<) !> Compare two character sequences for being greater than, the left-hand side, !> the right-hand side or both character sequences can be represented by !> a string. !> !> This operator is elemental and returns a default logical scalar value. interface operator(>=) module procedure :: ge_string_string module procedure :: ge_string_char module procedure :: ge_char_string end interface operator(>=) !> Compare two character sequences for being less than, the left-hand side, !> the right-hand side or both character sequences can be represented by !> a string. !> !> This operator is elemental and returns a default logical scalar value. interface operator(<=) module procedure :: le_string_string module procedure :: le_string_char module procedure :: le_char_string end interface operator(<=) !> Compare two character sequences for equality, the left-hand side, !> the right-hand side or both character sequences can be represented by !> a string. !> !> This operator is elemental and returns a default logical scalar value. interface operator(==) module procedure :: eq_string_string module procedure :: eq_string_char module procedure :: eq_char_string end interface operator(==) !> Compare two character sequences for inequality, the left-hand side, !> the right-hand side or both character sequences can be represented by !> a string. !> !> This operator is elemental and returns a default logical scalar value. interface operator(/=) module procedure :: ne_string_string module procedure :: ne_string_char module procedure :: ne_char_string end interface operator(/=) !> Concatenate two character sequences, the left-hand side, the right-hand side !> or both character sequences can be represented by a string. !> !> This operator is elemental and returns a scalar character value. interface operator(//) module procedure :: concat_string_string module procedure :: concat_string_char module procedure :: concat_char_string end interface operator(//) !> Write the character sequence hold by the string to a connected formatted !> unit. interface write(formatted) module procedure :: write_formatted end interface !> Write the character sequence hold by the string to a connected unformatted !> unit. interface write(unformatted) module procedure :: write_unformatted end interface !> Read a character sequence from a connected unformatted unit into the string. interface read(formatted) module procedure :: read_formatted end interface !> Read a character sequence from a connected unformatted unit into the string. interface read(unformatted) module procedure :: read_unformatted end interface contains !> Assign a character sequence to a string. elemental subroutine assign_string_char(lhs, rhs) type(string_type), intent(inout) :: lhs character(len=*), intent(in) :: rhs lhs%raw = rhs end subroutine assign_string_char !> Returns the length of the character sequence represented by the string. elemental function len_string(string) result(length) type(string_type), intent(in) :: string integer :: length if (allocated(string%raw)) then length = len(string%raw) else length = 0 end if end function len_string !> Returns the length of the character sequence without trailing spaces !> represented by the string. elemental function len_trim_string(string) result(length) type(string_type), intent(in) :: string integer :: length length = merge(len_trim(string%raw), 0, allocated(string%raw)) end function len_trim_string !> Character-to-integer conversion function. elemental function ichar_string(string) result(ich) type(string_type), intent(in) :: string integer :: ich if (allocated(string%raw) .and. len(string) > 0) then ich = ichar(string%raw(1:1)) else ich = 0 end if end function ichar_string !> Code in ASCII collating sequence. elemental function iachar_string(string) result(ich) type(string_type), intent(in) :: string integer :: ich if (allocated(string%raw) .and. len(string) > 0) then ich = iachar(string%raw(1:1)) else ich = 0 end if end function iachar_string !> Return the character sequence represented by the string. pure function char_string(string) result(character_string) type(string_type), intent(in) :: string character(len=len(string)) :: character_string character_string = maybe(string) end function char_string !> Return the character sequence represented by the string. elemental function char_string_pos(string, pos) result(character_string) type(string_type), intent(in) :: string integer, intent(in) :: pos character(len=1) :: character_string character_string = merge(string%raw(pos:pos), ' ', allocated(string%raw)) end function char_string_pos !> Return the character sequence represented by the string. pure function char_string_range(string, start, last) result(character_string) type(string_type), intent(in) :: string integer, intent(in) :: start integer, intent(in) :: last character(len=last-start+1) :: character_string character_string = merge(string%raw(int(start, long):int(last, long)), & repeat(' ', int(len(character_string), long)), allocated(string%raw)) end function char_string_range !> Returns the character sequence hold by the string without trailing spaces. elemental function trim_string(string) result(trimmed_string) type(string_type), intent(in) :: string type(string_type) :: trimmed_string trimmed_string = trim(maybe(string)) end function trim_string !> Left-adjust the character sequence represented by the string. !> The length of the character sequence remains unchanged. elemental function adjustl_string(string) result(adjusted_string) type(string_type), intent(in) :: string type(string_type) :: adjusted_string adjusted_string = adjustl(maybe(string)) end function adjustl_string !> Right-adjust the character sequence represented by the string. !> The length of the character sequence remains unchanged. elemental function adjustr_string(string) result(adjusted_string) type(string_type), intent(in) :: string type(string_type) :: adjusted_string adjusted_string = adjustr(maybe(string)) end function adjustr_string !> Repeats the character sequence hold by the string by the number of !> specified copies. elemental function repeat_string(string, ncopies) result(repeated_string) type(string_type), intent(in) :: string integer, intent(in) :: ncopies type(string_type) :: repeated_string repeated_string = repeat(maybe(string), ncopies) end function repeat_string !> Convert the character sequence hold by the input string to lower case elemental function to_lower_string(string) result(lowercase_string) type(string_type), intent(in) :: string type(string_type) :: lowercase_string lowercase_string%raw = to_lower_(maybe(string)) end function to_lower_string !> Convert the character sequence hold by the input string to upper case elemental function to_upper_string(string) result(uppercase_string) type(string_type), intent(in) :: string type(string_type) :: uppercase_string uppercase_string%raw = to_upper_(maybe(string)) end function to_upper_string !> Convert the character sequence hold by the input string to title case elemental function to_title_string(string) result(titlecase_string) type(string_type), intent(in) :: string type(string_type) :: titlecase_string titlecase_string%raw = to_title_(maybe(string)) end function to_title_string !> Convert the character sequence hold by the input string to sentence case elemental function to_sentence_string(string) result(sentence_string) type(string_type), intent(in) :: string type(string_type) :: sentence_string sentence_string%raw = to_sentence_(maybe(string)) end function to_sentence_string !> Reverse the character sequence hold by the input string elemental function reverse_string(string) result(reversed_string) type(string_type), intent(in) :: string type(string_type) :: reversed_string reversed_string%raw = reverse_(maybe(string)) end function reverse_string !> Position of a sequence of character within a character sequence. !> In this version both character sequences are represented by a string. elemental function index_string_string(string, substring, back) result(pos) type(string_type), intent(in) :: string type(string_type), intent(in) :: substring logical, intent(in), optional :: back integer :: pos pos = index(maybe(string), maybe(substring), optval(back, .false.)) end function index_string_string !> Position of a sequence of character within a character sequence. !> In this version the main character sequence is represented by a string. elemental function index_string_char(string, substring, back) result(pos) type(string_type), intent(in) :: string character(len=*), intent(in) :: substring logical, intent(in), optional :: back integer :: pos pos = index(maybe(string), substring, optval(back, .false.)) end function index_string_char !> Position of a sequence of character within a character sequence. !> In this version the sub character sequence is represented by a string. elemental function index_char_string(string, substring, back) result(pos) character(len=*), intent(in) :: string type(string_type), intent(in) :: substring logical, intent(in), optional :: back integer :: pos pos = index(string, maybe(substring), optval(back, .false.)) end function index_char_string !> Scan a character sequence for any of the characters in a set of characters. !> In this version both the character sequence and the character set are !> represented by a string. elemental function scan_string_string(string, set, back) result(pos) type(string_type), intent(in) :: string type(string_type), intent(in) :: set logical, intent(in), optional :: back integer :: pos pos = scan(maybe(string), maybe(set), optval(back, .false.)) end function scan_string_string !> Scan a character sequence for any of the characters in a set of characters. !> In this version the character sequences is represented by a string. elemental function scan_string_char(string, set, back) result(pos) type(string_type), intent(in) :: string character(len=*), intent(in) :: set logical, intent(in), optional :: back integer :: pos pos = scan(maybe(string), set, optval(back, .false.)) end function scan_string_char !> Scan a character sequence for any of the characters in a set of characters. !> In this version the set of characters is represented by a string. elemental function scan_char_string(string, set, back) result(pos) character(len=*), intent(in) :: string type(string_type), intent(in) :: set logical, intent(in), optional :: back integer :: pos pos = scan(string, maybe(set), optval(back, .false.)) end function scan_char_string !> Verify a character sequence for the absence any of the characters in !> a set of characters. In this version both the character sequence and !> the character set are represented by a string. elemental function verify_string_string(string, set, back) result(pos) type(string_type), intent(in) :: string type(string_type), intent(in) :: set logical, intent(in), optional :: back integer :: pos pos = verify(maybe(string), maybe(set), optval(back, .false.)) end function verify_string_string !> Verify a character sequence for the absence any of the characters in !> a set of characters. In this version the character sequences is !> represented by a string. elemental function verify_string_char(string, set, back) result(pos) type(string_type), intent(in) :: string character(len=*), intent(in) :: set logical, intent(in), optional :: back integer :: pos pos = verify(maybe(string), set, optval(back, .false.)) end function verify_string_char !> Verify a character sequence for the absence any of the characters in !> a set of characters. In this version the set of characters is !> represented by a string. elemental function verify_char_string(string, set, back) result(pos) character(len=*), intent(in) :: string type(string_type), intent(in) :: set logical, intent(in), optional :: back integer :: pos pos = verify(string, maybe(set), optval(back, .false.)) end function verify_char_string !> Moves the allocated character scalar from 'from' to 'to' !> No output elemental subroutine move_string_string(from, to) type(string_type), intent(inout), target :: from type(string_type), intent(inout), target :: to type(string_type), pointer :: fromp fromp => from if (associated(fromp,to)) return call move_alloc(from%raw, to%raw) end subroutine move_string_string !> Moves the allocated character scalar from 'from' to 'to' !> No output pure subroutine move_string_char(from, to) type(string_type), intent(inout) :: from character(len=:), intent(out), allocatable :: to call move_alloc(from%raw, to) end subroutine move_string_char !> Moves the allocated character scalar from 'from' to 'to' !> No output pure subroutine move_char_string(from, to) character(len=:), intent(inout), allocatable :: from type(string_type), intent(out) :: to call move_alloc(from, to%raw) end subroutine move_char_string !> Moves the allocated character scalar from 'from' to 'to' !> No output pure subroutine move_char_char(from, to) character(len=:), intent(inout), allocatable :: from character(len=:), intent(out), allocatable :: to call move_alloc(from, to) end subroutine move_char_char !> Compare two character sequences for being greater. !> In this version both character sequences are by a string. elemental function gt_string_string(lhs, rhs) result(is_gt) type(string_type), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_gt is_gt = maybe(lhs) > maybe(rhs) end function gt_string_string !> Compare two character sequences for being greater. !> In this version the left-hand side character sequences is by a string. elemental function gt_string_char(lhs, rhs) result(is_gt) type(string_type), intent(in) :: lhs character(len=*), intent(in) :: rhs logical :: is_gt is_gt = maybe(lhs) > rhs end function gt_string_char !> Compare two character sequences for being greater. !> In this version the right-hand side character sequences is by a string. elemental function gt_char_string(lhs, rhs) result(is_gt) character(len=*), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_gt is_gt = lhs > maybe(rhs) end function gt_char_string !> Compare two character sequences for being less. !> In this version both character sequences are by a string. elemental function lt_string_string(lhs, rhs) result(is_lt) type(string_type), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_lt is_lt = rhs > lhs end function lt_string_string !> Compare two character sequences for being less. !> In this version the left-hand side character sequences is by a string. elemental function lt_string_char(lhs, rhs) result(is_lt) type(string_type), intent(in) :: lhs character(len=*), intent(in) :: rhs logical :: is_lt is_lt = rhs > lhs end function lt_string_char !> Compare two character sequences for being less. !> In this version the right-hand side character sequences is by a string. elemental function lt_char_string(lhs, rhs) result(is_lt) character(len=*), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_lt is_lt = rhs > lhs end function lt_char_string !> Compare two character sequences for being greater or equal. !> In this version both character sequences are by a string. elemental function ge_string_string(lhs, rhs) result(is_ge) type(string_type), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_ge is_ge = .not. (rhs > lhs) end function ge_string_string !> Compare two character sequences for being greater or equal. !> In this version the left-hand side character sequences is by a string. elemental function ge_string_char(lhs, rhs) result(is_ge) type(string_type), intent(in) :: lhs character(len=*), intent(in) :: rhs logical :: is_ge is_ge = .not. (rhs > lhs) end function ge_string_char !> Compare two character sequences for being greater or equal !> In this version the right-hand side character sequences is by a string. elemental function ge_char_string(lhs, rhs) result(is_ge) character(len=*), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_ge is_ge = .not. (rhs > lhs) end function ge_char_string !> Compare two character sequences for being less or equal. !> In this version both character sequences are by a string. elemental function le_string_string(lhs, rhs) result(is_le) type(string_type), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_le is_le = .not. (lhs > rhs) end function le_string_string !> Compare two character sequences for being less or equal. !> In this version the left-hand side character sequences is by a string. elemental function le_string_char(lhs, rhs) result(is_le) type(string_type), intent(in) :: lhs character(len=*), intent(in) :: rhs logical :: is_le is_le = .not. (lhs > rhs) end function le_string_char !> Compare two character sequences for being less or equal !> In this version the right-hand side character sequences is by a string. elemental function le_char_string(lhs, rhs) result(is_le) character(len=*), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_le is_le = .not. (lhs > rhs) end function le_char_string !> Compare two character sequences for equality. !> In this version both character sequences are by a string. elemental function eq_string_string(lhs, rhs) result(is_eq) type(string_type), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_eq is_eq = .not.(lhs > rhs) if (is_eq) then is_eq = .not.(rhs > lhs) end if end function eq_string_string !> Compare two character sequences for equality. !> In this version the left-hand side character sequences is by a string. elemental function eq_string_char(lhs, rhs) result(is_eq) type(string_type), intent(in) :: lhs character(len=*), intent(in) :: rhs logical :: is_eq is_eq = .not.(lhs > rhs) if (is_eq) then is_eq = .not.(rhs > lhs) end if end function eq_string_char !> Compare two character sequences for equality. !> In this version the right-hand side character sequences is by a string. elemental function eq_char_string(lhs, rhs) result(is_eq) character(len=*), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_eq is_eq = .not.(lhs > rhs) if (is_eq) then is_eq = .not.(rhs > lhs) end if end function eq_char_string !> Compare two character sequences for inequality. !> In this version both character sequences are by a string. elemental function ne_string_string(lhs, rhs) result(is_ne) type(string_type), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_ne is_ne = lhs > rhs if (.not.is_ne) then is_ne = rhs > lhs end if end function ne_string_string !> Compare two character sequences for inequality. !> In this version the left-hand side character sequences is by a string. elemental function ne_string_char(lhs, rhs) result(is_ne) type(string_type), intent(in) :: lhs character(len=*), intent(in) :: rhs logical :: is_ne is_ne = lhs > rhs if (.not.is_ne) then is_ne = rhs > lhs end if end function ne_string_char !> Compare two character sequences for inequality. !> In this version the right-hand side character sequences is by a string. elemental function ne_char_string(lhs, rhs) result(is_ne) character(len=*), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_ne is_ne = lhs > rhs if (.not.is_ne) then is_ne = rhs > lhs end if end function ne_char_string !> Lexically compare two character sequences for being greater. !> In this version both character sequences are by a string. elemental function lgt_string_string(lhs, rhs) result(is_lgt) type(string_type), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_lgt is_lgt = lgt(maybe(lhs), maybe(rhs)) end function lgt_string_string !> Lexically compare two character sequences for being greater. !> In this version the left-hand side character sequences is by a string. elemental function lgt_string_char(lhs, rhs) result(is_lgt) type(string_type), intent(in) :: lhs character(len=*), intent(in) :: rhs logical :: is_lgt is_lgt = lgt(maybe(lhs), rhs) end function lgt_string_char !> Lexically compare two character sequences for being greater. !> In this version the right-hand side character sequences is by a string. elemental function lgt_char_string(lhs, rhs) result(is_lgt) character(len=*), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_lgt is_lgt = lgt(lhs, maybe(rhs)) end function lgt_char_string !> Lexically compare two character sequences for being less. !> In this version both character sequences are by a string. elemental function llt_string_string(lhs, rhs) result(is_llt) type(string_type), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_llt is_llt = llt(maybe(lhs), maybe(rhs)) end function llt_string_string !> Lexically compare two character sequences for being less. !> In this version the left-hand side character sequences is by a string. elemental function llt_string_char(lhs, rhs) result(is_llt) type(string_type), intent(in) :: lhs character(len=*), intent(in) :: rhs logical :: is_llt is_llt = llt(maybe(lhs), rhs) end function llt_string_char !> Lexically compare two character sequences for being less. !> In this version the right-hand side character sequences is by a string. elemental function llt_char_string(lhs, rhs) result(is_llt) character(len=*), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_llt is_llt = llt(lhs, maybe(rhs)) end function llt_char_string !> Lexically compare two character sequences for being greater or equal. !> In this version both character sequences are by a string. elemental function lge_string_string(lhs, rhs) result(is_lge) type(string_type), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_lge is_lge = lge(maybe(lhs), maybe(rhs)) end function lge_string_string !> Lexically compare two character sequences for being greater or equal. !> In this version the left-hand side character sequences is by a string. elemental function lge_string_char(lhs, rhs) result(is_lge) type(string_type), intent(in) :: lhs character(len=*), intent(in) :: rhs logical :: is_lge is_lge = lge(maybe(lhs), rhs) end function lge_string_char !> Lexically compare two character sequences for being greater or equal !> In this version the right-hand side character sequences is by a string. elemental function lge_char_string(lhs, rhs) result(is_lge) character(len=*), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_lge is_lge = lge(lhs, maybe(rhs)) end function lge_char_string !> Lexically compare two character sequences for being less or equal. !> In this version both character sequences are by a string. elemental function lle_string_string(lhs, rhs) result(is_lle) type(string_type), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_lle is_lle = lle(maybe(lhs), maybe(rhs)) end function lle_string_string !> Lexically compare two character sequences for being less or equal. !> In this version the left-hand side character sequences is by a string. elemental function lle_string_char(lhs, rhs) result(is_lle) type(string_type), intent(in) :: lhs character(len=*), intent(in) :: rhs logical :: is_lle is_lle = lle(maybe(lhs), rhs) end function lle_string_char !> Lexically compare two character sequences for being less or equal !> In this version the right-hand side character sequences is by a string. elemental function lle_char_string(lhs, rhs) result(is_lle) character(len=*), intent(in) :: lhs type(string_type), intent(in) :: rhs logical :: is_lle is_lle = lle(lhs, maybe(rhs)) end function lle_char_string !> Concatenate two character sequences. !> In this version both character sequences are by a string. elemental function concat_string_string(lhs, rhs) result(string) type(string_type), intent(in) :: lhs type(string_type), intent(in) :: rhs type(string_type) :: string string%raw = maybe(lhs) // maybe(rhs) end function concat_string_string !> Concatenate two character sequences. !> In this version the left-hand side character sequences is by a string. elemental function concat_string_char(lhs, rhs) result(string) type(string_type), intent(in) :: lhs character(len=*), intent(in) :: rhs type(string_type) :: string string%raw = maybe(lhs) // rhs end function concat_string_char !> Concatenate two character sequences. !> In this version the right-hand side character sequences is by a string. elemental function concat_char_string(lhs, rhs) result(string) character(len=*), intent(in) :: lhs type(string_type), intent(in) :: rhs type(string_type) :: string string%raw = lhs // maybe(rhs) end function concat_char_string !> Write the character sequence hold by the string to a connected unformatted !> unit. subroutine write_unformatted(string, unit, iostat, iomsg) type(string_type), intent(in) :: string integer, intent(in) :: unit integer, intent(out) :: iostat character(len=*), intent(inout) :: iomsg write(unit, iostat=iostat, iomsg=iomsg) int(len(string), long) if (iostat == 0) then write(unit, iostat=iostat, iomsg=iomsg) maybe(string) end if end subroutine write_unformatted !> Write the character sequence hold by the string to a connected formatted !> unit. subroutine write_formatted(string, unit, iotype, v_list, iostat, iomsg) type(string_type), intent(in) :: string integer, intent(in) :: unit character(len=*), intent(in) :: iotype integer, intent(in) :: v_list(:) integer, intent(out) :: iostat character(len=*), intent(inout) :: iomsg select case(iotype) case("LISTDIRECTED") write(unit, '(a)', iostat=iostat, iomsg=iomsg) maybe(string) case("NAMELIST") error stop "[Fatal] This implementation does not support namelist output" case default ! DT* select case(size(v_list)) case(0) ! DT write(unit, '(a)', iostat=iostat, iomsg=iomsg) maybe(string) case default error stop "[Fatal] This implementation does not support v_list formatters" end select end select end subroutine write_formatted !> Read a character sequence from a connected unformatted unit into the string. subroutine read_unformatted(string, unit, iostat, iomsg) type(string_type), intent(inout) :: string integer, intent(in) :: unit integer, intent(out) :: iostat character(len=*), intent(inout) :: iomsg character(len=:), allocatable :: buffer integer(long) :: chunk read(unit, iostat=iostat, iomsg=iomsg) chunk if (iostat == 0) then allocate(character(len=chunk) :: buffer) read(unit, iostat=iostat, iomsg=iomsg) buffer string%raw = buffer end if end subroutine read_unformatted !> Read a character sequence from a connected formatted unit into the string. subroutine read_formatted(string, unit, iotype, v_list, iostat, iomsg) type(string_type), intent(inout) :: string integer, intent(in) :: unit character(len=*), intent(in) :: iotype integer, intent(in) :: v_list(:) integer, intent(out) :: iostat character(len=*), intent(inout) :: iomsg character(len=:), allocatable :: line call unused_dummy_argument(v_list) select case(iotype) case("LISTDIRECTED") call read_line(unit, line, iostat, iomsg) case("NAMELIST") error stop "[Fatal] This implementation does not support namelist input" case default ! DT* error stop "[Fatal] This implementation does not support dt formatters" end select string%raw = line contains !> Internal routine to read a whole record from a formatted unit subroutine read_line(unit, line, iostat, iomsg) integer, intent(in) :: unit character(len=:), allocatable, intent(out) :: line integer, intent(out) :: iostat character(len=*), intent(inout) :: iomsg integer, parameter :: buffer_size = 512 character(len=buffer_size) :: buffer integer :: chunk line = '' do read(unit, '(a)', iostat=iostat, iomsg=iomsg, size=chunk, advance='no') & buffer if (iostat > 0) exit line = line // buffer(:chunk) if (iostat < 0) exit end do if (is_iostat_eor(iostat)) then iostat = 0 end if end subroutine read_line end subroutine read_formatted !> Do nothing but mark an unused dummy argument as such to acknowledge compile !> time warning like: !> !> Warning: Unused dummy argument ‘dummy’ at (1) [-Wunused-dummy-argument] !> !> We deeply trust in the compiler to inline and optimize this piece of code away. elemental subroutine unused_dummy_argument(dummy) class(*), intent(in) :: dummy associate(dummy => dummy); end associate end subroutine unused_dummy_argument !> Safely return the character sequences represented by the string pure function maybe(string) result(maybe_string) type(string_type), intent(in) :: string character(len=len(string)) :: maybe_string if (allocated(string%raw)) then maybe_string = string%raw else maybe_string = '' end if end function maybe end module stdlib_string_type fortran-lang-stdlib-0ede301/src/strings/CMakeLists.txt0000664000175000017500000000063215135654166023207 0ustar alastairalastairset(strings_fppFiles stdlib_string_type.fypp stdlib_string_type_constructor.fypp stdlib_str2num.fypp stdlib_strings_to_string.fypp stdlib_strings.fypp ) set(strings_cppFiles ) set(strings_f90Files ) configure_stdlib_target(${PROJECT_NAME}_strings strings_f90Files strings_fppFiles strings_cppFiles) target_link_libraries(${PROJECT_NAME}_strings PUBLIC ${PROJECT_NAME}_core) fortran-lang-stdlib-0ede301/src/strings/stdlib_str2num.fypp0000664000175000017500000005712515135654166024333 0ustar alastairalastair#:include "common.fypp" !> The `stdlib_str2num` module provides procedures and interfaces for conversion !> of characters to numerical types. Currently supported: `integer` and `real`. !> ([Specification](../page/specs/stdlib_str2num.html)) !> !> This code was modified from https://github.com/jalvesz/Fortran-String-to-Num by Alves Jose !> And was possible thanks to all the discussions in this thread https://fortran-lang.discourse.group/t/faster-string-to-double/ !> !> Known precisions limits of current proposal : !> Conversion to double precision is exact up to epsilon(0.0_dp) !> example: !> !> input : 123456.78901234567890123456789012345678901234567890+2 !> !> formatted read : 12345678.90123457 !> !> to_num : 12345678.90123457 !> !> difference abs : 0.1862645149230957E-08 !> !> difference rel : 0.1508742584455759E-13% !> !> Conversion to quadruple precision can deviate at about 200*epsilon(0.0_qp) !> example: !> !> input : 0.140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125E-443 !> !> formatted read : 0.140129846432481707092372958328991608E-443 !> !> to_num : 0.140129846432481707092372958328996233E-443 !> !> difference abs : 0.4625E-475 !> !> difference rel : 0.3300E-029% module stdlib_str2num use stdlib_kinds, only: sp, dp, xdp, qp, int8, int16, int32, int64 use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_positive_inf, ieee_quiet_nan implicit none private public :: to_num, to_num_from_stream integer(int8), parameter :: digit_0 = ichar('0',int8) integer(int8), parameter :: period = ichar('.',int8) - digit_0 integer(int8), parameter :: comma = ichar(',',int8) - digit_0 integer(int8), parameter :: minus_sign = ichar('-',int8) - digit_0 integer(int8), parameter :: plus_sign = ichar('+',int8) - digit_0 integer(int8), parameter :: Inf = ichar('I',int8) integer(int8), parameter :: NaN = ichar('N',int8) integer(int8), parameter :: le = ichar('e',int8) - digit_0 integer(int8), parameter :: BE = ichar('E',int8) - digit_0 integer(int8), parameter :: ld = ichar('d',int8) - digit_0 integer(int8), parameter :: BD = ichar('D',int8) - digit_0 integer(int8), parameter :: LF = 10, CR = 13, WS = 32 interface to_num !! version: experimental !! !! Conversion of strings to numbers !! ([Specification](../page/specs/stdlib_str2num.html#to-num-conversion-of-strings-to-numbers)) #:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES) module procedure to_${k1}$ #:endfor end interface interface to_num_from_stream !! version: experimental !! !! Conversion of a stream of values in a string to numbers !! ([Specification](../page/specs/stdlib_str2num.html#to-num-p-conversion-of-a-stream-of-values-in-a-strings-to-numbers)) #:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES) module procedure to_${k1}$_from_stream #:endfor end interface interface to_num_base #:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES) module procedure to_${k1}$_base #:endfor end interface contains !--------------------------------------------- ! String To Number interfaces !--------------------------------------------- #:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES) elemental function to_${k1}$(s,mold) result(v) ! -- In/out Variables character(*), intent(in) :: s !! input string ${t1}$, intent(in) :: mold !! dummy argument to disambiguate at compile time the generic interface ${t1}$ :: v !! Output ${t1}$ value ! -- Internal Variables integer(int8) :: p !! position within the number integer(int8) :: stat !! error status !---------------------------------------------- call to_num_base(s,v,p,stat) end function function to_${k1}$_from_stream(s,mold,stat) result(v) ! -- In/out Variables character(len=:), pointer :: s !! input string ${t1}$, intent(in) :: mold !! dummy argument to disambiguate at compile time the generic interface ${t1}$ :: v !! Output ${t1}$ value integer(int8),intent(inout), optional :: stat ! -- Internal Variables integer(int8) :: p !! position within the number integer(int8) :: err !---------------------------------------------- call to_num_base(s,v,p,err) p = min( p , len(s) ) s => s(p:) if(present(stat)) stat = err end function #:endfor !--------------------------------------------- ! String To Number Implementations !--------------------------------------------- #:for k1, t1 in INT_KINDS_TYPES elemental subroutine to_${k1}$_base(s,v,p,stat) !! Return an ${k1}$ integer ! -- In/out Variables character(*), intent(in) :: s !! input string ${t1}$, intent(out) :: v !! Output real value integer(int8), intent(out) :: p !! position within the number integer(int8), intent(out) :: stat !! status upon succes or failure to read ! -- Internal Variables integer(int8) :: val !---------------------------------------------- stat = 23 !! initialize error status with any number > 0 !---------------------------------------------- ! Find first non white space p = shift_to_nonwhitespace(s) !---------------------------------------------- v = 0 do while( p<=len(s) ) val = iachar(s(p:p))-digit_0 if( val >= 0 .and. val <= 9 ) then v = v*10 + val p = p + 1 else exit end if end do stat = 0 end subroutine #:endfor elemental subroutine to_sp_base(s,v,p,stat) integer, parameter :: wp = sp !! Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent ! -- In/out Variables character(*), intent(in) :: s !! input string real(wp), intent(inout) :: v !! Output real value integer(int8), intent(out) :: p !! last position within the string integer(int8), intent(out) :: stat !! status upon success or failure to read ! -- Internal Variables integer(int8), parameter :: nwnb = 39 !! number of whole number factors integer(int8), parameter :: nfnb = 37 !! number of fractional number factors integer :: e ! Notice: We use dp here to obtain exact precision for sp. ! Otherwise errors may appear in comparison to formatted read. ! See https://github.com/fortran-lang/stdlib/pull/743#issuecomment-1791953430 for more details real(dp), parameter :: whole_number_base(nwnb) = [(10._dp**(nwnb-e),e=1,nwnb)] real(dp), parameter :: fractional_base(nfnb) = [(10._dp**(-e),e=1,nfnb)] real(dp), parameter :: expbase(nwnb+nfnb) = [whole_number_base, fractional_base] integer(int8) :: sign, sige !! sign of integer number and exponential integer, parameter :: maxdpt = 11 !! Maximum depth to read values on int_wp integer(dp) :: int_wp !! long integer to capture fractional part integer :: i_exp !! integer to capture whole number part integer :: exp_aux integer(int8) :: i, pP, pE, val , resp !---------------------------------------------- stat = 23 !! initialize error status with any number > 0 !---------------------------------------------- ! Find first non white space p = shift_to_nonwhitespace(s) !---------------------------------------------- ! Verify leading negative sign = 1 if( iachar(s(p:p)) == minus_sign+digit_0 ) then sign = -1 p = p + 1 end if if( iachar(s(p:p)) == Inf ) then v = sign*ieee_value(v, ieee_positive_inf) return else if( iachar(s(p:p)) == NaN ) then v = ieee_value(v, ieee_quiet_nan) return end if !---------------------------------------------- ! read whole and fractional number in a single integer pP = 127 int_wp = 0 do i = p, min(maxdpt+p-1,len(s)) val = iachar(s(i:i))-digit_0 if( val >= 0 .and. val <= 9 ) then int_wp = int_wp*10 + val else if( val == period ) then pP = i else exit end if end do pE = i ! Fix the exponent position do while( i<=len(s) ) val = iachar(s(i:i))-digit_0 if( val < 0 .or. val > 9 ) exit i = i + 1 end do p = i resp = pE-min(pP,p) ! If no decimal indicator found it is taken as being in the current p position if( resp <= 0 ) resp = resp+1 !---------------------------------------------- ! Get exponential sige = 1 if( p= 0 .and. val <= 9 ) then i_exp = i_exp*10_int8 + val p = p + 1 else exit end if end do exp_aux = nwnb-1+resp-sige*i_exp if( exp_aux>0 .and. exp_aux<=nwnb+nfnb ) then v = sign*int_wp*expbase(exp_aux) else v = sign*int_wp*10._dp**(sige*i_exp-resp+1) end if stat = 0 end subroutine elemental subroutine to_dp_base(s,v,p,stat) integer, parameter :: wp = dp !! Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent ! -- In/out Variables character(*), intent(in) :: s !! input string real(wp), intent(inout) :: v !! Output real value integer(int8), intent(out) :: p !! last position within the string integer(int8), intent(out) :: stat !! status upon success or failure to read ! -- Internal Variables integer(int8), parameter :: nwnb = 40 !! number of whole number factors integer(int8), parameter :: nfnb = 64 !! number of fractional number factors integer :: e real(wp), parameter :: whole_number_base(nwnb) = [(10._wp**(nwnb-e),e=1,nwnb)] real(wp), parameter :: fractional_base(nfnb) = [(10._wp**(-e),e=1,nfnb)] real(wp), parameter :: expbase(nwnb+nfnb) = [whole_number_base, fractional_base] integer(int8) :: sign, sige !! sign of integer number and exponential integer, parameter :: maxdpt = 19 !! Maximum depth to read values on int_wp integer(wp) :: int_wp !! long integer to capture fractional part integer :: i_exp !! integer to capture whole number part integer :: exp_aux integer(int8) :: i, pP, pE, val , resp !---------------------------------------------- stat = 23 !! initialize error status with any number > 0 !---------------------------------------------- ! Find first non white space p = shift_to_nonwhitespace(s) !---------------------------------------------- ! Verify leading negative sign = 1 if( iachar(s(p:p)) == minus_sign+digit_0 ) then sign = -1 p = p + 1 end if if( iachar(s(p:p)) == Inf ) then v = sign*ieee_value(v, ieee_positive_inf) return else if( iachar(s(p:p)) == NaN ) then v = ieee_value(v, ieee_quiet_nan) return end if !---------------------------------------------- ! read whole and fractional number in a single integer pP = 127 int_wp = 0 do i = p, min(maxdpt+p-1,len(s)) val = iachar(s(i:i))-digit_0 if( val >= 0 .and. val <= 9 ) then int_wp = int_wp*10 + val else if( val == period ) then pP = i else exit end if end do pE = i ! Fix the exponent position do while( i<=len(s) ) val = iachar(s(i:i))-digit_0 if( val < 0 .or. val > 9 ) exit i = i + 1 end do p = i resp = pE-min(pP,p) ! If no decimal indicator found it is taken as being in the current p position if( resp <= 0 ) resp = resp+1 !---------------------------------------------- ! Get exponential sige = 1 if( p= 0 .and. val <= 9 ) then i_exp = i_exp*10_int8 + val p = p + 1 else exit end if end do exp_aux = nwnb-1+resp-sige*i_exp if( exp_aux>0 .and. exp_aux<=nwnb+nfnb ) then v = sign*int_wp*expbase(exp_aux) else v = sign*int_wp*10._wp**(sige*i_exp-resp+1) end if stat = 0 end subroutine #:if WITH_XDP elemental subroutine to_xdp_base(s,v,p,stat) integer, parameter :: wp = xdp !! Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent ! -- In/out Variables character(*), intent(in) :: s !! input string real(wp), intent(inout) :: v !! Output real value integer(int8), intent(out) :: p !! last position within the string integer(int8), intent(out) :: stat !! status upon success or failure to read ! -- Internal Variables integer(int8), parameter :: nwnb = 50 !! number of whole number factors integer(int8), parameter :: nfnb = 64 !! number of fractional number factors integer :: e real(wp), parameter :: whole_number_base(nwnb) = [(10._wp**(nwnb-e),e=1,nwnb)] real(wp), parameter :: fractional_base(nfnb) = [(10._wp**(-e),e=1,nfnb)] real(wp), parameter :: expbase(nwnb+nfnb) = [whole_number_base, fractional_base] integer(int8) :: sign, sige !! sign of integer number and exponential integer, parameter :: maxdpt = 19 !! Maximum depth to read values on int_dp integer(dp) :: int_dp1, int_dp2 !! long integers to capture whole and fractional part integer :: i_exp !! integer to capture exponent number integer :: exp_aux integer(int8) :: i, pP, pE, val , resp, icount, aux !---------------------------------------------- stat = 23 !! initialize error status with any number > 0 !---------------------------------------------- ! Find first non white space p = shift_to_nonwhitespace(s) !---------------------------------------------- ! Verify leading negative sign = 1 if( iachar(s(p:p)) == minus_sign+digit_0 ) then sign = -1 p = p + 1 end if if( iachar(s(p:p)) == Inf ) then v = sign*ieee_value(v, ieee_positive_inf) return else if( iachar(s(p:p)) == NaN ) then v = ieee_value(v, ieee_quiet_nan) return end if !---------------------------------------------- ! read whole and fractional number using two int64 values pP = 127 int_dp1 = 0 int_dp2 = 0 icount = 0 aux = 1 do i = p, min(2*maxdpt+p-1,len(s)) val = iachar(s(i:i))-digit_0 if( val >= 0 .and. val <= 9 ) then icount = icount + 1 if( icount<=maxdpt ) then int_dp1 = int_dp1*10 + val else if( icount<2*maxdpt ) then int_dp2 = int_dp2*10 + val end if else if( val == period ) then pP = i aux = 0 else exit end if end do pE = i ! Fix the exponent position do while( i<=len(s) ) val = iachar(s(i:i))-digit_0 if( val < 0 .or. val > 9 ) exit i = i + 1 end do p = i resp = pE-min(pP,p) ! If no decimal indicator found it is taken as being in the current p position if( resp <= 0 ) resp = resp+1 !---------------------------------------------- ! Get exponential sige = 1 if( p= 0 .and. val <= 9 ) then i_exp = i_exp*10_int8 + val p = p + 1 else exit end if end do exp_aux = nwnb-1+resp-sige*i_exp if( exp_aux>0 .and. exp_aux<=nwnb+nfnb ) then if( icount<=maxdpt ) then v = sign*int_dp1*expbase(exp_aux) else v = sign*(int_dp1 + int_dp2*fractional_base(maxdpt-1))*expbase(exp_aux-icount+maxdpt) end if else v = sign*(int_dp1 + int_dp2*fractional_base(maxdpt-1))*10._wp**(sige*i_exp-resp+maxdpt+aux) end if stat = 0 end subroutine #:endif #:if WITH_QP elemental subroutine to_qp_base(s,v,p,stat) integer, parameter :: wp = qp !! Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent ! -- In/out Variables character(*), intent(in) :: s !! input string real(wp), intent(inout) :: v !! Output real value integer(int8), intent(out) :: p !! last position within the string integer(int8), intent(out) :: stat !! status upon success or failure to read ! -- Internal Variables integer(int8), parameter :: nwnb = 50 !! number of whole number factors integer(int8), parameter :: nfnb = 64 !! number of fractional number factors integer :: e real(wp), parameter :: whole_number_base(nwnb) = [(10._wp**(nwnb-e),e=1,nwnb)] real(wp), parameter :: fractional_base(nfnb) = [(10._wp**(-e),e=1,nfnb)] real(wp), parameter :: expbase(nwnb+nfnb) = [whole_number_base, fractional_base] integer(int8) :: sign, sige !! sign of integer number and exponential integer, parameter :: maxdpt = 19 !! Maximum depth to read values on int_dp integer(dp) :: int_dp1, int_dp2 !! long integers to capture whole and fractional part integer :: i_exp !! integer to capture exponent number integer :: exp_aux integer(int8) :: i, pP, pE, val , resp, icount, aux !---------------------------------------------- stat = 23 !! initialize error status with any number > 0 !---------------------------------------------- ! Find first non white space p = shift_to_nonwhitespace(s) !---------------------------------------------- ! Verify leading negative sign = 1 if( iachar(s(p:p)) == minus_sign+digit_0 ) then sign = -1 p = p + 1 end if if( iachar(s(p:p)) == Inf ) then v = sign*ieee_value(v, ieee_positive_inf) return else if( iachar(s(p:p)) == NaN ) then v = ieee_value(v, ieee_quiet_nan) return end if !---------------------------------------------- ! read whole and fractional number using two int64 values pP = 127 int_dp1 = 0 int_dp2 = 0 icount = 0 aux = 1 do i = p, min(2*maxdpt+p-1,len(s)) val = iachar(s(i:i))-digit_0 if( val >= 0 .and. val <= 9 ) then icount = icount + 1 if( icount<=maxdpt ) then int_dp1 = int_dp1*10 + val else if( icount<2*maxdpt ) then int_dp2 = int_dp2*10 + val end if else if( val == period ) then pP = i aux = 0 else exit end if end do pE = i ! Fix the exponent position do while( i<=len(s) ) val = iachar(s(i:i))-digit_0 if( val < 0 .or. val > 9 ) exit i = i + 1 end do p = i resp = pE-min(pP,p) ! If no decimal indicator found it is taken as being in the current p position if( resp <= 0 ) resp = resp+1 !---------------------------------------------- ! Get exponential sige = 1 if( p= 0 .and. val <= 9 ) then i_exp = i_exp*10_int8 + val p = p + 1 else exit end if end do exp_aux = nwnb-1+resp-sige*i_exp if( exp_aux>0 .and. exp_aux<=nwnb+nfnb ) then if( icount<=maxdpt ) then v = sign*int_dp1*expbase(exp_aux) else v = sign*(int_dp1 + int_dp2*fractional_base(maxdpt-1))*expbase(exp_aux-icount+maxdpt) end if else v = sign*(int_dp1 + int_dp2*fractional_base(maxdpt-1))*10._wp**(sige*i_exp-resp+maxdpt+aux) end if stat = 0 end subroutine #:endif !--------------------------------------------- ! Internal Utility functions !--------------------------------------------- elemental function shift_to_nonwhitespace(s) result(p) !! move string to position of the next non white space character character(*),intent(in) :: s !! character chain integer(int8) :: p !! position !---------------------------------------------- p = 1 do while( p Format or transfer a ${t1}$ scalar as a string. pure module function to_string_${t1[0]}$_${k1}$(value, format) result(string) ${t1}$, intent(in) :: value character(len=*), intent(in), optional :: format character(len=:), allocatable :: string character(len=buffer_len) :: buffer integer :: stat write(buffer, '(' // optval(format, "g0") // ')', iostat=stat) value if (stat == 0) then string = trim(buffer) else string = err_sym end if end function to_string_${t1[0]}$_${k1}$ #:endfor #:for k1, t1 in CMPLX_KINDS_TYPES !> Format or transfer a ${t1}$ scalar as a string. pure module function to_string_${t1[0]}$_${k1}$(value, format) result(string) ${t1}$, intent(in) :: value character(len=*), intent(in), optional :: format character(len=:), allocatable :: string string = '(' // to_string_r_${k1}$(value%re, format) // ',' // & & to_string_r_${k1}$(value%im, format) // ')' end function to_string_${t1[0]}$_${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES !> Represent an integer of kind ${k1}$ as character sequence. pure module function to_string_1_${t1[0]}$_${k1}$(value) result(string) integer, parameter :: ik = ${k1}$ integer(ik), intent(in) :: value character(len=:), allocatable :: string integer, parameter :: buffer_len = range(value)+2 character(len=buffer_len) :: buffer integer :: pos integer(ik) :: n character(len=1), parameter :: numbers(-9:0) = & ["9", "8", "7", "6", "5", "4", "3", "2", "1", "0"] if (value == 0_ik) then string = numbers(0) return end if n = sign(value, -1_ik) buffer = "" pos = buffer_len + 1 do while (n < 0_ik) pos = pos - 1 buffer(pos:pos) = numbers(mod(n, 10_ik)) n = n/10_ik end do if (value < 0_ik) then pos = pos - 1 buffer(pos:pos) = '-' end if string = buffer(pos:) end function to_string_1_${t1[0]}$_${k1}$ pure module function to_string_2_${t1[0]}$_${k1}$(value, format) result(string) ${t1}$, intent(in) :: value character(len=*), intent(in) :: format character(len=:), allocatable :: string character(len=buffer_len) :: buffer integer :: stat write(buffer, "(" // format // ")", iostat=stat) value if (stat == 0) then string = trim(buffer) else string = err_sym end if end function to_string_2_${t1[0]}$_${k1}$ #:endfor #:for k1, t1 in LOG_KINDS_TYPES !> Represent an logical of kind ${k1}$ as character sequence. pure module function to_string_1_${t1[0]}$_${k1}$(value) result(string) ${t1}$, intent(in) :: value character(len=1) :: string string = merge("T", "F", value) end function to_string_1_${t1[0]}$_${k1}$ pure module function to_string_2_${t1[0]}$_${k1}$(value, format) result(string) ${t1}$, intent(in) :: value character(len=*), intent(in) :: format character(len=:), allocatable :: string character(len=buffer_len) :: buffer integer :: stat write(buffer, "(" // format // ")", iostat=stat) value if (stat == 0) then string = trim(buffer) else string = err_sym end if end function to_string_2_${t1[0]}$_${k1}$ #:endfor end submodule stdlib_strings_to_string fortran-lang-stdlib-0ede301/src/strings/stdlib_string_type_constructor.fypp0000664000175000017500000000232315135654166027723 0ustar alastairalastair#:include "common.fypp" submodule(stdlib_string_type) stdlib_string_type_constructor use stdlib_strings, only: to_string contains !> Constructor for new string instances from a scalar character value. elemental module function new_string(string) result(new) character(len=*), intent(in), optional :: string type(string_type) :: new if (present(string)) then new%raw = string end if end function new_string #:for kind in INT_KINDS !> Constructor for new string instances from an integer of kind ${kind}$. elemental module function new_string_from_integer_${kind}$(val) result(new) integer(${kind}$), intent(in) :: val type(string_type) :: new new%raw = to_string(val) end function new_string_from_integer_${kind}$ #:endfor #:for kind in LOG_KINDS !> Constructor for new string instances from a logical of kind ${kind}$. elemental module function new_string_from_logical_${kind}$(val) result(new) logical(${kind}$), intent(in) :: val type(string_type) :: new new%raw = to_string(val) end function new_string_from_logical_${kind}$ #:endfor end submodule stdlib_string_type_constructorfortran-lang-stdlib-0ede301/src/strings/stdlib_strings.fypp0000664000175000017500000011553015135654166024405 0ustar alastairalastair! SPDX-Identifier: MIT #:include "common.fypp" !> This module implements basic string handling routines. !> !> The specification of this module is available [here](../page/specs/stdlib_strings.html). module stdlib_strings use stdlib_ascii, only: whitespace use stdlib_string_type, only: string_type, char, verify, repeat, len, len_trim, move use stdlib_optval, only: optval use stdlib_kinds, only: sp, dp, xdp, qp, int8, int16, int32, int64, lk, c_bool, c_char use iso_c_binding, only: c_null_char implicit none private public :: to_string public :: to_c_char public :: strip, chomp public :: starts_with, ends_with public :: slice, find, replace_all, padl, padr, count, zfill, join !> Version: experimental !> !> Format or transfer other types as a string. !> ([Specification](../page/specs/stdlib_strings.html#to_string)) interface to_string #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES #:set IL_KINDS_TYPES = INT_KINDS_TYPES + LOG_KINDS_TYPES #:for k1, t1 in RC_KINDS_TYPES pure module function to_string_${t1[0]}$_${k1}$(value, format) result(string) ${t1}$, intent(in) :: value character(len=*), intent(in), optional :: format character(len=:), allocatable :: string end function to_string_${t1[0]}$_${k1}$ #:endfor #:for k1, t1 in IL_KINDS_TYPES pure module function to_string_1_${t1[0]}$_${k1}$(value) result(string) ${t1}$, intent(in) :: value character(len=#{if t1[0]=="l"}#1)#{else}#:), allocatable#{endif}# :: string end function to_string_1_${t1[0]}$_${k1}$ pure module function to_string_2_${t1[0]}$_${k1}$(value, format) result(string) ${t1}$, intent(in) :: value character(len=*), intent(in) :: format character(len=:), allocatable :: string end function to_string_2_${t1[0]}$_${k1}$ #:endfor end interface to_string !> Version: experimental !> !> Format or transfer other types as a string. !> ([Specification](../page/specs/stdlib_strings.html#to_c_char)) interface to_c_char module procedure to_c_char_from_char module procedure to_c_char_from_string end interface to_c_char !> Remove leading and trailing whitespace characters. !> !> Version: experimental interface strip module procedure :: strip_string module procedure :: strip_char end interface strip !> Remove trailing characters in set from string. !> If no character set is provided trailing whitespace is removed. !> !> Version: experimental interface chomp module procedure :: chomp_string module procedure :: chomp_char module procedure :: chomp_set_string_char module procedure :: chomp_set_char_char module procedure :: chomp_substring_string_string module procedure :: chomp_substring_char_string module procedure :: chomp_substring_string_char module procedure :: chomp_substring_char_char end interface chomp !> Check whether a string starts with substring or not !> !> Version: experimental interface starts_with module procedure :: starts_with_string_string module procedure :: starts_with_string_char module procedure :: starts_with_char_string module procedure :: starts_with_char_char end interface starts_with !> Check whether a string ends with substring or not !> !> Version: experimental interface ends_with module procedure :: ends_with_string_string module procedure :: ends_with_string_char module procedure :: ends_with_char_string module procedure :: ends_with_char_char end interface ends_with !> Extracts characters from the input string to return a new string !> !> Version: experimental interface slice module procedure :: slice_string module procedure :: slice_char end interface slice !> Finds the starting index of substring 'pattern' in the input 'string' !> [Specifications](link to the specs - to be completed) !> !> Version: experimental interface find module procedure :: find_string_string module procedure :: find_string_char module procedure :: find_char_string module procedure :: find_char_char end interface find !> Replaces all the occurrences of substring 'pattern' in the input 'string' !> with the replacement 'replacement' !> Version: experimental interface replace_all module procedure :: replace_all_string_string_string module procedure :: replace_all_string_string_char module procedure :: replace_all_string_char_string module procedure :: replace_all_char_string_string module procedure :: replace_all_string_char_char module procedure :: replace_all_char_string_char module procedure :: replace_all_char_char_string module procedure :: replace_all_char_char_char end interface replace_all !> Version: experimental !> !> Left pad the input string !> [Specifications](../page/specs/stdlib_strings.html#padl) interface padl module procedure :: padl_string_default module procedure :: padl_string_pad_with module procedure :: padl_char_default module procedure :: padl_char_pad_with end interface padl !> Version: experimental !> !> Right pad the input string !> [Specifications](../page/specs/stdlib_strings.html#padr) interface padr module procedure :: padr_string_default module procedure :: padr_string_pad_with module procedure :: padr_char_default module procedure :: padr_char_pad_with end interface padr !> Version: experimental !> !> Returns the number of times substring 'pattern' has appeared in the !> input string 'string' !> [Specifications](../page/specs/stdlib_strings.html#count) interface count module procedure :: count_string_string module procedure :: count_string_char module procedure :: count_char_string module procedure :: count_char_char end interface count !> Version: experimental !> !> Left pad the input string with zeros. !> [Specifications](../page/specs/stdlib_strings.html#zfill) interface zfill module procedure :: zfill_string module procedure :: zfill_char end interface zfill !> Version: experimental !> !> Joins an array of strings into a single string. !> The chunks are separated with a space, or an optional user-defined separator. !> [Specifications](../page/specs/stdlib_strings.html#join) interface join module procedure :: join_string module procedure :: join_char end interface join contains !> Remove leading and trailing whitespace characters. pure function strip_string(string) result(stripped_string) ! Avoid polluting the module scope and use the assignment only in this scope use stdlib_string_type, only : assignment(=) type(string_type), intent(in) :: string type(string_type) :: stripped_string stripped_string = strip(char(string)) end function strip_string !> Remove leading and trailing whitespace characters. pure function strip_char(string) result(stripped_string) character(len=*), intent(in) :: string character(len=:), allocatable :: stripped_string integer :: first, last first = verify(string, whitespace) if (first == 0) then stripped_string = "" else last = verify(string, whitespace, back=.true.) stripped_string = string(first:last) end if end function strip_char !> Remove trailing characters in set from string. !> Default character set variant where trailing whitespace is removed. pure function chomp_string(string) result(chomped_string) ! Avoid polluting the module scope and use the assignment only in this scope use stdlib_string_type, only : assignment(=) type(string_type), intent(in) :: string type(string_type) :: chomped_string integer :: last last = verify(string, whitespace, back=.true.) chomped_string = char(string, 1, last) end function chomp_string !> Remove trailing characters in set from string. !> Default character set variant where trailing whitespace is removed. pure function chomp_char(string) result(chomped_string) character(len=*), intent(in) :: string character(len=:), allocatable :: chomped_string integer :: last last = verify(string, whitespace, back=.true.) chomped_string = string(1:last) end function chomp_char !> Remove trailing characters in set from string. pure function chomp_set_string_char(string, set) result(chomped_string) ! Avoid polluting the module scope and use the assignment only in this scope use stdlib_string_type, only : assignment(=) type(string_type), intent(in) :: string character(len=1), intent(in) :: set(:) type(string_type) :: chomped_string chomped_string = chomp(char(string), set) end function chomp_set_string_char !> Remove trailing characters in set from string. pure function chomp_set_char_char(string, set) result(chomped_string) character(len=*), intent(in) :: string character(len=1), intent(in) :: set(:) character(len=:), allocatable :: chomped_string integer :: last last = verify(string, set_to_string(set), back=.true.) chomped_string = string(1:last) end function chomp_set_char_char !> Remove trailing substrings from string. pure function chomp_substring_string_string(string, substring) result(chomped_string) ! Avoid polluting the module scope and use the assignment only in this scope use stdlib_string_type, only : assignment(=) type(string_type), intent(in) :: string type(string_type), intent(in) :: substring type(string_type) :: chomped_string chomped_string = chomp(char(string), char(substring)) end function chomp_substring_string_string !> Remove trailing substrings from string. pure function chomp_substring_string_char(string, substring) result(chomped_string) ! Avoid polluting the module scope and use the assignment only in this scope use stdlib_string_type, only : assignment(=) type(string_type), intent(in) :: string character(len=*), intent(in) :: substring type(string_type) :: chomped_string chomped_string = chomp(char(string), substring) end function chomp_substring_string_char !> Remove trailing substrings from string. pure function chomp_substring_char_string(string, substring) result(chomped_string) character(len=*), intent(in) :: string type(string_type), intent(in) :: substring character(len=:), allocatable :: chomped_string chomped_string = chomp(string, char(substring)) end function chomp_substring_char_string !> Remove trailing substrings from string. pure function chomp_substring_char_char(string, substring) result(chomped_string) character(len=*), intent(in) :: string character(len=*), intent(in) :: substring character(len=:), allocatable :: chomped_string integer :: last, nsub last = len(string) nsub = len(substring) if (nsub > 0 .and. nsub <= last) then do while(last >= nsub) if (string(last-nsub+1:last) == substring) then last = last - nsub else exit end if end do end if if (last <= 0) then chomped_string = '' else chomped_string = string(1:last) end if end function chomp_substring_char_char !> Implementation to transfer a set of characters to a string representing the set. !> !> This function is internal and not part of the public API. pure function set_to_string(set) result(string) character(len=1), intent(in) :: set(:) character(len=size(set)) :: string string = transfer(set, string) end function set_to_string !> Check whether a string starts with substring or not pure function starts_with_char_char(string, substring) result(match) character(len=*), intent(in) :: string character(len=*), intent(in) :: substring logical :: match integer :: nsub nsub = len(substring) if (len(string) < nsub) then match = .false. return end if match = string(1:nsub) == substring end function starts_with_char_char !> Check whether a string starts with substring or not elemental function starts_with_string_char(string, substring) result(match) type(string_type), intent(in) :: string character(len=*), intent(in) :: substring logical :: match match = starts_with(char(string), substring) end function starts_with_string_char !> Check whether a string starts with substring or not elemental function starts_with_char_string(string, substring) result(match) character(len=*), intent(in) :: string type(string_type), intent(in) :: substring logical :: match match = starts_with(string, char(substring)) end function starts_with_char_string !> Check whether a string starts with substring or not elemental function starts_with_string_string(string, substring) result(match) type(string_type), intent(in) :: string type(string_type), intent(in) :: substring logical :: match match = starts_with(char(string), char(substring)) end function starts_with_string_string !> Check whether a string ends with substring or not pure function ends_with_char_char(string, substring) result(match) character(len=*), intent(in) :: string character(len=*), intent(in) :: substring logical :: match integer :: last, nsub last = len(string) nsub = len(substring) if (last < nsub) then match = .false. return end if match = string(last-nsub+1:last) == substring end function ends_with_char_char !> Check whether a string ends with substring or not elemental function ends_with_string_char(string, substring) result(match) type(string_type), intent(in) :: string character(len=*), intent(in) :: substring logical :: match match = ends_with(char(string), substring) end function ends_with_string_char !> Check whether a string ends with substring or not elemental function ends_with_char_string(string, substring) result(match) character(len=*), intent(in) :: string type(string_type), intent(in) :: substring logical :: match match = ends_with(string, char(substring)) end function ends_with_char_string !> Check whether a string ends with substring or not elemental function ends_with_string_string(string, substring) result(match) type(string_type), intent(in) :: string type(string_type), intent(in) :: substring logical :: match match = ends_with(char(string), char(substring)) end function ends_with_string_string !> Extract the characters from the region between 'first' and 'last' index (both inclusive) !> of the input 'string' by taking strides of length 'stride' !> Returns a new string elemental function slice_string(string, first, last, stride) result(sliced_string) type(string_type), intent(in) :: string integer, intent(in), optional :: first, last, stride type(string_type) :: sliced_string sliced_string = string_type(slice(char(string), first, last, stride)) end function slice_string !> Extract the characters from the region between 'first' and 'last' index (both inclusive) !> of the input 'string' by taking strides of length 'stride' !> Returns a new string pure function slice_char(string, first, last, stride) result(sliced_string) character(len=*), intent(in) :: string integer, intent(in), optional :: first, last, stride integer :: first_index, last_index, stride_vector, strides_taken, length_string, i, j character(len=:), allocatable :: sliced_string length_string = len(string) first_index = 0 ! first_index = -infinity last_index = length_string + 1 ! last_index = +infinity stride_vector = 1 if (present(stride)) then if (stride /= 0) then if (stride < 0) then first_index = length_string + 1 ! first_index = +infinity last_index = 0 ! last_index = -infinity end if stride_vector = stride end if else if (present(first) .and. present(last)) then if (last < first) then stride_vector = -1 end if end if end if if (present(first)) then first_index = first end if if (present(last)) then last_index = last end if if (stride_vector > 0) then first_index = max(first_index, 1) last_index = min(last_index, length_string) else first_index = min(first_index, length_string) last_index = max(last_index, 1) end if strides_taken = floor( real(last_index - first_index)/real(stride_vector) ) allocate(character(len=max(0, strides_taken + 1)) :: sliced_string) j = 1 do i = first_index, last_index, stride_vector sliced_string(j:j) = string(i:i) j = j + 1 end do end function slice_char !> Returns the starting index of the 'occurrence'th occurrence of substring 'pattern' !> in input 'string' !> Returns an integer elemental function find_string_string(string, pattern, occurrence, consider_overlapping) result(res) type(string_type), intent(in) :: string type(string_type), intent(in) :: pattern integer, intent(in), optional :: occurrence logical, intent(in), optional :: consider_overlapping integer :: res res = find(char(string), char(pattern), occurrence, consider_overlapping) end function find_string_string !> Returns the starting index of the 'occurrence'th occurrence of substring 'pattern' !> in input 'string' !> Returns an integer elemental function find_string_char(string, pattern, occurrence, consider_overlapping) result(res) type(string_type), intent(in) :: string character(len=*), intent(in) :: pattern integer, intent(in), optional :: occurrence logical, intent(in), optional :: consider_overlapping integer :: res res = find(char(string), pattern, occurrence, consider_overlapping) end function find_string_char !> Returns the starting index of the 'occurrence'th occurrence of substring 'pattern' !> in input 'string' !> Returns an integer elemental function find_char_string(string, pattern, occurrence, consider_overlapping) result(res) character(len=*), intent(in) :: string type(string_type), intent(in) :: pattern integer, intent(in), optional :: occurrence logical, intent(in), optional :: consider_overlapping integer :: res res = find(string, char(pattern), occurrence, consider_overlapping) end function find_char_string !> Returns the starting index of the 'occurrence'th occurrence of substring 'pattern' !> in input 'string' !> Returns an integer elemental function find_char_char(string, pattern, occurrence, consider_overlapping) result(res) character(len=*), intent(in) :: string character(len=*), intent(in) :: pattern integer, intent(in), optional :: occurrence logical, intent(in), optional :: consider_overlapping integer :: lps_array(len(pattern)) integer :: res, s_i, p_i, length_string, length_pattern, occurrence_ occurrence_ = optval(occurrence, 1) res = 0 length_string = len(string) length_pattern = len(pattern) if (length_pattern > 0 .and. length_pattern <= length_string & & .and. occurrence_ > 0) then lps_array = compute_lps(pattern) s_i = 1 p_i = 1 do while(s_i <= length_string) if (string(s_i:s_i) == pattern(p_i:p_i)) then if (p_i == length_pattern) then occurrence_ = occurrence_ - 1 if (occurrence_ == 0) then res = s_i - length_pattern + 1 exit else if (optval(consider_overlapping, .true.)) then p_i = lps_array(p_i) else p_i = 0 end if end if s_i = s_i + 1 p_i = p_i + 1 else if (p_i > 1) then p_i = lps_array(p_i - 1) + 1 else s_i = s_i + 1 end if end do end if end function find_char_char !> Computes longest prefix suffix for each index of the input 'string' !> !> Returns an array of integers pure function compute_lps(string) result(lps_array) character(len=*), intent(in) :: string integer :: lps_array(len(string)) integer :: i, j, length_string length_string = len(string) if (length_string > 0) then lps_array(1) = 0 i = 2 j = 1 do while (i <= length_string) if (string(j:j) == string(i:i)) then lps_array(i) = j i = i + 1 j = j + 1 else if (j > 1) then j = lps_array(j - 1) + 1 else lps_array(i) = 0 i = i + 1 end if end do end if end function compute_lps !> Replaces all occurrences of substring 'pattern' in the input 'string' !> with the replacement 'replacement' !> Returns a new string pure function replace_all_string_string_string(string, pattern, replacement) result(res) type(string_type), intent(in) :: string type(string_type), intent(in) :: pattern type(string_type), intent(in) :: replacement type(string_type) :: res res = string_type(replace_all(char(string), & & char(pattern), char(replacement))) end function replace_all_string_string_string !> Replaces all occurrences of substring 'pattern' in the input 'string' !> with the replacement 'replacement' !> Returns a new string pure function replace_all_string_string_char(string, pattern, replacement) result(res) type(string_type), intent(in) :: string type(string_type), intent(in) :: pattern character(len=*), intent(in) :: replacement type(string_type) :: res res = string_type(replace_all(char(string), char(pattern), replacement)) end function replace_all_string_string_char !> Replaces all occurrences of substring 'pattern' in the input 'string' !> with the replacement 'replacement' !> Returns a new string pure function replace_all_string_char_string(string, pattern, replacement) result(res) type(string_type), intent(in) :: string character(len=*), intent(in) :: pattern type(string_type), intent(in) :: replacement type(string_type) :: res res = string_type(replace_all(char(string), pattern, char(replacement))) end function replace_all_string_char_string !> Replaces all occurrences of substring 'pattern' in the input 'string' !> with the replacement 'replacement' !> Returns a new string pure function replace_all_char_string_string(string, pattern, replacement) result(res) character(len=*), intent(in) :: string type(string_type), intent(in) :: pattern type(string_type), intent(in) :: replacement character(len=:), allocatable :: res res = replace_all(string, char(pattern), char(replacement)) end function replace_all_char_string_string !> Replaces all occurrences of substring 'pattern' in the input 'string' !> with the replacement 'replacement' !> Returns a new string pure function replace_all_string_char_char(string, pattern, replacement) result(res) type(string_type), intent(in) :: string character(len=*), intent(in) :: pattern character(len=*), intent(in) :: replacement type(string_type) :: res res = string_type(replace_all(char(string), pattern, replacement)) end function replace_all_string_char_char !> Replaces all occurrences of substring 'pattern' in the input 'string' !> with the replacement 'replacement' !> Returns a new string pure function replace_all_char_string_char(string, pattern, replacement) result(res) character(len=*), intent(in) :: string type(string_type), intent(in) :: pattern character(len=*), intent(in) :: replacement character(len=:), allocatable :: res res = replace_all(string, char(pattern), replacement) end function replace_all_char_string_char !> Replaces all occurrences of substring 'pattern' in the input 'string' !> with the replacement 'replacement' !> Returns a new string pure function replace_all_char_char_string(string, pattern, replacement) result(res) character(len=*), intent(in) :: string character(len=*), intent(in) :: pattern type(string_type), intent(in) :: replacement character(len=:), allocatable :: res res = replace_all(string, pattern, char(replacement)) end function replace_all_char_char_string !> Replaces all the occurrences of substring 'pattern' in the input 'string' !> with the replacement 'replacement' !> Returns a new string pure function replace_all_char_char_char(string, pattern, replacement) result(res) character(len=*), intent(in) :: string character(len=*), intent(in) :: pattern character(len=*), intent(in) :: replacement character(len=:), allocatable :: res integer :: lps_array(len(pattern)) integer :: s_i, p_i, last, length_string, length_pattern res = "" length_string = len(string) length_pattern = len(pattern) last = 1 if (length_pattern > 0 .and. length_pattern <= length_string) then lps_array = compute_lps(pattern) s_i = 1 p_i = 1 do while (s_i <= length_string) if (string(s_i:s_i) == pattern(p_i:p_i)) then if (p_i == length_pattern) then res = res // & & string(last : s_i - length_pattern) // & & replacement last = s_i + 1 p_i = 0 end if s_i = s_i + 1 p_i = p_i + 1 else if (p_i > 1) then p_i = lps_array(p_i - 1) + 1 else s_i = s_i + 1 end if end do end if res = res // string(last : length_string) end function replace_all_char_char_char !> Left pad the input string with " " (1 whitespace) !> !> Returns a new string pure function padl_string_default(string, output_length) result(res) type(string_type), intent(in) :: string integer, intent(in) :: output_length type(string_type) :: res res = string_type(padl(char(string), output_length, " ")) end function padl_string_default !> Left pad the input string with the 'pad_with' character !> !> Returns a new string pure function padl_string_pad_with(string, output_length, pad_with) result(res) type(string_type), intent(in) :: string integer, intent(in) :: output_length character(len=1), intent(in) :: pad_with type(string_type) :: res res = string_type(padl(char(string), output_length, pad_with)) end function padl_string_pad_with !> Left pad the input string with " " (1 whitespace) !> !> Returns a new string pure function padl_char_default(string, output_length) result(res) character(len=*), intent(in) :: string integer, intent(in) :: output_length character(len=max(len(string), output_length)) :: res res = padl(string, output_length, " ") end function padl_char_default !> Left pad the input string with the 'pad_with' character !> !> Returns a new string pure function padl_char_pad_with(string, output_length, pad_with) result(res) character(len=*), intent(in) :: string integer, intent(in) :: output_length character(len=1), intent(in) :: pad_with character(len=max(len(string), output_length)) :: res integer :: string_length string_length = len(string) if (string_length < output_length) then res = repeat(pad_with, output_length - string_length) res(output_length - string_length + 1 : output_length) = string else res = string end if end function padl_char_pad_with !> Right pad the input string with " " (1 whitespace) !> !> Returns a new string pure function padr_string_default(string, output_length) result(res) type(string_type), intent(in) :: string integer, intent(in) :: output_length character(len=max(len(string), output_length)) :: char_output type(string_type) :: res ! We're taking advantage of `char_output` being longer than `string` and ! initialized with whitespaces. By casting `string` to a `character` ! type and back to `string_type`, we're effectively right-padding ! `string` with spaces, so we don't need to pad explicitly. char_output = char(string) res = string_type(char_output) end function padr_string_default !> Right pad the input string with the 'pad_with' character !> !> Returns a new string pure function padr_string_pad_with(string, output_length, pad_with) result(res) type(string_type), intent(in) :: string integer, intent(in) :: output_length character(len=1), intent(in) :: pad_with type(string_type) :: res res = string_type(padr(char(string), output_length, pad_with)) end function padr_string_pad_with !> Right pad the input string with " " (1 whitespace) !> !> Returns a new string pure function padr_char_default(string, output_length) result(res) character(len=*), intent(in) :: string integer, intent(in) :: output_length character(len=max(len(string), output_length)) :: res res = string end function padr_char_default !> Right pad the input string with the 'pad_with' character !> !> Returns a new string pure function padr_char_pad_with(string, output_length, pad_with) result(res) character(len=*), intent(in) :: string integer, intent(in) :: output_length character(len=1), intent(in) :: pad_with character(len=max(len(string), output_length)) :: res integer :: string_length string_length = len(string) res = string if (string_length < output_length) then res(string_length + 1 : output_length) = & repeat(pad_with, output_length - string_length) end if end function padr_char_pad_with !> Returns the number of times substring 'pattern' has appeared in the !> input string 'string' !> Returns an integer elemental function count_string_string(string, pattern, consider_overlapping) result(res) type(string_type), intent(in) :: string type(string_type), intent(in) :: pattern logical, intent(in), optional :: consider_overlapping integer :: res res = count(char(string), char(pattern), consider_overlapping) end function count_string_string !> Returns the number of times substring 'pattern' has appeared in the !> input string 'string' !> Returns an integer elemental function count_string_char(string, pattern, consider_overlapping) result(res) type(string_type), intent(in) :: string character(len=*), intent(in) :: pattern logical, intent(in), optional :: consider_overlapping integer :: res res = count(char(string), pattern, consider_overlapping) end function count_string_char !> Returns the number of times substring 'pattern' has appeared in the !> input string 'string' !> Returns an integer elemental function count_char_string(string, pattern, consider_overlapping) result(res) character(len=*), intent(in) :: string type(string_type), intent(in) :: pattern logical, intent(in), optional :: consider_overlapping integer :: res res = count(string, char(pattern), consider_overlapping) end function count_char_string !> Returns the number of times substring 'pattern' has appeared in the !> input string 'string' !> Returns an integer elemental function count_char_char(string, pattern, consider_overlapping) result(res) character(len=*), intent(in) :: string character(len=*), intent(in) :: pattern logical, intent(in), optional :: consider_overlapping integer :: lps_array(len(pattern)) integer :: res, s_i, p_i, length_string, length_pattern res = 0 length_string = len(string) length_pattern = len(pattern) if (length_pattern > 0 .and. length_pattern <= length_string) then lps_array = compute_lps(pattern) s_i = 1 p_i = 1 do while (s_i <= length_string) if (string(s_i:s_i) == pattern(p_i:p_i)) then if (p_i == length_pattern) then res = res + 1 if (optval(consider_overlapping, .true.)) then p_i = lps_array(p_i) else p_i = 0 end if end if s_i = s_i + 1 p_i = p_i + 1 else if (p_i > 1) then p_i = lps_array(p_i - 1) + 1 else s_i = s_i + 1 end if end do end if end function count_char_char !> Left pad the input string with zeros !> !> Returns a new string pure function zfill_string(string, output_length) result(res) type(string_type), intent(in) :: string integer, intent(in) :: output_length type(string_type) :: res res = string_type(padl(char(string), output_length, "0")) end function zfill_string !> Left pad the input string with zeros !> !> Returns a new string pure function zfill_char(string, output_length) result(res) character(len=*), intent(in) :: string integer, intent(in) :: output_length character(len=max(len(string), output_length)) :: res res = padl(string, output_length, "0") end function zfill_char !> Convert a Fortran character string to a C character array !> !> Version: experimental pure function to_c_char_from_char(value) result(cstr) character(len=*), intent(in) :: value character(kind=c_char) :: cstr(len(value)+1) integer :: i,lv lv = len(value) do concurrent (i=1:lv) cstr(i) = value(i:i) end do cstr(lv+1) = c_null_char end function to_c_char_from_char !> Convert a Fortran string type to a C character array !> !> Version: experimental pure function to_c_char_from_string(value) result(cstr) type(string_type), intent(in) :: value character(kind=c_char) :: cstr(len(value)+1) integer :: i,lv lv = len(value) do concurrent (i=1:lv) cstr(i) = char(value,pos=i) end do cstr(lv+1) = c_null_char end function to_c_char_from_string !> Joins a list of strings with a separator (default: space). !> Returns a new string pure type(string_type) function join_string(strings, separator) type(string_type), intent(in) :: strings(:) character(len=*), intent(in), optional :: separator integer :: ltot, i, lt, pos character(len=:), allocatable :: sep,joined ! Determine separator: use user-provided separator or default space if (present(separator)) then sep = separator else sep = ' ' end if ! Calculate the total length required, including separators ltot = sum(len_trim(strings)) + (size(strings) - 1) * len(sep) allocate(character(len=ltot) :: joined) ! Concatenate strings with separator pos = 0 do i = 1, size(strings) lt = len_trim(strings(i)) joined(pos+1:pos+lt) = char(strings(i),1,lt) pos = pos + lt if (i < size(strings)) then joined(pos+1:pos+len(sep)) = sep pos = pos + len(sep) end if end do call move(from=joined,to=join_string) end function join_string !> Joins a list of strings with a separator (default: space). !> Returns a new string pure function join_char(strings, separator) result(joined) character(*), intent(in) :: strings(:) character(len=*), intent(in), optional :: separator character(len=:), allocatable :: joined integer :: ltot, i, lt, pos character(len=:), allocatable :: sep ! Determine separator: use user-provided separator or default space if (present(separator)) then sep = separator else sep = ' ' end if ! Calculate the total length required, including separators ltot = sum(len_trim(strings)) + (size(strings) - 1) * len(sep) allocate(character(len=ltot) :: joined) joined = repeat(' ',ltot) ! Concatenate strings with separator pos = 0 do i = 1, size(strings) lt = len_trim(strings(i)) joined(pos+1:pos+lt) = strings(i)(1:lt) pos = pos + lt if (i < size(strings)) then joined(pos+1:pos+len(sep)) = sep pos = pos + len(sep) end if end do end function join_char end module stdlib_strings fortran-lang-stdlib-0ede301/CODE_OF_CONDUCT.md0000664000175000017500000000627315135654166020775 0ustar alastairalastair# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing or otherwise unacceptable behavior may be reported by contacting one of the project maintainers at caomaco@gmail.com or ondrej@certik.us. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version] [homepage]: https://contributor-covenant.org [version]: https://contributor-covenant.org/version/1/4/ fortran-lang-stdlib-0ede301/CMakeLists.txt0000664000175000017500000001200215135654166020721 0ustar alastairalastaircmake_minimum_required(VERSION 3.14.0) # Include overwrites before setting up the project set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_CURRENT_SOURCE_DIR}/config/DefaultFlags.cmake) project(fortran_stdlib LANGUAGES Fortran C DESCRIPTION "Community driven and agreed upon de facto standard library for Fortran" ) # Read version from file file(STRINGS "${PROJECT_SOURCE_DIR}/VERSION" PROJECT_VERSION) string(REPLACE "." ";" VERSION_LIST ${PROJECT_VERSION}) list(GET VERSION_LIST 0 PROJECT_VERSION_MAJOR) list(GET VERSION_LIST 1 PROJECT_VERSION_MINOR) list(GET VERSION_LIST 2 PROJECT_VERSION_PATCH) unset(VERSION_LIST) include(CTest) # Follow GNU conventions for installation directories include(GNUInstallDirs) include(${PROJECT_SOURCE_DIR}/cmake/stdlib.cmake) # --- CMake specific configuration and package data export add_subdirectory(config) # --- compiler selection if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 9.0) message(FATAL_ERROR "GCC Version 9 or newer required") endif() # --- silence gfortran-15 argument-mismatch warnings if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU AND CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 15.0 AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 16.0) add_compile_options("$<$:-Wno-external-argument-mismatch>") endif() # --- compiler feature checks include(CheckFortranSourceCompiles) include(CheckFortranSourceRuns) check_fortran_source_runs("i=0; error stop i; end" f18errorstop) check_fortran_source_compiles("real, allocatable :: array(:, :, :, :, :, :, :, :, :, :); end" f03rank SRC_EXT f90) check_fortran_source_runs("use, intrinsic :: iso_fortran_env, only : real128; real(real128) :: x; x = x+1; end" f03real128) if(NOT DEFINED CMAKE_MAXIMUM_RANK) set(CMAKE_MAXIMUM_RANK 4 CACHE STRING "Maximum array rank for generated procedures") endif() # --- determine if the following modules will be compiled check_modular("ANSI") check_modular("BITSETS") check_modular("HASHMAPS") check_modular("IO") check_modular("LINALG_ITERATIVE") check_modular("LOGGER") check_modular("QUADRATURE") check_modular("SPECIALMATRICES") check_modular("STRINGLIST") check_modular("STATS") check_modular("SYSTEM") option(FIND_BLAS "Find external BLAS and LAPACK" ON) # --- find external BLAS and LAPACK if(FIND_BLAS) message(STATUS "Searching for external BLAS/LAPACK") # Common MKL setup if(DEFINED ENV{MKLROOT} OR "${BLA_VENDOR}" MATCHES "^(Intel|Intel10_64)") enable_language("C") message(STATUS "Detected Intel MKL environment") endif() find_package(BLAS) find_package(LAPACK) if(BLAS_FOUND AND LAPACK_FOUND) message(STATUS "Found external BLAS: ${BLAS_LIBRARIES}") message(STATUS "Found external LAPACK: ${LAPACK_LIBRARIES}") # Detect ILP64 (common function) function(detect_ilp64 lib_name) set(${lib_name}_ILP64 False PARENT_SCOPE) # Prefer checking BLA_SIZEOF_INTEGER (available in CMake >= 3.22) if(DEFINED BLA_SIZEOF_INTEGER AND BLA_SIZEOF_INTEGER EQUAL 8) set(${lib_name}_ILP64 True PARENT_SCOPE) # Fallback: Check BLA_VENDOR manually for signs of ILP64 elseif("${BLA_VENDOR}" MATCHES ".*(_ilp|ILP64).*") set(${lib_name}_ILP64 True PARENT_SCOPE) endif() endfunction() detect_ilp64(BLAS) detect_ilp64(LAPACK) # Set compile definitions if(BLAS_ILP64 OR LAPACK_ILP64) message(STATUS "Enabling 64-bit integer support (ILP64)") add_compile_definitions(STDLIB_EXTERNAL_BLAS_I64 STDLIB_EXTERNAL_LAPACK_I64) set(WITH_ILP64 True CACHE BOOL "Use 64-bit integer BLAS/LAPACK" FORCE) else() message(STATUS "Using standard 32-bit integer interface") add_compile_definitions(STDLIB_EXTERNAL_BLAS STDLIB_EXTERNAL_LAPACK) endif() else() message(WARNING "External BLAS/LAPACK not found - " "Using built-in reference BLAS") endif() endif() # --- find preprocessor find_program(FYPP fypp) if(NOT FYPP) message(FATAL_ERROR "Preprocessor fypp not found! Please install fypp following the instructions in https://fypp.readthedocs.io/en/stable/fypp.html#installing") endif() # Custom preprocessor flags if(DEFINED CMAKE_MAXIMUM_RANK) set(fyppFlags "-DMAXRANK=${CMAKE_MAXIMUM_RANK}") elseif(f03rank) set(fyppFlags) else() set(fyppFlags "-DVERSION90") endif() list( APPEND fyppFlags "-DWITH_CBOOL=$" "-DWITH_QP=$" "-DWITH_XDP=$" "-DWITH_ILP64=$" "-DPROJECT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}" "-DPROJECT_VERSION_MINOR=${PROJECT_VERSION_MINOR}" "-DPROJECT_VERSION_PATCH=${PROJECT_VERSION_PATCH}" "-I${PROJECT_SOURCE_DIR}/include" ) include_directories(${PROJECT_SOURCE_DIR}/include) add_subdirectory(src) if(BUILD_TESTING) enable_testing() add_subdirectory(test) add_subdirectory(example) endif() install(EXPORT ${PROJECT_NAME}-targets NAMESPACE ${PROJECT_NAME}:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) # Export a pkg-config file include(${PROJECT_SOURCE_DIR}/config/export_pc.cmake) fortran-lang-stdlib-0ede301/.editorconfig0000664000175000017500000000223315135654166020643 0ustar alastairalastair# EditorConfig file. For more info, please see: # https://EditorConfig.org # top-most EditorConfig file root = true # All files should have a final newline and not have trailing whitespace # but we need to explicitly enumerate files we care about to prevent random junk # from being linted [*.{f90,F90}] indent_style = space indent_size = 4 trim_trailing_whitespace = true max_line_length = 132 insert_final_newline = true [{CMakeLists.txt, *.cmake}] indent_style = space indent_size = 2 trim_trailing_whitespace = true max_line_length = 132 insert_final_newline = true [*.md] max_line_length = off trim_trailing_whitespace = false charset = utf-8 insert_final_newline = true # Tab indentation (no size specified) [Makefile] indent_style = tab indent_size = 4 trim_trailing_whitespace = true max_line_length = 132 insert_final_newline = true [*.sh] indent_style = space indent_size = 2 trim_trailing_whitespace = true max_line_length = 132 insert_final_newline = true [*.nml] trim_trailing_whitespace = true max_line_length = 132 insert_final_newline = true [*.{yml,json}] indent_style = space indent_size = 2 trim_trailing_whitespace = true insert_final_newline = true fortran-lang-stdlib-0ede301/CHANGELOG.md0000664000175000017500000005667215135654166020017 0ustar alastairalastair# Version 0.8.1 Full release notes available at [v0.8.1] tag. [v0.8.1]: https://github.com/fortran-lang/stdlib/releases/tag/v0.8.1 Changes to the existing build system - Changes in the build system - Completed refactoring of `stdlib` into modular components using CMake [#1098](https://github.com/fortran-lang/stdlib/pull/1098) [#1100](https://github.com/fortran-lang/stdlib/pull/1100) [#1102](https://github.com/fortran-lang/stdlib/pull/1102) - Resolve race condition in parallel FYPP preprocessing [#1103](https://github.com/fortran-lang/stdlib/pull/1103) Changes to the existing modules - Change in module `stdlib_lingal_iterative_solvers` - Remove pure attribute from `stdlib_linop` `inner_product` [#1106](https://github.com/fortran-lang/stdlib/pull/1106) Changes to the existing documentation - Change in README - Addition of a DOI badge [#1097](https://github.com/fortran-lang/stdlib/pull/1097) - Update of the table with flags for modularizing `stdlib` [#1098](https://github.com/fortran-lang/stdlib/pull/1098) # Version 0.8.0 Full release notes available at [v0.8.0] tag. [v0.8.0]: https://github.com/fortran-lang/stdlib/releases/tag/v0.8.0 Summary of the most relevant pull requests (more than 100 total) - changes in module `stdlib_linalg` and related - Matrix Inverse [#828](https://github.com/fortran-lang/stdlib/pull/828) - Vector norms [#871](https://github.com/fortran-lang/stdlib/pull/871) - Matrix norms [#885](https://github.com/fortran-lang/stdlib/pull/885) - Cholesky factorization [#840](https://github.com/fortran-lang/stdlib/pull/840) - QR factorization [#832](https://github.com/fortran-lang/stdlib/pull/832) - Generalized eigenvalue problem [#909](https://github.com/fortran-lang/stdlib/pull/909) - Moore-Penrose pseudo-inverse [#899](https://github.com/fortran-lang/stdlib/pull/899) - Schur decomposition [#892](https://github.com/fortran-lang/stdlib/pull/892) - Matrix exponential [#1038](https://github.com/fortran-lang/stdlib/pull/1038) - Hermitian matrices [#896](https://github.com/fortran-lang/stdlib/pull/896) - Iterative solvers [#994](https://github.com/fortran-lang/stdlib/pull/994) - Bi-conjugate gradient stabilized method [#1034](https://github.com/fortran-lang/stdlib/pull/1034) - Pivoting QR decomposition [#1045](https://github.com/fortran-lang/stdlib/pull/1045) - Equality-constrained least-squares solver [#1046](https://github.com/fortran-lang/stdlib/pull/1046) - Generalized lagtm routine with support for arbitrary alpha and beta [#1068](https://github.com/fortran-lang/stdlib/pull/1068) - changes in module `stdlib_system` - `delete_file` [#966](https://github.com/fortran-lang/stdlib/pull/966) - `is_directory` [#946](https://github.com/fortran-lang/stdlib/pull/946) - `get_cwd` and `set_cwd` [#1014](https://github.com/fortran-lang/stdlib/pull/1014) - `exists` [#1026](https://github.com/fortran-lang/stdlib/pull/1026) - `null_device` [#945](https://github.com/fortran-lang/stdlib/pull/945) - `subprocessing` interface [#911](https://github.com/fortran-lang/stdlib/pull/911) - changes in module `stdlib_math` - Conversion functions: degrees-to-radians and vice versa [#845](https://github.com/fortran-lang/stdlib/pull/845) - changes in module `stdlib_intrinsics` - Extended intrinsic `matmul` for additional flexibility [#951](https://github.com/fortran-lang/stdlib/pull/951) - changes in module `stdlib_io` - Changes to `loadtxt`/`savetxt` [#877](https://github.com/fortran-lang/stdlib/pull/877) [#958](https://github.com/fortran-lang/stdlib/pull/958) - changes in module `stdlib_sorting` - `sort_index`: use only `int_index` iterators [#848](https://github.com/fortran-lang/stdlib/pull/848) - Addition of `sort_adj` [#849](https://github.com/fortran-lang/stdlib/pull/849) - improvements and fixes to existing modules - Fixes for factorial results, warnings, argument alignment, etc. [#876](https://github.com/fortran-lang/stdlib/pull/876) [#880](https://github.com/fortran-lang/stdlib/pull/880) [#879](https://github.com/fortran-lang/stdlib/pull/879) [#929](https://github.com/fortran-lang/stdlib/pull/929) - Fix sparse algebra support and examples [#760](https://github.com/fortran-lang/stdlib/pull/760) [#928](https://github.com/fortran-lang/stdlib/pull/928) - changes in CI/CD configurations - Upgrade CI/CD configurations [#854](https://github.com/fortran-lang/stdlib/pull/854) [#925](https://github.com/fortran-lang/stdlib/pull/925) [#1052](https://github.com/fortran-lang/stdlib/pull/1052) [#1072](https://github.com/fortran-lang/stdlib/pull/1072) [#1094](https://github.com/fortran-lang/stdlib/pull/1094) - build improvements - Changes in CMake configurations [#844](https://github.com/fortran-lang/stdlib/pull/844) [#923](https://github.com/fortran-lang/stdlib/pull/923) - Modularization [#1033](https://github.com/fortran-lang/stdlib/pull/1033) [#1050](https://github.com/fortran-lang/stdlib/pull/1050) [#1066](https://github.com/fortran-lang/stdlib/pull/1066) [#1081](https://github.com/fortran-lang/stdlib/pull/1081) - changes in documentation - Added tables summarizing preprocessing macros and flags [#1083](https://github.com/fortran-lang/stdlib/pull/1083) - Updated macOS architecture in README [#1059](https://github.com/fortran-lang/stdlib/pull/1059) - Added code coverage support [#1039](https://github.com/fortran-lang/stdlib/pull/1039) # Version 0.7.0 Full release notes available at [v0.7.0] tag. [v0.7.0]: https://github.com/fortran-lang/stdlib/releases/tag/v0.7.0 - new module `stdlib_constants` [#800](https://github.com/fortran-lang/stdlib/pull/800) - Many mathematical constants and most common physical ([codata](https://codata.org)) constants Changes to existing scripts and modules - changes in CI - Use of `fortran-setup` for GCC, Intel LLVM and Intel Classic [#834](https://github.com/fortran-lang/stdlib/pull/834) - change in module `stdlib_hashmaps` - Support of hash map key generic interfaces [#827](https://github.com/fortran-lang/stdlib/pull/827) - changes in module `stdlib_io` - Addition of a Fortran format specifier in `loadtxt` [#805](https://github.com/fortran-lang/stdlib/pull/805) - changes in module `stdlib_linalg` - Support of extended and quad precision checking [#821](https://github.com/fortran-lang/stdlib/pull/821) - Several fixes [#815](https://github.com/fortran-lang/stdlib/pull/815) [#818](https://github.com/fortran-lang/stdlib/pull/818) [#826](https://github.com/fortran-lang/stdlib/pull/826) [#830](https://github.com/fortran-lang/stdlib/pull/830) [#836](https://github.com/fortran-lang/stdlib/pull/836) - New procedures for Eigenvalues and Eigenvectors computation: `eig`, `eigh`, `eigvals`, `eigvalsh` [#816](https://github.com/fortran-lang/stdlib/pull/816) - New procedures for Singular Value Decomposition: `svd`, `svdvals` [#808](https://github.com/fortran-lang/stdlib/pull/808) - changes in module `stdlib_sorting` - Renamed variable from `int_size` to `int_index` [#824](https://github.com/fortran-lang/stdlib/pull/824) - Support of `int32` `index` array in `sort_index` [#829](https://github.com/fortran-lang/stdlib/pull/829) # Version 0.6.1 Full release notes available at [v0.6.1] tag. [v0.6.1]: https://github.com/fortran-lang/stdlib/releases/tag/v0.6.1 Changes to existing scripts and modules - changes in module `stdlib_linalg_lapack` - Renamed variable for compiler compliance [#812](https://github.com/fortran-lang/stdlib/pull/812) - change of the format in some example programs [#813](https://github.com/fortran-lang/stdlib/pull/813) # Version 0.6.0 Full release notes available at [v0.6.0] tag. [v0.6.0]: https://github.com/fortran-lang/stdlib/releases/tag/v0.6.0 - new script `fypp_deployment.py` to support `fpm` in combination with `fypp` files [#802](https://github.com/fortran-lang/stdlib/pull/802) Changes to existing scripts and modules - change in module `stdlib_hashmap_wrappers` - addition of `int32` hashmap key type [#778](https://github.com/fortran-lang/stdlib/pull/778) - changes in module `stdlib_linalg` - addition of the procedure `det` to compute determinants [#798](https://github.com/fortran-lang/stdlib/pull/798) - addition of the procedures `lstsq` and `lstsq_space` [#801](https://github.com/fortran-lang/stdlib/pull/801) [#809](https://github.com/fortran-lang/stdlib/pull/809) - addition of the procedures `solve` and `solve_lu` [#806](https://github.com/fortran-lang/stdlib/pull/806) - change in module `stdlib_linalg_blas` - addition of the documentation for `rotm` and `rotmg` [#795](https://github.com/fortran-lang/stdlib/pull/795) - use of macOS 12 in macOS CI [#807](https://github.com/fortran-lang/stdlib/pull/807) Changes to existing documentation - Improvement of the documentation `linalg` [#797](https://github.com/fortran-lang/stdlib/pull/797) # Version 0.5.0 Full release notes available at [v0.5.0] tag. [v0.5.0]: https://github.com/fortran-lang/stdlib/releases/tag/v0.5.0 - new module `stdlib_linalg_state` [#774](https://github.com/fortran-lang/stdlib/pull/774) - new derived type: `linalg_state_type` - new procedure: `linalg_error_handling` Changes to existing scripts and modules - addition of `implicit none` to all example programs [#780](https://github.com/fortran-lang/stdlib/pull/780) - change in module `stdlib_hashmaps` - fix the procedure `remove_chaining_entry` [#788](https://github.com/fortran-lang/stdlib/pull/788) - change in module `stdlib_linalg` - addition of the BLAS/LAPACK backends and interfaces [#772](https://github.com/fortran-lang/stdlib/pull/772) - change in module `stdlib_str2num` - fix the procedure `to_${k1}$_from_stream` [#789](https://github.com/fortran-lang/stdlib/pull/789) - upgrade of the Intel-classic compiler in macOS CI [#777](https://github.com/fortran-lang/stdlib/pull/777) Changes to existing documentation - Improvement of the documentation [#784](https://github.com/fortran-lang/stdlib/pull/784) [#781](https://github.com/fortran-lang/stdlib/pull/781) [#786](https://github.com/fortran-lang/stdlib/pull/786) - Improvement of the support of `fpm` [#787](https://github.com/fortran-lang/stdlib/pull/787) [#790](https://github.com/fortran-lang/stdlib/pull/790) # Version 0.4.0 Full release notes available at [v0.4.0] tag. [v0.4.0]: https://github.com/fortran-lang/stdlib/releases/tag/v0.4.0 - new module `stdlib_str2num` [#743](https://github.com/fortran-lang/stdlib/pull/743) - new procedures: `to_num`, `to_num_from_stream` Changes to existing scripts and modules - change in .gitignore - addition of the file extensions `.dat` and `.stream` [#768](https://github.com/fortran-lang/stdlib/pull/768) - addition of `.gitignore` to `stdlib-fpm` [#769](https://github.com/fortran-lang/stdlib/pull/769) - change in CI/CD - support of GCC 13 [#737](https://github.com/fortran-lang/stdlib/pull/737) - support of Intel compiler `ifx` [#752](https://github.com/fortran-lang/stdlib/pull/752) - change in script `fpm-deployment.sh` - changes to facilitate `fypp` preprocessing for the `fpm` deployment [#758](https://github.com/fortran-lang/stdlib/pull/758) - change in module `stdlib_ascii` - Improved procedures `to_lower` and `to_upper` [#733](https://github.com/fortran-lang/stdlib/pull/733) - change in module `stdlib_bitsets` - initialization in `bitset_type` [#753](https://github.com/fortran-lang/stdlib/pull/753) - improved procedure `bit_count_large` [#756](https://github.com/fortran-lang/stdlib/pull/756) - change in module `stdlib_hashmaps` - new procedure `get_all_keys` [#741](https://github.com/fortran-lang/stdlib/pull/741) - new file permissions [#762](https://github.com/fortran-lang/stdlib/pull/762) - change in module `stdlib_math` - new procedure `meshgrid` [#764](https://github.com/fortran-lang/stdlib/pull/764) - change in module `stdlib_specialfunctions_gamma` - fix procedure `gamma` [#730](https://github.com/fortran-lang/stdlib/pull/730) - change in module `stdlib_string_type` - fix procedure `move` [#736](https://github.com/fortran-lang/stdlib/pull/736) [#773](https://github.com/fortran-lang/stdlib/pull/773) - change in `SpookyV2Test.cpp` - Fix undefined use of types [#747](https://github.com/fortran-lang/stdlib/pull/747) Changes to the existing documentation - change in the specs `stdlib_hashmaps` - Correction of an intent of the variable "conflict" [#739](https://github.com/fortran-lang/stdlib/pull/739) - change in README.md - instructions to build `stdlib` with `fpm` through the `fpm-deployment.sh` script [#757](https://github.com/fortran-lang/stdlib/pull/757) # Version 0.3.0 Full release notes available at [v0.3.0] tag. [v0.3.0]: https://github.com/fortran-lang/stdlib/releases/tag/v0.3.0 - new modules `stdlib_hashmap_wrappers` and `stdlib_hashmap` [#611](https://github.com/fortran-lang/stdlib/pull/611) - new procedures in `stdlib_hashmap_wrappers`: `copy_key`, `copy_other`, `fibonacci_hash`, `fnv_1_hasher`, `fnv_1a_hasher`, `free_key`, `free_other`, `get`, `hasher_fun`, `operator(==)`, `seeded_nmhash32_hasher`, `seeded_nmhash32x_hasher`, `seeded_water_hasher`, `set`, `key_type`, `other_type` - new procedures in `stdlib_hashmaps`: `chaining_hashmap_type`, `hashmap_type`, `open_hashmap_type Changes to existing scripts and modules - change in script `doc-deployment.yml` - update of the script [#681](https://github.com/fortran-lang/stdlib/pull/681) - change in script `fpm-deployment.sh` - fixed a problem with `dat` and `npy` files in example dir not being deployed [#713](https://github.com/fortran-lang/stdlib/pull/713) - change in module `stdlib_bitsets` - remove define assignment for `bitset_64` and `bitset_large` [#727](https://github.com/fortran-lang/stdlib/pull/727) - change in module `stdlib_hashmap_open` - fix access violation in a type-bound procedure of `open_hashmap_type` [#707](https://github.com/fortran-lang/stdlib/pull/707) - change in module `stdlib_io_npy_load` - fix various bugs [#708](https://github.com/fortran-lang/stdlib/pull/708) [#711](https://github.com/fortran-lang/stdlib/pull/711) - change in module `stdlib_linalg` - addition of `kronecker_product` [#700](https://github.com/fortran-lang/stdlib/pull/700) - change in module `stdlib_quadrature_gauss` - fix erroneous gaussian quadrature points in `gauss_legendre` [#660](https://github.com/fortran-lang/stdlib/pull/660) - change in module `stdlib_sorting` - addition of radix sort [#712](https://github.com/fortran-lang/stdlib/pull/712) - support for sorting arrays of `bitset_64` and of `bitset_large` [#723](https://github.com/fortran-lang/stdlib/pull/723) - change in module `stdlib_stats_distribution_exponential` - convert `pdf_exp` and `cdf_exp` to `pure` functions [#717](https://github.com/fortran-lang/stdlib/pull/717) - change in module `stdlib_stats_distribution_normal` - convert `rvs_norm` to an `impure elemental` function [#665](https://github.com/fortran-lang/stdlib/pull/665) - remove unused module `stdlib_error` from module `stdlib_stats_distribution_normal` [#716](https://github.com/fortran-lang/stdlib/pull/716) - remove support for manual make builds [#657](https://github.com/fortran-lang/stdlib/pull/657) Changes to the existing documentation - change in README.md [#656](https://github.com/fortran-lang/stdlib/pull/656) [#659](https://github.com/fortran-lang/stdlib/pull/659) [#715](https://github.com/fortran-lang/stdlib/pull/715) [#725](https://github.com/fortran-lang/stdlib/pull/725) - change in `stdlib_stats_distribution_normal.md` - Improvement of the documentation [#718](https://github.com/fortran-lang/stdlib/pull/718) [#721](https://github.com/fortran-lang/stdlib/pull/721) - change in `stdlib_stats_distribution_exponential.md` - Improvement of the documentation [#721](https://github.com/fortran-lang/stdlib/pull/721) - change in the structure of the project `stdlib` - extraction of the demo programs from the specs in the directory example [#662](https://github.com/fortran-lang/stdlib/pull/662) - move the directory `src/tests` to `test` [#669](https://github.com/fortran-lang/stdlib/pull/669) - fix various docs [#663](https://github.com/fortran-lang/stdlib/pull/663) # Version 0.2.1 Full release notes available at [v0.2.1] tag. [v0.2.1]: https://github.com/fortran-lang/stdlib/releases/tag/v0.2.1 - build system related bugfixes # Version 0.2.0 Full release notes available at [v0.2.0] tag. [v0.2.0]: https://github.com/fortran-lang/stdlib/releases/tag/v0.2.0 - new module `stdlib_hash_32bit` [#573](https://github.com/fortran-lang/stdlib/pull/573) - new procedures: `fibonacci_hash`, `fnv_1_hash`, `fnv_1a_hash`, `new_nmhash32_seed`, `new_nmhash32x_seed`, `new_water_hash_seed`, `nmhash32`, `nmhash32x`, `odd_random_integer`, `universal_mult_hash`, and `water_hash` - new module `stdlib_hash_64bit` [#573](https://github.com/fortran-lang/stdlib/pull/573) - new procedures: `fibonacci_hash`, `fnv_1_hash`, `fnv_1a_hash`, `new_pengy_hash_seed`, `new_spooky_hash_seed`, `odd_random_integer`, `pengy_hash`, `spooky_hash`, `spookyhash_128`, and `universal_mult_hash` - new module `stdlib_array` [#603](https://github.com/fortran-lang/stdlib/pull/603) - new procedures `trueloc`, `falseloc` - new module `stdlib_distribution_uniform` [#272](https://github.com/fortran-lang/stdlib/pull/272) - new module `stdlib_selection` [#500](https://github.com/fortran-lang/stdlib/pull/500) - new procedures `select`, `arg_select` - new module `stdlib_version` [#579](https://github.com/fortran-lang/stdlib/pull/579) - new procedure `get_stdlib_version` - update module `stdlib_io` [597](https://github.com/fortran-lang/stdlib/pull/597) - new procedure `getline` - new module `stdlib_io_npy` [#581](https://github.com/fortran-lang/stdlib/pull/581) - new procedures `save_npy`, `load_npy` - update module `stdlib_math` - new procedures `is_close` and `all_close` [#488](https://github.com/fortran-lang/stdlib/pull/488) - new procedures `arg`, `argd` and `argpi` [#498](https://github.com/fortran-lang/stdlib/pull/498) - new procedure `diff` [#605](https://github.com/fortran-lang/stdlib/pull/605) Changes to existing modules - change in module `stdlib_math` - `linspace` and `logspace` made pure [#549](https://github.com/fortran-lang/stdlib/pull/549) - change in module `stdlib_string_type` - `move` procedure made *pure*/*elemental* [#562](https://github.com/fortran-lang/stdlib/pull/562) - support for quadruple precision made optional [#565](https://github.com/fortran-lang/stdlib/pull/565) - change in module `stdlib_io` - Modified format constants, and made public [#617](https://github.com/fortran-lang/stdlib/pull/617) - change in module `stdlib_math` - Minor update to `stdlib_math` module and document [#624](https://github.com/fortran-lang/stdlib/pull/624) # Version 0.1.0 Full release notes available at [v0.1.0] tag. [v0.1.0]: https://github.com/fortran-lang/stdlib/releases/tag/v0.1.0 - new module `stdlib_ascii` [#32](https://github.com/fortran-lang/stdlib/pull/32) - new module `stdlib_bitsets` [#239](https://github.com/fortran-lang/stdlib/pull/239) - new derived types `bitset_64` and `bitset_large` - new abstract base class `bitset_type` - new module `stdlib_error` [#53](https://github.com/fortran-lang/stdlib/pull/53) - new module `stdlib_io` - new procedures `loadtxt` and `savetxt` [#23](https://github.com/fortran-lang/stdlib/pull/23) [#37](https://github.com/fortran-lang/stdlib/pull/37) - new procedure `open` [#71](https://github.com/fortran-lang/stdlib/pull/71) [#77](https://github.com/fortran-lang/stdlib/pull/77) - new module `stdlib_kinds` [#63](https://github.com/fortran-lang/stdlib/pull/63) - new module `stdlib_linalg` - new procedures `diag`, `eye` and `trace` [#170](https://github.com/fortran-lang/stdlib/pull/170) - new procedure `outer_product` [#432](https://github.com/fortran-lang/stdlib/pull/432) - new module `stdlib_logger` - new derived type `logger_type` [#228](https://github.com/fortran-lang/stdlib/pull/228) [#261](https://github.com/fortran-lang/stdlib/pull/261) - new module `stdlib_math` - new procedure `clip` [#355](https://github.com/fortran-lang/stdlib/pull/355) - new procedures `linspace` and `logspace` [#420](https://github.com/fortran-lang/stdlib/pull/420) - new procedure `arange` [#480](https://github.com/fortran-lang/stdlib/pull/480) - new procedure `gcd` [#539](https://github.com/fortran-lang/stdlib/pull/539) - new module `stdlib_optval` [#73](https://github.com/fortran-lang/stdlib/pull/73) [#96](https://github.com/fortran-lang/stdlib/pull/96) [#139](https://github.com/fortran-lang/stdlib/pull/139) - new module `stdlib_quadrature` - new procedures `trapz`, `trapz_weights`, `simps` and `simps_weights` [#146](https://github.com/fortran-lang/stdlib/pull/146) - new procedures `gauss_legendre`, `gauss_legendre_lobatto` [#313](https://github.com/fortran-lang/stdlib/pull/313) - new module `stdlib_random` [#271](https://github.com/fortran-lang/stdlib/pull/271) - new module `stdlib_sorting` - new procedures `sort`, `ord_sort` and `sort_index` [#408](https://github.com/fortran-lang/stdlib/pull/408) - new module `stdlib_specialfunctions` - new procedures `legendre` and `dlegendre` [#313](https://github.com/fortran-lang/stdlib/pull/313) - new module `stdlib_stats` - new procedure `mean` [#124](https://github.com/fortran-lang/stdlib/pull/124) [#130](https://github.com/fortran-lang/stdlib/pull/130) [#132](https://github.com/fortran-lang/stdlib/pull/132) - new procedure `var` [#144](https://github.com/fortran-lang/stdlib/pull/144) - new procedure `moment` [#153](https://github.com/fortran-lang/stdlib/pull/153) - new procedure `corr` [#191](https://github.com/fortran-lang/stdlib/pull/191) - new procedure `median` [#426](https://github.com/fortran-lang/stdlib/pull/426) - new module `stdlib_string_type` - new derived types `string_type` [#320](https://github.com/fortran-lang/stdlib/pull/320) - new procedure `move` [#467](https://github.com/fortran-lang/stdlib/pull/467) - new module `stdlib_stringlist_type` - new derived types `stringlist_type` and `stringlist_index_type` [#470](https://github.com/fortran-lang/stdlib/pull/470) - new module `stdlib_strings` - new procedure `to_string` [#444](https://github.com/fortran-lang/stdlib/pull/444) - new procedures `strip` and `chomp` [#343](https://github.com/fortran-lang/stdlib/pull/343) - new procedures `starts_with` and `ends_with` [#384](https://github.com/fortran-lang/stdlib/pull/384) - new procedure `slice` [#414](https://github.com/fortran-lang/stdlib/pull/414) - new procedure `find` [#433](https://github.com/fortran-lang/stdlib/pull/433) - new procedure `replace_all` [#436](https://github.com/fortran-lang/stdlib/pull/436) - new procedures `padl` and `padr` [#441](https://github.com/fortran-lang/stdlib/pull/441) - new procedure `count` [#453](https://github.com/fortran-lang/stdlib/pull/453) - new module `stdlib_system` - new procedure `sleep` [#54](https://github.com/fortran-lang/stdlib/pull/54) fortran-lang-stdlib-0ede301/doc/0000775000175000017500000000000015135654166016733 5ustar alastairalastairfortran-lang-stdlib-0ede301/doc/media/0000775000175000017500000000000015135654166020012 5ustar alastairalastairfortran-lang-stdlib-0ede301/doc/media/favicon.ico0000664000175000017500000004107615135654166022143 0ustar alastairalastair@@ (B(@ Pu#PssPsPsږOrOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOrOsٕPsNrrSq"MwNsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsPtPu#Nr\OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsNs[Os~OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsPr}Ps]OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOtZNq$OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsMt!OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsNq$OsOsOsOsOsOsOsǡOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsPu#OrtOsOsOsOsOsOsOsǡOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsqOsOsOsOsOsOsOsOsǠOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOrOsܖOsOsOsOsOsOsOsŞOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsٖOrOsOsOsOsOsOsOs{ĜOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsbѲչؾӶpOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsPt]OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOspOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsٿkOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs׽hOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs׽dOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs׼aOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs׻_OsOsOsOsOsOsOsOsչOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsֻ[}OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsֺXzOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsֺVxOsOsOsOsOsOsOsRvOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsֺUwOsOsOsOsOsOsOshOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsչTwOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsչRvOsOsOsOsOsOsOsѲOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsոQuOsOsOsOsOsOsSvOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsոPtOsOsOsOsOsOsҴOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsԷOsOsOsOsRu}OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsԷ̩չOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsԷOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsԷOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsԷOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsԷOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsոOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsոQuQuarϯOsOsOsOsOsOsOsdέҴչչ׻oOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsչQuOsOsOsOsOs[}OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsչQuOsOsOsOsOsOs^OsOsOsOsOsOsOsȣOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsֺQuOsOsOsOsOsOsOsѲOsOsOsOsOsOsOsӵOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsֺQuOsOsOsOsOsOsOs}OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsֻQuOsOsOsOsOsOsOs]~OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsֻQuOsOsOsOsOsOsOsOsOsOsOsOsOsOsPtOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs׻QuOsOsOsOsOsOsOsOsOsOsOsOsOsOsgOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs׼QuOsOsOsOsOsOsOsOsӴOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs׼QuOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsٿOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs׽QuOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsXzOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsٿQuOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs˧OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsQuOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOstOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsQuOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsyOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsQuOsOsOsOsOsOsOsOsOsOsOsOsOsOsUw|ٿOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsgέέӴήέέέέչչչٿOsOsOsOsOsOsOsOsOrOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsNsݖOsOsOsOsOsOsOsOsOsOsOsOsOsOsPsڗOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsPsNtuOsOsOsOsOsOsOsOsOsOsOsOsOsOsNrrLu%OsOsOsOsOsOsOsOsOsOsOsOsOsOsPu#PtOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsLu%OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsSq"Or^OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsNrbPtOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs~PsYOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsPr`RsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsPtLu%Lu%NtuOsOsۖOrOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOrOsۗOsOrtNq$fortran-lang-stdlib-0ede301/doc/specs/0000775000175000017500000000000015135654166020050 5ustar alastairalastairfortran-lang-stdlib-0ede301/doc/specs/stdlib_error.md0000664000175000017500000000420215135654166023062 0ustar alastairalastair--- title: error --- # The `stdlib_error` module [TOC] ## Introduction Catching and handling errors. ## Procedures and methods provided ### `check` - Checks the value of a logical condition #### Status Experimental #### Description Checks the value of a logical condition. #### Syntax `call ` [[check(subroutine)]] `(condition, msg, code, warn)` #### Arguments `condition`: Shall be a scalar of type `logical`. `msg` (optional): Shall be a character expression containing the message to be printed to `stderr`. The default `msg` is 'Check failed.'. `code` (optional): Shall be a scalar of type `integer`. The default `code` is `1`. `warn` (optional): Shall be a scalar of type `logical`. The default `warn` is `.true.`. #### Return value If `condition` is `.false.`, and: * no other arguments are provided, this subroutine stops the program with the default message and exit code 1; * `msg` is provided, this subroutine stops the program and it prints the value of `msg`; * `code` is provided, this subroutine stops the program with the given exit code; * `warn` is provided and `warn` is `.true.`, this subroutine doesn't stop the program and prints the message. #### Examples ```fortran {!example/error/example_check1.f90!} ``` ```fortran {!example/error/example_check2.f90!} ``` ```fortran {!example/error/example_check3.f90!} ``` ```fortran {!example/error/example_check4.f90!} ``` ### `error_stop` - aborts the program #### Status Experimental #### Description Aborts the program with a message and a nonzero exit code. #### Syntax `call ` [[stdlib_error(module):error_stop(interface)]] `(msg, code)` #### Arguments `msg`: Shall be a character expression containing the message to be printed to `stderr`. `code` (optional): Shall be a scalar of type `integer` to be returned as exit code. #### Output Aborts the program with printing the message `msg` to `stderr` and a nonzero exit code. The nonzero exit code is equal to `code` if provided, and 1 otherwise. #### Examples Without error code: ```fortran {!example/error/example_error_stop1.f90!} ``` With error code: ```fortran {!example/error/example_error_stop2.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_sorting.md0000664000175000017500000010556515135654166023434 0ustar alastairalastair--- title: sorting --- # The `stdlib_sorting` module [TOC] ## Overview of sorting The sorting of collections of data is useful in the analysis of those collections. With its absence of generics and limited polymorphism, it is impractical, in current Fortran, to provide sorting routines for arbitrary collections of arbitrary types of data. However Fortran's arrays are by far its most widely used collection, and arrays of arbitrary types of data can often be sorted in terms of a single component of intrinsic type. The Fortran Standard Library therefore provides a module, `stdlib_sorting`, with procedures to sort arrays of simple intrinsic numeric types, i.e. the different kinds of integers and reals, the default assumed length character, and the `stdlib_string_type` module's `string_type` type. ## Overview of the module The module `stdlib_sorting` defines several public entities, two default integer parameters, `int_index` and `int_index_low`, and four overloaded subroutines: `ORD_SORT`, `SORT`, `RADIX_SORT` and `SORT_INDEX`. The overloaded subroutines also each have several specific names for versions corresponding to different types of array arguments. ### The parameters `int_index` and `int_index_low` The parameters `int_index` and `int_index_low` are used to specify the kind of integer used in indexing the various arrays. Currently the module sets `int_index` and `int_index_low` to the value of `int64` and `int32` from the `stdlib_kinds` module, respectively. ### The module subroutines The `stdlib_sorting` module provides three different overloaded subroutines intended to sort three different kinds of arrays of data: * `ORD_SORT` is intended to sort simple arrays of intrinsic data that have significant sections that were partially ordered before the sort; * `SORT_ADJOINT` is based on `ORD_SORT`, but in addition to sorting the input array, it re-orders a second array of the same size according to the same permutations; * `SORT_INDEX` is based on `ORD_SORT`, but in addition to sorting the input array, it returns indices that map the original array to its sorted version. This enables related arrays to be re-ordered in the same way; * `SORT` is intended to sort simple arrays of intrinsic data that are effectively unordered before the sort; * `RADIX_SORT` is intended to sort fixed width intrinsic data types (integers and reals). #### Licensing The Fortran Standard Library is distributed under the MIT License. However components of the library may be based on code with additional licensing restrictions. In particular `ORD_SORT`, `SORT_ADJOINT`, `SORT_INDEX`, and `SORT` are translations of codes with their own distribution restrictions. The `ORD_SORT`, `SORT_ADJOINT` and `SORT_INDEX` subroutines are essentially translations to Fortran 2008 of the `"Rust" sort` of the Rust Language distributed as part of [`slice.rs`](https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs). The header of the `slice.rs` file has as its licensing requirements: Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT file at the top-level directory of this distribution and at http://rust-lang.org/COPYRIGHT. Licensed under the Apache License, Version 2.0 or the MIT license , at your option. This file may not be copied, modified, or distributed except according to those terms. So the license for the `slice.rs` code is compatible with the use of modified versions of the code in the Fortran Standard Library under the MIT license. The `SORT` subroutine is essentially a translation to Fortran 2008 of the [`introsort`]((http://www.cs.rpi.edu/~musser/gp/introsort.ps) of David Musser. David Musser has given permission to include a variant of `introsort` in the Fortran Standard Library under the MIT license provided we cite: Musser, D.R., “Introspective Sorting and Selection Algorithms,” Software—Practice and Experience, Vol. 27(8), 983–993 (August 1997). as the official source of the algorithm. #### The `ORD_SORT` subroutine `ORD_SORT` is a translation of the `"Rust" sort` sorting algorithm contained in [`slice.rs`] (https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs). `"Rust" sort`, in turn, is inspired by the [`timsort` algorithm] (http://svn.python.org/projects/python/trunk/Objects/listsort.txt) that Tim Peters created for the Python Language. `ORD_SORT` is a hybrid stable comparison algorithm combining `merge sort`, and `insertion sort`. It has always at worst O(N Ln(N)) runtime performance in sorting random data, having a performance about 15-25% slower than `SORT` on such data. However it has much better performance than `SORT` on partially sorted data, having O(N) performance on uniformly increasing or decreasing data. When sorting in an increasing order, `ORD_SORT` begins by traversing the array starting in its tail attempting to identify `runs` in the array, where a run is either a uniformly decreasing sequence, `ARRAY(i-1) > ARRAY(i)`, or a non-decreasing, `ARRAY(i-1) <= ARRAY(i)`, sequence. First delimited decreasing sequences are reversed in their order. Then, if the sequence has less than `MIN_RUN` elements, previous elements in the array are added to the run using `insertion sort` until the run contains `MIN_RUN` elements or the array is completely processed. As each run is identified the start and length of the run are then pushed onto a stack and the stack is then processed using `merge` until it obeys the stack invariants: 1. len(i-2) > len(i-1) + len(i) 2. len(i-1) > len(i) ensuring that processing the stack is, at worst, of order `O(N Ln(N))`. However, because of the identification of decreasing and non-decreasing runs, processing of structured data can be much faster, with processing of uniformly decreasing or non-decreasing arrays being of order O(N). The result in our tests is that `ORD_SORT` is about 25% slower than `SORT` on purely random data, depending on the compiler, but can be `Ln(N)` faster than `SORT` on highly structured data. As a modified `merge sort`, `ORD_SORT` requires the use of a "scratch" array, that may be provided as an optional `work` argument or allocated internally on the stack. Arrays can be also sorted in a decreasing order by providing the argument `reverse = .true.`. #### The `SORT_ADJOINT` subroutine The `SORT` and `ORD_SORT` subroutines can sort rank 1 isolated arrays of intrinsic types, but do nothing for the coordinated sorting of related data, e.g., a related rank 1 array. Therefore the module provides a subroutine, `SORT_ADJOINT`, that re-order such a rank 1 array according to the same permutations as for the input array based on the `ORD_SORT` algorithm, in addition to sorting the input array. The logic of `SORT_ADJOINT` parallels that of `ORD_SORT`, with additional housekeeping to keep the associated array consistent with the sorted positions of the input array. Because of this additional housekeeping it has slower runtime performance than `ORD_SORT`. `SORT_ADJOINT` requires the use of two "scratch" arrays, that may be provided as optional `work` and `iwork` arguments or allocated internally on the stack. #### The `SORT_INDEX` subroutine The `SORT` and `ORD_SORT` subroutines can sort rank 1 isolated arrays of intrinsic types, but do nothing for the coordinated sorting of related data, e.g., multiple related rank 1 arrays, higher rank arrays, or arrays of derived types. For such related data, what is useful is an array of indices that maps a rank 1 array to its sorted form. For such a sort, a stable sort is useful, therefore the module provides a subroutine, `SORT_INDEX`, that generates such an array of indices based on the `ORD_SORT` algorithm, in addition to sorting the input array. The logic of `SORT_INDEX` parallels that of `ORD_SORT`, with additional housekeeping to keep the array of indices consistent with the sorted positions of the input array. Because of this additional housekeeping it has slower runtime performance than `ORD_SORT`. `SORT_INDEX` requires the use of two "scratch" arrays, that may be provided as optional `work` and `iwork` arguments or allocated internally on the stack. #### The `SORT` subroutine `SORT` uses the `introsort` sorting algorithm of David Musser. `introsort` is a hybrid unstable comparison algorithm combining `quicksort`, `insertion sort`, and `heap sort`. While this algorithm's runtime performance is always O(N Ln(N)), it is relatively fast on randomly ordered data, but does not show the improvement in performance on partly sorted data found for `ORD_SORT`. First it examines the array and estimates the depth of recursion a quick sort would require for ideal (random) data, `D = Ceiling(Ln(N)/Ln(2))`. It then defines a limit to the number of `quicksort` recursions to be allowed in processing, `D_limit = factor * D`, where factor is currently 2, and calls `introsort` proper. `introsort` proper then: 1. Examines the number of elements remaining to be sorted, and, if they are less than 16, sorts them using insertion sort and returns; 2. If they are not less than 16, checks whether the current depth of recursion exceeds `D_limit` and, if it does, processes the remaining elements with heap sort and returns; 3. If the current depth of recursion does not exceed `D_limit`, then in effect does a `quicksort` step: * Partitions the remaining array using a median of three, * Calls `introsort` proper on the leftmost partition, * Calls `introsort` proper on the rightmost partition, and then returns. The resulting algorithm is of order O(N Ln(N)) run time performance for all inputs. Because it relies on `quicksort`, the coefficient of the O(N Ln(N)) behavior is typically small compared to other sorting algorithms on random data. On partially sorted data it can show either slower `heap sort` performance, or enhanced performance by up to a factor of six. Still, even when it shows enhanced performance, its performance on partially sorted data is typically an order of magnitude slower than `ORD_SORT`. Its memory requirements are also low, being of order O(Ln(N)), while the memory requirements of `ORD_SORT`, `SORT_ADJOINT` and `SORT_INDEX` are of order O(N). #### The `RADIX_SORT` subroutine `RADIX_SORT` is a implementation of LSD [radix sort](https://www.growingwiththeweb.com/sorting/radix-sort-lsd/), using `256` as the radix. It only works for fixed width data, thus integers and reals. `RADIX_SORT` is always of O(N) runtime performance for any input data. For large and random data, it is about five (or more) times faster than other sort subroutines. The `RADIX_SORT` needs a buffer that have same size of the input data. Your can provide it using `work` argument, if not the subroutine will allocate the buffer and deallocate before return. ### Specifications of the `stdlib_sorting` procedures #### `ord_sort` - sorts an input array ##### Status Experimental ##### Description Returns an input `array` with the elements sorted in order of increasing, or decreasing, value. ##### Syntax `call ` [[stdlib_sorting(module):ord_sort(interface)]] `( array[, work, reverse ] )` ##### Class Generic subroutine. ##### Arguments `array` : shall be a rank one array of any of the types: `integer(int8)`, `integer(int16)`, `integer(int32)`, `integer(int64)`, `real(sp)`, `real(dp)`, `real(qp)`, `character(*)`, `type(string_type)`, `type(bitset_64)`, or `type(bitset_large)`. It is an `intent(inout)` argument. On input it is the array to be sorted. If both the type of `array` is real and at least one of the elements is a `NaN`, then the ordering of the result is undefined. Otherwise on return its elements will be sorted in order of non-decreasing value. `work` (optional): shall be a rank one array of the same type as array, and shall have at least `size(array)/2` elements. It is an `intent(out)` argument. It is intended to be used as "scratch" memory for internal record keeping. If associated with an array in static storage, its use can significantly reduce the stack memory requirements for the code. Its contents on return are undefined. `reverse` (optional): shall be a scalar of type default logical. It is an `intent(in)` argument. If present with a value of `.true.` then `array` will be sorted in order of non-increasing values in stable order. Otherwise index will sort `array` in order of non-decreasing values in stable order. ##### Notes `ORD_SORT` implements a hybrid sorting algorithm combining `merge sort`, and `insertion sort`. For most purposes it behaves like a `merge sort`, providing worst case `O(N Ln(N))` run time performance for most random arrays, that is typically slower than `SORT`. However, if the array has significant runs of decreasing or non-decreasing values, performance can be much better than `SORT`, with `O(N)` behavior on uniformly decreasing, or non-decreasing arrays. The optional `work` array replaces "scratch" memory that would otherwise be allocated on the stack. If `array` is of any type `REAL` the order of its elements on return undefined if any element of `array` is a `NaN`. Sorting of `CHARACTER(*)` and `STRING_TYPE` arrays are based on the operators `>` and `<`, and not on the function `LGT`. ##### Example ```fortran {!example/sorting/example_ord_sort.f90!} ``` #### `sort` - sorts an input array ##### Status Experimental ##### Description Returns an input array with the elements sorted in order of increasing, or decreasing, value. ##### Syntax `call ` [[stdlib_sorting(module):sort(interface)]] `( array[, reverse] )` ##### Class Pure generic subroutine. ##### Arguments `array` : shall be a rank one array of any of the types: `integer(int8)`, `integer(int16)`, `integer(int32)`, `integer(int64)`, `real(sp)`, `real(dp)`, `real(qp)`. `character(*)`, `type(string_type)`, `type(bitset_64)`, or `type(bitset_large)`. It is an `intent(inout)` argument. On return its input elements will be sorted in order of non-decreasing value. `reverse` (optional): shall be a scalar of type default logical. It is an `intent(in)` argument. If present with a value of `.true.` then `array` will be sorted in order of non-increasing values in unstable order. Otherwise index will sort `array` in order of non-decreasing values in unstable order. ##### Notes `SORT` implements a hybrid sorting algorithm combining `quicksort`, `merge sort`, and `insertion sort`. For most purposes it behaves like a `quicksort` with a median of three partition, providing good, `O(N Ln(N))`, run time performance for most random arrays, but defaulting to `merge sort` if the structure of the array results in the `quicksort` not converging as rapidly as expected. If `array` is of any type `REAL`, the behavior of the sorting is undefined if any element of `array` is a `NaN`. Sorting of `CHARACTER(*)` and `STRING_TYPE` arrays are based on the operators `<`, `<=`, `>`, and `>=`, and not on the functions `LLT`, `LLE`, `LGT`, or `LGE`. ##### Example ```fortran {!example/sorting/example_sort.f90!} ``` #### `radix_sort` - sorts an input array ##### Status Experimental ##### Description Returns an input array with the elements sorted in order of increasing, or decreasing, value. ##### Syntax `call ` [[stdlib_sorting(module):radix_sort(interface)]] `( array[, work, reverse] )` ##### Class Generic subroutine. ##### Arguments `array` : shall be a rank one array of any of the types: `integer(int8)`, `integer(int16)`, `integer(int32)`, `integer(int64)`, `real(sp)`, `real(dp)`. It is an `intent(inout)` argument. On return its input elements will be sorted in order of non-decreasing value. `work` (optional): shall be a rank one array of the same type as array, and shall have at least `size(array)` elements. It is an `intent(inout)` argument, and its contents on return are undefined. `reverse` (optional): shall be a scalar of type default `logical`. It is an `intent(in)` argument. If present with a value of `.true.` then `array` will be sorted in order of non-increasing values in unstable order. Otherwise index will sort `array` in order of non-decreasing values in unstable order. ##### Notes `radix_sort` implements a LSD radix sort algorithm with a `256` radix. For any input data it provides `O(N)` run time performance. If `array` is of any type `real` the order of its elements on return undefined if any element of `array` is a `NaN`. ##### Example ```fortran {!example/sorting/example_radix_sort.f90!} ``` #### `sort_adjoint` - sorts an associated array according to the same permutations as for the input array. ##### Status Experimental ##### Description Returns the input `array` sorted in the direction requested while retaining order stability, and an associated array whose elements are sorted according to the same permutations as for the input `array`. ##### Syntax `call ` [[stdlib_sorting(module):sort_adjoint(interface)]] `( array, adjoint_array[, work, iwork, reverse ] )` ##### Class Generic subroutine. ##### Arguments `array`: shall be a rank one array of any of the types: `integer(int8)`, `integer(int16)`, `integer(int32)`, `integer(int64)`, `real(sp)`, `real(dp)`, `real(qp)`, `character(*)`, `type(string_type)`, `type(bitset_64)`, or `type(bitset_large)`. It is an `intent(inout)` argument. On input it will be an array whose sorting indices are to be determined. On return it will be the sorted array. `adjoint_array`: shall be a rank one `integer` or `real` array of the size of `array`. It is an `intent(inout)` argument. On return it shall have values that are the indices needed to sort the original array in the desired direction. `work` (optional): shall be a rank one array of any of the same type as `array`, and shall have at least `size(array)/2` elements. It is an `intent(out)` argument. It is intended to be used as "scratch" memory for internal record keeping. If associated with an array in static storage, its use can significantly reduce the stack memory requirements for the code. Its contents on return are undefined. `iwork` (optional): shall be a rank one integer array of the same kind of the array `adjoint_array`, and shall have at least `size(array)/2` elements. It is an `intent(out)` argument. It is intended to be used as "scratch" memory for internal record keeping. If associated with an array in static storage, its use can significantly reduce the stack memory requirements for the code. Its contents on return are undefined. `reverse` (optional): shall be a scalar of type default logical. It is an `intent(in)` argument. If present with a value of `.true.` then `array` will be sorted in order of non-increasing values in stable order. Otherwise `array` will be sorted in order of non-decreasing values in stable order. ##### Notes `SORT_ADJOINT` implements the hybrid sorting algorithm of `ORD_SORT`, keeping the values of `adjoint_array` consistent with the elements of `array` as it is sorted. As a `merge sort` based algorithm, it is a stable sorting comparison algorithm. The optional `work` and `iwork` arrays replace "scratch" memory that would otherwise be allocated on the stack. If `array` is of any kind of `REAL` the order of the elements in `adjoint_array` and `array` on return are undefined if any element of `array` is a `NaN`. Sorting of `CHARACTER(*)` and `STRING_TYPE` arrays are based on the operator `>`, and not on the function `LGT`. It should be emphasized that the order of `array` will typically be different on return ##### Examples Sorting a rank one array with `sort_adjoint`: ```Fortran {!example/sorting/example_sort_adjoint.f90!} ``` #### `sort_index` - creates an array of sorting indices for an input array, while also sorting the array. ##### Status Experimental ##### Description Returns the input `array` sorted in the direction requested while retaining order stability, and an integer array whose elements would sort the input `array` to produce the output `array`. ##### Syntax `call ` [[stdlib_sorting(module):sort_index(interface)]] `( array, index[, work, iwork, reverse ] )` ##### Class Generic subroutine. ##### Arguments `array`: shall be a rank one array of any of the types: `integer(int8)`, `integer(int16)`, `integer(int32)`, `integer(int64)`, `real(sp)`, `real(dp)`, `real(qp)`, `character(*)`, `type(string_type)`, `type(bitset_64)`, or `type(bitset_large)`. It is an `intent(inout)` argument. On input it will be an array whose sorting indices are to be determined. On return it will be the sorted array. `index`: shall be a rank one integer array of kind `int_index` or `int_index_low` and of the size of `array`. It is an `intent(out)` argument. On return it shall have values that are the indices needed to sort the original array in the desired direction. `work` (optional): shall be a rank one array of any of the same type as `array`, and shall have at least `size(array)/2` elements. It is an `intent(out)` argument. It is intended to be used as "scratch" memory for internal record keeping. If associated with an array in static storage, its use can significantly reduce the stack memory requirements for the code. Its contents on return are undefined. `iwork` (optional): shall be a rank one integer array of the same kind of the array `index`, and shall have at least `size(array)/2` elements. It is an `intent(out)` argument. It is intended to be used as "scratch" memory for internal record keeping. If associated with an array in static storage, its use can significantly reduce the stack memory requirements for the code. Its contents on return are undefined. `reverse` (optional): shall be a scalar of type default logical. It is an `intent(in)` argument. If present with a value of `.true.` then `index` will sort `array` in order of non-increasing values in stable order. Otherwise index will sort `array` in order of non-decreasing values in stable order. ##### Notes `SORT_INDEX` implements the hybrid sorting algorithm of `ORD_SORT`, keeping the values of `index` consistent with the elements of `array` as it is sorted. As a `merge sort` based algorithm, it is a stable sorting comparison algorithm. The optional `work` and `iwork` arrays replace "scratch" memory that would otherwise be allocated on the stack. If `array` is of any kind of `REAL` the order of the elements in `index` and `array` on return are undefined if any element of `array` is a `NaN`. Sorting of `CHARACTER(*)` and `STRING_TYPE` arrays are based on the operator `>`, and not on the function `LGT`. It should be emphasized that the order of `array` will typically be different on return ##### Examples Sorting a rank one array with `sort_index`: ```Fortran {!example/sorting/example_sort_index.f90!} ``` Sorting a related rank one array: ```Fortran subroutine sort_related_data( a, b, work, index, iwork ) ! Sort `a`, and also sort `b` to be reorderd the same way as `a` integer, intent(inout) :: a(:) integer(int32), intent(inout) :: b(:) ! The same size as a integer(int32), intent(out) :: work(:) integer(int_index), intent(out) :: index(:) integer(int_index), intent(out) :: iwork(:) ! Find the indices to sort a call sort_index(a, index(1:size(a)),& work(1:size(a)/2), iwork(1:size(a)/2)) ! Sort b based on the sorting of a b(:) = b( index(1:size(a)) ) end subroutine sort_related_data ``` Sorting a rank 2 array based on the data in a column ```Fortran subroutine sort_related_data( array, column, work, index, iwork ) ! Reorder rows of `array` such that `array(:, column)` is sorted integer, intent(inout) :: array(:,:) integer(int32), intent(in) :: column integer(int32), intent(out) :: work(:) integer(int_index), intent(out) :: index(:) integer(int_index), intent(out) :: iwork(:) integer, allocatable :: dummy(:) integer :: i allocate(dummy(size(array, dim=1))) ! Extract a column of `array` dummy(:) = array(:, column) ! Find the indices to sort the column call sort_index(dummy, index(1:size(dummy)),& work(1:size(dummy)/2), iwork(1:size(dummy)/2)) ! Sort a based on the sorting of its column do i=1, size(array, dim=2) array(:, i) = array(index(1:size(array, dim=1)), i) end do end subroutine sort_related_data ``` Sorting an array of a derived type based on the data in one component ```fortran subroutine sort_a_data( a_data, a, work, index, iwork ) ! Sort `a_data` in terms of its component `a` type(a_type), intent(inout) :: a_data(:) integer(int32), intent(inout) :: a(:) integer(int32), intent(out) :: work(:) integer(int_index), intent(out) :: index(:) integer(int_index), intent(out) :: iwork(:) ! Extract a component of `a_data` a(1:size(a_data)) = a_data(:) % a ! Find the indices to sort the component call sort_index(a(1:size(a_data)), index(1:size(a_data)),& work(1:size(a_data)/2), iwork(1:size(a_data)/2)) ! Sort a_data based on the sorting of that component a_data(:) = a_data( index(1:size(a_data)) ) end subroutine sort_a_data ``` ### Performance benchmarks We have performed benchmarks of the procedures on nine different integer arrays each of size `2**16`: * Blocks - the array is divided into six blocks, each of distinct uniformly increasing integers. * Decreasing - values decrease uniformly from `2**16-1` to `0`. * Identical - all integers have the same value of 10. * Increasing - values increase uniformly from `0` to `2**16-1`. * Random dense - the integers are generated randomly from a set of values from `0` to `2**14-1` so duplicates are dense. * Random order - a set of integers from `0` to `2**16 - 1` in random order. * Random sparse - the integers are generated randomly from a set of values from `0` to `2**18-1` so duplicates are sparse. * Random-3 - the increasing array has 3 random exchanges of individual elements. * Random-10 - the final ten elements of the increasing array are replaced by random values. On three different default character arrays, each of length 4 and of size `20**4, with characters drawn from the set "a"-"p": * Char. Decreasing - values decrease uniformly from `"pppp"` to `"aaaa"`. * Char. Increasing - values decrease uniformly from `"aaaa"` to `"pppp"`. * Char. Random - the set of strings from `"aaaa"` to `"pppp"` in random order. On three different `string_type` arrays, each of length 4 elements and of size `16**3`, with characters drawn from the set "a"-"p": * String Decreasing - values decrease uniformly from `"ppp"` to `"aaa"`. * String Increasing - values decrease uniformly from `"aaa"` to `"ppp"`. * String Random - the set of strings from `"aaa"` to `"ppp"` in random order. These benchmarks have been performed on two different compilers, both on WSL with Ubuntu-20.04, Intel(R) Core(TM) i7-10700 CPU @ 2.9GHz, with 32 GB DDR4 memory. The first compiler is GNU Fortran (GCC) 9.4.0, with the following results. | Type | Elements | Array Name | Method | Time (s) | |-------------|----------|-----------------|-------------|-----------| | Integer | 65536 | Blocks | Ord_Sort | 0.001048 | | Integer | 65536 | Decreasing | Ord_Sort | 0.000204 | | Integer | 65536 | Identical | Ord_Sort | 0.000097 | | Integer | 65536 | Increasing | Ord_Sort | 0.000096 | | Integer | 65536 | Random dense | Ord_Sort | 0.006580 | | Integer | 65536 | Random order | Ord_Sort | 0.006886 | | Integer | 65536 | Random sparse | Ord_Sort | 0.006821 | | Integer | 65536 | Random 3 | Ord_Sort | 0.000461 | | Integer | 65536 | Random 10 | Ord_Sort | 0.000226 | | Character | 65536 | Char. Decrease | Ord_Sort | 0.000824 | | Character | 65536 | Char. Increase | Ord_Sort | 0.000370 | | Character | 65536 | Char. Random | Ord_Sort | 0.016020 | | String_type | 4096 | String Decrease | Ord_Sort | 0.000465 | | String_type | 4096 | String Increase | Ord_Sort | 0.000169 | | String_type | 4096 | String Random | Ord_Sort | 0.004194 | | Integer | 65536 | Blocks | Radix_Sort | 0.001610 | | Integer | 65536 | Decreasing | Radix_Sort | 0.001076 | | Integer | 65536 | Identical | Radix_Sort | 0.001074 | | Integer | 65536 | Increasing | Radix_Sort | 0.001060 | | Integer | 65536 | Random dense | Radix_Sort | 0.001161 | | Integer | 65536 | Random order | Radix_Sort | 0.001069 | | Integer | 65536 | Random sparse | Radix_Sort | 0.001005 | | Integer | 65536 | Random 3 | Radix_Sort | 0.001057 | | Integer | 65536 | Random 10 | Radix_Sort | 0.001046 | | Integer | 65536 | rand-real32 | Radix_Sort | 0.001429 | | Integer | 65536 | Blocks | Sort | 0.004269 | | Integer | 65536 | Decreasing | Sort | 0.005108 | | Integer | 65536 | Identical | Sort | 0.006257 | | Integer | 65536 | Increasing | Sort | 0.002093 | | Integer | 65536 | Random dense | Sort | 0.006032 | | Integer | 65536 | Random order | Sort | 0.006030 | | Integer | 65536 | Random sparse | Sort | 0.006126 | | Integer | 65536 | Random 3 | Sort | 0.007930 | | Integer | 65536 | Random 10 | Sort | 0.014729 | | Character | 65536 | Char. Decrease | Sort | 0.020623 | | Character | 65536 | Char. Increase | Sort | 0.008028 | | Character | 65536 | Char. Random | Sort | 0.014258 | | String_type | 4096 | String Decrease | Sort | 0.005542 | | String_type | 4096 | String Increase | Sort | 0.001987 | | String_type | 4096 | String Random | Sort | 0.003267 | | Integer | 65536 | Blocks | Sort_Index | 0.000686 | | Integer | 65536 | Decreasing | Sort_Index | 0.000529 | | Integer | 65536 | Identical | Sort_Index | 0.000218 | | Integer | 65536 | Increasing | Sort_Index | 0.000214 | | Integer | 65536 | Random dense | Sort_Index | 0.008044 | | Integer | 65536 | Random order | Sort_Index | 0.008042 | | Integer | 65536 | Random sparse | Sort_Index | 0.008148 | | Integer | 65536 | Random 3 | Sort_Index | 0.000677 | | Integer | 65536 | Random 10 | Sort_Index | 0.000387 | | Character | 65536 | Char. Decrease | Sort_Index | 0.000932 | | Character | 65536 | Char. Increase | Sort_Index | 0.000487 | | Character | 65536 | Char. Random | Sort_Index | 0.017231 | | String_type | 4096 | String Decrease | Sort_Index | 0.000489 | | String_type | 4096 | String Increase | Sort_Index | 0.000183 | | String_type | 4096 | String Random | Sort_Index | 0.004102 | The second compiler is Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.7.0 Build 20220726_000000, with the following results: | Type | Elements | Array Name | Method | Time (s) | |-------------|----------|-----------------|-------------|-----------| | Integer | 65536 | Blocks | Ord_Sort | 0.000135 | | Integer | 65536 | Decreasing | Ord_Sort | 0.000053 | | Integer | 65536 | Identical | Ord_Sort | 0.000033 | | Integer | 65536 | Increasing | Ord_Sort | 0.000034 | | Integer | 65536 | Random dense | Ord_Sort | 0.003291 | | Integer | 65536 | Random order | Ord_Sort | 0.003546 | | Integer | 65536 | Random sparse | Ord_Sort | 0.003313 | | Integer | 65536 | Random 3 | Ord_Sort | 0.000145 | | Integer | 65536 | Random 10 | Ord_Sort | 0.000070 | | Character | 65536 | Char. Decrease | Ord_Sort | 0.000696 | | Character | 65536 | Char. Increase | Ord_Sort | 0.000338 | | Character | 65536 | Char. Random | Ord_Sort | 0.015255 | | String_type | 4096 | String Decrease | Ord_Sort | 0.001276 | | String_type | 4096 | String Increase | Ord_Sort | 0.000153 | | String_type | 4096 | String Random | Ord_Sort | 0.024705 | | Integer | 65536 | Blocks | Radix_Sort | 0.001038 | | Integer | 65536 | Decreasing | Radix_Sort | 0.000910 | | Integer | 65536 | Identical | Radix_Sort | 0.000441 | | Integer | 65536 | Increasing | Radix_Sort | 0.000803 | | Integer | 65536 | Random dense | Radix_Sort | 0.000363 | | Integer | 65536 | Random order | Radix_Sort | 0.000741 | | Integer | 65536 | Random sparse | Radix_Sort | 0.000384 | | Integer | 65536 | Random 3 | Radix_Sort | 0.000877 | | Integer | 65536 | Random 10 | Radix_Sort | 0.000801 | | Integer | 65536 | rand-real32 | Radix_Sort | 0.000604 | | Integer | 65536 | Blocks | Sort | 0.001342 | | Integer | 65536 | Decreasing | Sort | 0.001391 | | Integer | 65536 | Identical | Sort | 0.001485 | | Integer | 65536 | Increasing | Sort | 0.000447 | | Integer | 65536 | Random dense | Sort | 0.002778 | | Integer | 65536 | Random order | Sort | 0.002896 | | Integer | 65536 | Random sparse | Sort | 0.003136 | | Integer | 65536 | Random 3 | Sort | 0.002996 | | Integer | 65536 | Random 10 | Sort | 0.005752 | | Character | 65536 | Char. Decrease | Sort | 0.021973 | | Character | 65536 | Char. Increase | Sort | 0.008391 | | Character | 65536 | Char. Random | Sort | 0.015155 | | String_type | 4096 | String Decrease | Sort | 0.034014 | | String_type | 4096 | String Increase | Sort | 0.010464 | | String_type | 4096 | String Random | Sort | 0.015748 | | Integer | 65536 | Blocks | Sort_Index | 0.000381 | | Integer | 65536 | Decreasing | Sort_Index | 0.000085 | | Integer | 65536 | Identical | Sort_Index | 0.000046 | | Integer | 65536 | Increasing | Sort_Index | 0.000046 | | Integer | 65536 | Random dense | Sort_Index | 0.004020 | | Integer | 65536 | Random order | Sort_Index | 0.004059 | | Integer | 65536 | Random sparse | Sort_Index | 0.004073 | | Integer | 65536 | Random 3 | Sort_Index | 0.000215 | | Integer | 65536 | Random 10 | Sort_Index | 0.000101 | | Character | 65536 | Char. Decrease | Sort_Index | 0.000680 | | Character | 65536 | Char. Increase | Sort_Index | 0.000356 | | Character | 65536 | Char. Random | Sort_Index | 0.016231 | | String_type | 4096 | String Decrease | Sort_Index | 0.001219 | | String_type | 4096 | String Increase | Sort_Index | 0.000125 | | String_type | 4096 | String Random | Sort_Index | 0.018631 | fortran-lang-stdlib-0ede301/doc/specs/stdlib_ascii.md0000664000175000017500000002462515135654166023034 0ustar alastairalastair--- title: ascii --- # The `stdlib_ascii` module [TOC] ## Introduction The `stdlib_ascii` module provides procedures for handling and manipulating intrinsic character variables and constants. ## Constants provided by `stdlib_ascii` ### `NUL` Null character ### `SOH` Start Of Heading Character ### `STX` Start Of Text character ### `ETX` End Of Text character ### `EOT` End Of Transmission character ### `ENQ` Enquiry character ### `ACK` Acknowledge character ### `BEL` Bell character ### `BS` Backspace character ### `TAB` Horizontal Tab character ### `LF` Line Feed character ### `VT` Vertical Tab character ### `FF` Form Feed character ### `CR` Carriage Return character ### `SO` Shift Out character ### `SI` Shift In character ### `DLE` Data Link Escape character ### `DC1` Device Control 1 character ### `DC2` Device Control 2 character ### `DC3` Device Control 3 character ### `DC4` Device Control 4 character ### `NAK` Negative Acknowledge character ### `SYN` Synchronous Idle character ### `ETB` End of Transmission Block character ### `CAN` Cancel character ### `EM` End of Medium character ### `SUB` Substitute character ### `ESC` Escape character ### `FS` File separator character ### `GS` Group Separator character ### `RS` Record Separator character ### `US` Unit separator character ### `DEL` Delete character ### `fullhex_digits` All the hexadecimal digits (0-9, A-F, a-f) ### `hex_digits` All the numerical and uppercase hexadecimal digits (0-9, A-F) ### `lowerhex_digits` All the numerical and lowercase hexadecimal digits (0-9, a-f) ### `digits` base 10 digits (0-9) ### `octal_digits` base 8 digits (0-7) ### `letters` Uppercase and lowercase letters of the english alphabet (A-Z, a-z) ### `uppercase` Uppercase english albhabets (A-Z) ### `lowercase` Lowercase english albhabets (a-z) ### `whitespace` All the ascii whitespace characters (space, horizontal tab, vertical tab, carriage return, line feed, form feed) ## Specification of the `stdlib_ascii` procedures ### `is_alpha` #### Status Experimental #### Description Checks whether input character is an ASCII letter (A-Z, a-z). #### Syntax `res =` [[stdlib_ascii(module):is_alpha(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_alphanum` #### Status Experimental #### Description Checks whether input character is an ASCII letter or a number (A-Z, a-z, 0-9). #### Syntax `res =` [[stdlib_ascii(module):is_alphanum(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_ascii` #### Status Experimental #### Description Checks whether input character is in the ASCII character set i.e in the range 0-128. #### Syntax `res =` [[stdlib_ascii(module):is_ascii(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_control` #### Status Experimental #### Description Checks whether input character is a control character. #### Syntax `res =` [[stdlib_ascii(module):is_control(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_digit` #### Status Experimental #### Description Checks whether input character is a digit (0-9). #### Syntax `res =` [[stdlib_ascii(module):is_digit(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_octal_digit` #### Status Experimental #### Description Checks whether input character is an octal digit (0-7) #### Syntax `res =` [[stdlib_ascii(module):is_octal_digit(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_hex_digit` #### Status Experimental #### Description Checks whether input character is a hexadecimal digit (0-9, A-F, a-f). #### Syntax `res =` [[stdlib_ascii(module):is_hex_digit(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_punctuation` #### Status Experimental #### Description Checks whether input character is a punctuation character. #### Syntax `res =` [[stdlib_ascii(module):is_punctuation(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_graphical` #### Status Experimental #### Description Checks whether input character is a graphical character (printable other than the space character). #### Syntax `res =` [[stdlib_ascii(module):is_graphical(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_printable` #### Status Experimental #### Description Checks whether input character is a printable character (including the space character). #### Syntax `res =` [[stdlib_ascii(module):is_printable(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_lower` #### Status Experimental #### Description Checks whether input character is a lowercase ASCII letter (a-z). #### Syntax `res =` [[stdlib_ascii(module):is_lower(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_upper` #### Status Experimental #### Description Checks whether input character is an uppercase ASCII letter (A-Z). #### Syntax `res =` [[stdlib_ascii(module):is_upper(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_white` #### Status Experimental #### Description Checks whether input character is a whitespace character (which includes space, horizontal tab, vertical tab, carriage return, linefeed and form feed characters) #### Syntax `res =` [[stdlib_ascii(module):is_white(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `is_blank` #### Status Experimental #### Description Checks whether input character is a blank character (which includes space and tabs). #### Syntax `res =` [[stdlib_ascii(module):is_blank(function)]] `(c)` #### Class Elemental function. #### Argument `c`: shall be an intrinsic `character(len=1)` type. It is an `intent(in)` argument. #### Result value The result is a `logical`. ### `to_lower` #### Status Experimental #### Description Converts input character variable to all lowercase. #### Syntax `res =` [[stdlib_ascii(module):to_lower(function)]] `(string)` #### Class Elemental function. #### Argument `string`: shall be an intrinsic character type. It is an `intent(in)` argument. #### Result value The result is an intrinsic character type of the same length as `string`. #### Example ```fortran {!example/ascii/example_ascii_to_lower.f90!} ``` ### `to_upper` #### Status Experimental #### Description Converts input character variable to all uppercase. #### Syntax `res =` [[stdlib_ascii(module):to_upper(function)]] `(string)` #### Class Elemental function. #### Argument `string`: shall be an intrinsic character type. It is an `intent(in)` argument. #### Result value The result is an intrinsic character type of the same length as `string`. #### Example ```fortran {!example/ascii/example_ascii_to_upper.f90!} ``` ### `to_title` #### Status Experimental #### Description Returns the titlecase version of the input character variable. Title case: First character of every word in the sentence is converted to uppercase and the rest of the characters are converted to lowercase. A word is a contiguous sequence of character(s) which consists of alphabetical character(s) and numeral(s) only and doesn't exclude any alphabetical character or numeral present next to either of its 2 ends. #### Syntax `res =` [[stdlib_ascii(module):to_title(function)]] `(string)` #### Class Elemental function. #### Argument `string`: shall be an intrinsic character type. It is an `intent(in)` argument. #### Result value The result is an intrinsic character type of the same length as `string`. #### Example ```fortran {!example/ascii/example_ascii_to_title.f90!} ``` ### `to_sentence` #### Status Experimental #### Description Returns the sentencecase version of the input character variable. The first alphabetical character of the sequence is transformed to uppercase unless it follows a numeral. The rest of the characters in the sequence are transformed to lowercase. #### Syntax `res =` [[stdlib_ascii(module):to_sentence(function)]] `(string)` #### Class Elemental function. #### Argument `string`: shall be an intrinsic character type. It is an `intent(in)` argument. #### Result value The result is an intrinsic character type of the same length as `string`. #### Example ```fortran {!example/ascii/example_ascii_to_sentence.f90!} ``` ### `reverse` #### Status Experimental #### Description Reverses the order of all characters in the input character type. #### Syntax `res =` [[stdlib_ascii(module):reverse(function)]] `(string)` #### Class Elemental function. #### Argument `string`: shall be an intrinsic character type. It is an `intent(in)` argument. #### Result value The result is an intrinsic character type of the same length as `string`. #### Example ```fortran {!example/ascii/example_ascii_reverse.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_array.md0000664000175000017500000000346015135654166023054 0ustar alastairalastair--- title: array --- # The `stdlib_array` module [TOC] ## Introduction Module for index manipulation and array handling tasks. ## Procedures and methods provided ### `trueloc` #### Status Experimental #### Description Turn a logical mask into an index array by selecting all true values. Provides similar functionality like the built-in `where` or the intrinsic procedures `merge` and `pack` when working with logical mask. The built-in / intrinsics are usually preferable to `trueloc`, unless the access to the index array is required. #### Syntax `loc =` [[trueloc(function)]] `(array[, lbound])` #### Class Pure function. #### Arguments `array`: List of default logical arrays. This argument is `intent(in)`. `lbound`: Lower bound of the array to index. This argument is `optional` and `intent(in)`. #### Return value Returns an array of default integer size, with a maximum length of `size(array)` elements. #### Examples ```fortran {!example/array/example_trueloc.f90!} ``` ### `falseloc` #### Status Experimental #### Description Turn a logical mask into an index array by selecting all false values. Provides similar functionality like the built-in `where` or the intrinsic procedures `merge` and `pack` when working with logical mask. The built-in / intrinsics are usually preferable to `falseloc`, unless the access to the index array is required. #### Syntax `loc =` [[falseloc(function)]] `(array[, lbound])` #### Class Pure function. #### Arguments `array`: List of default logical arrays. This argument is `intent(in)`. `lbound`: Lower bound of the array to index. This argument is `optional` and `intent(in)`. #### Return value Returns an array of default integer size, with a maximum length of `size(array)` elements. #### Examples ```fortran {!example/array/example_falseloc.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_bitsets.md0000664000175000017500000011741315135654166023417 0ustar alastairalastair--- title: bitsets --- # The `stdlib_bitsets` module [TOC] ## Introduction The `stdlib_bitsets` module implements bitset types. A bitset is a compact representation of a sequence of `bits` binary values. It can equivalently be considered as a sequence of logical values or as a subset of the integers 0 ... `bits-1`. For example, the value `1110` can be considered as defining the subset of integers [1, 2, 3]. The bits are indexed from 0 to `bits(bitset)-1`. A bitset is used when space savings are critical in applications that require a large number of closely related logical values. It may also improve performance by reducing memory traffic. To implement bitsets the module defines three bitset types, multiple constants, a character string literal that can be read to and from strings and formatted files, a simple character string literal that can be read to and from strings, assignments, procedures, methods, and operators. Note that the module assumes two's complement integers, but all current Fortran 95 and later processors use such integers. Note that the module defines a number of "binary" procedures, procedures with two bitset arguments. These arguments must be of the same type and should have the same number of `bits`. For reasons of performance the module does not enforce the `bits` constraint, but failure to obey that constraint results in undefined behavior. This undefined behavior includes undefined values for those bits that exceed the defined number of `bits` in the smaller bitset. The undefined behavior may also include a "segmentation fault" for attempting to address bits in the smaller bitset, beyond the defined number of `bits`. Other problems are also possible. ## The module's constants The module defines several public integer constants, almost all intended to serve as error codes in reporting problems through an optional `stat` argument. One constant, `bits_kind` is the integer kind value for indexing bits and reporting counts of bits. The other constants that are error codes are summarized below: |Error Code|Summary| |----------|-------| |`success`|No problems found| |`alloc_fault`|Failure with a memory allocation| |`array_size_invalid_error`|Attempt to define either negative bits or more than 64 bits in a `bitset_64`| |`char_string_invalid_error`|Invalid character found in a character string| |`char_string_too_large_error`|Character string was too large to be encoded in the bitset| |`char_string_too_small_error`|Character string was too small to hold the expected number of bits| |`index_invalid_error`|Index to a bitstring was less than zero or greater than the number of bits| |`integer_overflow_error`|Attempt to define an integer value bigger than `huge(0_bits_kind)`| |`read_failure`|Failure on a `read` statement| |`eof_failure`|An unexpected "End-of-File" on a `read` statement| |`write_failure`|Failure on a `write` statement| ## The `stdlib_bitsets` derived types The `stdlib_bitsets` module defines three derived types, `bitset_type`, `bitset_64`, and `bitset_large`. `bitset_type` is an abstract type that serves as the ancestor of `bitset_64` and `bitset_large`. `bitset_type` defines one method, `bits`, and all of its other methods are deferred to its extensions. `bitset_64` is a bitset that can handle up to 64 bits. `bitset_large` is a bitset that can handle up `huge(0_bits_kind)` bits. All attributes of the bitset types are private. The various types each define a sequence of binary values: 0 or 1. In some cases it is useful to associate a logical value, `test`, for each element of the sequence, where `test` is `.true.` if the value is 1 and `.false.` otherwise. The number of such values in an entity of that type is to be termed, `bits`. The bits are ordered in terms of position, that, in turn, is indexed from 0 to `bits-1`. `bitset_type` is used only as a `class` to define entities that can be either a `bitset_64` or a `bitset_large`. The syntax for using the types are: `class(` [[stdlib_bitsets(module):bitset_type(type)]] `) :: variable` `type(` [[stdlib_bitsets(module):bitset_64(type)]] `) :: variable` and `type(` [[stdlib_bitsets(module):bitset_large(type)]] `) :: variable` ## The *bitset-literal* A bitset value may be represented as a *bitset-literal-constant* character string in source code or as a *bitset-literal* in formatted files and non-constant strings. *bitset-literal-constant* is ' *bitset-literal* ' or " *bitset-literal* " *bitset-literal* is *bitsize-literal* *binary-literal* *bitsize-literal* is S *digit* [ *digit* ] ... *binary-literal* is B *binary-digit* [ *binary-digit* ] ... *digit* is 0 or 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8 or 9 *binary-digit* is 0 or 1 The *bitset-literal* consists of two parts: a *bitsize-literal* and a *binary-literal*. The sequence of decimal digits that is part of the *bitsize-literal* is interpreted as the decimal value of `bits`. The *binary-literal* value is interpreted as a sequence of bit values and there must be as many binary digits in the literal as there are `bits`. The sequence of binary digits are treated as if they were an unsigned integer with the i-th digit corresponding to the `bits-i` bit position. ## The *binary-literal* In defining the *bitset-literal* we also defined a *binary-literal*. While not suitable for file I/0, the *binary-literal* is suitable for transfer to and from character strings. In that case the length of the string is the number of bits and all characters in the string must be either "0" or "1". ## Summary of the module's operations The `stdlib_bitsets` module defines a number of operations: * "unary" methods of class `bitset_type`, * "binary" procedure overloads of type `bitset_64` or `bitset_large`, * assignments, and * "binary" comparison operators of type `bitset_64` or `bitset_large`. Each category will be discussed separately. ### Table of the `bitset_type` methods The `bitset_type` class has a number of methods. All except one, `bits`, are deferred. The methods consist of all procedures with one argument of class `bitset_type`. The procedures with two arguments of type `bitset_64` or `bitset_large` are not methods and are summarized in a separate table of procedures. The methods are summarized below: |Method name|Class|Summary| |-----------|-----|-------| |`all`|function|`.true.` if all bits are 1, `.false.` otherwise| |`any`|function|`.true.` if any bits are 1, `.false.` otherwise| |`bit_count`|function|returns the number of bits that are 1| |`bits`|function|returns the number of bits in the bitset| |`clear`|subroutine|sets a sequence of one or more bits to 0| |`flip`|subroutine|flips the value of a sequence of one or more bits| |`from_string`|subroutine|reads the bitset from a string treating it as a binary literal| |`init`|subroutine|creates a new bitset of size `bits` with no bits set| |`input`|subroutine|reads a bitset from an unformatted I/O unit| |`none`|function|`.true.` if no bits are 1, `.false.` otherwise| |`not`|subroutine|performs a logical `not` operation on all the bits| |`output`|subroutine|writes a bitset to an unformatted I/O unit| |`read_bitset`|subroutine|reads a bitset from a bitset literal in a character string or formatted I/O unit| |`set`|subroutine|sets a sequence of one or more bits to 1| |`test`|function|`.true.` if the bit at `pos` is 1, `.false.` otherwise| |`to_string`|subroutine|represents the bitset as a binary literal| |`value`|function|1 if the bit at `pos` is 1, 0 otherwise| |`write_bitset`|subroutine|writes a bitset as a bitset literal to a character string or formatted I/O unit| ### Table of the non-member procedure overloads The procedures with two arguments of type `bitset_large` or `bitset_64` must have both arguments of the same known type which prevents them from being methods. The bitwise "logical" procedures, `and`, `and_not`, `or`, and `xor` also require that the two bitset arguments have the same number of bits, otherwise the results are undefined. These procedures are summarized in the following table: |Procedure name|Class|Summary| |--------------|-----|-------| |`and`|elemental subroutine|Sets `self` to the bitwise `and` of the original bits in `self` and `set2`| |`and_not`|elemental subroutine|Sets `self` to the bitwise `and` of the original bits in `self` and the negation of `set2`| |`extract`|subroutine|creates a new bitset, `new`, from a range in `old`| |`or`|elemental subroutine|Sets `self` to the bitwise `or` of the original bits in `self` and `set2`| |`xor`|elemental subroutine|Sets `self` to the bitwise exclusive `or` of the original bits in `self` and `set2`| ### Assignments The module uses the intrinsic assignment operation, `=`, to create a duplicate of an original bitset. It additionally defines assignments to and from rank one arrays of logical type of kinds `int8`, `int16`, `int32`, and `int64`. In the assignment to and from logical arrays array index, `i`, is mapped to bit position, `pos=i-1`, and `.true.` is mapped to a set bit, and `.false.` is mapped to an unset bit. #### Example ```fortran {!example/bitsets/example_bitsets_assignment.f90!} ``` ### Table of the non-member comparison operations The comparison operators with two arguments of type `bitset_large` or `bitset_64` must have both arguments of the same known type which prevents them from being methods. The operands must also have the same number of bits otherwise the results are undefined. These operators are summarized in the following table: |Operator|Description| |--------|-----------| |`==`, `.eq.`|`.true.` if all bits in `set1` and `set2` have the same value, `.false.` otherwise| |`/=`, `.ne.`|`.true.` if any bits in `set1` and `set2` differ in value, `.false.` otherwise| |`>`, `.gt.`|`.true.` if the bits in `set1` and `set2` differ in value and the highest order differing bit is 1 in `set1` and 0 in `set2`, `.false.` otherwise| |`>=`, `.ge.`|`.true.` if the bits in `set1` and `set2` are the same or the highest order differing bit is 1 in `set1` and 0 in `set2`, `.false.` otherwise| |`<`, `.lt.`|`.true.` if the bits in `set1` and `set2` differ in value and the highest order differing bit is 0 in `set1` and 1 in `set2`, `.false.` otherwise| |`<=`, `.le.`|`.true.` if the bits in `set1` and `set2` are the same or the highest order differing bit is 0 in `set1` and 1 in `set2`, `.false.` otherwise| ## Specification of the `stdlib_bitsets` methods and procedures ### `all` - determine whether all bits are set in `self` #### Status Experimental #### Description Determines whether all bits are set to 1 in `self`. #### Syntax `result = self % ` [[bitset_type(type):all(bound)]] `()` #### Class Elemental function. #### Argument `self`: shall be a scalar expression of class `bitset_type`. It is an `intent(in)` argument. #### Result value The result is a default logical scalar. The result is `.true.` if all bits in `self` are set, otherwise it is `.false.`. #### Example ```fortran {!example/bitsets/example_bitsets_all.f90!} ``` ### `and` - bitwise `and` of the bits of two bitsets #### Status Experimental #### Description Sets the bits in `set1` to the bitwise `and` of the original bits in `set1` and `set2`. Note that `set1` and `set2` must have the same number of bits, otherwise the result is undefined. #### Syntax `call ` [[stdlib_bitsets(module):and(interface)]] `(set1, set2)` #### Class Elemental subroutine. #### Arguments `set1`: shall be a `bitset_64` or `bitset_large` scalar variable. It is an `intent(inout)` argument. On return the values of the bits in `set1` are the bitwise `and` of the original bits in `set1` with the corresponding bits in `set2`. `set2`: shall be a scalar expression of the same type as `set1`. It is an `intent(in)` argument. Note that `set2` must also have the same number of bits as `set1`. #### Example ```fortran {!example/bitsets/example_bitsets_and.f90!} ``` ### `and_not` - Bitwise `and` of one bitset with the negation of another #### Status Experimental #### Description Sets the bits of `set1` to bitwise `and` of the bits of `set1` with the bitwise negation of the corresponding bits of `set2`. Note that `set1` and `set2` must have the same number of bits, otherwise the result is undefined. #### Syntax `call ` [[stdlib_bitsets(module):and_not(interface)]] `(set1, set2)` #### Class Elemental subroutine. #### Arguments `set1`: shall be a scalar `bitset_64` or `bitset_large` variable. It is an `intent(inout)` argument. On return the values of the bits in `set1` are the bitwise `and` of the original bits in `set1` with the corresponding negation of the bits in `set2`. `set2`: shall be a scalar expression of the same type as `set1`. It is an `intent(in)` argument. Note that it should also have the same number of bits as `set1`, otherwise the result is undefined. #### Example ```fortran {!example/bitsets/example_bitsets_and_not.f90!} ``` ### `any` - determine whether any bits are set #### Status Experimental #### Description Determines whether any bits are set in `self`. #### Syntax `result = self % ` [[bitset_type(type):any(bound)]] `()` #### Class Elemental function. #### Argument `self`: shall be a scalar expression of class `bitset_type`. It is an `intent(in)` argument. #### Result value The result is a default logical scalar. The result is `.true.` if any bits in `self` are set, otherwise it is `.false.`. #### Example ```fortran {!example/bitsets/example_bitsets_any.f90!} ``` ### `bit_count` - return the number of bits that are set #### Status Experimental #### Description Returns the number of bits that are set to one in `self`. #### Syntax `result = self % ` [[bitset_type(type):bit_count(bound)]] ` ()` #### Class Elemental function. #### Argument `self`: shall be a scalar expression of class `bitset_type`. It is an `intent(in)` argument. #### Result value The result is an integer scalar of kind `bits_kind`, equal to the number of bits that are set in `self`. #### Example ```fortran {!example/bitsets/example_bitsets_bit_count.f90!} ``` #### `bits` - returns the number of bits #### Status Experimental #### Description Reports the number of bits in `self`. #### Syntax `result = self % ` [[bitset_type(type):bits(bound)]] ` ()` #### Class Elemental function. #### Argument `self`: shall be a scalar expression of class `bitset_type`. It is an `intent(in)` argument. #### Result value The result is an integer scalar of kind `bits_kind`, equal to the number of defined bits in `self`. #### Example ```fortran {!example/bitsets/example_bitsets_bits.f90!} ``` ### `clear` - clears a sequence of one or more bits #### Status Experimental #### Description * If only `pos` is present, clears the bit with position `pos` in `self`. * If `start_pos` and `end_pos` are present with `end_pos >= start_pos` clears the bits with positions from `start_pos` to `end_pos` in `self`. * if `start_pos` and `end_pos` are present with `end_pos < start_pos` `self` is unmodified. Note: Positions outside the range 0 to `bits(set) -1` are ignored. #### Syntax `call self % ` [[bitset_type(type):clear(bound)]] `(pos)` or `call self % ` [[bitset_type(type):clear(bound)]] `(start_pos, end_pos)` #### Class Elemental subroutine #### Arguments `self`: shall be a scalar variable of class `bitset_type`. It is an `intent(inout)` argument. `pos`: shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument. `start_pos`: shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument. `end_pos`: shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument. #### Example ```fortran {!example/bitsets/example_bitsets_clear.f90!} ``` ### `extract` - create a new bitset from a range in an old bitset #### Status Experimental #### Description Creates a new bitset, `new`, from a range, `start_pos` to `stop_pos`, in bitset `old`. If `start_pos` is greater than `stop_pos` the new bitset is empty. If `start_pos` is less than zero or `stop_pos` is greater than `bits(old)-1` then if `status` is present it has the value `index_invalid_error`, otherwise processing stops with an informative message. #### Syntax `call ` [[stdlib_bitsets(module):extract(interface)]] `(new, old, start_pos, stop_pos, status )` #### Class Subroutine #### Arguments `new`: shall be a scalar `bitset_64` or `bitset_large` variable. It is an `intent(out)` argument. It will be the new bitset. `old`: shall be a scalar expression of the same type as `new`. It is an `intent(in)` argument. It will be the source bitset. `start_pos`: shall be a scalar integer expression of the kind `bits_kind`. It is an `intent(in)` argument. `stop_pos`: shall be a scalar integer expression of the kind `bits_kind`. It is an `intent(in)` argument. `status` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. If present it shall have one of the values: * `success` - no problems found * `index_invalid_error` - `start_pos` was less than zero or `stop_pos` was greater than `bits(old)-1`. #### Example ```fortran {!example/bitsets/example_bitsets_extract.f90!} ``` ### `flip` - flip the values of a sequence of one or more bits #### Status Experimental #### Description Flip the values of a sequence of one or more bits. * If only `pos` is present flip the bit value with position `pos` in `self`. * If `start_pos` and `end_pos` are present with `end_pos >= start_pos` flip the bit values with positions from `start_pos` to `end_pos` in `self`. * If `end_pos < start_pos` then `self` is unmodified. #### Syntax `call self % ` [[bitset_type(type):flip(bound)]] ` (pos)` or `call self % ` [[bitset_type(type):flip(bound)]] ` (start_pos, end_pos)` #### Class Elemental subroutine. #### Arguments `self`: shall be a scalar class `bitset_type` variable It is an `intent(inout)` argument. `pos`: shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument. `start_pos`: shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument. `end_pos`: shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument. #### Example ```fortran {!example/bitsets/example_bitsets_flip.f90!} ``` ### `from_string` - initializes a bitset from a binary literal #### Status Experimental #### Description Initializes the bitset `self` from `string`, treating `string` as a binary literal. #### Syntax `call self % ` [[bitset_type(type):from_string(bound)]] `(string[, status])` #### Class Subroutine #### Arguments `self`: shall be a scalar class `bitset_type` variable. It is an `intent(out)` argument. `string`: shall be a scalar default character expression. It is an `intent(in)` argument. It shall consist only of the characters "0", and "1". `status` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. If present, on return its value shall be one of the error codes defined in this module. If absent, and its value would not have been `success`, then processing will stop with an informative text as its stop code. It shall have one of the error codes: * `success` - if no problems were found, * `alloc_fault` - if allocation of the bitset failed * `char_string_too_large_error` - if `string` was too large, or * `char_string_invalid_error` - if string had an invalid character. #### Example ```fortran {!example/bitsets/example_bitsets_from_string.f90!} ``` ### `init` - `bitset_type` initialization routines #### Status Experimental #### Description `bitset_type` initialization routine. #### Syntax `call self % ` [[bitset_type(type):init(bound)]] ` (bits [, status])` #### Class Subroutine. #### Arguments `self`: shall be a scalar `bitset_64` or `bitset_large` variable. It is an `intent(out)` argument. `bits`: shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument that if present specifies the number of bits in `set`. A negative value, or a value greater than 64 if `self` is of type `bitset_64`, is an error. `status` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument that, if present, returns an error code indicating any problem found in processing `init`, and if absent and an error was found result in stopping processing with an informative stop code. It can have any of the following error codes: * `success` - no problem found * `alloc_fault` - `self` was of type `bitset_large` and memory allocation failed * `array_size_invalid_error` - bits was present with either a negative value, or a value greater than 64 when `self` was of type `bitset_64`. #### Example ```fortran {!example/bitsets/example_bitsets_init.f90!} ``` ### `input` - reads a bitset from an unformatted file #### Status Experimental #### Description Reads a bitset from its binary representation in an unformatted file. #### Syntax `call self % ` [[bitset_type(type):input(bound)]] ` (unit [, status])` #### Class Subroutine #### Arguments `self`: shall be a scalar variable of class `bitset_64` or `bitset_large`. It is an `intent(out)` argument. `unit`: shall be a scalar default integer expression. It is an `intent(in)` argument. Its value must be that of a logical unit number for an open unformatted file with `read` or `readwrite` access positioned at the start of a bitset value written by a `bitset_type` `output` subroutine by the same processor. `status` (optional): shall be a scalar default integer variable. If present its value shall be of one of the error codes defined in this module. If absent and it would have had a value other than `success` processing will stop with an informative stop code. Allowed error code values for this `status` are: * `success` - no problem found * `alloc_fault` - `self` was of type `bitset_large` and allocation of memory failed. * `array_size_invalid_error` - if the number of bits read from `unit` is either negative or greater than 64, if class of `self` is `bitset_64`. * `read_failure` - failure during a read statement #### Example ```fortran {!example/bitsets/example_bitsets_input.f90!} ``` ### `none` - determines whether no bits are set #### Status Experimental #### Description Determines whether no bits are set in `self`. #### Syntax `result = self % ` [[bitset_type(type):none(bound)]] ` ()` #### Class Elemental function. #### Argument `self`: shall be a scalar expression of class `bitset_type`. It is an `intent(in)` argument. #### Result value The result is a default logical scalar. The result is `.true.` if no bits in `self` are set, otherwise it is `.false.`. #### Example ```fortran {!example/bitsets/example_bitsets_none.f90!} ``` ### `not` - Performs the logical complement on a bitset #### Status Experimental #### Description Performs the logical complement on the bits of `self`. #### Syntax `call self % ` [[bitset_type(type):not(bound)]] ` ()` #### Class Elemental subroutine. #### Argument `self` shall be a scalar variable of class `bitset_type`. It is an `intent(inout)` argument. On return its bits shall be the logical complement of their values on input. #### Example ```fortran {!example/bitsets/example_bitsets_not.f90!} ``` ### `or` - Bitwise OR of the bits of two bitsets #### Status Experimental #### Description Replaces the original bits of `set1` with the bitwise `or` of those bits with the bits of `set2`. Note `set1` and `set2` must have the same number of bits, otherwise the result is undefined. #### Syntax `call ` [[stdlib_bitsets(module):or(interface)]] `(set1, set2)` #### Class Elemental subroutine. #### Arguments `set1`: shall be a scalar `bitset_64` or `bitset_large` variable. It is an `intent(inout)` argument. On return the values of the bits in `setf` are the bitwise `or` of the original bits in `set1` with the corresponding bits in `set2`. `set2`: shall be a scalar expression of the same type as `set1`. It is an `intent(in)` argument. Note `bits(set2)` must equal `bits(set1)` otherwise the results are undefined. #### Example ```fortran {!example/bitsets/example_bitsets_or.f90!} ``` ### `output` - Writes a binary representation of a bitset to a file #### Status Experimental #### Description Writes a binary representation of a bitset to an unformatted file. #### Syntax `call self % ` [[bitset_type(type):output(bound)]] ` (unit[, status])` #### Class Subroutine. #### Arguments `self`: shall be a scalar expression of class `bitset_64` or `bitset_large`. It is an `intent(in)` argument. `unit`: shall be a scalar default integer expression. It is an `intent(in)` argument. Its value must be that of an I/O unit number for an open unformatted file with `write` or `readwrite` access. `status` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. If present on return it will have the value of `success` or `write_failure`. If absent and it would not have the value of `success` then processing will stop with an informative stop code. The two code values have the meaning: * `success` - no problem found * `write_failure` - a failure occurred in a write statement. #### Example ```fortran {!example/bitsets/example_bitsets_output.f90!} ``` ### `read_bitset` - initializes `self` with the value of a *bitset_literal* #### Status Experimental #### Description Reads a *bitset-literal* and initializes `self` with the corresponding value. #### Syntax `call self % ` [[bitset_type(type):read_bitset(bound)]] `(string[, status])` or `call self % ` [[bitset_type(type):read_bitset(bound)]] `(unit[, advance, status])` #### Class Subroutine #### Arguments `self`: shall be a scalar variable of class `bitset_type`. It is an `intent(out)` argument. Upon a successful return it is initialized with the value of a *bitset-literal*. `string` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It will consist of a left justified *bitset-literal*, terminated by either the end of the string or a blank. `unit` (optional): shall be a scalar default integer expression. It is an `intent(in)` argument. Its value must be that of an I/O unit number for an open formatted file with `read` or `readwrite` access positioned at the start of a *bitset-literal*. `advance` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It is the `advance` specifier for the final read of `unit`. If present it should have the value `'yes'` or `'no'`. If absent it has the default value of `'yes'`. `status` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. If present on return it shall have the value of one of the error codes of this module. If absent and it would not have had the value `success` processing will stop with a message as its error code. The possible error codes are: * `success` - no problems found; * `alloc_fault` - if `self` is of class `bitset_large` and allocation of the bits failed; * `array_size_invalid_error` - if the *bitset-literal* has a bits value greater than 64 and `self` is of class `bitset_64`; * `char_string_invalid_error` - if the `bitset-literal` has an invalid character; * `char_string_too_small_error` - if `string` ends before all the bits are read; * `eof_failure` - if a `read` statement reached an end-of-file before completing the read of the bitset literal, * `integer_overflow_error` - if the *bitset-literal* has a `bits` value larger than `huge(0_bits_kind)`; or * `read_failure` - if a read statement failed. #### Example ```fortran {!example/bitsets/example_bitsets_read_bitset.f90!} ``` ### `set` - sets a sequence of one or more bits to 1 #### Status Experimental #### Description Sets a sequence of one or more bits in `self` to 1. * If `start_pos` and `end_pos` are absent sets the bit at position `pos` in `self` to 1. * If `start_pos` and `end_pos` are present with `end_pos >= start_pos` set the bits at positions from `start_pos` to `end_pos` in `self` to 1. * If `start_pos` and `end_pos` are present with `end_pos < start_pos` `self` is unchanged. * Positions outside the range 0 to `bits(self)` are ignored. #### Syntax `call self % ` [[bitset_type(type):set(bound)]] ` (POS)` or `call self % ` [[bitset_type(type):set(bound)]] ` (START_POS, END_POS)` #### Class Elemental subroutine #### Arguments `self`: shall be a scalar variable of class `bitset_type`. It is an `intent(inout)` argument. `pos` (optional): shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument. `start_pos` (optional): shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument. `end_pos` (optional): shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument. #### Example ```fortran {!example/bitsets/example_bitsets_set.f90!} ``` ### `test` - determine whether a bit is set #### Status Experimental #### Descriptions Determine whether the bit at position `pos` is set to 1 in `self`. #### Syntax `result = self % ` [[bitset_type(type):test(bound)]] `(pos)` #### Class Elemental function. #### Arguments `self`: shall be a scalar expression of class `bitset_type`. It is an `intent(in)` argument. `pos`: shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument. #### Result value The result is a default logical scalar. The result is `.true.` if the bit at `pos` in `self` is set, otherwise it is `.false.`. If `pos` is outside the range `0... bits(self)-1` the result is `.false.`. #### Example ```fortran {!example/bitsets/example_bitsets_test.f90!} ``` ### `to_string` - represent a bitset as a binary literal ### Status Experimental #### Description Represents the value of `self` as a binary literal in `string`. #### Syntax `call self % ` [[bitset_type(type):to_string(bound)]] `(string[, status])` #### Class Subroutine #### Arguments `self`: shall be a scalar expression of class `bitset_type`. It is an `intent(in)` argument. `string`: shall be a scalar default character variable of allocatable length. It is an `intent(out)` argument. On return it shall have a *binary-literal* representation of the bitset `self`. `status` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. If present it shall have either the value `success` or `alloc_fault`. If absent and it would have had the value `alloc_fault` then processing will stop with an informative test as the stop code. The values have the following meanings: `success` - no problem found. `alloc_fault` - allocation of `string` failed. #### Example ```fortran {!example/bitsets/example_bitsets_to_string.f90!} ``` ### `value` - determine the value of a bit #### Status Experimental #### Description Determines the value of the bit at position, `pos`, in `self`. #### Syntax `result = self % ` [[bitset_type(type):value(bound)]] `(pos)` #### Class Elemental function. #### Arguments `self`: shall be a scalar expression of class `bitset_type`. It is an `intent(in)` argument. `pos`: shall be a scalar integer expression of kind `bits_kind`. It is an `intent(in)` argument. #### Result value The result is a default integer scalar. The result is one if the bit at `pos` in `self` is set, otherwise it is zero. If `pos` is outside the range `0... bits(set)-1` the result is zero. #### Example ```fortran {!example/bitsets/example_bitsets_value.f90!} ``` ### `write_bitset` - writes a *bitset-literal* #### Status Experimental #### Description Writes a *bitset-literal* representing `self`'s current value to a character string or formatted file. #### Syntax `call self % ` [[bitset_type(type):write_bitset(bound)]] `(string[, status])` or `call self % ` [[bitset_type(type):write_bitset(bound)]] ` (unit[, advance, status])` #### Class Subroutine #### Arguments `self`: shall be a scalar expression of class `bitset_type`. It is an `intent(in)` argument. `string` (optional): shall be a scalar default character variable of allocatable length. It is an `intent(out)` argument. `unit` (optional): shall be a scalar default logical expression. It is an `intent(in)` argument. Its value must be that of a I/O unit number for an open formatted file with `write` or `readwrite` access. `advance` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It is the `advance` specifier for the write to `unit`. If present it must have the value `'yes'` or `'no'`. It has the default value of `'yes'`. * if `advance` is not present or is present with a value of `'no'` then the bitset's *bitset-literal* is written to `unit` followed by a blank, and the current record is not advanced. * If `advance` is present with a value of `'yes'` then the bitset's *bitset-literal* is written to `unit` and the record is immediately advanced. `status` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. If present on return it shall have the value of one of the module's error codes. If absent and a problem was found processing will stop with an informative stop code. It may have the following error code values: * `success` - no problem was found * `alloc_fault` - allocation of the string failed * `write_failure` - the `write` to the `unit` failed #### Example ```fortran {!example/bitsets/example_bitsets_write_bitset.f90!} ``` ### `xor` - bitwise exclusive `or` #### Status Experimental #### Description Replaces `set1`'s bitset with the bitwise exclusive `or` of the original bits of `set1` and `set2`. Note `set1` and `set2` must have the samee number of bits, otherwise the result is undefined. #### Syntax `result = ` [[stdlib_bitsets(module):xor(interface)]] ` (set1, set2)` #### Class Elemental subroutine #### Arguments `set1`: shall be a scalar `bitset_64` or `bitset_large` variable. It is an `intent(inout)` argument. On return the values of the bits in `set1` are the bitwise exclusive `or` of the original bits in `set1` with the corresponding bits in `set2`. `set2` shall be a scalar expression of the same type as `set1`. It is an `intent(in)` argument. Note `set1` and `set2` must have the samee number of bits, otherwise the result is undefined. #### Example ```fortran {!example/bitsets/example_bitsets_xor.f90!} ``` ## Specification of the `stdlib_bitsets` operators ### `==` - compare two bitsets to determine whether the bits have the same value #### Status Experimental #### Description Returns `.true.` if all bits in `set1` and `set2` have the same value, `.false.` otherwise. #### Syntax `result = set1 ` [[stdlib_bitsets(module):==(interface)]] ` set2` or `result = set1 .EQ. set2` #### Class Elemental operator #### Arguments `set1`: shall be a scalar `bitset_64` or `bitset_large` expression. It is an `intent(in)` argument. `set2`: shall be a scalar expression of the same type as `self`. It will have the same number of bits as `set1`. It is an `intent(in)` argument. #### Result value The result is a default logical scalar. The result is `.true.` if the bits in both bitsets are set to the same value, otherwise the result is `.false.`. #### Example ```fortran {!example/bitsets/example_bitsets_equality.f90!} ``` ### `/=` - compare two bitsets to determine whether any bits differ in value #### Status Experimental #### Description Returns `.true.` if any bits in `self` and `set2` differ in value, `.false.` otherwise. #### Syntax `result = set1 ` [[stdlib_bitsets(module):/=(interface)]] ` set2` or `result = set1 .NE. set2` #### Class Elemental function #### Arguments `set1`: shall be a scalar `bitset_64` or `bitset_large` expression. It is an `intent(in)` argument. `set2`: shall be a scalar expression of the same type as `self`. It will have the same number of bits as `set1`. It is an `intent(in)` argument. #### Result value The result is a default logical scalar. The result is `.true.` if any bits in both bitsets differ, otherwise the result is `.false.`. #### Example ```fortran {!example/bitsets/example_bitsets_inequality.f90!} ``` ### `>=` - compare two bitsets to determine whether the first is greater than or equal to the second #### Status Experimental #### Description Returns `.true.` if the bits in `set1` and `set2` are the same or the highest order different bit is set to 1 in `set1` and to 0 in `set2`, `.false.`. otherwise. The sets must be the same size otherwise the results are undefined. #### Syntax `result = set1 ` [[stdlib_bitsets(module):>=(interface)]] ` set2` or `result = set1 .GE. set2` #### Class Elemental operator #### Arguments `set1`: shall be a scalar `bitset_64` or `bitset_large` expression. It is an `intent(in)` argument. `set2`: shall be a scalar expression of the same type as `self`. It will have the same number of bits as `set1`. It is an `intent(in)` argument. #### Result value The result is a default logical scalar. The result is `.true.` if the bits in `set1` and `set2` are the same or the highest order different bit is set to 1 in `set1` and to 0 in `set2`, `.false.` otherwise. #### Example ```fortran {!example/bitsets/example_bitsets_ge.f90!} ``` ### `>` - compare two bitsets to determine whether the first is greater than the other #### Status Experimental #### Description Returns `.true.` if the bits in `set1` and `set2` differ and the highest order different bit is set to 1 in `set1` and to 0 in `set2`, `.false.` otherwise. The sets must be the same size otherwise the results are undefined. #### Syntax `result = set1 ` [[stdlib_bitsets(module):>(interface)]] ` set2` or `result = set1 .GT. set2` #### Class Elemental operator #### Arguments `set1`: shall be a scalar `bitset_64` or `bitset_large` expression. It is an `intent(in)` argument. `set2`: shall be a scalar expression of the same type as `self`. It will have the same number of bits as `set1`. It is an `intent(in)` argument. #### Result value The result is a default logical scalar. The result is `.true.` if the bits in `set1` and `set2` differ and the highest order different bit is set to 1 in `set1` and to 0 in `set2`, `.false.` otherwise. #### Example ```fortran {!example/bitsets/example_bitsets_gt.f90!} ``` ### `<=` - compare two bitsets to determine whether the first is less than or equal to the other #### Status Experimental #### Description Returns `.true.` if the bits in `set1` and `set2` are the same or the highest order different bit is set to 0 in `set1` and to 1 in `set2`, `.false.` otherwise. The sets must be the same size otherwise the results are undefined. #### Syntax `result = set1 ` [[stdlib_bitsets(module):<=(interface)]] ` set2` or `result = set1 .LE. set2` #### Class Elemental operator #### Arguments `set1`: shall be a scalar `bitset_64` or `bitset_large` expression. It is an `intent(in)` argument. `set2`: shall be a scalar expression of the same type as `self`. It will have the same number of bits as `set1`. It is an `intent(in)` argument. #### Result value The result is a default logical scalar. The result is `.true.` if the bits in `set1` and `set2` are the same or the highest order different bit is set to 0 in `set1` and to 1 in `set2`, `.false.` otherwise. #### Example ```fortran {!example/bitsets/example_bitsets_le.f90!} ``` ### `<` - compare two bitsets to determine whether the first is less than the other #### Status Experimental #### Description Returns `.true.` if the bits in `set1` and `set2` differ and the highest order different bit is set to 0 in `set1` and to 1 in `set2`, `.false.` otherwise. The sets must be the same size otherwise the results are undefined. #### Syntax `result = set1 ` [[stdlib_bitsets(module):<(interface)]] ` set2` or `result = set1 .LT. set2 #### Class Elemental operator #### Arguments `set1`: shall be a scalar `bitset_64` or `bitset_large` expression. It is an `intent(in)` argument. `set2`: shall be a scalar expression of the same type as `self`. It will have the same number of bits as `set1`. It is an `intent(in)` argument. #### Result value The result is a default logical scalar. The result is `.true.` if the bits in `set1` and `set2` differ and the highest order different bit is set to 0 in `set1` and to 1 in `set2`, `.false.` otherwise. #### Example ```fortran {!example/bitsets/example_bitsets_lt.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_stats.md0000664000175000017500000003002115135654166023065 0ustar alastairalastair--- title: stats --- # Descriptive statistics [TOC] ## `corr` - Pearson correlation of array elements ### Status Experimental ### Description Returns the Pearson correlation of the elements of `array` along dimension `dim` if the corresponding element in `mask` is `true`. The Pearson correlation between two rows (or columns), say `x` and `y`, of `array` is defined as: ``` corr(x, y) = cov(x, y) / sqrt( var(x) * var(y)) ``` ### Syntax `result = ` [[stdlib_stats(module):corr(interface)]] `(array, dim [, mask])` ### Class Generic subroutine ### Arguments `array`: Shall be a rank-1 or a rank-2 array of type `integer`, `real`, or `complex`. It is an `intent(in)` argument. `dim`: Shall be a scalar of type `integer` with a value in the range from 1 to `n`, where `n` is the rank of `array`. It is an `intent(in)` argument. `mask` (optional): Shall be of type `logical` and either a scalar or an array of the same shape as `array`. It is an `intent(in)` argument. ### Return value If `array` is of rank 1 and of type `real` or `complex`, the result is of type `real` and has the same kind as `array`. If `array` is of rank 2 and of type `real` or `complex`, the result is of the same type and kind as `array`. If `array` is of type `integer`, the result is of type `real(dp)`. If `array` is of rank 1 and of size larger than 1, a scalar equal to 1 is returned. Otherwise, IEEE `NaN` is returned. If `array` is of rank 2, a rank-2 array with the corresponding correlations is returned. If `mask` is specified, the result is the Pearson correlation of all elements of `array` corresponding to `true` elements of `mask`. If every element of `mask` is `false`, the result is IEEE `NaN`. ### Example ```fortran {!example/stats/example_corr.f90!} ``` ## `cov` - covariance of array elements ### Status Experimental ### Description Returns the covariance of the elements of `array` along dimension `dim` if the corresponding element in `mask` is `true`. Per default, the covariance is defined as: ``` cov(array) = 1/(n-1) sum_i (array(i) - mean(array) * (array(i) - mean(array))) ``` where `n` is the number of elements. The scaling can be changed with the logical argument `corrected`. If `corrected` is `.false.`, then the sum is scaled with `n`, otherwise with `n-1`. ### Syntax `result = ` [[stdlib_stats(module):cov(interface)]] `(array, dim [, mask [, corrected]])` ### Class Generic subroutine ### Arguments `array`: Shall be a rank-1 or a rank-2 array of type `integer`, `real`, or `complex`. It is an `intent(in)` argument. `dim`: Shall be a scalar of type `integer` with a value in the range from 1 to `n`, where `n` is the rank of `array`. It is an `intent(in)` argument. `mask` (optional): Shall be of type `logical` and either a scalar or an array of the same shape as `array`. It is an `intent(in)` argument. `corrected` (optional): Shall be a scalar of type `logical`. If `corrected` is `.true.` (default value), the sum is scaled with `n-1`. If `corrected` is `.false.`, then the sum is scaled with `n`. It is an `intent(in)` argument. ### Return value If `array` is of rank 1 and of type `real` or `complex`, the result is of type `real` corresponding to the type of `array`. If `array` is of rank 2 and of type `real` or `complex`, the result is of the same type as `array`. If `array` is of type `integer`, the result is of type `real(dp)`. If `array` is of rank 1, a scalar with the covariance (that is the variance) of all elements in `array` is returned. If `array` is of rank 2, a rank-2 array is returned. If `mask` is specified, the result is the covariance of all elements of `array` corresponding to `true` elements of `mask`. If every element of `mask` is `false`, the result is IEEE `NaN`. ### Example ```fortran {!example/stats/example_cov.f90!} ``` ## `mean` - mean of array elements ### Status Experimental ### Description Returns the mean of all the elements of `array`, or of the elements of `array` along dimension `dim` if provided, and if the corresponding element in `mask` is `true`. ### Syntax `result = ` [[stdlib_stats(module):mean(interface)]] `(array [, mask])` `result = ` [[stdlib_stats(module):mean(interface)]] `(array, dim [, mask])` ### Class Generic subroutine ### Arguments `array`: Shall be an array of type `integer`, `real`, or `complex`. It is an `intent(in)` argument. `dim`: Shall be a scalar of type `integer` with a value in the range from 1 to `n`, where `n` is the rank of `array`. It is an `intent(in)` argument. `mask` (optional): Shall be of type `logical` and either a scalar or an array of the same shape as `array`. It is an `intent(in)` argument. ### Return value If `array` is of type `real` or `complex`, the result is of the same type as `array`. If `array` is of type `integer`, the result is of type `real(dp)`. If `dim` is absent, a scalar with the mean of all elements in `array` is returned. Otherwise, an array of rank `n-1`, where `n` equals the rank of `array`, and a shape similar to that of `array` with dimension `dim` dropped is returned. If `mask` is specified, the result is the mean of all elements of `array` corresponding to `true` elements of `mask`. If every element of `mask` is `false`, the result is IEEE `NaN`. ### Example ```fortran {!example/stats/example_mean.f90!} ``` ## `median` - median of array elements ### Status Experimental ### Description Returns the median of all the elements of `array`, or of the elements of `array` along dimension `dim` if provided, and if the corresponding element in `mask` is `true`. The median of the elements of `array` is defined as the "middle" element, after that the elements are sorted in an increasing order, e.g. `array_sorted = sort(array)`. If `n = size(array)` is an even number, the median is: ``` median(array) = array_sorted( floor( (n + 1) / 2.)) ``` and if `n` is an odd number, the median is: ``` median(array) = mean( array_sorted( floor( (n + 1) / 2.):floor( (n + 1) / 2.) + 1 ) ) ``` The current implementation relies on a selection algorithm applied on a copy of the whole array, using the subroutine [[stdlib_selection(module):select(interface)]] provided by the [[stdlib_selection(module)]] module. ### Syntax `result = ` [[stdlib_stats(module):median(interface)]] `(array [, mask])` `result = ` [[stdlib_stats(module):median(interface)]] `(array, dim [, mask])` ### Class Generic subroutine ### Arguments `array`: Shall be an array of type `integer` or `real`. It is an `intent(in)` argument. `dim`: Shall be a scalar of type `integer` with a value in the range from 1 to `n`, where `n` is the rank of `array`. It is an `intent(in)` argument. `mask` (optional): Shall be of type `logical` and either a scalar or an array of the same shape as `array`. It is an `intent(in)` argument. ### Return value If `array` is of type `real`, the result is of type `real` with the same kind as `array`. If `array` is of type `real` and contains IEEE `NaN`, the result is IEEE `NaN`. If `array` is of type `integer`, the result is of type `real(dp)`. If `dim` is absent, a scalar with the median of all elements in `array` is returned. Otherwise, an array of rank `n-1`, where `n` equals the rank of `array`, and a shape similar to that of `array` with dimension `dim` dropped is returned. If `mask` is specified, the result is the median of all elements of `array` corresponding to `true` elements of `mask`. If every element of `mask` is `false`, the result is IEEE `NaN`. ### Example ```fortran {!example/stats/example_median.f90!} ``` ## `moment` - central moments of array elements ### Status Experimental ### Description Returns the _k_-th order central moment of all the elements of `array`, or of the elements of `array` along dimension `dim` if provided, and if the corresponding element in `mask` is `true`. If a scalar or an array `center` is provided, the function returns the _k_-th order moment about 'center', of all the elements of `array`, or of the elements of `array` along dimension `dim` if provided, and if the corresponding element in `mask` is `true`. The _k_-th order central moment is defined as : ``` moment(array) = 1/n sum_i (array(i) - mean(array))^k ``` where `n` is the number of elements. The _k_-th order moment about `center` is defined as : ``` moment(array) = 1/n sum_i (array(i) - center)^k ``` ### Syntax `result = ` [[stdlib_stats(module):moment(interface)]] `(array, order [, center [, mask]])` `result = ` [[stdlib_stats(module):moment(interface)]] `(array, order, dim [, center [, mask]])` ### Class Generic subroutine ### Arguments `array`: Shall be an array of type `integer`, `real`, or `complex`. `order`: Shall be an scalar of type `integer`. `dim`: Shall be a scalar of type `integer` with a value in the range from 1 to `n`, where `n` is the rank of `array`. `center` (optional): Shall be a scalar of the same type of `result` if `dim` is not provided. If `dim` is provided, `center` shall be a scalar or an array (with a shape similar to that of `array` with dimension `dim` dropped) of the same type of `result`. `mask` (optional): Shall be of type `logical` and either a scalar or an array of the same shape as `array`. ### Return value If `array` is of type `real` or `complex`, the result is of the same type as `array`. If `array` is of type `integer`, the result is of type `real(dp)`. If `dim` is absent, a scalar with the _k_-th (central) moment of all elements in `array` is returned. Otherwise, an array of rank `n-1`, where `n` equals the rank of `array`, and a shape similar to that of `array` with dimension `dim` dropped is returned. If `mask` is specified, the result is the _k_-th (central) moment of all elements of `array` corresponding to `true` elements of `mask`. If every element of `mask` is `false`, the result is IEEE `NaN`. ### Example ```fortran {!example/stats/example_moment.f90!} ``` ## `var` - variance of array elements ### Status Experimental ### Description Returns the variance of all the elements of `array`, or of the elements of `array` along dimension `dim` if provided, and if the corresponding element in `mask` is `true`. Per default, the variance is defined as the best unbiased estimator and is computed as: ``` var(array) = 1/(n-1) sum_i (array(i) - mean(array))^2 ``` where `n` is the number of elements. The use of the term `n-1` for scaling is called Bessel 's correction. The scaling can be changed with the logical argument `corrected`. If `corrected` is `.false.`, then the sum is scaled with `n`, otherwise with `n-1`. ### Syntax `result = ` [[stdlib_stats(module):var(interface)]] `(array [, mask [, corrected]])` `result = ` [[stdlib_stats(module):var(interface)]] `(array, dim [, mask [, corrected]])` ### Class Generic subroutine ### Arguments `array`: Shall be an array of type `integer`, `real`, or `complex`. It is an `intent(in)` argument. `dim`: Shall be a scalar of type `integer` with a value in the range from 1 to `n`, where `n` is the rank of `array`. It is an `intent(in)` argument. `mask` (optional): Shall be of type `logical` and either a scalar or an array of the same shape as `array`. It is an `intent(in)` argument. `corrected` (optional): Shall be a scalar of type `logical`. If `corrected` is `.true.` (default value), the sum is scaled with `n-1`. If `corrected` is `.false.`, then the sum is scaled with `n`. It is an `intent(in)` argument. ### Return value If `array` is of type `real` or `complex`, the result is of type `real` corresponding to the type of `array`. If `array` is of type `integer`, the result is of type `real(dp)`. If `dim` is absent, a scalar with the variance of all elements in `array` is returned. Otherwise, an array of rank `n-1`, where `n` equals the rank of `array`, and a shape similar to that of `array` with dimension `dim` dropped is returned. If `mask` is specified, the result is the variance of all elements of `array` corresponding to `true` elements of `mask`. If every element of `mask` is `false`, the result is IEEE `NaN`. If the variance is computed with only one single element, then the result is IEEE `NaN` if `corrected` is `.true.` and is `0.` if `corrected` is `.false.`. ### Example ```fortran {!example/stats/example_var.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_specialfunctions_gamma.md0000664000175000017500000001542515135654166026455 0ustar alastairalastair--- title: specialfunctions_gamma --- # Special functions gamma [TOC] ## `gamma` - Calculate the gamma function ### Status Experimental ### Description The gamma function is defined as the analytic continuation of a convergent improper integral function on the whole complex plane except zero and negative integers: $$\Gamma(z)=\int_{0}^{\infty}x^{z-1}e^{-x}dx, \;\; z\in \mathbb{C} \setminus 0, -1, -2, \cdots$$ Fortran 2018 standard implements the intrinsic gamma function of real type argument in single and double precisions. Here the gamma function is extended to both integer and complex arguments. The values of the gamma function with integer arguments are exact. The values of the gamma function with complex arguments are approximated in single and double precisions by using Lanczos approximation. ### Syntax `result = ` [[stdlib_specialfunctions_gamma(module):gamma(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: should be a positive integer or a complex type number ### Return value The function returns a value with the same type and kind as input argument. ### Example ```fortran {!example/specialfunctions_gamma/example_gamma.f90!} ``` ## `log_gamma` - Calculate the natural logarithm of the gamma function ### Status Experimental ### Description Mathematically, logarithm of gamma function is a special function with complex arguments by itself. Due to the different branch cut structures and a different principal branch, natural logarithm of gamma function log_gamma(z) with complex argument is different from the ln(Gamma(z)). The two have the same real part but different imaginary part. Fortran 2018 standard implements intrinsic log_gamma function of absolute value of real type argument in single and double precision. Here the log_gamma function is extended to both integer and complex arguments. The values of log_gamma function with complex arguments are approximated in single and double precisions by using Stirling's approximation. ### Syntax `result = ` [[stdlib_specialfunctions_gamma(module):log_gamma(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a positive integer or a complex type number. ### Return value The function returns real single precision values for integer input arguments, while it returns complex values with the same kind as complex input arguments. ### Example ```fortran {!example/specialfunctions_gamma/example_log_gamma.f90!} ``` ## `log_factorial` - calculate the logarithm of a factorial ### Status Experimental ### Description Compute the natural logarithm of factorial, log(n!) ### Syntax `result = ` [[stdlib_specialfunctions_gamma(module):log_factorial(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a positive integer type number. ### Return value The function returns real type values with single precision. ### Example ```fortran {!example/specialfunctions_gamma/example_log_factorial.f90!} ``` ## `lower_incomplete_gamma` - calculate lower incomplete gamma integral ### Status Experimental ### Description The lower incomplete gamma function is defined as: $$\gamma(p,x)=\int_{0}^{x}t^{p-1}e^{-t}dt, \;\; p > 0, x\in \mathbb{R}$$ When x < 0, p must be positive integer. ### Syntax `result = ` [[stdlib_specialfunctions_gamma(module):lower_incomplete_gamma(interface)]] ` (p, x)` ### Class Elemental function ### Arguments `p`: is a positive integer or real type argument. `x`: is a real type argument. ### Return value The function returns a real type value with the same kind as argument x. ### Example ```fortran {!example/specialfunctions_gamma/example_ligamma.f90!} ``` ## `upper_incomplete_gamma` - calculate the upper incomplete gamma integral ### Status Experimental ### Description The upper incomplete gamma function is defined as: $$\Gamma (p, x) = \int_{x}^{\infty }t^{p-1}e^{-t}dt, \; \; p >0,\; x \in \mathbb{R}$$ When x < 0, p must be a positive integer. ### Syntax `result = ` [[stdlib_specialfunctions_gamma(module):upper_incomplete_gamma(interface)]] ` (p, x)` ### Class Elemental function ### Arguments `p`: is a positive integer or real type argument. `x`: is a real type argument. ### Return value The function returns a real type value with the same kind as argument x. ### Example ```fortran {!example/specialfunctions_gamma/example_uigamma.f90!} ``` ## `log_lower_incomplete_gamma` - calculate the natural logarithm of the lower incomplete gamma integral ### Status Experimental ### Description Compute the natural logarithm of the absolute value of the lower incomplete gamma function. ### Syntax `result = ` [[stdlib_specialfunctions_gamma(module):log_lower_incomplete_gamma(interface)]] ` (p, x)` ### Class Elemental function ### Arguments `p`: is a positive integer or real type argument. `x`: is a real type argument. ### Return value The function returns a real type value with the same kind as argument x. ## `log_upper_incomplete_gamma` - calculate logarithm of the upper incomplete gamma integral ### Status Experimental ### Description Compute the natural logarithm of the absolute value of the upper incomplete gamma function. ### Syntax `result = ` [[stdlib_specialfunctions_gamma(module):log_upper_incomplete_gamma(interface)]] ` (p, x)` ### Class Elemental function ### Arguments `p`: is a positive integer or real type argument. `x`: is a real type argument. ### Return value The function returns a real type value with the same kind as argument x. ## `regularized_gamma_p` - calculate the gamma quotient P ### Status Experimental ### Description The regularized gamma quotient P, also known as normalized incomplete gamma function, is defined as: $$P(p,x)=\gamma(p,x)/\Gamma(p)$$ The values of regularized gamma P is in the range of [0, 1] ### Syntax `result = ` [[stdlib_specialfunctions_gamma(module):regularized_gamma_p(interface)]] ` (p, x)` ### Class Elemental function ### Arguments `p`: is a positive integer or real type argument. `x`: is a real type argument. ### Return value The function returns a real type value with the same kind as argument x. ### Example ```fortran {!example/specialfunctions_gamma/example_gamma_p.f90!} ``` ## `regularized_gamma_q` - calculate the gamma quotient Q ### Status Experimental ### Description The regularized gamma quotient Q is defined as: $$Q(p,x)=\Gamma(p,x)/\Gamma(p)=1-P(p,x)$$ The values of regularized gamma Q is in the range of [0, 1] ### Syntax `result = ` [[stdlib_specialfunctions_gamma(module):regularized_gamma_q(interface)]] ` (p, x)` ### Class Elemental function ### Arguments `p`: is a positive integer or real type argument. `x`: is a real type argument. ### Return value The function returns a real type value with the same kind as argument x. ### Example ```fortran {!example/specialfunctions_gamma/example_gamma_q.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_system.md0000664000175000017500000007222015135654166023262 0ustar alastairalastair--- title: system --- # System and sub-processing module The `stdlib_system` module provides interface for interacting with external processes, enabling the execution and monitoring of system commands or applications directly from Fortran. [TOC] ## `run` - Execute an external process synchronously ### Status Experimental ### Description The `run` interface allows execution of external processes using a single command string or a list of arguments. Processes run synchronously, meaning execution is blocked until the process finishes. Optional arguments enable the collection of standard output and error streams, as well as sending input via standard input. Additionally, a callback function can be specified to execute upon process completion, optionally receiving a user-defined payload. ### Syntax `process = ` [[stdlib_system(module):run(interface)]] `(args [, stdin] [, want_stdout] [, want_stderr] [, callback] [, payload])` ### Arguments `args`: Shall be a `character(*)` string (for command-line execution) or a `character(*), dimension(:)` array (for argument-based execution). It specifies the command and arguments to execute. This is an `intent(in)` argument. `stdin` (optional): Shall be a `character(*)` value containing input to send to the process via standard input (pipe). This is an `intent(in)` argument. `want_stdout` (optional): Shall be a `logical` flag. If `.true.`, the standard output of the process will be captured; if `.false.` (default), it will be lost. This is an `intent(in)` argument. `want_stderr` (optional): Shall be a `logical` flag. If `.true.`, the standard error output of the process will be captured. If `.false.` (default), it will be lost. This is an `intent(in)` argument. `callback` (optional): Shall be a procedure conforming to the `process_callback` interface. If present, this function will be called upon process completion with the process ID, exit state, and optionally collected standard input, output, and error streams. This is an `intent(in)` argument. `payload` (optional): Shall be a generic (`class(*)`) scalar that will be passed to the callback function upon process completion. It allows users to associate custom data with the process execution. This is an `intent(inout), target` argument. ### Return Value Returns an object of type `process_type` that contains information about the state of the created process. ### Example ```fortran ! Example usage with command line or list of arguments type(process_type) :: p ! Run a simple command line synchronously p = run("echo 'Hello, world!'", want_stdout=.true.) ``` ## `runasync` - Execute an external process asynchronously ### Status Experimental ### Description The `runasync` interface allows execution of external processes using a single command string or a list of arguments. Processes are run asynchronously (non-blocking), meaning execution does not wait for the process to finish. Optional arguments enable the collection of standard output and error streams, as well as sending input via standard input. Additionally, a callback function can be specified to execute upon process completion, optionally receiving a user-defined payload. ### Syntax `process = ` [[stdlib_system(module):runasync(interface)]] `(args [, stdin] [, want_stdout] [, want_stderr] [, callback] [, payload])` ### Arguments `args`: Shall be a `character(*)` string (for command-line execution) or a `character(*), dimension(:)` array (for argument-based execution). It specifies the command and arguments to execute. This is an `intent(in)` argument. `stdin` (optional): Shall be a `character(*)` value containing input to send to the process via standard input (pipe). This is an `intent(in)` argument. `want_stdout` (optional): Shall be a `logical` flag. If `.true.`, the standard output of the process will be captured; if `.false.` (default), it will be lost. This is an `intent(in)` argument. `want_stderr` (optional): Shall be a `logical` flag. If `.true.`, the standard error output of the process will be captured. Default: `.false.`. This is an `intent(in)` argument. `callback` (optional): Shall be a procedure conforming to the `process_callback` interface. If present, this function will be called upon process completion with the process ID, exit state, and optionally collected standard input, output, and error streams. This is an `intent(in)` argument. `payload` (optional): Shall be a generic (`class(*)`) scalar that will be passed to the callback function upon process completion. It allows users to associate custom data with the process execution. This is an `intent(inout), target` argument. ### Return Value Returns an object of type `process_type` that contains information about the state of the created process. ### Example ```fortran {!example/system/example_process_1.f90!} ``` ## `is_running` - Check if a process is still running ### Status Experimental ### Description The `is_running` interface provides a method to check if an external process is still running. This is useful for monitoring the status of asynchronous processes created with the `run` interface. ### Syntax `status = ` [[stdlib_system(module):is_running(interface)]] `(process)` ### Arguments `process`: Shall be a `type(process_type)` object representing the external process to check. This is an `intent(inout)` argument. ### Return Value Returns a `logical` value: `.true.` if the process is still running, or `.false.` if the process has terminated. After a call to `is_running`, the `type(process_type)` structure is also updated to the latest process state. ### Example ```fortran {!example/system/example_process_2.f90!} ``` ## `is_completed` - Check if a process has completed execution ### Status Experimental ### Description The `is_completed` interface provides a method to check if an external process has finished execution. This is useful for determining whether asynchronous processes created with the `run` interface have terminated. ### Syntax `status = ` [[stdlib_system(module):is_completed(interface)]] `(process)` ### Arguments `process`: Shall be a `type(process_type)` object representing the external process to check. This is an `intent(inout)` argument. ### Return Value Returns a `logical` value: - `.true.` if the process has completed. - `.false.` if the process is still running. After a call to `is_completed`, the `type(process_type)` structure is updated to reflect the latest process state. ### Example ```fortran {!example/system/example_process_1.f90!} ``` ## `elapsed` - Return process lifetime in seconds ### Status Experimental ### Description The `elapsed` interface provides a method to calculate the total time that has elapsed since a process was started. This is useful for tracking the duration of an external process or for performance monitoring purposes. The result is a real value representing the elapsed time in seconds, measured from the time the process was created. ### Syntax `delta_t = ` [[stdlib_system(module):elapsed(interface)]] `(process)` ### Arguments `process`: Shall be a `type(process_type)` object representing the external process. It is an `intent(in)` argument. ### Return Value Returns a `real(real64)` value that represents the elapsed time (in seconds) since the process was started. If the process is still running, the value returned is the time elapsed until the call to this function. Otherwise, the total process duration from creation until completion is returned. ### Example ```fortran {!example/system/example_process_3.f90!} ``` ## `wait` - Wait until a running process is completed ### Status Experimental ### Description The `wait` interface provides a method to block the calling program until the specified process completes. If the process is running asynchronously, this subroutine will pause the workflow until the given process finishes. Additionally, an optional maximum wait time can be provided. If the process does not finish within the specified time, the subroutine will return without waiting further. On return from this routine, the process state is accordingly updated. This is useful when you want to wait for a background task to complete, but want to avoid indefinite blocking in case of process hang or delay. ### Syntax `call ` [[stdlib_system(module):wait(interface)]] `(process [, max_wait_time])` ### Arguments `process`: Shall be a `type(process_type)` object representing the external process to monitor. This is an `intent(inout)` argument, and its state is updated upon completion. `max_wait_time` (optional): Shall be a `real` value specifying the maximum wait time in seconds. If not provided, the subroutine will wait indefinitely until the process completes. ### Example ```fortran {!example/system/example_process_2.f90!} ``` ## `update` - Update the internal state of a process ### Status Experimental ### Description The `update` interface allows the internal state of a process object to be updated by querying the system. After the process completes, the standard output and standard error are retrieved, if they were requested, and loaded into the `process%stdout` and `process%stderr` string variables, respectively. This is especially useful for monitoring asynchronous processes and retrieving their output after they have finished. ### Syntax `call ` [[stdlib_system(module):update(interface)]] `(process)` ### Arguments `process`: Shall be a `type(process_type)` object representing the external process whose state needs to be updated. This is an `intent(inout)` argument, and its internal state is updated on completion. ### Example ```fortran {!example/system/example_process_5.f90!} ``` ## `kill` - Terminate a running process ### Status Experimental ### Description The `kill` interface is used to terminate a running external process. It attempts to stop the process and returns a boolean flag indicating whether the operation was successful. This interface is useful when a process needs to be forcefully stopped, for example, if it becomes unresponsive or if its execution is no longer required. ### Syntax `call ` [[stdlib_system(module):kill(interface)]] `(process, success)` ### Arguments `process`: Shall be a `type(process_type)` object representing the external process to be terminated. This is an `intent(inout)` argument, and on return is updated with the terminated process state. `success`: Shall be a `logical` variable. It is set to `.true.` if the process was successfully killed, or `.false.` otherwise. ### Example ```fortran {!example/system/example_process_4.f90!} ``` ## `sleep` - Pause execution for a specified time in milliseconds ### Status Experimental ### Description The `sleep` interface pauses the execution of a program for a specified duration, given in milliseconds. This routine acts as a cross-platform wrapper, abstracting the underlying platform-specific sleep implementations. It ensures that the requested sleep duration is honored on both Windows and Unix-like systems. ### Syntax `call ` [[stdlib_system(module):sleep(interface)]] `(millisec)` ### Arguments `millisec`: Shall be an `integer` representing the number of milliseconds to sleep. This is an `intent(in)` argument. ### Example ```fortran {!example/system/example_sleep.f90!} ``` ## `is_windows` - Check if the system is running on Windows ### Status Experimental ### Description The `is_windows` interface provides a quick, compile-time check to determine if the current system is Windows. It leverages a C function that checks for the presence of the `_WIN32` macro, which is defined in C compilers when targeting Windows. This function is highly efficient and works during the compilation phase, avoiding the need for runtime checks. ### Syntax `result = ` [[stdlib_system(module):is_windows(interface)]] `()` ### Return Value Returns a `logical` flag: `.true.` if the system is Windows, or `.false.` otherwise. ### Example ```fortran {!example/system/example_process_1.f90!} ``` ## `get_runtime_os` - Determine the OS type at runtime ### Status Experimental ### Description `get_runtime_os` inspects the runtime environment to identify the current OS type. It evaluates environment variables (`OSTYPE`, `OS`) and checks for specific files associated with known operating systems. The supported OS types are `integer, parameter` variables stored in the `stdlib_system` module: - **Linux** (`OS_LINUX`) - **macOS** (`OS_MACOS`) - **Windows** (`OS_WINDOWS`) - **Cygwin** (`OS_CYGWIN`) - **Solaris** (`OS_SOLARIS`) - **FreeBSD** (`OS_FREEBSD`) - **OpenBSD** (`OS_OPENBSD`) If the OS cannot be identified, the function returns `OS_UNKNOWN`. ### Syntax `os = ` [[stdlib_system(module):get_runtime_os(function)]] `()` ### Class Function ### Arguments None. ### Return Value Returns one of the `integer` `OS_*` parameters representing the OS type, from the `stdlib_system` module, or `OS_UNKNOWN` if undetermined. ### Example ```fortran {!example/system/example_get_runtime_os.f90!} ``` --- ## `OS_TYPE` - Cached OS type retrieval ### Status Experimental ### Description `OS_TYPE` provides a cached result of the `get_runtime_os` function. The OS type is determined during the first invocation and stored in a static variable. Subsequent calls reuse the cached value, making this function highly efficient. This caching mechanism ensures negligible overhead for repeated calls, unlike `get_runtime_os`, which performs a full runtime inspection. ### Syntax `os = ` [[stdlib_system(module):OS_TYPE(function)]]`()` ### Class Function ### Arguments None. ### Return Value Returns one of the `integer` `OS_*` parameters representing the OS type, from the `stdlib_system` module, or `OS_UNKNOWN` if undetermined. ### Example ```fortran {!example/system/example_os_type.f90!} ``` --- ## `FS_ERROR` - Helper function for error handling ### Status Experimental ### Description A helper function for returning the `type(state_type)` with the flag `STDLIB_FS_ERROR` set. ### Syntax `err = FS_ERROR([a1,a2,a3,a4...... a20])` ### Class Pure Function ### Arguments `a1,a2,a3.....a20`(optional): They are of type `class(*), dimension(..), optional, intent(in)`. An arbitrary list of `integer`, `real`, `complex`, `character` or `string_type` variables. Numeric variables may be provided as either scalars or rank-1 (array) inputs. ### Behavior Formats all the arguments into a nice error message, utilizing the constructor of [[stdlib_system(module):state_type(type)]] ### Return values `type(state_type)` ### Example ```fortran {!example/system/example_fs_error.f90!} ``` --- ## `FS_ERROR_CODE` - Helper function for error handling (with error code) ### Status Experimental ### Description A helper function for returning the `type(state_type)` with the flag `STDLIB_FS_ERROR` set. It also formats and prefixes the `code` passed to it as the first argument. ### Syntax `err = FS_ERROR_CODE(code [, a1,a2,a3,a4...... a19])` ### Class Pure Function ### Arguments `code`: An `integer` code. `a1,a2,a3.....a19`(optional): They are of type `class(*), dimension(..), optional, intent(in)`. An arbitrary list of `integer`, `real`, `complex`, `character` or `string_type` variables. Numeric variables may be provided as either scalars or rank-1 (array) inputs. ### Behavior Formats all the arguments into a nice error message, utilizing the constructor of [[stdlib_system(module):state_type(type)]] ### Return values `type(state_type)` ### Example ```fortran {!example/system/example_fs_error.f90!} ``` --- ## `is_file` - Test if a path is a regular file ### Status Experimental ### Description This function checks if a specified file system path is a regular file. It follows symbolic links and returns the status of the `target`. It is designed to work across multiple platforms. On Windows, paths with both forward `/` and backward `\` slashes are accepted. ### Syntax `result = ` [[stdlib_system(module):is_file(function)]]`(path)` ### Class Function ### Arguments `path`: Shall be a character string containing the file system path to evaluate. It is an `intent(in)` argument. ### Return values The function returns a `logical` value: - `.true.` if the path matches an existing regular file. - `.false.` otherwise, or if path does not exist. ### Example ```fortran {!example/system/example_is_file.f90!} ``` --- ## `is_directory` - Test if a path is a directory ### Status Experimental ### Description This function checks if a specified file system path is a directory. It follows symbolic links and returns the status of the `target`. It is designed to work across multiple platforms. On Windows, paths with both forward `/` and backward `\` slashes are accepted. ### Syntax `result = ` [[stdlib_system(module):is_directory(function)]]`(path)` ### Class Function ### Arguments `path`: Shall be a character string containing the file system path to evaluate. It is an `intent(in)` argument. ### Return values The function returns a `logical` value: - `.true.` if the path matches an existing directory. - `.false.` otherwise, or if the operating system is unsupported. ### Example ```fortran {!example/system/example_is_directory.f90!} ``` --- ## `is_symlink` - Test if a path is a symbolic link. ### Status Experimental ### Description This function checks if a specified file system path is a symbolic link to either a file or a directory. Use [[stdlib_system(module):is_file(function)]] and [[stdlib_system(module):is_directory(function)]] functions to check further if the link is to a file or a directory respectively. It is designed to work across multiple platforms. On Windows, paths with both forward `/` and backward `\` slashes are accepted. ### Syntax `result = ` [[stdlib_system(module):is_symlink(function)]]`(path)` ### Class Function ### Arguments `path`: Shall be a character string containing the file system path to evaluate. It is an `intent(in)` argument. ### Return values The function returns a `logical` value: - `.true.` if the path matches an existing regular file. - `.false.` otherwise, or if the path does not exist. ### Example ```fortran {!example/system/example_is_symlink.f90!} ``` --- ## `make_directory` - Creates an empty directory ### Status Experimental ### Description It creates an empty directory with default permissions. It is designed to work across multiple platforms. On Windows, paths with both forward `/` and backward `\` slashes are accepted. ### Syntax `call [[stdlib_system(module):make_directory(subroutine)]] (path [,err])` ### Class Subroutine ### Arguments `path`: Shall be a character string containing the path of the directory to create. It is an `intent(in)` argument. `err`(optional): Shall be of type `state_type`, and is used for error handling. It is an `optional, intent(out)` argument. ### Return values `err` is an optional state return flag. If not requested and an error occurs, an `FS_ERROR` will trigger an error stop. ### Example ```fortran {!example/system/example_make_directory.f90!} ``` --- ## `make_directory_all` - Creates an empty directory with all its parent directories ### Status Experimental ### Description It creates an empty directory with default permissions. It also creates all the necessary parent directories in the path if they do not exist already. ### Syntax `call [[stdlib_system(module):make_directory_all(subroutine)]] (path [,err])` ### Class Subroutine ### Arguments `path`: Shall be a character string containing the path of the directory to create. It is an `intent(in)` argument. `err`(optional): Shall be of type `state_type`, and is used for error handling. It is an `optional, intent(out)` argument. ### Return values `err` is an optional state return flag. If not requested and an error occurs, an `FS_ERROR` will trigger an error stop. ### Example ```fortran {!example/system/example_make_directory.f90!} ``` --- ## `remove_directory` - Removes an empty directory ### Status Experimental ### Description It deletes an empty directory. It is designed to work across multiple platforms. On Windows, paths with both forward `/` and backward `\` slashes are accepted. ### Syntax `call [[stdlib_system(module):remove_directory(subroutine)]] (path, err)` ### Class Subroutine ### Arguments `path`: Shall be a character string containing the path of the directory to create. It is an `intent(in)` argument. `err`(optional): Shall be of type `state_type`, and is used for error handling. It is an `optional, intent(out)` argument. ### Return values `err` is an optional state return flag. On error if not requested, an `FS_ERROR` will trigger an error stop. ### Example ```fortran {!example/system/example_remove_directory.f90!} ``` --- ## `get_cwd` - Gets the current working directory ### Status Experimental ### Description This subroutine retrieves the current working directory the running process is executing from. It is designed to work across multiple platforms. On Windows, paths with both forward `/` and backward `\` slashes are accepted. ### Syntax `call [[stdlib_system(module):get_cwd(subroutine)]] (cwd [, err])` ### Class Subroutine ### Arguments `cwd`: Shall be a character string for receiving the path of the current working directory (cwd). It is an `intent(out)` argument. `err`(optional): Shall be of type `state_type`, and is used for error handling. It is an `intent(out)` argument. ### Return values `err` is an optional state return flag. On error if not requested, an `FS_ERROR` will trigger an error stop. ### Example ```fortran {!example/system/example_cwd.f90!} ``` --- ## `set_cwd` - Sets the current working directory ### Status Experimental ### Description This subrotine sets the current working directory the process is executing from. It is designed to work across multiple platforms. On Windows, paths with both forward `/` and backward `\` slashes are accepted. ### Syntax `call [[stdlib_system(module):set_cwd(subroutine)]] (path [, err])` ### Class Subroutine ### Arguments `path`: Shall be a character string containing the path of the directory. It is an `intent(in)` argument. `err`(optional): Shall be of type `state_type`, and is used for error handling. It is an `intent(out)` argument. ### Return values `err` is an optional state return flag. On error if not requested, an `FS_ERROR` will trigger an error stop. ### Example ```fortran {!example/system/example_cwd.f90!} ``` --- ## `exists` - Checks if a path exists in the filesystem ### Status Experimental ### Description This function makes a system call (syscall) to retrieve metadata for the specified path and determines its type. It can distinguish between the following path types: - Regular File - Directory - Symbolic Link It returns a constant representing the detected path type, or `type_unknown` if the type cannot be determined. Any encountered errors are handled using `state_type`. ### Syntax `fs_type = [[stdlib_system(module):exists(function)]] (path [, err])` ### Class Function ### Arguments `path`: Shall be a character string containing the path. It is an `intent(in)` argument. `err`(optional): Shall be of type `state_type`, and is used for error handling. It is an `optional, intent(out)` argument. ### Return values `fs_type`: An `intent(out), integer` parameter indicating the type. The possible values are: - `fs_type_unknown`: 0 => an unknown type - `fs_type_regular_file`: 1 => a regular file - `fs_type_directory`: 2 => a directory - `fs_type_symlink`: 3 => a symbolic link `err`(optional): It is an optional state return flag. If not requested and an error occurs, an `FS_ERROR` will trigger an error stop. ```fortran {!example/system/example_exists.f90!} ``` --- ## `null_device` - Return the null device file path ### Status Experimental ### Description This function returns the file path of the null device, which is a special file used to discard any data written to it. It reads as an empty file. The null device's path varies by operating system: - On Windows, the null device is represented as `NUL`. - On UNIX-like systems (Linux, macOS), the null device is represented as `/dev/null`. ### Syntax `path = ` [[stdlib_system(module):null_device(function)]]`()` ### Class Function ### Arguments None. ### Return Value - **Type:** `character(:), allocatable` - Returns the null device file path as a character string, appropriate for the operating system. ### Example ```fortran {!example/system/example_null_device.f90!} ``` --- ## `delete_file` - Delete a file ### Status Experimental ### Description This subroutine deletes a specified file from the filesystem. It ensures that the file exists and is not a directory before attempting deletion. If the file cannot be deleted due to permissions, being a directory, or other issues, an error is raised. The function provides an optional error-handling mechanism via the `state_type` class. If the `err` argument is not provided, exceptions will trigger an `error stop`. ### Syntax `call ` [[stdlib_system(module):delete_file(subroutine)]]` (path [, err])` ### Class Subroutine ### Arguments `path`: Shall be a character string containing the path to the file to be deleted. It is an `intent(in)` argument. `err` (optional): Shall be a `type(state_type)` variable for error handling. If provided, errors are returned as a state object. If not provided, the program stops execution on error. ### Behavior - Checks if the file exists. If not, an error is raised. - Ensures the path is not a directory before deletion. - Attempts to delete the file, raising an error if unsuccessful. ### Return values The file is removed from the filesystem if the operation is successful. If the operation fails, an error is raised. ### Example ```fortran {!example/system/example_delete_file.f90!} ``` --- ## `join_path` - Joins the provided paths according to the OS ### Status Experimental ### Description This interface joins the paths provided to it according to the platform specific path-separator. i.e `\` for windows and `/` for others ### Syntax `res = ` [[stdlib_system(module):join_path(interface)]] ` (p1, p2)` `res = ` [[stdlib_system(module):join_path(interface)]] ` (p)` ### Class Pure function ### Arguments `p1, p2`: Shall be a character string or `type(string_type)`. It is an `intent(in)` argument. or `p`: Shall be a list of character strings or list of `type(string_type)`. It is an `intent(in)` argument. ### Return values The resultant path, either a character string or `type(string_type)`. ## `operator(/)` Alternative syntax to`join_path` using an overloaded operator. Join two paths according to the platform specific path-separator. ### Status Experimental ### Syntax `p = lval / rval` ### Class Pure function. ### Arguments `lval`: A character string or `type(string_type)`. It is an `intent(in)` argument. `rval`: A character string or `type(string_type)`. It is an `intent(in)` argument. ### Result value The result is an `allocatable` character string or `type(string_type)` #### Example ```fortran {!example/system/example_path_join.f90!} ``` --- ## `split_path` - splits a path immediately following the last separator ### Status Experimental ### Description This subroutine splits a path immediately following the last separator after removing the trailing separators splitting it into most of the times a directory and a file name. ### Syntax `call `[[stdlib_system(module):split_path(interface)]]`(p, head, tail)` ### Class Subroutine ### Arguments `p`: A character string or `type(string_type)` containing the path to be split. It is an `intent(in)` argument. `head`: The first part of the path. Either a character string or `type(string_type)`. It is an `intent(out)` argument. `tail`: The rest part of the path. Either a character string or `type(string_type)`. It is an `intent(out)` argument. ### Behavior - If `p` is empty, `head` is set to `.` and `tail` is left empty. - If `p` consists entirely of path-separators, `head` is set to the path-separator and `tail` is left empty. - `head` ends with a path-separator if and only if `p` appears to be a root directory or child of one. ### Return values The splitted path. `head` and `tail`. ### Example ```fortran {!example/system/example_path_split_path.f90!} ``` --- ## `base_name` - The last part of a path ### Status Experimental ### Description This function returns the last part of a path after removing trailing path separators. ### Syntax `res = ` [[stdlib_system(module):base_name(interface)]]`(p)` ### Class Function ### Arguments `p`: the path, a character string or `type(string_type)`. It is an `intent(in)` argument. ### Behavior - The `tail` of `[[stdlib_system(module):split_path(interface)]]` is exactly what is returned. Same Behavior. ### Return values A character string or `type(string_type)`. ### Example ```fortran {!example/system/example_path_base_name.f90!} ``` --- ## `dir_name` - Everything except the last part of the path ### Status Experimental ### Description This function returns everything except the last part of a path. ### Syntax `res = ` [[stdlib_system(module):dir_name(interface)]]`(p)` ### Class Function ### Arguments `p`: the path, a character string or `type(string_type)`. It is an `intent(in)` argument. ### Behavior - The `head` of `[[stdlib_system(module):split_path(interface)]]` is exactly what is returned. Same Behavior. ### Return values A character string or `type(string_type)`. ### Example ```fortran {!example/system/example_path_dir_name.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_stats_distribution_normal.md0000664000175000017500000001356615135654166027253 0ustar alastairalastair--- title: stats_distribution_normal --- # Statistical Distributions -- Normal Distribution Module [TOC] ## `rvs_normal` - normal distribution random variates ### Status Experimental ### Description A normal continuous random variate distribution, also known as Gaussian, or Gauss or Laplace-Gauss distribution. The location `loc` specifies the mean or expectation (\(\mu\)). The `scale` specifies the standard deviation (\(\sigma\)). Without argument, the function returns a standard normal distributed random variate \(N(0,1)\). With two arguments, the function returns a normal distributed random variate \(N(\mu=\text{loc}, \sigma^2=\text{scale}^2)\). For complex arguments, the real and imaginary parts are independent of each other. With three arguments, the function returns a rank-1 array of normal distributed random variates. With one or two arguments where the first is `array_size`, the function returns a rank-1 array of standard normal distributed random variates \(N(0,1)\). The `mold` argument determines the output type and kind; it is optional only for `real(dp)` (and defaults to `real(dp)` when omitted), but required for all other types. @note The algorithm used for generating exponential random variates is fundamentally limited to double precision.[^1] ### Syntax `result = ` [[stdlib_stats_distribution_normal(module):rvs_normal(interface)]] `([loc, scale] [[, array_size]])` `result = ` [[stdlib_stats_distribution_normal(module):rvs_normal(interface)]] `(array_size [, mold])` ### Class Elemental function (passing both `loc` and `scale`). ### Arguments `loc`: optional argument has `intent(in)` and is a scalar of type `real` or `complex`. `scale`: optional argument has `intent(in)` and is a positive scalar of type `real` or `complex`. `array_size`: optional argument has `intent(in)` and is a scalar of type `integer`. When used with `loc` and `scale`, specifies the size of the output array. When used alone or with `mold`, must be provided as the first argument. `mold`: optional argument (only for `real(dp)`; required for other types) has `intent(in)` and is a scalar of type `real` or `complex`. Used only to determine the type and kind of the output; its value is not referenced. When omitted (only allowed for `real(dp)`), defaults to `real(dp)`. When provided, generates standard normal variates \(N(0,1)\) of the specified type and kind. `loc` and `scale` arguments must be of the same type. ### Return value The result is a scalar or rank-1 array, with a size of `array_size`, and the same type as `scale` and `loc` (or same type and kind as `mold` when using the `array_size [, mold]` form; defaults to `real(dp)` when `mold` is omitted). If `scale` is non-positive, the result is `NaN`. ### Example ```fortran {!example/stats_distribution_normal/example_normal_rvs.f90!} ``` ## `pdf_normal` - normal distribution probability density function ### Status Experimental ### Description The probability density function (pdf) of the single real variable normal distribution: $$f(x) = \frac{1}{\sigma \sqrt{2\pi}} \exp{\left[-\frac{1}{2}\left(\frac{x-\mu}{\sigma}\right)^{2}\right]}$$ For a complex varible \( z=(x + y i) \) with independent real \( x \) and imaginary \( y \) parts, the joint probability density function is the product of the the corresponding real and imaginary marginal pdfs:[^2] $$f(x + y \mathit{i}) = f(x) f(y) = \frac{1}{2\pi\sigma_{x}\sigma_{y}} \exp{\left[-\frac{1}{2}\left(\left(\frac{x-\mu_x}{\sigma_{x}}\right)^{2}+\left(\frac{y-\mu_y}{\sigma_{y}}\right)^{2}\right)\right]}$$ ### Syntax `result = ` [[stdlib_stats_distribution_normal(module):pdf_normal(interface)]] `(x, loc, scale)` ### Class Elemental function ### Arguments `x`: has `intent(in)` and is a scalar of type `real` or `complex`. `loc`: has `intent(in)` and is a scalar of type `real` or `complex`. `scale`: has `intent(in)` and is a positive scalar of type `real` or `complex`. All three arguments must have the same type. ### Return value The result is a scalar or an array, with a shape conformable to the arguments, and the same type as the input arguments. If `scale` is non-positive, the result is `NaN`. ### Example ```fortran {!example/stats_distribution_normal/example_normal_pdf.f90!} ``` ## `cdf_normal` - normal distribution cumulative distribution function ### Status Experimental ### Description Cumulative distribution function of the single real variable normal distribution: $$F(x) = \frac{1}{2}\left [ 1+\text{erf}\left(\frac{x-\mu}{\sigma \sqrt{2}}\right) \right ]$$ For the complex variable \( z=(x + y i) \) with independent real \( x \) and imaginary \( y \) parts, the joint cumulative distribution function is the product of the corresponding real and imaginary marginal cdfs:[^2] $$ F(x+y\mathit{i})=F(x)F(y)=\frac{1}{4} \ \left[ 1+\text{erf}\left(\frac{x-\mu_x}{\sigma_x \sqrt{2}}\right) \right] \ \left[ 1+\text{erf}\left(\frac{y-\mu_y}{\sigma_y \sqrt{2}}\right) \right] $$ ### Syntax `result = ` [[stdlib_stats_distribution_normal(module):cdf_normal(interface)]] `(x, loc, scale)` ### Class Elemental function ### Arguments `x`: has `intent(in)` and is a scalar of type `real` or `complex`. `loc`: has `intent(in)` and is a scalar of type `real` or `complex`. `scale`: has `intent(in)` and is a positive scalar of type `real` or `complex`. All three arguments must have the same type. ### Return value The result is a scalar or an array, with a shape conformable to the arguments, and the same type as the input arguments. If `scale` is non-positive, the result is `NaN`. ### Example ```fortran {!example/stats_distribution_normal/example_normal_cdf.f90!} ``` [^1]: Marsaglia, George, and Wai Wan Tsang. "The ziggurat method for generating random variables." _Journal of statistical software_ 5 (2000): 1-7. [^2]: Miller, Scott, and Donald Childers. _Probability and random processes: With applications to signal processing and communications_. Academic Press, 2012 (p. 197). fortran-lang-stdlib-0ede301/doc/specs/stdlib_constants.md0000664000175000017500000000467615135654166023764 0ustar alastairalastair--- title: constants --- [TOC] ## Introduction The [[stdlib_constants]] module provides mathematical constants and the most common physical constants. **Warning**: The names of the most common physical constants are kept short as they are inside a dedicated module. Nonetheless, in case of overlapping names, they can always be renamed as following: ```fortran use stdlib_constants, only: clight => c ``` ## Codata The [[stdlib_codata(module)]] module defines all codata (physical) constants as derived type. The module is automatically generated with a simple [parser written in Python](https://github.com/MilanSkocic/codata/) The latest codata constants were released in 2022 by the [NIST](http://physics.nist.gov/constants) All values for the codata constants are provided as double precision reals. The names are quite long and can be aliased with shorter names. The derived type [[stdlib_codata_type(module):codata_constant_type(type)]] defines: * 4 members: * `name` (string) * `value` (double precision real) * `uncertainty` (double precision real) * `unit` (string) * 2 type-bound procedures: * `print`: to print the values of the constant members; * `to_real`: to get the value or the uncertainty to the desired precision. A module level interface [[stdlib_codata_type(module):to_real(interface)]] is available for getting the constant value or uncertainty of a constant. ## `to_real` - Get the constant value or its uncertainty. ### Status Experimental ### Description Convert a [[stdlib_codata_type(module):codata_constant_type(type)]] to a `real` (at least `sp`, or `dp`) scalar. **Warning**: Some constants cannot be converted to single precision `sp` reals due to the value of the exponents. ### Syntax `r = ` [[stdlib_codata_type(module):to_real(interface)]] `(c, mold [, uncertainty])` ### Arguments `c`: argument has `intent(in) ` and shall be of type [[stdlib_codata_type(module):codata_constant_type(type)]]. `mold`: argument has `intent(in)` and shall be of `real` type. **Note**: The type of the `mold` argument defines the type of the result. `uncertainty` (optional): argument has `intent(in)` and shall be of `logical` type. It specifies if the uncertainty needs to be returned instead of the value. Default to `.false.`. ### Return value Returns a scalar of `real` type which is either the value or the uncertainty of a codata constant. ## Example ```fortran {!example/constants/example_constants.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_io.md0000664000175000017500000002150615135654166022346 0ustar alastairalastair--- title: io --- # IO [TOC] ## `loadtxt` - load a 2D array from a text file ### Status Experimental ### Description Loads a rank-2 `array` from a text file. ### Syntax `call ` [[stdlib_io(module):loadtxt(interface)]] `(filename, array [, skiprows] [, max_rows] [, fmt] [, delimiter])` ### Arguments `filename`: Shall be a character expression containing the file name from which to load the rank-2 `array`. `array`: Shall be an allocatable rank-2 array of type `real`, `complex` or `integer`. `skiprows` (optional): Skip the first `skiprows` lines. If skipping more rows than present, a 0-sized array will be returned. The default is 0. `max_rows` (optional): Read `max_rows` lines of content after `skiprows` lines. A negative value results in reading all lines. A value of zero results in no lines to be read. The default value is -1. `fmt` (optional): Fortran format specifier for the text read. Defaults to the write format for the data type. Setting fmt='*' will specify list directed read. `delimiter` (optional): Shall be a character expression of length 1 that contains the delimiter used to separate the columns. The default is `' '`. ### Return value Returns an allocated rank-2 `array` with the content of `filename`. ### Example ```fortran {!example/io/example_loadtxt.f90!} ``` ## `open` - open a file ### Status Experimental ### Description Returns the unit number of a file opened to read, to write, or to read and write. The file might be a text file or a binary file. Text files are opened using a sequential access, while binary files are opened using a streamed access. ### Syntax `u = ` [[stdlib_io(module):open(function)]] `(filename [, mode] [, iostat])` ### Arguments `filename`: Shall be a character expression containing the name of the file to open. `mode` (optional): Shall be a character expression containing characters describing the way in which the file will be used. The available modes are: | Character | Meaning | | --------- | ------- | | `'r'` | open for reading (default) | | `'w'` | open for writing, truncating the file first | | `'x'` | open for exclusive creation, failing if the file already exists | | `'a'` | open for writing, appending to the end of the file if it exists | | `'+'` | open for updating (reading and writing) | | `'b'` | binary mode | | `'t'` | text mode (default) | The default `mode` is `'rt'` (i.e. open for reading a text file). The `mode` may include one of the four different methods for opening a file (i.e., `'r'`, `'w'`, `'x'`, and `'a'`). These four methods can be associated with the character `'+'` to open the file for updating. In addition, it can be specified if the file should be handled as a binary file (`'b'`) or a text file (`'t'`). `iostat` (optional): Shall be a scalar of type `integer` that receives the error status of `open`, if provided. If no error exists, `iostat` is zero. `u`: Shall be a scalar of type `integer` that specifies the unit number associated with the file `filename`. ### Return value The result is a scalar of type `integer`. ### Example ```fortran {!example/io/example_open.f90!} ``` ## `savetxt` - save a 2D array into a text file ### Status Experimental ### Description Saves a rank-2 `array` into a text file. ### Syntax `call ` [[stdlib_io(module):savetxt(interface)]] `(filename, array [, delimiter])` ### Arguments `filename`: Shall be a character expression containing the name of the file that will contain the 2D `array`. `array`: Shall be a rank-2 array of type `real`, `complex` or `integer`. `delimiter` (optional): Shall be a character expression of length 1 that contains the delimiter used to separate the columns. The default is `' '`. ### Output Provides a text file called `filename` that contains the rank-2 `array`. ### Example ```fortran {!example/io/example_savetxt.f90!} ``` ## `load_npy` ### Status Experimental ### Description Loads an `array` from a npy formatted binary file. ### Syntax `call ` [[stdlib_io_npy(module):load_npy(interface)]] `(filename, array[, iostat][, iomsg])` ### Arguments `filename`: Shall be a character expression containing the file name from which to load the `array`. This argument is `intent(in)`. `array`: Shall be an allocatable array of any rank of type `real`, `complex` or `integer`. This argument is `intent(out)`. `iostat`: Default integer, contains status of loading to file, zero in case of success. It is an optional argument, in case not present the program will halt for non-zero status. This argument is `intent(out)`. `iomsg`: Deferred length character value, contains error message in case `iostat` is non-zero. It is an optional argument, error message will be dropped if not present. This argument is `intent(out)`. ### Return value Returns an allocated `array` with the content of `filename` in case of success. ### Example ```fortran {!example/io/example_loadnpy.f90!} ``` ## `save_npy` ### Status Experimental ### Description Saves an `array` into a npy formatted binary file. ### Syntax `call ` [[stdlib_io_npy(module):save_npy(interface)]] `(filename, array[, iostat][, iomsg])` ### Arguments `filename`: Shall be a character expression containing the name of the file that will contain the `array`. This argument is `intent(in)`. `array`: Shall be an array of any rank of type `real`, `complex` or `integer`. This argument is `intent(in)`. `iostat`: Default integer, contains status of saving to file, zero in case of success. It is an optional argument, in case not present the program will halt for non-zero status. This argument is `intent(out)`. `iomsg`: Deferred length character value, contains error message in case `iostat` is non-zero. It is an optional argument, error message will be dropped if not present. This argument is `intent(out)`. ### Output Provides a npy file called `filename` that contains the rank-2 `array`. ### Example ```fortran {!example/io/example_savenpy.f90!} ``` ## `get_line` ### Status Experimental ### Description Read a whole line from a formatted unit into a string variable ### Syntax `call ` [[stdlib_io(module):get_line(interface)]] ` (unit, line[, iostat][, iomsg])` `call ` [[stdlib_io(module):get_line(interface)]] ` (line[, iostat][, iomsg])` ### Arguments `unit`: Formatted input unit. This argument is `intent(in)`. If `unit` is not specified standard input is used. `line`: Deferred length character or `string_type` variable. This argument is `intent(out)`. `iostat`: Default integer, contains status of reading from unit, zero in case of success. It is an optional argument, in case not present the program will halt for non-zero status. This argument is `intent(out)`. `iomsg`: Deferred length character value, contains error message in case `iostat` is non-zero. It is an optional argument, error message will be dropped if not present. This argument is `intent(out)`. ### Example ```fortran {!example/io/example_get_line.f90!} ``` ## Formatting constants ### Status Experimental ### Description Formatting constants for printing out integer, floating point, and complex numbers at their full precision. Provides formats for all kinds as defined in the `stdlib_kinds` module. ### Example ```fortran {!example/io/example_fmt_constants.f90!} ``` ## `get_file` - Read a whole ASCII file into a `character` or a `string` variable ### Status Experimental ### Description This subroutine interface reads the entirety of a specified ASCII file and returns its content as a string or an allocatable `character` variable. The function provides an optional error-handling mechanism via the `state_type` class. If the `err` argument is not provided, exceptions will trigger an `error stop`. The function also supports an optional flag to delete the file after reading. ### Syntax `call [[stdlib_io(module):get_file(subroutine)]] (filename, file [, err] [, delete=.false.])` ### Class Function ### Arguments `filename`: Shall be a character input containing the path to the ASCII file to read. It is an `intent(in)` argument. `file`: Shall be a `type(string_type)` or an allocatable `character` variable containing the full content of the specified file. It is an `intent(out)` argument. `err` (optional): Shall be a `type(state_type)` variable. It is an `intent(out)` argument used for error handling. `delete` (optional): Shall be a `logical` flag. If `.true.`, the file is deleted after reading. Default is `.false.`. It is an `intent(in)` argument. ### Return values Output variable `file` will contain the full content of the specified file. Raises `STDLIB_IO_ERROR` if the file is not found, cannot be opened, read, or deleted. Exceptions trigger an `error stop` unless the optional `err` argument is provided. ### Example ```fortran {!example/io/example_get_file.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_str2num.md0000664000175000017500000000414015135654166023344 0ustar alastairalastair--- title: str2num --- # The `stdlib_str2num` module This module proposes a function-style interface for string-to-number conversion. It also profits from Fortran's interfaces to implement precision-dependant algorithms to maximize runtime efficiency. [TOC] ## `to_num` - conversion of strings to numbers ### Status Experimental ### Description Convert a string or an array of strings to numerical types. ### Syntax `number = ` [[stdlib_str2num(module):to_num(interface)]] `(string, mold)` ### Arguments `string`: argument has `intent(in)` and is of type `character(*)`. `mold`: argument has `intent(in)` and is of numerical type (that is of `integer` or of `real`). **Note**: The type of the `mold` argument defines the type of the result. ### Return value Return a scalar of numerical type (i.e., `integer`, or `real`). ### Example ```fortran {!example/strings/example_string_to_number.f90!} ``` ## `to_num_from_stream` - conversion of a stream of values in a string to numbers ### Status Experimental ### Description Convert a stream of values in a string to an array of values. ### Syntax `number = ` [[stdlib_str2num(module):to_num_from_stream(interface)]] `(string, mold)` ### Arguments `string`: argument has `intent(in)` and is of type `character(:), pointer`. `mold`: argument has `intent(in)` and is of numerical type (currently of `integer` or `real`). **Note**: The type of the `mold` argument defines the type of the result. ### Return value Return a scalar of numerical type (i.e., `integer` or `real`). ### Example ```fortran {!example/strings/example_stream_of_strings_to_numbers.f90!} ``` ## Note The accuracy of the conversion is implementation dependent; it is recommended that implementers guarantee precision down to the last 3 bits. **The current implementation has been tested to provide for** : `sp` : exact match `dp` : precision up-to epsilon(0.0_dp) `qp` : precision around 200*epsilon(0.0_qp) Where precision refers to the relative difference between `to_num` and `read`. On the other hand, `to_num` provides speed-ups ranging from 4x to >10x compared to the intrinsic `read`. fortran-lang-stdlib-0ede301/doc/specs/stdlib_ansi.md0000664000175000017500000001170115135654166022665 0ustar alastairalastair--- title: terminal colors ... # The `stdlib_ansi` module [TOC] ## Introduction Support terminal escape sequences to produce styled and colored terminal output. ## Derived types provided ### ``ansi_code`` type The ``ansi_code`` type represent an ANSI escape sequence with a style, foreground color and background color attribute. By default the instances of this type are empty and represent no escape sequence. #### Status Experimental #### Example ```fortran {!example/ansi/example_ansi_color.f90!} ``` ## Constants provided ### ``style_reset`` Style enumerator representing a reset escape code. ### ``style_bold`` Style enumerator representing a bold escape code. ### ``style_dim`` Style enumerator representing a dim escape code. ### ``style_italic`` Style enumerator representing an italic escape code. ### ``style_underline`` Style enumerator representing an underline escape code. ### ``style_blink`` Style enumerator representing a blink escape code. ### ``style_blink_fast`` Style enumerator representing a (fast) blink escape code. ### ``style_reverse`` Style enumerator representing a reverse escape code. ### ``style_hidden`` Style enumerator representing a hidden escape code. ### ``style_strikethrough`` Style enumerator representing a strike-through escape code. ### ``fg_color_black`` Foreground color enumerator representing a foreground black color escape code. ### ``fg_color_red`` Foreground color enumerator representing a foreground red color escape code. ### ``fg_color_green`` Foreground color enumerator representing a foreground green color escape code. ### ``fg_color_yellow`` Foreground color enumerator representing a foreground yellow color escape code. ### ``fg_color_blue`` Foreground color enumerator representing a foreground blue color escape code. ### ``fg_color_magenta`` Foreground color enumerator representing a foreground magenta color escape code. ### ``fg_color_cyan`` Foreground color enumerator representing a foreground cyan color escape code. ### ``fg_color_white`` Foreground color enumerator representing a foreground white color escape code. ### ``fg_color_default`` Foreground color enumerator representing a foreground default color escape code. ### ``bg_color_black`` Background color enumerator representing a background black color escape code. ### ``bg_color_red`` Background color enumerator representing a background red color escape code. ### ``bg_color_green`` Background color enumerator representing a background green color escape code. ### ``bg_color_yellow`` Background color enumerator representing a background yellow color escape code. ### ``bg_color_blue`` Background color enumerator representing a background blue color escape code. ### ``bg_color_magenta`` Background color enumerator representing a background magenta color escape code. ### ``bg_color_cyan`` Background color enumerator representing a background cyan color escape code. ### ``bg_color_white`` Background color enumerator representing a background white color escape code. ### ``bg_color_default`` Background color enumerator representing a background default color escape code. ## Procedures and methods provided ### ``to_string`` Generic interface to turn a style, foreground or background enumerator into an actual escape code string for printout. #### Syntax `string =` [[stdlib_ansi(module):to_string(interface)]] `(code)` #### Class Pure function. #### Argument ``code``: Style, foreground or background code of ``ansi_code`` type, this argument is ``intent(in)``. #### Result value The result is a default character string. #### Status Experimental #### Example ```fortran {!example/ansi/example_ansi_to_string.f90!} ``` ### ``operator(+)`` Add two escape sequences, attributes in the right value override the left value ones. #### Syntax `code = lval + rval` #### Class Pure function. #### Argument ``lval``: Style, foreground or background code of ``ansi_code`` type, this argument is ``intent(in)``. ``rval``: Style, foreground or background code of ``ansi_code`` type, this argument is ``intent(in)``. #### Result value The result is a style, foreground or background code of ``ansi_code`` type. #### Status Experimental #### Example ```fortran {!example/ansi/example_ansi_combine.f90!} ``` ### ``operator(//)`` Concatenate an escape code with a string and turn it into an actual escape sequence #### Syntax `str = lval // rval` #### Class Pure function. #### Argument ``lval``: Style, foreground or background code of ``ansi_code`` type or a character string, this argument is ``intent(in)``. ``rval``: Style, foreground or background code of ``ansi_code`` type or a character string, this argument is ``intent(in)``. #### Result value The result is a character string with the escape sequence prepended or appended. #### Status Experimental #### Example ```fortran {!example/ansi/example_ansi_concat.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_specialfunctions_activations.md0000664000175000017500000003515215135654166027716 0ustar alastairalastair--- title: specialfunctions_activations --- # Special functions - Neural Networks activations and their gradients [TOC] ## `Gaussian` - Gaussian function ### Status Experimental ### Description Computes the gaussian function: $$f(x)=\exp(-x^2)$$ ### Syntax `result = ` [[stdlib_specialfunctions(module):gaussian(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ### Example ```fortran {!example/specialfunctions_activations/example_gaussian.f90!} ``` ## `Gaussian_grad` - Gradient of the Gaussian function ### Status Experimental ### Description Computes the gradient of the gaussian function: $$f(x)=-2 * x * \exp( - x ^ 2)$$ ### Syntax `result = ` [[stdlib_specialfunctions(module):gaussian_grad(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `Elu` - Exponential Linear Unit function ### Status Experimental ### Description Computes the gaussian function: $$ \text{f}(x) = \begin{cases} x, & \text{if } x \geq 0 \\ a * (\exp(x) - 1), & \text{otherwise} \end{cases} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):elu(interface)]] ` (x,a)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. `a`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ### Example ```fortran {!example/specialfunctions_activations/example_elu.f90!} ``` ## `Elu_grad` - Gradient of the Exponential Linear Unit function ### Status Experimental ### Description Computes the gradient of the gaussian function: $$ \text{f}(x) = \begin{cases} 1, & \text{if } x \geq 0 \\ a * \exp(x), & \text{otherwise} \end{cases} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):elu_grad(interface)]] ` (x,a)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. `a`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `Relu` - Rectified Linear Unit function ### Status Experimental ### Description Computes the Rectified Linear Unit function: $$f(x) = \text{max}(0,x)$$ ### Syntax `result = ` [[stdlib_specialfunctions(module):relu(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ### Example ```fortran {!example/specialfunctions_activations/example_relu.f90!} ``` ## `Relu_grad` - Gradient of the Rectified Linear Unit function ### Status Experimental ### Description Computes the gradient of the gaussian function: $$ f(x) = \begin{cases} 1, & \text{if } x \geq 0 \\ 0, & \text{otherwise} \end{cases} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):relu_grad(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `leaky_relu` - leaky Rectified Linear Unit function ### Status Experimental ### Description Computes the gaussian function: $$ \text{f}(x) = \begin{cases} x, & \text{if } x \geq 0 \\ a * x, & \text{otherwise} \end{cases} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):leaky_relu(interface)]] ` (x,a)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. `a`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ### Example ```fortran {!example/specialfunctions_activations/example_leaky_relu.f90!} ``` ## `leaky_relu_grad` - Gradient of the leaky Rectified Linear Unit function ### Status Experimental ### Description Computes the gradient of the leaky_relu function: $$ \text{f}(x) = \begin{cases} 1, & \text{if } x \geq 0 \\ a , & \text{otherwise} \end{cases} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):leaky_relu_grad(interface)]] ` (x,a)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. `a`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as the input argument. ## `Gelu` - Gaussian Error Linear Unit function ### Status Experimental ### Description Computes the Gaussian Error Linear Unit function: $$f(x) = \frac{1}{2} x ( 1 + \text{erf}(\frac{x}{\sqrt{2}}) ) $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):gelu(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ### Example ```fortran {!example/specialfunctions_activations/example_gelu.f90!} ``` ## `Gelu_grad` - Gradient of the Gaussian Error Linear Unit function ### Status Experimental ### Description Computes the gradient of the gaussian error linear unit function: $$ f(x) = \frac{1}{2} ( 1 + \text{erf}(x \sqrt{2}) ) + x \sqrt{2} \exp( -\frac{1}{2} x^2) $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):gelu_grad(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `Gelu_approx` - Approximation of the Gaussian Error Linear Unit function ### Status Experimental ### Description Computes a fast approximation of the Gaussian Error Linear Unit function using a fast $\text{erf}$ approximation: $$f(x) = \frac{1}{2} x ( 1 + \text{ferf}(\frac{x}{\sqrt{2}}) ) $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):gelu_approx(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `Gelu_approx_grad` - Gradient of the Approximated Gaussian Error Linear Unit function ### Status Experimental ### Description Computes the gradient of the gaussian error linear unit function using a fast $\text{erf}$ approximation: $$ f(x) = \frac{1}{2} ( 1 + \text{ferf}(x \sqrt{2}) ) + x \sqrt{2} \exp( -\frac{1}{2} x^2) $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):gelu_approx_grad(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `Selu` - Scaled Exponential Linear Unit function ### Status Experimental ### Description Applies the Scaled Exponential Linear Unit activation function: $$ f(x) = \begin{cases} scale * x, & \text{if } x \ge 0 \\ scale * (\alpha * exp(x) - \alpha ), & \text{otherwise} \end{cases} $$ Where, $$scale = 1.0507009873554804934193349852946$$ and $$\alpha = 1.6732632423543772848170429916717$$ ### Syntax `result = ` [[stdlib_specialfunctions(module):selu(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ### Example ```fortran {!example/specialfunctions_activations/example_selu.f90!} ``` ## `selu_grad` - Gradient of the Scaled Exponential Linear Unit function ### Status Experimental ### Description Applies the gradient of the Scaled Exponential Linear Unit activation function: $$ f(x) = \begin{cases} scale, & \text{if } x \ge 0 \\ scale * \alpha * exp(x) , & \text{otherwise} \end{cases} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):selu_grad(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `Sigmoid` - Sigmoid function ### Status Experimental ### Description Computes the sigmoid function: $$f(x) = \frac{1}{1+\exp(-x)} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):sigmoid(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `Sigmoid_grad` - Gradient of the Sigmoid function ### Status Experimental ### Description Computes the gradient of the Sigmoid function: $$f(x) = \frac{\exp(x)}{(1+\exp(x))^2} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):sigmoid_grad(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `SiLU` - Sigmoid Linear Unit function ### Status Experimental ### Description Computes the Sigmoid Linear Unit function: $$f(x) = \frac{x}{1+\exp(-x)} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):silu(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ### Example ```fortran {!example/specialfunctions_activations/example_silu.f90!} ``` ## `Silu_grad` - Gradient of the Sigmoid Linear Unit function ### Status Experimental ### Description Computes the gradient of the Sigmoid function: $$f(x) = \frac{\exp(x)*(x+(1+\exp(x))^2)}{(1+\exp(x))^2} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):silu_grad(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `Step` - Step function ### Status Experimental ### Description Computes the step function: $$ f(x) = \begin{cases} 1, & \text{if } x > 0 \\ 0, & \text{otherwise} \end{cases} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):step(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ### Example ```fortran {!example/specialfunctions_activations/example_step.f90!} ``` ## `step_grad` - Gradient of the Step function ### Status Experimental ### Description Computes the gradient of the Sigmoid function: $$f(x) = 0 $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):step_grad(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `softmax` - softmax function ### Status Experimental ### Description Computes the softmax function: $$f(x) = \frac{\exp(x)-\text{max}(x_j)}{\sum_j{\exp(x)-\text{max}(x_j)}}$$ ### Syntax `result = ` [[stdlib_specialfunctions(module):softmax(interface)]] ` (x,dim)` ### Class Pure function for ranks 1 to 4. ### Arguments `x`: Shall be an array of rank 1 to 4 of any `real` kind. `dim`: integer scalar indicating upon which dimension to apply the normalization. ### Return value The function returns an array with the same rank and kind as the input argument `x`. ### Example ```fortran {!example/specialfunctions_activations/example_softmax.f90!} ``` ## `softmax_grad` - Gradient of the softmax function ### Status Experimental ### Description Computes the gradient of the softmax function: $$f(x,dim) = \text{softmax}(x,dim)*(1-\text{softmax}(x,dim)) $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):softmax_grad(interface)]] ` (x,dim)` ### Class Pure function for ranks 1 to 4. ### Arguments `x`: Shall be an array of rank 1 to 4 of any `real` kind. `dim`: integer scalar indicating upon which dimension to apply the normalization. ### Return value The function returns a value with the same type and kind as input argument. ## `softplus` - softplus function ### Status Experimental ### Description Computes the softplus function: $$f(x) = \log(\exp(x)+1)$$ ### Syntax `result = ` [[stdlib_specialfunctions(module):softplus(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ### Example ```fortran {!example/specialfunctions_activations/example_softplus.f90!} ``` ## `softplus_grad` - Gradient of the softplus function ### Status Experimental ### Description Computes the gradient of the softplus function: $$f(x) = \frac{\exp(x)}{\exp(x)+1} $$ ### Syntax `result = ` [[stdlib_specialfunctions(module):softplus_grad(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `Fast tanh` - Approximation of the hyperbolic tangent function ### Status Experimental ### Description Computes an approximated but faster solution to: $$f(x)=\tanh(x)$$ ### Syntax `result = ` [[stdlib_specialfunctions(module):fast_tanh(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `fast_tanh_grad` - Gradient of the approximation of the hyperbolic tangent function ### Status Experimental ### Description Computes the gradient of the `fast_tanh` function: $$f(x)=1 - \fast_tanh(x)^2$$ ### Syntax `result = ` [[stdlib_specialfunctions(module):fast_tanh_grad(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument. ## `Fast erf` - Approximation of the error function ### Status Experimental ### Description Computes an approximated but faster solution to: $$f(x)=\erf(x)$$ ### Syntax `result = ` [[stdlib_specialfunctions(module):fast_erf(interface)]] ` (x)` ### Class Elemental function ### Arguments `x`: Shall be a scalar or array of any `real` kind. ### Return value The function returns a value with the same type and kind as input argument.fortran-lang-stdlib-0ede301/doc/specs/stdlib_stats_distribution_uniform.md0000664000175000017500000001233415135654166027432 0ustar alastairalastair--- title: stats_distribution_uniform --- # Statistical Distributions -- Uniform Distribution Module [TOC] ## `shuffle` - Using Fisher-Yates algorithm to generate a random permutation of a list ### Status Experimental ### Description Applying Fisher-Yates algorithm to generate an unbiased permutation for any list of intrinsic numerical data types. ### Syntax `result = ` [[stdlib_stats_distribution_uniform(module):shuffle(interface)]] `( list )` ### Class Function. ### Arguments `list`: argument has `intent(in)` and is a rank one array of `integer`, `real`, or `complex` type. ### Return value Return a randomized rank one array of the input type. ### Example ```fortran {!example/stats_distribution_uniform/example_shuffle.f90!} ``` ## `rvs_uniform` - uniform distribution random variates ### Status Experimental ### Description Without argument the function returns a scalar standard uniformly distributed variate U(0,1) of `real` type with single precision on [0,1]. With single argument `scale` of `integer` type the function returns a scalar uniformly distributed variate of `integer` type on [0,scale]. This is the standard Rectangular distribution. With single argument `scale` of `real` or `complex` type the function returns a scalar uniformly distributed variate of `real` type on [0, scale] or `complex` type on [(0, 0i), (scale, i(scale))]. With double arguments `loc` and `scale` the function returns a scalar uniformly distributed random variates of `integer` or `real` type on [loc, loc + scale], or `complex` type on [(loc, i(loc)), ((loc + scale), i(loc + scale))], dependent of input type. With triple arguments `loc`, `scale` and `array_size` the function returns a rank one array of uniformly distributed variates of `integer`, `real` or `complex` type with an array size of `array_size`. For `complex` type, the real part and imaginary part are independent of each other. Note: the algorithm used for generating uniform random variates is fundamentally limited to double precision. ### Syntax `result = ` [[stdlib_stats_distribution_uniform(module):rvs_uniform(interface)]] `([[loc,] scale] [[[,array_size]]])` ### Class Elemental function (without the third argument). ### Arguments `loc`: optional argument has `intent(in)` and is a scalar of type `integer`, `real` or `complex`. `scale`: optional argument has `intent(in)` and is a scalar of type `integer`, `real` or `complex`. `array_size`: optional argument has `intent(in)` and is a scalar of type `integer` with default kind. `loc` and `scale` must have the same type and kind when both are present. ### Return value The result is a scalar or a rank one array with size of `array_size`, of type `integer`, `real` or `complex` depending on the input type. ### Example ```fortran {!example/stats_distribution_uniform/example_uniform_rvs.f90!} ``` ## `pdf_uniform` - Uniform distribution probability density function ### Status Experimental ### Description The probability density function of the uniform distribution: f(x) = 0 x < loc or x > loc + scale for all types uniform distributions For random variable x in [loc, loc + scale]: f(x) = 1 / (scale + 1); for discrete uniform distribution. f(x) = 1 / scale; for continuous uniform distribution. f(x) = 1 / (scale%re * scale%im); for complex uniform distribution. ### Syntax `result = ` [[stdlib_stats_distribution_uniform(module):pdf_uniform(interface)]] `(x, loc, scale)` ### Class Elemental function. ### Arguments `x`: has `intent(in)` and is a scalar of type `integer`, `real` or `complex`. `loc`: has `intent(in)` and is a scalar of type `integer`, `real` or `complex`. `scale`: has `intent(in)` and is a scalar of type `integer`, `real` or `complex`. All three arguments must have the same type and kind. ### Return value The result is a scalar or an array, with a shape conformable to arguments, of type `real`. ### Example ```fortran {!example/stats_distribution_uniform/example_uniform_pdf.f90!} ``` ## `cdf_uniform` - Uniform distribution cumulative distribution function ### Status Experimental ### Description Cumulative distribution function of the uniform distribution: F(x) = 0 x < loc for all types uniform distributions F(x) = 1 x > loc + scale for all types uniform distributions For random variable x in [loc, loc + scale]: F(x) = (x - loc + 1) / (scale + 1); for discrete uniform distribution. F(x) = (x - loc) / scale; for continuous uniform distribution. F(x) = (x%re - loc%re)(x%im - loc%im) / (scale%re * scale%im); for complex uniform distribution. ### Syntax `result = ` [[stdlib_stats_distribution_uniform(module):cdf_uniform(interface)]] `(x, loc, scale)` ### Class Elemental function. ### Arguments `x`: has `intent(in)` and is a scalar of type `integer`, `real` or `complex`. `loc`: has `intent(in)` and is a scalar of type `integer`, `real` or `complex`. `scale`: has `intent(in)` and is a scalar of type `integer`, `real` or `complex`. All three arguments must have the same type and kind. ### Return value The result is a scalar or an array, with a shape conformable to arguments, of type `real`. ### Example ```fortran {!example/stats_distribution_uniform/example_uniform_cdf.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_strings.md0000664000175000017500000003234615135654166023434 0ustar alastairalastair--- title: strings --- # The `stdlib_strings` module [TOC] ## Introduction The `stdlib_strings` module provides basic string handling and manipulation routines. ## Procedures and methods provided ### `strip` #### Description Remove leading and trailing whitespace characters. #### Syntax `string = ` [[stdlib_strings(module):strip(interface)]] ` (string)` #### Status Experimental #### Class Pure function. #### Argument - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). #### Result value The result is of the same type as `string`. #### Example ```fortran {!example/strings/example_strip.f90!} ``` ### `chomp` #### Description Remove trailing characters in *set* or *substring* from *string*. If no character *set* or *substring* is provided trailing whitespace is removed. #### Syntax `string = ` [[stdlib_strings(module):chomp(interface)]] ` (string[, set|substring])` #### Status Experimental #### Class Pure function. #### Argument - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `set`: Array of length one character. This argument is intent(in). - `substring`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). #### Result value The result is of the same type as `string`. #### Example ```fortran {!example/strings/example_chomp.f90!} ``` ### `starts_with` #### Description Check if a *string* starts with a given *substring*. #### Syntax `string = ` [[stdlib_strings(module):starts_with(interface)]] ` (string, substring)` #### Status Experimental #### Class Pure function. #### Argument - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `substring`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). #### Result value The result is of scalar logical type. #### Example ```fortran {!example/strings/example_starts_with.f90!} ``` ### `ends_with` #### Description Check if a *string* ends with a given *substring*. #### Syntax `string = ` [[stdlib_strings(module):ends_with(interface)]] ` (string, substring)` #### Status Experimental #### Class Pure function. #### Argument - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `substring`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). #### Result value The result is of scalar logical type. #### Example ```fortran {!example/strings/example_ends_with.f90!} ``` ### `slice` #### Description Extracts the characters from the defined region of the input string by taking strides. Argument `first` and `last` defines this region for extraction by function `slice`. Argument `stride` defines the magnitude and direction (+/-) of stride to be taken while extraction. `stride` when given invalid value 0, is converted to +1. Deduction Process: Function first automatically deduces the optional arguments that are not provided by the user. Deduced `first` and `last` argument take +infinity or -infinity value and deduced `stride` argument takes value +1 or -1 depending upon the actual argument(s) provided by the user. Extraction Process: Extraction starts only if `last` is crossable from `first` with stride of `stride`. Extraction starts from the first valid index in the defined region to take stride of `stride` and ends when the last valid index in the defined region is crossed. If no valid index exists in the defined region, empty string is returned. #### Syntax `string = ` [[stdlib_strings(module):slice(interface)]] ` (string [, first, last, stride])` #### Status Experimental #### Class Pure function. #### Argument - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `first`: integer. This argument is intent(in) and optional. - `last`: integer. This argument is intent(in) and optional. - `stride`: integer. This argument is intent(in) and optional. #### Result value The result is of the same type as `string`. #### Example ```fortran {!example/strings/example_slice.f90!} ``` ### `find` #### Description Returns the starting index of the `occurrence`th occurrence of the substring `pattern` in the input string `string`. Default value of `occurrence` is set to `1`. If `consider_overlapping` is not provided or is set to `.true.` the function counts two overlapping occurrences of substring `pattern` as two different occurrences. If `occurrence`th occurrence is not found, function returns `0`. #### Syntax `string = ` [[stdlib_strings(module):find(interface)]] ` (string, pattern [, occurrence, consider_overlapping])` #### Status Experimental #### Class Elemental function #### Argument - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `pattern`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `occurrence`: integer. This argument is intent(in) and optional. - `consider_overlapping`: logical. This argument is intent(in) and optional. #### Result value The result is a scalar of integer type or an integer array of rank equal to the highest rank among all dummy arguments. #### Example ```fortran {!example/strings/example_find.f90!} ``` ### `replace_all` #### Description Replaces all occurrences of substring `pattern` in the input `string` with the replacement `replacement`. Occurrences overlapping on a base occurrence will not be replaced. #### Syntax `string = ` [[stdlib_strings(module):replace_all(interface)]] ` (string, pattern, replacement)` #### Status Experimental #### Class Pure function #### Argument - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `pattern`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `replacement`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). #### Result value The result is of the same type as `string`. #### Example ```fortran {!example/strings/example_replace_all.f90!} ``` ### `padl` #### Description Returns a string of length `output_length` left padded with `pad_with` character if it is provided, otherwise with `" "` (1 whitespace). If `output_length` is less than or equal to the length of `string`, padding is not performed. #### Syntax `string = ` [[stdlib_strings(module):padl(interface)]] ` (string, output_length [, pad_with])` #### Status Experimental #### Class Pure function #### Argument - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `output_length`: integer. This argument is intent(in). - `pad_with`: Character scalar of length 1. This argument is intent(in) and optional. #### Result value The result is of the same type as `string`. #### Example ```fortran {!example/strings/example_padl.f90!} ``` ### `padr` #### Description Returns a string of length `output_length` right padded with `pad_with` character if it is provided, otherwise with `" "` (1 whitespace). If `output_length` is less than or equal to the length of `string`, padding is not performed. #### Syntax `string = ` [[stdlib_strings(module):padr(interface)]] ` (string, output_length [, pad_with])` #### Status Experimental #### Class Pure function #### Argument - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `output_length`: integer. This argument is intent(in). - `pad_with`: Character scalar of length 1. This argument is intent(in) and optional. #### Result value The result is of the same type as `string`. #### Example ```fortran {!example/strings/example_padr.f90!} ``` ### `count` #### Description Returns the number of times the substring `pattern` has occurred in the input string `string`. If `consider_overlapping` is not provided or is set to `.true.` the function counts two overlapping occurrences of substring `pattern` as two different occurrences. #### Syntax `string = ` [[stdlib_strings(module):count(interface)]] ` (string, pattern [, consider_overlapping])` #### Status Experimental #### Class Elemental function #### Argument - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `pattern`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `consider_overlapping`: logical. This argument is intent(in) and optional. #### Result value The result is a scalar of integer type or an integer array of rank equal to the highest rank among all dummy arguments. #### Example ```fortran {!example/strings/example_count.f90!} ``` ### `zfill` #### Description Returns a string of length `output_length` left-padded with zeros. If `output_length` is less than or equal to the length of `string`, padding is not performed. #### Syntax `string = ` [[stdlib_strings(module):zfill(interface)]] ` (string, output_length)` #### Status Experimental #### Class Pure function #### Argument - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is intent(in). - `output_length`: integer. This argument is intent(in). #### Result value The result is of the same type as `string`. #### Example ```fortran {!example/strings/example_zfill.f90!} ``` ### `join` #### Description Joins an array of strings into a single string. This function concatenates the strings from the input array, inserting a separator between each string (default: space). A user-defined separator may be provided, The resulting string is returned. #### Syntax `joined = ` [[stdlib_strings(module):join(interface)]] ` (strings, separator)` #### Status Experimental #### Class Pure function #### Argument - `strings`: Array of strings (either `type(string_type)` or `character(len=*)`). This argument is `intent(in)`. It is an array of strings that will be concatenated together. - `separator`: `character(len=*)` scalar (optional). This argument is `intent(in)`. It specifies the separator to be used between the strings. If not provided, the default separator (a space) is used. #### Result value The result is of the same type as the elements of `strings` (`type(string_type)` or `character(len=:), allocatable`). #### Example ```fortran {!example/strings/example_join.f90!} ``` ### `to_string` #### Description Format or transfer a `integer/real/complex/logical` scalar as a string. Input a wrong `format` that cause the internal-IO to fail, the result value is a string of `[*]`. #### Syntax `string = ` [[stdlib_strings(module):to_string(interface)]] ` (value [, format])` #### Status Experimental #### Class Pure function. #### Argument - `value`: Shall be an `integer/real/complex/logical` scalar. This is an `intent(in)` argument. - `format`: Shall be a `character(len=*)` scalar like `'(F6.2)'` or just `'F6.2'`. This is an `intent(in)` and `optional` argument. Contains the edit descriptor to format `value` into a string, for example `'(F6.2)'` or `'(f6.2)'`. `to_string` will automatically enclose `format` in a set of parentheses, so passing `F6.2` or `f6.2` as `format` is possible as well. #### Result value The result is an `allocatable` length `character` scalar with up to `128` cached `character` length. #### Example ```fortran {!example/strings/example_to_string.f90!} ``` ### `to_c_char` #### Description Convert a Fortran `character` string or a `type(string_type)` variable to a C character array. This function converts a Fortran string into a C-style array of characters, ensuring proper null-termination for use in C functions or libraries. #### Syntax `cstr = ` [[stdlib_strings(module):to_c_char(function)]] ` (value)` #### Status Experimental #### Class Pure function. #### Argument - `value`: Shall be a `character(len=*)` string or a `type(string_type)` variable. It is an `intent(in)` argument. This Fortran variable will be converted to a C character array. #### Result value The result is a `character(kind=c_char)` array with a dimension of `len(value) + 1` to accommodate the null terminator. #### Example ```fortran {!example/strings/example_to_c_char.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_logger.md0000664000175000017500000010052515135654166023215 0ustar alastairalastair--- title: logger --- # Loggers [TOC] ## Introduction This module defines a derived type, its methods, a variable, and constants to be used for the reporting of errors, displaying messages, and other information. The derived type, `logger_type`, is to be used to define both global and local logger variables. The `logger_type` methods serve to configure the loggers and use the logger variables to report messages to a variable specific list of I/O units termed `log_units`. The variable, `global_logger`, of type `logger_type`, is intended to serve as the default global logger. The constants serve as error flags returned by the optional integer `stat` argument. The logger variables have the option to: * change which units receive the log messages; * report which units receive the log messages; * select which types of messages are logged; * precede messages by a blank line; * precede messages by a time stamp of the form `yyyy-mm-dd hh:mm:ss.sss`; * precede messages with the names of a module and procedure; * follow a message with the `stat` and `errmsg` of the error report that prompted the log message; * follow a message with the `iostat` and `iomsg` of the I/O error report that prompted the log message; * label a message with one of `'DEBUG: '`, `'INFO: '`, `'WARN: '`, `'ERROR: '`, or `'I/O ERROR: '`; * indent subsequent lines of the messages; and * format the text to fit within a maximum column width. While every effort has been made to make the code process and asynchronous I/O safe, it is always best to have each process write to its own dedicated logger file. For thread parallelism (e.g., with OpenMP), it is advised to put the logger call in a guarding region (e.g., in an OpenMP critical region). Note: Loggers of type `logger_type` normally report their messages to I/O units in the internal list termed `log_units`. However if `log_units` is empty then the messages go to the `output_unit` of the intrinsic module `iso_fortran_env`. ## The `stdlib_logger` constants The module defines nine distinct public integer constants for reporting errors in the `stat` arguments of some of the module's procedures. The constants, termed error codes, are as follows: Error Code | Description -----------------------|------------ `success` | no error was detected `close_failure` | a `close` statement for an I/O unit failed `index_invalid_error` | the `column` was invalid for the given `line` `non_sequential_error` | the I/O unit did not have `SEQUENTIAL` access `open_failure` | an `open` statement failed `read_only_error` | an output unit did not have an `access` specifier of `'WRITE'` or `'READWRITE'` `unformatted_in_error` | the unit did not have a `form` of `'FORMATTED'` `unopened_in_error` | the unit was not opened `write_fault` | one of the writes to `log_units` failed The module also defines eight distinct public integer constants for selecting the messages that are logged. These constants, termed severity levels, are (sorted following their increasing order of severity): `all_level`, `debug_level`, `information_level`, `warning_level`, `error_level`, `io_error_level`, `text_error_level`, and `none_level`. All log messages with a level (e.g., `debug_level`) lower than a specified severity level (e.g., `information_level`) will be ignored. The levels `error_level` and `io_error_level` have the same severity. The default severity level is `information_level`. ## The derived type: logger_type ### Status Experimental ### Description Serves to define 'logger' variables to be used in reporting significant events encountered during the execution of a program. ### Syntax `type(` [[stdlib_logger(module):logger_type(type)]] `) :: variable` ### Private attributes | Attribute | Type | Description | Initial value | |------------------|---------------|-------------------------------------------------|---------------------| | `add_blank_line` | Logical | Flag to precede output with a blank line | `.false.` | | `indent_lines` | Logical | Flag to indent subsequent lines by four columns | `.true.` | | `level` | Integer | Severity level | `information_level` | | `log_units` | Integer array | List of I/O units used for output | Unallocated | | `max_width` | Integer | Maximum column width of output | 0 | | `time_stamp` | Logical | Flag to precede output by a time stamp | `.true.` | | `units` | Integer | Count of the number of active output units | 0 | ## The `stdlib_logger` variable The module defines one public variable, `global_logger`, of type `logger_type`. As might be guessed from its name, `global_logger` is intended to serve as the default logger for use throughout an application. ### Public `logger_type` methods The module defines twelve public procedures: one function and eleven subroutines. The methods are: Method | Class | Description ---------------------|------------|------------ [`add_log_file`](./stdlib_logger.html#add_log_file-open-a-file-and-add-its-unit-to-self-log_units) | Subroutine | Opens a file using `newunit`, and adds the resulting unit to the `log_units` list [`add_log_unit`](./stdlib_logger.html#add_log_unit-add-a-unit-to-the-array-self-log_units) | Subroutine | Adds an existing unit to the `log_units` list [`configuration`](./stdlib_logger.html#configuration-report-a-loggers-configuration) | Subroutine | Reports the details of the logging configuration [`configure`](./stdlib_logger.html#configure-configure-the-logging-process) | Subroutine | Configures the details of the logging process [`log_debug`](./stdlib_logger.html#log_debug-writes-the-string-message-to-self-log_units) | Subroutine | Sends a message prepended by `'DEBUG: '` [`log_error`](./stdlib_logger.html#log_error-writes-the-string-message-to-self-log_units) | Subroutine | Sends a message prepended by `'ERROR: '` optionally followed by a `stat` or `errmsg` [`log_information`](./stdlib_logger.html#log_information-writes-the-string-message-to-self-log_units) | Subroutine | Sends a message prepended by `'INFO: '` [`log_io_error`](./stdlib_logger.html#log_io_error-write-the-string-message-to-self-log_units) | Subroutine | Sends a message prepended by `'I/O ERROR: '` optionally followed by an `iostat` or `iomsg` [`log_message`](./stdlib_logger.html#log_message-write-the-string-message-to-self-log_units) | Subroutine | Sends a message [`log_text_error`](./stdlib_logger.html#log_text_error-send-a-message-to-self-log_units-describing-an-error) | Subroutine | Sends a message describing an error found in a line of text [`log_units_assigned`](./stdlib_logger.html#log_units_assigned-returns-the-number-of-active-io-units) | Function | Returns the number of active I/O units in `log_units` [`log_warning`](./stdlib_logger.html#log_warning-write-the-string-message-to-log_units) | Subroutine | Sends a message prepended by `'WARN: '` [`remove_log_unit`](./stdlib_logger.html#remove_log_unit-remove-unit-from-self-log_units) | Subroutine | Removes the `unit` number from the `log_units` array ## Specification of the `logger_type` methods ### `add_log_file` - open a file and add its unit to `self % log_units` #### Status Experimental #### Description Opens a formatted, sequential access, output file, `filename` using `newunit` and adds the resulting unit number to the logger's `log_units` array. #### Syntax `call self % ` [[logger_type(type):add_log_file(bound)]] `( filename [, unit, action, position, status, stat ] )` #### Class Subroutine #### Arguments `self`: shall be a scalar variable of type `logger_type`. It is an `intent(inout)` argument. It shall be the logger to add the file to its `log_units`. `filename`: shall be a scalar default character expression. It is an `intent(in)` argument. It shall be the name of the file to be opened. `unit` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. It will be the unit number returned by the `newunit` specifier of the `open` statement for `filename`. `action` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It shall be the `action` specifier of the `open` statement and must have one of the values `'WRITE'` or `'READWRITE'`. It has the default value of `'WRITE'`. `position` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It shall be the `position` specifier of the `open` statement and must have one of the values `'ASIS'`, `'REWIND'`, or `'APPEND'`. It has the default value of `'REWIND'`. `status` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It shall be the `status` specifier of the `open` statement and must have one of the values `'OLD'`, `'NEW'`, `'REPLACE'`, or `'UNKNOWN'`. It has the default value of `'REPLACE'`. `stat` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. If present, on return it will have the value `success` if `filename` could be opened, the value `read_only_error` if the `action` specifier is `"READ"`, or the value `open_failure` if `filename` could not be opened. If absent and `filename` could not be opened then processing will stop with an informative message as the stop code. #### Example ```fortran {!example/logger/example_global_logger.f90!} ``` ### `add_log_unit` - add a unit to the array `self % log_units` #### Status Experimental #### Description Adds `unit` to the array of `self % log_units`. The `unit` shall be the unit number for an opened, sequential, formatted file with an `action` specifier of `'WRITE'` or `'READWRITE'`. Failure of `unit` to meet those requirements will cause `stat`, if present, to not be `success` and `unit` will not be added to `log_units`. In this case, if `stat` is not present, cause processing to stop with an informative string as the stop code. #### Syntax `call self % ` [[logger_type(type):add_log_unit(bound)]] `( unit [, stat ] )` #### Class. Subroutine. #### Arguments `self`: shall be a scalar variable of type `logger_type`. It is an `intent(inout)` argument. It shall be the logger to direct its output to `unit`. `unit`: shall be a scalar default integer expression. It is an `intent(in)` argument. It shall be the unit number for an opened, sequential, formatted file with an action specifier of `'WRITE'` or `'READWRITE'`. `stat` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. If absent and `unit` could not be added to self's `log_units` processing will stop with an informative message as the stop code. If present it shall have the value of one of the module's error codes indicating any errors found with `unit`. The codes are * `success` - no problem found * `non_sequential_error` - `unit` did not have an `access` specifier of `'SEQUENTIAL'` * `read_only_error` - `unit` had an `action` specifier of `'READ'` when it needs a specifier of `'WRITE'` or `'READWRITE'` * `unformatted_in_error` - `unit` did not have a `form` specifier of `'FORMATTED'` * `unopened_in_error` - `unit` was not opened #### Example ```fortran {!example/logger/example_add_log_unit.f90!} ``` ### `configuration` - report a logger's configuration #### Status Experimental #### Description Reports the configuration of a logger. #### Syntax `call self % ` [[logger_type(type):configuration(bound)]] `( [ add_blankline, indent, level, max_width, time_stamp, log_units ] )` #### Class Pure subroutine #### Arguments `self`: shall be a scalar expression of type `logger_type`. It is an `intent(in)` argument. It shall be the logger whose configuration is reported. `add_blank_line` (optional): shall be a scalar default logical variable. It is an `intent(out)` argument. A value of `.true.` starts output with a blank line, and `.false.` otherwise. `indent` (optional): shall be a scalar default logical variable. It is an `intent(out)` argument. A value of `.true.` indents subsequent lines by four spaces, and `.false.` otherwise. `level` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. The value corresponds to the severity level for ignoring a message. `max_width` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. A positive value bigger than four defines the maximum width of the output, otherwise there is no maximum width. `time_stamp` (optional): shall be a scalar default logical variable. It is an `intent(out)` argument. A value of `.true.` precedes output with a time stamp of the form 'yyyy-mm-dd hh:mm:ss.sss', and `.false.` otherwise. `log_units` (optional): shall be a rank one allocatable array variable of type default integer. It is an `intent(out)` argument. On return it shall be the elements of the `self`'s `log_units` array. If there were no elements in `self`'s `log_units`, a zero-sized array is returned. #### Example ```fortran module example_mod use stdlib_logger type(logger_type) :: logger contains subroutine example_sub(unit, ...) integer, intent(in) :: unit integer, allocatable :: log_units(:) call logger % configuration( log_units=log_units ) if ( size(log_units) == 0 ) then call add_logger_unit( unit ) end if end subroutine example_sub end module example_mod ``` ### `configure` - configure the logging process #### Status Experimental #### Description Configures the logging process for self. #### Syntax `call self % ` [[logger_type(type):configure(bound)]] `( [ add_blank_line, indent, level, max_width, time_stamp ] )` #### Class Pure subroutine #### Arguments `self`: shall be a scalar variable of type `logger_type`. It is an `intent(inout)` argument. It shall be the logger to be configured. `add_blank_line` (optional): shall be a scalar default logical expression. It is an `intent(in)` argument. Set to `.true.` to start output with a blank line, and to `.false.` otherwise. `indent` (optional): shall be a scalar default logical expression. It is an `intent(in)` argument. Set to `.true.` to indent subsequent lines by four spaces, and to `.false.` to not indent. `level` (optional): shall be a scalar default integer expression. It is an `intent(in)` argument. Set the severity level for ignoring a log message. `max_width` (optional): shall be a scalar default integer expression. It is an `intent(in)` argument. Set to a positive value bigger than four to define the maximum width of the output, otherwise there is no maximum width. `time_stamp` (optional): shall be a scalar default logical expression. It is an `intent(in)` argument. Set to `.true.` to precede output with a time stamp of the form 'yyyy-mm-dd hh:mm:ss.sss', and to `.false.` otherwise. #### Example ```fortran {!example/logger/example_configure.f90!} ``` ### `log_debug` - Writes the string `message` to `self % log_units` #### Status Experimental #### Description Writes the string `message` to `self % log_units` with optional additional text. #### Syntax `call self % ` [[logger_type(type):log_debug(bound)]] `( message [, module, procedure ] )` #### Behavior If time stamps are active, a time stamp is written, followed by `module` and `procedure` if present, and then `message` is written with the prefix `'DEBUG: '`. It is ignored if the `level` of `self` is higher than `debug_level`. #### Class Subroutine #### Arguments `self`: shall be a scalar variable of type `logger_type`. It is an `intent(in)` argument. It is the logger used to send the message. `message`: shall be a scalar default character expression. It is an `intent(in)` argument. * Note `message` may have embedded new_line calls. `module` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the module containing the `log_information` call. `procedure` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the procedure containing the `log_information` call. #### Example ```fortran module example_mod use stdlib_logger real, allocatable :: a(:) type(logger_type) :: logger contains subroutine example_sub( selection ) integer, intent(out) :: selection character(128) :: errmsg, message integer :: stat write(*,'(a)') "Enter an integer to select a widget" read(*,'(i0)') selection write( message, '(a, i0)' ) & "The user selected ", selection call logger % log_DEBUG( message, & module = 'EXAMPLE_MOD', procedure = 'EXAMPLE_SUB' ) end subroutine example_sub end module example_mod ``` ### `log_error` - Writes the string `message` to `self % log_units` #### Status Experimental #### Description Writes the string `message` to `self % log_units` with optional additional text. #### Syntax `call self % ` [[logger_type(type):log_error(bound)]] `( message [, module, procedure, stat, errmsg ] )` #### Behavior If time stamps are active for `self`, a time stamp is written, followed by `module` and `procedure` if present, then `message` is written with the prefix `'ERROR: '`, and then if `stat` or `errmsg` are present they are written. It is ignored if the `level` of `self` is higher than `error_level`. #### Class Subroutine #### Arguments `self`: shall be a scalar variable of type `logger_type`. It is an `intent(in)` argument. It is the logger used to send the message. `message`: shall be a scalar default character expression. It is an `intent(in)` argument. * Note `message` may have embedded new_line calls. `module` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the module containing the `log_error` call. `procedure` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the procedure containing the `log_error` call. `stat` (optional): shall be a scalar default integer expression. It is an `intent(in)` argument. It should be the `stat` specifier of the subroutine call or intrinsic statement that prompted the `log_error` call. `errmsg` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the `errmsg` specifier of the subroutine call or intrinsic statement that prompted the `log_error` call. #### Example ```fortran module example_mod use stdlib_logger real, allocatable :: a(:) type(logger_type) :: logger contains subroutine example_sub( size) integer, intent(in) :: size character(128) :: errmsg, message integer :: stat allocate( a(size), stat=stat, errmsg=errmsg ) if ( stat /= 0 ) then write( message, '(a, i0)' ) & "Allocation of A failed with SIZE = ", size call logger % log_error( message, & module = 'EXAMPLE_MOD', & procedure = 'EXAMPLE_SUB', & stat = stat, & errmsg = errmsg ) end if end subroutine example_sub end module example_mod ``` ### `log_information` - Writes the string `message` to `self % log_units` #### Status Experimental #### Description Writes the string `message` to `self % log_units` with optional additional text. #### Syntax `call self % ` [[logger_type(type):log_information(bound)]] `( message [, module, procedure ] )` #### Behavior If time stamps are active, a time stamp is written, followed by `module` and `procedure` if present, and then `message` is written with the prefix `'INFO: '`. It is ignored if the `level` of `self` is higher than `information_level`. #### Class Subroutine #### Arguments `self`: shall be a scalar variable of type `logger_type`. It is an `intent(in)` argument. It is the logger used to send the message. `message`: shall be a scalar default character expression. It is an `intent(in)` argument. * Note `message` may have embedded new_line calls. `module` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the module containing the `log_information` call. `procedure` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the procedure containing the `log_information` call. #### Example ```fortran module example_mod use stdlib_logger real, allocatable :: a(:) type(logger_type) :: logger contains subroutine example_sub( selection ) integer, intent(out) :: selection character(128) :: errmsg, message integer :: stat write(*,'(a)') "Enter an integer to select a widget" read(*,'(i0)') selection write( message, '(a, i0)' ) & "The user selected ", selection call logger % log_information( message, & module = 'EXAMPLE_MOD', procedure = 'EXAMPLE_SUB' ) end subroutine example_sub end module example_mod ``` ### `log_io_error` - Write the string `message` to `self % log_units` #### Status Experimental #### Description Writes the string `message` to `self % log_units` with optional additional text. #### Behavior If time stamps are active, a time stamp is written first. Then if `module` or `procedure` are present, they are written. Then `message` is written with the prefix `'I/O ERROR: '`. Then if `iostat` or `iomsg` are present they are written. It is ignored if the `level` of `self` is higher than `io_error_level`. #### Syntax `call self % ` [[logger_type(type):log_io_error(bound)]] `( message [, module, procedure, iostat, iomsg ] )` #### Class Subroutine #### Arguments `self`: shall be a scalar variable of type `logger_type`. It is an `intent(in)` argument. It is the logger used to send the message. `message`: shall be a scalar default character expression. It is an `intent(in)` argument. * Note `message` may have embedded new_line calls. `module` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the module containing the `log_io_error` call. `procedure` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the procedure containing the `log_io_error` call. `iostat` (optional): shall be a scalar default integer expression. It is an `intent(in)` argument. It should be the `iostat` specifier of the subroutine call or intrinsic statement that prompted the `log_io_error` call. `iomsg` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the `iomsg` specifier of the subroutine call or intrinsic statement that prompted the `log_io_error` call. #### Example ```fortran {!example/logger/example_log_io_error.f90!} ``` ### `log_message` - write the string `message` to `self % log_units` #### Status Experimental #### Description Writes the string `message` to `self % log_units` with optional additional text. #### Behavior If time stamps are active, a time stamp is written, then `module` and `procedure` are written if present, followed by `prefix \\ ': '`, if present, and finally `message`. No severity level is applied to `log_message`. #### Syntax `call self % ` [[logger_type(type):log_message(bound)]] `( message [, module, procedure, prefix ] )` #### Class Subroutine #### Arguments `self`: shall be a scalar variable of type `logger_type`. It is an `intent(in)` argument. It is the logger used to send the message. `message`: shall be a scalar default character expression. It is an `intent(in)` argument. * Note `message` may have embedded new_line calls. `module` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the module containing the `log_message` call. `procedure` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the procedure containing the `log_message` call. `prefix` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It will precede `message` with an `': '` appended. #### Example ```fortran module example_mod use stdlib_logger real, allocatable :: a(:) type(logger_type) :: logger contains subroutine example_sub( selection ) integer, intent(out) :: selection integer :: stat write(*,'(a)') "Enter an integer to select a widget" read(*,'(i0)') selection write( message, '(a, i0)' ) & "The user selected ", selection call logger % log_message( message, & module = 'EXAMPLE_MOD', & procedure = 'EXAMPLE_SUB', & prefix = `INFO' ) end subroutine example_sub end module example_mod ``` ### `log_text_error` - send a message to `self % log_units` describing an error #### Status Experimental #### Description `log_text_error` sends a message to `self % log_units` describing an error found in a line of text. #### Behavior If time stamps are active first a time stamp is written. Then if `filename` or `line_number` are present they are written with `column`. Then `line` is written. Then a caret, '^', is written below `line` at the column indicated by `column`. Then `summary` is written below the caret. It is ignored if the `level` of `self` is higher than `text_error_level`. #### Syntax `call self % ` [[logger_type(type):log_text_error(bound)]] `( line, column, summary [, filename, line_number, caret, stat ] )` #### Class Subroutine #### Arguments `self`: shall be a scalar variable of type `logger_type`. It is an `intent(in)` argument. It is the logger used to send the message. `line`: shall be a scalar default character expression. It is an `intent(in)` argument. It should be the line of text in which the error was found. `column`: shall be a scalar default integer expression. It is an `intent(in)` argument. It should be the one's based column at which the error begins. `summary`: shall be a scalar default character expression. It is an `intent(in)` argument. It should be a description of the error in `line`. `filename` (optional): shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the file, if any, in which `line` was found. `line_number` (optional): shall be a scalar default integer expression. It is an `intent(in)` argument. It should be the line number in `filename` associated with `line`. `caret` (optional): shall be a scalar default single character expression. It is an `intent(in)` argument. If present it will be placed below `line` on output to indicate the starting location of the error. It has a default value of '^'. `stat` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. If present it will have the value of `success` if no errors were encountered, the value `index_invalid_error` if `column` is less than one or greater than `len(line)+1`, or the value `write_fault` if the writes to any of `log_units` failed. If `stat` is absent and would not have the value `success` then processing will stop with an informative stop code. #### Example ```fortran {!example/logger/example_log_text_error.f90!} ``` ### `log_units_assigned` - returns the number of active I/O units #### Status Experimental #### Description Returns the number of active I/O units in `self % log_units` #### Syntax `result = self % ` [[logger_type(type):log_units_assigned(bound)]] `()` #### Class Elemental function #### Argument `self`: shall be a scalar expression of type `logger_type`. It is an `intent(in)` argument. It is the logger whose state is queried. #### Result character The result shall be a scalar of type default integer. #### Result value The result is the number of I/O units in `self % log_units`. #### Example ```fortran module example_mod use stdlib_logger type(logger_type) :: logger contains subroutine example_sub(unit, ...) integer, intent(in) :: unit integer, allocatable :: log_units(:) if ( logger % log_units_assigned() == 0 ) then call logger % add_log_unit( unit ) end if end subroutine example_sub end module example_mod ``` ### `log_warning` - write the string `message` to `log_units` #### Status Experimental #### Description Writes the string `message` to `log_units` with optional additional text. #### Behavior If time stamps are active, a time stamp is written, then `module` and `procedure` if present, then `message` is written with the prefix `WARN: '`. #### Syntax `call self % ` [[logger_type(type):log_warning(bound)]] `( message [, module, procedure ] )` #### Class Subroutine #### Arguments `self`: shall be a scalar variable of type `logger_type`. It is an `intent(in)` argument. It is the logger used to send the message. `message`: shall be a scalar default character expression. It is an `intent(in)` argument. * Note `message` may have embedded new_line calls. `module`: (optional) shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the module containing the `log_warning` call. `procedure`: (optional) shall be a scalar default character expression. It is an `intent(in)` argument. It should be the name of the procedure containing the `log_warning` call. #### Example ```fortran module example_mod use stdlib_logger real, allocatable :: a(:) type(logger_type) :: logger contains subroutine example_sub( size, stat ) integer, intent(in) :: size integer, intent(out) :: stat allocate( a(size) ) if ( stat /= 0 ) then write( message, '(a, i0)' ) & "Allocation of A failed with SIZE = ", size call logger % log_warning( message, & module = 'EXAMPLE_MOD', & procedure = 'EXAMPLE_SUB' ) end if end subroutine example_sub end module example_mod ``` ### `remove_log_unit` - remove `unit` from `self % log_units` #### Status Experimental #### Description Remove `unit` from the `self % log_units` list. If `close_unit` is present and `.true.` then the corresponding file is closed. If `unit` is not in `self % log_units` then nothing is done. #### Syntax `call self % ` [[logger_type(type):remove_log_unit(bound)]] `( unit [, close_unit, stat ] )` #### Class Subroutine #### Arguments `self`: shall be a scalar variable of type `logger_type`. It is an `intent(inout)` argument. It is the logger whose `log_units` is to be modified. `unit`: shall be a scalar default integer expression. It is an `intent(in)` argument. It should be one of the I/O `unit` numbers in `self % log_units`. If it is not, then nothing is done. `close_unit` (optional): shall be a scalar default logical expression. It is an `intent(in)` argument. If `.true` and `unit` is in `self % log_units` then `unit` will be closed, otherwise the I/O unit will be unaffected. `stat` (optional): shall be a scalar default integer variable. It is an `intent(out)` argument. If present it has the default value of `success`, but has the value `close_failure` if `close_unit` is present with the value `.true.`, and `unit` is initially in `log_units`, and closing `unit` fails. If `stat` is absent and closing the `unit` fails then processing stops with an informative stop code. #### Example ```fortran module example_mod use stdlib_logger, global => global_logger contains subroutine example_sub(unit, ...) integer, intent(in) :: unit call global % remove_log_unit( unit ) end subroutine example_sub end module example_mod ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_random.md0000664000175000017500000000246115135654166023216 0ustar alastairalastair--- title: random --- # Statistical Distributions -- Pseudorandom Number Generator Module [TOC] ## `random_seed` - set or get a value of seed to the probability distribution pseudorandom number generator ### Status Experimental ### Description Set or get the seed value before calling the probability distribution pseudorandom number generator for variates. ### Syntax `call ` [[stdlib_random(module):random_seed(interface)]] `(put, get)` ### Arguments `put`: argument has `intent(in)` and may be a scalar of type `integer`. `get`: argument has `intent(out)` and is a scalar of type `integer`. ### Return value Return a scalar of type `integer`. ### Example ```fortran {!example/random/example_random_seed.f90!} ``` ## `dist_rand` - Get a random integer with specified kind ### Status Experimental ### Description Generate an integer pseudorandom number in a specific range [-2^k, 2^k - 1] according to the input integer kind n. This pseudorandom number will be operated by bit opeartors instead of normal arithmetic operators. ### Syntax `result = ` [[stdlib_random(module):dist_rand(interface)]] `(n)` ### Arguments `n`: argument has `intent(in)` is a scalar of type `integer`. ### Return value Return a scalar of type `integer`. ### Example ```fortran {!example/random/example_dist_rand.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_stringlist_type.md0000664000175000017500000002120215135654166025173 0ustar alastairalastair--- title: stringlist_type --- # `stdlib_stringlist_type` module (1-D list of strings) [TOC] ## Introduction The `stdlib_stringlist_type` module provides with 2 derived types to deal with lists of strings. `stringlist_type` derived type represents one-dimensional list of variable-length strings (also referred as one-dimensional stringlist) which is compatible with Fortran intrinsic character and `stringlist_index_type` derived type represents an index to access, modify the elements of a stringlist, insert elements to a stringlist and much more. ## Derived types provided ### `stringlist_type` derived type The `stringlist_type` derived type represents one-dimensional list of strings (also referred as one-dimensional stringlist). The internal representation of the list is implementation dependent and is not visible to the user of the module. Note: _stringlist_ is an abstract concept which is expressed through the derived type `stringlist_type`. #### Status Experimental ### `stringlist_index_type` derived type An instance of the derived type `stringlist_index_type` represents either a forward index OR a backward index. The internal representation is implementation dependent and is not visible to the user of the module. `list_head` and `list_tail` are 2 special instances of this type representing the head and the tail of a stringlist respectively. An index is independent of the stringlist(or `stringlist_type`) it is used with and hence, an index can be used with multiple stringlists in the same program. #### Status Experimental ### fidx/bidx #### Description `fidx`: Returns an instance which represents forward index `idx`. `bidx`: Returns an instance which represents backward index `idx`. #### Syntax For fidx: `res = ` [[stdlib_stringlist_type(module):fidx(interface)]] ` (idx)` For bidx: `res = ` [[stdlib_stringlist_type(module):bidx(interface)]] ` (idx)` #### Status Experimental. #### Class Pure function. #### Argument - `idx`: Shall be of kind `integer`. This argument is `intent(in)`. #### Result value The result is of type `stringlist_index_type`. #### Example ```fortran {!example/stringlist_type/example_stringlist_type_fidx_bidx.f90!} ``` ### Constructor for `stringlist_type`(or stringlist) #### Description No arguments given: Initializes an empty stringlist(a stringlist containing no elements in it). With argument: Initializes a stringlist equivalent to the input array `array` i.e. a stringlist containing all elements of the input array `array` in the same order. #### Syntax `res = ` [[stdlib_stringlist_type(module):stringlist_type(interface)]] ` ([array])` #### Status Experimental #### Class Pure function. #### Argument - `array`: Shall be an array of `character` scalar or array of [[stdlib_string_type(module):string_type(type)]]. This argument is `intent(in)` and `optional`. #### Result value The result is an instance of type `stringlist_type`. #### Example ```fortran {!example/stringlist_type/example_stringlist_type_constructor.f90!} ``` ### insert_at #### Description Inserts the string `string` _AT_ the index `idx`, so that the newly added element is present at index `idx` after insertion. Inserting an element _AT_ index beyond `length + 1` inserts the element _AT_ `list_tail`, and likewise inserting _AT_ a non-positive index inserts the element _AT_ `list_head`. #### Syntax `call ` [[stdlib_stringlist_type(module):stringlist_type(type)]] `%` [[stringlist_type(type):insert_at(bound)]] ` (idx, string)` #### Status Experimental. #### Class Pure subroutine. #### Argument - `idx`: [[stdlib_stringlist_type(module):stringlist_index_type(type)]]. This argument is `intent(in)`. - `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is `intent(in)`. #### Example ```fortran {!example/stringlist_type/example_stringlist_type_insert_at.f90!} ``` ### get #### Description Returns the string present currently at the index `idx` in a stringlist. If index `idx` is out of bounds, then an empty string is returned. #### Syntax `res = ` [[stdlib_stringlist_type(module):stringlist_type(type)]] `%` [[stringlist_type(type):get(bound)]] ` (idx)` #### Status Experimental. #### Class Pure function. #### Argument - `idx`: [[stdlib_stringlist_type(module):stringlist_index_type(type)]]. This argument is `intent(in)`. #### Result value The result is a string of type `string_type`. #### Example ```fortran {!example/stringlist_type/example_stringlist_type_get.f90!} ``` ### len #### Description Returns the number of elements present currently in the stringlist. #### Syntax `res = ` [[stdlib_stringlist_type(module):stringlist_type(type)]] `%` [[stringlist_type(type):len(bound)]] ` ()` #### Status Experimental. #### Class Pure function. #### Argument No arguments. #### Result value The result is of type `integer`. #### Example ```fortran {!example/stringlist_type/example_stringlist_type_len.f90!} ``` ### clear #### Description Removes all elements from a stringlist. #### Syntax `call ` [[stdlib_stringlist_type(module):stringlist_type(type)]] `%` [[stringlist_type(type):clear(bound)]] ` ()` #### Status Experimental. #### Class Pure subroutine. #### Argument No arguments. #### Example ```fortran {!example/stringlist_type/example_stringlist_type_clear.f90!} ``` ### Comparison operator equal #### Description Compares left hand side (lhs) with right hand side (rhs) for equality. #### Syntax `res = lhs == rhs` `res = lhs .eq. rhs` #### Status Experimental. #### Class Pure function, `operator(==)` and `operator(.eq.)`. #### Argument - `lhs`: Shall be an array of `character` scalar or of [[stdlib_string_type(module):string_type(type)]] OR a [[stdlib_stringlist_type(module):stringlist_type(type)]]. This argument is `intent(in)`. - `rhs`: Shall be an array of `character` scalar or of [[stdlib_string_type(module):string_type(type)]] OR a [[stdlib_stringlist_type(module):stringlist_type(type)]]. This argument is `intent(in)`. #### Result value The result is a default `logical` scalar value. #### Example ```fortran {!example/stringlist_type/example_stringlist_type_equality_operator.f90!} ``` ### Comparison operator not equal #### Description Compares left hand side (lhs) with right hand side (rhs) for inequality. #### Syntax `res = lhs /= rhs` `res = lhs .ne. rhs` #### Status Experimental. #### Class Pure function, `operator(/=)` and `operator(.ne.)`. #### Argument - `lhs`: Shall be an array of `character` scalar or of [[stdlib_string_type(module):string_type(type)]] OR a [[stdlib_stringlist_type(module):stringlist_type(type)]]. This argument is `intent(in)`. - `rhs`: Shall be an array of `character` scalar or of [[stdlib_string_type(module):string_type(type)]] OR a [[stdlib_stringlist_type(module):stringlist_type(type)]]. This argument is `intent(in)`. #### Result value The result is a default `logical` scalar value. #### Example ```fortran {!example/stringlist_type/example_stringlist_type_inequality_operator.f90!} ``` ### Concatenation operator(//) #### Description Returns the concatenated output of left hand side (lhs) and right hand side (rhs). #### Syntax `res = lhs // rhs` #### Status Experimental. #### Class Pure function, `operator(//)`. #### Argument - `lhs`: Shall be a `character` scalar or [[stdlib_string_type(module):string_type(type)]] OR an array of `character` scalar or of [[stdlib_string_type(module):string_type(type)]] OR a [[stdlib_stringlist_type(module):stringlist_type(type)]]. This argument is `intent(in)`. - `rhs`: Shall be a `character` scalar or [[stdlib_string_type(module):string_type(type)]] OR an array of `character` scalar or of [[stdlib_string_type(module):string_type(type)]] OR a [[stdlib_stringlist_type(module):stringlist_type(type)]]. This argument is `intent(in)`. #### Result value The result is an instance of [[stdlib_stringlist_type(module):stringlist_type(type)]]. #### Example ```fortran {!example/stringlist_type/example_stringlist_type_concatenate_operator.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_sparse.md0000664000175000017500000003130015135654166023225 0ustar alastairalastair--- title: sparse --- # The `stdlib_sparse` module [TOC] ## Introduction The `stdlib_sparse` module provides derived types for standard sparse matrix data structures. It also provides math kernels such as sparse matrix-vector product and conversion between matrix types. ## Sparse matrix derived types ### The `sparse_type` abstract derived type #### Status Experimental #### Description The parent `sparse_type` is as an abstract derived type holding the basic common meta data needed to define a sparse matrix, as well as shared APIs. All sparse matrix flavors are extended from the `sparse_type`. ```Fortran type, public, abstract :: sparse_type integer :: nrows !! number of rows integer :: ncols !! number of columns integer :: nnz !! number of non-zero values integer :: storage !! assumed storage symmetry end type ``` The storage integer label should be assigned from the module's internal enumerator containing the following three enums: ```Fortran enum, bind(C) enumerator :: sparse_full !! Full Sparse matrix (no symmetry considerations) enumerator :: sparse_lower !! Symmetric Sparse matrix with triangular inferior storage enumerator :: sparse_upper !! Symmetric Sparse matrix with triangular supperior storage end enum ``` In the following, all sparse kinds will be presented in two main flavors: a data-less type `_type` useful for topological graph operations. And real/complex valued types `__type` containing the `data` buffer for the matrix values. The following rectangular matrix will be used to showcase how each sparse matrix holds the data internally: $$ M = \begin{bmatrix} 9 & 0 & 0 & 0 & -3 \\ 4 & 7 & 0 & 0 & 0 \\ 0 & 8 & -1 & 8 & 0 \\ 4 & 0 & 5 & 6 & 0 \\ \end{bmatrix} $$ ### `COO`: The COOrdinates compressed sparse format #### Status Experimental #### Description The `COO`, triplet or `ijv` format defines all non-zero elements of the matrix by explicitly allocating the `i,j` index and the value of the matrix. While some implementations use separate `row` and `col` arrays for the index, here we use a 2D array in order to promote fast memory acces to `ij`. ```Fortran type(COO_sp_type) :: COO call COO%malloc(4,5,10) COO%data(:) = real([9,-3,4,7,8,-1,8,4,5,6]) COO%index(1:2,1) = [1,1] COO%index(1:2,2) = [1,5] COO%index(1:2,3) = [2,1] COO%index(1:2,4) = [2,2] COO%index(1:2,5) = [3,2] COO%index(1:2,6) = [3,3] COO%index(1:2,7) = [3,4] COO%index(1:2,8) = [4,1] COO%index(1:2,9) = [4,3] COO%index(1:2,10) = [4,4] ``` ### `CSR`: The Compressed Sparse Row or Yale format #### Status Experimental #### Description The Compressed Sparse Row or Yale format `CSR` stores the matrix structure by compressing the row indices with a counter pointer `rowptr` enabling to know the first and last non-zero column index `col` of the given row. ```Fortran type(CSR_sp_type) :: CSR call CSR%malloc(4,5,10) CSR%data(:) = real([9,-3,4,7,8,-1,8,4,5,6]) CSR%col(:) = [1,5,1,2,2,3,4,1,3,4] CSR%rowptr(:) = [1,3,5,8,11] ``` ### `CSC`: The Compressed Sparse Column format #### Status Experimental #### Description The Compressed Sparse Colum `CSC` is similar to the `CSR` format but values are accesed first by column, thus an index counter is given by `colptr` which enables to know the first and last non-zero row index of a given colum. ```Fortran type(CSC_sp_type) :: CSC call CSC%malloc(4,5,10) CSC%data(:) = real([9,4,4,7,8,-1,5,8,6,-3]) CSC%row(:) = [1,2,4,2,3,3,4,3,4,1] CSC%colptr(:) = [1,4,6,8,10,11] ``` ### `ELLPACK`: ELL-pack storage format #### Status Experimental #### Description The `ELL` format stores data in a dense matrix of $nrows \times K$ in column major order. By imposing a constant number of elements per row $K$, this format will incur in additional zeros being stored, but it enables efficient vectorization as memory acces is carried out by constant sized strides. ```Fortran type(ELL_sp_type) :: ELL call ELL%malloc(num_rows=4,num_cols=5,num_nz_row=3) ELL%data(1,1:3) = real([9,-3,0]) ELL%data(2,1:3) = real([4,7,0]) ELL%data(3,1:3) = real([8,-1,8]) ELL%data(4,1:3) = real([4,5,6]) ELL%index(1,1:3) = [1,5,0] ELL%index(2,1:3) = [1,2,0] ELL%index(3,1:3) = [2,3,4] ELL%index(4,1:3) = [1,3,4] ``` ### `SELL-C`: The Sliced ELLPACK with Constant blocks format #### Status Experimental #### Description The Sliced ELLPACK format `SELLC` is a variation of the `ELLPACK` format. This modification reduces the storage size compared to the `ELLPACK` format but maintaining its efficient data access scheme. It can be seen as an intermediate format between `CSR` and `ELLPACK`. For more details read [the reference](https://arxiv.org/pdf/1307.6209v1) ## `add`- sparse matrix data accessors ### Status Experimental ### Description Type-bound procedures to enable adding data in a sparse matrix. ### Syntax `call matrix%add(i,j,v)` or `call matrix%add(i(:),j(:),v(:,:))` ### Arguments `i`: Shall be an integer value or rank-1 array. It is an `intent(in)` argument. `j`: Shall be an integer value or rank-1 array. It is an `intent(in)` argument. `v`: Shall be a `real` or `complex` value or rank-2 array. The type shall be in accordance to the declared sparse matrix object. It is an `intent(in)` argument. ## `at`- sparse matrix data accessors ### Status Experimental ### Description Type-bound procedures to enable requesting data from a sparse matrix. ### Syntax `v = matrix%at(i,j)` ### Arguments `i` : Shall be an integer value. It is an `intent(in)` argument. `j` : Shall be an integer value. It is an `intent(in)` argument. `v` : Shall be a `real` or `complex` value in accordance to the declared sparse matrix object. If the `ij` tuple is within the sparse pattern, `v` contains the value in the data buffer. If the `ij` tuple is outside the sparse pattern, `v` is equal `0`. If the `ij` tuple is outside the matrix pattern `(nrows,ncols)`, `v` is `NaN`. ### Example ```fortran {!example/linalg/example_sparse_data_accessors.f90!} ``` ## `spmv` - Sparse Matrix-Vector product ### Status Experimental ### Description Provide sparse matrix-vector product kernels for the current supported sparse matrix types. $$y=\alpha*op(M)*x+\beta*y$$ ### Syntax `call ` [[stdlib_sparse_spmv(module):spmv(interface)]] `(matrix,vec_x,vec_y [,alpha,beta,op])` ### Arguments `matrix`: Shall be a `real` or `complex` sparse type matrix. It is an `intent(in)` argument. `vec_x`: Shall be a rank-1 or rank-2 array of `real` or `complex` type array. It is an `intent(in)` argument. `vec_y`: Shall be a rank-1 or rank-2 array of `real` or `complex` type array. . It is an `intent(inout)` argument. `alpha`, `optional` : Shall be a scalar value of the same type as `vec_x`. Default value `alpha=1`. It is an `intent(in)` argument. `beta`, `optional` : Shall be a scalar value of the same type as `vec_x`. Default value `beta=0`. It is an `intent(in)` argument. `op`, `optional`: In-place operator identifier. Shall be a `character(1)` argument. It can have any of the following values: `N`: no transpose, `T`: transpose, `H`: hermitian or complex transpose. These values are provided as constants by the `stdlib_sparse` module: `sparse_op_none`, `sparse_op_transpose`, `sparse_op_hermitian` ## Sparse matrix to matrix conversions ### Status Experimental ### Description This module provides facility functions for converting between storage formats. ### Syntax `call ` [[stdlib_sparse_conversion(module):coo2ordered(interface)]] `(coo[,sort_data])` ### Arguments `COO` : Shall be any `COO` type. The same object will be returned with the arrays reallocated to the correct size after removing duplicates. It is an `intent(inout)` argument. `sort_data`, `optional` : Shall be a `logical` argument to determine whether data in the COO graph should be sorted while sorting the index array, default `.false.`. It is an `intent(in)` argument. ### Syntax `call ` [[stdlib_sparse_conversion(module):from_ijv(interface)]] `(sparse,row,col[,data,nrows,ncols,num_nz_rows,chunk])` ### Arguments `sparse` : Shall be a `COO`, `CSR`, `ELL` or `SELLC` type. The graph object will be returned with a canonical shape after sorting and removing duplicates from the `(row,col,data)` triplet. If the graph is `COO_type` no data buffer is allowed. It is an `intent(inout)` argument. `row` : rows index array. It is an `intent(in)` argument. `col` : columns index array. It is an `intent(in)` argument. `data`, `optional`: `real` or `complex` data array. It is an `intent(in)` argument. `nrows`, `optional`: number of rows, if not given it will be computed from the `row` array. It is an `intent(in)` argument. `ncols`, `optional`: number of columns, if not given it will be computed from the `col` array. It is an `intent(in)` argument. `num_nz_rows`, `optional`: number of non zeros per row, only valid in the case of an `ELL` matrix, by default it will computed from the largest row. It is an `intent(in)` argument. `chunk`, `optional`: chunk size, only valid in the case of a `SELLC` matrix, by default it will be taken from the `SELLC` default attribute chunk size. It is an `intent(in)` argument. ### Example ```fortran {!example/linalg/example_sparse_from_ijv.f90!} ``` ### Syntax `call ` [[stdlib_sparse_conversion(module):diag(interface)]] `(matrix,diagonal)` ### Arguments `matrix` : Shall be a `dense`, `COO`, `CSR` or `ELL` type. It is an `intent(in)` argument. `diagonal` : A rank-1 array of the same type as the `matrix`. It is an `intent(inout)` and `allocatable` argument. #### Note If the `diagonal` array has not been previously allocated, the `diag` subroutine will allocate it using the `nrows` of the `matrix`. ### Syntax `call ` [[stdlib_sparse_conversion(module):dense2coo(interface)]] `(dense,coo)` ### Arguments `dense` : Shall be a rank-2 array of `real` or `complex` type. It is an `intent(in)` argument. `coo` : Shall be a `COO` type of `real` or `complex` type. It is an `intent(out)` argument. ### Syntax `call ` [[stdlib_sparse_conversion(module):coo2dense(interface)]] `(coo,dense)` ### Arguments `coo` : Shall be a `COO` type of `real` or `complex` type. It is an `intent(in)` argument. `dense` : Shall be a rank-2 array of `real` or `complex` type. It is an `intent(out)` argument. ### Syntax `call ` [[stdlib_sparse_conversion(module):coo2csr(interface)]] `(coo,csr)` ### Arguments `coo` : Shall be a `COO` type of `real` or `complex` type. It is an `intent(in)` argument. `csr` : Shall be a `CSR` type of `real` or `complex` type. It is an `intent(out)` argument. ### Syntax `call ` [[stdlib_sparse_conversion(module):coo2csc(interface)]] `(coo,csc)` ### Arguments `coo` : Shall be a `COO` type of `real` or `complex` type. It is an `intent(in)` argument. `csc` : Shall be a `CSC` type of `real` or `complex` type. It is an `intent(out)` argument. ### Syntax `call ` [[stdlib_sparse_conversion(module):csr2coo(interface)]] `(csr,coo)` ### Arguments `csr` : Shall be a `CSR` type of `real` or `complex` type. It is an `intent(in)` argument. `coo` : Shall be a `COO` type of `real` or `complex` type. It is an `intent(out)` argument. ### Syntax `call ` [[stdlib_sparse_conversion(module):csr2sellc(interface)]] `(csr,sellc[,chunk])` ### Arguments `csr` : Shall be a `CSR` type of `real` or `complex` type. It is an `intent(in)` argument. `sellc` : Shall be a `SELLC` type of `real` or `complex` type. It is an `intent(out)` argument. `chunk`, `optional`: chunk size for the Sliced ELLPACK format. It is an `intent(in)` argument. ### Syntax `call ` [[stdlib_sparse_conversion(module):csr2sellc(interface)]] `(csr,ell[,num_nz_rows])` ### Arguments `csr` : Shall be a `CSR` type of `real` or `complex` type. It is an `intent(in)` argument. `ell` : Shall be a `ELL` type of `real` or `complex` type. It is an `intent(out)` argument. `num_nz_rows`, `optional`: number of non zeros per row. If not give, it will correspond to the size of the longest row in the `CSR` matrix. It is an `intent(in)` argument. ### Syntax `call ` [[stdlib_sparse_conversion(module):csc2coo(interface)]] `(csc,coo)` ### Arguments `csc` : Shall be a `CSC` type of `real` or `complex` type. It is an `intent(in)` argument. `coo` : Shall be a `COO` type of `real` or `complex` type. It is an `intent(out)` argument. ### Example ```fortran {!example/linalg/example_sparse_spmv.f90!} ```fortran-lang-stdlib-0ede301/doc/specs/stdlib_error_state_type.md0000664000175000017500000000551115135654166025327 0ustar alastairalastair--- title: state_type --- # State and Error Handling Derived Type [TOC] ## Introduction The `stdlib_error` module provides a derived type holding information on the state of operations within the standard library and procedures for expert control of workflows. An optional `state_type` variable to hold such information is provided as a form of expert API. If the user does not require state information but fatal errors are encountered during execution, the program will undergo a hard stop. Instead, if the state argument is present, the program will never stop but will return detailed error information into the state handler. ## Derived types provided ### The `state_type` derived type The `state_type` is defined as a derived type containing an integer error flag and fixed-size character strings to store an error message and the location of the error state change. Fixed-size string storage was chosen to facilitate the compiler's memory allocation and ultimately ensure maximum computational performance. A similarly named generic interface, `state_type`, is provided to allow the developer to create diagnostic messages and raise error flags easily. The call starts with an error flag or the location of the event and is followed by an arbitrary list of `integer`, `real`, `complex`, or `character` variables. Numeric variables may be provided as either scalars or rank-1 (array) inputs. #### Type-bound procedures The following convenience type-bound procedures are provided: - `print()` returns an allocatable character string containing state location, message, and error flag; - `print_message()` returns an allocatable character string containing the state message; - `ok()` returns a `logical` flag that is `.true.` in case of successful state (`flag==STDLIB_SUCCESS`); - `error()` returns a `logical` flag that is `.true.` in case of an error state (`flag/=STDLIB_SUCCESS`). #### Status Experimental #### Example ```fortran {!example/error/example_error_state1.f90!} ``` ## Error flags provided The module provides the following state flags: - `STDLIB_SUCCESS`: Successful execution - `STDLIB_VALUE_ERROR`: Numerical errors (such as infinity, not-a-number, range bounds) are encountered. - `STDLIB_LINALG_ERROR`: Linear Algebra errors are encountered, such as non-converging iterations, impossible operations, etc. - `STDLIB_INTERNAL_ERROR`: Provided as a developer safeguard for internal errors that should never occur. - `STDLIB_IO_ERROR`: Input/Output-related errors, such as file reading/writing failures. - `STDLIB_FS_ERROR`: File system-related errors, such as directory access issues. ## Comparison operators provided The module provides overloaded comparison operators for all comparisons of a `state_type` variable with an integer error flag: `<`, `<=`, `==`, `>=`, `>`, `/=`. fortran-lang-stdlib-0ede301/doc/specs/stdlib_quadrature.md0000664000175000017500000001614215135654166024114 0ustar alastairalastair--- title: quadrature --- # Numerical integration [TOC] ## `trapz` - integrate sampled values using trapezoidal rule ### Status Experimental ### Description Returns the trapezoidal rule integral of an array `y` representing discrete samples of a function. The integral is computed assuming either equidistant abscissas with spacing `dx` or arbitrary abscissas `x`. ### Syntax `result = ` [[stdlib_quadrature(module):trapz(interface)]] `(y, x)` `result = ` [[stdlib_quadrature(module):trapz(interface)]] `(y, dx)` ### Arguments `y`: Shall be a rank-one array of type `real`. `x`: Shall be a rank-one array of type `real` having the same kind and size as `y`. `dx`: Shall be a scalar of type `real` having the same kind as `y`. ### Return value The result is a scalar of type `real` having the same kind as `y`. If the size of `y` is zero or one, the result is zero. ### Example ```fortran {!example/quadrature/example_trapz.f90!} ``` ## `trapz_weights` - trapezoidal rule weights for given abscissas ### Status Experimental ### Description Given an array of abscissas `x`, computes the array of weights `w` such that if `y` represented function values tabulated at `x`, then `sum(w*y)` produces a trapezoidal rule approximation to the integral. ### Syntax `result = ` [[stdlib_quadrature(module):trapz_weights(interface)]] `(x)` ### Arguments `x`: Shall be a rank-one array of type `real`. ### Return value The result is a `real` array with the same size and kind as `x`. If the size of `x` is one, then the sole element of the result is zero. ### Example ```fortran {!example/quadrature/example_trapz_weights.f90!} ``` ## `simps` - integrate sampled values using Simpson's rule ### Status Experimental ### Description Returns the Simpson's rule integral of an array `y` representing discrete samples of a function. The integral is computed assuming either equidistant abscissas with spacing `dx` or arbitrary abscissas `x`. Simpson's ordinary ("1/3") rule is used for odd-length arrays. For even-length arrays, Simpson's 3/8 rule is also utilized in a way that depends on the value of `even`. If `even` is negative (positive), the 3/8 rule is used at the beginning (end) of the array. If `even` is zero or not present, the result is as if the 3/8 rule were first used at the beginning of the array, then at the end of the array, and these two results were averaged. ### Syntax `result = ` [[stdlib_quadrature(module):simps(interface)]] `(y, x [, even])` `result = ` [[stdlib_quadrature(module):simps(interface)]] `(y, dx [, even])` ### Arguments `y`: Shall be a rank-one array of type `real`. `x`: Shall be a rank-one array of type `real` having the same kind and size as `y`. `dx`: Shall be a scalar of type `real` having the same kind as `y`. `even`: (Optional) Shall be a default-kind `integer`. ### Return value The result is a scalar of type `real` having the same kind as `y`. If the size of `y` is zero or one, the result is zero. If the size of `y` is two, the result is the same as if `trapz` had been called instead. ### Example ```fortran {!example/quadrature/example_simps.f90!} ``` ## `simps_weights` - Simpson's rule weights for given abscissas ### Status Experimental ### Description Given an array of abscissas `x`, computes the array of weights `w` such that if `y` represented function values tabulated at `x`, then `sum(w*y)` produces a Simpson's rule approximation to the integral. Simpson's ordinary ("1/3") rule is used for odd-length arrays. For even-length arrays, Simpson's 3/8 rule is also utilized in a way that depends on the value of `even`. If `even` is negative (positive), the 3/8 rule is used at the beginning (end) of the array and the 1/3 rule used elsewhere. If `even` is zero or not present, the result is as if the 3/8 rule were first used at the beginning of the array, then at the end of the array, and then these two results were averaged. ### Syntax `result = ` [[stdlib_quadrature(module):simps_weights(interface)]] `(x [, even])` ### Arguments `x`: Shall be a rank-one array of type `real`. `even`: (Optional) Shall be a default-kind `integer`. ### Return value The result is a `real` array with the same size and kind as `x`. If the size of `x` is one, then the sole element of the result is zero. If the size of `x` is two, then the result is the same as if `trapz_weights` had been called instead. ### Example ```fortran {!example/quadrature/example_simps_weights.f90!} ``` ## `gauss_legendre` - Gauss-Legendre quadrature (a.k.a. Gaussian quadrature) nodes and weights ### Status Experimental ### Description Computes Gauss-Legendre quadrature (also known as simply Gaussian quadrature) nodes and weights, for any `N` (number of nodes). Using the nodes `x` and weights `w`, you can compute the integral of some function `f` as follows: `integral = sum(f(x) * w)`. Only double precision is supported - if lower precision is required, you must do the appropriate conversion yourself. Accuracy has been validated up to N=64 by comparing computed results to tablulated values known to be accurate to machine precision (maximum difference from those values is 2 epsilon). ### Syntax `subroutine ` [[stdlib_quadrature(module):gauss_legendre(interface)]] ` (x, w[, interval])` ### Arguments `x`: Shall be a rank-one array of type `real(real64)`. It is an *output* argument, representing the quadrature nodes. `w`: Shall be a rank-one array of type `real(real64)`, with the same dimension as `x`. It is an *output* argument, representing the quadrature weights. `interval`: (Optional) Shall be a two-element array of type `real(real64)`. If present, the nodes and weigts are calculated for integration from `interval(1)` to `interval(2)`. If not specified, the default integral is -1 to 1. ### Example ```fortran {!example/quadrature/example_gauss_legendre.f90!} ``` ## `gauss_legendre_lobatto` - Gauss-Legendre-Lobatto quadrature nodes and weights ### Status Experimental ### Description Computes Gauss-Legendre-Lobatto quadrature nodes and weights, for any `N` (number of nodes). Using the nodes `x` and weights `w`, you can compute the integral of some function `f` as follows: `integral = sum(f(x) * w)`. Only double precision is supported - if lower precision is required, you must do the appropriate conversion yourself. Accuracy has been validated up to N=64 by comparing computed results to tablulated values known to be accurate to machine precision (maximum difference from those values is 2 epsilon). ### Syntax `subroutine ` [[stdlib_quadrature(module):gauss_legendre_lobatto(interface)]] ` (x, w[, interval])` ### Arguments `x`: Shall be a rank-one array of type `real(real64)`. It is an *output* argument, representing the quadrature nodes. `w`: Shall be a rank-one array of type `real(real64)`, with the same dimension as `x`. It is an *output* argument, representing the quadrature weights. `interval`: (Optional) Shall be a two-element array of type `real(real64)`. If present, the nodes and weigts are calculated for integration from `interval(1)` to `interval(2)`. If not specified, the default integral is -1 to 1. ### Example ```fortran {!example/quadrature/example_gauss_legendre_lobatto.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_stats_distribution_exponential.md0000664000175000017500000001633515135654166030306 0ustar alastairalastair--- title: stats_distribution_exponential --- # Statistical Distributions -- Exponential Distribution Module [TOC] ## `rvs_exp` - exponential distribution random variates ### Status Experimental ### Description An exponential distribution is the distribution of time between events in a Poisson point process. The inverse `scale` parameter `lambda` specifies the average time between events (\(\lambda\)), also called the rate of events. The location `loc` specifies the value by which the distribution is shifted. Without argument, the function returns a random sample from the unshifted standard exponential distribution \(E(\lambda=1)\) or \(E(loc=0, scale=1)\). With a single argument of type `real`, the function returns a random sample from the exponential distribution \(E(\lambda=\text{lambda})\). For complex arguments, the real and imaginary parts are sampled independently of each other. With one argument of type `real` and one argument of type `integer`, the function returns a rank-1 array of exponentially distributed random variates for (E(\lambda=\text{lambda})\). With two arguments of type `real`, the function returns a random sample from the exponential distribution \(E(loc=loc, scale=scale)\). For complex arguments, the real and imaginary parts are sampled independently of each other. With two arguments of type `real` and one argument of type `integer`, the function returns a rank-1 array of exponentially distributed random variates for \(E(loc=loc, scale=scale)\). @note The algorithm used for generating exponential random variates is fundamentally limited to double precision.[^1] ### Syntax `result = ` [[stdlib_stats_distribution_exponential(module):rvs_exp(interface)]] `([loc, scale] [[, array_size]])` or `result = ` [[stdlib_stats_distribution_exponential(module):rvs_exp(interface)]] `([lambda] [[, array_size]])` ### Class Elemental function ### Arguments `lambda`: optional argument has `intent(in)` and is a scalar of type `real` or `complex`. If `lambda` is `real`, its value must be positive. If `lambda` is `complex`, both the real and imaginary components must be positive. `loc`: optional argument has `intent(in)` and is a scalar of type `real` or `complex`. `scale`: optional argument has `intent(in)` and is a positive scalar of type `real` or `complex`. If `scale` is `real`, its value must be positive. If `scale` is `complex`, both the real and imaginary components must be positive. `array_size`: optional argument has `intent(in)` and is a scalar of type `integer` with default kind. ### Return value If `lambda` is passed, the result is a scalar or rank-1 array with a size of `array_size`, and the same type as `lambda`. If `lambda` is non-positive, the result is `NaN`. If `loc` and `scale` are passed, the result is a scalar or rank-1 array with a size of `array_size`, and the same type as `scale`. If `scale` is non-positive, the result is `NaN`. ### Example ```fortran {!example/stats_distribution_exponential/example_exponential_rvs.f90!} ``` ## `pdf_exp` - exponential distribution probability density function ### Status Experimental ### Description The probability density function (pdf) of the single real variable exponential distribution is: $$f(x)=\begin{cases} \lambda e^{-\lambda x} &x\geqslant 0 \\\\ 0 &x< 0\end{cases}$$ For a complex variable \(z=(x + y i)\) with independent real \(x\) and imaginary \(y\) parts, the joint probability density function is the product of the corresponding real and imaginary marginal pdfs:[^2] $$f(x+\mathit{i}y)=f(x)f(y)=\begin{cases} \lambda_{x} \lambda_{y} e^{-(\lambda_{x} x + \lambda_{y} y)} &x\geqslant 0, y\geqslant 0 \\\\ 0 &\text{otherwise}\end{cases}$$ Instead of of the inverse scale parameter `lambda`, it is possible to pass `loc` and `scale`, where \(scale = \frac{1}{\lambda}\) and `loc` specifies the value by which the distribution is shifted. ### Syntax `result = ` [[stdlib_stats_distribution_exponential(module):pdf_exp(interface)]] `(x, loc, scale)` or `result = ` [[stdlib_stats_distribution_exponential(module):pdf_exp(interface)]] `(x, lambda)` ### Class Elemental function ### Arguments `x`: has `intent(in)` and is a scalar of type `real` or `complex`. `lambda`: has `intent(in)` and is a scalar of type `real` or `complex`. If `lambda` is `real`, its value must be positive. If `lambda` is `complex`, both the real and imaginary components must be positive. `loc`: has `intent(in)` and is a scalar of type `real` or `complex`. `scale`: has `intent(in)` and is a positive scalar of type `real` or `complex`. If `scale` is `real`, its value must be positive. If `scale` is `complex`, both the real and imaginary components must be positive. All arguments must have the same type. ### Return value The result is a scalar or an array, with a shape conformable to the arguments, and the same type as the input arguments. If non-positive `lambda` or `scale`, the result is `NaN`. ### Example ```fortran {!example/stats_distribution_exponential/example_exponential_pdf.f90!} ``` ## `cdf_exp` - exponential cumulative distribution function ### Status Experimental ### Description Cumulative distribution function (cdf) of the single real variable exponential distribution: $$F(x)=\begin{cases}1 - e^{-\lambda x} &x\geqslant 0 \\\\ 0 &x< 0\end{cases}$$ For a complex variable \(z=(x + y i)\) with independent real \(x\) and imaginary \(y\) parts, the joint cumulative distribution function is the product of corresponding real and imaginary marginal cdfs:[^2] $$F(x+\mathit{i}y)=F(x)F(y)=\begin{cases} (1 - e^{-\lambda_{x} x})(1 - e^{-\lambda_{y} y}) &x\geqslant 0, \;\; y\geqslant 0 \\\\ 0 & \text{otherwise} \end{cases}$$ Alternative to the inverse scale parameter `lambda`, it is possible to pass `loc` and `scale`, where \(scale = \frac{1}{\lambda}\) and `loc` specifies the value by which the distribution is shifted. ### Syntax `result = ` [[stdlib_stats_distribution_exponential(module):cdf_exp(interface)]] `(x, loc, scale)` or `result = ` [[stdlib_stats_distribution_exponential(module):cdf_exp(interface)]] `(x, lambda)` ### Class Elemental function ### Arguments `x`: has `intent(in)` and is a scalar of type `real` or `complex`. `lambda`: has `intent(in)` and is a scalar of type `real` or `complex`. If `lambda` is `real`, its value must be positive. If `lambda` is `complex`, both the real and imaginary components must be positive. `loc`: has `intent(in)` and is a scalar of type `real` or `complex`. `scale`: has `intent(in)` and is a positive scalar of type `real` or `complex`. If `scale` is `real`, its value must be positive. If `scale` is `complex`, both the real and imaginary components must be positive. All arguments must have the same type. ### Return value The result is a scalar or an array, with a shape conformable to the arguments, and the same type as the input arguments. With non-positive `lambda` or `scale`, the result is `NaN`. ### Example ```fortran {!example/stats_distribution_exponential/example_exponential_cdf.f90!} ``` [^1]: Marsaglia, George, and Wai Wan Tsang. "The ziggurat method for generating random variables." _Journal of statistical software_ 5 (2000): 1-7. [^2]: Miller, Scott, and Donald Childers. _Probability and random processes: With applications to signal processing and communications_. Academic Press, 2012 (p. 197). fortran-lang-stdlib-0ede301/doc/specs/stdlib_kinds.md0000664000175000017500000000263415135654166023050 0ustar alastairalastair--- title: kinds --- # The `stdlib_kinds` module [TOC] ## Introduction The `stdlib_kinds` module provides kind parameters for the Fortran intrinsic data types, *integer*, *logical*, *real*, and *complex*. ## Constants provided by `stdlib_kinds` ### `sp` Single precision real kind parameter. Provides real kind parameter for floating point numbers with a minimal precision of 6 significant digits. ### `dp` Double precision real kind parameter. Provides real kind parameter for floating point numbers with a minimal precision of 15 significant digits. ### `xdp` Extended double precision real kind parameter. Provides real kind parameter for floating point numbers with a minimal precision of 18 significant digits. If not available it has value `-1`. ### `qp` Quadruple precision real kind parameter. Provides real kind parameter for floating point numbers with a minimal precision of 33 significant digits. If not available it has value `-1`. ### `int8` Reexported intrinsic named constant `int8` from `iso_fortran_env`. ### `int16` Reexported intrinsic named constant `int16` from `iso_fortran_env`. ### `int32` Reexported intrinsic named constant `int32` from `iso_fortran_env`. ### `int64` Reexported intrinsic named constant `int64` from `iso_fortran_env`. ### `lk` Kind parameter of the default logical data type. ### `c_bool` Reexported intrinsic named constant `c_bool` from `iso_c_binding`. fortran-lang-stdlib-0ede301/doc/specs/stdlib_optval.md0000664000175000017500000000147415135654166023246 0ustar alastairalastair--- title: optval --- # Default values for optional arguments [TOC] ## `optval` - fallback value for optional arguments ### Status Experimental ### Description Returns `x` if it is present, otherwise `default`. This function is intended to be called in a procedure with one or more `optional` arguments, in order to conveniently fall back to a default value if an `optional` argument is not present. ### Syntax `result = ` [[stdlib_optval(module):optval(interface)]] `(x, default)` ### Arguments `x`: Shall be of type `integer`, `real`, `complex`, or `logical`, or a scalar of type `character`. `default`: Shall have the same type, kind, and rank as `x`. ### Return value If `x` is present, the result is `x`, otherwise the result is `default`. ### Example ```fortran {!example/optval/example_optval.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_specialfunctions.md0000664000175000017500000000247115135654166025310 0ustar alastairalastair--- title: specialfunctions --- # Special functions [TOC] ## `legendre` - Calculate Legendre polynomials ### Status Experimental ### Description Computes the value of the n-th Legendre polynomial at a specified point. Currently only 64 bit floating point is supported. This is an `elemental` function. ### Syntax `result = ` [[stdlib_specialfunctions(module):legendre(interface)]] ` (n, x)` ### Arguments `n`: Shall be a scalar of type `real(real64)`. `x`: Shall be a scalar or array (this function is elemental) of type `real(real64)`. ### Return value The function result will be the value of the `n`-th Legendre polynomial, evaluated at `x`. ## `dlegendre` - Calculate first derivatives of Legendre polynomials ### Status Experimental ### Description Computes the value of the first derivative of the n-th Legendre polynomial at a specified point. Currently only 64 bit floating point is supported. This is an `elemental` function. ### Syntax `result = ` [[stdlib_specialfunctions(module):dlegendre(interface)]] ` (n, x)` ### Arguments `n`: Shall be a scalar of type `real(real64)`. `x`: Shall be a scalar or array (this function is elemental) of type `real(real64)`. ### Return value The function result will be the value of the first derivative of the `n`-th Legendre polynomial, evaluated at `x`. fortran-lang-stdlib-0ede301/doc/specs/stdlib_hashmaps.md0000664000175000017500000014145615135654166023552 0ustar alastairalastair--- title: Hash maps --- # The `stdlib_hashmap_wrappers`, and `stdlib_hashmaps` modules [TOC] ## Overview of hash maps A hash map (hash table) is a data structure that maps *keys* to *values*. It uses a hash function to compute a hash code from the *key* that serves as an index into a linear array of *slots* (buckets) from which the desired *value* can be extracted. Each key ideally maps to a unique slot, but most hash functions are imperfect and can map multiple keys to the same *slot* resulting in collisions. Hash maps differ in how they deal with such collisions. This document discusses the hash maps in the Fortran Standard Library. ## Licensing The Fortran Standard Library is distributed under the MIT License. However components of the library should be evaluated as to whether they are compatible with the MIT License. The current hash maps were inspired by an [implementation](http://chasewoerner.org/src/hasht/) of David Chase. While the code has been greatly modified from his implementation, he has give permission for the unrestricted use of his code. ## The hash map modules The Fortran Standard Library provides two modules for the implementation of simple hash maps. These maps only accept hash functions with a single argument, the key, and yield a 32 bit hash code. The modules will need to be modified if it is desired to use hash functions with a different API. The two modules are: `stdlib_hashmap_wrappers`, and `stdlib_hashmaps` corresponding to the files: `stdlib_hashmap_wrappers.f90`, and `stdlib_hashmaps.f90` The module `stdlib_hashmap_wrappers` provides types and procedures for use by `stdlib_hashmaps`. It provides an interface to the 32 bit hash functions of the Standard Library module, `stdlib_hash_32bit`, and provides wrappers to some of the hash functions so that they no longer need to be supplied seeds. It also defines the `key_type` derived type. The `key_type` is used to define keys that, in turn, are used to identify the data entered into a hash map. The module `stdlib_hashmaps` defines the API for a parent datatype, `hashmap_type` and two extensions of that hash map type: `chaining_hashmap_type` and `open_hashmap_type`. The `hashmap_type` defines the Application Programmers Interface (API) for the procedures used by its two extensions. It explicitly defines five non-overridable procedures. It also defines the interfaces for eleven deferred procedures. It does not define the finalization routines for the two extension types, or one routine provided by the `open_hashmap_type`. The `chaining_hashmap_type` uses separate chaining with linked lists to deal with hash index collisions. In separate chaining the colliding indices are handled by using linked lists with their roots at the hash index. The `chaining_hashmap_type` procedures are implemented in the module `stdlib_hashmap_chaining` corresponding to the file, `stdlib_hashmap_chaining.f90`. The `open_hashmap_type` uses linear open addressing to deal with hash index collisions. In linear open addressing the colliding indices are handled by searching from the initial hash index in increasing steps of one (modulo the hash map size) for an open map slot. The `open_hashmap_type` procedures are implemented in the submodule `stdlib_hashmap_open` corresponding to the file `stdlib_hashmap_open.f90`. The maps use powers of two for their slot sizes, so that the function, `fibonacci_hash`, can be used to map the hash codes to indices in the map. This is expected to be more efficient than prime number mapping using a modulo operation, and reduces the requirement that the hash function need to do a good job randomizing its lower order bits. They do require a good randomizing hash method for good performance. Both adjust the map size to reduce collisions, based on the ratio of the number of hash map probes to the number of subroutine calls. Wile the maps make extensive use of pointers internally, a private finalization subroutine avoids memory leaks. The maps can take entry keys of type `key_type`, and other data (also commonly known as values, as in key value pairs) in any scalar type. The maps allow the addition, removal, and lookup of entries, and the inclusion of data in addition to the entry key. ## The `stdlib_hashmap_wrappers` module The `stdlib_hashmap_wrappers` module provides data types to represent keys and associated data stored in a module, but is also, a wrapper for the `stdlib_hash_32bit` module. It allows direct access to the `stdlib_hash_32bit` procedures: `fibonacci_hash`, `fnv_1_hasher`, `fnv_1a_hasher`; and provides wrapper functions, `seeded_nmhash32_hasher`, `seeded_nmhash32x_hasher`, and `seeded_water_hasher` to the hash functions: `nmhash32`, `nmhash32x`, and `water_hash`, respectively. It defines an interface, `hasher_fun`, compatible with the hash functions that take a `non-scalar key`. It defines one integer constant used as a kind value,`int_hash`. It also defines two types, `key_type` and `other_type`, and associated procedures, for storing and manipulating keys and their associated data. ### The `stdlib_hashmap_wrappers`'s constant, `int_hash` The constant `int_hash` is used to define the integer kind value for the returned hash codes and variables used to access them. It currently is imported from `stdlib_hash_32bit` where it has the value, `int32`. ### The `stdlib_hashmap_wrappers`' module's derived types The `stdlib_hashmap_wrappers` defines `key_type` which is intended to be used for the search keys of hash tables. The tye is opaque. The current representation is as follows ```fortran type :: key_type private integer(int8), allocatable :: value(:) end type key_type ``` The module also defines six procedures for those types: `copy_key`, `equal_keys`, `free_key`, `get`, `set`, and one operator, `==`, for use by the hash maps to manipulate or inquire of components of those types. ### Table of `stdlib_hashmap_wrappers` procedures The `stdlib_hashmap_wrappers` module provides procedures in several categories: procedures to manipulate data of the `key_type`; and 32 bit hash functions for keys. The procedures in each category are listed below. It also provides an operator to compare two key type values for equality. Procedures to manipulate `key_type` data: * `copy_key( key_in, key_out )` - Copies the contents of the key, `key_in`, to contents of the key, `key_out`. * `get( key, value )` - extracts the contents of `key` into `value`, an `int8` array, `int32` array, or character string. * `free_key( key )` - frees the memory in `key`. * `set( key, value )` - sets the content of `key` to `value`. Supported key types are `int8` array, `int32` array, and character string. Procedures to hash keys to 32 bit integers: * `fnv_1_hasher( key )` - hashes a `key` using the FNV-1 algorithm. * `fnv_1a_hasher( key )` - hashes a `key` using the FNV-1a algorithm. * `seeded_nmhash32_hasher( key )` - hashes a `key` using the nmhash32 algorithm. * `seeded_nmhash32x_hasher( key )` - hashes a `key` using the nmhash32x algorithm. * `seeded_water_hasher( key )` - hashes a `key` using the waterhash algorithm. Operator to compare two `key_type` values for equality * `key1 == key2` - compares `key1` with `key2` for equality ### Specifications of the `stdlib_hashmap_wrappers` procedures #### `copy_key` - Returns a copy of the key ##### Status Experimental ##### Description Returns a copy of an input of type `key_type`. ##### Syntax `call ` [[stdlib_hashmap_wrappers:copy_key]] `( old_key, new_key )` ##### Class Subroutine. ##### Arguments `old_key`: shall be a scalar expression of type `key_type`. It is an `intent(in)` argument. `new_key`: shall be a scalar variable of type `key_type`. It is an `intent(out)` argument. ##### Example ```fortran {!example/hashmaps/example_hashmaps_copy_key.f90!} ``` #### `fibonacci_hash` - maps an integer to a smaller number of bits ##### Status Experimental ##### Description `fibonacci_hash` is just a re-export of the function of the same name implemented in [`stdlib_hash_32bit`](https://stdlib.fortran-lang.org/page/spec/stdlib_hash_functions.html#fibonacci_hash-maps-an-integer-to-a-smaller-number-of-bits). It reduces the value of a 32 bit integer to a smaller number of bits. #### `fnv_1_hasher`- calculates a hash code from a key ##### Status Experimental ##### Description Calculates a 32 bit hash code from an input of type `key_type`. ##### Syntax `code = ` [[stdlib_hashmap_wrappers:fnv_1_hasher]] `( key )` ##### Class Pure function ##### Argument `key`: Shall be a scalar expression of type `key_type`. It is an `intent(in)` argument. ##### Result character The result is a scalar integer of kind `int32`. ##### Result value The result is a hash code created using the FNV-1 algorithm. ##### Note `fnv_1_hasher` is an implementation of the original FNV-1 hash code of Glenn Fowler, Landon Curt Noll, and Phong Vo. This code is relatively fast on short keys, and is small enough that it will often be retained in the instruction cache if hashing is intermittent. As a result it should give good performance for typical hash map applications. This code does not pass any of the SMHasher tests, but the resulting degradation in performance due to its larger number of collisions is expected to be minor compared to its faster hashing rate. ##### Example ```fortran {!example/hashmaps/example_hashmaps_fnv_1_hasher.f90!} ``` #### `fnv_1a_hasher`- calculates a hash code from a key ##### Status Experimental ##### Description Calculates a 32 bit hash code from an input of type `key_type`. ##### Syntax `code = ` [[stdlib_hashmap_wrappers:fnv_1a_hasher]] `( key )` ##### Class Pure function ##### Argument `key`: Shall be a scalar expression of type `key_type`. It is an `intent(in)` argument. ##### Result character The result is a scalar integer of kind `int32`. ##### Result value The result is a hash code created using the FNV-1a algorithm. ##### Note `fnv_1a_hasher` is an implementation of the original FNV-1A hash code of Glenn Fowler, Landon Curt Noll, and Phong Vo. This code is relatively fast on short keys, and is small enough that it will often be retained in the instruction cache if hashing is intermittent. As a result it should give good performance for typical hash map applications. This code does not pass any of the SMHasher tests, but the resulting degradation in performance due to its larger number of collisions is expected to be minor compared to its faster hashing rate. ##### Example ```fortran {!example/hashmaps/example_hashmaps_fnv_1a_hasher.f90!} ``` #### `free_key` - frees the memory associated with a key ##### Status Experimental ##### Description Deallocates the memory associated with a variable of type `key_type`. ##### Syntax `call ` [[stdlib_hashmap_wrappers:free_key]] `( key )` ##### Class Subroutine. ##### Argument `key`: shall be a scalar variable of type `key_type`. It is an `intent(out)` argument. ##### Example ```fortran {!example/hashmaps/example_hashmaps_free_key.f90!} ``` #### `get` - extracts the data from a derived type ##### Status Experimental ##### Description Extracts the data from a `key_type` and stores it in the variable `value`. ##### Syntax `call ` [[stdlib_hashmap_wrappers:get]] `( key, value )` ##### Class Subroutine. ##### Argument `key`: shall be a scalar expression of type `key_type`. It is an `intent(in)` argument. `value`: shall be an allocatable default `character` string variable, or an allocatable vector variable of type `integer` and kind `int8` or `int32`. ##### Example ```fortran {!example/hashmaps/example_hashmaps_get.f90!} ``` #### `hasher_fun`- serves as a function prototype. ##### Status Experimental ##### Description Serves as a prototype for hashing functions with a single, `key`, argument of type `key_type` returning an `int32` hash value. ##### Syntax `type(` [[stdlib_hashmap_wrappers:hasher_fun]] `), pointer :: fun_pointer` ##### Class Pure function prototype ##### Argument `key`: Shall be a rank one array expression of type `integer(int8)`. It is an `intent(in)` argument. ##### Result character The result is a scalar integer of kind `int32`. ##### Result value The result is a hash code. ##### Note `hasher_fun` is a prototype for defining dummy arguments and function pointers intended for use as a hash function for the hash maps. ##### Example ```fortran {!example/hashmaps/example_hashmaps_hasher_fun.f90!} ``` #### `operator(==)` - Compares two keys for equality ##### Status Experimental ##### Description Returns `.true.` if two keys are equal, and `.false.` otherwise. ##### Syntax `test = key1 == key2` ##### Class Pure operator. ##### Arguments `key1`: shall be a scalar expression of type `key_type`. It is an `intent(in)` argument. `key2`: shall be a scalar expression of type `key_type`. It is an `intent(in)` argument. ##### Result character The result is a value of type default `logical`. ##### Result value The result is `.true.` if the keys are equal, otherwise `.falss.`. ##### Example ```fortran {!example/hashmaps/example_hashmaps_equal_keys.f90!} ``` #### `seeded_nmhash32_hasher`- calculates a hash code from a key ##### Status Experimental ##### Description Calculates a 32 bit hash code from an input of type `key_type`. ##### Syntax `code = ` [[stdlib_hashmap_wrappers:seeded_nmhash32_hasher]] `( key )` ##### Class Pure function ##### Argument `key`: Shall be a scalar expression of type `key_type`. It is an `intent(in)` argument. ##### Result character The result is a scalar integer of kind `int32`. ##### Result value The result is a hash code created using the `nmhash32` algorithm. ##### Note `seeded_nmhash32_hasher` is a wrapper to the `NMHASH32_HASH` of the module `stdlib_hash_32bit`, which supplies a fixed seed to the wrapped function. `NMHASH32` is an implementation of the `nmhash32` hash code of James Z. M. Gao. This code has good, but not great, performance on long keys, poorer performance on short keys. As a result it should give fair performance for typical hash map applications. This code passes the SMHasher tests. ##### Example ```fortran {!example/hashmaps/example_hashmaps_seeded_nmhash32_hasher.f90!} ``` #### `seeded_nmhash32x_hasher`- calculates a hash code from a key ##### Status Experimental ##### Description Calculates a 32 bit hash code from an input of type `key_type`. ##### Syntax `code = ` [[stdlib_hashmap_wrappers:seeded_nmhash32x_hasher]] `( key )` ##### Class Pure function ##### Argument `key`: Shall be a scalar expression of type `key_type`. It is an `intent(in)` argument. ##### Result character The result is a scalar integer of kind `int32`. ##### Result value The result is a hash code created using the `nmhash32x` algorithm. ##### Note `seeded_nmhash32x_hasher` is a wrapper to the `nmhash32x_hash` of the module `stdlib_hash_32bit`, which supplies a fixed seed to the wrapped function. `nmhash32x` is an implementation of the `nmhash32x` hash code of James Z. M. Gao. This code has good, but not great, performance on long keys, poorer performance on short keys. As a result it should give fair performance for typical hash map applications. This code passes the SMHasher tests. ##### Example ```fortran {!example/hashmaps/example_hashmaps_seeded_nmhash32x_hasher.f90!} ``` #### `seeded_water_hasher`- calculates a hash code from a key ##### Status Experimental ##### Description Calculates a 32 bit hash code from an input of type `key_type`. ##### Syntax `code = ` [[stdlib_hashmap_wrappers:seeded_water_hasher]] `( key )` ##### Class Pure function ##### Argument `key`: Shall be a scalar expression of type `key_type`. It is an `intent(in)` argument. ##### Result character The result is a scalar integer of kind `int32`. ##### Result value The result is a hash code created using the `waterhash` algorithm. ##### Note `seeded_water_hasher` is a wrapper to the `water_hash` of the module `stdlib_hash_32bit`, which supplies a fixed seed to the wrapped function. `water_hash` is an implementation of the `waterhash` hash code of Tommy Ettinger. This code has excellent performance on long keys, and good performance on short keys. As a result it should give reasonable performance for typical hash table applications. This code passes the SMHasher tests. ##### Example ```fortran {!example/hashmaps/example_hashmaps_seeded_water_hasher.f90!} ``` #### `set` - places the data in a derived type ##### Status Experimental ##### Description Places the data from `value` in a `key_type`. ##### Syntax `call ` [[stdlib_hashmap_wrappers:set]] `( key, value )` ##### Class Subroutine. ##### Argument `key`: shall be a scalar variable of type `key_type`. It is an `intent(out)` argument. `value`: shall be a default `character` string scalar expression, or a vector expression of type `integer`and kind `int8` or `int32`. It is an `intent(in)` argument. ##### Note Values of types other than a scalar default character or and `int8` or `int32` vector can be used as the basis of a `key` by transferring the value to an `int8` vector. ##### Example ```fortran {!example/hashmaps/example_hashmaps_set.f90!} ``` ## The `stdlib_hashmaps` module The `stdlib_hashmaps` module defines three public data types, associated procedures and constants that implement two simple hash map types using separate chaining hashing and open addressing hashing. The derived type `hashmap_type` is the parent type to its two extensions: `chaining_hashmap_type` and `open_hashmap_type`. The extension types provide procedures to manipulate the structure of a hash map object: `init`, `map_entry`, `rehash`, `remove`, and `set_other_data`. They also provide procedures to inquire about entries in the hash map: `get_other_data`, and `key_test`. Finally they provide procedures to inquire about the overall structure and performance of the hash map object:`calls`, `entries`, `get_other_data`, `loading`, `slots`, and `total_depth`. The module also defines a number of public constants: `probe_factor`, `load_factor`, `map_probe_factor`, `default_bits`, `max_bits`, `int_calls`, `int_depth`, `int_index`, `int_probes`, `success`, `alloc_fault`, and `array_size_error`. Generic key interfaces for `key_test`, `map_entry`, `get_other_data`, `remove`, and `set_other_data` are povided so that the supported types of `int8` arrays, `int32` arrays and `character` scalars can be used in the key field as well as the base `key` type. So for `key_test`, `key_key_test` specifies key type for the key field, `int8_key_test` is `int8` for the key field and so on. Procedures other than `key_key_test` will call the `set` function to generate a key type and pass to `key_key_test`. ### The `stdlib_hashmaps` module's public constants The module defines several categories of public constants. Some are used to parameterize the empirical slot expansion code. Others parameterize the slots table size. Some are used to define integer kind values for different applications. Finally, some are used to report errors or success. The constants `probe_factor`, and `map_probe_factor` are used to parameterize the slot expansion code used to determine when in a in a procedure call the number of slots need to be increased to decrease the search path for an entry. The constant `probe_factor` is used to determine when the ratio of the number of map probes to map calls is too large and the slots need expansion. The constant `map_probe_factor` is used to determine when inserting a new entry the ratio of the number of map probes to map calls is too large and the slots need expansion. The constants `default_bits`, and `max_bits` are used to parameterize the table's slots size. The `default_bits` constant defines the default initial number of slots with a current value of 6 resulting in an initial `2**6 == 64` slots. This may optionally be overridden on hash map creation. The `max_bits` parameter sets the maximum table size as `2**max_bits` with a default value for `max_bits` of 30. The table will not work for a slots size greater than `2**30`. The constants `int_calls`, `int_depth`, `int_index`, and `int_probes` are used to define integer kind values for various contexts. The number of calls are reported and stored in entities of kind `int_calls`. Currently `int_calls` has the value of `int64`. The total depth, the number of inquiries needed to access all elements of the table, is reported and stored in entities of kind `int_depth`. Currently `int_depth` has the value of `int64`. The number of entries in the table, is reported and stored in entities of kind `int_index`. Currently `int_index` has the value of `int32`. The number of probes, hash map enquiries, are reported and stored in entities of kind `int_probes`. Currently `int_probes` has the value of `int64`. The constant `load_factor` is only used by the `open_hashmap_type`. It specifies the maximum fraction of the available slots that may be filled before expansion occurs. The current `load_factor = 0.5625` so the current implementation of `open_hashmap_type` can only hold a little more than `2**29` entries. Finally the error codes `success`, `alloc_fault`, and `array_size_error` are used to report the error status of certain procedure calls. The `succes` code indicates that no problems were found. The `alloc_fault` code indicates that a memory allocation failed. Finally the `array_size_error` indicates that on table creation `slots_bits` is less than `default_bits` or greater than `max_bits`. ### The `stdlib_hashmaps` module's derived types The `stdlib_hashmaps` module defines three public derived types and seven private types used in the implementation of the public types. The public types are the abstract `hashmap_type` and its extensions: `chaining_hashmap_type` and `open_hashmap_type`. The three private derived types, `chaining_map_entry_type`, `chaining_map_entry_ptr`, and `chaining_map_entry_pool` are used in the implementation of the `chaining_hashmap_type` public type. The four private derived types, `open_map_entry_type`, `open_map_entry_list`, `open_map_entry_ptr`, and `open_map_entry_pool` are used in the implementation of the `open_hashmap_type` public type. Each of these types are described below. #### The `hashmap_type` abstract type The `hashmap_type` abstract type serves as the parent type for the two types `chaining_hashmap_type` and `open_hashmap_type`. It defines eight private components: * `call_count` - the number of procedure calls on the map; * `nbits` - the number of bits used to address the slots; * `num_entries` - the number of entries in the map; * `num_free` - the number of entries in the free list of removed entries; * `probe_count` - the number of map probes since the last resizing or initialization; * `total_probes` - the number of probes of the map up to the last resizing or initialization; and * `hasher` - a pointer to the hash function used by the map. * `initialized` - track if map has been initialized It also defines five non-overridable procedures: * `calls` - returns the number of procedure calls on the map; * `entries` - returns the number of entries in the map; * `map_probes` - returns the number of map probes since initialization; * `num_slots` - returns the number of slots in the map; and * `slots_bits` - returns the number of bits used to address the slots; and ten deferred procedures: * `get_all_keys` - gets all the keys contained in a map; * `get_other_data` - gets the value associated with a key; * `init` - initializes the hash map; * `key_test` - returns a logical flag indicating whether the key is defined in the map. * `loading` - returns the ratio of the number of entries to the number of slots; * `map_entry` - inserts a key and optionally a corresponding value into the map; * `rehash` - rehashes the map with the provided hash function; * `remove` - removes the entry associated wit the key; * `set_other_data` - replaces the value associated with a key; * `total_depth` - returns the number of probes needed to address all the entries in the map; The type's definition is below: ```fortran type, abstract :: hashmap_type private integer(int_calls) :: call_count = 0 integer(int_calls) :: probe_count = 0 integer(int_calls) :: total_probes = 0 integer(int_index) :: num_entries = 0 integer(int_index) :: num_free = 0 integer(int32) :: nbits = default_bits procedure(hasher_fun), pointer, nopass :: hasher => fnv_1_hasher contains procedure, non_overridable, pass(map) :: calls procedure, non_overridable, pass(map) :: entries procedure, non_overridable, pass(map) :: map_probes procedure, non_overridable, pass(map) :: num_slots procedure, non_overridable, pass(map) :: slots_bits procedure(get_all_keys), deferred, pass(map) :: get_all_keys procedure(init_map), deferred, pass(map) :: init procedure(loading), deferred, pass(map) :: loading procedure(rehash_map), deferred, pass(map) :: rehash procedure(total_depth), deferred, pass(map) :: total_depth !! Generic interfaces for key types. procedure(key_key_test), deferred, pass(map) :: key_key_test procedure, non_overridable, pass(map) :: int8_key_test procedure, non_overridable, pass(map) :: int32_key_test procedure, non_overridable, pass(map) :: char_key_test procedure(key_map_entry), deferred, pass(map) :: key_map_entry procedure, non_overridable, pass(map) :: int8_map_entry procedure, non_overridable, pass(map) :: int32_map_entry procedure, non_overridable, pass(map) :: char_map_entry procedure(key_get_other_data), deferred, pass(map) :: key_get_other_data procedure, non_overridable, pass(map) :: int8_get_other_data procedure, non_overridable, pass(map) :: int32_get_other_data procedure, non_overridable, pass(map) :: char_get_other_data procedure(key_remove_entry), deferred, pass(map) :: key_remove_entry procedure, non_overridable, pass(map) :: int8_remove_entry procedure, non_overridable, pass(map) :: int32_remove_entry procedure, non_overridable, pass(map) :: char_remove_entry procedure(key_set_other_data), deferred, pass(map) :: key_set_other_data procedure, non_overridable, pass(map) :: int8_set_other_data procedure, non_overridable, pass(map) :: int32_set_other_data procedure, non_overridable, pass(map) :: char_set_other_data generic, public :: key_test => key_key_test, int8_key_test, int32_key_test, char_key_test generic, public :: map_entry => key_map_entry, int8_map_entry, int32_map_entry, char_map_entry generic, public :: get_other_data => key_get_other_data, int8_get_other_data, int32_get_other_data, char_get_other_data generic, public :: remove => key_remove_entry, int8_remove_entry, int32_remove_entry, char_remove_entry generic, public :: set_other_data => key_set_other_data, int8_set_other_data, int32_set_other_data, char_set_other_data end type hashmap_type ``` #### The `chaining_map_entry_type` derived type Entities of the type `chaining_map_entry_type` are used to define a linked list structure that stores the key, its other data, the hash of the key, and the resulting index into the inverse table. The type's definition is below: ```fortran type :: chaining_map_entry_type ! Chaining hash map entry type private integer(int_hash) :: hash_val ! Full hash value type(key_type) :: key ! The entry's key class(*), allocatable :: other ! Other entry data integer(int_index) :: index ! Index into inverse table type(chaining_map_entry_type), pointer :: & next => null() ! Next bucket end type chaining_map_entry_type ``` Currently the `int_hash` and `int_index` have the value of `int32`. #### The `chaining_map_entry_ptr` derived type The type `chaining_map_entry_ptr` is used to define the elements of the hash map that are either empty or link to the linked lists containing the elements of the table. The type's definition is below: ```fortran type chaining_map_entry_ptr ! Wrapper for a pointer to a chaining ! map entry type object type(chaining_map_entry_type), pointer :: target => null() end type chaining_map_entry_ptr ``` #### The `chaining_map_entry_pool` derived type The type `chaining_map_entry_pool` is used to implement a pool of allocated `chaining_map_entry_type` elements to save on allocation costs. The type's definition is below: ```fortran type :: chaining_map_entry_pool ! Type implementing a pool of allocated ! `chaining_map_entry_type` objects private ! Index of next bucket integer(int_index) :: next = 0 type(chaining_map_entry_type), allocatable :: more_map_entries(:) type(chaining_map_entry_pool), pointer :: lastpool => null() end type chaining_map_entry_pool ``` #### The `chaining_hashmap_type` derived type The `chaining_hashmap_type` derived type extends the `hashmap_type` to implements a separate chaining hash map. In addition to the components of the `hashmap_type` it provides the four components: * `cache` - a pool of `chaining_map_entry_pool` objects used to reduce allocation costs; * `free_list` - a free list of map entries; * `inverse` - an array of `chaining_map_entry_ptr` bucket lists (inverses) storing entries at fixed locations once entered; and * `slots` - an array of bucket lists serving as the hash map. It also implements all of the deferred procedures of the `hashmap_type` and a finalizer for its maps. The type's definition is as follows: ```fortran type, extends(hashmap_type) :: chaining_hashmap_type private type(chaining_map_entry_pool), pointer :: cache => null() type(chaining_map_entry_type), pointer :: free_list => null() type(chaining_map_entry_ptr), allocatable :: inverse(:) type(chaining_map_entry_ptr), allocatable :: slots(:) contains procedure :: get_all_keys => get_all_chaining_keys procedure :: key_get_other_data => get_other_chaining_data procedure :: init => init_chaining_map procedure :: loading => chaining_loading procedure :: key_map_entry => map_chain_entry procedure :: rehash => rehash_chaining_map procedure :: key_remove_entry => remove_chaining_entry procedure :: key_set_other_data => set_other_chaining_data procedure :: total_depth => total_chaining_depth procedure :: key_key_test => chaining_key_test final :: free_chaining_map end type chaining_hashmap_type ``` #### The `open_map_entry_type` derived type Entities of the type `open_map_entry_type` are used to define a linked list structure that stores the key, its other data, the hash of the key, and the resulting index into the inverse table. The type's definition is below: ```fortran type :: open_map_entry_type ! Open hash map entry type private integer(int_hash) :: hash_val ! Full hash value type(key_type) :: key ! The entry's key class(*), allocatable :: other ! Other entry data integer(int_index) :: index ! Index into inverse table end type open_map_entry_type ``` Currently `int_hash` and `int_index` have the value of `int32`. #### The `open_map_entry_ptr` derived type The type `open_map_entry_ptr` is used to define the elements of the hash map that are either empty or link to the linked lists containing the elements of the table. The type's definition is below: ```fortran type open_map_entry_ptr ! Wrapper for a pointer to a open ! map entry type object type(open_map_entry_type), pointer :: target => null() end type open_map_entry_ptr ``` #### The `open_hashmap_type` derived type The `open_hashmap_type` derived type extends the `hashmap_type` to implement an open addressing hash map. In addition to the components of the `hashmap_type` it provides the four components: * `cache` - a pool of `open_map_entry_pool` objects used to reduce allocation costs; * `free_list` - a free list of map entries; * `index_mask` - an `and` mask used in linear addressing; * `inverse` - an array of `open_map_entry_ptr` bucket lists (inverses) storing entries at fixed locations once entered; and * `slots` - an array of bucket lists serving as the hash map. It also implements all of the deferred procedures of the `hashmap_type` and a finalizer for its maps. The type's definition is as follows: ```fortran type, extends(hashmap_type) :: open_hashmap_type private integer(int_index) :: index_mask = 2_int_index**default_bits-1 type(open_map_entry_pool), pointer :: cache => null() type(open_map_entry_list), pointer :: free_list => null() type(open_map_entry_ptr), allocatable :: inverse(:) integer(int_index), allocatable :: slots(:) contains procedure :: get_all_keys => get_all_open_keys procedure :: key_get_other_data => get_other_open_data procedure :: init => init_open_map procedure :: loading => open_loading procedure :: key_map_entry => map_open_entry procedure :: rehash => rehash_open_map procedure :: key_remove_entry => remove_open_entry procedure :: key_set_other_data => set_other_open_data procedure :: total_depth => total_open_depth procedure :: key_key_test => open_key_test final :: free_open_map end type open_hashmap_type ``` ### Table of `stdlib_hashmap` procedures The `stdlib_hashmap` module provides procedures in several categories: a procedure to initialize the map; a procedure to modify the structure of a map; procedures to modify the content of a map; procedures to report on the content of a map; and procedures to report on the structure of the map. The procedures in each category are listed below. Procedure to initialize a chaining hash map: * `map % init( [hasher, slots_bits, status] )` - Routine to initialize a chaining hash map. Procedure to modify the structure of a map: * `map % rehash( hasher )` - Routine to change the hash function for a map. Procedures to modify the content of a map: * `map % map_entry( key[, other, conflict] )` - Inserts an entry into the hash map. * `map % remove( key[, existed] )` - Remove the entry, if any, associated with the `key`. * `map % set_other_data( key, other[, exists] )` - Change the value associated with the `key`. Procedures to report the content of a map: * `map % get_all_keys( all_keys )` - Returns all the keys contained in the map; * `map % get_other_data( key, other[, exists] )` - Returns the value associated with the `key`; * `map % key_test( key, present)` - Returns a flag indicating whether the `key` is present in the map. Procedures to report on the structure of the map: * `map % calls()` - the number of subroutine calls on the hash map. * `map % entries()`- the number of entries in a hash map. * `map % loading()` - the number of entries relative to the number of slots in a hash map. * `map % map_probes()` - the total number of table probes on a hash map. * `map % slots()` - Returns the number of allocated slots in a hash map. * `map % total_depth()` - Returns the total number of one's based offsets of slot entries from their slot index ### Specifications of the `stdlib_hashmaps` procedures #### `calls` - Returns the number of calls on the hash map ##### Status Experimental ##### Description Returns the number of procedure calls on a hash map. ##### Syntax `value = map % ` [[hashmap_type(type):calls(bound)]] `()` ##### Class Pure function ##### Argument `map` (pass) - shall be an expression of class `hashmap_type`. It is an `intent(in)` argument. ##### Result character The result will be an integer of kind `int_calls`. ##### Result value The result will be the number of procedure calls on the hash map. ##### Example ```fortran {!example/hashmaps/example_hashmaps_calls.f90!} ``` #### `entries` - Returns the number of entries in the hash map ##### Status Experimental ##### Description Returns the number of entries in a hash map. ##### Syntax `value = map % ` [[hashmap_type(type):entries(bound)]] `()` ##### Class Pure function ##### Argument `map` (pass) - shall be an expression of class `hashmap_type`. It is an `intent(in)` argument. ##### Result character The result will be an integer of kind `int_index`. ##### Result value The result will be the number of entries in the hash map. ##### Example ```fortran {!example/hashmaps/example_hashmaps_entries.f90!} ``` #### `get_all_keys` - Returns all the keys contained in a map ##### Status Experimental ##### Description Returns all the keys contained in a map. ##### Syntax `call map % ` [[hashmap_type(type):get_all_keys(bound)]] `( all_keys )` ##### Class Subroutine ##### Arguments `map` (pass): shall be a scalar variable of class `chaining_hashmap_type` or `open_hashmap_type`. It is an `intent(in)` argument. It will be the hash map used to store and access the other data. `all_keys`: shall be a rank-1 allocatable array of type `key_type`. It is an `intent(out)` argument. ##### Example ```fortran {!example/hashmaps/example_hashmaps_get_all_keys.f90!} ``` #### `get_other_data` - Returns other data associated with the `key` ##### Status Experimental ##### Description Returns the value associated with the `key`, ##### Syntax `value = map % ` [[hashmap_type(type):get_other_data(bound)]] `( key, other [, exists] )` ##### Class Subroutine ##### Arguments `map` (pass): shall be a scalar variable of class `chaining_hashmap_type` or `open_hashmap_type`. It is an `intent(inout)` argument. It will be the hash map used to store and access the other data. `key`: shall be a of type `key_type` scalar, `character` scalar, `int8` array or `int32` array. It is an `intent(in)` argument. `other`: shall be a allocatable unlimited polymorphic scalar. (class(*), allocatable) It is an `intent(out)` argument. It is the value associated with the `key`. `exists` (optional): shall be a variable of type logical. It is an `intent(out)` argument. If `.true.` an entry with the given `key` exists in the map and `other` is defined. If `.false.` `other` is undefined. ##### Example The following is an example of the retrieval of other data associated with a `key`: ```fortran {!example/hashmaps/example_hashmaps_get_other_data.f90!} ``` #### `init` - initializes a hash map ##### Status Experimental ##### Description Initializes a `hashmap_type` object. ##### Syntax `call map % ` [[hashmap_type(type):init(bound)]] `( [hasher, slots_bits, status ] )` ##### Class Subroutine ##### Arguments `map` (pass): shall be a scalar variable of class `chaining_hashmap_type` or `open_hashmap_type`. It is an `intent(out)` argument. It will be a hash map used to store and access the entries. `hasher`: (optional): shall be a procedure with interface `hash_fun`. It is an `intent(in)` argument. It is the procedure to be used to generate the hashes for the table from the keys of the entries. Defaults to fnv_1_hasher if not provided. `slots_bits` (optional): shall be a scalar default integer expression. It is an `intent(in)` argument. The initial number of slots in the table will be `2**slots_bits`. * `slots_bits` shall be a positive default integer less than `max_bits`, otherwise processing stops with an informative error code. * If `slots_bits` is absent then the effective value for `slots_bits` is `default_bits`. `status` (optional): shall be a scalar integer variable of kind `int32`. It is an `intent(out)` argument. On return if present it shall have an error code value. * If map was successfully initialized then `status` has the value `success`. * If allocation of memory for the `map` arrays fails then `status` has the value `alloc_fault`. * If `slot_bits < 6` or `slots_bits > max_bits` then `status` has the value of `array_size_error`. * If `status` is absent, but `status` would have a value other than `success`, then processing stops with an informative stop code. ##### Example ```fortran {!example/hashmaps/example_hashmaps_init.f90!} ``` #### `key_test` - indicates whether `key` is present ##### Status Experimental ##### Description Returns a logical flag indicating whether `key` is present for an entry in the map. ##### Syntax `call map % ` [[hashmap_type(type):key_test(bound)]] `( key, present )` ##### Class Subroutine. ##### Arguments `map` (pass): shall be a scalar variable of class `chaining_hashmap_type` or `open_hashmap_type`. It is an `intent(inout)` argument. It is the hash map whose entries are examined. `key`: shall be a of type `key_type` scalar, `character` scalar, `int8` array or `int32` array. It is an `intent(in)` argument. It is a `key` whose presence in the `map` is being examined. `present`: shall be a scalar variable of type `logical`. It is an `intent(out)` argument. It is a logical flag where `.true.` indicates that an entry with that `key` is present in the `map` and `.false.` indicates that no such entry is present. ##### Example ```fortran {!example/hashmaps/example_hashmaps_key_test.f90!} ``` #### `loading` - Returns the ratio of entries to slots ##### Status Experimental ##### Description Returns the ratio of the number of entries relative to the number of slots in the hash map. ##### Syntax `value = map % ` [[hashmap_type(type):loading(bound)]] `( )` ##### Class Pure function ##### Argument `map` (pass) - shall be an expression of class `chaining_hashmap_type` or `open_hashmap_type`. It is an `intent(in)` argument. ##### Result character The result will be a default real. ##### Result value The result will be the ratio of the number of entries relative to the number of slots in the hash map. ##### Example ```fortran {!example/hashmaps/example_hashmaps_loading.f90!} ``` #### `map_entry` - inserts an entry into the hash map ##### Status Experimental ##### Description Inserts an entry into the hash map if it is not already present. ##### Syntax `call map % ` [[hashmap_type(type):map_entry(bound)]] `( key[, other, conflict ] )` ##### Class Subroutine ##### Arguments `map` (pass): shall be a scalar variable of class `chaining_hashmap_type` or `open_hashmap_type`. It is an `intent(inout)` argument. It is the hash map to receive the entry. `key`: shall be a of type `key_type` scalar, `character` scalar, `int8` array or `int32` array. It is an `intent(in)` argument. It is the key for the entry to be placed in the table. `other` (optional): shall be a scalar of any type, including derived types. It is an `intent(in)` argument. If present it is the value to be associated with the `key`. `conflict` (optional): shall be a scalar variable of type `logical`. It is an `intent(out)` argument. If present, a `.true.` value indicates that an entry with the value of `key` already exists and the entry was not entered into the map, a `.false.` value indicates that `key` was not present in the map and the entry was added to the map. * If `key` is already present in `map` and the `conflict` argument has been provided then the presence of `other` is ignored. If `conflict` has not been provided then it routine will error stop. ##### Example ```fortran {!example/hashmaps/example_hashmaps_map_entry.f90!} ``` #### `map_probes` - returns the number of hash map probes ##### Status Experimental ##### Description Returns the total number of table probes on the hash map. ##### Syntax `result = map % ` [[hashmap_type(type):map_probes(bound)]] `( )` ##### Class Pure function ##### Argument `map` (pass): shall be a scalar expression of class `hashmap_type`. It is an `intent(in)` argument. It is the hash map of interest. ##### Result character The result is a scalar integer of kind `int_probes`. ##### Result value The result is the number of probes of `map` since initialization or rehashing. ##### Example ```fortran {!example/hashmaps/example_hashmaps_probes.f90!} ``` #### `num_slots` - returns the number of hash map slots. ##### Status Experimental ##### Description Returns the total number of slots on a hash map ##### Syntax `result = map % ` [[hashmap_type(type):num_slots(bound)]] `( )` ##### Class Pure function ##### Argument `map`: shall be a scalar expression of class `hashmap_type`. It is an `intent(in)` argument. It is the hash map of interest. ##### Result character The result is a scalar integer of kind `int_index`. ##### Result value The result is the number of slots in `map`. ##### Example ```fortran {!example/hashmaps/example_hashmaps_num_slots.f90!} ``` #### `rehash` - changes the hashing function ##### Status Experimental ##### Description Changes the hashing function for the map entries to that of `hasher`. ##### Syntax `call map % ` [[hashmap_type(type):rehash(bound)]] `( hasher )` ##### Class Subroutine ##### Arguments `map` (pass): shall be a scalar variable of class `chaining_hashmap_type` or `open_hashmap_type`. It is an `intent(inout)` argument. It is the hash map whose hashing method is to be changed. `hasher`: shall be a function of interface `hasher_fun`. It is the hash method to be used by `map`. ##### Example ```fortran {!example/hashmaps/example_hashmaps_rehash.f90!} ``` #### `remove` - removes an entry from the hash map ##### Status Experimental ##### Description Removes an entry from the hash map, `map`. ##### Syntax `call map % ` [[hashmap_type(type):remove(bound)]] `( key[, existed ])` ##### Class Subroutine ##### Arguments `map` (pass): shall be a scalar variable of class `chaining_hashmap_type` or `open_hashmap_type`. It is an `intent(inout)` argument. It is the hash map with the element to be removed. `key`: shall be a of type `key_type` scalar, `character` scalar, `int8` array or `int32` array. It is an `intent(in)` argument. It is the `key` identifying the entry to be removed. `existed` (optional): shall be a scalar variable of type default logical. It is an `intent(out)` argument. If present with the value `.true.` the entry existed in the map before removal, if `.false.` the entry was not present to be removed and the map is unchanged. If absent, the procedure returns with no entry with the given key. ##### Example ```fortran {!example/hashmaps/example_hashmaps_remove.f90!} ``` #### `set_other_data` - replaces the other data for an entry ##### Status Experimental ##### Description Replaces the other data in the map for the entry with the key value, `key`. ##### Syntax `call map % ` [[hashmap_type(type):set_other_data(bound)]] `( key, other[, exists] )` ##### Class Subroutine ##### Arguments `map` (pass): shall be a scalar variable of class `chaining_hashmap_type` or `open_hashmap_type`. It is an `intent(inout)` argument. It will be a hash map used to store and access the entry's data. `key`: shall be a of type `key_type` scalar, `character` scalar, `int8` array or `int32` array. It is an `intent(in)` argument. It is the `key` to the entry whose `other` data is to be replaced. `other` (optional): shall be a scalar of any type, including derived types. It is an `intent(in)` argument. If present it is the value to be associated with the `key`. `exists` (optional): shall be a scalar variable of type `logical`. It is an `intent(out)` argument. If present with the value `.true.` an entry with that `key` existed in the map and its `other` data was replaced. If `exists` is `.false.` the `key` did not exist and nothing was done. * If `key` is not already present in `map` and `exists` has not been provided then the routine will error stop. ##### Example ```fortran {!example/hashmaps/example_hashmaps_set_other_data.f90!} ``` #### `slots_bits` - returns the number of bits used to address the hash map slots ##### Status Experimental ##### Description Returns the total number of bits used to address the hash map slots. ##### Syntax `result = map % ` [[hashmap_type(type):slots_bits(bound)]] `( )` ##### Class Pure function ##### Argument `map` (pass): shall be a scalar expression of class `hashmap_type`. It is an `intent(in)` argument. It is the hash map of interest. ##### Result character The result is a scalar integer of kind `int_index`. ##### Result value The result is the number of bits used in addressing the slots in `map`. ##### Example ```fortran {!example/hashmaps/example_hashmaps_slots_bits.f90!} ``` #### `total_depth` - returns the total depth of the hash map entries ##### Status Experimental ##### Description Returns the total number of one's based offsets of slot entries from their slot index for a hash map ##### Syntax `result = map % ` [[hashmap_type:total_depth]] `( )` ##### Class Pure function ##### Argument `map` (pass): shall be a scalar expression of class `hashmap_type`. It is an `intent(in)` argument. It is the hash map of interest. ##### Result character The result is a scalar integer of kind `int_depth`. ##### Result value The result is the total number of one's based offsets of slot entries from their slot index the map. ##### Example ```fortran {!example/hashmaps/example_hashmaps_total_depth.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/index.md0000664000175000017500000000455215135654166021507 0ustar alastairalastair--- title: Specifications (specs) --- # Fortran stdlib Specifications (specs) This is an index/directory of the specifications (specs) for each new module/feature as described in the [workflow document](../Workflow.html). [TOC] ## Experimental Features & Modules - [ansi](./stdlib_ansi.html) - Terminal color and style escape sequences - [array](./stdlib_array.html) - Procedures for index manipulation and array handling - [ascii](./stdlib_ascii.html) - Procedures for handling ASCII characters - [constants](./stdlib_constants.html) - Constants - [bitsets](./stdlib_bitsets.html) - Bitset data types and procedures - [error](./stdlib_error.html) - Catching and handling errors - [state_type](./stdlib_error_state_type.html) - General state and error handling - [hash](./stdlib_hash_procedures.html) - Hashing integer vectors or character strings - [hashmaps](./stdlib_hashmaps.html) - Hash maps/tables - [io](./stdlib_io.html) - Input/output helper & convenience - [kinds](./stdlib_kinds.html) - Kind parameters - [linalg](./stdlib_linalg.html) - Linear Algebra - [linalg_state_type](./stdlib_linalg_state_type.html) - Linear Algebra state and error handling - [logger](./stdlib_logger.html) - Runtime logging system - [math](./stdlib_math.html) - General purpose mathematical functions - [optval](./stdlib_optval.html) - Fallback value for optional arguments - [quadrature](./stdlib_quadrature.html) - Numerical integration - [random](./stdlib_random.html) - Probability Distributions random number generator - [sorting](./stdlib_sorting.html) - Sorting of rank one arrays - [stats](./stdlib_stats.html) - Descriptive Statistics - [stats_distributions_uniform](./stdlib_stats_distribution_uniform.html) - Uniform Probability Distribution - [stats_distributions_normal](./stdlib_stats_distribution_normal.html) - Normal Probability Distribution - [stats_distributions_exponential](./stdlib_stats_distribution_exponential.html) - Exponential Probability Distribution - [string\_type](./stdlib_string_type.html) - Basic string support - [stringlist_type](./stdlib_stringlist_type.html) - 1-Dimensional list of strings - [strings](./stdlib_strings.html) - String handling and manipulation routines - [system](./stdlib_system.html) - OS and sub-processing routines - [version](./stdlib_version.html) - Version information ## Released/Stable Features & Modules - (None yet) fortran-lang-stdlib-0ede301/doc/specs/stdlib_selection.md0000664000175000017500000002253715135654166023731 0ustar alastairalastair--- title: selection --- # The `stdlib_selection` module [TOC] ## Overview of selection Suppose you wish to find the value of the k-th smallest entry in an array of size N, or the index of that value. While it could be done by sorting the whole array using [[stdlib_sorting(module):sort(interface)]] or [[stdlib_sorting(module):sort_index(interface)]] from [[stdlib_sorting(module)]] and then finding the k-th entry, that would require O(N x LOG(N)) time. However selection of a single entry can be done in O(N) time, which is much faster for large arrays. This is useful, for example, to quickly find the median of an array, or some other percentile. The Fortran Standard Library therefore provides a module, `stdlib_selection`, which implements selection algorithms. ## Overview of the module The module `stdlib_selection` defines two generic subroutines: * `select` is used to find the k-th smallest entry of an array. The input array is also modified in-place, and on return will be partially sorted such that `all(array(1:k) <= array(k)))` and `all(array(k) <= array((k+1):size(array)))` is true. The user can optionally specify `left` and `right` indices to constrain the search for the k-th smallest value. This can be useful if you have previously called `select` to find a smaller or larger rank (that will have led to partial sorting of `array`, thus implying some constraints on the location). * `arg_select` is used to find the index of the k-th smallest entry of an array. In this case the input array is not modified, but the user must provide an input index array with the same size as `array`, having indices that are a permutation of `1:size(array)`, which is modified instead. On return the index array is modified such that `all(array(index(1:k)) <= array(index(k)))` and `all(array(k) <= array(k+1:size(array)))`. The user can optionally specify `left` and `right` indices to constrain the search for the k-th smallest value. This can be useful if you have previously called `arg_select` to find a smaller or larger rank (that will have led to partial sorting of `index`, thus implying some constraints on the location). ## `select` - find the k-th smallest value in an input array ### Status Experimental ### Description Returns the k-th smallest value of `array(:)`, and also partially sorts `array(:)` such that `all(array(1:k) <= array(k))` and `all(array(k) <= array((k+1):size(array)))` ### Syntax `call ` [[stdlib_selection(module):select(interface)]] `( array, k, kth_smallest [, left, right ] )` ### Class Generic subroutine. ### Arguments `array` : shall be a rank one array of any of the types: `integer(int8)`, `integer(int16)`, `integer(int32)`, `integer(int64)`, `real(sp)`, `real(dp)`, `real(xdp)`, `real(qp)`. It is an `intent(inout)` argument. `k`: shall be a scalar with any of the types: `integer(int8)`, `integer(int16)`, `integer(int32)`, `integer(int64)`. It is an `intent(in)` argument. We search for the `k`-th smallest entry of `array(:)`. `kth_smallest`: shall be a scalar with the same type as `array`. It is an `intent(out)` argument. On return it contains the k-th smallest entry of `array(:)`. `left` (optional): shall be a scalar with the same type as `k`. It is an `intent(in)` argument. If specified then we assume the k-th smallest value is definitely contained in `array(left:size(array))`. If `left` is not present, the default is 1. This is typically useful if multiple calls to `select` are made, because the partial sorting of `array` implies constraints on where we need to search. `right` (optional): shall be a scalar with the same type as `k`. It is an `intent(in)` argument. If specified then we assume the k-th smallest value is definitely contained in `array(1:right)`. If `right` is not present, the default is `size(array)`. This is typically useful if multiple calls to `select` are made, because the partial sorting of `array` implies constraints on where we need to search. ### Notes Selection of a single value should have runtime of O(`size(array)`), so it is asymptotically faster than sorting `array` entirely. The test program at the end of this document shows that is the case. The code does not support `NaN` elements in `array`; it will run, but there is no consistent interpretation given to the order of `NaN` entries of `array` compared to other entries. `select` was derived from code in the Coretran library by Leon Foks, https://github.com/leonfoks/coretran. Leon Foks has given permission for the code here to be released under stdlib's MIT license. ### Example ```fortran {!example/selection/example_select.f90!} ``` ## `arg_select` - find the index of the k-th smallest value in an input array ### Status Experimental ### Description Returns the index of the k-th smallest value of `array(:)`, and also partially sorts the index-array `indx(:)` such that `all(array(indx(1:k)) <= array(indx(k)))` and `all(array(indx(k)) <= array(indx((k+1):size(array))))` ### Syntax `call ` [[stdlib_selection(module):arg_select(interface)]] `( array, indx, k, kth_smallest [, left, right ] )` ### Class Generic subroutine. ### Arguments `array` : shall be a rank one array of any of the types: `integer(int8)`, `integer(int16)`, `integer(int32)`, `integer(int64)`, `real(sp)`, `real(dp)`, `real(xdp)`, `real(qp)`. It is an `intent(in)` argument. On input it is the array in which we search for the k-th smallest entry. `indx`: shall be a rank one array with the same size as `array`, containing all integers from `1:size(array)` in any order. It is of any of the types: `integer(int8)`, `integer(int16)`, `integer(int32)`, `integer(int64)`. It is an `intent(inout)` argument. On return its elements will define a partial sorting of `array(:)` such that: `all( array(indx(1:k-1)) <= array(indx(k)) )` and `all(array(indx(k)) <= array(indx(k+1:size(array))))`. `k`: shall be a scalar with the same type as `indx`. It is an `intent(in)` argument. We search for the `k`-th smallest entry of `array(:)`. `kth_smallest`: a scalar with the same type as `indx`. It is an `intent(out)` argument, and on return it contains the index of the k-th smallest entry of `array(:)`. `left` (optional): shall be a scalar with the same type as `k`. It is an `intent(in)` argument. If specified then we assume the k-th smallest value is definitely contained in `array(indx(left:size(array)))`. If `left` is not present, the default is 1. This is typically useful if multiple calls to `arg_select` are made, because the partial sorting of `indx` implies constraints on where we need to search. `right` (optional): shall be a scalar with the same type as `k`. It is an `intent(in)` argument. If specified then we assume the k-th smallest value is definitely contained in `array(indx(1:right))`. If `right` is not present, the default is `size(array)`. This is typically useful if multiple calls to `arg_select` are made, because the reordering of `indx` implies constraints on where we need to search. ### Notes `arg_select` does not modify `array`, unlike `select`. The partial sorting of `indx` is not stable, i.e., indices that map to equal values of array may be reordered. The code does not support `NaN` elements in `array`; it will run, but there is no consistent interpretation given to the order of `NaN` entries of `array` compared to other entries. While it is essential that `indx` contains a permutation of the integers `1:size(array)`, the code does not check for this. For example if `size(array) == 4`, then we could have `indx = [4, 2, 1, 3]` or `indx = [1, 2, 3, 4]`, but not `indx = [2, 1, 2, 4]`. It is the user's responsibility to avoid such errors. Selection of a single value should have runtime of O(`size(array)`), so it is asymptotically faster than sorting `array` entirely. The test program at the end of these documents confirms that is the case. `arg_select` was derived using code from the Coretran library by Leon Foks, https://github.com/leonfoks/coretran. Leon Foks has given permission for the code here to be released under stdlib's MIT license. ### Example ```fortran {!example/selection/example_arg_select.f90!} ``` ## Comparison with using `sort` The following program compares the timings of `select` and `arg_select` for computing the median of an array, vs using `sort` from `stdlib`. In theory we should see a speed improvement with the selection routines which grows like LOG(size(`array`)). ```fortran {!example/selection/selection_vs_sort.f90!} ``` The results seem consistent with expectations when the `array` is large; the program prints: ``` select ; N= 1 ; PASS; Relative-speedup-vs-sort: 1.90928173 arg_select; N= 1 ; PASS; Relative-speedup-vs-sort: 1.76875830 select ; N= 11 ; PASS; Relative-speedup-vs-sort: 1.14835048 arg_select; N= 11 ; PASS; Relative-speedup-vs-sort: 1.00794709 select ; N= 101 ; PASS; Relative-speedup-vs-sort: 2.31012774 arg_select; N= 101 ; PASS; Relative-speedup-vs-sort: 1.92877376 select ; N= 1001 ; PASS; Relative-speedup-vs-sort: 4.24190664 arg_select; N= 1001 ; PASS; Relative-speedup-vs-sort: 3.54580402 select ; N= 10001 ; PASS; Relative-speedup-vs-sort: 5.61573362 arg_select; N= 10001 ; PASS; Relative-speedup-vs-sort: 4.79348087 select ; N= 100001 ; PASS; Relative-speedup-vs-sort: 7.28823519 arg_select; N= 100001 ; PASS; Relative-speedup-vs-sort: 6.03007460 ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_math.md0000664000175000017500000004442415135654166022674 0ustar alastairalastair--- title: math --- # The `stdlib_math` module [TOC] ## Introduction `stdlib_math` module provides general purpose mathematical functions. ## Procedures and Methods provided ### `clip` function #### Description Returns a value which lies in the given interval [`xmin`, `xmax`] (interval is `xmin` and `xmax` inclusive) and is closest to the input value `x`. #### Syntax `res = ` [[stdlib_math(module):clip(interface)]] ` (x, xmin, xmax)` #### Status Experimental #### Class Elemental function. #### Argument(s) `x`: scalar of either `integer` or `real` type. This argument is `intent(in)`. `xmin`: scalar of either `integer` or `real` type. This argument is `intent(in)`. `xmax`: scalar of either `integer` or `real` type, which must be greater than or equal to `xmin`. This argument is `intent(in)`. Note: All arguments must have same `type` and same `kind`. #### Output value or Result value The output is a scalar of `type` and `kind` same as to that of the arguments. #### Examples ##### Example 1: Here inputs are of type `integer` and kind `int32` ```fortran {!example/math/example_clip_integer.f90!} ``` ##### Example 2: Here inputs are of type `real` and kind `sp` ```fortran {!example/math/example_clip_real.f90!} ``` ### `swap` subroutine #### Description Swaps the values in `lhs` and `rhs`. #### Syntax `call` [[stdlib_math(module):swap(interface)]] ` (lhs, rhs)` #### Status Experimental #### Class Elemental subroutine. #### Argument(s) `lhs`: scalar or array of any of the intrinsic types `integer`, `real`, `complex`, `logical`, `character`, `string_type`, `bitset` type. This argument is `intent(inout)`. `rhs`: scalar or array of any of the intrinsic types `integer`, `real`, `complex`, `logical`, `character`, `string_type`, `bitset` type. This argument is `intent(inout)`. ##### Note All arguments must have same `type` and same `kind`. **WARNING**: For fix size characters with different length, the `swap` subroutine will truncate the longest amongst `lhs` and `rhs`. To avoid truncation it is possible to pass a subsection of the string. #### Examples ```fortran {!example/math/example_math_swap.F90!} ``` ### `gcd` function #### Description Returns the greatest common divisor of two integers. #### Syntax `res = ` [[stdlib_math(module):gcd(interface)]] ` (a, b)` #### Status Experimental #### Class Elemental function. #### Argument(s) `a`: One integer with `intent(in)` to get the divisor for. `b`: Another integer with `intent(in)` to get the divisor for. Note: All arguments must be integers of the same `kind`. #### Output value or Result value Returns an integer of the same `kind` as that of the arguments. #### Examples ##### Example 1: ```fortran {!example/math/example_gcd.f90!} ``` ### `linspace` - Create a linearly spaced rank one array #### Description Returns a linearly spaced rank 1 array from [`start`, `end`]. Optionally, you can specify the length of the returned array by passing `n`. #### Syntax `res = ` [[stdlib_math(module):linspace(interface)]] ` (start, end [, n])` #### Status Experimental #### Class Pure function. #### Argument(s) `start`: Shall be scalar of any numeric type or kind. This argument is `intent(in)`. `end`: Shall be the same `type` and `kind` as `start`. This argument is `intent(in)`. `n`: Shall be an integer specifying the length of the output. This argument is `optional` and `intent(in)`. #### Output value or Result value The output is a rank 1 array whose length is either 100 (default value) or `n`. If `n` == 1, return a rank 1 array whose only element is `end`. If `n` <= 0, return a rank 1 array with length 0. If `start`/`end` are `real` or `complex` types, the `result` will be of the same type and kind as `start`/`end`. If `start`/`end` are `integer` types, the `result` will default to a `real(dp)` array. #### Examples ##### Example 1: Here inputs are of type `complex` and kind `dp` ```fortran {!example/math/example_linspace_complex.f90!} ``` ##### Example 2: Here inputs are of type `integer` and kind `int16`, with the result defaulting to `real(dp)`. ```fortran {!example/math/example_linspace_int16.f90!} ``` ### `logspace` - Create a logarithmically spaced rank one array #### Description Returns a logarithmically spaced rank 1 array from [`base`^`start`, `base`^`end`]. The default size of the array is 50. Optionally, you can specify the length of the returned array by passing `n`. You can also specify the `base` used to compute the range (default 10). #### Syntax `res = ` [[stdlib_math(module):logspace(interface)]] ` (start, end [, n [, base]])` #### Status Experimental #### Class Pure function. #### Argument(s) `start`: Shall be a scalar of any numeric type. All kinds are supported for real and complex arguments. For integers, only the default kind is currently implemented. This argument is `intent(in)`. `end`: Shall be the same `type` and `kind` as `start`. This argument is `intent(in)`. `n`: Shall be an integer specifying the length of the output. This argument is `optional` and `intent(in)`. `base` : Shall be a scalar of any numeric type. All kinds are supported for real and complex arguments. For integers, only the default kind is currently implemented. This argument is `optional` and `intent(in)`. #### Output value or Result value The output is a rank 1 array whose length is either 50 (default value) or `n`. If `n` == 1, return a rank 1 array whose only element is `base`^`end`. If `n` <= 0, return a rank 1 array with length 0 The `type` and `kind` of the output is dependent on the `type` and `kind` of the passed parameters. For function calls where the `base` is not specified: `logspace(start, end)`/`logspace(start, end, n)`, the `type` and `kind` of the output follows the same scheme as above for `linspace`. >If `start`/`end` are `real` or `complex` types, the `result` will be the same type and kind as `start`/`end`. >If `start`/`end` are integer types, the `result` will default to a `real(dp)` array. For function calls where the `base` is specified, the `type` and `kind` of the result is in accordance with the following table: | `start`/`end` | `n` | `base` | `output` | | ------------- | --- | ------ | -------- | | `real(KIND)` | `Integer` | `real(KIND)` | `real(KIND)` | | " " | " " | `complex(KIND)` | `complex(KIND)` | | " " | " " | `Integer` | `real(KIND)` | | `complex(KIND)` | " " | `real(KIND)` | `complex(KIND)` | | " " | " " | `complex(KIND)` | `complex(KIND)` | | " " | " " | `Integer` | `complex(KIND)` | | `Integer` | " " | `real(KIND)` | `real(KIND)` | | " " | " " | `complex(KIND)` | `complex(KIND)` | | " " | " " | `Integer` | `Integer` | #### Examples ##### Example 1: Here inputs are of type `complex` and kind `dp`. `n` and `base` is not specified and thus default to 50 and 10, respectively. ```fortran {!example/math/example_logspace_complex.f90!} ``` ##### Example 2: Here inputs are of type `integer` and default kind. `base` is not specified and thus defaults to 10. ```fortran {!example/math/example_logspace_int.f90!} ``` ##### Example 3: Here `start`/`end` are of type `real` and double precision. `base` is type `complex` and also double precision. ```fortran {!example/math/example_logspace_rstart_cbase.f90!} ``` ### `arange` function #### Status Experimental #### Class Pure function. #### Description Creates a rank-1 `array` of the `integer/real` type with fixed-spaced values of given spacing, within a given interval. #### Syntax `result = ` [[stdlib_math(module):arange(interface)]] `(start [, end, step])` #### Arguments All arguments should be the same type and kind. `start`: Shall be an `integer/real` scalar. This is an `intent(in)` argument. The default `start` value is `1`. `end`: Shall be an `integer/real` scalar. This is an `intent(in)` and `optional` argument. The default `end` value is the inputted `start` value. `step`: Shall be an `integer/real` scalar and large than `0`. This is an `intent(in)` and `optional` argument. The default `step` value is `1`. ##### Warning If `step = 0`, the `step` argument will be corrected to `1/1.0` by the internal process of the `arange` function. If `step < 0`, the `step` argument will be corrected to `abs(step)` by the internal process of the `arange` function. #### Return value Returns a rank-1 `array` of fixed-spaced values. For `integer` type arguments, the length of the result vector is `(end - start)/step + 1`. For `real` type arguments, the length of the result vector is `floor((end - start)/step) + 1`. #### Example ```fortran {!example/math/example_math_arange.f90!} ``` ### `arg` function #### Status Experimental #### Class Elemental function. #### Description `arg` computes the phase angle (radian version) of `complex` scalar in the interval (-π,π]. The angles in `θ` are such that `z = abs(z)*exp((0.0, θ))`. #### Syntax `result = ` [[stdlib_math(module):arg(interface)]] `(z)` #### Arguments `z`: Shall be a `complex` scalar/array. This is an `intent(in)` argument. #### Return value Returns the `real` type phase angle (radian version) of the `complex` argument `z`. Notes: Although the angle of the complex number `0` is undefined, `arg((0,0))` returns the value `0`. #### Example ```fortran {!example/math/example_math_arg.f90!} ``` ### `argd` function #### Status Experimental #### Class Elemental function. #### Description `argd` computes the phase angle (degree version) of `complex` scalar in the interval (-180.0,180.0]. The angles in `θ` are such that `z = abs(z)*exp((0.0, θ*π/180.0))`. #### Syntax `result = ` [[stdlib_math(module):argd(interface)]] `(z)` #### Arguments `z`: Shall be a `complex` scalar/array. This is an `intent(in)` argument. #### Return value Returns the `real` type phase angle (degree version) of the `complex` argument `z`. Notes: Although the angle of the complex number `0` is undefined, `argd((0,0))` returns the value `0`. #### Example ```fortran {!example/math/example_math_argd.f90!} ``` ### `argpi` function #### Status Experimental #### Class Elemental function. #### Description `argpi` computes the phase angle (IEEE circular version) of `complex` scalar in the interval (-1.0,1.0]. The angles in `θ` are such that `z = abs(z)*exp((0.0, θ*π))`. #### Syntax `result = ` [[stdlib_math(module):argpi(interface)]] `(z)` #### Arguments `z`: Shall be a `complex` scalar/array. This is an `intent(in)` argument. #### Return value Returns the `real` type phase angle (circular version) of the `complex` argument `z`. Notes: Although the angle of the complex number `0` is undefined, `argpi((0,0))` returns the value `0`. #### Example ```fortran {!example/math/example_math_argpi.f90!} ``` ### `deg2rad` #### Status Experimental #### Class Elemenal function. #### Description `deg2rad` converts phase angles from degrees to radians. #### Syntax `result = ` [[stdlib_math(module):deg2rad(interface)]] `(theta)` #### Arguments `theta`: Shall be a `real` scalar/array. #### Return value Returns the `real` phase angle in radians. #### Example ```fortran {!example/math/example_math_deg2rad.f90!} ``` ### `rad2deg` #### Status Experimental #### Class Elemenal function. #### Description `rad2deg` converts phase angles from radians to degrees. #### Syntax `result = ` [[stdlib_math(module):rad2deg(interface)]] `(theta)` #### Arguments `theta`: Shall be a `real` scalar/array. #### Return value Returns the `real` phase angle in degrees. #### Example ```fortran {!example/math/example_math_rad2deg.f90!} ``` ### `is_close` function #### Description Returns a boolean scalar/array where two scalars/arrays are element-wise equal within a tolerance. ```fortran !> For `real` type is_close(a, b, rel_tol, abs_tol) = abs(a - b) <= max(rel_tol*(abs(a), abs(b)), abs_tol) !> and for `complex` type is_close(a, b, rel_tol, abs_tol) = is_close(a%re, b%re, rel_tol, abs_tol) .and. & is_close(a%im, b%im, rel_tol, abs_tol) ``` #### Syntax `bool = ` [[stdlib_math(module):is_close(interface)]] ` (a, b [, rel_tol, abs_tol, equal_nan])` #### Status Experimental. #### Class Elemental function. #### Arguments Note: All `real/complex` arguments must have same `kind`. If the value of `rel_tol/abs_tol` is negative (not recommended), it will be corrected to `abs(rel_tol/abs_tol)` by the internal process of `is_close`. `a`: Shall be a `real/complex` scalar/array. This argument is `intent(in)`. `b`: Shall be a `real/complex` scalar/array. This argument is `intent(in)`. `rel_tol`: Shall be a `real` scalar/array. This argument is `intent(in)` and `optional`, which is `sqrt(epsilon(..))` by default. `abs_tol`: Shall be a `real` scalar/array. This argument is `intent(in)` and `optional`, which is `0.0` by default. `equal_nan`: Shall be a `logical` scalar/array. This argument is `intent(in)` and `optional`, which is `.false.` by default. Whether to compare `NaN` values as equal. If `.true.`, `NaN` values in `a` will be considered equal to `NaN` values in `b`. #### Result value Returns a `logical` scalar/array. #### Example ```fortran {!example/math/example_math_is_close.f90!} ``` ### `all_close` function #### Description Returns a boolean scalar where two arrays are element-wise equal within a tolerance. #### Syntax `bool = ` [[stdlib_math(module):all_close(interface)]] ` (a, b [, rel_tol, abs_tol, equal_nan])` #### Status Experimental. #### Class Pure function. #### Arguments Note: All `real/complex` arguments must have same `kind`. If the value of `rel_tol/abs_tol` is negative (not recommended), it will be corrected to `abs(rel_tol/abs_tol)` by the internal process of `all_close`. `a`: Shall be a `real/complex` array. This argument is `intent(in)`. `b`: Shall be a `real/complex` array. This argument is `intent(in)`. `rel_tol`: Shall be a `real` scalar. This argument is `intent(in)` and `optional`, which is `sqrt(epsilon(..))` by default. `abs_tol`: Shall be a `real` scalar. This argument is `intent(in)` and `optional`, which is `0.0` by default. `equal_nan`: Shall be a `logical` scalar. This argument is `intent(in)` and `optional`, which is `.false.` by default. Whether to compare `NaN` values as equal. If `.true.`, `NaN` values in `a` will be considered equal to `NaN` values in `b`. #### Result value Returns a `logical` scalar. #### Example ```fortran {!example/math/example_math_all_close.f90!} ``` ### `diff` function #### Description Computes differences between adjacent elements of an array. #### Syntax For a rank-1 array: `y = ` [[stdlib_math(module):diff(interface)]] `(x [, n, prepend, append])` and for a rank-2 array: `y = ` [[stdlib_math(module):diff(interface)]] `(x [, n, dim, prepend, append])` #### Status Experimental. #### Class Pure function. #### Arguments `x`: The array to take a difference of. Shall be a `real/integer` and `rank-1/rank-2` array. This argument is `intent(in)`. `n`: How many times to iteratively calculate the difference. Shall be an `integer` scalar. This argument is `intent(in)` and `optional`, and has value of `1` by default. `dim`: The dimension of the input array along which to calculate the difference. Its value must be between `1` and `rank(x)`. Shall be an `integer` scalar. This argument is `intent(in)` and `optional` and has a value of `1` by default. `prepend`, `append`: Arrays to prepend or append to a along axis prior to performing the difference. The dimension and shape must match a except along axis. Shall be a `real/integer` and `rank-1/rank-2` array. This argument is `intent(in)` and `optional`, which is no value by default. Note: - The `x`, `prepend` and `append` arguments must have the same `type`, `kind` and `rank`. - If the value of `n` is less than or equal to `0` (which is not recommended), the return value of `diff` is `x`. - If the value of `dim` is not equal to `1` or `2` (which is not recommended), `1` will be used by the internal process of `diff`. #### Result value Returns the finite difference of the input array. Shall be a `real/integer` and `rank-1/rank-2` array. When both `prepend` and `append` are not present, the result `y` has one fewer element than `x` alongside the dimension `dim`. #### Example ```fortran {!example/math/example_diff.f90!} ``` ### `meshgrid` subroutine #### Description Computes a list of coordinate matrices from coordinate vectors. For $n \geq 1$ coordinate vectors $(x_1, x_2, ..., x_n)$ of sizes $(s_1, s_2, ..., s_n)$, `meshgrid` computes $n$ coordinate matrices $(X_1, X_2, ..., X_n)$ with identical shape corresponding to the selected indexing: - Cartesian indexing (default behavior): the shape of the coordinate matrices is $(s_2, s_1, s_3, s_4, ... s_n)$. - matrix indexing: the shape of the coordinate matrices is $(s_1, s_2, s_3, s_4, ... s_n)$. #### Syntax For a 2D problem in Cartesian indexing: `call ` [[stdlib_math(module):meshgrid(interface)]] `(x, y, xm, ym)` For a 3D problem in Cartesian indexing: `call ` [[stdlib_math(module):meshgrid(interface)]] `(x, y, z, xm, ym, zm)` For a 3D problem in matrix indexing: `call ` [[stdlib_math(module):meshgrid(interface)]] `(x, y, z, xm, ym, zm, indexing="ij")` The subroutine can be called in `n`-dimensional situations, as long as `n` is inferior to the maximum allowed array rank. #### Status Experimental. #### Class Subroutine. #### Arguments For a `n`-dimensional problem, with `n >= 1`: `x1, x2, ..., xn`: The coordinate vectors. Shall be `real/integer` and `rank-1` arrays. These arguments are `intent(in)`. `xm1, xm2, ..., xmn`: The coordinate matrices. Shall be arrays of type `real` or `integer` of adequate shape: - for Cartesian indexing, the shape of the coordinate matrices must be `[size(x2), size(x1), size(x3), ..., size(xn)]`. - for matrix indexing, the shape of the coordinate matrices must be `[size(x1), size(x2), size(x3), ..., size(xn)]`. These argument are `intent(out)`. `indexing`: the selected indexing. Shall be an `integer` equal to `stdlib_meshgrid_xy` for Cartesian indexing (default), or `stdlib_meshgrid_ij` for matrix indexing. `stdlib_meshgrid_xy` and `stdlib_meshgrid_ij` are public constants defined in the module. This argument is `intent(in)` and `optional`, and is equal to `stdlib_meshgrid_xy` by default. #### Example ```fortran {!example/math/example_meshgrid.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_string_type.md0000664000175000017500000007630015135654166024310 0ustar alastairalastair--- title: string_type --- # The `stdlib_string_type` module [TOC] ## Introduction The `stdlib_string_type` provides a derived type holding an arbitrary sequence of characters compatible with most Fortran intrinsic character procedures as well as operators for working with character variables and constants. ## Derived types provided ### The `string_type` derived type The `string_type` is defined as a non-extendible derived type representing a sequence of characters. The internal representation of the character sequence is implementation dependent and not visible for the user of the module. #### Status Experimental ## Procedures and methods provided Procedures returning `string_type` instances can usually be used in elemental context, while procedures returning scalar character values can only be used in a pure way. ### Constructor for empty string #### Status Experimental #### Description The module defines a constructor to create an empty string type. Creates a string instance representing an empty string. #### Syntax `res = ` [[stdlib_string_type(module):string_type(interface)]] ` ()` #### Class Elemental function. #### Argument None. #### Result value The result is an instance of `string_type` with zero length. #### Example ```fortran {!example/string_type/example_constructor_empty.f90!} ``` ### Constructor from character scalar #### Status Experimental #### Description The module defines a constructor to create a string type from a character scalar. Creates a string instance representing the input character scalar value. The constructor shall create an empty string if an unallocated deferred-length character variable is passed. #### Syntax `res = ` [[stdlib_string_type(module):string_type(interface)]] ` (string)` #### Class Elemental function. #### Argument `string`: shall be a scalar character value. It is an `intent(in)` argument. #### Result value The result is an instance of `string_type`. #### Example ```fortran {!example/string_type/example_constructor_scalar.f90!} ``` ### Constructor from integer scalar #### Status Experimental #### Description The module defines a constructor to create a string type from an integer scalar. #### Syntax `res = ` [[stdlib_string_type(module):string_type(interface)]] ` (string)` #### Class Elemental function. #### Argument `val`: shall be a scalar integer value. It is an `intent(in)` argument. #### Result value The result is an instance of `string_type`. #### Example ```fortran {!example/string_type/example_constructor_integer.f90!} ``` ### Constructor from logical scalar #### Status Experimental #### Description The module defines a constructor to create a string type from a logical scalar. #### Syntax `res = ` [[stdlib_string_type(module):string_type(interface)]] ` (string)` #### Class Elemental function. #### Argument `val`: shall be a scalar logical value. It is an `intent(in)` argument. #### Result value The result is an instance of `string_type`. #### Example ```fortran {!example/string_type/example_constructor_logical.f90!} ``` ### Assignment of character scalar #### Status Experimental #### Description The module defines an assignment operations, `=`, to create a string type from a character scalar. Creates a string instance representing the right-hand-side character scalar value. #### Syntax `lhs = rhs` #### Class Elemental subroutine, `assignment(=)`. #### Example ```fortran {!example/string_type/example_constructor_character.f90!} ``` ### Len function #### Status Experimental #### Description Returns the length of the string. #### Syntax `res = ` [[stdlib_string_type(module):len(interface)]] ` (string)` #### Class Elemental function. #### Argument `string`: Instance of a `string_type`. This argument is `intent(in)`. #### Result value The result is a default integer scalar value. #### Example ```fortran {!example/string_type/example_len.f90!} ``` ### Len\_trim function #### Status Experimental #### Description Returns the length of the character sequence without trailing spaces represented by the string. #### Syntax `res = ` [[stdlib_string_type(module):len_trim(interface)]] ` (string)` #### Class Elemental function. #### Argument `string`: Instance of a `string_type`. This argument is `intent(in)`. #### Result value The result is a default integer scalar value. #### Example ```fortran {!example/string_type/example_len_trim.f90!} ``` ### Trim function #### Status Experimental #### Description Returns the character sequence hold by the string without trailing spaces represented by a `string_type`. #### Syntax `res = ` [[stdlib_string_type(module):trim(interface)]] ` (string)` #### Class Elemental function. #### Argument - `string`: Instance of a `string_type`. This argument is `intent(in)`. #### Result value The result is a scalar `string_type` value. #### Example ```fortran {!example/string_type/example_trim.f90!} ``` ### Adjustl function #### Status Experimental #### Description Left-adjust the character sequence represented by the string. The length of the character sequence remains unchanged. #### Syntax `res = ` [[stdlib_string_type(module):adjustl(interface)]] ` (string)` #### Class Elemental function. #### Argument - `string`: Instance of a `string_type`. This argument is `intent(in)`. #### Result value The result is a scalar `string_type` value. #### Example ```fortran {!example/string_type/example_adjustl.f90!} ``` ### Adjustr function #### Status Experimental #### Description Right-adjust the character sequence represented by the string. The length of the character sequence remains unchanged. #### Syntax `res = ` [[stdlib_string_type(module):adjustr(interface)]] ` (string)` #### Class Elemental function. #### Argument - `string`: Instance of a `string_type`. This argument is `intent(in)`. #### Result value The result is a scalar `string_type` value. #### Example ```fortran {!example/string_type/example_adjustr.f90!} ``` ### Repeat function #### Status Experimental #### Description Repeats the character sequence hold by the string by the number of specified copies. #### Syntax `res = ` [[stdlib_string_type(module):repeat(interface)]] ` (string, ncopies)` #### Class Elemental function. #### Argument - `string`: Instance of a `string_type`. This argument is `intent(in)`. - `ncopies`: Integer of default type. This argument is `intent(in)`. #### Result value The result is a scalar `string_type` value. #### Example ```fortran {!example/string_type/example_repeat.f90!} ``` ### Char function #### Status Experimental #### Description Return the character sequence represented by the string. #### Syntax `res = ` [[stdlib_string_type(module):char(interface)]] ` (string)` #### Class Pure function. #### Argument - `string`: Instance of a `string_type`. This argument is `intent(in)`. #### Result value The result is a scalar character value. #### Example ```fortran {!example/string_type/example_char.f90!} ``` ### Char function (position variant) #### Status Experimental #### Description Return the character at a certain position in the string. #### Syntax `res = ` [[stdlib_string_type(module):char(interface)]] ` (string, pos)` #### Class Elemental function. #### Argument - `string`: Instance of a `string_type`. This argument is `intent(in)`. - `pos`: Integer of default type. This argument is `intent(in)`. #### Result value The result is a scalar character value. #### Example ```fortran {!example/string_type/example_char_position.f90!} ``` ### Char function (range variant) #### Status Experimental #### Description Return a substring from the character sequence of the string. #### Syntax `res = ` [[stdlib_string_type(module):char(interface)]] ` (string, start, last)` #### Class Pure function. #### Argument - `string`: Instance of a `string_type`. This argument is `intent(in)`. - `start`: Integer of default type. This argument is `intent(in)`. - `last`: Integer of default type. This argument is `intent(in)`. #### Result value The result is a scalar character value. #### Example ```fortran {!example/string_type/example_char_range.f90!} ``` ### Ichar function #### Status Experimental #### Description Character-to-integer conversion function. Returns the code for the character in the first character position of the character sequence in the system's native character set. #### Syntax `res = ` [[stdlib_string_type(module):ichar(interface)]] ` (string)` #### Class Elemental function. #### Argument - `string`: Instance of a `string_type`. This argument is `intent(in)`. #### Result value The result is a default integer scalar value. #### Example ```fortran {!example/string_type/example_ichar.f90!} ``` ### Iachar function #### Status Experimental #### Description Code in ASCII collating sequence. Returns the code for the ASCII character in the first character position of the character sequences represent by the string. #### Syntax `res = ` [[stdlib_string_type(module):iachar(interface)]] ` (string)` #### Class Elemental function. #### Argument - `string`: Instance of a `string_type`. This argument is `intent(in)`. #### Result value The result is a default integer scalar value. #### Example ```fortran {!example/string_type/example_iachar.f90!} ``` ### Index function #### Status Experimental #### Description Position of a *substring* within a *string*. Returns the position of the start of the leftmost or rightmost occurrence of string *substring* in *string*, counting from one. If *substring* is not present in *string*, zero is returned. #### Syntax `res = ` [[stdlib_string_type(module):index(interface)]] ` (string, substring[, back])` #### Class Elemental function. #### Argument - `string`: Either scalar character value or string type. This argument is `intent(in)`. - `substring`: Either scalar character value or string type. This argument is `intent(in)`. - `back`: Either absent or a scalar logical value. This argument is `intent(in)`. #### Result value The result is a default integer scalar value. #### Example ```fortran {!example/string_type/example_index.f90!} ``` ### Scan function #### Status Experimental #### Description Scans a *string* for the presence any of the characters in a *set* of characters. If *back* is either absent or *false*, this function returns the position of the leftmost character of *string* that is in *set*. If *back* is *true*, the rightmost position is returned. If no character of *set* is found in *string*, the result is zero. #### Syntax `res = ` [[stdlib_string_type(module):scan(interface)]] ` (string, set[, back])` #### Class Elemental function. #### Argument - `string`: Either scalar character value or string type. This argument is `intent(in)`. - `set`: Either scalar character value or string type. This argument is `intent(in)`. - `back`: Either absent or a scalar logical value. This argument is `intent(in)`. #### Result value The result is a default integer scalar value. #### Example ```fortran {!example/string_type/example_scan.f90!} ``` ### Verify function #### Status Experimental #### Description Verifies that all the characters in *string* belong to the set of characters in *set*. If *back* is either absent or *false*, this function returns the position of the leftmost character of *string* that is not in *set*. If *back* is *true*, the rightmost position is returned. If all characters of *string* are found in *set*, the result is zero. #### Syntax `res = ` [[stdlib_string_type(module):verify(interface)]] ` (string, set[, back])` #### Class Elemental function. #### Argument - `string`: Either scalar character value or string type. This argument is `intent(in)`. - `set`: Either scalar character value or string type. This argument is `intent(in)`. - `back`: Either absent or a scalar logical value. This argument is `intent(in)`. #### Result value The result is a default integer scalar value. #### Example ```fortran {!example/string_type/example_verify.f90!} ``` ### Lgt function (lexical greater than) #### Status Experimental #### Description Lexically compare the order of two character sequences being greater than. The left-hand side, the right-hand side or both character sequences can be represented by a string type. This defines three procedures overloading the intrinsic `lgt` procedure. #### Syntax `res = ` [[stdlib_string_type(module):lgt(interface)]] ` (lhs, rhs)` #### Class Elemental function. #### Argument - `lhs`: Either scalar character value or string type. This argument is `intent(in)`. - `rhs`: Either scalar character value or string type. This argument is `intent(in)`. #### Result value The result is a default logical scalar value. #### Example ```fortran {!example/string_type/example_lgt.f90!} ``` ### Llt function (lexical less than) #### Status Experimental #### Description Lexically compare the order of two character sequences being less than. The left-hand side, the right-hand side or both character sequences can be represented by a string type. This defines three procedures overloading the intrinsic `llt` procedure. #### Syntax `res = ` [[stdlib_string_type(module):llt(interface)]] ` (lhs, rhs)` #### Class Elemental function. #### Argument - `lhs`: Either scalar character value or string type. This argument is `intent(in)`. - `rhs`: Either scalar character value or string type. This argument is `intent(in)`. #### Result value The result is a default logical scalar value. #### Example ```fortran {!example/string_type/example_llt.f90!} ``` ### Lge function (lexical greater than or equal) #### Status Experimental #### Description Lexically compare the order of two character sequences being greater than or equal. The left-hand side, the right-hand side or both character sequences can be represented by a string type. This defines three procedures overloading the intrinsic `lge` procedure. #### Syntax `res = ` [[stdlib_string_type(module):lge(interface)]] ` (lhs, rhs)` #### Class Elemental function. #### Argument - `lhs`: Either scalar character value or string type. This argument is `intent(in)`. - `rhs`: Either scalar character value or string type. This argument is `intent(in)`. #### Result value The result is a default logical scalar value. #### Example ```fortran {!example/string_type/example_lge.f90!} ``` ### Lle function (lexical less than or equal) #### Status Experimental #### Description Lexically compare the order of two character sequences being less than or equal. The left-hand side, the right-hand side or both character sequences can be represented by a string type. This defines three procedures overloading the intrinsic `lle` procedure. #### Syntax `res = ` [[stdlib_string_type(module):lle(interface)]] ` (lhs, rhs)` #### Class Elemental function. #### Argument - `lhs`: Either scalar character value or string type. This argument is `intent(in)`. - `rhs`: Either scalar character value or string type. This argument is `intent(in)`. #### Result value The result is a default logical scalar value. #### Example ```fortran {!example/string_type/example_lle.f90!} ``` ### To\_lower function #### Status Experimental #### Description Returns a new string_type instance which holds the lowercase version of the character sequence hold by the input string. #### Syntax `lowercase_string = ` [[stdlib_string_type(module):to_lower(interface)]] ` (string)` #### Class Elemental function. #### Argument `string`: Instance of `string_type`. This argument is `intent(in)`. #### Result Value The result is a scalar `string_type` value. #### Example ```fortran {!example/string_type/example_to_lower.f90!} ``` ### To\_upper function #### Status Experimental #### Description Returns a new string_type instance which holds the uppercase version of the character sequence hold by the input string. #### Syntax `uppercase_string = ` [[stdlib_string_type(module):to_upper(interface)]] ` (string)` #### Class Elemental function. #### Argument `string`: Instance of `string_type`. This argument is `intent(in)`. #### Result Value The result is a scalar `string_type` value. #### Example ```fortran {!example/string_type/example_to_upper.f90!} ``` ### To\_title function #### Status Experimental #### Description Returns a new string_type instance which holds the titlecase version of the character sequence hold by the input string. Title case: First character of every word in the sentence is converted to uppercase and the rest of the characters are converted to lowercase. A word is a contiguous sequence of character(s) which consists of alphabetical character(s) and numeral(s) only and doesn't exclude any alphabetical character or numeral present next to either of its 2 ends. #### Syntax `titlecase_string = ` [[stdlib_string_type(module):to_title(interface)]] ` (string)` #### Class Elemental function. #### Argument `string`: Instance of `string_type`. This argument is `intent(in)`. #### Result Value The result is a scalar `string_type` value. #### Example ```fortran {!example/string_type/example_to_title.f90!} ``` ### To\_sentence function #### Status Experimental #### Description Returns a new string_type instance which holds the sentencecase version of the character sequence hold by the input string. Sentencecase version: The first alphabetical character of the input character sequence is transformed to uppercase unless it follows a numeral and the rest of the characters in the sequence are transformed to lowercase. #### Syntax `sentencecase_string = ` [[stdlib_string_type(module):to_sentence(interface)]] ` (string)` #### Class Elemental function. #### Argument `string`: Instance of `string_type`. This argument is `intent(in)`. #### Result Value The result is a scalar `string_type` value. #### Example ```fortran {!example/string_type/example_to_sentence.f90!} ``` ### Reverse function #### Status Experimental #### Description Returns a new string_type instance which holds the reversed version of the character sequence hold by the input string. #### Syntax `reverse_string = ` [[stdlib_string_type(module):reverse(interface)]] ` (string)` #### Class Elemental function. #### Argument `string`: Instance of `string_type`. This argument is `intent(in)`. #### Result Value The result is a scalar `string_type` value. #### Example ```fortran {!example/string_type/example_reverse.f90!} ``` ### Comparison operator greater #### Status Experimental #### Description Compare the order of two character sequences being greater. The left-hand side, the right-hand side or both character sequences can be represented by a string type. This defines three procedures overloading the intrinsic `operator(>)` and `operator(.gt.)`. #### Syntax `res = lhs > rhs` `res = lhs .gt. rhs` #### Class Elemental function, `operator(>)` and `operator(.gt.)`. #### Argument - `lhs`: Either scalar character value or string type. This argument is `intent(in)`. - `rhs`: Either scalar character value or string type. This argument is `intent(in)`. #### Result value The result is a default logical scalar value. #### Example ```fortran {!example/string_type/example_gt.f90!} ``` ### Comparison operator less #### Status Experimental #### Description Compare the order of two character sequences being less. The left-hand side, the right-hand side or both character sequences can be represented by a string type. This defines three procedures overloading the intrinsic `operator(<)` and `operator(.lt.)`. #### Syntax `res = lhs < rhs` `res = lhs .lt. rhs` #### Class Elemental function, `operator(<)` and `operator(.lt.)`. #### Argument - `lhs`: Either scalar character value or string type. This argument is `intent(in)`. - `rhs`: Either scalar character value or string type. This argument is `intent(in)`. #### Result value The result is a default logical scalar value. #### Example ```fortran {!example/string_type/example_lt.f90!} ``` ### Comparison operator greater or equal #### Status Experimental #### Description Compare the order of two character sequences being greater or equal. The left-hand side, the right-hand side or both character sequences can be represented by a string type. This defines three procedures overloading the intrinsic `operator(>=)` and `operator(.ge.)`. #### Syntax `res = lhs >= rhs` `res = lhs .ge. rhs` #### Class Elemental function, `operator(>=)` and `operator(.ge.)`. #### Argument - `lhs`: Either scalar character value or string type. This argument is `intent(in)`. - `rhs`: Either scalar character value or string type. This argument is `intent(in)`. #### Result value The result is a default logical scalar value. #### Example ```fortran {!example/string_type/example_ge.f90!} ``` ### Comparison operator less or equal #### Status Experimental #### Description Compare the order of two character sequences being less or equal. The left-hand side, the right-hand side or both character sequences can be represented by a string type. This defines three procedures overloading the intrinsic `operator(<=)` and `operator(.le.)`. #### Syntax `res = lhs <= rhs` `res = lhs .le. rhs` #### Class Elemental function, `operator(<=)` and `operator(.le.)`. #### Argument - `lhs`: Either scalar character value or string type. This argument is `intent(in)`. - `rhs`: Either scalar character value or string type. This argument is `intent(in)`. #### Result value The result is a default logical scalar value. #### Example ```fortran {!example/string_type/example_le.f90!} ``` ### Comparison operator equal #### Status Experimental #### Description Compare two character sequences for equality. The left-hand side, the right-hand side or both character sequences can be represented by a string type. This defines three procedures overloading the intrinsic `operator(==)` and `operator(.eq.)`. #### Syntax `res = lhs == rhs` `res = lhs .eq. rhs` #### Class Elemental function, `operator(==)` and `operator(.eq.)`. #### Argument - `lhs`: Either scalar character value or string type. This argument is `intent(in)`. - `rhs`: Either scalar character value or string type. This argument is `intent(in)`. #### Result value The result is a default logical scalar value. #### Example ```fortran {!example/string_type/example_eq.f90!} ``` ### Comparison operator not equal #### Status Experimental #### Description Compare two character sequences for inequality. The left-hand side, the right-hand side or both character sequences can be represented by a string type. This defines three procedures overloading the intrinsic `operator(/=)` and `operator(.ne.)`. #### Syntax `res = lhs /= rhs` `res = lhs .ne. rhs` #### Class Elemental function, `operator(/=)` and `operator(.ne.)`. #### Argument - `lhs`: Either scalar character value or string type. This argument is `intent(in)`. - `rhs`: Either scalar character value or string type. This argument is `intent(in)`. #### Result value The result is a default logical scalar value. #### Example ```fortran {!example/string_type/example_ne.f90!} ``` ### Concatenation operator #### Status Experimental #### Description Concatenate two character sequences. The left-hand side, the right-hand side or both character sequences can be represented by a string type. This defines three procedures overloading the intrinsic `operator(//)`. #### Syntax `res = lhs // rhs` #### Class Elemental function, `operator(//)`. #### Argument - `lhs`: Either scalar character value or string type. This argument is `intent(in)`. - `rhs`: Either scalar character value or string type. This argument is `intent(in)`. #### Result value The result is an instance of `string_type`. #### Example ```fortran {!example/string_type/example_cont.f90!} ``` ### Unformatted write #### Status Experimental #### Description Write the character sequence hold by the string to a connected unformatted unit. The character sequences is represented by an 64 bit signed integer record, holding the length of the following character record. #### Syntax `write(unit, iostat=iostat, iomsg=iomsg) string` #### Class Unformatted user defined derived type output. #### Argument - `string`: Instance of the string type to read. This argument is `intent(inout)`. - `unit`: Formatted unit for output. This argument is `intent(in)`. - `iostat`: Status identifier to indicate success of output operation. This argument is `intent(out)`. - `iomsg`: Buffer to return error message in case of failing output operation. This argument is `intent(inout)`. #### Example ```fortran {!example/string_type/example_uwrite.f90!} ``` ### Formatted write #### Status Experimental #### Description Write the character sequence hold by the string to a connected formatted unit. The current implementation is limited to list directed output and `dt` formatted output. Requesting namelist output will raise an error. #### Syntax `write(unit, fmt, iostat=iostat, iomsg=iomsg) string` #### Class Formatted user defined derived type output. #### Argument - `string`: Instance of the string type to read. This argument is `intent(inout)`. - `unit`: Formatted unit for output. This argument is `intent(in)`. - `iotype`: Type of formatted data transfer, has the value `"LISTDIRECTED"` for `fmt=*`, `"NAMELIST"` for namelist output or starts with `"DT"` for derived type output. This argument is `intent(in)`. - `v_list`: Rank one array of default integer type containing the edit descriptors for derived type output. This argument is `intent(in)`. - `iostat`: Status identifier to indicate success of output operation. This argument is `intent(out)`. - `iomsg`: Buffer to return error message in case of failing output operation. This argument is `intent(inout)`. #### Example ```fortran {!example/string_type/example_fwrite.f90!} ``` ### Unformatted read #### Status Experimental #### Description Read a character sequence from a connected unformatted unit into the string. The character sequences is represented by an 64 bit signed integer record, holding the length of the following character record. On failure the state the read variable is undefined and implementation dependent. #### Syntax `read(unit, iostat=iostat, iomsg=iomsg) string` #### Class Unformatted derived type input. #### Argument - `string`: Instance of the string type to read. This argument is `intent(inout)`. - `unit`: Formatted unit for input. This argument is `intent(in)`. - `iostat`: Status identifier to indicate success of input operation. This argument is `intent(out)`. - `iomsg`: Buffer to return error message in case of failing input operation. This argument is `intent(inout)`. #### Example ```fortran {!example/string_type/example_uread.f90!} ``` ### Formatted read #### Status Experimental #### Description Read a character sequence from a connected formatted unit into the string. List-directed input will retrieve the complete record into the string. On failure the state the read variable is undefined and implementation dependent. The current implementation is limited to list directed input. Requesting `dt` formatted input or namelist output will raise an error. #### Syntax `read(unit, fmt, iostat=iostat, iomsg=iomsg) string` #### Class Formatted derived type input. #### Argument - `string`: Instance of the string type to read. This argument is `intent(inout)`. - `unit`: Formatted unit for input. This argument is `intent(in)`. - `iotype`: Type of formatted data transfer, has the value `"LISTDIRECTED"` for `fmt=*`, `"NAMELIST"` for namelist input or starts with `"DT"` for derived type input. This argument is `intent(in)`. - `v_list`: Rank one array of default integer type containing the edit descriptors for derived type input. This argument is `intent(in)`. - `iostat`: Status identifier to indicate success of input operation. This argument is `intent(out)`. - `iomsg`: Buffer to return error message in case of failing input operation. This argument is `intent(inout)`. #### Example ```fortran {!example/string_type/example_fread.f90!} ``` ### move #### Status Experimental #### Description Moves the allocation from `from` to `to`, consequently deallocating `from` in this process. If `from` is not allocated before execution, `to` gets deallocated by the process. An unallocated `string_type` instance is equivalent to an empty string. If `from` and `to` are the same variable, then `from` remains unchanged. #### Syntax `call ` [[stdlib_string_type(module):move(interface)]] ` (from, to)` #### Class Pure subroutine (Elemental subroutine, only when both `from` and `to` are `type(string_type)`) #### Argument - `from`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is `intent(inout)`. - `to`: Character scalar or [[stdlib_string_type(module):string_type(type)]]. This argument is `intent(inout)` when both `from` and `to` are `type(string_type)`, otherwise `intent(out)`. #### Example ```fortran {!example/string_type/example_move.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_linalg.md0000664000175000017500000023226115135654166023207 0ustar alastairalastair--- title: linalg --- # Linear Algebra [TOC] The `stdlib` linear algebra library provides high-level APIs for dealing with common linear algebra operations. ## BLAS and LAPACK ### Status Experimental ### Description `BLAS` and `LAPACK` backends provide efficient low level implementations of many linear algebra algorithms, and are employed for non-trivial operators. A Modern Fortran version of the [Reference-LAPACK 3.10.1](http://github.com/reference-LAPACK) implementation is provided as a backend. Modern Fortran modules with full explicit typing features are provided after an [automated conversion](https://github.com/perazz/fortran-lapack/blob/main/scripts/modularize_blas.py) of the legacy codes: - [stdlib_linalg_blas(module)], [stdlib_linalg_lapack(module)] provide kind-agnostic interfaces to all functions. - Both libraries are available for 32- (`sp`), 64- (`dp`) and 128-bit (`qp`) `real` and `complex` numbers (the latter if available in the current build) - Free format, lower-case style - `implicit none(type, external)` applied to all procedures and modules - `intent` added and all `pure` procedures where possible - `stdlib` provides all procedures in two different flavors: (a) original BLAS/LAPACK names with a prefix `stdlib_?` (ex: `stdlib_dgemv`, `stdlib_sgemv`); (b) A generic, kind agnostic ``, i.e. `gemv`. - F77-style `parameter`s removed, and all numeric constants have been generalized with KIND-dependent Fortran intrinsics. - preprocessor-based OpenMP directives retained. The single-source module structure hopefully allows for cross-procedural inlining which is otherwise impossible without link-time optimization. When available, highly optimized libraries that take advantage of specialized processor instructions should be preferred over the `stdlib` implementation. Examples of such libraries are: OpenBLAS, MKL (TM), Accelerate, and ATLAS. In order to enable their usage, simply ensure that the following pre-processor macros are defined: - `STDLIB_EXTERNAL_BLAS` wraps all BLAS procedures (except for the 128-bit ones) to an external library - `STDLIB_EXTERNAL_LAPACK` wraps all LAPACK procedures (except for the 128-bit ones) to an external library These can be enabled during the build process. For example, with CMake, one can enable these preprocessor directives using `add_compile_definitions(STDLIB_EXTERNAL_BLAS STDLIB_EXTERNAL_LAPACK)`. The same is possible from the `fpm` branch, where the `cpp` preprocessor is enabled by default. For example, the macros can be added to the project's manifest: ```toml # Link against appropriate external BLAS and LAPACK libraries, if necessary [build] link = ["blas", "lapack"] [dependencies] stdlib="*" # Macros are only needed if using an external library [preprocess] [preprocess.cpp] macros = ["STDLIB_EXTERNAL_BLAS", "STDLIB_EXTERNAL_LAPACK"] ``` or directly via compiler flags: `fpm build --flag "-DSTDLIB_EXTERNAL_BLAS -DSTDLIB_EXTERNAL_LAPACK -lblas -llapack"`. ### Syntax All procedures in the `BLAS` and `LAPACK` backends follow the standard interfaces from the [Reference LAPACK](https://www.netlib.org/lapack/). So, the online [Users Guide](https://www.netlib.org/lapack/explore-html/) should be consulted for the full API and descriptions of procedure arguments and their usage. The `stdlib` implementation makes both kind-agnostic and specific procedure interfaces available via modules [stdlib_linalg_blas(module)] and [stdlib_linalg_lapack(module)]. Because all procedures start with a letter [that indicates the base datatype](https://www.netlib.org/lapack/lug/node24.html), the `stdlib` generic interface drops the heading letter and contains all kind-dependent implementations. For example, the generic interface to the `axpy` function looks like: ```fortran !> AXPY: constant times a vector plus a vector. interface axpy module procedure stdlib_saxpy module procedure stdlib_daxpy module procedure stdlib_qaxpy module procedure stdlib_caxpy module procedure stdlib_zaxpy module procedure stdlib_waxpy end interface axpy ``` The generic interface is the endpoint for using an external library. Whenever the latter is used, references to the internal `module procedure`s are replaced with interfaces to the external library, for example: ```fortran !> AXPY: constant times a vector plus a vector. interface axpy pure subroutine caxpy(n,ca,cx,incx,cy,incy) import sp,dp,qp,ilp,lk implicit none complex(sp), intent(in) :: ca,cx(*) integer(ilp), intent(in) :: incx,incy,n complex(sp), intent(inout) :: cy(*) end subroutine caxpy ! [....] module procedure stdlib_qaxpy end interface axpy ``` Note that the 128-bit functions are only provided by `stdlib` and always point to the internal implementation. Because 128-bit precision is identified as [stdlib_kinds(module):qp], initials for 128-bit procedures were labelled as `q` (quadruple-precision reals) and `w` ("wide" or quadruple-precision complex numbers). Extended precision ([stdlib_kinds(module):xdp]) calculations are labelled as `x` (extended-precision reals). and `y` (extended-precision complex numbers). ### Example ```fortran {!example/linalg/example_blas_gemv.f90!} ``` ```fortran {!example/linalg/example_lapack_getrf.f90!} ``` ### Licensing The Fortran Standard Library is distributed under the MIT License. `LAPACK` and its contained `BLAS` are a freely-available software package. They are available from [netlib](https://www.netlib.org/lapack/) via anonymous ftp and the World Wide Web. Thus, they can be included in commercial software packages (and have been). The license used for the `BLAS` and `LAPACK` backends is the [modified BSD license](https://www.netlib.org/lapack/LICENSE.txt). The header of the `LICENSE.txt` file has as its licensing requirements: Copyright (c) 1992-2013 The University of Tennessee and The University of Tennessee Research Foundation. All rights reserved. Copyright (c) 2000-2013 The University of California Berkeley. All rights reserved. Copyright (c) 2006-2013 The University of Colorado Denver. All rights reserved. $COPYRIGHT$ Additional copyrights may follow $HEADER$ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer listed in this license in the documentation and/or other materials provided with the distribution. - Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. The copyright holders provide no reassurances that the source code provided does not infringe any patent, copyright, or any other intellectual property rights of third parties. The copyright holders disclaim any liability to any recipient for claims brought against recipient by any third party for infringement of that parties intellectual property rights. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. So the license for the `LICENSE.txt` code is compatible with the use of modified versions of the code in the Fortran Standard Library under the MIT license. Credit for the `BLAS`, `LAPACK` libraries should be given to the [LAPACK authors](https://www.netlib.org/lapack/contributor-list.html). According to the original license, we also changed the name of the routines and commented the changes made to the original. ## `diag` - Create a diagonal array or extract the diagonal elements of an array ### Status Stable ### Class Pure function. ### Description Create a diagonal array or extract the diagonal elements of an array ### Syntax `d = ` [[stdlib_linalg(module):diag(interface)]] `(a [, k])` ### Arguments `a`: Shall be a rank-1 or or rank-2 array. If `a` is a rank-1 array (i.e. a vector) then `diag` returns a rank-2 array with the elements of `a` on the diagonal. If `a` is a rank-2 array (i.e. a matrix) then `diag` returns a rank-1 array of the diagonal elements. `k` (optional): Shall be a scalar of type `integer` and specifies the diagonal. The default `k = 0` represents the main diagonal, `k > 0` are diagonals above the main diagonal, `k < 0` are diagonals below the main diagonal. ### Return value Returns a diagonal array or a vector with the extracted diagonal elements. ### Example ```fortran {!example/linalg/example_diag1.f90!} ``` ```fortran {!example/linalg/example_diag2.f90!} ``` ```fortran {!example/linalg/example_diag3.f90!} ``` ```fortran {!example/linalg/example_diag4.f90!} ``` ```fortran {!example/linalg/example_diag5.f90!} ``` ## `eye` - Construct the identity matrix ### Status Stable ### Class Pure function. ### Description Constructs the identity matrix. ### Syntax `I = ` [[stdlib_linalg(module):eye(function)]] `(dim1 [, dim2] [, mold])` ### Arguments - `dim1`: A scalar of type `integer`. This is an `intent(in)` argument and specifies the number of rows. - `dim2`: A scalar of type `integer`. This is an optional `intent(in)` argument specifying the number of columns. If not provided, the matrix is square (`dim1 = dim2`). - `mold`: A scalar of any supported `integer`, `real`, or `complex` type. This is an optional `intent(in)` argument. If provided, the returned identity matrix will have the same type and kind as `mold`. If not provided, the matrix will be of type `real(real64)` by default. ### Return value Returns the identity matrix, with ones on the main diagonal and zeros elsewhere. - By default, the return value is of type `real(real64)`, which is recommended for arithmetic safety. - If the `mold` argument is provided, the return value will match the type and kind of `mold`, allowing for arbitrary `integer`, `real`, or `complex` return types. ### Example ```fortran !> Return default type (real64) A = eye(2,2)/2 !! A == diag([0.5_dp, 0.5_dp]) !> Return 32-bit complex A = eye(2,2, mold=(0.0,0.0))/2 !! A == diag([(0.5,0.5), (0.5,0.5)]) ``` ```fortran {!example/linalg/example_eye1.f90!} ``` ```fortran {!example/linalg/example_eye2.f90!} ``` ## `trace` - Trace of a matrix ### Status Stable ### Description Trace of a matrix (rank-2 array) ### Syntax `result = ` [[stdlib_linalg(module):trace(interface)]] `(A)` ### Arguments `A`: Shall be a rank-2 array. If `A` is not square, then `trace(A)` will return the sum of diagonal values from the square sub-section of `A`. ### Return value Returns the trace of the matrix, i.e. the sum of diagonal elements. ### Example ```fortran {!example/linalg/example_trace.f90!} ``` ## `outer_product` - Computes the outer product of two vectors ### Status Experimental ### Description Computes the outer product of two vectors ### Syntax `d = ` [[stdlib_linalg(module):outer_product(interface)]] `(u, v)` ### Arguments `u`: Shall be a rank-1 array `v`: Shall be a rank-1 array ### Return value Returns a rank-2 array equal to `u v^T` (where `u, v` are considered column vectors). The shape of the returned array is `[size(u), size(v)]`. ### Example ```fortran {!example/linalg/example_outer_product.f90!} ``` ## `kronecker_product` - Computes the Kronecker product of two rank-2 arrays ### Status Experimental ### Description Computes the Kronecker product of two rank-2 arrays ### Syntax `C = ` [[stdlib_linalg(module):kronecker_product(interface)]] `(A, B)` ### Arguments `A`: Shall be a rank-2 array with dimensions M1, N1 `B`: Shall be a rank-2 array with dimensions M2, N2 ### Return value Returns a rank-2 array equal to `A \otimes B`. The shape of the returned array is `[M1*M2, N1*N2]`. ### Example ```fortran {!example/linalg/example_kronecker_product.f90!} ``` ## `cross_product` - Computes the cross product of two vectors ### Status Experimental ### Description Computes the cross product of two vectors ### Syntax `c = ` [[stdlib_linalg(module):cross_product(interface)]] `(a, b)` ### Arguments `a`: Shall be a rank-1 and size-3 array `b`: Shall be a rank-1 and size-3 array ### Return value Returns a rank-1 and size-3 array which is perpendicular to both `a` and `b`. ### Example ```fortran {!example/linalg/example_cross_product.f90!} ``` ## `is_square` - Checks if a matrix is square ### Status Experimental ### Description Checks if a matrix is square ### Syntax `d = ` [[stdlib_linalg(module):is_square(interface)]] `(A)` ### Arguments `A`: Shall be a rank-2 array ### Return value Returns a `logical` scalar that is `.true.` if the input matrix is square, and `.false.` otherwise. ### Example ```fortran {!example/linalg/example_is_square.f90!} ``` ## `is_diagonal` - Checks if a matrix is diagonal ### Status Experimental ### Description Checks if a matrix is diagonal ### Syntax `d = ` [[stdlib_linalg(module):is_diagonal(interface)]] `(A)` ### Arguments `A`: Shall be a rank-2 array ### Return value Returns a `logical` scalar that is `.true.` if the input matrix is diagonal, and `.false.` otherwise. Note that nonsquare matrices may be diagonal, so long as `a_ij = 0` when `i /= j`. ### Example ```fortran {!example/linalg/example_is_diagonal.f90!} ``` ## `is_symmetric` - Checks if a matrix is symmetric ### Status Experimental ### Description Checks if a matrix is symmetric ### Syntax `d = ` [[stdlib_linalg(module):is_symmetric(interface)]] `(A)` ### Arguments `A`: Shall be a rank-2 array ### Return value Returns a `logical` scalar that is `.true.` if the input matrix is symmetric, and `.false.` otherwise. ### Example ```fortran {!example/linalg/example_is_symmetric.f90!} ``` ## `is_skew_symmetric` - Checks if a matrix is skew-symmetric ### Status Experimental ### Description Checks if a matrix is skew-symmetric ### Syntax `d = ` [[stdlib_linalg(module):is_skew_symmetric(interface)]] `(A)` ### Arguments `A`: Shall be a rank-2 array ### Return value Returns a `logical` scalar that is `.true.` if the input matrix is skew-symmetric, and `.false.` otherwise. ### Example ```fortran {!example/linalg/example_is_skew_symmetric.f90!} ``` ## `hermitian` - Compute the Hermitian version of a rank-2 matrix ### Status Experimental ### Description Compute the Hermitian version of a rank-2 matrix. For `complex` matrices, the function returns the conjugate transpose (`conjg(transpose(a))`). For `real` or `integer` matrices, the function returns the transpose (`transpose(a)`). ### Syntax `h = ` [[stdlib_linalg(module):hermitian(interface)]] `(a)` ### Arguments `a`: Shall be a rank-2 array of type `integer`, `real`, or `complex`. The input matrix `a` is not modified. ### Return value Returns a rank-2 array of the same shape and type as `a`. If `a` is of type `complex`, the Hermitian matrix is computed as `conjg(transpose(a))`. For `real` or `integer` types, it is equivalent to the intrinsic `transpose(a)`. ### Example ```fortran {!example/linalg/example_hermitian.f90!} ``` ## `is_hermitian` - Checks if a matrix is Hermitian ### Status Experimental ### Description Checks if a matrix is Hermitian ### Syntax `d = ` [[stdlib_linalg(module):is_hermitian(interface)]] `(A)` ### Arguments `A`: Shall be a rank-2 array ### Return value Returns a `logical` scalar that is `.true.` if the input matrix is Hermitian, and `.false.` otherwise. ### Example ```fortran {!example/linalg/example_is_hermitian.f90!} ``` ## `is_triangular` - Checks if a matrix is triangular ### Status Experimental ### Description Checks if a matrix is triangular ### Syntax `d = ` [[stdlib_linalg(module):is_triangular(interface)]] `(A,uplo)` ### Arguments `A`: Shall be a rank-2 array `uplo`: Shall be a single character from `{'u','U','l','L'}` ### Return value Returns a `logical` scalar that is `.true.` if the input matrix is the type of triangular specified by `uplo` (upper or lower), and `.false.` otherwise. Note that the definition of triangular used in this implementation allows nonsquare matrices to be triangular. Specifically, upper triangular matrices satisfy `a_ij = 0` when `j < i`, and lower triangular matrices satisfy `a_ij = 0` when `j > i`. ### Example ```fortran {!example/linalg/example_is_triangular.f90!} ``` ## `is_hessenberg` - Checks if a matrix is hessenberg ### Status Experimental ### Description Checks if a matrix is Hessenberg ### Syntax `d = ` [[stdlib_linalg(module):is_hessenberg(interface)]] `(A,uplo)` ### Arguments `A`: Shall be a rank-2 array `uplo`: Shall be a single character from `{'u','U','l','L'}` ### Return value Returns a `logical` scalar that is `.true.` if the input matrix is the type of Hessenberg specified by `uplo` (upper or lower), and `.false.` otherwise. Note that the definition of Hessenberg used in this implementation allows nonsquare matrices to be Hessenberg. Specifically, upper Hessenberg matrices satisfy `a_ij = 0` when `j < i-1`, and lower Hessenberg matrices satisfy `a_ij = 0` when `j > i+1`. ### Example ```fortran {!example/linalg/example_is_hessenberg.f90!} ``` ## `solve` - Solves a linear matrix equation or a linear system of equations. ### Status Stable ### Description This function computes the solution to a linear matrix equation \( A \cdot x = b \), where \( A \) is a square, full-rank, `real` or `complex` matrix. Result vector or array `x` returns the exact solution to within numerical precision, provided that the matrix is not ill-conditioned. An error is returned if the matrix is rank-deficient or singular to working precision. The solver is based on LAPACK's `*GESV` backends. ### Syntax `Pure` interface: `x = ` [[stdlib_linalg(module):solve(interface)]] `(a, b)` Expert interface: `x = ` [[stdlib_linalg(module):solve(interface)]] `(a, b [, overwrite_a], err)` ### Arguments `a`: Shall be a rank-2 `real` or `complex` square array containing the coefficient matrix. It is normally an `intent(in)` argument. If `overwrite_a=.true.`, it is an `intent(inout)` argument and is destroyed by the call. `b`: Shall be a rank-1 or rank-2 array of the same kind as `a`, containing the right-hand-side vector(s). It is an `intent(in)` argument. `overwrite_a` (optional): Shall be an input logical flag. if `.true.`, input matrix `a` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. The function is not `pure` if this argument is provided. ### Return value For a full-rank matrix, returns an array value that represents the solution to the linear system of equations. Raises `LINALG_ERROR` if the matrix is singular to working precision. Raises `LINALG_VALUE_ERROR` if the matrix and rhs vectors have invalid/incompatible sizes. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_solve1.f90!} {!example/linalg/example_solve2.f90!} ``` ## `solve_lu` - Solves a linear matrix equation or a linear system of equations (subroutine interface). ### Status Stable ### Description This subroutine computes the solution to a linear matrix equation \( A \cdot x = b \), where \( A \) is a square, full-rank, `real` or `complex` matrix. Result vector or array `x` returns the exact solution to within numerical precision, provided that the matrix is not ill-conditioned. An error is returned if the matrix is rank-deficient or singular to working precision. If all optional arrays are provided by the user, no internal allocations take place. The solver is based on LAPACK's `*GESV` backends. ### Syntax Simple (`Pure`) interface: `call ` [[stdlib_linalg(module):solve_lu(interface)]] `(a, b, x)` Expert (`Pure`) interface: `call ` [[stdlib_linalg(module):solve_lu(interface)]] `(a, b, x [, pivot, overwrite_a, err])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` square array containing the coefficient matrix. It is normally an `intent(in)` argument. If `overwrite_a=.true.`, it is an `intent(inout)` argument and is destroyed by the call. `b`: Shall be a rank-1 or rank-2 array of the same kind as `a`, containing the right-hand-side vector(s). It is an `intent(in)` argument. `x`: Shall be a rank-1 or rank-2 array of the same kind and size as `b`, that returns the solution(s) to the system. It is an `intent(inout)` argument, and must have the `contiguous` property. `pivot` (optional): Shall be a rank-1 array of the same kind and matrix dimension as `a`, providing storage for the diagonal pivot indices. It is an `intent(inout)` arguments, and returns the diagonal pivot indices. `overwrite_a` (optional): Shall be an input logical flag. if `.true.`, input matrix `a` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return value For a full-rank matrix, returns an array value that represents the solution to the linear system of equations. Raises `LINALG_ERROR` if the matrix is singular to working precision. Raises `LINALG_VALUE_ERROR` if the matrix and rhs vectors have invalid/incompatible sizes. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_solve3.f90!} ``` ## `lstsq` - Computes the least squares solution to a linear matrix equation. ### Status Stable ### Description This function computes the least-squares solution to a linear matrix equation \( A \cdot x = b \). Result vector `x` returns the approximate solution that minimizes the 2-norm \( || A \cdot x - b ||_2 \), i.e., it contains the least-squares solution to the problem. Matrix `A` may be full-rank, over-determined, or under-determined. The solver is based on LAPACK's `*GELSD` backends. ### Syntax `x = ` [[stdlib_linalg(module):lstsq(interface)]] `(a, b, [, cond, overwrite_a, rank, err])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` array containing the coefficient matrix. It is an `intent(inout)` argument. `b`: Shall be a rank-1 or rank-2 array of the same kind as `a`, containing one or more right-hand-side vector(s), each in its leading dimension. It is an `intent(in)` argument. `cond` (optional): Shall be a scalar `real` value cut-off threshold for rank evaluation: `s_i >= cond*maxval(s), i=1:rank`. Shall be a scalar, `intent(in)` argument. `overwrite_a` (optional): Shall be an input `logical` flag. If `.true.`, input matrix `A` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument. `rank` (optional): Shall be an `integer` scalar value, that contains the rank of input matrix `A`. This is an `intent(out)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return value Returns an array value of the same kind and rank as `b`, containing the solution(s) to the least squares system. Raises `LINALG_ERROR` if the underlying Singular Value Decomposition process did not converge. Raises `LINALG_VALUE_ERROR` if the matrix and right-hand-side vector have invalid/incompatible sizes. Exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_lstsq1.f90!} ``` ## `solve_lstsq` - Compute the least squares solution to a linear matrix equation (subroutine interface). ### Status Stable ### Description This subroutine computes the least-squares solution to a linear matrix equation \( A \cdot x = b \). Result vector `x` returns the approximate solution that minimizes the 2-norm \( || A \cdot x - b ||_2 \), i.e., it contains the least-squares solution to the problem. Matrix `A` may be full-rank, over-determined, or under-determined. The solver is based on LAPACK's `*GELSD` backends. ### Syntax `call ` [[stdlib_linalg(module):solve_lstsq(interface)]] `(a, b, x, [, real_storage, int_storage, [cmpl_storage, ] cond, singvals, overwrite_a, rank, err])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` array containing the coefficient matrix. It is an `intent(inout)` argument. `b`: Shall be a rank-1 or rank-2 array of the same kind as `a`, containing one or more right-hand-side vector(s), each in its leading dimension. It is an `intent(in)` argument. `x`: Shall be an array of same kind and rank as `b`, and leading dimension of at least `n`, containing the solution(s) to the least squares system. It is an `intent(inout)` argument. `real_storage` (optional): Shall be a `real` rank-1 array of the same kind `a`, providing working storage for the solver. It minimum size can be determined with a call to [[stdlib_linalg(module):lstsq_space(interface)]]. It is an `intent(inout)` argument. `int_storage` (optional): Shall be an `integer` rank-1 array, providing working storage for the solver. It minimum size can be determined with a call to [[stdlib_linalg(module):lstsq_space(interface)]]. It is an `intent(inout)` argument. `cmpl_storage` (optional): For `complex` systems, it shall be a `complex` rank-1 array, providing working storage for the solver. It minimum size can be determined with a call to [[stdlib_linalg(module):lstsq_space(interface)]]. It is an `intent(inout)` argument. `cond` (optional): Shall be a scalar `real` value cut-off threshold for rank evaluation: `s_i >= cond*maxval(s), i=1:rank`. Shall be a scalar, `intent(in)` argument. `singvals` (optional): Shall be a `real` rank-1 array of the same kind `a` and size at least `min(m,n)`, returning the list of singular values `s(i)>=cond*maxval(s)` from the internal SVD, in descending order of magnitude. It is an `intent(out)` argument. `overwrite_a` (optional): Shall be an input `logical` flag. If `.true.`, input matrix `A` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument. `rank` (optional): Shall be an `integer` scalar value, that contains the rank of input matrix `A`. This is an `intent(out)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return value Returns an array value that represents the solution to the least squares system. Raises `LINALG_ERROR` if the underlying Singular Value Decomposition process did not converge. Raises `LINALG_VALUE_ERROR` if the matrix and right-hand-side vector have invalid/incompatible sizes. Exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_lstsq2.f90!} ``` ## `lstsq_space` - Compute internal working space requirements for the least squares solver. ### Status Stable ### Description This subroutine computes the internal working space requirements for the least-squares solver, [[stdlib_linalg(module):solve_lstsq(interface)]] . ### Syntax `call ` [[stdlib_linalg(module):lstsq_space(interface)]] `(a, b, lrwork, liwork [, lcwork])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` array containing the linear system coefficient matrix. It is an `intent(in)` argument. `b`: Shall be a rank-1 or rank-2 array of the same kind as `a`, containing the system's right-hand-side vector(s). It is an `intent(in)` argument. `lrwork`: Shall be an `integer` scalar, that returns the minimum array size required for the `real` working storage to this system. `liwork`: Shall be an `integer` scalar, that returns the minimum array size required for the `integer` working storage to this system. `lcwork` (`complex` `a`, `b`): For a `complex` system, shall be an `integer` scalar, that returns the minimum array size required for the `complex` working storage to this system. ## `constrained_lstsq` - Compute the solution of the equality-constrained least-squares problem {#constrained-lstsq} ### Status Experimental ### Description This function computes the solution \(x\) of the equality-constrained linear least-squares problem $$ \begin{aligned} \mathrm{minimize} & \quad \| Ax - b \|^2 \\ \mathrm{subject~to} & \quad Cx = d, \end{aligned} $$ where \(A\) is an \( m \times n \) matrix (with \(m \geq n\)) and \(C\) a \( p \times n\) matrix (with \(p \leq n\)). The solver is based on LAPACK's `*GLSE` backends. ### Syntax `x = ` [[stdlib_linalg(module):constrained_lstsq(interface)]] `(A, b, C, d[, overwrite_matrices, err])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` array used in the definition of the least-squares cost. It is an `intent(inout)` argument. `b`: Shall be a rank-1 array of the same kind as `a` appearing in the definition of the least-squares cost. It is an `intent(inout)` argument. `c`: Shall be a rank-2 `real` or `complex` array of the same kind as `a` defining the linear equality constraints. It is an `intent(inout)` argument. `d`: Shall be a rank-1 array of the same kind as `a` appearing in the definition of the linear equality constraints. `overwrite_matrices` (optional): Shall be an input `logical` flag. If `.true.`, the input matrices and vectors will be overwritten during the computation of the solution. It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return value Returns an array of the same kind as `a` containing the solution of the equality constrained least-squares problem. Raises `LINALG_ERROR` if the underlying constrained least-squares solver did not converge. Raises `LINALG_VALUE_ERROR` if the matrices and vectors have invalid/incompatible dimensions. Exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_constrained_lstsq1.f90!} ``` ## `solve_constrained_lstsq` - Compute the solution of the equality-constrained least squares problem (subroutine interface) {#solve-constrained-lstsq} ### Status Experimental ### Description This subroutine computes the solution \(x\) of the equality-constrained linear least-squares problem $$ \begin{aligned} \mathrm{minimize} & \quad \| Ax - b \|^2 \\ \mathrm{subject~to} & \quad Cx = d, \end{aligned} $$ where \(A\) is an \( m \times n \) matrix (with \(m \geq n\)) and \(C\) a \( p \times n\) matrix (with \(p \leq n\)). The solver is based on LAPACK's `*GLSE` backends. ### Syntax `call ` [[stdlib_linalg(module):solve_constrained_lstsq(interface)]] `(a, b, c, d, x [, storage, overwrite_matrices, err])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` array used in the definition of the least-squares cost. It is an `intent(inout)` argument. `b`: Shall be a rank-1 array of the same kind as `a` appearing in the definition of the least-squares cost. It is an `intent(inout)` argument. `c`: Shall be a rank-2 `real` or `complex` array of the same kind as `a` defining the linear equality constraints. It is an `intent(inout)` argument. `d`: Shall be a rank-1 array of the same kind as `a` appearing in the definition of the linear equality constraints. `x`: Shall be a rank-1 array of the same kind as `a`. On exit, it contains the solution of the constrained least-squares problem. It is an `intent(out)` argument. `storage` (optional): Shall be a rank-1 array of the same kind as `a` providing working storage for the solver. Its minimum size can be determined with a call to [stdlib_linalg(module):constrained_lstsq_space(interface)]. It is an `intent(out)` argument. `overwrite_matrices` (optional): Shall be an input `logical` flag. If `.true.`, the input matrices and vectors will be overwritten during the computation of the solution. It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Example ```fortran {!example/linalg/example_constrained_lstsq2.f90!} ``` ## `constrained_lstsq_space` - Compute internal workspace requirements for the constrained least-square solver {#constrained-lstsq-space} ### Status Experimental ### Description This subroutine computes the internal workspace requirements for the constrained least-squares solver, [stdlib_linalg(module):solve_constrained_lstsq(interface)]. ### Syntax call [stdlib_linalg(module):constrained_lstsq_space(interface)]`(a, c, lwork [, err])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` array used in the definition of the least-squares cost. It is an `intent(in)` argument. `c`: Shall be a rank-2 `real` or `complex` array of the same kind as `a` defining the linear equality constraints. It is an `intent(in)` argument. `lwork`: Shall be an `integer` scalar returning the optimal size required for the workspace array to solve the constrained least-squares problem. ## `det` - Computes the determinant of a square matrix ### Status Stable ### Description This function computes the determinant of a `real` or `complex` square matrix. This interface comes with a `pure` version `det(a)`, and a non-pure version `det(a,overwrite_a,err)` that allows for more expert control. ### Syntax `c = ` [[stdlib_linalg(module):det(interface)]] `(a [, overwrite_a, err])` ### Arguments `a`: Shall be a rank-2 square array `overwrite_a` (optional): Shall be an input `logical` flag. if `.true.`, input matrix `a` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return value Returns a `real` scalar value of the same kind of `a` that represents the determinant of the matrix. Raises `LINALG_ERROR` if the matrix is singular. Raises `LINALG_VALUE_ERROR` if the matrix is non-square. Exceptions are returned to the `err` argument if provided; an `error stop` is triggered otherwise. ### Example ```fortran {!example/linalg/example_determinant.f90!} ``` ## `.det.` - Determinant operator of a square matrix ### Status Stable ### Description This operator returns the determinant of a real square matrix. This interface is equivalent to the `pure` version of determinant [[stdlib_linalg(module):det(interface)]]. ### Syntax `c = ` [[stdlib_linalg(module):operator(.det.)(interface)]] `a` ### Arguments `a`: Shall be a rank-2 square array of any `real` or `complex` kinds. It is an `intent(in)` argument. ### Return value Returns a real scalar value that represents the determinant of the matrix. Raises `LINALG_ERROR` if the matrix is singular. Raises `LINALG_VALUE_ERROR` if the matrix is non-square. Exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_determinant2.f90!} ``` ## `qr` - Compute the QR factorization of a matrix ### Status Experimental ### Description This subroutine computes the QR factorization of a `real` or `complex` matrix: \( A = Q R \) where \( Q \) is orthonormal and \( R \) is upper-triangular. Matrix \( A \) has size `[m,n]`, with \( m \ge n \). The results are returned in output matrices \( Q \) and \(R \), that have the same type and kind as \( A \). Given `k = min(m,n)`, one can write \( A = \( Q_1 Q_2 \) \cdot \( \frac{R_1}{0}\) \). Because the lower rows of \( R \) are zeros, a reduced problem \( A = Q_1 R_1 \) may be solved. The size of the input arguments determines what problem is solved: on full matrices (`shape(Q)==[m,m]`, `shape(R)==[m,n]`), the full problem is solved. On reduced matrices (`shape(Q)==[m,k]`, `shape(R)==[k,n]`), the reduced problem is solved. ### Syntax `call ` [[stdlib_linalg(module):qr(interface)]] `(a, q, r [, pivots] [, overwrite_a] [, storage] [, err])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` array containing the coefficient matrix of size `[m,n]`. It is an `intent(in)` argument, if `overwrite_a=.false.`. Otherwise, it is an `intent(inout)` argument, and is destroyed upon return. `q`: Shall be a rank-2 array of the same kind as `a`, containing the orthonormal matrix `q`. It is an `intent(out)` argument. It should have a shape equal to either `[m,m]` or `[m,k]`, whether the full or the reduced problem is sought for. `r`: Shall be a rank-2 array of the same kind as `a`, containing the upper triangular matrix `r`. It is an `intent(out)` argument. It should have a shape equal to either `[m,n]` or `[k,n]`, whether the full or the reduced problem is sought for. `pivots` (optional): Shall be an `integer` array of size `n`. If provided, QR factorization with column-pivoting is being computed. It is an `intent(out)` argument. `overwrite_a` (optional): Shall be an input `logical` flag (default: `.false.`). If `.true.`, input matrix `a` will be used as temporary storage and overwritten. This avoids internal data allocation. It is an `intent(in)` argument. `storage` (optional): Shall be a rank-1 array of the same type and kind as `a`, providing working storage for the solver. Its minimum size can be determined with a call to [[stdlib_linalg(module):qr_space(interface)]]. It is an `intent(out)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. It is an `intent(out)` argument. ### Return value Returns the QR factorization matrices into the \( Q \) and \( R \) arguments and the optional pivots in `pivots`. Raises `LINALG_VALUE_ERROR` if any of the matrices has invalid or unsuitable size for the full/reduced problem. Raises `LINALG_ERROR` on insufficient user storage space. If the state argument `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_qr.f90!} {!example/linalg/example_pivoting_qr.f90!} ``` ## `qr_space` - Compute internal working space requirements for the QR factorization. ### Status Experimental ### Description This subroutine computes the internal working space requirements for the QR factorization, [[stdlib_linalg(module):qr(interface)]] . ### Syntax `call ` [[stdlib_linalg(module):qr_space(interface)]] `(a, lwork, [, pivoting] [, err])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` array containing the coefficient matrix. It is an `intent(in)` argument. `lwork`: Shall be an `integer` scalar, that returns the minimum array size required for the working storage in [[stdlib_linalg(module):qr(interface)]] to factorize `a`. `pivoting` (optional): Shall a `logical` flag (default: `.false.`). If `.true.`, on exit `lwork` is the optimal workspace size for the QR factorization with column pivoting. If `.false.`, `lwork` is the optimal workspace size for the standard QR factorization. It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Example ```fortran {!example/linalg/example_qr_space.f90!} {!example/linalg/example_pivoting_qr_space.f90!} ``` ## `schur` - Compute the Schur decomposition of a matrix ### Status Experimental ### Description This subroutine computes the Schur decomposition of a `real` or `complex` matrix: \( A = Z T Z^H \), where \( Z \) is unitary (orthonormal) and \( T \) is upper-triangular (for complex matrices) or quasi-upper-triangular (for real matrices, with possible \( 2 \times 2 \) blocks on the diagonal). Matrix \( A \) has size `[n,n]`. The results are returned in output matrices \( T \) and \( Z \). Matrix \( T \) is the Schur form, and matrix \( Z \) is the unitary transformation matrix such that \( A = Z T Z^H \). If requested, the eigenvalues of \( T \) can also be returned as a `complex` array of size `[n]`. ### Syntax `call ` [[stdlib_linalg(module):schur(interface)]] `(a, t [, z,] [, eigvals] [, overwrite_a] [, storage] [, err])` ### Arguments - `a`: Shall be a rank-2 `real` or `complex` array containing the matrix to be decomposed. It is an `intent(inout)` argument if `overwrite_a = .true.`; otherwise, it is an `intent(in)` argument. - `t`: Shall be a rank-2 array of the same kind as `a`, containing the Schur form \( T \) of the matrix. It is an `intent(out)` argument and should have a shape of `[n,n]`. - `z`: Shall be a rank-2 array of the same kind as `a`, containing the unitary matrix \( Z \). It is an `intent(out)` argument and is optional. If provided, it should have the shape `[n,n]`. - `eigvals` (optional): Shall be a rank-1 `complex` or `real` array of the same kind as `a`, containing the eigenvalues of \( A \) (the diagonal elements of \( T \)), or their `real` component only. The array must be of size `[n]`. If not provided, the eigenvalues are not returned. It is an `intent(out)` argument. - `overwrite_a` (optional): Shall be a `logical` flag (default: `.false.`). If `.true.`, the input matrix `a` will be overwritten and destroyed upon return, avoiding internal data allocation. It is an `intent(in)` argument. - `storage` (optional): Shall be a rank-1 array of the same type and kind as `a`, providing working storage for the solver. Its minimum size can be determined with a call to [[stdlib_linalg(module):schur_space(interface)]]. It is an `intent(inout)` argument. - `err` (optional): Shall be a `type(linalg_state_type)` value. It is an `intent(out)` argument. If not provided, exceptions trigger an `error stop`. ### Return value Returns the Schur decomposition matrices into the \( T \) and \( Z \) arguments. If `eigvals` is provided, it will also return the eigenvalues of the matrix \( A \). Raises `LINALG_VALUE_ERROR` if any of the matrices have invalid or unsuitable size for the decomposition. Raises `LINALG_VALUE_ERROR` if the `real` component is only requested, but the eigenvalues have non-trivial imaginary parts. Raises `LINALG_ERROR` on insufficient user storage space. If the state argument `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_schur_eigvals.f90!} ``` --- ## `schur_space` - Compute internal working space requirements for the Schur decomposition ### Status Experimental ### Description This subroutine computes the internal working space requirements for the Schur decomposition, [[stdlib_linalg(module):schur(interface)]]. ### Syntax `call ` [[stdlib_linalg(module):schur_space(interface)]] `(a, lwork, [, err])` ### Arguments - `a`: Shall be a rank-2 `real` or `complex` array containing the matrix to be decomposed. It is an `intent(in)` argument. - `lwork`: Shall be an `integer` scalar that returns the minimum array size required for the working storage in [[stdlib_linalg(module):schur(interface)]] to decompose `a`. It is an `intent(out)` argument. - `err` (optional): Shall be a `type(linalg_state_type)` value. It is an `intent(out)` argument. ### Return value Returns the required working storage size `lwork` for the Schur decomposition. This value can be used to pre-allocate a workspace array in case multiple Schur decompositions of the same matrix size are needed. If pre-allocated working arrays are provided, no internal memory allocations will take place during the decomposition. ## `eig` - Eigenvalues and Eigenvectors of a Square Matrix ### Status Stable ### Description This subroutine computes the solution to the eigenproblem \( A \cdot \bar{v} - \lambda \cdot \bar{v} \), where \( A \) is a square, full-rank, `real` or `complex` matrix, or to the generalized eigenproblem \( A \cdot \bar{v} - \lambda \cdot B \cdot \bar{v} \), where \( B \) is a square matrix with the same type, kind and size as \( A \). Result array `lambda` returns the eigenvalues of \( A \). The user can request eigenvectors to be returned: if provided, on output `left` will contain the left eigenvectors, `right` the right eigenvectors of \( A \). Both `left` and `right` are rank-2 arrays, where eigenvectors are stored as columns. The solver is based on LAPACK's `*GEEV` (standard eigenproblem) and `*GGEV` (generalized eigenproblem) backends. ### Syntax For the standard eigenproblem: `call ` [[stdlib_linalg(module):eig(interface)]] `(a, lambda [, right] [,left] [,overwrite_a] [,err])` For the generalized eigenproblem: `call ` [[stdlib_linalg(module):eig(interface)]] `(a, b, lambda [, right] [, left] [, overwrite_a] [, overwrite_b] [, err]) ### Arguments `a` : `real` or `complex` square array containing the coefficient matrix. If `overwrite_a=.false.`, it is an `intent(in)` argument. Otherwise, it is an `intent(inout)` argument and is destroyed by the call. `b`: `real` or `complex` square array containing the second coefficient matrix. If `overwrite_b=.false.`, it is an `intent(in)` argument. Otherwise, it is an `intent(inout)` argument and is destroyed by the call. `lambda`: Shall be a `complex` or `real` rank-1 array of the same kind as `a`, containing the eigenvalues, or their `real` component only. It is an `intent(out)` argument. `right` (optional): Shall be a `complex` rank-2 array of the same size and kind as `a`, containing the right eigenvectors of `a`. It is an `intent(out)` argument. `left` (optional): Shall be a `complex` rank-2 array of the same size and kind as `a`, containing the left eigenvectors of `a`. It is an `intent(out)` argument. `overwrite_a` (optional): Shall be an input logical flag. if `.true.`, input matrix `a` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument. `overwrite_b` (optional): Shall be an input logical flag. If `.true.`, input matrix `b` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return value Raises `LINALG_ERROR` if the calculation did not converge. Raises `LINALG_VALUE_ERROR` if any matrix or arrays have invalid/incompatible sizes. Raises `LINALG_VALUE_ERROR` if the `real` component is only requested, but the eigenvalues have non-trivial imaginary parts. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_eig.f90!} ``` ## `eigh` - Eigenvalues and Eigenvectors of a Real symmetric or Complex Hermitian Square Matrix ### Status Stable ### Description This subroutine computes the solution to the eigendecomposition \( A \cdot \bar{v} - \lambda \cdot \bar{v} \), where \( A \) is a square, full-rank, `real` symmetric \( A = A^T \) or `complex` Hermitian \( A = A^H \) matrix. Result array `lambda` returns the `real` eigenvalues of \( A \). The user can request the orthogonal eigenvectors to be returned: on output `vectors` may contain the matrix of eigenvectors, returned as a column. Normally, only the lower triangular part of \( A \) is accessed. On input, `logical` flag `upper_a` allows the user to request what triangular part of the matrix should be used. The solver is based on LAPACK's `*SYEV` and `*HEEV` backends. ### Syntax `call ` [[stdlib_linalg(module):eigh(interface)]] `(a, lambda [, vectors] [, upper_a] [, overwrite_a] [,err])` ### Arguments `a` : `real` or `complex` square array containing the coefficient matrix. It is an `intent(in)` argument. If `overwrite_a=.true.`, it is an `intent(inout)` argument and is destroyed by the call. `lambda`: Shall be a `complex` rank-1 array of the same precision as `a`, containing the eigenvalues. It is an `intent(out)` argument. `vectors` (optional): Shall be a rank-2 array of the same type, size and kind as `a`, containing the eigenvectors of `a`. It is an `intent(out)` argument. `upper_a` (optional): Shall be an input `logical` flag. If `.true.`, the upper triangular part of `a` will be accessed. Otherwise, the lower triangular part will be accessed. It is an `intent(in)` argument. `overwrite_a` (optional): Shall be an input `logical` flag. If `.true.`, input matrix `a` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return value Raises `LINALG_ERROR` if the calculation did not converge. Raises `LINALG_VALUE_ERROR` if any matrix or arrays have invalid/incompatible sizes. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_eigh.f90!} ``` ## `eigvals` - Eigenvalues of a Square Matrix ### Status Stable ### Description This function computes the eigenvalues for either a standard or generalized eigenproblem: - **Standard eigenproblem**: \( A \cdot \bar{v} - \lambda \cdot \bar{v} \), where \( A \) is a square, full-rank `real` or `complex` matrix. - **Generalized eigenproblem**: \( A \cdot \bar{v} - \lambda \cdot B \cdot \bar{v} \), where \( B \) is a square matrix with the same type and kind as \( A \). The eigenvalues are stored in the result array `lambda`, which is `complex` (even for real input matrices). The solver uses LAPACK's `*GEEV` and `*GGEV` backends for the standard and generalized problems, respectively. ### Syntax For the standard eigenproblem: `lambda = ` [[stdlib_linalg(module):eigvals(interface)]] `(a [, err])` For the generalized eigenproblem: `lambda = ` [[stdlib_linalg(module):eigvals(interface)]] `(a, b [, err])` ### Arguments `a`: Shall be a `real` or `complex` square array containing the coefficient matrix. It is an `intent(in)` argument. `b` (optional): Shall be a `real` or `complex` square array containing the second coefficient matrix for the generalized problem. It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return Value Returns a `complex` rank-1 array containing the eigenvalues of the problem. Raises `LINALG_ERROR` if the calculation did not converge. Raises `LINALG_VALUE_ERROR` if any matrix or arrays have invalid/incompatible sizes. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_eigvals.f90!} ``` ## `eigvalsh` - Eigenvalues of a Real Symmetric or Complex Hermitian Square Matrix ### Status Stable ### Description This function returns the eigenvalues to matrix \( A \): a where \( A \) is a square, full-rank, `real` symmetric \( A = A^T \) or `complex` Hermitian \( A = A^H \) matrix. The eigenvalues are solutions to the eigenproblem \( A \cdot \bar{v} - \lambda \cdot \bar{v} \). Result array `lambda` is `real`, and returns the eigenvalues of \( A \). The solver is based on LAPACK's `*SYEV` and `*HEEV` backends. ### Syntax `lambda = ` [[stdlib_linalg(module):eigvalsh(interface)]] `(a, [, upper_a] [,err])` ### Arguments `a` : `real` or `complex` square array containing the coefficient matrix. It is an `intent(in)` argument. `upper_a` (optional): Shall be an input logical flag. If `.true.`, the upper triangular part of `a` will be used accessed. Otherwise, the lower triangular part will be accessed (default). It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return value Returns a `real` array containing the eigenvalues of `a`. Raises `LINALG_ERROR` if the calculation did not converge. Raises `LINALG_VALUE_ERROR` if any matrix or arrays have invalid/incompatible sizes. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_eigvalsh.f90!} ``` ## `svd` - Compute the singular value decomposition of a rank-2 array (matrix). ### Status Stable ### Description This subroutine computes the singular value decomposition of a `real` or `complex` rank-2 array (matrix) \( A = U \cdot S \cdot \V^T \). The solver is based on LAPACK's `*GESDD` backends. Result vector `s` returns the array of singular values on the diagonal of \( S \). If requested, `u` contains the left singular vectors, as columns of \( U \). If requested, `vt` contains the right singular vectors, as rows of \( V^T \). ### Syntax `call ` [[stdlib_linalg(module):svd(interface)]] `(a, s, [, u, vt, overwrite_a, full_matrices, err])` ### Class Subroutine ### Arguments `a`: Shall be a rank-2 `real` or `complex` array containing the coefficient matrix of size `[m,n]`. It is an `intent(inout)` argument, but returns unchanged unless `overwrite_a=.true.`. `s`: Shall be a rank-1 `real` array, returning the list of `k = min(m,n)` singular values. It is an `intent(out)` argument. `u` (optional): Shall be a rank-2 array of same kind as `a`, returning the left singular vectors of `a` as columns. Its size should be `[m,m]` unless `full_matrices=.false.`, in which case, it can be `[m,min(m,n)]`. It is an `intent(out)` argument. `vt` (optional): Shall be a rank-2 array of same kind as `a`, returning the right singular vectors of `a` as rows. Its size should be `[n,n]` unless `full_matrices=.false.`, in which case, it can be `[min(m,n),n]`. It is an `intent(out)` argument. `overwrite_a` (optional): Shall be an input `logical` flag. If `.true.`, input matrix `A` will be used as temporary storage and overwritten. This avoids internal data allocation. By default, `overwrite_a=.false.`. It is an `intent(in)` argument. `full_matrices` (optional): Shall be an input `logical` flag. If `.true.` (default), matrices `u` and `vt` shall be full-sized. Otherwise, their secondary dimension can be resized to `min(m,n)`. See `u`, `v` for details. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return values Returns an array `s` that contains the list of singular values of matrix `a`. If requested, returns a rank-2 array `u` that contains the left singular vectors of `a` along its columns. If requested, returns a rank-2 array `vt` that contains the right singular vectors of `a` along its rows. Raises `LINALG_ERROR` if the underlying Singular Value Decomposition process did not converge. Raises `LINALG_VALUE_ERROR` if the matrix or any of the output arrays invalid/incompatible sizes. Exceptions trigger an `error stop`, unless argument `err` is present. ### Example ```fortran {!example/linalg/example_svd.f90!} ``` ## `svdvals` - Compute the singular values of a rank-2 array (matrix). ### Status Stable ### Description This subroutine computes the singular values of a `real` or `complex` rank-2 array (matrix) from its singular value decomposition \( A = U \cdot S \cdot \V^T \). The solver is based on LAPACK's `*GESDD` backends. Result vector `s` returns the array of singular values on the diagonal of \( S \). ### Syntax `s = ` [[stdlib_linalg(module):svdvals(interface)]] `(a [, err])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` array containing the coefficient matrix of size `[m,n]`. It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return values Returns an array `s` that contains the list of singular values of matrix `a`. Raises `LINALG_ERROR` if the underlying Singular Value Decomposition process did not converge. Raises `LINALG_VALUE_ERROR` if the matrix or any of the output arrays invalid/incompatible sizes. Exceptions trigger an `error stop`, unless argument `err` is present. ### Example ```fortran {!example/linalg/example_svdvals.f90!} ``` ## `cholesky` - Compute the Cholesky factorization of a rank-2 square array (matrix) ### Status Experimental ### Description This subroutine computes the Cholesky factorization of a `real` or `complex` rank-2 square array (matrix), \( A = L \cdot L^T \), or \( A = U^T \cdot U \). \( A \) is symmetric or complex Hermitian, and \( L \), \( U \) are lower- or upper-triangular, respectively. The solver is based on LAPACK's `*POTRF` backends. ### Syntax `call ` [[stdlib_linalg(module):cholesky(interface)]] `(a, c, lower [, other_zeroed] [, err])` ### Class Subroutine ### Arguments `a`: Shall be a rank-2 square `real` or `complex` array containing the coefficient matrix of size `[n,n]`. It is an `intent(inout)` argument, but returns unchanged if the argument `c` is present. `c` (optional): Shall be a rank-2 square `real` or `complex` of the same size and kind as `a`. It is an `intent(out)` argument, that returns the triangular Cholesky matrix `L` or `U`. `lower`: Shall be an input `logical` flag. If `.true.`, the lower triangular decomposition \( A = L \cdot L^T \) will be performed. If `.false.`, the upper decomposition \( A = U^T \cdot U \) will be performed. `other_zeroed` (optional): Shall be an input `logical` flag. If `.true.`, the unused part of the output matrix will contain zeroes. Otherwise, it will not be accessed. This saves cpu time. By default, `other_zeroed=.true.`. It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. It is an `intent(out)` argument. ### Return values The factorized matrix is returned in-place overwriting `a` if no other arguments are provided. Otherwise, it can be provided as a second argument `c`. In this case, `a` is not overwritten. The `logical` flag `lower` determines whether the lower- or the upper-triangular factorization should be performed. Results are returned on the applicable triangular region of the output matrix, while the unused triangular region is filled by zeroes by default. Optional argument `other_zeroed`, if `.false.` allows the expert user to avoid zeroing the unused part; however, in this case, the unused region of the matrix is not accessed and will usually contain invalid values. Raises `LINALG_ERROR` if the underlying process did not converge. Raises `LINALG_VALUE_ERROR` if the matrix or any of the output arrays invalid/incompatible sizes. Exceptions trigger an `error stop`, unless argument `err` is present. ### Example ```fortran {!example/linalg/example_cholesky.f90!} ``` ## `chol` - Compute the Cholesky factorization of a rank-2 square array (matrix) ### Status Experimental ### Description This is a `pure` functional interface for the Cholesky factorization of a `real` or `complex` rank-2 square array (matrix) computed as \( A = L \cdot L^T \), or \( A = U^T \cdot U \). \( A \) is symmetric or complex Hermitian, and \( L \), \( U \) are lower- or upper-triangular, respectively. The solver is based on LAPACK's `*POTRF` backends. Result matrix `c` has the same size and kind as `a`, and returns the lower or upper triangular factor. ### Syntax `c = ` [[stdlib_linalg(module):chol(interface)]] `(a, lower [, other_zeroed])` ### Arguments `a`: Shall be a rank-2 square `real` or `complex` array containing the coefficient matrix of size `[n,n]`. It is an `intent(inout)` argument, but returns unchanged if argument `c` is present. `lower`: Shall be an input `logical` flag. If `.true.`, the lower triangular decomposition \( A = L \cdot L^T \) will be performed. If `.false.`, the upper decomposition \( A = U^T \cdot U \) will be performed. `other_zeroed` (optional): Shall be an input `logical` flag. If `.true.`, the unused part of the output matrix will contain zeroes. Otherwise, it will not be accessed. This saves cpu time. By default, `other_zeroed=.true.`. It is an `intent(in)` argument. ### Return values Returns a rank-2 array `c` of the same size and kind as `a`, that contains the triangular Cholesky matrix `L` or `U`. Raises `LINALG_ERROR` if the underlying process did not converge. Raises `LINALG_VALUE_ERROR` if the matrix or any of the output arrays invalid/incompatible sizes. Exceptions trigger an `error stop`, unless argument `err` is present. ### Example ```fortran {!example/linalg/example_chol.f90!} ``` ## `.inv.` - Inverse operator of a square matrix ### Status Stable ### Description This operator returns the inverse of a `real` or `complex` square matrix \( A \). The inverse \( A^{-1} \) is defined such that \( A \cdot A^{-1} = A^{-1} \cdot A = I_n \). This interface is equivalent to the function [[stdlib_linalg(module):inv(interface)]]. ### Syntax `b = ` [[stdlib_linalg(module):operator(.inv.)(interface)]] `a` ### Arguments `a`: Shall be a rank-2 square array of any `real` or `complex` kinds. It is an `intent(in)` argument. ### Return value Returns a rank-2 square array with the same type, kind and rank as `a`, that contains the inverse of `a`. If an exception occurred on input errors, or singular matrix, `NaN`s will be returned. For fine-grained error control in case of singular matrices prefer the `subroutine` and the `function` interfaces. ### Example ```fortran {!example/linalg/example_inverse_operator.f90!} ``` ## `invert` - Inversion of a square matrix ### Status Stable ### Description This subroutine inverts a square `real` or `complex` matrix in-place. The inverse \( A^{-1} \) is defined such that \( A \cdot A^{-1} = A^{-1} \cdot A = I_n \). On return, the input matrix `a` is replaced by its inverse. The solver is based on LAPACK's `*GETRF` and `*GETRI` backends. ### Syntax `call ` [[stdlib_linalg(module):invert(interface)]] `(a, [,inva] [, pivot] [, err])` ### Arguments `a`: Shall be a rank-2, square, `real` or `complex` array containing the coefficient matrix. If `inva` is provided, it is an `intent(in)` argument. If `inva` is not provided, it is an `intent(inout)` argument: on output, it is replaced by the inverse of `a`. `inva` (optional): Shall be a rank-2, square, `real` or `complex` array with the same size, and kind as `a`. On output, it contains the inverse of `a`. `pivot` (optional): Shall be a rank-1 array of the same kind and matrix dimension as `a`, that contains the diagonal pivot indices on return. It is an `intent(inout)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return value Computes the inverse of the matrix \( A \), \(A^{-1}\, and returns it either in \( A \) or in another matrix. Raises `LINALG_ERROR` if the matrix is singular or has invalid size. Raises `LINALG_VALUE_ERROR` if `inva` and `a` do not have the same size. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_inverse_inplace.f90!} ``` ```fortran {!example/linalg/example_inverse_subroutine.f90!} ``` ## `inv` - Inverse of a square matrix. ### Status Stable ### Description This function returns the inverse of a square `real` or `complex` matrix in-place. The inverse, \( A^{-1} \), is defined such that \( A \cdot A^{-1} = A^{-1} \cdot A = I_n \). The solver is based on LAPACK's `*GETRF` and `*GETRI` backends. ### Syntax `b ` [[stdlib_linalg(module):inv(interface)]] `(a, [, err])` ### Arguments `a`: Shall be a rank-2, square, `real` or `complex` array containing the coefficient matrix. It is an `intent(inout)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. It is an `intent(out)` argument. ### Return value Returns an array value of the same type, kind and rank as `a`, that contains the inverse matrix \(A^{-1}\). Raises `LINALG_ERROR` if the matrix is singular or has invalid size. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_inverse_function.f90!} ``` ## `pinv` - Moore-Penrose pseudo-inverse of a matrix ### Status Experimental ### Description This function computes the Moore-Penrose pseudo-inverse of a `real` or `complex` matrix. The pseudo-inverse, \( A^{+} \), generalizes the matrix inverse and satisfies the conditions: - \( A \cdot A^{+} \cdot A = A \) - \( A^{+} \cdot A \cdot A^{+} = A^{+} \) - \( (A \cdot A^{+})^T = A \cdot A^{+} \) - \( (A^{+} \cdot A)^T = A^{+} \cdot A \) The computation is based on singular value decomposition (SVD). Singular values below a relative tolerance threshold \( \text{rtol} \cdot \sigma_{\max} \), where \( \sigma_{\max} \) is the largest singular value, are treated as zero. ### Syntax `b =` [[stdlib_linalg(module):pinv(interface)]] `(a, [, rtol, err])` ### Arguments `a`: Shall be a rank-2, `real` or `complex` array of shape `[m, n]` containing the coefficient matrix. It is an `intent(in)` argument. `rtol` (optional): Shall be a scalar `real` value specifying the relative tolerance for singular value cutoff. If `rtol` is not provided, the default relative tolerance is \( \text{rtol} = \text{max}(m, n) \cdot \epsilon \), where \( \epsilon \) is the machine precision for the element type of `a`. It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. It is an `intent(out)` argument. ### Return value Returns an array value of the same type, kind, and rank as `a` with shape `[n, m]`, that contains the pseudo-inverse matrix \( A^{+} \). Raises `LINALG_ERROR` if the underlying SVD did not converge. Raises `LINALG_VALUE_ERROR` if `a` has invalid size. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_pseudoinverse.f90!} ``` ## `pseudoinvert` - Moore-Penrose pseudo-inverse of a matrix ### Status Experimental ### Description This subroutine computes the Moore-Penrose pseudo-inverse of a `real` or `complex` matrix. The pseudo-inverse \( A^{+} \) is a generalization of the matrix inverse and satisfies the following properties: - \( A \cdot A^{+} \cdot A = A \) - \( A^{+} \cdot A \cdot A^{+} = A^{+} \) - \( (A \cdot A^{+})^T = A \cdot A^{+} \) - \( (A^{+} \cdot A)^T = A^{+} \cdot A \) The computation is based on singular value decomposition (SVD). Singular values below a relative tolerance threshold \( \text{rtol} \cdot \sigma_{\max} \), where \( \sigma_{\max} \) is the largest singular value, are treated as zero. On return, matrix `pinva` `[n, m]` will store the pseudo-inverse of `a` `[m, n]`. ### Syntax `call ` [[stdlib_linalg(module):pseudoinvert(interface)]] `(a, pinva [, rtol] [, err])` ### Arguments `a`: Shall be a rank-2, `real` or `complex` array containing the coefficient matrix. It is an `intent(in)` argument. `pinva`: Shall be a rank-2 array of the same kind as `a`, and size equal to that of `transpose(a)`. On output, it contains the Moore-Penrose pseudo-inverse of `a`. `rtol` (optional): Shall be a scalar `real` value specifying the relative tolerance for singular value cutoff. If not provided, the default threshold is \( \text{max}(m, n) \cdot \epsilon \), where \( \epsilon \) is the machine precision for the element type of `a`. `err` (optional): Shall be a `type(linalg_state_type)` value. It is an `intent(out)` argument. ### Return value Computes the Moore-Penrose pseudo-inverse of the matrix \( A \), \( A^{+} \), and returns it in matrix `pinva`. Raises `LINALG_ERROR` if the underlying SVD did not converge. Raises `LINALG_VALUE_ERROR` if `pinva` and `a` have degenerate or incompatible sizes. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_pseudoinverse.f90!} ``` ## `.pinv.` - Moore-Penrose Pseudo-Inverse operator ### Status Experimental ### Description This operator returns the Moore-Penrose pseudo-inverse of a `real` or `complex` matrix \( A \). The pseudo-inverse \( A^{+} \) is computed using Singular Value Decomposition (SVD), and singular values below a given threshold are treated as zero. This interface is equivalent to the function [[stdlib_linalg(module):pinv(interface)]]. ### Syntax `b = ` [[stdlib_linalg(module):operator(.pinv.)(interface)]] `a` ### Arguments `a`: Shall be a rank-2 array of any `real` or `complex` kinds, with arbitrary dimensions \( m \times n \). It is an `intent(in)` argument. ### Return value Returns a rank-2 array with the same type, kind, and rank as `a`, that contains the Moore-Penrose pseudo-inverse of `a`. If an exception occurs, or if the input matrix is degenerate (e.g., rank-deficient), the returned matrix will contain `NaN`s. For more detailed error handling, it is recommended to use the `subroutine` or `function` interfaces. ### Example ```fortran {!example/linalg/example_pseudoinverse.f90!} ``` ## `get_norm` - Computes the vector norm of a generic-rank array. ### Status Experimental ### Description This `pure subroutine` interface computes one of several vector norms of `real` or `complex` array \( A \), depending on the value of the `order` input argument. \( A \) may be an array of any rank. Result `nrm` returns a `real`, scalar norm value for the whole array; if `dim` is specified, `nrm` is a rank n-1 array with the same shape as \(A \) and dimension `dim` dropped, containing all norms evaluated along `dim`. ### Syntax `call ` [[stdlib_linalg(module):get_norm(interface)]] `(a, nrm, order, [, dim, err])` ### Arguments `a`: Shall be a rank-n `real` or `complex` array containing the data. It is an `intent(in)` argument. `nrm`: if `dim` is absent, shall be a scalar with the norm evaluated over all the elements of the array. Otherwise, an array of rank `n-1`, and a shape similar to that of `a` with dimension `dim` dropped. `order`: Shall be an `integer` value or a `character` flag that specifies the norm type, as follows. It is an `intent(in)` argument. | Integer input | Character Input | Norm type | |------------------|------------------|---------------------------------------------------------| | `-huge(0)` | `'-inf', '-Inf'` | Minimum absolute value \( \min_i{ \left|a_i\right| } \) | | `1` | `'1'` | 1-norm \( \sum_i{ \left|a_i\right| } \) | | `2` | `'2'` | Euclidean norm \( \sqrt{\sum_i{ a_i^2 }} \) | | `>=3` | `'3','4',...` | p-norm \( \left( \sum_i{ \left|a_i\right|^p }\right) ^{1/p} \) | | `huge(0)` | `'inf', 'Inf'` | Maximum absolute value \( \max_i{ \left|a_i\right| } \) | `dim` (optional): Shall be a scalar `integer` value with a value in the range from `1` to `n`, where `n` is the rank of the array. It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. If `err` is not present, the function is `pure`. ### Return value By default, the return value `nrm` is a scalar, and contains the norm as evaluated over all elements of the generic-rank array \( A \). If the optional `dim` argument is present, `nrm` is a rank `n-1` array with the same shape as \( A \) except for dimension `dim`, that is collapsed. Each element of `nrm` contains the 1D norm of the elements of \( A \), evaluated along dimension `dim` only. Raises `LINALG_ERROR` if the requested norm type is invalid. Raises `LINALG_VALUE_ERROR` if any of the arguments has an invalid size. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_get_norm.f90!} ``` ## `norm` - Computes the vector norm of a generic-rank array. ### Status Experimental ### Description This function computes one of several vector norms of `real` or `complex` array \( A \), depending on the value of the `order` input argument. \( A \) may be an array of any rank. ### Syntax `x = ` [[stdlib_linalg(module):norm(interface)]] `(a, order, [, dim, err])` ### Arguments `a`: Shall be a rank-n `real` or `complex` array containing the data. It is an `intent(in)` argument. `order`: Shall be an `integer` value or a `character` flag that specifies the norm type, as follows. It is an `intent(in)` argument. | Integer input | Character Input | Norm type | |------------------|------------------|---------------------------------------------------------| | `-huge(0)` | `'-inf', '-Inf'` | Minimum absolute value \( \min_i{ \left|a_i\right| } \) | | `1` | `'1'` | 1-norm \( \sum_i{ \left|a_i\right| } \) | | `2` | `'2'` | Euclidean norm \( \sqrt{\sum_i{ a_i^2 }} \) | | `>=3` | `'3','4',...` | p-norm \( \left( \sum_i{ \left|a_i\right|^p }\right) ^{1/p} \) | | `huge(0)` | `'inf', 'Inf'` | Maximum absolute value \( \max_i{ \left|a_i\right| } \) | `dim` (optional): Shall be a scalar `integer` value with a value in the range from `1` to `n`, where `n` is the rank of the array. It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. If `err` is not present, the function is `pure`. ### Return value By default, the return value `x` is a scalar, and contains the norm as evaluated over all elements of the generic-rank array \( A \). If the optional `dim` argument is present, `x` is a rank `n-1` array with the same shape as \( A \) except for dimension `dim`, that is dropped. Each element of `x` contains the 1D norm of the elements of \( A \), evaluated along dimension `dim` only. Raises `LINALG_ERROR` if the requested norm type is invalid. Raises `LINALG_VALUE_ERROR` if any of the arguments has an invalid size. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_norm.f90!} ``` ## `mnorm` - Computes the matrix norm of a generic-rank array. ### Status Experimental ### Description This function computes one of several matrix norms of `real` or `complex` array \( A \), depending on the value of the `order` input argument. \( A \) must be an array of rank 2 or higher. For arrays of rank > 2, matrix norms are computed over specified dimensions. ### Syntax `x = ` [[stdlib_linalg(module):mnorm(interface)]] `(a [, order, dim, err])` ### Arguments `a`: Shall be a rank-n `real` or `complex` array containing the data, where n >= 2. It is an `intent(in)` argument. `order` (optional): Shall be an `integer` value or a `character` flag that specifies the norm type, as follows. It is an `intent(in)` argument. | Integer input | Character Input | Norm type | |------------------|---------------------------------|-----------------------------------------------------------------------------| | `1` | `'1'` | 1-norm (maximum column sum) \( \max_j \sum_i{ \left|a_{i,j}\right| } \) | | `2` | `'2'` | 2-norm (largest singular value) | | (not prov.) | `'Euclidean','Frobenius','Fro'` | Frobenius norm \( \sqrt{\sum_{i,j}{ \left|a_{i,j}\right|^2 }} \) | | `huge(0)` | `'inf', 'Inf', 'INF'` | Infinity norm (maximum row sum) \( \max_i \sum_j{ \left|a_{i,j}\right| } \) | `dim` (optional): For arrays of rank > 2, shall be an integer array of size 2 specifying the dimensions over which to compute the matrix norm. Default value is `[1,2]`. It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return value For rank-2 input arrays, the return value `x` is a scalar containing the matrix norm. For arrays of rank > 2, if the optional `dim` argument is present, `x` is a rank `n-2` array with the same shape as \( A \) except for dimensions `dim(1)` and `dim(2)`, which are dropped. Each element of `x` contains the matrix norm of the corresponding submatrix of \( A \), evaluated over the specified dimensions only, with the given order. If an invalid norm type is provided, defaults to 1-norm and raises `LINALG_ERROR`. Raises `LINALG_VALUE_ERROR` if any of the arguments has an invalid size. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_mnorm.f90!} ``` ## `expm` - Computes the matrix exponential {#expm} ### Status Experimental ### Description Given a matrix \(A\), this function computes its matrix exponential \(E = \exp(A)\) using a Pade approximation. ### Syntax `E = ` [[stdlib_linalg(module):expm(interface)]] `(a [, order])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` array containing the data. It is an `intent(in)` argument. `order` (optional): Shall be a non-negative `integer` value specifying the order of the Pade approximation. By default `order=10`. It is an `intent(in)` argument. ### Return value The returned array `E` contains the Pade approximation of \(\exp(A)\). If `A` is non-square or `order` is negative, it raises a `LINALG_VALUE_ERROR`. ### Example ```fortran {!example/linalg/example_expm.f90!} ``` ## `matrix_exp` - Computes the matrix exponential {#matrix_exp} ### Status Experimental ### Description Given a matrix \(A\), this function computes its matrix exponential \(E = \exp(A)\) using a Pade approximation. ### Syntax `call ` [[stdlib_linalg(module):matrix_exp(interface)]] `(a [, e, order, err])` ### Arguments `a`: Shall be a rank-2 `real` or `complex` array containing the data. If `e` is not passed, it is an `intent(inout)` argument and is overwritten on exit by the matrix exponential. If `e` is passed, it is an `intent(in)` argument and is left unchanged. `e` (optional): Shall be a rank-2 `real` or `complex` array with the same dimensions as `a`. It is an `intent(out)` argument. On exit, it contains the matrix exponential of `a`. `order` (optional): Shall be a non-negative `integer` value specifying the order of the Pade approximation. By default `order=10`. It is an `intent(in)` argument. `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. ### Return value The returned array `A` (in-place) or `E` (out-of-place) contains the Pade approximation of \(\exp(A)\). If `A` is non-square or `order` is negative, it raises a `LINALG_VALUE_ERROR`. If `err` is not present, exceptions trigger an `error stop`. ### Example ```fortran {!example/linalg/example_matrix_exp.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_hash_procedures.md0000664000175000017500000015344715135654166025127 0ustar alastairalastair--- title: hash --- # The `stdlib_hash_32bit` and `stdlib_hash_64bit` modules [TOC] ## Overview of hash procedures The comparison of lexical entities or other objects for equality can be computationally expensive. This cost is often reduced by computing a near unique integer value, termed a hash code, from the structure of the object using a procedure termed a hash function. Equality of hash codes is a necessary, but not sufficient, condition for the original objects to be equal. As integer comparisons are very efficient, performing an initial comparison of hash codes and then performing a detailed comparison only if the hash codes are equal can improve performance. The hash codes, in turn, can be mapped to a smaller set of integers, that can be used as an index, termed a hash index, to a rank-1 array, often termed a hash table. This mapping will be known as a scalar hash. The use of a hash table reduces the number of hash codes that need to be compared, further improving performance. A hash function can also be used to generate a checksum to verify that data has not changed. The Fortran Standard Library therefore provides procedures to compute hash codes and scalar hashes. This document only discusses the hash codes and scalar hashes in the library. ## Licensing The Fortran Standard Library is distributed under the MIT License. However components of the library may be based on code released under a different license. In particular, the hash codes are often based on algorithms considered as public domain (`Fibonacci Hash`, `Universal Multiplicative Hash)`or released under a different license than the MIT license (`FNV-1 Hash`, `FNV-1A Hash`, `nmhash32`, `nmhash32x`, `waterhash`, `pengyhash` and `SpookyHash`) The licensing status of the algorithms are discussed below. `fibonacci_hash` is a scalar hash. It is an implementation in Fortran 2008 and signed two's complement integers of the Fibonacci Hash described in D. E. Knuth, "The Art of Computer Programming, Second Edition, Volume 3, Sorting and Searching", Addison-Wesley, Upper Saddle River, NJ, pp. 517-518, 1998. The algorithms in that source are considered public domain, and its use is unrestricted. `universal_mult_hash` is a scalar hash. It is an implementation in Fortran 2008 and signed two's complement integers of the universal multiplicative hash algorithm of M. Dietzfelbinger, T. Hagerup, J. Katajainen, and M. Penttonen, "A Reliable Randomized Algorithm for the Closest-Pair Problem," J. Algorithms, Vol. 25, No. 1, Oct. 1997, pp. 19-51. Because of its publication in the Journal of Algorithms, the universal multiplicative hash algorithm is public domain. `fnv_1_hash` and `fnv_1a_hash` are translations to Fortran 2008 and signed two's complement integers of the `FNV-1` and `FNV-1a` hash functions of Glenn Fowler, Landon Curt Noll, and Phong Vo, that has been released into the public domain. Permission has been granted, by Landon Curt Noll, for the use of these algorithms in the Fortran Standard Library. A description of these functions is available at . These functions have been modified from their normal forms to also encode the structure size in the output hash. Similarly `spooky_hash` and associated procedures are translations to Fortran 2008 and signed two's complement integers of the unsigned 64 bit version 2 `SpookyHash` functions of Bob Jenkins to signed 64 bit operations. Version 2 was chosen over version 1 as it has better performance and fewer bad seeds Bob Jenkins has also put this code in the public domain and has given permission to treat this code as public domain in the USA, provided the code can be used under other licenses and he is given appropriate credit. `nmhash32` and `nmhash32x` are translations to Fortran 2008 and signed two's complement integers of the unsigned 32-bit hashes of James Z. M. Gao's `nmhash32` and `nmhash32x` version of 0.2, James Z. M. Gao has released his code under the BSD 2 Clause License. The BSD 2-Clause license is as follows: BSD 2-Clause License Copyright (c) 2021, James Z.M. Gao All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. `water_hash` is a translation to Fortran 2008 and signed two's complement integers of the `waterhash` algorithm of Tommy Ettinger. This algorithm is inspired by the Wy Hash of Wang Yi. Tommy Ettinger's original C++ code, `waterhash.h`, is available at URL: under the `unlicense`, . The `unlicense` reads as follows: This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to `pengy_hash` is a translation to Fortran 2008 and signed two's complement arithmetic of the `pengyhash` algorithm of Alberto Fajardo, copyright 2020. Alberto Fajardo's original C code, `pengyhash.c`, is available at the URL: https://github.com/tinypeng/pengyhash/blob/master/pengyhash.c under the BSD 2-Clause License: https://github.com/tinypeng/pengyhash/blob/master/LICENSE The BSD 2-Clause license is as follows: BSD 2-Clause License pengyhash Copyright (c) 2020 Alberto Fajardo All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## Glossary There are a few words used in this document that may not be familiar to readers of this document: * Key - a value to be used to find entries in a hash table typically using its hashed value for the initial search; * Salt - see seed, and; * Seed - an additional argument to a hash function that changes its output making some attacks impractical. ## The hash codes modules ### Overview of the modules The Standard Library provides two modules implementing hash functions and scalar hashes. The `stdlib_hash_32bit` module provides procedures to compute 32-bit integer hash codes and a scalar hash. The hash codes can be used for tables of up to `2**30` entries, and for keys with a few hundred elements, but performance has only been tested for tables up to `2**16` entries and performance may degrade for larger numbers of entries. The `stdlib_hash_64bit` module provides hash procedures to compute 64-bit integer hash codes and a scalar hash. The hash codes can, in principle, be used for tables of up to `2**62` entries, and for keys with a few thousand elements, but testing of performance has only been been for tables up to `2**16`elements and performance may degrade for larger numbers of entries. While one of the codes in `stdlib_hash_64bit`, `SPOOKY_HASH`, can also be used to calculate 128 bit hash codes, none of the current codes can be used to calculate 256 bit hash codes. Such larger hash codes are useful for larger hash tables and keys, and for checksums. Such larger keys and tables are little used, if used at all, in current Fortran codes, but the larger hash codes may be added to the library if there is a demand for them. Hash functions are often divided into two categories "cryptographic" and "non-cryptographic". Cryptographic hash functions produce codes that are infeasible to reverse without additional information beyond the identity of the hash function used to generate the code and the resulting codes. Non-cryptographic codes, in some circumstances, are believed to be reversible. The modules only implement hash functions that are considered non-cryptographic, with implementations available in the public domain. There are a number of algorithms available for the computation of non-cryptographic 32 and 64-bit hash codes that differ in their computational complexity, their relative performance on different size keys, and the expected uniqueness (randomness) of the resulting hash codes. Their relative performance in the analysis of text, in particular, can depend on the compiler, character set, language, and content. The quality of a hash function is often evaluated using the SMHasher test suite, originally written by [Austin Appleby](https://github.com/aappleby/smhasher), but greatly extended by [Reini Urban](https://github.com/rurban/smhasher). All except the simplest, `FNV_1` and `FNV_1A`, of the hash functions defined in the modules perform well on the tests in Reini Urban's version of SMHasher. There are two problems in implementing hash functions in Fortran. First, the static typing of Fortran makes it awkward to define general purpose hash functions. Instead hash functions are defined for some of the more common objects: character strings and rank-1 arrays of integers. Other objects can, in principle, be hashed by using `transfer` to map their contents to an integer array, typically one of kind `int8`. The other problem is that hash codes are typically defined using modular unsigned integer arithmetic. As such integers are not part of the current Fortran standard, workarounds have to be used. These can take two forms. In one, the operations are emulated by using an integer of a larger size, or, for the larger integers, by dividing the integer into two lower and higher order halves, and performing the operations on each half separately using the larger integers. In the second, the unsigned integers may be replaced directly by the corresponding signed integers, but otherwise not modifying the code logic. The first should be standard conforming on current compilers, but is more computationally intensive unless the compilers recognize underlying idioms that are rarely used in Fortran codes. The second is not standard conforming as bit operations involving the sign are undefined, but should yield equivalent results with fewer operations on compilers with two's complement integers that do not trap on over or under flow. The codes currently use the second method. In order to compile the hash function modules, the compilers must implement much of Fortran 2003, and selected components of Fortran 2008: submodules, 64-bit integers, and some bit intrinsics. The main limitation on valid compilers is whether they implement the submodules enhancement of Fortran 2008. In order to properly run the hash functions, the compilers must use two's complement integers, and be able to execute them with wraparound semantics and no integer overflow exceptions. Current Fortran 2003+ compilers solely use two's complement integers, and appear to be able to turn off overflow detection, so the modules use signed integer arithmetic. For that reason trapping on signed arithmetic must be disabled. The command line flags to disable overflow detection for compilers implementing submodules are summarized in the table below. Note that FLANG, gfortran (since version 10), ifort, and NAG all default to integer overflow wrapping. |Compiler|Legal flag|Illegal flag|Default| |---------|----------|------------|-------| | ARM Fortran | NA? | NA? | overflow wrapping? | | Cray Fortran | NA? | NA? | overflow wrapping? | | FLANG/PGI | -fwrapv | -ftrapv | -fwrapv | | gfortran | -fwrapv | -ftrapv | -fwrapv | | IBM Fortran | NA? | NA? | overflow wrapping? | | ifort| NA? | NA? | overflow wrapping | | NAG Fortran | -C=none | -C=intovf | -C=none | | NEC Fortran | NA? | NA? | overflow wrapping? | | NVIDIA Fortran | NA? | NA? | overflow wrapping? | All of the modules' hash functions take one or two arguments. All of them have as their first argument the object to be hashed, termed a *key*. Most have a second argument, termed a *seed*, that sets the initial value of the hash code changing the hash function behavior. In particular, inputs that hash to the same hash index with a given seed, will often hash to different indexes with a different seed. This difference in behavior makes algorithms that use a seed much more resistant to denial of service attacks that use the properties of a known hash to increase the number of hash table collisions. This additional integer must be kept the same for all hashes in a given hash table, but can be changed and the objects rehashed if collisions are unusually common. The *seed* can be either a scalar or a two-element array. Some of the hash functions have alternatives that allow incremental hashing. |Algorithm|Seed|Result| |---------|----|------| |FNV-1|None|32 or 64-bit integer| |FNV-1a|None|32 or 64-bit integer| |nmhash32 |32-bit scalar integer|32-bit integer| |nmhash32x |32-bit scalar integer|32-bit integer| |pengyhash |32-bit scalar integer|64-bit integer| |Spooky Hash|64-bit two element vector|64-bit two element vector| |waterhash|64-bit scalar integer|32-bit integer| The hash function modules each provide at least five algorithms for hash functions: two optimized for small (< 32 `int8` integer elements) keys, and three optimized for large (> 100 `int8` integer elements) keys. The core implementation for each algorithm is for keys that are vectors of `int8` integers. These core implementations are then used in wrappers for keys that are vectors of `int16`, `int32` and `int64` integers, or default character strings, in the expectation that inlining will eliminate the overhead of transferring the other keys to `int8` integer vectors. The `stdlib_hash_32bit` module provides implementations of five hash code algorithms: the *FNV_1* and *FNV_1A* variants of Glenn Fowler, Landon Curt Noll, and Kiem-Phong Vo; the *nmhash32* and *nmhash32x* of James Z. M. Gao; and the *waterhash* of Tommy Ettinger. The detailed implementation of each algorithm is handled in a separate submodule: `stdlib_hash_32bit_fnv`, `stdlib_hash_32bit_nm`, and `stdlib_hash_32bit_water`, respectively. The `nmhash32`, `nmhash32x`, and `waterhash` algorithms require seeds. The submodules provide separate seed generators for each algorithm. The module itself implements two scalar hash functions, `fibonacci_hash` and `universal_mult_hash`. It also implements the subroutine, `odd_random_integer`, for generating seeds for `universal_mult_hash`. All assume a two's complement sign bit, and no out of range checks. The `stdlib_hash_64bit` module also provides implementations of four hash code algorithms: the *FNV_1* and *FNV_1A* variants of Glenn Fowler, Landon Curt Noll, and Kiem-Phong Vo; the *pengyhash* of Alberto Fajardo; and the *SpookyHash* of Bob Jenkins. The detailed implementation of each algorithm is handled in a separate submodule: `stdlib_hash_64bit_fnv`, `stdlib_hash_64bit_pengy`, and `stdlib_hash_64bit_spooky`, respectively. The `pengyhash`, and `Spooky Hash` algorithms require seeds. The submodules provide separate seed generators for each algorithm. The module itself implements two scalar hash functions, `fibonacci_hash` and `universal_mult_hash`. It also implements the subroutine, `odd_random_integer`, for generating seeds for `universal_mult_hash`. All assume a two's complement sign bit, and no out of range checks. The `stdlib_hash_32bit_fnv` and `stdlib_hash_64bit_fnv` submodules each provide implementations of the FNV-1 and FNV-1A algorithms in the form of two separate overloaded functions: `FNV_1` and `FNV_1A`. The FNV-1 and FNV-2 algorithms differ in their order of the multiplication and exclusive or operations. They differ from their normal implementation in that they also encode the structure size in the hash code. The 32 and 64-bit algorithms differ in their initial offsets and in their multiplicative constants. Analysis suggests that `FNV_1A` should be better at randomizing the input, but tests with hash tables show negligible difference. These algorithms have the reputation of being particularly useful for small byte strings, i.e., strings of less than 32 bytes. While they do not at all perform well on the SMHasher test suite, usage indicates that this has little impact on the performance of small hash tables, and the small size of the functions allows their quick loading and retainment in the instruction cache, giving a performance boost where the hashing is intermittent. (See the [SMHasher discussion](https://github.com/rurban/smhasher/README.md) and [S. Richter, V. Alvarez, and J. Dittrich. 2015. A Seven-Dimensional Analysis of Hashing Methods and its Implications on Query Processing, Proceedings of the VLDB Endowment, Vol. 9, No. 3.](https://bigdata.uni-saarland.de/publications/p249-richter.pdf) [https://doi.org/10.14778/2850583.2850585](https://doi.org/10.14778/2850583.2850585). The `stdlib_hash_32bit_nm` submodule provides implementations of James Z.M. Gao's `nmhash32` and `nmhash32x` algorithms, version 0.2, in the form of the overloaded functions, `nmhash32` and `nmhash32x`. The implementations are based on the scalar versions of Gao's algorithms and not the vector versions that require access to the vector instructions of some compilers. Both algorithms perform well on the SMHasher tests, and have no known bad seeds. The vector versions of both codes perform well on large keys, with the `nmhash32x` faster on short keys. To provide randomly generated seeds for the two functions the submodule also defines the subroutines `new_nmhash32_seed` and `new_nmhash32x_seed`. Gao claims that `nmhash32x` is significantly faster than `nmhash32` on short seeds, but slower on long seeds, but our limited testing so far shows `nmhash32x` to be significantly faster on short seeds and slightly faster on long seeds. The `stdlib_hash_32bit_water` submodule provides implementations of Tommy Ettinger's `waterhash` algorithm in the form of the overloaded function, `water_hash`. Water Hash has not been tested by Reini Urban, but Tommy Ettinger has tested it with Urban's SMHasher and presents results that shows Water Hash passing all the tests. So far his testing hasn't found any bad seeds for the algorithm. To provide randomly generated seeds for the hash function the submodule also defines the subroutine `new_water_hash_seed`. The `stdlib_hash_64bit_pengy` submodule provides implementations of Alberto Fajardo's `pengyhash` in the form of the overloaded function, `pengy_hash`. Reini Urban's testing shows that PengyHash passes all the tests and has no bad seeds. To provide randomly generated seeds for the hash function the submodule also defines the subroutine `new_pengy_hash_seed`. The `stdlib_hash_64bit_spooky` submodule provides implementations of Bob Jenkins' SpookyHash in the form of the overloaded function, `spooky_hash`. Future implementations may provide the SpookyHash incremental hashing procedures. SpookyHash is optimized for large objects and should give excellent performance for objects greater than about 96 byes, but has significant overhead for smaller objects. The code was designed for little-endian compilers, and will give different results on big-endian compilers, but the hash quality on those compilers is probably just as good. SpookyHash version 2 passes all of Reini Urban's SMHasher tests, and has one bad seed only when reduced to a 32-bit output. Its only potential problem is undefined behavior if the key is misaligned. ## The `stdlib_hash_32bit` module ### Overview of the module Thirty two bit hash functions are primarily useful for generating hash codes and hash indices for hash tables. They tend to be less useful for generating checksums, which generally benefit from having a larger number of bits. The `stdlib_hash_32bit` module defines five public overloaded 32-bit hash code functions, `FNV_1`, `FNV-1A`, `nmhash32`, `nmhash32x` and `water_hash`, two scalar hash functions, `fibonacci_hash` and `universal_mult_hash`, four seed generators, `odd_random_integer` for `universal_mult_hash`, and `new_nmhash32_seed`, `new_nmhash32x_seed`, and `new_water_hash_seed`, for their respective hash code functions. It also defines the integer kind constant, `int_hash`, and a logical constant, `little_endian`, used to deal with one aspect of the machine dependence of the hash codes. ### The `int_hash` parameter It is necessary to define the kind of integer used to return the hash code. As `stdlib_hash_32bit` deals exclusively with 32-bit hash codes, `int_hash` is an alias for the integer kind `int32`. ### The `little_endian` parameter In implementing hash functions it is sometimes necessary to know the "endianess" of the compiler's integers. To this end the `stdlib_hash_32bit` module defines the logical parameter `little_endian` that, if true, indicates that the compiler has little-endian integers, and that if false indicates that the integers are big-endian. ### Specifications of the `stdlib_hash_32bit` procedures #### `fibonacci_hash` - maps an integer to a smaller number of bits ##### Status Experimental ##### Description Calculates an `nbits` hash code from a 32-bit integer. This is useful in mapping hash codes into small arrays. ##### Syntax `code = ` [[stdlib_hash_32bit:fibonacci_hash]] `( key, nbits )` ##### Class Elemental function ##### Arguments `key`: Shall be a scalar integer expression of kind `int32`. It is an `intent(in)` argument. `nbits` Shall be a scalar default integer expression with `0 < nbits < 32`. It is an `intent(in)` argument. ##### Result The result is an integer of kind `int32` with at most the lowest `nbits` nonzero, mapping to a range 0 to `nbits-1`. ##### Note `fibonacci_hash` is an implementation of the Fibonacci Hash of Donald E. Knuth. It multiplies the `key` by the odd valued approximation to `2**32/phi`, where `phi` is the golden ratio 1.618..., and returns the `nbits` upper bits of the product as the lowest bits of the result. ##### Example ```fortran {!example/hash_procedures/example_fibonacci_hash.f90!} ``` #### `fnv_1_hash`- calculates a hash code from a key ##### Status Experimental ##### Description Calculates a 32-bit hash code from a rank-1 integer array or a default character string. ##### Syntax `code = ` [[stdlib_hash_32bit:fnv_1_hash]] `( key )` ##### Class Pure/elemental function ##### Argument `key`: Shall be a deferred length default character scalar expression or a rank-1 integer array expression of kind `int8`, `int16`, `int32`, or `int64`. It is an `intent(in)` argument. ##### Result The result is a scalar integer of kind `int32`. ##### Note `fnv_1_hash` is an implementation of the original FNV-1 hash code of Glenn Fowler, Landon Curt Noll, and Phong Vo. It differs from typical implementations in that it also encodes the size of the structure in the hash code. This code is relatively fast on short keys, and is small enough that it will often be retained in the instruction cache if hashing is intermittent. As a result it should give good performance for typical hash table applications. This code does not pass any of the SMHasher tests, but the resulting degradation in performance due to its larger number of collisions is expected to be minor compared to its faster hashing rate. It is a *pure* function for integer arrays, and an *elemental* function for character strings. ##### Example ```fortran {!example/hash_procedures/example_fnv_1_hash.f90!} ``` #### `fnv_1a_hash`- calculates a hash code from a key ##### Status Experimental ##### Description Calculates a 32-bit hash code from a rank-1 integer array or a default character string. ##### Syntax `code = ` [[stdlib_hash_32bit:fnv_1a_hash]] `( key )` ##### Class Pure/elemental function ##### Argument `key`: Shall be a deferred length default character scalar expression or a rank-1 integer array expression of kind `int8`, `int16`, `int32`, or `int64`. It is an `intent(in)` argument. ##### Result The result is a scalar integer of kind `int32`. ##### Note `fnv_1a_hash` is an implementation of the alternative FNV-1a hash code of Glenn Fowler, Landon Curt Noll, and Phong Vo. It differs from typical implementations in that it also encodes the size of the structure in the hash code. This code is relatively fast on short keys, and is small enough that it will often be retained in the instruction cache if hashing is intermittent. As a result it should give good performance for typical hash table applications. This code does not pass any of the SMHasher tests, but the resulting degradation in performance due to its larger number of collisions is expected to be minor compared to its faster hashing rate. It is a *pure* function for integer arrays, and an *elemental* function for character strings. ##### Example ```fortran {!example/hash_procedures/example_fnv_1a_hash.f90!} ``` #### `new_nmhash32_seed`- returns a valid input seed for `nmhash32` ##### Status Experimental ##### Description Calculates a 32-bit "random" integer that is believed to be a valid seed for `nmhash32` and is also different from the input seed. ##### Syntax `call ` [[stdlib_hash_32bit:new_nmhash32_seed]] `( seed )` ##### Class Subroutine ##### Argument `seed`: shall be a defined integer scalar variable of kind `int32`. It is an `intent(inout)` argument. On input `seed` should be defined, and on output it will be different from the input `seed`. ##### Note Currently there are no known bad seeds for `nmhash32`, but if any are identified the procedure will be revised so that they cannot be returned. This subroutine uses Fortran's intrinsic `random_number` and the values returned can be changed by calling the intrinsic `random_init`. ##### Example See the example for `nmhash32`. #### `new_nmhash32x_seed`- returns a valid input seed for `nmhash32x` ##### Status Experimental ##### Description Calculates a 32-bit "random" integer that is believed to be a valid seed for `nmhash32x` and is also different from the input seed. ##### Syntax `call ` [[stdlib_hash_32bit:new_nmhash32x_seed]] `( seed )` ##### Class Subroutine ##### Argument `seed`: shall be a defined integer scalar variable of kind `int32`. It is an `intent(inout)` argument. On input `seed` should be defined, and on output it will be different from the input `seed`. ##### Note Currently there are no known bad seeds for `nmhash32x`, but if any are identified the procedure will be revised so that they cannot be returned. This subroutine uses Fortran's intrinsic `random_number` and the values returned can be changed by calling the intrinsic `random_init`. ##### Example See the example for `nmhash32x`. #### `new_water_hash_seed`- returns a valid input seed for `water_hash` ##### Status Experimental ##### Description Calculates a 64-bit "random" integer that is believed to be a valid seed for `water_hash` and is also different from the input seed. ##### Syntax `call ` [[stdlib_hash_32bit:new_water_hash_seed]] `( seed )` ##### Class Subroutine ##### Argument `seed`: shall be a defined integer scalar variable of kind `int64`. It is an `intent(inout)` argument. On input `seed` should be defined, and on output it will be different from the input `seed`. ##### Note Currently there are no known bad seeds for `water_hash`, but if any are identified the procedure will be revised so that they cannot be returned. This subroutine uses Fortran's intrinsic `random_number` and the values returned can be changed by calling the intrinsic `random_init`. ##### Example See the example for `water_hash`. #### `nmhash32`- calculates a hash code from a key and a seed ##### Status Experimental ##### Description Calculates a 32-bit hash code from a rank-1 integer array or a default character string, and the input `seed`. ##### Syntax `code = ` [[stdlib_hash_32bit:nmhash32]] `( key, seed )` ##### Class Pure/elemental function ##### Arguments `key`: Shall be a deferred length default character scalar expression or a rank-1 integer array expression of kind `int8`, `int16`, `int32`, or `int64`. It is an `intent(in)` argument. `seed`: shall be an integer scalar expression of kind `int32`. It is an `intent(in)` argument. ##### Result The result is a scalar integer of kind `int32`. ##### Note `nmhash32` is an implementation of the `nmhash32` hash code of James Z. M. Gao. This code has good, but not great, performance on long keys, poorer performance on short keys. As a result it should give fair performance for typical hash table applications. This code passes the SMHasher tests, and has no known bad seeds. It is a *pure* function for integer arrays, and an *elemental* function for character strings. ##### Example ```fortran {!example/hash_procedures/example_nmhash32.f90!} ``` #### `nmhash32x`- calculates a hash code from a key and a seed ##### Status Experimental ##### Description Calculates a 32-bit hash code from a rank-1 integer array or a default character string, and the input `seed`. ##### Syntax `code = ` [[stdlib_hash_32bit:nmhash32x]] `( key, seed )` ##### Class Pure/elemental function ##### Arguments `key`: Shall be a deferred length default character scalar expression or a rank-1 integer array expression of kind `int8`, `int16`, `int32`, or `int64`. It is an `intent(in)` argument. `seed`: shall be an integer scalar expression of kind `int32`. It is an `intent(in)` argument. ##### Result The result is a scalar integer of kind `int32`. ##### Note `nmhash32x` is an implementation of the `nmhash32x` hash code of James Z. M. Gao. This code has good, but not great, performance on long keys, poorer performance on short keys. As a result it should give fair performance for typical hash table applications. This code passes the SMHasher tests, and has no known bad seeds. It is a *pure* function for integer arrays, and an *elemental* function for character strings. ##### Example ```fortran {!example/hash_procedures/example_nmhash32x.f90!} ``` #### `odd_random_integer` - returns an odd integer ##### Status Experimental ##### Description Returns a random 32-bit integer distributed uniformly over the odd values. ##### Syntax `call ` [[stdlib_hash_32bit:odd_random_integer]] `( harvest )` ##### Class Subroutine ##### Argument `harvest`: Shall be a scalar integer variable of kind `int32`. It is an `intent(out)` argument. ##### Note `odd_random_integer` is intended to generate seeds for `universal_mult_hash`. `odd_random_integer` uses Fortran's intrinsic `random_number` and the values returned can be changed by calling the intrinsic `random_init`. ##### Example See `universal_mult_hash`. #### `universal_mult_hash` - maps an integer to a smaller number of bits ##### Status Experimental ##### Description Calculates an `nbits` hash code from a 32-bit integer. This is useful in mapping a hash value to a range 0 to `2**nbits-1`. ##### Syntax `code = ` [[stdlib_hash_32bit:universal_mult_hash]] `( key, seed, nbits )` ##### Class Elemental function ##### Arguments `key`: Shall be a scalar integer expression of kind `int32`. It is an `intent(in)` argument. `seed`: Shall be a scalar integer expression of kind `int32`. It is an `intent(in)` argument. It must have an odd value. `nbits` Shall be a scalar default integer expression with `0 < nbits < 32`. It is an `intent(in)` argument. ##### Result The result is a scalar integer of kind `int32` with at most the lowest `nbits` nonzero. ##### Note `universal_mult_hash` is an implementation of the Universal Multiplicative Hash of M. Dietzfelbinger, et al. It multiplies the `key` by `seed`, and returns the `nbits` upper bits of the product as the lowest bits of the result. ##### Example ```fortran {!example/hash_procedures/example_universal_mult_hash.f90!} ``` #### `water_hash`- calculates a hash code from a key and a seed ##### Status Experimental ##### Description Calculates a 32-bit hash code from a rank-1 integer array or a default character string, and the input `seed`. ##### Syntax `code = ` [[stdlib_hash_32bit:water_hash]] `( key, seed )` ##### Class Pure/elemental function ##### Arguments `key`: Shall be a deferred length default character scalar expression or a rank-1 integer array expression of kind `int8`, `int16`, `int32`, or `int64`. It is an `intent(in)` argument. `seed`: shall be an integer scalar expression of kind `int64`. It is an `intent(in)` argument. ##### Result The result is a scalar integer of kind `int32`. ##### Note `water_hash` is an implementation of the `waterhash` hash code of Tommy Ettinger. This code has excellent performance on long keys, and good performance on short keys. As a result it should give reasonable performance for typical hash table applications. This code passes the SMHasher tests. The `waterhash` is based on the `wyhash` of Wang Yi. While `wyhash` has a number of bad seeds, where randomization of the output is poor, so far testing has not found any bad seeds for `waterhash`. It can have undefined behavior if the key is not word aligned, i.e. some computer processors can only process a given size integer if the address of the integer is a multiple of the integer size. It is a *pure* function for integer arrays, and an *elemental* function for character strings. ##### Example ```fortran {!example/hash_procedures/example_water_hash.f90!} ``` ## The `stdlib_hash_64bit` module ### Overview of the module Sixty-four bit hash functions are generally overkill for hash table applications, and are primarily useful for check sums and related applications. As checksums often have to deal with extremely large files or directories, it is often useful to use incremental hashing as well as direct hashing, so 64-bit and higher hash algorithms often provide multiple implementations. The current module, for simplicity of API, doesn't provide any incremental hashes. The `stdlib_hash_64bit` module defines several public overloaded 64-bit hash procedures, `FNV_1`, `FNV-1A`, `pengy_hash`, and `spooky_hash`, two scalar hash functions, `fibonacci_hash` and `universal_mult_hash`, a seed generator, `odd_random_integer`, for the `universal_mult_hash`, and two seed generators, `new_pengy_hash_seed` and `new_spooky_hash_seed` for their respective hash functions. It also defines the integer kind constant, `int_hash`, used to specify the kind of the hash function results, and a logical constant, `little_endian`, used to deal with one aspect of the machine dependence of the hash codes. Note that while SpookyHash can be used as a sixty-four bit hash algorithm, its algorithms actually returns two element integer arrays of kind `int64`, so it can also be used as a 128 bit hash. ### The `int_hash` parameters It is necessary to define the kind of integer used to return the hash code. As `stdlib_haash_64bit` deals exclusively with 64-bit hash codes, `int_hash` is an alias for the integer kind `int64`. ### The `little_endian` parameter In implementing hash functions it is sometimes necessary to know the "endianess" of the compiler's integers. To this end the `stdlib_hash_64bit` module defines the logical parameter `little_endian` that if true indicates that the compiler has little-endian integers, and that if false indicates that the integers are big-endian. ### Specifications of the `stdlib_hash_64bit` procedures #### `fibonacci_hash` - maps an integer to a smaller number of bits ##### Status Experimental ##### Description Calculates an `nbits` hash code from a 64-bit integer. This is useful in mapping hash codes into small arrays. ##### Syntax `code = ` [[stdlib_hash_64bit:fibonacci_hash]] `( key, nbits )` ##### Class Elemental function ##### Arguments `key`: Shall be a scalar integer expression of kind `int64`. It is an `intent(in)` argument. `nbits` Shall be a scalar default integer expression with `0 < nbits < 64`. It is an `intent(in)` argument. ##### Result The result is an integer of kind `int64` with at most the lowest `nbits` nonzero, mapping to a range 0 to `nbits-1`. ##### Note `fibonacci_hash` is an implementation of the Fibonacci Hash of Donald E. Knuth. It multiplies the `key` by the odd valued approximation to `2**64/phi`, where `phi` is the golden ratio 1.618..., and returns the `nbits` upper bits of the product as the lowest bits of the result. ##### Example ```fortran {!example/hash_procedures/example_fibonacci_hash_64.f90!} ``` #### `FNV_1`- calculates a hash code from a key ##### Status Experimental ##### Description Calculates a 64-bit hash code from a rank-1 integer array or a default character string. ##### Syntax `code = ` [[stdlib_hash_64bit:fnv_1_hash]] `( key )` ##### Class Pure/elemental function ##### Argument `key`: Shall be a deferred length default character scalar expression or a rank-1 integer array expression of kind `int8`, `int16`, `int32`, or `int64`. It is an `intent(in)` argument. ##### Result The result is a scalar integer of kind `int64`. ##### Note `FNV_1` is an implementation of the original FNV-1 hash code of Glenn Fowler, Landon Curt Noll, and Phong Vo. It differs from typical implementations in that it also ecodes the size of the structure in the hash code. This code is relatively fast on short keys, and is small enough that it will often be retained in the instruction cache if hashing is intermittent. As a result it should give good performance for typical hash table applications, although it is rare for them to need 64 bits. This code does not pass any of the SMHasher tests, but the resulting degradation in performance due to its larger number of collisions is expected to be minor compared to its faster hashing rate. It is a *pure* function for integer arrays, and an *elemental* function for character strings. ##### Example ```fortran {!example/hash_procedures/example_fnv_1_hash_64.f90!} ``` #### `FNV_1A`- calculates a hash code from a key ##### Status Experimental ##### Description Calculates a 64-bit hash code from a rank-1 integer array or a default character string. ##### Syntax `code = ` [[stdlib_hash_64bit:fnv_1a_hash]] `( key )` ##### Class Pure/elemental function ##### Argument `key`: Shall be a deferred length default character scalar expression or a rank-1 integer array expression of kind `int8`, `int16`, `int32`, or `int64`. It is an `intent(in)` argument. ##### Result The result is a scalar integer of kind `int32`. ##### Note `FNV_1A` is an implementation of the alternative FNV-1a hash code of Glenn Fowler, Landon Curt Noll, and Phong Vo. It differs from typical implementations in that it also encodes the size of the structure in the hash code. This code is relatively fast on short keys, and is small enough that it will often be retained in the instruction cache if hashing is intermittent. As a result it should give good performance for typical hash table applications. This code does not pass any of the SMHasher tests, but the resulting degradation in performance due to its larger number of collisions is expected to be minor compared to its faster hashing rate. It is a *pure* function for integer arrays, and an *elemental* function for character strings. ##### Example ```fortran {!example/hash_procedures/example_fnv_1a_hash_64.f90!} ``` #### `new_pengy_hash_seed`- returns a valid input seed for `pengy_hash` ##### Status Experimental ##### Description Calculates a 32-bit "random" integer that is believed to be a valid seed for `pengy_hash` and is also different from the input seed. ##### Syntax `call ` [[stdlib_hash_64bit:new_pengy_hash_seed]] `( seed )` ##### Class Subroutine ##### Argument `seed`: shall be a defined integer scalar variable of kind `int32`. It is an `intent(inout)` argument. On input `seed` should be defined, and on output it will be different from the input `seed`. ##### Note Currently there are no known bad seeds for `pengy_hash`, but if any are identified the procedure will be revised so that they cannot be returned. This subroutine uses Fortran's intrinsic `random_number` and the values returned can be changed by calling the intrinsic `random_init`. ##### Example See the example for `pengy_hash`. #### `new_spooky_hash_seed`- returns a valid input seed for `spooky_hash` ##### Status Experimental ##### Description Calculates a 32-bit two element vector of "random" integer values that is believed to be a valid seed for `spooky_hash` and is also different from the input seed. ##### Syntax `call ` [[stdlib_hash_64bit:new_spooky_hash_seed]] `( seed )` ##### Class Subroutine ##### Argument `seed`: shall be a defined two element integer vector variable of kind `int32`. It is an `intent(inout)` argument. On input `seed` should be defined, and on output it will be different from the input `seed`. ##### Note Currently there are no known bad seeds for `spooky_hash`, but if any are identified the procedure will be revised so that they cannot be returned. This subroutine uses Fortran's intrinsic `random_number` and the values returned can be changed by calling the intrinsic `random_init`. ##### Example See the example for `spooky_hash`. #### `odd_random_integer` - returns odd integer ##### Status Experimental ##### Description Returns a random 64-bit integer distributed uniformly over the odd values. ##### Syntax `call ` [[stdlib_hash_64bit:odd_random_integer]] `( harvest )` ##### Class Subroutine ##### Argument `harvest`: Shall be an integer of kind `int64`. It is an `intent(out)` argument. ##### Note `odd_random_integer` is intended to generate seeds for `universal_mult_hash`. `odd_random_integer` uses Fortran's intrinsic `random_number` and the values returned can be changed by calling the intrinsic `random_init`. ##### Example See `universal_mult_hash`. #### `pengy_hash` - maps a character string or integer vector to an integer ##### Status Experimental ##### Description Maps a character string or integer vector to a 64-bit integer whose value also depends on a scalar 32-bit integer, `seed`. ##### Syntax `code = ` [[stdlib_hash_64bit:pengy_hash]] `( key, seed )` ##### Class Pure/elemental function ##### Arguments `key`: shall be a scalar expression of type default character or a rank-1 integer vector expression of kind `int8`, `int16`, `int32`, or `int64`. It is an `intent(in)` argument. `seed`: shall be an integer expression of kind `int64`. It is an `intent(in)` argument. ##### Result The result is an integer of kind `int64`. ##### Note `pengy_hash` is an implementation of the 64-bit `pengyhash` of Alberto Fajardo. The hash has acceptable performance on small keys, and good performance on long keys. It passes all the SMHasher tests, and has no known bad seeds. It is a *pure* function for integer arrays, and an *elemental* function for character strings. ##### Example ```fortran {!example/hash_procedures/example_pengy_hash.f90!} ``` #### `spooky_hash` - maps a character string or integer vector to an integer ##### Status Experimental ##### Description Maps a character string or integer vector to a 64-bit integer whose value also depends on a two element vector, `seed`. ##### Syntax `code = ` [[stdlib_hash_64bit:spooky_hash]] `( key, seed )` ##### Class Function ##### Arguments `key`: shall be a scalar of type default character expression or a rank-1 integer vector expression of kind `int8`, `int16`, `int32`, or `int64`. It is an `intent(in)` argument. `seed`: shall be a two element integer vector expression of kind `int64`. It is an `intent(in)` argument. ##### Result The result is a two element integer vector of kind `int64`. ##### Note `spooky_hash` is an implementation of the 64-bit version 2 of SpookyHash of Bob Jenkins. The code was designed for little-endian compilers. The output is different on big-endian compilers, but still probably as good quality. It is often used as a 64-bit hash using the first element of the returned value, but can be used as a 128 bit hash. This version of `spooky_hash` has good performance on small keys and excellent performance on long keys. It passes all the SMHasher tests and has no known bad seeds. ##### Example ```fortran {!example/hash_procedures/example_spooky_hash.f90!} ``` #### `universal_mult_hash` - maps an integer to a smaller number of bits ##### Status Experimental ##### Description Calculates an `nbits` hash code from a 64-bit integer. This is useful in mapping a hash value to a range 0 to `2**nbits-1`. ##### Syntax `code = ` [[stdlib_hash_64bit:universal_mult_hash]] `( key, seed, nbits )` ##### Class Elemental function ##### Arguments `key`: Shall be an integer of kind `int64`. It is an `intent(in)` argument. `seed`: Shall be an integer of kind `int64`. It is an `intent(in)` argument. It should be an odd value. `nbits` Shall be a default integer with `0 < nbits < 64`. It is an `intent(in)` argument. It must be an odd integer. ##### Result The result is an integer of kind `int64` with at most the lowest `nbits` nonzero. ##### Note `universal_mult_hash` is an implementation of the Universal Multiplicative Hash of M. Dietzfelbinger, et al. It multiplies the `key` by `seed`, and returns the `nbits` upper bits of the product as the lowest bits of the result. ##### Example ```fortran {!example/hash_procedures/example_universal_mult_hash_64.f90!} ``` ### Test Codes The Fortran Standard Library provides two categories of test codes. One category is tests of the relative performance of the various hash functions. The other is a comparison of the outputs of the Fortran hash functions, with the outputs of the C and C++ hash procedures that are the inspiration for the Fortran hash functions. In the `test/hash_functions_perf` subdirectory, the Fortran Standard Library provides two performance test codes for the hash functions of `stdlib_hash_32bit` and `stdlib_hash_64bit`, `test_32_bit_hash_performance` and `test_64_bit_hash_performance` respectively. These are primarily set up to test runtime performance of the functions. They take a sample of `2**18` integers of kind `int8` and break it up into vectors of size 1, 2, 4, 8, 16, 64, 256, and 1024 elements, yielding `2**18`, `2**17`, `2**16`, `2**15`, `2**14`, `2**12`, `2**10`, and `2**8` vectors respectively. These are then processed by the hash functions 4 times, and the time for processing is reported. Testing so far has been on a MacBook Pro with a 2.3 GHz Quad-Core Intel Core i5 and 8 GB 2133 MHz LPDDR3 of RAM, using GNU Fortran (GCC) 11.1.0 to compile the code. The results for `test_32_bit_hash_performance` is given by the following table: | Algorithm | Key Size Bytes | Key # | Time (s) | |------------|:---------:|:----------:|:--------:| | FNV-1 | 1 | 1048576 | 0.02949 | | FNV-1 | 2 | 524288 | 0.02361 | | FNV-1 | 4 | 262144 | 0.02016 | | FNV-1 | 8 | 131072 | 0.01806 | | FNV-1 | 16 | 65536 | 0.01867 | | FNV-1 | 64 | 16384 | 0.01717 | | FNV-1 | 256 | 4096 | 0.01759 | | FNV-1 | 1024 | 1024 | 0.01659 | | FNV-1a | 1 | 1048576 | 0.02897 | | FNV-1a | 2 | 524288 | 0.02472 | | FNV-1a | 4 | 262144 | 0.02025 | | FNV-1a | 8 | 131072 | 0.01901 | | FNV-1a | 16 | 65536 | 0.01898 | | FNV-1a | 64 | 16384 | 0.01784 | | FNV-1a | 256 | 4096 | 0.01723 | | FNV-1a | 1024 | 1024 | 0.01673 | | nmhash32 | 1 | 1048576 | 0.31092 | | nmhash32 | 2 | 524288 | 0.16230 | | nmhash32 | 4 | 262144 | 0.07815 | | nmhash32 | 8 | 131072 | 0.04176 | | nmhash32 | 16 | 65536 | 0.09261 | | nmhash32 | 64 | 16384 | 0.04587 | | nmhash32 | 256 | 4096 | 0.07238 | | nmhash32 | 1024 | 1024 | 0.07263 | | nmhash32x | 1 | 1048576 | 0.04294 | | nmhash32x | 2 | 524288 | 0.02937 | | nmhash32x | 4 | 262144 | 0.01096 | | nmhash32x | 8 | 131072 | 0.00911 | | nmhash32x | 16 | 65536 | 0.01291 | | nmhash32x | 64 | 16384 | 0.00859 | | nmhash32x | 256 | 4096 | 0.07373 | | nmhash32x | 1024 | 1024 | 0.07618 | | water | 1 | 1048576 | 0.12560 | | water | 2 | 524288 | 0.06302 | | water | 4 | 262144 | 0.04020 | | water | 8 | 131072 | 0.01999 | | water | 16 | 65536 | 0.01459 | | water | 64 | 16384 | 0.00923 | | water | 256 | 4096 | 0.00816 | | water | 1024 | 1024 | 0.00792 | while for `test_64_bit_hash_performance` the results are: | Algorithm | Key Size Bytes | Key # | Time (s) | |------------|:---------:|:----------:|:--------:| | FNV-1 | 1 | 1048576 | 0.02981 | | FNV-1 | 2 | 524288 | 0.02697 | | FNV-1 | 4 | 262144 | 0.02275 | | FNV-1 | 8 | 131072 | 0.02431 | | FNV-1 | 16 | 65536 | 0.02158 | | FNV-1 | 64 | 16384 | 0.02007 | | FNV-1 | 256 | 4096 | 0.01932 | | FNV-1 | 1024 | 1024 | 0.02089 | | FNV-1a | 1 | 1048576 | 0.03226 | | FNV-1a | 2 | 524288 | 0.03076 | | FNV-1a | 4 | 262144 | 0.02359 | | FNV-1a | 8 | 131072 | 0.02542 | | FNV-1a | 16 | 65536 | 0.02364 | | FNV-1a | 64 | 16384 | 0.02130 | | FNV-1a | 256 | 4096 | 0.01962 | | FNV-1a | 1024 | 1024 | 0.01966 | | Pengy | 1 | 1048576 | 0.24294 | | Pengy | 2 | 524288 | 0.12066 | | Pengy | 4 | 262144 | 0.06205 | | Pengy | 8 | 131072 | 0.03138 | | Pengy | 16 | 65536 | 0.01608 | | Pengy | 64 | 16384 | 0.00669 | | Pengy | 256 | 4096 | 0.00387 | | Pengy | 1024 | 1024 | 0.00295 | | Spooky | 1 | 1048576 | 0.11920 | | Spooky | 2 | 524288 | 0.07478 | | Spooky | 4 | 262144 | 0.03185 | | Spooky | 8 | 131072 | 0.01468 | | Spooky | 16 | 65536 | 0.01503 | | Spooky | 64 | 16384 | 0.00440 | | Spooky | 256 | 4096 | 0.00290 | | Spooky | 1024 | 1024 | 0.00177 | As the tested function will typically reside in the instruction cache these results do not include the costs of reloading the procedure if hashing is intermittent. If hashing is intermittent then that can more severely impact the performance of `nmhash32`, `nmhash32x`, `water_hash`, `pengy_hash`, and `spooky_hash` relative to `fnv_1_hash` and `fnv_1a_hash`. In the `test/hash_functions` subdirectory, the Fortran Standard Library contains codes to test the validity of the Fortran codes against the original C and C++ codes. It consists of one executable `test_hash_functions` that 1) generates a random sequence of 2048 integers of kind `int8`, and stores that sequence in the binary file `key_array.bin`; 2) reads the values in `key_array.bin`, and, for each complicated C/C++-coded hash procedure, generates a corresponding binary file containing 2049 hash values generated from the values in `key_array.bin`., and 3) reads the binary files, and, for each complicated C/C++-coded hash procedure, compares the contents of the binary file with the results of calculating hash values using the corresponding Fortran hash procedure on the same keys. fortran-lang-stdlib-0ede301/doc/specs/stdlib_linalg_iterative_solvers.md0000664000175000017500000003770715135654166027050 0ustar alastairalastair--- title: linalg_iterative_solvers --- # The `stdlib_linalg_iterative_solvers` module [TOC] ## Introduction The `stdlib_linalg_iterative_solvers` module provides base implementations for known iterative solver methods. Each method is exposed with two procedure flavors: * A `stdlib_solve__kernel` which holds the method's base implementation. The linear system argument is defined through a `stdlib_linop` derived type which enables extending the method for implicit or unknown (by `stdlib`) matrices or to complex scenarios involving distributed parallelism for which the user shall extend the `inner_product` and/or matrix-vector product to account for parallel syncrhonization. * A `stdlib_solve_` which proposes an off-the-shelf ready to use interface for `dense` and `CSR__type` matrices for all `real` kinds. ### The `stdlib_linop` derived type The `stdlib_linop__type` derive type is an auxiliary class enabling to abstract the definition of the linear system and the actual implementation of the solvers. #### Type-bound procedures The following type-bound procedure pointers enable customization of the solver: ##### `matvec` Proxy procedure for the matrix-vector product \( y = alpha * op(M) * x + beta * y \). #### Syntax `call ` [[stdlib_linalg_iterative_solvers(module):stdlib_linop_dp_type(type)]] `%matvec(x,y,alpha,beta,op)` ###### Class Subroutine ###### Argument(s) `x`: 1-D array of `real()`. This argument is `intent(in)`. `y`: 1-D array of `real()`. This argument is `intent(inout)`. `alpha`: scalar of `real()`. This argument is `intent(in)`. `beta`: scalar of `real()`. This argument is `intent(in)`. `op`: `character(1)` scalar which can be have any of the following values: `N` (no transpose), `T` (transpose) or `H` (conjugate transpose). This argument is `intent(in)`. ##### `inner_product` Proxy procedure for the `dot_product`. #### Syntax `res = ` [[stdlib_linalg_iterative_solvers(module):stdlib_linop_dp_type(type)]] `%inner_product(x,y)` ###### Class Function ###### Argument(s) `x`: 1-D array of `real()`. This argument is `intent(in)`. `y`: 1-D array of `real()`. This argument is `intent(in)`. ###### Output value or Result value The output is a scalar of `type` and `kind` same as to that of `x` and `y`. ### The `solver_workspace` derived type The `stdlib_solver_workspace__type` derive type is an auxiliary class enabling to hold the data associated to the working arrays needed by the solvers to operate. #### Type-bound procedures - `callback`: null pointer procedure enabling to pass a callback at each iteration to check on the solvers status. ##### Class Subroutine ##### Argument(s) `x`: 1-D array of `real()` type with the current state of the solution vector. This argument is `intent(in)` as it should not be modified by the callback. `norm_sq`: scalar of `real()` type representing the squared norm of the residual at the current iteration. This argument is `intent(in)`. `iter`: scalar of `integer` type giving the current iteration counter. This argument is `intent(in)`. ### `stdlib_solve_cg_kernel` subroutine #### Description Implements the Conjugate Gradient (CG) method for solving the linear system \( Ax = b \), where \( A \) is a symmetric positive-definite linear operator defined via the `stdlib_linop` type. This is the core implementation, allowing flexibility for custom matrix types or parallel environments. #### Syntax `call ` [[stdlib_linalg_iterative_solvers(module):stdlib_solve_cg_kernel(interface)]] ` (A, b, x, tol, maxiter, workspace)` #### Status Experimental #### Class Subroutine #### Argument(s) `A`: `class(stdlib_linop__type)` defining the linear operator. This argument is `intent(in)`. `b`: 1-D array of `real()` defining the loading conditions of the linear system. This argument is `intent(in)`. `x`: 1-D array of `real()` which serves as the input initial guess and the output solution. This argument is `intent(inout)`. `rtol` and `atol`: scalars of type `real()` specifying the convergence test. For convergence, the following criterion is used \( || b - Ax ||^2 <= max(rtol^2 * || b ||^2 , atol^2 ) \). These arguments are `intent(in)`. `maxiter`: scalar of type `integer` defining the maximum allowed number of iterations. This argument is `intent(in)`. `workspace`: scalar derived type of `type(stdlib_solver_workspace__type)` holding the work array for the solver. This argument is `intent(inout)`. ### `solve_cg` subroutine #### Description Provides a user-friendly interface to the CG method for solving \( Ax = b \), supporting `dense` and `CSR__type` matrices. It handles workspace allocation and optional parameters for customization. #### Syntax `call ` [[stdlib_linalg_iterative_solvers(module):stdlib_solve_cg(interface)]] ` (A, b, x [, di, rtol, atol, maxiter, restart, workspace])` #### Status Experimental #### Class Subroutine #### Argument(s) `A`: `dense` or `CSR__type` matrix defining the linear system. This argument is `intent(in)`. `b`: 1-D array of `real()` defining the right-hand-side (or loading) of the linear system. This argument is `intent(in)`. `x`: 1-D array of `real()` which serves as the input initial guess and as the output solution. This argument is `intent(inout)`. `di` (optional): 1-D mask array of type `logical(int8)` defining the degrees of freedom subject to dirichlet boundary conditions. The actual boundary conditions values should be stored in the `b` load array. This argument is `intent(in)`. `rtol` and `atol` (optional): scalars of type `real()` specifying the convergence test. For convergence, the following criterion is used \( || b - Ax ||^2 <= max(rtol^2 * || b ||^2 , atol^2 ) \). Defaults values are `rtol=1.e-5` and `atol=epsilon(1._)`. These arguments are `intent(in)`. `maxiter` (optional): scalar of type `integer` defining the maximum allowed number of iterations. If no value is given, a default of `N` is set, where `N = size(b)`. This argument is `intent(in)`. `workspace` (optional): scalar derived type of `type(stdlib_solver_workspace__type)` holding the work array for the solver. If the user passes its own `workspace`, then a pointer is set internally to it. Otherwise, memory will be internally allocated and deallocated before exiting the procedure. This argument is `intent(inout)`. #### Example ```fortran {!example/linalg/example_solve_cg.f90!} ``` ### `stdlib_solve_pcg_kernel` subroutine #### Description Implements the Preconditioned Conjugate Gradient (PCG) method for solving the linear system \( Ax = b \), where \( A \) is a symmetric positive-definite linear operator defined via the `stdlib_linop` type. This is the core implementation, allowing flexibility for custom matrix types or parallel environments. #### Syntax `call ` [[stdlib_linalg_iterative_solvers(module):stdlib_solve_cg_kernel(interface)]] ` (A, M, b, x, tol, maxiter, workspace)` #### Status Experimental #### Class Subroutine #### Argument(s) `A`: `class(stdlib_linop__type)` defining the linear operator. This argument is `intent(in)`. `M`: `class(stdlib_linop__type)` defining the preconditioner linear operator. This argument is `intent(in)`. `b`: 1-D array of `real()` defining the loading conditions of the linear system. This argument is `intent(in)`. `x`: 1-D array of `real()` which serves as the input initial guess and the output solution. This argument is `intent(inout)`. `rtol` and `atol` (optional): scalars of type `real()` specifying the convergence test. For convergence, the following criterion is used \( || b - Ax ||^2 <= max(rtol^2 * || b ||^2 , atol^2 ) \). These arguments are `intent(in)`. `maxiter`: scalar of type `integer` defining the maximum allowed number of iterations. This argument is `intent(in)`. `workspace`: scalar derived type of `type(stdlib_solver_workspace__type)` holding the work array for the solver. This argument is `intent(inout)`. #### Example ```fortran {!example/linalg/example_solve_custom.f90!} ``` ### `stdlib_solve_pcg` subroutine #### Description Provides a user-friendly interface to the PCG method for solving \( Ax = b \), supporting `dense` and `CSR__type` matrices. It supports optional preconditioners and handles workspace allocation. #### Syntax `call ` [[stdlib_linalg_iterative_solvers(module):stdlib_solve_pcg(interface)]] ` (A, b, x [, di, tol, maxiter, restart, precond, M, workspace])` #### Status Experimental #### Class Subroutine #### Argument(s) `A`: `dense` or `CSR__type` matrix defining the linear system. This argument is `intent(in)`. `b`: 1-D array of `real()` defining the loading conditions of the linear system. This argument is `intent(in)`. `x`: 1-D array of `real()` which serves as the input initial guess and the output solution. This argument is `intent(inout)`. `di` (optional): 1-D mask array of type `logical(int8)` defining the degrees of freedom subject to dirichlet boundary conditions. The actual boundary conditions values should be stored in the `b` load array. This argument is `intent(in)`. `rtol` and `atol` (optional): scalars of type `real()` specifying the convergence test. For convergence, the following criterion is used \( || b - Ax ||^2 <= max(rtol^2 * || b ||^2 , atol^2 ) \). Defaults values are `rtol=1.e-5` and `atol=epsilon(1._)`. These arguments are `intent(in)`. `maxiter` (optional): scalar of type `integer` defining the maximum allowed number of iterations. If no value is given, a default of `N` is set, where `N = size(b)`. This argument is `intent(in)`. `precond` (optional): scalar of type `integer` enabling to switch among the default preconditioners available with the following enum (`pc_none`, `pc_jacobi`). If no value is given, no preconditionning will be applied. This argument is `intent(in)`. `M` (optional): scalar derived type of `class(stdlib_linop__type)` defining a custom preconditioner linear operator. If given, `precond` will have no effect, a pointer is set to this custom preconditioner. `workspace` (optional): scalar derived type of `type(stdlib_solver_workspace__type)` holding the work temporal array for the solver. If the user passes its own `workspace`, then internally a pointer is set to it, otherwise, memory will be internally allocated and deallocated before exiting the procedure. This argument is `intent(inout)`. #### Example ```fortran {!example/linalg/example_solve_pcg.f90!} ``` ### `stdlib_solve_bicgstab_kernel` subroutine #### Description Implements the Biconjugate Gradient Stabilized (BiCGSTAB) method for solving the linear system \( Ax = b \), where \( A \) is a general (non-symmetric) linear operator defined via the `stdlib_linop` type. BiCGSTAB is particularly suitable for solving non-symmetric linear systems and provides better stability than the basic BiCG method. This is the core implementation, allowing flexibility for custom matrix types or parallel environments. #### Syntax `call ` [[stdlib_linalg_iterative_solvers(module):stdlib_solve_bicgstab_kernel(interface)]] ` (A, M, b, x, rtol, atol, maxiter, workspace)` #### Status Experimental #### Class Subroutine #### Argument(s) `A`: `class(stdlib_linop__type)` defining the linear operator. This argument is `intent(in)`. `M`: `class(stdlib_linop__type)` defining the preconditioner linear operator. This argument is `intent(in)`. `b`: 1-D array of `real()` defining the loading conditions of the linear system. This argument is `intent(in)`. `x`: 1-D array of `real()` which serves as the input initial guess and the output solution. This argument is `intent(inout)`. `rtol` and `atol`: scalars of type `real()` specifying the convergence test. For convergence, the following criterion is used \( || b - Ax ||^2 <= max(rtol^2 * || b ||^2 , atol^2 ) \). These arguments are `intent(in)`. `maxiter`: scalar of type `integer` defining the maximum allowed number of iterations. This argument is `intent(in)`. `workspace`: scalar derived type of `type(stdlib_solver_workspace__type)` holding the work array for the solver. This argument is `intent(inout)`. #### Note The BiCGSTAB method requires 8 auxiliary vectors in its workspace, making it more memory-intensive than CG or PCG methods. However, it can handle general non-symmetric matrices and often converges faster than BiCG for many problems. ### `stdlib_solve_bicgstab` subroutine #### Description Provides a user-friendly interface to the BiCGSTAB method for solving \( Ax = b \), supporting `dense` and `CSR__type` matrices. BiCGSTAB is suitable for general (non-symmetric) linear systems and supports optional preconditioners for improved convergence. It handles workspace allocation and optional parameters for customization. #### Syntax `call ` [[stdlib_linalg_iterative_solvers(module):stdlib_solve_bicgstab(interface)]] ` (A, b, x [, di, rtol, atol, maxiter, restart, precond, M, workspace])` #### Status Experimental #### Class Subroutine #### Argument(s) `A`: `dense` or `CSR__type` matrix defining the linear system. This argument is `intent(in)`. `b`: 1-D array of `real()` defining the loading conditions of the linear system. This argument is `intent(in)`. `x`: 1-D array of `real()` which serves as the input initial guess and the output solution. This argument is `intent(inout)`. `di` (optional): 1-D mask array of type `logical(int8)` defining the degrees of freedom subject to dirichlet boundary conditions. The actual boundary condition values should be stored in the `b` load array. This argument is `intent(in)`. `rtol` and `atol` (optional): scalars of type `real()` specifying the convergence test. For convergence, the following criterion is used \( || b - Ax ||^2 <= max(rtol^2 * || b ||^2 , atol^2 ) \). Default values are `rtol=1.e-5` and `atol=epsilon(1._)`. These arguments are `intent(in)`. `maxiter` (optional): scalar of type `integer` defining the maximum allowed number of iterations. If no value is given, a default of `N` is set, where `N = size(b)`. This argument is `intent(in)`. `restart` (optional): scalar of type `logical` indicating whether to restart the iteration with zero initial guess. Default is `.true.`. This argument is `intent(in)`. `precond` (optional): scalar of type `integer` enabling to switch among the default preconditioners available with the following enum (`pc_none`, `pc_jacobi`). If no value is given, no preconditioning will be applied. This argument is `intent(in)`. `M` (optional): scalar derived type of `class(stdlib_linop__type)` defining a custom preconditioner linear operator. If given, `precond` will have no effect, and a pointer is set to this custom preconditioner. This argument is `intent(in)`. `workspace` (optional): scalar derived type of `type(stdlib_solver_workspace__type)` holding the work temporal array for the solver. If the user passes its own `workspace`, then internally a pointer is set to it, otherwise, memory will be internally allocated and deallocated before exiting the procedure. This argument is `intent(inout)`. #### Note BiCGSTAB is particularly effective for: - Non-symmetric linear systems - Systems where CG cannot be applied - Cases where BiCG suffers from irregular convergence The method uses 8 auxiliary vectors internally, requiring more memory than simpler methods but often providing better stability and convergence properties. #### Example 1 ```fortran {!example/linalg/example_solve_bicgstab.f90!} ``` #### Example 2 ```fortran {!example/linalg/example_solve_bicgstab_wilkinson.f90!} ```fortran-lang-stdlib-0ede301/doc/specs/stdlib_version.md0000664000175000017500000000274315135654166023426 0ustar alastairalastair--- title: version --- # The `stdlib_version` module [TOC] ## Introduction The `stdlib_version` module contains the version of the standard library. The version information can be used as a compile time constant or retrieved from a getter function at runtime. In case the standard library is dynamically linked, the version number retrieved from the getter might mismatch the compile time constants provided from the version built against. Therefore, it is recommended to retrieve the version information always at runtime. ## Constants provided by `stdlib_version` ### `stdlib_version_string` String constant representing the version number. ### `stdlib_version_compact` Compact representation of the version string following the scheme: major * 10000 + minor * 100 + patch. ### `get_stdlib_version` #### Status Experimental #### Description Getter subroutine to retrieve version information #### Syntax `call ` [[stdlib_version(module):get_stdlib_version(subroutine)]] ` ([major], [minor], [patch], [string])` #### Class Pure subroutine. #### Argument `major`: shall be an intrinsic integer type. It is an optional, `intent(out)` argument. `minor`: shall be an intrinsic integer type. It is an optional, `intent(out)` argument. `patch`: shall be an intrinsic integer type. It is an optional, `intent(out)` argument. `string`: shall be a deferred length character type. It is an optional, `intent(out)` argument. #### Example ```fortran {!example/version/example_version.f90!} ``` fortran-lang-stdlib-0ede301/doc/specs/stdlib_specialmatrices.md0000664000175000017500000001721015135654166025104 0ustar alastairalastair--- title: specialmatrices --- # The `stdlib_specialmatrices` module [TOC] ## Introduction The `stdlib_specialmatrices` module provides derived types and specialized drivers for highly structured matrices often encountered in scientific computing as well as control and signal processing applications. These include: - Tridiagonal matrices - Symmetric Tridiagonal matrices (not yet supported) - Circulant matrices (not yet supported) - Toeplitz matrices (not yet supported) - Hankel matrices (not yet supported) In addition, it also provides a `Poisson2D` matrix type (not yet supported) corresponding to the sparse block tridiagonal matrix obtained from discretizing the Laplace operator on a 2D grid with the standard second-order accurate central finite-difference scheme. ## List of derived types for special matrices Below is a list of the currently supported derived types corresponding to different special matrices. Note that this module is under active development and this list will eventually grow. ### Tridiagonal matrices {#Tridiagonal} #### Status Experimental #### Description Tridiagonal matrices are ubiquituous in scientific computing and often appear when discretizing 1D differential operators. A generic tridiagonal matrix has the following structure: $$ A = \begin{bmatrix} a_1 & b_1 \\ c_1 & a_2 & b_2 \\ & \ddots & \ddots & \ddots \\ & & c_{n-2} & a_{n-1} & b_{n-1} \\ & & & c_{n-1} & a_n \end{bmatrix}. $$ Hence, only one vector of size `n` and two of size `n-1` need to be stored to fully represent the matrix. This particular structure also lends itself to specialized implementations for many linear algebra tasks. Interfaces to the most common ones will soon be provided by `stdlib_specialmatrices`. Tridiagonal matrices are available with all supported data types as `tridiagonal__type`, for example: - `tridiagonal_sp_type` : Tridiagonal matrix of size `n` with `real`/`single precision` data. - `tridiagonal_dp_type` : Tridiagonal matrix of size `n` with `real`/`double precision` data. - `tridiagonal_xdp_type` : Tridiagonal matrix of size `n` with `real`/`extended precision` data. - `tridiagonal_qp_type` : Tridiagonal matrix of size `n` with `real`/`quadruple precision` data. - `tridiagonal_csp_type` : Tridiagonal matrix of size `n` with `complex`/`single precision` data. - `tridiagonal_cdp_type` : Tridiagonal matrix of size `n` with `complex`/`double precision` data. - `tridiagonal_cxdp_type` : Tridiagonal matrix of size `n` with `complex`/`extended precision` data. - `tridiagonal_cqp_type` : Tridiagonal matrix of size `n` with `complex`/`quadruple precision` data. #### Syntax - To construct a tridiagonal matrix from already allocated arrays `dl` (lower diagonal, size `n-1`), `dv` (main diagonal, size `n`) and `du` (upper diagonal, size `n-1`): `A = ` [[stdlib_specialmatrices(module):tridiagonal(interface)]] `(dl, dv, du)` - To construct a tridiagonal matrix of size `n x n` with constant diagonal elements `dl`, `dv`, and `du`: `A = ` [[stdlib_specialmatrices(module):tridiagonal(interface)]] `(dl, dv, du, n)` #### Example ```fortran {!example/specialmatrices/example_tridiagonal_dp_type.f90!} ``` ## Specialized drivers for linear algebra tasks Below is a list of all the specialized drivers for linear algebra tasks currently provided by the `stdlib_specialmatrices` module. ### Matrix-vector products with `spmv` {#spmv} #### Status Experimental #### Description With the exception of `extended precision` and `quadruple precision`, all the types provided by `stdlib_specialmatrices` benefit from specialized kernels for matrix-vector products accessible via the common `spmv` interface. - For `tridiagonal` matrices, the backend is either LAPACK `lagtm` or the generalized routine `glagtm`, depending on the values and types of `alpha` and `beta`. #### Syntax `call ` [[stdlib_specialmatrices(module):spmv(interface)]] `(A, x, y [, alpha, beta, op])` #### Arguments - `A` : Shall be a matrix of one of the types provided by `stdlib_specialmatrices`. It is an `intent(in)` argument. - `x` : Shall be a rank-1 or rank-2 array with the same kind as `A`. It is an `intent(in)` argument. - `y` : Shall be a rank-1 or rank-2 array with the same kind as `A`. It is an `intent(inout)` argument. - `alpha` (optional) : Scalar value of the same type as `x`. It is an `intent(in)` argument. By default, `alpha = 1`. - `beta` (optional) : Scalar value of the same type as `y`. It is an `intent(in)` argument. By default `beta = 0`. - `op` (optional) : In-place operator identifier. Shall be a character(1) argument. It can have any of the following values: `N`: no transpose, `T`: transpose, `H`: hermitian or complex transpose. #### Examples ```fortran {!example/specialmatrices/example_specialmatrices_dp_spmv.f90!} ``` ## Utility functions ### `dense` : converting a special matrix to a standard Fortran array {#dense} #### Status Experimental #### Description Utility function to convert all the matrix types provided by `stdlib_specialmatrices` to a standard rank-2 array of the appropriate kind. #### Syntax `B = ` [[stdlib_specialmatrices(module):dense(interface)]] `(A)` #### Arguments - `A` : Shall be a matrix of one of the types provided by `stdlib_specialmatrices`. It is an `intent(in)` argument. - `B` : Shall be a rank-2 allocatable array of the appropriate `real` or `complex` kind. ### `transpose` : Transposition of a special matrix {#transpose} #### Status Experimental #### Description Utility function returning the transpose of a special matrix. The returned matrix is of the same type and kind as the input one. #### Syntax `B = ` [[stdlib_specialmatrices(module):transpose(interface)]] `(A)` #### Arguments - `A` : Shall be a matrix of one of the types provided by `stdlib_specialmatrices`. It is an `intent(in)` argument. - `B` : Shall be a matrix of one of the same type and kind as `A`. ### `hermitian` : Complex-conjugate transpose of a special matrix {#hermitian} #### Status Experimental #### Description Utility function returning the complex-conjugate transpose of a special matrix. The returned matrix is of the same type and kind as the input one. For real-valued matrices, `hermitian` is equivalent to `transpose`. #### Syntax `B = ` [[stdlib_specialmatrices(module):hermitian(interface)]] `(A)` #### Arguments - `A` : Shall be a matrix of one of the types provided by `stdlib_specialmatrices`. It is an `intent(in)` argument. - `B` : Shall be a matrix of one of the same type and kind as `A`. ### Operator overloading (`+`, `-`, `*`) {#operators} #### Status Experimental #### Description The definition of all standard artihmetic operators have been overloaded to be applicable for the matrix types defined by `stdlib_specialmatrices`: - Overloading the `+` operator for adding two matrices of the same type and kind. - Overloading the `-` operator for subtracting two matrices of the same type and kind. - Overloading the `*` for scalar-matrix multiplication. #### Syntax - Adding two matrices of the same type: `C = A` [[stdlib_specialmatrices(module):operator(+)(interface)]] `B` - Subtracting two matrices of the same type: `C = A` [[stdlib_specialmatrices(module):operator(-)(interface)]] `B` - Scalar multiplication `B = alpha` [[stdlib_specialmatrices(module):operator(*)(interface)]] `A` @note For addition (`+`) and subtraction (`-`), matrices `A`, `B` and `C` all need to be of the same type and kind. For scalar multiplication (`*`), `A` and `B` need to be of the same type and kind, while `alpha` is either `real` or `complex` (with the same kind again) depending on the type being used. @endnote fortran-lang-stdlib-0ede301/doc/specs/stdlib_linalg_state_type.md0000664000175000017500000000604615135654166025450 0ustar alastairalastair--- title: linalg_state_type --- # Linear Algebra -- State and Error Handling Module [TOC] ## Introduction The `stdlib_linalg_state` module provides a derived type holding information on the state of linear algebra operations, and procedures for expert control of linear algebra workflows. All linear algebra procedures are engineered to support returning an optional `linalg_state_type` variable to hold such information, as a form of expert API. If the user does not require state information but fatal errors are encountered during the execution of linear algebra routines, the program will undergo a hard stop. Instead, if the state argument is present, the program will never stop but will return detailed error information into the state handler. ## Derived types provided ### The `linalg_state_type` derived type The `linalg_state_type` is an extension of the `state_type` derived type, containing an integer error flag and fixed-size character strings to store an error message and the location of the error state change. Fixed-size string storage was chosen to facilitate the compiler's memory allocation and ultimately ensure maximum computational performance. A similarly named generic interface, `linalg_state_type`, is provided to allow the developer to create diagnostic messages and raise error flags easily. The call starts with an error flag or the location of the event and is followed by an arbitrary list of `integer`, `real`, `complex`, or `character` variables. Numeric variables may be provided as either scalars or rank-1 (array) inputs. #### Type-bound procedures The following convenience type-bound procedures are inherited from `state_type` and available: - `print()` returns an allocatable character string containing state location, message, and error flag; - `print_message()` returns an allocatable character string containing the state message; - `ok()` returns a `logical` flag that is `.true.` in case of successful state (`flag==LINALG_SUCCESS`); - `error()` returns a `logical` flag that is `.true.` in case of an error state (`flag/=LINALG_SUCCESS`). #### Status Experimental #### Example ```fortran {!example/linalg/example_state1.f90!} ``` ## Error flags provided The module provides the following state flags, mapped to the general `state_type` error flags: - `LINALG_SUCCESS`: Successful execution (equivalent to `STDLIB_SUCCESS`) - `LINALG_VALUE_ERROR`: Numerical errors (such as infinity, not-a-number, range bounds) are encountered (equivalent to `STDLIB_VALUE_ERROR`). - `LINALG_ERROR`: Linear Algebra errors are encountered, such as non-converging iterations, and impossible operations (equivalent to `STDLIB_LINALG_ERROR`). - `LINALG_INTERNAL_ERROR`: Provided as a developer safeguard for internal errors that should never occur (equivalent to `STDLIB_INTERNAL_ERROR`). ## Comparison operators provided The module provides overloaded comparison operators for all comparisons of a `linalg_state_type` variable with an integer error flag: `<`, `<=`, `==`, `>=`, `>`, `/=`. fortran-lang-stdlib-0ede301/doc/specs/stdlib_intrinsics.md0000664000175000017500000001441015135654166024120 0ustar alastairalastair--- title: intrinsics --- # The `stdlib_intrinsics` module [TOC] ## Introduction The `stdlib_intrinsics` module provides replacements for some of the well known intrinsic functions found in Fortran compilers for which either a faster and/or more accurate implementation is found which has also proven of interest to the Fortran community. ### `stdlib_sum` function #### Description The `stdlib_sum` function can replace the intrinsic `sum` for `real`, `complex` or `integer` arrays. It follows a chunked implementation which maximizes vectorization potential as well as reducing the round-off error. This procedure is recommended when summing large (e..g, >2**10 elements) arrays, for repetitive summation of smaller arrays consider the classical `sum`. #### Syntax `res = ` [[stdlib_intrinsics(module):stdlib_sum(interface)]] ` (x [,mask] )` `res = ` [[stdlib_intrinsics(module):stdlib_sum(interface)]] ` (x, dim [,mask] )` #### Status Experimental #### Class Pure function. #### Argument(s) `x`: N-D array of either `real`, `complex` or `integer` type. This argument is `intent(in)`. `dim` (optional): scalar of type `integer` with a value in the range from 1 to n, where n equals the rank of `x`. `mask` (optional): N-D array of `logical` values, with the same shape as `x`. This argument is `intent(in)`. #### Output value or Result value If `dim` is absent, the output is a scalar of the same `type` and `kind` as to that of `x`. Otherwise, an array of rank n-1, where n equals the rank of `x`, and a shape similar to that of `x` with dimension `dim` dropped is returned. ### `stdlib_sum_kahan` function #### Description The `stdlib_sum_kahan` function can replace the intrinsic `sum` for `real` or `complex` arrays. It follows a chunked implementation which maximizes vectorization potential complemented by an `elemental` kernel based on the [kahan summation](https://doi.org/10.1145%2F363707.363723) strategy to reduce the round-off error: ```fortran elemental subroutine kahan_kernel_(a,s,c) type(), intent(in) :: a type(), intent(inout) :: s type(), intent(inout) :: c type() :: t, y y = a - c t = s + y c = (t - s) - y s = t end subroutine ``` #### Syntax `res = ` [[stdlib_intrinsics(module):stdlib_sum_kahan(interface)]] ` (x [,mask] )` `res = ` [[stdlib_intrinsics(module):stdlib_sum_kahan(interface)]] ` (x, dim [,mask] )` #### Status Experimental #### Class Pure function. #### Argument(s) `x`: 1D array of either `real` or `complex` type. This argument is `intent(in)`. `dim` (optional): scalar of type `integer` with a value in the range from 1 to n, where n equals the rank of `x`. `mask` (optional): N-D array of `logical` values, with the same shape as `x`. This argument is `intent(in)`. #### Output value or Result value If `dim` is absent, the output is a scalar of the same type and kind as to that of `x`. Otherwise, an array of rank n-1, where n equals the rank of `x`, and a shape similar to that of `x` with dimension `dim` dropped is returned. #### Example ```fortran {!example/intrinsics/example_sum.f90!} ``` ### `stdlib_dot_product` function #### Description The `stdlib_dot_product` function can replace the intrinsic `dot_product` for 1D `real`, `complex` or `integer` arrays. It follows a chunked implementation which maximizes vectorization potential as well as reducing the round-off error. This procedure is recommended when crunching large arrays, for repetitive products of smaller arrays consider the classical `dot_product`. #### Syntax `res = ` [[stdlib_intrinsics(module):stdlib_dot_product(interface)]] ` (x, y)` #### Status Experimental #### Class Pure function. #### Argument(s) `x`: 1D array of either `real`, `complex` or `integer` type. This argument is `intent(in)`. `y`: 1D array of the same type and kind as `x`. This argument is `intent(in)`. #### Output value or Result value The output is a scalar of `type` and `kind` same as to that of `x` and `y`. ### `stdlib_dot_product_kahan` function #### Description The `stdlib_dot_product_kahan` function can replace the intrinsic `dot_product` for 1D `real` or `complex` arrays. It follows a chunked implementation which maximizes vectorization potential, complemented by the same `elemental` kernel based on the [kahan summation](https://doi.org/10.1145%2F363707.363723) used for `stdlib_sum` to reduce the round-off error. #### Syntax `res = ` [[stdlib_intrinsics(module):stdlib_dot_product_kahan(interface)]] ` (x, y)` #### Status Experimental #### Class Pure function. #### Argument(s) `x`: 1D array of either `real` or `complex` type. This argument is `intent(in)`. `y`: 1D array of the same type and kind as `x`. This argument is `intent(in)`. #### Output value or Result value The output is a scalar of the same type and kind as to that of `x` and `y`. ```fortran {!example/intrinsics/example_dot_product.f90!} ``` ### `stdlib_matmul` function #### Description The extension of the intrinsic function `matmul` to handle more than 2 and less than or equal to 5 matrices, with error handling using `linalg_state_type`. The optimal parenthesization to minimize the number of scalar multiplications is done using the Algorithm as outlined in Cormen, "Introduction to Algorithms", 4ed, ch-14, section-2. The actual matrix multiplication is performed using the `gemm` interfaces. It supports only `real` and `complex` matrices. #### Syntax `res = ` [[stdlib_intrinsics(module):stdlib_matmul(interface)]] ` (m1, m2, m3, m4, m5, err)` #### Status Experimental #### Class Function. #### Argument(s) `m1`, `m2`: 2D arrays of the same kind and type. `intent(in)` arguments. `m3`,`m4`,`m5`: 2D arrays of the same kind and type as the other matrices. `intent(in), optional` arguments. `err`: `type(linalg_state_type), intent(out), optional` argument. Can be used for elegant error handling. It is assigned `LINALG_VALUE_ERROR` in case the matrices are not of compatible sizes. #### Result The output is a matrix of the appropriate size. #### Example ```fortran {!example/intrinsics/example_matmul.f90!} ``` fortran-lang-stdlib-0ede301/doc/changelog.md0000664000175000017500000000005315135654166021202 0ustar alastairalastair--- title: Changelog --- {!CHANGELOG.md!} fortran-lang-stdlib-0ede301/doc/contributing/0000775000175000017500000000000015135654166021442 5ustar alastairalastairfortran-lang-stdlib-0ede301/doc/contributing/Workflow.md0000664000175000017500000000032615135654166023577 0ustar alastairalastair--- title: Workflow for Contributors --- @note This is a living document. You are welcome to propose changes to this workflow by opening an [issue](https://github.com/fortran-lang/stdlib/issues). {!WORKFLOW.md!} fortran-lang-stdlib-0ede301/doc/contributing/CodeOfConduct.md0000664000175000017500000000010315135654166024435 0ustar alastairalastair--- title: Contributor Code of Conduct --- {!CODE_OF_CONDUCT.md!} fortran-lang-stdlib-0ede301/doc/contributing/index.md0000664000175000017500000000030215135654166023066 0ustar alastairalastair--- title: Contributing --- This page aims to provide information that are useful for `stdlib` contributors. Issues can be reported on [GitHub](https://github.com/fortran-lang/stdlib/issues). fortran-lang-stdlib-0ede301/doc/contributing/StyleGuide.md0000664000175000017500000000032215135654166024037 0ustar alastairalastair--- title: Style Guide --- @note This is a living document. You are welcome to propose changes to this workflow by opening an [issue](https://github.com/fortran-lang/stdlib/issues). [TOC] {!STYLE_GUIDE.md!} fortran-lang-stdlib-0ede301/doc/index.md0000664000175000017500000000043415135654166020365 0ustar alastairalastair--- title: Contributing and specs --- @warning This page is currently under construction! @todo Improve the title of this FORD "pages" section, and improve the organization of pages to separate end-user, high-level documentation and examples from developer documentation and specs. fortran-lang-stdlib-0ede301/doc/License.md0000664000175000017500000000007115135654166020635 0ustar alastairalastair--- title: Fortran stdlib License (MIT) --- {!LICENSE!} fortran-lang-stdlib-0ede301/example/0000775000175000017500000000000015135654166017621 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/logger/0000775000175000017500000000000015135654166021100 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/logger/example_global_logger.f900000664000175000017500000000053115135654166025731 0ustar alastairalastairprogram example_global_logger use stdlib_logger, global => global_logger implicit none integer :: unit, stat call global%add_log_file('error_log.txt', unit, & position='asis', stat=stat) if (stat /= success) then error stop 'Unable to open "error_log.txt".' end if end program example_global_logger fortran-lang-stdlib-0ede301/example/logger/example_configure.f900000664000175000017500000000026315135654166025115 0ustar alastairalastairprogram example_configure use stdlib_logger, only: global => global_logger implicit none call global%configure(indent=.false., max_width=72) end program example_configure fortran-lang-stdlib-0ede301/example/logger/example_log_text_error.f900000664000175000017500000000206715135654166026176 0ustar alastairalastairprogram example_log_text_error use stdlib_logger implicit none character(*), parameter :: filename = 'dummy.txt' integer :: col_no, line_no, lun, status character(128) :: line character(*), parameter :: message = 'Bad text found.' open (newunit=lun, file=filename, status='old', & form='formatted') line_no = 0 do read (lun, fmt='(a)', end=900) line line_no = line_no + 1 call check_line(line, status, col_no) if (status /= 0) then call global_logger%log_text_error(line, & col_no, message, filename, line_no) error stop 'Error in reading '//filename end if end do 900 continue contains subroutine check_line(line, status, col_no) character(*), intent(in) :: line integer, intent(inout) :: status integer, intent(inout) :: col_no ! scan the line for forbidden characters col_no = scan(line, ".$/") ! col_no > 0 means there is a forbidden character status = col_no end subroutine end program example_log_text_error fortran-lang-stdlib-0ede301/example/logger/dummy.txt0000664000175000017500000000006415135654166022774 0ustar alastairalastaira word it should fail with the presence of this .$/ fortran-lang-stdlib-0ede301/example/logger/CMakeLists.txt0000664000175000017500000000037615135654166023646 0ustar alastairalastairADD_EXAMPLE(add_log_unit) ADD_EXAMPLE(configure) ADD_EXAMPLE(global_logger) ADD_EXAMPLE(log_io_error) set_tests_properties(log_io_error PROPERTIES WILL_FAIL true) ADD_EXAMPLE(log_text_error) set_tests_properties(log_text_error PROPERTIES WILL_FAIL true) fortran-lang-stdlib-0ede301/example/logger/example_add_log_unit.f900000664000175000017500000000102215135654166025556 0ustar alastairalastairprogram example_add_log_unit use stdlib_logger, only: global_logger, read_only_error implicit none character(256) :: iomsg integer :: iostat, unit, stat open (newunit=unit, file='error_log.txt', & form='formatted', status='replace', & position='rewind', & action='write', iostat=iostat, iomsg=iomsg) call global_logger%add_log_unit(unit, stat) select case (stat) case (read_only_error) error stop 'Unable to write to "error_log.txt".' end select end program example_add_log_unit fortran-lang-stdlib-0ede301/example/logger/example_log_io_error.f900000664000175000017500000000132215135654166025612 0ustar alastairalastairprogram example_log_io_error use stdlib_logger, global => global_logger implicit none character(*), parameter :: filename = 'nodummy.txt' integer :: iostat, lun character(128) :: iomsg character(*), parameter :: message = & 'Failure in opening "nodummy.txt".' open (newunit=lun, file=filename, form='formatted', & status='old', iostat=iostat, iomsg=iomsg) if (iostat /= 0) then call global%log_io_error(message, & procedure='EXAMPLE', & iostat=iostat, & iomsg=iomsg) error stop 'Error on opening a file' end if end program example_log_io_error fortran-lang-stdlib-0ede301/example/error/0000775000175000017500000000000015135654166020752 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/error/example_error_state2.f900000664000175000017500000000431515135654166025423 0ustar alastairalastairprogram example_error_state2 !! This example shows how to set a `type(state_type)` variable to process output conditions !! out of a simple division routine. The example is meant to highlight: !! 1) the different mechanisms that can be used to initialize the `state_type` variable providing !! strings, scalars, or arrays, on input to it; !! 2) `pure` setup of the error control use stdlib_error, only: state_type, STDLIB_VALUE_ERROR, STDLIB_SUCCESS implicit none type(state_type) :: err real :: a_div_b ! OK call very_simple_division(0.0,2.0,a_div_b,err) print *, err%print() ! Division by zero call very_simple_division(1.0,0.0,a_div_b,err) print *, err%print() ! Out of bounds call very_simple_division(huge(0.0),0.001,a_div_b,err) print *, err%print() contains !> Simple division returning an integer flag (LAPACK style) elemental subroutine very_simple_division(a,b,a_div_b,err) real, intent(in) :: a,b real, intent(out) :: a_div_b type(state_type), optional, intent(out) :: err type(state_type) :: err0 real, parameter :: MAXABS = huge(0.0) character(*), parameter :: this = 'simple division' !> Check a if (b==0.0) then ! Division by zero err0 = state_type(this,STDLIB_VALUE_ERROR,'Division by zero trying ',a,'/',b) elseif (.not.abs(b) rvs_normal implicit none real :: a(2, 3, 4), b(2, 3, 4) complex :: loc, scale integer :: seed_put, seed_get seed_put = 1234567 call random_seed(seed_put, seed_get) print *, norm() !single standard normal random variate ! 0.563655198 print *, norm(1.0, 2.0) !normal random variate mu=1.0, sigma=2.0 ! -0.633261681 print *, norm(0.0, 1.0, 10) !an array of 10 standard norml random variates ! -3.38123664E-02 -0.190365672 0.220678389 -0.424612164 -0.249541596 ! 0.865260184 1.11086845 -0.328349441 1.10873628 1.27049923 a(:, :, :) = 1.0 b(:, :, :) = 1.0 print *, norm(a, b) ! a rank 3 random variates array !0.152776539 -7.51764774E-02 1.47208166 0.180561781 1.32407105 ! 1.20383692 0.123445868 -0.455737948 -0.469808221 1.60750175 ! 1.05748117 0.720934749 0.407810807 1.48165631 2.31749439 ! 0.414566994 3.06084275 1.86505437 1.36338580 7.26878643E-02 ! 0.178585172 1.39557445 0.828021586 0.872084975 loc = (-1.0, 2.0) scale = (2.0, 1.0) print *, norm(loc, scale) !single complex normal random variate with real part of mu=-1, sigma=2; !imagainary part of mu=2.0 and sigma=1.0 ! (1.22566295,2.12518454) end program example_normal_rvs fortran-lang-stdlib-0ede301/example/stats_distribution_normal/example_normal_pdf.f900000664000175000017500000000363715135654166031313 0ustar alastairalastairprogram example_normal_pdf use stdlib_random, only: random_seed use stdlib_stats_distribution_normal, only: norm_pdf => pdf_normal, & norm => rvs_normal implicit none real, dimension(3, 4, 5) :: x, mu, sigma real :: xsum complex :: loc, scale integer :: seed_put, seed_get, i seed_put = 1234567 call random_seed(seed_put, seed_get) ! probability density at x=1.0 in standard normal print *, norm_pdf(1.0, 0., 1.) ! 0.241970733 ! probability density at x=2.0 with mu=-1.0 and sigma=2.0 print *, norm_pdf(2.0, -1.0, 2.0) ! 6.47588000E-02 ! probability density at x=1.0 with mu=1.0 and sigma=-1.0 (out of range) print *, norm_pdf(1.0, 1.0, -1.0) ! NaN ! standard normal random variates array x = reshape(norm(0.0, 1.0, 60), [3, 4, 5]) ! standard normal probability density array mu(:, :, :) = 0.0 sigma(:, :, :) = 1.0 print *, norm_pdf(x, mu, sigma) ! 0.340346158 0.285823315 0.398714304 0.391778737 0.389345556 ! 0.364551932 0.386712372 0.274370432 0.215250477 0.378006011 ! 0.215760440 0.177990928 0.278640658 0.223813817 0.356875211 ! 0.285167664 0.378533930 0.390739858 0.271684974 0.138273031 ! 0.135456234 0.331718773 0.398283750 0.383706540 ! probability density array where sigma<=0.0 for certain elements print *, norm_pdf([1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 0.0, -1.0]) ! 0.398942292 NaN NaN ! `pdf_normal` is pure and, thus, can be called concurrently xsum = 0.0 do concurrent (i=1:size(x,3)) xsum = xsum + sum(norm_pdf(x(:,:,i), mu(:,:,i), sigma(:,:,i))) end do print *, xsum ! 18.0754433 ! complex normal probability density function at x=(1.5,1.0) with real part ! of mu=1.0, sigma=1.0 and imaginary part of mu=-0.5, sigma=2.0 loc = (1.0, -0.5) scale = (1.0, 2.) print *, norm_pdf((1.5, 1.0), loc, scale) ! 5.30100204E-02 end program example_normal_pdf fortran-lang-stdlib-0ede301/example/stats_distribution_normal/CMakeLists.txt0000664000175000017500000000011015135654166027656 0ustar alastairalastairADD_EXAMPLE(normal_pdf) ADD_EXAMPLE(normal_rvs) ADD_EXAMPLE(normal_cdf) fortran-lang-stdlib-0ede301/example/stats_distribution_normal/example_normal_cdf.f900000664000175000017500000000365415135654166031275 0ustar alastairalastairprogram example_normal_cdf use stdlib_random, only: random_seed use stdlib_stats_distribution_normal, only: norm_cdf => cdf_normal, & norm => rvs_normal implicit none real, dimension(2, 3, 4) :: x, mu, sigma real :: xsum complex :: loc, scale integer :: seed_put, seed_get, i seed_put = 1234567 call random_seed(seed_put, seed_get) ! standard normal cumulative probability at x=0.0 print *, norm_cdf(0.0, 0.0, 1.0) ! 0.500000000 ! cumulative probability at x=2.0 with mu=-1.0 sigma=2.0 print *, norm_cdf(2.0, -1.0, 2.0) ! 0.933192849 ! cumulative probability at x=1.0 with mu=1.0 and sigma=-1.0 (out of range) print *, norm_cdf(1.0, 1.0, -1.0) ! NaN ! standard normal random variates array x = reshape(norm(0.0, 1.0, 24), [2, 3, 4]) ! standard normal cumulative array mu(:, :, :) = 0.0 sigma(:, :, :) = 1.0 print *, norm_cdf(x, mu, sigma) ! 0.713505626 0.207069695 0.486513376 0.424511284 0.587328553 ! 0.335559726 0.401470929 0.806552052 0.866687536 0.371323735 ! 0.866228044 0.898046613 0.198435277 0.141147852 0.681565762 ! 0.206268221 0.627057910 0.580759525 0.190364420 7.27325380E-02 ! 7.08068311E-02 0.728241026 0.522919059 0.390097380 ! cumulative probability array where sigma<=0.0 for certain elements print *, norm_cdf([1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 0.0, -1.0]) ! 0.500000000 NaN NaN ! `cdf_normal` is pure and, thus, can be called concurrently xsum = 0.0 do concurrent (i=1:size(x,3)) xsum = xsum + sum(norm_cdf(x(:,:,i), mu(:,:,i), sigma(:,:,i))) end do print *, xsum ! 11.3751936 ! complex normal cumulative distribution at x=(0.5,-0.5) with real part of ! mu=1.0, sigma=0.5 and imaginary part of mu=0.0, sigma=1.0 loc = (1.0, 0.0) scale = (0.5, 1.0) print *, norm_cdf((0.5, -0.5), loc, scale) ! 4.89511043E-02 end program example_normal_cdf fortran-lang-stdlib-0ede301/example/linalg/0000775000175000017500000000000015135654166021067 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/linalg/example_blas_gemv.f900000664000175000017500000000056615135654166025070 0ustar alastairalastairprogram example_gemv use stdlib_linalg, only: eye use stdlib_linalg_blas, only: sp,gemv implicit none real(sp) :: A(2, 2), B(2), C(2) B = [1.0,2.0] A = eye(2) ! Use legacy BLAS interface call gemv('No transpose',m=size(A,1),n=size(A,2),alpha=1.0,a=A,lda=size(A,1),x=B,incx=1,beta=0.0,y=C,incy=1) print *, C ! returns 1.0 2.0 end program example_gemv fortran-lang-stdlib-0ede301/example/linalg/example_schur_complex.f900000664000175000017500000000153715135654166026003 0ustar alastairalastair! This example demonstrates the Schur decomposition for a complex-valued matrix. program example_schur_complex use stdlib_linalg, only: schur use stdlib_linalg_constants, only: dp implicit none integer, parameter :: n = 3 complex(dp), dimension(n,n) :: A, T, Z ! Initialize a complex-valued square matrix A = reshape([ (1, 2), (3,-1), (4, 1), & (0,-1), (2, 0), (1,-2), & (2, 3), (1, 1), (0,-1) ], shape=[n,n]) ! Compute the Schur decomposition: A = Z T Z^H call schur(A, T, Z) ! Output results print *, "Original Matrix A:" print *, A print *, "Schur Form Matrix T:" print *, T print *, "Unitary Matrix Z:" print *, Z ! Test factorization: Z*T*Z^H = A print *, "Max error in reconstruction:", maxval(abs(matmul(Z, matmul(T, conjg(transpose(Z)))) - A)) end program example_schur_complex fortran-lang-stdlib-0ede301/example/linalg/example_mnorm.f900000664000175000017500000000137515135654166024260 0ustar alastairalastairprogram example_mnorm use stdlib_linalg, only: mnorm use stdlib_kinds, only: sp implicit none real(sp) :: a(3,3), na real(sp) :: b(3,3,4), nb(4) ! Array of 4 3x3 matrices ! Initialize example matrix a = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) ! Compute Euclidean norm of single matrix na = mnorm(a, 'Euclidean') print *, "Euclidean norm of matrix a:", na ! Initialize array of matrices b(:,:,1) = a b(:,:,2) = 2*a b(:,:,3) = 3*a b(:,:,4) = 4*a ! Compute infinity norm of each 3x3 matrix in b nb = mnorm(b, 'inf', dim=[1,2]) ! 18.0000000 36.0000000 54.0000000 72.0000000 print *, "Infinity norms of matrices in b:", nb end program example_mnorm fortran-lang-stdlib-0ede301/example/linalg/example_cholesky.f900000664000175000017500000000112215135654166024737 0ustar alastairalastair! Cholesky factorization: subroutine interface program example_cholesky use stdlib_linalg, only: cholesky implicit none real, dimension(3,3) :: A,L,U ! Set real matrix A = reshape( [ [6, 15, 55], & [15, 55, 225], & [55, 225, 979] ], [3,3] ) ! Decompose (lower) call cholesky(A, L, lower=.true.) ! Compare decomposition print *, maxval(abs(A-matmul(L,transpose(L)))) ! Decompose (upper) call cholesky(A, U, lower=.false.) ! Compare decomposition print *, maxval(abs(A-matmul(transpose(U),U))) end program example_cholesky fortran-lang-stdlib-0ede301/example/linalg/example_is_triangular.f900000664000175000017500000000060015135654166025761 0ustar alastairalastairprogram example_is_triangular use stdlib_linalg, only: is_triangular implicit none real :: A(3, 3), B(3, 3) logical :: res A = reshape([1., 0., 0., 4., 5., 0., 7., 8., 9.], shape(A)) B = reshape([1., 0., 3., 4., 5., 0., 7., 8., 9.], shape(B)) res = is_triangular(A, 'u') ! returns .true. res = is_triangular(B, 'u') ! returns .false. end program example_is_triangular fortran-lang-stdlib-0ede301/example/linalg/example_get_norm.f900000664000175000017500000000333615135654166024741 0ustar alastairalastair! Vector norm: demonstrate usage of the function interface program example_get_norm use stdlib_linalg, only: get_norm, linalg_state_type implicit none real :: a(3,3), nrm, nrmd(3) integer :: j type(linalg_state_type) :: err ! a = [ -3.00000000 0.00000000 3.00000000 ! -2.00000000 1.00000000 4.00000000 ! -1.00000000 2.00000000 5.00000000 ] a = reshape([(j-4,j=1,9)], [3,3]) print "(' a = [ ',3(g0,3x),2(/9x,3(g0,3x)),']')", transpose(a) ! Norm with integer input call get_norm(a, nrm, 2) print *, 'Euclidean norm = ',nrm ! 8.30662346 ! Norm with character input call get_norm(a, nrm, '2') print *, 'Euclidean norm = ',nrm ! 8.30662346 ! Euclidean norm of row arrays, a(i,:) call get_norm(a, nrmd, 2, dim=2) print *, 'Rows norms = ',nrmd ! 4.24264050 4.58257580 5.47722578 ! Euclidean norm of columns arrays, a(:,i) call get_norm(a, nrmd, 2, dim=1) print *, 'Columns norms = ',nrmd ! 3.74165750 2.23606801 7.07106781 ! Infinity norms call get_norm(a, nrm, 'inf') print *, 'maxval(||a||) = ',nrm ! 5.00000000 call get_norm(a, nrmd, 'inf', dim=2) print *, 'maxval(||a(i,:)||) = ',nrmd ! 3.00000000 4.00000000 5.00000000 call get_norm(a, nrm, '-inf') print *, 'minval(||a||) = ',nrm ! 0.00000000 call get_norm(a, nrmd, '-inf', dim=1) print *, 'minval(||a(:,i)||) = ',nrmd ! 1.00000000 0.00000000 3.00000000 ! Catch Error: ! [norm] returned Value Error: dimension 4 is out of rank for shape(a)= [3, 3] call get_norm(a, nrmd, 'inf', dim=4, err=err) print *, 'invalid: ',err%print() end program example_get_norm fortran-lang-stdlib-0ede301/example/linalg/example_is_hessenberg.f900000664000175000017500000000060015135654166025736 0ustar alastairalastairprogram example_is_hessenberg use stdlib_linalg, only: is_hessenberg implicit none real :: A(3, 3), B(3, 3) logical :: res A = reshape([1., 2., 0., 4., 5., 6., 7., 8., 9.], shape(A)) B = reshape([1., 2., 3., 4., 5., 6., 7., 8., 9.], shape(B)) res = is_hessenberg(A, 'u') ! returns .true. res = is_hessenberg(B, 'u') ! returns .false. end program example_is_hessenberg fortran-lang-stdlib-0ede301/example/linalg/example_eig.f900000664000175000017500000000126515135654166023672 0ustar alastairalastair! Eigendecomposition of a real square matrix program example_eig use stdlib_linalg, only: eig implicit none integer :: i real, allocatable :: A(:,:) complex, allocatable :: lambda(:),vectors(:,:) ! Decomposition of this square matrix ! NB Fortran is column-major -> transpose input A = transpose(reshape( [ [2, 2, 4], & [1, 3, 5], & [2, 3, 4] ], [3,3] )) ! Get eigenvalues and right eigenvectors allocate(lambda(3),vectors(3,3)) call eig(A, lambda, right=vectors) do i=1,3 print *, 'eigenvalue ',i,': ',lambda(i) print *, 'eigenvector ',i,': ',vectors(:,i) end do end program example_eig fortran-lang-stdlib-0ede301/example/linalg/example_eigh.f900000664000175000017500000000213715135654166024041 0ustar alastairalastair! Eigendecomposition of a real symmetric matrix program example_eigh use stdlib_linalg, only: eigh implicit none integer :: i real, allocatable :: A(:,:),lambda(:),vectors(:,:) complex, allocatable :: cA(:,:),cvectors(:,:) ! Decomposition of this symmetric matrix ! NB Fortran is column-major -> transpose input A = transpose(reshape( [ [2, 1, 4], & [1, 3, 5], & [4, 5, 4] ], [3,3] )) ! Note: real symmetric matrices have real (orthogonal) eigenvalues and eigenvectors allocate(lambda(3),vectors(3,3)) call eigh(A, lambda, vectors=vectors) print *, 'Real matrix' do i=1,3 print *, 'eigenvalue ',i,': ',lambda(i) print *, 'eigenvector ',i,': ',vectors(:,i) end do ! Complex hermitian matrices have real (orthogonal) eigenvalues and complex eigenvectors cA = A allocate(cvectors(3,3)) call eigh(cA, lambda, vectors=cvectors) print *, 'Complex matrix' do i=1,3 print *, 'eigenvalue ',i,': ',lambda(i) print *, 'eigenvector ',i,': ',cvectors(:,i) end do end program example_eigh fortran-lang-stdlib-0ede301/example/linalg/example_qr.f900000664000175000017500000000050115135654166023540 0ustar alastairalastairprogram example_qr use stdlib_linalg, only: qr implicit none real :: A(104, 32), Q(104,32), R(32,32) ! Create a random matrix call random_number(A) ! Compute its QR factorization (reduced) call qr(A,Q,R) ! Test factorization: Q*R = A print *, maxval(abs(matmul(Q,R)-A)) end program example_qr fortran-lang-stdlib-0ede301/example/linalg/example_trace.f900000664000175000017500000000030615135654166024217 0ustar alastairalastairprogram example_trace use stdlib_linalg, only: trace implicit none real :: A(3, 3) A = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) print *, trace(A) ! 1 + 5 + 9 end program example_trace fortran-lang-stdlib-0ede301/example/linalg/example_eig_generalized.f900000664000175000017500000000156615135654166026247 0ustar alastairalastair! Eigendecomposition of a real square matrix for the generalized eigenproblem program example_eig_generalized use stdlib_linalg, only: eig, eye implicit none integer :: i real, allocatable :: A(:,:), B(:,:) complex, allocatable :: lambda(:), vectors(:,:) ! Matrices for the generalized eigenproblem: A * v = lambda * B * v ! NB Fortran is column-major -> transpose input A = transpose(reshape([ [2, 2, 4], & [1, 3, 5], & [2, 3, 4] ], [3,3])) B = eye(3) ! Allocate eigenvalues and right eigenvectors allocate(lambda(3), vectors(3,3)) ! Get eigenvalues and right eigenvectors for the generalized problem call eig(A, B, lambda, right=vectors) do i = 1, 3 print *, 'Eigenvalue ', i, ': ', lambda(i) print *, 'Eigenvector ', i, ': ', vectors(:,i) end do end program example_eig_generalized fortran-lang-stdlib-0ede301/example/linalg/example_lstsq2.f900000664000175000017500000000245715135654166024362 0ustar alastairalastair! Demonstrate expert subroutine interface with pre-allocated arrays program example_lstsq2 use stdlib_linalg_constants, only: dp,ilp use stdlib_linalg, only: solve_lstsq, lstsq_space, linalg_state_type implicit none integer, allocatable :: x(:),y(:) real(dp), allocatable :: A(:,:),b(:),coef(:),real_space(:),singvals(:) integer(ilp), allocatable :: int_space(:) integer(ilp) :: lrwork,liwork,arank ! Data set x = [1, 2, 2] y = [5, 13, 25] ! Fit three points using a parabola, least squares method ! A = [1 x x**2] A = reshape([[1,1,1],x,x**2],[3,3]) b = y ! Get storage sizes for the arrays and pre-allocate data call lstsq_space(A,b,lrwork,liwork) allocate(coef(size(x)),real_space(lrwork),int_space(liwork),singvals(minval(shape(A)))) ! Solve coefficients of y = coef(1) + x*coef(2) + x^2*coef(3) ! with no internal allocations call solve_lstsq(A,b,x=coef, & real_storage=real_space, & int_storage=int_space, & singvals=singvals, & overwrite_a=.true., & rank=arank) print *, 'parabola: ',coef ! parabola: -0.42857142857141695 1.1428571428571503 4.2857142857142811 print *, 'rank: ',arank ! rank: 2 end program example_lstsq2 fortran-lang-stdlib-0ede301/example/linalg/example_sparse_spmv.f900000664000175000017500000000165115135654166025467 0ustar alastairalastairprogram example_sparse_spmv use stdlib_linalg_constants, only: dp use stdlib_sparse implicit none integer, parameter :: m = 4, n = 2 real(dp) :: A(m,n), x(n) real(dp) :: y_dense(m), y_coo(m), y_csr(m) real(dp) :: alpha, beta type(COO_dp_type) :: COO type(CSR_dp_type) :: CSR call random_number(A) ! Convert from dense to COO and CSR matrices call dense2coo( A , COO ) call coo2csr( COO , CSR ) ! Initialize vectors x = 1._dp y_dense = 2._dp y_coo = y_dense y_csr = y_dense ! Perform matrix-vector product alpha = 3._dp; beta = 2._dp y_dense = alpha * matmul(A,x) + beta * y_dense call spmv( COO , x , y_coo , alpha = alpha, beta = beta ) call spmv( CSR , x , y_csr , alpha = alpha, beta = beta ) print *, 'dense :', y_dense print *, 'coo :', y_coo print *, 'csr :', y_csr end program example_sparse_spmvfortran-lang-stdlib-0ede301/example/linalg/example_eigvals_generalized.f900000664000175000017500000000144115135654166027125 0ustar alastairalastair! Eigenvalues of a general real/complex matrix for the generalized eigenproblem program example_eigvals_generalized use stdlib_linalg, only: eigvals, eye implicit none real, allocatable :: A(:,:), B(:,:), lambda(:) complex, allocatable :: cA(:,:), cB(:,:), clambda(:) ! NB Fortran is column-major -> transpose input A = transpose(reshape([ [2, 8, 4], & [1, 3, 5], & [9, 5,-2] ], [3,3])) B = eye(3) ! Real generalized eigenproblem lambda = eigvals(A, B) print *, 'Real generalized matrix eigenvalues: ', lambda ! Complex generalized eigenproblem cA = cmplx(A, -2*A) cB = cmplx(B, 0.5*B) clambda = eigvals(cA, cB) print *, 'Complex generalized matrix eigenvalues: ', clambda end program example_eigvals_generalized fortran-lang-stdlib-0ede301/example/linalg/example_eye2.f900000664000175000017500000000024015135654166023762 0ustar alastairalastairprogram example_eye2 use stdlib_linalg, only: eye, diag implicit none print *, all(eye(4) == diag([1, 1, 1, 1])) ! prints .true. end program example_eye2 fortran-lang-stdlib-0ede301/example/linalg/example_solve_bicgstab_wilkinson.f900000664000175000017500000000305615135654166030211 0ustar alastairalastairprogram example_solve_bicgstab_wilkinson use stdlib_kinds, only: dp use stdlib_linalg_iterative_solvers use stdlib_sparse use stdlib_sparse_spmv implicit none integer, parameter :: n = 21 type(COO_dp_type) :: COO type(CSR_dp_type) :: A type(stdlib_solver_workspace_dp_type) :: workspace real(dp) :: b(n), x(n), norm_sq0 integer :: i ! Construct the Wilkinson's matrix in COO format ! https://en.wikipedia.org/wiki/Wilkinson_matrix call COO%malloc(n, n, n + 2*(n-1)) COO%data(1:n) = [( real(abs(i), kind=dp), i=-(n-1)/2, (n-1)/2)] COO%data(n+1:) = 1.0_dp do i = 1, n COO%index(1:2, i) = [i,i] end do do i = 1, n-1 COO%index(1:2, n+i) = [i,i+1] COO%index(1:2, n+n-1+i) = [i+1,i] end do call coo2ordered(COO,sort_data=.true.) ! Convert COO to CSR format call coo2csr(COO, A) ! Set up the right-hand side for the solution to be ones b = 0.0_dp x = 1.0_dp call spmv(A, x, b) ! b = A * 1 x = 0.0_dp ! initial guess ! Solve the system using BiCGSTAB workspace%callback => my_logger call stdlib_solve_bicgstab(A, b, x, rtol=1e-12_dp, maxiter=100, workspace=workspace) contains subroutine my_logger(x,norm_sq,iter) real(dp), intent(in) :: x(:) real(dp), intent(in) :: norm_sq integer, intent(in) :: iter if(iter == 0) norm_sq0 = norm_sq print *, "Iteration: ", iter, " Residual: ", norm_sq, " Relative: ", norm_sq/norm_sq0 end subroutine end program example_solve_bicgstab_wilkinsonfortran-lang-stdlib-0ede301/example/linalg/example_is_skew_symmetric.f900000664000175000017500000000054315135654166026664 0ustar alastairalastairprogram example_is_skew_symmetric use stdlib_linalg, only: is_skew_symmetric implicit none real :: A(2, 2), B(2, 2) logical :: res A = reshape([0., -3., 3., 0.], shape(A)) B = reshape([0., 3., 3., 0.], shape(B)) res = is_skew_symmetric(A) ! returns .true. res = is_skew_symmetric(B) ! returns .false. end program example_is_skew_symmetric fortran-lang-stdlib-0ede301/example/linalg/example_solve_custom.f900000664000175000017500000001207315135654166025647 0ustar alastairalastairmodule custom_solver use stdlib_kinds, only: int8, dp use stdlib_sparse, only: CSR_dp_type, spmv, diag use stdlib_linalg_iterative_solvers, only: stdlib_linop_dp_type, & stdlib_solver_workspace_dp_type, & stdlib_solve_pcg_kernel, & stdlib_size_wksp_pcg use stdlib_optval, only: optval implicit none private public :: stdlib_solve_pcg_custom contains subroutine stdlib_solve_pcg_custom(A,b,x,di,rtol,atol,maxiter,restart,workspace) type(CSR_dp_type), intent(in) :: A real(dp), intent(in) :: b(:) real(dp), intent(inout) :: x(:) real(dp), intent(in), optional :: rtol real(dp), intent(in), optional :: atol logical(int8), intent(in), optional, target :: di(:) integer, intent(in), optional :: maxiter logical, intent(in), optional :: restart type(stdlib_solver_workspace_dp_type), optional, intent(inout), target :: workspace !------------------------- type(stdlib_linop_dp_type) :: op type(stdlib_linop_dp_type) :: M type(stdlib_solver_workspace_dp_type), pointer :: workspace_ integer :: n, maxiter_ real(dp) :: rtol_, atol_ logical :: restart_ logical(int8), pointer :: di_(:) real(dp), allocatable :: diagonal(:) real(dp) :: norm_sq0 !------------------------- n = size(b) maxiter_ = optval(x=maxiter, default=n) restart_ = optval(x=restart, default=.true.) rtol_ = optval(x=rtol, default=1.e-4_dp) atol_ = optval(x=atol, default=0._dp) norm_sq0 = 0._dp !------------------------- ! internal memory setup op%matvec => my_matvec op%inner_product => my_dot M%matvec => my_jacobi_preconditioner if(present(di))then di_ => di else allocate(di_(n),source=.false._int8) end if if(present(workspace)) then workspace_ => workspace else allocate( workspace_ ) end if if(.not.allocated(workspace_%tmp)) allocate( workspace_%tmp(n,stdlib_size_wksp_pcg) , source = 0._dp ) workspace_%callback => my_logger !------------------------- ! Jacobi preconditioner factorization call diag(A,diagonal) where(abs(diagonal)>epsilon(0._dp)) diagonal = 1._dp/diagonal !------------------------- ! main call to the solver call stdlib_solve_pcg_kernel(op,M,b,x,rtol_,atol_,maxiter_,workspace_) !------------------------- ! internal memory cleanup if(.not.present(di)) deallocate(di_) di_ => null() if(.not.present(workspace)) then deallocate( workspace_%tmp ) deallocate( workspace_ ) end if workspace_ => null() contains subroutine my_matvec(x,y,alpha,beta,op) real(dp), intent(in) :: x(:) real(dp), intent(inout) :: y(:) real(dp), intent(in) :: alpha real(dp), intent(in) :: beta character(1), intent(in) :: op call spmv( A , x, y , alpha, beta , op) y = merge( 0._dp, y, di_ ) end subroutine subroutine my_jacobi_preconditioner(x,y,alpha,beta,op) real(dp), intent(in) :: x(:) real(dp), intent(inout) :: y(:) real(dp), intent(in) :: alpha real(dp), intent(in) :: beta character(1), intent(in) :: op y = merge( 0._dp, diagonal * x , di_ ) end subroutine real(dp) function my_dot(x,y) result(r) real(dp), intent(in) :: x(:) real(dp), intent(in) :: y(:) r = dot_product(x,y) end function subroutine my_logger(x,norm_sq,iter) real(dp), intent(in) :: x(:) real(dp), intent(in) :: norm_sq integer, intent(in) :: iter if(iter == 0) norm_sq0 = norm_sq print *, "Iteration: ", iter, " Residual: ", sqrt(norm_sq), " Relative: ", sqrt(norm_sq)/sqrt(norm_sq0) end subroutine end subroutine end module custom_solver program example_solve_custom use custom_solver use stdlib_kinds, only: int8, dp use stdlib_sparse, only: CSR_dp_type, COO_dp_type, dense2coo, coo2csr implicit none type(CSR_dp_type) :: laplacian_csr type(COO_dp_type) :: COO real(dp) :: laplacian(5,5) real(dp) :: x(5), rhs(5) logical(int8) :: dirichlet(5) laplacian = reshape( [1, -1, 0, 0, 0,& -1, 2, -1, 0, 0,& 0, -1, 2, -1, 0,& 0, 0, -1, 2, -1,& 0, 0, 0, -1, 1] , [5,5]) call dense2coo(laplacian,COO) call coo2csr(COO,laplacian_csr) x = 0._dp rhs = dble( [0,0,5,0,0] ) dirichlet = .false._int8 dirichlet([1,5]) = .true._int8 call stdlib_solve_pcg_custom(laplacian_csr, rhs, x, rtol=1.d-6, di=dirichlet) print *, x !> solution: [0.0, 2.5, 5.0, 2.5, 0.0] end program example_solve_customfortran-lang-stdlib-0ede301/example/linalg/example_state2.f900000664000175000017500000000447315135654166024334 0ustar alastairalastairprogram example_state2 !! This example shows how to set a `type(linalg_state_type)` variable to process output conditions !! out of a simple division routine. The example is meant to highlight: !! 1) the different mechanisms that can be used to initialize the `linalg_state` variable providing !! strings, scalars, or arrays, on input to it; !! 2) `pure` setup of the error control use stdlib_linalg_state, only: linalg_state_type, LINALG_VALUE_ERROR, LINALG_SUCCESS, & linalg_error_handling implicit none type(linalg_state_type) :: err real :: a_div_b ! OK call very_simple_division(0.0,2.0,a_div_b,err) print *, err%print() ! Division by zero call very_simple_division(1.0,0.0,a_div_b,err) print *, err%print() ! Out of bounds call very_simple_division(huge(0.0),0.001,a_div_b,err) print *, err%print() contains !> Simple division returning an integer flag (LAPACK style) elemental subroutine very_simple_division(a,b,a_div_b,err) real, intent(in) :: a,b real, intent(out) :: a_div_b type(linalg_state_type), optional, intent(out) :: err type(linalg_state_type) :: err0 real, parameter :: MAXABS = huge(0.0) character(*), parameter :: this = 'simple division' !> Check a if (b==0.0) then ! Division by zero err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'Division by zero trying ',a,'/',b) elseif (.not.abs(b) transpose input A = transpose(reshape( [ [2, 8, 4], & [1, 3, 5], & [9, 5,-2] ], [3,3] )) ! Note: real symmetric matrix lambda = eigvals(A) print *, 'Real matrix eigenvalues: ',lambda ! Complex general matrix cA = cmplx(A, -2*A) clambda = eigvals(cA) print *, 'Complex matrix eigenvalues: ',clambda end program example_eigvals fortran-lang-stdlib-0ede301/example/linalg/example_hermitian.f900000664000175000017500000000066315135654166025107 0ustar alastairalastair! Example program demonstrating the usage of hermitian program example_hermitian use stdlib_linalg, only: hermitian implicit none complex, dimension(2, 2) :: A, AT ! Define input matrices A = reshape([(1,2),(3,4),(5,6),(7,8)],[2,2]) ! Compute Hermitian matrices AT = hermitian(A) print *, "Original Complex Matrix:" print *, A print *, "Hermitian Complex Matrix:" print *, AT end program example_hermitian fortran-lang-stdlib-0ede301/example/linalg/example_eigvalsh.f900000664000175000017500000000145115135654166024725 0ustar alastairalastair! Eigenvalues of a real symmetric / complex hermitian matrix program example_eigvalsh use stdlib_linalg, only: eigvalsh implicit none real, allocatable :: A(:,:),lambda(:) complex, allocatable :: cA(:,:) ! Decomposition of this symmetric matrix ! NB Fortran is column-major -> transpose input A = transpose(reshape( [ [2, 1, 4], & [1, 3, 5], & [4, 5, 4] ], [3,3] )) ! Note: real symmetric matrices have real (orthogonal) eigenvalues and eigenvectors lambda = eigvalsh(A) print *, 'Symmetric matrix eigenvalues: ',lambda ! Complex hermitian matrices have real (orthogonal) eigenvalues and complex eigenvectors cA = A lambda = eigvalsh(cA) print *, 'Hermitian matrix eigenvalues: ',lambda end program example_eigvalsh fortran-lang-stdlib-0ede301/example/linalg/example_diag4.f900000664000175000017500000000035215135654166024112 0ustar alastairalastairprogram example_diag4 use stdlib_linalg, only: diag implicit none integer, parameter :: n = 12 real :: A(n, n) real :: v(n) call random_number(A) v = diag(A) ! v contains diagonal elements of A end program example_diag4 fortran-lang-stdlib-0ede301/example/linalg/example_outer_product.f900000664000175000017500000000041715135654166026022 0ustar alastairalastairprogram example_outer_product use stdlib_linalg, only: outer_product implicit none real, allocatable :: A(:, :), u(:), v(:) u = [1., 2., 3.] v = [3., 4.] A = outer_product(u, v) !A = reshape([3., 6., 9., 4., 8., 12.], [3,2]) end program example_outer_product fortran-lang-stdlib-0ede301/example/linalg/example_expm.f900000664000175000017500000000056715135654166024103 0ustar alastairalastairprogram example_expm use stdlib_linalg, only: expm implicit none real :: A(3, 3), E(3, 3) integer :: i A = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) E = expm(A) print *, "Matrix A :" do i = 1, 3 print *, A(i, :) end do print *, "Matrix exponential E = exp(A):" do i = 1, 3 print *, E(i, :) end do end program example_expm fortran-lang-stdlib-0ede301/example/linalg/example_is_symmetric.f900000664000175000017500000000051115135654166025626 0ustar alastairalastairprogram example_is_symmetric use stdlib_linalg, only: is_symmetric implicit none real :: A(2, 2), B(2, 2) logical :: res A = reshape([1., 3., 3., 4.], shape(A)) B = reshape([1., 0., 3., 4.], shape(B)) res = is_symmetric(A) ! returns .true. res = is_symmetric(B) ! returns .false. end program example_is_symmetric fortran-lang-stdlib-0ede301/example/linalg/example_qr_space.f900000664000175000017500000000121015135654166024711 0ustar alastairalastair! QR example with pre-allocated storage program example_qr_space use stdlib_linalg_constants, only: ilp use stdlib_linalg, only: qr, qr_space, linalg_state_type implicit none real :: A(104, 32), Q(104,32), R(32,32) real, allocatable :: work(:) integer(ilp) :: lwork type(linalg_state_type) :: err ! Create a random matrix call random_number(A) ! Prepare QR workspace call qr_space(A,lwork) allocate(work(lwork)) ! Compute its QR factorization (reduced) call qr(A,Q,R,storage=work,err=err) ! Test factorization: Q*R = A print *, maxval(abs(matmul(Q,R)-A)) print *, err%print() end program example_qr_space fortran-lang-stdlib-0ede301/example/linalg/example_diag3.f900000664000175000017500000000040715135654166024112 0ustar alastairalastairprogram example_diag3 use stdlib_linalg, only: diag implicit none integer, parameter :: n = 10 real :: c(n), ul(n - 1) real :: A(n, n) c = 2 ul = -1 A = diag(ul, -1) + diag(c) + diag(ul, 1) ! Gil Strang's favorite matrix end program example_diag3 fortran-lang-stdlib-0ede301/example/linalg/example_inverse_function.f900000664000175000017500000000112315135654166026477 0ustar alastairalastair! Matrix inversion example: function interface program example_inverse_function use stdlib_linalg_constants, only: dp use stdlib_linalg, only: inv,eye implicit none real(dp) :: A(2,2), Am1(2,2) ! Input matrix (NB Fortran is column major! input columns then transpose) A = transpose(reshape( [4, 3, & 3, 2], [2,2] )) ! Invert matrix Am1 = inv(A) print *, ' |',Am1(1,:),'|' ! | -2 3 | print *, ' inv(A)= |',Am1(2,:),'|' ! | 3 -4 | ! Final check print *, 'CHECK passed? ',matmul(A,Am1)==eye(2) end program example_inverse_function fortran-lang-stdlib-0ede301/example/linalg/CMakeLists.txt0000664000175000017500000000310115135654166023622 0ustar alastairalastairADD_EXAMPLE(diag1) ADD_EXAMPLE(diag2) ADD_EXAMPLE(diag3) ADD_EXAMPLE(diag4) ADD_EXAMPLE(diag5) ADD_EXAMPLE(eye1) ADD_EXAMPLE(eye2) ADD_EXAMPLE(is_diagonal) ADD_EXAMPLE(hermitian) ADD_EXAMPLE(is_hermitian) ADD_EXAMPLE(is_hessenberg) ADD_EXAMPLE(is_skew_symmetric) ADD_EXAMPLE(is_square) ADD_EXAMPLE(is_symmetric) ADD_EXAMPLE(is_triangular) ADD_EXAMPLE(inverse_operator) ADD_EXAMPLE(inverse_function) ADD_EXAMPLE(inverse_inplace) ADD_EXAMPLE(inverse_subroutine) ADD_EXAMPLE(pseudoinverse) ADD_EXAMPLE(outer_product) ADD_EXAMPLE(eig) ADD_EXAMPLE(eigh) ADD_EXAMPLE(eig_generalized) ADD_EXAMPLE(eigvals) ADD_EXAMPLE(eigvalsh) ADD_EXAMPLE(eigvals_generalized) ADD_EXAMPLE(trace) ADD_EXAMPLE(state1) ADD_EXAMPLE(state2) ADD_EXAMPLE(schur_real) ADD_EXAMPLE(schur_complex) ADD_EXAMPLE(schur_eigvals) ADD_EXAMPLE(blas_gemv) ADD_EXAMPLE(lapack_getrf) ADD_EXAMPLE(lstsq1) ADD_EXAMPLE(lstsq2) ADD_EXAMPLE(constrained_lstsq1) ADD_EXAMPLE(constrained_lstsq2) ADD_EXAMPLE(norm) ADD_EXAMPLE(mnorm) ADD_EXAMPLE(get_norm) ADD_EXAMPLE(solve1) ADD_EXAMPLE(solve2) ADD_EXAMPLE(solve3) if (STDLIB_LINALG_ITERATIVE) ADD_EXAMPLE(solve_bicgstab) ADD_EXAMPLE(solve_bicgstab_wilkinson) ADD_EXAMPLE(solve_cg) ADD_EXAMPLE(solve_pcg) ADD_EXAMPLE(solve_custom) endif() ADD_EXAMPLE(sparse_from_ijv) ADD_EXAMPLE(sparse_data_accessors) ADD_EXAMPLE(sparse_spmv) ADD_EXAMPLE(svd) ADD_EXAMPLE(svdvals) ADD_EXAMPLE(determinant) ADD_EXAMPLE(determinant2) ADD_EXAMPLE(qr) ADD_EXAMPLE(pivoting_qr) ADD_EXAMPLE(qr_space) ADD_EXAMPLE(pivoting_qr_space) ADD_EXAMPLE(cholesky) ADD_EXAMPLE(chol) ADD_EXAMPLE(expm) ADD_EXAMPLE(matrix_exp) fortran-lang-stdlib-0ede301/example/linalg/example_solve_pcg.f900000664000175000017500000000177515135654166025115 0ustar alastairalastairprogram example_solve_pcg use stdlib_kinds, only: int8, dp use stdlib_sparse use stdlib_linalg_iterative_solvers, only: stdlib_solve_pcg type(CSR_dp_type) :: laplacian_csr type(COO_dp_type) :: COO real(dp) :: laplacian(5,5) real(dp) :: x(5), rhs(5) logical(int8) :: dirichlet(5) laplacian = reshape( [1, -1, 0, 0, 0,& -1, 2, -1, 0, 0,& 0, -1, 2, -1, 0,& 0, 0, -1, 2, -1,& 0, 0, 0, -1, 1] , [5,5]) call dense2coo(laplacian,COO) call coo2csr(COO,laplacian_csr) x = 0._dp rhs = real( [0,0,5,0,0], kind=dp ) dirichlet = .false._int8 dirichlet([1,5]) = .true._int8 call stdlib_solve_pcg(laplacian, rhs, x, rtol=1.d-6, di=dirichlet) print *, x !> solution: [0.0, 2.5, 5.0, 2.5, 0.0] x = 0._dp call stdlib_solve_pcg(laplacian_csr, rhs, x, rtol=1.d-6, di=dirichlet) print *, x !> solution: [0.0, 2.5, 5.0, 2.5, 0.0] end programfortran-lang-stdlib-0ede301/example/linalg/example_solve3.f900000664000175000017500000000166615135654166024346 0ustar alastairalastairprogram example_solve3 use stdlib_linalg_constants, only: sp,ilp use stdlib_linalg, only: solve_lu, linalg_state_type implicit none integer(ilp) :: test integer(ilp), allocatable :: pivot(:) complex(sp), allocatable :: A(:,:),b(:),x(:) ! Solve a system of 3 complex linear equations: ! 2x + iy + 2z = (5-i) ! -ix + (4-3i)y + 6z = i ! 4x + 3y + z = 1 ! Note: Fortran is column-major! -> transpose A = transpose(reshape([(2.0, 0.0),(0.0, 1.0),(2.0,0.0), & (0.0,-1.0),(4.0,-3.0),(6.0,0.0), & (4.0, 0.0),(3.0, 0.0),(1.0,0.0)] , [3,3])) ! Pre-allocate x allocate(b(size(A,2)),pivot(size(A,2))) allocate(x,mold=b) ! Call system many times avoiding reallocation do test=1,100 b = test*[(5.0,-1.0),(0.0,1.0),(1.0,0.0)] call solve_lu(A,b,x,pivot) print "(i3,'-th solution: ',*(1x,f12.6))", test,x end do end program example_solve3 fortran-lang-stdlib-0ede301/example/linalg/example_schur_real.f900000664000175000017500000000143515135654166025254 0ustar alastairalastair! This example computes the Schur decomposition of a real-valued square matrix. program example_schur_real use stdlib_linalg, only: schur use stdlib_linalg_constants, only: dp implicit none integer, parameter :: n = 3 real(dp), dimension(n,n) :: A, T, Z ! Initialize a real-valued square matrix A = reshape([ 0, 2, 2, & 0, 1, 2, & 1, 0, 1], shape=[n,n]) ! Compute the Schur decomposition: A = Z T Z^T call schur(A, T, Z) ! Output results print *, "Original Matrix A:" print *, A print *, "Schur Form Matrix T:" print *, T print *, "Orthogonal Matrix Z:" print *, Z ! Test factorization: Z*T*Z^T = A print *, "Max error in reconstruction:", maxval(abs(matmul(Z, matmul(T, transpose(Z))) - A)) end program example_schur_real fortran-lang-stdlib-0ede301/example/linalg/example_determinant.f900000664000175000017500000000044415135654166025436 0ustar alastairalastairprogram example_determinant use stdlib_kinds, only: dp use stdlib_linalg, only: det, linalg_state_type implicit none real(dp) :: d ! Compute determinate of a real matrix d = det(reshape([real(dp)::1,2,3,4],[2,2])) print *, d ! a*d-b*c = -2.0 end program example_determinant fortran-lang-stdlib-0ede301/example/linalg/example_diag1.f900000664000175000017500000000031615135654166024107 0ustar alastairalastairprogram example_diag1 use stdlib_linalg, only: diag implicit none real, allocatable :: A(:, :) integer :: i A = diag([(1, i=1, 10)]) ! creates a 10 by 10 identity matrix end program example_diag1 fortran-lang-stdlib-0ede301/example/linalg/example_is_square.f900000664000175000017500000000050215135654166025112 0ustar alastairalastairprogram example_is_square use stdlib_linalg, only: is_square implicit none real :: A(2, 2), B(3, 2) logical :: res A = reshape([1., 2., 3., 4.], shape(A)) B = reshape([1., 2., 3., 4., 5., 6.], shape(B)) res = is_square(A) ! returns .true. res = is_square(B) ! returns .false. end program example_is_square fortran-lang-stdlib-0ede301/example/linalg/example_determinant2.f900000664000175000017500000000043715135654166025522 0ustar alastairalastairprogram example_determinant2 use stdlib_kinds, only: dp use stdlib_linalg, only: operator(.det.) implicit none real(dp) :: d ! Compute determinate of a real matrix d = .det.reshape([real(dp)::1,2,3,4],[2,2]) print *, d ! a*d-b*c = -2.0 end program example_determinant2 fortran-lang-stdlib-0ede301/example/linalg/example_sparse_data_accessors.f900000664000175000017500000000254315135654166027461 0ustar alastairalastairprogram example_sparse_data_accessors use stdlib_linalg_constants, only: dp use stdlib_sparse implicit none real(dp) :: mat(2, 2) real(dp), allocatable :: dense_matrix(:, :) type(CSR_dp_type) :: CSR type(COO_dp_type) :: COO integer :: i, j, locdof(2) ! Initial data mat(:, 1) = [1._dp, 2._dp] mat(:, 2) = [2._dp, 1._dp] allocate (dense_matrix(5, 5), source=0._dp) do i = 0, 3 dense_matrix(1 + i:2 + i, 1 + i:2 + i) = dense_matrix(1 + i:2 + i, 1 + i:2 + i) + mat end do print *, 'Original Matrix' do j = 1, 5 print '(5f8.1)', dense_matrix(j, :) end do ! Initialize CSR data and reset dense reference matrix call dense2coo(dense_matrix, COO) call coo2csr(COO, CSR) CSR%data = 0._dp dense_matrix = 0._dp ! Iteratively add blocks of data do i = 0, 3 locdof(1:2) = [1 + i, 2 + i] call CSR%add(locdof, locdof, mat) ! lets print a dense view of every step call csr2dense(CSR, dense_matrix) print '(A,I2)', 'Add block :', i + 1 do j = 1, 5 print '(5f8.1)', dense_matrix(j, :) end do end do ! Request values from the matrix print *, '' print *, 'within sparse pattern :', CSR%at(2, 1) print *, 'outside sparse pattern :', CSR%at(5, 2) print *, 'outside matrix pattern :', CSR%at(7, 7) end program example_sparse_data_accessors fortran-lang-stdlib-0ede301/example/linalg/example_solve_cg.f900000664000175000017500000000070015135654166024720 0ustar alastairalastairprogram example_solve_cg use stdlib_kinds, only: int8, dp use stdlib_linalg_iterative_solvers, only: stdlib_solve_cg real(dp) :: matrix(2,2) real(dp) :: x(2), rhs(2) matrix = reshape( [4, 1,& 1, 3] , [2,2]) x = dble( [2,1] ) !> initial guess rhs = dble( [1,2] ) !> rhs vector call stdlib_solve_cg(matrix, rhs, x, restart=.false.) print *, x !> solution: [0.0909, 0.6364] end programfortran-lang-stdlib-0ede301/example/linalg/example_schur_eigvals.f900000664000175000017500000000160415135654166025761 0ustar alastairalastair! This example includes eigenvalue computation in addition to ! the Schur decomposition for a randomly generated matrix. program example_schur_eigenvalues use stdlib_linalg, only: schur use stdlib_linalg_constants, only: dp implicit none integer, parameter :: n = 5 real(dp), dimension(n,n) :: A, T, Z complex(dp), dimension(n) :: eigenvalues ! Create a random real-valued square matrix call random_number(A) ! Compute the Schur decomposition and eigenvalues call schur(A, T, Z, eigenvalues) ! Output results print *, "Random Matrix A:" print *, A print *, "Schur Form Matrix T:" print *, T print *, "Orthogonal Matrix Z:" print *, Z print *, "Eigenvalues:" print *, eigenvalues ! Test factorization: Z*T*Z^T = A print *, "Max error in reconstruction:", maxval(abs(matmul(Z, matmul(T, transpose(Z))) - A)) end program example_schur_eigenvalues fortran-lang-stdlib-0ede301/example/linalg/example_cross_product.f900000664000175000017500000000036015135654166026012 0ustar alastairalastairprogram demo_cross_product use stdlib_linalg, only: cross_product implicit none real :: a(3), b(3), c(3) a = [1., 0., 0.] b = [0., 1., 0.] c = cross_product(a, b) !c = [0., 0., 1.] end program demo_cross_product fortran-lang-stdlib-0ede301/example/linalg/example_eye1.f900000664000175000017500000000111315135654166023761 0ustar alastairalastairprogram example_eye1 use stdlib_linalg, only: eye implicit none integer :: i(2, 2) real :: a(3, 3) real :: b(2, 3) !! Matrix is non-square. complex :: c(2, 2) I = eye(2) !! [1,0; 0,1] A = eye(3) !! [1.0,0.0,0.0; 0.0,1.0,0.0; 0.0,0.0,1.0] A = eye(3, 3) !! [1.0,0.0,0.0; 0.0,1.0,0.0; 0.0,0.0,1.0] B = eye(2, 3) !! [1.0,0.0,0.0; 0.0,1.0,0.0] C = eye(2, 2) !! [(1.0,0.0),(0.0,0.0); (0.0,0.0),(1.0,0.0)] C = (1.0, 1.0)*eye(2, 2) !! [(1.0,1.0),(0.0,0.0); (0.0,0.0),(1.0,1.0)] end program example_eye1 fortran-lang-stdlib-0ede301/example/linalg/example_solve1.f900000664000175000017500000000117415135654166024336 0ustar alastairalastairprogram example_solve1 use stdlib_linalg_constants, only: sp use stdlib_linalg, only: solve, linalg_state_type implicit none real(sp), allocatable :: A(:,:),b(:),x(:) ! Solve a system of 3 linear equations: ! 4x + 3y + 2z = 25 ! -2x + 2y + 3z = -10 ! 3x - 5y + 2z = -4 ! Note: Fortran is column-major! -> transpose A = transpose(reshape([ 4, 3, 2, & -2, 2, 3, & 3,-5, 2], [3,3])) b = [25,-10,-4] ! Get coefficients of y = coef(1) + x*coef(2) + x^2*coef(3) x = solve(A,b) print *, 'solution: ',x ! 5.0, 3.0, -2.0 end program example_solve1 fortran-lang-stdlib-0ede301/example/linalg/example_diag5.f900000664000175000017500000000043515135654166024115 0ustar alastairalastairprogram example_diag5 use stdlib_linalg, only: diag implicit none integer, parameter :: n = 3 real :: A(n, n) real, allocatable :: v(:) A = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [n, n]) v = diag(A, -1) ! v is [2,6] v = diag(A, 1) ! v is [4,8] end program example_diag5 fortran-lang-stdlib-0ede301/example/linalg/example_pivoting_qr.f900000664000175000017500000000061115135654166025461 0ustar alastairalastairprogram example_pivoting_qr use stdlib_linalg, only: qr implicit none real :: A(104, 32), Q(104, 32), R(32, 32) integer :: pivots(32) ! Create a random matrix call random_number(A) ! Compute its QR factorization (reduced) call qr(A, Q, R, pivots) ! Test factorization: Q*R = A print *, maxval(abs(matmul(Q, R) - A(:, pivots))) end program example_pivoting_qr fortran-lang-stdlib-0ede301/example/linalg/example_inverse_operator.f900000664000175000017500000000113715135654166026512 0ustar alastairalastair! Matrix inversion example: operator interface program example_inverse_operator use stdlib_linalg_constants, only: dp use stdlib_linalg, only: operator(.inv.),eye implicit none real(dp) :: A(2,2), Am1(2,2) ! Input matrix (NB Fortran is column major! input columns then transpose) A = transpose(reshape( [4, 3, & 3, 2], [2,2] )) ! Invert matrix Am1 = .inv.A print *, ' |',Am1(1,:),'|' ! | -2 3 | print *, ' inv(A)= |',Am1(2,:),'|' ! | 3 -4 | ! Final check print *, 'CHECK passed? ',matmul(A,Am1)==eye(2) end program example_inverse_operator fortran-lang-stdlib-0ede301/example/linalg/example_diag2.f900000664000175000017500000000037415135654166024114 0ustar alastairalastairprogram example_diag2 use stdlib_linalg, only: diag implicit none real, allocatable :: v(:) real, allocatable :: A(:, :) v = [1, 2, 3, 4, 5] A = diag(v) ! creates a 5 by 5 matrix with elements of v on the diagonal end program example_diag2 fortran-lang-stdlib-0ede301/example/linalg/example_svdvals.f900000664000175000017500000000110415135654166024600 0ustar alastairalastair! Singular Values program example_svdvals use stdlib_linalg_constants, only: dp use stdlib_linalg, only: svdvals implicit none real(dp), allocatable :: A(:,:),s(:) character(*), parameter :: fmt="(a,*(1x,f12.8))" ! We want to find the singular values of matrix: ! ! A = [ 3 2 2] ! [ 2 3 -2] ! A = transpose(reshape([ 3, 2, 2, & 2, 3,-2], [3,2])) ! Get singular values s = svdvals(A) ! Singular values: [5, 3] print fmt, ' ' print fmt, 'S = ',s print fmt, ' ' end program example_svdvals fortran-lang-stdlib-0ede301/example/linalg/example_pseudoinverse.f900000664000175000017500000000166115135654166026021 0ustar alastairalastair! Matrix pseudo-inversion example: function, subroutine, and operator interfaces program example_pseudoinverse use stdlib_linalg, only: pinv, pseudoinvert, operator(.pinv.), linalg_state_type implicit none real :: A(15,5), Am1(5,15) type(linalg_state_type) :: state ! Generate random matrix A (15x15) call random_number(A) ! Pseudo-inverse: Function interfcae Am1 = pinv(A, err=state) print *, 'Max error (function) : ', maxval(abs(A-matmul(A, matmul(Am1,A)))) ! User threshold Am1 = pinv(A, rtol=0.001, err=state) print *, 'Max error (rtol=0.001): ', maxval(abs(A-matmul(A, matmul(Am1,A)))) ! Pseudo-inverse: Subroutine interface call pseudoinvert(A, Am1, err=state) print *, 'Max error (subroutine): ', maxval(abs(A-matmul(A, matmul(Am1,A)))) ! Operator interface Am1 = .pinv.A print *, 'Max error (operator) : ', maxval(abs(A-matmul(A, matmul(Am1,A)))) end program example_pseudoinverse fortran-lang-stdlib-0ede301/example/linalg/example_matrix_exp.f900000664000175000017500000000071715135654166025307 0ustar alastairalastairprogram example_expm use stdlib_linalg, only: matrix_exp implicit none real :: A(3, 3), E(3, 3) integer :: i print *, "Matrix A :" do i = 1, 3 print *, A(i, :) end do A = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3]) call matrix_exp(A) ! In-place computation. ! For out-of-place, use call matrix_exp(A, E). print *, "Matrix exponential E = exp(A):" do i = 1, 3 print *, E(i, :) end do end program example_expm fortran-lang-stdlib-0ede301/example/linalg/example_solve2.f900000664000175000017500000000142415135654166024335 0ustar alastairalastairprogram example_solve2 use stdlib_linalg_constants, only: sp use stdlib_linalg, only: solve, linalg_state_type implicit none complex(sp), allocatable :: A(:,:),b(:),x(:) ! Solve a system of 3 complex linear equations: ! 2x + iy + 2z = (5-i) ! -ix + (4-3i)y + 6z = i ! 4x + 3y + z = 1 ! Note: Fortran is column-major! -> transpose A = transpose(reshape([(2.0, 0.0),(0.0, 1.0),(2.0,0.0), & (0.0,-1.0),(4.0,-3.0),(6.0,0.0), & (4.0, 0.0),(3.0, 0.0),(1.0,0.0)] , [3,3])) b = [(5.0,-1.0),(0.0,1.0),(1.0,0.0)] ! Get coefficients of y = coef(1) + x*coef(2) + x^2*coef(3) x = solve(A,b) print *, 'solution: ',x ! (1.0947,0.3674) (-1.519,-0.4539) (1.1784,-0.1078) end program example_solve2 fortran-lang-stdlib-0ede301/example/linalg/example_svd.f900000664000175000017500000000211415135654166023714 0ustar alastairalastair! Singular Value Decomposition program example_svd use stdlib_linalg_constants, only: dp use stdlib_linalg, only: svd implicit none real(dp), allocatable :: A(:,:),s(:),u(:,:),vt(:,:) character(*), parameter :: fmt = "(a,*(1x,f12.8))" ! We want to find the singular value decomposition of matrix: ! ! A = [ 3 2 2] ! [ 2 3 -2] ! A = transpose(reshape([ 3, 2, 2, & 2, 3,-2], [3,2])) ! Prepare arrays allocate(s(2),u(2,2),vt(3,3)) ! Get singular value decomposition call svd(A,s,u,vt) ! Singular values: [5, 3] print fmt, ' ' print fmt, 'S = ',s print fmt, ' ' ! Left vectors (may be flipped): ! [2/2 2/2] ! U = [2/2 -2/2] ! print fmt, ' ' print fmt, 'U = ',u(1,:) print fmt, ' ',u(2,:) ! Right vectors (may be flipped): ! [2/2 2/2 0] ! V = [1/18 -1/18 4/18] ! [ 2/3 -2/3 -1/3] ! print fmt, ' ' print fmt, ' ',vt(1,:) print fmt, 'VT= ',vt(2,:) print fmt, ' ',vt(3,:) print fmt, ' ' end program example_svd fortran-lang-stdlib-0ede301/example/linalg/example_constrained_lstsq2.f900000664000175000017500000000275215135654166026751 0ustar alastairalastair! Demonstrate expert subroutine interface with pre-allocated arrays program example_constrained_lstsq2 use stdlib_linalg_constants, only: dp use stdlib_linalg, only: solve_constrained_lstsq, constrained_lstsq_space implicit none integer, parameter :: m = 5, n = 4, p = 3 !> Least-squares cost. real(dp) :: A(m, n), b(m) !> Equality constraints. real(dp) :: C(p, n), d(p) !> Solution. real(dp) :: x(n), x_true(n) !> Workspace array. integer :: lwork real(dp), allocatable :: work(:) !> Least-squares cost. A(1, :) = [1.0_dp, 1.0_dp, 1.0_dp, 1.0_dp] A(2, :) = [1.0_dp, 3.0_dp, 1.0_dp, 1.0_dp] A(3, :) = [1.0_dp, -1.0_dp, 3.0_dp, 1.0_dp] A(4, :) = [1.0_dp, 1.0_dp, 1.0_dp, 3.0_dp] A(5, :) = [1.0_dp, 1.0_dp, 1.0_dp, -1.0_dp] b = [2.0_dp, 1.0_dp, 6.0_dp, 3.0_dp, 1.0_dp] !> Equality constraints. C(1, :) = [1.0_dp, 1.0_dp, 1.0_dp, -1.0_dp] C(2, :) = [1.0_dp, -1.0_dp, 1.0_dp, 1.0_dp] C(3, :) = [1.0_dp, 1.0_dp, -1.0_dp, 1.0_dp] d = [1.0_dp, 3.0_dp, -1.0_dp] !> Optimal workspace size. call constrained_lstsq_space(A, C, lwork) allocate (work(lwork)) ! Compute the solution. call solve_constrained_lstsq(A, b, C, d, x, & storage=work, & overwrite_matrices=.true.) x_true = [0.5_dp, -0.5_dp, 1.5_dp, 0.5_dp] print *, "Exact solution :" print *, x_true print * print *, "Computed solution :" print *, x end program example_constrained_lstsq2 fortran-lang-stdlib-0ede301/example/linalg/example_norm.f900000664000175000017500000000305715135654166024102 0ustar alastairalastair! Vector norm: demonstrate usage of the function interface program example_norm use stdlib_linalg, only: norm, linalg_state_type implicit none real :: a(3,3),na integer :: j type(linalg_state_type) :: err ! a = [ -3.00000000 0.00000000 3.00000000 ! -2.00000000 1.00000000 4.00000000 ! -1.00000000 2.00000000 5.00000000 ] a = reshape([(j-4,j=1,9)], [3,3]) print "(' a = [ ',3(g0,3x),2(/9x,3(g0,3x)),']')", transpose(a) ! Norm with integer input print *, 'Euclidean norm = ',norm(a, 2) ! 8.30662346 ! Norm with character input print *, 'Euclidean norm = ',norm(a, '2') ! 8.30662346 ! Euclidean norm of row arrays, a(i,:) print *, 'Rows norms = ',norm(a, 2, dim=2) ! 4.24264050 4.58257580 5.47722578 ! Euclidean norm of columns arrays, a(:,i) print *, 'Columns norms = ',norm(a, 2, dim=1) ! 3.74165750 2.23606801 7.07106781 ! Infinity norms print *, 'maxval(||a||) = ',norm(a, 'inf') ! 5.00000000 print *, 'maxval(||a(i,:)||) = ',norm(a, 'inf', dim=2) ! 3.00000000 4.00000000 5.00000000 print *, 'minval(||a||) = ',norm(a, '-inf') ! 0.00000000 print *, 'minval(||a(:,i)||) = ',norm(a, '-inf', dim=1) ! 1.00000000 0.00000000 3.00000000 ! Catch Error: ! [norm] returned Value Error: dimension 4 is out of rank for shape(a)= [3, 3] print *, 'invalid: ',norm(a,'inf', dim=4, err=err) print *, 'error = ',err%print() end program example_norm fortran-lang-stdlib-0ede301/example/linalg/example_lstsq1.f900000664000175000017500000000120615135654166024350 0ustar alastairalastair! Least-squares solver: functional interface program example_lstsq1 use stdlib_linalg_constants, only: dp use stdlib_linalg, only: lstsq implicit none integer, allocatable :: x(:),y(:) real(dp), allocatable :: A(:,:),b(:),coef(:) ! Data set x = [1, 2, 2] y = [5, 13, 25] ! Fit three points using a parabola, least squares method ! A = [1 x x**2] A = reshape([[1,1,1],x,x**2],[3,3]) b = y ! Get coefficients of y = coef(1) + x*coef(2) + x^2*coef(3) coef = lstsq(A,b) print *, 'parabola: ',coef ! parabola: -0.42857142857141695 1.1428571428571503 4.2857142857142811 end program example_lstsq1 fortran-lang-stdlib-0ede301/example/linalg/example_chol.f900000664000175000017500000000110115135654166024040 0ustar alastairalastair! Cholesky factorization: function interface program example_chol use stdlib_linalg, only: chol implicit none real, allocatable, dimension(:,:) :: A,L,U ! Set real matrix A = reshape( [ [6, 15, 55], & [15, 55, 225], & [55, 225, 979] ], [3,3] ) ! Decompose (lower) L = chol(A, lower=.true.) ! Compare decomposition print *, maxval(abs(A-matmul(L,transpose(L)))) ! Decompose (upper) U = chol(A, lower=.false.) ! Compare decomposition print *, maxval(abs(A-matmul(transpose(U),U))) end program example_chol fortran-lang-stdlib-0ede301/example/linalg/example_is_hermitian.f900000664000175000017500000000064515135654166025602 0ustar alastairalastairprogram example_is_hermitian use stdlib_linalg, only: is_hermitian implicit none complex :: A(2, 2), B(2, 2) logical :: res A = reshape([cmplx(1., 0.), cmplx(3., -1.), cmplx(3., 1.), cmplx(4., 0.)], shape(A)) B = reshape([cmplx(1., 0.), cmplx(3., 1.), cmplx(3., 1.), cmplx(4., 0.)], shape(B)) res = is_hermitian(A) ! returns .true. res = is_hermitian(B) ! returns .false. end program example_is_hermitian fortran-lang-stdlib-0ede301/example/linalg/example_lapack_getrf.f900000664000175000017500000000056015135654166025545 0ustar alastairalastairprogram example_getrf use stdlib_linalg, only: eye use stdlib_linalg_lapack, only: dp,ilp,getrf implicit none real(dp) :: A(3, 3) integer(ilp) :: ipiv(3),info A = eye(3) ! LAPACK matrix factorization interface (overwrite result) call getrf(size(A,1),size(A,2),A,size(A,1),ipiv,info) print *, info ! info==0: Success! end program example_getrf fortran-lang-stdlib-0ede301/example/linalg/example_kronecker_product.f900000664000175000017500000000132715135654166026650 0ustar alastairalastairprogram example_kronecker_product use stdlib_linalg, only: kronecker_product implicit none integer, parameter :: m1 = 1, n1 = 2, m2 = 2, n2 = 3 integer :: i, j real :: A(m1, n1), B(m2,n2) real, allocatable :: C(:,:) do j = 1, n1 do i = 1, m1 A(i,j) = i*j ! A = [1, 2] end do end do do j = 1, n2 do i = 1, m2 ! B = [ 1, 2, 3 ] B(i,j) = i*j ! [ 2, 4, 6 ] end do end do C = kronecker_product(A, B) ! C = [ a(1,1) * B(:,:) | a(1,2) * B(:,:) ] ! or in other words, ! C = [ 1.00 2.00 3.00 2.00 4.00 6.00 ] ! [ 2.00 4.00 6.00 4.00 8.00 12.00 ] end program example_kronecker_product fortran-lang-stdlib-0ede301/example/linalg/example_pivoting_qr_space.f900000664000175000017500000000135315135654166026640 0ustar alastairalastair! Pivoting QR example with pre-allocated storage program example_pivoting_qr_space use stdlib_linalg_constants, only: ilp use stdlib_linalg, only: qr, qr_space, linalg_state_type implicit none real :: A(104, 32), Q(104, 32), R(32, 32) real, allocatable :: work(:) integer(ilp) :: lwork, pivots(32) type(linalg_state_type) :: err ! Create a random matrix call random_number(A) ! Prepare QR workspace call qr_space(A, lwork, pivoting=.true.) allocate (work(lwork)) ! Compute its QR factorization (reduced) call qr(A, Q, R, pivots, storage=work, err=err) ! Test factorization: Q*R = A print *, maxval(abs(matmul(Q, R) - A(:, pivots))) print *, err%print() end program example_pivoting_qr_space fortran-lang-stdlib-0ede301/example/linalg/example_inverse_inplace.f900000664000175000017500000000114215135654166026266 0ustar alastairalastair! Matrix inversion example: in-place inversion program example_inverse_inplace use stdlib_linalg_constants, only: dp use stdlib_linalg, only: invert,eye implicit none real(dp) :: A(2,2), Am1(2,2) ! Input matrix (NB Fortran is column major! input columns then transpose) A = transpose(reshape( [4, 3, & 3, 2], [2,2] )) Am1 = A ! Invert matrix call invert(Am1) print *, ' |',Am1(1,:),'|' ! | -2 3 | print *, ' inv(A)= |',Am1(2,:),'|' ! | 3 -4 | ! Final check print *, 'CHECK passed? ',matmul(A,Am1)==eye(2) end program example_inverse_inplace fortran-lang-stdlib-0ede301/example/linalg/example_constrained_lstsq1.f900000664000175000017500000000222515135654166026743 0ustar alastairalastair! Constrained least-squares solver: functional interface program example_constrained_lstsq1 use stdlib_linalg_constants, only: dp use stdlib_linalg, only: constrained_lstsq implicit none integer, parameter :: m = 5, n = 4, p = 3 !> Least-squares cost. real(dp) :: A(m, n), b(m) !> Equality constraints. real(dp) :: C(p, n), d(p) !> Solution. real(dp) :: x(n), x_true(n) !> Least-squares cost. A(1, :) = [1.0_dp, 1.0_dp, 1.0_dp, 1.0_dp] A(2, :) = [1.0_dp, 3.0_dp, 1.0_dp, 1.0_dp] A(3, :) = [1.0_dp, -1.0_dp, 3.0_dp, 1.0_dp] A(4, :) = [1.0_dp, 1.0_dp, 1.0_dp, 3.0_dp] A(5, :) = [1.0_dp, 1.0_dp, 1.0_dp, -1.0_dp] b = [2.0_dp, 1.0_dp, 6.0_dp, 3.0_dp, 1.0_dp] !> Equality constraints. C(1, :) = [1.0_dp, 1.0_dp, 1.0_dp, -1.0_dp] C(2, :) = [1.0_dp, -1.0_dp, 1.0_dp, 1.0_dp] C(3, :) = [1.0_dp, 1.0_dp, -1.0_dp, 1.0_dp] d = [1.0_dp, 3.0_dp, -1.0_dp] ! Compute the solution. x = constrained_lstsq(A, b, C, d) x_true = [0.5_dp, -0.5_dp, 1.5_dp, 0.5_dp] print *, "Exact solution :" print *, x_true print * print *, "Computed solution :" print *, x end program example_constrained_lstsq1 fortran-lang-stdlib-0ede301/example/linalg/example_is_diagonal.f900000664000175000017500000000050415135654166025372 0ustar alastairalastairprogram example_is_diagonal use stdlib_linalg, only: is_diagonal implicit none real :: A(2, 2), B(2, 2) logical :: res A = reshape([1., 0., 0., 4.], shape(A)) B = reshape([1., 0., 3., 4.], shape(B)) res = is_diagonal(A) ! returns .true. res = is_diagonal(B) ! returns .false. end program example_is_diagonal fortran-lang-stdlib-0ede301/example/linalg/example_state1.f900000664000175000017500000000135315135654166024325 0ustar alastairalastairprogram example_state1 use stdlib_linalg_state, only: linalg_state_type, LINALG_SUCCESS, LINALG_VALUE_ERROR, & operator(/=) implicit none type(linalg_state_type) :: err ! To create a state variable, we enter its integer state flag, followed by a list of variables ! that will be automatically assembled into a formatted error message. No need to provide string formats err = linalg_state_type(LINALG_VALUE_ERROR,'just an example with scalar ',& 'integer=',1,'real=',2.0,'complex=',(3.0,1.0),'and array ',[1,2,3],'inputs') ! Print flag print *, err%print() ! Check success print *, 'Check error: ',err%error() print *, 'Check flag : ',err /= LINALG_SUCCESS end program example_state1 fortran-lang-stdlib-0ede301/example/linalg/example_solve_bicgstab.f900000664000175000017500000000212615135654166026111 0ustar alastairalastairprogram example_solve_bicgstab use stdlib_kinds, only: dp use stdlib_linalg_iterative_solvers implicit none integer, parameter :: n = 4 real(dp) :: A(n,n), b(n), x(n) integer :: i ! Example matrix (same as SciPy documentation) A = reshape([4.0_dp, 2.0_dp, 0.0_dp, 1.0_dp, & 3.0_dp, 0.0_dp, 0.0_dp, 2.0_dp, & 0.0_dp, 1.0_dp, 1.0_dp, 1.0_dp, & 0.0_dp, 2.0_dp, 1.0_dp, 0.0_dp], [n,n]) b = [-1.0_dp, -0.5_dp, -1.0_dp, 2.0_dp] x = 0.0_dp ! Initial guess print *, 'Solving Ax = b using BiCGSTAB method:' print *, 'Matrix A:' do i = 1, n print '(4F8.2)', A(i,:) end do print *, 'Right-hand side b:' print '(4F8.2)', b ! Solve using BiCGSTAB call stdlib_solve_bicgstab(A, b, x, rtol=1e-10_dp, atol=1e-12_dp) print *, 'Solution x:' print '(4F10.6)', x ! Verify solution print *, 'Verification A*x:' print '(4F10.6)', matmul(A, x) print *, 'Residual ||b - A*x||:' print *, norm2(b - matmul(A, x)) end program fortran-lang-stdlib-0ede301/example/version/0000775000175000017500000000000015135654166021306 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/version/CMakeLists.txt0000664000175000017500000000002515135654166024043 0ustar alastairalastairADD_EXAMPLE(version) fortran-lang-stdlib-0ede301/example/version/example_version.f900000664000175000017500000000033715135654166025031 0ustar alastairalastairprogram example_version use stdlib_version, only: get_stdlib_version implicit none character(len=:), allocatable :: version call get_stdlib_version(string=version) print '(a)', version end program example_version fortran-lang-stdlib-0ede301/example/stats_distribution_uniform/0000775000175000017500000000000015135654166025315 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/stats_distribution_uniform/CMakeLists.txt0000664000175000017500000000014015135654166030050 0ustar alastairalastairADD_EXAMPLE(shuffle) ADD_EXAMPLE(uniform_cdf) ADD_EXAMPLE(uniform_pdf) ADD_EXAMPLE(uniform_rvs) fortran-lang-stdlib-0ede301/example/stats_distribution_uniform/example_uniform_cdf.f900000664000175000017500000000343115135654166031644 0ustar alastairalastairprogram example_uniform_cdf use stdlib_random, only: random_seed use stdlib_stats_distribution_uniform, only: uni_cdf => cdf_uniform, & uni => rvs_uniform implicit none real :: x(3, 4, 5), a(3, 4, 5), b(3, 4, 5) complex :: loc, scale integer :: seed_put, seed_get seed_put = 1234567 call random_seed(seed_put, seed_get) print *, uni_cdf(0.5, 0., 1.) ! a cumulative at 0.5 in [0., 1.] !0.500000000 print *, uni_cdf(0.7, -1.0, 2.0) ! a cumulative at 0.7 in [-1.0, 1.0] ! 0.850000024 print *, uni_cdf(6, 2, 10) ! a cumulative at 6 in [2, 10] ! 0.454545468 a(:, :, :) = -1.0 b(:, :, :) = 2.0 x = reshape(uni(-1.0, 2.0, 60), [3, 4, 5]) ! uniform random variates array print *, uni_cdf(x, a, b) ! cumulative array in [-1.0, 1.0] !0.161520004 0.553248405 0.986900032 0.942091405 0.114239901 0.780188501 ! 0.854656875 0.464386612 0.284466714 0.748768032 0.301834047 0.337008357 !0.568843365 0.596165061 0.180993259 0.614166319 0.214835495 7.98164606E-02 !0.641274095 0.607101977 0.701139212 0.230517209 1.97925568E-02 0.857982159 !0.712761045 0.139202654 0.361759573 0.796536088 0.356012046 0.197665215 !9.80764329E-02 0.781620383 0.595349193 0.125651121 0.957528770 0.942990601 !0.259489566 7.84273148E-02 0.779313922 0.317909390 0.559013724 0.421358019 !0.878484428 7.67416358E-02 0.298707575 0.693327367 0.146014273 0.102338850 !0.855926156 0.250811368 0.300751567 0.110186398 0.502883077 0.738479793 !0.764856219 0.294822574 1.90783739E-02 0.631218433 0.752170086 0.196848959 loc = (0., 0.) scale = (2., 1.) print *, uni_cdf((1.2, 0.5), loc, scale) ! joint cumulative distribution at (1.2,0.5) in [(0.,0.), (2.,1.)] ! 0.300000012 end program example_uniform_cdf fortran-lang-stdlib-0ede301/example/stats_distribution_uniform/example_shuffle.f900000664000175000017500000000156515135654166031013 0ustar alastairalastairprogram example_shuffle use stdlib_random, only: random_seed use stdlib_stats_distribution_uniform, only: shuffle implicit none integer :: seed_put, seed_get, i real :: x(10) integer :: n(10) complex :: z(10) do i = 1, 10 n(i) = i x(i) = real(i) z(i) = cmplx(real(i), real(i)) end do seed_put = 32165498 call random_seed(seed_put, seed_get) ! set and get current value of seed print *, shuffle(n) ! get randomized n !10 6 9 2 8 1 3 5 7 4 print *, shuffle(x) ! get randomized x !5.0 10.0 9.0 4.0 3.0 8.0 2.0 1.0 7.0 6.0 print *, shuffle(z) ! get randomized z !(8.0, 8.0) (7.0, 7.0) (4.0, 4.0) (1.0, 1.0) (5.0, 5.0) !(9.0, 9.0) (6.0, 6.0) (3.0, 3.0) (2.0, 2.0) (10.0, 10.0) end program example_shuffle fortran-lang-stdlib-0ede301/example/stats_distribution_uniform/example_uniform_rvs.f900000664000175000017500000000532215135654166031723 0ustar alastairalastairprogram example_uniform_rvs use stdlib_random, only: random_seed use stdlib_stats_distribution_uniform, only: uni => rvs_uniform implicit none complex :: loc, scale real :: a(3, 4, 5), b(3, 4, 5) integer :: seed_put, seed_get seed_put = 1234567 call random_seed(seed_put, seed_get) print *, uni() !real standard uniform random variate in [0., 1.] ! 0.161520019 print *, uni(3.0) !an uniform random variate in [0., 3.] ! 1.65974522 print *, uni(-0.5, 1.0) !an uniform random variate in [-0.5, 0.5] ! 0.486900032 print *, uni(-1.0, 2.0, 10) !an array of 10 uniform random variates in [-1., 1.] !0.884182811 -0.771520197 0.560377002 0.709313750 -7.12267756E-02 !-0.431066573 0.497536063 -0.396331906 -0.325983286 0.137686729 print *, uni(20) !a random integer variate in [0, 20] ! 17 print *, uni(5, 13) !a random integer variate in [5, 18] ! 15 print *, uni(3, 19, 10) !an array of 10 integer variates in [3,22] !7 16 16 12 9 21 19 4 3 19 loc = (-0.5, -0.5) scale = (1.0, 1.0) print *, uni(scale) !a complex uniform random variate in unit square !(0.139202669, 0.361759573) print *, uni(loc, scale) !a complex uniform random variate in [(-0.5, -0.5), (0.5, 0.5)] !(0.296536088,-0.143987954) print *, uni(loc, scale, 10) !an array of 10 complex uniform random variate in [(-0.5, -0.5), (0.5, 0.5)] !(-0.302334785,-0.401923567) (0.281620383,9.534919262E-02) ! (-0.374348879,0.457528770) (0.442990601,-0.240510434) ! (-0.421572685,0.279313922) (-0.182090610,5.901372433E-02) ! (-7.864198089E-02,0.378484428) (-0.423258364,-0.201292425) ! (0.193327367,-0.353985727) (-0.397661150,0.355926156) a(:, :, :) = -0.5 b(:, :, :) = 1.0 print *, uni(a, b) !a rank 3 array of random variates in [-0.5,0.5] ! -0.249188632 -0.199248433 -0.389813602 2.88307667E-03 0.238479793, ! 0.264856219 -0.205177426 -0.480921626 0.131218433 0.252170086, ! -0.303151041 -8.89462233E-02 -0.377370685 0.341802299 0.323204756, ! 0.358679056 -0.138909757 0.384329498 -0.109372199 0.132353067, ! 0.494320452 0.419343710 -0.103044361 0.461389005 0.403132677 ! 0.121850729 0.403839290 -0.349389791 0.490482628 0.156600773 ! 8.46788883E-02 -0.483680278 0.388107836 0.119698405 0.154214382 ! 0.153113484 0.236523747 0.155937552 -0.135760903 0.219589531 ! 0.394639254 6.30156994E-02 -0.342692465 -0.444846451 -0.215700030 ! 0.204189956 -0.208748132 0.355063021 8.98272395E-02 -0.237928331 ! 2.98077464E-02 -0.485149682 -8.06870461E-02 -0.372713923 ! -0.178335011 0.283877611 -2.13934183E-02 -9.21690464E-03 ! 4.56320047E-02 0.220112979 end program example_uniform_rvs fortran-lang-stdlib-0ede301/example/stats_distribution_uniform/example_uniform_pdf.f900000664000175000017500000000351515135654166031664 0ustar alastairalastairprogram example_uniform_pdf use stdlib_random, only: random_seed use stdlib_stats_distribution_uniform, only: uni_pdf => pdf_uniform, & uni => rvs_uniform implicit none complex :: loc, scale real :: a(3, 4, 5), b(3, 4, 5), x(3, 4, 5) integer :: seed_put, seed_get seed_put = 1234567 call random_seed(seed_put, seed_get) print *, uni_pdf(3, 2, 10) !probability density at 3 in range [2, 10] ! 9.09090936E-02 print *, uni_pdf(0.5, 0.0, 1.0) !a probability density at 0.5 in [0., 1.] ! 1.00000000 print *, uni_pdf(0.7, -1.0, 2.0) !a probability density at 0.7 in [-1., 1.] ! 0.500000000 a(:, :, :) = 0.0 b(:, :, :) = 2.0 x = reshape(uni(0., 2., 60), [3, 4, 5])! uniform random variates array in [0., 2.] print *, uni_pdf(x, a, b) ! probability density array in [0., 2.] ! 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 ! 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 ! 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 ! 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 ! 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 ! 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 ! 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 ! 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 ! 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 ! 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 0.500000000 loc = (-0.5, -0.5) scale = (1.0, 1.0) print *, uni_pdf((-0.1, 0.2), loc, scale) ! joint probability density at (-0.1,0.2) in [(-0.5, -0.5), (0.5, 0.5)] ! 1.00000000 end program example_uniform_pdf fortran-lang-stdlib-0ede301/example/stats_distribution_exponential/0000775000175000017500000000000015135654166026164 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/stats_distribution_exponential/example_exponential_pdf.f900000664000175000017500000000471415135654166033404 0ustar alastairalastairprogram example_exponential_pdf use stdlib_random, only: random_seed use stdlib_stats_distribution_exponential, only: exp_pdf => pdf_exp, & rexp => rvs_exp implicit none real, dimension(2, 3, 4) :: x, loc, scale real :: xsum complex :: cloc, cscale integer :: seed_put, seed_get, i seed_put = 1234567 call random_seed(seed_put, seed_get) ! probability density at x=1.0 with loc=0 and scale=1.0 print *, exp_pdf(1.0, 0.0, 1.0) ! 0.367879450 ! probability density at x=1.0 with lambda=1.0 print *, exp_pdf(1.0, 1.0) ! 0.367879450 ! probability density at x=2.0 with lambda=2.0 print *, exp_pdf(2.0, 2.0) ! 3.66312787E-02 ! probability density at x=2.0 with loc=0.0 and scale=0.5 (lambda=2.0) print *, exp_pdf(2.0, 0.0, 0.5) ! 3.66312787E-02 ! probability density at x=1.5 with loc=0.5 and scale=0.5 (lambda=2.0) print *, exp_pdf(2.5, 0.5, 0.5) ! 3.66312787E-02 ! probability density at x=2.0 with loc=0.0 and scale=-1.0 (out of range) print *, exp_pdf(2.0, 0.0, -1.0) ! NaN ! standard exponential random variates array x = reshape(rexp(0.0, 2.0, 24), [2, 3, 4]) ! a rank-3 exponential probability density loc(:, :, :) = 0.0 scale(:, :, :) = 2.0 print *, exp_pdf(x, loc, scale) ! 0.349295378 0.332413018 0.470253497 0.443498343 0.317152828 ! 0.208242029 0.443112582 8.07073265E-02 0.245337561 0.436016470 ! 7.14025944E-02 5.33841923E-02 0.322308093 0.264558554 0.212898195 ! 0.100339092 0.226891592 0.444002301 9.91026312E-02 3.87373678E-02 ! 3.11400592E-02 0.349431813 0.482774824 0.432669312 ! probability density array where scale<=0.0 for certain elements (loc = 0.0) print *, exp_pdf([1.0, 1.0, 1.0], [0.0, 0.0, 0.0], [1.0, 0.0, -1.0]) ! 0.367879450 NaN NaN ! `pdf_exp` is pure and, thus, can be called concurrently xsum = 0.0 do concurrent (i=1:size(x,3)) xsum = xsum + sum(exp_pdf(x(:,:,i), loc(:,:,i), scale(:,:,i))) end do print *, xsum ! 6.45566940 ! complex exponential probability density function at (1.5, 0.0, 1.0) with real part ! of scale=1.0 and imaginary part of scale=0.5 cloc = (0.0, 0.0) cscale = (1.0, 0.5) print *, exp_pdf((1.5, 1.0), cloc, cscale) ! 6.03947677E-02 ! As above, but with scale%re < 0 cloc = (0.0, 0.0) cscale = (-1.0, 2.0) print *, exp_pdf((1.5, 1.0), cloc, cscale) ! NaN end program example_exponential_pdf fortran-lang-stdlib-0ede301/example/stats_distribution_exponential/example_exponential_rvs.f900000664000175000017500000000226415135654166033443 0ustar alastairalastairprogram example_exponential_rvs use stdlib_random, only: random_seed use stdlib_stats_distribution_exponential, only: rexp => rvs_exp implicit none complex :: cloc, cscale integer :: seed_put, seed_get seed_put = 1234567 call random_seed(seed_put, seed_get) ! single standard exponential random variate print *, rexp() ! 0.358690143 ! exponential random variate with loc=0 and scale=0.5 (lambda=2) print *, rexp(0.0, 0.5) ! 0.122672431 ! exponential random variate with lambda=2 print *, rexp(2.0) ! 0.204114929 ! exponential random variate with loc=0.6 and scale=0.2 (lambda=5) print *, rexp(0.6, 0.2) ! 0.681645989 ! an array of 10 variates with loc=0.0 and scale=3.0 (lambda=1/3) print *, rexp(0.0, 3.0, 10) ! 1.36567295 2.62772131 0.362352759 5.47133636 2.13591909 ! 0.410784155 5.83882189 6.71128035 1.31730068 1.90963650 ! single complex exponential random variate with real part of scale=0.5 (lambda=2.0); ! imagainary part of scale=1.6 (lambda=0.625) cloc = (0.0, 0.0) cscale = (0.5, 1.6) print *, rexp(cloc, cscale) ! (0.426896989,2.56968451) end program example_exponential_rvs fortran-lang-stdlib-0ede301/example/stats_distribution_exponential/CMakeLists.txt0000664000175000017500000000012715135654166030724 0ustar alastairalastairADD_EXAMPLE(exponential_cdf) ADD_EXAMPLE(exponential_pdf) ADD_EXAMPLE(exponential_rvs) fortran-lang-stdlib-0ede301/example/stats_distribution_exponential/example_exponential_cdf.f900000664000175000017500000000515415135654166033366 0ustar alastairalastairprogram example_exponential_cdf use stdlib_random, only: random_seed use stdlib_stats_distribution_exponential, only: exp_cdf => cdf_exp, & rexp => rvs_exp implicit none real, dimension(2, 3, 4) :: x, loc, scale real :: xsum complex :: cloc, cscale integer :: seed_put, seed_get, i seed_put = 1234567 call random_seed(seed_put, seed_get) ! standard exponential cumulative distribution at x=1.0 with loc=0.0, scale=1.0 print *, exp_cdf(1.0, 0.0, 1.0) ! 0.632120550 ! standard exponential cumulative distribution at x=1.0 with lambda=1.0 print *, exp_cdf(1.0, 1.0) ! 0.632120550 ! cumulative distribution at x=2.0 with lambda=2 print *, exp_cdf(2.0, 2.0) ! 0.981684387 ! cumulative distribution at x=2.0 with loc=0.0 and scale=0.5 (equivalent of lambda=2) print *, exp_cdf(2.0, 0.0, 0.5) ! 0.981684387 ! cumulative distribution at x=2.5 with loc=0.5 and scale=0.5 (equivalent of lambda=2) print *, exp_cdf(2.5, 0.5, 0.5) ! 0.981684387 ! cumulative distribution at x=2.0 with loc=0.0 and scale=-1.0 (out of range) print *, exp_cdf(2.0, 0.0, -1.0) ! NaN ! cumulative distribution at x=0.5 with loc=1.0 and scale=1.0, putting x below the minimum print *, exp_cdf(0.5, 1.0, 1.0) ! 0.00000000 ! standard exponential random variates array x = reshape(rexp(0.0, 2.0, 24), [2, 3, 4]) ! a rank-3 exponential cumulative distribution loc(:, :, :) = 0.0 scale(:, :, :) = 2.0 print *, exp_cdf(x, loc, scale) ! 0.301409245 0.335173965 5.94930053E-02 0.113003314 ! 0.365694344 0.583515942 0.113774836 0.838585377 ! 0.509324908 0.127967060 0.857194781 0.893231630 ! 0.355383813 0.470882893 0.574203610 0.799321830 ! 0.546216846 0.111995399 0.801794767 0.922525287 ! 0.937719882 0.301136374 3.44503522E-02 0.134661376 ! cumulative distribution array where scale<=0.0 for certain elements print *, exp_cdf([1.0, 1.0, 1.0], [0.0, 0.0, 0.0], [1.0, 0.0, -1.0]) ! 0.632120550 NaN NaN ! `cdf_exp` is pure and, thus, can be called concurrently xsum = 0.0 do concurrent (i=1:size(x,3)) xsum = xsum + sum(exp_cdf(x(:,:,i), loc(:,:,i), scale(:,:,i))) end do print *, xsum ! 11.0886612 ! complex exponential cumulative distribution at (0.5, 0.0, 2) with real part of ! scale=2 and imaginary part of scale=1.0 cloc = (0.0, 0.0) cscale = (2, 1.0) print *, exp_cdf((0.5, 0.5), cloc, cscale) ! 8.70351046E-02 ! As above, but with scale%im < 0 cloc = (0.0, 0.0) cscale = (1.0, -2.0) print *, exp_cdf((1.5, 1.0), cloc, cscale) ! NaN end program example_exponential_cdf fortran-lang-stdlib-0ede301/example/specialfunctions_activations/0000775000175000017500000000000015135654166025576 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/specialfunctions_activations/example_leaky_relu.f900000664000175000017500000000051315135654166031764 0ustar alastairalastairprogram example_gelu use stdlib_kinds, only: sp use stdlib_math, only: linspace use stdlib_specialfunctions, only: leaky_relu implicit none integer, parameter :: n = 10 real(sp) :: x(n), y(n) x = linspace(-2._sp, 2._sp, n) y = leaky_relu( x , 0.1_sp ) print *, y end program example_gelu fortran-lang-stdlib-0ede301/example/specialfunctions_activations/example_elu.f900000664000175000017500000000046615135654166030424 0ustar alastairalastairprogram example_elu use stdlib_kinds, only: sp use stdlib_math, only: linspace use stdlib_specialfunctions, only: elu implicit none integer, parameter :: n = 10 real(sp) :: x(n), y(n) x = linspace(-2._sp, 2._sp, n) y = elu( x , 1.0 ) print *, y end program example_elu fortran-lang-stdlib-0ede301/example/specialfunctions_activations/example_silu.f900000664000175000017500000000046615135654166030613 0ustar alastairalastairprogram example_silu use stdlib_kinds, only: sp use stdlib_math, only: linspace use stdlib_specialfunctions, only: silu implicit none integer, parameter :: n = 10 real(sp) :: x(n), y(n) x = linspace(-2._sp, 2._sp, n) y = silu( x ) print *, y end program example_silu fortran-lang-stdlib-0ede301/example/specialfunctions_activations/example_logsoftmax.f900000664000175000017500000000051615135654166032016 0ustar alastairalastairprogram example_logsoftmax use stdlib_kinds, only: sp use stdlib_math, only: linspace use stdlib_specialfunctions, only: logsoftmax implicit none integer, parameter :: n = 10 real(sp) :: x(n), y(n) x = linspace(-2._sp, 2._sp, n) y = logsoftmax( x ) print *, y end program example_logsoftmax fortran-lang-stdlib-0ede301/example/specialfunctions_activations/example_softplus.f900000664000175000017500000000050615135654166031511 0ustar alastairalastairprogram example_softplus use stdlib_kinds, only: sp use stdlib_math, only: linspace use stdlib_specialfunctions, only: softplus implicit none integer, parameter :: n = 10 real(sp) :: x(n), y(n) x = linspace(-2._sp, 2._sp, n) y = softplus( x ) print *, y end program example_softplus fortran-lang-stdlib-0ede301/example/specialfunctions_activations/example_gelu.f900000664000175000017500000000046615135654166030573 0ustar alastairalastairprogram example_gelu use stdlib_kinds, only: sp use stdlib_math, only: linspace use stdlib_specialfunctions, only: gelu implicit none integer, parameter :: n = 10 real(sp) :: x(n), y(n) x = linspace(-2._sp, 2._sp, n) y = gelu( x ) print *, y end program example_gelu fortran-lang-stdlib-0ede301/example/specialfunctions_activations/example_selu.f900000664000175000017500000000046615135654166030607 0ustar alastairalastairprogram example_selu use stdlib_kinds, only: sp use stdlib_math, only: linspace use stdlib_specialfunctions, only: selu implicit none integer, parameter :: n = 10 real(sp) :: x(n), y(n) x = linspace(-2._sp, 2._sp, n) y = selu( x ) print *, y end program example_selu fortran-lang-stdlib-0ede301/example/specialfunctions_activations/example_gaussian.f900000664000175000017500000000050615135654166031444 0ustar alastairalastairprogram example_gaussian use stdlib_kinds, only: sp use stdlib_math, only: linspace use stdlib_specialfunctions, only: gaussian implicit none integer, parameter :: n = 10 real(sp) :: x(n), y(n) x = linspace(-2._sp, 2._sp, n) y = gaussian( x ) print *, y end program example_gaussian fortran-lang-stdlib-0ede301/example/specialfunctions_activations/CMakeLists.txt0000664000175000017500000000033415135654166030336 0ustar alastairalastairADD_EXAMPLE(elu) ADD_EXAMPLE(gaussian) ADD_EXAMPLE(gelu) ADD_EXAMPLE(leaky_relu) ADD_EXAMPLE(relu) ADD_EXAMPLE(selu) ADD_EXAMPLE(silu) ADD_EXAMPLE(softmax) ADD_EXAMPLE(logsoftmax) ADD_EXAMPLE(softplus) ADD_EXAMPLE(step) fortran-lang-stdlib-0ede301/example/specialfunctions_activations/example_step.f900000664000175000017500000000046615135654166030612 0ustar alastairalastairprogram example_step use stdlib_kinds, only: sp use stdlib_math, only: linspace use stdlib_specialfunctions, only: step implicit none integer, parameter :: n = 10 real(sp) :: x(n), y(n) x = linspace(-2._sp, 2._sp, n) y = step( x ) print *, y end program example_step fortran-lang-stdlib-0ede301/example/specialfunctions_activations/example_softmax.f900000664000175000017500000000050215135654166031307 0ustar alastairalastairprogram example_softmax use stdlib_kinds, only: sp use stdlib_math, only: linspace use stdlib_specialfunctions, only: softmax implicit none integer, parameter :: n = 10 real(sp) :: x(n), y(n) x = linspace(-2._sp, 2._sp, n) y = softmax( x ) print *, y end program example_softmax fortran-lang-stdlib-0ede301/example/specialfunctions_activations/example_relu.f900000664000175000017500000000046615135654166030606 0ustar alastairalastairprogram example_relu use stdlib_kinds, only: sp use stdlib_math, only: linspace use stdlib_specialfunctions, only: relu implicit none integer, parameter :: n = 10 real(sp) :: x(n), y(n) x = linspace(-2._sp, 2._sp, n) y = relu( x ) print *, y end program example_relu fortran-lang-stdlib-0ede301/example/array/0000775000175000017500000000000015135654166020737 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/array/example_trueloc.f900000664000175000017500000000033615135654166024451 0ustar alastairalastairprogram example_trueloc use stdlib_array, only: trueloc implicit none real, allocatable :: array(:) allocate (array(500)) call random_number(array) array(trueloc(array > 0.5)) = 0.0 end program example_trueloc fortran-lang-stdlib-0ede301/example/array/CMakeLists.txt0000664000175000017500000000005315135654166023475 0ustar alastairalastairADD_EXAMPLE(falseloc) ADD_EXAMPLE(trueloc) fortran-lang-stdlib-0ede301/example/array/example_falseloc.f900000664000175000017500000000037115135654166024563 0ustar alastairalastairprogram example_falseloc use stdlib_array, only: falseloc implicit none real, allocatable :: array(:) allocate (array(-200:200)) call random_number(array) array(falseloc(array < 0.5, lbound(array, 1))) = 0.0 end program example_falseloc fortran-lang-stdlib-0ede301/example/io/0000775000175000017500000000000015135654166020230 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/io/example_open.f900000664000175000017500000000030715135654166023224 0ustar alastairalastairprogram example_open use stdlib_io, only: open implicit none integer :: u u = open ('example.dat', 'wt') write (u, '(a)') 'This is an example for open' close (u) end program example_open fortran-lang-stdlib-0ede301/example/io/example_fmt_constants.f900000664000175000017500000000163215135654166025147 0ustar alastairalastairprogram example_fmt_constants use stdlib_kinds, only: int32, int64, sp, dp use stdlib_io, only: FMT_INT, FMT_REAL_SP, FMT_REAL_DP, FMT_COMPLEX_SP, FMT_COMPLEX_DP implicit none integer(kind=int32) :: i32 integer(kind=int64) :: i64 real(kind=sp) :: r32 real(kind=dp) :: r64 complex(kind=sp) :: c32 complex(kind=dp) :: c64 i32 = 100_int32 i64 = 100_int64 r32 = 100.0_sp r64 = 100.0_dp c32 = cmplx(100.0_sp, kind=sp) c64 = cmplx(100.0_dp, kind=dp) print "(2("//FMT_INT//",1x))", i32, i64 ! outputs: 100 100 print FMT_REAL_SP, r32 ! outputs: 1.00000000E+02 print FMT_REAL_DP, r64 ! outputs: 1.0000000000000000E+002 print FMT_COMPLEX_SP, c32 ! outputs: 1.00000000E+02 0.00000000E+00 print FMT_COMPLEX_DP, c64 ! outputs: 1.0000000000000000E+002 0.0000000000000000E+000 end program example_fmt_constants fortran-lang-stdlib-0ede301/example/io/example_loadtxt.f900000664000175000017500000000050315135654166023740 0ustar alastairalastairprogram example_loadtxt use stdlib_io, only: loadtxt implicit none real, allocatable :: x(:, :) call loadtxt('example.dat', x) ! Can also use list directed format if the default read fails. call loadtxt('example.dat', x, fmt='*') call loadtxt('example.csv', x, delimiter=',') end program example_loadtxt fortran-lang-stdlib-0ede301/example/io/CMakeLists.txt0000664000175000017500000000025615135654166022773 0ustar alastairalastairADD_EXAMPLE(fmt_constants) #ADD_EXAMPLE(get_line) ADD_EXAMPLE(get_file) ADD_EXAMPLE(loadnpy) ADD_EXAMPLE(loadtxt) ADD_EXAMPLE(open) ADD_EXAMPLE(savenpy) ADD_EXAMPLE(savetxt) fortran-lang-stdlib-0ede301/example/io/example.dat0000664000175000017500000000014015135654166022350 0ustar alastairalastair 1.00000000E+00 1.00000000E+00 1.00000000E+00 1.00000000E+00 1.00000000E+00 1.00000000E+00 fortran-lang-stdlib-0ede301/example/io/example_get_line.f900000664000175000017500000000057015135654166024053 0ustar alastairalastairprogram example_getline use, intrinsic :: iso_fortran_env, only: input_unit, output_unit use stdlib_io, only: get_line implicit none character(len=:), allocatable :: line integer :: stat call get_line(input_unit, line, stat) do while (stat == 0) write (output_unit, '(a)') line call get_line(input_unit, line, stat) end do end program example_getline fortran-lang-stdlib-0ede301/example/io/example.csv0000664000175000017500000000014015135654166022373 0ustar alastairalastair 1.00000000E+00, 1.00000000E+00 1.00000000E+00, 1.00000000E+00 1.00000000E+00, 1.00000000E+00 fortran-lang-stdlib-0ede301/example/io/example_savetxt.f900000664000175000017500000000031215135654166023755 0ustar alastairalastairprogram example_savetxt use stdlib_io, only: savetxt implicit none real :: x(3, 2) = 1 call savetxt('example.dat', x) call savetxt('example.csv', x, delimiter=',') end program example_savetxt fortran-lang-stdlib-0ede301/example/io/example.npy0000664000175000017500000000023015135654166022406 0ustar alastairalastairNUMPYv{'descr': '= 2 call select(array, k, kth_smallest, left=2) print *, kth_smallest ! print 5.0 k = 6 ! Due to the previous two calls to select, we know for sure this is in ! an index >= 2 and <= 7 call select(array, k, kth_smallest, left=2, right=7) print *, kth_smallest ! print 4.0 end program example_select fortran-lang-stdlib-0ede301/example/selection/example_arg_select.f900000664000175000017500000000145515135654166025756 0ustar alastairalastairprogram example_arg_select use stdlib_selection, only: arg_select implicit none real, allocatable :: array(:) integer, allocatable :: indx(:) integer :: kth_smallest integer :: k array = [3., 2., 7., 4., 5., 1., 4., -1.] indx = [(k, k=1, size(array))] k = 2 call arg_select(array, indx, k, kth_smallest) print *, array(kth_smallest) ! print 1.0 k = 7 ! Due to the previous call to arg_select, we know for sure this is in an ! index >= 2 call arg_select(array, indx, k, kth_smallest, left=2) print *, array(kth_smallest) ! print 5.0 k = 6 ! Due to the previous two calls to arg_select, we know for sure this is in ! an index >= 2 and <= 7 call arg_select(array, indx, k, kth_smallest, left=2, right=7) print *, array(kth_smallest) ! print 4.0 end program example_arg_select fortran-lang-stdlib-0ede301/example/selection/CMakeLists.txt0000664000175000017500000000005415135654166024345 0ustar alastairalastairADD_EXAMPLE(arg_select) ADD_EXAMPLE(select) fortran-lang-stdlib-0ede301/example/selection/selection_vs_sort.f900000664000175000017500000000467415135654166025705 0ustar alastairalastairprogram selection_vs_sort use stdlib_kinds, only: int64 use stdlib_selection, only: select, arg_select use stdlib_sorting, only: sort implicit none call compare_select_sort_for_median(1) call compare_select_sort_for_median(11) call compare_select_sort_for_median(101) call compare_select_sort_for_median(1001) call compare_select_sort_for_median(10001) call compare_select_sort_for_median(100001) contains subroutine compare_select_sort_for_median(N) integer, intent(in) :: N integer :: i, k, result_arg_select, indx(N), indx_local(N) real :: random_vals(N), local_random_vals(N) integer, parameter :: test_reps = 100 integer(int64) :: t0, t1 real :: result_sort, result_select integer(int64) :: time_sort, time_select, time_arg_select logical :: select_test_passed, arg_select_test_passed ! Ensure N is odd if (mod(N, 2) /= 1) stop time_sort = 0 time_select = 0 time_arg_select = 0 select_test_passed = .true. arg_select_test_passed = .true. indx = (/(i, i=1, N)/) k = (N + 1)/2 ! Deliberate integer division do i = 1, test_reps call random_number(random_vals) ! Compute the median with sorting local_random_vals = random_vals call system_clock(t0) call sort(local_random_vals) result_sort = local_random_vals(k) call system_clock(t1) time_sort = time_sort + (t1 - t0) ! Compute the median with selection, assuming N is odd local_random_vals = random_vals call system_clock(t0) call select(local_random_vals, k, result_select) call system_clock(t1) time_select = time_select + (t1 - t0) ! Compute the median with arg_select, assuming N is odd local_random_vals = random_vals indx_local = indx call system_clock(t0) call arg_select(local_random_vals, indx_local, k, result_arg_select) call system_clock(t1) time_arg_select = time_arg_select + (t1 - t0) if (result_select /= result_sort) select_test_passed = .FALSE. if (local_random_vals(result_arg_select) /= result_sort) arg_select_test_passed = .FALSE. end do print *, "select ; N=", N, '; ', merge('PASS', 'FAIL', select_test_passed), & '; Relative-speedup-vs-sort:', (1.0*time_sort)/(1.0*time_select) print *, "arg_select; N=", N, '; ', merge('PASS', 'FAIL', arg_select_test_passed), & '; Relative-speedup-vs-sort:', (1.0*time_sort)/(1.0*time_arg_select) end subroutine end program fortran-lang-stdlib-0ede301/example/stringlist_type/0000775000175000017500000000000015135654166023064 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/stringlist_type/example_stringlist_type_concatenate_operator.f900000664000175000017500000000220615135654166034641 0ustar alastairalastairprogram example_concatenate_operator use stdlib_stringlist_type, only: stringlist_type, operator(//) use stdlib_string_type, only: string_type implicit none type(stringlist_type) :: first_stringlist, second_stringlist type(string_type), allocatable :: stringarray(:) first_stringlist = first_stringlist//"Element No. one" ! first_stringlist <-- {"Element No. one"} second_stringlist = string_type("Element No. two")//first_stringlist ! second_stringlist <-- {Element No. two, "Element No. one"} !> Creating an array of 2 string_type elements stringarray = [string_type("Element No. three"), string_type("Element No. four")] second_stringlist = first_stringlist//stringarray ! second_stringlist <-- {"Element No. one", "Element No. three", "Element No. four"} second_stringlist = ["#1", "#2"]//second_stringlist ! second_stringlist <-- {"#1", "#2", "Element No. one", "Element No. three", "Element No. four"} first_stringlist = first_stringlist//second_stringlist ! first_stringlist <-- {"Element No. one", "#1", "#2", "Element No. one", "Element No. three", "Element No. four"} end program example_concatenate_operator fortran-lang-stdlib-0ede301/example/stringlist_type/example_stringlist_type_insert_at.f900000664000175000017500000000151415135654166032433 0ustar alastairalastairprogram example_insert_at use stdlib_stringlist_type, only: stringlist_type, stringlist_index_type, fidx, bidx use stdlib_string_type, only: string_type implicit none type(stringlist_type) :: stringlist type(stringlist_index_type) :: index index = fidx(1) call stringlist%insert_at(index, "Element No. one") ! stringlist <-- {"Element No. one"} index = bidx(1) call stringlist%insert_at(index, string_type("Element No. two")) ! stringlist <-- {"Element No. one", "Element No. two"} call stringlist%insert_at(fidx(2), string_type("Element No. three")) ! stringlist <-- {"Element No. one", "Element No. three", "Element No. two"} call stringlist%insert_at(bidx(1), "Element No. four") ! stringlist <-- {"Element No. one", "Element No. three", "Element No. two", "Element No. four"} end program example_insert_at fortran-lang-stdlib-0ede301/example/stringlist_type/example_stringlist_type_len.f900000664000175000017500000000074315135654166031224 0ustar alastairalastairprogram example_len use stdlib_stringlist_type, only: stringlist_type, bidx implicit none type(stringlist_type) :: stringlist integer :: output output = stringlist%len() ! output <-- 0 !> inserting 2 elements to the stringlist call stringlist%insert_at(bidx(1), "Element No. one") call stringlist%insert_at(bidx(1), "Element No. two") ! stringlist <-- {"Element No. one", "Element No. two"} print'(a)', stringlist%len() ! 2 end program example_len fortran-lang-stdlib-0ede301/example/stringlist_type/example_stringlist_type_fidx_bidx.f900000664000175000017500000000040215135654166032376 0ustar alastairalastairprogram example_fidx_bidx use stdlib_stringlist_type, only: stringlist_index_type, fidx, bidx implicit none type(stringlist_index_type) :: index index = fidx(1) ! forward index 1 index = bidx(3) ! backward index 3 end program example_fidx_bidx fortran-lang-stdlib-0ede301/example/stringlist_type/example_stringlist_type_inequality_operator.f900000664000175000017500000000166415135654166034550 0ustar alastairalastairprogram example_inequality_operator use stdlib_stringlist_type, only: stringlist_type, bidx, list_tail, operator(/=) use stdlib_string_type, only: string_type implicit none type(stringlist_type) :: stringlist type(string_type), allocatable :: stringarray(:) logical :: res !> inserting 4 elements to the stringlist call stringlist%insert_at(bidx(1), "#1") call stringlist%insert_at(list_tail, "#2") call stringlist%insert_at(bidx(1), "#3") call stringlist%insert_at(list_tail, "#4") ! stringlist <-- {"#1", "#2", "#3", "#4"} !> creating an array of 4 string_type elements stringarray = [string_type("#1"), string_type("#2"), string_type("#3"), string_type("#4")] res = (stringarray /= stringlist) ! res <-- .false. res = (stringlist /= ["#111", "#222", "#333", "#444"]) ! res <-- .true. print'(a)', stringlist /= ["#4", "#3", "#1"] ! .true. end program example_inequality_operator fortran-lang-stdlib-0ede301/example/stringlist_type/example_stringlist_type_equality_operator.f900000664000175000017500000000165015135654166034214 0ustar alastairalastairprogram example_equality_operator use stdlib_stringlist_type, only: stringlist_type, fidx, list_head, operator(==) use stdlib_string_type, only: string_type implicit none type(stringlist_type) :: stringlist type(string_type), allocatable :: stringarray(:) logical :: res !> inserting 4 elements to the stringlist call stringlist%insert_at(fidx(1), "#1") call stringlist%insert_at(list_head, "#2") call stringlist%insert_at(fidx(1), "#3") call stringlist%insert_at(list_head, "#4") ! stringlist <-- {"#4", "#3", "#2", "#1"} !> creating an array of 4 string_type elements stringarray = [string_type("#4"), string_type("#3"), string_type("#2"), string_type("#1")] res = (stringarray == stringlist) ! res <-- .true. res = (stringlist == ["#4", "#3", "#2", "#1"]) ! res <-- .true. print'(a)', stringlist == ["#4", "#3", "#1"] ! .false. end program example_equality_operator fortran-lang-stdlib-0ede301/example/stringlist_type/CMakeLists.txt0000664000175000017500000000055615135654166025632 0ustar alastairalastairADD_EXAMPLE(stringlist_type_clear) ADD_EXAMPLE(stringlist_type_concatenate_operator) ADD_EXAMPLE(stringlist_type_constructor) ADD_EXAMPLE(stringlist_type_equality_operator) ADD_EXAMPLE(stringlist_type_fidx_bidx) ADD_EXAMPLE(stringlist_type_get) ADD_EXAMPLE(stringlist_type_inequality_operator) ADD_EXAMPLE(stringlist_type_insert_at) ADD_EXAMPLE(stringlist_type_len) fortran-lang-stdlib-0ede301/example/stringlist_type/example_stringlist_type_clear.f900000664000175000017500000000107715135654166031535 0ustar alastairalastairprogram example_clear use stdlib_stringlist_type, only: stringlist_type, fidx implicit none type(stringlist_type) :: stringlist !> inserting 2 elements to the stringlist call stringlist%insert_at(fidx(1), "Element No. one") call stringlist%insert_at(fidx(1), "Element No. two") ! stringlist <-- {"Element No. two", "Element No. one"} call stringlist%clear() ! stringlist <-- { } (empty stringlist) !> inserting 1 element to the stringlist call stringlist%insert_at(fidx(1), "Element No. one") ! stringlist <-- {"Element No. one"} end program example_clear fortran-lang-stdlib-0ede301/example/stringlist_type/example_stringlist_type_get.f900000664000175000017500000000156015135654166031223 0ustar alastairalastairprogram example_get use stdlib_stringlist_type, only: stringlist_type, fidx, bidx use stdlib_string_type, only: string_type implicit none type(stringlist_type) :: stringlist type(string_type) :: output !> inserting 4 elements to the stringlist call stringlist%insert_at(fidx(1), "Element No. one") call stringlist%insert_at(fidx(1), "Element No. two") call stringlist%insert_at(fidx(1), "Element No. three") call stringlist%insert_at(fidx(1), "Element No. four") ! stringlist <-- {"Element No. four", "Element No. three", "Element No. two", "Element No. one"} output = stringlist%get(fidx(1)) ! output <-- "Element No. four" output = stringlist%get(bidx(1)) ! output <-- "Element No. one" !> accessing out of bounds index output = stringlist%get(bidx(5)) ! output <-- "" output = stringlist%get(fidx(0)) ! output <-- "" end program example_get fortran-lang-stdlib-0ede301/example/stringlist_type/example_stringlist_type_constructor.f900000664000175000017500000000073415135654166033033 0ustar alastairalastairprogram example_constructor use stdlib_stringlist_type, only: stringlist_type use stdlib_string_type, only: string_type implicit none type(stringlist_type) :: stringlist stringlist = stringlist_type() ! stringlist <-- { } (empty stringlist) stringlist = stringlist_type(["#1", "#2", "#3"]) ! stringlist <-- {"#1", "#2", "#3"} stringlist = stringlist_type([string_type("#1"), string_type("#2")]) ! stringlist <-- {"#1", "#2"} end program example_constructor fortran-lang-stdlib-0ede301/example/specialmatrices/0000775000175000017500000000000015135654166022771 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/specialmatrices/CMakeLists.txt0000664000175000017500000000015415135654166025531 0ustar alastairalastairADD_EXAMPLE(specialmatrices_dp_spmv) ADD_EXAMPLE(specialmatrices_cdp_spmv) ADD_EXAMPLE(tridiagonal_dp_type) fortran-lang-stdlib-0ede301/example/specialmatrices/example_specialmatrices_cdp_spmv.f900000664000175000017500000000160315135654166032067 0ustar alastairalastairprogram example_tridiagonal_matrix_cdp use stdlib_linalg_constants, only: dp use stdlib_specialmatrices, only: tridiagonal_cdp_type, tridiagonal, dense, spmv implicit none integer, parameter :: n = 5 type(tridiagonal_cdp_type) :: A complex(dp) :: dl(n-1), dv(n), du(n-1) complex(dp) :: x(n), y(n), y_dense(n) integer :: i complex(dp) :: alpha, beta dl = [(cmplx(i,i, dp), i=1, n - 1)] dv = [(cmplx(2*i,2*i, dp), i=1, n)] du = [(cmplx(3*i,3*i, dp), i=1, n - 1)] A = tridiagonal(dl, dv, du) x = (1.0_dp, 0.0_dp) y = (3.0_dp, -7.0_dp) y_dense = (0.0_dp, 0.0_dp) alpha = cmplx(2.0_dp, 3.0_dp) beta = cmplx(-1.0_dp, 5.0_dp) y_dense = alpha * matmul(dense(A), x) + beta * y call spmv(A, x, y, alpha, beta) print *, 'dense :', y_dense print *, 'Tridiagonal :', y end program example_tridiagonal_matrix_cdp fortran-lang-stdlib-0ede301/example/specialmatrices/example_specialmatrices_dp_spmv.f900000664000175000017500000000137215135654166031727 0ustar alastairalastairprogram example_tridiagonal_matrix use stdlib_linalg_constants, only: dp use stdlib_specialmatrices, only: tridiagonal_dp_type, tridiagonal, dense, spmv implicit none integer, parameter :: n = 5 type(tridiagonal_dp_type) :: A real(dp) :: dl(n - 1), dv(n), du(n - 1) real(dp) :: x(n), y(n), y_dense(n) integer :: i ! Create an arbitrary tridiagonal matrix. dl = [(i, i=1, n - 1)]; dv = [(2*i, i=1, n)]; du = [(3*i, i=1, n - 1)] A = tridiagonal(dl, dv, du) ! Initialize vectors. x = 1.0_dp; y = 0.0_dp; y_dense = 0.0_dp ! Perform matrix-vector products. call spmv(A, x, y) y_dense = matmul(dense(A), x) print *, 'dense :', y_dense print *, 'Tridiagonal :', y end program example_tridiagonal_matrix fortran-lang-stdlib-0ede301/example/specialmatrices/example_tridiagonal_dp_type.f900000664000175000017500000000073415135654166031051 0ustar alastairalastairprogram example_tridiagonal_matrix use stdlib_linalg_constants, only: dp use stdlib_specialmatrices implicit none integer, parameter :: n = 5 type(Tridiagonal_dp_type) :: A real(dp) :: dl(n - 1), dv(n), du(n - 1) ! Generate random tridiagonal elements. call random_number(dl) call random_number(dv) call random_number(du) ! Create the corresponding Tridiagonal matrix. A = Tridiagonal(dl, dv, du) end program example_tridiagonal_matrix fortran-lang-stdlib-0ede301/example/math/0000775000175000017500000000000015135654166020552 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/math/example_gcd.f900000664000175000017500000000023515135654166023342 0ustar alastairalastairprogram example_gcd use stdlib_math, only: gcd implicit none integer :: a, b, c a = 48 b = 18 c = gcd(a, b) ! returns 6 end program example_gcd fortran-lang-stdlib-0ede301/example/math/example_linspace_complex.f900000664000175000017500000000050015135654166026125 0ustar alastairalastairprogram example_linspace_complex use stdlib_math, only: linspace use stdlib_kinds, only: dp implicit none complex(dp) :: start = cmplx(10.0_dp, 5.0_dp, kind=dp) complex(dp) :: end = cmplx(-10.0_dp, 15.0_dp, kind=dp) complex(dp) :: z(11) z = linspace(start, end, 11) end program example_linspace_complex fortran-lang-stdlib-0ede301/example/math/example_logspace_complex.f900000664000175000017500000000055015135654166026131 0ustar alastairalastairprogram example_logspace_complex use stdlib_math, only: logspace use stdlib_kinds, only: dp implicit none complex(dp) :: start = (10.0_dp, 5.0_dp) complex(dp) :: end = (-10.0_dp, 15.0_dp) complex(dp) :: z(11) ! Complex values raised to complex powers results in complex values z = logspace(start, end, 11) end program example_logspace_complex fortran-lang-stdlib-0ede301/example/math/example_logspace_int.f900000664000175000017500000000054215135654166025255 0ustar alastairalastairprogram example_logspace_int use stdlib_math, only: logspace use stdlib_kinds, only: dp implicit none integer, parameter :: start = 10 integer, parameter :: end = 23 integer, parameter :: n = 15 real(dp) :: r(n) ! Integer values raised to real powers results in real values r = logspace(start, end, n) end program example_logspace_int fortran-lang-stdlib-0ede301/example/math/example_diff.f900000664000175000017500000000115115135654166023513 0ustar alastairalastairprogram example_diff use stdlib_math, only: diff implicit none integer :: i(7) = [1, 1, 2, 3, 5, 8, 13] real :: x(6) = [0, 5, 15, 30, 50, 75] integer :: A(3, 3) = reshape([1, 7, 17, 3, 11, 19, 5, 13, 23], [3, 3]) integer :: Y(3, 2) print *, diff(i) ! [0, 1, 1, 2, 3, 5] print *, diff(x, 2) ! [5.0, 5.0, 5.0, 5.0] Y = diff(A, n=1, dim=2) print *, Y(1, :) ! [2, 2] print *, Y(2, :) ! [4, 2] print *, Y(3, :) ! [2, 4] print *, diff(i, prepend=[0]) ! [1, 0, 1, 1, 2, 3, 5] print *, diff(i, append=[21]) ! [0, 1, 1, 2, 3, 5, 8] end program example_diff fortran-lang-stdlib-0ede301/example/math/example_math_deg2rad.f900000664000175000017500000000035615135654166025132 0ustar alastairalastairprogram example_math_deg2rad use stdlib_math, only: deg2rad implicit none print *, deg2rad(0.0) ! 0.0 print *, deg2rad(90.0) ! 1.57508 print *, deg2rad(-180.0) ! -3.1416 end program example_math_deg2rad fortran-lang-stdlib-0ede301/example/math/example_math_rad2deg.f900000664000175000017500000000044615135654166025132 0ustar alastairalastairprogram example_math_rad2deg use stdlib_math, only: rad2deg use stdlib_constants, only: PI_sp implicit none print *, rad2deg(0.0) ! 0.0 print *, rad2deg(PI_sp / 2.0) ! 90.0 print *, rad2deg(-PI_sp) ! -3.1416 end program example_math_rad2deg fortran-lang-stdlib-0ede301/example/math/example_clip_integer.f900000664000175000017500000000054515135654166025255 0ustar alastairalastairprogram example_clip_integer use stdlib_math, only: clip use stdlib_kinds, only: int32 implicit none integer(int32) :: x integer(int32) :: xmin integer(int32) :: xmax integer(int32) :: clipped_value xmin = -5_int32 xmax = 5_int32 x = 12_int32 clipped_value = clip(x, xmin, xmax) ! clipped_value <- 5 end program example_clip_integer fortran-lang-stdlib-0ede301/example/math/example_clip_real.f900000664000175000017500000000051715135654166024542 0ustar alastairalastairprogram example_clip_real use stdlib_math, only: clip use stdlib_kinds, only: sp implicit none real(sp) :: x real(sp) :: xmin real(sp) :: xmax real(sp) :: clipped_value xmin = -5.769_sp xmax = 3.025_sp x = 3.025_sp clipped_value = clip(x, xmin, xmax) ! clipped_value <- 3.02500010 end program example_clip_real fortran-lang-stdlib-0ede301/example/math/CMakeLists.txt0000664000175000017500000000074115135654166023314 0ustar alastairalastairADD_EXAMPLE(clip_integer) ADD_EXAMPLE(clip_real) ADD_EXAMPLE(diff) ADD_EXAMPLE(gcd) ADD_EXAMPLE(linspace_complex) ADD_EXAMPLE(linspace_int16) ADD_EXAMPLE(logspace_complex) ADD_EXAMPLE(logspace_int) ADD_EXAMPLE(logspace_rstart_cbase) ADD_EXAMPLE(math_all_close) ADD_EXAMPLE(math_arange) ADD_EXAMPLE(math_argd) ADD_EXAMPLE(math_arg) ADD_EXAMPLE(math_argpi) ADD_EXAMPLE(math_deg2rad) ADD_EXAMPLE(math_rad2deg) ADD_EXAMPLE(math_is_close) ADD_EXAMPLEPP(math_swap) ADD_EXAMPLE(meshgrid) fortran-lang-stdlib-0ede301/example/math/example_math_argd.f900000664000175000017500000000055115135654166024534 0ustar alastairalastairprogram example_math_argd use stdlib_math, only: argd implicit none print *, argd((0.0, 0.0)) ! 0.0° print *, argd((3.0, 4.0)) ! 53.1° print *, argd(2.0*exp((0.0, 0.5))) ! 28.64° print *, argd([(0.0, 1.0), (1.0, 0.0), (0.0, -1.0), (-1.0, 0.0)]) ! [90°, 0°, -90°, 180°] end program example_math_argd fortran-lang-stdlib-0ede301/example/math/example_math_all_close.f900000664000175000017500000000055015135654166025553 0ustar alastairalastairprogram example_math_all_close use stdlib_math, only: all_close implicit none real :: y, NAN complex :: z(4, 4) y = -3 NAN = sqrt(y) z = (1.0, 1.0) print *, all_close(z + cmplx(1.0e-11, 1.0e-11), z) ! T print *, NAN, all_close([NAN], [NAN]), all_close([NAN], [NAN], equal_nan=.true.) ! NAN, F, T end program example_math_all_close fortran-lang-stdlib-0ede301/example/math/example_logspace_rstart_cbase.f900000664000175000017500000000063415135654166027141 0ustar alastairalastairprogram example_logspace_rstart_cbase use stdlib_math, only: logspace use stdlib_kinds, only: dp implicit none real(dp) :: start = 0.0_dp real(dp) :: end = 3.0_dp integer, parameter :: n = 4 complex(dp) :: base = (0.0_dp, 1.0_dp) complex(dp) :: z(n) ! complex values raised to real powers result in complex values z = logspace(start, end, n, base) end program example_logspace_rstart_cbase fortran-lang-stdlib-0ede301/example/math/example_meshgrid.f900000664000175000017500000000170515135654166024412 0ustar alastairalastairprogram example_meshgrid use stdlib_math, only: meshgrid, linspace, stdlib_meshgrid_ij use stdlib_kinds, only: sp implicit none integer, parameter :: nx = 3, ny = 2 real(sp) :: x(nx), y(ny), & xm_cart(ny, nx), ym_cart(ny, nx), & xm_mat(nx, ny), ym_mat(nx, ny) x = linspace(0_sp, 1_sp, nx) y = linspace(0_sp, 1_sp, ny) call meshgrid(x, y, xm_cart, ym_cart) print *, "xm_cart = " call print_2d_array(xm_cart) print *, "ym_cart = " call print_2d_array(ym_cart) call meshgrid(x, y, xm_mat, ym_mat, indexing=stdlib_meshgrid_ij) print *, "xm_mat = " call print_2d_array(xm_mat) print *, "ym_mat = " call print_2d_array(ym_mat) contains subroutine print_2d_array(array) real(sp), intent(in) :: array(:, :) integer :: i do i = 1, size(array, dim=1) print *, array(i, :) end do end subroutine end program example_meshgrid fortran-lang-stdlib-0ede301/example/math/example_math_arange.f900000664000175000017500000000143415135654166025055 0ustar alastairalastairprogram example_math_arange use stdlib_math, only: arange implicit none print *, arange(3) ! [1,2,3] print *, arange(-1) ! [1,0,-1] print *, arange(0, 2) ! [0,1,2] print *, arange(1, -1) ! [1,0,-1] print *, arange(0, 2, 2) ! [0,2] print *, arange(3.0) ! [1.0,2.0,3.0] print *, arange(0.0, 5.0) ! [0.0,1.0,2.0,3.0,4.0,5.0] print *, arange(0.0, 6.0, 2.5) ! [0.0,2.5,5.0] print *, (1.0, 1.0)*arange(3) ! [(1.0,1.0),(2.0,2.0),[3.0,3.0]] print *, arange(0.0, 2.0, -2.0) ! [0.0,2.0]. Not recommended: `step` argument is negative! print *, arange(0.0, 2.0, 0.0) ! [0.0,1.0,2.0]. Not recommended: `step` argument is zero! end program example_math_arange fortran-lang-stdlib-0ede301/example/math/example_math_swap.F900000664000175000017500000000206515135654166024533 0ustar alastairalastair#include "macros.inc" program example_math_swap use stdlib_math, only: swap implicit none block integer :: x, y x = 9 y = 18 call swap(x,y) end block block real :: x, y x = 4.0 y = 8.0 call swap(x,y) end block block real :: x(3), y(3) x = [1.0,2.0,3.0] y = [4.0,5.0,6.0] call swap(x,y) end block block character(4) :: x character(6) :: y x = 'abcd' y = 'efghij' call swap(x,y) ! x=efgh, y=abcd x = 'abcd' y = 'efghij' call swap(x,y(1:4)) ! x=efgh, y=abcdij end block block use stdlib_string_type type(string_type) :: x, y x = 'abcde' y = 'fghij' call swap(x,y) end block #if STDLIB_BITSETS == 1 block use stdlib_bitsets type(bitset_64) :: x, y call x%from_string('0000') call y%from_string('1111') call swap(x,y) end block #endif end program example_math_swap fortran-lang-stdlib-0ede301/example/math/example_linspace_int16.f900000664000175000017500000000042615135654166025426 0ustar alastairalastairprogram example_linspace_int16 use stdlib_math, only: linspace use stdlib_kinds, only: int16, dp implicit none integer(int16) :: start = 10_int16 integer(int16) :: end = 23_int16 real(dp) :: r(15) r = linspace(start, end, 15) end program example_linspace_int16 fortran-lang-stdlib-0ede301/example/math/example_math_arg.f900000664000175000017500000000053015135654166024365 0ustar alastairalastairprogram example_math_arg use stdlib_math, only: arg implicit none print *, arg((0.0, 0.0)) ! 0.0 print *, arg((3.0, 4.0)) ! 0.927 print *, arg(2.0*exp((0.0, 0.5))) ! 0.5 print *, arg([(0.0, 1.0), (1.0, 0.0), (0.0, -1.0), (-1.0, 0.0)]) ! [π/2, 0.0, -π/2, π] end program example_math_arg fortran-lang-stdlib-0ede301/example/math/example_math_argpi.f900000664000175000017500000000054715135654166024726 0ustar alastairalastairprogram example_math_argpi use stdlib_math, only: argpi implicit none print *, argpi((0.0, 0.0)) ! 0.0 print *, argpi((3.0, 4.0)) ! 0.295 print *, argpi(2.0*exp((0.0, 0.5))) ! 0.159 print *, argpi([(0.0, 1.0), (1.0, 0.0), (0.0, -1.0), (-1.0, 0.0)]) ! [0.5, 0.0, -0.5, 1.0] end program example_math_argpi fortran-lang-stdlib-0ede301/example/math/example_math_is_close.f900000664000175000017500000000070215135654166025415 0ustar alastairalastairprogram example_math_is_close use stdlib_math, only: is_close implicit none real :: x(2) = [1, 2], y, NAN y = -3 NAN = sqrt(y) print *, is_close(x, [real :: 1, 2.1]) ! [T, F] print *, is_close(2.0, 2.1, abs_tol=0.1) ! T print *, NAN, is_close(2.0, NAN), is_close(2.0, NAN, equal_nan=.true.) ! NAN, F, F print *, is_close(NAN, NAN), is_close(NAN, NAN, equal_nan=.true.) ! F, T end program example_math_is_close fortran-lang-stdlib-0ede301/example/CMakeLists.txt0000664000175000017500000000343515135654166022366 0ustar alastairalastairmacro(ADD_EXAMPLE name) add_executable(example_${name} example_${name}.f90) target_link_libraries(example_${name} "${PROJECT_NAME}") add_test(NAME ${name} COMMAND $ ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endmacro(ADD_EXAMPLE) macro(ADD_EXAMPLEPP name) add_executable(example_${name} example_${name}.F90) target_link_libraries(example_${name} "${PROJECT_NAME}") add_test(NAME ${name} COMMAND $ ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endmacro(ADD_EXAMPLEPP) if (STDLIB_ANSI) add_subdirectory(ansi) endif() add_subdirectory(array) add_subdirectory(ascii) if (STDLIB_BITSETS) add_subdirectory(bitsets) endif() add_subdirectory(constants) add_subdirectory(error) if (STDLIB_HASHMAPS) add_subdirectory(hashmaps) endif() add_subdirectory(hash_procedures) add_subdirectory(intrinsics) if (STDLIB_IO) add_subdirectory(io) endif() add_subdirectory(linalg) if (STDLIB_LOGGER) add_subdirectory(logger) endif() add_subdirectory(math) add_subdirectory(optval) if (STDLIB_QUADRATURE) add_subdirectory(quadrature) endif() add_subdirectory(selection) add_subdirectory(sorting) add_subdirectory(specialfunctions_gamma) if (STDLIB_SPECIALMATRICES) add_subdirectory(specialmatrices) endif() if (STDLIB_STATS) add_subdirectory(stats) add_subdirectory(stats_distribution_exponential) add_subdirectory(stats_distribution_normal) add_subdirectory(stats_distribution_uniform) add_subdirectory(random) endif() if (STDLIB_STRINGLIST) add_subdirectory(stringlist_type) endif() add_subdirectory(strings) add_subdirectory(string_type) if (STDLIB_SYSTEM) add_subdirectory(system) endif() add_subdirectory(version) fortran-lang-stdlib-0ede301/example/specialfunctions_gamma/0000775000175000017500000000000015135654166024334 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/specialfunctions_gamma/example_gamma_p.f900000664000175000017500000000026315135654166027771 0ustar alastairalastairprogram example_gamma_p use stdlib_specialfunctions_gamma, only: rgp => regularized_gamma_p implicit none print *, rgp(3.0, 5.0) ! 0.875347972 end program example_gamma_p fortran-lang-stdlib-0ede301/example/specialfunctions_gamma/CMakeLists.txt0000664000175000017500000000023115135654166027070 0ustar alastairalastairADD_EXAMPLE(gamma) ADD_EXAMPLE(gamma_p) ADD_EXAMPLE(gamma_q) ADD_EXAMPLE(ligamma) ADD_EXAMPLE(log_factorial) ADD_EXAMPLE(log_gamma) ADD_EXAMPLE(uigamma) fortran-lang-stdlib-0ede301/example/specialfunctions_gamma/example_uigamma.f900000664000175000017500000000033615135654166030011 0ustar alastairalastairprogram example_uigamma use stdlib_specialfunctions_gamma, only: uig => upper_incomplete_gamma implicit none print *, uig(3, -5.0) !2523.02295 print *, uig(2.3, 5.0) !6.95552528E-02 end program example_uigamma fortran-lang-stdlib-0ede301/example/specialfunctions_gamma/example_gamma.f900000664000175000017500000000114615135654166027453 0ustar alastairalastairprogram example_gamma use stdlib_kinds, only: sp, dp, int64 use stdlib_specialfunctions_gamma, only: gamma implicit none integer :: i integer(int64) :: n real :: x real(dp) :: y complex(sp) :: z i = 10 n = 15_int64 x = 2.5 y = 4.3_dp z = (2.3, 0.6) print *, gamma(i) !integer gives exact result ! 362880 print *, gamma(n) ! 87178291200 print *, gamma(x) ! intrinsic function call ! 1.32934034 print *, gamma(y) ! intrinsic function call ! 8.8553433604540341 print *, gamma(z) ! (0.988054395, 0.383354813) end program example_gamma fortran-lang-stdlib-0ede301/example/specialfunctions_gamma/example_ligamma.f900000664000175000017500000000041315135654166027774 0ustar alastairalastairprogram example_ligamma use stdlib_specialfunctions_gamma, only: lig => lower_incomplete_gamma implicit none integer :: p real :: p1 p = 3 p1 = 2.3 print *, lig(p, -5.0) ! -2521.02417 print *, lig(p1, 5.0) ! 1.09715652 end program example_ligamma fortran-lang-stdlib-0ede301/example/specialfunctions_gamma/example_log_factorial.f900000664000175000017500000000041615135654166031175 0ustar alastairalastairprogram example_log_factorial use stdlib_kinds, only: int64 use stdlib_specialfunctions_gamma, only: lf => log_factorial implicit none integer :: n n = 10 print *, lf(n) ! 15.1044130 print *, lf(35_int64) ! 92.1361771 end program example_log_factorial fortran-lang-stdlib-0ede301/example/specialfunctions_gamma/example_gamma_q.f900000664000175000017500000000026315135654166027772 0ustar alastairalastairprogram example_gamma_q use stdlib_specialfunctions_gamma, only: rgq => regularized_gamma_q implicit none print *, rgq(3.0, 5.0) ! 0.124652028 end program example_gamma_q fortran-lang-stdlib-0ede301/example/specialfunctions_gamma/example_log_gamma.f900000664000175000017500000000106615135654166030315 0ustar alastairalastairprogram example_log_gamma use stdlib_kinds, only: sp, dp use stdlib_specialfunctions_gamma, only: log_gamma implicit none integer :: i real :: x real(dp) :: y complex(sp) :: z i = 10 x = 8.76 y = x z = (5.345, -3.467) print *, log_gamma(i) !default single precision output !12.8018274 print *, log_gamma(x) !intrinsic function call !10.0942659 print *, log_gamma(y) !intrinsic function call !10.094265528673880 print *, log_gamma(z) !same kind as input !(2.56165648, -5.73382425) end program example_log_gamma fortran-lang-stdlib-0ede301/example/constants/0000775000175000017500000000000015135654166021635 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/constants/example_constants.f900000664000175000017500000000205015135654166025701 0ustar alastairalastairprogram example_constants use stdlib_constants, only: c, pi=>PI_dp use stdlib_codata, only: alpha=>ALPHA_PARTICLE_ELECTRON_MASS_RATIO use stdlib_codata_type, only : to_real use stdlib_kinds, only: dp, sp ! Use most common physical constants defined as double precision reals print *, "speed of light in vacuum= ", c ! Use of mathematical constants such as PI print *, "PI as double precision real= ", pi ! Use codata_constant type for evaluating the value to the desired precision print *, "Value of alpha... evaluated to double precision=", alpha%to_real(1.0_dp) print *, "Uncertainty of alpha... evaluated to double precision=", alpha%to_real(1.0_sp, .true.) print *, "Value of alpha... evaluated to single precision=", alpha%to_real(1.0_sp) ! Convert a codata constant to a real print *, "Value of the alpha... evaluated to double precision=", to_real(alpha, 1.0_dp) ! Print out codata constant attributes: name, value, uncertainty and unit call alpha%print() end program example_constants fortran-lang-stdlib-0ede301/example/constants/CMakeLists.txt0000664000175000017500000000002715135654166024374 0ustar alastairalastairADD_EXAMPLE(constants) fortran-lang-stdlib-0ede301/example/ascii/0000775000175000017500000000000015135654166020711 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/ascii/example_ascii_to_sentence.f900000664000175000017500000000042115135654166026417 0ustar alastairalastairprogram example_to_sentence use stdlib_ascii, only: to_sentence implicit none print *, to_sentence("hello!") ! returns "Hello!" print *, to_sentence("'enquoted'") ! returns "'Enquoted'" print *, to_sentence("1st") ! returns "1st" end program example_to_sentence fortran-lang-stdlib-0ede301/example/ascii/example_ascii_to_lower.f900000664000175000017500000000023515135654166025746 0ustar alastairalastairprogram example_to_lower use stdlib_ascii, only: to_lower implicit none print'(a)', to_lower("HELLo!") ! returns "hello!" end program example_to_lower fortran-lang-stdlib-0ede301/example/ascii/CMakeLists.txt0000664000175000017500000000021615135654166023450 0ustar alastairalastairADD_EXAMPLE(ascii_reverse) ADD_EXAMPLE(ascii_to_lower) ADD_EXAMPLE(ascii_to_sentence) ADD_EXAMPLE(ascii_to_title) ADD_EXAMPLE(ascii_to_upper) fortran-lang-stdlib-0ede301/example/ascii/example_ascii_reverse.f900000664000175000017500000000024715135654166025572 0ustar alastairalastairprogram example_reverse use stdlib_ascii, only: reverse implicit none print'(a)', reverse("Hello, World!") ! returns "!dlroW ,olleH" end program example_reverse fortran-lang-stdlib-0ede301/example/ascii/example_ascii_to_title.f900000664000175000017500000000041315135654166025735 0ustar alastairalastairprogram example_to_title use stdlib_ascii, only: to_title implicit none print *, to_title("hello there!") ! returns "Hello There!" print *, to_title("'enquoted'") ! returns "'Enquoted'" print *, to_title("1st") ! returns "1st" end program example_to_title fortran-lang-stdlib-0ede301/example/ascii/example_ascii_to_upper.f900000664000175000017500000000023515135654166025751 0ustar alastairalastairprogram example_to_upper use stdlib_ascii, only: to_upper implicit none print'(a)', to_upper("hello!") ! returns "HELLO!" end program example_to_upper fortran-lang-stdlib-0ede301/example/hashmaps/0000775000175000017500000000000015135654166021425 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_copy_key.f900000664000175000017500000000061315135654166027166 0ustar alastairalastairprogram example_copy_key use stdlib_hashmap_wrappers, only: & copy_key, operator(==), key_type, set use iso_fortran_env, only: int8 implicit none integer(int8) :: i, value(15) type(key_type) :: old_key, new_key value = [(i, i=1, 15)] call set(old_key, value) call copy_key(old_key, new_key) print *, "old_key == new_key = ", old_key == new_key end program example_copy_key fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_num_slots.f900000664000175000017500000000046315135654166027372 0ustar alastairalastairprogram example_num_slots use stdlib_hashmaps, only: chaining_hashmap_type, int_index implicit none type(chaining_hashmap_type) :: map integer(int_index) :: initial_slots call map%init() initial_slots = map%num_slots() print *, "Initial slots = ", initial_slots end program example_num_slots fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_slots_bits.f900000664000175000017500000000041115135654166027525 0ustar alastairalastairprogram example_slots_bits use stdlib_hashmaps, only: chaining_hashmap_type implicit none type(chaining_hashmap_type) :: map integer :: bits call map%init() bits = map%slots_bits() print *, "Initial slot bits = ", bits end program example_slots_bits fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_probes.f900000664000175000017500000000040715135654166026637 0ustar alastairalastairprogram example_probes use stdlib_hashmaps, only: chaining_hashmap_type implicit none type(chaining_hashmap_type) :: map integer :: nprobes call map%init() nprobes = map%map_probes() print *, "Initial probes = ", nprobes end program example_probes fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_fnv_1_hasher.f900000664000175000017500000000062315135654166027710 0ustar alastairalastairprogram example_fnv_1_hasher use stdlib_hashmap_wrappers, only: fnv_1_hasher, key_type, set use iso_fortran_env, only: int8, int32 implicit none integer(int8), allocatable :: array1(:) integer(int32) :: hash type(key_type) :: key array1 = [5_int8, 4_int8, 3_int8, 1_int8, 10_int8, 4_int8] call set(key, array1) hash = fnv_1_hasher(key) print *, hash end program example_fnv_1_hasher fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_get_all_keys.f900000664000175000017500000000177215135654166030015 0ustar alastairalastairprogram example_hashmaps_get_all_keys use stdlib_kinds, only: int32 use stdlib_hashmaps, only: chaining_hashmap_type use stdlib_hashmap_wrappers, only: get, key_type, set implicit none type(chaining_hashmap_type) :: map type(key_type) :: key type(key_type), allocatable :: keys(:) integer(int32) :: i character(:), allocatable :: str ! adding key-value pairs to the map call set(key, "initial key") call map%map_entry(key, "value 1") call set(key, "second key") call map%map_entry(key, "value 2") call set(key, "last key") call map%map_entry(key, "value 3") ! getting all the keys in the map call map%get_all_keys(keys) print '("Number of keys in the hashmap = ", I0)', size(keys) !Number of keys in the hashmap = 3 do i = 1, size(keys) call get( keys(i), str ) print '("Value of key ", I0, " = ", A)', i, str end do !Value of key 1 = initial key !Value of key 2 = second key !Value of key 3 = last key end program example_hashmaps_get_all_keys fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_seeded_nmhash32x_hasher.f900000664000175000017500000000070215135654166032021 0ustar alastairalastairprogram example_seeded_nmhash32x_hasher use stdlib_kinds, only: int8, int32 use stdlib_hashmap_wrappers, only: & seeded_nmhash32x_hasher, key_type, set implicit none integer(int8), allocatable :: array1(:) integer(int32) :: hash type(key_type) :: key array1 = [5_int8, 4_int8, 3_int8, 1_int8, 10_int8, 4_int8] call set(key, array1) hash = seeded_nmhash32x_hasher(key) print *, hash end program example_seeded_nmhash32x_hasher fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_hasher_fun.f900000664000175000017500000000076015135654166027471 0ustar alastairalastairprogram example_hasher_fun use stdlib_hashmap_wrappers, only: fnv_1a_hasher, hasher_fun, set, key_type use stdlib_kinds, only: int8, int32 implicit none procedure(hasher_fun), pointer :: hasher_pointer integer(int8), allocatable :: array1(:) integer(int32) :: hash type(key_type) :: key hasher_pointer => fnv_1a_hasher array1 = [5_int8, 4_int8, 3_int8, 1_int8, 10_int8, 4_int8] call set(key, array1) hash = hasher_pointer(key) print *, hash end program example_hasher_fun fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_seeded_water_hasher.f900000664000175000017500000000066515135654166031340 0ustar alastairalastairprogram example_seeded_water_hasher use stdlib_hashmap_wrappers, only: & seeded_water_hasher, key_type, set use iso_fortran_env, only: int8, int32 implicit none integer(int8), allocatable :: array1(:) integer(int32) :: hash type(key_type) :: key array1 = [5_int8, 4_int8, 3_int8, 1_int8, 10_int8, 4_int8] call set(key, array1) hash = seeded_water_hasher(key) print *, hash end program example_seeded_water_hasher fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_entries.f900000664000175000017500000000045515135654166027021 0ustar alastairalastairprogram example_entries use stdlib_hashmaps, only: open_hashmap_type, int_index implicit none type(open_hashmap_type) :: map integer(int_index) :: initial_entries call map%init() initial_entries = map%entries() print *, "INITIAL_ENTRIES = ", initial_entries end program example_entries fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_fnv_1a_hasher.f900000664000175000017500000000063515135654166030054 0ustar alastairalastairprogram example_fnv_1a_hasher use stdlib_hashmap_wrappers, only: & fnv_1a_hasher, key_type, set use iso_fortran_env, only: int8, int32 implicit none integer(int8), allocatable :: array1(:) integer(int32) :: hash type(key_type) :: key array1 = [5_int8, 4_int8, 3_int8, 1_int8, 10_int8, 4_int8] call set(key, array1) hash = fnv_1a_hasher(key) print *, hash end program example_fnv_1a_hasher fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_set_other_data.f900000664000175000017500000000207615135654166030336 0ustar alastairalastairprogram example_set_other_data use stdlib_kinds, only: int8 use stdlib_hashmaps, only: open_hashmap_type, chaining_hashmap_type use stdlib_hashmap_wrappers, only: key_type, set implicit none logical :: exists type(chaining_hashmap_type) :: map class(*), allocatable :: data type(key_type) :: key ! Initialize hashmap with 2^10 slots. ! Hashmap will dynamically increase size if needed. call map%init(slots_bits=10) call set(key, [5, 7, 4, 13]) call map%map_entry(key, 'A value') call map%set_other_data(key, 'Another value', exists) print *, 'The entry to have its other data replaced exists = ', exists call map%get_other_data(key, data, exists) print *, 'Get_other_data was successful = ', exists ! Hashmaps return an unlimited polymorphic type as other. ! Must be included in a select type operation to do further operations. select type (data) type is (character(*)) print *, 'Value is = ', data class default print *, 'Invalid data type in other' end select end program example_set_other_data fortran-lang-stdlib-0ede301/example/hashmaps/CMakeLists.txt0000664000175000017500000000153115135654166024165 0ustar alastairalastairADD_EXAMPLE(hashmaps_calls) ADD_EXAMPLE(hashmaps_copy_key) ADD_EXAMPLE(hashmaps_entries) ADD_EXAMPLE(hashmaps_equal_keys) ADD_EXAMPLE(hashmaps_fnv_1a_hasher) ADD_EXAMPLE(hashmaps_fnv_1_hasher) ADD_EXAMPLE(hashmaps_free_key) ADD_EXAMPLE(hashmaps_get) ADD_EXAMPLE(hashmaps_get_all_keys) ADD_EXAMPLE(hashmaps_get_other_data) ADD_EXAMPLE(hashmaps_hasher_fun) ADD_EXAMPLE(hashmaps_init) ADD_EXAMPLE(hashmaps_key_test) ADD_EXAMPLE(hashmaps_loading) ADD_EXAMPLE(hashmaps_map_entry) ADD_EXAMPLE(hashmaps_num_slots) ADD_EXAMPLE(hashmaps_probes) ADD_EXAMPLE(hashmaps_rehash) ADD_EXAMPLE(hashmaps_remove) ADD_EXAMPLE(hashmaps_seeded_nmhash32_hasher) ADD_EXAMPLE(hashmaps_seeded_nmhash32x_hasher) ADD_EXAMPLE(hashmaps_seeded_water_hasher) ADD_EXAMPLE(hashmaps_set) ADD_EXAMPLE(hashmaps_set_other_data) ADD_EXAMPLE(hashmaps_slots_bits) ADD_EXAMPLE(hashmaps_total_depth) fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_free_key.f900000664000175000017500000000055115135654166027136 0ustar alastairalastairprogram example_free_key use stdlib_hashmap_wrappers, only: & copy_key, free_key, key_type, set use iso_fortran_env, only: int8 implicit none integer(int8) :: i, value(15) type(key_type) :: old_key, new_key value = [(i, i=1, 15)] call set(old_key, value) call copy_key(old_key, new_key) call free_key(old_key) end program example_free_key fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_calls.f900000664000175000017500000000044715135654166026447 0ustar alastairalastairprogram example_calls use stdlib_hashmaps, only: chaining_hashmap_type, int_calls implicit none type(chaining_hashmap_type) :: map integer(int_calls) :: initial_calls call map%init() initial_calls = map%calls() print *, "INITIAL_CALLS = ", initial_calls end program example_calls fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_rehash.f900000664000175000017500000000071715135654166026623 0ustar alastairalastairprogram example_rehash use stdlib_kinds, only: int8 use stdlib_hashmaps, only: open_hashmap_type use stdlib_hashmap_wrappers, only: fnv_1a_hasher, & key_type, set implicit none type(open_hashmap_type) :: map type(key_type) :: key call map%init(slots_bits=10) call set(key, [5_int8, 7_int8, 4_int8, 13_int8]) call map%map_entry(key, 'A value') call map%rehash(fnv_1a_hasher) end program example_rehash fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_init.f900000664000175000017500000000230415135654166026306 0ustar alastairalastairprogram example_init use stdlib_hashmaps, only: chaining_hashmap_type, open_hashmap_type use stdlib_hashmap_wrappers, only: fnv_1_hasher implicit none type(chaining_hashmap_type) :: map logical :: present !If default values are used, then init can be typically be skipped as the first map_entry call will initialize the map using default values. call map%map_entry('key', 'value') call map%key_test('key', present) print *, "Key exists without explicit init call = ", present ! Init can be called to clear all items in a map. call map%init() call map%key_test('key', present) print *, "Key exists after re-initalization = ", present ! User can optional specify hasher type and slots_bits instead of using default values. ! Number of slots in the hashmap will initially equal 2**slots_bits. ! The hashmap will automatically re-size as needed; however for better performance, a rule of thumb is to size so that number of slots is ~2X expected number of entries. ! In this example with slots_bits=10, there will initially be 1024 slots in the map. call map%init(hasher=fnv_1_hasher, slots_bits=10) call map%map_entry('key', 'value') end program example_init fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_seeded_nmhash32_hasher.f900000664000175000017500000000070115135654166031630 0ustar alastairalastairprogram example_seeded_nmhash32_hasher use stdlib_hashmap_wrappers, only: & seeded_nmhash32_hasher, key_type, set use iso_fortran_env, only: int8, int32 implicit none integer(int8), allocatable :: array1(:) integer(int32) :: hash type(key_type) :: key array1 = [5_int8, 4_int8, 3_int8, 1_int8, 10_int8, 4_int8] call set(key, array1) hash = seeded_nmhash32_hasher(key) print *, hash end program example_seeded_nmhash32_hasher fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_set.f900000664000175000017500000000064415135654166026143 0ustar alastairalastairprogram example_set use stdlib_hashmap_wrappers, only: & get, key_type, set use iso_fortran_env, only: int8 implicit none integer(int8), allocatable :: value(:), result(:) type(key_type) :: key integer(int8) :: i allocate (value(1:15)) do i = 1, 15 value(i) = i end do call set(key, value) call get(key, result) print *, 'RESULT == VALUE = ', all(value == result) end program example_set fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_total_depth.f900000664000175000017500000000047715135654166027663 0ustar alastairalastairprogram example_total_depth use stdlib_hashmaps, only: chaining_hashmap_type, int_depth implicit none type(chaining_hashmap_type) :: map integer(int_depth) :: initial_depth call map%init() initial_depth = map%total_depth() print *, "Initial total depth = ", initial_depth end program example_total_depth fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_loading.f900000664000175000017500000000036615135654166026766 0ustar alastairalastairprogram example_loading use stdlib_hashmaps, only: open_hashmap_type implicit none type(open_hashmap_type) :: map real :: ratio call map%init() ratio = map%loading() print *, "Initial loading = ", ratio end program example_loading fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_get_other_data.f900000664000175000017500000000605315135654166030321 0ustar alastairalastairprogram example_get_other_data use stdlib_kinds, only: int8, int64 use stdlib_hashmaps, only: chaining_hashmap_type, int_index use stdlib_hashmap_wrappers, only: key_type, set implicit none logical :: conflict type(key_type) :: key type(chaining_hashmap_type) :: map type dummy_type integer :: value(4) end type dummy_type type(dummy_type) :: dummy class(*), allocatable :: data integer(int8), allocatable :: key_array(:) integer :: int_scalar ! Hashmap functions are setup to store scalar value types (other). Use a dervied ! type wrapper to store arrays. dummy%value = [4, 3, 2, 1] ! Explicitly set key type using set function call set(key, [0, 1]) call map%map_entry(key, dummy, conflict) if (.not. conflict) then call map%get_other_data(key, data) else error stop 'Key is already present in the map.' end if ! Get_other_data returns data as an unlimited polymorphic scalar. ! To use this type in other operations, there must be a select type operation. select type (data) type is (dummy_type) print *, 'Other data % value = ', data%value class default print *, 'Invalid data type in other' end select ! Also can use map_entry and get_other_data generic key interfaces. ! This is an exmple with integer arrays. call map%map_entry( [2,3], dummy, conflict) if (.not. conflict) then call map%get_other_data( [2,3], data) else error stop 'Key is already present in the map.' end if select type (data) type is (dummy_type) print *, 'Other data % value = ', data%value class default print *, 'Invalid data type in other' end select ! Integer scalar keys need to be passed as an array. int_scalar = 2 call map%map_entry( [int_scalar], dummy, conflict) if (.not. conflict) then call map%get_other_data( [int_scalar], data) else error stop 'Key is already present in the map.' end if select type (data) type is (dummy_type) print *, 'Other data % value = ', data%value class default print *, 'Invalid data type in other' end select ! Example using character type key interface call map%map_entry( 'key_string', dummy, conflict) if (.not. conflict) then call map%get_other_data( 'key_string', data) else error stop 'Key is already present in the map.' end if select type (data) type is (dummy_type) print *, 'Other data % value = ', data%value class default print *, 'Invalid data type in other' end select ! Transfer to int8 arrays to generate key for unsupported types. key_array = transfer( [0_int64, 1_int64], [0_int8] ) call map%map_entry( key_array, dummy, conflict) if (.not. conflict) then call map%get_other_data( key_array, data) else error stop 'Key is already present in the map.' end if select type (data) type is (dummy_type) print *, 'Other data % value = ', data%value class default print *, 'Invalid data type in other' end select end program example_get_other_data fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_equal_keys.f900000664000175000017500000000063715135654166027514 0ustar alastairalastairprogram example_equal_keys use stdlib_hashmap_wrappers, only: & copy_key, operator(==), key_type, set use iso_fortran_env, only: int8 implicit none integer(int8) :: i, value(15) type(key_type) :: old_key, new_key do i = 1, 15 value(i) = i end do call set(old_key, value) call copy_key(old_key, new_key) print *, "old_key == new_key = ", old_key == new_key end program example_equal_keys fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_key_test.f900000664000175000017500000000067315135654166027201 0ustar alastairalastairprogram example_key_test use stdlib_kinds, only: int8 use stdlib_hashmaps, only: chaining_hashmap_type use stdlib_hashmap_wrappers, only: key_type, set implicit none type(chaining_hashmap_type) :: map type(key_type) :: key logical :: present call map%init() call set(key, [0_int8, 1_int8]) call map%key_test(key, present) print *, "Initial key of 10 present for empty map = ", present end program example_key_test fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_get.f900000664000175000017500000000064415135654166026127 0ustar alastairalastairprogram example_get use stdlib_hashmap_wrappers, only: & get, key_type, set use iso_fortran_env, only: int8 implicit none integer(int8), allocatable :: value(:), result(:) type(key_type) :: key integer(int8) :: i allocate (value(1:15)) do i = 1, 15 value(i) = i end do call set(key, value) call get(key, result) print *, 'RESULT == VALUE = ', all(value == result) end program example_get fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_map_entry.f900000664000175000017500000000334415135654166027346 0ustar alastairalastairprogram example_map_entry use, intrinsic:: iso_fortran_env, only: int8, int64 use stdlib_hashmaps, only: chaining_hashmap_type use stdlib_hashmap_wrappers, only: key_type, set implicit none type(chaining_hashmap_type) :: map type(key_type) :: key logical :: conflict integer :: int_scalar type :: array_data_wrapper integer, allocatable :: array(:) end type type(array_data_wrapper) :: array_example ! Initialize hashmap with 2^10 slots. ! Hashmap will dynamically increase size if needed. call map%init(slots_bits=10) ! Explicitly set key using set function call set(key, [1, 2, 3]) call map%map_entry(key, 4, conflict) print *, 'CONFLICT = ', conflict ! Using map_entry int32 array interface call map%map_entry( [4, 5, 6], 4, conflict) print *, 'CONFLICT = ', conflict ! Integer scalars need to be passed as an array. int_scalar = 1 call map%map_entry( [int_scalar], 4, conflict) print *, 'CONFLICT = ', conflict ! Using map_entry character interface call map%map_entry( 'key_string', 4, conflict) print *, 'CONFLICT = ', conflict ! Transfer unsupported key types to int8 arrays. call map%map_entry( transfer( [1_int64, 2_int64, 3_int64], [0_int8] ), 4, conflict) print *, 'CONFLICT = ', conflict ! Keys can be mapped alone without a corresponding value (other) for 'Set' type functionality. call map%map_entry( [7, 8, 9], conflict=conflict) print *, 'CONFLICT = ', conflict ! Currently only scalar data can be mapped. ! Arrays will need a wrapper. array_example % array = [1,2,3,4,5] call map % map_entry( [10,11,12], array_example, conflict=conflict ) print *, 'CONFLICT = ', conflict end program example_map_entry fortran-lang-stdlib-0ede301/example/hashmaps/example_hashmaps_remove.f900000664000175000017500000000265715135654166026653 0ustar alastairalastairprogram example_remove use stdlib_kinds, only: int8, int64 use stdlib_hashmaps, only: open_hashmap_type use stdlib_hashmap_wrappers, only: key_type, set implicit none type(open_hashmap_type) :: map type(key_type) :: key logical :: existed integer :: int_scalar ! Initialize hashmap with 2^10 slots. ! Hashmap will dynamically increase size if needed. call map%init(slots_bits=10) ! Explicitly set key type using set function call set(key, [1, 2, 3]) call map%map_entry(key, 4.0) call map%remove(key, existed) print *, "Removed key existed = ", existed ! Using map_entry and remove int32 generic interface. call map%map_entry([1, 2, 3], 4.0) call map%remove([1, 2, 3], existed) print *, "Removed key existed = ", existed ! Integer scalars need to be passed as an array. int_scalar = 1 call map%map_entry( [int_scalar], 4.0) call map%remove( [int_scalar], existed) print *, "Removed key existed = ", existed ! Using map_entry and remove character generic interface. call map%map_entry('key_string', 4.0) call map%remove('key_string', existed) print *, "Removed key existed = ", existed ! Use transfer to int8 arrays for unsupported key types. call map%map_entry( transfer( [1_int64, 2_int64], [0_int8] ), 4.0) call map%remove( transfer( [1_int64,2_int64], [0_int8] ), existed) print *, "Removed key existed = ", existed end program example_remove fortran-lang-stdlib-0ede301/example/sorting/0000775000175000017500000000000015135654166021306 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/sorting/example_sort_adjoint.f900000664000175000017500000000063015135654166026037 0ustar alastairalastairprogram example_sort_adjoint use stdlib_sorting, only: sort_adjoint implicit none integer, allocatable :: array(:) real, allocatable :: adjoint(:) array = [5, 4, 3, 1, 10, 4, 9] allocate(adjoint, source=real(array)) call sort_adjoint(array, adjoint) print *, array !print [1, 3, 4, 4, 5, 9, 10] print *, adjoint !print [1., 3., 4., 4., 5., 9., 10.] end program example_sort_adjoint fortran-lang-stdlib-0ede301/example/sorting/example_radix_sort.f900000664000175000017500000000155715135654166025527 0ustar alastairalastairprogram example_radix_sort use iso_fortran_env, only: int8, int16, dp => real64 use stdlib_sorting, only: radix_sort implicit none integer(int8), allocatable :: arri8(:) integer(int16), allocatable :: arri16(:) real(dp) :: x real(dp), allocatable :: arrf64(:) arri8 = [-128, 127, 0, -1, 1] call radix_sort(arri8) print *, arri8 arri16 = [-32767, 32767, 0, 0, -3, 2, -3] call radix_sort(arri16, reverse=.true.) print *, arri16 allocate (arrf64(10)) x = 0.0_dp ! divide zero will arise compile error arrf64 = [1.0_dp/x, 0.0_dp, 0.0_dp/x, -1.0_dp/x, -0.0_dp, 1.0_dp, -1.0_dp, 3.45_dp, -3.14_dp, 3.44_dp] call radix_sort(arrf64) print *, arrf64 ! Expected output: ! nan, -inf, -3.14, -1.0, -0.0, 0.0, 1.0, 3.44, 3.45, inf ! Note: the position of nan is undefined end program example_radix_sort fortran-lang-stdlib-0ede301/example/sorting/example_sort_bitset.f900000664000175000017500000000206215135654166025702 0ustar alastairalastairprogram example_sort_bitset use stdlib_kinds, only: int32 use stdlib_sorting, only: sort use stdlib_bitsets, only: bitset_large implicit none type(bitset_large), allocatable :: array(:) integer(int32) :: i array = [bitset_l("0101"), & ! 5 bitset_l("0100"), & ! 4 bitset_l("0011"), & ! 3 bitset_l("0001"), & ! 1 bitset_l("1010"), & ! 10 bitset_l("0100"), & ! 4 bitset_l("1001")] ! 9 call sort(array) do i = 1, size(array) print *, to_string(array(i)) ! 0001 ! 0011 ! 0100 ! 0100 ! 0101 ! 1001 ! 1010 end do deallocate(array) contains function bitset_l(str) result(new_bitsetl) character(*), intent(in) :: str type(bitset_large) :: new_bitsetl call new_bitsetl%from_string(str) end function bitset_l function to_string(bitset) result(str) type(bitset_large), intent(in) :: bitset character(:), allocatable :: str call bitset%to_string(str) end function to_string end program example_sort_bitset fortran-lang-stdlib-0ede301/example/sorting/example_ord_sort.f900000664000175000017500000000045215135654166025175 0ustar alastairalastairprogram example_ord_sort use stdlib_sorting, only: ord_sort implicit none integer, allocatable :: array1(:), work(:) array1 = [5, 4, 3, 1, 10, 4, 9] allocate (work, mold=array1) call ord_sort(array1, work) print *, array1 !print [1, 3, 4, 4, 5, 9, 10] end program example_ord_sort fortran-lang-stdlib-0ede301/example/sorting/CMakeLists.txt0000664000175000017500000000025115135654166024044 0ustar alastairalastairADD_EXAMPLE(ord_sort) ADD_EXAMPLE(sort) ADD_EXAMPLE(sort_adjoint) ADD_EXAMPLE(sort_index) ADD_EXAMPLE(radix_sort) if (STDLIB_BITSETS) ADD_EXAMPLE(sort_bitset) endif() fortran-lang-stdlib-0ede301/example/sorting/example_sort_index.f900000664000175000017500000000057315135654166025524 0ustar alastairalastairprogram example_sort_index use stdlib_sorting, only: sort_index implicit none integer, allocatable :: array(:) integer, allocatable :: index(:) array = [5, 4, 3, 1, 10, 4, 9] allocate(index, mold=array) call sort_index(array, index) print *, array !print [1, 3, 4, 4, 5, 9, 10] print *, index !print [4, 3, 2, 6, 1, 7, 5] end program example_sort_index fortran-lang-stdlib-0ede301/example/sorting/example_sort.f900000664000175000017500000000035015135654166024326 0ustar alastairalastairprogram example_sort use stdlib_sorting, only: sort implicit none integer, allocatable :: array(:) array = [5, 4, 3, 1, 10, 4, 9] call sort(array) print *, array !print [1, 3, 4, 4, 5, 9, 10] end program example_sort fortran-lang-stdlib-0ede301/example/stats/0000775000175000017500000000000015135654166020757 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/stats/example_moment.f900000664000175000017500000000117415135654166024314 0ustar alastairalastairprogram example_moment use stdlib_stats, only: moment implicit none real :: x(1:6) = [1., 2., 3., 4., 5., 6.] real :: y(1:2, 1:3) = reshape([1., 2., 3., 4., 5., 6.], [2, 3]) print *, moment(x, 2) !returns 2.9167 print *, moment(y, 2) !returns 2.9167 print *, moment(y, 2, 1) !returns [0.25, 0.25, 0.25] print *, moment(y, 2, 1, mask=(y > 3.)) !returns [NaN, 0., 0.25] print *, moment(x, 2, center=0.) !returns 15.1667 print *, moment(y, 1, 1, center=0.) !returns [1.5, 3.5, 5.5] end program example_moment fortran-lang-stdlib-0ede301/example/stats/example_corr.f900000664000175000017500000000052315135654166023757 0ustar alastairalastairprogram example_corr use stdlib_stats, only: corr implicit none real :: x(1:6) = [1., 2., 3., 4., 5., 6.] real :: y(1:2, 1:3) = reshape([-1., 40., -3., 4., 10., 6.], [2, 3]) print *, corr(x, 1) !returns 1. print *, corr(y, 2) !returns reshape([ 1., -.32480, -.32480, 1. ], [ 2, 3]) end program example_corr fortran-lang-stdlib-0ede301/example/stats/example_mean.f900000664000175000017500000000075315135654166023737 0ustar alastairalastairprogram example_mean use stdlib_stats, only: mean implicit none real :: x(1:6) = [1., 2., 3., 4., 5., 6.] real :: y(1:2, 1:3) = reshape([1., 2., 3., 4., 5., 6.], [2, 3]) print *, mean(x) !returns 3.5 print *, mean(y) !returns 3.5 print *, mean(y, 1) !returns [ 1.5, 3.5, 5.5 ] print *, mean(y, 1, y > 3.) !returns [ NaN, 4.0, 5.5 ] end program example_mean fortran-lang-stdlib-0ede301/example/stats/example_var.f900000664000175000017500000000115515135654166023604 0ustar alastairalastairprogram example_var use stdlib_stats, only: var implicit none real :: x(1:6) = [1., 2., 3., 4., 5., 6.] real :: y(1:2, 1:3) = reshape([1., 2., 3., 4., 5., 6.], [2, 3]) print *, var(x) !returns 3.5 print *, var(x, corrected=.false.) !returns 2.9167 print *, var(y) !returns 3.5 print *, var(y, 1) !returns [0.5, 0.5, 0.5] print *, var(y, 1, y > 3.) !returns [NaN, NaN, 0.5] print *, var(y, 1, y > 3., corrected=.false.) !returns [NaN, 0., 0.25] end program example_var fortran-lang-stdlib-0ede301/example/stats/example_cov.f900000664000175000017500000000065715135654166023611 0ustar alastairalastairprogram example_cov use stdlib_stats, only: cov implicit none real :: x(1:6) = [1., 2., 3., 4., 5., 6.] real :: y(1:2, 1:3) = reshape([1., 2., 3., 4., 5., 6.], [2, 3]) print *, cov(x, 1) !returns 3.5 print *, cov(x, 1, corrected=.false.) !returns 2.9167 print *, cov(y, 1) !returns a square matrix of size 3 with all elements equal to 0.5 end program example_cov fortran-lang-stdlib-0ede301/example/stats/example_median.f900000664000175000017500000000077215135654166024255 0ustar alastairalastairprogram example_median use stdlib_stats, only: median implicit none real :: x(1:6) = [1., 2., 3., 4., 5., 6.] real :: y(1:2, 1:3) = reshape([1., 2., 3., 4., 5., 6.], [2, 3]) print *, median(x) !returns 3.5 print *, median(y) !returns 3.5 print *, median(y, 1) !returns [ 1.5, 3.5, 5.5 ] print *, median(y, 1, y > 3.) !returns [ NaN, 4.0, 5.5 ] end program example_median fortran-lang-stdlib-0ede301/example/stats/CMakeLists.txt0000664000175000017500000000015615135654166023521 0ustar alastairalastairADD_EXAMPLE(corr) ADD_EXAMPLE(cov) ADD_EXAMPLE(mean) ADD_EXAMPLE(median) ADD_EXAMPLE(moment) ADD_EXAMPLE(var) fortran-lang-stdlib-0ede301/example/ansi/0000775000175000017500000000000015135654166020553 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/ansi/example_ansi_combine.f900000664000175000017500000000041715135654166025236 0ustar alastairalastairprogram example_ansi_combine use stdlib_ansi, only : fg_color_red, style_bold, ansi_code, operator(+), to_string implicit none type(ansi_code) :: bold_red bold_red = fg_color_red + style_bold print '(a)', to_string(bold_red) end program example_ansi_combinefortran-lang-stdlib-0ede301/example/ansi/example_ansi_concat.f900000664000175000017500000000032515135654166025067 0ustar alastairalastairprogram example_ansi_concat use stdlib_ansi, only : fg_color_red, style_reset, operator(//) implicit none print '(a)', fg_color_red // "Colorized text message" // style_reset end program example_ansi_concatfortran-lang-stdlib-0ede301/example/ansi/example_ansi_color.f900000664000175000017500000000062615135654166024742 0ustar alastairalastairprogram example_ansi_color use stdlib_ansi, only : fg_color_blue, style_bold, style_reset, ansi_code, & & operator(//), operator(+) implicit none type(ansi_code) :: highlight, reset print '(a)', highlight // "Dull text message" // reset highlight = fg_color_blue + style_bold reset = style_reset print '(a)', highlight // "Colorful text message" // reset end program example_ansi_colorfortran-lang-stdlib-0ede301/example/ansi/example_ansi_to_string.f900000664000175000017500000000036215135654166025631 0ustar alastairalastairprogram example_ansi_to_string use stdlib_ansi, only : fg_color_green, style_reset, to_string implicit none print '(a)', to_string(fg_color_green) // "Colorized text message" // to_string(style_reset) end program example_ansi_to_stringfortran-lang-stdlib-0ede301/example/ansi/CMakeLists.txt0000664000175000017500000000014615135654166023314 0ustar alastairalastairADD_EXAMPLE(ansi_color) ADD_EXAMPLE(ansi_combine) ADD_EXAMPLE(ansi_concat) ADD_EXAMPLE(ansi_to_string)fortran-lang-stdlib-0ede301/example/quadrature/0000775000175000017500000000000015135654166021776 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/quadrature/example_simps.f900000664000175000017500000000035515135654166025167 0ustar alastairalastairprogram example_simps use stdlib_quadrature, only: simps implicit none real, parameter :: x(5) = [0., 1., 2., 3., 4.] real :: y(5) = 3.*x**2 print *, simps(y, x) ! 64.0 print *, simps(y, 0.5) ! 32.0 end program example_simps fortran-lang-stdlib-0ede301/example/quadrature/example_trapz.f900000664000175000017500000000035215135654166025171 0ustar alastairalastairprogram example_trapz use stdlib_quadrature, only: trapz implicit none real, parameter :: x(5) = [0., 1., 2., 3., 4.] real :: y(5) = x**2 print *, trapz(y, x) ! 22.0 print *, trapz(y, 0.5) ! 11.0 end program example_trapz fortran-lang-stdlib-0ede301/example/quadrature/example_gauss_legendre_lobatto.f900000664000175000017500000000053315135654166030545 0ustar alastairalastairprogram example_gauss_legendre_lobatto use iso_fortran_env, dp => real64 use stdlib_quadrature, only: gauss_legendre_lobatto implicit none integer, parameter :: N = 6 real(dp), dimension(N) :: x, w call gauss_legendre_lobatto(x, w) print *, "integral of x**2 from -1 to 1 is", sum(x**2*w) end program example_gauss_legendre_lobatto fortran-lang-stdlib-0ede301/example/quadrature/CMakeLists.txt0000664000175000017500000000023415135654166024535 0ustar alastairalastairADD_EXAMPLE(gauss_legendre) ADD_EXAMPLE(gauss_legendre_lobatto) ADD_EXAMPLE(simps) ADD_EXAMPLE(simps_weights) ADD_EXAMPLE(trapz) ADD_EXAMPLE(trapz_weights) fortran-lang-stdlib-0ede301/example/quadrature/example_gauss_legendre.f900000664000175000017500000000047315135654166027024 0ustar alastairalastairprogram example_gauss_legendre use iso_fortran_env, dp => real64 use stdlib_quadrature, only: gauss_legendre implicit none integer, parameter :: N = 6 real(dp), dimension(N) :: x, w call gauss_legendre(x, w) print *, "integral of x**2 from -1 to 1 is", sum(x**2*w) end program example_gauss_legendre fortran-lang-stdlib-0ede301/example/quadrature/example_trapz_weights.f900000664000175000017500000000040615135654166026723 0ustar alastairalastairprogram example_trapz_weights use stdlib_quadrature, only: trapz_weights implicit none real, parameter :: x(5) = [0., 1., 2., 3., 4.] real :: y(5) = x**2 real :: w(5) w = trapz_weights(x) print *, sum(w*y) ! 22.0 end program example_trapz_weights fortran-lang-stdlib-0ede301/example/quadrature/example_simps_weights.f900000664000175000017500000000041015135654166026711 0ustar alastairalastairprogram example_simps_weights use stdlib_quadrature, only: simps_weights implicit none real, parameter :: x(5) = [0., 1., 2., 3., 4.] real :: y(5) = 3.*x**2 real :: w(5) w = simps_weights(x) print *, sum(w*y) ! 64.0 end program example_simps_weights fortran-lang-stdlib-0ede301/example/string_type/0000775000175000017500000000000015135654166022170 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/string_type/example_trim.f900000664000175000017500000000032615135654166025177 0ustar alastairalastairprogram example_trim use stdlib_string_type implicit none type(string_type) :: string string = "Whitespace " string = trim(string) ! len(string) == 10 end program example_trim fortran-lang-stdlib-0ede301/example/string_type/example_constructor_integer.f900000664000175000017500000000036115135654166030325 0ustar alastairalastairprogram example_constructor_integer use stdlib_string_type implicit none type(string_type) :: string string = string_type(42) ! len(string) == 2 string = string_type(-289) ! len(string) == 4 end program example_constructor_integer fortran-lang-stdlib-0ede301/example/string_type/example_scan.f900000664000175000017500000000043115135654166025145 0ustar alastairalastairprogram example_scan use stdlib_string_type implicit none type(string_type) :: string integer :: pos string = "fortran" pos = scan(string, "ao") ! pos == 2 pos = scan(string, "ao", .true.) ! pos == 6 pos = scan(string, "c++") ! pos == 0 end program example_scan fortran-lang-stdlib-0ede301/example/string_type/example_to_sentence.f900000664000175000017500000000056515135654166026537 0ustar alastairalastairprogram example_to_sentence use stdlib_string_type implicit none type(string_type) :: string, sentencecase_string string = "sentencecase this string." ! string <-- "sentencecase this string." sentencecase_string = to_sentence(string) ! string <-- "sentencecase this string." ! sentencecase_string <-- "Sentencecase this string." end program example_to_sentence fortran-lang-stdlib-0ede301/example/string_type/example_uread.f900000664000175000017500000000045115135654166025323 0ustar alastairalastairprogram example_uread use stdlib_string_type implicit none type(string_type) :: string integer :: io string = "Important saved value" open (newunit=io, form="unformatted", status="scratch") write (io) string rewind (io) read (io) string close (io) end program example_uread fortran-lang-stdlib-0ede301/example/string_type/example_ne.f900000664000175000017500000000043015135654166024622 0ustar alastairalastairprogram example_ne use stdlib_string_type implicit none type(string_type) :: string logical :: res string = "bcd" res = string /= "abc" ! res .eqv. .true. res = string /= "bcd" ! res .eqv. .false. res = string /= "cde" ! res .eqv. .true. end program example_ne fortran-lang-stdlib-0ede301/example/string_type/example_gt.f900000664000175000017500000000042615135654166024637 0ustar alastairalastairprogram example_gt use stdlib_string_type implicit none type(string_type) :: string logical :: res string = "bcd" res = string > "abc" ! res .eqv. .true. res = string > "bcd" ! res .eqv. .false. res = string > "cde" ! res .eqv. .false. end program example_gt fortran-lang-stdlib-0ede301/example/string_type/example_constructor_character.f900000664000175000017500000000032315135654166030622 0ustar alastairalastairprogram example_constructor_character use stdlib_string_type implicit none type(string_type) :: string ! len(string) == 0 string = "Sequence" ! len(string) == 8 end program example_constructor_character fortran-lang-stdlib-0ede301/example/string_type/example_le.f900000664000175000017500000000043015135654166024620 0ustar alastairalastairprogram example_le use stdlib_string_type implicit none type(string_type) :: string logical :: res string = "bcd" res = string <= "abc" ! res .eqv. .false. res = string <= "bcd" ! res .eqv. .true. res = string <= "cde" ! res .eqv. .true. end program example_le fortran-lang-stdlib-0ede301/example/string_type/example_llt.f900000664000175000017500000000044415135654166025020 0ustar alastairalastairprogram example_llt use stdlib_string_type implicit none type(string_type) :: string logical :: res string = "bcd" res = llt(string, "abc") ! res .eqv. .false. res = llt(string, "bcd") ! res .eqv. .false. res = llt(string, "cde") ! res .eqv. .true. end program example_llt fortran-lang-stdlib-0ede301/example/string_type/example_fread.f900000664000175000017500000000047515135654166025312 0ustar alastairalastairprogram example_fread use stdlib_string_type implicit none type(string_type) :: string integer :: io string = "Important saved value" open (newunit=io, form="formatted", status="scratch") write (io, *) string write (io, *) rewind (io) read (io, *) string close (io) end program example_fread fortran-lang-stdlib-0ede301/example/string_type/example_adjustl.f900000664000175000017500000000040615135654166025671 0ustar alastairalastairprogram example_adjustl use stdlib_string_type implicit none type(string_type) :: string string = " Whitespace" string = adjustl(string) ! char(string) == "Whitespace " end program example_adjustl fortran-lang-stdlib-0ede301/example/string_type/example_repeat.f900000664000175000017500000000031415135654166025501 0ustar alastairalastairprogram example_repeat use stdlib_string_type implicit none type(string_type) :: string string = "What? " string = repeat(string, 3) ! string == "What? What? What? " end program example_repeat fortran-lang-stdlib-0ede301/example/string_type/example_cont.f900000664000175000017500000000027315135654166025170 0ustar alastairalastairprogram example_cont use stdlib_string_type implicit none type(string_type) :: string string = "Hello, " string = string//"World!" ! len(string) == 13 end program example_cont fortran-lang-stdlib-0ede301/example/string_type/example_adjustr.f900000664000175000017500000000040615135654166025677 0ustar alastairalastairprogram example_adjustr use stdlib_string_type implicit none type(string_type) :: string string = "Whitespace " string = adjustr(string) ! char(string) == " Whitespace" end program example_adjustr fortran-lang-stdlib-0ede301/example/string_type/example_constructor_empty.f900000664000175000017500000000027315135654166030030 0ustar alastairalastairprogram example_constructor_empty use stdlib_string_type implicit none type(string_type) :: string string = string_type() ! len(string) == 0 end program example_constructor_empty fortran-lang-stdlib-0ede301/example/string_type/CMakeLists.txt0000664000175000017500000000150615135654166024732 0ustar alastairalastairADD_EXAMPLE(adjustl) ADD_EXAMPLE(adjustr) ADD_EXAMPLE(char) ADD_EXAMPLE(char_position) ADD_EXAMPLE(char_range) ADD_EXAMPLE(constructor_character) ADD_EXAMPLE(constructor_empty) ADD_EXAMPLE(constructor_integer) ADD_EXAMPLE(constructor_logical) ADD_EXAMPLE(constructor_scalar) ADD_EXAMPLE(cont) ADD_EXAMPLE(eq) ADD_EXAMPLE(fread) ADD_EXAMPLE(fwrite) ADD_EXAMPLE(ge) ADD_EXAMPLE(gt) ADD_EXAMPLE(iachar) ADD_EXAMPLE(ichar) ADD_EXAMPLE(index) ADD_EXAMPLE(le) ADD_EXAMPLE(len) ADD_EXAMPLE(len_trim) ADD_EXAMPLE(lge) ADD_EXAMPLE(lgt) ADD_EXAMPLE(lle) ADD_EXAMPLE(llt) ADD_EXAMPLE(lt) ADD_EXAMPLE(move) ADD_EXAMPLE(ne) ADD_EXAMPLE(repeat) ADD_EXAMPLE(reverse) ADD_EXAMPLE(scan) ADD_EXAMPLE(to_lower) ADD_EXAMPLE(to_sentence) ADD_EXAMPLE(to_title) ADD_EXAMPLE(to_upper) ADD_EXAMPLE(trim) ADD_EXAMPLE(uread) ADD_EXAMPLE(uwrite) ADD_EXAMPLE(verify) fortran-lang-stdlib-0ede301/example/string_type/example_len_trim.f900000664000175000017500000000052115135654166026032 0ustar alastairalastairprogram example_len_trim use stdlib_string_type implicit none type(string_type) :: string integer :: length string = "Some longer sentence for this example." length = len_trim(string) ! length == 38 string = "Whitespace " length = len_trim(string) ! length == 10 end program example_len_trim fortran-lang-stdlib-0ede301/example/string_type/example_iachar.f900000664000175000017500000000027115135654166025452 0ustar alastairalastairprogram example_iachar use stdlib_string_type implicit none type(string_type) :: string integer :: code string = "Fortran" code = iachar(string) end program example_iachar fortran-lang-stdlib-0ede301/example/string_type/example_ichar.f900000664000175000017500000000026615135654166025315 0ustar alastairalastairprogram example_ichar use stdlib_string_type implicit none type(string_type) :: string integer :: code string = "Fortran" code = ichar(string) end program example_ichar fortran-lang-stdlib-0ede301/example/string_type/example_eq.f900000664000175000017500000000043115135654166024626 0ustar alastairalastairprogram example_eq use stdlib_string_type implicit none type(string_type) :: string logical :: res string = "bcd" res = string == "abc" ! res .eqv. .false. res = string == "bcd" ! res .eqv. .true. res = string == "cde" ! res .eqv. .false. end program example_eq fortran-lang-stdlib-0ede301/example/string_type/example_char_position.f900000664000175000017500000000060115135654166027061 0ustar alastairalastairprogram example_char_position use stdlib_string_type implicit none type(string_type) :: string character(len=:), allocatable :: dlc character(len=1), allocatable :: chars(:) string = "Character sequence" dlc = char(string, 3) ! dlc == "a" chars = char(string, [3, 5, 8, 12, 14, 15, 18]) ! chars == ["a", "a", "e", "e", "u", "e", "e"] end program example_char_position fortran-lang-stdlib-0ede301/example/string_type/example_constructor_logical.f900000664000175000017500000000037015135654166030302 0ustar alastairalastairprogram example_constructor_logical use stdlib_string_type implicit none type(string_type) :: string string = string_type(.true.) ! len(string) == 1 string = string_type(.false.) ! len(string) == 1 end program example_constructor_logical fortran-lang-stdlib-0ede301/example/string_type/example_char_range.f900000664000175000017500000000035115135654166026313 0ustar alastairalastairprogram example_char_range use stdlib_string_type implicit none type(string_type) :: string character(len=:), allocatable :: dlc string = "Fortran" dlc = char(string, 1, 4) ! dlc == "Fort" end program example_char_range fortran-lang-stdlib-0ede301/example/string_type/example_constructor_scalar.f900000664000175000017500000000040315135654166030132 0ustar alastairalastairprogram example_constructor_scalar use stdlib_string_type implicit none type(string_type) :: string string = string_type("Sequence") ! len(string) == 8 string = string_type(" S p a c e d ") ! len(string) == 13 end program example_constructor_scalar fortran-lang-stdlib-0ede301/example/string_type/example_to_title.f900000664000175000017500000000052715135654166026052 0ustar alastairalastairprogram example_to_title use stdlib_string_type implicit none type(string_type) :: string, titlecase_string string = "titlecase this string." ! string <-- "titlecase this string." titlecase_string = to_title(string) ! string <-- "titlecase this string." ! titlecase_string <-- "Titlecase This String." end program example_to_title fortran-lang-stdlib-0ede301/example/string_type/example_move.f900000664000175000017500000000107515135654166025174 0ustar alastairalastairprogram example_move use stdlib_string_type, only: string_type, assignment(=), move implicit none type(string_type) :: from_string character(len=:), allocatable :: from_char, to_char from_string = "move this string" from_char = "move this char" ! from_string <-- "move this string" ! from_char <-- "move this char" ! to_char <-- (unallocated) call move(from_string, to_char) ! from_string <-- "" ! to_char <-- "move this string" call move(from_char, to_char) ! from_char <-- (unallocated) ! to_string <-- "move this char" end program example_move fortran-lang-stdlib-0ede301/example/string_type/example_lge.f900000664000175000017500000000044315135654166024773 0ustar alastairalastairprogram example_lge use stdlib_string_type implicit none type(string_type) :: string logical :: res string = "bcd" res = lge(string, "abc") ! res .eqv. .true. res = lge(string, "bcd") ! res .eqv. .true. res = lge(string, "cde") ! res .eqv. .false. end program example_lge fortran-lang-stdlib-0ede301/example/string_type/example_lle.f900000664000175000017500000000044315135654166025000 0ustar alastairalastairprogram example_lle use stdlib_string_type implicit none type(string_type) :: string logical :: res string = "bcd" res = lle(string, "abc") ! res .eqv. .false. res = lle(string, "bcd") ! res .eqv. .true. res = lle(string, "cde") ! res .eqv. .true. end program example_lle fortran-lang-stdlib-0ede301/example/string_type/example_lgt.f900000664000175000017500000000044415135654166025013 0ustar alastairalastairprogram example_lgt use stdlib_string_type implicit none type(string_type) :: string logical :: res string = "bcd" res = lgt(string, "abc") ! res .eqv. .true. res = lgt(string, "bcd") ! res .eqv. .false. res = lgt(string, "cde") ! res .eqv. .false. end program example_lgt fortran-lang-stdlib-0ede301/example/string_type/example_ge.f900000664000175000017500000000043015135654166024613 0ustar alastairalastairprogram example_ge use stdlib_string_type implicit none type(string_type) :: string logical :: res string = "bcd" res = string >= "abc" ! res .eqv. .true. res = string >= "bcd" ! res .eqv. .true. res = string >= "cde" ! res .eqv. .false. end program example_ge fortran-lang-stdlib-0ede301/example/string_type/example_len.f900000664000175000017500000000047515135654166025007 0ustar alastairalastairprogram example_len use stdlib_string_type implicit none type(string_type) :: string integer :: length string = "Some longer sentence for this example." length = len(string) ! length == 38 string = "Whitespace " length = len(string) ! length == 38 end program example_len fortran-lang-stdlib-0ede301/example/string_type/example_uwrite.f900000664000175000017500000000045315135654166025544 0ustar alastairalastairprogram example_uwrite use stdlib_string_type implicit none type(string_type) :: string integer :: io string = "Important saved value" open (newunit=io, form="unformatted", status="scratch") write (io) string rewind (io) read (io) string close (io) end program example_uwrite fortran-lang-stdlib-0ede301/example/string_type/example_index.f900000664000175000017500000000051015135654166025326 0ustar alastairalastairprogram example_index use stdlib_string_type implicit none type(string_type) :: string integer :: pos string = "Search this string for this expression" pos = index(string, "this") ! pos == 8 pos = index(string, "this", back=.true.) ! pos == 24 pos = index(string, "This") ! pos == 0 end program example_index fortran-lang-stdlib-0ede301/example/string_type/example_to_upper.f900000664000175000017500000000052315135654166026060 0ustar alastairalastairprogram example_to_upper use stdlib_string_type implicit none type(string_type) :: string, uppercase_string string = "Uppercase This String" ! string <-- "Uppercase This String" uppercase_string = to_upper(string) ! string <-- "Uppercase This String" ! uppercase_string <-- "UPPERCASE THIS STRING" end program example_to_upper fortran-lang-stdlib-0ede301/example/string_type/example_char.f900000664000175000017500000000036015135654166025137 0ustar alastairalastairprogram example_char use stdlib_string_type implicit none type(string_type) :: string character(len=:), allocatable :: dlc string = "Character sequence" dlc = char(string) ! dlc == "Character sequence" end program example_char fortran-lang-stdlib-0ede301/example/string_type/example_fwrite.f900000664000175000017500000000047715135654166025533 0ustar alastairalastairprogram example_fwrite use stdlib_string_type implicit none type(string_type) :: string integer :: io string = "Important saved value" open (newunit=io, form="formatted", status="scratch") write (io, *) string write (io, *) rewind (io) read (io, *) string close (io) end program example_fwrite fortran-lang-stdlib-0ede301/example/string_type/example_lt.f900000664000175000017500000000042615135654166024644 0ustar alastairalastairprogram example_lt use stdlib_string_type implicit none type(string_type) :: string logical :: res string = "bcd" res = string < "abc" ! res .eqv. .false. res = string < "bcd" ! res .eqv. .false. res = string < "cde" ! res .eqv. .true. end program example_lt fortran-lang-stdlib-0ede301/example/string_type/example_to_lower.f900000664000175000017500000000052315135654166026055 0ustar alastairalastairprogram example_to_lower use stdlib_string_type implicit none type(string_type) :: string, lowercase_string string = "Lowercase This String" ! string <-- "Lowercase This String" lowercase_string = to_lower(string) ! string <-- "Lowercase This String" ! lowercase_string <-- "lowercase this string" end program example_to_lower fortran-lang-stdlib-0ede301/example/string_type/example_reverse.f900000664000175000017500000000050215135654166025673 0ustar alastairalastairprogram example_reverse use stdlib_string_type implicit none type(string_type) :: string, reverse_string string = "Reverse This String" ! string <-- "Reverse This String" reverse_string = reverse(string) ! string <-- "Reverse This String" ! reverse_string <-- "gnirtS sihT esreveR" end program example_reverse fortran-lang-stdlib-0ede301/example/string_type/example_verify.f900000664000175000017500000000057515135654166025536 0ustar alastairalastairprogram example_verify use stdlib_string_type implicit none type(string_type) :: string integer :: pos string = "fortran" pos = verify(string, "ao") ! pos == 1 pos = verify(string, "fo") ! pos == 3 pos = verify(string, "c++") ! pos == 1 pos = verify(string, "c++", back=.true.) ! pos == 7 pos = verify(string, string) ! pos == 0 end program example_verify fortran-lang-stdlib-0ede301/example/optval/0000775000175000017500000000000015135654166021126 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/optval/CMakeLists.txt0000664000175000017500000000002415135654166023662 0ustar alastairalastairADD_EXAMPLE(optval) fortran-lang-stdlib-0ede301/example/optval/example_optval.f900000664000175000017500000000047115135654166024470 0ustar alastairalastairprogram example_optval use stdlib_optval, only: optval implicit none print *, root(64.0) ! 8.0 print *, root(64.0, 3) ! 4.0 contains real function root(x, n) real, intent(in) :: x integer, intent(in), optional :: n root = x**(1.0/optval(n, 2)) end function root end program example_optval fortran-lang-stdlib-0ede301/example/hash_procedures/0000775000175000017500000000000015135654166022777 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/hash_procedures/example_nmhash32x.f900000664000175000017500000000055515135654166026652 0ustar alastairalastairprogram example_nmhash32x use stdlib_hash_32bit, only: nmhash32x, & new_nmhash32x_seed use iso_fortran_env, only: int32 implicit none integer(int32) :: hash integer(int32) :: seed = 42_int32 call new_nmhash32x_seed(seed) hash = nmhash32x([5, 4, 3, 1, 10, 4, 9], seed) print *, seed, hash end program example_nmhash32x fortran-lang-stdlib-0ede301/example/hash_procedures/example_universal_mult_hash_64.f900000664000175000017500000000101015135654166031407 0ustar alastairalastairprogram example_universal_mult_hash_64 use stdlib_hash_64bit, only: odd_random_integer, & universal_mult_hash use iso_fortran_env, only: int64 implicit none integer, allocatable :: array1(:) integer(int64) :: hash, seed, source seed = 0 allocate (array1(0:2**6 - 1)) array1 = 0 call odd_random_integer(seed) source = 42_int64 hash = universal_mult_hash(source, seed, 6) array1(hash) = source print *, seed, hash, array1 end program example_universal_mult_hash_64 fortran-lang-stdlib-0ede301/example/hash_procedures/example_pengy_hash.f900000664000175000017500000000060415135654166027157 0ustar alastairalastairprogram example_pengy_hash use stdlib_hash_64bit, only: new_pengy_hash_seed, pengy_hash use iso_fortran_env, only: int32, int64 implicit none integer, allocatable :: key(:) integer(int64) :: hash integer(int32) :: seed key = [0, 1, 2, 3] seed = 0_int32 call new_pengy_hash_seed(seed) hash = pengy_hash(key, seed) print *, seed, hash end program example_pengy_hash fortran-lang-stdlib-0ede301/example/hash_procedures/example_nmhash32.f900000664000175000017500000000054715135654166026463 0ustar alastairalastairprogram example_nmhash32 use stdlib_hash_32bit, only: nmhash32, & new_nmhash32_seed use iso_fortran_env, only: int32 implicit none integer(int32) :: hash integer(int32) :: seed = 42_int32 call new_nmhash32_seed(seed) hash = nmhash32([5, 4, 3, 1, 10, 4, 9], seed) print *, seed, hash end program example_nmhash32 fortran-lang-stdlib-0ede301/example/hash_procedures/example_spooky_hash.f900000664000175000017500000000065215135654166027364 0ustar alastairalastairprogram example_spooky_hash use stdlib_hash_64bit, only: new_spooky_hash_seed, & spooky_hash use iso_fortran_env, only: int64 implicit none integer, allocatable :: key(:) integer(int64) :: hash(2), seed(2) key = [0, 1, 2, 3] seed = [119_int64, 2_int64**41 - 1] call new_spooky_hash_seed(seed) hash = spooky_hash(key, seed) print *, seed, hash end program example_spooky_hash fortran-lang-stdlib-0ede301/example/hash_procedures/example_fnv_1a_hash_64.f900000664000175000017500000000045415135654166027523 0ustar alastairalastairprogram example_fnv_1a_hash_64 use stdlib_hash_64bit, only: fnv_1a_hash use iso_fortran_env, only: int64 implicit none integer, allocatable :: array1(:) integer(int64) :: hash array1 = [5, 4, 3, 1, 10, 4, 9] hash = fnv_1a_hash(array1) print *, hash end program example_fnv_1a_hash_64 fortran-lang-stdlib-0ede301/example/hash_procedures/example_universal_mult_hash.f900000664000175000017500000000105015135654166031102 0ustar alastairalastairprogram example_universal_mult_hash use stdlib_hash_32bit, only: odd_random_integer, & universal_mult_hash use iso_fortran_env, only: int32 implicit none integer, allocatable :: array1(:) integer(int32) :: hash, i, seed, source seed = 0 allocate (array1(0:2**6 - 1)) do i = 0, 2**6 - 1 array1(i) = i end do call odd_random_integer(seed) source = 42_int32 hash = universal_mult_hash(source, seed, 6) array1(hash) = source print *, seed, hash, array1 end program example_universal_mult_hash fortran-lang-stdlib-0ede301/example/hash_procedures/CMakeLists.txt0000664000175000017500000000053615135654166025543 0ustar alastairalastairADD_EXAMPLE(fibonacci_hash_64) ADD_EXAMPLE(fibonacci_hash) ADD_EXAMPLE(fnv_1a_hash_64) ADD_EXAMPLE(fnv_1a_hash) ADD_EXAMPLE(fnv_1_hash_64) ADD_EXAMPLE(fnv_1_hash) ADD_EXAMPLE(nmhash32) ADD_EXAMPLE(nmhash32x) ADD_EXAMPLE(pengy_hash) ADD_EXAMPLE(spooky_hash) ADD_EXAMPLE(universal_mult_hash_64) ADD_EXAMPLE(universal_mult_hash) ADD_EXAMPLE(water_hash) fortran-lang-stdlib-0ede301/example/hash_procedures/example_fnv_1_hash.f900000664000175000017500000000035415135654166027050 0ustar alastairalastairprogram example_fnv_1_hash use stdlib_hash_32bit, only: fnv_1_hash use iso_fortran_env, only: int32 implicit none integer(int32) :: hash hash = fnv_1_hash([5, 4, 3, 1, 10, 4, 9]) print *, hash end program example_fnv_1_hash fortran-lang-stdlib-0ede301/example/hash_procedures/example_fnv_1a_hash.f900000664000175000017500000000036015135654166027206 0ustar alastairalastairprogram example_fnv_1a_hash use stdlib_hash_32bit, only: fnv_1a_hash use iso_fortran_env, only: int32 implicit none integer(int32) :: hash hash = fnv_1a_hash([5, 4, 3, 1, 10, 4, 9]) print *, hash end program example_fnv_1a_hash fortran-lang-stdlib-0ede301/example/hash_procedures/example_fibonacci_hash_64.f900000664000175000017500000000061515135654166030265 0ustar alastairalastairprogram example_fibonacci_hash_64 use stdlib_hash_64bit, only: fibonacci_hash use iso_fortran_env, only: int64 implicit none integer, allocatable :: array1(:) integer(int64) :: hash, source allocate (array1(0:2**6 - 1)) array1(:) = 0 source = int(Z'1FFFFFFFF', int64) hash = fibonacci_hash(source, 6) array1(hash) = source print *, hash end program example_fibonacci_hash_64 fortran-lang-stdlib-0ede301/example/hash_procedures/example_water_hash.f900000664000175000017500000000057215135654166027163 0ustar alastairalastairprogram example_water_hash use stdlib_hash_32bit, only: water_hash, & new_water_hash_seed use iso_fortran_env, only: int32, int64 implicit none integer(int32) :: hash integer(int64) :: seed = 42_int64 call new_water_hash_seed(seed) hash = water_hash([5, 4, 3, 1, 10, 4, 9], seed) print *, hash, seed end program example_water_hash fortran-lang-stdlib-0ede301/example/hash_procedures/example_fibonacci_hash.f900000664000175000017500000000056715135654166027762 0ustar alastairalastairprogram example_fibonacci_hash use stdlib_hash_32bit, only: fibonacci_hash use iso_fortran_env, only: int32 implicit none integer, allocatable :: array1(:) integer(int32) :: hash, source allocate (array1(0:2**6 - 1)) array1(:) = 0 source = 42_int32 hash = fibonacci_hash(source, 6) array1(hash) = source print *, hash end program example_fibonacci_hash fortran-lang-stdlib-0ede301/example/hash_procedures/example_fnv_1_hash_64.f900000664000175000017500000000045015135654166027356 0ustar alastairalastairprogram example_fnv_1_hash_64 use stdlib_hash_64bit, only: fnv_1_hash use iso_fortran_env, only: int64 implicit none integer, allocatable :: array1(:) integer(int64) :: hash array1 = [5, 4, 3, 1, 10, 4, 9] hash = fnv_1_hash(array1) print *, hash end program example_fnv_1_hash_64 fortran-lang-stdlib-0ede301/example/system/0000775000175000017500000000000015135654166021145 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/system/example_process_5.f900000664000175000017500000000145515135654166025107 0ustar alastairalastair! Process example 5: Object-oriented interface program example_process_5 use stdlib_system, only: process_type, runasync, is_windows, sleep, update implicit none type(process_type) :: process if (is_windows()) then process = runasync("ping -n 10 127.0.0.1") else process = runasync("ping -c 10 127.0.0.1") endif ! Verify the process is running do while (process%is_running()) ! Update process state call update(process) ! Wait a bit before killing the process call sleep(millisec=1500) print *, "Process has been running for ",process%elapsed()," seconds..." end do print *, "Process ",process%pid()," completed in ",process%elapsed()," seconds." end program example_process_5 fortran-lang-stdlib-0ede301/example/system/example_path_join.f900000664000175000017500000000161515135654166025156 0ustar alastairalastair! Usage of join_path, operator(/) program example_path_join use stdlib_system, only: join_path, operator(/), OS_TYPE, OS_WINDOWS character(len=:), allocatable :: p1, p2, p3 character(len=20) :: parr(4) if(OS_TYPE() == OS_WINDOWS) then p1 = 'C:'/'Users'/'User1'/'Desktop' p2 = join_path('C:\Users\User1', 'Desktop') parr = [character(len=20) :: 'C:', 'Users', 'User1', 'Desktop'] p3 = join_path(parr) else p1 = ''/'home'/'User1'/'Desktop' p2 = join_path('/home/User1', 'Desktop') parr = [character(len=20) :: '', 'home', 'User1', 'Desktop'] p3 = join_path(parr) end if ! (p1 == p2 == p3) = '/home/User1/Desktop' OR 'C:\Users\User1\Desktop' print *, p1 ! /home/User1/Desktop OR 'C:\Users\User1\Desktop' print *, "p1 == p2: ", p1 == p2 ! T print *, "p2 == p3: ", p2 == p3 ! T end program example_path_join fortran-lang-stdlib-0ede301/example/system/example_is_file.f900000664000175000017500000000057115135654166024615 0ustar alastairalastair! Demonstrate usage of `is_file` program example_is_file use stdlib_system, only: is_file implicit none character(*), parameter :: path = "path/to/check" ! Test if path is a regular file if (is_file(path)) then print *, "The specified path is a regular file." else print *, "The specified path is not a regular file." end if end program example_is_file fortran-lang-stdlib-0ede301/example/system/example_process_1.f900000664000175000017500000000134015135654166025074 0ustar alastairalastair! Process example 1: Run a Command Synchronously and Capture Output program run_sync use stdlib_system, only: run, is_completed, is_windows, process_type implicit none type(process_type) :: p logical :: completed ! Run a synchronous process to list directory contents if (is_windows()) then p = run("dir", want_stdout=.true.) else p = run("ls -l", want_stdout=.true.) end if ! Check if the process is completed (should be true since wait=.true.) if (is_completed(p)) then print *, "Process completed successfully. The current directory: " print *, p%stdout else print *, "Process is still running (unexpected)." end if end program run_sync fortran-lang-stdlib-0ede301/example/system/example_fs_error.f900000664000175000017500000000150215135654166025017 0ustar alastairalastair! Demonstrate usage of `FS_ERROR`, `FS_ERROR_CODE` program example_fs_error use stdlib_system, only: FS_ERROR, FS_ERROR_CODE use stdlib_error, only: state_type, STDLIB_FS_ERROR implicit none type(state_type) :: err0, err1 err0 = FS_ERROR("Could not create directory", "`temp.dir`", "- Already exists") if (err0%state == STDLIB_FS_ERROR) then ! Error encountered: Filesystem Error: Could not create directory `temp.dir` - Already exists print *, err0%print() end if err1 = FS_ERROR_CODE(1, "Could not create directory", "`temp.dir`", "- Already exists") if (err1%state == STDLIB_FS_ERROR) then ! Error encountered: Filesystem Error: code - 1, Could not create directory `temp.dir` - Already exists print *, err1%print() end if end program example_fs_error fortran-lang-stdlib-0ede301/example/system/example_null_device.f900000664000175000017500000000101615135654166025467 0ustar alastairalastair! Showcase usage of the null device program example_null_device use stdlib_system, only: null_device use iso_fortran_env, only: output_unit implicit none integer :: unit logical :: screen_output = .false. if (screen_output) then unit = output_unit else ! Write to the null device if no screen output is wanted open(newunit=unit,file=null_device()) endif write(unit,*) "Hello, world!" if (.not.screen_output) close(unit) end program example_null_device fortran-lang-stdlib-0ede301/example/system/example_process_7.f900000664000175000017500000000076015135654166025107 0ustar alastairalastair! Process example 7: Usage of `kill` program example_process_7 use stdlib_system, only: process_type, runasync, kill implicit none type(process_type) :: p logical :: success ! Start a process asynchronously p = runasync("sleep 10") ! Attempt to kill the process call kill(p, success) if (success) then print *, "Process successfully killed." else print *, "Failed to kill the process." end if end program example_process_7 fortran-lang-stdlib-0ede301/example/system/example_path_dir_name.f900000664000175000017500000000070215135654166025771 0ustar alastairalastair! Usage of dir_name program example_path_dir_name use stdlib_system, only: dir_name, OS_TYPE, OS_WINDOWS character(len=:), allocatable :: p1, head, tail if(OS_TYPE() == OS_WINDOWS) then p1 = 'C:\Users' ! C:\Users else p1 = '/home' ! /home endif print *, 'dir_name of '// p1 // ' -> ' // dir_name(p1) ! dir_name of C:\Users -> C:\ ! OR ! dir_name of /home -> / end program example_path_dir_name fortran-lang-stdlib-0ede301/example/system/example_delete_file.f900000664000175000017500000000072315135654166025443 0ustar alastairalastair! Demonstrate usage of `delete_file` program example_delete_file use stdlib_system, only: delete_file use stdlib_error, only: state_type implicit none type(state_type) :: err character(*), parameter :: filename = "example.txt" ! Delete a file with error handling call delete_file(filename, err) if (err%error()) then print *, err%print() else print *, "File "//filename//" deleted successfully." end if end program example_delete_file fortran-lang-stdlib-0ede301/example/system/example_path_base_name.f900000664000175000017500000000066415135654166026134 0ustar alastairalastair! Usage of base_name program example_path_base_name use stdlib_system, only: base_name, OS_TYPE, OS_WINDOWS character(len=:), allocatable :: p1 if(OS_TYPE() == OS_WINDOWS) then p1 = 'C:\Users' else p1 = '/home' endif print *, 'base name of '// p1 // ' -> ' // base_name(p1) ! base name of C:\Users -> Users ! OR ! base name of /home -> home end program example_path_base_name fortran-lang-stdlib-0ede301/example/system/example_make_directory.f900000664000175000017500000000117015135654166026200 0ustar alastairalastair! Illustrate the usage of `make_directory`, `make_directory_all` program example_make_directory use stdlib_system, only: make_directory, make_directory_all use stdlib_error, only: state_type implicit none type(state_type) :: err call make_directory("temp_dir", err) if (err%error()) then print *, err%print() else print *, "directory created sucessfully" end if call make_directory_all("d1/d2/d3/d4", err) if (err%error()) then print *, err%print() else print *, "nested directories created sucessfully" end if end program example_make_directory fortran-lang-stdlib-0ede301/example/system/example_remove_directory.f900000664000175000017500000000066115135654166026564 0ustar alastairalastair! Illustrate the usage of `remove_directory` program example_remove_directory use stdlib_system, only: remove_directory use stdlib_error, only: state_type implicit none type(state_type) :: err call remove_directory("directory_to_be_removed", err) if (err%error()) then print *, err%print() else print *, "directory removed successfully" end if end program example_remove_directory fortran-lang-stdlib-0ede301/example/system/CMakeLists.txt0000664000175000017500000000107515135654166023710 0ustar alastairalastairADD_EXAMPLE(get_runtime_os) ADD_EXAMPLE(delete_file) ADD_EXAMPLE(null_device) ADD_EXAMPLE(os_type) ADD_EXAMPLE(process_1) ADD_EXAMPLE(process_2) ADD_EXAMPLE(process_3) ADD_EXAMPLE(process_4) ADD_EXAMPLE(process_5) ADD_EXAMPLE(process_6) ADD_EXAMPLE(process_7) ADD_EXAMPLE(sleep) ADD_EXAMPLE(fs_error) ADD_EXAMPLE(path_join) ADD_EXAMPLE(path_split_path) ADD_EXAMPLE(path_base_name) ADD_EXAMPLE(path_dir_name) ADD_EXAMPLE(make_directory) ADD_EXAMPLE(remove_directory) ADD_EXAMPLE(cwd) ADD_EXAMPLE(exists) ADD_EXAMPLE(is_file) ADD_EXAMPLE(is_directory) ADD_EXAMPLE(is_symlink)fortran-lang-stdlib-0ede301/example/system/example_process_3.f900000664000175000017500000000112015135654166025072 0ustar alastairalastair! Process example 3: Run with many arguments, and check runtime program run_with_args use stdlib_system, only: process_type, run, elapsed, wait implicit none type(process_type) :: p character(len=15), allocatable :: args(:) ! Define arguments for the `echo` command allocate(args(2)) args(1) = "echo" args(2) = "Hello, Fortran!" ! Run the command with arguments (synchronous) p = run(args) ! Print the runtime of the process print *, "Process runtime:", elapsed(p), "seconds." ! Clean up deallocate(args) end program run_with_args fortran-lang-stdlib-0ede301/example/system/example_get_runtime_os.f900000664000175000017500000000045115135654166026223 0ustar alastairalastair! Demonstrate usage of (non-cached) runtime OS query program example_get_runtime_os use stdlib_system, only: OS_NAME, get_runtime_os implicit none ! Runtime OS detection (full inspection) print *, "Runtime OS Type: ", OS_NAME(get_runtime_os()) end program example_get_runtime_os fortran-lang-stdlib-0ede301/example/system/example_os_type.f900000664000175000017500000000043115135654166024660 0ustar alastairalastair! Demonstrate OS detection program example_os_type use stdlib_system, only: OS_TYPE, OS_NAME implicit none integer :: current_os ! Cached OS detection current_os = OS_TYPE() print *, "Current OS Type: ", OS_NAME(current_os) end program example_os_type fortran-lang-stdlib-0ede301/example/system/example_sleep.f900000664000175000017500000000037415135654166024314 0ustar alastairalastair! Usage of `sleep` program example_sleep use stdlib_system, only: sleep implicit none print *, "Starting sleep..." ! Sleep for 500 milliseconds call sleep(500) print *, "Finished sleeping!" end program example_sleep fortran-lang-stdlib-0ede301/example/system/example_cwd.f900000664000175000017500000000141115135654166023752 0ustar alastairalastair! Illustrate the usage of `get_cwd`, `set_cwd` program example_cwd use stdlib_system, only: get_cwd, set_cwd use stdlib_error, only: state_type implicit none character(len=:), allocatable :: path type(state_type) :: err call get_cwd(path, err) if (err%error()) then print *, "Error getting current working directory: "//err%print() end if print *, "CWD: "//path call set_cwd("./src", err) if (err%error()) then print *, "Error setting current working directory: "//err%print() end if call get_cwd(path, err) if (err%error()) then print *, "Error getting current working directory after using set_cwd: "//err%print() end if print *, "CWD: "//path end program example_cwd fortran-lang-stdlib-0ede301/example/system/example_is_symlink.f900000664000175000017500000000115415135654166025362 0ustar alastairalastair! Demonstrate usage of `is_symlink` program example_is_symlink use stdlib_system, only: is_symlink, is_directory implicit none character(*), parameter :: path = "path/to/check" ! Test if path is a symbolic link if (is_symlink(path)) then print *, "The specified path is a symlink." ! Further check if it is linked to a file or a directory if (is_directory(path)) then print *, "Further, it is a link to a directory." else print *, "Further, it is a link to a file." end if else print *, "The specified path is not a symlink." end if end program example_is_symlink fortran-lang-stdlib-0ede301/example/system/example_process_4.f900000664000175000017500000000177015135654166025106 0ustar alastairalastair! Process example 4: Kill a running process program example_process_kill use stdlib_system, only: process_type, runasync, is_running, kill, elapsed, is_windows, sleep implicit none type(process_type) :: process logical :: running, success print *, "Starting a long-running process..." if (is_windows()) then process = runasync("ping -n 10 127.0.0.1") else process = runasync("ping -c 10 127.0.0.1") endif ! Verify the process is running running = is_running(process) print *, "Process running:", running ! Wait a bit before killing the process call sleep(millisec=250) print *, "Killing the process..." call kill(process, success) if (success) then print *, "Process killed successfully." else print *, "Failed to kill the process." endif ! Verify the process is no longer running running = is_running(process) print *, "Process running after kill:", running end program example_process_kill fortran-lang-stdlib-0ede301/example/system/example_process_6.f900000664000175000017500000000326515135654166025111 0ustar alastairalastair! Process example 6: Demonstrate callback program example_process_6 use stdlib_system, only: process_type, process_ID, run, is_running, kill, elapsed, is_windows, sleep implicit none type(process_type) :: p integer, target :: nfiles ! Run process, attach callback function and some data if (is_windows()) then p = run("dir",want_stdout=.true.,callback=get_dir_nfiles) else p = run("ls -l",want_stdout=.true.,callback=get_dir_nfiles,payload=nfiles) endif ! On exit, the number of files should have been extracted by the callback function print *, "Current directory has ",nfiles," files" contains ! Custom callback function: retrieve number of files from ls output subroutine get_dir_nfiles(pid, exit_state, stdin, stdout, stderr, payload) integer(process_ID), intent(in) :: pid integer, intent(in) :: exit_state character(len=*), optional, intent(in) :: stdin, stdout, stderr class(*), optional, intent(inout) :: payload integer :: i if (present(payload)) then select type (nfiles => payload) type is (integer) if (present(stdout)) then nfiles = count([ (stdout(i:i) == char(10), i=1,len(stdout)) ]) else nfiles = -1 endif class default error stop 'Wrong payload passed to the process' end select end if end subroutine get_dir_nfiles end program example_process_6 fortran-lang-stdlib-0ede301/example/system/example_exists.f900000664000175000017500000000152415135654166024521 0ustar alastairalastair! Illustrate the usage of `exists` program example_exists use stdlib_system, only: exists, fs_type_unknown, fs_type_regular_file, & fs_type_directory, fs_type_symlink use stdlib_error, only: state_type implicit none type(state_type) :: err ! Path to check character(*), parameter :: path = "path/to/check" ! To get the type of the path integer :: t t = exists(path, err) if (err%error()) then ! An error occured, print it print *, err%print() end if ! switching on the type returned by `exists` select case (t) case (fs_type_unknown); print *, "Unknown type!" case (fs_type_regular_file); print *, "Regular File!" case (fs_type_directory); print *, "Directory!" case (fs_type_symlink); print *, "Symbolic Link!" end select end program example_exists fortran-lang-stdlib-0ede301/example/system/example_path_split_path.f900000664000175000017500000000161215135654166026363 0ustar alastairalastair! Usage of split_path program example_path_split_path use stdlib_system, only: join_path, split_path, OS_TYPE, OS_WINDOWS character(len=:), allocatable :: p1, head, tail if(OS_TYPE() == OS_WINDOWS) then p1 = join_path('C:\Users\User1', 'Desktop') ! C:\Users\User1\Desktop else p1 = join_path('/home/User1', 'Desktop') ! /home/User1/Desktop endif call split_path(p1, head, tail) ! head = /home/User1 OR C:\Users\User1, tail = Desktop print *, p1 // " -> " // head // " + " // tail ! C:\Users\User1\Desktop -> C:\Users\User1 + Desktop ! OR ! /home/User1/Desktop -> /home/User1 + Desktop call split_path(head, p1, tail) ! p1 = /home OR C:\Users, tail = User1 print *, head // " -> " // p1 // " + " // tail ! C:\Users\User1 -> C:\Users + User1 ! OR ! /home/User1 -> /home + User1 end program example_path_split_path fortran-lang-stdlib-0ede301/example/system/example_is_directory.f900000664000175000017500000000053215135654166025677 0ustar alastairalastair! Demonstrate usage of `is_directory` program example_is_directory use stdlib_system, only: is_directory implicit none ! Test a directory path if (is_directory("/path/to/check")) then print *, "The specified path is a directory." else print *, "The specified path is not a directory." end if end program example_is_directory fortran-lang-stdlib-0ede301/example/system/example_process_2.f900000664000175000017500000000114015135654166025073 0ustar alastairalastair! Process example 2: Run an Asynchronous Command and check its status program run_async use stdlib_system, only: process_type, runasync, is_running, wait implicit none type(process_type) :: p ! Run an asynchronous process to sleep for 1 second p = runasync("sleep 1") ! Check if the process is running if (is_running(p)) then print *, "Process is running." else print *, "Process has already completed." end if ! Wait for the process to complete call wait(p, max_wait_time = 5.0) print *, "Process has now completed." end program run_async fortran-lang-stdlib-0ede301/example/random/0000775000175000017500000000000015135654166021101 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/random/example_dist_rand.f900000664000175000017500000000115015135654166025100 0ustar alastairalastairprogram example_dist_rand use stdlib_kinds, only: int8, int16, int32, int64 use stdlib_random, only: dist_rand, random_seed implicit none integer :: put, get put = 135792468 call random_seed(put, get) ! set and get current value of seed print *, dist_rand(1_int8) ! random integer in [-2^7, 2^7 - 1] ! -90 print *, dist_rand(1_int16) ! random integer in [-2^15, 2^15 - 1] ! -32725 print *, dist_rand(1_int32) ! random integer in [-2^31, 2^31 - 1] ! -1601563881 print *, dist_rand(1_int64) ! random integer in [-2^63, 2^63 - 1] ! 180977695517992208 end program example_dist_rand fortran-lang-stdlib-0ede301/example/random/example_random_seed.f900000664000175000017500000000037015135654166025414 0ustar alastairalastairprogram example_random_seed use stdlib_random, only: random_seed implicit none integer :: seed_put, seed_get seed_put = 1234567 call random_seed(seed_put, seed_get) ! set and get current value of seed end program example_random_seed fortran-lang-stdlib-0ede301/example/random/CMakeLists.txt0000664000175000017500000000006015135654166023635 0ustar alastairalastairADD_EXAMPLE(dist_rand) ADD_EXAMPLE(random_seed) fortran-lang-stdlib-0ede301/example/intrinsics/0000775000175000017500000000000015135654166022006 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/intrinsics/example_sum.f900000664000175000017500000000074115135654166024647 0ustar alastairalastairprogram example_sum use stdlib_kinds, only: sp use stdlib_intrinsics, only: stdlib_sum, stdlib_sum_kahan implicit none real(sp), allocatable :: x(:) real(sp) :: total_sum(3) allocate( x(1000) ) call random_number(x) total_sum(1) = sum(x) !> compiler intrinsic total_sum(2) = stdlib_sum(x) !> chunked summation total_sum(3) = stdlib_sum_kahan(x)!> chunked kahan summation print *, total_sum(1:3) end program example_sumfortran-lang-stdlib-0ede301/example/intrinsics/example_matmul.f900000664000175000017500000000112515135654166025337 0ustar alastairalastairprogram example_matmul use stdlib_intrinsics, only: stdlib_matmul complex :: x(2, 2), y(2, 2), z(2, 2) x = reshape([(0, 0), (1, 0), (1, 0), (0, 0)], [2, 2]) ! pauli x-matrix y = reshape([(0, 0), (0, 1), (0, -1), (0, 0)], [2, 2]) ! pauli y-matrix z = reshape([(1, 0), (0, 0), (0, 0), (-1, 0)], [2, 2]) ! pauli z-matrix print *, stdlib_matmul(x, y) ! should be iota*z print *, stdlib_matmul(y, z, x) ! should be iota*identity print *, stdlib_matmul(x, x, z, y) ! should be -iota*x print *, stdlib_matmul(x, x, z, y, y) ! should be z end program example_matmul fortran-lang-stdlib-0ede301/example/intrinsics/example_dot_product.f900000664000175000017500000000115715135654166026373 0ustar alastairalastairprogram example_dot_product use stdlib_kinds, only: sp use stdlib_intrinsics, only: stdlib_dot_product, stdlib_dot_product_kahan implicit none real(sp), allocatable :: x(:), y(:) real(sp) :: total_prod(3) allocate( x(1000), y(1000) ) call random_number(x) call random_number(y) total_prod(1) = dot_product(x,y) !> compiler intrinsic total_prod(2) = stdlib_dot_product(x,y) !> chunked summation over inner product total_prod(3) = stdlib_dot_product_kahan(x,y) !> chunked kahan summation over inner product print *, total_prod(1:3) end program example_dot_productfortran-lang-stdlib-0ede301/example/intrinsics/CMakeLists.txt0000664000175000017500000000007615135654166024551 0ustar alastairalastairADD_EXAMPLE(sum) ADD_EXAMPLE(dot_product) ADD_EXAMPLE(matmul) fortran-lang-stdlib-0ede301/example/bitsets/0000775000175000017500000000000015135654166021276 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_bit_count.f900000664000175000017500000000133115135654166027052 0ustar alastairalastairprogram example_bit_count use stdlib_bitsets implicit none character(*), parameter :: & bits_0 = '0000000000000000000' type(bitset_64) :: set0 type(bitset_large) :: set1 logical, allocatable :: logi(:) call set0%from_string(bits_0) if (set0%bit_count() == 0) then write (*, *) "FROM_STRING interpreted "// & "BITS_0's value properly." end if call set0%set(5) if (set0%bit_count() == 1) then write (*, *) "BIT_COUNT interpreted SET0's value properly." end if allocate( logi(1000), source=.false.) logi(1::7) = .true. set1 = logi if (set1%bit_count() == count(logi)) then write (*, *) "BIT_COUNT interpreted SET1's value properly." end if end program example_bit_count fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_all.f900000664000175000017500000000067115135654166025642 0ustar alastairalastairprogram example_all use stdlib_bitsets implicit none character(*), parameter :: & bits_all = '111111111111111111111111111111111' type(bitset_64) :: set0 call set0%from_string(bits_all) if (.not. set0%all()) then error stop "FROM_STRING failed to interpret"// & "BITS_ALL's value properly." else write (*, *) "FROM_STRING transferred BITS_ALL properly"// & " into set0." end if end program example_all fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_bits.f900000664000175000017500000000050615135654166026030 0ustar alastairalastairprogram example_bits use stdlib_bitsets implicit none character(*), parameter :: & bits_0 = '0000000000000000000' type(bitset_64) :: set0 call set0%from_string(bits_0) if (set0%bits() == 19) then write (*, *) "FROM_STRING interpreted "// & "BITS_0's size properly." end if end program example_bits fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_inequality.f900000664000175000017500000000077115135654166027257 0ustar alastairalastairprogram example_inequality use stdlib_bitsets implicit none type(bitset_64) :: set0, set1, set2 call set0%init(33) call set1%init(33) call set2%init(33) call set1%set(0) call set2%set(32) if (set0 /= set1 .and. set0 /= set2 .and. set1 /= set2 .and. & .not. set0 /= set0 .and. .not. set1 /= set1 .and. .not. & set2 /= set2) then write (*, *) 'Passed 64 bit inequality tests.' else error stop 'Failed 64 bit inequality tests.' end if end program example_inequality fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_from_string.f900000664000175000017500000000110315135654166027412 0ustar alastairalastairprogram example_from_string use stdlib_bitsets implicit none character(*), parameter :: & bits_all = '111111111111111111111111111111111' type(bitset_64) :: set0 call set0%from_string(bits_all) if (bits(set0) /= 33) then error stop "FROM_STRING failed to interpret "// & "BITS_ALL's size properly." else if (.not. set0%all()) then error stop "FROM_STRING failed to interpret"// & "BITS_ALL's value properly." else write (*, *) "FROM_STRING transferred BITS_ALL properly"// & " into set0." end if end program example_from_string fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_and.f900000664000175000017500000000111715135654166025630 0ustar alastairalastairprogram example_and use stdlib_bitsets implicit none type(bitset_large) :: set0, set1 call set0%init(166) call set1%init(166) call and(set0, set1) ! none none if (set0%none()) write (*, *) 'First test of AND worked.' call set0%not() call and(set0, set1) ! all none if (set0%none()) write (*, *) 'Second test of AND worked.' call set1%not() call and(set0, set1) ! none all if (set0%none()) write (*, *) 'Third test of AND worked.' call set0%not() call and(set0, set1) ! all all if (set0%all()) write (*, *) 'Fourth test of AND worked.' end program example_and fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_input.f900000664000175000017500000000206615135654166026231 0ustar alastairalastairprogram example_input use stdlib_bitsets implicit none character(*), parameter :: & bits_0 = '000000000000000000000000000000000', & bits_1 = '000000000000000000000000000000001', & bits_33 = '100000000000000000000000000000000' integer :: unit type(bitset_64) :: set0, set1, set2, set3, set4, set5 call set0%from_string(bits_0) call set1%from_string(bits_1) call set2%from_string(bits_33) open (newunit=unit, file='test.bin', status='replace', & form='unformatted', action='write') call set2%output(unit) call set1%output(unit) call set0%output(unit) close (unit) open (newunit=unit, file='test.bin', status='old', & form='unformatted', action='read') call set5%input(unit) call set4%input(unit) call set3%input(unit) close (unit) if (set3 /= set0 .or. set4 /= set1 .or. set5 /= set2) then error stop 'Transfer to and from units using '// & ' output and input failed.' else write (*, *) 'Transfer to and from units using '// & 'output and input succeeded.' end if end program example_input fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_test.f900000664000175000017500000000056715135654166026055 0ustar alastairalastairprogram example_test use stdlib_bitsets implicit none type(bitset_large) :: set0 call set0%init(166) call set0%not() if (set0%all()) write (*, *) 'SET0 is properly initialized.' call set0%clear(165) if (.not. set0%test(165)) write (*, *) 'Bit 165 is cleared.' call set0%set(165) if (set0%test(165)) write (*, *) 'Bit 165 is set.' end program example_test fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_set.f900000664000175000017500000000053115135654166025660 0ustar alastairalastairprogram example_set use stdlib_bitsets implicit none type(bitset_large) :: set0 call set0%init(166) if (set0%none()) write (*, *) 'SET0 is properly initialized.' call set0%set(165) if (set0%test(165)) write (*, *) 'Bit 165 is set.' call set0%set(0, 164) if (set0%all()) write (*, *) 'All bits are set.' end program example_set fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_not.f900000664000175000017500000000054215135654166025667 0ustar alastairalastairprogram example_not use stdlib_bitsets implicit none type(bitset_large) :: set0 call set0%init(155) if (set0%none()) then write (*, *) "FROM_STRING interpreted "// & "BITS_0's value properly." end if call set0%not() if (set0%all()) then write (*, *) "ALL interpreted SET0's value properly." end if end program example_not fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_read_bitset.f900000664000175000017500000000261215135654166027354 0ustar alastairalastairprogram example_read_bitset use stdlib_bitsets implicit none character(*), parameter :: & bits_0 = 'S33B000000000000000000000000000000000', & bits_1 = 'S33B000000000000000000000000000000001', & bits_2 = 'S33B100000000000000000000000000000000' character(:), allocatable :: test_0, test_1, test_2 integer :: unit, status type(bitset_64) :: set0, set1, set2, set3, set4, set5 call set0%read_bitset(bits_0, status) call set1%read_bitset(bits_1, status) call set2%read_bitset(bits_2, status) call set0%write_bitset(test_0, status) call set1%write_bitset(test_1, status) call set2%write_bitset(test_2, status) if (bits_0 == test_0 .and. bits_1 == test_1 .and. & bits_2 == test_2) then write (*, *) 'READ_BITSET to WRITE_BITSET strings worked.' end if open (newunit=unit, file='test.txt', status='replace', & form='formatted', action='write') call set2%write_bitset(unit, advance='no') call set1%write_bitset(unit, advance='no') call set0%write_bitset(unit) close (unit) open (newunit=unit, file='test.txt', status='old', & form='formatted', action='read') call set3%read_bitset(unit, advance='no') call set4%read_bitset(unit, advance='no') call set5%read_bitset(unit) if (set3 == set0 .and. set4 == set1 .and. set5 == set2) then write (*, *) 'WRITE_BITSET to READ_BITSET through unit worked.' end if end program example_read_bitset fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_to_string.f900000664000175000017500000000067615135654166027107 0ustar alastairalastairprogram example_to_string use stdlib_bitsets implicit none character(*), parameter :: & bits_all = '111111111111111111111111111111111' type(bitset_64) :: set0 character(:), allocatable :: new_string call set0%init(33) call set0%not() call set0%to_string(new_string) if (new_string == bits_all) then write (*, *) "TO_STRING transferred BITS0 properly"// & " into NEW_STRING." end if end program example_to_string fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_equality.f900000664000175000017500000000076115135654166026727 0ustar alastairalastairprogram example_equality use stdlib_bitsets implicit none type(bitset_64) :: set0, set1, set2 call set0%init(33) call set1%init(33) call set2%init(33) call set1%set(0) call set2%set(32) if (set0 == set0 .and. set1 == set1 .and. set2 == set2 .and. & .not. set0 == set1 .and. .not. set0 == set2 .and. .not. & set1 == set2) then write (*, *) 'Passed 64 bit equality tests.' else error stop 'Failed 64 bit equality tests.' end if end program example_equality fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_and_not.f900000664000175000017500000000121115135654166026503 0ustar alastairalastairprogram example_and_not use stdlib_bitsets implicit none type(bitset_large) :: set0, set1 call set0%init(166) call set1%init(166) call and_not(set0, set1) ! none none if (set0%none()) write (*, *) 'First test of AND_NOT worked.' call set0%not() call and_not(set0, set1) ! all none if (set0%all()) write (*, *) 'Second test of AND_NOT worked.' call set0%not() call set1%not() call and_not(set0, set1) ! none all if (set0%none()) write (*, *) 'Third test of AND_NOT worked.' call set0%not() call and_not(set0, set1) ! all all if (set0%none()) write (*, *) 'Fourth test of AND_NOT worked.' end program example_and_not fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_assignment.f900000664000175000017500000000147015135654166027240 0ustar alastairalastairprogram example_assignment use stdlib_bitsets use stdlib_kinds, only: int8, int32 implicit none logical(int8) :: logical1(64) = .true. logical(int32), allocatable :: logical2(:) type(bitset_64) :: set0, set1 set0 = logical1 if (set0%bits() /= 64) then error stop & ' initialization with logical(int8) failed to set'// & ' the right size.' else if (.not. set0%all()) then error stop ' initialization with'// & ' logical(int8) failed to set the right values.' else write (*, *) 'Initialization with logical(int8) succeeded.' end if set1 = set0 if (set1 == set0) & write (*, *) 'Initialization by assignment succeeded' logical2 = set1 if (all(logical2)) then write (*, *) 'Initialization of logical(int32) succeeded.' end if end program example_assignment fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_init.f900000664000175000017500000000041715135654166026033 0ustar alastairalastairprogram example_init use stdlib_bitsets implicit none type(bitset_large) :: set0 call set0%init(166) if (set0%bits() == 166) & write (*, *) 'SET0 has the proper size.' if (set0%none()) write (*, *) 'SET0 is properly initialized.' end program example_init fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_write_bitset.f900000664000175000017500000000261415135654166027575 0ustar alastairalastairprogram example_write_bitset use stdlib_bitsets implicit none character(*), parameter :: & bits_0 = 'S33B000000000000000000000000000000000', & bits_1 = 'S33B000000000000000000000000000000001', & bits_2 = 'S33B100000000000000000000000000000000' character(:), allocatable :: test_0, test_1, test_2 integer :: unit, status type(bitset_64) :: set0, set1, set2, set3, set4, set5 call set0%read_bitset(bits_0, status) call set1%read_bitset(bits_1, status) call set2%read_bitset(bits_2, status) call set0%write_bitset(test_0, status) call set1%write_bitset(test_1, status) call set2%write_bitset(test_2, status) if (bits_0 == test_0 .and. bits_1 == test_1 .and. & bits_2 == test_2) then write (*, *) 'READ_BITSET to WRITE_BITSET strings worked.' end if open (newunit=unit, file='test.txt', status='replace', & form='formatted', action='write') call set2%write_bitset(unit, advance='no') call set1%write_bitset(unit, advance='no') call set0%write_bitset(unit) close (unit) open (newunit=unit, file='test.txt', status='old', & form='formatted', action='read') call set3%read_bitset(unit, advance='no') call set4%read_bitset(unit, advance='no') call set5%read_bitset(unit) if (set3 == set0 .and. set4 == set1 .and. set5 == set2) then write (*, *) 'WRITE_BITSET to READ_BITSET through unit worked.' end if end program example_write_bitset fortran-lang-stdlib-0ede301/example/bitsets/CMakeLists.txt0000664000175000017500000000146715135654166024046 0ustar alastairalastairADD_EXAMPLE(bitsets_all) ADD_EXAMPLE(bitsets_and) ADD_EXAMPLE(bitsets_and_not) ADD_EXAMPLE(bitsets_any) ADD_EXAMPLE(bitsets_assignment) ADD_EXAMPLE(bitsets_bit_count) ADD_EXAMPLE(bitsets_bits) ADD_EXAMPLE(bitsets_clear) ADD_EXAMPLE(bitsets_equality) ADD_EXAMPLE(bitsets_extract) ADD_EXAMPLE(bitsets_flip) ADD_EXAMPLE(bitsets_from_string) ADD_EXAMPLE(bitsets_ge) ADD_EXAMPLE(bitsets_gt) ADD_EXAMPLE(bitsets_inequality) ADD_EXAMPLE(bitsets_init) ADD_EXAMPLE(bitsets_input) ADD_EXAMPLE(bitsets_le) ADD_EXAMPLE(bitsets_lt) ADD_EXAMPLE(bitsets_none) ADD_EXAMPLE(bitsets_not) ADD_EXAMPLE(bitsets_or) ADD_EXAMPLE(bitsets_output) ADD_EXAMPLE(bitsets_read_bitset) ADD_EXAMPLE(bitsets_set) ADD_EXAMPLE(bitsets_test) ADD_EXAMPLE(bitsets_to_string) ADD_EXAMPLE(bitsets_value) ADD_EXAMPLE(bitsets_write_bitset) ADD_EXAMPLE(bitsets_xor) fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_le.f900000664000175000017500000000107215135654166025466 0ustar alastairalastairprogram example_le use stdlib_bitsets implicit none type(bitset_64) :: set0, set1, set2 call set0%init(33) call set1%init(33) call set2%init(33) call set1%set(0) call set2%set(32) if (set0 <= set1 .and. set1 <= set2 .and. set0 <= set2 .and. & set0 <= set0 .and. set1 <= set1 .and. set2 <= set2 .and. & .not. set1 <= set0 .and. .not. set2 <= set0 .and. .not. & set2 <= set1) then write (*, *) 'Passed 64 bit less than or equal tests.' else error stop 'Failed 64 bit less than or equal tests.' end if end program example_le fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_output.f900000664000175000017500000000207015135654166026425 0ustar alastairalastairprogram example_output use stdlib_bitsets implicit none character(*), parameter :: & bits_0 = '000000000000000000000000000000000', & bits_1 = '000000000000000000000000000000001', & bits_33 = '100000000000000000000000000000000' integer :: unit type(bitset_64) :: set0, set1, set2, set3, set4, set5 call set0%from_string(bits_0) call set1%from_string(bits_1) call set2%from_string(bits_33) open (newunit=unit, file='test.bin', status='replace', & form='unformatted', action='write') call set2%output(unit) call set1%output(unit) call set0%output(unit) close (unit) open (newunit=unit, file='test.bin', status='old', & form='unformatted', action='read') call set5%input(unit) call set4%input(unit) call set3%input(unit) close (unit) if (set3 /= set0 .or. set4 /= set1 .or. set5 /= set2) then error stop 'Transfer to and from units using '// & ' output and input failed.' else write (*, *) 'Transfer to and from units using '// & 'output and input succeeded.' end if end program example_output fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_gt.f900000664000175000017500000000074715135654166025510 0ustar alastairalastairprogram example_gt use stdlib_bitsets implicit none type(bitset_64) :: set0, set1, set2 call set0%init(33) call set1%init(33) call set2%init(33) call set1%set(0) call set2%set(32) if (set1 > set0 .and. set2 > set1 .and. set2 > set0 .and. & .not. set0 > set0 .and. .not. set0 > set1 .and. .not. & set1 > set2) then write (*, *) 'Passed 64 bit greater than tests.' else error stop 'Failed 64 bit greater than tests.' end if end program example_gt fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_or.f900000664000175000017500000000112515135654166025505 0ustar alastairalastairprogram example_or use stdlib_bitsets implicit none type(bitset_large) :: set0, set1 call set0%init(166) call set1%init(166) call or(set0, set1) ! none none if (set0%none()) write (*, *) 'First test of OR worked.' call set0%not() call or(set0, set1) ! all none if (set0%all()) write (*, *) 'Second test of OR worked.' call set0%not() call set1%not() call or(set0, set1) ! none all if (set0%all()) write (*, *) 'Third test of OR worked.' call set0%not() call or(set0, set1) ! all all if (set0%all()) write (*, *) 'Fourth test of OR worked.' end program example_or fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_extract.f900000664000175000017500000000052615135654166026543 0ustar alastairalastairprogram example_extract use stdlib_bitsets implicit none type(bitset_large) :: set0, set1 call set0%init(166) call set0%set(100, 150) call extract(set1, set0, 100, 150) if (set1%bits() == 51) & write (*, *) 'SET1 has the proper size.' if (set1%all()) write (*, *) 'SET1 has the proper values.' end program example_extract fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_value.f900000664000175000017500000000057715135654166026213 0ustar alastairalastairprogram example_value use stdlib_bitsets implicit none type(bitset_large) :: set0 call set0%init(166) call set0%not() if (set0%all()) write (*, *) 'SET0 is properly initialized.' call set0%clear(165) if (set0%value(165) == 0) write (*, *) 'Bit 165 is cleared.' call set0%set(165) if (set0%value(165) == 1) write (*, *) 'Bit 165 is set.' end program example_value fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_lt.f900000664000175000017500000000074115135654166025507 0ustar alastairalastairprogram example_lt use stdlib_bitsets implicit none type(bitset_64) :: set0, set1, set2 call set0%init(33) call set1%init(33) call set2%init(33) call set1%set(0) call set2%set(32) if (set0 < set1 .and. set1 < set2 .and. set0 < set2 .and. & .not. set0 < set0 .and. .not. set2 < set0 .and. .not. & set2 < set1) then write (*, *) 'Passed 64 bit less than tests.' else error stop 'Failed 64 bit less than tests.' end if end program example_lt fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_none.f900000664000175000017500000000067115135654166026031 0ustar alastairalastairprogram example_none use stdlib_bitsets implicit none character(*), parameter :: & bits_0 = '0000000000000000000' type(bitset_large) :: set0 call set0%from_string(bits_0) if (set0%none()) then write (*, *) "FROM_STRING interpreted "// & "BITS_0's value properly." end if call set0%set(5) if (.not. set0%none()) then write (*, *) "NONE interpreted SET0's value properly." end if end program example_none fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_xor.f900000664000175000017500000000114015135654166025672 0ustar alastairalastairprogram example_xor use stdlib_bitsets implicit none type(bitset_large) :: set0, set1 call set0%init(166) call set1%init(166) call xor(set0, set1) ! none none if (set0%none()) write (*, *) 'First test of XOR worked.' call set0%not() call xor(set0, set1) ! all none if (set0%all()) write (*, *) 'Second test of XOR worked.' call set0%not() call set1%not() call xor(set0, set1) ! none all if (set0%all()) write (*, *) 'Third test of XOR worked.' call set0%not() call xor(set0, set1) ! all all if (set0%none()) write (*, *) 'Fourth test of XOR worked.' end program example_xor fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_flip.f900000664000175000017500000000054515135654166026024 0ustar alastairalastairprogram example_flip use stdlib_bitsets implicit none type(bitset_large) :: set0 call set0%init(166) if (set0%none()) write (*, *) 'SET0 is properly initialized.' call set0%flip(165) if (set0%test(165)) write (*, *) 'Bit 165 is flipped.' call set0%flip(0, 164) if (set0%all()) write (*, *) 'All bits are flipped.' end program example_flip fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_clear.f900000664000175000017500000000060115135654166026151 0ustar alastairalastairprogram example_clear use stdlib_bitsets implicit none type(bitset_large) :: set0 call set0%init(166) call set0%not() if (set0%all()) write (*, *) 'SET0 is properly initialized.' call set0%clear(165) if (.not. set0%test(165)) write (*, *) 'Bit 165 is cleared.' call set0%clear(0, 164) if (set0%none()) write (*, *) 'All bits are cleared.' end program example_clear fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_ge.f900000664000175000017500000000110215135654166025453 0ustar alastairalastairprogram example_ge use stdlib_bitsets implicit none type(bitset_64) :: set0, set1, set2 call set0%init(33) call set1%init(33) call set2%init(33) call set1%set(0) call set2%set(32) if (set1 >= set0 .and. set2 >= set1 .and. set2 >= set0 .and. & set0 >= set0 .and. set1 >= set1 .and. set2 >= set2 .and. & .not. set0 >= set1 .and. .not. set0 >= set2 .and. .not. & set1 >= set2) then write (*, *) 'Passed 64 bit greater than or equals tests.' else error stop 'Failed 64 bit greater than or equals tests.' end if end program example_ge fortran-lang-stdlib-0ede301/example/bitsets/example_bitsets_any.f900000664000175000017500000000066115135654166025660 0ustar alastairalastairprogram example_any use stdlib_bitsets implicit none character(*), parameter :: & bits_0 = '0000000000000000000' type(bitset_64) :: set0 call set0%from_string(bits_0) if (.not. set0%any()) then write (*, *) "FROM_STRING interpreted "// & "BITS_0's value properly." end if call set0%set(5) if (set0%any()) then write (*, *) "ANY interpreted SET0's value properly." end if end program example_any fortran-lang-stdlib-0ede301/example/strings/0000775000175000017500000000000015135654166021312 5ustar alastairalastairfortran-lang-stdlib-0ede301/example/strings/example_replace_all.f900000664000175000017500000000113115135654166025604 0ustar alastairalastairprogram example_replace_all use stdlib_string_type, only: string_type, assignment(=), write (formatted) use stdlib_strings, only: replace_all implicit none type(string_type) :: string string = "hurdles here, hurdles there, hurdles everywhere" ! string <-- "hurdles here, hurdles there, hurdles everywhere" print'(dt)', replace_all(string, "hurdles", "learn from") ! "learn from here, learn from there, learn from everywhere" string = replace_all(string, "hurdles", "technology") ! string <-- "technology here, technology there, technology everywhere" end program example_replace_all fortran-lang-stdlib-0ede301/example/strings/example_to_c_char.f900000664000175000017500000000104615135654166025267 0ustar alastairalastairprogram example_to_c_char use stdlib_strings, only: to_c_char use stdlib_string_type, only: string_type use stdlib_kinds, only: c_char implicit none character(kind=c_char), allocatable :: cstr(:),cstr2(:) character(*), parameter :: hello = "Hello, World!" ! Convert character array cstr = to_c_char(hello) ! Convert string type cstr2 = to_c_char(string_type(hello)) if (size(cstr)/=size(cstr2) .or. .not.all(cstr==cstr2)) then error stop 'String conversion error' end if end program example_to_c_char fortran-lang-stdlib-0ede301/example/strings/example_find.f900000664000175000017500000000064615135654166024273 0ustar alastairalastairprogram example_find use stdlib_string_type, only: string_type, assignment(=) use stdlib_strings, only: find implicit none type(string_type) :: string string = "needle in the character-stack" print *, find(string, "needle") ! 1 print *, find(string, ["a", "c"], [3, 2]) ! [27, 20] print *, find("qwqwqwq", "qwq", 3, [.false., .true.]) ! [0, 5] end program example_find fortran-lang-stdlib-0ede301/example/strings/example_zfill.f900000664000175000017500000000071215135654166024465 0ustar alastairalastairprogram example_zfill use stdlib_string_type, only: string_type, assignment(=), write (formatted) use stdlib_strings, only: zfill implicit none type(string_type) :: string string = "left pad this string with zeros" ! string <-- "left pad this string with zeros" print '(dt)', zfill(string, 36) ! "00000left pad this string with zeros" string = zfill(string, 36) ! string <-- "00000left pad this string with zeros" end program example_zfill fortran-lang-stdlib-0ede301/example/strings/example_to_string.f900000664000175000017500000000244115135654166025356 0ustar alastairalastairprogram example_to_string use stdlib_strings, only: to_string implicit none !> Example for `complex` type print *, to_string((1, 1)) !! "(1.00000000,1.00000000)" print *, to_string((1, 1), '(F6.2)') !! "( 1.00, 1.00)" print *, to_string((1000, 1), '(ES0.2)'), to_string((1000, 1), '(SP,F6.3)') !! "(1.00E+3,1.00)""(******,+1.000)" !! Too narrow formatter for real number !! Normal demonstration(`******` from Fortran Standard) !> Example for `integer` type print *, to_string(-3) !! "-3" print *, to_string(42, '(I4)') !! " 42" print *, to_string(1, '(I0.4)'), to_string(2, '(B4)') !! "0001"" 10" !> Example for `real` type print *, to_string(1.) !! "1.00000000" print *, to_string(1., '(F6.2)') !! " 1.00" print *, to_string(1., 'F6.2') !! " 1.00" print *, to_string(1., '(SP,ES9.2)'), to_string(1, '(F7.3)') !! "+1.00E+00""[*]" !! 1 wrong demonstration (`[*]` from `to_string`) !> Example for `logical` type print *, to_string(.true.) !! "T" print *, to_string(.true., '(L2)') !! " T" print *, to_string(.true., 'L2') !! " T" print *, to_string(.false., '(I5)') !! "[*]" !! 1 wrong demonstrations(`[*]` from `to_string`) end program example_to_string fortran-lang-stdlib-0ede301/example/strings/example_string_to_number.f900000664000175000017500000000042215135654166026723 0ustar alastairalastairprogram example_string_to_number use stdlib_kinds, only: dp use stdlib_str2num, only: to_num implicit none character(:), allocatable :: txt real(dp) :: x txt = ' 8.8541878128e−12 ' x = to_num( txt , x ) end program example_string_to_numberfortran-lang-stdlib-0ede301/example/strings/example_chomp.f900000664000175000017500000000121015135654166024445 0ustar alastairalastairprogram example_chomp use stdlib_ascii, only: TAB, VT, LF, CR, FF use stdlib_strings, only: chomp implicit none print'(a)', chomp(" hello ") ! " hello" print'(a)', chomp(TAB//"goodbye"//CR//LF) ! "\tgoodbye" print'(a)', chomp(" "//TAB//LF//VT//FF//CR) ! "" print'(a)', chomp(" ! ")//"!" ! " !!" print'(a)', chomp("Hello") ! "Hello" print'(a)', chomp("hello", ["l", "o"]) ! "he" print'(a)', chomp("hello", set=["l", "o"]) ! "he" print'(a)', chomp("hello", "lo") ! "hel" print'(a)', chomp("hello", substring="lo") ! "hel" end program example_chomp fortran-lang-stdlib-0ede301/example/strings/example_ends_with.f900000664000175000017500000000031615135654166025331 0ustar alastairalastairprogram example_ends_with use stdlib_strings, only: ends_with implicit none print'(l1)', ends_with("pattern", "ern") ! T print'(l1)', ends_with("pattern", "pat") ! F end program example_ends_with fortran-lang-stdlib-0ede301/example/strings/CMakeLists.txt0000664000175000017500000000054615135654166024057 0ustar alastairalastairADD_EXAMPLE(chomp) ADD_EXAMPLE(count) ADD_EXAMPLE(ends_with) ADD_EXAMPLE(find) ADD_EXAMPLE(join) ADD_EXAMPLE(padl) ADD_EXAMPLE(padr) ADD_EXAMPLE(replace_all) ADD_EXAMPLE(slice) ADD_EXAMPLE(starts_with) ADD_EXAMPLE(strip) ADD_EXAMPLE(to_string) ADD_EXAMPLE(to_c_char) ADD_EXAMPLE(zfill) ADD_EXAMPLE(string_to_number) ADD_EXAMPLE(stream_of_strings_to_numbers) fortran-lang-stdlib-0ede301/example/strings/example_padl.f900000664000175000017500000000063615135654166024272 0ustar alastairalastairprogram example_padl use stdlib_string_type, only: string_type, assignment(=), write (formatted) use stdlib_strings, only: padl implicit none type(string_type) :: string string = "left pad this string" ! string <-- "left pad this string" print '(dt)', padl(string, 25, "$") ! "$$$$$left pad this string" string = padl(string, 25) ! string <-- " left pad this string" end program example_padl fortran-lang-stdlib-0ede301/example/strings/example_padr.f900000664000175000017500000000064015135654166024273 0ustar alastairalastairprogram example_padr use stdlib_string_type, only: string_type, assignment(=), write (formatted) use stdlib_strings, only: padr implicit none type(string_type) :: string string = "right pad this string" ! string <-- "right pad this string" print '(dt)', padr(string, 25, "$") ! "right pad this string$$$$" string = padr(string, 25) ! string <-- "right pad this string " end program example_padr fortran-lang-stdlib-0ede301/example/strings/example_stream_of_strings_to_numbers.f900000664000175000017500000000141015135654166031326 0ustar alastairalastairprogram example_stream_of_strings_to_numbers use stdlib_kinds, only: dp use stdlib_str2num, only: to_num_from_stream implicit none character(:), allocatable, target :: chain character(len=:), pointer :: cptr real(dp), allocatable :: r(:), p(:) integer :: i chain = " 1.234 1.E1 1e0 0.1234E0 12.21e+001 -34.5E1" allocate( r(6), p(6) ) !> Example for streamline conversion using `to_num_from_stream` cptr => chain do i =1, 6 r(i) = to_num_from_stream( cptr , r(i) ) !> the pointer is shifted within the function end do read(chain,*) p print *, "Reading with to_num_from_stream" print *, r print *, "Reading with formatted read" print *, p end program example_stream_of_strings_to_numbers fortran-lang-stdlib-0ede301/example/strings/example_strip.f900000664000175000017500000000064715135654166024515 0ustar alastairalastairprogram example_strip use stdlib_ascii, only: TAB, VT, LF, CR, FF use stdlib_strings, only: strip implicit none print'(a)', strip(" hello ") ! "hello" print'(a)', strip(TAB//"goodbye"//CR//LF) ! "goodbye" print'(a)', strip(" "//TAB//LF//VT//FF//CR) ! "" print'(a)', strip(" ! ")//"!" ! "!!" print'(a)', strip("Hello") ! "Hello" end program example_strip fortran-lang-stdlib-0ede301/example/strings/example_join.f900000664000175000017500000000105515135654166024305 0ustar alastairalastairprogram example_join use stdlib_strings, only: join implicit none character(len=:), allocatable :: line character(*), parameter :: words(3) = [character(7) :: "Hello", "World", "Fortran"] ! Default separator (space) line = join(words) print *, "'" // line // "'" !! 'Hello World Fortran' ! Custom separator line = join(words, "_") print *, "'" // line // "'" !! 'Hello_World_Fortran' ! Custom 2-character separator line = join(words, ", ") print *, "'" // line // "'" !! 'Hello, World, Fortran' end program example_join fortran-lang-stdlib-0ede301/example/strings/example_count.f900000664000175000017500000000076115135654166024501 0ustar alastairalastairprogram example_count use stdlib_string_type, only: string_type, assignment(=) use stdlib_strings, only: count implicit none type(string_type) :: string string = "How much wood would a woodchuck chuck if a woodchuck could chuck wood?" print *, count(string, "wood") ! 4 print *, count(string, ["would", "chuck", "could"]) ! [1, 4, 1] print *, count("a long queueueueue", "ueu", [.false., .true.]) ! [2, 4] end program example_count fortran-lang-stdlib-0ede301/example/strings/example_starts_with.f900000664000175000017500000000033015135654166025714 0ustar alastairalastairprogram example_starts_with use stdlib_strings, only: starts_with implicit none print'(l1)', starts_with("pattern", "pat") ! T print'(l1)', starts_with("pattern", "ern") ! F end program example_starts_with fortran-lang-stdlib-0ede301/example/strings/example_slice.f900000664000175000017500000000067515135654166024454 0ustar alastairalastairprogram example_slice use stdlib_string_type use stdlib_strings, only: slice implicit none type(string_type) :: string character(len=10) :: chars string = "abcdefghij" ! string <-- "abcdefghij" chars = "abcdefghij" ! chars <-- "abcdefghij" print'(a)', slice("abcdefghij", 2, 6, 2) ! "bdf" print'(a)', slice(chars, 2, 6, 2) ! "bdf" string = slice(string, 2, 6, 2) ! string <-- "bdf" end program example_slice fortran-lang-stdlib-0ede301/VERSION0000664000175000017500000000000615135654166017232 0ustar alastairalastair0.8.1 fortran-lang-stdlib-0ede301/cmake/0000775000175000017500000000000015135654166017246 5ustar alastairalastairfortran-lang-stdlib-0ede301/cmake/stdlib.cmake0000664000175000017500000001211615135654166021532 0ustar alastairalastair# Preprocesses a list of files with given preprocessor and preprocessor options # # Args: # preproc [in]: Preprocessor program # preprocopts [in]: Preprocessor options # srcext [in]: File extension of the source files # trgext [in]: File extension of the target files # srcfiles [in]: List of the source files # trgfiles [out]: Contains the list of the preprocessed files on exit # function(preprocess preproc preprocopts srcext trgext srcfiles trgfiles) set(_trgfiles) foreach(srcfile IN LISTS srcfiles) get_filename_component(filename ${srcfile} NAME) string(REGEX REPLACE "\\.${srcext}$" ".${trgext}" trgfile ${filename}) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${trgfile} COMMAND ${preproc} ${preprocopts} ${CMAKE_CURRENT_SOURCE_DIR}/${srcfile} ${CMAKE_CURRENT_BINARY_DIR}/${trgfile} MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${srcfile}) list(APPEND _trgfiles ${CMAKE_CURRENT_BINARY_DIR}/${trgfile}) endforeach() set(${trgfiles} ${_trgfiles} PARENT_SCOPE) endfunction() # Preprocesses fortran files with fypp. # # It assumes that source files have the ".fypp" extension. Target files will be # created with the extension ".f90". The FYPP variable must contain the path to # the fypp-preprocessor. # # Args: # fyppopts [in]: Options to pass to fypp. # fyppfiles [in]: Files to be processed by fypp # f90files [out]: List of created f90 files on exit # function (fypp_f90 fyppopts fyppfiles f90files) preprocess("${FYPP}" "${fyppopts}" "fypp" "f90" "${fyppfiles}" _f90files) set(${f90files} ${_f90files} PARENT_SCOPE) endfunction() # For fortran sources that contain C preprocessor flags: create ".F90" files function (fypp_f90pp fyppopts fyppfiles F90files) preprocess("${FYPP}" "${fyppopts}" "fypp" "F90" "${fyppfiles}" _F90files) set(${F90files} ${_F90files} PARENT_SCOPE) endfunction() # Helper function to configure stdlib targets # # It preprocesses the given fypp and fypp+cpp files, combines them with the # regular Fortran files, and creates a library target with the given name. # Args: # target_name [in]: Name of the library target to create # regular_sources_var [in]: Regular Fortran sources # fypp_files_var [in]: Sources to be preprocessed with fypp # cpp_files_var [in]: Sources to be preprocessed with fypp and cpp # function(configure_stdlib_target target_name regular_sources_var fypp_files_var cpp_files_var) #### Pre-process: .fpp -> .f90 via Fypp fypp_f90("${fyppFlags}" "${${fypp_files_var}}" ${target_name}_fypp_outFiles) #### Pre-process: .fypp -> .F90 via Fypp (for C preprocessor directives) fypp_f90pp("${fyppFlags}" "${${cpp_files_var}}" ${target_name}_cpp_outFiles) list(APPEND all_sources ${${target_name}_fypp_outFiles}) list(APPEND all_sources ${${target_name}_cpp_outFiles}) list(APPEND all_sources ${${regular_sources_var}}) add_library(${target_name} ${all_sources}) add_library(${PROJECT_NAME}::${target_name} ALIAS ${target_name}) set_target_properties( ${target_name} PROPERTIES POSITION_INDEPENDENT_CODE ON WINDOWS_EXPORT_ALL_SYMBOLS ON ) if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 10.0) target_compile_options( ${target_name} PRIVATE $<$:-fno-range-check> ) endif() set(LIB_MOD_DIR ${CMAKE_CURRENT_BINARY_DIR}/mod_files/${target_name}/) #set(INSTALL_MOD_DIR "${CMAKE_INSTALL_MODULEDIR}/${target_name}") set(INSTALL_MOD_DIR "${CMAKE_INSTALL_MODULEDIR}") # We need the module directory before we finish the configure stage since the # build interface might resolve before the module directory is generated by CMake if(NOT EXISTS "${LIB_MOD_DIR}") file(MAKE_DIRECTORY "${LIB_MOD_DIR}") endif() set_target_properties(${target_name} PROPERTIES Fortran_MODULE_DIRECTORY ${LIB_MOD_DIR} ) target_include_directories(${target_name} PUBLIC $ $ ) install(TARGETS ${target_name} EXPORT ${PROJECT_NAME}-targets RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) install(DIRECTORY ${LIB_MOD_DIR} DESTINATION "${INSTALL_MOD_DIR}") endfunction() # Determine if a module will be compiled # # Defines a CMake function that creates an ON/OFF option for a given stdlib module, #sets a compile definition accordingly, and prints its enabled/disabled status. # # Args: # module [in]: Name of the module to be compiled # function(check_modular module) string(TOUPPER "${module}" umodule) option(STDLIB_${umodule} "Compile STDLIB ${umodule}" ON) if(STDLIB_${umodule}) message(STATUS "Enable stdlib module ${umodule}") add_compile_definitions(STDLIB_${umodule}=1) else() message(STATUS "Disable stdlib module ${umodule}") add_compile_definitions(STDLIB_${umodule}=0) endif() endfunction() fortran-lang-stdlib-0ede301/LICENSE0000664000175000017500000000207115135654166017173 0ustar alastairalastairMIT License Copyright (c) 2019-2021 stdlib contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. fortran-lang-stdlib-0ede301/config/0000775000175000017500000000000015135654166017433 5ustar alastairalastairfortran-lang-stdlib-0ede301/config/requirements.txt0000664000175000017500000000002415135654166022713 0ustar alastairalastairfypp argparse joblibfortran-lang-stdlib-0ede301/config/export_pc.cmake0000664000175000017500000000352015135654166022440 0ustar alastairalastair# Export a pkg-config file # Inspect linked libraries function(resolve_pc_libs out_var root_target) set(_result "") set(_visited "") function(_resolve target) # Prevent infinite recursion if(target IN_LIST _visited) return() endif() list(APPEND _visited "${target}") set(_visited "${_visited}" PARENT_SCOPE) if(TARGET "${target}") # Recurse into PUBLIC/INTERFACE deps first get_target_property(deps "${target}" INTERFACE_LINK_LIBRARIES) if(deps) foreach(dep IN LISTS deps) _resolve("${dep}") endforeach() endif() # Now append the target itself (if it produces a library) get_target_property(type "${target}" TYPE) if(type MATCHES "STATIC_LIBRARY|SHARED_LIBRARY") get_target_property(name "${target}" OUTPUT_NAME) if(NOT name) set(name "${target}") endif() list(APPEND _result "-l${name}") endif() else() # Plain linker flag or library list(APPEND _result "${target}") endif() set(_result "${_result}" PARENT_SCOPE) endfunction() _resolve("${root_target}") # Remove the duplicates by keeping the first occurrence list(REMOVE_DUPLICATES _result) # Reverse the order list(REVERSE _result) set(${out_var} "${_result}" PARENT_SCOPE) endfunction() resolve_pc_libs(PC_LIBS ${PROJECT_NAME}) string(REPLACE ";" " " PC_CONTENT "${PC_LIBS}") configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/config/template.pc" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" @ONLY ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" ) fortran-lang-stdlib-0ede301/config/template.cmake0000664000175000017500000000047315135654166022254 0ustar alastairalastair@PACKAGE_INIT@ set("@PROJECT_NAME@_WITH_CBOOL" @WITH_CBOOL@) set("@PROJECT_NAME@_WITH_QP" @WITH_QP@) set("@PROJECT_NAME@_WITH_XDP" @WITH_XDP@) set("@PROJECT_NAME@_WITH_ILP64" @WITH_ILP64@) if(NOT TARGET "@PROJECT_NAME@::@PROJECT_NAME@") include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") endif() fortran-lang-stdlib-0ede301/config/CMakeLists.txt0000664000175000017500000000453115135654166022176 0ustar alastairalastair# SPDX-Identifier: MIT if(NOT DEFINED CMAKE_INSTALL_MODULEDIR) set( CMAKE_INSTALL_MODULEDIR "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${CMAKE_Fortran_COMPILER_ID}-${CMAKE_Fortran_COMPILER_VERSION}" CACHE STRING "Directory in prefix to install generated module files" ) endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" PARENT_SCOPE) # Check for available features # Note: users can overwrite the automatic check by setting the value at configure time include(CheckFortranSourceRuns) if (NOT DEFINED WITH_CBOOL) check_fortran_source_runs( "use, intrinsic :: iso_c_binding, only: c_bool; integer, parameter :: lk = kind(.true.) if (c_bool == lk) stop 1 end" WITH_CBOOL ) set(WITH_CBOOL ${WITH_CBOOL} PARENT_SCOPE) endif() if (NOT DEFINED WITH_QP) check_fortran_source_runs( "if (selected_real_kind(33) == -1) stop 1; end" WITH_QP ) set(WITH_QP ${WITH_QP} PARENT_SCOPE) endif() if (NOT DEFINED WITH_XDP) check_fortran_source_runs( "if (any(selected_real_kind(18) == [-1, selected_real_kind(33)])) stop 1; end" WITH_XDP ) set(WITH_XDP ${WITH_XDP} PARENT_SCOPE) endif() # Check if WITH_ILP64 is defined; if not, set it to FALSE if (NOT DEFINED WITH_ILP64) set(WITH_ILP64 FALSE) set(WITH_ILP64 ${WITH_ILP64} PARENT_SCOPE) endif() # Export CMake package file include(CMakePackageConfigHelpers) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/template.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) if(BUILD_SHARED_LIBS OR PROJECT_VERSION_MAJOR EQUAL 0) # Due to the uncertain ABI compatibility of Fortran shared libraries # limit compatibility for dynamic linking to same minor version. set(COMPATIBILITY SameMinorVersion) else() # Require API compatibility via semantic versioning for static linking. set(COMPATIBILITY SameMajorVersion) endif() write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" VERSION "${PROJECT_VERSION}" COMPATIBILITY ${COMPATIBILITY} ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) fortran-lang-stdlib-0ede301/config/DefaultFlags.cmake0000664000175000017500000000217015135654166022776 0ustar alastairalastairif(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") set( CMAKE_Fortran_FLAGS_INIT "-fimplicit-none" "-ffree-line-length-132" ) set( CMAKE_Fortran_FLAGS_RELEASE_INIT ) set( CMAKE_Fortran_FLAGS_DEBUG_INIT "-Wall" "-Wextra" "-Wimplicit-procedure" "-std=f2018" ) elseif(CMAKE_Fortran_COMPILER_ID MATCHES "^Intel") set( CMAKE_Fortran_FLAGS_INIT ) set( CMAKE_Fortran_FLAGS_RELEASE_INIT ) if(WIN32) set( CMAKE_Fortran_FLAGS_DEBUG_INIT "/stand:f18" "/warn:declarations,general,usage,interfaces,unused" ) else() set( CMAKE_Fortran_FLAGS_DEBUG_INIT "-stand f18" "-warn declarations,general,usage,interfaces,unused" ) endif() else() set( CMAKE_Fortran_FLAGS_INIT ) set( CMAKE_Fortran_FLAGS_RELEASE_INIT ) set( CMAKE_Fortran_FLAGS_DEBUG_INIT ) endif() string(REPLACE ";" " " CMAKE_Fortran_FLAGS_INIT "${CMAKE_Fortran_FLAGS_INIT}") string(REPLACE ";" " " CMAKE_Fortran_FLAGS_RELEASE_INIT "${CMAKE_Fortran_FLAGS_RELEASE_INIT}") string(REPLACE ";" " " CMAKE_Fortran_FLAGS_DEBUG_INIT "${CMAKE_Fortran_FLAGS_DEBUG_INIT}") fortran-lang-stdlib-0ede301/config/template.pc0000664000175000017500000000047615135654166021601 0ustar alastairalastairprefix=@CMAKE_INSTALL_PREFIX@ libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ moduledir=${prefix}/@CMAKE_INSTALL_MODULEDIR@ Name: @PROJECT_NAME@ Description: @PROJECT_DESCRIPTION@ Version: @PROJECT_VERSION@ Libs: -L${libdir} @PC_CONTENT@ Cflags: -I${includedir} -I${moduledir} fortran-lang-stdlib-0ede301/config/cmake/0000775000175000017500000000000015135654166020513 5ustar alastairalastairfortran-lang-stdlib-0ede301/config/cmake/Findtest-drive.cmake0000664000175000017500000001125415135654166024407 0ustar alastairalastair# SPDX-Identifier: MIT #[[.rst: Find test-drive --------------- Makes the test-drive project available. Imported Targets ^^^^^^^^^^^^^^^^ This module provides the following imported target, if found: ``test-drive::test-drive`` The test-drive library Result Variables ^^^^^^^^^^^^^^^^ This module will define the following variables: ``TEST_DRIVE_FOUND`` True if the test-drive library is available ``TEST_DRIVE_SOURCE_DIR`` Path to the source directory of the test-drive project, only set if the project is included as source. ``TEST_DRIVE_BINARY_DIR`` Path to the binary directory of the test-drive project, only set if the project is included as source. Cache variables ^^^^^^^^^^^^^^^ The following cache variables may be set to influence the library detection: ``TEST_DRIVE_FIND_METHOD`` Methods to find or make the project available. Available methods are - ``cmake``: Try to find via CMake config file - ``pkgconf``: Try to find via pkg-config file - ``subproject``: Use source in subprojects directory - ``fetch``: Fetch the source from upstream ``TEST_DRIVE_DIR`` Used for searching the CMake config file ``TEST_DRIVE_SUBPROJECT`` Directory to find the test-drive subproject, relative to the project root #]] set(_lib "test-drive") set(_pkg "TEST_DRIVE") set(_url "https://github.com/fortran-lang/test-drive") if(NOT DEFINED "${_pkg}_FIND_METHOD") if(DEFINED "${PROJECT_NAME}-dependency-method") set("${_pkg}_FIND_METHOD" "${${PROJECT_NAME}-dependency-method}") else() set("${_pkg}_FIND_METHOD" "cmake" "pkgconf" "subproject" "fetch") endif() set("_${_pkg}_FIND_METHOD") endif() foreach(method ${${_pkg}_FIND_METHOD}) if(TARGET "${_lib}::${_lib}") break() endif() if("${method}" STREQUAL "cmake") message(STATUS "${_lib}: Find installed package") if(DEFINED "${_pkg}_DIR") set("_${_pkg}_DIR") set("${_lib}_DIR" "${_pkg}_DIR") endif() find_package("${_lib}" CONFIG QUIET) if("${_lib}_FOUND") message(STATUS "${_lib}: Found installed package") break() endif() endif() if("${method}" STREQUAL "pkgconf") find_package(PkgConfig QUIET) pkg_check_modules("${_pkg}" QUIET "${_lib}") if("${_pkg}_FOUND") message(STATUS "Found ${_lib} via pkg-config") add_library("${_lib}::${_lib}" INTERFACE IMPORTED) target_link_libraries( "${_lib}::${_lib}" INTERFACE "${${_pkg}_LINK_LIBRARIES}" ) target_include_directories( "${_lib}::${_lib}" INTERFACE "${${_pkg}_INCLUDE_DIRS}" ) break() endif() endif() if("${method}" STREQUAL "subproject") if(NOT DEFINED "${_pkg}_SUBPROJECT") set("_${_pkg}_SUBPROJECT") set("${_pkg}_SUBPROJECT" "subprojects/${_lib}") endif() set("${_pkg}_SOURCE_DIR" "${PROJECT_SOURCE_DIR}/${${_pkg}_SUBPROJECT}") set("${_pkg}_BINARY_DIR" "${PROJECT_BINARY_DIR}/${${_pkg}_SUBPROJECT}") if(EXISTS "${${_pkg}_SOURCE_DIR}/CMakeLists.txt") message(STATUS "Include ${_lib} from ${${_pkg}_SUBPROJECT}") add_subdirectory( "${${_pkg}_SOURCE_DIR}" "${${_pkg}_BINARY_DIR}" ) add_library("${_lib}::${_lib}" INTERFACE IMPORTED) target_link_libraries("${_lib}::${_lib}" INTERFACE "${_lib}") # We need the module directory in the subproject before we finish the configure stage if(NOT EXISTS "${${_pkg}_BINARY_DIR}/include") file(MAKE_DIRECTORY "${${_pkg}_BINARY_DIR}/include") endif() break() endif() endif() if("${method}" STREQUAL "fetch") message(STATUS "Retrieving ${_lib} from ${_url}") include(FetchContent) FetchContent_Declare( "${_lib}" GIT_REPOSITORY "${_url}" GIT_TAG "v0.4.0" ) FetchContent_MakeAvailable("${_lib}") add_library("${_lib}::${_lib}" INTERFACE IMPORTED) target_link_libraries("${_lib}::${_lib}" INTERFACE "${_lib}") # We need the module directory in the subproject before we finish the configure stage FetchContent_GetProperties("${_lib}" SOURCE_DIR "${_pkg}_SOURCE_DIR") FetchContent_GetProperties("${_lib}" BINARY_DIR "${_pkg}_BINARY_DIR") if(NOT EXISTS "${${_pkg}_BINARY_DIR}/include") file(MAKE_DIRECTORY "${${_pkg}_BINARY_DIR}/include") endif() break() endif() endforeach() if(TARGET "${_lib}::${_lib}") set("${_pkg}_FOUND" TRUE) else() set("${_pkg}_FOUND" FALSE) endif() if(DEFINED "_${_pkg}_SUBPROJECT") unset("${_pkg}_SUBPROJECT") unset("_${_pkg}_SUBPROJECT") endif() if(DEFINED "_${_pkg}_DIR") unset("${_lib}_DIR") unset("_${_pkg}_DIR") endif() if(DEFINED "_${_pkg}_FIND_METHOD") unset("${_pkg}_FIND_METHOD") unset("_${_pkg}_FIND_METHOD") endif() unset(_lib) unset(_pkg) unset(_url) fortran-lang-stdlib-0ede301/config/fypp_deployment.py0000664000175000017500000001433015135654166023224 0ustar alastairalastairimport os import fypp import argparse from joblib import Parallel, delayed C_PREPROCESSED = ( "example_math_swap", "stdlib_linalg_constants" , "stdlib_linalg_blas" , "stdlib_linalg_lapack", "stdlib_math", "stdlib_sorting", "stdlib_sorting_ord_sort", "stdlib_sorting_sort", "stdlib_sorting_sort_adjoint", "test_blas_lapack", "test_stdlib_math", "test_sorting" ) def pre_process_fypp(args): """use fypp to preprocess all source files. Processed files will be dumped at /temp/ or Parameters ---------- args : CLI arguments. """ kwd = [] kwd.append("-DMAXRANK="+str(args.maxrank)) kwd.append("-DPROJECT_VERSION_MAJOR="+str(args.vmajor)) kwd.append("-DPROJECT_VERSION_MINOR="+str(args.vminor)) kwd.append("-DPROJECT_VERSION_PATCH="+str(args.vpatch)) if args.with_qp: kwd.append("-DWITH_QP=True") if args.with_xdp: kwd.append("-DWITH_XDP=True") if args.with_ilp64: kwd.append("-DWITH_ILP64=True") optparser = fypp.get_option_parser() options, leftover = optparser.parse_args(args=kwd) options.includes = ['include'] if args.lnumbering: options.line_numbering = True tool = fypp.Fypp(options) # Create destination folders for preprocessing os.makedirs('src'+os.sep+'temp', exist_ok=True) os.makedirs('test'+os.sep+'temp', exist_ok=True) # Define the folders to search for *.fypp files folders = ['src','test'] # Process all folders fypp_files = [os.path.join(root, file) for folder in folders for root, _, files in os.walk(folder) for file in files if file.endswith(".fypp")] def process_f(file): source_file = file root = os.path.dirname(file) os.makedirs(root+os.sep+'temp', exist_ok=True) basename = os.path.splitext(os.path.basename(source_file))[0] sfx = 'f90' if basename not in C_PREPROCESSED else 'F90' target_file = root+os.sep+'temp' + os.sep + basename + '.' + sfx tool.process_file(source_file, target_file) Parallel(n_jobs=args.njob)(delayed(process_f)(f) for f in fypp_files) return def deploy_stdlib_fpm(with_ilp64): """create the stdlib-fpm folder for backwards compatibility (to be deprecated) """ import shutil prune=( "test_hash_functions.f90", "f18estop.f90", ) if with_ilp64: base_folder = 'stdlib-fpm-ilp64' else: base_folder = 'stdlib-fpm' os.makedirs(base_folder+os.sep+'include', exist_ok=True) os.makedirs(base_folder+os.sep+'src', exist_ok=True) os.makedirs(base_folder+os.sep+'test', exist_ok=True) os.makedirs(base_folder+os.sep+'example', exist_ok=True) def recursive_copy(folder): for root, _, files in os.walk(folder): for file in files: if file not in prune: if file.endswith((".f90", ".F90", ".dat", ".npy", ".c", ".h", ".inc")): shutil.copy2(os.path.join(root, file), base_folder+os.sep+folder+os.sep+file) recursive_copy('include') recursive_copy('src') recursive_copy('test') recursive_copy('example') for file in ['.gitignore','fpm.toml','LICENSE','VERSION']: shutil.copy2(file, base_folder+os.sep+file) return def fpm_build(args,unknown): import subprocess #========================================== # check compilers FPM_FC = os.environ['FPM_FC'] if "FPM_FC" in os.environ else "gfortran" FPM_CC = os.environ['FPM_CC'] if "FPM_CC" in os.environ else "gcc" FPM_CXX = os.environ['FPM_CXX'] if "FPM_CXX" in os.environ else "gcc" #========================================== # Filter out flags preprocessor = { 'gfortran':'-cpp ' , 'ifort':'-fpp ' , 'ifx':'-fpp ' } flags = preprocessor[FPM_FC] for idx, arg in enumerate(unknown): if arg.startswith("--flag"): flags= flags + unknown[idx+1] #========================================== # build with fpm subprocess.run("fpm build"+ " --compiler "+FPM_FC+ " --c-compiler "+FPM_CC+ " --cxx-compiler "+FPM_CXX+ " --flag \"{}\"".format(flags), shell=True, check=True) return if __name__ == "__main__": parser = argparse.ArgumentParser(description='Preprocess stdlib source files.') # fypp arguments parser.add_argument("--vmajor", type=int, default=0, help="Project Version Major") parser.add_argument("--vminor", type=int, default=8, help="Project Version Minor") parser.add_argument("--vpatch", type=int, default=1, help="Project Version Patch") parser.add_argument("--njob", type=int, default=4, help="Number of parallel jobs for preprocessing") parser.add_argument("--maxrank",type=int, default=4, help="Set the maximum allowed rank for arrays") parser.add_argument("--with_qp",action='store_true', help="Include WITH_QP in the command") parser.add_argument("--with_xdp",action='store_true', help="Include WITH_XDP in the command") parser.add_argument("--with_ilp64",action='store_true', help="Include WITH_ILP64 to build 64-bit integer BLAS/LAPACK") parser.add_argument("--lnumbering",action='store_true', help="Add line numbering in preprocessed files") parser.add_argument("--deploy_stdlib_fpm",action='store_true', help="create the stdlib-fpm folder") # external libraries arguments parser.add_argument("--build", action='store_true', help="Build the project") args, unknown = parser.parse_known_args() #========================================== # read current manifest with open('VERSION', 'r') as file: version = file.read().split(".") vmajor, vminor, vpatch = [int(value) for value in version] args.vmajor = max(vmajor,args.vmajor) args.vminor = max(vminor,args.vminor) args.vpatch = max(vpatch,args.vpatch) #========================================== # pre process the meta programming fypp files pre_process_fypp(args) if args.deploy_stdlib_fpm: deploy_stdlib_fpm(args.with_ilp64) #========================================== # build using fpm if args.build: fpm_build(args,unknown)